初始化博客后端

This commit is contained in:
2026-05-14 16:35:50 +08:00
commit 84e70aff12
646 changed files with 44291 additions and 0 deletions

34
.gitignore vendored Normal file
View File

@@ -0,0 +1,34 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
velocity.log
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
.DS_Store
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/

113
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,113 @@
variables: #变量
#网关
MES_BACK_CONTAINER: "mowen-blog-admin-api"
MES_BACK_IMAGE: "mowen-blog-admin-api"
MES_BACK_PORT: 8080
MAVEN_OPTS: "-Djava.awt.headless=true -Dmaven.repo.local=/mydata/jun/back_project/.m2" #指定maven的存储目录
cache:
paths:
- /mydata/jun/back_project/.m2
stages:
- build
- deploy
build-dev:jdk17:
stage: build
script:
- echo "=============== 开始编译打包任务 ==============="
- mvn clean package -DskipTests -P dev
#服务
- mkdir -p /mydata/mowen-blog/back_project/app
- cp Dockerfile /mydata/mowen-blog/back_project/app
- cp mes-admin/target/mowen-admin-dev-1.0.0.jar /mydata/mowen-blog/back_project/app
artifacts:
paths:
- build/
only:
- dev #当有代码合到主干时触发这个job
tags:
- blog-dev
image: moshangjunmowen/maven-jdk17:v3
build-test:jdk17:
stage: build
script:
- echo "=============== 开始编译打包任务 ==============="
- mvn clean package -Dmaven.test.skip=true -P test
#服务
- mkdir -p /mydata/mowen-blog/back_project/app
- cp Dockerfile /mydata/mowen-blog/back_project/app
- cp mes-admin/target/mowen-admin-test-1.0.0.jar /mydata/mowen-blog/back_project/app
artifacts:
paths:
- build/
only:
- test #当有代码合到主干时触发这个job
tags:
- mes-test
image: moshangjunmowen/maven-jdk17:v3
build-prod:jdk17:
stage: build
script:
- echo "=============== 开始编译打包任务 ==============="
- mvn clean package -Dmaven.test.skip=true -P prod
#服务
- mkdir -p /mydata/mowen-blog/back_project/app
- cp Dockerfile /mydata/mowen-blog/back_project/app
- cp mes-admin/target/mowen-admin-prod-1.0.0.jar /mydata/mowen-blog/back_project/app
artifacts:
paths:
- build/
only:
- main #当有代码合到主干时触发这个job
tags:
- pioneer-mes-prod
image: moshangjunmowen/maven-jdk17:v3
deploy-dev:jdk17:
stage: deploy
image: docker:29.4.3 #目的是为了在docker环境下的runner能执行docker命令
script:
- echo "=============== 开始部署应用 ==============="
- docker ps -a|grep $MES_BACK_CONTAINER && docker stop $MES_BACK_CONTAINER && docker rm $MES_BACK_CONTAINER || echo "not exist"
- docker images |grep $MES_BACK_IMAGE && docker rmi -f $MES_BACK_IMAGE || echo "not exist"
- docker build --build-arg JAR_FILE=mowen-admin-dev-1.0.0.jar -t $MES_BACK_IMAGE /mydata/mowen-blog/back_project/app
- docker run -d --restart=always --network=host --log-opt max-size=50m --log-opt max-file=3 --name $MES_BACK_CONTAINER $MES_BACK_IMAGE
only:
- dev #当有代码合到主干时触发这个job
tags:
- dev
deploy-test:jdk17:
stage: deploy
image: docker:29.4.3 #目的是为了在docker环境下的runner能执行docker命令
script:
- echo "=============== 开始部署应用 ==============="
- docker ps -a|grep $MES_BACK_CONTAINER && docker stop $MES_BACK_CONTAINER && docker rm $MES_BACK_CONTAINER || echo "not exist"
- docker images |grep $MES_BACK_IMAGE && docker rmi -f $MES_BACK_IMAGE || echo "not exist"
- docker build --build-arg JAR_FILE=mowen-admin-test-1.0.0.jar -t $MES_BACK_IMAGE /mydata/mowen-blog/back_project/app
- docker run -d --restart=always --network=host --log-opt max-size=50m --log-opt max-file=3 --name $MES_BACK_CONTAINER $MES_BACK_IMAGE
only:
- test #当有代码合到主干时触发这个job
tags:
- mes-test
deploy-prod:jdk17:
stage: deploy
image: docker:29.4.3 #目的是为了在docker环境下的runner能执行docker命令
script:
#服务
- docker ps -a|grep $MES_BACK_CONTAINER && docker stop $MES_BACK_CONTAINER && docker rm $MES_BACK_CONTAINER || echo "not exist"
- docker images |grep $MES_BACK_IMAGE && docker rmi -f $MES_BACK_IMAGE || echo "not exist"
- docker build --build-arg JAR_FILE=mowen-admin-prod-1.0.0.jar -t $MES_BACK_IMAGE /mydata/mowen-blog/back_project/app
- docker run -d --restart=always --network=host --log-opt max-size=50m --log-opt max-file=5 --name $MES_BACK_CONTAINER $MES_BACK_IMAGE
only:
- main #当有代码合到主干时触发这个job
tags:
- pioneer-mes-prod

15
Dockerfile Normal file
View File

@@ -0,0 +1,15 @@
# 使用你自建的精简 JRE 基础镜像(非 root, JVM 优化, 时区等已配置)
FROM moshangjunmowen/jdk-jre:v17.0.19
ARG JAR_FILE
LABEL maintainer="moshangjunmowen@foxmail.com"
# 复制 JAR 并设置所有权给非 root 用户 appuser (uid=1001)
COPY --chown=appuser:appuser ${JAR_FILE} /app/app.jar
# 通过追加 JAVA_TOOL_OPTIONS 来安全注入额外 JVM 参数
# 注意:基础镜像已设定 -Xmx1024M -Xms256M这里合并不会覆盖
ENV JAVA_TOOL_OPTIONS="-Djava.security.egd=file:/dev/./urandom ${JAVA_TOOL_OPTIONS}"
# 保持基础镜像的 ENTRYPOINT ["java", "-jar"],只需指定 jar 路径
CMD ["/app/app.jar"]

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 1024-lab
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

83
README.md Normal file
View File

@@ -0,0 +1,83 @@
### **SmartAdmin**
**SmartAdmin****中国·洛阳** [陌上君莫问](https://www.1024lab.net/) 基于SpringBoot2/3+Sa-Token+Mybatis-Plus 和 Vue3+Ant Design Vue+Uni-App+Uni-UI并以 <font color="#DC143C">**「高质量代码」为核心,「简洁、高效、安全」**</font>的快速开发平台。
**<font color="#DC143C">国内首个满足《网络安全-三级等保》、《数据安全》</font>** 功能要求,支持登录限制、接口国产加解密、数据脱敏等一系列安全要求。
**<font color="#DC143C">支持国产数据库【达梦、金仓、南大通用、海量数据、神州通用、OceanBase、GaussDB 高斯、阿里PolarDB、GoldenDB】等主流数据库【Mysql、PostgreSQL、SqlServer、Oracle】等</font>**
**<font color="#DC143C">前端提供JavaScript和TypeScript双版本后端提供Java8+SpringBoot2.X和Java17+SpringBoot3.X 双版本</font>**。
同时 **<font color="#DC143C">重磅开源</font>** 开源六年来 **<font color="#DC143C">千余家企业验证过且正在使用</font>** 的代码规范: **<font color="#DC143C">《高质量代码思想》、《Vue3规范》、《Java规范》</font>** ,让大家在这浮躁的世界里感受到一股把代码写好的清流!同时又能节省大量时间,减少加班,快乐工作,保持谦逊,保持学习,**<font color="#DC143C">热爱代码,更热爱生活</font>**
### **技术体系**
- 前端JavaScript/TypeScript + Vue3 + Vite5 + Pinia + Ant Design Vue 4.X
- 移动端uniapp (vue3版本) + uni-ui + 同时支持APP、小程序、H5
- 后端Java8/17 + SpringBoot2/3 + Sa Token + Mybatis-plus + 主流数据库/国产数据库
- 官方文档:[https://smartadmin.vip](https://smartadmin.vip)
- 电脑在线预览:[https://preview.smartadmin.vip](https://preview.smartadmin.vip)
- 移动端在线预览:[https://app.smartadmin.vip](https://app.smartadmin.vip/#/pages/login/login)
### **理念与思想**
- 我们分享的不是徒劳无功的各种功能,而是必须有的功能,如:数据变动记录、系统说明文档、版本更新记录、意见反馈、日志、心跳、单号生成器等等。
- 我们分享的还有经过上百家公司验证过的前端、后端、vue3等代码规范好的规范能让我敲下的每行代码更铿锵有力
- **我们推崇高质量的代码,身为开发,代码即利剑,键盘上一套行云流水,宛如侠客,事了拂衣去,深藏身与名。**
- **我们推崇团队的高度配合默契、互相帮助,从不加班,而不是一看到别人的代码就头皮发麻,留其 [996.ICU](https://baike.baidu.com/item/996.ICU) 加班。**
- **我们主动思考,保持谦逊,保持学习,热爱代码,更热爱生活。**
- **<font color="#DC143C">我们希望你希望你能花费3分钟认真阅读下面的每一个点让你感受从未有过的技术体验</font>**
### **功能亮点图**
<table>
<tr>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/login/login-bg.png"/></td>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/cut/home.png"/></td>
</tr>
<tr>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/login/login-fail-log.png"/></td>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/cut/doc.png"/></td>
</tr>
<tr>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/cut/code.png"/></td>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/cut/git-diff.png"/></td>
</tr>
<tr>
<td><img src="https://img.smartadmin.1024lab.net/smart-app/app1.png"/></td>
<td><img src="https://img.smartadmin.1024lab.net/smart-app/app2.png"/></td>
</tr>
<tr>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/cut/front.png"/></td>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/cut/back.png"/></td>
</tr>
</table>
### **功能亮点**
- **<font color="#DC143C">安全体系</font>**:满足国家三级等保要求,如双因子登录、密码加密、密码复杂度要求、登录错误次数锁定、登录超时退出、数据脱敏等网络安全和数据安全功能
- **<font color="#DC143C">接口加解密</font>**:支持请求参数和返回内容进行加解密操作,支持国产加密算法和其他国外加密算法
- **表格自定义列**:支持用户自定义列,并能将用户自定义列持久化到数据库
- **数据变更记录**支持基于git diff插件的数据变更记录查看数据变化更直观方便
- **在线文档**:支持右侧帮助文档(类似阿里云控制台右侧帮助文档效果)、支持意见反馈、版本记录 等功能
- **OA办公**:公司信息(发票、银行、员工等)、通知公告(阅读记录、次数等)
- **日志、监控**服务器心跳日志、登录日志、操作日志IP、浏览器、操作系统等设备信息
- **系统功能**:员工、部门、角色、权限、菜单、水印、文件管理、系统参数、数据字典、单号生成 等
- **代码生成** 基于每个表的配置、在线预览代码、下载 等
- **以上只是一些举例,更多灿若繁星的惊喜和细节,等待着你的发现!**[SmartAdmin 业内独有功能亮点](https://smartadmin.vip)
### **代码亮点**
- **【前端-双版本】:** 提供 js 和 ts 双版本,目录结构及其清晰
- **【前端-常量维护】:** vue-enum拒绝出现魔法数字常量枚举不可维护的现象
- **【前端-命名】:** 业内最好的api、常量等命名和写法
- **【前端-多环境支持】:** 独有的本地、开发、测试、预发布、生产 5个env环境配置文件
- **【前端-layout代码】** 业内代码最清晰的layout布局写法小白都能看懂
- **【前端-main.js】** 业内可能只有我们把main.js中的router加载方式写对了
- ----华丽前后端分割线----
- **【后端-独有目录结构】:** 业内独有的高质量的 Java代码分包结构适合大、中、小型项目结构非常清晰
- **【后端-公共配置文件】:** 业内独有的共用配置文件维护,简化共同配置
- **【后端-返回码维护】:** 业内独创的请求返回码维护,非常值得一看
- **【后端-四层架构】:** 四层架构controller, service, manager, dao为什么要有四层
- **【后端-多环境】:** maven多环境开发、测试、预发布、生产 环境配置
- **【后端-系统钩子】:** smart-reload为系统预留钩子动态加载在不重启程序前提下执行一些代码
- 以上只是沧海一粟,更多的细节等待你的发现![去查看](https://smartadmin.vip)

46
mowen-admin/pom.xml Normal file
View File

@@ -0,0 +1,46 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>online.junmowen.blog</groupId>
<artifactId>mowen-parent</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>mowen-admin</artifactId>
<packaging>jar</packaging>
<name>mowen-admin</name>
<description>莫问博客后台管理系统 - admin模块</description>
<dependencies>
<dependency>
<groupId>online.junmowen.blog</groupId>
<artifactId>mowen-base</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>online.junmowen.blog.admin.AdminApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,40 @@
package online.junmowen.blog.admin;
import online.junmowen.blog.base.listener.Ip2RegionListener;
import online.junmowen.blog.base.listener.LogVariableListener;
import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* SmartAdmin 项目启动类
*
* @Author 陌上君莫问-主任:卓大
* @Date 2022-08-29 21:00:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@EnableCaching
@EnableScheduling
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
@ComponentScan(AdminApplication.COMPONENT_SCAN)
@MapperScan(value = AdminApplication.COMPONENT_SCAN, annotationClass = Mapper.class)
@SpringBootApplication(exclude = {UserDetailsServiceAutoConfiguration.class})
public class AdminApplication {
public static final String COMPONENT_SCAN = "online.junmowen.blog";
public static void main(String[] args) {
SpringApplication application = new SpringApplication(AdminApplication.class);
// 添加 日志监听器,使 log4j2-spring.xml 可以间接读取到配置文件的属性
application.addListeners(new LogVariableListener(), new Ip2RegionListener());
application.run(args);
}
}

View File

@@ -0,0 +1,41 @@
package online.junmowen.blog.admin.config;
import jakarta.annotation.Resource;
import online.junmowen.blog.admin.interceptor.AdminInterceptor;
import online.junmowen.blog.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 陌上君莫问
* @Date 2021-09-02 20:21:10
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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/");
}
}

View File

@@ -0,0 +1,28 @@
package online.junmowen.blog.admin.config;
import online.junmowen.blog.base.module.support.operatelog.core.OperateLogAspect;
import online.junmowen.blog.base.module.support.operatelog.core.OperateLogConfig;
import org.springframework.context.annotation.Configuration;
/**
* 操作日志切面 配置
*
* @Author 陌上君莫问
* @Date 2022-05-30 21:22:12
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Configuration
public class OperateLogAspectConfig extends OperateLogAspect{
/**
* 配置信息
*/
@Override
public OperateLogConfig getOperateLogConfig() {
return OperateLogConfig.builder().corePoolSize(1).queueCapacity(10000).build();
}
}

View File

@@ -0,0 +1,68 @@
package online.junmowen.blog.admin.constant;
import online.junmowen.blog.base.constant.CacheKeyConst;
/**
* 缓存 key
*
* @Author 陌上君莫问-主任:卓大
* @Date 2022-01-07 18:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
public class AdminCacheConst extends CacheKeyConst {
public static class Department {
/**
* 部门列表
*/
public static final String DEPARTMENT_LIST_CACHE = "department_list_cache";
/**
* 部门树
*/
public static final String DEPARTMENT_TREE_CACHE = "department_tree_cache";
/**
* 某个部门以及下级的id列表
*/
public static final String DEPARTMENT_SELF_CHILDREN_CACHE = "department_self_children_cache";
/**
* 部门路径 缓存
*/
public static final String DEPARTMENT_PATH_CACHE = "department_path_cache";
}
/**
* 分类相关缓存
*/
public static class Category {
public static final String CATEGORY_ENTITY = "category_cache";
public static final String CATEGORY_SUB = "category_sub_cache";
public static final String CATEGORY_TREE = "category_tree_cache";
}
/**
* 登录相关
*/
public static class Login {
/**
* 请求用户信息
*/
public static final String REQUEST_EMPLOYEE = "login_request_employee";
/**
* 请求用户信息权限
*/
public static final String USER_PERMISSION = "login_user_permission";
}
}

View File

@@ -0,0 +1,17 @@
package online.junmowen.blog.admin.constant;
import online.junmowen.blog.base.constant.RedisKeyConst;
/**
* redis key 常量类
*
* @Author 陌上君莫问-主任:卓大
* @Date 2022-01-07 18:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
public class AdminRedisKeyConst extends RedisKeyConst {
}

View File

@@ -0,0 +1,59 @@
package online.junmowen.blog.admin.constant;
import online.junmowen.blog.base.constant.SwaggerTagConst;
/**
* swagger
*
* @Author 陌上君莫问
* @Date 2022-01-07 18:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
public class AdminSwaggerTagConst extends SwaggerTagConst {
public static class Business {
public static final String MANAGER_CATEGORY = "ERP进销存-分类管理";
public static final String MANAGER_GOODS = "ERP进销存-商品管理";
public static final String OA_BANK = "OA办公-银行卡信息";
public static final String OA_ENTERPRISE = "OA办公-企业";
public static final String OA_INVOICE = "OA办公-发票信息";
public static final String OA_NOTICE = "OA办公-通知公告";
}
public static class System {
public static final String SYSTEM_LOGIN = "系统-员工登录";
public static final String SYSTEM_EMPLOYEE = "系统-员工管理";
public static final String SYSTEM_DEPARTMENT = "系统-部门管理";
public static final String SYSTEM_MENU = "系统-菜单";
public static final String SYSTEM_DATA_SCOPE = "系统-系统-数据范围";
public static final String SYSTEM_ROLE = "系统-角色";
public static final String SYSTEM_ROLE_DATA_SCOPE = "系统-角色-数据范围";
public static final String SYSTEM_ROLE_EMPLOYEE = "系统-角色-员工";
public static final String SYSTEM_ROLE_MENU = "系统-角色-菜单";
public static final String SYSTEM_POSITION = "系统-职务管理";
public static final String SYSTEM_MESSAGE = "系统-消息";
}
}

View File

@@ -0,0 +1,141 @@
package online.junmowen.blog.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.SaAnnotationStrategy;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import online.junmowen.blog.admin.module.system.login.domain.RequestEmployee;
import online.junmowen.blog.admin.module.system.login.service.LoginService;
import online.junmowen.blog.base.common.annoation.NoNeedLogin;
import online.junmowen.blog.base.common.code.SystemErrorCode;
import online.junmowen.blog.base.common.code.UserErrorCode;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.base.common.util.SmartRequestUtil;
import online.junmowen.blog.base.common.util.SmartResponseUtil;
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 陌上君莫问-主任:卓大
* @Date 2023/7/26 20:20:33
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>Since 2012
*/
@Component
@Slf4j
public class AdminInterceptor implements HandlerInterceptor {
@Resource
private LoginService loginService;
@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();
String 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) {
updateActiveTimeout(requestEmployee);
SmartRequestUtil.setRequestUser(requestEmployee);
return true;
}
if (requestEmployee == null) {
SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID));
return false;
}
// 更新活跃
updateActiveTimeout(requestEmployee);
// --------------- 第三步: 校验 权限 ---------------
SmartRequestUtil.setRequestUser(requestEmployee);
if (SaAnnotationStrategy.instance.isAnnotationPresent.apply(method, SaIgnore.class)) {
return true;
}
// 如果是超级管理员的话,不需要校验权限
if (requestEmployee.getAdministratorFlag()) {
return true;
}
SaAnnotationStrategy.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;
}
/**
* 更新活跃时间
*/
private void updateActiveTimeout(RequestEmployee requestEmployee) {
if (requestEmployee == null) {
return;
}
StpUtil.updateLastActiveToNow();
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 清除上下文
SmartRequestUtil.remove();
}
}

