From 1e6f177e264b130cb69e79e4325156989629ec85 Mon Sep 17 00:00:00 2001
From: KKSU <15274802129@163.com>
Date: Mon, 17 Feb 2025 15:37:19 +0800
Subject: [PATCH] feat(user): 新增客服用户注册功能

---
 src/main/java/cc/mrbird/febs/user/req/ApiRegisterDto.java                 |   39 ++++++
 src/main/java/cc/mrbird/febs/user/service/IChatMemberService.java         |    8 +
 src/main/java/cc/mrbird/febs/user/conversion/ChatMemberConversion.java    |    9 +
 src/main/java/cc/mrbird/febs/user/service/Impl/ChatMemberServiceImpl.java |  147 ++++++++++++++++++++++++
 src/main/java/cc/mrbird/febs/user/controller/ChatUserController.java      |   33 +++++
 src/main/java/cc/mrbird/febs/user/entity/ChatMember.java                  |   58 +++++++++
 src/main/java/cc/mrbird/febs/common/utils/LoginUserUtil.java              |    6 +
 src/main/java/cc/mrbird/febs/user/mapper/ChatMemberMapper.java            |    7 +
 src/main/java/cc/mrbird/febs/common/interceptor/LoginInterceptor.java     |   13 -
 src/main/java/cc/mrbird/febs/common/utils/SubMailSend.java                |    2 
 10 files changed, 312 insertions(+), 10 deletions(-)

diff --git a/src/main/java/cc/mrbird/febs/common/interceptor/LoginInterceptor.java b/src/main/java/cc/mrbird/febs/common/interceptor/LoginInterceptor.java
index 4e1b19c..690b068 100644
--- a/src/main/java/cc/mrbird/febs/common/interceptor/LoginInterceptor.java
+++ b/src/main/java/cc/mrbird/febs/common/interceptor/LoginInterceptor.java
@@ -4,7 +4,7 @@
 import cc.mrbird.febs.common.utils.AppContants;
 import cc.mrbird.febs.common.utils.RedisUtils;
 import cc.mrbird.febs.common.utils.SpringContextUtil;
-import cc.mrbird.febs.mall.entity.MallMember;
+import cc.mrbird.febs.user.entity.ChatMember;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.crypto.asymmetric.KeyType;
 import cn.hutool.crypto.asymmetric.RSA;
@@ -20,10 +20,6 @@
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
-/**
- * @author xxx
- * @date 2020-08-24
- **/
 @Slf4j
 public class LoginInterceptor implements HandlerInterceptor {
 
@@ -51,10 +47,9 @@
             responseUnAuth(response);
             return false;
         }
-        MallMember member = JSON.parseObject(userJsonStr, MallMember.class);
-
-        request.getSession().setAttribute("member", member);
-//        log.info("登录用户token:"+token+",PHONE:"+member.getPhone());
+        ChatMember chatMember = JSON.parseObject(userJsonStr, ChatMember.class);
+        request.getSession().setAttribute("chatMember", chatMember);
+        log.info("登录用户{},{}",chatMember.getEmail(),token);
         return true;
     }
 
diff --git a/src/main/java/cc/mrbird/febs/common/utils/LoginUserUtil.java b/src/main/java/cc/mrbird/febs/common/utils/LoginUserUtil.java
index 08cdb4a..c059894 100644
--- a/src/main/java/cc/mrbird/febs/common/utils/LoginUserUtil.java
+++ b/src/main/java/cc/mrbird/febs/common/utils/LoginUserUtil.java
@@ -1,6 +1,7 @@
 package cc.mrbird.febs.common.utils;
 
 import cc.mrbird.febs.mall.entity.MallMember;
+import cc.mrbird.febs.user.entity.ChatMember;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
@@ -16,4 +17,9 @@
         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
         return (MallMember) request.getSession().getAttribute("member");
     }
+
+    public static ChatMember getLoginChatMember() {
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
+        return (ChatMember) request.getSession().getAttribute("chatMember");
+    }
 }
