package com.backendsys.modules.material.service.impl; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.bean.BeanUtil; import cn.hutool.json.JSONUtil; import com.backendsys.exception.CustException; import com.backendsys.modules.common.config.redis.utils.RedisUtil; import com.backendsys.modules.common.config.security.entity.SecurityUserInfo; import com.backendsys.modules.common.config.security.utils.CaptchaUtil; import com.backendsys.modules.common.config.security.utils.JwtUtil; import com.backendsys.modules.common.config.security.utils.LockStatusUtil; import com.backendsys.modules.common.config.security.utils.SecurityUtil; import com.backendsys.modules.material.entity.MaterialAudit; import com.backendsys.modules.material.entity.MaterialUser; import com.backendsys.modules.material.service.MaterialUserService; import com.backendsys.modules.sse.entity.SseResponse; import com.backendsys.modules.sse.entity.SseResponseEnum; import com.backendsys.modules.sse.utils.SseUtil; import com.backendsys.modules.system.dao.SysUserDao; import com.backendsys.modules.system.dao.SysUserInfoDao; import com.backendsys.modules.system.dao.SysUserRoleDao; import com.backendsys.modules.system.dao.SysUserRoleRelationDao; import com.backendsys.modules.system.entity.*; import com.backendsys.modules.system.service.SysAuthService; import com.backendsys.modules.system.service.SysCommonService; import com.backendsys.modules.system.service.SysUserIntegralService; import com.backendsys.modules.system.service.SysUserService; import com.backendsys.modules.system.utils.UserUtil; import com.backendsys.utils.response.PageEntity; import com.backendsys.utils.response.PageInfoResult; import com.backendsys.utils.v2.PageUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.env.Environment; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @Service public class MaterialUserServiceImpl implements MaterialUserService { @Autowired private UserUtil userUtil; @Autowired private SseUtil sseUtil; @Value("${spring.application.name}") private String APPLICATION_NAME; @Value("${tencent.sms.debug}") private String SMS_DEBUG; @Autowired private Environment env; @Autowired private LockStatusUtil lockStatusUtil; @Autowired private CaptchaUtil captchaUtil; @Autowired private RedisUtil redisUtil; @Autowired private SysUserDao sysUserDao; @Autowired private SysUserInfoDao sysUserInfoDao; @Autowired private SysUserRoleDao sysUserRoleDao; @Autowired private SysUserRoleRelationDao sysUserRoleRelationDao; @Autowired private SysAuthService sysAuthService; @Autowired private SysUserService sysUserService; @Autowired private SysCommonService sysCommonService; @Autowired private SysUserIntegralService sysUserIntegralService; /** * 获取素材用户列表 ({ invite_code = Material }) */ @Override public PageEntity selectMaterialUserList(String phone, Long role_id) { PageUtils.startPage(); // 分页 SysUserDTO sysUserDTO = new SysUserDTO(); sysUserDTO.setPhone(phone); sysUserDTO.setInvite_code("Material"); if (role_id != null) { sysUserDTO.setRole_id(Arrays.asList(role_id)); } List user_info_list = sysUserInfoDao.selectUserList(sysUserDTO); return new PageInfoResult(user_info_list).toEntity(); } /** * 获取素材用户角色列表 */ @Override public List selectMaterialUserRoleList() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.likeRight(SysUserRole::getRole_sign, "MATERIAL"); wrapper.orderByAsc(SysUserRole::getSort); List list = sysUserRoleDao.selectList(wrapper); return list; } /** * 审核素材用户 */ @Override @Transactional(rollbackFor = Exception.class) public Map auditMaterialUser(MaterialAudit materialAudit) { // 判断是否为素材用户 / 用户是否存在 SysUserInfo entity = new SysUserInfo(); entity.setUser_id(materialAudit.getUser_id()); entity.setInvite_code("Material"); SysUserInfo userInfo = sysUserService.selectUserInfo(entity); if (userInfo == null) throw new CustException("用户不存在"); // 判断用户是否待审核状态 (-1审核拒绝, 1待审核, 2审核通过) if (materialAudit.getUser_id() == SecurityUtil.getUserId()) throw new CustException("不能审核自己"); // [DB] 获取素材用户角色ID集合 List role_list = selectMaterialUserRoleList(); List role_ids = role_list.stream().map(SysUserRole::getRole_id).toList(); if (!role_ids.contains(materialAudit.getRole_id())) throw new CustException("必须指定素材用户角色"); // [DB] 更新用户信息-审核状态/用户状态 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(SysUserInfo::getUser_id, materialAudit.getUser_id()); wrapper.eq(SysUserInfo::getInvite_code, "Material"); // userInfo.setAudit_status(materialAudit.getAudit_status()); userInfo.setAudit_note("素材管理审核通过"); userInfo.setStatus(materialAudit.getStatus()); sysUserInfoDao.update(userInfo, wrapper); // // 如果是禁用状态,则清除该用户的登录信息 // if (materialAudit.getStatus() == -1) { // sysUserService.kickUser(materialAudit.getUser_id()); // } // [DB] 更新用户与角色关系 (先删,后增) LambdaQueryWrapper wrapperRoleRelation = new LambdaQueryWrapper<>(); wrapperRoleRelation.eq(SysUserRoleRelation::getUser_id, materialAudit.getUser_id()); sysUserRoleRelationDao.delete(wrapperRoleRelation); sysUserRoleRelationDao.insertBatch(materialAudit.getUser_id(), Arrays.asList(materialAudit.getRole_id())); // [2025-08-18] 需求:后台加白后,前台踢掉用户,强制让该用户重新登录; // https://www.tapd.cn/tapd_fe/61244365/story/detail/1161244365001000497 sysUserService.kickUser(materialAudit.getUser_id()); // // 重置的过期时间直接给7天 // Long tokenDurationMilliseconds = userUtil.getTokenDuration(true); // Integer tokenDurationHours = Convert.toInt(tokenDurationMilliseconds / 3600000L); // // 实时更新缓存: 用户信息 // SysUserInfo userInfoLasest = sysUserService.selectUserInfo(entity); // // 赋加缓存时间 { token_expiration } // SysUserInfo userInfoLasestCatch = userUtil.syncUpdateUserCatch(userInfoLasest, tokenDurationHours, true); // // 发送SSE消息到前端 // sseUtil.send(userInfoLasestCatch.getUser_id(), new SseResponse(SseResponseEnum.SYSTEM_USER_UPDATE, userInfoLasestCatch).toJsonStr()); return Map.of("user_id", materialAudit.getUser_id()); } // 注册素材用户 (手机号注册) @Override @Transactional(rollbackFor = Exception.class) public Map registerMaterialUser(MaterialUser materialUser) { // 判断是否允许注册 // [系统配置] 是否允许系统用户注册 Boolean SYSTEM_USER_ALLOW_REGISTER = Convert.toBool(sysCommonService.getCommonByTag("SYSTEM_USER_ALLOW_REGISTER")); if (!SYSTEM_USER_ALLOW_REGISTER) throw new CustException("系统已禁止注册"); String phone = materialUser.getPhone(); Integer phoneAreaCode = materialUser.getPhone_area_code(); Integer phoneValidCode = materialUser.getPhone_valid_code(); String activeProfile = env.getActiveProfiles()[0]; //if (!"local".equals(activeProfile)) { // // 判断是否处于登录错误的冻结状态 (2分钟内错误5次,则出现冻结提示) // lockStatusUtil.checkLockStatus(APPLICATION_NAME + "-register-error", phone); // // 判断图形验证码是否正确 // if (!captchaUtil.isCaptchaValid(captcha, httpRequestUtil.getKaptchaKey())) { // loginFail("验证码错误", username, false); // return null; // } //} // 判断短信验证码是否正确 if (!"local".equals(activeProfile)) { String redisKey = APPLICATION_NAME + "-sms-" + phone; Integer smsCode = redisUtil.getCacheObject(redisKey); // 判断是否发送验证码 if ("false".equals(SMS_DEBUG) && smsCode == null) throw new CustException("请先发送短信验证码"); // 判断短信验证码是否错误 if ("false".equals(SMS_DEBUG) && !smsCode.equals(phoneValidCode)) sysAuthService.loginFail("短信验证码错误", phone, true); } // [查询] 判断手机号是否存在 (如果存在就直接登录,返回Token) LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(SysUser::getPhone, phone).eq(SysUser::getPhone_area_code, phoneAreaCode); SysUser sysUserDetail = sysUserDao.selectOne(queryWrapper); if (sysUserDetail != null) { // [已注册] 返回登录信息 (并且7天免登录) SysUserInfo sysUserInfo = sysAuthService.loginSuccess(sysUserDetail.getId(), true); Map response = BeanUtil.beanToMap(sysUserInfo); response.put("is_register", false); return response; // } else { // [未注册] 通过校验并注册 (注册成功后,返回登录信息) // 注册 SysUserDTO registerEntity = new SysUserDTO(); registerEntity.setUsername(phone); registerEntity.setPhone(phone); registerEntity.setPhone_area_code(phoneAreaCode); registerEntity.setInvite_code("Material"); // 注册时,使用 [素材游客] 权限 (MATERIAL_GUEST) String role_sign = "MATERIAL_GUEST"; LambdaQueryWrapper wrapperRole = new LambdaQueryWrapper<>(); wrapperRole.eq(SysUserRole::getRole_sign, role_sign); SysUserRole roleDetail = sysUserRoleDao.selectOne(wrapperRole); registerEntity.setRole_id(Arrays.asList(roleDetail.getRole_id())); // 注册时,审核状态为 待审核 (-1拒绝, 1待审核, 2审核通过) registerEntity.setAudit_status(2); // 随机昵称 (6位) registerEntity.setNickname("用户" + RandomUtil.randomStringUpper(6)); // 创建用户 sysUserDao.insertUser(registerEntity); // 初始化用户积分 sysUserIntegralService.init(registerEntity.getId()); // [DB] 查询用户信息 SysUserInfo sysUserInfo = sysAuthService.loginSuccess(registerEntity.getId(), true); Map response = BeanUtil.beanToMap(sysUserInfo); response.put("is_register", true); return response; } } }