From 7a639d578ab75915c50dcfd9d78cfa8912bb9e5d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=BB=99=E9=A3=8E=E9=81=93=E9=AA=A8=E5=B0=8F=E5=8D=8A?=
=?UTF-8?q?=E4=BB=99=E5=84=BF?= <414571696@qq.com>
Date: Wed, 19 Mar 2025 01:06:14 +0800
Subject: [PATCH] =?UTF-8?q?1.=20member.controller.app.auth=20=E6=B7=BB?=
=?UTF-8?q?=E5=8A=A0customerRegister=E6=B3=A8=E5=86=8C=E6=96=B9=E6=B3=95?=
=?UTF-8?q?=202.=20=E6=B7=BB=E5=8A=A0register=E6=B6=88=E6=81=AF=E9=98=9F?=
=?UTF-8?q?=E5=88=97=EF=BC=8C=E6=B3=A8=E5=86=8C=E5=90=8C=E6=AD=A5=E5=8F=91?=
=?UTF-8?q?=E9=80=81mq=EF=BC=8C=E6=B3=A8=E5=86=8Cmenmber=E4=BF=A1=E6=81=AF?=
=?UTF-8?q?=E6=97=B6=E5=90=8C=E6=AD=A5=E5=A2=9E=E5=8A=A0crm=E5=AE=A2?=
=?UTF-8?q?=E6=88=B7=E4=BF=A1=E6=81=AF=EF=BC=8C=E6=A0=B9=E6=8D=AE=E6=98=AF?=
=?UTF-8?q?=E5=90=A6=E5=AD=98=E5=9C=A8=E9=82=80=E8=AF=B7=E7=A0=81=E5=86=B3?=
=?UTF-8?q?=E5=AE=9A=E5=BD=92=E5=B1=9E=EF=BC=8C=E6=97=A0=E9=82=80=E8=AF=B7?=
=?UTF-8?q?=E7=A0=81=E8=BF=9B=E5=85=A5=E5=85=AC=E6=B5=B7=202.=20LoginLogTy?=
=?UTF-8?q?peEnum=E6=B7=BB=E5=8A=A0=E6=89=8B=E6=9C=BA=E6=B3=A8=E5=86=8C?=
=?UTF-8?q?=E7=B1=BB=E5=9E=8B=E6=9E=9A=E4=B8=BE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../crm/api/customer/CrmCustomerApi.java | 16 +++++
.../api/customer/dto/CrmCustomerRespDTO.java | 13 ++++
.../module/crm/enums/LogRecordConstants.java | 4 ++
.../customer/CrmCustomerServiceImpl.java | 42 ++++++++++++-
.../yudao-module-member-biz/pom.xml | 6 ++
.../app/auth/AppAuthController.java | 7 +++
.../app/auth/vo/AppAuthCrmLoginReqVO.java | 32 ++++++++++
.../register/RegisterSendConsumer.java | 24 ++++++++
.../message/register/RegisterSendMessage.java | 30 ++++++++++
.../producer/register/RegisterProducer.java | 32 ++++++++++
.../service/auth/MemberAuthService.java | 10 +++-
.../service/auth/MemberAuthServiceImpl.java | 11 +++-
.../service/user/MemberUserService.java | 10 ++++
.../service/user/MemberUserServiceImpl.java | 59 +++++++++++++++++++
.../system/enums/logger/LoginLogTypeEnum.java | 1 +
15 files changed, 292 insertions(+), 5 deletions(-)
create mode 100644 yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java
create mode 100644 yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/dto/CrmCustomerRespDTO.java
create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthCrmLoginReqVO.java
create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/consumer/register/RegisterSendConsumer.java
create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/message/register/RegisterSendMessage.java
create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/register/RegisterProducer.java
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java
new file mode 100644
index 0000000000..5849e86fb6
--- /dev/null
+++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/CrmCustomerApi.java
@@ -0,0 +1,16 @@
+package cn.iocoder.yudao.module.crm.api.customer;
+
+import jakarta.validation.constraints.NotNull;
+
+public interface CrmCustomerApi {
+
+ /**
+ * 执行真正的邮件发送
+ * 注意,该方法仅仅提供给 MQ Consumer 使用
+ *
+ * @param mobile 手机号
+ * @param loginIp 登录 IP
+ * @param invitationCode 邀请码
+ */
+ void doCreate(@NotNull(message = "手机号不能为空") String mobile, String loginIp, String invitationCode);
+}
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/dto/CrmCustomerRespDTO.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/dto/CrmCustomerRespDTO.java
new file mode 100644
index 0000000000..8b37fc0428
--- /dev/null
+++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/customer/dto/CrmCustomerRespDTO.java
@@ -0,0 +1,13 @@
+package cn.iocoder.yudao.module.crm.api.customer.dto;
+import lombok.Data;
+
+@Data
+public class CrmCustomerRespDTO {
+
+ /**
+ * 编号
+ */
+ private Long id;
+
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
index aeeed316dd..03ca8568f0 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
+++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
@@ -29,6 +29,10 @@ public interface LogRecordConstants {
String CRM_CUSTOMER_TYPE = "CRM 客户";
String CRM_CUSTOMER_CREATE_SUB_TYPE = "创建客户";
String CRM_CUSTOMER_CREATE_SUCCESS = "创建了客户{{#customer.name}}";
+
+ String CRM_MEMBER_CUSTOMER_CREATE_SUB_TYPE = "会员同步建客户";
+ String CRM_MEMBER_CUSTOMER_CREATE_SUCCESS = "会员【{{#mobile}}】同步建了客户【{{#mobile}}】";
+
String CRM_CUSTOMER_UPDATE_SUB_TYPE = "更新客户";
String CRM_CUSTOMER_UPDATE_SUCCESS = "更新了客户【{{#customerName}}】: {_DIFF{#updateReqVO}}";
String CRM_CUSTOMER_DELETE_SUB_TYPE = "删除客户";
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
index 75d3af0138..ed7e35ad0e 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
+++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
@@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractTransferReqVO;
@@ -47,7 +48,6 @@ import java.time.LocalDateTime;
import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
@@ -63,7 +63,7 @@ import static java.util.Collections.singletonList;
@Service
@Slf4j
@Validated
-public class CrmCustomerServiceImpl implements CrmCustomerService {
+public class CrmCustomerServiceImpl implements CrmCustomerService, CrmCustomerApi {
@Resource
private CrmCustomerMapper customerMapper;
@@ -660,4 +660,42 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
return SpringUtil.getBean(getClass());
}
+
+
+
+ @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_MEMBER_CUSTOMER_CREATE_SUB_TYPE, bizNo = "{{#mobile}}",
+ success = CRM_MEMBER_CUSTOMER_CREATE_SUCCESS)
+ @Override
+ public void doCreate(String mobile, String loginIp, String invitationCode) {
+ CrmCustomerSaveReqVO createReqVO = new CrmCustomerSaveReqVO();
+ createReqVO.setId(null);
+ createReqVO.setMobile(mobile);
+
+
+ // 邀请码是否为空判断
+ if (StrUtil.isNotBlank(invitationCode)) {
+ AdminUserRespDTO adminUserRespDTO = adminUserApi.getUserByInvitationCode(invitationCode);
+ // 根据邀请码校验负责人用户是否存在
+ if (adminUserRespDTO == null) {
+ createReqVO.setOwnerUserId(null); // 不存在,则设置为null,客户进入公海
+ }else{
+ createReqVO.setOwnerUserId(adminUserRespDTO.getId()); //存在,设置负责人ID,创建归属
+ }
+ }
+
+ // 1. 校验拥有客户是否到达上限
+ validateCustomerExceedOwnerLimit(createReqVO.getOwnerUserId(), 1);
+
+ // 2. 插入客户
+ CrmCustomerDO customer = initCustomer(createReqVO, createReqVO.getOwnerUserId());
+ customerMapper.insert(customer);
+
+ // 3. 创建数据权限
+ permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
+ .setBizId(customer.getId()).setUserId(createReqVO.getOwnerUserId()).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置邀请人为负责人
+
+ // 4. 记录操作日志上下文
+ LogRecordContext.putVariable("customer", customer);
+
+ }
}
diff --git a/yudao-module-member/yudao-module-member-biz/pom.xml b/yudao-module-member/yudao-module-member-biz/pom.xml
index 3c9b81e65b..fda0c0b487 100644
--- a/yudao-module-member/yudao-module-member-biz/pom.xml
+++ b/yudao-module-member/yudao-module-member-biz/pom.xml
@@ -85,6 +85,12 @@
cn.iocoder.boot
yudao-spring-boot-starter-biz-ip
+
+ cn.iocoder.boot
+ yudao-module-crm-api
+ 2.4.1-SNAPSHOT
+ compile
+
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java
index 0693f02b2d..d526c871a3 100644
--- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java
@@ -49,6 +49,13 @@ public class AppAuthController {
return success(authService.login(reqVO));
}
+ @PostMapping("/customer-register")
+ @Operation(summary = "客户注册")
+ @PermitAll
+ public CommonResult customerRegister(AppAuthCrmLoginReqVO reqVO) {
+ return success(authService.customerRegister(reqVO));
+ }
+
@PostMapping("/logout")
@Operation(summary = "登出系统")
@PermitAll
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthCrmLoginReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthCrmLoginReqVO.java
new file mode 100644
index 0000000000..310c495d18
--- /dev/null
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthCrmLoginReqVO.java
@@ -0,0 +1,32 @@
+package cn.iocoder.yudao.module.member.controller.app.auth.vo;
+
+
+import cn.iocoder.yudao.framework.common.validation.Mobile;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.validator.constraints.Length;
+import jakarta.validation.constraints.NotEmpty;
+
+@Schema(description = "用户 APP - 手机 + 密码登录 Request VO,客户登录手机号密码必填,邀请码选填")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class AppAuthCrmLoginReqVO {
+ @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
+ @NotEmpty(message = "手机号不能为空")
+ @Mobile
+ private String mobile;
+
+ @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao")
+ @NotEmpty(message = "密码不能为空")
+ @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
+ private String password;
+
+
+ @Schema(description = "邀请码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1230")
+ private String inviteCode;
+}
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/consumer/register/RegisterSendConsumer.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/consumer/register/RegisterSendConsumer.java
new file mode 100644
index 0000000000..bd52c93f36
--- /dev/null
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/consumer/register/RegisterSendConsumer.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.member.mq.consumer.register;
+
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+import cn.iocoder.yudao.module.member.mq.message.register.RegisterSendMessage;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
+
+@Component
+@Slf4j
+public class RegisterSendConsumer {
+
+ @Resource
+ private CrmCustomerApi crmCustomerApi;
+
+ @EventListener
+ @Async // Spring Event 默认在 Producer 发送的线程,通过 @Async 实现异步
+ public void onMessage(RegisterSendMessage message) {
+ log.info("[onMessage][消息内容({})]", message);
+ crmCustomerApi.doCreate(message.getMobile(), message.getLogin_ip(), message.getInvitationCode());
+ }
+}
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/message/register/RegisterSendMessage.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/message/register/RegisterSendMessage.java
new file mode 100644
index 0000000000..2867fc5833
--- /dev/null
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/message/register/RegisterSendMessage.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.member.mq.message.register;
+
+import lombok.Data;
+import jakarta.validation.constraints.NotNull;
+
+
+/**
+ * 发送会员注册的消息
+ *
+ * @author an
+ */
+@Data
+public class RegisterSendMessage {
+ /**
+ * 手机号
+ */
+ @NotNull(message = "手机号不能为空")
+ private String mobile;
+
+ /**
+ * 注册ip
+ */
+ private String login_ip;
+
+ /**
+ * 邀请码
+ */
+ private String invitationCode;
+
+}
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/register/RegisterProducer.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/register/RegisterProducer.java
new file mode 100644
index 0000000000..43169bc5d4
--- /dev/null
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/register/RegisterProducer.java
@@ -0,0 +1,32 @@
+package cn.iocoder.yudao.module.member.mq.producer.register;
+import cn.iocoder.yudao.module.member.mq.message.register.RegisterSendMessage;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+
+import jakarta.annotation.Resource;
+
+/**
+ * Register 会员注册相关消息的 Producer
+ *
+ * @author an
+ * @since 2025/3/18 22:16
+ */
+@Slf4j
+@Component
+public class RegisterProducer {
+ @Resource
+ private ApplicationContext applicationContext;
+ /**
+ * 发送 {@link RegisterSendMessage} 消息
+ *
+ * @param mobile 手机号
+ * @param login_ip 注册ip
+ * @param invitationCode 邀请码
+ */
+ public void sendRegisterSendMessage(String mobile, String login_ip, String invitationCode) {
+ RegisterSendMessage message = new RegisterSendMessage().
+ setMobile(mobile).setLogin_ip(login_ip).setInvitationCode(invitationCode);
+ applicationContext.publishEvent(message);
+ }
+}
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java
index 3fad6e2325..a6de1876ec 100644
--- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java
@@ -6,9 +6,7 @@ import jakarta.validation.Valid;
/**
* 会员的认证 Service 接口
- *
* 提供用户的账号密码登录、token 的校验等认证相关的功能
- *
* @author 芋道源码
*/
public interface MemberAuthService {
@@ -28,6 +26,14 @@ public interface MemberAuthService {
*/
void logout(String token);
+ /**
+ * 客户注册
+ *
+ * @param reqVO 登陆信息
+ * @return 登录结果
+ */
+ AppAuthLoginRespVO customerRegister(AppAuthCrmLoginReqVO reqVO);
+
/**
* 手机 + 验证码登陆
*
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
index 69d9252b89..641faa682c 100644
--- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
@@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.member.service.auth;
import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
@@ -10,6 +9,7 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
import cn.iocoder.yudao.module.member.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
+import cn.iocoder.yudao.module.member.mq.producer.register.RegisterProducer;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.system.api.logger.LoginLogApi;
import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
@@ -77,6 +77,15 @@ public class MemberAuthServiceImpl implements MemberAuthService {
return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE, openid);
}
+ @Override
+ public AppAuthLoginRespVO customerRegister(AppAuthCrmLoginReqVO reqVO) {
+ // 使用手机 + 密码,进行登录。
+ String userIp = getClientIP();
+ MemberUserDO user = userService.createUserAndCustomerIfAbsent(reqVO.getMobile(), userIp, getTerminal(), reqVO.getInviteCode());
+ // 创建 Token 令牌,记录登录日志
+ return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE_Register, "0");
+ }
+
@Override
@Transactional
public AppAuthLoginRespVO smsLogin(AppAuthSmsLoginReqVO reqVO) {
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java
index 2c07d4b6ed..f956a50591 100644
--- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java
@@ -46,6 +46,16 @@ public interface MemberUserService {
*/
MemberUserDO createUserIfAbsent(@Mobile String mobile, String registerIp, Integer terminal);
+ /**
+ * 基于手机号创建用户,同时发送MQ消息,创建用户和客户
+ * 如果用户已经存在,则直接进行返回
+ *
+ * @param mobile 手机号
+ * @param registerIp 注册 IP
+ * @param terminal 终端 {@link TerminalEnum} *
+ * @return 用户对象
+ */
+ MemberUserDO createUserAndCustomerIfAbsent(@Mobile String mobile, String registerIp, Integer terminal,String invitationCode);
/**
* 创建用户
* 目的:三方登录时,如果未绑定用户时,自动创建对应用户
diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
index e44e8b2dfb..93d005f13e 100644
--- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
+++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
@@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.member.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
+import cn.iocoder.yudao.module.member.mq.producer.register.RegisterProducer;
import cn.iocoder.yudao.module.member.mq.producer.user.MemberUserProducer;
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
@@ -31,6 +32,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
+
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
@@ -64,6 +66,9 @@ public class MemberUserServiceImpl implements MemberUserService {
@Resource
private MemberUserProducer memberUserProducer;
+ @Resource
+ private RegisterProducer registerProducer;
+
@Override
public MemberUserDO getUserByMobile(String mobile) {
return memberUserMapper.selectByMobile(mobile);
@@ -86,6 +91,60 @@ public class MemberUserServiceImpl implements MemberUserService {
return createUser(mobile, null, null, registerIp, terminal);
}
+ /**
+ * 基于手机号创建用户同时创建CRM客户。
+ * 如果用户已经存在,则直接进行返回
+ *
+ * @param mobile 手机号
+ * @param registerIp 注册 IP
+ * @param terminal 终端
+ * @return 用户对象
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public MemberUserDO createUserAndCustomerIfAbsent(String mobile, String registerIp, Integer terminal,String invitationCode) {
+ // 用户已经存在
+ MemberUserDO user = memberUserMapper.selectByMobile(mobile);
+ if (user != null) {
+ // 如果会员不为空,则查询CRM客户是否存在,ri
+ return user;
+ }
+ // 用户不存在,则进行创建
+ return createUserAndCustomer(mobile, mobile, null, registerIp, terminal,invitationCode);
+ }
+
+
+ private MemberUserDO createUserAndCustomer(String mobile, String nickname, String avtar,
+ String registerIp, Integer terminal,String invitationCode) {
+ // 生成密码
+ String password = IdUtil.fastSimpleUUID();
+ // 插入用户
+ MemberUserDO user = new MemberUserDO();
+ user.setMobile(mobile);
+ user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
+ user.setPassword(encodePassword(password)); // 加密密码
+ user.setRegisterIp(registerIp).setRegisterTerminal(terminal);
+ user.setNickname(nickname).setAvatar(avtar); // 基础信息
+ if (StrUtil.isEmpty(nickname)) {
+ // 昵称为空时,随机一个名字,避免一些依赖 nickname 的逻辑报错,或者有点丑。例如说,短信发送有昵称时~
+ user.setNickname("用户" + RandomUtil.randomNumbers(6));
+ }
+ memberUserMapper.insert(user);
+
+ // 发送 MQ 消息:用户创建
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+
+ @Override
+ public void afterCommit() {
+ memberUserProducer.sendUserCreateMessage(user.getId());
+ registerProducer.sendRegisterSendMessage(user.getMobile(), user.getRegisterIp(), invitationCode);
+ }
+
+ });
+ return user;
+ }
+
+
@Override
@Transactional(rollbackFor = Exception.class)
public MemberUserDO createUser(String nickname, String avtar, String registerIp, Integer terminal) {
diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java
index 4c51f91688..15c4ec3ec6 100644
--- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java
+++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java
@@ -14,6 +14,7 @@ public enum LoginLogTypeEnum {
LOGIN_SOCIAL(101), // 使用社交登录
LOGIN_MOBILE(103), // 使用手机登陆
LOGIN_SMS(104), // 使用短信登陆
+ LOGIN_MOBILE_Register(105), // 使用手机注册
LOGOUT_SELF(200), // 自己主动登出
LOGOUT_DELETE(202), // 强制退出