增加环境变量配置,去除全局无用开关

This commit is contained in:
dengqichen 2025-05-30 11:20:24 +08:00
parent 48333f5b4a
commit 89ccf9d555
10 changed files with 156 additions and 154 deletions

5
.gitignore vendored
View File

@ -54,11 +54,6 @@ buildNumber.properties
ehthumbs.db ehthumbs.db
Thumbs.db Thumbs.db
# Spring Boot
application-local.yml
application-dev.yml
application-prod.yml
# Temporary files # Temporary files
*.tmp *.tmp
*.temp *.temp

View File

@ -1,5 +1,6 @@
package com.zeodao.reminder.config; package com.zeodao.reminder.config;
import com.zeodao.reminder.enums.TaskSystemType;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -65,7 +66,7 @@ public class TaskReminderConfig {
private String id; private String id;
private String name; private String name;
private Webhook webhook = new Webhook(); private Webhook webhook = new Webhook();
private String taskSystem; private TaskSystemType taskSystem;
private Map<String, Schedule> schedules = new HashMap<>(); private Map<String, Schedule> schedules = new HashMap<>();
private Zentao zentao = new Zentao(); private Zentao zentao = new Zentao();
@ -95,14 +96,28 @@ public class TaskReminderConfig {
this.webhook = webhook; this.webhook = webhook;
} }
public String getTaskSystem() { public TaskSystemType getTaskSystem() {
return taskSystem; return taskSystem;
} }
public void setTaskSystem(String taskSystem) { public void setTaskSystem(TaskSystemType taskSystem) {
this.taskSystem = taskSystem; this.taskSystem = taskSystem;
} }
/**
* 设置任务系统类型字符串版本用于配置文件兼容
*/
public void setTaskSystem(String taskSystemCode) {
this.taskSystem = TaskSystemType.fromCode(taskSystemCode);
}
/**
* 获取任务系统代码字符串版本用于向后兼容
*/
public String getTaskSystemCode() {
return taskSystem != null ? taskSystem.getCode() : null;
}
public Map<String, Schedule> getSchedules() { public Map<String, Schedule> getSchedules() {
return schedules; return schedules;
} }

View File

