diff --git a/.gitignore b/.gitignore
index a2a3040a..5b4c80c2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,3 +29,15 @@ build/
### VS Code ###
.vscode/
+
+/admin-api/java-api/target/
+
+
+/admin-web/typescript-ant-design-vue/node_modules/
+
+
+
+
+
+
+
diff --git a/README.md b/README.md
index be05793a..e541689c 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,3 @@
-### SmartAdmin 2.0 (即 vue3 的 js版本和ts版本 )正在火热开发中,欢迎持续关注 !
#### 简介
SmartAdmin由河南·洛阳 [1024创新实验室](https://www.1024lab.net/)团队研发的一套互联网企业级的通用型中后台解决方案!使用最前沿的前后台技术栈SpringBoot和Vue,前后端分离,**我们开源一套漂亮的代码和一套整洁的代码规范**,让大家在这浮躁的代码世界里感受到一股把代码写好的清流!同时又让开发者节省大量的时间,减少加班,快乐工作,热爱生活。SmartAdmin 让你从认识到忘不了,绝对是你最想要的!
diff --git a/smart-admin-web/.eslintignore b/admin-api/go-api/readme.md
similarity index 100%
rename from smart-admin-web/.eslintignore
rename to admin-api/go-api/readme.md
diff --git a/smart-admin-web/src/filters/index.js b/admin-api/java-api/README.md
similarity index 100%
rename from smart-admin-web/src/filters/index.js
rename to admin-api/java-api/README.md
diff --git a/admin-api/java-api/pom.xml b/admin-api/java-api/pom.xml
new file mode 100644
index 00000000..a49a58fb
--- /dev/null
+++ b/admin-api/java-api/pom.xml
@@ -0,0 +1,401 @@
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.4.1
+
+
+ net.1024lab
+ smart-admin
+ 2.0.0
+ jar
+
+ smart-admin
+ smart-admin project
+
+
+ 1.8
+ 4.3.0
+ 6.4.3
+ 3.4.1
+ 3.8.6
+ 2.7.0
+ 1.2.62
+ 1.2.6
+ 0.9.1
+ 4.2.0
+ 4.2.2
+ 2.3.2
+ 20030203.000550
+ 30.1.1-jre
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ com.github.ben-manes.caffeine
+ caffeine
+
+
+ error_prone_annotations
+ com.google.errorprone
+
+
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+ org.springframework
+ spring-mock
+ 2.0.8
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ ${mybatis-plus.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+
+ p6spy
+ p6spy
+ ${p6spy.version}
+
+
+
+ io.springfox
+ springfox-swagger2
+ ${swagger.version}
+
+
+ guava
+ com.google.guava
+
+
+
+
+
+ com.squareup.okhttp3
+ okhttp
+
+
+
+ io.springfox
+ springfox-swagger-ui
+ ${swagger.version}
+
+
+
+ com.alibaba
+ fastjson
+ ${fast-json.version}
+
+
+
+ com.alibaba
+ druid
+ ${druid.version}
+
+
+
+ io.jsonwebtoken
+ jjwt
+ ${jjwt.version}
+
+
+
+ com.google.guava
+ guava
+ ${google-guava.version}
+
+
+
+ com.github.penggle
+ kaptcha
+ ${kaptcha.version}
+
+
+
+ commons-io
+ commons-io
+ ${commons-io.version}
+
+
+
+
+ cn.afterturn
+ easypoi-spring-boot-starter
+ ${easypoi.version}
+
+
+
+ cn.afterturn
+ easypoi-base
+ ${easypoi.version}
+
+
+ javassist
+ org.javassist
+
+
+ guava
+ com.google.guava
+
+
+ xmlbeans
+ org.apache.xmlbeans
+
+
+
+
+
+ cn.afterturn
+ easypoi-web
+ ${easypoi.version}
+
+
+ javassist
+ org.javassist
+
+
+
+
+ cn.afterturn
+ easypoi-annotation
+ ${easypoi.version}
+
+
+
+
+ com.googlecode.concurrentlinkedhashmap
+ concurrentlinkedhashmap-lru
+ 1.4.2
+
+
+
+ org.reflections
+ reflections
+ 0.9.11
+
+
+ guava
+ com.google.guava
+
+
+
+
+
+
+ org.apache.commons
+ commons-collections4
+ 4.4
+
+
+
+ com.amazonaws
+ aws-java-sdk-s3
+ 1.11.842
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+
+
+ xerces
+ xercesImpl
+ 2.12.0
+
+
+ org.apache.poi
+ poi-scratchpad
+ 4.1.1
+
+
+
+
+ org.apache.poi
+ ooxml-schemas
+ 1.3
+
+
+
+
+ velocity
+ org.apache.velocity
+ 1.7
+
+
+
+ org.apache.velocity
+ velocity-engine-core
+ 2.0
+
+
+
+
+
+
+ ${profiles.active}-${project.name}
+
+
+ false
+ src/main/resources
+
+ dev/*
+ sit/*
+ pre/*
+ prod/*
+
+
+
+
+ src/main/resources/${profiles.active}
+ true
+
+ *.properties
+
+
+
+
+ src/main/resources/${profiles.active}
+ false
+
+ *.*
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.2
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+ true
+
+
+
+
+
+
+
+ dev
+
+ dev
+
+
+ true
+
+
+
+ sit
+
+ sit
+
+
+
+ pre
+
+ pre
+
+
+
+ prod
+
+ prod
+
+
+
+
+
\ No newline at end of file
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/SmartAdminApplication.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/SmartAdminApplication.java
similarity index 62%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/SmartAdminApplication.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/SmartAdminApplication.java
index b22d0670..ade0246a 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/SmartAdminApplication.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/SmartAdminApplication.java
@@ -1,5 +1,7 @@
-package net.lab1024.smartadmin;
+package net.lab1024.smartadmin.service;
+import org.apache.ibatis.annotations.Mapper;
+import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@@ -9,21 +11,18 @@ import org.springframework.scheduling.annotation.EnableScheduling;
/**
* [ admin 项目启动类 ]
*
- * @author yandanyang
- * @version 1.0
- * @company 1024lab.net
- * @copyright (c) 2019 1024lab.netInc. All rights reserved.
- * @date
- * @since JDK1.8
+ * @author 罗伊
*
*/
-@SpringBootApplication(scanBasePackages = {"net.lab1024.smartadmin", "cn.afterturn.easypoi"})
+@SpringBootApplication
@EnableCaching
@EnableScheduling
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
+@MapperScan(value = "net.lab1024.smartadmin.service.*",basePackageClasses = Mapper.class)
public class SmartAdminApplication {
public static void main(String[] args) {
SpringApplication.run(SmartAdminApplication.class, args);
+ System.out.println("####################### smart-admin-service start #######################");
}
}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/reload/annotation/SmartReload.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/anno/NoNeedLogin.java
similarity index 60%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/reload/annotation/SmartReload.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/anno/NoNeedLogin.java
index eac54afd..ec62643e 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/reload/annotation/SmartReload.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/anno/NoNeedLogin.java
@@ -1,4 +1,4 @@
-package net.lab1024.smartadmin.common.reload.annotation;
+package net.lab1024.smartadmin.service.common.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -6,13 +6,12 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * 定义 SmartReload 注解
+ * [ ]
*
- * @author zhuoda
+ * @author 罗伊
+ * @date 2020/8/21 14:55
*/
-@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
-public @interface SmartReload {
-
- String value();
+@Target(ElementType.METHOD)
+public @interface NoNeedLogin {
}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/anno/NoRepeatSubmit.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/anno/NoRepeatSubmit.java
new file mode 100644
index 00000000..7c0916d2
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/anno/NoRepeatSubmit.java
@@ -0,0 +1,29 @@
+package net.lab1024.smartadmin.service.common.anno;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 标记 需要防止重复提交 的注解
+ *
+ * @author listen
+ * @date 2020年11月25日 10:56:58
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface NoRepeatSubmit {
+
+ /**
+ * 重复提交间隔时间/毫秒
+ *
+ * @return
+ */
+ int value() default 1200;
+
+ /**
+ * 最长间隔30s
+ */
+ int MAX_INTERVAL = 30000;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/anno/NoValidPrivilege.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/anno/NoValidPrivilege.java
new file mode 100644
index 00000000..15e8ade4
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/anno/NoValidPrivilege.java
@@ -0,0 +1,14 @@
+package net.lab1024.smartadmin.service.common.anno;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2020/8/21 15:02
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface NoValidPrivilege {
+}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/department/DepartmentResponseCodeConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/DepartmentResponseCodeConst.java
similarity index 90%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/department/DepartmentResponseCodeConst.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/DepartmentResponseCodeConst.java
index a7a219e0..e7ce0cb7 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/department/DepartmentResponseCodeConst.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/DepartmentResponseCodeConst.java
@@ -1,6 +1,4 @@
-package net.lab1024.smartadmin.module.system.department;
-
-import net.lab1024.smartadmin.common.constant.ResponseCodeConst;
+package net.lab1024.smartadmin.service.common.codeconst;
/**
* 部门返回信息常量类
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/employee/constant/EmployeeResponseCodeConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/EmployeeResponseCodeConst.java
similarity index 76%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/employee/constant/EmployeeResponseCodeConst.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/EmployeeResponseCodeConst.java
index 379b8be7..19648743 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/employee/constant/EmployeeResponseCodeConst.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/EmployeeResponseCodeConst.java
@@ -1,12 +1,10 @@
-package net.lab1024.smartadmin.module.system.employee.constant;
-
-import net.lab1024.smartadmin.common.constant.ResponseCodeConst;
+package net.lab1024.smartadmin.service.common.codeconst;
/**
* 员工常量类
* 3001-3999
*
- * @author lidoudou
+ * @author 开云
* @date 2017年12月19日下午19:04:52
*/
public class EmployeeResponseCodeConst extends ResponseCodeConst {
@@ -34,16 +32,18 @@ public class EmployeeResponseCodeConst extends ResponseCodeConst {
/**
* 您的账号已被禁用,不得登录系统
*/
- public static final EmployeeResponseCodeConst IS_DISABLED = new EmployeeResponseCodeConst(3005, "您的账号已被禁用,不得登录系统!");
+ public static final EmployeeResponseCodeConst IS_DISABLED = new EmployeeResponseCodeConst(3005, "您的账号已被禁用");
/**
* 登录名已存在
*/
public static final EmployeeResponseCodeConst LOGIN_NAME_EXISTS = new EmployeeResponseCodeConst(3006, "登录名已存在!");
+
/**
- * 密码输入有误,请重新输入 10115
+ * 密码输入有误,请重新输入
*/
- public static final EmployeeResponseCodeConst PASSWORD_ERROR = new EmployeeResponseCodeConst(3007, "密码输入有误,请重新输入");
+ public static final EmployeeResponseCodeConst PASSWORD_ERROR = new EmployeeResponseCodeConst(3007, "密码错误");
+
/**
* 手机号已存在
*/
@@ -53,7 +53,12 @@ public class EmployeeResponseCodeConst extends ResponseCodeConst {
public static final EmployeeResponseCodeConst BIRTHDAY_ERROR = new EmployeeResponseCodeConst(3010, "生日格式不正确");
- public static final EmployeeResponseCodeConst VERIFICATION_CODE_INVALID = new EmployeeResponseCodeConst(3011, "验证码无效");
+ public static final EmployeeResponseCodeConst VERIFICATION_CODE_INVALID = new EmployeeResponseCodeConst(3011, "请输入正确的验证码");
+
+ /**
+ * 用户名或密码错误 多次错误用于前端判断展示验证码
+ */
+ public static final EmployeeResponseCodeConst LOGIN_FAILED_REPEATEDLY = new EmployeeResponseCodeConst(3012, "用户名或密码错误!");
public EmployeeResponseCodeConst(int code, String msg) {
super(code, msg);
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/FileResponseCodeConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/FileResponseCodeConst.java
new file mode 100644
index 00000000..bea7e99f
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/FileResponseCodeConst.java
@@ -0,0 +1,47 @@
+package net.lab1024.smartadmin.service.common.codeconst;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2020/8/25 11:57
+ */
+public class FileResponseCodeConst extends ResponseCodeConst {
+
+ /**
+ * 4001 -4999
+ */
+ public static final FileResponseCodeConst FILE_EMPTY = new FileResponseCodeConst(4001, "上传文件不能为空");
+
+ public static final FileResponseCodeConst FILE_SIZE_ERROR = new FileResponseCodeConst(4002, "上传文件超过%s,请重新上传!");
+
+ public static final FileResponseCodeConst UNKNOWN_FILE_TYPE = new FileResponseCodeConst(4003, "未知的文件类型!");
+
+ public static final FileResponseCodeConst LOCAL_UPDATE_PREFIX_ERROR = new FileResponseCodeConst(4004, "文件本地上传缺少URL前缀配置[local_upload_url_prefix]");
+
+ public static final FileResponseCodeConst UPLOAD_ERROR = new FileResponseCodeConst(4005, "上传失败");
+
+ public static final FileResponseCodeConst URL_ERROR = new FileResponseCodeConst(4006, "获取URL失败");
+
+ public static final FileResponseCodeConst FILE_MODULE_ERROR = new FileResponseCodeConst(4007, "文件目录类型错误");
+
+ public static final FileResponseCodeConst FILE_NOT_EXIST = new FileResponseCodeConst(4008, "文件不存在");
+
+ public static final FileResponseCodeConst DOWNLOAD_ERROR = new FileResponseCodeConst(4009, "文件下载失败");
+
+ public static final FileResponseCodeConst VOD_SERVICE_ERROR = new FileResponseCodeConst(4010, "VOD服务错误:");
+
+ public static final FileResponseCodeConst VOD_FILE_ERROR = new FileResponseCodeConst(4011, "请上传正确的音/视频格式");
+
+ public static final FileResponseCodeConst VOD_FILE_NOT_EXIST = new FileResponseCodeConst(4012, "视频文件不存在");
+
+ public static final FileResponseCodeConst FILE_NAME_ERROR = new FileResponseCodeConst(4013, "文件名称必须1-100个字符");
+
+ public static final FileResponseCodeConst VOD_TOKEN_ERROR = new FileResponseCodeConst(4014, "视频文件TOKEN失效");
+
+ public static final FileResponseCodeConst VOD_CIPHER_TEXT_ERROR = new FileResponseCodeConst(4015, "视频文件CIPHER_TEXT无效");
+
+ public FileResponseCodeConst(int code, String msg) {
+ super(code, msg);
+ }
+}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/login/LoginResponseCodeConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/LoginResponseCodeConst.java
similarity index 79%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/login/LoginResponseCodeConst.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/LoginResponseCodeConst.java
index 0cfb8d22..a24b44e9 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/login/LoginResponseCodeConst.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/LoginResponseCodeConst.java
@@ -1,12 +1,10 @@
-package net.lab1024.smartadmin.module.system.login;
-
-import net.lab1024.smartadmin.common.constant.ResponseCodeConst;
+package net.lab1024.smartadmin.service.common.codeconst;
/**
* 员工常量类
* 1001-1999
*
- * @author lidoudou
+ * @author 开云
* @date 2017年12月19日下午19:04:52
*/
public class LoginResponseCodeConst extends ResponseCodeConst {
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/position/PositionResponseCodeConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/PositionResponseCodeConst.java
similarity index 70%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/position/PositionResponseCodeConst.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/PositionResponseCodeConst.java
index 43528034..e9011c48 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/position/PositionResponseCodeConst.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/PositionResponseCodeConst.java
@@ -1,9 +1,7 @@
-package net.lab1024.smartadmin.module.system.position;
-
-import net.lab1024.smartadmin.common.constant.ResponseCodeConst;
+package net.lab1024.smartadmin.service.common.codeconst;
/**
- * @author zzr
+ * @author
*/
public class PositionResponseCodeConst extends ResponseCodeConst {
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/privilege/constant/PrivilegeResponseCodeConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/PrivilegeResponseCodeConst.java
similarity index 74%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/privilege/constant/PrivilegeResponseCodeConst.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/PrivilegeResponseCodeConst.java
index 3efbd9b2..6a8f0c3d 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/privilege/constant/PrivilegeResponseCodeConst.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/PrivilegeResponseCodeConst.java
@@ -1,16 +1,8 @@
-package net.lab1024.smartadmin.module.system.privilege.constant;
-
-import net.lab1024.smartadmin.common.constant.ResponseCodeConst;
+package net.lab1024.smartadmin.service.common.codeconst;
/**
- *
- * @author yandanyang
- * @version 1.0
- * @company 1024lab.net
- * @copyright (c) 2019 1024lab.netInc. All rights reserved.
- * @date
- * @since JDK1.8
+ * @author 罗伊
*/
public class PrivilegeResponseCodeConst extends ResponseCodeConst {
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/ResponseCodeConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/ResponseCodeConst.java
new file mode 100644
index 00000000..dae253a7
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/ResponseCodeConst.java
@@ -0,0 +1,111 @@
+package net.lab1024.smartadmin.service.common.codeconst;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 1 表示成功
+ * 10 - 100 表示 系统异常,即java报错了
+ * 100 以上, 业务
+ *
+ * 根据实际业务,设置范围值
+ * 正常100就够了
+ *
+ * @author Administrator
+ */
+@Slf4j
+public class ResponseCodeConst {
+
+ public static final ResponseCodeConst SUCCESS = new ResponseCodeConst(1, "操作成功!", true);
+
+ public static final ResponseCodeConst SYSTEM_ERROR = new ResponseCodeConst(11, "系统繁忙,请稍后重试");
+
+ public static final ResponseCodeConst ERROR_PARAM = new ResponseCodeConst(101, "参数异常");
+
+ public static final ResponseCodeConst ERROR_PARAM_ANY = new ResponseCodeConst(102, "%s参数异常!");
+
+ public static final ResponseCodeConst DEVELOPMENT = new ResponseCodeConst(112, "此功能正在开发中");
+
+ public static final ResponseCodeConst NOT_EXISTS = new ResponseCodeConst(113, "数据不存在");
+
+ public static final ResponseCodeConst REQUEST_METHOD_ERROR = new ResponseCodeConst(114, "请求方式错误");
+
+ public static final ResponseCodeConst JSON_FORMAT_ERROR = new ResponseCodeConst(115, "请求前端参数格式错误");
+
+ public static final ResponseCodeConst PERMISSION_DENIED = new ResponseCodeConst(116, "您没有权限修改数据");
+
+ public static final ResponseCodeConst ALREADY_EXIST = new ResponseCodeConst(117, "数据已存在");
+
+ public static final ResponseCodeConst STATUS_ERROR = new ResponseCodeConst(118, "数据状态异常");
+
+ public static final ResponseCodeConst AREA_ERROR = new ResponseCodeConst(119, "地区数据错误");
+
+ public static final ResponseCodeConst REQUEST_ERROR = new ResponseCodeConst(120, "请求异常");
+
+ public static final ResponseCodeConst TOKEN_ERROR = new ResponseCodeConst(121, "登录失效,请重新登录");
+
+ public static final ResponseCodeConst BUSINESS_HANDING = new ResponseCodeConst(122, "业务正在繁忙处理中,请稍后再试");
+
+ public static final ResponseCodeConst NOT_SUPPORT = new ResponseCodeConst(123, "暂不支持");
+
+ public static final ResponseCodeConst REPEAT_SUBMIT = new ResponseCodeConst(125, "太...太快了,请您稍后重试~");
+
+ protected int code;
+
+ protected String msg;
+
+ protected boolean success;
+
+ public ResponseCodeConst() {
+ }
+
+ protected ResponseCodeConst(int code, String msg) {
+ super();
+ this.code = code;
+ this.msg = msg;
+ ResponseCodeContainer.put(this);
+ }
+
+ protected ResponseCodeConst(int code, String msg, boolean success) {
+ super();
+ this.code = code;
+ this.msg = msg;
+ this.success = success;
+ ResponseCodeContainer.put(this);
+ }
+
+ protected ResponseCodeConst(int code) {
+ super();
+ this.code = code;
+ ResponseCodeContainer.put(this);
+ }
+
+ 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 boolean issucc() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static void init() {
+ log.info("-------------- ResponseCodeConst init -------------");
+ }
+
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/ResponseCodeContainer.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/ResponseCodeContainer.java
new file mode 100644
index 00000000..d5ff7771
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/ResponseCodeContainer.java
@@ -0,0 +1,73 @@
+package net.lab1024.smartadmin.service.common.codeconst;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2021/1/8 11:28
+ */
+@Slf4j
+public class ResponseCodeContainer {
+
+ private static final Map RESPONSE_CODE_MAP = new HashMap<>();
+
+ private static final Map, int[]> RESPONSE_CODE_RANGE_MAP = new HashMap<>();
+
+ /**
+ * id的范围:[start, end]左闭右闭
+ *
+ * @param clazz
+ * @param start
+ * @param end
+ */
+ public static void register(Class extends ResponseCodeConst> clazz, int start, int end) {
+ if (start > end) {
+ throw new IllegalArgumentException(" start > end!");
+ }
+
+ if (RESPONSE_CODE_RANGE_MAP.containsKey(clazz)) {
+ throw new IllegalArgumentException(String.format(" Class:%s already exist!", clazz.getSimpleName()));
+ }
+ RESPONSE_CODE_RANGE_MAP.forEach((k, v) -> {
+ if ((start >= v[0] && start <= v[1]) || (end >= v[0] && end <= v[1])) {
+ throw new IllegalArgumentException(String.format(" Class:%s 's id range[%d,%d] has " + "intersection with " + "class:%s", clazz.getSimpleName(), start, end,
+ k.getSimpleName()));
+ }
+ });
+
+ RESPONSE_CODE_RANGE_MAP.put(clazz, new int[]{start, end});
+
+ // 提前初始化static变量,进行范围检测
+ Field[] fields = clazz.getFields();
+ if (fields.length != 0) {
+ try {
+ fields[0].get(clazz);
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ log.error("", e);
+ }
+ }
+ }
+
+ public static void put(ResponseCodeConst codeConst) {
+ int[] idRange = RESPONSE_CODE_RANGE_MAP.get(codeConst.getClass());
+ if (idRange == null) {
+ throw new IllegalArgumentException(String.format(" Class:%s has not been registered!", codeConst.getClass().getSimpleName()));
+ }
+ int code = codeConst.code;
+ if (code < idRange[0] || code > idRange[1]) {
+ throw new IllegalArgumentException(String.format(" Id(%d) out of range[%d,%d], " + "class:%s", code, idRange[0], idRange[1], codeConst.getClass().getSimpleName()));
+ }
+ if (RESPONSE_CODE_MAP.keySet().contains(code)) {
+ log.error(String.format(" Id(%d) out of range[%d,%d], " + "class:%s code is repeat!", code, idRange[0], idRange[1], codeConst.getClass().getSimpleName()));
+ System.exit(0);
+ }
+ RESPONSE_CODE_MAP.put(code, codeConst);
+ }
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/ResponseCodeRegister.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/ResponseCodeRegister.java
new file mode 100644
index 00000000..decb66d1
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/ResponseCodeRegister.java
@@ -0,0 +1,30 @@
+package net.lab1024.smartadmin.service.common.codeconst;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2021/1/8 15:59
+ */
+@Slf4j
+public class ResponseCodeRegister {
+
+ // 范围声明
+ static {
+ // 系统功能,从0开始,step=1000
+ ResponseCodeContainer.register(ResponseCodeConst.class, 0, 1000);
+ ResponseCodeContainer.register(LoginResponseCodeConst.class, 1001, 1999);
+ ResponseCodeContainer.register(DepartmentResponseCodeConst.class, 2001, 2999);
+ ResponseCodeContainer.register(EmployeeResponseCodeConst.class, 3001, 3999);
+ ResponseCodeContainer.register(FileResponseCodeConst.class, 4001, 5000);
+ ResponseCodeContainer.register(RoleResponseCodeConst.class, 6001, 6999);
+ ResponseCodeContainer.register(PrivilegeResponseCodeConst.class, 7001, 7999);
+ ResponseCodeContainer.register(PositionResponseCodeConst.class, 13000, 13999);
+ }
+
+ public static void init() {
+ log.info("-------------- ResponseCodeConst init -------------");
+ }
+}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/role/basic/RoleResponseCodeConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/RoleResponseCodeConst.java
similarity index 78%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/role/basic/RoleResponseCodeConst.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/RoleResponseCodeConst.java
index c1818465..e9381db1 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/system/role/basic/RoleResponseCodeConst.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/codeconst/RoleResponseCodeConst.java
@@ -1,9 +1,7 @@
-package net.lab1024.smartadmin.module.system.role.basic;
-import net.lab1024.smartadmin.common.constant.ResponseCodeConst;
+package net.lab1024.smartadmin.service.common.codeconst;
/**
- *
- * @author yandanyang
+ * @author 罗伊
* 角色业务状态码 6001 - 6999
*/
public class RoleResponseCodeConst extends ResponseCodeConst {
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/domain/BaseEnum.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/BaseEnum.java
similarity index 87%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/domain/BaseEnum.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/BaseEnum.java
index 61ef2c66..2d8c41c3 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/domain/BaseEnum.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/BaseEnum.java
@@ -1,4 +1,4 @@
-package net.lab1024.smartadmin.common.domain;
+package net.lab1024.smartadmin.service.common.constant;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONAware;
@@ -10,6 +10,8 @@ import java.util.LinkedHashMap;
import java.util.Objects;
/**
+ * 枚举类接口
+ *
* @author listen
* @date 2018-07-17 下午 3:52
*/
@@ -18,7 +20,7 @@ public interface BaseEnum {
/**
* 获取枚举类的值
*
- * @return Object
+ * @return
*/
Object getValue();
@@ -67,24 +69,21 @@ public interface BaseEnum {
String enumJson = JSON.toJSONString(json, true);
enumJson = enumJson.replaceAll("\"", "");
- enumJson= enumJson.replaceAll("\t"," ");
- enumJson = enumJson.replaceAll("\n","
");
+ enumJson = enumJson.replaceAll("\t", " ");
+ enumJson = enumJson.replaceAll("\n", "
");
String prefix = "
export const
" + CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, clazz.getSimpleName() + " =
");
return prefix + "" + enumJson + "
";
}
-
@Data
class DeletedQuotationAware implements JSONAware {
private String value;
public DeletedQuotationAware(Object value) {
- if(value == null){
- this.value = "";
- }else if (value instanceof String) {
+ if (value instanceof String) {
this.value = "'" + value + "'";
- }else {
+ } else {
this.value = value.toString();
}
}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/CacheModuleBaseConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/CacheModuleBaseConst.java
new file mode 100644
index 00000000..a4059513
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/CacheModuleBaseConst.java
@@ -0,0 +1,63 @@
+package net.lab1024.smartadmin.service.common.constant;
+
+/**
+ * @author 罗伊
+ * @date 2021-01-31 0:00
+ */
+public class CacheModuleBaseConst {
+
+ public static class Employee {
+ /**
+ * 某个部门下的员工缓存
+ */
+ public static final String DEPARTMENT_EMPLOYEE_CACHE = "department_employee_cache";
+
+ /**
+ * 单个员工的缓存
+ */
+ public static final String SINGLE_EMPLOYEE_CACHE = "single_employee_cache";
+
+ /**
+ * 单个员工角色
+ */
+ public static final String SINGLE_EMPLOYEE_ROLE_CACHE = "single_employee_role_cache";
+ }
+
+ public static class Department {
+
+ /**
+ * 部门树
+ */
+ public static final String DEPARTMENT_CACHE = "department_cache";
+
+ /**
+ * 部门树
+ */
+ public static final String DEPARTMENT_TREE_CACHE = "department_tree_cache";
+
+ /**
+ * 某个部门以及下级的id列表
+ */
+ public static final String DEPARTMENT_TREE_ID_CACHE = "department_tree_id_cache";
+
+ }
+
+ public static class Category {
+
+ /**
+ * 类目
+ */
+ public static final String CATEGORY = "category_cache";
+
+ /**
+ * 类目子级
+ */
+ public static final String CATEGORY_SUB = "category_sub_cache";
+
+ /**
+ * 类目层级树 缓存
+ */
+ public static final String CATEGORY_TREE = "category_tree_cache";
+
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/CommonConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/CommonConst.java
new file mode 100644
index 00000000..3c496370
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/CommonConst.java
@@ -0,0 +1,150 @@
+package net.lab1024.smartadmin.service.common.constant;
+
+import com.google.common.collect.ImmutableSet;
+import org.springframework.util.CollectionUtils;
+
+import java.util.*;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2020/9/14 15:48
+ */
+public class CommonConst {
+
+ /**
+ * 全局通用分隔符
+ */
+ public static final String SEPARATOR = ",";
+
+ /**
+ * 全局通用分隔符 逗号
+ */
+ public static final Character SEPARATOR_CHAR = ',';
+
+ /**
+ * 全局通用分隔符 斜杠
+ */
+ public static final String SEPARATOR_SLASH = "/";
+
+ /**
+ * 全局通用分隔符 下划线
+ */
+ public static final String UNDERLINE = "_";
+
+ /**
+ * 空字符串
+ */
+ public static final String EMPTY_STR = "";
+
+ /**
+ * 空 MaP
+ * 注意:放入元素会抛异常
+ */
+ public static final Map EMPTY_MAP = Collections.unmodifiableMap(new HashMap<>(0));
+
+ /**
+ * 空 list
+ * 注意:放入元素会抛异常
+ */
+ public static final List EMPTY_LIST = Collections.unmodifiableList(new ArrayList<>(0));
+
+ /**
+ * 空字符串
+ */
+ public static final long DEFAULT_PARENT_ID = 0L;
+
+ /**
+ * 空字符串
+ */
+ public static final int ZERO = 0;
+
+
+ public static final class Token {
+
+ public static final String DEFAULT_TOKEN = "default-token-";
+
+ public static final String INNER_TOKEN_NAME = "inner-token";
+
+ public static final String OUTER_TOKEN_NAME = "x-access-token";
+
+ }
+
+ public static final class FileFolderConst {
+
+ /**
+ * 公用读取文件夹 public
+ */
+ public static final String FOLDER_PUBLIC = "pu";
+
+ /**
+ * 私有读取文件夹 private
+ */
+ public static final String FOLDER_PRIVATE = "pr";
+
+ /**
+ * 文件夹格式
+ */
+ public static final String FOLDER_FORMAT = "folder";
+
+ }
+
+ public static final class System {
+ /**
+ * oss url redis 过期时间
+ */
+ public static final int FILE_URL_EXPIRE_SECOND = 3600;
+
+ public static final int FILE_VO_EXPIRE_SECOND = 86400;
+
+ }
+
+ /**
+ * 长度类常量
+ */
+ public static final class NumberLimit {
+ /**
+ * 文件名称长度
+ */
+ public static final int FILE_NAME = 100;
+
+ }
+
+ public static final class ApiUrl {
+ /**
+ * 基础 api 前缀
+ */
+ public static final String API_PREFIX_SUPPORT = "/support";
+
+ /**
+ * 后管 api 前缀
+ */
+ public static final String API_PREFIX_ADMIN = "/admin";
+
+ }
+
+ public static final class Password {
+
+ public static final String DEFAULT = "123456";
+
+ public static final String SALT_FORMAT = "smart_%s_admin";
+ }
+
+ public static final class CommonCollection {
+
+ public static final Set IGNORE_URL = ImmutableSet.of("/swagger", "Excel", "/h5/api");
+
+ public static Boolean contain(Set ignores, String uri) {
+ if (CollectionUtils.isEmpty(ignores)) {
+ return false;
+ }
+ for (String ignoreUrl : ignores) {
+ if (uri.startsWith(ignoreUrl)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/GenderEnum.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/GenderEnum.java
new file mode 100644
index 00000000..439eb842
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/GenderEnum.java
@@ -0,0 +1,52 @@
+package net.lab1024.smartadmin.service.common.constant;
+
+/**
+ * 性别枚举类
+ *
+ * @author listen
+ * @date 2019/09/24 16:50
+ */
+public enum GenderEnum implements BaseEnum {
+
+ /**
+ * 0 未知
+ */
+ UNKNOWN(0, "未知"),
+
+ /**
+ * 男 1 奇数为阳
+ */
+ MAN(1, "男"),
+
+ /**
+ * 女 2 偶数为阴
+ */
+ WOMAN(2, "女");
+
+ private final Integer gender;
+
+ private final String desc;
+
+ GenderEnum(Integer gender, String desc) {
+ this.gender = gender;
+ this.desc = desc;
+ }
+ /**
+ * 获取枚举类的值
+ *
+ * @return Integer
+ */
+ @Override
+ public Integer getValue() {
+ return gender;
+ }
+ /**
+ * 获取枚举类的说明
+ *
+ * @return String
+ */
+ @Override
+ public String getDesc() {
+ return desc;
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/RedisKeyConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/RedisKeyConst.java
new file mode 100644
index 00000000..5a73ec8f
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/RedisKeyConst.java
@@ -0,0 +1,27 @@
+package net.lab1024.smartadmin.service.common.constant;
+
+/**
+ * redis key 常量类
+ *
+ * @author listen
+ * @date 2019/09/23 20:48
+ */
+public class RedisKeyConst {
+
+ public class Base {
+
+ private static final String PROJECT = "base:";
+
+ public static final String FILE_URL = PROJECT + "file:";
+
+ public static final String FILE_VO = PROJECT + "fileVO:";
+
+ public static final String LOCK = PROJECT + "lock:";
+
+ public static final String ID_GENERATOR = LOCK + "id:";
+
+ public static final String CAPTCHA = PROJECT + "captcha:";
+
+ }
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/SwaggerTagConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/SwaggerTagConst.java
new file mode 100644
index 00000000..8fe20ed2
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/SwaggerTagConst.java
@@ -0,0 +1,55 @@
+package net.lab1024.smartadmin.service.common.constant;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2021/1/9 11:45
+ */
+public class SwaggerTagConst {
+
+ public static class Support {
+
+ public static final String FILE = "基础-文件服务";
+
+ public static final String CACHE = "基础-缓存";
+
+ public static final String SYSTEM_CONFIG = "基础-系统参数";
+
+ public static final String ID_GENERATOR = "基础-ID生成器";
+
+ public static final String SMART_RELOAD = "基础-Reload";
+
+ public static final String TASK_SCHEDULER = "基础-任务调度";
+
+ public static final String USER_OPERATE_LOG = "基础-用户操作日志";
+
+ public static final String HEART_BEAT = "基础-心跳日志";
+
+ public static final String CAPTCHA = "基础-图形验证码";
+
+ }
+
+ public static class Admin {
+
+ public static final String MANAGER_EMPLOYEE = "管理端-员工";
+
+ public static final String MANAGER_EMPLOYEE_LOGIN = "管理端-员工登录";
+
+ public static final String MANAGER_DEPARTMENT = "管理端-部门";
+
+ public static final String MANAGER_ROLE = "管理端-角色";
+
+ public static final String MANAGER_NOTICE = "管理端-系统通知";
+
+ public static final String MANAGER_MENU = "管理端-菜单";
+
+ public static final String MANAGER_ROLE_MENU = "管理端-角色-菜单";
+
+ public static final String MANAGER_DATA_TRACER = "管理端-数据变动跟踪";
+
+ public static final String MANAGER_CATEGORY = "管理端-分类";
+
+ public static final String MANAGER_GOODS = "管理端-商品业务";
+ }
+}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/constant/SystemEnvironmentEnum.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/SystemEnvironmentEnum.java
similarity index 80%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/constant/SystemEnvironmentEnum.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/SystemEnvironmentEnum.java
index e8d0fd75..7e994fec 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/constant/SystemEnvironmentEnum.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/constant/SystemEnvironmentEnum.java
@@ -1,6 +1,4 @@
-package net.lab1024.smartadmin.constant;
-
-import net.lab1024.smartadmin.common.domain.BaseEnum;
+package net.lab1024.smartadmin.service.common.constant;
/**
* 系统环境枚举类
@@ -10,7 +8,6 @@ import net.lab1024.smartadmin.common.domain.BaseEnum;
*/
public enum SystemEnvironmentEnum implements BaseEnum {
-
/**
* dev
*/
@@ -31,19 +28,14 @@ public enum SystemEnvironmentEnum implements BaseEnum {
*/
PROD("prod", "生产环境");
+ private final String value;
- public static final String DEV_ENV = "dev";
-
-
- private String value;
-
- private String desc;
+ private final String desc;
SystemEnvironmentEnum(String value, String desc) {
this.value = value;
this.desc = desc;
}
-
/**
* 获取定义枚举value值
*
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/controller/AdminBaseController.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/controller/AdminBaseController.java
new file mode 100644
index 00000000..91b4cf5f
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/controller/AdminBaseController.java
@@ -0,0 +1,15 @@
+package net.lab1024.smartadmin.service.common.controller;
+
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.smartadmin.service.common.constant.CommonConst;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * @author: 卓大
+ * @create: 2020-03-31 08:54 PM from win10
+ */
+@Slf4j
+@RequestMapping(CommonConst.ApiUrl.API_PREFIX_ADMIN)
+public class AdminBaseController {
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/controller/SupportBaseController.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/controller/SupportBaseController.java
new file mode 100644
index 00000000..c76d0db1
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/controller/SupportBaseController.java
@@ -0,0 +1,14 @@
+package net.lab1024.smartadmin.service.common.controller;
+
+import net.lab1024.smartadmin.service.common.constant.CommonConst;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * 通用业务路由基类
+ *
+ * @author 胡克
+ * @date 2019/10/18 11:51
+ */
+@RequestMapping(CommonConst.ApiUrl.API_PREFIX_SUPPORT)
+public class SupportBaseController {
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/domain/PageBaseDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/domain/PageBaseDTO.java
new file mode 100644
index 00000000..9fa622aa
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/domain/PageBaseDTO.java
@@ -0,0 +1,52 @@
+package net.lab1024.smartadmin.service.common.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.Valid;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.List;
+
+/**
+ * 分页基础参数
+ *
+ * @author 善逸
+ * @Date Created in 2017/10/28 16:19
+ */
+@Data
+public class PageBaseDTO {
+
+ @ApiModelProperty(value = "页码(不能为空)", required = true, example = "1")
+ @NotNull(message = "分页参数不能为空")
+ private Integer pageNum;
+
+ @ApiModelProperty(value = "每页数量(不能为空)", required = true, example = "10")
+ @NotNull(message = "每页数量不能为空")
+ @Max(value = 200, message = "每页最大为200")
+ private Integer pageSize;
+
+ @ApiModelProperty("排序字段集合")
+ @Size(max = 10, message = "排序字段最多10")
+ @Valid
+ private List sortItemList;
+
+ /**
+ * 排序DTO类
+ */
+ @Data
+ public static class SortItemDTO {
+
+ @ApiModelProperty("true正序|false倒序")
+ @NotNull(message = "排序规则不能为空")
+ private Boolean isAsc;
+
+ @ApiModelProperty(value = "排序字段")
+ @NotBlank(message = "排序字段不能为空")
+ @Length(max = 30, message = "排序字段最多30")
+ private String column;
+ }
+}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/domain/PageResultDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/domain/PageResultDTO.java
similarity index 83%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/domain/PageResultDTO.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/domain/PageResultDTO.java
index 23995832..fee6c0d8 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/domain/PageResultDTO.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/domain/PageResultDTO.java
@@ -1,4 +1,4 @@
-package net.lab1024.smartadmin.common.domain;
+package net.lab1024.smartadmin.service.common.domain;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -8,7 +8,7 @@ import java.util.List;
/**
* Page返回对象
*
- * @Author lihaifan
+ * @Author 善逸
* @Date Created in 2017/10/31 15:05
*/
@Data
@@ -44,4 +44,7 @@ public class PageResultDTO {
@ApiModelProperty(value = "结果集")
private List list;
+ @ApiModelProperty("是否为空")
+ private Boolean emptyFlag;
+
}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/domain/ResponseDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/domain/ResponseDTO.java
similarity index 67%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/domain/ResponseDTO.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/domain/ResponseDTO.java
index 92ec781e..b5bafdf8 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/domain/ResponseDTO.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/domain/ResponseDTO.java
@@ -1,13 +1,13 @@
-package net.lab1024.smartadmin.common.domain;
+package net.lab1024.smartadmin.service.common.domain;
-import net.lab1024.smartadmin.common.constant.ResponseCodeConst;
+import net.lab1024.smartadmin.service.common.codeconst.ResponseCodeConst;
/**
* 返回类
*
* @param
- * @author zhuoda
+ * @author 1024lab
*/
public class ResponseDTO {
@@ -25,7 +25,7 @@ public class ResponseDTO {
public ResponseDTO(ResponseCodeConst responseCodeConst, String msg) {
this.code = responseCodeConst.getCode();
this.msg = msg;
- this.success = responseCodeConst.isSuccess();
+ this.success = responseCodeConst.issucc();
}
public ResponseDTO(ResponseCodeConst responseCodeConst, T data) {
@@ -33,7 +33,7 @@ public class ResponseDTO {
this.code = responseCodeConst.getCode();
this.msg = responseCodeConst.getMsg();
this.data = data;
- this.success = responseCodeConst.isSuccess();
+ this.success = responseCodeConst.issucc();
}
public ResponseDTO(ResponseCodeConst responseCodeConst, T data, String msg) {
@@ -41,13 +41,13 @@ public class ResponseDTO {
this.code = responseCodeConst.getCode();
this.msg = msg;
this.data = data;
- this.success = responseCodeConst.isSuccess();
+ this.success = responseCodeConst.issucc();
}
private ResponseDTO(ResponseCodeConst responseCodeConst) {
this.code = responseCodeConst.getCode();
this.msg = responseCodeConst.getMsg();
- this.success = responseCodeConst.isSuccess();
+ this.success = responseCodeConst.issucc();
}
public ResponseDTO(ResponseDTO responseDTO) {
@@ -56,6 +56,18 @@ public class ResponseDTO {
this.success = responseDTO.isSuccess();
}
+ public ResponseDTO(ResponseCodeConst codeConst, boolean isSuccess) {
+ this.code = codeConst.getCode();
+ this.msg = codeConst.getMsg();
+ this.success = isSuccess;
+ }
+
+ public ResponseDTO(int code, String msg, boolean isSuccess) {
+ this.code = code;
+ this.msg = msg;
+ this.success = isSuccess;
+ }
+
public static ResponseDTO succ() {
return new ResponseDTO(ResponseCodeConst.SUCCESS);
}
@@ -68,27 +80,34 @@ public class ResponseDTO {
return new ResponseDTO(ResponseCodeConst.SUCCESS, data);
}
- public static ResponseDTO succMsg(String msg) {
+ public static ResponseDTO succMsg(String msg) {
return new ResponseDTO(ResponseCodeConst.SUCCESS, msg);
}
-
public static ResponseDTO wrap(ResponseCodeConst codeConst) {
return new ResponseDTO<>(codeConst);
}
- public static ResponseDTO wrap(ResponseCodeConst codeConst, T t) {
- return new ResponseDTO(codeConst, t);
+ public static ResponseDTO wrap(ResponseCodeConst codeConst, boolean isSuccess) {
+ return new ResponseDTO<>(codeConst, isSuccess);
}
- public static ResponseDTO wrap(ResponseCodeConst codeConst, String msg) {
- return new ResponseDTO(codeConst, msg);
+ public static ResponseDTO wrap(ResponseDTO responseDTO) {
+ return new ResponseDTO<>(responseDTO.getCode(), responseDTO.getMsg(), responseDTO.isSuccess());
+ }
+
+ public static ResponseDTO wrapData(ResponseCodeConst codeConst, T t) {
+ return new ResponseDTO(codeConst, t);
}
public static ResponseDTO wrapMsg(ResponseCodeConst codeConst, String msg) {
return new ResponseDTO(codeConst, msg);
}
+ public static ResponseDTO wrapDataMsg(ResponseCodeConst codeConst, T t, String msg) {
+ return new ResponseDTO(codeConst, t, msg);
+ }
+
public String getMsg() {
return msg;
}
@@ -126,7 +145,6 @@ public class ResponseDTO {
@Override
public String toString() {
- return "ResponseDTO{" + "code=" + code + ", msg='" + msg + '\'' + ", success=" + success + ", data=" + data +
- '}';
+ return "ResponseDTO{" + "code=" + code + ", msg='" + msg + '\'' + ", success=" + success + ", data=" + data + '}';
}
}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/excel/ExcelStyle.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/excel/ExcelStyle.java
new file mode 100644
index 00000000..41bdd3d9
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/excel/ExcelStyle.java
@@ -0,0 +1,183 @@
+package net.lab1024.smartadmin.service.common.excel;
+
+import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
+import cn.afterturn.easypoi.excel.entity.params.ExcelForEachParams;
+import cn.afterturn.easypoi.excel.export.styler.IExcelExportStyler;
+import org.apache.poi.ss.usermodel.*;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2020/9/25 19:52
+ */
+public class ExcelStyle implements IExcelExportStyler {
+ private static final short STRING_FORMAT = (short) BuiltinFormats.getBuiltinFormat("TEXT");
+ private static final short FONT_SIZE_TEN = 10;
+ private static final short FONT_SIZE_ELEVEN = 11;
+ private static final short FONT_SIZE_TWELVE = 12;
+ /**
+ * 大标题样式
+ */
+ private CellStyle headerStyle;
+ /**
+ * 每列标题样式
+ */
+ private CellStyle titleStyle;
+ /**
+ * 数据行样式
+ */
+ private CellStyle styles;
+
+ public ExcelStyle(Workbook workbook) {
+ this.init(workbook);
+ }
+
+ /**
+ * 初始化样式
+ *
+ * @param workbook
+ */
+ private void init(Workbook workbook) {
+ this.headerStyle = initHeaderStyle(workbook);
+ this.titleStyle = initTitleStyle(workbook);
+ this.styles = initStyles(workbook);
+ }
+
+ /**
+ * 大标题样式
+ *
+ * @param color
+ * @return
+ */
+ @Override
+ public CellStyle getHeaderStyle(short color) {
+ return headerStyle;
+ }
+
+ /**
+ * 每列标题样式
+ *
+ * @param color
+ * @return
+ */
+ @Override
+ public CellStyle getTitleStyle(short color) {
+ return titleStyle;
+ }
+
+ /**
+ * 数据行样式
+ *
+ * @param parity 可以用来表示奇偶行
+ * @param entity 数据内容
+ * @return 样式
+ */
+ @Override
+ public CellStyle getStyles(boolean parity, ExcelExportEntity entity) {
+ return styles;
+ }
+
+ /**
+ * 获取样式方法
+ *
+ * @param dataRow 数据行
+ * @param obj 对象
+ * @param data 数据
+ */
+ @Override
+ public CellStyle getStyles(Cell cell, int dataRow, ExcelExportEntity entity, Object obj, Object data) {
+ return getStyles(true, entity);
+ }
+
+ /**
+ * 模板使用的样式设置
+ */
+ @Override
+ public CellStyle getTemplateStyles(boolean isSingle, ExcelForEachParams excelForEachParams) {
+ return null;
+ }
+
+ /**
+ * 初始化--大标题样式
+ *
+ * @param workbook
+ * @return
+ */
+ private CellStyle initHeaderStyle(Workbook workbook) {
+ CellStyle style = getBaseCellStyle(workbook);
+ style.setFont(getFont(workbook, FONT_SIZE_TWELVE, true));
+ return style;
+ }
+
+ /**
+ * 初始化--每列标题样式
+ *
+ * @param workbook
+ * @return
+ */
+ private CellStyle initTitleStyle(Workbook workbook) {
+ CellStyle style = getBaseCellStyle(workbook);
+ style.setFont(getFont(workbook, FONT_SIZE_ELEVEN, false));
+ //背景色
+ style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ return style;
+ }
+
+ /**
+ * 初始化--数据行样式
+ *
+ * @param workbook
+ * @return
+ */
+ private CellStyle initStyles(Workbook workbook) {
+ CellStyle style = getBaseCellStyle(workbook);
+ style.setFont(getFont(workbook, FONT_SIZE_TEN, false));
+ style.setDataFormat(STRING_FORMAT);
+ style.setAlignment(HorizontalAlignment.LEFT);
+ return style;
+ }
+
+ /**
+ * 基础样式
+ *
+ * @return
+ */
+ private CellStyle getBaseCellStyle(Workbook workbook) {
+ CellStyle style = workbook.createCellStyle();
+ //下边框
+ style.setBorderBottom(BorderStyle.THIN);
+ //左边框
+ style.setBorderLeft(BorderStyle.THIN);
+ //上边框
+ style.setBorderTop(BorderStyle.THIN);
+ //右边框
+ style.setBorderRight(BorderStyle.THIN);
+ //水平居中
+ style.setAlignment(HorizontalAlignment.CENTER);
+ //上下居中
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ //设置自动换行
+ style.setWrapText(true);
+ return style;
+ }
+
+ /**
+ * 字体样式
+ *
+ * @param size 字体大小
+ * @param isBold 是否加粗
+ * @return
+ */
+ private Font getFont(Workbook workbook, short size, boolean isBold) {
+ Font font = workbook.createFont();
+ //字体样式
+ font.setFontName("宋体");
+ //是否加粗
+ font.setBold(isBold);
+ //字体大小
+ font.setFontHeightInPoints(size);
+ return font;
+ }
+}
\ No newline at end of file
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/exception/SmartBusinessException.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/exception/SmartBusinessException.java
similarity index 69%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/exception/SmartBusinessException.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/exception/SmartBusinessException.java
index 904f3a7b..e167df92 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/exception/SmartBusinessException.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/exception/SmartBusinessException.java
@@ -1,20 +1,22 @@
-package net.lab1024.smartadmin.common.exception;
+package net.lab1024.smartadmin.service.common.exception;
+
+import net.lab1024.smartadmin.service.common.codeconst.ResponseCodeConst;
+
/**
- *
* [ 业务逻辑异常,全局异常拦截后统一返回ResponseCodeConst.SYSTEM_ERROR ]
- *
- * @version 1.0
- * @since JDK1.8
- * @author yandanyang
- * @company 1024lab.net
- * @copyright (c) 2019 1024lab.netInc. All rights reserved.
- * @date
+ *
+ * @author 罗伊
+ * @date 2020/8/25 11:57
*/
public class SmartBusinessException extends RuntimeException {
public SmartBusinessException() {
}
+ public SmartBusinessException(ResponseCodeConst responseCodeConst) {
+ super(responseCodeConst.getMsg());
+ }
+
public SmartBusinessException(String message) {
super(message);
}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/json/BigDecimalNullZeroSerializer.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/json/BigDecimalNullZeroSerializer.java
new file mode 100644
index 00000000..532c45b5
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/json/BigDecimalNullZeroSerializer.java
@@ -0,0 +1,26 @@
+package net.lab1024.smartadmin.service.common.json;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2020/8/20 16:04
+ */
+public class BigDecimalNullZeroSerializer extends JsonSerializer {
+
+ @Override
+ public void serialize(BigDecimal value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+ if (value == null) {
+ jsonGenerator.writeNumber(BigDecimal.ZERO);
+ return;
+ }
+ jsonGenerator.writeNumber(value);
+ }
+}
\ No newline at end of file
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/json/FileKeySerializer.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/json/FileKeySerializer.java
new file mode 100644
index 00000000..557d2487
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/json/FileKeySerializer.java
@@ -0,0 +1,42 @@
+package net.lab1024.smartadmin.service.common.json;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
+import net.lab1024.smartadmin.service.module.support.file.service.FileService;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.io.IOException;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2020/8/15 15:06
+ */
+public class FileKeySerializer extends JsonSerializer {
+
+ @Autowired
+ private FileService fileService;
+
+
+ @Override
+ public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+ if (StringUtils.isEmpty(value)) {
+ jsonGenerator.writeString(value);
+ return;
+ }
+ if(fileService == null){
+ jsonGenerator.writeString(value);
+ return;
+ }
+ ResponseDTO responseDTO = fileService.getFileUrl(value);
+ if(responseDTO.isSuccess()){
+ jsonGenerator.writeString(responseDTO.getData());
+ return;
+ }
+ jsonGenerator.writeString(value);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/json/FileKeyVoSerializer.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/json/FileKeyVoSerializer.java
new file mode 100644
index 00000000..a0af56bf
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/json/FileKeyVoSerializer.java
@@ -0,0 +1,43 @@
+package net.lab1024.smartadmin.service.common.json;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.google.common.collect.Lists;
+import net.lab1024.smartadmin.service.module.support.file.domain.vo.FileVO;
+import net.lab1024.smartadmin.service.module.support.file.service.FileService;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2020/8/15 15:06
+ */
+public class FileKeyVoSerializer extends JsonSerializer {
+
+ @Autowired
+ private FileService fileService;
+
+
+ @Override
+ public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+ if (StringUtils.isEmpty(value)) {
+ jsonGenerator.writeObject(Lists.newArrayList());
+ return;
+ }
+ if(fileService == null){
+ jsonGenerator.writeString(value);
+ return;
+ }
+ String[] fileKeyArray = value.split(",");
+ List fileKeyList = Arrays.asList(fileKeyArray);
+ List fileKeyVOList = fileService.getFileList(fileKeyList);
+ jsonGenerator.writeObject(fileKeyVOList);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/security/SmartSecurityMetadataSource.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/security/SmartSecurityMetadataSource.java
new file mode 100644
index 00000000..11300478
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/security/SmartSecurityMetadataSource.java
@@ -0,0 +1,114 @@
+package net.lab1024.smartadmin.service.common.security;
+
+import net.lab1024.smartadmin.service.common.anno.NoValidPrivilege;
+import net.lab1024.smartadmin.service.util.SmartSecurityUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.prepost.*;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * 此类用于默认给所有接口添加权限 @privilegeCheck.checkPermission('%s')
+ * %s 为类名.方法名
+ * 和使用@PreAuthorize("@privilegeCheck.checkPermission('%s')") 效果一致
+ * 避免所有接口都添加一遍 减轻工作量
+ *
+ * @author 罗伊
+ * @date 2021-08-30 23:08
+ */
+public class SmartSecurityMetadataSource extends PrePostAnnotationSecurityMetadataSource {
+
+ public static final String PRIVILEGE_CHECK_NAME = "privilegeCheck";
+
+ private static String EXPRESSION_FORMAT = "@privilegeCheck.checkPermission('%s')";
+
+ private final PrePostInvocationAttributeFactory attributeFactory;
+
+ private String projectModule;
+
+ private List ignoreUrlList;
+
+ public SmartSecurityMetadataSource(PrePostInvocationAttributeFactory attributeFactory, List ignoreUrlList, String projectModule) {
+ super(attributeFactory);
+ this.attributeFactory = attributeFactory;
+ this.projectModule = projectModule;
+ this.ignoreUrlList = ignoreUrlList;
+ }
+
+
+ @Override
+ public Collection getAttributes(Method method, Class> targetClass) {
+ //只对固定的包的所有接口进行控制
+ if (!targetClass.getName().startsWith(projectModule)) {
+ return super.getAttributes(method, targetClass);
+ }
+ //是否需要权限
+ NoValidPrivilege methodNoValidPrivilege = method.getAnnotation(NoValidPrivilege.class);
+ if (methodNoValidPrivilege != null) {
+ return Collections.emptyList();
+ }
+ NoValidPrivilege classNoValidPrivilege = targetClass.getAnnotation(NoValidPrivilege.class);
+ if (classNoValidPrivilege != null) {
+ return Collections.emptyList();
+ }
+ //是否添加security原有注解
+ PreAuthorize preAuthorize = method.getAnnotation(PreAuthorize.class);
+ if (preAuthorize != null) {
+ return super.getAttributes(method, targetClass);
+ }
+ PostAuthorize postAuthorize = method.getAnnotation(PostAuthorize.class);
+ if (postAuthorize != null) {
+ return super.getAttributes(method, targetClass);
+ }
+ //自己的控制
+ GetMapping getMapping = method.getAnnotation(GetMapping.class);
+ PostMapping postMapping = method.getAnnotation(PostMapping.class);
+ RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
+ if (getMapping == null && postMapping == null && requestMapping == null) {
+ return super.getAttributes(method, targetClass);
+ }
+ //获取注解值
+ String uriPrefix = SmartSecurityUtil.getUriPrefix(method);
+ List annotationValueList = SmartSecurityUtil.getAnnotationValueList(method, uriPrefix);
+ //判断是否被忽略
+ if (this.contain(ignoreUrlList, annotationValueList)) {
+ return super.getAttributes(method, targetClass);
+ }
+ ArrayList configAttributes = new ArrayList(1);
+ String classFullName = targetClass.getName();
+ String methodName = method.getName();
+ String[] classNameArray = StringUtils.split(classFullName, "\\.");
+ String controllerName = classNameArray[classNameArray.length - 1];
+ String privilegeName = controllerName + "." + methodName;
+ String preAuthorizeAttribute = String.format(EXPRESSION_FORMAT, privilegeName);
+ PreInvocationAttribute pre = this.attributeFactory.createPreInvocationAttribute(null, null, preAuthorizeAttribute);
+ if (pre != null) {
+ configAttributes.add(pre);
+ }
+ return configAttributes;
+ }
+
+ public Boolean contain(List ignores, List valueList) {
+ if (CollectionUtils.isEmpty(ignores)) {
+ return false;
+ }
+ for (String ignoreUrl : ignores) {
+ for (String uri : valueList) {
+ if (uri.contains(ignoreUrl)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/security/SmartSecurityNoLoginUrl.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/security/SmartSecurityNoLoginUrl.java
new file mode 100644
index 00000000..4fd8e11c
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/security/SmartSecurityNoLoginUrl.java
@@ -0,0 +1,72 @@
+package net.lab1024.smartadmin.service.common.security;
+
+import com.google.common.collect.Lists;
+import net.lab1024.smartadmin.service.common.anno.NoNeedLogin;
+import net.lab1024.smartadmin.service.util.SmartSecurityUtil;
+import org.apache.commons.collections4.CollectionUtils;
+import org.reflections.Reflections;
+import org.reflections.scanners.MethodAnnotationsScanner;
+import org.reflections.scanners.TypeAnnotationsScanner;
+import org.reflections.util.ConfigurationBuilder;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2021/8/31 10:20
+ */
+public class SmartSecurityNoLoginUrl {
+
+ private List noLoginUrlList;
+
+ public SmartSecurityNoLoginUrl(String scanPath){
+ this.noLoginUrlList = this.initNoLoginUrlList(scanPath);
+ }
+
+
+ public List getNoLoginUrlList(){
+ return noLoginUrlList;
+ }
+
+ /**
+ * 获取无需登录的url信息
+ *
+ * @return
+ */
+ private List initNoLoginUrlList(String scanPath) {
+ List noLoginUrlList = Lists.newArrayList();
+ //一些常量uri
+ noLoginUrlList.add("/swagger-ui.html");
+ noLoginUrlList.add("/swagger-resources/**");
+ noLoginUrlList.add("/webjars/**");
+ noLoginUrlList.add("/*/api-docs");
+ //添加无需登录注解的uri
+ Reflections reflections = new Reflections(new ConfigurationBuilder().forPackages(scanPath).addScanners(new MethodAnnotationsScanner(), new TypeAnnotationsScanner()));
+ Set methodSet = reflections.getMethodsAnnotatedWith(NoNeedLogin.class);
+ Set> classSet = reflections.getTypesAnnotatedWith(NoNeedLogin.class);
+ //方法级别无需登录
+ for (Method method : methodSet) {
+ String uriPrefix = SmartSecurityUtil.getUriPrefix(method);
+ List valueList = SmartSecurityUtil.getAnnotationValueList(method, uriPrefix);
+ noLoginUrlList.addAll(valueList);
+ }
+ //类级别无需登录
+ for (Class clazz : classSet) {
+ Method[] methods = clazz.getMethods();
+ for (Method method : methods) {
+ String uriPrefix = SmartSecurityUtil.getUriPrefix(method);
+ List valueList = SmartSecurityUtil.getAnnotationValueList(method, uriPrefix);
+ noLoginUrlList.addAll(valueList);
+ }
+ }
+ return noLoginUrlList;
+ }
+
+
+}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/anno/ApiModelPropertyEnum.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/swagger/ApiModelPropertyEnum.java
similarity index 67%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/anno/ApiModelPropertyEnum.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/swagger/ApiModelPropertyEnum.java
index c9babff3..616c3abc 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/anno/ApiModelPropertyEnum.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/swagger/ApiModelPropertyEnum.java
@@ -1,6 +1,6 @@
-package net.lab1024.smartadmin.common.anno;
+package net.lab1024.smartadmin.service.common.swagger;
-import net.lab1024.smartadmin.common.domain.BaseEnum;
+import net.lab1024.smartadmin.service.common.constant.BaseEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -8,7 +8,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * 枚举类字段属性的注解
+ * 枚举类字段属性的 自定义 swagger 注解
*
* @author listen
* @date 2019/05/16 15:18
@@ -26,22 +26,12 @@ public @interface ApiModelPropertyEnum {
String example() default "";
- /**
- * 是否隐藏
- *
- * @return
- */
boolean hidden() default false;
- /**
- * 是否必须
- *
- * @return
- */
boolean required() default true;
String dataType() default "";
- String enumDesc() default "";
+ String desc() default "";
}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/swagger/SmartSwaggerApiModelEnumPlugin.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/swagger/ApiModelPropertyEnumPlugin.java
similarity index 55%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/swagger/SmartSwaggerApiModelEnumPlugin.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/swagger/ApiModelPropertyEnumPlugin.java
index dbc2d586..f4a8af4b 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/swagger/SmartSwaggerApiModelEnumPlugin.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/swagger/ApiModelPropertyEnumPlugin.java
@@ -1,30 +1,12 @@
-/*
- *
- * Copyright 2015 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *
- */
+package net.lab1024.smartadmin.service.common.swagger;
-package net.lab1024.smartadmin.common.swagger;
-
-import net.lab1024.smartadmin.common.anno.ApiModelPropertyEnum;
-import net.lab1024.smartadmin.common.domain.BaseEnum;
import com.google.common.base.Function;
import com.google.common.base.Optional;
+import net.lab1024.smartadmin.service.common.constant.BaseEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
@@ -41,26 +23,28 @@ import static springfox.documentation.schema.Annotations.findPropertyAnnotation;
* @author listen
* @date 2019年5月16日 15:36:56
*/
-public class SmartSwaggerApiModelEnumPlugin implements ModelPropertyBuilderPlugin {
+@Component
+@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1)
+public class ApiModelPropertyEnumPlugin implements ModelPropertyBuilderPlugin {
@Override
public void apply(ModelPropertyContext context) {
- Optional enumOptional = Optional.absent();
+ Optional annotation = Optional.absent();
if (context.getAnnotatedElement().isPresent()) {
- enumOptional = enumOptional.or(findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
+ annotation = annotation.or(findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
}
if (context.getBeanPropertyDefinition().isPresent()) {
- enumOptional = enumOptional.or(findPropertyAnnotation(context.getBeanPropertyDefinition().get(), ApiModelPropertyEnum.class));
+ annotation = annotation.or(findPropertyAnnotation(context.getBeanPropertyDefinition().get(), ApiModelPropertyEnum.class));
}
- if (enumOptional.isPresent()) {
- ApiModelPropertyEnum anEnum = enumOptional.get();
+ if (annotation.isPresent()) {
+ ApiModelPropertyEnum anEnum = annotation.get();
String enumInfo = BaseEnum.getInfo(anEnum.value());
context.getBuilder()
- .required(enumOptional.transform(toIsRequired()).or(false))
- .description(anEnum.enumDesc() + ":" + enumInfo)
- .example(enumOptional.transform(toExample()).orNull())
+ .required(annotation.transform(toIsRequired()).or(false))
+ .description(anEnum.desc() + ":" + enumInfo)
+ .example(annotation.transform(toExample()).orNull())
.isHidden(anEnum.hidden());
}
}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/validator/bigdecimal/ComparisonSymbolEnum.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/validator/BigDecimalSymbolEnum.java
similarity index 80%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/validator/bigdecimal/ComparisonSymbolEnum.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/validator/BigDecimalSymbolEnum.java
index e59d0bf3..2adcb648 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/validator/bigdecimal/ComparisonSymbolEnum.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/validator/BigDecimalSymbolEnum.java
@@ -1,4 +1,4 @@
-package net.lab1024.smartadmin.common.validator.bigdecimal;
+package net.lab1024.smartadmin.service.common.validator;
/**
* 比较符枚举类
@@ -6,7 +6,7 @@ package net.lab1024.smartadmin.common.validator.bigdecimal;
* @author listen
* @date 2018/03/20 14:01
*/
-public enum ComparisonSymbolEnum {
+public enum BigDecimalSymbolEnum {
/**
* 等于
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/validator/bigdecimal/BigDecimalValidator.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/validator/BigDecimalValidator.java
similarity index 92%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/validator/bigdecimal/BigDecimalValidator.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/validator/BigDecimalValidator.java
index 5ba85bf7..507c7436 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/validator/bigdecimal/BigDecimalValidator.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/validator/BigDecimalValidator.java
@@ -1,6 +1,6 @@
-package net.lab1024.smartadmin.common.validator.bigdecimal;
+package net.lab1024.smartadmin.service.common.validator;
-import net.lab1024.smartadmin.util.SmartBigDecimalUtil;
+import net.lab1024.smartadmin.service.util.SmartBigDecimalUtil;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
@@ -22,7 +22,7 @@ public class BigDecimalValidator implements ConstraintValidator {
+public class CheckEnumValidator implements ConstraintValidator {
/**
* 枚举类实例集合
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/domain/ValidateList.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/validator/ValidateList.java
similarity index 97%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/domain/ValidateList.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/validator/ValidateList.java
index c3907e63..c4b82873 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/common/domain/ValidateList.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/common/validator/ValidateList.java
@@ -1,11 +1,11 @@
-package net.lab1024.smartadmin.common.domain;
+package net.lab1024.smartadmin.service.common.validator;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.*;
/**
- * @author: zhuoda
+ * @author: 卓大
* @create: 2020-02-03 17:37 PM from win10
*/
public class ValidateList implements List {
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SecurityConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SecurityConfig.java
new file mode 100644
index 00000000..40c1538f
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SecurityConfig.java
@@ -0,0 +1,113 @@
+package net.lab1024.smartadmin.service.config;
+
+import net.lab1024.smartadmin.service.common.security.SmartSecurityNoLoginUrl;
+import net.lab1024.smartadmin.service.filters.SmartTokenFilter;
+import net.lab1024.smartadmin.service.handler.AuthenticationFailHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import java.util.List;
+
+/**
+ * Spring Security
+ *
+ * @author 善逸
+ * @date 2021/8/3 17:50
+ */
+@Configuration
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Value("${access-control-allow-origin}")
+ private String accessControlAllowOrigin;
+
+ /**
+ * 认证失败处理类
+ */
+ @Autowired
+ private AuthenticationFailHandler authenticationFailHandler;
+
+ /**
+ * 无需登录的url
+ */
+ @Autowired
+ private SmartSecurityNoLoginUrl smartSecurityNoLoginUrl;
+
+ /**
+ * token过滤器
+ */
+ @Autowired
+ private SmartTokenFilter smartTokenFilter;
+
+ /**
+ * 跨域配置
+ *
+ * @return
+ */
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ CorsConfiguration config = new CorsConfiguration();
+ config.setAllowCredentials(true);
+ // 设置访问源地址
+ config.addAllowedOriginPattern(accessControlAllowOrigin);
+ // 设置访问源请求头
+ config.addAllowedHeader("*");
+ // 设置访问源请求方法
+ config.addAllowedMethod("*");
+ // 对接口配置跨域设置
+ source.registerCorsConfiguration("/**", config);
+ return new CorsFilter(source);
+ }
+
+ /**
+ * anyRequest | 匹配所有请求路径
+ * access | SpringEl表达式结果为true时可以访问
+ * anonymous | 匿名可以访问
+ * denyAll | 用户不能访问
+ * fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录)
+ * hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问
+ * hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问
+ * hasAuthority | 如果有参数,参数表示权限,则其权限可以访问
+ * hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
+ * hasRole | 如果有参数,参数表示角色,则其角色可以访问
+ * permitAll | 用户可以任意访问
+ * rememberMe | 允许通过remember-me登录的用户访问
+ * authenticated | 用户登录后可访问
+ */
+ @Override
+ protected void configure(HttpSecurity httpSecurity) throws Exception {
+ httpSecurity
+ // CSRF禁用,因为不使用session
+ .csrf().disable()
+ // 认证失败处理类
+ .exceptionHandling().authenticationEntryPoint(authenticationFailHandler).and()
+ // 基于token,所以不需要session
+ .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
+ // 过滤请求
+ .authorizeRequests()
+ .antMatchers("/admin/**").authenticated();
+
+ httpSecurity.addFilterBefore(smartTokenFilter, UsernamePasswordAuthenticationFilter.class);
+ httpSecurity.addFilterBefore(corsFilter(), SmartTokenFilter.class);
+ }
+
+ @Override
+ public void configure(WebSecurity web) {
+ // 忽略url
+ WebSecurity.IgnoredRequestConfigurer ignoring = web.ignoring();
+ List noLoginUrlList = smartSecurityNoLoginUrl.getNoLoginUrlList();
+ for (String url : noLoginUrlList) {
+ ignoring.antMatchers(url);
+ }
+ }
+
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SecurityMethodConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SecurityMethodConfig.java
new file mode 100644
index 00000000..97796c0e
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SecurityMethodConfig.java
@@ -0,0 +1,35 @@
+package net.lab1024.smartadmin.service.config;
+
+import net.lab1024.smartadmin.service.common.security.SmartSecurityMetadataSource;
+import net.lab1024.smartadmin.service.common.security.SmartSecurityNoLoginUrl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.access.expression.method.ExpressionBasedAnnotationAttributeFactory;
+import org.springframework.security.access.method.MethodSecurityMetadataSource;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
+
+/**
+ * 此类用于注入自己的 method校验
+ * SmartSecurityMetadataSource
+ * @author 罗伊
+ * @date 2021-08-31 0:01
+ */
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class SecurityMethodConfig extends GlobalMethodSecurityConfiguration {
+
+ @Value("${project.module}")
+ private String projectModule;
+
+ /**
+ * 无需登录的url
+ */
+ @Autowired
+ private SmartSecurityNoLoginUrl smartSecurityNoLoginUrl;
+
+ @Override
+ public MethodSecurityMetadataSource customMethodSecurityMetadataSource(){
+ ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory(this.getExpressionHandler());
+ return new SmartSecurityMetadataSource(attributeFactory, smartSecurityNoLoginUrl.getNoLoginUrlList(),projectModule);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SecurityNoLoginUrlConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SecurityNoLoginUrlConfig.java
new file mode 100644
index 00000000..d9687c42
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SecurityNoLoginUrlConfig.java
@@ -0,0 +1,24 @@
+package net.lab1024.smartadmin.service.config;
+
+import net.lab1024.smartadmin.service.common.security.SmartSecurityNoLoginUrl;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2021/9/1 21:40
+ */
+@Configuration
+public class SecurityNoLoginUrlConfig {
+
+ @Value("${project.module}")
+ private String projectModule;
+
+ @Bean
+ public SmartSecurityNoLoginUrl securityNoLoginUrl(){
+ return new SmartSecurityNoLoginUrl(projectModule);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartAsyncConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartAsyncConfig.java
new file mode 100644
index 00000000..3c52c056
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartAsyncConfig.java
@@ -0,0 +1,66 @@
+package net.lab1024.smartadmin.service.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.task.AsyncTaskExecutor;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+/**
+ * 异步调用线程配置
+ *
+ * @author 胡克
+ * @date 2019/12/26 11:54
+ */
+@Slf4j
+@Configuration
+public class SmartAsyncConfig {
+
+ /**
+ * 线程池 配置bean名称
+ */
+ public static final String ASYNC_EXECUTOR = "asyncExecutor";
+
+ /**
+ * 配置线程池
+ *
+ * @return
+ */
+ @Bean(name = ASYNC_EXECUTOR)
+ public AsyncTaskExecutor executor() {
+ ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
+ // 核心线程数量
+ taskExecutor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
+ // 最大线程数量
+ taskExecutor.setMaxPoolSize(Runtime.getRuntime().availableProcessors());
+ taskExecutor.setThreadNamePrefix(ASYNC_EXECUTOR);
+ taskExecutor.initialize();
+ return taskExecutor;
+ }
+
+ /**
+ * spring 异步任务 异常配置
+ */
+ @Configuration
+ public static class AsyncExceptionConfig implements AsyncConfigurer {
+ @Override
+ public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+ return new AsyncExceptionHandler();
+ }
+ }
+
+ /**
+ * 自定义异常处理
+ */
+ public static class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
+ @Override
+ public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
+ log.error("异步任务发生异常:{}, 参数:{}, ", method.getDeclaringClass().getSimpleName() + "." + method.getName(), Arrays.toString(objects), throwable);
+ }
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartCacheConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartCacheConfig.java
new file mode 100644
index 00000000..0a63ced3
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartCacheConfig.java
@@ -0,0 +1,63 @@
+package net.lab1024.smartadmin.service.config;
+
+import com.github.benmanes.caffeine.cache.LoadingCache;
+import com.google.common.collect.Maps;
+import net.lab1024.smartadmin.service.module.support.beancache.cache.AbstractCaffeineCache;
+import net.lab1024.smartadmin.service.module.support.beancache.cache.AbstractDisableCache;
+import net.lab1024.smartadmin.service.module.support.beancache.cache.IBeanCache;
+import net.lab1024.smartadmin.service.module.support.beancache.domain.CacheData;
+import net.lab1024.smartadmin.service.module.support.beancache.load.CacheLoad;
+import net.lab1024.smartadmin.service.module.support.beancache.load.CacheLoadMethod;
+import org.reflections.Reflections;
+import org.reflections.scanners.MethodAnnotationsScanner;
+import org.reflections.util.ConfigurationBuilder;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2020/9/6 16:01
+ */
+@Configuration
+public class SmartCacheConfig {
+
+ @Value("${cache.maximumSize:5000}")
+ private Integer cacheMaximumSize;
+
+ @Value("${cache.expireDays:5}")
+ private Integer expireDays;
+
+ @Value("${cache.scanPath}")
+ private String scanPath;
+
+ @Bean
+ @Primary
+ public IBeanCache beanCache() {
+ return new AbstractCaffeineCache() {
+ LoadingCache cache = this.initCache(cacheMaximumSize,expireDays, scanPath);
+ @Override
+ public LoadingCache getCache() {
+ return cache;
+ }
+ };
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(IBeanCache.class)
+ public IBeanCache beanDisableCache() {
+ return new AbstractDisableCache(scanPath);
+ }
+
+
+
+}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/config/SmartKaptchaConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartCaptchaConfig.java
similarity index 51%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/config/SmartKaptchaConfig.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartCaptchaConfig.java
index 06dd1c95..2415bd32 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/config/SmartKaptchaConfig.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartCaptchaConfig.java
@@ -1,9 +1,9 @@
-package net.lab1024.smartadmin.config;
+package net.lab1024.smartadmin.service.config;
-import net.lab1024.smartadmin.common.kaptcha.KaptchaNoise;
-import net.lab1024.smartadmin.common.kaptcha.KaptchaWordRenderer;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
+import net.lab1024.smartadmin.service.module.support.captcha.render.CaptchaNoise;
+import net.lab1024.smartadmin.service.module.support.captcha.render.CaptchaWordRenderer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -12,36 +12,38 @@ import java.util.Properties;
/**
* [ 验证码配置 ]
*
- * @author yandanyang
+ * @author 罗伊
* @version 1.0
- * @company 1024lab.net
- * @copyright (c) 2018 1024lab.netInc. All rights reserved.
- * @date 2019/7/4 0004 上午 9:40
* @since JDK1.8
*/
@Configuration
-public class SmartKaptchaConfig {
+public class SmartCaptchaConfig {
+ /**
+ * 图形验证码配置
+ *
+ * @return
+ */
@Bean
- public DefaultKaptcha getDefaultKaptcha(){
- DefaultKaptcha defaultKaptcha=new DefaultKaptcha();
- Properties properties=new Properties();
- properties.setProperty("kaptcha.border", "no");
- properties.setProperty("kaptcha.border.color", "34,114,200");
- properties.setProperty("kaptcha.image.width", "125");
- properties.setProperty("kaptcha.image.height", "45");
- properties.setProperty("kaptcha.textproducer.char.string", "0123456789");
- properties.setProperty("kaptcha.textproducer.char.length", "4");
- properties.setProperty("kaptcha.textproducer.font.names", "Arial,Arial Narrow,Serif,Helvetica,Tahoma,Times New Roman,Verdana");
- properties.setProperty("kaptcha.textproducer.font.size", "38");
+ public DefaultKaptcha getDefaultCaptcha() {
+ DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+ Properties properties = new Properties();
+ properties.setProperty("kaptcha.border", "no" );
+ properties.setProperty("kaptcha.border.color", "34,114,200" );
+ properties.setProperty("kaptcha.image.width", "125" );
+ properties.setProperty("kaptcha.image.height", "45" );
+ properties.setProperty("kaptcha.textproducer.char.string", "123456789" );
+ properties.setProperty("kaptcha.textproducer.char.length", "4" );
+ properties.setProperty("kaptcha.textproducer.font.names", "Arial,Arial Narrow,Serif,Helvetica,Tahoma,Times New Roman,Verdana" );
+ properties.setProperty("kaptcha.textproducer.font.size", "38" );
- properties.setProperty("kaptcha.background.clear.from", "white");
- properties.setProperty("kaptcha.background.clear.to", "white");
+ properties.setProperty("kaptcha.background.clear.from", "white" );
+ properties.setProperty("kaptcha.background.clear.to", "white" );
- properties.setProperty("kaptcha.word.impl", KaptchaWordRenderer.class.getName());
- properties.setProperty("kaptcha.noise.impl", KaptchaNoise.class.getName());
+ properties.setProperty("kaptcha.word.impl", CaptchaWordRenderer.class.getName());
+ properties.setProperty("kaptcha.noise.impl", CaptchaNoise.class.getName());
- Config config=new Config(properties);
+ Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartConverterStringToLocalDate.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartConverterStringToLocalDate.java
new file mode 100644
index 00000000..1eb1a1f1
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartConverterStringToLocalDate.java
@@ -0,0 +1,34 @@
+package net.lab1024.smartadmin.service.config;
+
+import net.lab1024.smartadmin.service.util.date.SmartDateFormatterEnum;
+import net.lab1024.smartadmin.service.util.date.SmartLocalDateUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.converter.Converter;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeParseException;
+
+/**
+ * string 转为 LocalDate 配置类
+ *
+ * @author 胡克
+ * @date 2020/3/6 14:34
+ */
+@Configuration
+public class SmartConverterStringToLocalDate implements Converter {
+
+ @Override
+ public LocalDate convert(String str) {
+ if (StringUtils.isBlank(str)) {
+ return null;
+ }
+ LocalDate localDate;
+ try {
+ localDate = SmartLocalDateUtil.parseDate(str, SmartDateFormatterEnum.YMD);
+ } catch (DateTimeParseException e) {
+ throw new RuntimeException("请输入正确的日期格式:yyyy-MM-dd");
+ }
+ return localDate;
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartConverterStringToLocalDateTime.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartConverterStringToLocalDateTime.java
new file mode 100644
index 00000000..4bdbf494
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartConverterStringToLocalDateTime.java
@@ -0,0 +1,37 @@
+package net.lab1024.smartadmin.service.config;
+
+import net.lab1024.smartadmin.service.util.date.SmartDateFormatterEnum;
+import net.lab1024.smartadmin.service.util.date.SmartLocalDateUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.converter.Converter;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeParseException;
+
+/**
+ * string 转为 LocalDate 配置类
+ *
+ * @author 胡克
+ * @date 2020/3/6 14:34
+ */
+@Configuration
+public class SmartConverterStringToLocalDateTime implements Converter {
+
+
+ @Override
+ public LocalDateTime convert(String str) {
+ if (StringUtils.isBlank(str)) {
+ return null;
+ }
+ LocalDateTime localDateTime;
+ try {
+ localDateTime = SmartLocalDateUtil.parse(str, SmartDateFormatterEnum.YMD_HMS);
+ } catch (DateTimeParseException e) {
+ throw new RuntimeException("请输入正确的日期格式:yyyy-MM-dd HH:mm:ss");
+ }
+ return localDateTime;
+ }
+
+
+}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/config/SmartDruidDataSourceConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartDruidDataSourceConfig.java
similarity index 62%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/config/SmartDruidDataSourceConfig.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartDruidDataSourceConfig.java
index 560bda2a..c476a87b 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/config/SmartDruidDataSourceConfig.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartDruidDataSourceConfig.java
@@ -1,4 +1,4 @@
-package net.lab1024.smartadmin.config;
+package net.lab1024.smartadmin.service.config;
import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.stat.StatFilter;
@@ -6,17 +6,25 @@ import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
-import com.alibaba.druid.util.JdbcConstants;
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.plugin.Interceptor;
+import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
import java.sql.SQLException;
@@ -25,60 +33,59 @@ import java.util.HashMap;
import java.util.Map;
/**
- * [ 数据源配置 ]
+ * [ ]
*
- * @author yandanyang
- * @version 1.0
- * @company 1024lab.net
- * @copyright (c) 2019 1024lab.netInc. All rights reserved.
- * @date
- * @since JDK1.8
+ * @author 罗伊
+ * @date 2020/8/25 11:57
*/
@Slf4j
@Configuration
public class SmartDruidDataSourceConfig {
@Value("${spring.datasource.driver-class-name}")
- String driver;
+ private String driver;
@Value("${spring.datasource.url}")
- String url;
+ private String url;
@Value("${spring.datasource.username}")
- String username;
+ private String username;
@Value("${spring.datasource.password}")
- String password;
+ private String password;
@Value("${spring.datasource.initial-size}")
- int initialSize;
+ private int initialSize;
@Value("${spring.datasource.min-idle}")
- int minIdle;
+ private int minIdle;
@Value("${spring.datasource.max-active}")
- int maxActive;
+ private int maxActive;
@Value("${spring.datasource.max-wait}")
- long maxWait;
+ private long maxWait;
@Value("${spring.datasource.time-between-eviction-runs-millis}")
- long timeBetweenEvictionRunsMillis;
+ private long timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.min-evictable-idle-time-millis}")
- long minEvictableIdleTimeMillis;
+ private long minEvictableIdleTimeMillis;
@Value("${spring.datasource.filters}")
- String filters;
+ private String filters;
@Value("${spring.datasource.druid.username}")
- String druidUserName;
+ private String druidUserName;
@Value("${spring.datasource.druid.password}")
- String druidPassword;
+ private String druidPassword;
@Value("${spring.datasource.druid.login.enabled}")
- boolean druidLoginEnable;
+ private boolean druidLoginEnable;
+
+ @Value("${spring.datasource.druid.service.scanner}")
+ private String serviceScanner;
@Autowired
private StatFilter logSlowSql;
@@ -86,11 +93,14 @@ public class SmartDruidDataSourceConfig {
@Autowired
private DruidStatInterceptor druidStatInterceptor;
+ @Autowired
+ private MybatisPlusInterceptor mybatisPlusInterceptor;
+
@Bean
@Primary
public DataSource druidDataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
- druidDataSource.setDbType(JdbcConstants.MYSQL);
+ druidDataSource.setDbType(DbType.MYSQL.getDb());
druidDataSource.setDriverClassName(driver);
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
@@ -101,6 +111,7 @@ public class SmartDruidDataSourceConfig {
druidDataSource.setMaxWait(maxWait);
druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
+ druidDataSource.setValidationQuery("SELECT 1");
try {
druidDataSource.setFilters(filters);
ArrayList arrayList = new ArrayList<>();
@@ -115,12 +126,33 @@ public class SmartDruidDataSourceConfig {
}
@Bean
- public ServletRegistrationBean druidServlet() {
- ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
+ public SqlSessionFactory sqlSessionFactory() throws Exception {
+ MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
+ factoryBean.setDataSource(druidDataSource());
+ PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
+ Resource[] resources = resolver.getResources("classpath*:/mapper/**/*.xml");
+ factoryBean.setMapperLocations(resources);
+
+ // 设置 MyBatis-Plus 分页插件
+ Interceptor[] plugins = {mybatisPlusInterceptor};
+ factoryBean.setPlugins(plugins);
+
+ return factoryBean.getObject();
+ }
+
+ /**
+ * 非正式环境 加载
+ *
+ * @return
+ */
+ @Bean
+ @Conditional(SmartSystemEnvNotProdCondition.class)
+ public ServletRegistrationBean druidServlet() {
+ ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
servletRegistrationBean.setServlet(new StatViewServlet());
servletRegistrationBean.addUrlMappings("/druid/*");
Map initParameters = new HashMap();
- //不设置用户名密码可以直接通过druid/index.html访问
+ // 不设置用户名密码可以直接通过druid/index.html访问
if (druidLoginEnable) {
initParameters.put("loginUsername", druidUserName);
initParameters.put("loginPassword", druidPassword);
@@ -131,11 +163,11 @@ public class SmartDruidDataSourceConfig {
}
@Bean
- public FilterRegistrationBean filterRegistrationBean() {
- FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
+ public FilterRegistrationBean filterRegistrationBean() {
+ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
- filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
+ filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/*");
return filterRegistrationBean;
}
@@ -143,21 +175,20 @@ public class SmartDruidDataSourceConfig {
public StatFilter logSlowSql() {
StatFilter statFilter = new StatFilter();
statFilter.setMergeSql(true);
- statFilter.setSlowSqlMillis(300);
+ statFilter.setSlowSqlMillis(500);
statFilter.setLogSlowSql(true);
return statFilter;
}
@Bean(name = "druid-stat-interceptor")
public DruidStatInterceptor druidStatInterceptor() {
- DruidStatInterceptor dsInterceptor = new DruidStatInterceptor();
- return dsInterceptor;
+ return new DruidStatInterceptor();
}
@Bean
public JdkRegexpMethodPointcut jdkRegexpMethodPointcut() {
JdkRegexpMethodPointcut jdkRegexpMethodPointcut = new JdkRegexpMethodPointcut();
- jdkRegexpMethodPointcut.setPatterns("net.lab1024.smartadmin.module..*Service.*");
+ jdkRegexpMethodPointcut.setPatterns(serviceScanner);
return jdkRegexpMethodPointcut;
}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartHeartBeatConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartHeartBeatConfig.java
new file mode 100644
index 00000000..27b21521
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartHeartBeatConfig.java
@@ -0,0 +1,40 @@
+package net.lab1024.smartadmin.service.config;
+
+import net.lab1024.smartadmin.service.module.support.heartbeat.HeartBeatRecordHandler;
+import net.lab1024.smartadmin.service.module.support.heartbeat.core.HeartBeatManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * [ 服务心跳配置 ]
+ *
+ * @author 罗伊
+ * @date 2021/1/9 14:13
+ */
+@Configuration
+public class SmartHeartBeatConfig {
+
+ /**
+ * 延迟执行时间
+ */
+ @Value("${heart-beat.delayHandlerTime}")
+ private Long delayHandlerTime;
+
+ /**
+ * 间隔执行时间
+ */
+ @Value("${heart-beat.intervalTime}")
+ private Long intervalTime;
+
+ @Autowired
+ private HeartBeatRecordHandler heartBeatRecordHandler;
+
+
+ @Bean
+ public HeartBeatManager heartBeatManager(){
+ return new HeartBeatManager(delayHandlerTime,intervalTime,heartBeatRecordHandler);
+ }
+}
\ No newline at end of file
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartMybatisPlusConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartMybatisPlusConfig.java
new file mode 100644
index 00000000..a9454bc5
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartMybatisPlusConfig.java
@@ -0,0 +1,30 @@
+package net.lab1024.smartadmin.service.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * MybatisPlus 配置
+ *
+ * @author listen
+ * @date 2021/06/06 19:30
+ */
+@Configuration
+@EnableTransactionManagement
+public class SmartMybatisPlusConfig {
+
+ /**
+ * 分页插件
+ */
+ @Bean
+ public MybatisPlusInterceptor paginationInterceptor() {
+ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+ interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+ return interceptor;
+ }
+
+}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/config/SmartRedisConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartRedisConfig.java
similarity index 93%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/config/SmartRedisConfig.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartRedisConfig.java
index 829ca01f..1d57b412 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/config/SmartRedisConfig.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartRedisConfig.java
@@ -1,4 +1,4 @@
-package net.lab1024.smartadmin.config;
+package net.lab1024.smartadmin.service.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
@@ -14,12 +14,8 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* [ redis配置 ]
*
- * @author yandanyang
- * @version 1.0
- * @company 1024lab.net
- * @copyright (c) 2019 1024lab.netInc. All rights reserved.
- * @date
- * @since JDK1.8
+ * @author 罗伊
+ * @date 2020/8/25 11:57
*/
@Configuration
public class SmartRedisConfig {
@@ -70,5 +66,4 @@ public class SmartRedisConfig {
return redisTemplate.opsForZSet();
}
-
}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartRedisMqConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartRedisMqConfig.java
new file mode 100644
index 00000000..f0f8f919
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartRedisMqConfig.java
@@ -0,0 +1,68 @@
+package net.lab1024.smartadmin.service.config;
+
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.smartadmin.service.module.support.redismq.RedisMqTopicEnum;
+import net.lab1024.smartadmin.service.module.support.redismq.RedisMsgHandler;
+import net.lab1024.smartadmin.service.util.SmartBaseEnumUtil;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.listener.PatternTopic;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date
+ */
+@Slf4j
+@Configuration
+public class SmartRedisMqConfig {
+
+ @Value("${redis.mq.topic:SmartAdmin}")
+ private String topic;
+ @Value("${redis.mq.scanPath:net.lab1024.smartadmin.service}")
+ private String scanPath;
+
+ /**
+ * redis topic
+ * @param connectionFactory
+ * @param listenerAdapter
+ * @return
+ */
+ @Bean
+ public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
+ RedisMessageListenerContainer container = new RedisMessageListenerContainer();
+ container.setConnectionFactory(connectionFactory);
+ boolean checkEnum = SmartBaseEnumUtil.checkEnum(topic, RedisMqTopicEnum.class);
+ if (!checkEnum) {
+ log.error("topic:{},系统暂未定义", topic);
+ throw new RuntimeException("无效的redis topic");
+ }
+ container.addMessageListener(listenerAdapter, new PatternTopic(topic));
+ return container;
+ }
+
+ /**
+ * redis消息处理类
+ * @return
+ */
+ @Bean
+ public RedisMsgHandler redisMsgHandler() {
+ return new RedisMsgHandler(scanPath);
+ }
+
+ /**
+ * redis消息处理方法
+ * @param receiver
+ * @return
+ */
+ @Bean
+ public MessageListenerAdapter listenerAdapter(RedisMsgHandler receiver) {
+ return new MessageListenerAdapter(receiver, RedisMsgHandler.METHOD_NAME);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartRepeatSubmitAspectConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartRepeatSubmitAspectConfig.java
new file mode 100644
index 00000000..f8d81b85
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartRepeatSubmitAspectConfig.java
@@ -0,0 +1,43 @@
+package net.lab1024.smartadmin.service.config;
+
+import com.alibaba.fastjson.JSON;
+import net.lab1024.smartadmin.service.module.support.repeatsubmit.SmartRepeatSubmitAspect;
+import net.lab1024.smartadmin.service.module.support.repeatsubmit.SmartRepeatSubmitUserDTO;
+import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginInfoDTO;
+import net.lab1024.smartadmin.service.util.SmartEmployeeTokenUtil;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * [ 接口重复提交配置 ]
+ *
+ * @author 罗伊
+ * @date 2021/1/27 11:22
+ */
+@Configuration
+public class SmartRepeatSubmitAspectConfig {
+
+ @Bean
+ public SmartRepeatSubmitAspect repeatSubmitAspect() {
+ return new SmartRepeatSubmitAspect(this::userFunction);
+ }
+
+ /**
+ * 请求用户信息
+ *
+ * @return
+ */
+ private SmartRepeatSubmitUserDTO userFunction(HttpServletRequest request) {
+ EmployeeLoginInfoDTO requestEmployee = SmartEmployeeTokenUtil.getRequestEmployee();
+ if(requestEmployee == null){
+ return null;
+ }
+ SmartRepeatSubmitUserDTO repeatSubmitUserDTO = new SmartRepeatSubmitUserDTO();
+ repeatSubmitUserDTO.setUserId(requestEmployee.getEmployeeId());
+ repeatSubmitUserDTO.setUserName(requestEmployee.getActualName());
+ repeatSubmitUserDTO.setExtData(JSON.toJSONString(requestEmployee));
+ return repeatSubmitUserDTO;
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartResponseEncryptAspectConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartResponseEncryptAspectConfig.java
new file mode 100644
index 00000000..e203bbdf
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartResponseEncryptAspectConfig.java
@@ -0,0 +1,45 @@
+package net.lab1024.smartadmin.service.config;
+
+import com.alibaba.fastjson.JSON;
+import net.lab1024.smartadmin.service.module.support.responseencrypt.ResponseEncryptDecryptAspect;
+import net.lab1024.smartadmin.service.module.support.responseencrypt.ResponseEncryptDecryptUserDTO;
+import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginInfoDTO;
+import net.lab1024.smartadmin.service.util.SmartEmployeeTokenUtil;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * [ 接口加解密配置 ]
+ *
+ * @author 罗伊
+ * @date 2021/1/27 11:22
+ */
+@Configuration
+public class SmartResponseEncryptAspectConfig {
+
+
+ @Bean
+ public ResponseEncryptDecryptAspect responseEncryptAspect() {
+ return new ResponseEncryptDecryptAspect(this::employeeFunction);
+ }
+
+ /**
+ * 请求用户信息
+ * @param request
+ * @return
+ */
+ private ResponseEncryptDecryptUserDTO employeeFunction(HttpServletRequest request){
+ EmployeeLoginInfoDTO employeeLoginInfoDTO = SmartEmployeeTokenUtil.getRequestEmployee();
+ if(employeeLoginInfoDTO == null){
+ return null;
+ }
+ ResponseEncryptDecryptUserDTO responseEncryptDecryptUserDTO = new ResponseEncryptDecryptUserDTO();
+ responseEncryptDecryptUserDTO.setUserId(employeeLoginInfoDTO.getEmployeeId());
+ responseEncryptDecryptUserDTO.setUserName(employeeLoginInfoDTO.getActualName());
+ responseEncryptDecryptUserDTO.setExtData(JSON.toJSONString(employeeLoginInfoDTO));
+ return responseEncryptDecryptUserDTO;
+ }
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartRestTemplateConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartRestTemplateConfig.java
new file mode 100644
index 00000000..bc671e69
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartRestTemplateConfig.java
@@ -0,0 +1,126 @@
+package net.lab1024.smartadmin.service.config;
+
+import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
+import okhttp3.ConnectionPool;
+import okhttp3.OkHttpClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2020/8/25 11:57
+ */
+@Configuration
+public class SmartRestTemplateConfig {
+
+ @Value("${http.pool.max-total}")
+ private Integer maxTotal;
+
+ @Value("${http.pool.connect-timeout}")
+ private Integer connectTimeout;
+
+ @Value("${http.pool.read-timeout}")
+ private Integer readTimeout;
+
+ @Value("${http.pool.write-timeout}")
+ private Integer writeTimeout;
+
+ @Value("${http.pool.keep-alive}")
+ private Integer keepAlive;
+
+ @Bean
+ public RestTemplate restTemplate() {
+ RestTemplate restTemplate = new RestTemplate();
+ restTemplate.setRequestFactory(this.clientHttpRequestFactory());
+ List> messageConverterList = restTemplate.getMessageConverters();
+ messageConverterList.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
+ messageConverterList.addAll(converters());
+ return restTemplate;
+ }
+
+ public List> converters() {
+ List> converters = new ArrayList<>();
+ HttpMessageConverter> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
+ FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
+ List fastMediaTypes = new ArrayList<>();
+ fastMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
+ fastMediaTypes.add(MediaType.APPLICATION_JSON);
+ fastConverter.setSupportedMediaTypes(fastMediaTypes);
+ converters.add(converter);
+ converters.add(fastConverter);
+ return converters;
+ }
+
+
+ public OkHttp3ClientHttpRequestFactory clientHttpRequestFactory() {
+ return new OkHttp3ClientHttpRequestFactory(httpClientBuilder());
+ }
+
+ public OkHttpClient httpClientBuilder() {
+ return new OkHttpClient.Builder()
+ .retryOnConnectionFailure(false)
+ .connectionPool(this.pool())
+ .connectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
+ .readTimeout(readTimeout,TimeUnit.MILLISECONDS)
+ .writeTimeout(writeTimeout,TimeUnit.MILLISECONDS)
+ .build();
+ }
+
+ public ConnectionPool pool() {
+ return new ConnectionPool(maxTotal, keepAlive, TimeUnit.MILLISECONDS);
+ }
+
+
+ @Bean
+ public X509TrustManager x509TrustManager() {
+ return new X509TrustManager() {
+ @Override
+ public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
+ }
+ @Override
+ public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
+ }
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+ };
+ }
+
+ @Bean
+ public SSLSocketFactory sslSocketFactory() {
+ try {
+ //信任任何链接
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());
+ return sslContext.getSocketFactory();
+ } catch (NoSuchAlgorithmException | KeyManagementException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartSchedulingConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartSchedulingConfig.java
new file mode 100644
index 00000000..dd7e20c2
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartSchedulingConfig.java
@@ -0,0 +1,51 @@
+package net.lab1024.smartadmin.service.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.logging.log4j.util.Strings;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+import org.springframework.scheduling.config.Task;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author 卓大
+ * @Date 2020/5/22
+ */
+@Slf4j
+@Configuration
+public class SmartSchedulingConfig implements SchedulingConfigurer {
+
+ private ScheduledTaskRegistrar taskRegistrar;
+
+ public ScheduledTaskRegistrar getTaskRegistrar() {
+ return taskRegistrar;
+ }
+
+ /**
+ * 结束定时任务
+ */
+ public void destroy() {
+ List taskList = new ArrayList<>();
+ taskList.addAll(taskRegistrar.getCronTaskList());
+ taskList.addAll(taskRegistrar.getTriggerTaskList());
+ taskList.addAll(taskRegistrar.getFixedDelayTaskList());
+ taskList.addAll(taskRegistrar.getFixedRateTaskList());
+
+ List taskName = taskList.stream().map(Task::toString).collect(Collectors.toList());
+
+ taskRegistrar.destroy();
+
+ log.warn("已结束定时任务:\n{}", Strings.join(taskName, '\n'));
+ }
+
+ @Override
+ public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
+ this.taskRegistrar = taskRegistrar;
+ }
+
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartSerializerLocalDateTimeConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartSerializerLocalDateTimeConfig.java
new file mode 100644
index 00000000..3891eaad
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartSerializerLocalDateTimeConfig.java
@@ -0,0 +1,31 @@
+package net.lab1024.smartadmin.service.config;
+
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import net.lab1024.smartadmin.service.util.date.SmartDateFormatterEnum;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * java8 localDate 时间类格式化配置
+ *
+ * @author listen
+ * @date 2021年8月31日 21:19
+ */
+@Configuration
+public class SmartSerializerLocalDateTimeConfig {
+
+ @Bean
+ public Jackson2ObjectMapperBuilderCustomizer customizer() {
+ return builder -> {
+ builder.deserializers(new LocalDateDeserializer(SmartDateFormatterEnum.YMD.getFormatter()));
+ builder.deserializers(new LocalDateTimeDeserializer(SmartDateFormatterEnum.YMD_HMS.getFormatter()));
+ builder.serializers(new LocalDateSerializer(SmartDateFormatterEnum.YMD.getFormatter()));
+ builder.serializers(new LocalDateTimeSerializer(SmartDateFormatterEnum.YMD_HMS.getFormatter()));
+ };
+ }
+
+}
\ No newline at end of file
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartStorageCloudConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartStorageCloudConfig.java
new file mode 100644
index 00000000..e76f5e96
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartStorageCloudConfig.java
@@ -0,0 +1,64 @@
+package net.lab1024.smartadmin.service.config;
+
+import com.amazonaws.ClientConfiguration;
+import com.amazonaws.Protocol;
+import com.amazonaws.auth.AWSStaticCredentialsProvider;
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.client.builder.AwsClientBuilder;
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+/**
+ * @author Administrator
+ */
+@Data
+@Configuration
+@ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = "cloud")
+public class SmartStorageCloudConfig {
+
+ @Value("${file.storage.cloud.region}")
+ private String region;
+
+ @Value("${file.storage.cloud.endpoint}")
+ private String endpoint;
+
+ @Value("${file.storage.cloud.bucket-name}")
+ private String bucketName;
+
+ @Value("${file.storage.cloud.access-key}")
+ private String accessKey;
+
+ @Value("${file.storage.cloud.secret-key}")
+ private String secretKey;
+
+ @Value("${file.storage.cloud.url.expire}")
+ private Long urlExpire;
+
+ @Value("${file.storage.cloud.url.public}")
+ private String publicUrl;
+
+ /**
+ * 初始化 云oss client 配置
+ *
+ * @return
+ */
+ @Bean
+ public AmazonS3 initAmazonS3() {
+ ClientConfiguration clientConfig = new ClientConfiguration();
+ clientConfig.setProtocol(Protocol.HTTPS);
+ AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
+ .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
+ .withClientConfiguration(clientConfig)
+ .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint, region))
+ .withPathStyleAccessEnabled(false)
+ .build();
+ return s3Client;
+ }
+
+}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/config/SmartSwaggerDynamicGroupConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartSwaggerDynamicGroupConfig.java
similarity index 56%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/config/SmartSwaggerDynamicGroupConfig.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartSwaggerDynamicGroupConfig.java
index aad7b175..21bc6c1d 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/config/SmartSwaggerDynamicGroupConfig.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartSwaggerDynamicGroupConfig.java
@@ -1,6 +1,5 @@
-package net.lab1024.smartadmin.config;
+package net.lab1024.smartadmin.service.config;
-import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
@@ -8,8 +7,8 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
-import net.lab1024.smartadmin.constant.SwaggerTagConst;
-import net.lab1024.smartadmin.interceptor.SmartAuthenticationInterceptor;
+import net.lab1024.smartadmin.service.common.constant.CommonConst;
+import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@@ -17,10 +16,10 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.EnvironmentAware;
+import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
-import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
@@ -28,41 +27,29 @@ import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
-import springfox.documentation.service.*;
+import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
- * [ 根据SwaggerTagConst内部类动态生成Swagger group ]
+ * [ 根据SwaggerTagConst内部类动态生成Swagger ]
*
- * @author yandanyang
- * @version 1.0
- * @company 1024lab.net
- * @copyright (c) 2018 1024lab.netInc. All rights reserved.
- * @date 2019/8/7 0007 下午 19:20
- * @since JDK1.8
+ * @author 罗伊
+ * @date 2020/8/25 11:57
*/
@Slf4j
@EnableSwagger2
-@EnableKnife4j
@Configuration
-@Profile({"dev", "sit", "pre", "prod"})
+@Conditional(SmartSystemEnvNotProdCondition.class)
public class SmartSwaggerDynamicGroupConfig implements EnvironmentAware, BeanDefinitionRegistryPostProcessor {
- /**
- * 分组名称
- */
- private String apiGroupName;
-
/**
* 文档标题
*/
@@ -88,6 +75,16 @@ public class SmartSwaggerDynamicGroupConfig implements EnvironmentAware, BeanDef
*/
private String packAge;
+ /**
+ * host
+ */
+ private String host;
+
+ /**
+ * 接口Tag类
+ */
+ private String swaggerTagClass;
+
private int groupIndex = 0;
private String groupName = "default";
@@ -98,12 +95,13 @@ public class SmartSwaggerDynamicGroupConfig implements EnvironmentAware, BeanDef
@Override
public void setEnvironment(Environment environment) {
- this.apiGroupName = environment.getProperty("swagger.apiGroupName");
- this.title = environment.getProperty("swagger.title");
- this.description = environment.getProperty("swagger.description");
- this.version = environment.getProperty("swagger.version");
- this.serviceUrl = environment.getProperty("swagger.serviceUrl");
- this.packAge = environment.getProperty("swagger.packAge");
+ this.title = environment.getProperty("swagger.title" );
+ this.description = environment.getProperty("swagger.description" );
+ this.version = environment.getProperty("swagger.version" );
+ this.serviceUrl = environment.getProperty("swagger.serviceUrl" );
+ this.packAge = environment.getProperty("swagger.packAge" );
+ this.host = environment.getProperty("swagger.host" );
+ this.swaggerTagClass = environment.getProperty("swagger.tagClass" );
}
@Override
@@ -118,8 +116,15 @@ public class SmartSwaggerDynamicGroupConfig implements EnvironmentAware, BeanDef
}
private void groupBuild() {
- Class clazz = SwaggerTagConst.class;
- Class[] innerClazz = clazz.getDeclaredClasses();
+ Class clazz = null;
+ try {
+ clazz = Class.forName(swaggerTagClass);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ log.error("swaggerTagClass unfounded :{}", swaggerTagClass);
+ return;
+ }
+ Class[] innerClazz = clazz.getClasses();
for (Class cls : innerClazz) {
String group = cls.getSimpleName();
List apiTags = Lists.newArrayList();
@@ -140,57 +145,33 @@ public class SmartSwaggerDynamicGroupConfig implements EnvironmentAware, BeanDef
}
private Docket baseDocket() {
- // 配置全局参数 token
+ // 配置全局参数 token header
ParameterBuilder tokenPar = new ParameterBuilder();
- Parameter parameter = tokenPar.name(SmartAuthenticationInterceptor.TOKEN_NAME)
- .description("token")
- .modelRef(new ModelRef("string"))
- .parameterType("header")
- .defaultValue("")
+ tokenPar.name(CommonConst.Token.OUTER_TOKEN_NAME)
+ .description("token" )
+ .modelRef(new ModelRef("string" ))
+ .parameterType("header" ).defaultValue("1" )
.required(false)
.build();
- // 请求类型过滤规则
- Predicate controllerPredicate = getControllerPredicate();
- // controller 包路径
- Predicate controllerPackage = RequestHandlerSelectors.basePackage(packAge);
- return new Docket(DocumentationType.SWAGGER_2)
+ // 此行必须放在配置前面执行 因为要初始化groupName
+ Predicate controllerPredicate = this.getControllerPredicate();
+ // swagger配置
+ Docket docket = new Docket(DocumentationType.SWAGGER_2)
.groupName(groupName)
.forCodeGeneration(true)
.select()
- .apis(controllerPackage)
+ .apis(RequestHandlerSelectors.basePackage(packAge))
.apis(controllerPredicate)
.paths(PathSelectors.any())
- .build()
- .apiInfo(this.serviceApiInfo())
- .securitySchemes(securitySchemes())
- .securityContexts(securityContexts())
- .globalOperationParameters(Lists.newArrayList(parameter));
- }
+ .build().apiInfo(this.serviceApiInfo())
+ .globalOperationParameters(Lists.newArrayList(tokenPar.build()));
- private List securitySchemes() {
- List apiKeyList = new ArrayList<>();
- apiKeyList.add(new ApiKey("x-access-token", "x-access-token", "header"));
- return apiKeyList;
- }
+ if (StringUtils.isNotBlank(host)) {
+ docket = docket.host(host);
+ }
- private List securityContexts() {
- List securityContexts = new ArrayList<>();
- securityContexts.add(
- SecurityContext.builder()
- .securityReferences(defaultAuth())
- .forPaths(PathSelectors.any())
- .build());
- return securityContexts;
- }
-
- List defaultAuth() {
- AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
- AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
- authorizationScopes[0] = authorizationScope;
- List securityReferences = new ArrayList<>();
- securityReferences.add(new SecurityReference("x-access-token", authorizationScopes));
- return securityReferences;
+ return docket;
}
private Predicate getControllerPredicate() {
@@ -203,34 +184,18 @@ public class SmartSwaggerDynamicGroupConfig implements EnvironmentAware, BeanDef
api = apiOptional.get();
}
List tags = Arrays.asList(api.tags());
- if (api != null && apiTags.containsAll(tags)) {
- return true;
- }
- return false;
+ return apiTags.containsAll(tags);
};
groupIndex++;
- return Predicates.or(
- Predicates.and(RequestHandlerSelectors.withClassAnnotation(RestController.class), methodPredicate),
- Predicates.and(
- RequestHandlerSelectors.withMethodAnnotation(ResponseBody.class), methodPredicate)
- );
+ return Predicates.and(RequestHandlerSelectors.withClassAnnotation(RestController.class), methodPredicate);
}
private ApiInfo serviceApiInfo() {
- return new ApiInfoBuilder()
- .title(title)
- .description(description)
- .version(version)
- .license("Apache License Version 2.0")
- .contact(new Contact("1024创新实验室", "http://www.1024lab.net", ""))
- .termsOfServiceUrl(serviceUrl)
- .build();
+ return new ApiInfoBuilder().title(title).description(description).version(version).termsOfServiceUrl(serviceUrl).build();
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
-
-
}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartSystemEnvNotProdCondition.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartSystemEnvNotProdCondition.java
new file mode 100644
index 00000000..46ab0be6
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartSystemEnvNotProdCondition.java
@@ -0,0 +1,35 @@
+package net.lab1024.smartadmin.service.config;
+
+import net.lab1024.smartadmin.service.common.constant.SystemEnvironmentEnum;
+import net.lab1024.smartadmin.service.util.SmartBaseEnumUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Condition;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+/**
+ * 当前系统环境
+ *
+ * @author listen
+ * @date 2019/08/27 08:56
+ */
+@Configuration
+public class SmartSystemEnvNotProdCondition implements Condition {
+
+ @Value("${spring.profiles.active}")
+ private String systemEnvironment;
+
+ @Override
+ public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
+ String property = conditionContext.getEnvironment().getProperty("spring.profiles.active");
+ return StringUtils.isNotBlank(property) && !SystemEnvironmentEnum.PROD.equalsValue(property);
+ }
+
+ @Bean
+ public SystemEnvironmentEnum initEnvironment() {
+ return SmartBaseEnumUtil.getEnumByValue(systemEnvironment, SystemEnvironmentEnum.class);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartWebAppConfig.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartWebAppConfig.java
new file mode 100644
index 00000000..358f434e
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/config/SmartWebAppConfig.java
@@ -0,0 +1,48 @@
+package net.lab1024.smartadmin.service.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * @Description
+ * @Author 善逸
+ * @Date Created in 2017/10/24 13:48
+ */
+@Configuration
+public class SmartWebAppConfig implements WebMvcConfigurer {
+
+ @Autowired
+ private Map interceptorMp;
+
+ @Value("${file.storage.local.path}")
+ private String localPath;
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ for(Entry entry : interceptorMp.entrySet()){
+ registry.addInterceptor(entry.getValue()).addPathPatterns(entry.getKey() + "/**");
+ }
+
+ }
+
+ @Override
+ public void addViewControllers(ViewControllerRegistry registry) {
+ registry.addViewController("/druidMonitor").setViewName("redirect:druid/index.html");
+ registry.addViewController("/swaggerApi").setViewName("redirect:swagger-ui.html");
+ }
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ registry.addResourceHandler("/**")
+ .addResourceLocations("classpath:/META-INF/resources/","classpath:/resources/","classpath:/static/","file:" + localPath);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/filters/SmartTokenFilter.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/filters/SmartTokenFilter.java
new file mode 100644
index 00000000..07155043
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/filters/SmartTokenFilter.java
@@ -0,0 +1,66 @@
+package net.lab1024.smartadmin.service.filters;
+
+import net.lab1024.smartadmin.service.common.constant.CommonConst;
+import net.lab1024.smartadmin.service.module.system.login.EmployeeLoginTokenService;
+import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginBO;
+import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginInfoDTO;
+import net.lab1024.smartadmin.service.util.SmartBeanUtil;
+import net.lab1024.smartadmin.service.util.SmartEmployeeTokenUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * token过滤器
+ */
+@Component
+public class SmartTokenFilter extends OncePerRequestFilter {
+ private static final String TOKEN_NAME = "x-access-token";
+
+ @Autowired
+ private EmployeeLoginTokenService loginTokenService;
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+ throws ServletException, IOException {
+ //需要做token校验, 消息头的token优先于请求query参数的token
+ String xHeaderToken = request.getHeader(TOKEN_NAME);
+ String xRequestToken = request.getParameter(TOKEN_NAME);
+ String xAccessToken = null != xHeaderToken ? xHeaderToken : xRequestToken;
+ if (StringUtils.isBlank(xAccessToken)) {
+ // 若未给予spring security上下文用户授权 则会授权失败 进入AuthenticationEntryPointImpl
+ chain.doFilter(request, response);
+ return;
+ }
+
+ // 先清理spring security上下文
+ SecurityContextHolder.clearContext();
+
+ // 判断请求分组
+ String requestURI = request.getRequestURI();
+ if (StringUtils.startsWithIgnoreCase(requestURI, CommonConst.ApiUrl.API_PREFIX_ADMIN)) {
+ // 后管 获取用户信息
+ EmployeeLoginBO loginBO = loginTokenService.getEmployeeLoginBO(xAccessToken);
+ // 若获取到了登陆信息 则把用户信息设置到上下文中
+ if (null != loginBO) {
+ SmartEmployeeTokenUtil.setUser(SmartBeanUtil.copy(loginBO, EmployeeLoginInfoDTO.class));
+ UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginBO, null, loginBO.getAuthorities());
+ authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+ SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+ }
+ }
+
+ // 若未给予spring security上下文用户授权 则会授权失败 进入AuthenticationEntryPointImpl
+ chain.doFilter(request, response);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/handler/AuthenticationFailHandler.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/handler/AuthenticationFailHandler.java
new file mode 100644
index 00000000..6ca6e7c1
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/handler/AuthenticationFailHandler.java
@@ -0,0 +1,39 @@
+package net.lab1024.smartadmin.service.handler;
+
+import com.alibaba.fastjson.JSONObject;
+import net.lab1024.smartadmin.service.common.codeconst.LoginResponseCodeConst;
+import net.lab1024.smartadmin.service.common.codeconst.ResponseCodeConst;
+import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * 认证失败处理
+ */
+@Component
+public class AuthenticationFailHandler implements AuthenticationEntryPoint {
+
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException {
+ this.outputResult(response, LoginResponseCodeConst.LOGIN_ERROR);
+ }
+
+ /**
+ * 输出
+ *
+ * @param response
+ * @param respCode
+ * @throws IOException
+ */
+ private void outputResult(HttpServletResponse response, ResponseCodeConst respCode) throws IOException {
+ String msg = JSONObject.toJSONString(ResponseDTO.wrap(respCode));
+ response.setContentType("application/json;charset=UTF-8");
+ response.getWriter().write(msg);
+ response.flushBuffer();
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/handler/SmartGlobalExceptionHandler.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/handler/SmartGlobalExceptionHandler.java
new file mode 100644
index 00000000..37a80a9b
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/handler/SmartGlobalExceptionHandler.java
@@ -0,0 +1,104 @@
+package net.lab1024.smartadmin.service.handler;
+
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.smartadmin.service.common.codeconst.ResponseCodeConst;
+import net.lab1024.smartadmin.service.common.constant.SystemEnvironmentEnum;
+import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
+import net.lab1024.smartadmin.service.common.exception.SmartBusinessException;
+import org.springframework.beans.TypeMismatchException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.validation.BindException;
+import org.springframework.validation.FieldError;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * [ 全局异常拦截 ]
+ *
+ * @author 罗伊
+ * @date 2020/8/25 11:57
+ */
+@Slf4j
+@ControllerAdvice
+public class SmartGlobalExceptionHandler {
+
+ @Autowired
+ private SystemEnvironmentEnum systemEnvironmentEnum;
+
+ /**
+ * 添加全局异常处理流程
+ *
+ * @param e
+ * @return
+ * @throws Exception
+ */
+ @ResponseBody
+ @ExceptionHandler(Exception.class)
+ public ResponseDTO exceptionHandler(Exception e) {
+
+ // json 格式错误
+ if (e instanceof HttpMessageNotReadableException) {
+ return ResponseDTO.wrap(ResponseCodeConst.JSON_FORMAT_ERROR);
+ }
+
+ String uri = null;
+ RequestAttributes request = RequestContextHolder.getRequestAttributes();
+ if (null != request) {
+ ServletRequestAttributes servletRequest = (ServletRequestAttributes) request;
+ uri = servletRequest.getRequest().getRequestURI();
+ }
+
+ // http 请求方式错误
+ if (e instanceof HttpRequestMethodNotSupportedException) {
+ return ResponseDTO.wrap(ResponseCodeConst.REQUEST_METHOD_ERROR);
+ }
+
+ // 参数类型错误
+ if (e instanceof TypeMismatchException) {
+ return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM);
+ }
+
+ // 参数校验未通过
+ if (e instanceof MethodArgumentNotValidException) {
+ List fieldErrors = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors();
+ List msgList = fieldErrors.stream().map(FieldError::getDefaultMessage).collect(Collectors.toList());
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, String.join(",", msgList));
+ }
+
+ // 参数绑定错误
+ if (e instanceof BindException) {
+ List fieldErrors = ((BindException) e).getFieldErrors();
+ List error = fieldErrors.stream().map(field -> field.getField() + ":" + field.getRejectedValue()).collect(Collectors.toList());
+ String errorMsg = ResponseCodeConst.ERROR_PARAM.getMsg() + ":" + error.toString();
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, errorMsg);
+ }
+
+ if (e instanceof SmartBusinessException) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.SYSTEM_ERROR, e.getMessage());
+ }
+
+ if (e instanceof AccessDeniedException) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.SYSTEM_ERROR, "您暂无权限");
+ }
+
+ log.error("捕获全局异常,URL:{}", uri, e);
+
+ // 正式环境 不返回错误信息
+ if (SystemEnvironmentEnum.PROD == systemEnvironmentEnum) {
+ return ResponseDTO.wrap(ResponseCodeConst.SYSTEM_ERROR);
+ }
+
+ return ResponseDTO.wrapMsg(ResponseCodeConst.SYSTEM_ERROR, e.toString());
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/interceptor/BusinessAuthorityInterceptor.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/interceptor/BusinessAuthorityInterceptor.java
new file mode 100644
index 00000000..390939f5
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/interceptor/BusinessAuthorityInterceptor.java
@@ -0,0 +1,60 @@
+package net.lab1024.smartadmin.service.interceptor;
+
+import net.lab1024.smartadmin.service.common.constant.CommonConst;
+import net.lab1024.smartadmin.service.util.SmartEmployeeTokenUtil;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * [ 登录拦截器 ]
+ *
+ * @author 罗伊
+ */
+@Component(CommonConst.ApiUrl.API_PREFIX_ADMIN)
+public class BusinessAuthorityInterceptor implements HandlerInterceptor {
+
+ @Value("${access-control-allow-origin}")
+ private String accessControlAllowOrigin;
+
+ /**
+ * 拦截服务器端响应处理ajax请求返回结果
+ *
+ * @param request
+ * @param response
+ * @param handler
+ * @return
+ * @throws Exception
+ */
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ //跨域设置
+ this.crossDomainConfig(response);
+ return true;
+ }
+
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
+ SmartEmployeeTokenUtil.remove();
+ }
+
+ /**
+ * 配置跨域
+ *
+ * @param response
+ */
+ private void crossDomainConfig(HttpServletResponse response) {
+ response.setHeader("Access-Control-Allow-Origin", accessControlAllowOrigin);
+ response.setHeader("Access-Control-Allow-Credentials", "true");
+ response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
+ response.setHeader("Access-Control-Expose-Headers", "*");
+ response.setHeader("Access-Control-Allow-Headers", "Authentication,Origin, X-Requested-With, Content-Type, " + "Accept, x-access-token");
+ response.setHeader("Cache-Control", "no-cache");
+ response.setHeader("Pragma", "no-cache");
+ response.setHeader("Expires ", "-1");
+ }
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/interceptor/SupportAuthorityInterceptor.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/interceptor/SupportAuthorityInterceptor.java
new file mode 100644
index 00000000..a8056c9d
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/interceptor/SupportAuthorityInterceptor.java
@@ -0,0 +1,54 @@
+package net.lab1024.smartadmin.service.interceptor;
+
+import net.lab1024.smartadmin.service.common.constant.CommonConst;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 公用api 拦截器
+ *
+ * @author Administrator
+ */
+@Component(CommonConst.ApiUrl.API_PREFIX_SUPPORT)
+public class SupportAuthorityInterceptor implements HandlerInterceptor {
+
+ @Value("${access-control-allow-origin}")
+ private String accessControlAllowOrigin;
+
+ /**
+ * 拦截服务器端响应处理ajax请求返回结果
+ *
+ * @param request
+ * @param response
+ * @param handler
+ * @return
+ * @throws Exception
+ */
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ //跨域设置
+ this.crossDomainConfig(response);
+ return true;
+ }
+
+ /**
+ * 配置跨域
+ *
+ * @param response
+ */
+ private void crossDomainConfig(HttpServletResponse response) {
+ response.setHeader("Access-Control-Allow-Origin", accessControlAllowOrigin);
+ response.setHeader("Access-Control-Allow-Credentials", "true");
+ response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
+ response.setHeader("Access-Control-Expose-Headers", "*");
+ response.setHeader("Access-Control-Allow-Headers", "Authentication,Origin, X-Requested-With, Content-Type, " + "Accept, x-access-token");
+ response.setHeader("Cache-Control", "no-cache");
+ response.setHeader("Pragma", "no-cache");
+ response.setHeader("Expires ", "-1");
+ }
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/listener/SmartAdminStartupRunner.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/listener/SmartAdminStartupRunner.java
new file mode 100644
index 00000000..0a8ddd25
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/listener/SmartAdminStartupRunner.java
@@ -0,0 +1,29 @@
+package net.lab1024.smartadmin.service.listener;
+
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.smartadmin.service.common.codeconst.ResponseCodeRegister;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+
+/**
+ * 应用启动加载
+ *
+ * @author zhuo
+ * @version 1.0
+ * @since JDK1.8
+ */
+@Slf4j
+@Component
+public class SmartAdminStartupRunner implements CommandLineRunner {
+
+ @Override
+ public void run(String... args) {
+
+ log.info("###################### init start ######################");
+
+ // 初始化状态码
+ ResponseCodeRegister.init();
+
+ log.info("###################### init complete ######################");
+ }
+}
\ No newline at end of file
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/CategoryController.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/CategoryController.java
new file mode 100644
index 00000000..c2317d23
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/CategoryController.java
@@ -0,0 +1,57 @@
+package net.lab1024.smartadmin.service.module.business.category;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import net.lab1024.smartadmin.service.common.constant.SwaggerTagConst;
+import net.lab1024.smartadmin.service.common.controller.AdminBaseController;
+import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
+import net.lab1024.smartadmin.service.module.business.category.domain.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+ * 类目 路由
+ *
+ * @author 胡克
+ * @date 2021/1/21 9:10
+ */
+@Api(tags = SwaggerTagConst.Admin.MANAGER_CATEGORY)
+@RestController
+public class CategoryController extends AdminBaseController {
+
+ @Autowired
+ private CategoryService categoryService;
+
+ @ApiOperation("添加类目 by listen")
+ @PostMapping("/category/add")
+ public ResponseDTO add(@RequestBody @Valid CategoryAddDTO addDTO) {
+ return categoryService.add(addDTO);
+ }
+
+ @ApiOperation("更新类目 by listen")
+ @PostMapping("/category/update")
+ public ResponseDTO update(@RequestBody @Valid CategoryUpdateDTO updateDTO) {
+ return categoryService.update(updateDTO);
+ }
+
+ @ApiOperation("查询类目详情 by listen")
+ @GetMapping("/category/{categoryId}")
+ public ResponseDTO queryDetail(@PathVariable Long categoryId) {
+ return categoryService.queryDetail(categoryId);
+ }
+
+ @ApiOperation("查询类目层级树 by listen")
+ @PostMapping("/category/tree")
+ public ResponseDTO> queryTree(@RequestBody @Valid CategoryTreeQueryDTO queryDTO) {
+ return categoryService.queryTree(queryDTO);
+ }
+
+ @ApiOperation("删除类目 by listen")
+ @GetMapping("/category/del/{categoryId}")
+ public ResponseDTO delete(@PathVariable Long categoryId) {
+ return categoryService.delete(categoryId);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/CategoryDao.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/CategoryDao.java
new file mode 100644
index 00000000..9fdd7464
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/CategoryDao.java
@@ -0,0 +1,50 @@
+package net.lab1024.smartadmin.service.module.business.category;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import net.lab1024.smartadmin.service.module.business.category.constant.CategoryTypeEnum;
+import net.lab1024.smartadmin.service.module.business.category.domain.CategoryEntity;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * 类目 dao
+ *
+ * @author 胡克
+ * @date 2021/1/20 16:29
+ */
+@Component
+@Mapper
+public interface CategoryDao extends BaseMapper {
+
+ /**
+ * 根据父级id 类型 查询子类
+ *
+ * @param parentIdList
+ * @param categoryType {@link CategoryTypeEnum}
+ * @param deletedFlag
+ * @return
+ */
+ List queryByParentId(@Param("parentIdList") List parentIdList,
+ @Param("categoryType") Integer categoryType,
+ @Param("deletedFlag") Boolean deletedFlag);
+
+ /**
+ * 根据类型和id查询
+ * @param categoryType
+ * @param categoryId
+ * @return
+ */
+ CategoryEntity selectByTypeAndId(@Param("categoryType") Integer categoryType, @Param("categoryId") Long categoryId);
+
+ /**
+ * 查看类目 具体条件 看sql
+ *
+ * @param entity
+ * @return
+ */
+ CategoryEntity selectOne(CategoryEntity entity);
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/CategoryQueryService.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/CategoryQueryService.java
new file mode 100644
index 00000000..5240c8b7
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/CategoryQueryService.java
@@ -0,0 +1,333 @@
+package net.lab1024.smartadmin.service.module.business.category;
+
+import com.google.common.collect.Lists;
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.smartadmin.service.common.constant.CacheModuleBaseConst;
+import net.lab1024.smartadmin.service.common.constant.CommonConst;
+import net.lab1024.smartadmin.service.module.business.category.domain.CategoryEntity;
+import net.lab1024.smartadmin.service.module.business.category.domain.CategorySimpleDTO;
+import net.lab1024.smartadmin.service.module.business.category.domain.CategoryTreeQueryDTO;
+import net.lab1024.smartadmin.service.module.business.category.domain.CategoryTreeVO;
+import net.lab1024.smartadmin.service.module.support.beancache.cache.IBeanCache;
+import net.lab1024.smartadmin.service.module.support.beancache.key.CacheKey;
+import net.lab1024.smartadmin.service.module.support.beancache.load.CacheLoad;
+import net.lab1024.smartadmin.service.util.SmartBeanUtil;
+import net.lab1024.smartadmin.service.util.SmartStringUtil;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 类目 查询 业务类
+ *
+ * @author 胡克
+ * @date 2021/1/20 16:26
+ */
+@Service
+@Slf4j
+public class CategoryQueryService {
+
+ @Autowired
+ private CategoryDao categoryDao;
+
+ @Autowired
+ private IBeanCache cache;
+
+ /**
+ * 查詢类目
+ *
+ * @param cacheKey
+ * @return
+ */
+ @CacheLoad(CacheModuleBaseConst.Category.CATEGORY)
+ public CategoryEntity queryCategory(String cacheKey) {
+ String businessId = CacheKey.getBusinessIdByCacheKey(cacheKey);
+ return categoryDao.selectById(businessId);
+ }
+
+ /**
+ * 查询类目 子级
+ *
+ * @param cacheKey
+ * @return
+ */
+ @CacheLoad(CacheModuleBaseConst.Category.CATEGORY_SUB)
+ public List querySubCategory(String cacheKey) {
+ /**
+ * 下划线 分隔 key
+ * 左边 categoryId 右边 type
+ */
+ String businessId = CacheKey.getBusinessIdByCacheKey(cacheKey);
+ String[] split = businessId.split(CommonConst.UNDERLINE);
+ Integer categoryType = split.length > 1 ? Integer.valueOf(split[1]) : null;
+ return categoryDao.queryByParentId(Lists.newArrayList(Long.valueOf(split[0])), categoryType, false);
+ }
+
+ /**
+ * 以 类目id+下划线+类型 作为缓存key
+ *
+ * @param categoryId
+ * @param categoryType
+ * @return
+ */
+ private static String getCacheId(Long categoryId, Integer categoryType) {
+ return categoryId + CommonConst.UNDERLINE + categoryType;
+ }
+
+ /**
+ * 批量查询类目 子级
+ *
+ * @param categoryIdList
+ * @return
+ */
+ public Map> querySubCategoryFromCache(List categoryIdList) {
+ return categoryIdList.stream().collect(Collectors.toMap(Function.identity(), e -> {
+ String cacheKey = CacheKey.cacheKey(CacheModuleBaseConst.Category.CATEGORY_SUB, e.toString());
+ return cache.get(cacheKey);
+ }));
+ }
+
+ /**
+ * 根据 id 查询未删除的类目
+ *
+ * @param categoryId
+ * @return 可能 null
+ */
+ public Optional queryCategory(Long categoryId) {
+ if (null == categoryId) {
+ return Optional.empty();
+ }
+ String cacheKey = CacheKey.cacheKey(CacheModuleBaseConst.Category.CATEGORY, categoryId.toString());
+ CategoryEntity entity = cache.get(cacheKey);
+ if (null == entity || entity.getDeletedFlag()) {
+ return Optional.empty();
+ }
+ return Optional.of(entity);
+ }
+
+ /**
+ * 根据 类目id 查询未删除的子类
+ *
+ * @param categoryId
+ * @return 没有返回空集合
+ */
+ public List queryCategoryByParent(Long categoryId, Integer categoryType) {
+ if (null == categoryId) {
+ return CommonConst.EMPTY_LIST;
+ }
+ String cacheKey = CacheKey.cacheKey(CacheModuleBaseConst.Category.CATEGORY_SUB, getCacheId(categoryId, categoryType));
+ return cache.get(cacheKey);
+ }
+
+ /**
+ * 根据 类目id集合 查询未删除的类目集合
+ *
+ * @param categoryIdList
+ * @return
+ */
+ public Map queryCategoryList(List categoryIdList) {
+ if (CollectionUtils.isEmpty(categoryIdList)) {
+ return CommonConst.EMPTY_MAP;
+ }
+ categoryIdList = categoryIdList.stream().distinct().collect(Collectors.toList());
+
+ return categoryIdList.stream().collect(Collectors.toMap(Function.identity(), e -> {
+ String cacheKey = CacheKey.cacheKey(CacheModuleBaseConst.Category.CATEGORY, e.toString());
+ return cache.get(cacheKey);
+ }));
+ }
+
+ /**
+ * 根据类目id 移除缓存
+ */
+ public void removeCache() {
+ cache.removeByModule(CacheModuleBaseConst.Category.CATEGORY);
+ cache.removeByModule(CacheModuleBaseConst.Category.CATEGORY_SUB);
+ // 移除整个类目树缓存
+ cache.removeByModule(CacheModuleBaseConst.Category.CATEGORY_TREE);
+ }
+
+ /**
+ * 根据类目id 递归查询该id的所有子类id 递归查询
+ * 同时存入缓存
+ * 注意:查询出来的集合 不包含传递的父类参数
+ *
+ * @param categoryIdList
+ */
+ public List queryCategorySubId(List categoryIdList) {
+ if (CollectionUtils.isEmpty(categoryIdList)) {
+ return CommonConst.EMPTY_LIST;
+ }
+ // 查询所有子类
+ Map> subTypeMap = this.querySubCategoryFromCache(categoryIdList);
+ if (MapUtils.isEmpty(subTypeMap)) {
+ return Lists.newArrayList();
+ }
+ // 递归查询子类
+ categoryIdList = subTypeMap.values().stream().flatMap(Collection::stream).map(CategoryEntity::getCategoryId).distinct().collect(Collectors.toList());
+ if (CollectionUtils.isEmpty(categoryIdList)) {
+ return Lists.newArrayList();
+ }
+ categoryIdList.addAll(this.queryCategorySubId(categoryIdList));
+ return categoryIdList;
+ }
+
+ /**
+ * 查询自身以及所有子节点
+ * @param categoryIdList
+ * @return
+ */
+ public List queryCategorySelfAndSubId(List categoryIdList) {
+ List subIdList = this.queryCategorySubId(categoryIdList);
+ subIdList.addAll(categoryIdList);
+ return subIdList;
+ }
+
+ /**
+ * 查询类目 层级树
+ * 优先查询缓存
+ *
+ * @return
+ */
+ public List queryCategoryTree(CategoryTreeQueryDTO queryDTO) {
+ // 查询缓存
+ Long parentId = queryDTO.getParentId();
+ Integer categoryType = queryDTO.getCategoryType();
+ String cacheKey = CacheKey.cacheKey(CacheModuleBaseConst.Category.CATEGORY_TREE, getCacheId(parentId, categoryType));
+ List treeList = cache.get(cacheKey);
+ if (null != treeList) {
+ return treeList;
+ }
+ // 查询一级类目
+ List categoryEntityList = this.queryCategoryByParent(parentId, categoryType);
+ treeList = SmartBeanUtil.copyList(categoryEntityList, CategoryTreeVO.class);
+ treeList.forEach(e -> {
+ e.setLabel(e.getCategoryName());
+ e.setValue(e.getCategoryId());
+ e.setCategoryFullName(e.getCategoryName());
+ });
+ // 递归设置子类
+ this.queryAndSetSubCategory(treeList);
+ // 放入缓存
+ cache.put(cacheKey, treeList);
+ return treeList;
+ }
+
+ /**
+ * 递归查询设置类目子类
+ * 从缓存查询子类
+ *
+ * @param treeList
+ */
+ private void queryAndSetSubCategory(List treeList) {
+ if (CollectionUtils.isEmpty(treeList)) {
+ return;
+ }
+ List parentIdList = treeList.stream().map(CategoryTreeVO::getValue).collect(Collectors.toList());
+ Map> categorySubMap = this.querySubCategoryFromCache(parentIdList);
+ treeList.forEach(e -> {
+ List childrenEntityList = categorySubMap.getOrDefault(e.getValue(), Lists.newArrayList());
+ List childrenVOList = SmartBeanUtil.copyList(childrenEntityList, CategoryTreeVO.class);
+ childrenVOList.forEach(item -> {
+ item.setLabel(item.getCategoryName());
+ item.setValue(item.getCategoryId());
+ item.setCategoryFullName(e.getCategoryFullName() + CommonConst.SEPARATOR_SLASH + item.getCategoryName());
+ });
+ // 递归查询
+ this.queryAndSetSubCategory(childrenVOList);
+ e.setChildren(childrenVOList);
+ });
+ }
+
+ /**
+ * 根据类目id 查询类目详情 包含类目全称 如:医考/医师资格/临床执业
+ *
+ * @param categoryId
+ * @return
+ */
+ public CategorySimpleDTO queryCategoryInfo(Long categoryId) {
+ String cacheKey = CacheKey.cacheKey(CacheModuleBaseConst.Category.CATEGORY, categoryId.toString());
+ CategoryEntity categoryEntity = cache.get(cacheKey);
+ if (null == categoryEntity || categoryEntity.getDeletedFlag()) {
+ return null;
+ }
+
+ // 递归查询分类和所有父级类目
+ List parentCategoryList = this.queryCategoryAndParent(categoryId);
+ // 拼接父级类目名称 斜杠分隔返回
+ List nameList = parentCategoryList.stream().map(CategoryEntity::getCategoryName).collect(Collectors.toList());
+
+ // 返回DTO
+ CategorySimpleDTO categoryDTO = new CategorySimpleDTO();
+ categoryDTO.setCategoryId(categoryId);
+ categoryDTO.setCategoryName(categoryEntity.getCategoryName());
+ categoryDTO.setCategoryFullName(SmartStringUtil.join(nameList, CommonConst.SEPARATOR_SLASH));
+ categoryDTO.setParentId(categoryEntity.getParentId());
+ return categoryDTO;
+ }
+
+ /**
+ * 递归查询分类和所有父级类目 ps:特别注意返回的集合中 包含自己
+ *
+ * @param categoryId
+ * @return
+ */
+ public List queryCategoryAndParent(Long categoryId) {
+ List parentCategoryList = Lists.newArrayList();
+ String cacheKey = CacheKey.cacheKey(CacheModuleBaseConst.Category.CATEGORY, categoryId.toString());
+ CategoryEntity categoryEntity = cache.get(cacheKey);
+ if (null == categoryEntity || categoryEntity.getDeletedFlag()) {
+ return parentCategoryList;
+ }
+
+ // 父级始终放在第一位
+ parentCategoryList.add(0, categoryEntity);
+ Long parentId = categoryEntity.getParentId();
+ if (Objects.equals(CommonConst.DEFAULT_PARENT_ID, parentId)) {
+ return parentCategoryList;
+ }
+ parentCategoryList.addAll(0, this.queryCategoryAndParent(parentId));
+ return parentCategoryList;
+ }
+
+ /**
+ * 处理类目名称
+ *
+ * @param categoryIdList
+ */
+ public List queryCategoryName(List categoryIdList) {
+ if (CollectionUtils.isEmpty(categoryIdList)) {
+ return null;
+ }
+ Map categoryMap = this.queryCategoryList(categoryIdList);
+ List categoryNameList = Lists.newArrayList();
+ categoryIdList.forEach(e -> {
+ CategoryEntity categoryEntity = categoryMap.get(e);
+ if (categoryEntity != null) {
+ categoryNameList.add(categoryMap.get(e).getCategoryName());
+ }
+ });
+ return categoryNameList;
+ }
+
+ /**
+ * 根据类目id 查询类目名称
+ *
+ * @param categoryId
+ * @return
+ */
+ public String queryCategoryName(Long categoryId) {
+ String cacheKey = CacheKey.cacheKey(CacheModuleBaseConst.Category.CATEGORY, categoryId.toString());
+ CategoryEntity categoryEntity = cache.get(cacheKey);
+ if (null == categoryEntity || categoryEntity.getDeletedFlag()) {
+ return null;
+ }
+ return categoryEntity.getCategoryName();
+ }
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/CategoryService.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/CategoryService.java
new file mode 100644
index 00000000..234ee049
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/CategoryService.java
@@ -0,0 +1,207 @@
+package net.lab1024.smartadmin.service.module.business.category;
+
+import com.google.common.collect.Lists;
+import net.lab1024.smartadmin.service.common.codeconst.ResponseCodeConst;
+import net.lab1024.smartadmin.service.common.constant.CommonConst;
+import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
+import net.lab1024.smartadmin.service.module.business.category.domain.*;
+import net.lab1024.smartadmin.service.util.SmartBeanUtil;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * 类目 业务
+ *
+ * @author 胡克
+ * @date 2021/1/20 16:26
+ */
+@Service
+public class CategoryService {
+
+ @Autowired
+ private CategoryDao categoryDao;
+
+ @Autowired
+ private CategoryQueryService categoryQueryService;
+
+ /**
+ * 添加类目
+ *
+ * @author 胡克
+ * @date 2021/1/20 17:17
+ */
+ public ResponseDTO add(CategoryAddDTO addDTO) {
+ // 校验类目
+ CategoryEntity categoryEntity = SmartBeanUtil.copy(addDTO, CategoryEntity.class);
+ ResponseDTO res = this.checkCategory(categoryEntity, false);
+ if (!res.isSuccess()) {
+ return res;
+ }
+ // 没有父类则使用默认父类
+ Long parentId = null == addDTO.getParentId() ? CommonConst.DEFAULT_PARENT_ID : addDTO.getParentId();
+ categoryEntity.setParentId(parentId);
+ categoryEntity.setSort(null == addDTO.getSort() ? CommonConst.ZERO : addDTO.getSort());
+ categoryEntity.setDeletedFlag(false);
+
+ // 保存数据
+ categoryDao.insert(categoryEntity);
+
+ // 更新缓存
+ categoryQueryService.removeCache();
+ return ResponseDTO.succ();
+ }
+
+ /**
+ * 更新类目
+ * 不能更新父级类目
+ *
+ * @author 胡克
+ * @date 2021/1/20 17:17
+ */
+ public ResponseDTO update(CategoryUpdateDTO updateDTO) {
+ // 校验类目
+ Long categoryId = updateDTO.getCategoryId();
+ Optional optional = categoryQueryService.queryCategory(categoryId);
+ if (!optional.isPresent()) {
+ return ResponseDTO.wrap(ResponseCodeConst.NOT_EXISTS);
+ }
+ CategoryEntity categoryEntity = SmartBeanUtil.copy(updateDTO, CategoryEntity.class);
+
+ /**
+ * 不更新类目类型
+ * 不更新父类id
+ */
+ Integer categoryType = optional.get().getCategoryType();
+ categoryEntity.setCategoryType(categoryType);
+ categoryEntity.setParentId(optional.get().getParentId());
+
+ ResponseDTO responseDTO = this.checkCategory(categoryEntity, true);
+ if (!responseDTO.isSuccess()) {
+ return responseDTO;
+ }
+ categoryDao.updateById(categoryEntity);
+
+ // 更新缓存
+ categoryQueryService.removeCache();
+ return ResponseDTO.succ();
+ }
+
+ /**
+ * 新增/更新 类目时的 校验
+ *
+ * @param categoryEntity
+ * @param isUpdate
+ * @return
+ */
+ private ResponseDTO checkCategory(CategoryEntity categoryEntity, boolean isUpdate) {
+ // 校验父级是否存在
+ Long parentId = categoryEntity.getParentId();
+ Integer categoryType = categoryEntity.getCategoryType();
+ if (null != parentId) {
+ if (Objects.equals(categoryEntity.getCategoryId(), parentId)) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, "父级类目怎么和自己相同了");
+ }
+ if (!Objects.equals(parentId, CommonConst.DEFAULT_PARENT_ID)) {
+ Optional optional = categoryQueryService.queryCategory(parentId);
+ if (!optional.isPresent()) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.NOT_EXISTS, "父级类目不存在~");
+ }
+
+ CategoryEntity parent = optional.get();
+ if (!Objects.equals(categoryType, parent.getCategoryType())) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, "与父级类目类型不一致");
+ }
+ }
+
+ } else {
+ // 如果没有父类 使用默认父类
+ parentId = CommonConst.DEFAULT_PARENT_ID;
+ }
+
+ // 校验同父类下 名称是否重复
+ CategoryEntity queryEntity = new CategoryEntity();
+ queryEntity.setParentId(parentId);
+ queryEntity.setCategoryType(categoryType);
+ queryEntity.setCategoryName(categoryEntity.getCategoryName());
+ queryEntity.setDeletedFlag(false);
+ queryEntity = categoryDao.selectOne(queryEntity);
+ if (null != queryEntity) {
+ if (isUpdate) {
+ if (!Objects.equals(queryEntity.getCategoryId(), categoryEntity.getCategoryId())) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, "同级下已存在相同类目~");
+ }
+ } else {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, "同级下已存在相同类目~");
+ }
+ }
+ return ResponseDTO.succ();
+ }
+
+ /**
+ * 查询 类目详情
+ *
+ * @param categoryId
+ * @return
+ */
+ public ResponseDTO queryDetail(Long categoryId) {
+ Optional optional = categoryQueryService.queryCategory(categoryId);
+ if (!optional.isPresent()) {
+ return ResponseDTO.wrap(ResponseCodeConst.NOT_EXISTS);
+ }
+ CategoryVO adminVO = SmartBeanUtil.copy(optional.get(), CategoryVO.class);
+ return ResponseDTO.succData(adminVO);
+ }
+
+ /**
+ * 根据父级id 查询所有子类 返回层级树
+ * 如果父类id 为空 返回所有类目层级
+ *
+ * @param queryDTO
+ * @return
+ */
+ public ResponseDTO> queryTree(CategoryTreeQueryDTO queryDTO) {
+ if (null == queryDTO.getParentId()) {
+ if (null == queryDTO.getCategoryType()) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, "类目类型不能为空");
+ }
+ queryDTO.setParentId(CommonConst.DEFAULT_PARENT_ID);
+ }
+ List treeList = categoryQueryService.queryCategoryTree(queryDTO);
+ return ResponseDTO.succData(treeList);
+ }
+
+ /**
+ * 删除类目
+ * 如果有未删除的子类 则无法删除
+ *
+ * @param categoryId
+ * @return
+ */
+ public ResponseDTO delete(Long categoryId) {
+ Optional optional = categoryQueryService.queryCategory(categoryId);
+ if (!optional.isPresent()) {
+ return ResponseDTO.wrap(ResponseCodeConst.NOT_EXISTS);
+ }
+
+ List categorySubId = categoryQueryService.queryCategorySubId(Lists.newArrayList(categoryId));
+ if (CollectionUtils.isNotEmpty(categorySubId)) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, "请先删除子级类目");
+ }
+
+ // 更新数据
+ CategoryEntity categoryEntity = new CategoryEntity();
+ categoryEntity.setCategoryId(categoryId);
+ categoryEntity.setDeletedFlag(true);
+ categoryDao.updateById(categoryEntity);
+
+ // 更新缓存
+ categoryQueryService.removeCache();
+ return ResponseDTO.succ();
+ }
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/constant/CategoryTypeEnum.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/constant/CategoryTypeEnum.java
new file mode 100644
index 00000000..b0225030
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/constant/CategoryTypeEnum.java
@@ -0,0 +1,54 @@
+package net.lab1024.smartadmin.service.module.business.category.constant;
+
+
+import net.lab1024.smartadmin.service.common.constant.BaseEnum;
+
+/**
+ * 分类类型 枚举
+ *
+ * @author listen
+ * @date 2021/08/05 15:26
+ */
+public enum CategoryTypeEnum implements BaseEnum {
+
+ /**
+ * 1 商品
+ */
+ GOODS(1, "商品"),
+
+ /**
+ * 2 测试分类
+ */
+ DEMO(2, "测试分类"),
+
+ ;
+
+ private final Integer type;
+
+ private final String desc;
+
+ CategoryTypeEnum(Integer type, String desc) {
+ this.type = type;
+ this.desc = desc;
+ }
+
+ /**
+ * 获取枚举类的值
+ *
+ * @return Integer
+ */
+ @Override
+ public Integer getValue() {
+ return type;
+ }
+
+ /**
+ * 获取枚举类的说明
+ *
+ * @return String
+ */
+ @Override
+ public String getDesc() {
+ return desc;
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryAddDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryAddDTO.java
new file mode 100644
index 00000000..54b2569c
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryAddDTO.java
@@ -0,0 +1,14 @@
+package net.lab1024.smartadmin.service.module.business.category.domain;
+
+import lombok.Data;
+
+/**
+ * 类目 添加 DTO 类
+ *
+ * @author 胡克
+ * @date 2021/1/20 16:24
+ */
+@Data
+public class CategoryAddDTO extends CategoryBaseDTO {
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryBaseDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryBaseDTO.java
new file mode 100644
index 00000000..45094438
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryBaseDTO.java
@@ -0,0 +1,44 @@
+package net.lab1024.smartadmin.service.module.business.category.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import net.lab1024.smartadmin.service.common.swagger.ApiModelPropertyEnum;
+import net.lab1024.smartadmin.service.common.validator.CheckEnum;
+import net.lab1024.smartadmin.service.module.business.category.constant.CategoryTypeEnum;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 类目 基础属性 DTO 类
+ *
+ * @author 胡克
+ * @date 2021/1/20 16:17
+ */
+@Data
+public class CategoryBaseDTO {
+
+ @ApiModelProperty(value = "类目名称", required = true)
+ @NotBlank(message = "类目名称不能为空")
+ @Length(max = 20, message = "类目名称最多20字符")
+ private String categoryName;
+
+ @ApiModelPropertyEnum(desc = "分类类型", value = CategoryTypeEnum.class)
+ @CheckEnum(enumClazz = CategoryTypeEnum.class, required = true, message = "分类类型错误")
+ private Integer categoryType;
+
+ @ApiModelProperty("父级类目id|可选")
+ private Long parentId;
+
+ @ApiModelProperty("排序|可选")
+ private Integer sort;
+
+ @ApiModelProperty("备注|可选")
+ @Length(max = 200, message = "备注最多200字符")
+ private String remark;
+
+ @ApiModelProperty("禁用状态")
+ @NotNull(message = "禁用状态不能为空")
+ private Boolean disabledFlag;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryEntity.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryEntity.java
new file mode 100644
index 00000000..29f10aa2
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryEntity.java
@@ -0,0 +1,63 @@
+package net.lab1024.smartadmin.service.module.business.category.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 类目 实体类
+ *
+ * @author 胡克
+ * @date 2021/8/6 9:45
+ */
+@Data
+@TableName("t_category")
+public class CategoryEntity {
+
+ @TableId(type = IdType.AUTO)
+ private Long categoryId;
+
+ /**
+ * 类目名称
+ */
+ private String categoryName;
+
+ /**
+ * 类目 类型
+ *
+ * @see CategoryTypeEnum
+ */
+ private Integer categoryType;
+
+ /**
+ * 父级类目id
+ */
+ private Long parentId;
+
+ /**
+ * 是否禁用
+ */
+ private Boolean disabledFlag;
+
+ /**
+ * 排序
+ */
+ private Integer sort;
+
+ /**
+ * 删除状态
+ */
+ private Boolean deletedFlag;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ private LocalDateTime updateTime;
+
+ private LocalDateTime createTime;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategorySimpleDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategorySimpleDTO.java
new file mode 100644
index 00000000..997efece
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategorySimpleDTO.java
@@ -0,0 +1,26 @@
+package net.lab1024.smartadmin.service.module.business.category.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 类目 基础属性 DTO 类
+ *
+ * @author 胡克
+ * @date 2021/1/20 16:17
+ */
+@Data
+public class CategorySimpleDTO {
+
+ @ApiModelProperty("类目id")
+ private Long categoryId;
+
+ @ApiModelProperty("类目名称")
+ private String categoryName;
+
+ @ApiModelProperty("类目层级全称")
+ private String categoryFullName;
+
+ @ApiModelProperty("父级id")
+ private Long parentId;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryTreeQueryDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryTreeQueryDTO.java
new file mode 100644
index 00000000..096079ce
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryTreeQueryDTO.java
@@ -0,0 +1,24 @@
+package net.lab1024.smartadmin.service.module.business.category.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import net.lab1024.smartadmin.service.common.swagger.ApiModelPropertyEnum;
+import net.lab1024.smartadmin.service.common.validator.CheckEnum;
+import net.lab1024.smartadmin.service.module.business.category.constant.CategoryTypeEnum;
+
+/**
+ * 类目 层级树查询 DTO 类
+ *
+ * @author 胡克
+ * @date 2021/1/20 16:17
+ */
+@Data
+public class CategoryTreeQueryDTO {
+
+ @ApiModelPropertyEnum(desc = "分类类型|可选", value = CategoryTypeEnum.class)
+ @CheckEnum(enumClazz = CategoryTypeEnum.class, message = "分类类型错误")
+ private Integer categoryType;
+
+ @ApiModelProperty("父级类目id|可选")
+ private Long parentId;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryTreeVO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryTreeVO.java
new file mode 100644
index 00000000..88171db6
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryTreeVO.java
@@ -0,0 +1,25 @@
+package net.lab1024.smartadmin.service.module.business.category.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 类目 层级树 vo
+ *
+ * @author listen
+ * @date 2021/01/21 17:03
+ */
+@Data
+public class CategoryTreeVO extends CategorySimpleDTO {
+
+ @ApiModelProperty("类目id")
+ private Long value;
+
+ @ApiModelProperty("类目名称")
+ private String label;
+
+ @ApiModelProperty("子类")
+ private List children;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryUpdateDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryUpdateDTO.java
new file mode 100644
index 00000000..fc4cb54c
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryUpdateDTO.java
@@ -0,0 +1,20 @@
+package net.lab1024.smartadmin.service.module.business.category.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 类目 更新 DTO 类
+ *
+ * @author 胡克
+ * @date 2021/1/20 16:24
+ */
+@Data
+public class CategoryUpdateDTO extends CategoryBaseDTO {
+
+ @ApiModelProperty("类目id")
+ @NotNull(message = "类目id不能为空")
+ private Long categoryId;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryVO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryVO.java
new file mode 100644
index 00000000..56c13a5e
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/domain/CategoryVO.java
@@ -0,0 +1,23 @@
+package net.lab1024.smartadmin.service.module.business.category.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 类目 VO 类
+ *
+ * @author 胡克
+ * @date 2021/1/20 16:24
+ */
+@Data
+public class CategoryVO extends CategoryBaseDTO {
+
+ @ApiModelProperty("类目id")
+ private Long categoryId;
+
+ private LocalDateTime updateTime;
+
+ private LocalDateTime createTime;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/package-info.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/package-info.java
new file mode 100644
index 00000000..3d3252b2
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/category/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * 类目 业务
+ * 包含 商品 等类型
+ */
+package net.lab1024.smartadmin.service.module.business.category;
\ No newline at end of file
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/GoodsController.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/GoodsController.java
new file mode 100644
index 00000000..b87fda56
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/GoodsController.java
@@ -0,0 +1,64 @@
+package net.lab1024.smartadmin.service.module.business.goods;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import net.lab1024.smartadmin.service.common.constant.SwaggerTagConst;
+import net.lab1024.smartadmin.service.common.controller.AdminBaseController;
+import net.lab1024.smartadmin.service.common.domain.PageResultDTO;
+import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
+import net.lab1024.smartadmin.service.module.business.goods.domain.*;
+import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginInfoDTO;
+import net.lab1024.smartadmin.service.util.SmartEmployeeTokenUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+
+/**
+ * 商品业务 路由
+ *
+ * @author 胡克
+ * @date 2021/08/21 19:10
+ */
+@Api(tags = SwaggerTagConst.Admin.MANAGER_GOODS)
+@RestController
+public class GoodsController extends AdminBaseController {
+
+ @Autowired
+ private GoodsService goodsService;
+
+ @ApiOperation("添加商品 by listen")
+ @PostMapping("/goods/add")
+ public ResponseDTO add(@RequestBody @Valid GoodsAddDTO addDTO) {
+ EmployeeLoginInfoDTO employee = SmartEmployeeTokenUtil.getRequestEmployee();
+ addDTO.setUpdateId(employee.getEmployeeId());
+ addDTO.setUpdateName(employee.getActualName());
+ return goodsService.add(addDTO);
+ }
+
+ @ApiOperation("更新商品 by listen")
+ @PostMapping("/goods/update")
+ public ResponseDTO update(@RequestBody @Valid GoodsUpdateDTO updateDTO) {
+ EmployeeLoginInfoDTO employee = SmartEmployeeTokenUtil.getRequestEmployee();
+ updateDTO.setUpdateId(employee.getEmployeeId());
+ updateDTO.setUpdateName(employee.getActualName());
+ return goodsService.update(updateDTO);
+ }
+
+ @ApiOperation("删除 by listen")
+ @PostMapping("/goods/del")
+ public ResponseDTO del(@RequestBody @Valid GoodsDelDTO delDTO) {
+ EmployeeLoginInfoDTO employee = SmartEmployeeTokenUtil.getRequestEmployee();
+ delDTO.setUpdateId(employee.getEmployeeId());
+ delDTO.setUpdateName(employee.getActualName());
+ return goodsService.del(delDTO);
+ }
+
+ @ApiOperation("分页查询 by listen")
+ @PostMapping("/goods/query")
+ public ResponseDTO> query(@RequestBody @Valid GoodsQueryDTO queryDTO) {
+ return goodsService.query(queryDTO);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/GoodsDao.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/GoodsDao.java
new file mode 100644
index 00000000..3207255d
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/GoodsDao.java
@@ -0,0 +1,39 @@
+package net.lab1024.smartadmin.service.module.business.goods;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import net.lab1024.smartadmin.service.module.business.goods.domain.GoodsAdminVO;
+import net.lab1024.smartadmin.service.module.business.goods.domain.GoodsBO;
+import net.lab1024.smartadmin.service.module.business.goods.domain.GoodsEntity;
+import net.lab1024.smartadmin.service.module.business.goods.domain.GoodsQueryDTO;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * 商品 dao
+ *
+ * @author 胡克
+ * @date 2021/8/6 15:26
+ */
+@Component
+public interface GoodsDao extends BaseMapper {
+
+ /**
+ * 查询1个商品 具体条件看sql
+ *
+ * @param goodsBO
+ * @return
+ */
+ GoodsEntity selectOne(GoodsBO goodsBO);
+
+ /**
+ * 分页 查询商品
+ *
+ * @param page
+ * @param queryDTO
+ * @return
+ */
+ List query(Page page, @Param("query") GoodsQueryDTO queryDTO);
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/GoodsManager.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/GoodsManager.java
new file mode 100644
index 00000000..da3844ef
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/GoodsManager.java
@@ -0,0 +1,16 @@
+package net.lab1024.smartadmin.service.module.business.goods;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import net.lab1024.smartadmin.service.module.business.goods.domain.GoodsEntity;
+import org.springframework.stereotype.Service;
+
+/**
+ * 商品 manager
+ *
+ * @author 胡克
+ * @date 2021/8/6 15:26
+ */
+@Service
+public class GoodsManager extends ServiceImpl {
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/GoodsService.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/GoodsService.java
new file mode 100644
index 00000000..98d15a21
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/GoodsService.java
@@ -0,0 +1,146 @@
+package net.lab1024.smartadmin.service.module.business.goods;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import net.lab1024.smartadmin.service.common.codeconst.ResponseCodeConst;
+import net.lab1024.smartadmin.service.common.domain.PageResultDTO;
+import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
+import net.lab1024.smartadmin.service.module.business.category.CategoryQueryService;
+import net.lab1024.smartadmin.service.module.business.category.constant.CategoryTypeEnum;
+import net.lab1024.smartadmin.service.module.business.category.domain.CategoryEntity;
+import net.lab1024.smartadmin.service.module.business.goods.domain.*;
+import net.lab1024.smartadmin.service.util.SmartBeanUtil;
+import net.lab1024.smartadmin.service.util.SmartPageUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * 商品 业务
+ *
+ * @author 胡克
+ * @date 2021/8/6 15:27
+ */
+@Service
+public class GoodsService {
+
+ @Autowired
+ private GoodsDao goodsDao;
+
+ @Autowired
+ private GoodsManager goodsManager;
+
+ @Autowired
+ private CategoryQueryService categoryQueryService;
+
+ /**
+ * 添加商品
+ *
+ * @param addDTO
+ * @return
+ */
+ public ResponseDTO add(GoodsAddDTO addDTO) {
+ // 商品校验
+ ResponseDTO res = this.checkGoods(addDTO, null);
+ if (!res.isSuccess()) {
+ return res;
+ }
+
+ GoodsEntity goodsEntity = SmartBeanUtil.copy(addDTO, GoodsEntity.class);
+ goodsDao.insert(goodsEntity);
+ return ResponseDTO.succ();
+ }
+
+ /**
+ * 更新商品
+ *
+ * @param updateDTO
+ * @return
+ */
+ public ResponseDTO update(GoodsUpdateDTO updateDTO) {
+ // 商品校验
+ ResponseDTO res = this.checkGoods(updateDTO, updateDTO.getGoodsId());
+ if (!res.isSuccess()) {
+ return res;
+ }
+
+ GoodsEntity goodsEntity = SmartBeanUtil.copy(updateDTO, GoodsEntity.class);
+ goodsDao.updateById(goodsEntity);
+ return ResponseDTO.succ();
+ }
+
+ /**
+ * 添加/更新 商品校验
+ *
+ * @param addDTO
+ * @param goodsId 不为空 代表更新商品
+ * @return
+ */
+ private ResponseDTO checkGoods(GoodsAddDTO addDTO, Long goodsId) {
+ // 校验商品名称重复
+ Long categoryId = addDTO.getCategoryId();
+
+ GoodsBO goodsBO = new GoodsBO();
+ goodsBO.setGoodsName(addDTO.getGoodsName());
+ goodsBO.setGoodsType(addDTO.getGoodsType());
+ goodsBO.setCategoryId(categoryId);
+ goodsBO.setDeletedFlag(false);
+ GoodsEntity goodsEntity = goodsDao.selectOne(goodsBO);
+ if (null != goodsEntity) {
+ if (null == goodsId || !Objects.equals(goodsEntity.getGoodsId(), goodsId)) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ALREADY_EXIST, "商品名称不能重复~");
+ }
+ }
+
+ // 校验类目id
+ Optional optional = categoryQueryService.queryCategory(categoryId);
+ if (!optional.isPresent() || !CategoryTypeEnum.GOODS.equalsValue(optional.get().getCategoryType())) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.NOT_EXISTS, "商品类目不存在~");
+ }
+
+ return ResponseDTO.succ();
+ }
+
+ /**
+ * 批量删除
+ *
+ * @param delDTO
+ * @return
+ */
+ public ResponseDTO del(GoodsDelDTO delDTO) {
+ // 批量更新删除状态
+ List goodsList = delDTO.getGoodsIdList().stream().map(id -> {
+ GoodsEntity goodsEntity = new GoodsEntity();
+ goodsEntity.setGoodsId(id);
+ goodsEntity.setDeletedFlag(true);
+ return goodsEntity;
+ }).collect(Collectors.toList());
+ goodsManager.updateBatchById(goodsList);
+ return ResponseDTO.succ();
+ }
+
+ /**
+ * 分页查询
+ *
+ * @param queryDTO
+ * @return
+ */
+ public ResponseDTO> query(GoodsQueryDTO queryDTO) {
+ queryDTO.setDeletedFlag(false);
+ Page page = SmartPageUtil.convert2PageQuery(queryDTO);
+ List list = goodsDao.query(page, queryDTO);
+ PageResultDTO pageResult = SmartPageUtil.convert2PageResult(page, list);
+ if (pageResult.getEmptyFlag()) {
+ return ResponseDTO.succData(pageResult);
+ }
+ // 查询分类名称
+ List categoryIdList = list.stream().map(GoodsAdminVO::getCategoryId).distinct().collect(Collectors.toList());
+ Map categoryMap = categoryQueryService.queryCategoryList(categoryIdList);
+ list.forEach(e -> e.setCategoryName(categoryMap.get(e.getCategoryId()).getCategoryName()));
+ return ResponseDTO.succData(pageResult);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/constant/GoodsTypeEnum.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/constant/GoodsTypeEnum.java
new file mode 100644
index 00000000..a4191753
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/constant/GoodsTypeEnum.java
@@ -0,0 +1,54 @@
+package net.lab1024.smartadmin.service.module.business.goods.constant;
+
+
+import net.lab1024.smartadmin.service.common.constant.BaseEnum;
+
+/**
+ * 商品类型 枚举
+ *
+ * @author listen
+ * @date 2021/08/05 15:26
+ */
+public enum GoodsTypeEnum implements BaseEnum {
+
+ /**
+ * 1 图书
+ */
+ BOOK(1, "图书"),
+
+ /**
+ * 2 课程
+ */
+ COURSE(2, "课程"),
+
+ ;
+
+ private final Integer type;
+
+ private final String desc;
+
+ GoodsTypeEnum(Integer type, String desc) {
+ this.type = type;
+ this.desc = desc;
+ }
+
+ /**
+ * 获取枚举类的值
+ *
+ * @return Integer
+ */
+ @Override
+ public Integer getValue() {
+ return type;
+ }
+
+ /**
+ * 获取枚举类的说明
+ *
+ * @return String
+ */
+ @Override
+ public String getDesc() {
+ return desc;
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsAddDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsAddDTO.java
new file mode 100644
index 00000000..db94372e
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsAddDTO.java
@@ -0,0 +1,20 @@
+package net.lab1024.smartadmin.service.module.business.goods.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 商品 添加 DTO
+ *
+ * @author 胡克
+ * @date 2021/8/5 14:42
+ */
+@Data
+public class GoodsAddDTO extends GoodsBaseDTO {
+
+ @ApiModelProperty(hidden = true)
+ private Long updateId;
+
+ @ApiModelProperty(hidden = true)
+ private String updateName;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsAdminVO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsAdminVO.java
new file mode 100644
index 00000000..f7ff5271
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsAdminVO.java
@@ -0,0 +1,26 @@
+package net.lab1024.smartadmin.service.module.business.goods.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 商品 添加 DTO
+ *
+ * @author 胡克
+ * @date 2021/8/5 14:42
+ */
+@Data
+public class GoodsAdminVO extends GoodsBaseDTO {
+
+ @ApiModelProperty("商品id")
+ private Long goodsId;
+
+ @ApiModelProperty("商品分类")
+ private String categoryName;
+
+ private LocalDateTime updateTime;
+
+ private LocalDateTime createTime;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsBO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsBO.java
new file mode 100644
index 00000000..625ddf81
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsBO.java
@@ -0,0 +1,36 @@
+package net.lab1024.smartadmin.service.module.business.goods.domain;
+
+import lombok.Data;
+import net.lab1024.smartadmin.service.module.business.goods.constant.GoodsTypeEnum;
+
+/**
+ * 商品
+ *
+ * @author 胡克
+ * @date 2021/8/5 14:42
+ */
+@Data
+public class GoodsBO {
+
+ /**
+ * 商品类型
+ *
+ * @see GoodsTypeEnum
+ */
+ private Integer goodsType;
+
+ /**
+ * 商品分类
+ */
+ private Long categoryId;
+
+ /**
+ * 商品名称
+ */
+ private String goodsName;
+
+ /**
+ * 删除状态
+ */
+ private Boolean deletedFlag;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsBaseDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsBaseDTO.java
new file mode 100644
index 00000000..a6d1b657
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsBaseDTO.java
@@ -0,0 +1,60 @@
+package net.lab1024.smartadmin.service.module.business.goods.domain;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import net.lab1024.smartadmin.service.common.json.FileKeySerializer;
+import net.lab1024.smartadmin.service.common.swagger.ApiModelPropertyEnum;
+import net.lab1024.smartadmin.service.common.validator.CheckEnum;
+import net.lab1024.smartadmin.service.module.business.goods.constant.GoodsTypeEnum;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.DecimalMin;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+
+/**
+ * 商品 基础属性 DTO
+ *
+ * @author 胡克
+ * @date 2021/8/5 14:42
+ */
+@Data
+public class GoodsBaseDTO {
+
+ @ApiModelPropertyEnum(desc = "商品类型", value = GoodsTypeEnum.class)
+ @CheckEnum(enumClazz = GoodsTypeEnum.class, message = "商品类型错误")
+ private Integer goodsType;
+
+ @ApiModelProperty("商品分类")
+ @NotNull(message = "商品分类不能为空")
+ private Long categoryId;
+
+ @ApiModelProperty("商品名称")
+ @NotBlank(message = "商品名称不能为空")
+ @Length(max = 200, message = "商品名称最多50字符")
+ private String goodsName;
+
+ @ApiModelProperty("商品简介")
+ @Length(max = 200, message = "商品简介最多200字符")
+ private String goodsIntro;
+
+ @ApiModelProperty("商品价格")
+ @NotNull(message = "商品价格不能为空")
+ @DecimalMin(value = "0", message = "商品价格最低0")
+ private BigDecimal price;
+
+ @ApiModelProperty("商品封面")
+ @Length(max = 250, message = "商品封面最多250字符")
+ @JsonSerialize(using = FileKeySerializer.class)
+ private String coverPic;
+
+ @ApiModelProperty("上架状态")
+ @NotNull(message = "上架状态不能为空")
+ private Boolean shelvesFlag;
+
+ @ApiModelProperty("备注|可选")
+ @Length(max = 200, message = "备注最多200字符")
+ private String remark;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsDelDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsDelDTO.java
new file mode 100644
index 00000000..c1d86cad
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsDelDTO.java
@@ -0,0 +1,29 @@
+package net.lab1024.smartadmin.service.module.business.goods.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.Size;
+import java.util.List;
+
+/**
+ * 商品 删除 DTO
+ *
+ * @author 胡克
+ * @date 2021/8/5 14:42
+ */
+@Data
+public class GoodsDelDTO {
+
+ @ApiModelProperty("商品id集合")
+ @NotEmpty(message = "商品id不能为空")
+ @Size(max = 99, message = "一次最多删除99")
+ private List goodsIdList;
+
+ @ApiModelProperty(hidden = true)
+ private Long updateId;
+
+ @ApiModelProperty(hidden = true)
+ private String updateName;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsEntity.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsEntity.java
new file mode 100644
index 00000000..319d077c
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsEntity.java
@@ -0,0 +1,77 @@
+package net.lab1024.smartadmin.service.module.business.goods.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import net.lab1024.smartadmin.service.module.business.goods.constant.GoodsTypeEnum;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 商品 实体类
+ *
+ * @author 胡克
+ * @date 2021/8/5 14:42
+ */
+@Data
+@TableName("t_goods")
+public class GoodsEntity {
+
+ @TableId(type = IdType.AUTO)
+ private Long goodsId;
+
+ /**
+ * 商品类型
+ *
+ * @see GoodsTypeEnum
+ */
+ private Integer goodsType;
+
+ /**
+ * 第三方商品id
+ */
+ private Long thirdGoodsId;
+
+ /**
+ * 商品分类
+ */
+ private Long categoryId;
+
+ /**
+ * 商品名称
+ */
+ private String goodsName;
+
+ /**
+ * 商品简介
+ */
+ private String goodsIntro;
+
+ /**
+ * 商品价格
+ */
+ private BigDecimal price;
+
+ /**
+ * 商品封面
+ */
+ private String coverPic;
+
+ /**
+ * 上架状态
+ */
+ private Boolean shelvesFlag;
+
+ /**
+ * 删除状态
+ */
+ private Boolean deletedFlag;
+
+ private String remark;
+
+ private LocalDateTime updateTime;
+
+ private LocalDateTime createTime;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsQueryDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsQueryDTO.java
new file mode 100644
index 00000000..6f035229
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsQueryDTO.java
@@ -0,0 +1,36 @@
+package net.lab1024.smartadmin.service.module.business.goods.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import net.lab1024.smartadmin.service.common.domain.PageBaseDTO;
+import net.lab1024.smartadmin.service.common.swagger.ApiModelPropertyEnum;
+import net.lab1024.smartadmin.service.common.validator.CheckEnum;
+import net.lab1024.smartadmin.service.module.business.goods.constant.GoodsTypeEnum;
+import org.hibernate.validator.constraints.Length;
+
+/**
+ * 商品 添加 DTO
+ *
+ * @author 胡克
+ * @date 2021/8/5 14:42
+ */
+@Data
+public class GoodsQueryDTO extends PageBaseDTO {
+
+ @ApiModelPropertyEnum(desc = "商品类型|可选", value = GoodsTypeEnum.class)
+ @CheckEnum(enumClazz = GoodsTypeEnum.class, message = "商品类型错误")
+ private Integer goodsType;
+
+ @ApiModelProperty("商品分类")
+ private Integer categoryId;
+
+ @ApiModelProperty("搜索词")
+ @Length(max = 30, message = "搜索词最多30字符")
+ private String searchWord;
+
+ @ApiModelProperty("上架状态")
+ private Boolean shelvesFlag;
+
+ @ApiModelProperty(hidden = true)
+ private Boolean deletedFlag;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsUpdateDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsUpdateDTO.java
new file mode 100644
index 00000000..e768fdee
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/goods/domain/GoodsUpdateDTO.java
@@ -0,0 +1,20 @@
+package net.lab1024.smartadmin.service.module.business.goods.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 商品 更新 DTO
+ *
+ * @author 胡克
+ * @date 2021/8/5 14:42
+ */
+@Data
+public class GoodsUpdateDTO extends GoodsAddDTO {
+
+ @ApiModelProperty("商品id")
+ @NotNull(message = "商品id不能为空")
+ private Long goodsId;
+}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/business/notice/NoticeController.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/NoticeController.java
similarity index 50%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/business/notice/NoticeController.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/NoticeController.java
index 5d42d5d9..e62fbb6a 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/business/notice/NoticeController.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/NoticeController.java
@@ -1,96 +1,87 @@
-package net.lab1024.smartadmin.module.business.notice;
+package net.lab1024.smartadmin.service.module.business.notice;
-import net.lab1024.smartadmin.common.anno.NoValidPrivilege;
-import net.lab1024.smartadmin.common.domain.PageParamDTO;
-import net.lab1024.smartadmin.common.domain.PageResultDTO;
-import net.lab1024.smartadmin.common.domain.ResponseDTO;
-import net.lab1024.smartadmin.constant.SwaggerTagConst;
-import net.lab1024.smartadmin.module.business.notice.domain.dto.*;
-import net.lab1024.smartadmin.util.SmartRequestTokenUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
+import net.lab1024.smartadmin.service.common.constant.SwaggerTagConst;
+import net.lab1024.smartadmin.service.common.controller.AdminBaseController;
+import net.lab1024.smartadmin.service.common.domain.PageBaseDTO;
+import net.lab1024.smartadmin.service.common.domain.PageResultDTO;
+import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
+import net.lab1024.smartadmin.service.module.business.notice.domain.dto.*;
+import net.lab1024.smartadmin.service.module.business.notice.domain.vo.NoticeDetailVO;
+import net.lab1024.smartadmin.service.module.business.notice.domain.vo.NoticeVO;
+import net.lab1024.smartadmin.service.util.SmartEmployeeTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
- * [ ]
+ * [ 通知公告 ]
*
- * @author yandanyang
- * @version 1.0
- * @company 1024lab.net
- * @copyright (c) 2019 1024lab.netInc. All rights reserved.
- * @date 2019-07-11 16:19:48
- * @since JDK1.8
+ * @author 罗伊
+ * @date
*/
@RestController
@Api(tags = {SwaggerTagConst.Admin.MANAGER_NOTICE})
-public class NoticeController {
+public class NoticeController extends AdminBaseController {
@Autowired
private NoticeService noticeService;
- @ApiOperation(value = "分页查询全部消息", notes = "@author yandanyang")
+ @ApiOperation(value = "分页查询全部消息", notes = "@author 罗伊")
@PostMapping("/notice/page/query")
- @NoValidPrivilege
public ResponseDTO> queryByPage(@RequestBody NoticeQueryDTO queryDTO) {
return noticeService.queryByPage(queryDTO);
}
- @ApiOperation(value = "获取已收取的所有消息", notes = "@author yandanyang")
+ @ApiOperation(value = "获取已收取的所有消息", notes = "@author 罗伊")
@PostMapping("/notice/receive/page/query")
- @NoValidPrivilege
public ResponseDTO> queryReceiveByPage(@RequestBody NoticeReceiveQueryDTO queryDTO) {
- return noticeService.queryReceiveByPage(queryDTO, SmartRequestTokenUtil.getRequestUser());
+ queryDTO.setEmployeeId(SmartEmployeeTokenUtil.getRequestEmployeeId());
+ return noticeService.queryReceiveByPage(queryDTO);
}
- @ApiOperation(value = "分页查询未读消息", notes = "@author yandanyang")
+ @ApiOperation(value = "分页查询未读消息", notes = "@author 罗伊")
@PostMapping("/notice/unread/page/query")
- @NoValidPrivilege
- public ResponseDTO> queryUnreadByPage(@RequestBody PageParamDTO queryDTO) {
- return noticeService.queryUnreadByPage(queryDTO, SmartRequestTokenUtil.getRequestUser());
+ public ResponseDTO> queryUnreadByPage(@RequestBody PageBaseDTO queryDTO) {
+ return noticeService.queryUnreadByPage(queryDTO, SmartEmployeeTokenUtil.getRequestEmployeeId());
}
- @ApiOperation(value = "添加", notes = "@author yandanyang")
+ @ApiOperation(value = "添加", notes = "@author 罗伊")
@PostMapping("/notice/add")
- @NoValidPrivilege
- public ResponseDTO add(@RequestBody @Valid NoticeAddDTO addTO) {
- return noticeService.add(addTO, SmartRequestTokenUtil.getRequestUser());
+ public ResponseDTO add(@RequestBody @Valid NoticeAddDTO addDTO) {
+ addDTO.setCreateId(SmartEmployeeTokenUtil.getRequestEmployeeId());
+ return noticeService.add(addDTO);
}
- @ApiOperation(value = "修改", notes = "@author yandanyang")
+ @ApiOperation(value = "修改", notes = "@author 罗伊")
@PostMapping("/notice/update")
- @NoValidPrivilege
public ResponseDTO update(@RequestBody @Valid NoticeUpdateDTO updateDTO) {
return noticeService.update(updateDTO);
}
- @ApiOperation(value = "删除", notes = "@author yandanyang")
+ @ApiOperation(value = "删除", notes = "@author 罗伊")
@GetMapping("/notice/delete/{id}")
- @NoValidPrivilege
public ResponseDTO delete(@PathVariable("id") Long id) {
return noticeService.delete(id);
}
- @ApiOperation(value = "详情", notes = "@author yandanyang")
+ @ApiOperation(value = "详情", notes = "@author 罗伊")
@GetMapping("/notice/detail/{id}")
- @NoValidPrivilege
public ResponseDTO detail(@PathVariable("id") Long id) {
return noticeService.detail(id);
}
- @ApiOperation(value = "发送", notes = "@author yandanyang")
+ @ApiOperation(value = "发送", notes = "@author 罗伊")
@GetMapping("/notice/send/{id}")
- @NoValidPrivilege
public ResponseDTO send(@PathVariable("id") Long id) {
- return noticeService.send(id, SmartRequestTokenUtil.getRequestUser());
+ return noticeService.send(id, SmartEmployeeTokenUtil.getRequestEmployeeId());
}
- @ApiOperation(value = "读取消息", notes = "@author yandanyang")
+ @ApiOperation(value = "读取消息", notes = "@author 罗伊")
@GetMapping("/notice/read/{id}")
- @NoValidPrivilege
public ResponseDTO read(@PathVariable("id") Long id) {
- return noticeService.read(id, SmartRequestTokenUtil.getRequestUser());
+ return noticeService.read(id, SmartEmployeeTokenUtil.getRequestEmployeeId());
}
}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/NoticeManage.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/NoticeManage.java
new file mode 100644
index 00000000..b47991bd
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/NoticeManage.java
@@ -0,0 +1,86 @@
+package net.lab1024.smartadmin.service.module.business.notice;
+
+import net.lab1024.smartadmin.service.module.business.notice.dao.NoticeDao;
+import net.lab1024.smartadmin.service.module.business.notice.dao.NoticeReceiveRecordDao;
+import net.lab1024.smartadmin.service.module.business.notice.domain.dto.NoticeUpdateDTO;
+import net.lab1024.smartadmin.service.module.business.notice.domain.entity.NoticeEntity;
+import net.lab1024.smartadmin.service.module.business.notice.domain.entity.NoticeReceiveRecordEntity;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ */
+@Service
+public class NoticeManage {
+
+ @Autowired
+ private NoticeDao noticeDao;
+
+ @Autowired
+ private NoticeReceiveRecordDao noticeReceiveRecordDao;
+
+ /**
+ * 发送消息
+ *
+ * @param entity
+ * @param employeeId
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public void send(NoticeEntity entity, Long employeeId) {
+ entity.setSendStatus(true);
+ noticeDao.updateById(entity);
+ //默认发件人 已读此消息
+ NoticeReceiveRecordEntity recordEntity = new NoticeReceiveRecordEntity();
+ recordEntity.setEmployeeId(employeeId);
+ recordEntity.setNoticeId(entity.getId());
+ noticeReceiveRecordDao.insert(recordEntity);
+ }
+
+
+ /**
+ * 保存读取记录
+ *
+ * @param noticeId
+ * @param employeeId
+ */
+ public void saveReadRecord(Long noticeId, Long employeeId) {
+ NoticeReceiveRecordEntity recordEntity = new NoticeReceiveRecordEntity();
+ recordEntity.setEmployeeId(employeeId);
+ recordEntity.setNoticeId(noticeId);
+ noticeReceiveRecordDao.insert(recordEntity);
+ }
+
+
+ /**
+ * 消息删除
+ *
+ * @param entity
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public void delete(NoticeEntity entity) {
+ if (entity.getSendStatus()) {
+ //消息已发送 执行逻辑删除
+ noticeDao.logicDeleteById(entity.getId(), true);
+ } else {
+ //消息未发送 执行真实删除
+ noticeDao.deleteById(entity.getId());
+ }
+ }
+
+ /**
+ * 更新消息
+ *
+ * @param updateDTO
+ */
+ public void update(NoticeUpdateDTO updateDTO) {
+ NoticeEntity updateEntity = new NoticeEntity();
+ updateEntity.setId(updateDTO.getId());
+ updateEntity.setTitle(updateDTO.getTitle());
+ updateEntity.setContent(updateDTO.getContent());
+ noticeDao.updateById(updateEntity);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/NoticeService.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/NoticeService.java
new file mode 100644
index 00000000..68a0660a
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/NoticeService.java
@@ -0,0 +1,215 @@
+package net.lab1024.smartadmin.service.module.business.notice;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import net.lab1024.smartadmin.service.common.codeconst.ResponseCodeConst;
+import net.lab1024.smartadmin.service.common.domain.PageBaseDTO;
+import net.lab1024.smartadmin.service.common.domain.PageResultDTO;
+import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
+import net.lab1024.smartadmin.service.module.business.notice.dao.NoticeDao;
+import net.lab1024.smartadmin.service.module.business.notice.dao.NoticeReceiveRecordDao;
+import net.lab1024.smartadmin.service.module.business.notice.domain.dto.*;
+import net.lab1024.smartadmin.service.module.business.notice.domain.entity.NoticeEntity;
+import net.lab1024.smartadmin.service.module.business.notice.domain.entity.NoticeReceiveRecordEntity;
+import net.lab1024.smartadmin.service.module.business.notice.domain.vo.NoticeDetailVO;
+import net.lab1024.smartadmin.service.module.business.notice.domain.vo.NoticeVO;
+import net.lab1024.smartadmin.service.util.SmartBeanUtil;
+import net.lab1024.smartadmin.service.util.SmartPageUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ */
+@Service
+public class NoticeService {
+
+ @Autowired
+ private NoticeDao noticeDao;
+
+ @Autowired
+ private NoticeReceiveRecordDao noticeReceiveRecordDao;
+
+ @Autowired
+ private NoticeManage noticeManage;
+
+ /**
+ * @author 罗伊
+ * @description 分页查询
+ * @date 2019-07-11 16:19:48
+ */
+ public ResponseDTO> queryByPage(NoticeQueryDTO queryDTO) {
+ queryDTO.setDeletedFlag(false);
+ Page page = SmartPageUtil.convert2PageQuery(queryDTO);
+ List dtoList = noticeDao.queryByPage(page, queryDTO);
+ PageResultDTO pageResultDTO = SmartPageUtil.convert2PageResult(page, dtoList);
+ return ResponseDTO.succData(pageResultDTO);
+ }
+
+ /**
+ * 获取当前登录人的消息列表
+ *
+ * @param queryDTO
+ * @return
+ */
+ public ResponseDTO> queryReceiveByPage(NoticeReceiveQueryDTO queryDTO) {
+ queryDTO.setSendStatus(true);
+ Page page = SmartPageUtil.convert2PageQuery(queryDTO);
+ List dtoList = noticeDao.queryReceiveByPage(page, queryDTO);
+ //根据用户的接收时间设置读取状态,以便前端对其设置
+ dtoList.forEach(e -> {
+ e.setReadStatus(e.getReceiveTime() != null);
+ });
+ PageResultDTO pageResultDTO = SmartPageUtil.convert2PageResult(page, dtoList);
+ return ResponseDTO.succData(pageResultDTO);
+ }
+
+ /**
+ * 获取我的未读消息
+ *
+ * @param queryDTO
+ * @return
+ */
+ public ResponseDTO> queryUnreadByPage(PageBaseDTO queryDTO, Long employeeId) {
+ Page page = SmartPageUtil.convert2PageQuery(queryDTO);
+ List dtoList = noticeDao.queryUnreadByPage(page, employeeId, true);
+ PageResultDTO pageResultDTO = SmartPageUtil.convert2PageResult(page, dtoList);
+ return ResponseDTO.succData(pageResultDTO);
+ }
+
+ /**
+ * @author 罗伊
+ * @description 添加
+ * @date 2019-07-11 16:19:48
+ */
+ public ResponseDTO add(NoticeAddDTO addDTO) {
+ NoticeEntity entity = SmartBeanUtil.copy(addDTO, NoticeEntity.class);
+ entity.setCreateUser(addDTO.getCreateId());
+ entity.setSendStatus(false);
+ entity.setDeletedFlag(true);
+ noticeDao.insert(entity);
+ return ResponseDTO.succ();
+ }
+
+ /**
+ * @author 罗伊
+ * @description 编辑
+ * @date 2019-07-11 16:19:48
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO update(NoticeUpdateDTO updateDTO) {
+ NoticeEntity entity = noticeDao.selectById(updateDTO.getId());
+ if (entity == null) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, "此系统通知不存在");
+ }
+ if (entity.getDeletedFlag()) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, "此系统通知已删除");
+ }
+ if (entity.getSendStatus()) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, "此系统通知已发送无法修改");
+ }
+ noticeManage.update(updateDTO);
+ return ResponseDTO.succ();
+ }
+
+ /**
+ * @author 罗伊
+ * @description 删除
+ * @date 2019-07-11 16:19:48
+ */
+ public ResponseDTO delete(Long id) {
+ NoticeEntity entity = noticeDao.selectById(id);
+ if (entity == null) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, "此系统通知不存在");
+ }
+ noticeManage.delete(entity);
+ return ResponseDTO.succ();
+ }
+
+ /**
+ * @author 罗伊
+ * @description 根据ID查询
+ * @date 2019-07-11 16:19:48
+ */
+ public ResponseDTO detail(Long id) {
+ NoticeDetailVO noticeDTO = noticeDao.detail(id);
+ return ResponseDTO.succData(noticeDTO);
+ }
+
+ /**
+ * 获取某人的未读消息数
+ *
+ * @param employeeId
+ * @return
+ */
+ private Integer getUnreadCount(Long employeeId) {
+ return noticeDao.noticeUnreadCount(employeeId, true);
+ }
+
+ /**
+ * 发送给所有在线用户未读消息数
+ *
+ * @param id
+ * @param employeeId
+ * @return
+ */
+ public ResponseDTO send(Long id, Long employeeId) {
+ NoticeEntity entity = noticeDao.selectById(id);
+ if (entity == null) {
+ return ResponseDTO.wrapMsg(ResponseCodeConst.ERROR_PARAM, "此系统通知不存在");
+ }
+ noticeManage.send(entity, employeeId);
+ this.sendMessage(employeeId);
+ return ResponseDTO.succ();
+ }
+
+ /**
+ * 发送系统通知 ,发送人不进行接收,需再事务外调用 以防止数据隔离级别不同造成未读消息数异常
+ *
+ * @param sendEmployeeId
+ */
+ private void sendMessage(Long sendEmployeeId) {
+/* List onLineEmployeeIds = WebSocketServer.getOnLineUserList();
+ if (CollectionUtils.isEmpty(onLineEmployeeIds)) {
+ return;
+ }
+ //在线用户已读消息数
+ Map readCountMap = new HashMap<>();
+ List readCountList = noticeDao.readCount(onLineEmployeeIds);
+ if (CollectionUtils.isNotEmpty(readCountList)) {
+ readCountMap = readCountList.stream().collect(Collectors.toMap(NoticeReadCountDTO::getEmployeeId, NoticeReadCountDTO::getReadCount));
+ }
+ //已发送消息数
+ Integer noticeCount = noticeDao.noticeCount(true);
+ for (Long employeeId : onLineEmployeeIds) {
+ if (Objects.equals(employeeId, sendEmployeeId)) {
+ continue;
+ }
+ int readCount = readCountMap.get(employeeId) == null ? 0 : readCountMap.get(employeeId);
+ WebSocketServer.sendOneOnLineUser(String.valueOf(noticeCount - readCount), employeeId);
+ }*/
+ }
+
+ /**
+ * 读取消息
+ *
+ * @param id
+ * @param employeeId
+ * @return
+ */
+ public ResponseDTO read(Long id, Long employeeId) {
+ NoticeDetailVO noticeDTO = noticeDao.detail(id);
+
+ NoticeReceiveRecordEntity recordEntity = noticeReceiveRecordDao.selectByEmployeeAndNotice(employeeId, id);
+ if (recordEntity != null) {
+ return ResponseDTO.succData(noticeDTO);
+ }
+ noticeManage.saveReadRecord(id, employeeId);
+ this.sendMessage(employeeId);
+ return ResponseDTO.succData(noticeDTO);
+ }
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/dao/NoticeDao.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/dao/NoticeDao.java
new file mode 100644
index 00000000..b7f2edba
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/dao/NoticeDao.java
@@ -0,0 +1,112 @@
+package net.lab1024.smartadmin.service.module.business.notice.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import net.lab1024.smartadmin.service.module.business.notice.domain.dto.NoticeQueryDTO;
+import net.lab1024.smartadmin.service.module.business.notice.domain.dto.NoticeReadCountDTO;
+import net.lab1024.smartadmin.service.module.business.notice.domain.dto.NoticeReceiveDTO;
+import net.lab1024.smartadmin.service.module.business.notice.domain.dto.NoticeReceiveQueryDTO;
+import net.lab1024.smartadmin.service.module.business.notice.domain.entity.NoticeEntity;
+import net.lab1024.smartadmin.service.module.business.notice.domain.vo.NoticeDetailVO;
+import net.lab1024.smartadmin.service.module.business.notice.domain.vo.NoticeVO;
+import net.lab1024.smartadmin.service.module.system.datascope.DataScope;
+import net.lab1024.smartadmin.service.module.system.datascope.constant.DataScopeTypeEnum;
+import net.lab1024.smartadmin.service.module.system.datascope.constant.DataScopeWhereInTypeEnum;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ */
+@Mapper
+@Component
+public interface NoticeDao extends BaseMapper {
+
+ /**
+ * 分页查询
+ *
+ * @param queryDTO
+ * @return NoticeEntity
+ */
+ @DataScope(dataScopeType = DataScopeTypeEnum.NOTICE, joinSql = "n.create_user in (#employeeIds)", whereInType = DataScopeWhereInTypeEnum.EMPLOYEE)
+ List queryByPage(Page page, @Param("queryDTO") NoticeQueryDTO queryDTO);
+
+
+ /**
+ * 获取某人的未读消息
+ *
+ * @param page
+ * @param employeeId
+ * @return
+ */
+ @DataScope(dataScopeType = DataScopeTypeEnum.NOTICE, joinSql = "e.department_id in (#departmentIds)", whereInType = DataScopeWhereInTypeEnum.DEPARTMENT)
+ List queryUnreadByPage(Page page, @Param("employeeId") Long employeeId, @Param("sendStatus") Boolean sendStatus);
+
+
+ /**
+ * 获取
+ *
+ * @param page
+ * @param queryDTO
+ * @return
+ */
+ List queryReceiveByPage(Page page, @Param("queryDTO") NoticeReceiveQueryDTO queryDTO);
+
+ /**
+ * 详情
+ *
+ * @param id
+ * @return
+ */
+ NoticeDetailVO detail(@Param("id") Long id);
+
+ /**
+ * 根据id删除 逻辑删除
+ *
+ * @param id
+ * @param deletedFlag
+ */
+ void logicDeleteById(@Param("id") Long id, @Param("deletedFlag") Boolean deletedFlag);
+
+
+ /**
+ * 批量逻辑删除
+ *
+ * @param idList
+ * @param deletedFlag
+ * @return
+ */
+ void logicDeleteByIds(@Param("idList") List idList, @Param("deletedFlag") Boolean deletedFlag);
+
+ /**
+ * 获取消息总数
+ *
+ * @return
+ */
+ Integer noticeCount(@Param("sendStatus") Boolean sendStatus);
+
+
+ /**
+ * 获取已读消息数
+ *
+ * @param employeeIds
+ * @return
+ */
+ List readCount(@Param("employeeIds") List employeeIds);
+
+
+ /**
+ * 获取某人的未读消息数
+ *
+ * @param employeeId
+ * @param sendStatus
+ * @return
+ */
+ Integer noticeUnreadCount(@Param("employeeId") Long employeeId, @Param("sendStatus") Boolean sendStatus);
+
+}
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/business/notice/dao/NoticeReceiveRecordDao.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/dao/NoticeReceiveRecordDao.java
similarity index 73%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/business/notice/dao/NoticeReceiveRecordDao.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/dao/NoticeReceiveRecordDao.java
index 682e0d74..274b51a2 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/business/notice/dao/NoticeReceiveRecordDao.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/dao/NoticeReceiveRecordDao.java
@@ -1,7 +1,7 @@
-package net.lab1024.smartadmin.module.business.notice.dao;
+package net.lab1024.smartadmin.service.module.business.notice.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import net.lab1024.smartadmin.module.business.notice.domain.entity.NoticeReceiveRecordEntity;
+import net.lab1024.smartadmin.service.module.business.notice.domain.entity.NoticeReceiveRecordEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
@@ -11,12 +11,7 @@ import java.util.List;
/**
* [ ]
*
- * @author yandanyang
- * @version 1.0
- * @company 1024lab.net
- * @copyright (c) 2018 1024lab.netInc. All rights reserved.
- * @date 2019-07-11 16:19:48
- * @since JDK1.8
+ * @author 罗伊
*/
@Mapper
@Component
diff --git a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/business/notice/domain/dto/NoticeAddDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeAddDTO.java
similarity index 59%
rename from smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/business/notice/domain/dto/NoticeAddDTO.java
rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeAddDTO.java
index 572817d1..5d5759b2 100644
--- a/smart-admin-service/smart-admin-api/src/main/java/net/lab1024/smartadmin/module/business/notice/domain/dto/NoticeAddDTO.java
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeAddDTO.java
@@ -1,4 +1,4 @@
-package net.lab1024.smartadmin.module.business.notice.domain.dto;
+package net.lab1024.smartadmin.service.module.business.notice.domain.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -7,12 +7,7 @@ import org.hibernate.validator.constraints.Length;
/**
* [ ]
*
- * @author yandanyang
- * @version 1.0
- * @company 1024lab.net
- * @copyright (c) 2018 1024lab.netInc. All rights reserved.
- * @date 2019/3/27 0027 下午 12:27
- * @since JDK1.8
+ * @author 罗伊
*/
@Data
public class NoticeAddDTO {
@@ -25,4 +20,7 @@ public class NoticeAddDTO {
@Length(max = 5000)
private String content;
+ @ApiModelProperty(hidden = true)
+ private Long createId;
+
}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeQueryDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeQueryDTO.java
new file mode 100644
index 00000000..ceb96edc
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeQueryDTO.java
@@ -0,0 +1,29 @@
+package net.lab1024.smartadmin.service.module.business.notice.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import net.lab1024.smartadmin.service.common.domain.PageBaseDTO;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ */
+@Data
+public class NoticeQueryDTO extends PageBaseDTO {
+
+
+ @ApiModelProperty("开始日期")
+ private String startDate;
+
+ @ApiModelProperty("结束日期")
+ private String endDate;
+
+
+ @ApiModelProperty("消息标题")
+ private String title;
+
+ @ApiModelProperty(value = "是否删除", hidden = true)
+ private Boolean deletedFlag;
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeReadCountDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeReadCountDTO.java
new file mode 100644
index 00000000..3d7f33d4
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeReadCountDTO.java
@@ -0,0 +1,21 @@
+package net.lab1024.smartadmin.service.module.business.notice.domain.dto;
+
+import lombok.Data;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ */
+@Data
+public class NoticeReadCountDTO {
+ /**
+ * 员工id
+ */
+ private Long employeeId;
+ /**
+ * 已读消息数
+ */
+ private Integer readCount;
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeReceiveDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeReceiveDTO.java
new file mode 100644
index 00000000..c4ba2f84
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeReceiveDTO.java
@@ -0,0 +1,33 @@
+package net.lab1024.smartadmin.service.module.business.notice.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ */
+@Data
+public class NoticeReceiveDTO{
+
+ @ApiModelProperty("id")
+ private Long id;
+
+ @ApiModelProperty("消息标题")
+ private String title;
+
+
+ @ApiModelProperty("消息创建人")
+ private Long createUser;
+
+ @ApiModelProperty("消息创建人名称")
+ private String createUserName;
+
+ @ApiModelProperty("结束时间")
+ private LocalDateTime receiveTime;
+
+ private Boolean readStatus;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeReceiveQueryDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeReceiveQueryDTO.java
new file mode 100644
index 00000000..cf07cefe
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeReceiveQueryDTO.java
@@ -0,0 +1,20 @@
+package net.lab1024.smartadmin.service.module.business.notice.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ */
+@Data
+public class NoticeReceiveQueryDTO extends NoticeQueryDTO {
+
+ @ApiModelProperty(hidden = true)
+ private Long employeeId;
+
+ @ApiModelProperty(hidden = true)
+ private Boolean sendStatus;
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeUpdateDTO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeUpdateDTO.java
new file mode 100644
index 00000000..4c44c2d2
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/dto/NoticeUpdateDTO.java
@@ -0,0 +1,16 @@
+package net.lab1024.smartadmin.service.module.business.notice.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ */
+@Data
+public class NoticeUpdateDTO extends NoticeAddDTO {
+
+ @ApiModelProperty("id")
+ private Long id;
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/entity/NoticeEntity.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/entity/NoticeEntity.java
new file mode 100644
index 00000000..027767dc
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/entity/NoticeEntity.java
@@ -0,0 +1,58 @@
+package net.lab1024.smartadmin.service.module.business.notice.domain.entity;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ */
+@Data
+@TableName("t_notice")
+public class NoticeEntity {
+ /**
+ * 主键id
+ */
+ @TableId(type = IdType.AUTO)
+ private Long id;
+ /**
+ * 消息标题
+ */
+ private String title;
+
+ /**
+ * 消息内容
+ */
+ private String content;
+
+ /**
+ * 消息创建人
+ */
+ private Long createUser;
+
+ /**
+ * 发送状态
+ */
+ private Boolean sendStatus;
+
+ /**
+ * 删除状态
+ */
+ private Boolean deletedFlag;
+
+
+ /**
+ * 更新时间
+ */
+ private LocalDateTime updateTime;
+
+ /**
+ * 创建时间
+ */
+ private LocalDateTime createTime;
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/entity/NoticeReceiveRecordEntity.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/entity/NoticeReceiveRecordEntity.java
new file mode 100644
index 00000000..eac5fdf8
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/entity/NoticeReceiveRecordEntity.java
@@ -0,0 +1,45 @@
+package net.lab1024.smartadmin.service.module.business.notice.domain.entity;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ */
+@Data
+@TableName("t_notice_receive_record")
+public class NoticeReceiveRecordEntity{
+
+ /**
+ * 主键id
+ */
+ @TableId(type = IdType.AUTO)
+ private Long id;
+ /**
+ * 消息id
+ */
+ private Long noticeId;
+
+ /**
+ * 消息接收人
+ */
+ private Long employeeId;
+
+
+ /**
+ * 更新时间
+ */
+ private LocalDateTime updateTime;
+
+ /**
+ * 创建时间
+ */
+ private LocalDateTime createTime;
+
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/vo/NoticeDetailVO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/vo/NoticeDetailVO.java
new file mode 100644
index 00000000..8fb3d90f
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/vo/NoticeDetailVO.java
@@ -0,0 +1,23 @@
+package net.lab1024.smartadmin.service.module.business.notice.domain.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ */
+@Data
+public class NoticeDetailVO extends NoticeVO {
+
+
+ @ApiModelProperty("消息内容")
+ private String content;
+
+ @ApiModelProperty("更新时间")
+ private LocalDateTime updateTime;
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/vo/NoticeVO.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/vo/NoticeVO.java
new file mode 100644
index 00000000..e64d3e19
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/business/notice/domain/vo/NoticeVO.java
@@ -0,0 +1,34 @@
+package net.lab1024.smartadmin.service.module.business.notice.domain.vo;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ */
+@Data
+public class NoticeVO {
+
+ @ApiModelProperty("id")
+ private Long id;
+
+ @ApiModelProperty("消息标题")
+ private String title;
+
+
+ @ApiModelProperty("消息创建人")
+ private Long createUser;
+
+ private Integer sendStatus;
+
+ @ApiModelProperty("消息创建人名称")
+ private String createUserName;
+
+ @ApiModelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/beancache/cache/AbstractCaffeineCache.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/beancache/cache/AbstractCaffeineCache.java
new file mode 100644
index 00000000..383cf5a6
--- /dev/null
+++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/beancache/cache/AbstractCaffeineCache.java
@@ -0,0 +1,220 @@
+package net.lab1024.smartadmin.service.module.support.beancache.cache;
+
+import com.alibaba.fastjson.JSON;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.LoadingCache;
+import net.lab1024.smartadmin.service.module.support.beancache.domain.CacheData;
+import net.lab1024.smartadmin.service.module.support.beancache.key.CacheKey;
+import net.lab1024.smartadmin.service.module.support.beancache.key.CacheKeyBuilder;
+import net.lab1024.smartadmin.service.module.support.beancache.load.CacheLoadMethod;
+import net.lab1024.smartadmin.service.third.SmartApplicationContext;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.compress.utils.Lists;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * [ ]
+ *
+ * @author 罗伊
+ * @date 2021/4/14 15:12
+ */
+public abstract class AbstractCaffeineCache implements IBeanCache {
+
+ /**
+ * 获取缓存
+ * @return
+ */
+ @Override
+ public abstract LoadingCache getCache();
+
+ /**
+ * 移除某个缓存
+ * @param key
+ */
+ @Override
+ public void remove(String key) {
+ getCache().invalidate(key);
+ }
+
+ /**
+ * 清除所有
+ */
+ @Override
+ public void clear() {
+ getCache().invalidateAll();
+ }
+
+ /**
+ * 获取某个缓存对象
+ * @param key
+ * @return
+ */
+ @Override
+ public T get(String key) {
+ LoadingCache cache = getCache();
+ CacheData cacheData = cache.get(key);
+ if(cacheData == null){
+ return null;
+ }
+ if(cacheData.getExpireTime() == null){
+ return (T)cacheData.getData();
+ }
+ long expireTime = cacheData.getExpireTime();
+ long current = System.currentTimeMillis();
+ if(expireTime > current){
+ return (T)cacheData.getData();
+ }
+ //缓存过期 移除key 重新获取
+ cache.invalidate(key);
+ return (T)cache.get(key).getData();
+ }
+
+ /**
+ * 刷新某个缓存key-异步刷新
+ * @param key
+ */
+ @Override
+ public void refresh(String key){
+ LoadingCache cache = getCache();
+ cache.refresh(key);
+ }
+
+ /**
+ * 设置key->value
+ * @param key
+ * @param obj
+ */
+ @Override
+ public void put(String key, Object obj) {
+ CacheData cacheData = new CacheData();
+ cacheData.setData(obj);
+ getCache().put(key, cacheData);
+ }
+
+
+ @Override
+ public void put(String key, Object obj, long expireSecond) {
+ CacheData cacheData = new CacheData();
+ long expireTime = System.currentTimeMillis() + expireSecond * 1000;
+ cacheData.setExpireTime(expireTime);
+ cacheData.setData(obj);
+ getCache().put(key, cacheData);
+ }
+
+ /**
+ * 判断是否包含某个key
+ * @param key
+ * @return
+ */
+ @Override
+ public boolean containsKey(String key) {
+ ConcurrentMap concurrentMap = getCache().asMap();
+ return concurrentMap.containsKey(key);
+ }
+
+ /**
+ * 所有key集合
+ * @return
+ */
+ @Override
+ public Set keySet() {
+ ConcurrentMap concurrentMap = getCache().asMap();
+ return concurrentMap.keySet();
+ }
+
+ /**
+ * 移除某个模块的所有key
+ * @param module
+ */
+ @Override
+ public void removeByModule(String module) {
+ ConcurrentMap concurrentMap = getCache().asMap();
+ List removeKeys = Lists.newArrayList();
+ Set keySet = concurrentMap.keySet();
+ keySet.forEach(e -> {
+ CacheKeyBuilder cacheKeyBuilder = JSON.parseObject(e, CacheKeyBuilder.class);
+ if (cacheKeyBuilder.getCacheModule().equals(module)){
+ removeKeys.add(e);
+ }
+ });
+ if (CollectionUtils.isNotEmpty(removeKeys)) {
+ getCache().invalidateAll(removeKeys);
+ }
+ }
+
+ /**
+ * 移除某个模块 某个分组下的缓存
+ * @param module
+ * @param group
+ */
+ @Override
+ public void removeByModuleAndGroup(String module, String group){
+ ConcurrentMap concurrentMap = getCache().asMap();
+ List removeKeys = Lists.newArrayList();
+ Set keySet = concurrentMap.keySet();
+ keySet.forEach(e -> {
+ CacheKeyBuilder cacheKeyBuilder = JSON.parseObject(e, CacheKeyBuilder.class);
+ if (cacheKeyBuilder.getCacheModule().equals(module) && group.equals(cacheKeyBuilder.getGroup())){
+ removeKeys.add(e);
+ }
+ });
+ if (CollectionUtils.isNotEmpty(removeKeys)) {
+ getCache().invalidateAll(removeKeys);
+ }
+ }
+
+ /**
+ * 根据缓存个数和过期时间初始化缓存的方法
+ * @param expireDays
+ * @param maximumSize
+ * @param scanPath
+ * @return
+ */
+ public LoadingCache initCache(Integer expireDays, Integer maximumSize, String scanPath) {
+ //加载缓存方法
+ Map methodMap = cacheLoadFunction(scanPath);
+ //构建缓存对象
+ Caffeine