View File

@@ -0,0 +1,36 @@
package online.junmowen.blog.admin.module.business.category.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import online.junmowen.blog.base.common.enumeration.BaseEnum;
/**
* 分类类型 枚举
*
* @Author 陌上君莫问
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@AllArgsConstructor
@Getter
public enum CategoryTypeEnum implements BaseEnum {
/**
* 1 商品
*/
GOODS(1, "商品"),
/**
* 2 自定义
*/
CUSTOM(2, "自定义"),
;
private final Integer value;
private final String desc;
}

View File

@@ -0,0 +1,69 @@
package online.junmowen.blog.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 online.junmowen.blog.admin.constant.AdminSwaggerTagConst;
import online.junmowen.blog.admin.module.business.category.domain.form.CategoryAddForm;
import online.junmowen.blog.admin.module.business.category.domain.form.CategoryTreeQueryForm;
import online.junmowen.blog.admin.module.business.category.domain.form.CategoryUpdateForm;
import online.junmowen.blog.admin.module.business.category.domain.vo.CategoryTreeVO;
import online.junmowen.blog.admin.module.business.category.domain.vo.CategoryVO;
import online.junmowen.blog.admin.module.business.category.service.CategoryService;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 类目
*
* @Author 陌上君莫问
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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<String> add(@RequestBody @Valid CategoryAddForm addForm) {
return categoryService.add(addForm);
}
@Operation(summary = "更新类目 @author 胡克")
@PostMapping("/category/update")
@SaCheckPermission("category:update")
public ResponseDTO<String> update(@RequestBody @Valid CategoryUpdateForm updateForm) {
return categoryService.update(updateForm);
}
@Operation(summary = "查询类目详情 @author 胡克")
@GetMapping("/category/{categoryId}")
public ResponseDTO<CategoryVO> queryDetail(@PathVariable Long categoryId) {
return categoryService.queryDetail(categoryId);
}
@Operation(summary = "查询类目层级树 @author 胡克")
@PostMapping("/category/tree")
@SaCheckPermission("category:tree")
public ResponseDTO<List<CategoryTreeVO>> queryTree(@RequestBody @Valid CategoryTreeQueryForm queryForm) {
return categoryService.queryTree(queryForm);
}
@Operation(summary = "删除类目 @author 胡克")
@GetMapping("/category/delete/{categoryId}")
@SaCheckPermission("category:delete")
public ResponseDTO<String> delete(@PathVariable Long categoryId) {
return categoryService.delete(categoryId);
}
}

View File

@@ -0,0 +1,61 @@
package online.junmowen.blog.admin.module.business.category.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import online.junmowen.blog.admin.module.business.category.constant.CategoryTypeEnum;
import online.junmowen.blog.admin.module.business.category.domain.entity.CategoryEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 类目 dao
*
* @Author 陌上君莫问
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Mapper
public interface CategoryDao extends BaseMapper<CategoryEntity> {
/**
* 根据父级id 类型 查询子类
*
* @param parentIdList 父级id集合
* @param deletedFlag 删除标识
* @return 列表
*/
List<CategoryEntity> queryByParentId(@Param("parentIdList") List<Long> parentIdList,
@Param("deletedFlag") Boolean deletedFlag);
/**
* 根据父级id 类型 查询子类
*
* @param parentIdList 父级id集合
* @param categoryType {@link CategoryTypeEnum}
* @param deletedFlag 删除标识
* @return 列表
*/
List<CategoryEntity> queryByParentIdAndType(@Param("parentIdList") List<Long> parentIdList,
@Param("categoryType") Integer categoryType,
@Param("deletedFlag") Boolean deletedFlag);
/**
* 某个类型的所有
*/
List<CategoryEntity> queryByType(@Param("categoryType") Integer categoryType,
@Param("deletedFlag") Boolean deletedFlag);
/**
* 根据类型和id查询
*/
CategoryEntity selectByTypeAndId(@Param("categoryType") Integer categoryType, @Param("categoryId") Long categoryId);
/**
* 查看类目 具体条件 看sql
*/
CategoryEntity selectOne(CategoryEntity entity);
}

View File

@@ -0,0 +1,43 @@
package online.junmowen.blog.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 online.junmowen.blog.admin.module.business.category.constant.CategoryTypeEnum;
import online.junmowen.blog.base.common.swagger.SchemaEnum;
import online.junmowen.blog.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;
}

View File

@@ -0,0 +1,26 @@
package online.junmowen.blog.admin.module.business.category.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 类目 基础属性 DTO 类
*
* @author 胡克
* @date 2021/1/20 16:17
*/
@Data
public class CategorySimpleDTO {
@Schema(description = "类目id")
private Long categoryId;
@Schema(description = "类目名称")
private String categoryName;
@Schema(description = "类目层级全称")
private String categoryFullName;
@Schema(description = "父级id")
private Long parentId;
}

View File

@@ -0,0 +1,70 @@
package online.junmowen.blog.admin.module.business.category.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import online.junmowen.blog.admin.module.business.category.constant.CategoryTypeEnum;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 类目 实体类
*
* @Author 陌上君莫问
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
@TableName("t_category")
public class CategoryEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.AUTO)
private Long categoryId;
/**
* 类目名称
*/
private String categoryName;
/**
* 类目 类型
*
* @see CategoryTypeEnum
*/
private Integer categoryType;
/**
* 父级类目id
*/
private Long parentId;
/**
* 是否禁用
*/
private Boolean disabledFlag;
/**
* 排序
*/
private Integer sort;
/**
* 删除状态
*/
private Boolean deletedFlag;
/**
* 备注
*/
private String remark;
private LocalDateTime updateTime;
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,47 @@
package online.junmowen.blog.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 online.junmowen.blog.admin.module.business.category.constant.CategoryTypeEnum;
import online.junmowen.blog.base.common.swagger.SchemaEnum;
import online.junmowen.blog.base.common.validator.enumeration.CheckEnum;
import org.hibernate.validator.constraints.Length;
/**
* 类目 添加
*
* @Author 陌上君莫问
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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;
}

View File

@@ -0,0 +1,25 @@
package online.junmowen.blog.admin.module.business.category.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import online.junmowen.blog.admin.module.business.category.constant.CategoryTypeEnum;
import online.junmowen.blog.base.common.swagger.SchemaEnum;
/**
* 类目 层级树查询
*
* @Author 陌上君莫问
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class CategoryTreeQueryForm {
@SchemaEnum(desc = "分类类型|可选", value = CategoryTypeEnum.class)
private Integer categoryType;
@Schema(description = "父级类目id|可选")
private Long parentId;
}

View File

@@ -0,0 +1,22 @@
package online.junmowen.blog.admin.module.business.category.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 类目 更新
*
* @Author 陌上君莫问
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class CategoryUpdateForm extends CategoryAddForm {
@Schema(description = "类目id")
@NotNull(message = "类目id不能为空")
private Long categoryId;
}

View File

@@ -0,0 +1,43 @@
package online.junmowen.blog.admin.module.business.category.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 类目 层级树 vo
*
* @Author 陌上君莫问
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class CategoryTreeVO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "类目id")
private Long categoryId;
@Schema(description = "类目名称")
private String categoryName;
@Schema(description = "类目层级全称")
private String categoryFullName;
@Schema(description = "父级id")
private Long parentId;
@Schema(description = "类目id")
private Long value;
@Schema(description = "类目名称")
private String label;
@Schema(description = "子类")
private List<CategoryTreeVO> children;
}

View File

@@ -0,0 +1,46 @@
package online.junmowen.blog.admin.module.business.category.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import online.junmowen.blog.admin.module.business.category.constant.CategoryTypeEnum;
import online.junmowen.blog.base.common.swagger.SchemaEnum;
import java.time.LocalDateTime;
/**
* 类目
*
* @Author 陌上君莫问
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class CategoryVO {
@Schema(description = "类目名称", required = true)
private String categoryName;
@SchemaEnum(desc = "分类类型", value = CategoryTypeEnum.class)
private Integer categoryType;
@Schema(description = "父级类目id|可选")
private Long parentId;
@Schema(description = "排序|可选")
private Integer sort;
@Schema(description = "备注|可选")
private String remark;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "类目id")
private Long categoryId;
private LocalDateTime updateTime;
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,113 @@
package online.junmowen.blog.admin.module.business.category.manager;
import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import online.junmowen.blog.admin.constant.AdminCacheConst;
import online.junmowen.blog.admin.module.business.category.dao.CategoryDao;
import online.junmowen.blog.admin.module.business.category.domain.entity.CategoryEntity;
import online.junmowen.blog.admin.module.business.category.domain.vo.CategoryTreeVO;
import online.junmowen.blog.base.common.constant.StringConst;
import online.junmowen.blog.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 陌上君莫问
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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<CategoryEntity> querySubCategory(Long categoryId) {
return categoryDao.queryByParentId(Lists.newArrayList(categoryId), false);
}
/**
* 查询类目 层级树
* 优先查询缓存
*/
@Cacheable(AdminCacheConst.Category.CATEGORY_TREE)
public List<CategoryTreeVO> queryCategoryTree(Long parentId, Integer categoryType) {
List<CategoryEntity> allCategoryEntityList = categoryDao.queryByType(categoryType, false);
List<CategoryEntity> categoryEntityList = allCategoryEntityList.stream().filter(e -> e.getParentId().equals(parentId)).collect(Collectors.toList());
List<CategoryTreeVO> 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<CategoryTreeVO> treeList, List<CategoryEntity> allCategoryEntityList) {
if (CollectionUtils.isEmpty(treeList)) {
return;
}
List<Long> parentIdList = treeList.stream().map(CategoryTreeVO::getValue).collect(Collectors.toList());
List<CategoryEntity> categoryEntityList = allCategoryEntityList.stream().filter(e -> parentIdList.contains(e.getParentId())).collect(Collectors.toList());
Map<Long, List<CategoryEntity>> categorySubMap = categoryEntityList.stream().collect(Collectors.groupingBy(CategoryEntity::getParentId));
treeList.forEach(e -> {
List<CategoryEntity> childrenEntityList = categorySubMap.getOrDefault(e.getValue(), Lists.newArrayList());
List<CategoryTreeVO> 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);
});
}
}

