package com.ruoyi.web.controller.user;
|
|
import cn.hutool.core.util.ObjectUtil;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.github.pagehelper.PageInfo;
|
import com.ruoyi.common.constant.HttpStatus;
|
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.im.comm.Result;
|
import com.ruoyi.im.dto.RegisterDto;
|
import com.ruoyi.im.out.UserAccountOut;
|
import com.ruoyi.im.service.ImApiServcie;
|
import com.ruoyi.im.service.UserKycService;
|
import com.ruoyi.im.service.UserPolicyService;
|
import com.ruoyi.im.util.ConverterUtil;
|
import com.ruoyi.im.util.PhoneNumberValidatorUtil;
|
import com.ruoyi.im.util.SymmetricCryptoUtil;
|
import com.ruoyi.system.domain.UserAccount;
|
import com.ruoyi.system.domain.UserKyc;
|
import com.ruoyi.system.domain.UserPolicy;
|
import com.ruoyi.system.domain.vo.UserAccountUpdateVo;
|
import com.ruoyi.system.domain.vo.UserAccountVo;
|
import com.ruoyi.system.service.UserAccountService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.util.CollectionUtils;
|
import org.springframework.validation.annotation.Validated;
|
import org.springframework.web.bind.annotation.*;
|
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
@RestController
|
@RequestMapping("/im/user")
|
@Slf4j
|
public class UserController extends BaseController {
|
|
@Autowired
|
UserAccountService userAccountService;
|
|
@Autowired
|
private ImApiServcie imApiServcie;
|
|
@Autowired
|
private UserKycService userKycService;
|
|
@Autowired
|
UserPolicyService userPolicyService;
|
|
/**
|
* 获取会员列表
|
*/
|
@GetMapping("/list")
|
public TableDataInfo list(UserAccountVo vo)
|
{
|
// 创建查询条件包装器
|
LambdaQueryWrapper<UserAccount> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
LambdaQueryWrapper<UserPolicy> userPolicyWrapper = new LambdaQueryWrapper<>();
|
userPolicyWrapper
|
.eq(UserPolicy::getApprovalStatus, 1)
|
.eq(UserPolicy::getPayStatus,2)
|
.select(UserPolicy::getUserId);
|
List<UserPolicy> userPolicies = userPolicyService.list(userPolicyWrapper);
|
List<Integer> userIds = userPolicies.stream()
|
.map(UserPolicy::getUserId)
|
.collect(Collectors.toList());
|
if(null != vo.getActivate() && vo.getActivate()){
|
queryWrapper.in(UserAccount::getId,userIds);
|
}else if(null != vo.getActivate() && !vo.getActivate()){
|
queryWrapper.notIn(UserAccount::getId,userIds);
|
}
|
|
if (ObjectUtil.isNotEmpty(vo.getKeywords())) {
|
String keywords = vo.getKeywords().trim();
|
if (StringUtils.isNotEmpty(keywords)) {
|
queryWrapper.and(wrapper -> wrapper
|
.eq(UserAccount::getInvitationCode, keywords)
|
.or()
|
// 使用右模糊匹配,可以利用索引
|
.likeRight(UserAccount::getPhoneNumber, keywords)
|
.or()
|
.likeRight(UserAccount::getAccount, keywords)
|
.or()
|
.likeRight(UserAccount::getNickname, keywords)
|
);
|
}
|
}
|
|
// 添加其他条件
|
queryWrapper
|
.eq(ObjectUtil.isNotEmpty(vo.getAccountType()), UserAccount::getAccountType, vo.getAccountType())
|
.eq(ObjectUtil.isNotEmpty(vo.getStatus()), UserAccount::getStatus, vo.getStatus())
|
.eq(ObjectUtil.isNotEmpty(vo.getPosition()), UserAccount::getPosition, vo.getPosition())
|
.between(ObjectUtil.isAllNotEmpty(vo.getStartTime(), vo.getEndTime()),
|
UserAccount::getCreateTime, vo.getStartTime(), vo.getEndTime());
|
|
// 默认按创建时间倒序
|
queryWrapper.orderByDesc(UserAccount::getCreateTime);
|
startPage();
|
List<UserAccount> list = userAccountService.list(queryWrapper);
|
|
List<Integer> idList = list.stream()
|
.map(UserAccount::getId)
|
.collect(Collectors.toList());
|
if(!CollectionUtils.isEmpty(idList)){
|
List<UserKyc> kycList = userKycService.list(new LambdaQueryWrapper<UserKyc>()
|
.in(UserKyc::getUserId, idList)
|
);
|
|
Map<Integer, UserKyc> kycMap = kycList.stream()
|
.collect(Collectors.toMap(UserKyc::getUserId, kyc -> kyc));
|
|
list.forEach(f->{
|
if(ObjectUtil.isNotEmpty(kycMap.get(f.getId()))){
|
f.setName(kycMap.get(f.getId()).getName());
|
f.setIdCard(kycMap.get(f.getId()).getIdCard());
|
}
|
});
|
}
|
|
PageInfo<UserAccount> pageInfo = new PageInfo<>(list);
|
|
// 转换为输出对象并递归加载下级列表(最多3级)
|
List<UserAccountOut> toList = convertToUserAccountOutWithSubordinates(list, 3);
|
|
TableDataInfo rspData = new TableDataInfo();
|
rspData.setCode(HttpStatus.SUCCESS);
|
rspData.setMsg("查询成功");
|
rspData.setRows(toList);
|
rspData.setTotal(pageInfo.getTotal());
|
return rspData;
|
}
|
|
/**
|
* 转换用户账户列表并递归加载下级用户
|
* @param userAccounts 用户账户列表
|
* @param maxLevel 最大递归层级
|
* @return 包含下级列表的用户输出对象列表
|
*/
|
private List<UserAccountOut> convertToUserAccountOutWithSubordinates(List<UserAccount> userAccounts, int maxLevel) {
|
if (ObjectUtil.isEmpty(userAccounts) || maxLevel <= 0) {
|
return new ArrayList<>();
|
}
|
// 收集用户ID用于查询激活状态
|
List<Integer> idList = userAccounts.stream()
|
.map(UserAccount::getId)
|
.filter(ObjectUtil::isNotEmpty)
|
.collect(Collectors.toList());
|
|
// 批量查询激活状态
|
Set<Integer> activatedUserIds = Collections.emptySet();
|
if (!idList.isEmpty()) {
|
LambdaQueryWrapper<UserPolicy> userPolicyWrapper = new LambdaQueryWrapper<>();
|
userPolicyWrapper.in(UserPolicy::getUserId, idList)
|
.eq(UserPolicy::getApprovalStatus, 1)
|
.select(UserPolicy::getUserId);
|
|
List<UserPolicy> policyList = userPolicyService.list(userPolicyWrapper);
|
activatedUserIds = policyList.stream()
|
.map(UserPolicy::getUserId)
|
.collect(Collectors.toSet());
|
}
|
|
// 转换基础信息并设置激活状态
|
List<UserAccountOut> result = new ArrayList<>();
|
for (UserAccount user : userAccounts) {
|
UserAccountOut out = ConverterUtil.convert(user, UserAccountOut.class);
|
// 设置激活状态
|
out.setActivate(activatedUserIds.contains(user.getId()));
|
result.add(out);
|
}
|
|
// 递归加载下级用户
|
loadSubordinateUsersRecursive(result, maxLevel);
|
|
return result;
|
}
|
|
/**
|
* 递归加载多级下级用户
|
* @param userAccountOuts 当前层级的用户列表
|
* @param remainingLevels 剩余递归层级
|
*/
|
private void loadSubordinateUsersRecursive(List<UserAccountOut> userAccountOuts, int remainingLevels) {
|
if (ObjectUtil.isEmpty(userAccountOuts) || remainingLevels <= 0) {
|
return;
|
}
|
|
// 加载当前级别的下级用户
|
loadCurrentLevelSubordinates(userAccountOuts);
|
|
// 递归加载下级的下级
|
for (UserAccountOut user : userAccountOuts) {
|
if (ObjectUtil.isNotEmpty(user.getSubordinateList())) {
|
loadSubordinateUsersRecursive(user.getSubordinateList(), remainingLevels - 1);
|
}
|
}
|
}
|
|
private void loadCurrentLevelSubordinates(List<UserAccountOut> userAccountOuts) {
|
if (ObjectUtil.isEmpty(userAccountOuts)) {
|
return;
|
}
|
|
// 收集所有用户的账号(用于查询下级)
|
List<String> accounts = userAccountOuts.stream()
|
.map(UserAccountOut::getAccount)
|
.filter(ObjectUtil::isNotEmpty)
|
.distinct()
|
.collect(Collectors.toList());
|
|
if (accounts.isEmpty()) {
|
userAccountOuts.forEach(user -> user.setSubordinateList(new ArrayList<>()));
|
return;
|
}
|
|
// 批量查询所有直接下级用户
|
LambdaQueryWrapper<UserAccount> queryWrapper = new LambdaQueryWrapper<>();
|
queryWrapper.in(UserAccount::getInvitationAccount, accounts);
|
List<UserAccount> allSubordinates = userAccountService.list(queryWrapper);
|
|
// 转换为输出对象
|
List<UserAccountOut> allSubordinateOuts = ConverterUtil.convertToList(allSubordinates, UserAccountOut.class);
|
|
// === 新增:为下级用户设置激活状态 ===
|
setActivateStatusForUsers(allSubordinateOuts);
|
// =================================
|
|
// 收集所有需要设置 KYC 的用户(当前层级 + 下级)
|
List<UserAccountOut> allUsers = new ArrayList<>();
|
allUsers.addAll(userAccountOuts);
|
allUsers.addAll(allSubordinateOuts);
|
|
// 一次性设置所有用户的 KYC 信息
|
setKycInfoForUsers(allUsers);
|
|
// 按邀请人账号分组
|
Map<String, List<UserAccountOut>> subordinateMap = allSubordinateOuts.stream()
|
.filter(sub -> ObjectUtil.isNotEmpty(sub.getInvitationAccount()))
|
.collect(Collectors.groupingBy(UserAccountOut::getInvitationAccount));
|
|
// 为每个用户设置下级列表
|
for (UserAccountOut user : userAccountOuts) {
|
if (ObjectUtil.isNotEmpty(user.getAccount())) {
|
List<UserAccountOut> subordinates = subordinateMap.get(user.getAccount());
|
user.setSubordinateList(ObjectUtil.isNotEmpty(subordinates) ? subordinates : new ArrayList<>());
|
} else {
|
user.setSubordinateList(new ArrayList<>());
|
}
|
}
|
}
|
|
/**
|
* 为用户列表设置激活状态
|
*/
|
private void setActivateStatusForUsers(List<UserAccountOut> users) {
|
if (ObjectUtil.isEmpty(users)) {
|
return;
|
}
|
|
// 收集用户ID
|
List<Integer> idList = users.stream()
|
.map(UserAccountOut::getId)
|
.filter(ObjectUtil::isNotEmpty)
|
.collect(Collectors.toList());
|
|
if (idList.isEmpty()) {
|
return;
|
}
|
|
// 批量查询激活状态
|
LambdaQueryWrapper<UserPolicy> userPolicyWrapper = new LambdaQueryWrapper<>();
|
userPolicyWrapper.in(UserPolicy::getUserId, idList)
|
.eq(UserPolicy::getApprovalStatus, 1)
|
.select(UserPolicy::getUserId);
|
|
List<UserPolicy> policyList = userPolicyService.list(userPolicyWrapper);
|
Set<Integer> activatedUserIds = policyList.stream()
|
.map(UserPolicy::getUserId)
|
.collect(Collectors.toSet());
|
|
// 设置激活状态
|
users.forEach(user -> {
|
user.setActivate(activatedUserIds.contains(user.getId()));
|
});
|
}
|
|
/**
|
* 为用户列表设置 KYC 信息
|
*/
|
private void setKycInfoForUsers(List<UserAccountOut> users) {
|
if (ObjectUtil.isEmpty(users)) {
|
return;
|
}
|
|
// 收集用户ID
|
List<Integer> idList = users.stream()
|
.map(UserAccountOut::getId)
|
.filter(ObjectUtil::isNotEmpty)
|
.collect(Collectors.toList());
|
|
if (idList.isEmpty()) {
|
return;
|
}
|
|
// 批量查询 KYC 信息
|
List<UserKyc> kycList = userKycService.list(new LambdaQueryWrapper<UserKyc>()
|
.in(UserKyc::getUserId, idList)
|
);
|
|
// 转换为 Map
|
Map<Integer, UserKyc> kycMap = kycList.stream()
|
.collect(Collectors.toMap(UserKyc::getUserId, kyc -> kyc, (existing, replacement) -> existing));
|
|
// 设置 KYC 信息
|
users.forEach(user -> {
|
if (ObjectUtil.isNotEmpty(user.getId()) && ObjectUtil.isNotEmpty(kycMap.get(user.getId()))) {
|
UserKyc kyc = kycMap.get(user.getId());
|
user.setName(kyc.getName());
|
user.setIdCard(kyc.getIdCard());
|
}
|
});
|
}
|
|
/**
|
* 获取用户的下级树形结构
|
* @param userId 用户ID
|
* @param maxLevel 最大层级深度
|
* @return 用户下级树形结构
|
*/
|
@GetMapping("/subordinateTree/{userId}")
|
public AjaxResult getSubordinateTree(@PathVariable Integer userId,
|
@RequestParam(defaultValue = "3") int maxLevel) {
|
try {
|
UserAccount userAccount = userAccountService.getById(userId);
|
if (ObjectUtil.isEmpty(userAccount)) {
|
return AjaxResult.error("用户不存在");
|
}
|
|
// 转换当前用户
|
UserAccountOut userOut = ConverterUtil.convert(userAccount, UserAccountOut.class);
|
|
// 递归加载下级树
|
List<UserAccountOut> userList = new ArrayList<>();
|
userList.add(userOut);
|
loadSubordinateUsersRecursive(userList, maxLevel);
|
|
return AjaxResult.success(userOut);
|
} catch (Exception e) {
|
log.error("获取用户下级树失败", e);
|
return AjaxResult.error("获取下级树失败");
|
}
|
}
|
|
/**
|
* 获取用户的直接下级列表(不分页)
|
*/
|
@GetMapping("/directSubordinates/{userId}")
|
public AjaxResult getDirectSubordinates(@PathVariable Integer userId) {
|
try {
|
UserAccount userAccount = userAccountService.getById(userId);
|
if (ObjectUtil.isEmpty(userAccount)) {
|
return AjaxResult.error("用户不存在");
|
}
|
|
// 查询直接下级
|
LambdaQueryWrapper<UserAccount> queryWrapper = new LambdaQueryWrapper<>();
|
queryWrapper.eq(UserAccount::getInvitationAccount, userAccount.getAccount());
|
List<UserAccount> subordinates = userAccountService.list(queryWrapper);
|
|
List<UserAccountOut> result = ConverterUtil.convertToList(subordinates, UserAccountOut.class);
|
return AjaxResult.success(result);
|
} catch (Exception e) {
|
log.error("获取直接下级列表失败", e);
|
return AjaxResult.error("获取下级列表失败");
|
}
|
}
|
|
|
|
|
|
/**
|
* 修改会员
|
*/
|
// @PreAuthorize("@ss.hasPermi('im:user:updateUserAccount')")
|
@PostMapping("/updateUserAccount")
|
public AjaxResult updateUserAccount(UserAccountUpdateVo vo) {
|
|
try {
|
UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper<UserAccount>()
|
.eq(UserAccount::getAccount,vo.getAccount())
|
);
|
if(ObjectUtil.isEmpty(userAccount)){
|
return AjaxResult.error("会员不存在!");
|
}
|
if(StringUtils.isNotEmpty(vo.getPhoneNumber())){
|
PhoneNumberValidatorUtil.ValidationResult result = PhoneNumberValidatorUtil.validatePhoneNumber(vo.getPhoneNumber());
|
if(!result.isValid()){
|
return AjaxResult.error("手机号格式不正确!");
|
}
|
}
|
if(StringUtils.isNotEmpty(vo.getPassword()) && StringUtils.isEmpty(vo.getOldPassword())){
|
return AjaxResult.error("旧密码不能为空!");
|
}
|
if(StringUtils.isNotEmpty(vo.getPassword())){
|
String s = SymmetricCryptoUtil.decryptPassword(userAccount.getPassword());
|
if(!vo.getOldPassword().equals(s)){
|
return AjaxResult.error("旧密码不正确!");
|
}
|
}
|
vo.setAccount(userAccount.getCloudMessageAccount());
|
return imApiServcie.updateUserAccount(vo);
|
}catch (Exception e){
|
e.printStackTrace();
|
logger.error("修改会员失败!");
|
}
|
return AjaxResult.success();
|
}
|
|
/**
|
* 创建会员
|
*/
|
@PostMapping("/batchRegister")
|
public Result batchRegister(@Validated RegisterDto dto){
|
try {
|
if(null == dto.getType()){
|
return Result.error("类型不能为空");
|
}else if(dto.getType() == 2){
|
if(StringUtils.isEmpty(dto.getAccount())){
|
return Result.error("账号不能为空");
|
}
|
if(StringUtils.isEmpty(dto.getPassword())){
|
return Result.error("密码不能为空");
|
}
|
if(StringUtils.isEmpty(dto.getNikeName())){
|
return Result.error("昵称不能为空");
|
}
|
}else if (dto.getType() == 1){
|
if(dto.getNumber() <= 0){
|
return Result.error("数量不能为空");
|
}else if(dto.getNumber() > 100){
|
return Result.error("批量注册最多一次100");
|
}
|
}
|
return imApiServcie.batchRegister(dto);
|
}catch (Exception e){
|
e.printStackTrace();
|
log.error("-----------批量注册报错------------");
|
return Result.error("注册失败,请稍后再试!");
|
}
|
}
|
|
}
|