✨ SYSTEM:同步 jdk21 boot 最新代码
✨ INFRA:同步 jdk21 boot 最新代码
This commit is contained in:
@@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.member.controller.admin.address.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
/**
|
||||
|
||||
@@ -73,9 +73,8 @@ public class AppAuthController {
|
||||
|
||||
@PostMapping("/sms-login")
|
||||
@Operation(summary = "使用手机 + 验证码登录")
|
||||
public CommonResult<AppAuthLoginRespVO> smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO,
|
||||
@RequestHeader Integer terminal) {
|
||||
return success(authService.smsLogin(reqVO, terminal));
|
||||
public CommonResult<AppAuthLoginRespVO> smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO) {
|
||||
return success(authService.smsLogin(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/send-sms-code")
|
||||
@@ -122,7 +121,7 @@ public class AppAuthController {
|
||||
description = "参考 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html 文档")
|
||||
public CommonResult<SocialWxJsapiSignatureRespDTO> createWeixinMpJsapiSignature(@RequestParam("url") String url) {
|
||||
SocialWxJsapiSignatureRespDTO signature = socialClientApi.createWxMpJsapiSignature(
|
||||
UserTypeEnum.MEMBER.getValue(), url).getCheckedData();
|
||||
UserTypeEnum.MEMBER.getValue(), url);
|
||||
return success(AuthConvert.INSTANCE.convert(signature));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,15 +15,16 @@ import jakarta.validation.constraints.NotEmpty;
|
||||
@Builder
|
||||
public class AppAuthWeixinMiniAppLoginReqVO {
|
||||
|
||||
@Schema(description = "手机 code,小程序通过 wx.getPhoneNumber 方法获得", requiredMode = Schema.RequiredMode.REQUIRED, example = "hello")
|
||||
@Schema(description = "手机 code,小程序通过 wx.getPhoneNumber 方法获得", requiredMode = Schema.RequiredMode.REQUIRED, example = "hello")
|
||||
@NotEmpty(message = "手机 code 不能为空")
|
||||
private String phoneCode;
|
||||
|
||||
@Schema(description = "登录 code,小程序通过 wx.login 方法获得", requiredMode = Schema.RequiredMode.REQUIRED, example = "word")
|
||||
@Schema(description = "登录 code,小程序通过 wx.login 方法获得", requiredMode = Schema.RequiredMode.REQUIRED, example = "word")
|
||||
@NotEmpty(message = "登录 code 不能为空")
|
||||
private String loginCode;
|
||||
|
||||
@Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
|
||||
@NotEmpty(message = "state 不能为空")
|
||||
private String state;
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ package cn.iocoder.yudao.module.member.controller.app.point;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
||||
import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordRespVO;
|
||||
import cn.iocoder.yudao.module.member.convert.point.MemberPointRecordConvert;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO;
|
||||
@@ -33,9 +35,10 @@ public class AppMemberPointRecordController {
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得用户积分记录分页")
|
||||
@PreAuthenticated
|
||||
public CommonResult<PageResult<AppMemberPointRecordRespVO>> getPointRecordPage(@Valid PageParam pageVO) {
|
||||
PageResult<MemberPointRecordDO> pageResult = pointRecordService.getPointRecordPage(getLoginUserId(), pageVO);
|
||||
return success(MemberPointRecordConvert.INSTANCE.convertPage02(pageResult));
|
||||
public CommonResult<PageResult<AppMemberPointRecordRespVO>> getPointRecordPage(
|
||||
@Valid AppMemberPointRecordPageReqVO pageReqVO) {
|
||||
PageResult<MemberPointRecordDO> pageResult = pointRecordService.getPointRecordPage(getLoginUserId(), pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, AppMemberPointRecordRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.member.controller.app.point.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "用户 App - 用户积分记录分页 Request VO")
|
||||
@Data
|
||||
public class AppMemberPointRecordPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "是否增加积分", example = "true")
|
||||
private Boolean addStatus; // true - 增加;false - 减少;null - 不筛选
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
@@ -2,11 +2,16 @@ package cn.iocoder.yudao.module.member.controller.app.social;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
||||
import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserBindReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserRespVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO;
|
||||
import cn.iocoder.yudao.module.member.convert.social.SocialUserConvert;
|
||||
import cn.iocoder.yudao.module.system.api.social.SocialUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -15,11 +20,12 @@ import org.springframework.web.bind.annotation.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "用户 App - 社交用户")
|
||||
@RestController
|
||||
@RequestMapping("/system/social-user")
|
||||
@RequestMapping("/member/social-user")
|
||||
@Validated
|
||||
public class AppSocialUserController {
|
||||
|
||||
@@ -28,17 +34,30 @@ public class AppSocialUserController {
|
||||
|
||||
@PostMapping("/bind")
|
||||
@Operation(summary = "社交绑定,使用 code 授权码")
|
||||
public CommonResult<Boolean> socialBind(@RequestBody @Valid AppSocialUserBindReqVO reqVO) {
|
||||
socialUserApi.bindSocialUser(SocialUserConvert.INSTANCE.convert(getLoginUserId(), UserTypeEnum.MEMBER.getValue(), reqVO));
|
||||
return CommonResult.success(true);
|
||||
public CommonResult<String> socialBind(@RequestBody @Valid AppSocialUserBindReqVO reqVO) {
|
||||
SocialUserBindReqDTO reqDTO = new SocialUserBindReqDTO(getLoginUserId(), UserTypeEnum.MEMBER.getValue(),
|
||||
reqVO.getType(), reqVO.getCode(), reqVO.getState());
|
||||
String openid = socialUserApi.bindSocialUser(reqDTO);
|
||||
return success(openid);
|
||||
}
|
||||
|
||||
@DeleteMapping("/unbind")
|
||||
@Operation(summary = "取消社交绑定")
|
||||
@PreAuthenticated
|
||||
public CommonResult<Boolean> socialUnbind(@RequestBody AppSocialUserUnbindReqVO reqVO) {
|
||||
socialUserApi.unbindSocialUser(SocialUserConvert.INSTANCE.convert(getLoginUserId(), UserTypeEnum.MEMBER.getValue(), reqVO));
|
||||
return CommonResult.success(true);
|
||||
SocialUserUnbindReqDTO reqDTO = new SocialUserUnbindReqDTO(getLoginUserId(), UserTypeEnum.MEMBER.getValue(),
|
||||
reqVO.getType(), reqVO.getOpenid());
|
||||
socialUserApi.unbindSocialUser(reqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得社交用户")
|
||||
@Parameter(name = "type", description = "社交平台的类型,参见 SocialTypeEnum 枚举值", required = true, example = "10")
|
||||
@PreAuthenticated
|
||||
public CommonResult<AppSocialUserRespVO> getSocialUser(@RequestParam("type") Integer type) {
|
||||
SocialUserRespDTO socialUser = socialUserApi.getSocialUserByUserId(UserTypeEnum.MEMBER.getValue(), getLoginUserId(), type);
|
||||
return success(BeanUtils.toBean(socialUser, AppSocialUserRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,9 +13,6 @@ import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "用户 APP - 社交绑定 Request VO,使用 code 授权码")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AppSocialUserBindReqVO {
|
||||
|
||||
@Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.yudao.module.member.controller.app.social.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "用户 APP - 社交用户 Response VO")
|
||||
@Data
|
||||
public class AppSocialUserRespVO {
|
||||
|
||||
@Schema(description = "社交用户的 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE")
|
||||
private String openid;
|
||||
|
||||
@Schema(description = "社交用户的昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "社交用户的头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||
private String avatar;
|
||||
|
||||
}
|
||||
@@ -13,9 +13,6 @@ import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "用户 APP - 取消社交绑定 Request VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AppSocialUserUnbindReqVO {
|
||||
|
||||
@Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
|
||||
@@ -57,17 +57,25 @@ public class AppMemberUserController {
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-mobile-by-weixin")
|
||||
@Operation(summary = "基于微信小程序的授权码,修改用户手机")
|
||||
@PreAuthenticated
|
||||
public CommonResult<Boolean> updateUserMobileByWeixin(@RequestBody @Valid AppMemberUserUpdateMobileByWeixinReqVO reqVO) {
|
||||
userService.updateUserMobileByWeixin(getLoginUserId(), reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-password")
|
||||
@Operation(summary = "修改用户密码", description = "用户修改密码时使用")
|
||||
@PreAuthenticated
|
||||
public CommonResult<Boolean> updatePassword(@RequestBody @Valid AppMemberUserUpdatePasswordReqVO reqVO) {
|
||||
public CommonResult<Boolean> updateUserPassword(@RequestBody @Valid AppMemberUserUpdatePasswordReqVO reqVO) {
|
||||
userService.updateUserPassword(getLoginUserId(), reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/reset-password")
|
||||
@Operation(summary = "重置密码", description = "用户忘记密码时使用")
|
||||
public CommonResult<Boolean> resetPassword(@RequestBody @Valid AppMemberUserResetPasswordReqVO reqVO) {
|
||||
public CommonResult<Boolean> resetUserPassword(@RequestBody @Valid AppMemberUserResetPasswordReqVO reqVO) {
|
||||
userService.resetUserPassword(reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ public class AppMemberUserInfoRespVO {
|
||||
@Schema(description = "用户手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
|
||||
private String mobile;
|
||||
|
||||
@Schema(description = "用户性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
private Integer point;
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package cn.iocoder.yudao.module.member.controller.app.user.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "用户 APP - 基于微信小程序的授权码,修改手机 Request VO")
|
||||
@Data
|
||||
public class AppMemberUserUpdateMobileByWeixinReqVO {
|
||||
|
||||
@Schema(description = "手机 code,小程序通过 wx.getPhoneNumber 方法获得",
|
||||
requiredMode = Schema.RequiredMode.REQUIRED, example = "hello")
|
||||
@NotEmpty(message = "手机 code 不能为空")
|
||||
private String code;
|
||||
|
||||
}
|
||||
@@ -14,9 +14,6 @@ import jakarta.validation.constraints.Pattern;
|
||||
|
||||
@Schema(description = "用户 APP - 修改手机 Request VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AppMemberUserUpdateMobileReqVO {
|
||||
|
||||
@Schema(description = "手机验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@@ -25,14 +22,13 @@ public class AppMemberUserUpdateMobileReqVO {
|
||||
@Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "手机号",requiredMode = Schema.RequiredMode.REQUIRED,example = "15823654487")
|
||||
@Schema(description = "手机号",requiredMode = Schema.RequiredMode.REQUIRED, example = "15823654487")
|
||||
@NotBlank(message = "手机号不能为空")
|
||||
@Length(min = 8, max = 11, message = "手机号码长度为 8-11 位")
|
||||
@Mobile
|
||||
private String mobile;
|
||||
|
||||
@Schema(description = "原手机验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotEmpty(message = "原手机验证码不能为空")
|
||||
@Schema(description = "原手机验证码", example = "1024")
|
||||
@Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位")
|
||||
@Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
|
||||
private String oldCode;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.member.controller.app.user.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.common.SexEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
@@ -15,4 +17,7 @@ public class AppMemberUserUpdateReqVO {
|
||||
@URL(message = "头像必须是 URL 格式")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer sex;
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,4 @@ public interface MemberPointRecordConvert {
|
||||
}
|
||||
PageResult<MemberPointRecordRespVO> convertPage(PageResult<MemberPointRecordDO> pageResult);
|
||||
|
||||
PageResult<AppMemberPointRecordRespVO> convertPage02(PageResult<MemberPointRecordDO> pageResult);
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO;
|
||||
@@ -47,10 +48,9 @@ public interface MemberSignInRecordConvert {
|
||||
// 1. 计算是第几天签到
|
||||
configs.sort(Comparator.comparing(MemberSignInConfigDO::getDay));
|
||||
MemberSignInConfigDO lastConfig = CollUtil.getLast(configs); // 最大签到天数配置
|
||||
// 1.2. 计算今天是第几天签到
|
||||
// 1.2. 计算今天是第几天签到 (只有连续签到才加否则重置为 1)
|
||||
int day = 1;
|
||||
// TODO @puhui999:要判断是不是昨天签到的;是否是昨天的判断,可以抽个方法到 util 里
|
||||
if (lastRecord != null) {
|
||||
if (lastRecord != null && DateUtils.isYesterday(lastRecord.getCreateTime())) {
|
||||
day = lastRecord.getDay() + 1;
|
||||
}
|
||||
// 1.3 判断是否超出了最大签到配置
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package cn.iocoder.yudao.module.member.convert.social;
|
||||
|
||||
import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserBindReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface SocialUserConvert {
|
||||
|
||||
SocialUserConvert INSTANCE = Mappers.getMapper(SocialUserConvert.class);
|
||||
|
||||
SocialUserBindReqDTO convert(Long userId, Integer userType, AppSocialUserBindReqVO reqVO);
|
||||
|
||||
SocialUserUnbindReqDTO convert(Long userId, Integer userType, AppSocialUserUnbindReqVO reqVO);
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@@ -27,9 +28,14 @@ public interface MemberPointRecordMapper extends BaseMapperX<MemberPointRecordDO
|
||||
.orderByDesc(MemberPointRecordDO::getId));
|
||||
}
|
||||
|
||||
default PageResult<MemberPointRecordDO> selectPage(Long userId, PageParam pageVO) {
|
||||
return selectPage(pageVO, new LambdaQueryWrapperX<MemberPointRecordDO>()
|
||||
default PageResult<MemberPointRecordDO> selectPage(Long userId, AppMemberPointRecordPageReqVO pageReqVO) {
|
||||
return selectPage(pageReqVO, new LambdaQueryWrapperX<MemberPointRecordDO>()
|
||||
.eq(MemberPointRecordDO::getUserId, userId)
|
||||
.betweenIfPresent(MemberPointRecordDO::getCreateTime, pageReqVO.getCreateTime())
|
||||
.gt(Boolean.TRUE.equals(pageReqVO.getAddStatus()),
|
||||
MemberPointRecordDO::getPoint, 0)
|
||||
.lt(Boolean.FALSE.equals(pageReqVO.getAddStatus()),
|
||||
MemberPointRecordDO::getPoint, 0)
|
||||
.orderByDesc(MemberPointRecordDO::getId));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.member.framework.web.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration;
|
||||
import org.springdoc.core.models.GroupedOpenApi;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* member 模块的 web 组件的 Configuration
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class MemberWebConfiguration {
|
||||
|
||||
/**
|
||||
* member 模块的 API 分组
|
||||
*/
|
||||
@Bean
|
||||
public GroupedOpenApi memberGroupedOpenApi() {
|
||||
return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("member");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* member 模块的 web 配置
|
||||
*/
|
||||
package cn.iocoder.yudao.module.member.framework.web;
|
||||
@@ -1,6 +1,5 @@
|
||||
package cn.iocoder.yudao.module.member.service.auth;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
|
||||
import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
@@ -33,10 +32,9 @@ public interface MemberAuthService {
|
||||
* 手机 + 验证码登陆
|
||||
*
|
||||
* @param reqVO 登陆信息
|
||||
* @param terminal 终端 {@link TerminalEnum}
|
||||
* @return 登录结果
|
||||
*/
|
||||
AppAuthLoginRespVO smsLogin(@Valid AppAuthSmsLoginReqVO reqVO, Integer terminal);
|
||||
AppAuthLoginRespVO smsLogin(@Valid AppAuthSmsLoginReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 社交登录,使用 code 授权码
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.util.Objects;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getTerminal;
|
||||
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
@@ -69,7 +70,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
String openid = null;
|
||||
if (reqVO.getSocialType() != null) {
|
||||
openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
|
||||
reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())).getCheckedData();
|
||||
reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
|
||||
}
|
||||
|
||||
// 创建 Token 令牌,记录登录日志
|
||||
@@ -78,20 +79,20 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AppAuthLoginRespVO smsLogin(AppAuthSmsLoginReqVO reqVO, Integer terminal) {
|
||||
public AppAuthLoginRespVO smsLogin(AppAuthSmsLoginReqVO reqVO) {
|
||||
// 校验验证码
|
||||
String userIp = getClientIP();
|
||||
smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_LOGIN.getScene(), userIp));
|
||||
|
||||
// 获得获得注册用户
|
||||
MemberUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), userIp, terminal);
|
||||
MemberUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), userIp, getTerminal());
|
||||
Assert.notNull(user, "获取用户失败,结果为空");
|
||||
|
||||
// 如果 socialType 非空,说明需要绑定社交用户
|
||||
String openid = null;
|
||||
if (reqVO.getSocialType() != null) {
|
||||
openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
|
||||
reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())).getCheckedData();
|
||||
reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
|
||||
}
|
||||
|
||||
// 创建 Token 令牌,记录登录日志
|
||||
@@ -99,16 +100,25 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO) {
|
||||
// 使用 code 授权码,进行登录。然后,获得到绑定的用户编号
|
||||
SocialUserRespDTO socialUser = socialUserApi.getSocialUser(UserTypeEnum.MEMBER.getValue(), reqVO.getType(),
|
||||
reqVO.getCode(), reqVO.getState()).getCheckedData();
|
||||
SocialUserRespDTO socialUser = socialUserApi.getSocialUserByCode(UserTypeEnum.MEMBER.getValue(), reqVO.getType(),
|
||||
reqVO.getCode(), reqVO.getState());
|
||||
if (socialUser == null) {
|
||||
throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
|
||||
throw exception(AUTH_SOCIAL_USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 自动登录
|
||||
MemberUserDO user = userService.getUser(socialUser.getUserId());
|
||||
// 情况一:已绑定,直接读取用户信息
|
||||
MemberUserDO user;
|
||||
if (socialUser.getUserId() != null) {
|
||||
user = userService.getUser(socialUser.getUserId());
|
||||
// 情况二:未绑定,注册用户 + 绑定用户
|
||||
} else {
|
||||
user = userService.createUser(socialUser.getNickname(), socialUser.getAvatar(), getClientIP(), getTerminal());
|
||||
socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
|
||||
reqVO.getType(), reqVO.getCode(), reqVO.getState()));
|
||||
}
|
||||
if (user == null) {
|
||||
throw exception(USER_NOT_EXISTS);
|
||||
}
|
||||
@@ -121,7 +131,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
public AppAuthLoginRespVO weixinMiniAppLogin(AppAuthWeixinMiniAppLoginReqVO reqVO) {
|
||||
// 获得对应的手机号信息
|
||||
SocialWxPhoneNumberInfoRespDTO phoneNumberInfo = socialClientApi.getWxMaPhoneNumberInfo(
|
||||
UserTypeEnum.MEMBER.getValue(), reqVO.getPhoneCode()).getCheckedData();
|
||||
UserTypeEnum.MEMBER.getValue(), reqVO.getPhoneCode());
|
||||
Assert.notNull(phoneNumberInfo, "获得手机信息失败,结果为空");
|
||||
|
||||
// 获得获得注册用户
|
||||
@@ -131,7 +141,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
|
||||
// 绑定社交用户
|
||||
String openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
|
||||
SocialTypeEnum.WECHAT_MINI_APP.getType(), reqVO.getLoginCode(), reqVO.getState())).getCheckedData();
|
||||
SocialTypeEnum.WECHAT_MINI_APP.getType(), reqVO.getLoginCode(), reqVO.getState()));
|
||||
|
||||
// 创建 Token 令牌,记录登录日志
|
||||
return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, openid);
|
||||
@@ -144,14 +154,14 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
// 创建 Token 令牌
|
||||
OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.createAccessToken(new OAuth2AccessTokenCreateReqDTO()
|
||||
.setUserId(user.getId()).setUserType(getUserType().getValue())
|
||||
.setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT)).getCheckedData();
|
||||
.setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT));
|
||||
// 构建返回结果
|
||||
return AuthConvert.INSTANCE.convert(accessTokenRespDTO, openid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSocialAuthorizeUrl(Integer type, String redirectUri) {
|
||||
return socialClientApi.getAuthorizeUrl(type, UserTypeEnum.MEMBER.getValue(), redirectUri).getCheckedData();
|
||||
return socialClientApi.getAuthorizeUrl(type, UserTypeEnum.MEMBER.getValue(), redirectUri);
|
||||
}
|
||||
|
||||
private MemberUserDO login0(String mobile, String password) {
|
||||
@@ -195,7 +205,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
@Override
|
||||
public void logout(String token) {
|
||||
// 删除访问令牌
|
||||
OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.removeAccessToken(token).getCheckedData();
|
||||
OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.removeAccessToken(token);
|
||||
if (accessTokenRespDTO == null) {
|
||||
return;
|
||||
}
|
||||
@@ -214,11 +224,17 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
}
|
||||
// 情况 2:如果是重置密码场景,需要校验手机号是存在的
|
||||
if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_RESET_PASSWORD.getScene())) {
|
||||
MemberUserDO user= userService.getUserByMobile(reqVO.getMobile());
|
||||
MemberUserDO user = userService.getUserByMobile(reqVO.getMobile());
|
||||
if (user == null) {
|
||||
throw exception(USER_MOBILE_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
// 情况 3:如果是修改密码场景,需要查询手机号,无需前端传递
|
||||
if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene())) {
|
||||
MemberUserDO user = userService.getUser(userId);
|
||||
// TODO 芋艿:后续 member user 手机非强绑定,这块需要做下调整;
|
||||
reqVO.setMobile(user.getMobile());
|
||||
}
|
||||
|
||||
// 执行发送
|
||||
smsCodeApi.sendSmsCode(AuthConvert.INSTANCE.convert(reqVO).setCreateIp(getClientIP()));
|
||||
@@ -232,7 +248,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
||||
@Override
|
||||
public AppAuthLoginRespVO refreshToken(String refreshToken) {
|
||||
OAuth2AccessTokenRespDTO accessTokenDO = oauth2TokenApi.refreshAccessToken(refreshToken,
|
||||
OAuth2ClientConstants.CLIENT_ID_DEFAULT).getCheckedData();
|
||||
OAuth2ClientConstants.CLIENT_ID_DEFAULT);
|
||||
return AuthConvert.INSTANCE.convert(accessTokenDO, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,6 @@ public interface MemberGroupService {
|
||||
*/
|
||||
PageResult<MemberGroupDO> getGroupPage(MemberGroupPageReqVO pageReqVO);
|
||||
|
||||
|
||||
/**
|
||||
* 获得指定状态的用户分组列表
|
||||
*
|
||||
@@ -73,7 +72,6 @@ public interface MemberGroupService {
|
||||
*/
|
||||
List<MemberGroupDO> getGroupListByStatus(Integer status);
|
||||
|
||||
|
||||
/**
|
||||
* 获得开启状态的用户分组列表
|
||||
*
|
||||
|
||||
@@ -12,6 +12,8 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会员经验记录 Service 实现类
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package cn.iocoder.yudao.module.member.service.point;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO;
|
||||
import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
|
||||
|
||||
@@ -25,10 +25,10 @@ public interface MemberPointRecordService {
|
||||
* 【会员】获得积分记录分页
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param pageVO 分页查询
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 签到记录分页
|
||||
*/
|
||||
PageResult<MemberPointRecordDO> getPointRecordPage(Long userId, PageParam pageVO);
|
||||
PageResult<MemberPointRecordDO> getPointRecordPage(Long userId, AppMemberPointRecordPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 创建用户积分记录
|
||||
|
||||
@@ -5,6 +5,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
|
||||
import cn.iocoder.yudao.module.member.dal.mysql.point.MemberPointRecordMapper;
|
||||
@@ -59,8 +60,8 @@ public class MemberPointRecordServiceImpl implements MemberPointRecordService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<MemberPointRecordDO> getPointRecordPage(Long userId, PageParam pageVO) {
|
||||
return memberPointRecordMapper.selectPage(userId, pageVO);
|
||||
public PageResult<MemberPointRecordDO> getPointRecordPage(Long userId, AppMemberPointRecordPageReqVO pageReqVO) {
|
||||
return memberPointRecordMapper.selectPage(userId, pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,14 +19,12 @@ import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
|
||||
import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService;
|
||||
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -77,50 +75,15 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService
|
||||
}
|
||||
summary.setTodaySignIn(DateUtils.isToday(lastRecord.getCreateTime()));
|
||||
|
||||
// 4. 校验今天是否签到,没有签到则直接返回
|
||||
// 4.1 校验今天是否签到,没有签到则直接返回
|
||||
if (!summary.getTodaySignIn()) {
|
||||
return summary;
|
||||
}
|
||||
// 4.1. 判断连续签到天数
|
||||
// TODO @puhui999:连续签到,可以基于 lastRecord 的 day 和当前时间判断呀?按 day 统计连续签到天数可能不准确
|
||||
// 1. day 只是记录第几天签到的有可能不连续,比如第一次签到是周一,第二次签到是周三这样 lastRecord 的 day 为 2 但是并不是连续的两天
|
||||
// 2. day 超出签到规则的最大天数会重置到从第一天开始签到(我理解为开始下一轮,类似一周签到七天七天结束下周又从周一开始签到)
|
||||
// 1. 回复:周三签到,day 要归 1 呀。连续签到哈;
|
||||
List<MemberSignInRecordDO> signInRecords = signInRecordMapper.selectListByUserId(userId);
|
||||
signInRecords.sort(Comparator.comparing(MemberSignInRecordDO::getCreateTime).reversed()); // 根据签到时间倒序
|
||||
summary.setContinuousDay(calculateConsecutiveDays(signInRecords));
|
||||
// 4.2 连续签到天数
|
||||
summary.setContinuousDay(lastRecord.getDay());
|
||||
return summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算连续签到天数
|
||||
*
|
||||
* @param signInRecords 签到记录列表
|
||||
* @return int 连续签到天数
|
||||
*/
|
||||
public int calculateConsecutiveDays(List<MemberSignInRecordDO> signInRecords) {
|
||||
int consecutiveDays = 1; // 初始连续天数为1
|
||||
LocalDate previousDate = null;
|
||||
|
||||
for (MemberSignInRecordDO record : signInRecords) {
|
||||
LocalDate currentDate = record.getCreateTime().toLocalDate();
|
||||
|
||||
if (previousDate != null) {
|
||||
// 检查相邻两个日期是否连续
|
||||
if (currentDate.minusDays(1).isEqual(previousDate)) {
|
||||
consecutiveDays++;
|
||||
} else {
|
||||
// 如果日期不连续,停止遍历
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
previousDate = currentDate;
|
||||
}
|
||||
|
||||
return consecutiveDays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<MemberSignInRecordDO> getSignInRecordPage(MemberSignInRecordPageReqVO pageReqVO) {
|
||||
// 根据用户昵称查询出用户ids
|
||||
|
||||
@@ -5,10 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.validation.Mobile;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserResetPasswordReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateMobileReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdatePasswordReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.user.vo.*;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
@@ -49,6 +46,18 @@ public interface MemberUserService {
|
||||
*/
|
||||
MemberUserDO createUserIfAbsent(@Mobile String mobile, String registerIp, Integer terminal);
|
||||
|
||||
/**
|
||||
* 创建用户
|
||||
* 目的:三方登录时,如果未绑定用户时,自动创建对应用户
|
||||
*
|
||||
* @param nickname 昵称
|
||||
* @param avtar 头像
|
||||
* @param registerIp 注册 IP
|
||||
* @param terminal 终端 {@link TerminalEnum}
|
||||
* @return 用户对象
|
||||
*/
|
||||
MemberUserDO createUser(String nickname, String avtar, String registerIp, Integer terminal);
|
||||
|
||||
/**
|
||||
* 更新用户的最后登陆信息
|
||||
*
|
||||
@@ -82,13 +91,21 @@ public interface MemberUserService {
|
||||
void updateUser(Long userId, AppMemberUserUpdateReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 【会员】修改手机
|
||||
* 【会员】修改手机,基于手机验证码
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param reqVO 请求信息
|
||||
*/
|
||||
void updateUserMobile(Long userId, AppMemberUserUpdateMobileReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 【会员】修改手机,基于微信小程序的授权码
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param reqVO 请求信息
|
||||
*/
|
||||
void updateUserMobileByWeixin(Long userId, AppMemberUserUpdateMobileByWeixinReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 【会员】修改密码
|
||||
*
|
||||
@@ -169,4 +186,5 @@ public interface MemberUserService {
|
||||
* @return 更新结果
|
||||
*/
|
||||
boolean updateUserPoint(Long userId, Integer point);
|
||||
|
||||
}
|
||||
|
||||
@@ -2,17 +2,15 @@ package cn.iocoder.yudao.module.member.service.user;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.*;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserResetPasswordReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateMobileReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdatePasswordReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.user.vo.*;
|
||||
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;
|
||||
@@ -20,6 +18,8 @@ import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
|
||||
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;
|
||||
import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO;
|
||||
import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -55,6 +55,9 @@ public class MemberUserServiceImpl implements MemberUserService {
|
||||
@Resource
|
||||
private SmsCodeApi smsCodeApi;
|
||||
|
||||
@Resource
|
||||
private SocialClientApi socialClientApi;
|
||||
|
||||
@Resource
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@@ -80,10 +83,17 @@ public class MemberUserServiceImpl implements MemberUserService {
|
||||
return user;
|
||||
}
|
||||
// 用户不存在,则进行创建
|
||||
return createUser(mobile, registerIp, terminal);
|
||||
return createUser(mobile, null, null, registerIp, terminal);
|
||||
}
|
||||
|
||||
private MemberUserDO createUser(String mobile, String registerIp, Integer terminal) {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public MemberUserDO createUser(String nickname, String avtar, String registerIp, Integer terminal) {
|
||||
return createUser(null, nickname, avtar, registerIp, terminal);
|
||||
}
|
||||
|
||||
private MemberUserDO createUser(String mobile, String nickname, String avtar,
|
||||
String registerIp, Integer terminal) {
|
||||
// 生成密码
|
||||
String password = IdUtil.fastSimpleUUID();
|
||||
// 插入用户
|
||||
@@ -91,8 +101,12 @@ public class MemberUserServiceImpl implements MemberUserService {
|
||||
user.setMobile(mobile);
|
||||
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
|
||||
user.setPassword(encodePassword(password)); // 加密密码
|
||||
user.setRegisterIp(registerIp);
|
||||
user.setRegisterTerminal(terminal);
|
||||
user.setRegisterIp(registerIp).setRegisterTerminal(terminal);
|
||||
user.setNickname(nickname).setAvatar(avtar); // 基础信息
|
||||
if (StrUtil.isEmpty(nickname)) {
|
||||
// 昵称为空时,随机一个名字,避免一些依赖 nickname 的逻辑报错,或者有点丑。例如说,短信发送有昵称时~
|
||||
user.setNickname("用户" + RandomUtil.randomNumbers(6));
|
||||
}
|
||||
memberUserMapper.insert(user);
|
||||
|
||||
// 发送 MQ 消息:用户创建
|
||||
@@ -128,29 +142,45 @@ public class MemberUserServiceImpl implements MemberUserService {
|
||||
|
||||
@Override
|
||||
public void updateUser(Long userId, AppMemberUserUpdateReqVO reqVO) {
|
||||
memberUserMapper.updateById(new MemberUserDO().setId(userId)
|
||||
.setNickname(reqVO.getNickname()).setAvatar(reqVO.getAvatar()));
|
||||
MemberUserDO updateObj = BeanUtils.toBean(reqVO, MemberUserDO.class).setId(userId);
|
||||
memberUserMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateUserMobile(Long userId, AppMemberUserUpdateMobileReqVO reqVO) {
|
||||
// 检测用户是否存在
|
||||
// 1.1 检测用户是否存在
|
||||
MemberUserDO user = validateUserExists(userId);
|
||||
// 校验新手机是否已经被绑定
|
||||
// 1.2 校验新手机是否已经被绑定
|
||||
validateMobileUnique(null, reqVO.getMobile());
|
||||
|
||||
// 校验旧手机和旧验证码
|
||||
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode())
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));
|
||||
// 使用新验证码
|
||||
// 2.1 校验旧手机和旧验证码
|
||||
// 补充说明:从安全性来说,老手机也校验 oldCode 验证码会更安全。但是由于 uni-app 商城界面暂时没做,所以这里不强制校验
|
||||
if (StrUtil.isNotEmpty(reqVO.getOldCode())) {
|
||||
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode())
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));
|
||||
}
|
||||
// 2.2 使用新验证码
|
||||
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode())
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));
|
||||
|
||||
// 更新用户手机
|
||||
// 3. 更新用户手机
|
||||
memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(reqVO.getMobile()).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUserMobileByWeixin(Long userId, AppMemberUserUpdateMobileByWeixinReqVO reqVO) {
|
||||
// 1.1 获得对应的手机号信息
|
||||
SocialWxPhoneNumberInfoRespDTO phoneNumberInfo = socialClientApi.getWxMaPhoneNumberInfo(
|
||||
UserTypeEnum.MEMBER.getValue(), reqVO.getCode());
|
||||
Assert.notNull(phoneNumberInfo, "获得手机信息失败,结果为空");
|
||||
// 1.2 校验新手机是否已经被绑定
|
||||
validateMobileUnique(userId, phoneNumberInfo.getPhoneNumber());
|
||||
|
||||
// 2. 更新用户手机
|
||||
memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(phoneNumberInfo.getPhoneNumber()).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUserPassword(Long userId, AppMemberUserUpdatePasswordReqVO reqVO) {
|
||||
// 检测用户是否存在
|
||||
|
||||
Reference in New Issue
Block a user