Compare commits
211 Commits
mentat-631
...
feature/io
Author | SHA1 | Date | |
---|---|---|---|
![]() |
db9c485285 | ||
![]() |
9841c869a2 | ||
![]() |
a8c87d168a | ||
![]() |
9b9fd30c90 | ||
![]() |
3a2c691af0 | ||
![]() |
ce919d12d1 | ||
![]() |
89fb71e857 | ||
![]() |
9b30d5d355 | ||
![]() |
e3dcea9cb3 | ||
![]() |
d7b8cf547f | ||
![]() |
624f5283b3 | ||
![]() |
3dafd31da6 | ||
![]() |
8c84ac9d8a | ||
![]() |
88088c7987 | ||
![]() |
7b5aa23d5c | ||
![]() |
ea8dd67e9e | ||
![]() |
61a0c05279 | ||
![]() |
05c5482715 | ||
![]() |
6a35ca7290 | ||
![]() |
5a456a95e7 | ||
![]() |
1995c322e7 | ||
![]() |
1719b69ef7 | ||
![]() |
643e289384 | ||
![]() |
6b9cca0b79 | ||
![]() |
bd18e73052 | ||
![]() |
d8d37d1bb9 | ||
![]() |
9658ed1a0d | ||
![]() |
e4ef1c8190 | ||
![]() |
edc6a8ad4a | ||
![]() |
c0e2bdbdd4 | ||
![]() |
2932314ee0 | ||
![]() |
84bc5aec1e | ||
![]() |
07b3ac20f6 | ||
![]() |
64fefaa630 | ||
![]() |
061819f25b | ||
![]() |
1f8576f643 | ||
![]() |
9e77692414 | ||
![]() |
18e789d4fb | ||
![]() |
1aef8515e2 | ||
![]() |
a83ce3b667 | ||
![]() |
1e69face92 | ||
![]() |
7c79aae2b4 | ||
![]() |
10334f3fb6 | ||
![]() |
c7b1cc9a43 | ||
![]() |
74492d65f0 | ||
![]() |
75ed4486c4 | ||
![]() |
840cfad84a | ||
![]() |
037ab39ac7 | ||
![]() |
30fd7996f6 | ||
![]() |
2759a32331 | ||
![]() |
54956fcbb9 | ||
![]() |
f7b62b4bcc | ||
![]() |
2f9d9723b3 | ||
![]() |
609cc71930 | ||
![]() |
12ce87b305 | ||
![]() |
c8ebad91dd | ||
![]() |
73a7ccbd75 | ||
![]() |
6d00b02795 | ||
![]() |
39a6eb4792 | ||
![]() |
efd0a86007 | ||
![]() |
c935312bf8 | ||
![]() |
819323d3db | ||
![]() |
15f46db7ac | ||
![]() |
ae9ff74e23 | ||
![]() |
b8c653d18b | ||
![]() |
acf0e401d3 | ||
![]() |
5692571a9c | ||
![]() |
bb7e56e28e | ||
![]() |
d3f28b92a7 | ||
![]() |
9fbc953dd1 | ||
![]() |
e5453028f1 | ||
![]() |
f3dd628aba | ||
![]() |
79cb96702a | ||
![]() |
1bf7fd39fc | ||
![]() |
fdaf5e50ca | ||
![]() |
0ce0c3f3d2 | ||
![]() |
d1fc18a409 | ||
![]() |
39f71168eb | ||
![]() |
eaeeb34e74 | ||
![]() |
ebf5693255 | ||
![]() |
ae26ca5d00 | ||
![]() |
98e6124c2f | ||
![]() |
0ddee90366 | ||
![]() |
81e3866665 | ||
![]() |
5ea3e5db0d | ||
![]() |
87adf15a93 | ||
![]() |
2578ca7311 | ||
![]() |
059f64acb0 | ||
![]() |
34231bc5f8 | ||
![]() |
e30795fb69 | ||
![]() |
261011d1a8 | ||
![]() |
56ae4503a6 | ||
![]() |
424922b488 | ||
![]() |
a677e98de0 | ||
![]() |
f1dd7999db | ||
![]() |
476101189e | ||
![]() |
4968590685 | ||
![]() |
f00b3005c7 | ||
![]() |
d6ecc032c2 | ||
![]() |
d745a1832d | ||
![]() |
39ec137047 | ||
![]() |
e5f439aecd | ||
![]() |
86a413f57d | ||
![]() |
a4228b927b | ||
![]() |
88cc4c987b | ||
![]() |
69d1a70900 | ||
![]() |
d26ef6b89e | ||
![]() |
96fb953730 | ||
![]() |
806c828bb5 | ||
![]() |
d60374d646 | ||
![]() |
7a7ca4293c | ||
![]() |
3e66a922bf | ||
![]() |
e0d9f7cfba | ||
![]() |
4208339d4d | ||
![]() |
7d53a6dd52 | ||
![]() |
abf5a22cd0 | ||
![]() |
f97fb0a8fe | ||
![]() |
024109dac9 | ||
![]() |
ed2296e4c7 | ||
![]() |
10c0b86f9b | ||
![]() |
cccad2c6c1 | ||
![]() |
c4943e97c7 | ||
![]() |
1c1abae5bb | ||
![]() |
63fcc69930 | ||
![]() |
710f29d911 | ||
![]() |
4d6ea0043f | ||
![]() |
841ad5875c | ||
![]() |
4868ef795c | ||
![]() |
31f28c0419 | ||
![]() |
65b8410cd8 | ||
![]() |
1e4cc953d3 | ||
![]() |
4f7ac969fe | ||
![]() |
9d26381dcc | ||
![]() |
ee9a733c72 | ||
![]() |
9bb231eb73 | ||
![]() |
456b54d4cb | ||
![]() |
d4e4207ae9 | ||
![]() |
45a4108138 | ||
![]() |
0f51229954 | ||
![]() |
7e2498d417 | ||
![]() |
7384b5c3f6 | ||
![]() |
02562cb77d | ||
![]() |
4e1d7d0877 | ||
![]() |
f5706972a0 | ||
![]() |
4c2ed461d4 | ||
![]() |
e36671255a | ||
![]() |
427cf8e4f6 | ||
![]() |
94effa87a3 | ||
![]() |
76f0bd816c | ||
![]() |
8de0de615f | ||
![]() |
32e25cf4a2 | ||
![]() |
96bffc4199 | ||
![]() |
9b2ec3d341 | ||
![]() |
d6e491937c | ||
![]() |
69695b1189 | ||
![]() |
2b681f90ca | ||
![]() |
e6afd28f01 | ||
![]() |
aff0446a38 | ||
![]() |
91240351ed | ||
![]() |
5c3a960403 | ||
![]() |
12a80ca4b8 | ||
![]() |
a6670f3870 | ||
![]() |
b353aa8508 | ||
![]() |
6cceab5ba4 | ||
![]() |
11a6e8ebf7 | ||
![]() |
0db165f6d9 | ||
![]() |
2d29bf4e6f | ||
![]() |
c7ccb8286a | ||
![]() |
a685402688 | ||
![]() |
a5f82fedb3 | ||
![]() |
5b7e637ebf | ||
![]() |
8cce737523 | ||
![]() |
e850fbf675 | ||
![]() |
b632726a69 | ||
![]() |
126aa1b40a | ||
![]() |
1dadfb8fba | ||
![]() |
6eb40aa544 | ||
![]() |
6a80d7c75f | ||
![]() |
7f70b1fe94 | ||
![]() |
cd101ec7fc | ||
![]() |
d2c7ec2445 | ||
![]() |
36a828866b | ||
![]() |
86a4748140 | ||
![]() |
efc5ea23bf | ||
![]() |
238f603f69 | ||
![]() |
d3a4c3c718 | ||
![]() |
8e54eef8af | ||
![]() |
b4af042c64 | ||
![]() |
c2a50c4d9c | ||
![]() |
5f6bcc4a35 | ||
![]() |
973ff1bbb9 | ||
![]() |
8bd0519cf3 | ||
![]() |
9af286693f | ||
![]() |
5d5d5c33f5 | ||
![]() |
8242735d84 | ||
![]() |
7288e6c980 | ||
![]() |
83d86bcf9b | ||
![]() |
7c9714d014 | ||
![]() |
5bdc2db0c3 | ||
![]() |
83bd96d672 | ||
![]() |
fa585578a0 | ||
![]() |
387ef6f396 | ||
![]() |
b453856864 | ||
![]() |
f8d1fa9b49 | ||
![]() |
3f01ba7538 | ||
![]() |
b47176c96e | ||
![]() |
d698ef70b5 | ||
![]() |
2a984504d9 | ||
![]() |
cb59a61a04 | ||
![]() |
ef4fb7ec05 | ||
![]() |
6b69dd74d4 |
28
README.md
28
README.md
@@ -1,7 +1,7 @@
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/Spring%20Boot-2.7.18-blue.svg" alt="Downloads">
|
||||
<img src="https://img.shields.io/badge/Spring%20Boot-3.3.1-blue.svg" alt="Downloads">
|
||||
<img src="https://img.shields.io/badge/Vue-3.2-blue.svg" alt="Downloads">
|
||||
<img src="https://img.shields.io/github/license/YunaiV/ruoyi-vue-pro"/>
|
||||
<img src="https://img.shields.io/github/license/YunaiV/ruoyi-vue-pro" alt="Downloads" />
|
||||
</p>
|
||||
|
||||
**严肃声明:现在、未来都不会有商业版本,所有代码全部开源!!**
|
||||
@@ -281,26 +281,26 @@
|
||||
|
||||
| 框架 | 说明 | 版本 | 学习指南 |
|
||||
|---------------------------------------------------------------------------------------------|------------------|----------------|----------------------------------------------------------------|
|
||||
| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.7.18 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
|
||||
| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 3.3.1 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
|
||||
| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | |
|
||||
| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.23 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||
| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.7 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
|
||||
| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.6.1 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||
| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 4.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||
| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 /7.0 | |
|
||||
| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.32.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
|
||||
| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
|
||||
| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.7.11 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
|
||||
| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.5 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
|
||||
| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.8.0 | [文档](https://doc.iocoder.cn/bpm/) |
|
||||
| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 6.1.10 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
|
||||
| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 6.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
|
||||
| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 8.0.1 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
|
||||
| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 7.0.0 | [文档](https://doc.iocoder.cn/bpm/) |
|
||||
| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |
|
||||
| [Springdoc](https://springdoc.org/) | Swagger 文档 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
|
||||
| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.12.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
|
||||
| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.10 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
||||
| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.5 | |
|
||||
| [Springdoc](https://springdoc.org/) | Swagger 文档 | 2.3.0 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
|
||||
| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 9.0.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
|
||||
| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 3.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
||||
| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.17.1 | |
|
||||
| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.5.5.Final | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
|
||||
| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.34 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
|
||||
| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |
|
||||
| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.0 | - |
|
||||
| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.10.1 | - |
|
||||
| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 5.7.0 | - |
|
||||
|
||||
## 🐷 演示图
|
||||
|
||||
|
16
pom.xml
16
pom.xml
@@ -15,7 +15,7 @@
|
||||
<!-- 各种 module 拓展 -->
|
||||
<module>yudao-module-system</module>
|
||||
<module>yudao-module-infra</module>
|
||||
<!-- <module>yudao-module-member</module>-->
|
||||
<!-- <module>yudao-module-member</module>-->
|
||||
<!-- <module>yudao-module-bpm</module>-->
|
||||
<!-- <module>yudao-module-report</module>-->
|
||||
<!-- <module>yudao-module-mp</module>-->
|
||||
@@ -24,6 +24,7 @@
|
||||
<!-- <module>yudao-module-crm</module>-->
|
||||
<!-- <module>yudao-module-erp</module>-->
|
||||
<!-- <module>yudao-module-ai</module>-->
|
||||
<module>yudao-module-iot</module>
|
||||
</modules>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
@@ -31,17 +32,17 @@
|
||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||
|
||||
<properties>
|
||||
<revision>2.2.0-jdk8-snapshot</revision>
|
||||
<revision>2.2.0-snapshot</revision>
|
||||
<!-- Maven 相关 -->
|
||||
<java.version>1.8</java.version>
|
||||
<java.version>17</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
|
||||
<maven-surefire-plugin.version>3.2.2</maven-surefire-plugin.version>
|
||||
<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
|
||||
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
|
||||
<!-- 看看咋放到 bom 里 -->
|
||||
<lombok.version>1.18.34</lombok.version>
|
||||
<spring.boot.version>2.7.18</spring.boot.version>
|
||||
<spring.boot.version>3.3.1</spring.boot.version>
|
||||
<mapstruct.version>1.5.5.Final</mapstruct.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
@@ -92,6 +93,11 @@
|
||||
<version>${mapstruct.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<!-- 编译参数写在 arg 内,解决 Spring Boot 3.2 的 Parameter Name Discovery 问题 -->
|
||||
<debug>false</debug>
|
||||
<compilerArgs>
|
||||
<arg>-parameters</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
@@ -50,7 +50,7 @@ services:
|
||||
--spring.datasource.dynamic.datasource.slave.url=${SLAVE_DATASOURCE_URL:-jdbc:mysql://yudao-mysql:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true}
|
||||
--spring.datasource.dynamic.datasource.slave.username=${SLAVE_DATASOURCE_USERNAME:-root}
|
||||
--spring.datasource.dynamic.datasource.slave.password=${SLAVE_DATASOURCE_PASSWORD:-123456}
|
||||
--spring.redis.host=${REDIS_HOST:-yudao-redis}
|
||||
--spring.data.redis.host=${REDIS_HOST:-yudao-redis}
|
||||
depends_on:
|
||||
- mysql
|
||||
- redis
|
||||
|
@@ -11,7 +11,7 @@
|
||||
Target Server Version : 80200 (8.2.0)
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 28/07/2024 23:20:28
|
||||
Date: 31/08/2024 09:22:45
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
@@ -62,7 +62,7 @@ COMMIT;
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `infra_api_error_log`;
|
||||
CREATE TABLE `infra_api_error_log` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`trace_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '链路追踪编号',
|
||||
`user_id` int NOT NULL DEFAULT 0 COMMENT '用户编号',
|
||||
`user_type` tinyint NOT NULL DEFAULT 0 COMMENT '用户类型',
|
||||
@@ -91,7 +91,7 @@ CREATE TABLE `infra_api_error_log` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 19166 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 20014 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_api_error_log
|
||||
@@ -128,7 +128,7 @@ CREATE TABLE `infra_codegen_column` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2470 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2483 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_codegen_column
|
||||
@@ -166,7 +166,7 @@ CREATE TABLE `infra_codegen_table` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 186 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 187 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_codegen_table
|
||||
@@ -179,7 +179,7 @@ COMMIT;
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `infra_config`;
|
||||
CREATE TABLE `infra_config` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '参数主键',
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '参数主键',
|
||||
`category` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '参数分组',
|
||||
`type` tinyint NOT NULL COMMENT '参数类型',
|
||||
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '参数名称',
|
||||
@@ -250,7 +250,7 @@ CREATE TABLE `infra_file` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1447 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1472 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_file
|
||||
@@ -438,7 +438,7 @@ CREATE TABLE `system_dict_data` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1588 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1592 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_dict_data
|
||||
@@ -858,6 +858,10 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1585, 2, '回复', '2', 'ai_write_type', 0, '', '', '', '1', '2024-07-10 21:26:06', '1', '2024-07-10 21:26:06', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1586, 2, '腾讯云', 'TENCENT', 'system_sms_channel_code', 0, '', '', '', '1', '2024-07-22 22:23:16', '1', '2024-07-22 22:23:16', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1587, 3, '华为云', 'HUAWEI', 'system_sms_channel_code', 0, '', '', '', '1', '2024-07-22 22:23:46', '1', '2024-07-22 22:23:53', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1588, 1, 'OpenAI 微软', 'AzureOpenAI', 'ai_platform', 0, '', '', '', '1', '2024-08-10 14:07:41', '1', '2024-08-10 14:07:41', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1589, 10, 'BPMN 设计器', '10', 'bpm_model_type', 0, 'primary', '', '', '1', '2024-08-26 15:22:17', '1', '2024-08-26 16:46:02', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1590, 20, 'SIMPLE 设计器', '20', 'bpm_model_type', 0, 'success', '', '', '1', '2024-08-26 15:22:27', '1', '2024-08-26 16:45:58', b'0');
|
||||
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1591, 4, '七牛云', 'QINIU', 'system_sms_channel_code', 0, '', '', '', '1', '2024-08-31 08:45:03', '1', '2024-08-31 08:45:24', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@@ -877,7 +881,7 @@ CREATE TABLE `system_dict_type` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 629 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 630 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_dict_type
|
||||
@@ -975,6 +979,7 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (626, '写作长度', 'ai_write_length', 0, '', '1', '2024-07-07 15:18:41', '1', '2024-07-07 15:18:41', b'0', '1970-01-01 00:00:00');
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (627, '写作格式', 'ai_write_format', 0, '', '1', '2024-07-07 15:14:34', '1', '2024-07-07 15:14:34', b'0', '1970-01-01 00:00:00');
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (628, 'AI 写作类型', 'ai_write_type', 0, '', '1', '2024-07-10 21:25:29', '1', '2024-07-10 21:25:29', b'0', '1970-01-01 00:00:00');
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (629, 'BPM 流程模型类型', 'bpm_model_type', 0, '', '1', '2024-08-26 15:21:43', '1', '2024-08-26 15:21:43', b'0', '1970-01-01 00:00:00');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@@ -998,7 +1003,7 @@ CREATE TABLE `system_login_log` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 3261 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 3289 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_login_log
|
||||
@@ -1129,7 +1134,7 @@ CREATE TABLE `system_menu` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2798 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2808 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_menu
|
||||
@@ -1293,7 +1298,6 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1193, '流程模型', '', 2, 1, 1186, 'model', 'fa-solid:project-diagram', 'bpm/model/index', 'BpmModel', 0, b'1', b'1', b'1', '1', '2021-12-31 23:24:58', '1', '2024-03-19 12:25:19', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1194, '模型查询', 'bpm:model:query', 3, 1, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-03 19:01:10', '1', '2022-04-20 17:03:10', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1195, '模型创建', 'bpm:model:create', 3, 2, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-03 19:01:24', '1', '2022-04-20 17:03:10', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1196, '模型导入', 'bpm:model:import', 3, 3, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-03 19:01:35', '1', '2022-04-20 17:03:10', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1197, '模型更新', 'bpm:model:update', 3, 4, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-03 19:02:28', '1', '2022-04-20 17:03:10', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1198, '模型删除', 'bpm:model:delete', 3, 5, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-03 19:02:43', '1', '2022-04-20 17:03:10', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1199, '模型发布', 'bpm:model:deploy', 3, 6, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-03 19:03:24', '1', '2022-04-20 17:03:10', b'0');
|
||||
@@ -1952,7 +1956,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2784, '绘画管理', '', 2, 11, 2760, 'image', 'fa:file-image-o', 'ai/image/manager/index.vue', 'AiImageManager', 0, b'1', b'1', b'1', '', '2024-06-26 13:32:31', '1', '2024-06-26 21:37:13', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2785, '绘画查询', 'ai:image:query', 3, 1, 2784, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-06-26 13:32:31', '1', '2024-06-26 22:21:57', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2786, '绘画删除', 'ai:image:delete', 3, 4, 2784, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-06-26 13:32:31', '1', '2024-06-26 22:22:08', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2787, '会话更新公开状态', 'ai:image:update-public-status', 3, 2, 2784, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-06-26 22:47:56', '1', '2024-06-26 22:47:56', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2787, '绘图更新', 'ai:image:update', 3, 2, 2784, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-06-26 22:47:56', '1', '2024-08-31 09:21:35', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2788, '音乐管理', '', 2, 12, 2760, 'music', 'fa:music', 'ai/music/manager/index.vue', 'AiMusicManager', 0, b'1', b'1', b'1', '', '2024-06-27 15:03:33', '1', '2024-06-27 23:04:19', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2789, '音乐查询', 'ai:music:query', 3, 1, 2788, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-06-27 15:03:33', '', '2024-06-27 15:03:33', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2790, '音乐更新', 'ai:music:update', 3, 3, 2788, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-06-27 15:03:33', '', '2024-06-27 15:03:33', b'0');
|
||||
@@ -1961,8 +1965,18 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2793, '写作管理', '', 2, 13, 2760, 'write', 'fa:bookmark-o', 'ai/write/manager/index.vue', 'AiWriteManager', 0, b'1', b'1', b'1', '', '2024-07-10 13:24:34', '1', '2024-07-10 21:31:59', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2794, 'AI 写作查询', 'ai:write:query', 3, 1, 2793, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-07-10 13:24:34', '', '2024-07-10 13:24:34', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2795, 'AI 写作删除', 'ai:write:delete', 3, 4, 2793, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-07-10 13:24:34', '', '2024-07-10 13:24:34', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2796, 'AI 音乐', '', 2, 4, 2758, 'music', 'fa:music', 'ai/music/index/index.vue', 'AiMusic', 0, b'1', b'1', b'1', '1', '2024-07-17 09:21:12', '1', '2024-07-17 09:36:12', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2796, 'AI 音乐', '', 2, 4, 2758, 'music', 'fa:music', 'ai/music/index/index.vue', 'AiMusic', 0, b'1', b'1', b'1', '1', '2024-07-17 09:21:12', '1', '2024-07-29 21:11:52', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2797, '客服中心', '', 2, 100, 2362, 'kefu', 'fa-solid:user-alt', 'mall/promotion/kefu/index', 'KeFu', 0, b'1', b'1', b'1', '1', '2024-07-17 23:49:05', '1', '2024-07-17 23:49:16', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2798, 'AI 思维导图', '', 2, 5, 2758, 'mind-map', 'fa:sitemap', 'ai/mindmap/index/index.vue', 'AiMindMap', 0, b'1', b'1', b'1', '1', '2024-07-29 21:31:59', '1', '2024-07-29 21:33:20', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2799, '导图管理', '', 2, 14, 2760, 'mind-map', 'fa:map', 'ai/mindmap/manager/index', 'AiMindMapManager', 0, b'1', b'1', b'1', '', '2024-08-10 09:15:09', '1', '2024-08-10 17:24:28', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2800, '思维导图查询', 'ai:mind-map:query', 3, 1, 2799, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-08-10 09:15:09', '', '2024-08-10 09:15:09', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2801, '思维导图删除', 'ai:mind-map:delete', 3, 4, 2799, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-08-10 09:15:09', '', '2024-08-10 09:15:09', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2802, '会话查询', 'promotion:kefu-conversation:query', 3, 1, 2797, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-08-31 09:17:52', '1', '2024-08-31 09:18:52', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2803, '会话更新', 'promotion:kefu-conversation:update', 3, 2, 2797, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-08-31 09:18:15', '1', '2024-08-31 09:19:29', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2804, '消息查询', 'promotion:kefu-message:query', 3, 10, 2797, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-08-31 09:18:42', '1', '2024-08-31 09:18:42', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2805, '会话删除', 'promotion:kefu-conversation:delete', 3, 3, 2797, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-08-31 09:19:51', '1', '2024-08-31 09:20:32', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2806, '消息发送', 'promotion:kefu-message:send', 3, 12, 2797, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-08-31 09:20:06', '1', '2024-08-31 09:20:06', b'0');
|
||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2807, '消息更新', 'promotion:kefu-message:update', 3, 11, 2797, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-08-31 09:20:22', '1', '2024-08-31 09:20:22', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@@ -2084,7 +2098,7 @@ CREATE TABLE `system_oauth2_access_token` (
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_access_token`(`access_token` ASC) USING BTREE,
|
||||
INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 8784 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 9563 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_oauth2_access_token
|
||||
@@ -2206,7 +2220,7 @@ CREATE TABLE `system_oauth2_refresh_token` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1598 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1620 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_oauth2_refresh_token
|
||||
@@ -2239,7 +2253,7 @@ CREATE TABLE `system_operate_log` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 9053 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录 V2 版本';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 9056 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录 V2 版本';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_operate_log
|
||||
@@ -2298,7 +2312,7 @@ CREATE TABLE `system_role` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 153 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色信息表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 154 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色信息表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_role
|
||||
@@ -2307,9 +2321,10 @@ BEGIN;
|
||||
INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, '超级管理员', 'super_admin', 1, 1, '', 0, 1, '超级管理员', 'admin', '2021-01-05 17:03:48', '', '2022-02-22 05:08:21', b'0', 1);
|
||||
INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, '普通角色', 'common', 2, 2, '', 0, 1, '普通角色', 'admin', '2021-01-05 17:03:48', '', '2022-02-22 05:08:20', b'0', 1);
|
||||
INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3, 'CRM 管理员', 'crm_admin', 2, 1, '', 0, 1, 'CRM 专属角色', '1', '2024-02-24 10:51:13', '1', '2024-02-24 02:51:32', b'0', 1);
|
||||
INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (101, '测试账号', 'test', 0, 2, '[105,106,107]', 0, 2, '', '', '2021-01-06 13:49:35', '1', '2024-07-27 23:30:47', b'0', 1);
|
||||
INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (101, '测试账号', 'test', 0, 1, '[]', 0, 2, '', '', '2021-01-06 13:49:35', '1', '2024-08-11 10:41:10', b'0', 1);
|
||||
INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (109, '租户管理员', 'tenant_admin', 0, 1, '', 0, 1, '系统自动生成', '1', '2022-02-22 00:56:14', '1', '2022-02-22 00:56:14', b'0', 121);
|
||||
INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (111, '租户管理员', 'tenant_admin', 0, 1, '', 0, 1, '系统自动生成', '1', '2022-03-07 21:37:58', '1', '2022-03-07 21:37:58', b'0', 122);
|
||||
INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (153, '某角色', 'tt', 4, 1, '', 0, 2, '', '1', '2024-08-17 14:09:35', '1', '2024-08-17 14:09:35', b'0', 1);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@@ -2390,7 +2405,6 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1623, 101, 1193, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1624, 101, 1194, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1625, 101, 1195, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1626, 101, 1196, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1627, 101, 1197, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1628, 101, 1198, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1629, 101, 1199, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', b'0', 1);
|
||||
@@ -3195,9 +3209,8 @@ CREATE TABLE `system_sms_channel` (
|
||||
-- Records of system_sms_channel
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `system_sms_channel` (`id`, `signature`, `code`, `status`, `remark`, `api_key`, `api_secret`, `callback_url`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 'Ballcat', 'ALIYUN', 0, '你要改哦,只有我可以用!!!!', 'LTAI5tCnKso2uG3kJ5gRav88', 'fGJ5SNXL7P1NHNRmJ7DJaMJGPyE55C', NULL, '', '2021-03-31 11:53:10', '1', '2023-12-02 22:10:17', b'0');
|
||||
INSERT INTO `system_sms_channel` (`id`, `signature`, `code`, `status`, `remark`, `api_key`, `api_secret`, `callback_url`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 'Ballcat', 'ALIYUN', 0, '你要改哦,只有我可以用!!!!', 'LTAI5tCnKso2uG3kJ5gRav88', 'fGJ5SNXL7P1NHNRmJ7DJaMJGPyE55C', NULL, '', '2021-03-31 11:53:10', '1', '2024-08-04 08:53:26', b'0');
|
||||
INSERT INTO `system_sms_channel` (`id`, `signature`, `code`, `status`, `remark`, `api_key`, `api_secret`, `callback_url`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (4, '测试渠道', 'DEBUG_DING_TALK', 0, '123', '696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859', 'SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67', NULL, '1', '2021-04-13 00:23:14', '1', '2022-03-27 20:29:49', b'0');
|
||||
INSERT INTO `system_sms_channel` (`id`, `signature`, `code`, `status`, `remark`, `api_key`, `api_secret`, `callback_url`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (6, '测试演示', 'DEBUG_DING_TALK', 0, '仅测试', '696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859', 'SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67', NULL, '1', '2022-04-10 23:07:59', '1', '2023-12-02 22:10:08', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@@ -3222,7 +3235,7 @@ CREATE TABLE `system_sms_code` (
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号'
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 628 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 632 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_sms_code
|
||||
@@ -3263,7 +3276,7 @@ CREATE TABLE `system_sms_log` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 987 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1088 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_sms_log
|
||||
@@ -3293,24 +3306,25 @@ CREATE TABLE `system_sms_template` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信模板';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信模板';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_sms_template
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 1, 0, 'test_01', '测试验证码短信', '正在进行登录操作{operation},您的验证码是{code}', '[\"operation\",\"code\"]', '测试备注', '4383920', 6, 'DEBUG_DING_TALK', '', '2021-03-31 10:49:38', '1', '2023-12-02 22:32:47', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 1, 0, 'test_01', '测试验证码短信', '正在进行登录操作{operation},您的验证码是{code}', '[\"operation\",\"code\"]', '测试备注', '4383920', 4, 'DEBUG_DING_TALK', '', '2021-03-31 10:49:38', '1', '2024-08-18 11:57:18', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3, 1, 0, 'test_02', '公告通知', '您的验证码{code},该验证码5分钟内有效,请勿泄漏于他人!', '[\"code\"]', NULL, 'SMS_207945135', 2, 'ALIYUN', '', '2021-03-31 11:56:30', '1', '2021-04-10 01:22:02', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (6, 3, 0, 'test-01', '测试模板', '哈哈哈 {name}', '[\"name\"]', 'f哈哈哈', '4383920', 6, 'DEBUG_DING_TALK', '1', '2021-04-10 01:07:21', '1', '2022-12-10 21:26:09', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (6, 3, 0, 'test-01', '测试模板', '哈哈哈 {name}', '[\"name\"]', 'f哈哈哈', '4383920', 4, 'DEBUG_DING_TALK', '1', '2021-04-10 01:07:21', '1', '2024-08-18 11:57:07', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (7, 3, 0, 'test-04', '测试下', '老鸡{name},牛逼{code}', '[\"name\",\"code\"]', '哈哈哈哈', 'suibian', 4, 'DEBUG_DING_TALK', '1', '2021-04-13 00:29:53', '1', '2023-12-02 22:35:34', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (8, 1, 0, 'user-sms-login', '前台用户短信登录', '您的验证码是{code}', '[\"code\"]', NULL, '4372216', 6, 'DEBUG_DING_TALK', '1', '2021-10-11 08:10:00', '1', '2022-12-10 21:25:59', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (8, 1, 0, 'user-sms-login', '前台用户短信登录', '您的验证码是{code}', '[\"code\"]', NULL, '4372216', 4, 'DEBUG_DING_TALK', '1', '2021-10-11 08:10:00', '1', '2024-08-18 11:57:06', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (9, 2, 0, 'bpm_task_assigned', '【工作流】任务被分配', '您收到了一条新的待办任务:{processInstanceName}-{taskName},申请人:{startUserNickname},处理链接:{detailUrl}', '[\"processInstanceName\",\"taskName\",\"startUserNickname\",\"detailUrl\"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2022-01-21 22:31:19', '1', '2022-01-22 00:03:36', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (10, 2, 0, 'bpm_process_instance_reject', '【工作流】流程被不通过', '您的流程被审批不通过:{processInstanceName},原因:{reason},查看链接:{detailUrl}', '[\"processInstanceName\",\"reason\",\"detailUrl\"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2022-01-22 00:03:31', '1', '2022-05-01 12:33:14', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (11, 2, 0, 'bpm_process_instance_approve', '【工作流】流程被通过', '您的流程被审批通过:{processInstanceName},查看链接:{detailUrl}', '[\"processInstanceName\",\"detailUrl\"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2022-01-22 00:04:31', '1', '2022-03-27 20:32:21', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (12, 2, 0, 'demo', '演示模板', '我就是测试一下下', '[]', NULL, 'biubiubiu', 6, 'DEBUG_DING_TALK', '1', '2022-04-10 23:22:49', '1', '2023-03-24 23:45:07', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (12, 2, 0, 'demo', '演示模板', '我就是测试一下下', '[]', NULL, 'biubiubiu', 4, 'DEBUG_DING_TALK', '1', '2022-04-10 23:22:49', '1', '2024-08-18 11:57:04', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (14, 1, 0, 'user-update-mobile', '会员用户 - 修改手机', '您的验证码{code},该验证码 5 分钟内有效,请勿泄漏于他人!', '[\"code\"]', '', 'null', 4, 'DEBUG_DING_TALK', '1', '2023-08-19 18:58:01', '1', '2023-08-19 11:34:04', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (15, 1, 0, 'user-update-password', '会员用户 - 修改密码', '您的验证码{code},该验证码 5 分钟内有效,请勿泄漏于他人!', '[\"code\"]', '', 'null', 4, 'DEBUG_DING_TALK', '1', '2023-08-19 18:58:01', '1', '2023-08-19 11:34:18', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (16, 1, 0, 'user-reset-password', '会员用户 - 重置密码', '您的验证码{code},该验证码 5 分钟内有效,请勿泄漏于他人!', '[\"code\"]', '', 'null', 4, 'DEBUG_DING_TALK', '1', '2023-08-19 18:58:01', '1', '2023-12-02 22:35:27', b'0');
|
||||
INSERT INTO `system_sms_template` (`id`, `type`, `status`, `code`, `name`, `content`, `params`, `remark`, `api_template_id`, `channel_id`, `channel_code`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (17, 2, 0, 'bpm_task_timeout', '【工作流】任务审批超时', '您收到了一条超时的待办任务:{processInstanceName}-{taskName},处理链接:{detailUrl}', '[\"processInstanceName\",\"taskName\",\"detailUrl\"]', '', 'X', 4, 'DEBUG_DING_TALK', '1', '2024-08-16 21:59:15', '1', '2024-08-16 21:59:34', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@@ -3367,7 +3381,7 @@ CREATE TABLE `system_social_user` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 36 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 37 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_social_user
|
||||
@@ -3392,7 +3406,7 @@ CREATE TABLE `system_social_user_bind` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 119 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 120 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_social_user_bind
|
||||
@@ -3559,10 +3573,10 @@ CREATE TABLE `system_users` (
|
||||
-- Records of system_users
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1,2]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/bf2002b38950c904243be7c825d3f82e29f25a44526583c3fde2ebdff3a87f75.png', 0, '0:0:0:0:0:0:0:1', '2024-07-28 11:35:00', 'admin', '2021-01-05 17:03:47', NULL, '2024-07-28 11:35:00', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '0:0:0:0:0:0:0:1', '2024-03-18 21:09:04', '', '2021-01-13 23:50:35', NULL, '2024-03-18 21:09:04', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$04$jDFLttgfik0QqJKAbfhMa.2A9xXoZmAIxakdFJUzkX.MgBKT6ddo6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-07-13 23:13:16', '', '2021-01-21 02:13:53', NULL, '2024-07-13 23:13:16', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1,2]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/bf2002b38950c904243be7c825d3f82e29f25a44526583c3fde2ebdff3a87f75.png', 0, '0:0:0:0:0:0:0:1', '2024-08-26 16:54:00', 'admin', '2021-01-05 17:03:47', NULL, '2024-08-26 16:54:00', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 0, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', '1', '2024-08-17 11:06:13', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$04$fUBSmjKCPYAUmnMzOb6qE.eZCGPhHi1JmAKclODbfS/O7fHOl2bH6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '0:0:0:0:0:0:0:1', '2024-08-11 17:48:12', '', '2021-01-13 23:50:35', NULL, '2024-08-11 17:48:12', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$04$jDFLttgfik0QqJKAbfhMa.2A9xXoZmAIxakdFJUzkX.MgBKT6ddo6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-08-11 09:38:08', '', '2021-01-21 02:13:53', NULL, '2024-08-11 09:38:08', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (107, 'admin107', '$2a$10$dYOOBKMO93v/.ReCqzyFg.o67Tqk.bbc2bhrpyBGkIw9aypCtr2pm', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '', NULL, '1', '2022-02-20 22:59:33', '1', '2022-02-27 08:26:51', b'0', 118);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (108, 'admin108', '$2a$10$y6mfvKoNYL1GXWak8nYwVOH.kCWqjactkzdoIDgiKl93WN3Ejg.Lu', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '', NULL, '1', '2022-02-20 23:00:50', '1', '2022-02-27 08:26:53', b'0', 119);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (109, 'admin109', '$2a$10$JAqvH0tEc0I7dfDVBI7zyuB4E3j.uH6daIjV53.vUS6PknFkDJkuK', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '', NULL, '1', '2022-02-20 23:11:50', '1', '2022-02-27 08:26:56', b'0', 120);
|
||||
@@ -3572,7 +3586,7 @@ INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`,
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (113, 'aoteman', '$2a$10$0acJOIk2D25/oC87nyclE..0lzeu9DtQ/n3geP4fkun/zIVRhHJIO', '芋道', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '127.0.0.1', '2022-03-19 18:38:51', '1', '2022-03-07 21:37:58', NULL, '2022-03-19 18:38:51', b'0', 122);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (114, 'hrmgr', '$2a$10$TR4eybBioGRhBmDBWkqWLO6NIh3mzYa8KBKDDB5woiGYFVlRAi.fu', 'hr 小姐姐', NULL, NULL, '[5]', '', '15601691236', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-03-24 22:21:05', '1', '2022-03-19 21:50:58', NULL, '2024-03-24 22:21:05', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (115, 'aotemane', '$2a$04$GcyP0Vyzb2F2Yni5PuIK9ueGxM0tkZGMtDwVRwrNbtMvorzbpNsV2', '阿呆', '11222', 102, '[1,2]', '7648@qq.com', '15601691229', 2, '', 0, '', NULL, '1', '2022-04-30 02:55:43', '1', '2024-04-04 09:37:14', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (117, 'admin123', '$2a$10$WI8Gg/lpZQIrOEZMHqka7OdFaD4Nx.B/qY8ZGTTUKrOJwaHFqibaC', '测试号', '1111', 100, '[2]', '', '15601691234', 1, '', 0, '', NULL, '1', '2022-07-09 17:40:26', '1', '2022-07-09 17:40:26', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (117, 'admin123', '$2a$10$WI8Gg/lpZQIrOEZMHqka7OdFaD4Nx.B/qY8ZGTTUKrOJwaHFqibaC', '测试号02', '1111', 100, '[2]', '', '15601691234', 1, '', 0, '', NULL, '1', '2022-07-09 17:40:26', '1', '2024-08-11 10:12:03', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (118, 'goudan', '$2a$04$OB1SuphCdiLVRpiYRKeqH.8NYS7UIp5vmIv1W7U4w6toiFeOAATVK', '狗蛋', NULL, 103, '[1]', '', '15601691239', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-03-17 09:10:27', '1', '2022-07-09 17:44:43', '1', '2024-04-04 09:48:05', b'0', 1);
|
||||
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (131, 'hh', '$2a$04$jyH9h6.gaw8mpOjPfHIpx.8as2Rzfcmdlj5rlJFwgCw4rsv/MTb2K', '呵呵', NULL, 100, '[]', '777@qq.com', '15601882312', 1, '', 0, '', NULL, '1', '2024-04-27 08:45:56', '1', '2024-04-27 08:45:56', b'0', 1);
|
||||
COMMIT;
|
||||
|
@@ -14,14 +14,13 @@
|
||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||
|
||||
<properties>
|
||||
<revision>2.2.0-jdk8-snapshot</revision>
|
||||
<revision>2.2.0-snapshot</revision>
|
||||
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
|
||||
<!-- 统一依赖管理 -->
|
||||
<spring.boot.version>2.7.18</spring.boot.version>
|
||||
<spring.boot.version>3.3.1</spring.boot.version>
|
||||
<!-- Web 相关 -->
|
||||
<springdoc.version>1.7.0</springdoc.version>
|
||||
<springdoc.version>2.3.0</springdoc.version>
|
||||
<knife4j.version>4.5.0</knife4j.version>
|
||||
<servlet.versoin>2.5</servlet.versoin>
|
||||
<!-- DB 相关 -->
|
||||
<druid.version>1.2.23</druid.version>
|
||||
<mybatis.version>3.5.16</mybatis.version>
|
||||
@@ -34,26 +33,28 @@
|
||||
<dm8.jdbc.version>8.1.3.62</dm8.jdbc.version>
|
||||
<kingbase.jdbc.version>8.6.0</kingbase.jdbc.version>
|
||||
<opengauss.jdbc.version>5.0.2</opengauss.jdbc.version>
|
||||
<taos.version>3.3.3</taos.version>
|
||||
<!-- 消息队列 -->
|
||||
<rocketmq-spring.version>2.3.0</rocketmq-spring.version>
|
||||
<!-- 服务保障相关 -->
|
||||
<lock4j.version>2.2.7</lock4j.version>
|
||||
<!-- 监控相关 -->
|
||||
<skywalking.version>8.12.0</skywalking.version>
|
||||
<spring-boot-admin.version>2.7.15</spring-boot-admin.version>
|
||||
<skywalking.version>9.0.0</skywalking.version>
|
||||
<spring-boot-admin.version>3.3.2</spring-boot-admin.version>
|
||||
<opentracing.version>0.33.0</opentracing.version>
|
||||
<!-- Test 测试相关 -->
|
||||
<podam.version>7.2.11.RELEASE</podam.version> <!-- Spring Boot 2.X 最多使用 7.2.11 版本 -->
|
||||
<podam.version>8.0.2.RELEASE</podam.version>
|
||||
<jedis-mock.version>1.1.2</jedis-mock.version>
|
||||
<mockito-inline.version>4.11.0</mockito-inline.version>
|
||||
<mockito-inline.version>5.2.0</mockito-inline.version>
|
||||
<!-- Bpm 工作流相关 -->
|
||||
<flowable.version>6.8.0</flowable.version>
|
||||
<flowable.version>7.0.1</flowable.version>
|
||||
<!-- 工具类相关 -->
|
||||
<captcha-plus.version>1.0.10</captcha-plus.version>
|
||||
<captcha-plus.version>2.0.3</captcha-plus.version>
|
||||
<jsoup.version>1.18.1</jsoup.version>
|
||||
<lombok.version>1.18.34</lombok.version>
|
||||
<mapstruct.version>1.5.5.Final</mapstruct.version>
|
||||
<hutool.version>5.8.29</hutool.version>
|
||||
<hutool-5.version>5.8.29</hutool-5.version>
|
||||
<hutool-6.version>6.0.0-M14</hutool-6.version>
|
||||
<easyexcel.verion>3.3.4</easyexcel.verion>
|
||||
<velocity.version>2.3</velocity.version>
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
@@ -64,12 +65,13 @@
|
||||
<tika-core.version>2.9.2</tika-core.version>
|
||||
<ip2region.version>2.7.0</ip2region.version>
|
||||
<bizlog-sdk.version>3.0.6</bizlog-sdk.version>
|
||||
<mqtt.version>1.2.5</mqtt.version>
|
||||
<!-- 三方云服务相关 -->
|
||||
<okio.version>3.5.0</okio.version>
|
||||
<okhttp3.version>4.11.0</okhttp3.version>
|
||||
<commons-io.version>2.15.1</commons-io.version>
|
||||
<minio.version>8.5.7</minio.version>
|
||||
<justauth.version>1.0.8</justauth.version>
|
||||
<justauth.version>2.0.5</justauth.version>
|
||||
<jimureport.version>1.7.8</jimureport.version>
|
||||
<xercesImpl.version>2.12.2</xercesImpl.version>
|
||||
<weixin-java.version>4.6.0</weixin-java.version>
|
||||
@@ -143,12 +145,12 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
<version>${knife4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-ui</artifactId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
|
||||
<version>${springdoc.version}</version>
|
||||
</dependency>
|
||||
|
||||
@@ -161,7 +163,7 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<artifactId>druid-spring-boot-3-starter</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -171,7 +173,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -181,7 +183,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId> <!-- 多数据源 -->
|
||||
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId> <!-- 多数据源 -->
|
||||
<version>${dynamic-datasource.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -231,18 +233,8 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.redisson</groupId>
|
||||
<!-- 使用 redisson-spring-data-27 替代,解决 Tuple NoClassDefFoundError 报错 -->
|
||||
<artifactId>redisson-spring-data-33</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson-spring-data-27</artifactId>
|
||||
<version>${redisson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.dameng</groupId>
|
||||
@@ -262,6 +254,12 @@
|
||||
<version>${kingbase.jdbc.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>${taos.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Job 定时任务相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
@@ -459,7 +457,12 @@
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
<version>${hutool-5.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara.hutool</groupId>
|
||||
<artifactId>hutool-extra</artifactId>
|
||||
<version>${hutool-6.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -496,12 +499,6 @@
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>${guice.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>transmittable-thread-local</artifactId> <!-- 解决 ThreadLocal 父子线程的传值问题 -->
|
||||
@@ -586,7 +583,7 @@
|
||||
<!-- 积木报表-->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.jimureport</groupId>
|
||||
<artifactId>jimureport-spring-boot-starter</artifactId>
|
||||
<artifactId>jimureport-spring-boot3-starter-fastjson2</artifactId>
|
||||
<version>${jimureport.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -601,6 +598,13 @@
|
||||
<version>${xercesImpl.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- MQTT -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.paho</groupId>
|
||||
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||
<version>${mqtt.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
@@ -60,7 +60,7 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-ui</artifactId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
|
||||
<scope>provided</scope> <!-- 设置为 provided,主要是 PageParam 使用到 -->
|
||||
</dependency>
|
||||
|
||||
|
@@ -3,9 +3,9 @@ package cn.iocoder.yudao.framework.common.pojo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Schema(description="分页参数")
|
||||
|
@@ -11,7 +11,7 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Map;
|
||||
@@ -111,7 +111,7 @@ public class HttpUtils {
|
||||
authorization = Base64.decodeStr(authorization);
|
||||
clientId = StrUtil.subBefore(authorization, ":", false);
|
||||
clientSecret = StrUtil.subAfter(authorization, ":", false);
|
||||
// 再从 Param 中获取
|
||||
// 再从 Param 中获取
|
||||
} else {
|
||||
clientId = request.getParameter("client_id");
|
||||
clientSecret = request.getParameter("client_secret");
|
||||
@@ -143,4 +143,21 @@ public class HttpUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP get 请求,基于 {@link cn.hutool.http.HttpUtil} 实现
|
||||
*
|
||||
* 为什么要封装该方法,因为 HttpUtil 默认封装的方法,没有允许传递 headers 参数
|
||||
*
|
||||
* @param url URL
|
||||
* @param headers 请求头
|
||||
* @return 请求结果
|
||||
*/
|
||||
public static String get(String url, Map<String, String> headers) {
|
||||
try (HttpResponse response = HttpRequest.get(url)
|
||||
.addHeaders(headers)
|
||||
.execute()) {
|
||||
return response.body();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,19 +1,16 @@
|
||||
package cn.iocoder.yudao.framework.common.util.servlet;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import cn.hutool.extra.servlet.JakartaServletUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -32,22 +29,7 @@ public class ServletUtils {
|
||||
@SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码
|
||||
public static void writeJSON(HttpServletResponse response, Object object) {
|
||||
String content = JsonUtils.toJsonString(object);
|
||||
ServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回附件
|
||||
*
|
||||
* @param response 响应
|
||||
* @param filename 文件名
|
||||
* @param content 附件内容
|
||||
*/
|
||||
public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException {
|
||||
// 设置 header 和 contentType
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
// 输出附件
|
||||
IoUtil.write(response.getOutputStream(), false, content);
|
||||
JakartaServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +67,7 @@ public class ServletUtils {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
return ServletUtil.getClientIP(request);
|
||||
return JakartaServletUtil.getClientIP(request);
|
||||
}
|
||||
|
||||
public static boolean isJsonRequest(ServletRequest request) {
|
||||
@@ -95,7 +77,7 @@ public class ServletUtils {
|
||||
public static String getBody(HttpServletRequest request) {
|
||||
// 只有在 json 请求在读取,因为只有 CacheRequestBodyFilter 才会进行缓存,支持重复读取
|
||||
if (isJsonRequest(request)) {
|
||||
return ServletUtil.getBody(request);
|
||||
return JakartaServletUtil.getBody(request);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -103,17 +85,17 @@ public class ServletUtils {
|
||||
public static byte[] getBodyBytes(HttpServletRequest request) {
|
||||
// 只有在 json 请求在读取,因为只有 CacheRequestBodyFilter 才会进行缓存,支持重复读取
|
||||
if (isJsonRequest(request)) {
|
||||
return ServletUtil.getBodyBytes(request);
|
||||
return JakartaServletUtil.getBodyBytes(request);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getClientIP(HttpServletRequest request) {
|
||||
return ServletUtil.getClientIP(request);
|
||||
return JakartaServletUtil.getClientIP(request);
|
||||
}
|
||||
|
||||
public static Map<String, String> getParamMap(HttpServletRequest request) {
|
||||
return ServletUtil.getParamMap(request);
|
||||
return JakartaServletUtil.getParamMap(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -4,10 +4,10 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import jakarta.validation.Validation;
|
||||
import jakarta.validation.Validator;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@@ -2,8 +2,8 @@ package cn.iocoder.yudao.framework.common.validation;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({
|
||||
|
@@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.common.validation;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@@ -2,8 +2,8 @@ package cn.iocoder.yudao.framework.common.validation;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.yudao.framework.common.validation;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({
|
||||
|
@@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.common.validation;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
|
||||
public class MobileValidator implements ConstraintValidator<Mobile, String> {
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.yudao.framework.common.validation;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({
|
||||
|
@@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.common.validation;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.hutool.core.util.PhoneUtil;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
|
||||
public class TelephoneValidator implements ConstraintValidator<Telephone, String> {
|
||||
|
||||
|
@@ -13,7 +13,7 @@ import java.util.Set;
|
||||
/**
|
||||
* 基于 MyBatis Plus 多租户的功能,实现 DB 层面的多租户的功能
|
||||
*
|
||||
* @author 芋道源码
|
||||
* @author
|
||||
*/
|
||||
public class TenantDatabaseInterceptor implements TenantLineHandler {
|
||||
|
||||
|
@@ -46,6 +46,7 @@ public class TenantJobAspect {
|
||||
try {
|
||||
joinPoint.proceed();
|
||||
} catch (Throwable e) {
|
||||
log.error("[execute][租户({}) 执行 Job 发生异常", tenantId, e);
|
||||
results.put(tenantId, ExceptionUtil.getRootCauseMessage(e));
|
||||
}
|
||||
});
|
||||
|
@@ -15,10 +15,10 @@ import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@@ -4,10 +4,10 @@ import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,11 @@
|
||||
|
||||
package org.springframework.messaging.handler.invocation;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
@@ -27,11 +32,6 @@ import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.handler.HandlerMethod;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
|
||||
|
||||
/**
|
||||
@@ -50,10 +50,12 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
|
||||
private static final Object[] EMPTY_ARGS = new Object[0];
|
||||
|
||||
|
||||
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
|
||||
|
||||
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
|
||||
|
||||
/**
|
||||
* Create an instance from a {@code HandlerMethod}.
|
||||
*/
|
||||
@@ -81,6 +83,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
super(bean, methodName, parameterTypes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} to use for resolving method argument values.
|
||||
*/
|
||||
@@ -91,12 +94,13 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
/**
|
||||
* Set the ParameterNameDiscoverer for resolving parameter names when needed
|
||||
* (e.g. default request attribute name).
|
||||
* <p>Default is a {@link DefaultParameterNameDiscoverer}.
|
||||
* <p>Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}.
|
||||
*/
|
||||
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
|
||||
this.parameterNameDiscoverer = parameterNameDiscoverer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invoke the method after resolving its argument values in the context of the given message.
|
||||
* <p>Argument values are commonly resolved through
|
||||
@@ -200,20 +204,21 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertTargetBean(getBridgedMethod(), getBean(), args);
|
||||
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
|
||||
String text = (ex.getMessage() == null || ex.getCause() instanceof NullPointerException) ?
|
||||
"Illegal argument": ex.getMessage();
|
||||
throw new IllegalStateException(formatInvokeError(text, args), ex);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
// Unwrap for HandlerExceptionResolvers ...
|
||||
Throwable targetException = ex.getTargetException();
|
||||
if (targetException instanceof RuntimeException) {
|
||||
throw (RuntimeException) targetException;
|
||||
if (targetException instanceof RuntimeException runtimeException) {
|
||||
throw runtimeException;
|
||||
}
|
||||
else if (targetException instanceof Error) {
|
||||
throw (Error) targetException;
|
||||
else if (targetException instanceof Error error) {
|
||||
throw error;
|
||||
}
|
||||
else if (targetException instanceof Exception) {
|
||||
throw (Exception) targetException;
|
||||
else if (targetException instanceof Exception exception) {
|
||||
throw exception;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
|
||||
@@ -225,7 +230,8 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
return new AsyncResultMethodParameter(returnValue);
|
||||
}
|
||||
|
||||
private class AsyncResultMethodParameter extends HandlerMethodParameter {
|
||||
|
||||
private class AsyncResultMethodParameter extends AnnotatedMethodParameter {
|
||||
|
||||
@Nullable
|
||||
private final Object returnValue;
|
||||
|
@@ -4,9 +4,9 @@ import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.converters.longconverter.LongStringConverter;
|
||||
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@@ -13,9 +13,8 @@ import org.quartz.PersistJobDataAfterExecution;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import static cn.hutool.core.exceptions.ExceptionUtil.getRootCauseMessage;
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.yudao.framework.quartz.core.service;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
|
@@ -3,10 +3,10 @@ package cn.iocoder.yudao.framework.tracer.core.filter;
|
||||
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
@@ -63,18 +63,28 @@
|
||||
<artifactId>opengauss-jdbc</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<artifactId>druid-spring-boot-3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId> <!-- 多数据源 -->
|
||||
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId> <!-- 多数据源 -->
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.yudao.framework.datasource.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.datasource.core.filter.DruidAdRemoveFilter;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
|
||||
import com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
@@ -3,10 +3,10 @@ package cn.iocoder.yudao.framework.datasource.core.filter;
|
||||
import com.alibaba.druid.util.Utils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
@@ -7,6 +7,8 @@ import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
|
||||
import com.baomidou.mybatisplus.extension.incrementer.*;
|
||||
import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
|
||||
import com.baomidou.mybatisplus.extension.parser.cache.JdkSerialCaffeineJsqlParseCache;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@@ -16,6 +18,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* MyBaits 配置类
|
||||
*
|
||||
@@ -26,6 +30,14 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
||||
lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试
|
||||
public class YudaoMybatisAutoConfiguration {
|
||||
|
||||
static {
|
||||
// 动态 SQL 智能优化支持本地缓存加速解析,更完善的租户复杂 XML 动态 SQL 支持,静态注入缓存
|
||||
JsqlParserGlobal.setJsqlParseCache(new JdkSerialCaffeineJsqlParseCache(
|
||||
(cache) -> cache.maximumSize(1024)
|
||||
.expireAfterWrite(5, TimeUnit.SECONDS))
|
||||
);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
|
||||
@@ -34,7 +46,7 @@ public class YudaoMybatisAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MetaObjectHandler defaultMetaObjectHandler(){
|
||||
public MetaObjectHandler defaultMetaObjectHandler() {
|
||||
return new DefaultDBFieldHandler(); // 自动填充参数类
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
|
||||
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
@@ -21,7 +21,8 @@ import java.lang.reflect.Method;
|
||||
*/
|
||||
public class ExpressionIdempotentKeyResolver implements IdempotentKeyResolver {
|
||||
|
||||
private final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||
private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
|
||||
private final ExpressionParser expressionParser = new SpelExpressionParser();
|
||||
|
||||
@Override
|
||||
|
@@ -9,13 +9,13 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
|
||||
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.SortedMap;
|
||||
@@ -69,7 +69,7 @@ public class ApiSignatureAspect {
|
||||
|
||||
// 3. 将 nonce 记入缓存,防止重复使用(重点二:此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2 )
|
||||
String nonce = request.getHeader(signature.nonce());
|
||||
signatureRedisDAO.setNonce(nonce, signature.timeout() * 2, signature.timeUnit());
|
||||
signatureRedisDAO.setNonce(appId, nonce, signature.timeout() * 2, signature.timeUnit());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ public class ApiSignatureAspect {
|
||||
}
|
||||
|
||||
// 3. 检查 nonce 是否存在,有且仅能使用一次
|
||||
return signatureRedisDAO.getNonce(nonce) == null;
|
||||
return signatureRedisDAO.getNonce(appId, nonce) == null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,5 +165,4 @@ public class ApiSignatureAspect {
|
||||
return sortedMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -22,7 +22,7 @@ public class ApiSignatureRedisDAO {
|
||||
* VALUE 格式:String
|
||||
* 过期时间:不固定
|
||||
*/
|
||||
private static final String SIGNATURE_NONCE = "api_signature_nonce:%s";
|
||||
private static final String SIGNATURE_NONCE = "api_signature_nonce:%s:%s";
|
||||
|
||||
/**
|
||||
* 签名密钥
|
||||
@@ -36,16 +36,16 @@ public class ApiSignatureRedisDAO {
|
||||
|
||||
// ========== 验签随机数 ==========
|
||||
|
||||
public String getNonce(String nonce) {
|
||||
return stringRedisTemplate.opsForValue().get(formatNonceKey(nonce));
|
||||
public String getNonce(String appId, String nonce) {
|
||||
return stringRedisTemplate.opsForValue().get(formatNonceKey(appId, nonce));
|
||||
}
|
||||
|
||||
public void setNonce(String nonce, int time, TimeUnit timeUnit) {
|
||||
stringRedisTemplate.opsForValue().set(formatNonceKey(nonce), "", time, timeUnit);
|
||||
public void setNonce(String appId, String nonce, int time, TimeUnit timeUnit) {
|
||||
stringRedisTemplate.opsForValue().set(formatNonceKey(appId, nonce), "", time, timeUnit);
|
||||
}
|
||||
|
||||
private static String formatNonceKey(String key) {
|
||||
return String.format(SIGNATURE_NONCE, key);
|
||||
private static String formatNonceKey(String appId, String nonce) {
|
||||
return String.format(SIGNATURE_NONCE, appId, nonce);
|
||||
}
|
||||
|
||||
// ========== 签名密钥 ==========
|
||||
|
@@ -6,13 +6,13 @@ import cn.hutool.crypto.digest.DigestUtil;
|
||||
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
|
||||
import cn.iocoder.yudao.framework.signature.core.aop.ApiSignatureAspect;
|
||||
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
@@ -69,7 +69,7 @@ public class ApiSignatureTest {
|
||||
// 断言结果
|
||||
assertTrue(result);
|
||||
// 断言调用
|
||||
verify(signatureRedisDAO).setNonce(eq(nonce), eq(120), eq(TimeUnit.SECONDS));
|
||||
verify(signatureRedisDAO).setNonce(eq(appId), eq(nonce), eq(120), eq(TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -26,10 +26,6 @@
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson-spring-data-27</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.redis.config;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import org.redisson.spring.starter.RedissonAutoConfiguration;
|
||||
import org.redisson.spring.starter.RedissonAutoConfigurationV2;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
@@ -13,7 +13,7 @@ import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
/**
|
||||
* Redis 配置类
|
||||
*/
|
||||
@AutoConfiguration(before = RedissonAutoConfiguration.class) // 目的:使用自己定义的 RedisTemplate Bean
|
||||
@AutoConfiguration(before = RedissonAutoConfigurationV2.class) // 目的:使用自己定义的 RedisTemplate Bean
|
||||
public class YudaoRedisAutoConfiguration {
|
||||
|
||||
/**
|
||||
|
@@ -8,10 +8,10 @@ import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||
import com.mzt.logapi.beans.LogRecord;
|
||||
import com.mzt.logapi.service.ILogRecordService;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -29,18 +29,22 @@ public class LogRecordServiceImpl implements ILogRecordService {
|
||||
|
||||
@Override
|
||||
public void record(LogRecord logRecord) {
|
||||
// 1. 补全通用字段
|
||||
OperateLogCreateReqDTO reqDTO = new OperateLogCreateReqDTO();
|
||||
reqDTO.setTraceId(TracerUtils.getTraceId());
|
||||
// 补充用户信息
|
||||
fillUserFields(reqDTO);
|
||||
// 补全模块信息
|
||||
fillModuleFields(reqDTO, logRecord);
|
||||
// 补全请求信息
|
||||
fillRequestFields(reqDTO);
|
||||
try {
|
||||
reqDTO.setTraceId(TracerUtils.getTraceId());
|
||||
// 补充用户信息
|
||||
fillUserFields(reqDTO);
|
||||
// 补全模块信息
|
||||
fillModuleFields(reqDTO, logRecord);
|
||||
// 补全请求信息
|
||||
fillRequestFields(reqDTO);
|
||||
|
||||
// 2. 异步记录日志
|
||||
operateLogApi.createOperateLog(reqDTO);
|
||||
// 2. 异步记录日志
|
||||
operateLogApi.createOperateLogAsync(reqDTO);
|
||||
} catch (Throwable ex) {
|
||||
// 由于 @Async 异步调用,这里打印下日志,更容易跟进
|
||||
log.error("[record][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void fillUserFields(OperateLogCreateReqDTO reqDTO) {
|
||||
|
@@ -1,12 +1,11 @@
|
||||
package cn.iocoder.yudao.framework.security.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
|
||||
|
||||
/**
|
||||
* 自定义的 URL 的安全配置
|
||||
@@ -15,7 +14,7 @@ import javax.annotation.Resource;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public abstract class AuthorizeRequestsCustomizer
|
||||
implements Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry>, Ordered {
|
||||
implements Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry>, Ordered {
|
||||
|
||||
@Resource
|
||||
private WebProperties webProperties;
|
||||
|
@@ -4,8 +4,8 @@ import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
@@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkService
|
||||
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||
import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi;
|
||||
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||
@@ -21,8 +22,6 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* Spring Security 自动配置类,主要用于相关组件的配置
|
||||
*
|
||||
|
@@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter
|
||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -28,8 +30,6 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.util.pattern.PathPattern;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -126,26 +126,25 @@ public class YudaoWebSecurityConfigurerAdapter {
|
||||
// 设置每个请求的权限
|
||||
httpSecurity
|
||||
// ①:全局共享规则
|
||||
.authorizeRequests()
|
||||
// 1.1 静态资源,可匿名访问
|
||||
.antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
||||
// 1.2 设置 @PermitAll 无需认证
|
||||
.antMatchers(HttpMethod.GET, permitAllUrls.get(HttpMethod.GET).toArray(new String[0])).permitAll()
|
||||
.antMatchers(HttpMethod.POST, permitAllUrls.get(HttpMethod.POST).toArray(new String[0])).permitAll()
|
||||
.antMatchers(HttpMethod.PUT, permitAllUrls.get(HttpMethod.PUT).toArray(new String[0])).permitAll()
|
||||
.antMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll()
|
||||
// 1.3 基于 yudao.security.permit-all-urls 无需认证
|
||||
.antMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll()
|
||||
// 1.4 设置 App API 无需认证
|
||||
.antMatchers(buildAppApi("/**")).permitAll()
|
||||
// 1.5 验证码captcha 允许匿名访问
|
||||
.antMatchers("/captcha/get", "/captcha/check").permitAll()
|
||||
.authorizeHttpRequests(c -> c
|
||||
// 1.1 静态资源,可匿名访问
|
||||
.requestMatchers(HttpMethod.GET, "/*.html", "/*.html", "/*.css", "/*.js").permitAll()
|
||||
// 1.1 设置 @PermitAll 无需认证
|
||||
.requestMatchers(HttpMethod.GET, permitAllUrls.get(HttpMethod.GET).toArray(new String[0])).permitAll()
|
||||
.requestMatchers(HttpMethod.POST, permitAllUrls.get(HttpMethod.POST).toArray(new String[0])).permitAll()
|
||||
.requestMatchers(HttpMethod.PUT, permitAllUrls.get(HttpMethod.PUT).toArray(new String[0])).permitAll()
|
||||
.requestMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll()
|
||||
.requestMatchers(HttpMethod.HEAD, permitAllUrls.get(HttpMethod.HEAD).toArray(new String[0])).permitAll()
|
||||
.requestMatchers(HttpMethod.PATCH, permitAllUrls.get(HttpMethod.PATCH).toArray(new String[0])).permitAll()
|
||||
// 1.2 基于 yudao.security.permit-all-urls 无需认证
|
||||
.requestMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll()
|
||||
// 1.3 设置 App API 无需认证
|
||||
.requestMatchers(buildAppApi("/**")).permitAll()
|
||||
)
|
||||
// ②:每个项目的自定义规则
|
||||
.and().authorizeRequests(registry -> // 下面,循环设置自定义规则
|
||||
authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(registry)))
|
||||
.authorizeHttpRequests(c -> authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(c)))
|
||||
// ③:兜底规则,必须认证
|
||||
.authorizeRequests()
|
||||
.anyRequest().authenticated();
|
||||
.authorizeHttpRequests(c -> c.anyRequest().authenticated());
|
||||
|
||||
// 添加 Token Filter
|
||||
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
|
@@ -16,10 +16,10 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
@@ -8,16 +8,14 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.FORBIDDEN;
|
||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED;
|
||||
|
||||
/**
|
||||
* 访问一个需要认证的 URL 资源,已经认证(登录)但是没有权限的情况下,返回 {@link GlobalErrorCodeConstants#FORBIDDEN} 错误码。
|
||||
|
@@ -8,9 +8,9 @@ import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED;
|
||||
|
||||
|
@@ -12,7 +12,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
|
@@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
|
||||
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
||||
import cn.iocoder.yudao.framework.test.config.RedisTestConfiguration;
|
||||
import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
|
||||
import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure;
|
||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
||||
import org.redisson.spring.starter.RedissonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
|
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.test.core.ut;
|
||||
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
|
||||
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
|
||||
import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
|
||||
import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure;
|
||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
||||
import com.github.yulichang.autoconfigure.MybatisPlusJoinAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
|
@@ -7,10 +7,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import uk.co.jemos.podam.api.PodamFactory;
|
||||
import uk.co.jemos.podam.api.PodamFactoryImpl;
|
||||
import uk.co.jemos.podam.common.AttributeStrategy;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
|
@@ -40,11 +40,11 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-ui</artifactId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@@ -2,15 +2,11 @@ package cn.iocoder.yudao.framework.apilog.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter;
|
||||
import cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkServiceImpl;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkServiceImpl;
|
||||
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
|
||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||
import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration;
|
||||
import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi;
|
||||
import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi;
|
||||
import jakarta.servlet.Filter;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@@ -19,23 +15,9 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
@AutoConfiguration(after = YudaoWebAutoConfiguration.class)
|
||||
public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer {
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
||||
public ApiAccessLogFrameworkService apiAccessLogFrameworkService(ApiAccessLogApi apiAccessLogApi) {
|
||||
return new ApiAccessLogFrameworkServiceImpl(apiAccessLogApi);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
||||
public ApiErrorLogFrameworkService apiErrorLogFrameworkService(ApiErrorLogApi apiErrorLogApi) {
|
||||
return new ApiErrorLogFrameworkServiceImpl(apiErrorLogApi);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 ApiAccessLogFilter Bean,记录 API 请求日志
|
||||
*/
|
||||
@@ -43,8 +25,8 @@ public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer {
|
||||
@ConditionalOnProperty(prefix = "yudao.access-log", value = "enable", matchIfMissing = true) // 允许使用 yudao.access-log.enable=false 禁用访问日志
|
||||
public FilterRegistrationBean<ApiAccessLogFilter> apiAccessLogFilter(WebProperties webProperties,
|
||||
@Value("${spring.application.name}") String applicationName,
|
||||
ApiAccessLogFrameworkService apiAccessLogFrameworkService) {
|
||||
ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogFrameworkService);
|
||||
ApiAccessLogApi apiAccessLogApi) {
|
||||
ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogApi);
|
||||
return createFilterBean(filter, WebFilterOrderEnum.API_ACCESS_LOG_FILTER);
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,6 @@ import cn.hutool.core.util.BooleanUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService;
|
||||
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
@@ -18,18 +17,19 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||
import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi;
|
||||
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
@@ -53,12 +53,12 @@ public class ApiAccessLogFilter extends ApiRequestFilter {
|
||||
|
||||
private final String applicationName;
|
||||
|
||||
private final ApiAccessLogFrameworkService apiAccessLogFrameworkService;
|
||||
private final ApiAccessLogApi apiAccessLogApi;
|
||||
|
||||
public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogFrameworkService apiAccessLogFrameworkService) {
|
||||
public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogApi apiAccessLogApi) {
|
||||
super(webProperties);
|
||||
this.applicationName = applicationName;
|
||||
this.apiAccessLogFrameworkService = apiAccessLogFrameworkService;
|
||||
this.apiAccessLogApi = apiAccessLogApi;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,7 +91,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter {
|
||||
if (!enable) {
|
||||
return;
|
||||
}
|
||||
apiAccessLogFrameworkService.createApiAccessLog(accessLog);
|
||||
apiAccessLogApi.createApiAccessLogAsync(accessLog);
|
||||
} catch (Throwable th) {
|
||||
log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), toJsonString(accessLog), th);
|
||||
}
|
||||
@@ -160,8 +160,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter {
|
||||
// ========== 解析 @ApiAccessLog、@Swagger 注解 ==========
|
||||
|
||||
private static OperateTypeEnum parseOperateLogType(HttpServletRequest request) {
|
||||
RequestMethod requestMethod = ArrayUtil.firstMatch(method ->
|
||||
StrUtil.equalsAnyIgnoreCase(method.name(), request.getMethod()), RequestMethod.values());
|
||||
RequestMethod requestMethod = RequestMethod.resolve(request.getMethod());
|
||||
if (requestMethod == null) {
|
||||
return OperateTypeEnum.OTHER;
|
||||
}
|
||||
@@ -236,7 +235,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter {
|
||||
return;
|
||||
}
|
||||
// 情况三:Object,遍历处理
|
||||
Iterator<Map.Entry<String, JsonNode>> iterator = node.fields();
|
||||
Iterator<Map.Entry<String, JsonNode>> iterator = node.properties().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, JsonNode> entry = iterator.next();
|
||||
if (ArrayUtil.contains(sanitizeKeys, entry.getKey())
|
||||
|
@@ -6,13 +6,13 @@ import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@@ -1,19 +0,0 @@
|
||||
package cn.iocoder.yudao.framework.apilog.core.service;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
|
||||
|
||||
/**
|
||||
* API 访问日志 Framework Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface ApiAccessLogFrameworkService {
|
||||
|
||||
/**
|
||||
* 创建 API 访问日志
|
||||
*
|
||||
* @param reqDTO API 访问日志
|
||||
*/
|
||||
void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO);
|
||||
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
package cn.iocoder.yudao.framework.apilog.core.service;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi;
|
||||
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
/**
|
||||
* API 访问日志 Framework Service 实现类
|
||||
*
|
||||
* 基于 {@link ApiAccessLogApi} 服务,记录访问日志
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class ApiAccessLogFrameworkServiceImpl implements ApiAccessLogFrameworkService {
|
||||
|
||||
private final ApiAccessLogApi apiAccessLogApi;
|
||||
|
||||
@Override
|
||||
@Async
|
||||
public void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO) {
|
||||
try {
|
||||
apiAccessLogApi.createApiAccessLog(reqDTO);
|
||||
} catch (Throwable ex) {
|
||||
// 由于 @Async 异步调用,这里打印下日志,更容易跟进
|
||||
log.error("[createApiAccessLog][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
package cn.iocoder.yudao.framework.apilog.core.service;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
|
||||
|
||||
/**
|
||||
* API 错误日志 Framework Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface ApiErrorLogFrameworkService {
|
||||
|
||||
/**
|
||||
* 创建 API 错误日志
|
||||
*
|
||||
* @param reqDTO API 错误日志
|
||||
*/
|
||||
void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO);
|
||||
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
package cn.iocoder.yudao.framework.apilog.core.service;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi;
|
||||
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
/**
|
||||
* API 错误日志 Framework Service 实现类
|
||||
*
|
||||
* 基于 {@link ApiErrorLogApi} 服务,记录错误日志
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class ApiErrorLogFrameworkServiceImpl implements ApiErrorLogFrameworkService {
|
||||
|
||||
private final ApiErrorLogApi apiErrorLogApi;
|
||||
|
||||
@Override
|
||||
@Async
|
||||
public void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO) {
|
||||
try {
|
||||
apiErrorLogApi.createApiErrorLog(reqDTO);
|
||||
} catch (Throwable ex) {
|
||||
// 由于 @Async 异步调用,这里打印下日志,更容易跟进
|
||||
log.error("[createApiErrorLog][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -62,6 +62,10 @@ public class BannerApplicationRunner implements ApplicationRunner {
|
||||
if (isNotPresent("cn.iocoder.yudao.module.ai.framework.web.config.AiWebConfiguration")) {
|
||||
System.out.println("[AI 大模型 yudao-module-ai - 已禁用][参考 https://doc.iocoder.cn/ai/build/ 开启]");
|
||||
}
|
||||
// IOT 物联网
|
||||
if (isNotPresent("cn.iocoder.yudao.module.iot.framework.web.config.IotWebConfiguration")) {
|
||||
System.out.println("[IOT 物联网 yudao-module-iot - 已禁用][参考 https://doc.iocoder.cn/iot/build/ 开启]");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.swagger.config;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* Swagger 配置属性
|
||||
|
@@ -10,10 +10,14 @@ import io.swagger.v3.oas.models.media.StringSchema;
|
||||
import io.swagger.v3.oas.models.parameters.Parameter;
|
||||
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
import org.springdoc.core.*;
|
||||
import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
|
||||
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
|
||||
import org.springdoc.core.models.GroupedOpenApi;
|
||||
import org.springdoc.core.properties.SpringDocConfigProperties;
|
||||
import org.springdoc.core.providers.JavadocProvider;
|
||||
import org.springdoc.core.service.OpenAPIService;
|
||||
import org.springdoc.core.service.SecurityService;
|
||||
import org.springdoc.core.utils.PropertyResolverUtils;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
|
@@ -7,9 +7,9 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@ConfigurationProperties(prefix = "yudao.web")
|
||||
@Validated
|
||||
|
@@ -1,12 +1,14 @@
|
||||
package cn.iocoder.yudao.framework.web.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
|
||||
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
|
||||
import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter;
|
||||
import cn.iocoder.yudao.framework.web.core.filter.DemoFilter;
|
||||
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||
import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.Filter;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
@@ -25,9 +27,6 @@ import org.springframework.web.filter.CorsFilter;
|
||||
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.Filter;
|
||||
|
||||
@AutoConfiguration
|
||||
@EnableConfigurationProperties(WebProperties.class)
|
||||
public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
|
||||
@@ -59,8 +58,9 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GlobalExceptionHandler globalExceptionHandler(ApiErrorLogFrameworkService ApiErrorLogFrameworkService) {
|
||||
return new GlobalExceptionHandler(applicationName, ApiErrorLogFrameworkService);
|
||||
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
||||
public GlobalExceptionHandler globalExceptionHandler(ApiErrorLogApi apiErrorLogApi) {
|
||||
return new GlobalExceptionHandler(applicationName, apiErrorLogApi);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 过滤 /admin-api、/app-api 等 API 请求的过滤器
|
||||
|
@@ -3,10 +3,10 @@ package cn.iocoder.yudao.framework.web.core.filter;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
@@ -2,10 +2,10 @@ package cn.iocoder.yudao.framework.web.core.filter;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import jakarta.servlet.ReadListener;
|
||||
import jakarta.servlet.ServletInputStream;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
@@ -6,9 +6,9 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.DEMO_DENY;
|
||||
|
||||
|
@@ -4,7 +4,7 @@ import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
|
||||
import cn.hutool.extra.servlet.JakartaServletUtil;
|
||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
@@ -13,10 +13,16 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi;
|
||||
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
|
||||
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import jakarta.validation.ValidationException;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.BindException;
|
||||
@@ -28,11 +34,8 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.validation.ValidationException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -57,7 +60,7 @@ public class GlobalExceptionHandler {
|
||||
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
||||
private final String applicationName;
|
||||
|
||||
private final ApiErrorLogFrameworkService apiErrorLogFrameworkService;
|
||||
private final ApiErrorLogApi apiErrorLogApi;
|
||||
|
||||
/**
|
||||
* 处理所有异常,主要是提供给 Filter 使用
|
||||
@@ -87,7 +90,10 @@ public class GlobalExceptionHandler {
|
||||
return validationException((ValidationException) ex);
|
||||
}
|
||||
if (ex instanceof NoHandlerFoundException) {
|
||||
return noHandlerFoundExceptionHandler(request, (NoHandlerFoundException) ex);
|
||||
return noHandlerFoundExceptionHandler((NoHandlerFoundException) ex);
|
||||
}
|
||||
if (ex instanceof NoResourceFoundException) {
|
||||
return noResourceFoundExceptionHandler(request, (NoResourceFoundException) ex);
|
||||
}
|
||||
if (ex instanceof HttpRequestMethodNotSupportedException) {
|
||||
return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex);
|
||||
@@ -119,7 +125,7 @@ public class GlobalExceptionHandler {
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||||
public CommonResult<?> methodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException ex) {
|
||||
log.warn("[missingServletRequestParameterExceptionHandler]", ex);
|
||||
log.warn("[methodArgumentTypeMismatchExceptionHandler]", ex);
|
||||
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", ex.getMessage()));
|
||||
}
|
||||
|
||||
@@ -145,6 +151,22 @@ public class GlobalExceptionHandler {
|
||||
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 SpringMVC 请求参数类型错误
|
||||
*
|
||||
* 例如说,接口上设置了 @RequestBody实体中 xx 属性类型为 Integer,结果传递 xx 参数类型为 String
|
||||
*/
|
||||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
||||
public CommonResult<?> methodArgumentTypeInvalidFormatExceptionHandler(HttpMessageNotReadableException ex) {
|
||||
log.warn("[methodArgumentTypeInvalidFormatExceptionHandler]", ex);
|
||||
if(ex.getCause() instanceof InvalidFormatException) {
|
||||
InvalidFormatException invalidFormatException = (InvalidFormatException) ex.getCause();
|
||||
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", invalidFormatException.getValue()));
|
||||
}else {
|
||||
return defaultExceptionHandler(ServletUtils.getRequest(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 Validator 校验不通过产生的异常
|
||||
*/
|
||||
@@ -173,11 +195,20 @@ public class GlobalExceptionHandler {
|
||||
* 2. spring.mvc.static-path-pattern 为 /statics/**
|
||||
*/
|
||||
@ExceptionHandler(NoHandlerFoundException.class)
|
||||
public CommonResult<?> noHandlerFoundExceptionHandler(HttpServletRequest req, NoHandlerFoundException ex) {
|
||||
public CommonResult<?> noHandlerFoundExceptionHandler(NoHandlerFoundException ex) {
|
||||
log.warn("[noHandlerFoundExceptionHandler]", ex);
|
||||
return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getRequestURL()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 SpringMVC 请求地址不存在
|
||||
*/
|
||||
@ExceptionHandler(NoResourceFoundException.class)
|
||||
private CommonResult<?> noResourceFoundExceptionHandler(HttpServletRequest req, NoResourceFoundException ex) {
|
||||
log.warn("[noResourceFoundExceptionHandler]", ex);
|
||||
return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getResourcePath()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 SpringMVC 请求方法不正确
|
||||
*
|
||||
@@ -240,7 +271,7 @@ public class GlobalExceptionHandler {
|
||||
// 情况二:处理异常
|
||||
log.error("[defaultExceptionHandler]", ex);
|
||||
// 插入异常日志
|
||||
this.createExceptionLog(req, ex);
|
||||
createExceptionLog(req, ex);
|
||||
// 返回 ERROR CommonResult
|
||||
return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
|
||||
}
|
||||
@@ -252,7 +283,7 @@ public class GlobalExceptionHandler {
|
||||
// 初始化 errorLog
|
||||
buildExceptionLog(errorLog, req, e);
|
||||
// 执行插入 errorLog
|
||||
apiErrorLogFrameworkService.createApiErrorLog(errorLog);
|
||||
apiErrorLogApi.createApiErrorLogAsync(errorLog);
|
||||
} catch (Throwable th) {
|
||||
log.error("[createExceptionLog][url({}) log({}) 发生异常]", req.getRequestURI(), JsonUtils.toJsonString(errorLog), th);
|
||||
}
|
||||
@@ -266,7 +297,7 @@ public class GlobalExceptionHandler {
|
||||
errorLog.setExceptionName(e.getClass().getName());
|
||||
errorLog.setExceptionMessage(ExceptionUtil.getMessage(e));
|
||||
errorLog.setExceptionRootCauseMessage(ExceptionUtil.getRootCauseMessage(e));
|
||||
errorLog.setExceptionStackTrace(ExceptionUtils.getStackTrace(e));
|
||||
errorLog.setExceptionStackTrace(ExceptionUtil.stacktraceToString(e));
|
||||
StackTraceElement[] stackTraceElements = e.getStackTrace();
|
||||
Assert.notEmpty(stackTraceElements, "异常 stackTraceElements 不能为空");
|
||||
StackTraceElement stackTraceElement = stackTraceElements[0];
|
||||
@@ -279,12 +310,12 @@ public class GlobalExceptionHandler {
|
||||
errorLog.setApplicationName(applicationName);
|
||||
errorLog.setRequestUrl(request.getRequestURI());
|
||||
Map<String, Object> requestParams = MapUtil.<String, Object>builder()
|
||||
.put("query", ServletUtils.getParamMap(request))
|
||||
.put("body", ServletUtils.getBody(request)).build();
|
||||
.put("query", JakartaServletUtil.getParamMap(request))
|
||||
.put("body", JakartaServletUtil.getBody(request)).build();
|
||||
errorLog.setRequestParams(JsonUtils.toJsonString(requestParams));
|
||||
errorLog.setRequestMethod(request.getMethod());
|
||||
errorLog.setUserAgent(ServletUtils.getUserAgent(request));
|
||||
errorLog.setUserIp(ServletUtils.getClientIP(request));
|
||||
errorLog.setUserIp(JakartaServletUtil.getClientIP(request));
|
||||
errorLog.setExceptionTime(LocalDateTime.now());
|
||||
}
|
||||
|
||||
@@ -301,51 +332,57 @@ public class GlobalExceptionHandler {
|
||||
}
|
||||
// 1. 数据报表
|
||||
if (message.contains("report_")) {
|
||||
log.error("[报表模块 yudao-module-report - 表结构未导入][参考 https://doc.iocoder.cn/report/ 开启]");
|
||||
log.error("[报表模块 yudao-module-report - 表结构未导入][参考 https://cloud.iocoder.cn/report/ 开启]");
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||
"[报表模块 yudao-module-report - 表结构未导入][参考 https://doc.iocoder.cn/report/ 开启]");
|
||||
"[报表模块 yudao-module-report - 表结构未导入][参考 https://cloud.iocoder.cn/report/ 开启]");
|
||||
}
|
||||
// 2. 工作流
|
||||
if (message.contains("bpm_")) {
|
||||
log.error("[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://doc.iocoder.cn/bpm/ 开启]");
|
||||
log.error("[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://cloud.iocoder.cn/bpm/ 开启]");
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||
"[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://doc.iocoder.cn/bpm/ 开启]");
|
||||
"[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://cloud.iocoder.cn/bpm/ 开启]");
|
||||
}
|
||||
// 3. 微信公众号
|
||||
if (message.contains("mp_")) {
|
||||
log.error("[微信公众号 yudao-module-mp - 表结构未导入][参考 https://doc.iocoder.cn/mp/build/ 开启]");
|
||||
log.error("[微信公众号 yudao-module-mp - 表结构未导入][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||
"[微信公众号 yudao-module-mp - 表结构未导入][参考 https://doc.iocoder.cn/mp/build/ 开启]");
|
||||
"[微信公众号 yudao-module-mp - 表结构未导入][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
|
||||
}
|
||||
// 4. 商城系统
|
||||
if (StrUtil.containsAny(message, "product_", "promotion_", "trade_")) {
|
||||
log.error("[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]");
|
||||
log.error("[商城系统 yudao-module-mall - 已禁用][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||
"[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]");
|
||||
"[商城系统 yudao-module-mall - 已禁用][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
|
||||
}
|
||||
// 5. ERP 系统
|
||||
if (message.contains("erp_")) {
|
||||
log.error("[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://doc.iocoder.cn/erp/build/ 开启]");
|
||||
log.error("[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||
"[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://doc.iocoder.cn/erp/build/ 开启]");
|
||||
"[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
|
||||
}
|
||||
// 6. CRM 系统
|
||||
if (message.contains("crm_")) {
|
||||
log.error("[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://doc.iocoder.cn/crm/build/ 开启]");
|
||||
log.error("[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||
"[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://doc.iocoder.cn/crm/build/ 开启]");
|
||||
"[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
|
||||
}
|
||||
// 7. 支付平台
|
||||
if (message.contains("pay_")) {
|
||||
log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]");
|
||||
log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://cloud.iocoder.cn/pay/build/ 开启]");
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||
"[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]");
|
||||
"[支付模块 yudao-module-pay - 表结构未导入][参考 https://cloud.iocoder.cn/pay/build/ 开启]");
|
||||
}
|
||||
// 8. AI 大模型
|
||||
if (message.contains("ai_")) {
|
||||
log.error("[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://doc.iocoder.cn/ai/build/ 开启]");
|
||||
log.error("[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||
"[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://doc.iocoder.cn/ai/build/ 开启]");
|
||||
"[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
|
||||
}
|
||||
// 9. IOT 物联网
|
||||
if (message.contains("iot_")) {
|
||||
log.error("[IOT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||
"[IOT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@@ -11,8 +11,8 @@ import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 专属于 web 包的工具类
|
||||
|
@@ -6,10 +6,10 @@ import lombok.AllArgsConstructor;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
@@ -2,8 +2,8 @@ package cn.iocoder.yudao.framework.xss.core.filter;
|
||||
|
||||
import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@@ -7,11 +7,11 @@ import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.PathMatcher;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
@@ -4,8 +4,8 @@ import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* WebSocket 配置项
|
||||
|
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
|
||||
import cn.iocoder.yudao.framework.websocket.config.WebSocketProperties;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
|
||||
|
||||
/**
|
||||
* WebSocket 的权限自定义
|
||||
@@ -17,8 +17,8 @@ public class WebSocketAuthorizeRequestsCustomizer extends AuthorizeRequestsCusto
|
||||
private final WebSocketProperties webSocketProperties;
|
||||
|
||||
@Override
|
||||
public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
|
||||
registry.antMatchers(webSocketProperties.getPath()).permitAll();
|
||||
public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry registry) {
|
||||
registry.requestMatchers(webSocketProperties.getPath()).permitAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维脑图等功能。
|
||||
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维导图等功能。
|
||||
目前已接入各种模型,不限于:
|
||||
国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek
|
||||
国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
|
||||
|
@@ -1,11 +1,8 @@
|
||||
package cn.iocoder.yudao.module.ai.enums;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* AI 内置聊天角色的枚举
|
||||
*
|
||||
@@ -13,16 +10,16 @@ import java.util.Arrays;
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum AiChatRoleEnum implements IntArrayValuable {
|
||||
public enum AiChatRoleEnum {
|
||||
|
||||
AI_WRITE_ROLE(1, "写作助手", """
|
||||
AI_WRITE_ROLE("写作助手", """
|
||||
你是一位出色的写作助手,能够帮助用户生成创意和灵感,并在用户提供场景和提示词时生成对应的回复。你的任务包括:
|
||||
1. 撰写建议:根据用户提供的主题或问题,提供详细的写作建议、情节发展方向、角色设定以及背景描写,确保内容结构清晰、有逻辑。
|
||||
2. 回复生成:根据用户提供的场景和提示词,生成合适的对话或文字回复,确保语气和风格符合场景需求。
|
||||
除此之外不需要除了正文内容外的其他回复,如标题、开头、任何解释性语句或道歉。
|
||||
"""),
|
||||
|
||||
AI_MIND_MAP_ROLE(2, "脑图助手", """
|
||||
AI_MIND_MAP_ROLE("导图助手", """
|
||||
你是一位非常优秀的思维导图助手,你会把用户的所有提问都总结成思维导图,然后以 Markdown 格式输出。markdown 只需要输出一级标题,二级标题,三级标题,四级标题,最多输出四级,除此之外不要输出任何其他 markdown 标记。下面是一个合格的例子:
|
||||
# Geek-AI 助手
|
||||
## 完整的开源系统
|
||||
@@ -39,11 +36,6 @@ public enum AiChatRoleEnum implements IntArrayValuable {
|
||||
除此之外不要任何解释性语句。
|
||||
""");
|
||||
|
||||
// TODO @xin:这个 role 是不是删除掉好点哈。= = 目前主要是没做角色枚举。这里多了 role 反倒容易误解哈
|
||||
/**
|
||||
* 角色
|
||||
*/
|
||||
private final Integer role;
|
||||
/**
|
||||
* 角色名
|
||||
*/
|
||||
@@ -54,11 +46,4 @@ public enum AiChatRoleEnum implements IntArrayValuable {
|
||||
*/
|
||||
private final String systemMessage;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AiChatRoleEnum::getRole).toArray();
|
||||
|
||||
@Override
|
||||
public int[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
|
||||
/**
|
||||
* AI 错误码枚举类
|
||||
*
|
||||
* <p>
|
||||
* ai 系统,使用 1-040-000-000 段
|
||||
*/
|
||||
public interface ErrorCodeConstants {
|
||||
@@ -45,9 +45,16 @@ public interface ErrorCodeConstants {
|
||||
// ========== API 音乐 1-040-006-000 ==========
|
||||
ErrorCode MUSIC_NOT_EXISTS = new ErrorCode(1_022_006_000, "音乐不存在!");
|
||||
|
||||
|
||||
// ========== API 写作 1-022-007-000 ==========
|
||||
ErrorCode WRITE_NOT_EXISTS = new ErrorCode(1_022_007_000, "作文不存在!");
|
||||
ErrorCode WRITE_STREAM_ERROR = new ErrorCode(1_022_07_001, "写作生成异常!");
|
||||
|
||||
// ========== API 思维导图 1-040-008-000 ==========
|
||||
ErrorCode MIND_MAP_NOT_EXISTS = new ErrorCode(1_040_008_000, "思维导图不存在!");
|
||||
|
||||
// ========== API 知识库 1-022-008-000 ==========
|
||||
ErrorCode KNOWLEDGE_NOT_EXISTS = new ErrorCode(1_022_008_000, "知识库不存在!");
|
||||
ErrorCode KNOWLEDGE_DOCUMENT_NOT_EXISTS = new ErrorCode(1_022_008_001, "文档不存在!");
|
||||
ErrorCode KNOWLEDGE_SEGMENT_NOT_EXISTS = new ErrorCode(1_022_008_002, "段落不存在!");
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.ai.enums.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* AI 知识库-文档状态的枚举
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum AiKnowledgeDocumentStatusEnum implements IntArrayValuable {
|
||||
|
||||
IN_PROGRESS(10, "索引中"),
|
||||
SUCCESS(20, "可用"),
|
||||
FAIL(30, "失败");
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private final Integer status;
|
||||
|
||||
/**
|
||||
* 状态名
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AiKnowledgeDocumentStatusEnum::getStatus).toArray();
|
||||
|
||||
@Override
|
||||
public int[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
@@ -12,7 +12,7 @@
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维脑图等功能。
|
||||
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维导图等功能。
|
||||
目前已接入各种模型,不限于:
|
||||
国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek
|
||||
国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
|
||||
|
@@ -5,10 +5,7 @@ import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDrawReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageRespVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyActionReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyImagineReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO;
|
||||
@@ -45,6 +42,13 @@ public class AiImageController {
|
||||
return success(BeanUtils.toBean(pageResult, AiImageRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/public-page")
|
||||
@Operation(summary = "获取公开的绘图分页")
|
||||
public CommonResult<PageResult<AiImageRespVO>> getImagePagePublic(AiImagePublicPageReqVO pageReqVO) {
|
||||
PageResult<AiImageDO> pageResult = imageService.getImagePagePublic(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, AiImageRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/get-my")
|
||||
@Operation(summary = "获取【我的】绘图记录")
|
||||
@Parameter(name = "id", required = true, description = "绘画编号", example = "1024")
|
||||
|
@@ -0,0 +1,14 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.image.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - AI 绘画公开的分页 Request VO")
|
||||
@Data
|
||||
public class AiImagePublicPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "提示词")
|
||||
private String prompt;
|
||||
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeCreateMyReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeRespVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeUpdateMyReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO;
|
||||
import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "管理后台 - AI 知识库")
|
||||
@RestController
|
||||
@RequestMapping("/ai/knowledge")
|
||||
@Validated
|
||||
public class AiKnowledgeController {
|
||||
|
||||
@Resource
|
||||
private AiKnowledgeService knowledgeService;
|
||||
|
||||
@GetMapping("/my-page")
|
||||
@Operation(summary = "获取【我的】知识库分页")
|
||||
public CommonResult<PageResult<AiKnowledgeRespVO>> getKnowledgePageMy(@Validated PageParam pageReqVO) {
|
||||
PageResult<AiKnowledgeDO> pageResult = knowledgeService.getKnowledgePageMy(getLoginUserId(), pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, AiKnowledgeRespVO.class));
|
||||
}
|
||||
|
||||
@PostMapping("/create-my")
|
||||
@Operation(summary = "创建【我的】知识库")
|
||||
public CommonResult<Long> createKnowledgeMy(@RequestBody @Valid AiKnowledgeCreateMyReqVO createReqVO) {
|
||||
return success(knowledgeService.createKnowledgeMy(createReqVO, getLoginUserId()));
|
||||
}
|
||||
|
||||
@PutMapping("/update-my")
|
||||
@Operation(summary = "更新【我的】知识库")
|
||||
public CommonResult<Boolean> updateKnowledgeMy(@RequestBody @Valid AiKnowledgeUpdateMyReqVO updateReqVO) {
|
||||
knowledgeService.updateKnowledgeMy(updateReqVO, getLoginUserId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentRespVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeDocumentCreateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
|
||||
import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - AI 知识库文档")
|
||||
@RestController
|
||||
@RequestMapping("/ai/knowledge/document")
|
||||
@Validated
|
||||
public class AiKnowledgeDocumentController {
|
||||
|
||||
@Resource
|
||||
private AiKnowledgeDocumentService documentService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "新建文档")
|
||||
public CommonResult<Long> createKnowledgeDocument(@Valid AiKnowledgeDocumentCreateReqVO reqVO) {
|
||||
Long knowledgeDocumentId = documentService.createKnowledgeDocument(reqVO);
|
||||
return success(knowledgeDocumentId);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获取文档分页")
|
||||
public CommonResult<PageResult<AiKnowledgeDocumentRespVO>> getKnowledgeDocumentPageMy(@Valid AiKnowledgeDocumentPageReqVO pageReqVO) {
|
||||
PageResult<AiKnowledgeDocumentDO> pageResult = documentService.getKnowledgeDocumentPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, AiKnowledgeDocumentRespVO.class));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新文档")
|
||||
public CommonResult<Boolean> updateKnowledgeDocument(@Valid @RequestBody AiKnowledgeDocumentUpdateReqVO reqVO) {
|
||||
documentService.updateKnowledgeDocument(reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentRespVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateStatusReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
|
||||
import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeSegmentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - AI 知识库段落")
|
||||
@RestController
|
||||
@RequestMapping("/ai/knowledge/segment")
|
||||
@Validated
|
||||
public class AiKnowledgeSegmentController {
|
||||
|
||||
@Resource
|
||||
private AiKnowledgeSegmentService segmentService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获取段落分页")
|
||||
public CommonResult<PageResult<AiKnowledgeSegmentRespVO>> getKnowledgeSegmentPageMy(@Valid AiKnowledgeSegmentPageReqVO pageReqVO) {
|
||||
PageResult<AiKnowledgeSegmentDO> pageResult = segmentService.getKnowledgeSegmentPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, AiKnowledgeSegmentRespVO.class));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新段落内容")
|
||||
public CommonResult<Boolean> updateKnowledgeSegment(@Valid @RequestBody AiKnowledgeSegmentUpdateReqVO reqVO) {
|
||||
segmentService.updateKnowledgeSegment(reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-status")
|
||||
@Operation(summary = "启禁用段落内容")
|
||||
public CommonResult<Boolean> updateKnowledgeSegmentStatus(@Valid @RequestBody AiKnowledgeSegmentUpdateStatusReqVO reqVO) {
|
||||
segmentService.updateKnowledgeSegmentStatus(reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库文档的分页 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeDocumentPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "文档名称", example = "Java 开发手册")
|
||||
private String name;
|
||||
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库-文档 Response VO")
|
||||
@Data
|
||||
public class AiKnowledgeDocumentRespVO extends PageParam {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long knowledgeId;
|
||||
|
||||
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 是一门面向对象的语言.....")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "文档 url", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://doc.iocoder.cn")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer tokens;
|
||||
|
||||
@Schema(description = "字符数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1008")
|
||||
private Integer wordCount;
|
||||
|
||||
@Schema(description = "切片状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer sliceStatus;
|
||||
|
||||
@Schema(description = "文档状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status;
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - AI 更新 知识库-文档 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeDocumentUpdateReqVO {
|
||||
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583")
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "是否启用", example = "1")
|
||||
@InEnum(CommonStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "名称", example = "Java 开发手册")
|
||||
private String name;
|
||||
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库创建【我的】 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeCreateMyReqVO {
|
||||
|
||||
@Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ruoyi-vue-pro 用户指南")
|
||||
@NotBlank(message = "知识库名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "知识库描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "存储 ruoyi-vue-pro 操作文档")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "可见权限,只能选择哪些人可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1]")
|
||||
private List<Long> visibilityPermissions;
|
||||
|
||||
@Schema(description = "嵌入模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "嵌入模型不能为空")
|
||||
private Long modelId;
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库文档的创建 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeDocumentCreateReqVO {
|
||||
|
||||
@Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1204")
|
||||
@NotNull(message = "知识库编号不能为空")
|
||||
private Long knowledgeId;
|
||||
|
||||
@Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "三方登陆")
|
||||
@NotBlank(message = "文档名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "文档 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://doc.iocoder.cn")
|
||||
@URL(message = "文档 URL 格式不正确")
|
||||
private String url;
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库 Response VO")
|
||||
@Data
|
||||
public class AiKnowledgeRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ruoyi-vue-pro 用户指南")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "知识库描述", example = "帮助你快速构建系统")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "14")
|
||||
private Long modelId;
|
||||
|
||||
@Schema(description = "模型标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "qwen-72b-chat")
|
||||
private String model;
|
||||
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库更新【我的】 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeUpdateMyReqVO {
|
||||
|
||||
@Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1204")
|
||||
@NotNull(message = "知识库编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
|
||||
@NotBlank(message = "知识库名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "知识库描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "可见权限,只能选择哪些人可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1]")
|
||||
private List<Long> visibilityPermissions;
|
||||
|
||||
@Schema(description = "嵌入模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "嵌入模型不能为空")
|
||||
private Long modelId;
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库分段的分页 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeSegmentPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "分段状态", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "文档编号", example = "1")
|
||||
private Integer documentId;
|
||||
|
||||
@Schema(description = "分段内容关键字", example = "Java 开发")
|
||||
private String keyword;
|
||||
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库-文档 Response VO")
|
||||
@Data
|
||||
public class AiKnowledgeSegmentRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long documentId;
|
||||
|
||||
@Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long knowledgeId;
|
||||
|
||||
@Schema(description = "向量库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1858496a-1dde-4edf-a43e-0aed08f37f8c")
|
||||
private String vectorId;
|
||||
|
||||
@Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer tokens;
|
||||
|
||||
@Schema(description = "字符数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1008")
|
||||
private Integer wordCount;
|
||||
|
||||
@Schema(description = "文档状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status;
|
||||
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - AI 更新 知识库-段落 request VO")
|
||||
@Data
|
||||
public class AiKnowledgeSegmentUpdateReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册")
|
||||
private String content;
|
||||
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库段落的更新状态 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeSegmentUpdateStatusReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "是否启用不能为空")
|
||||
@InEnum(CommonStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
}
|
@@ -1,20 +1,25 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.mindmap;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapRespVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO;
|
||||
import cn.iocoder.yudao.module.ai.service.mindmap.AiMindMapService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "管理后台 - AI 思维导图")
|
||||
@@ -26,10 +31,29 @@ public class AiMindMapController {
|
||||
private AiMindMapService mindMapService;
|
||||
|
||||
@PostMapping(value = "/generate-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
@Operation(summary = "脑图生成(流式)", description = "流式返回,响应较快")
|
||||
@Operation(summary = "导图生成(流式)", description = "流式返回,响应较快")
|
||||
@PermitAll // 解决 SSE 最终响应的时候,会被 Access Denied 拦截的问题
|
||||
public Flux<CommonResult<String>> generateMindMap(@RequestBody @Valid AiMindMapGenerateReqVO generateReqVO) {
|
||||
return mindMapService.generateMindMap(generateReqVO, getLoginUserId());
|
||||
}
|
||||
|
||||
// ================ 导图管理 ================
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除思维导图")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('ai:mind-map:delete')")
|
||||
public CommonResult<Boolean> deleteMindMap(@RequestParam("id") Long id) {
|
||||
mindMapService.deleteMindMap(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得思维导图分页")
|
||||
@PreAuthorize("@ss.hasPermission('ai:mind-map:query')")
|
||||
public CommonResult<PageResult<AiMindMapRespVO>> getMindMapPage(@Valid AiMindMapPageReqVO pageReqVO) {
|
||||
PageResult<AiMindMapDO> pageResult = mindMapService.getMindMapPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, AiMindMapRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - AI 思维导图分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class AiMindMapPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "用户编号", example = "4325")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "生成内容提示", example = "Java 学习路线")
|
||||
private String prompt;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - AI 思维导图 Response VO")
|
||||
@Data
|
||||
public class AiMindMapRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3373")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4325")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "生成内容提示", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 学习路线")
|
||||
private String prompt;
|
||||
|
||||
@Schema(description = "生成的思维导图内容")
|
||||
private String generatedContent;
|
||||
|
||||
@Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI")
|
||||
private String platform;
|
||||
|
||||
@Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo-0125")
|
||||
private String model;
|
||||
|
||||
@Schema(description = "错误信息")
|
||||
private String errorMessage;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@@ -30,7 +30,7 @@ public class AiImageDO extends BaseDO {
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,61 @@
|
||||
package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AI 知识库 DO
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@TableName(value = "ai_knowledge", autoResultMap = true)
|
||||
@Data
|
||||
public class AiKnowledgeDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 用户编号
|
||||
* <p>
|
||||
* 关联 AdminUserDO 的 userId 字段
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 知识库名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 知识库描述
|
||||
*/
|
||||
private String description;
|
||||
// TODO @新:如果全部可见,需要怎么设置?
|
||||
/**
|
||||
* 可见权限,只能选择哪些人可见
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<Long> visibilityPermissions;
|
||||
/**
|
||||
* 嵌入模型编号
|
||||
*/
|
||||
private Long modelId;
|
||||
/**
|
||||
* 模型标识
|
||||
*/
|
||||
private String model;
|
||||
/**
|
||||
* 状态
|
||||
* <p>
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.ai.enums.knowledge.AiKnowledgeDocumentStatusEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* AI 知识库-文档 DO
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@TableName(value = "ai_knowledge_document")
|
||||
@Data
|
||||
public class AiKnowledgeDocumentDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 知识库编号
|
||||
*
|
||||
* 关联 {@link AiKnowledgeDO#getId()}
|
||||
*/
|
||||
private Long knowledgeId;
|
||||
/**
|
||||
* 文件名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 文件 URL
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* token 数量
|
||||
*/
|
||||
private Integer tokens;
|
||||
/**
|
||||
* 字符数
|
||||
*/
|
||||
private Integer wordCount;
|
||||
/**
|
||||
* 切片状态
|
||||
* <p>
|
||||
* 枚举 {@link AiKnowledgeDocumentStatusEnum}
|
||||
*/
|
||||
private Integer sliceStatus;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
* <p>
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* AI 知识库-文档分段 DO
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@TableName(value = "ai_knowledge_segment")
|
||||
@Data
|
||||
public class AiKnowledgeSegmentDO extends BaseDO {
|
||||
|
||||
public static final String FIELD_KNOWLEDGE_ID = "knowledgeId";
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 向量库的编号
|
||||
*/
|
||||
private String vectorId;
|
||||
/**
|
||||
* 知识库编号
|
||||
*
|
||||
* 关联 {@link AiKnowledgeDO#getId()}
|
||||
*/
|
||||
private Long knowledgeId;
|
||||
/**
|
||||
* 文档编号
|
||||
*
|
||||
* 关联 {@link AiKnowledgeDocumentDO#getId()}
|
||||
*/
|
||||
private Long documentId;
|
||||
/**
|
||||
* 切片内容
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 字符数
|
||||
*/
|
||||
private Integer wordCount;
|
||||
/**
|
||||
* token 数量
|
||||
*/
|
||||
private Integer tokens;
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user