30262728@qq.com пре 2 недеља
родитељ
комит
5732318f49
23 измењених фајлова са 606 додато и 177 уклоњено
  1. 20 0
      qnfhq-api/src/main/java/com/qnfhq/constant/ApiConstant.java
  2. 71 27
      qnfhq-api/src/main/java/com/qnfhq/modules/user/controller/ApiAppUserController.java
  3. 4 4
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/AppLoginDTO.java
  4. 19 14
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/AppRegisterDTO.java
  5. 3 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/AppUserDTO.java
  6. 32 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/CheckCaptchaDTO.java
  7. 25 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/CheckEmailCodeDTO.java
  8. 26 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/CheckPhoneCodeDTO.java
  9. 5 17
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/ResetPwdByEmailDTO.java
  10. 5 5
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/ResetPwdByPhoneDTO.java
  11. 35 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/ResetPwdEmailDTO.java
  12. 29 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/ResetPwdPhoneDTO.java
  13. 4 2
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/SendEmailCodeDTO.java
  14. 7 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/SendPhoneCodeDTO.java
  15. 6 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/entity/AppUserEntity.java
  16. 2 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/enums/UserCodeTypeEnum.java
  17. 9 4
      qnfhq-api/src/main/java/com/qnfhq/modules/user/service/AppUserService.java
  18. 197 88
      qnfhq-api/src/main/java/com/qnfhq/modules/user/service/impl/AppUserServiceImpl.java
  19. 72 0
      qnfhq-api/src/main/java/com/qnfhq/utils/EmailValidUtils.java
  20. 7 2
      qnfhq-api/src/main/resources/i18n/messages_zh.properties
  21. 10 14
      qnfhq-api/src/main/resources/i18n/validation_zh.properties
  22. 3 0
      qnfhq-api/src/main/resources/mapper/user/AppUserDao.xml
  23. 15 0
      qnfhq-common/src/main/java/com/qnfhq/common/utils/DateUtils.java

+ 20 - 0
qnfhq-api/src/main/java/com/qnfhq/constant/ApiConstant.java

@@ -14,4 +14,24 @@ public interface ApiConstant {
      * 邮箱验证码过期时间 5分钟
      */
     int EMAIL_EXPIRE = 300;
+
+    /**
+     * 验证码过期时间 10分钟
+     */
+    int CHECK_EXPIRE = 600;
+
+    /**
+     * 密码输错锁n次锁1小时
+     */
+    int PASSWORD_FAIL_HOUR_TIMES = 5;
+    /**
+     * 密码输错锁n次锁24小时
+     */
+    int PASSWORD_FAIL_DAY_TIMES = 10;
+
+    /**
+     * 密码输错锁时间1小时
+     */
+    int PASSWORD_FAIL_LOCK_HOUR = 3600;
+    int PASSWORD_FAIL_LOCK_24HOUR = 24*3600;
 }

+ 71 - 27
qnfhq-api/src/main/java/com/qnfhq/modules/user/controller/ApiAppUserController.java

