diff --git a/README.md b/README.md
index ea7c1c14..e850848d 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,28 @@
### **SmartAdmin**
-**SmartAdmin** 由 **河南·洛阳** [1024创新实验室](https://www.1024lab.net/) 坚持以 **「高质量代码」为核心,「简洁、高效、安全」**的中后台解决方案!
+**SmartAdmin** 由 **中国·洛阳** [1024创新实验室](https://www.1024lab.net/) 基于SpringBoot2/3+Sa-Token+Mybatis-Plus 和 Vue3+Ant Design Vue+Uni-App+Uni-UI,并以 **「高质量代码」为核心,「简洁、高效、安全」**的快速开发平台。
-**国内首个满足《网络安全》、《数据安全》、三级等保**, 支持登录限制、支持接口国产加解密、支持数据加解密等一系列安全措施的开源项目。
+**国内首个满足《网络安全-三级等保》、《数据安全》** 功能要求,支持登录限制、接口国产加解密、数据脱敏等一系列安全要求。
-**我们开源一套漂亮的代码和一套整洁的代码规范**,让大家在这浮躁的代码世界里感受到一股把代码写好的清流!同时又让开发者节省大量的时间,减少加班,快乐工作,保持谦逊,保持学习,**热爱代码,更热爱生活**
+前端提供 **JavaScript和TypeScript双版本**,后端提供 **Java8+SpringBoot2.X和Java17+SpringBoot3.X 双版本**。
+
+同时 **重磅开源** 开源六年来 **千余家企业验证过且正在使用** 的代码规范: **《高质量代码思想》、《Vue3规范》、《Java规范》** ,让大家在这浮躁的世界里感受到一股把代码写好的清流!同时又能节省大量时间,减少加班,快乐工作,保持谦逊,保持学习,**热爱代码,更热爱生活** !
### **技术体系**
-- 前端:Vue3 + Vite5 + Vue-Router + Pinia + Ant Design Vue 4.X
+- 前端:JavaScript/TypeScript + Vue3 + Vite5 + Pinia + Ant Design Vue 4.X
- 移动端:uniapp (vue3版本) + uni-ui + (同时支持APP、小程序、H5)
-- 后端:SpringBoot + Sa Token + Mybatis-plus + 多种数据库
+- 后端:Java8/17 + SpringBoot2/3 + Sa Token + Mybatis-plus + 多种数据库
- 电脑在线预览:[https://preview.smartadmin.vip](https://preview.smartadmin.vip)
-- 官方文档:[https://smartadmin.vip](https://smartadmin.vip)
+- 官方文档:[https://smartadmin.vip](https://smartadmin.vip)
- 移动端在线预览:[https://app.smartadmin.vip](https://app.smartadmin.vip/#/pages/login/login)
### **理念与思想**
-- 我们分享的不是徒劳无功的各种功能,而是必须有的功能,如:网络安全、数据变动记录、系统说明文档、版本更新记录、意见反馈、日志、心跳、单号生成器等等。
-- 我们分享的还有经过上百家公司验证过的前端、后端、vue3等代码规范,好的规范能让我们敲下的每行代码更铿锵有力!
+- 我们分享的不是徒劳无功的各种功能,而是必须有的功能,如:数据变动记录、系统说明文档、版本更新记录、意见反馈、日志、心跳、单号生成器等等。
+- 我们分享的还有经过上百家公司验证过的前端、后端、vue3等代码规范,好的规范能让我敲下的每行代码更铿锵有力!
- **我们推崇高质量的代码,身为开发,代码即利剑,键盘上一套行云流水,宛如侠客,事了拂衣去,深藏身与名。**
- **我们推崇团队的高度配合默契、互相帮助,从不加班,而不是一看到别人的代码就头皮发麻,留其 [996.ICU](https://baike.baidu.com/item/996.ICU) 加班。**
+- **我们主动思考,保持谦逊,保持学习,热爱代码,更热爱生活。**
+- **我们希望你,希望你能花费3分钟认真阅读下面的每一个点,让你感受从未有过的技术体验!**
### **功能亮点图**
@@ -47,7 +51,7 @@
### **功能亮点**
-- **安全体系**:满足国家三级等保要求,如密码加密、密码复杂度要求、登录错误次数锁定、登录超时退出等关键功能
+- **安全体系**:满足国家三级等保要求,如双因子登录、密码加密、密码复杂度要求、登录错误次数锁定、登录超时退出、数据脱敏等网络安全和数据安全功能
- **接口加解密**:支持请求参数和返回内容进行加解密操作,支持国产加密算法和其他国外加密算法
- **表格自定义列**:支持用户自定义列,并能将用户自定义列持久化到数据库
- **数据变更记录**:支持基于git diff插件的数据变更记录,查看数据变化更直观方便
@@ -56,7 +60,7 @@
- **日志、监控**:服务器心跳日志、登录日志、操作日志(IP、浏览器、操作系统等设备信息)
- **系统功能**:员工、部门、角色、权限、菜单、水印、文件管理、系统参数、数据字典、单号生成 等
- **代码生成**: 基于每个表的配置、在线预览代码、下载 等
-- **以上只是一些举例,更多灿若繁星的惊喜和细节,等待着你的发现!**:[SmartAdmin 业内独有功能亮点](https://smartadmin.vip/views/v3/base/FunctionFeature.html)
+- **以上只是一些举例,更多灿若繁星的惊喜和细节,等待着你的发现!**:[SmartAdmin 业内独有功能亮点](https://smartadmin.vip)
### **代码亮点**
@@ -74,12 +78,4 @@
- **【后端-四层架构】:** 四层架构(controller, service, manager, dao),为什么要有四层
- **【后端-多环境】:** maven多环境:开发、测试、预发布、生产 环境配置
- **【后端-系统钩子】:** smart-reload,为系统预留钩子,动态加载,在不重启程序前提下执行一些代码
-- 以上只是沧海一粟,更多的细节等待你的发现
-
-
-
-
-### **特别鸣谢**
-
-**特别感谢 Gitee 提供的开源代码平台**
-
+- 以上只是沧海一粟,更多的细节等待你的发现
diff --git a/smart-admin-api-java17-springboot3/pom.xml b/smart-admin-api-java17-springboot3/pom.xml
new file mode 100644
index 00000000..4d8ad346
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/pom.xml
@@ -0,0 +1,410 @@
+
+ 4.0.0
+
+ net.1024lab
+ sa-parent
+ 3.0.0
+ pom
+
+ sa-parent
+ SmartAdmin project
+
+
+ sa-base
+ sa-admin
+
+
+
+ 17
+ UTF-8
+ UTF-8
+ 3.3.1
+ 2.0.8
+ 3.5.7
+ 3.9.1
+ 4.4.0
+ 2.0.52
+ 1.2.23
+ 1.4.2
+ 20.0
+ 1.21
+ 0.9.11
+ 2.15.0
+ 3.12.0
+ 4.4
+ 1.13
+ 1.9
+ 2.12.0
+ 3.3.2
+ 5.2.4
+ 1.4
+ 1.11.842
+ 2.23.1
+ 5.8.29
+ 2.3
+ 0.9.1
+ 0.9.0
+ 3.1
+ 1.37.0
+ 2.7.0
+ 1.59
+ 2.13.4
+ 2.16.1
+ 1.2.0
+ 3.25.0
+ 2.2
+ 2.3.33
+ 1.18.1
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${springboot.version}
+ pom
+ import
+
+
+
+
+ com.baomidou
+ mybatis-plus-spring-boot3-starter
+ ${mybatis-plus.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+
+ p6spy
+ p6spy
+ ${p6spy.version}
+
+
+
+ com.github.xiaoymin
+ knife4j-openapi3-jakarta-spring-boot-starter
+ ${knife4j.version}
+
+
+
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+
+
+ com.alibaba
+ druid-spring-boot-3-starter
+ ${druid.version}
+
+
+
+ com.googlecode.concurrentlinkedhashmap
+ concurrentlinkedhashmap-lru
+ ${google-linkedhashmap.version}
+
+
+
+ com.google.guava
+ guava
+ ${google-guava.version}
+
+
+
+ eu.bitwalker
+ UserAgentUtils
+ ${user-agent-utils.version}
+
+
+
+ org.reflections
+ reflections
+ ${reflections.version}
+
+
+ guava
+ com.google.guava
+
+
+
+
+
+ commons-io
+ commons-io
+ ${commons-io.version}
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+ org.apache.commons
+ commons-collections4
+ ${commons-collections4.version}
+
+
+
+ commons-codec
+ commons-codec
+ ${commons-codec.version}
+
+
+
+ com.amazonaws
+ aws-java-sdk-s3
+ ${aws-java-sdk.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+
+ org.apache.commons
+ commons-text
+ ${commons-text.version}
+
+
+
+ cn.hutool
+ hutool-all
+ ${hutool.version}
+
+
+
+ io.jsonwebtoken
+ jjwt
+ ${jjwt.version}
+
+
+
+ com.auth0
+ jwks-rsa
+ ${jwks-rsa.version}
+
+
+
+
+ org.apache.velocity
+ velocity-engine-core
+ ${velocity-engine-core.version}
+
+
+ org.apache.velocity.tools
+ velocity-tools-generic
+ ${velocity-tools.version}
+
+
+
+
+
+ cn.dev33
+ sa-token-spring-boot3-starter
+ ${sa-token.version}
+
+
+
+
+ cn.dev33
+ sa-token-redis-jackson
+ ${sa-token.version}
+
+
+
+
+
+ org.lionsoul
+ ip2region
+ ${ip2region.version}
+
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+ ${bcprov.version}
+
+
+
+ com.alibaba
+ easyexcel
+ ${easy-excel.version}
+
+
+ poi-ooxml-schemas
+ org.apache.poi
+
+
+
+
+
+ org.apache.poi
+ poi
+ ${poi.version}
+
+
+
+ org.apache.poi
+ poi-ooxml
+ ${poi.version}
+
+
+
+ org.apache.poi
+ poi-scratchpad
+ ${poi.version}
+
+
+
+ org.apache.poi
+ ooxml-schemas
+ ${ooxml-schemas.version}
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ ${jackson-datatype-jsr310.version}
+
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+ ${jackson-dataformat-yaml.version}
+
+
+
+ net.1024lab
+ smartdb
+ ${smartdb.version}
+
+
+
+
+ org.redisson
+ redisson-spring-boot-starter
+ ${redisson.version}
+
+
+
+ org.yaml
+ snakeyaml
+ ${snakeyaml.version}
+
+
+
+ org.jsoup
+ jsoup
+ ${jsoup.version}
+
+
+
+ org.freemarker
+ freemarker
+ ${freemarker.version}
+
+
+
+
+
+
+
+ ${project.name}-${profiles.active}-${project.version}
+
+
+ false
+ src/main/resources
+
+ dev/*
+ test/*
+ pre/*
+ prod/*
+
+
+
+
+ src/main/resources/${profiles.active}
+ true
+
+ *.yaml
+
+
+
+
+ src/main/resources/${profiles.active}
+ false
+
+ *.*
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.13.0
+
+ -parameters
+ 17
+ 17
+ UTF-8
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${springboot.version}
+
+
+
+
+
+
+
+ dev
+
+ dev
+
+
+ true
+
+
+
+
+ test
+
+ test
+
+
+
+
+ pre
+
+ pre
+
+
+
+
+ prod
+
+ prod
+
+
+
+
+
\ No newline at end of file
diff --git a/smart-admin-api/sa-admin/pom.xml b/smart-admin-api-java17-springboot3/sa-admin/pom.xml
similarity index 100%
rename from smart-admin-api/sa-admin/pom.xml
rename to smart-admin-api-java17-springboot3/sa-admin/pom.xml
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/AdminApplication.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/AdminApplication.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/AdminApplication.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/AdminApplication.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/config/MvcConfig.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/config/MvcConfig.java
new file mode 100644
index 00000000..f5e88a5e
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/config/MvcConfig.java
@@ -0,0 +1,41 @@
+package net.lab1024.sa.admin.config;
+
+import jakarta.annotation.Resource;
+import net.lab1024.sa.admin.interceptor.AdminInterceptor;
+import net.lab1024.sa.base.config.SwaggerConfig;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * web相关配置
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2021-09-02 20:21:10
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Configuration
+public class MvcConfig implements WebMvcConfigurer {
+
+ @Resource
+ private AdminInterceptor adminInterceptor;
+
+
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(adminInterceptor)
+ .excludePathPatterns(SwaggerConfig.SWAGGER_WHITELIST)
+ .addPathPatterns("/**");
+ }
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
+ registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+ }
+
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/config/OperateLogAspectConfig.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/config/OperateLogAspectConfig.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/config/OperateLogAspectConfig.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/config/OperateLogAspectConfig.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminCacheConst.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminCacheConst.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminCacheConst.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminCacheConst.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminRedisKeyConst.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminRedisKeyConst.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminRedisKeyConst.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminRedisKeyConst.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminSwaggerTagConst.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminSwaggerTagConst.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminSwaggerTagConst.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminSwaggerTagConst.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/interceptor/AdminInterceptor.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/interceptor/AdminInterceptor.java
new file mode 100644
index 00000000..7205c5fe
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/interceptor/AdminInterceptor.java
@@ -0,0 +1,188 @@
+package net.lab1024.sa.admin.interceptor;
+
+import cn.dev33.satoken.annotation.SaIgnore;
+import cn.dev33.satoken.exception.SaTokenException;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.strategy.SaStrategy;
+import cn.hutool.core.util.StrUtil;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.sa.admin.module.system.login.domain.RequestEmployee;
+import net.lab1024.sa.admin.module.system.login.service.LoginService;
+import net.lab1024.sa.base.common.annoation.NoNeedLogin;
+import net.lab1024.sa.base.common.code.SystemErrorCode;
+import net.lab1024.sa.base.common.code.UserErrorCode;
+import net.lab1024.sa.base.common.constant.StringConst;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.domain.SystemEnvironment;
+import net.lab1024.sa.base.common.enumeration.SystemEnvironmentEnum;
+import net.lab1024.sa.base.common.enumeration.UserTypeEnum;
+import net.lab1024.sa.base.common.util.SmartRequestUtil;
+import net.lab1024.sa.base.common.util.SmartResponseUtil;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import java.lang.reflect.Method;
+
+/**
+ * admin 拦截器
+ *
+ * @Author 1024创新实验室-主任:卓大
+ * @Date 2023/7/26 20:20:33
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室,Since 2012
+ */
+
+@Component
+@Slf4j
+public class AdminInterceptor implements HandlerInterceptor {
+
+ @Resource
+ private LoginService loginService;
+
+ @Resource
+ private SystemEnvironment systemEnvironment;
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+
+ // OPTIONS请求直接return
+ if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
+ response.setStatus(HttpStatus.NO_CONTENT.value());
+ return false;
+ }
+
+ boolean isHandler = handler instanceof HandlerMethod;
+ if (!isHandler) {
+ return true;
+ }
+
+ try {
+ // --------------- 第一步: 根据token 获取用户 ---------------
+
+ String tokenValue = StpUtil.getTokenValue();
+ boolean debugNumberTokenFlag = isDevDebugNumberToken(tokenValue);
+
+ String loginId = null;
+ if (debugNumberTokenFlag) {
+ //开发、测试环境,且为数字的话,则表明为 调试临时用户,即需要调用 sa-token switch
+ loginId = UserTypeEnum.ADMIN_EMPLOYEE.getValue() + StringConst.COLON + tokenValue;
+ StpUtil.switchTo(loginId);
+ } else {
+ loginId = (String) StpUtil.getLoginIdByToken(tokenValue);
+ }
+
+ RequestEmployee requestEmployee = loginService.getLoginEmployee(loginId, request);
+
+ // --------------- 第二步: 校验 登录 ---------------
+
+ Method method = ((HandlerMethod) handler).getMethod();
+ NoNeedLogin noNeedLogin = ((HandlerMethod) handler).getMethodAnnotation(NoNeedLogin.class);
+ if (noNeedLogin != null) {
+ checkActiveTimeout(requestEmployee, debugNumberTokenFlag);
+ return true;
+ }
+
+ if (requestEmployee == null) {
+ SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID));
+ return false;
+ }
+
+ // 检测token 活跃频率
+ checkActiveTimeout(requestEmployee, debugNumberTokenFlag);
+
+
+ // --------------- 第三步: 校验 权限 ---------------
+
+ SmartRequestUtil.setRequestUser(requestEmployee);
+ if (SaStrategy.instance.isAnnotationPresent.apply(method, SaIgnore.class)) {
+ return true;
+ }
+
+ // 如果是超级管理员的话,不需要校验权限
+ if (requestEmployee.getAdministratorFlag()) {
+ return true;
+ }
+
+ SaStrategy.instance.checkMethodAnnotation.accept(method);
+
+ } catch (SaTokenException e) {
+ /*
+ * sa-token 异常状态码
+ * 具体请看: https://sa-token.cc/doc.html#/fun/exception-code
+ */
+ int code = e.getCode();
+ if (code == 11041 || code == 11051) {
+ SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.NO_PERMISSION));
+ } else if (code == 11016) {
+ SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_ACTIVE_TIMEOUT));
+ } else if (code >= 11011 && code <= 11015) {
+ SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID));
+ } else {
+ SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.PARAM_ERROR));
+ }
+ return false;
+ } catch (Throwable e) {
+ SmartResponseUtil.write(response, ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR));
+ log.error(e.getMessage(), e);
+ return false;
+ }
+
+ // 通过验证
+ return true;
+ }
+
+
+ /**
+ * 检测:token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结
+ */
+ private void checkActiveTimeout(RequestEmployee requestEmployee, boolean debugNumberTokenFlag) {
+
+ // 对于开发环境的 数字 debug token ,不需要检测活跃有效期
+ if (debugNumberTokenFlag) {
+ return;
+ }
+
+ // 用户不在线,也不用检测
+ if (requestEmployee == null) {
+ return;
+ }
+
+ StpUtil.checkActiveTimeout();
+ StpUtil.updateLastActiveToNow();
+ }
+
+
+ /**
+ * 是否为开发使用的 debug token
+ *
+ * @param token
+ * @return
+ */
+ private boolean isDevDebugNumberToken(String token) {
+ if (!StrUtil.isNumeric(token)) {
+ return false;
+ }
+ return systemEnvironment.getCurrentEnvironment() == SystemEnvironmentEnum.DEV
+ || systemEnvironment.getCurrentEnvironment() == SystemEnvironmentEnum.TEST;
+ }
+
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+ // 清除上下文
+ SmartRequestUtil.remove();
+ // 开发环境,关闭 sa token 的临时切换用户
+ if (systemEnvironment.getCurrentEnvironment() == SystemEnvironmentEnum.DEV) {
+ StpUtil.endSwitch();
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/listener/AdminStartupRunner.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/listener/AdminStartupRunner.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/listener/AdminStartupRunner.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/listener/AdminStartupRunner.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/constant/CategoryTypeEnum.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/constant/CategoryTypeEnum.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/constant/CategoryTypeEnum.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/constant/CategoryTypeEnum.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/controller/CategoryController.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/controller/CategoryController.java
new file mode 100644
index 00000000..2c7ff73a
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/controller/CategoryController.java
@@ -0,0 +1,69 @@
+package net.lab1024.sa.admin.module.business.category.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
+import net.lab1024.sa.admin.module.business.category.domain.form.CategoryAddForm;
+import net.lab1024.sa.admin.module.business.category.domain.form.CategoryTreeQueryForm;
+import net.lab1024.sa.admin.module.business.category.domain.form.CategoryUpdateForm;
+import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryTreeVO;
+import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryVO;
+import net.lab1024.sa.admin.module.business.category.service.CategoryService;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 类目
+ *
+ * @Author 1024创新实验室: 胡克
+ * @Date 2021/08/05 21:26:58
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@RestController
+@Tag(name = AdminSwaggerTagConst.Business.MANAGER_CATEGORY)
+public class CategoryController {
+
+ @Resource
+ private CategoryService categoryService;
+
+ @Operation(summary = "添加类目 @author 胡克")
+ @PostMapping("/category/add")
+ @SaCheckPermission("category:add")
+ public ResponseDTO add(@RequestBody @Valid CategoryAddForm addForm) {
+ return categoryService.add(addForm);
+ }
+
+ @Operation(summary = "更新类目 @author 胡克")
+ @PostMapping("/category/update")
+ @SaCheckPermission("category:update")
+ public ResponseDTO update(@RequestBody @Valid CategoryUpdateForm updateForm) {
+ return categoryService.update(updateForm);
+ }
+
+ @Operation(summary = "查询类目详情 @author 胡克")
+ @GetMapping("/category/{categoryId}")
+ public ResponseDTO queryDetail(@PathVariable Long categoryId) {
+ return categoryService.queryDetail(categoryId);
+ }
+
+ @Operation(summary = "查询类目层级树 @author 胡克")
+ @PostMapping("/category/tree")
+ @SaCheckPermission("category:tree")
+ public ResponseDTO> queryTree(@RequestBody @Valid CategoryTreeQueryForm queryForm) {
+ return categoryService.queryTree(queryForm);
+ }
+
+ @Operation(summary = "删除类目 @author 胡克")
+ @GetMapping("/category/delete/{categoryId}")
+ @SaCheckPermission("category:delete")
+ public ResponseDTO delete(@PathVariable Long categoryId) {
+ return categoryService.delete(categoryId);
+ }
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/dao/CategoryDao.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/dao/CategoryDao.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/dao/CategoryDao.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/dao/CategoryDao.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategoryBaseDTO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategoryBaseDTO.java
new file mode 100644
index 00000000..4849d606
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategoryBaseDTO.java
@@ -0,0 +1,43 @@
+package net.lab1024.sa.admin.module.business.category.domain.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum;
+import net.lab1024.sa.base.common.swagger.SchemaEnum;
+import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
+import org.hibernate.validator.constraints.Length;
+
+/**
+ * 类目 基础属性 DTO 类
+ *
+ * @author 胡克
+ * @date 2021/1/20 16:17
+ */
+@Data
+public class CategoryBaseDTO {
+
+ @Schema(description = "类目名称", required = true)
+ @NotBlank(message = "类目名称不能为空")
+ @Length(max = 20, message = "类目名称最多20字符")
+ private String categoryName;
+
+ @SchemaEnum(desc = "分类类型", value = CategoryTypeEnum.class)
+ @CheckEnum(value = CategoryTypeEnum.class, required = true, message = "分类错误")
+ private Integer categoryType;
+
+ @Schema(description = "父级类目id|可选")
+ private Long parentId;
+
+ @Schema(description = "排序|可选")
+ private Integer sort;
+
+ @Schema(description = "备注|可选")
+ @Length(max = 200, message = "备注最多200字符")
+ private String remark;
+
+ @Schema(description = "禁用状态")
+ @NotNull(message = "禁用状态不能为空")
+ private Boolean disabledFlag;
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategorySimpleDTO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategorySimpleDTO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategorySimpleDTO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategorySimpleDTO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/entity/CategoryEntity.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/entity/CategoryEntity.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/entity/CategoryEntity.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/entity/CategoryEntity.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryAddForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryAddForm.java
new file mode 100644
index 00000000..df2a169e
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryAddForm.java
@@ -0,0 +1,47 @@
+package net.lab1024.sa.admin.module.business.category.domain.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum;
+import net.lab1024.sa.base.common.swagger.SchemaEnum;
+import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
+import org.hibernate.validator.constraints.Length;
+
+/**
+ * 类目 添加
+ *
+ * @Author 1024创新实验室: 胡克
+ * @Date 2021/08/05 21:26:58
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class CategoryAddForm {
+
+ @Schema(description = "类目名称", required = true)
+ @NotBlank(message = "类目名称不能为空")
+ @Length(max = 20, message = "类目名称最多20字符")
+ private String categoryName;
+
+ @SchemaEnum(desc = "分类类型", value = CategoryTypeEnum.class)
+ @CheckEnum(value = CategoryTypeEnum.class, required = true, message = "分类错误")
+ private Integer categoryType;
+
+ @Schema(description = "父级类目id|可选")
+ private Long parentId;
+
+ @Schema(description = "排序|可选")
+ private Integer sort;
+
+ @Schema(description = "备注|可选")
+ @Length(max = 200, message = "备注最多200字符")
+ private String remark;
+
+ @Schema(description = "禁用状态")
+ @NotNull(message = "禁用状态不能为空")
+ private Boolean disabledFlag;
+
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryTreeQueryForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryTreeQueryForm.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryTreeQueryForm.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryTreeQueryForm.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryUpdateForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryUpdateForm.java
new file mode 100644
index 00000000..bfa44913
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryUpdateForm.java
@@ -0,0 +1,22 @@
+package net.lab1024.sa.admin.module.business.category.domain.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * 类目 更新
+ *
+ * @Author 1024创新实验室: 胡克
+ * @Date 2021/08/05 21:26:58
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class CategoryUpdateForm extends CategoryAddForm {
+
+ @Schema(description = "类目id")
+ @NotNull(message = "类目id不能为空")
+ private Long categoryId;
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryTreeVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryTreeVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryTreeVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryTreeVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryVO.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/manager/CategoryCacheManager.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/manager/CategoryCacheManager.java
new file mode 100644
index 00000000..72a2be63
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/manager/CategoryCacheManager.java
@@ -0,0 +1,113 @@
+package net.lab1024.sa.admin.module.business.category.manager;
+
+import com.google.common.collect.Lists;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.sa.admin.constant.AdminCacheConst;
+import net.lab1024.sa.admin.module.business.category.dao.CategoryDao;
+import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity;
+import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryTreeVO;
+import net.lab1024.sa.base.common.constant.StringConst;
+import net.lab1024.sa.base.common.util.SmartBeanUtil;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 类目 查询 缓存
+ *
+ * @Author 1024创新实验室: 胡克
+ * @Date 2021/08/05 21:26:58
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+@Slf4j
+public class CategoryCacheManager {
+
+
+ @Resource
+ private CategoryDao categoryDao;
+
+
+ /**
+ * 根据类目id 移除缓存
+ */
+ @CacheEvict(value = {AdminCacheConst.Category.CATEGORY_ENTITY, AdminCacheConst.Category.CATEGORY_SUB, AdminCacheConst.Category.CATEGORY_TREE}, allEntries = true)
+ public void removeCache() {
+ log.info("clear CATEGORY ,CATEGORY_SUB ,CATEGORY_TREE");
+ }
+
+ /**
+ * 查詢类目
+ *
+ */
+ @Cacheable(AdminCacheConst.Category.CATEGORY_ENTITY)
+ public CategoryEntity queryCategory(Long categoryId) {
+ return categoryDao.selectById(categoryId);
+ }
+
+ /**
+ * 查询类目 子级
+ *
+ */
+ @Cacheable(AdminCacheConst.Category.CATEGORY_SUB)
+ public List querySubCategory(Long categoryId) {
+ return categoryDao.queryByParentId(Lists.newArrayList(categoryId), false);
+ }
+
+
+ /**
+ * 查询类目 层级树
+ * 优先查询缓存
+ */
+ @Cacheable(AdminCacheConst.Category.CATEGORY_TREE)
+ public List queryCategoryTree(Long parentId, Integer categoryType) {
+ List allCategoryEntityList = categoryDao.queryByType(categoryType, false);
+
+ List categoryEntityList = allCategoryEntityList.stream().filter(e -> e.getParentId().equals(parentId)).collect(Collectors.toList());
+ List treeList = SmartBeanUtil.copyList(categoryEntityList, CategoryTreeVO.class);
+ treeList.forEach(e -> {
+ e.setLabel(e.getCategoryName());
+ e.setValue(e.getCategoryId());
+ e.setCategoryFullName(e.getCategoryName());
+ });
+ // 递归设置子类
+ this.queryAndSetSubCategory(treeList, allCategoryEntityList);
+ return treeList;
+ }
+
+ /**
+ * 递归查询设置类目子类
+ * 从缓存查询子类
+ *
+ */
+ private void queryAndSetSubCategory(List treeList, List allCategoryEntityList) {
+ if (CollectionUtils.isEmpty(treeList)) {
+ return;
+ }
+ List parentIdList = treeList.stream().map(CategoryTreeVO::getValue).collect(Collectors.toList());
+ List categoryEntityList = allCategoryEntityList.stream().filter(e -> parentIdList.contains(e.getParentId())).collect(Collectors.toList());
+ Map> categorySubMap = categoryEntityList.stream().collect(Collectors.groupingBy(CategoryEntity::getParentId));
+ 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() + StringConst.SEPARATOR_SLASH + item.getCategoryName());
+ });
+ // 递归查询
+ this.queryAndSetSubCategory(childrenVOList, allCategoryEntityList);
+ e.setChildren(childrenVOList);
+ });
+ }
+
+
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/service/CategoryQueryService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/service/CategoryQueryService.java
new file mode 100644
index 00000000..9def1521
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/service/CategoryQueryService.java
@@ -0,0 +1,188 @@
+package net.lab1024.sa.admin.module.business.category.service;
+
+import cn.hutool.core.util.StrUtil;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.sa.admin.module.business.category.domain.dto.CategorySimpleDTO;
+import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity;
+import net.lab1024.sa.admin.module.business.category.manager.CategoryCacheManager;
+import net.lab1024.sa.base.common.constant.StringConst;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 类目 查询 业务类
+ *
+ * @Author 1024创新实验室: 胡克
+ * @Date 2021/08/05 21:26:58
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+@Slf4j
+public class CategoryQueryService {
+
+ private static final Long DEFAULT_CATEGORY_PARENT_ID = 0L;
+
+ @Resource
+ private CategoryCacheManager categoryCacheManager;
+
+ /**
+ * 根据 id 查询未删除的类目
+ *
+ * @param categoryId
+ * @return 可能 null
+ */
+ public Optional queryCategory(Long categoryId) {
+ if (null == categoryId) {
+ return Optional.empty();
+ }
+ CategoryEntity entity = categoryCacheManager.queryCategory(categoryId);
+ if (null == entity || entity.getDeletedFlag()) {
+ return Optional.empty();
+ }
+ return Optional.of(entity);
+ }
+
+
+ /**
+ * 根据 类目id集合 查询未删除的类目集合
+ */
+ public Map queryCategoryList(List categoryIdList) {
+ if (CollectionUtils.isEmpty(categoryIdList)) {
+ return Collections.emptyMap();
+ }
+ categoryIdList = categoryIdList.stream().distinct().collect(Collectors.toList());
+ Map categoryEntityMap = Maps.newHashMap();
+ for (Long categoryId : categoryIdList) {
+ CategoryEntity categoryEntity = categoryCacheManager.queryCategory(categoryId);
+ if (categoryEntity != null) {
+ categoryEntityMap.put(categoryId, categoryEntity);
+ }
+ }
+ return categoryEntityMap;
+ }
+
+
+ /**
+ * 根据类目id 递归查询该id的所有子类id 递归查询
+ * 同时存入缓存
+ * 注意:查询出来的集合 不包含传递的父类参数
+ */
+ public List queryCategorySubId(List categoryIdList) {
+ if (CollectionUtils.isEmpty(categoryIdList)) {
+ return Collections.emptyList();
+ }
+ //所有子类
+ List categoryEntityList = Lists.newArrayList();
+ categoryIdList.forEach(e -> {
+ categoryEntityList.addAll(categoryCacheManager.querySubCategory(e));
+ });
+ Map> subTypeMap = categoryEntityList.stream().collect(Collectors.groupingBy(CategoryEntity::getCategoryId));
+ // 递归查询子类
+ 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;
+ }
+
+
+ /**
+ * 处理类目名称
+ */
+ 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 查询类目名称
+ */
+ public String queryCategoryName(Long categoryId) {
+ CategoryEntity categoryEntity = categoryCacheManager.queryCategory(categoryId);
+ if (null == categoryEntity || categoryEntity.getDeletedFlag()) {
+ return null;
+ }
+ return categoryEntity.getCategoryName();
+ }
+
+ /**
+ * 根据类目id 查询类目详情 包含类目全称 如:医考/医师资格/临床执业
+ */
+ public CategorySimpleDTO queryCategoryInfo(Long categoryId) {
+ CategoryEntity categoryEntity = categoryCacheManager.queryCategory(categoryId);
+ if (null == categoryEntity || categoryEntity.getDeletedFlag()) {
+ return null;
+ }
+ String fullName = this.queryFullName(categoryId);
+ // 返回DTO
+ CategorySimpleDTO categoryDTO = new CategorySimpleDTO();
+ categoryDTO.setCategoryId(categoryId);
+ categoryDTO.setCategoryName(categoryEntity.getCategoryName());
+ categoryDTO.setCategoryFullName(fullName);
+ categoryDTO.setParentId(categoryEntity.getParentId());
+ return categoryDTO;
+ }
+
+ /**
+ * 递归查询分类和所有父级类目
+ * ps:特别注意返回的集合中 包含自己
+ */
+ public List queryCategoryAndParent(Long categoryId) {
+ List parentCategoryList = Lists.newArrayList();
+ CategoryEntity categoryEntity = categoryCacheManager.queryCategory(categoryId);
+ if (null == categoryEntity || categoryEntity.getDeletedFlag()) {
+ return parentCategoryList;
+ }
+
+ // 父级始终放在第一位
+ parentCategoryList.add(0, categoryEntity);
+ Long parentId = categoryEntity.getParentId();
+ if (Objects.equals(DEFAULT_CATEGORY_PARENT_ID, parentId)) {
+ return parentCategoryList;
+ }
+ parentCategoryList.addAll(0, this.queryCategoryAndParent(parentId));
+ return parentCategoryList;
+ }
+
+ /**
+ * 查询 分类全称 如:医考/医师资格/临床执业
+ */
+ public String queryFullName(Long categoryId) {
+ List parentCategoryList = this.queryCategoryAndParent(categoryId);
+ // 拼接父级类目名称 斜杠分隔返回
+ List nameList = parentCategoryList.stream().map(CategoryEntity::getCategoryName).collect(Collectors.toList());
+ return StrUtil.join(StringConst.SEPARATOR_SLASH, nameList);
+ }
+
+ /**
+ * 查询 分类全称 如:医考/医师资格/临床执业
+ */
+ public Map queryFullName(List categoryIdList) {
+ if (CollectionUtils.isEmpty(categoryIdList)) {
+ return Maps.newHashMap();
+ }
+ // 循环内查询的缓存 还ok
+ return categoryIdList.stream().collect(Collectors.toMap(Function.identity(), this::queryFullName));
+ }
+
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/service/CategoryService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/service/CategoryService.java
new file mode 100644
index 00000000..130b685d
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/service/CategoryService.java
@@ -0,0 +1,206 @@
+package net.lab1024.sa.admin.module.business.category.service;
+
+import com.google.common.collect.Lists;
+import jakarta.annotation.Resource;
+import net.lab1024.sa.admin.module.business.category.dao.CategoryDao;
+import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity;
+import net.lab1024.sa.admin.module.business.category.domain.form.CategoryAddForm;
+import net.lab1024.sa.admin.module.business.category.domain.form.CategoryTreeQueryForm;
+import net.lab1024.sa.admin.module.business.category.domain.form.CategoryUpdateForm;
+import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryTreeVO;
+import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryVO;
+import net.lab1024.sa.admin.module.business.category.manager.CategoryCacheManager;
+import net.lab1024.sa.base.common.code.UserErrorCode;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.SmartBeanUtil;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * 类目
+ *
+ * @Author 1024创新实验室: 胡克
+ * @Date 2021/08/05 21:26:58
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+public class CategoryService {
+
+ @Resource
+ private CategoryDao categoryDao;
+
+ @Resource
+ private CategoryQueryService categoryQueryService;
+
+ @Resource
+ private CategoryCacheManager categoryCacheManager;
+
+ /**
+ * 添加类目
+ */
+ public ResponseDTO add(CategoryAddForm addForm) {
+ // 校验类目
+ CategoryEntity categoryEntity = SmartBeanUtil.copy(addForm, CategoryEntity.class);
+ ResponseDTO res = this.checkCategory(categoryEntity, false);
+ if (!res.getOk()) {
+ return res;
+ }
+ // 没有父类则使用默认父类
+ Long parentId = null == addForm.getParentId() ? NumberUtils.LONG_ZERO : addForm.getParentId();
+ categoryEntity.setParentId(parentId);
+ categoryEntity.setSort(null == addForm.getSort() ? 0 : addForm.getSort());
+ categoryEntity.setDeletedFlag(false);
+
+ // 保存数据
+ categoryDao.insert(categoryEntity);
+
+ // 更新缓存
+ categoryCacheManager.removeCache();
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 更新类目
+ * 不能更新父级类目
+ *
+ */
+ public ResponseDTO update(CategoryUpdateForm updateForm) {
+ // 校验类目
+ Long categoryId = updateForm.getCategoryId();
+ Optional optional = categoryQueryService.queryCategory(categoryId);
+ if (!optional.isPresent()) {
+ return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
+ }
+ CategoryEntity categoryEntity = SmartBeanUtil.copy(updateForm, CategoryEntity.class);
+
+ /*
+ 不更新类目类型
+ 不更新父类id
+ */
+ Integer categoryType = optional.get().getCategoryType();
+ categoryEntity.setCategoryType(categoryType);
+ categoryEntity.setParentId(optional.get().getParentId());
+
+ ResponseDTO responseDTO = this.checkCategory(categoryEntity, true);
+ if (!responseDTO.getOk()) {
+ return responseDTO;
+ }
+ categoryDao.updateById(categoryEntity);
+
+ // 更新缓存
+ categoryCacheManager.removeCache();
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 新增/更新 类目时的 校验
+ *
+ */
+ 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.userErrorParam("父级类目怎么和自己相同了");
+ }
+ if (!Objects.equals(parentId, NumberUtils.LONG_ZERO)) {
+ Optional optional = categoryQueryService.queryCategory(parentId);
+ if (!optional.isPresent()) {
+ return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST, "父级类目不存在~");
+ }
+
+ CategoryEntity parent = optional.get();
+ if (!Objects.equals(categoryType, parent.getCategoryType())) {
+ return ResponseDTO.userErrorParam("与父级类目类型不一致");
+ }
+ }
+
+ } else {
+ // 如果没有父类 使用默认父类
+ parentId = NumberUtils.LONG_ZERO;
+ }
+
+ // 校验同父类下 名称是否重复
+ 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.userErrorParam("同级下已存在相同类目~");
+ }
+ } else {
+ return ResponseDTO.userErrorParam("同级下已存在相同类目~");
+ }
+ }
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 查询 类目详情
+ *
+ */
+ public ResponseDTO queryDetail(Long categoryId) {
+ Optional optional = categoryQueryService.queryCategory(categoryId);
+ if (!optional.isPresent()) {
+ return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
+ }
+ CategoryVO adminVO = SmartBeanUtil.copy(optional.get(), CategoryVO.class);
+ return ResponseDTO.ok(adminVO);
+ }
+
+ /**
+ * 根据父级id 查询所有子类 返回层级树
+ * 如果父类id 为空 返回所有类目层级
+ *
+ */
+ public ResponseDTO> queryTree(CategoryTreeQueryForm queryForm) {
+ if (null == queryForm.getParentId()) {
+ if (null == queryForm.getCategoryType()) {
+ return ResponseDTO.userErrorParam("类目类型不能为空");
+ }
+ queryForm.setParentId(NumberUtils.LONG_ZERO);
+ }
+ List treeList = categoryCacheManager.queryCategoryTree(queryForm.getParentId(), queryForm.getCategoryType());
+ return ResponseDTO.ok(treeList);
+ }
+
+ /**
+ * 删除类目
+ * 如果有未删除的子类 则无法删除
+ *
+ */
+ public ResponseDTO delete(Long categoryId) {
+ Optional optional = categoryQueryService.queryCategory(categoryId);
+ if (!optional.isPresent()) {
+ return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
+ }
+
+ List categorySubId = categoryQueryService.queryCategorySubId(Lists.newArrayList(categoryId));
+ if (CollectionUtils.isNotEmpty(categorySubId)) {
+ return ResponseDTO.userErrorParam("请先删除子级类目");
+ }
+
+ // 更新数据
+ CategoryEntity categoryEntity = new CategoryEntity();
+ categoryEntity.setCategoryId(categoryId);
+ categoryEntity.setDeletedFlag(true);
+ categoryDao.updateById(categoryEntity);
+
+ // 更新缓存
+ categoryCacheManager.removeCache();
+ return ResponseDTO.ok();
+ }
+
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/constant/GoodsStatusEnum.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/constant/GoodsStatusEnum.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/constant/GoodsStatusEnum.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/constant/GoodsStatusEnum.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/controller/GoodsController.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/controller/GoodsController.java
new file mode 100644
index 00000000..42b69b09
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/controller/GoodsController.java
@@ -0,0 +1,94 @@
+package net.lab1024.sa.admin.module.business.goods.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
+import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsAddForm;
+import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsQueryForm;
+import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsUpdateForm;
+import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsExcelVO;
+import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsVO;
+import net.lab1024.sa.admin.module.business.goods.service.GoodsService;
+import net.lab1024.sa.base.common.domain.PageResult;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.domain.ValidateList;
+import net.lab1024.sa.base.common.util.SmartExcelUtil;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * 商品业务
+ *
+ * @Author 1024创新实验室: 胡克
+ * @Date 2021-10-25 20:26:54
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@RestController
+@Tag(name = AdminSwaggerTagConst.Business.MANAGER_GOODS)
+public class GoodsController {
+
+ @Resource
+ private GoodsService goodsService;
+
+ @Operation(summary = "分页查询 @author 胡克")
+ @PostMapping("/goods/query")
+ @SaCheckPermission("goods:query")
+ public ResponseDTO> query(@RequestBody @Valid GoodsQueryForm queryForm) {
+ return goodsService.query(queryForm);
+ }
+
+ @Operation(summary = "添加商品 @author 胡克")
+ @PostMapping("/goods/add")
+ @SaCheckPermission("goods:add")
+ public ResponseDTO add(@RequestBody @Valid GoodsAddForm addForm) {
+ return goodsService.add(addForm);
+ }
+
+ @Operation(summary = "更新商品 @author 胡克")
+ @PostMapping("/goods/update")
+ @SaCheckPermission("goods:update")
+ public ResponseDTO update(@RequestBody @Valid GoodsUpdateForm updateForm) {
+ return goodsService.update(updateForm);
+ }
+
+ @Operation(summary = "删除 @author 卓大")
+ @GetMapping("/goods/delete/{goodsId}")
+ @SaCheckPermission("goods:delete")
+ public ResponseDTO delete(@PathVariable Long goodsId) {
+ return goodsService.delete(goodsId);
+ }
+
+ @Operation(summary = "批量 @author 卓大")
+ @PostMapping("/goods/batchDelete")
+ @SaCheckPermission("goods:batchDelete")
+ public ResponseDTO batchDelete(@RequestBody @Valid ValidateList idList) {
+ return goodsService.batchDelete(idList);
+ }
+
+ // --------------- 导出和导入 -------------------
+
+ @Operation(summary = "导入 @author 卓大")
+ @PostMapping("/goods/importGoods")
+ @SaCheckPermission("goods:importGoods")
+ public ResponseDTO importGoods(@RequestParam MultipartFile file) {
+ return goodsService.importGoods(file);
+ }
+
+ @Operation(summary = "导出 @author 卓大")
+ @GetMapping("/goods/exportGoods")
+ @SaCheckPermission("goods:exportGoods")
+ public void exportGoods(HttpServletResponse response) throws IOException {
+ List goodsList = goodsService.getAllGoods();
+ SmartExcelUtil.exportExcel(response,"商品列表.xlsx","商品",GoodsExcelVO.class, goodsList);
+ }
+
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/dao/GoodsDao.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/dao/GoodsDao.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/dao/GoodsDao.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/dao/GoodsDao.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/entity/GoodsEntity.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/entity/GoodsEntity.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/entity/GoodsEntity.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/entity/GoodsEntity.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsAddForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsAddForm.java
new file mode 100644
index 00000000..02d27022
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsAddForm.java
@@ -0,0 +1,56 @@
+package net.lab1024.sa.admin.module.business.goods.domain.form;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum;
+import net.lab1024.sa.base.common.json.deserializer.DictValueVoDeserializer;
+import net.lab1024.sa.base.common.swagger.SchemaEnum;
+import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
+
+import java.math.BigDecimal;
+
+/**
+ * 商品 添加表单
+ *
+ * @Author 1024创新实验室: 胡克
+ * @Date 2021-10-25 20:26:54
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class GoodsAddForm {
+
+ @Schema(description = "商品分类")
+ @NotNull(message = "商品分类不能为空")
+ private Long categoryId;
+
+ @Schema(description = "商品名称")
+ @NotBlank(message = "商品名称不能为空")
+ private String goodsName;
+
+ @SchemaEnum(GoodsStatusEnum.class)
+ @CheckEnum(message = "商品状态错误", value = GoodsStatusEnum.class, required = true)
+ private Integer goodsStatus;
+
+ @Schema(description = "产地")
+ @NotBlank(message = "产地 不能为空 ")
+ @JsonDeserialize(using = DictValueVoDeserializer.class)
+ private String place;
+
+ @Schema(description = "商品价格")
+ @NotNull(message = "商品价格不能为空")
+ @DecimalMin(value = "0", message = "商品价格最低0")
+ private BigDecimal price;
+
+ @Schema(description = "上架状态")
+ @NotNull(message = "上架状态不能为空")
+ private Boolean shelvesFlag;
+
+ @Schema(description = "备注|可选")
+ private String remark;
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsImportForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsImportForm.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsImportForm.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsImportForm.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsQueryForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsQueryForm.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsQueryForm.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsQueryForm.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsUpdateForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsUpdateForm.java
new file mode 100644
index 00000000..46896535
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsUpdateForm.java
@@ -0,0 +1,22 @@
+package net.lab1024.sa.admin.module.business.goods.domain.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * 商品 更新表单
+ *
+ * @Author 1024创新实验室: 胡克
+ * @Date 2021-10-25 20:26:54
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class GoodsUpdateForm extends GoodsAddForm {
+
+ @Schema(description = "商品id")
+ @NotNull(message = "商品id不能为空")
+ private Long goodsId;
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsExcelVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsExcelVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsExcelVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsExcelVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsVO.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/service/GoodsService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/service/GoodsService.java
new file mode 100644
index 00000000..b9287196
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/service/GoodsService.java
@@ -0,0 +1,211 @@
+package net.lab1024.sa.admin.module.business.goods.service;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum;
+import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity;
+import net.lab1024.sa.admin.module.business.category.service.CategoryQueryService;
+import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum;
+import net.lab1024.sa.admin.module.business.goods.dao.GoodsDao;
+import net.lab1024.sa.admin.module.business.goods.domain.entity.GoodsEntity;
+import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsAddForm;
+import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsImportForm;
+import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsQueryForm;
+import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsUpdateForm;
+import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsExcelVO;
+import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsVO;
+import net.lab1024.sa.base.common.code.UserErrorCode;
+import net.lab1024.sa.base.common.domain.PageResult;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.exception.BusinessException;
+import net.lab1024.sa.base.common.util.SmartBeanUtil;
+import net.lab1024.sa.base.common.util.SmartEnumUtil;
+import net.lab1024.sa.base.common.util.SmartPageUtil;
+import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
+import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
+import net.lab1024.sa.base.module.support.dict.service.DictCacheService;
+import net.lab1024.sa.base.module.support.dict.service.DictService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 商品
+ *
+ * @Author 1024创新实验室: 胡克
+ * @Date 2021-10-25 20:26:54
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+@Slf4j
+public class GoodsService {
+
+ @Resource
+ private GoodsDao goodsDao;
+
+ @Resource
+ private CategoryQueryService categoryQueryService;
+
+ @Resource
+ private DataTracerService dataTracerService;
+
+ @Resource
+ private DictCacheService dictCacheService;
+
+ /**
+ * 添加商品
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO add(GoodsAddForm addForm) {
+ // 商品校验
+ ResponseDTO res = this.checkGoods(addForm);
+ if (!res.getOk()) {
+ return res;
+ }
+ GoodsEntity goodsEntity = SmartBeanUtil.copy(addForm, GoodsEntity.class);
+ goodsEntity.setDeletedFlag(Boolean.FALSE);
+ goodsDao.insert(goodsEntity);
+ dataTracerService.insert(goodsEntity.getGoodsId(), DataTracerTypeEnum.GOODS);
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 更新商品
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO update(GoodsUpdateForm updateForm) {
+ // 商品校验
+ ResponseDTO res = this.checkGoods(updateForm);
+ if (!res.getOk()) {
+ return res;
+ }
+ GoodsEntity originEntity = goodsDao.selectById(updateForm.getGoodsId());
+ GoodsEntity goodsEntity = SmartBeanUtil.copy(updateForm, GoodsEntity.class);
+ goodsDao.updateById(goodsEntity);
+ dataTracerService.update(updateForm.getGoodsId(), DataTracerTypeEnum.GOODS, originEntity, goodsEntity);
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 添加/更新 商品校验
+ */
+ private ResponseDTO checkGoods(GoodsAddForm addForm) {
+ // 校验类目id
+ Long categoryId = addForm.getCategoryId();
+ Optional optional = categoryQueryService.queryCategory(categoryId);
+ if (!optional.isPresent() || !CategoryTypeEnum.GOODS.equalsValue(optional.get().getCategoryType())) {
+ return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST, "商品类目不存在~");
+ }
+
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 删除
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO delete(Long goodsId) {
+ GoodsEntity goodsEntity = goodsDao.selectById(goodsId);
+ if (goodsEntity == null) {
+ return ResponseDTO.userErrorParam("商品不存在");
+ }
+
+ if (!goodsEntity.getGoodsStatus().equals(GoodsStatusEnum.SELL_OUT.getValue())) {
+ return ResponseDTO.userErrorParam("只有售罄的商品才可以删除");
+ }
+
+ batchDelete(Collections.singletonList(goodsId));
+ dataTracerService.batchDelete(Collections.singletonList(goodsId), DataTracerTypeEnum.GOODS);
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 批量删除
+ */
+ public ResponseDTO batchDelete(List goodsIdList) {
+ if (CollectionUtils.isEmpty(goodsIdList)) {
+ return ResponseDTO.ok();
+ }
+
+ goodsDao.batchUpdateDeleted(goodsIdList, Boolean.TRUE);
+ return ResponseDTO.ok();
+ }
+
+
+ /**
+ * 分页查询
+ */
+ public ResponseDTO> query(GoodsQueryForm queryForm) {
+ queryForm.setDeletedFlag(false);
+ Page> page = SmartPageUtil.convert2PageQuery(queryForm);
+ List list = goodsDao.query(page, queryForm);
+ PageResult pageResult = SmartPageUtil.convert2PageResult(page, list);
+ if (pageResult.getEmptyFlag()) {
+ return ResponseDTO.ok(pageResult);
+ }
+ // 查询分类名称
+ List categoryIdList = list.stream().map(GoodsVO::getCategoryId).distinct().collect(Collectors.toList());
+ Map categoryMap = categoryQueryService.queryCategoryList(categoryIdList);
+ list.forEach(e -> {
+ CategoryEntity categoryEntity = categoryMap.get(e.getCategoryId());
+ if (categoryEntity != null) {
+ e.setCategoryName(categoryEntity.getCategoryName());
+ }
+ });
+ return ResponseDTO.ok(pageResult);
+ }
+
+ /**
+ * 商品导入
+ *
+ * @param file 上传文件
+ * @return 结果
+ */
+ public ResponseDTO importGoods(MultipartFile file) {
+ List dataList;
+ try {
+ dataList = EasyExcel.read(file.getInputStream()).head(GoodsImportForm.class)
+ .sheet()
+ .doReadSync();
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ throw new BusinessException("数据格式存在问题,无法读取");
+ }
+
+ if (CollectionUtils.isEmpty(dataList)) {
+ return ResponseDTO.userErrorParam("数据为空");
+ }
+
+ return ResponseDTO.okMsg("成功导入" + dataList.size() + "条,具体数据为:" + JSON.toJSONString(dataList));
+ }
+
+ /**
+ * 商品导出
+ */
+ public List getAllGoods() {
+ List goodsEntityList = goodsDao.selectList(null);
+ return goodsEntityList.stream()
+ .map(e ->
+ GoodsExcelVO.builder()
+ .goodsStatus(SmartEnumUtil.getEnumDescByValue(e.getGoodsStatus(), GoodsStatusEnum.class))
+ .categoryName(categoryQueryService.queryCategoryName(e.getCategoryId()))
+ .place(Arrays.stream(e.getPlace().split(",")).map(code -> dictCacheService.selectValueNameByValueCode(code)).collect(Collectors.joining(",")))
+ .price(e.getPrice())
+ .goodsName(e.getGoodsName())
+ .remark(e.getRemark())
+ .build()
+ )
+ .collect(Collectors.toList());
+
+ }
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankController.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankController.java
new file mode 100644
index 00000000..f17cbd45
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankController.java
@@ -0,0 +1,74 @@
+package net.lab1024.sa.admin.module.business.oa.bank;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
+import net.lab1024.sa.admin.module.business.oa.bank.domain.BankCreateForm;
+import net.lab1024.sa.admin.module.business.oa.bank.domain.BankQueryForm;
+import net.lab1024.sa.admin.module.business.oa.bank.domain.BankUpdateForm;
+import net.lab1024.sa.admin.module.business.oa.bank.domain.BankVO;
+import net.lab1024.sa.base.common.domain.PageResult;
+import net.lab1024.sa.base.common.domain.RequestUser;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.SmartRequestUtil;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * OA办公-OA银行信息
+ *
+ * @Author 1024创新实验室:善逸
+ * @Date 2022/6/23 21:59:22
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@RestController
+@Tag(name = AdminSwaggerTagConst.Business.OA_BANK)
+public class BankController {
+
+ @Resource
+ private BankService bankService;
+
+ @Operation(summary = "分页查询银行信息 @author 善逸")
+ @PostMapping("/oa/bank/page/query")
+ public ResponseDTO> queryByPage(@RequestBody @Valid BankQueryForm queryForm) {
+ return bankService.queryByPage(queryForm);
+ }
+
+ @Operation(summary = "根据企业ID查询银行信息列表 @author 善逸")
+ @GetMapping("/oa/bank/query/list/{enterpriseId}")
+ public ResponseDTO> queryList(@PathVariable Long enterpriseId) {
+ return bankService.queryList(enterpriseId);
+ }
+
+ @Operation(summary = "查询银行信息详情 @author 善逸")
+ @GetMapping("/oa/bank/get/{bankId}")
+ public ResponseDTO getDetail(@PathVariable Long bankId) {
+ return bankService.getDetail(bankId);
+ }
+
+ @Operation(summary = "新建银行信息 @author 善逸")
+ @PostMapping("/oa/bank/create")
+ public ResponseDTO createBank(@RequestBody @Valid BankCreateForm createVO) {
+ RequestUser requestUser = SmartRequestUtil.getRequestUser();
+ createVO.setCreateUserId(requestUser.getUserId());
+ createVO.setCreateUserName(requestUser.getUserName());
+ return bankService.createBank(createVO);
+ }
+
+ @Operation(summary = "编辑银行信息 @author 善逸")
+ @PostMapping("/oa/bank/update")
+ public ResponseDTO updateBank(@RequestBody @Valid BankUpdateForm updateVO) {
+ return bankService.updateBank(updateVO);
+ }
+
+ @Operation(summary = "删除银行信息 @author 善逸")
+ @GetMapping("/oa/bank/delete/{bankId}")
+ public ResponseDTO deleteBank(@PathVariable Long bankId) {
+ return bankService.deleteBank(bankId);
+ }
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankDao.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankDao.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankDao.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankDao.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankService.java
new file mode 100644
index 00000000..177c50d3
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankService.java
@@ -0,0 +1,145 @@
+package net.lab1024.sa.admin.module.business.oa.bank;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.sa.admin.module.business.oa.bank.domain.*;
+import net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseDao;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEntity;
+import net.lab1024.sa.base.common.domain.PageResult;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.SmartBeanUtil;
+import net.lab1024.sa.base.common.util.SmartPageUtil;
+import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerConst;
+import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
+import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * OA办公-OA银行信息
+ *
+ * @Author 1024创新实验室:善逸
+ * @Date 2022/6/23 21:59:22
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+@Slf4j
+public class BankService {
+
+ @Resource
+ private BankDao bankDao;
+
+ @Resource
+ private EnterpriseDao enterpriseDao;
+
+ @Resource
+ private DataTracerService dataTracerService;
+
+ /**
+ * 分页查询银行信息
+ */
+ public ResponseDTO> queryByPage(BankQueryForm queryForm) {
+ queryForm.setDeletedFlag(Boolean.FALSE);
+ Page> page = SmartPageUtil.convert2PageQuery(queryForm);
+ List bankList = bankDao.queryPage(page, queryForm);
+ PageResult pageResult = SmartPageUtil.convert2PageResult(page, bankList);
+ return ResponseDTO.ok(pageResult);
+ }
+
+ /**
+ * 根据企业ID查询不分页的银行列表
+ */
+ public ResponseDTO> queryList(Long enterpriseId) {
+ BankQueryForm queryForm = new BankQueryForm();
+ queryForm.setEnterpriseId(enterpriseId);
+ queryForm.setDeletedFlag(Boolean.FALSE);
+ List bankList = bankDao.queryPage(null, queryForm);
+ return ResponseDTO.ok(bankList);
+ }
+
+ /**
+ * 查询银行信息详情
+ */
+ public ResponseDTO getDetail(Long bankId) {
+ // 校验银行信息是否存在
+ BankVO bankVO = bankDao.getDetail(bankId, Boolean.FALSE);
+ if (Objects.isNull(bankVO)) {
+ return ResponseDTO.userErrorParam("银行信息不存在");
+ }
+ return ResponseDTO.ok(bankVO);
+ }
+
+ /**
+ * 新建银行信息
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO createBank(BankCreateForm createVO) {
+ Long enterpriseId = createVO.getEnterpriseId();
+ // 校验企业是否存在
+ EnterpriseEntity enterpriseDetail = enterpriseDao.selectById(enterpriseId);
+ if (Objects.isNull(enterpriseDetail) || enterpriseDetail.getDeletedFlag()) {
+ return ResponseDTO.userErrorParam("企业不存在");
+ }
+ // 验证银行信息账号是否重复
+ BankEntity validateBank = bankDao.queryByAccountNumber(enterpriseId, createVO.getAccountNumber(), null, Boolean.FALSE);
+ if (Objects.nonNull(validateBank)) {
+ return ResponseDTO.userErrorParam("银行信息账号重复");
+ }
+ // 数据插入
+ BankEntity insertBank = SmartBeanUtil.copy(createVO, BankEntity.class);
+ bankDao.insert(insertBank);
+ dataTracerService.addTrace(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE, "新增银行:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(insertBank));
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 编辑银行信息
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO updateBank(BankUpdateForm updateVO) {
+ Long enterpriseId = updateVO.getEnterpriseId();
+ // 校验企业是否存在
+ EnterpriseEntity enterpriseDetail = enterpriseDao.selectById(enterpriseId);
+ if (Objects.isNull(enterpriseDetail) || enterpriseDetail.getDeletedFlag()) {
+ return ResponseDTO.userErrorParam("企业不存在");
+ }
+ Long bankId = updateVO.getBankId();
+ // 校验银行信息是否存在
+ BankEntity bankDetail = bankDao.selectById(bankId);
+ if (Objects.isNull(bankDetail) || bankDetail.getDeletedFlag()) {
+ return ResponseDTO.userErrorParam("银行信息不存在");
+ }
+ // 验证银行信息账号是否重复
+ BankEntity validateBank = bankDao.queryByAccountNumber(updateVO.getEnterpriseId(), updateVO.getAccountNumber(), bankId, Boolean.FALSE);
+ if (Objects.nonNull(validateBank)) {
+ return ResponseDTO.userErrorParam("银行信息账号重复");
+ }
+ // 数据编辑
+ BankEntity updateBank = SmartBeanUtil.copy(updateVO, BankEntity.class);
+ bankDao.updateById(updateBank);
+ dataTracerService.addTrace(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE, "更新银行:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(bankDetail, updateBank));
+ return ResponseDTO.ok();
+ }
+
+
+ /**
+ * 删除银行信息
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO deleteBank(Long bankId) {
+ // 校验银行信息是否存在
+ BankEntity bankDetail = bankDao.selectById(bankId);
+ if (Objects.isNull(bankDetail) || bankDetail.getDeletedFlag()) {
+ return ResponseDTO.userErrorParam("银行信息不存在");
+ }
+ bankDao.deleteBank(bankId, Boolean.TRUE);
+ dataTracerService.addTrace(bankDetail.getEnterpriseId(), DataTracerTypeEnum.OA_ENTERPRISE, "删除银行:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(bankDetail));
+ return ResponseDTO.ok();
+ }
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankCreateForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankCreateForm.java
new file mode 100644
index 00000000..53980852
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankCreateForm.java
@@ -0,0 +1,57 @@
+package net.lab1024.sa.admin.module.business.oa.bank.domain;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+/**
+ * OA办公-银行信息新建
+ *
+ * @Author 1024创新实验室:善逸
+ * @Date 2022/6/23 21:59:22
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class BankCreateForm {
+
+ @Schema(description = "开户银行")
+ @NotBlank(message = "开户银行不能为空")
+ @Length(max = 200, message = "开户银行最多200字符")
+ private String bankName;
+
+ @Schema(description = "账户名称")
+ @NotBlank(message = "账户名称不能为空")
+ @Length(max = 200, message = "账户名称最多200字符")
+ private String accountName;
+
+ @Schema(description = "账号")
+ @NotBlank(message = "账号不能为空")
+ @Length(max = 200, message = "账号最多200字符")
+ private String accountNumber;
+
+ @Schema(description = "备注")
+ @Length(max = 500, message = "备注最多500字符")
+ private String remark;
+
+ @Schema(description = "是否对公")
+ @NotNull(message = "是否对公不能为空")
+ private Boolean businessFlag;
+
+ @Schema(description = "企业")
+ @NotNull(message = "企业不能为空")
+ private Long enterpriseId;
+
+ @Schema(description = "禁用状态")
+ @NotNull(message = "禁用状态不能为空")
+ private Boolean disabledFlag;
+
+ @Schema(hidden = true)
+ private Long createUserId;
+
+ @Schema(hidden = true)
+ private String createUserName;
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankEntity.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankEntity.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankEntity.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankEntity.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankQueryForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankQueryForm.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankQueryForm.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankQueryForm.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankUpdateForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankUpdateForm.java
new file mode 100644
index 00000000..e77d8277
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankUpdateForm.java
@@ -0,0 +1,22 @@
+package net.lab1024.sa.admin.module.business.oa.bank.domain;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * OA办公-银行信息更新
+ *
+ * @Author 1024创新实验室:善逸
+ * @Date 2022/6/23 21:59:22
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class BankUpdateForm extends BankCreateForm {
+
+ @Schema(description = "银行信息ID")
+ @NotNull(message = "银行信息ID不能为空")
+ private Long bankId;
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankVO.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseController.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseController.java
new file mode 100644
index 00000000..ad904791
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseController.java
@@ -0,0 +1,134 @@
+package net.lab1024.sa.admin.module.business.oa.enterprise;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.form.*;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseEmployeeVO;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseExcelVO;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO;
+import net.lab1024.sa.admin.util.AdminRequestUtil;
+import net.lab1024.sa.base.common.domain.PageResult;
+import net.lab1024.sa.base.common.domain.RequestUser;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.*;
+import net.lab1024.sa.base.module.support.operatelog.annotation.OperateLog;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 企业
+ *
+ * @Author 1024创新实验室: 开云
+ * @Date 2022/7/28 20:37:15
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Slf4j
+@RestController
+@Tag(name = AdminSwaggerTagConst.Business.OA_ENTERPRISE)
+@OperateLog
+public class EnterpriseController {
+
+ @Resource
+ private EnterpriseService enterpriseService;
+
+ @Operation(summary = "分页查询企业模块 @author 开云")
+ @PostMapping("/oa/enterprise/page/query")
+ @SaCheckPermission("oa:enterprise:query")
+ public ResponseDTO> queryByPage(@RequestBody @Valid EnterpriseQueryForm queryForm) {
+ return enterpriseService.queryByPage(queryForm);
+ }
+
+ @Operation(summary = "导出企业信息 @author 卓大")
+ @PostMapping("/oa/enterprise/exportExcel")
+ public void exportExcel(@RequestBody @Valid EnterpriseQueryForm queryForm, HttpServletResponse response) throws IOException {
+ List data = enterpriseService.getExcelExportData(queryForm);
+ if (CollectionUtils.isEmpty(data)) {
+ SmartResponseUtil.write(response, ResponseDTO.userErrorParam("暂无数据"));
+ return;
+ }
+
+ String watermark = AdminRequestUtil.getRequestUser().getActualName();
+ watermark += SmartLocalDateUtil.format(LocalDateTime.now(), SmartDateFormatterEnum.YMD_HMS);
+
+ SmartExcelUtil.exportExcelWithWatermark(response,"企业基本信息.xlsx","企业信息",EnterpriseExcelVO.class,data,watermark);
+
+ }
+
+ @Operation(summary = "查询企业详情 @author 开云")
+ @GetMapping("/oa/enterprise/get/{enterpriseId}")
+ @SaCheckPermission("oa:enterprise:detail")
+ public ResponseDTO getDetail(@PathVariable Long enterpriseId) {
+ return ResponseDTO.ok(enterpriseService.getDetail(enterpriseId));
+ }
+
+ @Operation(summary = "新建企业 @author 开云")
+ @PostMapping("/oa/enterprise/create")
+ @SaCheckPermission("oa:enterprise:add")
+ public ResponseDTO createEnterprise(@RequestBody @Valid EnterpriseCreateForm createVO) {
+ RequestUser requestUser = SmartRequestUtil.getRequestUser();
+ createVO.setCreateUserId(requestUser.getUserId());
+ createVO.setCreateUserName(requestUser.getUserName());
+ return enterpriseService.createEnterprise(createVO);
+ }
+
+ @Operation(summary = "编辑企业 @author 开云")
+ @PostMapping("/oa/enterprise/update")
+ @SaCheckPermission("oa:enterprise:update")
+ public ResponseDTO updateEnterprise(@RequestBody @Valid EnterpriseUpdateForm updateVO) {
+ return enterpriseService.updateEnterprise(updateVO);
+ }
+
+ @Operation(summary = "删除企业 @author 开云")
+ @GetMapping("/oa/enterprise/delete/{enterpriseId}")
+ @SaCheckPermission("oa:enterprise:delete")
+ public ResponseDTO deleteEnterprise(@PathVariable Long enterpriseId) {
+ return enterpriseService.deleteEnterprise(enterpriseId);
+ }
+
+ @Operation(summary = "按照类型查询企业 @author 开云")
+ @GetMapping("/oa/enterprise/query/list")
+ public ResponseDTO> queryList(@RequestParam(value = "type", required = false) Integer type) {
+ return enterpriseService.queryList(type);
+ }
+
+
+ @Operation(summary = "企业添加员工 @author 罗伊")
+ @PostMapping("/oa/enterprise/employee/add")
+ @SaCheckPermission("oa:enterprise:addEmployee")
+ public ResponseDTO addEmployee(@RequestBody @Valid EnterpriseEmployeeForm enterpriseEmployeeForm) {
+ return enterpriseService.addEmployee(enterpriseEmployeeForm);
+ }
+
+ @Operation(summary = "查询企业全部员工 @author 罗伊")
+ @PostMapping("/oa/enterprise/employee/list")
+ public ResponseDTO> employeeList(@RequestBody @Valid List enterpriseIdList) {
+ return ResponseDTO.ok(enterpriseService.employeeList(enterpriseIdList));
+ }
+
+ @Operation(summary = "分页查询企业员工 @author 卓大")
+ @PostMapping("/oa/enterprise/employee/queryPage")
+ public ResponseDTO> queryPageEmployeeList(@RequestBody @Valid EnterpriseEmployeeQueryForm queryForm) {
+ return ResponseDTO.ok(enterpriseService.queryPageEmployeeList(queryForm));
+ }
+
+
+ @Operation(summary = "企业删除员工 @author 罗伊")
+ @PostMapping("/oa/enterprise/employee/delete")
+ @SaCheckPermission("oa:enterprise:deleteEmployee")
+ public ResponseDTO deleteEmployee(@RequestBody @Valid EnterpriseEmployeeForm enterpriseEmployeeForm) {
+ return enterpriseService.deleteEmployee(enterpriseEmployeeForm);
+ }
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseEmployeeManager.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseEmployeeManager.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseEmployeeManager.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseEmployeeManager.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseService.java
new file mode 100644
index 00000000..5ea17e6c
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseService.java
@@ -0,0 +1,238 @@
+package net.lab1024.sa.admin.module.business.oa.enterprise;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.google.common.collect.Lists;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseDao;
+import net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseEmployeeDao;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEmployeeEntity;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEntity;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.form.*;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseEmployeeVO;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseExcelVO;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO;
+import net.lab1024.sa.admin.module.system.department.service.DepartmentService;
+import net.lab1024.sa.base.common.code.UserErrorCode;
+import net.lab1024.sa.base.common.domain.PageResult;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.SmartBeanUtil;
+import net.lab1024.sa.base.common.util.SmartPageUtil;
+import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
+import net.lab1024.sa.base.module.support.datatracer.domain.form.DataTracerForm;
+import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * 企业
+ *
+ * @Author 1024创新实验室: 开云
+ * @Date 2022/7/28 20:37:15
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+@Slf4j
+public class EnterpriseService {
+
+ @Resource
+ private EnterpriseDao enterpriseDao;
+
+ @Resource
+ private EnterpriseEmployeeDao enterpriseEmployeeDao;
+
+ @Resource
+ private EnterpriseEmployeeManager enterpriseEmployeeManager;
+
+ @Resource
+ private DataTracerService dataTracerService;
+
+ @Resource
+ private DepartmentService departmentService;
+
+ /**
+ * 分页查询企业模块
+ *
+ */
+ public ResponseDTO> queryByPage(EnterpriseQueryForm queryForm) {
+ queryForm.setDeletedFlag(Boolean.FALSE);
+ Page> page = SmartPageUtil.convert2PageQuery(queryForm);
+ List enterpriseList = enterpriseDao.queryPage(page, queryForm);
+ PageResult pageResult = SmartPageUtil.convert2PageResult(page, enterpriseList);
+ return ResponseDTO.ok(pageResult);
+ }
+
+ /**
+ * 获取导出数据
+ */
+ public List getExcelExportData(EnterpriseQueryForm queryForm) {
+ queryForm.setDeletedFlag(false);
+ return enterpriseDao.selectExcelExportData(queryForm);
+ }
+
+ /**
+ * 查询企业详情
+ *
+ */
+ public EnterpriseVO getDetail(Long enterpriseId) {
+ return enterpriseDao.getDetail(enterpriseId, Boolean.FALSE);
+ }
+
+ /**
+ * 新建企业
+ *
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO createEnterprise(EnterpriseCreateForm createVO) {
+ // 验证企业名称是否重复
+ EnterpriseEntity validateEnterprise = enterpriseDao.queryByEnterpriseName(createVO.getEnterpriseName(), null, Boolean.FALSE);
+ if (Objects.nonNull(validateEnterprise)) {
+ return ResponseDTO.userErrorParam("企业名称重复");
+ }
+ // 数据插入
+ EnterpriseEntity insertEnterprise = SmartBeanUtil.copy(createVO, EnterpriseEntity.class);
+ enterpriseDao.insert(insertEnterprise);
+ dataTracerService.insert(insertEnterprise.getEnterpriseId(), DataTracerTypeEnum.OA_ENTERPRISE);
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 编辑企业
+ *
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO updateEnterprise(EnterpriseUpdateForm updateVO) {
+ Long enterpriseId = updateVO.getEnterpriseId();
+ // 校验企业是否存在
+ EnterpriseEntity enterpriseDetail = enterpriseDao.selectById(enterpriseId);
+ if (Objects.isNull(enterpriseDetail) || enterpriseDetail.getDeletedFlag()) {
+ return ResponseDTO.userErrorParam("企业不存在");
+ }
+ // 验证企业名称是否重复
+ EnterpriseEntity validateEnterprise = enterpriseDao.queryByEnterpriseName(updateVO.getEnterpriseName(), enterpriseId, Boolean.FALSE);
+ if (Objects.nonNull(validateEnterprise)) {
+ return ResponseDTO.userErrorParam("企业名称重复");
+ }
+ // 数据编辑
+ EnterpriseEntity updateEntity = SmartBeanUtil.copy(enterpriseDetail, EnterpriseEntity.class);
+ SmartBeanUtil.copyProperties(updateVO, updateEntity);
+ enterpriseDao.updateById(updateEntity);
+
+ //变更记录
+ DataTracerForm dataTracerForm = DataTracerForm.builder()
+ .dataId(updateVO.getEnterpriseId())
+ .type(DataTracerTypeEnum.OA_ENTERPRISE)
+ .content("修改企业信息")
+ .diffOld(dataTracerService.getChangeContent(enterpriseDetail))
+ .diffNew(dataTracerService.getChangeContent(updateEntity))
+ .build();
+
+ dataTracerService.addTrace(dataTracerForm);
+ return ResponseDTO.ok();
+ }
+
+
+ /**
+ * 删除企业
+ *
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO deleteEnterprise(Long enterpriseId) {
+ // 校验企业是否存在
+ EnterpriseEntity enterpriseDetail = enterpriseDao.selectById(enterpriseId);
+ if (Objects.isNull(enterpriseDetail) || enterpriseDetail.getDeletedFlag()) {
+ return ResponseDTO.userErrorParam("企业不存在");
+ }
+ enterpriseDao.deleteEnterprise(enterpriseId, Boolean.TRUE);
+ dataTracerService.delete(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE);
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 企业列表查询
+ */
+ public ResponseDTO> queryList(Integer type) {
+ List enterpriseList = enterpriseDao.queryList(type, Boolean.FALSE, Boolean.FALSE);
+ return ResponseDTO.ok(enterpriseList);
+ }
+
+ //----------------------------------------- 以下为员工相关--------------------------------------------
+
+ /**
+ * 企业添加员工
+ *
+ */
+ public synchronized ResponseDTO addEmployee(EnterpriseEmployeeForm enterpriseEmployeeForm) {
+ Long enterpriseId = enterpriseEmployeeForm.getEnterpriseId();
+ EnterpriseEntity enterpriseEntity = enterpriseDao.selectById(enterpriseId);
+ if (enterpriseEntity == null || enterpriseEntity.getDeletedFlag()) {
+ return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
+ }
+ //过滤掉已存在的员工
+ List waitAddEmployeeIdList = enterpriseEmployeeForm.getEmployeeIdList();
+ List enterpriseEmployeeEntityList = enterpriseEmployeeDao.selectByEnterpriseAndEmployeeIdList(enterpriseId, waitAddEmployeeIdList);
+ if (CollectionUtils.isNotEmpty(enterpriseEmployeeEntityList)) {
+ List existEmployeeIdList = enterpriseEmployeeEntityList.stream().map(EnterpriseEmployeeEntity::getEmployeeId).collect(Collectors.toList());
+ waitAddEmployeeIdList = waitAddEmployeeIdList.stream().filter(e -> !existEmployeeIdList.contains(e)).collect(Collectors.toList());
+ }
+ if (CollectionUtils.isEmpty(waitAddEmployeeIdList)) {
+ return ResponseDTO.ok();
+ }
+ List batchAddList = Lists.newArrayList();
+ for (Long employeeId : waitAddEmployeeIdList) {
+ EnterpriseEmployeeEntity enterpriseEmployeeEntity = new EnterpriseEmployeeEntity();
+ enterpriseEmployeeEntity.setEnterpriseId(enterpriseId);
+ enterpriseEmployeeEntity.setEmployeeId(employeeId);
+ batchAddList.add(enterpriseEmployeeEntity);
+ }
+ enterpriseEmployeeManager.saveBatch(batchAddList);
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 企业删除员工
+ *
+ */
+ public synchronized ResponseDTO deleteEmployee(EnterpriseEmployeeForm enterpriseEmployeeForm) {
+ Long enterpriseId = enterpriseEmployeeForm.getEnterpriseId();
+ EnterpriseEntity enterpriseEntity = enterpriseDao.selectById(enterpriseId);
+ if (enterpriseEntity == null || enterpriseEntity.getDeletedFlag()) {
+ return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
+ }
+ List waitDeleteEmployeeIdList = enterpriseEmployeeForm.getEmployeeIdList();
+ enterpriseEmployeeDao.deleteByEnterpriseAndEmployeeIdList(enterpriseId, waitDeleteEmployeeIdList);
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 企业下员工列表
+ *
+ */
+ public List employeeList(List enterpriseIdList) {
+ if (CollectionUtils.isEmpty(enterpriseIdList)) {
+ return Lists.newArrayList();
+ }
+ return enterpriseEmployeeDao.selectByEnterpriseIdList(enterpriseIdList);
+ }
+
+ /**
+ * 分页查询企业员工
+ *
+ */
+ public PageResult queryPageEmployeeList(EnterpriseEmployeeQueryForm queryForm) {
+ Page> page = SmartPageUtil.convert2PageQuery(queryForm);
+ List enterpriseEmployeeVOList = enterpriseEmployeeDao.queryPageEmployeeList(page, queryForm);
+ for (EnterpriseEmployeeVO enterpriseEmployeeVO : enterpriseEmployeeVOList) {
+ enterpriseEmployeeVO.setDepartmentName(departmentService.getDepartmentPath(enterpriseEmployeeVO.getDepartmentId()));
+ }
+ return SmartPageUtil.convert2PageResult(page, enterpriseEmployeeVOList);
+ }
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/constant/EnterpriseTypeEnum.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/constant/EnterpriseTypeEnum.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/constant/EnterpriseTypeEnum.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/constant/EnterpriseTypeEnum.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseDao.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseDao.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseDao.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseDao.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseEmployeeDao.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseEmployeeDao.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseEmployeeDao.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseEmployeeDao.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEmployeeEntity.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEmployeeEntity.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEmployeeEntity.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEmployeeEntity.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEntity.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEntity.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEntity.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEntity.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseCreateForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseCreateForm.java
new file mode 100644
index 00000000..02ff7507
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseCreateForm.java
@@ -0,0 +1,100 @@
+package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Pattern;
+import lombok.Data;
+import net.lab1024.sa.admin.module.business.oa.enterprise.constant.EnterpriseTypeEnum;
+import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer;
+import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer;
+import net.lab1024.sa.base.common.swagger.SchemaEnum;
+import net.lab1024.sa.base.common.util.SmartVerificationUtil;
+import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
+import org.hibernate.validator.constraints.Length;
+
+/**
+ * OA企业模块创建
+ *
+ * @Author 1024创新实验室: 开云
+ * @Date 2022/7/28 20:37:15
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class EnterpriseCreateForm {
+
+ @Schema(description = "企业名称")
+ @NotBlank(message = "企业名称不能为空")
+ @Length(max = 200, message = "企业名称最多200字符")
+ private String enterpriseName;
+
+ @Schema(description = "企业logo")
+ @JsonSerialize(using = FileKeyVoSerializer.class)
+ @JsonDeserialize(using = FileKeyVoDeserializer.class)
+ private String enterpriseLogo;
+
+ @Schema(description = "统一社会信用代码")
+ @NotBlank(message = "统一社会信用代码不能为空")
+ @Length(max = 200, message = "统一社会信用代码最多200字符")
+ private String unifiedSocialCreditCode;
+
+ @Schema(description = "联系人")
+ @NotBlank(message = "联系人不能为空")
+ @Length(max = 100, message = "联系人最多100字符")
+ private String contact;
+
+ @Schema(description = "联系人电话")
+ @NotBlank(message = "联系人电话不能为空")
+ @Pattern(regexp = SmartVerificationUtil.PHONE_REGEXP, message = "手机号格式不正确")
+ private String contactPhone;
+
+ @SchemaEnum(desc = "类型", value = EnterpriseTypeEnum.class)
+ @CheckEnum(message = "类型不正确", value = EnterpriseTypeEnum.class)
+ private Integer type;
+
+ @Schema(description = "邮箱")
+ @Pattern(regexp = SmartVerificationUtil.EMAIL, message = "邮箱格式不正确")
+ private String email;
+
+ @Schema(description = "省份")
+ private Integer province;
+
+ @Schema(description = "省份名称")
+ private String provinceName;
+
+ @Schema(description = "城市")
+ private Integer city;
+
+ @Schema(description = "城市名称")
+ private String cityName;
+
+ @Schema(description = "区县")
+ private Integer district;
+
+ @Schema(description = "区县名称")
+ private String districtName;
+
+ @Schema(description = "详细地址")
+ @Length(max = 500, message = "详细地址最多500字符")
+ private String address;
+
+ @Schema(description = "营业执照")
+ @JsonSerialize(using = FileKeyVoSerializer.class)
+ @JsonDeserialize(using = FileKeyVoDeserializer.class)
+ private String businessLicense;
+
+ @Schema(description = "禁用状态")
+ @NotNull(message = "禁用状态不能为空")
+ private Boolean disabledFlag;
+
+ @Schema(description = "创建人", hidden = true)
+ private Long createUserId;
+
+ @Schema(description = "创建人", hidden = true)
+ private String createUserName;
+
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseEmployeeForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseEmployeeForm.java
new file mode 100644
index 00000000..ce74d4ee
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseEmployeeForm.java
@@ -0,0 +1,29 @@
+package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 企业员工
+ *
+ * @Author 1024创新实验室: 罗伊
+ * @Date 2022/7/28 20:37:15
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class EnterpriseEmployeeForm {
+
+ @Schema(description = "企业id")
+ @NotNull(message = "企业id不能为空")
+ private Long enterpriseId;
+
+ @Schema(description = "员工信息id")
+ @NotEmpty(message = "员工信息id不能为空")
+ private List employeeIdList;
+}
\ No newline at end of file
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseEmployeeQueryForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseEmployeeQueryForm.java
new file mode 100644
index 00000000..eba6b985
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseEmployeeQueryForm.java
@@ -0,0 +1,32 @@
+package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import net.lab1024.sa.base.common.domain.PageParam;
+import org.hibernate.validator.constraints.Length;
+
+/**
+ * 查询企业员工
+ *
+ * @Author 1024创新实验室: 开云
+ * @Date 2021-12-20 21:06:49
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class EnterpriseEmployeeQueryForm extends PageParam {
+
+ @Schema(description = "搜索词")
+ @Length(max = 20, message = "搜索词最多20字符")
+ private String keyword;
+
+ @Schema(description = "公司Id")
+ @NotNull(message = "公司id 不能为空")
+ private Long enterpriseId;
+
+ @Schema(description = "删除标识", hidden = true)
+ private Boolean deletedFlag;
+
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseQueryForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseQueryForm.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseQueryForm.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseQueryForm.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseUpdateForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseUpdateForm.java
new file mode 100644
index 00000000..f2978d2d
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseUpdateForm.java
@@ -0,0 +1,22 @@
+package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * OA企业模块编辑
+ *
+ * @Author 1024创新实验室: 开云
+ * @Date 2022/7/28 20:37:15
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class EnterpriseUpdateForm extends EnterpriseCreateForm {
+
+ @Schema(description = "企业ID")
+ @NotNull(message = "企业ID不能为空")
+ private Long enterpriseId;
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseEmployeeVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseEmployeeVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseEmployeeVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseEmployeeVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseExcelVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseExcelVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseExcelVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseExcelVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseListVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseListVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseListVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseListVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseVO.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceController.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceController.java
new file mode 100644
index 00000000..52b5ea50
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceController.java
@@ -0,0 +1,80 @@
+package net.lab1024.sa.admin.module.business.oa.invoice;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
+import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceAddForm;
+import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceQueryForm;
+import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceUpdateForm;
+import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceVO;
+import net.lab1024.sa.base.common.domain.PageResult;
+import net.lab1024.sa.base.common.domain.RequestUser;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.SmartRequestUtil;
+import net.lab1024.sa.base.module.support.operatelog.annotation.OperateLog;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * OA发票信息
+ *
+ * @Author 1024创新实验室: 善逸
+ * @Date 2022-06-23 19:32:59
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Slf4j
+@RestController
+@Tag(name = AdminSwaggerTagConst.Business.OA_INVOICE)
+public class InvoiceController {
+
+ @Resource
+ private InvoiceService invoiceService;
+
+ @Operation(summary = "分页查询发票信息 @author 善逸")
+ @PostMapping("/oa/invoice/page/query")
+ public ResponseDTO> queryByPage(@RequestBody @Valid InvoiceQueryForm queryForm) {
+ return invoiceService.queryByPage(queryForm);
+ }
+
+ @Operation(summary = "查询发票信息详情 @author 善逸")
+ @GetMapping("/oa/invoice/get/{invoiceId}")
+ public ResponseDTO getDetail(@PathVariable Long invoiceId) {
+ return invoiceService.getDetail(invoiceId);
+ }
+
+ @Operation(summary = "新建发票信息 @author 善逸")
+ @PostMapping("/oa/invoice/create")
+ public ResponseDTO createInvoice(@RequestBody @Valid InvoiceAddForm createVO) {
+ RequestUser requestUser = SmartRequestUtil.getRequestUser();
+ createVO.setCreateUserId(requestUser.getUserId());
+ createVO.setCreateUserName(requestUser.getUserName());
+ return invoiceService.createInvoice(createVO);
+ }
+
+ @Operation(summary = "编辑发票信息 @author 善逸")
+ @PostMapping("/oa/invoice/update")
+ @OperateLog
+ public ResponseDTO updateInvoice(@RequestBody @Valid InvoiceUpdateForm updateVO) {
+ return invoiceService.updateInvoice(updateVO);
+ }
+
+ @Operation(summary = "删除发票信息 @author 善逸")
+ @GetMapping("/invoice/delete/{invoiceId}")
+ public ResponseDTO deleteInvoice(@PathVariable Long invoiceId) {
+ return invoiceService.deleteInvoice(invoiceId);
+ }
+
+ @Operation(summary = "查询列表 @author lidoudou")
+ @GetMapping("/oa/invoice/query/list/{enterpriseId}")
+ public ResponseDTO> queryList(@PathVariable Long enterpriseId) {
+ return invoiceService.queryList(enterpriseId);
+ }
+
+
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceDao.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceDao.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceDao.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceDao.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceService.java
new file mode 100644
index 00000000..dda73c3a
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceService.java
@@ -0,0 +1,143 @@
+package net.lab1024.sa.admin.module.business.oa.invoice;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.sa.admin.module.business.oa.enterprise.EnterpriseService;
+import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO;
+import net.lab1024.sa.admin.module.business.oa.invoice.domain.*;
+import net.lab1024.sa.base.common.domain.PageResult;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.SmartBeanUtil;
+import net.lab1024.sa.base.common.util.SmartPageUtil;
+import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerConst;
+import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
+import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * OA发票信息
+ *
+ * @Author 1024创新实验室: 善逸
+ * @Date 2022-06-23 19:32:59
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+@Slf4j
+public class InvoiceService {
+
+ @Resource
+ private InvoiceDao invoiceDao;
+
+ @Resource
+ private EnterpriseService enterpriseService;
+
+ @Resource
+ private DataTracerService dataTracerService;
+
+ /**
+ * 分页查询发票信息
+ */
+ public ResponseDTO> queryByPage(InvoiceQueryForm queryForm) {
+ queryForm.setDeletedFlag(Boolean.FALSE);
+ Page> page = SmartPageUtil.convert2PageQuery(queryForm);
+ List invoiceList = invoiceDao.queryPage(page, queryForm);
+ PageResult pageResult = SmartPageUtil.convert2PageResult(page, invoiceList);
+ return ResponseDTO.ok(pageResult);
+ }
+
+ public ResponseDTO> queryList(Long enterpriseId) {
+ InvoiceQueryForm queryForm = new InvoiceQueryForm();
+ queryForm.setDeletedFlag(Boolean.FALSE);
+ queryForm.setDisabledFlag(Boolean.FALSE);
+ queryForm.setEnterpriseId(enterpriseId);
+ List invoiceList = invoiceDao.queryPage(null, queryForm);
+ return ResponseDTO.ok(invoiceList);
+ }
+
+ /**
+ * 查询发票信息详情
+ */
+ public ResponseDTO getDetail(Long invoiceId) {
+ // 校验发票信息是否存在
+ InvoiceVO invoiceVO = invoiceDao.getDetail(invoiceId, Boolean.FALSE);
+ if (Objects.isNull(invoiceVO)) {
+ return ResponseDTO.userErrorParam("发票信息不存在");
+ }
+ return ResponseDTO.ok(invoiceVO);
+ }
+
+ /**
+ * 新建发票信息
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO createInvoice(InvoiceAddForm createVO) {
+ Long enterpriseId = createVO.getEnterpriseId();
+ // 校验企业是否存在
+ EnterpriseVO enterpriseVO = enterpriseService.getDetail(enterpriseId);
+ if (Objects.isNull(enterpriseVO)) {
+ return ResponseDTO.userErrorParam("企业不存在");
+ }
+ // 验证发票信息账号是否重复
+ InvoiceEntity validateInvoice = invoiceDao.queryByAccountNumber(enterpriseId, createVO.getAccountNumber(), null, Boolean.FALSE);
+ if (Objects.nonNull(validateInvoice)) {
+ return ResponseDTO.userErrorParam("发票信息账号重复");
+ }
+ // 数据插入
+ InvoiceEntity insertInvoice = SmartBeanUtil.copy(createVO, InvoiceEntity.class);
+ invoiceDao.insert(insertInvoice);
+ dataTracerService.addTrace(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE, "新增发票:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(insertInvoice));
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 编辑发票信息
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO updateInvoice(InvoiceUpdateForm updateVO) {
+ Long enterpriseId = updateVO.getEnterpriseId();
+ // 校验企业是否存在
+ EnterpriseVO enterpriseVO = enterpriseService.getDetail(enterpriseId);
+ if (Objects.isNull(enterpriseVO)) {
+ return ResponseDTO.userErrorParam("企业不存在");
+ }
+ Long invoiceId = updateVO.getInvoiceId();
+ // 校验发票信息是否存在
+ InvoiceEntity invoiceDetail = invoiceDao.selectById(invoiceId);
+ if (Objects.isNull(invoiceDetail) || invoiceDetail.getDeletedFlag()) {
+ return ResponseDTO.userErrorParam("发票信息不存在");
+ }
+ // 验证发票信息账号是否重复
+ InvoiceEntity validateInvoice = invoiceDao.queryByAccountNumber(updateVO.getEnterpriseId(), updateVO.getAccountNumber(), invoiceId, Boolean.FALSE);
+ if (Objects.nonNull(validateInvoice)) {
+ return ResponseDTO.userErrorParam("发票信息账号重复");
+ }
+ // 数据编辑
+ InvoiceEntity updateInvoice = SmartBeanUtil.copy(updateVO, InvoiceEntity.class);
+ invoiceDao.updateById(updateInvoice);
+ dataTracerService.addTrace(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE, "更新发票:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(invoiceDetail, updateInvoice));
+ return ResponseDTO.ok();
+ }
+
+
+ /**
+ * 删除发票信息
+ */
+ @Transactional(rollbackFor = Exception.class)
+ public ResponseDTO deleteInvoice(Long invoiceId) {
+ // 校验发票信息是否存在
+ InvoiceEntity invoiceDetail = invoiceDao.selectById(invoiceId);
+ if (Objects.isNull(invoiceDetail) || invoiceDetail.getDeletedFlag()) {
+ return ResponseDTO.userErrorParam("发票信息不存在");
+ }
+ invoiceDao.deleteInvoice(invoiceId, Boolean.TRUE);
+ dataTracerService.addTrace(invoiceDetail.getEnterpriseId(), DataTracerTypeEnum.OA_ENTERPRISE, "删除发票:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(invoiceDetail));
+ return ResponseDTO.ok();
+ }
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceAddForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceAddForm.java
new file mode 100644
index 00000000..136178a8
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceAddForm.java
@@ -0,0 +1,58 @@
+package net.lab1024.sa.admin.module.business.oa.invoice.domain;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+/**
+ * OA发票信息新建
+ *
+ * @Author 1024创新实验室: 善逸
+ * @Date 2022-06-23 19:32:59
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class InvoiceAddForm {
+
+ @Schema(description = "开票抬头")
+ @NotBlank(message = "开票抬头不能为空")
+ @Length(max = 200, message = "开票抬头最多200字符")
+ private String invoiceHeads;
+
+ @Schema(description = "纳税人识别号")
+ @NotBlank(message = "纳税人识别号不能为空")
+ @Length(max = 200, message = "纳税人识别号最多200字符")
+ private String taxpayerIdentificationNumber;
+
+ @Schema(description = "银行账户")
+ @NotBlank(message = "银行账户不能为空")
+ @Length(max = 200, message = "银行账户最多200字符")
+ private String accountNumber;
+
+ @Schema(description = "开户行")
+ @NotBlank(message = "开户行不能为空")
+ @Length(max = 200, message = "开户行最多200字符")
+ private String bankName;
+
+ @Schema(description = "启用状态")
+ @NotNull(message = "启用状态不能为空")
+ private Boolean disabledFlag;
+
+ @Schema(description = "备注")
+ @Length(max = 500, message = "备注最多500字符")
+ private String remark;
+
+ @Schema(description = "企业")
+ @NotNull(message = "企业不能为空")
+ private Long enterpriseId;
+
+ @Schema(description = "创建人", hidden = true)
+ private Long createUserId;
+
+ @Schema(description = "创建人名称", hidden = true)
+ private String createUserName;
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceEntity.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceEntity.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceEntity.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceEntity.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceQueryForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceQueryForm.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceQueryForm.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceQueryForm.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceUpdateForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceUpdateForm.java
new file mode 100644
index 00000000..a8c6d6c1
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceUpdateForm.java
@@ -0,0 +1,22 @@
+package net.lab1024.sa.admin.module.business.oa.invoice.domain;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * OA发票信息编辑
+ *
+ * @Author 1024创新实验室: 善逸
+ * @Date 2022-06-23 19:32:59
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class InvoiceUpdateForm extends InvoiceAddForm {
+
+ @Schema(description = "发票信息ID")
+ @NotNull(message = "发票信息ID不能为空")
+ private Long invoiceId;
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/constant/NoticeVisibleRangeDataTypeEnum.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/constant/NoticeVisibleRangeDataTypeEnum.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/constant/NoticeVisibleRangeDataTypeEnum.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/constant/NoticeVisibleRangeDataTypeEnum.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/controller/NoticeController.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/controller/NoticeController.java
new file mode 100644
index 00000000..78fb7bd4
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/controller/NoticeController.java
@@ -0,0 +1,140 @@
+package net.lab1024.sa.admin.module.business.oa.notice.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.extra.servlet.JakartaServletUtil;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.validation.Valid;
+import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.form.*;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.*;
+import net.lab1024.sa.admin.module.business.oa.notice.service.NoticeEmployeeService;
+import net.lab1024.sa.admin.module.business.oa.notice.service.NoticeService;
+import net.lab1024.sa.admin.module.business.oa.notice.service.NoticeTypeService;
+import net.lab1024.sa.base.common.domain.PageResult;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.SmartRequestUtil;
+import net.lab1024.sa.base.module.support.operatelog.annotation.OperateLog;
+import net.lab1024.sa.base.module.support.repeatsubmit.annoation.RepeatSubmit;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 公告、通知、新闻等等
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-08-12 21:40:39
+ * @Wechat 卓大1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Tag(name = AdminSwaggerTagConst.Business.OA_NOTICE)
+@RestController
+@OperateLog
+public class NoticeController {
+
+ @Resource
+ private NoticeService noticeService;
+
+ @Resource
+ private NoticeTypeService noticeTypeService;
+
+ @Resource
+ private NoticeEmployeeService noticeEmployeeService;
+
+ // --------------------- 通知公告类型 -------------------------
+
+ @Operation(summary = "通知公告类型-获取全部 @author 卓大")
+ @GetMapping("/oa/noticeType/getAll")
+ public ResponseDTO> getAll() {
+ return ResponseDTO.ok(noticeTypeService.getAll());
+ }
+
+ @Operation(summary = "通知公告类型-添加 @author 卓大")
+ @GetMapping("/oa/noticeType/add/{name}")
+ public ResponseDTO add(@PathVariable String name) {
+ return noticeTypeService.add(name);
+ }
+
+ @Operation(summary = "通知公告类型-修改 @author 卓大")
+ @GetMapping("/oa/noticeType/update/{noticeTypeId}/{name}")
+ public ResponseDTO update(@PathVariable Long noticeTypeId, @PathVariable String name) {
+ return noticeTypeService.update(noticeTypeId, name);
+ }
+
+ @Operation(summary = "通知公告类型-删除 @author 卓大")
+ @GetMapping("/oa/noticeType/delete/{noticeTypeId}")
+ public ResponseDTO deleteNoticeType(@PathVariable Long noticeTypeId) {
+ return noticeTypeService.delete(noticeTypeId);
+ }
+
+ // --------------------- 【管理】通知公告-------------------------
+
+
+ @Operation(summary = "【管理】通知公告-分页查询 @author 卓大")
+ @PostMapping("/oa/notice/query")
+ @SaCheckPermission("oa:notice:query")
+ public ResponseDTO> query(@RequestBody @Valid NoticeQueryForm queryForm) {
+ return ResponseDTO.ok(noticeService.query(queryForm));
+ }
+
+ @Operation(summary = "【管理】通知公告-添加 @author 卓大")
+ @PostMapping("/oa/notice/add")
+ @RepeatSubmit
+ @SaCheckPermission("oa:notice:add")
+ public ResponseDTO add(@RequestBody @Valid NoticeAddForm addForm) {
+ addForm.setCreateUserId(SmartRequestUtil.getRequestUserId());
+ return noticeService.add(addForm);
+ }
+
+ @Operation(summary = "【管理】通知公告-更新 @author 卓大")
+ @PostMapping("/oa/notice/update")
+ @RepeatSubmit
+ @SaCheckPermission("oa:notice:update")
+ public ResponseDTO update(@RequestBody @Valid NoticeUpdateForm updateForm) {
+ return noticeService.update(updateForm);
+ }
+
+ @Operation(summary = "【管理】通知公告-更新详情 @author 卓大")
+ @GetMapping("/oa/notice/getUpdateVO/{noticeId}")
+ @SaCheckPermission("oa:notice:update")
+ public ResponseDTO getUpdateFormVO(@PathVariable Long noticeId) {
+ return ResponseDTO.ok(noticeService.getUpdateFormVO(noticeId));
+ }
+
+ @Operation(summary = "【管理】通知公告-删除 @author 卓大")
+ @GetMapping("/oa/notice/delete/{noticeId}")
+ @SaCheckPermission("oa:notice:delete")
+ public ResponseDTO delete(@PathVariable Long noticeId) {
+ return noticeService.delete(noticeId);
+ }
+
+ // --------------------- 【员工】查看 通知公告 -------------------------
+
+
+ @Operation(summary = "【员工】通知公告-查看详情 @author 卓大")
+ @GetMapping("/oa/notice/employee/view/{noticeId}")
+ public ResponseDTO view(@PathVariable Long noticeId, HttpServletRequest request) {
+ return noticeEmployeeService.view(
+ SmartRequestUtil.getRequestUserId(),
+ noticeId,
+ JakartaServletUtil.getClientIP(request),
+ request.getHeader("User-Agent")
+ );
+ }
+
+ @Operation(summary = "【员工】通知公告-查询全部 @author 卓大")
+ @PostMapping("/oa/notice/employee/query")
+ public ResponseDTO> queryEmployeeNotice(@RequestBody @Valid NoticeEmployeeQueryForm noticeEmployeeQueryForm) {
+ return noticeEmployeeService.queryList(SmartRequestUtil.getRequestUserId(), noticeEmployeeQueryForm);
+ }
+
+ @Operation(summary = "【员工】通知公告-查询 查看记录 @author 卓大")
+ @PostMapping("/oa/notice/employee/queryViewRecord")
+ public ResponseDTO> queryViewRecord(@RequestBody @Valid NoticeViewRecordQueryForm noticeViewRecordQueryForm) {
+ return ResponseDTO.ok(noticeEmployeeService.queryViewRecord(noticeViewRecordQueryForm));
+ }
+}
\ No newline at end of file
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeDao.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeDao.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeDao.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeDao.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeTypeDao.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeTypeDao.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeTypeDao.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeTypeDao.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeEntity.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeEntity.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeEntity.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeEntity.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeTypeEntity.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeTypeEntity.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeTypeEntity.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeTypeEntity.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeAddForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeAddForm.java
new file mode 100644
index 00000000..1bd1fe37
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeAddForm.java
@@ -0,0 +1,78 @@
+package net.lab1024.sa.admin.module.business.oa.notice.domain.form;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer;
+import org.hibernate.validator.constraints.Length;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 通知公告 添加表单
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-08-12 21:40:39
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class NoticeAddForm {
+
+ @Schema(description = "标题")
+ @NotBlank(message = "标题不能为空")
+ @Length(max = 200, message = "标题最多200字符")
+ private String title;
+
+ @Schema(description = "分类")
+ @NotNull(message = "分类不能为空")
+ private Long noticeTypeId;
+
+ @Schema(description = "是否全部可见")
+ @NotNull(message = "是否全部可见不能为空")
+ private Boolean allVisibleFlag;
+
+ @Schema(description = "是否定时发布")
+ @NotNull(message = "是否定时发布不能为空")
+ private Boolean scheduledPublishFlag;
+
+ @Schema(description = "发布时间")
+ @NotNull(message = "发布时间不能为空")
+ private LocalDateTime publishTime;
+
+ @Schema(description = "纯文本内容")
+ @NotNull(message = "文本内容不能为空")
+ private String contentText;
+
+ @Schema(description = "html内容")
+ @NotNull(message = "html内容不能为空")
+ private String contentHtml;
+
+ @Schema(description = "附件,多个英文逗号分隔|可选")
+ @Length(max = 1000, message = "最多1000字符")
+ @JsonDeserialize(using = FileKeyVoDeserializer.class)
+ private String attachment;
+
+ @Schema(description = "作者")
+ @NotBlank(message = "作者不能为空")
+ private String author;
+
+ @Schema(description = "来源")
+ @NotBlank(message = "标题不能为空")
+ private String source;
+
+ @Schema(description = "文号")
+ private String documentNumber;
+
+ @Schema(hidden = true)
+ private Long createUserId;
+
+ @Schema(description = "可见范围设置|可选")
+ @Valid
+ private List visibleRangeList;
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeEmployeeQueryForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeEmployeeQueryForm.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeEmployeeQueryForm.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeEmployeeQueryForm.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeQueryForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeQueryForm.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeQueryForm.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeQueryForm.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeUpdateForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeUpdateForm.java
new file mode 100644
index 00000000..13d7553a
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeUpdateForm.java
@@ -0,0 +1,23 @@
+package net.lab1024.sa.admin.module.business.oa.notice.domain.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * 通知公告 更新表单
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-08-12 21:40:39
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class NoticeUpdateForm extends NoticeAddForm {
+
+ @Schema(description = "id")
+ @NotNull(message = "通知id不能为空")
+ private Long noticeId;
+
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeViewRecordQueryForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeViewRecordQueryForm.java
new file mode 100644
index 00000000..415828cf
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeViewRecordQueryForm.java
@@ -0,0 +1,31 @@
+package net.lab1024.sa.admin.module.business.oa.notice.domain.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import net.lab1024.sa.base.common.domain.PageParam;
+
+/**
+ * 通知公告 阅读记录查询
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-08-12 21:40:39
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class NoticeViewRecordQueryForm extends PageParam {
+
+ @Schema(description = "通知公告id")
+ @NotNull(message = "通知公告id不能为空")
+ private Long noticeId;
+
+ @Schema(description = "部门id")
+ private Long departmentId;
+
+ @Schema(description = "关键字")
+ private String keywords;
+
+
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeVisibleRangeForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeVisibleRangeForm.java
new file mode 100644
index 00000000..c831db69
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeVisibleRangeForm.java
@@ -0,0 +1,33 @@
+package net.lab1024.sa.admin.module.business.oa.notice.domain.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import net.lab1024.sa.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum;
+import net.lab1024.sa.base.common.swagger.SchemaEnum;
+import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
+
+/**
+ * 通知公告 可见范围数据
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-08-12 21:40:39
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class NoticeVisibleRangeForm {
+
+ @SchemaEnum(NoticeVisibleRangeDataTypeEnum.class)
+ @CheckEnum(value = NoticeVisibleRangeDataTypeEnum.class, required = true, message = "数据类型错误")
+ private Integer dataType;
+
+ @Schema(description = "员工/部门id")
+ @NotNull(message = "员工/部门id不能为空")
+ private Long dataId;
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeDetailVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeDetailVO.java
new file mode 100644
index 00000000..096a0d06
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeDetailVO.java
@@ -0,0 +1,84 @@
+package net.lab1024.sa.admin.module.business.oa.notice.domain.vo;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer;
+
+import java.time.LocalDateTime;
+
+/**
+ * 通知公告 详情
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-08-12 21:40:39
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class NoticeDetailVO {
+
+ @Schema(description = "id")
+ private Long noticeId;
+
+ @Schema(description = "标题")
+ private String title;
+
+ @Schema(description = "分类")
+ private Long noticeTypeId;
+
+ @Schema(description = "分类名称")
+ private Long noticeTypeName;
+
+ @Schema(description = "是否全部可见")
+ @NotNull(message = "是否全部可见不能为空")
+ private Boolean allVisibleFlag;
+
+ @Schema(description = "是否定时发布")
+ @NotNull(message = "是否定时发布不能为空")
+ private Boolean scheduledPublishFlag;
+
+ @Schema(description = "纯文本内容")
+ private String contentText;
+
+ @Schema(description = "html内容")
+ private String contentHtml;
+
+ @Schema(description = "附件")
+ @JsonSerialize(using = FileKeyVoSerializer.class)
+ private String attachment;
+
+ @Schema(description = "发布时间")
+ @NotNull(message = "发布时间不能为空")
+ private LocalDateTime publishTime;
+
+ @Schema(description = "作者")
+ @NotBlank(message = "作者不能为空")
+ private String author;
+
+ @Schema(description = "来源")
+ @NotBlank(message = "标题不能为空")
+ private String source;
+
+ @Schema(description = "文号")
+ private String documentNumber;
+
+ @Schema(description = "页面浏览量")
+ private Integer pageViewCount;
+
+ @Schema(description = "用户浏览量")
+ private Integer userViewCount;
+
+ @Schema(description = "创建人名称")
+ private Long createUserName;
+
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+
+ @Schema(description = "更新时间")
+ private LocalDateTime updateTime;
+
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeEmployeeVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeEmployeeVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeEmployeeVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeEmployeeVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeTypeVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeTypeVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeTypeVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeTypeVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeUpdateFormVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeUpdateFormVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeUpdateFormVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeUpdateFormVO.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVO.java
new file mode 100644
index 00000000..b67100e2
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVO.java
@@ -0,0 +1,72 @@
+package net.lab1024.sa.admin.module.business.oa.notice.domain.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+
+/**
+ * 新闻、公告 VO
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-08-12 21:40:39
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class NoticeVO {
+
+ @Schema(description = "id")
+ private Long noticeId;
+
+ @Schema(description = "标题")
+ private String title;
+
+ @Schema(description = "分类")
+ private Long noticeTypeId;
+
+ @Schema(description = "分类名称")
+ private String noticeTypeName;
+
+ @Schema(description = "是否全部可见")
+ private Boolean allVisibleFlag;
+
+ @Schema(description = "是否定时发布")
+ private Boolean scheduledPublishFlag;
+
+ @Schema(description = "发布状态")
+ private Boolean publishFlag;
+
+ @Schema(description = "发布时间")
+ private LocalDateTime publishTime;
+
+ @Schema(description = "作者")
+ private String author;
+
+ @Schema(description = "来源")
+ private String source;
+
+ @Schema(description = "文号")
+ private String documentNumber;
+
+ @Schema(description = "页面浏览量")
+ private Integer pageViewCount;
+
+ @Schema(description = "用户浏览量")
+ private Integer userViewCount;
+
+ @Schema(description = "删除标识")
+ private Boolean deletedFlag;
+
+ @Schema(description = "创建人名称")
+ private String createUserName;
+
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+
+ @Schema(description = "更新时间")
+ private LocalDateTime updateTime;
+
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeViewRecordVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeViewRecordVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeViewRecordVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeViewRecordVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVisibleRangeVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVisibleRangeVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVisibleRangeVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVisibleRangeVO.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/manager/NoticeManager.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/manager/NoticeManager.java
new file mode 100644
index 00000000..78b02e16
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/manager/NoticeManager.java
@@ -0,0 +1,62 @@
+package net.lab1024.sa.admin.module.business.oa.notice.manager;
+
+import jakarta.annotation.Resource;
+import net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeEntity;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeVisibleRangeForm;
+import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
+import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * 通知、公告 manager
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-08-12 21:40:39
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+public class NoticeManager {
+
+ @Resource
+ private NoticeDao noticeDao;
+
+ @Resource
+ private DataTracerService dataTracerService;
+
+ /**
+ * 保存
+ */
+ @Transactional(rollbackFor = Throwable.class)
+ public void save(NoticeEntity noticeEntity, List visibleRangeFormList) {
+ noticeDao.insert(noticeEntity);
+ Long noticeId = noticeEntity.getNoticeId();
+ // 保存可见范围
+ if (CollectionUtils.isNotEmpty(visibleRangeFormList)) {
+ noticeDao.insertVisibleRange(noticeId, visibleRangeFormList);
+ }
+ dataTracerService.insert(noticeId, DataTracerTypeEnum.OA_NOTICE);
+ }
+
+ /**
+ * 更新
+ *
+ */
+ @Transactional(rollbackFor = Throwable.class)
+ public void update(NoticeEntity old, NoticeEntity noticeEntity, List visibleRangeList) {
+ noticeDao.updateById(noticeEntity);
+ Long noticeId = noticeEntity.getNoticeId();
+ // 保存可见范围
+ if (CollectionUtils.isNotEmpty(visibleRangeList)) {
+ noticeDao.deleteVisibleRange(noticeId);
+ noticeDao.insertVisibleRange(noticeId, visibleRangeList);
+ }
+ dataTracerService.update(noticeId, DataTracerTypeEnum.OA_NOTICE, old, noticeEntity);
+ }
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeEmployeeService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeEmployeeService.java
new file mode 100644
index 00000000..2f2404de
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeEmployeeService.java
@@ -0,0 +1,155 @@
+package net.lab1024.sa.admin.module.business.oa.notice.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.google.common.collect.Lists;
+import jakarta.annotation.Resource;
+import net.lab1024.sa.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum;
+import net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeEmployeeQueryForm;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeViewRecordQueryForm;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.*;
+import net.lab1024.sa.admin.module.system.department.service.DepartmentService;
+import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity;
+import net.lab1024.sa.admin.module.system.employee.service.EmployeeService;
+import net.lab1024.sa.base.common.domain.PageResult;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.SmartBeanUtil;
+import net.lab1024.sa.base.common.util.SmartPageUtil;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+
+/**
+ * 员工查看 通知。公告
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-08-12 21:40:39
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+public class NoticeEmployeeService {
+
+ @Resource
+ private NoticeDao noticeDao;
+
+ @Resource
+ private NoticeService noticeService;
+
+ @Resource
+ private DepartmentService departmentService;
+
+ @Resource
+ private EmployeeService employeeService;
+
+ /**
+ * 查询我的 通知、公告清单
+ */
+ public ResponseDTO> queryList(Long requestEmployeeId, NoticeEmployeeQueryForm noticeEmployeeQueryForm) {
+ Page> page = SmartPageUtil.convert2PageQuery(noticeEmployeeQueryForm);
+
+ List employeeDepartmentIdList = Lists.newArrayList();
+ EmployeeEntity employeeEntity = employeeService.getById(requestEmployeeId);
+ // 如果不是管理员 则获取请求人的 部门及其子部门
+ if (!employeeEntity.getAdministratorFlag() && employeeEntity.getDepartmentId() != null) {
+ employeeDepartmentIdList = departmentService.selfAndChildrenIdList(employeeEntity.getDepartmentId());
+ }
+
+ List noticeList = null;
+ //只查询未读的
+ if (noticeEmployeeQueryForm.getNotViewFlag() != null && noticeEmployeeQueryForm.getNotViewFlag()) {
+ noticeList = noticeDao.queryEmployeeNotViewNotice(page,
+ requestEmployeeId,
+ noticeEmployeeQueryForm,
+ employeeDepartmentIdList,
+ false,
+ employeeEntity.getAdministratorFlag(),
+ NoticeVisibleRangeDataTypeEnum.DEPARTMENT.getValue(),
+ NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue());
+ } else {
+ // 查询全部
+ noticeList = noticeDao.queryEmployeeNotice(page,
+ requestEmployeeId,
+ noticeEmployeeQueryForm,
+ employeeDepartmentIdList,
+ false,
+ employeeEntity.getAdministratorFlag(),
+ NoticeVisibleRangeDataTypeEnum.DEPARTMENT.getValue(),
+ NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue());
+ }
+ // 设置发布日期
+ noticeList.forEach(notice -> notice.setPublishDate(notice.getPublishTime().toLocalDate()));
+
+ return ResponseDTO.ok(SmartPageUtil.convert2PageResult(page, noticeList));
+ }
+
+
+ /**
+ * 查询我的 待查看的 通知、公告清单
+ */
+ public ResponseDTO view(Long requestEmployeeId, Long noticeId, String ip, String userAgent) {
+ NoticeUpdateFormVO updateFormVO = noticeService.getUpdateFormVO(noticeId);
+ if (updateFormVO == null || Boolean.TRUE.equals(updateFormVO.getDeletedFlag())) {
+ return ResponseDTO.userErrorParam("通知公告不存在");
+ }
+
+ EmployeeEntity employeeEntity = employeeService.getById(requestEmployeeId);
+ if (!updateFormVO.getAllVisibleFlag() && !checkVisibleRange(updateFormVO.getVisibleRangeList(), requestEmployeeId, employeeEntity.getDepartmentId())) {
+ return ResponseDTO.userErrorParam("对不起,您没有权限查看内容");
+ }
+
+ NoticeDetailVO noticeDetailVO = SmartBeanUtil.copy(updateFormVO, NoticeDetailVO.class);
+ long viewCount = noticeDao.viewRecordCount(noticeId, requestEmployeeId);
+ if (viewCount == 0) {
+ noticeDao.insertViewRecord(noticeId, requestEmployeeId, ip, userAgent, 1);
+ // 该员工对于这个通知是第一次查看 页面浏览量+1 用户浏览量+1
+ noticeDao.updateViewCount(noticeId, 1, 1);
+ noticeDetailVO.setPageViewCount(noticeDetailVO.getPageViewCount() + 1);
+ noticeDetailVO.setUserViewCount(noticeDetailVO.getUserViewCount() + 1);
+ } else {
+ noticeDao.updateViewRecord(noticeId, requestEmployeeId, ip, userAgent);
+ // 该员工对于这个通知不是第一次查看 页面浏览量+1 用户浏览量+0
+ noticeDao.updateViewCount(noticeId, 1, 0);
+ noticeDetailVO.setPageViewCount(noticeDetailVO.getPageViewCount() + 1);
+ }
+
+ return ResponseDTO.ok(noticeDetailVO);
+ }
+
+ /**
+ * 校验是否有查看权限的范围
+ *
+ */
+ public boolean checkVisibleRange(List visibleRangeList, Long employeeId, Long departmentId) {
+ // 员工范围
+ boolean anyMatch = visibleRangeList.stream().anyMatch(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.equalsValue(e.getDataType()) && Objects.equals(e.getDataId(), employeeId));
+ if (anyMatch) {
+ return true;
+ }
+
+ //部门范围
+ List visibleDepartmentIdList = visibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.DEPARTMENT.equalsValue(e.getDataType()))
+ .map(NoticeVisibleRangeVO::getDataId).collect(Collectors.toList());
+
+ for (Long visibleDepartmentId : visibleDepartmentIdList) {
+ List departmentIdList = departmentService.selfAndChildrenIdList(visibleDepartmentId);
+ if (departmentIdList.contains(departmentId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 分页查询 查看记录
+ */
+ public PageResult queryViewRecord(NoticeViewRecordQueryForm noticeViewRecordQueryForm) {
+ Page> page = SmartPageUtil.convert2PageQuery(noticeViewRecordQueryForm);
+ List noticeViewRecordList = noticeDao.queryNoticeViewRecordList(page, noticeViewRecordQueryForm);
+ return SmartPageUtil.convert2PageResult(page, noticeViewRecordList);
+ }
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeService.java
new file mode 100644
index 00000000..2236f536
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeService.java
@@ -0,0 +1,236 @@
+package net.lab1024.sa.admin.module.business.oa.notice.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.google.common.collect.Maps;
+import jakarta.annotation.Resource;
+import net.lab1024.sa.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum;
+import net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeEntity;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeAddForm;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeQueryForm;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeUpdateForm;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeVisibleRangeForm;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeTypeVO;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeUpdateFormVO;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVO;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVisibleRangeVO;
+import net.lab1024.sa.admin.module.business.oa.notice.manager.NoticeManager;
+import net.lab1024.sa.admin.module.system.department.dao.DepartmentDao;
+import net.lab1024.sa.admin.module.system.department.domain.entity.DepartmentEntity;
+import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO;
+import net.lab1024.sa.admin.module.system.department.service.DepartmentService;
+import net.lab1024.sa.admin.module.system.employee.dao.EmployeeDao;
+import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity;
+import net.lab1024.sa.base.common.constant.StringConst;
+import net.lab1024.sa.base.common.domain.PageResult;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.SmartBeanUtil;
+import net.lab1024.sa.base.common.util.SmartPageUtil;
+import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
+import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 通知。公告 后台管理业务
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-08-12 21:40:39
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+public class NoticeService {
+
+ @Resource
+ private NoticeDao noticeDao;
+
+ @Resource
+ private NoticeManager noticeManager;
+
+ @Resource
+ private EmployeeDao employeeDao;
+
+ @Resource
+ private DepartmentDao departmentDao;
+
+ @Resource
+ private DepartmentService departmentService;
+
+ @Resource
+ private NoticeTypeService noticeTypeService;
+
+ @Resource
+ private DataTracerService dataTracerService;
+
+ /**
+ * 查询 通知、公告
+ *
+ */
+ public PageResult query(NoticeQueryForm queryForm) {
+ Page> page = SmartPageUtil.convert2PageQuery(queryForm);
+ List list = noticeDao.query(page, queryForm);
+ LocalDateTime now = LocalDateTime.now();
+ list.forEach(e -> e.setPublishFlag(e.getPublishTime().isBefore(now)));
+ return SmartPageUtil.convert2PageResult(page, list);
+ }
+
+ /**
+ * 添加
+ */
+ public ResponseDTO add(NoticeAddForm addForm) {
+ // 校验并获取可见范围
+ ResponseDTO validate = this.checkAndBuildVisibleRange(addForm);
+ if (!validate.getOk()) {
+ return ResponseDTO.error(validate);
+ }
+
+ // build 资讯
+ NoticeEntity noticeEntity = SmartBeanUtil.copy(addForm, NoticeEntity.class);
+ // 发布时间:不是定时发布时 默认为 当前
+ if (!addForm.getScheduledPublishFlag()) {
+ noticeEntity.setPublishTime(LocalDateTime.now());
+ }
+ // 保存数据
+ noticeManager.save(noticeEntity, addForm.getVisibleRangeList());
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 校验并返回可见范围
+ *
+ */
+ private ResponseDTO checkAndBuildVisibleRange(NoticeAddForm form) {
+ // 校验资讯分类
+ NoticeTypeVO noticeType = noticeTypeService.getByNoticeTypeId(form.getNoticeTypeId());
+ if (noticeType == null) {
+ return ResponseDTO.userErrorParam("分类不存在");
+ }
+
+ if (form.getAllVisibleFlag()) {
+ return ResponseDTO.ok();
+ }
+
+ /*
+ * 校验可见范围
+ * 非全部可见时 校验选择的员工|部门
+ */
+ List visibleRangeUpdateList = form.getVisibleRangeList();
+ if (CollectionUtils.isEmpty(visibleRangeUpdateList)) {
+ return ResponseDTO.userErrorParam("未设置可见范围");
+ }
+
+ // 校验可见范围-> 员工
+ List employeeIdList = visibleRangeUpdateList.stream()
+ .filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.equalsValue(e.getDataType()))
+ .map(NoticeVisibleRangeForm::getDataId)
+ .distinct().collect(Collectors.toList());
+ if (CollectionUtils.isNotEmpty(employeeIdList)) {
+ employeeIdList = employeeIdList.stream().distinct().collect(Collectors.toList());
+ List dbEmployeeIdList = employeeDao.selectBatchIds(employeeIdList).stream().map(EmployeeEntity::getEmployeeId).collect(Collectors.toList());
+ Collection subtract = CollectionUtils.subtract(employeeIdList, dbEmployeeIdList);
+ if (!subtract.isEmpty()) {
+ return ResponseDTO.userErrorParam("员工id不存在:" + subtract);
+ }
+ }
+
+ // 校验可见范围-> 部门
+ List deptIdList = visibleRangeUpdateList.stream()
+ .filter(e -> NoticeVisibleRangeDataTypeEnum.DEPARTMENT.equalsValue(e.getDataType()))
+ .map(NoticeVisibleRangeForm::getDataId)
+ .distinct().collect(Collectors.toList());
+ if (CollectionUtils.isNotEmpty(deptIdList)) {
+ deptIdList = deptIdList.stream().distinct().collect(Collectors.toList());
+ List dbDeptIdList = departmentDao.selectBatchIds(deptIdList).stream().map(DepartmentEntity::getDepartmentId).collect(Collectors.toList());
+ Collection subtract = CollectionUtils.subtract(deptIdList, dbDeptIdList);
+ if (!subtract.isEmpty()) {
+ return ResponseDTO.userErrorParam("部门id不存在:" + subtract);
+ }
+ }
+ return ResponseDTO.ok();
+ }
+
+
+ /**
+ * 更新
+ *
+ */
+ public ResponseDTO update(NoticeUpdateForm updateForm) {
+
+ NoticeEntity oldNoticeEntity = noticeDao.selectById(updateForm.getNoticeId());
+ if (oldNoticeEntity == null) {
+ return ResponseDTO.userErrorParam("通知不存在");
+ }
+
+ // 校验并获取可见范围
+ ResponseDTO res = this.checkAndBuildVisibleRange(updateForm);
+ if (!res.getOk()) {
+ return ResponseDTO.error(res);
+ }
+
+ // 更新
+ NoticeEntity noticeEntity = SmartBeanUtil.copy(updateForm, NoticeEntity.class);
+ noticeManager.update(oldNoticeEntity, noticeEntity, updateForm.getVisibleRangeList());
+ return ResponseDTO.ok();
+ }
+
+
+ /**
+ * 删除
+ *
+ */
+ public ResponseDTO delete(Long noticeId) {
+ NoticeEntity noticeEntity = noticeDao.selectById(noticeId);
+ if (null == noticeEntity || noticeEntity.getDeletedFlag()) {
+ return ResponseDTO.userErrorParam("通知公告不存在");
+ }
+ // 更新删除状态
+ noticeDao.updateDeletedFlag(noticeId);
+ dataTracerService.delete(noticeId, DataTracerTypeEnum.OA_NOTICE);
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 获取更新表单用的详情
+ */
+ public NoticeUpdateFormVO getUpdateFormVO(Long noticeId) {
+ NoticeEntity noticeEntity = noticeDao.selectById(noticeId);
+ if (null == noticeEntity) {
+ return null;
+ }
+
+ NoticeUpdateFormVO updateFormVO = SmartBeanUtil.copy(noticeEntity, NoticeUpdateFormVO.class);
+ if (!updateFormVO.getAllVisibleFlag()) {
+ List noticeVisibleRangeList = noticeDao.queryVisibleRange(noticeId);
+ List employeeIdList = noticeVisibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue().equals(e.getDataType()))
+ .map(NoticeVisibleRangeVO::getDataId)
+ .collect(Collectors.toList());
+
+ Map employeeMap = null;
+ if (CollectionUtils.isNotEmpty(employeeIdList)) {
+ employeeMap = employeeDao.selectBatchIds(employeeIdList).stream().collect(Collectors.toMap(EmployeeEntity::getEmployeeId, Function.identity()));
+ } else {
+ employeeMap = Maps.newHashMap();
+ }
+ for (NoticeVisibleRangeVO noticeVisibleRange : noticeVisibleRangeList) {
+ if (noticeVisibleRange.getDataType().equals(NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue())) {
+ EmployeeEntity employeeEntity = employeeMap.get(noticeVisibleRange.getDataId());
+ noticeVisibleRange.setDataName(employeeEntity == null ? StringConst.EMPTY : employeeEntity.getActualName());
+ } else {
+ DepartmentVO departmentVO = departmentService.getDepartmentById(noticeVisibleRange.getDataId());
+ noticeVisibleRange.setDataName(departmentVO == null ? StringConst.EMPTY : departmentVO.getName());
+ }
+ }
+ updateFormVO.setVisibleRangeList(noticeVisibleRangeList);
+ }
+ return updateFormVO;
+ }
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeTypeService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeTypeService.java
new file mode 100644
index 00000000..6e8a3114
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeTypeService.java
@@ -0,0 +1,87 @@
+package net.lab1024.sa.admin.module.business.oa.notice.service;
+
+import cn.hutool.core.util.StrUtil;
+import jakarta.annotation.Resource;
+import net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeTypeDao;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeTypeEntity;
+import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeTypeVO;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.SmartBeanUtil;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * 通知。公告 类型
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-08-12 21:40:39
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+public class NoticeTypeService {
+
+ @Resource
+ private NoticeTypeDao noticeTypeDao;
+
+ /**
+ * 查询全部
+ * @return
+ */
+ public List getAll() {
+ return SmartBeanUtil.copyList(noticeTypeDao.selectList(null), NoticeTypeVO.class);
+ }
+
+ public NoticeTypeVO getByNoticeTypeId(Long noticceTypeId) {
+ return SmartBeanUtil.copy(noticeTypeDao.selectById(noticceTypeId), NoticeTypeVO.class);
+ }
+
+ public synchronized ResponseDTO add(String name) {
+ if (StrUtil.isBlank(name)) {
+ return ResponseDTO.userErrorParam("类型名称不能为空");
+ }
+
+ List noticeTypeEntityList = noticeTypeDao.selectList(null);
+ if (!CollectionUtils.isEmpty(noticeTypeEntityList)) {
+ boolean exist = noticeTypeEntityList.stream().map(NoticeTypeEntity::getNoticeTypeName).collect(Collectors.toSet()).contains(name);
+ if (exist) {
+ return ResponseDTO.userErrorParam("类型名称已经存在");
+ }
+ }
+ noticeTypeDao.insert(NoticeTypeEntity.builder().noticeTypeName(name).build());
+ return ResponseDTO.ok();
+ }
+
+ public synchronized ResponseDTO update(Long noticeTypeId, String name) {
+ if (StrUtil.isBlank(name)) {
+ return ResponseDTO.userErrorParam("类型名称不能为空");
+ }
+
+ NoticeTypeEntity noticeTypeEntity = noticeTypeDao.selectById(noticeTypeId);
+ if (noticeTypeEntity == null) {
+ return ResponseDTO.userErrorParam("类型名称不存在");
+ }
+
+ List noticeTypeEntityList = noticeTypeDao.selectList(null);
+ if (!CollectionUtils.isEmpty(noticeTypeEntityList)) {
+ Optional optionalNoticeTypeEntity = noticeTypeEntityList.stream().filter(e -> e.getNoticeTypeName().equals(name)).findFirst();
+ if (optionalNoticeTypeEntity.isPresent() && !optionalNoticeTypeEntity.get().getNoticeTypeId().equals(noticeTypeId)) {
+ return ResponseDTO.userErrorParam("类型名称已经存在");
+ }
+ }
+ noticeTypeEntity.setNoticeTypeName(name);
+ noticeTypeDao.updateById(noticeTypeEntity);
+ return ResponseDTO.ok();
+ }
+
+ public synchronized ResponseDTO delete(Long noticeTypeId) {
+ noticeTypeDao.deleteById(noticeTypeId);
+ return ResponseDTO.ok();
+ }
+
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScope.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScope.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScope.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScope.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScopeController.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScopeController.java
new file mode 100644
index 00000000..8f2fec8e
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScopeController.java
@@ -0,0 +1,38 @@
+package net.lab1024.sa.admin.module.system.datascope;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
+import net.lab1024.sa.admin.module.system.datascope.domain.DataScopeAndViewTypeVO;
+import net.lab1024.sa.admin.module.system.datascope.service.DataScopeService;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 查询支持的数据范围类型
+ *
+ * @Author 1024创新实验室: 罗伊
+ * @Date 2022-03-18 20:59:17
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@RestController
+@Tag(name = AdminSwaggerTagConst.System.SYSTEM_DATA_SCOPE)
+public class DataScopeController {
+
+ @Resource
+ private DataScopeService dataScopeService;
+
+ @Operation(summary = "获取当前系统所配置的所有数据范围 @author 罗伊")
+ @GetMapping("/dataScope/list")
+ public ResponseDTO> dataScopeList() {
+ return dataScopeService.dataScopeList();
+ }
+
+
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/MyBatisPlugin.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/MyBatisPlugin.java
new file mode 100644
index 00000000..76dab10e
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/MyBatisPlugin.java
@@ -0,0 +1,186 @@
+package net.lab1024.sa.admin.module.system.datascope;
+
+import cn.hutool.core.util.StrUtil;
+import com.google.common.collect.Maps;
+import jakarta.annotation.Resource;
+import net.lab1024.sa.admin.module.system.datascope.domain.DataScopeSqlConfig;
+import net.lab1024.sa.admin.module.system.datascope.service.DataScopeSqlConfigService;
+import net.lab1024.sa.base.common.domain.DataScopePlugin;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.ibatis.mapping.*;
+import org.apache.ibatis.plugin.Intercepts;
+import org.apache.ibatis.plugin.Invocation;
+import org.apache.ibatis.plugin.Plugin;
+import org.apache.ibatis.plugin.Signature;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * mybaits sql 拦截
+ *
+ * @Author 1024创新实验室: 罗伊
+ * @Date 2022-03-18 20:59:17
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Intercepts({@Signature(type = org.apache.ibatis.executor.Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
+@Component
+public class MyBatisPlugin extends DataScopePlugin {
+
+ @Resource
+ private ApplicationContext applicationContext;
+
+ @Override
+ public Object intercept(Invocation invocation) throws Throwable {
+
+ MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
+ Object parameter = invocation.getArgs()[1];
+
+ BoundSql boundSql = mappedStatement.getBoundSql(parameter);
+ String originalSql = boundSql.getSql().trim();
+ String id = mappedStatement.getId();
+ List methodStrList = StrUtil.split(id, ".");
+ String path = methodStrList.get(methodStrList.size() - 2) + "." + methodStrList.get(methodStrList.size() - 1);
+ DataScopeSqlConfigService dataScopeSqlConfigService = this.dataScopeSqlConfigService();
+ if (dataScopeSqlConfigService == null) {
+ return invocation.proceed();
+ }
+ DataScopeSqlConfig sqlConfigDTO = dataScopeSqlConfigService.getSqlConfig(path);
+ if (sqlConfigDTO != null) {
+ Map paramMap = this.getParamList(sqlConfigDTO.getParamName(), parameter);
+ BoundSql newBoundSql = copyFromBoundSql(mappedStatement, boundSql, this.joinSql(originalSql, paramMap, sqlConfigDTO));
+ ParameterMap map = mappedStatement.getParameterMap();
+ MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql), map);
+ invocation.getArgs()[0] = newMs;
+ }
+
+ Object obj = invocation.proceed();
+ return obj;
+ }
+
+
+ private Map getParamList(String paramName, Object parameter) {
+ Map paramMap = Maps.newHashMap();
+ if (StringUtils.isEmpty(paramName)) {
+ return paramMap;
+ }
+ if (parameter == null) {
+ return paramMap;
+ }
+ if (parameter instanceof Map) {
+ String[] paramNameArray = paramName.split(",");
+ Map, ?> parameterMap = (Map) parameter;
+ for (String param : paramNameArray) {
+ if(parameterMap.containsKey(param)){
+ paramMap.put(param, parameterMap.get(param));
+ }
+ }
+ }
+ return paramMap;
+ }
+
+ private String joinSql(String sql, Map paramMap, DataScopeSqlConfig sqlConfigDTO) {
+ if (null == sqlConfigDTO) {
+ return sql;
+ }
+ String appendSql = this.dataScopeSqlConfigService().getJoinSql(paramMap, sqlConfigDTO);
+ if (StringUtils.isEmpty(appendSql)) {
+ return sql;
+ }
+ Integer appendSqlWhereIndex = sqlConfigDTO.getWhereIndex();
+ String where = "where";
+ String order = "order by";
+ String group = "group by";
+ int whereIndex = StringUtils.ordinalIndexOf(sql.toLowerCase(), where, appendSqlWhereIndex + 1);
+ int orderIndex = sql.toLowerCase().indexOf(order);
+ int groupIndex = sql.toLowerCase().indexOf(group);
+ if (whereIndex > -1) {
+ String subSql = sql.substring(0, whereIndex + where.length() + 1);
+ subSql = subSql + " " + appendSql + " AND " + sql.substring(whereIndex + where.length() + 1);
+ return subSql;
+ }
+
+ if (groupIndex > -1) {
+ String subSql = sql.substring(0, groupIndex);
+ subSql = subSql + " where " + appendSql + " " + sql.substring(groupIndex);
+ return subSql;
+ }
+ if (orderIndex > -1) {
+ String subSql = sql.substring(0, orderIndex);
+ subSql = subSql + " where " + appendSql + " " + sql.substring(orderIndex);
+ return subSql;
+ }
+ sql += " where " + appendSql;
+ return sql;
+ }
+
+ public DataScopeSqlConfigService dataScopeSqlConfigService() {
+ return (DataScopeSqlConfigService) applicationContext.getBean("dataScopeSqlConfigService");
+ }
+
+ public class BoundSqlSqlSource implements SqlSource {
+
+ BoundSql boundSql;
+
+ public BoundSqlSqlSource(BoundSql boundSql) {
+ this.boundSql = boundSql;
+ }
+
+ @Override
+ public BoundSql getBoundSql(Object parameterObject) {
+ return boundSql;
+ }
+ }
+
+ /**
+ * 复制MappedStatement对象
+ */
+ private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource, ParameterMap parameterMap) {
+
+ MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());
+ builder.resource(ms.getResource());
+ builder.fetchSize(ms.getFetchSize());
+ builder.statementType(ms.getStatementType());
+ builder.keyGenerator(ms.getKeyGenerator());
+ builder.timeout(ms.getTimeout());
+ builder.parameterMap(parameterMap);
+ builder.resultMaps(ms.getResultMaps());
+ builder.resultSetType(ms.getResultSetType());
+ builder.cache(ms.getCache());
+ builder.flushCacheRequired(ms.isFlushCacheRequired());
+ builder.useCache(ms.isUseCache());
+ return builder.build();
+ }
+
+ /**
+ * 复制BoundSql对象
+ */
+ private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql) {
+ BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), sql, boundSql.getParameterMappings(), boundSql.getParameterObject());
+ for (ParameterMapping mapping : boundSql.getParameterMappings()) {
+ String prop = mapping.getProperty();
+ if (boundSql.hasAdditionalParameter(prop)) {
+ newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
+ }
+ }
+ return newBoundSql;
+ }
+
+ @Override
+ public Object plugin(Object arg0) {
+ return Plugin.wrap(arg0, this);
+ }
+
+ @Override
+ public void setProperties(Properties arg0) {
+
+ }
+
+}
\ No newline at end of file
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeTypeEnum.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeTypeEnum.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeTypeEnum.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeTypeEnum.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeViewTypeEnum.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeViewTypeEnum.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeViewTypeEnum.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeViewTypeEnum.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeWhereInTypeEnum.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeWhereInTypeEnum.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeWhereInTypeEnum.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeWhereInTypeEnum.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeAndViewTypeVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeAndViewTypeVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeAndViewTypeVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeAndViewTypeVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeDTO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeDTO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeDTO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeDTO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeSqlConfig.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeSqlConfig.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeSqlConfig.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeSqlConfig.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeViewTypeVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeViewTypeVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeViewTypeVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeViewTypeVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeService.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeService.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeService.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeSqlConfigService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeSqlConfigService.java
new file mode 100644
index 00000000..38200442
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeSqlConfigService.java
@@ -0,0 +1,137 @@
+package net.lab1024.sa.admin.module.system.datascope.service;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import net.lab1024.sa.admin.AdminApplication;
+import net.lab1024.sa.admin.module.system.datascope.DataScope;
+import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeTypeEnum;
+import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeViewTypeEnum;
+import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeWhereInTypeEnum;
+import net.lab1024.sa.admin.module.system.datascope.domain.DataScopeSqlConfig;
+import net.lab1024.sa.admin.module.system.datascope.strategy.AbstractDataScopeStrategy;
+import net.lab1024.sa.base.common.util.SmartRequestUtil;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.reflections.Reflections;
+import org.reflections.scanners.MethodAnnotationsScanner;
+import org.reflections.util.ClasspathHelper;
+import org.reflections.util.ConfigurationBuilder;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Service;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * sql配置
+ *
+ * @Author 1024创新实验室: 罗伊
+ * @Date 2020/11/28 20:59:17
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Slf4j
+@Service
+public class DataScopeSqlConfigService {
+
+ /**
+ * 注解joinsql 参数
+ */
+ private static final String EMPLOYEE_PARAM = "#employeeIds";
+
+ private static final String DEPARTMENT_PARAM = "#departmentIds";
+
+ private final ConcurrentHashMap dataScopeMethodMap = new ConcurrentHashMap<>();
+
+ @Resource
+ private DataScopeViewService dataScopeViewService;
+
+ @Resource
+ private ApplicationContext applicationContext;
+
+
+ @PostConstruct
+ private void initDataScopeMethodMap() {
+ this.refreshDataScopeMethodMap();
+ }
+
+ /**
+ * 刷新 所有添加数据范围注解的接口方法配置>
+ */
+ private Map refreshDataScopeMethodMap() {
+ Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage(AdminApplication.COMPONENT_SCAN)).setScanners(new MethodAnnotationsScanner()));
+ Set methods = reflections.getMethodsAnnotatedWith(DataScope.class);
+ for (Method method : methods) {
+ DataScope dataScopeAnnotation = method.getAnnotation(DataScope.class);
+ if (dataScopeAnnotation != null) {
+ DataScopeSqlConfig configDTO = new DataScopeSqlConfig();
+ configDTO.setDataScopeType(dataScopeAnnotation.dataScopeType());
+ configDTO.setJoinSql(dataScopeAnnotation.joinSql());
+ configDTO.setWhereIndex(dataScopeAnnotation.whereIndex());
+ configDTO.setDataScopeWhereInType(dataScopeAnnotation.whereInType());
+ configDTO.setParamName(dataScopeAnnotation.paramName());
+ configDTO.setJoinSqlImplClazz(dataScopeAnnotation.joinSqlImplClazz());
+ dataScopeMethodMap.put(method.getDeclaringClass().getSimpleName() + "." + method.getName(), configDTO);
+ }
+ }
+ return dataScopeMethodMap;
+ }
+
+ /**
+ * 根据调用的方法获取,此方法的配置信息
+ *
+ */
+ public DataScopeSqlConfig getSqlConfig(String method) {
+ return this.dataScopeMethodMap.get(method);
+ }
+
+ /**
+ * 组装需要拼接的sql
+ */
+ public String getJoinSql(Map paramMap, DataScopeSqlConfig sqlConfigDTO) {
+ DataScopeTypeEnum dataScopeTypeEnum = sqlConfigDTO.getDataScopeType();
+ String joinSql = sqlConfigDTO.getJoinSql();
+ Long employeeId = SmartRequestUtil.getRequestUserId();
+ if (employeeId == null) {
+ return "";
+ }
+ if (DataScopeWhereInTypeEnum.CUSTOM_STRATEGY == sqlConfigDTO.getDataScopeWhereInType()) {
+ Class strategyClass = sqlConfigDTO.getJoinSqlImplClazz();
+ if (strategyClass == null) {
+ log.warn("data scope custom strategy class is null");
+ return "";
+ }
+ AbstractDataScopeStrategy powerStrategy = (AbstractDataScopeStrategy) applicationContext.getBean(sqlConfigDTO.getJoinSqlImplClazz());
+ if (powerStrategy == null) {
+ log.warn("data scope custom strategy class:{} ,bean is null", sqlConfigDTO.getJoinSqlImplClazz());
+ return "";
+ }
+ DataScopeViewTypeEnum viewTypeEnum = dataScopeViewService.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
+ return powerStrategy.getCondition(viewTypeEnum,paramMap, sqlConfigDTO);
+ }
+ if (DataScopeWhereInTypeEnum.EMPLOYEE == sqlConfigDTO.getDataScopeWhereInType()) {
+ List canViewEmployeeIds = dataScopeViewService.getCanViewEmployeeId(dataScopeTypeEnum, employeeId);
+ if (CollectionUtils.isEmpty(canViewEmployeeIds)) {
+ return "";
+ }
+ String employeeIds = StringUtils.join(canViewEmployeeIds, ",");
+ String sql = joinSql.replaceAll(EMPLOYEE_PARAM, employeeIds);
+ return sql;
+ }
+ if (DataScopeWhereInTypeEnum.DEPARTMENT == sqlConfigDTO.getDataScopeWhereInType()) {
+ List canViewDepartmentIds = dataScopeViewService.getCanViewDepartmentId(dataScopeTypeEnum, employeeId);
+ if (CollectionUtils.isEmpty(canViewDepartmentIds)) {
+ return "";
+ }
+ String departmentIds = StringUtils.join(canViewDepartmentIds, ",");
+ String sql = joinSql.replaceAll(DEPARTMENT_PARAM, departmentIds);
+ return sql;
+ }
+ return "";
+ }
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeViewService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeViewService.java
new file mode 100644
index 00000000..b426af30
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeViewService.java
@@ -0,0 +1,139 @@
+package net.lab1024.sa.admin.module.system.datascope.service;
+
+import com.google.common.collect.Lists;
+import jakarta.annotation.Resource;
+import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeTypeEnum;
+import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeViewTypeEnum;
+import net.lab1024.sa.admin.module.system.department.service.DepartmentService;
+import net.lab1024.sa.admin.module.system.employee.dao.EmployeeDao;
+import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity;
+import net.lab1024.sa.admin.module.system.role.dao.RoleDataScopeDao;
+import net.lab1024.sa.admin.module.system.role.dao.RoleEmployeeDao;
+import net.lab1024.sa.admin.module.system.role.domain.entity.RoleDataScopeEntity;
+import net.lab1024.sa.base.common.util.SmartEnumUtil;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 数据范围
+ *
+ * @Author 1024创新实验室: 罗伊
+ * @Date 2020/11/28 20:59:17
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+public class DataScopeViewService {
+
+ @Resource
+ private RoleEmployeeDao roleEmployeeDao;
+
+ @Resource
+ private RoleDataScopeDao roleDataScopeDao;
+
+ @Resource
+ private EmployeeDao employeeDao;
+
+ @Resource
+ private DepartmentService departmentService;
+
+ /**
+ * 获取某人可以查看的所有人员信息
+ */
+ public List getCanViewEmployeeId(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) {
+ DataScopeViewTypeEnum viewType = this.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
+ if (DataScopeViewTypeEnum.ME == viewType) {
+ return this.getMeEmployeeIdList(employeeId);
+ }
+ if (DataScopeViewTypeEnum.DEPARTMENT == viewType) {
+ return this.getDepartmentEmployeeIdList(employeeId);
+ }
+ if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB == viewType) {
+ return this.getDepartmentAndSubEmployeeIdList(employeeId);
+ }
+ return Lists.newArrayList();
+ }
+
+ /**
+ * 获取某人可以查看的所有部门信息
+ */
+ public List getCanViewDepartmentId(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) {
+ DataScopeViewTypeEnum viewType = this.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
+ if (DataScopeViewTypeEnum.ME == viewType) {
+ return this.getMeDepartmentIdList(employeeId);
+ }
+ if (DataScopeViewTypeEnum.DEPARTMENT == viewType) {
+ return this.getMeDepartmentIdList(employeeId);
+ }
+ if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB == viewType) {
+ return this.getDepartmentAndSubIdList(employeeId);
+ }
+ return Lists.newArrayList();
+ }
+
+ public List getMeDepartmentIdList(Long employeeId) {
+ EmployeeEntity employeeEntity = employeeDao.selectById(employeeId);
+ return Lists.newArrayList(employeeEntity.getDepartmentId());
+ }
+
+ public List getDepartmentAndSubIdList(Long employeeId) {
+ EmployeeEntity employeeEntity = employeeDao.selectById(employeeId);
+ return departmentService.selfAndChildrenIdList(employeeEntity.getDepartmentId());
+ }
+
+ /**
+ * 根据员工id 获取各数据范围最大的可见范围 map>
+ */
+ public DataScopeViewTypeEnum getEmployeeDataScopeViewType(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) {
+ if (employeeId == null) {
+ return DataScopeViewTypeEnum.ME;
+ }
+
+ List roleIdList = roleEmployeeDao.selectRoleIdByEmployeeId(employeeId);
+ //未设置角色 默认本人
+ if (CollectionUtils.isEmpty(roleIdList)) {
+ return DataScopeViewTypeEnum.ME;
+ }
+ //未设置角色数据范围 默认本人
+ List dataScopeRoleList = roleDataScopeDao.listByRoleIdList(roleIdList);
+ if (CollectionUtils.isEmpty(dataScopeRoleList)) {
+ return DataScopeViewTypeEnum.ME;
+ }
+ Map> listMap = dataScopeRoleList.stream().collect(Collectors.groupingBy(RoleDataScopeEntity::getDataScopeType));
+ List viewLevelList = listMap.getOrDefault(dataScopeTypeEnum.getValue(), Lists.newArrayList());
+ if (CollectionUtils.isEmpty(viewLevelList)) {
+ return DataScopeViewTypeEnum.ME;
+ }
+ RoleDataScopeEntity maxLevel = viewLevelList.stream().max(Comparator.comparing(e -> SmartEnumUtil.getEnumByValue(e.getViewType(), DataScopeViewTypeEnum.class).getLevel())).get();
+ return SmartEnumUtil.getEnumByValue(maxLevel.getViewType(), DataScopeViewTypeEnum.class);
+ }
+
+ /**
+ * 获取本人相关 可查看员工id
+ */
+ private List getMeEmployeeIdList(Long employeeId) {
+ return Lists.newArrayList(employeeId);
+ }
+
+ /**
+ * 获取本部门相关 可查看员工id
+ */
+ private List getDepartmentEmployeeIdList(Long employeeId) {
+ EmployeeEntity employeeEntity = employeeDao.selectById(employeeId);
+ return employeeDao.getEmployeeIdByDepartmentId(employeeEntity.getDepartmentId(), false);
+ }
+
+ /**
+ * 获取本部门及下属子部门相关 可查看员工id
+ */
+ private List getDepartmentAndSubEmployeeIdList(Long employeeId) {
+ List allDepartmentIds = getDepartmentAndSubIdList(employeeId);
+ return employeeDao.getEmployeeIdByDepartmentIdList(allDepartmentIds, false);
+ }
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/strategy/AbstractDataScopeStrategy.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/strategy/AbstractDataScopeStrategy.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/strategy/AbstractDataScopeStrategy.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/strategy/AbstractDataScopeStrategy.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/controller/DepartmentController.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/controller/DepartmentController.java
new file mode 100644
index 00000000..2dc9e5c7
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/controller/DepartmentController.java
@@ -0,0 +1,68 @@
+package net.lab1024.sa.admin.module.system.department.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
+import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentAddForm;
+import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentUpdateForm;
+import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentTreeVO;
+import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO;
+import net.lab1024.sa.admin.module.system.department.service.DepartmentService;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 部门
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-01-12 20:37:48
+ * @Wechat 卓大1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@RestController
+@Tag(name = AdminSwaggerTagConst.System.SYSTEM_DEPARTMENT)
+public class DepartmentController {
+
+ @Resource
+ private DepartmentService departmentService;
+
+ @Operation(summary = "查询部门树形列表 @author 卓大")
+ @GetMapping("/department/treeList")
+ public ResponseDTO> departmentTree() {
+ return departmentService.departmentTree();
+ }
+
+ @Operation(summary = "添加部门 @author 卓大")
+ @PostMapping("/department/add")
+ @SaCheckPermission("system:department:add")
+ public ResponseDTO addDepartment(@Valid @RequestBody DepartmentAddForm createDTO) {
+ return departmentService.addDepartment(createDTO);
+ }
+
+ @Operation(summary = "更新部门 @author 卓大")
+ @PostMapping("/department/update")
+ @SaCheckPermission("system:department:update")
+ public ResponseDTO updateDepartment(@Valid @RequestBody DepartmentUpdateForm updateDTO) {
+ return departmentService.updateDepartment(updateDTO);
+ }
+
+ @Operation(summary = "删除部门 @author 卓大")
+ @GetMapping("/department/delete/{departmentId}")
+ @SaCheckPermission("system:department:delete")
+ public ResponseDTO deleteDepartment(@PathVariable Long departmentId) {
+ return departmentService.deleteDepartment(departmentId);
+ }
+
+ @Operation(summary = "查询部门列表 @author 卓大")
+ @GetMapping("/department/listAll")
+ public ResponseDTO> listAll() {
+ return ResponseDTO.ok(departmentService.listAll());
+ }
+
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/dao/DepartmentDao.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/dao/DepartmentDao.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/dao/DepartmentDao.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/dao/DepartmentDao.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/entity/DepartmentEntity.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/entity/DepartmentEntity.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/entity/DepartmentEntity.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/entity/DepartmentEntity.java
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentAddForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentAddForm.java
new file mode 100644
index 00000000..f7f92c27
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentAddForm.java
@@ -0,0 +1,35 @@
+package net.lab1024.sa.admin.module.system.department.domain.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+/**
+ * 部门 添加表单
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-01-12 20:37:48
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class DepartmentAddForm {
+
+ @Schema(description = "部门名称")
+ @Length(min = 1, max = 50, message = "请输入正确的部门名称(1-50个字符)")
+ @NotNull(message = "请输入正确的部门名称(1-50个字符)")
+ private String name;
+
+ @Schema(description = "排序")
+ @NotNull(message = "排序值")
+ private Integer sort;
+
+ @Schema(description = "部门负责人id")
+ private Long managerId;
+
+ @Schema(description = "上级部门id (可选)")
+ private Long parentId;
+
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentUpdateForm.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentUpdateForm.java
new file mode 100644
index 00000000..a65d2324
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentUpdateForm.java
@@ -0,0 +1,23 @@
+package net.lab1024.sa.admin.module.system.department.domain.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * 部门 更新表单
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-01-12 20:37:48
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Data
+public class DepartmentUpdateForm extends DepartmentAddForm {
+
+ @Schema(description = "部门id")
+ @NotNull(message = "部门id不能为空")
+ private Long departmentId;
+
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentEmployeeTreeVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentEmployeeTreeVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentEmployeeTreeVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentEmployeeTreeVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentTreeVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentTreeVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentTreeVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentTreeVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentVO.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentVO.java
similarity index 100%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentVO.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentVO.java
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/manager/DepartmentCacheManager.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/manager/DepartmentCacheManager.java
similarity index 86%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/manager/DepartmentCacheManager.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/manager/DepartmentCacheManager.java
index 3ed6f350..a53a74e3 100644
--- a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/manager/DepartmentCacheManager.java
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/manager/DepartmentCacheManager.java
@@ -2,6 +2,7 @@ package net.lab1024.sa.admin.module.system.department.manager;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.constant.AdminCacheConst;
import net.lab1024.sa.admin.module.system.department.dao.DepartmentDao;
@@ -10,12 +11,10 @@ import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
-import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -141,13 +140,15 @@ public class DepartmentCacheManager {
return treeVOList;
}
- /**
+ /**
* 构建所有根节点的下级树形结构
- *
+ * 返回值为层序遍历结果
+ * [由于departmentDao中listAll给出数据根据Sort降序 所以同一层中Sort值较大的优先遍历]
*/
- private void recursiveBuildTree(List nodeList, List allDepartmentList) {
+ private List recursiveBuildTree(List nodeList, List allDepartmentList) {
int nodeSize = nodeList.size();
- for (int i = 0; i < nodeSize; i++) {
+ List childIdList = new ArrayList<>();
+ for(int i = 0; i < nodeSize; i++) {
int preIndex = i - 1;
int nextIndex = i + 1;
DepartmentTreeVO node = nodeList.get(i);
@@ -158,16 +159,34 @@ public class DepartmentCacheManager {
node.setNextId(nodeList.get(nextIndex).getDepartmentId());
}
- ArrayList selfAndAllChildrenIdList = Lists.newArrayList();
- selfAndAllChildrenIdList.add(node.getDepartmentId());
- node.setSelfAndAllChildrenIdList(selfAndAllChildrenIdList);
-
List children = getChildren(node.getDepartmentId(), allDepartmentList);
+
+ List tempChildIdList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(children)) {
node.setChildren(children);
- this.recursiveBuildTree(children, allDepartmentList);
+ tempChildIdList = this.recursiveBuildTree(children, allDepartmentList);
}
+
+ if(CollectionUtils.isEmpty(node.getSelfAndAllChildrenIdList())) {
+ node.setSelfAndAllChildrenIdList(
+ new ArrayList<>()
+ );
+ }
+ node.getSelfAndAllChildrenIdList().add(node.getDepartmentId());
+
+ if(CollectionUtils.isNotEmpty(tempChildIdList)) {
+ node.getSelfAndAllChildrenIdList().addAll(tempChildIdList);
+ childIdList.addAll(tempChildIdList);
+ }
+
}
+
+ // 保证本层遍历顺序
+ for(int i = nodeSize - 1; i >= 0; i--) {
+ childIdList.add(0, nodeList.get(i).getDepartmentId());
+ }
+
+ return childIdList;
}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/service/DepartmentService.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/service/DepartmentService.java
new file mode 100644
index 00000000..5f7d1520
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/service/DepartmentService.java
@@ -0,0 +1,190 @@
+package net.lab1024.sa.admin.module.system.department.service;
+
+import jakarta.annotation.Resource;
+import net.lab1024.sa.admin.module.system.department.dao.DepartmentDao;
+import net.lab1024.sa.admin.module.system.department.domain.entity.DepartmentEntity;
+import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentAddForm;
+import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentUpdateForm;
+import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentTreeVO;
+import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO;
+import net.lab1024.sa.admin.module.system.department.manager.DepartmentCacheManager;
+import net.lab1024.sa.admin.module.system.employee.dao.EmployeeDao;
+import net.lab1024.sa.base.common.code.UserErrorCode;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.SmartBeanUtil;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 部门 service
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2022-01-12 20:37:48
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@Service
+public class DepartmentService {
+
+ @Resource
+ private DepartmentDao departmentDao;
+
+ @Resource
+ private EmployeeDao employeeDao;
+
+ @Resource
+ private DepartmentCacheManager departmentCacheManager;
+
+ // ---------------------------- 增加、修改、删除 ----------------------------
+
+ /**
+ * 新增添加部门
+ *
+ */
+
+ public ResponseDTO addDepartment(DepartmentAddForm departmentAddForm) {
+ DepartmentEntity departmentEntity = SmartBeanUtil.copy(departmentAddForm, DepartmentEntity.class);
+ departmentDao.insert(departmentEntity);
+ this.clearCache();
+ return ResponseDTO.ok();
+ }
+
+
+ /**
+ * 更新部门信息
+ *
+ */
+ public ResponseDTO updateDepartment(DepartmentUpdateForm updateDTO) {
+ if (updateDTO.getParentId() == null) {
+ return ResponseDTO.userErrorParam("父级部门id不能为空");
+ }
+ DepartmentEntity entity = departmentDao.selectById(updateDTO.getDepartmentId());
+ if (entity == null) {
+ return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
+ }
+ DepartmentEntity departmentEntity = SmartBeanUtil.copy(updateDTO, DepartmentEntity.class);
+ departmentEntity.setSort(updateDTO.getSort());
+ departmentDao.updateById(departmentEntity);
+ this.clearCache();
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 根据id删除部门
+ * 1、需要判断当前部门是否有子部门,有子部门则不允许删除
+ * 2、需要判断当前部门是否有员工,有员工则不能删除
+ *
+ */
+ public ResponseDTO deleteDepartment(Long departmentId) {
+ DepartmentEntity departmentEntity = departmentDao.selectById(departmentId);
+ if (null == departmentEntity) {
+ return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
+ }
+ // 是否有子级部门
+ int subDepartmentNum = departmentDao.countSubDepartment(departmentId);
+ if (subDepartmentNum > 0) {
+ return ResponseDTO.userErrorParam("请先删除子级部门");
+ }
+
+ // 是否有未删除员工
+ int employeeNum = employeeDao.countByDepartmentId(departmentId, Boolean.FALSE);
+ if (employeeNum > 0) {
+ return ResponseDTO.userErrorParam("请先删除部门员工");
+ }
+ departmentDao.deleteById(departmentId);
+ // 清除缓存
+ this.clearCache();
+ return ResponseDTO.ok();
+ }
+
+ /**
+ * 清除自身以及下级的id列表缓存
+ */
+ private void clearCache() {
+ departmentCacheManager.clearCache();
+ }
+
+ // ---------------------------- 查询 ----------------------------
+
+ /**
+ * 获取部门树形结构
+ */
+ public ResponseDTO> departmentTree() {
+ List treeVOList = departmentCacheManager.getDepartmentTree();
+ return ResponseDTO.ok(treeVOList);
+ }
+
+
+ /**
+ * 自身以及所有下级的部门id列表
+ *
+ */
+ public List selfAndChildrenIdList(Long departmentId) {
+ return departmentCacheManager.getDepartmentSelfAndChildren(departmentId);
+ }
+
+
+ /**
+ * 获取所有部门
+ *
+ */
+ public List listAll() {
+ return departmentCacheManager.getDepartmentList();
+ }
+
+
+ /**
+ * 获取部门
+ *
+ */
+ public DepartmentVO getDepartmentById(Long departmentId) {
+ return departmentCacheManager.getDepartmentMap().get(departmentId);
+ }
+
+ /**
+ * 获取部门路径:/公司/研发部/产品组
+ */
+ public String getDepartmentPath(Long departmentId) {
+ return departmentCacheManager.getDepartmentPathMap().get(departmentId);
+ }
+
+ /**
+ * 查询全部父级部门(不包含自己)
+ *
+ */
+ public List queryAllParentDepartment(Long departmentId) {
+ List list = new ArrayList<>();
+
+ Map departmentMap = departmentCacheManager.getDepartmentMap();
+ DepartmentVO departmentVO = departmentMap.get(departmentId);
+ while (departmentVO != null) {
+ list.add(departmentVO);
+ departmentVO = departmentMap.get(departmentVO.getParentId());
+ }
+ Collections.reverse(list);
+ return list;
+ }
+
+ /**
+ * 查询全部父级部门(不包含自己)
+ *
+ */
+ public List queryAllParentDepartmentIdList(Long departmentId) {
+ List list = new ArrayList<>();
+
+ Map departmentMap = departmentCacheManager.getDepartmentMap();
+ DepartmentVO departmentVO = departmentMap.get(departmentId);
+ while (departmentVO != null) {
+ list.add(departmentVO.getDepartmentId());
+ departmentVO = departmentMap.get(departmentVO.getParentId());
+ }
+ Collections.reverse(list);
+ return list;
+ }
+
+}
diff --git a/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/controller/EmployeeController.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/controller/EmployeeController.java
new file mode 100644
index 00000000..6393827a
--- /dev/null
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/controller/EmployeeController.java
@@ -0,0 +1,129 @@
+package net.lab1024.sa.admin.module.system.employee.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
+import net.lab1024.sa.admin.module.system.employee.domain.form.*;
+import net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO;
+import net.lab1024.sa.admin.module.system.employee.service.EmployeeService;
+import net.lab1024.sa.base.common.domain.PageResult;
+import net.lab1024.sa.base.common.domain.ResponseDTO;
+import net.lab1024.sa.base.common.util.SmartRequestUtil;
+import net.lab1024.sa.base.module.support.apiencrypt.annotation.ApiDecrypt;
+import net.lab1024.sa.base.module.support.securityprotect.service.Level3ProtectConfigService;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 员工
+ *
+ * @Author 1024创新实验室-主任: 卓大
+ * @Date 2021-12-09 22:57:49
+ * @Wechat zhuoda1024
+ * @Email lab1024@163.com
+ * @Copyright 1024创新实验室
+ */
+@RestController
+@Tag(name = AdminSwaggerTagConst.System.SYSTEM_EMPLOYEE)
+public class EmployeeController {
+
+ @Resource
+ private EmployeeService employeeService;
+
+ @Resource
+ private Level3ProtectConfigService level3ProtectConfigService;
+
+ @PostMapping("/employee/query")
+ @Operation(summary = "员工管理查询 @author 卓大")
+ public ResponseDTO> query(@Valid @RequestBody EmployeeQueryForm query) {
+ return employeeService.queryEmployee(query);
+ }
+
+ @Operation(summary = "添加员工(返回添加员工的密码) @author 卓大")
+ @PostMapping("/employee/add")
+ @SaCheckPermission("system:employee:add")
+ public ResponseDTO addEmployee(@Valid @RequestBody EmployeeAddForm employeeAddForm) {
+ return employeeService.addEmployee(employeeAddForm);
+ }
+
+ @Operation(summary = "更新员工 @author 卓大")
+ @PostMapping("/employee/update")
+ @SaCheckPermission("system:employee:update")
+ public ResponseDTO updateEmployee(@Valid @RequestBody EmployeeUpdateForm employeeUpdateForm) {
+ return employeeService.updateEmployee(employeeUpdateForm);
+ }
+
+ @Operation(summary = "更新登录人信息 @author 善逸")
+ @PostMapping("/employee/update/login")
+ public ResponseDTO updateByLogin(@Valid @RequestBody EmployeeUpdateForm employeeUpdateForm) {
+ employeeUpdateForm.setEmployeeId(SmartRequestUtil.getRequestUserId());
+ return employeeService.updateEmployee(employeeUpdateForm);
+ }
+
+ @Operation(summary = "更新登录人头像 @author 善逸")
+ @PostMapping("/employee/update/avatar")
+ public ResponseDTO updateAvatar(@Valid @RequestBody EmployeeUpdateAvatarForm employeeUpdateAvatarForm) {
+ employeeUpdateAvatarForm.setEmployeeId(SmartRequestUtil.getRequestUserId());
+ return employeeService.updateAvatar(employeeUpdateAvatarForm);
+ }
+
+ @Operation(summary = "更新员工禁用/启用状态 @author 卓大")
+ @GetMapping("/employee/update/disabled/{employeeId}")
+ @SaCheckPermission("system:employee:disabled")
+ public ResponseDTO updateDisableFlag(@PathVariable Long employeeId) {
+ return employeeService.updateDisableFlag(employeeId);
+ }
+
+ @Operation(summary = "批量删除员工 @author 卓大")
+ @PostMapping("/employee/update/batch/delete")
+ @SaCheckPermission("system:employee:delete")
+ public ResponseDTO batchUpdateDeleteFlag(@RequestBody List employeeIdList) {
+ return employeeService.batchUpdateDeleteFlag(employeeIdList);
+ }
+
+ @Operation(summary = "批量调整员工部门 @author 卓大")
+ @PostMapping("/employee/update/batch/department")
+ @SaCheckPermission("system:employee:department:update")
+ public ResponseDTO batchUpdateDepartment(@Valid @RequestBody EmployeeBatchUpdateDepartmentForm batchUpdateDepartmentForm) {
+ return employeeService.batchUpdateDepartment(batchUpdateDepartmentForm);
+ }
+
+ @Operation(summary = "修改密码 @author 卓大")
+ @PostMapping("/employee/update/password")
+ @ApiDecrypt
+ public ResponseDTO updatePassword(@Valid @RequestBody EmployeeUpdatePasswordForm updatePasswordForm) {
+ updatePasswordForm.setEmployeeId(SmartRequestUtil.getRequestUserId());
+ return employeeService.updatePassword(SmartRequestUtil.getRequestUser(), updatePasswordForm);
+ }
+
+ @Operation(summary = "获取密码复杂度 @author 卓大")
+ @GetMapping("/employee/getPasswordComplexityEnabled")
+ @ApiDecrypt
+ public ResponseDTO getPasswordComplexityEnabled() {
+ return ResponseDTO.ok(level3ProtectConfigService.isPasswordComplexityEnabled());
+ }
+
+ @Operation(summary = "重置员工密码 @author 卓大")
+ @GetMapping("/employee/update/password/reset/{employeeId}")
+ @SaCheckPermission("system:employee:password:reset")
+ public ResponseDTO resetPassword(@PathVariable Long employeeId) {
+ return employeeService.resetPassword(employeeId);
+ }
+
+ @Operation(summary = "查询员工-根据部门id @author 卓大")
+ @GetMapping("/employee/getAllEmployeeByDepartmentId/{departmentId}")
+ public ResponseDTO> getAllEmployeeByDepartmentId(@PathVariable Long departmentId) {
+ return employeeService.getAllEmployeeByDepartmentId(departmentId, Boolean.FALSE);
+ }
+
+ @Operation(summary = "查询所有员工 @author 卓大")
+ @GetMapping("/employee/queryAll")
+ public ResponseDTO> queryAllEmployee(@RequestParam(value = "disabledFlag", required = false) Boolean disabledFlag) {
+ return employeeService.queryAllEmployee(disabledFlag);
+ }
+
+}
diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/dao/EmployeeDao.java b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/dao/EmployeeDao.java
similarity index 95%
rename from smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/dao/EmployeeDao.java
rename to smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/dao/EmployeeDao.java
index 78d75521..1003af00 100644
--- a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/dao/EmployeeDao.java
+++ b/smart-admin-api-java17-springboot3/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/dao/EmployeeDao.java
@@ -66,7 +66,7 @@ public interface EmployeeDao extends BaseMapper