新闻采集修改,完成发送邮件
This commit is contained in:
@@ -7,6 +7,8 @@ CREATE TABLE `tb_crontab_task` (
|
|||||||
`task_id` VARCHAR(64) NOT NULL COMMENT '任务ID',
|
`task_id` VARCHAR(64) NOT NULL COMMENT '任务ID',
|
||||||
`task_name` VARCHAR(100) NOT NULL COMMENT '任务名称',
|
`task_name` VARCHAR(100) NOT NULL COMMENT '任务名称',
|
||||||
`task_group` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT' COMMENT '任务分组',
|
`task_group` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT' COMMENT '任务分组',
|
||||||
|
`meta_id` VARCHAR(64) NOT NULL COMMENT '任务元数据ID',
|
||||||
|
`default_recipient` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否使用默认接收人(0:否 1:是)',
|
||||||
`bean_name` VARCHAR(100) NOT NULL COMMENT 'Bean名称',
|
`bean_name` VARCHAR(100) NOT NULL COMMENT 'Bean名称',
|
||||||
`method_name` VARCHAR(100) NOT NULL COMMENT '方法名称',
|
`method_name` VARCHAR(100) NOT NULL COMMENT '方法名称',
|
||||||
`method_params` VARCHAR(500) DEFAULT NULL COMMENT '方法参数',
|
`method_params` VARCHAR(500) DEFAULT NULL COMMENT '方法参数',
|
||||||
@@ -95,3 +97,77 @@ CREATE TABLE `tb_data_collection_item` (
|
|||||||
KEY `idx_publish_time` (`publish_time`),
|
KEY `idx_publish_time` (`publish_time`),
|
||||||
KEY `idx_source_url` (`source_url`)
|
KEY `idx_source_url` (`source_url`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='数据采集项表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='数据采集项表';
|
||||||
|
|
||||||
|
-- ====================================================
|
||||||
|
-- 定时任务元数据表(存储爬虫任务的元数据配置)
|
||||||
|
-- ====================================================
|
||||||
|
DROP TABLE IF EXISTS `tb_crontab_task_meta`;
|
||||||
|
CREATE TABLE `tb_crontab_task_meta` (
|
||||||
|
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
|
||||||
|
`meta_id` VARCHAR(64) NOT NULL COMMENT '元数据ID',
|
||||||
|
`name` VARCHAR(100) NOT NULL COMMENT '任务名称',
|
||||||
|
`description` VARCHAR(500) DEFAULT NULL COMMENT '任务描述',
|
||||||
|
`category` VARCHAR(50) NOT NULL COMMENT '任务分类(如:人民日报新闻爬取)',
|
||||||
|
`bean_name` VARCHAR(100) NOT NULL COMMENT 'Bean名称(执行器类名)',
|
||||||
|
`method_name` VARCHAR(100) NOT NULL COMMENT '执行方法名',
|
||||||
|
`script_path` VARCHAR(255) DEFAULT NULL COMMENT 'Python脚本路径(相对于basePath)',
|
||||||
|
`param_schema` TEXT DEFAULT NULL COMMENT '参数模板(JSON格式,定义参数名、类型、描述、默认值等)',
|
||||||
|
`auto_publish` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否自动发布',
|
||||||
|
`sort_order` INT DEFAULT 0 COMMENT '排序号',
|
||||||
|
`creator` VARCHAR(64) DEFAULT NULL COMMENT '创建者',
|
||||||
|
`updater` VARCHAR(64) DEFAULT NULL COMMENT '更新者',
|
||||||
|
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
`delete_time` DATETIME DEFAULT NULL COMMENT '删除时间',
|
||||||
|
`deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除(0:否 1:是)',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `uk_meta_id` (`meta_id`),
|
||||||
|
KEY `idx_category` (`category`),
|
||||||
|
KEY `idx_deleted` (`deleted`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='定时任务元数据表';
|
||||||
|
|
||||||
|
-- ====================================================
|
||||||
|
-- 定时任务邮件通知默认接收人员表(关联任务元数据,定义默认接收人员)
|
||||||
|
-- ====================================================
|
||||||
|
DROP TABLE IF EXISTS `tb_crontab_email_default`;
|
||||||
|
CREATE TABLE `tb_crontab_email_default` (
|
||||||
|
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
|
||||||
|
`default_id` VARCHAR(64) NOT NULL COMMENT '默认ID',
|
||||||
|
`meta_id` VARCHAR(64) NOT NULL COMMENT '关联任务元数据ID',
|
||||||
|
`user_id` VARCHAR(64) NOT NULL COMMENT '关联用户ID',
|
||||||
|
`creator` VARCHAR(64) DEFAULT NULL COMMENT '创建者',
|
||||||
|
`updater` VARCHAR(64) DEFAULT NULL COMMENT '更新者',
|
||||||
|
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
`delete_time` DATETIME DEFAULT NULL COMMENT '删除时间',
|
||||||
|
`deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除(0:否 1:是)',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `uk_default_id` (`default_id`),
|
||||||
|
UNIQUE KEY `uk_meta_id` (`meta_id`),
|
||||||
|
KEY `idx_deleted` (`deleted`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='定时任务邮件通知默认接收人员表';
|
||||||
|
|
||||||
|
-- ====================================================
|
||||||
|
-- 定时任务邮件接收人表(1对多)
|
||||||
|
-- ====================================================
|
||||||
|
DROP TABLE IF EXISTS `tb_crontab_email_recipient`;
|
||||||
|
CREATE TABLE `tb_crontab_email_recipient` (
|
||||||
|
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
|
||||||
|
`recipient_id` VARCHAR(64) NOT NULL COMMENT '接收人ID',
|
||||||
|
`task_id` VARCHAR(64) DEFAULT NULL COMMENT '关联任务ID(NULL表示不属于任何任务)',
|
||||||
|
`user_id` VARCHAR(64) DEFAULT NULL COMMENT '关联用户ID',
|
||||||
|
`email` VARCHAR(100) NOT NULL COMMENT '邮箱地址',
|
||||||
|
`name` VARCHAR(100) DEFAULT NULL COMMENT '接收人姓名',
|
||||||
|
`creator` VARCHAR(64) DEFAULT NULL COMMENT '创建者',
|
||||||
|
`updater` VARCHAR(64) DEFAULT NULL COMMENT '更新者',
|
||||||
|
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
`delete_time` DATETIME DEFAULT NULL COMMENT '删除时间',
|
||||||
|
`deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除(0:否 1:是)',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `uk_recipient_id` (`recipient_id`),
|
||||||
|
KEY `idx_task_id` (`task_id`),
|
||||||
|
KEY `idx_user_id` (`user_id`),
|
||||||
|
KEY `idx_email` (`email`),
|
||||||
|
KEY `idx_deleted` (`deleted`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='定时任务邮件接收人表';
|
||||||
@@ -38,7 +38,9 @@ INSERT INTO `tb_sys_config` (id, config_key, config_value, config_type, config_g
|
|||||||
('10', 'system.banner.interval', '5000', 'number', 'banner', 'Banner切换间隔(毫秒)', 0, '1', now()),
|
('10', 'system.banner.interval', '5000', 'number', 'banner', 'Banner切换间隔(毫秒)', 0, '1', now()),
|
||||||
('11', 'system.resource.auto_publish', 'false', 'boolean', 'resource', '资源自动发布', 0, '1', now()),
|
('11', 'system.resource.auto_publish', 'false', 'boolean', 'resource', '资源自动发布', 0, '1', now()),
|
||||||
('12', 'system.resource.auto_publish_time', '08:00', 'string', 'resource', '自动发布时间', 0, '1', now()),
|
('12', 'system.resource.auto_publish_time', '08:00', 'string', 'resource', '自动发布时间', 0, '1', now()),
|
||||||
('13', 'system.ai.enabled', 'true', 'boolean', 'ai', '是否启用智能体', 0, '1', now());
|
('13', 'system.ai.enabled', 'true', 'boolean', 'ai', '是否启用智能体', 0, '1', now()),
|
||||||
|
('14', 'crawler.pythonPath', 'F:/Environment/Conda/envs/schoolNewsCrawler/python.exe', 'string', 'crawler', 'Python可执行文件路径', 1, '1', now()),
|
||||||
|
('15', 'crawler.basePath', 'F:/Project/schoolNews/schoolNewsCrawler', 'string', 'crawler', '爬虫脚本根目录', 1, '1', now());
|
||||||
|
|
||||||
-- 注意:默认superadmin用户已在 initMenuData.sql 中创建,此处无需重复创建
|
-- 注意:默认superadmin用户已在 initMenuData.sql 中创建,此处无需重复创建
|
||||||
|
|
||||||
|
|||||||
102
schoolNewsServ/.bin/mysql/sql/initCrontabMetaData.sql
Normal file
102
schoolNewsServ/.bin/mysql/sql/initCrontabMetaData.sql
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
-- ====================================================
|
||||||
|
-- 定时任务元数据初始化脚本
|
||||||
|
-- ====================================================
|
||||||
|
|
||||||
|
-- 插入人民日报新闻爬取任务的元数据
|
||||||
|
|
||||||
|
-- 1. 关键字搜索爬取
|
||||||
|
INSERT INTO `tb_crontab_task_meta` (
|
||||||
|
`id`, `meta_id`, `name`, `description`, `category`,
|
||||||
|
`bean_name`, `method_name`, `script_path`, `param_schema`,
|
||||||
|
`sort_order`, `creator`, `create_time`
|
||||||
|
) VALUES (
|
||||||
|
'1',
|
||||||
|
'rmbr_keyword_search',
|
||||||
|
'关键字搜索爬取',
|
||||||
|
'根据关键字搜索人民日报新闻内容',
|
||||||
|
'人民日报新闻爬取',
|
||||||
|
'newsCrewerTask',
|
||||||
|
'execute',
|
||||||
|
'crawler/RmrbSearch.py',
|
||||||
|
'[
|
||||||
|
{
|
||||||
|
"name": "query",
|
||||||
|
"description": "搜索关键字",
|
||||||
|
"type": "String",
|
||||||
|
"value": "",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "total",
|
||||||
|
"description": "总新闻数量",
|
||||||
|
"type": "Integer",
|
||||||
|
"value": 10,
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]',
|
||||||
|
1,
|
||||||
|
'system',
|
||||||
|
NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 2. 排行榜爬取
|
||||||
|
INSERT INTO `tb_crontab_task_meta` (
|
||||||
|
`id`, `meta_id`, `name`, `description`, `category`,
|
||||||
|
`bean_name`, `method_name`, `script_path`, `param_schema`,
|
||||||
|
`sort_order`, `creator`, `create_time`
|
||||||
|
) VALUES (
|
||||||
|
'2',
|
||||||
|
'rmbr_hotpoint',
|
||||||
|
'排行榜爬取',
|
||||||
|
'爬取人民日报热门排行榜新闻',
|
||||||
|
'人民日报新闻爬取',
|
||||||
|
'newsCrewerTask',
|
||||||
|
'execute',
|
||||||
|
'crawler/RmrbHotPoint.py',
|
||||||
|
'[]',
|
||||||
|
2,
|
||||||
|
'system',
|
||||||
|
NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 3. 往日精彩头条爬取
|
||||||
|
INSERT INTO `tb_crontab_task_meta` (
|
||||||
|
`id`, `meta_id`, `name`, `description`, `category`,
|
||||||
|
`bean_name`, `method_name`, `script_path`, `param_schema`,
|
||||||
|
`sort_order`, `creator`, `create_time`
|
||||||
|
) VALUES (
|
||||||
|
'3',
|
||||||
|
'rmbr_trending',
|
||||||
|
'往日精彩头条爬取',
|
||||||
|
'爬取人民日报往日精彩头条新闻',
|
||||||
|
'人民日报新闻爬取',
|
||||||
|
'newsCrewerTask',
|
||||||
|
'execute',
|
||||||
|
'crawler/RmrbTrending.py',
|
||||||
|
'[
|
||||||
|
{
|
||||||
|
"name": "startDate",
|
||||||
|
"description": "开始日期",
|
||||||
|
"type": "String",
|
||||||
|
"value": "",
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "endDate",
|
||||||
|
"description": "结束日期",
|
||||||
|
"type": "String",
|
||||||
|
"value": "",
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "yesterday",
|
||||||
|
"description": "是否是昨天",
|
||||||
|
"type": "Boolean",
|
||||||
|
"value": true,
|
||||||
|
"required": false
|
||||||
|
}
|
||||||
|
]',
|
||||||
|
3,
|
||||||
|
'system',
|
||||||
|
NOW()
|
||||||
|
);
|
||||||
@@ -52,7 +52,7 @@ public class AchievementController {
|
|||||||
* 删除成就
|
* 删除成就
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/achievement")
|
@DeleteMapping("/achievement")
|
||||||
public ResultDomain<Void> deleteAchievement(@RequestBody TbAchievement achievement) {
|
public ResultDomain<Boolean> deleteAchievement(@RequestBody TbAchievement achievement) {
|
||||||
return achievementService.deleteAchievement(achievement.getAchievementID());
|
return achievementService.deleteAchievement(achievement.getAchievementID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ public class AchievementController {
|
|||||||
* 撤销用户成就
|
* 撤销用户成就
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/revoke")
|
@DeleteMapping("/revoke")
|
||||||
public ResultDomain<Void> revokeAchievement(
|
public ResultDomain<Boolean> revokeAchievement(
|
||||||
@RequestParam(name = "userID") String userID,
|
@RequestParam(name = "userID") String userID,
|
||||||
@RequestParam(name = "achievementID") String achievementID) {
|
@RequestParam(name = "achievementID") String achievementID) {
|
||||||
return achievementService.revokeAchievement(userID, achievementID);
|
return achievementService.revokeAchievement(userID, achievementID);
|
||||||
|
|||||||
@@ -168,8 +168,8 @@ public class ACHAchievementServiceImpl implements AchievementService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public ResultDomain<Void> deleteAchievement(String achievementID) {
|
public ResultDomain<Boolean> deleteAchievement(String achievementID) {
|
||||||
ResultDomain<Void> resultDomain = new ResultDomain<>();
|
ResultDomain<Boolean> resultDomain = new ResultDomain<>();
|
||||||
try {
|
try {
|
||||||
if (!StringUtils.hasText(achievementID)) {
|
if (!StringUtils.hasText(achievementID)) {
|
||||||
resultDomain.fail("成就ID不能为空");
|
resultDomain.fail("成就ID不能为空");
|
||||||
@@ -188,7 +188,7 @@ public class ACHAchievementServiceImpl implements AchievementService {
|
|||||||
int result = achievementMapper.updateAchievement(achievement);
|
int result = achievementMapper.updateAchievement(achievement);
|
||||||
|
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
resultDomain.success("删除成就成功", (Void) null);
|
resultDomain.success("删除成就成功", true);
|
||||||
} else {
|
} else {
|
||||||
resultDomain.fail("删除成就失败");
|
resultDomain.fail("删除成就失败");
|
||||||
}
|
}
|
||||||
@@ -405,8 +405,8 @@ public class ACHAchievementServiceImpl implements AchievementService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public ResultDomain<Void> revokeAchievement(String userID, String achievementID) {
|
public ResultDomain<Boolean> revokeAchievement(String userID, String achievementID) {
|
||||||
ResultDomain<Void> resultDomain = new ResultDomain<>();
|
ResultDomain<Boolean> resultDomain = new ResultDomain<>();
|
||||||
try {
|
try {
|
||||||
if (!StringUtils.hasText(userID) || !StringUtils.hasText(achievementID)) {
|
if (!StringUtils.hasText(userID) || !StringUtils.hasText(achievementID)) {
|
||||||
resultDomain.fail("参数不能为空");
|
resultDomain.fail("参数不能为空");
|
||||||
@@ -417,7 +417,7 @@ public class ACHAchievementServiceImpl implements AchievementService {
|
|||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
// 重置进度
|
// 重置进度
|
||||||
progressMapper.deleteProgress(userID, achievementID);
|
progressMapper.deleteProgress(userID, achievementID);
|
||||||
resultDomain.success("撤销成就成功", (Void) null);
|
resultDomain.success("撤销成就成功", true);
|
||||||
} else {
|
} else {
|
||||||
resultDomain.fail("撤销成就失败");
|
resultDomain.fail("撤销成就失败");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ public interface AchievementService {
|
|||||||
/**
|
/**
|
||||||
* @description 删除成就
|
* @description 删除成就
|
||||||
* @param achievementID 成就ID
|
* @param achievementID 成就ID
|
||||||
* @return ResultDomain<Void> 删除结果
|
* @return ResultDomain<Boolean> 删除结果
|
||||||
*/
|
*/
|
||||||
ResultDomain<Void> deleteAchievement(String achievementID);
|
ResultDomain<Boolean> deleteAchievement(String achievementID);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 获取所有成就列表
|
* @description 获取所有成就列表
|
||||||
@@ -112,9 +112,9 @@ public interface AchievementService {
|
|||||||
* @description 撤销用户成就(管理员功能)
|
* @description 撤销用户成就(管理员功能)
|
||||||
* @param userID 用户ID
|
* @param userID 用户ID
|
||||||
* @param achievementID 成就ID
|
* @param achievementID 成就ID
|
||||||
* @return ResultDomain<Void> 撤销结果
|
* @return ResultDomain<Boolean> 撤销结果
|
||||||
*/
|
*/
|
||||||
ResultDomain<Void> revokeAchievement(String userID, String achievementID);
|
ResultDomain<Boolean> revokeAchievement(String userID, String achievementID);
|
||||||
|
|
||||||
// ==================== 成就进度管理 ====================
|
// ==================== 成就进度管理 ====================
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.xyzh.api.crontab;
|
|||||||
|
|
||||||
import org.xyzh.common.core.domain.ResultDomain;
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
import org.xyzh.common.core.page.PageParam;
|
import org.xyzh.common.core.page.PageParam;
|
||||||
|
import org.xyzh.common.dto.crontab.CreateTaskRequest;
|
||||||
import org.xyzh.common.dto.crontab.TbCrontabTask;
|
import org.xyzh.common.dto.crontab.TbCrontabTask;
|
||||||
import org.xyzh.common.dto.crontab.TbCrontabLog;
|
import org.xyzh.common.dto.crontab.TbCrontabLog;
|
||||||
import org.xyzh.common.vo.CrontabTaskVO;
|
import org.xyzh.common.vo.CrontabTaskVO;
|
||||||
@@ -27,6 +28,15 @@ public interface CrontabService {
|
|||||||
*/
|
*/
|
||||||
ResultDomain<TbCrontabTask> createTask(TbCrontabTask task);
|
ResultDomain<TbCrontabTask> createTask(TbCrontabTask task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建定时任务并绑定邮件接收人
|
||||||
|
* @param request 创建任务请求(包含任务信息、是否使用默认接收人、额外接收人列表)
|
||||||
|
* @return ResultDomain<TbCrontabTask> 创建结果
|
||||||
|
* @author yslg
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabTask> createTaskWithRecipients(CreateTaskRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 更新定时任务
|
* @description 更新定时任务
|
||||||
* @param task 任务对象
|
* @param task 任务对象
|
||||||
@@ -36,6 +46,15 @@ public interface CrontabService {
|
|||||||
*/
|
*/
|
||||||
ResultDomain<TbCrontabTask> updateTask(TbCrontabTask task);
|
ResultDomain<TbCrontabTask> updateTask(TbCrontabTask task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新定时任务并更新邮件接收人
|
||||||
|
* @param request 更新任务请求(包含任务信息、是否使用默认接收人、额外接收人列表)
|
||||||
|
* @return ResultDomain<TbCrontabTask> 更新结果
|
||||||
|
* @author yslg
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabTask> updateTaskWithRecipients(CreateTaskRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 删除定时任务
|
* @description 删除定时任务
|
||||||
* @param taskId 任务ID
|
* @param taskId 任务ID
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package org.xyzh.api.crontab;
|
||||||
|
|
||||||
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabEmailDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务邮件通知默认接收人服务接口
|
||||||
|
* @filename EmailDefaultService.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
public interface EmailDefaultService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建默认接收人
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabEmailDefault> createDefault(TbCrontabEmailDefault emailDefault);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新默认接收人
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabEmailDefault> updateDefault(TbCrontabEmailDefault emailDefault);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除默认接收人
|
||||||
|
*/
|
||||||
|
ResultDomain<Boolean> deleteDefault(String defaultId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据defaultId查询
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabEmailDefault> getDefaultById(String defaultId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据metaId查询
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabEmailDefault> getDefaultByMetaId(String metaId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package org.xyzh.api.crontab;
|
||||||
|
|
||||||
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
|
import org.xyzh.common.core.page.PageRequest;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabEmailRecipient;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务邮件接收人服务接口
|
||||||
|
* @filename EmailRecipientService.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
public interface EmailRecipientService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建邮件接收人
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabEmailRecipient> createRecipient(TbCrontabEmailRecipient recipient);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 批量创建邮件接收人
|
||||||
|
*/
|
||||||
|
ResultDomain<Boolean> batchCreateRecipient(List<TbCrontabEmailRecipient> recipients);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新邮件接收人
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabEmailRecipient> updateRecipient(TbCrontabEmailRecipient recipient);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除邮件接收人
|
||||||
|
*/
|
||||||
|
ResultDomain<Boolean> deleteRecipient(String recipientId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据ID查询
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabEmailRecipient> getRecipientById(String recipientId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据任务ID查询接收人列表
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabEmailRecipient> getRecipientsByTaskId(String taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 分页查询邮件接收人
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabEmailRecipient> getRecipientPage(PageRequest<TbCrontabEmailRecipient> request);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除任务的所有接收人
|
||||||
|
*/
|
||||||
|
ResultDomain<Boolean> deleteRecipientsByTaskId(String taskId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package org.xyzh.api.crontab;
|
||||||
|
|
||||||
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
|
import org.xyzh.common.core.page.PageRequest;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabTaskMeta;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务元数据服务接口
|
||||||
|
* @filename TaskMetaService.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
public interface TaskMetaService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建任务元数据
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabTaskMeta> createTaskMeta(TbCrontabTaskMeta taskMeta);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新任务元数据
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabTaskMeta> updateTaskMeta(TbCrontabTaskMeta taskMeta);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除任务元数据
|
||||||
|
*/
|
||||||
|
ResultDomain<Boolean> deleteTaskMeta(String metaId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据ID查询任务元数据
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabTaskMeta> getTaskMetaById(String metaId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据任务ID查询任务元数据
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabTaskMeta> getTaskMetaByTaskId(String taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 查询所有任务元数据
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabTaskMeta> getAllTaskMeta();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据分类查询任务元数据
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabTaskMeta> getTaskMetaByCategory(String category);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 分页查询任务元数据
|
||||||
|
*/
|
||||||
|
ResultDomain<TbCrontabTaskMeta> getTaskMetaPage(PageRequest<TbCrontabTaskMeta> request);
|
||||||
|
}
|
||||||
@@ -9,6 +9,40 @@ package org.xyzh.api.system.config;
|
|||||||
*/
|
*/
|
||||||
public interface SysConfigService {
|
public interface SysConfigService {
|
||||||
|
|
||||||
/** */
|
Object getSysConfig(String key);
|
||||||
String getSysConfig(String key);
|
|
||||||
|
/**
|
||||||
|
* 获取字符串类型配置
|
||||||
|
* @param key 配置键
|
||||||
|
* @return 配置值
|
||||||
|
*/
|
||||||
|
String getStringConfig(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取整数类型配置
|
||||||
|
* @param key 配置键
|
||||||
|
* @return 配置值,如果不存在或解析失败返回null
|
||||||
|
*/
|
||||||
|
Integer getIntConfig(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取布尔类型配置
|
||||||
|
* @param key 配置键
|
||||||
|
* @return 配置值,如果不存在或解析失败返回null
|
||||||
|
*/
|
||||||
|
Boolean getBooleanConfig(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取浮点数类型配置
|
||||||
|
* @param key 配置键
|
||||||
|
* @return 配置值,如果不存在或解析失败返回null
|
||||||
|
*/
|
||||||
|
Double getDoubleConfig(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取长整数类型配置
|
||||||
|
* @param key 配置键
|
||||||
|
* @return 配置值,如果不存在或解析失败返回null
|
||||||
|
*/
|
||||||
|
Long getLongConfig(String key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package org.xyzh.common.dto.crontab;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建定时任务请求
|
||||||
|
* @filename CreateTaskRequest.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
public class CreateTaskRequest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 任务信息
|
||||||
|
*/
|
||||||
|
private TbCrontabTask task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 任务元数据ID(用于查找默认接收人配置)
|
||||||
|
*/
|
||||||
|
private String metaId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 额外添加的接收人列表(从系统用户中选择,前端传入完整信息避免重复查询)
|
||||||
|
*/
|
||||||
|
private List<RecipientUserInfo> additionalRecipients;
|
||||||
|
|
||||||
|
public TbCrontabTask getTask() {
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTask(TbCrontabTask task) {
|
||||||
|
this.task = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMetaId() {
|
||||||
|
return metaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetaId(String metaId) {
|
||||||
|
this.metaId = metaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RecipientUserInfo> getAdditionalRecipients() {
|
||||||
|
return additionalRecipients;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAdditionalRecipients(List<RecipientUserInfo> additionalRecipients) {
|
||||||
|
this.additionalRecipients = additionalRecipients;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 接收人用户信息(从tb_sys_user选择)
|
||||||
|
*/
|
||||||
|
public static class RecipientUserInfo {
|
||||||
|
/**
|
||||||
|
* @description 用户ID
|
||||||
|
*/
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 用户邮箱
|
||||||
|
*/
|
||||||
|
private String userEmail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 用户名称
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
public String getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(String userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserEmail() {
|
||||||
|
return userEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserEmail(String userEmail) {
|
||||||
|
this.userEmail = userEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RecipientUserInfo{" +
|
||||||
|
"userId='" + userId + '\'' +
|
||||||
|
", userEmail='" + userEmail + '\'' +
|
||||||
|
", username='" + username + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "CreateTaskRequest{" +
|
||||||
|
"task=" + task +
|
||||||
|
", metaId='" + metaId + '\'' +
|
||||||
|
", additionalRecipients=" + additionalRecipients +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
package org.xyzh.common.dto.crontab;
|
||||||
|
|
||||||
|
import org.xyzh.common.dto.BaseDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务邮件通知默认接收人员表
|
||||||
|
* @filename TbCrontabEmailDefault.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
public class TbCrontabEmailDefault extends BaseDTO {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 默认ID
|
||||||
|
*/
|
||||||
|
private String defaultId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 关联任务元数据ID
|
||||||
|
*/
|
||||||
|
private String metaId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 关联用户ID
|
||||||
|
*/
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 关联用户邮箱
|
||||||
|
*/
|
||||||
|
private String userEmail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 关联用户名称
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建者
|
||||||
|
*/
|
||||||
|
private String creator;
|
||||||
|
/**
|
||||||
|
* @description 更新者
|
||||||
|
*/
|
||||||
|
private String updater;
|
||||||
|
|
||||||
|
public String getDefaultId() {
|
||||||
|
return defaultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultId(String defaultId) {
|
||||||
|
this.defaultId = defaultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMetaId() {
|
||||||
|
return metaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetaId(String metaId) {
|
||||||
|
this.metaId = metaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(String userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserEmail() {
|
||||||
|
return userEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserEmail(String userEmail) {
|
||||||
|
this.userEmail = userEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreator() {
|
||||||
|
return creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreator(String creator) {
|
||||||
|
this.creator = creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdater() {
|
||||||
|
return updater;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdater(String updater) {
|
||||||
|
this.updater = updater;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TbCrontabEmailDefault{" +
|
||||||
|
"id=" + getID() +
|
||||||
|
", defaultId='" + defaultId + '\'' +
|
||||||
|
", metaId='" + metaId + '\'' +
|
||||||
|
", userId='" + userId + '\'' +
|
||||||
|
", userEmail='" + userEmail + '\'' +
|
||||||
|
", username='" + username + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package org.xyzh.common.dto.crontab;
|
||||||
|
|
||||||
|
import org.xyzh.common.dto.BaseDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务邮件接收人表
|
||||||
|
* @filename TbCrontabEmailRecipient.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
public class TbCrontabEmailRecipient extends BaseDTO {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 接收人ID
|
||||||
|
*/
|
||||||
|
private String recipientId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 关联任务ID(NULL表示不属于任务)
|
||||||
|
*/
|
||||||
|
private String taskId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 关联用户ID
|
||||||
|
*/
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 邮箱地址
|
||||||
|
*/
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 接收人姓名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建者
|
||||||
|
*/
|
||||||
|
private String creator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新者
|
||||||
|
*/
|
||||||
|
private String updater;
|
||||||
|
|
||||||
|
public String getRecipientId() {
|
||||||
|
return recipientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecipientId(String recipientId) {
|
||||||
|
this.recipientId = recipientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTaskId() {
|
||||||
|
return taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskId(String taskId) {
|
||||||
|
this.taskId = taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(String userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreator() {
|
||||||
|
return creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreator(String creator) {
|
||||||
|
this.creator = creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdater() {
|
||||||
|
return updater;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdater(String updater) {
|
||||||
|
this.updater = updater;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TbCrontabEmailRecipient{" +
|
||||||
|
"id=" + getID() +
|
||||||
|
", recipientId='" + recipientId + '\'' +
|
||||||
|
", taskId='" + taskId + '\'' +
|
||||||
|
", userId='" + userId + '\'' +
|
||||||
|
", email='" + email + '\'' +
|
||||||
|
", name='" + name + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,6 +43,16 @@ public class TbCrontabTask extends BaseDTO {
|
|||||||
*/
|
*/
|
||||||
private String methodParams;
|
private String methodParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 元数据ID(关联任务元数据表)
|
||||||
|
*/
|
||||||
|
private String metaId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 是否使用默认接收人(false:否 true:是)
|
||||||
|
*/
|
||||||
|
private Boolean defaultRecipient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Cron表达式
|
* @description Cron表达式
|
||||||
*/
|
*/
|
||||||
@@ -126,6 +136,22 @@ public class TbCrontabTask extends BaseDTO {
|
|||||||
this.methodParams = methodParams;
|
this.methodParams = methodParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMetaId() {
|
||||||
|
return metaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetaId(String metaId) {
|
||||||
|
this.metaId = metaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getDefaultRecipient() {
|
||||||
|
return defaultRecipient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultRecipient(Boolean defaultRecipient) {
|
||||||
|
this.defaultRecipient = defaultRecipient;
|
||||||
|
}
|
||||||
|
|
||||||
public String getCronExpression() {
|
public String getCronExpression() {
|
||||||
return cronExpression;
|
return cronExpression;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,187 @@
|
|||||||
|
package org.xyzh.common.dto.crontab;
|
||||||
|
|
||||||
|
import org.xyzh.common.dto.BaseDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务元数据表
|
||||||
|
* @filename TbCrontabTaskMeta.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
public class TbCrontabTaskMeta extends BaseDTO {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 元数据ID
|
||||||
|
*/
|
||||||
|
private String metaId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 任务名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 任务描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 任务分类(如:人民日报新闻爬取)
|
||||||
|
*/
|
||||||
|
private String category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Bean名称(执行器类名)
|
||||||
|
*/
|
||||||
|
private String beanName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 执行方法名
|
||||||
|
*/
|
||||||
|
private String methodName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Python脚本路径(相对于basePath)
|
||||||
|
*/
|
||||||
|
private String scriptPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 参数模板(JSON格式)
|
||||||
|
*/
|
||||||
|
private String paramSchema;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 是否自动发布
|
||||||
|
*/
|
||||||
|
private Boolean autoPublish;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 排序号
|
||||||
|
*/
|
||||||
|
private Integer sortOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建者
|
||||||
|
*/
|
||||||
|
private String creator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新者
|
||||||
|
*/
|
||||||
|
private String updater;
|
||||||
|
|
||||||
|
public String getMetaId() {
|
||||||
|
return metaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetaId(String metaId) {
|
||||||
|
this.metaId = metaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCategory() {
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategory(String category) {
|
||||||
|
this.category = category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBeanName() {
|
||||||
|
return beanName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBeanName(String beanName) {
|
||||||
|
this.beanName = beanName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMethodName() {
|
||||||
|
return methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMethodName(String methodName) {
|
||||||
|
this.methodName = methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScriptPath() {
|
||||||
|
return scriptPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScriptPath(String scriptPath) {
|
||||||
|
this.scriptPath = scriptPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParamSchema() {
|
||||||
|
return paramSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParamSchema(String paramSchema) {
|
||||||
|
this.paramSchema = paramSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getAutoPublish() {
|
||||||
|
return autoPublish;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoPublish(Boolean autoPublish) {
|
||||||
|
this.autoPublish = autoPublish;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSortOrder() {
|
||||||
|
return sortOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSortOrder(Integer sortOrder) {
|
||||||
|
this.sortOrder = sortOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreator() {
|
||||||
|
return creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreator(String creator) {
|
||||||
|
this.creator = creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdater() {
|
||||||
|
return updater;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdater(String updater) {
|
||||||
|
this.updater = updater;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TbCrontabTaskMeta{" +
|
||||||
|
"id=" + getID() +
|
||||||
|
", metaId='" + metaId + '\'' +
|
||||||
|
", name='" + name + '\'' +
|
||||||
|
", category='" + category + '\'' +
|
||||||
|
", beanName='" + beanName + '\'' +
|
||||||
|
", methodName='" + methodName + '\'' +
|
||||||
|
", scriptPath='" + scriptPath + '\'' +
|
||||||
|
", paramSchema='" + paramSchema + '\'' +
|
||||||
|
", autoPublish=" + autoPublish +
|
||||||
|
", sortOrder=" + sortOrder +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,21 +5,14 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.xyzh.api.crontab.CrontabService;
|
import org.xyzh.api.crontab.CrontabService;
|
||||||
|
import org.xyzh.api.crontab.TaskMetaService;
|
||||||
import org.xyzh.common.core.domain.ResultDomain;
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabTaskMeta;
|
||||||
import org.xyzh.common.core.page.PageParam;
|
import org.xyzh.common.core.page.PageParam;
|
||||||
import org.xyzh.common.core.page.PageRequest;
|
import org.xyzh.common.core.page.PageRequest;
|
||||||
|
import org.xyzh.common.dto.crontab.CreateTaskRequest;
|
||||||
import org.xyzh.common.dto.crontab.TbCrontabTask;
|
import org.xyzh.common.dto.crontab.TbCrontabTask;
|
||||||
import org.xyzh.common.dto.crontab.TbCrontabLog;
|
import org.xyzh.common.dto.crontab.TbCrontabLog;
|
||||||
import org.xyzh.crontab.pojo.CrontabItem;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
|
|
||||||
import org.xyzh.common.utils.spring.SpringContextUtil;
|
|
||||||
import org.xyzh.crontab.config.CrontabProperties;
|
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,157 +31,124 @@ public class CrontabController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private CrontabService crontabService;
|
private CrontabService crontabService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TaskMetaService taskMetaService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取可创建的定时任务
|
* 获取可创建的定时任务(从数据库获取任务元数据列表)
|
||||||
* @return
|
* @return ResultDomain<TbCrontabTaskMeta>
|
||||||
*/
|
*/
|
||||||
@GetMapping("/getEnabledCrontabList")
|
@GetMapping("/getEnabledCrontabList")
|
||||||
public ResultDomain<CrontabItem> getEnabledCrontabList(@RequestParam(required = false) String param) {
|
public ResultDomain<TbCrontabTaskMeta> getEnabledCrontabList(@RequestParam(required = false) String param) {
|
||||||
ResultDomain<CrontabItem> rd = new ResultDomain<>();
|
|
||||||
try {
|
try {
|
||||||
// 仅返回爬虫能力的元信息(任务模版列表),不包含调度相关内容
|
// 从数据库查询所有任务元数据
|
||||||
CrontabProperties props =
|
ResultDomain<TbCrontabTaskMeta> result = taskMetaService.getAllTaskMeta();
|
||||||
SpringContextUtil.getBean(CrontabProperties.class);
|
result.getDataList().forEach(item->{
|
||||||
String jString = JSON.toJSONString(props);
|
item.setBeanName("");
|
||||||
props = JSON.parseObject(jString, CrontabProperties.class);
|
item.setMethodName("");
|
||||||
props.getItems().forEach(item->item.getMethods().forEach(
|
item.setScriptPath("");
|
||||||
method->{
|
});
|
||||||
method.setClazz(null);
|
return result;
|
||||||
method.setExcuete_method(null);
|
|
||||||
}));
|
|
||||||
rd.success("ok", props.getItems());
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
ResultDomain<TbCrontabTaskMeta> rd = new ResultDomain<>();
|
||||||
rd.fail("获取可创建定时任务失败: " + e.getMessage());
|
rd.fail("获取可创建定时任务失败: " + e.getMessage());
|
||||||
}
|
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建定时任务
|
* 创建定时任务并绑定邮件接收人(从数据库获取元数据配置)
|
||||||
* @param crontabItem
|
* @param request 创建任务请求(包含任务信息、元数据ID、是否使用默认接收人、额外接收人列表)
|
||||||
* @return
|
* @return ResultDomain<TbCrontabTask>
|
||||||
*/
|
*/
|
||||||
@PostMapping("/crontabTask")
|
@PostMapping("/crontabTask")
|
||||||
public ResultDomain<TbCrontabTask> createCrontab(@RequestBody TbCrontabTask crontabItem) {
|
public ResultDomain<TbCrontabTask> createCrontab(@RequestBody CreateTaskRequest request) {
|
||||||
ResultDomain<TbCrontabTask> rd = new ResultDomain<>();
|
ResultDomain<TbCrontabTask> rd = new ResultDomain<>();
|
||||||
try {
|
try {
|
||||||
// 根据前端传入的taskGroup和methodName(都是中文显示名)查找配置
|
TbCrontabTask crontabItem = request.getTask();
|
||||||
if (crontabItem.getTaskGroup() == null || crontabItem.getTaskGroup().isEmpty()) {
|
String metaId = request.getMetaId();
|
||||||
rd.fail("任务分组不能为空");
|
|
||||||
return rd;
|
// 验证元数据ID
|
||||||
}
|
if (metaId == null || metaId.isEmpty()) {
|
||||||
if (crontabItem.getMethodName() == null || crontabItem.getMethodName().isEmpty()) {
|
rd.fail("任务元数据ID不能为空");
|
||||||
rd.fail("方法名称不能为空");
|
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据taskGroup和methodName查找配置
|
// 从数据库查询任务元数据
|
||||||
CrontabItem.CrontabMethod method = findMethodByTaskGroupAndMethodName(
|
ResultDomain<TbCrontabTaskMeta> metaResult = taskMetaService.getTaskMetaById(metaId);
|
||||||
crontabItem.getTaskGroup(),
|
if (!metaResult.isSuccess() || metaResult.getData() == null) {
|
||||||
crontabItem.getMethodName()
|
rd.fail("未找到对应的任务元数据: metaId=" + metaId);
|
||||||
);
|
|
||||||
|
|
||||||
if (method != null) {
|
|
||||||
// 填充beanName和实际的Java方法名
|
|
||||||
crontabItem.setBeanName(method.getClazz());
|
|
||||||
crontabItem.setMethodName(method.getExcuete_method());
|
|
||||||
|
|
||||||
// 将scriptPath添加到methodParams中
|
|
||||||
JSONObject methodParams = JSON.parseObject(crontabItem.getMethodParams());
|
|
||||||
methodParams.put("scriptPath", method.getPath());
|
|
||||||
crontabItem.setMethodParams(methodParams.toJSONString());
|
|
||||||
|
|
||||||
logger.info("创建任务 - taskGroup: {}, methodName: {}, beanName: {}, excuete_method: {}, scriptPath: {}",
|
|
||||||
crontabItem.getTaskGroup(), method.getName(), method.getClazz(),
|
|
||||||
method.getExcuete_method(), method.getPath());
|
|
||||||
} else {
|
|
||||||
rd.fail("未找到对应的配置: taskGroup=" + crontabItem.getTaskGroup()
|
|
||||||
+ ", methodName=" + crontabItem.getMethodName());
|
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
return crontabService.createTask(crontabItem);
|
TbCrontabTaskMeta taskMeta = metaResult.getData();
|
||||||
|
|
||||||
|
// 填充任务信息
|
||||||
|
crontabItem.setTaskGroup(taskMeta.getCategory()); // 任务分组使用category
|
||||||
|
crontabItem.setBeanName(taskMeta.getBeanName());
|
||||||
|
crontabItem.setMethodName(taskMeta.getMethodName());
|
||||||
|
crontabItem.setMetaId(metaId); // 保存metaId,执行时从数据库读取scriptPath
|
||||||
|
|
||||||
|
logger.info("创建任务并绑定接收人 - metaId: {}, name: {}, category: {}, defaultRecipient: {}, additionalCount: {}",
|
||||||
|
metaId, taskMeta.getName(), taskMeta.getCategory(),
|
||||||
|
crontabItem.getDefaultRecipient(),
|
||||||
|
request.getAdditionalRecipients() != null ? request.getAdditionalRecipients().size() : 0);
|
||||||
|
|
||||||
|
return crontabService.createTaskWithRecipients(request);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("创建定时任务失败", e);
|
logger.error("创建定时任务并绑定接收人失败", e);
|
||||||
rd.fail("创建定时任务失败: " + e.getMessage());
|
rd.fail("创建定时任务并绑定接收人失败: " + e.getMessage());
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据taskGroup和methodName查找对应的方法配置
|
* 更新定时任务并更新邮件接收人(从数据库获取元数据配置)
|
||||||
*/
|
* @param request 更新任务请求(包含任务信息、元数据ID、是否使用默认接收人、额外接收人列表)
|
||||||
private CrontabItem.CrontabMethod findMethodByTaskGroupAndMethodName(String taskGroup, String methodName) {
|
* @return ResultDomain<TbCrontabTask>
|
||||||
CrontabProperties props = SpringContextUtil.getBean(CrontabProperties.class);
|
|
||||||
if (props == null || props.getItems() == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (CrontabItem item : props.getItems()) {
|
|
||||||
if (item.getName().equals(taskGroup)) {
|
|
||||||
for (CrontabItem.CrontabMethod method : item.getMethods()) {
|
|
||||||
if (method.getName().equals(methodName)) {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新定时任务
|
|
||||||
* @param crontabItem
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@PutMapping("/crontabTask")
|
@PutMapping("/crontabTask")
|
||||||
public ResultDomain<TbCrontabTask> updateCrontab(@RequestBody TbCrontabTask crontabItem) {
|
public ResultDomain<TbCrontabTask> updateCrontab(@RequestBody CreateTaskRequest request) {
|
||||||
ResultDomain<TbCrontabTask> rd = new ResultDomain<>();
|
ResultDomain<TbCrontabTask> rd = new ResultDomain<>();
|
||||||
try {
|
try {
|
||||||
|
TbCrontabTask crontabItem = request.getTask();
|
||||||
|
String metaId = request.getMetaId();
|
||||||
|
|
||||||
// 确保id字段正确传递(用于数据库更新)
|
// 确保id字段正确传递(用于数据库更新)
|
||||||
if (crontabItem.getTaskId() != null && crontabItem.getID() == null) {
|
if (crontabItem.getTaskId() != null && crontabItem.getID() == null) {
|
||||||
crontabItem.setID(crontabItem.getTaskId());
|
crontabItem.setID(crontabItem.getTaskId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据前端传入的taskGroup和methodName(都是中文显示名)查找配置
|
// 验证元数据ID
|
||||||
if (crontabItem.getTaskGroup() == null || crontabItem.getTaskGroup().isEmpty()) {
|
if (metaId == null || metaId.isEmpty()) {
|
||||||
rd.fail("任务分组不能为空");
|
rd.fail("任务元数据ID不能为空");
|
||||||
return rd;
|
|
||||||
}
|
|
||||||
if (crontabItem.getMethodName() == null || crontabItem.getMethodName().isEmpty()) {
|
|
||||||
rd.fail("方法名称不能为空");
|
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据taskGroup和methodName查找配置
|
// 从数据库查询任务元数据
|
||||||
CrontabItem.CrontabMethod method = findMethodByTaskGroupAndMethodName(
|
ResultDomain<TbCrontabTaskMeta> metaResult = taskMetaService.getTaskMetaById(metaId);
|
||||||
crontabItem.getTaskGroup(),
|
if (!metaResult.isSuccess() || metaResult.getData() == null) {
|
||||||
crontabItem.getMethodName()
|
rd.fail("未找到对应的任务元数据: metaId=" + metaId);
|
||||||
);
|
|
||||||
|
|
||||||
if (method != null) {
|
|
||||||
// 填充beanName和实际的Java方法名
|
|
||||||
crontabItem.setBeanName(method.getClazz());
|
|
||||||
crontabItem.setMethodName(method.getExcuete_method());
|
|
||||||
|
|
||||||
// 将scriptPath添加到methodParams中
|
|
||||||
JSONObject methodParams = JSON.parseObject(crontabItem.getMethodParams());
|
|
||||||
methodParams.put("scriptPath", method.getPath());
|
|
||||||
crontabItem.setMethodParams(methodParams.toJSONString());
|
|
||||||
|
|
||||||
logger.info("更新任务 - id: {}, taskGroup: {}, methodName: {}, beanName: {}, excuete_method: {}, scriptPath: {}",
|
|
||||||
crontabItem.getID(), crontabItem.getTaskGroup(), method.getName(), method.getClazz(),
|
|
||||||
method.getExcuete_method(), method.getPath());
|
|
||||||
} else {
|
|
||||||
rd.fail("未找到对应的配置: taskGroup=" + crontabItem.getTaskGroup()
|
|
||||||
+ ", methodName=" + crontabItem.getMethodName());
|
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
return crontabService.updateTask(crontabItem);
|
TbCrontabTaskMeta taskMeta = metaResult.getData();
|
||||||
|
|
||||||
|
// 填充任务信息
|
||||||
|
crontabItem.setTaskGroup(taskMeta.getCategory());
|
||||||
|
crontabItem.setBeanName(taskMeta.getBeanName());
|
||||||
|
crontabItem.setMethodName(taskMeta.getMethodName());
|
||||||
|
crontabItem.setMetaId(metaId); // 保存metaId,执行时从数据库读取scriptPath
|
||||||
|
|
||||||
|
logger.info("更新任务 - id: {}, metaId: {}, name: {}, category: {}, defaultRecipient: {}",
|
||||||
|
crontabItem.getID(), metaId, taskMeta.getName(), taskMeta.getCategory(),
|
||||||
|
crontabItem.getDefaultRecipient());
|
||||||
|
|
||||||
|
// 调用带接收人更新的方法
|
||||||
|
return crontabService.updateTaskWithRecipients(request);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("更新定时任务失败", e);
|
logger.error("更新定时任务并更新接收人失败", e);
|
||||||
rd.fail("更新定时任务失败: " + e.getMessage());
|
rd.fail("更新定时任务并更新接收人失败: " + e.getMessage());
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package org.xyzh.crontab.controller;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.xyzh.api.crontab.EmailDefaultService;
|
||||||
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabEmailDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务邮件通知默认接收人控制器
|
||||||
|
* @filename EmailDefaultController.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/crontab/email/default")
|
||||||
|
public class EmailDefaultController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(EmailDefaultController.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EmailDefaultService emailDefaultService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建默认接收人
|
||||||
|
* @param emailDefault 默认接收人
|
||||||
|
* @return ResultDomain<TbCrontabEmailDefault>
|
||||||
|
*/
|
||||||
|
@PostMapping
|
||||||
|
public ResultDomain<TbCrontabEmailDefault> createDefault(@RequestBody TbCrontabEmailDefault emailDefault) {
|
||||||
|
return emailDefaultService.createDefault(emailDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新默认接收人
|
||||||
|
* @param emailDefault 默认接收人
|
||||||
|
* @return ResultDomain<TbCrontabEmailDefault>
|
||||||
|
*/
|
||||||
|
@PutMapping
|
||||||
|
public ResultDomain<TbCrontabEmailDefault> updateDefault(@RequestBody TbCrontabEmailDefault emailDefault) {
|
||||||
|
return emailDefaultService.updateDefault(emailDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除默认接收人
|
||||||
|
* @param defaultId 默认ID
|
||||||
|
* @return ResultDomain<Boolean>
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/{defaultId}")
|
||||||
|
public ResultDomain<Boolean> deleteDefault(@PathVariable String defaultId) {
|
||||||
|
return emailDefaultService.deleteDefault(defaultId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据defaultId查询
|
||||||
|
* @param defaultId 默认ID
|
||||||
|
* @return ResultDomain<TbCrontabEmailDefault>
|
||||||
|
*/
|
||||||
|
@GetMapping("/{defaultId}")
|
||||||
|
public ResultDomain<TbCrontabEmailDefault> getDefaultById(@PathVariable String defaultId) {
|
||||||
|
return emailDefaultService.getDefaultById(defaultId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据metaId查询
|
||||||
|
* @param metaId 元数据ID
|
||||||
|
* @return ResultDomain<TbCrontabEmailDefault>
|
||||||
|
*/
|
||||||
|
@GetMapping("/meta/{metaId}")
|
||||||
|
public ResultDomain<TbCrontabEmailDefault> getDefaultByMetaId(@PathVariable String metaId) {
|
||||||
|
return emailDefaultService.getDefaultByMetaId(metaId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
package org.xyzh.crontab.controller;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.xyzh.api.crontab.EmailRecipientService;
|
||||||
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
|
import org.xyzh.common.core.page.PageRequest;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabEmailRecipient;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务邮件接收人控制器
|
||||||
|
* @filename EmailRecipientController.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/crontab/email/recipient")
|
||||||
|
public class EmailRecipientController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(EmailRecipientController.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EmailRecipientService emailRecipientService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建邮件接收人
|
||||||
|
* @param recipient 邮件接收人
|
||||||
|
* @return ResultDomain<TbCrontabEmailRecipient>
|
||||||
|
*/
|
||||||
|
@PostMapping
|
||||||
|
public ResultDomain<TbCrontabEmailRecipient> createRecipient(@RequestBody TbCrontabEmailRecipient recipient) {
|
||||||
|
return emailRecipientService.createRecipient(recipient);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 批量创建邮件接收人
|
||||||
|
* @param recipients 邮件接收人列表
|
||||||
|
* @return ResultDomain<Boolean>
|
||||||
|
*/
|
||||||
|
@PostMapping("/batch")
|
||||||
|
public ResultDomain<Boolean> batchCreateRecipient(@RequestBody List<TbCrontabEmailRecipient> recipients) {
|
||||||
|
return emailRecipientService.batchCreateRecipient(recipients);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新邮件接收人
|
||||||
|
* @param recipient 邮件接收人
|
||||||
|
* @return ResultDomain<TbCrontabEmailRecipient>
|
||||||
|
*/
|
||||||
|
@PutMapping
|
||||||
|
public ResultDomain<TbCrontabEmailRecipient> updateRecipient(@RequestBody TbCrontabEmailRecipient recipient) {
|
||||||
|
return emailRecipientService.updateRecipient(recipient);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除邮件接收人
|
||||||
|
* @param recipientId 接收人ID
|
||||||
|
* @return ResultDomain<Boolean>
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/{recipientId}")
|
||||||
|
public ResultDomain<Boolean> deleteRecipient(@PathVariable String recipientId) {
|
||||||
|
return emailRecipientService.deleteRecipient(recipientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据ID查询
|
||||||
|
* @param recipientId 接收人ID
|
||||||
|
* @return ResultDomain<TbCrontabEmailRecipient>
|
||||||
|
*/
|
||||||
|
@GetMapping("/{recipientId}")
|
||||||
|
public ResultDomain<TbCrontabEmailRecipient> getRecipientById(@PathVariable String recipientId) {
|
||||||
|
return emailRecipientService.getRecipientById(recipientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据任务ID查询接收人列表
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @return ResultDomain<TbCrontabEmailRecipient>
|
||||||
|
*/
|
||||||
|
@GetMapping("/task/{taskId}")
|
||||||
|
public ResultDomain<TbCrontabEmailRecipient> getRecipientsByTaskId(@PathVariable String taskId) {
|
||||||
|
return emailRecipientService.getRecipientsByTaskId(taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 分页查询邮件接收人
|
||||||
|
* @param pageRequest 分页请求
|
||||||
|
* @return ResultDomain<TbCrontabEmailRecipient>
|
||||||
|
*/
|
||||||
|
@PostMapping("/page")
|
||||||
|
public ResultDomain<TbCrontabEmailRecipient> getRecipientPage(@RequestBody PageRequest<TbCrontabEmailRecipient> pageRequest) {
|
||||||
|
return emailRecipientService.getRecipientPage(pageRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除任务的所有接收人
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @return ResultDomain<Boolean>
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/task/{taskId}")
|
||||||
|
public ResultDomain<Boolean> deleteRecipientsByTaskId(@PathVariable String taskId) {
|
||||||
|
return emailRecipientService.deleteRecipientsByTaskId(taskId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package org.xyzh.crontab.controller;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.xyzh.api.crontab.TaskMetaService;
|
||||||
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
|
import org.xyzh.common.core.page.PageRequest;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabTaskMeta;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务元数据控制器
|
||||||
|
* @filename TaskMetaController.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/crontab/meta")
|
||||||
|
public class TaskMetaController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(TaskMetaController.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TaskMetaService taskMetaService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建任务元数据
|
||||||
|
* @param taskMeta 任务元数据
|
||||||
|
* @return ResultDomain<TbCrontabTaskMeta>
|
||||||
|
*/
|
||||||
|
@PostMapping
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> createTaskMeta(@RequestBody TbCrontabTaskMeta taskMeta) {
|
||||||
|
return taskMetaService.createTaskMeta(taskMeta);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新任务元数据
|
||||||
|
* @param taskMeta 任务元数据
|
||||||
|
* @return ResultDomain<TbCrontabTaskMeta>
|
||||||
|
*/
|
||||||
|
@PutMapping
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> updateTaskMeta(@RequestBody TbCrontabTaskMeta taskMeta) {
|
||||||
|
return taskMetaService.updateTaskMeta(taskMeta);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除任务元数据
|
||||||
|
* @param metaId 元数据ID
|
||||||
|
* @return ResultDomain<Boolean>
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/{metaId}")
|
||||||
|
public ResultDomain<Boolean> deleteTaskMeta(@PathVariable String metaId) {
|
||||||
|
return taskMetaService.deleteTaskMeta(metaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据ID查询任务元数据
|
||||||
|
* @param metaId 元数据ID
|
||||||
|
* @return ResultDomain<TbCrontabTaskMeta>
|
||||||
|
*/
|
||||||
|
@GetMapping("/{metaId}")
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> getTaskMetaById(@PathVariable String metaId) {
|
||||||
|
return taskMetaService.getTaskMetaById(metaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 查询所有任务元数据
|
||||||
|
* @return ResultDomain<TbCrontabTaskMeta>
|
||||||
|
*/
|
||||||
|
@GetMapping("/all")
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> getAllTaskMeta() {
|
||||||
|
return taskMetaService.getAllTaskMeta();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据分类查询任务元数据
|
||||||
|
* @param category 分类
|
||||||
|
* @return ResultDomain<TbCrontabTaskMeta>
|
||||||
|
*/
|
||||||
|
@GetMapping("/category/{category}")
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> getTaskMetaByCategory(@PathVariable String category) {
|
||||||
|
return taskMetaService.getTaskMetaByCategory(category);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 分页查询任务元数据
|
||||||
|
* @param pageRequest 分页请求
|
||||||
|
* @return ResultDomain<TbCrontabTaskMeta>
|
||||||
|
*/
|
||||||
|
@PostMapping("/page")
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> getTaskMetaPage(@RequestBody PageRequest<TbCrontabTaskMeta> pageRequest) {
|
||||||
|
return taskMetaService.getTaskMetaPage(pageRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package org.xyzh.crontab.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabEmailDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务邮件通知默认接收人访问层
|
||||||
|
* @filename EmailDefaultMapper.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface EmailDefaultMapper extends BaseMapper<TbCrontabEmailDefault> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 插入默认接收人
|
||||||
|
*/
|
||||||
|
int insertDefault(@Param("emailDefault") TbCrontabEmailDefault emailDefault);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新默认接收人
|
||||||
|
*/
|
||||||
|
int updateDefault(@Param("emailDefault") TbCrontabEmailDefault emailDefault);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除默认接收人(逻辑删除)
|
||||||
|
*/
|
||||||
|
int deleteDefault(@Param("defaultId") String defaultId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据defaultId查询
|
||||||
|
*/
|
||||||
|
TbCrontabEmailDefault selectDefaultById(@Param("defaultId") String defaultId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据metaId查询
|
||||||
|
*/
|
||||||
|
List<TbCrontabEmailDefault> selectDefaultByMetaId(@Param("metaId") String metaId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package org.xyzh.crontab.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.xyzh.common.core.page.PageParam;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabEmailRecipient;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务邮件接收人访问层
|
||||||
|
* @filename EmailRecipientMapper.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface EmailRecipientMapper extends BaseMapper<TbCrontabEmailRecipient> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 插入邮件接收人
|
||||||
|
*/
|
||||||
|
int insertRecipient(@Param("recipient") TbCrontabEmailRecipient recipient);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 批量插入邮件接收人
|
||||||
|
*/
|
||||||
|
int batchInsertRecipient(@Param("recipients") List<TbCrontabEmailRecipient> recipients);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新邮件接收人
|
||||||
|
*/
|
||||||
|
int updateRecipient(@Param("recipient") TbCrontabEmailRecipient recipient);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除邮件接收人(逻辑删除)
|
||||||
|
*/
|
||||||
|
int deleteRecipient(@Param("recipientId") String recipientId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据接收人ID查询
|
||||||
|
*/
|
||||||
|
TbCrontabEmailRecipient selectRecipientById(@Param("recipientId") String recipientId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据任务ID查询接收人列表
|
||||||
|
*/
|
||||||
|
List<TbCrontabEmailRecipient> selectRecipientsByTaskId(@Param("taskId") String taskId);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 分页查询邮件接收人
|
||||||
|
*/
|
||||||
|
List<TbCrontabEmailRecipient> selectRecipientPage(@Param("filter") TbCrontabEmailRecipient filter, @Param("pageParam") PageParam pageParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 查询邮件接收人总数
|
||||||
|
*/
|
||||||
|
int countSelectRecipient(@Param("filter") TbCrontabEmailRecipient filter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除任务的所有接收人
|
||||||
|
*/
|
||||||
|
int deleteRecipientsByTaskId(@Param("taskId") String taskId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package org.xyzh.crontab.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.xyzh.common.core.page.PageParam;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabTaskMeta;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务元数据访问层
|
||||||
|
* @filename TaskMetaMapper.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface TaskMetaMapper extends BaseMapper<TbCrontabTaskMeta> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 插入任务元数据
|
||||||
|
*/
|
||||||
|
int insertTaskMeta(@Param("taskMeta") TbCrontabTaskMeta taskMeta);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新任务元数据
|
||||||
|
*/
|
||||||
|
int updateTaskMeta(@Param("taskMeta") TbCrontabTaskMeta taskMeta);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除任务元数据(逻辑删除)
|
||||||
|
*/
|
||||||
|
int deleteTaskMeta(@Param("metaId") String metaId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据元数据ID查询
|
||||||
|
*/
|
||||||
|
TbCrontabTaskMeta selectTaskMetaById(@Param("metaId") String metaId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据任务ID查询
|
||||||
|
*/
|
||||||
|
TbCrontabTaskMeta selectTaskMetaByTaskId(@Param("taskId") String taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 查询所有任务元数据
|
||||||
|
*/
|
||||||
|
List<TbCrontabTaskMeta> selectAllTaskMeta();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据分类查询任务元数据
|
||||||
|
*/
|
||||||
|
List<TbCrontabTaskMeta> selectTaskMetaByCategory(@Param("category") String category);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 分页查询任务元数据
|
||||||
|
*/
|
||||||
|
List<TbCrontabTaskMeta> selectTaskMetaPage(@Param("filter") TbCrontabTaskMeta filter, @Param("pageParam") PageParam pageParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 查询任务元数据总数
|
||||||
|
*/
|
||||||
|
int countSelectTaskMeta(@Param("filter") TbCrontabTaskMeta filter);
|
||||||
|
}
|
||||||
@@ -157,9 +157,12 @@ public class TaskExecutor {
|
|||||||
Map<String, Object> params = JSON.parseObject(methodParams,
|
Map<String, Object> params = JSON.parseObject(methodParams,
|
||||||
new TypeReference<Map<String, Object>>(){});
|
new TypeReference<Map<String, Object>>(){});
|
||||||
|
|
||||||
// 注入taskId和logId
|
// 注入taskId、logId和metaId
|
||||||
params.put("taskId", task.getTaskId());
|
params.put("taskId", task.getTaskId());
|
||||||
params.put("logId", log.getID());
|
params.put("logId", log.getID());
|
||||||
|
if (task.getMetaId() != null) {
|
||||||
|
params.put("metaId", task.getMetaId());
|
||||||
|
}
|
||||||
|
|
||||||
taskParams.setParams(params);
|
taskParams.setParams(params);
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,14 @@ import org.springframework.scheduling.support.CronExpression;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.xyzh.api.crontab.CrontabService;
|
import org.xyzh.api.crontab.CrontabService;
|
||||||
|
import org.xyzh.api.crontab.EmailDefaultService;
|
||||||
|
import org.xyzh.api.crontab.EmailRecipientService;
|
||||||
import org.xyzh.common.core.domain.ResultDomain;
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
import org.xyzh.common.core.page.PageDomain;
|
import org.xyzh.common.core.page.PageDomain;
|
||||||
import org.xyzh.common.core.page.PageParam;
|
import org.xyzh.common.core.page.PageParam;
|
||||||
|
import org.xyzh.common.dto.crontab.CreateTaskRequest;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabEmailDefault;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabEmailRecipient;
|
||||||
import org.xyzh.common.dto.crontab.TbCrontabTask;
|
import org.xyzh.common.dto.crontab.TbCrontabTask;
|
||||||
import org.xyzh.common.dto.crontab.TbCrontabLog;
|
import org.xyzh.common.dto.crontab.TbCrontabLog;
|
||||||
import org.xyzh.common.utils.IDUtils;
|
import org.xyzh.common.utils.IDUtils;
|
||||||
@@ -50,6 +55,12 @@ public class CrontabServiceImpl implements CrontabService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ResourcePermissionService resourcePermissionService;
|
private ResourcePermissionService resourcePermissionService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EmailDefaultService emailDefaultService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EmailRecipientService emailRecipientService;
|
||||||
|
|
||||||
// ----------------定时任务管理--------------------------------
|
// ----------------定时任务管理--------------------------------
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -115,6 +126,101 @@ public class CrontabServiceImpl implements CrontabService {
|
|||||||
return resultDomain;
|
return resultDomain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<TbCrontabTask> createTaskWithRecipients(CreateTaskRequest request) {
|
||||||
|
ResultDomain<TbCrontabTask> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
TbCrontabTask task = request.getTask();
|
||||||
|
|
||||||
|
// 1. 创建任务
|
||||||
|
ResultDomain<TbCrontabTask> createResult = createTask(task);
|
||||||
|
if (!createResult.isSuccess()) {
|
||||||
|
return createResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
String taskId = task.getTaskId();
|
||||||
|
String metaId = request.getMetaId();
|
||||||
|
|
||||||
|
|
||||||
|
// 3. 添加额外的接收人
|
||||||
|
if (request.getAdditionalRecipients() != null && !request.getAdditionalRecipients().isEmpty()) {
|
||||||
|
try {
|
||||||
|
for (CreateTaskRequest.RecipientUserInfo userInfo : request.getAdditionalRecipients()) {
|
||||||
|
TbCrontabEmailRecipient recipient = new TbCrontabEmailRecipient();
|
||||||
|
recipient.setTaskId(taskId);
|
||||||
|
recipient.setUserId(userInfo.getUserId());
|
||||||
|
recipient.setEmail(userInfo.getUserEmail());
|
||||||
|
recipient.setName(userInfo.getUsername());
|
||||||
|
recipient.setCreator(task.getCreator());
|
||||||
|
|
||||||
|
emailRecipientService.createRecipient(recipient);
|
||||||
|
}
|
||||||
|
logger.info("为任务{}添加了{}个额外接收人", taskId, request.getAdditionalRecipients().size());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("添加额外接收人异常,但不影响任务创建: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resultDomain.success("创建任务并绑定接收人成功", task);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("创建任务并绑定接收人异常: ", e);
|
||||||
|
resultDomain.fail("创建任务并绑定接收人异常: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<TbCrontabTask> updateTaskWithRecipients(CreateTaskRequest request) {
|
||||||
|
ResultDomain<TbCrontabTask> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
TbCrontabTask task = request.getTask();
|
||||||
|
|
||||||
|
// 1. 更新任务
|
||||||
|
ResultDomain<TbCrontabTask> updateResult = updateTask(task);
|
||||||
|
if (!updateResult.isSuccess()) {
|
||||||
|
return updateResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
String taskId = task.getTaskId();
|
||||||
|
String metaId = request.getMetaId();
|
||||||
|
|
||||||
|
// 2. 先删除该任务的旧接收人
|
||||||
|
try {
|
||||||
|
emailRecipientService.deleteRecipientsByTaskId(taskId);
|
||||||
|
logger.info("已删除任务{}的旧接收人配置", taskId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("删除旧接收人异常: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 添加额外的接收人
|
||||||
|
if (request.getAdditionalRecipients() != null && !request.getAdditionalRecipients().isEmpty()) {
|
||||||
|
try {
|
||||||
|
for (CreateTaskRequest.RecipientUserInfo userInfo : request.getAdditionalRecipients()) {
|
||||||
|
TbCrontabEmailRecipient recipient = new TbCrontabEmailRecipient();
|
||||||
|
recipient.setTaskId(taskId);
|
||||||
|
recipient.setUserId(userInfo.getUserId());
|
||||||
|
recipient.setEmail(userInfo.getUserEmail());
|
||||||
|
recipient.setName(userInfo.getUsername());
|
||||||
|
recipient.setUpdater(task.getUpdater());
|
||||||
|
|
||||||
|
emailRecipientService.createRecipient(recipient);
|
||||||
|
}
|
||||||
|
logger.info("为任务{}添加了{}个额外接收人", taskId, request.getAdditionalRecipients().size());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("添加额外接收人异常,但不影响任务更新: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resultDomain.success("更新任务并更新接收人成功", task);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("更新任务并更新接收人异常: ", e);
|
||||||
|
resultDomain.fail("更新任务并更新接收人异常: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public ResultDomain<TbCrontabTask> updateTask(TbCrontabTask task) {
|
public ResultDomain<TbCrontabTask> updateTask(TbCrontabTask task) {
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
package org.xyzh.crontab.service.impl;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.xyzh.api.crontab.EmailDefaultService;
|
||||||
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabEmailDefault;
|
||||||
|
import org.xyzh.common.utils.IDUtils;
|
||||||
|
import org.xyzh.crontab.mapper.EmailDefaultMapper;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务邮件通知默认接收人服务实现类
|
||||||
|
* @filename EmailDefaultServiceImpl.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class EmailDefaultServiceImpl implements EmailDefaultService {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(EmailDefaultServiceImpl.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EmailDefaultMapper emailDefaultMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<TbCrontabEmailDefault> createDefault(TbCrontabEmailDefault emailDefault) {
|
||||||
|
ResultDomain<TbCrontabEmailDefault> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
|
||||||
|
// 生成ID
|
||||||
|
emailDefault.setID(IDUtils.generateID());
|
||||||
|
if (emailDefault.getDefaultId() == null || emailDefault.getDefaultId().isEmpty()) {
|
||||||
|
emailDefault.setDefaultId(IDUtils.generateID());
|
||||||
|
}
|
||||||
|
emailDefault.setCreateTime(new Date());
|
||||||
|
emailDefault.setDeleted(false);
|
||||||
|
|
||||||
|
int count = emailDefaultMapper.insertDefault(emailDefault);
|
||||||
|
if (count > 0) {
|
||||||
|
resultDomain.success("创建默认接收人成功", emailDefault);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("创建默认接收人失败");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("创建默认接收人异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("创建默认接收人失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<TbCrontabEmailDefault> updateDefault(TbCrontabEmailDefault emailDefault) {
|
||||||
|
ResultDomain<TbCrontabEmailDefault> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
emailDefault.setUpdateTime(new Date());
|
||||||
|
int count = emailDefaultMapper.updateDefault(emailDefault);
|
||||||
|
if (count > 0) {
|
||||||
|
resultDomain.success("更新默认接收人成功", emailDefault);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("更新默认接收人失败");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("更新默认接收人异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("更新默认接收人失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<Boolean> deleteDefault(String defaultId) {
|
||||||
|
ResultDomain<Boolean> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
int count = emailDefaultMapper.deleteDefault(defaultId);
|
||||||
|
if (count > 0) {
|
||||||
|
resultDomain.success("删除默认接收人成功", true);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("删除默认接收人失败");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("删除默认接收人异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("删除默认接收人失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultDomain<TbCrontabEmailDefault> getDefaultById(String defaultId) {
|
||||||
|
ResultDomain<TbCrontabEmailDefault> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
TbCrontabEmailDefault emailDefault = emailDefaultMapper.selectDefaultById(defaultId);
|
||||||
|
if (emailDefault != null) {
|
||||||
|
resultDomain.success("查询默认接收人成功", emailDefault);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("默认接收人不存在");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("查询默认接收人异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("查询默认接收人失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultDomain<TbCrontabEmailDefault> getDefaultByMetaId(String metaId) {
|
||||||
|
ResultDomain<TbCrontabEmailDefault> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
List<TbCrontabEmailDefault> emailDefault = emailDefaultMapper.selectDefaultByMetaId(metaId);
|
||||||
|
if (emailDefault != null) {
|
||||||
|
resultDomain.success("查询默认接收人成功", emailDefault);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("该任务元数据未配置默认接收人");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("查询默认接收人异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("查询默认接收人失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
package org.xyzh.crontab.service.impl;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.xyzh.api.crontab.EmailRecipientService;
|
||||||
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
|
import org.xyzh.common.core.page.PageDomain;
|
||||||
|
import org.xyzh.common.core.page.PageParam;
|
||||||
|
import org.xyzh.common.core.page.PageRequest;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabEmailRecipient;
|
||||||
|
import org.xyzh.common.utils.IDUtils;
|
||||||
|
import org.xyzh.crontab.mapper.EmailRecipientMapper;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务邮件接收人服务实现类
|
||||||
|
* @filename EmailRecipientServiceImpl.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class EmailRecipientServiceImpl implements EmailRecipientService {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(EmailRecipientServiceImpl.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EmailRecipientMapper emailRecipientMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<TbCrontabEmailRecipient> createRecipient(TbCrontabEmailRecipient recipient) {
|
||||||
|
ResultDomain<TbCrontabEmailRecipient> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
// 生成ID
|
||||||
|
recipient.setID(IDUtils.generateID());
|
||||||
|
if (recipient.getRecipientId() == null || recipient.getRecipientId().isEmpty()) {
|
||||||
|
recipient.setRecipientId(IDUtils.generateID());
|
||||||
|
}
|
||||||
|
recipient.setCreateTime(new Date());
|
||||||
|
recipient.setDeleted(false);
|
||||||
|
|
||||||
|
int count = emailRecipientMapper.insertRecipient(recipient);
|
||||||
|
if (count > 0) {
|
||||||
|
resultDomain.success("创建邮件接收人成功", recipient);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("创建邮件接收人失败");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("创建邮件接收人异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("创建邮件接收人失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<Boolean> batchCreateRecipient(List<TbCrontabEmailRecipient> recipients) {
|
||||||
|
ResultDomain<Boolean> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
for (TbCrontabEmailRecipient recipient : recipients) {
|
||||||
|
recipient.setID(IDUtils.generateID());
|
||||||
|
if (recipient.getRecipientId() == null || recipient.getRecipientId().isEmpty()) {
|
||||||
|
recipient.setRecipientId(IDUtils.generateID());
|
||||||
|
}
|
||||||
|
recipient.setCreateTime(new Date());
|
||||||
|
recipient.setDeleted(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = emailRecipientMapper.batchInsertRecipient(recipients);
|
||||||
|
if (count > 0) {
|
||||||
|
resultDomain.setSuccess(true);
|
||||||
|
resultDomain.setMessage("批量创建邮件接收人成功");
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("批量创建邮件接收人失败");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("批量创建邮件接收人异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("批量创建邮件接收人失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<TbCrontabEmailRecipient> updateRecipient(TbCrontabEmailRecipient recipient) {
|
||||||
|
ResultDomain<TbCrontabEmailRecipient> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
recipient.setUpdateTime(new Date());
|
||||||
|
int count = emailRecipientMapper.updateRecipient(recipient);
|
||||||
|
if (count > 0) {
|
||||||
|
resultDomain.success("更新邮件接收人成功", recipient);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("更新邮件接收人失败");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("更新邮件接收人异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("更新邮件接收人失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<Boolean> deleteRecipient(String recipientId) {
|
||||||
|
ResultDomain<Boolean> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
int count = emailRecipientMapper.deleteRecipient(recipientId);
|
||||||
|
if (count > 0) {
|
||||||
|
resultDomain.success("删除邮件接收人成功", true);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("删除邮件接收人失败");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("删除邮件接收人异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("删除邮件接收人失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultDomain<TbCrontabEmailRecipient> getRecipientById(String recipientId) {
|
||||||
|
ResultDomain<TbCrontabEmailRecipient> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
TbCrontabEmailRecipient recipient = emailRecipientMapper.selectRecipientById(recipientId);
|
||||||
|
if (recipient != null) {
|
||||||
|
resultDomain.success("查询邮件接收人成功", recipient);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("邮件接收人不存在");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("查询邮件接收人异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("查询邮件接收人失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultDomain<TbCrontabEmailRecipient> getRecipientsByTaskId(String taskId) {
|
||||||
|
ResultDomain<TbCrontabEmailRecipient> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
List<TbCrontabEmailRecipient> list = emailRecipientMapper.selectRecipientsByTaskId(taskId);
|
||||||
|
resultDomain.success("查询邮件接收人列表成功", list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("查询邮件接收人列表异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("查询邮件接收人列表失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultDomain<TbCrontabEmailRecipient> getRecipientPage(PageRequest<TbCrontabEmailRecipient> request) {
|
||||||
|
ResultDomain<TbCrontabEmailRecipient> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
PageParam pageParam = request.getPageParam();
|
||||||
|
List<TbCrontabEmailRecipient> list = emailRecipientMapper.selectRecipientPage(request.getFilter(), pageParam);
|
||||||
|
int total = emailRecipientMapper.countSelectRecipient(request.getFilter());
|
||||||
|
|
||||||
|
PageDomain<TbCrontabEmailRecipient> pageDomain = new PageDomain<>();
|
||||||
|
pageDomain.setPageParam(pageParam);
|
||||||
|
pageParam.setTotalElements(total);
|
||||||
|
pageDomain.setDataList(list);
|
||||||
|
|
||||||
|
resultDomain.success("分页查询邮件接收人成功", pageDomain);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("分页查询邮件接收人异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("分页查询邮件接收人失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<Boolean> deleteRecipientsByTaskId(String taskId) {
|
||||||
|
ResultDomain<Boolean> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
int count = emailRecipientMapper.deleteRecipientsByTaskId(taskId);
|
||||||
|
resultDomain.success("删除任务的所有接收人成功,共" + count + "条", true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("删除任务的所有接收人异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("删除任务的所有接收人失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,187 @@
|
|||||||
|
package org.xyzh.crontab.service.impl;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.xyzh.api.crontab.TaskMetaService;
|
||||||
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
|
import org.xyzh.common.core.page.PageDomain;
|
||||||
|
import org.xyzh.common.core.page.PageParam;
|
||||||
|
import org.xyzh.common.core.page.PageRequest;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabTaskMeta;
|
||||||
|
import org.xyzh.common.utils.IDUtils;
|
||||||
|
import org.xyzh.crontab.mapper.TaskMetaMapper;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 定时任务元数据服务实现类
|
||||||
|
* @filename TaskMetaServiceImpl.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class TaskMetaServiceImpl implements TaskMetaService {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(TaskMetaServiceImpl.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TaskMetaMapper taskMetaMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> createTaskMeta(TbCrontabTaskMeta taskMeta) {
|
||||||
|
ResultDomain<TbCrontabTaskMeta> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
// 检查meta_id是否已存在
|
||||||
|
TbCrontabTaskMeta existing = taskMetaMapper.selectTaskMetaById(taskMeta.getMetaId());
|
||||||
|
if (existing != null) {
|
||||||
|
resultDomain.fail("任务元数据ID已存在: " + taskMeta.getMetaId());
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成ID
|
||||||
|
taskMeta.setID(IDUtils.generateID());
|
||||||
|
taskMeta.setCreateTime(new Date());
|
||||||
|
taskMeta.setDeleted(false);
|
||||||
|
|
||||||
|
// 默认值
|
||||||
|
if (taskMeta.getSortOrder() == null) {
|
||||||
|
taskMeta.setSortOrder(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = taskMetaMapper.insertTaskMeta(taskMeta);
|
||||||
|
if (count > 0) {
|
||||||
|
resultDomain.success("创建任务元数据成功", taskMeta);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("创建任务元数据失败");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("创建任务元数据异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("创建任务元数据失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> updateTaskMeta(TbCrontabTaskMeta taskMeta) {
|
||||||
|
ResultDomain<TbCrontabTaskMeta> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
taskMeta.setUpdateTime(new Date());
|
||||||
|
int count = taskMetaMapper.updateTaskMeta(taskMeta);
|
||||||
|
if (count > 0) {
|
||||||
|
resultDomain.success("更新任务元数据成功", taskMeta);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("更新任务元数据失败");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("更新任务元数据异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("更新任务元数据失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ResultDomain<Boolean> deleteTaskMeta(String metaId) {
|
||||||
|
ResultDomain<Boolean> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
int count = taskMetaMapper.deleteTaskMeta(metaId);
|
||||||
|
if (count > 0) {
|
||||||
|
resultDomain.success("删除任务元数据成功", true);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("删除任务元数据失败");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("删除任务元数据异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("删除任务元数据失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> getTaskMetaById(String metaId) {
|
||||||
|
ResultDomain<TbCrontabTaskMeta> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
TbCrontabTaskMeta taskMeta = taskMetaMapper.selectTaskMetaById(metaId);
|
||||||
|
if (taskMeta != null) {
|
||||||
|
resultDomain.success("查询任务元数据成功", taskMeta);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("任务元数据不存在");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("查询任务元数据异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("查询任务元数据失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> getTaskMetaByTaskId(String taskId) {
|
||||||
|
ResultDomain<TbCrontabTaskMeta> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
TbCrontabTaskMeta taskMeta = taskMetaMapper.selectTaskMetaByTaskId(taskId);
|
||||||
|
if (taskMeta != null) {
|
||||||
|
resultDomain.success("查询任务元数据成功", taskMeta);
|
||||||
|
} else {
|
||||||
|
resultDomain.fail("任务元数据不存在");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("查询任务元数据异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("查询任务元数据失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> getAllTaskMeta() {
|
||||||
|
ResultDomain<TbCrontabTaskMeta> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
List<TbCrontabTaskMeta> list = taskMetaMapper.selectAllTaskMeta();
|
||||||
|
resultDomain.success("查询所有任务元数据成功", list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("查询所有任务元数据异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("查询所有任务元数据失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> getTaskMetaByCategory(String category) {
|
||||||
|
ResultDomain<TbCrontabTaskMeta> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
List<TbCrontabTaskMeta> list = taskMetaMapper.selectTaskMetaByCategory(category);
|
||||||
|
resultDomain.success("查询分类任务元数据成功", list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("查询分类任务元数据异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("查询分类任务元数据失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultDomain<TbCrontabTaskMeta> getTaskMetaPage(PageRequest<TbCrontabTaskMeta> request) {
|
||||||
|
ResultDomain<TbCrontabTaskMeta> resultDomain = new ResultDomain<>();
|
||||||
|
try {
|
||||||
|
PageParam pageParam = request.getPageParam();
|
||||||
|
List<TbCrontabTaskMeta> list = taskMetaMapper.selectTaskMetaPage(request.getFilter(), pageParam);
|
||||||
|
int total = taskMetaMapper.countSelectTaskMeta(request.getFilter());
|
||||||
|
|
||||||
|
PageDomain<TbCrontabTaskMeta> pageDomain = new PageDomain<>();
|
||||||
|
pageDomain.setPageParam(pageParam);
|
||||||
|
pageParam.setTotalElements(total);
|
||||||
|
pageDomain.setDataList(list);
|
||||||
|
|
||||||
|
resultDomain.success("分页查询任务元数据成功", pageDomain);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("分页查询任务元数据异常: {}", e.getMessage(), e);
|
||||||
|
resultDomain.fail("分页查询任务元数据失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return resultDomain;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
package org.xyzh.crontab.task;
|
package org.xyzh.crontab.task;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.xyzh.crontab.config.CrawlerProperties;
|
import org.xyzh.api.system.config.SysConfigService;
|
||||||
import org.xyzh.crontab.pojo.TaskParams;
|
import org.xyzh.crontab.pojo.TaskParams;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Python命令任务抽象类
|
* @description Python命令任务抽象类(从数据库获取配置)
|
||||||
* @filename PythonCommandTask.java
|
* @filename PythonCommandTask.java
|
||||||
* @author yslg
|
* @author yslg
|
||||||
* @copyright xyzh
|
* @copyright xyzh
|
||||||
@@ -17,23 +17,36 @@ import java.util.List;
|
|||||||
public abstract class PythonCommandTask extends CommandTask {
|
public abstract class PythonCommandTask extends CommandTask {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
protected CrawlerProperties crawlerProperties;
|
protected SysConfigService sysConfigService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取Python可执行文件路径
|
* 获取Python可执行文件路径(从数据库系统配置获取)
|
||||||
*/
|
*/
|
||||||
protected String getPythonPath() {
|
protected String getPythonPath() {
|
||||||
return crawlerProperties.getPythonPath() != null
|
try {
|
||||||
? crawlerProperties.getPythonPath()
|
String value = sysConfigService.getStringConfig("crawler.pythonPath");
|
||||||
: "python";
|
if (value != null && !value.isEmpty()) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("获取Python路径配置失败,使用默认值: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
return "python"; // 默认值
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取脚本基础路径
|
* 获取脚本基础路径(从数据库系统配置获取)
|
||||||
*/
|
*/
|
||||||
protected String getScriptBasePath() {
|
protected String getScriptBasePath() {
|
||||||
return crawlerProperties.getBasePath() != null
|
try {
|
||||||
? crawlerProperties.getBasePath()
|
String value = sysConfigService.getStringConfig("crawler.basePath");
|
||||||
: "../schoolNewsCrawler";
|
if (value != null && !value.isEmpty()) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("获取脚本基础路径配置失败,使用默认值: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
return "../schoolNewsCrawler"; // 默认值
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,11 +4,19 @@ import com.alibaba.fastjson2.JSON;
|
|||||||
import com.alibaba.fastjson2.TypeReference;
|
import com.alibaba.fastjson2.TypeReference;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.xyzh.api.crontab.CrontabService;
|
||||||
import org.xyzh.api.crontab.DataCollectionItemService;
|
import org.xyzh.api.crontab.DataCollectionItemService;
|
||||||
|
import org.xyzh.api.crontab.EmailDefaultService;
|
||||||
|
import org.xyzh.api.crontab.EmailRecipientService;
|
||||||
|
import org.xyzh.api.crontab.TaskMetaService;
|
||||||
import org.xyzh.common.core.domain.ResultDomain;
|
import org.xyzh.common.core.domain.ResultDomain;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabEmailDefault;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabEmailRecipient;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabTask;
|
||||||
|
import org.xyzh.common.dto.crontab.TbCrontabTaskMeta;
|
||||||
import org.xyzh.common.dto.crontab.TbDataCollectionItem;
|
import org.xyzh.common.dto.crontab.TbDataCollectionItem;
|
||||||
|
import org.xyzh.common.utils.EmailUtils;
|
||||||
import org.xyzh.common.utils.IDUtils;
|
import org.xyzh.common.utils.IDUtils;
|
||||||
import org.xyzh.crontab.config.CrontabProperties;
|
|
||||||
import org.xyzh.crontab.pojo.TaskParams;
|
import org.xyzh.crontab.pojo.TaskParams;
|
||||||
import org.xyzh.crontab.task.PythonCommandTask;
|
import org.xyzh.crontab.task.PythonCommandTask;
|
||||||
|
|
||||||
@@ -18,9 +26,9 @@ import java.nio.file.Paths;
|
|||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 新闻爬虫定时任务
|
* @description 新闻爬虫定时任务
|
||||||
@@ -33,10 +41,22 @@ import java.util.Map;
|
|||||||
public class NewsCrawlerTask extends PythonCommandTask {
|
public class NewsCrawlerTask extends PythonCommandTask {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private CrontabProperties crontabProperties;
|
private DataCollectionItemService itemService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DataCollectionItemService itemService;
|
private TaskMetaService taskMetaService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CrontabService crontabService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EmailDefaultService emailDefaultService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EmailRecipientService emailRecipientService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EmailUtils emailUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建Python脚本参数
|
* 构建Python脚本参数
|
||||||
@@ -45,12 +65,24 @@ public class NewsCrawlerTask extends PythonCommandTask {
|
|||||||
protected List<String> buildPythonArgs(TaskParams taskParams) throws Exception {
|
protected List<String> buildPythonArgs(TaskParams taskParams) throws Exception {
|
||||||
List<String> args = new ArrayList<>();
|
List<String> args = new ArrayList<>();
|
||||||
|
|
||||||
// 1. 从params获取scriptPath
|
// 1. 从数据库读取scriptPath(通过metaId)
|
||||||
String scriptPath = taskParams.getParamAsString("scriptPath");
|
String metaId = taskParams.getParamAsString("metaId");
|
||||||
if (scriptPath == null || scriptPath.isEmpty()) {
|
if (metaId == null || metaId.isEmpty()) {
|
||||||
throw new Exception("scriptPath参数缺失");
|
throw new Exception("metaId参数缺失,无法获取scriptPath");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResultDomain<TbCrontabTaskMeta> metaResult = taskMetaService.getTaskMetaById(metaId);
|
||||||
|
if (!metaResult.isSuccess() || metaResult.getData() == null) {
|
||||||
|
throw new Exception("未找到任务元数据: metaId=" + metaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
String scriptPath = metaResult.getData().getScriptPath();
|
||||||
|
if (scriptPath == null || scriptPath.isEmpty()) {
|
||||||
|
throw new Exception("任务元数据中scriptPath为空: metaId=" + metaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("从数据库读取scriptPath: {}, metaId: {}", scriptPath, metaId);
|
||||||
|
|
||||||
// 2. 生成输出文件名
|
// 2. 生成输出文件名
|
||||||
String timestamp = String.valueOf(System.currentTimeMillis());
|
String timestamp = String.valueOf(System.currentTimeMillis());
|
||||||
String outputFile = String.format("output/news_%s.json", timestamp);
|
String outputFile = String.format("output/news_%s.json", timestamp);
|
||||||
@@ -70,7 +102,7 @@ public class NewsCrawlerTask extends PythonCommandTask {
|
|||||||
Object value = entry.getValue();
|
Object value = entry.getValue();
|
||||||
|
|
||||||
// 跳过特殊参数
|
// 跳过特殊参数
|
||||||
if (key.startsWith("_") || key.equals("scriptPath") ||
|
if (key.startsWith("_") || key.equals("metaId") ||
|
||||||
key.equals("taskId") || key.equals("logId")) {
|
key.equals("taskId") || key.equals("logId")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -130,7 +162,12 @@ public class NewsCrawlerTask extends PythonCommandTask {
|
|||||||
|
|
||||||
// 保存新闻数据到数据库
|
// 保存新闻数据到数据库
|
||||||
if (taskId != null && !taskId.isEmpty() && logId != null && !logId.isEmpty()) {
|
if (taskId != null && !taskId.isEmpty() && logId != null && !logId.isEmpty()) {
|
||||||
saveNewsToDatabase(newsList, taskId, logId);
|
ResultDomain<TbCrontabTask> taskResult = crontabService.getTaskById(taskId);
|
||||||
|
|
||||||
|
saveNewsToDatabase(newsList, taskResult.getData(), logId);
|
||||||
|
|
||||||
|
// 发送邮件通知
|
||||||
|
sendEmailNotification(taskId, taskResult.getData(), newsList);
|
||||||
} else {
|
} else {
|
||||||
logger.warn("未提供任务ID或日志ID,跳过数据保存");
|
logger.warn("未提供任务ID或日志ID,跳过数据保存");
|
||||||
}
|
}
|
||||||
@@ -139,14 +176,20 @@ public class NewsCrawlerTask extends PythonCommandTask {
|
|||||||
/**
|
/**
|
||||||
* 将新闻数据保存到数据库
|
* 将新闻数据保存到数据库
|
||||||
*/
|
*/
|
||||||
private void saveNewsToDatabase(List<ArticleStruct> newsList, String taskId, String logId) {
|
private void saveNewsToDatabase(List<ArticleStruct> newsList, TbCrontabTask task, String logId) {
|
||||||
|
String taskId = task.getTaskId();
|
||||||
logger.info("开始保存 {} 条新闻到数据库,任务ID: {},日志ID: {}", newsList.size(), taskId, logId);
|
logger.info("开始保存 {} 条新闻到数据库,任务ID: {},日志ID: {}", newsList.size(), taskId, logId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<TbDataCollectionItem> itemList = new ArrayList<>();
|
List<TbDataCollectionItem> itemList = new ArrayList<>();
|
||||||
|
ResultDomain<TbCrontabTaskMeta> metaResult = taskMetaService.getTaskMetaByTaskId(taskId);
|
||||||
|
if (!metaResult.isSuccess() || metaResult.getData() == null) {
|
||||||
|
throw new Exception("未找到任务元数据: taskId=" + taskId);
|
||||||
|
}
|
||||||
|
TbCrontabTaskMeta taskMeta = metaResult.getData();
|
||||||
|
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
SimpleDateFormat parser = new SimpleDateFormat("yyyy年MM月dd日HH:mm");
|
SimpleDateFormat parser = new SimpleDateFormat("yyyy年MM月dd日HH:mm");
|
||||||
|
|
||||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
for (ArticleStruct news : newsList) {
|
for (ArticleStruct news : newsList) {
|
||||||
@@ -209,9 +252,155 @@ public class NewsCrawlerTask extends PythonCommandTask {
|
|||||||
} else {
|
} else {
|
||||||
logger.warn("没有有效的新闻数据需要保存");
|
logger.warn("没有有效的新闻数据需要保存");
|
||||||
}
|
}
|
||||||
|
if (taskMeta.getAutoPublish()){
|
||||||
|
publishNewsToArticle(newsList, task, logId);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("保存新闻数据到数据库异常: ", e);
|
logger.error("保存新闻数据到数据库异常: ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送邮件通知
|
||||||
|
*/
|
||||||
|
private void sendEmailNotification(String taskId, TbCrontabTask task, List<ArticleStruct> newsList) {
|
||||||
|
try {
|
||||||
|
List<String> recipients = new ArrayList<>();
|
||||||
|
|
||||||
|
// 2. 如果使用默认接收人,查询默认接收人列表
|
||||||
|
if (Boolean.TRUE.equals(task.getDefaultRecipient()) && task.getMetaId() != null) {
|
||||||
|
ResultDomain<TbCrontabEmailDefault> defaultResult = emailDefaultService.getDefaultByMetaId(task.getMetaId());
|
||||||
|
if (defaultResult.isSuccess() && defaultResult.getDataList() != null) {
|
||||||
|
for (TbCrontabEmailDefault defaultRecipient : defaultResult.getDataList()) {
|
||||||
|
if (defaultRecipient.getUserEmail() != null && !defaultRecipient.getUserEmail().isEmpty()) {
|
||||||
|
recipients.add(defaultRecipient.getUserEmail());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 查询额外接收人
|
||||||
|
ResultDomain<TbCrontabEmailRecipient> recipientResult = emailRecipientService.getRecipientsByTaskId(taskId);
|
||||||
|
if (recipientResult.isSuccess() && recipientResult.getDataList() != null) {
|
||||||
|
for (TbCrontabEmailRecipient recipient : recipientResult.getDataList()) {
|
||||||
|
if (recipient.getEmail() != null && !recipient.getEmail().isEmpty()) {
|
||||||
|
recipients.add(recipient.getEmail());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 去重
|
||||||
|
recipients = recipients.stream().distinct().collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (recipients.isEmpty()) {
|
||||||
|
logger.info("任务 {} 没有配置接收人,跳过邮件发送", task.getTaskName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 构建邮件内容
|
||||||
|
String subject = "【新闻爬虫通知】" + task.getTaskName() + " 执行完成";
|
||||||
|
String content = buildEmailContent(task.getTaskName(), newsList);
|
||||||
|
|
||||||
|
// 6. 发送邮件
|
||||||
|
int successCount = 0;
|
||||||
|
for (String email : recipients) {
|
||||||
|
if (emailUtils.sendHtmlEmail(email, subject, content)) {
|
||||||
|
successCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("邮件发送完成,成功发送: {}/{},任务: {}", successCount, recipients.size(), task.getTaskName());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("发送邮件通知异常,但不影响任务执行: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建邮件HTML内容
|
||||||
|
*/
|
||||||
|
private String buildEmailContent(String taskName, List<ArticleStruct> newsList) {
|
||||||
|
StringBuilder html = new StringBuilder();
|
||||||
|
html.append("<!DOCTYPE html>")
|
||||||
|
.append("<html>")
|
||||||
|
.append("<head>")
|
||||||
|
.append("<meta charset='UTF-8'>")
|
||||||
|
.append("<style>")
|
||||||
|
.append("body { font-family: 'Microsoft YaHei', Arial, sans-serif; background-color: #f5f5f5; margin: 0; padding: 20px; }")
|
||||||
|
.append(".container { max-width: 800px; margin: 0 auto; background-color: #ffffff; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); overflow: hidden; }")
|
||||||
|
.append(".header { background: linear-gradient(135deg, #C62828 0%, #E53935 100%); padding: 30px; text-align: center; color: #ffffff; }")
|
||||||
|
.append(".header h1 { margin: 0; font-size: 24px; }")
|
||||||
|
.append(".content { padding: 30px; }")
|
||||||
|
.append(".summary { background-color: #f8f9fa; border-left: 4px solid #C62828; padding: 15px; margin: 20px 0; }")
|
||||||
|
.append(".news-list { margin-top: 20px; }")
|
||||||
|
.append(".news-item { border-bottom: 1px solid #e0e0e0; padding: 15px 0; }")
|
||||||
|
.append(".news-item:last-child { border-bottom: none; }")
|
||||||
|
.append(".news-title { font-size: 16px; font-weight: bold; color: #333; margin-bottom: 8px; }")
|
||||||
|
.append(".news-meta { font-size: 14px; color: #666; }")
|
||||||
|
.append(".news-link { color: #C62828; text-decoration: none; }")
|
||||||
|
.append(".footer { background-color: #f8f9fa; padding: 20px; text-align: center; color: #999; font-size: 12px; }")
|
||||||
|
.append("</style>")
|
||||||
|
.append("</head>")
|
||||||
|
.append("<body>")
|
||||||
|
.append("<div class='container'>")
|
||||||
|
.append("<div class='header'>")
|
||||||
|
.append("<h1>新闻爬虫执行通知</h1>")
|
||||||
|
.append("</div>")
|
||||||
|
.append("<div class='content'>");
|
||||||
|
|
||||||
|
// 摘要信息
|
||||||
|
html.append("<div class='summary'>")
|
||||||
|
.append("<p><strong>任务名称:</strong>").append(taskName).append("</p>")
|
||||||
|
.append("<p><strong>执行时间:</strong>").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).append("</p>")
|
||||||
|
.append("<p><strong>爬取数量:</strong>").append(newsList.size()).append(" 条</p>")
|
||||||
|
.append("</div>");
|
||||||
|
|
||||||
|
// 新闻列表
|
||||||
|
html.append("<div class='news-list'>")
|
||||||
|
.append("<h3>爬取内容:</h3>");
|
||||||
|
|
||||||
|
int count = Math.min(newsList.size(), 10); // 最多显示10条
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
ArticleStruct news = newsList.get(i);
|
||||||
|
html.append("<div class='news-item'>")
|
||||||
|
.append("<div class='news-title'>").append(news.getTitle() != null ? news.getTitle() : "无标题").append("</div>")
|
||||||
|
.append("<div class='news-meta'>")
|
||||||
|
.append("来源:").append(news.getSource() != null ? news.getSource() : "未知")
|
||||||
|
.append(" | ")
|
||||||
|
.append("发布时间:").append(news.getPublishTime() != null ? news.getPublishTime() : "未知");
|
||||||
|
|
||||||
|
if (news.getUrl() != null && !news.getUrl().isEmpty()) {
|
||||||
|
html.append(" | <a href='").append(news.getUrl()).append("' class='news-link' target='_blank'>查看原文</a>");
|
||||||
|
}
|
||||||
|
|
||||||
|
html.append("</div>")
|
||||||
|
.append("</div>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newsList.size() > 10) {
|
||||||
|
html.append("<p style='text-align: center; color: #666; margin-top: 15px;'>")
|
||||||
|
.append("还有 ").append(newsList.size() - 10).append(" 条新闻未显示,请登录系统查看详情")
|
||||||
|
.append("</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
html.append("</div>"); // news-list
|
||||||
|
html.append("</div>"); // content
|
||||||
|
|
||||||
|
// 页脚
|
||||||
|
html.append("<div class='footer'>")
|
||||||
|
.append("<p>此邮件由系统自动发送,请勿回复</p>")
|
||||||
|
.append("<p>Copyright © 红色思政智能体平台</p>")
|
||||||
|
.append("</div>")
|
||||||
|
.append("</div>") // container
|
||||||
|
.append("</body>")
|
||||||
|
.append("</html>");
|
||||||
|
|
||||||
|
return html.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO 自动发布功能,把采集的数据发布到文章表
|
||||||
|
private void publishNewsToArticle(List<ArticleStruct> newsList, TbCrontabTask task, String logId) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,5 +47,3 @@ crontab:
|
|||||||
description: 是否是昨天
|
description: 是否是昨天
|
||||||
type: Boolean
|
type: Boolean
|
||||||
value: true
|
value: true
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
<result column="bean_name" property="beanName" />
|
<result column="bean_name" property="beanName" />
|
||||||
<result column="method_name" property="methodName" />
|
<result column="method_name" property="methodName" />
|
||||||
<result column="method_params" property="methodParams" />
|
<result column="method_params" property="methodParams" />
|
||||||
|
<result column="meta_id" property="metaId" />
|
||||||
|
<result column="default_recipient" property="defaultRecipient" />
|
||||||
<result column="cron_expression" property="cronExpression" />
|
<result column="cron_expression" property="cronExpression" />
|
||||||
<result column="status" property="status" />
|
<result column="status" property="status" />
|
||||||
<result column="description" property="description" />
|
<result column="description" property="description" />
|
||||||
@@ -26,7 +28,7 @@
|
|||||||
|
|
||||||
<!-- 字段列表 -->
|
<!-- 字段列表 -->
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
id, task_id, task_name, task_group, bean_name, method_name, method_params,
|
id, task_id, task_name, task_group, bean_name, method_name, method_params, meta_id, default_recipient,
|
||||||
cron_expression, status, description, concurrent, misfire_policy,
|
cron_expression, status, description, concurrent, misfire_policy,
|
||||||
creator, updater, create_time, update_time, delete_time, deleted
|
creator, updater, create_time, update_time, delete_time, deleted
|
||||||
</sql>
|
</sql>
|
||||||
@@ -132,6 +134,8 @@
|
|||||||
<if test="task.beanName != null">bean_name,</if>
|
<if test="task.beanName != null">bean_name,</if>
|
||||||
<if test="task.methodName != null">method_name,</if>
|
<if test="task.methodName != null">method_name,</if>
|
||||||
<if test="task.methodParams != null">method_params,</if>
|
<if test="task.methodParams != null">method_params,</if>
|
||||||
|
<if test="task.metaId != null">meta_id,</if>
|
||||||
|
<if test="task.defaultRecipient != null">default_recipient,</if>
|
||||||
<if test="task.cronExpression != null">cron_expression,</if>
|
<if test="task.cronExpression != null">cron_expression,</if>
|
||||||
<if test="task.status != null">status,</if>
|
<if test="task.status != null">status,</if>
|
||||||
<if test="task.description != null">description,</if>
|
<if test="task.description != null">description,</if>
|
||||||
@@ -150,6 +154,8 @@
|
|||||||
<if test="task.beanName != null">#{task.beanName},</if>
|
<if test="task.beanName != null">#{task.beanName},</if>
|
||||||
<if test="task.methodName != null">#{task.methodName},</if>
|
<if test="task.methodName != null">#{task.methodName},</if>
|
||||||
<if test="task.methodParams != null">#{task.methodParams},</if>
|
<if test="task.methodParams != null">#{task.methodParams},</if>
|
||||||
|
<if test="task.metaId != null">#{task.metaId},</if>
|
||||||
|
<if test="task.defaultRecipient != null">#{task.defaultRecipient},</if>
|
||||||
<if test="task.cronExpression != null">#{task.cronExpression},</if>
|
<if test="task.cronExpression != null">#{task.cronExpression},</if>
|
||||||
<if test="task.status != null">#{task.status},</if>
|
<if test="task.status != null">#{task.status},</if>
|
||||||
<if test="task.description != null">#{task.description},</if>
|
<if test="task.description != null">#{task.description},</if>
|
||||||
@@ -170,6 +176,8 @@
|
|||||||
<if test="task.beanName != null">bean_name = #{task.beanName},</if>
|
<if test="task.beanName != null">bean_name = #{task.beanName},</if>
|
||||||
<if test="task.methodName != null">method_name = #{task.methodName},</if>
|
<if test="task.methodName != null">method_name = #{task.methodName},</if>
|
||||||
<if test="task.methodParams != null">method_params = #{task.methodParams},</if>
|
<if test="task.methodParams != null">method_params = #{task.methodParams},</if>
|
||||||
|
<if test="task.metaId != null">meta_id = #{task.metaId},</if>
|
||||||
|
<if test="task.defaultRecipient != null">default_recipient = #{task.defaultRecipient},</if>
|
||||||
<if test="task.cronExpression != null">cron_expression = #{task.cronExpression},</if>
|
<if test="task.cronExpression != null">cron_expression = #{task.cronExpression},</if>
|
||||||
<if test="task.status != null">status = #{task.status},</if>
|
<if test="task.status != null">status = #{task.status},</if>
|
||||||
<if test="task.description != null">description = #{task.description},</if>
|
<if test="task.description != null">description = #{task.description},</if>
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="org.xyzh.crontab.mapper.EmailDefaultMapper">
|
||||||
|
|
||||||
|
<!-- 结果映射 -->
|
||||||
|
<resultMap id="BaseResultMap" type="org.xyzh.common.dto.crontab.TbCrontabEmailDefault">
|
||||||
|
<id column="id" property="ID" />
|
||||||
|
<result column="default_id" property="defaultId" />
|
||||||
|
<result column="meta_id" property="metaId" />
|
||||||
|
<result column="user_id" property="userId" />
|
||||||
|
<result column="user_email" property="userEmail" />
|
||||||
|
<result column="username" property="username" />
|
||||||
|
<result column="creator" property="creator" />
|
||||||
|
<result column="updater" property="updater" />
|
||||||
|
<result column="create_time" property="createTime" />
|
||||||
|
<result column="update_time" property="updateTime" />
|
||||||
|
<result column="delete_time" property="deleteTime" />
|
||||||
|
<result column="deleted" property="deleted" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<!-- 字段列表 -->
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id, default_id, meta_id, user_id,
|
||||||
|
creator, updater, create_time, update_time, delete_time, deleted
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<!-- 插入默认接收人 -->
|
||||||
|
<insert id="insertDefault" parameterType="org.xyzh.common.dto.crontab.TbCrontabEmailDefault">
|
||||||
|
INSERT INTO tb_crontab_email_default (
|
||||||
|
id, default_id, meta_id, user_id, creator, create_time
|
||||||
|
) VALUES (
|
||||||
|
#{emailDefault.ID}, #{emailDefault.defaultId}, #{emailDefault.metaId},
|
||||||
|
#{emailDefault.userId}, #{emailDefault.creator}, NOW()
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<!-- 更新默认接收人 -->
|
||||||
|
<update id="updateDefault" parameterType="org.xyzh.common.dto.crontab.TbCrontabEmailDefault">
|
||||||
|
UPDATE tb_crontab_email_default
|
||||||
|
SET meta_id = #{emailDefault.metaId},
|
||||||
|
user_id = #{emailDefault.userId},
|
||||||
|
updater = #{emailDefault.updater},
|
||||||
|
update_time = NOW()
|
||||||
|
WHERE default_id = #{emailDefault.defaultId}
|
||||||
|
AND deleted = 0
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 删除默认接收人(逻辑删除) -->
|
||||||
|
<update id="deleteDefault">
|
||||||
|
UPDATE tb_crontab_email_default
|
||||||
|
SET deleted = 1,
|
||||||
|
delete_time = NOW()
|
||||||
|
WHERE default_id = #{defaultId}
|
||||||
|
AND deleted = 0
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 根据defaultId查询 -->
|
||||||
|
<select id="selectDefaultById" resultMap="BaseResultMap">
|
||||||
|
SELECT tced.id, tced.default_id, tced.meta_id, tced.user_id, tu.email as user_email, tu.username
|
||||||
|
FROM tb_crontab_email_default tced
|
||||||
|
LEFT JOIN tb_sys_user tu ON tced.user_id = tu.id
|
||||||
|
WHERE tced.default_id = #{defaultId}
|
||||||
|
AND tced.deleted = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 根据metaId查询 -->
|
||||||
|
<select id="selectDefaultByMetaId" resultMap="BaseResultMap">
|
||||||
|
SELECT tced.id, tced.default_id, tced.meta_id, tced.user_id, tu.email as user_email, tu.username
|
||||||
|
FROM tb_crontab_email_default tced
|
||||||
|
LEFT JOIN tb_sys_user tu ON tced.user_id = tu.id
|
||||||
|
WHERE tced.meta_id = #{metaId}
|
||||||
|
AND tced.deleted = 0
|
||||||
|
LIMIT 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="org.xyzh.crontab.mapper.EmailRecipientMapper">
|
||||||
|
|
||||||
|
<!-- 结果映射 -->
|
||||||
|
<resultMap id="BaseResultMap" type="org.xyzh.common.dto.crontab.TbCrontabEmailRecipient">
|
||||||
|
<id column="id" property="ID" />
|
||||||
|
<result column="recipient_id" property="recipientId" />
|
||||||
|
<result column="task_id" property="taskId" />
|
||||||
|
<result column="user_id" property="userId" />
|
||||||
|
<result column="email" property="email" />
|
||||||
|
<result column="name" property="name" />
|
||||||
|
<result column="creator" property="creator" />
|
||||||
|
<result column="updater" property="updater" />
|
||||||
|
<result column="create_time" property="createTime" />
|
||||||
|
<result column="update_time" property="updateTime" />
|
||||||
|
<result column="delete_time" property="deleteTime" />
|
||||||
|
<result column="deleted" property="deleted" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<!-- 字段列表 -->
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id, recipient_id, task_id, user_id, email, name,
|
||||||
|
creator, updater, create_time, update_time, delete_time, deleted
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<!-- 查询条件 -->
|
||||||
|
<sql id="Base_Where_Clause">
|
||||||
|
<where>
|
||||||
|
deleted = 0
|
||||||
|
<if test="filter.recipientId != null and filter.recipientId != ''">
|
||||||
|
AND recipient_id = #{filter.recipientId}
|
||||||
|
</if>
|
||||||
|
<if test="filter.taskId != null and filter.taskId != ''">
|
||||||
|
AND task_id = #{filter.taskId}
|
||||||
|
</if>
|
||||||
|
<if test="filter.userId != null and filter.userId != ''">
|
||||||
|
AND user_id = #{filter.userId}
|
||||||
|
</if>
|
||||||
|
<if test="filter.email != null and filter.email != ''">
|
||||||
|
AND email LIKE CONCAT('%', #{filter.email}, '%')
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<!-- 插入邮件接收人 -->
|
||||||
|
<insert id="insertRecipient" parameterType="org.xyzh.common.dto.crontab.TbCrontabEmailRecipient">
|
||||||
|
INSERT INTO tb_crontab_email_recipient (
|
||||||
|
id, recipient_id, task_id, user_id, email, name, creator, create_time
|
||||||
|
) VALUES (
|
||||||
|
#{recipient.ID}, #{recipient.recipientId}, #{recipient.taskId},
|
||||||
|
#{recipient.userId}, #{recipient.email}, #{recipient.name},
|
||||||
|
#{recipient.creator}, NOW()
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<!-- 批量插入邮件接收人 -->
|
||||||
|
<insert id="batchInsertRecipient">
|
||||||
|
INSERT INTO tb_crontab_email_recipient (
|
||||||
|
id, recipient_id, task_id, user_id, email, name, creator, create_time
|
||||||
|
) VALUES
|
||||||
|
<foreach collection="recipients" item="item" separator=",">
|
||||||
|
(#{item.ID}, #{item.recipientId}, #{item.taskId},
|
||||||
|
#{item.userId}, #{item.email}, #{item.name}, #{item.creator}, NOW())
|
||||||
|
</foreach>
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<!-- 更新邮件接收人 -->
|
||||||
|
<update id="updateRecipient" parameterType="org.xyzh.common.dto.crontab.TbCrontabEmailRecipient">
|
||||||
|
UPDATE tb_crontab_email_recipient
|
||||||
|
SET task_id = #{recipient.taskId},
|
||||||
|
user_id = #{recipient.userId},
|
||||||
|
email = #{recipient.email},
|
||||||
|
name = #{recipient.name},
|
||||||
|
updater = #{recipient.updater},
|
||||||
|
update_time = NOW()
|
||||||
|
WHERE recipient_id = #{recipient.recipientId}
|
||||||
|
AND deleted = 0
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 删除邮件接收人(逻辑删除) -->
|
||||||
|
<update id="deleteRecipient">
|
||||||
|
UPDATE tb_crontab_email_recipient
|
||||||
|
SET deleted = 1,
|
||||||
|
delete_time = NOW()
|
||||||
|
WHERE recipient_id = #{recipientId}
|
||||||
|
AND deleted = 0
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 根据ID查询 -->
|
||||||
|
<select id="selectRecipientById" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_crontab_email_recipient
|
||||||
|
WHERE recipient_id = #{recipientId}
|
||||||
|
AND deleted = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 根据任务ID查询接收人列表 -->
|
||||||
|
<select id="selectRecipientsByTaskId" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_crontab_email_recipient
|
||||||
|
WHERE task_id = #{taskId}
|
||||||
|
AND deleted = 0
|
||||||
|
ORDER BY create_time ASC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 查询所有接收人 -->
|
||||||
|
<select id="selectAllRecipients" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_crontab_email_recipient
|
||||||
|
WHERE deleted = 0
|
||||||
|
ORDER BY create_time ASC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 分页查询 -->
|
||||||
|
<select id="selectRecipientPage" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_crontab_email_recipient
|
||||||
|
<include refid="Base_Where_Clause" />
|
||||||
|
ORDER BY create_time DESC
|
||||||
|
LIMIT #{pageParam.offset}, #{pageParam.pageSize}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 查询总数 -->
|
||||||
|
<select id="countSelectRecipient" resultType="int">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM tb_crontab_email_recipient
|
||||||
|
<include refid="Base_Where_Clause" />
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 删除任务的所有接收人 -->
|
||||||
|
<update id="deleteRecipientsByTaskId">
|
||||||
|
UPDATE tb_crontab_email_recipient
|
||||||
|
SET deleted = 1,
|
||||||
|
delete_time = NOW()
|
||||||
|
WHERE task_id = #{taskId}
|
||||||
|
AND deleted = 0
|
||||||
|
</update>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="org.xyzh.crontab.mapper.TaskMetaMapper">
|
||||||
|
|
||||||
|
<!-- 结果映射 -->
|
||||||
|
<resultMap id="BaseResultMap" type="org.xyzh.common.dto.crontab.TbCrontabTaskMeta">
|
||||||
|
<id column="id" property="ID" />
|
||||||
|
<result column="meta_id" property="metaId" />
|
||||||
|
<result column="name" property="name" />
|
||||||
|
<result column="description" property="description" />
|
||||||
|
<result column="category" property="category" />
|
||||||
|
<result column="bean_name" property="beanName" />
|
||||||
|
<result column="method_name" property="methodName" />
|
||||||
|
<result column="script_path" property="scriptPath" />
|
||||||
|
<result column="param_schema" property="paramSchema" />
|
||||||
|
<result column="auto_publish" property="autoPublish" />
|
||||||
|
<result column="sort_order" property="sortOrder" />
|
||||||
|
<result column="creator" property="creator" />
|
||||||
|
<result column="updater" property="updater" />
|
||||||
|
<result column="create_time" property="createTime" />
|
||||||
|
<result column="update_time" property="updateTime" />
|
||||||
|
<result column="delete_time" property="deleteTime" />
|
||||||
|
<result column="deleted" property="deleted" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<!-- 字段列表 -->
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id, meta_id, name, description, category, bean_name, method_name,
|
||||||
|
script_path, param_schema, auto_publish, sort_order,
|
||||||
|
creator, updater, create_time, update_time, delete_time, deleted
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<!-- 查询条件 -->
|
||||||
|
<sql id="Base_Where_Clause">
|
||||||
|
<where>
|
||||||
|
deleted = 0
|
||||||
|
<if test="filter.metaId != null and filter.metaId != ''">
|
||||||
|
AND meta_id = #{filter.metaId}
|
||||||
|
</if>
|
||||||
|
<if test="filter.name != null and filter.name != ''">
|
||||||
|
AND name LIKE CONCAT('%', #{filter.name}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="filter.category != null and filter.category != ''">
|
||||||
|
AND category = #{filter.category}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<!-- 插入任务元数据 -->
|
||||||
|
<insert id="insertTaskMeta" parameterType="org.xyzh.common.dto.crontab.TbCrontabTaskMeta">
|
||||||
|
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 (
|
||||||
|
#{taskMeta.ID}, #{taskMeta.metaId}, #{taskMeta.name}, #{taskMeta.description},
|
||||||
|
#{taskMeta.category}, #{taskMeta.beanName}, #{taskMeta.methodName},
|
||||||
|
#{taskMeta.scriptPath}, #{taskMeta.paramSchema}, #{taskMeta.autoPublish}, #{taskMeta.sortOrder},
|
||||||
|
#{taskMeta.creator}, NOW()
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<!-- 更新任务元数据 -->
|
||||||
|
<update id="updateTaskMeta" parameterType="org.xyzh.common.dto.crontab.TbCrontabTaskMeta">
|
||||||
|
UPDATE tb_crontab_task_meta
|
||||||
|
SET name = #{taskMeta.name},
|
||||||
|
description = #{taskMeta.description},
|
||||||
|
category = #{taskMeta.category},
|
||||||
|
bean_name = #{taskMeta.beanName},
|
||||||
|
method_name = #{taskMeta.methodName},
|
||||||
|
script_path = #{taskMeta.scriptPath},
|
||||||
|
param_schema = #{taskMeta.paramSchema},
|
||||||
|
auto_publish = #{taskMeta.autoPublish},
|
||||||
|
sort_order = #{taskMeta.sortOrder},
|
||||||
|
updater = #{taskMeta.updater},
|
||||||
|
update_time = NOW()
|
||||||
|
WHERE meta_id = #{taskMeta.metaId}
|
||||||
|
AND deleted = 0
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 删除任务元数据(逻辑删除) -->
|
||||||
|
<update id="deleteTaskMeta">
|
||||||
|
UPDATE tb_crontab_task_meta
|
||||||
|
SET deleted = 1,
|
||||||
|
delete_time = NOW()
|
||||||
|
WHERE meta_id = #{metaId}
|
||||||
|
AND deleted = 0
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 根据ID查询 -->
|
||||||
|
<select id="selectTaskMetaById" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_crontab_task_meta
|
||||||
|
WHERE meta_id = #{metaId}
|
||||||
|
AND deleted = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 根据TaskID查询 -->
|
||||||
|
<select id="selectTaskMetaByTaskId" resultMap="BaseResultMap">
|
||||||
|
SELECT tcte.*
|
||||||
|
FROM tb_crontab_task tct
|
||||||
|
LEFT JOIN tb_crontab_task_meta tcte ON tct.meta_id = tcte.meta_id
|
||||||
|
WHERE tct.task_id = #{taskId}
|
||||||
|
AND tcte.deleted = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 查询所有任务元数据 -->
|
||||||
|
<select id="selectAllTaskMeta" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_crontab_task_meta
|
||||||
|
WHERE deleted = 0
|
||||||
|
ORDER BY sort_order ASC, create_time DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 根据分类查询 -->
|
||||||
|
<select id="selectTaskMetaByCategory" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_crontab_task_meta
|
||||||
|
WHERE category = #{category}
|
||||||
|
AND deleted = 0
|
||||||
|
ORDER BY sort_order ASC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 分页查询 -->
|
||||||
|
<select id="selectTaskMetaPage" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_crontab_task_meta
|
||||||
|
<include refid="Base_Where_Clause" />
|
||||||
|
ORDER BY sort_order ASC, create_time DESC
|
||||||
|
LIMIT #{pageParam.offset}, #{pageParam.pageSize}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 查询总数 -->
|
||||||
|
<select id="countSelectTaskMeta" resultType="int">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM tb_crontab_task_meta
|
||||||
|
<include refid="Base_Where_Clause" />
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -2,6 +2,8 @@ package org.xyzh.system.mapper;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.xyzh.common.core.page.PageParam;
|
||||||
import org.xyzh.common.dto.system.TbSysConfig;
|
import org.xyzh.common.dto.system.TbSysConfig;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -16,12 +18,55 @@ import java.util.List;
|
|||||||
@Mapper
|
@Mapper
|
||||||
public interface SysConfigMapper extends BaseMapper<TbSysConfig> {
|
public interface SysConfigMapper extends BaseMapper<TbSysConfig> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 插入系统配置
|
||||||
|
*/
|
||||||
|
int insertSysConfig(@Param("config") TbSysConfig config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新系统配置
|
||||||
|
*/
|
||||||
|
int updateSysConfig(@Param("config") TbSysConfig config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 删除系统配置(逻辑删除)
|
||||||
|
*/
|
||||||
|
int deleteSysConfig(@Param("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据配置键查询
|
||||||
|
*/
|
||||||
|
TbSysConfig selectSysConfigByKey(@Param("configKey") String configKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据ID查询
|
||||||
|
*/
|
||||||
|
TbSysConfig selectSysConfigById(@Param("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 查询所有系统配置
|
||||||
|
*/
|
||||||
|
List<TbSysConfig> selectAllSysConfig();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据分组查询系统配置
|
||||||
|
*/
|
||||||
|
List<TbSysConfig> selectSysConfigByGroup(@Param("configGroup") String configGroup);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 查询系统配置列表
|
* @description 查询系统配置列表
|
||||||
* @param filter 过滤条件
|
* @param filter 过滤条件
|
||||||
* @return List<TbSysConfig> 系统配置列表
|
* @return List<TbSysConfig> 系统配置列表
|
||||||
* @author yslg
|
|
||||||
* @since 2025-10-15
|
|
||||||
*/
|
*/
|
||||||
List<TbSysConfig> selectSysConfigs(TbSysConfig filter);
|
List<TbSysConfig> selectSysConfigs(@Param("filter") TbSysConfig filter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 分页查询系统配置
|
||||||
|
*/
|
||||||
|
List<TbSysConfig> selectSysConfigPage(@Param("filter") TbSysConfig filter, @Param("pageParam") PageParam pageParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 查询系统配置总数
|
||||||
|
*/
|
||||||
|
int countSelectSysConfig(@Param("filter") TbSysConfig filter);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,208 @@
|
|||||||
package org.xyzh.system.service.config.impl;
|
package org.xyzh.system.service.config.impl;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.xyzh.api.system.config.SysConfigService;
|
import org.xyzh.api.system.config.SysConfigService;
|
||||||
|
import org.xyzh.common.dto.system.TbSysConfig;
|
||||||
|
import org.xyzh.system.mapper.SysConfigMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 系统配置服务实现
|
||||||
|
* @author AI Assistant
|
||||||
|
* @since 2025-11-18
|
||||||
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class SysConfigServiceImpl implements SysConfigService{
|
public class SysConfigServiceImpl implements SysConfigService {
|
||||||
|
|
||||||
@Override
|
private static final Logger logger = LoggerFactory.getLogger(SysConfigServiceImpl.class);
|
||||||
public String getSysConfig(String key) {
|
|
||||||
|
@Autowired
|
||||||
|
private SysConfigMapper sysConfigMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据key查询配置
|
||||||
|
*/
|
||||||
|
private TbSysConfig getConfigByKey(String key) {
|
||||||
|
if (key == null || key.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
return sysConfigMapper.selectSysConfigByKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getSysConfig(String key) {
|
||||||
|
try {
|
||||||
|
TbSysConfig config = getConfigByKey(key);
|
||||||
|
if (config == null) {
|
||||||
|
logger.warn("配置项不存在: {}", key);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String configType = config.getConfigType();
|
||||||
|
String configValue = config.getConfigValue();
|
||||||
|
|
||||||
|
if (configValue == null || configValue.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据config_type返回对应的类型
|
||||||
|
if (configType == null || "string".equalsIgnoreCase(configType)) {
|
||||||
|
return configValue;
|
||||||
|
} else if ("number".equalsIgnoreCase(configType) || "integer".equalsIgnoreCase(configType)) {
|
||||||
|
try {
|
||||||
|
// 尝试解析为Integer,如果失败则解析为Long
|
||||||
|
return Integer.parseInt(configValue);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
try {
|
||||||
|
return Long.parseLong(configValue);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
logger.error("配置项 {} 的值无法转换为数字: {}", key, configValue);
|
||||||
|
return configValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ("boolean".equalsIgnoreCase(configType)) {
|
||||||
|
String value = configValue.toLowerCase().trim();
|
||||||
|
if ("true".equals(value) || "1".equals(value) || "yes".equals(value) || "on".equals(value)) {
|
||||||
|
return true;
|
||||||
|
} else if ("false".equals(value) || "0".equals(value) || "no".equals(value) || "off".equals(value)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
logger.warn("配置项 {} 的值无法识别为Boolean: {}", key, value);
|
||||||
|
return configValue;
|
||||||
|
}
|
||||||
|
} else if ("double".equalsIgnoreCase(configType) || "float".equalsIgnoreCase(configType)) {
|
||||||
|
try {
|
||||||
|
return Double.parseDouble(configValue);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
logger.error("配置项 {} 的值无法转换为Double: {}", key, configValue);
|
||||||
|
return configValue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 未知类型,直接返回字符串
|
||||||
|
return configValue;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取配置失败: {}", key, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStringConfig(String key) {
|
||||||
|
try {
|
||||||
|
TbSysConfig config = getConfigByKey(key);
|
||||||
|
if (config == null) {
|
||||||
|
logger.warn("配置项不存在: {}", key);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return config.getConfigValue();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取字符串配置失败: {}", key, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getIntConfig(String key) {
|
||||||
|
try {
|
||||||
|
TbSysConfig config = getConfigByKey(key);
|
||||||
|
if (config == null) {
|
||||||
|
logger.warn("配置项不存在: {}", key);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String value = config.getConfigValue();
|
||||||
|
if (value == null || value.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
logger.error("配置项 {} 的值无法转换为Integer: {}", key, e.getMessage());
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取Integer配置失败: {}", key, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getBooleanConfig(String key) {
|
||||||
|
try {
|
||||||
|
TbSysConfig config = getConfigByKey(key);
|
||||||
|
if (config == null) {
|
||||||
|
logger.warn("配置项不存在: {}", key);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String value = config.getConfigValue();
|
||||||
|
if (value == null || value.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支持多种布尔值表示:true/false, 1/0, yes/no, on/off
|
||||||
|
value = value.toLowerCase().trim();
|
||||||
|
if ("true".equals(value) || "1".equals(value) || "yes".equals(value) || "on".equals(value)) {
|
||||||
|
return true;
|
||||||
|
} else if ("false".equals(value) || "0".equals(value) || "no".equals(value) || "off".equals(value)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
logger.warn("配置项 {} 的值无法识别为Boolean: {}", key, value);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取Boolean配置失败: {}", key, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getDoubleConfig(String key) {
|
||||||
|
try {
|
||||||
|
TbSysConfig config = getConfigByKey(key);
|
||||||
|
if (config == null) {
|
||||||
|
logger.warn("配置项不存在: {}", key);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String value = config.getConfigValue();
|
||||||
|
if (value == null || value.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Double.parseDouble(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
logger.error("配置项 {} 的值无法转换为Double: {}", key, e.getMessage());
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取Double配置失败: {}", key, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getLongConfig(String key) {
|
||||||
|
try {
|
||||||
|
TbSysConfig config = getConfigByKey(key);
|
||||||
|
if (config == null) {
|
||||||
|
logger.warn("配置项不存在: {}", key);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String value = config.getConfigValue();
|
||||||
|
if (value == null || value.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Long.parseLong(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
logger.error("配置项 {} 的值无法转换为Long: {}", key, e.getMessage());
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取Long配置失败: {}", key, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,55 +2,138 @@
|
|||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="org.xyzh.system.mapper.SysConfigMapper">
|
<mapper namespace="org.xyzh.system.mapper.SysConfigMapper">
|
||||||
|
|
||||||
<!-- 基础结果映射 -->
|
<!-- 结果映射 -->
|
||||||
<resultMap id="BaseResultMap" type="org.xyzh.common.dto.system.TbSysConfig">
|
<resultMap id="BaseResultMap" type="org.xyzh.common.dto.system.TbSysConfig">
|
||||||
<id column="id" property="id" jdbcType="VARCHAR"/>
|
<id column="id" property="ID" />
|
||||||
<result column="config_key" property="configKey" jdbcType="VARCHAR"/>
|
<result column="config_key" property="configKey" />
|
||||||
<result column="config_value" property="configValue" jdbcType="LONGVARCHAR"/>
|
<result column="config_value" property="configValue" />
|
||||||
<result column="config_type" property="configType" jdbcType="VARCHAR"/>
|
<result column="config_type" property="configType" />
|
||||||
<result column="config_group" property="configGroup" jdbcType="VARCHAR"/>
|
<result column="config_group" property="configGroup" />
|
||||||
<result column="description" property="description" jdbcType="VARCHAR"/>
|
<result column="description" property="description" />
|
||||||
<result column="is_system" property="isSystem" jdbcType="BOOLEAN"/>
|
<result column="is_system" property="isSystem" />
|
||||||
<result column="creator" property="creator" jdbcType="VARCHAR"/>
|
<result column="creator" property="creator" />
|
||||||
<result column="updater" property="updater" jdbcType="VARCHAR"/>
|
<result column="updater" property="updater" />
|
||||||
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
|
<result column="create_time" property="createTime" />
|
||||||
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
|
<result column="update_time" property="updateTime" />
|
||||||
<result column="delete_time" property="deleteTime" jdbcType="TIMESTAMP"/>
|
<result column="delete_time" property="deleteTime" />
|
||||||
<result column="deleted" property="deleted" jdbcType="BOOLEAN"/>
|
<result column="deleted" property="deleted" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<!-- 基础字段 -->
|
<!-- 字段列表 -->
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
id, config_key, config_value, config_type, config_group, description,
|
id, config_key, config_value, config_type, config_group, description,
|
||||||
is_system, creator, updater, create_time, update_time, delete_time, deleted
|
is_system, creator, updater, create_time, update_time, delete_time, deleted
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<!-- 通用条件 -->
|
<!-- 查询条件 -->
|
||||||
<sql id="Where_Clause">
|
<sql id="Base_Where_Clause">
|
||||||
<where>
|
<where>
|
||||||
deleted = 0
|
deleted = 0
|
||||||
<if test="configKey != null and configKey != ''">
|
<if test="filter.configKey != null and filter.configKey != ''">
|
||||||
AND config_key = #{configKey}
|
AND config_key = #{filter.configKey}
|
||||||
</if>
|
</if>
|
||||||
<if test="configGroup != null and configGroup != ''">
|
<if test="filter.configGroup != null and filter.configGroup != ''">
|
||||||
AND config_group = #{configGroup}
|
AND config_group = #{filter.configGroup}
|
||||||
</if>
|
</if>
|
||||||
<if test="configType != null and configType != ''">
|
<if test="filter.configType != null and filter.configType != ''">
|
||||||
AND config_type = #{configType}
|
AND config_type = #{filter.configType}
|
||||||
</if>
|
</if>
|
||||||
<if test="isSystem != null">
|
<if test="filter.isSystem != null">
|
||||||
AND is_system = #{isSystem}
|
AND is_system = #{filter.isSystem}
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<!-- selectSysConfigs -->
|
<!-- 插入系统配置 -->
|
||||||
<select id="selectSysConfigs" resultMap="BaseResultMap">
|
<insert id="insertSysConfig" parameterType="org.xyzh.common.dto.system.TbSysConfig">
|
||||||
SELECT
|
INSERT INTO tb_sys_config (
|
||||||
<include refid="Base_Column_List"/>
|
id, config_key, config_value, config_type, config_group, description,
|
||||||
|
is_system, creator, create_time
|
||||||
|
) VALUES (
|
||||||
|
#{config.ID}, #{config.configKey}, #{config.configValue}, #{config.configType},
|
||||||
|
#{config.configGroup}, #{config.description}, #{config.isSystem},
|
||||||
|
#{config.creator}, NOW()
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<!-- 更新系统配置 -->
|
||||||
|
<update id="updateSysConfig" parameterType="org.xyzh.common.dto.system.TbSysConfig">
|
||||||
|
UPDATE tb_sys_config
|
||||||
|
SET config_value = #{config.configValue},
|
||||||
|
config_type = #{config.configType},
|
||||||
|
config_group = #{config.configGroup},
|
||||||
|
description = #{config.description},
|
||||||
|
is_system = #{config.isSystem},
|
||||||
|
updater = #{config.updater},
|
||||||
|
update_time = NOW()
|
||||||
|
WHERE id = #{config.ID}
|
||||||
|
AND deleted = 0
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 删除系统配置(逻辑删除) -->
|
||||||
|
<update id="deleteSysConfig">
|
||||||
|
UPDATE tb_sys_config
|
||||||
|
SET deleted = 1,
|
||||||
|
delete_time = NOW()
|
||||||
|
WHERE id = #{id}
|
||||||
|
AND deleted = 0
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 根据配置键查询 -->
|
||||||
|
<select id="selectSysConfigByKey" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
FROM tb_sys_config
|
FROM tb_sys_config
|
||||||
<include refid="Where_Clause"/>
|
WHERE config_key = #{configKey}
|
||||||
|
AND deleted = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 根据ID查询 -->
|
||||||
|
<select id="selectSysConfigById" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_sys_config
|
||||||
|
WHERE id = #{id}
|
||||||
|
AND deleted = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 查询所有系统配置 -->
|
||||||
|
<select id="selectAllSysConfig" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_sys_config
|
||||||
|
WHERE deleted = 0
|
||||||
ORDER BY config_group, config_key
|
ORDER BY config_group, config_key
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- 根据分组查询 -->
|
||||||
|
<select id="selectSysConfigByGroup" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_sys_config
|
||||||
|
WHERE config_group = #{configGroup}
|
||||||
|
AND deleted = 0
|
||||||
|
ORDER BY config_key
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 查询系统配置列表 -->
|
||||||
|
<select id="selectSysConfigs" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_sys_config
|
||||||
|
<include refid="Base_Where_Clause" />
|
||||||
|
ORDER BY config_group, config_key
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 分页查询 -->
|
||||||
|
<select id="selectSysConfigPage" resultMap="BaseResultMap">
|
||||||
|
SELECT <include refid="Base_Column_List" />
|
||||||
|
FROM tb_sys_config
|
||||||
|
<include refid="Base_Where_Clause" />
|
||||||
|
ORDER BY config_group, config_key
|
||||||
|
LIMIT #{pageParam.offset}, #{pageParam.pageSize}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 查询总数 -->
|
||||||
|
<select id="countSelectSysConfig" resultType="int">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM tb_sys_config
|
||||||
|
<include refid="Base_Where_Clause" />
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ export const achievementApi = {
|
|||||||
/**
|
/**
|
||||||
* 删除成就
|
* 删除成就
|
||||||
* @param achievement 成就信息(包含achievementID)
|
* @param achievement 成就信息(包含achievementID)
|
||||||
* @returns Promise<ResultDomain<void>>
|
* @returns Promise<ResultDomain<Boolean>>
|
||||||
*/
|
*/
|
||||||
async deleteAchievement(achievement: Achievement): Promise<ResultDomain<void>> {
|
async deleteAchievement(achievement: Achievement): Promise<ResultDomain<Boolean>> {
|
||||||
const response = await api.delete<void>('/achievements/achievement', achievement);
|
const response = await api.delete<boolean>('/achievements/achievement', achievement);
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -138,10 +138,10 @@ export const achievementApi = {
|
|||||||
* 撤销用户成就
|
* 撤销用户成就
|
||||||
* @param userID 用户ID
|
* @param userID 用户ID
|
||||||
* @param achievementID 成就ID
|
* @param achievementID 成就ID
|
||||||
* @returns Promise<ResultDomain<void>>
|
* @returns Promise<ResultDomain<Boolean>>
|
||||||
*/
|
*/
|
||||||
async revokeAchievement(userID: string, achievementID: string): Promise<ResultDomain<void>> {
|
async revokeAchievement(userID: string, achievementID: string): Promise<ResultDomain<Boolean>> {
|
||||||
const response = await api.delete<void>('/achievements/revoke', null, {
|
const response = await api.delete<boolean>('/achievements/revoke', null, {
|
||||||
params: { userID, achievementID }
|
params: { userID, achievementID }
|
||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
|
|||||||
@@ -169,15 +169,15 @@ export const documentSegmentApi = {
|
|||||||
* @param documentId Dify文档ID
|
* @param documentId Dify文档ID
|
||||||
* @param segmentId 分段ID
|
* @param segmentId 分段ID
|
||||||
* @param childChunkId 子块ID
|
* @param childChunkId 子块ID
|
||||||
* @returns Promise<ResultDomain<void>>
|
* @returns Promise<ResultDomain<Boolean>>
|
||||||
*/
|
*/
|
||||||
async deleteChildChunk(
|
async deleteChildChunk(
|
||||||
datasetId: string,
|
datasetId: string,
|
||||||
documentId: string,
|
documentId: string,
|
||||||
segmentId: string,
|
segmentId: string,
|
||||||
childChunkId: string
|
childChunkId: string
|
||||||
): Promise<ResultDomain<void>> {
|
): Promise<ResultDomain<Boolean>> {
|
||||||
const response = await api.delete<void>(
|
const response = await api.delete<boolean>(
|
||||||
`/ai/dify/datasets/${datasetId}/documents/${documentId}/segments/${segmentId}/child_chunks/${childChunkId}`
|
`/ai/dify/datasets/${datasetId}/documents/${documentId}/segments/${segmentId}/child_chunks/${childChunkId}`
|
||||||
);
|
);
|
||||||
return response.data;
|
return response.data;
|
||||||
|
|||||||
@@ -147,15 +147,15 @@ export const fileUploadApi = {
|
|||||||
* @param datasetId Dify数据集ID
|
* @param datasetId Dify数据集ID
|
||||||
* @param documentId Dify文档ID
|
* @param documentId Dify文档ID
|
||||||
* @param enabled 是否启用
|
* @param enabled 是否启用
|
||||||
* @returns Promise<ResultDomain<void>>
|
* @returns Promise<ResultDomain<Boolean>>
|
||||||
*/
|
*/
|
||||||
async updateDocumentStatus(
|
async updateDocumentStatus(
|
||||||
datasetId: string,
|
datasetId: string,
|
||||||
documentId: string,
|
documentId: string,
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
): Promise<ResultDomain<void>> {
|
): Promise<ResultDomain<Boolean>> {
|
||||||
const action = enabled ? 'enable' : 'disable';
|
const action = enabled ? 'enable' : 'disable';
|
||||||
const response = await api.post<void>(
|
const response = await api.post<boolean>(
|
||||||
`/ai/dify/datasets/${datasetId}/documents/status/${action}`,
|
`/ai/dify/datasets/${datasetId}/documents/status/${action}`,
|
||||||
{ document_ids: [documentId] }
|
{ document_ids: [documentId] }
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,7 +5,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { api } from '@/apis/index';
|
import { api } from '@/apis/index';
|
||||||
import type { CrontabTask, CrontabLog, DataCollectionItem, CrontabItem, ResultDomain, PageParam } from '@/types';
|
import type {
|
||||||
|
CrontabTask,
|
||||||
|
CrontabLog,
|
||||||
|
DataCollectionItem,
|
||||||
|
CrontabItem,
|
||||||
|
TaskMeta,
|
||||||
|
EmailDefault,
|
||||||
|
EmailRecipient,
|
||||||
|
CreateTaskRequest,
|
||||||
|
ResultDomain,
|
||||||
|
PageParam
|
||||||
|
} from '@/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务API服务
|
* 定时任务API服务
|
||||||
@@ -16,11 +27,11 @@ export const crontabApi = {
|
|||||||
// ==================== 定时任务管理 ====================
|
// ==================== 定时任务管理 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取可创建的定时任务模板列表
|
* 获取可创建的定时任务列表(从数据库获取任务元数据)
|
||||||
* @returns Promise<ResultDomain<CrontabItem>>
|
* @returns Promise<ResultDomain<TaskMeta>>
|
||||||
*/
|
*/
|
||||||
async getEnabledCrontabList(): Promise<ResultDomain<CrontabItem>> {
|
async getEnabledCrontabList(): Promise<ResultDomain<TaskMeta>> {
|
||||||
const response = await api.get<CrontabItem>(`${this.baseUrl}/getEnabledCrontabList`);
|
const response = await api.get<TaskMeta>(`${this.baseUrl}/getEnabledCrontabList`);
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -29,18 +40,18 @@ export const crontabApi = {
|
|||||||
* @param task 任务对象
|
* @param task 任务对象
|
||||||
* @returns Promise<ResultDomain<CrontabTask>>
|
* @returns Promise<ResultDomain<CrontabTask>>
|
||||||
*/
|
*/
|
||||||
async createTask(task: CrontabTask): Promise<ResultDomain<CrontabTask>> {
|
async createTask(task: CreateTaskRequest): Promise<ResultDomain<CrontabTask>> {
|
||||||
const response = await api.post<CrontabTask>(`${this.baseUrl}/crontabTask`, task);
|
const response = await api.post<CrontabTask>(`${this.baseUrl}/crontabTask`, task);
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新定时任务
|
* 更新定时任务
|
||||||
* @param task 任务对象
|
* @param request 更新任务请求(包含任务信息、元数据ID等)
|
||||||
* @returns Promise<ResultDomain<CrontabTask>>
|
* @returns Promise<ResultDomain<CrontabTask>>
|
||||||
*/
|
*/
|
||||||
async updateTask(task: CrontabTask): Promise<ResultDomain<CrontabTask>> {
|
async updateTask(request: CreateTaskRequest): Promise<ResultDomain<CrontabTask>> {
|
||||||
const response = await api.put<CrontabTask>(`${this.baseUrl}/crontabTask`, task);
|
const response = await api.put<CrontabTask>(`${this.baseUrl}/crontabTask`, request);
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -255,5 +266,254 @@ export const crontabApi = {
|
|||||||
const response = await api.put<string>(`${this.baseUrl}/collection/item/${itemId}/status/${status}`);
|
const response = await api.put<string>(`${this.baseUrl}/collection/item/${itemId}/status/${status}`);
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== 任务元数据管理 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建任务元数据
|
||||||
|
* @param taskMeta 任务元数据
|
||||||
|
* @returns Promise<ResultDomain<TaskMeta>>
|
||||||
|
*/
|
||||||
|
async createTaskMeta(taskMeta: TaskMeta): Promise<ResultDomain<TaskMeta>> {
|
||||||
|
const response = await api.post<TaskMeta>(`${this.baseUrl}/meta`, taskMeta);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新任务元数据
|
||||||
|
* @param taskMeta 任务元数据
|
||||||
|
* @returns Promise<ResultDomain<TaskMeta>>
|
||||||
|
*/
|
||||||
|
async updateTaskMeta(taskMeta: TaskMeta): Promise<ResultDomain<TaskMeta>> {
|
||||||
|
const response = await api.put<TaskMeta>(`${this.baseUrl}/meta`, taskMeta);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除任务元数据
|
||||||
|
* @param metaId 元数据ID
|
||||||
|
* @returns Promise<ResultDomain<boolean>>
|
||||||
|
*/
|
||||||
|
async deleteTaskMeta(metaId: string): Promise<ResultDomain<boolean>> {
|
||||||
|
const response = await api.delete<boolean>(`${this.baseUrl}/meta/${metaId}`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询任务元数据
|
||||||
|
* @param metaId 元数据ID
|
||||||
|
* @returns Promise<ResultDomain<TaskMeta>>
|
||||||
|
*/
|
||||||
|
async getTaskMetaById(metaId: string): Promise<ResultDomain<TaskMeta>> {
|
||||||
|
const response = await api.get<TaskMeta>(`${this.baseUrl}/meta/${metaId}`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询所有任务元数据
|
||||||
|
* @returns Promise<ResultDomain<TaskMeta>>
|
||||||
|
*/
|
||||||
|
async getAllTaskMeta(): Promise<ResultDomain<TaskMeta>> {
|
||||||
|
const response = await api.get<TaskMeta>(`${this.baseUrl}/meta/all`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据分类查询任务元数据
|
||||||
|
* @param category 分类
|
||||||
|
* @returns Promise<ResultDomain<TaskMeta>>
|
||||||
|
*/
|
||||||
|
async getTaskMetaByCategory(category: string): Promise<ResultDomain<TaskMeta>> {
|
||||||
|
const response = await api.get<TaskMeta>(`${this.baseUrl}/meta/category/${category}`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询任务元数据
|
||||||
|
* @param filter 过滤条件
|
||||||
|
* @param pageParam 分页参数
|
||||||
|
* @returns Promise<ResultDomain<TaskMeta>>
|
||||||
|
*/
|
||||||
|
async getTaskMetaPage(filter?: Partial<TaskMeta>, pageParam?: PageParam): Promise<ResultDomain<TaskMeta>> {
|
||||||
|
const response = await api.post<TaskMeta>(`${this.baseUrl}/meta/page`, {
|
||||||
|
filter,
|
||||||
|
pageParam: {
|
||||||
|
pageNumber: pageParam?.pageNumber || 1,
|
||||||
|
pageSize: pageParam?.pageSize || 10
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 邮件默认接收人管理 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建默认接收人
|
||||||
|
* @param emailDefault 默认接收人
|
||||||
|
* @returns Promise<ResultDomain<EmailDefault>>
|
||||||
|
*/
|
||||||
|
async createEmailDefault(emailDefault: EmailDefault): Promise<ResultDomain<EmailDefault>> {
|
||||||
|
const response = await api.post<EmailDefault>(`${this.baseUrl}/email/default`, emailDefault);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新默认接收人
|
||||||
|
* @param emailDefault 默认接收人
|
||||||
|
* @returns Promise<ResultDomain<EmailDefault>>
|
||||||
|
*/
|
||||||
|
async updateEmailDefault(emailDefault: EmailDefault): Promise<ResultDomain<EmailDefault>> {
|
||||||
|
const response = await api.put<EmailDefault>(`${this.baseUrl}/email/default`, emailDefault);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除默认接收人
|
||||||
|
* @param defaultId 默认ID
|
||||||
|
* @returns Promise<ResultDomain<boolean>>
|
||||||
|
*/
|
||||||
|
async deleteEmailDefault(defaultId: string): Promise<ResultDomain<boolean>> {
|
||||||
|
const response = await api.delete<boolean>(`${this.baseUrl}/email/default/${defaultId}`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据defaultId查询
|
||||||
|
* @param defaultId 默认ID
|
||||||
|
* @returns Promise<ResultDomain<EmailDefault>>
|
||||||
|
*/
|
||||||
|
async getEmailDefaultById(defaultId: string): Promise<ResultDomain<EmailDefault>> {
|
||||||
|
const response = await api.get<EmailDefault>(`${this.baseUrl}/email/default/${defaultId}`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据metaId查询默认接收人
|
||||||
|
* @param metaId 元数据ID
|
||||||
|
* @returns Promise<ResultDomain<EmailDefault>>
|
||||||
|
*/
|
||||||
|
async getEmailDefaultByMetaId(metaId: string): Promise<ResultDomain<EmailDefault>> {
|
||||||
|
const response = await api.get<EmailDefault>(`${this.baseUrl}/email/default/meta/${metaId}`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 邮件接收人管理 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建邮件接收人
|
||||||
|
* @param recipient 邮件接收人
|
||||||
|
* @returns Promise<ResultDomain<EmailRecipient>>
|
||||||
|
*/
|
||||||
|
async createEmailRecipient(recipient: EmailRecipient): Promise<ResultDomain<EmailRecipient>> {
|
||||||
|
const response = await api.post<EmailRecipient>(`${this.baseUrl}/email/recipient`, recipient);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量创建邮件接收人
|
||||||
|
* @param recipients 邮件接收人列表
|
||||||
|
* @returns Promise<ResultDomain<boolean>>
|
||||||
|
*/
|
||||||
|
async batchCreateEmailRecipient(recipients: EmailRecipient[]): Promise<ResultDomain<boolean>> {
|
||||||
|
const response = await api.post<boolean>(`${this.baseUrl}/email/recipient/batch`, recipients);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新邮件接收人
|
||||||
|
* @param recipient 邮件接收人
|
||||||
|
* @returns Promise<ResultDomain<EmailRecipient>>
|
||||||
|
*/
|
||||||
|
async updateEmailRecipient(recipient: EmailRecipient): Promise<ResultDomain<EmailRecipient>> {
|
||||||
|
const response = await api.put<EmailRecipient>(`${this.baseUrl}/email/recipient`, recipient);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除邮件接收人
|
||||||
|
* @param recipientId 接收人ID
|
||||||
|
* @returns Promise<ResultDomain<boolean>>
|
||||||
|
*/
|
||||||
|
async deleteEmailRecipient(recipientId: string): Promise<ResultDomain<boolean>> {
|
||||||
|
const response = await api.delete<boolean>(`${this.baseUrl}/email/recipient/${recipientId}`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询接收人
|
||||||
|
* @param recipientId 接收人ID
|
||||||
|
* @returns Promise<ResultDomain<EmailRecipient>>
|
||||||
|
*/
|
||||||
|
async getEmailRecipientById(recipientId: string): Promise<ResultDomain<EmailRecipient>> {
|
||||||
|
const response = await api.get<EmailRecipient>(`${this.baseUrl}/email/recipient/${recipientId}`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据default_id查询接收人列表
|
||||||
|
* @param defaultId 默认ID
|
||||||
|
* @returns Promise<ResultDomain<EmailRecipient>>
|
||||||
|
*/
|
||||||
|
async getRecipientsByDefaultId(defaultId: string): Promise<ResultDomain<EmailRecipient>> {
|
||||||
|
const response = await api.get<EmailRecipient>(`${this.baseUrl}/email/recipient/default/${defaultId}`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据任务ID查询接收人列表
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @returns Promise<ResultDomain<EmailRecipient>>
|
||||||
|
*/
|
||||||
|
async getRecipientsByTaskId(taskId: string): Promise<ResultDomain<EmailRecipient>> {
|
||||||
|
const response = await api.get<EmailRecipient>(`${this.baseUrl}/email/recipient/task/${taskId}`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询所有启用的接收人
|
||||||
|
* @returns Promise<ResultDomain<EmailRecipient>>
|
||||||
|
*/
|
||||||
|
async getAllEnabledRecipients(): Promise<ResultDomain<EmailRecipient>> {
|
||||||
|
const response = await api.get<EmailRecipient>(`${this.baseUrl}/email/recipient/enabled`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询邮件接收人
|
||||||
|
* @param filter 过滤条件
|
||||||
|
* @param pageParam 分页参数
|
||||||
|
* @returns Promise<ResultDomain<EmailRecipient>>
|
||||||
|
*/
|
||||||
|
async getEmailRecipientPage(filter?: Partial<EmailRecipient>, pageParam?: PageParam): Promise<ResultDomain<EmailRecipient>> {
|
||||||
|
const response = await api.post<EmailRecipient>(`${this.baseUrl}/email/recipient/page`, {
|
||||||
|
filter,
|
||||||
|
pageParam: {
|
||||||
|
pageNumber: pageParam?.pageNumber || 1,
|
||||||
|
pageSize: pageParam?.pageSize || 10
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除default_id的所有接收人
|
||||||
|
* @param defaultId 默认ID
|
||||||
|
* @returns Promise<ResultDomain<boolean>>
|
||||||
|
*/
|
||||||
|
async deleteRecipientsByDefaultId(defaultId: string): Promise<ResultDomain<boolean>> {
|
||||||
|
const response = await api.delete<boolean>(`${this.baseUrl}/email/recipient/default/${defaultId}`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除任务的所有接收人
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @returns Promise<ResultDomain<boolean>>
|
||||||
|
*/
|
||||||
|
async deleteRecipientsByTaskId(taskId: string): Promise<ResultDomain<boolean>> {
|
||||||
|
const response = await api.delete<boolean>(`${this.baseUrl}/email/recipient/task/${taskId}`);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ export interface CrontabTask extends BaseDTO {
|
|||||||
taskName?: string;
|
taskName?: string;
|
||||||
/** 任务分组 */
|
/** 任务分组 */
|
||||||
taskGroup?: string;
|
taskGroup?: string;
|
||||||
|
/** 元数据ID(关联任务元数据表) */
|
||||||
|
metaId?: string;
|
||||||
|
/** 是否使用默认接收人 */
|
||||||
|
defaultRecipient?: boolean;
|
||||||
/** Bean名称 */
|
/** Bean名称 */
|
||||||
beanName?: string;
|
beanName?: string;
|
||||||
/** 方法名称 */
|
/** 方法名称 */
|
||||||
@@ -172,6 +176,8 @@ export interface CrontabMethod {
|
|||||||
excuete_method?: string;
|
excuete_method?: string;
|
||||||
/** Python脚本路径 */
|
/** Python脚本路径 */
|
||||||
path: string;
|
path: string;
|
||||||
|
/** 元数据ID(从数据库加载时使用) */
|
||||||
|
metaId?: string;
|
||||||
/** 参数定义列表 */
|
/** 参数定义列表 */
|
||||||
params?: CrontabParam[];
|
params?: CrontabParam[];
|
||||||
}
|
}
|
||||||
@@ -186,3 +192,95 @@ export interface CrontabItem {
|
|||||||
methods: CrontabMethod[];
|
methods: CrontabMethod[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时任务元数据
|
||||||
|
*/
|
||||||
|
export interface TaskMeta extends BaseDTO {
|
||||||
|
/** 元数据ID */
|
||||||
|
metaId?: string;
|
||||||
|
/** 任务名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 任务描述 */
|
||||||
|
description?: string;
|
||||||
|
/** 任务分类 */
|
||||||
|
category?: string;
|
||||||
|
/** Bean名称 */
|
||||||
|
beanName?: string;
|
||||||
|
/** 方法名称 */
|
||||||
|
methodName?: string;
|
||||||
|
/** 脚本路径 */
|
||||||
|
scriptPath?: string;
|
||||||
|
/** 参数模式(JSON Schema) */
|
||||||
|
paramSchema?: string;
|
||||||
|
/** 是否自动发布 */
|
||||||
|
autoPublish?: boolean;
|
||||||
|
/** 排序 */
|
||||||
|
sortOrder?: number;
|
||||||
|
/** 创建者 */
|
||||||
|
creator?: string;
|
||||||
|
/** 更新者 */
|
||||||
|
updater?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件默认接收人
|
||||||
|
*/
|
||||||
|
export interface EmailDefault extends BaseDTO {
|
||||||
|
/** 默认ID */
|
||||||
|
defaultId?: string;
|
||||||
|
/** 元数据ID */
|
||||||
|
metaId?: string;
|
||||||
|
/** 用户ID */
|
||||||
|
userId?: string;
|
||||||
|
userEmail?: string;
|
||||||
|
username?:string;
|
||||||
|
/** 创建者 */
|
||||||
|
creator?: string;
|
||||||
|
/** 更新者 */
|
||||||
|
updater?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮件接收人
|
||||||
|
*/
|
||||||
|
export interface EmailRecipient extends BaseDTO {
|
||||||
|
/** 接收人ID */
|
||||||
|
recipientId?: string;
|
||||||
|
/** 任务ID */
|
||||||
|
taskId?: string;
|
||||||
|
/** 用户ID */
|
||||||
|
userId?: string;
|
||||||
|
/** 邮箱 */
|
||||||
|
email?: string;
|
||||||
|
/** 姓名 */
|
||||||
|
name?: string;
|
||||||
|
/** 创建者 */
|
||||||
|
creator?: string;
|
||||||
|
/** 更新者 */
|
||||||
|
updater?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收人用户信息
|
||||||
|
*/
|
||||||
|
export interface RecipientUserInfo {
|
||||||
|
/** 用户ID */
|
||||||
|
userId: string;
|
||||||
|
/** 用户邮箱 */
|
||||||
|
userEmail: string;
|
||||||
|
/** 用户名称 */
|
||||||
|
username: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建任务请求
|
||||||
|
*/
|
||||||
|
export interface CreateTaskRequest {
|
||||||
|
/** 任务信息 */
|
||||||
|
task: CrontabTask;
|
||||||
|
/** 任务元数据ID */
|
||||||
|
metaId: string;
|
||||||
|
/** 额外添加的接收人列表 */
|
||||||
|
additionalRecipients?: RecipientUserInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ export interface TaskItemVO extends LearningTask {
|
|||||||
username?: string;
|
username?: string;
|
||||||
deptID?: string;
|
deptID?: string;
|
||||||
deptName?: string;
|
deptName?: string;
|
||||||
parentDeptID?: string;
|
parentID?: string;
|
||||||
/** 是否必修 */
|
/** 是否必修 */
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
/** 排序号 */
|
/** 排序号 */
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export interface UserVO extends BaseDTO {
|
|||||||
/** 学习等级 */
|
/** 学习等级 */
|
||||||
level?: number;
|
level?: number;
|
||||||
deptID?: string;
|
deptID?: string;
|
||||||
parentDeptID?: string;
|
parentID?: string;
|
||||||
/** 部门名称 */
|
/** 部门名称 */
|
||||||
deptName?: string;
|
deptName?: string;
|
||||||
/** 角色名称 */
|
/** 角色名称 */
|
||||||
|
|||||||
@@ -206,16 +206,16 @@
|
|||||||
<div class="form-item" v-if="selectedTemplate">
|
<div class="form-item" v-if="selectedTemplate">
|
||||||
<span class="form-label required">爬取方法</span>
|
<span class="form-label required">爬取方法</span>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="selectedMethod"
|
v-model="selectedMethodId"
|
||||||
placeholder="请选择爬取方法"
|
placeholder="请选择爬取方法"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="method in selectedTemplate.methods"
|
v-for="method in selectedTemplate.methods"
|
||||||
:key="method.name"
|
:key="method.metaId"
|
||||||
:label="method.name"
|
:label="method.name"
|
||||||
:value="method"
|
:value="method.metaId"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
<span class="form-tip">
|
<span class="form-tip">
|
||||||
@@ -282,15 +282,42 @@
|
|||||||
placeholder="请输入爬虫描述"
|
placeholder="请输入爬虫描述"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 邮件接收人配置 -->
|
||||||
<div class="form-item">
|
<div class="form-item">
|
||||||
<span class="form-label">是否允许并发</span>
|
<span class="form-label">邮件通知</span>
|
||||||
<el-radio-group v-model="formData.concurrent">
|
<el-checkbox v-model="useDefaultRecipients">
|
||||||
<el-radio :label="1">允许</el-radio>
|
使用默认接收人
|
||||||
<el-radio :label="0">禁止</el-radio>
|
</el-checkbox>
|
||||||
</el-radio-group>
|
<span class="form-tip" v-if="useDefaultRecipients && defaultRecipients.length > 0">
|
||||||
<span class="form-tip">
|
默认接收人:{{ defaultRecipients.map(r => r.username).join('、') }}
|
||||||
建议禁止并发,避免重复抓取
|
|
||||||
</span>
|
</span>
|
||||||
|
<span class="form-tip" v-else-if="useDefaultRecipients && defaultRecipients.length === 0">
|
||||||
|
该任务模板暂无默认接收人
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-item">
|
||||||
|
<span class="form-label">额外接收人</span>
|
||||||
|
<div class="recipient-list">
|
||||||
|
<el-tag
|
||||||
|
v-for="recipient in additionalRecipients"
|
||||||
|
:key="recipient.userId"
|
||||||
|
closable
|
||||||
|
@close="removeRecipient(recipient)"
|
||||||
|
style="margin-right: 8px; margin-bottom: 8px;"
|
||||||
|
>
|
||||||
|
{{ recipient.username }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
<el-button
|
||||||
|
@click="showRecipientSelector"
|
||||||
|
size="small"
|
||||||
|
style="margin-top: 8px;"
|
||||||
|
>
|
||||||
|
选择接收人
|
||||||
|
</el-button>
|
||||||
|
<!-- TODO: 在这里添加自定义的用户选择组件 -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -305,17 +332,38 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<GenericSelector
|
||||||
|
v-model:visible="showUserSelector"
|
||||||
|
title="选择邮件接收人"
|
||||||
|
left-title="可选人员"
|
||||||
|
right-title="已选人员"
|
||||||
|
:fetch-available-api="fetchAllUsers"
|
||||||
|
:initialTargetItems="selectedRecipients"
|
||||||
|
:filter-selected="filterUsers"
|
||||||
|
:item-config="{ id: 'userId', label: 'username', sublabel: 'userEmail' }"
|
||||||
|
:use-tree="true"
|
||||||
|
:tree-transform="transformUserToTree"
|
||||||
|
:tree-props="{ children: 'children', label: 'username', id: 'userId' }"
|
||||||
|
:only-leaf-selectable="true"
|
||||||
|
unit-name="人"
|
||||||
|
search-placeholder="搜索用户姓名或邮箱..."
|
||||||
|
@confirm="handleUserConfirm"
|
||||||
|
@cancel="resetUserSelector"
|
||||||
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</AdminLayout>
|
</AdminLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, onMounted, watch } from 'vue';
|
import { ref, reactive, onMounted, watch, computed } from 'vue';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
import { Plus, Search, Refresh, DocumentCopy, VideoPlay, VideoPause, Promotion, Edit, Delete } from '@element-plus/icons-vue';
|
import { Plus, Search, Refresh, DocumentCopy, VideoPlay, VideoPause, Promotion, Edit, Delete } from '@element-plus/icons-vue';
|
||||||
import { crontabApi } from '@/apis/crontab';
|
import { crontabApi } from '@/apis/crontab';
|
||||||
import type { CrontabTask, CrontabItem, CrontabMethod, PageParam } from '@/types';
|
import { userApi } from '@/apis/system/user';
|
||||||
|
import type { CrontabTask, TaskMeta, CrontabItem, CrontabMethod, CrontabParam, PageParam, CreateTaskRequest, RecipientUserInfo, UserVO, ResultDomain, EmailDefault } from '@/types';
|
||||||
import { AdminLayout } from '@/views/admin';
|
import { AdminLayout } from '@/views/admin';
|
||||||
|
import { GenericSelector } from '@/components';
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'NewsCrawlerView'
|
name: 'NewsCrawlerView'
|
||||||
});
|
});
|
||||||
@@ -325,12 +373,20 @@ const submitting = ref(false);
|
|||||||
const crawlerList = ref<CrontabTask[]>([]);
|
const crawlerList = ref<CrontabTask[]>([]);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
// 爬虫模板数据
|
// 爬虫元数据
|
||||||
const crawlerTemplates = ref<CrontabItem[]>([]);
|
const taskMetaList = ref<TaskMeta[]>([]);
|
||||||
|
const crawlerTemplates = ref<CrontabItem[]>([]); // 转换后的模板结构
|
||||||
const selectedTemplate = ref<CrontabItem | null>(null);
|
const selectedTemplate = ref<CrontabItem | null>(null);
|
||||||
const selectedMethod = ref<CrontabMethod | null>(null);
|
const selectedMethodId = ref<string>(''); // 选中的方法ID(metaId)
|
||||||
|
const selectedMetaId = ref<string>(''); // 选中的元数据ID
|
||||||
const dynamicParams = ref<Record<string, any>>({});
|
const dynamicParams = ref<Record<string, any>>({});
|
||||||
|
|
||||||
|
// 邮件接收人相关
|
||||||
|
const useDefaultRecipients = ref<boolean>(false);
|
||||||
|
const defaultRecipients = ref<RecipientUserInfo[]>([]);
|
||||||
|
const additionalRecipients = ref<RecipientUserInfo[]>([]);
|
||||||
|
const showUserSelector = ref<boolean>(false);
|
||||||
|
|
||||||
// 搜索表单
|
// 搜索表单
|
||||||
const searchForm = reactive({
|
const searchForm = reactive({
|
||||||
taskName: '',
|
taskName: '',
|
||||||
@@ -361,40 +417,251 @@ const formData = reactive<Partial<CrontabTask>>({
|
|||||||
description: ''
|
description: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 根据selectedMethodId获取完整的method对象
|
||||||
|
const selectedMethod = computed(() => {
|
||||||
|
if (!selectedTemplate.value || !selectedMethodId.value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return selectedTemplate.value.methods.find(m => m.metaId === selectedMethodId.value) || null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 计算已选接收人(包括默认接收人+额外添加的接收人)
|
||||||
|
const selectedRecipients = computed(() => {
|
||||||
|
if (useDefaultRecipients.value) {
|
||||||
|
// 合并默认接收人和额外接收人,去重
|
||||||
|
const all = [...defaultRecipients.value, ...additionalRecipients.value];
|
||||||
|
const uniqueMap = new Map<string, RecipientUserInfo>();
|
||||||
|
all.forEach(r => uniqueMap.set(r.userId, r));
|
||||||
|
return Array.from(uniqueMap.values());
|
||||||
|
} else {
|
||||||
|
return additionalRecipients.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 监听模板选择变化
|
// 监听模板选择变化
|
||||||
watch(selectedTemplate, (newTemplate, oldTemplate) => {
|
watch(selectedTemplate, (newTemplate, oldTemplate) => {
|
||||||
// 只在用户手动切换模板时重置(oldTemplate存在且不为null时才重置)
|
// 只在用户手动切换模板时重置(oldTemplate存在且不为null时才重置)
|
||||||
// 编辑回填时oldTemplate为null,不会触发重置
|
// 编辑回填时oldTemplate为null,不会触发重置
|
||||||
if (newTemplate && oldTemplate) {
|
if (newTemplate && oldTemplate) {
|
||||||
selectedMethod.value = null;
|
selectedMethodId.value = '';
|
||||||
dynamicParams.value = {};
|
dynamicParams.value = {};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 监听方法选择变化
|
// 监听方法选择变化
|
||||||
watch(selectedMethod, (newMethod) => {
|
watch(selectedMethodId, (newMethodId) => {
|
||||||
if (newMethod) {
|
if (newMethodId && selectedMethod.value) {
|
||||||
|
// 保存metaId
|
||||||
|
selectedMetaId.value = newMethodId;
|
||||||
|
|
||||||
dynamicParams.value = {};
|
dynamicParams.value = {};
|
||||||
// 遍历params数组提取默认值
|
// 遍历params数组提取默认值
|
||||||
if (newMethod.params && Array.isArray(newMethod.params)) {
|
if (selectedMethod.value.params && Array.isArray(selectedMethod.value.params)) {
|
||||||
newMethod.params.forEach(param => {
|
selectedMethod.value.params.forEach((param: CrontabParam) => {
|
||||||
dynamicParams.value[param.name] = param.value;
|
dynamicParams.value[param.name] = param.value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载该任务模板的默认接收人
|
||||||
|
if (selectedMetaId.value) {
|
||||||
|
loadDefaultRecipients(selectedMetaId.value);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 加载爬虫模板
|
// ==================== 人员选择器相关 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. 获取所有人员列表的接口方法
|
||||||
|
*/
|
||||||
|
async function fetchAllUsers(): Promise<ResultDomain<any>> {
|
||||||
|
try {
|
||||||
|
const result = await userApi.getUserList({});
|
||||||
|
if (result.success && result.dataList) {
|
||||||
|
// 转换为 GenericSelector 需要的格式
|
||||||
|
const users = result.dataList.map((user: UserVO) => ({
|
||||||
|
userId: user.id || '',
|
||||||
|
username: user.username || user.email || 'Unknown',
|
||||||
|
userEmail: user.email || '',
|
||||||
|
deptID: user.deptID,
|
||||||
|
deptName: user.deptName,
|
||||||
|
parentID: user.parentID
|
||||||
|
}));
|
||||||
|
|
||||||
|
return {
|
||||||
|
...result,
|
||||||
|
dataList: users
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('获取用户列表失败');
|
||||||
|
return {
|
||||||
|
code: 500,
|
||||||
|
success: false,
|
||||||
|
login: true,
|
||||||
|
auth: true,
|
||||||
|
message: '获取用户列表失败',
|
||||||
|
dataList: []
|
||||||
|
} as ResultDomain<any>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2. 过滤方法:从可选项中移除已选项
|
||||||
|
*/
|
||||||
|
function filterUsers(available: any[], selected: any[]): any[] {
|
||||||
|
const selectedIds = new Set(selected.map(item => item.userId));
|
||||||
|
return available.filter(item => !selectedIds.has(item.userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 3. 构建多级部门树的方法
|
||||||
|
*/
|
||||||
|
function transformUserToTree(flatData: any[]): any[] {
|
||||||
|
if (!flatData || flatData.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第一步:按部门分组,收集每个部门下的用户
|
||||||
|
const deptMap = new Map<string, any>();
|
||||||
|
const tree: any[] = [];
|
||||||
|
|
||||||
|
flatData.forEach(item => {
|
||||||
|
if (!item.deptID) return;
|
||||||
|
|
||||||
|
if (!deptMap.has(item.deptID)) {
|
||||||
|
// 创建部门节点
|
||||||
|
deptMap.set(item.deptID, {
|
||||||
|
userId: `dept_${item.deptID}`,
|
||||||
|
username: item.deptName || '未分配部门',
|
||||||
|
userEmail: '',
|
||||||
|
deptID: item.deptID,
|
||||||
|
deptName: item.deptName,
|
||||||
|
parentID: item.parentID,
|
||||||
|
children: [],
|
||||||
|
isDept: true // 标记这是部门节点
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加用户到部门的children中
|
||||||
|
const deptNode = deptMap.get(item.deptID);
|
||||||
|
if (deptNode) {
|
||||||
|
deptNode.children.push({
|
||||||
|
...item,
|
||||||
|
isDept: false // 标记这是用户节点
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 第二步:构建部门层级关系
|
||||||
|
const allDepts = Array.from(deptMap.values());
|
||||||
|
const deptTreeMap = new Map<string, any>();
|
||||||
|
|
||||||
|
// 初始化所有部门节点(创建副本)
|
||||||
|
allDepts.forEach(dept => {
|
||||||
|
deptTreeMap.set(dept.deptID, { ...dept });
|
||||||
|
});
|
||||||
|
|
||||||
|
// 第三步:建立部门的父子关系
|
||||||
|
allDepts.forEach(dept => {
|
||||||
|
const node = deptTreeMap.get(dept.deptID);
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
|
if (!dept.parentID || dept.parentID === '0' || dept.parentID === '') {
|
||||||
|
// 根部门
|
||||||
|
tree.push(node);
|
||||||
|
} else {
|
||||||
|
// 子部门
|
||||||
|
const parent = deptTreeMap.get(dept.parentID);
|
||||||
|
if (parent) {
|
||||||
|
if (!parent.children) {
|
||||||
|
parent.children = [];
|
||||||
|
}
|
||||||
|
// 保存当前节点的用户列表
|
||||||
|
const users = node.children || [];
|
||||||
|
node.children = [];
|
||||||
|
// 将部门节点添加到父部门
|
||||||
|
parent.children.push(node);
|
||||||
|
// 恢复用户列表
|
||||||
|
node.children = users;
|
||||||
|
} else {
|
||||||
|
// 找不到父节点,作为根节点
|
||||||
|
tree.push(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 4. 显示用户选择器
|
||||||
|
*/
|
||||||
|
function showRecipientSelector() {
|
||||||
|
showUserSelector.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 5. 确认选择用户
|
||||||
|
*/
|
||||||
|
|
||||||
|
function handleUserConfirm(selected: any[]) {
|
||||||
|
// 过滤掉部门节点,只保留用户节点
|
||||||
|
const userItems = selected.filter(item => item.isDept !== true && !defaultRecipients.value.find(r => r.userId === item.userId));
|
||||||
|
additionalRecipients.value = userItems.map(item => ({
|
||||||
|
userId: item.userId,
|
||||||
|
username: item.username,
|
||||||
|
userEmail: item.userEmail || ''
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 6. 取消/重置选择器
|
||||||
|
*/
|
||||||
|
function resetUserSelector() {
|
||||||
|
console.log('❌ 取消选择');
|
||||||
|
// 不做任何操作,保持原有选择
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 加载爬虫模板(从数据库加载TaskMeta,转换为CrontabItem结构)
|
||||||
async function loadCrawlerTemplates() {
|
async function loadCrawlerTemplates() {
|
||||||
try {
|
try {
|
||||||
const result = await crontabApi.getEnabledCrontabList();
|
const result = await crontabApi.getEnabledCrontabList();
|
||||||
if (result.success && result.dataList) {
|
if (result.success && result.dataList) {
|
||||||
crawlerTemplates.value = result.dataList;
|
taskMetaList.value = result.dataList;
|
||||||
|
|
||||||
|
// 将TaskMeta[]按category分组转换为CrontabItem[]
|
||||||
|
const grouped = new Map<string, TaskMeta[]>();
|
||||||
|
result.dataList.forEach((meta: TaskMeta) => {
|
||||||
|
const category = meta.category || '未分类';
|
||||||
|
if (!grouped.has(category)) {
|
||||||
|
grouped.set(category, []);
|
||||||
|
}
|
||||||
|
grouped.get(category)!.push(meta);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 转换为CrontabItem结构
|
||||||
|
crawlerTemplates.value = Array.from(grouped.entries()).map(([category, metas]) => ({
|
||||||
|
name: category,
|
||||||
|
methods: metas.map(meta => ({
|
||||||
|
name: meta.name || '',
|
||||||
|
clazz: meta.beanName || '',
|
||||||
|
excuete_method: meta.methodName || '',
|
||||||
|
path: meta.scriptPath || '',
|
||||||
|
metaId: meta.metaId || '', // 保存metaId
|
||||||
|
params: meta.paramSchema ? JSON.parse(meta.paramSchema) : []
|
||||||
|
}))
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(result.message || '加载爬虫模板失败');
|
ElMessage.error(result.message || '加载爬虫模板失败');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载爬虫模板失败:', error);
|
|
||||||
ElMessage.error('加载爬虫模板失败');
|
ElMessage.error('加载爬虫模板失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -428,7 +695,6 @@ async function loadCrawlerList() {
|
|||||||
total.value = 0;
|
total.value = 0;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载爬虫列表失败:', error);
|
|
||||||
ElMessage.error('加载爬虫列表失败');
|
ElMessage.error('加载爬虫列表失败');
|
||||||
crawlerList.value = [];
|
crawlerList.value = [];
|
||||||
total.value = 0;
|
total.value = 0;
|
||||||
@@ -468,50 +734,68 @@ function handleAdd() {
|
|||||||
isEdit.value = false;
|
isEdit.value = false;
|
||||||
resetFormData();
|
resetFormData();
|
||||||
selectedTemplate.value = null;
|
selectedTemplate.value = null;
|
||||||
selectedMethod.value = null;
|
selectedMethodId.value = '';
|
||||||
dynamicParams.value = {};
|
dynamicParams.value = {};
|
||||||
dialogVisible.value = true;
|
dialogVisible.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑爬虫
|
// 编辑爬虫
|
||||||
function handleEdit(row: CrontabTask) {
|
async function handleEdit(row: CrontabTask) {
|
||||||
isEdit.value = true;
|
isEdit.value = true;
|
||||||
Object.assign(formData, row);
|
Object.assign(formData, row);
|
||||||
|
|
||||||
// 重置选择
|
// 重置选择
|
||||||
selectedTemplate.value = null;
|
selectedTemplate.value = null;
|
||||||
selectedMethod.value = null;
|
selectedMethodId.value = '';
|
||||||
dynamicParams.value = {};
|
dynamicParams.value = {};
|
||||||
|
|
||||||
// 尝试解析methodParams来回填表单
|
// 回填邮件接收人配置
|
||||||
|
useDefaultRecipients.value = row.defaultRecipient || false;
|
||||||
|
additionalRecipients.value = [];
|
||||||
|
|
||||||
|
// 加载该任务的额外接收人
|
||||||
|
if (row.taskId) {
|
||||||
|
try {
|
||||||
|
const recipientsResult = await crontabApi.getRecipientsByTaskId(row.taskId);
|
||||||
|
if (recipientsResult.success && recipientsResult.dataList) {
|
||||||
|
additionalRecipients.value = recipientsResult.dataList.map(item => ({
|
||||||
|
userId: item.userId || '',
|
||||||
|
username: item.name || '',
|
||||||
|
userEmail: item.email || ''
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载额外接收人失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通过metaId直接匹配
|
||||||
|
if (row.metaId) {
|
||||||
|
// 遍历所有模板和方法,找到匹配的metaId
|
||||||
|
for (const template of crawlerTemplates.value) {
|
||||||
|
const method = template.methods.find(m => m.metaId === row.metaId);
|
||||||
|
if (method) {
|
||||||
|
// 找到匹配的方法,设置template和method
|
||||||
|
selectedTemplate.value = template;
|
||||||
|
selectedMethodId.value = method.metaId || '';
|
||||||
|
selectedMetaId.value = method.metaId || '';
|
||||||
|
|
||||||
|
// 回填动态参数
|
||||||
if (row.methodParams) {
|
if (row.methodParams) {
|
||||||
try {
|
try {
|
||||||
const params = JSON.parse(row.methodParams);
|
const params = JSON.parse(row.methodParams);
|
||||||
// 如果有scriptPath,尝试匹配模板和方法
|
// 排除系统参数
|
||||||
if (params.scriptPath) {
|
const { scriptPath, taskId, logId, ...restParams } = params;
|
||||||
const template = crawlerTemplates.value.find(t =>
|
|
||||||
t.methods.some(m => m.path === params.scriptPath)
|
|
||||||
);
|
|
||||||
if (template) {
|
|
||||||
const method = template.methods.find(m => m.path === params.scriptPath);
|
|
||||||
if (method) {
|
|
||||||
// 先设置template和method,触发watch填充默认值
|
|
||||||
selectedTemplate.value = template;
|
|
||||||
selectedMethod.value = method;
|
|
||||||
|
|
||||||
// 然后使用nextTick确保watch执行完后再覆盖为实际值
|
|
||||||
// 回填动态参数(排除scriptPath)
|
|
||||||
const { scriptPath, ...restParams } = params;
|
|
||||||
// 延迟设置,确保watch先执行完
|
// 延迟设置,确保watch先执行完
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
dynamicParams.value = restParams;
|
dynamicParams.value = restParams;
|
||||||
console.log('📝 编辑回填 - template:', template.name, 'method:', method.name, 'params:', restParams);
|
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('解析methodParams失败:', error);
|
console.error('解析methodParams失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,7 +813,6 @@ async function handleStart(row: CrontabTask) {
|
|||||||
ElMessage.error(result.message || '启动失败');
|
ElMessage.error(result.message || '启动失败');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('启动爬虫失败:', error);
|
|
||||||
ElMessage.error('启动爬虫失败');
|
ElMessage.error('启动爬虫失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -545,7 +828,6 @@ async function handlePause(row: CrontabTask) {
|
|||||||
ElMessage.error(result.message || '暂停失败');
|
ElMessage.error(result.message || '暂停失败');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('暂停爬虫失败:', error);
|
|
||||||
ElMessage.error('暂停爬虫失败');
|
ElMessage.error('暂停爬虫失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -563,15 +845,21 @@ async function handleExecute(row: CrontabTask) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = await crontabApi.executeTaskOnce(row.taskId!);
|
// 异步执行,不等待任务完成
|
||||||
|
crontabApi.executeTaskOnce(row.taskId!).then(result => {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
ElMessage.success('爬虫执行成功,请稍后查看执行日志');
|
ElMessage.success('任务已提交执行,请稍后查看执行日志');
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(result.message || '执行失败');
|
ElMessage.error(result.message || '提交执行失败');
|
||||||
}
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
ElMessage.error('提交执行失败');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 立即提示用户任务已触发
|
||||||
|
ElMessage.info('任务执行已触发,正在后台运行...');
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (error !== 'cancel') {
|
if (error !== 'cancel') {
|
||||||
console.error('执行爬虫失败:', error);
|
|
||||||
ElMessage.error('执行爬虫失败');
|
ElMessage.error('执行爬虫失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -599,7 +887,6 @@ async function handleDelete(row: CrontabTask) {
|
|||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (error !== 'cancel') {
|
if (error !== 'cancel') {
|
||||||
console.error('删除爬虫失败:', error);
|
|
||||||
ElMessage.error('删除爬虫失败');
|
ElMessage.error('删除爬虫失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -620,7 +907,6 @@ async function validateCron() {
|
|||||||
ElMessage.error(result.message || 'Cron表达式格式错误');
|
ElMessage.error(result.message || 'Cron表达式格式错误');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('验证Cron表达式失败:', error);
|
|
||||||
ElMessage.error('验证失败');
|
ElMessage.error('验证失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -640,6 +926,12 @@ async function handleSubmit() {
|
|||||||
ElMessage.warning('请输入Cron表达式');
|
ElMessage.warning('请输入Cron表达式');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 校验additionRecipients的email存在
|
||||||
|
const recipientWithoutEmail = additionalRecipients.value.find(recipient => !recipient.userEmail);
|
||||||
|
if (recipientWithoutEmail) {
|
||||||
|
ElMessage.warning(`${recipientWithoutEmail.username} 邮箱不能为空`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 验证必填参数
|
// 验证必填参数
|
||||||
if (selectedMethod.value.params && Array.isArray(selectedMethod.value.params)) {
|
if (selectedMethod.value.params && Array.isArray(selectedMethod.value.params)) {
|
||||||
@@ -659,26 +951,24 @@ async function handleSubmit() {
|
|||||||
|
|
||||||
submitting.value = true;
|
submitting.value = true;
|
||||||
try {
|
try {
|
||||||
// 传递taskGroup和methodName(中文名),后端根据这两个name查找配置并填充beanName、methodName和scriptPath
|
// 构建CreateTaskRequest
|
||||||
const data = {
|
const requestData: CreateTaskRequest = {
|
||||||
|
metaId: selectedMetaId.value,
|
||||||
|
task: {
|
||||||
...formData,
|
...formData,
|
||||||
taskGroup: selectedTemplate.value.name, // 模板名称(中文)
|
defaultRecipient: useDefaultRecipients.value,
|
||||||
methodName: selectedMethod.value.name, // 方法名称(中文)
|
|
||||||
methodParams: JSON.stringify({
|
methodParams: JSON.stringify({
|
||||||
...dynamicParams.value // 只传用户输入的参数,scriptPath由后端填充
|
...dynamicParams.value
|
||||||
})
|
})
|
||||||
|
} as CrontabTask,
|
||||||
|
additionalRecipients: additionalRecipients.value
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('📤 准备提交的数据:', data);
|
|
||||||
console.log('📤 taskGroup:', selectedTemplate.value.name);
|
|
||||||
console.log('📤 methodName:', selectedMethod.value.name);
|
|
||||||
console.log('📤 动态参数:', dynamicParams.value);
|
|
||||||
|
|
||||||
let result;
|
let result;
|
||||||
if (isEdit.value) {
|
if (isEdit.value) {
|
||||||
result = await crontabApi.updateTask(data as CrontabTask);
|
result = await crontabApi.updateTask(requestData);
|
||||||
} else {
|
} else {
|
||||||
result = await crontabApi.createTask(data as CrontabTask);
|
result = await crontabApi.createTask(requestData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
@@ -689,7 +979,6 @@ async function handleSubmit() {
|
|||||||
ElMessage.error(result.message || (isEdit.value ? '更新失败' : '创建失败'));
|
ElMessage.error(result.message || (isEdit.value ? '更新失败' : '创建失败'));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('提交失败:', error);
|
|
||||||
ElMessage.error('提交失败');
|
ElMessage.error('提交失败');
|
||||||
} finally {
|
} finally {
|
||||||
submitting.value = false;
|
submitting.value = false;
|
||||||
@@ -713,8 +1002,41 @@ function resetFormData() {
|
|||||||
status: 0,
|
status: 0,
|
||||||
concurrent: 0,
|
concurrent: 0,
|
||||||
misfirePolicy: 3,
|
misfirePolicy: 3,
|
||||||
description: ''
|
description: '',
|
||||||
|
defaultRecipient: false
|
||||||
});
|
});
|
||||||
|
useDefaultRecipients.value = false;
|
||||||
|
defaultRecipients.value = [];
|
||||||
|
additionalRecipients.value = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 邮件接收人相关方法
|
||||||
|
async function loadDefaultRecipients(metaId: string) {
|
||||||
|
try {
|
||||||
|
const result = await crontabApi.getEmailDefaultByMetaId(metaId);
|
||||||
|
|
||||||
|
if (result.success && result.dataList && result.dataList.length > 0) {
|
||||||
|
defaultRecipients.value = result.dataList
|
||||||
|
.map(item => ({
|
||||||
|
userId: item.userId!,
|
||||||
|
username: item.username!,
|
||||||
|
userEmail: item.userEmail!
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
defaultRecipients.value = [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
defaultRecipients.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 用户可以在这里添加自定义的邮件接收人选择逻辑
|
||||||
|
|
||||||
|
function removeRecipient(recipient: RecipientUserInfo) {
|
||||||
|
const index = additionalRecipients.value.findIndex(r => r.userId === recipient.userId);
|
||||||
|
if (index > -1) {
|
||||||
|
additionalRecipients.value.splice(index, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
|
|||||||
@@ -551,7 +551,7 @@ async function fetchTaskUsers() {
|
|||||||
username: item.username,
|
username: item.username,
|
||||||
deptID: item.deptID,
|
deptID: item.deptID,
|
||||||
deptName: item.deptName,
|
deptName: item.deptName,
|
||||||
parentDeptID: item.parentDeptID
|
parentID: item.parentID
|
||||||
}));
|
}));
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
@@ -604,7 +604,7 @@ function transformUsersToTree(flatData: any[]): any[] {
|
|||||||
displayName: deptName,
|
displayName: deptName,
|
||||||
deptID: deptID,
|
deptID: deptID,
|
||||||
deptName: deptName,
|
deptName: deptName,
|
||||||
parentDeptID: item.parentDeptID,
|
parentID: item.parentID,
|
||||||
children: [],
|
children: [],
|
||||||
isDept: true // 标记这是部门节点
|
isDept: true // 标记这是部门节点
|
||||||
});
|
});
|
||||||
@@ -635,12 +635,12 @@ function transformUsersToTree(flatData: any[]): any[] {
|
|||||||
const node = deptTreeMap.get(dept.deptID);
|
const node = deptTreeMap.get(dept.deptID);
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
|
|
||||||
if (!dept.parentDeptID || dept.parentDeptID === '0' || dept.parentDeptID === '') {
|
if (!dept.parentID || dept.parentID === '0' || dept.parentID === '') {
|
||||||
// 根部门
|
// 根部门
|
||||||
tree.push(node);
|
tree.push(node);
|
||||||
} else {
|
} else {
|
||||||
// 子部门
|
// 子部门
|
||||||
const parent = deptTreeMap.get(dept.parentDeptID);
|
const parent = deptTreeMap.get(dept.parentID);
|
||||||
if (parent) {
|
if (parent) {
|
||||||
// 将用户节点暂存
|
// 将用户节点暂存
|
||||||
const users = node.children || [];
|
const users = node.children || [];
|
||||||
|
|||||||
@@ -588,8 +588,8 @@ function transformUsersToTree(flatData: any[]): any[] {
|
|||||||
flatData.forEach(item => {
|
flatData.forEach(item => {
|
||||||
const deptID = item.deptID || 'unknown';
|
const deptID = item.deptID || 'unknown';
|
||||||
const deptName = item.deptName || '未分配部门';
|
const deptName = item.deptName || '未分配部门';
|
||||||
// 优先使用 parentID,如果不存在则使用 parentDeptID
|
// 优先使用 parentID,如果不存在则使用 parentID
|
||||||
const parentID = item.parentID || item.parentDeptID;
|
const parentID = item.parentID || item.parentID;
|
||||||
|
|
||||||
if (!deptMap.has(deptID)) {
|
if (!deptMap.has(deptID)) {
|
||||||
// 创建部门节点
|
// 创建部门节点
|
||||||
@@ -598,7 +598,7 @@ function transformUsersToTree(flatData: any[]): any[] {
|
|||||||
displayName: deptName,
|
displayName: deptName,
|
||||||
deptID: deptID,
|
deptID: deptID,
|
||||||
deptName: deptName,
|
deptName: deptName,
|
||||||
parentDeptID: parentID,
|
parentID: parentID,
|
||||||
children: [],
|
children: [],
|
||||||
isDept: true
|
isDept: true
|
||||||
});
|
});
|
||||||
@@ -629,12 +629,12 @@ function transformUsersToTree(flatData: any[]): any[] {
|
|||||||
const node = deptTreeMap.get(dept.deptID);
|
const node = deptTreeMap.get(dept.deptID);
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
|
|
||||||
if (!dept.parentDeptID || dept.parentDeptID === '0' || dept.parentDeptID === '') {
|
if (!dept.parentID || dept.parentID === '0' || dept.parentID === '') {
|
||||||
// 根部门
|
// 根部门
|
||||||
tree.push(node);
|
tree.push(node);
|
||||||
} else {
|
} else {
|
||||||
// 子部门
|
// 子部门
|
||||||
const parent = deptTreeMap.get(dept.parentDeptID);
|
const parent = deptTreeMap.get(dept.parentID);
|
||||||
if (parent) {
|
if (parent) {
|
||||||
// 将用户节点暂存
|
// 将用户节点暂存
|
||||||
const users = node.children || [];
|
const users = node.children || [];
|
||||||
|
|||||||
@@ -607,7 +607,7 @@ async function fetchTaskUsers() {
|
|||||||
username: item.username,
|
username: item.username,
|
||||||
deptID: item.deptID,
|
deptID: item.deptID,
|
||||||
deptName: item.deptName,
|
deptName: item.deptName,
|
||||||
parentDeptID: item.parentDeptID
|
parentID: item.parentID
|
||||||
}));
|
}));
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
@@ -656,7 +656,7 @@ function transformUsersToTree(flatData: any[]): any[] {
|
|||||||
displayName: deptName,
|
displayName: deptName,
|
||||||
deptID: deptID,
|
deptID: deptID,
|
||||||
deptName: deptName,
|
deptName: deptName,
|
||||||
parentDeptID: item.parentDeptID,
|
parentID: item.parentID,
|
||||||
children: [],
|
children: [],
|
||||||
isDept: true // 标记这是部门节点
|
isDept: true // 标记这是部门节点
|
||||||
});
|
});
|
||||||
@@ -687,12 +687,12 @@ function transformUsersToTree(flatData: any[]): any[] {
|
|||||||
const node = deptTreeMap.get(dept.deptID);
|
const node = deptTreeMap.get(dept.deptID);
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
|
|
||||||
if (!dept.parentDeptID || dept.parentDeptID === '0' || dept.parentDeptID === '') {
|
if (!dept.parentID || dept.parentID === '0' || dept.parentID === '') {
|
||||||
// 根部门
|
// 根部门
|
||||||
tree.push(node);
|
tree.push(node);
|
||||||
} else {
|
} else {
|
||||||
// 子部门
|
// 子部门
|
||||||
const parent = deptTreeMap.get(dept.parentDeptID);
|
const parent = deptTreeMap.get(dept.parentID);
|
||||||
if (parent) {
|
if (parent) {
|
||||||
// 将用户节点暂存
|
// 将用户节点暂存
|
||||||
const users = node.children || [];
|
const users = node.children || [];
|
||||||
|
|||||||
59
爬虫定时任务模块修改.md
Normal file
59
爬虫定时任务模块修改.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
crawler:
|
||||||
|
# Python 可执行文件路径(Windows 建议指向 python.exe;如已在 PATH,可直接用 "python")
|
||||||
|
pythonPath: F:/Environment/Conda/envs/schoolNewsCrawler/python.exe
|
||||||
|
# 爬虫脚本根目录(NewsCrawlerTask 的工作目录)
|
||||||
|
basePath: F:/Project/schoolNews/schoolNewsCrawler
|
||||||
|
|
||||||
|
# 下面为原有的定时任务清单(保持不变,仅修正到正确文件)
|
||||||
|
crontab:
|
||||||
|
items:
|
||||||
|
- name: 人民日报新闻爬取
|
||||||
|
methods:
|
||||||
|
- name: 关键字搜索爬取
|
||||||
|
clazz: newsCrewerTask
|
||||||
|
excuete_method: execute
|
||||||
|
path: crawler/RmrbSearch.py
|
||||||
|
params:
|
||||||
|
- name: query
|
||||||
|
description: 搜索关键字
|
||||||
|
type: String
|
||||||
|
value: ""
|
||||||
|
required: true
|
||||||
|
- name: total
|
||||||
|
description: 总新闻数量
|
||||||
|
type: Integer
|
||||||
|
value: 10
|
||||||
|
required: true
|
||||||
|
- name: 排行榜爬取
|
||||||
|
clazz: newsCrewerTask
|
||||||
|
excuete_method: execute
|
||||||
|
path: crawler/RmrbHotPoint.py
|
||||||
|
- name: 往日精彩头条爬取
|
||||||
|
clazz: newsCrewerTask
|
||||||
|
excuete_method: execute
|
||||||
|
path: crawler/RmrbTrending.py
|
||||||
|
params:
|
||||||
|
- name: startDate
|
||||||
|
description: 开始日期
|
||||||
|
type: String
|
||||||
|
value: ""
|
||||||
|
required: false
|
||||||
|
- name: endDate
|
||||||
|
description: 结束日期
|
||||||
|
type: String
|
||||||
|
value: ""
|
||||||
|
required: false
|
||||||
|
- name: yesterday
|
||||||
|
description: 是否是昨天
|
||||||
|
type: Boolean
|
||||||
|
value: true
|
||||||
|
|
||||||
|
|
||||||
|
1. 改成系统表配置。
|
||||||
|
2. 通过system模块的config配置crawler的基本信息
|
||||||
|
3. 创建定时任务meta表存放定时任务的元数据
|
||||||
|
4. 创建定时任务meta邮件人员模板表,存放定时任务的邮件人员模板
|
||||||
|
5. 创建定时任务邮件接收人员表,存放定时任务的邮件接收人员
|
||||||
|
6. 修改dto、service、mapper、controller等,实现定时任务meta的查询。定时任务meta邮件人员模板的增删改查。定时任务邮件接收人员的增删改查。
|
||||||
|
7. 修改定时任务的param等内容,实现定时任务的执行。
|
||||||
|
8. 修改前端接口请求逻辑,实现定时任务和邮件人员的增删改查。
|
||||||
Reference in New Issue
Block a user