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), // 强制退出