securityReferences = new ArrayList<>();
+ securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
+ return securityReferences;
+ }
+
+ /**
+ * 添加摘要信息
+ */
+ private ApiInfo apiInfo()
+ {
+ // 用ApiInfoBuilder进行定制
+ return new ApiInfoBuilder()
+ // 设置标题
+ .title("标题:数字消防综合管理系统_接口文档")
+ // 描述
+ .description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
+ // 作者信息
+ .contact(new Contact(ruoyiConfig.getName(), null, null))
+ // 版本
+ .version("版本号:" + ruoyiConfig.getVersion())
+ .build();
+ }
+}
diff --git a/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties b/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties
new file mode 100644
index 00000000..2b23f85a
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties
@@ -0,0 +1 @@
+restart.include.json=/com.alibaba.fastjson.*.jar
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
new file mode 100644
index 00000000..0683a1ef
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -0,0 +1,63 @@
+ruoyi:
+ # 文件路径
+ profile: D:/ruoyi/uploadPath
+# 数据源配置
+spring:
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ druid:
+ # 主库数据源
+ master:
+# url: jdbc:mysql://121.40.191.30:3306/ry-base-tenant?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ url: jdbc:mysql://43.139.7.36:3306/ry-base-tenant?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: it@luokeng
+# password: 123456
+
+ # 从库数据源
+ slave:
+ # 从数据源开关/默认关闭
+ enabled: false
+ url:
+ username:
+ password:
+ # 初始连接数
+ initialSize: 5
+ # 最小连接池数量
+ minIdle: 10
+ # 最大连接池数量
+ maxActive: 20
+ # 配置获取连接等待超时的时间
+ maxWait: 60000
+ # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+ timeBetweenEvictionRunsMillis: 60000
+ # 配置一个连接在池中最小生存的时间,单位是毫秒
+ minEvictableIdleTimeMillis: 300000
+ # 配置一个连接在池中最大生存的时间,单位是毫秒
+ maxEvictableIdleTimeMillis: 900000
+ # 配置检测连接是否有效
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 设置白名单,不填则允许所有访问
+ allow:
+ url-pattern: /druid/*
+ # 控制台管理用户名和密码
+ login-username: ruoyi
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 慢SQL记录
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: true
diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml
new file mode 100644
index 00000000..b4aa52c5
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/application-druid.yml
@@ -0,0 +1,57 @@
+# 数据源配置
+spring:
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ druid:
+ # 主库数据源
+ master:
+ url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: root
+ # 从库数据源
+ slave:
+ # 从数据源开关/默认关闭
+ enabled: false
+ url:
+ username:
+ password:
+ # 初始连接数
+ initialSize: 5
+ # 最小连接池数量
+ minIdle: 10
+ # 最大连接池数量
+ maxActive: 20
+ # 配置获取连接等待超时的时间
+ maxWait: 60000
+ # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+ timeBetweenEvictionRunsMillis: 60000
+ # 配置一个连接在池中最小生存的时间,单位是毫秒
+ minEvictableIdleTimeMillis: 300000
+ # 配置一个连接在池中最大生存的时间,单位是毫秒
+ maxEvictableIdleTimeMillis: 900000
+ # 配置检测连接是否有效
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 设置白名单,不填则允许所有访问
+ allow:
+ url-pattern: /druid/*
+ # 控制台管理用户名和密码
+ login-username: ruoyi
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 慢SQL记录
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: true
diff --git a/ruoyi-admin/src/main/resources/application-test.yml b/ruoyi-admin/src/main/resources/application-test.yml
new file mode 100644
index 00000000..8217380e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/application-test.yml
@@ -0,0 +1,61 @@
+ruoyi:
+ # 文件路径
+ profile: /project/xinchuang/xiaofang-dm/uploadPath
+
+# 数据源配置
+spring:
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ druid:
+ # 主库数据源
+ master:
+ url: jdbc:mysql://192.168.254.125:3306/xiaofang?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: abcd1234
+ # 从库数据源
+ slave:
+ # 从数据源开关/默认关闭
+ enabled: false
+ url:
+ username:
+ password:
+ # 初始连接数
+ initialSize: 5
+ # 最小连接池数量
+ minIdle: 10
+ # 最大连接池数量
+ maxActive: 20
+ # 配置获取连接等待超时的时间
+ maxWait: 60000
+ # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+ timeBetweenEvictionRunsMillis: 60000
+ # 配置一个连接在池中最小生存的时间,单位是毫秒
+ minEvictableIdleTimeMillis: 300000
+ # 配置一个连接在池中最大生存的时间,单位是毫秒
+ maxEvictableIdleTimeMillis: 900000
+ # 配置检测连接是否有效
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 设置白名单,不填则允许所有访问
+ allow:
+ url-pattern: /druid/*
+ # 控制台管理用户名和密码
+ login-username: ruoyi
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 慢SQL记录
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: true
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
new file mode 100644
index 00000000..c05620e3
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -0,0 +1,154 @@
+# 项目相关配置
+ruoyi:
+ # 名称
+ name: RuoYi
+ # 版本
+ version: 1.0.0
+ # 版权年份
+ copyrightYear: 2022
+ # 实例演示开关
+ demoEnabled: true
+ # 获取ip地址开关
+ addressEnabled: false
+ # 验证码类型 math 数组计算 char 字符验证
+ captchaType: math
+ tenant:
+ enable: true
+ ignore-urls:
+ - /system/tenant/get-id-by-name # 基于名字获取租户,不许带租户编号
+ - /captcha/get # 获取图片验证码,和租户无关
+ - /captcha/check # 校验图片验证码,和租户无关
+ - /infra/file/*/get/** # 获取图片,和租户无关
+ - /system/sms/callback/* # 短信回调接口,无法带上租户编号
+ - /app-api/pay/order/notify/* # 支付回调通知,不携带租户编号
+ - /jmreport/** # 积木报表,无法携带租户编号。*匹配任意字符(除了路径分隔符),而**匹配任意字符
+# 开发环境配置
+server:
+ # 服务器的HTTP端口,默认为8080
+ port: 8080
+ servlet:
+ # 应用的访问路径
+ context-path: /
+ tomcat:
+ # tomcat的URI编码
+ uri-encoding: UTF-8
+ # 连接数满后的排队数,默认为100
+ accept-count: 1000
+ threads:
+ # tomcat最大线程数,默认为200
+ max: 800
+ # Tomcat启动初始化的线程数,默认值10
+ min-spare: 100
+
+# 日志配置
+logging:
+ level:
+ com.ruoyi: debug
+ org.springframework: warn
+
+# 用户配置
+user:
+ password:
+ # 密码最大错误次数
+ maxRetryCount: 5
+ # 密码锁定时间(默认10分钟)
+ lockTime: 10
+
+# Spring配置
+spring:
+ # 资源信息
+ messages:
+ # 国际化资源文件路径
+ basename: i18n/messages
+ profiles:
+ active: dev
+ # 文件上传
+ servlet:
+ multipart:
+ # 单个文件大小
+ max-file-size: 10MB
+ # 设置总上传的文件大小
+ max-request-size: 20MB
+ # 服务模块
+ devtools:
+ restart:
+ # 热部署开关
+ enabled: false
+ cache:
+ type: ehcache
+ ehcache:
+ config: classpath:/ehcache.xml
+ # redis 配置
+# redis:
+# # 地址
+# host: localhost
+# # 端口,默认为6379
+# port: 6379
+# # 数据库索引
+# database: 0
+# # 密码
+# password:
+# # 连接超时时间
+# timeout: 10s
+# lettuce:
+# pool:
+# # 连接池中的最小空闲连接
+# min-idle: 0
+# # 连接池中的最大空闲连接
+# max-idle: 8
+# # 连接池的最大数据库连接数
+# max-active: 8
+# # #连接池最大阻塞等待时间(使用负值表示没有限制)
+# max-wait: -1ms
+
+# token配置
+token:
+ # 令牌自定义标识
+ header: Authorization
+ # 令牌密钥
+ secret: abcytrmiuumwefsadfdfafahvwxyz
+ # 令牌有效期(默认30分钟)
+ expireTime: 30
+
+# MyBatis Plus配置
+mybatis-plus:
+ # 搜索指定包别名
+ typeAliasesPackage: com.ruoyi.**.domain
+ # 配置mapper的扫描,找到所有的mapper.xml映射文件
+ mapperLocations: classpath*:mapper/**/*Mapper.xml
+ # 加载全局的配置文件
+ configLocation: classpath:mybatis/mybatis-config.xml
+
+# PageHelper分页插件
+pagehelper:
+ helperDialect: mysql
+ supportMethodsArguments: true
+ params: count=countSql
+
+# Swagger配置
+swagger:
+ # 是否开启swagger
+ enabled: true
+ # 请求前缀
+ pathMapping: /dev-api
+
+# 防止XSS攻击
+xss:
+ # 过滤开关
+ enabled: true
+ # 排除链接(多个用逗号分隔)
+ excludes: /system/notice
+ # 匹配链接
+ urlPatterns: /system/*,/monitor/*,/tool/*
+
+# 工作流 Flowable 配置
+flowable:
+ # 1. false: 默认值,Flowable 启动时,对比数据库表中保存的版本,如果不匹配。将抛出异常
+ # 2. true: 启动时会对数据库中所有表进行更新操作,如果表存在,不做处理,反之,自动创建表
+ # 3. create_drop: 启动时自动创建表,关闭时自动删除表
+ # 4. drop_create: 启动时,删除旧表,再创建新表
+ database-schema-update: true # 设置为 false,可通过 https://github.com/flowable/flowable-sql 初始化
+ db-history-used: true # flowable6 默认 true 生成信息表,无需手动设置
+ check-process-definitions: false # 设置为 false,禁用 /resources/processes 自动部署 BPMN XML 流程
+ history-level: full # full:保存历史数据的最高级别,可保存全部流程相关细节,包括流程流转各节点参数
+
diff --git a/ruoyi-admin/src/main/resources/banner.txt b/ruoyi-admin/src/main/resources/banner.txt
new file mode 100644
index 00000000..0931cb84
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/banner.txt
@@ -0,0 +1,24 @@
+Application Version: ${ruoyi.version}
+Spring Boot Version: ${spring-boot.version}
+////////////////////////////////////////////////////////////////////
+// _ooOoo_ //
+// o8888888o //
+// 88" . "88 //
+// (| ^_^ |) //
+// O\ = /O //
+// ____/`---'\____ //
+// .' \\| |// `. //
+// / \\||| : |||// \ //
+// / _||||| -:- |||||- \ //
+// | | \\\ - /// | | //
+// | \_| ''\---/'' | | //
+// \ .-\__ `-` ___/-. / //
+// ___`. .' /--.--\ `. . ___ //
+// ."" '< `.___\_<|>_/___.' >'"". //
+// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
+// \ \ `-. \_ __\ /__ _/ .-` / / //
+// ========`-.____`-.___\_____/___.-`____.-'======== //
+// `=---=' //
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
+// 佛祖保佑 永不宕机 永无BUG //
+////////////////////////////////////////////////////////////////////
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/ehcache.xml b/ruoyi-admin/src/main/resources/ehcache.xml
new file mode 100644
index 00000000..c2bad019
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/ehcache.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-admin/src/main/resources/i18n/messages.properties b/ruoyi-admin/src/main/resources/i18n/messages.properties
new file mode 100644
index 00000000..b0bc5ed0
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/i18n/messages.properties
@@ -0,0 +1,37 @@
+#错误消息
+not.null=* 必须填写
+user.jcaptcha.error=验证码错误
+user.jcaptcha.expire=验证码已失效
+user.not.exists=用户不存在/密码错误
+user.password.not.match=用户不存在/密码错误
+user.password.retry.limit.count=密码输入错误{0}次
+user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
+user.password.delete=对不起,您的账号已被删除
+user.blocked=用户已封禁,请联系管理员
+role.blocked=角色已封禁,请联系管理员
+user.logout.success=退出成功
+
+length.not.valid=长度必须在{min}到{max}个字符之间
+
+user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
+user.password.not.valid=* 5-50个字符
+
+user.email.not.valid=邮箱格式错误
+user.mobile.phone.number.not.valid=手机号格式错误
+user.login.success=登录成功
+user.register.success=注册成功
+user.notfound=请重新登录
+user.forcelogout=管理员强制退出,请重新登录
+user.unknown.error=未知错误,请重新登录
+
+##文件上传消息
+upload.exceed.maxSize=上传的文件大小超出限制的文件大小! 允许的文件最大大小是:{0}MB!
+upload.filename.exceed.length=上传的文件名最长{0}个字符
+
+##权限
+no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
+no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
+no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
+no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
+no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
+no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml
new file mode 100644
index 00000000..9a26a231
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/logback.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+ ${log.pattern}
+
+
+
+
+
+ ${log.path}/sys-info.log
+
+
+
+ ${log.path}/sys-info.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+ INFO
+
+ ACCEPT
+
+ DENY
+
+
+
+
+ ${log.path}/sys-error.log
+
+
+
+ ${log.path}/sys-error.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+ ERROR
+
+ ACCEPT
+
+ DENY
+
+
+
+
+
+ ${log.path}/sys-user.log
+
+
+ ${log.path}/sys-user.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml
new file mode 100644
index 00000000..ac47c038
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-admin/src/main/resources/templatefile/消防安全重点部位情况登记表.xlsx b/ruoyi-admin/src/main/resources/templatefile/消防安全重点部位情况登记表.xlsx
new file mode 100644
index 00000000..8e58d705
Binary files /dev/null and b/ruoyi-admin/src/main/resources/templatefile/消防安全重点部位情况登记表.xlsx differ
diff --git a/ruoyi-admin/target/classes/META-INF/spring-devtools.properties b/ruoyi-admin/target/classes/META-INF/spring-devtools.properties
new file mode 100644
index 00000000..2b23f85a
--- /dev/null
+++ b/ruoyi-admin/target/classes/META-INF/spring-devtools.properties
@@ -0,0 +1 @@
+restart.include.json=/com.alibaba.fastjson.*.jar
\ No newline at end of file
diff --git a/ruoyi-admin/target/classes/application-dev.yml b/ruoyi-admin/target/classes/application-dev.yml
new file mode 100644
index 00000000..0683a1ef
--- /dev/null
+++ b/ruoyi-admin/target/classes/application-dev.yml
@@ -0,0 +1,63 @@
+ruoyi:
+ # 文件路径
+ profile: D:/ruoyi/uploadPath
+# 数据源配置
+spring:
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ druid:
+ # 主库数据源
+ master:
+# url: jdbc:mysql://121.40.191.30:3306/ry-base-tenant?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ url: jdbc:mysql://43.139.7.36:3306/ry-base-tenant?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: it@luokeng
+# password: 123456
+
+ # 从库数据源
+ slave:
+ # 从数据源开关/默认关闭
+ enabled: false
+ url:
+ username:
+ password:
+ # 初始连接数
+ initialSize: 5
+ # 最小连接池数量
+ minIdle: 10
+ # 最大连接池数量
+ maxActive: 20
+ # 配置获取连接等待超时的时间
+ maxWait: 60000
+ # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+ timeBetweenEvictionRunsMillis: 60000
+ # 配置一个连接在池中最小生存的时间,单位是毫秒
+ minEvictableIdleTimeMillis: 300000
+ # 配置一个连接在池中最大生存的时间,单位是毫秒
+ maxEvictableIdleTimeMillis: 900000
+ # 配置检测连接是否有效
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 设置白名单,不填则允许所有访问
+ allow:
+ url-pattern: /druid/*
+ # 控制台管理用户名和密码
+ login-username: ruoyi
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 慢SQL记录
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: true
diff --git a/ruoyi-admin/target/classes/application-druid.yml b/ruoyi-admin/target/classes/application-druid.yml
new file mode 100644
index 00000000..b4aa52c5
--- /dev/null
+++ b/ruoyi-admin/target/classes/application-druid.yml
@@ -0,0 +1,57 @@
+# 数据源配置
+spring:
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ druid:
+ # 主库数据源
+ master:
+ url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: root
+ # 从库数据源
+ slave:
+ # 从数据源开关/默认关闭
+ enabled: false
+ url:
+ username:
+ password:
+ # 初始连接数
+ initialSize: 5
+ # 最小连接池数量
+ minIdle: 10
+ # 最大连接池数量
+ maxActive: 20
+ # 配置获取连接等待超时的时间
+ maxWait: 60000
+ # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+ timeBetweenEvictionRunsMillis: 60000
+ # 配置一个连接在池中最小生存的时间,单位是毫秒
+ minEvictableIdleTimeMillis: 300000
+ # 配置一个连接在池中最大生存的时间,单位是毫秒
+ maxEvictableIdleTimeMillis: 900000
+ # 配置检测连接是否有效
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 设置白名单,不填则允许所有访问
+ allow:
+ url-pattern: /druid/*
+ # 控制台管理用户名和密码
+ login-username: ruoyi
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 慢SQL记录
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: true
diff --git a/ruoyi-admin/target/classes/application-test.yml b/ruoyi-admin/target/classes/application-test.yml
new file mode 100644
index 00000000..8217380e
--- /dev/null
+++ b/ruoyi-admin/target/classes/application-test.yml
@@ -0,0 +1,61 @@
+ruoyi:
+ # 文件路径
+ profile: /project/xinchuang/xiaofang-dm/uploadPath
+
+# 数据源配置
+spring:
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ druid:
+ # 主库数据源
+ master:
+ url: jdbc:mysql://192.168.254.125:3306/xiaofang?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: abcd1234
+ # 从库数据源
+ slave:
+ # 从数据源开关/默认关闭
+ enabled: false
+ url:
+ username:
+ password:
+ # 初始连接数
+ initialSize: 5
+ # 最小连接池数量
+ minIdle: 10
+ # 最大连接池数量
+ maxActive: 20
+ # 配置获取连接等待超时的时间
+ maxWait: 60000
+ # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+ timeBetweenEvictionRunsMillis: 60000
+ # 配置一个连接在池中最小生存的时间,单位是毫秒
+ minEvictableIdleTimeMillis: 300000
+ # 配置一个连接在池中最大生存的时间,单位是毫秒
+ maxEvictableIdleTimeMillis: 900000
+ # 配置检测连接是否有效
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 设置白名单,不填则允许所有访问
+ allow:
+ url-pattern: /druid/*
+ # 控制台管理用户名和密码
+ login-username: ruoyi
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 慢SQL记录
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: true
diff --git a/ruoyi-admin/target/classes/application.yml b/ruoyi-admin/target/classes/application.yml
new file mode 100644
index 00000000..c05620e3
--- /dev/null
+++ b/ruoyi-admin/target/classes/application.yml
@@ -0,0 +1,154 @@
+# 项目相关配置
+ruoyi:
+ # 名称
+ name: RuoYi
+ # 版本
+ version: 1.0.0
+ # 版权年份
+ copyrightYear: 2022
+ # 实例演示开关
+ demoEnabled: true
+ # 获取ip地址开关
+ addressEnabled: false
+ # 验证码类型 math 数组计算 char 字符验证
+ captchaType: math
+ tenant:
+ enable: true
+ ignore-urls:
+ - /system/tenant/get-id-by-name # 基于名字获取租户,不许带租户编号
+ - /captcha/get # 获取图片验证码,和租户无关
+ - /captcha/check # 校验图片验证码,和租户无关
+ - /infra/file/*/get/** # 获取图片,和租户无关
+ - /system/sms/callback/* # 短信回调接口,无法带上租户编号
+ - /app-api/pay/order/notify/* # 支付回调通知,不携带租户编号
+ - /jmreport/** # 积木报表,无法携带租户编号。*匹配任意字符(除了路径分隔符),而**匹配任意字符
+# 开发环境配置
+server:
+ # 服务器的HTTP端口,默认为8080
+ port: 8080
+ servlet:
+ # 应用的访问路径
+ context-path: /
+ tomcat:
+ # tomcat的URI编码
+ uri-encoding: UTF-8
+ # 连接数满后的排队数,默认为100
+ accept-count: 1000
+ threads:
+ # tomcat最大线程数,默认为200
+ max: 800
+ # Tomcat启动初始化的线程数,默认值10
+ min-spare: 100
+
+# 日志配置
+logging:
+ level:
+ com.ruoyi: debug
+ org.springframework: warn
+
+# 用户配置
+user:
+ password:
+ # 密码最大错误次数
+ maxRetryCount: 5
+ # 密码锁定时间(默认10分钟)
+ lockTime: 10
+
+# Spring配置
+spring:
+ # 资源信息
+ messages:
+ # 国际化资源文件路径
+ basename: i18n/messages
+ profiles:
+ active: dev
+ # 文件上传
+ servlet:
+ multipart:
+ # 单个文件大小
+ max-file-size: 10MB
+ # 设置总上传的文件大小
+ max-request-size: 20MB
+ # 服务模块
+ devtools:
+ restart:
+ # 热部署开关
+ enabled: false
+ cache:
+ type: ehcache
+ ehcache:
+ config: classpath:/ehcache.xml
+ # redis 配置
+# redis:
+# # 地址
+# host: localhost
+# # 端口,默认为6379
+# port: 6379
+# # 数据库索引
+# database: 0
+# # 密码
+# password:
+# # 连接超时时间
+# timeout: 10s
+# lettuce:
+# pool:
+# # 连接池中的最小空闲连接
+# min-idle: 0
+# # 连接池中的最大空闲连接
+# max-idle: 8
+# # 连接池的最大数据库连接数
+# max-active: 8
+# # #连接池最大阻塞等待时间(使用负值表示没有限制)
+# max-wait: -1ms
+
+# token配置
+token:
+ # 令牌自定义标识
+ header: Authorization
+ # 令牌密钥
+ secret: abcytrmiuumwefsadfdfafahvwxyz
+ # 令牌有效期(默认30分钟)
+ expireTime: 30
+
+# MyBatis Plus配置
+mybatis-plus:
+ # 搜索指定包别名
+ typeAliasesPackage: com.ruoyi.**.domain
+ # 配置mapper的扫描,找到所有的mapper.xml映射文件
+ mapperLocations: classpath*:mapper/**/*Mapper.xml
+ # 加载全局的配置文件
+ configLocation: classpath:mybatis/mybatis-config.xml
+
+# PageHelper分页插件
+pagehelper:
+ helperDialect: mysql
+ supportMethodsArguments: true
+ params: count=countSql
+
+# Swagger配置
+swagger:
+ # 是否开启swagger
+ enabled: true
+ # 请求前缀
+ pathMapping: /dev-api
+
+# 防止XSS攻击
+xss:
+ # 过滤开关
+ enabled: true
+ # 排除链接(多个用逗号分隔)
+ excludes: /system/notice
+ # 匹配链接
+ urlPatterns: /system/*,/monitor/*,/tool/*
+
+# 工作流 Flowable 配置
+flowable:
+ # 1. false: 默认值,Flowable 启动时,对比数据库表中保存的版本,如果不匹配。将抛出异常
+ # 2. true: 启动时会对数据库中所有表进行更新操作,如果表存在,不做处理,反之,自动创建表
+ # 3. create_drop: 启动时自动创建表,关闭时自动删除表
+ # 4. drop_create: 启动时,删除旧表,再创建新表
+ database-schema-update: true # 设置为 false,可通过 https://github.com/flowable/flowable-sql 初始化
+ db-history-used: true # flowable6 默认 true 生成信息表,无需手动设置
+ check-process-definitions: false # 设置为 false,禁用 /resources/processes 自动部署 BPMN XML 流程
+ history-level: full # full:保存历史数据的最高级别,可保存全部流程相关细节,包括流程流转各节点参数
+
diff --git a/ruoyi-admin/target/classes/banner.txt b/ruoyi-admin/target/classes/banner.txt
new file mode 100644
index 00000000..0931cb84
--- /dev/null
+++ b/ruoyi-admin/target/classes/banner.txt
@@ -0,0 +1,24 @@
+Application Version: ${ruoyi.version}
+Spring Boot Version: ${spring-boot.version}
+////////////////////////////////////////////////////////////////////
+// _ooOoo_ //
+// o8888888o //
+// 88" . "88 //
+// (| ^_^ |) //
+// O\ = /O //
+// ____/`---'\____ //
+// .' \\| |// `. //
+// / \\||| : |||// \ //
+// / _||||| -:- |||||- \ //
+// | | \\\ - /// | | //
+// | \_| ''\---/'' | | //
+// \ .-\__ `-` ___/-. / //
+// ___`. .' /--.--\ `. . ___ //
+// ."" '< `.___\_<|>_/___.' >'"". //
+// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
+// \ \ `-. \_ __\ /__ _/ .-` / / //
+// ========`-.____`-.___\_____/___.-`____.-'======== //
+// `=---=' //
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
+// 佛祖保佑 永不宕机 永无BUG //
+////////////////////////////////////////////////////////////////////
\ No newline at end of file
diff --git a/ruoyi-admin/target/classes/com/ruoyi/RuoYiApplication.class b/ruoyi-admin/target/classes/com/ruoyi/RuoYiApplication.class
new file mode 100644
index 00000000..622bd74c
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/RuoYiApplication.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/RuoYiServletInitializer.class b/ruoyi-admin/target/classes/com/ruoyi/RuoYiServletInitializer.class
new file mode 100644
index 00000000..57c45ef9
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/RuoYiServletInitializer.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/TestFlowableApplication.class b/ruoyi-admin/target/classes/com/ruoyi/TestFlowableApplication.class
new file mode 100644
index 00000000..b756b93e
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/TestFlowableApplication.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/DevinUtil.class b/ruoyi-admin/target/classes/com/ruoyi/web/DevinUtil.class
new file mode 100644
index 00000000..4a06690e
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/DevinUtil.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/common/CaptchaController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/common/CaptchaController.class
new file mode 100644
index 00000000..e250ac12
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/common/CaptchaController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/common/CommonController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/common/CommonController.class
new file mode 100644
index 00000000..a47791c1
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/common/CommonController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/ServerController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/ServerController.class
new file mode 100644
index 00000000..54c33012
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/ServerController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysLogininforController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysLogininforController.class
new file mode 100644
index 00000000..3a42803c
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysLogininforController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysOperlogController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysOperlogController.class
new file mode 100644
index 00000000..3e08e462
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysOperlogController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysUserOnlineController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysUserOnlineController.class
new file mode 100644
index 00000000..81014f7b
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysUserOnlineController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysConfigController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysConfigController.class
new file mode 100644
index 00000000..e33e637e
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysConfigController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDeptController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDeptController.class
new file mode 100644
index 00000000..9dde9809
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDeptController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDictDataController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDictDataController.class
new file mode 100644
index 00000000..20df5911
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDictDataController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDictTypeController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDictTypeController.class
new file mode 100644
index 00000000..6c2c3dbf
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDictTypeController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysIndexController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysIndexController.class
new file mode 100644
index 00000000..4e6fdb06
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysIndexController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysLoginController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysLoginController.class
new file mode 100644
index 00000000..afa71048
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysLoginController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysMenuController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysMenuController.class
new file mode 100644
index 00000000..146c36f9
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysMenuController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysNoticeController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysNoticeController.class
new file mode 100644
index 00000000..7e313568
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysNoticeController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysPostController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysPostController.class
new file mode 100644
index 00000000..f4e3641e
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysPostController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysProfileController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysProfileController.class
new file mode 100644
index 00000000..9e6981d7
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysProfileController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysRegisterController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysRegisterController.class
new file mode 100644
index 00000000..0fc9d05c
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysRegisterController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysRoleController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysRoleController.class
new file mode 100644
index 00000000..6c1d0503
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysRoleController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysTreeDictController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysTreeDictController.class
new file mode 100644
index 00000000..5ce95268
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysTreeDictController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysTreeDictDataController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysTreeDictDataController.class
new file mode 100644
index 00000000..480aaec0
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysTreeDictDataController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysUserController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysUserController.class
new file mode 100644
index 00000000..246ba21d
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysUserController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/TenantController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/TenantController.class
new file mode 100644
index 00000000..91628cfc
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/TenantController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/TenantPackageController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/TenantPackageController.class
new file mode 100644
index 00000000..48214ece
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/system/TenantPackageController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/SwaggerController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/SwaggerController.class
new file mode 100644
index 00000000..57181b86
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/SwaggerController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/TestController.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/TestController.class
new file mode 100644
index 00000000..e1ba511e
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/TestController.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/UserEntity.class b/ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/UserEntity.class
new file mode 100644
index 00000000..dec262a7
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/UserEntity.class differ
diff --git a/ruoyi-admin/target/classes/com/ruoyi/web/core/config/SwaggerConfig.class b/ruoyi-admin/target/classes/com/ruoyi/web/core/config/SwaggerConfig.class
new file mode 100644
index 00000000..39c4b3f5
Binary files /dev/null and b/ruoyi-admin/target/classes/com/ruoyi/web/core/config/SwaggerConfig.class differ
diff --git a/ruoyi-admin/target/classes/ehcache.xml b/ruoyi-admin/target/classes/ehcache.xml
new file mode 100644
index 00000000..c2bad019
--- /dev/null
+++ b/ruoyi-admin/target/classes/ehcache.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-admin/target/classes/i18n/messages.properties b/ruoyi-admin/target/classes/i18n/messages.properties
new file mode 100644
index 00000000..b0bc5ed0
--- /dev/null
+++ b/ruoyi-admin/target/classes/i18n/messages.properties
@@ -0,0 +1,37 @@
+#错误消息
+not.null=* 必须填写
+user.jcaptcha.error=验证码错误
+user.jcaptcha.expire=验证码已失效
+user.not.exists=用户不存在/密码错误
+user.password.not.match=用户不存在/密码错误
+user.password.retry.limit.count=密码输入错误{0}次
+user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
+user.password.delete=对不起,您的账号已被删除
+user.blocked=用户已封禁,请联系管理员
+role.blocked=角色已封禁,请联系管理员
+user.logout.success=退出成功
+
+length.not.valid=长度必须在{min}到{max}个字符之间
+
+user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
+user.password.not.valid=* 5-50个字符
+
+user.email.not.valid=邮箱格式错误
+user.mobile.phone.number.not.valid=手机号格式错误
+user.login.success=登录成功
+user.register.success=注册成功
+user.notfound=请重新登录
+user.forcelogout=管理员强制退出,请重新登录
+user.unknown.error=未知错误,请重新登录
+
+##文件上传消息
+upload.exceed.maxSize=上传的文件大小超出限制的文件大小! 允许的文件最大大小是:{0}MB!
+upload.filename.exceed.length=上传的文件名最长{0}个字符
+
+##权限
+no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
+no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
+no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
+no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
+no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
+no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
diff --git a/ruoyi-admin/target/classes/logback.xml b/ruoyi-admin/target/classes/logback.xml
new file mode 100644
index 00000000..9a26a231
--- /dev/null
+++ b/ruoyi-admin/target/classes/logback.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+ ${log.pattern}
+
+
+
+
+
+ ${log.path}/sys-info.log
+
+
+
+ ${log.path}/sys-info.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+ INFO
+
+ ACCEPT
+
+ DENY
+
+
+
+
+ ${log.path}/sys-error.log
+
+
+
+ ${log.path}/sys-error.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+ ERROR
+
+ ACCEPT
+
+ DENY
+
+
+
+
+
+ ${log.path}/sys-user.log
+
+
+ ${log.path}/sys-user.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-admin/target/classes/mybatis/mybatis-config.xml b/ruoyi-admin/target/classes/mybatis/mybatis-config.xml
new file mode 100644
index 00000000..ac47c038
--- /dev/null
+++ b/ruoyi-admin/target/classes/mybatis/mybatis-config.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-admin/target/classes/templatefile/消防安全重点部位情况登记表.xlsx b/ruoyi-admin/target/classes/templatefile/消防安全重点部位情况登记表.xlsx
new file mode 100644
index 00000000..8e58d705
Binary files /dev/null and b/ruoyi-admin/target/classes/templatefile/消防安全重点部位情况登记表.xlsx differ
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
new file mode 100644
index 00000000..b929a62b
--- /dev/null
+++ b/ruoyi-common/pom.xml
@@ -0,0 +1,206 @@
+
+
+
+ ruoyi
+ com.ruoyi
+ 3.8.4
+
+ 4.0.0
+
+ ruoyi-common
+
+
+ common通用工具
+
+
+
+
+ com.alibaba
+ easyexcel
+
+
+
+ org.springframework
+ spring-context-support
+
+
+
+
+ org.springframework
+ spring-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+
+ com.github.pagehelper
+ pagehelper-spring-boot-starter
+
+
+ org.mybatis
+ mybatis
+
+
+ org.mybatis
+ mybatis-spring
+
+
+ com.github.jsqlparser
+ jsqlparser
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+
+ com.alibaba.fastjson2
+ fastjson2
+
+
+
+
+ commons-io
+ commons-io
+
+
+
+
+ commons-fileupload
+ commons-fileupload
+
+
+
+
+ org.apache.poi
+ poi-ooxml
+
+
+
+
+ org.yaml
+ snakeyaml
+
+
+
+
+ io.jsonwebtoken
+ jjwt
+
+
+
+
+ javax.xml.bind
+ jaxb-api
+
+
+
+ net.sf.ehcache
+ ehcache
+ 2.10.6
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+
+
+
+
+
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+
+ eu.bitwalker
+ UserAgentUtils
+
+
+
+
+ javax.servlet
+ javax.servlet-api
+
+
+
+
+ cn.hutool
+ hutool-all
+
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+ com.github.xiaoymin
+ knife4j-spring-boot-starter
+
+
+
+
+ com.alibaba
+ druid-spring-boot-starter
+
+
+
+ org.mapstruct
+ mapstruct
+
+
+ org.mapstruct
+ mapstruct-jdk8
+
+
+ org.mapstruct
+ mapstruct-processor
+
+
+
+ com.alibaba
+ transmittable-thread-local
+
+
+
+
+
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java
new file mode 100644
index 00000000..1d6d4f44
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 匿名访问不鉴权注解
+ *
+ * @author ruoyi
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Anonymous
+{
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
new file mode 100644
index 00000000..aae7f72c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
@@ -0,0 +1,33 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 数据权限过滤注解
+ *
+ * @author ruoyi
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataScope
+{
+ /**
+ * 部门表的别名
+ */
+ public String deptAlias() default "";
+
+ /**
+ * 用户表的别名
+ */
+ public String userAlias() default "";
+
+ /**
+ * 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来
+ */
+ public String permission() default "";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
new file mode 100644
index 00000000..79cd191f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
@@ -0,0 +1,28 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import com.ruoyi.common.enums.DataSourceType;
+
+/**
+ * 自定义多数据源切换注解
+ *
+ * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
+ *
+ * @author ruoyi
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface DataSource
+{
+ /**
+ * 切换数据源名称
+ */
+ public DataSourceType value() default DataSourceType.MASTER;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictFormat.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictFormat.java
new file mode 100644
index 00000000..5ff76a07
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictFormat.java
@@ -0,0 +1,22 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 字典格式化
+ *
+ * 实现将字典数据的值,格式化成字典数据的标签
+ */
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface DictFormat {
+
+ /**
+ * 例如说,SysDictTypeConstants、InfDictTypeConstants
+ *
+ * @return 字典类型
+ */
+ String value();
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
new file mode 100644
index 00000000..a8fa282b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
@@ -0,0 +1,187 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.math.BigDecimal;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import com.ruoyi.common.utils.poi.ExcelHandlerAdapter;
+
+/**
+ * 自定义导出Excel数据注解
+ *
+ * @author ruoyi
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Excel
+{
+ /**
+ * 导出时在excel中排序
+ */
+ public int sort() default Integer.MAX_VALUE;
+
+ /**
+ * 导出到Excel中的名字.
+ */
+ public String name() default "";
+
+ /**
+ * 日期格式, 如: yyyy-MM-dd
+ */
+ public String dateFormat() default "";
+
+ /**
+ * 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
+ */
+ public String dictType() default "";
+
+ /**
+ * 读取内容转表达式 (如: 0=男,1=女,2=未知)
+ */
+ public String readConverterExp() default "";
+
+ /**
+ * 分隔符,读取字符串组内容
+ */
+ public String separator() default ",";
+
+ /**
+ * BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
+ */
+ public int scale() default -1;
+
+ /**
+ * BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
+ */
+ public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
+
+ /**
+ * 导出时在excel中每个列的高度 单位为字符
+ */
+ public double height() default 14;
+
+ /**
+ * 导出时在excel中每个列的宽 单位为字符
+ */
+ public double width() default 16;
+
+ /**
+ * 文字后缀,如% 90 变成90%
+ */
+ public String suffix() default "";
+
+ /**
+ * 当值为空时,字段的默认值
+ */
+ public String defaultValue() default "";
+
+ /**
+ * 提示信息
+ */
+ public String prompt() default "";
+
+ /**
+ * 设置只能选择不能输入的列内容.
+ */
+ public String[] combo() default {};
+
+ /**
+ * 是否需要纵向合并单元格,应对需求:含有list集合单元格)
+ */
+ public boolean needMerge() default false;
+
+ /**
+ * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
+ */
+ public boolean isExport() default true;
+
+ /**
+ * 另一个类中的属性名称,支持多级获取,以小数点隔开
+ */
+ public String targetAttr() default "";
+
+ /**
+ * 是否自动统计数据,在最后追加一行统计数据总和
+ */
+ public boolean isStatistics() default false;
+
+ /**
+ * 导出类型(0数字 1字符串 2图片)
+ */
+ public ColumnType cellType() default ColumnType.STRING;
+
+ /**
+ * 导出列头背景色
+ */
+ public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
+
+ /**
+ * 导出列头字体颜色
+ */
+ public IndexedColors headerColor() default IndexedColors.WHITE;
+
+ /**
+ * 导出单元格背景色
+ */
+ public IndexedColors backgroundColor() default IndexedColors.WHITE;
+
+ /**
+ * 导出单元格字体颜色
+ */
+ public IndexedColors color() default IndexedColors.BLACK;
+
+ /**
+ * 导出字段对齐方式
+ */
+ public HorizontalAlignment align() default HorizontalAlignment.CENTER;
+
+ /**
+ * 自定义数据处理器
+ */
+ public Class> handler() default ExcelHandlerAdapter.class;
+
+ /**
+ * 自定义数据处理器参数
+ */
+ public String[] args() default {};
+
+ /**
+ * 字段类型(0:导出导入;1:仅导出;2:仅导入)
+ */
+ Type type() default Type.ALL;
+
+ public enum Type
+ {
+ ALL(0), EXPORT(1), IMPORT(2);
+ private final int value;
+
+ Type(int value)
+ {
+ this.value = value;
+ }
+
+ public int value()
+ {
+ return this.value;
+ }
+ }
+
+ public enum ColumnType
+ {
+ NUMERIC(0), STRING(1), IMAGE(2);
+ private final int value;
+
+ ColumnType(int value)
+ {
+ this.value = value;
+ }
+
+ public int value()
+ {
+ return this.value;
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java
new file mode 100644
index 00000000..1f1cc81b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Excel注解集
+ *
+ * @author ruoyi
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Excels
+{
+ public Excel[] value();
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java
new file mode 100644
index 00000000..ca02c6c4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java
@@ -0,0 +1,46 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.enums.OperatorType;
+
+/**
+ * 自定义操作日志记录注解
+ *
+ * @author ruoyi
+ *
+ */
+@Target({ ElementType.PARAMETER, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Log
+{
+ /**
+ * 模块
+ */
+ public String title() default "";
+
+ /**
+ * 功能
+ */
+ public BusinessType businessType() default BusinessType.OTHER;
+
+ /**
+ * 操作人类别
+ */
+ public OperatorType operatorType() default OperatorType.MANAGE;
+
+ /**
+ * 是否保存请求的参数
+ */
+ public boolean isSaveRequestData() default true;
+
+ /**
+ * 是否保存响应的参数
+ */
+ public boolean isSaveResponseData() default true;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java
new file mode 100644
index 00000000..0f024c7d
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java
@@ -0,0 +1,40 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.enums.LimitType;
+
+/**
+ * 限流注解
+ *
+ * @author ruoyi
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RateLimiter
+{
+ /**
+ * 限流key
+ */
+ public String key() default CacheConstants.RATE_LIMIT_KEY;
+
+ /**
+ * 限流时间,单位秒
+ */
+ public int time() default 60;
+
+ /**
+ * 限流次数
+ */
+ public int count() default 100;
+
+ /**
+ * 限流类型
+ */
+ public LimitType limitType() default LimitType.DEFAULT;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java
new file mode 100644
index 00000000..b7697481
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java
@@ -0,0 +1,31 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 自定义注解防止表单重复提交
+ *
+ * @author ruoyi
+ *
+ */
+@Inherited
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RepeatSubmit
+{
+ /**
+ * 间隔时间(ms),小于此时间视为重复提交
+ */
+ public int interval() default 5000;
+
+ /**
+ * 提示消息
+ */
+ public String message() default "不允许重复提交,请稍候再试";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ReportExcel.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ReportExcel.java
new file mode 100644
index 00000000..f1e13972
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ReportExcel.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 自定义easy excel报表下载表单时对数据进行格式转换
+ *
+ * @author ruoyi
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface ReportExcel
+{
+
+ /**
+ * 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
+ */
+ public String dictType() default "";
+ /**
+ * 如果是字典类型,值的转方式。0-为展示所有字典值并且带□和☑
+ */
+ public String dictTransferType() default "0";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
new file mode 100644
index 00000000..9f69c358
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
@@ -0,0 +1,150 @@
+package com.ruoyi.common.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 读取项目相关配置
+ *
+ * @author ruoyi
+ */
+@Component
+@ConfigurationProperties(prefix = "ruoyi")
+public class RuoYiConfig
+{
+ /** 项目名称 */
+ private String name;
+
+ /** 版本 */
+ private String version;
+
+ /** 版权年份 */
+ private String copyrightYear;
+
+ /** 实例演示开关 */
+ private boolean demoEnabled;
+
+ /** 上传路径 */
+ 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 boolean isDemoEnabled()
+ {
+ return demoEnabled;
+ }
+
+ public void setDemoEnabled(boolean demoEnabled)
+ {
+ this.demoEnabled = demoEnabled;
+ }
+
+ public static String getProfile()
+ {
+ return profile;
+ }
+
+ public void setProfile(String profile)
+ {
+ RuoYiConfig.profile = profile;
+ }
+
+ public static boolean isAddressEnabled()
+ {
+ return addressEnabled;
+ }
+
+ public void setAddressEnabled(boolean addressEnabled)
+ {
+ RuoYiConfig.addressEnabled = addressEnabled;
+ }
+
+ public static String getCaptchaType() {
+ return captchaType;
+ }
+
+ public void setCaptchaType(String captchaType) {
+ RuoYiConfig.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 getTempDownloadPath()
+ {
+ return getProfile() + "/download/temp/";
+ }
+ /**
+ * 获取上传路径
+ */
+ public static String getUploadPath()
+ {
+ return getProfile() + "/upload";
+ }
+
+ /**
+ * 获取文件模板路径
+ */
+ public static String getTemplateFilePath()
+ {
+ return getProfile() + "/template";
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java
new file mode 100644
index 00000000..296733b9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java
@@ -0,0 +1,54 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 缓存的key 常量
+ *
+ * @author ruoyi
+ */
+public class CacheConstants
+{
+ /**
+ * 登录用户 redis key
+ */
+ public static final String LOGIN_TOKEN_KEY = "login_tokens:";
+
+ /**
+ * 验证码 redis key
+ */
+ public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
+
+ /**
+ * 参数管理 cache key
+ */
+ public static final String SYS_CONFIG_KEY = "sys_config:";
+
+ /**
+ * 字典管理 cache key
+ */
+ public static final String SYS_DICT_KEY = "sys_dict:";
+
+ /**
+ * 分类管理-list cache key
+ */
+ public static final String TREE_DICT_KEY = "sys_tree_dict:";
+
+ /**
+ * 防重提交 redis key
+ */
+ public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
+
+ /**
+ * 限流 redis key
+ */
+ public static final String RATE_LIMIT_KEY = "rate_limit:";
+
+ /**
+ * 登录账户密码错误次数 redis key
+ */
+ public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
+
+ /**
+ * 租户管理 cache key
+ */
+ public static final String SYS_TENANT_KEY = "sys_tenant:";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
new file mode 100644
index 00000000..ed687257
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -0,0 +1,152 @@
+package com.ruoyi.common.constant;
+
+import io.jsonwebtoken.Claims;
+
+/**
+ * 通用常量信息
+ *
+ * @author ruoyi
+ */
+public class Constants
+{
+ /**
+ * UTF-8 字符集
+ */
+ public static final String UTF8 = "UTF-8";
+
+ /**
+ * GBK 字符集
+ */
+ public static final String GBK = "GBK";
+
+ /**
+ * www主域
+ */
+ public static final String WWW = "www.";
+
+ /**
+ * http请求
+ */
+ public static final String HTTP = "http://";
+
+ /**
+ * https请求
+ */
+ public static final String HTTPS = "https://";
+
+ /**
+ * 通用成功标识
+ */
+ public static final String SUCCESS = "0";
+
+ /**
+ * 通用失败标识
+ */
+ public static final String FAIL = "1";
+
+ /**
+ * 通用true标识
+ */
+ public static final String TRUE = "1";
+
+ /**
+ * 通用false标识
+ */
+ public static final String FALSE = "0";
+
+ /**
+ * 登录成功
+ */
+ public static final String LOGIN_SUCCESS = "Success";
+
+ /**
+ * 注销
+ */
+ public static final String LOGOUT = "Logout";
+
+ /**
+ * 注册
+ */
+ public static final String REGISTER = "Register";
+
+ /**
+ * 登录失败
+ */
+ public static final String LOGIN_FAIL = "Error";
+
+ /**
+ * 验证码有效期(分钟)
+ */
+ public static final Integer CAPTCHA_EXPIRATION = 2;
+
+ /**
+ * 令牌
+ */
+ public static final String TOKEN = "token";
+
+ /**
+ * 令牌前缀
+ */
+ public static final String TOKEN_PREFIX = "Bearer ";
+
+ /**
+ * 令牌前缀
+ */
+ public static final String LOGIN_USER_KEY = "login_user_key";
+
+ /**
+ * 用户ID
+ */
+ public static final String JWT_USERID = "userid";
+
+ /**
+ * 用户名称
+ */
+ public static final String JWT_USERNAME = Claims.SUBJECT;
+
+ /**
+ * 用户头像
+ */
+ public static final String JWT_AVATAR = "avatar";
+
+ /**
+ * 创建时间
+ */
+ public static final String JWT_CREATED = "created";
+
+ /**
+ * 用户权限
+ */
+ public static final String JWT_AUTHORITIES = "authorities";
+
+ /**
+ * 资源映射路径 前缀
+ */
+ public static final String RESOURCE_PREFIX = "/profile";
+
+ /**
+ * RMI 远程方法调用
+ */
+ public static final String LOOKUP_RMI = "rmi:";
+
+ /**
+ * LDAP 远程方法调用
+ */
+ public static final String LOOKUP_LDAP = "ldap:";
+
+ /**
+ * LDAPS 远程方法调用
+ */
+ public static final String LOOKUP_LDAPS = "ldaps:";
+
+ /**
+ * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
+ */
+ public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
+
+ /**
+ * 定时任务违规的字符
+ */
+ public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
+ "org.springframework", "org.apache", "com.ruoyi.common.utils.file" };
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/ErrorCodeConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ErrorCodeConstants.java
new file mode 100644
index 00000000..66485bea
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ErrorCodeConstants.java
@@ -0,0 +1,145 @@
+package com.ruoyi.common.constant;
+
+
+import com.ruoyi.common.exception.ErrorCode;
+
+/**
+ * Member 错误码枚举类
+ *
+ * member 系统,使用 1-004-000-000 段
+ */
+public interface ErrorCodeConstants {
+
+ // ========== AUTH 模块 1002000000 ==========
+ ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确");
+ ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用");
+ ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确,原因:{}");
+ ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1002000005, "未绑定账号,需要进行绑定");
+ ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1002000006, "Token 已经过期");
+ ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1002000007, "手机号不存在");
+
+ // ========== 菜单模块 1002001000 ==========
+ ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1002001000, "已经存在该名字的菜单");
+ ErrorCode MENU_PARENT_NOT_EXISTS = new ErrorCode(1002001001, "父菜单不存在");
+ ErrorCode MENU_PARENT_ERROR = new ErrorCode(1002001002, "不能设置自己为父菜单");
+ ErrorCode MENU_NOT_EXISTS = new ErrorCode(1002001003, "菜单不存在");
+ ErrorCode MENU_EXISTS_CHILDREN = new ErrorCode(1002001004, "存在子菜单,无法删除");
+ ErrorCode MENU_PARENT_NOT_DIR_OR_MENU = new ErrorCode(1002001005, "父菜单的类型必须是目录或者菜单");
+
+ // ========== 角色模块 1002002000 ==========
+ ErrorCode ROLE_NOT_EXISTS = new ErrorCode(1002002000, "角色不存在");
+ ErrorCode ROLE_NAME_DUPLICATE = new ErrorCode(1002002001, "已经存在名为【{}】的角色");
+ ErrorCode ROLE_CODE_DUPLICATE = new ErrorCode(1002002002, "已经存在编码为【{}】的角色");
+ ErrorCode ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE = new ErrorCode(1002002003, "不能操作类型为系统内置的角色");
+ ErrorCode ROLE_IS_DISABLE = new ErrorCode(1002002004, "名字为【{}】的角色已被禁用");
+ ErrorCode ROLE_ADMIN_CODE_ERROR = new ErrorCode(1002002005, "编码【{}】不能使用");
+
+ // ========== 用户模块 1002003000 ==========
+ ErrorCode USER_USERNAME_EXISTS = new ErrorCode(1002003000, "用户账号已经存在");
+ ErrorCode USER_MOBILE_EXISTS = new ErrorCode(1002003001, "手机号已经存在");
+ ErrorCode USER_EMAIL_EXISTS = new ErrorCode(1002003002, "邮箱已经存在");
+ ErrorCode USER_NOT_EXISTS = new ErrorCode(1002003003, "用户不存在");
+ ErrorCode USER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1002003004, "导入用户数据不能为空!");
+ ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1002003005, "用户密码校验失败");
+ ErrorCode USER_IS_DISABLE = new ErrorCode(1002003006, "名字为【{}】的用户已被禁用");
+ ErrorCode USER_COUNT_MAX = new ErrorCode(1002003008, "创建用户失败,原因:超过租户最大租户配额({})!");
+
+ // ========== 部门模块 1002004000 ==========
+ ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1002004000, "已经存在该名字的部门");
+ ErrorCode DEPT_PARENT_NOT_EXITS = new ErrorCode(1002004001,"父级部门不存在");
+ ErrorCode DEPT_NOT_FOUND = new ErrorCode(1002004002, "当前部门不存在");
+ ErrorCode DEPT_EXITS_CHILDREN = new ErrorCode(1002004003, "存在子部门,无法删除");
+ ErrorCode DEPT_PARENT_ERROR = new ErrorCode(1002004004, "不能设置自己为父部门");
+ ErrorCode DEPT_EXISTS_USER = new ErrorCode(1002004005, "部门中存在员工,无法删除");
+ ErrorCode DEPT_NOT_ENABLE = new ErrorCode(1002004006, "部门不处于开启状态,不允许选择");
+ ErrorCode DEPT_PARENT_IS_CHILD = new ErrorCode(1002004007, "不能设置自己的子部门为父部门");
+
+ // ========== 岗位模块 1002005000 ==========
+ ErrorCode POST_NOT_FOUND = new ErrorCode(1002005000, "当前岗位不存在");
+ ErrorCode POST_NOT_ENABLE = new ErrorCode(1002005001, "岗位({}) 不处于开启状态,不允许选择");
+ ErrorCode POST_NAME_DUPLICATE = new ErrorCode(1002005002, "已经存在该名字的岗位");
+ ErrorCode POST_CODE_DUPLICATE = new ErrorCode(1002005003, "已经存在该标识的岗位");
+
+ // ========== 字典类型 1002006000 ==========
+ ErrorCode DICT_TYPE_NOT_EXISTS = new ErrorCode(1002006001, "当前字典类型不存在");
+ ErrorCode DICT_TYPE_NOT_ENABLE = new ErrorCode(1002006002, "字典类型不处于开启状态,不允许选择");
+ ErrorCode DICT_TYPE_NAME_DUPLICATE = new ErrorCode(1002006003, "已经存在该名字的字典类型");
+ ErrorCode DICT_TYPE_TYPE_DUPLICATE = new ErrorCode(1002006004, "已经存在该类型的字典类型");
+ ErrorCode DICT_TYPE_HAS_CHILDREN = new ErrorCode(1002006005, "无法删除,该字典类型还有字典数据");
+
+ // ========== 字典数据 1002007000 ==========
+ ErrorCode DICT_DATA_NOT_EXISTS = new ErrorCode(1002007001, "当前字典数据不存在");
+ ErrorCode DICT_DATA_NOT_ENABLE = new ErrorCode(1002007002, "字典数据({})不处于开启状态,不允许选择");
+ ErrorCode DICT_DATA_VALUE_DUPLICATE = new ErrorCode(1002007003, "已经存在该值的字典数据");
+
+ // ========== 通知公告 1002008000 ==========
+ ErrorCode NOTICE_NOT_FOUND = new ErrorCode(1002008001, "当前通知公告不存在");
+
+ // ========== 短信渠道 1002011000 ==========
+ ErrorCode SMS_CHANNEL_NOT_EXISTS = new ErrorCode(1002011000, "短信渠道不存在");
+ ErrorCode SMS_CHANNEL_DISABLE = new ErrorCode(1002011001, "短信渠道不处于开启状态,不允许选择");
+ ErrorCode SMS_CHANNEL_HAS_CHILDREN = new ErrorCode(1002011002, "无法删除,该短信渠道还有短信模板");
+
+ // ========== 短信模板 1002012000 ==========
+ ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1002012000, "短信模板不存在");
+ ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002012001, "已经存在编码为【{}】的短信模板");
+
+ // ========== 短信发送 1002013000 ==========
+ ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1002013000, "手机号不存在");
+ ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1002013001, "模板参数({})缺失");
+ ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1002013002, "短信模板不存在");
+
+ // ========== 短信验证码 1002014000 ==========
+ ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1002014000, "验证码不存在");
+ ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1002014001, "验证码已过期");
+ ErrorCode SMS_CODE_USED = new ErrorCode(1002014002, "验证码已使用");
+ ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1002014003, "验证码不正确");
+ ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1002014004, "超过每日短信发送数量");
+ ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1002014005, "短信发送过于频率");
+ ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1002014006, "手机号已被使用");
+ ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1002014007, "验证码未被使用");
+
+ // ========== 租户信息 1002015000 ==========
+ ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1002015000, "租户不存在");
+ ErrorCode TENANT_DISABLE = new ErrorCode(1002015001, "名字为【%s】的租户已被禁用");
+ ErrorCode TENANT_EXPIRE = new ErrorCode(1002015002, "名字为【%s】的租户已过期");
+ ErrorCode TENANT_CAN_NOT_UPDATE_SYSTEM = new ErrorCode(1002015003, "系统租户不能进行修改、删除等操作!");
+
+ // ========== 租户套餐 1002016000 ==========
+ ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1002016000, "租户套餐不存在");
+ ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1002016001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除");
+ ErrorCode TENANT_PACKAGE_DISABLE = new ErrorCode(1002016002, "名字为【{}】的租户套餐已被禁用");
+
+ // ========== 错误码模块 1002017000 ==========
+ ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002017000, "错误码不存在");
+ ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1002017001, "已经存在编码为【{}】的错误码");
+
+ // ========== 社交用户 1002018000 ==========
+ ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1002018000, "社交授权失败,原因是:{}");
+ ErrorCode SOCIAL_USER_UNBIND_NOT_SELF = new ErrorCode(1002018001, "社交解绑失败,非当前用户绑定");
+ ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1002018002, "社交授权失败,找不到对应的用户");
+
+ // ========== 系统敏感词 1002019000 =========
+ ErrorCode SENSITIVE_WORD_NOT_EXISTS = new ErrorCode(1002019000, "系统敏感词在所有标签中都不存在");
+ ErrorCode SENSITIVE_WORD_EXISTS = new ErrorCode(1002019001, "系统敏感词已在标签中存在");
+
+ // ========== OAuth2 客户端 1002020000 =========
+ ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1002020000, "OAuth2 客户端不存在");
+ ErrorCode OAUTH2_CLIENT_EXISTS = new ErrorCode(1002020001, "OAuth2 客户端编号已存在");
+ ErrorCode OAUTH2_CLIENT_DISABLE = new ErrorCode(1002020002, "OAuth2 客户端已禁用");
+ ErrorCode OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS = new ErrorCode(1002020003, "不支持该授权类型");
+ ErrorCode OAUTH2_CLIENT_SCOPE_OVER = new ErrorCode(1002020004, "授权范围过大");
+ ErrorCode OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH = new ErrorCode(1002020005, "无效 redirect_uri: {}");
+ ErrorCode OAUTH2_CLIENT_CLIENT_SECRET_ERROR = new ErrorCode(1002020006, "无效 client_secret: {}");
+
+ // ========== OAuth2 授权 1002021000 =========
+ ErrorCode OAUTH2_GRANT_CLIENT_ID_MISMATCH = new ErrorCode(1002021000, "client_id 不匹配");
+ ErrorCode OAUTH2_GRANT_REDIRECT_URI_MISMATCH = new ErrorCode(1002021001, "redirect_uri 不匹配");
+ ErrorCode OAUTH2_GRANT_STATE_MISMATCH = new ErrorCode(1002021002, "state 不匹配");
+ ErrorCode OAUTH2_GRANT_CODE_NOT_EXISTS = new ErrorCode(1002021003, "code 不存在");
+
+ // ========== OAuth2 授权 1002022000 =========
+ ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1002022000, "code 不存在");
+ ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1002022000, "code 已过期");
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
new file mode 100644
index 00000000..7d899d49
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
@@ -0,0 +1,117 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 代码生成通用常量
+ *
+ * @author ruoyi
+ */
+public class GenConstants
+{
+ /** 单表(增删改查) */
+ public static final String TPL_CRUD = "crud";
+
+ /** 树表(增删改查) */
+ public static final String TPL_TREE = "tree";
+
+ /** 主子表(增删改查) */
+ public static final String TPL_SUB = "sub";
+
+ /** 树编码字段 */
+ public static final String TREE_CODE = "treeCode";
+
+ /** 树父编码字段 */
+ public static final String TREE_PARENT_CODE = "treeParentCode";
+
+ /** 树名称字段 */
+ public static final String TREE_NAME = "treeName";
+
+ /** 上级菜单ID字段 */
+ public static final String PARENT_MENU_ID = "parentMenuId";
+
+ /** 上级菜单名称字段 */
+ public static final String PARENT_MENU_NAME = "parentMenuName";
+
+ /** 数据库字符串类型 */
+ public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
+
+ /** 数据库文本类型 */
+ public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
+
+ /** 数据库时间类型 */
+ public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
+
+ /** 数据库数字类型 */
+ public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
+ "bit", "bigint", "float", "double", "decimal" };
+
+ /** 页面不需要编辑字段 */
+ public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
+
+ /** 页面不需要显示的列表字段 */
+ public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
+ "update_time" };
+
+ /** 页面不需要查询字段 */
+ public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
+ "update_time", "remark" };
+
+ /** Entity基类字段 */
+ public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
+
+ /** Tree基类字段 */
+ public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" };
+
+ /** 文本框 */
+ public static final String HTML_INPUT = "input";
+
+ /** 文本域 */
+ public static final String HTML_TEXTAREA = "textarea";
+
+ /** 下拉框 */
+ public static final String HTML_SELECT = "select";
+
+ /** 单选框 */
+ public static final String HTML_RADIO = "radio";
+
+ /** 复选框 */
+ public static final String HTML_CHECKBOX = "checkbox";
+
+ /** 日期控件 */
+ public static final String HTML_DATETIME = "datetime";
+
+ /** 图片上传控件 */
+ public static final String HTML_IMAGE_UPLOAD = "imageUpload";
+
+ /** 文件上传控件 */
+ public static final String HTML_FILE_UPLOAD = "fileUpload";
+
+ /** 富文本控件 */
+ public static final String HTML_EDITOR = "editor";
+
+ /** 字符串类型 */
+ public static final String TYPE_STRING = "String";
+
+ /** 整型 */
+ public static final String TYPE_INTEGER = "Integer";
+
+ /** 长整型 */
+ public static final String TYPE_LONG = "Long";
+
+ /** 浮点型 */
+ public static final String TYPE_DOUBLE = "Double";
+
+ /** 高精度计算类型 */
+ public static final String TYPE_BIGDECIMAL = "BigDecimal";
+
+ /** 时间类型 */
+ public static final String TYPE_DATE = "Date";
+
+ /** 模糊查询 */
+ public static final String QUERY_LIKE = "LIKE";
+
+ /** 相等查询 */
+ public static final String QUERY_EQ = "EQ";
+
+ /** 需要 */
+ public static final String REQUIRE = "1";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java
new file mode 100644
index 00000000..54a24394
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java
@@ -0,0 +1,93 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 返回状态码
+ *
+ * @author ruoyi
+ */
+public class HttpStatus {
+ /**
+ * 操作成功
+ */
+ public static final int SUCCESS = 200;
+
+ /**
+ * 对象创建成功
+ */
+ public static final int CREATED = 201;
+
+ /**
+ * 请求已经被接受
+ */
+ public static final int ACCEPTED = 202;
+
+ /**
+ * 操作已经执行成功,但是没有返回数据
+ */
+ public static final int NO_CONTENT = 204;
+
+ /**
+ * 资源已被移除
+ */
+ public static final int MOVED_PERM = 301;
+
+ /**
+ * 重定向
+ */
+ public static final int SEE_OTHER = 303;
+
+ /**
+ * 资源没有被修改
+ */
+ public static final int NOT_MODIFIED = 304;
+
+ /**
+ * 参数列表错误(缺少,格式不匹配)
+ */
+ public static final int BAD_REQUEST = 400;
+
+ /**
+ * 未授权
+ */
+ public static final int UNAUTHORIZED = 401;
+
+ /**
+ * 访问受限,授权过期
+ */
+ public static final int FORBIDDEN = 403;
+
+ /**
+ * 资源,服务未找到
+ */
+ public static final int NOT_FOUND = 404;
+
+ /**
+ * 不允许的http方法
+ */
+ public static final int BAD_METHOD = 405;
+
+ /**
+ * 资源冲突,或者资源被锁
+ */
+ public static final int CONFLICT = 409;
+
+ /**
+ * 不支持的数据,媒体类型
+ */
+ public static final int UNSUPPORTED_TYPE = 415;
+
+ /**
+ * 系统内部错误
+ */
+ public static final int ERROR = 500;
+
+ /**
+ * 接口未实现
+ */
+ public static final int NOT_IMPLEMENTED = 501;
+
+ /**
+ * 系统警告消息
+ */
+ public static final int WARN = 601;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java
new file mode 100644
index 00000000..62ad8154
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java
@@ -0,0 +1,50 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 任务调度通用常量
+ *
+ * @author ruoyi
+ */
+public class ScheduleConstants
+{
+ public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
+
+ /** 执行目标key */
+ public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
+
+ /** 默认 */
+ public static final String MISFIRE_DEFAULT = "0";
+
+ /** 立即触发执行 */
+ public static final String MISFIRE_IGNORE_MISFIRES = "1";
+
+ /** 触发一次执行 */
+ public static final String MISFIRE_FIRE_AND_PROCEED = "2";
+
+ /** 不触发立即执行 */
+ public static final String MISFIRE_DO_NOTHING = "3";
+
+ public enum Status
+ {
+ /**
+ * 正常
+ */
+ NORMAL("0"),
+ /**
+ * 暂停
+ */
+ PAUSE("1");
+
+ private String value;
+
+ private Status(String value)
+ {
+ this.value = value;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/SqlConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/SqlConstants.java
new file mode 100644
index 00000000..85dcdbfa
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/SqlConstants.java
@@ -0,0 +1,29 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 数据库常量信息
+ *
+ * @author wangzongrun
+ */
+public class SqlConstants {
+ /**
+ * 数据库排序 升序
+ */
+ public static final String ASC = "ASC";
+
+ /**
+ * 数据库排序 降序
+ */
+ public static final String DESC = "DESC";
+
+ /**
+ * 数据库 开始时间字段名
+ */
+ public static final String FIELD_NAME_BEGIN_TIME = "beginTime";
+
+ /**
+ * 数据库 开始时间字段名
+ */
+ public static final String FIELD_NAME_END_TIME = "endTime";
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/SysErrorCodeConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/SysErrorCodeConstants.java
new file mode 100644
index 00000000..83da849c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/SysErrorCodeConstants.java
@@ -0,0 +1,146 @@
+package com.ruoyi.common.constant;
+
+
+import com.ruoyi.common.exception.ErrorCode;
+
+/**
+ * System 错误码枚举类
+ *
+ * system 系统,使用 1-002-000-000 段
+ */
+public interface SysErrorCodeConstants {
+
+ // ========== AUTH 模块 1002000000 ==========
+ ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确");
+ ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用");
+ ErrorCode AUTH_LOGIN_CAPTCHA_NOT_FOUND = new ErrorCode(1002000003, "验证码不存在");
+ ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确");
+ ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1002000005, "未绑定账号,需要进行绑定");
+ ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1002000006, "Token 已经过期");
+ ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1002000007, "手机号不存在");
+
+ // ========== 菜单模块 1002001000 ==========
+ ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1002001000, "已经存在该名字的菜单");
+ ErrorCode MENU_PARENT_NOT_EXISTS = new ErrorCode(1002001001, "父菜单不存在");
+ ErrorCode MENU_PARENT_ERROR = new ErrorCode(1002001002, "不能设置自己为父菜单");
+ ErrorCode MENU_NOT_EXISTS = new ErrorCode(1002001003, "菜单不存在");
+ ErrorCode MENU_EXISTS_CHILDREN = new ErrorCode(1002001004, "存在子菜单,无法删除");
+ ErrorCode MENU_PARENT_NOT_DIR_OR_MENU = new ErrorCode(1002001005, "父菜单的类型必须是目录或者菜单");
+
+ // ========== 角色模块 1002002000 ==========
+ ErrorCode ROLE_NOT_EXISTS = new ErrorCode(1002002000, "角色不存在");
+ ErrorCode ROLE_NAME_DUPLICATE = new ErrorCode(1002002001, "已经存在名为【{}】的角色");
+ ErrorCode ROLE_CODE_DUPLICATE = new ErrorCode(1002002002, "已经存在编码为【{}】的角色");
+ ErrorCode ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE = new ErrorCode(1002002003, "不能操作类型为系统内置的角色");
+ ErrorCode ROLE_IS_DISABLE = new ErrorCode(1002002004, "名字为【{}】的角色已被禁用");
+ ErrorCode ROLE_ADMIN_CODE_ERROR = new ErrorCode(1002002005, "编码【{}】不能使用");
+
+ // ========== 用户模块 1002003000 ==========
+ ErrorCode USER_USERNAME_EXISTS = new ErrorCode(1002003000, "用户账号已经存在");
+ ErrorCode USER_MOBILE_EXISTS = new ErrorCode(1002003001, "手机号已经存在");
+ ErrorCode USER_EMAIL_EXISTS = new ErrorCode(1002003002, "邮箱已经存在");
+ ErrorCode USER_NOT_EXISTS = new ErrorCode(1002003003, "用户不存在");
+ ErrorCode USER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1002003004, "导入用户数据不能为空!");
+ ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1002003005, "用户密码校验失败");
+ ErrorCode USER_IS_DISABLE = new ErrorCode(1002003006, "名字为【{}】的用户已被禁用");
+ ErrorCode USER_COUNT_MAX = new ErrorCode(1002003008, "创建用户失败,原因:超过租户最大租户配额({})!");
+
+ // ========== 部门模块 1002004000 ==========
+ ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1002004000, "已经存在该名字的部门");
+ ErrorCode DEPT_PARENT_NOT_EXITS = new ErrorCode(1002004001, "父级部门不存在");
+ ErrorCode DEPT_NOT_FOUND = new ErrorCode(1002004002, "当前部门不存在");
+ ErrorCode DEPT_EXITS_CHILDREN = new ErrorCode(1002004003, "存在子部门,无法删除");
+ ErrorCode DEPT_PARENT_ERROR = new ErrorCode(1002004004, "不能设置自己为父部门");
+ ErrorCode DEPT_EXISTS_USER = new ErrorCode(1002004005, "部门中存在员工,无法删除");
+ ErrorCode DEPT_NOT_ENABLE = new ErrorCode(1002004006, "部门不处于开启状态,不允许选择");
+ ErrorCode DEPT_PARENT_IS_CHILD = new ErrorCode(1002004007, "不能设置自己的子部门为父部门");
+
+ // ========== 岗位模块 1002005000 ==========
+ ErrorCode POST_NOT_FOUND = new ErrorCode(1002005000, "当前岗位不存在");
+ ErrorCode POST_NOT_ENABLE = new ErrorCode(1002005001, "岗位({}) 不处于开启状态,不允许选择");
+ ErrorCode POST_NAME_DUPLICATE = new ErrorCode(1002005002, "已经存在该名字的岗位");
+ ErrorCode POST_CODE_DUPLICATE = new ErrorCode(1002005003, "已经存在该标识的岗位");
+
+ // ========== 字典类型 1002006000 ==========
+ ErrorCode DICT_TYPE_NOT_EXISTS = new ErrorCode(1002006001, "当前字典类型不存在");
+ ErrorCode DICT_TYPE_NOT_ENABLE = new ErrorCode(1002006002, "字典类型不处于开启状态,不允许选择");
+ ErrorCode DICT_TYPE_NAME_DUPLICATE = new ErrorCode(1002006003, "已经存在该名字的字典类型");
+ ErrorCode DICT_TYPE_TYPE_DUPLICATE = new ErrorCode(1002006004, "已经存在该类型的字典类型");
+ ErrorCode DICT_TYPE_HAS_CHILDREN = new ErrorCode(1002006005, "无法删除,该字典类型还有字典数据");
+
+ // ========== 字典数据 1002007000 ==========
+ ErrorCode DICT_DATA_NOT_EXISTS = new ErrorCode(1002007001, "当前字典数据不存在");
+ ErrorCode DICT_DATA_NOT_ENABLE = new ErrorCode(1002007002, "字典数据({})不处于开启状态,不允许选择");
+ ErrorCode DICT_DATA_VALUE_DUPLICATE = new ErrorCode(1002007003, "已经存在该值的字典数据");
+
+ // ========== 通知公告 1002008000 ==========
+ ErrorCode NOTICE_NOT_FOUND = new ErrorCode(1002008001, "当前通知公告不存在");
+
+ // ========== 短信渠道 1002011000 ==========
+ ErrorCode SMS_CHANNEL_NOT_EXISTS = new ErrorCode(1002011000, "短信渠道不存在");
+ ErrorCode SMS_CHANNEL_DISABLE = new ErrorCode(1002011001, "短信渠道不处于开启状态,不允许选择");
+ ErrorCode SMS_CHANNEL_HAS_CHILDREN = new ErrorCode(1002011002, "无法删除,该短信渠道还有短信模板");
+
+ // ========== 短信模板 1002012000 ==========
+ ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1002012000, "短信模板不存在");
+ ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002012001, "已经存在编码为【{}】的短信模板");
+
+ // ========== 短信发送 1002013000 ==========
+ ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1002013000, "手机号不存在");
+ ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1002013001, "模板参数({})缺失");
+ ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1002013002, "短信模板不存在");
+
+ // ========== 短信验证码 1002014000 ==========
+ ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1002014000, "验证码不存在");
+ ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1002014001, "验证码已过期");
+ ErrorCode SMS_CODE_USED = new ErrorCode(1002014002, "验证码已使用");
+ ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1002014003, "验证码不正确");
+ ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1002014004, "超过每日短信发送数量");
+ ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1002014005, "短信发送过于频率");
+ ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1002014006, "手机号已被使用");
+ ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1002014007, "验证码未被使用");
+
+ // ========== 租户信息 1002015000 ==========
+ ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1002015000, "租户不存在");
+ ErrorCode TENANT_DISABLE = new ErrorCode(1002015001, "名字为【{}】的租户已被禁用");
+ ErrorCode TENANT_EXPIRE = new ErrorCode(1002015002, "名字为【{}】的租户已过期");
+ ErrorCode TENANT_CAN_NOT_UPDATE_SYSTEM = new ErrorCode(1002015003, "系统租户不能进行修改、删除等操作!");
+
+ // ========== 租户套餐 1002016000 ==========
+ ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1002016000, "租户套餐不存在");
+ ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1002016001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除");
+ ErrorCode TENANT_PACKAGE_DISABLE = new ErrorCode(1002016002, "名字为【{}】的租户套餐已被禁用");
+
+ // ========== 错误码模块 1002017000 ==========
+ ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002017000, "错误码不存在");
+ ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1002017001, "已经存在编码为【{}】的错误码");
+
+ // ========== 社交用户 1002018000 ==========
+ ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1002018000, "社交授权失败,原因是:{}");
+ ErrorCode SOCIAL_USER_UNBIND_NOT_SELF = new ErrorCode(1002018001, "社交解绑失败,非当前用户绑定");
+ ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1002018002, "社交授权失败,找不到对应的用户");
+
+ // ========== 系统敏感词 1002019000 =========
+ ErrorCode SENSITIVE_WORD_NOT_EXISTS = new ErrorCode(1002019000, "系统敏感词在所有标签中都不存在");
+ ErrorCode SENSITIVE_WORD_EXISTS = new ErrorCode(1002019001, "系统敏感词已在标签中存在");
+
+ // ========== OAuth2 客户端 1002020000 =========
+ ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1002020000, "OAuth2 客户端不存在");
+ ErrorCode OAUTH2_CLIENT_EXISTS = new ErrorCode(1002020001, "OAuth2 客户端编号已存在");
+ ErrorCode OAUTH2_CLIENT_DISABLE = new ErrorCode(1002020002, "OAuth2 客户端已禁用");
+ ErrorCode OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS = new ErrorCode(1002020003, "不支持该授权类型");
+ ErrorCode OAUTH2_CLIENT_SCOPE_OVER = new ErrorCode(1002020004, "授权范围过大");
+ ErrorCode OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH = new ErrorCode(1002020005, "无效 redirect_uri: {}");
+ ErrorCode OAUTH2_CLIENT_CLIENT_SECRET_ERROR = new ErrorCode(1002020006, "无效 client_secret: {}");
+
+ // ========== OAuth2 授权 1002021000 =========
+ ErrorCode OAUTH2_GRANT_CLIENT_ID_MISMATCH = new ErrorCode(1002021000, "client_id 不匹配");
+ ErrorCode OAUTH2_GRANT_REDIRECT_URI_MISMATCH = new ErrorCode(1002021001, "redirect_uri 不匹配");
+ ErrorCode OAUTH2_GRANT_STATE_MISMATCH = new ErrorCode(1002021002, "state 不匹配");
+ ErrorCode OAUTH2_GRANT_CODE_NOT_EXISTS = new ErrorCode(1002021003, "code 不存在");
+
+ // ========== OAuth2 授权 1002022000 =========
+ ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1002022000, "code 不存在");
+ ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1002022000, "code 已过期");
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/TreeConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/TreeConstants.java
new file mode 100644
index 00000000..3752848b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/TreeConstants.java
@@ -0,0 +1,29 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 树形通用常量信息
+ *
+ * @author wangzongrun
+ */
+public class TreeConstants {
+ /**
+ * 无父级的情况下,祖籍的值
+ */
+ public static final String ANCESTORS_ROOT_VALUE = "0";
+
+ /**
+ * 无父级的情况下,
+ */
+ public static final String PARENT_ROOT_VALUE = "0";
+
+ /**
+ * 无父级的情况下,层次默认值
+ */
+ public static final Integer LAYOUT_DEPTH_INIT_VALUE = 1;
+
+ /**
+ * 层次码分隔符
+ * .不能直接转义,添加转移字符
+ */
+ public static final String LAYOUT_CODE_SEPARATOR = ".";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
new file mode 100644
index 00000000..a936cd83
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
@@ -0,0 +1,78 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 用户常量信息
+ *
+ * @author ruoyi
+ */
+public class UserConstants
+{
+ /**
+ * 平台内系统用户的唯一标志
+ */
+ public static final String SYS_USER = "SYS_USER";
+
+ /** 正常状态 */
+ public static final String NORMAL = "0";
+
+ /** 异常状态 */
+ public static final String EXCEPTION = "1";
+
+ /** 用户封禁状态 */
+ public static final String USER_DISABLE = "1";
+
+ /** 角色封禁状态 */
+ public static final String ROLE_DISABLE = "1";
+
+ /** 部门正常状态 */
+ public static final String DEPT_NORMAL = "0";
+
+ /** 部门停用状态 */
+ public static final String DEPT_DISABLE = "1";
+
+ /** 字典正常状态 */
+ public static final String DICT_NORMAL = "0";
+
+ /** 是否为系统默认(是) */
+ public static final String YES = "Y";
+
+ /** 是否菜单外链(是) */
+ public static final String YES_FRAME = "0";
+
+ /** 是否菜单外链(否) */
+ public static final String NO_FRAME = "1";
+
+ /** 菜单类型(目录) */
+ public static final String TYPE_DIR = "M";
+
+ /** 菜单类型(菜单) */
+ public static final String TYPE_MENU = "C";
+
+ /** 菜单类型(按钮) */
+ public static final String TYPE_BUTTON = "F";
+
+ /** Layout组件标识 */
+ public final static String LAYOUT = "Layout";
+
+ /** ParentView组件标识 */
+ public final static String PARENT_VIEW = "ParentView";
+
+ /** InnerLink组件标识 */
+ public final static String INNER_LINK = "InnerLink";
+
+ /** 校验返回结果码 */
+ public final static String UNIQUE = "0";
+ public final static String NOT_UNIQUE = "1";
+
+ /**
+ * 用户名长度限制
+ */
+ public static final int USERNAME_MIN_LENGTH = 2;
+ public static final int USERNAME_MAX_LENGTH = 20;
+
+ /**
+ * 密码长度限制
+ */
+ public static final int PASSWORD_MIN_LENGTH = 5;
+ public static final int PASSWORD_MAX_LENGTH = 20;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/convert/DictConvert.java b/ruoyi-common/src/main/java/com/ruoyi/common/convert/DictConvert.java
new file mode 100644
index 00000000..cf40ccdd
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/convert/DictConvert.java
@@ -0,0 +1,71 @@
+package com.ruoyi.common.convert;
+
+import cn.hutool.core.convert.Convert;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.data.ReadCellData;
+import com.alibaba.excel.metadata.data.WriteCellData;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+import com.ruoyi.common.annotation.DictFormat;
+import com.ruoyi.common.utils.DictUtils;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Excel 数据字典转换器
+ *
+ * @author 芋道源码
+ */
+@Slf4j
+public class DictConvert implements Converter {
+
+ @Override
+ public Class> supportJavaTypeKey() {
+ throw new UnsupportedOperationException("暂不支持,也不需要");
+ }
+
+ @Override
+ public CellDataTypeEnum supportExcelTypeKey() {
+ throw new UnsupportedOperationException("暂不支持,也不需要");
+ }
+
+ @Override
+ public Object convertToJavaData(ReadCellData readCellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
+ // 使用字典解析
+ String type = getType(contentProperty);
+ String label = readCellData.getStringValue();
+ String value = DictUtils.getDictValue(type, label);
+ if (value == null) {
+ log.error("[convertToJavaData][type({}) 解析不掉 label({})]", type, label);
+ return null;
+ }
+ // 将 String 的 value 转换成对应的属性
+ Class> fieldClazz = contentProperty.getField().getType();
+ return Convert.convert(fieldClazz, value);
+ }
+
+ @Override
+ public WriteCellData convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
+ // 空时,返回空
+ if (object == null) {
+ return new WriteCellData<>("");
+ }
+
+ // 使用字典格式化
+ String type = getType(contentProperty);
+ String value = String.valueOf(object);
+ String label = DictUtils.getDictLabel(type, value);
+ if (label == null) {
+ log.error("[convertToExcelData][type({}) 转换不了 label({})]", type, value);
+ return new WriteCellData<>("");
+ }
+ // 生成 Excel 小表格
+ return new WriteCellData<>(label);
+ }
+
+ private static String getType(ExcelContentProperty contentProperty) {
+ return contentProperty.getField().getAnnotation(DictFormat.class).value();
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/convert/JsonConvert.java b/ruoyi-common/src/main/java/com/ruoyi/common/convert/JsonConvert.java
new file mode 100644
index 00000000..5b512b3b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/convert/JsonConvert.java
@@ -0,0 +1,33 @@
+package com.ruoyi.common.convert;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.data.WriteCellData;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+import com.ruoyi.common.utils.JsonUtils;
+
+/**
+ * Excel Json 转换器
+ *
+ * @author 芋道源码
+ */
+public class JsonConvert implements Converter {
+
+ @Override
+ public Class> supportJavaTypeKey() {
+ throw new UnsupportedOperationException("暂不支持,也不需要");
+ }
+
+ @Override
+ public CellDataTypeEnum supportExcelTypeKey() {
+ throw new UnsupportedOperationException("暂不支持,也不需要");
+ }
+
+ @Override
+ public WriteCellData convertToExcelData(Object value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
+ // 生成 Excel 小表格
+ return new WriteCellData<>(JsonUtils.toJsonString(value));
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
new file mode 100644
index 00000000..0645d64b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
@@ -0,0 +1,236 @@
+package com.ruoyi.common.core.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.metadata.OrderItem;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.ruoyi.common.constant.HttpStatus;
+import com.ruoyi.common.constant.SqlConstants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.page.PageDomain;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.page.TableSupport;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.PageUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.sql.SqlUtil;
+import org.apache.poi.ss.formula.functions.T;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+
+import java.beans.PropertyEditorSupport;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * web层通用数据处理
+ *
+ * @author ruoyi
+ */
+public class BaseController {
+ protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ /**
+ * 将前台传递过来的日期格式的字符串,自动转化为Date类型
+ */
+ @InitBinder
+ public void initBinder(WebDataBinder binder) {
+ // Date 类型转换
+ binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
+ @Override
+ public void setAsText(String text) {
+ setValue(DateUtils.parseDate(text));
+ }
+ });
+ }
+
+ /**
+ * 设置请求分页数据
+ */
+ protected void startPage() {
+ PageUtils.startPage();
+ }
+ protected void startPage(String orderBy) {
+ PageUtils.startPage(orderBy);
+ }
+ /**
+ * 设置mybatis-plus请求分页数据
+ */
+ protected Page getPage(OrderItem... sorts) {
+ Page page = new Page<>();
+ PageDomain pageDomain = TableSupport.buildPageRequest();
+ Integer pageNum = pageDomain.getPageNum();
+ Integer pageSize = pageDomain.getPageSize();
+ String orderColumn = pageDomain.getOrderByColumn();
+ String isAsc = pageDomain.getIsAsc();
+
+ if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) {
+ page.setCurrent(pageNum);
+ page.setSize(pageSize);
+ page.setOptimizeCountSql(false);
+ page.setMaxLimit(500L);
+ }
+ //排序
+ if (StringUtils.isNotBlank(orderColumn)) {
+ if (SqlConstants.ASC.equalsIgnoreCase(isAsc)) {
+ page.addOrder(OrderItem.asc(orderColumn));
+ } else {
+ page.addOrder(OrderItem.desc(orderColumn));
+ }
+ }
+ if (sorts.length >0) {
+ page.addOrder(sorts);
+ }
+ return page;
+ }
+
+ /**
+ * mybatis-plus响应请求分页数据
+ *
+ * @param page
+ */
+ protected TableDataInfo getDataTable(IPage> page) {
+ TableDataInfo rspData = new TableDataInfo();
+ rspData.setCode(HttpStatus.SUCCESS);
+ rspData.setMsg("查询成功");
+ rspData.setRows(page.getRecords());
+ rspData.setTotal(page.getTotal());
+ rspData.setPageNum(page.getCurrent());
+ rspData.setPageSize(page.getSize());
+ rspData.setTotalPageNum(page.getPages());
+ return rspData;
+ }
+
+ /**
+ * 设置请求排序数据
+ */
+ protected void startOrderBy() {
+ PageDomain pageDomain = TableSupport.buildPageRequest();
+ if (StringUtils.isNotEmpty(pageDomain.getOrderBy())) {
+ String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+ PageHelper.orderBy(orderBy);
+ }
+ }
+
+ /**
+ * 清理分页的线程变量
+ */
+ protected void clearPage() {
+ PageUtils.clearPage();
+ }
+
+ /**
+ * 响应请求分页数据
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ protected TableDataInfo getDataTable(List> list) {
+ TableDataInfo rspData = new TableDataInfo();
+ rspData.setCode(HttpStatus.SUCCESS);
+ rspData.setMsg("查询成功");
+ rspData.setRows(list);
+ rspData.setTotal(new PageInfo(list).getTotal());
+ return rspData;
+ }
+
+ /**
+ * 返回成功
+ */
+ public AjaxResult success() {
+ return AjaxResult.success();
+ }
+
+ /**
+ * 返回失败消息
+ */
+ public AjaxResult error() {
+ return AjaxResult.error();
+ }
+
+ /**
+ * 返回成功消息
+ */
+ public AjaxResult success(String message) {
+ return AjaxResult.success(message);
+ }
+
+ /**
+ * 返回成功消息
+ */
+ public AjaxResult success(Object data) {
+ return AjaxResult.success(data);
+ }
+
+ /**
+ * 返回失败消息
+ */
+ public AjaxResult error(String message) {
+ return AjaxResult.error(message);
+ }
+
+ /**
+ * 返回警告消息
+ */
+ public AjaxResult warn(String message) {
+ return AjaxResult.warn(message);
+ }
+
+ /**
+ * 响应返回结果
+ *
+ * @param rows 影响行数
+ * @return 操作结果
+ */
+ protected AjaxResult toAjax(int rows) {
+ return rows > 0 ? AjaxResult.success() : AjaxResult.error();
+ }
+
+ /**
+ * 响应返回结果
+ *
+ * @param result 结果
+ * @return 操作结果
+ */
+ protected AjaxResult toAjax(boolean result) {
+ return result ? success() : error();
+ }
+
+ /**
+ * 页面跳转
+ */
+ public String redirect(String url) {
+ return StringUtils.format("redirect:{}", url);
+ }
+
+ /**
+ * 获取用户缓存信息
+ */
+ public LoginUser getLoginUser() {
+ return SecurityUtils.getLoginUser();
+ }
+
+ /**
+ * 获取登录用户id
+ */
+ public Long getUserId() {
+ return getLoginUser().getUserId();
+ }
+
+ /**
+ * 获取登录部门id
+ */
+ public Long getDeptId() {
+ return getLoginUser().getDeptId();
+ }
+
+ /**
+ * 获取登录用户名
+ */
+ public String getUsername() {
+ return getLoginUser().getUsername();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java
new file mode 100644
index 00000000..3dc5afc9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java
@@ -0,0 +1,179 @@
+package com.ruoyi.common.core.domain;
+
+import com.ruoyi.common.constant.HttpStatus;
+import com.ruoyi.common.utils.StringUtils;
+
+import java.util.HashMap;
+
+/**
+ * 操作消息提醒
+ *
+ * @author ruoyi
+ */
+public class AjaxResult extends HashMap {
+ 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";
+
+ /**
+ * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
+ */
+ public AjaxResult() {
+ }
+
+ /**
+ * 初始化一个新创建的 AjaxResult 对象
+ *
+ * @param code 状态码
+ * @param msg 返回内容
+ */
+ public AjaxResult(int code, String msg) {
+ super.put(CODE_TAG, code);
+ super.put(MSG_TAG, msg);
+ }
+
+ /**
+ * 初始化一个新创建的 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);
+ }
+
+ /**
+ * 方便链式调用
+ *
+ * @param key 键
+ * @param value 值
+ * @return 数据对象
+ */
+ @Override
+ public AjaxResult put(String key, Object value) {
+ super.put(key, value);
+ return this;
+ }
+ public boolean isSuccess(){
+ return super.get("code") != null && "200".equals(super.get("code").toString());
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
new file mode 100644
index 00000000..9ae0db89
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
@@ -0,0 +1,124 @@
+package com.ruoyi.common.core.domain;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * Entity基类
+ *
+ * @author ruoyi
+ */
+public class BaseEntity implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 搜索值 */
+ @TableField(exist = false)
+ private String searchValue;
+
+ /** 创建者 */
+ @TableField(fill = FieldFill.INSERT)
+ private String createBy;
+
+ /** 创建时间 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @TableField(fill = FieldFill.INSERT)
+ private Date createTime;
+
+ /** 更新者 */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private String updateBy;
+
+ /** 更新时间 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Date updateTime;
+
+ /** 备注 */
+ @TableField(exist = false)
+ private String remark;
+
+ /** 请求参数 */
+ @TableField(exist = false)
+ private Map 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 getParams()
+ {
+ if (params == null)
+ {
+ params = new HashMap<>();
+ }
+ return params;
+ }
+
+ public void setParams(Map params)
+ {
+ this.params = params;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/DictTreeEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/DictTreeEntity.java
new file mode 100644
index 00000000..16f21c82
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/DictTreeEntity.java
@@ -0,0 +1,118 @@
+package com.ruoyi.common.core.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.ruoyi.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Tree基类
+ *
+ * @author ruoyi
+ */
+@Data
+public class DictTreeEntity {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键
+ */
+ @Excel(name = "主键")
+ @TableId(value = "ID", type = IdType.ASSIGN_ID)
+ private String id;
+
+ /**
+ * 名称
+ */
+ @Excel(name = "名称")
+ private String label;
+
+ /**
+ * 编码
+ */
+ @Excel(name = "编码")
+ private String code;
+
+ /**
+ * 备注
+ */
+ @Excel(name = "备注")
+ private String remark;
+
+ /**
+ * 父节点ID
+ */
+ private String pid;
+
+ /**
+ * 显示顺序
+ */
+ private Integer orderNum;
+
+ /**
+ * 层次码
+ * 说明:
+ * 顶级层次码为0
+ * 非顶级使用4位数字显示,起始位1000
+ */
+ private String levelCode;
+
+ /**
+ * 层次
+ * 说明:
+ * 结合层次码,计算树形结构的的层次
+ */
+ private Integer levelDepth;
+
+ /**
+ * 是否叶子节点
+ *
+ * 说明:
+ * 新建节点,默认为末级节点,并更新父节点为非末级节点
+ */
+ private String isLeaf;
+
+ /**
+ * 创建者
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date createTime;
+
+ /**
+ * 更新者
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private String updateBy;
+
+ /**
+ * 更新时间
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date updateTime;
+
+ /**
+ * 删除标志
+ */
+ @TableLogic
+ private String delFlag;
+
+ /**
+ * 子节点
+ */
+ @TableField(exist = false)
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ private List> children = new ArrayList<>();
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
new file mode 100644
index 00000000..a1290d99
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
@@ -0,0 +1,102 @@
+package com.ruoyi.common.core.domain;
+
+import com.ruoyi.common.constant.HttpStatus;
+
+import java.io.Serializable;
+
+/**
+ * 响应信息主体
+ *
+ * @author ruoyi
+ */
+public class R implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 成功
+ */
+ public static final int SUCCESS = HttpStatus.SUCCESS;
+
+ /**
+ * 失败
+ */
+ public static final int FAIL = HttpStatus.ERROR;
+
+ private int code;
+
+ private String msg;
+
+ private T data;
+
+ public static R ok() {
+ return restResult(null, SUCCESS, "操作成功");
+ }
+
+ public static R ok(T data) {
+ return restResult(data, SUCCESS, "操作成功");
+ }
+
+ public static R ok(T data, String msg) {
+ return restResult(data, SUCCESS, msg);
+ }
+
+ public static R fail() {
+ return restResult(null, FAIL, "操作失败");
+ }
+
+ public static R fail(String msg) {
+ return restResult(null, FAIL, msg);
+ }
+
+ public static R fail(T data) {
+ return restResult(data, FAIL, "操作失败");
+ }
+
+ public static R fail(T data, String msg) {
+ return restResult(data, FAIL, msg);
+ }
+
+ public static R fail(int code, String msg) {
+ return restResult(null, code, msg);
+ }
+
+ private static R restResult(T data, int code, String msg) {
+ R apiResult = new R<>();
+ apiResult.setCode(code);
+ apiResult.setData(data);
+ apiResult.setMsg(msg);
+ return apiResult;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public void setMsg(String msg) {
+ this.msg = msg;
+ }
+
+ public T getData() {
+ return data;
+ }
+
+ public void setData(T data) {
+ this.data = data;
+ }
+
+ public static Boolean isError(R ret) {
+ return !isSuccess(ret);
+ }
+
+ public static Boolean isSuccess(R ret) {
+ return R.SUCCESS == ret.getCode();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TenantBaseDO.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TenantBaseDO.java
new file mode 100644
index 00000000..f5609b0a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TenantBaseDO.java
@@ -0,0 +1,20 @@
+package com.ruoyi.common.core.domain;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 拓展多租户的 BaseDO 基类
+ *
+ * @author 芋道源码
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public abstract class TenantBaseDO extends BaseEntity {
+
+ /**
+ * 多租户编号
+ */
+ private Long tenantId;
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java
new file mode 100644
index 00000000..a180a18c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java
@@ -0,0 +1,79 @@
+package com.ruoyi.common.core.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tree基类
+ *
+ * @author ruoyi
+ */
+public class TreeEntity extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 父菜单名称 */
+ private String parentName;
+
+ /** 父菜单ID */
+ private Long parentId;
+
+ /** 显示顺序 */
+ private Integer orderNum;
+
+ /** 祖级列表 */
+ private String ancestors;
+
+ /** 子部门 */
+ private List> children = new ArrayList<>();
+
+ public String getParentName()
+ {
+ return parentName;
+ }
+
+ public void setParentName(String parentName)
+ {
+ this.parentName = parentName;
+ }
+
+ public Long getParentId()
+ {
+ return parentId;
+ }
+
+ public void setParentId(Long parentId)
+ {
+ this.parentId = parentId;
+ }
+
+ public Integer getOrderNum()
+ {
+ return orderNum;
+ }
+
+ public void setOrderNum(Integer orderNum)
+ {
+ this.orderNum = orderNum;
+ }
+
+ public String getAncestors()
+ {
+ return ancestors;
+ }
+
+ public void setAncestors(String ancestors)
+ {
+ this.ancestors = ancestors;
+ }
+
+ public List> getChildren()
+ {
+ return children;
+ }
+
+ public void setChildren(List> children)
+ {
+ this.children = children;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java
new file mode 100644
index 00000000..bd835db9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java
@@ -0,0 +1,77 @@
+package com.ruoyi.common.core.domain;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.stream.Collectors;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.core.domain.entity.SysMenu;
+
+/**
+ * Treeselect树结构实体类
+ *
+ * @author ruoyi
+ */
+public class TreeSelect implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 节点ID */
+ private Long id;
+
+ /** 节点名称 */
+ private String label;
+
+ /** 子节点 */
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ private List children;
+
+ public TreeSelect()
+ {
+
+ }
+
+ public TreeSelect(SysDept dept)
+ {
+ this.id = dept.getDeptId();
+ this.label = dept.getDeptName();
+ this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
+ }
+
+ public TreeSelect(SysMenu menu)
+ {
+ this.id = menu.getMenuId();
+ this.label = menu.getMenuName();
+ this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
+ }
+
+ public Long getId()
+ {
+ return id;
+ }
+
+ public void setId(Long id)
+ {
+ this.id = id;
+ }
+
+ public String getLabel()
+ {
+ return label;
+ }
+
+ public void setLabel(String label)
+ {
+ this.label = label;
+ }
+
+ public List getChildren()
+ {
+ return children;
+ }
+
+ public void setChildren(List children)
+ {
+ this.children = children;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java
new file mode 100644
index 00000000..16ffd7f8
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java
@@ -0,0 +1,221 @@
+package com.ruoyi.common.core.domain.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 部门表 sys_dept
+ *
+ * @author ruoyi
+ */
+public class SysDept extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 部门ID */
+ @TableId(type = IdType.AUTO)
+ private Long deptId;
+
+ /** 父部门ID */
+ private Long parentId;
+
+ /** 祖级列表 */
+ private String ancestors;
+
+ /** 部门名称 */
+ private String deptName;
+
+ /** 显示顺序 */
+ private Integer orderNum;
+
+ /** 负责人 */
+ private String leader;
+
+ /** 联系电话 */
+ private String phone;
+
+ /** 邮箱 */
+ private String email;
+
+ /** 部门状态:0正常,1停用 */
+ private String status;
+
+ /** 删除标志(0代表存在 2代表删除) */
+ private String delFlag;
+
+ /** 父部门名称 */
+ @TableField(exist = false)
+ private String parentName;
+ /**
+ * 多租户编号
+ */
+ private Long tenantId;
+ /** 子部门 */
+ @TableField(exist = false)
+ private List children = new ArrayList();
+
+ public Long getDeptId()
+ {
+ return deptId;
+ }
+
+ public void setDeptId(Long deptId)
+ {
+ this.deptId = deptId;
+ }
+
+ public Long getParentId()
+ {
+ return parentId;
+ }
+
+ public void setParentId(Long parentId)
+ {
+ this.parentId = parentId;
+ }
+
+ public String getAncestors()
+ {
+ return ancestors;
+ }
+
+ public void setAncestors(String ancestors)
+ {
+ this.ancestors = ancestors;
+ }
+
+ @NotBlank(message = "部门名称不能为空")
+ @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
+ public String getDeptName()
+ {
+ return deptName;
+ }
+
+ public void setDeptName(String deptName)
+ {
+ this.deptName = deptName;
+ }
+
+ @NotNull(message = "显示顺序不能为空")
+ public Integer getOrderNum()
+ {
+ return orderNum;
+ }
+
+ public void setOrderNum(Integer orderNum)
+ {
+ this.orderNum = orderNum;
+ }
+
+ public String getLeader()
+ {
+ return leader;
+ }
+
+ public void setLeader(String leader)
+ {
+ this.leader = leader;
+ }
+
+ @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
+ public String getPhone()
+ {
+ return phone;
+ }
+
+ public void setPhone(String phone)
+ {
+ this.phone = phone;
+ }
+
+ @Email(message = "邮箱格式不正确")
+ @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
+ public String getEmail()
+ {
+ return email;
+ }
+
+ public void setEmail(String email)
+ {
+ this.email = email;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getDelFlag()
+ {
+ return delFlag;
+ }
+
+ public void setDelFlag(String delFlag)
+ {
+ this.delFlag = delFlag;
+ }
+
+ public String getParentName()
+ {
+ return parentName;
+ }
+
+ public void setParentName(String parentName)
+ {
+ this.parentName = parentName;
+ }
+
+ public List getChildren()
+ {
+ return children;
+ }
+
+ public void setChildren(List children)
+ {
+ this.children = children;
+ }
+
+ public Long getTenantId() {
+ return this.tenantId;
+ }
+
+ public void setTenantId(Long tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("deptId", getDeptId())
+ .append("parentId", getParentId())
+ .append("ancestors", getAncestors())
+ .append("deptName", getDeptName())
+ .append("orderNum", getOrderNum())
+ .append("leader", getLeader())
+ .append("phone", getPhone())
+ .append("email", getEmail())
+ .append("status", getStatus())
+ .append("delFlag", getDelFlag())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java
new file mode 100644
index 00000000..0d88bbcc
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java
@@ -0,0 +1,180 @@
+package com.ruoyi.common.core.domain.entity;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 字典数据表 sys_dict_data
+ *
+ * @author ruoyi
+ */
+public class SysDictData extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 字典编码 */
+ @Excel(name = "字典编码", cellType = ColumnType.NUMERIC)
+ @TableId(type = IdType.AUTO)
+ private Long dictCode;
+
+ /** 字典排序 */
+ @Excel(name = "字典排序", cellType = ColumnType.NUMERIC)
+ private Long dictSort;
+
+ /** 字典标签 */
+ @Excel(name = "字典标签")
+ private String dictLabel;
+
+ /** 字典键值 */
+ @Excel(name = "字典键值")
+ private String dictValue;
+
+ /** 字典类型 */
+ @Excel(name = "字典类型")
+ private String dictType;
+
+ /** 样式属性(其他样式扩展) */
+ private String cssClass;
+
+ /** 表格字典样式 */
+ private String listClass;
+
+ /** 是否默认(Y是 N否) */
+ @Excel(name = "是否默认", readConverterExp = "Y=是,N=否")
+ private String isDefault;
+
+ /** 状态(0正常 1停用) */
+ @Excel(name = "状态", readConverterExp = "0=正常,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/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java
new file mode 100644
index 00000000..4c8b7424
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java
@@ -0,0 +1,100 @@
+package com.ruoyi.common.core.domain.entity;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 字典类型表 sys_dict_type
+ *
+ * @author ruoyi
+ */
+public class SysDictType extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 字典主键 */
+ @Excel(name = "字典主键", cellType = ColumnType.NUMERIC)
+ @TableId(type = IdType.AUTO)
+ private Long dictId;
+
+ /** 字典名称 */
+ @Excel(name = "字典名称")
+ private String dictName;
+
+ /** 字典类型 */
+ @Excel(name = "字典类型")
+ private String dictType;
+
+ /** 状态(0正常 1停用) */
+ @Excel(name = "状态", readConverterExp = "0=正常,1=停用")
+ private String status;
+
+ public Long getDictId()
+ {
+ return dictId;
+ }
+
+ public void setDictId(Long dictId)
+ {
+ this.dictId = dictId;
+ }
+
+ @NotBlank(message = "字典名称不能为空")
+ @Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符")
+ public String getDictName()
+ {
+ return dictName;
+ }
+
+ public void setDictName(String dictName)
+ {
+ this.dictName = dictName;
+ }
+
+ @NotBlank(message = "字典类型不能为空")
+ @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
+ @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
+ public String getDictType()
+ {
+ return dictType;
+ }
+
+ public void setDictType(String dictType)
+ {
+ this.dictType = dictType;
+ }
+
+ 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("dictId", getDictId())
+ .append("dictName", getDictName())
+ .append("dictType", getDictType())
+ .append("status", getStatus())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
new file mode 100644
index 00000000..44eae08f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
@@ -0,0 +1,252 @@
+package com.ruoyi.common.core.domain.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.ruoyi.common.core.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 菜单权限表 sys_menu
+ *
+ * @author ruoyi
+ */
+public class SysMenu extends BaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 菜单ID
+ */
+ @TableId(type = IdType.AUTO)
+ private Long menuId;
+
+ /**
+ * 菜单名称
+ */
+ private String menuName;
+
+ /**
+ * 父菜单ID
+ */
+ private Long parentId;
+
+ /**
+ * 显示顺序
+ */
+ private Integer orderNum;
+
+ /**
+ * 路由地址
+ */
+ private String path;
+
+ /**
+ * 组件路径
+ */
+ private String component;
+
+ /**
+ * 路由参数
+ */
+ private String query;
+
+ /**
+ * 是否为外链(0是 1否)
+ */
+ private String isFrame;
+
+ /**
+ * 是否缓存(0缓存 1不缓存)
+ */
+ private String isCache;
+
+ /**
+ * 类型(M目录 C菜单 F按钮)
+ */
+ private String menuType;
+
+ /**
+ * 显示状态(0显示 1隐藏)
+ */
+ private String visible;
+
+ /**
+ * 菜单状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 权限字符串
+ */
+ private String perms;
+
+ /**
+ * 菜单图标
+ */
+ private String icon;
+
+ /**
+ * 子菜单
+ */
+ @TableField(exist = false)
+ private List children = new ArrayList();
+
+ public Long getMenuId() {
+ return menuId;
+ }
+
+ public void setMenuId(Long menuId) {
+ this.menuId = menuId;
+ }
+
+ @NotBlank(message = "菜单名称不能为空")
+ @Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符")
+ public String getMenuName() {
+ return menuName;
+ }
+
+ public void setMenuName(String menuName) {
+ this.menuName = menuName;
+ }
+
+
+ public Long getParentId() {
+ return parentId;
+ }
+
+ public void setParentId(Long parentId) {
+ this.parentId = parentId;
+ }
+
+ @NotNull(message = "显示顺序不能为空")
+ public Integer getOrderNum() {
+ return orderNum;
+ }
+
+ public void setOrderNum(Integer orderNum) {
+ this.orderNum = orderNum;
+ }
+
+ @Size(min = 0, max = 200, message = "路由地址不能超过200个字符")
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ @Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
+ public String getComponent() {
+ return component;
+ }
+
+ public void setComponent(String component) {
+ this.component = component;
+ }
+
+ public String getQuery() {
+ return query;
+ }
+
+ public void setQuery(String query) {
+ this.query = query;
+ }
+
+ public String getIsFrame() {
+ return isFrame;
+ }
+
+ public void setIsFrame(String isFrame) {
+ this.isFrame = isFrame;
+ }
+
+ public String getIsCache() {
+ return isCache;
+ }
+
+ public void setIsCache(String isCache) {
+ this.isCache = isCache;
+ }
+
+ @NotBlank(message = "菜单类型不能为空")
+ public String getMenuType() {
+ return menuType;
+ }
+
+ public void setMenuType(String menuType) {
+ this.menuType = menuType;
+ }
+
+ public String getVisible() {
+ return visible;
+ }
+
+ public void setVisible(String visible) {
+ this.visible = visible;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ @Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符")
+ public String getPerms() {
+ return perms;
+ }
+
+ public void setPerms(String perms) {
+ this.perms = perms;
+ }
+
+ public String getIcon() {
+ return icon;
+ }
+
+ public void setIcon(String icon) {
+ this.icon = icon;
+ }
+
+ public List getChildren() {
+ return children;
+ }
+
+ public void setChildren(List children) {
+ this.children = children;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+ .append("menuId", getMenuId())
+ .append("menuName", getMenuName())
+ .append("parentId", getParentId())
+ .append("orderNum", getOrderNum())
+ .append("path", getPath())
+ .append("component", getComponent())
+ .append("isFrame", getIsFrame())
+ .append("IsCache", getIsCache())
+ .append("menuType", getMenuType())
+ .append("visible", getVisible())
+ .append("status ", getStatus())
+ .append("perms", getPerms())
+ .append("icon", getIcon())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java
new file mode 100644
index 00000000..bf07e8d1
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java
@@ -0,0 +1,261 @@
+package com.ruoyi.common.core.domain.entity;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+import java.util.Set;
+
+/**
+ * 角色表 sys_role
+ *
+ * @author ruoyi
+ */
+public class SysRole extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 角色ID */
+ @Excel(name = "角色序号", cellType = ColumnType.NUMERIC)
+ @TableId(type = IdType.AUTO)
+ private Long roleId;
+
+ /** 角色名称 */
+ @Excel(name = "角色名称")
+ private String roleName;
+
+ /** 角色权限 */
+ @Excel(name = "角色权限")
+ private String roleKey;
+
+ /** 角色排序 */
+ @Excel(name = "角色排序")
+ private String roleSort;
+
+ /** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */
+ @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
+ private String dataScope;
+
+ /** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */
+ private boolean menuCheckStrictly;
+
+ /** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */
+ private boolean deptCheckStrictly;
+
+ /** 角色状态(0正常 1停用) */
+ @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
+ private String status;
+
+ /** 删除标志(0代表存在 2代表删除) */
+ private String delFlag;
+
+ /** 用户是否存在此角色标识 默认不存在 */
+ @TableField(exist = false)
+ private boolean flag = false;
+
+ /** 菜单组 */
+ @TableField(exist = false)
+ private Long[] menuIds;
+
+ /** 部门组(数据权限) */
+ @TableField(exist = false)
+ private Long[] deptIds;
+
+ /** 角色菜单权限 */
+ @TableField(exist = false)
+ private Set permissions;
+ /**
+ * 多租户编号
+ */
+ private Long tenantId;
+ public SysRole()
+ {
+
+ }
+
+ public SysRole(Long roleId)
+ {
+ this.roleId = roleId;
+ }
+
+ public Long getRoleId()
+ {
+ return roleId;
+ }
+
+ public void setRoleId(Long roleId)
+ {
+ this.roleId = roleId;
+ }
+
+ public boolean isAdmin()
+ {
+ return isAdmin(this.roleId);
+ }
+
+ public static boolean isAdmin(Long roleId)
+ {
+ return roleId != null && 1L == roleId;
+ }
+
+ @NotBlank(message = "角色名称不能为空")
+ @Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符")
+ public String getRoleName()
+ {
+ return roleName;
+ }
+
+ public void setRoleName(String roleName)
+ {
+ this.roleName = roleName;
+ }
+
+ @NotBlank(message = "权限字符不能为空")
+ @Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符")
+ public String getRoleKey()
+ {
+ return roleKey;
+ }
+
+ public void setRoleKey(String roleKey)
+ {
+ this.roleKey = roleKey;
+ }
+
+ @NotBlank(message = "显示顺序不能为空")
+ public String getRoleSort()
+ {
+ return roleSort;
+ }
+
+ public void setRoleSort(String roleSort)
+ {
+ this.roleSort = roleSort;
+ }
+
+ public String getDataScope()
+ {
+ return dataScope;
+ }
+
+ public void setDataScope(String dataScope)
+ {
+ this.dataScope = dataScope;
+ }
+
+ public boolean isMenuCheckStrictly()
+ {
+ return menuCheckStrictly;
+ }
+
+ public void setMenuCheckStrictly(boolean menuCheckStrictly)
+ {
+ this.menuCheckStrictly = menuCheckStrictly;
+ }
+
+ public boolean isDeptCheckStrictly()
+ {
+ return deptCheckStrictly;
+ }
+
+ public void setDeptCheckStrictly(boolean deptCheckStrictly)
+ {
+ this.deptCheckStrictly = deptCheckStrictly;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getDelFlag()
+ {
+ return delFlag;
+ }
+
+ public void setDelFlag(String delFlag)
+ {
+ this.delFlag = delFlag;
+ }
+
+ public boolean isFlag()
+ {
+ return flag;
+ }
+
+ public void setFlag(boolean flag)
+ {
+ this.flag = flag;
+ }
+
+ public Long[] getMenuIds()
+ {
+ return menuIds;
+ }
+
+ public void setMenuIds(Long[] menuIds)
+ {
+ this.menuIds = menuIds;
+ }
+
+ public Long[] getDeptIds()
+ {
+ return deptIds;
+ }
+
+ public void setDeptIds(Long[] deptIds)
+ {
+ this.deptIds = deptIds;
+ }
+
+ public Set getPermissions()
+ {
+ return permissions;
+ }
+
+ public void setPermissions(Set permissions)
+ {
+ this.permissions = permissions;
+ }
+
+ public Long getTenantId() {
+ return this.tenantId;
+ }
+
+ public void setTenantId(Long tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("roleId", getRoleId())
+ .append("roleName", getRoleName())
+ .append("roleKey", getRoleKey())
+ .append("roleSort", getRoleSort())
+ .append("dataScope", getDataScope())
+ .append("menuCheckStrictly", isMenuCheckStrictly())
+ .append("deptCheckStrictly", isDeptCheckStrictly())
+ .append("status", getStatus())
+ .append("delFlag", getDelFlag())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
new file mode 100644
index 00000000..de21286e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
@@ -0,0 +1,345 @@
+package com.ruoyi.common.core.domain.entity;
+
+import java.util.Date;
+import java.util.List;
+import javax.validation.constraints.*;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.annotation.Excel.Type;
+import com.ruoyi.common.annotation.Excels;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.xss.Xss;
+
+/**
+ * 用户对象 sys_user
+ *
+ * @author ruoyi
+ */
+public class SysUser extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 用户ID */
+ @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
+ @TableId(type = IdType.AUTO)
+ private Long userId;
+
+ /** 部门ID */
+ @Excel(name = "部门编号", type = Type.IMPORT)
+ private Long deptId;
+
+ /** 用户账号 */
+ @Excel(name = "登录名称")
+ private String userName;
+
+ /** 用户昵称 */
+ @Excel(name = "用户名称")
+ private String nickName;
+
+ /** 用户邮箱 */
+ @Excel(name = "用户邮箱")
+ private String email;
+
+ /** 手机号码 */
+ @Excel(name = "手机号码")
+ private String phonenumber;
+
+ /** 用户性别 */
+ @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
+ private String sex;
+
+ /** 用户头像 */
+ private String avatar;
+
+ /** 密码 */
+ private String password;
+
+ /** 帐号状态(0正常 1停用) */
+ @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
+ private String status;
+
+ /** 删除标志(0代表存在 2代表删除) */
+ private String delFlag;
+
+ /** 最后登录IP */
+ @Excel(name = "最后登录IP", type = Type.EXPORT)
+ private String loginIp;
+
+ /** 最后登录时间 */
+ @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
+ private Date loginDate;
+
+ /** 部门对象 */
+ @Excels({
+ @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
+ @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT)
+ })
+ @TableField(exist = false)
+ private SysDept dept;
+
+ /** 角色对象 */
+ @TableField(exist = false)
+ private List roles;
+
+ /** 角色组 */
+ @TableField(exist = false)
+ private Long[] roleIds;
+
+ /** 岗位组 */
+ @TableField(exist = false)
+ private Long[] postIds;
+
+ /** 角色ID */
+ @TableField(exist = false)
+ private Long roleId;
+ /**
+ * 多租户编号
+ */
+ private Long tenantId;
+ public SysUser()
+ {
+
+ }
+
+ public SysUser(Long userId)
+ {
+ this.userId = userId;
+ }
+
+ public Long getUserId()
+ {
+ return userId;
+ }
+
+ public void setUserId(Long userId)
+ {
+ this.userId = userId;
+ }
+
+ public boolean isAdmin()
+ {
+ return isAdmin(this.userId);
+ }
+
+ public static boolean isAdmin(Long userId)
+ {
+ return userId != null && 1L == userId;
+ }
+
+ public Long getDeptId()
+ {
+ return deptId;
+ }
+
+ public void setDeptId(Long deptId)
+ {
+ this.deptId = deptId;
+ }
+
+ @Xss(message = "用户昵称不能包含脚本字符")
+ @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")
+ public String getNickName()
+ {
+ return nickName;
+ }
+
+ public void setNickName(String nickName)
+ {
+ this.nickName = nickName;
+ }
+
+ @Xss(message = "用户账号不能包含脚本字符")
+ @NotBlank(message = "用户账号不能为空")
+ @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
+ public String getUserName()
+ {
+ return userName;
+ }
+
+ public void setUserName(String userName)
+ {
+ this.userName = userName;
+ }
+
+ @Email(message = "邮箱格式不正确")
+ @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
+ public String getEmail()
+ {
+ return email;
+ }
+
+ public void setEmail(String email)
+ {
+ this.email = email;
+ }
+
+ @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")
+ public String getPhonenumber()
+ {
+ return phonenumber;
+ }
+
+ public void setPhonenumber(String phonenumber)
+ {
+ this.phonenumber = phonenumber;
+ }
+
+ public String getSex()
+ {
+ return sex;
+ }
+
+ public void setSex(String sex)
+ {
+ this.sex = sex;
+ }
+
+ public String getAvatar()
+ {
+ return avatar;
+ }
+
+ public void setAvatar(String avatar)
+ {
+ this.avatar = avatar;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getDelFlag()
+ {
+ return delFlag;
+ }
+
+ public void setDelFlag(String delFlag)
+ {
+ this.delFlag = delFlag;
+ }
+
+ public String getLoginIp()
+ {
+ return loginIp;
+ }
+
+ public void setLoginIp(String loginIp)
+ {
+ this.loginIp = loginIp;
+ }
+
+ public Date getLoginDate()
+ {
+ return loginDate;
+ }
+
+ public void setLoginDate(Date loginDate)
+ {
+ this.loginDate = loginDate;
+ }
+
+ public SysDept getDept()
+ {
+ return dept;
+ }
+
+ public void setDept(SysDept dept)
+ {
+ this.dept = dept;
+ }
+
+ public List getRoles()
+ {
+ return roles;
+ }
+
+ public void setRoles(List roles)
+ {
+ this.roles = roles;
+ }
+
+ public Long[] getRoleIds()
+ {
+ return roleIds;
+ }
+
+ public void setRoleIds(Long[] roleIds)
+ {
+ this.roleIds = roleIds;
+ }
+
+ public Long[] getPostIds()
+ {
+ return postIds;
+ }
+
+ public void setPostIds(Long[] postIds)
+ {
+ this.postIds = postIds;
+ }
+
+ public Long getRoleId()
+ {
+ return roleId;
+ }
+
+ public void setRoleId(Long roleId)
+ {
+ this.roleId = roleId;
+ }
+
+ public Long getTenantId() {
+ return this.tenantId;
+ }
+
+ public void setTenantId(Long tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("userId", getUserId())
+ .append("deptId", getDeptId())
+ .append("userName", getUserName())
+ .append("nickName", getNickName())
+ .append("email", getEmail())
+ .append("phonenumber", getPhonenumber())
+ .append("sex", getSex())
+ .append("avatar", getAvatar())
+ .append("password", getPassword())
+ .append("status", getStatus())
+ .append("delFlag", getDelFlag())
+ .append("loginIp", getLoginIp())
+ .append("loginDate", getLoginDate())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .append("dept", getDept())
+ .toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java
new file mode 100644
index 00000000..b5bc8c8e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java
@@ -0,0 +1,69 @@
+package com.ruoyi.common.core.domain.model;
+
+/**
+ * 用户登录对象
+ *
+ * @author ruoyi
+ */
+public class LoginBody
+{
+ /**
+ * 用户名
+ */
+ private String username;
+
+ /**
+ * 用户密码
+ */
+ private String password;
+
+ /**
+ * 验证码
+ */
+ private String code;
+
+ /**
+ * 唯一标识
+ */
+ private String uuid;
+
+ public String getUsername()
+ {
+ return username;
+ }
+
+ public void setUsername(String username)
+ {
+ this.username = username;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ public String getCode()
+ {
+ return code;
+ }
+
+ public void setCode(String code)
+ {
+ this.code = code;
+ }
+
+ public String getUuid()
+ {
+ return uuid;
+ }
+
+ public void setUuid(String uuid)
+ {
+ this.uuid = uuid;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java
new file mode 100644
index 00000000..79dba4e7
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java
@@ -0,0 +1,295 @@
+package com.ruoyi.common.core.domain.model;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 登录用户身份权限
+ *
+ * @author ruoyi
+ */
+public class LoginUser implements UserDetails
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 用户ID
+ */
+ private Long userId;
+
+ /**
+ * 部门ID
+ */
+ private Long deptId;
+
+ /**
+ * 用户唯一标识
+ */
+ private String token;
+
+ /**
+ * 登录时间
+ */
+ private Long loginTime;
+
+ /**
+ * 过期时间
+ */
+ private Long expireTime;
+
+ /**
+ * 登录IP地址
+ */
+ private String ipaddr;
+
+ /**
+ * 登录地点
+ */
+ private String loginLocation;
+
+ /**
+ * 浏览器类型
+ */
+ private String browser;
+
+ /**
+ * 操作系统
+ */
+ private String os;
+
+ /**
+ * 权限列表
+ */
+ private Set permissions;
+
+ /**
+ * 数据范围信息
+ */
+ private List dataScopes;
+
+ /**
+ * 用户信息
+ */
+ private SysUser user;
+ /**
+ * 租户编号
+ */
+ private Long tenantId;
+
+ public Long getUserId()
+ {
+ return userId;
+ }
+
+ public void setUserId(Long userId)
+ {
+ this.userId = userId;
+ }
+
+ public Long getDeptId()
+ {
+ return deptId;
+ }
+
+ public void setDeptId(Long deptId)
+ {
+ this.deptId = deptId;
+ }
+
+ public String getToken()
+ {
+ return token;
+ }
+
+ public void setToken(String token)
+ {
+ this.token = token;
+ }
+
+ public LoginUser()
+ {
+ }
+
+ public LoginUser(SysUser user, Set permissions)
+ {
+ this.user = user;
+ this.permissions = permissions;
+ }
+
+ public LoginUser(Long userId, Long deptId, SysUser user, Set permissions, List dataScopes,Long tenantId)
+ {
+ this.userId = userId;
+ this.deptId = deptId;
+ this.user = user;
+ this.permissions = permissions;
+ this.dataScopes = dataScopes;
+ this.tenantId = tenantId;
+ }
+
+ @JSONField(serialize = false)
+ @Override
+ public String getPassword()
+ {
+ return user.getPassword();
+ }
+
+ @Override
+ public String getUsername()
+ {
+ return user.getUserName();
+ }
+
+ /**
+ * 账户是否未过期,过期无法验证
+ */
+ @JSONField(serialize = false)
+ @Override
+ public boolean isAccountNonExpired()
+ {
+ return true;
+ }
+
+ /**
+ * 指定用户是否解锁,锁定的用户无法进行身份验证
+ *
+ * @return
+ */
+ @JSONField(serialize = false)
+ @Override
+ public boolean isAccountNonLocked()
+ {
+ return true;
+ }
+
+ /**
+ * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
+ *
+ * @return
+ */
+ @JSONField(serialize = false)
+ @Override
+ public boolean isCredentialsNonExpired()
+ {
+ return true;
+ }
+
+ /**
+ * 是否可用 ,禁用的用户不能身份验证
+ *
+ * @return
+ */
+ @JSONField(serialize = false)
+ @Override
+ public boolean isEnabled()
+ {
+ return true;
+ }
+
+ public Long getLoginTime()
+ {
+ return loginTime;
+ }
+
+ public void setLoginTime(Long loginTime)
+ {
+ this.loginTime = loginTime;
+ }
+
+ public String getIpaddr()
+ {
+ return ipaddr;
+ }
+
+ public void setIpaddr(String ipaddr)
+ {
+ this.ipaddr = ipaddr;
+ }
+
+ public String getLoginLocation()
+ {
+ return loginLocation;
+ }
+
+ public void setLoginLocation(String loginLocation)
+ {
+ this.loginLocation = loginLocation;
+ }
+
+ public String getBrowser()
+ {
+ return browser;
+ }
+
+ public void setBrowser(String browser)
+ {
+ this.browser = browser;
+ }
+
+ public String getOs()
+ {
+ return os;
+ }
+
+ public void setOs(String os)
+ {
+ this.os = os;
+ }
+
+ public Long getExpireTime()
+ {
+ return expireTime;
+ }
+
+ public void setExpireTime(Long expireTime)
+ {
+ this.expireTime = expireTime;
+ }
+
+ public Set getPermissions()
+ {
+ return permissions;
+ }
+
+ public void setPermissions(Set permissions)
+ {
+ this.permissions = permissions;
+ }
+
+ public List getDataScopes() {
+ return dataScopes;
+ }
+
+ public void setDataScopes(List dataScopes) {
+ this.dataScopes = dataScopes;
+ }
+
+ public SysUser getUser()
+ {
+ return user;
+ }
+
+ public void setUser(SysUser user)
+ {
+ this.user = user;
+ }
+
+ public Long getTenantId() {
+ return this.tenantId;
+ }
+
+ public void setTenantId(Long tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ @Override
+ public Collection extends GrantedAuthority> getAuthorities()
+ {
+ return null;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java
new file mode 100644
index 00000000..868a1fc5
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java
@@ -0,0 +1,11 @@
+package com.ruoyi.common.core.domain.model;
+
+/**
+ * 用户注册对象
+ *
+ * @author ruoyi
+ */
+public class RegisterBody extends LoginBody
+{
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java
new file mode 100644
index 00000000..8966cb4c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java
@@ -0,0 +1,101 @@
+package com.ruoyi.common.core.page;
+
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 分页数据
+ *
+ * @author ruoyi
+ */
+public class PageDomain
+{
+ /** 当前记录起始索引 */
+ private Integer pageNum;
+
+ /** 每页显示记录数 */
+ private Integer pageSize;
+
+ /** 排序列 */
+ private String orderByColumn;
+
+ /** 排序的方向desc或者asc */
+ private String isAsc = "asc";
+
+ /** 分页参数合理化 */
+ private Boolean reasonable = true;
+
+ public String getOrderBy()
+ {
+ if (StringUtils.isEmpty(orderByColumn))
+ {
+ return "";
+ }
+ return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
+ }
+
+ public Integer getPageNum()
+ {
+ return pageNum;
+ }
+
+ public void setPageNum(Integer pageNum)
+ {
+ this.pageNum = pageNum;
+ }
+
+ public Integer getPageSize()
+ {
+ return pageSize;
+ }
+
+ public void setPageSize(Integer pageSize)
+ {
+ this.pageSize = pageSize;
+ }
+
+ public String getOrderByColumn()
+ {
+ return orderByColumn;
+ }
+
+ public void setOrderByColumn(String orderByColumn)
+ {
+ this.orderByColumn = orderByColumn;
+ }
+
+ public String getIsAsc()
+ {
+ return isAsc;
+ }
+
+ public void setIsAsc(String isAsc)
+ {
+ if (StringUtils.isNotEmpty(isAsc))
+ {
+ // 兼容前端排序类型
+ if ("ascending".equals(isAsc))
+ {
+ isAsc = "asc";
+ }
+ else if ("descending".equals(isAsc))
+ {
+ isAsc = "desc";
+ }
+ this.isAsc = isAsc;
+ }
+ }
+
+ public Boolean getReasonable()
+ {
+ if (StringUtils.isNull(reasonable))
+ {
+ return Boolean.TRUE;
+ }
+ return reasonable;
+ }
+
+ public void setReasonable(Boolean reasonable)
+ {
+ this.reasonable = reasonable;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
new file mode 100644
index 00000000..96294659
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
@@ -0,0 +1,116 @@
+package com.ruoyi.common.core.page;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 表格分页数据对象
+ *
+ * @author ruoyi
+ */
+public class TableDataInfo implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 总记录数 */
+ private long total;
+
+ /** 列表数据 */
+ private List> rows;
+
+ /** 消息状态码 */
+ private int code;
+
+ /** 消息内容 */
+ private String msg;
+ /** 当前记录起始索引 */
+ private long pageNum;
+
+ /** 每页显示记录数 */
+ private long pageSize;
+
+ /** 总页数 */
+ private long totalPageNum;
+ /**
+ * 表格数据对象
+ */
+ public TableDataInfo()
+ {
+ }
+
+ /**
+ * 分页
+ *
+ * @param list 列表数据
+ * @param total 总记录数
+ */
+ public TableDataInfo(List> list, int total)
+ {
+ this.rows = list;
+ this.total = total;
+ }
+
+ public long getTotal()
+ {
+ return total;
+ }
+
+ public void setTotal(long total)
+ {
+ this.total = total;
+ }
+
+ public List> getRows()
+ {
+ return rows;
+ }
+
+ public void setRows(List> rows)
+ {
+ this.rows = rows;
+ }
+
+ public int getCode()
+ {
+ return code;
+ }
+
+ public void setCode(int code)
+ {
+ this.code = code;
+ }
+
+ public String getMsg()
+ {
+ return msg;
+ }
+
+ public void setMsg(String msg)
+ {
+ this.msg = msg;
+ }
+
+ public long getPageNum() {
+ return pageNum;
+ }
+
+ public void setPageNum(long pageNum) {
+ this.pageNum = pageNum;
+ }
+
+ public long getPageSize() {
+ return pageSize;
+ }
+
+ public void setPageSize(long pageSize) {
+ this.pageSize = pageSize;
+ }
+
+ public long getTotalPageNum() {
+ return totalPageNum;
+ }
+
+ public void setTotalPageNum(long totalPageNum) {
+ this.totalPageNum = totalPageNum;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java
new file mode 100644
index 00000000..a120c300
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java
@@ -0,0 +1,56 @@
+package com.ruoyi.common.core.page;
+
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.ServletUtils;
+
+/**
+ * 表格数据处理
+ *
+ * @author ruoyi
+ */
+public class TableSupport
+{
+ /**
+ * 当前记录起始索引
+ */
+ public static final String PAGE_NUM = "pageNum";
+
+ /**
+ * 每页显示记录数
+ */
+ public static final String PAGE_SIZE = "pageSize";
+
+ /**
+ * 排序列
+ */
+ public static final String ORDER_BY_COLUMN = "orderByColumn";
+
+ /**
+ * 排序的方向 "desc" 或者 "asc".
+ */
+ public static final String IS_ASC = "isAsc";
+
+ /**
+ * 分页参数合理化
+ */
+ public static final String REASONABLE = "reasonable";
+
+ /**
+ * 封装分页对象
+ */
+ public static PageDomain getPageDomain()
+ {
+ PageDomain pageDomain = new PageDomain();
+ pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1));
+ pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10));
+ pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
+ pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
+ pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
+ return pageDomain;
+ }
+
+ public static PageDomain buildPageRequest()
+ {
+ return getPageDomain();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/BaseServiceImpl.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/BaseServiceImpl.java
new file mode 100644
index 00000000..7d3c417d
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/BaseServiceImpl.java
@@ -0,0 +1,12 @@
+//package com.ruoyi.common.core.service;
+//
+//import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+//import org.springframework.beans.factory.annotation.Autowired;
+//
+//public class BaseServiceImpl, T> extends ServiceImpl implements IBaseService {
+// @Autowired
+// private BaseMapper mapper;
+//
+//
+//}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/IBaseService.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/IBaseService.java
new file mode 100644
index 00000000..592bcfa6
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/IBaseService.java
@@ -0,0 +1,6 @@
+//package com.ruoyi.common.core.service;
+//
+//import com.baomidou.mybatisplus.extension.service.IService;
+//
+//public interface IBaseService extends IService {
+//}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java
new file mode 100644
index 00000000..84124aac
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java
@@ -0,0 +1,86 @@
+package com.ruoyi.common.core.text;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 字符集工具类
+ *
+ * @author ruoyi
+ */
+public class CharsetKit
+{
+ /** ISO-8859-1 */
+ public static final String ISO_8859_1 = "ISO-8859-1";
+ /** UTF-8 */
+ public static final String UTF_8 = "UTF-8";
+ /** GBK */
+ public static final String GBK = "GBK";
+
+ /** ISO-8859-1 */
+ public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
+ /** UTF-8 */
+ public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
+ /** GBK */
+ public static final Charset CHARSET_GBK = Charset.forName(GBK);
+
+ /**
+ * 转换为Charset对象
+ *
+ * @param charset 字符集,为空则返回默认字符集
+ * @return Charset
+ */
+ public static Charset charset(String charset)
+ {
+ return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
+ }
+
+ /**
+ * 转换字符串的字符集编码
+ *
+ * @param source 字符串
+ * @param srcCharset 源字符集,默认ISO-8859-1
+ * @param destCharset 目标字符集,默认UTF-8
+ * @return 转换后的字符集
+ */
+ public static String convert(String source, String srcCharset, String destCharset)
+ {
+ return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
+ }
+
+ /**
+ * 转换字符串的字符集编码
+ *
+ * @param source 字符串
+ * @param srcCharset 源字符集,默认ISO-8859-1
+ * @param destCharset 目标字符集,默认UTF-8
+ * @return 转换后的字符集
+ */
+ public static String convert(String source, Charset srcCharset, Charset destCharset)
+ {
+ if (null == srcCharset)
+ {
+ srcCharset = StandardCharsets.ISO_8859_1;
+ }
+
+ if (null == destCharset)
+ {
+ destCharset = StandardCharsets.UTF_8;
+ }
+
+ if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
+ {
+ return source;
+ }
+ return new String(source.getBytes(srcCharset), destCharset);
+ }
+
+ /**
+ * @return 系统字符集编码
+ */
+ public static String systemCharset()
+ {
+ return Charset.defaultCharset().name();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
new file mode 100644
index 00000000..b82321cd
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
@@ -0,0 +1,1000 @@
+package com.ruoyi.common.core.text;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.util.Set;
+import com.ruoyi.common.utils.StringUtils;
+import org.apache.commons.lang3.ArrayUtils;
+
+/**
+ * 类型转换器
+ *
+ * @author ruoyi
+ */
+public class Convert
+{
+ /**
+ * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static String toStr(Object value, String defaultValue)
+ {
+ if (null == value)
+ {
+ return defaultValue;
+ }
+ if (value instanceof String)
+ {
+ return (String) value;
+ }
+ return value.toString();
+ }
+
+ /**
+ * 转换为字符串
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static String toStr(Object value)
+ {
+ return toStr(value, null);
+ }
+
+ /**
+ * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Character toChar(Object value, Character defaultValue)
+ {
+ if (null == value)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Character)
+ {
+ return (Character) value;
+ }
+
+ final String valueStr = toStr(value, null);
+ return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
+ }
+
+ /**
+ * 转换为字符
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Character toChar(Object value)
+ {
+ return toChar(value, null);
+ }
+
+ /**
+ * 转换为byte
+ * 如果给定的值为null
,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Byte toByte(Object value, Byte defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Byte)
+ {
+ return (Byte) value;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number) value).byteValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return Byte.parseByte(valueStr);
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为byte
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Byte toByte(Object value)
+ {
+ return toByte(value, null);
+ }
+
+ /**
+ * 转换为Short
+ * 如果给定的值为null
,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Short toShort(Object value, Short defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Short)
+ {
+ return (Short) value;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number) value).shortValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return Short.parseShort(valueStr.trim());
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为Short
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Short toShort(Object value)
+ {
+ return toShort(value, null);
+ }
+
+ /**
+ * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Number toNumber(Object value, Number defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Number)
+ {
+ return (Number) value;
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return NumberFormat.getInstance().parse(valueStr);
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Number toNumber(Object value)
+ {
+ return toNumber(value, null);
+ }
+
+ /**
+ * 转换为int
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Integer toInt(Object value, Integer defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Integer)
+ {
+ return (Integer) value;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number) value).intValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return Integer.parseInt(valueStr.trim());
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为int
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Integer toInt(Object value)
+ {
+ return toInt(value, null);
+ }
+
+ /**
+ * 转换为Integer数组
+ *
+ * @param str 被转换的值
+ * @return 结果
+ */
+ public static Integer[] toIntArray(String str)
+ {
+ return toIntArray(",", str);
+ }
+
+ /**
+ * 转换为Long数组
+ *
+ * @param str 被转换的值
+ * @return 结果
+ */
+ public static Long[] toLongArray(String str)
+ {
+ return toLongArray(",", str);
+ }
+
+ /**
+ * 转换为Integer数组
+ *
+ * @param split 分隔符
+ * @param split 被转换的值
+ * @return 结果
+ */
+ public static Integer[] toIntArray(String split, String str)
+ {
+ if (StringUtils.isEmpty(str))
+ {
+ return new Integer[] {};
+ }
+ String[] arr = str.split(split);
+ final Integer[] ints = new Integer[arr.length];
+ for (int i = 0; i < arr.length; i++)
+ {
+ final Integer v = toInt(arr[i], 0);
+ ints[i] = v;
+ }
+ return ints;
+ }
+
+ /**
+ * 转换为Long数组
+ *
+ * @param split 分隔符
+ * @param str 被转换的值
+ * @return 结果
+ */
+ public static Long[] toLongArray(String split, String str)
+ {
+ if (StringUtils.isEmpty(str))
+ {
+ return new Long[] {};
+ }
+ String[] arr = str.split(split);
+ final Long[] longs = new Long[arr.length];
+ for (int i = 0; i < arr.length; i++)
+ {
+ final Long v = toLong(arr[i], null);
+ longs[i] = v;
+ }
+ return longs;
+ }
+
+ /**
+ * 转换为String数组
+ *
+ * @param str 被转换的值
+ * @return 结果
+ */
+ public static String[] toStrArray(String str)
+ {
+ return toStrArray(",", str);
+ }
+
+ /**
+ * 转换为String数组
+ *
+ * @param split 分隔符
+ * @param split 被转换的值
+ * @return 结果
+ */
+ public static String[] toStrArray(String split, String str)
+ {
+ return str.split(split);
+ }
+
+ /**
+ * 转换为long
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Long toLong(Object value, Long defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Long)
+ {
+ return (Long) value;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number) value).longValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ // 支持科学计数法
+ return new BigDecimal(valueStr.trim()).longValue();
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为long
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Long toLong(Object value)
+ {
+ return toLong(value, null);
+ }
+
+ /**
+ * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Double toDouble(Object value, Double defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Double)
+ {
+ return (Double) value;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number) value).doubleValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ // 支持科学计数法
+ return new BigDecimal(valueStr.trim()).doubleValue();
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Double toDouble(Object value)
+ {
+ return toDouble(value, null);
+ }
+
+ /**
+ * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Float toFloat(Object value, Float defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Float)
+ {
+ return (Float) value;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number) value).floatValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return Float.parseFloat(valueStr.trim());
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Float toFloat(Object value)
+ {
+ return toFloat(value, null);
+ }
+
+ /**
+ * 转换为boolean
+ * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Boolean toBool(Object value, Boolean defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Boolean)
+ {
+ return (Boolean) value;
+ }
+ String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ valueStr = valueStr.trim().toLowerCase();
+ switch (valueStr)
+ {
+ case "true":
+ case "yes":
+ case "ok":
+ case "1":
+ return true;
+ case "false":
+ case "no":
+ case "0":
+ return false;
+ default:
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为boolean
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Boolean toBool(Object value)
+ {
+ return toBool(value, null);
+ }
+
+ /**
+ * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值
+ *
+ * @param clazz Enum的Class
+ * @param value 值
+ * @param defaultValue 默认值
+ * @return Enum
+ */
+ public static > E toEnum(Class clazz, Object value, E defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (clazz.isAssignableFrom(value.getClass()))
+ {
+ @SuppressWarnings("unchecked")
+ E myE = (E) value;
+ return myE;
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return Enum.valueOf(clazz, valueStr);
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ *
+ * @param clazz Enum的Class
+ * @param value 值
+ * @return Enum
+ */
+ public static > E toEnum(Class clazz, Object value)
+ {
+ return toEnum(clazz, value, null);
+ }
+
+ /**
+ * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static BigInteger toBigInteger(Object value, BigInteger defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof BigInteger)
+ {
+ return (BigInteger) value;
+ }
+ if (value instanceof Long)
+ {
+ return BigInteger.valueOf((Long) value);
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return new BigInteger(valueStr);
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static BigInteger toBigInteger(Object value)
+ {
+ return toBigInteger(value, null);
+ }
+
+ /**
+ * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof BigDecimal)
+ {
+ return (BigDecimal) value;
+ }
+ if (value instanceof Long)
+ {
+ return new BigDecimal((Long) value);
+ }
+ if (value instanceof Double)
+ {
+ return new BigDecimal((Double) value);
+ }
+ if (value instanceof Integer)
+ {
+ return new BigDecimal((Integer) value);
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return new BigDecimal(valueStr);
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static BigDecimal toBigDecimal(Object value)
+ {
+ return toBigDecimal(value, null);
+ }
+
+ /**
+ * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+ *
+ * @param obj 对象
+ * @return 字符串
+ */
+ public static String utf8Str(Object obj)
+ {
+ return str(obj, CharsetKit.CHARSET_UTF_8);
+ }
+
+ /**
+ * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+ *
+ * @param obj 对象
+ * @param charsetName 字符集
+ * @return 字符串
+ */
+ public static String str(Object obj, String charsetName)
+ {
+ return str(obj, Charset.forName(charsetName));
+ }
+
+ /**
+ * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+ *
+ * @param obj 对象
+ * @param charset 字符集
+ * @return 字符串
+ */
+ public static String str(Object obj, Charset charset)
+ {
+ if (null == obj)
+ {
+ return null;
+ }
+
+ if (obj instanceof String)
+ {
+ return (String) obj;
+ }
+ else if (obj instanceof byte[])
+ {
+ return str((byte[]) obj, charset);
+ }
+ else if (obj instanceof Byte[])
+ {
+ byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
+ return str(bytes, charset);
+ }
+ else if (obj instanceof ByteBuffer)
+ {
+ return str((ByteBuffer) obj, charset);
+ }
+ return obj.toString();
+ }
+
+ /**
+ * 将byte数组转为字符串
+ *
+ * @param bytes byte数组
+ * @param charset 字符集
+ * @return 字符串
+ */
+ public static String str(byte[] bytes, String charset)
+ {
+ return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
+ }
+
+ /**
+ * 解码字节码
+ *
+ * @param data 字符串
+ * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
+ * @return 解码后的字符串
+ */
+ public static String str(byte[] data, Charset charset)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+
+ if (null == charset)
+ {
+ return new String(data);
+ }
+ return new String(data, charset);
+ }
+
+ /**
+ * 将编码的byteBuffer数据转换为字符串
+ *
+ * @param data 数据
+ * @param charset 字符集,如果为空使用当前系统字符集
+ * @return 字符串
+ */
+ public static String str(ByteBuffer data, String charset)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+
+ return str(data, Charset.forName(charset));
+ }
+
+ /**
+ * 将编码的byteBuffer数据转换为字符串
+ *
+ * @param data 数据
+ * @param charset 字符集,如果为空使用当前系统字符集
+ * @return 字符串
+ */
+ public static String str(ByteBuffer data, Charset charset)
+ {
+ if (null == charset)
+ {
+ charset = Charset.defaultCharset();
+ }
+ return charset.decode(data).toString();
+ }
+
+ // ----------------------------------------------------------------------- 全角半角转换
+ /**
+ * 半角转全角
+ *
+ * @param input String.
+ * @return 全角字符串.
+ */
+ public static String toSBC(String input)
+ {
+ return toSBC(input, null);
+ }
+
+ /**
+ * 半角转全角
+ *
+ * @param input String
+ * @param notConvertSet 不替换的字符集合
+ * @return 全角字符串.
+ */
+ public static String toSBC(String input, Set notConvertSet)
+ {
+ char[] c = input.toCharArray();
+ for (int i = 0; i < c.length; i++)
+ {
+ if (null != notConvertSet && notConvertSet.contains(c[i]))
+ {
+ // 跳过不替换的字符
+ continue;
+ }
+
+ if (c[i] == ' ')
+ {
+ c[i] = '\u3000';
+ }
+ else if (c[i] < '\177')
+ {
+ c[i] = (char) (c[i] + 65248);
+
+ }
+ }
+ return new String(c);
+ }
+
+ /**
+ * 全角转半角
+ *
+ * @param input String.
+ * @return 半角字符串
+ */
+ public static String toDBC(String input)
+ {
+ return toDBC(input, null);
+ }
+
+ /**
+ * 替换全角为半角
+ *
+ * @param text 文本
+ * @param notConvertSet 不替换的字符集合
+ * @return 替换后的字符
+ */
+ public static String toDBC(String text, Set notConvertSet)
+ {
+ char[] c = text.toCharArray();
+ for (int i = 0; i < c.length; i++)
+ {
+ if (null != notConvertSet && notConvertSet.contains(c[i]))
+ {
+ // 跳过不替换的字符
+ continue;
+ }
+
+ if (c[i] == '\u3000')
+ {
+ c[i] = ' ';
+ }
+ else if (c[i] > '\uFF00' && c[i] < '\uFF5F')
+ {
+ c[i] = (char) (c[i] - 65248);
+ }
+ }
+ String returnString = new String(c);
+
+ return returnString;
+ }
+
+ /**
+ * 数字金额大写转换 先写个完整的然后将如零拾替换成零
+ *
+ * @param n 数字
+ * @return 中文大写数字
+ */
+ public static String digitUppercase(double n)
+ {
+ String[] fraction = { "角", "分" };
+ String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
+ String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } };
+
+ String head = n < 0 ? "负" : "";
+ n = Math.abs(n);
+
+ String s = "";
+ for (int i = 0; i < fraction.length; i++)
+ {
+ s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
+ }
+ if (s.length() < 1)
+ {
+ s = "整";
+ }
+ int integerPart = (int) Math.floor(n);
+
+ for (int i = 0; i < unit[0].length && integerPart > 0; i++)
+ {
+ String p = "";
+ for (int j = 0; j < unit[1].length && n > 0; j++)
+ {
+ p = digit[integerPart % 10] + unit[1][j] + p;
+ integerPart = integerPart / 10;
+ }
+ s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
+ }
+ return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java
new file mode 100644
index 00000000..c78ac776
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java
@@ -0,0 +1,92 @@
+package com.ruoyi.common.core.text;
+
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 字符串格式化
+ *
+ * @author ruoyi
+ */
+public class StrFormatter
+{
+ public static final String EMPTY_JSON = "{}";
+ public static final char C_BACKSLASH = '\\';
+ public static final char C_DELIM_START = '{';
+ public static final char C_DELIM_END = '}';
+
+ /**
+ * 格式化字符串
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ *
+ * @param strPattern 字符串模板
+ * @param argArray 参数列表
+ * @return 结果
+ */
+ public static String format(final String strPattern, final Object... argArray)
+ {
+ if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
+ {
+ return strPattern;
+ }
+ final int strPatternLength = strPattern.length();
+
+ // 初始化定义好的长度以获得更好的性能
+ StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
+
+ int handledPosition = 0;
+ int delimIndex;// 占位符所在位置
+ for (int argIndex = 0; argIndex < argArray.length; argIndex++)
+ {
+ delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
+ if (delimIndex == -1)
+ {
+ if (handledPosition == 0)
+ {
+ return strPattern;
+ }
+ else
+ { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
+ sbuf.append(strPattern, handledPosition, strPatternLength);
+ return sbuf.toString();
+ }
+ }
+ else
+ {
+ if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
+ {
+ if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
+ {
+ // 转义符之前还有一个转义符,占位符依旧有效
+ sbuf.append(strPattern, handledPosition, delimIndex - 1);
+ sbuf.append(Convert.utf8Str(argArray[argIndex]));
+ handledPosition = delimIndex + 2;
+ }
+ else
+ {
+ // 占位符被转义
+ argIndex--;
+ sbuf.append(strPattern, handledPosition, delimIndex - 1);
+ sbuf.append(C_DELIM_START);
+ handledPosition = delimIndex + 1;
+ }
+ }
+ else
+ {
+ // 正常占位符
+ sbuf.append(strPattern, handledPosition, delimIndex);
+ sbuf.append(Convert.utf8Str(argArray[argIndex]));
+ handledPosition = delimIndex + 2;
+ }
+ }
+ }
+ // 加入最后一个占位符后所有的字符
+ sbuf.append(strPattern, handledPosition, strPattern.length());
+
+ return sbuf.toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java
new file mode 100644
index 00000000..10b7306f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java
@@ -0,0 +1,20 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 操作状态
+ *
+ * @author ruoyi
+ *
+ */
+public enum BusinessStatus
+{
+ /**
+ * 成功
+ */
+ SUCCESS,
+
+ /**
+ * 失败
+ */
+ FAIL,
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java
new file mode 100644
index 00000000..2e17c4a5
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java
@@ -0,0 +1,59 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 业务操作类型
+ *
+ * @author ruoyi
+ */
+public enum BusinessType
+{
+ /**
+ * 其它
+ */
+ OTHER,
+
+ /**
+ * 新增
+ */
+ INSERT,
+
+ /**
+ * 修改
+ */
+ UPDATE,
+
+ /**
+ * 删除
+ */
+ DELETE,
+
+ /**
+ * 授权
+ */
+ GRANT,
+
+ /**
+ * 导出
+ */
+ EXPORT,
+
+ /**
+ * 导入
+ */
+ IMPORT,
+
+ /**
+ * 强退
+ */
+ FORCE,
+
+ /**
+ * 生成代码
+ */
+ GENCODE,
+
+ /**
+ * 清空数据
+ */
+ CLEAN,
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/CommonStatusEnum.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/CommonStatusEnum.java
new file mode 100644
index 00000000..707cf90e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/CommonStatusEnum.java
@@ -0,0 +1,38 @@
+package com.ruoyi.common.enums;
+
+import com.ruoyi.common.utils.collection.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 通用状态枚举
+ *
+ * hasPermi
+ */
+@Getter
+@AllArgsConstructor
+public enum CommonStatusEnum implements IntArrayValuable {
+
+ ENABLE(0, "开启"),
+ DISABLE(1, "关闭");
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CommonStatusEnum::getStatus).toArray();
+
+
+ /**
+ * 状态值
+ */
+ private final Integer status;
+ /**
+ * 状态名
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java
new file mode 100644
index 00000000..0d945be5
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 数据源
+ *
+ * @author ruoyi
+ */
+public enum DataSourceType
+{
+ /**
+ * 主库
+ */
+ MASTER,
+
+ /**
+ * 从库
+ */
+ SLAVE
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java
new file mode 100644
index 00000000..be6f7392
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java
@@ -0,0 +1,36 @@
+package com.ruoyi.common.enums;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.springframework.lang.Nullable;
+
+/**
+ * 请求方式
+ *
+ * @author ruoyi
+ */
+public enum HttpMethod
+{
+ GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
+
+ private static final Map mappings = new HashMap<>(16);
+
+ static
+ {
+ for (HttpMethod httpMethod : values())
+ {
+ mappings.put(httpMethod.name(), httpMethod);
+ }
+ }
+
+ @Nullable
+ public static HttpMethod resolve(@Nullable String method)
+ {
+ return (method != null ? mappings.get(method) : null);
+ }
+
+ public boolean matches(String method)
+ {
+ return (this == resolve(method));
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java
new file mode 100644
index 00000000..c609fd8a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java
@@ -0,0 +1,20 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 限流类型
+ *
+ * @author ruoyi
+ */
+
+public enum LimitType
+{
+ /**
+ * 默认策略全局限流
+ */
+ DEFAULT,
+
+ /**
+ * 根据请求者IP进行限流
+ */
+ IP
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java
new file mode 100644
index 00000000..bdd143c1
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 操作人类别
+ *
+ * @author ruoyi
+ */
+public enum OperatorType
+{
+ /**
+ * 其它
+ */
+ OTHER,
+
+ /**
+ * 后台用户
+ */
+ MANAGE,
+
+ /**
+ * 手机端用户
+ */
+ MOBILE
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/RoleCodeEnum.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/RoleCodeEnum.java
new file mode 100644
index 00000000..09ab14a3
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/RoleCodeEnum.java
@@ -0,0 +1,30 @@
+package com.ruoyi.common.enums;
+
+import com.ruoyi.common.utils.ObjectUtils;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 角色标识枚举
+ */
+@Getter
+@AllArgsConstructor
+public enum RoleCodeEnum {
+
+ SUPER_ADMIN("admin", "超级管理员"), TENANT_ADMIN("tenant_admin", "租户管理员"),
+ ;
+
+ /**
+ * 角色编码
+ */
+ private final String code;
+ /**
+ * 名字
+ */
+ private final String name;
+
+ public static boolean isSuperAdmin(String code) {
+ return ObjectUtils.equalsAny(code, SUPER_ADMIN.getCode());
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java
new file mode 100644
index 00000000..d7ff44a9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java
@@ -0,0 +1,30 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 用户状态
+ *
+ * @author ruoyi
+ */
+public enum UserStatus
+{
+ OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
+
+ private final String code;
+ private final String info;
+
+ UserStatus(String code, String info)
+ {
+ this.code = code;
+ this.info = info;
+ }
+
+ public String getCode()
+ {
+ return code;
+ }
+
+ public String getInfo()
+ {
+ return info;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/DeviceStatusEnum.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/DeviceStatusEnum.java
new file mode 100644
index 00000000..25f1c0b7
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/DeviceStatusEnum.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.enums.bs;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 角色标识枚举
+ */
+@Getter
+@AllArgsConstructor
+public enum DeviceStatusEnum {
+
+ EXCEPTION(0, "异常"),
+ NORMAL(1, "正常"),
+ INVALID(1, "失效"),
+ ;
+
+ /**
+ * 编码
+ */
+ private final Integer code;
+ /**
+ * 名称
+ */
+ private final String name;
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/TaskCodeEnum.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/TaskCodeEnum.java
new file mode 100644
index 00000000..46806184
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/TaskCodeEnum.java
@@ -0,0 +1,25 @@
+package com.ruoyi.common.enums.bs;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 任务编码
+ */
+@Getter
+@AllArgsConstructor
+public enum TaskCodeEnum {
+
+ POINT("point", "点位巡查"),
+ ;
+
+ /**
+ * 编码
+ */
+ private final String code;
+ /**
+ * 名称
+ */
+ private final String name;
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/TaskExceptionStatusEnum.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/TaskExceptionStatusEnum.java
new file mode 100644
index 00000000..1e55dea5
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/TaskExceptionStatusEnum.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.enums.bs;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 角色标识枚举
+ */
+@Getter
+@AllArgsConstructor
+public enum TaskExceptionStatusEnum {
+
+ PENDING("pending", "待检"),
+ NORMAL("normal", "正常"),
+ EXCEPTION("exception", "异常"),
+ ;
+
+ /**
+ * 编码
+ */
+ private final String code;
+ /**
+ * 名称
+ */
+ private final String name;
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/TaskSettingStatusEnum.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/TaskSettingStatusEnum.java
new file mode 100644
index 00000000..18341e22
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/TaskSettingStatusEnum.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.enums.bs;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 角色标识枚举
+ */
+@Getter
+@AllArgsConstructor
+public enum TaskSettingStatusEnum {
+
+ NOTSET("notset", "未设置"),
+ SETED("seted", "已设置"),
+ ;
+
+ /**
+ * 编码
+ */
+ private final String code;
+ /**
+ * 名称
+ */
+ private final String name;
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/TaskTypeEnum.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/TaskTypeEnum.java
new file mode 100644
index 00000000..75eff0b9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/bs/TaskTypeEnum.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.enums.bs;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 任务编码
+ */
+@Getter
+@AllArgsConstructor
+public enum TaskTypeEnum {
+
+ STANDARD("standard", "标准"),
+ CUSTOM("custom", "定制"),
+ SELF("self", "自制"),
+ ;
+
+ /**
+ * 编码
+ */
+ private final String code;
+ /**
+ * 名称
+ */
+ private final String name;
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java
new file mode 100644
index 00000000..f6ad2ab4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java
@@ -0,0 +1,15 @@
+package com.ruoyi.common.exception;
+
+/**
+ * 演示模式异常
+ *
+ * @author ruoyi
+ */
+public class DemoModeException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ public DemoModeException()
+ {
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/ErrorCode.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ErrorCode.java
new file mode 100644
index 00000000..43920680
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ErrorCode.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.exception;
+
+import lombok.Data;
+
+/**
+ * 错误码对象
+ * TODO 错误码设计成对象的原因,为未来的 i18 国际化做准备
+ */
+@Data
+public class ErrorCode {
+
+ /**
+ * 错误码
+ */
+ private final Integer code;
+ /**
+ * 错误提示
+ */
+ private final String msg;
+
+ public ErrorCode(Integer code, String message) {
+ this.code = code;
+ this.msg = message;
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java
new file mode 100644
index 00000000..81a71b5d
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java
@@ -0,0 +1,58 @@
+package com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java
new file mode 100644
index 00000000..fcc7ab6e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java
@@ -0,0 +1,74 @@
+package com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java
new file mode 100644
index 00000000..980fa465
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java
new file mode 100644
index 00000000..b55d72e1
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java
@@ -0,0 +1,97 @@
+package com.ruoyi.common.exception.base;
+
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java
new file mode 100644
index 00000000..871f09b5
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.exception.file;
+
+import com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java
new file mode 100644
index 00000000..70e0ec9b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java
new file mode 100644
index 00000000..ec6ab054
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java
new file mode 100644
index 00000000..8b2af16c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java
@@ -0,0 +1,81 @@
+package com.ruoyi.common.exception.file;
+
+import java.util.Arrays;
+import org.apache.commons.fileupload.FileUploadException;
+
+/**
+ * 文件上传 误异常类
+ *
+ * @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/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java
new file mode 100644
index 00000000..a567b408
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java
@@ -0,0 +1,34 @@
+package com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java
new file mode 100644
index 00000000..389dbc75
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java
new file mode 100644
index 00000000..85f94861
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java
new file mode 100644
index 00000000..c292d70e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.exception.user;
+
+import com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java
new file mode 100644
index 00000000..a7f3e5ff
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java
new file mode 100644
index 00000000..3f95c0b1
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.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/ruoyi-common/src/main/java/com/ruoyi/common/exception/util/ServiceExceptionUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/util/ServiceExceptionUtil.java
new file mode 100644
index 00000000..767a62c4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/util/ServiceExceptionUtil.java
@@ -0,0 +1,124 @@
+package com.ruoyi.common.exception.util;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.ruoyi.common.exception.ErrorCode;
+import com.ruoyi.common.exception.ServiceException;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * {@link ServiceException} 工具类
+ *
+ * 目的在于,格式化异常信息提示。
+ * 考虑到 String.format 在参数不正确时会报错,因此使用 {} 作为占位符,并使用 {@link #doFormat(int, String, Object...)} 方法来格式化
+ *
+ * 因为 {@link #MESSAGES} 里面默认是没有异常信息提示的模板的,所以需要使用方自己初始化进去。目前想到的有几种方式:
+ *
+ * 1. 异常提示信息,写在枚举类中,例如说,cn.iocoder.oceans.user.api.constants.ErrorCodeEnum 类 + ServiceExceptionConfiguration
+ * 2. 异常提示信息,写在 .properties 等等配置文件
+ * 3. 异常提示信息,写在 Apollo 等等配置中心中,从而实现可动态刷新
+ * 4. 异常提示信息,存储在 db 等等数据库中,从而实现可动态刷新
+ *
+ * @author wangzongrun
+ */
+@Slf4j
+public class ServiceExceptionUtil {
+
+ /**
+ * 错误码提示模板
+ */
+ private static final ConcurrentMap MESSAGES = new ConcurrentHashMap<>();
+
+ public static void putAll(Map messages) {
+ ServiceExceptionUtil.MESSAGES.putAll(messages);
+ }
+
+ public static void put(Integer code, String message) {
+ ServiceExceptionUtil.MESSAGES.put(code, message);
+ }
+
+ public static void delete(Integer code, String message) {
+ ServiceExceptionUtil.MESSAGES.remove(code, message);
+ }
+
+ // ========== 和 ServiceException 的集成 ==========
+
+ public static ServiceException exception(ErrorCode errorCode) {
+ String messagePattern = MESSAGES.getOrDefault(errorCode.getCode(), errorCode.getMsg());
+ return exception0(errorCode.getCode(), messagePattern);
+ }
+
+ public static ServiceException exception(ErrorCode errorCode, Object... params) {
+ String messagePattern = MESSAGES.getOrDefault(errorCode.getCode(), errorCode.getMsg());
+ return exception0(errorCode.getCode(), messagePattern, params);
+ }
+
+ /**
+ * 创建指定编号的 ServiceException 的异常
+ *
+ * @param code 编号
+ * @return 异常
+ */
+ public static ServiceException exception(Integer code) {
+ return exception0(code, MESSAGES.get(code));
+ }
+
+ /**
+ * 创建指定编号的 ServiceException 的异常
+ *
+ * @param code 编号
+ * @param params 消息提示的占位符对应的参数
+ * @return 异常
+ */
+ public static ServiceException exception(Integer code, Object... params) {
+ return exception0(code, MESSAGES.get(code), params);
+ }
+
+ public static ServiceException exception0(Integer code, String messagePattern, Object... params) {
+ String message = doFormat(code, messagePattern, params);
+ return new ServiceException(message, code);
+ }
+
+ // ========== 格式化方法 ==========
+
+ /**
+ * 将错误编号对应的消息使用 params 进行格式化。
+ *
+ * @param code 错误编号
+ * @param messagePattern 消息模版
+ * @param params 参数
+ * @return 格式化后的提示
+ */
+ @VisibleForTesting
+ public static String doFormat(int code, String messagePattern, Object... params) {
+ StringBuilder sbuf = new StringBuilder(messagePattern.length() + 50);
+ int i = 0;
+ int j;
+ int l;
+ for (l = 0; l < params.length; l++) {
+ j = messagePattern.indexOf("{}", i);
+ if (j == -1) {
+ log.error("[doFormat][参数过多:错误码({})|错误内容({})|参数({})", code, messagePattern, params);
+ if (i == 0) {
+ return messagePattern;
+ } else {
+ sbuf.append(messagePattern.substring(i));
+ return sbuf.toString();
+ }
+ } else {
+ sbuf.append(messagePattern, i, j);
+ sbuf.append(params[l]);
+ i = j + 2;
+ }
+ }
+ if (messagePattern.indexOf("{}", i) != -1) {
+ log.error("[doFormat][参数过少:错误码({})|错误内容({})|参数({})", code, messagePattern, params);
+ }
+ sbuf.append(messagePattern.substring(i));
+ return sbuf.toString();
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/ApiRequestFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/ApiRequestFilter.java
new file mode 100644
index 00000000..ea1bb9e8
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/ApiRequestFilter.java
@@ -0,0 +1,30 @@
+package com.ruoyi.common.filter;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 过滤 /admin-api、/app-api 等 API 请求的过滤器
+ *
+ * @author 芋道源码
+ */
+@RequiredArgsConstructor
+public abstract class ApiRequestFilter extends OncePerRequestFilter {
+
+
+ @Override
+ protected boolean shouldNotFilter(HttpServletRequest request) {
+ if (StrUtil.startWith(request.getRequestURI(),"/profile/",false)) {
+ //静态资源,不需要走TenantSecurityWebFilter过滤器
+ return true;
+ }
+ // 只过滤 API 请求的地址
+// return !StrUtil.startWithAny(request.getRequestURI(), webProperties.getAdminApi().getPrefix(),
+// webProperties.getAppApi().getPrefix());
+ return false;
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java
new file mode 100644
index 00000000..a145789d
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.filter;
+
+import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
+
+/**
+ * 排除JSON敏感属性
+ *
+ * @author ruoyi
+ */
+public class PropertyPreExcludeFilter extends SimplePropertyPreFilter
+{
+ public PropertyPreExcludeFilter()
+ {
+ }
+
+ public PropertyPreExcludeFilter addExcludes(String... filters)
+ {
+ for (int i = 0; i < filters.length; i++)
+ {
+ this.getExcludes().add(filters[i]);
+ }
+ return this;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java
new file mode 100644
index 00000000..a1bcfe2a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java
@@ -0,0 +1,52 @@
+package com.ruoyi.common.filter;
+
+import java.io.IOException;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.http.MediaType;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * Repeatable 过滤器
+ *
+ * @author ruoyi
+ */
+public class RepeatableFilter implements Filter
+{
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException
+ {
+
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException
+ {
+ ServletRequest requestWrapper = null;
+ if (request instanceof HttpServletRequest
+ && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
+ {
+ requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
+ }
+ if (null == requestWrapper)
+ {
+ chain.doFilter(request, response);
+ }
+ else
+ {
+ chain.doFilter(requestWrapper, response);
+ }
+ }
+
+ @Override
+ public void destroy()
+ {
+
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
new file mode 100644
index 00000000..407d1ba4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
@@ -0,0 +1,76 @@
+package com.ruoyi.common.filter;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import com.ruoyi.common.utils.http.HttpHelper;
+import com.ruoyi.common.constant.Constants;
+
+/**
+ * 构建可重复读取inputStream的request
+ *
+ * @author ruoyi
+ */
+public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
+{
+ private final byte[] body;
+
+ public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
+ {
+ super(request);
+ request.setCharacterEncoding(Constants.UTF8);
+ response.setCharacterEncoding(Constants.UTF8);
+
+ body = HttpHelper.getBodyString(request).getBytes(Constants.UTF8);
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException
+ {
+ return new BufferedReader(new InputStreamReader(getInputStream()));
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException
+ {
+ final ByteArrayInputStream bais = new ByteArrayInputStream(body);
+ return new ServletInputStream()
+ {
+ @Override
+ public int read() throws IOException
+ {
+ return bais.read();
+ }
+
+ @Override
+ public int available() throws IOException
+ {
+ return body.length;
+ }
+
+ @Override
+ public boolean isFinished()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isReady()
+ {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener)
+ {
+
+ }
+ };
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java
new file mode 100644
index 00000000..9052f0da
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java
@@ -0,0 +1,75 @@
+package com.ruoyi.common.filter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.enums.HttpMethod;
+
+/**
+ * 防止XSS攻击的过滤器
+ *
+ * @author ruoyi
+ */
+public class XssFilter implements Filter
+{
+ /**
+ * 排除链接
+ */
+ public List excludes = new ArrayList<>();
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException
+ {
+ String tempExcludes = filterConfig.getInitParameter("excludes");
+ if (StringUtils.isNotEmpty(tempExcludes))
+ {
+ String[] url = tempExcludes.split(",");
+ for (int i = 0; url != null && i < url.length; i++)
+ {
+ excludes.add(url[i]);
+ }
+ }
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException
+ {
+ HttpServletRequest req = (HttpServletRequest) request;
+ HttpServletResponse resp = (HttpServletResponse) response;
+ if (handleExcludeURL(req, resp))
+ {
+ chain.doFilter(request, response);
+ return;
+ }
+ XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
+ chain.doFilter(xssRequest, response);
+ }
+
+ private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
+ {
+ String url = request.getServletPath();
+ String method = request.getMethod();
+ // GET DELETE 不过滤
+ if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method))
+ {
+ return true;
+ }
+ return StringUtils.matches(url, excludes);
+ }
+
+ @Override
+ public void destroy()
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
new file mode 100644
index 00000000..b1eeb65c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
@@ -0,0 +1,111 @@
+package com.ruoyi.common.filter;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import org.apache.commons.io.IOUtils;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.html.EscapeUtil;
+
+/**
+ * XSS过滤处理
+ *
+ * @author ruoyi
+ */
+public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
+{
+ /**
+ * @param request
+ */
+ public XssHttpServletRequestWrapper(HttpServletRequest request)
+ {
+ super(request);
+ }
+
+ @Override
+ public String[] getParameterValues(String name)
+ {
+ String[] values = super.getParameterValues(name);
+ if (values != null)
+ {
+ int length = values.length;
+ String[] escapseValues = new String[length];
+ for (int i = 0; i < length; i++)
+ {
+ // 防xss攻击和过滤前后空格
+ escapseValues[i] = EscapeUtil.clean(values[i]).trim();
+ }
+ return escapseValues;
+ }
+ return super.getParameterValues(name);
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException
+ {
+ // 非json类型,直接返回
+ if (!isJsonRequest())
+ {
+ return super.getInputStream();
+ }
+
+ // 为空,直接返回
+ String json = IOUtils.toString(super.getInputStream(), "utf-8");
+ if (StringUtils.isEmpty(json))
+ {
+ return super.getInputStream();
+ }
+
+ // xss过滤
+ json = EscapeUtil.clean(json).trim();
+ byte[] jsonBytes = json.getBytes("utf-8");
+ final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);
+ return new ServletInputStream()
+ {
+ @Override
+ public boolean isFinished()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isReady()
+ {
+ return true;
+ }
+
+ @Override
+ public int available() throws IOException
+ {
+ return jsonBytes.length;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener)
+ {
+ }
+
+ @Override
+ public int read() throws IOException
+ {
+ return bis.read();
+ }
+ };
+ }
+
+ /**
+ * 是否是Json请求
+ *
+ * @param request
+ */
+ public boolean isJsonRequest()
+ {
+ String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
+ return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/handler/JsonLongSetTypeHandler.java b/ruoyi-common/src/main/java/com/ruoyi/common/handler/JsonLongSetTypeHandler.java
new file mode 100644
index 00000000..80d546bf
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/handler/JsonLongSetTypeHandler.java
@@ -0,0 +1,31 @@
+package com.ruoyi.common.handler;
+
+import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.ruoyi.common.utils.JsonUtils;
+
+import java.util.Set;
+
+/**
+ * 参考 {@link com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler} 实现
+ * 在我们将字符串反序列化为 Set 并且泛型为 Long 时,如果每个元素的数值太小,会被处理成 Integer 类型,导致可能存在隐性的 BUG。
+ *
+ * 例如说哦,SysUserDO 的 postIds 属性
+ *
+ * hasPermi
+ */
+public class JsonLongSetTypeHandler extends AbstractJsonTypeHandler {
+
+ private static final TypeReference> typeReference = new TypeReference>(){};
+
+ @Override
+ protected Object parse(String json) {
+ return JsonUtils.parseObject(json, typeReference);
+ }
+
+ @Override
+ protected String toJson(Object obj) {
+ return JsonUtils.toJsonString(obj);
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/dataobject/BaseDO.java b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/dataobject/BaseDO.java
new file mode 100644
index 00000000..43bbb1d1
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/dataobject/BaseDO.java
@@ -0,0 +1,68 @@
+package com.ruoyi.common.mybatis.dataobject;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import lombok.Data;
+import org.apache.ibatis.type.JdbcType;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 基础实体对象
+ *
+ * hasPermi
+ */
+@Data
+public abstract class BaseDO implements Serializable {
+
+ /**
+ * 创建时间
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private Date createTime;
+ /**
+ * 最后更新时间
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Date updateTime;
+ /**
+ * 创建者,目前使用 SysUser 的 id 编号
+ *
+ * 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。
+ */
+ @TableField(fill = FieldFill.INSERT, jdbcType = JdbcType.VARCHAR)
+ private String creator;
+ /**
+ * 更新者,目前使用 SysUser 的 id 编号
+ *
+ * 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.VARCHAR)
+ private String updater;
+ /**
+ * 是否删除
+ */
+ @TableLogic
+ private Boolean deleted;
+ /** 请求参数 */
+ @TableField(exist = false)
+ private Map params ;
+
+ public Map getParams()
+ {
+ if (params == null)
+ {
+ params = new HashMap<>();
+ }
+ return params;
+ }
+
+ public void setParams(Map params)
+ {
+ this.params = params;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/handler/DefaultDBFieldHandler.java b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/handler/DefaultDBFieldHandler.java
new file mode 100644
index 00000000..b4797ca3
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/handler/DefaultDBFieldHandler.java
@@ -0,0 +1,87 @@
+package com.ruoyi.common.mybatis.handler;
+
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.ruoyi.common.mybatis.dataobject.BaseDO;
+import com.ruoyi.common.utils.SecurityUtils;
+import org.apache.ibatis.reflection.MetaObject;
+
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * 通用参数填充实现类
+ *
+ * 如果没有显式的对通用参数进行赋值,这里会对通用参数进行填充、赋值
+ *
+ * @author hexiaowu
+ */
+public class DefaultDBFieldHandler implements MetaObjectHandler {
+
+ @Override
+ public void insertFill(MetaObject metaObject) {
+ if (Objects.nonNull(metaObject)) {
+ if (metaObject.getOriginalObject() instanceof BaseDO) {
+ BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();
+
+ Date current = new Date();
+ // 创建时间为空,则以当前时间为插入时间
+ if (Objects.isNull(baseDO.getCreateTime())) {
+ baseDO.setCreateTime(current);
+ }
+ // 更新时间为空,则以当前时间为更新时间
+ if (Objects.isNull(baseDO.getUpdateTime())) {
+ baseDO.setUpdateTime(current);
+ }
+
+ Long userId = SecurityUtils.getLoginUserId();
+ // 当前登录用户不为空,创建人为空,则当前登录用户为创建人
+ if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())) {
+ baseDO.setCreator(userId.toString());
+ }
+ // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
+ if (Objects.nonNull(userId) && Objects.isNull(baseDO.getUpdater())) {
+ baseDO.setUpdater(userId.toString());
+ }
+ }
+ //创建人
+ Object createBy = getFieldValByName("createBy", metaObject);
+ String username = SecurityUtils.getUsernameNoExcePtion();
+ if (Objects.nonNull(username) && Objects.isNull(createBy)) {
+ setFieldValByName("updateBy", username, metaObject);
+ setFieldValByName("createBy", username, metaObject);
+ }
+ if (metaObject.hasGetter("updateTime") && metaObject.getValue("updateTime") == null) {
+ setFieldValByName("updateTime", new Date(), metaObject);
+ }
+ //强制设置租户字段
+// String tenantId = metaObject.findProperty("tenantId", true);
+// if (StrUtil.isNotBlank(tenantId)) {
+// setFieldValByName(tenantId, TenantContextHolder, metaObject);
+// }
+// System.out.println(1);
+ }
+ }
+
+ @Override
+ public void updateFill(MetaObject metaObject) {
+ // 更新时间为空,则以当前时间为更新时间
+ Object modifyTime = getFieldValByName("updateTime", metaObject);
+ if (Objects.isNull(modifyTime)) {
+ setFieldValByName("updateTime", new Date(), metaObject);
+ }
+
+ // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
+ Object modifier = getFieldValByName("updater", metaObject);
+ Long userId = SecurityUtils.getLoginUserId();
+ if (Objects.nonNull(userId) && Objects.isNull(modifier)) {
+ setFieldValByName("updater", userId.toString(), metaObject);
+ }
+ // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
+ Object updateBy = getFieldValByName("updateBy", metaObject);
+ String username = SecurityUtils.getUsernameNoExcePtion();
+ if (Objects.nonNull(username) && Objects.isNull(updateBy)) {
+ setFieldValByName("updateBy", username, metaObject);
+ }
+ //强制设置租户字段
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/mapper/BaseMapperX.java b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/mapper/BaseMapperX.java
new file mode 100644
index 00000000..667af281
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/mapper/BaseMapperX.java
@@ -0,0 +1,94 @@
+package com.ruoyi.common.mybatis.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import com.ruoyi.common.mybatis.pojo.PageParam;
+import com.ruoyi.common.mybatis.pojo.PageResult;
+import com.ruoyi.common.mybatis.util.MyBatisUtils;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力
+ */
+public interface BaseMapperX extends BaseMapper {
+
+ default PageResult selectPage(PageParam pageParam, @Param("ew") Wrapper queryWrapper) {
+ // MyBatis Plus 查询
+ IPage mpPage = MyBatisUtils.buildPage(pageParam);
+ selectPage(mpPage, queryWrapper);
+ // 转换返回
+ return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
+ }
+
+ default T selectOne(String field, Object value) {
+ return selectOne(new QueryWrapper().eq(field, value));
+ }
+
+ default T selectOne(SFunction field, Object value) {
+ return selectOne(new LambdaQueryWrapper().eq(field, value));
+ }
+
+ default T selectOne(String field1, Object value1, String field2, Object value2) {
+ return selectOne(new QueryWrapper().eq(field1, value1).eq(field2, value2));
+ }
+
+ default T selectOne(SFunction field1, Object value1, SFunction field2, Object value2) {
+ return selectOne(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2));
+ }
+
+ default Long selectCount() {
+ return selectCount(new QueryWrapper());
+ }
+
+ default Long selectCount(String field, Object value) {
+ return selectCount(new QueryWrapper().eq(field, value));
+ }
+
+ default Long selectCount(SFunction field, Object value) {
+ return selectCount(new LambdaQueryWrapper().eq(field, value));
+ }
+
+ default List selectList() {
+ return selectList(new QueryWrapper<>());
+ }
+
+ default List selectList(String field, Object value) {
+ return selectList(new QueryWrapper().eq(field, value));
+ }
+
+ default List selectList(SFunction field, Object value) {
+ return selectList(new LambdaQueryWrapper().eq(field, value));
+ }
+
+ default List selectList(String field, Collection> values) {
+ return selectList(new QueryWrapper().in(field, values));
+ }
+
+ default List selectList(SFunction field, Collection> values) {
+ return selectList(new LambdaQueryWrapper().in(field, values));
+ }
+
+ /**
+ * 逐条插入,适合少量数据插入,或者对性能要求不高的场景
+ *
+ * 如果大量,请使用 {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#saveBatch(Collection)} 方法
+ * 使用示例,可见 RoleMenuBatchInsertMapper、UserRoleBatchInsertMapper 类
+ *
+ * @param entities 实体们
+ */
+ default void insertBatch(Collection entities) {
+ entities.forEach(this::insert);
+ }
+
+ default void updateBatch(T update) {
+ update(update, new QueryWrapper<>());
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/pojo/PageParam.java b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/pojo/PageParam.java
new file mode 100644
index 00000000..0d8df561
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/pojo/PageParam.java
@@ -0,0 +1,30 @@
+package com.ruoyi.common.mybatis.pojo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+@ApiModel("分页参数")
+@Data
+public class PageParam implements Serializable {
+
+ private static final Integer PAGE_NO = 1;
+ private static final Integer PAGE_SIZE = 10;
+
+ @ApiModelProperty(value = "页码,从 1 开始", required = true,example = "1")
+ @NotNull(message = "页码不能为空")
+ @Min(value = 1, message = "页码最小值为 1")
+ private Integer pageNo = PAGE_NO;
+
+ @ApiModelProperty(value = "每页条数,最大值为 100", required = true, example = "10")
+ @NotNull(message = "每页条数不能为空")
+ @Min(value = 1, message = "每页条数最小值为 1")
+ @Max(value = 100, message = "每页条数最大值为 100")
+ private Integer pageSize = PAGE_SIZE;
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/pojo/PageResult.java b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/pojo/PageResult.java
new file mode 100644
index 00000000..a20fb18f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/pojo/PageResult.java
@@ -0,0 +1,42 @@
+package com.ruoyi.common.mybatis.pojo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+@ApiModel("分页结果")
+@Data
+public final class PageResult implements Serializable {
+
+ @ApiModelProperty(value = "数据", required = true)
+ private List list;
+
+ @ApiModelProperty(value = "总量", required = true)
+ private Long total;
+
+ public PageResult() {
+ }
+
+ public PageResult(List list, Long total) {
+ this.list = list;
+ this.total = total;
+ }
+
+ public PageResult(Long total) {
+ this.list = new ArrayList<>();
+ this.total = total;
+ }
+
+ public static PageResult empty() {
+ return new PageResult<>(0L);
+ }
+
+ public static PageResult empty(Long total) {
+ return new PageResult<>(total);
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/pojo/SortingField.java b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/pojo/SortingField.java
new file mode 100644
index 00000000..fbe472f8
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/pojo/SortingField.java
@@ -0,0 +1,56 @@
+package com.ruoyi.common.mybatis.pojo;
+
+import java.io.Serializable;
+
+/**
+ * 排序字段 DTO
+ *
+ * 类名加了 ing 的原因是,避免和 ES SortField 重名。
+ */
+public class SortingField implements Serializable {
+
+ /**
+ * 顺序 - 升序
+ */
+ public static final String ORDER_ASC = "asc";
+ /**
+ * 顺序 - 降序
+ */
+ public static final String ORDER_DESC = "desc";
+
+ /**
+ * 字段
+ */
+ private String field;
+ /**
+ * 顺序
+ */
+ private String order;
+
+ // 空构造方法,解决反序列化
+ public SortingField() {
+ }
+
+ public SortingField(String field, String order) {
+ this.field = field;
+ this.order = order;
+ }
+
+ public String getField() {
+ return field;
+ }
+
+ public SortingField setField(String field) {
+ this.field = field;
+ return this;
+ }
+
+ public String getOrder() {
+ return order;
+ }
+
+ public SortingField setOrder(String order) {
+ this.order = order;
+ return this;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/query/LambdaQueryWrapperX.java b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/query/LambdaQueryWrapperX.java
new file mode 100644
index 00000000..b6abbcac
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/query/LambdaQueryWrapperX.java
@@ -0,0 +1,135 @@
+package com.ruoyi.common.mybatis.query;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import com.ruoyi.common.utils.collection.ArrayUtils;
+import org.springframework.util.StringUtils;
+
+import java.util.Collection;
+
+/**
+ * 拓展 MyBatis Plus QueryWrapper 类,主要增加如下功能:
+ *
+ * 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。
+ *
+ * @param 数据类型
+ */
+public class LambdaQueryWrapperX