View File

@@ -0,0 +1,188 @@
package online.junmowen.blog.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 online.junmowen.blog.admin.module.business.category.domain.dto.CategorySimpleDTO;
import online.junmowen.blog.admin.module.business.category.domain.entity.CategoryEntity;
import online.junmowen.blog.admin.module.business.category.manager.CategoryCacheManager;
import online.junmowen.blog.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 陌上君莫问
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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<CategoryEntity> 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<Long, CategoryEntity> queryCategoryList(List<Long> categoryIdList) {
if (CollectionUtils.isEmpty(categoryIdList)) {
return Collections.emptyMap();
}
categoryIdList = categoryIdList.stream().distinct().collect(Collectors.toList());
Map<Long, CategoryEntity> 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<Long> queryCategorySubId(List<Long> categoryIdList) {
if (CollectionUtils.isEmpty(categoryIdList)) {
return Collections.emptyList();
}
//所有子类
List<CategoryEntity> categoryEntityList = Lists.newArrayList();
categoryIdList.forEach(e -> {
categoryEntityList.addAll(categoryCacheManager.querySubCategory(e));
});
Map<Long, List<CategoryEntity>> 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<String> queryCategoryName(List<Long> categoryIdList) {
if (CollectionUtils.isEmpty(categoryIdList)) {
return null;
}
Map<Long, CategoryEntity> categoryMap = this.queryCategoryList(categoryIdList);
List<String> 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<CategoryEntity> queryCategoryAndParent(Long categoryId) {
List<CategoryEntity> 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<CategoryEntity> parentCategoryList = this.queryCategoryAndParent(categoryId);
// 拼接父级类目名称 斜杠分隔返回
List<String> nameList = parentCategoryList.stream().map(CategoryEntity::getCategoryName).collect(Collectors.toList());
return StrUtil.join(StringConst.SEPARATOR_SLASH, nameList);
}
/**
* 查询 分类全称 如:医考/医师资格/临床执业
*/
public Map<Long, String> queryFullName(List<Long> categoryIdList) {
if (CollectionUtils.isEmpty(categoryIdList)) {
return Maps.newHashMap();
}
// 循环内查询的缓存 还ok
return categoryIdList.stream().collect(Collectors.toMap(Function.identity(), this::queryFullName));
}
}

View File

@@ -0,0 +1,206 @@
package online.junmowen.blog.admin.module.business.category.service;
import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import online.junmowen.blog.admin.module.business.category.dao.CategoryDao;
import online.junmowen.blog.admin.module.business.category.domain.entity.CategoryEntity;
import online.junmowen.blog.admin.module.business.category.domain.form.CategoryAddForm;
import online.junmowen.blog.admin.module.business.category.domain.form.CategoryTreeQueryForm;
import online.junmowen.blog.admin.module.business.category.domain.form.CategoryUpdateForm;
import online.junmowen.blog.admin.module.business.category.domain.vo.CategoryTreeVO;
import online.junmowen.blog.admin.module.business.category.domain.vo.CategoryVO;
import online.junmowen.blog.admin.module.business.category.manager.CategoryCacheManager;
import online.junmowen.blog.base.common.code.UserErrorCode;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.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 陌上君莫问
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Service
public class CategoryService {
@Resource
private CategoryDao categoryDao;
@Resource
private CategoryQueryService categoryQueryService;
@Resource
private CategoryCacheManager categoryCacheManager;
/**
* 添加类目
*/
public ResponseDTO<String> add(CategoryAddForm addForm) {
// 校验类目
CategoryEntity categoryEntity = SmartBeanUtil.copy(addForm, CategoryEntity.class);
ResponseDTO<String> 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<String> update(CategoryUpdateForm updateForm) {
// 校验类目
Long categoryId = updateForm.getCategoryId();
Optional<CategoryEntity> 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<String> responseDTO = this.checkCategory(categoryEntity, true);
if (!responseDTO.getOk()) {
return responseDTO;
}
categoryDao.updateById(categoryEntity);
// 更新缓存
categoryCacheManager.removeCache();
return ResponseDTO.ok();
}
/**
* 新增/更新 类目时的 校验
*
*/
private ResponseDTO<String> 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<CategoryEntity> 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<CategoryVO> queryDetail(Long categoryId) {
Optional<CategoryEntity> 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<List<CategoryTreeVO>> queryTree(CategoryTreeQueryForm queryForm) {
if (null == queryForm.getParentId()) {
if (null == queryForm.getCategoryType()) {
return ResponseDTO.userErrorParam("类目类型不能为空");
}
queryForm.setParentId(NumberUtils.LONG_ZERO);
}
List<CategoryTreeVO> treeList = categoryCacheManager.queryCategoryTree(queryForm.getParentId(), queryForm.getCategoryType());
return ResponseDTO.ok(treeList);
}
/**
* 删除类目
* 如果有未删除的子类 则无法删除
*
*/
public ResponseDTO<String> delete(Long categoryId) {
Optional<CategoryEntity> optional = categoryQueryService.queryCategory(categoryId);
if (!optional.isPresent()) {
return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
}
List<Long> 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();
}
}

View File

@@ -0,0 +1,42 @@
package online.junmowen.blog.admin.module.business.goods.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import online.junmowen.blog.base.common.enumeration.BaseEnum;
/**
* 商品状态
*
* @Author 陌上君莫问
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@AllArgsConstructor
@Getter
public enum GoodsStatusEnum implements BaseEnum {
/**
* 1 预约中
*/
APPOINTMENT(1, "预约中"),
/**
* 2 售卖
*/
SELL(2, "售卖中"),
/**
* 3 售罄
*/
SELL_OUT(3, "售罄"),
;
private final Integer value;
private final String desc;
}

View File

@@ -0,0 +1,94 @@
package online.junmowen.blog.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 online.junmowen.blog.admin.constant.AdminSwaggerTagConst;
import online.junmowen.blog.admin.module.business.goods.domain.form.GoodsAddForm;
import online.junmowen.blog.admin.module.business.goods.domain.form.GoodsQueryForm;
import online.junmowen.blog.admin.module.business.goods.domain.form.GoodsUpdateForm;
import online.junmowen.blog.admin.module.business.goods.domain.vo.GoodsExcelVO;
import online.junmowen.blog.admin.module.business.goods.domain.vo.GoodsVO;
import online.junmowen.blog.admin.module.business.goods.service.GoodsService;
import online.junmowen.blog.base.common.domain.PageResult;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.base.common.domain.ValidateList;
import online.junmowen.blog.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 陌上君莫问
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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<PageResult<GoodsVO>> query(@RequestBody @Valid GoodsQueryForm queryForm) {
return goodsService.query(queryForm);
}
@Operation(summary = "添加商品 @author 胡克")
@PostMapping("/goods/add")
@SaCheckPermission("goods:add")
public ResponseDTO<String> add(@RequestBody @Valid GoodsAddForm addForm) {
return goodsService.add(addForm);
}
@Operation(summary = "更新商品 @author 胡克")
@PostMapping("/goods/update")
@SaCheckPermission("goods:update")
public ResponseDTO<String> update(@RequestBody @Valid GoodsUpdateForm updateForm) {
return goodsService.update(updateForm);
}
@Operation(summary = "删除 @author 卓大")
@GetMapping("/goods/delete/{goodsId}")
@SaCheckPermission("goods:delete")
public ResponseDTO<String> delete(@PathVariable Long goodsId) {
return goodsService.delete(goodsId);
}
@Operation(summary = "批量 @author 卓大")
@PostMapping("/goods/batchDelete")
@SaCheckPermission("goods:batchDelete")
public ResponseDTO<String> batchDelete(@RequestBody @Valid ValidateList<Long> idList) {
return goodsService.batchDelete(idList);
}
// --------------- 导出和导入 -------------------
@Operation(summary = "导入 @author 卓大")
@PostMapping("/goods/importGoods")
@SaCheckPermission("goods:importGoods")
public ResponseDTO<String> 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<GoodsExcelVO> goodsList = goodsService.getAllGoods();
SmartExcelUtil.exportExcel(response,"商品列表.xlsx","商品",GoodsExcelVO.class, goodsList);
}
}

View File

@@ -0,0 +1,36 @@
package online.junmowen.blog.admin.module.business.goods.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import online.junmowen.blog.admin.module.business.goods.domain.entity.GoodsEntity;
import online.junmowen.blog.admin.module.business.goods.domain.form.GoodsQueryForm;
import online.junmowen.blog.admin.module.business.goods.domain.vo.GoodsVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 商品
*
* @Author 陌上君莫问
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Mapper
public interface GoodsDao extends BaseMapper<GoodsEntity> {
/**
* 分页 查询商品
*
*/
List<GoodsVO> query(Page page, @Param("query") GoodsQueryForm query);
/**
* 批量更新删除状态
*/
void batchUpdateDeleted(@Param("goodsIdList")List<Long> goodsIdList,@Param("deletedFlag")Boolean deletedFlag);
}

View File

@@ -0,0 +1,71 @@
package online.junmowen.blog.admin.module.business.goods.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 商品 实体类
*
* @Author 陌上君莫问
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
@TableName("t_goods")
public class GoodsEntity {
@TableId(type = IdType.AUTO)
private Long goodsId;
/**
* 商品状态:[1:预约中,2:售卖中,3:售罄]
*/
private Integer goodsStatus;
/**
* 商品分类
*/
private Long categoryId;
/**
* 商品名称
*/
private String goodsName;
/**
* 产地
*/
private String place;
/**
* 商品价格
*/
private BigDecimal price;
/**
* 上架状态
*/
private Boolean shelvesFlag;
/**
* 删除状态
*/
private Boolean deletedFlag;
/**
* 备注
*/
private String remark;
private LocalDateTime updateTime;
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,56 @@
package online.junmowen.blog.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 online.junmowen.blog.admin.module.business.goods.constant.GoodsStatusEnum;
import online.junmowen.blog.base.common.json.deserializer.DictDataDeserializer;
import online.junmowen.blog.base.common.swagger.SchemaEnum;
import online.junmowen.blog.base.common.validator.enumeration.CheckEnum;
import java.math.BigDecimal;
/**
* 商品 添加表单
*
* @Author 陌上君莫问
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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 = DictDataDeserializer.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;
}

View File

@@ -0,0 +1,37 @@
package online.junmowen.blog.admin.module.business.goods.domain.form;
import org.apache.fesod.sheet.annotation.ExcelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* 商品 导入表单
*
* @Author 陌上君莫问
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class GoodsImportForm {
@ExcelProperty("商品分类")
private String categoryName;
@ExcelProperty("商品名称")
private String goodsName;
@ExcelProperty("商品状态错误")
private String goodsStatus;
@ExcelProperty("产地")
private String place;
@ExcelProperty("商品价格")
private BigDecimal price;
@ExcelProperty("备注")
private String remark;
}

View File

@@ -0,0 +1,45 @@
package online.junmowen.blog.admin.module.business.goods.domain.form;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import online.junmowen.blog.admin.module.business.goods.constant.GoodsStatusEnum;
import online.junmowen.blog.base.common.domain.PageParam;
import online.junmowen.blog.base.common.json.deserializer.DictDataDeserializer;
import online.junmowen.blog.base.common.swagger.SchemaEnum;
import online.junmowen.blog.base.common.validator.enumeration.CheckEnum;
import org.hibernate.validator.constraints.Length;
/**
* 商品 分页查询
*
* @Author 陌上君莫问
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class GoodsQueryForm extends PageParam {
@Schema(description = "商品分类")
private Integer categoryId;
@Schema(description = "搜索词")
@Length(max = 30, message = "搜索词最多30字符")
private String searchWord;
@SchemaEnum(GoodsStatusEnum.class)
@CheckEnum(message = "商品状态错误", value = GoodsStatusEnum.class, required = false)
private Integer goodsStatus;
@Schema(description = "产地")
@JsonDeserialize(using = DictDataDeserializer.class)
private String place;
@Schema(description = "上架状态")
private Boolean shelvesFlag;
@Schema(hidden = true)
private Boolean deletedFlag;
}

View File

@@ -0,0 +1,22 @@
package online.junmowen.blog.admin.module.business.goods.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 商品 更新表单
*
* @Author 陌上君莫问
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class GoodsUpdateForm extends GoodsAddForm {
@Schema(description = "商品id")
@NotNull(message = "商品id不能为空")
private Long goodsId;
}

View File

@@ -0,0 +1,44 @@
package online.junmowen.blog.admin.module.business.goods.domain.vo;
import org.apache.fesod.sheet.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* excel商品
*
* @Author 陌上君莫问
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class GoodsExcelVO {
@ExcelProperty("商品分类")
private String categoryName;
@ExcelProperty("商品名称")
private String goodsName;
@ExcelProperty("商品状态错误")
private String goodsStatus;
@ExcelProperty("产地")
private String place;
@ExcelProperty("商品价格")
private BigDecimal price;
@ExcelProperty("备注")
private String remark;
}

View File

@@ -0,0 +1,53 @@
package online.junmowen.blog.admin.module.business.goods.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import online.junmowen.blog.admin.module.business.goods.constant.GoodsStatusEnum;
import online.junmowen.blog.base.common.swagger.SchemaEnum;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 商品
*
* @Author 陌上君莫问
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class GoodsVO {
@Schema(description = "商品分类")
private Long categoryId;
@Schema(description = "商品名称")
private String goodsName;
@SchemaEnum(GoodsStatusEnum.class)
private Integer goodsStatus;
@Schema(description = "产地")
private String place;
@Schema(description = "商品价格")
private BigDecimal price;
@Schema(description = "上架状态")
private Boolean shelvesFlag;
@Schema(description = "备注|可选")
private String remark;
@Schema(description = "商品id")
private Long goodsId;
@Schema(description = "商品分类")
private String categoryName;
private LocalDateTime updateTime;
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,211 @@
package online.junmowen.blog.admin.module.business.goods.service;
import org.apache.fesod.sheet.FastExcel;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import online.junmowen.blog.admin.module.business.category.constant.CategoryTypeEnum;
import online.junmowen.blog.admin.module.business.category.domain.entity.CategoryEntity;
import online.junmowen.blog.admin.module.business.category.service.CategoryQueryService;
import online.junmowen.blog.admin.module.business.goods.constant.GoodsStatusEnum;
import online.junmowen.blog.admin.module.business.goods.dao.GoodsDao;
import online.junmowen.blog.admin.module.business.goods.domain.entity.GoodsEntity;
import online.junmowen.blog.admin.module.business.goods.domain.form.GoodsAddForm;
import online.junmowen.blog.admin.module.business.goods.domain.form.GoodsImportForm;
import online.junmowen.blog.admin.module.business.goods.domain.form.GoodsQueryForm;
import online.junmowen.blog.admin.module.business.goods.domain.form.GoodsUpdateForm;
import online.junmowen.blog.admin.module.business.goods.domain.vo.GoodsExcelVO;
import online.junmowen.blog.admin.module.business.goods.domain.vo.GoodsVO;
import online.junmowen.blog.base.common.code.UserErrorCode;
import online.junmowen.blog.base.common.domain.PageResult;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.base.common.exception.BusinessException;
import online.junmowen.blog.base.common.util.SmartBeanUtil;
import online.junmowen.blog.base.common.util.SmartEnumUtil;
import online.junmowen.blog.base.common.util.SmartPageUtil;
import online.junmowen.blog.base.module.support.datatracer.constant.DataTracerTypeEnum;
import online.junmowen.blog.base.module.support.datatracer.service.DataTracerService;
import online.junmowen.blog.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 陌上君莫问
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Service
@Slf4j
public class GoodsService {
@Resource
private GoodsDao goodsDao;
@Resource
private CategoryQueryService categoryQueryService;
@Resource
private DataTracerService dataTracerService;
@Resource
private DictService dictService;
/**
* 添加商品
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> add(GoodsAddForm addForm) {
// 商品校验
ResponseDTO<String> 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<String> update(GoodsUpdateForm updateForm) {
// 商品校验
ResponseDTO<String> 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<String> checkGoods(GoodsAddForm addForm) {
// 校验类目id
Long categoryId = addForm.getCategoryId();
Optional<CategoryEntity> 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<String> 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<String> batchDelete(List<Long> goodsIdList) {
if (CollectionUtils.isEmpty(goodsIdList)) {
return ResponseDTO.ok();
}
goodsDao.batchUpdateDeleted(goodsIdList, Boolean.TRUE);
return ResponseDTO.ok();
}
/**
* 分页查询
*/
public ResponseDTO<PageResult<GoodsVO>> query(GoodsQueryForm queryForm) {
queryForm.setDeletedFlag(false);
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
List<GoodsVO> list = goodsDao.query(page, queryForm);
PageResult<GoodsVO> pageResult = SmartPageUtil.convert2PageResult(page, list);
if (pageResult.getEmptyFlag()) {
return ResponseDTO.ok(pageResult);
}
// 查询分类名称
List<Long> categoryIdList = list.stream().map(GoodsVO::getCategoryId).distinct().collect(Collectors.toList());
Map<Long, CategoryEntity> 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<String> importGoods(MultipartFile file) {
List<GoodsImportForm> dataList;
try {
dataList = FastExcel.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<GoodsExcelVO> getAllGoods() {
List<GoodsEntity> goodsEntityList = goodsDao.selectList(null);
String dictCode = "GOODS_PLACE";
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 -> dictService.getDictDataLabel(dictCode, code)).collect(Collectors.joining(",")))
.price(e.getPrice())
.goodsName(e.getGoodsName())
.remark(e.getRemark())
.build()
)
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,82 @@
package online.junmowen.blog.admin.module.business.oa.bank.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 online.junmowen.blog.admin.constant.AdminSwaggerTagConst;
import online.junmowen.blog.admin.module.business.oa.bank.service.BankService;
import online.junmowen.blog.admin.module.business.oa.bank.domain.BankCreateForm;
import online.junmowen.blog.admin.module.business.oa.bank.domain.BankQueryForm;
import online.junmowen.blog.admin.module.business.oa.bank.domain.BankUpdateForm;
import online.junmowen.blog.admin.module.business.oa.bank.domain.BankVO;
import online.junmowen.blog.base.common.domain.PageResult;
import online.junmowen.blog.base.common.domain.RequestUser;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.base.common.util.SmartRequestUtil;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* OA办公-OA银行信息
*
* @Author 陌上君莫问
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@RestController
@Tag(name = AdminSwaggerTagConst.Business.OA_BANK)
public class BankController {
@Resource
private BankService bankService;
@Operation(summary = "分页查询银行信息 @author 陌上君莫问")
@PostMapping("/oa/bank/page/query")
@SaCheckPermission("oa:bank:query")
public ResponseDTO<PageResult<BankVO>> queryByPage(@RequestBody @Valid BankQueryForm queryForm) {
return bankService.queryByPage(queryForm);
}
@Operation(summary = "根据企业ID查询银行信息列表 @author 陌上君莫问")
@GetMapping("/oa/bank/query/list/{enterpriseId}")
@SaCheckPermission("oa:bank:query")
public ResponseDTO<List<BankVO>> queryList(@PathVariable Long enterpriseId) {
return bankService.queryList(enterpriseId);
}
@Operation(summary = "查询银行信息详情 @author 陌上君莫问")
@GetMapping("/oa/bank/get/{bankId}")
@SaCheckPermission("oa:bank:query")
public ResponseDTO<BankVO> getDetail(@PathVariable Long bankId) {
return bankService.getDetail(bankId);
}
@Operation(summary = "新建银行信息 @author 陌上君莫问")
@PostMapping("/oa/bank/create")
@SaCheckPermission("oa:bank:add")
public ResponseDTO<String> 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")
@SaCheckPermission("oa:bank:update")
public ResponseDTO<String> updateBank(@RequestBody @Valid BankUpdateForm updateVO) {
return bankService.updateBank(updateVO);
}
@Operation(summary = "删除银行信息 @author 陌上君莫问")
@GetMapping("/oa/bank/delete/{bankId}")
@SaCheckPermission("oa:bank:delete")
public ResponseDTO<String> deleteBank(@PathVariable Long bankId) {
return bankService.deleteBank(bankId);
}
}

View File

@@ -0,0 +1,46 @@
package online.junmowen.blog.admin.module.business.oa.bank.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import online.junmowen.blog.admin.module.business.oa.bank.domain.BankEntity;
import online.junmowen.blog.admin.module.business.oa.bank.domain.BankQueryForm;
import online.junmowen.blog.admin.module.business.oa.bank.domain.BankVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* OA办公-OA银行信息
*
* @Author 陌上君莫问
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Mapper
public interface BankDao extends BaseMapper<BankEntity> {
/**
* 根据账号查询
*/
BankEntity queryByAccountNumber(@Param("enterpriseId") Long enterpriseId, @Param("accountNumber") String accountNumber, @Param("excludeBankId") Long excludeBankId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 删除银行信息
*
*/
void deleteBank(@Param("bankId") Long bankId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 银行信息分页查询
*
*/
List<BankVO> queryPage(Page page, @Param("queryForm") BankQueryForm queryForm);
/**
* 查询银行信息详情
*/
BankVO getDetail(@Param("bankId") Long bankId, @Param("deletedFlag") Boolean deletedFlag);
}

View File

@@ -0,0 +1,57 @@
package online.junmowen.blog.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 陌上君莫问
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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;
}

View File

@@ -0,0 +1,95 @@
package online.junmowen.blog.admin.module.business.oa.bank.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import online.junmowen.blog.base.module.support.datatracer.annoation.DataTracerFieldLabel;
import java.time.LocalDateTime;
/**
* OA办公-OA银行信息
*
* @Author 陌上君莫问
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
@TableName("t_oa_bank")
public class BankEntity {
/**
* 银行信息ID
*/
@TableId(type = IdType.AUTO)
@DataTracerFieldLabel("银行信息ID")
private Long bankId;
/**
* 开户银行
*/
@DataTracerFieldLabel("开户银行")
private String bankName;
/**
* 账户名称
*/
@DataTracerFieldLabel("账户名称")
private String accountName;
/**
* 账号
*/
@DataTracerFieldLabel("账号")
private String accountNumber;
/**
* 备注
*/
@DataTracerFieldLabel("备注")
private String remark;
/**
* 是否对公
*/
@DataTracerFieldLabel("是否对公")
private Boolean businessFlag;
/**
* 企业ID
*/
private Long enterpriseId;
/**
* 禁用状态
*/
@DataTracerFieldLabel("禁用状态")
private Boolean disabledFlag;
/**
* 删除状态
*/
private Boolean deletedFlag;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人ID
*/
private String createUserName;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,40 @@
package online.junmowen.blog.admin.module.business.oa.bank.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import online.junmowen.blog.base.common.domain.PageParam;
import org.hibernate.validator.constraints.Length;
import java.time.LocalDate;
/**
* OA办公-OA银行信息查询
*
* @Author 陌上君莫问
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class BankQueryForm extends PageParam {
@Schema(description = "企业ID")
private Long enterpriseId;
@Schema(description = "关键字")
@Length(max = 200, message = "关键字最多200字符")
private String keywords;
@Schema(description = "开始时间")
private LocalDate startTime;
@Schema(description = "结束时间")
private LocalDate endTime;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "删除状态", hidden = true)
private Boolean deletedFlag;
}

View File

@@ -0,0 +1,22 @@
package online.junmowen.blog.admin.module.business.oa.bank.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* OA办公-银行信息更新
*
* @Author 陌上君莫问
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class BankUpdateForm extends BankCreateForm {
@Schema(description = "银行信息ID")
@NotNull(message = "银行信息ID不能为空")
private Long bankId;
}

View File

@@ -0,0 +1,58 @@
package online.junmowen.blog.admin.module.business.oa.bank.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* OA办公-OA银行信息
*
* @Author 陌上君莫问
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class BankVO {
@Schema(description = "银行信息ID")
private Long bankId;
@Schema(description = "开户银行")
private String bankName;
@Schema(description = "账户名称")
private String accountName;
@Schema(description = "账号")
private String accountNumber;
@Schema(description = "备注")
private String remark;
@Schema(description = "是否对公")
private Boolean businessFlag;
@Schema(description = "企业ID")
private Long enterpriseId;
@Schema(description = "企业名称")
private String enterpriseName;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "创建人ID")
private Long createUserId;
@Schema(description = "创建人名称")
private String createUserName;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,146 @@
package online.junmowen.blog.admin.module.business.oa.bank.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import online.junmowen.blog.admin.module.business.oa.bank.dao.BankDao;
import online.junmowen.blog.admin.module.business.oa.bank.domain.*;
import online.junmowen.blog.admin.module.business.oa.enterprise.dao.EnterpriseDao;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.entity.EnterpriseEntity;
import online.junmowen.blog.base.common.domain.PageResult;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.base.common.util.SmartBeanUtil;
import online.junmowen.blog.base.common.util.SmartPageUtil;
import online.junmowen.blog.base.module.support.datatracer.constant.DataTracerConst;
import online.junmowen.blog.base.module.support.datatracer.constant.DataTracerTypeEnum;
import online.junmowen.blog.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 陌上君莫问
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Service
@Slf4j
public class BankService {
@Resource
private BankDao bankDao;
@Resource
private EnterpriseDao enterpriseDao;
@Resource
private DataTracerService dataTracerService;
/**
* 分页查询银行信息
*/
public ResponseDTO<PageResult<BankVO>> queryByPage(BankQueryForm queryForm) {
queryForm.setDeletedFlag(Boolean.FALSE);
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
List<BankVO> bankList = bankDao.queryPage(page, queryForm);
PageResult<BankVO> pageResult = SmartPageUtil.convert2PageResult(page, bankList);
return ResponseDTO.ok(pageResult);
}
/**
* 根据企业ID查询不分页的银行列表
*/
public ResponseDTO<List<BankVO>> queryList(Long enterpriseId) {
BankQueryForm queryForm = new BankQueryForm();
queryForm.setEnterpriseId(enterpriseId);
queryForm.setDeletedFlag(Boolean.FALSE);
List<BankVO> bankList = bankDao.queryPage(null, queryForm);
return ResponseDTO.ok(bankList);
}
/**
* 查询银行信息详情
*/
public ResponseDTO<BankVO> 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<String> 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<String> 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<String> 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();
}
}

View File

@@ -0,0 +1,46 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.constant;
import online.junmowen.blog.base.common.enumeration.BaseEnum;
/**
* 企业类型
*
* @Author 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
public enum EnterpriseTypeEnum implements BaseEnum {
/**
* 有限企业
*/
NORMAL(1, "有限企业"),
/**
* 外资企业
*/
FOREIGN(2, "外资企业"),
;
private Integer value;
private String desc;
EnterpriseTypeEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
@Override
public Integer getValue() {
return value;
}
@Override
public String getDesc() {
return desc;
}
}

View File

@@ -0,0 +1,138 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.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 lombok.extern.slf4j.Slf4j;
import online.junmowen.blog.admin.constant.AdminSwaggerTagConst;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.form.*;
import online.junmowen.blog.admin.module.business.oa.enterprise.service.EnterpriseService;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseEmployeeVO;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseExcelVO;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO;
import online.junmowen.blog.admin.util.AdminRequestUtil;
import online.junmowen.blog.base.common.domain.PageResult;
import online.junmowen.blog.base.common.domain.RequestUser;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.base.common.util.*;
import online.junmowen.blog.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 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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<PageResult<EnterpriseVO>> 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<EnterpriseExcelVO> 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<EnterpriseVO> getDetail(@PathVariable Long enterpriseId) {
return ResponseDTO.ok(enterpriseService.getDetail(enterpriseId));
}
@Operation(summary = "新建企业 @author 开云")
@PostMapping("/oa/enterprise/create")
@SaCheckPermission("oa:enterprise:add")
public ResponseDTO<String> 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<String> updateEnterprise(@RequestBody @Valid EnterpriseUpdateForm updateVO) {
return enterpriseService.updateEnterprise(updateVO);
}
@Operation(summary = "删除企业 @author 开云")
@GetMapping("/oa/enterprise/delete/{enterpriseId}")
@SaCheckPermission("oa:enterprise:delete")
public ResponseDTO<String> deleteEnterprise(@PathVariable Long enterpriseId) {
return enterpriseService.deleteEnterprise(enterpriseId);
}
@Operation(summary = "按照类型查询企业 @author 开云")
@GetMapping("/oa/enterprise/query/list")
@SaCheckPermission("oa:enterprise:query")
public ResponseDTO<List<EnterpriseListVO>> 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<String> addEmployee(@RequestBody @Valid EnterpriseEmployeeForm enterpriseEmployeeForm) {
return enterpriseService.addEmployee(enterpriseEmployeeForm);
}
@Operation(summary = "查询企业全部员工 @author 陌上君莫问")
@PostMapping("/oa/enterprise/employee/list")
@SaCheckPermission("oa:enterprise:queryEmployee")
public ResponseDTO<List<EnterpriseEmployeeVO>> employeeList(@RequestBody @Valid List<Long> enterpriseIdList) {
return ResponseDTO.ok(enterpriseService.employeeList(enterpriseIdList));
}
@Operation(summary = "分页查询企业员工 @author 卓大")
@PostMapping("/oa/enterprise/employee/queryPage")
@SaCheckPermission("oa:enterprise:queryEmployee")
public ResponseDTO<PageResult<EnterpriseEmployeeVO>> 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<String> deleteEmployee(@RequestBody @Valid EnterpriseEmployeeForm enterpriseEmployeeForm) {
return enterpriseService.deleteEmployee(enterpriseEmployeeForm);
}
}

