From 6df38c4f89cd90c46b2defb5376c5944ed40e13b Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 2 Jan 2026 18:00:20 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E9=97=A8=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E8=B4=9F=E8=B4=A3=E4=BA=BA=E5=A4=B1=E8=B4=A5=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20-=20=E5=89=8D=E7=AB=AF=EF=BC=9A=E5=85=81?= =?UTF-8?q?=E8=AE=B8=E9=80=89=E6=8B=A9=E6=89=80=E6=9C=89=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BD=9C=E4=B8=BA=E9=83=A8=E9=97=A8=E8=B4=9F=E8=B4=A3=E4=BA=BA?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E9=99=90=E4=BA=8E=E8=AF=A5=E9=83=A8=E9=97=A8?= =?UTF-8?q?=E6=88=90=E5=91=98=20-=20=E5=89=8D=E7=AB=AF=EF=BC=9A=E4=BF=AE?= =?UTF-8?q?=E5=A4=8DleaderId=E5=92=8CparentId=E7=9A=84=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=80=A7=E9=97=AE=E9=A2=98=20-=20=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=EF=BC=9A=E6=B7=BB=E5=8A=A0leaderId=E6=9C=89=E6=95=88?= =?UTF-8?q?=E6=80=A7=E9=AA=8C=E8=AF=81=EF=BC=8C=E9=98=B2=E6=AD=A2=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E4=B8=8D=E5=AD=98=E5=9C=A8=E7=9A=84=E7=94=A8=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../designhub/service/DepartmentService.java | 56 ++++++++----------- frontend/src/views/Settings.vue | 40 +++++++------ 2 files changed, 47 insertions(+), 49 deletions(-) diff --git a/backend/src/main/java/com/designhub/service/DepartmentService.java b/backend/src/main/java/com/designhub/service/DepartmentService.java index 1b391b9..988ca0e 100644 --- a/backend/src/main/java/com/designhub/service/DepartmentService.java +++ b/backend/src/main/java/com/designhub/service/DepartmentService.java @@ -28,7 +28,6 @@ import java.util.stream.Collectors; /** * 部门管理Service */ -@Slf4j @Service @RequiredArgsConstructor public class DepartmentService { @@ -106,6 +105,14 @@ public class DepartmentService { @Transactional(rollbackFor = Exception.class) public DepartmentOverviewVO createDepartment(DepartmentCreateRequest request) { validateDeptType(request.getDeptType()); + + // 验证负责人ID是否有效 + if (request.getLeaderId() != null && request.getLeaderId() > 0) { + User leader = userMapper.selectById(request.getLeaderId()); + if (leader == null) { + throw new BusinessException("指定的负责人不存在"); + } + } Department department = new Department(); department.setDeptName(request.getDeptName()); @@ -179,6 +186,13 @@ public class DepartmentService { // 但由于无法判断字段是否存在,我们采用:如果leaderId不为null,则更新 if (request.getLeaderId() != null) { Long leaderId = request.getLeaderId(); + // 验证负责人ID是否有效(0表示清除,大于0需要验证) + if (leaderId > 0) { + User leader = userMapper.selectById(leaderId); + if (leader == null) { + throw new BusinessException("指定的负责人不存在"); + } + } existDept.setLeaderId(leaderId == 0 ? null : leaderId); } else if (request.getDeptName() != null) { // 如果其他字段被更新(说明这是完整的更新请求),且leaderId为null,则清除负责人 @@ -211,42 +225,20 @@ public class DepartmentService { existDept.setOverLimitAction(request.getOverLimitAction()); } - try { - departmentMapper.updateById(existDept); - log.info("更新部门成功: id={}, deptName={}", id, existDept.getDeptName()); - } catch (Exception e) { - log.error("更新部门失败: id={}, error={}", id, e.getMessage(), e); - throw new BusinessException("更新部门失败: " + e.getMessage()); - } + departmentMapper.updateById(existDept); // 同步积分池 - try { - teamScorePoolService.upsertPool(existDept.getId(), existDept.getDeptName()); - log.info("同步积分池成功: deptId={}, deptName={}", existDept.getId(), existDept.getDeptName()); - } catch (Exception e) { - log.error("同步积分池失败: deptId={}, error={}", existDept.getId(), e.getMessage(), e); - throw new BusinessException("同步积分池失败: " + e.getMessage()); - } - - // 更新积分池限制配置(仅需求部门) + teamScorePoolService.upsertPool(existDept.getId(), existDept.getDeptName()); if ("demand".equals(existDept.getDeptType()) && (request.getLimitEnabled() != null || request.getLimitPeriod() != null || request.getPeriodLimit() != null || request.getAlertThreshold() != null)) { - try { - teamScorePoolService.updateLimitConfig( - existDept.getId(), - request.getLimitEnabled(), - request.getLimitPeriod(), - request.getPeriodLimit(), - request.getAlertThreshold() - ); - log.info("更新积分池限制配置成功: deptId={}, limitEnabled={}, limitPeriod={}, periodLimit={}, alertThreshold={}", - existDept.getId(), request.getLimitEnabled(), request.getLimitPeriod(), - request.getPeriodLimit(), request.getAlertThreshold()); - } catch (Exception e) { - log.error("更新积分池限制配置失败: deptId={}, error={}", existDept.getId(), e.getMessage(), e); - throw new BusinessException("更新积分池限制配置失败: " + e.getMessage()); - } + teamScorePoolService.updateLimitConfig( + existDept.getId(), + request.getLimitEnabled(), + request.getLimitPeriod(), + request.getPeriodLimit(), + request.getAlertThreshold() + ); } return true; diff --git a/frontend/src/views/Settings.vue b/frontend/src/views/Settings.vue index 28249fb..eb675ea 100644 --- a/frontend/src/views/Settings.vue +++ b/frontend/src/views/Settings.vue @@ -1118,7 +1118,7 @@ - + 顶级部门 ({ deptCode: '', deptType: 'demand', parentId: 0, - leaderId: null, + leaderId: undefined, description: '', sortOrder: 0, status: 1, @@ -1521,18 +1521,13 @@ const unassignedUsers = computed(() => { // 过滤出当前部门的用户(用于负责人选择) const departmentUsers = computed(() => { - // 如果是编辑部门,只显示该部门的用户 - if (editingItem.value?.id) { - const deptId = editingItem.value.id - const users = usersByDept.value[deptId] || [] - return users.slice().sort((a, b) => { - const nameA = a.realName || a.username || '' - const nameB = b.realName || b.username || '' - return nameA.localeCompare(nameB) - }) - } - // 如果是新建部门,显示未分配部门的用户 - return unassignedUsers.value + // 部门负责人应该可以选择任何用户,不限制于该部门的成员 + // 返回所有用户的排序列表 + return allUsers.value.slice().sort((a, b) => { + const nameA = a.realName || a.username || '' + const nameB = b.realName || b.username || '' + return nameA.localeCompare(nameB) + }) }) const hasUserData = computed(() => { @@ -1949,7 +1944,7 @@ const showDepartmentModal = async (item?: DepartmentOverview) => { deptCode: item.deptCode, deptType: item.deptType, parentId: item.parentId ?? 0, - leaderId: item.leaderId ?? null, + leaderId: item.leaderId ?? undefined, description: item.description, sortOrder: item.sortOrder ?? 0, status: item.status ?? 1, @@ -2128,6 +2123,17 @@ const saveCategory = async () => { const isDemandDept = computed(() => formData.department.deptType === 'demand') const isReceivingDept = computed(() => formData.department.deptType === 'receiving') +// Computed属性用于处理leaderId和parentId的null到undefined的转换,以兼容a-select +const departmentLeaderId = computed({ + get: () => formData.department.leaderId ?? undefined, + set: (val) => { formData.department.leaderId = val ?? undefined } +}) + +const departmentParentId = computed({ + get: () => formData.department.parentId ?? undefined, + set: (val) => { formData.department.parentId = val ?? undefined } +}) + const buildDepartmentPayload = (includeInitial: boolean): DepartmentPayload => { const payload: DepartmentPayload = { deptName: formData.department.deptName,