From 89fc9e10895c09a0c0b70689789463e92d79e10e Mon Sep 17 00:00:00 2001
From: xiangpei <xiangpei@timesnew.cn>
Date: 星期二, 05 三月 2024 09:20:21 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 ycl-common/src/main/java/utils/DictUtils.java                                      |  186 +
 ycl-common/src/main/java/utils/file/FileUploadUtils.java                           |  233 ++
 ycl-pojo/src/main/java/com/ycl/platform/entity/TMonitor.java                       |  461 ++++
 ycl-common/src/main/java/exception/user/CaptchaExpireException.java                |   16 
 ycl-common/src/main/java/exception/base/BaseException.java                         |   97 
 ycl-common/src/main/java/exception/file/FileException.java                         |   19 
 ycl-common/src/main/java/exception/user/UserPasswordNotMatchException.java         |   16 
 ycl-common/src/main/java/exception/file/InvalidExtensionException.java             |   80 
 ycl-common/src/main/java/exception/user/UserNotExistsException.java                |   16 
 ycl-common/src/main/java/exception/user/UserPasswordRetryLimitExceedException.java |   16 
 ycl-server/src/main/java/com/ycl/utils/poi/ExcelUtil.java                          |    4 
 ycl-server/src/main/java/com/ycl/platform/service/ITMonitorService.java            |   62 
 ycl-common/src/main/java/pojo/BaseEntity.java                                      |  119 +
 ycl-common/src/main/java/exception/file/FileSizeLimitExceededException.java        |   16 
 ycl-common/src/main/java/utils/file/ImageUtils.java                                |   99 
 ycl-common/src/main/java/exception/job/TaskException.java                          |   34 
 ycl-common/src/main/java/exception/user/UserException.java                         |   18 
 ycl-common/src/main/java/exception/GlobalException.java                            |   58 
 ycl-common/src/main/java/exception/user/BlackListException.java                    |   16 
 ycl-common/src/main/java/utils/uuid/Seq.java                                       |   87 
 ycl-common/src/main/java/utils/file/MimeTypeUtils.java                             |   59 
 ycl-common/src/main/java/annotation/Excels.java                                    |    2 
 ycl-common/src/main/java/utils/MessageUtils.java                                   |   25 
 ycl-common/src/main/java/exception/user/CaptchaException.java                      |   16 
 ycl-common/src/main/java/pojo/AjaxResult.java                                      |  217 ++
 ycl-common/src/main/java/utils/poi/ExcelUtil.java                                  | 1713 ++++++++++++++++
 ycl-common/src/main/java/utils/uuid/IdUtils.java                                   |   49 
 ycl-common/src/main/java/utils/poi/ExcelHandlerAdapter.java                        |   24 
 ycl-pojo/src/main/java/com/ycl/system/AjaxResult.java                              |    6 
 ycl-common/src/main/java/exception/DemoModeException.java                          |   15 
 ycl-server/src/main/resources/mapper/zgyw/TMonitorMapper.xml                       |  201 +
 ycl-common/src/main/java/exception/ServiceException.java                           |   74 
 ycl-common/src/main/java/utils/file/FileTypeUtils.java                             |   77 
 ycl-common/src/main/java/utils/file/FileUtils.java                                 |  286 ++
 ycl-generator/src/main/resources/vm/java/controller.java.vm                        |    1 
 ycl-common/src/main/java/config/PlatformConfig.java                                |  122 +
 ycl-server/src/main/java/com/ycl/platform/mapper/TMonitorMapper.java               |   62 
 ycl-common/src/main/java/utils/SpringUtils.java                                    |  157 +
 ycl-common/src/main/java/exception/file/FileNameLengthLimitExceededException.java  |   16 
 ycl-server/src/main/java/com/ycl/platform/service/impl/TMonitorServiceImpl.java    |   94 
 ycl-common/src/main/java/utils/redis/RedisCache.java                               |  265 ++
 ycl-common/src/main/java/utils/uuid/UUID.java                                      |  485 ++++
 ycl-common/src/main/java/pojo/SysDictData.java                                     |  167 +
 ycl-common/src/main/java/utils/reflect/ReflectUtils.java                           |  406 +++
 ycl-common/pom.xml                                                                 |    5 
 ycl-common/src/main/java/exception/UtilException.java                              |   26 
 ycl-common/src/main/java/annotation/Excel.java                                     |    4 
 ycl-server/src/main/java/com/ycl/platform/controller/TMonitorController.java       |   98 
 ycl-common/src/main/java/exception/file/FileUploadException.java                   |   61 
 49 files changed, 6,377 insertions(+), 9 deletions(-)

diff --git a/ycl-common/pom.xml b/ycl-common/pom.xml
index 67ab2fd..d5b3290 100644
--- a/ycl-common/pom.xml
+++ b/ycl-common/pom.xml
@@ -43,7 +43,10 @@
             <groupId>org.apache.tomcat.embed</groupId>
             <artifactId>tomcat-embed-core</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
     </dependencies>
 
 </project>
diff --git a/ycl-server/src/main/java/com/ycl/annotation/Excel.java b/ycl-common/src/main/java/annotation/Excel.java
similarity index 97%
rename from ycl-server/src/main/java/com/ycl/annotation/Excel.java
rename to ycl-common/src/main/java/annotation/Excel.java
index fe3b54f..a8c8a60 100644
--- a/ycl-server/src/main/java/com/ycl/annotation/Excel.java
+++ b/ycl-common/src/main/java/annotation/Excel.java
@@ -1,8 +1,8 @@
-package com.ycl.annotation;
+package annotation;
 
-import com.ycl.utils.poi.ExcelHandlerAdapter;
 import org.apache.poi.ss.usermodel.HorizontalAlignment;
 import org.apache.poi.ss.usermodel.IndexedColors;
