|
|
@@ -252,12 +252,10 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
|
|
|
public Map<String, String> changePhoneVerification(String phone, String oldPassword, String verificationCode) {
|
|
|
Map<String, String> changePhoneMap = new HashMap<>();
|
|
|
if (oldPassword != null && !oldPassword.equals("")) {
|
|
|
- LambdaQueryWrapper<StoreUser> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
|
|
- userLambdaQueryWrapper.eq(StoreUser::getPhone, phone);
|
|
|
- StoreUser storeUser = this.getOne(userLambdaQueryWrapper);
|
|
|
- // 由于password字段使用了EncryptTypeHandler,查询时密码会被自动解密
|
|
|
- // 所以这里直接比较解密后的密码和用户输入的明文密码
|
|
|
- if (storeUser != null && storeUser.getPassword() != null && storeUser.getPassword().equals(oldPassword)) {
|
|
|
+ LambdaUpdateWrapper<StoreUser> userLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
|
|
|
+ userLambdaUpdateWrapper.eq(StoreUser::getPhone, phone);
|
|
|
+ StoreUser storeUser = this.getOne(userLambdaUpdateWrapper);
|
|
|
+ if (storeUser.getPassword().equals(oldPassword)) {
|
|
|
changePhoneMap.put("passwordStatus", "1");
|
|
|
return changePhoneMap;
|
|
|
} else {
|
|
|
@@ -405,151 +403,215 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public R<IPage<StoreUserVo>> getStoreUserList(int pageNum, int pageSize, String id, String phone, Integer status,Integer accountType) {
|
|
|
-
|
|
|
+ public R<IPage<StoreUserVo>> getStoreUserList(int pageNum, int pageSize, String id, String phone, Integer status, Integer accountType, String mainAccountId, String mainAccountPhone) {
|
|
|
IPage<StoreUser> page = new Page<>(pageNum, pageSize);
|
|
|
IPage<StoreUserVo> storeUserVoIPage = new Page<>();
|
|
|
- // 查询子账号(accountType == 2)
|
|
|
+ // 子账号分支:以 store_platform_user_role 每条记录为一行(不去重 userId),同一子账号在不同店铺展示多行,每行带主账号 id
|
|
|
if (accountType == 2) {
|
|
|
- // 构建子账号查询条件
|
|
|
- LambdaQueryWrapper<StoreUser> subAccountWrapper = new LambdaQueryWrapper<>();
|
|
|
- subAccountWrapper.eq(StoreUser::getAccountType, 2) // 子账号类型
|
|
|
- .eq(status != null, StoreUser::getStatus, status);
|
|
|
-
|
|
|
- // 先通过中间表storePlatformUserRole获取所有子账号的userId列表
|
|
|
LambdaQueryWrapper<StorePlatformUserRole> roleWrapper = new LambdaQueryWrapper<>();
|
|
|
+ roleWrapper.eq(StorePlatformUserRole::getDeleteFlag, 0);
|
|
|
List<StorePlatformUserRole> userRoles = storePlatformUserRoleMapper.selectList(roleWrapper);
|
|
|
- List<Integer> subAccountUserIds = null;
|
|
|
- if (!CollectionUtils.isEmpty(userRoles)) {
|
|
|
- // 提取所有在中间表中的子账号userId
|
|
|
- subAccountUserIds = userRoles.stream()
|
|
|
- .map(StorePlatformUserRole::getUserId)
|
|
|
- .distinct()
|
|
|
- .collect(Collectors.toList());
|
|
|
+ if (CollectionUtils.isEmpty(userRoles)) {
|
|
|
+ storeUserVoIPage.setRecords(new ArrayList<>());
|
|
|
+ storeUserVoIPage.setTotal(0);
|
|
|
+ storeUserVoIPage.setCurrent(pageNum);
|
|
|
+ storeUserVoIPage.setSize(pageSize);
|
|
|
+ return R.data(storeUserVoIPage);
|
|
|
}
|
|
|
|
|
|
- // 当id不为空时,对ID进行模糊查询(将ID转换为字符串进行模糊匹配)
|
|
|
- if (StringUtils.isNotEmpty(id)) {
|
|
|
- // 使用apply方法,将ID转换为字符串进行模糊查询
|
|
|
- subAccountWrapper.apply("CAST(id AS CHAR) LIKE {0}", "%" + id + "%");
|
|
|
+ // 主账号ID 模糊:只保留 platform 中 store_id 属于这些主账号店铺的 role 记录
|
|
|
+ if (StringUtils.isNotEmpty(mainAccountId)) {
|
|
|
+ LambdaQueryWrapper<StoreUser> mainById = new LambdaQueryWrapper<>();
|
|
|
+ mainById.eq(StoreUser::getAccountType, 1).eq(StoreUser::getDeleteFlag, 0)
|
|
|
+ .apply("CAST(id AS CHAR) LIKE {0}", "%" + mainAccountId + "%");
|
|
|
+ List<StoreUser> mains = storeUserMapper.selectList(mainById);
|
|
|
+ List<Integer> storeIds = mains == null ? Collections.emptyList() : mains.stream().map(StoreUser::getStoreId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
|
|
+ if (storeIds.isEmpty()) {
|
|
|
+ userRoles = Collections.emptyList();
|
|
|
+ } else {
|
|
|
+ userRoles = userRoles.stream().filter(r -> storeIds.contains(r.getStoreId())).collect(Collectors.toList());
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- // 当phone不为空时,对子账号和主账号电话进行模糊查询,并关联storePlatformUserRole
|
|
|
- if (StringUtils.isNotEmpty(phone)) {
|
|
|
- if (subAccountUserIds != null && !subAccountUserIds.isEmpty()) {
|
|
|
- // 先查询主账号phone匹配的主账号ID列表
|
|
|
- LambdaQueryWrapper<StoreUser> mainAccountWrapper = new LambdaQueryWrapper<>();
|
|
|
- mainAccountWrapper.eq(StoreUser::getAccountType, 1)
|
|
|
- .like(StoreUser::getPhone, phone);
|
|
|
- List<StoreUser> mainAccounts = storeUserMapper.selectList(mainAccountWrapper);
|
|
|
- List<Integer> mainAccountIds = mainAccounts.stream()
|
|
|
- .map(StoreUser::getId)
|
|
|
- .collect(Collectors.toList());
|
|
|
-
|
|
|
- // 限制查询范围:只查询在中间表中存在的子账号
|
|
|
- subAccountWrapper.in(StoreUser::getId, subAccountUserIds);
|
|
|
- // 查询条件:在中间表范围内的子账号中,子账号phone匹配 OR 主账号phone匹配
|
|
|
- subAccountWrapper.and(wrapper -> {
|
|
|
- // 子账号本身的phone模糊查询
|
|
|
- wrapper.like(StoreUser::getPhone, phone);
|
|
|
- // 或者主账号phone匹配(通过subAccountId关联到主账号)
|
|
|
- if (!CollectionUtils.isEmpty(mainAccountIds)) {
|
|
|
- wrapper.or().in(StoreUser::getSubAccountId, mainAccountIds);
|
|
|
- }
|
|
|
- });
|
|
|
+ // 主账号联系电话 模糊:只保留 platform 中 store_id 属于这些主账号店铺的 role 记录
|
|
|
+ if (StringUtils.isNotEmpty(mainAccountPhone) && !userRoles.isEmpty()) {
|
|
|
+ LambdaQueryWrapper<StoreUser> mainByPhone = new LambdaQueryWrapper<>();
|
|
|
+ mainByPhone.eq(StoreUser::getAccountType, 1).eq(StoreUser::getDeleteFlag, 0).like(StoreUser::getPhone, mainAccountPhone);
|
|
|
+ List<StoreUser> mains = storeUserMapper.selectList(mainByPhone);
|
|
|
+ List<Integer> storeIds = mains == null ? Collections.emptyList() : mains.stream().map(StoreUser::getStoreId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
|
|
+ if (storeIds.isEmpty()) {
|
|
|
+ userRoles = Collections.emptyList();
|
|
|
} else {
|
|
|
- // 如果没有中间表数据,先查询主账号phone匹配的主账号ID
|
|
|
- LambdaQueryWrapper<StoreUser> mainAccountWrapper = new LambdaQueryWrapper<>();
|
|
|
- mainAccountWrapper.eq(StoreUser::getAccountType, 1)
|
|
|
- .like(StoreUser::getPhone, phone);
|
|
|
- List<StoreUser> mainAccounts = storeUserMapper.selectList(mainAccountWrapper);
|
|
|
- List<Integer> mainAccountIds = mainAccounts.stream()
|
|
|
- .map(StoreUser::getId)
|
|
|
- .collect(Collectors.toList());
|
|
|
-
|
|
|
- // 查询条件:子账号phone匹配 OR 主账号phone匹配
|
|
|
- if (!CollectionUtils.isEmpty(mainAccountIds)) {
|
|
|
- subAccountWrapper.and(wrapper -> {
|
|
|
- wrapper.like(StoreUser::getPhone, phone)
|
|
|
- .or().in(StoreUser::getSubAccountId, mainAccountIds);
|
|
|
- });
|
|
|
- } else {
|
|
|
- // 如果没有主账号匹配,只查询子账号phone
|
|
|
- subAccountWrapper.like(StoreUser::getPhone, phone);
|
|
|
- }
|
|
|
+ userRoles = userRoles.stream().filter(r -> storeIds.contains(r.getStoreId())).collect(Collectors.toList());
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ if (userRoles.isEmpty()) {
|
|
|
+ storeUserVoIPage.setRecords(new ArrayList<>());
|
|
|
+ storeUserVoIPage.setTotal(0);
|
|
|
+ storeUserVoIPage.setCurrent(pageNum);
|
|
|
+ storeUserVoIPage.setSize(pageSize);
|
|
|
+ return R.data(storeUserVoIPage);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按 (userId, role_id) 去重,同一用户同一角色只保留一条(保留 id 最小的一条)
|
|
|
+ userRoles = userRoles.stream()
|
|
|
+ .sorted(Comparator.comparing(StorePlatformUserRole::getId, Comparator.nullsLast(Comparator.naturalOrder())))
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ r -> (r.getUserId() != null ? r.getUserId() : 0) + "_" + (r.getRoleId() != null ? r.getRoleId() : ""),
|
|
|
+ r -> r,
|
|
|
+ (a, b) -> a
|
|
|
+ ))
|
|
|
+ .values().stream()
|
|
|
+ .sorted(Comparator.comparing(StorePlatformUserRole::getId, Comparator.nullsLast(Comparator.naturalOrder())))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 按子账号 id/phone/status 过滤:批量查 store_user,只保留对应子账号满足条件的 role
|
|
|
+ List<Integer> distinctUserIds = userRoles.stream().map(StorePlatformUserRole::getUserId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
|
|
+ List<StoreUser> subAccountList = distinctUserIds.isEmpty() ? Collections.emptyList() : storeUserMapper.selectBatchIds(distinctUserIds);
|
|
|
+ // 根据 status 参数决定子账号池:选「注销中/已注销」时只保留对应状态;否则排除注销中、已注销
|
|
|
+ Map<Integer, StoreUser> subAccountMap;
|
|
|
+ if (status != null && (status == -1 || status == 2)) {
|
|
|
+ final int filterStatus = status;
|
|
|
+ subAccountMap = subAccountList == null ? new HashMap<>() : subAccountList.stream()
|
|
|
+ .filter(u -> u.getDeleteFlag() != null && u.getDeleteFlag() == 0)
|
|
|
+ .filter(u -> {
|
|
|
+ if (filterStatus == -1) return u.getStatus() != null && u.getStatus() == -1;
|
|
|
+ return (u.getStatus() != null && u.getStatus() == 2) || (u.getLogoutFlag() != null && u.getLogoutFlag() == 1);
|
|
|
+ })
|
|
|
+ .collect(Collectors.toMap(StoreUser::getId, u -> u, (a, b) -> a));
|
|
|
} else {
|
|
|
- // phone为空时,如果中间表有数据,限制只查询中间表中的子账号
|
|
|
- if (subAccountUserIds != null && !subAccountUserIds.isEmpty()) {
|
|
|
- subAccountWrapper.in(StoreUser::getId, subAccountUserIds);
|
|
|
+ subAccountMap = subAccountList == null ? new HashMap<>() : subAccountList.stream()
|
|
|
+ .filter(u -> u.getDeleteFlag() != null && u.getDeleteFlag() == 0
|
|
|
+ && (u.getLogoutFlag() == null || u.getLogoutFlag() == 0)
|
|
|
+ && (u.getStatus() == null || (u.getStatus() != -1 && u.getStatus() != 2)))
|
|
|
+ .collect(Collectors.toMap(StoreUser::getId, u -> u, (a, b) -> a));
|
|
|
+ }
|
|
|
+ List<StorePlatformUserRole> filteredRoles = new ArrayList<>();
|
|
|
+ for (StorePlatformUserRole role : userRoles) {
|
|
|
+ StoreUser subAccount = subAccountMap.get(role.getUserId());
|
|
|
+ if (subAccount == null) continue;
|
|
|
+ if (StringUtils.isNotEmpty(id) && (subAccount.getId() == null || !String.valueOf(subAccount.getId()).contains(id)))
|
|
|
+ continue;
|
|
|
+ if (StringUtils.isNotEmpty(phone) && (subAccount.getPhone() == null || !subAccount.getPhone().contains(phone)))
|
|
|
+ continue;
|
|
|
+ // 状态筛选:选「注销中/已注销」时以 store_user 为准(已由 subAccountMap 限定);否则以 role.status 为准
|
|
|
+ int rowStatus;
|
|
|
+ if (status != null && (status == -1 || status == 2)) {
|
|
|
+ rowStatus = (subAccount.getStatus() != null && subAccount.getStatus() == -1) ? -1
|
|
|
+ : ((subAccount.getStatus() != null && subAccount.getStatus() == 2) || (subAccount.getLogoutFlag() != null && subAccount.getLogoutFlag() == 1)) ? 2
|
|
|
+ : (subAccount.getStatus() != null ? subAccount.getStatus() : 0);
|
|
|
+ } else {
|
|
|
+ rowStatus = role.getStatus() != null ? role.getStatus() : (subAccount.getStatus() != null ? subAccount.getStatus() : 0);
|
|
|
}
|
|
|
+ if (status != null && !status.equals(rowStatus)) continue;
|
|
|
+ filteredRoles.add(role);
|
|
|
+ }
|
|
|
+ filteredRoles.sort(Comparator.comparing(StorePlatformUserRole::getId, Comparator.nullsLast(Comparator.naturalOrder())));
|
|
|
+
|
|
|
+ int total = filteredRoles.size();
|
|
|
+ storeUserVoIPage.setTotal(total);
|
|
|
+ storeUserVoIPage.setCurrent(pageNum);
|
|
|
+ storeUserVoIPage.setSize(pageSize);
|
|
|
+ int from = (pageNum - 1) * pageSize;
|
|
|
+ if (from >= total) {
|
|
|
+ storeUserVoIPage.setRecords(new ArrayList<>());
|
|
|
+ return R.data(storeUserVoIPage);
|
|
|
+ }
|
|
|
+ int to = Math.min(from + pageSize, total);
|
|
|
+ List<StorePlatformUserRole> pageRoles = filteredRoles.subList(from, to);
|
|
|
+
|
|
|
+ // 批量查本页主账号,避免 N+1
|
|
|
+ List<Integer> pageStoreIds = pageRoles.stream().map(StorePlatformUserRole::getStoreId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
|
|
+ Map<Integer, StoreUser> mainAccountMap = new HashMap<>();
|
|
|
+ if (!pageStoreIds.isEmpty()) {
|
|
|
+ LambdaQueryWrapper<StoreUser> mainW = new LambdaQueryWrapper<>();
|
|
|
+ mainW.eq(StoreUser::getAccountType, 1).eq(StoreUser::getDeleteFlag, 0).in(StoreUser::getStoreId, pageStoreIds);
|
|
|
+ List<StoreUser> mains = storeUserMapper.selectList(mainW);
|
|
|
+ if (mains != null) mains.forEach(m -> mainAccountMap.put(m.getStoreId(), m));
|
|
|
}
|
|
|
|
|
|
- subAccountWrapper.orderByDesc(StoreUser::getCreatedTime);
|
|
|
-
|
|
|
- IPage<StoreUser> subAccountsPage = storeUserMapper.selectPage(page, subAccountWrapper);
|
|
|
- BeanUtils.copyProperties(subAccountsPage, storeUserVoIPage);
|
|
|
-
|
|
|
List<StoreUserVo> resultRecords = new ArrayList<>();
|
|
|
- for (StoreUser subAccount : subAccountsPage.getRecords()) {
|
|
|
+ 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);
|
|
|
-
|
|
|
- // 查询主账号信息(通过 subAccountId 关联)
|
|
|
- if (subAccount.getSubAccountId() != null) {
|
|
|
- StoreUser mainAccount = storeUserMapper.selectById(subAccount.getSubAccountId());
|
|
|
- if (mainAccount != null) {
|
|
|
- // 设置主账号联系电话
|
|
|
- storeUserVo.setParentAccountPhone(mainAccount.getPhone());
|
|
|
- storeUserVo.setParentAccountId(mainAccount.getId());
|
|
|
- storeUserVo.setParentAccountName(mainAccount.getName());
|
|
|
- }
|
|
|
+ // 分页列表:账号ID、parentAccountId 均为主账号 id(与主账号联系电话对应),子账号 id 放入 subAccountId
|
|
|
+ Integer mainId = mainAccount != null ? mainAccount.getId() : subAccount.getSubAccountId();
|
|
|
+ storeUserVo.setId(mainId != null ? mainId : subAccount.getId());
|
|
|
+ storeUserVo.setSubAccountId(subAccount.getId());
|
|
|
+ storeUserVo.setParentAccountId(mainId);
|
|
|
+ int rowStatus = role.getStatus() != null ? role.getStatus() : (subAccount.getStatus() != null ? subAccount.getStatus() : 0);
|
|
|
+ storeUserVo.setStatus(rowStatus);
|
|
|
+ storeUserVo.setSwitchStatus(rowStatus == 0);
|
|
|
+ storeUserVo.setPhone(subAccount.getPhone());
|
|
|
+ if (mainAccount != null) {
|
|
|
+ storeUserVo.setParentAccountPhone(mainAccount.getPhone());
|
|
|
+ storeUserVo.setParentAccountName(mainAccount.getName());
|
|
|
}
|
|
|
-
|
|
|
- // 不返回密码
|
|
|
storeUserVo.setPassword(null);
|
|
|
storeUserVo.setPayPassword(null);
|
|
|
-
|
|
|
resultRecords.add(storeUserVo);
|
|
|
}
|
|
|
-
|
|
|
storeUserVoIPage.setRecords(resultRecords);
|
|
|
return R.data(storeUserVoIPage);
|
|
|
}
|
|
|
|
|
|
- // 查询主账号(accountType == 1)
|
|
|
+ // 主账号分支:直接查库返回最新 status,主账号页面展示子账号数量(按 store_platform_user_role 统计);排除注销中、已注销
|
|
|
LambdaQueryWrapper<StoreUser> storeUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
|
|
- storeUserLambdaQueryWrapper.like(!StringUtils.isEmpty(id), StoreUser::getId, id)
|
|
|
- .like(!StringUtils.isEmpty(phone), StoreUser::getPhone, phone)
|
|
|
+ storeUserLambdaQueryWrapper.eq(StoreUser::getDeleteFlag, 0)
|
|
|
+ .like(StringUtils.isNotEmpty(id), StoreUser::getId, id)
|
|
|
+ .like(StringUtils.isNotEmpty(phone), StoreUser::getPhone, phone)
|
|
|
.eq(status != null, StoreUser::getStatus, status)
|
|
|
- .eq(StoreUser::getAccountType, accountType)
|
|
|
+ .eq(StoreUser::getAccountType, 1)
|
|
|
+ .and(w -> w.isNull(StoreUser::getLogoutFlag).or().eq(StoreUser::getLogoutFlag, 0))
|
|
|
+ .and(w -> w.isNull(StoreUser::getStatus).or().in(StoreUser::getStatus, 0, 1))
|
|
|
.orderByDesc(StoreUser::getCreatedTime);
|
|
|
-
|
|
|
+
|
|
|
IPage<StoreUser> storeUsers = storeUserMapper.selectPage(page, storeUserLambdaQueryWrapper);
|
|
|
BeanUtils.copyProperties(storeUsers, storeUserVoIPage);
|
|
|
-
|
|
|
- for (StoreUser storeUser : storeUserVoIPage.getRecords()) {
|
|
|
- // 不返回密码
|
|
|
- storeUser.setPassword(null);
|
|
|
- storeUser.setPayPassword(null);
|
|
|
-
|
|
|
- // 如果是主账号,统计子账号数量
|
|
|
- if (accountType == 1) {
|
|
|
- List<StoreUser> childAccounts = getChildAccountsByParentId(String.valueOf(storeUser.getId()));
|
|
|
- Integer childCount = childAccounts != null ? childAccounts.size() : 0;
|
|
|
- storeUser.setChildAccountCount(childCount);
|
|
|
- if (childAccounts != null && !childAccounts.isEmpty()) {
|
|
|
- List<String> childPhoneNumbers = childAccounts.stream()
|
|
|
- .map(StoreUser::getPhone)
|
|
|
- .collect(Collectors.toList());
|
|
|
- storeUser.setChildPhoneNumbers(childPhoneNumbers);
|
|
|
- }
|
|
|
+
|
|
|
+ List<StoreUserVo> resultRecords = new ArrayList<>();
|
|
|
+ for (StoreUser storeUser : storeUsers.getRecords()) {
|
|
|
+ StoreUserVo vo = new StoreUserVo();
|
|
|
+ BeanUtils.copyProperties(storeUser, vo);
|
|
|
+ vo.setPassword(null);
|
|
|
+ vo.setPayPassword(null);
|
|
|
+ vo.setSwitchStatus(storeUser.getStatus() != null && storeUser.getStatus() == 0);
|
|
|
+ int childCount = countSubAccountUserIdsByStoreId(storeUser.getStoreId(), storeUser.getId());
|
|
|
+ vo.setChildAccountCount(childCount);
|
|
|
+ List<Integer> childUserIds = getSubAccountUserIdsByStoreId(storeUser.getStoreId(), storeUser.getId());
|
|
|
+ if (!childUserIds.isEmpty()) {
|
|
|
+ List<StoreUser> childUsers = storeUserMapper.selectBatchIds(childUserIds);
|
|
|
+ vo.setChildPhoneNumbers(childUsers == null ? Collections.emptyList() : childUsers.stream().map(StoreUser::getPhone).collect(Collectors.toList()));
|
|
|
}
|
|
|
+ resultRecords.add(vo);
|
|
|
}
|
|
|
-
|
|
|
+ storeUserVoIPage.setRecords(resultRecords);
|
|
|
return R.data(storeUserVoIPage);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 按 store_platform_user_role 统计该店铺下子账号数量(排除主账号自身,按 distinct user_id 计)
|
|
|
+ */
|
|
|
+ private int countSubAccountUserIdsByStoreId(Integer storeId, Integer excludeUserId) {
|
|
|
+ List<Integer> userIds = getSubAccountUserIdsByStoreId(storeId, excludeUserId);
|
|
|
+ return userIds == null ? 0 : userIds.size();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 按 store_platform_user_role 查询该店铺下子账号 userId 列表(排除主账号自身)
|
|
|
+ */
|
|
|
+ private List<Integer> getSubAccountUserIdsByStoreId(Integer storeId, Integer excludeUserId) {
|
|
|
+ if (storeId == null) return Collections.emptyList();
|
|
|
+ LambdaQueryWrapper<StorePlatformUserRole> w = new LambdaQueryWrapper<>();
|
|
|
+ w.eq(StorePlatformUserRole::getStoreId, storeId).eq(StorePlatformUserRole::getDeleteFlag, 0);
|
|
|
+ if (excludeUserId != null) w.ne(StorePlatformUserRole::getUserId, excludeUserId);
|
|
|
+ List<StorePlatformUserRole> list = storePlatformUserRoleMapper.selectList(w);
|
|
|
+ return list == null ? Collections.emptyList() : list.stream().map(StorePlatformUserRole::getUserId).distinct().collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public R<StoreUserVo> editStoreUser(StoreUser storeUser) {
|
|
|
storeUserMapper.updateById(storeUser);
|
|
|
@@ -567,124 +629,226 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
|
|
|
storeUserMapper.updateById(storeUserById);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ /**
|
|
|
+ * web端切换商家端用户状态(主账号底下有子账号时禁止禁用;子账号无限制)。
|
|
|
+ * 若同一账号既是主账号又是子账号:禁用时只禁用子账号角色,主账号保持启用。
|
|
|
+ */
|
|
|
@Override
|
|
|
- public R<StoreUserVo> deleteStoreUser(String id) {
|
|
|
- StoreUser storeUser = storeUserMapper.selectById(id);
|
|
|
- String phone = storeUser.getPhone();
|
|
|
- Integer storeId = storeUser.getStoreId();
|
|
|
-
|
|
|
- // 判断该账号是否关联店铺
|
|
|
- if (ObjectUtils.isNotEmpty(storeId)) {
|
|
|
- List<StoreInfo> storeInfos = storeInfoMapper.selectList(new LambdaQueryWrapper<StoreInfo>().eq(StoreInfo::getId, storeId).eq(StoreInfo::getDeleteFlag, 0).eq(StoreInfo::getLogoutFlag, 0));
|
|
|
- if (ObjectUtils.isNotEmpty(storeInfos)) {
|
|
|
- return R.fail("请删除店铺后再删除账号");
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ LambdaUpdateWrapper<StorePlatformUserRole> roleUpdateWrapper = new LambdaUpdateWrapper<>();
|
|
|
+ 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(newStatus);
|
|
|
+ vo.setSwitchStatus(newStatus == 0);
|
|
|
+ return R.data(vo);
|
|
|
|
|
|
- storeUserMapper.deleteById(id);
|
|
|
- //删除用户redis中的token
|
|
|
- baseRedisService.delete("store_" + storeUser.getPhone());
|
|
|
- //删除该账号的店铺
|
|
|
- storeInfoMapper.delete(new LambdaQueryWrapper<StoreInfo>().eq(StoreInfo::getId, storeId));
|
|
|
- //删除该账号的动态
|
|
|
- lifeUserDynamicsMapper.delete(new LambdaQueryWrapper<LifeUserDynamics>().eq(LifeUserDynamics::getPhoneId, "store_" + phone));
|
|
|
- //删除该账号关注的信息
|
|
|
- lifeFansMapper.delete(new LambdaQueryWrapper<LifeFans>().eq(LifeFans::getFansId, "store_" + phone));
|
|
|
- //删除关注该账号的信息
|
|
|
- lifeFansMapper.delete(new LambdaQueryWrapper<LifeFans>().eq(LifeFans::getFollowedId, "store_" + phone));
|
|
|
- //删除该账号的通知信息
|
|
|
- lifeNoticeMapper.delete(new LambdaQueryWrapper<LifeNotice>().eq(LifeNotice::getReceiverId, "store_" + phone));
|
|
|
- //删除该账号的发送消息信息
|
|
|
- lifeMessageMapper.delete(new LambdaQueryWrapper<LifeMessage>().eq(LifeMessage::getSenderId, "store_" + phone));
|
|
|
- //删除该账号的接受消息信息
|
|
|
- lifeMessageMapper.delete(new LambdaQueryWrapper<LifeMessage>().eq(LifeMessage::getReceiverId, "store_" + phone));
|
|
|
-
|
|
|
- return R.success("删除成功");
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- @Override
|
|
|
- public void switchingStates(StoreUser storeUserParam) {
|
|
|
- StoreUser storeUser = storeUserMapper.selectById(storeUserParam.getId());
|
|
|
- //如果当前为启用,则删除token
|
|
|
- if (storeUser.getStatus() == 0) {
|
|
|
- //删除用户redis中的token
|
|
|
- baseRedisService.delete("store_" + storeUser.getPhone());
|
|
|
+ // 本次为禁用
|
|
|
+ if (newStatus == 0) {
|
|
|
+ // 2 对于主账号:有关联子账号则禁止禁用,请先删除主账号下的子账号
|
|
|
+ if (isMainAccount) {
|
|
|
+ List<StoreUser> subAccounts = getSubAccountsByMainAccountId(storeUserParam.getId());
|
|
|
+ if (subAccounts != null && !subAccounts.isEmpty()) {
|
|
|
+ throw new RuntimeException("请先删除主账号下的子账号后再禁用");
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- //根据当前状态切另一个状态
|
|
|
- storeUser.setStatus(storeUser.getStatus() == 0 ? 1 : 0);
|
|
|
- storeUserMapper.updateById(storeUser);
|
|
|
+ // 启用/禁用:更新 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(storeUserParam.getId());
|
|
|
+ vo.setStatus(newStatus);
|
|
|
+ vo.setSwitchStatus(newStatus == 0);
|
|
|
+ return R.data(vo);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 分页查询
|
|
|
+ *
|
|
|
+ * @param
|
|
|
+ * @param
|
|
|
+ * @param id
|
|
|
+ * @param phone
|
|
|
+ * @param status
|
|
|
+ * @param accountType
|
|
|
+ * @return
|
|
|
+ */
|
|
|
@Override
|
|
|
public String exportExcel(String id, String phone, String status, Integer accountType) throws IOException {
|
|
|
- // 定义格式化模式
|
|
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
- if (accountType==1){
|
|
|
- List<StoreUser> storeUsers = storeUserMapper.selectList(
|
|
|
- new LambdaQueryWrapper<StoreUser>()
|
|
|
- .like(StringUtils.isNotEmpty(id), StoreUser::getId, id)
|
|
|
- .like(StringUtils.isNotEmpty(phone), StoreUser::getPhone, phone)
|
|
|
- .eq(StringUtils.isNotEmpty(status), StoreUser::getStatus, status)
|
|
|
- .eq(StoreUser::getAccountType, 1)
|
|
|
- .orderByDesc(StoreUser::getCreatedTime)
|
|
|
- );
|
|
|
-
|
|
|
- List<StoreUserExcelVo> storeUserExcelVoList = new ArrayList<>();
|
|
|
- int serialNumber = 0;
|
|
|
- for (StoreUser storeUser : storeUsers) {
|
|
|
- StoreUserExcelVo storeUserExcelVo = new StoreUserExcelVo();
|
|
|
- storeUserExcelVo.setSerialNumber(++serialNumber);
|
|
|
-
|
|
|
- Integer currentUserId = storeUser.getId();
|
|
|
- BeanUtils.copyProperties(storeUser, storeUserExcelVo);
|
|
|
- Instant instant = storeUser.getCreatedTime().toInstant();
|
|
|
- // 格式化时间
|
|
|
- String formattedTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime().format(formatter);
|
|
|
- storeUserExcelVo.setCreatedTime(formattedTime);
|
|
|
- //格式化状态
|
|
|
- storeUserExcelVo.setStatus(storeUser.getStatus() == 0 ? "启用" : "禁用");
|
|
|
- List<StoreUser> childAccounts = getChildAccountsByParentId(String.valueOf(currentUserId));
|
|
|
- Integer childCount = childAccounts != null ? childAccounts.size() : 0;
|
|
|
- storeUserExcelVo.setChildAccountCount(childCount);
|
|
|
- storeUserExcelVoList.add(storeUserExcelVo);
|
|
|
+ // 主账号导出:与 getStoreUserList 主账号分支一致,子账号数量按 store_platform_user_role 统计;排除注销中、已注销
|
|
|
+ if (accountType == 1) {
|
|
|
+ LambdaQueryWrapper<StoreUser> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(StoreUser::getDeleteFlag, 0)
|
|
|
+ .like(StringUtils.isNotEmpty(id), StoreUser::getId, id)
|
|
|
+ .like(StringUtils.isNotEmpty(phone), StoreUser::getPhone, phone)
|
|
|
+ .eq(StringUtils.isNotEmpty(status), StoreUser::getStatus, status)
|
|
|
+ .eq(StoreUser::getAccountType, 1)
|
|
|
+ .and(w -> w.isNull(StoreUser::getLogoutFlag).or().eq(StoreUser::getLogoutFlag, 0))
|
|
|
+ .and(w -> w.isNull(StoreUser::getStatus).or().in(StoreUser::getStatus, 0, 1))
|
|
|
+ .orderByDesc(StoreUser::getCreatedTime);
|
|
|
+ List<StoreUser> storeUsers = storeUserMapper.selectList(wrapper);
|
|
|
+ List<StoreUserExcelVo> storeUserExcelVoList = new ArrayList<>();
|
|
|
+ int serialNumber = 0;
|
|
|
+ for (StoreUser storeUser : storeUsers) {
|
|
|
+ StoreUserExcelVo vo = new StoreUserExcelVo();
|
|
|
+ vo.setSerialNumber(++serialNumber);
|
|
|
+ BeanUtils.copyProperties(storeUser, vo);
|
|
|
+ vo.setCreatedTime(storeUser.getCreatedTime() != null ? storeUser.getCreatedTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().format(formatter) : null);
|
|
|
+ vo.setStatus(storeUser.getStatus() == null ? "" : (storeUser.getStatus() == 0 ? "启用" : "禁用"));
|
|
|
+ vo.setChildAccountCount(countSubAccountUserIdsByStoreId(storeUser.getStoreId(), storeUser.getId()));
|
|
|
+ storeUserExcelVoList.add(vo);
|
|
|
+ }
|
|
|
+ String fileName = UUID.randomUUID().toString().replace("-", "");
|
|
|
+ String filePath = ExcelGenerator.generateExcel(excelPath + excelGeneratePath + fileName + ".xlsx", storeUserExcelVoList, StoreUserExcelVo.class);
|
|
|
+ return aliOSSUtil.uploadFile(new File(filePath), "excel/" + fileName + ".xlsx");
|
|
|
}
|
|
|
- String fileName = UUID.randomUUID().toString().replace("-", "");
|
|
|
- String filePath = ExcelGenerator.generateExcel(excelPath + excelGeneratePath + fileName + ".xlsx", storeUserExcelVoList, StoreUserExcelVo.class);
|
|
|
- return aliOSSUtil.uploadFile(new File(filePath), "excel/" + fileName + ".xlsx");
|
|
|
+ // 子账号导出:与 getStoreUserList 子账号分页一致,每条 store_platform_user_role 为一行(不去重),带主账号 id
|
|
|
+ LambdaQueryWrapper<StorePlatformUserRole> roleWrapper = new LambdaQueryWrapper<>();
|
|
|
+ roleWrapper.eq(StorePlatformUserRole::getDeleteFlag, 0);
|
|
|
+ List<StorePlatformUserRole> userRoles = storePlatformUserRoleMapper.selectList(roleWrapper);
|
|
|
+ if (CollectionUtils.isEmpty(userRoles)) {
|
|
|
+ String fileName = UUID.randomUUID().toString().replace("-", "");
|
|
|
+ String filePath = ExcelGenerator.generateExcel(excelPath + excelGeneratePath + fileName + ".xlsx", new ArrayList<StoreSubExcelVo>(), StoreSubExcelVo.class);
|
|
|
+ return aliOSSUtil.uploadFile(new File(filePath), "excel/" + fileName + ".xlsx");
|
|
|
}
|
|
|
- List<StoreUser> storeUsers = storeUserMapper.selectList(
|
|
|
- new LambdaQueryWrapper<StoreUser>()
|
|
|
- .like(StringUtils.isNotEmpty(id), StoreUser::getId, id)
|
|
|
- .like(StringUtils.isNotEmpty(phone), StoreUser::getPhone, phone)
|
|
|
- .eq(StringUtils.isNotEmpty(status), StoreUser::getStatus, status)
|
|
|
- .eq(StoreUser::getAccountType, 2)
|
|
|
- .orderByDesc(StoreUser::getCreatedTime)
|
|
|
- );
|
|
|
- List<StoreSubExcelVo> storeUserExcelVoList = new ArrayList<>();
|
|
|
- int serialNumber = 0;
|
|
|
- for (StoreUser subAccount : storeUsers) {
|
|
|
- StoreSubExcelVo storeUserExcelVo = new StoreSubExcelVo();
|
|
|
- storeUserExcelVo.setSerialNumber(++serialNumber);
|
|
|
- BeanUtils.copyProperties(subAccount, storeUserExcelVo);
|
|
|
- if (subAccount.getSubAccountId() != null){
|
|
|
- StoreUser mainAccount = storeUserMapper.selectById(subAccount.getSubAccountId());
|
|
|
- if (mainAccount != null){
|
|
|
- storeUserExcelVo.setId(mainAccount.getId());
|
|
|
- storeUserExcelVo.setParentAccountPhone(mainAccount.getPhone());
|
|
|
- }
|
|
|
+ // 按 (userId, role_id) 去重,与 getStoreUserList 子账号分页一致
|
|
|
+ userRoles = userRoles.stream()
|
|
|
+ .sorted(Comparator.comparing(StorePlatformUserRole::getId, Comparator.nullsLast(Comparator.naturalOrder())))
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ r -> (r.getUserId() != null ? r.getUserId() : 0) + "_" + (r.getRoleId() != null ? r.getRoleId() : ""),
|
|
|
+ r -> r,
|
|
|
+ (a, b) -> a
|
|
|
+ ))
|
|
|
+ .values().stream()
|
|
|
+ .sorted(Comparator.comparing(StorePlatformUserRole::getId, Comparator.nullsLast(Comparator.naturalOrder())))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ List<Integer> distinctUserIds = userRoles.stream().map(StorePlatformUserRole::getUserId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
|
|
+ List<StoreUser> subAccountList = distinctUserIds.isEmpty() ? Collections.emptyList() : storeUserMapper.selectBatchIds(distinctUserIds);
|
|
|
+ Integer statusInt = null;
|
|
|
+ if (StringUtils.isNotEmpty(status)) {
|
|
|
+ try {
|
|
|
+ statusInt = Integer.parseInt(status.trim());
|
|
|
+ } catch (NumberFormatException ignored) {
|
|
|
}
|
|
|
-
|
|
|
- Instant instant = subAccount.getCreatedTime().toInstant();
|
|
|
- // 格式化时间
|
|
|
- String formattedTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime().format(formatter);
|
|
|
- storeUserExcelVo.setCreatedTime(formattedTime);
|
|
|
- //格式化状态
|
|
|
- storeUserExcelVo.setStatus(subAccount.getStatus() == 0 ? "启用" : "禁用");
|
|
|
- storeUserExcelVoList.add(storeUserExcelVo);
|
|
|
+ }
|
|
|
+ // 与 getStoreUserList 一致:选「注销中/已注销」时只保留对应状态;否则排除注销中、已注销
|
|
|
+ Map<Integer, StoreUser> subAccountMap;
|
|
|
+ if (statusInt != null && (statusInt == -1 || statusInt == 2)) {
|
|
|
+ final int filterStatus = statusInt;
|
|
|
+ subAccountMap = subAccountList == null ? new HashMap<>() : subAccountList.stream()
|
|
|
+ .filter(u -> u.getDeleteFlag() != null && u.getDeleteFlag() == 0)
|
|
|
+ .filter(u -> {
|
|
|
+ if (filterStatus == -1) return u.getStatus() != null && u.getStatus() == -1;
|
|
|
+ return (u.getStatus() != null && u.getStatus() == 2) || (u.getLogoutFlag() != null && u.getLogoutFlag() == 1);
|
|
|
+ })
|
|
|
+ .collect(Collectors.toMap(StoreUser::getId, u -> u, (a, b) -> a));
|
|
|
+ } else {
|
|
|
+ subAccountMap = subAccountList == null ? new HashMap<>() : subAccountList.stream()
|
|
|
+ .filter(u -> u.getDeleteFlag() != null && u.getDeleteFlag() == 0
|
|
|
+ && (u.getLogoutFlag() == null || u.getLogoutFlag() == 0)
|
|
|
+ && (u.getStatus() == null || (u.getStatus() != -1 && u.getStatus() != 2)))
|
|
|
+ .collect(Collectors.toMap(StoreUser::getId, u -> u, (a, b) -> a));
|
|
|
+ }
|
|
|
+ List<StorePlatformUserRole> filteredRoles = new ArrayList<>();
|
|
|
+ for (StorePlatformUserRole role : userRoles) {
|
|
|
+ StoreUser subAccount = subAccountMap.get(role.getUserId());
|
|
|
+ if (subAccount == null) continue;
|
|
|
+ if (StringUtils.isNotEmpty(id) && (subAccount.getId() == null || !String.valueOf(subAccount.getId()).contains(id)))
|
|
|
+ continue;
|
|
|
+ if (StringUtils.isNotEmpty(phone) && (subAccount.getPhone() == null || !subAccount.getPhone().contains(phone)))
|
|
|
+ continue;
|
|
|
+ int rowStatus;
|
|
|
+ if (statusInt != null && (statusInt == -1 || statusInt == 2)) {
|
|
|
+ rowStatus = (subAccount.getStatus() != null && subAccount.getStatus() == -1) ? -1
|
|
|
+ : ((subAccount.getStatus() != null && subAccount.getStatus() == 2) || (subAccount.getLogoutFlag() != null && subAccount.getLogoutFlag() == 1)) ? 2
|
|
|
+ : (subAccount.getStatus() != null ? subAccount.getStatus() : 0);
|
|
|
+ } else {
|
|
|
+ rowStatus = role.getStatus() != null ? role.getStatus() : (subAccount.getStatus() != null ? subAccount.getStatus() : 0);
|
|
|
+ }
|
|
|
+ if (statusInt != null && !statusInt.equals(rowStatus)) continue;
|
|
|
+ filteredRoles.add(role);
|
|
|
+ }
|
|
|
+ // 子账号导出与列表一致:按创建时间从近到远(降序)
|
|
|
+ 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()) {
|
|
|
+ LambdaQueryWrapper<StoreUser> mainW = new LambdaQueryWrapper<>();
|
|
|
+ mainW.eq(StoreUser::getAccountType, 1).eq(StoreUser::getDeleteFlag, 0).in(StoreUser::getStoreId, storeIds);
|
|
|
+ List<StoreUser> mains = storeUserMapper.selectList(mainW);
|
|
|
+ if (mains != null) mains.forEach(m -> mainAccountMap.put(m.getStoreId(), m));
|
|
|
+ }
|
|
|
+ List<StoreSubExcelVo> storeSubExcelVoList = new ArrayList<>();
|
|
|
+ int serialNumber = 0;
|
|
|
+ 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.setParentAccountId(mainAccount != null ? mainAccount.getId() : null);
|
|
|
+ vo.setParentAccountPhone(mainAccount != null ? mainAccount.getPhone() : null);
|
|
|
+ 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 ? "启用" : "禁用"));
|
|
|
+ storeSubExcelVoList.add(vo);
|
|
|
}
|
|
|
String fileName = UUID.randomUUID().toString().replace("-", "");
|
|
|
- String filePath = ExcelGenerator.generateExcel(excelPath + excelGeneratePath + fileName + ".xlsx", storeUserExcelVoList, StoreSubExcelVo.class);
|
|
|
+ String filePath = ExcelGenerator.generateExcel(excelPath + excelGeneratePath + fileName + ".xlsx", storeSubExcelVoList, StoreSubExcelVo.class);
|
|
|
return aliOSSUtil.uploadFile(new File(filePath), "excel/" + fileName + ".xlsx");
|
|
|
+
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -910,33 +1074,90 @@ public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 删除门店
|
|
|
+ * 删除门店
|
|
|
+ *
|
|
|
* @param storeUserVo
|
|
|
*/
|
|
|
|
|
|
@Override
|
|
|
- public void 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) {
|
|
|
- storeUserMapper.deleteById(storeUserVo.getId());
|
|
|
- nearMeService.removeGeolocation(Boolean.TRUE, storeUser.getId().toString());
|
|
|
- String storePhone = "store_" + storeUserVo.getPhone();
|
|
|
- String key = baseRedisService.getString(storePhone);
|
|
|
- if (key != null) {
|
|
|
- //删除用户redis中的token
|
|
|
- baseRedisService.delete(key);
|
|
|
+ public String deleteStoreAccountInfo(StoreUserVo storeUserVo) {
|
|
|
+ // 解析用户:优先用子账号联系方式 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());
|
|
|
}
|
|
|
- LambdaQueryWrapper<LifeFans> lifeFansLambdaQueryWrapper = new LambdaQueryWrapper<LifeFans>().eq(LifeFans::getFollowedId, "store_" + storeUser.getPhone())
|
|
|
- .or().eq(LifeFans::getFansId, "store_" + storeUser.getPhone());
|
|
|
- lifeFansMapper.delete(lifeFansLambdaQueryWrapper);
|
|
|
+ }
|
|
|
+ if (storeUserVo == null) {
|
|
|
+ log.warn("deleteStoreAccountInfo 用户不存在或已删除,请传子账号联系电话(phone)或用户id");
|
|
|
+ return "删除失败";
|
|
|
+ }
|
|
|
+ // 通过 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 "删除失败";
|
|
|
+ }
|
|
|
+ Integer userId = storeUser.getId();
|
|
|
+
|
|
|
+ // 删除主账号校验:该主账号下有店铺禁止删除、该主账号下有子账号禁止删除(主账号列表返回的 id 即主账号 id)
|
|
|
+ if (storeUserVo.getAccountType() != null && storeUserVo.getAccountType() == 1) {
|
|
|
if (storeUser.getStoreId() != null) {
|
|
|
- storeInfoMapper.deleteById(storeUser.getStoreId());
|
|
|
+ log.error("该主账号下存在店铺,禁止删除");
|
|
|
+ return "当前账号下存在店铺 禁止删除";
|
|
|
+ }
|
|
|
+ Integer mainIdForCheck = storeUserVo.getId();
|
|
|
+ if (mainIdForCheck != null) {
|
|
|
+ List<StoreUser> subAccounts = getSubAccountsByMainAccountId(mainIdForCheck);
|
|
|
+ if (subAccounts != null && !subAccounts.isEmpty()) {
|
|
|
+ log.error("该主账号下存在关联子账号,禁止删除");
|
|
|
+ return "当前账号下存在子账号禁止删除";
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // 主账号 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 "删除失败";
|
|
|
+ }
|
|
|
+ // 查询主账号下的子账号数量(按 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);
|
|
|
+ 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 "删除失败";
|
|
|
}
|
|
|
|
|
|
@Override
|