Pre Merge pull request !250 from egd/fix-member-api

pull/250/MERGE
egd 2026-05-11 07:21:00 +00:00 committed by Gitee
commit 62350cf734
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
10 changed files with 63 additions and 7 deletions

View File

@ -24,6 +24,9 @@ public class MemberUserRespDTO {
@Schema(description = "手机号", example = "15601691300")
private String mobile;
@Schema(description = "邮箱", example = "member@iocoder.cn")
private String email;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;

View File

@ -14,6 +14,7 @@ public interface ErrorCodeConstants {
ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1_004_001_001, "手机号未注册用户");
ErrorCode USER_MOBILE_USED = new ErrorCode(1_004_001_002, "修改手机失败,该手机号({})已经被使用");
ErrorCode USER_POINT_NOT_ENOUGH = new ErrorCode(1_004_001_003, "用户积分余额不足");
ErrorCode USER_EMAIL_USED = new ErrorCode(1_004_001_004, "修改邮箱失败,该邮箱({})已经被使用");
// ========== AUTH 模块 1-004-003-000 ==========
ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1_004_003_000, "登录失败,账号密码不正确");

View File

@ -5,7 +5,9 @@ import lombok.Data;
import org.hibernate.validator.constraints.URL;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.List;
@ -26,6 +28,11 @@ public class MemberUserBaseVO {
@NotNull(message = "状态不能为空")
private Byte status;
@Schema(description = "邮箱", example = "member@iocoder.cn")
@Email(message = "邮箱格式不正确")
@Size(max = 50, message = "邮箱长度不能超过 50 个字符")
private String email;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
@NotNull(message = "用户昵称不能为空")
private String nickname;

View File

@ -21,6 +21,9 @@ public class MemberUserPageReqVO extends PageParam {
@Schema(description = "手机号", example = "15601691300")
private String mobile;
@Schema(description = "邮箱", example = "member@iocoder.cn")
private String email;
@Schema(description = "用户昵称", example = "李四")
private String nickname;

View File

@ -23,6 +23,9 @@ public class AppMemberUserInfoRespVO {
@Schema(description = "用户手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
private String mobile;
@Schema(description = "邮箱", example = "member@iocoder.cn")
private String email;
@Schema(description = "用户性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer sex;

View File

@ -1,11 +1,12 @@
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;
import javax.validation.constraints.Email;
import javax.validation.constraints.Size;
@Schema(description = "用户 App - 会员用户更新 Request VO")
@Data
public class AppMemberUserUpdateReqVO {
@ -17,6 +18,11 @@ public class AppMemberUserUpdateReqVO {
@URL(message = "头像必须是 URL 格式")
private String avatar;
@Schema(description = "邮箱", example = "member@iocoder.cn")
@Email(message = "邮箱格式不正确")
@Size(max = 50, message = "邮箱长度不能超过 50 个字符")
private String email;
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer sex;

View File

@ -45,6 +45,10 @@ public class MemberUserDO extends TenantBaseDO {
*
*/
private String mobile;
/**
*
*/
private String email;
/**
*
*

View File

@ -26,6 +26,10 @@ public interface MemberUserMapper extends BaseMapperX<MemberUserDO> {
return selectOne(MemberUserDO::getMobile, mobile);
}
default MemberUserDO selectByEmail(String email) {
return selectOne(MemberUserDO::getEmail, email);
}
default List<MemberUserDO> selectListByNicknameLike(String nickname) {
return selectList(new LambdaQueryWrapperX<MemberUserDO>()
.likeIfPresent(MemberUserDO::getNickname, nickname));
@ -42,6 +46,7 @@ public interface MemberUserMapper extends BaseMapperX<MemberUserDO> {
// 分页查询
return selectPage(reqVO, new LambdaQueryWrapperX<MemberUserDO>()
.likeIfPresent(MemberUserDO::getMobile, reqVO.getMobile())
.likeIfPresent(MemberUserDO::getEmail, reqVO.getEmail())
.betweenIfPresent(MemberUserDO::getLoginDate, reqVO.getLoginDate())
.likeIfPresent(MemberUserDO::getNickname, reqVO.getNickname())
.betweenIfPresent(MemberUserDO::getCreateTime, reqVO.getCreateTime())

View File

@ -3,7 +3,10 @@ package cn.iocoder.yudao.module.member.service.user;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.*;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
@ -142,6 +145,8 @@ public class MemberUserServiceImpl implements MemberUserService {
@Override
public void updateUser(Long userId, AppMemberUserUpdateReqVO reqVO) {
validateUserExists(userId);
validateEmailUnique(userId, reqVO.getEmail());
MemberUserDO updateObj = BeanUtils.toBean(reqVO, MemberUserDO.class).setId(userId);
memberUserMapper.updateById(updateObj);
}
@ -238,6 +243,8 @@ public class MemberUserServiceImpl implements MemberUserService {
validateUserExists(updateReqVO.getId());
// 校验手机唯一
validateMobileUnique(updateReqVO.getId(), updateReqVO.getMobile());
// 校验邮箱唯一
validateEmailUnique(updateReqVO.getId(), updateReqVO.getEmail());
// 更新
MemberUserDO updateObj = MemberUserConvert.INSTANCE.convert(updateReqVO);
@ -274,6 +281,25 @@ public class MemberUserServiceImpl implements MemberUserService {
}
}
@VisibleForTesting
void validateEmailUnique(Long id, String email) {
if (StrUtil.isBlank(email)) {
return;
}
MemberUserDO user = memberUserMapper.selectByEmail(email);
if (user == null) {
return;
}
// 如果 id 为空,说明不用比较是否为相同 id 的用户
if (id == null) {
throw exception(USER_EMAIL_USED, email);
}
if (!user.getId().equals(id)) {
throw exception(USER_EMAIL_USED, email);
}
}
@Override
public PageResult<MemberUserDO> getUserPage(MemberUserPageReqVO pageReqVO) {
return memberUserMapper.selectPage(pageReqVO);

View File

@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.service.member;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
@ -14,8 +13,7 @@ import org.springframework.stereotype.Service;
@Service
public class MemberServiceImpl implements MemberService {
@Value("${yudao.info.base-package}")
private String basePackage;
private static final String MEMBER_USER_API_CLASS_NAME = "cn.iocoder.yudao.module.member.api.user.MemberUserApi";
private volatile Object memberUserApi;
@ -46,7 +44,7 @@ public class MemberServiceImpl implements MemberService {
private Object getMemberUserApi() {
if (memberUserApi == null) {
memberUserApi = SpringUtil.getBean(ClassUtil.loadClass(String.format("%s.module.member.api.user.MemberUserApi", basePackage)));
memberUserApi = SpringUtil.getBean(ClassUtil.loadClass(MEMBER_USER_API_CLASS_NAME));
}
return memberUserApi;
}