定时任务增加系统定时任务

This commit is contained in:
2025-11-25 14:45:11 +08:00
parent 5d14957eba
commit 24c5188eb0
14 changed files with 988 additions and 30 deletions

View File

@@ -275,3 +275,56 @@ INSERT INTO `tb_crontab_task_meta` (
NOW()
);
-- 9. 热门资源推荐任务
INSERT INTO `tb_crontab_task_meta` (
`id`, `meta_id`, `name`, `description`, `category`,
`bean_name`, `method_name`, `script_path`, `param_schema`, `auto_publish`,
`sort_order`, `creator`, `create_time`
) VALUES (
'9',
'top_recommend_task',
'热门资源推荐',
'每天凌晨1点自动更新热门推荐资源浏览量TOP10+最新发布TOP10',
'系统内部任务',
'topRecommendTask',
'execute',
'',
'[]',
0,
9,
'system',
NOW()
);
-- 创建热门资源推荐任务实例
INSERT INTO `tb_crontab_task` (
`id`, `task_id`, `meta_id`, `task_name`,`task_group`, `description`,`bean_name`,
`cron_expression`, `method_name`, `method_params`, `status`, `creator`, `create_time`
) VALUES (
'9',
'task_top_recommend_daily',
'top_recommend_task',
'每日热门资源推荐更新',
'系统内部任务',
'每天凌晨1点自动更新热门推荐资源列表',
'topRecommendTask',
'0 0 1 * * ?',
'execute',
'{}',
1,
'system',
NOW()
);
-- 赋予root用户和superadmin角色对热门资源推荐任务的读写执行权限
INSERT INTO `tb_resource_permission` (`id`, `resource_type`, `resource_id`, `dept_id`,
`role_id`, `can_read`, `can_write`, `can_execute`, `creator`, `updater`,
`create_time`, `update_time`, `delete_time`, `deleted`)
VALUES ('671f0c40642e6a69c2be9b6d7a4e986e', 7, 'task_top_recommend_daily', 'root_department',
'superadmin', 1, 1, 1, '1', NULL,
'2025-11-25 13:57:16', '2025-11-25 13:57:16', NULL, 0);
INSERT INTO `tb_resource_permission` (`id`, `resource_type`, `resource_id`, `dept_id`,
`role_id`, `can_read`, `can_write`, `can_execute`, `creator`, `updater`,
`create_time`, `update_time`, `delete_time`, `deleted`)
VALUES ('c365853b6a0e38a9c504962de4403e57', 7, 'task_top_recommend_daily', NULL, NULL,
1, 0, 0, '1', NULL,
'2025-11-25 13:57:16', '2025-11-25 13:57:16', NULL, 0);

View File