@@ -49,25 +49,16 @@ public class ApiAppUserController {
     private CaptchaService captchaService;
 
 
+    /**
+     * 邮箱+手机号码注册
+     * @param dto
+     * @param request
+     * @return
+     */
     @PostMapping("/register")
     @Operation(summary = "注册")
     public Result register(@RequestBody AppRegisterDTO dto, HttpServletRequest request) {
-        //表单校验
         ValidatorUtils.validateEntity(dto);
-
-//        int signType = dto.getSignType();
-//        if(signType==1) {
-//            if(StringUtils.isEmpty(dto.getEmail())) {
-//                throw new RenException(MessageUtils.message("email.code_empty"));//邮箱不能为空!
-//            }
-//        } else if (signType==2) {
-//            if(StringUtils.isEmpty(dto.getPhone())) {
-//                throw new RenException(MessageUtils.message("phone_code_empty"));//手机号不能为空!
-//            }
-//        } else {
-//            throw new RenException(MessageUtils.message("user.register.signtype.err"));//登录类型错误
-//        }
-
         return appUserService.register(dto,request);
     }
 
@@ -75,9 +66,7 @@ public class ApiAppUserController {
     @PostMapping("/login")
     @Operation(summary = "登录")
     public Result login(@RequestBody AppLoginDTO dto, HttpServletRequest request) {
-
         ValidatorUtils.validateEntity(dto);
-
         return appUserService.login(dto,request);
     }
 
@@ -123,10 +112,6 @@ public class ApiAppUserController {
 
         ValidatorUtils.validateEntity(sendCodeDTO);
 
-        if (StringUtils.isEmpty(sendCodeDTO.getEmail())) {
-            throw new RenException(MessageUtils.message("email.code_empty"));//邮箱不能为空!
-        }
-
         return appUserService.sendEmailCode(sendCodeDTO.getCodeType(),sendCodeDTO.getEmail());
 
     }
@@ -139,35 +124,37 @@ public class ApiAppUserController {
      */
     @PostMapping("/sendMobileCode")
     public Result sendMobileCode (@RequestBody SendPhoneCodeDTO codeDTO){
-        return appUserService.sendMobileCode(codeDTO.getCodeType(),codeDTO.getPhone(),codeDTO.getZone() == null ? "" : codeDTO.getZone());
+        ValidatorUtils.validateEntity(codeDTO);
+        return appUserService.sendMobileCode(codeDTO.getCodeType(),codeDTO.getPhone(),codeDTO.getZone());
     }
 
 
     @GetMapping("/captcha")
-    @Operation(summary = "验证码")
+    @Operation(summary = "图形验证码")
     @Parameter(in = ParameterIn.QUERY, ref = "string", name = "uuid", required = true)
     public void captcha(HttpServletResponse response, String uuid) throws IOException {
         //唯一标识不能为空
         AssertUtils.isBlank(uuid, ErrorCode.IDENTIFIER_NOT_NULL);
-
         //生成验证码
         captchaService.create(response, uuid);
     }
 
+
+
+
     /**
-     * 重置登陆密码
+     * 重置登陆密码 old
      *
      * @return
      */
     @PostMapping("/resetPwdByEmail")
     public Result resetPwdByEmail (@RequestBody ResetPwdByEmailDTO codeDTO){
         ValidatorUtils.validateEntity(codeDTO);
-
         return appUserService.resetPwdByEmail(codeDTO);
     }
 
     /**
-     * 重置登陆密码
+     * 重置登陆密码 old
      *
      * @return
      */
@@ -177,4 +164,61 @@ public class ApiAppUserController {
 
         return appUserService.resetPwdByPhone(codeDTO);
     }
+
+    /**
+     * 验证图形验证码:
+     * 找回密码 FIND_PASSWORD
+     *
+     * @param dto
+     * @param request
+     * @return
+     */
+    @PostMapping("/checkCaptcha")
+    @Operation(summary = "验证图形验证码")
+    public Result checkCaptcha(@RequestBody CheckCaptchaDTO dto, HttpServletRequest request) {
+        ValidatorUtils.validateEntity(dto);
+        return appUserService.checkCaptcha(dto,request);
+    }
+
+    /**
+     * 验证手机验证码
+     * @return
+     */
+    @PostMapping("/checkPhoneCode")
+    public Result checkPhoneCode (@RequestBody CheckPhoneCodeDTO dto){
+        ValidatorUtils.validateEntity(dto);
+        return appUserService.checkPhoneCode(dto.getCodeType(),dto.getZone(),dto.getPhone(),dto.getCode());
+    }
+
+    /**
+     * 验证邮箱验证码
+     * @return
+     */
+    @PostMapping("/checkEmailCode")
+    public Result checkEmailCode (@RequestBody CheckEmailCodeDTO dto){
+        ValidatorUtils.validateEntity(dto);
+        return appUserService.checkEmailCode(dto.getCodeType(),dto.getEmail(),dto.getCode());
+    }
+
+    /**
+     * 重置登陆密码
+     *
+     * @return
+     */
+    @PostMapping("/resetPwdEmail")
+    public Result resetPwdEmail (@RequestBody ResetPwdEmailDTO dto){
+        ValidatorUtils.validateEntity(dto);
+        return appUserService.resetPwdByEmail(dto.getEmail(),dto.getNewPwd());
+    }
+
+    /**
+     * 重置登陆密码
+     *
+     * @return
+     */
+    @PostMapping("/resetPwdPhone")
+    public Result resetPwdPhone (@RequestBody ResetPwdPhoneDTO dto){
+        ValidatorUtils.validateEntity(dto);
+        return appUserService.resetPwdByPhone(dto.getZone(),dto.getPhone(),dto.getNewPwd());
+    }
 }

+ 4 - 4
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/AppLoginDTO.java

@@ -24,19 +24,19 @@ import lombok.Data;
 public class AppLoginDTO {
 
     @Schema(title = "密码")
-    @NotBlank(message="{AppLoginDTO.loginPassword.NotBlank}")//密码不能为空
+    @NotBlank(message="{NotBlank.password}")//密码不能为空
     private String loginPassword;
 
     @Schema(title = "账号")
-    @NotBlank(message="AppLoginDTO.loginName.NotBlank")//账号不能为空
+    @NotBlank(message="{NotBlank.loginName}")//账号不能为空
     private String loginName;
 
     @Schema(title = "验证码")
-    @NotBlank(message="AppLoginDTO.code.NotBlank")//验证码不能为空
+    @NotBlank(message="{NotBlank.code}")//验证码不能为空
     private String code;
 
     @Schema(title = "唯一标识")
-    @NotBlank(message="AppLoginDTO.uuid.NotBlank")//唯一标识不能为空
+    @NotBlank(message="{NotBlank.uuid}")//唯一标识不能为空
     private String uuid;
 
 //    @Schema(title = "登录类型")

+ 19 - 14
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/AppRegisterDTO.java

@@ -9,6 +9,7 @@
 package com.qnfhq.modules.user.dto;
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.Email;
 import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 import lombok.Data;
@@ -17,34 +18,38 @@ import lombok.Data;
 /**
  * 注册表单
  *
- * @author Mark sunlightcs@gmail.com
+ * @author Yelz
  */
 @Data
 @Schema(title = "注册表单")
 public class AppRegisterDTO {
 
     @Schema(title = "密码")
-    @NotBlank(message="{AppRegisterDTO.loginPassword.NotBlank}")//密码不能为空
+    @NotBlank(message="{NotBlank.password}")//密码不能为空
     private String loginPassword;
 
     @Schema(title = "邮箱")
-    @NotBlank(message="{AppRegisterDTO.email.NotBlank}")//邮箱不能为空
+    @Email(message = "{Email.format.err}")//邮箱格式不正确
+    @NotBlank(message="{NotBlank.email}")//邮箱不能为空
     private String email;
 
-    @Schema(title = "验证码")
-    @NotBlank(message="{AppRegisterDTO.code.NotBlank}")//验证码不能为空
-    private String code;
+    @Schema(title = "区号")
+    @NotBlank(message="{NotBlank.zone}")//区号不能为空
+    private String zone;
 
-//    @Schema(title = "手机号")
-//    private String phone;
-
-//    @Schema(title = "登录类型")
-//    @NotNull(message="{AppRegisterDTO.signType.NotNull}")//登录类型不能为空
-//    private int signType;
+    @Schema(title = "手机号")
+    @NotBlank(message="{NotBlank.phone}")//手机号不能为空
+    private String phone;
 
     @Schema(title = "推荐码")
     private String activeCode;
 
-//    @Schema(title = "区号")
-//    private String zone;
+    @Schema(title = "验证码类型")
+    @NotBlank(message="{NotBlank.codeType}")//验证码类型不能空
+    private String codeType;
+
+    //    @Schema(title = "验证码")
+//    @NotBlank(message="{NotBlank.code}")//验证码不能为空
+//    private String code;
+
 }

+ 3 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/AppUserDTO.java

@@ -27,6 +27,9 @@ public class AppUserDTO implements Serializable {
 	@SchemaProperty(name = "登陆密码")
 	private String loginPassword;
 
+    @SchemaProperty(name = "区号")
+    private String zone;
+
 	@SchemaProperty(name = "手机号")
 	private String phone;
 

+ 32 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/CheckCaptchaDTO.java

@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.qnfhq.modules.user.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+
+@Data
+@Schema(title = "校验验证码表单")
+public class CheckCaptchaDTO {
+
+//    @Schema(title = "验证码类型")
+//    @NotBlank(message="{NotBlank.codeType}")//验证码类型不能空
+//    private String codeType;
+
+    @Schema(title = "验证码")
+    @NotBlank(message="{NotBlank.code}")//验证码不能为空
+    private String code;
+
+    @Schema(title = "唯一标识")
+    @NotBlank(message="{NotBlank.uuid}")//唯一标识不能为空
+    private String uuid;
+
+}

+ 25 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/CheckEmailCodeDTO.java

@@ -0,0 +1,25 @@
+package com.qnfhq.modules.user.dto;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+@Data
+public class CheckEmailCodeDTO {
+
+    @Schema(title = "验证码类型")
+    @NotBlank(message="{NotBlank.codeType}")//验证码类型不能空
+    private String codeType;
+
+    @Schema(title = "邮箱")
+    @Email(message = "{Email.format.err}")//邮箱格式不正确
+    @NotBlank(message="{NotBlank.email}")//邮箱不能为空
+    private String email;
+
+    @Schema(title = "验证码")
+    @NotBlank(message="{NotBlank.code}")//验证码不能为空
+    private String code;
+
+}

+ 26 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/CheckPhoneCodeDTO.java

@@ -0,0 +1,26 @@
+package com.qnfhq.modules.user.dto;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+@Data
+public class CheckPhoneCodeDTO {
+
+    @Schema(title = "验证码类型")
+    @NotBlank(message="{NotBlank.codeType}")//验证码类型不能空
+    private String codeType;
+
+    @Schema(title = "手机号")
+    @NotBlank(message="{NotBlank.phone}")//手机号不能为空
+    private String phone;
+
+    @Schema(title = "区号")
+    @NotBlank(message="{NotBlank.zone}")//区号不能为空
+    private String zone;
+
+    @Schema(title = "验证码")
+    @NotBlank(message="{NotBlank.code}")//验证码不能为空
+    private String code;
+}

+ 5 - 17
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/ResetPwdByEmailDTO.java

@@ -14,7 +14,7 @@ import lombok.Data;
 
 
 /**
- * 重设密码
+ * 重设密码 old
  *
  * @author Yelz 30262728@qq.com
  */
@@ -22,30 +22,18 @@ import lombok.Data;
 @Schema(title = "重设密码表单")
 public class ResetPwdByEmailDTO {
 
-
-
     @Schema(title = "密码")
-    @NotBlank(message="{ResetPwdDTO.newPwd.NotBlank}")//密码不能为空
+    @NotBlank(message="{NotBlank.password}")//密码不能为空
     private String newPwd;
 
     @Schema(title = "邮箱")
-    @NotBlank(message="ResetPwdDTO.email.NotBlank")//邮箱不能为空
+    @NotBlank(message="{NotBlank.email}")//邮箱不能为空
     private String email;
 
-    @Schema(title = "邮箱验证码")
-    @NotBlank(message="ResetPwdDTO.code.NotBlank")//邮箱验证码不能为空
+    @Schema(title = "验证码")
+    @NotBlank(message="{NotBlank.code}")//验证码不能为空
     private String code;
 
-//    @Schema(title = "谷歌验证码")
-//    @NotBlank(message="ResetPwdDTO.googleCode.NotBlank")//谷歌验证码不能为空
-//    private String googleCode;
-
-//    @Schema(title = "图形验证码")
-//    @NotBlank(message="ResetPwdDTO.uuidCode.NotBlank")//图形验证码不能为空
-//    private String uuidCode;
-//
-//    @Schema(title = "唯一标识")
-//    private String uuid;
 
 
 }

+ 5 - 5
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/ResetPwdByPhoneDTO.java

@@ -5,7 +5,7 @@ import jakarta.validation.constraints.NotBlank;
 import lombok.Data;
 
 /**
- * 一句话描述
+ * 重设密码表单 old
  *
  * @Author: Yelz
  * @Date: 2025/11/14 15:04
@@ -15,19 +15,19 @@ import lombok.Data;
 @Schema(title = "重设密码表单")
 public class ResetPwdByPhoneDTO {
     @Schema(title = "密码")
-    @NotBlank(message="{ResetPwdDTO.newPwd.NotBlank}")//新密码不能为空
+    @NotBlank(message="{NotBlank.password}")//新密码不能为空
     private String newPwd;
 
     @Schema(title = "手机号")
-    @NotBlank(message="ResetPwdDTO.phone.NotBlank")//手机号不能为空
+    @NotBlank(message="{NotBlank.phone}")//手机号不能为空
     private String phone;
 
     @Schema(title = "验证码")
-    @NotBlank(message="ResetPwdDTO.code.NotBlank")//验证码不能为空
+    @NotBlank(message="{NotBlank.code}")//验证码不能为空
     private String code;
 
     @Schema(title = "区号")
-    @NotBlank(message="ResetPwdDTO.zone.NotBlank")//区号不能为空
+    @NotBlank(message="{NotBlank.zone}")//区号不能为空
     private String zone;
 
 //    @Schema(title = "谷歌验证码")

+ 35 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/ResetPwdEmailDTO.java

@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.qnfhq.modules.user.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+
+/**
+ * 重设密码
+ *
+ * @author Yelz 30262728@qq.com
+ */
+@Data
+@Schema(title = "重设密码表单")
+public class ResetPwdEmailDTO {
+
+    @Schema(title = "密码")
+    @NotBlank(message="{NotBlank.password}")//密码不能为空
+    private String newPwd;
+
+    @Schema(title = "邮箱")
+    @NotBlank(message="{NotBlank.email}")//邮箱不能为空
+    private String email;
+
+
+
+}

+ 29 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/ResetPwdPhoneDTO.java

@@ -0,0 +1,29 @@
+package com.qnfhq.modules.user.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+/**
+ * 重设密码表单 old
+ *
+ * @Author: Yelz
+ * @Date: 2025/11/14 15:04
+ * @Description:
+ */
+@Data
+@Schema(title = "重设密码表单")
+public class ResetPwdPhoneDTO {
+    @Schema(title = "密码")
+    @NotBlank(message="{NotBlank.password}")//新密码不能为空
+    private String newPwd;
+
+    @Schema(title = "手机号")
+    @NotBlank(message="{NotBlank.phone}")//手机号不能为空
+    private String phone;
+
+    @Schema(title = "区号")
+    @NotBlank(message="{NotBlank.zone}")//区号不能为空
+    private String zone;
+
+}

+ 4 - 2
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/SendEmailCodeDTO.java

@@ -2,6 +2,7 @@ package com.qnfhq.modules.user.dto;
 
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.Email;
 import jakarta.validation.constraints.NotBlank;
 import lombok.Data;
 
@@ -9,11 +10,12 @@ import lombok.Data;
 public class SendEmailCodeDTO {
 
     @Schema(title = "验证码类型")
-    @NotBlank(message="{SendEmailCodeDTO.codeType.NotBlank}")//验证码类型不能空
+    @NotBlank(message="{NotBlank.codeType}")//验证码类型不能空
     private String codeType;
 
     @Schema(title = "邮箱")
-    @NotBlank(message="{SendEmailCodeDTO.email.NotBlank}")//邮箱不能为空
+    @Email(message = "{Email.format.err}")//邮箱格式不正确
+    @NotBlank(message="{NotBlank.email}")//邮箱不能为空
     private String email;
 
 

+ 7 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/SendPhoneCodeDTO.java

@@ -2,16 +2,23 @@ package com.qnfhq.modules.user.dto;
 
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
 import lombok.Data;
 
 @Data
 public class SendPhoneCodeDTO {
 
     @Schema(title = "验证码类型")
+    @NotBlank(message="{NotBlank.codeType}")//验证码类型不能空
     private String codeType;
 
+    @Schema(title = "手机号")
+    @NotBlank(message="{NotBlank.phone}")//手机号不能为空
     private String phone;
 
+    @Schema(title = "区号")
+    @NotBlank(message="{NotBlank.zone}")//区号不能为空
     private String zone;
 
+
 }

+ 6 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/entity/AppUserEntity.java

@@ -37,7 +37,9 @@ public class AppUserEntity implements Serializable {
     /**
      * 手机号
      */
+    private String zone;
 	private String phone;
+
     /**
      * 0-正常 1-测试
      */
@@ -112,4 +114,8 @@ public class AppUserEntity implements Serializable {
      * 昵称
      */
 	private String nickname;
+    /**
+     * 提币或c2c卖出限制时间
+     */
+    private Date transferOutTime;
 }

+ 2 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/enums/UserCodeTypeEnum.java

@@ -20,10 +20,12 @@ public enum UserCodeTypeEnum {
      * 找回用户
      */
     FIND_USER  ,
+
     /**
      * 找回用户
      */
     FIND_PASSWORD  ,
+
     /**
      * 修改密码
      */

+ 9 - 4
qnfhq-api/src/main/java/com/qnfhq/modules/user/service/AppUserService.java

@@ -2,12 +2,10 @@ package com.qnfhq.modules.user.service;
 
 import com.qnfhq.common.service.BaseService;
 import com.qnfhq.common.utils.Result;
-import com.qnfhq.modules.user.dto.AppLoginDTO;
-import com.qnfhq.modules.user.dto.AppRegisterDTO;
-import com.qnfhq.modules.user.dto.ResetPwdByEmailDTO;
-import com.qnfhq.modules.user.dto.ResetPwdByPhoneDTO;
+import com.qnfhq.modules.user.dto.*;
 import com.qnfhq.modules.user.entity.AppUserEntity;
 import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.web.bind.annotation.RequestBody;
 
 /**
  * 玩家用户表
@@ -65,4 +63,11 @@ public interface AppUserService extends BaseService<AppUserEntity> {
     Result resetPwdByPhone(ResetPwdByPhoneDTO codeDTO);
 
 
+    Result checkCaptcha(CheckCaptchaDTO dto, HttpServletRequest request);
+
+    Result checkPhoneCode(String codeType,String zone,String phone,String code);
+
+    Result checkEmailCode(String codeType,String email,String code);
+    Result resetPwdByEmail(String email,String pwd);
+    Result resetPwdByPhone(String zone,String phone,String pwd);
 }

+ 197 - 88
qnfhq-api/src/main/java/com/qnfhq/modules/user/service/impl/AppUserServiceImpl.java

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.qnfhq.common.exception.RenException;
 import com.qnfhq.common.redis.RedisUtils;
+import com.qnfhq.common.utils.DateUtils;
 import com.qnfhq.common.utils.IpUtils;
 import com.qnfhq.common.utils.MessageUtils;
 import com.qnfhq.common.utils.Result;
@@ -22,6 +23,7 @@ import com.qnfhq.modules.user.entity.SettingEntity;
 import com.qnfhq.modules.user.enums.*;
 import com.qnfhq.modules.user.service.*;
 import com.qnfhq.utils.EmailUtils;
+import com.qnfhq.utils.EmailValidUtils;
 import com.qnfhq.utils.OrderUtils;
 import com.qnfhq.utils.password.PasswordUtils;
 import com.qnfhq.utils.sms.SmsSenderUtil;
@@ -125,63 +127,32 @@ public class AppUserServiceImpl extends BaseServiceImpl<AppUserDao, AppUserEntit
         }
 
         AppUserEntity appUserEntity = new AppUserEntity();
-//        int signType = registerDto.getSignType();
-//        if(signType==1) {//使用邮箱注册、校验验证码
-            AppUserEntity appUser = baseDao.selectOne(new LambdaQueryWrapper<AppUserEntity>()
-                    .eq(AppUserEntity::getEmail, registerDto.getEmail())
-                    .last(" limit 1")
-            );
-            if(Objects.nonNull(appUser)){
-                throw new RenException(MessageUtils.message("user.register.email.exisit"));//邮箱已存在
-            }
-
-
-            final String registerEmailCode = String.format("%s%s", CachePrefix.EMAIL_CODE.getPrefix()+ UserCodeTypeEnum.valueOf("REGISTER"), registerDto.getEmail());
-            Object emailCode = redisUtils.get(registerEmailCode);
-            if (emailCode == null) {
-                throw new RenException(MessageUtils.message("user.register.code.err"));//验证码错误
-            } else {
-                final String codeKeyTry = String.format("%s%s", registerEmailCode,"try");
-                checkCodeTryTimes(codeKeyTry);
-                String validCode = emailCode.toString();
-                if (!registerDto.getCode().equalsIgnoreCase(validCode)) {
-                    redisUtils.increment(codeKeyTry, 1L, ApiConstant.EMAIL_EXPIRE);
-                    throw new RenException(MessageUtils.message("user.register.code.err"));//验证码错误
-                }
-            }
-            redisUtils.delete(registerEmailCode);
-            appUserEntity.setLoginName(registerDto.getEmail());
-//        } else if (signType==2) {//使用手机号注册
-//            AppUserEntity appUser = baseDao.selectOne(new LambdaQueryWrapper<AppUserEntity>()
-//                    .eq(AppUserEntity::getPhone, registerDto.getPhone())
-//                    .last(" limit 1")
-//            );
-//            if(Objects.nonNull(appUser)){
-//                throw new RenException(MessageUtils.message("user.register.phone.exist"));//手机号已经存在
-//            }
-//
-//            final String registerPhoneCode = String.format("%s%s%s", CachePrefix.SMS_CODE.getPrefix()+ UserCodeTypeEnum.valueOf("REGISTER"), registerDto.getZone(), registerDto.getPhone());
-//            Object smsCode = redisUtils.get(registerPhoneCode);
-//            if (smsCode == null) {
-//                throw new RenException(MessageUtils.message("user.register.code.err"));//验证码错误
-//            } else {
-//                String validCode = smsCode.toString();
-//                if (!registerDto.getCode().equalsIgnoreCase(validCode)) {
-//                    redisUtils.delete(registerPhoneCode);
-//                    throw new RenException(MessageUtils.message("user.register.code.err"));//验证码错误
-//                }
-//            }
-//            redisUtils.delete(registerPhoneCode);
-//            appUserEntity.setLoginName(registerDto.getPhone());
-//        } else {
-//            throw new RenException(MessageUtils.message("user.register.signtype.err"));//登录类型错误
-//        }
+        //临时邮箱检测
+        EmailValidUtils.validateEmail(registerDto.getEmail());
+
+        //验证码校验
+        String codeType = registerDto.getCodeType();
+        final String phoneCodeResultKey = String.format("%s%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),registerDto.getZone(),registerDto.getPhone(),":result");
+        verifyResult(phoneCodeResultKey);
+        final String emailCodeResultKey = String.format("%s%s%s%s", CachePrefix.EMAIL_CODE.getPrefix(), UserCodeTypeEnum.valueOf(codeType).name(), registerDto.getEmail(),":result");
+        verifyResult(emailCodeResultKey);
+
+        AppUserEntity appUser = getUserByEmail(registerDto.getEmail());
+        if(Objects.nonNull(appUser)){
+            throw new RenException(MessageUtils.message("user.register.email.exisit"));//邮箱已存在
+        }
+        appUser = getUserByMobile(registerDto.getPhone());
+        if(Objects.nonNull(appUser)){
+            throw new RenException(MessageUtils.message("user.register.phone.exisit"));//手机号已存在
+        }
 
+        appUserEntity.setLoginName(registerDto.getEmail().toLowerCase());
         String host = request.getServerName();
         appUserEntity.setHost(host);
         appUserEntity.setRegisterIp(IpUtils.getIpAddr(request));
-        appUserEntity.setEmail(registerDto.getEmail());
-        //appUserEntity.setPhone(registerDto.getPhone());
+        appUserEntity.setEmail(registerDto.getEmail().toLowerCase());
+        appUserEntity.setZone(registerDto.getZone());
+        appUserEntity.setPhone(registerDto.getPhone());
         appUserEntity.setStatus(0);
         appUserEntity.setIsTest(0);
         appUserEntity.setIsBlack(UserBlackEnum.NORMAL.getCode());
@@ -253,18 +224,27 @@ public class AppUserServiceImpl extends BaseServiceImpl<AppUserDao, AppUserEntit
             throw new RenException(MessageUtils.message("appUser.login.code.err"));//验证码错误
         }
 
-        //账号密码校验
+        //账号密码失败重试次数
+        checkPwdErrTryTimes(dto.getLoginName());
+
+
+//        passwordTryTimes(pwdFailHourKey);
+
         AppUserEntity appUser = getUserByLoginName(dto.getLoginName());
         if(appUser==null) {
             throw new RenException(MessageUtils.message("appUser.loginName.or.password.err"));//账号或密码错误
         }
         if(!PasswordUtils.matches(dto.getLoginPassword(),appUser.getLoginPassword())){
-            throw new RenException(MessageUtils.message("appUser.loginName.or.password.err"));//账号或密码错误
+            long pwdFailTimes = setPwdErrTryTimes(dto.getLoginName());
+            checkPwdErrTryTimes(dto.getLoginName());
+            throw new RenException(MessageUtils.message("appUser.loginName.or.password.err.limit.chance",ApiConstant.PASSWORD_FAIL_HOUR_TIMES-pwdFailTimes));//账号或密码错误,您还有4次机会
         }
         //是否黑名单
         if(Objects.nonNull(appUser.getIsBlack()) && appUser.getIsBlack() == UserBlackEnum.BLOCK.getCode()){
             throw new RenException(MessageUtils.message("user_is_black"));//您的账号已被列入黑名单,无法登录。
         }
+
+
         StpUtil.login(appUser.getId());
         appuserLoginLogService.insertAppActionLog(appUser, "用户登录", "0", request);
 
@@ -352,7 +332,7 @@ public class AppUserServiceImpl extends BaseServiceImpl<AppUserDao, AppUserEntit
             }
         }
 
-        final String emailKey = String.format("%s%s%s",CachePrefix.EMAIL_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType),email);
+        final String emailKey = String.format("%s%s%s",CachePrefix.EMAIL_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),email);
         sendCodeFrequencyLimit(ApiConstant.EMAIL_EXPIRE,emailKey);
 
         Result result = new Result();
@@ -389,7 +369,7 @@ public class AppUserServiceImpl extends BaseServiceImpl<AppUserDao, AppUserEntit
         }
 
 
-        final String smsKey = String.format("%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType),zone,phone);
+        final String smsKey = String.format("%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),zone,phone);
         sendCodeFrequencyLimit(ApiConstant.SMS_EXPIRE,smsKey);
 
         //发送验证码
@@ -401,9 +381,7 @@ public class AppUserServiceImpl extends BaseServiceImpl<AppUserDao, AppUserEntit
         sendPhoneDto.setCode(codeType);
         sendPhoneDto.setParams(map);
         Result result = smsSendService.sendMobileCodeV2(sendPhoneDto);
-        log.info("result={}", result);
         if(result.getCode() == 200){
-            //验证码有效期5分钟
             redisUtils.set(smsKey, randomCode, ApiConstant.SMS_EXPIRE);
             final String codeTryKey = String.format("%s%s", smsKey,"try");
             redisUtils.delete(codeTryKey);
@@ -432,21 +410,9 @@ public class AppUserServiceImpl extends BaseServiceImpl<AppUserDao, AppUserEntit
         Result result = new Result();
 
         //校验邮箱验证码
-        final String emailCodeKey = String.format("%s%s", CachePrefix.EMAIL_CODE.getPrefix()+ UserCodeTypeEnum.valueOf("FIND_PASSWORD"), codeDTO.getEmail());
-        Object emailCode = redisUtils.get(emailCodeKey);
-        if (emailCode == null) {
-            throw new RenException(MessageUtils.message("user.register.code.err"));//验证码错误
-        } else {
-            final String codeKeyTry = String.format("%s%s", emailCodeKey,"try");
-            checkCodeTryTimes(codeKeyTry);
-            String validCode = emailCode.toString();
-            if (!codeDTO.getCode().equalsIgnoreCase(validCode)) {
-                redisUtils.increment(codeKeyTry, 1L, ApiConstant.EMAIL_EXPIRE);
-                throw new RenException(MessageUtils.message("user.register.code.err"));//验证码错误
-            }
-        }
-        redisUtils.delete(emailCodeKey);
+        checkEmailCode("FIND_PASSWORD",codeDTO.getEmail(),codeDTO.getCode());
 
+        //更新密码
         AppUserEntity appUser = getUserByEmail(codeDTO.getEmail());
         if(Objects.isNull(appUser)){
             throw new RenException(MessageUtils.message("user.not.exist"));//用户不存在
@@ -457,6 +423,65 @@ public class AppUserServiceImpl extends BaseServiceImpl<AppUserDao, AppUserEntit
 
     }
 
+
+    @Override
+    public Result resetPwdByEmail(String email,String newPwd) {
+        Result result = new Result();
+        String codeType = "FIND_PASSWORD";
+        //校验邮箱验证码
+        final String emailCodeResultKey = String.format("%s%s%s%s", CachePrefix.EMAIL_CODE.getPrefix(), UserCodeTypeEnum.valueOf(codeType).name(), email,":result");
+        verifyResult(emailCodeResultKey);
+
+        //更新密码
+        AppUserEntity appUser = getUserByEmail(email);
+        if(Objects.isNull(appUser)){
+            throw new RenException(MessageUtils.message("user.not.exist"));//用户不存在
+        }
+        final String phoneCodeResultKey = String.format("%s%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),appUser.getZone(),appUser.getPhone(),":result");
+        verifyResult(phoneCodeResultKey);
+
+        appUser.setLoginPassword(PasswordUtils.encode(newPwd));
+        appUser.setTransferOutTime(DateUtils.addDays(new Date(),1));
+        updateById(appUser);
+
+        return result;
+
+    }
+
+
+    @Override
+    public Result resetPwdByPhone(String zone,String phone,String newPwd) {
+        Result result = new Result();
+        String codeType = "FIND_PASSWORD";
+        //校验手机验证码
+        final String phoneCodeResultKey = String.format("%s%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),zone,phone,":result");
+        verifyResult(phoneCodeResultKey);
+
+
+        //更新密码
+        AppUserEntity appUser = getUserByMobile(phone);
+        if(Objects.isNull(appUser)){
+            throw new RenException(MessageUtils.message("user.not.exist"));//用户不存在
+        }
+
+        final String emailCodeResultKey = String.format("%s%s%s%s", CachePrefix.EMAIL_CODE.getPrefix(), UserCodeTypeEnum.valueOf(codeType).name(), appUser.getEmail(),":result");
+        verifyResult(emailCodeResultKey);
+
+        appUser.setLoginPassword(PasswordUtils.encode(newPwd));
+        updateById(appUser);
+        return result;
+
+    }
+
+
+    private void verifyResult(String codeResultKey) {
+        Object codeResult = redisUtils.get(codeResultKey);
+        if(Objects.isNull(codeResult) || (int)codeResult != 1){
+            throw new RenException(MessageUtils.message("system.busy.try.again.later"));//系统繁忙,请稍后再试
+        }
+        redisUtils.delete(codeResultKey);
+    }
+
     /**
      * 重设密码
      * @param codeDTO
@@ -467,21 +492,9 @@ public class AppUserServiceImpl extends BaseServiceImpl<AppUserDao, AppUserEntit
         Result result = new Result();
 
         //校验手机验证码
-        final String phoneCodeKey = String.format("%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf("FIND_PASSWORD"),codeDTO.getZone(),codeDTO.getPhone());
-        Object phoneCode = redisUtils.get(phoneCodeKey);
-        if (phoneCode == null) {
-            throw new RenException(MessageUtils.message("user.register.code.err"));//验证码错误
-        } else {
-            final String codeKeyTry = String.format("%s%s", phoneCodeKey,"try");
-            checkCodeTryTimes(codeKeyTry);
-            String validCode = phoneCode.toString();
-            if (!codeDTO.getCode().equalsIgnoreCase(validCode)) {
-                redisUtils.increment(codeKeyTry, 1L, ApiConstant.SMS_EXPIRE);
-                throw new RenException(MessageUtils.message("user.register.code.err"));//验证码错误
-            }
-        }
-        redisUtils.delete(phoneCodeKey);
+        checkPhoneCode("FIND_PASSWORD",codeDTO.getZone(),codeDTO.getPhone(),codeDTO.getCode());
 
+        //更新密码
         AppUserEntity appUser = getUserByMobile(codeDTO.getPhone());
         if(Objects.isNull(appUser)){
             throw new RenException(MessageUtils.message("user.not.exist"));//用户不存在
@@ -492,7 +505,9 @@ public class AppUserServiceImpl extends BaseServiceImpl<AppUserDao, AppUserEntit
 
     }
 
-    //重试5次验证失败
+    /**
+     *限制验证码重试次数
+     */
     private void checkCodeTryTimes(String codeKey) {
         Object tryTimesObj = redisUtils.get(codeKey);
         if(Objects.nonNull(tryTimesObj)){
@@ -501,9 +516,103 @@ public class AppUserServiceImpl extends BaseServiceImpl<AppUserDao, AppUserEntit
                 throw new RenException(MessageUtils.message("code.try.times.limit"));//重试次数过多
             }
         }
+    }
+
+    /**
+     * 校验密码输错次数
+     * 密码输错5次,锁住1小时
+     * 累计输错10次,锁24小时
+     */
+    private void checkPwdErrTryTimes(String loginName) {
+        final String codeKey = String.format("%s%s","pwd_fail_hour_times:", loginName);
+        Object tryTimesObj = redisUtils.get(codeKey);
+        if(Objects.nonNull(tryTimesObj)){
+            long pwdHourFailTimes = Long.valueOf(tryTimesObj.toString());
+            if(pwdHourFailTimes>=ApiConstant.PASSWORD_FAIL_HOUR_TIMES){
+                long expireTime = redisUtils.getExpire(codeKey);
+                if(expireTime>3600){
+                    long hourL = expireTime/3600L;
+                    throw new RenException(MessageUtils.message("pwd.fail.times.excess.day.lock",hourL));//账号已锁,{0}小时后解锁
+                } else if(expireTime>60){
+                    long minL = expireTime/60L;
+                    throw new RenException(MessageUtils.message("pwd.fail.times.excess.hour.lock",minL));//账号已锁,{0}分钟后解锁
+                } else {
+                    throw new RenException(MessageUtils.message("pwd.fail.times.excess.second.lock",expireTime));//账号已锁,{0}秒后解锁
+                }
+            }
+        }
+    }
+
+    /**
+     * 设置密码输错次数+1
+     */
+    private long setPwdErrTryTimes(String loginName) {
+        final String pwdErrTimsHourKey = String.format("%s%s","pwd_fail_hour_times:", loginName);
+        final String pwdErrTimsDayKey = String.format("%s%s","pwd_fail_day_times:", loginName);
+
+        long pwdErrDayTimes = redisUtils.increment(pwdErrTimsDayKey, 1L, ApiConstant.PASSWORD_FAIL_LOCK_24HOUR);
+        long pwdFailTimes = 1;
+        if(pwdErrDayTimes>=ApiConstant.PASSWORD_FAIL_DAY_TIMES) {
+            pwdFailTimes = redisUtils.increment(pwdErrTimsHourKey, 1L, ApiConstant.PASSWORD_FAIL_LOCK_24HOUR);
+        } else {
+            pwdFailTimes = redisUtils.increment(pwdErrTimsHourKey, 1L, ApiConstant.PASSWORD_FAIL_LOCK_HOUR);
+        }
+        return pwdFailTimes;
+    }
+
+
+    @Override
+    public Result checkCaptcha(CheckCaptchaDTO dto, HttpServletRequest request)
+    {
+        if(!captchaService.validate(dto.getUuid(), dto.getCode())) {
+            throw new RenException(MessageUtils.message("appUser.login.code.err"));//验证码错误
+        }
+        Result result = new Result();
+        return result;
+    }
+
+    @Override
+    public Result checkPhoneCode(String codeType,String zone,String phone,String code)
+    {
+        //校验手机验证码
+        final String phoneCodeKey = String.format("%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),zone,phone);
+        return checkCode(phoneCodeKey,code);
+    }
 
 
+    @Override
+    public Result checkEmailCode(String codeType,String email,String code)
+    {
+        //校验邮箱验证码
+        final String emailCodeKey = String.format("%s%s%s", CachePrefix.EMAIL_CODE.getPrefix(), UserCodeTypeEnum.valueOf(codeType).name(), email);
+        return checkCode(emailCodeKey,code);
     }
 
+    /**
+     * 校验验证码
+     * @param cacheKey
+     * @param code
+     * @return
+     */
+    private Result checkCode(String cacheKey,String code) {
+        Object checkCode = redisUtils.get(cacheKey);
+        if (checkCode == null) {
+            throw new RenException(MessageUtils.message("user.register.code.err"));//验证码错误
+        } else {
+            final String codeKeyTry = String.format("%s%s", cacheKey,"try");
+            checkCodeTryTimes(codeKeyTry);
+            String validCode = checkCode.toString();
+            if (!code.equalsIgnoreCase(validCode)) {
+                redisUtils.increment(codeKeyTry, 1L, ApiConstant.CHECK_EXPIRE);
+                throw new RenException(MessageUtils.message("user.register.code.err"));//验证码错误
+            }
+        }
+        redisUtils.delete(cacheKey);
+        //设置验证结果
+        final String checkCodeResult = String.format("%s%s",cacheKey,":result");
+        redisUtils.set(checkCodeResult,1,ApiConstant.CHECK_EXPIRE);
 
+        Result result = new Result();
+        return result;
+    }
 }

+ 72 - 0
qnfhq-api/src/main/java/com/qnfhq/utils/EmailValidUtils.java

@@ -0,0 +1,72 @@
+package com.qnfhq.utils;
+
+import com.qnfhq.common.exception.RenException;
+import com.qnfhq.common.utils.MessageUtils;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * 验证邮箱非临时邮箱
+ *
+ * @Author: Yelz 30262728@qq.com
+ * @Date: 2025/11/15 09:21
+ * @Description:
+ */
+public class EmailValidUtils {
+
+    // 常见临时邮箱域名
+    private final static Set<String> TEMP_DOMAINS = new HashSet<>(Set.of(
+            "tempmail.com", "10minutemail.com", "guerrillamail.com",
+            "mailinator.com", "yopmail.com", "throwawaymail.com",
+            "temp-mail.org", "fakeinbox.com", "disposableemail.com",
+            "trashmail.com", "getairmail.com", "tempail.com",
+            "maildrop.cc", "sharklasers.com", "guerrillamail.net",
+            "grr.la", "spam4.me", "dispostable.com",
+            "tmpmail.org", "owleyes.ch", "33mail.com"
+    ));
+
+    // 常见可信邮箱域名(知名邮箱服务商)
+//    private final static Set<String> TRUSTED_DOMAINS = new HashSet<>(Set.of(
+//            "gmail.com", "outlook.com", "hotmail.com", "yahoo.com",
+//            "qq.com", "163.com", "126.com", "sina.com","sina.cn",
+//            "sohu.com", "icloud.com", "aol.com", "protonmail.com",
+//            "live.com", "msn.com", "foxmail.com", "139.com"
+//    ));
+
+
+
+    /**
+     * 邮箱验证
+     */
+    public static void validateEmail(String email) {
+
+        String domain = extractDomain(email);
+
+        // 临时邮箱检测
+        if (isTempEmailDomain(domain)) {
+            throw new RenException(MessageUtils.message("user.register.email.isTemp"));//检测到临时邮箱,请使用真实邮箱
+        }
+
+    }
+
+    /**
+     * 提取邮箱域名
+     */
+    public static String extractDomain(String email) {
+        int atIndex = email.lastIndexOf('@');
+        if (atIndex > 0 && atIndex < email.length() - 1) {
+            return email.substring(atIndex + 1).toLowerCase();
+        }
+        return "";
+    }
+
+    /**
+     * 检查是否为临时邮箱域名
+     */
+    public static boolean isTempEmailDomain(String domain) {
+        return TEMP_DOMAINS.contains(domain.toLowerCase());
+    }
+
+
+}

+ 7 - 2
qnfhq-api/src/main/resources/i18n/messages_zh.properties

@@ -47,5 +47,10 @@ user.not.exist=\u7528\u6237\u4e0d\u5b58\u5728
 code.try.times.limit=\u91cd\u8bd5\u6b21\u6570\u8fc7\u591a
 user.sendcode.frequency.limit=\u9a8c\u8bc1\u7801\u8bf7\u6c42\u592a\u8fc7\u9891\u7387\uff0c\u8bf760\u79d2\u540e\u518d\u8bd5
 user.email.send.fail=\u90ae\u7bb1\u53d1\u9001\u5931\u8d25
-
-
+user.register.email.isTemp=\u68c0\u6d4b\u5230\u4e34\u65f6\u90ae\u7bb1\uff0c\u8bf7\u4f7f\u7528\u771f\u5b9e\u90ae\u7bb1
+system.busy.try.again.later=\u7cfb\u7edf\u7e41\u5fd9\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5
+user.register.phone.exisit=\u624b\u673a\u53f7\u5df2\u5b58\u5728
+appUser.loginName.or.password.err.limit.chance=\u8d26\u53f7\u6216\u5bc6\u7801\u9519\u8bef\uff0c\u60a8\u8fd8\u6709{0}\u6b21\u673a\u4f1a
+pwd.fail.times.excess.hour.lock=\u8d26\u53f7\u5df2\u9501\uff0c{0}\u5206\u949f\u540e\u89e3\u9501
+pwd.fail.times.excess.day.lock=\u8d26\u53f7\u5df2\u9501\uff0c{0}\u5c0f\u65f6\u540e\u89e3\u9501
+pwd.fail.times.excess.second.lock=\u8d26\u53f7\u5df2\u9501\uff0c{0}\u79d2\u540e\u89e3\u9501

+ 10 - 14
qnfhq-api/src/main/resources/i18n/validation_zh.properties

@@ -1,14 +1,10 @@
-AppRegisterDTO.email.NotBlank=\u90ae\u7bb1\u4e0d\u80fd\u4e3a\u7a7a
-AppRegisterDTO.loginPassword.NotBlank=\u5bc6\u7801\u4e0d\u80fd\u4e3a\u7a7a
-AppRegisterDTO.code.NotBlank=\u9a8c\u8bc1\u7801\u4e0d\u80fd\u4e3a\u7a7a
-SendEmailCodeDTO.codeType.NotBlank=\u9a8c\u8bc1\u7801\u7c7b\u578b\u4e0d\u80fd\u7a7a
-SendEmailCodeDTO.email.NotBlank=\u90ae\u7bb1\u4e0d\u80fd\u4e3a\u7a7a
-AppLoginDTO.loginPassword.NotBlank=\u5bc6\u7801\u4e0d\u80fd\u4e3a\u7a7a
-AppLoginDTO.loginName.NotBlank=\u8d26\u53f7\u4e0d\u80fd\u4e3a\u7a7a
-AppLoginDTO.code.NotBlank=\u9a8c\u8bc1\u7801\u4e0d\u80fd\u4e3a\u7a7a
-AppLoginDTO.uuid.NotBlank=\u552f\u4e00\u6807\u8bc6\u4e0d\u80fd\u4e3a\u7a7a
-ResetPwdDTO.newPwd.NotBlank=\u65b0\u5bc6\u7801\u4e0d\u80fd\u4e3a\u7a7a
-ResetPwdDTO.email.NotBlank=\u90ae\u7bb1\u4e0d\u80fd\u4e3a\u7a7a
-ResetPwdDTO.phone.NotBlank=\u624b\u673a\u53f7\u4e0d\u80fd\u4e3a\u7a7a
-ResetPwdDTO.code.NotBlank=\u9a8c\u8bc1\u7801\u4e0d\u80fd\u4e3a\u7a7a
-ResetPwdDTO.zone.NotBlank=\u533a\u53f7\u4e0d\u80fd\u4e3a\u7a7a
+NotBlank.password=\u5bc6\u7801\u4e0d\u80fd\u4e3a\u7a7a
+NotBlank.email=\u90ae\u7bb1\u4e0d\u80fd\u4e3a\u7a7a
+NotBlank.codeType=\u9a8c\u8bc1\u7801\u7c7b\u578b\u4e0d\u80fd\u7a7a
+NotBlank.loginName=\u8d26\u53f7\u4e0d\u80fd\u4e3a\u7a7a
+NotBlank.uuid=\u552f\u4e00\u6807\u8bc6\u4e0d\u80fd\u4e3a\u7a7a
+NotBlank.phone=\u624b\u673a\u53f7\u4e0d\u80fd\u4e3a\u7a7a
+NotBlank.zone=\u533a\u53f7\u4e0d\u80fd\u4e3a\u7a7a
+NotBlank.code=\u9a8c\u8bc1\u7801\u4e0d\u80fd\u4e3a\u7a7a
+Email.format.err=\u90ae\u7bb1\u683c\u5f0f\u4e0d\u6b63\u786e
+

+ 3 - 0
qnfhq-api/src/main/resources/mapper/user/AppUserDao.xml

@@ -8,6 +8,7 @@
         <result property="loginName" column="login_name"/>
         <result property="loginPassword" column="login_password"/>
         <result property="phone" column="phone"/>
+        <result property="zone" column="zone"/>
         <result property="isTest" column="is_test"/>
         <result property="status" column="status"/>
         <result property="appParentIds" column="app_parent_ids"/>
@@ -27,6 +28,8 @@
         <result property="avatar" column="avatar"/>
         <result property="nickname" column="nickname"/>
         <result property="uid" column="uid"/>
+        <result property="transferOutTime" column="transfer_out_time"/>
+
     </resultMap>
 
 

+ 15 - 0
qnfhq-common/src/main/java/com/qnfhq/common/utils/DateUtils.java

@@ -2,6 +2,7 @@ package com.qnfhq.common.utils;
 
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.util.Calendar;
 import java.util.Date;
 
 /**
@@ -52,4 +53,18 @@ public class DateUtils {
         }
         return null;
     }
+
+
+    /**
+     * 日期加n天
+     * @param date
+     * @return
+     */
+    public static Date addDays(Date date,int n) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(Calendar.DAY_OF_YEAR, n);
+        return calendar.getTime();
+    }
+
 }