查询优化

master
zzy 2026-04-21 15:27:14 +08:00
parent d88a9ca74a
commit 7e06b0f6fd
8 changed files with 244 additions and 80 deletions

View File

@ -5,44 +5,22 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.List;
import static com.fjrcloud.community.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* - Request VO
*
* @author
*/
@Schema(description = "管理后台 - 会员用户分页 Request VO") @Schema(description = "管理后台 - 会员用户分页 Request VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class MemberUserPageReqVO extends PageParam { public class MemberUserPageReqVO extends PageParam {
/**
*
*/
@Schema(description = "手机号", example = "15601691300") @Schema(description = "手机号", example = "15601691300")
private String mobile; private String mobile;
@Schema(description = "用户昵称", example = "李四")
private String nickname;
@Schema(description = "最后登录时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] loginDate;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "会员标签编号列表", example = "[1, 2]")
private List<Long> tagIds;
@Schema(description = "会员等级编号", example = "1")
private Long levelId;
@Schema(description = "用户分组编号", example = "1")
private Long groupId;
// TODO 芋艿:注册用户类型;
// TODO 芋艿:登录用户类型;
} }

View File

@ -2,17 +2,16 @@ package com.fjrcloud.community.module.member.dal.mysql.user;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fjrcloud.community.framework.common.pojo.PageResult; import com.fjrcloud.community.framework.common.pojo.PageResult;
import com.fjrcloud.community.framework.mybatis.core.mapper.BaseMapperX; import com.fjrcloud.community.framework.mybatis.core.mapper.BaseMapperX;
import com.fjrcloud.community.framework.mybatis.core.query.LambdaQueryWrapperX; import com.fjrcloud.community.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.fjrcloud.community.module.member.controller.admin.user.vo.MemberUserPageReqVO; import com.fjrcloud.community.module.member.controller.admin.user.vo.MemberUserPageReqVO;
import com.fjrcloud.community.module.member.dal.dataobject.user.MemberUserDO; import com.fjrcloud.community.module.member.dal.dataobject.user.MemberUserDO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* User Mapper * User Mapper
@ -22,43 +21,114 @@ import java.util.stream.Collectors;
@Mapper @Mapper
public interface MemberUserMapper extends BaseMapperX<MemberUserDO> { public interface MemberUserMapper extends BaseMapperX<MemberUserDO> {
/**
*
*
* @param mobile
* @return
*/
default MemberUserDO selectByMobile(String mobile) { default MemberUserDO selectByMobile(String mobile) {
return selectOne(MemberUserDO::getMobile, mobile); return selectOne(MemberUserDO::getMobile, mobile);
} }
/**
*
*
* @param nickname
* @return
*/
default List<MemberUserDO> selectListByNicknameLike(String nickname) { default List<MemberUserDO> selectListByNicknameLike(String nickname) {
return selectList(new LambdaQueryWrapperX<MemberUserDO>() return selectList(new LambdaQueryWrapperX<MemberUserDO>()
.likeIfPresent(MemberUserDO::getNickname, nickname)); .likeIfPresent(MemberUserDO::getNickname, nickname));
} }
default PageResult<MemberUserDO> selectPage(MemberUserPageReqVO reqVO) { /**
// 处理 tagIds 过滤条件 * ID
String tagIdSql = ""; *
if (CollUtil.isNotEmpty(reqVO.getTagIds())) { * @param reqVO
tagIdSql = reqVO.getTagIds().stream() * @param tenantId ID
.map(tagId -> "FIND_IN_SET(" + tagId + ", tag_ids)") * @return
.collect(Collectors.joining(" OR ")); */
} default PageResult<MemberUserDO> selectPageByTenantId(MemberUserPageReqVO reqVO, Long tenantId) {
// 分页查询
return selectPage(reqVO, new LambdaQueryWrapperX<MemberUserDO>() return selectPage(reqVO, new LambdaQueryWrapperX<MemberUserDO>()
.likeIfPresent(MemberUserDO::getMobile, reqVO.getMobile()) .likeIfPresent(MemberUserDO::getMobile, reqVO.getMobile())
.betweenIfPresent(MemberUserDO::getLoginDate, reqVO.getLoginDate()) // 使用 EXISTS 子查询关联会员-租户关系表
.likeIfPresent(MemberUserDO::getNickname, reqVO.getNickname()) .apply("EXISTS (SELECT 1 FROM member_user_tenant_rel rel WHERE rel.user_id = member_user.id AND rel.tenant_id = {0})", tenantId)
.betweenIfPresent(MemberUserDO::getCreateTime, reqVO.getCreateTime())
.eqIfPresent(MemberUserDO::getLevelId, reqVO.getLevelId())
.eqIfPresent(MemberUserDO::getGroupId, reqVO.getGroupId())
.apply(StrUtil.isNotEmpty(tagIdSql), tagIdSql)
.orderByDesc(MemberUserDO::getId)); .orderByDesc(MemberUserDO::getId));
} }
/**
*
*
* @param reqVO
* @return
*/
default PageResult<MemberUserDO> selectPage(MemberUserPageReqVO reqVO) {
return selectPage(reqVO, buildQueryWrapper(reqVO, null));
}
/**
* ID
*
* @param reqVO
* @param userIds ID
* @return
*/
default PageResult<MemberUserDO> selectPageByUserIds(MemberUserPageReqVO reqVO, Collection<Long> userIds) {
// 如果用户ID列表为空返回空结果
if (CollUtil.isEmpty(userIds)) {
return PageResult.empty();
}
// 去重,避免生成冗余的 IN 语句
List<Long> distinctUserIds = CollUtil.distinct(userIds);
if (CollUtil.isEmpty(distinctUserIds)) {
return PageResult.empty();
}
return selectPage(reqVO, buildQueryWrapper(reqVO, distinctUserIds));
}
/**
*
*
* @param reqVO
* @param userIds ID
* @return
*/
default LambdaQueryWrapperX<MemberUserDO> buildQueryWrapper(MemberUserPageReqVO reqVO, Collection<Long> userIds) {
return new LambdaQueryWrapperX<MemberUserDO>()
.likeIfPresent(MemberUserDO::getMobile, reqVO.getMobile())
.inIfPresent(MemberUserDO::getId, userIds)
.orderByDesc(MemberUserDO::getId);
}
/**
* ID
*
* @param groupId ID
* @return
*/
default Long selectCountByGroupId(Long groupId) { default Long selectCountByGroupId(Long groupId) {
return selectCount(MemberUserDO::getGroupId, groupId); return selectCount(MemberUserDO::getGroupId, groupId);
} }
/**
* ID
*
* @param levelId ID
* @return
*/
default Long selectCountByLevelId(Long levelId) { default Long selectCountByLevelId(Long levelId) {
return selectCount(MemberUserDO::getLevelId, levelId); return selectCount(MemberUserDO::getLevelId, levelId);
} }
/**
* ID
*
* @param tagId ID
* @return
*/
default Long selectCountByTagId(Long tagId) { default Long selectCountByTagId(Long tagId) {
return selectCount(new LambdaQueryWrapperX<MemberUserDO>() return selectCount(new LambdaQueryWrapperX<MemberUserDO>()
.apply("FIND_IN_SET({0}, tag_ids)", tagId)); .apply("FIND_IN_SET({0}, tag_ids)", tagId));

View File

@ -25,6 +25,16 @@ public interface MemberUserTenantRelMapper extends BaseMapperX<MemberUserTenantR
return selectList(MemberUserTenantRelDO::getUserId, userId); return selectList(MemberUserTenantRelDO::getUserId, userId);
} }
/**
* ID
*
* @param tenantId ID
* @return
*/
default List<MemberUserTenantRelDO> selectListByTenantId(Long tenantId) {
return selectList(MemberUserTenantRelDO::getTenantId, tenantId);
}
/** /**
* IDID * IDID
* *

View File

@ -3,11 +3,15 @@ package com.fjrcloud.community.module.member.service.user;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.*; import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.fjrcloud.community.framework.common.enums.CommonStatusEnum; import com.fjrcloud.community.framework.common.enums.CommonStatusEnum;
import com.fjrcloud.community.framework.common.enums.UserTypeEnum; import com.fjrcloud.community.framework.common.enums.UserTypeEnum;
import com.fjrcloud.community.framework.common.pojo.PageResult; import com.fjrcloud.community.framework.common.pojo.PageResult;
import com.fjrcloud.community.framework.common.util.object.BeanUtils; import com.fjrcloud.community.framework.common.util.object.BeanUtils;
import com.fjrcloud.community.framework.tenant.core.context.TenantContextHolder;
import com.fjrcloud.community.module.member.controller.admin.user.vo.MemberUserPageReqVO; import com.fjrcloud.community.module.member.controller.admin.user.vo.MemberUserPageReqVO;
import com.fjrcloud.community.module.member.controller.admin.user.vo.MemberUserUpdateReqVO; import com.fjrcloud.community.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
import com.fjrcloud.community.module.member.controller.app.user.vo.*; import com.fjrcloud.community.module.member.controller.app.user.vo.*;
@ -37,6 +41,7 @@ import java.util.List;
import static com.fjrcloud.community.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.fjrcloud.community.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.fjrcloud.community.framework.common.util.servlet.ServletUtils.getClientIP; import static com.fjrcloud.community.framework.common.util.servlet.ServletUtils.getClientIP;
import static com.fjrcloud.community.framework.tenant.core.security.TenantSecurityWebFilter.SYSTEM_TENANT_ID;
import static com.fjrcloud.community.module.member.enums.ErrorCodeConstants.*; import static com.fjrcloud.community.module.member.enums.ErrorCodeConstants.*;
/** /**
@ -64,6 +69,9 @@ public class MemberUserServiceImpl implements MemberUserService {
@Resource @Resource
private MemberUserProducer memberUserProducer; private MemberUserProducer memberUserProducer;
@Resource
private MemberUserTenantRelService userTenantRelService;
@Override @Override
public MemberUserDO getUserByMobile(String mobile) { public MemberUserDO getUserByMobile(String mobile) {
return memberUserMapper.selectByMobile(mobile); return memberUserMapper.selectByMobile(mobile);
@ -77,7 +85,7 @@ public class MemberUserServiceImpl implements MemberUserService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public MemberUserDO createUserIfAbsent(String mobile, String registerIp, Integer terminal) { public MemberUserDO createUserIfAbsent(String mobile, String registerIp, Integer terminal) {
// 用户已经存在 // 用户已经存在,直接返回
MemberUserDO user = memberUserMapper.selectByMobile(mobile); MemberUserDO user = memberUserMapper.selectByMobile(mobile);
if (user != null) { if (user != null) {
return user; return user;
@ -92,37 +100,51 @@ public class MemberUserServiceImpl implements MemberUserService {
return createUser(null, nickname, avtar, registerIp, terminal); return createUser(null, nickname, avtar, registerIp, terminal);
} }
/**
*
*
* @param mobile
* @param nickname
* @param avtar
* @param registerIp IP
* @param terminal
* @return
*/
private MemberUserDO createUser(String mobile, String nickname, String avtar, private MemberUserDO createUser(String mobile, String nickname, String avtar,
String registerIp, Integer terminal) { String registerIp, Integer terminal) {
// 生成密码 // 生成随机密码
String password = IdUtil.fastSimpleUUID(); String password = IdUtil.fastSimpleUUID();
// 插入用户
// 构建用户对象
MemberUserDO user = new MemberUserDO(); MemberUserDO user = new MemberUserDO();
user.setMobile(mobile); user.setMobile(mobile);
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启状态
user.setPassword(encodePassword(password)); // 加密密码 user.setPassword(encodePassword(password)); // 加密密码
user.setRegisterIp(registerIp).setRegisterTerminal(terminal); user.setRegisterIp(registerIp).setRegisterTerminal(terminal);
user.setNickname(nickname).setAvatar(avtar); // 基础信息 user.setNickname(nickname).setAvatar(avtar); // 基础信息
// 昵称为空时,生成随机昵称
if (StrUtil.isEmpty(nickname)) { if (StrUtil.isEmpty(nickname)) {
// 昵称为空时,随机一个名字,避免一些依赖 nickname 的逻辑报错,或者有点丑。例如说,短信发送有昵称时~
user.setNickname("用户" + RandomUtil.randomNumbers(6)); user.setNickname("用户" + RandomUtil.randomNumbers(6));
} }
// 插入数据库
memberUserMapper.insert(user); memberUserMapper.insert(user);
// 发送 MQ 消息:用户创建 // 发送 MQ 消息:用户创建
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override @Override
public void afterCommit() { public void afterCommit() {
memberUserProducer.sendUserCreateMessage(user.getId()); memberUserProducer.sendUserCreateMessage(user.getId());
} }
}); });
return user; return user;
} }
@Override @Override
public void updateUserLogin(Long id, String loginIp) { public void updateUserLogin(Long id, String loginIp) {
// 更新最后登录IP和时间
memberUserMapper.updateById(new MemberUserDO().setId(id) memberUserMapper.updateById(new MemberUserDO().setId(id)
.setLoginIp(loginIp).setLoginDate(LocalDateTime.now())); .setLoginIp(loginIp).setLoginDate(LocalDateTime.now()));
} }
@ -155,11 +177,11 @@ public class MemberUserServiceImpl implements MemberUserService {
validateMobileUnique(null, reqVO.getMobile()); validateMobileUnique(null, reqVO.getMobile());
// 2.1 校验旧手机和旧验证码 // 2.1 校验旧手机和旧验证码
// 补充说明:从安全性来说,老手机也校验 oldCode 验证码会更安全。但是由于 uni-app 商城界面暂时没做,所以这里不强制校验
if (StrUtil.isNotEmpty(reqVO.getOldCode())) { if (StrUtil.isNotEmpty(reqVO.getOldCode())) {
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode()) smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode())
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())); .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));
} }
// 2.2 使用新验证码 // 2.2 使用新验证码
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode()) smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode())
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())); .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));
@ -174,6 +196,7 @@ public class MemberUserServiceImpl implements MemberUserService {
SocialWxPhoneNumberInfoRespDTO phoneNumberInfo = socialClientApi.getWxMaPhoneNumberInfo( SocialWxPhoneNumberInfoRespDTO phoneNumberInfo = socialClientApi.getWxMaPhoneNumberInfo(
UserTypeEnum.MEMBER.getValue(), reqVO.getCode()); UserTypeEnum.MEMBER.getValue(), reqVO.getCode());
Assert.notNull(phoneNumberInfo, "获得手机信息失败,结果为空"); Assert.notNull(phoneNumberInfo, "获得手机信息失败,结果为空");
// 1.2 校验新手机是否已经被绑定 // 1.2 校验新手机是否已经被绑定
validateMobileUnique(userId, phoneNumberInfo.getPhoneNumber()); validateMobileUnique(userId, phoneNumberInfo.getPhoneNumber());
@ -185,6 +208,7 @@ public class MemberUserServiceImpl implements MemberUserService {
public void updateUserPassword(Long userId, AppMemberUserUpdatePasswordReqVO reqVO) { public void updateUserPassword(Long userId, AppMemberUserUpdatePasswordReqVO reqVO) {
// 检测用户是否存在 // 检测用户是否存在
MemberUserDO user = validateUserExists(userId); MemberUserDO user = validateUserExists(userId);
// 校验验证码 // 校验验证码
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getCode()) smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getCode())
.setScene(SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene()).setUsedIp(getClientIP())); .setScene(SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene()).setUsedIp(getClientIP()));
@ -208,6 +232,12 @@ public class MemberUserServiceImpl implements MemberUserService {
.password(passwordEncoder.encode(reqVO.getPassword())).build()); .password(passwordEncoder.encode(reqVO.getPassword())).build());
} }
/**
*
*
* @param mobile
* @return
*/
private MemberUserDO validateUserExists(String mobile) { private MemberUserDO validateUserExists(String mobile) {
MemberUserDO user = memberUserMapper.selectByMobile(mobile); MemberUserDO user = memberUserMapper.selectByMobile(mobile);
if (user == null) { if (user == null) {
@ -234,12 +264,12 @@ public class MemberUserServiceImpl implements MemberUserService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateUser(MemberUserUpdateReqVO updateReqVO) { public void updateUser(MemberUserUpdateReqVO updateReqVO) {
// 校验存在 // 校验用户存在
validateUserExists(updateReqVO.getId()); validateUserExists(updateReqVO.getId());
// 校验手机唯一 // 校验手机唯一
validateMobileUnique(updateReqVO.getId(), updateReqVO.getMobile()); validateMobileUnique(updateReqVO.getId(), updateReqVO.getMobile());
// 更新 // 更新用户信息
MemberUserDO updateObj = MemberUserConvert.INSTANCE.convert(updateReqVO); MemberUserDO updateObj = MemberUserConvert.INSTANCE.convert(updateReqVO);
memberUserMapper.updateById(updateObj); memberUserMapper.updateById(updateObj);
} }
@ -261,14 +291,18 @@ public class MemberUserServiceImpl implements MemberUserService {
if (StrUtil.isBlank(mobile)) { if (StrUtil.isBlank(mobile)) {
return; return;
} }
MemberUserDO user = memberUserMapper.selectByMobile(mobile); MemberUserDO user = memberUserMapper.selectByMobile(mobile);
if (user == null) { if (user == null) {
return; return;
} }
// 如果 id 为空,说明不用比较是否为相同 id 的用户
// 如果 id 为空,说明是新增场景,手机号已被使用
if (id == null) { if (id == null) {
throw exception(USER_MOBILE_USED, mobile); throw exception(USER_MOBILE_USED, mobile);
} }
// 如果 id 不为空,检查是否为同一用户
if (!user.getId().equals(id)) { if (!user.getId().equals(id)) {
throw exception(USER_MOBILE_USED, mobile); throw exception(USER_MOBILE_USED, mobile);
} }
@ -276,12 +310,27 @@ public class MemberUserServiceImpl implements MemberUserService {
@Override @Override
public PageResult<MemberUserDO> getUserPage(MemberUserPageReqVO pageReqVO) { public PageResult<MemberUserDO> getUserPage(MemberUserPageReqVO pageReqVO) {
// 获取当前租户ID
Long currentTenantId = TenantContextHolder.getTenantId();
// 如果是系统租户,直接查询所有会员
if (SYSTEM_TENANT_ID.equals(currentTenantId)) {
return memberUserMapper.selectPage(pageReqVO); return memberUserMapper.selectPage(pageReqVO);
} }
// 校验租户ID有效性
if (currentTenantId == null) {
log.warn("[getUserPage][当前租户ID为空返回空结果]");
return PageResult.empty();
}
// 使用联表查询,一次性获取当前租户下的会员分页数据
return memberUserMapper.selectPageByTenantId(pageReqVO, currentTenantId);
}
@Override @Override
public void updateUserLevel(Long id, Long levelId, Integer experience) { public void updateUserLevel(Long id, Long levelId, Integer experience) {
// 0 代表无等级防止UpdateById时会被过滤掉的问题 // 0 代表无等级:防止 UpdateById 时被过滤掉
levelId = ObjectUtil.defaultIfNull(levelId, 0L); levelId = ObjectUtil.defaultIfNull(levelId, 0L);
memberUserMapper.updateById(new MemberUserDO() memberUserMapper.updateById(new MemberUserDO()
.setId(id) .setId(id)
@ -307,8 +356,10 @@ public class MemberUserServiceImpl implements MemberUserService {
@Override @Override
public boolean updateUserPoint(Long id, Integer point) { public boolean updateUserPoint(Long id, Integer point) {
if (point > 0) { if (point > 0) {
// 积分增加
memberUserMapper.updatePointIncr(id, point); memberUserMapper.updatePointIncr(id, point);
} else if (point < 0) { } else if (point < 0) {
// 积分减少,返回是否成功
return memberUserMapper.updatePointDecr(id, point) > 0; return memberUserMapper.updatePointDecr(id, point) > 0;
} }
return true; return true;

View File

@ -52,4 +52,7 @@ public interface MemberUserTenantRelService {
* @param tenantIds ID * @param tenantIds ID
*/ */
void batchAssignUserToTenants(Long userId, List<Long> tenantIds); void batchAssignUserToTenants(Long userId, List<Long> tenantIds);
List<MemberUserTenantRelDO> getUserTenantRelsByTenantId(Long tenantId);
} }

View File

@ -35,6 +35,11 @@ public class MemberUserTenantRelServiceImpl implements MemberUserTenantRelServic
return memberUserTenantRelMapper.selectListByUserId(userId); return memberUserTenantRelMapper.selectListByUserId(userId);
} }
@Override
public List<MemberUserTenantRelDO> getUserTenantRelsByTenantId(Long tenantId) {
return memberUserTenantRelMapper.selectListByTenantId(tenantId);
}
@Override @Override
public MemberUserTenantRelDO getUserTenantRel(Long userId, Long tenantId) { public MemberUserTenantRelDO getUserTenantRel(Long userId, Long tenantId) {
return memberUserTenantRelMapper.selectByUserIdAndTenantId(userId, tenantId); return memberUserTenantRelMapper.selectByUserIdAndTenantId(userId, tenantId);

View File

@ -9,10 +9,54 @@ import org.apache.ibatis.annotations.Mapper;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set;
@Mapper @Mapper
public interface AdminUserMapper extends BaseMapperX<AdminUserDO> { public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
/**
* ID
*
* @param reqVO
* @param deptIds ID
* @param userIds ID
* @return
*/
default PageResult<AdminUserDO> selectPage(UserPageReqVO reqVO, Set<Long> deptIds, Set<Long> userIds) {
return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
.likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername())
.likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())
.eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus())
.betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getCreateTime())
.inIfPresent(AdminUserDO::getDeptId, deptIds)
.inIfPresent(AdminUserDO::getId, userIds)
.orderByDesc(AdminUserDO::getId));
}
/**
* ID
*
* @param reqVO
* @param tenantId ID
* @return
*/
default PageResult<AdminUserDO> selectPageByTenantId(UserPageReqVO reqVO, Long tenantId) {
return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
.likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername())
.likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())
.eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus())
.betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getCreateTime())
// 使用 EXISTS 子查询关联用户-租户关系表
.apply("EXISTS (SELECT 1 FROM system_user_tenant_rel rel WHERE rel.user_id = system_users.id AND rel.tenant_id = {0})", tenantId)
.orderByDesc(AdminUserDO::getId));
}
/**
*
*
* @param username
* @return
*/
default AdminUserDO selectByUsername(String username) { default AdminUserDO selectByUsername(String username) {
return selectOne(AdminUserDO::getUsername, username); return selectOne(AdminUserDO::getUsername, username);
} }
@ -25,17 +69,6 @@ public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
return selectOne(AdminUserDO::getMobile, mobile); return selectOne(AdminUserDO::getMobile, mobile);
} }
default PageResult<AdminUserDO> selectPage(UserPageReqVO reqVO, Collection<Long> deptIds, Collection<Long> userIds) {
return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
.likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername())
.likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())
.eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus())
.betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getCreateTime())
.inIfPresent(AdminUserDO::getDeptId, deptIds)
.inIfPresent(AdminUserDO::getId, userIds)
.orderByDesc(AdminUserDO::getId));
}
default List<AdminUserDO> selectListByNickname(String nickname) { default List<AdminUserDO> selectListByNickname(String nickname) {
return selectList(new LambdaQueryWrapperX<AdminUserDO>().like(AdminUserDO::getNickname, nickname)); return selectList(new LambdaQueryWrapperX<AdminUserDO>().like(AdminUserDO::getNickname, nickname));
} }

