From 652951bd0ce1eebcae43221e50d4cfda99c10aba Mon Sep 17 00:00:00 2001
From: 刘帅 <rr.iii@qq.com>
Date: 星期二, 22 九月 2026 17:37:40 +0800
Subject: [PATCH] bug:修改问题

---
 cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/UserMgrController.java |   78 +++++++++++++++++++--------------------
 1 files changed, 38 insertions(+), 40 deletions(-)

diff --git a/cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/UserMgrController.java b/cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/UserMgrController.java
index eb4a78f..90bbaa7 100644
--- a/cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/UserMgrController.java
+++ b/cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/UserMgrController.java
@@ -3,7 +3,6 @@
 import cn.hutool.crypto.SecureUtil;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.dsh.course.mapper.UserMapper;
@@ -154,6 +153,11 @@
         User user = this.userService.getById(userId);
         Role role = roleService.getById(user.getRoleid());
         Dept dept = deptService.getById(user.getDeptid());
+        // 兼容历史账号:部分账号的登录手机号仅保存在 account 字段。
+        // 个人资料页必须能回显该绑定手机号,避免前端提交空值。
+        if (StringUtils.isEmpty(user.getPhone()) && !StringUtils.isEmpty(user.getAccount())) {
+            user.setPhone(user.getAccount());
+        }
         user.setPhone(maskPhone(user.getPhone()));
         user.setIdCard(maskIdCard(user.getIdCard()));
         model.addAttribute(user);
@@ -176,6 +180,11 @@
         }
         roleLambdaQueryWrapper.eq(Role::getObjType,UserExt.getUser().getObjectType());
         List<Role> list = roleService.list(roleLambdaQueryWrapper);
+        // 员工可能是由平台账号创建、后续归属到门店的,原角色不一定属于当前登录人的角色范围。
+        // 编辑时仍需保留该角色作为可选项,避免下拉框无法回显。
+        if (role != null && list.stream().noneMatch(item -> Objects.equals(item.getId(), role.getId()))) {
+            list.add(role);
+        }
         model.addAttribute("list",list);
         model.addAttribute("language",UserExt.getLanguage());
         // 部门列表
@@ -210,6 +219,11 @@
         User user = this.userService.getById(userId);
         Role role = roleService.getById(user.getRoleid());
         Dept dept = deptService.getById(user.getDeptid());
+        // 兼容历史账号:部分账号的登录手机号仅保存在 account 字段。
+        // 个人资料页必须能回显该绑定手机号,避免前端提交空值。
+        if (StringUtils.isEmpty(user.getPhone()) && !StringUtils.isEmpty(user.getAccount())) {
+            user.setPhone(user.getAccount());
+        }
         user.setPhone(maskPhone(user.getPhone()));
         user.setIdCard(maskIdCard(user.getIdCard()));
         model.addAttribute(user);
@@ -411,7 +425,6 @@
         this.userService.save(objectUser);
         if (!assignedStores.isEmpty()) {
             replaceStoreRelations(objectUser.getId(), assignedStores);
-            syncStoreManagers(objectUser, Collections.<Integer>emptyList(), assignedStores);
         }
         return SUCCESS_TIP;
     }
@@ -431,9 +444,12 @@
         }
         User oldUser = userService.getById(user.getId());
         // 判断是否更改电话