View File

@@ -0,0 +1,63 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.entity.EnterpriseEntity;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.form.EnterpriseQueryForm;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseExcelVO;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 企业
*
* @Author 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Mapper
public interface EnterpriseDao extends BaseMapper<EnterpriseEntity> {
/**
* 根据企业名称查询
*
*/
EnterpriseEntity queryByEnterpriseName(@Param("enterpriseName") String enterpriseName, @Param("excludeEnterpriseId") Long excludeEnterpriseId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 删除企业
*/
void deleteEnterprise(@Param("enterpriseId") Long enterpriseId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 企业分页查询
*
*/
List<EnterpriseVO> queryPage(Page page, @Param("queryForm") EnterpriseQueryForm queryForm);
/**
* 查询导出的数据
*
*/
List<EnterpriseExcelVO> selectExcelExportData(@Param("queryForm") EnterpriseQueryForm queryForm);
/**
* 查询企业详情
*
*/
EnterpriseVO getDetail(@Param("enterpriseId") Long enterpriseId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 查询列表
*
*/
List<EnterpriseListVO> queryList(@Param("type") Integer type, @Param("disabledFlag") Boolean disabledFlag, @Param("deletedFlag") Boolean deletedFlag);
}

View File

@@ -0,0 +1,68 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.entity.EnterpriseEmployeeEntity;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.form.EnterpriseEmployeeQueryForm;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseEmployeeVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
import java.util.List;
/**
* 企业员工
*
* @Author 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Mapper
public interface EnterpriseEmployeeDao extends BaseMapper<EnterpriseEmployeeEntity> {
/**
* 根据员工查询
*/
List<EnterpriseEmployeeVO> selectByEmployeeIdList(@Param("employeeIdList")Collection<Long> employeeIdList);
/**
* 查询员工关联的企业
*/
List<Long> selectEnterpriseIdByEmployeeId(@Param("employeeId")Long employeeId);
/**
* 根据企业查询
*/
List<EnterpriseEmployeeVO> selectByEnterpriseIdList(@Param("enterpriseIdList")Collection<Long> enterpriseIdList);
/**
* 根据企业查询
*/
List<EnterpriseEmployeeEntity> selectByEnterpriseId(@Param("enterpriseId")Long enterpriseId);
/**
* 查询企业下的所有员工id
*/
List<Long> selectEmployeeIdByEnterpriseIdList(@Param("enterpriseIdList")Collection<Long> enterpriseIdList);
/**
* 根据员工删除
*/
void deleteByEnterpriseAndEmployeeIdList(@Param("enterpriseId")Long enterpriseId, @Param("employeeIdList")Collection<Long> employeeIdList);
/**
* 根据员工查询
*/
List<EnterpriseEmployeeEntity> selectByEnterpriseAndEmployeeIdList(@Param("enterpriseId")Long enterpriseId, @Param("employeeIdList")Collection<Long> employeeIdList);
/**
* 删除某员工关联的所有企业
*/
void deleteByEmployeeId(@Param("employeeId")Long employeeId);
/**
* 分页查询企业员工
*/
List<EnterpriseEmployeeVO> queryPageEmployeeList(Page<?> page,@Param("queryForm") EnterpriseEmployeeQueryForm queryForm);
}

View File

@@ -0,0 +1,51 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 企业员工
*
* @Author 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
@TableName("t_oa_enterprise_employee")
@NoArgsConstructor
public class EnterpriseEmployeeEntity {
@TableId(type = IdType.AUTO)
private Long enterpriseEmployeeId;
/**
* 企业ID
*/
private Long enterpriseId;
/**
* 员工
*/
private Long employeeId;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
public EnterpriseEmployeeEntity(Long enterpriseId, Long employeeId) {
this.enterpriseId = enterpriseId;
this.employeeId = employeeId;
}
}

View File

@@ -0,0 +1,153 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import online.junmowen.blog.admin.module.business.oa.enterprise.constant.EnterpriseTypeEnum;
import online.junmowen.blog.base.module.support.datatracer.annoation.DataTracerFieldEnum;
import online.junmowen.blog.base.module.support.datatracer.annoation.DataTracerFieldLabel;
import java.time.LocalDateTime;
/**
* 企业
*
* @Author 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
@TableName("t_oa_enterprise")
public class EnterpriseEntity {
/**
* 企业ID
*/
@TableId(type = IdType.AUTO)
private Long enterpriseId;
/**
* 企业名称
*/
@DataTracerFieldLabel("企业名称")
private String enterpriseName;
/**
* 企业logo
*/
@DataTracerFieldLabel("企业logo")
private String enterpriseLogo;
/**
* 统一社会信用代码
*/
@DataTracerFieldLabel("统一社会信用代码")
private String unifiedSocialCreditCode;
/**
* 类型
*
* @see EnterpriseTypeEnum
*/
@DataTracerFieldLabel("类型")
@DataTracerFieldEnum(enumClass = EnterpriseTypeEnum.class)
private Integer type;
/**
* 联系人
*/
@DataTracerFieldLabel("联系人")
private String contact;
/**
* 联系人电话
*/
@DataTracerFieldLabel("联系人电话")
private String contactPhone;
/**
* 邮箱
*/
@DataTracerFieldLabel("邮箱")
private String email;
/**
* 省份
*/
private Integer province;
/**
* 省份名称
*/
@DataTracerFieldLabel("省份名称")
private String provinceName;
/**
* 城市
*/
private Integer city;
/**
* 城市名称
*/
@DataTracerFieldLabel("城市名称")
private String cityName;
/**
* 区县
*/
private Integer district;
/**
* 区县名称
*/
@DataTracerFieldLabel("区县名称")
private String districtName;
/**
* 详细地址
*/
@DataTracerFieldLabel("详细地址")
private String address;
/**
* 营业执照
*/
@DataTracerFieldLabel("营业执照")
private String businessLicense;
/**
* 禁用状态
*/
@DataTracerFieldLabel("禁用状态")
private Boolean disabledFlag;
/**
* 删除状态
*/
@DataTracerFieldLabel("删除状态")
private Boolean deletedFlag;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人ID
*/
private String createUserName;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,100 @@
package online.junmowen.blog.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 online.junmowen.blog.admin.module.business.oa.enterprise.constant.EnterpriseTypeEnum;
import online.junmowen.blog.base.common.json.deserializer.FileKeyVoDeserializer;
import online.junmowen.blog.base.common.json.serializer.FileKeyVoSerializer;
import online.junmowen.blog.base.common.swagger.SchemaEnum;
import online.junmowen.blog.base.common.util.SmartVerificationUtil;
import online.junmowen.blog.base.common.validator.enumeration.CheckEnum;
import org.hibernate.validator.constraints.Length;
/**
* OA企业模块创建
*
* @Author 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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;
}

View File

@@ -0,0 +1,29 @@
package online.junmowen.blog.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 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class EnterpriseEmployeeForm {
@Schema(description = "企业id")
@NotNull(message = "企业id不能为空")
private Long enterpriseId;
@Schema(description = "员工信息id")
@NotEmpty(message = "员工信息id不能为空")
private List<Long> employeeIdList;
}

View File

@@ -0,0 +1,32 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import online.junmowen.blog.base.common.domain.PageParam;
import org.hibernate.validator.constraints.Length;
/**
* 查询企业员工
*
* @Author 陌上君莫问
* @Date 2021-12-20 21:06:49
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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;
}

View File

@@ -0,0 +1,38 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import online.junmowen.blog.base.common.domain.PageParam;
import org.hibernate.validator.constraints.Length;
import java.time.LocalDate;
/**
* OA企业模块分页查询
*
* @Author 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class EnterpriseQueryForm extends PageParam {
@Schema(description = "关键字")
@Length(max = 200, message = "关键字最多200字符")
private String keywords;
@Schema(description = "开始时间")
private LocalDate startTime;
@Schema(description = "结束时间")
private LocalDate endTime;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "删除状态", hidden = true)
private Boolean deletedFlag;
}

View File

@@ -0,0 +1,22 @@
package online.junmowen.blog.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 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class EnterpriseUpdateForm extends EnterpriseCreateForm {
@Schema(description = "企业ID")
@NotNull(message = "企业ID不能为空")
private Long enterpriseId;
}

View File

@@ -0,0 +1,47 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 企业员工信息
*
* @Author 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class EnterpriseEmployeeVO {
private Long enterpriseEmployeeId;
@Schema(description = "企业ID")
private Long enterpriseId;
@Schema(description = "企业名称")
private String enterpriseName;
@Schema(description = "员工")
private Long employeeId;
@Schema(description = "登录账号")
private String loginName;
@Schema(description = "员工名称")
private String actualName;
@Schema(description = "手机号码")
private String phone;
@Schema(description = "部门id")
private Long departmentId;
@Schema(description = "是否被禁用")
private Boolean disabledFlag;
@Schema(description = "部门名称")
private String departmentName;
}

View File

@@ -0,0 +1,48 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo;
import org.apache.fesod.sheet.annotation.ExcelProperty;
import lombok.Data;
/**
* 企业信息
*
* @Author 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class EnterpriseExcelVO {
@ExcelProperty("企业名称")
private String enterpriseName;
@ExcelProperty("统一社会信用代码")
private String unifiedSocialCreditCode;
@ExcelProperty("企业类型")
private String typeName;
@ExcelProperty("联系人")
private String contact;
@ExcelProperty("联系人电话")
private String contactPhone;
@ExcelProperty("邮箱")
private String email;
@ExcelProperty("省份名称")
private String provinceName;
@ExcelProperty("城市名称")
private String cityName;
@ExcelProperty("区县名称")
private String districtName;
@ExcelProperty("详细地址")
private String address;
}

View File

@@ -0,0 +1,20 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* OA企业模块列表
*
* @author lihaifan
* @date 2022/6/23 14:31
*/
@Data
public class EnterpriseListVO {
@Schema(description = "企业ID")
private Long enterpriseId;
@Schema(description = "企业名称")
private String enterpriseName;
}

View File

@@ -0,0 +1,89 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import online.junmowen.blog.admin.module.business.oa.enterprise.constant.EnterpriseTypeEnum;
import online.junmowen.blog.base.common.json.serializer.FileKeyVoSerializer;
import online.junmowen.blog.base.common.swagger.SchemaEnum;
import java.time.LocalDateTime;
/**
* 企业信息
*
* @Author 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class EnterpriseVO {
@Schema(description = "企业ID")
private Long enterpriseId;
@Schema(description = "企业名称")
private String enterpriseName;
@Schema(description = "企业logo")
@JsonSerialize(using = FileKeyVoSerializer.class)
private String enterpriseLogo;
@Schema(description = "统一社会信用代码")
private String unifiedSocialCreditCode;
@SchemaEnum(desc = "类型", value = EnterpriseTypeEnum.class)
private Integer type;
@Schema(description = "联系人")
private String contact;
@Schema(description = "联系人电话")
private String contactPhone;
@Schema(description = "邮箱")
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 = "详细地址")
private String address;
@Schema(description = "营业执照")
@JsonSerialize(using = FileKeyVoSerializer.class)
private String businessLicense;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "创建人ID")
private Long createUserId;
@Schema(description = "创建人名称")
private String createUserName;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,19 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.manager;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import online.junmowen.blog.admin.module.business.oa.enterprise.dao.EnterpriseEmployeeDao;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.entity.EnterpriseEmployeeEntity;
import org.springframework.stereotype.Service;
/**
* 企业员工关系 manager
*
* @Author 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Service
public class EnterpriseEmployeeManager extends ServiceImpl<EnterpriseEmployeeDao, EnterpriseEmployeeEntity> {
}

View File

@@ -0,0 +1,239 @@
package online.junmowen.blog.admin.module.business.oa.enterprise.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import online.junmowen.blog.admin.module.business.oa.enterprise.dao.EnterpriseDao;
import online.junmowen.blog.admin.module.business.oa.enterprise.dao.EnterpriseEmployeeDao;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.entity.EnterpriseEmployeeEntity;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.entity.EnterpriseEntity;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.form.*;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseEmployeeVO;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseExcelVO;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO;
import online.junmowen.blog.admin.module.business.oa.enterprise.manager.EnterpriseEmployeeManager;
import online.junmowen.blog.admin.module.system.department.service.DepartmentService;
import online.junmowen.blog.base.common.code.UserErrorCode;
import online.junmowen.blog.base.common.domain.PageResult;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.base.common.util.SmartBeanUtil;
import online.junmowen.blog.base.common.util.SmartPageUtil;
import online.junmowen.blog.base.module.support.datatracer.constant.DataTracerTypeEnum;
import online.junmowen.blog.base.module.support.datatracer.domain.form.DataTracerForm;
import online.junmowen.blog.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 陌上君莫问
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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<PageResult<EnterpriseVO>> queryByPage(EnterpriseQueryForm queryForm) {
queryForm.setDeletedFlag(Boolean.FALSE);
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
List<EnterpriseVO> enterpriseList = enterpriseDao.queryPage(page, queryForm);
PageResult<EnterpriseVO> pageResult = SmartPageUtil.convert2PageResult(page, enterpriseList);
return ResponseDTO.ok(pageResult);
}
/**
* 获取导出数据
*/
public List<EnterpriseExcelVO> 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<String> 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<String> 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<String> 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<List<EnterpriseListVO>> queryList(Integer type) {
List<EnterpriseListVO> enterpriseList = enterpriseDao.queryList(type, Boolean.FALSE, Boolean.FALSE);
return ResponseDTO.ok(enterpriseList);
}
//----------------------------------------- 以下为员工相关--------------------------------------------
/**
* 企业添加员工
*
*/
public synchronized ResponseDTO<String> 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<Long> waitAddEmployeeIdList = enterpriseEmployeeForm.getEmployeeIdList();
List<EnterpriseEmployeeEntity> enterpriseEmployeeEntityList = enterpriseEmployeeDao.selectByEnterpriseAndEmployeeIdList(enterpriseId, waitAddEmployeeIdList);
if (CollectionUtils.isNotEmpty(enterpriseEmployeeEntityList)) {
List<Long> 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<EnterpriseEmployeeEntity> 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<String> 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<Long> waitDeleteEmployeeIdList = enterpriseEmployeeForm.getEmployeeIdList();
enterpriseEmployeeDao.deleteByEnterpriseAndEmployeeIdList(enterpriseId, waitDeleteEmployeeIdList);
return ResponseDTO.ok();
}
/**
* 企业下员工列表
*
*/
public List<EnterpriseEmployeeVO> employeeList(List<Long> enterpriseIdList) {
if (CollectionUtils.isEmpty(enterpriseIdList)) {
return Lists.newArrayList();
}
return enterpriseEmployeeDao.selectByEnterpriseIdList(enterpriseIdList);
}
/**
* 分页查询企业员工
*
*/
public PageResult<EnterpriseEmployeeVO> queryPageEmployeeList(EnterpriseEmployeeQueryForm queryForm) {
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
List<EnterpriseEmployeeVO> enterpriseEmployeeVOList = enterpriseEmployeeDao.queryPageEmployeeList(page, queryForm);
for (EnterpriseEmployeeVO enterpriseEmployeeVO : enterpriseEmployeeVOList) {
enterpriseEmployeeVO.setDepartmentName(departmentService.getDepartmentPath(enterpriseEmployeeVO.getDepartmentId()));
}
return SmartPageUtil.convert2PageResult(page, enterpriseEmployeeVOList);
}
}

View File

@@ -0,0 +1,88 @@
package online.junmowen.blog.admin.module.business.oa.invoice.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 lombok.extern.slf4j.Slf4j;
import online.junmowen.blog.admin.constant.AdminSwaggerTagConst;
import online.junmowen.blog.admin.module.business.oa.invoice.service.InvoiceService;
import online.junmowen.blog.admin.module.business.oa.invoice.domain.InvoiceAddForm;
import online.junmowen.blog.admin.module.business.oa.invoice.domain.InvoiceQueryForm;
import online.junmowen.blog.admin.module.business.oa.invoice.domain.InvoiceUpdateForm;
import online.junmowen.blog.admin.module.business.oa.invoice.domain.InvoiceVO;
import online.junmowen.blog.base.common.domain.PageResult;
import online.junmowen.blog.base.common.domain.RequestUser;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.base.common.util.SmartRequestUtil;
import online.junmowen.blog.base.module.support.operatelog.annotation.OperateLog;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* OA发票信息
*
* @Author 陌上君莫问
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Slf4j
@RestController
@Tag(name = AdminSwaggerTagConst.Business.OA_INVOICE)
public class InvoiceController {
@Resource
private InvoiceService invoiceService;
@Operation(summary = "分页查询发票信息 @author 陌上君莫问")
@PostMapping("/oa/invoice/page/query")
@SaCheckPermission("oa:invoice:query")
public ResponseDTO<PageResult<InvoiceVO>> queryByPage(@RequestBody @Valid InvoiceQueryForm queryForm) {
return invoiceService.queryByPage(queryForm);
}
@Operation(summary = "查询发票信息详情 @author 陌上君莫问")
@GetMapping("/oa/invoice/get/{invoiceId}")
@SaCheckPermission("oa:invoice:query")
public ResponseDTO<InvoiceVO> getDetail(@PathVariable Long invoiceId) {
return invoiceService.getDetail(invoiceId);
}
@Operation(summary = "新建发票信息 @author 陌上君莫问")
@PostMapping("/oa/invoice/create")
@SaCheckPermission("oa:invoice:add")
public ResponseDTO<String> createInvoice(@RequestBody @Valid InvoiceAddForm createVO) {
RequestUser requestUser = SmartRequestUtil.getRequestUser();
createVO.setCreateUserId(requestUser.getUserId());
createVO.setCreateUserName(requestUser.getUserName());
return invoiceService.createInvoice(createVO);
}
@OperateLog
@Operation(summary = "编辑发票信息 @author 陌上君莫问")
@PostMapping("/oa/invoice/update")
@SaCheckPermission("oa:invoice:update")
public ResponseDTO<String> updateInvoice(@RequestBody @Valid InvoiceUpdateForm updateVO) {
return invoiceService.updateInvoice(updateVO);
}
@Operation(summary = "删除发票信息 @author 陌上君莫问")
@GetMapping("/invoice/delete/{invoiceId}")
@SaCheckPermission("oa:invoice:delete")
public ResponseDTO<String> deleteInvoice(@PathVariable Long invoiceId) {
return invoiceService.deleteInvoice(invoiceId);
}
@Operation(summary = "查询列表 @author lidoudou")
@GetMapping("/oa/invoice/query/list/{enterpriseId}")
@SaCheckPermission("oa:invoice:query")
public ResponseDTO<List<InvoiceVO>> queryList(@PathVariable Long enterpriseId) {
return invoiceService.queryList(enterpriseId);
}
}

View File

@@ -0,0 +1,59 @@
package online.junmowen.blog.admin.module.business.oa.invoice.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import online.junmowen.blog.admin.module.business.oa.invoice.domain.InvoiceEntity;
import online.junmowen.blog.admin.module.business.oa.invoice.domain.InvoiceQueryForm;
import online.junmowen.blog.admin.module.business.oa.invoice.domain.InvoiceVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* OA发票信息
*
* @Author 陌上君莫问
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Mapper
public interface InvoiceDao extends BaseMapper<InvoiceEntity> {
/**
* 根据账号查询
* @param enterpriseId
* @param accountNumber
* @param excludeInvoiceId
* @param deletedFlag
* @return
*/
InvoiceEntity queryByAccountNumber(@Param("enterpriseId") Long enterpriseId, @Param("accountNumber") String accountNumber, @Param("excludeInvoiceId") Long excludeInvoiceId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 删除发票信息
*
* @param invoiceId
* @param deletedFlag
*/
void deleteInvoice(@Param("invoiceId") Long invoiceId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 发票信息分页查询
*
* @param page
* @param queryForm
* @return
*/
List<InvoiceVO> queryPage(Page page, @Param("queryForm") InvoiceQueryForm queryForm);
/**
* 查询发票信息详情
* @param invoiceId
* @param deletedFlag
* @return
*/
InvoiceVO getDetail(@Param("invoiceId") Long invoiceId, @Param("deletedFlag") Boolean deletedFlag);
}

View File

@@ -0,0 +1,58 @@
package online.junmowen.blog.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 陌上君莫问
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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;
}

View File

@@ -0,0 +1,98 @@
package online.junmowen.blog.admin.module.business.oa.invoice.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import online.junmowen.blog.base.module.support.datatracer.annoation.DataTracerFieldLabel;
import java.time.LocalDateTime;
/**
* OA发票信息
*
* @Author 陌上君莫问
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
@TableName("t_oa_invoice")
public class InvoiceEntity {
/**
* 发票信息ID
*/
@TableId(type = IdType.AUTO)
private Long invoiceId;
/**
* 开票抬头
*/
@DataTracerFieldLabel("开票抬头")
private String invoiceHeads;
/**
* 纳税人识别号
*/
@DataTracerFieldLabel("纳税人识别号")
private String taxpayerIdentificationNumber;
/**
* 银行账户
*/
@DataTracerFieldLabel("银行账户")
private String accountNumber;
/**
* 开户行
*/
@DataTracerFieldLabel("开户行")
private String bankName;
/**
* 备注
*/
@DataTracerFieldLabel("备注")
private String remark;
/**
* 企业ID
*/
private Long enterpriseId;
/**
* 禁用状态
*/
@DataTracerFieldLabel("禁用状态")
private Boolean disabledFlag;
/**
* 删除状态
*/
@DataTracerFieldLabel("删除状态")
private Boolean deletedFlag;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人ID
*/
private String createUserName;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,40 @@
package online.junmowen.blog.admin.module.business.oa.invoice.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import online.junmowen.blog.base.common.domain.PageParam;
import org.hibernate.validator.constraints.Length;
import java.time.LocalDate;
/**
* OA发票信息查询
*
* @Author 陌上君莫问
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class InvoiceQueryForm extends PageParam {
@Schema(description = "企业ID")
private Long enterpriseId;
@Schema(description = "关键字")
@Length(max = 200, message = "关键字最多200字符")
private String keywords;
@Schema(description = "开始时间")
private LocalDate startTime;
@Schema(description = "结束时间")
private LocalDate endTime;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "删除状态", hidden = true)
private Boolean deletedFlag;
}

View File

@@ -0,0 +1,22 @@
package online.junmowen.blog.admin.module.business.oa.invoice.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* OA发票信息编辑
*
* @Author 陌上君莫问
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class InvoiceUpdateForm extends InvoiceAddForm {
@Schema(description = "发票信息ID")
@NotNull(message = "发票信息ID不能为空")
private Long invoiceId;
}

View File

@@ -0,0 +1,58 @@
package online.junmowen.blog.admin.module.business.oa.invoice.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* OA发票信息
*
* @Author 陌上君莫问
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class InvoiceVO {
@Schema(description = "发票信息ID")
private Long invoiceId;
@Schema(description = "开票抬头")
private String invoiceHeads;
@Schema(description = "纳税人识别号")
private String taxpayerIdentificationNumber;
@Schema(description = "银行账户")
private String accountNumber;
@Schema(description = "开户行")
private String bankName;
@Schema(description = "备注")
private String remark;
@Schema(description = "企业")
private Long enterpriseId;
@Schema(description = "企业名称")
private String enterpriseName;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "创建人ID")
private Long createUserId;
@Schema(description = "创建人名称")
private String createUserName;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,144 @@
package online.junmowen.blog.admin.module.business.oa.invoice.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import online.junmowen.blog.admin.module.business.oa.enterprise.service.EnterpriseService;
import online.junmowen.blog.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO;
import online.junmowen.blog.admin.module.business.oa.invoice.dao.InvoiceDao;
import online.junmowen.blog.admin.module.business.oa.invoice.domain.*;
import online.junmowen.blog.base.common.domain.PageResult;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.base.common.util.SmartBeanUtil;
import online.junmowen.blog.base.common.util.SmartPageUtil;
import online.junmowen.blog.base.module.support.datatracer.constant.DataTracerConst;
import online.junmowen.blog.base.module.support.datatracer.constant.DataTracerTypeEnum;
import online.junmowen.blog.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 陌上君莫问
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Service
@Slf4j
public class InvoiceService {
@Resource
private InvoiceDao invoiceDao;
@Resource
private EnterpriseService enterpriseService;
@Resource
private DataTracerService dataTracerService;
/**
* 分页查询发票信息
*/
public ResponseDTO<PageResult<InvoiceVO>> queryByPage(InvoiceQueryForm queryForm) {
queryForm.setDeletedFlag(Boolean.FALSE);
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
List<InvoiceVO> invoiceList = invoiceDao.queryPage(page, queryForm);
PageResult<InvoiceVO> pageResult = SmartPageUtil.convert2PageResult(page, invoiceList);
return ResponseDTO.ok(pageResult);
}
public ResponseDTO<List<InvoiceVO>> queryList(Long enterpriseId) {
InvoiceQueryForm queryForm = new InvoiceQueryForm();
queryForm.setDeletedFlag(Boolean.FALSE);
queryForm.setDisabledFlag(Boolean.FALSE);
queryForm.setEnterpriseId(enterpriseId);
List<InvoiceVO> invoiceList = invoiceDao.queryPage(null, queryForm);
return ResponseDTO.ok(invoiceList);
}
/**
* 查询发票信息详情
*/
public ResponseDTO<InvoiceVO> 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<String> 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<String> 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<String> 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();
}
}

