fix: align queue checks with viewer department

This commit is contained in:
Your Name 2026-03-12 17:10:21 +08:00
parent 7010098ab3
commit 9fba6b03f4
2 changed files with 105 additions and 24 deletions

View File

@ -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<TaskItem> 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<TaskItem> items = taskItemService.getAvailableItems(page, pageSize, taskTypeId, keyword, filterDeptId, sortBy, includeQueuing, brandId, categoryId, platformId, taskSubType, viewerDeptId);
return Result.success(items);
}

View File

@ -79,7 +79,7 @@ public class TaskItemService {
*/
public IPage<TaskItem> 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<TaskItem> 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<TaskItem> 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<TaskItem> pageParam = new Page<>(page, pageSize);
IPage<TaskItem> 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<TaskItem> 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<com.designhub.entity.TaskUnlockStatus> 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<com.designhub.entity.TaskUnlockStatus> 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<com.designhub.entity.TaskUnlockStatus> 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);