添加用户要求信息

This commit is contained in:
zk
2026-03-12 15:07:50 +08:00
parent aa16d63c40
commit 24fe596d27
7 changed files with 197 additions and 9 deletions
@@ -33,6 +33,6 @@ public class LoginController {
public LoginVo smsLogin(@Validated @RequestBody SmsLoginDto dto,
HttpServletRequest request,
HttpServletResponse response) {
return loginServer.smsLogin(dto.getMobileNumber(), dto.getCode(), request, response);
return loginServer.smsLogin(dto.getMobileNumber(), dto.getCode(), dto.getInviteCode(), request, response);
}
}
@@ -17,4 +17,9 @@ public class SmsLoginDto {
@NotBlank(message = "验证码不能为空")
private String code;
/**
* 邀请码(可选)
*/
private String inviteCode;
}
@@ -59,6 +59,9 @@ public class LoginServer {
@Autowired
private RedisServerTool redisServerTool;
@Autowired
private UserRegisterServer userRegisterServer;
/**
* 发送短信验证码
*/
@@ -76,7 +79,7 @@ public class LoginServer {
* 短信验证码登录
*/
@Transactional(rollbackFor = Exception.class)
public LoginVo smsLogin(String mobileNumber, String code, HttpServletRequest request, HttpServletResponse response) {
public LoginVo smsLogin(String mobileNumber, String code, String inviteCode, HttpServletRequest request, HttpServletResponse response) {
Assert.hasText(mobileNumber, "手机号不能为空");
Assert.hasText(code, "验证码不能为空");
@@ -91,13 +94,7 @@ public class LoginServer {
// 用户不存在则自动注册
if (user == null) {
user = new User();
user.setMobileNumber(mobileNumber);
user.setNick("用户" + mobileNumber.substring(mobileNumber.length() - 4));
user.setStatus(0);
user.setIsDelete(0L);
user.setCreateTime(Instant.now());
userMapper.insert(user);
user = userRegisterServer.register(mobileNumber, inviteCode);
}
// 检查用户状态
@@ -0,0 +1,126 @@
package org.jiayunet.server;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jiayunet.exception.BusinessException;
import org.jiayunet.exception.BusinessExpCodeEnum;
import org.jiayunet.mapper.UserInviteMapper;
import org.jiayunet.mapper.UserMapper;
import org.jiayunet.pojo.po.User;
import org.jiayunet.pojo.po.UserInvite;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.security.SecureRandom;
import java.time.Instant;
/**
* 用户注册服务
*
* @author zk
*/
@Service
@Slf4j
public class UserRegisterServer {
/**
* 邀请码字符集(大写字母+数字)
*/
private static final String INVITE_CODE_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* 邀请码长度
*/
private static final int INVITE_CODE_LENGTH = 10;
/**
* 安全随机数生成器
*/
private static final SecureRandom RANDOM = new SecureRandom();
@Autowired
private UserMapper userMapper;
@Autowired
private UserInviteMapper userInviteMapper;
/**
* 注册新用户
*
* @param mobileNumber 手机号
* @param inviteCode 邀请码(可选)
* @return 新注册的用户
*/
@Transactional(rollbackFor = Exception.class)
public User register(String mobileNumber, String inviteCode) {
// 创建用户
User user = new User();
user.setMobileNumber(mobileNumber);
user.setNick("用户" + mobileNumber.substring(mobileNumber.length() - 4));
user.setInviteCode(generateInviteCode());
user.setStatus(0);
user.setIsDelete(0L);
user.setCreateTime(Instant.now());
userMapper.insert(user);
// 绑定邀请关系
if (StringUtils.hasText(inviteCode)) {
bindInvite(user, inviteCode);
}
return user;
}
/**
* 绑定邀请关系
*/
private void bindInvite(User user, String inviteCode) {
// 查找邀请人
User inviter = userMapper.selectOne(
new LambdaQueryWrapper<User>()
.eq(User::getInviteCode, inviteCode)
);
if (inviter == null) {
log.warn("邀请码无效 inviteCode:{} userId:{}", inviteCode, user.getId());
return;
}
// 不能自己邀请自己
if (inviter.getId().equals(user.getId())) {
return;
}
// 记录邀请关系
UserInvite invite = new UserInvite();
invite.setUserId(user.getId());
invite.setInviterId(inviter.getId());
invite.setInviteCode(inviteCode);
invite.setCreateTime(Instant.now());
userInviteMapper.insert(invite);
}
/**
* 生成10位邀请码(大写字母+数字),确保唯一
*/
private String generateInviteCode() {
for (int i = 0; i < 3; i++) {
StringBuilder sb = new StringBuilder(INVITE_CODE_LENGTH);
for (int j = 0; j < INVITE_CODE_LENGTH; j++) {
sb.append(INVITE_CODE_CHARS.charAt(RANDOM.nextInt(INVITE_CODE_CHARS.length())));
}
String code = sb.toString();
// 检查是否已存在
Long count = userMapper.selectCount(
new LambdaQueryWrapper<User>().eq(User::getInviteCode, code)
);
if (count == 0) {
return code;
}
log.warn("邀请码碰撞 code:{} 第{}次重试", code, i + 1);
}
throw new BusinessException(BusinessExpCodeEnum.UNKNOWN_ERROR, "邀请码生成失败,请重试");
}
}
@@ -0,0 +1,14 @@
package org.jiayunet.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.jiayunet.pojo.po.UserInvite;
/**
* 用户邀请记录Mapper
*
* @author zk
*/
@Mapper
public interface UserInviteMapper extends CommonMapper<UserInvite> {
}
@@ -79,6 +79,11 @@ public class User {
*/
private String wechatUnionId;
/**
* 邀请码
*/
private String inviteCode;
/**
* 状态 0 正常 1 禁用
*/
@@ -0,0 +1,41 @@
package org.jiayunet.pojo.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.Instant;
/**
* 用户邀请记录表
*
* @author zk
*/
@Data
@TableName(value = "bg_user_invite")
public class UserInvite {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 被邀请人ID
*/
private Long userId;
/**
* 邀请人ID
*/
private Long inviterId;
/**
* 使用的邀请码
*/
private String inviteCode;
/**
* 邀请时间
*/
private Instant createTime;
}