diff --git a/README.md b/README.md
index 7b47b2eb..9ea44b54 100644
--- a/README.md
+++ b/README.md
@@ -56,7 +56,7 @@
| 工具类框架 | Hutool、Lombok | [Hutool文档](https://www.hutool.cn/docs/) | 减少代码冗余 增加安全性 |
| 代码生成器 | 适配MP、Knife4j规范化代码 | [Hutool文档](https://www.hutool.cn/docs/) | 一键生成前后端代码 |
| 部署方式 | Docker | [Docker文档](https://docs.docker.com/) | 容器编排 一键部署业务集群 |
-| 国际化(未完成) | SpringMessage | [SpringMVC文档](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc) | Spring标准国际化方案 |
+| 国际化 | SpringMessage | [SpringMVC文档](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc) | Spring标准国际化方案 |
## 软件架构图
diff --git a/config/dev/application.yml b/config/dev/application.yml
index d33d9fe9..68a49b04 100644
--- a/config/dev/application.yml
+++ b/config/dev/application.yml
@@ -55,6 +55,10 @@ spring:
pathmatch:
# 适配 boot 2.6 路由与 springfox 兼容
matching-strategy: ANT_PATH_MATCHER
+ # 资源信息
+ messages:
+ # 国际化资源文件路径
+ basename: i18n/messages
servlet:
multipart:
# 整个请求大小限制
diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteUserService.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteUserService.java
index 6771b11c..42febe1f 100644
--- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteUserService.java
+++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteUserService.java
@@ -26,11 +26,4 @@ public interface RemoteUserService {
*/
Boolean registerUserInfo(SysUser sysUser);
- /**
- * 检查用户名是否唯一
- *
- * @param username 用户名
- * @return 结果
- */
- String checkUserNameUnique(String username);
}
diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/form/LoginBody.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/form/LoginBody.java
index 852aef62..c8770d45 100644
--- a/ruoyi-auth/src/main/java/com/ruoyi/auth/form/LoginBody.java
+++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/form/LoginBody.java
@@ -22,16 +22,16 @@ public class LoginBody {
/**
* 用户名
*/
- @NotBlank(message = "用户名不能为空")
- @Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "账户长度必须在2到20个字符之间")
+ @NotBlank(message = "{user.username.not.blank}")
+ @Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}")
@ApiModelProperty(value = "用户名")
private String username;
/**
* 用户密码
*/
- @NotBlank(message = "密码不能为空")
- @Length(min = UserConstants.PASSWORD_MIN_LENGTH, max = UserConstants.PASSWORD_MAX_LENGTH, message = "密码长度必须在5到20个字符之间")
+ @NotBlank(message = "{user.password.not.blank}")
+ @Length(min = UserConstants.PASSWORD_MIN_LENGTH, max = UserConstants.PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}")
@ApiModelProperty(value = "用户密码")
private String password;
diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java
index 043d9c49..6a00bf95 100644
--- a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java
+++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java
@@ -5,9 +5,10 @@ import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.auth.form.RegisterBody;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.Constants;
-import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.enums.UserType;
import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.exception.user.UserException;
+import com.ruoyi.common.core.utils.MessageUtils;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.utils.RedisUtils;
@@ -44,8 +45,8 @@ public class SysLoginService {
userInfo = remoteUserService.getUserInfo(username);
if (ObjectUtil.isNull(userInfo)) {
- recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
- throw new ServiceException("登录用户:" + username + " 不存在");
+ recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists", username));
+ throw new UserException("user.not.exists", username);
}
} catch (Exception e) {
recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage());
@@ -56,9 +57,8 @@ public class SysLoginService {
Integer errorNumber = RedisUtils.getCacheObject(CacheConstants.LOGIN_ERROR + username);
// 锁定时间内登录 则踢出
if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(CacheConstants.LOGIN_ERROR_NUMBER)) {
- String msg = "密码错误次数过多,帐户锁定" + CacheConstants.LOGIN_ERROR_LIMIT_TIME + "分钟";
- recordLogininfor(username, Constants.LOGIN_FAIL, msg);
- throw new ServiceException(msg, null);
+ recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", CacheConstants.LOGIN_ERROR_LIMIT_TIME));
+ throw new UserException("user.password.retry.limit.exceed", CacheConstants.LOGIN_ERROR_LIMIT_TIME);
}
if (!BCrypt.checkpw(password, userInfo.getPassword())) {
@@ -66,26 +66,24 @@ public class SysLoginService {
errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
// 达到规定错误次数 则锁定登录
if (errorNumber.equals(CacheConstants.LOGIN_ERROR_NUMBER)) {
- String msg = "密码错误次数过多,帐户锁定" + CacheConstants.LOGIN_ERROR_LIMIT_TIME + "分钟";
RedisUtils.setCacheObject(CacheConstants.LOGIN_ERROR + username, errorNumber, CacheConstants.LOGIN_ERROR_LIMIT_TIME, TimeUnit.MINUTES);
- recordLogininfor(username, Constants.LOGIN_FAIL, msg);
- throw new ServiceException(msg, null);
+ recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", CacheConstants.LOGIN_ERROR_LIMIT_TIME));
+ throw new UserException("user.password.retry.limit.exceed", CacheConstants.LOGIN_ERROR_LIMIT_TIME);
} else {
// 未达到规定错误次数 则递增
- String msg = "密码输入错误" + errorNumber + "次";
RedisUtils.setCacheObject(CacheConstants.LOGIN_ERROR + username, errorNumber);
- recordLogininfor(username, Constants.LOGIN_FAIL, msg);
- throw new ServiceException(msg, null);
+ recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.count", errorNumber));
+ throw new UserException("user.password.retry.limit.count", errorNumber);
}
}
// 登录成功 清空错误次数
RedisUtils.deleteObject(CacheConstants.LOGIN_ERROR + username);
- recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
+ recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
return userInfo;
}
public void logout(String loginName) {
- recordLogininfor(loginName, Constants.LOGOUT, "退出成功");
+ recordLogininfor(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success"));
}
/**
@@ -97,9 +95,6 @@ public class SysLoginService {
// 校验用户类型是否存在
String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
- if (UserConstants.NOT_UNIQUE.equals(remoteUserService.checkUserNameUnique(username))) {
- throw new ServiceException("保存用户 " + username + " 失败,注册账号已存在");
- }
// 注册用户信息
SysUser sysUser = new SysUser();
sysUser.setUserName(username);
@@ -108,9 +103,9 @@ public class SysLoginService {
sysUser.setUserType(userType);
boolean regFlag = remoteUserService.registerUserInfo(sysUser);
if (!regFlag) {
- throw new ServiceException("注册失败,请联系系统管理人员");
+ throw new UserException("user.register.error");
}
- recordLogininfor(username, Constants.REGISTER, "注册成功");
+ recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"));
}
/**
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/CaptchaException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/CaptchaException.java
index 961f6045..9cca4111 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/CaptchaException.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/CaptchaException.java
@@ -1,14 +1,18 @@
-package com.ruoyi.common.core.exception;
-
-/**
- * 验证码错误异常类
- *
- * @author ruoyi
- */
-public class CaptchaException extends RuntimeException {
- private static final long serialVersionUID = 1L;
-
- public CaptchaException(String msg) {
- super(msg);
- }
-}
+package com.ruoyi.common.core.exception;
+
+/**
+ * 验证码错误异常类
+ *
+ * @author Lion Li
+ */
+public class CaptchaException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public CaptchaException() {
+ super("user.jcaptcha.error");
+ }
+
+ public CaptchaException(String msg) {
+ super(msg);
+ }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java
index ba5b87fa..022366b6 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java
@@ -42,6 +42,7 @@ public final class ServiceException extends RuntimeException {
return detailMessage;
}
+ @Override
public String getMessage() {
return message;
}
@@ -59,4 +60,4 @@ public final class ServiceException extends RuntimeException {
this.detailMessage = detailMessage;
return this;
}
-}
\ No newline at end of file
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java
index 95c1becd..aa00f84b 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java
@@ -1,5 +1,7 @@
package com.ruoyi.common.core.exception.base;
+import com.ruoyi.common.core.utils.MessageUtils;
+import com.ruoyi.common.core.utils.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -49,4 +51,16 @@ public class BaseException extends RuntimeException {
this(null, null, null, defaultMessage);
}
+ @Override
+ public String getMessage() {
+ String message = null;
+ if (!StringUtils.isEmpty(code)) {
+ message = MessageUtils.message(code, args);
+ }
+ if (message == null) {
+ message = defaultMessage;
+ }
+ return message;
+ }
+
}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java
index a65c0564..561b1b63 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java
@@ -5,12 +5,12 @@ import com.ruoyi.common.core.exception.base.BaseException;
/**
* 用户信息异常类
*
- * @author ruoyi
+ * @author Lion Li
*/
public class UserException extends BaseException {
private static final long serialVersionUID = 1L;
- public UserException(String code, Object[] args) {
+ public UserException(String code, Object... args) {
super("user", code, args, null);
}
}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/MessageUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/MessageUtils.java
new file mode 100644
index 00000000..24928f88
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/MessageUtils.java
@@ -0,0 +1,28 @@
+package com.ruoyi.common.core.utils;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
+
+/**
+ * 获取i18n资源文件
+ *
+ * @author Lion Li
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class MessageUtils {
+
+ private static final MessageSource MESSAGE_SOURCE = SpringUtils.getBean(MessageSource.class);
+
+ /**
+ * 根据消息键和参数 获取消息 委托给spring messageSource
+ *
+ * @param code 消息键
+ * @param args 参数
+ * @return 获取国际化翻译值
+ */
+ public static String message(String code, Object... args) {
+ return MESSAGE_SOURCE.getMessage(code, args, LocaleContextHolder.getLocale());
+ }
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/I18nConfig.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/I18nConfig.java
new file mode 100644
index 00000000..2f4b1539
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/I18nConfig.java
@@ -0,0 +1,21 @@
+package com.ruoyi.common.web.config;
+
+import com.ruoyi.common.web.core.I18nLocaleResolver;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.LocaleResolver;
+
+/**
+ * 国际化配置
+ *
+ * @author Lion Li
+ */
+@Configuration
+public class I18nConfig {
+
+ @Bean
+ public LocaleResolver localeResolver() {
+ return new I18nLocaleResolver();
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/core/I18nLocaleResolver.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/core/I18nLocaleResolver.java
new file mode 100644
index 00000000..73fe5b0c
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/core/I18nLocaleResolver.java
@@ -0,0 +1,31 @@
+package com.ruoyi.common.web.core;
+
+import org.springframework.web.servlet.LocaleResolver;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Locale;
+
+/**
+ * 获取请求头国际化信息
+ *
+ * @author Lion Li
+ */
+public class I18nLocaleResolver implements LocaleResolver {
+
+ @Override
+ public Locale resolveLocale(HttpServletRequest httpServletRequest) {
+ String language = httpServletRequest.getHeader("content-language");
+ Locale locale = Locale.getDefault();
+ if (language != null && language.length() > 0) {
+ String[] split = language.split("_");
+ locale = new Locale(split[0], split[1]);
+ }
+ return locale;
+ }
+
+ @Override
+ public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
+
+ }
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/resources/META-INF/spring.factories b/ruoyi-common/ruoyi-common-web/src/main/resources/META-INF/spring.factories
index 485802b1..f6c18046 100644
--- a/ruoyi-common/ruoyi-common-web/src/main/resources/META-INF/spring.factories
+++ b/ruoyi-common/ruoyi-common-web/src/main/resources/META-INF/spring.factories
@@ -1 +1,2 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=
\ No newline at end of file
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ com.ruoyi.common.web.config.I18nConfig
diff --git a/ruoyi-common/ruoyi-common-web/src/main/resources/i18n/messages.properties b/ruoyi-common/ruoyi-common-web/src/main/resources/i18n/messages.properties
new file mode 100644
index 00000000..e0e65ce1
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/resources/i18n/messages.properties
@@ -0,0 +1,39 @@
+#错误消息
+not.null=* 必须填写
+user.jcaptcha.not.blank=验证码不能为空
+user.jcaptcha.error=验证码错误
+user.jcaptcha.expire=验证码已失效
+user.not.exists=对不起, 您的账号:{0} 不存在.
+user.password.not.match=用户不存在/密码错误
+user.password.retry.limit.count=密码输入错误{0}次
+user.password.retry.limit.exceed=密码错误次数过多,帐户锁定{0}分钟
+user.password.delete=对不起,您的账号:{0} 已被删除
+user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
+role.blocked=角色已封禁,请联系管理员
+user.logout.success=退出成功
+length.not.valid=长度必须在{min}到{max}个字符之间
+user.username.not.blank=用户名不能为空
+user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
+user.username.length.valid=账户长度必须在{min}到{max}个字符之间
+user.password.not.blank=用户密码不能为空
+user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
+user.password.not.valid=* 5-50个字符
+user.email.not.valid=邮箱格式错误
+user.mobile.phone.number.not.valid=手机号格式错误
+user.login.success=登录成功
+user.register.success=注册成功
+user.register.save.error=保存用户 {0} 失败,注册账号已存在
+user.register.error=注册失败,请联系系统管理人员
+user.notfound=请重新登录
+user.forcelogout=管理员强制退出,请重新登录
+user.unknown.error=未知错误,请重新登录
+##文件上传消息
+upload.exceed.maxSize=上传的文件大小超出限制的文件大小!
允许的文件最大大小是:{0}MB!
+upload.filename.exceed.length=上传的文件名最长{0}个字符
+##权限
+no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
+no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
+no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
+no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
+no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
+no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
diff --git a/ruoyi-common/ruoyi-common-web/src/main/resources/i18n/messages_en_US.properties b/ruoyi-common/ruoyi-common-web/src/main/resources/i18n/messages_en_US.properties
new file mode 100644
index 00000000..f113ca8b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/resources/i18n/messages_en_US.properties
@@ -0,0 +1,39 @@
+#错误消息
+not.null=* Required fill in
+user.jcaptcha.not.blank=Captcha cannot be blank
+user.jcaptcha.error=Captcha error
+user.jcaptcha.expire=Captcha invalid
+user.not.exists=Sorry, your account: {0} does not exist
+user.password.not.match=User does not exist/Password error
+user.password.retry.limit.count=Password input error {0} times
+user.password.retry.limit.exceed=Too many password errors, account locked for {0} minutes
+user.password.delete=Sorry, your account:{0} has been deleted
+user.blocked=Sorry, your account: {0} has been disabled. Please contact the administrator
+role.blocked=Role disabled,please contact administrators
+user.logout.success=Exit successful
+length.not.valid=The length must be between {min} and {max} characters
+user.username.not.blank=Username cannot be blank
+user.username.not.valid=* 2 to 20 chinese characters, letters, numbers or underscores, and must start with a non number
+user.username.length.valid=Account length must be between {min} and {max} characters
+user.password.not.blank=Password cannot be empty
+user.password.length.valid=Password length must be between {min} and {max} characters
+user.password.not.valid=* 5-50 characters
+user.email.not.valid=Mailbox format error
+user.mobile.phone.number.not.valid=Phone number format error
+user.login.success=Login successful
+user.register.success=Register successful
+user.register.save.error=Failed to save user {0}, The registered account already exists
+user.register.error=Register failed, please contact system administrator
+user.notfound=Please login again
+user.forcelogout=The administrator is forced to exit,please login again
+user.unknown.error=Unknown error, please login again
+##文件上传消息
+upload.exceed.maxSize=The uploaded file size exceeds the limit file size!
the maximum allowed file size is:{0}MB!
+upload.filename.exceed.length=The maximum length of uploaded file name is {0} characters
+##权限
+no.permission=You do not have permission to the data,please contact your administrator to add permissions [{0}]
+no.create.permission=You do not have permission to create data,please contact your administrator to add permissions [{0}]
+no.update.permission=You do not have permission to modify data,please contact your administrator to add permissions [{0}]
+no.delete.permission=You do not have permission to delete data,please contact your administrator to add permissions [{0}]
+no.export.permission=You do not have permission to export data,please contact your administrator to add permissions [{0}]
+no.view.permission=You do not have permission to view data,please contact your administrator to add permissions [{0}]
diff --git a/ruoyi-common/ruoyi-common-web/src/main/resources/i18n/messages_zh_CN.properties b/ruoyi-common/ruoyi-common-web/src/main/resources/i18n/messages_zh_CN.properties
new file mode 100644
index 00000000..e0e65ce1
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/resources/i18n/messages_zh_CN.properties
@@ -0,0 +1,39 @@
+#错误消息
+not.null=* 必须填写
+user.jcaptcha.not.blank=验证码不能为空
+user.jcaptcha.error=验证码错误
+user.jcaptcha.expire=验证码已失效
+user.not.exists=对不起, 您的账号:{0} 不存在.
+user.password.not.match=用户不存在/密码错误
+user.password.retry.limit.count=密码输入错误{0}次
+user.password.retry.limit.exceed=密码错误次数过多,帐户锁定{0}分钟
+user.password.delete=对不起,您的账号:{0} 已被删除
+user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
+role.blocked=角色已封禁,请联系管理员
+user.logout.success=退出成功
+length.not.valid=长度必须在{min}到{max}个字符之间
+user.username.not.blank=用户名不能为空
+user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
+user.username.length.valid=账户长度必须在{min}到{max}个字符之间
+user.password.not.blank=用户密码不能为空
+user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
+user.password.not.valid=* 5-50个字符
+user.email.not.valid=邮箱格式错误
+user.mobile.phone.number.not.valid=手机号格式错误
+user.login.success=登录成功
+user.register.success=注册成功
+user.register.save.error=保存用户 {0} 失败,注册账号已存在
+user.register.error=注册失败,请联系系统管理人员
+user.notfound=请重新登录
+user.forcelogout=管理员强制退出,请重新登录
+user.unknown.error=未知错误,请重新登录
+##文件上传消息
+upload.exceed.maxSize=上传的文件大小超出限制的文件大小!
允许的文件最大大小是:{0}MB!
+upload.filename.exceed.length=上传的文件名最长{0}个字符
+##权限
+no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
+no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
+no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
+no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
+no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
+no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java
index 7b31a612..a770bed2 100644
--- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java
+++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java
@@ -7,6 +7,7 @@ import cn.hutool.core.util.IdUtil;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.CaptchaException;
+import com.ruoyi.common.core.exception.user.CaptchaExpireException;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.reflect.ReflectUtils;
@@ -85,17 +86,17 @@ public class ValidateCodeServiceImpl implements ValidateCodeService {
@Override
public void checkCaptcha(String code, String uuid) throws CaptchaException {
if (StringUtils.isEmpty(code)) {
- throw new CaptchaException("验证码不能为空");
+ throw new CaptchaException("user.jcaptcha.not.blank");
}
if (StringUtils.isEmpty(uuid)) {
- throw new CaptchaException("验证码已失效");
+ throw new CaptchaExpireException();
}
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
String captcha = RedisUtils.getCacheObject(verifyKey);
RedisUtils.deleteObject(verifyKey);
if (!code.equalsIgnoreCase(captcha)) {
- throw new CaptchaException("验证码错误");
+ throw new CaptchaException();
}
}
}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/dubbo/RemoteUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/dubbo/RemoteUserServiceImpl.java
index 5a0fa081..950bdc0c 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/dubbo/RemoteUserServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/dubbo/RemoteUserServiceImpl.java
@@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.enums.UserStatus;
import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.exception.user.UserException;
import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser;
@@ -37,13 +38,13 @@ public class RemoteUserServiceImpl implements RemoteUserService {
public LoginUser getUserInfo(String username) {
SysUser sysUser = userService.selectUserByUserName(username);
if (ObjectUtil.isNull(sysUser)) {
- throw new ServiceException("用户名或密码错误");
+ throw new UserException("user.not.exists", username);
}
if (UserStatus.DELETED.getCode().equals(sysUser.getDelFlag())) {
- throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
+ throw new UserException("user.password.delete", username);
}
if (UserStatus.DISABLE.getCode().equals(sysUser.getStatus())) {
- throw new ServiceException("对不起,您的账号:" + username + " 已停用");
+ throw new UserException("user.blocked", username);
}
// 角色集合
Set rolePermission = permissionService.getRolePermission(sysUser.getUserId());
@@ -70,13 +71,9 @@ public class RemoteUserServiceImpl implements RemoteUserService {
throw new ServiceException("当前系统没有开启注册功能");
}
if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username))) {
- throw new ServiceException("保存用户'" + username + "'失败,注册账号已存在");
+ throw new UserException("user.register.save.error", username);
}
return userService.registerUser(sysUser);
}
- @Override
- public String checkUserNameUnique(String username) {
- return userService.checkUserNameUnique(username);
- }
}
diff --git a/ruoyi-ui/src/utils/request.js b/ruoyi-ui/src/utils/request.js
index 925732ff..dd83fb92 100644
--- a/ruoyi-ui/src/utils/request.js
+++ b/ruoyi-ui/src/utils/request.js
@@ -1,161 +1,163 @@
-import axios from 'axios'
-import { Notification, MessageBox, Message, Loading } from 'element-ui'
-import store from '@/store'
-import { getToken } from '@/utils/auth'
-import errorCode from '@/utils/errorCode'
-import { tansParams, blobValidate } from "@/utils/ruoyi";
-import cache from '@/plugins/cache'
-import { saveAs } from 'file-saver'
-
-let downloadLoadingInstance;
-// 是否显示重新登录
-let isReloginShow;
-
-axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
-// 创建axios实例
-const service = axios.create({
- // axios中请求配置有baseURL选项,表示请求URL公共部分
- baseURL: process.env.VUE_APP_BASE_API,
- // 超时
- timeout: 10000
-})
-
-// request拦截器
-service.interceptors.request.use(config => {
- // 是否需要设置 token
- const isToken = (config.headers || {}).isToken === false
- // 是否需要防止数据重复提交
- const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
- if (getToken() && !isToken) {
- config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
- }
- // get请求映射params参数
- if (config.method === 'get' && config.params) {
- let url = config.url + '?' + tansParams(config.params);
- url = url.slice(0, -1);
- config.params = {};
- config.url = url;
- }
- if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
- const requestObj = {
- url: config.url,
- data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
- time: new Date().getTime()
- }
- const sessionObj = cache.session.getJSON('sessionObj')
- if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
- cache.session.setJSON('sessionObj', requestObj)
- } else {
- const s_url = sessionObj.url; // 请求地址
- const s_data = sessionObj.data; // 请求数据
- const s_time = sessionObj.time; // 请求时间
- const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
- if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
- const message = '数据正在处理,请勿重复提交';
- console.warn(`[${s_url}]: ` + message)
- return Promise.reject(new Error(message))
- } else {
- cache.session.setJSON('sessionObj', requestObj)
- }
- }
- }
- return config
-}, error => {
- console.log(error)
- Promise.reject(error)
-})
-
-// 响应拦截器
-service.interceptors.response.use(res => {
- // 未设置状态码则默认成功状态
- const code = res.data.code || 200;
- // 获取错误信息
- const msg = errorCode[code] || res.data.msg || errorCode['default']
- // 二进制数据则直接返回
- if(res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer'){
- return res.data
- }
- if (code === 401) {
- if (!isReloginShow) {
- isReloginShow = true;
- MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
- confirmButtonText: '重新登录',
- cancelButtonText: '取消',
- type: 'warning'
- }
- ).then(() => {
- isReloginShow = false;
- store.dispatch('LogOut').then(() => {
- // 如果是登录页面不需要重新加载
- if (window.location.hash.indexOf("#/login") != 0) {
- location.href = '/index';
- }
- })
- }).catch(() => {
- isReloginShow = false;
- });
- }
- return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
- } else if (code === 500) {
- Message({
- message: msg,
- type: 'error'
- })
- return Promise.reject(new Error(msg))
- } else if (code !== 200) {
- Notification.error({
- title: msg
- })
- return Promise.reject('error')
- } else {
- return res.data
- }
- },
- error => {
- console.log('err' + error)
- let { message } = error;
- if (message == "Network Error") {
- message = "后端接口连接异常";
- }
- else if (message.includes("timeout")) {
- message = "系统接口请求超时";
- }
- else if (message.includes("Request failed with status code")) {
- message = "系统接口" + message.substr(message.length - 3) + "异常";
- }
- Message({
- message: message,
- type: 'error',
- duration: 5 * 1000
- })
- return Promise.reject(error)
- }
-)
-
-// 通用下载方法
-export function download(url, params, filename) {
- downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
- return service.post(url, params, {
- transformRequest: [(params) => { return tansParams(params) }],
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
- responseType: 'blob'
- }).then(async (data) => {
- const isLogin = await blobValidate(data);
- if (isLogin) {
- const blob = new Blob([data])
- saveAs(blob, filename)
- } else {
- const resText = await data.text();
- const rspObj = JSON.parse(resText);
- const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
- Message.error(errMsg);
- }
- downloadLoadingInstance.close();
- }).catch((r) => {
- console.error(r)
- Message.error('下载文件出现错误,请联系管理员!')
- downloadLoadingInstance.close();
- })
-}
-
-export default service
+import axios from 'axios'
+import { Notification, MessageBox, Message, Loading } from 'element-ui'
+import store from '@/store'
+import { getToken } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
+import { tansParams, blobValidate } from "@/utils/ruoyi";
+import cache from '@/plugins/cache'
+import { saveAs } from 'file-saver'
+
+let downloadLoadingInstance;
+// 是否显示重新登录
+let isReloginShow;
+
+axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
+// 对应国际化资源文件后缀
+axios.defaults.headers['Content-Language'] = 'zh_CN'
+// 创建axios实例
+const service = axios.create({
+ // axios中请求配置有baseURL选项,表示请求URL公共部分
+ baseURL: process.env.VUE_APP_BASE_API,
+ // 超时
+ timeout: 10000
+})
+
+// request拦截器
+service.interceptors.request.use(config => {
+ // 是否需要设置 token
+ const isToken = (config.headers || {}).isToken === false
+ // 是否需要防止数据重复提交
+ const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
+ if (getToken() && !isToken) {
+ config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
+ }
+ // get请求映射params参数
+ if (config.method === 'get' && config.params) {
+ let url = config.url + '?' + tansParams(config.params);
+ url = url.slice(0, -1);
+ config.params = {};
+ config.url = url;
+ }
+ if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
+ const requestObj = {
+ url: config.url,
+ data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
+ time: new Date().getTime()
+ }
+ const sessionObj = cache.session.getJSON('sessionObj')
+ if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
+ cache.session.setJSON('sessionObj', requestObj)
+ } else {
+ const s_url = sessionObj.url; // 请求地址
+ const s_data = sessionObj.data; // 请求数据
+ const s_time = sessionObj.time; // 请求时间
+ const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
+ if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
+ const message = '数据正在处理,请勿重复提交';
+ console.warn(`[${s_url}]: ` + message)
+ return Promise.reject(new Error(message))
+ } else {
+ cache.session.setJSON('sessionObj', requestObj)
+ }
+ }
+ }
+ return config
+}, error => {
+ console.log(error)
+ Promise.reject(error)
+})
+
+// 响应拦截器
+service.interceptors.response.use(res => {
+ // 未设置状态码则默认成功状态
+ const code = res.data.code || 200;
+ // 获取错误信息
+ const msg = errorCode[code] || res.data.msg || errorCode['default']
+ // 二进制数据则直接返回
+ if(res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer'){
+ return res.data
+ }
+ if (code === 401) {
+ if (!isReloginShow) {
+ isReloginShow = true;
+ MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
+ confirmButtonText: '重新登录',
+ cancelButtonText: '取消',
+ type: 'warning'
+ }
+ ).then(() => {
+ isReloginShow = false;
+ store.dispatch('LogOut').then(() => {
+ // 如果是登录页面不需要重新加载
+ if (window.location.hash.indexOf("#/login") != 0) {
+ location.href = '/index';
+ }
+ })
+ }).catch(() => {
+ isReloginShow = false;
+ });
+ }
+ return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
+ } else if (code === 500) {
+ Message({
+ message: msg,
+ type: 'error'
+ })
+ return Promise.reject(new Error(msg))
+ } else if (code !== 200) {
+ Notification.error({
+ title: msg
+ })
+ return Promise.reject('error')
+ } else {
+ return res.data
+ }
+ },
+ error => {
+ console.log('err' + error)
+ let { message } = error;
+ if (message == "Network Error") {
+ message = "后端接口连接异常";
+ }
+ else if (message.includes("timeout")) {
+ message = "系统接口请求超时";
+ }
+ else if (message.includes("Request failed with status code")) {
+ message = "系统接口" + message.substr(message.length - 3) + "异常";
+ }
+ Message({
+ message: message,
+ type: 'error',
+ duration: 5 * 1000
+ })
+ return Promise.reject(error)
+ }
+)
+
+// 通用下载方法
+export function download(url, params, filename) {
+ downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
+ return service.post(url, params, {
+ transformRequest: [(params) => { return tansParams(params) }],
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+ responseType: 'blob'
+ }).then(async (data) => {
+ const isLogin = await blobValidate(data);
+ if (isLogin) {
+ const blob = new Blob([data])
+ saveAs(blob, filename)
+ } else {
+ const resText = await data.text();
+ const rspObj = JSON.parse(resText);
+ const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
+ Message.error(errMsg);
+ }
+ downloadLoadingInstance.close();
+ }).catch((r) => {
+ console.error(r)
+ Message.error('下载文件出现错误,请联系管理员!')
+ downloadLoadingInstance.close();
+ })
+}
+
+export default service
diff --git a/ruoyi-ui/src/views/register.vue b/ruoyi-ui/src/views/register.vue
index 5bda9892..266e2c2d 100644
--- a/ruoyi-ui/src/views/register.vue
+++ b/ruoyi-ui/src/views/register.vue
@@ -1,209 +1,210 @@
-
-
-
- 若依后台管理系统
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
![]()
-
-
-
-
- 注 册
- 注 册 中...
-
-
- 使用已有账户登录
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ 若依后台管理系统
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+ 注 册
+ 注 册 中...
+
+
+ 使用已有账户登录
+
+
+
+
+
+
+
+
+
+
+