diff --git a/backend-src.tar.gz b/backend-src.tar.gz index 92988cd..9f16423 100644 Binary files a/backend-src.tar.gz and b/backend-src.tar.gz differ diff --git a/backend/src/main/java/com/designhub/controller/UserController.java b/backend/src/main/java/com/designhub/controller/UserController.java index 85369b4..7670a8a 100644 --- a/backend/src/main/java/com/designhub/controller/UserController.java +++ b/backend/src/main/java/com/designhub/controller/UserController.java @@ -46,6 +46,12 @@ public class UserController { return Result.success(userService.getAllUsers()); } + @Operation(summary = "获取所有需求部门的成员列表") + @GetMapping("/demand-dept-members") + public Result> getAllDemandDeptMembers() { + return Result.success(userService.getAllDemandDeptMembers()); + } + @Operation(summary = "根据ID获取用户") @GetMapping("/{id}") public Result getUserById(@PathVariable Long id) { diff --git a/backend/src/main/java/com/designhub/service/DepartmentService.java b/backend/src/main/java/com/designhub/service/DepartmentService.java index 38638fb..b7f3019 100644 --- a/backend/src/main/java/com/designhub/service/DepartmentService.java +++ b/backend/src/main/java/com/designhub/service/DepartmentService.java @@ -471,6 +471,28 @@ public class DepartmentService { ); } + /** + * 获取所有需求部门的ID列表(包括 demand 和 primary_demand 类型) + * 用于跨部门成员分配功能 + */ + public List getAllDemandDeptIds() { + List demandDepts = departmentMapper.selectList( + new LambdaQueryWrapper() + .in(Department::getDeptType, "demand", "primary_demand") + .eq(Department::getStatus, 1) + .eq(Department::getDeleted, 0) + ); + + List allDeptIds = new java.util.ArrayList<>(); + for (Department dept : demandDepts) { + allDeptIds.add(dept.getId()); + // 递归获取所有子部门ID + allDeptIds.addAll(getAllChildDeptIds(dept.getId())); + } + + return allDeptIds; + } + private Integer defaultLimitEnabled(Integer limitEnabled) { return limitEnabled != null ? limitEnabled : 0; } diff --git a/backend/src/main/java/com/designhub/service/SystemConfigService.java b/backend/src/main/java/com/designhub/service/SystemConfigService.java index 77beada..1ae496f 100644 --- a/backend/src/main/java/com/designhub/service/SystemConfigService.java +++ b/backend/src/main/java/com/designhub/service/SystemConfigService.java @@ -223,6 +223,7 @@ public class SystemConfigService { createConfigIfNotExists("task.grab_timeout", "30", "task", "抢单超时时间(分钟)", "任务发布后多久无人抢单则自动关闭", "number", 1); createConfigIfNotExists("task.auto_close_days", "7", "task", "自动关闭天数", "未完成的任务多少天后自动关闭", "number", 1); createConfigIfNotExists("task.primary_dept_can_fill_detail", "false", "task", "一级需求部门可填写任务明细", "开启后,一级需求部门发布任务时可以填写任务明细;关闭后,任务明细将由需求部门填写", "boolean", 1); + createConfigIfNotExists("primary_dept_cross_dept_assign", "false", "task", "允许跨部门分配成员", "开启后,需求部门负责人审核一级需求任务时可以选择所有需求部门的成员来完善任务明细", "boolean", 1); // 积分相关配置 createConfigIfNotExists("score.low_balance_alert", "100", "score", "积分余额预警阈值", "部门积分低于此值时发出预警", "number", 1); diff --git a/backend/src/main/java/com/designhub/service/UserService.java b/backend/src/main/java/com/designhub/service/UserService.java index c194b36..2d79335 100644 --- a/backend/src/main/java/com/designhub/service/UserService.java +++ b/backend/src/main/java/com/designhub/service/UserService.java @@ -398,6 +398,45 @@ public class UserService { ); } + /** + * 获取所有需求部门的成员列表 + * 用于一级需求部门任务的跨部门成员分配 + */ + public List getAllDemandDeptMembers() { + // 1. 获取所有需求部门的ID(dept_type = 'demand' 或 'primary_demand') + List demandDeptIds = departmentService.getAllDemandDeptIds(); + + if (demandDeptIds.isEmpty()) { + log.warn("没有找到需求部门"); + return new java.util.ArrayList<>(); + } + + log.info("查询需求部门成员,部门IDs: {}", demandDeptIds); + + // 2. 查询这些部门下的所有成员 + List users = userMapper.selectList( + new LambdaQueryWrapper() + .in(User::getDeptId, demandDeptIds) + .eq(User::getStatus, 1) // 只查询启用状态的用户 + .eq(User::getDeleted, 0) // 只查询未删除的用户 + .orderByAsc(User::getDeptId) + .orderByAsc(User::getRealName) + ); + + // 3. 填充部门名称 + for (User user : users) { + if (user.getDeptId() != null && (user.getDeptName() == null || user.getDeptName().isEmpty())) { + Department dept = departmentMapper.selectById(user.getDeptId()); + if (dept != null) { + user.setDeptName(dept.getDeptName()); + } + } + } + + log.info("查询到 {} 个需求部门成员", users.size()); + return users; + } + /** * 调整用户所属部门 */ diff --git a/frontend/src/api/user.ts b/frontend/src/api/user.ts index ff23873..4065711 100644 --- a/frontend/src/api/user.ts +++ b/frontend/src/api/user.ts @@ -53,6 +53,14 @@ export const getAllUsers = async (): Promise => { return response.data || []; }; +/** + * 获取所有需求部门的成员列表(用于跨部门分配) + */ +export const getAllDemandDeptMembers = async (): Promise => { + const response = await request.get('/users/demand-dept-members'); + return response.data || []; +}; + /** * 根据ID获取用户 */ diff --git a/frontend/src/views/Settings.vue b/frontend/src/views/Settings.vue index e4001a4..38488ca 100644 --- a/frontend/src/views/Settings.vue +++ b/frontend/src/views/Settings.vue @@ -1348,9 +1348,32 @@ + + + 成员分配范围 + + +
+
+
+ + 允许跨部门分配成员 +
+
+ 开启后,需求部门负责人审核一级需求任务时,可以选择所有需求部门的成员来完善任务明细。
+ 关闭后,只能选择当前负责人所属部门的成员。 +
+ +
+
+ { // 加载一级需求部门配置 const primaryDeptCanFillDetailConfig = configs.find((c: any) => c.configKey === 'primary_dept_can_fill_detail') + const crossDeptAssignConfig = configs.find((c: any) => c.configKey === 'primary_dept_cross_dept_assign') primaryDeptConfig.value = { - canFillDetail: primaryDeptCanFillDetailConfig?.configValue === 'true' + canFillDetail: primaryDeptCanFillDetailConfig?.configValue === 'true', + crossDeptAssign: crossDeptAssignConfig?.configValue === 'true' } } catch (error) { console.error('加载任务发布类型配置失败:', error) @@ -5027,7 +5053,8 @@ const handleSavePrimaryDeptConfig = async () => { savingPrimaryDeptConfig.value = true try { await batchUpdateSystemConfigs({ - 'primary_dept_can_fill_detail': primaryDeptConfig.value.canFillDetail.toString() + 'primary_dept_can_fill_detail': primaryDeptConfig.value.canFillDetail.toString(), + 'primary_dept_cross_dept_assign': primaryDeptConfig.value.crossDeptAssign.toString() }) message.success('一级需求部门配置保存成功') } catch (error: any) { diff --git a/frontend/src/views/TaskHall.vue b/frontend/src/views/TaskHall.vue index af35e71..5abc4e7 100644 --- a/frontend/src/views/TaskHall.vue +++ b/frontend/src/views/TaskHall.vue @@ -1948,17 +1948,24 @@ placeholder="请选择部门成员" style="width: 100%" show-search - :filter-option="(input, option) => option.label.toLowerCase().includes(input.toLowerCase())" + :filter-option="(input, option) => { + const label = option.label || '' + const deptName = option['data-dept'] || '' + return label.toLowerCase().includes(input.toLowerCase()) || deptName.toLowerCase().includes(input.toLowerCase()) + }" >
{{ member.realName }} - {{ member.username }} + + {{ member.deptName ? `${member.deptName} · ` : '' }}{{ member.username }} +
@@ -2370,7 +2377,7 @@ import * as userApi from '@/api/user' import * as configApi from '@/api/config' import * as authApi from '@/api/auth' import * as departmentApi from '@/api/department' -import { getWorkHoursConfig } from '@/api/system' +import { getWorkHoursConfig, getSystemConfig } from '@/api/system' import type { Task, TaskApprovalDTO, TaskProduct, ExportTaskHallParams } from '@/api/task' import { exportTaskHall } from '@/api/task' import type { DesignerWithWorkload } from '@/api/user' @@ -3696,7 +3703,7 @@ const primaryApproveModalVisible = ref(false) const primaryApproveTaskData = ref(null) const primaryApproveCompleterId = ref(undefined) const primaryApproveComment = ref('') -const deptMembersList = ref>([]) +const deptMembersList = ref>([]) const primaryApprovalLoading = ref(false) // 判断任务是否已预先指定设计师 @@ -5437,55 +5444,80 @@ const handleApprovePrimaryTask = async (task: Task) => { try { const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}') - // 优先使用用户管理的需求部门(dept_type = 'demand'),而不是接单部门 - let deptId = userInfo.deptId - let selectedDeptName = '' - - // 从管理的部门中找需求部门(demand类型) - if (managedDepartments.value.length > 0) { - // 优先找需求部门 - const demandDept = managedDepartments.value.find(d => d.deptType === 'demand') - if (demandDept) { - deptId = demandDept.deptId - selectedDeptName = demandDept.deptName - console.log(`使用用户管理的需求部门: ${selectedDeptName} (ID: ${deptId})`) - } else { - // 没有需求部门,使用第一个部门 - deptId = managedDepartments.value[0].deptId - selectedDeptName = managedDepartments.value[0].deptName - console.log(`没有找到需求部门,使用第一个管理的部门: ${selectedDeptName} (ID: ${deptId})`) - } - } else if (userInfo.managedDepartments && userInfo.managedDepartments.length > 0) { - // 优先找需求部门 - const demandDept = userInfo.managedDepartments.find((d: any) => d.deptType === 'demand') - if (demandDept) { - deptId = demandDept.deptId - selectedDeptName = demandDept.deptName - console.log(`使用userInfo中管理的需求部门: ${selectedDeptName} (ID: ${deptId})`) - } else { - deptId = userInfo.managedDepartments[0].deptId - selectedDeptName = userInfo.managedDepartments[0].deptName - console.log(`没有找到需求部门,使用userInfo中第一个管理的部门: ${selectedDeptName} (ID: ${deptId})`) - } + // 先检查是否开启了跨部门分配功能 + let crossDeptAssignEnabled = false + try { + const configResponse = await getSystemConfig('primary_dept_cross_dept_assign') + crossDeptAssignEnabled = configResponse.data?.configValue === 'true' + console.log('跨部门分配功能状态:', crossDeptAssignEnabled) + } catch (e) { + console.log('获取跨部门分配配置失败,使用默认值(关闭)') } - if (!deptId) { - message.error('无法获取部门信息') - return + if (crossDeptAssignEnabled) { + // 开启跨部门分配:获取所有需求部门的成员 + console.log('跨部门分配已开启,获取所有需求部门成员') + const allMembers = await userApi.getAllDemandDeptMembers() + deptMembersList.value = (allMembers || []).map(u => ({ + id: u.id!, + realName: u.realName || u.username, + username: u.username, + deptName: u.deptName || '' + })) + console.log(`获取到${deptMembersList.value.length}个需求部门成员(跨部门)`) + } else { + // 未开启跨部门分配:只获取当前负责人部门的成员 + // 优先使用用户管理的需求部门(dept_type = 'demand'),而不是接单部门 + let deptId = userInfo.deptId + let selectedDeptName = '' + + // 从管理的部门中找需求部门(demand类型) + if (managedDepartments.value.length > 0) { + // 优先找需求部门 + const demandDept = managedDepartments.value.find(d => d.deptType === 'demand') + if (demandDept) { + deptId = demandDept.deptId + selectedDeptName = demandDept.deptName + console.log(`使用用户管理的需求部门: ${selectedDeptName} (ID: ${deptId})`) + } else { + // 没有需求部门,使用第一个部门 + deptId = managedDepartments.value[0].deptId + selectedDeptName = managedDepartments.value[0].deptName + console.log(`没有找到需求部门,使用第一个管理的部门: ${selectedDeptName} (ID: ${deptId})`) + } + } else if (userInfo.managedDepartments && userInfo.managedDepartments.length > 0) { + // 优先找需求部门 + const demandDept = userInfo.managedDepartments.find((d: any) => d.deptType === 'demand') + if (demandDept) { + deptId = demandDept.deptId + selectedDeptName = demandDept.deptName + console.log(`使用userInfo中管理的需求部门: ${selectedDeptName} (ID: ${deptId})`) + } else { + deptId = userInfo.managedDepartments[0].deptId + selectedDeptName = userInfo.managedDepartments[0].deptName + console.log(`没有找到需求部门,使用userInfo中第一个管理的部门: ${selectedDeptName} (ID: ${deptId})`) + } + } + + if (!deptId) { + message.error('无法获取部门信息') + return + } + + console.log(`查询部门 ${deptId} (${selectedDeptName}) 的成员(包含子部门)`) + + // 获取部门成员(包含所有子部门) + const response = await userApi.getUserList(1, 1000, undefined, deptId, 1, true) + deptMembersList.value = (response.records || []).map(u => ({ + id: u.id!, + realName: u.realName || u.username, + username: u.username, + deptName: u.deptName || '' + })) + + console.log(`获取到${deptMembersList.value.length}个部门成员(含子部门)`) } - console.log(`查询部门 ${deptId} (${selectedDeptName}) 的成员(包含子部门)`) - - // 获取部门成员(包含所有子部门) - const response = await userApi.getUserList(1, 1000, undefined, deptId, 1, true) - deptMembersList.value = (response.records || []).map(u => ({ - id: u.id!, - realName: u.realName || u.username, - username: u.username - })) - - console.log(`获取到${deptMembersList.value.length}个部门成员(含子部门)`) - primaryApproveTaskData.value = task primaryApproveCompleterId.value = undefined primaryApproveComment.value = ''