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(systemBusinessConfig.getName(), null, null))
+ // 版本
+ .version("版本号:" + systemBusinessConfig.getVersion())
+ .build();
+ }
+}
diff --git a/postdischarge-admin/src/main/resources/META-INF/spring-devtools.properties b/postdischarge-admin/src/main/resources/META-INF/spring-devtools.properties
new file mode 100644
index 00000000..2b23f85a
--- /dev/null
+++ b/postdischarge-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/postdischarge-admin/src/main/resources/application-dev.yml b/postdischarge-admin/src/main/resources/application-dev.yml
new file mode 100644
index 00000000..f168146f
--- /dev/null
+++ b/postdischarge-admin/src/main/resources/application-dev.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/post-discharge?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: admin
+ 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
\ No newline at end of file
diff --git a/postdischarge-admin/src/main/resources/application-prod.yml b/postdischarge-admin/src/main/resources/application-prod.yml
new file mode 100644
index 00000000..f168146f
--- /dev/null
+++ b/postdischarge-admin/src/main/resources/application-prod.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/post-discharge?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: admin
+ 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
\ No newline at end of file
diff --git a/postdischarge-admin/src/main/resources/application.yml b/postdischarge-admin/src/main/resources/application.yml
new file mode 100644
index 00000000..e40edc54
--- /dev/null
+++ b/postdischarge-admin/src/main/resources/application.yml
@@ -0,0 +1,171 @@
+# 项目相关配置
+xinelu:
+ # 名称
+ name: postdischarge
+ # 版本GlobalExceptionHandler
+ version: 0.0.1
+ # 版权年份
+ copyrightYear: 2024
+ # 实例演示开关
+ demoEnabled: true
+ # 文件路径 示例( Windows配置D:/postdischarge/uploadPath,Linux配置 /home/postdischarge/uploadPath)
+ profile: D:/postdischarge/uploadPath
+ # 获取ip地址开关
+ addressEnabled: false
+ # 验证码类型 math 数组计算 char 字符验证
+ captchaType: math
+
+# 开发环境配置
+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.xinelu: debug
+ org.springframework: warn
+
+# Spring配置
+spring:
+ # 资源信息
+ messages:
+ # 国际化资源文件路径
+ basename: i18n/messages
+ profiles:
+ active: dev
+ # 文件上传
+ servlet:
+ multipart:
+ # 单个文件大小
+ max-file-size: 10MB
+ # 设置总上传的文件大小
+ max-request-size: 20MB
+ # 服务模块
+ devtools:
+ restart:
+ # 热部署开关
+ enabled: true
+ # redis 配置
+ redis:
+ # 地址
+ host: localhost
+ # 端口,默认为6379
+ port: 6379
+ # 数据库索引
+ database: 6
+ # 密码
+ password: xinelu@6990
+ # 连接超时时间
+ timeout: 10s
+ lettuce:
+ pool:
+ # 连接池中的最小空闲连接
+ min-idle: 0
+ # 连接池中的最大空闲连接
+ max-idle: 8
+ # 连接池的最大数据库连接数
+ max-active: 8
+ # #连接池最大阻塞等待时间(使用负值表示没有限制)
+ max-wait: -1ms
+
+# token配置
+token:
+ # 令牌自定义标识
+ header: Authorization
+ # 令牌密钥
+ secret: DIweGcEWJTbvo48dnvOMR8GsDW
+ # 令牌有效期(默认30分钟)
+ expireTime: 30
+
+## MyBatis-Plus配置
+mybatis-plus:
+ # 实体扫描,多个package用逗号或者分号分隔
+ typeAliasesPackage: com.xinelu.**.domain
+ # 对应的 XML 文件位置
+ mapperLocations: classpath*:mapper/**/*Mapper.xml
+ # 启动时是否检查 MyBatis XML 文件的存在,默认不检查
+ checkConfigLocation: false
+ # 通过该属性可指定 MyBatis 的执行器,MyBatis 的执行器总共有三种
+ executorType: SIMPLE
+ # 指定外部化 MyBatis Properties 配置,通过该配置可以抽离配置,实现不同环境的配置部署
+ configurationProperties: null
+ configuration:
+ # 自动驼峰命名规则(camel case)映射
+ mapUnderscoreToCamelCase: true
+ # 默认枚举处理类,如果配置了该属性,枚举将统一使用指定处理器进行处理
+ defaultEnumTypeHandler: org.apache.ibatis.type.EnumTypeHandler
+ # 当设置为 true 的时候,懒加载的对象可能被任何懒属性全部加载,否则,每个属性都按需加载。需要和 lazyLoadingEnabled 一起使用。
+ aggressiveLazyLoading: true
+ # MyBatis 自动映射策略
+ autoMappingBehavior: PARTIAL
+ # MyBatis 自动映射时未知列或未知属性处理策
+ autoMappingUnknownColumnBehavior: NONE
+ # Mybatis一级缓存,默认为 SESSION
+ localCacheScope: SESSION
+ # 开启Mybatis二级缓存,默认为 true
+ cacheEnabled: true
+ global-config:
+ # 是否打印 Logo banner
+ banner: true
+ # 是否初始化 SqlRunner
+ enableSqlRunner: false
+ dbConfig:
+ # 主键类型
+ idType: AUTO
+ # 表名前缀
+ tablePrefix: null
+ # 字段 format,例: %s,(对主键无效)
+ columnFormat: null
+ # 表名是否使用驼峰转下划线命名,只对表名生效
+ tableUnderline: true
+ # 大写命名,对表名和字段名均生效
+ capitalMode: false
+ # 全局的entity的逻辑删除字段属性名
+ logicDeleteField: null
+ # 逻辑已删除值
+ logicDeleteValue: 1
+ # 逻辑未删除值
+ logicNotDeleteValue: 0
+ # 字段验证策略之 insert,在 insert 的时候的字段验证策略
+ insertStrategy: NOT_NULL
+ # 字段验证策略之 update,在 update 的时候的字段验证策略
+ updateStrategy: NOT_NULL
+ # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
+ selectStrategy: NOT_NULL
+
+# PageHelper分页插件
+pagehelper:
+ helperDialect: mysql
+ reasonable: true
+ supportMethodsArguments: true
+ params: count=countSql
+
+# Swagger配置
+swagger:
+ # 是否开启swagger
+ enabled: true
+ # 请求前缀
+ pathMapping: /dev-api
+
+# 防止XSS攻击
+xss:
+ # 过滤开关
+ enabled: true
+ # 排除链接(多个用逗号分隔)
+ excludes: /system/notice
+ # 匹配链接
+ urlPatterns: /system/*,/monitor/*,/tool/*
diff --git a/postdischarge-admin/src/main/resources/banner.txt b/postdischarge-admin/src/main/resources/banner.txt
new file mode 100644
index 00000000..d48b9dad
--- /dev/null
+++ b/postdischarge-admin/src/main/resources/banner.txt
@@ -0,0 +1,9 @@
+Application Version: ${xinelu.version}
+Spring Boot Version: ${spring-boot.version}
+ . ____ _ __ _ _
+/\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
+( ( )___ | '_ | '_| | '_ / _` | \ \ \ \
+ \/ ___)| |_)| | | | | || (_| | ) ) ) )
+ ' |____| .__|_| |_|_| |___, | / / / /
+ =========|_|==============|___/=/_/_/_/
+ :: Spring Boot :: (v${spring-boot.version})
\ No newline at end of file
diff --git a/postdischarge-admin/src/main/resources/i18n/messages.properties b/postdischarge-admin/src/main/resources/i18n/messages.properties
new file mode 100644
index 00000000..ede2df8c
--- /dev/null
+++ b/postdischarge-admin/src/main/resources/i18n/messages.properties
@@ -0,0 +1,32 @@
+#错误消息
+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}次,帐户锁定10分钟
+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/postdischarge-admin/src/main/resources/logback.xml b/postdischarge-admin/src/main/resources/logback.xml
new file mode 100644
index 00000000..2a123dad
--- /dev/null
+++ b/postdischarge-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/postdischarge-admin/src/main/resources/mybatis/mybatis-config.xml b/postdischarge-admin/src/main/resources/mybatis/mybatis-config.xml
new file mode 100644
index 00000000..b0c7ce73
--- /dev/null
+++ b/postdischarge-admin/src/main/resources/mybatis/mybatis-config.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/postdischarge-common/pom.xml b/postdischarge-common/pom.xml
new file mode 100644
index 00000000..f64df95d
--- /dev/null
+++ b/postdischarge-common/pom.xml
@@ -0,0 +1,116 @@
+
+
+
+ com.xinelu
+ postdischarge
+ 0.0.1
+
+ 4.0.0
+
+ postdischarge-common
+
+
+ common通用工具
+
+
+
+
+
+ org.springframework
+ spring-context-support
+
+
+
+ org.springframework
+ spring-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ com.github.pagehelper
+ pagehelper-spring-boot-starter
+
+
+
+ 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
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+ eu.bitwalker
+ UserAgentUtils
+
+
+
+ javax.servlet
+ javax.servlet-api
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
\ No newline at end of file
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/annotation/Anonymous.java b/postdischarge-common/src/main/java/com/xinelu/common/annotation/Anonymous.java
new file mode 100644
index 00000000..c5a5c1fa
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/annotation/Anonymous.java
@@ -0,0 +1,14 @@
+package com.xinelu.common.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 匿名访问不鉴权注解
+ *
+ * @author xinelu
+ */
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Anonymous {
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/annotation/DataScope.java b/postdischarge-common/src/main/java/com/xinelu/common/annotation/DataScope.java
new file mode 100644
index 00000000..393771f7
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/annotation/DataScope.java
@@ -0,0 +1,23 @@
+package com.xinelu.common.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 数据权限过滤注解
+ *
+ * @author xinelu
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataScope {
+ /**
+ * 部门表的别名
+ */
+ public String deptAlias() default "";
+
+ /**
+ * 用户表的别名
+ */
+ public String userAlias() default "";
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/annotation/DataSource.java b/postdischarge-common/src/main/java/com/xinelu/common/annotation/DataSource.java
new file mode 100644
index 00000000..6103a7be
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/annotation/DataSource.java
@@ -0,0 +1,23 @@
+package com.xinelu.common.annotation;
+
+import com.xinelu.common.enums.DataSourceType;
+
+import java.lang.annotation.*;
+
+/**
+ * 自定义多数据源切换注解
+ *
+ * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
+ *
+ * @author xinelu
+ */
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface DataSource {
+ /**
+ * 切换数据源名称
+ */
+ public DataSourceType value() default DataSourceType.MASTER;
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/annotation/Excel.java b/postdischarge-common/src/main/java/com/xinelu/common/annotation/Excel.java
new file mode 100644
index 00000000..962e5a74
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/annotation/Excel.java
@@ -0,0 +1,174 @@
+package com.xinelu.common.annotation;
+
+import com.xinelu.common.utils.poi.ExcelHandlerAdapter;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.math.BigDecimal;
+
+/**
+ * 自定义导出Excel数据注解
+ *
+ * @author xinelu
+ */
+@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 {};
+
+ /**
+ * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
+ */
+ public boolean isExport() default true;
+
+ /**
+ * 另一个类中的属性名称,支持多级获取,以小数点隔开
+ */
+ public String targetAttr() default "";
+
+ /**
+ * 是否自动统计数据,在最后追加一行统计数据总和
+ */
+ public boolean isStatistics() default false;
+
+ /**
+ * 导出类型(0数字 1字符串)
+ */
+ public ColumnType cellType() default ColumnType.STRING;
+
+ /**
+ * 导出字体颜色
+ */
+ public IndexedColors color() default IndexedColors.BLACK;
+
+ /**
+ * 导出字段对齐方式
+ */
+ public HorizontalAlignment align() default HorizontalAlignment.CENTER;
+
+ /**
+ * 自定义数据处理器
+ */
+ public Class> handler() default ExcelHandlerAdapter.class;
+
+ /**
+ * 自定义数据处理器参数
+ */
+ public String[] args() default {};
+
+ public enum Align {
+ AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
+ private final int value;
+
+ Align(int value) {
+ this.value = value;
+ }
+
+ public int value() {
+ return this.value;
+ }
+ }
+
+ /**
+ * 字段类型(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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/annotation/Excels.java b/postdischarge-common/src/main/java/com/xinelu/common/annotation/Excels.java
new file mode 100644
index 00000000..979eb099
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/annotation/Excels.java
@@ -0,0 +1,17 @@
+package com.xinelu.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Excel注解集
+ *
+ * @author xinelu
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Excels {
+ public Excel[] value();
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/annotation/Log.java b/postdischarge-common/src/main/java/com/xinelu/common/annotation/Log.java
new file mode 100644
index 00000000..5ed73021
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/annotation/Log.java
@@ -0,0 +1,41 @@
+package com.xinelu.common.annotation;
+
+import com.xinelu.common.enums.BusinessType;
+import com.xinelu.common.enums.OperatorType;
+
+import java.lang.annotation.*;
+
+/**
+ * 自定义操作日志记录注解
+ *
+ * @author xinelu
+ */
+@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/postdischarge-common/src/main/java/com/xinelu/common/annotation/RateLimiter.java b/postdischarge-common/src/main/java/com/xinelu/common/annotation/RateLimiter.java
new file mode 100644
index 00000000..0bd14893
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/annotation/RateLimiter.java
@@ -0,0 +1,36 @@
+package com.xinelu.common.annotation;
+
+import com.xinelu.common.constant.CacheConstants;
+import com.xinelu.common.enums.LimitType;
+
+import java.lang.annotation.*;
+
+/**
+ * 限流注解
+ *
+ * @author xinelu
+ */
+@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/postdischarge-common/src/main/java/com/xinelu/common/annotation/RepeatSubmit.java b/postdischarge-common/src/main/java/com/xinelu/common/annotation/RepeatSubmit.java
new file mode 100644
index 00000000..b4ef238a
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/annotation/RepeatSubmit.java
@@ -0,0 +1,24 @@
+package com.xinelu.common.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 自定义注解防止表单重复提交
+ *
+ * @author xinelu
+ */
+@Inherited
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RepeatSubmit {
+ /**
+ * 间隔时间(ms),小于此时间视为重复提交
+ */
+ public int interval() default 5000;
+
+ /**
+ * 提示消息
+ */
+ public String message() default "不允许重复提交,请稍候再试";
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/config/SystemBusinessConfig.java b/postdischarge-common/src/main/java/com/xinelu/common/config/SystemBusinessConfig.java
new file mode 100644
index 00000000..0b6559f5
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/config/SystemBusinessConfig.java
@@ -0,0 +1,132 @@
+package com.xinelu.common.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 读取项目相关配置
+ *
+ * @author xinelu
+ */
+@Component
+@ConfigurationProperties(prefix = "xinelu")
+public class SystemBusinessConfig {
+ /**
+ * 项目名称
+ */
+ 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) {
+ SystemBusinessConfig.profile = profile;
+ }
+
+ public static boolean isAddressEnabled() {
+ return addressEnabled;
+ }
+
+ public void setAddressEnabled(boolean addressEnabled) {
+ SystemBusinessConfig.addressEnabled = addressEnabled;
+ }
+
+ public static String getCaptchaType() {
+ return captchaType;
+ }
+
+ public void setCaptchaType(String captchaType) {
+ SystemBusinessConfig.captchaType = captchaType;
+ }
+
+ /**
+ * 获取导入上传路径
+ */
+ public static String getImportPath() {
+ return getProfile() + "/import";
+ }
+
+ /**
+ * 获取头像上传路径
+ */
+ public static String getAvatarPath() {
+ return getProfile() + "/avatar";
+ }
+
+ /**
+ * 获取下载路径
+ */
+ public static String getDownloadPath() {
+ return getProfile() + "/download/";
+ }
+
+ /**
+ * 获取上传路径
+ */
+ public static String getUploadPath() {
+ return getProfile() + "/upload";
+ }
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/constant/CacheConstants.java b/postdischarge-common/src/main/java/com/xinelu/common/constant/CacheConstants.java
new file mode 100644
index 00000000..11966287
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/constant/CacheConstants.java
@@ -0,0 +1,38 @@
+package com.xinelu.common.constant;
+
+/**
+ * 缓存的key 常量
+ *
+ * @author xinelu
+ */
+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:";
+
+ /**
+ * 防重提交 redis key
+ */
+ public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
+
+ /**
+ * 限流 redis key
+ */
+ public static final String RATE_LIMIT_KEY = "rate_limit:";
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/constant/Constants.java b/postdischarge-common/src/main/java/com/xinelu/common/constant/Constants.java
new file mode 100644
index 00000000..0be737ca
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/constant/Constants.java
@@ -0,0 +1,136 @@
+package com.xinelu.common.constant;
+
+import io.jsonwebtoken.Claims;
+
+/**
+ * 通用常量信息
+ *
+ * @author xinelu
+ */
+public class Constants {
+ /**
+ * UTF-8 字符集
+ */
+ public static final String UTF8 = "UTF-8";
+
+ /**
+ * GBK 字符集
+ */
+ public static final String GBK = "GBK";
+
+ /**
+ * 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";
+
+ /**
+ * 登录成功
+ */
+ 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.xinelu"};
+
+ /**
+ * 定时任务违规的字符
+ */
+ public static final String[] JOB_ERROR_STR = {"java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
+ "org.springframework", "org.apache", "com.xinelu.common.utils.file"};
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/constant/GenConstants.java b/postdischarge-common/src/main/java/com/xinelu/common/constant/GenConstants.java
new file mode 100644
index 00000000..4be6671e
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/constant/GenConstants.java
@@ -0,0 +1,186 @@
+package com.xinelu.common.constant;
+
+/**
+ * 代码生成通用常量
+ *
+ * @author xinelu
+ */
+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/postdischarge-common/src/main/java/com/xinelu/common/constant/HttpStatus.java b/postdischarge-common/src/main/java/com/xinelu/common/constant/HttpStatus.java
new file mode 100644
index 00000000..bea70afa
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/constant/HttpStatus.java
@@ -0,0 +1,89 @@
+package com.xinelu.common.constant;
+
+/**
+ * 返回状态码
+ *
+ * @author xinelu
+ */
+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;
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/constant/ScheduleConstants.java b/postdischarge-common/src/main/java/com/xinelu/common/constant/ScheduleConstants.java
new file mode 100644
index 00000000..659afea6
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/constant/ScheduleConstants.java
@@ -0,0 +1,56 @@
+package com.xinelu.common.constant;
+
+/**
+ * 任务调度通用常量
+ *
+ * @author xinelu
+ */
+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/postdischarge-common/src/main/java/com/xinelu/common/constant/UserConstants.java b/postdischarge-common/src/main/java/com/xinelu/common/constant/UserConstants.java
new file mode 100644
index 00000000..4d996955
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/constant/UserConstants.java
@@ -0,0 +1,111 @@
+package com.xinelu.common.constant;
+
+/**
+ * 用户常量信息
+ *
+ * @author xinelu
+ */
+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/postdischarge-common/src/main/java/com/xinelu/common/core/controller/BaseController.java b/postdischarge-common/src/main/java/com/xinelu/common/core/controller/BaseController.java
new file mode 100644
index 00000000..a44a6cca
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/controller/BaseController.java
@@ -0,0 +1,167 @@
+package com.xinelu.common.core.controller;
+
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.xinelu.common.core.domain.model.LoginUser;
+import com.xinelu.common.utils.sql.SqlUtil;
+import com.xinelu.common.constant.HttpStatus;
+import com.xinelu.common.core.domain.AjaxResult;
+import com.xinelu.common.core.page.PageDomain;
+import com.xinelu.common.core.page.TableDataInfo;
+import com.xinelu.common.core.page.TableSupport;
+import com.xinelu.common.utils.DateUtils;
+import com.xinelu.common.utils.PageUtils;
+import com.xinelu.common.utils.SecurityUtils;
+import com.xinelu.common.utils.StringUtils;
+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 xinelu
+ */
+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 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 error(String message) {
+ return AjaxResult.error(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/postdischarge-common/src/main/java/com/xinelu/common/core/domain/AjaxResult.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/AjaxResult.java
new file mode 100644
index 00000000..1d0590fc
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/AjaxResult.java
@@ -0,0 +1,155 @@
+package com.xinelu.common.core.domain;
+
+import com.xinelu.common.constant.HttpStatus;
+import com.xinelu.common.utils.StringUtils;
+
+import java.util.HashMap;
+
+/**
+ * 操作消息提醒
+ *
+ * @author xinelu
+ */
+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);
+ }
+
+ /**
+ * 返回错误消息
+ *
+ * @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;
+ }
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/core/domain/BaseEntity.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/BaseEntity.java
new file mode 100644
index 00000000..233f18ca
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/BaseEntity.java
@@ -0,0 +1,113 @@
+package com.xinelu.common.core.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Entity基类
+ *
+ * @author xinelu
+ */
+public class BaseEntity implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 搜索值
+ */
+ private String searchValue;
+
+ /**
+ * 创建者
+ */
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date createTime;
+
+ /**
+ * 更新者
+ */
+ private String updateBy;
+
+ /**
+ * 更新时间
+ */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date updateTime;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 请求参数
+ */
+ 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/postdischarge-common/src/main/java/com/xinelu/common/core/domain/R.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/R.java
new file mode 100644
index 00000000..ffffb4e7
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/R.java
@@ -0,0 +1,94 @@
+package com.xinelu.common.core.domain;
+
+import com.xinelu.common.constant.HttpStatus;
+
+import java.io.Serializable;
+
+/**
+ * 响应信息主体
+ *
+ * @author xinelu
+ */
+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;
+ }
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/core/domain/TreeEntity.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/TreeEntity.java
new file mode 100644
index 00000000..7f079f7b
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/TreeEntity.java
@@ -0,0 +1,78 @@
+package com.xinelu.common.core.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tree基类
+ *
+ * @author xinelu
+ */
+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/postdischarge-common/src/main/java/com/xinelu/common/core/domain/TreeSelect.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/TreeSelect.java
new file mode 100644
index 00000000..a590cfa1
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/TreeSelect.java
@@ -0,0 +1,74 @@
+package com.xinelu.common.core.domain;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.xinelu.common.core.domain.entity.SysDept;
+import com.xinelu.common.core.domain.entity.SysMenu;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Treeselect树结构实体类
+ *
+ * @author xinelu
+ */
+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/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysDept.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysDept.java
new file mode 100644
index 00000000..be1fb763
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysDept.java
@@ -0,0 +1,203 @@
+package com.xinelu.common.core.domain.entity;
+
+import com.xinelu.common.core.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 部门表 sys_dept
+ *
+ * @author xinelu
+ */
+public class SysDept extends BaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 部门ID
+ */
+ 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;
+
+ /**
+ * 父部门名称
+ */
+ private String parentName;
+
+ /**
+ * 子部门
+ */
+ 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;
+ }
+
+ @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/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysDictData.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysDictData.java
new file mode 100644
index 00000000..93543e5b
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysDictData.java
@@ -0,0 +1,175 @@
+package com.xinelu.common.core.domain.entity;
+
+import com.xinelu.common.annotation.Excel;
+import com.xinelu.common.annotation.Excel.ColumnType;
+import com.xinelu.common.constant.UserConstants;
+import com.xinelu.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.Size;
+
+/**
+ * 字典数据表 sys_dict_data
+ *
+ * @author xinelu
+ */
+public class SysDictData extends BaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 字典编码
+ */
+ @Excel(name = "字典编码", cellType = ColumnType.NUMERIC)
+ 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) ? true : false;
+ }
+
+ 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/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysDictType.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysDictType.java
new file mode 100644
index 00000000..8fa36de5
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysDictType.java
@@ -0,0 +1,96 @@
+package com.xinelu.common.core.domain.entity;
+
+import com.xinelu.common.annotation.Excel;
+import com.xinelu.common.annotation.Excel.ColumnType;
+import com.xinelu.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.Pattern;
+import javax.validation.constraints.Size;
+
+/**
+ * 字典类型表 sys_dict_type
+ *
+ * @author xinelu
+ */
+public class SysDictType extends BaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 字典主键
+ */
+ @Excel(name = "字典主键", cellType = ColumnType.NUMERIC)
+ 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/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysMenu.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysMenu.java
new file mode 100644
index 00000000..650ec9ed
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysMenu.java
@@ -0,0 +1,259 @@
+package com.xinelu.common.core.domain.entity;
+
+import com.xinelu.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 xinelu
+ */
+public class SysMenu extends BaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 菜单ID
+ */
+ private Long menuId;
+
+ /**
+ * 菜单名称
+ */
+ private String menuName;
+
+ /**
+ * 父菜单名称
+ */
+ private String parentName;
+
+ /**
+ * 父菜单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;
+
+ /**
+ * 子菜单
+ */
+ 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 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;
+ }
+
+ @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/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysRole.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysRole.java
new file mode 100644
index 00000000..dd55e073
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysRole.java
@@ -0,0 +1,222 @@
+package com.xinelu.common.core.domain.entity;
+
+import com.xinelu.common.annotation.Excel;
+import com.xinelu.common.annotation.Excel.ColumnType;
+import com.xinelu.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.Size;
+
+/**
+ * 角色表 sys_role
+ *
+ * @author xinelu
+ */
+public class SysRole extends BaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 角色ID
+ */
+ @Excel(name = "角色序号", cellType = ColumnType.NUMERIC)
+ 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;
+
+ /**
+ * 用户是否存在此角色标识 默认不存在
+ */
+ private boolean flag = false;
+
+ /**
+ * 菜单组
+ */
+ private Long[] menuIds;
+
+ /**
+ * 部门组(数据权限)
+ */
+ private Long[] deptIds;
+
+ 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;
+ }
+
+ @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/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysUser.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysUser.java
new file mode 100644
index 00000000..db8c99fc
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/entity/SysUser.java
@@ -0,0 +1,322 @@
+package com.xinelu.common.core.domain.entity;
+
+import com.xinelu.common.annotation.Excel;
+import com.xinelu.common.annotation.Excel.ColumnType;
+import com.xinelu.common.annotation.Excel.Type;
+import com.xinelu.common.annotation.Excels;
+import com.xinelu.common.core.domain.BaseEntity;
+import com.xinelu.common.xss.Xss;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 用户对象 sys_user
+ *
+ * @author xinelu
+ */
+public class SysUser extends BaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 用户ID
+ */
+ @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
+ 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)
+ })
+ private SysDept dept;
+
+ /**
+ * 角色对象
+ */
+ private List roles;
+
+ /**
+ * 角色组
+ */
+ private Long[] roleIds;
+
+ /**
+ * 岗位组
+ */
+ private Long[] postIds;
+
+ /**
+ * 角色ID
+ */
+ private Long roleId;
+
+ 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;
+ }
+
+ @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/postdischarge-common/src/main/java/com/xinelu/common/core/domain/model/LoginBody.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/model/LoginBody.java
new file mode 100644
index 00000000..892b5e32
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/model/LoginBody.java
@@ -0,0 +1,60 @@
+package com.xinelu.common.core.domain.model;
+
+/**
+ * 用户登录对象
+ *
+ * @author xinelu
+ */
+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/postdischarge-common/src/main/java/com/xinelu/common/core/domain/model/LoginUser.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/model/LoginUser.java
new file mode 100644
index 00000000..f75de319
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/model/LoginUser.java
@@ -0,0 +1,234 @@
+package com.xinelu.common.core.domain.model;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import com.xinelu.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.Set;
+
+/**
+ * 登录用户身份权限
+ *
+ * @author xinelu
+ */
+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 SysUser user;
+
+ 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) {
+ this.userId = userId;
+ this.deptId = deptId;
+ this.user = user;
+ this.permissions = permissions;
+ }
+
+ @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 SysUser getUser() {
+ return user;
+ }
+
+ public void setUser(SysUser user) {
+ this.user = user;
+ }
+
+ @Override
+ public Collection extends GrantedAuthority> getAuthorities() {
+ return null;
+ }
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/core/domain/model/RegisterBody.java b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/model/RegisterBody.java
new file mode 100644
index 00000000..af488b84
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/domain/model/RegisterBody.java
@@ -0,0 +1,10 @@
+package com.xinelu.common.core.domain.model;
+
+/**
+ * 用户注册对象
+ *
+ * @author xinelu
+ */
+public class RegisterBody extends LoginBody {
+
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/core/page/PageDomain.java b/postdischarge-common/src/main/java/com/xinelu/common/core/page/PageDomain.java
new file mode 100644
index 00000000..c38ad582
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/page/PageDomain.java
@@ -0,0 +1,93 @@
+package com.xinelu.common.core.page;
+
+import com.xinelu.common.utils.StringUtils;
+
+/**
+ * 分页数据
+ *
+ * @author xinelu
+ */
+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/postdischarge-common/src/main/java/com/xinelu/common/core/page/TableDataInfo.java b/postdischarge-common/src/main/java/com/xinelu/common/core/page/TableDataInfo.java
new file mode 100644
index 00000000..e6cad640
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/page/TableDataInfo.java
@@ -0,0 +1,82 @@
+package com.xinelu.common.core.page;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 表格分页数据对象
+ *
+ * @author xinelu
+ */
+public class TableDataInfo implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 总记录数
+ */
+ private long total;
+
+ /**
+ * 列表数据
+ */
+ private List> rows;
+
+ /**
+ * 消息状态码
+ */
+ private int code;
+
+ /**
+ * 消息内容
+ */
+ private String msg;
+
+ /**
+ * 表格数据对象
+ */
+ 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;
+ }
+}
diff --git a/postdischarge-common/src/main/java/com/xinelu/common/core/page/TableSupport.java b/postdischarge-common/src/main/java/com/xinelu/common/core/page/TableSupport.java
new file mode 100644
index 00000000..52a863a8
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/page/TableSupport.java
@@ -0,0 +1,53 @@
+package com.xinelu.common.core.page;
+
+import com.xinelu.common.core.text.Convert;
+import com.xinelu.common.utils.ServletUtils;
+
+/**
+ * 表格数据处理
+ *
+ * @author xinelu
+ */
+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/postdischarge-common/src/main/java/com/xinelu/common/core/redis/RedisCache.java b/postdischarge-common/src/main/java/com/xinelu/common/core/redis/RedisCache.java
new file mode 100644
index 00000000..4b0ad744
--- /dev/null
+++ b/postdischarge-common/src/main/java/com/xinelu/common/core/redis/RedisCache.java
@@ -0,0 +1,223 @@
+package com.xinelu.common.core.redis;
+
+import org.springframework.data.redis.core.BoundSetOperations;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * spring redis 工具类
+ *
+ * @author xinelu
+ **/
+@SuppressWarnings(value = {"unchecked", "rawtypes"})
+@Component
+public class RedisCache {
+ @Resource
+ public RedisTemplate redisTemplate;
+
+ /**
+ * 缓存基本的对象,Integer、String、实体类等
+ *
+ * @param key 缓存的键值
+ * @param value 缓存的值
+ */
+ public void setCacheObject(final String key, final T value) {
+ redisTemplate.opsForValue().set(key, value);
+ }
+
+ /**
+ * 缓存基本的对象,Integer、String、实体类等
+ *
+ * @param key 缓存的键值
+ * @param value 缓存的值
+ * @param timeout 时间
+ * @param timeUnit 时间颗粒度
+ */
+ public void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
+ redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
+ }
+
+ /**
+ * 设置有效时间
+ *
+ * @param key Redis键
+ * @param timeout 超时时间
+ * @return true=设置成功;false=设置失败
+ */
+ public boolean expire(final String key, final long timeout) {
+ return expire(key, timeout, TimeUnit.SECONDS);
+ }
+
+ /**
+ * 设置有效时间
+ *
+ * @param key Redis键
+ * @param timeout 超时时间
+ * @param unit 时间单位
+ * @return true=设置成功;false=设置失败
+ */
+ public boolean expire(final String key, final long timeout, final TimeUnit unit) {
+ return redisTemplate.expire(key, timeout, unit);
+ }
+
+ /**
+ * 获得缓存的基本对象。
+ *
+ * @param key 缓存键值
+ * @return 缓存键值对应的数据
+ */
+ public T getCacheObject(final String key) {
+ ValueOperations operation = redisTemplate.opsForValue();
+ return operation.get(key);
+ }
+
+ /**
+ * 删除单个对象
+ *
+ * @param key
+ */
+ public boolean deleteObject(final String key) {
+ return redisTemplate.delete(key);
+ }
+
+ /**
+ * 删除集合对象
+ *
+ * @param collection 多个对象
+ * @return
+ */
+ public long deleteObject(final Collection collection) {
+ return redisTemplate.delete(collection);
+ }
+
+ /**
+ * 缓存List数据
+ *
+ * @param key 缓存的键值
+ * @param dataList 待缓存的List数据
+ * @return 缓存的对象
+ */
+ public long setCacheList(final String key, final List dataList) {
+ Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
+ return count == null ? 0 : count;
+ }
+
+ /**
+ * 获得缓存的list对象
+ *
+ * @param key 缓存的键值
+ * @return 缓存键值对应的数据
+ */
+ public List getCacheList(final String key) {
+ return redisTemplate.opsForList().range(key, 0, -1);
+ }
+
+ /**
+ * 缓存Set
+ *
+ * @param key 缓存键值
+ * @param dataSet 缓存的数据
+ * @return 缓存数据的对象
+ */
+ public BoundSetOperations setCacheSet(final String key, final Set dataSet) {
+ BoundSetOperations setOperation = redisTemplate.boundSetOps(key);
+ Iterator it = dataSet.iterator();
+ while (it.hasNext()) {
+ setOperation.add(it.next());
+ }
+ return setOperation;
+ }
+
+ /**
+ * 获得缓存的set
+ *
+ * @param key
+ * @return
+ */
+ public Set getCacheSet(final String key) {
+ return redisTemplate.opsForSet().members(key);
+ }
+
+ /**
+ * 缓存Map
+ *
+ * @param key
+ * @param dataMap
+ */
+ public void setCacheMap(final String key, final Map dataMap) {
+ if (dataMap != null) {
+ redisTemplate.opsForHash().putAll(key, dataMap);
+ }
+ }
+
+ /**
+ * 获得缓存的Map
+ *
+ * @param key
+ * @return
+ */
+ public Map getCacheMap(final String key) {
+ return redisTemplate.opsForHash().entries(key);
+ }
+
+ /**
+ * 往Hash中存入数据
+ *
+ * @param key Redis键
+ * @param hKey Hash键
+ * @param value 值
+ */
+ public void setCacheMapValue(final String key, final String hKey, final T value) {
+ redisTemplate.opsForHash().put(key, hKey, value);
+ }
+
+ /**
+ * 获取Hash中的数据
+ *
+ * @param key Redis键
+ * @param hKey Hash键
+ * @return Hash中的对象
+ */
+ public T getCacheMapValue(final String key, final String hKey) {
+ HashOperations opsForHash = redisTemplate.opsForHash();
+ return opsForHash.get(key, hKey);
+ }
+
+ /**
+ * 删除Hash中的数据
+ *
+ * @param key
+ * @param hKey
+ */
+ public void delCacheMapValue(final String key, final String hKey) {
+ HashOperations hashOperations = redisTemplate.opsForHash();
+ hashOperations.delete(key, hKey);
+ }
+
+ /**
+ * 获取多个Hash中的数据
+ *
+ * @param key Redis键
+ * @param hKeys Hash键集合
+ * @return Hash对象集合
+ */
+ public List getMultiCacheMapValue(final String key, final Collection