diff --git a/backend/src/main/java/com/designhub/controller/TaskItemController.java b/backend/src/main/java/com/designhub/controller/TaskItemController.java index b94ffc4..f27d717 100644 --- a/backend/src/main/java/com/designhub/controller/TaskItemController.java +++ b/backend/src/main/java/com/designhub/controller/TaskItemController.java @@ -61,9 +61,24 @@ public class TaskItemController { @Parameter(description = "品牌ID") @RequestParam(required = false) Long brandId, @Parameter(description = "类目ID") @RequestParam(required = false) Long categoryId, @Parameter(description = "平台ID") @RequestParam(required = false) Long platformId, - @Parameter(description = "需求类型") @RequestParam(required = false) String taskSubType) { - - IPage items = taskItemService.getAvailableItems(page, pageSize, taskTypeId, keyword, filterDeptId, sortBy, includeQueuing, brandId, categoryId, platformId, taskSubType); + @Parameter(description = "需求类型") @RequestParam(required = false) String taskSubType, + @RequestHeader(value = "Authorization", required = false) String token) { + + Long viewerDeptId = null; + if (token != null && !token.trim().isEmpty()) { + try { + String actualToken = jwtUtil.extractTokenFromHeader(token); + Long userId = jwtUtil.getUserIdFromToken(actualToken); + com.designhub.entity.User user = userMapper.selectById(userId); + if (user != null) { + viewerDeptId = user.getDeptId(); + } + } catch (Exception e) { + log.debug("解析任务大厅用户部门失败,继续使用默认口径: {}", e.getMessage()); + } + } + + IPage items = taskItemService.getAvailableItems(page, pageSize, taskTypeId, keyword, filterDeptId, sortBy, includeQueuing, brandId, categoryId, platformId, taskSubType, viewerDeptId); return Result.success(items); } diff --git a/backend/src/main/java/com/designhub/service/TaskItemService.java b/backend/src/main/java/com/designhub/service/TaskItemService.java index ee05917..008c877 100644 --- a/backend/src/main/java/com/designhub/service/TaskItemService.java +++ b/backend/src/main/java/com/designhub/service/TaskItemService.java @@ -79,7 +79,7 @@ public class TaskItemService { */ public IPage getAvailableItems(Integer page, Integer pageSize, Long taskTypeId, String keyword, Long filterDeptId, String sortBy, Boolean includeQueuing) { - return getAvailableItems(page, pageSize, taskTypeId, keyword, filterDeptId, sortBy, includeQueuing, null, null, null, null); + return getAvailableItems(page, pageSize, taskTypeId, keyword, filterDeptId, sortBy, includeQueuing, null, null, null, null, null); } /** @@ -95,6 +95,14 @@ public class TaskItemService { public IPage getAvailableItems(Integer page, Integer pageSize, Long taskTypeId, String keyword, Long filterDeptId, String sortBy, Boolean includeQueuing, Long brandId, Long categoryId, Long platformId, String taskSubType) { + return getAvailableItems(page, pageSize, taskTypeId, keyword, filterDeptId, sortBy, includeQueuing, + brandId, categoryId, platformId, taskSubType, null); + } + + public IPage getAvailableItems(Integer page, Integer pageSize, Long taskTypeId, String keyword, + Long filterDeptId, String sortBy, Boolean includeQueuing, + Long brandId, Long categoryId, Long platformId, String taskSubType, + Long viewerDeptId) { Page pageParam = new Page<>(page, pageSize); IPage result; @@ -154,7 +162,8 @@ public class TaskItemService { // 🔥 填充排队状态信息 if (result.getRecords() != null && !result.getRecords().isEmpty()) { - fillUnlockStatusForItems(result.getRecords(), filterDeptId); + Long statusDeptId = viewerDeptId != null ? viewerDeptId : filterDeptId; + fillUnlockStatusForItems(result.getRecords(), statusDeptId); // 🔥 按排序方式和解锁状态排序:可抢单的排前面 List sortedRecords = new java.util.ArrayList<>(result.getRecords()); @@ -215,24 +224,7 @@ public class TaskItemService { } } - // 确定目标部门 - Long targetDeptId = deptId; - if (targetDeptId == null) { - // 优先使用已接单的部门 - targetDeptId = item.getReceiverDeptId(); - } - - if (targetDeptId == null) { - // 🔥 从 task_unlock_status 表中查询该任务对应的部门 - com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper wrapper = - new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>(); - wrapper.eq(com.designhub.entity.TaskUnlockStatus::getTaskItemId, item.getId()) - .last("LIMIT 1"); - com.designhub.entity.TaskUnlockStatus unlockStatus = taskUnlockService.getUnlockStatusMapper().selectOne(wrapper); - if (unlockStatus != null) { - targetDeptId = unlockStatus.getDeptId(); - } - } + Long targetDeptId = resolveApplicableQueueDeptId(item, deptId); // 填充解锁状态 if (targetDeptId != null) { @@ -299,6 +291,71 @@ public class TaskItemService { return false; } + private Long resolveApplicableQueueDeptId(TaskItem item, Long viewerDeptId) { + if (item == null) { + return null; + } + if (item.getReceiverDeptId() != null) { + return item.getReceiverDeptId(); + } + + com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper wrapper = + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>(); + wrapper.eq(com.designhub.entity.TaskUnlockStatus::getTaskItemId, item.getId()) + .orderByAsc(com.designhub.entity.TaskUnlockStatus::getDeptId) + .orderByAsc(com.designhub.entity.TaskUnlockStatus::getId); + List unlockStatuses = taskUnlockService.getUnlockStatusMapper().selectList(wrapper); + if (unlockStatuses == null || unlockStatuses.isEmpty()) { + return null; + } + + if (viewerDeptId != null) { + Long matchedDeptId = null; + int bestDistance = Integer.MAX_VALUE; + for (com.designhub.entity.TaskUnlockStatus unlockStatus : unlockStatuses) { + Long candidateDeptId = unlockStatus.getDeptId(); + if (candidateDeptId == null || !isDeptMatchedOrInherited(viewerDeptId, candidateDeptId)) { + continue; + } + int distance = getDeptDistance(viewerDeptId, candidateDeptId); + if (distance < bestDistance) { + bestDistance = distance; + matchedDeptId = candidateDeptId; + } + } + if (matchedDeptId != null) { + return matchedDeptId; + } + } + + return unlockStatuses.get(0).getDeptId(); + } + + private int getDeptDistance(Long userDeptId, Long targetDeptId) { + if (userDeptId == null || targetDeptId == null) { + return Integer.MAX_VALUE; + } + if (targetDeptId.equals(userDeptId)) { + return 0; + } + + Long currentDeptId = userDeptId; + int distance = 0; + while (currentDeptId != null) { + if (targetDeptId.equals(currentDeptId)) { + return distance; + } + com.designhub.entity.Department currentDept = departmentMapper.selectById(currentDeptId); + if (currentDept == null || currentDept.getParentId() == null + || currentDeptId.equals(currentDept.getParentId())) { + break; + } + currentDeptId = currentDept.getParentId(); + distance++; + } + return isSharedGrabDept(userDeptId, targetDeptId) ? distance + 1000 : Integer.MAX_VALUE; + } + private boolean isSharedGrabDept(Long userDeptId, Long targetDeptId) { return isDeptInTree(userDeptId, AI_VISUAL_DEPT_ID) && isDeptInTree(targetDeptId, GRAPHIC_VISUAL_DEPT_ID); @@ -546,7 +603,10 @@ public class TaskItemService { if (!"assigned".equals(releaseType)) { // 非指定任务,检查是否可抢单 - Long targetDeptId = item.getReceiverDeptId() != null ? item.getReceiverDeptId() : user.getDeptId(); + Long targetDeptId = resolveApplicableQueueDeptId(item, user.getDeptId()); + if (targetDeptId == null) { + targetDeptId = item.getReceiverDeptId() != null ? item.getReceiverDeptId() : user.getDeptId(); + } if (!taskUnlockService.canGrab(itemId, targetDeptId, releaseType)) { throw new BusinessException(ResultCode.TASK_STATUS_ERROR, "该任务正在排队中,暂不可接单"); } @@ -643,6 +703,12 @@ public class TaskItemService { // 🔥 任务被抢单后,检查并补充解锁下一批任务 Long grabberDeptId = user.getDeptId(); + if (!isAssignedItem && !"assigned".equals(releaseType)) { + Long queueDeptId = resolveApplicableQueueDeptId(item, user.getDeptId()); + if (queueDeptId != null) { + grabberDeptId = queueDeptId; + } + } if (grabberDeptId != null) { try { taskUnlockService.onTaskGrabbed(grabberDeptId);