Compare commits

...

177 Commits

Author SHA1 Message Date
xueqingkun a9348831f7 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0
# Conflicts:
#	know_sub_business/pom.xml
#	know_sub_rag/src/main/java/com/supervision/knowsub/config/ElasticsearchVectorStoreConfig.java
#	pom.xml
4 months ago
xueqingkun c1bed86083 1. 添加部署文档 4 months ago
xueqingkun 830b769334 1. 添加部署文档 4 months ago
liu 616678229f RAG代码提交 8 months ago
liu 4fb5164193 RAG代码提交 8 months ago
liu 665ee4af13 RAG代码提交 8 months ago
liu c5182c9e78 优化 8 months ago
liu 12d94a2cc5 优化 8 months ago
liu c0371f1106 优化 8 months ago
liu 4b3f90f5ca 新增模块 8 months ago
liu ac99475b72 新增模块 8 months ago
liu dc808e5ea2 新增模块 8 months ago
liu f6f9668e41 新增模块 8 months ago
liu 822b766890 新增模块 8 months ago
liu 6eb2f5f7e1 新增模块 8 months ago
liu 6056be868b bugfix:增加字段,解决报送时间不正确的问题 8 months ago
liu bcf8f80cf0 bugfix:增加字段,解决报送时间不正确的问题 8 months ago
liu 3a45d21bdc bugfix:修复首页统计不正确的问题 8 months ago
liu 67323144e5 bugfix:修复首页统计不正确的问题 8 months ago
liu 97aed8f4b8 优化:增加了部分注释的展示 8 months ago
liu 0aaf410670 bugfix:修复撤回中不生效的问题 8 months ago
liu 9c99d93488 bugfix:修复修改内容不生效的问题 8 months ago
liu 5c865858cf bugfix:修复链接不生效的问题 8 months ago
xueqingkun 441d19b05b updateUserInfo 允许修改账户名 8 months ago
liu c52e90207c bugfix:修复知识审批类型不生效的问题 8 months ago
xueqingkun 44b95e8198 updateUserInfo 允许修改账户名 8 months ago
liu ecd71a1635 优化过期失效的字段 8 months ago
liu 556a93394a 优化过期失效的字段 8 months ago
liu 10aa3e7496 优化过期失效的字段 8 months ago
liu 92324e5611 知识提报增加知识来源展示 8 months ago
liu 5cc2096081 测试时,国企检测为一小时一次 8 months ago
liu 66dd45bd33 测试时,国企检测为一小时一次 8 months ago
liu 05599e81ed 测试时,国企检测为一小时一次 8 months ago
liu 6969ea36e7 增加流程发文时间的字段显示 8 months ago
xueqingkun 2ed247bbdd saveSubLibrary 修改提示语言 8 months ago
liu 48503274df 增加驳回的一些状态 8 months ago
liu 4772481fe8 增加驳回的一些状态 8 months ago
liu 20e0b9e66e 增加驳回的一些状态 8 months ago
liu 8c3854ed7b 增加驳回的一些状态 8 months ago
liu 9db1cbe498 增加驳回的一些状态 8 months ago
xueqingkun 026ced7ca7 saveFlow 添加同名校验 8 months ago
xueqingkun 9b8343c270 fix bugs update-flow 8 months ago
liu c81a637bbd bugfix:225 同一个流程设置两个审批人,两个人审批通过后,在流程记录里差不多第一个人的记录 8 months ago
liu 2e6d8f5bc0 优化,首页状态查询 8 months ago
liu b0583d3821 优化,增加报送时间字段 8 months ago
liu 5e19b9302f 优化,增加报送时间字段 8 months ago
liu 4738cf5a5b 优化,修改LocalDate 8 months ago
liu 93c5fa9966 优化,修改LocalDate 8 months ago
liu c103d319ce 优化,增加定时任务自动失效 8 months ago
liu 85018312e6 优化,增加实例字段 8 months ago
liu 6cfda3f94d 优化,增加实例字段 8 months ago
xueqingkun b9aaf77f26 role info add roletype 8 months ago
liu 5458f7508e 优化,增加实例字段 8 months ago
xueqingkun b13559fc89 role info add roletype 8 months ago
xueqingkun 0ce350a564 role info add roletype 8 months ago
xueqingkun f712898e2a fix bugs 8 months ago
xueqingkun 09e091f2e1 fix bugs 8 months ago
xueqingkun b8107fe9ab fix bugs 8 months ago
xueqingkun ca003bb585 添加头像字段 8 months ago
liu cc179c0490 优化,增加实例字段 8 months ago
xueqingkun 3ab095c896 fix bugs 8 months ago
xueqingkun 63ac2da86e 添加url过来规则 8 months ago
xueqingkun ade711d440 添加 修改用户状态 接口 8 months ago
liu 3a3ba9f264 优化,增加实例字段 8 months ago
xueqingkun 731e9c452e 修改docker构建相关文件 8 months ago
liu 3d337e3770 优化,增加实例字段 8 months ago
xueqingkun 6a370ccb3f 修改docker构建相关文件 8 months ago
liu c31fa4b91b bugfix 8 months ago
liu 8ef17b0c0d bugfix 8 months ago
xueqingkun 54aa030842 添加docker构建相关文件 8 months ago
xueqingkun 9bcea5047d Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
xueqingkun 79050e5dd6 列表查询添加排序 8 months ago
xueqingkun b161b1ab1c 添加docker构建相关文件 8 months ago
liu 7d00c995fa bugfix 8 months ago
xueqingkun 796d19ce48 添加流程查询排序功能 8 months ago
xueqingkun fcbcfbf4fc 代码调整 8 months ago
liu 16665d2b50 bugfix 8 months ago
liu e222210897 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
liu 652bd5823c bugfix 8 months ago
xueqingkun 8458618c9b 添加model类中的@TableField(fill = FieldFill.INSERT) 8 months ago
liu 5ec1b19314 bugfix 8 months ago
liu 4a4ae22e18 优化,分页查询状态由后端提供 8 months ago
liu 4a874e3191 bugfix 8 months ago
liu b597fc8c6c bugfix 8 months ago
liu 6134044f67 bugfix 8 months ago
liu be1a84581d bugfix 8 months ago
liu 2581d63a3d 优化日志记录 8 months ago
liu e2d7f6b70b 优化 8 months ago
liu 4148839796 优化 8 months ago
xueqingkun fed6b8d003 调整代码 8 months ago
liu 367780fd8e bugfix 8 months ago
liu ddd363678a bugfix 8 months ago
liu 306023b414 增加摘要字段 8 months ago
xueqingkun 0de6d3cd0e 添加字典关联相关表 8 months ago
xueqingkun b8d4e127f2 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
xueqingkun c2f14f42ff 添加字典关联相关功能 8 months ago
liu 0ba0a8dc9b bugfix 8 months ago
xueqingkun 6c34611600 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
xueqingkun 9f17d99c92 添加字典关联相关表 8 months ago
liu 50008b4786 优化分页查询接口 8 months ago
liu 8b35fda32d 优化文件上传 8 months ago
xueqingkun 23689b08a8 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
xueqingkun 63148d39e0 添加用户管理相关功能 8 months ago
liu ca05bbf00a 用户增加部门信息 8 months ago
xueqingkun 55432b8039 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
xueqingkun 0e4af14729 添加用户管理相关功能 8 months ago
liu f9205b6288 bugfix 8 months ago
xueqingkun 24ee3299db 新增system_user_role_relation表相关类 8 months ago
xueqingkun a2beaffbe8 新增system_user_role_relation表相关类 8 months ago
xueqingkun bf843d00d2 新增文件下载功能 8 months ago
xueqingkun 4919b5b58c Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
xueqingkun eddea4349a 添加部门相关功能代码 8 months ago
xueqingkun 95c44aa499 ks_system_user添加status字段 8 months ago
liu ba4fa3500d 首页知识统计 8 months ago
xueqingkun bf19792821 ks_system_dept添加parentDeptId字段 8 months ago
xueqingkun a367b5e43c 修改角色功能相关代码 8 months ago
xueqingkun 460eafc17a 修改应用子库相关代码 8 months ago
xueqingkun b85c59cd6d 添加流程修改相关代码 8 months ago
xueqingkun 35c4e1064c 修改createtime updatetime 数据类型为datetime类型 8 months ago
xueqingkun 81440497f2 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
xueqingkun 55c1cf864b 添加流程修改相关代码 8 months ago
liu 7df455e52f 优化登录流程 8 months ago
xueqingkun 19b1e27d19 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
xueqingkun 6fd8f43abf SystemUser 添加最后一次登录时间字段 8 months ago
liu 78eb3c8eba 优化登录流程 8 months ago
xueqingkun f850986442 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
xueqingkun f923f5d542 提交mapper 8 months ago
liu 64ec4f5add 提交流程提交相关代码 8 months ago
liu fd4a95a514 提交流程提交相关代码 8 months ago
xueqingkun 09af8bc295 添加流程创建相关代码 8 months ago
liu 8443e627a8 提交流程提交相关代码 8 months ago
liu 01273bbaa6 提交流程提交相关代码 8 months ago
liu e34786f505 提交流程提交相关代码 8 months ago
liu 4d18d7f31e 提交枚举类 8 months ago
xueqingkun 5335db573e 提交部分代码2 8 months ago
xueqingkun c9fdfd7713 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
xueqingkun 5463942117 提交部分代码 8 months ago
liu 13de6c99c2 提交知识审批部分业务 8 months ago
xueqingkun fb8b39b876 去除SystemFlow中的flowtype 8 months ago
xueqingkun 7fffc967bc 新加表 8 months ago
xueqingkun 9f50e47d34 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
liu fd06e8c95e 提交知识管理代码 8 months ago
xueqingkun 2600422585 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
liu 28babec162 提交知识管理代码 8 months ago
xueqingkun 4845c9717e 添加用户登录相关功能 8 months ago
xueqingkun 30ea11fc10 添加sm2加密工具类 8 months ago
xueqingkun 7b9d194a5b 修复子库管理分页查询bug
修复子库管理新增重复bug
8 months ago
xueqingkun 33b5d518a9 添加角色管理功能接口 8 months ago
xueqingkun bbdef82170 Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
xueqingkun 5e5a87e564 添加应用子库功能接口 8 months ago
liu 770d0d3d65 提交文件方法 8 months ago
liu 99531ba68f 提交知识新增 8 months ago
liu 74d89f37d1 Revert "test回退"
This reverts commit ff61e4f4fb.
8 months ago
liu ff61e4f4fb test回退 8 months ago
liu b74d67a1cd 提交知识库查询 8 months ago
liu ec04dde752 提交知识库查询 8 months ago
xueqingkun 114234c1fd Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
xueqingkun f532438b32 pom 添加依赖 8 months ago
liu b450b1297f Merge remote-tracking branch 'origin/dev_1.0.0' into dev_1.0.0 8 months ago
liu e96b47142a 提交知识库查询 8 months ago
xueqingkun de2690e424 model 添加FieldFill.INSERT FieldFill.INSERT_UPDATE 8 months ago
liu 2f13836417 提交知识库查询 8 months ago
liu 3d6e28670e init 8 months ago
xueqingkun 8f5bf9f49b 修改pom 8 months ago
liu b2b9a4a909 init 8 months ago
xueqingkun 1aad5c6343 添加model模块pom依赖
(cherry picked from commit 1b3bf54515)
8 months ago
xueqingkun 53cfd57206 添加model模块
(cherry picked from commit 771f7b6646)
8 months ago
liu f52d3fd39a init 8 months ago
liu 286adc84aa init 8 months ago
liu 47345c9917 init 8 months ago
liu 3a01a66a08 init 8 months ago
liu 2ef62e26ef init 8 months ago
liu 41bd894b1e init 8 months ago
liu a0e1d6ad41 init 8 months ago
liu 46b84a60af init 8 months ago
liu a2e5eac4dc init 8 months ago
liu edb6297ff4 init 8 months ago

2
.gitignore vendored

@ -24,3 +24,5 @@
hs_err_pid*
replay_pid*
.idea

@ -1,3 +1,51 @@
# know_sub
知识报送后端服务
## 服务组件介绍
| 服务名称 | docker 镜像名称 | 服务描述 |
|------|-------------|------------|
| 前端服务 | know-sub-nginx:1.0.0 | 提供前端服务 |
| 后端服务 | know-sub-web:1.0.0 | 提供展示报送后端服务 |
| 数据库 | mysql:5.7 | 提供数据库服务 |
### 安装包结构说明
| 文件/文件夹 | 说明 |
| - |---------------|
| know-sub-nginx/ | 存放nginx静态文件 |
| know-sub-web/ | 存放后端服务程序 |
| mysql | 数据库持久化数据 |
| know_sub_init.sql | 初始化数据库脚本 |
| .env | 应用的环境配置 |
| docker-compose.yml | docker-compose 配置文件 |
| images-all-one.tar.gz | 镜像文件 |
## 快速启动
### 要求
- CPU >= 8 核
- RAM >= 16 GB
- Disk >= 500 GB
- Docker >= 24.0.6 & Docker Compose >= v2.27.0
### 步骤
1. 下载安装包,解压到~/install/know-sub/docker-compose目录
2. 进入~/install/know-sub/docker-compose目录执行加载镜像命令
```bash
docker load -i images-all-one.tar.gz
```
3. 执行如下命令启动服务
```bash
docker-compose up -d
```
4. 查看启动的服务状态(由于第一次启动mysql需要执行初始化脚本需要等待一段时间know-sub-web 才能连接到数据库)
```bash
docker-compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
know-sub-mysql mysql:5.7 "docker-entrypoint.s…" mysql 12 seconds ago Up 11 seconds (healthy) 33060/tcp, 0.0.0.0:42415->3306/tcp
know-sub-nginx know-sub-nginx:1.0.0 "/docker-entrypoint.…" know-sub-nginx 12 seconds ago Up 11 seconds 443/tcp, 0.0.0.0:1180->80/tcp
know-sub-web know-sub-web:1.0.0 "java -Xms256m -Xmx1…" know-sub-web 12 seconds ago Up 11 seconds 0.0.0.0:9201->9201/tcp
```
5. 访问地址
http://ip:1180/#/login 用户名admin 密码: qgYXFnT1

@ -0,0 +1 @@
-- 新增RAG搜索的SQL

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

@ -0,0 +1,13 @@
# mysql相关配置内容
MYSQL_PASSWORD=llm@984573~!eda
MYSQL_PORT=42415
# 知识报送后台服务相关配置内容
WEB_HTTP_PORT=9201
SPRING_PROFILES_ACTIVE=prod
# nginx相关配置内容
NGINX_HTTP_PORT=1180
KNOW_SUB_SERVERS=know-sub-web:9201
TIMEZONE='Asia/Shanghai'

@ -0,0 +1,65 @@
services:
mysql:
image: mysql:5.7
container_name: know-sub-mysql
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
- TZ=${TIMEZONE}
command:
--max_connections=100
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--default-authentication-plugin=mysql_native_password
--tls_version="TLSv1.2,TLSv1.3"
ports:
- ${MYSQL_PORT}:3306
volumes:
- ./mysql/data:/var/lib/mysql
- ./know_sub_init.sql:/docker-entrypoint-initdb.d/know_sub_init.sql
networks:
- know-sub-network
healthcheck:
test: [ "CMD", "mysqladmin" ,"ping", "-uroot", "-p${MYSQL_PASSWORD}" ]
interval: 10s
timeout: 10s
retries: 3
start_period: 40s
restart: always
know-sub-web:
depends_on:
mysql:
condition: service_started
image: know-sub-web:1.0.0
container_name: know-sub-web
ports:
- ${WEB_HTTP_PORT}:9201
volumes:
- ./know-sub-web/:/data/know_sub/web/
command:
--spring.profiles.active=${SPRING_PROFILES_ACTIVE}
--datasource.password=${MYSQL_PASSWORD}
environment:
- TZ=${TIMEZONE}
networks:
- know-sub-network
restart: always
know-sub-nginx:
depends_on:
know-sub-web:
condition: service_started
image: know-sub-nginx:1.0.0
container_name: know-sub-nginx
ports:
- ${NGINX_HTTP_PORT}:80
volumes:
- ./know-sub-nginx/html/:/usr/share/nginx/html/
environment:
- TZ=${TIMEZONE}
- KNOW_SUB_SERVERS=${KNOW_SUB_SERVERS}
networks:
- know-sub-network
restart: always
networks:
know-sub-network:
driver: bridge

File diff suppressed because one or more lines are too long

@ -0,0 +1,23 @@
# 设置基础镜像
FROM nginx:1.25
# 覆盖原镜像的启动脚本
COPY ./docs/docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod 777 /docker-entrypoint.sh
# 删除默认的配置文件
RUN rm /etc/nginx/conf.d/default.conf
# 复制配置文件信息
COPY ./docs/conf.d/http.conf ./docs/conf.d/https.conf /etc/nginx/conf.d/
COPY ./docs/conf.d/nginx.conf /etc/nginx/nginx.conf
COPY ./docs/conf.d/servers.conf.template /data/know_sub/nginx/conf/servers.conf.template
# 复制ssl证书信息
COPY ./docs/ssl /data/know_sub/nginx/ssl
# 暴漏服务端口
EXPOSE 80 443
# 设置启动命令
CMD ["nginx","-g","daemon off;"]

@ -0,0 +1,20 @@
# 构建步骤
- 运行Dockerfile文件构建镜像 docker build -t know-sub-nginx:1.0.0 .
# 启动说明
- docker run -itd --name know-sub-nginx -p 1180:80 -v /data/know_sub/html/:/usr/share/nginx/html/ \
-e KNOW_SUB_SERVERS=192.168.10.138:9201 know-sub-nginx:1.0.0
- itd : -itd : 无交互模式启动
- -p 1180:80 : 端口映射 **必填**
- KNOW_SUB_SERVERS : 后端服务器地址,只允许有单个。 **必填**
- know-sub-nginx:1.0.0 构建的镜像名称
# 注意事项
- 如果需要对后端服务进行负载均衡把 /data/know_sub/nginx/conf/ 目录挂载出来然后创建配置文件servers.conf\
编辑配置文件:
```shell
upstream know_sub_servers {
server $KNOW_SUB_SERVERS;
}
```