View File

@@ -0,0 +1,36 @@
package online.junmowen.blog.admin.module.business.oa.notice.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import online.junmowen.blog.base.common.enumeration.BaseEnum;
/**
* 公告、通知 可见范围类型
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Getter
@AllArgsConstructor
public enum NoticeVisibleRangeDataTypeEnum implements BaseEnum {
/**
* 员工
*/
EMPLOYEE(1, "员工"),
/**
* 部门
*/
DEPARTMENT(2, "部门"),
;
private final Integer value;
private final String desc;
}

View File

@@ -0,0 +1,140 @@
package online.junmowen.blog.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 online.junmowen.blog.admin.constant.AdminSwaggerTagConst;
import online.junmowen.blog.admin.module.business.oa.notice.domain.form.*;
import online.junmowen.blog.admin.module.business.oa.notice.domain.vo.*;
import online.junmowen.blog.admin.module.business.oa.notice.service.NoticeEmployeeService;
import online.junmowen.blog.admin.module.business.oa.notice.service.NoticeService;
import online.junmowen.blog.admin.module.business.oa.notice.service.NoticeTypeService;
import online.junmowen.blog.base.common.domain.PageResult;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.base.common.util.SmartRequestUtil;
import online.junmowen.blog.base.module.support.operatelog.annotation.OperateLog;
import online.junmowen.blog.base.module.support.repeatsubmit.annoation.RepeatSubmit;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 公告、通知、新闻等等
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat 卓大1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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<List<NoticeTypeVO>> getAll() {
return ResponseDTO.ok(noticeTypeService.getAll());
}
@Operation(summary = "通知公告类型-添加 @author 卓大")
@GetMapping("/oa/noticeType/add/{name}")
public ResponseDTO<String> add(@PathVariable String name) {
return noticeTypeService.add(name);
}
@Operation(summary = "通知公告类型-修改 @author 卓大")
@GetMapping("/oa/noticeType/update/{noticeTypeId}/{name}")
public ResponseDTO<String> update(@PathVariable Long noticeTypeId, @PathVariable String name) {
return noticeTypeService.update(noticeTypeId, name);
}
@Operation(summary = "通知公告类型-删除 @author 卓大")
@GetMapping("/oa/noticeType/delete/{noticeTypeId}")
public ResponseDTO<String> deleteNoticeType(@PathVariable Long noticeTypeId) {
return noticeTypeService.delete(noticeTypeId);
}
// --------------------- 【管理】通知公告-------------------------
@Operation(summary = "【管理】通知公告-分页查询 @author 卓大")
@PostMapping("/oa/notice/query")
@SaCheckPermission("oa:notice:query")
public ResponseDTO<PageResult<NoticeVO>> 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<String> 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<String> update(@RequestBody @Valid NoticeUpdateForm updateForm) {
return noticeService.update(updateForm);
}
@Operation(summary = "【管理】通知公告-更新详情 @author 卓大")
@GetMapping("/oa/notice/getUpdateVO/{noticeId}")
@SaCheckPermission("oa:notice:update")
public ResponseDTO<NoticeUpdateFormVO> getUpdateFormVO(@PathVariable Long noticeId) {
return ResponseDTO.ok(noticeService.getUpdateFormVO(noticeId));
}
@Operation(summary = "【管理】通知公告-删除 @author 卓大")
@GetMapping("/oa/notice/delete/{noticeId}")
@SaCheckPermission("oa:notice:delete")
public ResponseDTO<String> delete(@PathVariable Long noticeId) {
return noticeService.delete(noticeId);
}
// --------------------- 【员工】查看 通知公告 -------------------------
@Operation(summary = "【员工】通知公告-查看详情 @author 卓大")
@GetMapping("/oa/notice/employee/view/{noticeId}")
public ResponseDTO<NoticeDetailVO> 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<PageResult<NoticeEmployeeVO>> queryEmployeeNotice(@RequestBody @Valid NoticeEmployeeQueryForm noticeEmployeeQueryForm) {
return noticeEmployeeService.queryList(SmartRequestUtil.getRequestUserId(), noticeEmployeeQueryForm);
}
@Operation(summary = "【员工】通知公告-查询 查看记录 @author 卓大")
@PostMapping("/oa/notice/employee/queryViewRecord")
public ResponseDTO<PageResult<NoticeViewRecordVO>> queryViewRecord(@RequestBody @Valid NoticeViewRecordQueryForm noticeViewRecordQueryForm) {
return ResponseDTO.ok(noticeEmployeeService.queryViewRecord(noticeViewRecordQueryForm));
}
}

