fix: expand receiving department children for task type routing
This commit is contained in:
parent
c76551bef2
commit
462e1a4e88
@ -646,6 +646,63 @@ public class DepartmentService {
|
||||
log.info("获取部门{}的所有子部门ID: {}", deptId, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门自身及所有子部门ID
|
||||
*/
|
||||
public List<Long> getDeptAndChildIds(Long deptId) {
|
||||
if (deptId == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<Long> result = new ArrayList<>();
|
||||
result.add(deptId);
|
||||
result.addAll(getAllChildDeptIds(deptId));
|
||||
return result.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 展开逗号分隔的部门ID,自动包含所有子部门
|
||||
*/
|
||||
public List<Long> expandDeptIdsWithChildren(String deptIdsText) {
|
||||
if (!StringUtils.hasText(deptIdsText)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<Long> deptIds = Arrays.stream(deptIdsText.split(","))
|
||||
.map(String::trim)
|
||||
.filter(StringUtils::hasText)
|
||||
.map(idText -> {
|
||||
try {
|
||||
return Long.parseLong(idText);
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("解析部门ID失败: {}", idText);
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return expandDeptIdsWithChildren(deptIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 展开部门ID列表,自动包含所有子部门
|
||||
*/
|
||||
public List<Long> expandDeptIdsWithChildren(List<Long> deptIds) {
|
||||
if (CollectionUtils.isEmpty(deptIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
java.util.LinkedHashSet<Long> result = new java.util.LinkedHashSet<>();
|
||||
for (Long deptId : deptIds) {
|
||||
if (deptId == null) {
|
||||
continue;
|
||||
}
|
||||
result.addAll(getDeptAndChildIds(deptId));
|
||||
}
|
||||
return new ArrayList<>(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否为任何部门的负责人
|
||||
@ -665,4 +722,3 @@ public class DepartmentService {
|
||||
return count != null && count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -39,6 +39,7 @@ public class TaskApprovalService {
|
||||
private final CategoryMapper categoryMapper;
|
||||
private final PlatformMapper platformMapper;
|
||||
private final NotificationService notificationService;
|
||||
private final DepartmentService departmentService;
|
||||
private final TeamScorePoolService teamScorePoolService;
|
||||
|
||||
@org.springframework.beans.factory.annotation.Autowired
|
||||
@ -1013,9 +1014,8 @@ public class TaskApprovalService {
|
||||
}
|
||||
|
||||
if (allowedDeptIds != null && !allowedDeptIds.isEmpty()) {
|
||||
String[] deptIds = allowedDeptIds.split(",");
|
||||
if (deptIds.length > 0) {
|
||||
Long deptId = Long.parseLong(deptIds[0].trim());
|
||||
List<Long> expandedDeptIds = departmentService.expandDeptIdsWithChildren(allowedDeptIds);
|
||||
for (Long deptId : expandedDeptIds) {
|
||||
Department dept = departmentMapper.selectById(deptId);
|
||||
if (dept != null && dept.getLeaderId() != null) {
|
||||
log.info("从任务类型配置获取接单部门负责人(降级方案): 部门={}, 负责人ID={}",
|
||||
|
||||
@ -132,19 +132,7 @@ public class TaskItemService {
|
||||
if (allowedDepts == null || allowedDepts.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
String[] deptIds = allowedDepts.split(",");
|
||||
for (String deptIdStr : deptIds) {
|
||||
try {
|
||||
Long deptId = Long.parseLong(deptIdStr.trim());
|
||||
// 🔥 检查是否匹配筛选部门或其子部门
|
||||
if (filterDeptAndChildIds.contains(deptId)) {
|
||||
return true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// 忽略无效的部门ID
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return expandAllowedDeptIds(allowedDepts).stream().anyMatch(filterDeptAndChildIds::contains);
|
||||
})
|
||||
.map(com.designhub.entity.DemandType::getId)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
@ -369,23 +357,7 @@ public class TaskItemService {
|
||||
if (allowedDeptIds == null || allowedDeptIds.isBlank()) {
|
||||
return java.util.Collections.emptyList();
|
||||
}
|
||||
|
||||
List<Long> result = new java.util.ArrayList<>();
|
||||
Set<Long> seen = new java.util.HashSet<>();
|
||||
for (String deptIdText : allowedDeptIds.split(",")) {
|
||||
if (deptIdText == null || deptIdText.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Long deptId = Long.parseLong(deptIdText.trim());
|
||||
if (seen.add(deptId)) {
|
||||
result.add(deptId);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("解析排队部门ID失败: taskItemId={}, deptIdText={}", item.getId(), deptIdText);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return new java.util.ArrayList<>(expandAllowedDeptIds(allowedDeptIds));
|
||||
}
|
||||
|
||||
private int getDeptDistance(Long userDeptId, Long targetDeptId) {
|
||||
@ -1883,11 +1855,11 @@ public class TaskItemService {
|
||||
log.info("管理员模式,有权限");
|
||||
} else {
|
||||
// 部门负责人:检查子任务的任务类型配置的 allowed_dept_ids 是否包含该部门
|
||||
Long targetDeptId = getTargetDeptIdFromTaskType(item.getTaskTypeId());
|
||||
log.info("子任务 {} 的目标部门ID: {}, 查询的部门ID: {}",
|
||||
item.getId(), targetDeptId, receiverDeptId);
|
||||
List<Long> targetDeptIds = getTargetDeptIdsFromTaskType(item.getTaskTypeId());
|
||||
log.info("子任务 {} 的目标部门ID列表: {}, 查询的部门ID: {}",
|
||||
item.getId(), targetDeptIds, receiverDeptId);
|
||||
|
||||
if (targetDeptId != null && targetDeptId.equals(receiverDeptId)) {
|
||||
if (targetDeptIds.contains(receiverDeptId)) {
|
||||
hasPermission = true;
|
||||
log.info("匹配成功(通过任务类型配置)");
|
||||
}
|
||||
@ -2108,17 +2080,22 @@ public class TaskItemService {
|
||||
* 如果当前类型未配置,则递归向上查找父级类型的配置
|
||||
*/
|
||||
private Long getTargetDeptIdFromTaskType(Long taskTypeId) {
|
||||
List<Long> targetDeptIds = getTargetDeptIdsFromTaskType(taskTypeId);
|
||||
return targetDeptIds.isEmpty() ? null : targetDeptIds.get(0);
|
||||
}
|
||||
|
||||
private List<Long> getTargetDeptIdsFromTaskType(Long taskTypeId) {
|
||||
log.debug("getTargetDeptIdFromTaskType 调用, taskTypeId: {}", taskTypeId);
|
||||
|
||||
if (taskTypeId == null) {
|
||||
log.debug("taskTypeId 为空,返回 null");
|
||||
return null;
|
||||
return java.util.Collections.emptyList();
|
||||
}
|
||||
|
||||
com.designhub.entity.DemandType taskType = demandTypeMapper.selectById(taskTypeId);
|
||||
if (taskType == null) {
|
||||
log.warn("任务类型 {} 不存在", taskTypeId);
|
||||
return null;
|
||||
return java.util.Collections.emptyList();
|
||||
}
|
||||
|
||||
log.debug("任务类型: id={}, name={}, parentId={}, allowedDeptIds={}",
|
||||
@ -2127,26 +2104,42 @@ public class TaskItemService {
|
||||
// 如果当前类型配置了allowed_dept_ids,返回第一个部门ID
|
||||
String allowedDeptIds = taskType.getAllowedDeptIds();
|
||||
if (allowedDeptIds != null && !allowedDeptIds.isEmpty()) {
|
||||
try {
|
||||
String[] deptIds = allowedDeptIds.split(",");
|
||||
if (deptIds.length > 0) {
|
||||
Long result = Long.parseLong(deptIds[0].trim());
|
||||
log.debug("找到 allowed_dept_ids: {}, 返回第一个: {}", allowedDeptIds, result);
|
||||
return result;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("解析allowed_dept_ids失败: {}", allowedDeptIds, e);
|
||||
List<Long> expandedDeptIds = new java.util.ArrayList<>(expandAllowedDeptIds(allowedDeptIds));
|
||||
if (!expandedDeptIds.isEmpty()) {
|
||||
log.debug("找到 allowed_dept_ids: {}, 展开后返回: {}", allowedDeptIds, expandedDeptIds);
|
||||
return expandedDeptIds;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果当前类型未配置,递归查找父级
|
||||
if (taskType.getParentId() != null) {
|
||||
log.debug("当前类型未配置 allowed_dept_ids, 递归查找父级: {}", taskType.getParentId());
|
||||
return getTargetDeptIdFromTaskType(taskType.getParentId());
|
||||
return getTargetDeptIdsFromTaskType(taskType.getParentId());
|
||||
}
|
||||
|
||||
log.debug("未找到配置的部门,返回 null");
|
||||
return null;
|
||||
return java.util.Collections.emptyList();
|
||||
}
|
||||
|
||||
private Set<Long> expandAllowedDeptIds(String allowedDeptIds) {
|
||||
Set<Long> result = new java.util.LinkedHashSet<>();
|
||||
if (allowedDeptIds == null || allowedDeptIds.trim().isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (String deptIdText : allowedDeptIds.split(",")) {
|
||||
if (deptIdText == null || deptIdText.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Long deptId = Long.parseLong(deptIdText.trim());
|
||||
result.addAll(getDeptAndChildIds(deptId));
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("解析接单部门ID失败: {}", deptIdText);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void markPipelineItemUnlocked(TaskItem item) {
|
||||
|
||||
@ -1260,14 +1260,8 @@ public class TaskService {
|
||||
if (allowedDepts == null || allowedDepts.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
// 检查用户部门是否在允许列表中
|
||||
String[] deptIds = allowedDepts.split(",");
|
||||
for (String deptId : deptIds) {
|
||||
if (deptId.trim().equals(String.valueOf(userDeptId))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
// 选择父级接单部门时,运行时需要自动覆盖所有子部门。
|
||||
return expandAllowedDeptIds(allowedDepts).contains(userDeptId);
|
||||
})
|
||||
.map(DemandType::getId)
|
||||
.collect(Collectors.toList());
|
||||
@ -1294,19 +1288,7 @@ public class TaskService {
|
||||
if (allowedDepts == null || allowedDepts.isEmpty()) {
|
||||
return false; // 所有部门都可接单的不纳入筛选结果
|
||||
}
|
||||
String[] deptIds = allowedDepts.split(",");
|
||||
for (String deptIdStr : deptIds) {
|
||||
try {
|
||||
Long deptId = Long.parseLong(deptIdStr.trim());
|
||||
// 🔥 检查是否匹配筛选部门或其子部门
|
||||
if (filterDeptAndChildSet.contains(deptId)) {
|
||||
return true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// 忽略无效的部门ID
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return expandAllowedDeptIds(allowedDepts).stream().anyMatch(filterDeptAndChildSet::contains);
|
||||
})
|
||||
.map(DemandType::getId)
|
||||
.collect(Collectors.toList());
|
||||
@ -4263,6 +4245,28 @@ public class TaskService {
|
||||
collectChildDeptIds(deptId, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Set<Long> expandAllowedDeptIds(String allowedDeptIds) {
|
||||
Set<Long> result = new HashSet<>();
|
||||
if (!StringUtils.hasText(allowedDeptIds)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (String deptIdText : allowedDeptIds.split(",")) {
|
||||
String trimmed = deptIdText == null ? "" : deptIdText.trim();
|
||||
if (trimmed.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Long deptId = Long.parseLong(trimmed);
|
||||
result.addAll(getDeptAndChildIds(deptId));
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("解析接单部门ID失败: {}", deptIdText);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归收集所有子部门ID
|
||||
|
||||
@ -40,6 +40,9 @@ public class TaskUnlockService {
|
||||
|
||||
@Autowired
|
||||
private DemandTypeMapper demandTypeMapper;
|
||||
|
||||
@Autowired
|
||||
private DepartmentService departmentService;
|
||||
|
||||
@Autowired
|
||||
private TaskStatusNotificationService taskStatusNotificationService;
|
||||
@ -744,27 +747,7 @@ public class TaskUnlockService {
|
||||
if (allowedDeptIds == null || allowedDeptIds.trim().isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
String[] parts = allowedDeptIds.split(",");
|
||||
List<Long> result = new ArrayList<>();
|
||||
Set<Long> seen = new HashSet<>();
|
||||
for (String part : parts) {
|
||||
if (part == null) {
|
||||
continue;
|
||||
}
|
||||
String s = part.trim();
|
||||
if (s.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Long id = Long.parseLong(s);
|
||||
if (seen.add(id)) {
|
||||
result.add(id);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// 忽略
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return departmentService.expandDeptIdsWithChildren(allowedDeptIds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -4351,6 +4351,24 @@ const flatDepartmentOptions = computed(() => {
|
||||
return groups
|
||||
})
|
||||
|
||||
const expandReceivingDepartmentIds = (selectedDeptIds: number[] = []) => {
|
||||
const expanded = new Set<number>()
|
||||
|
||||
const appendDeptAndChildren = (deptId?: number) => {
|
||||
if (!deptId || expanded.has(deptId)) {
|
||||
return
|
||||
}
|
||||
|
||||
expanded.add(deptId)
|
||||
departments.value
|
||||
.filter(d => d.parentId === deptId && d.deptType === 'receiving' && d.status === 1)
|
||||
.forEach(child => appendDeptAndChildren(child.id))
|
||||
}
|
||||
|
||||
selectedDeptIds.forEach(id => appendDeptAndChildren(id))
|
||||
return Array.from(expanded)
|
||||
}
|
||||
|
||||
// 根据部门ID字符串获取部门名称
|
||||
const getDeptNamesFromIds = (idsStr: string) => {
|
||||
if (!idsStr) return ''
|
||||
@ -5175,9 +5193,9 @@ const saveDemandType = async () => {
|
||||
isEnabled: formData.demandType.isEnabled ?? 1,
|
||||
// 父级ID(二级、三级分类需要设置)
|
||||
parentId: (addLevel === 'level2' || addLevel === 'level3') ? formData.demandType.parentId : null,
|
||||
// 将部门ID数组转换为逗号分隔的字符串(仅二级分类需要设置)
|
||||
// 选择父级接单部门时,同时持久化所有子级接单部门,保证运行时精确匹配也能命中。
|
||||
allowedDeptIds: addLevel === 'level2' && formData.demandType.departmentIds?.length > 0
|
||||
? formData.demandType.departmentIds.join(',')
|
||||
? expandReceivingDepartmentIds(formData.demandType.departmentIds).join(',')
|
||||
: null
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user