package com.designhub.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.designhub.entity.Department; import com.designhub.entity.Task; import com.designhub.entity.TaskItem; import com.designhub.entity.User; import com.designhub.mapper.DepartmentMapper; import com.designhub.mapper.TaskMapper; import com.designhub.mapper.TaskItemMapper; import com.designhub.mapper.UserMapper; import com.designhub.vo.DesignerStatsVO; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * 设计师统计Service */ @Service @Slf4j @RequiredArgsConstructor public class DesignerService { private final UserMapper userMapper; private final TaskMapper taskMapper; private final TaskItemMapper taskItemMapper; private final DepartmentMapper departmentMapper; /** * 获取所有设计师的统计信息 */ public List getAllDesignerStats() { return getAllDesignerStats(null); } /** * 获取所有设计师的统计信息(支持部门筛选) */ public List getAllDesignerStats(Long deptId) { List targetDeptIds; if (deptId != null) { // 如果指定了部门,获取该部门及其所有子部门 targetDeptIds = getDeptAndChildIds(deptId); log.debug("筛选部门: deptId={}, targetDeptIds={}", deptId, targetDeptIds); } else { // 仅获取接单部门(designer/receiving)的用户 targetDeptIds = departmentMapper.selectList( new LambdaQueryWrapper() .eq(Department::getDeptType, "receiving") .eq(Department::getStatus, 1) ).stream() .map(Department::getId) .collect(Collectors.toList()); } if (targetDeptIds.isEmpty()) { return new ArrayList<>(); } List designers = userMapper.selectList( new LambdaQueryWrapper() .eq(User::getStatus, 1) .in(User::getDeptId, targetDeptIds) ); return designers.stream() .map(this::buildDesignerStats) .collect(Collectors.toList()); } /** * 递归获取部门及其所有子部门ID */ private List getDeptAndChildIds(Long deptId) { List deptIds = new ArrayList<>(); deptIds.add(deptId); List children = departmentMapper.selectList( new LambdaQueryWrapper() .eq(Department::getParentId, deptId) .eq(Department::getStatus, 1) ); for (Department child : children) { deptIds.addAll(getDeptAndChildIds(child.getId())); } return deptIds; } /** * 获取单个设计师的统计信息 */ public DesignerStatsVO getDesignerStats(Long userId) { User user = userMapper.selectById(userId); if (user == null) { return null; } return buildDesignerStats(user); } /** * 获取排行榜数据(支持按月查询) */ public List getLeaderboard(String type, Integer limit, String month) { List stats; // 如果指定了月份,则查询该月份的数据 if (month != null && !month.isEmpty()) { stats = getDesignerStatsByMonth(month); } else { // 否则查询全部数据 stats = getAllDesignerStats(); } // 根据类型排序 switch (type) { case "score": // 积分榜 stats.sort((a, b) -> Integer.compare( b.getTotalScore() != null ? b.getTotalScore() : 0, a.getTotalScore() != null ? a.getTotalScore() : 0 )); break; case "efficiency": // 效率榜(完成率) stats.sort((a, b) -> Double.compare( b.getCompletionRate() != null ? b.getCompletionRate() : 0.0, a.getCompletionRate() != null ? a.getCompletionRate() : 0.0 )); break; case "quality": // 好评榜 stats.sort((a, b) -> { int countCompare = Integer.compare( b.getGoodReviewCount() != null ? b.getGoodReviewCount() : 0, a.getGoodReviewCount() != null ? a.getGoodReviewCount() : 0 ); if (countCompare == 0) { // 好评数相同时,比较平均评分 return Double.compare( b.getAvgRating() != null ? b.getAvgRating() : 0.0, a.getAvgRating() != null ? a.getAvgRating() : 0.0 ); } return countCompare; }); break; case "diligence": // 勤勉榜(总任务数) stats.sort((a, b) -> Integer.compare( b.getTotalTaskCount() != null ? b.getTotalTaskCount() : 0, a.getTotalTaskCount() != null ? a.getTotalTaskCount() : 0 )); break; default: // 默认按积分排序 stats.sort((a, b) -> Integer.compare( b.getTotalScore() != null ? b.getTotalScore() : 0, a.getTotalScore() != null ? a.getTotalScore() : 0 )); } // 限制返回数量 if (limit != null && limit > 0 && stats.size() > limit) { return stats.subList(0, limit); } return stats; } /** * 构建设计师统计信息 */ private DesignerStatsVO buildDesignerStats(User user) { DesignerStatsVO stats = new DesignerStatsVO(); // 基本信息 stats.setUserId(user.getId()); stats.setUserName(user.getRealName()); stats.setAvatar(user.getAvatar()); stats.setDeptName(user.getDeptName()); // 查询任务统计 Long userId = user.getId(); // 总接收任务数(包括主任务和子任务) Long mainTotalCount = taskMapper.selectCount( new LambdaQueryWrapper() .eq(Task::getReceiverId, userId) .eq(Task::getDeleted, 0) ); Long subTotalCount = taskItemMapper.selectCount( new LambdaQueryWrapper() .eq(TaskItem::getReceiverId, userId) ); Integer totalCount = (mainTotalCount != null ? mainTotalCount.intValue() : 0) + (subTotalCount != null ? subTotalCount.intValue() : 0); stats.setTotalTaskCount(totalCount); // 进行中任务数(包括主任务和子任务) Long mainInProgressCount = taskMapper.selectCount( new LambdaQueryWrapper() .eq(Task::getReceiverId, userId) .eq(Task::getStatus, "in_progress") .eq(Task::getDeleted, 0) ); // 同时查询子任务表中进行中的任务数 Long subInProgressCount = taskItemMapper.selectCount( new LambdaQueryWrapper() .eq(TaskItem::getReceiverId, userId) .eq(TaskItem::getStatus, "in_progress") ); Integer inProgressCount = (mainInProgressCount != null ? mainInProgressCount.intValue() : 0) + (subInProgressCount != null ? subInProgressCount.intValue() : 0); stats.setInProgressCount(inProgressCount); log.debug("设计师进行中任务统计: userId={}, mainInProgress={}, subInProgress={}, total={}", userId, mainInProgressCount, subInProgressCount, inProgressCount); // 待接单任务数(队列)- 这里应该是用户已接收但还未开始的任务,实际上应该是0 // 因为一旦接收任务,状态就会变成 in_progress // 队列数可以理解为用户当前可以接的任务数(这个需要从任务大厅查询,这里暂时设为0) stats.setQueueCount(0); // 已完成任务数(包括主任务和子任务) Long mainCompletedCount = taskMapper.selectCount( new LambdaQueryWrapper() .eq(Task::getReceiverId, userId) .eq(Task::getStatus, "completed") .eq(Task::getDeleted, 0) ); Long subCompletedCount = taskItemMapper.selectCount( new LambdaQueryWrapper() .eq(TaskItem::getReceiverId, userId) .eq(TaskItem::getStatus, "completed") ); Integer completedCount = (mainCompletedCount != null ? mainCompletedCount.intValue() : 0) + (subCompletedCount != null ? subCompletedCount.intValue() : 0); stats.setCompletedCount(completedCount); // 延误任务数 Long delayedCountLong = taskMapper.selectCount( new LambdaQueryWrapper() .eq(Task::getReceiverId, userId) .eq(Task::getIsDelayed, 1) ); Integer delayedCount = delayedCountLong.intValue(); stats.setDelayedCount(delayedCount); // 计算完成率 if (totalCount > 0) { stats.setCompletionRate(completedCount * 100.0 / totalCount); } else { stats.setCompletionRate(0.0); } // 计算准时率 if (completedCount > 0) { Integer ontimeCount = completedCount - delayedCount; stats.setOntimeRate(ontimeCount * 100.0 / completedCount); } else { stats.setOntimeRate(0.0); } // 查询已完成任务的详细信息(用于计算积分和评分) List completedTasks = taskMapper.selectList( new LambdaQueryWrapper() .eq(Task::getReceiverId, userId) .eq(Task::getStatus, "completed") .eq(Task::getDeleted, 0) ); // 查询已完成子任务(用于计算积分) List completedSubTasks = taskItemMapper.selectList( new LambdaQueryWrapper() .eq(TaskItem::getReceiverId, userId) .eq(TaskItem::getStatus, "completed") ); // 累计获得积分(主任务 + 子任务) // 优先使用 scoreReward(实际获得积分),如果没有则使用 score(任务积分) Integer mainTaskScore = completedTasks.stream() .map(task -> { if (task.getScoreReward() != null && task.getScoreReward().compareTo(java.math.BigDecimal.ZERO) > 0) { return task.getScoreReward(); } return task.getScore() != null ? task.getScore() : java.math.BigDecimal.ZERO; }) .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add) .intValue(); Integer subTaskScore = completedSubTasks.stream() .map(item -> item.getTotalScore() != null ? item.getTotalScore() : java.math.BigDecimal.ZERO) .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add) .intValue(); Integer totalScore = mainTaskScore + subTaskScore; stats.setTotalScore(totalScore); log.debug("设计师积分统计: userId={}, mainTaskScore={}, subTaskScore={}, totalScore={}", userId, mainTaskScore, subTaskScore, totalScore); // 平均评分 List ratings = completedTasks.stream() .map(Task::getRating) .filter(rating -> rating != null && rating > 0) .collect(Collectors.toList()); if (!ratings.isEmpty()) { double avgRating = ratings.stream() .mapToInt(Integer::intValue) .average() .orElse(0.0); stats.setAvgRating(avgRating); // 好评数(5星) long goodReviewCount = ratings.stream() .filter(rating -> rating == 5) .count(); stats.setGoodReviewCount((int) goodReviewCount); } else { stats.setAvgRating(0.0); stats.setGoodReviewCount(0); } // 在线状态(简化处理,实际应该通过WebSocket或心跳机制维护) stats.setOnlineStatus(1); stats.setLastActiveTime("刚刚"); return stats; } /** * 获取指定月份的设计师统计信息 */ private List getDesignerStatsByMonth(String month) { // 解析月份 (YYYY-MM) String[] parts = month.split("-"); if (parts.length != 2) { return getAllDesignerStats(); // 格式错误时返回全部数据 } int year = Integer.parseInt(parts[0]); int monthNum = Integer.parseInt(parts[1]); // 计算月份的起始和结束时间 String startDate = String.format("%d-%02d-01 00:00:00", year, monthNum); String endDate; if (monthNum == 12) { endDate = String.format("%d-01-01 00:00:00", year + 1); } else { endDate = String.format("%d-%02d-01 00:00:00", year, monthNum + 1); } // 获取接单部门的设计师列表 List receivingDeptIds = departmentMapper.selectList( new LambdaQueryWrapper() .eq(Department::getDeptType, "receiving") .eq(Department::getStatus, 1) ).stream() .map(Department::getId) .collect(Collectors.toList()); if (receivingDeptIds.isEmpty()) { return new ArrayList<>(); } List designers = userMapper.selectList( new LambdaQueryWrapper() .eq(User::getStatus, 1) .in(User::getDeptId, receivingDeptIds) ); // 构建每个设计师的月度统计 return designers.stream() .map(user -> buildDesignerMonthStats(user, startDate, endDate)) .collect(Collectors.toList()); } /** * 构建设计师指定月份的统计信息 */ private DesignerStatsVO buildDesignerMonthStats(User user, String startDate, String endDate) { DesignerStatsVO stats = new DesignerStatsVO(); // 基本信息 stats.setUserId(user.getId()); stats.setUserName(user.getRealName()); stats.setAvatar(user.getAvatar()); stats.setDeptName(user.getDeptName()); Long userId = user.getId(); // 当月总接收任务数 Long totalCountLong = taskMapper.selectCount( new LambdaQueryWrapper() .eq(Task::getReceiverId, userId) .ge(Task::getCreateTime, startDate) .lt(Task::getCreateTime, endDate) ); stats.setTotalTaskCount(totalCountLong.intValue()); // 当月进行中任务数(实际在月份查询时应该是0,因为查历史月份) Long inProgressCountLong = taskMapper.selectCount( new LambdaQueryWrapper() .eq(Task::getReceiverId, userId) .eq(Task::getStatus, "in_progress") .ge(Task::getCreateTime, startDate) .lt(Task::getCreateTime, endDate) ); stats.setInProgressCount(inProgressCountLong.intValue()); stats.setQueueCount(0); // 当月已完成任务数 Long completedCountLong = taskMapper.selectCount( new LambdaQueryWrapper() .eq(Task::getReceiverId, userId) .eq(Task::getStatus, "completed") .ge(Task::getCompleteTime, startDate) .lt(Task::getCompleteTime, endDate) ); stats.setCompletedCount(completedCountLong.intValue()); // 当月总积分(已完成任务的积分之和) List completedTasks = taskMapper.selectList( new LambdaQueryWrapper() .eq(Task::getReceiverId, userId) .eq(Task::getStatus, "completed") .ge(Task::getCompleteTime, startDate) .lt(Task::getCompleteTime, endDate) ); Integer totalScore = completedTasks.stream() .map(task -> task.getScore() != null ? task.getScore() : java.math.BigDecimal.ZERO) .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add) .intValue(); stats.setTotalScore(totalScore); // 当月延期任务数 Long delayedCountLong = taskMapper.selectCount( new LambdaQueryWrapper() .eq(Task::getReceiverId, userId) .eq(Task::getIsDelayed, 1) .ge(Task::getCompleteTime, startDate) .lt(Task::getCompleteTime, endDate) ); stats.setDelayedCount(delayedCountLong.intValue()); // 计算当月完成率 if (totalCountLong > 0) { double completionRate = (completedCountLong.doubleValue() / totalCountLong.doubleValue()) * 100; stats.setCompletionRate(completionRate); } else { stats.setCompletionRate(0.0); } // 计算当月按时完成率 if (completedCountLong > 0) { long ontimeCount = completedCountLong - delayedCountLong; double ontimeRate = (ontimeCount / (double)completedCountLong) * 100; stats.setOntimeRate(ontimeRate); } else { stats.setOntimeRate(0.0); } // 当月平均评分 Double avgRating = completedTasks.stream() .filter(task -> task.getRating() != null && task.getRating() > 0) .mapToInt(Task::getRating) .average() .orElse(0.0); stats.setAvgRating(avgRating); // 当月好评数(评分>=4) long goodReviewCount = completedTasks.stream() .filter(task -> task.getRating() != null && task.getRating() >= 4) .count(); stats.setGoodReviewCount((int)goodReviewCount); // 在线状态(历史月份时设为离线) stats.setOnlineStatus(0); stats.setLastActiveTime(null); return stats; } /** * 获取设计师进行中的任务列表(包括主任务和子任务) * 返回统一格式的 Map 列表 */ public List> getDesignerInProgressTasks(Long userId) { List> result = new ArrayList<>(); // 1. 查询主任务 List mainTasks = taskMapper.selectList( new LambdaQueryWrapper() .eq(Task::getReceiverId, userId) .eq(Task::getStatus, "in_progress") .eq(Task::getDeleted, 0) .orderByDesc(Task::getCreateTime) ); for (Task task : mainTasks) { java.util.Map item = new java.util.LinkedHashMap<>(); item.put("id", task.getId()); item.put("taskNo", task.getTaskNo()); item.put("title", task.getTitle()); item.put("spuInfo", task.getSpuInfo()); // 添加SPU信息 item.put("status", task.getStatus()); item.put("progress", task.getProgress()); item.put("score", task.getScore()); // 使用实际接单时间作为开始时间 item.put("startTime", task.getActualStartTime() != null ? task.getActualStartTime() : task.getStartTime()); item.put("deadline", task.getDeadline()); item.put("createTime", task.getCreateTime()); item.put("isSubTask", false); item.put("type", "主任务"); result.add(item); } // 2. 查询子任务 List subTasks = taskItemMapper.selectList( new LambdaQueryWrapper() .eq(TaskItem::getReceiverId, userId) .eq(TaskItem::getStatus, "in_progress") .orderByDesc(TaskItem::getCreateTime) ); for (TaskItem item : subTasks) { java.util.Map taskItem = new java.util.LinkedHashMap<>(); taskItem.put("id", item.getId()); taskItem.put("taskNo", item.getItemNo()); // 获取主任务信息 Task mainTask = taskMapper.selectById(item.getTaskId()); // 优先显示主任务的SPU信息,否则显示子任务标题 String spuInfo = mainTask != null ? mainTask.getSpuInfo() : null; taskItem.put("title", spuInfo != null ? spuInfo : ("子任务 #" + item.getGroupNo())); taskItem.put("spuInfo", spuInfo); taskItem.put("status", item.getStatus()); taskItem.put("progress", item.getProgress()); taskItem.put("score", item.getTotalScore()); taskItem.put("startTime", item.getCreateTime()); // 使用创建时间作为开始时间 taskItem.put("deadline", mainTask != null ? mainTask.getDeadline() : null); taskItem.put("createTime", item.getCreateTime()); taskItem.put("isSubTask", true); taskItem.put("type", "子任务"); taskItem.put("mainTaskId", item.getTaskId()); result.add(taskItem); } return result; } }