View File

@@ -0,0 +1,125 @@
package online.junmowen.blog.admin.module.business.oa.notice.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import online.junmowen.blog.admin.module.business.oa.notice.domain.entity.NoticeEntity;
import online.junmowen.blog.admin.module.business.oa.notice.domain.form.NoticeEmployeeQueryForm;
import online.junmowen.blog.admin.module.business.oa.notice.domain.form.NoticeQueryForm;
import online.junmowen.blog.admin.module.business.oa.notice.domain.form.NoticeViewRecordQueryForm;
import online.junmowen.blog.admin.module.business.oa.notice.domain.form.NoticeVisibleRangeForm;
import online.junmowen.blog.admin.module.business.oa.notice.domain.vo.NoticeEmployeeVO;
import online.junmowen.blog.admin.module.business.oa.notice.domain.vo.NoticeVO;
import online.junmowen.blog.admin.module.business.oa.notice.domain.vo.NoticeViewRecordVO;
import online.junmowen.blog.admin.module.business.oa.notice.domain.vo.NoticeVisibleRangeVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 公告、通知、新闻等等
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Mapper
public interface NoticeDao extends BaseMapper<NoticeEntity> {
// ================================= 数据范围相关 【子表】 =================================
/**
* 保存可见范围
*
*/
void insertVisibleRange(@Param("noticeId") Long noticeId, @Param("visibleRangeFormList") List<NoticeVisibleRangeForm> visibleRangeFormList);
/**
* 删除可见范围
*
*/
void deleteVisibleRange(@Param("noticeId") Long noticeId);
/**
* 相关可见范围
*
*/
List<NoticeVisibleRangeVO> queryVisibleRange(@Param("noticeId") Long noticeId);
// ================================= 通知公告【主表】 相关 =================================
/**
* 后管分页查询资讯
*
*/
List<NoticeVO> query(Page<?> page, @Param("query") NoticeQueryForm queryForm);
/**
* 更新删除状态
*
*/
void updateDeletedFlag(@Param("noticeId") Long noticeId);
// ================================= 通知公告【员工查看】 相关 =================================
/**
* 查询 员工 查看到的通知公告
*
*/
List<NoticeEmployeeVO> queryEmployeeNotice(Page<?> page,
@Param("requestEmployeeId") Long requestEmployeeId,
@Param("query") NoticeEmployeeQueryForm noticeEmployeeQueryForm,
@Param("requestEmployeeDepartmentIdList") List<Long> requestEmployeeDepartmentIdList,
@Param("deletedFlag") boolean deletedFlag,
@Param("administratorFlag") boolean administratorFlag,
@Param("departmentDataType") Integer departmentDataType,
@Param("employeeDataType") Integer employeeDataType
);
/**
* 查询 员工 未读的通知公告
*
*/
List<NoticeEmployeeVO> queryEmployeeNotViewNotice(Page<?> page,
@Param("requestEmployeeId") Long requestEmployeeId,
@Param("query") NoticeEmployeeQueryForm noticeEmployeeQueryForm,
@Param("requestEmployeeDepartmentIdList") List<Long> requestEmployeeDepartmentIdList,
@Param("deletedFlag") boolean deletedFlag,
@Param("administratorFlag") boolean administratorFlag,
@Param("departmentDataType") Integer departmentDataType,
@Param("employeeDataType") Integer employeeDataType
);
long viewRecordCount(@Param("noticeId")Long noticeId, @Param("employeeId")Long employeeId);
/**
* 查询通知、公告的 查看记录
*/
List<NoticeViewRecordVO> queryNoticeViewRecordList(Page page,@Param("queryForm") NoticeViewRecordQueryForm noticeViewRecordQueryForm);
/**
* 保存查看记录
*/
void insertViewRecord(@Param("noticeId") Long noticeId, @Param("employeeId") Long employeeId, @Param("ip") String ip, @Param("userAgent") String userAgent,@Param("pageViewCount") Integer pageViewCount);
/**
* 更新查看记录
*/
void updateViewRecord(@Param("noticeId")Long noticeId, @Param("employeeId")Long requestEmployeeId,@Param("ip") String ip, @Param("userAgent")String userAgent);
/**
* 更新 浏览量
*
* @param noticeId 通知 id
* @param pageViewCountIncrement 页面浏览量的增量
* @param userViewCountIncrement 用户浏览量的增量
*/
void updateViewCount(@Param("noticeId")Long noticeId,@Param("pageViewCountIncrement") Integer pageViewCountIncrement, @Param("userViewCountIncrement")Integer userViewCountIncrement);
}

