From 3b9ab7fa4a44abbdbc2450c8b4a8dc1be9686a0a Mon Sep 17 00:00:00 2001 From: egd <7769519+egberd@user.noreply.gitee.com> Date: Thu, 7 May 2026 15:41:40 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=B4=E6=8C=81=E7=8E=B0=E6=9C=89=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1,=E4=BF=AE=E5=A4=8DMemberUser=E7=BC=BA=E5=A4=B1?= =?UTF-8?q?=E7=9A=84email=E5=AD=97=E6=AE=B5;=E4=BF=AE=E5=A4=8D=E5=8F=8D?= =?UTF-8?q?=E5=B0=84=E8=8E=B7=E5=8F=96MemberUserApi=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E5=80=BC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/user/dto/MemberUserRespDTO.java | 3 ++ .../member/enums/ErrorCodeConstants.java | 1 + .../admin/user/vo/MemberUserBaseVO.java | 7 +++++ .../admin/user/vo/MemberUserPageReqVO.java | 3 ++ .../app/user/vo/AppMemberUserInfoRespVO.java | 3 ++ .../app/user/vo/AppMemberUserUpdateReqVO.java | 10 +++++-- .../dal/dataobject/user/MemberUserDO.java | 4 +++ .../dal/mysql/user/MemberUserMapper.java | 5 ++++ .../service/user/MemberUserServiceImpl.java | 28 ++++++++++++++++++- .../service/member/MemberServiceImpl.java | 6 ++-- 10 files changed, 63 insertions(+), 7 deletions(-) diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java index 79be9e521..00c40a4d7 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java @@ -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; diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java index ee970a54c..c28fcfcf4 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java @@ -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, "登录失败,账号密码不正确"); diff --git a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserBaseVO.java b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserBaseVO.java index e8c9974c8..b13ffa4f5 100644 --- a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserBaseVO.java +++ b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserBaseVO.java @@ -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; diff --git a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserPageReqVO.java b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserPageReqVO.java index abb94285e..299e6e253 100644 --- a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserPageReqVO.java +++ b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserPageReqVO.java @@ -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; diff --git a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java index 72e4fa3fa..fd9b90749 100644 --- a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java +++ b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java @@ -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; diff --git a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateReqVO.java b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateReqVO.java index cca08e926..dea99281a 100644 --- a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateReqVO.java +++ b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateReqVO.java @@ -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; diff --git a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java index 97ddc191d..11954c0ad 100644 --- a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java +++ b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java @@ -45,6 +45,10 @@ public class MemberUserDO extends TenantBaseDO { * 手机 */ private String mobile; + /** + * 邮箱 + */ + private String email; /** * 加密后的密码 * diff --git a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java index 3f871020c..6200bf125 100644 --- a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java +++ b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java @@ -26,6 +26,10 @@ public interface MemberUserMapper extends BaseMapperX { return selectOne(MemberUserDO::getMobile, mobile); } + default MemberUserDO selectByEmail(String email) { + return selectOne(MemberUserDO::getEmail, email); + } + default List selectListByNicknameLike(String nickname) { return selectList(new LambdaQueryWrapperX() .likeIfPresent(MemberUserDO::getNickname, nickname)); @@ -42,6 +46,7 @@ public interface MemberUserMapper extends BaseMapperX { // 分页查询 return selectPage(reqVO, new LambdaQueryWrapperX() .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()) diff --git a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java index e12c096f6..9d1b8d26b 100644 --- a/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java +++ b/yudao-module-member/yudao-module-member-server/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java @@ -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 getUserPage(MemberUserPageReqVO pageReqVO) { return memberUserMapper.selectPage(pageReqVO); diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/member/MemberServiceImpl.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/member/MemberServiceImpl.java index 7b31e0456..e03201cce 100644 --- a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/member/MemberServiceImpl.java +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/member/MemberServiceImpl.java @@ -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; }