View File

@ -50,6 +50,7 @@ import java.util.stream.Collectors;
import static com.fjrcloud.community.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.fjrcloud.community.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.fjrcloud.community.framework.common.util.collection.CollectionUtils.*; import static com.fjrcloud.community.framework.common.util.collection.CollectionUtils.*;
import static com.fjrcloud.community.framework.tenant.core.security.TenantSecurityWebFilter.SYSTEM_TENANT_ID;
import static com.fjrcloud.community.module.system.enums.ErrorCodeConstants.*; import static com.fjrcloud.community.module.system.enums.ErrorCodeConstants.*;
import static com.fjrcloud.community.module.system.enums.LogRecordConstants.*; import static com.fjrcloud.community.module.system.enums.LogRecordConstants.*;
@ -265,6 +266,10 @@ public class AdminUserServiceImpl implements AdminUserService {
@Override @Override
public PageResult<AdminUserDO> getUserPage(UserPageReqVO reqVO) { public PageResult<AdminUserDO> getUserPage(UserPageReqVO reqVO) {
Long currentTenantId = TenantContextHolder.getTenantId();
// 如果是系统租户,直接查询所有用户(支持按角色和部门过滤)
if (SYSTEM_TENANT_ID.equals(currentTenantId)) {
Set<Long> userIds = null; Set<Long> userIds = null;
if (reqVO.getRoleId() != null) { if (reqVO.getRoleId() != null) {
userIds = permissionService.getUserRoleIdListByRoleId(singleton(reqVO.getRoleId())); userIds = permissionService.getUserRoleIdListByRoleId(singleton(reqVO.getRoleId()));
@ -272,10 +277,19 @@ public class AdminUserServiceImpl implements AdminUserService {
return PageResult.empty(); return PageResult.empty();
} }
} }
return userMapper.selectPage(reqVO, getDeptCondition(reqVO.getDeptId()), userIds); return userMapper.selectPage(reqVO, getDeptCondition(reqVO.getDeptId()), userIds);
} }
// 校验租户ID有效性
if (currentTenantId == null) {
log.warn("[getUserPage][当前租户ID为空返回空结果]");
return PageResult.empty();
}
// 如果不是系统租户,使用联表查询在当前租户下有关联的用户
return userMapper.selectPageByTenantId(reqVO, currentTenantId);
}
@Override @Override
public AdminUserDO getUser(Long id) { public AdminUserDO getUser(Long id) {
return userMapper.selectById(id); return userMapper.selectById(id);