+import utils.poi.ExcelHandlerAdapter;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
diff --git a/ycl-server/src/main/java/com/ycl/annotation/Excels.java b/ycl-common/src/main/java/annotation/Excels.java
similarity index 91%
rename from ycl-server/src/main/java/com/ycl/annotation/Excels.java
rename to ycl-common/src/main/java/annotation/Excels.java
index b109839..07cd4be 100644
--- a/ycl-server/src/main/java/com/ycl/annotation/Excels.java
+++ b/ycl-common/src/main/java/annotation/Excels.java
@@ -1,4 +1,4 @@
-package com.ycl.annotation;
+package annotation;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
diff --git a/ycl-common/src/main/java/config/PlatformConfig.java b/ycl-common/src/main/java/config/PlatformConfig.java
new file mode 100644
index 0000000..aa1c20f
--- /dev/null
+++ b/ycl-common/src/main/java/config/PlatformConfig.java
@@ -0,0 +1,122 @@
+package config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 璇诲彇椤圭洰鐩稿叧閰嶇疆
+ * 
+ * @author platform
+ */
+@Component
+@ConfigurationProperties(prefix = "platform")
+public class PlatformConfig
+{
+    /** 椤圭洰鍚嶇О */
+    private String name;
+
+    /** 鐗堟湰 */
+    private String version;
+
+    /** 鐗堟潈骞翠唤 */
+    private String copyrightYear;
+
+    /** 涓婁紶璺緞 */
+    private static String profile;
+
+    /** 鑾峰彇鍦板潃寮�鍏� */
+    private static boolean addressEnabled;
+
+    /** 楠岃瘉鐮佺被鍨� */
+    private static String captchaType;
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public String getVersion()
+    {
+        return version;
+    }
+
+    public void setVersion(String version)
+    {
+        this.version = version;
+    }
+
+    public String getCopyrightYear()
+    {
+        return copyrightYear;
+    }
+
+    public void setCopyrightYear(String copyrightYear)
+    {
+        this.copyrightYear = copyrightYear;
+    }
+
+    public static String getProfile()
+    {
+        return profile;
+    }
+
+    public void setProfile(String profile)
+    {
+        PlatformConfig.profile = profile;
+    }
+
+    public static boolean isAddressEnabled()
+    {
+        return addressEnabled;
+    }
+
+    public void setAddressEnabled(boolean addressEnabled)
+    {
+        PlatformConfig.addressEnabled = addressEnabled;
+    }
+
+    public static String getCaptchaType() {
+        return captchaType;
+    }
+
+    public void setCaptchaType(String captchaType) {
+        PlatformConfig.captchaType = captchaType;
+    }
+
+    /**
+     * 鑾峰彇瀵煎叆涓婁紶璺緞
+     */
+    public static String getImportPath()
+    {
+        return getProfile() + "/import";
+    }
+
+    /**
+     * 鑾峰彇澶村儚涓婁紶璺緞
+     */
+    public static String getAvatarPath()
+    {
+        return getProfile() + "/avatar";
+    }
+
+    /**
+     * 鑾峰彇涓嬭浇璺緞
+     */
+    public static String getDownloadPath()
+    {
+        return getProfile() + "/download/";
+    }
+
+    /**
+     * 鑾峰彇涓婁紶璺緞
+     */
+    public static String getUploadPath()
+    {
+        return getProfile() + "/upload";
+    }
+}
diff --git a/ycl-common/src/main/java/exception/DemoModeException.java b/ycl-common/src/main/java/exception/DemoModeException.java
new file mode 100644
index 0000000..d7f61f6
--- /dev/null
+++ b/ycl-common/src/main/java/exception/DemoModeException.java
@@ -0,0 +1,15 @@
+package exception;
+
+/**
+ * 婕旂ず妯″紡寮傚父
+ * 
+ * @author ruoyi
+ */
+public class DemoModeException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public DemoModeException()
+    {
+    }
+}
diff --git a/ycl-common/src/main/java/exception/GlobalException.java b/ycl-common/src/main/java/exception/GlobalException.java
new file mode 100644
index 0000000..7a0485d
--- /dev/null
+++ b/ycl-common/src/main/java/exception/GlobalException.java
@@ -0,0 +1,58 @@
+package exception;
+
+/**
+ * 鍏ㄥ眬寮傚父
+ * 
+ * @author ruoyi
+ */
+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;
+    }
+}
\ No newline at end of file
diff --git a/ycl-common/src/main/java/exception/ServiceException.java b/ycl-common/src/main/java/exception/ServiceException.java
new file mode 100644
index 0000000..b3576ac
--- /dev/null
+++ b/ycl-common/src/main/java/exception/ServiceException.java
@@ -0,0 +1,74 @@
+package exception;
+
+/**
+ * 涓氬姟寮傚父
+ * 
+ * @author ruoyi
+ */
+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;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public ServiceException setMessage(String message)
+    {
+        this.message = message;
+        return this;
+    }
+
+    public ServiceException setDetailMessage(String detailMessage)
+    {
+        this.detailMessage = detailMessage;
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/ycl-common/src/main/java/exception/UtilException.java b/ycl-common/src/main/java/exception/UtilException.java
new file mode 100644
index 0000000..a8f1ae8
--- /dev/null
+++ b/ycl-common/src/main/java/exception/UtilException.java
@@ -0,0 +1,26 @@
+package exception;
+
+/**
+ * 宸ュ叿绫诲紓甯�
+ * 
+ * @author ruoyi
+ */
+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/ycl-common/src/main/java/exception/base/BaseException.java b/ycl-common/src/main/java/exception/base/BaseException.java
new file mode 100644
index 0000000..f7c5d39
--- /dev/null
+++ b/ycl-common/src/main/java/exception/base/BaseException.java
@@ -0,0 +1,97 @@
+package exception.base;
+
+import utils.MessageUtils;
+import utils.StringUtils;
+
+/**
+ * 鍩虹寮傚父
+ * 
+ * @author ruoyi
+ */
+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);
+    }
+
+    @Override
+    public String getMessage()
+    {
+        String message = null;
+        if (!StringUtils.isEmpty(code))
+        {
+            message = MessageUtils.message(code, args);
+        }
+        if (message == null)
+        {
+            message = defaultMessage;
+        }
+        return message;
+    }
+
+    public String getModule()
+    {
+        return module;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public Object[] getArgs()
+    {
+        return args;
+    }
+
+    public String getDefaultMessage()
+    {
+        return defaultMessage;
+    }
+}
diff --git a/ycl-common/src/main/java/exception/file/FileException.java b/ycl-common/src/main/java/exception/file/FileException.java
new file mode 100644
index 0000000..0b77431
--- /dev/null
+++ b/ycl-common/src/main/java/exception/file/FileException.java
@@ -0,0 +1,19 @@
+package exception.file;
+
+import exception.base.BaseException;
+
+/**
+ * 鏂囦欢淇℃伅寮傚父绫�
+ * 
+ * @author ruoyi
+ */
+public class FileException extends BaseException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileException(String code, Object[] args)
+    {
+        super("file", code, args, null);
+    }
+
+}
diff --git a/ycl-common/src/main/java/exception/file/FileNameLengthLimitExceededException.java b/ycl-common/src/main/java/exception/file/FileNameLengthLimitExceededException.java
new file mode 100644
index 0000000..f56ca39
--- /dev/null
+++ b/ycl-common/src/main/java/exception/file/FileNameLengthLimitExceededException.java
@@ -0,0 +1,16 @@
+package exception.file;
+
+/**
+ * 鏂囦欢鍚嶇О瓒呴暱闄愬埗寮傚父绫�
+ * 
+ * @author ruoyi
+ */
+public class FileNameLengthLimitExceededException extends FileException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileNameLengthLimitExceededException(int defaultFileNameLength)
+    {
+        super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
+    }
+}
diff --git a/ycl-common/src/main/java/exception/file/FileSizeLimitExceededException.java b/ycl-common/src/main/java/exception/file/FileSizeLimitExceededException.java
new file mode 100644
index 0000000..f816f63
--- /dev/null
+++ b/ycl-common/src/main/java/exception/file/FileSizeLimitExceededException.java
@@ -0,0 +1,16 @@
+package exception.file;
+
+/**
+ * 鏂囦欢鍚嶅ぇ灏忛檺鍒跺紓甯哥被
+ * 
+ * @author ruoyi
+ */
+public class FileSizeLimitExceededException extends FileException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileSizeLimitExceededException(long defaultMaxSize)
+    {
+        super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
+    }
+}
diff --git a/ycl-common/src/main/java/exception/file/FileUploadException.java b/ycl-common/src/main/java/exception/file/FileUploadException.java
new file mode 100644
index 0000000..1973db6
--- /dev/null
+++ b/ycl-common/src/main/java/exception/file/FileUploadException.java
@@ -0,0 +1,61 @@
+package exception.file;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * 鏂囦欢涓婁紶寮傚父绫�
+ * 
+ * @author ruoyi
+ */
+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/ycl-common/src/main/java/exception/file/InvalidExtensionException.java b/ycl-common/src/main/java/exception/file/InvalidExtensionException.java
new file mode 100644
index 0000000..4bf6fa8
--- /dev/null
+++ b/ycl-common/src/main/java/exception/file/InvalidExtensionException.java
@@ -0,0 +1,80 @@
+package exception.file;
+
+import java.util.Arrays;
+
+/**
+ * 鏂囦欢涓婁紶 璇紓甯哥被
+ * 
+ * @author ruoyi
+ */
+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 + "]鍚庣紑[" + 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/ycl-common/src/main/java/exception/job/TaskException.java b/ycl-common/src/main/java/exception/job/TaskException.java
new file mode 100644
index 0000000..fdd78e6
--- /dev/null
+++ b/ycl-common/src/main/java/exception/job/TaskException.java
@@ -0,0 +1,34 @@
+package exception.job;
+
+/**
+ * 璁″垝绛栫暐寮傚父
+ * 
+ * @author ruoyi
+ */
+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
+    }
+}
\ No newline at end of file
diff --git a/ycl-common/src/main/java/exception/user/BlackListException.java b/ycl-common/src/main/java/exception/user/BlackListException.java
new file mode 100644
index 0000000..bea9054
--- /dev/null
+++ b/ycl-common/src/main/java/exception/user/BlackListException.java
@@ -0,0 +1,16 @@
+package exception.user;
+
+/**
+ * 榛戝悕鍗旾P寮傚父绫�
+ * 
+ * @author ruoyi
+ */
+public class BlackListException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public BlackListException()
+    {
+        super("login.blocked", null);
+    }
+}
diff --git a/ycl-common/src/main/java/exception/user/CaptchaException.java b/ycl-common/src/main/java/exception/user/CaptchaException.java
new file mode 100644
index 0000000..b75c494
--- /dev/null
+++ b/ycl-common/src/main/java/exception/user/CaptchaException.java
@@ -0,0 +1,16 @@
+package exception.user;
+
+/**
+ * 楠岃瘉鐮侀敊璇紓甯哥被
+ * 
+ * @author ruoyi
+ */
+public class CaptchaException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public CaptchaException()
+    {
+        super("user.jcaptcha.error", null);
+    }
+}
diff --git a/ycl-common/src/main/java/exception/user/CaptchaExpireException.java b/ycl-common/src/main/java/exception/user/CaptchaExpireException.java
new file mode 100644
index 0000000..d6f402c
--- /dev/null
+++ b/ycl-common/src/main/java/exception/user/CaptchaExpireException.java
@@ -0,0 +1,16 @@
+package exception.user;
+
+/**
+ * 楠岃瘉鐮佸け鏁堝紓甯哥被
+ * 
+ * @author ruoyi
+ */
+public class CaptchaExpireException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public CaptchaExpireException()
+    {
+        super("user.jcaptcha.expire", null);
+    }
+}
diff --git a/ycl-common/src/main/java/exception/user/UserException.java b/ycl-common/src/main/java/exception/user/UserException.java
new file mode 100644
index 0000000..87b3719
--- /dev/null
+++ b/ycl-common/src/main/java/exception/user/UserException.java
@@ -0,0 +1,18 @@
+package exception.user;
+
+import exception.base.BaseException;
+
+/**
+ * 鐢ㄦ埛淇℃伅寮傚父绫�
+ * 
+ * @author ruoyi
+ */
+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/ycl-common/src/main/java/exception/user/UserNotExistsException.java b/ycl-common/src/main/java/exception/user/UserNotExistsException.java
new file mode 100644
index 0000000..fb1c712
--- /dev/null
+++ b/ycl-common/src/main/java/exception/user/UserNotExistsException.java
@@ -0,0 +1,16 @@
+package exception.user;
+
+/**
+ * 鐢ㄦ埛涓嶅瓨鍦ㄥ紓甯哥被
+ * 
+ * @author ruoyi
+ */
+public class UserNotExistsException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserNotExistsException()
+    {
+        super("user.not.exists", null);
+    }
+}
diff --git a/ycl-common/src/main/java/exception/user/UserPasswordNotMatchException.java b/ycl-common/src/main/java/exception/user/UserPasswordNotMatchException.java
new file mode 100644
index 0000000..96c87da
--- /dev/null
+++ b/ycl-common/src/main/java/exception/user/UserPasswordNotMatchException.java
@@ -0,0 +1,16 @@
+package exception.user;
+
+/**
+ * 鐢ㄦ埛瀵嗙爜涓嶆纭垨涓嶇鍚堣鑼冨紓甯哥被
+ * 
+ * @author ruoyi
+ */
+public class UserPasswordNotMatchException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordNotMatchException()
+    {
+        super("user.password.not.match", null);
+    }
+}
diff --git a/ycl-common/src/main/java/exception/user/UserPasswordRetryLimitExceedException.java b/ycl-common/src/main/java/exception/user/UserPasswordRetryLimitExceedException.java
new file mode 100644
index 0000000..3bad759
--- /dev/null
+++ b/ycl-common/src/main/java/exception/user/UserPasswordRetryLimitExceedException.java
@@ -0,0 +1,16 @@
+package exception.user;
+
+/**
+ * 鐢ㄦ埛閿欒鏈�澶ф鏁板紓甯哥被
+ * 
+ * @author ruoyi
+ */
+public class UserPasswordRetryLimitExceedException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime)
+    {
+        super("user.password.retry.limit.exceed", new Object[] { retryLimitCount, lockTime });
+    }
+}
diff --git a/ycl-common/src/main/java/pojo/AjaxResult.java b/ycl-common/src/main/java/pojo/AjaxResult.java
new file mode 100644
index 0000000..ed0831b
--- /dev/null
+++ b/ycl-common/src/main/java/pojo/AjaxResult.java
@@ -0,0 +1,217 @@
+package pojo;
+
+import constant.HttpStatus;
+import utils.StringUtils;
+
+import java.util.HashMap;
+import java.util.Objects;
+
+/**
+ * 鎿嶄綔娑堟伅鎻愰啋
+ * 
+ * @author ruoyi
+ */
+public class AjaxResult extends HashMap<String, Object>
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鐘舵�佺爜 */
+    public static final String CODE_TAG = "code";
+
+    /** 杩斿洖鍐呭 */
+    public static final String MSG_TAG = "msg";
+
+    /** 鏁版嵁瀵硅薄 */
+    public static final String DATA_TAG = "data";
+
+    /**
+     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� pojo.AjaxResult 瀵硅薄锛屼娇鍏惰〃绀轰竴涓┖娑堟伅銆�
+     */
+    public AjaxResult()
+    {
+    }
+
+    /**
+     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� pojo.AjaxResult 瀵硅薄
+     * 
+     * @param code 鐘舵�佺爜
+     * @param msg 杩斿洖鍐呭
+     */
+    public AjaxResult(int code, String msg)
+    {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+    }
+
+    /**
+     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� pojo.AjaxResult 瀵硅薄
+     * 
+     * @param code 鐘舵�佺爜
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     */
+    public AjaxResult(int code, String msg, Object data)
+    {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+        if (StringUtils.isNotNull(data))
+        {
+            super.put(DATA_TAG, data);
+        }
+    }
+
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     * 
+     * @return 鎴愬姛娑堟伅
+     */
+    public static AjaxResult success()
+    {
+        return AjaxResult.success("鎿嶄綔鎴愬姛");
+    }
+
+    /**
+     * 杩斿洖鎴愬姛鏁版嵁
+     * 
+     * @return 鎴愬姛娑堟伅
+     */
+    public static AjaxResult success(Object data)
+    {
+        return AjaxResult.success("鎿嶄綔鎴愬姛", data);
+    }
+
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     * 
+     * @param msg 杩斿洖鍐呭
+     * @return 鎴愬姛娑堟伅
+     */
+    public static AjaxResult success(String msg)
+    {
+        return AjaxResult.success(msg, null);
+    }
+
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     * 
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     * @return 鎴愬姛娑堟伅
+     */
+    public static AjaxResult success(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.SUCCESS, msg, data);
+    }
+
+    /**
+     * 杩斿洖璀﹀憡娑堟伅
+     *
+     * @param msg 杩斿洖鍐呭
+     * @return 璀﹀憡娑堟伅
+     */
+    public static AjaxResult warn(String msg)
+    {
+        return AjaxResult.warn(msg, null);
+    }
+
+    /**
+     * 杩斿洖璀﹀憡娑堟伅
+     *
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     * @return 璀﹀憡娑堟伅
+     */
+    public static AjaxResult warn(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.WARN, msg, data);
+    }
+
+    /**
+     * 杩斿洖閿欒娑堟伅
+     * 
+     * @return 閿欒娑堟伅
+     */
+    public static AjaxResult error()
+    {
+        return AjaxResult.error("鎿嶄綔澶辫触");
+    }
+
+    /**
+     * 杩斿洖閿欒娑堟伅
+     * 
+     * @param msg 杩斿洖鍐呭
+     * @return 閿欒娑堟伅
+     */
+    public static AjaxResult error(String msg)
+    {
+        return AjaxResult.error(msg, null);
+    }
+
+    /**
+     * 杩斿洖閿欒娑堟伅
+     * 
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     * @return 閿欒娑堟伅
+     */
+    public static AjaxResult error(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.ERROR, msg, data);
+    }
+
+    /**
+     * 杩斿洖閿欒娑堟伅
+     * 
+     * @param code 鐘舵�佺爜
+     * @param msg 杩斿洖鍐呭
+     * @return 閿欒娑堟伅
+     */
+    public static AjaxResult error(int code, String msg)
+    {
+        return new AjaxResult(code, msg, null);
+    }
+
+    /**
+     * 鏄惁涓烘垚鍔熸秷鎭�
+     *
+     * @return 缁撴灉
+     */
+    public boolean isSuccess()
+    {
+        return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
+    }
+
+    /**
+     * 鏄惁涓鸿鍛婃秷鎭�
+     *
+     * @return 缁撴灉
+     */
+    public boolean isWarn()
+    {
+        return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
+    }
+
+    /**
+     * 鏄惁涓洪敊璇秷鎭�
+     *
+     * @return 缁撴灉
+     */
+    public boolean isError()
+    {
+        return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
+    }
+
+    /**
+     * 鏂逛究閾惧紡璋冪敤
+     *
+     * @param key 閿�
+     * @param value 鍊�
+     * @return 鏁版嵁瀵硅薄
+     */
+    @Override
+    public AjaxResult put(String key, Object value)
+    {
+        super.put(key, value);
+        return this;
+    }
+}
diff --git a/ycl-common/src/main/java/pojo/BaseEntity.java b/ycl-common/src/main/java/pojo/BaseEntity.java
new file mode 100644
index 0000000..bd7c87a
--- /dev/null
+++ b/ycl-common/src/main/java/pojo/BaseEntity.java
@@ -0,0 +1,119 @@
+package pojo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Entity鍩虹被
+ * 
+ * @author ruoyi
+ */
+public class BaseEntity implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鎼滅储鍊� */
+    @JsonIgnore
+    private String searchValue;
+
+    /** 鍒涘缓鑰� */
+    private String createBy;
+
+    /** 鍒涘缓鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /** 鏇存柊鑰� */
+    private String updateBy;
+
+    /** 鏇存柊鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /** 澶囨敞 */
+    private String remark;
+
+    /** 璇锋眰鍙傛暟 */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    private Map<String, Object> params;
+
+    public String getSearchValue()
+    {
+        return searchValue;
+    }
+
+    public void setSearchValue(String searchValue)
+    {
+        this.searchValue = searchValue;
+    }
+
+    public String getCreateBy()
+    {
+        return createBy;
+    }
+
+    public void setCreateBy(String createBy)
+    {
+        this.createBy = createBy;
+    }
+
+    public Date getCreateTime()
+    {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime)
+    {
+        this.createTime = createTime;
+    }
+
+    public String getUpdateBy()
+    {
+        return updateBy;
+    }
+
+    public void setUpdateBy(String updateBy)
+    {
+        this.updateBy = updateBy;
+    }
+
+    public Date getUpdateTime()
+    {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime)
+    {
+        this.updateTime = updateTime;
+    }
+
+    public String getRemark()
+    {
+        return remark;
+    }
+
+    public void setRemark(String remark)
+    {
+        this.remark = remark;
+    }
+
+    public Map<String, Object> getParams()
+    {
+        if (params == null)
+        {
+            params = new HashMap<>();
+        }
+        return params;
+    }
+
+    public void setParams(Map<String, Object> params)
+    {
+        this.params = params;
+    }
+}
diff --git a/ycl-common/src/main/java/pojo/SysDictData.java b/ycl-common/src/main/java/pojo/SysDictData.java
new file mode 100644
index 0000000..5ca7938
--- /dev/null
+++ b/ycl-common/src/main/java/pojo/SysDictData.java
@@ -0,0 +1,167 @@
+package pojo;
+
+import constant.UserConstants;
+import jakarta.validation.constraints.NotBlank;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import javax.validation.constraints.Size;
+
+/**
+ * 瀛楀吀鏁版嵁琛� sys_dict_data
+ * 
+ * @author ruoyi
+ */
+public class SysDictData extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 瀛楀吀缂栫爜 */
+    private Long dictCode;
+
+    /** 瀛楀吀鎺掑簭 */
+    private Long dictSort;
+
+    /** 瀛楀吀鏍囩 */
+    private String dictLabel;
+
+    /** 瀛楀吀閿�� */
+    private String dictValue;
+
+    /** 瀛楀吀绫诲瀷 */
+    private String dictType;
+
+    /** 鏍峰紡灞炴�э紙鍏朵粬鏍峰紡鎵╁睍锛� */
+    private String cssClass;
+
+    /** 琛ㄦ牸瀛楀吀鏍峰紡 */
+    private String listClass;
+
+    /** 鏄惁榛樿锛圷鏄� N鍚︼級 */
+    private String isDefault;
+
+    /** 鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+    private String status;
+
+    public Long getDictCode()
+    {
+        return dictCode;
+    }
+
+    public void setDictCode(Long dictCode)
+    {
+        this.dictCode = dictCode;
+    }
+
+    public Long getDictSort()
+    {
+        return dictSort;
+    }
+
+    public void setDictSort(Long dictSort)
+    {
+        this.dictSort = dictSort;
+    }
+
+    @NotBlank(message = "瀛楀吀鏍囩涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "瀛楀吀鏍囩闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+    public String getDictLabel()
+    {
+        return dictLabel;
+    }
+
+    public void setDictLabel(String dictLabel)
+    {
+        this.dictLabel = dictLabel;
+    }
+
+    @NotBlank(message = "瀛楀吀閿�间笉鑳戒负绌�")
+    @Size(min = 0, max = 100, message = "瀛楀吀閿�奸暱搴︿笉鑳借秴杩�100涓瓧绗�")
+    public String getDictValue()
+    {
+        return dictValue;
+    }
+
+    public void setDictValue(String dictValue)
+    {
+        this.dictValue = dictValue;
+    }
+
+    @NotBlank(message = "瀛楀吀绫诲瀷涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+    public String getDictType()
+    {
+        return dictType;
+    }
+
+    public void setDictType(String dictType)
+    {
+        this.dictType = dictType;
+    }
+
+    @Size(min = 0, max = 100, message = "鏍峰紡灞炴�ч暱搴︿笉鑳借秴杩�100涓瓧绗�")
+    public String getCssClass()
+    {
+        return cssClass;
+    }
+
+    public void setCssClass(String cssClass)
+    {
+        this.cssClass = cssClass;
+    }
+
+    public String getListClass()
+    {
+        return listClass;
+    }
+
+    public void setListClass(String listClass)
+    {
+        this.listClass = listClass;
+    }
+
+    public boolean getDefault()
+    {
+        return UserConstants.YES.equals(this.isDefault);
+    }
+
+    public String getIsDefault()
+    {
+        return isDefault;
+    }
+
+    public void setIsDefault(String isDefault)
+    {
+        this.isDefault = isDefault;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+    
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("dictCode", getDictCode())
+            .append("dictSort", getDictSort())
+            .append("dictLabel", getDictLabel())
+            .append("dictValue", getDictValue())
+            .append("dictType", getDictType())
+            .append("cssClass", getCssClass())
+            .append("listClass", getListClass())
+            .append("isDefault", getIsDefault())
+            .append("status", getStatus())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}
diff --git a/ycl-common/src/main/java/utils/DictUtils.java b/ycl-common/src/main/java/utils/DictUtils.java
new file mode 100644
index 0000000..80babf1
--- /dev/null
+++ b/ycl-common/src/main/java/utils/DictUtils.java
@@ -0,0 +1,186 @@
+package utils;
+
+import com.alibaba.fastjson2.JSONArray;
+import constant.CacheConstants;
+import pojo.SysDictData;
+import utils.redis.RedisCache;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 瀛楀吀宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+public class DictUtils
+{
+    /**
+     * 鍒嗛殧绗�
+     */
+    public static final String SEPARATOR = ",";
+
+    /**
+     * 璁剧疆瀛楀吀缂撳瓨
+     * 
+     * @param key 鍙傛暟閿�
+     * @param dictDatas 瀛楀吀鏁版嵁鍒楄〃
+     */
+    public static void setDictCache(String key, List<SysDictData> dictDatas)
+    {
+        SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas);
+    }
+
+    /**
+     * 鑾峰彇瀛楀吀缂撳瓨
+     * 
+     * @param key 鍙傛暟閿�
+     * @return dictDatas 瀛楀吀鏁版嵁鍒楄〃
+     */
+    public static List<SysDictData> getDictCache(String key)
+    {
+        JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
+        if (StringUtils.isNotNull(arrayCache))
+        {
+            return arrayCache.toList(SysDictData.class);
+        }
+        return null;
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏稿�艰幏鍙栧瓧鍏告爣绛�
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param dictValue 瀛楀吀鍊�
+     * @return 瀛楀吀鏍囩
+     */
+    public static String getDictLabel(String dictType, String dictValue)
+    {
+        return getDictLabel(dictType, dictValue, SEPARATOR);
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏告爣绛捐幏鍙栧瓧鍏稿��
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param dictLabel 瀛楀吀鏍囩
+     * @return 瀛楀吀鍊�
+     */
+    public static String getDictValue(String dictType, String dictLabel)
+    {
+        return getDictValue(dictType, dictLabel, SEPARATOR);
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏稿�艰幏鍙栧瓧鍏告爣绛�
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param dictValue 瀛楀吀鍊�
+     * @param separator 鍒嗛殧绗�
+     * @return 瀛楀吀鏍囩
+     */
+    public static String getDictLabel(String dictType, String dictValue, String separator)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        List<SysDictData> datas = getDictCache(dictType);
+
+        if (StringUtils.isNotNull(datas))
+        {
+            if (StringUtils.containsAny(separator, dictValue))
+            {
+                for (SysDictData dict : datas)
+                {
+                    for (String value : dictValue.split(separator))
+                    {
+                        if (value.equals(dict.getDictValue()))
+                        {
+                            propertyString.append(dict.getDictLabel()).append(separator);
+                            break;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for (SysDictData dict : datas)
+                {
+                    if (dictValue.equals(dict.getDictValue()))
+                    {
+                        return dict.getDictLabel();
+                    }
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏告爣绛捐幏鍙栧瓧鍏稿��
+     * 
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param dictLabel 瀛楀吀鏍囩
+     * @param separator 鍒嗛殧绗�
+     * @return 瀛楀吀鍊�
+     */
+    public static String getDictValue(String dictType, String dictLabel, String separator)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        List<SysDictData> datas = getDictCache(dictType);
+
+        if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas))
+        {
+            for (SysDictData dict : datas)
+            {
+                for (String label : dictLabel.split(separator))
+                {
+                    if (label.equals(dict.getDictLabel()))
+                    {
+                        propertyString.append(dict.getDictValue()).append(separator);
+                        break;
+                    }
+                }
+            }
+        }
+        else
+        {
+            for (SysDictData dict : datas)
+            {
+                if (dictLabel.equals(dict.getDictLabel()))
+                {
+                    return dict.getDictValue();
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 鍒犻櫎鎸囧畾瀛楀吀缂撳瓨
+     * 
+     * @param key 瀛楀吀閿�
+     */
+    public static void removeDictCache(String key)
+    {
+        SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key));
+    }
+
+    /**
+     * 娓呯┖瀛楀吀缂撳瓨
+     */
+    public static void clearDictCache()
+    {
+        Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.SYS_DICT_KEY + "*");
+        SpringUtils.getBean(RedisCache.class).deleteObject(keys);
+    }
+
+    /**
+     * 璁剧疆cache key
+     * 
+     * @param configKey 鍙傛暟閿�
+     * @return 缂撳瓨閿甼ey
+     */
+    public static String getCacheKey(String configKey)
+    {
+        return CacheConstants.SYS_DICT_KEY + configKey;
+    }
+}
diff --git a/ycl-common/src/main/java/utils/MessageUtils.java b/ycl-common/src/main/java/utils/MessageUtils.java
new file mode 100644
index 0000000..a053792
--- /dev/null
+++ b/ycl-common/src/main/java/utils/MessageUtils.java
@@ -0,0 +1,25 @@
+package utils;
+
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
+
+/**
+ * 鑾峰彇i18n璧勬簮鏂囦欢
+ * 
+ * @author ruoyi
+ */
+public class MessageUtils
+{
+    /**
+     * 鏍规嵁娑堟伅閿拰鍙傛暟 鑾峰彇娑堟伅 濮旀墭缁檚pring messageSource
+     *
+     * @param code 娑堟伅閿�
+     * @param args 鍙傛暟
+     * @return 鑾峰彇鍥介檯鍖栫炕璇戝��
+     */
+    public static String message(String code, Object... args)
+    {
+        MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
+        return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
+    }
+}
diff --git a/ycl-common/src/main/java/utils/SpringUtils.java b/ycl-common/src/main/java/utils/SpringUtils.java
new file mode 100644
index 0000000..54f8d6f
--- /dev/null
+++ b/ycl-common/src/main/java/utils/SpringUtils.java
@@ -0,0 +1,157 @@
+package utils;
+
+import org.springframework.aop.framework.AopContext;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * spring宸ュ叿绫� 鏂逛究鍦ㄩ潪spring绠$悊鐜涓幏鍙朾ean
+ * 
+ * @author ruoyi
+ */
+@Component
+public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware 
+{
+    /** Spring搴旂敤涓婁笅鏂囩幆澧� */
+    private static ConfigurableListableBeanFactory beanFactory;
+
+    private static ApplicationContext applicationContext;
+
+    @Override
+    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException 
+    {
+        SpringUtils.beanFactory = beanFactory;
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException 
+    {
+        SpringUtils.applicationContext = applicationContext;
+    }
+
+    /**
+     * 鑾峰彇瀵硅薄
+     *
+     * @param name
+     * @return Object 涓�涓互鎵�缁欏悕瀛楁敞鍐岀殑bean鐨勫疄渚�
+     * @throws BeansException
+     *
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String name) throws BeansException
+    {
+        return (T) beanFactory.getBean(name);
+    }
+
+    /**
+     * 鑾峰彇绫诲瀷涓簉equiredType鐨勫璞�
+     *
+     * @param clz
+     * @return
+     * @throws BeansException
+     *
+     */
+    public static <T> T getBean(Class<T> clz) throws BeansException
+    {
+        T result = (T) beanFactory.getBean(clz);
+        return result;
+    }
+
+    /**
+     * 濡傛灉BeanFactory鍖呭惈涓�涓笌鎵�缁欏悕绉板尮閰嶇殑bean瀹氫箟锛屽垯杩斿洖true
+     *
+     * @param name
+     * @return boolean
+     */
+    public static boolean containsBean(String name)
+    {
+        return beanFactory.containsBean(name);
+    }
+
+    /**
+     * 鍒ゆ柇浠ョ粰瀹氬悕瀛楁敞鍐岀殑bean瀹氫箟鏄竴涓猻ingleton杩樻槸涓�涓猵rototype銆� 濡傛灉涓庣粰瀹氬悕瀛楃浉搴旂殑bean瀹氫箟娌℃湁琚壘鍒帮紝灏嗕細鎶涘嚭涓�涓紓甯革紙NoSuchBeanDefinitionException锛�
+     *
+     * @param name
+     * @return boolean
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.isSingleton(name);
+    }
+
+    /**
+     * @param name
+     * @return Class 娉ㄥ唽瀵硅薄鐨勭被鍨�
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getType(name);
+    }
+
+    /**
+     * 濡傛灉缁欏畾鐨刡ean鍚嶅瓧鍦╞ean瀹氫箟涓湁鍒悕锛屽垯杩斿洖杩欎簺鍒悕
+     *
+     * @param name
+     * @return
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getAliases(name);
+    }
+
+    /**
+     * 鑾峰彇aop浠g悊瀵硅薄
+     * 
+     * @param invoker
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getAopProxy(T invoker)
+    {
+        return (T) AopContext.currentProxy();
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鐨勭幆澧冮厤缃紝鏃犻厤缃繑鍥瀗ull
+     *
+     * @return 褰撳墠鐨勭幆澧冮厤缃�
+     */
+    public static String[] getActiveProfiles()
+    {
+        return applicationContext.getEnvironment().getActiveProfiles();
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鐨勭幆澧冮厤缃紝褰撴湁澶氫釜鐜閰嶇疆鏃讹紝鍙幏鍙栫涓�涓�
+     *
+     * @return 褰撳墠鐨勭幆澧冮厤缃�
+     */
+    public static String getActiveProfile()
+    {
+        final String[] activeProfiles = getActiveProfiles();
+        return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
+    }
+
+    /**
+     * 鑾峰彇閰嶇疆鏂囦欢涓殑鍊�
+     *
+     * @param key 閰嶇疆鏂囦欢鐨刱ey
+     * @return 褰撳墠鐨勯厤缃枃浠剁殑鍊�
+     *
+     */
+    public static String getRequiredProperty(String key)
+    {
+        return applicationContext.getEnvironment().getRequiredProperty(key);
+    }
+}
diff --git a/ycl-common/src/main/java/utils/file/FileTypeUtils.java b/ycl-common/src/main/java/utils/file/FileTypeUtils.java
new file mode 100644
index 0000000..16aa2cf
--- /dev/null
+++ b/ycl-common/src/main/java/utils/file/FileTypeUtils.java
@@ -0,0 +1,77 @@
+package utils.file;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.File;
+
+/**
+ * 鏂囦欢绫诲瀷宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class FileTypeUtils
+{
+    /**
+     * 鑾峰彇鏂囦欢绫诲瀷
+     * <p>
+     * 渚嬪: ruoyi.txt, 杩斿洖: txt
+     * 
+     * @param file 鏂囦欢鍚�
+     * @return 鍚庣紑锛堜笉鍚�".")
+     */
+    public static String getFileType(File file)
+    {
+        if (null == file)
+        {
+            return StringUtils.EMPTY;
+        }
+        return getFileType(file.getName());
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢绫诲瀷
+     * <p>
+     * 渚嬪: ruoyi.txt, 杩斿洖: txt
+     *
+     * @param fileName 鏂囦欢鍚�
+     * @return 鍚庣紑锛堜笉鍚�".")
+     */
+    public static String getFileType(String fileName)
+    {
+        int separatorIndex = fileName.lastIndexOf(".");
+        if (separatorIndex < 0)
+        {
+            return "";
+        }
+        return fileName.substring(separatorIndex + 1).toLowerCase();
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢绫诲瀷
+     * 
+     * @param photoByte 鏂囦欢瀛楄妭鐮�
+     * @return 鍚庣紑锛堜笉鍚�".")
+     */
+    public static String getFileExtendName(byte[] photoByte)
+    {
+        String strFileExtendName = "JPG";
+        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
+                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
+        {
+            strFileExtendName = "GIF";
+        }
+        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
+        {
+            strFileExtendName = "JPG";
+        }
+        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
+        {
+            strFileExtendName = "BMP";
+        }
+        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
+        {
+            strFileExtendName = "PNG";
+        }
+        return strFileExtendName;
+    }
+}
\ No newline at end of file
diff --git a/ycl-common/src/main/java/utils/file/FileUploadUtils.java b/ycl-common/src/main/java/utils/file/FileUploadUtils.java
new file mode 100644
index 0000000..03e8799
--- /dev/null
+++ b/ycl-common/src/main/java/utils/file/FileUploadUtils.java
@@ -0,0 +1,233 @@
+package utils.file;
+
+import config.PlatformConfig;
+import constant.Constants;
+import exception.file.FileNameLengthLimitExceededException;
+import exception.file.FileSizeLimitExceededException;
+import exception.file.InvalidExtensionException;
+import org.apache.commons.io.FilenameUtils;
+import org.springframework.web.multipart.MultipartFile;
+import utils.DateUtils;
+import utils.StringUtils;
+import utils.uuid.Seq;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.Objects;
+
+/**
+ * 鏂囦欢涓婁紶宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class FileUploadUtils
+{
+    /**
+     * 榛樿澶у皬 50M
+     */
+    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
+
+    /**
+     * 榛樿鐨勬枃浠跺悕鏈�澶ч暱搴� 100
+     */
+    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
+
+    /**
+     * 榛樿涓婁紶鐨勫湴鍧�
+     */
+    private static String defaultBaseDir = PlatformConfig.getProfile();
+
+    public static void setDefaultBaseDir(String defaultBaseDir)
+    {
+        FileUploadUtils.defaultBaseDir = defaultBaseDir;
+    }
+
+    public static String getDefaultBaseDir()
+    {
+        return defaultBaseDir;
+    }
+
+    /**
+     * 浠ラ粯璁ら厤缃繘琛屾枃浠朵笂浼�
+     *
+     * @param file 涓婁紶鐨勬枃浠�
+     * @return 鏂囦欢鍚嶇О
+     * @throws Exception
+     */
+    public static final String upload(MultipartFile file) throws IOException
+    {
+        try
+        {
+            return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+        }
+        catch (Exception e)
+        {
+            throw new IOException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 鏍规嵁鏂囦欢璺緞涓婁紶
+     *
+     * @param baseDir 鐩稿搴旂敤鐨勫熀鐩綍
+     * @param file 涓婁紶鐨勬枃浠�
+     * @return 鏂囦欢鍚嶇О
+     * @throws IOException
+     */
+    public static final String upload(String baseDir, MultipartFile file) throws IOException
+    {
+        try
+        {
+            return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+        }
+        catch (Exception e)
+        {
+            throw new IOException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 鏂囦欢涓婁紶
+     *
+     * @param baseDir 鐩稿搴旂敤鐨勫熀鐩綍
+     * @param file 涓婁紶鐨勬枃浠�
+     * @param allowedExtension 涓婁紶鏂囦欢绫诲瀷
+     * @return 杩斿洖涓婁紶鎴愬姛鐨勬枃浠跺悕
+     * @throws FileSizeLimitExceededException 濡傛灉瓒呭嚭鏈�澶уぇ灏�
+     * @throws FileNameLengthLimitExceededException 鏂囦欢鍚嶅お闀�
+     * @throws IOException 姣斿璇诲啓鏂囦欢鍑洪敊鏃�
+     * @throws InvalidExtensionException 鏂囦欢鏍¢獙寮傚父
+     */
+    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
+            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
+            InvalidExtensionException
+    {
+        int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
+        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
+        {
+            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
+        }
+
+        assertAllowed(file, allowedExtension);
+
+        String fileName = extractFilename(file);
+
+        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
+        file.transferTo(Paths.get(absPath));
+        return getPathFileName(baseDir, fileName);
+    }
+
+    /**
+     * 缂栫爜鏂囦欢鍚�
+     */
+    public static final String extractFilename(MultipartFile file)
+    {
+        return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
+                FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
+    }
+
+    public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
+    {
+        File desc = new File(uploadDir + File.separator + fileName);
+
+        if (!desc.exists())
+        {
+            if (!desc.getParentFile().exists())
+            {
+                desc.getParentFile().mkdirs();
+            }
+        }
+        return desc;
+    }
+
+    public static final String getPathFileName(String uploadDir, String fileName) throws IOException
+    {
+        int dirLastIndex = PlatformConfig.getProfile().length() + 1;
+        String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
+        return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
+    }
+
+    /**
+     * 鏂囦欢澶у皬鏍¢獙
+     *
+     * @param file 涓婁紶鐨勬枃浠�
+     * @return
+     * @throws FileSizeLimitExceededException 濡傛灉瓒呭嚭鏈�澶уぇ灏�
+     * @throws InvalidExtensionException
+     */
+    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
+            throws FileSizeLimitExceededException, InvalidExtensionException
+    {
+        long size = file.getSize();
+        if (size > DEFAULT_MAX_SIZE)
+        {
+            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
+        }
+
+        String fileName = file.getOriginalFilename();
+        String extension = getExtension(file);
+        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
+        {
+            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
+            {
+                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
+                        fileName);
+            }
+            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
+            {
+                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
+                        fileName);
+            }
+            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
+            {
+                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
+                        fileName);
+            }
+            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
+            {
+                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
+                        fileName);
+            }
+            else
+            {
+                throw new InvalidExtensionException(allowedExtension, extension, fileName);
+            }
+        }
+    }
+
+    /**
+     * 鍒ゆ柇MIME绫诲瀷鏄惁鏄厑璁哥殑MIME绫诲瀷
+     *
+     * @param extension
+     * @param allowedExtension
+     * @return
+     */
+    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
+    {
+        for (String str : allowedExtension)
+        {
+            if (str.equalsIgnoreCase(extension))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢鍚嶇殑鍚庣紑
+     *
+     * @param file 琛ㄥ崟鏂囦欢
+     * @return 鍚庣紑鍚�
+     */
+    public static final String getExtension(MultipartFile file)
+    {
+        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
+        if (StringUtils.isEmpty(extension))
+        {
+            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
+        }
+        return extension;
+    }
+}
diff --git a/ycl-common/src/main/java/utils/file/FileUtils.java b/ycl-common/src/main/java/utils/file/FileUtils.java
new file mode 100644
index 0000000..9aa3e7b
--- /dev/null
+++ b/ycl-common/src/main/java/utils/file/FileUtils.java
@@ -0,0 +1,286 @@
+package utils.file;
+
+import config.PlatformConfig;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import utils.DateUtils;
+import utils.StringUtils;
+import utils.uuid.IdUtils;
+
+import java.io.*;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 鏂囦欢澶勭悊宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+public class FileUtils
+{
+    public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
+
+    /**
+     * 杈撳嚭鎸囧畾鏂囦欢鐨刡yte鏁扮粍
+     * 
+     * @param filePath 鏂囦欢璺緞
+     * @param os 杈撳嚭娴�
+     * @return
+     */
+    public static void writeBytes(String filePath, OutputStream os) throws IOException
+    {
+        FileInputStream fis = null;
+        try
+        {
+            File file = new File(filePath);
+            if (!file.exists())
+            {
+                throw new FileNotFoundException(filePath);
+            }
+            fis = new FileInputStream(file);
+            byte[] b = new byte[1024];
+            int length;
+            while ((length = fis.read(b)) > 0)
+            {
+                os.write(b, 0, length);
+            }
+        }
+        catch (IOException e)
+        {
+            throw e;
+        }
+        finally
+        {
+            IOUtils.close(os);
+            IOUtils.close(fis);
+        }
+    }
+
+    /**
+     * 鍐欐暟鎹埌鏂囦欢涓�
+     *
+     * @param data 鏁版嵁
+     * @return 鐩爣鏂囦欢
+     * @throws IOException IO寮傚父
+     */
+    public static String writeImportBytes(byte[] data) throws IOException
+    {
+        return writeBytes(data, PlatformConfig.getImportPath());
+    }
+
+    /**
+     * 鍐欐暟鎹埌鏂囦欢涓�
+     *
+     * @param data 鏁版嵁
+     * @param uploadDir 鐩爣鏂囦欢
+     * @return 鐩爣鏂囦欢
+     * @throws IOException IO寮傚父
+     */
+    public static String writeBytes(byte[] data, String uploadDir) throws IOException
+    {
+        FileOutputStream fos = null;
+        String pathName = "";
+        try
+        {
+            String extension = getFileExtendName(data);
+            pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
+            File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName);
+            fos = new FileOutputStream(file);
+            fos.write(data);
+        }
+        finally
+        {
+            IOUtils.close(fos);
+        }
+        return FileUploadUtils.getPathFileName(uploadDir, pathName);
+    }
+
+    /**
+     * 鍒犻櫎鏂囦欢
+     * 
+     * @param filePath 鏂囦欢
+     * @return
+     */
+    public static boolean deleteFile(String filePath)
+    {
+        boolean flag = false;
+        File file = new File(filePath);
+        // 璺緞涓烘枃浠朵笖涓嶄负绌哄垯杩涜鍒犻櫎
+        if (file.isFile() && file.exists())
+        {
+            flag = file.delete();
+        }
+        return flag;
+    }
+
+    /**
+     * 鏂囦欢鍚嶇О楠岃瘉
+     * 
+     * @param filename 鏂囦欢鍚嶇О
+     * @return true 姝e父 false 闈炴硶
+     */
+    public static boolean isValidFilename(String filename)
+    {
+        return filename.matches(FILENAME_PATTERN);
+    }
+
+    /**
+     * 妫�鏌ユ枃浠舵槸鍚﹀彲涓嬭浇
+     * 
+     * @param resource 闇�瑕佷笅杞界殑鏂囦欢
+     * @return true 姝e父 false 闈炴硶
+     */
+    public static boolean checkAllowDownload(String resource)
+    {
+        // 绂佹鐩綍涓婅烦绾у埆
+        if (StringUtils.contains(resource, ".."))
+        {
+            return false;
+        }
+
+        // 妫�鏌ュ厑璁镐笅杞界殑鏂囦欢瑙勫垯
+        if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
+        {
+            return true;
+        }
+
+        // 涓嶅湪鍏佽涓嬭浇鐨勬枃浠惰鍒�
+        return false;
+    }
+
+    /**
+     * 涓嬭浇鏂囦欢鍚嶉噸鏂扮紪鐮�
+     * 
+     * @param request 璇锋眰瀵硅薄
+     * @param fileName 鏂囦欢鍚�
+     * @return 缂栫爜鍚庣殑鏂囦欢鍚�
+     */
+    public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
+    {
+        final String agent = request.getHeader("USER-AGENT");
+        String filename = fileName;
+        if (agent.contains("MSIE"))
+        {
+            // IE娴忚鍣�
+            filename = URLEncoder.encode(filename, "utf-8");
+            filename = filename.replace("+", " ");
+        }
+        else if (agent.contains("Firefox"))
+        {
+            // 鐏嫄娴忚鍣�
+            filename = new String(fileName.getBytes(), "ISO8859-1");
+        }
+        else if (agent.contains("Chrome"))
+        {
+            // google娴忚鍣�
+            filename = URLEncoder.encode(filename, "utf-8");
+        }
+        else
+        {
+            // 鍏跺畠娴忚鍣�
+            filename = URLEncoder.encode(filename, "utf-8");
+        }
+        return filename;
+    }
+
+    /**
+     * 涓嬭浇鏂囦欢鍚嶉噸鏂扮紪鐮�
+     *
+     * @param response 鍝嶅簲瀵硅薄
+     * @param realFileName 鐪熷疄鏂囦欢鍚�
+     */
+    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
+    {
+        String percentEncodedFileName = percentEncode(realFileName);
+
+        StringBuilder contentDispositionValue = new StringBuilder();
+        contentDispositionValue.append("attachment; filename=")
+                .append(percentEncodedFileName)
+                .append(";")
+                .append("filename*=")
+                .append("utf-8''")
+                .append(percentEncodedFileName);
+
+        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
+        response.setHeader("Content-disposition", contentDispositionValue.toString());
+        response.setHeader("download-filename", percentEncodedFileName);
+    }
+
+    /**
+     * 鐧惧垎鍙风紪鐮佸伐鍏锋柟娉�
+     *
+     * @param s 闇�瑕佺櫨鍒嗗彿缂栫爜鐨勫瓧绗︿覆
+     * @return 鐧惧垎鍙风紪鐮佸悗鐨勫瓧绗︿覆
+     */
+    public static String percentEncode(String s) throws UnsupportedEncodingException
+    {
+        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
+        return encode.replaceAll("\\+", "%20");
+    }
+
+    /**
+     * 鑾峰彇鍥惧儚鍚庣紑
+     * 
+     * @param photoByte 鍥惧儚鏁版嵁
+     * @return 鍚庣紑鍚�
+     */
+    public static String getFileExtendName(byte[] photoByte)
+    {
+        String strFileExtendName = "jpg";
+        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
+                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
+        {
+            strFileExtendName = "gif";
+        }
+        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
+        {
+            strFileExtendName = "jpg";
+        }
+        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
+        {
+            strFileExtendName = "bmp";
+        }
+        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
+        {
+            strFileExtendName = "png";
+        }
+        return strFileExtendName;
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢鍚嶇О /profile/upload/2022/04/16/ruoyi.png -- ruoyi.png
+     * 
+     * @param fileName 璺緞鍚嶇О
+     * @return 娌℃湁鏂囦欢璺緞鐨勫悕绉�
+     */
+    public static String getName(String fileName)
+    {
+        if (fileName == null)
+        {
+            return null;
+        }
+        int lastUnixPos = fileName.lastIndexOf('/');
+        int lastWindowsPos = fileName.lastIndexOf('\\');
+        int index = Math.max(lastUnixPos, lastWindowsPos);
+        return fileName.substring(index + 1);
+    }
+
+    /**
+     * 鑾峰彇涓嶅甫鍚庣紑鏂囦欢鍚嶇О /profile/upload/2022/04/16/ruoyi.png -- ruoyi
+     * 
+     * @param fileName 璺緞鍚嶇О
+     * @return 娌℃湁鏂囦欢璺緞鍜屽悗缂�鐨勫悕绉�
+     */
+    public static String getNameNotSuffix(String fileName)
+    {
+        if (fileName == null)
+        {
+            return null;
+        }
+        String baseName = FilenameUtils.getBaseName(fileName);
+        return baseName;
+    }
+}
diff --git a/ycl-common/src/main/java/utils/file/ImageUtils.java b/ycl-common/src/main/java/utils/file/ImageUtils.java
new file mode 100644
index 0000000..1ca8635
--- /dev/null
+++ b/ycl-common/src/main/java/utils/file/ImageUtils.java
@@ -0,0 +1,99 @@
+package utils.file;
+
+import config.PlatformConfig;
+import constant.Constants;
+import org.apache.poi.util.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import utils.StringUtils;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Arrays;
+
+/**
+ * 鍥剧墖澶勭悊宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class ImageUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
+
+    public static byte[] getImage(String imagePath)
+    {
+        InputStream is = getFile(imagePath);
+        try
+        {
+            return IOUtils.toByteArray(is);
+        }
+        catch (Exception e)
+        {
+            log.error("鍥剧墖鍔犺浇寮傚父 {}", e);
+            return null;
+        }
+        finally
+        {
+            IOUtils.closeQuietly(is);
+        }
+    }
+
+    public static InputStream getFile(String imagePath)
+    {
+        try
+        {
+            byte[] result = readFile(imagePath);
+            result = Arrays.copyOf(result, result.length);
+            return new ByteArrayInputStream(result);
+        }
+        catch (Exception e)
+        {
+            log.error("鑾峰彇鍥剧墖寮傚父 {}", e);
+        }
+        return null;
+    }
+
+    /**
+     * 璇诲彇鏂囦欢涓哄瓧鑺傛暟鎹�
+     * 
+     * @param url 鍦板潃
+     * @return 瀛楄妭鏁版嵁
+     */
+    public static byte[] readFile(String url)
+    {
+        InputStream in = null;
+        try
+        {
+            if (url.startsWith("http"))
+            {
+                // 缃戠粶鍦板潃
+                URL urlObj = new URL(url);
+                URLConnection urlConnection = urlObj.openConnection();
+                urlConnection.setConnectTimeout(30 * 1000);
+                urlConnection.setReadTimeout(60 * 1000);
+                urlConnection.setDoInput(true);
+                in = urlConnection.getInputStream();
+            }
+            else
+            {
+                // 鏈満鍦板潃
+                String localPath = PlatformConfig.getProfile();
+                String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
+                in = new FileInputStream(downloadPath);
+            }
+            return IOUtils.toByteArray(in);
+        }
+        catch (Exception e)
+        {
+            log.error("鑾峰彇鏂囦欢璺緞寮傚父 {}", e);
+            return null;
+        }
+        finally
+        {
+            IOUtils.closeQuietly(in);
+        }
+    }
+}
diff --git a/ycl-common/src/main/java/utils/file/MimeTypeUtils.java b/ycl-common/src/main/java/utils/file/MimeTypeUtils.java
new file mode 100644
index 0000000..5e3603a
--- /dev/null
+++ b/ycl-common/src/main/java/utils/file/MimeTypeUtils.java
@@ -0,0 +1,59 @@
+package utils.file;
+
+/**
+ * 濯掍綋绫诲瀷宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+public class MimeTypeUtils
+{
+    public static final String IMAGE_PNG = "image/png";
+
+    public static final String IMAGE_JPG = "image/jpg";
+
+    public static final String IMAGE_JPEG = "image/jpeg";
+
+    public static final String IMAGE_BMP = "image/bmp";
+
+    public static final String IMAGE_GIF = "image/gif";
+    
+    public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
+
+    public static final String[] FLASH_EXTENSION = { "swf", "flv" };
+
+    public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
+            "asf", "rm", "rmvb" };
+
+    public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
+
+    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
+            // 鍥剧墖
+            "bmp", "gif", "jpg", "jpeg", "png",
+            // word excel powerpoint
+            "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
+            // 鍘嬬缉鏂囦欢
+            "rar", "zip", "gz", "bz2",
+            // 瑙嗛鏍煎紡
+            "mp4", "avi", "rmvb",
+            // pdf
+            "pdf" };
+
+    public static String getExtension(String prefix)
+    {
+        switch (prefix)
+        {
+            case IMAGE_PNG:
+                return "png";
+            case IMAGE_JPG:
+                return "jpg";
+            case IMAGE_JPEG:
+                return "jpeg";
+            case IMAGE_BMP:
+                return "bmp";
+            case IMAGE_GIF:
+                return "gif";
+            default:
+                return "";
+        }
+    }
+}
diff --git a/ycl-common/src/main/java/utils/poi/ExcelHandlerAdapter.java b/ycl-common/src/main/java/utils/poi/ExcelHandlerAdapter.java
new file mode 100644
index 0000000..18ae051
--- /dev/null
+++ b/ycl-common/src/main/java/utils/poi/ExcelHandlerAdapter.java
@@ -0,0 +1,24 @@
+package utils.poi;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Workbook;
+
+/**
+ * Excel鏁版嵁鏍煎紡澶勭悊閫傞厤鍣�
+ * 
+ * @author ruoyi
+ */
+public interface ExcelHandlerAdapter
+{
+    /**
+     * 鏍煎紡鍖�
+     * 
+     * @param value 鍗曞厓鏍兼暟鎹��
+     * @param args excel娉ㄨВargs鍙傛暟缁�
+     * @param cell 鍗曞厓鏍煎璞�
+     * @param wb 宸ヤ綔绨垮璞�
+     *
+     * @return 澶勭悊鍚庣殑鍊�
+     */
+    Object format(Object value, String[] args, Cell cell, Workbook wb);
+}
diff --git a/ycl-common/src/main/java/utils/poi/ExcelUtil.java b/ycl-common/src/main/java/utils/poi/ExcelUtil.java
new file mode 100644
index 0000000..7c2c8d9
--- /dev/null
+++ b/ycl-common/src/main/java/utils/poi/ExcelUtil.java
@@ -0,0 +1,1713 @@
+package utils.poi;
+
+import annotation.Excel;
+import annotation.Excels;
+import config.PlatformConfig;
+import exception.UtilException;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.RegExUtils;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import org.apache.poi.hssf.usermodel.*;
+import org.apache.poi.ooxml.POIXMLDocumentPart;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellRangeAddressList;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.*;
+import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import pojo.AjaxResult;
+import utils.DateUtils;
+import utils.DictUtils;
+import utils.StringUtils;
+import utils.file.FileTypeUtils;
+import utils.file.FileUtils;
+import utils.file.ImageUtils;
+import utils.reflect.ReflectUtils;
+import utils.text.Convert;
+
+import java.io.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Excel鐩稿叧澶勭悊
+ * 
+ * @author ruoyi
+ */
+public class ExcelUtil<T>
+{
+    private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
+
+    public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
+
+    public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
+
+    /**
+     * 鐢ㄤ簬dictType灞炴�ф暟鎹瓨鍌紝閬垮厤閲嶅鏌ョ紦瀛�
+     */
+    public Map<String, String> sysDictMap = new HashMap<String, String>();
+
+    /**
+     * Excel sheet鏈�澶ц鏁帮紝榛樿65536
+     */
+    public static final int sheetSize = 65536;
+
+    /**
+     * 宸ヤ綔琛ㄥ悕绉�
+     */
+    private String sheetName;
+
+    /**
+     * 瀵煎嚭绫诲瀷锛圗XPORT:瀵煎嚭鏁版嵁锛汭MPORT锛氬鍏ユā鏉匡級
+     */
+    private Excel.Type type;
+
+    /**
+     * 宸ヤ綔钖勫璞�
+     */
+    private Workbook wb;
+
+    /**
+     * 宸ヤ綔琛ㄥ璞�
+     */
+    private Sheet sheet;
+
+    /**
+     * 鏍峰紡鍒楄〃
+     */
+    private Map<String, CellStyle> styles;
+
+    /**
+     * 瀵煎叆瀵煎嚭鏁版嵁鍒楄〃
+     */
+    private List<T> list;
+
+    /**
+     * 娉ㄨВ鍒楄〃
+     */
+    private List<Object[]> fields;
+
+    /**
+     * 褰撳墠琛屽彿
+     */
+    private int rownum;
+
+    /**
+     * 鏍囬
+     */
+    private String title;
+
+    /**
+     * 鏈�澶ч珮搴�
+     */
+    private short maxHeight;
+
+    /**
+     * 鍚堝苟鍚庢渶鍚庤鏁�
+     */
+    private int subMergedLastRowNum = 0;
+
+    /**
+     * 鍚堝苟鍚庡紑濮嬭鏁�
+     */
+    private int subMergedFirstRowNum = 1;
+
+    /**
+     * 瀵硅薄鐨勫瓙鍒楄〃鏂规硶
+     */
+    private Method subMethod;
+
+    /**
+     * 瀵硅薄鐨勫瓙鍒楄〃灞炴��
+     */
+    private List<Field> subFields;
+
+    /**
+     * 缁熻鍒楄〃
+     */
+    private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
+
+    /**
+     * 鏁板瓧鏍煎紡
+     */
+    private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
+
+    /**
+     * 瀹炰綋瀵硅薄
+     */
+    public Class<T> clazz;
+
+    /**
+     * 闇�瑕佹帓闄ゅ垪灞炴��
+     */
+    public String[] excludeFields;
+
+    public ExcelUtil(Class<T> clazz)
+    {
+        this.clazz = clazz;
+    }
+
+    /**
+     * 闅愯棌Excel涓垪灞炴��
+     *
+     * @param fields 鍒楀睘鎬у悕 绀轰緥[鍗曚釜"name"/澶氫釜"id","name"]
+     * @throws Exception
+     */
+    public void hideColumn(String... fields)
+    {
+        this.excludeFields = fields;
+    }
+
+    public void init(List<T> list, String sheetName, String title, Excel.Type type)
+    {
+        if (list == null)
+        {
+            list = new ArrayList<T>();
+        }
+        this.list = list;
+        this.sheetName = sheetName;
+        this.type = type;
+        this.title = title;
+        createExcelField();
+        createWorkbook();
+        createTitle();
+        createSubHead();
+    }
+
+    /**
+     * 鍒涘缓excel绗竴琛屾爣棰�
+     */
+    public void createTitle()
+    {
+        if (StringUtils.isNotEmpty(title))
+        {
+            subMergedFirstRowNum++;
+            subMergedLastRowNum++;
+            int titleLastCol = this.fields.size() - 1;
+            if (isSubList())
+            {
+                titleLastCol = titleLastCol + subFields.size() - 1;
+            }
+            Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
+            titleRow.setHeightInPoints(30);
+            Cell titleCell = titleRow.createCell(0);
+            titleCell.setCellStyle(styles.get("title"));
+            titleCell.setCellValue(title);
+            sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol));
+        }
+    }
+
+    /**
+     * 鍒涘缓瀵硅薄鐨勫瓙鍒楄〃鍚嶇О
+     */
+    public void createSubHead()
+    {
+        if (isSubList())
+        {
+            subMergedFirstRowNum++;
+            subMergedLastRowNum++;
+            Row subRow = sheet.createRow(rownum);
+            int excelNum = 0;
+            for (Object[] objects : fields)
+            {
+                Excel attr = (Excel) objects[1];
+                Cell headCell1 = subRow.createCell(excelNum);
+                headCell1.setCellValue(attr.name());
+                headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+                excelNum++;
+            }
+            int headFirstRow = excelNum - 1;
+            int headLastRow = headFirstRow + subFields.size() - 1;
+            if (headLastRow > headFirstRow)
+            {
+                sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow));
+            }
+            rownum++;
+        }
+    }
+
+    /**
+     * 瀵筫xcel琛ㄥ崟榛樿绗竴涓储寮曞悕杞崲鎴恖ist
+     * 
+     * @param is 杈撳叆娴�
+     * @return 杞崲鍚庨泦鍚�
+     */
+    public List<T> importExcel(InputStream is)
+    {
+        List<T> list = null;
+        try
+        {
+            list = importExcel(is, 0);
+        }
+        catch (Exception e)
+        {
+            log.error("瀵煎叆Excel寮傚父{}", e.getMessage());
+            throw new UtilException(e.getMessage());
+        }
+        finally
+        {
+            IOUtils.closeQuietly(is);
+        }
+        return list;
+    }
+
+    /**
+     * 瀵筫xcel琛ㄥ崟榛樿绗竴涓储寮曞悕杞崲鎴恖ist
+     * 
+     * @param is 杈撳叆娴�
+     * @param titleNum 鏍囬鍗犵敤琛屾暟
+     * @return 杞崲鍚庨泦鍚�
+     */
+    public List<T> importExcel(InputStream is, int titleNum) throws Exception
+    {
+        return importExcel(StringUtils.EMPTY, is, titleNum);
+    }
+
+    /**
+     * 瀵筫xcel琛ㄥ崟鎸囧畾琛ㄦ牸绱㈠紩鍚嶈浆鎹㈡垚list
+     * 
+     * @param sheetName 琛ㄦ牸绱㈠紩鍚�
+     * @param titleNum 鏍囬鍗犵敤琛屾暟
+     * @param is 杈撳叆娴�
+     * @return 杞崲鍚庨泦鍚�
+     */
+    public List<T> importExcel(String sheetName, InputStream is, int titleNum) throws Exception
+    {
+        this.type = Excel.Type.IMPORT;
+        this.wb = WorkbookFactory.create(is);
+        List<T> list = new ArrayList<T>();
+        // 濡傛灉鎸囧畾sheet鍚�,鍒欏彇鎸囧畾sheet涓殑鍐呭 鍚﹀垯榛樿鎸囧悜绗�1涓猻heet
+        Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0);
+        if (sheet == null)
+        {
+            throw new IOException("鏂囦欢sheet涓嶅瓨鍦�");
+        }
+        boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook);
+        Map<String, PictureData> pictures;
+        if (isXSSFWorkbook)
+        {
+            pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb);
+        }
+        else
+        {
+            pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb);
+        }
+        // 鑾峰彇鏈�鍚庝竴涓潪绌鸿鐨勮涓嬫爣锛屾瘮濡傛�昏鏁颁负n锛屽垯杩斿洖鐨勪负n-1
+        int rows = sheet.getLastRowNum();
+        if (rows > 0)
+        {
+            // 瀹氫箟涓�涓猰ap鐢ㄤ簬瀛樻斁excel鍒楃殑搴忓彿鍜宖ield.
+            Map<String, Integer> cellMap = new HashMap<String, Integer>();
+            // 鑾峰彇琛ㄥご
+            Row heard = sheet.getRow(titleNum);
+            for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++)
+            {
+                Cell cell = heard.getCell(i);
+                if (StringUtils.isNotNull(cell))
+                {
+                    String value = this.getCellValue(heard, i).toString();
+                    cellMap.put(value, i);
+                }
+                else
+                {
+                    cellMap.put(null, i);
+                }
+            }
+            // 鏈夋暟鎹椂鎵嶅鐞� 寰楀埌绫荤殑鎵�鏈塮ield.
+            List<Object[]> fields = this.getFields();
+            Map<Integer, Object[]> fieldsMap = new HashMap<Integer, Object[]>();
+            for (Object[] objects : fields)
+            {
+                Excel attr = (Excel) objects[1];
+                Integer column = cellMap.get(attr.name());
+                if (column != null)
+                {
+                    fieldsMap.put(column, objects);
+                }
+            }
+            for (int i = titleNum + 1; i <= rows; i++)
+            {
+                // 浠庣2琛屽紑濮嬪彇鏁版嵁,榛樿绗竴琛屾槸琛ㄥご.
+                Row row = sheet.getRow(i);
+                // 鍒ゆ柇褰撳墠琛屾槸鍚︽槸绌鸿
+                if (isRowEmpty(row))
+                {
+                    continue;
+                }
+                T entity = null;
+                for (Map.Entry<Integer, Object[]> entry : fieldsMap.entrySet())
+                {
+                    Object val = this.getCellValue(row, entry.getKey());
+
+                    // 濡傛灉涓嶅瓨鍦ㄥ疄渚嬪垯鏂板缓.
+                    entity = (entity == null ? clazz.newInstance() : entity);
+                    // 浠巑ap涓緱鍒板搴斿垪鐨刦ield.
+                    Field field = (Field) entry.getValue()[0];
+                    Excel attr = (Excel) entry.getValue()[1];
+                    // 鍙栧緱绫诲瀷,骞舵牴鎹璞$被鍨嬭缃��.
+                    Class<?> fieldType = field.getType();
+                    if (String.class == fieldType)
+                    {
+                        String s = Convert.toStr(val);
+                        if (StringUtils.endsWith(s, ".0"))
+                        {
+                            val = StringUtils.substringBefore(s, ".0");
+                        }
+                        else
+                        {
+                            String dateFormat = field.getAnnotation(Excel.class).dateFormat();
+                            if (StringUtils.isNotEmpty(dateFormat))
+                            {
+                                val = parseDateToStr(dateFormat, val);
+                            }
+                            else
+                            {
+                                val = Convert.toStr(val);
+                            }
+                        }
+                    }
+                    else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
+                    {
+                        val = Convert.toInt(val);
+                    }
+                    else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
+                    {
+                        val = Convert.toLong(val);
+                    }
+                    else if (Double.TYPE == fieldType || Double.class == fieldType)
+                    {
+                        val = Convert.toDouble(val);
+                    }
+                    else if (Float.TYPE == fieldType || Float.class == fieldType)
+                    {
+                        val = Convert.toFloat(val);
+                    }
+                    else if (BigDecimal.class == fieldType)
+                    {
+                        val = Convert.toBigDecimal(val);
+                    }
+                    else if (Date.class == fieldType)
+                    {
+                        if (val instanceof String)
+                        {
+                            val = DateUtils.parseDate(val);
+                        }
+                        else if (val instanceof Double)
+                        {
+                            val = DateUtil.getJavaDate((Double) val);
+                        }
+                    }
+                    else if (Boolean.TYPE == fieldType || Boolean.class == fieldType)
+                    {
+                        val = Convert.toBool(val, false);
+                    }
+                    if (StringUtils.isNotNull(fieldType))
+                    {
+                        String propertyName = field.getName();
+                        if (StringUtils.isNotEmpty(attr.targetAttr()))
+                        {
+                            propertyName = field.getName() + "." + attr.targetAttr();
+                        }
+                        if (StringUtils.isNotEmpty(attr.readConverterExp()))
+                        {
+                            val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
+                        }
+                        else if (StringUtils.isNotEmpty(attr.dictType()))
+                        {
+                            val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
+                        }
+                        else if (!attr.handler().equals(ExcelHandlerAdapter.class))
+                        {
+                            val = dataFormatHandlerAdapter(val, attr, null);
+                        }
+                        else if (Excel.ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
+                        {
+                            PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey());
+                            if (image == null)
+                            {
+                                val = "";
+                            }
+                            else
+                            {
+                                byte[] data = image.getData();
+                                val = FileUtils.writeImportBytes(data);
+                            }
+                        }
+                        ReflectUtils.invokeSetter(entity, propertyName, val);
+                    }
+                }
+                list.add(entity);
+            }
+        }
+        return list;
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param list 瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @return 缁撴灉
+     */
+    public AjaxResult exportExcel(List<T> list, String sheetName)
+    {
+        return exportExcel(list, sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param list 瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param title 鏍囬
+     * @return 缁撴灉
+     */
+    public AjaxResult exportExcel(List<T> list, String sheetName, String title)
+    {
+        this.init(list, sheetName, title, Excel.Type.EXPORT);
+        return exportExcel();
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param response 杩斿洖鏁版嵁
+     * @param list 瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @return 缁撴灉
+     */
+    public void exportExcel(HttpServletResponse response, List<T> list, String sheetName)
+    {
+        exportExcel(response, list, sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param response 杩斿洖鏁版嵁
+     * @param list 瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param title 鏍囬
+     * @return 缁撴灉
+     */
+    public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title)
+    {
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        this.init(list, sheetName, title, Excel.Type.EXPORT);
+        exportExcel(response);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @return 缁撴灉
+     */
+    public AjaxResult importTemplateExcel(String sheetName)
+    {
+        return importTemplateExcel(sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param title 鏍囬
+     * @return 缁撴灉
+     */
+    public AjaxResult importTemplateExcel(String sheetName, String title)
+    {
+        this.init(null, sheetName, title, Excel.Type.IMPORT);
+        return exportExcel();
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @return 缁撴灉
+     */
+    public void importTemplateExcel(HttpServletResponse response, String sheetName)
+    {
+        importTemplateExcel(response, sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param title 鏍囬
+     * @return 缁撴灉
+     */
+    public void importTemplateExcel(HttpServletResponse response, String sheetName, String title)
+    {
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        this.init(null, sheetName, title, Excel.Type.IMPORT);
+        exportExcel(response);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @return 缁撴灉
+     */
+    public void exportExcel(HttpServletResponse response)
+    {
+        try
+        {
+            writeSheet();
+            wb.write(response.getOutputStream());
+        }
+        catch (Exception e)
+        {
+            log.error("瀵煎嚭Excel寮傚父{}", e.getMessage());
+        }
+        finally
+        {
+            IOUtils.closeQuietly(wb);
+        }
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @return 缁撴灉
+     */
+    public AjaxResult exportExcel()
+    {
+        OutputStream out = null;
+        try
+        {
+            writeSheet();
+            String filename = encodingFilename(sheetName);
+            out = new FileOutputStream(getAbsoluteFile(filename));
+            wb.write(out);
+            return AjaxResult.success(filename);
+        }
+        catch (Exception e)
+        {
+            log.error("瀵煎嚭Excel寮傚父{}", e.getMessage());
+            throw new UtilException("瀵煎嚭Excel澶辫触锛岃鑱旂郴缃戠珯绠$悊鍛橈紒");
+        }
+        finally
+        {
+            IOUtils.closeQuietly(wb);
+            IOUtils.closeQuietly(out);
+        }
+    }
+
+    /**
+     * 鍒涘缓鍐欏叆鏁版嵁鍒癝heet
+     */
+    public void writeSheet()
+    {
+        // 鍙栧嚭涓�鍏辨湁澶氬皯涓猻heet.
+        int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize));
+        for (int index = 0; index < sheetNo; index++)
+        {
+            createSheet(sheetNo, index);
+
+            // 浜х敓涓�琛�
+            Row row = sheet.createRow(rownum);
+            int column = 0;
+            // 鍐欏叆鍚勪釜瀛楁鐨勫垪澶村悕绉�
+            for (Object[] os : fields)
+            {
+                Field field = (Field) os[0];
+                Excel excel = (Excel) os[1];
+                if (Collection.class.isAssignableFrom(field.getType()))
+                {
+                    for (Field subField : subFields)
+                    {
+                        Excel subExcel = subField.getAnnotation(Excel.class);
+                        this.createHeadCell(subExcel, row, column++);
+                    }
+                }
+                else
+                {
+                    this.createHeadCell(excel, row, column++);
+                }
+            }
+            if (Excel.Type.EXPORT.equals(type))
+            {
+                fillExcelData(index, row);
+                addStatisticsRow();
+            }
+        }
+    }
+
+    /**
+     * 濉厖excel鏁版嵁
+     * 
+     * @param index 搴忓彿
+     * @param row 鍗曞厓鏍艰
+     */
+    @SuppressWarnings("unchecked")
+    public void fillExcelData(int index, Row row)
+    {
+        int startNo = index * sheetSize;
+        int endNo = Math.min(startNo + sheetSize, list.size());
+        int rowNo = (1 + rownum) - startNo;
+        for (int i = startNo; i < endNo; i++)
+        {
+            rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo;
+            row = sheet.createRow(rowNo);
+            // 寰楀埌瀵煎嚭瀵硅薄.
+            T vo = (T) list.get(i);
+            Collection<?> subList = null;
+            if (isSubList())
+            {
+                if (isSubListValue(vo))
+                {
+                    subList = getListCellValue(vo);
+                    subMergedLastRowNum = subMergedLastRowNum + subList.size();
+                }
+                else
+                {
+                    subMergedFirstRowNum++;
+                    subMergedLastRowNum++;
+                }
+            }
+            int column = 0;
+            for (Object[] os : fields)
+            {
+                Field field = (Field) os[0];
+                Excel excel = (Excel) os[1];
+                if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList))
+                {
+                    boolean subFirst = false;
+                    for (Object obj : subList)
+                    {
+                        if (subFirst)
+                        {
+                            rowNo++;
+                            row = sheet.createRow(rowNo);
+                        }
+                        List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);
+                        int subIndex = 0;
+                        for (Field subField : subFields)
+                        {
+                            if (subField.isAnnotationPresent(Excel.class))
+                            {
+                                subField.setAccessible(true);
+                                Excel attr = subField.getAnnotation(Excel.class);
+                                this.addCell(attr, row, (T) obj, subField, column + subIndex);
+                            }
+                            subIndex++;
+                        }
+                        subFirst = true;
+                    }
+                    this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();
+                }
+                else
+                {
+                    this.addCell(excel, row, vo, field, column++);
+                }
+            }
+        }
+    }
+
+    /**
+     * 鍒涘缓琛ㄦ牸鏍峰紡
+     * 
+     * @param wb 宸ヤ綔钖勫璞�
+     * @return 鏍峰紡鍒楄〃
+     */
+    private Map<String, CellStyle> createStyles(Workbook wb)
+    {
+        // 鍐欏叆鍚勬潯璁板綍,姣忔潯璁板綍瀵瑰簲excel琛ㄤ腑鐨勪竴琛�
+        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
+        CellStyle style = wb.createCellStyle();
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        Font titleFont = wb.createFont();
+        titleFont.setFontName("Arial");
+        titleFont.setFontHeightInPoints((short) 16);
+        titleFont.setBold(true);
+        style.setFont(titleFont);
+        styles.put("title", style);
+
+        style = wb.createCellStyle();
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setBorderRight(BorderStyle.THIN);
+        style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderTop(BorderStyle.THIN);
+        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        Font dataFont = wb.createFont();
+        dataFont.setFontName("Arial");
+        dataFont.setFontHeightInPoints((short) 10);
+        style.setFont(dataFont);
+        styles.put("data", style);
+
+        style = wb.createCellStyle();
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        Font totalFont = wb.createFont();
+        totalFont.setFontName("Arial");
+        totalFont.setFontHeightInPoints((short) 10);
+        style.setFont(totalFont);
+        styles.put("total", style);
+
+        styles.putAll(annotationHeaderStyles(wb, styles));
+
+        styles.putAll(annotationDataStyles(wb));
+
+        return styles;
+    }
+
+    /**
+     * 鏍规嵁Excel娉ㄨВ鍒涘缓琛ㄦ牸澶存牱寮�
+     * 
+     * @param wb 宸ヤ綔钖勫璞�
+     * @return 鑷畾涔夋牱寮忓垪琛�
+     */
+    private Map<String, CellStyle> annotationHeaderStyles(Workbook wb, Map<String, CellStyle> styles)
+    {
+        Map<String, CellStyle> headerStyles = new HashMap<String, CellStyle>();
+        for (Object[] os : fields)
+        {
+            Excel excel = (Excel) os[1];
+            String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor());
+            if (!headerStyles.containsKey(key))
+            {
+                CellStyle style = wb.createCellStyle();
+                style.cloneStyleFrom(styles.get("data"));
+                style.setAlignment(HorizontalAlignment.CENTER);
+                style.setVerticalAlignment(VerticalAlignment.CENTER);
+                style.setFillForegroundColor(excel.headerBackgroundColor().index);
+                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+                Font headerFont = wb.createFont();
+                headerFont.setFontName("Arial");
+                headerFont.setFontHeightInPoints((short) 10);
+                headerFont.setBold(true);
+                headerFont.setColor(excel.headerColor().index);
+                style.setFont(headerFont);
+                headerStyles.put(key, style);
+            }
+        }
+        return headerStyles;
+    }
+
+    /**
+     * 鏍规嵁Excel娉ㄨВ鍒涘缓琛ㄦ牸鍒楁牱寮�
+     * 
+     * @param wb 宸ヤ綔钖勫璞�
+     * @return 鑷畾涔夋牱寮忓垪琛�
+     */
+    private Map<String, CellStyle> annotationDataStyles(Workbook wb)
+    {
+        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
+        for (Object[] os : fields)
+        {
+            Excel excel = (Excel) os[1];
+            String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor());
+            if (!styles.containsKey(key))
+            {
+                CellStyle style = wb.createCellStyle();
+                style.setAlignment(excel.align());
+                style.setVerticalAlignment(VerticalAlignment.CENTER);
+                style.setBorderRight(BorderStyle.THIN);
+                style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+                style.setBorderLeft(BorderStyle.THIN);
+                style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+                style.setBorderTop(BorderStyle.THIN);
+                style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+                style.setBorderBottom(BorderStyle.THIN);
+                style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+                style.setFillForegroundColor(excel.backgroundColor().getIndex());
+                Font dataFont = wb.createFont();
+                dataFont.setFontName("Arial");
+                dataFont.setFontHeightInPoints((short) 10);
+                dataFont.setColor(excel.color().index);
+                style.setFont(dataFont);
+                styles.put(key, style);
+            }
+        }
+        return styles;
+    }
+
+    /**
+     * 鍒涘缓鍗曞厓鏍�
+     */
+    public Cell createHeadCell(Excel attr, Row row, int column)
+    {
+        // 鍒涘缓鍒�
+        Cell cell = row.createCell(column);
+        // 鍐欏叆鍒椾俊鎭�
+        cell.setCellValue(attr.name());
+        setDataValidation(attr, row, column);
+        cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+        if (isSubList())
+        {
+            // 濉厖榛樿鏍峰紡锛岄槻姝㈠悎骞跺崟鍏冩牸鏍峰紡澶辨晥
+            sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
+            if (attr.needMerge())
+            {
+                sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
+            }
+        }
+        return cell;
+    }
+
+    /**
+     * 璁剧疆鍗曞厓鏍间俊鎭�
+     * 
+     * @param value 鍗曞厓鏍煎��
+     * @param attr 娉ㄨВ鐩稿叧
+     * @param cell 鍗曞厓鏍间俊鎭�
+     */
+    public void setCellVo(Object value, Excel attr, Cell cell)
+    {
+        if (Excel.ColumnType.STRING == attr.cellType())
+        {
+            String cellValue = Convert.toStr(value);
+            // 瀵逛簬浠讳綍浠ヨ〃杈惧紡瑙﹀彂瀛楃 =-+@寮�澶寸殑鍗曞厓鏍硷紝鐩存帴浣跨敤tab瀛楃浣滀负鍓嶇紑锛岄槻姝SV娉ㄥ叆銆�
+            if (StringUtils.startsWithAny(cellValue, FORMULA_STR))
+            {
+                cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0");
+            }
+            if (value instanceof Collection && StringUtils.equals("[]", cellValue))
+            {
+                cellValue = StringUtils.EMPTY;
+            }
+            cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix());
+        }
+        else if (Excel.ColumnType.NUMERIC == attr.cellType())
+        {
+            if (StringUtils.isNotNull(value))
+            {
+                cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
+            }
+        }
+        else if (Excel.ColumnType.IMAGE == attr.cellType())
+        {
+            ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
+            String imagePath = Convert.toStr(value);
+            if (StringUtils.isNotEmpty(imagePath))
+            {
+                byte[] data = ImageUtils.getImage(imagePath);
+                getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
+                        cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
+            }
+        }
+    }
+
+    /**
+     * 鑾峰彇鐢诲竷
+     */
+    public static Drawing<?> getDrawingPatriarch(Sheet sheet)
+    {
+        if (sheet.getDrawingPatriarch() == null)
+        {
+            sheet.createDrawingPatriarch();
+        }
+        return sheet.getDrawingPatriarch();
+    }
+
+    /**
+     * 鑾峰彇鍥剧墖绫诲瀷,璁剧疆鍥剧墖鎻掑叆绫诲瀷
+     */
+    public int getImageType(byte[] value)
+    {
+        String type = FileTypeUtils.getFileExtendName(value);
+        if ("JPG".equalsIgnoreCase(type))
+        {
+            return Workbook.PICTURE_TYPE_JPEG;
+        }
+        else if ("PNG".equalsIgnoreCase(type))
+        {
+            return Workbook.PICTURE_TYPE_PNG;
+        }
+        return Workbook.PICTURE_TYPE_JPEG;
+    }
+
+    /**
+     * 鍒涘缓琛ㄦ牸鏍峰紡
+     */
+    public void setDataValidation(Excel attr, Row row, int column)
+    {
+        if (attr.name().indexOf("娉細") >= 0)
+        {
+            sheet.setColumnWidth(column, 6000);
+        }
+        else
+        {
+            // 璁剧疆鍒楀
+            sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
+        }
+        if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0)
+        {
+            if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255)
+            {
+                // 濡傛灉涓嬫媺鏁板ぇ浜�15鎴栧瓧绗︿覆闀垮害澶т簬255锛屽垯浣跨敤涓�涓柊sheet瀛樺偍锛岄伩鍏嶇敓鎴愮殑妯℃澘涓嬫媺鍊艰幏鍙栦笉鍒�
+                setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
+            }
+            else
+            {
+                // 鎻愮ず淇℃伅鎴栧彧鑳介�夋嫨涓嶈兘杈撳叆鐨勫垪鍐呭.
+                setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
+            }
+        }
+    }
+
+    /**
+     * 娣诲姞鍗曞厓鏍�
+     */
+    public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
+    {
+        Cell cell = null;
+        try
+        {
+            // 璁剧疆琛岄珮
+            row.setHeight(maxHeight);
+            // 鏍规嵁Excel涓缃儏鍐靛喅瀹氭槸鍚﹀鍑�,鏈変簺鎯呭喌闇�瑕佷繚鎸佷负绌�,甯屾湜鐢ㄦ埛濉啓杩欎竴鍒�.
+            if (attr.isExport())
+            {
+                // 鍒涘缓cell
+                cell = row.createCell(column);
+                if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
+                {
+                    CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
+                    sheet.addMergedRegion(cellAddress);
+                }
+                cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
+
+                // 鐢ㄤ簬璇诲彇瀵硅薄涓殑灞炴��
+                Object value = getTargetValue(vo, field, attr);
+                String dateFormat = attr.dateFormat();
+                String readConverterExp = attr.readConverterExp();
+                String separator = attr.separator();
+                String dictType = attr.dictType();
+                if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
+                {
+                    cell.setCellValue(parseDateToStr(dateFormat, value));
+                }
+                else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
+                {
+                    cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
+                }
+                else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
+                {
+                    if (!sysDictMap.containsKey(dictType + value))
+                    {
+                        String lable = convertDictByExp(Convert.toStr(value), dictType, separator);
+                        sysDictMap.put(dictType + value, lable);
+                    }
+                    cell.setCellValue(sysDictMap.get(dictType + value));
+                }
+                else if (value instanceof BigDecimal && -1 != attr.scale())
+                {
+                    cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
+                }
+                else if (!attr.handler().equals(ExcelHandlerAdapter.class))
+                {
+                    cell.setCellValue(dataFormatHandlerAdapter(value, attr, cell));
+                }
+                else
+                {
+                    // 璁剧疆鍒楃被鍨�
+                    setCellVo(value, attr, cell);
+                }
+                addStatisticsData(column, Convert.toStr(value), attr);
+            }
+        }
+        catch (Exception e)
+        {
+            log.error("瀵煎嚭Excel澶辫触{}", e);
+        }
+        return cell;
+    }
+
+    /**
+     * 璁剧疆 POI XSSFSheet 鍗曞厓鏍兼彁绀烘垨閫夋嫨妗�
+     * 
+     * @param sheet 琛ㄥ崟
+     * @param textlist 涓嬫媺妗嗘樉绀虹殑鍐呭
+     * @param promptContent 鎻愮ず鍐呭
+     * @param firstRow 寮�濮嬭
+     * @param endRow 缁撴潫琛�
+     * @param firstCol 寮�濮嬪垪
+     * @param endCol 缁撴潫鍒�
+     */
+    public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow,
+            int firstCol, int endCol)
+    {
+        DataValidationHelper helper = sheet.getDataValidationHelper();
+        DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1");
+        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
+        DataValidation dataValidation = helper.createValidation(constraint, regions);
+        if (StringUtils.isNotEmpty(promptContent))
+        {
+            // 濡傛灉璁剧疆浜嗘彁绀轰俊鎭垯榧犳爣鏀句笂鍘绘彁绀�
+            dataValidation.createPromptBox("", promptContent);
+            dataValidation.setShowPromptBox(true);
+        }
+        // 澶勭悊Excel鍏煎鎬ч棶棰�
+        if (dataValidation instanceof XSSFDataValidation)
+        {
+            dataValidation.setSuppressDropDownArrow(true);
+            dataValidation.setShowErrorBox(true);
+        }
+        else
+        {
+            dataValidation.setSuppressDropDownArrow(false);
+        }
+        sheet.addValidationData(dataValidation);
+    }
+
+    /**
+     * 璁剧疆鏌愪簺鍒楃殑鍊煎彧鑳借緭鍏ラ鍒剁殑鏁版嵁,鏄剧ず涓嬫媺妗嗭紙鍏煎瓒呭嚭涓�瀹氭暟閲忕殑涓嬫媺妗嗭級.
+     * 
+     * @param sheet 瑕佽缃殑sheet.
+     * @param textlist 涓嬫媺妗嗘樉绀虹殑鍐呭
+     * @param promptContent 鎻愮ず鍐呭
+     * @param firstRow 寮�濮嬭
+     * @param endRow 缁撴潫琛�
+     * @param firstCol 寮�濮嬪垪
+     * @param endCol 缁撴潫鍒�
+     */
+    public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
+    {
+        String hideSheetName = "combo_" + firstCol + "_" + endCol;
+        Sheet hideSheet = wb.createSheet(hideSheetName); // 鐢ㄤ簬瀛樺偍 涓嬫媺鑿滃崟鏁版嵁
+        for (int i = 0; i < textlist.length; i++)
+        {
+            hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
+        }
+        // 鍒涘缓鍚嶇О锛屽彲琚叾浠栧崟鍏冩牸寮曠敤
+        Name name = wb.createName();
+        name.setNameName(hideSheetName + "_data");
+        name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
+        DataValidationHelper helper = sheet.getDataValidationHelper();
+        // 鍔犺浇涓嬫媺鍒楄〃鍐呭
+        DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data");
+        // 璁剧疆鏁版嵁鏈夋晥鎬у姞杞藉湪鍝釜鍗曞厓鏍间笂,鍥涗釜鍙傛暟鍒嗗埆鏄細璧峰琛屻�佺粓姝㈣銆佽捣濮嬪垪銆佺粓姝㈠垪
+        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
+        // 鏁版嵁鏈夋晥鎬у璞�
+        DataValidation dataValidation = helper.createValidation(constraint, regions);
+        if (StringUtils.isNotEmpty(promptContent))
+        {
+            // 濡傛灉璁剧疆浜嗘彁绀轰俊鎭垯榧犳爣鏀句笂鍘绘彁绀�
+            dataValidation.createPromptBox("", promptContent);
+            dataValidation.setShowPromptBox(true);
+        }
+        // 澶勭悊Excel鍏煎鎬ч棶棰�
+        if (dataValidation instanceof XSSFDataValidation)
+        {
+            dataValidation.setSuppressDropDownArrow(true);
+            dataValidation.setShowErrorBox(true);
+        }
+        else
+        {
+            dataValidation.setSuppressDropDownArrow(false);
+        }
+
+        sheet.addValidationData(dataValidation);
+        // 璁剧疆hiddenSheet闅愯棌
+        wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
+    }
+
+    /**
+     * 瑙f瀽瀵煎嚭鍊� 0=鐢�,1=濂�,2=鏈煡
+     * 
+     * @param propertyValue 鍙傛暟鍊�
+     * @param converterExp 缈昏瘧娉ㄨВ
+     * @param separator 鍒嗛殧绗�
+     * @return 瑙f瀽鍚庡��
+     */
+    public static String convertByExp(String propertyValue, String converterExp, String separator)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        String[] convertSource = converterExp.split(",");
+        for (String item : convertSource)
+        {
+            String[] itemArray = item.split("=");
+            if (StringUtils.containsAny(propertyValue, separator))
+            {
+                for (String value : propertyValue.split(separator))
+                {
+                    if (itemArray[0].equals(value))
+                    {
+                        propertyString.append(itemArray[1] + separator);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                if (itemArray[0].equals(propertyValue))
+                {
+                    return itemArray[1];
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 鍙嶅悜瑙f瀽鍊� 鐢�=0,濂�=1,鏈煡=2
+     * 
+     * @param propertyValue 鍙傛暟鍊�
+     * @param converterExp 缈昏瘧娉ㄨВ
+     * @param separator 鍒嗛殧绗�
+     * @return 瑙f瀽鍚庡��
+     */
+    public static String reverseByExp(String propertyValue, String converterExp, String separator)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        String[] convertSource = converterExp.split(",");
+        for (String item : convertSource)
+        {
+            String[] itemArray = item.split("=");
+            if (StringUtils.containsAny(propertyValue, separator))
+            {
+                for (String value : propertyValue.split(separator))
+                {
+                    if (itemArray[1].equals(value))
+                    {
+                        propertyString.append(itemArray[0] + separator);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                if (itemArray[1].equals(propertyValue))
+                {
+                    return itemArray[0];
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 瑙f瀽瀛楀吀鍊�
+     * 
+     * @param dictValue 瀛楀吀鍊�
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param separator 鍒嗛殧绗�
+     * @return 瀛楀吀鏍囩
+     */
+    public static String convertDictByExp(String dictValue, String dictType, String separator)
+    {
+        return DictUtils.getDictLabel(dictType, dictValue, separator);
+    }
+
+    /**
+     * 鍙嶅悜瑙f瀽鍊煎瓧鍏稿��
+     * 
+     * @param dictLabel 瀛楀吀鏍囩
+     * @param dictType 瀛楀吀绫诲瀷
+     * @param separator 鍒嗛殧绗�
+     * @return 瀛楀吀鍊�
+     */
+    public static String reverseDictByExp(String dictLabel, String dictType, String separator)
+    {
+        return DictUtils.getDictValue(dictType, dictLabel, separator);
+    }
+
+    /**
+     * 鏁版嵁澶勭悊鍣�
+     * 
+     * @param value 鏁版嵁鍊�
+     * @param excel 鏁版嵁娉ㄨВ
+     * @return
+     */
+    public String dataFormatHandlerAdapter(Object value, Excel excel, Cell cell)
+    {
+        try
+        {
+            Object instance = excel.handler().newInstance();
+            Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
+            value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
+        }
+        catch (Exception e)
+        {
+            log.error("涓嶈兘鏍煎紡鍖栨暟鎹� " + excel.handler(), e.getMessage());
+        }
+        return Convert.toStr(value);
+    }
+
+    /**
+     * 鍚堣缁熻淇℃伅
+     */
+    private void addStatisticsData(Integer index, String text, Excel entity)
+    {
+        if (entity != null && entity.isStatistics())
+        {
+            Double temp = 0D;
+            if (!statistics.containsKey(index))
+            {
+                statistics.put(index, temp);
+            }
+            try
+            {
+                temp = Double.valueOf(text);
+            }
+            catch (NumberFormatException e)
+            {
+            }
+            statistics.put(index, statistics.get(index) + temp);
+        }
+    }
+
+    /**
+     * 鍒涘缓缁熻琛�
+     */
+    public void addStatisticsRow()
+    {
+        if (statistics.size() > 0)
+        {
+            Row row = sheet.createRow(sheet.getLastRowNum() + 1);
+            Set<Integer> keys = statistics.keySet();
+            Cell cell = row.createCell(0);
+            cell.setCellStyle(styles.get("total"));
+            cell.setCellValue("鍚堣");
+
+            for (Integer key : keys)
+            {
+                cell = row.createCell(key);
+                cell.setCellStyle(styles.get("total"));
+                cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
+            }
+            statistics.clear();
+        }
+    }
+
+    /**
+     * 缂栫爜鏂囦欢鍚�
+     */
+    public String encodingFilename(String filename)
+    {
+        filename = UUID.randomUUID() + "_" + filename + ".xlsx";
+        return filename;
+    }
+
+    /**
+     * 鑾峰彇涓嬭浇璺緞
+     * 
+     * @param filename 鏂囦欢鍚嶇О
+     */
+    public String getAbsoluteFile(String filename)
+    {
+        String downloadPath = PlatformConfig.getDownloadPath() + filename;
+        File desc = new File(downloadPath);
+        if (!desc.getParentFile().exists())
+        {
+            desc.getParentFile().mkdirs();
+        }
+        return downloadPath;
+    }
+
+    /**
+     * 鑾峰彇bean涓殑灞炴�у��
+     * 
+     * @param vo 瀹炰綋瀵硅薄
+     * @param field 瀛楁
+     * @param excel 娉ㄨВ
+     * @return 鏈�缁堢殑灞炴�у��
+     * @throws Exception
+     */
+    private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
+    {
+        Object o = field.get(vo);
+        if (StringUtils.isNotEmpty(excel.targetAttr()))
+        {
+            String target = excel.targetAttr();
+            if (target.contains("."))
+            {
+                String[] targets = target.split("[.]");
+                for (String name : targets)
+                {
+                    o = getValue(o, name);
+                }
+            }
+            else
+            {
+                o = getValue(o, target);
+            }
+        }
+        return o;
+    }
+
+    /**
+     * 浠ョ被鐨勫睘鎬х殑get鏂规硶鏂规硶褰㈠紡鑾峰彇鍊�
+     * 
+     * @param o
+     * @param name
+     * @return value
+     * @throws Exception
+     */
+    private Object getValue(Object o, String name) throws Exception
+    {
+        if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name))
+        {
+            Class<?> clazz = o.getClass();
+            Field field = clazz.getDeclaredField(name);
+            field.setAccessible(true);
+            o = field.get(o);
+        }
+        return o;
+    }
+
+    /**
+     * 寰楀埌鎵�鏈夊畾涔夊瓧娈�
+     */
+    private void createExcelField()
+    {
+        this.fields = getFields();
+        this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
+        this.maxHeight = getRowHeight();
+    }
+
+    /**
+     * 鑾峰彇瀛楁娉ㄨВ淇℃伅
+     */
+    public List<Object[]> getFields()
+    {
+        List<Object[]> fields = new ArrayList<Object[]>();
+        List<Field> tempFields = new ArrayList<>();
+        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
+        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
+        for (Field field : tempFields)
+        {
+            if (!ArrayUtils.contains(this.excludeFields, field.getName()))
+            {
+                // 鍗曟敞瑙�
+                if (field.isAnnotationPresent(Excel.class))
+                {
+                    Excel attr = field.getAnnotation(Excel.class);
+                    if (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == type))
+                    {
+                        field.setAccessible(true);
+                        fields.add(new Object[] { field, attr });
+                    }
+                    if (Collection.class.isAssignableFrom(field.getType()))
+                    {
+                        subMethod = getSubMethod(field.getName(), clazz);
+                        ParameterizedType pt = (ParameterizedType) field.getGenericType();
+                        Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
+                        this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
+                    }
+                }
+
+                // 澶氭敞瑙�
+                if (field.isAnnotationPresent(Excels.class))
+                {
+                    Excels attrs = field.getAnnotation(Excels.class);
+                    Excel[] excels = attrs.value();
+                    for (Excel attr : excels)
+                    {
+                        if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
+                                && (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == type)))
+                        {
+                            field.setAccessible(true);
+                            fields.add(new Object[] { field, attr });
+                        }
+                    }
+                }
+            }
+        }
+        return fields;
+    }
+
+    /**
+     * 鏍规嵁娉ㄨВ鑾峰彇鏈�澶ц楂�
+     */
+    public short getRowHeight()
+    {
+        double maxHeight = 0;
+        for (Object[] os : this.fields)
+        {
+            Excel excel = (Excel) os[1];
+            maxHeight = Math.max(maxHeight, excel.height());
+        }
+        return (short) (maxHeight * 20);
+    }
+
+    /**
+     * 鍒涘缓涓�涓伐浣滅翱
+     */
+    public void createWorkbook()
+    {
+        this.wb = new SXSSFWorkbook(500);
+        this.sheet = wb.createSheet();
+        wb.setSheetName(0, sheetName);
+        this.styles = createStyles(wb);
+    }
+
+    /**
+     * 鍒涘缓宸ヤ綔琛�
+     * 
+     * @param sheetNo sheet鏁伴噺
+     * @param index 搴忓彿
+     */
+    public void createSheet(int sheetNo, int index)
+    {
+        // 璁剧疆宸ヤ綔琛ㄧ殑鍚嶇О.
+        if (sheetNo > 1 && index > 0)
+        {
+            this.sheet = wb.createSheet();
+            this.createTitle();
+            wb.setSheetName(index, sheetName + index);
+        }
+    }
+
+    /**
+     * 鑾峰彇鍗曞厓鏍煎��
+     * 
+     * @param row 鑾峰彇鐨勮
+     * @param column 鑾峰彇鍗曞厓鏍煎垪鍙�
+     * @return 鍗曞厓鏍煎��
+     */
+    public Object getCellValue(Row row, int column)
+    {
+        if (row == null)
+        {
+            return row;
+        }
+        Object val = "";
+        try
+        {
+            Cell cell = row.getCell(column);
+            if (StringUtils.isNotNull(cell))
+            {
+                if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA)
+                {
+                    val = cell.getNumericCellValue();
+                    if (DateUtil.isCellDateFormatted(cell))
+                    {
+                        val = DateUtil.getJavaDate((Double) val); // POI Excel 鏃ユ湡鏍煎紡杞崲
+                    }
+                    else
+                    {
+                        if ((Double) val % 1 != 0)
+                        {
+                            val = new BigDecimal(val.toString());
+                        }
+                        else
+                        {
+                            val = new DecimalFormat("0").format(val);
+                        }
+                    }
+                }
+                else if (cell.getCellType() == CellType.STRING)
+                {
+                    val = cell.getStringCellValue();
+                }
+                else if (cell.getCellType() == CellType.BOOLEAN)
+                {
+                    val = cell.getBooleanCellValue();
+                }
+                else if (cell.getCellType() == CellType.ERROR)
+                {
+                    val = cell.getErrorCellValue();
+                }
+
+            }
+        }
+        catch (Exception e)
+        {
+            return val;
+        }
+        return val;
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁鏄┖琛�
+     * 
+     * @param row 鍒ゆ柇鐨勮
+     * @return
+     */
+    private boolean isRowEmpty(Row row)
+    {
+        if (row == null)
+        {
+            return true;
+        }
+        for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++)
+        {
+            Cell cell = row.getCell(i);
+            if (cell != null && cell.getCellType() != CellType.BLANK)
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 鑾峰彇Excel2003鍥剧墖
+     *
+     * @param sheet 褰撳墠sheet瀵硅薄
+     * @param workbook 宸ヤ綔绨垮璞�
+     * @return Map key:鍥剧墖鍗曞厓鏍肩储寮曪紙1_1锛塖tring锛寁alue:鍥剧墖娴丳ictureData
+     */
+    public static Map<String, PictureData> getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook)
+    {
+        Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
+        List<HSSFPictureData> pictures = workbook.getAllPictures();
+        if (!pictures.isEmpty())
+        {
+            for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren())
+            {
+                HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
+                if (shape instanceof HSSFPicture)
+                {
+                    HSSFPicture pic = (HSSFPicture) shape;
+                    int pictureIndex = pic.getPictureIndex() - 1;
+                    HSSFPictureData picData = pictures.get(pictureIndex);
+                    String picIndex = anchor.getRow1() + "_" + anchor.getCol1();
+                    sheetIndexPicMap.put(picIndex, picData);
+                }
+            }
+            return sheetIndexPicMap;
+        }
+        else
+        {
+            return sheetIndexPicMap;
+        }
+    }
+
+    /**
+     * 鑾峰彇Excel2007鍥剧墖
+     *
+     * @param sheet 褰撳墠sheet瀵硅薄
+     * @param workbook 宸ヤ綔绨垮璞�
+     * @return Map key:鍥剧墖鍗曞厓鏍肩储寮曪紙1_1锛塖tring锛寁alue:鍥剧墖娴丳ictureData
+     */
+    public static Map<String, PictureData> getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook)
+    {
+        Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
+        for (POIXMLDocumentPart dr : sheet.getRelations())
+        {
+            if (dr instanceof XSSFDrawing)
+            {
+                XSSFDrawing drawing = (XSSFDrawing) dr;
+                List<XSSFShape> shapes = drawing.getShapes();
+                for (XSSFShape shape : shapes)
+                {
+                    if (shape instanceof XSSFPicture)
+                    {
+                        XSSFPicture pic = (XSSFPicture) shape;
+                        XSSFClientAnchor anchor = pic.getPreferredSize();
+                        CTMarker ctMarker = anchor.getFrom();
+                        String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol();
+                        sheetIndexPicMap.put(picIndex, pic.getPictureData());
+                    }
+                }
+            }
+        }
+        return sheetIndexPicMap;
+    }
+
+    /**
+     * 鏍煎紡鍖栦笉鍚岀被鍨嬬殑鏃ユ湡瀵硅薄
+     * 
+     * @param dateFormat 鏃ユ湡鏍煎紡
+     * @param val 琚牸寮忓寲鐨勬棩鏈熷璞�
+     * @return 鏍煎紡鍖栧悗鐨勬棩鏈熷瓧绗�
+     */
+    public String parseDateToStr(String dateFormat, Object val)
+    {
+        if (val == null)
+        {
+            return "";
+        }
+        String str;
+        if (val instanceof Date)
+        {
+            str = DateUtils.parseDateToStr(dateFormat, (Date) val);
+        }
+        else if (val instanceof LocalDateTime)
+        {
+            str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDateTime) val));
+        }
+        else if (val instanceof LocalDate)
+        {
+            str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDate) val));
+        }
+        else
+        {
+            str = val.toString();
+        }
+        return str;
+    }
+
+    /**
+     * 鏄惁鏈夊璞$殑瀛愬垪琛�
+     */
+    public boolean isSubList()
+    {
+        return StringUtils.isNotNull(subFields) && subFields.size() > 0;
+    }
+
+    /**
+     * 鏄惁鏈夊璞$殑瀛愬垪琛紝闆嗗悎涓嶄负绌�
+     */
+    public boolean isSubListValue(T vo)
+    {
+        return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0;
+    }
+
+    /**
+     * 鑾峰彇闆嗗悎鐨勫��
+     */
+    public Collection<?> getListCellValue(Object obj)
+    {
+        Object value;
+        try
+        {
+            value = subMethod.invoke(obj, new Object[] {});
+        }
+        catch (Exception e)
+        {
+            return new ArrayList<Object>();
+        }
+        return (Collection<?>) value;
+    }
+
+    /**
+     * 鑾峰彇瀵硅薄鐨勫瓙鍒楄〃鏂规硶
+     * 
+     * @param name 鍚嶇О
+     * @param pojoClass 绫诲璞�
+     * @return 瀛愬垪琛ㄦ柟娉�
+     */
+    public Method getSubMethod(String name, Class<?> pojoClass)
+    {
+        StringBuffer getMethodName = new StringBuffer("get");
+        getMethodName.append(name.substring(0, 1).toUpperCase());
+        getMethodName.append(name.substring(1));
+        Method method = null;
+        try
+        {
+            method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});
+        }
+        catch (Exception e)
+        {
+            log.error("鑾峰彇瀵硅薄寮傚父{}", e.getMessage());
+        }
+        return method;
+    }
+}
diff --git a/ycl-common/src/main/java/utils/redis/RedisCache.java b/ycl-common/src/main/java/utils/redis/RedisCache.java
new file mode 100644
index 0000000..d83bfc5
--- /dev/null
+++ b/ycl-common/src/main/java/utils/redis/RedisCache.java
@@ -0,0 +1,265 @@
+package utils.redis;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.BoundSetOperations;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * spring redis 宸ュ叿绫�
+ *
+ * @author ruoyi
+ **/
+@SuppressWarnings(value = { "unchecked", "rawtypes" })
+@Component
+public class RedisCache
+{
+    @Autowired
+    public RedisTemplate redisTemplate;
+
+    /**
+     * 缂撳瓨鍩烘湰鐨勫璞★紝Integer銆丼tring銆佸疄浣撶被绛�
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @param value 缂撳瓨鐨勫��
+     */
+    public <T> void setCacheObject(final String key, final T value)
+    {
+        redisTemplate.opsForValue().set(key, value);
+    }
+
+    /**
+     * 缂撳瓨鍩烘湰鐨勫璞★紝Integer銆丼tring銆佸疄浣撶被绛�
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @param value 缂撳瓨鐨勫��
+     * @param timeout 鏃堕棿
+     * @param timeUnit 鏃堕棿棰楃矑搴�
+     */
+    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
+    {
+        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
+    }
+
+    /**
+     * 璁剧疆鏈夋晥鏃堕棿
+     *
+     * @param key Redis閿�
+     * @param timeout 瓒呮椂鏃堕棿
+     * @return true=璁剧疆鎴愬姛锛沠alse=璁剧疆澶辫触
+     */
+    public boolean expire(final String key, final long timeout)
+    {
+        return expire(key, timeout, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 璁剧疆鏈夋晥鏃堕棿
+     *
+     * @param key Redis閿�
+     * @param timeout 瓒呮椂鏃堕棿
+     * @param unit 鏃堕棿鍗曚綅
+     * @return true=璁剧疆鎴愬姛锛沠alse=璁剧疆澶辫触
+     */
+    public boolean expire(final String key, final long timeout, final TimeUnit unit)
+    {
+        return redisTemplate.expire(key, timeout, unit);
+    }
+
+    /**
+     * 鑾峰彇鏈夋晥鏃堕棿
+     *
+     * @param key Redis閿�
+     * @return 鏈夋晥鏃堕棿
+     */
+    public long getExpire(final String key)
+    {
+        return redisTemplate.getExpire(key);
+    }
+
+    /**
+     * 鍒ゆ柇 key鏄惁瀛樺湪
+     *
+     * @param key 閿�
+     * @return true 瀛樺湪 false涓嶅瓨鍦�
+     */
+    public Boolean hasKey(String key)
+    {
+        return redisTemplate.hasKey(key);
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨勫熀鏈璞°��
+     *
+     * @param key 缂撳瓨閿��
+     * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
+     */
+    public <T> T getCacheObject(final String key)
+    {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        return operation.get(key);
+    }
+
+    /**
+     * 鍒犻櫎鍗曚釜瀵硅薄
+     *
+     * @param key
+     */
+    public boolean deleteObject(final String key)
+    {
+        return redisTemplate.delete(key);
+    }
+
+    /**
+     * 鍒犻櫎闆嗗悎瀵硅薄
+     *
+     * @param collection 澶氫釜瀵硅薄
+     * @return
+     */
+    public boolean deleteObject(final Collection collection)
+    {
+        return redisTemplate.delete(collection) > 0;
+    }
+
+    /**
+     * 缂撳瓨List鏁版嵁
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @param dataList 寰呯紦瀛樼殑List鏁版嵁
+     * @return 缂撳瓨鐨勫璞�
+     */
+    public <T> long setCacheList(final String key, final List<T> dataList)
+    {
+        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
+        return count == null ? 0 : count;
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨刲ist瀵硅薄
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
+     */
+    public <T> List<T> getCacheList(final String key)
+    {
+        return redisTemplate.opsForList().range(key, 0, -1);
+    }
+
+    /**
+     * 缂撳瓨Set
+     *
+     * @param key 缂撳瓨閿��
+     * @param dataSet 缂撳瓨鐨勬暟鎹�
+     * @return 缂撳瓨鏁版嵁鐨勫璞�
+     */
+    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
+    {
+        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
+        Iterator<T> it = dataSet.iterator();
+        while (it.hasNext())
+        {
+            setOperation.add(it.next());
+        }
+        return setOperation;
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨剆et
+     *
+     * @param key
+     * @return
+     */
+    public <T> Set<T> getCacheSet(final String key)
+    {
+        return redisTemplate.opsForSet().members(key);
+    }
+
+    /**
+     * 缂撳瓨Map
+     *
+     * @param key
+     * @param dataMap
+     */
+    public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
+    {
+        if (dataMap != null) {
+            redisTemplate.opsForHash().putAll(key, dataMap);
+        }
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨凪ap
+     *
+     * @param key
+     * @return
+     */
+    public <T> Map<String, T> getCacheMap(final String key)
+    {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * 寰�Hash涓瓨鍏ユ暟鎹�
+     *
+     * @param key Redis閿�
+     * @param hKey Hash閿�
+     * @param value 鍊�
+     */
+    public <T> void setCacheMapValue(final String key, final String hKey, final T value)
+    {
+        redisTemplate.opsForHash().put(key, hKey, value);
+    }
+
+    /**
+     * 鑾峰彇Hash涓殑鏁版嵁
+     *
+     * @param key Redis閿�
+     * @param hKey Hash閿�
+     * @return Hash涓殑瀵硅薄
+     */
+    public <T> T getCacheMapValue(final String key, final String hKey)
+    {
+        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
+        return opsForHash.get(key, hKey);
+    }
+
+    /**
+     * 鑾峰彇澶氫釜Hash涓殑鏁版嵁
+     *
+     * @param key Redis閿�
+     * @param hKeys Hash閿泦鍚�
+     * @return Hash瀵硅薄闆嗗悎
+     */
+    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
+    {
+        return redisTemplate.opsForHash().multiGet(key, hKeys);
+    }
+
+    /**
+     * 鍒犻櫎Hash涓殑鏌愭潯鏁版嵁
+     *
+     * @param key Redis閿�
+     * @param hKey Hash閿�
+     * @return 鏄惁鎴愬姛
+     */
+    public boolean deleteCacheMapValue(final String key, final String hKey)
+    {
+        return redisTemplate.opsForHash().delete(key, hKey) > 0;
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨勫熀鏈璞″垪琛�
+     *
+     * @param pattern 瀛楃涓插墠缂�
+     * @return 瀵硅薄鍒楄〃
+     */
+    public Collection<String> keys(final String pattern)
+    {
+        return redisTemplate.keys(pattern);
+    }
+}
diff --git a/ycl-common/src/main/java/utils/reflect/ReflectUtils.java b/ycl-common/src/main/java/utils/reflect/ReflectUtils.java
new file mode 100644
index 0000000..dc60225
--- /dev/null
+++ b/ycl-common/src/main/java/utils/reflect/ReflectUtils.java
@@ -0,0 +1,406 @@
+package utils.reflect;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import utils.DateUtils;
+import utils.text.Convert;
+
+import java.lang.reflect.*;
+import java.util.Date;
+
+/**
+ * 鍙嶅皠宸ュ叿绫�. 鎻愪緵璋冪敤getter/setter鏂规硶, 璁块棶绉佹湁鍙橀噺, 璋冪敤绉佹湁鏂规硶, 鑾峰彇娉涘瀷绫诲瀷Class, 琚獳OP杩囩殑鐪熷疄绫荤瓑宸ュ叿鍑芥暟.
+ * 
+ * @author ruoyi
+ */
+@SuppressWarnings("rawtypes")
+public class ReflectUtils
+{
+    private static final String SETTER_PREFIX = "set";
+
+    private static final String GETTER_PREFIX = "get";
+
+    private static final String CGLIB_CLASS_SEPARATOR = "$$";
+
+    private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);
+
+    /**
+     * 璋冪敤Getter鏂规硶.
+     * 鏀寔澶氱骇锛屽锛氬璞″悕.瀵硅薄鍚�.鏂规硶
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeGetter(Object obj, String propertyName)
+    {
+        Object object = obj;
+        for (String name : StringUtils.split(propertyName, "."))
+        {
+            String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
+            object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
+        }
+        return (E) object;
+    }
+
+    /**
+     * 璋冪敤Setter鏂规硶, 浠呭尮閰嶆柟娉曞悕銆�
+     * 鏀寔澶氱骇锛屽锛氬璞″悕.瀵硅薄鍚�.鏂规硶
+     */
+    public static <E> void invokeSetter(Object obj, String propertyName, E value)
+    {
+        Object object = obj;
+        String[] names = StringUtils.split(propertyName, ".");
+        for (int i = 0; i < names.length; i++)
+        {
+            if (i < names.length - 1)
+            {
+                String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
+                object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
+            }
+            else
+            {
+                String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
+                invokeMethodByName(object, setterMethodName, new Object[] { value });
+            }
+        }
+    }
+
+    /**
+     * 鐩存帴璇诲彇瀵硅薄灞炴�у��, 鏃犺private/protected淇グ绗�, 涓嶇粡杩噂etter鍑芥暟.
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E getFieldValue(final Object obj, final String fieldName)
+    {
+        Field field = getAccessibleField(obj, fieldName);
+        if (field == null)
+        {
+            logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + fieldName + "] 瀛楁 ");
+            return null;
+        }
+        E result = null;
+        try
+        {
+            result = (E) field.get(obj);
+        }
+        catch (IllegalAccessException e)
+        {
+            logger.error("涓嶅彲鑳芥姏鍑虹殑寮傚父{}", e.getMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 鐩存帴璁剧疆瀵硅薄灞炴�у��, 鏃犺private/protected淇グ绗�, 涓嶇粡杩噑etter鍑芥暟.
+     */
+    public static <E> void setFieldValue(final Object obj, final String fieldName, final E value)
+    {
+        Field field = getAccessibleField(obj, fieldName);
+        if (field == null)
+        {
+            // throw new IllegalArgumentException("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + fieldName + "] 瀛楁 ");
+            logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + fieldName + "] 瀛楁 ");
+            return;
+        }
+        try
+        {
+            field.set(obj, value);
+        }
+        catch (IllegalAccessException e)
+        {
+            logger.error("涓嶅彲鑳芥姏鍑虹殑寮傚父: {}", e.getMessage());
+        }
+    }
+
+    /**
+     * 鐩存帴璋冪敤瀵硅薄鏂规硶, 鏃犺private/protected淇グ绗�.
+     * 鐢ㄤ簬涓�娆℃�ц皟鐢ㄧ殑鎯呭喌锛屽惁鍒欏簲浣跨敤getAccessibleMethod()鍑芥暟鑾峰緱Method鍚庡弽澶嶈皟鐢�.
+     * 鍚屾椂鍖归厤鏂规硶鍚�+鍙傛暟绫诲瀷锛�
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
+            final Object[] args)
+    {
+        if (obj == null || methodName == null)
+        {
+            return null;
+        }
+        Method method = getAccessibleMethod(obj, methodName, parameterTypes);
+        if (method == null)
+        {
+            logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + methodName + "] 鏂规硶 ");
+            return null;
+        }
+        try
+        {
+            return (E) method.invoke(obj, args);
+        }
+        catch (Exception e)
+        {
+            String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
+            throw convertReflectionExceptionToUnchecked(msg, e);
+        }
+    }
+
+    /**
+     * 鐩存帴璋冪敤瀵硅薄鏂规硶, 鏃犺private/protected淇グ绗︼紝
+     * 鐢ㄤ簬涓�娆℃�ц皟鐢ㄧ殑鎯呭喌锛屽惁鍒欏簲浣跨敤getAccessibleMethodByName()鍑芥暟鑾峰緱Method鍚庡弽澶嶈皟鐢�.
+     * 鍙尮閰嶅嚱鏁板悕锛屽鏋滄湁澶氫釜鍚屽悕鍑芥暟璋冪敤绗竴涓��
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args)
+    {
+        Method method = getAccessibleMethodByName(obj, methodName, args.length);
+        if (method == null)
+        {
+            // 濡傛灉涓虹┖涓嶆姤閿欙紝鐩存帴杩斿洖绌恒��
+            logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + methodName + "] 鏂规硶 ");
+            return null;
+        }
+        try
+        {
+            // 绫诲瀷杞崲锛堝皢鍙傛暟鏁版嵁绫诲瀷杞崲涓虹洰鏍囨柟娉曞弬鏁扮被鍨嬶級
+            Class<?>[] cs = method.getParameterTypes();
+            for (int i = 0; i < cs.length; i++)
+            {
+                if (args[i] != null && !args[i].getClass().equals(cs[i]))
+                {
+                    if (cs[i] == String.class)
+                    {
+                        args[i] = Convert.toStr(args[i]);
+                        if (StringUtils.endsWith((String) args[i], ".0"))
+                        {
+                            args[i] = StringUtils.substringBefore((String) args[i], ".0");
+                        }
+                    }
+                    else if (cs[i] == Integer.class)
+                    {
+                        args[i] = Convert.toInt(args[i]);
+                    }
+                    else if (cs[i] == Long.class)
+                    {
+                        args[i] = Convert.toLong(args[i]);
+                    }
+                    else if (cs[i] == Double.class)
+                    {
+                        args[i] = Convert.toDouble(args[i]);
+                    }
+                    else if (cs[i] == Float.class)
+                    {
+                        args[i] = Convert.toFloat(args[i]);
+                    }
+                    else if (cs[i] == Date.class)
+                    {
+                        if (args[i] instanceof String)
+                        {
+                            args[i] = DateUtils.parseDate(args[i]);
+                        }
+                        else
+                        {
+                            args[i] = DateUtil.getJavaDate((Double) args[i]);
+                        }
+                    }
+                    else if (cs[i] == boolean.class || cs[i] == Boolean.class)
+                    {
+                        args[i] = Convert.toBool(args[i]);
+                    }
+                }
+            }
+            return (E) method.invoke(obj, args);
+        }
+        catch (Exception e)
+        {
+            String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
+            throw convertReflectionExceptionToUnchecked(msg, e);
+        }
+    }
+
+    /**
+     * 寰幆鍚戜笂杞瀷, 鑾峰彇瀵硅薄鐨凞eclaredField, 骞跺己鍒惰缃负鍙闂�.
+     * 濡傚悜涓婅浆鍨嬪埌Object浠嶆棤娉曟壘鍒�, 杩斿洖null.
+     */
+    public static Field getAccessibleField(final Object obj, final String fieldName)
+    {
+        // 涓虹┖涓嶆姤閿欍�傜洿鎺ヨ繑鍥� null
+        if (obj == null)
+        {
+            return null;
+        }
+        Validate.notBlank(fieldName, "fieldName can't be blank");
+        for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
+        {
+            try
+            {
+                Field field = superClass.getDeclaredField(fieldName);
+                makeAccessible(field);
+                return field;
+            }
+            catch (NoSuchFieldException e)
+            {
+                continue;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 寰幆鍚戜笂杞瀷, 鑾峰彇瀵硅薄鐨凞eclaredMethod,骞跺己鍒惰缃负鍙闂�.
+     * 濡傚悜涓婅浆鍨嬪埌Object浠嶆棤娉曟壘鍒�, 杩斿洖null.
+     * 鍖归厤鍑芥暟鍚�+鍙傛暟绫诲瀷銆�
+     * 鐢ㄤ簬鏂规硶闇�瑕佽澶氭璋冪敤鐨勬儏鍐�. 鍏堜娇鐢ㄦ湰鍑芥暟鍏堝彇寰桵ethod,鐒跺悗璋冪敤Method.invoke(Object obj, Object... args)
+     */
+    public static Method getAccessibleMethod(final Object obj, final String methodName,
+            final Class<?>... parameterTypes)
+    {
+        // 涓虹┖涓嶆姤閿欍�傜洿鎺ヨ繑鍥� null
+        if (obj == null)
+        {
+            return null;
+        }
+        Validate.notBlank(methodName, "methodName can't be blank");
+        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
+        {
+            try
+            {
+                Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
+                makeAccessible(method);
+                return method;
+            }
+            catch (NoSuchMethodException e)
+            {
+                continue;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 寰幆鍚戜笂杞瀷, 鑾峰彇瀵硅薄鐨凞eclaredMethod,骞跺己鍒惰缃负鍙闂�.
+     * 濡傚悜涓婅浆鍨嬪埌Object浠嶆棤娉曟壘鍒�, 杩斿洖null.
+     * 鍙尮閰嶅嚱鏁板悕銆�
+     * 鐢ㄤ簬鏂规硶闇�瑕佽澶氭璋冪敤鐨勬儏鍐�. 鍏堜娇鐢ㄦ湰鍑芥暟鍏堝彇寰桵ethod,鐒跺悗璋冪敤Method.invoke(Object obj, Object... args)
+     */
+    public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum)
+    {
+        // 涓虹┖涓嶆姤閿欍�傜洿鎺ヨ繑鍥� null
+        if (obj == null)
+        {
+            return null;
+        }
+        Validate.notBlank(methodName, "methodName can't be blank");
+        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
+        {
+            Method[] methods = searchType.getDeclaredMethods();
+            for (Method method : methods)
+            {
+                if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum)
+                {
+                    makeAccessible(method);
+                    return method;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 鏀瑰彉private/protected鐨勬柟娉曚负public锛屽敖閲忎笉璋冪敤瀹為檯鏀瑰姩鐨勮鍙ワ紝閬垮厤JDK鐨凷ecurityManager鎶辨�ㄣ��
+     */
+    public static void makeAccessible(Method method)
+    {
+        if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
+                && !method.isAccessible())
+        {
+            method.setAccessible(true);
+        }
+    }
+
+    /**
+     * 鏀瑰彉private/protected鐨勬垚鍛樺彉閲忎负public锛屽敖閲忎笉璋冪敤瀹為檯鏀瑰姩鐨勮鍙ワ紝閬垮厤JDK鐨凷ecurityManager鎶辨�ㄣ��
+     */
+    public static void makeAccessible(Field field)
+    {
+        if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
+                || Modifier.isFinal(field.getModifiers())) && !field.isAccessible())
+        {
+            field.setAccessible(true);
+        }
+    }
+
+    /**
+     * 閫氳繃鍙嶅皠, 鑾峰緱Class瀹氫箟涓0鏄庣殑娉涘瀷鍙傛暟鐨勭被鍨�, 娉ㄦ剰娉涘瀷蹇呴』瀹氫箟鍦ㄧ埗绫诲
+     * 濡傛棤娉曟壘鍒�, 杩斿洖Object.class.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Class<T> getClassGenricType(final Class clazz)
+    {
+        return getClassGenricType(clazz, 0);
+    }
+
+    /**
+     * 閫氳繃鍙嶅皠, 鑾峰緱Class瀹氫箟涓0鏄庣殑鐖剁被鐨勬硾鍨嬪弬鏁扮殑绫诲瀷.
+     * 濡傛棤娉曟壘鍒�, 杩斿洖Object.class.
+     */
+    public static Class getClassGenricType(final Class clazz, final int index)
+    {
+        Type genType = clazz.getGenericSuperclass();
+
+        if (!(genType instanceof ParameterizedType))
+        {
+            logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType");
+            return Object.class;
+        }
+
+        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
+
+        if (index >= params.length || index < 0)
+        {
+            logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+                    + params.length);
+            return Object.class;
+        }
+        if (!(params[index] instanceof Class))
+        {
+            logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
+            return Object.class;
+        }
+
+        return (Class) params[index];
+    }
+
+    public static Class<?> getUserClass(Object instance)
+    {
+        if (instance == null)
+        {
+            throw new RuntimeException("Instance must not be null");
+        }
+        Class clazz = instance.getClass();
+        if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR))
+        {
+            Class<?> superClass = clazz.getSuperclass();
+            if (superClass != null && !Object.class.equals(superClass))
+            {
+                return superClass;
+            }
+        }
+        return clazz;
+
+    }
+
+    /**
+     * 灏嗗弽灏勬椂鐨刢hecked exception杞崲涓簎nchecked exception.
+     */
+    public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e)
+    {
+        if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
+                || e instanceof NoSuchMethodException)
+        {
+            return new IllegalArgumentException(msg, e);
+        }
+        else if (e instanceof InvocationTargetException)
+        {
+            return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());
+        }
+        return new RuntimeException(msg, e);
+    }
+}
diff --git a/ycl-common/src/main/java/utils/uuid/IdUtils.java b/ycl-common/src/main/java/utils/uuid/IdUtils.java
new file mode 100644
index 0000000..2eb86cd
--- /dev/null
+++ b/ycl-common/src/main/java/utils/uuid/IdUtils.java
@@ -0,0 +1,49 @@
+package utils.uuid;
+
+/**
+ * ID鐢熸垚鍣ㄥ伐鍏风被
+ * 
+ * @author ruoyi
+ */
+public class IdUtils
+{
+    /**
+     * 鑾峰彇闅忔満UUID
+     * 
+     * @return 闅忔満UUID
+     */
+    public static String randomUUID()
+    {
+        return UUID.randomUUID().toString();
+    }
+
+    /**
+     * 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎
+     *
+     * @return 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎
+     */
+    public static String simpleUUID()
+    {
+        return UUID.randomUUID().toString(true);
+    }
+
+    /**
+     * 鑾峰彇闅忔満UUID锛屼娇鐢ㄦ�ц兘鏇村ソ鐨凾hreadLocalRandom鐢熸垚UUID
+     *
+     * @return 闅忔満UUID
+     */
+    public static String fastUUID()
+    {
+        return UUID.fastUUID().toString();
+    }
+
+    /**
+     * 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎锛屼娇鐢ㄦ�ц兘鏇村ソ鐨凾hreadLocalRandom鐢熸垚UUID
+     * 
+     * @return 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎
+     */
+    public static String fastSimpleUUID()
+    {
+        return UUID.fastUUID().toString(true);
+    }
+}
diff --git a/ycl-common/src/main/java/utils/uuid/Seq.java b/ycl-common/src/main/java/utils/uuid/Seq.java
new file mode 100644
index 0000000..96cab0f
--- /dev/null
+++ b/ycl-common/src/main/java/utils/uuid/Seq.java
@@ -0,0 +1,87 @@
+package utils.uuid;
+
+import utils.DateUtils;
+import utils.StringUtils;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author ruoyi 搴忓垪鐢熸垚绫�
+ */
+public class Seq
+{
+    // 閫氱敤搴忓垪绫诲瀷
+    public static final String commSeqType = "COMMON";
+
+    // 涓婁紶搴忓垪绫诲瀷
+    public static final String uploadSeqType = "UPLOAD";
+
+    // 閫氱敤鎺ュ彛搴忓垪鏁�
+    private static AtomicInteger commSeq = new AtomicInteger(1);
+
+    // 涓婁紶鎺ュ彛搴忓垪鏁�
+    private static AtomicInteger uploadSeq = new AtomicInteger(1);
+
+    // 鏈哄櫒鏍囪瘑
+    private static final String machineCode = "A";
+
+    /**
+     * 鑾峰彇閫氱敤搴忓垪鍙�
+     * 
+     * @return 搴忓垪鍊�
+     */
+    public static String getId()
+    {
+        return getId(commSeqType);
+    }
+    
+    /**
+     * 榛樿16浣嶅簭鍒楀彿 yyMMddHHmmss + 涓�浣嶆満鍣ㄦ爣璇� + 3闀垮害寰幆閫掑瀛楃涓�
+     * 
+     * @return 搴忓垪鍊�
+     */
+    public static String getId(String type)
+    {
+        AtomicInteger atomicInt = commSeq;
+        if (uploadSeqType.equals(type))
+        {
+            atomicInt = uploadSeq;
+        }
+        return getId(atomicInt, 3);
+    }
+
+    /**
+     * 閫氱敤鎺ュ彛搴忓垪鍙� yyMMddHHmmss + 涓�浣嶆満鍣ㄦ爣璇� + length闀垮害寰幆閫掑瀛楃涓�
+     * 
+     * @param atomicInt 搴忓垪鏁�
+     * @param length 鏁板�奸暱搴�
+     * @return 搴忓垪鍊�
+     */
+    public static String getId(AtomicInteger atomicInt, int length)
+    {
+        String result = DateUtils.dateTimeNow();
+        result += machineCode;
+        result += getSeq(atomicInt, length);
+        return result;
+    }
+
+    /**
+     * 搴忓垪寰幆閫掑瀛楃涓瞇1, 10 鐨� (length)骞傛鏂�), 鐢�0宸﹁ˉ榻恖ength浣嶆暟
+     * 
+     * @return 搴忓垪鍊�
+     */
+    private synchronized static String getSeq(AtomicInteger atomicInt, int length)
+    {
+        // 鍏堝彇鍊煎啀+1
+        int value = atomicInt.getAndIncrement();
+
+        // 濡傛灉鏇存柊鍚庡��>=10 鐨� (length)骞傛鏂瑰垯閲嶇疆涓�1
+        int maxSeq = (int) Math.pow(10, length);
+        if (atomicInt.get() >= maxSeq)
+        {
+            atomicInt.set(1);
+        }
+        // 杞瓧绗︿覆锛岀敤0宸﹁ˉ榻�
+        return StringUtils.padl(value, length);
+    }
+}
diff --git a/ycl-common/src/main/java/utils/uuid/UUID.java b/ycl-common/src/main/java/utils/uuid/UUID.java
new file mode 100644
index 0000000..5a6d24f
--- /dev/null
+++ b/ycl-common/src/main/java/utils/uuid/UUID.java
@@ -0,0 +1,485 @@
+package utils.uuid;
+
+import exception.UtilException;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * 鎻愪緵閫氱敤鍞竴璇嗗埆鐮侊紙universally unique identifier锛夛紙UUID锛夊疄鐜�
+ *
+ * @author ruoyi
+ */
+public final class UUID implements java.io.Serializable, Comparable<UUID>
+{
+    private static final long serialVersionUID = -1185015143654744140L;
+
+    /**
+     * SecureRandom 鐨勫崟渚�
+     *
+     */
+    private static class Holder
+    {
+        static final SecureRandom numberGenerator = getSecureRandom();
+    }
+
+    /** 姝UID鐨勬渶楂�64鏈夋晥浣� */
+    private final long mostSigBits;
+
+    /** 姝UID鐨勬渶浣�64鏈夋晥浣� */
+    private final long leastSigBits;
+
+    /**
+     * 绉佹湁鏋勯��
+     * 
+     * @param data 鏁版嵁
+     */
+    private UUID(byte[] data)
+    {
+        long msb = 0;
+        long lsb = 0;
+        assert data.length == 16 : "data must be 16 bytes in length";
+        for (int i = 0; i < 8; i++)
+        {
+            msb = (msb << 8) | (data[i] & 0xff);
+        }
+        for (int i = 8; i < 16; i++)
+        {
+            lsb = (lsb << 8) | (data[i] & 0xff);
+        }
+        this.mostSigBits = msb;
+        this.leastSigBits = lsb;
+    }
+
+    /**
+     * 浣跨敤鎸囧畾鐨勬暟鎹瀯閫犳柊鐨� UUID銆�
+     *
+     * @param mostSigBits 鐢ㄤ簬 {@code UUID} 鐨勬渶楂樻湁鏁� 64 浣�
+     * @param leastSigBits 鐢ㄤ簬 {@code UUID} 鐨勬渶浣庢湁鏁� 64 浣�
+     */
+    public UUID(long mostSigBits, long leastSigBits)
+    {
+        this.mostSigBits = mostSigBits;
+        this.leastSigBits = leastSigBits;
+    }
+
+    /**
+     * 鑾峰彇绫诲瀷 4锛堜吉闅忔満鐢熸垚鐨勶級UUID 鐨勯潤鎬佸伐鍘傘��
+     * 
+     * @return 闅忔満鐢熸垚鐨� {@code UUID}
+     */
+    public static UUID fastUUID()
+    {
+        return randomUUID(false);
+    }
+
+    /**
+     * 鑾峰彇绫诲瀷 4锛堜吉闅忔満鐢熸垚鐨勶級UUID 鐨勯潤鎬佸伐鍘傘�� 浣跨敤鍔犲瘑鐨勫己浼殢鏈烘暟鐢熸垚鍣ㄧ敓鎴愯 UUID銆�
+     * 
+     * @return 闅忔満鐢熸垚鐨� {@code UUID}
+     */
+    public static UUID randomUUID()
+    {
+        return randomUUID(true);
+    }
+
+    /**
+     * 鑾峰彇绫诲瀷 4锛堜吉闅忔満鐢熸垚鐨勶級UUID 鐨勯潤鎬佸伐鍘傘�� 浣跨敤鍔犲瘑鐨勫己浼殢鏈烘暟鐢熸垚鍣ㄧ敓鎴愯 UUID銆�
+     * 
+     * @param isSecure 鏄惁浣跨敤{@link SecureRandom}濡傛灉鏄彲浠ヨ幏寰楁洿瀹夊叏鐨勯殢鏈虹爜锛屽惁鍒欏彲浠ュ緱鍒版洿濂界殑鎬ц兘
+     * @return 闅忔満鐢熸垚鐨� {@code UUID}
+     */
+    public static UUID randomUUID(boolean isSecure)
+    {
+        final Random ng = isSecure ? Holder.numberGenerator : getRandom();
+
+        byte[] randomBytes = new byte[16];
+        ng.nextBytes(randomBytes);
+        randomBytes[6] &= 0x0f; /* clear version */
+        randomBytes[6] |= 0x40; /* set to version 4 */
+        randomBytes[8] &= 0x3f; /* clear variant */
+        randomBytes[8] |= 0x80; /* set to IETF variant */
+        return new UUID(randomBytes);
+    }
+
+    /**
+     * 鏍规嵁鎸囧畾鐨勫瓧鑺傛暟缁勮幏鍙栫被鍨� 3锛堝熀浜庡悕绉扮殑锛塙UID 鐨勯潤鎬佸伐鍘傘��
+     *
+     * @param name 鐢ㄤ簬鏋勯�� UUID 鐨勫瓧鑺傛暟缁勩��
+     *
+     * @return 鏍规嵁鎸囧畾鏁扮粍鐢熸垚鐨� {@code UUID}
+     */
+    public static UUID nameUUIDFromBytes(byte[] name)
+    {
+        MessageDigest md;
+        try
+        {
+            md = MessageDigest.getInstance("MD5");
+        }
+        catch (NoSuchAlgorithmException nsae)
+        {
+            throw new InternalError("MD5 not supported");
+        }
+        byte[] md5Bytes = md.digest(name);
+        md5Bytes[6] &= 0x0f; /* clear version */
+        md5Bytes[6] |= 0x30; /* set to version 3 */
+        md5Bytes[8] &= 0x3f; /* clear variant */
+        md5Bytes[8] |= 0x80; /* set to IETF variant */
+        return new UUID(md5Bytes);
+    }
+
+    /**
+     * 鏍规嵁 {@link #toString()} 鏂规硶涓弿杩扮殑瀛楃涓叉爣鍑嗚〃绀哄舰寮忓垱寤簕@code UUID}銆�
+     *
+     * @param name 鎸囧畾 {@code UUID} 瀛楃涓�
+     * @return 鍏锋湁鎸囧畾鍊肩殑 {@code UUID}
+     * @throws IllegalArgumentException 濡傛灉 name 涓� {@link #toString} 涓弿杩扮殑瀛楃涓茶〃绀哄舰寮忎笉绗︽姏鍑烘寮傚父
+     *
+     */
+    public static UUID fromString(String name)
+    {
+        String[] components = name.split("-");
+        if (components.length != 5)
+        {
+            throw new IllegalArgumentException("Invalid UUID string: " + name);
+        }
+        for (int i = 0; i < 5; i++)
+        {
+            components[i] = "0x" + components[i];
+        }
+
+        long mostSigBits = Long.decode(components[0]).longValue();
+        mostSigBits <<= 16;
+        mostSigBits |= Long.decode(components[1]).longValue();
+        mostSigBits <<= 16;
+        mostSigBits |= Long.decode(components[2]).longValue();
+
+        long leastSigBits = Long.decode(components[3]).longValue();
+        leastSigBits <<= 48;
+        leastSigBits |= Long.decode(components[4]).longValue();
+
+        return new UUID(mostSigBits, leastSigBits);
+    }
+
+    /**
+     * 杩斿洖姝� UUID 鐨� 128 浣嶅�间腑鐨勬渶浣庢湁鏁� 64 浣嶃��
+     *
+     * @return 姝� UUID 鐨� 128 浣嶅�间腑鐨勬渶浣庢湁鏁� 64 浣嶃��
+     */
+    public long getLeastSignificantBits()
+    {
+        return leastSigBits;
+    }
+
+    /**
+     * 杩斿洖姝� UUID 鐨� 128 浣嶅�间腑鐨勬渶楂樻湁鏁� 64 浣嶃��
+     *
+     * @return 姝� UUID 鐨� 128 浣嶅�间腑鏈�楂樻湁鏁� 64 浣嶃��
+     */
+    public long getMostSignificantBits()
+    {
+        return mostSigBits;
+    }
+
+    /**
+     * 涓庢 {@code UUID} 鐩稿叧鑱旂殑鐗堟湰鍙�. 鐗堟湰鍙锋弿杩版 {@code UUID} 鏄浣曠敓鎴愮殑銆�
+     * <p>
+     * 鐗堟湰鍙峰叿鏈変互涓嬪惈鎰�:
+     * <ul>
+     * <li>1 鍩轰簬鏃堕棿鐨� UUID
+     * <li>2 DCE 瀹夊叏 UUID
+     * <li>3 鍩轰簬鍚嶇О鐨� UUID
+     * <li>4 闅忔満鐢熸垚鐨� UUID
+     * </ul>
+     *
+     * @return 姝� {@code UUID} 鐨勭増鏈彿
+     */
+    public int version()
+    {
+        // Version is bits masked by 0x000000000000F000 in MS long
+        return (int) ((mostSigBits >> 12) & 0x0f);
+    }
+
+    /**
+     * 涓庢 {@code UUID} 鐩稿叧鑱旂殑鍙樹綋鍙枫�傚彉浣撳彿鎻忚堪 {@code UUID} 鐨勫竷灞�銆�
+     * <p>
+     * 鍙樹綋鍙峰叿鏈変互涓嬪惈鎰忥細
+     * <ul>
+     * <li>0 涓� NCS 鍚戝悗鍏煎淇濈暀
+     * <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF&nbsp;RFC&nbsp;4122</a>(Leach-Salz), 鐢ㄤ簬姝ょ被
+     * <li>6 淇濈暀锛屽井杞悜鍚庡吋瀹�
+     * <li>7 淇濈暀渚涗互鍚庡畾涔変娇鐢�
+     * </ul>
+     *
+     * @return 姝� {@code UUID} 鐩稿叧鑱旂殑鍙樹綋鍙�
+     */
+    public int variant()
+    {
+        // This field is composed of a varying number of bits.
+        // 0 - - Reserved for NCS backward compatibility
+        // 1 0 - The IETF aka Leach-Salz variant (used by this class)
+        // 1 1 0 Reserved, Microsoft backward compatibility
+        // 1 1 1 Reserved for future definition.
+        return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
+    }
+
+    /**
+     * 涓庢 UUID 鐩稿叧鑱旂殑鏃堕棿鎴冲�笺��
+     *
+     * <p>
+     * 60 浣嶇殑鏃堕棿鎴冲�兼牴鎹 {@code UUID} 鐨� time_low銆乼ime_mid 鍜� time_hi 瀛楁鏋勯�犮��<br>
+     * 鎵�寰楀埌鐨勬椂闂存埑浠� 100 姣井绉掍负鍗曚綅锛屼粠 UTC锛堥�氱敤鍗忚皟鏃堕棿锛� 1582 骞� 10 鏈� 15 鏃ラ浂鏃跺紑濮嬨��
+     *
+     * <p>
+     * 鏃堕棿鎴冲�间粎鍦ㄥ湪鍩轰簬鏃堕棿鐨� UUID锛堝叾 version 绫诲瀷涓� 1锛変腑鎵嶆湁鎰忎箟銆�<br>
+     * 濡傛灉姝� {@code UUID} 涓嶆槸鍩轰簬鏃堕棿鐨� UUID锛屽垯姝ゆ柟娉曟姏鍑� UnsupportedOperationException銆�
+     *
+     * @throws UnsupportedOperationException 濡傛灉姝� {@code UUID} 涓嶆槸 version 涓� 1 鐨� UUID銆�
+     */
+    public long timestamp() throws UnsupportedOperationException
+    {
+        checkTimeBase();
+        return (mostSigBits & 0x0FFFL) << 48//
+                | ((mostSigBits >> 16) & 0x0FFFFL) << 32//
+                | mostSigBits >>> 32;
+    }
+
+    /**
+     * 涓庢 UUID 鐩稿叧鑱旂殑鏃堕挓搴忓垪鍊笺��
+     *
+     * <p>
+     * 14 浣嶇殑鏃堕挓搴忓垪鍊兼牴鎹 UUID 鐨� clock_seq 瀛楁鏋勯�犮�俢lock_seq 瀛楁鐢ㄤ簬淇濊瘉鍦ㄥ熀浜庢椂闂寸殑 UUID 涓殑鏃堕棿鍞竴鎬с��
+     * <p>
+     * {@code clockSequence} 鍊间粎鍦ㄥ熀浜庢椂闂寸殑 UUID锛堝叾 version 绫诲瀷涓� 1锛変腑鎵嶆湁鎰忎箟銆� 濡傛灉姝� UUID 涓嶆槸鍩轰簬鏃堕棿鐨� UUID锛屽垯姝ゆ柟娉曟姏鍑�
+     * UnsupportedOperationException銆�
+     *
+     * @return 姝� {@code UUID} 鐨勬椂閽熷簭鍒�
+     *
+     * @throws UnsupportedOperationException 濡傛灉姝� UUID 鐨� version 涓嶄负 1
+     */
+    public int clockSequence() throws UnsupportedOperationException
+    {
+        checkTimeBase();
+        return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
+    }
+
+    /**
+     * 涓庢 UUID 鐩稿叧鐨勮妭鐐瑰�笺��
+     *
+     * <p>
+     * 48 浣嶇殑鑺傜偣鍊兼牴鎹 UUID 鐨� node 瀛楁鏋勯�犮�傛瀛楁鏃ㄥ湪鐢ㄤ簬淇濆瓨鏈哄櫒鐨� IEEE 802 鍦板潃锛岃鍦板潃鐢ㄤ簬鐢熸垚姝� UUID 浠ヤ繚璇佺┖闂村敮涓�鎬с��
+     * <p>
+     * 鑺傜偣鍊间粎鍦ㄥ熀浜庢椂闂寸殑 UUID锛堝叾 version 绫诲瀷涓� 1锛変腑鎵嶆湁鎰忎箟銆�<br>
+     * 濡傛灉姝� UUID 涓嶆槸鍩轰簬鏃堕棿鐨� UUID锛屽垯姝ゆ柟娉曟姏鍑� UnsupportedOperationException銆�
+     *
+     * @return 姝� {@code UUID} 鐨勮妭鐐瑰��
+     *
+     * @throws UnsupportedOperationException 濡傛灉姝� UUID 鐨� version 涓嶄负 1
+     */
+    public long node() throws UnsupportedOperationException
+    {
+        checkTimeBase();
+        return leastSigBits & 0x0000FFFFFFFFFFFFL;
+    }
+
+    /**
+     * 杩斿洖姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡銆�
+     *
+     * <p>
+     * UUID 鐨勫瓧绗︿覆琛ㄧず褰㈠紡鐢辨 BNF 鎻忚堪锛�
+     * 
+     * <pre>
+     * {@code
+     * UUID                   = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
+     * time_low               = 4*<hexOctet>
+     * time_mid               = 2*<hexOctet>
+     * time_high_and_version  = 2*<hexOctet>
+     * variant_and_sequence   = 2*<hexOctet>
+     * node                   = 6*<hexOctet>
+     * hexOctet               = <hexDigit><hexDigit>
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * </pre>
+     * 
+     * </blockquote>
+     *
+     * @return 姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡
+     * @see #toString(boolean)
+     */
+    @Override
+    public String toString()
+    {
+        return toString(false);
+    }
+
+    /**
+     * 杩斿洖姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡銆�
+     *
+     * <p>
+     * UUID 鐨勫瓧绗︿覆琛ㄧず褰㈠紡鐢辨 BNF 鎻忚堪锛�
+     * 
+     * <pre>
+     * {@code
+     * UUID                   = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
+     * time_low               = 4*<hexOctet>
+     * time_mid               = 2*<hexOctet>
+     * time_high_and_version  = 2*<hexOctet>
+     * variant_and_sequence   = 2*<hexOctet>
+     * node                   = 6*<hexOctet>
+     * hexOctet               = <hexDigit><hexDigit>
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * </pre>
+     * 
+     * </blockquote>
+     *
+     * @param isSimple 鏄惁绠�鍗曟ā寮忥紝绠�鍗曟ā寮忎负涓嶅甫'-'鐨刄UID瀛楃涓�
+     * @return 姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡
+     */
+    public String toString(boolean isSimple)
+    {
+        final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
+        // time_low
+        builder.append(digits(mostSigBits >> 32, 8));
+        if (!isSimple)
+        {
+            builder.append('-');
+        }
+        // time_mid
+        builder.append(digits(mostSigBits >> 16, 4));
+        if (!isSimple)
+        {
+            builder.append('-');
+        }
+        // time_high_and_version
+        builder.append(digits(mostSigBits, 4));
+        if (!isSimple)
+        {
+            builder.append('-');
+        }
+        // variant_and_sequence
+        builder.append(digits(leastSigBits >> 48, 4));
+        if (!isSimple)
+        {
+            builder.append('-');
+        }
+        // node
+        builder.append(digits(leastSigBits, 12));
+
+        return builder.toString();
+    }
+
+    /**
+     * 杩斿洖姝� UUID 鐨勫搱甯岀爜銆�
+     *
+     * @return UUID 鐨勫搱甯岀爜鍊笺��
+     */
+    @Override
+    public int hashCode()
+    {
+        long hilo = mostSigBits ^ leastSigBits;
+        return ((int) (hilo >> 32)) ^ (int) hilo;
+    }
+
+    /**
+     * 灏嗘瀵硅薄涓庢寚瀹氬璞℃瘮杈冦��
+     * <p>
+     * 褰撲笖浠呭綋鍙傛暟涓嶄负 {@code null}銆佽�屾槸涓�涓� UUID 瀵硅薄銆佸叿鏈変笌姝� UUID 鐩稿悓鐨� varriant銆佸寘鍚浉鍚岀殑鍊硷紙姣忎竴浣嶅潎鐩稿悓锛夋椂锛岀粨鏋滄墠涓� {@code true}銆�
+     *
+     * @param obj 瑕佷笌涔嬫瘮杈冪殑瀵硅薄
+     *
+     * @return 濡傛灉瀵硅薄鐩稿悓锛屽垯杩斿洖 {@code true}锛涘惁鍒欒繑鍥� {@code false}
+     */
+    @Override
+    public boolean equals(Object obj)
+    {
+        if ((null == obj) || (obj.getClass() != UUID.class))
+        {
+            return false;
+        }
+        UUID id = (UUID) obj;
+        return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
+    }
+
+    // Comparison Operations
+
+    /**
+     * 灏嗘 UUID 涓庢寚瀹氱殑 UUID 姣旇緝銆�
+     *
+     * <p>
+     * 濡傛灉涓や釜 UUID 涓嶅悓锛屼笖绗竴涓� UUID 鐨勬渶楂樻湁鏁堝瓧娈靛ぇ浜庣浜屼釜 UUID 鐨勫搴斿瓧娈碉紝鍒欑涓�涓� UUID 澶т簬绗簩涓� UUID銆�
+     *
+     * @param val 涓庢 UUID 姣旇緝鐨� UUID
+     *
+     * @return 鍦ㄦ UUID 灏忎簬銆佺瓑浜庢垨澶т簬 val 鏃讹紝鍒嗗埆杩斿洖 -1銆�0 鎴� 1銆�
+     *
+     */
+    @Override
+    public int compareTo(UUID val)
+    {
+        // The ordering is intentionally set up so that the UUIDs
+        // can simply be numerically compared as two numbers
+        return (this.mostSigBits < val.mostSigBits ? -1 : //
+                (this.mostSigBits > val.mostSigBits ? 1 : //
+                        (this.leastSigBits < val.leastSigBits ? -1 : //
+                                (this.leastSigBits > val.leastSigBits ? 1 : //
+                                        0))));
+    }
+
+    // -------------------------------------------------------------------------------------------------------------------
+    // Private method start
+    /**
+     * 杩斿洖鎸囧畾鏁板瓧瀵瑰簲鐨刪ex鍊�
+     * 
+     * @param val 鍊�
+     * @param digits 浣�
+     * @return 鍊�
+     */
+    private static String digits(long val, int digits)
+    {
+        long hi = 1L << (digits * 4);
+        return Long.toHexString(hi | (val & (hi - 1))).substring(1);
+    }
+
+    /**
+     * 妫�鏌ユ槸鍚︿负time-based鐗堟湰UUID
+     */
+    private void checkTimeBase()
+    {
+        if (version() != 1)
+        {
+            throw new UnsupportedOperationException("Not a time-based UUID");
+        }
+    }
+
+    /**
+     * 鑾峰彇{@link SecureRandom}锛岀被鎻愪緵鍔犲瘑鐨勫己闅忔満鏁扮敓鎴愬櫒 (RNG)
+     * 
+     * @return {@link SecureRandom}
+     */
+    public static SecureRandom getSecureRandom()
+    {
+        try
+        {
+            return SecureRandom.getInstance("SHA1PRNG");
+        }
+        catch (NoSuchAlgorithmException e)
+        {
+            throw new UtilException(e);
+        }
+    }
+
+    /**
+     * 鑾峰彇闅忔満鏁扮敓鎴愬櫒瀵硅薄<br>
+     * ThreadLocalRandom鏄疛DK 7涔嬪悗鎻愪緵骞跺彂浜х敓闅忔満鏁帮紝鑳藉瑙e喅澶氫釜绾跨▼鍙戠敓鐨勭珵浜変簤澶恒��
+     * 
+     * @return {@link ThreadLocalRandom}
+     */
+    public static ThreadLocalRandom getRandom()
+    {
+        return ThreadLocalRandom.current();
+    }
+}
diff --git a/ycl-generator/src/main/resources/vm/java/controller.java.vm b/ycl-generator/src/main/resources/vm/java/controller.java.vm
index 9e32eb7..374e71a 100644
--- a/ycl-generator/src/main/resources/vm/java/controller.java.vm
+++ b/ycl-generator/src/main/resources/vm/java/controller.java.vm
@@ -21,6 +21,7 @@
 import com.ycl.common.utils.poi.ExcelUtil;
 #if($table.crud || $table.sub)
 import com.ycl.common.core.page.TableDataInfo;
+import pojo.AjaxResult;
 #elseif($table.tree)
 #end
 
diff --git a/ycl-pojo/src/main/java/com/ycl/platform/entity/TMonitor.java b/ycl-pojo/src/main/java/com/ycl/platform/entity/TMonitor.java
new file mode 100644
index 0000000..e531e58
--- /dev/null
+++ b/ycl-pojo/src/main/java/com/ycl/platform/entity/TMonitor.java
@@ -0,0 +1,461 @@
+package com.ycl.platform.entity;
+
+import annotation.Excel;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ycl.system.entity.BaseEntity;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
+import java.util.Date;
+
+/**
+ * 璁惧璧勪骇瀵硅薄 t_monitor
+ * 
+ * @author ruoyi
+ * @date 2024-03-04
+ */
+public class TMonitor extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 璁惧缂栫爜 */
+    @Excel(name = "璁惧缂栫爜")
+    private String serialNumber;
+
+    /** 璁惧鍚嶇О */
+    @Excel(name = "璁惧鍚嶇О")
+    private String name;
+
+    /** 鐩戞帶鐐逛綅绫诲瀷 [1.涓�绫昏棰戠洃鎺х偣;2.浜岀被瑙嗛鐩戞帶鐐�;3.涓夌被瑙嗛鐩戞帶鐐�;4.鍏畨鍐呴儴瑙嗛鐩戞帶鐐�;9.鍏朵粬鐐逛綅;] */
+    @Excel(name = "鐩戞帶鐐逛綅绫诲瀷 [1.涓�绫昏棰戠洃鎺х偣;2.浜岀被瑙嗛鐩戞帶鐐�;3.涓夌被瑙嗛鐩戞帶鐐�;4.鍏畨鍐呴儴瑙嗛鐩戞帶鐐�;9.鍏朵粬鐐逛綅;]")
+    private Long siteType;
+
+    /** 鎽勫儚鏈篗ac鍦板潃 */
+    @Excel(name = "鎽勫儚鏈篗ac鍦板潃")
+    private String macAddr;
+
+    /** 鎽勫儚鏈篒PV4鎴朓PV6鍦板潃 */
+    @Excel(name = "鎽勫儚鏈篒PV4鎴朓PV6鍦板潃")
+    private String ip;
+
+    /** 鎽勫儚鏈哄姛鑳界被鍨媅1.瑙嗛鐩戞帶;2.杞﹁締璇嗗埆;3.浜哄憳璇嗗埆;] 鏁版嵁鏍煎紡[濉叆澶氫釜鍊煎苟浠�/闅斿紑銆備緥濡�  1/2] */
+    @Excel(name = "鎽勫儚鏈哄姛鑳界被鍨媅1.瑙嗛鐩戞帶;2.杞﹁締璇嗗埆;3.浜哄憳璇嗗埆;] 鏁版嵁鏍煎紡[濉叆澶氫釜鍊煎苟浠�/闅斿紑銆備緥濡�  1/2]")
+    private String cameraFunType;
+
+    /** 璁惧缁忓害锛岃嚦灏戜繚鐣欏叚浣嶅皬鏁� */
+    @Excel(name = "璁惧缁忓害锛岃嚦灏戜繚鐣欏叚浣嶅皬鏁�")
+    private String longitude;
+
+    /** 璁惧缁村害锛岃嚦灏戜繚鐣欏叚浣嶅皬鏁� */
+    @Excel(name = "璁惧缁村害锛岃嚦灏戜繚鐣欏叚浣嶅皬鏁�")
+    private String latitude;
+
+    /** 鎽勫儚鏈洪噰闆嗗尯鍩熷弬鑰冨瓧鍏歌〃锛屾暟鎹閫変互/闅斿紑 */
+    @Excel(name = "鎽勫儚鏈洪噰闆嗗尯鍩熷弬鑰冨瓧鍏歌〃锛屾暟鎹閫変互/闅斿紑")
+    private String cameraCaptureArea;
+
+    /** 璁惧鐘舵�� 1/2 鍙敤/涓嶅彲鐢� */
+    @Excel(name = "璁惧鐘舵�� 1/2 鍙敤/涓嶅彲鐢�")
+    private Long onState;
+
+    /** 琛屾斂鍖哄煙 */
+    @Excel(name = "琛屾斂鍖哄煙")
+    private String civilCode;
+
+    /** 鏄惁闆嗘垚璁惧锛�0/1 涓嶆槸/鏄� */
+    @Excel(name = "鏄惁闆嗘垚璁惧锛�0/1 涓嶆槸/鏄�")
+    private Long integratedDevice;
+
+    /** 鎽勫儚鏈哄搧鐗� [1.娴峰悍濞佽;2.澶у崕;3.澶╁湴浼熶笟;4.绉戣揪;5.瀹夎澹�;6.鍗氫笘;7.浜氬畨;8.鑻遍鎷�;9.瀹囪;10.娴蜂俊;11.涓槦鐢靛瓙;12.鏄庢櫙;13.鑱旀兂;14.涓叴;15.绱㈠凹;16.涓夋槦;99.鍏跺畠; */
+    @Excel(name = "鎽勫儚鏈哄搧鐗� [1.娴峰悍濞佽;2.澶у崕;3.澶╁湴浼熶笟;4.绉戣揪;5.瀹夎澹�;6.鍗氫笘;7.浜氬畨;8.鑻遍鎷�;9.瀹囪;10.娴蜂俊;11.涓槦鐢靛瓙;12.鏄庢櫙;13.鑱旀兂;14.涓叴;15.绱㈠凹;16.涓夋槦;99.鍏跺畠;")
+    private Long cameraBrand;
+
+    /** 瀹夎鍦板潃 */
+    @Excel(name = "瀹夎鍦板潃")
+    private String address;
+
+    /** 鑱旂綉灞炴�� 0/1 宸茶仈缃�/鏈仈缃� */
+    @Excel(name = "鑱旂綉灞炴�� 0/1 宸茶仈缃�/鏈仈缃�")
+    private Long netWorking;
+
+    /** 鎵�灞炶緰鍖哄叕瀹夋満鍏� */
+    @Excel(name = "鎵�灞炶緰鍖哄叕瀹夋満鍏�")
+    private String publicSecurity;
+
+    /** 瀹夎鏃堕棿 yyyy-MM-dd HH:mm:ss */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "瀹夎鏃堕棿 yyyy-MM-dd HH:mm:ss", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date installedTime;
+
+    /** 绠$悊鍗曚綅 */
+    @Excel(name = "绠$悊鍗曚綅")
+    private String managementUnit;
+
+    /** 绠$悊鍗曚綅鑱旂郴鏂瑰紡 */
+    @Excel(name = "绠$悊鍗曚綅鑱旂郴鏂瑰紡")
+    private String muContactInfo;
+
+    /** 褰曡薄淇濆瓨澶╂暟 0 - 2147483647 */
+    @Excel(name = "褰曡薄淇濆瓨澶╂暟 0 - 2147483647")
+    private Long storageDays;
+
+    /** 鐩戣鏂逛綅 [1.涓�;2.瑗�;3.鍗�;4.鍖�;5.涓滃崡;6.涓滃寳;7.瑗垮崡;8.瑗垮寳;9.鍏ㄥ悜;] */
+    @Excel(name = "鐩戣鏂逛綅 [1.涓�;2.瑗�;3.鍗�;4.鍖�;5.涓滃崡;6.涓滃寳;7.瑗垮崡;8.瑗垮寳;9.鍏ㄥ悜;]")
+    private Long monitorAzimuth;
+
+    /** 鎽勫儚鏈哄満鏅璁剧収鐗嘦RL */
+    @Excel(name = "鎽勫儚鏈哄満鏅璁剧収鐗嘦RL")
+    private String scenePhotoAddr;
+
+    /** 璁惧鍨嬪彿 */
+    @Excel(name = "璁惧鍨嬪彿")
+    private String model;
+
+    /** 鐐逛綅淇楃О */
+    @Excel(name = "鐐逛綅淇楃О")
+    private String siteVulgo;
+
+    /** 鎽勫儚鏈虹被鍨� [1.鐞冩満;2.鍗婄悆;3.鍥哄畾鏋満;4.閬ユ帶鏋満;5.鍗″彛鏋満;99.鏈煡; */
+    @Excel(name = "鎽勫儚鏈虹被鍨� [1.鐞冩満;2.鍗婄悆;3.鍥哄畾鏋満;4.閬ユ帶鏋満;5.鍗″彛鏋満;99.鏈煡;")
+    private Long cameraType;
+
+    /** 琛ュ厜灞炴�1.鏃犺ˉ鍏�;2.绾㈠琛ュ厜;3.鐧藉厜琛ュ厜;9.鍏朵粬琛ュ厜;]  */
+    @Excel(name = "琛ュ厜灞炴�1.鏃犺ˉ鍏�;2.绾㈠琛ュ厜;3.鐧藉厜琛ュ厜;9.鍏朵粬琛ュ厜;] ")
+    private Long cameraLightType;
+
+    /** 鎽勫儚鏈虹紪鐮佹牸寮� [1.MPEG-4;2.H.264;3.SVAC;4.H.265;] */
+    @Excel(name = "鎽勫儚鏈虹紪鐮佹牸寮� [1.MPEG-4;2.H.264;3.SVAC;4.H.265;]")
+    private Long encodedFormat;
+
+    /** 鎵�灞為儴闂�/琛屼笟 鍙栧�艰寖鍥�(澶氶��) : [1.鍏畨鏈哄叧;2.鐜繚閮ㄩ棬;3.鏂囧崥閮ㄩ棬;4.鍖荤枟閮ㄩ棬;5.鏃呮父绠$悊;6.鏂伴椈骞跨數;7.椋熷搧鍖昏嵂鐩戠潱绠$悊閮ㄩ棬;8.鏁欒偛绠$悊閮ㄩ棬;9.妫�瀵熼櫌;10.娉曢櫌;11.閲戣瀺閮ㄩ棬;12.浜ら�氶儴闂�;13.浣忔埧鍜屽煄涔″缓璁鹃儴闂�;14.姘村埄閮ㄩ棬;15.鏋椾笟閮ㄩ棬;16.瀹夊叏鐢熶骇鐩戠潱閮ㄩ棬;17.甯傛斂甯傚濮�;18.鍥藉湡灞�;] 鏁版嵁鏍煎紡[濉叆澶氫釜鍊煎苟浠�/闅斿紑銆備緥濡�  1/2] */
+    @Excel(name = "鎵�灞為儴闂�/琛屼笟 鍙栧�艰寖鍥�(澶氶��) : [1.鍏畨鏈哄叧;2.鐜繚閮ㄩ棬;3.鏂囧崥閮ㄩ棬;4.鍖荤枟閮ㄩ棬;5.鏃呮父绠$悊;6.鏂伴椈骞跨數;7.椋熷搧鍖昏嵂鐩戠潱绠$悊閮ㄩ棬;8.鏁欒偛绠$悊閮ㄩ棬;9.妫�瀵熼櫌;10.娉曢櫌;11.閲戣瀺閮ㄩ棬;12.浜ら�氶儴闂�;13.浣忔埧鍜屽煄涔″缓璁鹃儴闂�;14.姘村埄閮ㄩ棬;15.鏋椾笟閮ㄩ棬;16.瀹夊叏鐢熶骇鐩戠潱閮ㄩ棬;17.甯傛斂甯傚濮�;18.鍥藉湡灞�;] 鏁版嵁鏍煎紡[濉叆澶氫釜鍊煎苟浠�/闅斿紑銆備緥濡�  1/2]")
+    private String cameraDept;
+
+    /** 琛屼笟缂栫爜 [00.绀句細娌诲畨璺潰鎺ュ叆;01.绀句細娌诲畨绀惧尯鎺ュ叆;02.绀句細娌诲畨鍐呴儴鎺ュ叆;03.绀句細娌诲畨鍏朵粬鎺ュ叆;04.浜ら�氳矾闈㈡帴鍏�;05.浜ら�氬崱鍙f帴鍏�;06.浜ら�氬唴閮ㄦ帴鍏�;07.浜ら�氬叾浠栨帴鍏�;08.鍩庡競绠$悊鎺ュ叆;09.鍗敓鐜繚鎺ュ叆;10.鍟嗘娴峰叧鎺ュ叆;11.鏁欒偛閮ㄩ棬鎺ュ叆;] */
+    @Excel(name = "琛屼笟缂栫爜 [00.绀句細娌诲畨璺潰鎺ュ叆;01.绀句細娌诲畨绀惧尯鎺ュ叆;02.绀句細娌诲畨鍐呴儴鎺ュ叆;03.绀句細娌诲畨鍏朵粬鎺ュ叆;04.浜ら�氳矾闈㈡帴鍏�;05.浜ら�氬崱鍙f帴鍏�;06.浜ら�氬唴閮ㄦ帴鍏�;07.浜ら�氬叾浠栨帴鍏�;08.鍩庡競绠$悊鎺ュ叆;09.鍗敓鐜繚鎺ュ叆;10.鍟嗘娴峰叧鎺ュ叆;11.鏁欒偛閮ㄩ棬鎺ュ叆;]")
+    private String hybm;
+
+    /** 绫诲瀷缂栫爜 : [131.鎽勫儚鏈虹紪鐮�;132.缃戠粶鎽勫儚鏈虹紪鐮�;] */
+    @Excel(name = "绫诲瀷缂栫爜 : [131.鎽勫儚鏈虹紪鐮�;132.缃戠粶鎽勫儚鏈虹紪鐮�;]")
+    private Long lxbm;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setSerialNumber(String serialNumber) 
+    {
+        this.serialNumber = serialNumber;
+    }
+
+    public String getSerialNumber() 
+    {
+        return serialNumber;
+    }
+    public void setName(String name) 
+    {
+        this.name = name;
+    }
+
+    public String getName() 
+    {
+        return name;
+    }
+    public void setSiteType(Long siteType) 
+    {
+        this.siteType = siteType;
+    }
+
+    public Long getSiteType() 
+    {
+        return siteType;
+    }
+    public void setMacAddr(String macAddr) 
+    {
+        this.macAddr = macAddr;
+    }
+
+    public String getMacAddr() 
+    {
+        return macAddr;
+    }
+    public void setIp(String ip) 
+    {
+        this.ip = ip;
+    }
+
+    public String getIp() 
+    {
+        return ip;
+    }
+    public void setCameraFunType(String cameraFunType) 
+    {
+        this.cameraFunType = cameraFunType;
+    }
+
+    public String getCameraFunType() 
+    {
+        return cameraFunType;
+    }
+    public void setLongitude(String longitude) 
+    {
+        this.longitude = longitude;
+    }
+
+    public String getLongitude() 
+    {
+        return longitude;
+    }
+    public void setLatitude(String latitude) 
+    {
+        this.latitude = latitude;
+    }
+
+    public String getLatitude() 
+    {
+        return latitude;
+    }
+    public void setCameraCaptureArea(String cameraCaptureArea) 
+    {
+        this.cameraCaptureArea = cameraCaptureArea;
+    }
+
+    public String getCameraCaptureArea() 
+    {
+        return cameraCaptureArea;
+    }
+    public void setOnState(Long onState) 
+    {
+        this.onState = onState;
+    }
+
+    public Long getOnState() 
+    {
+        return onState;
+    }
+    public void setCivilCode(String civilCode) 
+    {
+        this.civilCode = civilCode;
+    }
+
+    public String getCivilCode() 
+    {
+        return civilCode;
+    }
+    public void setIntegratedDevice(Long integratedDevice) 
+    {
+        this.integratedDevice = integratedDevice;
+    }
+
+    public Long getIntegratedDevice() 
+    {
+        return integratedDevice;
+    }
+    public void setCameraBrand(Long cameraBrand) 
+    {
+        this.cameraBrand = cameraBrand;
+    }
+
+    public Long getCameraBrand() 
+    {
+        return cameraBrand;
+    }
+    public void setAddress(String address) 
+    {
+        this.address = address;
+    }
+
+    public String getAddress() 
+    {
+        return address;
+    }
+    public void setNetWorking(Long netWorking) 
+    {
+        this.netWorking = netWorking;
+    }
+
+    public Long getNetWorking() 
+    {
+        return netWorking;
+    }
+    public void setPublicSecurity(String publicSecurity) 
+    {
+        this.publicSecurity = publicSecurity;
+    }
+
+    public String getPublicSecurity() 
+    {
+        return publicSecurity;
+    }
+    public void setInstalledTime(Date installedTime) 
+    {
+        this.installedTime = installedTime;
+    }
+
+    public Date getInstalledTime() 
+    {
+        return installedTime;
+    }
+    public void setManagementUnit(String managementUnit) 
+    {
+        this.managementUnit = managementUnit;
+    }
+
+    public String getManagementUnit() 
+    {
+        return managementUnit;
+    }
+    public void setMuContactInfo(String muContactInfo) 
+    {
+        this.muContactInfo = muContactInfo;
+    }
+
+    public String getMuContactInfo() 
+    {
+        return muContactInfo;
+    }
+    public void setStorageDays(Long storageDays) 
+    {
+        this.storageDays = storageDays;
+    }
+
+    public Long getStorageDays() 
+    {
+        return storageDays;
+    }
+    public void setMonitorAzimuth(Long monitorAzimuth) 
+    {
+        this.monitorAzimuth = monitorAzimuth;
+    }
+
+    public Long getMonitorAzimuth() 
+    {
+        return monitorAzimuth;
+    }
+    public void setScenePhotoAddr(String scenePhotoAddr) 
+    {
+        this.scenePhotoAddr = scenePhotoAddr;
+    }
+
+    public String getScenePhotoAddr() 
+    {
+        return scenePhotoAddr;
+    }
+    public void setModel(String model) 
+    {
+        this.model = model;
+    }
+
+    public String getModel() 
+    {
+        return model;
+    }
+    public void setSiteVulgo(String siteVulgo) 
+    {
+        this.siteVulgo = siteVulgo;
+    }
+
+    public String getSiteVulgo() 
+    {
+        return siteVulgo;
+    }
+    public void setCameraType(Long cameraType) 
+    {
+        this.cameraType = cameraType;
+    }
+
+    public Long getCameraType() 
+    {
+        return cameraType;
+    }
+    public void setCameraLightType(Long cameraLightType) 
+    {
+        this.cameraLightType = cameraLightType;
+    }
+
+    public Long getCameraLightType() 
+    {
+        return cameraLightType;
+    }
+    public void setEncodedFormat(Long encodedFormat) 
+    {
+        this.encodedFormat = encodedFormat;
+    }
+
+    public Long getEncodedFormat() 
+    {
+        return encodedFormat;
+    }
+    public void setCameraDept(String cameraDept) 
+    {
+        this.cameraDept = cameraDept;
+    }
+
+    public String getCameraDept() 
+    {
+        return cameraDept;
+    }
+    public void setHybm(String hybm) 
+    {
+        this.hybm = hybm;
+    }
+
+    public String getHybm() 
+    {
+        return hybm;
+    }
+    public void setLxbm(Long lxbm) 
+    {
+        this.lxbm = lxbm;
+    }
+
+    public Long getLxbm() 
+    {
+        return lxbm;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("serialNumber", getSerialNumber())
+            .append("name", getName())
+            .append("siteType", getSiteType())
+            .append("macAddr", getMacAddr())
+            .append("ip", getIp())
+            .append("cameraFunType", getCameraFunType())
+            .append("longitude", getLongitude())
+            .append("latitude", getLatitude())
+            .append("cameraCaptureArea", getCameraCaptureArea())
+            .append("onState", getOnState())
+            .append("civilCode", getCivilCode())
+            .append("integratedDevice", getIntegratedDevice())
+            .append("cameraBrand", getCameraBrand())
+            .append("address", getAddress())
+            .append("netWorking", getNetWorking())
+            .append("publicSecurity", getPublicSecurity())
+            .append("installedTime", getInstalledTime())
+            .append("managementUnit", getManagementUnit())
+            .append("muContactInfo", getMuContactInfo())
+            .append("storageDays", getStorageDays())
+            .append("monitorAzimuth", getMonitorAzimuth())
+            .append("scenePhotoAddr", getScenePhotoAddr())
+            .append("model", getModel())
+            .append("siteVulgo", getSiteVulgo())
+            .append("cameraType", getCameraType())
+            .append("cameraLightType", getCameraLightType())
+            .append("encodedFormat", getEncodedFormat())
+            .append("cameraDept", getCameraDept())
+            .append("hybm", getHybm())
+            .append("lxbm", getLxbm())
+            .toString();
+    }
+}
diff --git a/ycl-pojo/src/main/java/com/ycl/system/AjaxResult.java b/ycl-pojo/src/main/java/com/ycl/system/AjaxResult.java
index 6d1aedf..bf8de85 100644
--- a/ycl-pojo/src/main/java/com/ycl/system/AjaxResult.java
+++ b/ycl-pojo/src/main/java/com/ycl/system/AjaxResult.java
@@ -26,14 +26,14 @@
     public static final String DATA_TAG = "data";
 
     /**
-     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� AjaxResult 瀵硅薄锛屼娇鍏惰〃绀轰竴涓┖娑堟伅銆�
+     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� pojo.AjaxResult 瀵硅薄锛屼娇鍏惰〃绀轰竴涓┖娑堟伅銆�
      */
     public AjaxResult()
     {
     }
 
     /**
-     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� AjaxResult 瀵硅薄
+     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� pojo.AjaxResult 瀵硅薄
      * 
      * @param code 鐘舵�佺爜
      * @param msg 杩斿洖鍐呭
@@ -45,7 +45,7 @@
     }
 
     /**
-     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� AjaxResult 瀵硅薄
+     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� pojo.AjaxResult 瀵硅薄
      * 
      * @param code 鐘舵�佺爜
      * @param msg 杩斿洖鍐呭
diff --git a/ycl-server/src/main/java/com/ycl/platform/controller/TMonitorController.java b/ycl-server/src/main/java/com/ycl/platform/controller/TMonitorController.java
new file mode 100644
index 0000000..abde607
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/platform/controller/TMonitorController.java
@@ -0,0 +1,98 @@
+package com.ycl.platform.controller;
+
+import annotation.Log;
+import com.ycl.platform.entity.TMonitor;
+import com.ycl.platform.service.ITMonitorService;
+import com.ycl.system.AjaxResult;
+import com.ycl.system.controller.BaseController;
+import com.ycl.system.page.TableDataInfo;
+import com.ycl.utils.poi.ExcelUtil;
+import enumeration.BusinessType;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 璁惧璧勪骇Controller
+ *
+ * @author ruoyi
+ * @date 2024-03-04
+ */
+@RestController
+@RequestMapping("/system/monitor")
+public class TMonitorController extends BaseController
+{
+    @Autowired
+    private ITMonitorService tMonitorService;
+
+    /**
+     * 鏌ヨ璁惧璧勪骇鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('system:monitor:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TMonitor tMonitor)
+    {
+        startPage();
+        List<TMonitor> list = tMonitorService.selectTMonitorList(tMonitor);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭璁惧璧勪骇鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('system:monitor:export')")
+    @Log(title = "璁惧璧勪骇", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, TMonitor tMonitor)
+    {
+        List<TMonitor> list = tMonitorService.selectTMonitorList(tMonitor);
+        ExcelUtil<TMonitor> util = new ExcelUtil<TMonitor>(TMonitor.class);
+        util.exportExcel(response, list, "璁惧璧勪骇鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇璁惧璧勪骇璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('system:monitor:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(tMonitorService.selectTMonitorById(id));
+    }
+
+    /**
+     * 鏂板璁惧璧勪骇
+     */
+    @PreAuthorize("@ss.hasPermi('system:monitor:add')")
+    @Log(title = "璁惧璧勪骇", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TMonitor tMonitor)
+    {
+        return toAjax(tMonitorService.insertTMonitor(tMonitor));
+    }
+
+    /**
+     * 淇敼璁惧璧勪骇
+     */
+    @PreAuthorize("@ss.hasPermi('system:monitor:edit')")
+    @Log(title = "璁惧璧勪骇", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TMonitor tMonitor)
+    {
+        return toAjax(tMonitorService.updateTMonitor(tMonitor));
+    }
+
+    /**
+     * 鍒犻櫎璁惧璧勪骇
+     */
+    @PreAuthorize("@ss.hasPermi('system:monitor:remove')")
+    @Log(title = "璁惧璧勪骇", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(tMonitorService.deleteTMonitorByIds(ids));
+    }
+}
diff --git a/ycl-server/src/main/java/com/ycl/platform/mapper/TMonitorMapper.java b/ycl-server/src/main/java/com/ycl/platform/mapper/TMonitorMapper.java
new file mode 100644
index 0000000..6245c2d
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/platform/mapper/TMonitorMapper.java
@@ -0,0 +1,62 @@
+package com.ycl.platform.mapper;
+
+import com.ycl.platform.entity.TMonitor;
+
+import java.util.List;
+
+/**
+ * 璁惧璧勪骇Mapper鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2024-03-04
+ */
+public interface TMonitorMapper 
+{
+    /**
+     * 鏌ヨ璁惧璧勪骇
+     * 
+     * @param id 璁惧璧勪骇涓婚敭
+     * @return 璁惧璧勪骇
+     */
+    public TMonitor selectTMonitorById(Long id);
+
+    /**
+     * 鏌ヨ璁惧璧勪骇鍒楄〃
+     * 
+     * @param tMonitor 璁惧璧勪骇
+     * @return 璁惧璧勪骇闆嗗悎
+     */
+    public List<TMonitor> selectTMonitorList(TMonitor tMonitor);
+
+    /**
+     * 鏂板璁惧璧勪骇
+     * 
+     * @param tMonitor 璁惧璧勪骇
+     * @return 缁撴灉
+     */
+    public int insertTMonitor(TMonitor tMonitor);
+
+    /**
+     * 淇敼璁惧璧勪骇
+     * 
+     * @param tMonitor 璁惧璧勪骇
+     * @return 缁撴灉
+     */
+    public int updateTMonitor(TMonitor tMonitor);
+
+    /**
+     * 鍒犻櫎璁惧璧勪骇
+     * 
+     * @param id 璁惧璧勪骇涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteTMonitorById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧璧勪骇
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteTMonitorByIds(Long[] ids);
+}
diff --git a/ycl-server/src/main/java/com/ycl/platform/service/ITMonitorService.java b/ycl-server/src/main/java/com/ycl/platform/service/ITMonitorService.java
new file mode 100644
index 0000000..24745d8
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/platform/service/ITMonitorService.java
@@ -0,0 +1,62 @@
+package com.ycl.platform.service;
+
+import com.ycl.platform.entity.TMonitor;
+
+import java.util.List;
+
+/**
+ * 璁惧璧勪骇Service鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2024-03-04
+ */
+public interface ITMonitorService 
+{
+    /**
+     * 鏌ヨ璁惧璧勪骇
+     * 
+     * @param id 璁惧璧勪骇涓婚敭
+     * @return 璁惧璧勪骇
+     */
+    public TMonitor selectTMonitorById(Long id);
+
+    /**
+     * 鏌ヨ璁惧璧勪骇鍒楄〃
+     * 
+     * @param tMonitor 璁惧璧勪骇
+     * @return 璁惧璧勪骇闆嗗悎
+     */
+    public List<TMonitor> selectTMonitorList(TMonitor tMonitor);
+
+    /**
+     * 鏂板璁惧璧勪骇
+     * 
+     * @param tMonitor 璁惧璧勪骇
+     * @return 缁撴灉
+     */
+    public int insertTMonitor(TMonitor tMonitor);
+
+    /**
+     * 淇敼璁惧璧勪骇
+     * 
+     * @param tMonitor 璁惧璧勪骇
+     * @return 缁撴灉
+     */
+    public int updateTMonitor(TMonitor tMonitor);
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧璧勪骇
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑璁惧璧勪骇涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteTMonitorByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎璁惧璧勪骇淇℃伅
+     * 
+     * @param id 璁惧璧勪骇涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteTMonitorById(Long id);
+}
diff --git a/ycl-server/src/main/java/com/ycl/platform/service/impl/TMonitorServiceImpl.java b/ycl-server/src/main/java/com/ycl/platform/service/impl/TMonitorServiceImpl.java
new file mode 100644
index 0000000..32d6e38
--- /dev/null
+++ b/ycl-server/src/main/java/com/ycl/platform/service/impl/TMonitorServiceImpl.java
@@ -0,0 +1,94 @@
+package com.ycl.platform.service.impl;
+
+import com.ycl.platform.entity.TMonitor;
+import com.ycl.platform.mapper.TMonitorMapper;
+import com.ycl.platform.service.ITMonitorService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 璁惧璧勪骇Service涓氬姟灞傚鐞�
+ * 
+ * @author ruoyi
+ * @date 2024-03-04
+ */
+@Service
+public class TMonitorServiceImpl implements ITMonitorService
+{
+    @Autowired
+    private TMonitorMapper tMonitorMapper;
+
+    /**
+     * 鏌ヨ璁惧璧勪骇
+     * 
+     * @param id 璁惧璧勪骇涓婚敭
+     * @return 璁惧璧勪骇
+     */
+    @Override
+    public TMonitor selectTMonitorById(Long id)
+    {
+        return tMonitorMapper.selectTMonitorById(id);
+    }
+
+    /**
+     * 鏌ヨ璁惧璧勪骇鍒楄〃
+     * 
+     * @param tMonitor 璁惧璧勪骇
+     * @return 璁惧璧勪骇
+     */
+    @Override
+    public List<TMonitor> selectTMonitorList(TMonitor tMonitor)
+    {
+        return tMonitorMapper.selectTMonitorList(tMonitor);
+    }
+
+    /**
+     * 鏂板璁惧璧勪骇
+     * 
+     * @param tMonitor 璁惧璧勪骇
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertTMonitor(TMonitor tMonitor)
+    {
+        return tMonitorMapper.insertTMonitor(tMonitor);
+    }
+
+    /**
+     * 淇敼璁惧璧勪骇
+     * 
+     * @param tMonitor 璁惧璧勪骇
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateTMonitor(TMonitor tMonitor)
+    {
+        return tMonitorMapper.updateTMonitor(tMonitor);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎璁惧璧勪骇
+     * 
+     * @param ids 闇�瑕佸垹闄ょ殑璁惧璧勪骇涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteTMonitorByIds(Long[] ids)
+    {
+        return tMonitorMapper.deleteTMonitorByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎璁惧璧勪骇淇℃伅
+     * 
+     * @param id 璁惧璧勪骇涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteTMonitorById(Long id)
+    {
+        return tMonitorMapper.deleteTMonitorById(id);
+    }
+}
diff --git a/ycl-server/src/main/java/com/ycl/utils/poi/ExcelUtil.java b/ycl-server/src/main/java/com/ycl/utils/poi/ExcelUtil.java
index 36dae2e..f5d0758 100644
--- a/ycl-server/src/main/java/com/ycl/utils/poi/ExcelUtil.java
+++ b/ycl-server/src/main/java/com/ycl/utils/poi/ExcelUtil.java
@@ -1,7 +1,7 @@
 package com.ycl.utils.poi;
 
-import com.ycl.annotation.Excel;
-import com.ycl.annotation.Excels;
+import annotation.Excel;
+import annotation.Excels;
 import com.ycl.config.PlatformConfig;
 import com.ycl.exception.UtilException;
 import com.ycl.system.AjaxResult;
diff --git a/ycl-server/src/main/resources/mapper/zgyw/TMonitorMapper.xml b/ycl-server/src/main/resources/mapper/zgyw/TMonitorMapper.xml
new file mode 100644
index 0000000..b0750cf
--- /dev/null
+++ b/ycl-server/src/main/resources/mapper/zgyw/TMonitorMapper.xml
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ycl.platform.mapper.TMonitorMapper">
+    
+    <resultMap type="com.ycl.platform.entity.TMonitor" id="TMonitorResult">
+        <result property="id"    column="id"    />
+        <result property="serialNumber"    column="serial_number"    />
+        <result property="name"    column="name"    />
+        <result property="siteType"    column="site_type"    />
+        <result property="macAddr"    column="mac_addr"    />
+        <result property="ip"    column="ip"    />
+        <result property="cameraFunType"    column="camera_fun_type"    />
+        <result property="longitude"    column="longitude"    />
+        <result property="latitude"    column="latitude"    />
+        <result property="cameraCaptureArea"    column="camera_capture_area"    />
+        <result property="onState"    column="on_state"    />
+        <result property="civilCode"    column="civil_code"    />
+        <result property="integratedDevice"    column="integrated_device"    />
+        <result property="cameraBrand"    column="camera_brand"    />
+        <result property="address"    column="address"    />
+        <result property="netWorking"    column="net_working"    />
+        <result property="publicSecurity"    column="public_security"    />
+        <result property="installedTime"    column="installed_time"    />
+        <result property="managementUnit"    column="management_unit"    />
+        <result property="muContactInfo"    column="mu_contact_info"    />
+        <result property="storageDays"    column="storage_days"    />
+        <result property="monitorAzimuth"    column="monitor_azimuth"    />
+        <result property="scenePhotoAddr"    column="scene_photo_addr"    />
+        <result property="model"    column="model"    />
+        <result property="siteVulgo"    column="site_vulgo"    />
+        <result property="cameraType"    column="camera_type"    />
+        <result property="cameraLightType"    column="camera_light_type"    />
+        <result property="encodedFormat"    column="encoded_format"    />
+        <result property="cameraDept"    column="camera_dept"    />
+        <result property="hybm"    column="hybm"    />
+        <result property="lxbm"    column="lxbm"    />
+    </resultMap>
+
+    <sql id="selectTMonitorVo">
+        select id, serial_number, name, site_type, mac_addr, ip, camera_fun_type, longitude, latitude, camera_capture_area, on_state, civil_code, integrated_device, camera_brand, address, net_working, public_security, installed_time, management_unit, mu_contact_info, storage_days, monitor_azimuth, scene_photo_addr, model, site_vulgo, camera_type, camera_light_type, encoded_format, camera_dept, hybm, lxbm from t_monitor
+    </sql>
+
+    <select id="selectTMonitorList" parameterType="com.ycl.platform.entity.TMonitor" resultMap="TMonitorResult">
+        <include refid="selectTMonitorVo"/>
+        <where>  
+            <if test="serialNumber != null  and serialNumber != ''"> and serial_number = #{serialNumber}</if>
+            <if test="name != null  and name != ''"> and name like concat('%', #{name}, '%')</if>
+            <if test="siteType != null "> and site_type = #{siteType}</if>
+            <if test="macAddr != null  and macAddr != ''"> and mac_addr = #{macAddr}</if>
+            <if test="ip != null  and ip != ''"> and ip = #{ip}</if>
+            <if test="cameraFunType != null  and cameraFunType != ''"> and camera_fun_type = #{cameraFunType}</if>
+            <if test="longitude != null  and longitude != ''"> and longitude = #{longitude}</if>
+            <if test="latitude != null  and latitude != ''"> and latitude = #{latitude}</if>
+            <if test="cameraCaptureArea != null  and cameraCaptureArea != ''"> and camera_capture_area = #{cameraCaptureArea}</if>
+            <if test="onState != null "> and on_state = #{onState}</if>
+            <if test="civilCode != null  and civilCode != ''"> and civil_code = #{civilCode}</if>
+            <if test="integratedDevice != null "> and integrated_device = #{integratedDevice}</if>
+            <if test="cameraBrand != null "> and camera_brand = #{cameraBrand}</if>
+            <if test="address != null  and address != ''"> and address = #{address}</if>
+            <if test="netWorking != null "> and net_working = #{netWorking}</if>
+            <if test="publicSecurity != null  and publicSecurity != ''"> and public_security = #{publicSecurity}</if>
+            <if test="installedTime != null "> and installed_time = #{installedTime}</if>
+            <if test="managementUnit != null  and managementUnit != ''"> and management_unit = #{managementUnit}</if>
+            <if test="muContactInfo != null  and muContactInfo != ''"> and mu_contact_info = #{muContactInfo}</if>
+            <if test="storageDays != null "> and storage_days = #{storageDays}</if>
+            <if test="monitorAzimuth != null "> and monitor_azimuth = #{monitorAzimuth}</if>
+            <if test="scenePhotoAddr != null  and scenePhotoAddr != ''"> and scene_photo_addr = #{scenePhotoAddr}</if>
+            <if test="model != null  and model != ''"> and model = #{model}</if>
+            <if test="siteVulgo != null  and siteVulgo != ''"> and site_vulgo = #{siteVulgo}</if>
+            <if test="cameraType != null "> and camera_type = #{cameraType}</if>
+            <if test="cameraLightType != null "> and camera_light_type = #{cameraLightType}</if>
+            <if test="encodedFormat != null "> and encoded_format = #{encodedFormat}</if>
+            <if test="cameraDept != null  and cameraDept != ''"> and camera_dept = #{cameraDept}</if>
+            <if test="hybm != null  and hybm != ''"> and hybm = #{hybm}</if>
+            <if test="lxbm != null "> and lxbm = #{lxbm}</if>
+        </where>
+    </select>
+    
+    <select id="selectTMonitorById" parameterType="Long" resultMap="TMonitorResult">
+        <include refid="selectTMonitorVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertTMonitor" parameterType="com.ycl.platform.entity.TMonitor" useGeneratedKeys="true" keyProperty="id">
+        insert into t_monitor
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="serialNumber != null and serialNumber != ''">serial_number,</if>
+            <if test="name != null and name != ''">name,</if>
+            <if test="siteType != null">site_type,</if>
+            <if test="macAddr != null and macAddr != ''">mac_addr,</if>
+            <if test="ip != null and ip != ''">ip,</if>
+            <if test="cameraFunType != null and cameraFunType != ''">camera_fun_type,</if>
+            <if test="longitude != null and longitude != ''">longitude,</if>
+            <if test="latitude != null and latitude != ''">latitude,</if>
+            <if test="cameraCaptureArea != null and cameraCaptureArea != ''">camera_capture_area,</if>
+            <if test="onState != null">on_state,</if>
+            <if test="civilCode != null and civilCode != ''">civil_code,</if>
+            <if test="integratedDevice != null">integrated_device,</if>
+            <if test="cameraBrand != null">camera_brand,</if>
+            <if test="address != null">address,</if>
+            <if test="netWorking != null">net_working,</if>
+            <if test="publicSecurity != null">public_security,</if>
+            <if test="installedTime != null">installed_time,</if>
+            <if test="managementUnit != null">management_unit,</if>
+            <if test="muContactInfo != null">mu_contact_info,</if>
+            <if test="storageDays != null">storage_days,</if>
+            <if test="monitorAzimuth != null">monitor_azimuth,</if>
+            <if test="scenePhotoAddr != null">scene_photo_addr,</if>
+            <if test="model != null">model,</if>
+            <if test="siteVulgo != null">site_vulgo,</if>
+            <if test="cameraType != null">camera_type,</if>
+            <if test="cameraLightType != null">camera_light_type,</if>
+            <if test="encodedFormat != null">encoded_format,</if>
+            <if test="cameraDept != null">camera_dept,</if>
+            <if test="hybm != null">hybm,</if>
+            <if test="lxbm != null">lxbm,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="serialNumber != null and serialNumber != ''">#{serialNumber},</if>
+            <if test="name != null and name != ''">#{name},</if>
+            <if test="siteType != null">#{siteType},</if>
+            <if test="macAddr != null and macAddr != ''">#{macAddr},</if>
+            <if test="ip != null and ip != ''">#{ip},</if>
+            <if test="cameraFunType != null and cameraFunType != ''">#{cameraFunType},</if>
+            <if test="longitude != null and longitude != ''">#{longitude},</if>
+            <if test="latitude != null and latitude != ''">#{latitude},</if>
+            <if test="cameraCaptureArea != null and cameraCaptureArea != ''">#{cameraCaptureArea},</if>
+            <if test="onState != null">#{onState},</if>
+            <if test="civilCode != null and civilCode != ''">#{civilCode},</if>
+            <if test="integratedDevice != null">#{integratedDevice},</if>
+            <if test="cameraBrand != null">#{cameraBrand},</if>
+            <if test="address != null">#{address},</if>
+            <if test="netWorking != null">#{netWorking},</if>
+            <if test="publicSecurity != null">#{publicSecurity},</if>
+            <if test="installedTime != null">#{installedTime},</if>
+            <if test="managementUnit != null">#{managementUnit},</if>
+            <if test="muContactInfo != null">#{muContactInfo},</if>
+            <if test="storageDays != null">#{storageDays},</if>
+            <if test="monitorAzimuth != null">#{monitorAzimuth},</if>
+            <if test="scenePhotoAddr != null">#{scenePhotoAddr},</if>
+            <if test="model != null">#{model},</if>
+            <if test="siteVulgo != null">#{siteVulgo},</if>
+            <if test="cameraType != null">#{cameraType},</if>
+            <if test="cameraLightType != null">#{cameraLightType},</if>
+            <if test="encodedFormat != null">#{encodedFormat},</if>
+            <if test="cameraDept != null">#{cameraDept},</if>
+            <if test="hybm != null">#{hybm},</if>
+            <if test="lxbm != null">#{lxbm},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTMonitor" parameterType="com.ycl.platform.entity.TMonitor">
+        update t_monitor
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="serialNumber != null and serialNumber != ''">serial_number = #{serialNumber},</if>
+            <if test="name != null and name != ''">name = #{name},</if>
+            <if test="siteType != null">site_type = #{siteType},</if>
+            <if test="macAddr != null and macAddr != ''">mac_addr = #{macAddr},</if>
+            <if test="ip != null and ip != ''">ip = #{ip},</if>
+            <if test="cameraFunType != null and cameraFunType != ''">camera_fun_type = #{cameraFunType},</if>
+            <if test="longitude != null and longitude != ''">longitude = #{longitude},</if>
+            <if test="latitude != null and latitude != ''">latitude = #{latitude},</if>
+            <if test="cameraCaptureArea != null and cameraCaptureArea != ''">camera_capture_area = #{cameraCaptureArea},</if>
+            <if test="onState != null">on_state = #{onState},</if>
+            <if test="civilCode != null and civilCode != ''">civil_code = #{civilCode},</if>
+            <if test="integratedDevice != null">integrated_device = #{integratedDevice},</if>
+            <if test="cameraBrand != null">camera_brand = #{cameraBrand},</if>
+            <if test="address != null">address = #{address},</if>
+            <if test="netWorking != null">net_working = #{netWorking},</if>
+            <if test="publicSecurity != null">public_security = #{publicSecurity},</if>
+            <if test="installedTime != null">installed_time = #{installedTime},</if>
+            <if test="managementUnit != null">management_unit = #{managementUnit},</if>
+            <if test="muContactInfo != null">mu_contact_info = #{muContactInfo},</if>
+            <if test="storageDays != null">storage_days = #{storageDays},</if>
+            <if test="monitorAzimuth != null">monitor_azimuth = #{monitorAzimuth},</if>
+            <if test="scenePhotoAddr != null">scene_photo_addr = #{scenePhotoAddr},</if>
+            <if test="model != null">model = #{model},</if>
+            <if test="siteVulgo != null">site_vulgo = #{siteVulgo},</if>
+            <if test="cameraType != null">camera_type = #{cameraType},</if>
+            <if test="cameraLightType != null">camera_light_type = #{cameraLightType},</if>
+            <if test="encodedFormat != null">encoded_format = #{encodedFormat},</if>
+            <if test="cameraDept != null">camera_dept = #{cameraDept},</if>
+            <if test="hybm != null">hybm = #{hybm},</if>
+            <if test="lxbm != null">lxbm = #{lxbm},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteTMonitorById" parameterType="Long">
+        delete from t_monitor where id = #{id}
+    </delete>
+
+    <delete id="deleteTMonitorByIds" parameterType="String">
+        delete from t_monitor where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file

--
Gitblit v1.8.0