feat: 群通知增加处理人信息和@功能

- 任务指派时发送群通知并@被指定的设计师
- 子任务组指派时发送群通知并@被指定的设计师
- 任务驳回时如果有处理人发送群通知并@处理人
- 子任务组驳回时发送群通知并@所有处理人
- 钉钉机器人支持通过手机号@群成员
This commit is contained in:
Your Name 2026-01-04 08:30:03 +08:00
parent 3733713e5c
commit d0cb8e800f
3 changed files with 198 additions and 2 deletions

View File

@ -259,6 +259,16 @@ public class DingTalkService {
* 发送机器人消息
*/
public boolean sendRobotMessage(String title, String content) {
return sendRobotMessage(title, content, null);
}
/**
* 发送机器人消息,支持@指定人(通过手机号)
* @param title 消息标题
* @param content 消息内容
* @param atMobiles 要@的手机号列表,null或空表示不@任何人
*/
public boolean sendRobotMessage(String title, String content, List<String> atMobiles) {
DingTalkConfig config = getConfig();
if (config == null || config.getRobotWebhook() == null) {
log.warn("钉钉机器人未配置");
@ -281,6 +291,15 @@ public class DingTalkService {
markdown.put("title", title);
markdown.put("text", "### " + title + "\n\n" + content);
message.put("markdown", markdown);
// 添加@人功能
if (atMobiles != null && !atMobiles.isEmpty()) {
Map<String, Object> at = new HashMap<>();
at.put("atMobiles", atMobiles);
at.put("isAtAll", false);
message.put("at", at);
log.info("群消息将@手机号: {}", atMobiles);
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

View File

@ -184,6 +184,34 @@ public class TaskApprovalService {
"task_reject",
taskId
);
// 如果任务有指定的处理人,发送群通知告知驳回
if (task.getReceiverId() != null) {
try {
com.designhub.entity.User receiver = userMapper.selectById(task.getReceiverId());
if (receiver != null) {
String title = "任务已驳回";
StringBuilder content = new StringBuilder();
content.append("-------------------------------- \n");
content.append(" 【 任 务 已 驳 回 】 \n");
content.append("-------------------------------- \n\n");
content.append("任务名称:").append(task.getTitle()).append(" \n");
content.append("任务编号:").append(task.getTaskNo()).append(" \n");
content.append("原处理人:").append(receiver.getRealName()).append(" \n");
content.append("驳回原因:").append(reason).append(" \n");
content.append(" \n");
content.append("--------------------------------");
java.util.List<String> atMobiles = receiver.getPhone() != null ?
java.util.Arrays.asList(receiver.getPhone()) : null;
dingTalkService.sendRobotMessage(title, content.toString(), atMobiles);
}
} catch (Exception e) {
log.error("发送任务驳回群通知失败", e);
}
}
log.info("需求部门负责人驳回任务,任务ID:{},审核人:{}", taskId, approverId);
}
@ -268,9 +296,47 @@ public class TaskApprovalService {
}
logApproval(taskId, approverId, 2, "approve", logComment);
// 如果指定了接收人,发送通知
// 发送钉钉群通知
if (assignedReceiverId != null) {
log.info("任务【{}】已指定给设计师", task.getTitle());
// 指定了设计师,发送群通知并@该设计师
log.info("任务【{}】已指定给设计师,准备发送钉钉群通知", task.getTitle());
try {
com.designhub.entity.User receiver = userMapper.selectById(assignedReceiverId);
String receiverName = receiver != null ? receiver.getRealName() : "未知";
String receiverPhone = receiver != null ? receiver.getPhone() : null;
String title = "任务已指派";
StringBuilder content = new StringBuilder();
content.append("-------------------------------- \n");
content.append(" 【 任 务 已 指 派 】 \n");
content.append("-------------------------------- \n\n");
content.append("任务名称:").append(task.getTitle()).append(" \n");
content.append("任务编号:").append(task.getTaskNo()).append(" \n");
content.append("任务积分:").append(task.getScore()).append(" 分 \n");
content.append("指派给:").append(receiverName).append(" \n");
if (task.getEstimatedHours() != null) {
content.append("预估工时:").append(task.getEstimatedHours().intValue()).append(" 小时 \n");
}
if (task.getPublisherName() != null && !task.getPublisherName().isEmpty()) {
content.append("发起人:").append(task.getPublisherName()).append(" \n");
}
content.append(" \n");
content.append("-------------------------------- \n");
content.append("请尽快处理!qd.yydd.ai \n");
content.append("--------------------------------");
// 发送群通知并@指定的设计师
java.util.List<String> atMobiles = receiverPhone != null ?
java.util.Arrays.asList(receiverPhone) : null;
dingTalkService.sendRobotMessage(title, content.toString(), atMobiles);
log.info("任务指派群通知已发送,@手机号: {}", receiverPhone);
} catch (Exception e) {
log.error("发送任务指派群通知失败", e);
}
} else {
log.info("任务【{}】已发布到任务大厅,准备发送钉钉群通知", task.getTitle());
// 任务发布到大厅,发送钉钉群机器人通知
@ -409,6 +475,34 @@ public class TaskApprovalService {
"task_reject",
taskId
);
// 如果任务有指定的处理人,发送群通知告知驳回
if (task.getReceiverId() != null) {
try {
com.designhub.entity.User receiver = userMapper.selectById(task.getReceiverId());
if (receiver != null) {
String title = "任务已驳回";
StringBuilder content = new StringBuilder();
content.append("-------------------------------- \n");
content.append(" 【 任 务 已 驳 回 】 \n");
content.append("-------------------------------- \n\n");
content.append("任务名称:").append(task.getTitle()).append(" \n");
content.append("任务编号:").append(task.getTaskNo()).append(" \n");
content.append("原处理人:").append(receiver.getRealName()).append(" \n");
content.append("驳回原因:").append(reason).append(" \n");
content.append(" \n");
content.append("--------------------------------");
java.util.List<String> atMobiles = receiver.getPhone() != null ?
java.util.Arrays.asList(receiver.getPhone()) : null;
dingTalkService.sendRobotMessage(title, content.toString(), atMobiles);
}
} catch (Exception e) {
log.error("发送任务驳回群通知失败", e);
}
}
log.info("接单部门负责人驳回任务,任务ID:{},审核人:{}", taskId, approverId);
}

View File

@ -502,6 +502,40 @@ public class TaskItemService {
notification.setPriority(2);
notification.setPushDingtalk(1); // 推送到钉钉
notificationService.sendNotification(notification);
// 发送钉钉群通知并@指定的设计师
try {
int totalScore = groupItems.stream().mapToInt(item -> item.getTotalScore() != null ? item.getTotalScore() : 0).sum();
String title = "子任务组已指派";
StringBuilder content = new StringBuilder();
content.append("-------------------------------- \n");
content.append(" 【 子 任 务 组 已 指 派 】 \n");
content.append("-------------------------------- \n\n");
content.append("主任务:").append(mainTask.getTitle()).append(" \n");
content.append("任务编号:").append(mainTask.getTaskNo()).append(" \n");
content.append("任务组:第 ").append(groupNo).append(" 组 \n");
content.append("子任务数量:").append(groupItems.size()).append(" 个 \n");
content.append("总积分:").append(totalScore).append(" 分 \n");
content.append("指派给:").append(receiver.getRealName()).append(" \n");
if (mainTask.getPublisherName() != null && !mainTask.getPublisherName().isEmpty()) {
content.append("发起人:").append(mainTask.getPublisherName()).append(" \n");
}
content.append(" \n");
content.append("-------------------------------- \n");
content.append("请尽快处理!qd.yydd.ai \n");
content.append("--------------------------------");
// @指定的设计师
java.util.List<String> atMobiles = receiver.getPhone() != null ?
java.util.Arrays.asList(receiver.getPhone()) : null;
dingTalkService.sendRobotMessage(title, content.toString(), atMobiles);
log.info("子任务组指派群通知已发送,@手机号: {}", receiver.getPhone());
} catch (Exception e) {
log.error("发送子任务组指派群通知失败", e);
}
log.info("第 {} 组 {} 个子任务已指派给设计师 {}", groupNo, groupItems.size(), receiver.getRealName());
} else {
@ -653,6 +687,55 @@ public class TaskItemService {
notification.setPushDingtalk(1); // 推送到钉钉
notificationService.sendNotification(notification);
}
// 6. 查找该任务组中有处理人的子任务,发送群通知@处理人
try {
List<TaskItem> groupItems = taskItemMapper.selectList(
new LambdaQueryWrapper<TaskItem>()
.eq(TaskItem::getTaskId, taskId)
.eq(TaskItem::getGroupNo, groupNo)
);
// 收集所有处理人的手机号
java.util.Set<String> atMobiles = new java.util.HashSet<>();
java.util.Set<String> receiverNames = new java.util.HashSet<>();
for (TaskItem item : groupItems) {
if (item.getReceiverId() != null) {
com.designhub.entity.User receiver = userMapper.selectById(item.getReceiverId());
if (receiver != null) {
if (receiver.getPhone() != null) {
atMobiles.add(receiver.getPhone());
}
if (receiver.getRealName() != null) {
receiverNames.add(receiver.getRealName());
}
}
}
}
// 如果有处理人,发送群通知
if (!receiverNames.isEmpty()) {
String title = "子任务组已驳回";
StringBuilder content = new StringBuilder();
content.append("-------------------------------- \n");
content.append(" 【 子 任 务 组 已 驳 回 】 \n");
content.append("-------------------------------- \n\n");
content.append("主任务:").append(mainTask.getTitle()).append(" \n");
content.append("任务编号:").append(mainTask.getTaskNo()).append(" \n");
content.append("任务组:第 ").append(groupNo).append(" 组 \n");
content.append("原处理人:").append(String.join("、", receiverNames)).append(" \n");
content.append("驳回原因:").append(reason).append(" \n");
content.append(" \n");
content.append("--------------------------------");
dingTalkService.sendRobotMessage(title, content.toString(),
atMobiles.isEmpty() ? null : new java.util.ArrayList<>(atMobiles));
}
} catch (Exception e) {
log.error("发送子任务组驳回群通知失败", e);
}
}
/**