View File

@@ -0,0 +1,19 @@
package online.junmowen.blog.admin.module.business.oa.notice.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import online.junmowen.blog.admin.module.business.oa.notice.domain.entity.NoticeTypeEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* 通知公告类型
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Mapper
public interface NoticeTypeDao extends BaseMapper<NoticeTypeEntity> {
}

View File

@@ -0,0 +1,99 @@
package online.junmowen.blog.admin.module.business.oa.notice.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 通知公告
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
@TableName("t_notice")
public class NoticeEntity {
@TableId(type = IdType.AUTO)
private Long noticeId;
/**
* 类型
*/
private Long noticeTypeId;
/**
* 标题
*/
private String title;
/**
* 是否全部可见
*/
private Boolean allVisibleFlag;
/**
* 是否定时发布
*/
private Boolean scheduledPublishFlag;
/**
* 发布时间
*/
private LocalDateTime publishTime;
/**
* 内容 纯文本
*/
private String contentText;
/**
* 内容 html
*/
private String contentHtml;
/**
* 附件
* 多个英文逗号分隔
*/
private String attachment;
/**
* 页面浏览量
*/
private Integer pageViewCount;
/**
* 用户浏览量
*/
private Integer userViewCount;
/**
* 来源
*/
private String source;
/**
* 作者
*/
private String author;
/**
* 文号
*/
private String documentNumber;
private Boolean deletedFlag;
private Long createUserId;
private LocalDateTime updateTime;
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,41 @@
package online.junmowen.blog.admin.module.business.oa.notice.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 通知公告类型
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
@TableName("t_notice_type")
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class NoticeTypeEntity {
@TableId(type = IdType.AUTO)
private Long noticeTypeId;
/**
* 名称
*/
private String noticeTypeName;
private LocalDateTime updateTime;
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,78 @@
package online.junmowen.blog.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 online.junmowen.blog.base.common.json.deserializer.FileKeyVoDeserializer;
import org.hibernate.validator.constraints.Length;
import java.time.LocalDateTime;
import java.util.List;
/**
* 通知公告 添加表单
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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<NoticeVisibleRangeForm> visibleRangeList;
}

View File

@@ -0,0 +1,35 @@
package online.junmowen.blog.admin.module.business.oa.notice.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import online.junmowen.blog.base.common.domain.PageParam;
import java.time.LocalDate;
/**
* 通知公告 员工查询表单
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class NoticeEmployeeQueryForm extends PageParam {
@Schema(description = "标题、作者、来源、文号")
private String keywords;
@Schema(description = "分类")
private Long noticeTypeId;
@Schema(description = "发布-开始时间")
private LocalDate publishTimeBegin;
@Schema(description = "未读标识")
private Boolean notViewFlag;
@Schema(description = "发布-截止时间")
private LocalDate publishTimeEnd;
}

View File

@@ -0,0 +1,48 @@
package online.junmowen.blog.admin.module.business.oa.notice.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import online.junmowen.blog.base.common.domain.PageParam;
import java.time.LocalDate;
/**
* 通知公告 管理查询表单
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class NoticeQueryForm extends PageParam {
@Schema(description = "分类")
private Long noticeTypeId;
@Schema(description = "标题、作者、来源")
private String keywords;
@Schema(description = "文号")
private String documentNumber;
@Schema(description = "创建人")
private String createUserName;
@Schema(description = "删除标识")
private Boolean deletedFlag;
@Schema(description = "创建-开始时间")
private LocalDate createTimeBegin;
@Schema(description = "创建-截止时间")
private LocalDate createTimeEnd;
@Schema(description = "发布-开始时间")
private LocalDate publishTimeBegin;
@Schema(description = "发布-截止时间")
private LocalDate publishTimeEnd;
}

View File

@@ -0,0 +1,23 @@
package online.junmowen.blog.admin.module.business.oa.notice.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 通知公告 更新表单
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class NoticeUpdateForm extends NoticeAddForm {
@Schema(description = "id")
@NotNull(message = "通知id不能为空")
private Long noticeId;
}

View File

@@ -0,0 +1,31 @@
package online.junmowen.blog.admin.module.business.oa.notice.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import online.junmowen.blog.base.common.domain.PageParam;
/**
* 通知公告 阅读记录查询
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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;
}

View File

@@ -0,0 +1,33 @@
package online.junmowen.blog.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 online.junmowen.blog.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum;
import online.junmowen.blog.base.common.swagger.SchemaEnum;
import online.junmowen.blog.base.common.validator.enumeration.CheckEnum;
/**
* 通知公告 可见范围数据
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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;
}

View File

@@ -0,0 +1,84 @@
package online.junmowen.blog.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 online.junmowen.blog.base.common.json.serializer.FileKeyVoSerializer;
import java.time.LocalDateTime;
/**
* 通知公告 详情
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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;
}

View File

@@ -0,0 +1,26 @@
package online.junmowen.blog.admin.module.business.oa.notice.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDate;
/**
* 通知公告 员工查看
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class NoticeEmployeeVO extends NoticeVO {
@Schema(description = "是否查看")
private Boolean viewFlag;
@Schema(description = "发布日期")
private LocalDate publishDate;
}

View File

@@ -0,0 +1,24 @@
package online.junmowen.blog.admin.module.business.oa.notice.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 通知公告 类型
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class NoticeTypeVO {
@Schema(description = "通知类型id")
private Long noticeTypeId;
@Schema(description = "通知类型-名称")
private String noticeTypeName;
}

View File

@@ -0,0 +1,35 @@
package online.junmowen.blog.admin.module.business.oa.notice.domain.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import online.junmowen.blog.base.common.json.serializer.FileKeyVoSerializer;
import java.util.List;
/**
* 用于更新 【通知、公告】 的 VO 对象
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class NoticeUpdateFormVO extends NoticeVO {
@Schema(description = "纯文本内容")
private String contentText;
@Schema(description = "html内容")
private String contentHtml;
@Schema(description = "附件")
@JsonSerialize(using = FileKeyVoSerializer.class)
private String attachment;
@Schema(description = "可见范围")
private List<NoticeVisibleRangeVO> visibleRangeList;
}

View File

@@ -0,0 +1,72 @@
package online.junmowen.blog.admin.module.business.oa.notice.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 新闻、公告 VO
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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;
}

View File

@@ -0,0 +1,49 @@
package online.junmowen.blog.admin.module.business.oa.notice.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 浏览记录 VO
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class NoticeViewRecordVO {
@Schema(description = "员工ID")
private Long employeeId;
@Schema(description = "员工姓名")
private String employeeName;
@Schema(description = "员工部门名称")
private String departmentName;
@Schema(description = "查看次数")
private Integer pageViewCount;
@Schema(description = "首次ip")
private String firstIp;
@Schema(description = "首次用户设备等标识")
private String firstUserAgent;
@Schema(description = "首次查看时间")
private LocalDateTime createTime;
@Schema(description = "最后一次 ip")
private String lastIp;
@Schema(description = "最后一次 用户设备等标识")
private String lastUserAgent;
@Schema(description = "最后一次查看时间")
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,29 @@
package online.junmowen.blog.admin.module.business.oa.notice.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import online.junmowen.blog.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum;
import online.junmowen.blog.base.common.swagger.SchemaEnum;
/**
* 新闻、公告 可见范围数据 VO
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Data
public class NoticeVisibleRangeVO {
@SchemaEnum(NoticeVisibleRangeDataTypeEnum.class)
private Integer dataType;
@Schema(description = "员工/部门id")
private Long dataId;
@Schema(description = "员工/部门 名称")
private String dataName;
}

View File

@@ -0,0 +1,62 @@
package online.junmowen.blog.admin.module.business.oa.notice.manager;
import jakarta.annotation.Resource;
import online.junmowen.blog.admin.module.business.oa.notice.dao.NoticeDao;
import online.junmowen.blog.admin.module.business.oa.notice.domain.entity.NoticeEntity;
import online.junmowen.blog.admin.module.business.oa.notice.domain.form.NoticeVisibleRangeForm;
import online.junmowen.blog.base.module.support.datatracer.constant.DataTracerTypeEnum;
import online.junmowen.blog.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 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Service
public class NoticeManager {
@Resource
private NoticeDao noticeDao;
@Resource
private DataTracerService dataTracerService;
/**
* 保存
*/
@Transactional(rollbackFor = Throwable.class)
public void save(NoticeEntity noticeEntity, List<NoticeVisibleRangeForm> 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<NoticeVisibleRangeForm> 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);
}
}

View File

