wuchen 2 месяцев назад
Родитель
Сommit
ba44d9e035

+ 6 - 2
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreSubExcelVo.java

@@ -15,14 +15,18 @@ public class StoreSubExcelVo {
     @ApiModelProperty(value = "序号")
     private Integer serialNumber;
 
-    @ApiModelProperty(value = "主账号ID")
+    @ApiModelProperty(value = "主账号ID(主账号联系方式所对应的id)")
     @ExcelHeader(value = "主账号ID")
-    private Integer id;
+    private Integer parentAccountId;
 
     @ApiModelProperty(value = "主账号手机号")
     @ExcelHeader(value = "主账号手机号码")
     private String parentAccountPhone;
 
+    @ApiModelProperty(value = "子账号ID")
+    @ExcelHeader(value = "子账号ID")
+    private Integer subAccountId;
+
     @ApiModelProperty(value = "手机号码")
     @ExcelHeader(value = "手机号码")
     private String phone;

+ 4 - 1
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreUserVo.java

@@ -20,9 +20,12 @@ import java.util.List;
 @JsonInclude
 @ApiModel(value = "StoreUserVo对象", description = "门店用户扩展")
 public class StoreUserVo extends StoreUser {
-     @ApiModelProperty(value = "父账号Id")
+     @ApiModelProperty(value = "父账号Id(主账号联系方式所对应的id)")
     private Integer parentAccountId;
 
+    @ApiModelProperty(value = "子账号ID(用于删除/禁用等操作,子账号列表时必填)")
+    private Integer subAccountId;
+
     @ApiModelProperty(value = "登录Token")
     private String token;
 

+ 7 - 8
alien-store/src/main/java/shop/alien/store/controller/StoreUserController.java

@@ -289,7 +289,7 @@ public class StoreUserController {
     @ApiOperation("web端切换商家端用户状态(主账号有子账号时禁止禁用;返回更新后状态供前端及时展示)")
     @ApiOperationSupport(order = 7)
     @PutMapping("/switchingStates")
-    public R<StoreUserVo> switchingStates(@RequestBody StoreUser storeUser) {
+    public R<StoreUserVo> switchingStates(@RequestBody StoreUserVo storeUser) {
         log.info("StoreUserController.switchingStates?storeUser={}", storeUser);
         try {
             return storeUserService.switchingStates(storeUser);
@@ -417,15 +417,14 @@ public class StoreUserController {
     }
 
     /**
-     * 手动删除商家账号及店铺
-     *  进行校验
+     * 删除商家账号(优先按子账号删除:传子账号联系电话 phone,关联 store_user.id 与 store_platform_user_role.user_id 走子账号逻辑)
      */
-    @ApiOperation("手动删除商家账号及店铺")
+    @ApiOperation("删除商家账号(传子账号联系电话 phone 按子账号删除)")
     @PostMapping("/deleteStoreAccountInfo")
-    public R<StoreUserVo> deleteStoreAccountInfo(@RequestBody StoreUserVo storeUserVo) {
-        log.info("StoreUserController.deleteStoreAccountInfo?storeUserVo={}", storeUserVo);
-        storeUserService.deleteStoreAccountInfo(storeUserVo);
-        return R.success("删除成功");
+    public R<String> deleteStoreAccountInfo(@RequestBody StoreUserVo storeUserVo) {
+        log.info("StoreUserController.deleteStoreAccountInfo?phone={}, id={}", storeUserVo.getPhone(), storeUserVo.getSubAccountId());
+        boolean ok = storeUserService.deleteStoreAccountInfo(storeUserVo);
+        return ok ? R.success("删除成功") : R.fail("删除失败,请传子账号联系电话(phone)或用户不存在");
     }
 
     /**

+ 1 - 1
alien-store/src/main/java/shop/alien/store/service/StoreUserService.java

@@ -124,7 +124,7 @@ public interface StoreUserService extends IService<StoreUser> {
      *
      * @return boolean
      */
-    R<StoreUserVo> switchingStates(StoreUser storeUser);
+    R<StoreUserVo> switchingStates(StoreUserVo storeUser);
 
 
     /**

+ 152 - 112
alien-store/src/main/java/shop/alien/store/service/impl/StoreUserServiceImpl.java

@@ -506,7 +506,14 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
                 if (status != null && !status.equals(rowStatus)) continue;
                 filteredRoles.add(role);
             }
-            filteredRoles.sort(Comparator.comparing(StorePlatformUserRole::getId, Comparator.nullsLast(Comparator.naturalOrder())));
+            // 子账号 tab 按创建时间从近到远(降序)
+            filteredRoles.sort(Comparator.comparing(
+                    (StorePlatformUserRole r) -> {
+                        StoreUser sub = subAccountMap.get(r.getUserId());
+                        return sub != null && sub.getCreatedTime() != null ? sub.getCreatedTime() : new Date(0L);
+                    },
+                    Comparator.nullsLast(Comparator.reverseOrder())
+            ).thenComparing(StorePlatformUserRole::getId, Comparator.nullsLast(Comparator.reverseOrder())));
 
             int total = filteredRoles.size();
             storeUserVoIPage.setTotal(total);
@@ -534,11 +541,17 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
             for (StorePlatformUserRole role : pageRoles) {
                 StoreUser subAccount = subAccountMap.get(role.getUserId());
                 if (subAccount == null) continue;
+                StoreUser mainAccount = role.getStoreId() == null ? null : mainAccountMap.get(role.getStoreId());
                 StoreUserVo storeUserVo = new StoreUserVo();
                 BeanUtils.copyProperties(subAccount, storeUserVo);
-                storeUserVo.setSwitchStatus(subAccount.getStatus() != null && subAccount.getStatus() == 0);
+                // 子账号列表:账号ID 展示主账号联系方式所对应的 id(主账号ID),子账号 id 放入 subAccountId 供删除/禁用使用
+                storeUserVo.setId(mainAccount != null ? mainAccount.getId() : subAccount.getId());
+                storeUserVo.setSubAccountId(subAccount.getId());
+                // 行状态以角色为准(既是主账号也是子账号时仅禁用子账号角色,store_user 未改,列表需展示该子账号为禁用)
+                int rowStatus = role.getStatus() != null ? role.getStatus() : (subAccount.getStatus() != null ? subAccount.getStatus() : 0);
+                storeUserVo.setStatus(rowStatus);
+                storeUserVo.setSwitchStatus(rowStatus == 0);
                 storeUserVo.setPhone(subAccount.getPhone());
-                StoreUser mainAccount = role.getStoreId() == null ? null : mainAccountMap.get(role.getStoreId());
                 if (mainAccount != null) {
                     storeUserVo.setParentAccountId(mainAccount.getId());
                     storeUserVo.setParentAccountPhone(mainAccount.getPhone());
@@ -625,53 +638,76 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
 
 
     /**
-     * web端切换商家端用户状态(主账号底下有子账号时禁止禁用;子账号无限制)。
-     * 若同一账号既是主账号又是子账号:禁用时只禁用子账号角色,主账号保持启用。
+     * web端切换商家端用户状态(启用/禁用)。
+     * 1 既是主账号也是子账号且本次为禁用:只禁用子账号角色,不更新 store_user,主账号保持启用
+     * 2 对于主账号需先删除主账号下的子账号后再禁用;主账号没有关联子账号可以禁用
+     * 3 对于子账号可以禁用:对 store_platform_user_role 和 store_user 表 status 改成 1
      */
     @Override
-    public R<StoreUserVo> switchingStates(StoreUser storeUserParam) {
-        StoreUser storeUser = storeUserMapper.selectById(storeUserParam.getId());
-        if (storeUser == null) {
-            throw new RuntimeException("用户不存在");
-        }
-        // 仅当「即将禁用」时校验:主账号且该店铺下在 store_platform_user_role 中有关联子账号则禁止禁用
-        if (storeUser.getStatus() != null && storeUser.getStatus() == 0) {
-            if (storeUser.getAccountType() != null && storeUser.getAccountType() == 1) {
-                int subCount = countSubAccountUserIdsByStoreId(storeUser.getStoreId(), storeUser.getId());
-                if (subCount > 0) {
-                    throw new RuntimeException("请先删除主账号下的子账号后再禁用");
-                }
+    public R<StoreUserVo> switchingStates(StoreUserVo storeUserParam) {
+        // 默认传 0 表示执行禁用(状态改为 1),分页列表展示为禁用;传 1 表示执行启用(状态改为 0),分页列表展示为启用
+        int currentStatus = storeUserParam.getStatus() != null ? storeUserParam.getStatus() : 0;
+        int newStatus = (currentStatus == 0) ? 1 : 0;
+        boolean isMainAccount = storeUserParam.getAccountType() != null && storeUserParam.getAccountType() == 1;
+
+        if(storeUserParam.getAccountType()==2){
+            StoreUser storeUser = storeUserMapper.selectById(storeUserParam.getSubAccountId());
+            if (storeUser == null) {
+                throw new RuntimeException("用户不存在");
+            }
+            // 统计该用户在 platform 中未删除的角色数,用于判断是否「既是主账号也是子账号」
+            long roleCount = storePlatformUserRoleMapper.selectCount(
+                    new LambdaQueryWrapper<StorePlatformUserRole>()
+                            .eq(StorePlatformUserRole::getUserId, storeUser.getId())
+                            .eq(StorePlatformUserRole::getDeleteFlag, 0));
+            log.info("员工状态的status roleCount={}",roleCount);
+            boolean isBothMainAndSub = isMainAccount && roleCount > 0;
+            // 1 既是主账号也是子账号且本次为禁用:只禁用子账号角色,不更新 store_user,主账号保持启用;子账号在列表上按 role.status 展示为禁用
+            if (isBothMainAndSub) {
+                LambdaUpdateWrapper<StorePlatformUserRole> roleUpdateWrapper = new LambdaUpdateWrapper<>();
+                roleUpdateWrapper.eq(StorePlatformUserRole::getUserId, storeUser.getId())
+                        .eq(StorePlatformUserRole::getDeleteFlag, 0)
+                        .set(StorePlatformUserRole::getStatus, currentStatus);
+                storePlatformUserRoleMapper.update(null, roleUpdateWrapper);
+                StoreUserVo vo = new StoreUserVo();
+                vo.setId(storeUser.getId());
+                vo.setStatus(newStatus);
+                vo.setSwitchStatus(newStatus == 0);
+                return R.data(vo);
             }
-        }
-        int newStatus = storeUser.getStatus() == 0 ? 1 : 0;
-        // 是否既是主账号又在 store_platform_user_role 中有记录(即也是子账号)
-        long roleCount = storePlatformUserRoleMapper.selectCount(new LambdaQueryWrapper<StorePlatformUserRole>().eq(StorePlatformUserRole::getUserId, storeUser.getId()));
-        boolean isBothMainAndSub = (storeUser.getAccountType() != null && storeUser.getAccountType() == 1) && roleCount > 0;
-        if (isBothMainAndSub && newStatus == 1) {
-            // 既是主账号也是子账号且本次为禁用:只禁用子账号角色,不更新 store_user,主账号保持启用
             LambdaUpdateWrapper<StorePlatformUserRole> roleUpdateWrapper = new LambdaUpdateWrapper<>();
-            roleUpdateWrapper.eq(StorePlatformUserRole::getUserId, storeUser.getId()).set(StorePlatformUserRole::getStatus, 1);
+            roleUpdateWrapper.eq(StorePlatformUserRole::getUserId, storeUser.getId())
+                    .eq(StorePlatformUserRole::getDeleteFlag, 0)
+                    .set(StorePlatformUserRole::getStatus, currentStatus);
             storePlatformUserRoleMapper.update(null, roleUpdateWrapper);
+            baseRedisService.delete("store_" + storeUser.getPhone());
+            LambdaUpdateWrapper<StoreUser> userUpdateWrapper = new LambdaUpdateWrapper<>();
+            userUpdateWrapper.eq(StoreUser::getId, storeUser.getId()).set(StoreUser::getStatus, currentStatus);
+            storeUserMapper.update(null, userUpdateWrapper);
             StoreUserVo vo = new StoreUserVo();
             vo.setId(storeUser.getId());
-            vo.setStatus(1);
-            vo.setSwitchStatus(false);
+            vo.setStatus(newStatus);
+            vo.setSwitchStatus(newStatus == 0);
             return R.data(vo);
+
         }
-        if (newStatus == 1) {
-            baseRedisService.delete("store_" + storeUser.getPhone());
-        }
-        LambdaUpdateWrapper<StoreUser> queryWrapper = new LambdaUpdateWrapper<>();
-        queryWrapper.eq(StoreUser::getId, storeUser.getId()).set(StoreUser::getStatus, newStatus);
-        int updateCount = storeUserMapper.update(null, queryWrapper);
-        if (updateCount <= 0) {
-            throw new RuntimeException("更新失败");
+
+        // 本次为禁用
+        if (newStatus == 0) {
+            // 2 对于主账号:有关联子账号则禁止禁用,请先删除主账号下的子账号
+            if (isMainAccount) {
+                List<StoreUser> subAccounts = getSubAccountsByMainAccountId(storeUserParam.getId());
+                if (subAccounts != null && !subAccounts.isEmpty()) {
+                    throw new RuntimeException("请先删除主账号下的子账号后再禁用");
+                }
+            }
         }
-        LambdaUpdateWrapper<StorePlatformUserRole> roleUpdateWrapper = new LambdaUpdateWrapper<>();
-        roleUpdateWrapper.eq(StorePlatformUserRole::getUserId, storeUser.getId()).set(StorePlatformUserRole::getStatus, newStatus);
-        storePlatformUserRoleMapper.update(null, roleUpdateWrapper);
+        // 启用/禁用:更新 store_user 的 status(禁用 0→1,启用 1→0),列表即时展示用返回的 vo
+        LambdaUpdateWrapper<StoreUser> userUpdateWrapper = new LambdaUpdateWrapper<>();
+        userUpdateWrapper.eq(StoreUser::getId, storeUserParam.getId()).set(StoreUser::getStatus, newStatus);
+        storeUserMapper.update(null, userUpdateWrapper);
         StoreUserVo vo = new StoreUserVo();
-        vo.setId(storeUser.getId());
+        vo.setId(storeUserParam.getId());
         vo.setStatus(newStatus);
         vo.setSwitchStatus(newStatus == 0);
         return R.data(vo);
@@ -784,7 +820,14 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
             if (statusInt != null && !statusInt.equals(rowStatus)) continue;
             filteredRoles.add(role);
         }
-        filteredRoles.sort(Comparator.comparing(StorePlatformUserRole::getId, Comparator.nullsLast(Comparator.naturalOrder())));
+        // 子账号导出与列表一致:按创建时间从近到远(降序)
+        filteredRoles.sort(Comparator.comparing(
+                (StorePlatformUserRole r) -> {
+                    StoreUser sub = subAccountMap.get(r.getUserId());
+                    return sub != null && sub.getCreatedTime() != null ? sub.getCreatedTime() : new Date(0L);
+                },
+                Comparator.nullsLast(Comparator.reverseOrder())
+        ).thenComparing(StorePlatformUserRole::getId, Comparator.nullsLast(Comparator.reverseOrder())));
         List<Integer> storeIds = filteredRoles.stream().map(StorePlatformUserRole::getStoreId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
         Map<Integer, StoreUser> mainAccountMap = new HashMap<>();
         if (!storeIds.isEmpty()) {
@@ -798,19 +841,18 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
         for (StorePlatformUserRole role : filteredRoles) {
             StoreUser subAccount = subAccountMap.get(role.getUserId());
             if (subAccount == null) continue;
+            StoreUser mainAccount = role.getStoreId() == null ? null : mainAccountMap.get(role.getStoreId());
             StoreSubExcelVo vo = new StoreSubExcelVo();
             vo.setSerialNumber(++serialNumber);
-            vo.setId(subAccount.getId());
+            vo.setParentAccountId(mainAccount != null ? mainAccount.getId() : null);
+            vo.setParentAccountPhone(mainAccount != null ? mainAccount.getPhone() : null);
+            vo.setSubAccountId(subAccount.getId());
             vo.setPhone(subAccount.getPhone());
             vo.setCreatedTime(subAccount.getCreatedTime() != null ? subAccount.getCreatedTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().format(formatter) : null);
             int rowStatus = (subAccount.getStatus() != null && subAccount.getStatus() == -1) ? -1
                     : ((subAccount.getStatus() != null && subAccount.getStatus() == 2) || (subAccount.getLogoutFlag() != null && subAccount.getLogoutFlag() == 1)) ? 2
                     : (role.getStatus() != null ? role.getStatus() : (subAccount.getStatus() != null ? subAccount.getStatus() : 0));
             vo.setStatus(rowStatus == -1 ? "注销中" : rowStatus == 2 ? "已注销" : (rowStatus == 0 ? "启用" : "禁用"));
-            StoreUser mainAccount = role.getStoreId() == null ? null : mainAccountMap.get(role.getStoreId());
-            if (mainAccount != null) {
-                vo.setParentAccountPhone(mainAccount.getPhone());
-            }
             storeSubExcelVoList.add(vo);
         }
         String fileName = UUID.randomUUID().toString().replace("-", "");
@@ -1049,85 +1091,83 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
 
     @Override
     public boolean deleteStoreAccountInfo(StoreUserVo storeUserVo) {
-        LambdaQueryWrapper<StoreUser> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(StoreUser::getId, storeUserVo.getId());
-        queryWrapper.eq(StoreUser::getDeleteFlag, 0);
-        StoreUser storeUser = storeUserMapper.selectOne(queryWrapper);
-        // 主账号删除前校验:底下有店铺或有关联子账号则禁止删除
-        if (storeUser != null && storeUser.getAccountType() != null && storeUser.getAccountType() == 1) {
-            if (storeUser.getStoreId() != null) {
-                throw new RuntimeException("该主账号下存在店铺,禁止删除");
-            }
-            List<StoreUser> subAccounts = getSubAccountsByMainAccountId(storeUser.getId());
-            if (subAccounts != null && !subAccounts.isEmpty()) {
-                throw new RuntimeException("该主账号下存在关联子账号,禁止删除");
+        // 解析用户:优先用子账号联系方式 phone 查;未传 phone 时用 id/subAccountId 查 store_user,后端从库中拿到子账号联系方式(phone)
+        StoreUser storeUser = null;
+        if ((storeUserVo.getId() != null || storeUserVo.getSubAccountId() != null)) {
+            Integer idParam = storeUserVo.getSubAccountId() != null ? storeUserVo.getSubAccountId() : storeUserVo.getId();
+            storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>()
+                    .eq(StoreUser::getId, idParam).eq(StoreUser::getDeleteFlag, 0));
+            if (storeUser != null) {
+                log.info("deleteStoreAccountInfo 通过 id 查到用户,后端拿到子账号联系方式: userId={}, phone={}", storeUser.getId(), storeUser.getPhone());
             }
         }
+        if (storeUserVo == null) {
+            log.warn("deleteStoreAccountInfo 用户不存在或已删除,请传子账号联系电话(phone)或用户id");
+            return false;
+        }
+        // 通过 phone 再尝试解析用户(前端可能只传 phone)
+        if (storeUser == null && storeUserVo.getPhone() != null) {
+            storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>()
+                    .eq(StoreUser::getPhone, storeUserVo.getPhone()).eq(StoreUser::getDeleteFlag, 0));
+        }
         if (storeUser == null) {
+            log.warn("deleteStoreAccountInfo 用户不存在或已删除,请传子账号联系电话(phone)或用户id");
             return false;
         }
         Integer userId = storeUser.getId();
-        String phone = storeUser.getPhone();
-
-        // 1. 先查询该用户在所有店铺下的子账号数量(未删除的)
-        LambdaQueryWrapper<StorePlatformUserRole> countWrapper = new LambdaQueryWrapper<>();
-        countWrapper.eq(StorePlatformUserRole::getUserId, userId)
-                .eq(StorePlatformUserRole::getDeleteFlag, 0);
-        long subAccountCount = storePlatformUserRoleMapper.selectCount(countWrapper);
-        log.info("用户在所有店铺下的子账号数量: userId={}, count={}", userId, subAccountCount);
-
-        long roleCount = storePlatformUserRoleMapper.selectCount(new LambdaQueryWrapper<StorePlatformUserRole>().eq(StorePlatformUserRole::getUserId, storeUser.getId()));
-        if (roleCount != 0 || subAccountCount > 1) {
-            // 2. 逻辑删除 store_platform_user_role 表的记录
-            LambdaUpdateWrapper<StorePlatformUserRole> wrapper = new LambdaUpdateWrapper<>();
-            wrapper.eq(StorePlatformUserRole::getUserId, userId)
-                    .eq(StorePlatformUserRole::getDeleteFlag, 0)
-                    .set(StorePlatformUserRole::getDeleteFlag, 1);
-            storePlatformUserRoleMapper.update(null, wrapper);
-            log.info("该账号有多个子账号,不删除 store_user 记录: userId={}, count={}", userId, subAccountCount);
-            String tokenKey = "store_" + phone;
-            baseRedisService.delete(tokenKey);
-            return true;
-        } else if (subAccountCount == 1) {
-            // 2. 逻辑删除 store_platform_user_role 表的记录
-            LambdaUpdateWrapper<StorePlatformUserRole> updateWrapper = new LambdaUpdateWrapper<>();
-            updateWrapper.eq(StorePlatformUserRole::getUserId, userId)
-                    .eq(StorePlatformUserRole::getDeleteFlag, 0)
-                    .set(StorePlatformUserRole::getDeleteFlag, 1);
-            storePlatformUserRoleMapper.update(null, updateWrapper);
-            // 删除 token
-            String tokenKey = "store_" + phone;
-            baseRedisService.delete(tokenKey);
-            // 3. 如果只是一个账号的子账号(删除前只有1个),则需要进一步判断是否为主账号,再决定是否同时逻辑删除 store_user 表
 
-            // 主账号:逻辑删除 store_user 及关联数据(入口已保证无店铺、无子账号)
-            LambdaUpdateWrapper<StoreUser> userUpdateWrapper = new LambdaUpdateWrapper<>();
-            userUpdateWrapper.eq(StoreUser::getId, userId)
-                    .eq(StoreUser::getDeleteFlag, 0)
-                    .set(StoreUser::getDeleteFlag, 1);
-            int userUpdateResult = storeUserMapper.update(null, userUpdateWrapper);
-            if (userUpdateResult > 0) {
-                log.info("主账号仅1条 platform 记录,已逻辑删除 store_user: userId={}", userId);
-            } else {
-                log.warn("逻辑删除 store_user 记录失败或记录不存在: userId={}", userId);
+        // 删除主账号校验:该主账号下有店铺禁止删除、该主账号下有子账号禁止删除(主账号列表返回的 id 即主账号 id)
+        if (storeUserVo.getAccountType() != null && storeUserVo.getAccountType() == 1) {
+            if (storeUser.getStoreId() != null) {
+                log.error("该主账号下存在店铺,禁止删除");
+                return false;
             }
-            return true;
-        } else {
-            // 删除 token
-            String tokenKey = "store_" + phone;
-            baseRedisService.delete(tokenKey);
+            Integer mainIdForCheck = storeUserVo.getId();
+            if (mainIdForCheck != null) {
+                List<StoreUser> subAccounts = getSubAccountsByMainAccountId(mainIdForCheck);
+                if (subAccounts != null && !subAccounts.isEmpty()) {
+                    log.error("该主账号下存在关联子账号,禁止删除");
+                    return false;
+                }
+            }
+        }
+
+        // 主账号 id:优先用子账号 store_user.sub_account_id;无则用前端列表返回的 parentAccountId(与分页接口 records 字段一致)
+        Integer mainAccountId = storeUser.getSubAccountId() != null ? storeUser.getSubAccountId() : storeUserVo.getParentAccountId();
+        if (mainAccountId == null) {
+            log.warn("deleteStoreAccountInfo 无法确定主账号,请传 parentAccountId 或保证子账号 store_user.sub_account_id 有值");
+            return false;
+        }
+        // 查询主账号下的子账号数量(按 store_user 统计:account_type=2 且 sub_account_id=主账号id)
+        List<StoreUser> subAccountsUnderMain = getSubAccountsByMainAccountId(mainAccountId);
+        int subAccountCount = subAccountsUnderMain != null ? subAccountsUnderMain.size() : 0;
+        log.info("主账号下子账号数量: mainAccountId={}, subAccountCount={}", mainAccountId, subAccountCount);
+
+        // 仅删除该主账号对应店铺下的角色:取主账号的 store_id,按 userId + storeId 逻辑删除 store_platform_user_role
+        StoreUser mainAccount = storeUserMapper.selectById(mainAccountId);
+        Integer storeId = mainAccount != null ? mainAccount.getStoreId() : null;
+        LambdaUpdateWrapper<StorePlatformUserRole> roleUpdateWrapper = new LambdaUpdateWrapper<>();
+        roleUpdateWrapper.eq(StorePlatformUserRole::getUserId, userId).eq(StorePlatformUserRole::getDeleteFlag, 0);
+        if (storeId != null) {
+            roleUpdateWrapper.eq(StorePlatformUserRole::getStoreId, storeId);
+        }
+        roleUpdateWrapper.set(StorePlatformUserRole::getDeleteFlag, 1);
+        storePlatformUserRoleMapper.update(null, roleUpdateWrapper);
+
+        // 主账号下子账号唯一:逻辑删除 store_platform_user_role 和 store_user;不唯一:只逻辑删除 store_platform_user_role
+        if (subAccountCount == 1) {
             LambdaUpdateWrapper<StoreUser> userUpdateWrapper = new LambdaUpdateWrapper<>();
             userUpdateWrapper.eq(StoreUser::getId, userId)
                     .eq(StoreUser::getDeleteFlag, 0)
                     .set(StoreUser::getDeleteFlag, 1);
-            int userUpdateResult = storeUserMapper.update(null, userUpdateWrapper);
-            if (userUpdateResult > 0) {
-                log.info("用户无 platform 记录且非主账号,已逻辑删除 store_user: userId={}", userId);
-            } else {
-                log.warn("逻辑删除 store_user 记录失败或记录不存在: userId={}", userId);
-            }
-            return true;
+            storeUserMapper.update(null, userUpdateWrapper);
+            log.info("主账号下子账号唯一,已逻辑删除 store_platform_user_role 和 store_user: userId={}", userId);
+            String tokenKey = "store_" + storeUser.getPhone();
+            baseRedisService.delete(tokenKey);
+        } else {
+            log.info("主账号下子账号数不为1,仅逻辑删除 store_platform_user_role,不删 store_user: mainAccountId={}, subAccountCount={}", mainAccountId, subAccountCount);
         }
+        return true;
 
     }
 
@@ -1172,7 +1212,7 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
     @Override
     public List<StoreUser> getSubAccountsByMainAccountId(Integer mainAccountId) {
         LambdaQueryWrapper<StoreUser> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(StoreUser::getAccountType, 2)  // 子账号类型
+        queryWrapper // 子账号类型
                 .eq(StoreUser::getSubAccountId, mainAccountId)  // 关联主账号ID
                 .eq(StoreUser::getDeleteFlag, 0)  // 未删除的账号
                 .orderByDesc(StoreUser::getCreatedTime);  // 按创建时间倒序