@ -1,6 +1,7 @@
package com.zeodao.reminder.controller; package com.zeodao.reminder.controller;
import com.zeodao.reminder.config.TaskReminderConfig; import com.zeodao.reminder.config.TaskReminderConfig;
import com.zeodao.reminder.enums.TaskSystemType;
import com.zeodao.reminder.model.ZentaoTask; import com.zeodao.reminder.model.ZentaoTask;
import com.zeodao.reminder.model.ZentaoBug; import com.zeodao.reminder.model.ZentaoBug;
import com.zeodao.reminder.scheduler.DynamicTaskScheduler; import com.zeodao.reminder.scheduler.DynamicTaskScheduler;
@ -239,7 +240,7 @@ public class TaskReminderController {
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
} }
if (!"zentao".equals(group.getTaskSystem())) { if (group.getTaskSystem() != TaskSystemType.ZENTAO) {
response.put("success", false); response.put("success", false);
response.put("message", "该群组不是禅道类型"); response.put("message", "该群组不是禅道类型");
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
@ -274,7 +275,7 @@ public class TaskReminderController {
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
} }
if (!"zentao".equals(group.getTaskSystem())) { if (group.getTaskSystem() != TaskSystemType.ZENTAO) {
response.put("success", false); response.put("success", false);
response.put("message", "该群组不是禅道类型"); response.put("message", "该群组不是禅道类型");
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
@ -307,7 +308,7 @@ public class TaskReminderController {
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
} }
if (!"zentao".equals(group.getTaskSystem())) { if (group.getTaskSystem() != TaskSystemType.ZENTAO) {
response.put("success", false); response.put("success", false);
response.put("message", "该群组不是禅道类型"); response.put("message", "该群组不是禅道类型");
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
@ -342,7 +343,7 @@ public class TaskReminderController {
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
} }
if (!"zentao".equals(group.getTaskSystem())) { if (group.getTaskSystem() != TaskSystemType.ZENTAO) {
response.put("success", false); response.put("success", false);
response.put("message", "该群组不是禅道类型"); response.put("message", "该群组不是禅道类型");
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
@ -375,7 +376,7 @@ public class TaskReminderController {
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
} }
if (!"zentao".equals(group.getTaskSystem())) { if (group.getTaskSystem() != TaskSystemType.ZENTAO) {
response.put("success", false); response.put("success", false);
response.put("message", "该群组不是禅道类型"); response.put("message", "该群组不是禅道类型");
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
@ -414,7 +415,7 @@ public class TaskReminderController {
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
} }
if (!"zentao".equals(group.getTaskSystem())) { if (group.getTaskSystem() != TaskSystemType.ZENTAO) {
response.put("success", false); response.put("success", false);
response.put("message", "该群组不是禅道类型"); response.put("message", "该群组不是禅道类型");
return ResponseEntity.ok(response); return ResponseEntity.ok(response);

View File

@ -2,18 +2,13 @@ package com.zeodao.reminder.service;
import com.zeodao.reminder.config.TaskReminderConfig; import com.zeodao.reminder.config.TaskReminderConfig;
import com.zeodao.reminder.enums.ScheduleType; import com.zeodao.reminder.enums.ScheduleType;
import com.zeodao.reminder.strategy.EnabledChecker;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Comparator;
import java.util.List;
/** /**
* 启用状态检查服务 * 启用状态检查服务
* 使用责任链模式按优先级检查各级启用状态 * 简化版本直接检查提醒类型的启用状态
* *
* @author Zeodao * @author Zeodao
* @version 2.0.0 * @version 2.0.0
@ -23,38 +18,29 @@ public class EnabledCheckService {
private static final Logger logger = LoggerFactory.getLogger(EnabledCheckService.class); private static final Logger logger = LoggerFactory.getLogger(EnabledCheckService.class);
private final List<EnabledChecker> enabledCheckers;
@Autowired
public EnabledCheckService(List<EnabledChecker> enabledCheckers) {
// 按优先级排序
this.enabledCheckers = enabledCheckers.stream()
.sorted(Comparator.comparingInt(EnabledChecker::getPriority))
.toList();
logger.info("初始化启用状态检查器,共 {} 个检查器", this.enabledCheckers.size());
}
/** /**
* 检查群组的特定提醒类型是否启用 * 检查群组的特定提醒类型是否启用
* 使用责任链模式任何一个检查器返回false则整体返回false
* *
* @param group 群组配置 * @param group 群组配置
* @param scheduleType 提醒类型 * @param scheduleType 提醒类型
* @return 是否启用 * @return 是否启用
*/ */
public boolean isReminderEnabled(TaskReminderConfig.Group group, ScheduleType scheduleType) { public boolean isReminderEnabled(TaskReminderConfig.Group group, ScheduleType scheduleType) {
for (EnabledChecker checker : enabledCheckers) { TaskReminderConfig.Schedule schedule = group.getSchedules().get(scheduleType.getCode());
if (!checker.isEnabled(group, scheduleType)) {
logger.debug("检查器 {} 返回false群组: {}, 提醒类型: {}", if (schedule == null) {
checker.getClass().getSimpleName(), group.getName(), scheduleType.getDescription()); logger.debug("群组 {} 未配置 {} 提醒", group.getName(), scheduleType.getDescription());
return false; return false;
} }
boolean enabled = schedule.isEnabled();
if (!enabled) {
logger.debug("群组 {} 的 {} 提醒已禁用", group.getName(), scheduleType.getDescription());
} else {
logger.debug("群组 {} 的 {} 提醒已启用", group.getName(), scheduleType.getDescription());
} }
logger.debug("所有检查器通过,群组: {}, 提醒类型: {} 已启用", return enabled;
group.getName(), scheduleType.getDescription());
return true;
} }
/** /**

View File

@ -72,7 +72,7 @@ public class TaskReminderService {
// 转换字符串类型为枚举类型 // 转换字符串类型为枚举类型
ScheduleType scheduleTypeEnum = ScheduleType.fromCode(scheduleType); ScheduleType scheduleTypeEnum = ScheduleType.fromCode(scheduleType);
TaskSystemType taskSystemTypeEnum = TaskSystemType.fromCode(group.getTaskSystem()); TaskSystemType taskSystemTypeEnum = group.getTaskSystem();
if (scheduleTypeEnum == null) { if (scheduleTypeEnum == null) {
logger.error("无效的提醒类型: {}", scheduleType); logger.error("无效的提醒类型: {}", scheduleType);
@ -80,7 +80,7 @@ public class TaskReminderService {
} }
if (taskSystemTypeEnum == null) { if (taskSystemTypeEnum == null) {
logger.error("无效的任务系统类型: {}", group.getTaskSystem()); logger.error("无效的任务系统类型: {}", group.getTaskSystemCode());
return; return;
} }

View File

@ -2,6 +2,7 @@ package com.zeodao.reminder.service;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.zeodao.reminder.config.TaskReminderConfig; import com.zeodao.reminder.config.TaskReminderConfig;
import com.zeodao.reminder.enums.TaskSystemType;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
@ -233,14 +234,15 @@ public class WechatWebhookService {
StringBuilder message = new StringBuilder(); StringBuilder message = new StringBuilder();
// 根据任务管理系统类型生成不同的标题和操作指引 // 根据任务管理系统类型生成不同的标题和操作指引
String systemName = getTaskSystemDisplayName(group.getTaskSystem()); TaskSystemType taskSystemType = group.getTaskSystem();
String systemIcon = getTaskSystemIcon(group.getTaskSystem()); String systemName = taskSystemType != null ? taskSystemType.getDescription() : "任务管理系统";
String systemIcon = getTaskSystemIcon(taskSystemType);
message.append("## ").append(systemIcon).append(" ").append(systemName).append("任务状态提醒\n\n"); message.append("## ").append(systemIcon).append(" ").append(systemName).append("任务状态提醒\n\n");
message.append("⏰ **时间:** ").append(timestamp).append(" (").append(dayOfWeek).append(")\n\n"); message.append("⏰ **时间:** ").append(timestamp).append(" (").append(dayOfWeek).append(")\n\n");
message.append("📢 ").append(baseMessage).append("\n\n"); message.append("📢 ").append(baseMessage).append("\n\n");
message.append("🔗 **操作指引:**\n"); message.append("🔗 **操作指引:**\n");
message.append(getTaskSystemInstructions(group.getTaskSystem())); message.append(getTaskSystemInstructions(taskSystemType));
message.append("💡 及时更新任务状态有助于团队协作和项目管理"); message.append("💡 及时更新任务状态有助于团队协作和项目管理");
return message.toString(); return message.toString();
@ -258,32 +260,23 @@ public class WechatWebhookService {
return createTaskReminderMessage(allGroups.get(0).getId(), baseMessage, timeType); return createTaskReminderMessage(allGroups.get(0).getId(), baseMessage, timeType);
} }
/**
* 获取任务管理系统的显示名称
*/
private String getTaskSystemDisplayName(String taskSystem) {
switch (taskSystem.toLowerCase()) {
case "zentao": return "禅道";
case "smartsheet": return "智能表格";
case "jira": return "Jira";
case "trello": return "Trello";
case "asana": return "Asana";
case "notion": return "Notion";
default: return "任务管理系统";
}
}
/** /**
* 获取任务管理系统的图标 * 获取任务管理系统的图标
*/ */
private String getTaskSystemIcon(String taskSystem) { private String getTaskSystemIcon(TaskSystemType taskSystemType) {
switch (taskSystem.toLowerCase()) { if (taskSystemType == null) {
case "zentao": return "📋"; return "📋";
case "smartsheet": return "📊"; }
case "jira": return "🎯";
case "trello": return "📌"; switch (taskSystemType) {
case "asana": return ""; case ZENTAO: return "📋";
case "notion": return "📝"; case SMARTSHEET: return "📊";
case JIRA: return "🎯";
case TRELLO: return "📌";
case ASANA: return "";
case NOTION: return "📝";
default: return "📋"; default: return "📋";
} }
} }
@ -291,24 +284,31 @@ public class WechatWebhookService {
/** /**
* 获取任务管理系统的操作指引 * 获取任务管理系统的操作指引
*/ */
private String getTaskSystemInstructions(String taskSystem) { private String getTaskSystemInstructions(TaskSystemType taskSystemType) {
switch (taskSystem.toLowerCase()) { if (taskSystemType == null) {
case "zentao": return "1. 登录任务管理系统\n" +
"2. 查看分配给自己的任务\n" +
"3. 更新任务状态和进度\n" +
"4. 添加必要的工作记录\n\n";
}
switch (taskSystemType) {
case ZENTAO:
return "1. 登录禅道系统\n" + return "1. 登录禅道系统\n" +
"2. 查看分配给自己的任务\n" + "2. 查看分配给自己的任务\n" +
"3. 更新任务状态和进度\n" + "3. 更新任务状态和进度\n" +
"4. 添加必要的工作日志\n\n"; "4. 添加必要的工作日志\n\n";
case "smartsheet": case SMARTSHEET:
return "1. 打开智能表格\n" + return "1. 打开智能表格\n" +
"2. 找到自己负责的任务行\n" + "2. 找到自己负责的任务行\n" +
"3. 更新任务状态和完成百分比\n" + "3. 更新任务状态和完成百分比\n" +
"4. 添加备注说明进展情况\n\n"; "4. 添加备注说明进展情况\n\n";
case "jira": case JIRA:
return "1. 登录Jira系统\n" + return "1. 登录Jira系统\n" +
"2. 查看分配给自己的Issue\n" + "2. 查看分配给自己的Issue\n" +
"3. 更新Issue状态\n" + "3. 更新Issue状态\n" +
"4. 记录工作日志和时间\n\n"; "4. 记录工作日志和时间\n\n";
case "trello": case TRELLO:
return "1. 打开Trello看板\n" + return "1. 打开Trello看板\n" +
"2. 找到自己的任务卡片\n" + "2. 找到自己的任务卡片\n" +
"3. 移动卡片到对应状态列\n" + "3. 移动卡片到对应状态列\n" +

View File

@ -1,30 +0,0 @@
package com.zeodao.reminder.strategy;
import com.zeodao.reminder.config.TaskReminderConfig;
import com.zeodao.reminder.enums.ScheduleType;
/**
* 启用状态检查器接口
* 使用策略模式检查不同级别的启用状态
*
* @author Zeodao
* @version 2.0.0
*/
public interface EnabledChecker {
/**
* 检查是否启用
*
* @param group 群组配置
* @param scheduleType 提醒类型
* @return 是否启用
*/
boolean isEnabled(TaskReminderConfig.Group group, ScheduleType scheduleType);
/**
* 获取检查器的优先级数字越小优先级越高
*
* @return 优先级
*/
int getPriority();
}

View File

@ -1,42 +0,0 @@
package com.zeodao.reminder.strategy;
import com.zeodao.reminder.config.TaskReminderConfig;
import com.zeodao.reminder.enums.ScheduleType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 提醒计划级别启用状态检查器
* 检查特定提醒类型是否启用
*
* @author Zeodao
* @version 2.0.0
*/
@Component
public class ScheduleEnabledChecker implements EnabledChecker {
private static final Logger logger = LoggerFactory.getLogger(ScheduleEnabledChecker.class);
@Override
public boolean isEnabled(TaskReminderConfig.Group group, ScheduleType scheduleType) {
TaskReminderConfig.Schedule schedule = group.getSchedules().get(scheduleType.getCode());
if (schedule == null) {
logger.debug("群组 {} 未配置 {} 提醒", group.getName(), scheduleType.getDescription());
return false;
}
boolean enabled = schedule.isEnabled();
if (!enabled) {
logger.debug("群组 {} 的 {} 提醒已禁用", group.getName(), scheduleType.getDescription());
}
return enabled;
}
@Override
public int getPriority() {
return 2; // 次优先级在群组启用的前提下检查具体提醒类型
}
}

View File

@ -15,8 +15,8 @@ task:
# 群组配置列表 # 群组配置列表
groups: groups:
# 禅道团队群 # 禅道团队群
- id: "zentao-team" - id: "chainhub"
name: "禅道开发团队" name: "一站式平台"
webhook: webhook:
url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=614b110b-8957-4be8-95b9-4eca84c15028" url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=614b110b-8957-4be8-95b9-4eca84c15028"
task-system: "zentao" # 任务管理系统类型zentao, smartsheet, jira, trello 等 task-system: "zentao" # 任务管理系统类型zentao, smartsheet, jira, trello 等
@ -45,11 +45,11 @@ task:
overdue-reminder: overdue-reminder:
time: "0 0 10 * * MON-FRI" # 工作日上午10点 time: "0 0 10 * * MON-FRI" # 工作日上午10点
message: "禅道逾期任务提醒" # 这个消息会被系统动态生成包含具体的任务和BUG统计信息 message: "禅道逾期任务提醒" # 这个消息会被系统动态生成包含具体的任务和BUG统计信息
enabled: false # 启用逾期提醒 enabled: true # 启用逾期提醒
# 智能表格团队群 # 智能表格团队群
- id: "smartsheet-team" - id: "longi-scp"
name: "智能表格团队" name: "隆基需求计划"
webhook: webhook:
url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=614b110b-8957-4be8-95b9-4eca84c15028" url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=614b110b-8957-4be8-95b9-4eca84c15028"
task-system: "smartsheet" task-system: "smartsheet"
@ -61,7 +61,7 @@ task:
evening: evening:
time: "0 20 17 * * MON-FRI" # 工作日下午5点20分 time: "0 20 17 * * MON-FRI" # 工作日下午5点20分
message: "下班前提醒:请在智能表格中更新今日工作完成情况,为明天做好准备!" message: "下班前提醒:请在智能表格中更新今日工作完成情况,为明天做好准备!"
enabled: false # 禁用晚上提醒(示例:智能表格团队不需要晚上提醒) enabled: true # 禁用晚上提醒(示例:智能表格团队不需要晚上提醒)
# 日志配置 # 日志配置
logging: logging:

View File

@ -0,0 +1,77 @@
server:
port: 8080
spring:
application:
name: zeodao-task-reminder
# 多群任务提醒配置
task:
reminder:
# 全局默认配置
global:
timeout: 5000 # 超时时间(毫秒)
# 群组配置列表
groups:
# 禅道团队群
- id: "chainhub"
name: "一站式平台"
webhook:
url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=614b110b-8957-4be8-95b9-4eca84c15028"
task-system: "zentao" # 任务管理系统类型zentao, smartsheet, jira, trello 等
# 禅道配置
zentao:
api-url: "https://zentao.iscmtech.com"
username: "admin" # 请替换为实际的禅道用户名
password: "Lianyu!@#~123456" # 请替换为实际的禅道密码
project-id: 38 # 项目ID同时用于获取任务和BUG
kanban-id: 39 # 看板ID看板模式项目需要
# 用户映射:禅道用户名 -> 企业微信手机号(显示使用真实姓名)
user-mapping:
"dengqichen": "18525522818"
"songwei": "15724574541"
# 也可以直接用用户名映射
# "zhangsan": "13600136000"
schedules:
morning:
time: "0 0 9 * * MON-FRI" # 工作日早上9点
message: "早上好!新的一天开始了,请大家及时登录禅道系统刷新今日的任务状态,确保任务进度准确反映当前工作情况。"
enabled: true # 启用早上提醒
evening:
time: "0 30 17 * * MON-FRI" # 工作日下午5:30
message: "下班前提醒:请大家登录禅道系统,及时更新今日任务的完成状态和进度,为明天的工作安排做好准备!"
enabled: true # 启用晚上提醒
overdue-reminder:
time: "0 0 10 * * MON-FRI" # 工作日上午10点
message: "禅道逾期任务提醒" # 这个消息会被系统动态生成包含具体的任务和BUG统计信息
enabled: true # 启用逾期提醒
# 智能表格团队群
- id: "longi-scp"
name: "隆基需求计划"
webhook:
url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=ed54908b-0f58-46b7-beb6-8facca4438d6"
task-system: "smartsheet"
schedules:
morning:
time: "0 50 8 * * MON-FRI" # 工作日早上8点50分
message: "早上好!请大家及时更新智能表格中的任务状态,确保项目进度信息准确无误。"
enabled: true # 启用早上提醒
evening:
time: "0 20 17 * * MON-FRI" # 工作日下午5点20分
message: "下班前提醒:请在智能表格中更新今日工作完成情况,为明天做好准备!"
enabled: true # 禁用晚上提醒(示例:智能表格团队不需要晚上提醒)
# 日志配置
logging:
level:
com.zeodao.reminder: DEBUG
org.springframework.web: INFO
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file:
name: logs/task-reminder.log
max-size: 10MB
max-history: 30