@ -0,0 +1,28 @@
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
client_max_body_size 20M; # 设置客户端请求的最大上传大小为 20MB可以根据实际情况修改
location / {
root /usr/share/nginx/html/dist;
index index.html index.htm;
# add_header Cache-Control no-store;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html/dist;
}
location /know-sub/ {
proxy_pass http://know_sub_servers/know-sub/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

@ -0,0 +1,44 @@
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /data/know_sub/nginx/ssl/cert.pem;
ssl_certificate_key /data/know_sub/nginx/ssl/key.pem;
# 配置SSL参数
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384;
# 配置SSL会话缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 30m;
# 配置SSL安全性选项
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
client_max_body_size 20M; # 设置客户端请求的最大上传大小为 20MB可以根据实际情况修改
location / {
root /usr/share/nginx/html/dist;
index index.html index.htm;
# add_header Cache-Control no-store;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html/dist;
}
location /know-sub/ {
proxy_pass http://know_sub_servers/know-sub/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

@ -0,0 +1,33 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /data/know_sub/nginx/conf/*.conf;
include /etc/nginx/conf.d/*.conf;
}

@ -0,0 +1,6 @@
# 前台服务后端地址,多个地址可用与负载均衡
# 解析以逗号分隔的多个 upstream 值
upstream know_sub_servers {
server $KNOW_SUB_SERVERS;
}

@ -0,0 +1,64 @@
#!/bin/sh
# vim:sw=4:ts=4:et
set -e
# /etc/nginx/conf.d/servers.conf 文件不存在,就通过环境变量 KNOW_SUB_SERVERS生成/data/know_sub/nginx/conf/servers.conf
if [ ! -f "/data/know_sub/nginx/conf/servers.conf" ]; then
echo "BEGIN REPLACE SERVERS.CONF ...."
if [ -z "${KNOW_SUB_SERVERS}" ]; then
export KNOW_SUB_SERVERS="${KNOW_SUB_SERVERS}"
fi
# 替换文件中的变量
envsubst '$KNOW_SUB_SERVERS' < /data/know_sub/nginx/conf/servers.conf.template > /data/know_sub/nginx/conf/servers.conf
echo "REPLACEMENT COMPLETE"
else
echo "SERVERS.CONF ALREADY EXISTS"
fi
entrypoint_log() {
if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
echo "$@"
fi
}
if [ "$1" = "nginx" ] || [ "$1" = "nginx-debug" ]; then
if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then
entrypoint_log "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration"
entrypoint_log "$0: Looking for shell scripts in /docker-entrypoint.d/"
find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do
case "$f" in
*.envsh)
if [ -x "$f" ]; then
entrypoint_log "$0: Sourcing $f";
. "$f"
else
# warn on shell scripts without exec bit
entrypoint_log "$0: Ignoring $f, not executable";
fi
;;
*.sh)
if [ -x "$f" ]; then
entrypoint_log "$0: Launching $f";
"$f"
else
# warn on shell scripts without exec bit
entrypoint_log "$0: Ignoring $f, not executable";
fi
;;
*) entrypoint_log "$0: Ignoring $f";;
esac
done
entrypoint_log "$0: Configuration complete; ready for start up"
else
entrypoint_log "$0: No files found in /docker-entrypoint.d/, skipping configuration"
fi
fi
exec "$@"

@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDdzCCAl8CFC5Pwm//gTURwneg5cjhbkyueufNMA0GCSqGSIb3DQEBCwUAMHgx
CzAJBgNVBAYTAkNIMQswCQYDVQQIDAJOSjEOMAwGA1UEBwwFbmogeWgxDDAKBgNV
BAoMA3NzdDEMMAoGA1UECwwDc3N0MQ8wDQYDVQQDDAZzc3RvcmcxHzAdBgkqhkiG
9w0BCQEWEDEyMzQ1NkBlbWFpbC5jb20wHhcNMjMxMTEwMDEyMzIzWhcNMjMxMjEw
MDEyMzIzWjB4MQswCQYDVQQGEwJDSDELMAkGA1UECAwCTkoxDjAMBgNVBAcMBW5q
IHloMQwwCgYDVQQKDANzc3QxDDAKBgNVBAsMA3NzdDEPMA0GA1UEAwwGc3N0b3Jn
MR8wHQYJKoZIhvcNAQkBFhAxMjM0NTZAZW1haWwuY29tMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEA0/VotZw72C+GVQnKsVfwtxeXEPPfiUfE0/H6mp8A
jhxHnFofNK5mvjYs3++U9UEfP1jq84flaD5qgrEGzhauJg6NdrLdcd9RCguu8Pkm
YHIMVl9UzLQexKg15wh0Fc8S6vc3xGBPfosS29YJulXcUZB2CeVJ9CXCTx2Z1dRG
Ug9eMTiPwgB8GnQ56h2GjTyCnVWeVoXBFVef6sY0czkPoJVPk7TZI3K5BmaLBNX1
0L4OzaJtOa6ZWll3rGxVrk/7oB+Z3t3l8NXF9SrmC039K3sZerNLjlVUdkGD52jz
xCc4Eixcus2pduKfIP3dUhdn05TNUln1/nIFRErcXUWdswIDAQABMA0GCSqGSIb3
DQEBCwUAA4IBAQCLmsogw3J6KOyHnzaWQaKvhRzqPAupIBY4HYTk+hyOahgMMkkd
+3QIiWU/pp0Nu5iyYytzGRCQIz1Jh+xpk3UQVpayDB8C4XIB7oyzpuatTuyeCvq/
lnDlk8jk64EewLLWE2pOce6yAKZ/xhcQiDI9YcjgGOkUOjv7Hgqhzwlafrt5FXGB
znFmVi5A52RqkkteplkRsl08OE5VmfxwFYJWZ7QXMlp5ec13oCE21PU+cmLLF/Vb
xl7JJKeMOgDICiSczcYzwP56SiYFktKQ8KmDotFWgBM9mtxkEcOqPb2Xe9vzOclk
AK+5bHhgF2yZGhjbNuzp/FwGSAIozuR5IXxJ
-----END CERTIFICATE-----

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICvTCCAaUCAQAweDELMAkGA1UEBhMCQ0gxCzAJBgNVBAgMAk5KMQ4wDAYDVQQH
DAVuaiB5aDEMMAoGA1UECgwDc3N0MQwwCgYDVQQLDANzc3QxDzANBgNVBAMMBnNz
dG9yZzEfMB0GCSqGSIb3DQEJARYQMTIzNDU2QGVtYWlsLmNvbTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBANP1aLWcO9gvhlUJyrFX8LcXlxDz34lHxNPx
+pqfAI4cR5xaHzSuZr42LN/vlPVBHz9Y6vOH5Wg+aoKxBs4WriYOjXay3XHfUQoL
rvD5JmByDFZfVMy0HsSoNecIdBXPEur3N8RgT36LEtvWCbpV3FGQdgnlSfQlwk8d
mdXURlIPXjE4j8IAfBp0Oeodho08gp1VnlaFwRVXn+rGNHM5D6CVT5O02SNyuQZm
iwTV9dC+Ds2ibTmumVpZd6xsVa5P+6Afmd7d5fDVxfUq5gtN/St7GXqzS45VVHZB
g+do88QnOBIsXLrNqXbinyD93VIXZ9OUzVJZ9f5yBURK3F1FnbMCAwEAAaAAMA0G
CSqGSIb3DQEBCwUAA4IBAQCFdN/RMNZtduCGs21f5Le4uGePh2nHzqB2tPzPsWYV
LLPO/pInHB0lQ3vJLFtIeaTLIDwB+AFcdM7rNhMGz9rj/Qrk9LCvgm+CQGUOy1h4
r1tJ27z+8xfwHls/fgghHnSLoaUvma2FfIQzZc/rGTDLkdERBZ1skxOVqIw56qlA
aPyKUt9s/fg6P5xMSv5SDIR89n0i3TChSa8nNdHV1Ld44mLZ7Aw29ChXI5DaQ05t
B6rdNz3AofmxlkzHIlFl46kPMy4H5jgHWlOBT+eLHv/fecPWCNpgnr9vi7O2Ih9o
i8KHDeK1T9Bl5U+sGof6E0Sey/xBOEGnYzuiQUl4kxfL
-----END CERTIFICATE REQUEST-----

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDT9Wi1nDvYL4ZV
CcqxV/C3F5cQ89+JR8TT8fqanwCOHEecWh80rma+Nizf75T1QR8/WOrzh+VoPmqC
sQbOFq4mDo12st1x31EKC67w+SZgcgxWX1TMtB7EqDXnCHQVzxLq9zfEYE9+ixLb
1gm6VdxRkHYJ5Un0JcJPHZnV1EZSD14xOI/CAHwadDnqHYaNPIKdVZ5WhcEVV5/q
xjRzOQ+glU+TtNkjcrkGZosE1fXQvg7Nom05rplaWXesbFWuT/ugH5ne3eXw1cX1
KuYLTf0rexl6s0uOVVR2QYPnaPPEJzgSLFy6zal24p8g/d1SF2fTlM1SWfX+cgVE
StxdRZ2zAgMBAAECggEAAPoKh3u20uI1LkMjSfnrxAw5x/w3tXw9LfTZgMjmycDb
m57Wsflzw8CgKFAEUbUBHdudCY5AwmA3QW7rZxu3pbk/caKVXqb2yqMPJVEgmiUs
ZWF/FIpn8eQMi4oAbvFLVwXYnfELrLubVKQB23f10fJmeNkzpApggNjUEqYtxMcH
MjfUmXzrZhvFKdRjdmyITa4gI9djuRvOIfWz0bZTePUtcfgCfpkM3lbxWRIst7Dg
FqCcgX68XOHHDCzzWTE7LasFBZx3mAcOyRMC+MKw96becC4r1c2KFFKh8tFp57y2
hQ1ybjxeF2MaWf3I/ioi2uTUza+L8m2RsKwABcRwIQKBgQDUrnn/WtKdryDU0rBj
cwsKTrMCycblwYCJj58cGSiETTVJOlhh1N2QtE/kwQI69tUVOc7C5p5FZzk+iff7
KwvwDqurtW5kKHE5IamUnKqv32bbHuRtg9CB0ktmmbxOrwP5s+QGhh5fKGvFKs3D
xVytLVw76f+BLK4NaBbzCdEN6wKBgQD/IT0F9f9XnTIa1a/bNVLCuRRZdWjDK40i
bD8EgO9T/FxK4yXSV3IB2C6mQNdMxDcmFBTS7EoXPZpZYuFCqBKQvV1OQ0yUAy2b
+PmmZMBakbpQHkIjkq2cgXNXaVdDeKPfoG4SqPz/6x7p/Np/UG9Ey8juNuQXmIiH
wwjwTfqVWQKBgQDNd6ogykuDTvd24/zIdxIJaTKD1Q+0U5asTvY2HRAJkNWT4ywT
h6Rt8eTlaJmRAXmmQezAWjA5eJnTE1NhcZrc1i9/eY4mcPPBcAX2rswvkLI7qsKg
EqJTaSiy/H7xvR8oE2SN8PBSmihTmSCkq3z3SUU8FLpkvxd/mDnjnm469QKBgQCg
rRQ7ftPTH+MAV3erPIfkrp8MQA88a181QKrncTRI1nRhjXCyafQZCUdH2So+5Iw+
5QLAW6PFwzxD8yweyK74jOoIcgX2aZH92u2PR4CFCaYm8weAU84W9MfpUyRsD7xV
CDqKcfb0TeVoQ6Bv8f5Be34N2HAKFDxYFBK7FMEt8QKBgDNBG3n8/912dDWV1Dve
o4v+TAnlAMHgEXZH+VCCzeIyj1UkUh4sxdIGGaGCPrWGrqxIYIKPKX8gPIWQ7QJj
QJZyL5nqGXWwZUvBuHzE3tB24XJpuHGfg+oBdDfg0aiEMTQKnRORdgHHVdB9W3SN
2TrXQbtwB1X+wioA4615n6ih
-----END PRIVATE KEY-----

@ -0,0 +1,11 @@
# 设置基础镜像
FROM openjdk:17-jdk-alpine
# 复制java jar 到容器中
#COPY know_sub_business-1.0.0.jar /data/know_sub/web/know_sub_business-1.0.0.jar
# 暴漏服务端口
EXPOSE 9201
# 设置启动命令
ENTRYPOINT ["java","-Xms256m","-Xmx1g", "-Xss2m", "-Dspring.profiles.active=prod","-Dfile.encoding=utf-8","-Duser.timezone=Asia/Shanghai","-jar","/data/know_sub/web/know_sub_business-1.0.0.jar"]

@ -0,0 +1,8 @@
构建步骤
- 运行Dockerfile文件构建镜像 docker build -t know-sub-web:1.0.0 .
# 启动说明
- docker run -itd --name know-sub-web -p9201:9201 -v /data/know_sub/web/:/data/know_sub/web/ know-sub-web:1.0.0 --spring.profiles.active=test
- itd : -itd : 无交互模式启动
- -p9201:9201 : 端口映射 **必填**
- know-sub-web:1.0.0 构建的镜像名称

@ -6,12 +6,12 @@
<groupId>com.supervision</groupId>
<artifactId>know_sub</artifactId>
<version>1.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<artifactId>know_sub_business</artifactId>
<version>1.0.0</version>
<name>know_sub_business</name>
<description>know_sub_business</description>
<packaging>jar</packaging>
<properties>
<java.version>17</java.version>
@ -27,6 +27,31 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.supervision</groupId>
<artifactId>know_sub_common</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.supervision</groupId>
<artifactId>know_sub_model</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- <dependency>
<groupId>com.supervision</groupId>
<artifactId>know_sub_rag</artifactId>
<version>1.0.0</version>
</dependency>-->
</dependencies>
<build>

@ -1,9 +1,16 @@
package com.supervision.knowsub;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
@MapperScan(basePackages = {"com.supervision.**.mapper"})
@EnableConfigurationProperties
public class KnowSubBusinessApplication {
public static void main(String[] args) {

@ -0,0 +1,47 @@
package com.supervision.knowsub.controller;
import com.supervision.knowsub.exception.BusinessException;
import com.supervision.knowsub.service.FileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@Slf4j
@RestController
@Tag(name = "文件管理类")
@RequiredArgsConstructor
@RequestMapping("file")
public class FileController {
private final FileService fileService;
@Operation(summary = "文件上传")
@PostMapping("upload")
public String fileUpload(@RequestParam(name = "file") MultipartFile file) throws IOException {
byte[] bytes = file.getBytes();
if (bytes.length > 20 * 1024 * 1024){
throw new BusinessException("文件过大,文件大小请不要超过20MB");
}
return fileService.uploadFile(file.getOriginalFilename(), bytes);
}
@Operation(summary = "根据文件ID删除文件")
@GetMapping("deleteFileById")
public void deleteFileById(String fileId){
fileService.deleteFileById(fileId);
}
@Operation(summary = "下载文件")
@GetMapping("/downloadFile")
public void downloadFile(@RequestParam String fileId, HttpServletResponse response) {
fileService.downloadFile(fileId, response);
}
}

@ -0,0 +1,18 @@
package com.supervision.knowsub.controller;
import com.supervision.knowsub.domain.UserInfo;
import com.supervision.knowsub.util.UserUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("test")
public class TestController {
@GetMapping("testToken")
public void testToken(){
UserInfo user = UserUtil.getUser();
}
}

@ -0,0 +1,28 @@
package com.supervision.knowsub.controller.homepage;
import com.supervision.knowsub.entity.vo.homepage.MyKnowledgeStatisticsResVO;
import com.supervision.knowsub.service.HomepageService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@Tag(name = "首页")
@RestController
@RequestMapping("homepage")
@RequiredArgsConstructor
public class HomepageController {
private final HomepageService homepageService;
@Operation(summary = "查询我的知识")
@GetMapping("queryMyKnowledge")
public MyKnowledgeStatisticsResVO queryMyKnowledgeStatistics(){
return homepageService.queryMyKnowledgeStatistics();
}
}

@ -0,0 +1,82 @@
package com.supervision.knowsub.controller.knowledge;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.entity.vo.knowledge.KnowledgeFlowRecordResVO;
import com.supervision.knowsub.entity.vo.knowledge.ProcessFlowReqVO;
import com.supervision.knowsub.model.KnowledgeFlowRecord;
import com.supervision.knowsub.service.KnowledgeFlowService;
import com.supervision.knowsub.vo.knowledge.KnowledgeFlowResVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.mvc.condition.RequestConditionHolder;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Slf4j
@RestController
@Tag(name = "知识流程")
@RequiredArgsConstructor
@RequestMapping("knowledgeFlow")
public class KnowledgeFlowController {
private final KnowledgeFlowService knowledgeFlowService;
@Operation(summary = "分页查询知识审批流程")
@Parameters({
@Parameter(name = "processStatus", description = "审批状态 1未审批 2已审批", in = ParameterIn.QUERY),
@Parameter(name = "title", description = "标题,支持模糊", in = ParameterIn.QUERY),
@Parameter(name = "publishDeptId", description = "发文部门id", in = ParameterIn.QUERY),
@Parameter(name = "baseId", description = "应用字库ID", in = ParameterIn.QUERY),
@Parameter(name = "submittedDeptId", description = "报送部门ID", in = ParameterIn.QUERY),
@Parameter(name = "flowType", description = "审批类型 1知识报送 2:知识撤回 3 知识删除", in = ParameterIn.QUERY),
@Parameter(name = "publishDateBegin", description = "发文时间开始", in = ParameterIn.QUERY),
@Parameter(name = "publishDateEnd", description = "发文时间结束", in = ParameterIn.QUERY),
@Parameter(name = "submitDateBegin", description = "报送时间开始", in = ParameterIn.QUERY),
@Parameter(name = "submitDateEnd", description = "报送时间结束", in = ParameterIn.QUERY),
@Parameter(name = "pageNum", description = "分页", in = ParameterIn.QUERY),
@Parameter(name = "pageSize", description = "分页", in = ParameterIn.QUERY)
})
@GetMapping("queryKnowledgeFlowPage")
public IPage<KnowledgeFlowResVO> queryKnowledgeFlowPage(Integer processStatus,
@RequestParam(required = false) String title,
@RequestParam(required = false) String publishDeptId,
@RequestParam(required = false) String baseId,
@RequestParam(required = false) String submittedDeptId,
@RequestParam(required = false) Integer flowType,
@RequestParam(required = false) LocalDate publishDateBegin,
@RequestParam(required = false) LocalDate publishDateEnd,
@RequestParam(required = false) LocalDate submitDateBegin,
@RequestParam(required = false) LocalDate submitDateEnd,
Integer pageNum, Integer pageSize) {
return knowledgeFlowService.queryKnowledgeFlowPage(processStatus, title, publishDeptId, baseId, submittedDeptId, flowType,
publishDateBegin, publishDateEnd, submitDateBegin, submitDateEnd, pageNum, pageSize);
}
@Operation(summary = "审批知识流程")
@PostMapping("processKnowledgeFlow")
public void processKnowledgeFlow(@RequestBody ProcessFlowReqVO reqVO) {
knowledgeFlowService.processKnowledgeFlow(reqVO);
}
@Operation(summary = "查询知识库流转记录")
@Parameters({
@Parameter(name = "knowledgeId", description = "审批状态 1未审批 2已审批", in = ParameterIn.QUERY),
@Parameter(name = "flowInstanceId", description = "流程实例ID,可不填", in = ParameterIn.QUERY)
})
@GetMapping("queryKnowledgeFlowRecord")
public List<KnowledgeFlowRecordResVO> queryKnowledgeFlowRecord(String knowledgeId, @RequestParam(required = false) String flowInstanceId) {
return knowledgeFlowService.queryKnowledgeFlowRecord(knowledgeId, flowInstanceId);
}
}

@ -0,0 +1,92 @@
package com.supervision.knowsub.controller.knowledge;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.entity.vo.knowledge.KnowledgeDetailResVO;
import com.supervision.knowsub.entity.vo.knowledge.ModifyKnowledgeReqVO;
import com.supervision.knowsub.entity.vo.knowledge.SaveKnowledgeReqVO;
import com.supervision.knowsub.service.KnowledgeManageService;
import com.supervision.knowsub.model.Knowledge;
import com.supervision.knowsub.vo.knowledge.KnowledgePageResVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Slf4j
@RestController
@Tag(name = "知识库查询")
@RequiredArgsConstructor
@RequestMapping("knowledge")
public class KnowledgeManageController {
private final KnowledgeManageService knowledgeManageService;
@Operation(summary = "查询知识库分页-除全部可以看所有外,其他tab都是看到自己报送的知识的状态(或参与过的)")
@Parameters({
@Parameter(name = "status", description = "流转状态 为空查全部,1草稿 2通过 3驳回 4已撤回 5已失效 6已删除 9待审批(这里包含了10,11,12,统一用9)", in = ParameterIn.QUERY),
@Parameter(name = "title", description = "标题,支持模糊", in = ParameterIn.QUERY),
@Parameter(name = "publishDeptId", description = "发文部门id", in = ParameterIn.QUERY),
@Parameter(name = "baseId", description = "应用字库ID", in = ParameterIn.QUERY),
@Parameter(name = "submittedDeptId", description = "报送部门ID", in = ParameterIn.QUERY),
@Parameter(name = "publishDateBegin", description = "发文时间开始", in = ParameterIn.QUERY),
@Parameter(name = "publishDateEnd", description = "发文时间结束", in = ParameterIn.QUERY),
@Parameter(name = "submitDateBegin", description = "报送时间开始", in = ParameterIn.QUERY),
@Parameter(name = "submitDateEnd", description = "报送时间结束", in = ParameterIn.QUERY),
@Parameter(name = "pageNum", description = "分页", in = ParameterIn.QUERY),
@Parameter(name = "pageSize", description = "分页", in = ParameterIn.QUERY)
})
@GetMapping("queryKnowledgePage")
public IPage<KnowledgePageResVO> queryKnowledgePage(@RequestParam(required = false) Integer status,
@RequestParam(required = false) String title,
@RequestParam(required = false) String publishDeptId,
@RequestParam(required = false) String baseId,
@RequestParam(required = false) String submittedDeptId,
@RequestParam(required = false) LocalDate publishDateBegin,
@RequestParam(required = false)LocalDate publishDateEnd,
@RequestParam(required = false) LocalDate submitDateBegin,
@RequestParam(required = false) LocalDate submitDateEnd,
Integer pageNum, Integer pageSize) {
return knowledgeManageService.queryKnowledgePage(status, title, publishDeptId, baseId, submittedDeptId, publishDateBegin, publishDateEnd,submitDateBegin,submitDateEnd, pageNum, pageSize);
}
@Operation(summary = "新增知识库")
@PostMapping("saveKnowledge")
public void saveKnowledge(@RequestBody SaveKnowledgeReqVO reqVO) {
knowledgeManageService.saveKnowledge(reqVO);
}
@Operation(summary = "修改知识库(status:1草稿/3驳回/4已撤回/5已失效,才能修改)")
@PostMapping("updateKnowledge")
public void updateKnowledge(@RequestBody ModifyKnowledgeReqVO reqVO) {
Assert.notBlank(reqVO.getKnowledgeId(), "知识ID不能为空");
knowledgeManageService.updateKnowledge(reqVO);
}
@Operation(summary = "撤回知识库(status:2通过/5已失效)")
@GetMapping("recallKnowledge")
public void recallKnowledge(String knowledgeId,String remark) {
knowledgeManageService.recallKnowledge(knowledgeId,remark);
}
@Operation(summary = "查看知识的详细信息")
@GetMapping("queryKnowledgeDetail")
public KnowledgeDetailResVO queryKnowledgeDetail(String knowledgeId) {
return knowledgeManageService.queryKnowledgeDetail(knowledgeId);
}
@Operation(summary = "删除知识库-逻辑删除(status:1草稿/2通过/3驳回/4已撤回/5已失效)")
@GetMapping("deleteKnowledge")
public void deleteKnowledge(String knowledgeId,String remark) {
knowledgeManageService.deleteKnowledge(knowledgeId,remark);
}
}

@ -0,0 +1,59 @@
package com.supervision.knowsub.controller.system;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.service.ApplicationSubLibraryService;
import com.supervision.knowsub.vo.sublibrary.SubLibraryReqVo;
import com.supervision.knowsub.vo.sublibrary.SubLibraryResVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
*
*/
@Tag(name = "应用子库管理")
@RestController
@RequestMapping("/applicationSubLibrary")
@RequiredArgsConstructor
public class ApplicationSubLibraryController {
private final ApplicationSubLibraryService applicationSubLibraryService;
@Operation(summary = "增加应用子库")
@PostMapping("/save")
public String saveSubLibrary(@RequestBody SubLibraryReqVo subLibraryReqVo) {
return applicationSubLibraryService.saveSubLibrary(subLibraryReqVo);
}
@Operation(summary = "修改应用子库")
@PostMapping("/update")
public void updateSubLibrary(@RequestBody SubLibraryReqVo subLibraryReqVo) {
applicationSubLibraryService.updateSubLibrary(subLibraryReqVo);
}
@Operation(summary = "删除应用子库")
@DeleteMapping("/delete")
public Boolean deleteSubLibrary(@Parameter(name = "id") @RequestParam(name="id") String id) {
return applicationSubLibraryService.deleteSubLibrary(id);
}
@Operation(summary = "分页查询应用子库")
@GetMapping("/list")
public IPage<SubLibraryResVo> listSubLibrary(@Parameter(name = "baseName",description = "应用子库名") @RequestParam(required = false) String baseName,
@Parameter(name = "baseCode",description = "应用库code") @RequestParam(required = false) String baseCode,
@Parameter(name = "pageNum",description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
@Parameter(name = "pageSize",description = "每页大小") @RequestParam(defaultValue = "10") Integer pageSize) {
SubLibraryReqVo subLibraryReqVo = new SubLibraryReqVo();
subLibraryReqVo.setBaseCode(baseCode);
subLibraryReqVo.setBaseName(baseName);
return applicationSubLibraryService.listSubLibrary(subLibraryReqVo,pageNum,pageSize);
}
}

@ -0,0 +1,52 @@
package com.supervision.knowsub.controller.system;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.service.DeptManageService;
import com.supervision.knowsub.vo.dept.DeptInfoReqVo;
import com.supervision.knowsub.vo.dept.DeptInfoResVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@Tag(name = "部门管理")
@RestController
@RequestMapping("/deptManage")
@RequiredArgsConstructor
public class DeptManageController {
private final DeptManageService deptManageService;
@Operation(summary = "增加部门信息")
@PostMapping("/save")
public String saveDept(@RequestBody DeptInfoReqVo deptInfoReqVo) {
return deptManageService.saveDept(deptInfoReqVo);
}
@Operation(summary = "修改部门信息")
@PostMapping("/update")
public void updateDept(@RequestBody DeptInfoReqVo deptInfoReqVo) {
deptManageService.updateDept(deptInfoReqVo);
}
@Operation(summary = "删除部门信息")
@DeleteMapping("/delete")
public Boolean deleteDept(@Parameter(name = "id") @RequestParam(name="id") String id) {
return deptManageService.deleteDept(id);
}
@Operation(summary = "分页查询部门信息列表")
@GetMapping("/list")
public IPage<DeptInfoResVo> listDept(@Parameter(name = "deptName",description = "机构名称") @RequestParam(required = false) String deptName,
@Parameter(name = "deptCode",description = "机构编码") @RequestParam(required = false) String deptCode,
@Parameter(name = "pageNum",description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
@Parameter(name = "pageSize",description = "每页大小") @RequestParam(defaultValue = "10") Integer pageSize) {
return deptManageService.pageListDept(deptName,deptCode,pageNum,pageSize);
}
}

@ -0,0 +1,71 @@
package com.supervision.knowsub.controller.system;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.model.SystemDic;
import com.supervision.knowsub.model.SystemDicData;
import com.supervision.knowsub.service.DicManageService;
import com.supervision.knowsub.vo.dic.DicDataReqVo;
import com.supervision.knowsub.vo.dic.DicReqVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "字典管理")
@RestController
@RequestMapping("/dicManage")
@RequiredArgsConstructor
public class DicManageController {
private final DicManageService dicManageService;
@Operation(summary = "增加字典信息")
@PostMapping("/saveDic")
public String saveDic(@RequestBody DicReqVo dicReqVo) {
return dicManageService.saveDic(dicReqVo);
}
@Operation(summary = "修改字典信息")
@PostMapping("/updateDic")
public void updateDic(@RequestBody DicReqVo dicReqVo) {
dicManageService.updateDic(dicReqVo);
}
@Operation(summary = "删除字典信息")
@DeleteMapping("/delete")
public Boolean deleteDic(@Parameter(name = "id") @RequestParam(name="id") String id) {
return dicManageService.deleteDic(id);
}
@Operation(summary = "分页查询字典信息列表")
@GetMapping("/list")
public IPage<SystemDic> listDic(@Parameter(name = "dicName",description = "字典名称") @RequestParam(required = false) String dicName,
@Parameter(name = "dicCode",description = "字典编码") @RequestParam(required = false) String dicCode,
@Parameter(name = "pageNum",description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
@Parameter(name = "pageSize",description = "每页大小") @RequestParam(defaultValue = "10") Integer pageSize) {
return dicManageService.listDic(dicName,dicCode,pageNum,pageSize);
}
@Operation(summary = "保存字典值配置信息")
@PostMapping("/saveDicData")
public String saveDicData(@RequestParam(name = "dicId") String dicId, @RequestBody List<DicDataReqVo> dicDataReqVoList) {
return dicManageService.saveDicData(dicId,dicDataReqVoList);
}
@Operation(summary = "查询字典配置信息列表")
@GetMapping("/queryDicDate")
public List<SystemDicData> queryDicDate(@RequestParam(name = "dicId") String dicId) {
return dicManageService.queryDicDate(dicId);
}
}

@ -0,0 +1,71 @@
package com.supervision.knowsub.controller.system;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.service.FlowManageService;
import com.supervision.knowsub.vo.flow.BaseResVo;
import com.supervision.knowsub.vo.flow.FlowDetailResVo;
import com.supervision.knowsub.vo.flow.FlowInfoReqVo;
import com.supervision.knowsub.vo.flow.FlowInfoResVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "流程管理")
@RestController
@RequestMapping("/flow")
@RequiredArgsConstructor
public class FlowManageController {
private final FlowManageService flowManageService;
@Operation(summary = "新建流程")
@PostMapping("/save")
public String saveFlow(@RequestBody FlowInfoReqVo flowInfoReqVo) {
flowInfoReqVo.setFlowTypeListForFlowType();
return flowManageService.saveFlow(flowInfoReqVo);
}
@Operation(summary = "修改流程")
@PostMapping("/update")
public void updateFlow(@RequestBody FlowInfoReqVo flowInfoReqVo) {
flowInfoReqVo.setFlowTypeListForFlowType();
flowManageService.updateFlow(flowInfoReqVo);
}
@Operation(summary = "删除流程")
@DeleteMapping("/delete")
public Boolean deleteFlow(@Parameter(name = "id") @RequestParam(name="id") String id) {
return flowManageService.deleteFlow(id);
}
@Operation(summary = "分页查询流程列表")
@GetMapping("/list")
public IPage<FlowInfoResVo> listFlow(@Parameter(name = "flowName",description = "流程名称") @RequestParam(required = false) String flowName,
@Parameter(name = "pageNum",description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
@Parameter(name = "pageSize",description = "每页大小") @RequestParam(defaultValue = "10") Integer pageSize) {
return flowManageService.pageListFlow(flowName,pageNum,pageSize);
}
@Operation(summary = "查询可选择的子库信息列表")
@GetMapping("/optionalBaseList")
public List<BaseResVo> optionalBaseList(@Parameter(name = "flowType",description = "数据类型id多个id用英文逗号拼接")
@RequestParam(name = "flowType",required = false) List<Integer> flowType) {
return flowManageService.optionalBaseList(flowType);
}
@Operation(summary = "查询流程详情")
@GetMapping("/getFlowDetail")
public FlowDetailResVo getFlowDetail(@Parameter(name = "flowId",description = "流程id") @RequestParam("flowId") String flowId) {
FlowDetailResVo flowDetail = flowManageService.getFlowDetail(flowId);
flowDetail.setFlowTypeFromFlowTypeIdList();
return flowDetail;
}
}

@ -0,0 +1,45 @@
package com.supervision.knowsub.controller.system;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.model.SystemRole;
import com.supervision.knowsub.service.RoleManageService;
import com.supervision.knowsub.vo.role.RoleReqVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@Tag(name = "用户角色管理")
@RestController
@RequestMapping("/roleManage")
@RequiredArgsConstructor
public class RoleManageController {
private final RoleManageService roleManageService;
@Operation(summary = "新增角色")
@PostMapping("/save")
public String saveRole(@RequestBody RoleReqVo roleReqVo) {
return roleManageService.saveRole(roleReqVo);
}
@Operation(summary = "修改角色")
@PostMapping("/update")
public void updateRole(@RequestBody RoleReqVo roleReqVo) {
roleManageService.updateRole(roleReqVo);
}
@Operation(summary = "删除角色")
@DeleteMapping("/delete")
public Boolean deleteRole(@Parameter(name = "id") @RequestParam(name="id") String id) {
return roleManageService.deleteRole(id);
}
@Operation(summary = "查看角色列表")
@GetMapping("/list")
public IPage<SystemRole> list(@Parameter(name = "roleName",description = "角色名称") @RequestParam(required = false) String roleName,
@Parameter(name = "pageNum",description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
@Parameter(name = "pageSize",description = "每页大小") @RequestParam(defaultValue = "10") Integer pageSize) {
return roleManageService.list(roleName, pageNum, pageSize);
}
}

@ -0,0 +1,84 @@
package com.supervision.knowsub.controller.system;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.exception.BusinessException;
import com.supervision.knowsub.service.UserManageService;
import com.supervision.knowsub.vo.user.*;
import com.supervision.knowsub.dto.user.UserInfoDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@Tag(name = "用户管理")
@RestController
@RequestMapping("user")
@RequiredArgsConstructor
public class UserController {
private final UserManageService userManageService;
@Operation(summary = "登录")
@PostMapping("login")
public LoginResVO login(@RequestBody LoginReqVO reqVO) {
if (!StrUtil.isAllNotBlank(reqVO.getUserAccount(), reqVO.getPassword())) {
throw new BusinessException("用户名不能为空");
}
return userManageService.login(reqVO);
}
@Operation(summary = "查看账号信息")
@GetMapping("getUserAccountInfo")
public UserInfoDTO getUserAccountInfo() {
return userManageService.getUserAccountInfo();
}
@Operation(summary = "新增用户信息")
@PostMapping("/saveUserInfo")
public String saveUserInfo(@RequestBody UserInfoReqVo userInfoReqVo) {
return userManageService.saveUserInfo(userInfoReqVo);
}
@Operation(summary = "修改用户信息")
@PostMapping("/update")
public void updateUser(@RequestBody UserInfoReqVo userInfoReqVo) {
userManageService.updateUserInfo(userInfoReqVo);
}
@Operation(summary = "修改用户状态")
@PostMapping("/updateUserStatus")
public void updateUserStatus(@RequestBody UserStatusReqVo userStatusReqVo) {
userManageService.updateUserStatus(userStatusReqVo);
}
@Operation(summary = "删除用户信息")
@DeleteMapping("/delete")
public Boolean deleteUser(@Parameter(name = "id") @RequestParam(name="id") String id) {
return userManageService.deleteUser(id);
}
@Operation(summary = "查看用户信息列表")
@GetMapping("/list")
public IPage<UserInfoDTO> list(@Parameter(name = "userName",description = "用户名") @RequestParam(required = false) String userName,
@Parameter(name = "deptId",description = "部门id") @RequestParam(required = false) String deptId,
@Parameter(name = "roleId",description = "角色id") @RequestParam(required = false) String roleId,
@Parameter(name = "roleName",description = "角色名") @RequestParam(required = false) String roleName,
@Parameter(name = "pageNum",description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
@Parameter(name = "pageSize",description = "每页大小") @RequestParam(defaultValue = "10") Integer pageSize) {
return userManageService.list(userName, deptId, roleId, roleName, pageNum, pageSize);
}
@Operation(summary = "重置用户密码")
@PutMapping("/resetPW")
public Boolean resetPW(@RequestBody UserPwReqVo userPwReqVo) {
return userManageService.resetPW(userPwReqVo);
}
}

@ -0,0 +1,46 @@
package com.supervision.knowsub.entity.vo.homepage;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class MyKnowledgeStatisticsResVO {
@Schema(description = "用户名")
private String userName;
@Schema(description = "最近登录时间")
private LocalDateTime lastLoginTime;
/**
*
*/
@Schema(description = "全量知识")
private Long knowledgeCount;
/**
*
*/
@Schema(description = "待审批")
private Long waitProcessCount;
/**
*
*/
@Schema(description = "审批通过")
private Long passProcessCount;
/**
*
*/
@Schema(description = "驳回")
private Long rejectProcessCount;
/**
*
*/
@Schema(description = "已失效")
private Long invalidProcessCount;
}

@ -0,0 +1,39 @@
package com.supervision.knowsub.entity.vo.knowledge;
import com.supervision.knowsub.model.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class KnowledgeDetailResVO {
private Knowledge knowledge;
private KnowledgeInfo knowledgeInfo;
private KnowledgeContext knowledgeContext;
private List<KnowledgeLink> knowledgeLinkList;
private List<FileInfo> fileInfoList;
private String publishDept;
private String submittedDeptName;
private String baseName;
public KnowledgeDetailResVO(Knowledge knowledge, KnowledgeInfo knowledgeInfo, KnowledgeContext knowledgeContext, List<KnowledgeLink> knowledgeLinkList, List<FileInfo> fileInfoList) {
this.knowledge = knowledge;
this.knowledgeInfo = knowledgeInfo;
this.knowledgeContext = knowledgeContext;
this.knowledgeLinkList = knowledgeLinkList;
this.fileInfoList = fileInfoList;
}
}

@ -0,0 +1,29 @@
package com.supervision.knowsub.entity.vo.knowledge;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class KnowledgeFlowRecordResVO {
private String id;
private String knowledgeId;
private String processName;
private String remark;
private LocalDateTime processTime;
private String processUserId;
private String processDeptId;
private String processUserName;
private String processDeptName;
private Integer processOrder;
}

@ -0,0 +1,14 @@
package com.supervision.knowsub.entity.vo.knowledge;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class KnowledgeLinkVO {
@Schema(description = "链接名称")
private String linkName;
@Schema(description = "链接地址")
private String linkUrl;
}

@ -0,0 +1,14 @@
package com.supervision.knowsub.entity.vo.knowledge;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@Schema(description = "修改知识库请求参数 ")
public class ModifyKnowledgeReqVO extends SaveKnowledgeReqVO{
@Schema(description = "知识ID")
private String knowledgeId;
}

@ -0,0 +1,17 @@
package com.supervision.knowsub.entity.vo.knowledge;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class ProcessFlowReqVO {
@Schema(description = "操作类型 1通过 2驳回")
private Integer operate;
private String todoId;
private String knowledgeId;
private String remark;
}

@ -0,0 +1,49 @@
package com.supervision.knowsub.entity.vo.knowledge;
import cn.hutool.core.date.DateTime;
import com.supervision.knowsub.model.KnowledgeInfo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import lombok.Data;
import java.util.List;
@Data
public class SaveKnowledgeReqVO {
@Schema(description = "操作类型 1草稿 2提交")
@Max(value = 2, message = "操作类型 1草稿 2提交")
@Min(value = 1, message = "操作类型 1草稿 2提交")
private Integer operate;
@Schema(description = "应用子库ID")
private String baseId;
@Schema(description = "标题")
private String title;
@Schema(description = "HTML富文本的内容")
private String content;
@Schema(description = "摘要")
private String excerpt;
@Schema(description = "相关附件列表 file_info表ID")
private List<String> fileIdList;
@Schema(description = "链接列表")
private List<KnowledgeLinkVO> linkList;
@Schema(description = "发布部门Id")
private String publishDeptId;
@Schema(description = "提交审批的备注")
private String remark;
@Schema(description = "知识的基础信息")
private KnowledgeInfo knowledgeInfo;
}

@ -0,0 +1,28 @@
package com.supervision.knowsub.enums;
/**
* 1 2 3
*/
public enum FlowTypeEnum {
SUBMIT(1, "知识报送审批"),
RECALL(2, "知识撤回审批"),
DELETE(3, "知识删除审批");
private final Integer flowType;
private final String desc;
FlowTypeEnum(Integer flowType, String desc) {
this.flowType = flowType;
this.desc = desc;
}
public Integer getFlowType() {
return flowType;
}
public String getDesc() {
return desc;
}
}

@ -0,0 +1,29 @@
package com.supervision.knowsub.enums;
/**
* 0: 1 2 3
*/
public enum RoleTypeEnum {
NORMAL(0, "普通角色"),
ADMIN(1, "管理员"),
KNOWLEDGE_SUBMIT(2, "知识报送"),
KNOWLEDGE_APPROVAL(3, "知识审批");
private Integer roleType;
private String desc;
RoleTypeEnum(Integer roleType, String desc) {
this.roleType = roleType;
this.desc = desc;
}
public Integer getRoleType() {
return roleType;
}
public String getDesc() {
return desc;
}
}

@ -0,0 +1,37 @@
package com.supervision.knowsub.enums;
/**
* 1稿 2 4 5 6 10() 11() 12() 15() 16() 17()
*/
public enum StatusEnum {
DRAFT(1, "草稿"),
PASS(2, "通过"),
RECALL(4, "已撤回"),
INVALID(5, "已失效"),
DELETE(6, "已删除"),
WAIT_APPROVAL(10, "待审批(新增)"),
WAIT_APPROVAL_DELETE(11, "待审批(删除)"),
WAIT_APPROVAL_RECALL(12, "待审批(撤回)"),
RECALL_APPROVAL_SUBMIT(15, "驳回(新增)"),
RECALL_APPROVAL_DELETE(16, "驳回(删除)"),
RECALL_APPROVAL_RECALL(17, "驳回(撤回)");
private final Integer status;
private final String desc;
StatusEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}

@ -0,0 +1,21 @@
package com.supervision.knowsub.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.model.SystemBase;
import com.supervision.knowsub.vo.sublibrary.SubLibraryReqVo;
import com.supervision.knowsub.vo.sublibrary.SubLibraryResVo;
import java.util.List;
public interface ApplicationSubLibraryService {
String saveSubLibrary(SubLibraryReqVo subLibraryReqVo);
void updateSubLibrary(SubLibraryReqVo subLibraryReqVo);
Boolean deleteSubLibrary(String id);
IPage<SubLibraryResVo> listSubLibrary(SubLibraryReqVo subLibraryReqVo,Integer pageNum,Integer pageSize);
List<SystemBase> listAllSubLibrary();
}

@ -0,0 +1,16 @@
package com.supervision.knowsub.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.vo.dept.DeptInfoReqVo;
import com.supervision.knowsub.vo.dept.DeptInfoResVo;
public interface DeptManageService {
String saveDept(DeptInfoReqVo deptInfoReqVo);
void updateDept(DeptInfoReqVo deptInfoReqVo);
Boolean deleteDept(String id);
IPage<DeptInfoResVo> pageListDept(String deptName, String deptCode, Integer pageNum, Integer pageSize);
}

@ -0,0 +1,24 @@
package com.supervision.knowsub.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.model.SystemDic;
import com.supervision.knowsub.model.SystemDicData;
import com.supervision.knowsub.vo.dept.DeptInfoResVo;
import com.supervision.knowsub.vo.dic.DicDataReqVo;
import com.supervision.knowsub.vo.dic.DicReqVo;
import java.util.List;
public interface DicManageService {
String saveDic(DicReqVo dicReqVo);
void updateDic(DicReqVo dicReqVo);
Boolean deleteDic(String id);
IPage<SystemDic> listDic(String dicName, String dicCode, Integer pageNum, Integer pageSize);
String saveDicData(String dicId, List<DicDataReqVo> dicDataReqVoList);
List<SystemDicData> queryDicDate(String dicId);
}

@ -0,0 +1,17 @@
package com.supervision.knowsub.service;
import com.supervision.knowsub.model.FileInfo;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
public interface FileService {
String uploadFile(String fileName, byte[] fileBytes);
void deleteFileById(String fileId);
List<FileInfo> listByFileId(List<String> fileIdList);
void downloadFile(String fileId, HttpServletResponse response);
}

@ -0,0 +1,57 @@
package com.supervision.knowsub.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.vo.flow.BaseResVo;
import com.supervision.knowsub.vo.flow.FlowDetailResVo;
import com.supervision.knowsub.vo.flow.FlowInfoReqVo;
import com.supervision.knowsub.vo.flow.FlowInfoResVo;
import com.supervision.knowsub.vo.sublibrary.SubLibraryResVo;
import java.util.List;
public interface FlowManageService {
String saveFlow(FlowInfoReqVo flowInfoReqVo);
/**
* typeIds使ids
* @param typeIds
* @return
*/
List<String> listUsedBaseIds(List<Integer> typeIds);
/**
*
* @param flowInfoReqVo
*/
void updateFlow(FlowInfoReqVo flowInfoReqVo);
/**
*
* @param id
* @return
*/
Boolean deleteFlow(String id);
/**
*
* @param flowName
* @param pageNum
* @param pageSize
* @return
*/
IPage<FlowInfoResVo> pageListFlow(String flowName, Integer pageNum, Integer pageSize);
/**
*
* @param flowType
* @return
*/
List<BaseResVo> optionalBaseList(List<Integer> flowType);
/**
*
* @param flowId id
* @return
*/
FlowDetailResVo getFlowDetail(String flowId);
}

@ -0,0 +1,36 @@
package com.supervision.knowsub.service;
import com.supervision.knowsub.dto.flow.SystemFlowRuleDTO;
import com.supervision.knowsub.vo.flow.NodeInfo;
import java.util.List;
public interface FlowRuleManageService {
/**
*
* @param flowId id
* @param nodeInfoList
* @return
*/
boolean saveFlowRule(String flowId, List<NodeInfo> nodeInfoList);
void saveFlowRule(List<SystemFlowRuleDTO> systemFlowRuleDTOList);
void updateFlowRule(List<SystemFlowRuleDTO> systemFlowRuleDTOList);
/**
*
* @param flowId id
* @param nodeInfoList
* @return
*/
boolean updateFlowRule(String flowId, List<NodeInfo> nodeInfoList);
List<NodeInfo> listFlowRule(String flowId);
void deleteFlowRuleByRuleIds(List<String> ruleIdList);
}

@ -0,0 +1,8 @@
package com.supervision.knowsub.service;
import com.supervision.knowsub.entity.vo.homepage.MyKnowledgeStatisticsResVO;
public interface HomepageService {
MyKnowledgeStatisticsResVO queryMyKnowledgeStatistics();
}

@ -0,0 +1,29 @@
package com.supervision.knowsub.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.entity.vo.knowledge.KnowledgeFlowRecordResVO;
import com.supervision.knowsub.entity.vo.knowledge.ProcessFlowReqVO;
import com.supervision.knowsub.enums.FlowTypeEnum;
import com.supervision.knowsub.model.Knowledge;
import com.supervision.knowsub.model.KnowledgeFlowRecord;
import com.supervision.knowsub.vo.knowledge.KnowledgeFlowResVO;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
public interface KnowledgeFlowService {
IPage<KnowledgeFlowResVO> queryKnowledgeFlowPage(Integer processStatus,String title, String publishDeptId, String baseId, String submitDeptId, Integer flowType,
LocalDate publishDateBegin, LocalDate publishDateEnd,LocalDate submitDateBegin, LocalDate submitDateEnd,
Integer pageNum, Integer pageSize);
void submitFlowProcess(Knowledge knowledge, FlowTypeEnum flowTypeEnum, String userId, String deptId, String remark);
void processKnowledgeFlow(ProcessFlowReqVO reqVO);
List<KnowledgeFlowRecordResVO> queryKnowledgeFlowRecord(String knowledgeId, String flowInstanceId);
}

@ -0,0 +1,37 @@
package com.supervision.knowsub.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.entity.vo.knowledge.KnowledgeDetailResVO;
import com.supervision.knowsub.entity.vo.knowledge.ModifyKnowledgeReqVO;
import com.supervision.knowsub.entity.vo.knowledge.SaveKnowledgeReqVO;
import com.supervision.knowsub.model.Knowledge;
import com.supervision.knowsub.vo.knowledge.KnowledgePageResVO;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.time.LocalDate;
import java.time.LocalDateTime;
public interface KnowledgeManageService {
IPage<KnowledgePageResVO> queryKnowledgePage(Integer status,
String title,
String publishDeptId,
String baseId,
String submitDeptId,
LocalDate publishDateBegin,
LocalDate publishDateEnd,
LocalDate submitDateBegin,
LocalDate submitDateEnd,
Integer pageNum, Integer pageSize);
void saveKnowledge(SaveKnowledgeReqVO reqVO);
void updateKnowledge(ModifyKnowledgeReqVO reqVO);
void recallKnowledge(String knowledgeId, String remark);
KnowledgeDetailResVO queryKnowledgeDetail(String knowledgeId);
void deleteKnowledge(String knowledgeId, String remark);
}

@ -0,0 +1,16 @@
package com.supervision.knowsub.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.model.SystemRole;
import com.supervision.knowsub.vo.role.RoleReqVo;
public interface RoleManageService {
String saveRole(RoleReqVo roleReqVo);
void updateRole(RoleReqVo roleReqVo);
Boolean deleteRole(String id);
IPage<SystemRole> list(String roleName, Integer pageNum, Integer pageSize);
}

@ -0,0 +1,32 @@
package com.supervision.knowsub.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.model.SystemUser;
import com.supervision.knowsub.vo.user.*;
import com.supervision.knowsub.dto.user.UserInfoDTO;
import java.util.List;
public interface UserManageService {
LoginResVO login(LoginReqVO reqVO);
UserInfoDTO getUserAccountInfo();
List<SystemUser> listUserByDeptId(String deptId,Integer status);
Long countUserByDeptId(String deptId,Integer status);
String saveUserInfo(UserInfoReqVo userInfoReqVo);
void updateUserInfo(UserInfoReqVo userInfoReqVo);
Boolean deleteUser(String id);
IPage<UserInfoDTO> list(String userName, String deptId, String roleId, String roleName,Integer pageNum, Integer pageSize);
Boolean resetPW(UserPwReqVo userPwReqVo);
void updateUserStatus(UserStatusReqVo userStatusReqVo);
}

@ -0,0 +1,19 @@
package com.supervision.knowsub.service;
import com.supervision.knowsub.dto.role.UserRoleDTO;
import com.supervision.knowsub.model.SystemUserRoleRelation;
import java.util.List;
public interface UserRoleRelationManageService {
List<SystemUserRoleRelation> saveUserRoleRelation(String userId, List<String> roleIdList);
List<SystemUserRoleRelation> updateUserRoleRelation(String userId, List<String> roleIdList);
List<UserRoleDTO> listUserRole(String userId, String roleId,String roleName);
List<UserRoleDTO> listUserRoleByUserIds(List<String> userIds);
void deleteUserRoleRelation(String userId);
}

@ -0,0 +1,115 @@
package com.supervision.knowsub.service.impl;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.model.SystemBase;
import com.supervision.knowsub.model.SystemBaseDeptRelation;
import com.supervision.knowsub.service.ApplicationSubLibraryService;
import com.supervision.knowsub.service.SystemBaseDeptRelationService;
import com.supervision.knowsub.service.SystemBaseService;
import com.supervision.knowsub.vo.sublibrary.SubLibraryReqVo;
import com.supervision.knowsub.vo.sublibrary.SubLibraryResVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Objects;
@Service
@RequiredArgsConstructor
public class ApplicationSubLibraryServiceImpl implements ApplicationSubLibraryService {
private final SystemBaseService systemBaseService;
private final SystemBaseDeptRelationService systemBaseDeptRelationService;
@Override
@Transactional(rollbackFor = Exception.class)
public String saveSubLibrary(SubLibraryReqVo subLibraryReqVo) {
Assert.notEmpty(subLibraryReqVo.getBaseCode(), "子库编码不能为空");
Assert.notEmpty(subLibraryReqVo.getBaseName(), "子库名称不能为空");
Assert.notEmpty(subLibraryReqVo.getDeptIds(), "关联部门不能为空");
Long count = systemBaseService.lambdaQuery().eq(SystemBase::getBaseCode, subLibraryReqVo.getBaseCode())
.or(query -> query.eq(SystemBase::getBaseName, subLibraryReqVo.getBaseName())).count();
Assert.isTrue(count == 0, "子库编码或子库名称已存在");
// 保存应用子库信息
SystemBase systemBase = new SystemBase();
systemBase.setBaseCode(subLibraryReqVo.getBaseCode());
systemBase.setBaseName(subLibraryReqVo.getBaseName());
systemBaseService.save(systemBase);
// 保存应用子库管理部门信息
systemBaseDeptRelationService.saveBatch(subLibraryReqVo.getDeptIds().stream().map(deptId -> {
SystemBaseDeptRelation systemBaseDeptRelation = new SystemBaseDeptRelation();
systemBaseDeptRelation.setBaseId(systemBase.getId());
systemBaseDeptRelation.setDeptId(deptId);
return systemBaseDeptRelation;
}).toList());
return systemBase.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateSubLibrary(SubLibraryReqVo subLibraryReqVo) {
Assert.notEmpty(subLibraryReqVo.getBaseCode(), "子库编码不能为空");
Assert.notEmpty(subLibraryReqVo.getBaseName(), "子库名称不能为空");
Assert.notEmpty(subLibraryReqVo.getDeptIds(), "关联部门不能为空");
SystemBase dbSystemBase = systemBaseService.getById(subLibraryReqVo.getId());
Assert.isTrue(Objects.nonNull(dbSystemBase), "子库不存在");
if (!StrUtil.equals(dbSystemBase.getBaseCode(), subLibraryReqVo.getBaseCode())){
// 子库编码修改
Long count = systemBaseService.lambdaQuery().eq(SystemBase::getBaseCode, subLibraryReqVo.getBaseCode()).count();
Assert.isTrue(count == 0, "子库编码已存在");
}
// 更新应用子库信息
SystemBase systemBase = new SystemBase();
systemBase.setId(subLibraryReqVo.getId());
systemBase.setBaseName(subLibraryReqVo.getBaseName());
systemBase.setBaseCode(subLibraryReqVo.getBaseCode());
systemBaseService.updateById(systemBase);
// 更新应用子库管理部门信息(先删除再新增)
systemBaseDeptRelationService.lambdaUpdate().eq(SystemBaseDeptRelation::getBaseId, systemBase.getId()).remove();
systemBaseDeptRelationService.saveBatch(subLibraryReqVo.getDeptIds().stream().map(deptId -> {
SystemBaseDeptRelation systemBaseDeptRelation = new SystemBaseDeptRelation();
systemBaseDeptRelation.setBaseId(systemBase.getId());
systemBaseDeptRelation.setDeptId(deptId);
return systemBaseDeptRelation;
}).toList());
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteSubLibrary(String id) {
Assert.notEmpty(id, "子库id不能为空");
systemBaseService.removeById(id);
systemBaseDeptRelationService.lambdaUpdate().eq(SystemBaseDeptRelation::getBaseId, id).remove();
return true;
}
@Override
public IPage<SubLibraryResVo> listSubLibrary(SubLibraryReqVo subLibraryReqVo,Integer pageNum,Integer pageSize) {
return systemBaseService.listSubLibrary(subLibraryReqVo, pageNum, pageSize);
}
@Override
public List<SystemBase> listAllSubLibrary() {
return systemBaseService.list();
}
}

@ -0,0 +1,81 @@
package com.supervision.knowsub.service.impl;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.model.SystemDept;
import com.supervision.knowsub.service.DeptManageService;
import com.supervision.knowsub.service.SystemDeptService;
import com.supervision.knowsub.service.UserManageService;
import com.supervision.knowsub.vo.dept.DeptInfoReqVo;
import com.supervision.knowsub.vo.dept.DeptInfoResVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
public class DeptManageServiceImpl implements DeptManageService {
private final SystemDeptService systemDeptService;
private final UserManageService userManageService;
@Override
@Transactional(rollbackFor = Exception.class)
public String saveDept(DeptInfoReqVo deptInfoReqVo) {
Assert.notEmpty(deptInfoReqVo.getDeptName(), "部门名称不能为空");
Assert.notEmpty(deptInfoReqVo.getDeptCode(), "部门编码不能为空");
Long count = systemDeptService.lambdaQuery().eq(SystemDept::getDeptCode, deptInfoReqVo.getDeptCode())
.or(true,(queryWrapper -> queryWrapper.eq(SystemDept::getDeptName, deptInfoReqVo.getDeptName()))).count();
Assert.isTrue(count == 0, "部门名或编码已存在");
SystemDept systemDept = new SystemDept();
systemDept.setDeptCode(deptInfoReqVo.getDeptCode());
systemDept.setDeptName(deptInfoReqVo.getDeptName());
systemDept.setParentDeptId(deptInfoReqVo.getParentDeptId());
systemDept.setRemark(deptInfoReqVo.getRemark());
systemDeptService.save(systemDept);
return systemDept.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateDept(DeptInfoReqVo deptInfoReqVo) {
Assert.notEmpty(deptInfoReqVo.getId(), "id不能为空");
Assert.notEmpty(deptInfoReqVo.getDeptName(), "部门名称不能为空");
Assert.notEmpty(deptInfoReqVo.getDeptCode(), "部门编码不能为空");
Long count = systemDeptService.lambdaQuery()
.and(true,(queryWrapper -> queryWrapper.eq(SystemDept::getDeptCode, deptInfoReqVo.getDeptCode())
.or().eq(SystemDept::getDeptName, deptInfoReqVo.getDeptName())))
.and(true,(queryWrapper -> queryWrapper.ne(SystemDept::getId, deptInfoReqVo.getId())))
.count();
Assert.isTrue(count == 0, "部门名或编码已存在");
SystemDept systemDept = new SystemDept();
systemDept.setId(deptInfoReqVo.getId());
systemDept.setDeptCode(deptInfoReqVo.getDeptCode());
systemDept.setDeptName(deptInfoReqVo.getDeptName());
systemDept.setParentDeptId(deptInfoReqVo.getParentDeptId());
systemDept.setRemark(deptInfoReqVo.getRemark());
systemDeptService.updateById(systemDept);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteDept(String id) {
Long count = userManageService.countUserByDeptId(id, 0);
Assert.isTrue(count == 0, "该部门下存在用户,不能删除");
return systemDeptService.removeById(id);
}
@Override
public IPage<DeptInfoResVo> pageListDept(String deptName, String deptCode, Integer pageNum, Integer pageSize) {
return systemDeptService.pageListDept(deptName, deptCode, pageNum, pageSize);
}
}

@ -0,0 +1,123 @@
package com.supervision.knowsub.service.impl;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.supervision.knowsub.model.SystemDic;
import com.supervision.knowsub.model.SystemDicData;
import com.supervision.knowsub.service.DicManageService;
import com.supervision.knowsub.service.SystemDicDataService;
import com.supervision.knowsub.service.SystemDicService;
import com.supervision.knowsub.vo.dic.DicDataReqVo;
import com.supervision.knowsub.vo.dic.DicReqVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@RequiredArgsConstructor
public class DicManageServiceImpl implements DicManageService {
private final SystemDicService systemDicService;
private final SystemDicDataService systemDicDataService;
@Override
@Transactional(rollbackFor = Exception.class)
public String saveDic(DicReqVo dicReqVo) {
Assert.notEmpty(dicReqVo.getDicName(), "字典名称不能为空");
Assert.notEmpty(dicReqVo.getDicCode(), "字典编码不能为空");
Long count = systemDicService.lambdaQuery().eq(SystemDic::getDicCode, dicReqVo.getDicCode()).count();
Assert.isTrue(count == 0, "字典编码已存在");
SystemDic systemDic = new SystemDic();
systemDic.setDicName(dicReqVo.getDicName());
systemDic.setDicCode(dicReqVo.getDicCode());
systemDic.setRemark(dicReqVo.getRemark());
systemDicService.save(systemDic);
return systemDic.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateDic(DicReqVo dicReqVo) {
Assert.notEmpty(dicReqVo.getId(), "字典id不能为空");
Assert.notEmpty(dicReqVo.getDicName(), "字典名称不能为空");
Assert.notEmpty(dicReqVo.getDicCode(), "字典编码不能为空");
SystemDic dbDic = systemDicService.getById(dicReqVo.getId());
Assert.notNull(dbDic, "字典不存在");
if (!StrUtil.equals(dbDic.getDicCode(), dicReqVo.getDicCode())){
// 判断字典编码是否重复
Long count = systemDicService.lambdaQuery().eq(SystemDic::getDicCode, dicReqVo.getDicCode()).count();
Assert.isTrue(count == 0, "字典编码已存在");
}
// 更新数据
systemDicService.lambdaUpdate().set(SystemDic::getDicName, dicReqVo.getDicName())
.set(SystemDic::getDicCode, dicReqVo.getDicCode())
.set(SystemDic::getRemark, dicReqVo.getRemark())
.eq(SystemDic::getId, dicReqVo.getId()).update();
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteDic(String id) {
Assert.notEmpty(id, "字典id不能为空");
boolean success = systemDicService.removeById(id);
if (success){
systemDicDataService.lambdaUpdate().eq(SystemDicData::getDicId, id).remove();
}
return success;
}
@Override
public IPage<SystemDic> listDic(String dicName, String dicCode, Integer pageNum, Integer pageSize) {
return systemDicService.lambdaQuery()
.like(StrUtil.isNotEmpty(dicName), SystemDic::getDicName, dicName)
.eq(StrUtil.isNotEmpty(dicCode), SystemDic::getDicCode, dicCode)
.orderBy(true,false, SystemDic::getUpdateTime)
.page(new Page<>(pageNum, pageSize));
}
@Override
@Transactional(rollbackFor = Exception.class)
public String saveDicData(String dicId, List<DicDataReqVo> dicDataReqVoList) {
Assert.notEmpty(dicId, "字典id不能为空");
//清除原本的数据
systemDicDataService.lambdaUpdate().eq(SystemDicData::getDicId, dicId).remove();
List<SystemDicData> list = dicDataReqVoList.stream().map(dicDataReqVo -> {
SystemDicData systemDicData = new SystemDicData();
systemDicData.setDicId(dicId);
systemDicData.setDicLabel(dicDataReqVo.getDicLabel());
systemDicData.setDicValue(dicDataReqVo.getDicValue());
systemDicData.setDicSort(ObjUtil.isNull(dicDataReqVo.getDicSort()) ? 0 : dicDataReqVo.getDicSort());
return systemDicData;
}).toList();
systemDicDataService.saveBatch(list);
return dicId;
}
@Override
public List<SystemDicData> queryDicDate(String dicId) {
Assert.notEmpty(dicId, "字典id不能为空");
return systemDicDataService.lambdaQuery().eq(SystemDicData::getDicId, dicId).orderBy(true,true, SystemDicData::getDicSort).list();
}
}

@ -0,0 +1,98 @@
package com.supervision.knowsub.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.unit.DataSizeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.supervision.knowsub.exception.BusinessException;
import com.supervision.knowsub.model.FileBlob;
import com.supervision.knowsub.model.FileInfo;
import com.supervision.knowsub.service.FileBlobService;
import com.supervision.knowsub.service.FileInfoService;
import com.supervision.knowsub.service.FileService;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@Service
@Slf4j
@RequiredArgsConstructor
public class FileServiceImpl implements FileService {
private final FileInfoService fileInfoService;
private final FileBlobService fileBlobService;
@Override
@Transactional(rollbackFor = Exception.class)
public String uploadFile(String fileName, byte[] fileBytes) {
log.info("{}:文件进行保存", fileName);
FileBlob fileBlob = new FileBlob();
fileBlob.setBlobByte(fileBytes);
fileBlob.insert();
FileInfo fileInfo = new FileInfo();
fileInfo.setFileName(fileName);
fileInfo.setFileSize(fileBytes.length);
fileInfo.setFileSizeStr(DataSizeUtil.format(fileBytes.length));
fileInfo.setFileType(FileUtil.getSuffix(fileName));
fileInfo.setFileBlobId(fileBlob.getId());
fileInfoService.save(fileInfo);
log.info("{}:文件保存成功", fileName);
return fileInfo.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteFileById(String fileId) {
FileInfo one = fileInfoService.lambdaQuery().eq(FileInfo::getId, fileId).one();
if (ObjectUtil.isNotEmpty(one)){
fileBlobService.removeById(one.getFileBlobId());
fileInfoService.removeById(fileId);
}
}
@Override
public List<FileInfo> listByFileId(List<String> fileIdList) {
if (CollUtil.isEmpty(fileIdList)){
return new ArrayList<>();
}
return fileInfoService.lambdaQuery().in(FileInfo::getId, fileIdList).list();
}
@Override
public void downloadFile(String fileId, HttpServletResponse response) {
Assert.notEmpty(fileId, "文件id不能为空");
FileInfo fileInfo = fileInfoService.getById(fileId);
Assert.notNull(fileInfo, "文件不存在");
FileBlob fileBlob = fileBlobService.getById(fileInfo.getFileBlobId());
Assert.notNull(fileBlob, "文件内容不存在");
if (StrUtil.isNotEmpty(fileInfo.getFileName())){
response.setHeader("Content-Disposition", "attachment;filename=" +
URLEncoder.encode(fileInfo.getFileName(), StandardCharsets.UTF_8));
}
try (ServletOutputStream outputStream = response.getOutputStream()){
response.setContentType("application/octet-stream");
outputStream.write(fileBlob.getBlobByte());
outputStream.flush();
}catch (Exception e){
log.error("文件下载失败",e);
throw new BusinessException("下载文件失败",e);
}
}
}

@ -0,0 +1,305 @@
package com.supervision.knowsub.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.dto.flow.SystemFlowTypeDTO;
import com.supervision.knowsub.exception.BusinessException;
import com.supervision.knowsub.model.SystemBase;
import com.supervision.knowsub.model.SystemFlow;
import com.supervision.knowsub.model.SystemFlowBaseRelation;
import com.supervision.knowsub.model.SystemFlowTypeRelation;
import com.supervision.knowsub.service.*;
import com.supervision.knowsub.vo.flow.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
@Service
@Slf4j
@RequiredArgsConstructor
public class FlowManageServiceImpl implements FlowManageService {
private final SystemFlowService systemFlowService;
private final SystemFlowBaseRelationService systemFlowBaseRelationService;
private final SystemFlowTypeRelationService systemFlowTypeRelationService;
private final FlowRuleManageService flowRuleManageService;
private final ApplicationSubLibraryService applicationSubLibraryService;
@Override
@Transactional(rollbackFor = Exception.class)
public String saveFlow(FlowInfoReqVo flowInfoReqVo) {
assertBase(flowInfoReqVo);
Long count = systemFlowService.lambdaQuery().eq(SystemFlow::getFlowName, flowInfoReqVo.getFlowName()).count();
Assert.isTrue(count == 0, "流程名称已存在");
// 一个子库最多对应一种流程类型
List<String> baseIdList = flowInfoReqVo.getBaseIdList();
List<Integer> flowTypeList = flowInfoReqVo.getFlowTypeList();
if (CollUtil.isNotEmpty(baseIdList) & CollUtil.isNotEmpty(flowTypeList)){
List<SystemFlowTypeRelation> flowTypeRelationList = systemFlowTypeRelationService.lambdaQuery().in(SystemFlowTypeRelation::getBaseId, baseIdList).list();
flowTypeRelationList.forEach(flowTypeRelation ->
Assert.isTrue(!flowTypeList.contains(flowTypeRelation.getFlowType()), "该子库已存在流程类型"));
}
// 保存数据
return doSaveFlow(flowInfoReqVo);
}
private String doSaveFlow(FlowInfoReqVo flowInfoReqVo) {
// 保存主表数据
SystemFlow systemFlow = new SystemFlow();
systemFlow.setFlowName(flowInfoReqVo.getFlowName());
systemFlow.setRemark(flowInfoReqVo.getRemark());
systemFlowService.save(systemFlow);
// 保存关联表数据
List<String> baseIdList = flowInfoReqVo.getBaseIdList();
List<SystemFlowBaseRelation> flowBaseRelationList = flowInfoReqVo.getBaseIdList().stream().map(baseId -> {
SystemFlowBaseRelation flowBaseRelation = new SystemFlowBaseRelation();
flowBaseRelation.setFlowId(systemFlow.getId());
flowBaseRelation.setBaseId(baseId);
return flowBaseRelation;
}).toList();
systemFlowBaseRelationService.saveBatch(flowBaseRelationList);
doBatchSaveFlowTypeRelation(systemFlow.getId(), flowInfoReqVo.getFlowTypeList(), baseIdList);
flowRuleManageService.saveFlowRule(systemFlow.getId(), flowInfoReqVo.getNodeInfoList());
return systemFlow.getId();
}
/**
*
* @param flowId id
* @param flowTypeList id
* @param baseIdList id
*/
private void doBatchSaveFlowTypeRelation(String flowId,List<Integer> flowTypeList, List<String> baseIdList) {
List<SystemFlowTypeRelation> flowTypeRelationList = flowTypeList.stream().map(flowType -> baseIdList.stream()
.map(baseId -> {
SystemFlowTypeRelation flowTypeRelation = new SystemFlowTypeRelation();
flowTypeRelation.setFlowType(flowType);
flowTypeRelation.setBaseId(baseId);
flowTypeRelation.setFlowId(flowId);
return flowTypeRelation;
}).toList()).flatMap(Collection::stream).toList();
systemFlowTypeRelationService.saveBatch(flowTypeRelationList);
}
@Override
public List<String> listUsedBaseIds(List<Integer> typeIds){
if (CollUtil.isEmpty(typeIds)){
return CollUtil.newArrayList();
}
return systemFlowTypeRelationService.lambdaQuery().in(SystemFlowTypeRelation::getFlowType, typeIds).list()
.stream().map(SystemFlowTypeRelation::getBaseId).distinct().toList();
}
private void assertBase(FlowInfoReqVo flowInfoReqVo){
Assert.notEmpty(flowInfoReqVo.getFlowName());
Assert.notEmpty(flowInfoReqVo.getFlowTypeList());
Assert.notEmpty(flowInfoReqVo.getBaseIdList());
Assert.notEmpty(flowInfoReqVo.getNodeInfoList());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateFlow(FlowInfoReqVo flowInfoReqVo) {
Assert.notEmpty(flowInfoReqVo.getId(), "流程id不能为空");
assertBase(flowInfoReqVo);
SystemFlow dbSystem = systemFlowService.getById(flowInfoReqVo.getId());
Assert.notNull(dbSystem, "流程不存在");
// 一个子库最多对应一种流程类型
List<String> baseIdList = flowInfoReqVo.getBaseIdList();
List<Integer> flowTypeList = flowInfoReqVo.getFlowTypeList();
if (CollUtil.isNotEmpty(baseIdList) && CollUtil.isNotEmpty(flowTypeList)){
List<SystemFlowTypeRelation> flowTypeRelationList = systemFlowTypeRelationService.lambdaQuery()
.in(SystemFlowTypeRelation::getBaseId, baseIdList).notIn(SystemFlowTypeRelation::getFlowId, flowInfoReqVo.getId()).list();
flowTypeRelationList.forEach(flowTypeRelation ->
Assert.isTrue(!flowTypeList.contains(flowTypeRelation.getFlowType()), "该子库已存在流程类型"));
}
// 更新主表数据
doUpdateFlow(flowInfoReqVo);
}
/**
*
* @param flowInfoReqVo
*/
private void doUpdateFlow(FlowInfoReqVo flowInfoReqVo) {
// 更新主表数据
SystemFlow systemFlow = new SystemFlow();
systemFlow.setId(flowInfoReqVo.getId());
systemFlow.setFlowName(flowInfoReqVo.getFlowName());
systemFlow.setRemark(flowInfoReqVo.getRemark());
systemFlowService.updateById(systemFlow);
// 更新关联表数据
updateFlowBaseRelation(flowInfoReqVo.getId(), flowInfoReqVo.getBaseIdList());
// 更新流程类型关联表数据
updateFlowTypeRelation(flowInfoReqVo.getId(), flowInfoReqVo.getFlowTypeList(), flowInfoReqVo.getBaseIdList());
// 更新流程规则表数据
flowRuleManageService.updateFlowRule(flowInfoReqVo.getId(), flowInfoReqVo.getNodeInfoList());
}
/**
*
*
*
*
* @param flowId id
* @param baseIdList id
*/
private void updateFlowBaseRelation(String flowId, List<String> baseIdList){
List<SystemFlowBaseRelation> dbFlowBaseRelationList = systemFlowBaseRelationService.lambdaQuery().eq(SystemFlowBaseRelation::getFlowId, flowId).list();
List<String> dbBaseIds = dbFlowBaseRelationList.stream().map(SystemFlowBaseRelation::getBaseId).toList();
// 数据库中不存在,入参中存在,新增
List<String> needInsert = baseIdList.stream().filter(baseId -> !dbBaseIds.contains(baseId)).toList();
// 数据库中存在,入参中不存在,删除
List<String> needDelete = dbBaseIds.stream().filter(baseId -> !baseIdList.contains(baseId)).toList();
if (CollUtil.isNotEmpty(needInsert)){
List<SystemFlowBaseRelation> baseRelationList = needInsert.stream().map(baseId -> {
SystemFlowBaseRelation flowBaseRelation = new SystemFlowBaseRelation();
flowBaseRelation.setBaseId(baseId);
flowBaseRelation.setFlowId(flowId);
return flowBaseRelation;
}).toList();
systemFlowBaseRelationService.saveBatch(baseRelationList);
}
if (CollUtil.isNotEmpty(needDelete)){
systemFlowBaseRelationService.lambdaUpdate().in(SystemFlowBaseRelation::getBaseId, needDelete)
.eq(SystemFlowBaseRelation::getFlowId, flowId).remove();
}
}
/**
*
*
*
*
* @param flowId id
* @param flowTypeList
* @param baseIdList id
*/
private void updateFlowTypeRelation(String flowId, List<Integer> flowTypeList,List<String> baseIdList){
List<SystemFlowTypeRelation> flowTypeRelationList = systemFlowTypeRelationService.lambdaQuery().eq(SystemFlowTypeRelation::getFlowId, flowId).list();
// 从数据库中查询出来的数据
List<SystemFlowTypeDTO> dbFlowTypeDTOList = flowTypeRelationList.stream().map(SystemFlowTypeDTO::buildWithFlowTypeRelation).toList();
// 入参中的数据
List<SystemFlowTypeDTO> flowTypeDTOList = flowTypeList.stream().map(flowType ->
baseIdList.stream().map(baseId ->
SystemFlowTypeDTO.builder().baseId(baseId).flowId(flowId).flowType(flowType).build()).toList()
).flatMap(Collection::stream).toList();
// 数据库中不存在,入参中存在,新增 流程类型与子库id组合成唯一数据
List<SystemFlowTypeDTO> needInsert = flowTypeDTOList.stream().filter(systemFlowTypeDTO ->
dbFlowTypeDTOList.stream().noneMatch(dbSystemFlowTypeDTO ->
dbSystemFlowTypeDTO.contentEquals(systemFlowTypeDTO))
).toList();
// 数据库中存在,入参中不存在,删除 流程类型与子库id组合成唯一数据
List<SystemFlowTypeDTO> needDelete = dbFlowTypeDTOList.stream().filter(dbSystemFlowTypeDTO ->
flowTypeDTOList.stream().noneMatch(dbSystemFlowTypeDTO::contentEquals)).toList();
if (CollUtil.isNotEmpty(needInsert)){
List<SystemFlowTypeRelation> flowTypeRelations = needInsert.stream().map(SystemFlowTypeDTO::toSystemFlowTypeRelation).toList();
systemFlowTypeRelationService.saveBatch(flowTypeRelations);
}
if (CollUtil.isNotEmpty(needDelete)){
List<String> needDeleteIds = needDelete.stream().map(SystemFlowTypeDTO::getId).filter(StrUtil::isNotEmpty).toList();
systemFlowTypeRelationService.removeBatchByIds(needDeleteIds);
}
}
@Override
public Boolean deleteFlow(String id) {
throw new BusinessException("暂不支持删除流程");
}
@Override
public IPage<FlowInfoResVo> pageListFlow(String flowName, Integer pageNum, Integer pageSize) {
return systemFlowService.pageListFlow(flowName, pageNum, pageSize);
}
@Override
public List<BaseResVo> optionalBaseList(List<Integer> flowType) {
List<SystemBase> allSubLibrary = applicationSubLibraryService.listAllSubLibrary();
final List<SystemFlowTypeRelation> flowTypeRelationList = new ArrayList<>();
if (CollUtil.isNotEmpty(flowType)){
flowTypeRelationList.addAll(
systemFlowTypeRelationService.lambdaQuery()
.in(SystemFlowTypeRelation::getFlowType, flowType).list()) ;
}
return allSubLibrary.stream().filter(systemBase ->
flowTypeRelationList.stream().noneMatch(flowTypeRelation ->
flowTypeRelation.getBaseId().equals(systemBase.getId()))).map(systemBase -> {
BaseResVo baseResVo = new BaseResVo();
baseResVo.setBaseId(systemBase.getId());
baseResVo.setBaseName(systemBase.getBaseName());
return baseResVo;
}).toList();
}
@Override
public FlowDetailResVo getFlowDetail(String flowId) {
Assert.notEmpty(flowId, "流程id不能为空");
SystemFlow systemFlow = systemFlowService.getById(flowId);
Assert.notNull(systemFlow, "流程不存在");
FlowDetailResVo flowDetail = FlowDetailResVo.builder().id(systemFlow.getId())
.flowName(systemFlow.getFlowName()).remark(systemFlow.getRemark()).build();
List<SystemFlowBaseRelation> flowBaseRelationList = systemFlowBaseRelationService.lambdaQuery().eq(SystemFlowBaseRelation::getFlowId, flowId).list();
if (CollUtil.isNotEmpty(flowBaseRelationList)){
flowDetail.setSubLibraryIdList(flowBaseRelationList.stream().map(SystemFlowBaseRelation::getBaseId).toList());
}
List<SystemFlowTypeRelation> flowTypeRelationList = systemFlowTypeRelationService.lambdaQuery().eq(SystemFlowTypeRelation::getFlowId, flowId).list();
if (CollUtil.isNotEmpty(flowTypeRelationList)){
flowDetail.setFlowTypeIdList(
flowTypeRelationList.stream().map(SystemFlowTypeRelation::getFlowType).distinct().toList());
}
List<NodeInfo> nodeInfos = flowRuleManageService.listFlowRule(flowId);
nodeInfos.sort(Comparator.comparing(NodeInfo::getOrder));
flowDetail.setNodeInfoList(nodeInfos);
return flowDetail;
}
}

@ -0,0 +1,195 @@
package com.supervision.knowsub.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.supervision.knowsub.dto.flow.SystemFlowRuleDTO;
import com.supervision.knowsub.model.SystemFlowRule;
import com.supervision.knowsub.model.SystemFlowRuleUser;
import com.supervision.knowsub.service.FlowRuleManageService;
import com.supervision.knowsub.service.SystemFlowRuleService;
import com.supervision.knowsub.service.SystemFlowRuleUserService;
import com.supervision.knowsub.vo.flow.NodeInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Slf4j
@RequiredArgsConstructor
public class FlowRuleManageServiceImpl implements FlowRuleManageService {
private final SystemFlowRuleService systemFlowRuleService;
private final SystemFlowRuleUserService systemFlowRuleUserService;
@Override
@Transactional(rollbackFor = Exception.class)
public boolean saveFlowRule(String flowId, List<NodeInfo> nodeInfoList) {
Assert.notEmpty(flowId, "流程id不能为空");
Assert.notEmpty(nodeInfoList, "节点信息不能为空");
int i = 0;
for (NodeInfo nodeInfo : nodeInfoList) {
SystemFlowRule flowRule = new SystemFlowRule();
flowRule.setFlowId(flowId);
flowRule.setRuleName(nodeInfo.getNodeName());
flowRule.setRuleOrder(i++);
flowRule.setRoleId(nodeInfo.getRoleId());
systemFlowRuleService.save(flowRule);
systemFlowRuleUserService.saveBatch(nodeInfo.getUserIdList().stream().map(userId -> {
SystemFlowRuleUser flowRuleUser = new SystemFlowRuleUser();
flowRuleUser.setFlowId(flowId);
flowRuleUser.setRuleId(flowRule.getId());
flowRuleUser.setUserId(userId);
return flowRuleUser;
}).toList());
}
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveFlowRule(List<SystemFlowRuleDTO> systemFlowRuleDTOList) {
if (CollUtil.isEmpty(systemFlowRuleDTOList)){
return;
}
for (SystemFlowRuleDTO systemFlowRuleDTO : systemFlowRuleDTOList) {
SystemFlowRule systemFlowRule = systemFlowRuleDTO.toSystemFlowRule();
systemFlowRuleService.save(systemFlowRule);
List<SystemFlowRuleUser> systemFlowRuleUserList = systemFlowRuleDTO.toSystemFlowRuleUserList();
if (CollUtil.isNotEmpty(systemFlowRuleUserList)){
for (SystemFlowRuleUser systemFlowRuleUser : systemFlowRuleUserList) {
systemFlowRuleUser.setRuleId(systemFlowRule.getId());
systemFlowRuleUserService.save(systemFlowRuleUser);
}
}
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateFlowRule(List<SystemFlowRuleDTO> systemFlowRuleDTOList) {
if (CollUtil.isEmpty(systemFlowRuleDTOList)){
return;
}
systemFlowRuleDTOList.forEach(systemFlowRuleDTO -> Assert.notEmpty(systemFlowRuleDTO.getId(), "流程id不能为空"));
for (SystemFlowRuleDTO systemFlowRuleDTO : systemFlowRuleDTOList) {
SystemFlowRule systemFlowRule = systemFlowRuleDTO.toSystemFlowRule();
systemFlowRuleService.updateById(systemFlowRule);
systemFlowRuleUserService.lambdaUpdate().eq(SystemFlowRuleUser::getRuleId, systemFlowRuleDTO.getId()).remove();
List<SystemFlowRuleUser> systemFlowRuleUserList = systemFlowRuleDTO.toSystemFlowRuleUserList();
if (CollUtil.isNotEmpty(systemFlowRuleUserList)){
for (SystemFlowRuleUser systemFlowRuleUser : systemFlowRuleUserList) {
systemFlowRuleUser.setRuleId(systemFlowRule.getId());
systemFlowRuleUserService.save(systemFlowRuleUser);
}
}
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean updateFlowRule(String flowId, List<NodeInfo> nodeInfoList) {
Assert.notEmpty(flowId, "流程id不能为空");
List<String> nodeIds = nodeInfoList.stream().map(NodeInfo::getId).filter(StrUtil::isNotEmpty).toList();
List<SystemFlowRule> flowRuleList = systemFlowRuleService.lambdaQuery().eq(SystemFlowRule::getFlowId, flowId).list();
List<String> flowRuleIdList = flowRuleList.stream().map(SystemFlowRule::getId).toList();
Set<String> flowRuleIdSet = flowRuleList.stream().map(SystemFlowRule::getId).collect(Collectors.toSet());
FlowRuleDTOPair flowRuleDTOPair = pickInsertAndUpdateFlowRuleDTO(flowId, nodeInfoList, flowRuleIdSet);
// 新增数据
if (CollUtil.isNotEmpty(flowRuleDTOPair.needAddRuleList())){
saveFlowRule(flowRuleDTOPair.needAddRuleList());
}
// 更新数据
if (CollUtil.isNotEmpty(flowRuleDTOPair.needUpdateRuleList())){
updateFlowRule(flowRuleDTOPair.needUpdateRuleList());
}
//如果数据库中存在,列表中不存在,则删除
List<String> needDeleteRuleIdList = flowRuleIdList.stream().filter(ruleId -> !nodeIds.contains(ruleId)).toList();
if (CollUtil.isNotEmpty(needDeleteRuleIdList)){
deleteFlowRuleByRuleIds(needDeleteRuleIdList);
}
return true;
}
/**
*
* @param flowId id
* @param nodeInfoList
* @param flowRuleIdSet
* @return
*/
private FlowRuleDTOPair pickInsertAndUpdateFlowRuleDTO(String flowId, List<NodeInfo> nodeInfoList, Set<String> flowRuleIdSet) {
List<SystemFlowRuleDTO> needUpdateRuleList = new ArrayList<>();
List<SystemFlowRuleDTO> needAddRuleList = new ArrayList<>();
int order = 0;
for (NodeInfo nodeInfo : nodeInfoList) {
nodeInfo.setOrder(order++);
if (StrUtil.isNotEmpty(nodeInfo.getId()) && flowRuleIdSet.contains(nodeInfo.getId())){
// 需要更新的数据
needUpdateRuleList.add(SystemFlowRuleDTO.builderWithNodeInfo(flowId, nodeInfo));
}else {
// id为空或者不包含在数据库中需要增加的数据
needAddRuleList.add(SystemFlowRuleDTO.builderWithNodeInfo(flowId, nodeInfo));
}
}
return new FlowRuleDTOPair(needUpdateRuleList, needAddRuleList);
}
private record FlowRuleDTOPair(List<SystemFlowRuleDTO> needUpdateRuleList, List<SystemFlowRuleDTO> needAddRuleList) {
}
@Override
public List<NodeInfo> listFlowRule(String flowId) {
if (StrUtil.isEmpty(flowId)){
return CollUtil.newArrayList();
}
List<SystemFlowRule> flowRuleList = systemFlowRuleService.lambdaQuery().eq(SystemFlowRule::getFlowId, flowId).list();
if (CollUtil.isEmpty(flowRuleList)){
return CollUtil.newArrayList();
}
List<NodeInfo> nodeInfoList = flowRuleList.stream().map(flowRule -> NodeInfo.builder()
.NodeName(flowRule.getRuleName()).id(flowRule.getId())
.order(flowRule.getRuleOrder()).roleId(flowRule.getRoleId()).build())
.collect(Collectors.toList());
List<SystemFlowRuleUser> ruleUserList = systemFlowRuleUserService.lambdaQuery().in(SystemFlowRuleUser::getFlowId, flowId).list();
Map<String, List<SystemFlowRuleUser>> ruleUserGroupByRuleId = ruleUserList.stream().collect(Collectors.groupingBy(SystemFlowRuleUser::getRuleId));
nodeInfoList.forEach(nodeInfo -> {
List<SystemFlowRuleUser> ruleUserListByRuleId = ruleUserGroupByRuleId.get(nodeInfo.getId());
if (CollUtil.isNotEmpty(ruleUserListByRuleId)){
nodeInfo.setUserIdList(ruleUserListByRuleId.stream().map(SystemFlowRuleUser::getUserId).toList());
}
});
return nodeInfoList;
}
@Override
public void deleteFlowRuleByRuleIds(List<String> ruleIdList) {
if (CollUtil.isEmpty(ruleIdList)){
log.info("流程规则id为空不执行删除操作");
return;
}
systemFlowRuleService.removeBatchByIds(ruleIdList);
systemFlowRuleUserService.lambdaUpdate().in(SystemFlowRuleUser::getRuleId, ruleIdList).remove();
}
}

@ -0,0 +1,108 @@
package com.supervision.knowsub.service.impl;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.supervision.knowsub.domain.UserInfo;
import com.supervision.knowsub.entity.vo.homepage.MyKnowledgeStatisticsResVO;
import com.supervision.knowsub.enums.RoleTypeEnum;
import com.supervision.knowsub.enums.StatusEnum;
import com.supervision.knowsub.exception.BusinessException;
import com.supervision.knowsub.model.Knowledge;
import com.supervision.knowsub.model.KnowledgeFlowTodo;
import com.supervision.knowsub.model.SystemUser;
import com.supervision.knowsub.service.*;
import com.supervision.knowsub.util.UserUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Slf4j
@Service
@RequiredArgsConstructor
public class HomepageServiceImpl implements HomepageService {
private final KnowledgeService knowledgeService;
private final SystemUserService systemUserService;
private final KnowledgeFlowTodoService knowledgeFlowTodoService;
private final KnowledgeFlowRecordService knowledgeFlowRecordService;
private final KnowledgeSubmitRecordService knowledgeSubmitRecordService;
/**
*
* ,
*
* 0
* <p>
* :,,
* <p>
*
*
*
*
* :
*
* : ,使,,
* <p>
*
*
*
*
* : ,
*
*
* @return
*/
@Override
public MyKnowledgeStatisticsResVO queryMyKnowledgeStatistics() {
UserInfo user = UserUtil.getUser();
SystemUser systemUser = systemUserService.getOptById(user.getId()).orElseThrow(() -> new BusinessException("未找到用户"));
MyKnowledgeStatisticsResVO resVO = new MyKnowledgeStatisticsResVO();
resVO.setUserName(user.getUsername());
resVO.setLastLoginTime(systemUser.getRecentLoginTime());
// 首先查询用户是否有审批的权限,
List<Integer> roleTypeList = user.getRoleTypeList();
log.info("用户角色信息:{}", JSONUtil.toJsonStr(roleTypeList));
Set<Integer> passStatusSet = new HashSet<>(List.of(new Integer[]{2, 11, 12, 16, 17}));
Long passTotalCount = knowledgeService.lambdaQuery().in(Knowledge::getStatus, passStatusSet).count();
resVO.setKnowledgeCount(passTotalCount);
// 如果用户有审批权限,则以审批人的视角
if (roleTypeList.contains(RoleTypeEnum.KNOWLEDGE_APPROVAL.getRoleType())) {
log.info("用户有知识审批权限,以审批人的视角进行统计");
// 待审批
resVO.setWaitProcessCount(knowledgeFlowTodoService.lambdaQuery().eq(KnowledgeFlowTodo::getTodoUserId, user.getId()).count());
// 由我审批并标记为审批通过的数量
resVO.setPassProcessCount(knowledgeFlowRecordService.queryPassProcessCountByUser(user.getId(), 1, null));
// 由我审批并标记为“驳回”的知识数量。
resVO.setRejectProcessCount(knowledgeFlowRecordService.queryPassProcessCountByUser(user.getId(), 2, null));
// 查询由我审批且目前已失效的
resVO.setInvalidProcessCount(knowledgeFlowRecordService.queryPassProcessCountByUser(user.getId(), null, 5));
}
// 没有被配置审批权限,则以报送人员视角进行统计
else if (roleTypeList.contains(RoleTypeEnum.KNOWLEDGE_SUBMIT.getRoleType())) {
log.info("用户没有被配置知识审批权限,则以报送人员视角进行统计");
// 待审批:我提交的且当前处于“待审批”状态的知识数量。
resVO.setWaitProcessCount(knowledgeSubmitRecordService.queryKnowledgeSubmitTodoCount(user.getId()));
// 驳回的数量
Long recallSubmitCount = knowledgeSubmitRecordService.queryKnowledgeSubmitStatusCount(user.getId(), StatusEnum.RECALL_APPROVAL_SUBMIT.getStatus());
Long recallDeleteCount = knowledgeSubmitRecordService.queryKnowledgeSubmitStatusCount(user.getId(), StatusEnum.RECALL_APPROVAL_DELETE.getStatus());
Long recallRecallCount = knowledgeSubmitRecordService.queryKnowledgeSubmitStatusCount(user.getId(), StatusEnum.RECALL_APPROVAL_RECALL.getStatus());
resVO.setRejectProcessCount(NumberUtil.add(recallSubmitCount, recallDeleteCount, recallRecallCount).longValue());
resVO.setInvalidProcessCount(knowledgeSubmitRecordService.queryKnowledgeSubmitStatusCount(user.getId(), StatusEnum.INVALID.getStatus()));
resVO.setPassProcessCount(knowledgeSubmitRecordService.queryKnowledgeSubmitStatusCount(user.getId(), StatusEnum.PASS.getStatus()));
} else {
log.info("用户没有任何角色权限,就只展示全量的,其他的都是0");
}
// 没有任何角色权限,就只展示全量的,其他的都是0
return resVO;
}
}

@ -0,0 +1,364 @@
package com.supervision.knowsub.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.supervision.knowsub.domain.UserInfo;
import com.supervision.knowsub.entity.vo.knowledge.KnowledgeFlowRecordResVO;
import com.supervision.knowsub.entity.vo.knowledge.ProcessFlowReqVO;
import com.supervision.knowsub.enums.FlowTypeEnum;
import com.supervision.knowsub.enums.StatusEnum;
import com.supervision.knowsub.exception.BusinessException;
import com.supervision.knowsub.mapper.KnowledgeFlowRecordMapper;
import com.supervision.knowsub.model.*;
import com.supervision.knowsub.service.*;
import com.supervision.knowsub.util.UserUtil;
import com.supervision.knowsub.vo.knowledge.KnowledgeFlowResVO;
import com.supervision.knowsub.vo.knowledge.KnowledgePageResVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class KnowledgeFlowServiceImpl implements KnowledgeFlowService {
private final KnowledgeFlowRecordService knowledgeFlowRecordService;
private final SystemFlowTypeRelationService systemFlowTypeRelationService;
private final SystemFlowRuleService systemFlowRuleService;
private final SystemFlowRuleUserService systemFlowRuleUserService;
private final KnowledgeFlowTodoService knowledgeFlowTodoService;
private final KnowledgeService knowledgeService;
private final SystemUserService systemUserService;
private final SystemDeptService systemDeptService;
private final KnowledgeSubmitRecordService knowledgeSubmitRecordService;
@Override
public IPage<KnowledgeFlowResVO> queryKnowledgeFlowPage(Integer processStatus, String title, String publishDeptId, String baseId,
String submitDeptId, Integer flowType,
LocalDate publishDateBegin, LocalDate publishDateEnd, LocalDate submitDateBegin, LocalDate submitDateEnd,
Integer pageNum, Integer pageSize) {
Assert.notNull(processStatus, "审批状态不能为空");
UserInfo user = UserUtil.getUser();
IPage<KnowledgeFlowResVO> result;
// 查询待办
if (1 == processStatus) {
result = knowledgeFlowRecordService.queryKnowledgeFlowTodoPage(user.getId(), title, publishDeptId, baseId, submitDeptId, flowType,
publishDateBegin, publishDateEnd, submitDateBegin, submitDateEnd, new Page<>(pageNum, pageSize));
}
// 查询已办
else if (2 == processStatus) {
result = knowledgeFlowRecordService.queryKnowledgeFlowCompletePage(user.getId(), title, publishDeptId, baseId, submitDeptId, flowType,
publishDateBegin, publishDateEnd, submitDateBegin, submitDateEnd, new Page<>(pageNum, pageSize));
} else {
throw new BusinessException("不支持的状态类型");
}
// 然后填充一些字段
List<KnowledgeFlowResVO> records = result.getRecords();
// 获取所有部门
Set<String> publishDeptSet = records.stream().map(KnowledgeFlowResVO::getPublishDeptId).collect(Collectors.toSet());
Set<String> submitDeptSet = records.stream().map(KnowledgeFlowResVO::getSubmitDeptId).collect(Collectors.toSet());
Collection<String> deptIdSet = CollUtil.union(submitDeptSet, publishDeptSet);
Map<String, String> deptMap = new HashMap<>();
if (CollUtil.isNotEmpty(deptIdSet)) {
deptMap = systemDeptService.listByIds(deptIdSet).stream().collect(Collectors.toMap(SystemDept::getId, SystemDept::getDeptName));
}
// 获取所有子库
Set<String> userIdSet = records.stream().map(KnowledgeFlowResVO::getSubmitUserId).collect(Collectors.toSet());
Map<String, String> userMap = new HashMap<>();
if (CollUtil.isNotEmpty(userIdSet)) {
userMap = systemUserService.listByIds(userIdSet).stream().collect(Collectors.toMap(SystemUser::getId, SystemUser::getUsername));
}
for (KnowledgeFlowResVO record : records) {
record.setSubmitUserName(userMap.getOrDefault(record.getSubmitUserId(), "未知用户"));
record.setSubmitDeptName(deptMap.getOrDefault(record.getSubmitDeptId(), "未知部门"));
record.setPublishDeptName(deptMap.getOrDefault(record.getPublishDeptId(), "未知部门"));
}
return result;
}
/**
*
*/
@Transactional(rollbackFor = Exception.class)
public void submitFlowProcess(Knowledge knowledge, FlowTypeEnum flowTypeEnum, String userId, String deptId, String remark) {
String flowInstanceId = UUID.fastUUID().toString();
// 首先查询到知识对应的子库
String baseId = knowledge.getBaseId();
if (StrUtil.isBlank(baseId)) {
throw new BusinessException("未找到对应的子库");
}
// 首先找到对应的审批流
Optional<SystemFlowTypeRelation> systemFlowTypeRelationOpt = systemFlowTypeRelationService.lambdaQuery()
.eq(SystemFlowTypeRelation::getBaseId, baseId)
.eq(SystemFlowTypeRelation::getFlowType, flowTypeEnum.getFlowType())
.last(" limit 1").oneOpt();
SystemFlowTypeRelation systemFlowTypeRelation = systemFlowTypeRelationOpt.orElseThrow(() -> new BusinessException("未找到审批流程,请联系管理员配置审批流程"));
List<SystemFlowRule> roleOrderList = queryFlowRuleWithOrder(systemFlowTypeRelation.getFlowId());
// 首先获取第一个节点,校验当前用户是否有权限提交
SystemFlowRule firstRule = roleOrderList.get(0);
Optional<SystemFlowRuleUser> systemFlowRuleUserOpt = systemFlowRuleUserService.lambdaQuery().eq(SystemFlowRuleUser::getFlowId, firstRule.getFlowId())
.eq(SystemFlowRuleUser::getUserId, userId).eq(SystemFlowRuleUser::getRuleId, firstRule.getId()).oneOpt();
if (systemFlowRuleUserOpt.isEmpty()) {
throw new BusinessException("当前用户没有权限提交:" + flowTypeEnum.getDesc() + " 流程,请联系管理员确认");
}
// 然后找到下一个节点
SystemFlowRule nextRule = roleOrderList.get(1);
List<SystemFlowRuleUser> nextRuleUserList = systemFlowRuleUserService.lambdaQuery().eq(SystemFlowRuleUser::getFlowId, nextRule.getFlowId()).eq(SystemFlowRuleUser::getRuleId, nextRule.getId()).list();
if (CollUtil.isEmpty(nextRuleUserList)) {
throw new BusinessException("审批节点未配置审批用户,流程提交失败");
}
// 创建审批记录的对象
KnowledgeFlowRecord knowledgeFlowRecord = KnowledgeFlowRecord.builder()
.type(1)
.knowledgeId(knowledge.getId())
.flowId(systemFlowTypeRelation.getFlowId())
// 新建的流程需要赋予一个实例ID
.flowInstanceId(flowInstanceId)
.flowType(flowTypeEnum.getFlowType())
.flowRuleId(firstRule.getId())
.flowRuleOrder(firstRule.getRuleOrder())
.processName(flowTypeEnum.getDesc())
.remark(remark)
.submitUserId(userId)
.submitDeptId(deptId)
.build();
knowledgeFlowRecordService.save(knowledgeFlowRecord);
// 只要是发起了审批流程,不管是什么流程,都进行记录发起人
KnowledgeSubmitRecord knowledgeSubmitRecord = new KnowledgeSubmitRecord();
knowledgeSubmitRecord.setKnowledgeId(knowledge.getId());
knowledgeSubmitRecord.setFlowId(systemFlowTypeRelation.getFlowId());
knowledgeSubmitRecord.setFlowType(systemFlowTypeRelation.getFlowType());
knowledgeSubmitRecord.setSubmitUserId(userId);
knowledgeSubmitRecord.setSubmitDeptId(deptId);
knowledgeSubmitRecordService.save(knowledgeSubmitRecord);
// 生成下一个节点的TODO
for (SystemFlowRuleUser todoUser : nextRuleUserList) {
KnowledgeFlowTodo todo = new KnowledgeFlowTodo();
todo.setFlowId(nextRule.getFlowId());
todo.setFlowInstanceId(flowInstanceId);
todo.setSubmitUserId(flowInstanceId);
todo.setFlowType(flowTypeEnum.getFlowType());
todo.setKnowledgeId(knowledge.getId());
todo.setRuleId(nextRule.getId());
todo.setTodoUserId(todoUser.getUserId());
todo.setSubmitUserId(userId);
todo.insert();
}
}
private List<SystemFlowRule> queryFlowRuleWithOrder(String flowId) {
List<SystemFlowRule> ruleList = systemFlowRuleService.lambdaQuery().eq(SystemFlowRule::getFlowId, flowId).list();
if (CollUtil.isEmpty(ruleList)) {
throw new BusinessException("审批流节点为空,请联系管理员配置审批流节点");
}
// 根据rule_order进行升序排序
List<SystemFlowRule> ruleOrderList = ruleList.stream().sorted(Comparator.comparingInt(SystemFlowRule::getRuleOrder)).toList();
// 应该最少有两个节点,一个是起始节点,一个是审批节点才行
if (ruleOrderList.size() < 2) {
throw new BusinessException("审批流节点数量不足,请联系管理员确认审批流节点是否正确");
}
return ruleOrderList;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void processKnowledgeFlow(ProcessFlowReqVO reqVO) {
// 首先获取这个审批任务
KnowledgeFlowTodo knowledgeFlowTodo = knowledgeFlowTodoService.getOptById(reqVO.getTodoId()).orElseThrow(() -> new BusinessException("审批任务不存在"));
// 找到发起节点
KnowledgeFlowRecord submitFlowRecord = knowledgeFlowRecordService.lambdaQuery().eq(KnowledgeFlowRecord::getFlowInstanceId, knowledgeFlowTodo.getFlowInstanceId())
.eq(KnowledgeFlowRecord::getType, 1).orderByDesc(KnowledgeFlowRecord::getCreateTime).last(" limit 1").oneOpt().orElse(new KnowledgeFlowRecord());
UserInfo user = UserUtil.getUser();
// 将这个任务对应的TODO删除掉
knowledgeFlowTodoService.lambdaUpdate().eq(KnowledgeFlowTodo::getFlowInstanceId, knowledgeFlowTodo.getFlowInstanceId()).remove();
// 然后获取下一个节点
List<SystemFlowRule> ruleOrderList = queryFlowRuleWithOrder(knowledgeFlowTodo.getFlowId());
// 从list中找到当前节点
SystemFlowRule currentRule = null;
// 然后根据order找到当前节点在ruleOrderList中的索引号(根据ID进行查找)
int index = 0;
for (int i = 0; i < ruleOrderList.size(); i++) {
SystemFlowRule rule = ruleOrderList.get(i);
if (rule.getId().equals(knowledgeFlowTodo.getRuleId())) {
index = i;
currentRule = rule;
}
}
if (ObjectUtils.isEmpty(currentRule)) {
throw new BusinessException("审批节点不存在");
}
if (1 == reqVO.getOperate()) {
// 如果当前节点的索引号和节点数量-1相等(因为索引从0开始),说明是最后一个节点,这时说明流程走完了
if ((ruleOrderList.size() - 1) == index) {
// 这时走流程结束的流程
KnowledgeFlowRecord newKnowledgeFlowRecord = KnowledgeFlowRecord.builder().type(2).knowledgeId(knowledgeFlowTodo.getKnowledgeId())
.flowId(knowledgeFlowTodo.getFlowId()).flowInstanceId(knowledgeFlowTodo.getFlowInstanceId())
.flowType(knowledgeFlowTodo.getFlowType()).flowRuleId(currentRule.getId()).flowRuleOrder(currentRule.getRuleOrder())
.processName("通过").processStatus(1).processUserId(user.getId())
.processDeptId(user.getDeptId()).processTime(LocalDateTime.now()).remark(reqVO.getRemark())
.submitUserId(submitFlowRecord.getSubmitUserId()).submitDeptId(submitFlowRecord.getSubmitDeptId())
.build();
knowledgeFlowRecordService.save(newKnowledgeFlowRecord);
// 将知识的状态进行修改(需要修改为对应的状态,看提交的是什么流程)
Integer flowType = knowledgeFlowTodo.getFlowType();
// 如果是知识报送,就置为通过
if (flowType.equals(FlowTypeEnum.SUBMIT.getFlowType())) {
// 如果是通过,就把报送时间设置为最后一次审批通过的时间
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.PASS.getStatus()).set(Knowledge::getSubmitDate, LocalDate.now()).set(Knowledge::getDraftBelongUserId, null)
.eq(Knowledge::getId, reqVO.getKnowledgeId()).update();
} else if (flowType.equals(FlowTypeEnum.RECALL.getFlowType())) {
// 如果是撤回,就置为草稿,并且草稿所属人应该是提交流程的人
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.DRAFT.getStatus()).set(Knowledge::getDraftBelongUserId, submitFlowRecord.getSubmitUserId())
.eq(Knowledge::getId, reqVO.getKnowledgeId()).update();
} else if (flowType.equals(FlowTypeEnum.DELETE.getFlowType())) {
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.DELETE.getStatus()).set(Knowledge::getDraftBelongUserId, null)
.eq(Knowledge::getId, reqVO.getKnowledgeId()).update();
} else {
throw new BusinessException("未知的流程类型");
}
} else {
SystemFlowRule nextRule;
try {
nextRule = ruleOrderList.get(index + 1);
} catch (IndexOutOfBoundsException e) {
throw new BusinessException("未找到下一个审批节点,请联系管理员解决");
}
List<SystemFlowRuleUser> nextRuleUserList = systemFlowRuleUserService.lambdaQuery().eq(SystemFlowRuleUser::getFlowId, nextRule.getFlowId())
.eq(SystemFlowRuleUser::getRuleId, nextRule.getId()).list();
if (CollUtil.isEmpty(nextRuleUserList)) {
throw new BusinessException("下级审批节点未配置审批用户,审批失败,请联系管理员解决");
}
// 保存这个节点的审批记录
KnowledgeFlowRecord newKnowledgeFlowRecord = KnowledgeFlowRecord.builder().type(2).knowledgeId(knowledgeFlowTodo.getKnowledgeId())
.flowId(knowledgeFlowTodo.getFlowId()).flowInstanceId(knowledgeFlowTodo.getFlowInstanceId())
.flowType(knowledgeFlowTodo.getFlowType()).flowRuleId(currentRule.getId()).flowRuleOrder(currentRule.getRuleOrder())
.processName("通过").processStatus(1).processUserId(user.getId())
.processDeptId(user.getDeptId()).processTime(LocalDateTime.now()).remark(reqVO.getRemark())
.submitUserId(submitFlowRecord.getSubmitUserId()).submitDeptId(submitFlowRecord.getSubmitDeptId())
.build();
knowledgeFlowRecordService.save(newKnowledgeFlowRecord);
// 生成下一个节点的TODO
for (SystemFlowRuleUser todoUser : nextRuleUserList) {
KnowledgeFlowTodo todo = new KnowledgeFlowTodo();
todo.setFlowId(nextRule.getFlowId());
todo.setKnowledgeId(knowledgeFlowTodo.getKnowledgeId());
todo.setFlowInstanceId(knowledgeFlowTodo.getFlowInstanceId());
todo.setTodoUserId(todoUser.getUserId());
todo.setSubmitUserId(submitFlowRecord.getSubmitUserId());
todo.setFlowType(knowledgeFlowTodo.getFlowType());
todo.setRuleId(nextRule.getId());
todo.insert();
}
}
}
// 驳回流程
else if (2 == reqVO.getOperate()) {
KnowledgeFlowRecord newKnowledgeFlowRecord = KnowledgeFlowRecord.builder().type(2)
.knowledgeId(knowledgeFlowTodo.getKnowledgeId())
.flowId(knowledgeFlowTodo.getFlowId())
.flowType(knowledgeFlowTodo.getFlowType())
.flowRuleId(currentRule.getId())
.flowInstanceId(knowledgeFlowTodo.getFlowInstanceId())
.flowRuleOrder(currentRule.getRuleOrder())
.processName("驳回")
.processStatus(2)
.processUserId(user.getId())
.processDeptId(user.getDeptId())
.processTime(LocalDateTime.now())
.remark(reqVO.getRemark())
.submitUserId(submitFlowRecord.getSubmitUserId())
.submitDeptId(submitFlowRecord.getSubmitDeptId()).build();
knowledgeFlowRecordService.save(newKnowledgeFlowRecord);
// 驳回,需要分辨驳回的状态是什么
if (knowledgeFlowTodo.getFlowType().equals(FlowTypeEnum.SUBMIT.getFlowType())) {
// 如果是知识报送,就置为驳回(审批)
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.RECALL_APPROVAL_SUBMIT.getStatus()).set(Knowledge::getDraftBelongUserId, knowledgeFlowTodo.getSubmitUserId())
.eq(Knowledge::getId, reqVO.getKnowledgeId()).update();
} else if (knowledgeFlowTodo.getFlowType().equals(FlowTypeEnum.RECALL.getFlowType())) {
// 如果是撤回,就置为驳回(撤回)
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.RECALL_APPROVAL_RECALL.getStatus()).set(Knowledge::getDraftBelongUserId, submitFlowRecord.getSubmitUserId())
.eq(Knowledge::getId, reqVO.getKnowledgeId()).update();
} else if (knowledgeFlowTodo.getFlowType().equals(FlowTypeEnum.DELETE.getFlowType())) {
// 如果是删除,就置为驳回(删除)
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.RECALL_APPROVAL_DELETE.getStatus()).set(Knowledge::getDraftBelongUserId, submitFlowRecord.getSubmitUserId())
.eq(Knowledge::getId, reqVO.getKnowledgeId()).update();
} else {
throw new BusinessException("未知的流程类型");
}
} else {
throw new BusinessException("暂不支持的审批类型");
}
}
@Override
public List<KnowledgeFlowRecordResVO> queryKnowledgeFlowRecord(String knowledgeId, String flowInstanceId) {
List<KnowledgeFlowRecord> list = knowledgeFlowRecordService.lambdaQuery().eq(KnowledgeFlowRecord::getKnowledgeId, knowledgeId)
.eq(StrUtil.isNotBlank(flowInstanceId), KnowledgeFlowRecord::getFlowInstanceId, flowInstanceId).list();
// 根据时间进行排序
List<KnowledgeFlowRecordResVO> result = list.stream().map(knowledgeFlowRecord -> {
KnowledgeFlowRecordResVO node = new KnowledgeFlowRecordResVO();
node.setKnowledgeId(knowledgeFlowRecord.getKnowledgeId());
node.setProcessName(knowledgeFlowRecord.getProcessName());
node.setRemark(knowledgeFlowRecord.getRemark());
node.setProcessOrder(knowledgeFlowRecord.getFlowRuleOrder());
// 判断是不是发起的,如果是发起的,那么process的是发起人.否则是审批人
if (1 == knowledgeFlowRecord.getType()) {
node.setProcessTime(knowledgeFlowRecord.getCreateTime());
node.setProcessUserId(knowledgeFlowRecord.getSubmitUserId());
node.setProcessDeptId(knowledgeFlowRecord.getSubmitDeptId());
} else {
node.setProcessTime(knowledgeFlowRecord.getProcessTime());
node.setProcessUserId(knowledgeFlowRecord.getProcessUserId());
node.setProcessDeptId(knowledgeFlowRecord.getProcessDeptId());
}
return node;
}).sorted(Comparator.comparing(KnowledgeFlowRecordResVO::getProcessTime).reversed()).toList();
// 然后把人名和部门名进行转换
Set<String> userIdSet = result.stream().map(KnowledgeFlowRecordResVO::getProcessUserId).collect(Collectors.toSet());
List<SystemUser> systemUsers = new ArrayList<>();
if (CollUtil.isNotEmpty(userIdSet)) {
systemUsers = systemUserService.listByIds(userIdSet);
}
Map<String, String> userNameMap = systemUsers.stream().collect(Collectors.toMap(SystemUser::getId, SystemUser::getUsername));
Set<String> deptIdSet = result.stream().map(KnowledgeFlowRecordResVO::getProcessDeptId).collect(Collectors.toSet());
List<SystemDept> systemDeptList = new ArrayList<>();
if (CollUtil.isNotEmpty(deptIdSet)) {
systemDeptList = systemDeptService.listByIds(deptIdSet);
}
Map<String, String> deptNameMap = systemDeptList.stream().collect(Collectors.toMap(SystemDept::getId, SystemDept::getDeptName));
result.forEach(node -> {
node.setProcessUserName(userNameMap.getOrDefault(node.getProcessUserId(), "未知用户"));
node.setProcessDeptName(deptNameMap.getOrDefault(node.getProcessDeptId(), "未知部门"));
});
return result;
}
}

@ -0,0 +1,429 @@
package com.supervision.knowsub.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.knowsub.domain.UserInfo;
import com.supervision.knowsub.dto.base.UserBaseOperateAuthDTO;
import com.supervision.knowsub.entity.vo.knowledge.*;
import com.supervision.knowsub.enums.FlowTypeEnum;
import com.supervision.knowsub.enums.StatusEnum;
import com.supervision.knowsub.exception.BusinessException;
import com.supervision.knowsub.model.*;
import com.supervision.knowsub.service.*;
import com.supervision.knowsub.util.UserUtil;
import com.supervision.knowsub.vo.knowledge.KnowledgePageResVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class KnowledgeManageServiceImpl implements KnowledgeManageService {
private final KnowledgeService knowledgeService;
private final KnowledgeContextService knowledgeContextService;
private final KnowledgeInfoService knowledgeInfoService;
private final KnowledgeAttachmentService knowledgeAttachmentService;
private final KnowledgeLinkService knowledgeLinkService;
private final KnowledgeFlowRecordService flowRecordService;
private final FileService fileService;
private final KnowledgeFlowService knowledgeFlowService;
private final SystemDeptService systemDeptService;
private final SystemBaseService systemBaseService;
@Override
public IPage<KnowledgePageResVO> queryKnowledgePage(Integer status,
String title,
String publishDeptId,
String baseId,
String submitDeptId,
LocalDate publishDateBegin,
LocalDate publishDateEnd, LocalDate submitDateBegin,
LocalDate submitDateEnd, Integer pageNum, Integer pageSize) {
String userId = UserUtil.getUser().getId();
// 除全部可以看所有外,其他tab都是看到自己报送的知识的状态(或参与过的)
IPage<KnowledgePageResVO> knowledgeIPage = knowledgeService.queryKnowledgePage(status, title, publishDeptId, baseId, submitDeptId, publishDateBegin, publishDateEnd, submitDateBegin, submitDateEnd, userId, pageNum, pageSize);
List<KnowledgePageResVO> records = knowledgeIPage.getRecords();
if (CollUtil.isEmpty(records)) {
return knowledgeIPage;
}
// 获取所有部门
Set<String> submitDeptSet = records.stream().map(Knowledge::getSubmitDeptId).collect(Collectors.toSet());
Set<String> publishDeptSet = records.stream().map(Knowledge::getPublishDeptId).collect(Collectors.toSet());
Collection<String> deptIdSet = CollUtil.union(submitDeptSet, publishDeptSet);
Map<String, String> deptMap = systemDeptService.listByIds(deptIdSet).stream().collect(Collectors.toMap(SystemDept::getId, SystemDept::getDeptName));
// 获取所有子库
Set<String> baseIdSet = records.stream().map(Knowledge::getBaseId).collect(Collectors.toSet());
Map<String, String> baseMap = systemBaseService.listByIds(baseIdSet).stream().collect(Collectors.toMap(SystemBase::getId, SystemBase::getBaseName));
List<KnowledgePageResVO> list = records.stream().map(knowledge -> {
KnowledgePageResVO node = BeanUtil.copyProperties(knowledge, KnowledgePageResVO.class);
node.setBaseName(baseMap.getOrDefault(knowledge.getBaseId(), "全部"));
node.setSubmitDeptName(deptMap.getOrDefault(knowledge.getSubmitDeptId(), "未知部门"));
node.setPublishDeptName(deptMap.getOrDefault(knowledge.getPublishDeptId(), "未知部门"));
return node;
}).toList();
// 进行只是的标记操作
markKnowledgeOperationFlag(list);
// status是查全部,则在页面展示的时候,需要把16,17进行转换
if (ObjectUtil.isNull(status)) {
for (KnowledgePageResVO knowledgePageResVO : list) {
// 如果状态是16,17,则在页面展示的时候,展示为通过
if (Objects.equals(knowledgePageResVO.getStatus(), StatusEnum.RECALL_APPROVAL_RECALL.getStatus())
|| Objects.equals(knowledgePageResVO.getStatus(), StatusEnum.RECALL_APPROVAL_DELETE.getStatus())) {
knowledgePageResVO.setStatus(StatusEnum.PASS.getStatus());
}
}
}
knowledgeIPage.setRecords(list);
return knowledgeIPage;
}
/**
*
*/
private void markKnowledgeOperationFlag(List<KnowledgePageResVO> list) {
// 获取用户所有子库的操作权限
UserInfo user = UserUtil.getUser();
List<UserBaseOperateAuthDTO> baseOperateAuthDTOList = systemBaseService.queryUserBaseOperateAuth(user.getId());
Map<String, Set<Integer>> baseOperateAuthMap = baseOperateAuthDTOList.stream()
.collect(Collectors.groupingBy(UserBaseOperateAuthDTO::getBaseId, Collectors.mapping(UserBaseOperateAuthDTO::getFlowType, Collectors.toSet())));
// 首先需要看用户对这个子库的权限是什么,如果用户有该子库的对应的操作权限,则允许进行对应操作
for (KnowledgePageResVO knowledgePageResVO : list) {
String baseId = knowledgePageResVO.getBaseId();
if (StatusEnum.DRAFT.getStatus().equals(knowledgePageResVO.getStatus())) {
// 如果是草稿,就只允许编辑和删除
knowledgePageResVO.setModifyFlag(1);
knowledgePageResVO.setDeleteFlag(1);
} else if (StatusEnum.PASS.getStatus().equals(knowledgePageResVO.getStatus())) {
// 如果是已发布,就只允许撤回.需要有该子库权限
if (baseOperateAuthMap.containsKey(baseId) && baseOperateAuthMap.get(baseId).contains(FlowTypeEnum.RECALL.getFlowType())) {
knowledgePageResVO.setRecallFlag(1);
}
// 已发布的,也可以直接删除,但是也要校验权限
if (baseOperateAuthMap.containsKey(baseId) && baseOperateAuthMap.get(baseId).contains(FlowTypeEnum.DELETE.getFlowType())) {
knowledgePageResVO.setDeleteFlag(1);
}
} else if (StatusEnum.RECALL_APPROVAL_SUBMIT.getStatus().equals(knowledgePageResVO.getStatus())) {
// 如果是新增驳回,就可以支持编辑和删除,但是需要校验是否需要有权限
if (baseOperateAuthMap.containsKey(baseId) && baseOperateAuthMap.get(baseId).contains(FlowTypeEnum.SUBMIT.getFlowType())) {
knowledgePageResVO.setModifyFlag(1);
}
if (baseOperateAuthMap.containsKey(baseId) && baseOperateAuthMap.get(baseId).contains(FlowTypeEnum.DELETE.getFlowType())) {
knowledgePageResVO.setDeleteFlag(1);
}
} else if (StatusEnum.RECALL_APPROVAL_DELETE.getStatus().equals(knowledgePageResVO.getStatus())
|| StatusEnum.RECALL_APPROVAL_RECALL.getStatus().equals(knowledgePageResVO.getStatus())) {
// 如果是删除驳回和撤回驳回,就可以继续支持撤回和删除流程,但是需要校验是否需要有权限
if (baseOperateAuthMap.containsKey(baseId) && baseOperateAuthMap.get(baseId).contains(FlowTypeEnum.SUBMIT.getFlowType())) {
knowledgePageResVO.setRecallFlag(1);
}
if (baseOperateAuthMap.containsKey(baseId) && baseOperateAuthMap.get(baseId).contains(FlowTypeEnum.DELETE.getFlowType())) {
knowledgePageResVO.setDeleteFlag(1);
}
} else if (StatusEnum.INVALID.getStatus().equals(knowledgePageResVO.getStatus())) {
// 如果是已失效,支持编辑撤回删除,但是需要校验是否有对应的权限
if (baseOperateAuthMap.containsKey(baseId) && baseOperateAuthMap.get(baseId).contains(FlowTypeEnum.SUBMIT.getFlowType())) {
knowledgePageResVO.setModifyFlag(1);
}
if (baseOperateAuthMap.containsKey(baseId) && baseOperateAuthMap.get(baseId).contains(FlowTypeEnum.RECALL.getFlowType())) {
knowledgePageResVO.setRecallFlag(1);
}
if (baseOperateAuthMap.containsKey(baseId) && baseOperateAuthMap.get(baseId).contains(FlowTypeEnum.DELETE.getFlowType())) {
knowledgePageResVO.setDeleteFlag(1);
}
}
// 其他状态就全部置灰
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveKnowledge(SaveKnowledgeReqVO reqVO) {
if (2 == reqVO.getOperate()) {
Assert.notBlank(reqVO.getBaseId(), "应用子库不能为空");
KnowledgeInfo knowledgeInfo = reqVO.getKnowledgeInfo();
Assert.notNull(knowledgeInfo, "有效日期不能为空");
Assert.notBlank(reqVO.getPublishDeptId(), "发文部门不能为空");
Assert.notNull(knowledgeInfo.getPublishDate(), "发文时间不能为空");
Assert.notNull(knowledgeInfo.getTimeliness(), "有效日期不能为空");
}
var context = new KnowledgeContext();
context.setContext(reqVO.getContent());
knowledgeContextService.save(context);
// 保存基本信息
KnowledgeInfo baseInfo = Optional.ofNullable(reqVO.getKnowledgeInfo()).orElse(new KnowledgeInfo());
baseInfo.setContextId(context.getId());
knowledgeInfoService.save(baseInfo);
Knowledge knowledge = new Knowledge();
knowledge.setTitle(reqVO.getTitle());
knowledge.setContentId(context.getId());
knowledge.setInfoId(baseInfo.getId());
knowledge.setBaseId(reqVO.getBaseId());
knowledge.setPublishDeptId(reqVO.getPublishDeptId());
knowledge.setExcerpt(reqVO.getExcerpt());
// 目前只有人工添加
knowledge.setKnowledgeFrom(1);
knowledge.setStatus(reqVO.getOperate() == 1 ? StatusEnum.DRAFT.getStatus() : StatusEnum.WAIT_APPROVAL.getStatus());
knowledge.setSubmitDeptId(UserUtil.getUser().getDeptId());
if (1 == reqVO.getOperate()) {
knowledge.setDraftBelongUserId(UserUtil.getUser().getId());
}
knowledgeService.save(knowledge);
// 保存知识的基本信息
// 附件以及URL没添加
for (String fileId : reqVO.getFileIdList()) {
KnowledgeAttachment attachment = new KnowledgeAttachment();
attachment.setKnowledgeId(knowledge.getId());
attachment.setFileId(fileId);
knowledgeAttachmentService.save(attachment);
}
for (KnowledgeLinkVO knowLedgeLinkVO : reqVO.getLinkList()) {
KnowledgeLink knowledgeLink = new KnowledgeLink();
knowledgeLink.setKnowledgeId(knowledge.getId());
knowledgeLink.setLinkName(knowLedgeLinkVO.getLinkName());
knowledgeLink.setLinkUrl(knowLedgeLinkVO.getLinkUrl());
knowledgeLinkService.save(knowledgeLink);
}
// 这里需要进行判断,如果状态为2,说明要走流程
if (1 != reqVO.getOperate()) {
// 这里需要走流程
UserInfo user = UserUtil.getUser();
knowledgeFlowService.submitFlowProcess(knowledge, FlowTypeEnum.SUBMIT, user.getId(), user.getDeptId(), reqVO.getRemark());
// 如果提交了审批,就把草稿所属人置为空
knowledgeService.lambdaUpdate().set(Knowledge::getDraftBelongUserId, null).eq(Knowledge::getId, knowledge.getId()).update();
}
}
/**
* @param reqVO
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void updateKnowledge(ModifyKnowledgeReqVO reqVO) {
if (2 == reqVO.getOperate()) {
Assert.notBlank(reqVO.getBaseId(), "应用子库不能为空");
KnowledgeInfo knowledgeInfo = reqVO.getKnowledgeInfo();
Assert.notNull(knowledgeInfo, "有效日期不能为空");
Assert.notBlank(reqVO.getPublishDeptId(), "发文部门不能为空");
Assert.notNull(knowledgeInfo.getPublishDate(), "发文时间不能为空");
Assert.notNull(knowledgeInfo.getTimeliness(), "有效日期不能为空");
}
Knowledge knowledge = knowledgeService.getOptById(reqVO.getKnowledgeId()).orElseThrow(() -> new BusinessException("未找到知识"));
// 首先校验状态,草稿/已撤回/已失效/驳回,才能修改(通过的,要先撤回才能修改)
Set<Integer> canModifyStatusSet = Set.of(StatusEnum.DRAFT.getStatus(), StatusEnum.RECALL.getStatus(), StatusEnum.INVALID.getStatus(), StatusEnum.RECALL_APPROVAL_SUBMIT.getStatus());
if (!canModifyStatusSet.contains(knowledge.getStatus())) {
throw new BusinessException("当前状态不支持修改");
}
// 找到对应的content
KnowledgeContext context = knowledgeContextService.getOptById(knowledge.getContentId()).orElse(KnowledgeContext.builder().id(reqVO.getKnowledgeId()).build());
context.setContext(reqVO.getContent());
context.updateById();
// 然后更新
knowledge.setTitle(reqVO.getTitle());
knowledge.setExcerpt(reqVO.getExcerpt());
knowledge.setBaseId(reqVO.getBaseId());
knowledge.setPublishDeptId(reqVO.getPublishDeptId());
knowledge.setSubmitDeptId(UserUtil.getUser().getDeptId());
knowledge.setStatus(reqVO.getOperate() == 1 ? StatusEnum.DRAFT.getStatus() : StatusEnum.WAIT_APPROVAL.getStatus());
// 如果保存为草稿
if (1 == reqVO.getOperate()) {
knowledge.setDraftBelongUserId(UserUtil.getUser().getId());
}
knowledgeService.updateById(knowledge);
// 更新基础信息
KnowledgeInfo knowledgeInfo = reqVO.getKnowledgeInfo();
// 这里需要用SQL进行更新,不能用封装的updateById,因为前端某些字段可能变为空,用updateById不能让那个想为空的变成空
knowledgeInfoService.lambdaUpdate()
.set(KnowledgeInfo::getPolicyType, knowledgeInfo.getPolicyType())
.set(KnowledgeInfo::getTerritory, knowledgeInfo.getTerritory())
.set(KnowledgeInfo::getPublishScope, knowledgeInfo.getPublishScope())
.set(KnowledgeInfo::getKnowledgeTag, knowledgeInfo.getKnowledgeTag())
.set(KnowledgeInfo::getExecTimeBegin, knowledgeInfo.getExecTimeBegin())
.set(KnowledgeInfo::getExecTimeEnd, knowledgeInfo.getExecTimeEnd())
.set(KnowledgeInfo::getTimeliness, knowledgeInfo.getTimeliness())
.set(KnowledgeInfo::getPublishDate, knowledgeInfo.getPublishDate())
.eq(KnowledgeInfo::getId, knowledgeInfo.getId()).update();
// 有可能更新附件
updateKnowledgeFile(reqVO, knowledge);
// 有可能更新URL
updateKnowledgeLink(reqVO, knowledge);
// 这里需要进行判断,如果状态为2,说明要走流程
if (1 != reqVO.getOperate()) {
UserInfo user = UserUtil.getUser();
knowledgeFlowService.submitFlowProcess(knowledge, FlowTypeEnum.SUBMIT, user.getId(), user.getDeptId(), reqVO.getRemark());
// 将状态修改问待审批
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.WAIT_APPROVAL.getStatus()).eq(Knowledge::getId, knowledge.getId()).update();
// 如果提交了审批,就把草稿所属人置为空
knowledgeService.lambdaUpdate().set(Knowledge::getDraftBelongUserId, null).eq(Knowledge::getId, knowledge.getId()).update();
}
}
private void updateKnowledgeLink(ModifyKnowledgeReqVO reqVO, Knowledge knowledge) {
// 直接删除原来的
knowledgeLinkService.lambdaUpdate().eq(KnowledgeLink::getKnowledgeId, knowledge.getId()).remove();
for (KnowledgeLinkVO knowLedgeLinkVO : reqVO.getLinkList()) {
KnowledgeLink knowledgeLink = new KnowledgeLink();
knowledgeLink.setKnowledgeId(knowledge.getId());
knowledgeLink.setLinkName(knowLedgeLinkVO.getLinkName());
knowledgeLink.setLinkUrl(knowLedgeLinkVO.getLinkUrl());
knowledgeLinkService.save(knowledgeLink);
}
}
private void updateKnowledgeFile(ModifyKnowledgeReqVO reqVO, Knowledge knowledge) {
// 获取数据库中的附件ID
List<KnowledgeAttachment> oldFileList = knowledgeAttachmentService.lambdaQuery().eq(KnowledgeAttachment::getKnowledgeId, knowledge.getId()).list();
if (CollUtil.isEmpty(reqVO.getFileIdList())) {
if (CollUtil.isNotEmpty(oldFileList)) {
knowledgeAttachmentService.lambdaUpdate().eq(KnowledgeAttachment::getKnowledgeId, knowledge.getId()).remove();
// 删除文件
for (KnowledgeAttachment knowledgeAttachment : oldFileList) {
fileService.deleteFileById(knowledgeAttachment.getFileId());
}
}
} else {
List<String> newFileIdList = reqVO.getFileIdList();
// 遍历旧的附件,如果新的附件列表中不包含,则删除
for (KnowledgeAttachment oldFile : oldFileList) {
if (!newFileIdList.contains(oldFile.getId())) {
knowledgeAttachmentService.lambdaUpdate().eq(KnowledgeAttachment::getFileId, oldFile.getId()).remove();
fileService.deleteFileById(oldFile.getFileId());
}
}
List<String> oldFileIdList = oldFileList.stream().map(KnowledgeAttachment::getFileId).toList();
// 再添加新的附件
for (String fileId : reqVO.getFileIdList()) {
if (!oldFileIdList.contains(fileId)) {
KnowledgeAttachment attachment = new KnowledgeAttachment();
attachment.setKnowledgeId(knowledge.getId());
attachment.setFileId(fileId);
knowledgeAttachmentService.save(attachment);
}
}
}
}
@Override
public void recallKnowledge(String knowledgeId, String remark) {
Knowledge knowledge = knowledgeService.getOptById(knowledgeId).orElseThrow(() -> new BusinessException("未找到知识"));
// 只有通过状态或已失效状态才支持撤回
Set<Integer> canRecallStatusSet = Set.of(StatusEnum.PASS.getStatus(), StatusEnum.INVALID.getStatus());
if (!canRecallStatusSet.contains(knowledge.getStatus())) {
throw new BusinessException("该知识状态不能撤回");
}
// 走撤回流程
UserInfo user = UserUtil.getUser();
knowledgeFlowService.submitFlowProcess(knowledge, FlowTypeEnum.RECALL, user.getId(), user.getDeptId(), remark);
// 然后将状态修改问带审核
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.WAIT_APPROVAL_RECALL.getStatus()).eq(Knowledge::getId, knowledge.getId()).update();
}
@Override
public KnowledgeDetailResVO queryKnowledgeDetail(String knowledgeId) {
Knowledge knowledge = knowledgeService.getOptById(knowledgeId).orElseThrow(() -> new BusinessException("未找到知识"));
KnowledgeInfo knowledgeInfo = knowledgeInfoService.getOptById(knowledge.getInfoId()).orElse(new KnowledgeInfo());
KnowledgeContext knowledgeContext = knowledgeContextService.getOptById(knowledge.getContentId()).orElse(new KnowledgeContext());
List<KnowledgeLink> knowledgeLinkList = knowledgeLinkService.lambdaQuery().eq(KnowledgeLink::getKnowledgeId, knowledgeId).list();
List<KnowledgeAttachment> knowledgeAttachmentList = knowledgeAttachmentService.lambdaQuery().eq(KnowledgeAttachment::getKnowledgeId, knowledgeId).list();
List<String> fileIdList = knowledgeAttachmentList.stream().map(KnowledgeAttachment::getFileId).toList();
List<FileInfo> fileInfos = fileService.listByFileId(fileIdList);
// 查看详情的时候,需要返回相应的库名和部门名称
KnowledgeDetailResVO knowledgeDetailResVO = new KnowledgeDetailResVO(knowledge, knowledgeInfo, knowledgeContext, knowledgeLinkList, fileInfos);
knowledgeDetailResVO.setBaseName(systemBaseService.getOptById(knowledge.getBaseId()).map(SystemBase::getBaseName).orElse("未知子库"));
knowledgeDetailResVO.setSubmittedDeptName(systemDeptService.getOptById(knowledge.getSubmitDeptId()).map(SystemDept::getDeptName).orElse("未知部门"));
knowledgeDetailResVO.setPublishDept(systemDeptService.getOptById(knowledge.getPublishDeptId()).map(SystemDept::getDeptName).orElse("未知部门"));
return knowledgeDetailResVO;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteKnowledge(String knowledgeId, String remark) {
// 删除是逻辑删除,如果当前状态是草稿,且没有走过审批流程,则可以直接删除
Knowledge knowledge = knowledgeService.getOptById(knowledgeId).orElseThrow(() -> new BusinessException("未找到知识"));
// 如果非草稿,则校验是否是通过/驳回/已撤回/已失效状态,如果是,则需要走审批流程进行删除
Set<Integer> canDeleteStatusSet = Set.of(StatusEnum.PASS.getStatus(), StatusEnum.RECALL_APPROVAL_RECALL.getStatus(), StatusEnum.RECALL_APPROVAL_DELETE.getStatus(), StatusEnum.INVALID.getStatus());
// 如果是审批草稿,需要进行判断之前是否有过记录
if (Objects.equals(StatusEnum.DRAFT.getStatus(), knowledge.getStatus())) {
// 需要判断之前是否走过审批流程
if (flowRecordService.lambdaQuery().eq(KnowledgeFlowRecord::getKnowledgeId, knowledgeId).count() == 0) {
// 如果没有走过审批的记录,则可以直接删除
knowledgeService.removeById(knowledgeId);
knowledgeInfoService.removeById(knowledge.getInfoId());
knowledgeContextService.lambdaUpdate().eq(KnowledgeContext::getId, knowledge.getContentId()).remove();
// 删除文件
List<KnowledgeAttachment> list = knowledgeAttachmentService.lambdaQuery().eq(KnowledgeAttachment::getKnowledgeId, knowledgeId).list();
List<String> fileIdList = list.stream().map(KnowledgeAttachment::getFileId).toList();
fileService.listByFileId(fileIdList);
knowledgeAttachmentService.lambdaUpdate().eq(KnowledgeAttachment::getKnowledgeId, knowledgeId).remove();
} else {
// 如果有过审批记录,则直接修改状态为逻辑删除
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.DELETE.getStatus())
.set(Knowledge::getDraftBelongUserId, null)
.eq(Knowledge::getId, knowledge.getId()).update();
}
} else if (Objects.equals(StatusEnum.RECALL_APPROVAL_SUBMIT.getStatus(), knowledge.getStatus())) {
// 如果是新增驳回的,需要判断除了本次驳回的,是否有被审批通过过,如果有被报送且审批通过过,就要走流程进行删除
if (flowRecordService.lambdaQuery().eq(KnowledgeFlowRecord::getKnowledgeId, knowledgeId).eq(KnowledgeFlowRecord::getFlowType, FlowTypeEnum.SUBMIT.getFlowType()).eq(KnowledgeFlowRecord::getProcessStatus, 1).count() > 0) {
// 如果有,则走流程进行删除
// 这时需要走审批流程进行删除
UserInfo user = UserUtil.getUser();
knowledgeFlowService.submitFlowProcess(knowledge, FlowTypeEnum.DELETE, user.getId(), user.getDeptId(), remark);
// 然后将状态修改为待审核
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.WAIT_APPROVAL_DELETE.getStatus()).eq(Knowledge::getId, knowledge.getId()).update();
}else {
// 如果有过审批记录,则直接修改状态为逻辑删除
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.DELETE.getStatus())
.set(Knowledge::getDraftBelongUserId, null)
.eq(Knowledge::getId, knowledge.getId()).update();
}
} else if (canDeleteStatusSet.contains(knowledge.getStatus())) {
// 这时需要走审批流程进行删除
UserInfo user = UserUtil.getUser();
knowledgeFlowService.submitFlowProcess(knowledge, FlowTypeEnum.DELETE, user.getId(), user.getDeptId(), remark);
// 然后将状态修改为待审核
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.WAIT_APPROVAL_DELETE.getStatus()).eq(Knowledge::getId, knowledge.getId()).update();
} else {
throw new BusinessException("审批中的知识不支持删除");
}
}
}

@ -0,0 +1,70 @@
package com.supervision.knowsub.service.impl;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.supervision.knowsub.model.SystemRole;
import com.supervision.knowsub.service.RoleManageService;
import com.supervision.knowsub.service.SystemRoleService;
import com.supervision.knowsub.vo.role.RoleReqVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class RoleManageServiceImpl implements RoleManageService {
private final SystemRoleService systemRoleService;
@Override
public String saveRole(RoleReqVo roleReqVo) {
Assert.notEmpty(roleReqVo.getRoleName(), "角色名称不能为空");
Long count = systemRoleService.lambdaQuery().eq(SystemRole::getRoleName, roleReqVo.getRoleName()).count();
Assert.isTrue(count == 0, "角色名称已存在");
// 保存角色
SystemRole systemRole = new SystemRole();
systemRole.setRoleName(roleReqVo.getRoleName());
systemRole.setRemark(roleReqVo.getMark());
systemRole.setRoleType(null == roleReqVo.getManage() ? 0 : roleReqVo.getManage());
systemRoleService.save(systemRole);
return systemRole.getId();
}
@Override
public void updateRole(RoleReqVo roleReqVo) {
Assert.notEmpty(roleReqVo.getId(), "角色id不能为空");
Assert.notEmpty(roleReqVo.getRoleName(), "角色名称不能为空");
SystemRole dbSystemRole = systemRoleService.getById(roleReqVo.getId());
Assert.notNull(dbSystemRole, "角色不存在");
if (!StrUtil.equals(dbSystemRole.getRoleName(), roleReqVo.getRoleName())){
Long count = systemRoleService.lambdaQuery().eq(SystemRole::getRoleName, roleReqVo.getRoleName()).count();
Assert.isTrue(count == 0, "角色名称已存在");
}
dbSystemRole.setRoleName(roleReqVo.getRoleName());
dbSystemRole.setRemark(roleReqVo.getMark());
dbSystemRole.setRoleType(null == roleReqVo.getManage() ? 0 : roleReqVo.getManage());
systemRoleService.updateById(dbSystemRole);
}
@Override
public Boolean deleteRole(String id) {
Assert.notEmpty(id, "角色id不能为空");
return systemRoleService.removeById(id);
}
@Override
public IPage<SystemRole> list(String roleName, Integer pageNum, Integer pageSize) {
return systemRoleService.lambdaQuery().like(StrUtil.isNotEmpty(roleName), SystemRole::getRoleName, roleName)
.orderBy(true,false ,SystemRole::getUpdateTime).page(new Page<>(pageNum, pageSize));
}
}

@ -0,0 +1,214 @@
package com.supervision.knowsub.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.supervision.knowsub.domain.UserInfo;
import com.supervision.knowsub.dto.role.UserRoleDTO;
import com.supervision.knowsub.dto.user.UserPageQuery;
import com.supervision.knowsub.exception.BusinessException;
import com.supervision.knowsub.model.SystemDept;
import com.supervision.knowsub.model.SystemUser;
import com.supervision.knowsub.service.SystemDeptService;
import com.supervision.knowsub.service.UserManageService;
import com.supervision.knowsub.service.UserRoleRelationManageService;
import com.supervision.knowsub.util.TokenUtil;
import com.supervision.knowsub.util.UserUtil;
import com.supervision.knowsub.vo.user.*;
import com.supervision.knowsub.dto.user.UserInfoDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class UserManageServiceImpl implements UserManageService {
@Value("${user.default.password}")
private String defaultPassword;
private final SystemUserServiceImpl systemUserService;
private final UserRoleRelationManageService userRoleRelationManageService;
private final SystemDeptService systemDeptService;
@Override
@Transactional(rollbackFor = Exception.class)
public LoginResVO login(LoginReqVO reqVO) {
Optional<SystemUser> user = systemUserService.lambdaQuery().eq(SystemUser::getAccount, reqVO.getUserAccount()).last("limit 1").oneOpt();
if (user.isEmpty() || !UserUtil.checkUserPassword(reqVO.getPassword(), user.get().getUserPd())) {
throw new BusinessException("用户名或密码有误!");
}
if (user.get().getStatus() == 1){
throw new BusinessException("该用户已被停用,请联系管理员!");
}
LoginResVO loginResVO = BeanUtil.toBean(user.get(), LoginResVO.class);
loginResVO.setUsername(user.get().getUsername());
List<UserRoleDTO> userRoleDTOS = userRoleRelationManageService.listUserRole(user.get().getId(),null,null);
loginResVO.setUserRoleDTOList(userRoleDTOS);
// 获取用户的部门
Optional<SystemDept> optById = systemDeptService.getOptById(user.get().getDeptId());
loginResVO.setDeptName(optById.isPresent() ? optById.get().getDeptName() : "未知部门");
UserInfo userInfoToken = BeanUtil.copyProperties(user.get(), UserInfo.class);
userInfoToken.setRoleTypeList(userRoleDTOS.stream().map(UserRoleDTO::getRoleType).distinct().toList());
// 更新用户最近的登录时间
systemUserService.lambdaUpdate().set(SystemUser::getRecentLoginTime, LocalDateTime.now()).eq(SystemUser::getId, user.get().getId()).update();
String token = TokenUtil.creatToken(JSONUtil.toJsonStr(userInfoToken));
loginResVO.setToken(token);
return loginResVO;
}
@Override
public UserInfoDTO getUserAccountInfo() {
UserInfo user = UserUtil.getUser();
SystemUser systemUser = systemUserService.getById(user.getId());
if (ObjectUtil.isEmpty(systemUser)){
throw new BusinessException("用户信息不存在");
}
return BeanUtil.toBean(systemUser, UserInfoDTO.class);
}
@Override
public List<SystemUser> listUserByDeptId(String deptId,Integer status) {
Assert.notEmpty(deptId,"部门id不能为空");
return systemUserService.lambdaQuery().eq(SystemUser::getDeptId,deptId).
eq(ObjUtil.isNull(status),SystemUser::getStatus,status).list();
}
@Override
public Long countUserByDeptId(String deptId,Integer status) {
Assert.notEmpty(deptId,"部门id不能为空");
return systemUserService.lambdaQuery().eq(SystemUser::getDeptId,deptId)
.eq(ObjUtil.isNull(status),SystemUser::getStatus,status).count();
}
@Override
@Transactional(rollbackFor = Exception.class)
public String saveUserInfo(UserInfoReqVo userInfoReqVo) {
Assert.notEmpty(userInfoReqVo.getAccount(), "用户名不能为空");
Assert.notEmpty(userInfoReqVo.getUsername(), "姓名不能为空");
Assert.notEmpty(userInfoReqVo.getDeptId(), "部门不能为空");
Assert.notEmpty(userInfoReqVo.getRoleIds(), "角色不能为空");
Long count = systemUserService.lambdaQuery().eq(SystemUser::getAccount, userInfoReqVo.getAccount()).count();
Assert.isTrue(count == 0, "用户名已存在");
SystemUser systemUser = BeanUtil.toBean(userInfoReqVo, SystemUser.class);
// 设置默认密码
systemUser.setUserPd(UserUtil.signPassword(defaultPassword));
systemUser.setStatus(0);
systemUserService.save(systemUser);
userRoleRelationManageService.saveUserRoleRelation(systemUser.getId(), userInfoReqVo.getRoleIds());
return systemUser.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateUserInfo(UserInfoReqVo userInfoReqVo) {
Assert.notEmpty(userInfoReqVo.getId(), "用户id不能为空");
Assert.notEmpty(userInfoReqVo.getAccount(), "用户名不能为空");
Assert.notEmpty(userInfoReqVo.getUsername(), "姓名不能为空");
Assert.notEmpty(userInfoReqVo.getDeptId(), "部门不能为空");
Assert.notEmpty(userInfoReqVo.getRoleIds(), "角色不能为空");
Long count = systemUserService.lambdaQuery()
.eq(SystemUser::getAccount, userInfoReqVo.getAccount())
.ne(SystemUser::getId, userInfoReqVo.getId()).count();
Assert.isTrue(count == 0, "用户名已存在,请更改用户名");
systemUserService.lambdaUpdate()
.set(SystemUser::getUsername, userInfoReqVo.getUsername())
.set(SystemUser::getAccount, userInfoReqVo.getAccount())
.set(SystemUser::getDeptId, userInfoReqVo.getDeptId())
.set(SystemUser::getRemark, userInfoReqVo.getRemark())
.set(SystemUser::getHeadPicId, userInfoReqVo.getHeadPicId())
.eq(SystemUser::getId, userInfoReqVo.getId())
.update();
userRoleRelationManageService.updateUserRoleRelation(userInfoReqVo.getId(), userInfoReqVo.getRoleIds());
}
@Override
public Boolean deleteUser(String id) {
Assert.notEmpty(id, "用户id不能为空");
SystemUser systemUser = systemUserService.getById(id);
Assert.notNull(systemUser, "用户不存在");
Assert.isFalse(systemUser.getStatus() == 0, "该用户已启用,不能删除");
systemUserService.removeById(id);
userRoleRelationManageService.deleteUserRoleRelation(id);
return true;
}
@Override
public IPage<UserInfoDTO> list(String userName, String deptId, String roleId,String roleName, Integer pageNum, Integer pageSize) {
List<UserRoleDTO> userRoleDTOS = new ArrayList<>();
if (StrUtil.isNotEmpty(roleId) || StrUtil.isNotEmpty(roleName)){
userRoleDTOS = userRoleRelationManageService.listUserRole(null, roleId, roleName);
if (CollUtil.isEmpty(userRoleDTOS)){
return Page.of(pageNum, pageSize, 0);
}
}
//构建查询条件
UserPageQuery userPageQuery = UserPageQuery.builder().userName(userName).deptId(deptId)
.excludeUserIdList(userRoleDTOS.stream().map(UserRoleDTO::getUserId).toList()).build();
IPage<UserInfoDTO> userInfoPage = systemUserService.pageList(userPageQuery, pageNum, pageSize);
if (CollUtil.isEmpty(userInfoPage.getRecords())){
return userInfoPage;
}
// 填充用户角色
List<UserRoleDTO> userRoleDTOList = userRoleRelationManageService.listUserRoleByUserIds(
userInfoPage.getRecords().stream().map(UserInfoDTO::getId).toList());
Map<String, List<UserRoleDTO>> userIdMapUserRoleDTo = userRoleDTOList.stream().collect(Collectors.groupingBy(UserRoleDTO::getUserId));
userInfoPage.convert(userInfoDTO -> {
userInfoDTO.setUserRoleList(userIdMapUserRoleDTo.get(userInfoDTO.getId()));
return userInfoDTO;
});
return userInfoPage;
}
@Override
public Boolean resetPW(UserPwReqVo userPwReqVo) {
Assert.notEmpty(userPwReqVo.getId(), "用户id不能为空");
Assert.notEmpty(userPwReqVo.getPassword(), "密码不能为空");
return systemUserService.lambdaUpdate()
.set(SystemUser::getUserPd, UserUtil.signPassword(userPwReqVo.getPassword()))
.eq(SystemUser::getId, userPwReqVo.getId()).update();
}
@Override
public void updateUserStatus(UserStatusReqVo userStatusReqVo) {
Assert.notEmpty(userStatusReqVo.getId(), "用户id不能为空");
Assert.notNull(userStatusReqVo.getStatus(), "用户状态不能为空");
systemUserService.lambdaUpdate().set(SystemUser::getStatus, userStatusReqVo.getStatus())
.eq(SystemUser::getId, userStatusReqVo.getId()).update();
}
}

@ -0,0 +1,77 @@
package com.supervision.knowsub.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.supervision.knowsub.dto.role.UserRoleDTO;
import com.supervision.knowsub.model.SystemUserRoleRelation;
import com.supervision.knowsub.service.SystemUserRoleRelationService;
import com.supervision.knowsub.service.UserRoleRelationManageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
public class UserRoleRelationManageServiceImpl implements UserRoleRelationManageService {
private final SystemUserRoleRelationService userRoleRelationService;
@Override
@Transactional(rollbackFor = Exception.class)
public List<SystemUserRoleRelation> saveUserRoleRelation(String userId, List<String> roleIdList) {
Assert.notEmpty(userId, "用户id不能为空");
if (CollUtil.isEmpty(roleIdList)){
log.info("saveUserRoleRelation:userId:{},roleList is empty",userId);
return CollUtil.newArrayList();
}
List<SystemUserRoleRelation> userRoleList = roleIdList.stream().map(roleId -> {
SystemUserRoleRelation userRole = new SystemUserRoleRelation();
userRole.setRoleId(roleId);
userRole.setUserId(userId);
return userRole;
}).toList();
userRoleRelationService.saveBatch(userRoleList);
return userRoleList;
}
@Override
@Transactional(rollbackFor = Exception.class)
public List<SystemUserRoleRelation> updateUserRoleRelation(String userId, List<String> roleIdList) {
Assert.notEmpty(userId, "用户id不能为空");
userRoleRelationService.lambdaUpdate().eq(SystemUserRoleRelation::getUserId,userId).remove();
if (CollUtil.isEmpty(roleIdList)){
log.info("updateUserRoleRelation:userId:{},roleList is empty",userId);
return CollUtil.newArrayList();
}
return saveUserRoleRelation(userId,roleIdList);
}
@Override
@Transactional(rollbackFor = Exception.class)
public List<UserRoleDTO> listUserRole(String userId, String roleId,String roleName) {
return userRoleRelationService.listUserRole(userId,roleId,roleName);
}
@Override
public List<UserRoleDTO> listUserRoleByUserIds(List<String> userIds) {
if (CollUtil.isEmpty(userIds)){
return CollUtil.newArrayList();
}
return userRoleRelationService.listUserRoleByUserIds(userIds);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteUserRoleRelation(String userId) {
userRoleRelationService.lambdaUpdate().eq(SystemUserRoleRelation::getUserId,userId).remove();
}
}

@ -0,0 +1,44 @@
package com.supervision.knowsub.task;
import cn.hutool.core.util.ObjectUtil;
import com.supervision.knowsub.dto.knowledge.CheckInvalidDTO;
import com.supervision.knowsub.enums.StatusEnum;
import com.supervision.knowsub.model.Knowledge;
import com.supervision.knowsub.service.KnowledgeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.List;
@Slf4j
@Component
@RequiredArgsConstructor
public class InvalidCheckTask {
private final KnowledgeService knowledgeService;
/**
* ,01:00
* ,
*/
//@Scheduled(cron = "0 0 1 * * ?")
@Scheduled(cron = "0 0 * * * ?")
public void checkInvalidKnowledge() {
log.info("定时任务,检查是否存在过期任务开始");
List<CheckInvalidDTO> checkInvalidDTOS = knowledgeService.queryKnowledgeInvalidList();
for (CheckInvalidDTO checkInvalidDTO : checkInvalidDTOS) {
// 校验当前时间是否超过了最大时间
if (LocalDateTime.now().isAfter(checkInvalidDTO.getExecTimeEnd())) {
log.info("标题:{},过期时间:{},目前已过期,标记为过期", checkInvalidDTO.getTitle(), checkInvalidDTO.getExecTimeEnd());
// 如果超过了当前时间,说明过期了
knowledgeService.lambdaUpdate().set(Knowledge::getStatus, StatusEnum.INVALID.getStatus())
.eq(Knowledge::getId, checkInvalidDTO.getKnowledgeId()).update();
}
}
log.info("定时任务,检查是否存在过期任务结束");
}
}

@ -0,0 +1,77 @@
server:
port: 9201
servlet:
context-path: /know-sub
undertow:
# HTTP post内容的最大大小。当值为-1时默认值为大小是无限的
max-http-post-size: -1
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 512
# 是否分配的直接内存
direct-buffers: true
spring:
main:
allow-bean-definition-overriding: true
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
## 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://know-sub-mysql:3306/know_sub?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&serverTimezone=GMT%2B8
username: root
password: ${datasource.password}
initial-size: 5 # 初始化大小
min-idle: 10 # 最小连接数
max-active: 20 # 最大连接数
max-wait: 60000 # 获取连接时的最大等待时间
min-evictable-idle-time-millis: 300000 # 一个连接在池中最小生存的时间,单位是毫秒
time-between-eviction-runs-millis: 60000 # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒
filters: stat,wall # 配置扩展插件stat-监控统计log4j-日志wall-防火墙防止SQL注入去掉后监控界面的sql无法统计
validation-query: SELECT 1 # 检测连接是否有效的 SQL语句为空时以下三个配置均无效
test-on-borrow: true # 申请连接时执行validationQuery检测连接是否有效默认true开启后会降低性能
test-on-return: true # 归还连接时执行validationQuery检测连接是否有效默认false开启后会降低性能
test-while-idle: true # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis执行validationQuery检测连接是否有效默认false建议开启不影响性能
stat-view-servlet:
enabled: true # 是否开启 StatViewServlet
loginUsername: admin
loginPassword: 123456
filter:
stat:
enabled: true # 是否开启 FilterStat默认true
log-slow-sql: true # 是否开启 慢SQL 记录默认false
slow-sql-millis: 5000 # 慢 SQL 的标准,默认 3000单位毫秒
merge-sql: false # 合并多个连接池的监控数据默认false
mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# springdoc-openapi项目配置
springdoc:
# 默认是false需要设置为true 解决GET请求时,用自定义对象接受现实错误的问题
default-flat-param-object: true
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
paths-to-match: '/**'
packages-to-scan: com.supervision
# knife4j的增强配置不需要增强可以不配
knife4j:
enable: true
setting:
language: zh_cn
user:
# 默认密码
default:
password: 123456

@ -0,0 +1,78 @@
#服务器端口
server:
port: 9201
servlet:
context-path: /know-sub
undertow:
# HTTP post内容的最大大小。当值为-1时默认值为大小是无限的
max-http-post-size: -1
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 512
# 是否分配的直接内存
direct-buffers: true
spring:
main:
allow-bean-definition-overriding: true
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
## 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.10.138:3306/know_sub?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&serverTimezone=GMT%2B8
username: root
password: '123456'
initial-size: 5 # 初始化大小
min-idle: 10 # 最小连接数
max-active: 20 # 最大连接数
max-wait: 60000 # 获取连接时的最大等待时间
min-evictable-idle-time-millis: 300000 # 一个连接在池中最小生存的时间,单位是毫秒
time-between-eviction-runs-millis: 60000 # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒
filters: stat,wall # 配置扩展插件stat-监控统计log4j-日志wall-防火墙防止SQL注入去掉后监控界面的sql无法统计
validation-query: SELECT 1 # 检测连接是否有效的 SQL语句为空时以下三个配置均无效
test-on-borrow: true # 申请连接时执行validationQuery检测连接是否有效默认true开启后会降低性能
test-on-return: true # 归还连接时执行validationQuery检测连接是否有效默认false开启后会降低性能
test-while-idle: true # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis执行validationQuery检测连接是否有效默认false建议开启不影响性能
stat-view-servlet:
enabled: true # 是否开启 StatViewServlet
loginUsername: admin
loginPassword: 123456
filter:
stat:
enabled: true # 是否开启 FilterStat默认true
log-slow-sql: true # 是否开启 慢SQL 记录默认false
slow-sql-millis: 5000 # 慢 SQL 的标准,默认 3000单位毫秒
merge-sql: false # 合并多个连接池的监控数据默认false
mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# springdoc-openapi项目配置
springdoc:
# 默认是false需要设置为true 解决GET请求时,用自定义对象接受现实错误的问题
default-flat-param-object: true
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
paths-to-match: '/**'
packages-to-scan: com.supervision
# knife4j的增强配置不需要增强可以不配
knife4j:
enable: true
setting:
language: zh_cn
user:
# 默认密码
default:
password: 123456

@ -1 +0,0 @@
spring.application.name=know_sub_business

@ -0,0 +1,78 @@
#服务器端口
server:
port: 9201
servlet:
context-path: /know-sub
undertow:
# HTTP post内容的最大大小。当值为-1时默认值为大小是无限的
max-http-post-size: -1
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 512
# 是否分配的直接内存
direct-buffers: true
spring:
main:
allow-bean-definition-overriding: true
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
## 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.10.137:3306/know_sub?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&serverTimezone=GMT%2B8
username: root
password: '123456'
initial-size: 5 # 初始化大小
min-idle: 10 # 最小连接数
max-active: 20 # 最大连接数
max-wait: 60000 # 获取连接时的最大等待时间
min-evictable-idle-time-millis: 300000 # 一个连接在池中最小生存的时间,单位是毫秒
time-between-eviction-runs-millis: 60000 # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒
filters: stat,wall # 配置扩展插件stat-监控统计log4j-日志wall-防火墙防止SQL注入去掉后监控界面的sql无法统计
validation-query: SELECT 1 # 检测连接是否有效的 SQL语句为空时以下三个配置均无效
test-on-borrow: true # 申请连接时执行validationQuery检测连接是否有效默认true开启后会降低性能
test-on-return: true # 归还连接时执行validationQuery检测连接是否有效默认false开启后会降低性能
test-while-idle: true # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis执行validationQuery检测连接是否有效默认false建议开启不影响性能
stat-view-servlet:
enabled: true # 是否开启 StatViewServlet
loginUsername: admin
loginPassword: 123456
filter:
stat:
enabled: true # 是否开启 FilterStat默认true
log-slow-sql: true # 是否开启 慢SQL 记录默认false
slow-sql-millis: 5000 # 慢 SQL 的标准,默认 3000单位毫秒
merge-sql: false # 合并多个连接池的监控数据默认false
mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# springdoc-openapi项目配置
springdoc:
# 默认是false需要设置为true 解决GET请求时,用自定义对象接受现实错误的问题
default-flat-param-object: true
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
paths-to-match: '/**'
packages-to-scan: com.supervision
# knife4j的增强配置不需要增强可以不配
knife4j:
enable: true
setting:
language: zh_cn
user:
# 默认密码
default:
password: 123456

@ -6,43 +6,106 @@
<groupId>com.supervision</groupId>
<artifactId>know_sub</artifactId>
<version>1.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<artifactId>know_sub_common</artifactId>
<version>1.0.0</version>
<name>know_sub_common</name>
<packaging>jar</packaging>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!--移除Tomcat依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
</dependency>
<!-- 其他依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--jsr303-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
</dependency>
<!-- SpringBoot集成mybatis框架 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<parameters>true</parameters>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,38 @@
package com.supervision.knowsub.config;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
public class DateFormatConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
objectMapper.registerModule(javaTimeModule);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return objectMapper;
}
}

@ -0,0 +1,106 @@
package com.supervision.knowsub.config;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.supervision.knowsub.exception.BusinessException;
import com.supervision.knowsub.util.TokenUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {
public JwtInterceptor() {
}
// @Override
// public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// //请求消息头获取用户ID
// String token = request.getHeader("token");
// if (StrUtil.isBlank(token)) {
// // 如果是swagger来的接口,说明这里是测试的,会伪造一个用户
// String referer = request.getHeader("Referer");
// if (StrUtil.isNotBlank(referer) && StrUtil.contains(referer, "doc.html")) {
//// cacheAuth(JWTUtil.parseToken(devActiveUser()));
// setTokenToRequestHolder(devActiveUser());
// return true;
// } else {
// throw new BusinessException("当前用户未登录", HttpStatus.UNAUTHORIZED.value());
// }
// }
// JWT jwt = JWTUtil.parseToken(token);
// // 校验token是否过期,如果过期了,需要提示过期重新登录
// checkTokenExpire(jwt);
// // cacheAuth(jwt);
// return true;
// }
/**
* ,mock
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
Map<String, Object> map = new HashMap<>();
map.put("id", "1");
map.put("account", "test");
map.put("username", "测试");
map.put("deptId", "1");
map.put("roleId", "1");
setTokenToRequestHolder(TokenUtil.creatToken(JSONUtil.toJsonStr(map)));
return true;
}
private void setTokenToRequestHolder(String token) {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (ObjectUtils.isEmpty(requestAttributes)) {
throw new BusinessException("未获取到用户信息");
}
requestAttributes.setAttribute("token", token, 0);
}
@Override
public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler,
@Nullable Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
private void checkTokenExpire(JWT jwt) {
Object expireTime = jwt.getPayload("expireTime");
long l = Long.parseLong(String.valueOf(expireTime));
// 校验是否比当前时间大
long currentTimeMillis = System.currentTimeMillis();
if (currentTimeMillis > l) {
throw new BusinessException("用户登录已过期,请重新登录", HttpStatus.UNAUTHORIZED.value());
}
}
private String devActiveUser() {
Map<String, Object> map = new HashMap<>();
map.put("id", "1");
map.put("account", "test");
map.put("username", "测试");
map.put("deptId", "1");
map.put("roleId", "1");
return TokenUtil.creatToken(JSONUtil.toJsonStr(map));
}
}

@ -0,0 +1,31 @@
package com.supervision.knowsub.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.supervision.knowsub.util.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Optional;
@Component
@Slf4j
public class MybatisMetaHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("填充创建和开始时间以及新增用户");
// 填充
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
Optional.ofNullable(UserUtil.getUser()).ifPresent(user -> this.strictInsertFill(metaObject, "createUserId", String.class, user.getId()));
Optional.ofNullable(UserUtil.getUser()).ifPresent(user -> this.strictInsertFill(metaObject, "updateUserId", String.class, user.getId()));
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("填充修改时间以及修改用户");
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
Optional.ofNullable(UserUtil.getUser()).ifPresent(user -> this.strictInsertFill(metaObject, "updateUserId", String.class, user.getId()));
}
}

@ -0,0 +1,36 @@
/*
* : MybatisPlusConfig
* :
* : <>
* : RedName
* : 2022/8/9
* : <>
* : <>
* : <>
*/
package com.supervision.knowsub.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* <>
*
* @author RedName
* @version [, 2022/8/9]
* @see [/]
* @since [/]
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

@ -0,0 +1,159 @@
package com.supervision.knowsub.config;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
import java.util.Map;
/**
*
*
* @author :liu
* create :2020-11-16 10:50
**/
@Component
@Aspect
@Slf4j
public class RequestLogConfig {
@SuppressWarnings("all")
@Around("within(com..*..controller..*) && @within(org.springframework.web.bind.annotation.RestController)")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long start = System.currentTimeMillis();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Object result = proceedingJoinPoint.proceed();
RequestInfo requestInfo = new RequestInfo();
requestInfo.setUrl(request.getRequestURL().toString());
requestInfo.setHttpMethod(request.getMethod());
requestInfo.setClassMethod(String.format("%s.%s",proceedingJoinPoint.getSignature().getDeclaringType().getSimpleName(),
proceedingJoinPoint.getSignature().getName()));
requestInfo.setRequestParams(getRequestParamsByProceedingJoinPoint(proceedingJoinPoint));
requestInfo.setResult(proceedResult(result));
requestInfo.setTimeCost(System.currentTimeMillis() - start);
log.info("Request Info: {}", JSONUtil.toJsonStr(requestInfo));
return result;
}
private Object proceedResult(Object result) {
String value = null;
try {
value = JSONUtil.toJsonStr(result);
} catch (Exception e) {
value = result.toString();
}
if (StrUtil.isNotBlank(value) && value.length() > 10240){
value = value.substring(0, 1024) + "......" + value.substring(value.length() - 1024);
return value;
}
return result;
}
@SuppressWarnings("all")
@AfterThrowing(pointcut = "@within(org.springframework.web.bind.annotation.RestController)", throwing = "e")
public void doAfterThrow(JoinPoint joinPoint, RuntimeException e) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
RequestErrorInfo requestErrorInfo = new RequestErrorInfo();
requestErrorInfo.setUrl(request.getRequestURL().toString());
requestErrorInfo.setHttpMethod(request.getMethod());
requestErrorInfo.setClassMethod(String.format("%s.%s", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName()));
requestErrorInfo.setRequestParams(getRequestParamsByJoinPoint(joinPoint));
requestErrorInfo.setException(e);
log.info("Error Request Info : {}", JSONUtil.toJsonStr(requestErrorInfo));
}
/**
*
*
* @param proceedingJoinPoint
* @return
*/
private Map<String, Object> getRequestParamsByProceedingJoinPoint(ProceedingJoinPoint proceedingJoinPoint) {
//参数名
String[] paramNames = ((MethodSignature) proceedingJoinPoint.getSignature()).getParameterNames();
//参数值
Object[] paramValues = proceedingJoinPoint.getArgs();
return buildRequestParam(paramNames, paramValues);
}
private Map<String, Object> getRequestParamsByJoinPoint(JoinPoint joinPoint) {
//参数名
String[] paramNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
//参数值
Object[] paramValues = joinPoint.getArgs();
return buildRequestParam(paramNames, paramValues);
}
private Map<String, Object> buildRequestParam(String[] paramNames, Object[] paramValues) {
Map<String, Object> requestParams = new HashMap<>();
if (paramNames == null){
return requestParams;
}
for (int i = 0; i < paramNames.length; i++) {
Object value = paramValues[i];
if (value instanceof ServletRequest || value instanceof ServletResponse) {
//ServletRequest不能序列化从入参里排除否则报异常java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
//ServletResponse不能序列化 从入参里排除否则报异常java.lang.IllegalStateException: getOutputStream() has already been called for this response
continue;
}
//如果是文件对象
if (value instanceof MultipartFile) {
MultipartFile file = (MultipartFile) value;
//获取文件名
value = file.getOriginalFilename();
} else if (value instanceof String) {
// 如果参数很长,就对参数进行修剪
String temp = (String) value;
if (!ObjectUtils.isEmpty(temp) && temp.length() > 1024) {
value = temp.substring(0, 10) + "......" + temp.substring(temp.length() - 10);
}
}
requestParams.put(paramNames[i], value);
}
return requestParams;
}
@Data
public static class RequestInfo {
private String url;
private String httpMethod;
private String classMethod;
private Object requestParams;
private Object result;
private Long timeCost;
}
@Data
public static class RequestErrorInfo {
private String url;
private String httpMethod;
private String classMethod;
private Object requestParams;
private RuntimeException exception;
}
}

@ -0,0 +1,124 @@
package com.supervision.knowsub.config;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.supervision.knowsub.domain.GlobalResult;
import com.supervision.knowsub.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.Objects;
import java.util.stream.Collectors;
/**
*
*
* @author wb
* @date 2022/3/10 13:24
*/
@Slf4j
@RestControllerAdvice(annotations = RestController.class, basePackages = {"com.supervision.**.controller"})
public class ResponseConfig implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(@Nullable MethodParameter methodParameter,
@Nullable Class<? extends HttpMessageConverter<?>> aClass) {
assert methodParameter != null;
String lowerCase = methodParameter.getDeclaringClass().getName().toLowerCase();
log.info(lowerCase);
if (lowerCase.contains("swagger") || lowerCase.contains("springdoc")) {
return false;
} else {
log.info("--------{}---------", lowerCase);
return true;
}
}
@Override
@SuppressWarnings("all")
public Object beforeBodyWrite(Object o, @Nullable MethodParameter methodParameter, @Nullable MediaType mediaType,
@Nullable Class<? extends HttpMessageConverter<?>> aClass, @Nullable ServerHttpRequest serverHttpRequest,
@Nullable ServerHttpResponse serverHttpResponse) {
serverHttpResponse.getHeaders().set("Content-Type", "application/json");
if (Objects.isNull(o)) {
return GlobalResult.ok(null, "success");
}
if (o instanceof GlobalResult) {
return o;
}
// 对于String类型的返回值需要进行特殊处理
if (o instanceof String) {
return JSONUtil.toJsonStr(GlobalResult.ok(o, "success"));
}
return GlobalResult.ok(o, "success");
}
/**
*
*
* @param exception
* @return
*/
@ExceptionHandler(BusinessException.class)
public GlobalResult<?> businessExceptionResponse(BusinessException exception) {
log.error(exception.getMessage(), exception);
Integer code = null == exception.getCode() ? HttpStatus.INTERNAL_SERVER_ERROR.value(): exception.getCode();
String message = StrUtil.isNotEmpty(exception.getMessage()) ? exception.getMessage() : "业务异常";
return GlobalResult.error( code, exception.getMessage(), message);
}
/**
*
*
* @param exception
* @return
*/
@ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
public GlobalResult<?> validationExceptionResponse(MethodArgumentNotValidException exception) {
log.error(exception.getMessage(), exception);
// 格式化错误信息
String errorMsg = exception.getBindingResult().getFieldErrors().stream()
.map(e -> e.getField() + ":" + e.getDefaultMessage()).collect(Collectors.joining("、"));
return GlobalResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), errorMsg, "参数验证异常");
}
/**
*
* @param exception
* @return
*/
@ExceptionHandler(IllegalArgumentException.class)
public GlobalResult<?> manualValidationExceptionResponse(IllegalArgumentException exception) {
log.error(exception.getMessage(), exception);
return GlobalResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), exception.getMessage(), "参数验证异常");
}
/**
*
*
* @param exception
* @return
*/
@ExceptionHandler(Exception.class)
public GlobalResult<?> validationExceptionResponse(Exception exception) {
log.error(exception.getMessage(), exception);
return GlobalResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "未知错误", "未知错误");
}
}

@ -0,0 +1,58 @@
package com.supervision.knowsub.config;
import cn.hutool.core.util.RandomUtil;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class SwaggerConfiguration {
/**
* @Tag x-order
*
* @return the global open api customizer
*/
@Bean
public GlobalOpenApiCustomizer orderGlobalOpenApiCustomizer() {
return openApi -> {
if (openApi.getTags() != null) {
openApi.getTags().forEach(tag -> {
Map<String, Object> map = new HashMap<>();
map.put("x-order", RandomUtil.randomInt(0, 100));
tag.setExtensions(map);
});
}
if (openApi.getPaths() != null) {
openApi.addExtension("x-test123", "333");
openApi.getPaths().addExtension("x-abb", RandomUtil.randomInt(1, 100));
}
};
}
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("知识报送API")
.version("1.3")
.description("Knife4j集成springdoc-openapi示例")
.termsOfService("http://doc.xiaominfo.com")
.license(new License().name("Apache 2.0")
.url("http://doc.xiaominfo.com")));
}
}

@ -0,0 +1,58 @@
package com.supervision.knowsub.config;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加权限拦截器
registry.addInterceptor(new JwtInterceptor())
.addPathPatterns("/**")
.excludePathPatterns(ignorePathPatterns());
}
public List<String> ignorePathPatterns() {
List<String> paths = new ArrayList<>();
paths.add("/swagger-resources/**");
paths.add("/webjars/**");
paths.add("/v3/**");
paths.add("/swagger-ui.html/**");
paths.add("/swagger-ui/**");
paths.add("/webjars/");
paths.add("/doc.html/**");
paths.add("/error");
paths.add("/favicon.ico");
paths.add("/user/login");
paths.add("/user/register");
paths.add("/user/changePassWord");
paths.add("/user/checkAccount");
paths.add("/webSocket/**");
paths.add("/ask/downloadTalkVideo");
paths.add("/file/downloadFile");
paths.add("/aqLibrary/downloadQuestionLibraryTemplate");
paths.add("/medicalRecManage/downloadMedicalAnswerTemplate");
paths.add("/qaKnowledge/**");
// 开发环境,放开不校验token.每次修改这里需要重启(热部署不行)
//paths.add("/**");
return paths;
}
}

@ -0,0 +1,45 @@
package com.supervision.knowsub.domain;
import lombok.Data;
import org.springframework.http.HttpStatus;
@Data
public class GlobalResult<T> {
private int code = 200;
private String msg = "success";
private T data;
public static <T> GlobalResult<T> ok() {
return ok(null);
}
public static <T> GlobalResult<T> ok(T data) {
GlobalResult<T> globalResult = new GlobalResult<>();
globalResult.setData(data);
return globalResult;
}
public static <T> GlobalResult<T> ok(T data, String message) {
GlobalResult<T> globalResult = new GlobalResult<>();
globalResult.setMsg(message);
globalResult.setData(data);
return globalResult;
}
public static <T> GlobalResult<T> error(String msg) {
return error(HttpStatus.INTERNAL_SERVER_ERROR.value(), null, msg);
}
public static <T> GlobalResult<T> error(int code, T data, String msg) {
GlobalResult<T> globalResult = new GlobalResult<>();
globalResult.setCode(code);
globalResult.setData(data);
globalResult.setMsg(msg);
return globalResult;
}
}

@ -0,0 +1,36 @@
package com.supervision.knowsub.domain;
import lombok.Data;
import java.util.List;
@Data
public class UserInfo {
private String id;
/**
* ID
*/
private String roleId;
/**
*
*/
private String username;
/**
*
*/
private String account;
/**
* ID
*/
private String deptId;
/**
*
*/
private List<Integer> roleTypeList;
}

@ -0,0 +1,76 @@
/*
* : CustomException
* :
* : <>
* : RedName
* : 2022/8/5
* : <>
* : <>
* : <>
*/
package com.supervision.knowsub.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
/**
* <>
*
*
* @author ljt
* @version [, 2022/8/5]
* @see [/]
* @since [/]
*/
@Slf4j
public class BusinessException extends RuntimeException {
/**
*
*/
private final Integer code;
/**
*
*/
private final String message;
public BusinessException(Throwable cause) {
super(cause);
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.message = null;
}
public BusinessException(Throwable cause, String message) {
super(cause);
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.message = message;
}
public BusinessException(String message) {
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.message = message;
}
public BusinessException(String message, Integer code) {
this.message = message;
this.code = code;
}
public BusinessException(String message, Throwable e) {
super(message, e);
log.error(message, e);
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.message = message;
}
@Override
public String getMessage() {
return message;
}
public Integer getCode() {
return code;
}
}

@ -0,0 +1,97 @@
package com.supervision.knowsub.util;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
public class SM2Util {
private static SM2 sm2 = getSM2();
/**
* ; 使使
*/
public static void generateKey() {
KeyPair pair = SecureUtil.generateKeyPair("SM2");
PrivateKey privateKey = pair.getPrivate();
PublicKey publicKey = pair.getPublic();
System.out.println("private:"+Base64.encode(privateKey.getEncoded()));
System.out.println("public:"+Base64.encode(publicKey.getEncoded()));
}
/**
*
* @param content
* @param sign
* @return truefalse
*/
public static boolean verify(String content,String sign){
return sm2.verifyHex(HexUtil.encodeHexStr(content), sign);
}
/**
*
* @param content
* @return base64
*/
public static String encryptBase64(String content){
return sm2.encryptBase64(content,KeyType.PublicKey);
}
/**
*
* @param data
* @return
*/
public static String decrypt(String data){
return sm2.decryptStr(data, KeyType.PrivateKey);
}
/**
*
* @param content
* @return 142
*/
public static String sign(String content){
return sm2.signHex(HexUtil.encodeHexStr(content));
}
public static SM2 getSM2(){
String privateKey = ResourceUtil.readUtf8Str("sm2_private.key");
String publicKey = ResourceUtil.readUtf8Str("sm2_public.key");
return new SM2(privateKey, publicKey);
}
public static void main(String[] args) {
String content = "张三里斯忘我ss **##";
String encryptBase64 = encryptBase64(content);
System.out.println("加密结果:"+encryptBase64);
String decrypt = decrypt(encryptBase64);
System.out.println("解密结果:"+decrypt);
String sign = sign(content);
System.out.println("签名结果:"+sign);
boolean verify = verify(content, sign);
System.out.println("正向验证结果:"+verify);
boolean verify1 = verify("djaoidf", sign);
System.out.println("反向验证结果:"+verify1);
}
}

@ -0,0 +1,128 @@
package com.supervision.knowsub.util;
import cn.hutool.core.util.ArrayUtil;
import jakarta.validation.constraints.NotNull;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import java.util.Map;
/***
* @author ljt
* @since 2020/8/4 17:37
*
*/
@Component
@Lazy(false)
public class SpringBeanUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
/**
* applicationContext
*
* @return ApplicationContext
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void setApplicationContext(@NotNull ApplicationContext applicationContext) {
SpringBeanUtil.applicationContext = applicationContext;
}
//通过name获取 Bean.
/**
* name Bean
*
* @param <T> Bean
* @param name Bean
* @return Bean
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
/**
* classBean
*
* @param <T> Bean
* @param clazz Bean
* @return Bean
*/
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
/**
* name,ClazzBean
*
* @param <T> bean
* @param name Bean
* @param clazz bean
* @return Bean
*/
public static <T> T getBean(String name, Class<T> clazz) {
return applicationContext.getBean(name, clazz);
}
/**
* Bean
*
* @param <T> Bean
* @param type nullbean
* @return beankeybeannamevalueBean
* @since 5.3.3
*/
public static <T> Map<String, T> getBeansOfType(Class<T> type) {
return applicationContext.getBeansOfType(type);
}
/**
* Bean
*
* @param type nullbean
* @return bean
* @since 5.3.3
*/
public static String[] getBeanNamesForType(Class<?> type) {
return applicationContext.getBeanNamesForType(type);
}
/**
*
*
* @param key key
* @return
* @since 5.3.3
*/
public static String getProperty(String key) {
return applicationContext.getEnvironment().getProperty(key);
}
/**
* null
*
* @return
* @since 5.3.3
*/
public static String[] getActiveProfiles() {
return applicationContext.getEnvironment().getActiveProfiles();
}
/**
*
*
* @return
* @since 5.3.3
*/
public static String getActiveProfile() {
final String[] activeProfiles = getActiveProfiles();
return ArrayUtil.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
}
}

@ -0,0 +1,19 @@
package com.supervision.knowsub.util;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
public class TokenUtil {
public static String creatToken(String userInfo){
final JWTSigner signer = JWTSignerUtil.hs256("123456".getBytes());
JSONObject info = JSONUtil.parseObj(userInfo);
// 过期时间一天,同时这个字段也作为单点登录使用
info.putOnce("expireTime",System.currentTimeMillis() + 1000 * 60 * 60 * 24);
info.putOnce("issueTime",System.currentTimeMillis());
return JWTUtil.createToken(info, signer);
}
}

@ -0,0 +1,63 @@
package com.supervision.knowsub.util;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.supervision.knowsub.domain.UserInfo;
import com.supervision.knowsub.exception.BusinessException;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
public class UserUtil {
public static UserInfo getUser() {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (ObjectUtils.isEmpty(requestAttributes)) {
throw new BusinessException("未获取到用户信息");
}
HttpServletRequest request = requestAttributes.getRequest();
String token = request.getHeader("token");
if (StrUtil.isBlank(token)) {
token = (String) request.getAttribute("token");
}
if (ObjectUtil.isEmpty(token)) {
throw new BusinessException("未获取到用户token信息");
}
JWT jwt = JWTUtil.parseToken(token);
JSONObject claimsJson = jwt.getPayload().getClaimsJson();
// String userStr = ThreadCache.USER.get();
UserInfo bean = JSONUtil.toBean(claimsJson.toString(), UserInfo.class);
if (ObjectUtil.isEmpty(bean)) {
throw new BusinessException("未获取到用户信息");
}
return bean;
}
/**
*
* @param password
* @param userPd
* @return
*/
public static boolean checkUserPassword(String password, String userPd) {
return SM2Util.verify(password, userPd);
}
/**
*
* @param password
* @return
*/
public static String signPassword(String password){
return SM2Util.sign(password);
}
}

@ -0,0 +1 @@
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgIc/Neoxk2aVlkKS4WyHJQ6NTWRMcaSh7dqAeH7gHKyegCgYIKoEcz1UBgi2hRANCAASSC2D8SWIwi6S2QmAzuiJXwtcTHcPsY/Epd4y6VOy0x5OZ4+hXdAq9KrXtRXJlbho1x8+0Rifr396CChxfYcAN

@ -0,0 +1 @@
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEkgtg/EliMIuktkJgM7oiV8LXEx3D7GPxKXeMulTstMeTmePoV3QKvSq17UVyZW4aNcfPtEYn69/eggocX2HADQ==

@ -0,0 +1,154 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>com.supervision</groupId>
<artifactId>know_sub</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>know_sub_etl</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-tika-document-reader</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>io.springboot.ai</groupId>-->
<!-- <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-elasticsearch-store</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.supervision</groupId>
<artifactId>know_sub_common</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.supervision</groupId>
<artifactId>know_sub_model</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>central</id>
<name>aliyun central repo</name>
<url>https://maven.aliyun.com/nexus/content/repositories/central/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<parameters>true</parameters>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,18 @@
package som.supervision.knowsub;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
@MapperScan(basePackages = {"com.supervision.**.mapper"})
@EnableConfigurationProperties
public class KnowSubEtlApplication {
public static void main(String[] args) {
SpringApplication.run(KnowSubEtlApplication.class, args);
}
}

@ -0,0 +1,33 @@
package som.supervision.knowsub.config;
import org.elasticsearch.client.RestClient;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.vectorstore.ElasticsearchVectorStore;
import org.springframework.ai.vectorstore.ElasticsearchVectorStoreOptions;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;
@Configuration
@EnableConfigurationProperties(EmbeddingProperties.class)
public class ElasticsearchVectorStoreConfig {
@Bean
@ConditionalOnProperty(prefix = "embedding", name = "url")
public EmbeddingModel embeddingModel(EmbeddingProperties embeddingProperties) {
Assert.notNull(embeddingProperties.getUrl(), "配置文件embedding:url未找到");
return new VectorEmbeddingModel(embeddingProperties.getUrl());
}
@Bean
@ConditionalOnProperty(prefix = "embedding", name = "url")
public ElasticsearchVectorStore vectorStore(EmbeddingModel embeddingModel, RestClient restClient) {
ElasticsearchVectorStoreOptions options = new ElasticsearchVectorStoreOptions();
options.setIndexName("know-sub-rag-store");
options.setDimensions(1024);
return new ElasticsearchVectorStore(options, restClient, embeddingModel, true);
}
}

@ -0,0 +1,12 @@
package som.supervision.knowsub.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "embedding")
public class EmbeddingProperties {
private String url;
}

@ -0,0 +1,57 @@
package som.supervision.knowsub.config;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.*;
import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
public class VectorEmbeddingModel implements EmbeddingModel {
private final String embeddingUrl;
public VectorEmbeddingModel(String embeddingUrl) {
this.embeddingUrl = embeddingUrl;
}
@Override
public List<Double> embed(Document document) {
List<List<Double>> list = this.call(new EmbeddingRequest(List.of(document.getContent()), EmbeddingOptions.EMPTY))
.getResults()
.stream()
.map(Embedding::getOutput)
.toList();
return list.iterator().next();
}
@Override
public EmbeddingResponse call(EmbeddingRequest request) {
Assert.notEmpty(request.getInstructions(), "At least one text is required!");
List<List<Double>> embeddingList = new ArrayList<>();
for (String inputContent : request.getInstructions()) {
// 这里需要吧inputContent转化为向量数据
String post = HttpUtil.post(embeddingUrl, JSONUtil.toJsonStr(Map.of("text", inputContent)));
EmbeddingData bean = JSONUtil.toBean(post, EmbeddingData.class);
embeddingList.add(bean.embeddings);
}
var indexCounter = new AtomicInteger(0);
List<Embedding> embeddings = embeddingList.stream()
.map(e -> new Embedding(e, indexCounter.getAndIncrement()))
.toList();
return new EmbeddingResponse(embeddings);
}
@Data
private static class EmbeddingData {
private List<Double> embeddings;
}
}

@ -0,0 +1,27 @@
package som.supervision.knowsub.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.annotations.Param;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import som.supervision.knowsub.service.KnowledgeEtlService;
import java.io.IOException;
@Tag(name = "知识ETL类")
@RestController
@RequestMapping("etl")
@RequiredArgsConstructor
public class KnowledgeEtlController {
private final KnowledgeEtlService knowledgeEtlService;
@Operation(summary = "对知识进行ETL")
@PostMapping("knowledgeEtl")
public void knowledgeEtl(@RequestParam("files") MultipartFile[] files) {
knowledgeEtlService.knowledgeEtl(files);
}
}

@ -0,0 +1,12 @@
package som.supervision.knowsub.service;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
public interface KnowledgeEtlService {
void knowledgeEtl(MultipartFile[] files);
}

@ -0,0 +1,66 @@
package som.supervision.knowsub.service.impl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.ElasticsearchVectorStore;
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import som.supervision.knowsub.service.KnowledgeEtlService;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
@Service
@RequiredArgsConstructor
public class KnowledgeEtlServiceImpl implements KnowledgeEtlService {
private final ElasticsearchVectorStore elasticsearchVectorStore;
/**
* <a href="https://zhuanlan.zhihu.com/p/703705663"/>
*
* @param inputStream
*/
private void loadFile(InputStream inputStream, String fileName) {
// 首先使用tika进行文件切分操作
log.info("{} 进行内容切分", fileName);
TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(new InputStreamResource(inputStream));
List<Document> documents = tikaDocumentReader.read();
log.info("{} 切分完成,开始进行chunk分割", fileName);
// 然后切分为chunk
TokenTextSplitter tokenTextSplitter = new TokenTextSplitter(500, 250, 10, 1000, true);
List<Document> apply = tokenTextSplitter.apply(documents);
for (Document document : apply) {
document.getMetadata().put("fileName", fileName);
}
log.info("{} 切分完成,开始进行保存到向量库中", fileName);
// 保存到向量数据库中
elasticsearchVectorStore.accept(apply);
log.info("{} 保存完成", fileName);
}
@Override
public void knowledgeEtl(MultipartFile[] files) {
AtomicInteger atomicInteger = new AtomicInteger(1);
for (MultipartFile file : files) {
try {
loadFile(file.getInputStream(), file.getOriginalFilename());
} catch (Exception e) {
log.error("{}文件处理失败", file.getOriginalFilename(), e);
}
int andIncrement = atomicInteger.getAndIncrement();
log.info("处理第{}个文件,剩余:{}个", andIncrement, files.length - andIncrement + 1);
}
log.info("文件处理结束");
}
}

@ -0,0 +1,94 @@
#服务器端口
server:
port: 9202
servlet:
context-path: /know-sub-etl
undertow:
# HTTP post内容的最大大小。当值为-1时默认值为大小是无限的
max-http-post-size: -1
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 512
# 是否分配的直接内存
direct-buffers: true
spring:
elasticsearch:
uris: http://192.168.10.137:9200
main:
allow-bean-definition-overriding: true
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
## 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.10.137:3306/know_sub?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&serverTimezone=GMT%2B8
username: root
password: '123456'
initial-size: 5 # 初始化大小
min-idle: 10 # 最小连接数
max-active: 20 # 最大连接数
max-wait: 60000 # 获取连接时的最大等待时间
min-evictable-idle-time-millis: 300000 # 一个连接在池中最小生存的时间,单位是毫秒
time-between-eviction-runs-millis: 60000 # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒
filters: stat,wall # 配置扩展插件stat-监控统计log4j-日志wall-防火墙防止SQL注入去掉后监控界面的sql无法统计
validation-query: SELECT 1 # 检测连接是否有效的 SQL语句为空时以下三个配置均无效
test-on-borrow: true # 申请连接时执行validationQuery检测连接是否有效默认true开启后会降低性能
test-on-return: true # 归还连接时执行validationQuery检测连接是否有效默认false开启后会降低性能
test-while-idle: true # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis执行validationQuery检测连接是否有效默认false建议开启不影响性能
stat-view-servlet:
enabled: true # 是否开启 StatViewServlet
loginUsername: admin
loginPassword: 123456
filter:
stat:
enabled: true # 是否开启 FilterStat默认true
log-slow-sql: true # 是否开启 慢SQL 记录默认false
slow-sql-millis: 5000 # 慢 SQL 的标准,默认 3000单位毫秒
merge-sql: false # 合并多个连接池的监控数据默认false
mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# springdoc-openapi项目配置
springdoc:
# 默认是false需要设置为true 解决GET请求时,用自定义对象接受现实错误的问题
default-flat-param-object: true
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
paths-to-match: '/**'
packages-to-scan: com.supervision
# knife4j的增强配置不需要增强可以不配
knife4j:
enable: true
setting:
language: zh_cn
user:
# 默认密码
default:
password: 123456
#spring:
# elasticsearch:
# uris: http://192.168.10.137:9200
embedding:
url: http://192.168.10.137:8711/embeddings/
vector:
redis:
uri: redis://:123456@192.168.10.137:6380
indexName: 'know-sub-rag-store'
prefix: 'know-sub-rag-store:'

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>com.supervision</groupId>
<artifactId>know_sub</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>know_sub_model</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>${mybatis-puls-spring-boot.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations-jakarta</artifactId>
<version>2.2.19</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

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

Loading…
Cancel
Save