-        if (user.getPhone() != null && user.getPhone().contains("*")) {
+        if (StringUtils.isEmpty(user.getPhone()) || user.getPhone().contains("*")) {
             // The edit view displays a masked phone. Treat an unchanged masked
-            // value as "keep original", never as a value to persist.
+            // value, or an omitted field, as "keep original", never as a
+            // value to persist. Some edit forms do not submit disabled or
+            // hidden fields; allowing an empty value through would erase the
+            // stored phone after deployment.
         } else if (!Objects.equals(oldUser.getPhone(), user.getPhone())) {
             User phone = userService.getOne(new QueryWrapper<User>().eq("phone", user.getPhone()));
             if (phone == null){
@@ -445,13 +461,16 @@
         oldUser.setName(user.getName());
         oldUser.setBirthday(user.getBirthday());
         oldUser.setDeptid(user.getDeptid());
-        if (user.getIdCard() == null || !user.getIdCard().contains("*")) oldUser.setIdCard(user.getIdCard());
+        // 身份证号为空说明本次表单没有提交该字段,不能覆盖数据库中的历史值;
+        // 脱敏值同样只用于回显,不能写回数据库。
+        if (!StringUtils.isEmpty(user.getIdCard()) && !user.getIdCard().contains("*")) {
+            oldUser.setIdCard(user.getIdCard());
+        }
         oldUser.setSex(user.getSex());
         oldUser.setEmail(user.getEmail());
         if (user.getAvatar()!=null && (!user.getAvatar().equals("")))
         oldUser.setAvatar(user.getAvatar());
         if (user.getStoreIds() != null) {
-            List<Integer> previousStoreIds = userMapper.getStoreIdsByUserId(oldUser.getId());
             List<TStore> assignedStores = validateStores(user.getStoreIds());
             if (assignedStores == null) return ResultUtil.error("所选门店不存在、已停用或不在当前账号管理范围内");
             replaceStoreRelations(oldUser.getId(), assignedStores);
@@ -463,17 +482,22 @@
                 // 清除旧字段关联,避免已移除的首个门店仍被当作该员工所属门店。
                 oldUser.setObjectId(null);
             }
-            syncStoreManagers(oldUser, previousStoreIds, assignedStores);
+        }
+        // 门店关联会维护员工归属信息,但不能覆盖编辑页明确选择的角色。
+        // 必须在关联处理后写入,否则有门店的员工会被上面的兼容逻辑强制改回角色 3。
+        // 个人资料页不提供 roleid_ 回显控件时,旧版前端可能提交字符串
+        // "undefined";该值绝不能覆盖 sys_user.roleid。
+        if (isValidRoleId(user.getRoleid())) {
+            oldUser.setRoleid(user.getRoleid());
         }
         this.userService.updateById(oldUser);
-        // 门店表仅保存店长 ID 和联系电话;店长名称由 storeStaffId 关联 sys_user.name 展示。
-        // 员工资料修改但门店未修改时,也要将其手机号同步给当前负责的门店。
-        if (user.getStoreIds() == null) {
-            storeService.update(new LambdaUpdateWrapper<TStore>()
-                    .eq(TStore::getStoreStaffId, oldUser.getId())
-                    .set(TStore::getPhone, oldUser.getPhone()));
-        }
         return SUCCESS_TIP;
+    }
+
+    private boolean isValidRoleId(String roleId) {
+        return !StringUtils.isEmpty(roleId)
+                && !"undefined".equalsIgnoreCase(roleId)
+                && !"null".equalsIgnoreCase(roleId);
     }
 
     private String maskPhone(String value) {
@@ -511,32 +535,6 @@
         userMapper.deleteStoreRelations(userId);
         for (TStore store : stores) {
             userMapper.insertStoreRelation(IdWorker.getId(), userId, store.getId());
-        }
-    }
-
-    /**
-     * 同步员工与门店的负责人信息。门店移除时,只清理仍由该员工负责的门店,
-     * 防止并发或后续操作已为门店设置新店长时被错误覆盖。
-     */
-    private void syncStoreManagers(User user, List<Integer> previousStoreIds, List<TStore> assignedStores) {
-        Set<Integer> assignedStoreIds = assignedStores.stream()
-                .map(TStore::getId)
-                .collect(Collectors.toSet());
-
-        for (Integer previousStoreId : previousStoreIds) {
-            if (!assignedStoreIds.contains(previousStoreId)) {
-                storeService.update(new LambdaUpdateWrapper<TStore>()
-                        .eq(TStore::getId, previousStoreId)
-                        .eq(TStore::getStoreStaffId, user.getId())
-                        .set(TStore::getStoreStaffId, null)
-                        .set(TStore::getPhone, null));
-            }
-        }
-
-        for (TStore store : assignedStores) {
-            store.setStoreStaffId(user.getId());
-            store.setPhone(user.getPhone());
-            storeService.updateById(store);
         }
     }
 

--
Gitblit v1.7.1