ret) {
+ return Result.SUCCESS == ret.getCode();
+ }
+
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/enums/UserStatus.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/enums/UserStatus.java
new file mode 100644
index 0000000..372edf3
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/enums/UserStatus.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.core.enums;
+
+/**
+ * 用户状态
+ *
+ * @author muyu
+ */
+public enum UserStatus {
+ OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
+
+ private final String code;
+ private final String info;
+
+ UserStatus (String code, String info) {
+ this.code = code;
+ this.info = info;
+ }
+
+ public String getCode () {
+ return code;
+ }
+
+ public String getInfo () {
+ return info;
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/CaptchaException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/CaptchaException.java
new file mode 100644
index 0000000..e7ffa41
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/CaptchaException.java
@@ -0,0 +1,14 @@
+package com.ruoyi.common.core.exception;
+
+/**
+ * 验证码错误异常类
+ *
+ * @author muyu
+ */
+public class CaptchaException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public CaptchaException (String msg) {
+ super(msg);
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/CheckedException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/CheckedException.java
new file mode 100644
index 0000000..a3a1804
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/CheckedException.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.core.exception;
+
+/**
+ * 检查异常
+ *
+ * @author muyu
+ */
+public class CheckedException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public CheckedException (String message) {
+ super(message);
+ }
+
+ public CheckedException (Throwable cause) {
+ super(cause);
+ }
+
+ public CheckedException (String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public CheckedException (String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/DemoModeException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/DemoModeException.java
new file mode 100644
index 0000000..fba3799
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/DemoModeException.java
@@ -0,0 +1,13 @@
+package com.ruoyi.common.core.exception;
+
+/**
+ * 演示模式异常
+ *
+ * @author muyu
+ */
+public class DemoModeException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public DemoModeException () {
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/GlobalException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/GlobalException.java
new file mode 100644
index 0000000..48e0e53
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/GlobalException.java
@@ -0,0 +1,51 @@
+package com.ruoyi.common.core.exception;
+
+/**
+ * 全局异常
+ *
+ * @author muyu
+ */
+public class GlobalException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 错误提示
+ */
+ private String message;
+
+ /**
+ * 错误明细,内部调试错误
+ *
+ * 和 {@link CommonResult#getDetailMessage()} 一致的设计
+ */
+ private String detailMessage;
+
+ /**
+ * 空构造方法,避免反序列化问题
+ */
+ public GlobalException () {
+ }
+
+ public GlobalException (String message) {
+ this.message = message;
+ }
+
+ public String getDetailMessage () {
+ return detailMessage;
+ }
+
+ public GlobalException setDetailMessage (String detailMessage) {
+ this.detailMessage = detailMessage;
+ return this;
+ }
+
+ @Override
+ public String getMessage () {
+ return message;
+ }
+
+ public GlobalException setMessage (String message) {
+ this.message = message;
+ return this;
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/InnerAuthException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/InnerAuthException.java
new file mode 100644
index 0000000..ef166c1
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/InnerAuthException.java
@@ -0,0 +1,14 @@
+package com.ruoyi.common.core.exception;
+
+/**
+ * 内部认证异常
+ *
+ * @author muyu
+ */
+public class InnerAuthException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public InnerAuthException (String message) {
+ super(message);
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/PreAuthorizeException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/PreAuthorizeException.java
new file mode 100644
index 0000000..7dd9818
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/PreAuthorizeException.java
@@ -0,0 +1,13 @@
+package com.ruoyi.common.core.exception;
+
+/**
+ * 权限异常
+ *
+ * @author muyu
+ */
+public class PreAuthorizeException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public PreAuthorizeException () {
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java
new file mode 100644
index 0000000..e965736
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java
@@ -0,0 +1,65 @@
+package com.ruoyi.common.core.exception;
+
+/**
+ * 业务异常
+ *
+ * @author muyu
+ */
+public final class ServiceException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 错误码
+ */
+ private Integer code;
+
+ /**
+ * 错误提示
+ */
+ private String message;
+
+ /**
+ * 错误明细,内部调试错误
+ *
+ * 和 {@link CommonResult#getDetailMessage()} 一致的设计
+ */
+ private String detailMessage;
+
+ /**
+ * 空构造方法,避免反序列化问题
+ */
+ public ServiceException () {
+ }
+
+ public ServiceException (String message) {
+ this.message = message;
+ }
+
+ public ServiceException (String message, Integer code) {
+ this.message = message;
+ this.code = code;
+ }
+
+ public String getDetailMessage () {
+ return detailMessage;
+ }
+
+ public ServiceException setDetailMessage (String detailMessage) {
+ this.detailMessage = detailMessage;
+ return this;
+ }
+
+ @Override
+ public String getMessage () {
+ return message;
+ }
+
+ public ServiceException setMessage (String message) {
+ this.message = message;
+ return this;
+ }
+
+ public Integer getCode () {
+ return code;
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/UtilException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/UtilException.java
new file mode 100644
index 0000000..b1b8b79
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/UtilException.java
@@ -0,0 +1,22 @@
+package com.ruoyi.common.core.exception;
+
+/**
+ * 工具类异常
+ *
+ * @author muyu
+ */
+public class UtilException extends RuntimeException {
+ private static final long serialVersionUID = 8247610319171014183L;
+
+ public UtilException (Throwable e) {
+ super(e.getMessage(), e);
+ }
+
+ public UtilException (String message) {
+ super(message);
+ }
+
+ public UtilException (String message, Throwable throwable) {
+ super(message, throwable);
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotLoginException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotLoginException.java
new file mode 100644
index 0000000..b7bb2e6
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotLoginException.java
@@ -0,0 +1,14 @@
+package com.ruoyi.common.core.exception.auth;
+
+/**
+ * 未能通过的登录认证异常
+ *
+ * @author muyu
+ */
+public class NotLoginException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public NotLoginException (String message) {
+ super(message);
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotPermissionException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotPermissionException.java
new file mode 100644
index 0000000..d530c3f
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotPermissionException.java
@@ -0,0 +1,20 @@
+package com.ruoyi.common.core.exception.auth;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 未能通过的权限认证异常
+ *
+ * @author muyu
+ */
+public class NotPermissionException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public NotPermissionException (String permission) {
+ super(permission);
+ }
+
+ public NotPermissionException (String[] permissions) {
+ super(StringUtils.join(permissions, ","));
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotRoleException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotRoleException.java
new file mode 100644
index 0000000..20c7b99
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/auth/NotRoleException.java
@@ -0,0 +1,20 @@
+package com.ruoyi.common.core.exception.auth;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 未能通过的角色认证异常
+ *
+ * @author muyu
+ */
+public class NotRoleException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public NotRoleException (String role) {
+ super(role);
+ }
+
+ public NotRoleException (String[] roles) {
+ super(StringUtils.join(roles, ","));
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java
new file mode 100644
index 0000000..23d0485
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java
@@ -0,0 +1,69 @@
+package com.ruoyi.common.core.exception.base;
+
+/**
+ * 基础异常
+ *
+ * @author muyu
+ */
+public class BaseException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 所属模块
+ */
+ private String module;
+
+ /**
+ * 错误码
+ */
+ private String code;
+
+ /**
+ * 错误码对应的参数
+ */
+ private Object[] args;
+
+ /**
+ * 错误消息
+ */
+ private String defaultMessage;
+
+ public BaseException (String module, String code, Object[] args, String defaultMessage) {
+ this.module = module;
+ this.code = code;
+ this.args = args;
+ this.defaultMessage = defaultMessage;
+ }
+
+ public BaseException (String module, String code, Object[] args) {
+ this(module, code, args, null);
+ }
+
+ public BaseException (String module, String defaultMessage) {
+ this(module, null, null, defaultMessage);
+ }
+
+ public BaseException (String code, Object[] args) {
+ this(null, code, args, null);
+ }
+
+ public BaseException (String defaultMessage) {
+ this(null, null, null, defaultMessage);
+ }
+
+ public String getModule () {
+ return module;
+ }
+
+ public String getCode () {
+ return code;
+ }
+
+ public Object[] getArgs () {
+ return args;
+ }
+
+ public String getDefaultMessage () {
+ return defaultMessage;
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileException.java
new file mode 100644
index 0000000..416e3f0
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileException.java
@@ -0,0 +1,17 @@
+package com.ruoyi.common.core.exception.file;
+
+import com.ruoyi.common.core.exception.base.BaseException;
+
+/**
+ * 文件信息异常类
+ *
+ * @author muyu
+ */
+public class FileException extends BaseException {
+ private static final long serialVersionUID = 1L;
+
+ public FileException (String code, Object[] args, String msg) {
+ super("file", code, args, msg);
+ }
+
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileNameLengthLimitExceededException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileNameLengthLimitExceededException.java
new file mode 100644
index 0000000..cbca03d
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileNameLengthLimitExceededException.java
@@ -0,0 +1,14 @@
+package com.ruoyi.common.core.exception.file;
+
+/**
+ * 文件名称超长限制异常类
+ *
+ * @author muyu
+ */
+public class FileNameLengthLimitExceededException extends FileException {
+ private static final long serialVersionUID = 1L;
+
+ public FileNameLengthLimitExceededException (int defaultFileNameLength) {
+ super("upload.filename.exceed.length", new Object[]{defaultFileNameLength}, "the filename is too long");
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileSizeLimitExceededException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileSizeLimitExceededException.java
new file mode 100644
index 0000000..5655ecc
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileSizeLimitExceededException.java
@@ -0,0 +1,14 @@
+package com.ruoyi.common.core.exception.file;
+
+/**
+ * 文件名大小限制异常类
+ *
+ * @author muyu
+ */
+public class FileSizeLimitExceededException extends FileException {
+ private static final long serialVersionUID = 1L;
+
+ public FileSizeLimitExceededException (long defaultMaxSize) {
+ super("upload.exceed.maxSize", new Object[]{defaultMaxSize}, "the filesize is too large");
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileUploadException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileUploadException.java
new file mode 100644
index 0000000..d83f47a
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileUploadException.java
@@ -0,0 +1,52 @@
+package com.ruoyi.common.core.exception.file;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * 文件上传异常类
+ *
+ * @author muyu
+ */
+public class FileUploadException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ private final Throwable cause;
+
+ public FileUploadException () {
+ this(null, null);
+ }
+
+ public FileUploadException (final String msg) {
+ this(msg, null);
+ }
+
+ public FileUploadException (String msg, Throwable cause) {
+ super(msg);
+ this.cause = cause;
+ }
+
+ @Override
+ public void printStackTrace (PrintStream stream) {
+ super.printStackTrace(stream);
+ if (cause != null) {
+ stream.println("Caused by:");
+ cause.printStackTrace(stream);
+ }
+ }
+
+ @Override
+ public void printStackTrace (PrintWriter writer) {
+ super.printStackTrace(writer);
+ if (cause != null) {
+ writer.println("Caused by:");
+ cause.printStackTrace(writer);
+ }
+ }
+
+ @Override
+ public Throwable getCause () {
+ return cause;
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/InvalidExtensionException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/InvalidExtensionException.java
new file mode 100644
index 0000000..2191518
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/file/InvalidExtensionException.java
@@ -0,0 +1,67 @@
+package com.ruoyi.common.core.exception.file;
+
+import java.util.Arrays;
+
+/**
+ * 文件上传 误异常类
+ *
+ * @author muyu
+ */
+public class InvalidExtensionException extends FileUploadException {
+ private static final long serialVersionUID = 1L;
+
+ private String[] allowedExtension;
+ private String extension;
+ private String filename;
+
+ public InvalidExtensionException (String[] allowedExtension, String extension, String filename) {
+ super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]");
+ this.allowedExtension = allowedExtension;
+ this.extension = extension;
+ this.filename = filename;
+ }
+
+ public String[] getAllowedExtension () {
+ return allowedExtension;
+ }
+
+ public String getExtension () {
+ return extension;
+ }
+
+ public String getFilename () {
+ return filename;
+ }
+
+ public static class InvalidImageExtensionException extends InvalidExtensionException {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidImageExtensionException (String[] allowedExtension, String extension, String filename) {
+ super(allowedExtension, extension, filename);
+ }
+ }
+
+ public static class InvalidFlashExtensionException extends InvalidExtensionException {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidFlashExtensionException (String[] allowedExtension, String extension, String filename) {
+ super(allowedExtension, extension, filename);
+ }
+ }
+
+ public static class InvalidMediaExtensionException extends InvalidExtensionException {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidMediaExtensionException (String[] allowedExtension, String extension, String filename) {
+ super(allowedExtension, extension, filename);
+ }
+ }
+
+ public static class InvalidVideoExtensionException extends InvalidExtensionException {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidVideoExtensionException (String[] allowedExtension, String extension, String filename) {
+ super(allowedExtension, extension, filename);
+ }
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/job/TaskException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/job/TaskException.java
new file mode 100644
index 0000000..812f167
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/job/TaskException.java
@@ -0,0 +1,29 @@
+package com.ruoyi.common.core.exception.job;
+
+/**
+ * 计划策略异常
+ *
+ * @author muyu
+ */
+public class TaskException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ private Code code;
+
+ public TaskException (String msg, Code code) {
+ this(msg, code, null);
+ }
+
+ public TaskException (String msg, Code code, Exception nestedEx) {
+ super(msg, nestedEx);
+ this.code = code;
+ }
+
+ public Code getCode () {
+ return code;
+ }
+
+ public enum Code {
+ TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaExpireException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaExpireException.java
new file mode 100644
index 0000000..0c77614
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaExpireException.java
@@ -0,0 +1,14 @@
+package com.ruoyi.common.core.exception.user;
+
+/**
+ * 验证码失效异常类
+ *
+ * @author muyu
+ */
+public class CaptchaExpireException extends UserException {
+ private static final long serialVersionUID = 1L;
+
+ public CaptchaExpireException () {
+ super("user.jcaptcha.expire", null);
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java
new file mode 100644
index 0000000..9f966df
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.core.exception.user;
+
+import com.ruoyi.common.core.exception.base.BaseException;
+
+/**
+ * 用户信息异常类
+ *
+ * @author muyu
+ */
+public class UserException extends BaseException {
+ private static final long serialVersionUID = 1L;
+
+ public UserException (String code, Object[] args) {
+ super("user", code, args, null);
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordNotMatchException.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordNotMatchException.java
new file mode 100644
index 0000000..66dbe2b
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordNotMatchException.java
@@ -0,0 +1,14 @@
+package com.ruoyi.common.core.exception.user;
+
+/**
+ * 用户密码不正确或不符合规范异常类
+ *
+ * @author muyu
+ */
+public class UserPasswordNotMatchException extends UserException {
+ private static final long serialVersionUID = 1L;
+
+ public UserPasswordNotMatchException () {
+ super("user.password.not.match", null);
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/text/CharsetKit.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/text/CharsetKit.java
new file mode 100644
index 0000000..d3d18c5
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/text/CharsetKit.java
@@ -0,0 +1,94 @@
+package com.ruoyi.common.core.text;
+
+import com.ruoyi.common.core.utils.StringUtils;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 字符集工具类
+ *
+ * @author muyu
+ */
+public class CharsetKit {
+ /**
+ * ISO-8859-1
+ */
+ public static final String ISO_8859_1 = "ISO-8859-1";
+ /**
+ * UTF-8
+ */
+ public static final String UTF_8 = "UTF-8";
+ /**
+ * GBK
+ */
+ public static final String GBK = "GBK";
+
+ /**
+ * ISO-8859-1
+ */
+ public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
+ /**
+ * UTF-8
+ */
+ public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
+ /**
+ * GBK
+ */
+ public static final Charset CHARSET_GBK = Charset.forName(GBK);
+
+ /**
+ * 转换为Charset对象
+ *
+ * @param charset 字符集,为空则返回默认字符集
+ *
+ * @return Charset
+ */
+ public static Charset charset (String charset) {
+ return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
+ }
+
+ /**
+ * 转换字符串的字符集编码
+ *
+ * @param source 字符串
+ * @param srcCharset 源字符集,默认ISO-8859-1
+ * @param destCharset 目标字符集,默认UTF-8
+ *
+ * @return 转换后的字符集
+ */
+ public static String convert (String source, String srcCharset, String destCharset) {
+ return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
+ }
+
+ /**
+ * 转换字符串的字符集编码
+ *
+ * @param source 字符串
+ * @param srcCharset 源字符集,默认ISO-8859-1
+ * @param destCharset 目标字符集,默认UTF-8
+ *
+ * @return 转换后的字符集
+ */
+ public static String convert (String source, Charset srcCharset, Charset destCharset) {
+ if (null == srcCharset) {
+ srcCharset = StandardCharsets.ISO_8859_1;
+ }
+
+ if (null == destCharset) {
+ destCharset = StandardCharsets.UTF_8;
+ }
+
+ if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) {
+ return source;
+ }
+ return new String(source.getBytes(srcCharset), destCharset);
+ }
+
+ /**
+ * @return 系统字符集编码
+ */
+ public static String systemCharset () {
+ return Charset.defaultCharset().name();
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/text/Convert.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/text/Convert.java
new file mode 100644
index 0000000..552d65d
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/text/Convert.java
@@ -0,0 +1,903 @@
+package com.ruoyi.common.core.text;
+
+import com.ruoyi.common.core.utils.StringUtils;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.util.Set;
+
+/**
+ * 类型转换器
+ *
+ * @author muyu
+ */
+public class Convert {
+ /**
+ * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ *
+ * @return 结果
+ */
+ public static String toStr (Object value, String defaultValue) {
+ if (null == value) {
+ return defaultValue;
+ }
+ if (value instanceof String) {
+ return (String) value;
+ }
+ return value.toString();
+ }
+
+ /**
+ * 转换为字符串
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ *
+ * @return 结果
+ */
+ public static String toStr (Object value) {
+ return toStr(value, null);
+ }
+
+ /**
+ * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ *
+ * @return 结果
+ */
+ public static Character toChar (Object value, Character defaultValue) {
+ if (null == value) {
+ return defaultValue;
+ }
+ if (value instanceof Character) {
+ return (Character) value;
+ }
+
+ final String valueStr = toStr(value, null);
+ return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
+ }
+
+ /**
+ * 转换为字符
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ *
+ * @return 结果
+ */
+ public static Character toChar (Object value) {
+ return toChar(value, null);
+ }
+
+ /**
+ * 转换为byte
+ * 如果给定的值为null
,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ *
+ * @return 结果
+ */
+ public static Byte toByte (Object value, Byte defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Byte) {
+ return (Byte) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).byteValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return Byte.parseByte(valueStr);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为byte
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ *
+ * @return 结果
+ */
+ public static Byte toByte (Object value) {
+ return toByte(value, null);
+ }
+
+ /**
+ * 转换为Short
+ * 如果给定的值为null
,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ *
+ * @return 结果
+ */
+ public static Short toShort (Object value, Short defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Short) {
+ return (Short) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).shortValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return Short.parseShort(valueStr.trim());
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为Short
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ *
+ * @return 结果
+ */
+ public static Short toShort (Object value) {
+ return toShort(value, null);
+ }
+
+ /**
+ * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ *
+ * @return 结果
+ */
+ public static Number toNumber (Object value, Number defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Number) {
+ return (Number) value;
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return NumberFormat.getInstance().parse(valueStr);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ *
+ * @return 结果
+ */
+ public static Number toNumber (Object value) {
+ return toNumber(value, null);
+ }
+
+ /**
+ * 转换为int
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ *
+ * @return 结果
+ */
+ public static Integer toInt (Object value, Integer defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Integer) {
+ return (Integer) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).intValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return Integer.parseInt(valueStr.trim());
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为int
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ *
+ * @return 结果
+ */
+ public static Integer toInt (Object value) {
+ return toInt(value, null);
+ }
+
+ /**
+ * 转换为Integer数组
+ *
+ * @param str 被转换的值
+ *
+ * @return 结果
+ */
+ public static Integer[] toIntArray (String str) {
+ return toIntArray(",", str);
+ }
+
+ /**
+ * 转换为Long数组
+ *
+ * @param str 被转换的值
+ *
+ * @return 结果
+ */
+ public static Long[] toLongArray (String str) {
+ return toLongArray(",", str);
+ }
+
+ /**
+ * 转换为Integer数组
+ *
+ * @param split 分隔符
+ * @param str 被转换的值
+ *
+ * @return 结果
+ */
+ public static Integer[] toIntArray (String split, String str) {
+ if (StringUtils.isEmpty(str)) {
+ return new Integer[]{};
+ }
+ String[] arr = str.split(split);
+ final Integer[] ints = new Integer[arr.length];
+ for (int i = 0 ; i < arr.length ; i++) {
+ final Integer v = toInt(arr[i], 0);
+ ints[i] = v;
+ }
+ return ints;
+ }
+
+ /**
+ * 转换为Long数组
+ *
+ * @param split 分隔符
+ * @param str 被转换的值
+ *
+ * @return 结果
+ */
+ public static Long[] toLongArray (String split, String str) {
+ if (StringUtils.isEmpty(str)) {
+ return new Long[]{};
+ }
+ String[] arr = str.split(split);
+ final Long[] longs = new Long[arr.length];
+ for (int i = 0 ; i < arr.length ; i++) {
+ final Long v = toLong(arr[i], null);
+ longs[i] = v;
+ }
+ return longs;
+ }
+
+ /**
+ * 转换为String数组
+ *
+ * @param str 被转换的值
+ *
+ * @return 结果
+ */
+ public static String[] toStrArray (String str) {
+ return toStrArray(",", str);
+ }
+
+ /**
+ * 转换为String数组
+ *
+ * @param split 分隔符
+ * @param str 被转换的值
+ *
+ * @return 结果
+ */
+ public static String[] toStrArray (String split, String str) {
+ return str.split(split);
+ }
+
+ /**
+ * 转换为long
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ *
+ * @return 结果
+ */
+ public static Long toLong (Object value, Long defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Long) {
+ return (Long) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).longValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ // 支持科学计数法
+ return new BigDecimal(valueStr.trim()).longValue();
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为long
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ *
+ * @return 结果
+ */
+ public static Long toLong (Object value) {
+ return toLong(value, null);
+ }
+
+ /**
+ * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ *
+ * @return 结果
+ */
+ public static Double toDouble (Object value, Double defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Double) {
+ return (Double) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).doubleValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ // 支持科学计数法
+ return new BigDecimal(valueStr.trim()).doubleValue();
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ *
+ * @return 结果
+ */
+ public static Double toDouble (Object value) {
+ return toDouble(value, null);
+ }
+
+ /**
+ * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ *
+ * @return 结果
+ */
+ public static Float toFloat (Object value, Float defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Float) {
+ return (Float) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).floatValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return Float.parseFloat(valueStr.trim());
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ *
+ * @return 结果
+ */
+ public static Float toFloat (Object value) {
+ return toFloat(value, null);
+ }
+
+ /**
+ * 转换为boolean
+ * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ *
+ * @return 结果
+ */
+ public static Boolean toBool (Object value, Boolean defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Boolean) {
+ return (Boolean) value;
+ }
+ String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ valueStr = valueStr.trim().toLowerCase();
+ switch (valueStr) {
+ case "true":
+ case "yes":
+ case "ok":
+ case "1":
+ return true;
+ case "false":
+ case "no":
+ case "0":
+ return false;
+ default:
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为boolean
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ *
+ * @return 结果
+ */
+ public static Boolean toBool (Object value) {
+ return toBool(value, null);
+ }
+
+ /**
+ * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值
+ *
+ * @param clazz Enum的Class
+ * @param value 值
+ * @param defaultValue 默认值
+ *
+ * @return Enum
+ */
+ public static > E toEnum (Class clazz, Object value, E defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (clazz.isAssignableFrom(value.getClass())) {
+ @SuppressWarnings("unchecked")
+ E myE = (E) value;
+ return myE;
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return Enum.valueOf(clazz, valueStr);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ *
+ * @param clazz Enum的Class
+ * @param value 值
+ *
+ * @return Enum
+ */
+ public static > E toEnum (Class clazz, Object value) {
+ return toEnum(clazz, value, null);
+ }
+
+ /**
+ * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ *
+ * @return 结果
+ */
+ public static BigInteger toBigInteger (Object value, BigInteger defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof BigInteger) {
+ return (BigInteger) value;
+ }
+ if (value instanceof Long) {
+ return BigInteger.valueOf((Long) value);
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return new BigInteger(valueStr);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ *
+ * @return 结果
+ */
+ public static BigInteger toBigInteger (Object value) {
+ return toBigInteger(value, null);
+ }
+
+ /**
+ * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ *
+ * @return 结果
+ */
+ public static BigDecimal toBigDecimal (Object value, BigDecimal defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof BigDecimal) {
+ return (BigDecimal) value;
+ }
+ if (value instanceof Long) {
+ return new BigDecimal((Long) value);
+ }
+ if (value instanceof Double) {
+ return BigDecimal.valueOf((Double) value);
+ }
+ if (value instanceof Integer) {
+ return new BigDecimal((Integer) value);
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return new BigDecimal(valueStr);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ *
+ * @return 结果
+ */
+ public static BigDecimal toBigDecimal (Object value) {
+ return toBigDecimal(value, null);
+ }
+
+ /**
+ * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+ *
+ * @param obj 对象
+ *
+ * @return 字符串
+ */
+ public static String utf8Str (Object obj) {
+ return str(obj, CharsetKit.CHARSET_UTF_8);
+ }
+
+ /**
+ * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+ *
+ * @param obj 对象
+ * @param charsetName 字符集
+ *
+ * @return 字符串
+ */
+ public static String str (Object obj, String charsetName) {
+ return str(obj, Charset.forName(charsetName));
+ }
+
+ /**
+ * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+ *
+ * @param obj 对象
+ * @param charset 字符集
+ *
+ * @return 字符串
+ */
+ public static String str (Object obj, Charset charset) {
+ if (null == obj) {
+ return null;
+ }
+
+ if (obj instanceof String) {
+ return (String) obj;
+ } else if (obj instanceof byte[] || obj instanceof Byte[]) {
+ if (obj instanceof byte[]) {
+ return str((byte[]) obj, charset);
+ } else {
+ Byte[] bytes = (Byte[]) obj;
+ int length = bytes.length;
+ byte[] dest = new byte[length];
+ for (int i = 0 ; i < length ; i++) {
+ dest[i] = bytes[i];
+ }
+ return str(dest, charset);
+ }
+ } else if (obj instanceof ByteBuffer) {
+ return str((ByteBuffer) obj, charset);
+ }
+ return obj.toString();
+ }
+
+ /**
+ * 将byte数组转为字符串
+ *
+ * @param bytes byte数组
+ * @param charset 字符集
+ *
+ * @return 字符串
+ */
+ public static String str (byte[] bytes, String charset) {
+ return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
+ }
+
+ /**
+ * 解码字节码
+ *
+ * @param data 字符串
+ * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
+ *
+ * @return 解码后的字符串
+ */
+ public static String str (byte[] data, Charset charset) {
+ if (data == null) {
+ return null;
+ }
+
+ if (null == charset) {
+ return new String(data);
+ }
+ return new String(data, charset);
+ }
+
+ /**
+ * 将编码的byteBuffer数据转换为字符串
+ *
+ * @param data 数据
+ * @param charset 字符集,如果为空使用当前系统字符集
+ *
+ * @return 字符串
+ */
+ public static String str (ByteBuffer data, String charset) {
+ if (data == null) {
+ return null;
+ }
+
+ return str(data, Charset.forName(charset));
+ }
+
+ /**
+ * 将编码的byteBuffer数据转换为字符串
+ *
+ * @param data 数据
+ * @param charset 字符集,如果为空使用当前系统字符集
+ *
+ * @return 字符串
+ */
+ public static String str (ByteBuffer data, Charset charset) {
+ if (null == charset) {
+ charset = Charset.defaultCharset();
+ }
+ return charset.decode(data).toString();
+ }
+
+ // ----------------------------------------------------------------------- 全角半角转换
+
+ /**
+ * 半角转全角
+ *
+ * @param input String.
+ *
+ * @return 全角字符串.
+ */
+ public static String toSBC (String input) {
+ return toSBC(input, null);
+ }
+
+ /**
+ * 半角转全角
+ *
+ * @param input String
+ * @param notConvertSet 不替换的字符集合
+ *
+ * @return 全角字符串.
+ */
+ public static String toSBC (String input, Set notConvertSet) {
+ char[] c = input.toCharArray();
+ for (int i = 0 ; i < c.length ; i++) {
+ if (null != notConvertSet && notConvertSet.contains(c[i])) {
+ // 跳过不替换的字符
+ continue;
+ }
+
+ if (c[i] == ' ') {
+ c[i] = '\u3000';
+ } else if (c[i] < '\177') {
+ c[i] = (char) (c[i] + 65248);
+
+ }
+ }
+ return new String(c);
+ }
+
+ /**
+ * 全角转半角
+ *
+ * @param input String.
+ *
+ * @return 半角字符串
+ */
+ public static String toDBC (String input) {
+ return toDBC(input, null);
+ }
+
+ /**
+ * 替换全角为半角
+ *
+ * @param text 文本
+ * @param notConvertSet 不替换的字符集合
+ *
+ * @return 替换后的字符
+ */
+ public static String toDBC (String text, Set notConvertSet) {
+ char[] c = text.toCharArray();
+ for (int i = 0 ; i < c.length ; i++) {
+ if (null != notConvertSet && notConvertSet.contains(c[i])) {
+ // 跳过不替换的字符
+ continue;
+ }
+
+ if (c[i] == '\u3000') {
+ c[i] = ' ';
+ } else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
+ c[i] = (char) (c[i] - 65248);
+ }
+ }
+ return new String(c);
+ }
+
+ /**
+ * 数字金额大写转换 先写个完整的然后将如零拾替换成零
+ *
+ * @param n 数字
+ *
+ * @return 中文大写数字
+ */
+ public static String digitUppercase (double n) {
+ String[] fraction = {"角", "分"};
+ String[] digit = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
+ String[][] unit = {{"元", "万", "亿"}, {"", "拾", "佰", "仟"}};
+
+ String head = n < 0 ? "负" : "";
+ n = Math.abs(n);
+
+ String s = "";
+ for (int i = 0 ; i < fraction.length ; i++) {
+ // 优化double计算精度丢失问题
+ BigDecimal nNum = new BigDecimal(n);
+ BigDecimal decimal = new BigDecimal(10);
+ BigDecimal scale = nNum.multiply(decimal).setScale(2, RoundingMode.HALF_EVEN);
+ double d = scale.doubleValue();
+ s += (digit[(int) (Math.floor(d * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
+ }
+ if (s.length() < 1) {
+ s = "整";
+ }
+ int integerPart = (int) Math.floor(n);
+
+ for (int i = 0 ; i < unit[0].length && integerPart > 0 ; i++) {
+ String p = "";
+ for (int j = 0 ; j < unit[1].length && n > 0 ; j++) {
+ p = digit[integerPart % 10] + unit[1][j] + p;
+ integerPart = integerPart / 10;
+ }
+ s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
+ }
+ return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/text/StrFormatter.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/text/StrFormatter.java
new file mode 100644
index 0000000..841dd25
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/text/StrFormatter.java
@@ -0,0 +1,77 @@
+package com.ruoyi.common.core.text;
+
+import com.ruoyi.common.core.utils.StringUtils;
+
+/**
+ * 字符串格式化
+ *
+ * @author muyu
+ */
+public class StrFormatter {
+ public static final String EMPTY_JSON = "{}";
+ public static final char C_BACKSLASH = '\\';
+ public static final char C_DELIM_START = '{';
+ public static final char C_DELIM_END = '}';
+
+ /**
+ * 格式化字符串
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ *
+ * @param strPattern 字符串模板
+ * @param argArray 参数列表
+ *
+ * @return 结果
+ */
+ public static String format (final String strPattern, final Object... argArray) {
+ if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) {
+ return strPattern;
+ }
+ final int strPatternLength = strPattern.length();
+
+ // 初始化定义好的长度以获得更好的性能
+ StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
+
+ int handledPosition = 0;
+ int delimIndex;// 占位符所在位置
+ for (int argIndex = 0 ; argIndex < argArray.length ; argIndex++) {
+ delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
+ if (delimIndex == -1) {
+ if (handledPosition == 0) {
+ return strPattern;
+ } else { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
+ sbuf.append(strPattern, handledPosition, strPatternLength);
+ return sbuf.toString();
+ }
+ } else {
+ if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) {
+ if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) {
+ // 转义符之前还有一个转义符,占位符依旧有效
+ sbuf.append(strPattern, handledPosition, delimIndex - 1);
+ sbuf.append(Convert.utf8Str(argArray[argIndex]));
+ handledPosition = delimIndex + 2;
+ } else {
+ // 占位符被转义
+ argIndex--;
+ sbuf.append(strPattern, handledPosition, delimIndex - 1);
+ sbuf.append(C_DELIM_START);
+ handledPosition = delimIndex + 1;
+ }
+ } else {
+ // 正常占位符
+ sbuf.append(strPattern, handledPosition, delimIndex);
+ sbuf.append(Convert.utf8Str(argArray[argIndex]));
+ handledPosition = delimIndex + 2;
+ }
+ }
+ }
+ // 加入最后一个占位符后所有的字符
+ sbuf.append(strPattern, handledPosition, strPattern.length());
+
+ return sbuf.toString();
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java
new file mode 100644
index 0000000..9f17724
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java
@@ -0,0 +1,158 @@
+package com.ruoyi.common.core.utils;
+
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+import java.lang.management.ManagementFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.*;
+import java.util.Date;
+
+/**
+ * 时间工具类
+ *
+ * @author muyu
+ */
+public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
+ public static String YYYY = "yyyy";
+
+ public static String YYYY_MM = "yyyy-MM";
+
+ public static String YYYY_MM_DD = "yyyy-MM-dd";
+
+ public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+ public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+ private static String[] parsePatterns = {
+ "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
+ "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
+ "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+
+ /**
+ * 获取当前Date型日期
+ *
+ * @return Date() 当前日期
+ */
+ public static Date getNowDate () {
+ return new Date();
+ }
+
+ /**
+ * 获取当前日期, 默认格式为yyyy-MM-dd
+ *
+ * @return String
+ */
+ public static String getDate () {
+ return dateTimeNow(YYYY_MM_DD);
+ }
+
+ public static final String getTime () {
+ return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+ }
+
+ public static final String dateTimeNow () {
+ return dateTimeNow(YYYYMMDDHHMMSS);
+ }
+
+ public static final String dateTimeNow (final String format) {
+ return parseDateToStr(format, new Date());
+ }
+
+ public static final String dateTime (final Date date) {
+ return parseDateToStr(YYYY_MM_DD, date);
+ }
+
+ public static final String parseDateToStr (final String format, final Date date) {
+ return new SimpleDateFormat(format).format(date);
+ }
+
+ public static final Date dateTime (final String format, final String ts) {
+ try {
+ return new SimpleDateFormat(format).parse(ts);
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * 日期路径 即年/月/日 如2018/08/08
+ */
+ public static final String datePath () {
+ Date now = new Date();
+ return DateFormatUtils.format(now, "yyyy/MM/dd");
+ }
+
+ /**
+ * 日期路径 即年/月/日 如20180808
+ */
+ public static final String dateTime () {
+ Date now = new Date();
+ return DateFormatUtils.format(now, "yyyyMMdd");
+ }
+
+ /**
+ * 日期型字符串转化为日期 格式
+ */
+ public static Date parseDate (Object str) {
+ if (str == null) {
+ return null;
+ }
+ try {
+ return parseDate(str.toString(), parsePatterns);
+ } catch (ParseException e) {
+ return null;
+ }
+ }
+
+ /**
+ * 获取服务器启动时间
+ */
+ public static Date getServerStartDate () {
+ long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+ return new Date(time);
+ }
+
+ /**
+ * 计算时间差
+ *
+ * @param endDate 最后时间
+ * @param startTime 开始时间
+ *
+ * @return 时间差(天/小时/分钟)
+ */
+ public static String timeDistance (Date endDate, Date startTime) {
+ long nd = 1000 * 24 * 60 * 60;
+ long nh = 1000 * 60 * 60;
+ long nm = 1000 * 60;
+ // long ns = 1000;
+ // 获得两个时间的毫秒时间差异
+ long diff = endDate.getTime() - startTime.getTime();
+ // 计算差多少天
+ long day = diff / nd;
+ // 计算差多少小时
+ long hour = diff % nd / nh;
+ // 计算差多少分钟
+ long min = diff % nd % nh / nm;
+ // 计算差多少秒//输出结果
+ // long sec = diff % nd % nh % nm / ns;
+ return day + "天" + hour + "小时" + min + "分钟";
+ }
+
+ /**
+ * 增加 LocalDateTime ==> Date
+ */
+ public static Date toDate (LocalDateTime temporalAccessor) {
+ ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
+ return Date.from(zdt.toInstant());
+ }
+
+ /**
+ * 增加 LocalDate ==> Date
+ */
+ public static Date toDate (LocalDate temporalAccessor) {
+ LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
+ ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
+ return Date.from(zdt.toInstant());
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/utils/ExceptionUtil.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/utils/ExceptionUtil.java
new file mode 100644
index 0000000..3a2639e
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/utils/ExceptionUtil.java
@@ -0,0 +1,35 @@
+package com.ruoyi.common.core.utils;
+
+import org.apache.commons.lang3.exception.ExceptionUtils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * 错误信息处理类。
+ *
+ * @author muyu
+ */
+public class ExceptionUtil {
+ /**
+ * 获取exception的详细错误信息。
+ */
+ public static String getExceptionMessage (Throwable e) {
+ StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw, true));
+ return sw.toString();
+ }
+
+ public static String getRootErrorMessage (Exception e) {
+ Throwable root = ExceptionUtils.getRootCause(e);
+ root = (root == null ? e : root);
+ if (root == null) {
+ return "";
+ }
+ String msg = root.getMessage();
+ if (msg == null) {
+ return "null";
+ }
+ return StringUtils.defaultString(msg);
+ }
+}
diff --git a/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/utils/GtlUtil.java b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/utils/GtlUtil.java
new file mode 100644
index 0000000..360f5f1
--- /dev/null
+++ b/ruoyi-common/muyu-common-core/src/main/java/com/ruoyi/common/core/utils/GtlUtil.java
@@ -0,0 +1,54 @@
+package com.ruoyi.common.core.utils;
+
+import com.alibaba.fastjson2.JSON;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @ClassName GtlUtil
+ * @Description 常用功能工具类
+ * @Author gtl
+ */
+public class GtlUtil {
+
+ /**
+ * 判断字符串是否被base64编码过
+ * @param str 字符串
+ * @return true/false
+ */
+ public static boolean isBase64(String str){
+ final Pattern BASE64_PATTERN = Pattern.compile("^[A-Za-z0-9+/]*={0,2}$");
+ return BASE64_PATTERN.matcher(str).matches();
+ }
+
+ /**
+ * 将List