package com.designhub.service; import com.designhub.entity.*; import com.designhub.mapper.UserMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.HashSet; import java.util.Set; /** * 任务状态变更通知服务 * 负责在任务状态变化时通知需求人 */ @Service @Slf4j @RequiredArgsConstructor public class TaskStatusNotificationService { private final NotificationService notificationService; private final UserMapper userMapper; private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); /** * 通知需求人:任务已解锁(排队中 → 抢单中) */ @Async public void notifyTaskUnlocked(TaskItem item, Task mainTask) { if (mainTask == null) { log.warn("通知任务解锁失败:主任务为空"); return; } Set demandUserIds = getDemandUserIds(mainTask); if (demandUserIds.isEmpty()) { log.warn("通知任务解锁失败:没有找到需求人"); return; } String content = String.format( "您发布的任务《%s》已完成排队,现已开放设计师抢单。\n" + "任务编号:%s\n" + "发布时间:%s\n" + "设计师正在抢单中,请耐心等待...", mainTask.getTitle(), item.getItemNo(), formatTime(mainTask.getCreateTime()) ); for (Long userId : demandUserIds) { try { Notification notification = new Notification(); notification.setReceiverId(userId); notification.setNotificationType("task_status"); notification.setTitle("📢 任务已开放抢单"); notification.setContent(content); notification.setRelatedId(item.getId()); notification.setRelatedType("task_item"); notification.setPriority(1); // 普通优先级 notification.setPushDingtalk(1); // 推送钉钉 notificationService.sendNotification(notification); log.info("已通知需求人 {} 任务 {} 已解锁开放抢单", userId, item.getItemNo()); } catch (Exception e) { log.error("通知需求人 {} 任务解锁失败: {}", userId, e.getMessage()); } } } /** * 通知需求人:任务已被接单(抢单中 → 进行中) */ @Async public void notifyTaskGrabbed(TaskItem item, Task mainTask, User designer) { if (mainTask == null || designer == null) { log.warn("通知任务接单失败:主任务或设计师信息为空"); return; } Set demandUserIds = getDemandUserIds(mainTask); if (demandUserIds.isEmpty()) { return; } String content = String.format( "您发布的任务《%s》已被设计师接单。\n" + "任务编号:%s\n" + "接单设计师:%s\n" + "预计完成:%s\n" + "如有问题可联系设计师沟通。", mainTask.getTitle(), item.getItemNo(), designer.getRealName(), item.getDeadline() != null ? formatTime(item.getDeadline()) : "待定" ); for (Long userId : demandUserIds) { // 不通知自己(如果设计师就是需求人) if (userId.equals(designer.getId())) { continue; } try { Notification notification = new Notification(); notification.setReceiverId(userId); notification.setNotificationType("task_status"); notification.setTitle("🎉 任务已被接单"); notification.setContent(content); notification.setRelatedId(item.getId()); notification.setRelatedType("task_item"); notification.setPriority(1); notification.setPushDingtalk(1); notificationService.sendNotification(notification); log.info("已通知需求人 {} 任务 {} 已被 {} 接单", userId, item.getItemNo(), designer.getRealName()); } catch (Exception e) { log.error("通知需求人 {} 任务接单失败: {}", userId, e.getMessage()); } } } /** * 通知需求人:任务已完成 */ @Async public void notifyTaskCompleted(TaskItem item, Task mainTask, User designer) { if (mainTask == null || designer == null) { log.warn("通知任务完成失败:主任务或设计师信息为空"); return; } Set demandUserIds = getDemandUserIds(mainTask); if (demandUserIds.isEmpty()) { return; } String content = String.format( "您发布的任务《%s》已完成。\n" + "任务编号:%s\n" + "完成设计师:%s\n" + "完成时间:%s\n" + "请及时查收并确认交付物。", mainTask.getTitle(), item.getItemNo(), designer.getRealName(), formatTime(item.getCompleteTime() != null ? item.getCompleteTime() : LocalDateTime.now()) ); for (Long userId : demandUserIds) { try { Notification notification = new Notification(); notification.setReceiverId(userId); notification.setNotificationType("task_status"); notification.setTitle("✅ 任务已完成"); notification.setContent(content); notification.setRelatedId(item.getId()); notification.setRelatedType("task_item"); notification.setPriority(2); // 重要 notification.setPushDingtalk(1); notificationService.sendNotification(notification); log.info("已通知需求人 {} 任务 {} 已完成", userId, item.getItemNo()); } catch (Exception e) { log.error("通知需求人 {} 任务完成失败: {}", userId, e.getMessage()); } } } /** * 批量通知任务解锁 */ @Async public void batchNotifyTasksUnlocked(java.util.List items, java.util.Map taskMap) { if (items == null || items.isEmpty()) { return; } // 按主任务分组,避免同一任务的多个子任务重复通知 java.util.Map> groupedByTask = items.stream() .collect(java.util.stream.Collectors.groupingBy(TaskItem::getTaskId)); for (java.util.Map.Entry> entry : groupedByTask.entrySet()) { Long taskId = entry.getKey(); java.util.List taskItems = entry.getValue(); Task mainTask = taskMap.get(taskId); if (mainTask == null) { continue; } Set demandUserIds = getDemandUserIds(mainTask); if (demandUserIds.isEmpty()) { continue; } // 构建通知内容 String itemNos = taskItems.stream() .map(TaskItem::getItemNo) .collect(java.util.stream.Collectors.joining(", ")); String content = String.format( "您发布的任务《%s》有 %d 个子任务已完成排队,现已开放设计师抢单。\n" + "子任务编号:%s\n" + "设计师正在抢单中,请耐心等待...", mainTask.getTitle(), taskItems.size(), itemNos ); for (Long userId : demandUserIds) { try { Notification notification = new Notification(); notification.setReceiverId(userId); notification.setNotificationType("task_status"); notification.setTitle("📢 任务已开放抢单"); notification.setContent(content); notification.setRelatedId(taskId); notification.setRelatedType("task"); notification.setPriority(1); notification.setPushDingtalk(1); notificationService.sendNotification(notification); } catch (Exception e) { log.error("批量通知任务解锁失败: {}", e.getMessage()); } } } } /** * 获取任务的所有需求人(发布者 + 详情填写人 + 一级发起人) */ private Set getDemandUserIds(Task task) { Set userIds = new HashSet<>(); // 发布者 if (task.getPublisherId() != null) { userIds.add(task.getPublisherId()); } // 详情填写人 if (task.getDetailCompleterId() != null) { userIds.add(task.getDetailCompleterId()); } // 一级发起人 if (task.getPrimaryPublisherId() != null) { userIds.add(task.getPrimaryPublisherId()); } return userIds; } /** * 格式化时间 */ private String formatTime(LocalDateTime time) { if (time == null) { return "未知"; } return time.format(DATE_TIME_FORMATTER); } }