diff --git a/src/main/java/com/zeodao/reminder/config/SchedulerConfig.java b/src/main/java/com/zeodao/reminder/config/SchedulerConfig.java index 8bbf7e0..9181ad7 100644 --- a/src/main/java/com/zeodao/reminder/config/SchedulerConfig.java +++ b/src/main/java/com/zeodao/reminder/config/SchedulerConfig.java @@ -7,7 +7,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; /** * 任务调度器配置 - * + * * @author Zeodao * @version 2.0.0 */ diff --git a/src/main/java/com/zeodao/reminder/config/TaskReminderConfig.java b/src/main/java/com/zeodao/reminder/config/TaskReminderConfig.java index a6c8e00..ee6f292 100644 --- a/src/main/java/com/zeodao/reminder/config/TaskReminderConfig.java +++ b/src/main/java/com/zeodao/reminder/config/TaskReminderConfig.java @@ -20,6 +20,7 @@ import java.util.Map; public class TaskReminderConfig { private Global global = new Global(); + private List groups = new ArrayList<>(); public Global getGlobal() { @@ -43,13 +44,12 @@ public class TaskReminderConfig { */ public Group getGroupById(String groupId) { return groups.stream() - .filter(group -> group.getId().equals(groupId)) - .findFirst() - .orElse(null); + .filter(group -> group.getId().equals(groupId)) + .findFirst() + .orElse(null); } - public static class Global { private int timeout = 5000; @@ -64,12 +64,17 @@ public class TaskReminderConfig { public static class Group { private String id; + private String name; + private Webhook webhook = new Webhook(); + private TaskSystemType taskSystem; + private Map schedules = new HashMap<>(); private Zentao zentao = new Zentao(); + private Map userMapping = new HashMap<>(); public String getId() { @@ -127,7 +132,6 @@ public class TaskReminderConfig { } - public Zentao getZentao() { return zentao; } @@ -159,7 +163,9 @@ public class TaskReminderConfig { public static class Schedule { private String time; + private String message; + private boolean enabled = true; // 默认启用 public String getTime() { @@ -189,10 +195,15 @@ public class TaskReminderConfig { public static class Zentao { private String apiUrl; + private String token; + private String username; + private String password; + private Integer projectId; + private Integer kanbanId; public String getApiUrl() { diff --git a/src/main/java/com/zeodao/reminder/controller/TaskReminderController.java b/src/main/java/com/zeodao/reminder/controller/TaskReminderController.java index f9432b9..7b58582 100644 --- a/src/main/java/com/zeodao/reminder/controller/TaskReminderController.java +++ b/src/main/java/com/zeodao/reminder/controller/TaskReminderController.java @@ -187,8 +187,8 @@ public class TaskReminderController { */ @PostMapping("/groups/{groupId}/{scheduleType}") public ResponseEntity> triggerGroupReminder( - @PathVariable String groupId, - @PathVariable String scheduleType) { + @PathVariable String groupId, + @PathVariable String scheduleType) { Map response = new HashMap<>(); try { diff --git a/src/main/java/com/zeodao/reminder/enums/ScheduleType.java b/src/main/java/com/zeodao/reminder/enums/ScheduleType.java index 1676108..8640457 100644 --- a/src/main/java/com/zeodao/reminder/enums/ScheduleType.java +++ b/src/main/java/com/zeodao/reminder/enums/ScheduleType.java @@ -7,23 +7,24 @@ package com.zeodao.reminder.enums; * @version 2.0.0 */ public enum ScheduleType { - + /** * 早上提醒 */ MORNING("morning", "早上提醒"), - + /** * 晚上提醒 */ EVENING("evening", "晚上提醒"), - + /** * 逾期任务提醒 */ OVERDUE_REMINDER("overdue-reminder", "逾期任务提醒"); private final String code; + private final String description; ScheduleType(String code, String description) { diff --git a/src/main/java/com/zeodao/reminder/enums/TaskSystemType.java b/src/main/java/com/zeodao/reminder/enums/TaskSystemType.java index 1869e21..2aaad6f 100644 --- a/src/main/java/com/zeodao/reminder/enums/TaskSystemType.java +++ b/src/main/java/com/zeodao/reminder/enums/TaskSystemType.java @@ -7,38 +7,39 @@ package com.zeodao.reminder.enums; * @version 2.0.0 */ public enum TaskSystemType { - + /** * 禅道 */ ZENTAO("zentao", "禅道"), - + /** * 智能表格 */ SMARTSHEET("smartsheet", "智能表格"), - + /** * Jira */ JIRA("jira", "Jira"), - + /** * Trello */ TRELLO("trello", "Trello"), - + /** * Asana */ ASANA("asana", "Asana"), - + /** * Notion */ NOTION("notion", "Notion"); private final String code; + private final String description; TaskSystemType(String code, String description) { diff --git a/src/main/java/com/zeodao/reminder/model/ProjectInfo.java b/src/main/java/com/zeodao/reminder/model/ProjectInfo.java index f6fc3d1..e55281c 100644 --- a/src/main/java/com/zeodao/reminder/model/ProjectInfo.java +++ b/src/main/java/com/zeodao/reminder/model/ProjectInfo.java @@ -16,8 +16,11 @@ import lombok.NoArgsConstructor; public class ProjectInfo { private Integer id; + private String name; + private String status; + private boolean exists; /** @@ -32,11 +35,16 @@ public class ProjectInfo { */ public String getStatusDescription() { switch (status) { - case "wait": return "未开始"; - case "doing": return "进行中"; - case "suspended": return "已挂起"; - case "closed": return "已关闭"; - default: return "未知状态"; + case "wait": + return "未开始"; + case "doing": + return "进行中"; + case "suspended": + return "已挂起"; + case "closed": + return "已关闭"; + default: + return "未知状态"; } } diff --git a/src/main/java/com/zeodao/reminder/model/ZentaoTask.java b/src/main/java/com/zeodao/reminder/model/ZentaoTask.java index fd9435e..8b86234 100644 --- a/src/main/java/com/zeodao/reminder/model/ZentaoTask.java +++ b/src/main/java/com/zeodao/reminder/model/ZentaoTask.java @@ -13,37 +13,69 @@ import lombok.Data; public class ZentaoTask { private String id; + private String name; + private String type; + private String status; + private String pri; + private String assignedTo; + private String assignedToRealName; + private String assignedDate; + private String deadline; + private String estStarted; + private String realStarted; + private String finishedBy; + private String finishedDate; + private String canceledBy; + private String canceledDate; + private String closedBy; + private String closedDate; + private String closedReason; + private String lastEditedBy; + private String lastEditedDate; + private String openedBy; + private String openedDate; + private String desc; + private String project; + private String story; + private String storyTitle; + private String module; + private String estimate; + private String consumed; + private String left; + private String progress; + private String color; + private String deleted; /** @@ -150,11 +182,16 @@ public class ZentaoTask { */ public String getPriorityDesc() { switch (pri) { - case "1": return "高"; - case "2": return "中"; - case "3": return "低"; - case "4": return "最低"; - default: return "普通"; + case "1": + return "高"; + case "2": + return "中"; + case "3": + return "低"; + case "4": + return "最低"; + default: + return "普通"; } } } diff --git a/src/main/java/com/zeodao/reminder/model/ZentaoUser.java b/src/main/java/com/zeodao/reminder/model/ZentaoUser.java index 5d5104d..d762ba2 100644 --- a/src/main/java/com/zeodao/reminder/model/ZentaoUser.java +++ b/src/main/java/com/zeodao/reminder/model/ZentaoUser.java @@ -14,36 +14,68 @@ import lombok.Data; public class ZentaoUser { private String id; + private String account; + private String realname; + private String nickname; + private String avatar; + private String birthday; + private String gender; + private String email; + private String skype; + private String qq; + private String yahoo; + private String gtalk; + private String wangwang; + private String mobile; + private String phone; + private String address; + private String zipcode; + private String join; + private String visits; + private String ip; + private String last; + private String fails; + private String locked; + private String feedback; + private String mail; + private String clientStatus; + private String clientLang; + private String dept; + private String role; + private String type; + private String groups; + private String view; + private String deleted; } diff --git a/src/main/java/com/zeodao/reminder/scheduler/DynamicTaskScheduler.java b/src/main/java/com/zeodao/reminder/scheduler/DynamicTaskScheduler.java index 09c468f..934e2bb 100644 --- a/src/main/java/com/zeodao/reminder/scheduler/DynamicTaskScheduler.java +++ b/src/main/java/com/zeodao/reminder/scheduler/DynamicTaskScheduler.java @@ -131,8 +131,8 @@ public class DynamicTaskScheduler { */ public int getActiveTaskCount() { return (int) scheduledTasks.values().stream() - .filter(future -> future != null && !future.isCancelled()) - .count(); + .filter(future -> future != null && !future.isCancelled()) + .count(); } /** diff --git a/src/main/java/com/zeodao/reminder/service/UserMappingService.java b/src/main/java/com/zeodao/reminder/service/UserMappingService.java index e641ee6..c9c8b5b 100644 --- a/src/main/java/com/zeodao/reminder/service/UserMappingService.java +++ b/src/main/java/com/zeodao/reminder/service/UserMappingService.java @@ -28,7 +28,7 @@ public class UserMappingService { /** * 根据禅道用户名获取企业微信@标识 * - * @param group 群组配置 + * @param group 群组配置 * @param zentaoUsername 禅道用户名 * @return 企业微信@标识,如 @13800138000 或 null */ @@ -106,7 +106,7 @@ public class UserMappingService { /** * 批量获取企业微信@标识 * - * @param group 群组配置 + * @param group 群组配置 * @param zentaoUsernames 禅道用户名列表 * @return 企业微信@标识列表 */ diff --git a/src/main/java/com/zeodao/reminder/service/WechatWebhookService.java b/src/main/java/com/zeodao/reminder/service/WechatWebhookService.java index a71abd2..ef608d7 100644 --- a/src/main/java/com/zeodao/reminder/service/WechatWebhookService.java +++ b/src/main/java/com/zeodao/reminder/service/WechatWebhookService.java @@ -185,10 +185,10 @@ public class WechatWebhookService { // 设置请求配置 RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(timeout) - .setSocketTimeout(timeout) - .setConnectionRequestTimeout(timeout) - .build(); + .setConnectTimeout(timeout) + .setSocketTimeout(timeout) + .setConnectionRequestTimeout(timeout) + .build(); httpPost.setConfig(requestConfig); // 设置请求头 @@ -261,7 +261,6 @@ public class WechatWebhookService { } - /** * 获取任务管理系统的图标 */ @@ -271,13 +270,20 @@ public class WechatWebhookService { } switch (taskSystemType) { - case ZENTAO: return "📋"; - case SMARTSHEET: return "📊"; - case JIRA: return "🎯"; - case TRELLO: return "📌"; - case ASANA: return "✅"; - case NOTION: return "📝"; - default: return "📋"; + case ZENTAO: + return "📋"; + case SMARTSHEET: + return "📊"; + case JIRA: + return "🎯"; + case TRELLO: + return "📌"; + case ASANA: + return "✅"; + case NOTION: + return "📝"; + default: + return "📋"; } } @@ -287,37 +293,37 @@ public class WechatWebhookService { private String getTaskSystemInstructions(TaskSystemType taskSystemType) { if (taskSystemType == null) { return "1. 登录任务管理系统\n" + - "2. 查看分配给自己的任务\n" + - "3. 更新任务状态和进度\n" + - "4. 添加必要的工作记录\n\n"; + "2. 查看分配给自己的任务\n" + + "3. 更新任务状态和进度\n" + + "4. 添加必要的工作记录\n\n"; } switch (taskSystemType) { case ZENTAO: return "1. 登录禅道系统\n" + - "2. 查看分配给自己的任务\n" + - "3. 更新任务状态和进度\n" + - "4. 添加必要的工作日志\n\n"; + "2. 查看分配给自己的任务\n" + + "3. 更新任务状态和进度\n" + + "4. 添加必要的工作日志\n\n"; case SMARTSHEET: return "1. 打开智能表格\n" + - "2. 找到自己负责的任务行\n" + - "3. 更新任务状态和完成百分比\n" + - "4. 添加备注说明进展情况\n\n"; + "2. 找到自己负责的任务行\n" + + "3. 更新任务状态和完成百分比\n" + + "4. 添加备注说明进展情况\n\n"; case JIRA: return "1. 登录Jira系统\n" + - "2. 查看分配给自己的Issue\n" + - "3. 更新Issue状态\n" + - "4. 记录工作日志和时间\n\n"; + "2. 查看分配给自己的Issue\n" + + "3. 更新Issue状态\n" + + "4. 记录工作日志和时间\n\n"; case TRELLO: return "1. 打开Trello看板\n" + - "2. 找到自己的任务卡片\n" + - "3. 移动卡片到对应状态列\n" + - "4. 添加评论记录进展\n\n"; + "2. 找到自己的任务卡片\n" + + "3. 移动卡片到对应状态列\n" + + "4. 添加评论记录进展\n\n"; default: return "1. 登录任务管理系统\n" + - "2. 查看分配给自己的任务\n" + - "3. 更新任务状态和进度\n" + - "4. 添加必要的工作记录\n\n"; + "2. 查看分配给自己的任务\n" + + "3. 更新任务状态和进度\n" + + "4. 添加必要的工作记录\n\n"; } } @@ -326,14 +332,22 @@ public class WechatWebhookService { */ private String getDayOfWeekInChinese(int dayOfWeek) { switch (dayOfWeek) { - case 1: return "星期一"; - case 2: return "星期二"; - case 3: return "星期三"; - case 4: return "星期四"; - case 5: return "星期五"; - case 6: return "星期六"; - case 7: return "星期日"; - default: return "未知"; + case 1: + return "星期一"; + case 2: + return "星期二"; + case 3: + return "星期三"; + case 4: + return "星期四"; + case 5: + return "星期五"; + case 6: + return "星期六"; + case 7: + return "星期日"; + default: + return "未知"; } } } diff --git a/src/main/java/com/zeodao/reminder/service/ZentaoApiService.java b/src/main/java/com/zeodao/reminder/service/ZentaoApiService.java index c087d19..5b1e117 100644 --- a/src/main/java/com/zeodao/reminder/service/ZentaoApiService.java +++ b/src/main/java/com/zeodao/reminder/service/ZentaoApiService.java @@ -39,6 +39,7 @@ public class ZentaoApiService { private static final Logger logger = LoggerFactory.getLogger(ZentaoApiService.class); private final ObjectMapper objectMapper = new ObjectMapper(); + private final Map sessionCache = new HashMap<>(); /** @@ -211,7 +212,8 @@ public class ZentaoApiService { if (rootNode.has("data")) { JsonNode dataNode = rootNode.get("data"); return objectMapper.convertValue( - dataNode, new TypeReference>() {}); + dataNode, new TypeReference>() { + }); } } } diff --git a/src/main/java/com/zeodao/reminder/service/ZentaoTaskReminderService.java b/src/main/java/com/zeodao/reminder/service/ZentaoTaskReminderService.java index 98fff8e..1de9250 100644 --- a/src/main/java/com/zeodao/reminder/service/ZentaoTaskReminderService.java +++ b/src/main/java/com/zeodao/reminder/service/ZentaoTaskReminderService.java @@ -144,10 +144,10 @@ public class ZentaoTaskReminderService { * 构建统一的项目状态提醒消息(包含任务和BUG) */ private String buildProjectStatusMessage(TaskReminderConfig.Group group, - List incompleteTasks, - List unresolvedBugs, - ProjectInfo projectInfo, - List mentionedMobiles) { + List incompleteTasks, + List unresolvedBugs, + ProjectInfo projectInfo, + List mentionedMobiles) { StringBuilder message = new StringBuilder(); // 消息头部 @@ -194,7 +194,7 @@ public class ZentaoTaskReminderService { for (ZentaoTask task : items.tasks) { String statusIcon = task.isOverdue() ? "🔴" : "⚪"; message.append("- ").append(statusIcon).append(" [任务").append(task.getId()).append("] ") - .append(task.getName()); + .append(task.getName()); if (task.getDeadline() != null && !task.getDeadline().isEmpty() && !"0000-00-00".equals(task.getDeadline())) { message.append(" (").append(task.getDeadline()).append(")"); @@ -206,7 +206,7 @@ public class ZentaoTaskReminderService { for (ZentaoBug bug : items.bugs) { String statusIcon = bug.isOverdue() ? "🔴" : "🐛"; message.append("- ").append(statusIcon).append(" [BUG").append(bug.getId()).append("] ") - .append(bug.getTitle()); + .append(bug.getTitle()); if (bug.getSeverity() != null && !bug.getSeverity().isEmpty()) { message.append(" [").append(bug.getSeverityDesc()).append("]"); } @@ -277,6 +277,7 @@ public class ZentaoTaskReminderService { */ private static class ProjectItems { List tasks = new ArrayList<>(); + List bugs = new ArrayList<>(); } @@ -284,10 +285,10 @@ public class ZentaoTaskReminderService { * 构建任务提醒消息(保留原方法以兼容性) */ private String buildTaskReminderMessage(TaskReminderConfig.Group group, - Map> tasksByAssignee, - List allTasks, - ProjectInfo projectInfo, - List mentionedMobiles) { + Map> tasksByAssignee, + List allTasks, + ProjectInfo projectInfo, + List mentionedMobiles) { StringBuilder message = new StringBuilder(); // 简化消息头部 @@ -323,7 +324,7 @@ public class ZentaoTaskReminderService { String statusIcon = task.isOverdue() ? "🔴" : "⚪"; message.append("- ").append(statusIcon).append(" [").append(task.getId()).append("] ") - .append(task.getName()); + .append(task.getName()); // 截止日期 if (task.getDeadline() != null && !task.getDeadline().isEmpty() && @@ -346,10 +347,10 @@ public class ZentaoTaskReminderService { * 构建BUG提醒消息 */ private String buildBugReminderMessage(TaskReminderConfig.Group group, - Map> bugsByAssignee, - List allBugs, - ProjectInfo projectInfo, - List mentionedMobiles) { + Map> bugsByAssignee, + List allBugs, + ProjectInfo projectInfo, + List mentionedMobiles) { StringBuilder message = new StringBuilder(); // 简化消息头部 @@ -385,7 +386,7 @@ public class ZentaoTaskReminderService { String statusIcon = bug.isOverdue() ? "🔴" : "🐛"; message.append("- ").append(statusIcon).append(" [").append(bug.getId()).append("] ") - .append(bug.getTitle()); + .append(bug.getTitle()); // 严重程度 if (bug.getSeverity() != null && !bug.getSeverity().isEmpty()) { @@ -458,7 +459,6 @@ public class ZentaoTaskReminderService { } - /** * 获取任务详情(用于测试) */ diff --git a/src/main/java/com/zeodao/reminder/strategy/ReminderHandler.java b/src/main/java/com/zeodao/reminder/strategy/ReminderHandler.java index 1ace8ab..06708f9 100644 --- a/src/main/java/com/zeodao/reminder/strategy/ReminderHandler.java +++ b/src/main/java/com/zeodao/reminder/strategy/ReminderHandler.java @@ -16,7 +16,7 @@ public interface ReminderHandler { /** * 判断是否支持处理指定的提醒类型 * - * @param scheduleType 提醒类型 + * @param scheduleType 提醒类型 * @param taskSystemType 任务系统类型 * @return 是否支持 */ diff --git a/src/main/java/com/zeodao/reminder/strategy/ReminderHandlerFactory.java b/src/main/java/com/zeodao/reminder/strategy/ReminderHandlerFactory.java index 6c47a91..2d53960 100644 --- a/src/main/java/com/zeodao/reminder/strategy/ReminderHandlerFactory.java +++ b/src/main/java/com/zeodao/reminder/strategy/ReminderHandlerFactory.java @@ -27,7 +27,7 @@ public class ReminderHandlerFactory { /** * 获取合适的提醒处理器 * - * @param scheduleType 提醒类型 + * @param scheduleType 提醒类型 * @param taskSystemType 任务系统类型 * @return 提醒处理器,如果没有找到则返回null */ @@ -49,7 +49,7 @@ public class ReminderHandlerFactory { * 获取合适的提醒处理器(字符串参数版本,用于兼容) * * @param scheduleTypeCode 提醒类型代码 - * @param taskSystemCode 任务系统类型代码 + * @param taskSystemCode 任务系统类型代码 * @return 提醒处理器,如果没有找到则返回null */ public ReminderHandler getHandler(String scheduleTypeCode, String taskSystemCode) { diff --git a/src/main/java/com/zeodao/reminder/strategy/TextReminderHandler.java b/src/main/java/com/zeodao/reminder/strategy/TextReminderHandler.java index 6916b73..f54755a 100644 --- a/src/main/java/com/zeodao/reminder/strategy/TextReminderHandler.java +++ b/src/main/java/com/zeodao/reminder/strategy/TextReminderHandler.java @@ -35,11 +35,7 @@ public class TextReminderHandler implements ReminderHandler { logger.info("处理文本提醒 - 群组: {}, 类型: {}", group.getName(), scheduleType.getDescription()); // 生成带格式的提醒消息 - String message = wechatWebhookService.createTaskReminderMessage( - group.getId(), - schedule.getMessage(), - scheduleType.getDescription() - ); + String message = wechatWebhookService.createTaskReminderMessage(group.getId(), schedule.getMessage(), scheduleType.getDescription()); // 发送消息 boolean success = wechatWebhookService.sendMarkdownMessage(group.getId(), message); diff --git a/src/main/java/com/zeodao/reminder/util/HolidayUtil.java b/src/main/java/com/zeodao/reminder/util/HolidayUtil.java index 687a425..66298d5 100644 --- a/src/main/java/com/zeodao/reminder/util/HolidayUtil.java +++ b/src/main/java/com/zeodao/reminder/util/HolidayUtil.java @@ -31,7 +31,6 @@ public class HolidayUtil { } - /** * 初始化2025年节假日 * 根据国务院办公厅2024年11月12日发布的《关于2025年部分节假日安排的通知》