From 9b5407060a7d94bed558fb0a37f08f60d0457dee Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 14 Jan 2026 19:26:14 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=B5=81=E6=B0=B4=E7=BA=BF?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E5=AE=A1=E6=A0=B8=E9=80=9A=E8=BF=87=E5=90=8E?= =?UTF-8?q?=E5=8F=AA=E9=80=9A=E7=9F=A5=E4=B8=80=E4=B8=AA=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E5=B8=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增sendTaskAssignedNotification方法 - 流水线任务审核通过后,遍历第一个部门的所有子任务 - 给每个子任务的设计师都发送钉钉通知 - 每个设计师收到的通知只包含自己负责的任务明细 --- .../service/TaskApprovalService.java | 309 ++++++++++-------- 1 file changed, 173 insertions(+), 136 deletions(-) diff --git a/backend/src/main/java/com/designhub/service/TaskApprovalService.java b/backend/src/main/java/com/designhub/service/TaskApprovalService.java index 905fdb1..327f107 100644 --- a/backend/src/main/java/com/designhub/service/TaskApprovalService.java +++ b/backend/src/main/java/com/designhub/service/TaskApprovalService.java @@ -265,144 +265,34 @@ public class TaskApprovalService { logApproval(taskId, approverId, 2, "approve", logComment); // 发送钉钉通知 - if (finalReceiverId != null) { - // 指定了设计师,发送个人通知和群通知 - log.info("任务【{}】已指定给设计师,准备发送钉钉通知", task.getTitle()); - try { - com.designhub.entity.User receiver = userMapper.selectById(finalReceiverId); - String receiverName = receiver != null ? receiver.getRealName() : "未知"; - String receiverPhone = receiver != null ? receiver.getPhone() : null; - - // 1. 构建统一格式的通知内容(与"新任务发布"模版保持一致) - StringBuilder content = new StringBuilder(); - - // 基本信息 - content.append("**任务名称**:").append(task.getTitle()).append(" \n"); - content.append("**任务编号**:").append(task.getTaskNo()).append(" \n"); - - // 任务详情 - if (task.getBrandName() != null && !task.getBrandName().isEmpty()) { - content.append("**品牌**:").append(task.getBrandName()).append(" \n"); + // 对于流水线任务,需要给第一个部门的所有子任务设计师发送通知 + java.util.Set notifiedReceiverIds = new java.util.HashSet<>(); + + if (task.getIsPipeline() != null && task.getIsPipeline() == 1) { + // 流水线任务:查询第一个部门的所有子任务,给每个设计师发送通知 + List firstDeptItems = taskItemMapper.selectList( + new LambdaQueryWrapper() + .eq(TaskItem::getTaskId, task.getId()) + .eq(TaskItem::getStatus, "in_progress") + .isNotNull(TaskItem::getReceiverId) + ); + + for (TaskItem item : firstDeptItems) { + if (item.getReceiverId() != null && !notifiedReceiverIds.contains(item.getReceiverId())) { + notifiedReceiverIds.add(item.getReceiverId()); + sendTaskAssignedNotification(task, item.getReceiverId(), isPreAssigned); } - if (task.getPlatformName() != null && !task.getPlatformName().isEmpty()) { - content.append("**平台**:").append(task.getPlatformName()).append(" \n"); - } - if (task.getSpuInfo() != null && !task.getSpuInfo().isEmpty()) { - content.append("**SPU**:").append(task.getSpuInfo()).append(" \n"); - } - if (task.getTaskSubType() != null && !task.getTaskSubType().isEmpty()) { - content.append("**任务类型**:").append(task.getTaskSubType()).append(" \n"); - } - - content.append(" \n"); - - // 查询子任务获取任务类型明细 - List taskItems = taskItemMapper.selectList( - new LambdaQueryWrapper() - .eq(TaskItem::getTaskId, task.getId()) - .orderByAsc(TaskItem::getGroupNo) - ); - - if (!taskItems.isEmpty()) { - content.append("**任务明细**: \n"); - for (TaskItem item : taskItems) { - // 通过任务类型ID获取接单部门名称 - String deptName = "未指定"; - if (item.getTaskTypeId() != null) { - try { - DemandType demandType = configService.getDemandTypeById(item.getTaskTypeId()); - if (demandType != null && demandType.getAllowedDeptIds() != null && !demandType.getAllowedDeptIds().isEmpty()) { - String[] deptIds = demandType.getAllowedDeptIds().split(","); - Long firstDeptId = Long.parseLong(deptIds[0].trim()); - Department dept = departmentMapper.selectById(firstDeptId); - if (dept != null) { - deptName = dept.getDeptName(); - } - } - } catch (Exception e) { - log.warn("获取部门名称失败: {}", e.getMessage()); - } - } - - // 格式化工时显示 - String hoursDisplay = formatEstimatedHours(item.getEstimatedHours()); - - content.append(" \n"); - content.append("▸ **").append(deptName).append("** | ") - .append(item.getTotalScore()).append("分 | ") - .append(hoursDisplay).append(" \n"); - - // 解析并显示任务类型明细 - if (item.getTypeDetails() != null && !item.getTypeDetails().isEmpty()) { - try { - @SuppressWarnings("unchecked") - List> typeDetails = - objectMapper.readValue(item.getTypeDetails(), List.class); - for (java.util.Map detail : typeDetails) { - String typeName = String.valueOf(detail.get("typeName")); - Object qtyObj = detail.get("quantity"); - Object scoreObj = detail.get("totalScore"); - int qty = qtyObj instanceof Number ? ((Number) qtyObj).intValue() : 1; - String score = scoreObj != null ? String.valueOf(scoreObj) : "0"; - content.append("  └ ").append(typeName) - .append(" ×").append(qty) - .append(" = ").append(score).append("分 \n"); - } - } catch (Exception e) { - log.warn("解析任务类型明细失败: {}", e.getMessage()); - } - } - } - } else { - // 没有子任务时显示总积分和工时 - content.append("**任务积分**:").append(task.getScore()).append(" 分 \n"); - if (task.getEstimatedHours() != null) { - content.append("**预估工时**:").append(formatEstimatedHours(task.getEstimatedHours())).append(" \n"); - } - } - - content.append(" \n"); - - // 发起人信息 - if (task.getPublisherName() != null && !task.getPublisherName().isEmpty()) { - content.append("**发起人**:").append(task.getPublisherName()).append(" \n"); - } - if (task.getPublisherDeptName() != null && !task.getPublisherDeptName().isEmpty()) { - content.append("**发起部门**:").append(task.getPublisherDeptName()).append(" \n"); - } - - // 指派信息 - content.append("**指派给**:").append(receiverName).append(" \n"); - - content.append(" \n"); - content.append("点击下方按钮查看详情"); - - // 2. 发送个人钉钉通知给设计师 - Notification notification = new Notification(); - notification.setReceiverId(finalReceiverId); - notification.setTitle("任务已指派"); - notification.setContent(content.toString()); - notification.setNotificationType("TASK_ASSIGNED"); - notification.setRelatedType("task"); - notification.setRelatedId(task.getId()); - notification.setPushDingtalk(1); // 推送到钉钉 - notificationService.sendNotification(notification); - log.info("任务指派个人通知已发送给设计师: userId={}", finalReceiverId); - - // 3. 只有非预先指定的任务才发送群通知(预先指定的任务只发送个人通知) - if (!isPreAssigned) { - // 发送群通知并@指定的设计师,使用相同的内容模版 - java.util.List atMobiles = receiverPhone != null ? - java.util.Arrays.asList(receiverPhone) : null; - dingTalkService.sendRobotMessage("任务已指派", content.toString(), atMobiles); - log.info("任务指派群通知已发送,@手机号: {}", receiverPhone); - } else { - log.info("任务【{}】为预先指定任务,只发送个人通知,不发送群通知", task.getTitle()); - } - } catch (Exception e) { - log.error("发送任务指派通知失败", e); } - } else { + log.info("流水线任务【{}】已通知 {} 个设计师", task.getTitle(), notifiedReceiverIds.size()); + } else if (finalReceiverId != null) { + // 普通任务:只通知一个设计师 + sendTaskAssignedNotification(task, finalReceiverId, isPreAssigned); + notifiedReceiverIds.add(finalReceiverId); + log.info("普通任务【{}】已通知设计师: {}", task.getTitle(), finalReceiverId); + } + + // 如果没有指定设计师(发布到大厅),发送群通知 + if (notifiedReceiverIds.isEmpty()) { log.info("任务【{}】已发布到任务大厅,准备发送钉钉群通知", task.getTitle()); // 任务发布到大厅,发送钉钉群机器人通知 // 注意:钉钉Markdown换行需要两个空格+换行符 @@ -906,4 +796,151 @@ public class TaskApprovalService { // WorkHoursCalculator 返回 "--" 表示无效,这里保持 "未设置" 的语义 return "--".equals(formatted) ? "未设置" : formatted; } + + /** + * 发送任务指派通知给设计师 + * @param task 任务 + * @param receiverId 接收人ID + * @param isPreAssigned 是否预先指定 + */ + private void sendTaskAssignedNotification(Task task, Long receiverId, boolean isPreAssigned) { + try { + com.designhub.entity.User receiver = userMapper.selectById(receiverId); + if (receiver == null) { + log.warn("接收人不存在: {}", receiverId); + return; + } + String receiverName = receiver.getRealName(); + String receiverPhone = receiver.getPhone(); + + // 构建通知内容 + StringBuilder content = new StringBuilder(); + + // 基本信息 + content.append("**任务名称**:").append(task.getTitle()).append(" \n"); + content.append("**任务编号**:").append(task.getTaskNo()).append(" \n"); + + // 任务详情 + if (task.getBrandName() != null && !task.getBrandName().isEmpty()) { + content.append("**品牌**:").append(task.getBrandName()).append(" \n"); + } + if (task.getPlatformName() != null && !task.getPlatformName().isEmpty()) { + content.append("**平台**:").append(task.getPlatformName()).append(" \n"); + } + if (task.getSpuInfo() != null && !task.getSpuInfo().isEmpty()) { + content.append("**SPU**:").append(task.getSpuInfo()).append(" \n"); + } + if (task.getTaskSubType() != null && !task.getTaskSubType().isEmpty()) { + content.append("**任务类型**:").append(task.getTaskSubType()).append(" \n"); + } + + content.append(" \n"); + + // 查询该设计师负责的子任务 + List receiverItems = taskItemMapper.selectList( + new LambdaQueryWrapper() + .eq(TaskItem::getTaskId, task.getId()) + .eq(TaskItem::getReceiverId, receiverId) + .orderByAsc(TaskItem::getGroupNo) + ); + + if (!receiverItems.isEmpty()) { + content.append("**您负责的任务明细**: \n"); + for (TaskItem item : receiverItems) { + // 通过任务类型ID获取接单部门名称 + String deptName = "未指定"; + if (item.getTaskTypeId() != null) { + try { + DemandType demandType = configService.getDemandTypeById(item.getTaskTypeId()); + if (demandType != null && demandType.getAllowedDeptIds() != null && !demandType.getAllowedDeptIds().isEmpty()) { + String[] deptIds = demandType.getAllowedDeptIds().split(","); + Long firstDeptId = Long.parseLong(deptIds[0].trim()); + Department dept = departmentMapper.selectById(firstDeptId); + if (dept != null) { + deptName = dept.getDeptName(); + } + } + } catch (Exception e) { + log.warn("获取部门名称失败: {}", e.getMessage()); + } + } + + // 格式化工时显示 + String hoursDisplay = formatEstimatedHours(item.getEstimatedHours()); + + content.append(" \n"); + content.append("▸ **").append(deptName).append("** | ") + .append(item.getTotalScore()).append("分 | ") + .append(hoursDisplay).append(" \n"); + + // 解析并显示任务类型明细 + if (item.getTypeDetails() != null && !item.getTypeDetails().isEmpty()) { + try { + @SuppressWarnings("unchecked") + List> typeDetails = + objectMapper.readValue(item.getTypeDetails(), List.class); + for (java.util.Map detail : typeDetails) { + String typeName = String.valueOf(detail.get("typeName")); + Object qtyObj = detail.get("quantity"); + Object scoreObj = detail.get("totalScore"); + int qty = qtyObj instanceof Number ? ((Number) qtyObj).intValue() : 1; + String score = scoreObj != null ? String.valueOf(scoreObj) : "0"; + content.append("  └ ").append(typeName) + .append(" ×").append(qty) + .append(" = ").append(score).append("分 \n"); + } + } catch (Exception e) { + log.warn("解析任务类型明细失败: {}", e.getMessage()); + } + } + } + } else { + // 没有子任务时显示总积分和工时 + content.append("**任务积分**:").append(task.getScore()).append(" 分 \n"); + if (task.getEstimatedHours() != null) { + content.append("**预估工时**:").append(formatEstimatedHours(task.getEstimatedHours())).append(" \n"); + } + } + + content.append(" \n"); + + // 发起人信息 + if (task.getPublisherName() != null && !task.getPublisherName().isEmpty()) { + content.append("**发起人**:").append(task.getPublisherName()).append(" \n"); + } + if (task.getPublisherDeptName() != null && !task.getPublisherDeptName().isEmpty()) { + content.append("**发起部门**:").append(task.getPublisherDeptName()).append(" \n"); + } + + // 指派信息 + content.append("**指派给**:").append(receiverName).append(" \n"); + + content.append(" \n"); + content.append("点击下方按钮查看详情"); + + // 发送个人钉钉通知给设计师 + Notification notification = new Notification(); + notification.setReceiverId(receiverId); + notification.setTitle("任务已指派"); + notification.setContent(content.toString()); + notification.setNotificationType("TASK_ASSIGNED"); + notification.setRelatedType("task"); + notification.setRelatedId(task.getId()); + notification.setPushDingtalk(1); // 推送到钉钉 + notificationService.sendNotification(notification); + log.info("任务指派个人通知已发送给设计师: userId={}, name={}", receiverId, receiverName); + + // 只有非预先指定的任务才发送群通知(预先指定的任务只发送个人通知) + if (!isPreAssigned) { + java.util.List atMobiles = receiverPhone != null ? + java.util.Arrays.asList(receiverPhone) : null; + dingTalkService.sendRobotMessage("任务已指派", content.toString(), atMobiles); + log.info("任务指派群通知已发送,@手机号: {}", receiverPhone); + } else { + log.info("任务【{}】为预先指定任务,只发送个人通知,不发送群通知", task.getTitle()); + } + } catch (Exception e) { + log.error("发送任务指派通知失败: receiverId={}", receiverId, e); + } + } }