@@ -0,0 +1,155 @@
package online.junmowen.blog.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 online.junmowen.blog.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum;
import online.junmowen.blog.admin.module.business.oa.notice.dao.NoticeDao;
import online.junmowen.blog.admin.module.business.oa.notice.domain.form.NoticeEmployeeQueryForm;
import online.junmowen.blog.admin.module.business.oa.notice.domain.form.NoticeViewRecordQueryForm;
import online.junmowen.blog.admin.module.business.oa.notice.domain.vo.*;
import online.junmowen.blog.admin.module.system.department.service.DepartmentService;
import online.junmowen.blog.admin.module.system.employee.domain.entity.EmployeeEntity;
import online.junmowen.blog.admin.module.system.employee.service.EmployeeService;
import online.junmowen.blog.base.common.domain.PageResult;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.base.common.util.SmartBeanUtil;
import online.junmowen.blog.base.common.util.SmartPageUtil;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 员工查看 通知。公告
*
* @Author 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Service
public class NoticeEmployeeService {
@Resource
private NoticeDao noticeDao;
@Resource
private NoticeService noticeService;
@Resource
private DepartmentService departmentService;
@Resource
private EmployeeService employeeService;
/**
* 查询我的 通知、公告清单
*/
public ResponseDTO<PageResult<NoticeEmployeeVO>> queryList(Long requestEmployeeId, NoticeEmployeeQueryForm noticeEmployeeQueryForm) {
Page<?> page = SmartPageUtil.convert2PageQuery(noticeEmployeeQueryForm);
List<Long> employeeDepartmentIdList = Lists.newArrayList();
EmployeeEntity employeeEntity = employeeService.getById(requestEmployeeId);
// 如果不是管理员 则获取请求人的 部门及其子部门
if (!employeeEntity.getAdministratorFlag() && employeeEntity.getDepartmentId() != null) {
employeeDepartmentIdList = departmentService.selfAndChildrenIdList(employeeEntity.getDepartmentId());
}
List<NoticeEmployeeVO> 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<NoticeDetailVO> 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<NoticeVisibleRangeVO> 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<Long> visibleDepartmentIdList = visibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.DEPARTMENT.equalsValue(e.getDataType()))
.map(NoticeVisibleRangeVO::getDataId).collect(Collectors.toList());
for (Long visibleDepartmentId : visibleDepartmentIdList) {
List<Long> departmentIdList = departmentService.selfAndChildrenIdList(visibleDepartmentId);
if (departmentIdList.contains(departmentId)) {
return true;
}
}
return false;
}
/**
* 分页查询 查看记录
*/
public PageResult<NoticeViewRecordVO> queryViewRecord(NoticeViewRecordQueryForm noticeViewRecordQueryForm) {
Page<?> page = SmartPageUtil.convert2PageQuery(noticeViewRecordQueryForm);
List<NoticeViewRecordVO> noticeViewRecordList = noticeDao.queryNoticeViewRecordList(page, noticeViewRecordQueryForm);
return SmartPageUtil.convert2PageResult(page, noticeViewRecordList);
}
}

View File

@@ -0,0 +1,240 @@
package online.junmowen.blog.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 online.junmowen.blog.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum;
import online.junmowen.blog.admin.module.business.oa.notice.dao.NoticeDao;
import online.junmowen.blog.admin.module.business.oa.notice.domain.entity.NoticeEntity;
import online.junmowen.blog.admin.module.business.oa.notice.domain.form.NoticeAddForm;
import online.junmowen.blog.admin.module.business.oa.notice.domain.form.NoticeQueryForm;
import online.junmowen.blog.admin.module.business.oa.notice.domain.form.NoticeUpdateForm;
import online.junmowen.blog.admin.module.business.oa.notice.domain.form.NoticeVisibleRangeForm;
import online.junmowen.blog.admin.module.business.oa.notice.domain.vo.NoticeTypeVO;
import online.junmowen.blog.admin.module.business.oa.notice.domain.vo.NoticeUpdateFormVO;
import online.junmowen.blog.admin.module.business.oa.notice.domain.vo.NoticeVO;
import online.junmowen.blog.admin.module.business.oa.notice.domain.vo.NoticeVisibleRangeVO;
import online.junmowen.blog.admin.module.business.oa.notice.manager.NoticeManager;
import online.junmowen.blog.admin.module.system.department.dao.DepartmentDao;
import online.junmowen.blog.admin.module.system.department.domain.entity.DepartmentEntity;
import online.junmowen.blog.admin.module.system.department.domain.vo.DepartmentVO;
import online.junmowen.blog.admin.module.system.department.service.DepartmentService;
import online.junmowen.blog.admin.module.system.employee.dao.EmployeeDao;
import online.junmowen.blog.admin.module.system.employee.domain.entity.EmployeeEntity;
import online.junmowen.blog.base.common.constant.StringConst;
import online.junmowen.blog.base.common.domain.PageResult;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.base.common.util.SmartBeanUtil;
import online.junmowen.blog.base.common.util.SmartPageUtil;
import online.junmowen.blog.base.module.support.datatracer.constant.DataTracerTypeEnum;
import online.junmowen.blog.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 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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<NoticeVO> query(NoticeQueryForm queryForm) {
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
List<NoticeVO> 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<String> add(NoticeAddForm addForm) {
// 校验并获取可见范围
ResponseDTO<String> 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<String> checkAndBuildVisibleRange(NoticeAddForm form) {
// 校验资讯分类
NoticeTypeVO noticeType = noticeTypeService.getByNoticeTypeId(form.getNoticeTypeId());
if (noticeType == null) {
return ResponseDTO.userErrorParam("分类不存在");
}
if (form.getAllVisibleFlag()) {
return ResponseDTO.ok();
}
/*
* 校验可见范围
* 非全部可见时 校验选择的员工|部门
*/
List<NoticeVisibleRangeForm> visibleRangeUpdateList = form.getVisibleRangeList();
if (CollectionUtils.isEmpty(visibleRangeUpdateList)) {
return ResponseDTO.userErrorParam("未设置可见范围");
}
// 校验可见范围-> 员工
List<Long> 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<Long> dbEmployeeIdList = employeeDao.selectBatchIds(employeeIdList).stream().map(EmployeeEntity::getEmployeeId).collect(Collectors.toList());
Collection<Long> subtract = CollectionUtils.subtract(employeeIdList, dbEmployeeIdList);
if (!subtract.isEmpty()) {
return ResponseDTO.userErrorParam("员工id不存在" + subtract);
}
}
// 校验可见范围-> 部门
List<Long> 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<Long> dbDeptIdList = departmentDao.selectBatchIds(deptIdList).stream().map(DepartmentEntity::getDepartmentId).collect(Collectors.toList());
Collection<Long> subtract = CollectionUtils.subtract(deptIdList, dbDeptIdList);
if (!subtract.isEmpty()) {
return ResponseDTO.userErrorParam("部门id不存在" + subtract);
}
}
return ResponseDTO.ok();
}
/**
* 更新
*
*/
public ResponseDTO<String> update(NoticeUpdateForm updateForm) {
NoticeEntity oldNoticeEntity = noticeDao.selectById(updateForm.getNoticeId());
if (oldNoticeEntity == null) {
return ResponseDTO.userErrorParam("通知不存在");
}
// 校验并获取可见范围
ResponseDTO<String> 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<String> 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);
NoticeTypeVO noticeType = noticeTypeService.getByNoticeTypeId(noticeEntity.getNoticeTypeId());
updateFormVO.setNoticeTypeName(noticeType.getNoticeTypeName());
updateFormVO.setPublishFlag(updateFormVO.getPublishTime() != null && updateFormVO.getPublishTime().isBefore(LocalDateTime.now()));
if (!updateFormVO.getAllVisibleFlag()) {
List<NoticeVisibleRangeVO> noticeVisibleRangeList = noticeDao.queryVisibleRange(noticeId);
List<Long> employeeIdList = noticeVisibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue().equals(e.getDataType()))
.map(NoticeVisibleRangeVO::getDataId)
.collect(Collectors.toList());
Map<Long, EmployeeEntity> 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.getDepartmentName());
}
}
updateFormVO.setVisibleRangeList(noticeVisibleRangeList);
}
return updateFormVO;
}
}

View File

@@ -0,0 +1,87 @@
package online.junmowen.blog.admin.module.business.oa.notice.service;
import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Resource;
import online.junmowen.blog.admin.module.business.oa.notice.dao.NoticeTypeDao;
import online.junmowen.blog.admin.module.business.oa.notice.domain.entity.NoticeTypeEntity;
import online.junmowen.blog.admin.module.business.oa.notice.domain.vo.NoticeTypeVO;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import online.junmowen.blog.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 陌上君莫问
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Service
public class NoticeTypeService {
@Resource
private NoticeTypeDao noticeTypeDao;
/**
* 查询全部
* @return
*/
public List<NoticeTypeVO> 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<String> add(String name) {
if (StrUtil.isBlank(name)) {
return ResponseDTO.userErrorParam("类型名称不能为空");
}
List<NoticeTypeEntity> 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<String> update(Long noticeTypeId, String name) {
if (StrUtil.isBlank(name)) {
return ResponseDTO.userErrorParam("类型名称不能为空");
}
NoticeTypeEntity noticeTypeEntity = noticeTypeDao.selectById(noticeTypeId);
if (noticeTypeEntity == null) {
return ResponseDTO.userErrorParam("类型名称不存在");
}
List<NoticeTypeEntity> noticeTypeEntityList = noticeTypeDao.selectList(null);
if (!CollectionUtils.isEmpty(noticeTypeEntityList)) {
Optional<NoticeTypeEntity> 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<String> delete(Long noticeTypeId) {
noticeTypeDao.deleteById(noticeTypeId);
return ResponseDTO.ok();
}
}

View File

@@ -0,0 +1,50 @@
package online.junmowen.blog.admin.module.system.datascope;
import online.junmowen.blog.admin.module.system.datascope.constant.DataScopeTypeEnum;
import online.junmowen.blog.admin.module.system.datascope.constant.DataScopeWhereInTypeEnum;
import online.junmowen.blog.admin.module.system.datascope.strategy.AbstractDataScopeStrategy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 数据范围
*
* @Author 陌上君莫问
* @Date 2022-03-18 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataScope {
DataScopeTypeEnum dataScopeType() ;
DataScopeWhereInTypeEnum whereInType() default DataScopeWhereInTypeEnum.EMPLOYEE;
/**
* DataScopeWhereInTypeEnum.CUSTOM_STRATEGY类型 才可使用joinSqlImplClazz属性
*/
Class<? extends AbstractDataScopeStrategy> joinSqlImplClazz() default AbstractDataScopeStrategy.class;
/**
* 多个参数已逗号分隔本属性主要用于joinSqlImplClazz 实现类跟进参数进行不同的范围控制如不使用CUSTOM_STRATEGY可不做配置
*/
String paramName() default "";
/**
*
* 第几个where 条件 从0开始
*/
int whereIndex() default 0;
/**
* DataScopeWhereInTypeEnum为CUSTOM_STRATEGY类型时此属性无效
*/
String joinSql() default "";
}

View File

@@ -0,0 +1,38 @@
package online.junmowen.blog.admin.module.system.datascope;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import online.junmowen.blog.admin.constant.AdminSwaggerTagConst;
import online.junmowen.blog.admin.module.system.datascope.domain.DataScopeAndViewTypeVO;
import online.junmowen.blog.admin.module.system.datascope.service.DataScopeService;
import online.junmowen.blog.base.common.domain.ResponseDTO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 查询支持的数据范围类型
*
* @Author 陌上君莫问
* @Date 2022-03-18 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@RestController
@Tag(name = AdminSwaggerTagConst.System.SYSTEM_DATA_SCOPE)
public class DataScopeController {
@Resource
private DataScopeService dataScopeService;
@Operation(summary = "获取当前系统所配置的所有数据范围 @author 陌上君莫问")
@GetMapping("/dataScope/list")
public ResponseDTO<List<DataScopeAndViewTypeVO>> dataScopeList() {
return dataScopeService.dataScopeList();
}
}

View File

@@ -0,0 +1,186 @@
package online.junmowen.blog.admin.module.system.datascope;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import online.junmowen.blog.admin.module.system.datascope.domain.DataScopeSqlConfig;
import online.junmowen.blog.admin.module.system.datascope.service.DataScopeSqlConfigService;
import online.junmowen.blog.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 陌上君莫问
* @Date 2022-03-18 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
@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<String> 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<String, Object> 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<String, Object> getParamList(String paramName, Object parameter) {
Map<String, Object> 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<String, Object> 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) {
}
}

View File

@@ -0,0 +1,56 @@
package online.junmowen.blog.admin.module.system.datascope.constant;
import online.junmowen.blog.base.common.enumeration.BaseEnum;
/**
* 数据范围 类型
*
* @Author 陌上君莫问
* @Date 2020/11/28 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
public enum DataScopeTypeEnum implements BaseEnum {
/**
* 系统通知
*/
NOTICE(1, 20, "系统通知", "系统通知数据范围"),
;
private final Integer value;
private final Integer sort;
private final String name;
private final String desc;
DataScopeTypeEnum(Integer value, Integer sort, String name, String desc) {
this.value = value;
this.sort = sort;
this.name = name;
this.desc = desc;
}
@Override
public Integer getValue() {
return value;
}
public Integer getSort() {
return sort;
}
@Override
public String getDesc() {
return desc;
}
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,65 @@
package online.junmowen.blog.admin.module.system.datascope.constant;
import online.junmowen.blog.base.common.enumeration.BaseEnum;
/**
* 数据可见范围类型
*
* @Author 陌上君莫问
* @Date 2020/11/28 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
public enum DataScopeViewTypeEnum implements BaseEnum {
/**
* 本人
*/
ME(0, 0, "本人"),
/**
* 部门
*/
DEPARTMENT(1, 5, "本部门"),
/**
* 本部门及下属子部门
*/
DEPARTMENT_AND_SUB(2, 10, "本部门及下属子部门"),
/**
* 全部
*/
ALL(10, 100, "全部");
private final Integer value;
private final Integer level;
private final String desc;
DataScopeViewTypeEnum(Integer value, Integer level, String desc) {
this.value = value;
this.level = level;
this.desc = desc;
}
@Override
public Integer getValue() {
return value;
}
public Integer getLevel() {
return level;
}
@Override
public String getDesc() {
return desc;
}
}

View File

@@ -0,0 +1,51 @@
package online.junmowen.blog.admin.module.system.datascope.constant;
import online.junmowen.blog.base.common.enumeration.BaseEnum;
/**
* 数据范围 sql where
*
* @Author 陌上君莫问
* @Date 2020/11/28 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://junmowen.online">陌上君莫问</a>
*/
public enum DataScopeWhereInTypeEnum implements BaseEnum {
/**
* 以员工IN
*/
EMPLOYEE(0, "以员工IN"),
/**
* 以部门IN
*/
DEPARTMENT(1, "以部门IN"),
/**
* 自定义策略
*/
CUSTOM_STRATEGY(2, "自定义策略");
private final Integer value;
private final String desc;
DataScopeWhereInTypeEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
@Override
public Integer getValue() {
return value;
}
@Override
public String getDesc() {
return desc;
}
}

Some files were not shown because too many files have changed in this diff Show More