diff --git a/src/main/java/cc/mrbird/febs/common/utils/SubMailSend.java b/src/main/java/cc/mrbird/febs/common/utils/SubMailSend.java
index 9ff0e30..dd7db56 100644
--- a/src/main/java/cc/mrbird/febs/common/utils/SubMailSend.java
+++ b/src/main/java/cc/mrbird/febs/common/utils/SubMailSend.java
@@ -87,8 +87,8 @@
     private static boolean request(JSONObject vars, String project, String to) {
         TreeMap<String, Object> requestData = new TreeMap<String, Object>();
         requestData.put("appid", APP_ID);
-        requestData.put("project", project);
         requestData.put("to", to);
+        requestData.put("project", project);
         requestData.put("from", FROM);
         if (!vars.isEmpty()) {
             requestData.put("vars", vars.toString());
diff --git a/src/main/java/cc/mrbird/febs/user/controller/ChatUserController.java b/src/main/java/cc/mrbird/febs/user/controller/ChatUserController.java
new file mode 100644
index 0000000..90e2d82
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/user/controller/ChatUserController.java
@@ -0,0 +1,33 @@
+package cc.mrbird.febs.user.controller;
+
+import cc.mrbird.febs.common.entity.FebsResponse;
+import cc.mrbird.febs.user.req.ApiRegisterDto;
+import cc.mrbird.febs.user.service.IChatMemberService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+@Slf4j
+@RestController
+@RequestMapping(value = "/api/chatUser")
+@RequiredArgsConstructor
+@CrossOrigin("*")
+@Api(value = "ChatUserController", tags = "客服用户")
+public class ChatUserController {
+
+    private final IChatMemberService chatMemberService;
+
+    /**
+     * 主账号注册 主账号添加子账号
+     * @param apiRegisterDto
+     * @return
+     */
+    @ApiOperation(value = "注册", notes = "注册")
+    @PostMapping(value = "/register")
+    public FebsResponse register(@RequestBody ApiRegisterDto apiRegisterDto) {
+        return chatMemberService.register(apiRegisterDto);
+    }
+
+}
diff --git a/src/main/java/cc/mrbird/febs/user/conversion/ChatMemberConversion.java b/src/main/java/cc/mrbird/febs/user/conversion/ChatMemberConversion.java
new file mode 100644
index 0000000..9332205
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/user/conversion/ChatMemberConversion.java
@@ -0,0 +1,9 @@
+package cc.mrbird.febs.user.conversion;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+@Mapper
+public abstract class ChatMemberConversion {
+    public static final ChatMemberConversion INSTANCE = Mappers.getMapper(ChatMemberConversion.class);
+}
diff --git a/src/main/java/cc/mrbird/febs/user/entity/ChatMember.java b/src/main/java/cc/mrbird/febs/user/entity/ChatMember.java
new file mode 100644
index 0000000..7d38bba
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/user/entity/ChatMember.java
@@ -0,0 +1,58 @@
+package cc.mrbird.febs.user.entity;
+
+import cc.mrbird.febs.common.entity.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ *
+ `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '联系手机号码',
+ `email` varchar(90) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '注册邮箱',
+ `password` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '登录密码',
+ `trade_password` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '支付密码',
+ `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '昵称',
+ `sex` int DEFAULT '0' COMMENT '性别 0-女 1-男性 2-未填写',
+ `invite_id` varchar(8) DEFAULT NULL COMMENT '邀请码',
+ `referrer_id` varchar(8) DEFAULT NULL COMMENT '推荐人邀请码',
+ `referrer_ids` text COMMENT '推荐人线路',
+ `level` varchar(255) DEFAULT NULL COMMENT '代理层级',
+ `account_status` int DEFAULT '1' COMMENT '账户状态;1-正常 0-禁用',
+ `account_type` int DEFAULT '0' COMMENT '账户类型;1-正常用户 0-测试账户',
+ `avatar` varchar(500) DEFAULT NULL COMMENT '头像',
+ `director` int DEFAULT '2' COMMENT '是否是主账号 1-是 0-否',
+ `director_time` datetime DEFAULT NULL COMMENT '购买套餐的时间',
+ `director_fail_time` datetime DEFAULT NULL COMMENT '套餐到期时间',
+ `last_login_time` datetime DEFAULT NULL COMMENT '上一次登录时间',
+ `company_id` bigint DEFAULT NULL COMMENT '公司ID',
+ `role_id` bigint DEFAULT NULL COMMENT '角色ID',
+ */
+@Data
+@TableName("chat_member")
+public class ChatMember extends BaseEntity {
+
+    private String phone;//联系手机号码
+    private String email;//注册邮箱
+    private String password;//登录密码
+    private String tradePassword;//支付密码
+    private String name;//昵称
+    private Integer sex;//性别 0-女 1-男性 2-未填写
+    private String inviteId;//邀请码
+    private String referrerId;//推荐人邀请码
+    private String referrerIds;//推荐人线路
+    private String level;//代理层级
+    private Integer accountStatus;//账户状态;1-正常 0-禁用
+    private Integer accountType;//账户类型;1-正常用户 0-测试账户
+    private String avatar;//头像
+    private Integer director;//是否是主账号 1-是 0-否
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date directorTime;//购买套餐的时间
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date directorFailTime;//套餐到期时间
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date lastLoginTime;//上一次登录时间
+    private Long companyId;//公司ID
+    private Long roleId;//角色ID
+}
diff --git a/src/main/java/cc/mrbird/febs/user/mapper/ChatMemberMapper.java b/src/main/java/cc/mrbird/febs/user/mapper/ChatMemberMapper.java
new file mode 100644
index 0000000..6b44beb
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/user/mapper/ChatMemberMapper.java
@@ -0,0 +1,7 @@
+package cc.mrbird.febs.user.mapper;
+
+import cc.mrbird.febs.user.entity.ChatMember;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+public interface ChatMemberMapper extends BaseMapper<ChatMember> {
+}
diff --git a/src/main/java/cc/mrbird/febs/user/req/ApiRegisterDto.java b/src/main/java/cc/mrbird/febs/user/req/ApiRegisterDto.java
new file mode 100644
index 0000000..9aa774d
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/user/req/ApiRegisterDto.java
@@ -0,0 +1,39 @@
+package cc.mrbird.febs.user.req;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+@ApiModel(value = "ApiRegisterDto", description = "用户注册参数类")
+public class ApiRegisterDto {
+
+    @NotBlank(message = "邮箱不能为空!")
+    @ApiModelProperty(value = "邮箱", example = "152@163.com")
+    private String account;
+
+    @NotBlank(message = "类型不能为空!")
+    @ApiModelProperty(value = "类型 1-手机号 2-邮箱", example = "1")
+    private String type = "1";
+
+    @NotBlank(message = "验证码不能为空")
+    @ApiModelProperty(value = "验证码", example = "123456")
+    private String code;
+
+    @NotBlank(message = "密码不能为空")
+    @ApiModelProperty(value = "密码", example = "123456")
+    private String password;
+
+    @NotBlank(message = "密码不能为空")
+    @ApiModelProperty(value = "重复密码", example = "123456")
+    private String passwordAgain;
+
+    @ApiModelProperty(value = "邀请码")
+    private String inviteId;
+
+    @NotBlank(message = "注册类型不能为空")
+    @ApiModelProperty(value = "注册类型 1-正常注册 0-手动添加子账号", example = "1")
+    private Integer registerType;//注册类型 1-正常注册 0-手动添加子账号
+}
diff --git a/src/main/java/cc/mrbird/febs/user/service/IChatMemberService.java b/src/main/java/cc/mrbird/febs/user/service/IChatMemberService.java
new file mode 100644
index 0000000..a1552d3
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/user/service/IChatMemberService.java
@@ -0,0 +1,8 @@
+package cc.mrbird.febs.user.service;
+
+import cc.mrbird.febs.common.entity.FebsResponse;
+import cc.mrbird.febs.user.req.ApiRegisterDto;
+
+public interface IChatMemberService {
+    FebsResponse register(ApiRegisterDto apiRegisterDto);
+}
diff --git a/src/main/java/cc/mrbird/febs/user/service/Impl/ChatMemberServiceImpl.java b/src/main/java/cc/mrbird/febs/user/service/Impl/ChatMemberServiceImpl.java
new file mode 100644
index 0000000..e7963ea
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/user/service/Impl/ChatMemberServiceImpl.java
@@ -0,0 +1,147 @@
+package cc.mrbird.febs.user.service.Impl;
+
+import cc.mrbird.febs.common.entity.FebsResponse;
+import cc.mrbird.febs.common.enumerates.YesOrNoEnum;
+import cc.mrbird.febs.common.exception.FebsException;
+import cc.mrbird.febs.common.utils.AppContants;
+import cc.mrbird.febs.common.utils.ShareCodeUtil;
+import cc.mrbird.febs.mall.entity.MallMember;
+import cc.mrbird.febs.mall.entity.MallMemberWallet;
+import cc.mrbird.febs.mall.entity.RunVip;
+import cc.mrbird.febs.user.entity.ChatMember;
+import cc.mrbird.febs.user.mapper.ChatMemberMapper;
+import cc.mrbird.febs.user.req.ApiRegisterDto;
+import cc.mrbird.febs.user.service.IChatMemberService;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.crypto.SecureUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+@Transactional
+public class ChatMemberServiceImpl extends ServiceImpl<ChatMemberMapper, ChatMember> implements IChatMemberService {
+
+    @Override
+    public FebsResponse register(ApiRegisterDto apiRegisterDto) {
+        String account = apiRegisterDto.getAccount();
+
+        MallMember mallMember = this.baseMapper.selectInfoByAccount(account);
+        if (mallMember != null) {
+            throw new FebsException("手机号已注册");
+        }
+        /**
+         * 验证两次密码是否一致
+         */
+        String password = registerDto.getPassword();
+        String passwordAgain = registerDto.getPasswordAgain();
+        if(!password.equals(passwordAgain)){
+            throw new FebsException("密码不一致");
+        }
+
+        //邀请码为admin的时候(后台添加用户),不需要验证验证码
+        if (!"admin".equals(registerDto.getRegistType())) {
+            String code = registerDto.getCode();
+            boolean flags = commonService.verifyCode(account, code);
+            if (!flags) {
+                throw new FebsException("验证码错误");
+            }
+        }
+
+        mallMember = new MallMember();
+        mallMember.setPassword(SecureUtil.md5(registerDto.getPassword()));
+
+        // 判断账号类型
+        if (AppContants.ACCOUNT_TYPE_MOBILE.equals(registerDto.getType())) {
+            mallMember.setPhone(registerDto.getAccount());
+        } else {
+            mallMember.setEmail(registerDto.getAccount());
+        }
+        //对于邀请码的验证和上级联系人的验证
+        Integer count = this.baseMapper.selectCount(null);
+        if (count != null && count != 0) {
+            if(StrUtil.isEmpty(registerDto.getInviteId())){
+                throw new FebsException("请输入邀请码");
+            }
+            String inviteId = registerDto.getInviteId();
+            MallMember inviteMember = this.baseMapper.selectInfoByInviteId(inviteId);
+            if (inviteMember == null) {
+                throw new FebsException("邀请码不存在");
+            }
+            mallMember.setReferrerId(registerDto.getInviteId());
+//            if(!StrUtil.isEmpty(registerDto.getInviteId())){
+//                String inviteId = registerDto.getInviteId();
+//                MallMember inviteMember = this.baseMapper.selectInfoByInviteId(inviteId);
+//                if (inviteMember == null) {
+//                    throw new FebsException("邀请码不存在");
+//                }
+//                mallMember.setReferrerId(registerDto.getInviteId());
+//            }
+        }
+        mallMember.setName(account);
+        mallMember.setAvatar("https://res.runstep.cc/rslogo.png");
+        mallMember.setAccountStatus(YesOrNoEnum.YES.getValue());
+        mallMember.setAccountType(MallMember.ACCOUNT_TYPE_NORMAL);
+        mallMember.setSex("男");
+        mallMember.setDirector(YesOrNoEnum.NO.getValue());
+        mallMember.setDirectorTime(DateUtil.date());
+        mallMember.setBindPhone(account);
+
+        this.baseMapper.insert(mallMember);
+
+        String inviteId = ShareCodeUtil.toSerialCode(mallMember.getId());
+        mallMember.setInviteId(inviteId);
+
+        //推荐人和推荐人链
+        boolean flag = false;
+        String parentId = mallMember.getReferrerId();
+        if (StrUtil.isBlank(parentId)) {
+            flag = true;
+        }
+        String ids = "";
+        while (!flag) {
+            if (StrUtil.isBlank(ids)) {
+                ids += parentId;
+            } else {
+                ids += ("," + parentId);
+            }
+            MallMember parentMember = this.baseMapper.selectInfoByInviteId(parentId);
+            if (parentMember == null) {
+                break;
+            }
+            parentId = parentMember.getReferrerId();
+            if (StrUtil.isBlank(parentMember.getReferrerId())) {
+                flag = true;
+            }
+        }
+
+        if (StrUtil.isNotBlank(ids)) {
+            mallMember.setReferrerIds(ids);
+        }
+        //会员VIP等级
+        List<RunVip> runVips = runVipMapper.selectList(new LambdaQueryWrapper<RunVip>().orderByAsc(RunVip::getOrderNumber));
+        if (StrUtil.isBlank(mallMember.getLevel()) && CollUtil.isNotEmpty(runVips)) {
+            RunVip runVip = runVips.get(0);
+            mallMember.setLevel(runVip.getVipCode());
+        }
+        this.baseMapper.updateById(mallMember);
+
+        MallMemberWallet wallet = new MallMemberWallet();
+        wallet.setBalance(BigDecimal.ZERO);
+        wallet.setMemberId(mallMember.getId());
+        mallMemberWalletMapper.insert(wallet);
+
+        agentProducer.sendNodeUpMsg(mallMember.getId());
+        return new FebsResponse().success().message("注册成功");
+    }
+}

--
Gitblit v1.9.1