@@ -170,6 +170,7 @@ INSERT INTO `tb_sys_menu` VALUES
('8001', 'menu_admin_meta_email_default', '默认接收人配置', 'menu_admin_crontab_manage', '/admin/manage/crontab/meta-email-default', 'admin/manage/crontab/MetaEmailDefaultView', NULL, 1, 0, 'SidebarLayout', '1', NULL, '2025-11-18 18:00:00', '2025-11-18 18:00:00', NULL, 0),
('8002', 'menu_admin_crontab_log', '执行日志', 'menu_admin_crontab_manage', '/admin/manage/crontab/log', 'admin/manage/crontab/LogManagementView', NULL, 2, 0, 'SidebarLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:48:39', NULL, 0),
('8003', 'menu_admin_news_crawler', '新闻爬虫配置', 'menu_admin_crontab_manage', '/admin/manage/crontab/news-crawler', 'admin/manage/crontab/NewsCrawlerView', NULL, 3, 0, 'SidebarLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:48:39', NULL, 0),
('8004', 'menu_admin_system_task', '系统定时任务配置', 'menu_admin_crontab_manage', '/admin/manage/crontab/system-task', 'admin/manage/crontab/SystemTaskView', NULL, 4, 0, 'SidebarLayout', '1', NULL, '2025-11-25 13:45:00', '2025-11-25 13:45:00', NULL, 0),
-- 消息通知模块菜单 (9000-9999)
('9001', 'menu_admin_message_manage', '消息管理', NULL, '/admin/manage/message', 'admin/manage/message/MessageManageView', 'admin/notice.svg', 9, 0, 'SidebarLayout', '1', NULL, '2025-11-13 10:00:00', '2025-11-13 10:00:00', NULL, 0),
-- 用户端消息中心菜单 (650-699)
@@ -238,6 +239,7 @@ INSERT INTO `tb_sys_menu_permission` (id, permission_id, menu_id, creator, creat
('233', 'perm_crontab_manage', 'menu_admin_crontab_task', '1', now()),
('234', 'perm_crontab_manage', 'menu_admin_crontab_log', '1', now()),
('235', 'perm_crontab_manage', 'menu_admin_news_crawler', '1', now()),
('252', 'perm_crontab_manage', 'menu_admin_system_task', '1', now()),
-- 消息通知管理菜单权限关联
('240', 'perm_message_manage', 'menu_admin_message_manage', '1', now()),

View File

@@ -46,7 +46,8 @@ public interface ResourceService {
* @author yslg
* @since 2025-10-15
*/
ResultDomain<ResourceVO> getResourcePageOrderByViewCount(TbResource filter, PageParam pageParam);
ResultDomain<ResourceVO> getResourcePageOrder(TbResource filter, PageParam pageParam);
/**
* @description 根据ID获取资源详情
* @param resourceID 资源ID

View File

@@ -42,7 +42,7 @@ public class CrontabController {
public ResultDomain<TbCrontabTaskMeta> getEnabledCrontabList(@RequestParam(required = false) String param) {
try {
// 从数据库查询所有任务元数据
ResultDomain<TbCrontabTaskMeta> result = taskMetaService.getAllTaskMeta();
ResultDomain<TbCrontabTaskMeta> result = taskMetaService.getTaskMetaByCategory(param);
result.getDataList().forEach(item->{
item.setBeanName("");
item.setMethodName("");

View File

@@ -0,0 +1,168 @@
package org.xyzh.crontab.task.recommendTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.xyzh.api.news.recommend.ResourceRecommendService;
import org.xyzh.api.news.resource.ResourceService;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageParam;
import org.xyzh.common.dto.BaseDTO;
import org.xyzh.common.dto.resource.TbResource;
import org.xyzh.common.dto.resource.TbResourceRecommend;
import org.xyzh.common.utils.IDUtils;
import org.xyzh.common.vo.ResourceVO;
import org.xyzh.crontab.pojo.TaskParams;
import org.xyzh.crontab.task.BaseTask;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @description 热门资源推荐定时任务 - 每天凌晨1点自动更新热门推荐
* @filename TopRecommendTask.java
* @author yslg
* @copyright xyzh
* @since 2025-11-25
*/
@Component("topRecommendTask")
public class TopRecommendTask extends BaseTask {
@Autowired
private ResourceService resourceService;
@Autowired
private ResourceRecommendService resourceRecommendService;
@Override
@Transactional(rollbackFor = Exception.class)
protected void doExecute(TaskParams taskParams) throws Exception {
logger.info("开始执行热门资源推荐任务");
try {
// 1. 清除旧的热门推荐recommend_type = 1
// clearOldRecommends();
// 2. 获取浏览量前10的资源
List<ResourceVO> topViewCountResources = getTopResourcesByViewCount(10);
logger.info("获取到浏览量前10的资源数量: {}", topViewCountResources.size());
// 3. 获取发布时间前10的资源
List<ResourceVO> topPublishTimeResources = getTopResourcesByPublishTime(10);
logger.info("获取到发布时间前10的资源数量: {}", topPublishTimeResources.size());
// 4. 合并并去重(使用 Set 确保资源ID唯一
Set<String> resourceIds = new HashSet<>();
List<TbResourceRecommend> recommendList = new ArrayList<>();
int orderNum = 1;
// 添加浏览量前10
for (ResourceVO vo : topViewCountResources) {
if (vo.getResource() != null && resourceIds.add(vo.getResource().getResourceID())) {
recommendList.add(createRecommend(vo.getResource().getResourceID(), orderNum++));
}
}
// 添加发布时间前10
for (ResourceVO vo : topPublishTimeResources) {
if (vo.getResource() != null && resourceIds.add(vo.getResource().getResourceID())) {
recommendList.add(createRecommend(vo.getResource().getResourceID(), orderNum++));
}
}
// 5. 批量插入新推荐
if (!recommendList.isEmpty()) {
for (TbResourceRecommend recommend : recommendList) {
ResultDomain<TbResourceRecommend> addResult = resourceRecommendService.addRecommend(recommend);
if (!addResult.isSuccess()) {
logger.warn("插入推荐失败: 资源ID={}, 原因={}", recommend.getResourceID(), addResult.getMessage());
}
}
logger.info("成功插入{}条热门推荐记录", recommendList.size());
} else {
logger.warn("没有找到符合条件的资源,未插入推荐记录");
}
logger.info("热门资源推荐任务执行成功,共推荐{}个资源", resourceIds.size());
} catch (Exception e) {
logger.error("热门资源推荐任务执行失败: {}", e.getMessage(), e);
throw e;
}
}
/**
* 清除旧的热门推荐记录
*/
private void clearOldRecommends() {
logger.info("清除旧的热门推荐记录recommend_type = 1");
// 暂时跳过清除逻辑Service层方法待添加
// TODO: 实现 deleteRecommendsByType 方法后启用
}
/**
* 获取浏览量前N的资源
*/
private List<ResourceVO> getTopResourcesByViewCount(int limit) {
TbResource filter = new TbResource();
filter.setStatus(1); // 只查询已发布的资源
// 设置排序:按浏览量降序
List<BaseDTO.OrderType> orderTypes = new ArrayList<>();
orderTypes.add(new BaseDTO.OrderType("view_count", "DESC"));
orderTypes.add(new BaseDTO.OrderType("publish_time", "DESC"));
filter.setOrderTypes(orderTypes);
PageParam pageParam = new PageParam();
pageParam.setPageSize(limit);
pageParam.setOffset(0L);
ResultDomain<ResourceVO> result = resourceService.getResourcePageOrder(filter, pageParam);
if (result.isSuccess() && result.getDataList() != null) {
return result.getDataList();
}
return new ArrayList<>();
}
/**
* 获取发布时间前N的资源最新发布
*/
private List<ResourceVO> getTopResourcesByPublishTime(int limit) {
TbResource filter = new TbResource();
filter.setStatus(1); // 只查询已发布的资源
// 设置排序:按发布时间降序
List<BaseDTO.OrderType> orderTypes = new ArrayList<>();
orderTypes.add(new BaseDTO.OrderType("publish_time", "DESC"));
orderTypes.add(new BaseDTO.OrderType("create_time", "DESC"));
filter.setOrderTypes(orderTypes);
PageParam pageParam = new PageParam();
pageParam.setPageSize(limit);
pageParam.setOffset(0L);
ResultDomain<ResourceVO> result = resourceService.getResourcePageOrder(filter, pageParam);
if (result.isSuccess() && result.getDataList() != null) {
return result.getDataList();
}
return new ArrayList<>();
}
/**
* 创建推荐记录
*/
private TbResourceRecommend createRecommend(String resourceId, int orderNum) {
TbResourceRecommend recommend = new TbResourceRecommend();
recommend.setID(IDUtils.generateID());
recommend.setResourceID(resourceId);
recommend.setRecommendType(1); // 1-热门资源推荐
recommend.setOrderNum(orderNum);
recommend.setCreateTime(new Date());
recommend.setUpdateTime(new Date());
recommend.setDeleted(false);
return recommend;
}
}

View File

@@ -274,7 +274,7 @@
AND ct.task_name LIKE CONCAT('%', #{filter.taskName}, '%')
</if>
<if test="filter.taskGroup != null and filter.taskGroup != ''">
AND ct.task_group = #{filter.taskGroup}
AND ct.task_group LIKE CONCAT('%', #{filter.taskGroup}, '%')
</if>
<if test="filter.status != null">
AND ct.status = #{filter.status}
@@ -337,7 +337,7 @@
AND ct.task_name LIKE CONCAT('%', #{filter.taskName}, '%')
</if>
<if test="filter.taskGroup != null and filter.taskGroup != ''">
AND ct.task_group = #{filter.taskGroup}
AND ct.task_group LIKE CONCAT('%', #{filter.taskGroup}, '%')
</if>
<if test="filter.status != null">
AND ct.status = #{filter.status}

View File

@@ -115,7 +115,7 @@
<select id="selectTaskMetaByCategory" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List" />
FROM tb_crontab_task_meta
WHERE category = #{category}
WHERE category LIKE CONCAT('%', #{category}, '%')
AND deleted = 0
ORDER BY sort_order ASC
</select>

View File

@@ -59,7 +59,7 @@ public class ResourceController {
public ResultDomain<ResourceVO> getResourcePageOrderByViewCount(@RequestBody PageRequest<TbResource> request) {
TbResource filter = request.getFilter();
PageParam pageParam = request.getPageParam();
return resourceService.getResourcePageOrderByViewCount(filter, pageParam);
return resourceService.getResourcePageOrder(filter, pageParam);
}
/**

View File

@@ -176,7 +176,7 @@ public interface ResourceMapper extends BaseMapper<TbResource> {
* @author yslg
* @since 2025-10-15
*/
List<ResourceVO> selectResourcesPageOrderByViewCount(@Param("filter") TbResource filter, @Param("pageParam") PageParam pageParam, @Param("userDeptRoles") List<UserDeptRoleVO> userDeptRoles);
List<ResourceVO> selectResourcesPageOrder(@Param("filter") TbResource filter, @Param("pageParam") PageParam pageParam, @Param("userDeptRoles") List<UserDeptRoleVO> userDeptRoles);
/**
* @description 统计资源总数

View File

@@ -161,7 +161,7 @@ public class NCResourceServiceImpl implements ResourceService {
}
@Override
public ResultDomain<ResourceVO> getResourcePageOrderByViewCount(TbResource filter, PageParam pageParam) {
public ResultDomain<ResourceVO> getResourcePageOrder(TbResource filter, PageParam pageParam) {
ResultDomain<ResourceVO> resultDomain = new ResultDomain<>();
try {
if (filter == null) {
@@ -170,7 +170,7 @@ public class NCResourceServiceImpl implements ResourceService {
// 获取当前用户的部门角色
List<UserDeptRoleVO> userDeptRoles = LoginUtil.getCurrentDeptRole();
// 直接查询ResourceVO列表
List<ResourceVO> resourceVOList = resourceMapper.selectResourcesPageOrderByViewCount(filter, pageParam, userDeptRoles);
List<ResourceVO> resourceVOList = resourceMapper.selectResourcesPageOrder(filter, pageParam, userDeptRoles);
logger.info("资源数量{}",resourceVOList.size());
long total = resourceMapper.countResources(filter, userDeptRoles);
pageParam.setTotalElements(total);
@@ -284,6 +284,7 @@ public class NCResourceServiceImpl implements ResourceService {
// 进行审核
ResultDomain<String> pass =auditService.auditText(resource.getTitle() + " "+resource.getContent());
if(pass.isSuccess()){
resource.setPublishTime(new Date());
resource.setIsAudited(true);
}else {
auditService.sendAuditResultMessage(resource.getCreator(), "文章"+resource.getTitle(), pass.getDataList());
@@ -509,6 +510,7 @@ public class NCResourceServiceImpl implements ResourceService {
ResultDomain<String> pass = auditService.auditText(resource.getTitle()+" "+resource.getContent());
if (pass.isSuccess()) {
resource.setIsAudited(true);
resource.setPublishTime(new Date());
} else {
// 审核失败标记状态为4审核失败
resource.setStatus(4);
@@ -562,6 +564,7 @@ public class NCResourceServiceImpl implements ResourceService {
ResultDomain<String> pass = auditService.auditText(resource.getTitle()+" "+resource.getContent());
if (pass.isSuccess()) {
resource.setIsAudited(true);
resource.setPublishTime(new Date());
} else {
// 审核失败标记状态为3审核失败
resource.setStatus(3);

View File

@@ -378,7 +378,7 @@
</association>
</resultMap>
<select id="selectResourcesPageOrderByViewCount" resultMap="ResourceVOResultMap">
<select id="selectResourcesPageOrder" resultMap="ResourceVOResultMap">
SELECT
r.*,
MAX(CASE WHEN rec.recommend_type = 1 THEN 1 ELSE 0 END) AS is_top_recommend,