diff --git a/schoolNewsCrawler/crawler/xxqg/XxqgCrawler.py b/schoolNewsCrawler/crawler/xxqg/XxqgCrawler.py index 70fe8dd..e64c848 100644 --- a/schoolNewsCrawler/crawler/xxqg/XxqgCrawler.py +++ b/schoolNewsCrawler/crawler/xxqg/XxqgCrawler.py @@ -430,6 +430,8 @@ class XxqgCrawler(BaseCrawler): if is_page(): pass logger.info(f"解析文章详情完成: {news_item.url}") + if news_item.contentRows: + news_item.executeStatus = 1 return news_item @@ -586,7 +588,7 @@ class XxqgCrawler(BaseCrawler): # json.dump([item.model_dump() for item in resultDomain.dataList] if resultDomain.dataList else [], f, ensure_ascii=False, indent=4) return resultDomain - def crawl_base(self, config: CrawlerConfig, yesterday=True, start:Optional[str]=None, end:Optional[str]=None) -> ResultDomain: + def crawl_base(self, config: UrlConfig, yesterday=True, start:Optional[str]=None, end:Optional[str]=None) -> ResultDomain: news_list = [] resultDomain = ResultDomain(code=0, message="", success=True, dataList=news_list) @@ -616,7 +618,7 @@ class XxqgCrawler(BaseCrawler): time.sleep(3) # 等待所有请求完成 request_list = self.driver.requests json_request = [] - target_path = config.params.get("path") + target_path = config.params.get("path", "") target_request = None logger.info(f"开始查找目标JSON请求,共有 {len(request_list)} 个请求") diff --git a/schoolNewsServ/admin/src/main/resources/log4j2-spring.xml b/schoolNewsServ/admin/src/main/resources/log4j2-spring.xml index 7a3e9b2..bd4b3a6 100644 --- a/schoolNewsServ/admin/src/main/resources/log4j2-spring.xml +++ b/schoolNewsServ/admin/src/main/resources/log4j2-spring.xml @@ -101,24 +101,31 @@ + + + + + + + diff --git a/schoolNewsServ/common/common-dto/src/main/java/org/xyzh/common/dto/BaseDTO.java b/schoolNewsServ/common/common-dto/src/main/java/org/xyzh/common/dto/BaseDTO.java index 96940e2..15adbe6 100644 --- a/schoolNewsServ/common/common-dto/src/main/java/org/xyzh/common/dto/BaseDTO.java +++ b/schoolNewsServ/common/common-dto/src/main/java/org/xyzh/common/dto/BaseDTO.java @@ -2,6 +2,7 @@ package org.xyzh.common.dto; import java.io.Serializable; import java.util.Date; +import java.util.List; /** @@ -53,6 +54,41 @@ public class BaseDTO implements Serializable{ */ private boolean deleted; + private List orderTypes; + + public static class OrderType { + private String field; + private String order; + + // 无参构造函数(Jackson反序列化需要) + public OrderType() { + } + + public OrderType(String field, String order) { + this.field = field; + this.order = order; + } + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + + public String getOrder() { + return order; + } + + public void setOrder(String order) { + if("ASC".equals(order.toUpperCase()) || "DESC".equals(order.toUpperCase())) { + this.order = order.toUpperCase(); + }else{ + throw new IllegalArgumentException("order must be ASC or DESC"); + } + } + } public BaseDTO() { @@ -174,6 +210,14 @@ public class BaseDTO implements Serializable{ this.deleted = deleted; } + public List getOrderTypes() { + return orderTypes; + } + + public void setOrderTypes(List orderTypes) { + this.orderTypes = orderTypes; + } + @Override public String toString(){ return "BaseDTO { id=" + id + ", createTime=" + createTime + ", updateTime=" + updateTime + ", deleteTime=" + deleteTime + ", deleted=" + deleted + " }"; diff --git a/schoolNewsServ/crontab/src/main/java/org/xyzh/crontab/task/newsTask/NewsCrawlerTask.java b/schoolNewsServ/crontab/src/main/java/org/xyzh/crontab/task/newsTask/NewsCrawlerTask.java index 3b0a63a..5522805 100644 --- a/schoolNewsServ/crontab/src/main/java/org/xyzh/crontab/task/newsTask/NewsCrawlerTask.java +++ b/schoolNewsServ/crontab/src/main/java/org/xyzh/crontab/task/newsTask/NewsCrawlerTask.java @@ -323,7 +323,16 @@ public class NewsCrawlerTask extends PythonCommandTask { // 自动发布并记录成功发布的 URL 集合 Set publishedUrls = new HashSet<>(); if (taskMeta.getAutoPublish().booleanValue()){ - publishedUrls = publishNewsToArticle(passDataResult.getDataList(), task, logId); + // 合并通过审核和未通过审核的采集项,都进行自动发布 + // 通过审核的会发布为status=1,未通过审核的会发布为status=4 + List allItems = new ArrayList<>(); + if (passDataResult.getDataList() != null) { + allItems.addAll(passDataResult.getDataList()); + } + if (notPassDataResult.getDataList() != null) { + allItems.addAll(notPassDataResult.getDataList()); + } + publishedUrls = publishNewsToArticle(allItems, task, logId); } Set notPathUrls = new HashSet<>(notPassList.stream().map(TbDataCollectionItem::getSourceUrl).toList()); diff --git a/schoolNewsServ/news/src/main/java/org/xyzh/news/service/impl/NCResourceServiceImpl.java b/schoolNewsServ/news/src/main/java/org/xyzh/news/service/impl/NCResourceServiceImpl.java index 7e18d43..4f79152 100644 --- a/schoolNewsServ/news/src/main/java/org/xyzh/news/service/impl/NCResourceServiceImpl.java +++ b/schoolNewsServ/news/src/main/java/org/xyzh/news/service/impl/NCResourceServiceImpl.java @@ -169,8 +169,9 @@ public class NCResourceServiceImpl implements ResourceService { } // 获取当前用户的部门角色 List userDeptRoles = LoginUtil.getCurrentDeptRole(); - // 直接查询ResourceVO列表,SQL已经LEFT JOIN了recommend表 + // 直接查询ResourceVO列表 List resourceVOList = resourceMapper.selectResourcesPageOrderByViewCount(filter, pageParam, userDeptRoles); + logger.info("资源数量{}",resourceVOList.size()); long total = resourceMapper.countResources(filter, userDeptRoles); pageParam.setTotalElements(total); pageParam.setTotalPages((int) Math.ceil((double) total / pageParam.getPageSize())); diff --git a/schoolNewsServ/news/src/main/resources/mapper/ResourceMapper.xml b/schoolNewsServ/news/src/main/resources/mapper/ResourceMapper.xml index 698066d..8e14912 100644 --- a/schoolNewsServ/news/src/main/resources/mapper/ResourceMapper.xml +++ b/schoolNewsServ/news/src/main/resources/mapper/ResourceMapper.xml @@ -347,11 +347,12 @@ + - - + + @@ -408,13 +409,21 @@ r.author, r.source, r.source_url, r.view_count, r.like_count, r.collect_count, r.status, r.is_recommend, r.is_banner, r.publish_time, r.creator, r.updater, r.create_time, r.update_time, r.delete_time, r.deleted - ORDER BY r.view_count DESC, r.publish_time DESC, r.create_time DESC + + ORDER BY + + r.${orderType.field} ${orderType.order} + + + + ORDER BY r.view_count DESC, r.publish_time DESC, r.create_time DESC + LIMIT #{pageParam.pageSize} OFFSET #{pageParam.offset} - SELECT COUNT(DISTINCT r.id) + SELECT COUNT(DISTINCT r.resource_id) FROM tb_resource r WHERE r.deleted = 0 diff --git a/schoolNewsWeb/src/types/base/index.ts b/schoolNewsWeb/src/types/base/index.ts index 943af25..b5ecfa3 100644 --- a/schoolNewsWeb/src/types/base/index.ts +++ b/schoolNewsWeb/src/types/base/index.ts @@ -18,6 +18,13 @@ export interface BaseDTO { deleteTime?: string; /** 是否删除 */ deleted?: boolean; + + orderTypes?: OrderType[]; +} + +export interface OrderType { + field: string; + order: 'ASC' | 'DESC'; } /** diff --git a/schoolNewsWeb/src/views/admin/manage/content/ColumnManagementView.vue b/schoolNewsWeb/src/views/admin/manage/content/ColumnManagementView.vue index 80300a1..9594762 100644 --- a/schoolNewsWeb/src/views/admin/manage/content/ColumnManagementView.vue +++ b/schoolNewsWeb/src/views/admin/manage/content/ColumnManagementView.vue @@ -40,6 +40,11 @@ 查看和分析热门文章的访问统计数据 + + + + + @@ -381,6 +386,7 @@ const ideologicalRecommends = ref([]); // 热门文章列表 const hotArticles = ref([]); const hotArticleLimit = ref(20); +const sortOrder = ref('default'); // 排序规则:default-默认, viewCount-浏览量, publishTime-发布时间 // 添加至TOP的加载状态 const addingToTop = ref>(new Set()); @@ -473,21 +479,31 @@ async function loadTabData(tab: string) { async function loadHotArticles() { loading.value = true; try { - // 获取已发布的文章,按浏览量排序 + // 构建过滤条件 + const filter: any = { + status: 1 // 只显示已发布的 + }; + + // 根据排序规则设置orderTypes + if (sortOrder.value === 'viewCount') { + filter.orderTypes = [{ field: 'view_count', order: 'DESC' }]; + } else if (sortOrder.value === 'publishTime') { + filter.orderTypes = [{ field: 'publish_time', order: 'DESC' }]; + } + // default情况下orderTypes为空,使用SQL中的默认排序 + + // 获取已发布的文章 const result = await resourceApi.getResourcePageOrderByViewCount( { pageNumber: 1, pageSize: hotArticleLimit.value }, - { - status: 1 // 只显示已发布的 - } + filter ); if (result.success && result.pageDomain?.dataList) { - // 按浏览量降序排序 - hotArticles.value = result.pageDomain.dataList - .sort((a, b) => (b.resource?.viewCount || 0) - (a.resource?.viewCount || 0)); + // 直接使用后端返回的排序结果 + hotArticles.value = result.pageDomain.dataList; } } catch (error) { console.error('加载热门文章失败:', error); @@ -542,7 +558,7 @@ async function searchResources() { const result = await resourceApi.getResourcePageOrderByViewCount( { pageNumber: 1, pageSize: 50 }, { - keyword: searchKeyword.value, + title: searchKeyword.value, status: 1 // 只显示已发布的 } ); @@ -1055,6 +1071,11 @@ async function addToIdeologicalRecommends(resourceID?: string) { align-items: center; } + .stat-title { + min-width: 0; /* 允许flex子元素缩小到内容以下 */ + overflow: hidden; /* 隐藏溢出内容 */ + } + .stat-actions { display: flex; align-items: center;
查看和分析热门文章的访问统计数据