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,