298 lines
11 KiB
Java
298 lines
11 KiB
Java
package com.zeodao.reminder.service;
|
||
|
||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||
import com.zeodao.reminder.config.TaskReminderConfig;
|
||
import org.apache.http.client.config.RequestConfig;
|
||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||
import org.apache.http.client.methods.HttpPost;
|
||
import org.apache.http.entity.StringEntity;
|
||
import org.apache.http.impl.client.CloseableHttpClient;
|
||
import org.apache.http.impl.client.HttpClients;
|
||
import org.apache.http.util.EntityUtils;
|
||
import org.slf4j.Logger;
|
||
import org.slf4j.LoggerFactory;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.stereotype.Service;
|
||
|
||
import java.io.IOException;
|
||
import java.nio.charset.StandardCharsets;
|
||
import java.time.LocalDateTime;
|
||
import java.time.format.DateTimeFormatter;
|
||
import java.util.HashMap;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
|
||
/**
|
||
* 企业微信Webhook服务
|
||
*
|
||
* @author Zeodao
|
||
* @version 1.0.0
|
||
*/
|
||
@Service
|
||
public class WechatWebhookService {
|
||
|
||
private static final Logger logger = LoggerFactory.getLogger(WechatWebhookService.class);
|
||
|
||
@Autowired
|
||
private TaskReminderConfig taskReminderConfig;
|
||
|
||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||
|
||
/**
|
||
* 发送文本消息到指定群组
|
||
*
|
||
* @param groupId 群组ID
|
||
* @param message 消息内容
|
||
* @return 是否发送成功
|
||
*/
|
||
public boolean sendTextMessage(String groupId, String message) {
|
||
try {
|
||
TaskReminderConfig.Group group = taskReminderConfig.getGroupById(groupId);
|
||
if (group == null) {
|
||
logger.error("未找到群组配置: {}", groupId);
|
||
return false;
|
||
}
|
||
|
||
Map<String, Object> messageBody = createTextMessage(message);
|
||
return sendMessage(group.getWebhook().getUrl(), messageBody);
|
||
} catch (Exception e) {
|
||
logger.error("发送企业微信消息失败, 群组: {}", groupId, e);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 发送Markdown格式消息到指定群组
|
||
*
|
||
* @param groupId 群组ID
|
||
* @param content Markdown内容
|
||
* @return 是否发送成功
|
||
*/
|
||
public boolean sendMarkdownMessage(String groupId, String content) {
|
||
try {
|
||
TaskReminderConfig.Group group = taskReminderConfig.getGroupById(groupId);
|
||
if (group == null) {
|
||
logger.error("未找到群组配置: {}", groupId);
|
||
return false;
|
||
}
|
||
|
||
Map<String, Object> messageBody = createMarkdownMessage(content);
|
||
return sendMessage(group.getWebhook().getUrl(), messageBody);
|
||
} catch (Exception e) {
|
||
logger.error("发送企业微信Markdown消息失败, 群组: {}", groupId, e);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 兼容旧版本的方法 - 发送到第一个启用的群组
|
||
*/
|
||
@Deprecated
|
||
public boolean sendMarkdownMessage(String content) {
|
||
List<TaskReminderConfig.Group> enabledGroups = taskReminderConfig.getEnabledGroups();
|
||
if (enabledGroups.isEmpty()) {
|
||
logger.error("没有启用的群组配置");
|
||
return false;
|
||
}
|
||
|
||
return sendMarkdownMessage(enabledGroups.get(0).getId(), content);
|
||
}
|
||
|
||
/**
|
||
* 创建文本消息体
|
||
*/
|
||
private Map<String, Object> createTextMessage(String content) {
|
||
Map<String, Object> message = new HashMap<>();
|
||
message.put("msgtype", "text");
|
||
|
||
Map<String, Object> text = new HashMap<>();
|
||
text.put("content", content);
|
||
message.put("text", text);
|
||
|
||
return message;
|
||
}
|
||
|
||
/**
|
||
* 创建Markdown消息体
|
||
*/
|
||
private Map<String, Object> createMarkdownMessage(String content) {
|
||
Map<String, Object> message = new HashMap<>();
|
||
message.put("msgtype", "markdown");
|
||
|
||
Map<String, Object> markdown = new HashMap<>();
|
||
markdown.put("content", content);
|
||
message.put("markdown", markdown);
|
||
|
||
return message;
|
||
}
|
||
|
||
/**
|
||
* 发送消息到企业微信
|
||
*/
|
||
private boolean sendMessage(String webhookUrl, Map<String, Object> messageBody) throws IOException {
|
||
int timeout = taskReminderConfig.getGlobal().getTimeout();
|
||
|
||
logger.info("准备发送消息到企业微信,URL: {}", webhookUrl);
|
||
|
||
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
|
||
HttpPost httpPost = new HttpPost(webhookUrl);
|
||
|
||
// 设置请求配置
|
||
RequestConfig requestConfig = RequestConfig.custom()
|
||
.setConnectTimeout(timeout)
|
||
.setSocketTimeout(timeout)
|
||
.setConnectionRequestTimeout(timeout)
|
||
.build();
|
||
httpPost.setConfig(requestConfig);
|
||
|
||
// 设置请求头
|
||
httpPost.setHeader("Content-Type", "application/json; charset=utf-8");
|
||
|
||
// 设置请求体
|
||
String jsonBody = objectMapper.writeValueAsString(messageBody);
|
||
StringEntity entity = new StringEntity(jsonBody, StandardCharsets.UTF_8);
|
||
httpPost.setEntity(entity);
|
||
|
||
logger.debug("发送消息内容: {}", jsonBody);
|
||
|
||
// 执行请求
|
||
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
|
||
int statusCode = response.getStatusLine().getStatusCode();
|
||
String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
|
||
|
||
if (statusCode == 200) {
|
||
logger.info("企业微信消息发送成功,响应: {}", responseBody);
|
||
return true;
|
||
} else {
|
||
logger.error("企业微信消息发送失败,状态码: {}, 响应: {}", statusCode, responseBody);
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 创建带时间戳的任务提醒消息
|
||
*/
|
||
public String createTaskReminderMessage(String groupId, String baseMessage, String timeType) {
|
||
TaskReminderConfig.Group group = taskReminderConfig.getGroupById(groupId);
|
||
if (group == null) {
|
||
logger.error("未找到群组配置: {}", groupId);
|
||
return baseMessage;
|
||
}
|
||
|
||
LocalDateTime now = LocalDateTime.now();
|
||
String timestamp = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||
String dayOfWeek = getDayOfWeekInChinese(now.getDayOfWeek().getValue());
|
||
|
||
StringBuilder message = new StringBuilder();
|
||
|
||
// 根据任务管理系统类型生成不同的标题和操作指引
|
||
String systemName = getTaskSystemDisplayName(group.getTaskSystem());
|
||
String systemIcon = getTaskSystemIcon(group.getTaskSystem());
|
||
|
||
message.append("## ").append(systemIcon).append(" ").append(systemName).append("任务状态提醒\n\n");
|
||
message.append("**⏰ 时间:** ").append(timestamp).append(" (").append(dayOfWeek).append(")\n");
|
||
message.append("**📝 提醒类型:** ").append(timeType).append("\n\n");
|
||
message.append("### 📢 重要提醒\n");
|
||
message.append(baseMessage).append("\n\n");
|
||
message.append("### 🔗 操作指引\n");
|
||
message.append(getTaskSystemInstructions(group.getTaskSystem()));
|
||
message.append("---\n");
|
||
message.append("💡 **温馨提示:** 及时更新任务状态有助于团队协作和项目管理");
|
||
|
||
return message.toString();
|
||
}
|
||
|
||
/**
|
||
* 兼容旧版本的方法
|
||
*/
|
||
@Deprecated
|
||
public String createTaskReminderMessage(String baseMessage, String timeType) {
|
||
List<TaskReminderConfig.Group> enabledGroups = taskReminderConfig.getEnabledGroups();
|
||
if (enabledGroups.isEmpty()) {
|
||
return baseMessage;
|
||
}
|
||
return createTaskReminderMessage(enabledGroups.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) {
|
||
switch (taskSystem.toLowerCase()) {
|
||
case "zentao": return "📋";
|
||
case "smartsheet": return "📊";
|
||
case "jira": return "🎯";
|
||
case "trello": return "📌";
|
||
case "asana": return "✅";
|
||
case "notion": return "📝";
|
||
default: return "📋";
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取任务管理系统的操作指引
|
||
*/
|
||
private String getTaskSystemInstructions(String taskSystem) {
|
||
switch (taskSystem.toLowerCase()) {
|
||
case "zentao":
|
||
return "1. 登录禅道系统\n" +
|
||
"2. 查看分配给自己的任务\n" +
|
||
"3. 更新任务状态和进度\n" +
|
||
"4. 添加必要的工作日志\n\n";
|
||
case "smartsheet":
|
||
return "1. 打开智能表格\n" +
|
||
"2. 找到自己负责的任务行\n" +
|
||
"3. 更新任务状态和完成百分比\n" +
|
||
"4. 添加备注说明进展情况\n\n";
|
||
case "jira":
|
||
return "1. 登录Jira系统\n" +
|
||
"2. 查看分配给自己的Issue\n" +
|
||
"3. 更新Issue状态\n" +
|
||
"4. 记录工作日志和时间\n\n";
|
||
case "trello":
|
||
return "1. 打开Trello看板\n" +
|
||
"2. 找到自己的任务卡片\n" +
|
||
"3. 移动卡片到对应状态列\n" +
|
||
"4. 添加评论记录进展\n\n";
|
||
default:
|
||
return "1. 登录任务管理系统\n" +
|
||
"2. 查看分配给自己的任务\n" +
|
||
"3. 更新任务状态和进度\n" +
|
||
"4. 添加必要的工作记录\n\n";
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取中文星期
|
||
*/
|
||
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 "未知";
|
||
}
|
||
}
|
||
}
|