Compare commits
95 Commits
v2025.08(j
...
master
Author | SHA1 | Date |
---|---|---|
![]() |
34c9f1c285 | |
![]() |
5211b4e64f | |
![]() |
cb5f05b421 | |
![]() |
21243b124c | |
![]() |
8fbd9e818c | |
![]() |
ed962134f6 | |
![]() |
0838c3345a | |
![]() |
e07a81f81c | |
![]() |
edb5cdd372 | |
![]() |
34aea48b7c | |
![]() |
32a68885bb | |
![]() |
cbba929db8 | |
![]() |
78dea8a9cc | |
![]() |
44c9391254 | |
![]() |
92581e3b24 | |
![]() |
a89b6d14a8 | |
![]() |
d8fbd0f6c5 | |
![]() |
0626acc93b | |
![]() |
b584e56023 | |
![]() |
c015b68db8 | |
![]() |
2321829cc3 | |
![]() |
24402eaeef | |
![]() |
2503432067 | |
![]() |
59429be4df | |
![]() |
85a87a234a | |
![]() |
88687d2719 | |
![]() |
a66fe7cc10 | |
![]() |
6980b8cab9 | |
![]() |
178ee2004b | |
![]() |
41ef63d5d0 | |
![]() |
c52d76b274 | |
![]() |
de5795dca7 | |
![]() |
abf26721c2 | |
![]() |
7d2f7cd7fd | |
![]() |
ffb883f55e | |
![]() |
c9f6b6c1ef | |
![]() |
1b2abcc10e | |
![]() |
045b362142 | |
![]() |
606e9e27a5 | |
![]() |
35d62571fd | |
![]() |
ad5f07ce02 | |
![]() |
c87fe17ee6 | |
![]() |
63b4b52613 | |
![]() |
7b8401c715 | |
![]() |
a63587e8cb | |
![]() |
fceaa7ae00 | |
![]() |
b30396d149 | |
![]() |
7edcebf51f | |
![]() |
caa75004fb | |
![]() |
e34ed5cfa6 | |
![]() |
091591f1c0 | |
![]() |
2573a98f72 | |
![]() |
273d8f6a2a | |
![]() |
e792054adb | |
![]() |
b836c28736 | |
![]() |
9252e7b5f0 | |
![]() |
921398e437 | |
![]() |
816e1fbf9b | |
![]() |
8e45cf5787 | |
![]() |
49572b2994 | |
![]() |
a980c09d01 | |
![]() |
37d120b193 | |
![]() |
2cabcbcf8d | |
![]() |
8ae052a750 | |
![]() |
6434ba1847 | |
![]() |
9c6c2f154a | |
![]() |
8d686bc618 | |
![]() |
3baeb4f8ef | |
![]() |
88c9335f7a | |
![]() |
adadcf4f62 | |
![]() |
c55fe616b6 | |
![]() |
b4df6f93cb | |
![]() |
66824310c1 | |
![]() |
110c38bf6e | |
![]() |
8772b9444d | |
![]() |
fa02450c56 | |
![]() |
7cca8d09b1 | |
![]() |
89fccaf4a9 | |
![]() |
1ad76857b3 | |
![]() |
cd08ffe9e8 | |
![]() |
9f4c7f1fea | |
![]() |
2de710190e | |
![]() |
2382c3d844 | |
![]() |
d7a1562f0b | |
![]() |
f0c89963b9 | |
![]() |
1f02103d1b | |
![]() |
104d94977b | |
![]() |
a277987139 | |
![]() |
9502fef140 | |
![]() |
c252bc246f | |
![]() |
840ab74677 | |
![]() |
ec990c9a4f | |
![]() |
9f8188dcd4 | |
![]() |
19ca4e7e89 | |
![]() |
953a33b4f7 |
Binary file not shown.
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 40 KiB |
6
pom.xml
6
pom.xml
|
@ -34,14 +34,14 @@
|
|||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||
|
||||
<properties>
|
||||
<revision>2025.08-jdk8-SNAPSHOT</revision>
|
||||
<revision>2025.09-jdk8-SNAPSHOT</revision>
|
||||
<!-- Maven 相关 -->
|
||||
<java.version>1.8</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<maven-surefire-plugin.version>3.2.2</maven-surefire-plugin.version>
|
||||
<maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version>
|
||||
<maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>
|
||||
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
|
||||
<flatten-maven-plugin.version>1.7.2</flatten-maven-plugin.version>
|
||||
<!-- maven-surefire-plugin 暂时无法通过 bom 的依赖读取(兼容老版本 IDEA 2024 及以前版本) -->
|
||||
<lombok.version>1.18.38</lombok.version>
|
||||
<spring.boot.version>2.7.18</spring.boot.version>
|
||||
|
|
|
@ -4303,7 +4303,7 @@ CREATE TABLE system_tenant
|
|||
contact_name varchar(30) NOT NULL,
|
||||
contact_mobile varchar(500) DEFAULT NULL NULL,
|
||||
status smallint DEFAULT 0 NOT NULL,
|
||||
website varchar(256) DEFAULT '' NULL,
|
||||
websites varchar(256) DEFAULT '' NULL,
|
||||
package_id bigint NOT NULL,
|
||||
expire_time datetime NOT NULL,
|
||||
account_count int NOT NULL,
|
||||
|
@ -4320,7 +4320,7 @@ COMMENT ON COLUMN system_tenant.contact_user_id IS '联系人的用户编号';
|
|||
COMMENT ON COLUMN system_tenant.contact_name IS '联系人';
|
||||
COMMENT ON COLUMN system_tenant.contact_mobile IS '联系手机';
|
||||
COMMENT ON COLUMN system_tenant.status IS '租户状态(0正常 1停用)';
|
||||
COMMENT ON COLUMN system_tenant.website IS '绑定域名';
|
||||
COMMENT ON COLUMN system_tenant.websites IS '绑定域名数组';
|
||||
COMMENT ON COLUMN system_tenant.package_id IS '租户套餐编号';
|
||||
COMMENT ON COLUMN system_tenant.expire_time IS '过期时间';
|
||||
COMMENT ON COLUMN system_tenant.account_count IS '账号数量';
|
||||
|
@ -4336,9 +4336,9 @@ COMMENT ON TABLE system_tenant IS '租户表';
|
|||
-- ----------------------------
|
||||
-- @formatter:off
|
||||
SET IDENTITY_INSERT system_tenant ON;
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2026-07-10 00:00:00', 30, '1', '2022-02-22 00:56:14', '1', '2025-04-03 21:33:01', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2024-09-22 12:10:50', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2026-07-10 00:00:00', 30, '1', '2022-02-22 00:56:14', '1', '2025-04-03 21:33:01', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2024-09-22 12:10:50', '0');
|
||||
COMMIT;
|
||||
SET IDENTITY_INSERT system_tenant OFF;
|
||||
-- @formatter:on
|
||||
|
|
|
@ -4608,7 +4608,7 @@ CREATE TABLE system_tenant
|
|||
contact_name varchar(30) NOT NULL,
|
||||
contact_mobile varchar(500) NULL DEFAULT NULL,
|
||||
status int2 NOT NULL DEFAULT 0,
|
||||
website varchar(256) NULL DEFAULT '',
|
||||
websites varchar(256) NULL DEFAULT '',
|
||||
package_id int8 NOT NULL,
|
||||
expire_time timestamp NOT NULL,
|
||||
account_count int4 NOT NULL,
|
||||
|
@ -4628,7 +4628,7 @@ COMMENT ON COLUMN system_tenant.contact_user_id IS '联系人的用户编号';
|
|||
COMMENT ON COLUMN system_tenant.contact_name IS '联系人';
|
||||
COMMENT ON COLUMN system_tenant.contact_mobile IS '联系手机';
|
||||
COMMENT ON COLUMN system_tenant.status IS '租户状态(0正常 1停用)';
|
||||
COMMENT ON COLUMN system_tenant.website IS '绑定域名';
|
||||
COMMENT ON COLUMN system_tenant.websites IS '绑定域名数组';
|
||||
COMMENT ON COLUMN system_tenant.package_id IS '租户套餐编号';
|
||||
COMMENT ON COLUMN system_tenant.expire_time IS '过期时间';
|
||||
COMMENT ON COLUMN system_tenant.account_count IS '账号数量';
|
||||
|
@ -4644,9 +4644,9 @@ COMMENT ON TABLE system_tenant IS '租户表';
|
|||
-- ----------------------------
|
||||
-- @formatter:off
|
||||
BEGIN;
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2026-07-10 00:00:00', 30, '1', '2022-02-22 00:56:14', '1', '2025-04-03 21:33:01', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2024-09-22 12:10:50', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2026-07-10 00:00:00', 30, '1', '2022-02-22 00:56:14', '1', '2025-04-03 21:33:01', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2024-09-22 12:10:50', '0');
|
||||
COMMIT;
|
||||
-- @formatter:on
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
Target Server Version : 80200 (8.2.0)
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 12/05/2025 09:09:45
|
||||
Date: 31/08/2025 11:12:28
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
|
@ -49,7 +49,7 @@ CREATE TABLE `infra_api_access_log` (
|
|||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_create_time`(`create_time` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 35953 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 36233 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_api_access_log
|
||||
|
@ -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 = 22175 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 22656 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 = 2538 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2603 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 = 191 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 196 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_codegen_table
|
||||
|
@ -251,7 +251,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 = 1898 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1983 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_file
|
||||
|
@ -276,21 +276,22 @@ CREATE TABLE `infra_file_config` (
|
|||
`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 = 31 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件配置表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 35 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件配置表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_file_config
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (4, '数据库(示例)', 1, '我是数据库', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.db.DBFileClientConfig\",\"domain\":\"http://127.0.0.1:48080\"}', '1', '2022-03-15 23:56:24', '1', '2025-05-02 18:30:28', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (22, '七牛存储器(示例)', 20, '请换成你自己的密钥!!!', b'1', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"s3.cn-south-1.qiniucs.com\",\"domain\":\"http://test.yudao.iocoder.cn\",\"bucket\":\"ruoyi-vue-pro\",\"accessKey\":\"3TvrJ70gl2Gt6IBe7_IZT1F6i_k0iMuRtyEv4EyS\",\"accessSecret\":\"wd0tbVBYlp0S-ihA8Qg2hPLncoP83wyrIq24OZuY\",\"enablePathStyleAccess\":false}', '1', '2024-01-13 22:11:12', '1', '2025-05-02 18:30:28', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (24, '腾讯云存储(示例)', 20, '请换成你的密钥!!!', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"https://cos.ap-shanghai.myqcloud.com\",\"domain\":\"http://tengxun-oss.iocoder.cn\",\"bucket\":\"aoteman-1255880240\",\"accessKey\":\"AKIDAF6WSh1uiIjwqtrOsGSN3WryqTM6cTMt\",\"accessSecret\":\"X\"}', '1', '2024-11-09 16:03:22', '1', '2025-05-02 18:30:28', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (25, '阿里云存储(示例)', 20, '', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"oss-cn-beijing.aliyuncs.com\",\"domain\":\"http://ali-oss.iocoder.cn\",\"bucket\":\"yunai-aoteman\",\"accessKey\":\"LTAI5tEQLgnDyjh3WpNcdMKA\",\"accessSecret\":\"X\",\"enablePathStyleAccess\":false}', '1', '2024-11-09 16:47:08', '1', '2025-05-02 18:30:28', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (26, '火山云存储(示例)', 20, '', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"tos-s3-cn-beijing.volces.com\",\"domain\":null,\"bucket\":\"yunai\",\"accessKey\":\"AKLTZjc3Zjc4MzZmMjU3NDk0ZTgxYmIyMmFkNTIwMDI1ZGE\",\"accessSecret\":\"X==\",\"enablePathStyleAccess\":false}', '1', '2024-11-09 16:56:42', '1', '2025-05-02 18:30:28', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (27, '华为云存储(示例)', 20, '', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"obs.cn-east-3.myhuaweicloud.com\",\"domain\":\"\",\"bucket\":\"yudao\",\"accessKey\":\"PVDONDEIOTW88LF8DC4U\",\"accessSecret\":\"X\",\"enablePathStyleAccess\":false}', '1', '2024-11-09 17:18:41', '1', '2025-05-02 18:30:28', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (28, 'MinIO 存储(示例)', 20, '', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"http://127.0.0.1:9000\",\"domain\":\"http://127.0.0.1:9000/yudao\",\"bucket\":\"yudao\",\"accessKey\":\"admin\",\"accessSecret\":\"password\",\"enablePathStyleAccess\":false}', '1', '2024-11-09 17:43:10', '1', '2025-05-02 18:30:28', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (29, '本地存储(示例)', 10, '仅适合 mac 或 windows', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.local.LocalFileClientConfig\",\"basePath\":\"/Users/yunai/tmp/file\",\"domain\":\"http://127.0.0.1:48080\"}', '1', '2025-05-02 11:25:45', '1', '2025-05-02 18:30:28', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (30, 'SFTP 存储(示例)', 12, '', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.sftp.SftpFileClientConfig\",\"basePath\":\"/upload\",\"domain\":\"http://127.0.0.1:48080\",\"host\":\"127.0.0.1\",\"port\":2222,\"username\":\"foo\",\"password\":\"pass\"}', '1', '2025-05-02 16:34:10', '1', '2025-05-02 18:30:28', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (4, '数据库(示例)', 1, '我是数据库', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.db.DBFileClientConfig\",\"domain\":\"http://127.0.0.1:48080\"}', '1', '2022-03-15 23:56:24', '1', '2025-08-18 08:35:14', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (22, '七牛存储器(示例)', 20, '请换成你自己的密钥!!!', b'1', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"s3.cn-south-1.qiniucs.com\",\"domain\":\"http://test.yudao.iocoder.cn\",\"bucket\":\"ruoyi-vue-pro\",\"accessKey\":\"3TvrJ70gl2Gt6IBe7_IZT1F6i_k0iMuRtyEv4EyS\",\"accessSecret\":\"wd0tbVBYlp0S-ihA8Qg2hPLncoP83wyrIq24OZuY\",\"enablePathStyleAccess\":false,\"enablePublicAccess\":true}', '1', '2024-01-13 22:11:12', '1', '2025-08-18 08:35:14', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (24, '腾讯云存储(示例)', 20, '请换成你的密钥!!!', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"https://cos.ap-shanghai.myqcloud.com\",\"domain\":\"http://tengxun-oss.iocoder.cn\",\"bucket\":\"aoteman-1255880240\",\"accessKey\":\"AKIDAF6WSh1uiIjwqtrOsGSN3WryqTM6cTMt\",\"accessSecret\":\"X\",\"enablePathStyleAccess\":false,\"enablePublicAccess\":true}', '1', '2024-11-09 16:03:22', '1', '2025-08-18 08:35:14', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (25, '阿里云存储(示例)', 20, '', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"oss-cn-beijing.aliyuncs.com\",\"domain\":\"http://ali-oss.iocoder.cn\",\"bucket\":\"yunai-aoteman\",\"accessKey\":\"LTAI5tEQLgnDyjh3WpNcdMKA\",\"accessSecret\":\"X\",\"enablePathStyleAccess\":false,\"enablePublicAccess\":true}', '1', '2024-11-09 16:47:08', '1', '2025-08-18 08:35:14', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (26, '火山云存储(示例)', 20, '', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"tos-s3-cn-beijing.volces.com\",\"domain\":null,\"bucket\":\"yunai\",\"accessKey\":\"AKLTZjc3Zjc4MzZmMjU3NDk0ZTgxYmIyMmFkNTIwMDI1ZGE\",\"accessSecret\":\"X==\",\"enablePathStyleAccess\":false,\"enablePublicAccess\":true}', '1', '2024-11-09 16:56:42', '1', '2025-08-18 08:35:14', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (27, '华为云存储(示例)', 20, '', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"obs.cn-east-3.myhuaweicloud.com\",\"domain\":\"\",\"bucket\":\"yudao\",\"accessKey\":\"PVDONDEIOTW88LF8DC4U\",\"accessSecret\":\"X\",\"enablePathStyleAccess\":false}', '1', '2024-11-09 17:18:41', '1', '2025-08-18 08:35:14', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (28, 'MinIO 存储(示例)', 20, '', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"http://127.0.0.1:9000\",\"domain\":\"http://127.0.0.1:9000/yudao\",\"bucket\":\"yudao\",\"accessKey\":\"admin\",\"accessSecret\":\"password\",\"enablePathStyleAccess\":false,\"enablePublicAccess\":true}', '1', '2024-11-09 17:43:10', '1', '2025-08-18 08:35:14', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (29, '本地存储(示例)', 10, '仅适合 mac 或 windows', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.local.LocalFileClientConfig\",\"basePath\":\"/Users/yunai/tmp/file\",\"domain\":\"http://127.0.0.1:48080\"}', '1', '2025-05-02 11:25:45', '1', '2025-08-18 08:35:14', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (30, 'SFTP 存储(示例)', 12, '', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.sftp.SftpFileClientConfig\",\"basePath\":\"/upload\",\"domain\":\"http://127.0.0.1:48080\",\"host\":\"127.0.0.1\",\"port\":2222,\"username\":\"foo\",\"password\":\"pass\"}', '1', '2025-05-02 16:34:10', '1', '2025-08-18 08:35:14', b'0');
|
||||
INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (34, '七牛云存储【私有】(示例)', 20, '请换成你自己的密钥!!!', b'0', '{\"@class\":\"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"s3.cn-south-1.qiniucs.com\",\"domain\":\"http://t151glocd.hn-bkt.clouddn.com\",\"bucket\":\"ruoyi-vue-pro-private\",\"accessKey\":\"3TvrJ70gl2Gt6IBe7_IZT1F6i_k0iMuRtyEv4EyS\",\"accessSecret\":\"wd0tbVBYlp0S-ihA8Qg2hPLncoP83wyrIq24OZuY\",\"enablePathStyleAccess\":false,\"enablePublicAccess\":false}', '1', '2025-08-17 21:22:00', '1', '2025-08-18 08:35:55', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -336,7 +337,7 @@ CREATE TABLE `infra_job` (
|
|||
`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 = 36 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 38 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_job
|
||||
|
@ -355,6 +356,8 @@ INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`
|
|||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (27, '任务日志清理 Job', 2, 'jobLogCleanJob', '', '0 0 0 * * ?', 3, 0, 0, '1', '2023-10-03 11:01:33', '1', '2024-09-12 13:40:34', b'0');
|
||||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (33, 'demoJob', 2, 'demoJob', '', '0 * * * * ?', 1, 1, 0, '1', '2024-10-27 19:38:46', '1', '2025-05-10 18:13:54', b'0');
|
||||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (35, '转账订单的同步 Job', 2, 'payTransferSyncJob', '', '0 * * * * ?', 0, 0, 0, '1', '2025-05-10 17:35:54', '1', '2025-05-10 18:13:52', b'0');
|
||||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (36, 'IoT 设备离线检查 Job', 2, 'iotDeviceOfflineCheckJob', '', '0 * * * * ?', 0, 0, 0, '1', '2025-07-03 23:48:44', '\"1\"', '2025-07-03 23:48:47', b'0');
|
||||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (37, 'IoT OTA 升级推送 Job', 2, 'iotOtaUpgradeJob', '', '0 * * * * ?', 0, 0, 0, '1', '2025-07-03 23:49:07', '\"1\"', '2025-07-03 23:49:13', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -378,7 +381,7 @@ CREATE TABLE `infra_job_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 = 972 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 980 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_job_log
|
||||
|
@ -448,7 +451,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 = 3003 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 3031 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_dict_data
|
||||
|
@ -639,7 +642,7 @@ 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 (1230, 13, '支付宝条码支付', 'alipay_bar', 'pay_channel_code', 0, 'primary', '', '支付宝条码支付', '1', '2023-02-18 23:32:24', '1', '2023-07-19 20:09:23', 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 (1231, 10, 'Vue2 Element UI 标准模版', '10', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:03:55', '1', '2023-04-13 00:03:55', 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 (1232, 20, 'Vue3 Element Plus 标准模版', '20', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:04:08', '1', '2023-04-13 00:04:08', 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 (1234, 30, 'Vben2.0 Ant Design Schema 模版', '30', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:04:26', '1', '2025-04-23 21:27:34', 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 (1234, 30, 'Vben2.0 Ant Design Schema 模版', '30', 'infra_codegen_front_type', 1, '', '', '', '1', '2023-04-13 00:04:26', '1', '2025-07-27 10:55:14', 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 (1244, 0, '按件', '1', 'trade_delivery_express_charge_mode', 0, '', '', '', '1', '2023-05-21 22:46:40', '1', '2023-05-21 22:46:40', 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 (1245, 1, '按重量', '2', 'trade_delivery_express_charge_mode', 0, '', '', '', '1', '2023-05-21 22:46:58', '1', '2023-05-21 22:46: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 (1246, 2, '按体积', '3', 'trade_delivery_express_charge_mode', 0, '', '', '', '1', '2023-05-21 22:47:18', '1', '2023-05-21 22:47:18', b'0');
|
||||
|
@ -881,36 +884,21 @@ 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 (1691, 6, '重排', '6', 'ai_model_type', 0, '', '', '', '1', '2025-03-03 12:28:26', '1', '2025-03-03 12:28:26', 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 (1692, 14, 'MiniMax', 'MiniMax', 'ai_platform', 0, '', '', '', '1', '2025-03-11 20:04:51', '1', '2025-03-11 20:04:51', 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 (1693, 15, '月之暗灭', 'Moonshot', 'ai_platform', 0, '', '', '', '1', '2025-03-11 20:05:08', '1', '2025-03-11 20:05:08', 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 (2000, 0, '标准数据格式(JSON)', '0', 'iot_data_format', 0, 'default', '', '', '1', '2024-08-10 11:53:26', '1', '2025-03-17 09:28: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 (2001, 1, '透传/自定义', '1', 'iot_data_format', 0, 'default', '', '', '1', '2024-08-10 11:53:37', '1', '2025-03-17 09:28:19', 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 (2002, 0, '直连设备', '0', 'iot_product_device_type', 0, 'default', '', '', '1', '2024-08-10 11:54:58', '1', '2025-03-17 09:28:22', 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 (2003, 2, '网关设备', '2', 'iot_product_device_type', 0, 'default', '', '', '1', '2024-08-10 11:55:08', '1', '2025-03-17 09:28:28', 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 (2004, 1, '网关子设备', '1', 'iot_product_device_type', 0, 'default', '', '', '1', '2024-08-10 11:55:20', '1', '2025-03-17 09:28:31', 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 (2005, 1, '已发布', '1', 'iot_product_status', 0, 'success', '', '', '1', '2024-08-10 12:10:33', '1', '2025-03-17 09:28:34', 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 (2006, 0, '开发中', '0', 'iot_product_status', 0, 'default', '', '', '1', '2024-08-10 14:19:18', '1', '2025-03-17 09:28:39', 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 (2007, 0, '弱校验', '0', 'iot_validate_type', 0, '', '', '', '1', '2024-09-06 20:05:48', '1', '2025-03-17 09:28: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 (2008, 1, '免校验', '1', 'iot_validate_type', 0, '', '', '', '1', '2024-09-06 20:06:03', '1', '2025-03-17 09:28:44', 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 (2009, 0, 'Wi-Fi', '0', 'iot_net_type', 0, '', '', '', '1', '2024-09-06 22:04:47', '1', '2025-03-17 09:28:47', 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 (2010, 1, '蜂窝(2G / 3G / 4G / 5G)', '1', 'iot_net_type', 0, '', '', '', '1', '2024-09-06 22:05:14', '1', '2025-03-17 09:28:49', 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 (2010, 1, '移动网络', '1', 'iot_net_type', 0, '', '', '', '1', '2024-09-06 22:05:14', '1', '2025-06-12 23:27:19', 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 (2011, 2, '以太网', '2', 'iot_net_type', 0, '', '', '', '1', '2024-09-06 22:05:35', '1', '2025-03-17 09:28:51', 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 (2012, 3, '其他', '3', 'iot_net_type', 0, '', '', '', '1', '2024-09-06 22:05:52', '1', '2025-03-17 09:28:54', 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 (2013, 0, '自定义', '0', 'iot_protocol_type', 0, '', '', '', '1', '2024-09-06 22:26:10', '1', '2025-03-17 09:28:56', 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 (2014, 1, 'Modbus', '1', 'iot_protocol_type', 0, '', '', '', '1', '2024-09-06 22:26:21', '1', '2025-03-17 09:28: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 (2015, 2, 'OPC UA', '2', 'iot_protocol_type', 0, '', '', '', '1', '2024-09-06 22:26:31', '1', '2025-03-17 09:29:00', 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 (2016, 3, 'ZigBee', '3', 'iot_protocol_type', 0, '', '', '', '1', '2024-09-06 22:26:39', '1', '2025-03-17 09:29:04', 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 (2017, 4, 'BLE', '4', 'iot_protocol_type', 0, '', '', '', '1', '2024-09-06 22:26:48', '1', '2025-03-17 09:29: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 (2018, 0, '未激活', '0', 'iot_device_state', 0, '', '', '', '1', '2024-09-21 08:13:34', '1', '2025-03-17 09:29:09', 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 (2019, 1, '在线', '1', 'iot_device_state', 0, '', '', '', '1', '2024-09-21 08:13:48', '1', '2025-03-17 09:29:12', 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 (2020, 2, '离线', '2', 'iot_device_state', 0, '', '', '', '1', '2024-09-21 08:13:59', '1', '2025-03-17 09:29:14', 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 (2021, 1, '属性', '1', 'iot_thing_model_type', 0, '', '', '', '1', '2024-09-29 20:03:01', '1', '2025-03-17 09:29:24', 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 (2022, 2, '服务', '2', 'iot_thing_model_type', 0, '', '', '', '1', '2024-09-29 20:03:11', '1', '2025-03-17 09:29:27', 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 (2023, 3, '事件', '3', 'iot_thing_model_type', 0, '', '', '', '1', '2024-09-29 20:03:20', '1', '2025-03-17 09:29:29', 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 (2024, 1, 'JAR 部署', '0', 'iot_plugin_deploy_type', 0, '', '', '', '1', '2024-12-13 10:55:32', '1', '2025-03-17 09:29:32', 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 (2025, 2, '独立部署', '1', 'iot_plugin_deploy_type', 0, '', '', '', '1', '2024-12-13 10:55:43', '1', '2025-03-17 09:29:34', 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 (2026, 0, '停止', '0', 'iot_plugin_status', 0, 'danger', '', '', '1', '2024-12-13 11:07:37', '1', '2025-03-17 09:29:37', 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 (2027, 1, '运行', '1', 'iot_plugin_status', 0, '', '', '', '1', '2024-12-13 11:07:45', '1', '2025-03-17 09:34:17', 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 (2028, 0, '普通插件', '0', 'iot_plugin_type', 0, '', '', '', '1', '2024-12-13 11:08:32', '1', '2025-03-17 09:34:19', 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 (2029, 1, '设备插件', '1', 'iot_plugin_type', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:34:22', 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 (2030, 1, '升每分钟', 'L/min', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:34:24', 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 (2031, 2, '毫克每千克', 'mg/kg', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:34:27', 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 (2032, 3, '浊度', 'NTU', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:34:31', b'0');
|
||||
|
@ -1043,20 +1031,59 @@ 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 (2160, 130, '分米', 'dm', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', 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 (2161, 131, '千米', 'km', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', 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 (2162, 132, '米', 'm', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', 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 (2163, 1, '输入', '1', 'iot_data_bridge_direction_enum', 0, 'primary', '', '', '1', '2025-03-09 12:38:24', '1', '2025-03-17 09:40:46', 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 (2164, 2, '输出', '2', 'iot_data_bridge_direction_enum', 0, 'primary', '', '', '1', '2025-03-09 12:38:36', '1', '2025-03-17 09:40:46', 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 (2165, 1, 'HTTP', '1', 'iot_data_bridge_type_enum', 0, 'primary', '', '', '1', '2025-03-09 12:39:54', '1', '2025-03-17 09:40:46', 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 (2166, 2, 'TCP', '2', 'iot_data_bridge_type_enum', 0, 'primary', '', '', '1', '2025-03-09 12:40:06', '1', '2025-03-17 09:40:46', 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 (2167, 3, 'WEBSOCKET', '3', 'iot_data_bridge_type_enum', 0, 'primary', '', '', '1', '2025-03-09 12:40:24', '1', '2025-03-17 09:40:46', 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 (2168, 10, 'MQTT', '10', 'iot_data_bridge_type_enum', 0, 'primary', '', '', '1', '2025-03-09 12:40:37', '1', '2025-03-17 09:40:46', 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 (2169, 20, 'DATABASE', '20', 'iot_data_bridge_type_enum', 0, 'primary', '', '', '1', '2025-03-09 12:41:05', '1', '2025-03-17 09:40:46', 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 (2170, 21, 'REDIS_STREAM', '21', 'iot_data_bridge_type_enum', 0, 'primary', '', '', '1', '2025-03-09 12:41:18', '1', '2025-03-17 09:40:46', 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 (2171, 30, 'ROCKETMQ', '30', 'iot_data_bridge_type_enum', 0, 'primary', '', '', '1', '2025-03-09 12:41:30', '1', '2025-03-17 09:40:46', 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 (2172, 31, 'RABBITMQ', '31', 'iot_data_bridge_type_enum', 0, 'primary', '', '', '1', '2025-03-09 12:41:47', '1', '2025-03-17 09:40:46', 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 (2173, 32, 'KAFKA', '32', 'iot_data_bridge_type_enum', 0, 'primary', '', '', '1', '2025-03-09 12:41:59', '1', '2025-03-17 09:40:46', 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 (2165, 1, 'HTTP', '1', 'iot_data_sink_type_enum', 0, 'default', '', '', '1', '2025-03-09 12:39:54', '1', '2025-06-24 12:44:47', 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 (2166, 2, 'TCP', '2', 'iot_data_sink_type_enum', 0, 'default', '', '', '1', '2025-03-09 12:40:06', '1', '2025-06-24 12:44:46', 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 (2167, 3, 'WebSocket', '3', 'iot_data_sink_type_enum', 0, 'default', '', '', '1', '2025-03-09 12:40:24', '1', '2025-06-24 12:44:45', 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 (2168, 10, 'MQTT', '10', 'iot_data_sink_type_enum', 0, 'default', '', '', '1', '2025-03-09 12:40:37', '1', '2025-06-24 12:44:44', 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 (2169, 20, 'Database', '20', 'iot_data_sink_type_enum', 0, 'default', '', '', '1', '2025-03-09 12:41:05', '1', '2025-06-24 12:44:44', 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 (2170, 21, 'Redis Stream', '21', 'iot_data_sink_type_enum', 0, 'default', '', '', '1', '2025-03-09 12:41:18', '1', '2025-06-24 12:44:43', 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 (2171, 30, 'RocketMQ', '30', 'iot_data_sink_type_enum', 0, 'default', '', '', '1', '2025-03-09 12:41:30', '1', '2025-06-24 12:44:42', 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 (2172, 31, 'RabbitMQ', '31', 'iot_data_sink_type_enum', 0, 'default', '', '', '1', '2025-03-09 12:41:47', '1', '2025-06-24 12:44: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 (2173, 32, 'Kafka', '32', 'iot_data_sink_type_enum', 0, 'default', '', '', '1', '2025-03-09 12:41:59', '1', '2025-06-24 12:44:39', 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 (2174, 1, '设备上下线变更', '1', 'iot_rule_scene_trigger_type_enum', 0, 'primary', '', '', '1', '2025-03-20 15:00:01', '\"1\"', '2025-07-06 10:28: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 (2175, 2, '物模型属性上报', '2', 'iot_rule_scene_trigger_type_enum', 0, 'primary', '', '', '1', '2025-03-20 15:00:09', '\"1\"', '2025-07-06 10:28:22', 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 (2176, 1, '设备状态', 'state', 'iot_device_message_type_enum', 0, 'primary', '', '', '1', '2025-03-20 15:24:58', '1', '2025-03-20 15:24: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 (2177, 2, '设备属性', 'property', 'iot_device_message_type_enum', 0, 'primary', '', '', '1', '2025-03-20 15:25:09', '1', '2025-03-20 15:25:09', 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 (2178, 3, '设备事件', 'event', 'iot_device_message_type_enum', 0, 'primary', '', '', '1', '2025-03-20 15:25:23', '1', '2025-03-20 15:25:23', 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 (2179, 4, '设备服务', 'service', 'iot_device_message_type_enum', 0, 'primary', '', '', '1', '2025-03-20 15:25:39', '1', '2025-03-20 15:25:39', 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 (2180, 5, '设备配置', 'config', 'iot_device_message_type_enum', 0, 'primary', '', '', '1', '2025-03-20 15:25:51', '1', '2025-03-20 15:25:57', 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 (2181, 6, '设备 OTA', 'ota', 'iot_device_message_type_enum', 0, 'primary', '', '', '1', '2025-03-20 15:26:17', '1', '2025-03-20 15:26:17', 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 (2182, 7, '设备注册', 'register', 'iot_device_message_type_enum', 0, 'primary', '', '', '1', '2025-03-20 15:26:35', '1', '2025-03-20 15:26:35', 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 (2183, 8, '设备拓扑', 'topology', 'iot_device_message_type_enum', 0, 'primary', '', '', '1', '2025-03-20 15:26:46', '1', '2025-03-20 15:26:46', 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 (2184, 1, '设备属性设置', '1', 'iot_rule_scene_action_type_enum', 0, 'primary', '', '', '1', '2025-03-28 15:27:12', '\"1\"', '2025-07-06 10:37:33', 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 (2185, 2, '设备服务调用', '2', 'iot_rule_scene_action_type_enum', 0, 'primary', '', '', '1', '2025-03-28 15:27:25', '\"1\"', '2025-07-06 10:37: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 (2186, 100, '告警触发', '100', 'iot_rule_scene_action_type_enum', 0, 'primary', '', '', '1', '2025-03-28 15:27:35', '\"1\"', '2025-07-06 10:37:50', 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 (3000, 16, '百川智能', 'BaiChuan', 'ai_platform', 0, '', '', '', '1', '2025-03-23 12:15:46', '1', '2025-03-23 12:15:46', 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 (3001, 50, 'Vben5.0 Ant Design Schema 模版', '40', 'infra_codegen_front_type', 0, '', '', NULL, '1', '2025-04-23 21:47:47', '1', '2025-05-02 12:01:15', 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 (3002, 6, '支付宝余额', '6', 'brokerage_withdraw_type', 0, '', '', 'API 打款', '1', '2025-05-10 08:24:49', '1', '2025-05-10 08:24:49', 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 (3003, 1, 'Alink', 'Alink', 'iot_codec_type', 0, '', '', '阿里云 Alink', '1', '2025-06-12 22:56:06', '1', '2025-06-12 23:22:24', 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 (3004, 3, 'WARN', '3', 'iot_alert_level', 0, 'warning', '', '', '1', '2025-06-27 20:32:22', '1', '2025-06-27 20:34:31', 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 (3005, 1, 'INFO', '1', 'iot_alert_level', 0, 'primary', '', '', '1', '2025-06-27 20:33:28', '1', '2025-06-27 20:34:35', 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 (3006, 5, 'ERROR', '5', 'iot_alert_level', 0, 'danger', '', '', '1', '2025-06-27 20:33:50', '1', '2025-06-27 20:33:50', 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 (3007, 1, '短信', '1', 'iot_alert_receive_type', 0, '', '', '', '1', '2025-06-27 22:49:30', '1', '2025-06-27 22:49:30', 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 (3008, 2, '邮箱', '2', 'iot_alert_receive_type', 0, '', '', '', '1', '2025-06-27 22:49:39', '1', '2025-06-27 22:50:07', 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 (3009, 3, '站内信', '3', 'iot_alert_receive_type', 0, '', '', '', '1', '2025-06-27 22:50:20', '1', '2025-06-27 22:50:20', 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 (3010, 1, '全部设备', '1', 'iot_ota_task_device_scope', 0, '', '', '', '1', '2025-07-02 09:43:09', '1', '2025-07-02 09:43:09', 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 (3011, 2, '指定设备', '2', 'iot_ota_task_device_scope', 0, '', '', '', '1', '2025-07-02 09:43:15', '1', '2025-07-02 09:43:15', 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 (3012, 10, '进行中', '10', 'iot_ota_task_status', 0, 'primary', '', '', '1', '2025-07-02 09:44:01', '\"1\"', '2025-07-02 09:44:21', 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 (3013, 20, '已结束', '20', 'iot_ota_task_status', 0, 'success', '', '', '1', '2025-07-02 09:44:14', '\"1\"', '2025-07-02 23:56:12', 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 (3014, 30, '已取消', '30', 'iot_ota_task_status', 0, 'danger', '', '', '1', '2025-07-02 09:44:36', '1', '2025-07-02 09:44:36', 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 (3015, 0, '待推送', '0', 'iot_ota_task_record_status', 0, '', '', '', '1', '2025-07-02 09:45:16', '1', '2025-07-02 09:45: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 (3016, 10, '已推送', '10', 'iot_ota_task_record_status', 0, '', '', '', '1', '2025-07-02 09:45:25', '1', '2025-07-02 09:45:25', 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 (3017, 20, '升级中', '20', 'iot_ota_task_record_status', 0, 'primary', '', '', '1', '2025-07-02 09:45:37', '1', '2025-07-02 09:45:37', 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 (3018, 30, '升级成功', '30', 'iot_ota_task_record_status', 0, 'success', '', '', '1', '2025-07-02 09:45:47', '1', '2025-07-02 09:45:47', 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 (3019, 40, '升级失败', '40', 'iot_ota_task_record_status', 0, 'danger', '', '', '1', '2025-07-02 09:46:02', '1', '2025-07-02 09: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 (3020, 50, '升级取消', '50', 'iot_ota_task_record_status', 0, 'warning', '', '', '1', '2025-07-02 09:46:09', '\"1\"', '2025-07-02 09:46:27', 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 (3021, 1, 'IP 定位', '1', 'iot_location_type', 0, '', '', '', '1', '2025-07-05 09:56:46', '1', '2025-07-05 09:56:46', 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 (3022, 2, '设备上报', '2', 'iot_location_type', 0, '', '', '', '1', '2025-07-05 09:56:57', '1', '2025-07-05 09:56:57', 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 (3023, 3, '手动定位', '3', 'iot_location_type', 0, '', '', '', '1', '2025-07-05 09:57:05', '1', '2025-07-05 09:57:05', 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 (3024, 3, '设备事件上报', '3', 'iot_rule_scene_trigger_type_enum', 0, '', '', '', '1', '2025-07-06 10:28:29', '1', '2025-07-06 10:28:29', 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 (3025, 4, '设备服务调用', '4', 'iot_rule_scene_trigger_type_enum', 0, '', '', '', '1', '2025-07-06 10:28:35', '1', '2025-07-06 10:28:35', 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 (3026, 100, '定时触发', '100', 'iot_rule_scene_trigger_type_enum', 0, '', '', '', '1', '2025-07-06 10:28:48', '1', '2025-07-06 10:28:48', 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 (3027, 101, '告警恢复', '101', 'iot_rule_scene_action_type_enum', 0, '', '', '', '1', '2025-07-06 10:37:57', '1', '2025-07-06 10:37:57', 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 (3028, 2, 'Anthropic', 'Anthropic', 'ai_platform', 0, '', '', '', '1', '2025-08-21 22:54:24', '1', '2025-08-21 22:57: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 (3029, 2, '谷歌 Gemini', 'Gemini', 'ai_platform', 0, '', '', '', '1', '2025-08-22 22:39:35', '1', '2025-08-22 22:44:49', 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 (3030, 1, '文件系统', 'filesystem', 'ai_mcp_client_name', 0, '', '', '', '1', '2025-08-28 13:58:43', '1', '2025-08-28 21:19:42', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -1076,7 +1103,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 = 2000 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2008 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_dict_type
|
||||
|
@ -1175,20 +1202,24 @@ 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 (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');
|
||||
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (640, 'AI 模型类型', 'ai_model_type', 0, '', '1', '2025-03-03 12:24:07', '1', '2025-03-03 12:24:07', 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 (1000, 'IoT 数据格式', 'iot_data_format', 0, '', '1', '2024-08-10 11:52:58', '1', '2025-03-17 09:25:06', 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 (1001, 'IoT 产品设备类型', 'iot_product_device_type', 0, '', '1', '2024-08-10 11:54:30', '1', '2025-03-17 09:25:08', 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 (1002, 'IoT 产品状态', 'iot_product_status', 0, '', '1', '2024-08-10 12:06:09', '1', '2025-03-17 09:25:10', 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 (1003, 'IoT 数据校验级别', 'iot_validate_type', 0, '', '1', '2024-09-06 20:05:13', '1', '2025-03-17 09:25:12', 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 (1004, 'IoT 联网方式', 'iot_net_type', 0, '', '1', '2024-09-06 22:04:13', '1', '2025-03-17 09:25:14', 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 (1005, 'IoT 接入网关协议', 'iot_protocol_type', 0, '', '1', '2024-09-06 22:20:17', '1', '2025-03-17 09:25:16', 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 (1006, 'IoT 设备状态', 'iot_device_state', 0, '', '1', '2024-09-21 08:12:55', '1', '2025-03-17 09:25:19', 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 (1007, 'IoT 物模型功能类型', 'iot_thing_model_type', 0, '', '1', '2024-09-29 20:02:36', '1', '2025-03-17 09:25:24', 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 (1008, 'IoT 插件部署方式', 'iot_plugin_deploy_type', 0, '', '1', '2024-12-13 10:55:13', '1', '2025-03-17 09:25:27', 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 (1009, 'IoT 插件状态', 'iot_plugin_status', 0, '', '1', '2024-12-13 11:05:34', '1', '2025-03-17 09:25:30', 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 (1010, 'IoT 插件类型', 'iot_plugin_type', 0, '', '1', '2024-12-13 11:08:19', '1', '2025-03-17 09:25:32', 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 (1011, 'IoT 物模型单位', 'iot_thing_model_unit', 0, '', '1', '2024-12-25 17:36:46', '1', '2025-03-17 09:25:35', 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 (1012, 'IoT 数据桥接的方向枚举', 'iot_data_bridge_direction_enum', 0, '', '1', '2025-03-09 12:37:40', '1', '2025-03-17 09:25:39', 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 (1013, 'IoT 数据桥梁的类型枚举', 'iot_data_bridge_type_enum', 0, '', '1', '2025-03-09 12:39:36', '1', '2025-04-06 17:09:46', 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 (1013, 'IoT 数据流转目的的类型枚举', 'iot_data_sink_type_enum', 0, '', '1', '2025-03-09 12:39:36', '1', '2025-06-24 12:45:24', 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 (1014, 'IoT 场景流转的触发类型枚举', 'iot_rule_scene_trigger_type_enum', 0, '', '1', '2025-03-20 14:59:44', '1', '2025-03-20 14:59:44', 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 (1015, 'IoT 设备消息类型枚举', 'iot_device_message_type_enum', 0, '', '1', '2025-03-20 15:01:15', '1', '2025-03-20 15:01:15', 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 (1016, 'IoT 规则场景的触发类型枚举', 'iot_rule_scene_action_type_enum', 0, '', '1', '2025-03-28 15:26:54', '1', '2025-03-28 15:29:13', 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 (2000, 'IoT 数据格式', 'iot_codec_type', 0, 'IoT 编解码器类型', '1', '2025-06-12 22:55:46', '1', '2025-06-12 22:55:46', 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 (2001, 'IoT 告警级别', 'iot_alert_level', 0, '', '1', '2025-06-27 20:30:57', '1', '2025-06-27 20:30:57', 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 (2002, 'IoT 告警', 'iot_alert_receive_type', 0, '', '1', '2025-06-27 22:49:19', '1', '2025-06-27 22:49:19', 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 (2003, 'IoT 固件设备范围', 'iot_ota_task_device_scope', 0, '', '1', '2025-07-02 09:42:49', '1', '2025-07-02 09:42:49', 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 (2004, 'IoT 固件升级任务状态', 'iot_ota_task_status', 0, '', '1', '2025-07-02 09:43:43', '1', '2025-07-02 09:43:43', 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 (2005, 'IoT 固件升级记录状态', 'iot_ota_task_record_status', 0, '', '1', '2025-07-02 09:45:02', '1', '2025-07-02 09:45:02', 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 (2006, 'IoT 定位类型', 'iot_location_type', 0, '', '1', '2025-07-05 09:56:25', '1', '2025-07-05 09:56:25', 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 (2007, 'AI MCP 客户端名字', 'ai_mcp_client_name', 0, '', '1', '2025-08-28 13:57:40', '1', '2025-08-28 13:57:40', b'0', '1970-01-01 00:00:00');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -1212,7 +1243,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 = 3822 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 4021 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_login_log
|
||||
|
@ -1246,7 +1277,7 @@ CREATE TABLE `system_mail_account` (
|
|||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `system_mail_account` (`id`, `mail`, `username`, `password`, `host`, `port`, `ssl_enable`, `starttls_enable`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '7684413@qq.com', '7684413@qq.com', '1234576', '127.0.0.1', 8080, b'0', b'0', '1', '2023-01-25 17:39:52', '1', '2025-04-04 16:34:40', b'0');
|
||||
INSERT INTO `system_mail_account` (`id`, `mail`, `username`, `password`, `host`, `port`, `ssl_enable`, `starttls_enable`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 'ydym_test@163.com', 'ydym_test@163.com', 'WBZTEINMIFVRYSOE', 'smtp.163.com', 465, b'1', b'0', '1', '2023-01-26 01:26:03', '1', '2023-04-12 22:39:38', b'0');
|
||||
INSERT INTO `system_mail_account` (`id`, `mail`, `username`, `password`, `host`, `port`, `ssl_enable`, `starttls_enable`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 'ydym_test@163.com', 'ydym_test@163.com', 'WBZTEINMIFVRYSOE', 'smtp.163.com', 465, b'1', b'0', '1', '2023-01-26 01:26:03', '1', '2025-07-26 21:57:55', b'0');
|
||||
INSERT INTO `system_mail_account` (`id`, `mail`, `username`, `password`, `host`, `port`, `ssl_enable`, `starttls_enable`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3, '76854114@qq.com', '3335', '11234', 'yunai1.cn', 466, b'0', b'0', '1', '2023-01-27 15:06:38', '1', '2023-01-27 07:08:36', b'1');
|
||||
INSERT INTO `system_mail_account` (`id`, `mail`, `username`, `password`, `host`, `port`, `ssl_enable`, `starttls_enable`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (4, '7685413x@qq.com', '2', '3', '4', 5, b'1', b'0', '1', '2023-04-12 23:05:06', '1', '2023-04-12 15:05:11', b'1');
|
||||
COMMIT;
|
||||
|
@ -1259,14 +1290,16 @@ CREATE TABLE `system_mail_log` (
|
|||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`user_id` bigint NULL DEFAULT NULL COMMENT '用户编号',
|
||||
`user_type` tinyint NULL DEFAULT NULL COMMENT '用户类型',
|
||||
`to_mail` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '接收邮箱地址',
|
||||
`to_mails` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '接收邮箱地址',
|
||||
`cc_mails` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '抄送邮箱地址',
|
||||
`bcc_mails` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '密送邮箱地址',
|
||||
`account_id` bigint NOT NULL COMMENT '邮箱账号编号',
|
||||
`from_mail` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '发送邮箱地址',
|
||||
`template_id` bigint NOT NULL COMMENT '模板编号',
|
||||
`template_code` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模板编码',
|
||||
`template_nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '模版发送人名称',
|
||||
`template_title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件标题',
|
||||
`template_content` varchar(10240) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件内容',
|
||||
`template_content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件内容',
|
||||
`template_params` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件参数',
|
||||
`send_status` tinyint NOT NULL DEFAULT 0 COMMENT '发送状态',
|
||||
`send_time` datetime NULL DEFAULT NULL COMMENT '发送时间',
|
||||
|
@ -1278,7 +1311,7 @@ CREATE TABLE `system_mail_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 = 360 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '邮件日志表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 367 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '邮件日志表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_mail_log
|
||||
|
@ -1314,8 +1347,8 @@ CREATE TABLE `system_mail_template` (
|
|||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `system_mail_template` (`id`, `name`, `code`, `account_id`, `nickname`, `title`, `content`, `params`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (13, '后台用户短信登录', 'admin-sms-login', 1, '奥特曼', '你猜我猜', '<p>您的验证码是{code},名字是{name}</p>', '[\"code\",\"name\"]', 0, '3', '1', '2021-10-11 08:10:00', '1', '2023-12-02 19:51:14', b'0');
|
||||
INSERT INTO `system_mail_template` (`id`, `name`, `code`, `account_id`, `nickname`, `title`, `content`, `params`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (14, '测试模版', 'test_01', 2, '芋艿', '一个标题', '<p>你是 {key01} 吗?</p><p><br></p><p>是的话,赶紧 {key02} 一下!</p>', '[\"key01\",\"key02\"]', 0, NULL, '1', '2023-01-26 01:27:40', '1', '2023-01-27 10:32:16', b'0');
|
||||
INSERT INTO `system_mail_template` (`id`, `name`, `code`, `account_id`, `nickname`, `title`, `content`, `params`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (15, '3', '2', 2, '7', '4', '<p>45</p>', '[]', 1, '80', '1', '2023-01-27 15:50:35', '1', '2023-01-27 16:34:49', b'0');
|
||||
INSERT INTO `system_mail_template` (`id`, `name`, `code`, `account_id`, `nickname`, `title`, `content`, `params`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (14, '测试模版', 'test_01', 2, '芋艿', '一个标题', '<p>你是 {key01} 吗?</p><p><br></p><p>是的话,赶紧 {key02} 一下!</p>', '[\"key01\",\"key02\"]', 0, NULL, '1', '2023-01-26 01:27:40', '1', '2025-07-26 21:48:45', b'0');
|
||||
INSERT INTO `system_mail_template` (`id`, `name`, `code`, `account_id`, `nickname`, `title`, `content`, `params`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (15, '3', '2', 2, '7', '4', '<p>45</p>', '[]', 1, '80', '1', '2023-01-27 15:50:35', '1', '2025-07-26 21:47:49', b'1');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -1343,7 +1376,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 = 5013 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 5042 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_menu
|
||||
|
@ -2201,55 +2234,47 @@ 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 (2924, '工具删除', 'ai:tool:delete', 3, 4, 2920, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2025-03-14 11:19:29', '', '2025-03-14 11: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 (4000, 'IoT 物联网', '', 1, 500, 0, '/iot', 'fa-solid:hdd', '', '', 0, b'1', b'1', b'1', '1', '2024-08-10 09:55:28', '1', '2024-12-07 15:58: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 (4001, '设备接入', '', 1, 2, 4000, 'device', 'ep:platform', '', '', 0, b'1', b'1', b'1', '1', '2024-08-10 09:57:56', '1', '2025-02-27 08:39:49', 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 (4002, '产品管理', '', 2, 2, 4001, 'product', 'fa-solid:tools', 'iot/product/product/index', 'IoTProduct', 0, b'1', b'1', b'1', '', '2024-08-10 02:38:02', '1', '2024-12-07 18:47:53', 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 (4002, '产品管理', '', 2, 1, 4001, 'product', 'fa-solid:tools', 'iot/product/product/index', 'IoTProduct', 0, b'1', b'1', b'1', '', '2024-08-10 02:38:02', '1', '2025-06-15 20:56: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 (4003, '产品查询', 'iot:product:query', 3, 1, 4002, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-08-10 02:38:02', '', '2024-12-07 15:55:00', 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 (4004, '产品创建', 'iot:product:create', 3, 2, 4002, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-08-10 02:38:02', '', '2024-12-07 15:55:03', 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 (4005, '产品更新', 'iot:product:update', 3, 3, 4002, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-08-10 02:38:02', '', '2024-12-07 15:55:05', 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 (4006, '产品删除', 'iot:product:delete', 3, 4, 4002, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-08-10 02:38:02', '', '2024-12-07 15:55: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 (4007, '产品导出', 'iot:product:export', 3, 5, 4002, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-08-10 02:38:02', '', '2024-12-07 15:55: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 (4008, '设备管理', '', 2, 4, 4001, 'device', 'fa:mobile', 'iot/device/device/index', 'IoTDevice', 0, b'1', b'1', b'1', '', '2024-09-16 18:48:19', '1', '2024-12-14 11:39:30', 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 (4008, '设备管理', '', 2, 2, 4001, 'device', 'fa:mobile', 'iot/device/device/index', 'IoTDevice', 0, b'1', b'1', b'1', '', '2024-09-16 18:48:19', '1', '2025-06-15 20:56: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 (4009, '设备查询', 'iot:device:query', 3, 1, 4008, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-09-16 18:48:19', '1', '2024-12-07 15:55:40', 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 (4010, '设备创建', 'iot:device:create', 3, 2, 4008, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-09-16 18:48:19', '1', '2024-12-07 15:55:41', 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 (4011, '设备更新', 'iot:device:update', 3, 3, 4008, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-09-16 18:48:19', '1', '2024-12-07 15:55: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 (4012, '设备删除', 'iot:device:delete', 3, 4, 4008, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-09-16 18:48:19', '1', '2024-12-07 15:55:43', 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 (4013, '设备导出', 'iot:device:export', 3, 5, 4008, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-09-16 18:48:19', '1', '2024-12-07 15:55:44', 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 (4014, '产品分类', '', 2, 1, 4001, 'product-category', 'ep:notebook', 'iot/product/category/index', 'IotProductCategory', 0, b'1', b'1', b'1', '', '2024-12-07 16:01:35', '1', '2024-12-07 16:31: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 (4014, '产品分类', '', 2, 3, 4001, 'product-category', 'ep:notebook', 'iot/product/category/index', 'IotProductCategory', 0, b'1', b'1', b'1', '', '2024-12-07 16:01:35', '1', '2025-06-15 20:56:39', 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 (4015, '产品分类查询', 'iot:product-category:query', 3, 1, 4014, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-07 16:01:35', '', '2024-12-07 16:01: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 (4016, '产品分类创建', 'iot:product-category:create', 3, 2, 4014, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-07 16:01:35', '', '2024-12-07 16:01: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 (4017, '产品分类更新', 'iot:product-category:update', 3, 3, 4014, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-07 16:01:35', '', '2024-12-07 16:01: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 (4018, '产品分类删除', 'iot:product-category:delete', 3, 4, 4014, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-07 16:01:35', '', '2024-12-07 16:01: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 (4025, '插件管理', '', 2, 5, 4047, 'plugin-config', 'ep:folder-opened', 'iot/plugin/index', 'IoTPlugin', 0, b'1', b'1', b'1', '', '2024-12-09 21:25:06', '1', '2025-02-05 22:23: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 (4026, '插件查询', 'iot:plugin-config:query', 3, 1, 4025, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-09 21:25:06', '', '2025-02-05 21:23: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 (4027, '插件创建', 'iot:plugin-config:create', 3, 2, 4025, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-09 21:25:06', '', '2025-02-05 21:23: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 (4028, '插件更新', 'iot:plugin-config:update', 3, 3, 4025, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-09 21:25:06', '', '2025-02-05 21:23: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 (4029, '插件删除', 'iot:plugin-config:delete', 3, 4, 4025, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-09 21:25:06', '', '2025-02-05 21:23: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 (4030, '插件导出', 'iot:plugin-config:export', 3, 5, 4025, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-09 21:25:06', '', '2025-02-05 21:23: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 (4031, '设备分组', '', 2, 3, 4001, 'device-group', 'fa-solid:layer-group', 'iot/device/group/index', 'IotDeviceGroup', 0, b'1', b'1', b'1', '', '2024-12-14 17:08:29', '1', '2024-12-14 17:09:17', 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 (4032, '设备分组查询', 'iot:device-group:query', 3, 1, 4031, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-14 17:08:29', '', '2024-12-14 17:08: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 (4033, '设备分组创建', 'iot:device-group:create', 3, 2, 4031, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-14 17:08:29', '', '2024-12-14 17:08: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 (4034, '设备分组更新', 'iot:device-group:update', 3, 3, 4031, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-14 17:08:29', '', '2024-12-14 17:08: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 (4035, '设备分组删除', 'iot:device-group:delete', 3, 4, 4031, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-14 17:08:29', '', '2024-12-14 17:08: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 (4036, '设备导入', 'iot:device:import', 3, 6, 4008, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-12-15 10:35:47', '1', '2024-12-15 10:35:47', 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 (4037, '产品物模型', '', 2, 2, 4001, 'thing-model', 'ep:mostly-cloudy', 'iot/thingmodel/index', 'IoTThingModel', 0, b'0', b'0', b'0', '', '2024-12-16 17:17:50', '1', '2024-12-27 11:03:37', 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 (4037, '产品物模型', '', 2, 99, 4001, 'thing-model', 'ep:mostly-cloudy', 'iot/thingmodel/index', 'IoTThingModel', 0, b'0', b'0', b'0', '', '2024-12-16 17:17:50', '1', '2025-06-15 20:56: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 (4038, '产品物模型功能查询', 'iot:thing-model:query', 3, 1, 4037, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-16 17:17:51', '', '2025-03-17 09:14:54', 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 (4039, '产品物模型功能创建', 'iot:thing-model:create', 3, 2, 4037, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-16 17:17:52', '', '2025-03-17 09:14:58', 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 (4040, '产品物模型功能更新', 'iot:thing-model:update', 3, 3, 4037, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-16 17:17:52', '', '2025-03-17 09:15:03', 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 (4041, '产品物模型功能删除', 'iot:thing-model:delete', 3, 4, 4037, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-16 17:17:52', '', '2025-03-17 09:15: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 (4042, '产品物模型功能导出', 'iot:thing-model:export', 3, 5, 4037, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-12-16 17:17:53', '', '2025-03-17 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 (4043, '设备上行', 'iot:device:upstream', 3, 7, 4008, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-01-28 04:40:16', '1', '2025-01-31 22:45:53', 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 (4043, '设备消息发送', 'iot:device:message-send', 3, 12, 4008, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-01-28 04:40:16', '1', '2025-06-14 14:09:26', 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 (4044, '设备属性查询', 'iot:device:property-query', 3, 10, 4008, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-01-28 11:52:54', '1', '2025-01-28 11:52:54', 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 (4045, '设备日志查询', 'iot:device:log-query', 3, 11, 4008, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-01-28 11:53:22', '1', '2025-01-28 11:53:22', 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 (4046, '设备下行', 'iot:device:downstream', 3, 8, 4008, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-01-31 22:46:11', '1', '2025-01-31 22:46:11', 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 (4047, '运维管理', '', 1, 2, 4000, 'operations', 'fa:cog', '', '', 0, b'1', b'1', b'1', '1', '2025-02-05 22:21:37', '1', '2025-02-05 22:22:53', 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 (4045, '设备消息查询', 'iot:device:message-query', 3, 11, 4008, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-01-28 11:53:22', '1', '2025-06-14 11:11: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 (4047, '运维管理', '', 1, 4, 4000, 'operation', 'fa:align-center', '', '', 0, b'1', b'1', b'1', '1', '2025-02-05 22:21:37', '\"1\"', '2025-06-30 20:12:48', 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 (4048, '规则引擎', '', 1, 3, 4000, 'rule', 'fa-solid:cogs', '', '', 0, b'1', b'1', b'1', '1', '2025-02-11 14:10:54', '1', '2025-02-11 14:10:54', 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 (4049, '场景联动', '', 2, 1, 4048, 'scene', 'ep:link', 'iot/rule/scene/index', 'Scene', 0, b'1', b'1', b'1', '1', '2025-02-11 14:12:44', '1', '2025-02-12 10:15:36', 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 (4050, 'IoT首页', '', 2, 1, 4000, 'home', 'ep:home-filled', 'iot/home/index', 'IotHome', 0, b'1', b'1', b'1', '1', '2025-02-27 08:39:35', '1', '2025-02-27 08:40: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 (4051, '数据桥梁', '', 2, 0, 4048, 'data-bridge', 'ep:guide', 'iot/rule/databridge/index', 'IotDataBridge', 0, b'1', b'1', b'1', '', '2025-03-09 13:47:11', '1', '2025-03-09 13:47:51', 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 (4052, 'IoT 数据桥梁查询', 'iot:data-bridge:query', 3, 1, 4051, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2025-03-09 13:47:11', '', '2025-03-09 13:47:11', 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 (4053, 'IoT 数据桥梁创建', 'iot:data-bridge:create', 3, 2, 4051, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2025-03-09 13:47:11', '', '2025-03-09 13:47:11', 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 (4054, 'IoT 数据桥梁更新', 'iot:data-bridge:update', 3, 3, 4051, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2025-03-09 13:47:11', '', '2025-03-09 13:47:11', 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 (4055, 'IoT 数据桥梁删除', 'iot:data-bridge:delete', 3, 4, 4051, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2025-03-09 13:47:12', '', '2025-03-09 13:47: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 (4056, 'IoT 数据桥梁导出', 'iot:data-bridge:export', 3, 5, 4051, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2025-03-09 13:47:12', '', '2025-03-09 13:47: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 (4049, '场景联动', '', 2, 1, 4048, 'scene', 'ep:link', 'iot/rule/scene/index', 'IoTSceneRule', 0, b'1', b'1', b'1', '1', '2025-02-11 14:12:44', '\"1\"', '2025-08-09 15:38: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 (4050, 'IoT 首页', '', 2, 1, 4000, 'home', 'ep:home-filled', 'iot/home/index', 'IotHome', 0, b'1', b'1', b'1', '1', '2025-02-27 08:39:35', '1', '2025-06-24 14:22:50', 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 (4051, '数据流转', '', 2, 2, 4048, 'data-rule', 'ep:guide', 'iot/rule/data/index', 'IoTDataRule', 0, b'1', b'1', b'1', '', '2025-03-09 13:47:11', '\"1\"', '2025-08-09 15:38:37', 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 (4052, '数据流转规则查询', 'iot:data-rule:query', 3, 1, 4051, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-03-09 13:47:11', '1', '2025-06-24 20:48:04', 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 (4053, '数据流转规则创建', 'iot:data-rule:create', 3, 2, 4051, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-03-09 13:47:11', '1', '2025-06-24 20:48: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 (4054, '数据流转规则更新', 'iot:data-rule:update', 3, 3, 4051, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-03-09 13:47:11', '1', '2025-06-24 20:48:11', 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 (4055, '数据流转规则删除', 'iot:data-rule:delete', 3, 4, 4051, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-03-09 13:47:12', '1', '2025-06-24 20:48:15', 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 (5000, 'AI 工作流', '', 2, 5, 2758, 'workflow', 'fa:hand-grab-o', 'ai/workflow/index.vue', 'AiWorkflow', 0, b'1', b'1', b'1', '1', '2025-03-25 09:50:27', '1', '2025-05-03 18:55: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 (5001, 'AI 工作流查询', 'ai:workflow:query', 3, 1, 5000, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-03-25 09:51:11', '1', '2025-03-25 09:51:11', 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 (5002, 'AI 工作流创建', 'ai:workflow:create', 3, 2, 5000, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-03-25 09:51:28', '1', '2025-03-25 09:51:28', b'0');
|
||||
|
@ -2260,6 +2285,34 @@ 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 (5010, '租户切换', 'system:tenant:visit', 3, 999, 1138, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-05-05 15:25:32', '1', '2025-05-05 15:25: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 (5011, '转账订单查询', 'pay:transfer:query', 3, 1, 2559, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-05-08 12:46:53', '1', '2025-05-08 12:46:53', 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 (5012, '转账订单导出', 'pay:transfer:export', 3, 2, 2559, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-05-10 17:00:28', '1', '2025-05-10 17:00: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 (5013, '场景联动查询', 'iot:rule-scene:query', 3, 1, 4049, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-06-20 16:53:01', '1', '2025-06-20 16:53:01', 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 (5014, '场景联动创建', 'iot:rule-scene:create', 3, 2, 4049, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-06-20 16:54:31', '1', '2025-06-20 16:54:31', 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 (5015, '场景联动更新', 'iot:rule-scene:update', 3, 3, 4049, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-06-20 16:54:47', '1', '2025-06-20 16:54:47', 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 (5016, '场景联动删除', 'iot:rule-scene:delete', 3, 4, 4049, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-06-20 16:55:04', '1', '2025-06-20 16:55:27', 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 (5017, '场景联动导出', 'iot:rule-scene:export', 3, 5, 4049, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-06-20 16:57:56', '1', '2025-06-20 16:57: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 (5018, '数据流转目的查询', 'iot:data-sink:query', 3, 11, 4051, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-06-24 20:48:40', '1', '2025-06-24 20:48:40', 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 (5019, '数据流转目的创建', 'iot:data-sink:create', 3, 12, 4051, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-06-24 20:48:57', '1', '2025-06-24 20:48: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 (5020, '数据流转目的更新', 'iot:data-sink:update', 3, 13, 4051, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-06-24 20:49:10', '1', '2025-06-24 20:49: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 (5021, '数据流转目的删除', 'iot:data-sink:delete', 3, 14, 4051, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-06-24 20:49:23', '1', '2025-06-24 20:49:23', 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 (5022, '告警配置', '', 2, 1, 5028, 'config', 'fa:connectdevelop', 'iot/alert/config/index', 'IotAlertConfig', 0, b'1', b'1', b'1', '', '2025-06-27 14:28:59', '1', '2025-06-27 22:31: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 (5023, '告警配置查询', 'iot:alert-config:query', 3, 1, 5022, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-06-27 14:28:59', '1', '2025-06-28 16:00:31', 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 (5024, '告警配置创建', 'iot:alert-config:create', 3, 2, 5022, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-06-27 14:28:59', '1', '2025-06-28 16:00: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 (5025, '告警配置更新', 'iot:alert-config:update', 3, 3, 5022, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-06-27 14:28:59', '1', '2025-06-28 16:00:43', 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 (5026, '告警配置删除', 'iot:alert-config:delete', 3, 4, 5022, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-06-27 14:29:00', '1', '2025-06-28 16:00:39', 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 (5028, '告警中心', '', 1, 3, 4000, 'alert', 'fa:soundcloud', '', '', 0, b'1', b'1', b'1', '1', '2025-06-27 22:30:04', '1', '2025-06-27 22:30: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 (5029, '告警记录', '', 2, 2, 5028, 'record', 'fa-solid:record-vinyl', 'iot/alert/record/index', 'IotAlertRecord', 0, b'1', b'1', b'1', '', '2025-06-28 07:59:32', '1', '2025-06-28 16:01:48', 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 (5030, '告警记录查询', 'iot:alert-record:query', 3, 1, 5029, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-06-28 07:59:32', '1', '2025-06-28 16:00:53', 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 (5031, '告警记录处理', 'iot:alert-record:process', 3, 2, 5029, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-06-28 07:59:32', '1', '2025-06-28 16:01:04', 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 (5032, 'OTA 固件', '', 2, 1, 4047, 'ota/firmware', 'fa-solid:award', 'iot/ota/firmware/index', 'IoTOtaFirmware', 0, b'1', b'1', b'1', '', '2025-06-30 07:50:29', '\"1\"', '2025-06-30 20:13: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 (5033, 'OTA 固件查询', 'iot:ota-firmware:query', 3, 1, 5032, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-06-30 07:50:29', '\"1\"', '2025-06-30 17:38: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 (5034, 'OTA 固件创建', 'iot:ota-firmware:create', 3, 2, 5032, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-06-30 07:50:29', '\"1\"', '2025-06-30 17:38:21', 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 (5035, 'OTA 固件更新', 'iot:ota-firmware:update', 3, 3, 5032, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-06-30 07:50:29', '\"1\"', '2025-06-30 17:38: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 (5036, 'OTA 固件删除', 'iot:ota-firmware:delete', 3, 4, 5032, '', '', '', '', 0, b'1', b'1', b'1', '', '2025-06-30 07:50:29', '\"1\"', '2025-06-30 17:38:37', 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 (5037, 'OTA 升级任务查询', 'iot:ota-task:create', 3, 11, 5032, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-07-02 23:56:56', '1', '2025-07-02 23:56: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 (5038, 'OTA 升级任务取消', 'iot:ota-task:cancel', 3, 13, 5032, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-07-02 23:57:26', '1', '2025-07-02 23:57:26', 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 (5039, 'OTA 升级任务创建', 'iot:ota-task:create', 3, 12, 5032, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-07-02 23:57:52', '1', '2025-07-02 23:57: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 (5040, 'OTA 升级记录查询', 'iot:ota-task-record:query', 3, 21, 5032, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-07-02 23:58:30', '1', '2025-07-02 23:58:30', 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 (5041, 'OTA 升级记录取消', 'iot:ota-task-record:cancel', 3, 23, 5032, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-07-02 23:59:18', '1', '2025-07-02 23:59:18', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -2285,7 +2338,7 @@ CREATE TABLE `system_notice` (
|
|||
-- Records of system_notice
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `system_notice` (`id`, `title`, `content`, `type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, '芋道的公众', '<p>新版本内容133</p>', 1, 0, 'admin', '2021-01-05 17:03:48', '1', '2022-05-04 21:00:20', b'0', 1);
|
||||
INSERT INTO `system_notice` (`id`, `title`, `content`, `type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, '芋道的公众', '<p>新版本内容133222</p>', 1, 0, 'admin', '2021-01-05 17:03:48', '\"1\"', '2025-08-31 09:38:22', b'0', 1);
|
||||
INSERT INTO `system_notice` (`id`, `title`, `content`, `type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, '维护通知:2018-07-01 系统凌晨维护', '<p><img src=\"http://test.yudao.iocoder.cn/b7cb3cf49b4b3258bf7309a09dd2f4e5.jpg\" alt=\"\" data-href=\"\">11112222<img src=\"http://test.yudao.iocoder.cn/fe44fc7bdb82ca421184b2eebbaee9e2148d4a1827479a4eb4521e11d2a062ba.png\" alt=\"image\" data-href=\"http://test.yudao.iocoder.cn/fe44fc7bdb82ca421184b2eebbaee9e2148d4a1827479a4eb4521e11d2a062ba.png\">3333</p>', 2, 1, 'admin', '2021-01-05 17:03:48', '1', '2025-04-18 23:56:40', b'0', 1);
|
||||
INSERT INTO `system_notice` (`id`, `title`, `content`, `type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, '我是测试标题', '<p>哈哈哈哈123</p>', 1, 0, '110', '2022-02-22 01:01:25', '110', '2022-02-22 01:01:46', b'0', 121);
|
||||
COMMIT;
|
||||
|
@ -2381,7 +2434,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 = 16697 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 20179 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_oauth2_access_token
|
||||
|
@ -2449,7 +2502,7 @@ CREATE TABLE `system_oauth2_client` (
|
|||
-- Records of system_oauth2_client
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `system_oauth2_client` (`id`, `client_id`, `secret`, `name`, `logo`, `description`, `status`, `access_token_validity_seconds`, `refresh_token_validity_seconds`, `redirect_uris`, `authorized_grant_types`, `scopes`, `auto_approve_scopes`, `authorities`, `resource_ids`, `additional_information`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, 'default', 'admin123', '芋道源码', 'http://test.yudao.iocoder.cn/20250502/sort2_1746189740718.png', '我是描述', 0, 1800, 2592000, '[\"https://www.iocoder.cn\",\"https://doc.iocoder.cn\"]', '[\"password\",\"authorization_code\",\"implicit\",\"refresh_token\"]', '[\"user.read\",\"user.write\"]', '[]', '[\"user.read\",\"user.write\"]', '[]', '{}', '1', '2022-05-11 21:47:12', '1', '2025-05-02 20:42:22', b'0');
|
||||
INSERT INTO `system_oauth2_client` (`id`, `client_id`, `secret`, `name`, `logo`, `description`, `status`, `access_token_validity_seconds`, `refresh_token_validity_seconds`, `redirect_uris`, `authorized_grant_types`, `scopes`, `auto_approve_scopes`, `authorities`, `resource_ids`, `additional_information`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, 'default', 'admin123', '芋道源码', 'http://test.yudao.iocoder.cn/20250502/sort2_1746189740718.png', '我是描述', 0, 1800, 2592000, '[\"https://www.iocoder.cn\",\"https://doc.iocoder.cn\"]', '[\"password\",\"authorization_code\",\"implicit\",\"refresh_token\",\"client_credentials\"]', '[\"user.read\",\"user.write\"]', '[]', '[\"user.read\",\"user.write\"]', '[]', '{}', '1', '2022-05-11 21:47:12', '1', '2025-08-21 10:04:50', b'0');
|
||||
INSERT INTO `system_oauth2_client` (`id`, `client_id`, `secret`, `name`, `logo`, `description`, `status`, `access_token_validity_seconds`, `refresh_token_validity_seconds`, `redirect_uris`, `authorized_grant_types`, `scopes`, `auto_approve_scopes`, `authorities`, `resource_ids`, `additional_information`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (40, 'test', 'test2', 'biubiu', 'http://test.yudao.iocoder.cn/xx/20250502/ed07110a37464b5299f8bd7c67ad65c7_1746187077009.jpg', '啦啦啦啦', 0, 1800, 43200, '[\"https://www.iocoder.cn\"]', '[\"password\",\"authorization_code\",\"implicit\"]', '[\"user_info\",\"projects\"]', '[\"user_info\"]', '[]', '[]', '{}', '1', '2022-05-12 00:28:20', '1', '2025-05-02 19:58:08', b'0');
|
||||
INSERT INTO `system_oauth2_client` (`id`, `client_id`, `secret`, `name`, `logo`, `description`, `status`, `access_token_validity_seconds`, `refresh_token_validity_seconds`, `redirect_uris`, `authorized_grant_types`, `scopes`, `auto_approve_scopes`, `authorities`, `resource_ids`, `additional_information`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (41, 'yudao-sso-demo-by-code', 'test', '基于授权码模式,如何实现 SSO 单点登录?', 'http://test.yudao.iocoder.cn/it/20250502/sign_1746181948685.png', NULL, 0, 1800, 43200, '[\"http://127.0.0.1:18080\"]', '[\"authorization_code\",\"refresh_token\"]', '[\"user.read\",\"user.write\"]', '[]', '[]', '[]', NULL, '1', '2022-09-29 13:28:31', '1', '2025-05-02 18:32:30', b'0');
|
||||
INSERT INTO `system_oauth2_client` (`id`, `client_id`, `secret`, `name`, `logo`, `description`, `status`, `access_token_validity_seconds`, `refresh_token_validity_seconds`, `redirect_uris`, `authorized_grant_types`, `scopes`, `auto_approve_scopes`, `authorities`, `resource_ids`, `additional_information`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (42, 'yudao-sso-demo-by-password', 'test', '基于密码模式,如何实现 SSO 单点登录?', 'http://test.yudao.iocoder.cn/604bdc695e13b3b22745be704d1f2aa8ee05c5f26f9fead6d1ca49005afbc857.jpeg', NULL, 0, 1800, 43200, '[\"http://127.0.0.1:18080\"]', '[\"password\",\"refresh_token\"]', '[\"user.read\",\"user.write\"]', '[]', '[]', '[]', NULL, '1', '2022-10-04 17:40:16', '1', '2025-05-04 16:00:46', b'0');
|
||||
|
@ -2503,7 +2556,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 = 2036 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2201 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_oauth2_refresh_token
|
||||
|
@ -2537,7 +2590,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 = 9090 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录 V2 版本';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 9134 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录 V2 版本';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_operate_log
|
||||
|
@ -2605,11 +2658,9 @@ 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, 1, '[]', 0, 2, '123', '', '2021-01-06 13:49:35', '1', '2025-04-30 17:38:28', 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 (155, '测试数据权限', 'test-dp', 3, 2, '[100,102,103,104,105,108]', 0, 2, '', '1', '2025-03-31 14:58:06', '1', '2025-04-17 23:07:44', 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 (158, '2', '3', 4, 1, '', 0, 2, NULL, '1', '2025-04-17 20:08:08', '1', '2025-04-17 23:05:31', b'0', 1);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -2668,87 +2719,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 (707, 2, 113, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1296, 110, 1, '110', '2022-02-23 00:23:55', '110', '2022-02-23 00:23:55', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1578, 111, 1, '1', '2022-03-07 21:37:58', '1', '2022-03-07 21:37:58', b'0', 122);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1604, 101, 1216, '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 (1605, 101, 1217, '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 (1606, 101, 1218, '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 (1607, 101, 1219, '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 (1608, 101, 1220, '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 (1609, 101, 1221, '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 (1610, 101, 5, '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 (1611, 101, 1222, '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 (1612, 101, 1118, '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 (1613, 101, 1119, '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 (1614, 101, 1120, '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 (1615, 101, 1185, '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 (1616, 101, 1186, '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 (1617, 101, 1187, '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 (1618, 101, 1188, '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 (1619, 101, 1189, '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 (1620, 101, 1190, '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 (1621, 101, 1191, '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 (1622, 101, 1192, '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 (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 (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);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1630, 101, 1200, '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 (1631, 101, 1201, '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 (1632, 101, 1202, '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 (1633, 101, 1207, '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 (1634, 101, 1208, '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 (1635, 101, 1209, '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 (1636, 101, 1210, '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 (1637, 101, 1211, '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 (1638, 101, 1212, '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 (1639, 101, 1213, '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 (1640, 101, 1215, '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 (1641, 101, 2, '1', '2022-04-01 22:21:24', '1', '2022-04-01 22:21:24', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1642, 101, 1031, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1643, 101, 1032, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1644, 101, 1033, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1645, 101, 1034, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1646, 101, 1035, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1647, 101, 1050, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1648, 101, 1051, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1649, 101, 1052, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1650, 101, 1053, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1651, 101, 1054, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1652, 101, 1056, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1653, 101, 1057, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1654, 101, 1058, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1655, 101, 1059, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1656, 101, 1060, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1657, 101, 1066, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1658, 101, 1067, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1659, 101, 1070, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1664, 101, 1075, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1666, 101, 1077, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1667, 101, 1078, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1668, 101, 1082, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1669, 101, 1083, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1670, 101, 1084, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1671, 101, 1085, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1672, 101, 1086, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1673, 101, 1087, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1674, 101, 1088, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1675, 101, 1089, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1679, 101, 1237, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1680, 101, 1238, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1681, 101, 1239, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1682, 101, 1240, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1683, 101, 1241, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1684, 101, 1242, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1685, 101, 1243, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1687, 101, 106, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1688, 101, 110, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1689, 101, 111, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1690, 101, 112, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1691, 101, 113, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1692, 101, 114, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1693, 101, 115, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1694, 101, 116, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1729, 109, 100, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1730, 109, 101, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1731, 109, 1063, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', b'0', 121);
|
||||
|
@ -3028,119 +2998,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 (2182, 2, 2016, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2183, 2, 2017, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2184, 2, 2018, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2188, 101, 1024, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2189, 101, 1, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2190, 101, 1025, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2191, 101, 1026, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2192, 101, 1027, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2193, 101, 1028, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2194, 101, 1029, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2195, 101, 1030, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2196, 101, 1036, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2197, 101, 1037, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2198, 101, 1038, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2199, 101, 1039, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2200, 101, 1040, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2201, 101, 1042, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2202, 101, 1043, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2203, 101, 1045, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2204, 101, 1046, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2205, 101, 1048, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2206, 101, 2083, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2207, 101, 1063, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2208, 101, 1064, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2209, 101, 1065, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2210, 101, 1093, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2211, 101, 1094, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2212, 101, 1095, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2213, 101, 1096, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2214, 101, 1097, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2215, 101, 1098, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2216, 101, 1100, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2217, 101, 1101, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2218, 101, 1102, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2219, 101, 1103, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2220, 101, 1104, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2221, 101, 1105, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2222, 101, 1106, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2223, 101, 2130, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2224, 101, 1107, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2225, 101, 2131, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2226, 101, 1108, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2227, 101, 2132, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2228, 101, 1109, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2229, 101, 2133, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2230, 101, 2134, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2232, 101, 2135, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2234, 101, 2136, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2236, 101, 2137, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2238, 101, 2138, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2240, 101, 2139, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2242, 101, 2140, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2243, 101, 2141, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2244, 101, 2142, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2245, 101, 2143, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2246, 101, 2144, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2247, 101, 2145, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2248, 101, 2146, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2249, 101, 2147, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2250, 101, 100, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2251, 101, 2148, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2252, 101, 101, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2253, 101, 2149, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2254, 101, 102, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2255, 101, 2150, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2256, 101, 103, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2257, 101, 2151, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2258, 101, 104, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2259, 101, 2152, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2260, 101, 105, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2261, 101, 107, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2262, 101, 108, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2263, 101, 109, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2264, 101, 1138, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2265, 101, 1139, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2266, 101, 1140, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2267, 101, 1141, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2268, 101, 1142, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2269, 101, 1143, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2270, 101, 1224, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2271, 101, 1225, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2272, 101, 1226, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2273, 101, 1227, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2274, 101, 1228, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2275, 101, 1229, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2282, 101, 1261, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2283, 101, 1263, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2284, 101, 1264, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2285, 101, 1265, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2286, 101, 1266, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2287, 101, 1267, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2288, 101, 1001, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2289, 101, 1002, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2290, 101, 1003, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2291, 101, 1004, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2292, 101, 1005, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2293, 101, 1006, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2294, 101, 1007, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2295, 101, 1008, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2296, 101, 1009, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2297, 101, 1010, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2298, 101, 1011, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2299, 101, 1012, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2300, 101, 500, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2301, 101, 1013, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2302, 101, 501, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2303, 101, 1014, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2304, 101, 1015, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2305, 101, 1016, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2306, 101, 1017, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2307, 101, 1018, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2308, 101, 1019, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2309, 101, 1020, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2310, 101, 1021, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2311, 101, 1022, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2312, 101, 1023, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2929, 109, 1224, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2930, 109, 1225, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2931, 109, 1226, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 121);
|
||||
|
@ -3358,7 +3215,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 (4193, 109, 2730, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4194, 109, 1195, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4195, 109, 2731, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4196, 109, 1196, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4197, 109, 2732, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4198, 109, 1197, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4199, 109, 2733, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
|
||||
|
@ -3417,7 +3273,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 (4252, 111, 2730, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4253, 111, 1195, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4254, 111, 2731, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4255, 111, 1196, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4256, 111, 2732, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4257, 111, 1197, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4258, 111, 2733, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
|
||||
|
@ -3443,8 +3298,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 (4278, 111, 1220, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4279, 111, 1221, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4280, 111, 1222, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5777, 101, 2739, '1', '2024-04-30 09:38:37', '1', '2024-04-30 09:38:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5778, 101, 2740, '1', '2024-04-30 09:38:37', '1', '2024-04-30 09:38:37', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5779, 2, 2739, '1', '2024-07-07 20:39:38', '1', '2024-07-07 20:39:38', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5780, 2, 2740, '1', '2024-07-07 20:39:38', '1', '2024-07-07 20:39:38', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5781, 2, 2758, '1', '2024-07-07 20:39:38', '1', '2024-07-07 20:39:38', b'0', 1);
|
||||
|
@ -3452,9 +3305,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 (5783, 2, 2362, '1', '2024-07-07 20:39:38', '1', '2024-07-07 20:39:38', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5784, 2, 2387, '1', '2024-07-07 20:39:38', '1', '2024-07-07 20:39:38', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5785, 2, 2030, '1', '2024-07-07 20:39:38', '1', '2024-07-07 20:39:38', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5786, 101, 2758, '1', '2024-07-07 20:39:55', '1', '2024-07-07 20:39:55', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5787, 101, 2759, '1', '2024-07-07 20:39:55', '1', '2024-07-07 20:39:55', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5788, 101, 2783, '1', '2024-07-07 20:39:55', '1', '2024-07-07 20:39:55', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5789, 109, 2739, '1', '2024-07-13 22:37:24', '1', '2024-07-13 22:37:24', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5790, 109, 2740, '1', '2024-07-13 22:37:24', '1', '2024-07-13 22:37:24', b'0', 121);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5791, 111, 2739, '1', '2024-07-13 22:37:24', '1', '2024-07-13 22:37:24', b'0', 122);
|
||||
|
@ -3475,7 +3325,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 (6115, 155, 4043, '1', '2025-04-01 13:49:30', '1', '2025-04-01 13:49:30', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6116, 155, 4044, '1', '2025-04-01 13:49:30', '1', '2025-04-01 13:49:30', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6117, 155, 4045, '1', '2025-04-01 13:49:30', '1', '2025-04-01 13:49:30', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6118, 155, 4046, '1', '2025-04-01 13:49:30', '1', '2025-04-01 13:49:30', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6119, 155, 4001, '1', '2025-04-01 13:49:30', '1', '2025-04-01 13:49:30', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6120, 155, 4002, '1', '2025-04-01 13:49:30', '1', '2025-04-01 13:49:30', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6121, 155, 4003, '1', '2025-04-01 13:49:30', '1', '2025-04-01 13:49:30', b'0', 1);
|
||||
|
@ -3495,7 +3344,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 (6135, 155, 4017, '1', '2025-04-01 13:49:30', '1', '2025-04-01 13:49:30', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6136, 155, 4018, '1', '2025-04-01 13:49:30', '1', '2025-04-01 13:49:30', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6137, 155, 4031, '1', '2025-04-01 13:49:30', '1', '2025-04-01 13:49:30', b'0', 1);
|
||||
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6138, 101, 5010, '1', '2025-05-05 17:49:17', '1', '2025-05-05 17:49:17', b'0', 1);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -3550,7 +3398,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 = 666 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 681 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_sms_code
|
||||
|
@ -3591,7 +3439,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 = 1290 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1491 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_sms_log
|
||||
|
@ -3724,7 +3572,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 = 164 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 165 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_social_user_bind
|
||||
|
@ -3742,8 +3590,8 @@ CREATE TABLE `system_tenant` (
|
|||
`contact_user_id` bigint NULL DEFAULT NULL COMMENT '联系人的用户编号',
|
||||
`contact_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '联系人',
|
||||
`contact_mobile` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '联系手机',
|
||||
`status` tinyint NOT NULL DEFAULT 0 COMMENT '租户状态(0正常 1停用)',
|
||||
`website` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '绑定域名',
|
||||
`status` tinyint NOT NULL DEFAULT 0 COMMENT '租户状态',
|
||||
`websites` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '绑定域名数组',
|
||||
`package_id` bigint NOT NULL COMMENT '租户套餐编号',
|
||||
`expire_time` datetime NOT NULL COMMENT '过期时间',
|
||||
`account_count` int NOT NULL COMMENT '账号数量',
|
||||
|
@ -3759,9 +3607,9 @@ CREATE TABLE `system_tenant` (
|
|||
-- Records of system_tenant
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', b'0');
|
||||
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2026-07-10 00:00:00', 30, '1', '2022-02-22 00:56:14', '1', '2025-04-03 21:33:01', b'0');
|
||||
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2024-09-22 12:10:50', b'0');
|
||||
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `websites`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn,127.0.0.1:3000,wxc4598c446f8a9cb3', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2025-08-19 05:18:41', b'0');
|
||||
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `websites`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn,123321', 111, '2026-07-10 00:00:00', 30, '1', '2022-02-22 00:56:14', '1', '2025-08-19 21:19:29', b'0');
|
||||
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `websites`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2025-08-24 14:46:15', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -3786,8 +3634,7 @@ CREATE TABLE `system_tenant_package` (
|
|||
-- Records of system_tenant_package
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `system_tenant_package` (`id`, `name`, `status`, `remark`, `menu_ids`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (111, '普通套餐', 0, '小功能', '[1,2,5,1031,1032,1033,1034,1035,1036,1037,1038,1039,1050,1051,1052,1053,1054,1056,1057,1058,1059,1060,1063,1064,1065,1066,1067,1070,1075,1077,1078,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1118,1119,1120,100,101,102,103,106,107,110,111,112,113,1138,114,1139,115,1140,116,1141,1142,1143,2713,2714,2715,2716,2717,2718,2720,1185,2721,1186,2722,1187,2723,1188,2724,1189,2725,1190,2726,1191,2727,2472,1192,2728,1193,2729,1194,2730,1195,2731,1196,2732,1197,2733,2478,1198,2734,2479,1199,2735,2480,1200,2481,1201,2482,1202,2483,2739,2484,2740,2485,2486,2487,1207,2488,1208,2489,1209,2490,1210,2491,1211,2492,1212,2493,1213,2494,2495,1215,1216,2497,1217,1218,1219,1220,1221,1222,1224,1225,1226,1227,1228,1229,1237,1238,1239,1240,1241,1242,1243,2525,1255,1256,1001,1257,1002,1258,1003,1259,1004,1260,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020]', '1', '2022-02-22 00:54:00', '1', '2024-07-13 22:37:24', b'0');
|
||||
INSERT INTO `system_tenant_package` (`id`, `name`, `status`, `remark`, `menu_ids`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (112, '再来一个套餐', 0, '1234', '[1024,1,1025,1026,2,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1042,1043,1045,1046,1048,1050,1051,1052,1053,1054,1056,1057,1058,2083,1059,1060,1063,1064,1065,1066,1067,1070,1075,1077,1078,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1100,1101,1102,1103,1104,1105,1106,2130,1107,2131,1108,2132,1109,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,100,2148,101,2149,102,2150,103,2151,104,2152,105,106,107,108,109,110,111,112,113,1138,114,1139,115,1140,116,1141,1142,1143,2739,2740,1224,1225,1226,1227,1228,1229,1237,1238,1239,1240,1241,1242,1243,1255,1256,1257,1258,1259,1260,1261,1263,1264,1265,1266,1267,2447,2448,2449,2450,2451,2452,2453,2472,2478,2479,2480,2481,2482,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2497,2525,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,500,1013,501,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023]', '1', '2025-04-04 08:15:02', '1', '2025-04-04 08:15:21', b'0');
|
||||
INSERT INTO `system_tenant_package` (`id`, `name`, `status`, `remark`, `menu_ids`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (111, '普通套餐', 0, '小功能', '[1,2,5,1031,1032,1033,1034,1035,1036,1037,1038,1039,1050,1051,1052,1053,1054,1056,1057,1058,1059,1060,1063,1064,1065,1066,1067,1070,1075,1077,1078,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1118,1119,1120,100,101,102,103,106,107,110,111,112,113,114,1138,1139,115,1140,116,1141,1142,1143,2713,2714,2715,2716,2717,2718,2720,2721,1185,2722,1186,1187,2723,1188,2724,1189,2725,1190,2726,1191,2727,2472,1192,2728,2729,1193,1194,2730,1195,2731,2732,1197,2733,2478,1198,2734,2479,1199,2735,2480,1200,2481,1201,2482,1202,2739,2483,2484,2740,2485,2486,2487,1207,2488,1208,2489,1209,2490,1210,2491,1211,2492,1212,2493,1213,2494,2495,1215,1216,2497,1217,1218,1219,1220,1221,1222,1224,1225,1226,1227,1228,1229,1237,1238,1239,1240,1241,1242,1243,2525,1255,1256,1001,1257,1002,1258,1003,1259,1004,1260,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020]', '1', '2022-02-22 00:54:00', '1', '2025-05-14 14:06:34', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -3837,7 +3684,7 @@ CREATE TABLE `system_user_role` (
|
|||
`deleted` bit(1) NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 49 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户和角色关联表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 50 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户和角色关联表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_user_role
|
||||
|
@ -3845,7 +3692,6 @@ CREATE TABLE `system_user_role` (
|
|||
BEGIN;
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 1, 1, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:17', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, 2, 2, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:13', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, 100, 101, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:13', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, 100, 1, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:12', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6, 100, 2, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:11', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (10, 103, 1, '1', '2022-01-11 13:19:45', '1', '2022-01-11 13:19:45', b'0', 1);
|
||||
|
@ -3856,10 +3702,10 @@ INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_t
|
|||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (22, 115, 2, '1', '2022-07-21 22:08:30', '1', '2022-07-21 22:08:30', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (35, 112, 1, '1', '2024-03-15 20:00:24', '1', '2024-03-15 20:00:24', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (36, 118, 1, '1', '2024-03-17 09:12:08', '1', '2024-03-17 09:12:08', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (38, 114, 101, '1', '2024-03-24 22:23:03', '1', '2024-03-24 22:23:03', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (46, 117, 1, '1', '2024-10-02 10:16:11', '1', '2024-10-02 10:16:11', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (47, 104, 2, '1', '2025-01-04 10:40:33', '1', '2025-01-04 10:40:33', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (48, 100, 155, '1', '2025-04-04 10:41:14', '1', '2025-04-04 10:41:14', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (49, 142, 1, '1', '2025-07-23 09:11:42', '1', '2025-07-23 09:11:42', b'0', 1);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -3888,15 +3734,15 @@ CREATE TABLE `system_users` (
|
|||
`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 = 142 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户信息表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 143 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户信息表';
|
||||
|
||||
-- ----------------------------
|
||||
-- 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$04$KljJDa/LK7QfDm0lF5OhuePhlPfjRH3tB2Wu351Uidz.oQGJXevPi', '芋道源码', '管理员', 103, '[1,2]', '11aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/test/20250502/avatar_1746154660449.png', 0, '0:0:0:0:0:0:0:1', '2025-05-10 18:03:15', 'admin', '2021-01-05 17:03:47', NULL, '2025-05-10 18:03:15', 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$04$KljJDa/LK7QfDm0lF5OhuePhlPfjRH3tB2Wu351Uidz.oQGJXevPi', '芋道源码', '管理员', 103, '[1,2]', '11aoteman@126.com', '18818260272', 2, 'http://test.yudao.iocoder.cn/user/avatar/20250709/blob_1752042302026.jpg', 0, '0:0:0:0:0:0:0:1', '2025-08-30 19:57:52', 'admin', '2021-01-05 17:03:47', NULL, '2025-08-30 19:57:52', 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$04$h.aaPKgO.odHepnk5PCsWeEwKdojFWdTItxGKfx1r0e1CSeBzsTJ6', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2025-04-08 09:36:40', '', '2021-01-07 09:07:17', NULL, '2025-04-21 14:23: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 (103, 'yuanma', '$2a$04$fUBSmjKCPYAUmnMzOb6qE.eZCGPhHi1JmAKclODbfS/O7fHOl2bH6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, NULL, 0, '0:0:0:0:0:0:0:1', '2024-08-11 17:48:12', '', '2021-01-13 23:50:35', NULL, '2025-04-21 14:23: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 (103, 'yuanma', '$2a$04$fUBSmjKCPYAUmnMzOb6qE.eZCGPhHi1JmAKclODbfS/O7fHOl2bH6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, NULL, 0, '0:0:0:0:0:0:0:1', '2024-08-11 17:48:12', '', '2021-01-13 23:50:35', '1', '2025-07-09 23:41:58', 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$BrwaYn303hjA/6TnXqdGoOLhyHOAA0bVrAFu6.1dJKycqKUnIoRz2', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2025-03-28 20:01:16', '', '2021-01-21 02:13:53', NULL, '2025-04-21 14:23: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, NULL, 0, '', NULL, '1', '2022-02-20 22:59:33', '1', '2025-04-21 14:23:08', 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, NULL, 0, '', NULL, '1', '2022-02-20 23:00:50', '1', '2025-04-21 14:23:08', b'0', 119);
|
||||
|
@ -3907,11 +3753,11 @@ 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', '芋道1', NULL, NULL, NULL, '', '15601691300', 0, NULL, 0, '127.0.0.1', '2022-03-19 18:38:51', '1', '2022-03-07 21:37:58', '1', '2025-05-05 15:30:53', 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, NULL, 0, '0:0:0:0:0:0:0:1', '2024-03-24 22:21:05', '1', '2022-03-19 21:50:58', NULL, '2025-04-21 14:23: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 (115, 'aotemane', '$2a$04$GcyP0Vyzb2F2Yni5PuIK9ueGxM0tkZGMtDwVRwrNbtMvorzbpNsV2', '阿呆', '11222', 102, '[1,2]', '7648@qq.com', '15601691229', 2, NULL, 0, '', NULL, '1', '2022-04-30 02:55:43', '1', '2025-04-21 14:23: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 (117, 'admin123', '$2a$04$sEtimsHu9YCkYY4/oqElHem2Ijc9ld20eYO6lN.g/21NfLUTDLB9W', '测试号02', '1111', 100, '[2]', '', '15601691234', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2024-10-02 10:16:20', '1', '2022-07-09 17:40:26', NULL, '2025-04-21 14:23: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 (118, 'goudan', '$2a$04$jth0yOj8cSJq84D6vrzusOHDwW/LpBfgBnQ6bfFlD8zNZfM632Ta2', '狗蛋', NULL, 103, '[1]', '', '15601691239', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2024-03-17 09:10:27', '1', '2022-07-09 17:44:43', '1', '2025-04-21 14:23: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 (131, 'hh', '$2a$04$jyH9h6.gaw8mpOjPfHIpx.8as2Rzfcmdlj5rlJFwgCw4rsv/MTb2K', '呵呵', NULL, 100, '[]', '777@qq.com', '15601882312', 1, NULL, 0, '', NULL, '1', '2024-04-27 08:45:56', '1', '2025-04-21 14:23: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 (117, 'admin123', '$2a$04$sEtimsHu9YCkYY4/oqElHem2Ijc9ld20eYO6lN.g/21NfLUTDLB9W', '测试号02', '1111', 100, '[2]', '', '15601691234', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2024-10-02 10:16:20', '1', '2022-07-09 17:40:26', '1', '2025-05-14 09:56: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 (118, 'goudan', '$2a$04$jth0yOj8cSJq84D6vrzusOHDwW/LpBfgBnQ6bfFlD8zNZfM632Ta2', '狗蛋', NULL, 103, '[1]', '', '15601691239', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2024-03-17 09:10:27', '1', '2022-07-09 17:44:43', '1', '2025-07-09 23:52:36', 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 (139, 'wwbwwb', '$2a$04$aOHoFbQU6zfBk/1Z9raF/ugTdhjNdx7culC1HhO0zvoczAnahCiMq', '小秃头', NULL, NULL, NULL, '', '', 0, NULL, 0, '0:0:0:0:0:0:0:1', '2024-09-10 21:03:58', NULL, '2024-09-10 21:03:58', NULL, '2025-04-21 14:23: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 (141, 'admin1', '$2a$04$oj6F6d7HrZ70kYVD3TNzEu.m3TPUzajOVuC66zdKna8KRerK1FmVa', '新用户', NULL, NULL, NULL, '', '', 0, '', 0, '0:0:0:0:0:0:0:1', '2025-04-08 13:09:07', '1', '2025-04-08 13:09:07', '1', '2025-04-08 13:09:07', 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 (141, 'admin1', '$2a$04$oj6F6d7HrZ70kYVD3TNzEu.m3TPUzajOVuC66zdKna8KRerK1FmVa', '新用户', NULL, NULL, NULL, '', '', 0, '', 0, '0:0:0:0:0:0:0:1', '2025-04-08 13:09:07', '1', '2025-04-08 13:09:07', '1', '2025-05-14 19:11:48', 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 (142, 'test01', '$2a$04$vxfBq9d3vVIfUbo6Dw7Mt.KOJfvG7RJ.l2/B3Kw09NtNyAZ1vbB1m', 'test01', '', NULL, '[]', '', '', 1, '', 0, '0:0:0:0:0:0:0:1', '2025-07-29 19:47:17', '1', '2025-07-09 21:07:10', NULL, '2025-07-29 19:47:17', b'0', 1);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
|
|
@ -4608,7 +4608,7 @@ CREATE TABLE system_tenant
|
|||
contact_name varchar(30) NOT NULL,
|
||||
contact_mobile varchar(500) NULL DEFAULT NULL,
|
||||
status int2 NOT NULL DEFAULT 0,
|
||||
website varchar(256) NULL DEFAULT '',
|
||||
websites varchar(256) NULL DEFAULT '',
|
||||
package_id int8 NOT NULL,
|
||||
expire_time timestamp NOT NULL,
|
||||
account_count int4 NOT NULL,
|
||||
|
@ -4628,7 +4628,7 @@ COMMENT ON COLUMN system_tenant.contact_user_id IS '联系人的用户编号';
|
|||
COMMENT ON COLUMN system_tenant.contact_name IS '联系人';
|
||||
COMMENT ON COLUMN system_tenant.contact_mobile IS '联系手机';
|
||||
COMMENT ON COLUMN system_tenant.status IS '租户状态(0正常 1停用)';
|
||||
COMMENT ON COLUMN system_tenant.website IS '绑定域名';
|
||||
COMMENT ON COLUMN system_tenant.websites IS '绑定域名数组';
|
||||
COMMENT ON COLUMN system_tenant.package_id IS '租户套餐编号';
|
||||
COMMENT ON COLUMN system_tenant.expire_time IS '过期时间';
|
||||
COMMENT ON COLUMN system_tenant.account_count IS '账号数量';
|
||||
|
@ -4644,9 +4644,9 @@ COMMENT ON TABLE system_tenant IS '租户表';
|
|||
-- ----------------------------
|
||||
-- @formatter:off
|
||||
BEGIN;
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2026-07-10 00:00:00', 30, '1', '2022-02-22 00:56:14', '1', '2025-04-03 21:33:01', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2024-09-22 12:10:50', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2026-07-10 00:00:00', 30, '1', '2022-02-22 00:56:14', '1', '2025-04-03 21:33:01', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2024-09-22 12:10:50', '0');
|
||||
COMMIT;
|
||||
-- @formatter:on
|
||||
|
||||
|
|
|
@ -4495,7 +4495,7 @@ CREATE TABLE system_tenant
|
|||
contact_name varchar2(30) NULL,
|
||||
contact_mobile varchar2(500) DEFAULT NULL NULL,
|
||||
status smallint DEFAULT 0 NOT NULL,
|
||||
website varchar2(256) DEFAULT '' NULL,
|
||||
websites varchar2(256) DEFAULT '' NULL,
|
||||
package_id number NOT NULL,
|
||||
expire_time date NOT NULL,
|
||||
account_count number NOT NULL,
|
||||
|
@ -4515,7 +4515,7 @@ COMMENT ON COLUMN system_tenant.contact_user_id IS '联系人的用户编号';
|
|||
COMMENT ON COLUMN system_tenant.contact_name IS '联系人';
|
||||
COMMENT ON COLUMN system_tenant.contact_mobile IS '联系手机';
|
||||
COMMENT ON COLUMN system_tenant.status IS '租户状态(0正常 1停用)';
|
||||
COMMENT ON COLUMN system_tenant.website IS '绑定域名';
|
||||
COMMENT ON COLUMN system_tenant.websites IS '绑定域名数组';
|
||||
COMMENT ON COLUMN system_tenant.package_id IS '租户套餐编号';
|
||||
COMMENT ON COLUMN system_tenant.expire_time IS '过期时间';
|
||||
COMMENT ON COLUMN system_tenant.account_count IS '账号数量';
|
||||
|
@ -4530,9 +4530,9 @@ COMMENT ON TABLE system_tenant IS '租户表';
|
|||
-- Records of system_tenant
|
||||
-- ----------------------------
|
||||
-- @formatter:off
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, to_date('2099-02-19 17:14:16', 'SYYYY-MM-DD HH24:MI:SS'), 9999, '1', to_date('2021-01-05 17:03:47', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2023-11-06 11:41:41', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, to_date('2026-07-10 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 30, '1', to_date('2022-02-22 00:56:14', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2025-04-03 21:33:01', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, to_date('2022-04-29 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 50, '1', to_date('2022-03-07 21:37:58', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2024-09-22 12:10:50', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, to_date('2099-02-19 17:14:16', 'SYYYY-MM-DD HH24:MI:SS'), 9999, '1', to_date('2021-01-05 17:03:47', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2023-11-06 11:41:41', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, to_date('2026-07-10 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 30, '1', to_date('2022-02-22 00:56:14', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2025-04-03 21:33:01', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, to_date('2022-04-29 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 50, '1', to_date('2022-03-07 21:37:58', 'SYYYY-MM-DD HH24:MI:SS'), '1', to_date('2024-09-22 12:10:50', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
COMMIT;
|
||||
-- @formatter:on
|
||||
|
||||
|
|
|
@ -4608,7 +4608,7 @@ CREATE TABLE system_tenant
|
|||
contact_name varchar(30) NOT NULL,
|
||||
contact_mobile varchar(500) NULL DEFAULT NULL,
|
||||
status int2 NOT NULL DEFAULT 0,
|
||||
website varchar(256) NULL DEFAULT '',
|
||||
websites varchar(256) NULL DEFAULT '',
|
||||
package_id int8 NOT NULL,
|
||||
expire_time timestamp NOT NULL,
|
||||
account_count int4 NOT NULL,
|
||||
|
@ -4628,7 +4628,7 @@ COMMENT ON COLUMN system_tenant.contact_user_id IS '联系人的用户编号';
|
|||
COMMENT ON COLUMN system_tenant.contact_name IS '联系人';
|
||||
COMMENT ON COLUMN system_tenant.contact_mobile IS '联系手机';
|
||||
COMMENT ON COLUMN system_tenant.status IS '租户状态(0正常 1停用)';
|
||||
COMMENT ON COLUMN system_tenant.website IS '绑定域名';
|
||||
COMMENT ON COLUMN system_tenant.websites IS '绑定域名数组';
|
||||
COMMENT ON COLUMN system_tenant.package_id IS '租户套餐编号';
|
||||
COMMENT ON COLUMN system_tenant.expire_time IS '过期时间';
|
||||
COMMENT ON COLUMN system_tenant.account_count IS '账号数量';
|
||||
|
@ -4644,9 +4644,9 @@ COMMENT ON TABLE system_tenant IS '租户表';
|
|||
-- ----------------------------
|
||||
-- @formatter:off
|
||||
BEGIN;
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2026-07-10 00:00:00', 30, '1', '2022-02-22 00:56:14', '1', '2025-04-03 21:33:01', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2024-09-22 12:10:50', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2026-07-10 00:00:00', 30, '1', '2022-02-22 00:56:14', '1', '2025-04-03 21:33:01', '0');
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2024-09-22 12:10:50', '0');
|
||||
COMMIT;
|
||||
-- @formatter:on
|
||||
|
||||
|
|
|
@ -10834,7 +10834,7 @@ CREATE TABLE system_tenant
|
|||
contact_name nvarchar(30) NOT NULL,
|
||||
contact_mobile nvarchar(500) DEFAULT NULL NULL,
|
||||
status tinyint DEFAULT 0 NOT NULL,
|
||||
website nvarchar(256) DEFAULT '' NULL,
|
||||
websites nvarchar(256) DEFAULT '' NULL,
|
||||
package_id bigint NOT NULL,
|
||||
expire_time datetime2 NOT NULL,
|
||||
account_count int NOT NULL,
|
||||
|
@ -10965,11 +10965,11 @@ BEGIN TRANSACTION
|
|||
GO
|
||||
SET IDENTITY_INSERT system_tenant ON
|
||||
GO
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, N'芋道源码', NULL, N'芋艿', N'17321315478', 0, N'www.iocoder.cn', 0, N'2099-02-19 17:14:16', 9999, N'1', N'2021-01-05 17:03:47', N'1', N'2023-11-06 11:41:41', N'0')
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, N'芋道源码', NULL, N'芋艿', N'17321315478', 0, N'www.iocoder.cn', 0, N'2099-02-19 17:14:16', 9999, N'1', N'2021-01-05 17:03:47', N'1', N'2023-11-06 11:41:41', N'0')
|
||||
GO
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, N'小租户', 110, N'小王2', N'15601691300', 0, N'zsxq.iocoder.cn', 111, N'2026-07-10 00:00:00', 30, N'1', N'2022-02-22 00:56:14', N'1', N'2025-04-03 21:33:01', N'0')
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, N'小租户', 110, N'小王2', N'15601691300', 0, N'zsxq.iocoder.cn', 111, N'2026-07-10 00:00:00', 30, N'1', N'2022-02-22 00:56:14', N'1', N'2025-04-03 21:33:01', N'0')
|
||||
GO
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, N'测试租户', 113, N'芋道', N'15601691300', 0, N'test.iocoder.cn', 111, N'2022-04-29 00:00:00', 50, N'1', N'2022-03-07 21:37:58', N'1', N'2024-09-22 12:10:50', N'0')
|
||||
INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, websites, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, N'测试租户', 113, N'芋道', N'15601691300', 0, N'test.iocoder.cn', 111, N'2022-04-29 00:00:00', 50, N'1', N'2022-03-07 21:37:58', N'1', N'2024-09-22 12:10:50', N'0')
|
||||
GO
|
||||
SET IDENTITY_INSERT system_tenant OFF
|
||||
GO
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||
|
||||
<properties>
|
||||
<revision>2025.08-jdk8-SNAPSHOT</revision>
|
||||
<revision>2025.09-jdk8-SNAPSHOT</revision>
|
||||
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
|
||||
<!-- 统一依赖管理 -->
|
||||
<spring.framework.version>5.3.39</spring.framework.version>
|
||||
|
@ -27,19 +27,19 @@
|
|||
<springdoc.version>1.8.0</springdoc.version>
|
||||
<knife4j.version>4.5.0</knife4j.version>
|
||||
<!-- DB 相关 -->
|
||||
<druid.version>1.2.24</druid.version>
|
||||
<druid.version>1.2.27</druid.version>
|
||||
<mybatis.version>3.5.19</mybatis.version>
|
||||
<mybatis-plus.version>3.5.12</mybatis-plus.version>
|
||||
<mybatis-plus.version>3.5.14</mybatis-plus.version>
|
||||
<mybatis-plus-join.version>1.5.4</mybatis-plus-join.version>
|
||||
<dynamic-datasource.version>4.3.1</dynamic-datasource.version>
|
||||
<easy-trans.version>3.0.6</easy-trans.version>
|
||||
<redisson.version>3.41.0</redisson.version>
|
||||
<redisson.version>3.51.0</redisson.version>
|
||||
<dm8.jdbc.version>8.1.3.140</dm8.jdbc.version>
|
||||
<kingbase.jdbc.version>8.6.0</kingbase.jdbc.version>
|
||||
<opengauss.jdbc.version>5.1.0</opengauss.jdbc.version>
|
||||
<taos.version>3.3.3</taos.version>
|
||||
<taos.version>3.7.3</taos.version>
|
||||
<!-- 消息队列 -->
|
||||
<rocketmq-spring.version>2.3.2</rocketmq-spring.version>
|
||||
<rocketmq-spring.version>2.3.4</rocketmq-spring.version>
|
||||
<!-- RPC 相关 -->
|
||||
<!-- Config 配置中心相关 -->
|
||||
<!-- Job 定时任务相关 -->
|
||||
|
@ -52,22 +52,23 @@
|
|||
<opentracing.version>0.33.0</opentracing.version>
|
||||
<!-- Test 测试相关 -->
|
||||
<podam.version>7.2.11.RELEASE</podam.version> <!-- Spring Boot 2.X 最多使用 7.2.11 版本 -->
|
||||
<jedis-mock.version>1.1.4</jedis-mock.version>
|
||||
<jedis-mock.version>1.1.11</jedis-mock.version>
|
||||
<mockito-inline.version>4.11.0</mockito-inline.version>
|
||||
<!-- Bpm 工作流相关 -->
|
||||
<flowable.version>6.8.0</flowable.version>
|
||||
<!-- 工具类相关 -->
|
||||
<anji-plus-captcha.version>1.4.0</anji-plus-captcha.version>
|
||||
<jsoup.version>1.18.1</jsoup.version>
|
||||
<lombok.version>1.18.36</lombok.version>
|
||||
<jsoup.version>1.21.2</jsoup.version>
|
||||
<lombok.version>1.18.38</lombok.version>
|
||||
<mapstruct.version>1.6.3</mapstruct.version>
|
||||
<hutool.version>5.8.35</hutool.version>
|
||||
<fastexcel.version>1.2.0</fastexcel.version>
|
||||
<hutool-5.version>5.8.40</hutool-5.version>
|
||||
<fastexcel.version>1.3.0</fastexcel.version>
|
||||
<velocity.version>2.4</velocity.version> <!-- JDK8 不能从 2.4 升级到 2.4.1,会报包不存在!!!! -->
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
<guava.version>33.4.8-jre</guava.version>
|
||||
<transmittable-thread-local.version>2.14.5</transmittable-thread-local.version>
|
||||
<commons-net.version>3.11.1</commons-net.version>
|
||||
<commons-lang3.version>3.18.0</commons-lang3.version>
|
||||
<jsch.version>0.1.55</jsch.version>
|
||||
<tika-core.version>2.9.3</tika-core.version> <!-- JDK8 不能从 2.9.3 升级到 3.X,会报 JDK8 不支持 -->
|
||||
<ip2region.version>2.7.0</ip2region.version>
|
||||
|
@ -81,9 +82,9 @@
|
|||
<awssdk.version>2.30.14</awssdk.version>
|
||||
<justauth.version>1.16.7</justauth.version>
|
||||
<justauth-starter.version>1.4.0</justauth-starter.version>
|
||||
<jimureport.version>2.1.0</jimureport.version>
|
||||
<jimubi.version>1.9.5</jimubi.version>
|
||||
<weixin-java.version>4.7.5.B</weixin-java.version>
|
||||
<jimureport.version>2.1.1</jimureport.version>
|
||||
<jimubi.version>2.1.0</jimubi.version>
|
||||
<weixin-java.version>4.7.7-20250808.182223</weixin-java.version>
|
||||
<!-- 专属于 JDK8 安全漏洞升级 -->
|
||||
<logback.version>1.2.13</logback.version> <!-- 无法使用 1.3.X 版本,启动会报错 -->
|
||||
</properties>
|
||||
|
@ -304,7 +305,7 @@
|
|||
<exclusion>
|
||||
<groupId>org.redisson</groupId>
|
||||
<!-- 使用 redisson-spring-data-27 替代,解决 Tuple NoClassDefFoundError 报错 -->
|
||||
<artifactId>redisson-spring-data-34</artifactId>
|
||||
<artifactId>redisson-spring-data-35</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
@ -545,7 +546,7 @@
|
|||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
<version>${hutool-5.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -595,6 +596,12 @@
|
|||
<version>${jsch.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version> <!-- 解决 CVE-2025-48924 漏洞 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.anji-plus</groupId>
|
||||
<artifactId>captcha-spring-boot-starter</artifactId> <!-- 验证码,一般用于登录使用 -->
|
||||
|
@ -668,6 +675,10 @@
|
|||
<groupId>com.github.jsqlparser</groupId>
|
||||
<artifactId>jsqlparser</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
|
|
@ -2,14 +2,12 @@ package cn.iocoder.yudao.framework.common.biz.system.oauth2.dto;
|
|||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "RPC 服务 - OAuth2 访问令牌的信息 Response DTO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2AccessTokenRespDTO implements Serializable {
|
||||
|
||||
@Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "tudou")
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.Arrays;
|
|||
@AllArgsConstructor
|
||||
public enum DateIntervalEnum implements ArrayValuable<Integer> {
|
||||
|
||||
HOUR(0, "小时"), // 特殊:字典里,暂时不会有这个枚举!!!因为大多数情况下,用不到这个间隔
|
||||
DAY(1, "天"),
|
||||
WEEK(2, "周"),
|
||||
MONTH(3, "月"),
|
||||
|
|
|
@ -17,6 +17,8 @@ public interface WebFilterOrderEnum {
|
|||
|
||||
int REQUEST_BODY_CACHE_FILTER = Integer.MIN_VALUE + 500;
|
||||
|
||||
int API_ENCRYPT_FILTER = REQUEST_BODY_CACHE_FILTER + 1;
|
||||
|
||||
// OrderedRequestContextFilter 默认为 -105,用于国际化上下文等等
|
||||
|
||||
int TENANT_CONTEXT_FILTER = - 104; // 需要保证在 ApiAccessLogFilter 前面
|
||||
|
|
|
@ -25,16 +25,16 @@ public class CommonResult<T> implements Serializable {
|
|||
* @see ErrorCode#getCode()
|
||||
*/
|
||||
private Integer code;
|
||||
/**
|
||||
* 返回数据
|
||||
*/
|
||||
private T data;
|
||||
/**
|
||||
* 错误提示,用户可阅读
|
||||
*
|
||||
* @see ErrorCode#getMsg() ()
|
||||
*/
|
||||
private String msg;
|
||||
/**
|
||||
* 返回数据
|
||||
*/
|
||||
private T data;
|
||||
|
||||
/**
|
||||
* 将传入的 result 对象,转换成另外一个泛型结果的对象
|
||||
|
|
|
@ -11,12 +11,12 @@ import java.util.List;
|
|||
@Data
|
||||
public final class PageResult<T> implements Serializable {
|
||||
|
||||
@Schema(description = "数据", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<T> list;
|
||||
|
||||
@Schema(description = "总量", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long total;
|
||||
|
||||
@Schema(description = "数据", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<T> list;
|
||||
|
||||
public PageResult() {
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import cn.hutool.core.lang.Assert;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
|
@ -16,8 +17,7 @@ import java.time.temporal.TemporalAdjusters;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.hutool.core.date.DatePattern.UTC_MS_WITH_XXX_OFFSET_PATTERN;
|
||||
import static cn.hutool.core.date.DatePattern.createFormatter;
|
||||
import static cn.hutool.core.date.DatePattern.*;
|
||||
|
||||
/**
|
||||
* 时间工具类,用于 {@link LocalDateTime}
|
||||
|
@ -69,17 +69,32 @@ public class LocalDateTimeUtils {
|
|||
* 创建指定时间
|
||||
*
|
||||
* @param year 年
|
||||
* @param mouth 月
|
||||
* @param month 月
|
||||
* @param day 日
|
||||
* @return 指定时间
|
||||
*/
|
||||
public static LocalDateTime buildTime(int year, int mouth, int day) {
|
||||
return LocalDateTime.of(year, mouth, day, 0, 0, 0);
|
||||
public static LocalDateTime buildTime(int year, int month, int day) {
|
||||
return LocalDateTime.of(year, month, day, 0, 0, 0);
|
||||
}
|
||||
|
||||
public static LocalDateTime[] buildBetweenTime(int year1, int mouth1, int day1,
|
||||
int year2, int mouth2, int day2) {
|
||||
return new LocalDateTime[]{buildTime(year1, mouth1, day1), buildTime(year2, mouth2, day2)};
|
||||
public static LocalDateTime[] buildBetweenTime(int year1, int month1, int day1,
|
||||
int year2, int month2, int day2) {
|
||||
return new LocalDateTime[]{buildTime(year1, month1, day1), buildTime(year2, month2, day2)};
|
||||
}
|
||||
|
||||
/**
|
||||
* 判指定断时间,是否在该时间范围内
|
||||
*
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param time 指定时间
|
||||
* @return 是否
|
||||
*/
|
||||
public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime, Timestamp time) {
|
||||
if (startTime == null || endTime == null || time == null) {
|
||||
return false;
|
||||
}
|
||||
return LocalDateTimeUtil.isIn(LocalDateTimeUtil.of(time), startTime, endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -234,6 +249,11 @@ public class LocalDateTimeUtils {
|
|||
// 2. 循环,生成时间范围
|
||||
List<LocalDateTime[]> timeRanges = new ArrayList<>();
|
||||
switch (intervalEnum) {
|
||||
case HOUR:
|
||||
while (startTime.isBefore(endTime)) {
|
||||
timeRanges.add(new LocalDateTime[]{startTime, startTime.plusHours(1).minusNanos(1)});
|
||||
startTime = startTime.plusHours(1);
|
||||
}
|
||||
case DAY:
|
||||
while (startTime.isBefore(endTime)) {
|
||||
timeRanges.add(new LocalDateTime[]{startTime, startTime.plusDays(1).minusNanos(1)});
|
||||
|
@ -297,6 +317,8 @@ public class LocalDateTimeUtils {
|
|||
|
||||
// 2. 循环,生成时间范围
|
||||
switch (intervalEnum) {
|
||||
case HOUR:
|
||||
return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATETIME_MINUTE_PATTERN);
|
||||
case DAY:
|
||||
return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATE_PATTERN);
|
||||
case WEEK:
|
||||
|
|
|
@ -49,8 +49,15 @@ public class HttpUtils {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
private String append(String base, Map<String, ?> query, boolean fragment) {
|
||||
return append(base, query, null, fragment);
|
||||
public static String removeUrlQuery(String url) {
|
||||
if (!StrUtil.contains(url, '?')) {
|
||||
return url;
|
||||
}
|
||||
UrlBuilder builder = UrlBuilder.of(url, Charset.defaultCharset());
|
||||
// 移除 query、fragment
|
||||
builder.setQuery(null);
|
||||
builder.setFragment(null);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,18 +3,23 @@ package cn.iocoder.yudao.framework.common.util.json;
|
|||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeDeserializer;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -26,13 +31,18 @@ import java.util.List;
|
|||
@Slf4j
|
||||
public class JsonUtils {
|
||||
|
||||
@Getter
|
||||
private static ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
static {
|
||||
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略 null 值
|
||||
objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化
|
||||
// 解决 LocalDateTime 的序列化
|
||||
SimpleModule simpleModule = new JavaTimeModule()
|
||||
.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
|
||||
.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
|
||||
objectMapper.registerModules(simpleModule);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,6 +109,18 @@ public class JsonUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static <T> T parseObject(byte[] text, Type type) {
|
||||
if (ArrayUtil.isEmpty(text)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.readValue(text, objectMapper.getTypeFactory().constructType(type));
|
||||
} catch (IOException e) {
|
||||
log.error("json parse err,json:{}", text, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串解析成指定类型的对象
|
||||
* 使用 {@link #parseObject(String, Class)} 时,在@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 的场景下,
|
||||
|
|
|
@ -60,4 +60,8 @@ public class ObjectUtils {
|
|||
return Arrays.asList(array).contains(obj);
|
||||
}
|
||||
|
||||
public static boolean isNotAllEmpty(Object... objs) {
|
||||
return !ObjectUtil.isAllEmpty(objs);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.framework.tenant.config;
|
||||
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.iocoder.yudao.framework.common.biz.system.tenant.TenantCommonApi;
|
||||
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
||||
import cn.iocoder.yudao.framework.redis.config.YudaoCacheProperties;
|
||||
|
@ -8,7 +9,6 @@ import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkService
|
|||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect;
|
||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor;
|
||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJobAspect;
|
||||
import cn.iocoder.yudao.framework.tenant.core.mq.rabbitmq.TenantRabbitMQInitializer;
|
||||
import cn.iocoder.yudao.framework.tenant.core.mq.redis.TenantRedisMessageInterceptor;
|
||||
import cn.iocoder.yudao.framework.tenant.core.mq.rocketmq.TenantRocketMQInitializer;
|
||||
|
@ -20,7 +20,6 @@ import cn.iocoder.yudao.framework.tenant.core.web.TenantContextWebFilter;
|
|||
import cn.iocoder.yudao.framework.tenant.core.web.TenantVisitContextInterceptor;
|
||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||
import cn.iocoder.yudao.framework.common.biz.system.tenant.TenantCommonApi;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
|
@ -46,8 +45,10 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
|
|||
import org.springframework.web.util.pattern.PathPattern;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
|
@ -93,41 +94,13 @@ public class YudaoTenantAutoConfiguration {
|
|||
// ========== WEB ==========
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter(TenantProperties tenantProperties) {
|
||||
public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter() {
|
||||
FilterRegistrationBean<TenantContextWebFilter> registrationBean = new FilterRegistrationBean<>();
|
||||
registrationBean.setFilter(new TenantContextWebFilter());
|
||||
registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER);
|
||||
addIgnoreUrls(tenantProperties);
|
||||
return registrationBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果 Controller 接口上,有 {@link TenantIgnore} 注解,那么添加到忽略的 URL 中
|
||||
*
|
||||
* @param tenantProperties 租户配置
|
||||
*/
|
||||
private void addIgnoreUrls(TenantProperties tenantProperties) {
|
||||
// 获得接口对应的 HandlerMethod 集合
|
||||
RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping)
|
||||
applicationContext.getBean("requestMappingHandlerMapping");
|
||||
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
|
||||
// 获得有 @TenantIgnore 注解的接口
|
||||
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethodMap.entrySet()) {
|
||||
HandlerMethod handlerMethod = entry.getValue();
|
||||
if (!handlerMethod.hasMethodAnnotation(TenantIgnore.class)) {
|
||||
continue;
|
||||
}
|
||||
// 添加到忽略的 URL 中
|
||||
if (entry.getKey().getPatternsCondition() != null) {
|
||||
tenantProperties.getIgnoreUrls().addAll(entry.getKey().getPatternsCondition().getPatterns());
|
||||
}
|
||||
if (entry.getKey().getPathPatternsCondition() != null) {
|
||||
tenantProperties.getIgnoreUrls().addAll(
|
||||
convertList(entry.getKey().getPathPatternsCondition().getPatterns(), PathPattern::getPatternString));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TenantVisitContextInterceptor tenantVisitContextInterceptor(TenantProperties tenantProperties,
|
||||
SecurityFrameworkService securityFrameworkService) {
|
||||
|
@ -155,18 +128,40 @@ public class YudaoTenantAutoConfiguration {
|
|||
GlobalExceptionHandler globalExceptionHandler,
|
||||
TenantFrameworkService tenantFrameworkService) {
|
||||
FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>();
|
||||
registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, webProperties,
|
||||
registrationBean.setFilter(new TenantSecurityWebFilter(webProperties, tenantProperties, getTenantIgnoreUrls(),
|
||||
globalExceptionHandler, tenantFrameworkService));
|
||||
registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER);
|
||||
return registrationBean;
|
||||
}
|
||||
|
||||
// ========== Job ==========
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = "com.xxl.job.core.handler.annotation.XxlJob")
|
||||
public TenantJobAspect tenantJobAspect(TenantFrameworkService tenantFrameworkService) {
|
||||
return new TenantJobAspect(tenantFrameworkService);
|
||||
/**
|
||||
* 如果 Controller 接口上,有 {@link TenantIgnore} 注解,则添加到忽略租户的 URL 集合中
|
||||
*
|
||||
* @return 忽略租户的 URL 集合
|
||||
*/
|
||||
private Set<String> getTenantIgnoreUrls() {
|
||||
Set<String> ignoreUrls = new HashSet<>();
|
||||
// 获得接口对应的 HandlerMethod 集合
|
||||
RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping)
|
||||
applicationContext.getBean("requestMappingHandlerMapping");
|
||||
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
|
||||
// 获得有 @TenantIgnore 注解的接口
|
||||
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethodMap.entrySet()) {
|
||||
HandlerMethod handlerMethod = entry.getValue();
|
||||
if (!handlerMethod.hasMethodAnnotation(TenantIgnore.class) // 方法级
|
||||
&& !handlerMethod.getBeanType().isAnnotationPresent(TenantIgnore.class)) { // 接口级
|
||||
continue;
|
||||
}
|
||||
// 添加到忽略的 URL 中
|
||||
if (entry.getKey().getPatternsCondition() != null) {
|
||||
ignoreUrls.addAll(entry.getKey().getPatternsCondition().getPatterns());
|
||||
}
|
||||
if (entry.getKey().getPathPatternsCondition() != null) {
|
||||
ignoreUrls.addAll(
|
||||
convertList(entry.getKey().getPathPatternsCondition().getPatterns(), PathPattern::getPatternString));
|
||||
}
|
||||
}
|
||||
return ignoreUrls;
|
||||
}
|
||||
|
||||
// ========== MQ ==========
|
||||
|
|
|
@ -75,7 +75,7 @@ public class TenantDatabaseInterceptor implements TenantLineHandler {
|
|||
if (TenantBaseDO.class.isAssignableFrom(tableInfo.getEntityType())) {
|
||||
return false;
|
||||
}
|
||||
// 如果添加了 @TenantIgnore 注解,显然也不忽略租户
|
||||
// 如果添加了 @TenantIgnore 注解,则忽略租户
|
||||
TenantIgnore tenantIgnore = tableInfo.getEntityType().getAnnotation(TenantIgnore.class);
|
||||
return tenantIgnore != null;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
|||
public class TenantRabbitMQInitializer implements BeanPostProcessor {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("PatternVariableCanBeUsed")
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof RabbitTemplate) {
|
||||
RabbitTemplate rabbitTemplate = (RabbitTemplate) bean;
|
||||
|
@ -20,4 +21,4 @@ public class TenantRabbitMQInitializer implements BeanPostProcessor {
|
|||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
|||
public class TenantRocketMQInitializer implements BeanPostProcessor {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("PatternVariableCanBeUsed")
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof DefaultRocketMQListenerContainer) {
|
||||
DefaultRocketMQListenerContainer container = (DefaultRocketMQListenerContainer) bean;
|
||||
|
@ -50,4 +51,4 @@ public class TenantRocketMQInitializer implements BeanPostProcessor {
|
|||
consumerImpl.registerConsumeMessageHook(new TenantRocketMQConsumeMessageHook());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 多租户 Security Web 过滤器
|
||||
|
@ -35,17 +36,26 @@ public class TenantSecurityWebFilter extends ApiRequestFilter {
|
|||
|
||||
private final TenantProperties tenantProperties;
|
||||
|
||||
/**
|
||||
* 允许忽略租户的 URL 列表
|
||||
*
|
||||
* 目的:解决 <a href="https://gitee.com/zhijiantianya/yudao-cloud/issues/ICUQL9">修改配置会导致 @TenantIgnore Controller 接口过滤失效</>
|
||||
*/
|
||||
private final Set<String> ignoreUrls;
|
||||
|
||||
private final AntPathMatcher pathMatcher;
|
||||
|
||||
private final GlobalExceptionHandler globalExceptionHandler;
|
||||
private final TenantFrameworkService tenantFrameworkService;
|
||||
|
||||
public TenantSecurityWebFilter(TenantProperties tenantProperties,
|
||||
WebProperties webProperties,
|
||||
public TenantSecurityWebFilter(WebProperties webProperties,
|
||||
TenantProperties tenantProperties,
|
||||
Set<String> ignoreUrls,
|
||||
GlobalExceptionHandler globalExceptionHandler,
|
||||
TenantFrameworkService tenantFrameworkService) {
|
||||
super(webProperties);
|
||||
this.tenantProperties = tenantProperties;
|
||||
this.ignoreUrls = ignoreUrls;
|
||||
this.pathMatcher = new AntPathMatcher();
|
||||
this.globalExceptionHandler = globalExceptionHandler;
|
||||
this.tenantFrameworkService = tenantFrameworkService;
|
||||
|
@ -62,7 +72,7 @@ public class TenantSecurityWebFilter extends ApiRequestFilter {
|
|||
if (tenantId == null) {
|
||||
tenantId = user.getTenantId();
|
||||
TenantContextHolder.setTenantId(tenantId);
|
||||
// 如果传递了租户编号,则进行比对租户编号,避免越权问题
|
||||
// 如果传递了租户编号,则进行比对租户编号,避免越权问题
|
||||
} else if (!Objects.equals(user.getTenantId(), TenantContextHolder.getTenantId())) {
|
||||
log.error("[doFilterInternal][租户({}) User({}/{}) 越权访问租户({}) URL({}/{})]",
|
||||
user.getTenantId(), user.getId(), user.getUserType(),
|
||||
|
@ -101,13 +111,20 @@ public class TenantSecurityWebFilter extends ApiRequestFilter {
|
|||
}
|
||||
|
||||
private boolean isIgnoreUrl(HttpServletRequest request) {
|
||||
String apiUri = request.getRequestURI().substring(request.getContextPath().length());
|
||||
// 快速匹配,保证性能
|
||||
if (CollUtil.contains(tenantProperties.getIgnoreUrls(), request.getRequestURI())) {
|
||||
if (CollUtil.contains(tenantProperties.getIgnoreUrls(), apiUri)
|
||||
|| CollUtil.contains(ignoreUrls, apiUri)) {
|
||||
return true;
|
||||
}
|
||||
// 逐个 Ant 路径匹配
|
||||
for (String url : tenantProperties.getIgnoreUrls()) {
|
||||
if (pathMatcher.match(url, request.getRequestURI())) {
|
||||
if (pathMatcher.match(url, apiUri)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (String url : ignoreUrls) {
|
||||
if (pathMatcher.match(url, apiUri)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,7 +96,6 @@ public class EnvLoadBalancerClient implements ReactorServiceInstanceLoadBalancer
|
|||
List<ServiceInstance> chooseInstances = CollectionUtils.filterList(instances, instance -> StrUtil.isEmpty(EnvUtils.getTag(instance)));
|
||||
// 【重要】补充说明:如果希望在 chooseInstances 为空时,不允许打到有 tag 的实例,可以取消注释下面的代码
|
||||
if (CollUtil.isEmpty(chooseInstances)) {
|
||||
log.warn("[getInstanceResponseWithoutTag][serviceId({}) 没有不带 tag 的服务实例列表,直接使用所有服务实例列表]", serviceId);
|
||||
chooseInstances = instances;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ public class YudaoAsyncAutoConfiguration {
|
|||
return new BeanPostProcessor() {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("PatternVariableCanBeUsed")
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
// 处理 ThreadPoolTaskExecutor
|
||||
if (bean instanceof ThreadPoolTaskExecutor) {
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
package cn.iocoder.yudao.framework.tracer.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
|
||||
import cn.iocoder.yudao.framework.tracer.core.aop.BizTraceAspect;
|
||||
import cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter;
|
||||
import io.opentracing.Tracer;
|
||||
import io.opentracing.util.GlobalTracer;
|
||||
import org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
|
@ -20,31 +16,28 @@ import org.springframework.context.annotation.Bean;
|
|||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnClass(name = {
|
||||
"org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer",
|
||||
"io.opentracing.Tracer"
|
||||
"org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer", // 来自 apm-toolkit-opentracing.jar
|
||||
// "io.opentracing.Tracer", // 来自 opentracing-api.jar
|
||||
"javax.servlet.Filter"
|
||||
})
|
||||
@EnableConfigurationProperties(TracerProperties.class)
|
||||
@ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true)
|
||||
public class YudaoTracerAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public TracerProperties bizTracerProperties() {
|
||||
return new TracerProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BizTraceAspect bizTracingAop() {
|
||||
return new BizTraceAspect(tracer());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Tracer tracer() {
|
||||
// 创建 SkywalkingTracer 对象
|
||||
SkywalkingTracer tracer = new SkywalkingTracer();
|
||||
// 设置为 GlobalTracer 的追踪器
|
||||
GlobalTracer.registerIfAbsent(tracer);
|
||||
return tracer;
|
||||
}
|
||||
// TODO @芋艿:skywalking 不兼容最新的 opentracing 版本。同时,opentracing 也停止了维护,尬住了!后续换 opentelemetry 即可!
|
||||
// @Bean
|
||||
// public BizTraceAspect bizTracingAop() {
|
||||
// return new BizTraceAspect(tracer());
|
||||
// }
|
||||
//
|
||||
// @Bean
|
||||
// public Tracer tracer() {
|
||||
// // 创建 SkywalkingTracer 对象
|
||||
// SkywalkingTracer tracer = new SkywalkingTracer();
|
||||
// // 设置为 GlobalTracer 的追踪器
|
||||
// GlobalTracer.registerIfAbsent(tracer);
|
||||
// return tracer;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 创建 TraceFilter 过滤器,响应 header 设置 traceId
|
||||
|
|
|
@ -69,9 +69,8 @@ public class YudaoRedisMQConsumerAutoConfiguration {
|
|||
@ConditionalOnBean(AbstractRedisStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听
|
||||
public RedisPendingMessageResendJob redisPendingMessageResendJob(List<AbstractRedisStreamMessageListener<?>> listeners,
|
||||
RedisMQTemplate redisTemplate,
|
||||
@Value("${spring.application.name}") String groupName,
|
||||
RedissonClient redissonClient) {
|
||||
return new RedisPendingMessageResendJob(listeners, redisTemplate, groupName, redissonClient);
|
||||
return new RedisPendingMessageResendJob(listeners, redisTemplate, redissonClient);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,14 +140,14 @@ public class YudaoRedisMQConsumerAutoConfiguration {
|
|||
*
|
||||
* @return 消费者名字
|
||||
*/
|
||||
private static String buildConsumerName() {
|
||||
public static String buildConsumerName() {
|
||||
return String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验 Redis 版本号,是否满足最低的版本号要求!
|
||||
*/
|
||||
private static void checkRedisVersion(RedisTemplate<String, ?> redisTemplate) {
|
||||
public static void checkRedisVersion(RedisTemplate<String, ?> redisTemplate) {
|
||||
// 获得 Redis 版本
|
||||
Properties info = redisTemplate.execute((RedisCallback<Properties>) RedisServerCommands::info);
|
||||
String version = MapUtil.getStr(info, "redis_version");
|
||||
|
|
|
@ -35,7 +35,6 @@ public class RedisPendingMessageResendJob {
|
|||
|
||||
private final List<AbstractRedisStreamMessageListener<?>> listeners;
|
||||
private final RedisMQTemplate redisTemplate;
|
||||
private final String groupName;
|
||||
private final RedissonClient redissonClient;
|
||||
|
||||
/**
|
||||
|
@ -64,13 +63,13 @@ public class RedisPendingMessageResendJob {
|
|||
private void execute() {
|
||||
StreamOperations<String, Object, Object> ops = redisTemplate.getRedisTemplate().opsForStream();
|
||||
listeners.forEach(listener -> {
|
||||
PendingMessagesSummary pendingMessagesSummary = Objects.requireNonNull(ops.pending(listener.getStreamKey(), groupName));
|
||||
PendingMessagesSummary pendingMessagesSummary = Objects.requireNonNull(ops.pending(listener.getStreamKey(), listener.getGroup()));
|
||||
// 每个消费者的 pending 队列消息数量
|
||||
Map<String, Long> pendingMessagesPerConsumer = pendingMessagesSummary.getPendingMessagesPerConsumer();
|
||||
pendingMessagesPerConsumer.forEach((consumerName, pendingMessageCount) -> {
|
||||
log.info("[processPendingMessage][消费者({}) 消息数量({})]", consumerName, pendingMessageCount);
|
||||
// 每个消费者的 pending消息的详情信息
|
||||
PendingMessages pendingMessages = ops.pending(listener.getStreamKey(), Consumer.from(groupName, consumerName), Range.unbounded(), pendingMessageCount);
|
||||
PendingMessages pendingMessages = ops.pending(listener.getStreamKey(), Consumer.from(listener.getGroup(), consumerName), Range.unbounded(), pendingMessageCount);
|
||||
if (pendingMessages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -91,7 +90,7 @@ public class RedisPendingMessageResendJob {
|
|||
.ofObject(records.get(0).getValue()) // 设置内容
|
||||
.withStreamKey(listener.getStreamKey()));
|
||||
// ack 消息消费完成
|
||||
redisTemplate.getRedisTemplate().opsForStream().acknowledge(groupName, records.get(0));
|
||||
redisTemplate.getRedisTemplate().opsForStream().acknowledge(listener.getGroup(), records.get(0));
|
||||
log.info("[processPendingMessage][消息({})重新投递成功]", records.get(0).getId());
|
||||
});
|
||||
});
|
||||
|
|
|
@ -53,6 +53,12 @@ public abstract class AbstractRedisStreamMessageListener<T extends AbstractRedis
|
|||
this.streamKey = messageType.getDeclaredConstructor().newInstance().getStreamKey();
|
||||
}
|
||||
|
||||
protected AbstractRedisStreamMessageListener(String streamKey, String group) {
|
||||
this.messageType = null;
|
||||
this.streamKey = streamKey;
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(ObjectRecord<String, String> message) {
|
||||
// 消费消息
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
package cn.iocoder.yudao.framework.mybatis.config;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.handler.DefaultDBFieldHandler;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
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.handlers.JacksonTypeHandler;
|
||||
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 com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
|
@ -18,6 +22,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
@ -42,6 +47,8 @@ public class YudaoMybatisAutoConfiguration {
|
|||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
|
||||
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 分页插件
|
||||
// ↓↓↓ 按需开启,可能会影响到 updateBatch 的地方:例如说文件配置管理 ↓↓↓
|
||||
// mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); // 拦截没有指定条件的 update 和 delete 语句
|
||||
return mybatisPlusInterceptor;
|
||||
}
|
||||
|
||||
|
@ -73,4 +80,15 @@ public class YudaoMybatisAutoConfiguration {
|
|||
throw new IllegalArgumentException(StrUtil.format("DbType{} 找不到合适的 IKeyGenerator 实现类", dbType));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JacksonTypeHandler jacksonTypeHandler(List<ObjectMapper> objectMappers) {
|
||||
// 特殊:设置 JacksonTypeHandler 的 ObjectMapper!
|
||||
ObjectMapper objectMapper = CollUtil.getFirst(objectMappers);
|
||||
if (objectMapper == null) {
|
||||
objectMapper = JsonUtils.getObjectMapper();
|
||||
}
|
||||
JacksonTypeHandler.setObjectMapper(objectMapper);
|
||||
return new JacksonTypeHandler(Object.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fhs.core.trans.vo.TransPojo;
|
||||
import lombok.Data;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
@ -38,14 +37,14 @@ public abstract class BaseDO implements Serializable, TransPojo {
|
|||
*
|
||||
* 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT, jdbcType = JdbcType.VARCHAR)
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String creator;
|
||||
/**
|
||||
* 更新者,目前使用 SysUser 的 id 编号
|
||||
*
|
||||
* 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.VARCHAR)
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private String updater;
|
||||
/**
|
||||
* 是否删除
|
||||
|
|
|
@ -2,7 +2,6 @@ package cn.iocoder.yudao.framework.mybatis.core.handler;
|
|||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
|
||||
|
@ -19,6 +18,7 @@ import java.util.Objects;
|
|||
public class DefaultDBFieldHandler implements MetaObjectHandler {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("PatternVariableCanBeUsed")
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) {
|
||||
BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();
|
||||
|
|
|
@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.pojo.SortingField;
|
|||
import cn.iocoder.yudao.framework.mybatis.core.enums.DbTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
|
@ -47,16 +48,36 @@ public class MyBatisUtils {
|
|||
return page;
|
||||
}
|
||||
|
||||
@SuppressWarnings("PatternVariableCanBeUsed")
|
||||
public static <T> void addOrder(Wrapper<T> wrapper, Collection<SortingField> sortingFields) {
|
||||
if (CollUtil.isEmpty(sortingFields)) {
|
||||
return;
|
||||
}
|
||||
QueryWrapper<T> query = (QueryWrapper<T>) wrapper;
|
||||
for (SortingField sortingField : sortingFields) {
|
||||
query.orderBy(true,
|
||||
SortingField.ORDER_ASC.equals(sortingField.getOrder()),
|
||||
StrUtil.toUnderlineCase(sortingField.getField()));
|
||||
if (wrapper instanceof QueryWrapper) {
|
||||
QueryWrapper<T> query = (QueryWrapper<T>) wrapper;
|
||||
for (SortingField sortingField : sortingFields) {
|
||||
query.orderBy(true,
|
||||
SortingField.ORDER_ASC.equals(sortingField.getOrder()),
|
||||
StrUtil.toUnderlineCase(sortingField.getField()));
|
||||
}
|
||||
} else if (wrapper instanceof LambdaQueryWrapper) {
|
||||
// LambdaQueryWrapper 不直接支持字符串字段排序,使用 last 方法拼接 ORDER BY
|
||||
LambdaQueryWrapper<T> lambdaQuery = (LambdaQueryWrapper<T>) wrapper;
|
||||
StringBuilder orderBy = new StringBuilder();
|
||||
for (SortingField sortingField : sortingFields) {
|
||||
if (StrUtil.isNotEmpty(orderBy)) {
|
||||
orderBy.append(", ");
|
||||
}
|
||||
orderBy.append(StrUtil.toUnderlineCase(sortingField.getField()))
|
||||
.append(" ")
|
||||
.append(SortingField.ORDER_ASC.equals(sortingField.getOrder()) ? "ASC" : "DESC");
|
||||
}
|
||||
lambdaQuery.last("ORDER BY " + orderBy);
|
||||
// 另外个思路:https://blog.csdn.net/m0_59084856/article/details/138450913
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported wrapper type: " + wrapper.getClass().getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||
import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
|
||||
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
|
@ -18,7 +18,7 @@ public class DefaultIdempotentKeyResolver implements IdempotentKeyResolver {
|
|||
@Override
|
||||
public String resolver(JoinPoint joinPoint, Idempotent idempotent) {
|
||||
String methodName = joinPoint.getSignature().toString();
|
||||
String argsStr = StrUtil.join(",", joinPoint.getArgs());
|
||||
String argsStr = StrUtils.joinMethodArgs(joinPoint);
|
||||
return SecureUtil.md5(methodName + argsStr);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||
import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
|
||||
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
|
@ -19,7 +19,7 @@ public class UserIdempotentKeyResolver implements IdempotentKeyResolver {
|
|||
@Override
|
||||
public String resolver(JoinPoint joinPoint, Idempotent idempotent) {
|
||||
String methodName = joinPoint.getSignature().toString();
|
||||
String argsStr = StrUtil.join(",", joinPoint.getArgs());
|
||||
String argsStr = StrUtils.joinMethodArgs(joinPoint);
|
||||
Long userId = WebFrameworkUtils.getLoginUserId();
|
||||
Integer userType = WebFrameworkUtils.getLoginUserType();
|
||||
return SecureUtil.md5(methodName + argsStr + userId + userType);
|
||||
|
|
|
@ -39,7 +39,7 @@ public class RateLimiterAspect {
|
|||
|
||||
@Before("@annotation(rateLimiter)")
|
||||
public void beforePointCut(JoinPoint joinPoint, RateLimiter rateLimiter) {
|
||||
// 获得 IdempotentKeyResolver 对象
|
||||
// 获得 RateLimiterKeyResolver 对象
|
||||
RateLimiterKeyResolver keyResolver = keyResolvers.get(rateLimiter.keyResolver());
|
||||
Assert.notNull(keyResolver, "找不到对应的 RateLimiterKeyResolver");
|
||||
// 解析 Key
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
|
||||
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
|
@ -19,7 +19,7 @@ public class ClientIpRateLimiterKeyResolver implements RateLimiterKeyResolver {
|
|||
@Override
|
||||
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
|
||||
String methodName = joinPoint.getSignature().toString();
|
||||
String argsStr = StrUtil.join(",", joinPoint.getArgs());
|
||||
String argsStr = StrUtils.joinMethodArgs(joinPoint);
|
||||
String clientIp = ServletUtils.getClientIP();
|
||||
return SecureUtil.md5(methodName + argsStr + clientIp);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
|
||||
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
|
@ -18,7 +18,7 @@ public class DefaultRateLimiterKeyResolver implements RateLimiterKeyResolver {
|
|||
@Override
|
||||
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
|
||||
String methodName = joinPoint.getSignature().toString();
|
||||
String argsStr = StrUtil.join(",", joinPoint.getArgs());
|
||||
String argsStr = StrUtils.joinMethodArgs(joinPoint);
|
||||
return SecureUtil.md5(methodName + argsStr);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.system.SystemUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
|
||||
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
|
@ -19,7 +19,7 @@ public class ServerNodeRateLimiterKeyResolver implements RateLimiterKeyResolver
|
|||
@Override
|
||||
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
|
||||
String methodName = joinPoint.getSignature().toString();
|
||||
String argsStr = StrUtil.join(",", joinPoint.getArgs());
|
||||
String argsStr = StrUtils.joinMethodArgs(joinPoint);
|
||||
String serverNode = String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());
|
||||
return SecureUtil.md5(methodName + argsStr + serverNode);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
|
||||
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
|
@ -19,7 +19,7 @@ public class UserRateLimiterKeyResolver implements RateLimiterKeyResolver {
|
|||
@Override
|
||||
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
|
||||
String methodName = joinPoint.getSignature().toString();
|
||||
String argsStr = StrUtil.join(",", joinPoint.getArgs());
|
||||
String argsStr = StrUtils.joinMethodArgs(joinPoint);
|
||||
Long userId = WebFrameworkUtils.getLoginUserId();
|
||||
Integer userType = WebFrameworkUtils.getLoginUserType();
|
||||
return SecureUtil.md5(methodName + argsStr + userId + userType);
|
||||
|
|
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.ratelimiter.core.redis;
|
|||
import lombok.AllArgsConstructor;
|
||||
import org.redisson.api.*;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -40,11 +41,13 @@ public class RateLimiterRedisDAO {
|
|||
String redisKey = formatKey(key);
|
||||
RRateLimiter rateLimiter = redissonClient.getRateLimiter(redisKey);
|
||||
long rateInterval = timeUnit.toSeconds(time);
|
||||
Duration duration = Duration.ofSeconds(rateInterval);
|
||||
// 1. 如果不存在,设置 rate 速率
|
||||
RateLimiterConfig config = rateLimiter.getConfig();
|
||||
if (config == null) {
|
||||
rateLimiter.trySetRate(RateType.OVERALL, count, rateInterval, RateIntervalUnit.SECONDS);
|
||||
rateLimiter.expire(rateInterval, TimeUnit.SECONDS); // 原因参见 https://t.zsxq.com/lcR0W
|
||||
rateLimiter.trySetRate(RateType.OVERALL, count, duration);
|
||||
// 原因参见 https://t.zsxq.com/lcR0W
|
||||
rateLimiter.expire(duration);
|
||||
return rateLimiter;
|
||||
}
|
||||
// 2. 如果存在,并且配置相同,则直接返回
|
||||
|
@ -54,8 +57,9 @@ public class RateLimiterRedisDAO {
|
|||
return rateLimiter;
|
||||
}
|
||||
// 3. 如果存在,并且配置不同,则进行新建
|
||||
rateLimiter.setRate(RateType.OVERALL, count, rateInterval, RateIntervalUnit.SECONDS);
|
||||
rateLimiter.expire(rateInterval, TimeUnit.SECONDS); // 原因参见 https://t.zsxq.com/lcR0W
|
||||
rateLimiter.setRate(RateType.OVERALL, count, duration);
|
||||
// 原因参见 https://t.zsxq.com/lcR0W
|
||||
rateLimiter.expire(duration);
|
||||
return rateLimiter;
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,8 @@ public class YudaoWebSecurityConfigurerAdapter {
|
|||
// 获得有 @PermitAll 注解的接口
|
||||
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethodMap.entrySet()) {
|
||||
HandlerMethod handlerMethod = entry.getValue();
|
||||
if (!handlerMethod.hasMethodAnnotation(PermitAll.class)) {
|
||||
if (!handlerMethod.hasMethodAnnotation(PermitAll.class) // 方法级
|
||||
&& !handlerMethod.getBeanType().isAnnotationPresent(PermitAll.class)) { // 接口级
|
||||
continue;
|
||||
}
|
||||
Set<String> urls = new HashSet<>();
|
||||
|
|
|
@ -61,7 +61,13 @@
|
|||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- xss -->
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<scope>provided</scope> <!-- 设置为 provided,只有工具类需要使用到 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package cn.iocoder.yudao.framework.encrypt.config;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* HTTP API 加解密配置
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "yudao.api-encrypt")
|
||||
@Validated
|
||||
@Data
|
||||
public class ApiEncryptProperties {
|
||||
|
||||
/**
|
||||
* 是否开启
|
||||
*/
|
||||
@NotNull(message = "是否开启不能为空")
|
||||
private Boolean enable;
|
||||
|
||||
/**
|
||||
* 请求头(响应头)名称
|
||||
*
|
||||
* 1. 如果该请求头非空,则表示请求参数已被「前端」加密,「后端」需要解密
|
||||
* 2. 如果该响应头非空,则表示响应结果已被「后端」加密,「前端」需要解密
|
||||
*/
|
||||
@NotEmpty(message = "请求头(响应头)名称不能为空")
|
||||
private String header = "X-Api-Encrypt";
|
||||
|
||||
/**
|
||||
* 对称加密算法,用于请求/响应的加解密
|
||||
*
|
||||
* 目前支持
|
||||
* 【对称加密】:
|
||||
* 1. {@link cn.hutool.crypto.symmetric.SymmetricAlgorithm#AES}
|
||||
* 2. {@link cn.hutool.crypto.symmetric.SM4#ALGORITHM_NAME} (需要自己二次开发,成本低)
|
||||
* 【非对称加密】
|
||||
* 1. {@link cn.hutool.crypto.asymmetric.AsymmetricAlgorithm#RSA}
|
||||
* 2. {@link cn.hutool.crypto.asymmetric.SM2} (需要自己二次开发,成本低)
|
||||
*
|
||||
* @see <a href="https://help.aliyun.com/zh/ssl-certificate/what-are-a-public-key-and-a-private-key">什么是公钥和私钥?</a>
|
||||
*/
|
||||
@NotEmpty(message = "对称加密算法不能为空")
|
||||
private String algorithm;
|
||||
|
||||
/**
|
||||
* 请求的解密密钥
|
||||
*
|
||||
* 注意:
|
||||
* 1. 如果是【对称加密】时,它「后端」对应的是“密钥”。对应的,「前端」也对应的也是“密钥”。
|
||||
* 2. 如果是【非对称加密】时,它「后端」对应的是“私钥”。对应的,「前端」对应的是“公钥”。(重要!!!)
|
||||
*/
|
||||
@NotEmpty(message = "请求的解密密钥不能为空")
|
||||
private String requestKey;
|
||||
|
||||
/**
|
||||
* 响应的加密密钥
|
||||
*
|
||||
* 注意:
|
||||
* 1. 如果是【对称加密】时,它「后端」对应的是“密钥”。对应的,「前端」也对应的也是“密钥”。
|
||||
* 2. 如果是【非对称加密】时,它「后端」对应的是“公钥”。对应的,「前端」对应的是“私钥”。(重要!!!)
|
||||
*/
|
||||
@NotEmpty(message = "响应的加密密钥不能为空")
|
||||
private String responseKey;
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package cn.iocoder.yudao.framework.encrypt.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
|
||||
import cn.iocoder.yudao.framework.encrypt.core.filter.ApiEncryptFilter;
|
||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
import static cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration.createFilterBean;
|
||||
|
||||
@AutoConfiguration
|
||||
@Slf4j
|
||||
@EnableConfigurationProperties(ApiEncryptProperties.class)
|
||||
@ConditionalOnProperty(prefix = "yudao.api-encrypt", name = "enable", havingValue = "true")
|
||||
public class YudaoApiEncryptAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<ApiEncryptFilter> apiEncryptFilter(WebProperties webProperties,
|
||||
ApiEncryptProperties apiEncryptProperties,
|
||||
RequestMappingHandlerMapping requestMappingHandlerMapping,
|
||||
GlobalExceptionHandler globalExceptionHandler) {
|
||||
ApiEncryptFilter filter = new ApiEncryptFilter(webProperties, apiEncryptProperties,
|
||||
requestMappingHandlerMapping, globalExceptionHandler);
|
||||
return createFilterBean(filter, WebFilterOrderEnum.API_ENCRYPT_FILTER);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package cn.iocoder.yudao.framework.encrypt.core.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* HTTP API 加解密注解
|
||||
*/
|
||||
@Documented
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ApiEncrypt {
|
||||
|
||||
/**
|
||||
* 是否对请求参数进行解密,默认 true
|
||||
*/
|
||||
boolean request() default true;
|
||||
|
||||
/**
|
||||
* 是否对响应结果进行加密,默认 true
|
||||
*/
|
||||
boolean response() default true;
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package cn.iocoder.yudao.framework.encrypt.core.filter;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.asymmetric.AsymmetricDecryptor;
|
||||
import cn.hutool.crypto.asymmetric.KeyType;
|
||||
import cn.hutool.crypto.symmetric.SymmetricDecryptor;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* 解密请求 {@link HttpServletRequestWrapper} 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class ApiDecryptRequestWrapper extends HttpServletRequestWrapper {
|
||||
|
||||
private final byte[] body;
|
||||
|
||||
public ApiDecryptRequestWrapper(HttpServletRequest request,
|
||||
SymmetricDecryptor symmetricDecryptor,
|
||||
AsymmetricDecryptor asymmetricDecryptor) throws IOException {
|
||||
super(request);
|
||||
// 读取 body,允许 HEX、BASE64 传输
|
||||
String requestBody = StrUtil.utf8Str(
|
||||
IoUtil.readBytes(request.getInputStream(), false));
|
||||
|
||||
// 解密 body
|
||||
body = symmetricDecryptor != null ? symmetricDecryptor.decrypt(requestBody)
|
||||
: asymmetricDecryptor.decrypt(requestBody, KeyType.PrivateKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() {
|
||||
return new BufferedReader(new InputStreamReader(this.getInputStream()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentLength() {
|
||||
return body.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getContentLengthLong() {
|
||||
return body.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() {
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(body);
|
||||
return new ServletInputStream() {
|
||||
|
||||
@Override
|
||||
public int read() {
|
||||
return stream.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() {
|
||||
return body.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener readListener) {
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
package cn.iocoder.yudao.framework.encrypt.core.filter;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.asymmetric.AsymmetricDecryptor;
|
||||
import cn.hutool.crypto.asymmetric.AsymmetricEncryptor;
|
||||
import cn.hutool.crypto.symmetric.SymmetricDecryptor;
|
||||
import cn.hutool.crypto.symmetric.SymmetricEncryptor;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.encrypt.config.ApiEncryptProperties;
|
||||
import cn.iocoder.yudao.framework.encrypt.core.annotation.ApiEncrypt;
|
||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||
import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter;
|
||||
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
|
||||
|
||||
/**
|
||||
* API 加密过滤器,处理 {@link ApiEncrypt} 注解。
|
||||
*
|
||||
* 1. 解密请求参数
|
||||
* 2. 加密响应结果
|
||||
*
|
||||
* 疑问:为什么不使用 SpringMVC 的 RequestBodyAdvice 或 ResponseBodyAdvice 机制呢?
|
||||
* 回答:考虑到项目中会记录访问日志、异常日志,以及 HTTP API 签名等场景,最好是全局级、且提前做解析!!!
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Slf4j
|
||||
public class ApiEncryptFilter extends ApiRequestFilter {
|
||||
|
||||
private final ApiEncryptProperties apiEncryptProperties;
|
||||
|
||||
private final RequestMappingHandlerMapping requestMappingHandlerMapping;
|
||||
|
||||
private final GlobalExceptionHandler globalExceptionHandler;
|
||||
|
||||
private final SymmetricDecryptor requestSymmetricDecryptor;
|
||||
private final AsymmetricDecryptor requestAsymmetricDecryptor;
|
||||
|
||||
private final SymmetricEncryptor responseSymmetricEncryptor;
|
||||
private final AsymmetricEncryptor responseAsymmetricEncryptor;
|
||||
|
||||
public ApiEncryptFilter(WebProperties webProperties,
|
||||
ApiEncryptProperties apiEncryptProperties,
|
||||
RequestMappingHandlerMapping requestMappingHandlerMapping,
|
||||
GlobalExceptionHandler globalExceptionHandler) {
|
||||
super(webProperties);
|
||||
this.apiEncryptProperties = apiEncryptProperties;
|
||||
this.requestMappingHandlerMapping = requestMappingHandlerMapping;
|
||||
this.globalExceptionHandler = globalExceptionHandler;
|
||||
if (StrUtil.equalsIgnoreCase(apiEncryptProperties.getAlgorithm(), "AES")) {
|
||||
this.requestSymmetricDecryptor = SecureUtil.aes(StrUtil.utf8Bytes(apiEncryptProperties.getRequestKey()));
|
||||
this.requestAsymmetricDecryptor = null;
|
||||
this.responseSymmetricEncryptor = SecureUtil.aes(StrUtil.utf8Bytes(apiEncryptProperties.getResponseKey()));
|
||||
this.responseAsymmetricEncryptor = null;
|
||||
} else if (StrUtil.equalsIgnoreCase(apiEncryptProperties.getAlgorithm(), "RSA")) {
|
||||
this.requestSymmetricDecryptor = null;
|
||||
this.requestAsymmetricDecryptor = SecureUtil.rsa(apiEncryptProperties.getRequestKey(), null);
|
||||
this.responseSymmetricEncryptor = null;
|
||||
this.responseAsymmetricEncryptor = SecureUtil.rsa(null, apiEncryptProperties.getResponseKey());
|
||||
} else {
|
||||
// 补充说明:如果要支持 SM2、SM4 等算法,可在此处增加对应实例的创建,并添加相应的 Maven 依赖即可。
|
||||
throw new IllegalArgumentException("不支持的加密算法:" + apiEncryptProperties.getAlgorithm());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullableProblems")
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws ServletException, IOException {
|
||||
// 获取 @ApiEncrypt 注解
|
||||
ApiEncrypt apiEncrypt = getApiEncrypt(request);
|
||||
boolean requestEnable = apiEncrypt != null && apiEncrypt.request();
|
||||
boolean responseEnable = apiEncrypt != null && apiEncrypt.response();
|
||||
String encryptHeader = request.getHeader(apiEncryptProperties.getHeader());
|
||||
if (!requestEnable && !responseEnable && StrUtil.isBlank(encryptHeader)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 解密请求
|
||||
if (ObjectUtils.equalsAny(HttpMethod.valueOf(request.getMethod()),
|
||||
HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE)) {
|
||||
try {
|
||||
if (StrUtil.isNotBlank(encryptHeader)) {
|
||||
request = new ApiDecryptRequestWrapper(request,
|
||||
requestSymmetricDecryptor, requestAsymmetricDecryptor);
|
||||
} else if (requestEnable) {
|
||||
throw invalidParamException("请求未包含加密标头,请检查是否正确配置了加密标头");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex);
|
||||
ServletUtils.writeJSON(response, result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 执行过滤器链
|
||||
if (responseEnable) {
|
||||
// 特殊:仅包装,最后执行。目的:Response 内容可以被重复读取!!!
|
||||
response = new ApiEncryptResponseWrapper(response);
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
|
||||
// 3. 加密响应(真正执行)
|
||||
if (responseEnable) {
|
||||
((ApiEncryptResponseWrapper) response).encrypt(apiEncryptProperties,
|
||||
responseSymmetricEncryptor, responseAsymmetricEncryptor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 @ApiEncrypt 注解
|
||||
*
|
||||
* @param request 请求
|
||||
*/
|
||||
@SuppressWarnings("PatternVariableCanBeUsed")
|
||||
private ApiEncrypt getApiEncrypt(HttpServletRequest request) {
|
||||
try {
|
||||
// 特殊:兼容 SpringBoot 2.X 版本会报错的问题 https://t.zsxq.com/kqyiB
|
||||
if (!ServletRequestPathUtils.hasParsedRequestPath(request)) {
|
||||
ServletRequestPathUtils.parseAndCache(request);
|
||||
}
|
||||
|
||||
// 解析 @ApiEncrypt 注解
|
||||
HandlerExecutionChain mappingHandler = requestMappingHandlerMapping.getHandler(request);
|
||||
if (mappingHandler == null) {
|
||||
return null;
|
||||
}
|
||||
Object handler = mappingHandler.getHandler();
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
ApiEncrypt annotation = handlerMethod.getMethodAnnotation(ApiEncrypt.class);
|
||||
if (annotation == null) {
|
||||
annotation = handlerMethod.getBeanType().getAnnotation(ApiEncrypt.class);
|
||||
}
|
||||
return annotation;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[getApiEncrypt][url({}/{}) 获取 @ApiEncrypt 注解失败]",
|
||||
request.getRequestURI(), request.getMethod(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package cn.iocoder.yudao.framework.encrypt.core.filter;
|
||||
|
||||
import cn.hutool.crypto.asymmetric.AsymmetricEncryptor;
|
||||
import cn.hutool.crypto.asymmetric.KeyType;
|
||||
import cn.hutool.crypto.symmetric.SymmetricEncryptor;
|
||||
import cn.iocoder.yudao.framework.encrypt.config.ApiEncryptProperties;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.WriteListener;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* 加密响应 {@link HttpServletResponseWrapper} 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class ApiEncryptResponseWrapper extends HttpServletResponseWrapper {
|
||||
|
||||
private final ByteArrayOutputStream byteArrayOutputStream;
|
||||
private final ServletOutputStream servletOutputStream;
|
||||
private final PrintWriter printWriter;
|
||||
|
||||
public ApiEncryptResponseWrapper(HttpServletResponse response) {
|
||||
super(response);
|
||||
this.byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
this.servletOutputStream = this.getOutputStream();
|
||||
this.printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream));
|
||||
}
|
||||
|
||||
public void encrypt(ApiEncryptProperties properties,
|
||||
SymmetricEncryptor symmetricEncryptor,
|
||||
AsymmetricEncryptor asymmetricEncryptor) throws IOException {
|
||||
// 1.1 清空 body
|
||||
HttpServletResponse response = (HttpServletResponse) this.getResponse();
|
||||
response.resetBuffer();
|
||||
// 1.2 获取 body
|
||||
this.flushBuffer();
|
||||
byte[] body = byteArrayOutputStream.toByteArray();
|
||||
|
||||
// 2. 加密 body
|
||||
String encryptedBody = symmetricEncryptor != null ? symmetricEncryptor.encryptBase64(body)
|
||||
: asymmetricEncryptor.encryptBase64(body, KeyType.PublicKey);
|
||||
response.getWriter().write(encryptedBody);
|
||||
|
||||
// 3. 添加加密 header 标识
|
||||
this.addHeader(properties.getHeader(), "true");
|
||||
// 特殊:特殊:https://juejin.cn/post/6867327674675625992
|
||||
this.addHeader("Access-Control-Expose-Headers", properties.getHeader());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintWriter getWriter() {
|
||||
return printWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBuffer() throws IOException {
|
||||
if (servletOutputStream != null) {
|
||||
servletOutputStream.flush();
|
||||
}
|
||||
if (printWriter != null) {
|
||||
printWriter.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
byteArrayOutputStream.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletOutputStream getOutputStream() {
|
||||
return new ServletOutputStream() {
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWriteListener(WriteListener writeListener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) {
|
||||
byteArrayOutputStream.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullableProblems")
|
||||
public void write(byte[] b) throws IOException {
|
||||
byteArrayOutputStream.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullableProblems")
|
||||
public void write(byte[] b, int off, int len) {
|
||||
byteArrayOutputStream.write(b, off, len);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* HTTP API 加密组件:支持 Request 和 Response 的加密、解密
|
||||
*/
|
||||
package cn.iocoder.yudao.framework.encrypt;
|
|
@ -1,10 +1,10 @@
|
|||
package cn.iocoder.yudao.framework.jackson.config;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.NumberSerializer;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeDeserializer;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
|
||||
import com.fasterxml.jackson.databind.Module;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||
|
@ -13,39 +13,65 @@ import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
|||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
|
||||
@AutoConfiguration
|
||||
@AutoConfiguration(after = JacksonAutoConfiguration.class)
|
||||
@Slf4j
|
||||
public class YudaoJacksonAutoConfiguration {
|
||||
|
||||
/**
|
||||
* 从 Builder 源头定制(关键:使用 *ByType,避免 handledType 要求)
|
||||
*/
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer ldtEpochMillisCustomizer() {
|
||||
return builder -> builder
|
||||
// Long -> Number
|
||||
.serializerByType(Long.class, NumberSerializer.INSTANCE)
|
||||
.serializerByType(Long.TYPE, NumberSerializer.INSTANCE)
|
||||
// LocalDate / LocalTime
|
||||
.serializerByType(LocalDate.class, LocalDateSerializer.INSTANCE)
|
||||
.deserializerByType(LocalDate.class, LocalDateDeserializer.INSTANCE)
|
||||
.serializerByType(LocalTime.class, LocalTimeSerializer.INSTANCE)
|
||||
.deserializerByType(LocalTime.class, LocalTimeDeserializer.INSTANCE)
|
||||
// LocalDateTime < - > EpochMillis
|
||||
.serializerByType(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
|
||||
.deserializerByType(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 以 Bean 形式暴露 Module(Boot 会自动注册到所有 ObjectMapper)
|
||||
*/
|
||||
@Bean
|
||||
public Module timestampSupportModuleBean() {
|
||||
SimpleModule m = new SimpleModule("TimestampSupportModule");
|
||||
// Long -> Number,避免前端精度丢失
|
||||
m.addSerializer(Long.class, NumberSerializer.INSTANCE);
|
||||
m.addSerializer(Long.TYPE, NumberSerializer.INSTANCE);
|
||||
// LocalDate / LocalTime
|
||||
m.addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE);
|
||||
m.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE);
|
||||
m.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE);
|
||||
m.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE);
|
||||
// LocalDateTime < - > EpochMillis
|
||||
m.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE);
|
||||
m.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化全局 JsonUtils,直接使用主 ObjectMapper
|
||||
*/
|
||||
@Bean
|
||||
@SuppressWarnings("InstantiationOfUtilityClass")
|
||||
public JsonUtils jsonUtils(List<ObjectMapper> objectMappers) {
|
||||
// 1.1 创建 SimpleModule 对象
|
||||
SimpleModule simpleModule = new SimpleModule();
|
||||
simpleModule
|
||||
// 新增 Long 类型序列化规则,数值超过 2^53-1,在 JS 会出现精度丢失问题,因此 Long 自动序列化为字符串类型
|
||||
.addSerializer(Long.class, NumberSerializer.INSTANCE)
|
||||
.addSerializer(Long.TYPE, NumberSerializer.INSTANCE)
|
||||
.addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE)
|
||||
.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)
|
||||
.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)
|
||||
.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)
|
||||
// 新增 LocalDateTime 序列化、反序列化规则,使用 Long 时间戳
|
||||
.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
|
||||
.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
|
||||
// 1.2 注册到 objectMapper
|
||||
objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));
|
||||
|
||||
// 2. 设置 objectMapper 到 JsonUtils
|
||||
JsonUtils.init(CollUtil.getFirst(objectMappers));
|
||||
log.info("[init][初始化 JsonUtils 成功]");
|
||||
public JsonUtils jsonUtils(ObjectMapper objectMapper) {
|
||||
JsonUtils.init(objectMapper);
|
||||
log.debug("[init][初始化 JsonUtils 成功]");
|
||||
return new JsonUtils();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
package cn.iocoder.yudao.framework.swagger.config;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
||||
import com.github.xiaoymin.knife4j.core.conf.ExtensionsConstants;
|
||||
import com.github.xiaoymin.knife4j.core.conf.GlobalConstants;
|
||||
import com.github.xiaoymin.knife4j.spring.configuration.Knife4jProperties;
|
||||
import com.github.xiaoymin.knife4j.spring.configuration.Knife4jSetting;
|
||||
import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springdoc.core.SpringDocConfigProperties;
|
||||
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 增强扩展属性支持
|
||||
*
|
||||
* 参考 <a href="https://github.com/xiaoymin/knife4j/issues/913">Spring Boot 3.4 以上版本 /v3/api-docs 解决接口报错,依赖修复</a>
|
||||
*
|
||||
* @since 4.1.0
|
||||
* @author <a href="xiaoymin@foxmail.com">xiaoymin@foxmail.com</a>
|
||||
* 2022/12/11 22:40
|
||||
*/
|
||||
@Primary
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class Knife4jOpenApiCustomizer extends com.github.xiaoymin.knife4j.spring.extension.Knife4jOpenApiCustomizer
|
||||
implements GlobalOpenApiCustomizer {
|
||||
|
||||
final Knife4jProperties knife4jProperties;
|
||||
final SpringDocConfigProperties properties;
|
||||
|
||||
public Knife4jOpenApiCustomizer(Knife4jProperties knife4jProperties, SpringDocConfigProperties properties) {
|
||||
super(knife4jProperties,properties);
|
||||
this.knife4jProperties = knife4jProperties;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customise(OpenAPI openApi) {
|
||||
if (knife4jProperties.isEnable()) {
|
||||
Knife4jSetting setting = knife4jProperties.getSetting();
|
||||
OpenApiExtensionResolver openApiExtensionResolver = new OpenApiExtensionResolver(setting, knife4jProperties.getDocuments());
|
||||
// 解析初始化
|
||||
openApiExtensionResolver.start();
|
||||
Map<String, Object> objectMap = new HashMap<>();
|
||||
objectMap.put(GlobalConstants.EXTENSION_OPEN_SETTING_NAME, setting);
|
||||
objectMap.put(GlobalConstants.EXTENSION_OPEN_MARKDOWN_NAME, openApiExtensionResolver.getMarkdownFiles());
|
||||
openApi.addExtension(GlobalConstants.EXTENSION_OPEN_API_NAME, objectMap);
|
||||
addOrderExtension(openApi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 往 OpenAPI 内 tags 字段添加 x-order 属性
|
||||
*
|
||||
* @param openApi openApi
|
||||
*/
|
||||
private void addOrderExtension(OpenAPI openApi) {
|
||||
if (CollectionUtils.isEmpty(properties.getGroupConfigs())) {
|
||||
return;
|
||||
}
|
||||
// 获取包扫描路径
|
||||
Set<String> packagesToScan =
|
||||
properties.getGroupConfigs().stream()
|
||||
.map(SpringDocConfigProperties.GroupConfig::getPackagesToScan)
|
||||
.filter(toScan -> !CollectionUtils.isEmpty(toScan))
|
||||
.flatMap(List::stream)
|
||||
.collect(Collectors.toSet());
|
||||
if (CollectionUtils.isEmpty(packagesToScan)) {
|
||||
return;
|
||||
}
|
||||
// 扫描包下被 ApiSupport 注解的 RestController Class
|
||||
Set<Class<?>> classes = packagesToScan.stream()
|
||||
.map(packageToScan -> scanPackageByAnnotation(packageToScan, RestController.class))
|
||||
.flatMap(Set::stream)
|
||||
.filter(clazz -> clazz.isAnnotationPresent(ApiSupport.class))
|
||||
.collect(Collectors.toSet());
|
||||
if (!CollectionUtils.isEmpty(classes)) {
|
||||
// ApiSupport oder 值存入 tagSortMap<Tag.name,ApiSupport.order>
|
||||
Map<String, Integer> tagOrderMap = new HashMap<>();
|
||||
classes.forEach(clazz -> {
|
||||
Tag tag = getTag(clazz);
|
||||
if (Objects.nonNull(tag)) {
|
||||
ApiSupport apiSupport = clazz.getAnnotation(ApiSupport.class);
|
||||
tagOrderMap.putIfAbsent(tag.name(), apiSupport.order());
|
||||
}
|
||||
});
|
||||
// 往 openApi tags 字段添加 x-order 增强属性
|
||||
if (openApi.getTags() != null) {
|
||||
openApi.getTags().forEach(tag -> {
|
||||
if (tagOrderMap.containsKey(tag.getName())) {
|
||||
tag.addExtension(ExtensionsConstants.EXTENSION_ORDER, tagOrderMap.get(tag.getName()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Tag getTag(Class<?> clazz) {
|
||||
// 从类上获取
|
||||
Tag tag = clazz.getAnnotation(Tag.class);
|
||||
if (Objects.isNull(tag)) {
|
||||
// 从接口上获取
|
||||
Class<?>[] interfaces = clazz.getInterfaces();
|
||||
if (ArrayUtils.isNotEmpty(interfaces)) {
|
||||
for (Class<?> interfaceClazz : interfaces) {
|
||||
Tag anno = interfaceClazz.getAnnotation(Tag.class);
|
||||
if (Objects.nonNull(anno)) {
|
||||
tag = anno;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
private Set<Class<?>> scanPackageByAnnotation(String packageName, final Class<? extends Annotation> annotationClass) {
|
||||
ClassPathScanningCandidateComponentProvider scanner =
|
||||
new ClassPathScanningCandidateComponentProvider(false);
|
||||
scanner.addIncludeFilter(new AnnotationTypeFilter(annotationClass));
|
||||
Set<Class<?>> classes = new HashSet<>();
|
||||
for (BeanDefinition beanDefinition : scanner.findCandidateComponents(packageName)) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(beanDefinition.getBeanClassName());
|
||||
classes.add(clazz);
|
||||
} catch (ClassNotFoundException ignore) {
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
||||
|
@ -42,6 +43,7 @@ import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_
|
|||
@ConditionalOnClass({OpenAPI.class})
|
||||
@EnableConfigurationProperties(SwaggerProperties.class)
|
||||
@ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = true) // 设置为 false 时,禁用
|
||||
@Import(Knife4jOpenApiCustomizer.class)
|
||||
public class YudaoSwaggerAutoConfiguration {
|
||||
|
||||
// ========== 全局 OpenAPI 配置 ==========
|
||||
|
|
|
@ -8,7 +8,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
|
@ -29,12 +28,22 @@ public class CacheRequestBodyWrapper extends HttpServletRequestWrapper {
|
|||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() throws IOException {
|
||||
public BufferedReader getReader() {
|
||||
return new BufferedReader(new InputStreamReader(this.getInputStream()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
public int getContentLength() {
|
||||
return body.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getContentLengthLong() {
|
||||
return body.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() {
|
||||
final ByteArrayInputStream inputStream = new ByteArrayInputStream(body);
|
||||
// 返回 ServletInputStream
|
||||
return new ServletInputStream() {
|
||||
|
|
|
@ -5,7 +5,6 @@ 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.hutool.extra.servlet.JakartaServletUtil;
|
||||
import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi;
|
||||
import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
|
@ -17,6 +16,7 @@ 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 com.fasterxml.jackson.databind.exc.InvalidFormatException;
|
||||
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
|
@ -32,6 +32,7 @@ import org.springframework.web.bind.MissingServletRequestParameterException;
|
|||
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.multipart.MaxUploadSizeExceededException;
|
||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -92,12 +93,12 @@ public class GlobalExceptionHandler {
|
|||
if (ex instanceof ValidationException) {
|
||||
return validationException((ValidationException) ex);
|
||||
}
|
||||
if (ex instanceof MaxUploadSizeExceededException) {
|
||||
return maxUploadSizeExceededExceptionHandler((MaxUploadSizeExceededException) ex);
|
||||
}
|
||||
if (ex instanceof NoHandlerFoundException) {
|
||||
return noHandlerFoundExceptionHandler((NoHandlerFoundException) ex);
|
||||
}
|
||||
// if (ex instanceof NoResourceFoundException) {
|
||||
// return noResourceFoundExceptionHandler(request, (NoResourceFoundException) ex);
|
||||
// }
|
||||
if (ex instanceof HttpRequestMethodNotSupportedException) {
|
||||
return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex);
|
||||
}
|
||||
|
@ -177,6 +178,7 @@ public class GlobalExceptionHandler {
|
|||
* 例如说,接口上设置了 @RequestBody 实体中 xx 属性类型为 Integer,结果传递 xx 参数类型为 String
|
||||
*/
|
||||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
||||
@SuppressWarnings("PatternVariableCanBeUsed")
|
||||
public CommonResult<?> methodArgumentTypeInvalidFormatExceptionHandler(HttpMessageNotReadableException ex) {
|
||||
log.warn("[methodArgumentTypeInvalidFormatExceptionHandler]", ex);
|
||||
if (ex.getCause() instanceof InvalidFormatException) {
|
||||
|
@ -209,6 +211,14 @@ public class GlobalExceptionHandler {
|
|||
return CommonResult.error(BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理上传文件过大异常
|
||||
*/
|
||||
@ExceptionHandler(MaxUploadSizeExceededException.class)
|
||||
public CommonResult<?> maxUploadSizeExceededExceptionHandler(MaxUploadSizeExceededException ex) {
|
||||
return CommonResult.error(BAD_REQUEST.getCode(), "上传文件过大,请调整后重试");
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 SpringMVC 请求地址不存在
|
||||
*
|
||||
|
@ -222,15 +232,6 @@ public class GlobalExceptionHandler {
|
|||
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 请求方法不正确
|
||||
*
|
||||
|
@ -265,6 +266,16 @@ public class GlobalExceptionHandler {
|
|||
return CommonResult.error(FORBIDDEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 Guava UncheckedExecutionException
|
||||
*
|
||||
* 例如说,缓存加载报错,可见 <a href="https://t.zsxq.com/UszdH">https://t.zsxq.com/UszdH</a>
|
||||
*/
|
||||
@ExceptionHandler(value = UncheckedExecutionException.class)
|
||||
public CommonResult<?> uncheckedExecutionExceptionHandler(HttpServletRequest req, UncheckedExecutionException ex) {
|
||||
return allExceptionHandler(req, ex.getCause());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理业务异常 ServiceException
|
||||
*
|
||||
|
@ -295,6 +306,12 @@ public class GlobalExceptionHandler {
|
|||
*/
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
public CommonResult<?> defaultExceptionHandler(HttpServletRequest req, Throwable ex) {
|
||||
// 特殊:如果是 ServiceException 的异常,则直接返回
|
||||
// 例如说:https://gitee.com/zhijiantianya/yudao-cloud/issues/ICSSRM、https://gitee.com/zhijiantianya/yudao-cloud/issues/ICT6FM
|
||||
if (ex.getCause() != null && ex.getCause() instanceof ServiceException) {
|
||||
return serviceExceptionHandler((ServiceException) ex.getCause());
|
||||
}
|
||||
|
||||
// 情况一:处理表不存在的异常
|
||||
CommonResult<?> tableNotExistsResult = handleTableNotExists(ex);
|
||||
if (tableNotExistsResult != null) {
|
||||
|
|
|
@ -148,6 +148,7 @@ public class WebFrameworkUtils {
|
|||
return (CommonResult<?>) request.getAttribute(REQUEST_ATTRIBUTE_COMMON_RESULT);
|
||||
}
|
||||
|
||||
@SuppressWarnings("PatternVariableCanBeUsed")
|
||||
public static HttpServletRequest getRequest() {
|
||||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
if (!(requestAttributes instanceof ServletRequestAttributes)) {
|
||||
|
|
|
@ -4,4 +4,5 @@ cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration
|
|||
cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration
|
||||
cn.iocoder.yudao.framework.apilog.config.YudaoApiLogRpcAutoConfiguration
|
||||
cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration
|
||||
cn.iocoder.yudao.framework.banner.config.YudaoBannerAutoConfiguration
|
||||
cn.iocoder.yudao.framework.banner.config.YudaoBannerAutoConfiguration
|
||||
cn.iocoder.yudao.framework.encrypt.config.YudaoApiEncryptAutoConfiguration
|
|
@ -0,0 +1,86 @@
|
|||
package cn.iocoder.yudao.framework.encrypt;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.asymmetric.AsymmetricAlgorithm;
|
||||
import cn.hutool.crypto.asymmetric.KeyType;
|
||||
import cn.hutool.crypto.asymmetric.RSA;
|
||||
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 各种 API 加解密的测试类:不是单测,而是方便大家生成密钥、加密、解密等操作。
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@SuppressWarnings("ConstantValue")
|
||||
public class ApiEncryptTest {
|
||||
|
||||
@Test
|
||||
public void testGenerateAsymmetric() {
|
||||
String asymmetricAlgorithm = AsymmetricAlgorithm.RSA.getValue();
|
||||
// String asymmetricAlgorithm = "SM2";
|
||||
// String asymmetricAlgorithm = SM4.ALGORITHM_NAME;
|
||||
// String asymmetricAlgorithm = SymmetricAlgorithm.AES.getValue();
|
||||
String requestClientKey = null;
|
||||
String requestServerKey = null;
|
||||
String responseClientKey = null;
|
||||
String responseServerKey = null;
|
||||
if (Objects.equals(asymmetricAlgorithm, AsymmetricAlgorithm.RSA.getValue())) {
|
||||
// 请求的密钥
|
||||
RSA requestRsa = SecureUtil.rsa();
|
||||
requestClientKey = requestRsa.getPublicKeyBase64();
|
||||
requestServerKey = requestRsa.getPrivateKeyBase64();
|
||||
// 响应的密钥
|
||||
RSA responseRsa = new RSA();
|
||||
responseClientKey = responseRsa.getPrivateKeyBase64();
|
||||
responseServerKey = responseRsa.getPublicKeyBase64();
|
||||
} else if (Objects.equals(asymmetricAlgorithm, SymmetricAlgorithm.AES.getValue())) {
|
||||
// AES 密钥可选 32、24、16 位
|
||||
// 请求的密钥(前后端密钥一致)
|
||||
requestClientKey = RandomUtil.randomNumbers(32);
|
||||
requestServerKey = requestClientKey;
|
||||
// 响应的密钥(前后端密钥一致)
|
||||
responseClientKey = RandomUtil.randomNumbers(32);
|
||||
responseServerKey = responseClientKey;
|
||||
}
|
||||
|
||||
// 打印结果
|
||||
System.out.println("requestClientKey = " + requestClientKey);
|
||||
System.out.println("requestServerKey = " + requestServerKey);
|
||||
System.out.println("responseClientKey = " + responseClientKey);
|
||||
System.out.println("responseServerKey = " + responseServerKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncrypt_aes() {
|
||||
String key = "52549111389893486934626385991395";
|
||||
String body = "{\n" +
|
||||
" \"username\": \"admin\",\n" +
|
||||
" \"password\": \"admin123\",\n" +
|
||||
" \"uuid\": \"3acd87a09a4f48fb9118333780e94883\",\n" +
|
||||
" \"code\": \"1024\"\n" +
|
||||
"}";
|
||||
String encrypt = SecureUtil.aes(StrUtil.utf8Bytes(key))
|
||||
.encryptBase64(body);
|
||||
System.out.println("encrypt = " + encrypt);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncrypt_rsa() {
|
||||
String key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCls2rIpnGdYnLFgz1XU13GbNQ5DloyPpvW00FPGjqn5Z6JpK+kDtVlnkhwR87iRrE5Vf2WNqRX6vzbLSgveIQY8e8oqGCb829myjf1MuI+ZzN4ghf/7tEYhZJGPI9AbfxFqBUzm+kR3/HByAI22GLT96WM26QiMK8n3tIP/yiLswIDAQAB";
|
||||
String body = "{\n" +
|
||||
" \"username\": \"admin\",\n" +
|
||||
" \"password\": \"admin123\",\n" +
|
||||
" \"uuid\": \"3acd87a09a4f48fb9118333780e94883\",\n" +
|
||||
" \"code\": \"1024\"\n" +
|
||||
"}";
|
||||
String encrypt = SecureUtil.rsa(null, key)
|
||||
.encryptBase64(body, KeyType.PublicKey);
|
||||
System.out.println("encrypt = " + encrypt);
|
||||
}
|
||||
|
||||
}
|
|
@ -40,6 +40,11 @@
|
|||
<artifactId>javax.servlet-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId> <!-- 接口文档 -->
|
||||
<artifactId>knife4j-gateway-spring-boot-starter</artifactId>
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
package cn.iocoder.yudao.gateway.jackson;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.NumberSerializer;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeDeserializer;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
|
||||
import com.fasterxml.jackson.databind.Module;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
import org.springframework.boot.web.codec.CodecCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class GatewayJacksonAutoConfiguration {
|
||||
|
||||
/**
|
||||
* 从 Builder 源头定制(关键:使用 *ByType,避免 handledType 要求)
|
||||
*/
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer ldtEpochMillisCustomizer() {
|
||||
return builder -> builder
|
||||
// Long -> Number
|
||||
.serializerByType(Long.class, NumberSerializer.INSTANCE)
|
||||
.serializerByType(Long.TYPE, NumberSerializer.INSTANCE)
|
||||
// LocalDate / LocalTime
|
||||
.serializerByType(LocalDate.class, LocalDateSerializer.INSTANCE)
|
||||
.deserializerByType(LocalDate.class, LocalDateDeserializer.INSTANCE)
|
||||
.serializerByType(LocalTime.class, LocalTimeSerializer.INSTANCE)
|
||||
.deserializerByType(LocalTime.class, LocalTimeDeserializer.INSTANCE)
|
||||
// LocalDateTime < - > EpochMillis
|
||||
.serializerByType(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
|
||||
.deserializerByType(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 以 Bean 形式暴露 Module(Boot 会自动注册到所有 ObjectMapper)
|
||||
*/
|
||||
@Bean
|
||||
public Module timestampSupportModuleBean() {
|
||||
SimpleModule m = new SimpleModule("TimestampSupportModule");
|
||||
// Long -> Number
|
||||
m.addSerializer(Long.class, NumberSerializer.INSTANCE);
|
||||
m.addSerializer(Long.TYPE, NumberSerializer.INSTANCE);
|
||||
// LocalDate / LocalTime
|
||||
m.addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE);
|
||||
m.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE);
|
||||
m.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE);
|
||||
m.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE);
|
||||
// LocalDateTime < - > EpochMillis
|
||||
m.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE);
|
||||
m.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化全局 JsonUtils,直接使用主 ObjectMapper
|
||||
*/
|
||||
@Bean
|
||||
@SuppressWarnings("InstantiationOfUtilityClass")
|
||||
public JsonUtils jsonUtils(ObjectMapper objectMapper) {
|
||||
JsonUtils.init(objectMapper);
|
||||
log.debug("[init][初始化 JsonUtils 成功]");
|
||||
return new JsonUtils();
|
||||
}
|
||||
|
||||
/**
|
||||
* WebFlux 场景:强制默认编解码器使用同一个 ObjectMapper
|
||||
*/
|
||||
@Bean
|
||||
public CodecCustomizer unifyJackson(ObjectMapper om) {
|
||||
return configurer -> {
|
||||
Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(om);
|
||||
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder(om);
|
||||
configurer.defaultCodecs().jackson2JsonDecoder(decoder);
|
||||
configurer.defaultCodecs().jackson2JsonEncoder(encoder);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
package cn.iocoder.yudao.gateway.jackson;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.NumberSerializer;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeDeserializer;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class JacksonAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public JsonUtils jsonUtils(List<ObjectMapper> objectMappers) {
|
||||
// 1.1 创建 SimpleModule 对象
|
||||
SimpleModule simpleModule = new SimpleModule();
|
||||
simpleModule
|
||||
// 新增 Long 类型序列化规则,数值超过 2^53-1,在 JS 会出现精度丢失问题,因此 Long 自动序列化为字符串类型
|
||||
.addSerializer(Long.class, NumberSerializer.INSTANCE)
|
||||
.addSerializer(Long.TYPE, NumberSerializer.INSTANCE)
|
||||
.addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE)
|
||||
.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)
|
||||
.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)
|
||||
.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)
|
||||
// 新增 LocalDateTime 序列化、反序列化规则,使用 Long 时间戳
|
||||
.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
|
||||
.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
|
||||
// 1.2 注册到 objectMapper
|
||||
objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));
|
||||
|
||||
// 2. 设置 objectMapper 到 JsonUtils
|
||||
JsonUtils.init(CollUtil.getFirst(objectMappers));
|
||||
log.info("[init][初始化 JsonUtils 成功]");
|
||||
return new JsonUtils();
|
||||
}
|
||||
|
||||
}
|
|
@ -181,6 +181,10 @@ spring:
|
|||
- Path=/admin-api/ai/**
|
||||
filters:
|
||||
- RewritePath=/admin-api/ai/v3/api-docs, /v3/api-docs # 配置,保证转发到 /v3/api-docs
|
||||
- id: ai-mcp-server # 路由的编号(MCP Server)
|
||||
uri: grayLb://ai-server
|
||||
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
|
||||
- Path=/sse, /mcp/message
|
||||
## iot-server 服务
|
||||
- id: iot-admin-api # 路由的编号
|
||||
uri: grayLb://iot-server
|
||||
|
|
|
@ -33,6 +33,8 @@ public enum AiPlatformEnum implements ArrayValuable<String> {
|
|||
|
||||
OPENAI("OpenAI", "OpenAI"), // OpenAI 官方
|
||||
AZURE_OPENAI("AzureOpenAI", "AzureOpenAI"), // OpenAI 微软
|
||||
ANTHROPIC("Anthropic", "Anthropic"), // Anthropic Claude
|
||||
GEMINI("Gemini", "Gemini"), // 谷歌 Gemini
|
||||
OLLAMA("Ollama", "Ollama"),
|
||||
|
||||
STABLE_DIFFUSION("StableDiffusion", "StableDiffusion"), // Stability AI
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>yudao-module-ai-server</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
|
@ -18,8 +19,8 @@
|
|||
国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
|
||||
</description>
|
||||
<properties>
|
||||
<spring-ai.version>1.0.0</spring-ai.version>
|
||||
<alibaba-ai.version>1.0.0.2</alibaba-ai.version>
|
||||
<spring-ai.version>1.0.1</spring-ai.version>
|
||||
<alibaba-ai.version>1.0.0.3</alibaba-ai.version>
|
||||
<tinyflow.version>1.0.2</tinyflow.version>
|
||||
</properties>
|
||||
|
||||
|
@ -119,6 +120,11 @@
|
|||
<artifactId>spring-ai-starter-model-azure-openai</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-starter-model-anthropic</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-starter-model-deepseek</artifactId>
|
||||
|
@ -217,6 +223,24 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- MCP 相关 -->
|
||||
<!--
|
||||
特殊说明:不能使用 spring-ai-starter-mcp-server-webflux 或 spring-ai-starter-mcp-client-webflux !!!
|
||||
原因:项目使用了 SpringMVC,而不是 WebFlux。引入上述 2 个,会导致 SSE Server 失效。
|
||||
-->
|
||||
<dependency>
|
||||
<!-- 服务端 -->
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- 客户端 -->
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-starter-mcp-client</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- TinyFlow:AI 工作流 -->
|
||||
<dependency>
|
||||
<groupId>dev.tinyflow</groupId>
|
||||
|
|
|
@ -20,9 +20,46 @@ tenant-id: {{adminTenantId}}
|
|||
"content": "1+1=?"
|
||||
}
|
||||
|
||||
### 获得指定对话的消息列表
|
||||
GET {{baseUrl}}/ai/chat/message/list-by-conversation-id?conversationId=1781604279872581649
|
||||
### 发送消息(流式)【带文件】
|
||||
POST {{baseUrl}}/ai/chat/message/send-stream
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
tenant-id: {{adminTenantId}}
|
||||
|
||||
{
|
||||
"conversationId": "1781604279872581797",
|
||||
"content": "图片里有什么?",
|
||||
"attachmentUrls": ["http://test.yudao.iocoder.cn/1755531278.jpeg"]
|
||||
}
|
||||
|
||||
### 发送消息(流式)【追问带文件】
|
||||
POST {{baseUrl}}/ai/chat/message/send-stream
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
tenant-id: {{adminTenantId}}
|
||||
|
||||
{
|
||||
"conversationId": "1781604279872581799",
|
||||
"content": "说下图片里,有哪些字?",
|
||||
"useContext": true
|
||||
}
|
||||
|
||||
### 发送消息(流式)【联网搜索】
|
||||
POST {{baseUrl}}/ai/chat/message/send-stream
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
tenant-id: {{adminTenantId}}
|
||||
|
||||
{
|
||||
"conversationId": "1781604279872581799",
|
||||
"content": "今天是周几?",
|
||||
"useSearch": true
|
||||
}
|
||||
|
||||
### 获得指定对话的消息列表
|
||||
GET {{baseUrl}}/ai/chat/message/list-by-conversation-id?conversationId=1781604279872581799
|
||||
Authorization: {{token}}
|
||||
tenant-id: {{adminTenantId}}
|
||||
|
||||
### 删除消息
|
||||
DELETE {{baseUrl}}/ai/chat/message/delete?id=50
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message;
|
||||
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchResponse;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
|
@ -37,6 +38,9 @@ public class AiChatMessageRespVO {
|
|||
@Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "推理内容", example = "要达到这个目标,你需要...")
|
||||
private String reasoningContent;
|
||||
|
||||
@Schema(description = "是否携带上下文", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
private Boolean useContext;
|
||||
|
||||
|
@ -46,6 +50,12 @@ public class AiChatMessageRespVO {
|
|||
@Schema(description = "知识库段落数组")
|
||||
private List<KnowledgeSegment> segments;
|
||||
|
||||
@Schema(description = "联网搜索的网页内容数组")
|
||||
private List<AiWebSearchResponse.WebPage> webSearchPages;
|
||||
|
||||
@Schema(description = "附件 URL 数组", example = "https://www.iocoder.cn/1.png")
|
||||
private List<String> attachmentUrls;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-12 12:51")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message;
|
|||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - AI 聊天消息发送 Request VO")
|
||||
@Data
|
||||
|
@ -22,4 +22,10 @@ public class AiChatMessageSendReqVO {
|
|||
@Schema(description = "是否携带上下文", example = "true")
|
||||
private Boolean useContext;
|
||||
|
||||
@Schema(description = "是否联网搜索", example = "true")
|
||||
private Boolean useSearch;
|
||||
|
||||
@Schema(description = "附件 URL 数组", example = "https://www.iocoder.cn/1.png")
|
||||
private List<String> attachmentUrls;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message;
|
||||
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchResponse;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
|
@ -29,12 +30,18 @@ public class AiChatMessageSendRespVO {
|
|||
@Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "推理内容", example = "要达到这个目标,你需要...")
|
||||
private String reasoningContent;
|
||||
|
||||
@Schema(description = "知识库段落编号数组", example = "[1,2,3]")
|
||||
private List<Long> segmentIds;
|
||||
|
||||
@Schema(description = "知识库段落数组")
|
||||
private List<AiChatMessageRespVO.KnowledgeSegment> segments;
|
||||
|
||||
@Schema(description = "联网搜索的网页内容数组")
|
||||
private List<AiWebSearchResponse.WebPage> webSearchPages;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
|
|
|
@ -52,6 +52,9 @@ public class AiChatRoleRespVO implements VO {
|
|||
@Schema(description = "引用的工具编号列表", example = "1,2,3")
|
||||
private List<Long> toolIds;
|
||||
|
||||
@Schema(description = "引用的 MCP Client 名字列表", example = "filesystem")
|
||||
private List<String> mcpClientNames;
|
||||
|
||||
@Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Boolean publicStatus;
|
||||
|
||||
|
|
|
@ -37,4 +37,7 @@ public class AiChatRoleSaveMyReqVO {
|
|||
@Schema(description = "引用的工具编号列表", example = "1,2,3")
|
||||
private List<Long> toolIds;
|
||||
|
||||
@Schema(description = "引用的 MCP Client 名字列表", example = "filesystem")
|
||||
private List<String> mcpClientNames;
|
||||
|
||||
}
|
|
@ -50,6 +50,9 @@ public class AiChatRoleSaveReqVO {
|
|||
@Schema(description = "引用的工具编号列表", example = "1,2,3")
|
||||
private List<Long> toolIds;
|
||||
|
||||
@Schema(description = "引用的 MCP Client 名字列表", example = "filesystem")
|
||||
private List<String> mcpClientNames;
|
||||
|
||||
@Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "是否公开不能为空")
|
||||
private Boolean publicStatus;
|
||||
|
|
|
@ -2,14 +2,20 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.chat;
|
|||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.StringListTypeHandler;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchResponse;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.ai.chat.messages.MessageType;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -87,6 +93,10 @@ public class AiChatMessageDO extends BaseDO {
|
|||
* 聊天内容
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 推理内容
|
||||
*/
|
||||
private String reasoningContent;
|
||||
|
||||
/**
|
||||
* 是否携带上下文
|
||||
|
@ -101,4 +111,16 @@ public class AiChatMessageDO extends BaseDO {
|
|||
@TableField(typeHandler = LongListTypeHandler.class)
|
||||
private List<Long> segmentIds;
|
||||
|
||||
/**
|
||||
* 联网搜索的网页内容数组
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<AiWebSearchResponse.WebPage> webSearchPages;
|
||||
|
||||
/**
|
||||
* 附件 URL 数组
|
||||
*/
|
||||
@TableField(typeHandler = StringListTypeHandler.class)
|
||||
private List<String> attachmentUrls;
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.model;
|
|||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.StringListTypeHandler;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
|
@ -80,6 +81,13 @@ public class AiChatRoleDO extends BaseDO {
|
|||
*/
|
||||
@TableField(typeHandler = LongListTypeHandler.class)
|
||||
private List<Long> toolIds;
|
||||
/**
|
||||
* 引用的 MCP Client 名字列表
|
||||
*
|
||||
* 关联 spring.ai.mcp.client 下的名字
|
||||
*/
|
||||
@TableField(typeHandler = StringListTypeHandler.class)
|
||||
private List<String> mcpClientNames;
|
||||
|
||||
/**
|
||||
* 是否公开
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package cn.iocoder.yudao.module.ai.dal.dataobject.model;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.ai.service.model.tool.DirectoryListToolFunction;
|
||||
import cn.iocoder.yudao.module.ai.service.model.tool.WeatherQueryToolFunction;
|
||||
import cn.iocoder.yudao.module.ai.tool.function.DirectoryListToolFunction;
|
||||
import cn.iocoder.yudao.module.ai.tool.function.WeatherQueryToolFunction;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
|
|
@ -2,25 +2,34 @@ package cn.iocoder.yudao.module.ai.framework.ai.config;
|
|||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.AiModelFactory;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.AiModelFactoryImpl;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.AiModelFactory;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.AiModelFactoryImpl;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.gemini.GeminiChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowApiConstants;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchClient;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.bocha.AiBoChaWebSearchClient;
|
||||
import cn.iocoder.yudao.module.ai.tool.method.PersonService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.ai.deepseek.DeepSeekChatModel;
|
||||
import org.springframework.ai.deepseek.DeepSeekChatOptions;
|
||||
import org.springframework.ai.deepseek.api.DeepSeekApi;
|
||||
import org.springframework.ai.embedding.BatchingStrategy;
|
||||
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
|
||||
import org.springframework.ai.model.tool.ToolCallingManager;
|
||||
import org.springframework.ai.openai.OpenAiChatModel;
|
||||
import org.springframework.ai.openai.OpenAiChatOptions;
|
||||
import org.springframework.ai.openai.api.OpenAiApi;
|
||||
import org.springframework.ai.support.ToolCallbacks;
|
||||
import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator;
|
||||
import org.springframework.ai.tokenizer.TokenCountEstimator;
|
||||
import org.springframework.ai.tool.ToolCallback;
|
||||
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties;
|
||||
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties;
|
||||
import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties;
|
||||
|
@ -30,6 +39,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 芋道 AI 自动配置
|
||||
*
|
||||
|
@ -51,20 +62,49 @@ public class AiAutoConfiguration {
|
|||
|
||||
// ========== 各种 AI Client 创建 ==========
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "yudao.ai.gemini.enable", havingValue = "true")
|
||||
public GeminiChatModel geminiChatModel(YudaoAiProperties yudaoAiProperties) {
|
||||
YudaoAiProperties.Gemini properties = yudaoAiProperties.getGemini();
|
||||
return buildGeminiChatClient(properties);
|
||||
}
|
||||
|
||||
public GeminiChatModel buildGeminiChatClient(YudaoAiProperties.Gemini properties) {
|
||||
if (StrUtil.isEmpty(properties.getModel())) {
|
||||
properties.setModel(GeminiChatModel.MODEL_DEFAULT);
|
||||
}
|
||||
OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
|
||||
.openAiApi(OpenAiApi.builder()
|
||||
.baseUrl(GeminiChatModel.BASE_URL)
|
||||
.completionsPath(GeminiChatModel.COMPLETE_PATH)
|
||||
.apiKey(properties.getApiKey())
|
||||
.build())
|
||||
.defaultOptions(OpenAiChatOptions.builder()
|
||||
.model(properties.getModel())
|
||||
.temperature(properties.getTemperature())
|
||||
.maxTokens(properties.getMaxTokens())
|
||||
.topP(properties.getTopP())
|
||||
.build())
|
||||
.toolCallingManager(getToolCallingManager())
|
||||
.build();
|
||||
return new GeminiChatModel(openAiChatModel);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "yudao.ai.doubao.enable", havingValue = "true")
|
||||
public DouBaoChatModel douBaoChatClient(YudaoAiProperties yudaoAiProperties) {
|
||||
YudaoAiProperties.DouBaoProperties properties = yudaoAiProperties.getDoubao();
|
||||
YudaoAiProperties.DouBao properties = yudaoAiProperties.getDoubao();
|
||||
return buildDouBaoChatClient(properties);
|
||||
}
|
||||
|
||||
public DouBaoChatModel buildDouBaoChatClient(YudaoAiProperties.DouBaoProperties properties) {
|
||||
public DouBaoChatModel buildDouBaoChatClient(YudaoAiProperties.DouBao properties) {
|
||||
if (StrUtil.isEmpty(properties.getModel())) {
|
||||
properties.setModel(DouBaoChatModel.MODEL_DEFAULT);
|
||||
}
|
||||
OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
|
||||
.openAiApi(OpenAiApi.builder()
|
||||
.baseUrl(DouBaoChatModel.BASE_URL)
|
||||
.completionsPath(DouBaoChatModel.COMPLETE_PATH)
|
||||
.apiKey(properties.getApiKey())
|
||||
.build())
|
||||
.defaultOptions(OpenAiChatOptions.builder()
|
||||
|
@ -81,20 +121,20 @@ public class AiAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnProperty(value = "yudao.ai.siliconflow.enable", havingValue = "true")
|
||||
public SiliconFlowChatModel siliconFlowChatClient(YudaoAiProperties yudaoAiProperties) {
|
||||
YudaoAiProperties.SiliconFlowProperties properties = yudaoAiProperties.getSiliconflow();
|
||||
YudaoAiProperties.SiliconFlow properties = yudaoAiProperties.getSiliconflow();
|
||||
return buildSiliconFlowChatClient(properties);
|
||||
}
|
||||
|
||||
public SiliconFlowChatModel buildSiliconFlowChatClient(YudaoAiProperties.SiliconFlowProperties properties) {
|
||||
public SiliconFlowChatModel buildSiliconFlowChatClient(YudaoAiProperties.SiliconFlow properties) {
|
||||
if (StrUtil.isEmpty(properties.getModel())) {
|
||||
properties.setModel(SiliconFlowApiConstants.MODEL_DEFAULT);
|
||||
}
|
||||
OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
|
||||
.openAiApi(OpenAiApi.builder()
|
||||
DeepSeekChatModel openAiChatModel = DeepSeekChatModel.builder()
|
||||
.deepSeekApi(DeepSeekApi.builder()
|
||||
.baseUrl(SiliconFlowApiConstants.DEFAULT_BASE_URL)
|
||||
.apiKey(properties.getApiKey())
|
||||
.build())
|
||||
.defaultOptions(OpenAiChatOptions.builder()
|
||||
.defaultOptions(DeepSeekChatOptions.builder()
|
||||
.model(properties.getModel())
|
||||
.temperature(properties.getTemperature())
|
||||
.maxTokens(properties.getMaxTokens())
|
||||
|
@ -108,11 +148,11 @@ public class AiAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnProperty(value = "yudao.ai.hunyuan.enable", havingValue = "true")
|
||||
public HunYuanChatModel hunYuanChatClient(YudaoAiProperties yudaoAiProperties) {
|
||||
YudaoAiProperties.HunYuanProperties properties = yudaoAiProperties.getHunyuan();
|
||||
YudaoAiProperties.HunYuan properties = yudaoAiProperties.getHunyuan();
|
||||
return buildHunYuanChatClient(properties);
|
||||
}
|
||||
|
||||
public HunYuanChatModel buildHunYuanChatClient(YudaoAiProperties.HunYuanProperties properties) {
|
||||
public HunYuanChatModel buildHunYuanChatClient(YudaoAiProperties.HunYuan properties) {
|
||||
if (StrUtil.isEmpty(properties.getModel())) {
|
||||
properties.setModel(HunYuanChatModel.MODEL_DEFAULT);
|
||||
}
|
||||
|
@ -122,13 +162,14 @@ public class AiAutoConfiguration {
|
|||
StrUtil.startWithIgnoreCase(properties.getModel(), "deepseek") ? HunYuanChatModel.DEEP_SEEK_BASE_URL
|
||||
: HunYuanChatModel.BASE_URL);
|
||||
}
|
||||
// 创建 OpenAiChatModel、HunYuanChatModel 对象
|
||||
OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
|
||||
.openAiApi(OpenAiApi.builder()
|
||||
// 创建 DeepSeekChatModel、HunYuanChatModel 对象
|
||||
DeepSeekChatModel openAiChatModel = DeepSeekChatModel.builder()
|
||||
.deepSeekApi(DeepSeekApi.builder()
|
||||
.baseUrl(properties.getBaseUrl())
|
||||
.completionsPath(HunYuanChatModel.COMPLETE_PATH)
|
||||
.apiKey(properties.getApiKey())
|
||||
.build())
|
||||
.defaultOptions(OpenAiChatOptions.builder()
|
||||
.defaultOptions(DeepSeekChatOptions.builder()
|
||||
.model(properties.getModel())
|
||||
.temperature(properties.getTemperature())
|
||||
.maxTokens(properties.getMaxTokens())
|
||||
|
@ -142,25 +183,30 @@ public class AiAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnProperty(value = "yudao.ai.xinghuo.enable", havingValue = "true")
|
||||
public XingHuoChatModel xingHuoChatClient(YudaoAiProperties yudaoAiProperties) {
|
||||
YudaoAiProperties.XingHuoProperties properties = yudaoAiProperties.getXinghuo();
|
||||
YudaoAiProperties.XingHuo properties = yudaoAiProperties.getXinghuo();
|
||||
return buildXingHuoChatClient(properties);
|
||||
}
|
||||
|
||||
public XingHuoChatModel buildXingHuoChatClient(YudaoAiProperties.XingHuoProperties properties) {
|
||||
public XingHuoChatModel buildXingHuoChatClient(YudaoAiProperties.XingHuo properties) {
|
||||
if (StrUtil.isEmpty(properties.getModel())) {
|
||||
properties.setModel(XingHuoChatModel.MODEL_DEFAULT);
|
||||
}
|
||||
OpenAiApi.Builder builder = OpenAiApi.builder()
|
||||
.baseUrl(XingHuoChatModel.BASE_URL_V1)
|
||||
.apiKey(properties.getAppKey() + ":" + properties.getSecretKey());
|
||||
if ("x1".equals(properties.getModel())) {
|
||||
builder.baseUrl(XingHuoChatModel.BASE_URL_V2)
|
||||
.completionsPath(XingHuoChatModel.BASE_COMPLETIONS_PATH_V2);
|
||||
}
|
||||
OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
|
||||
.openAiApi(OpenAiApi.builder()
|
||||
.baseUrl(XingHuoChatModel.BASE_URL)
|
||||
.apiKey(properties.getAppKey() + ":" + properties.getSecretKey())
|
||||
.build())
|
||||
.openAiApi(builder.build())
|
||||
.defaultOptions(OpenAiChatOptions.builder()
|
||||
.model(properties.getModel())
|
||||
.temperature(properties.getTemperature())
|
||||
.maxTokens(properties.getMaxTokens())
|
||||
.topP(properties.getTopP())
|
||||
.build())
|
||||
// TODO @芋艿:星火的 function call 有 bug,会报 ToolResponseMessage must have an id 错误!!!
|
||||
.toolCallingManager(getToolCallingManager())
|
||||
.build();
|
||||
return new XingHuoChatModel(openAiChatModel);
|
||||
|
@ -169,11 +215,11 @@ public class AiAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnProperty(value = "yudao.ai.baichuan.enable", havingValue = "true")
|
||||
public BaiChuanChatModel baiChuanChatClient(YudaoAiProperties yudaoAiProperties) {
|
||||
YudaoAiProperties.BaiChuanProperties properties = yudaoAiProperties.getBaichuan();
|
||||
YudaoAiProperties.BaiChuan properties = yudaoAiProperties.getBaichuan();
|
||||
return buildBaiChuanChatClient(properties);
|
||||
}
|
||||
|
||||
public BaiChuanChatModel buildBaiChuanChatClient(YudaoAiProperties.BaiChuanProperties properties) {
|
||||
public BaiChuanChatModel buildBaiChuanChatClient(YudaoAiProperties.BaiChuan properties) {
|
||||
if (StrUtil.isEmpty(properties.getModel())) {
|
||||
properties.setModel(BaiChuanChatModel.MODEL_DEFAULT);
|
||||
}
|
||||
|
@ -196,7 +242,7 @@ public class AiAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnProperty(value = "yudao.ai.midjourney.enable", havingValue = "true")
|
||||
public MidjourneyApi midjourneyApi(YudaoAiProperties yudaoAiProperties) {
|
||||
YudaoAiProperties.MidjourneyProperties config = yudaoAiProperties.getMidjourney();
|
||||
YudaoAiProperties.Midjourney config = yudaoAiProperties.getMidjourney();
|
||||
return new MidjourneyApi(config.getBaseUrl(), config.getApiKey(), config.getNotifyUrl());
|
||||
}
|
||||
|
||||
|
@ -222,4 +268,22 @@ public class AiAutoConfiguration {
|
|||
return SpringUtil.getBean(ToolCallingManager.class);
|
||||
}
|
||||
|
||||
// ========== Web Search 相关 ==========
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "yudao.ai.web-search.enable", havingValue = "true")
|
||||
public AiWebSearchClient webSearchClient(YudaoAiProperties yudaoAiProperties) {
|
||||
return new AiBoChaWebSearchClient(yudaoAiProperties.getWebSearch().getApiKey());
|
||||
}
|
||||
|
||||
// ========== MCP 相关 ==========
|
||||
|
||||
/**
|
||||
* 参考自 <a href="https://docs.spring.io/spring-ai/reference/api/mcp/mcp-client-boot-starter-docs.html">MCP Server Boot Starter</>
|
||||
*/
|
||||
@Bean
|
||||
public List<ToolCallback> toolCallbacks(PersonService personService) {
|
||||
return List.of(ToolCallbacks.from(personService));
|
||||
}
|
||||
|
||||
}
|
|
@ -13,49 +13,54 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||
@Data
|
||||
public class YudaoAiProperties {
|
||||
|
||||
/**
|
||||
* 谷歌 Gemini
|
||||
*/
|
||||
private Gemini gemini;
|
||||
|
||||
/**
|
||||
* 字节豆包
|
||||
*/
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
private DouBaoProperties doubao;
|
||||
private DouBao doubao;
|
||||
|
||||
/**
|
||||
* 腾讯混元
|
||||
*/
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
private HunYuanProperties hunyuan;
|
||||
private HunYuan hunyuan;
|
||||
|
||||
/**
|
||||
* 硅基流动
|
||||
*/
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
private SiliconFlowProperties siliconflow;
|
||||
private SiliconFlow siliconflow;
|
||||
|
||||
/**
|
||||
* 讯飞星火
|
||||
*/
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
private XingHuoProperties xinghuo;
|
||||
private XingHuo xinghuo;
|
||||
|
||||
/**
|
||||
* 百川
|
||||
*/
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
private BaiChuanProperties baichuan;
|
||||
private BaiChuan baichuan;
|
||||
|
||||
/**
|
||||
* Midjourney 绘图
|
||||
*/
|
||||
private MidjourneyProperties midjourney;
|
||||
private Midjourney midjourney;
|
||||
|
||||
/**
|
||||
* Suno 音乐
|
||||
*/
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
private SunoProperties suno;
|
||||
private Suno suno;
|
||||
|
||||
/**
|
||||
* 网络搜索
|
||||
*/
|
||||
private WebSearch webSearch;
|
||||
|
||||
@Data
|
||||
public static class DouBaoProperties {
|
||||
public static class Gemini {
|
||||
|
||||
private String enable;
|
||||
private String apiKey;
|
||||
|
@ -68,7 +73,20 @@ public class YudaoAiProperties {
|
|||
}
|
||||
|
||||
@Data
|
||||
public static class HunYuanProperties {
|
||||
public static class DouBao {
|
||||
|
||||
private String enable;
|
||||
private String apiKey;
|
||||
|
||||
private String model;
|
||||
private Double temperature;
|
||||
private Integer maxTokens;
|
||||
private Double topP;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class HunYuan {
|
||||
|
||||
private String enable;
|
||||
private String baseUrl;
|
||||
|
@ -82,7 +100,7 @@ public class YudaoAiProperties {
|
|||
}
|
||||
|
||||
@Data
|
||||
public static class SiliconFlowProperties {
|
||||
public static class SiliconFlow {
|
||||
|
||||
private String enable;
|
||||
private String apiKey;
|
||||
|
@ -95,7 +113,7 @@ public class YudaoAiProperties {
|
|||
}
|
||||
|
||||
@Data
|
||||
public static class XingHuoProperties {
|
||||
public static class XingHuo {
|
||||
|
||||
private String enable;
|
||||
private String appId;
|
||||
|
@ -110,7 +128,7 @@ public class YudaoAiProperties {
|
|||
}
|
||||
|
||||
@Data
|
||||
public static class BaiChuanProperties {
|
||||
public static class BaiChuan {
|
||||
|
||||
private String enable;
|
||||
private String apiKey;
|
||||
|
@ -123,7 +141,7 @@ public class YudaoAiProperties {
|
|||
}
|
||||
|
||||
@Data
|
||||
public static class MidjourneyProperties {
|
||||
public static class Midjourney {
|
||||
|
||||
private String enable;
|
||||
private String baseUrl;
|
||||
|
@ -134,12 +152,21 @@ public class YudaoAiProperties {
|
|||
}
|
||||
|
||||
@Data
|
||||
public static class SunoProperties {
|
||||
public static class Suno {
|
||||
|
||||
private boolean enable = false;
|
||||
private boolean enable;
|
||||
|
||||
private String baseUrl;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class WebSearch {
|
||||
|
||||
private boolean enable;
|
||||
|
||||
private String apiKey;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core;
|
||||
package cn.iocoder.yudao.module.ai.framework.ai.core.model;
|
||||
|
||||
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
|
@ -1,4 +1,4 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core;
|
||||
package cn.iocoder.yudao.module.ai.framework.ai.core.model;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
|
@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.ai.framework.ai.config.AiAutoConfiguration;
|
|||
import cn.iocoder.yudao.module.ai.framework.ai.config.YudaoAiProperties;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.gemini.GeminiChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowApiConstants;
|
||||
|
@ -67,6 +68,7 @@ import org.springframework.ai.minimax.MiniMaxChatOptions;
|
|||
import org.springframework.ai.minimax.MiniMaxEmbeddingModel;
|
||||
import org.springframework.ai.minimax.MiniMaxEmbeddingOptions;
|
||||
import org.springframework.ai.minimax.api.MiniMaxApi;
|
||||
import org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration;
|
||||
import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration;
|
||||
import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingAutoConfiguration;
|
||||
import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingProperties;
|
||||
|
@ -93,6 +95,8 @@ import org.springframework.ai.openai.OpenAiImageModel;
|
|||
import org.springframework.ai.openai.api.OpenAiApi;
|
||||
import org.springframework.ai.openai.api.OpenAiImageApi;
|
||||
import org.springframework.ai.openai.api.common.OpenAiApiConstants;
|
||||
import org.springframework.ai.anthropic.AnthropicChatModel;
|
||||
import org.springframework.ai.anthropic.api.AnthropicApi;
|
||||
import org.springframework.ai.stabilityai.StabilityAiImageModel;
|
||||
import org.springframework.ai.stabilityai.api.StabilityAiApi;
|
||||
import org.springframework.ai.vectorstore.SimpleVectorStore;
|
||||
|
@ -168,6 +172,10 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
return buildOpenAiChatModel(apiKey, url);
|
||||
case AZURE_OPENAI:
|
||||
return buildAzureOpenAiChatModel(apiKey, url);
|
||||
case ANTHROPIC:
|
||||
return buildAnthropicChatModel(apiKey, url);
|
||||
case GEMINI:
|
||||
return buildGeminiChatModel(apiKey);
|
||||
case OLLAMA:
|
||||
return buildOllamaChatModel(url);
|
||||
default:
|
||||
|
@ -206,6 +214,10 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
return SpringUtil.getBean(OpenAiChatModel.class);
|
||||
case AZURE_OPENAI:
|
||||
return SpringUtil.getBean(AzureOpenAiChatModel.class);
|
||||
case ANTHROPIC:
|
||||
return SpringUtil.getBean(AnthropicChatModel.class);
|
||||
case GEMINI:
|
||||
return SpringUtil.getBean(GeminiChatModel.class);
|
||||
case OLLAMA:
|
||||
return SpringUtil.getBean(OllamaChatModel.class);
|
||||
default:
|
||||
|
@ -260,7 +272,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
String cacheKey = buildClientCacheKey(MidjourneyApi.class, AiPlatformEnum.MIDJOURNEY.getPlatform(), apiKey,
|
||||
url);
|
||||
return Singleton.get(cacheKey, (Func0<MidjourneyApi>) () -> {
|
||||
YudaoAiProperties.MidjourneyProperties properties = SpringUtil.getBean(YudaoAiProperties.class)
|
||||
YudaoAiProperties.Midjourney properties = SpringUtil.getBean(YudaoAiProperties.class)
|
||||
.getMidjourney();
|
||||
return new MidjourneyApi(url, apiKey, properties.getNotifyUrl());
|
||||
});
|
||||
|
@ -347,7 +359,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
* 可参考 {@link DashScopeImageAutoConfiguration} 的 dashScopeImageModel 方法
|
||||
*/
|
||||
private static DashScopeImageModel buildTongYiImagesModel(String key) {
|
||||
DashScopeImageApi dashScopeImageApi = new DashScopeImageApi(key);
|
||||
DashScopeImageApi dashScopeImageApi = DashScopeImageApi.builder().apiKey(key).build();
|
||||
return DashScopeImageModel.builder()
|
||||
.dashScopeApi(dashScopeImageApi)
|
||||
.build();
|
||||
|
@ -397,7 +409,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
* 可参考 {@link AiAutoConfiguration#douBaoChatClient(YudaoAiProperties)}
|
||||
*/
|
||||
private ChatModel buildDouBaoChatModel(String apiKey) {
|
||||
YudaoAiProperties.DouBaoProperties properties = new YudaoAiProperties.DouBaoProperties()
|
||||
YudaoAiProperties.DouBao properties = new YudaoAiProperties.DouBao()
|
||||
.setApiKey(apiKey);
|
||||
return new AiAutoConfiguration().buildDouBaoChatClient(properties);
|
||||
}
|
||||
|
@ -406,7 +418,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
* 可参考 {@link AiAutoConfiguration#hunYuanChatClient(YudaoAiProperties)}
|
||||
*/
|
||||
private ChatModel buildHunYuanChatModel(String apiKey, String url) {
|
||||
YudaoAiProperties.HunYuanProperties properties = new YudaoAiProperties.HunYuanProperties()
|
||||
YudaoAiProperties.HunYuan properties = new YudaoAiProperties.HunYuan()
|
||||
.setBaseUrl(url).setApiKey(apiKey);
|
||||
return new AiAutoConfiguration().buildHunYuanChatClient(properties);
|
||||
}
|
||||
|
@ -415,7 +427,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
* 可参考 {@link AiAutoConfiguration#siliconFlowChatClient(YudaoAiProperties)}
|
||||
*/
|
||||
private ChatModel buildSiliconFlowChatModel(String apiKey) {
|
||||
YudaoAiProperties.SiliconFlowProperties properties = new YudaoAiProperties.SiliconFlowProperties()
|
||||
YudaoAiProperties.SiliconFlow properties = new YudaoAiProperties.SiliconFlow()
|
||||
.setApiKey(apiKey);
|
||||
return new AiAutoConfiguration().buildSiliconFlowChatClient(properties);
|
||||
}
|
||||
|
@ -473,7 +485,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
private static XingHuoChatModel buildXingHuoChatModel(String key) {
|
||||
List<String> keys = StrUtil.split(key, '|');
|
||||
Assert.equals(keys.size(), 2, "XingHuoChatClient 的密钥需要 (appKey|secretKey) 格式");
|
||||
YudaoAiProperties.XingHuoProperties properties = new YudaoAiProperties.XingHuoProperties()
|
||||
YudaoAiProperties.XingHuo properties = new YudaoAiProperties.XingHuo()
|
||||
.setAppKey(keys.get(0)).setSecretKey(keys.get(1));
|
||||
return new AiAutoConfiguration().buildXingHuoChatClient(properties);
|
||||
}
|
||||
|
@ -482,7 +494,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
* 可参考 {@link AiAutoConfiguration#baiChuanChatClient(YudaoAiProperties)}
|
||||
*/
|
||||
private BaiChuanChatModel buildBaiChuanChatModel(String apiKey) {
|
||||
YudaoAiProperties.BaiChuanProperties properties = new YudaoAiProperties.BaiChuanProperties()
|
||||
YudaoAiProperties.BaiChuan properties = new YudaoAiProperties.BaiChuan()
|
||||
.setApiKey(apiKey);
|
||||
return new AiAutoConfiguration().buildBaiChuanChatClient(properties);
|
||||
}
|
||||
|
@ -512,6 +524,30 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link AnthropicChatAutoConfiguration} 的 anthropicApi 方法
|
||||
*/
|
||||
private static AnthropicChatModel buildAnthropicChatModel(String apiKey, String url) {
|
||||
AnthropicApi.Builder builder = AnthropicApi.builder().apiKey(apiKey);
|
||||
if (StrUtil.isNotEmpty(url)) {
|
||||
builder.baseUrl(url);
|
||||
}
|
||||
AnthropicApi anthropicApi = builder.build();
|
||||
return AnthropicChatModel.builder()
|
||||
.anthropicApi(anthropicApi)
|
||||
.toolCallingManager(getToolCallingManager())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link AiAutoConfiguration#buildGeminiChatClient(YudaoAiProperties.Gemini)}
|
||||
*/
|
||||
private static GeminiChatModel buildGeminiChatModel(String apiKey) {
|
||||
YudaoAiProperties.Gemini properties = SpringUtil.getBean(YudaoAiProperties.class)
|
||||
.getGemini().setApiKey(apiKey);
|
||||
return new AiAutoConfiguration().buildGeminiChatClient(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link OpenAiImageAutoConfiguration} 的 openAiImageModel 方法
|
||||
*/
|
|
@ -6,7 +6,6 @@ import org.springframework.ai.chat.model.ChatModel;
|
|||
import org.springframework.ai.chat.model.ChatResponse;
|
||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||
import org.springframework.ai.chat.prompt.Prompt;
|
||||
import org.springframework.ai.openai.OpenAiChatModel;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
|
@ -19,13 +18,14 @@ import reactor.core.publisher.Flux;
|
|||
public class DouBaoChatModel implements ChatModel {
|
||||
|
||||
public static final String BASE_URL = "https://ark.cn-beijing.volces.com/api";
|
||||
public static final String COMPLETE_PATH = "/v3/chat/completions";
|
||||
|
||||
public static final String MODEL_DEFAULT = "doubao-1-5-lite-32k-250115";
|
||||
|
||||
/**
|
||||
* 兼容 OpenAI 接口,进行复用
|
||||
*/
|
||||
private final OpenAiChatModel openAiChatModel;
|
||||
private final ChatModel openAiChatModel;
|
||||
|
||||
@Override
|
||||
public ChatResponse call(Prompt prompt) {
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.gemini;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.ai.chat.model.ChatModel;
|
||||
import org.springframework.ai.chat.model.ChatResponse;
|
||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||
import org.springframework.ai.chat.prompt.Prompt;
|
||||
import org.springframework.ai.openai.OpenAiChatModel;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* 谷歌 Gemini {@link ChatModel} 实现类,基于 Google AI Studio 提供的 <a href="https://ai.google.dev/gemini-api/docs/openai">OpenAI 兼容方案</a>
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class GeminiChatModel implements ChatModel {
|
||||
|
||||
public static final String BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/";
|
||||
public static final String COMPLETE_PATH = "/chat/completions";
|
||||
|
||||
public static final String MODEL_DEFAULT = "gemini-2.5-flash";
|
||||
|
||||
/**
|
||||
* 兼容 OpenAI 接口,进行复用
|
||||
*/
|
||||
private final OpenAiChatModel openAiChatModel;
|
||||
|
||||
@Override
|
||||
public ChatResponse call(Prompt prompt) {
|
||||
return openAiChatModel.call(prompt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<ChatResponse> stream(Prompt prompt) {
|
||||
return openAiChatModel.stream(prompt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatOptions getDefaultOptions() {
|
||||
return openAiChatModel.getDefaultOptions();
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,6 @@ import org.springframework.ai.chat.model.ChatModel;
|
|||
import org.springframework.ai.chat.model.ChatResponse;
|
||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||
import org.springframework.ai.chat.prompt.Prompt;
|
||||
import org.springframework.ai.openai.OpenAiChatModel;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
|
@ -22,6 +21,7 @@ import reactor.core.publisher.Flux;
|
|||
public class HunYuanChatModel implements ChatModel {
|
||||
|
||||
public static final String BASE_URL = "https://api.hunyuan.cloud.tencent.com";
|
||||
public static final String COMPLETE_PATH = "/v1/chat/completions";
|
||||
|
||||
public static final String MODEL_DEFAULT = "hunyuan-turbo";
|
||||
|
||||
|
@ -32,7 +32,7 @@ public class HunYuanChatModel implements ChatModel {
|
|||
/**
|
||||
* 兼容 OpenAI 接口,进行复用
|
||||
*/
|
||||
private final OpenAiChatModel openAiChatModel;
|
||||
private final ChatModel openAiChatModel;
|
||||
|
||||
@Override
|
||||
public ChatResponse call(Prompt prompt) {
|
||||
|
|
|
@ -23,7 +23,7 @@ public class SiliconFlowChatModel implements ChatModel {
|
|||
/**
|
||||
* 兼容 OpenAI 接口,进行复用
|
||||
*/
|
||||
private final OpenAiChatModel openAiChatModel;
|
||||
private final ChatModel openAiChatModel;
|
||||
|
||||
@Override
|
||||
public ChatResponse call(Prompt prompt) {
|
||||
|
|
|
@ -6,7 +6,6 @@ import org.springframework.ai.chat.model.ChatModel;
|
|||
import org.springframework.ai.chat.model.ChatResponse;
|
||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||
import org.springframework.ai.chat.prompt.Prompt;
|
||||
import org.springframework.ai.openai.OpenAiChatModel;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
|
@ -18,28 +17,34 @@ import reactor.core.publisher.Flux;
|
|||
@RequiredArgsConstructor
|
||||
public class XingHuoChatModel implements ChatModel {
|
||||
|
||||
public static final String BASE_URL = "https://spark-api-open.xf-yun.com";
|
||||
public static final String BASE_URL_V1 = "https://spark-api-open.xf-yun.com";
|
||||
|
||||
public static final String MODEL_DEFAULT = "generalv3.5";
|
||||
public static final String BASE_URL_V2 = "https://spark-api-open.xf-yun.com";
|
||||
public static final String BASE_COMPLETIONS_PATH_V2 = "/v2/chat/completions";
|
||||
|
||||
/**
|
||||
* 兼容 OpenAI 接口,进行复用
|
||||
* 已知模型名列表:x1、4.0Ultra、generalv3.5、max-32k、generalv3、pro-128k、lite
|
||||
*/
|
||||
private final OpenAiChatModel openAiChatModel;
|
||||
public static final String MODEL_DEFAULT = "4.0Ultra";
|
||||
|
||||
/**
|
||||
* v1 兼容 OpenAI 接口,进行复用
|
||||
*/
|
||||
private final ChatModel openAiChatModelV1;
|
||||
|
||||
@Override
|
||||
public ChatResponse call(Prompt prompt) {
|
||||
return openAiChatModel.call(prompt);
|
||||
return openAiChatModelV1.call(prompt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<ChatResponse> stream(Prompt prompt) {
|
||||
return openAiChatModel.stream(prompt);
|
||||
return openAiChatModelV1.stream(prompt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatOptions getDefaultOptions() {
|
||||
return openAiChatModel.getDefaultOptions();
|
||||
return openAiChatModelV1.getDefaultOptions();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core.webserch;
|
||||
|
||||
/**
|
||||
* 网络搜索客户端接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface AiWebSearchClient {
|
||||
|
||||
/**
|
||||
* 网页搜索
|
||||
*
|
||||
* @param request 搜索请求
|
||||
* @return 搜索结果
|
||||
*/
|
||||
AiWebSearchResponse search(AiWebSearchRequest request);
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core.webserch;
|
||||
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AiWebSearchRequest {
|
||||
|
||||
/**
|
||||
* 用户的搜索词
|
||||
*/
|
||||
@NotEmpty(message = "搜索词不能为空")
|
||||
private String query;
|
||||
|
||||
/**
|
||||
* 是否显示文本摘要
|
||||
*
|
||||
* true - 显示
|
||||
* false - 不显示(默认)
|
||||
*/
|
||||
private Boolean summary;
|
||||
|
||||
/**
|
||||
* 返回结果的条数
|
||||
*/
|
||||
@NotNull(message = "返回结果条数不能为空")
|
||||
@Min(message = "返回结果条数最小为 1", value = 1)
|
||||
@Max(message = "返回结果条数最大为 50", value = 50)
|
||||
private Integer count;
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core.webserch;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class AiWebSearchResponse {
|
||||
|
||||
/**
|
||||
* 总数(总共匹配的网页数)
|
||||
*/
|
||||
private Long total;
|
||||
|
||||
/**
|
||||
* 数据列表
|
||||
*/
|
||||
private List<WebPage> lists;
|
||||
|
||||
/**
|
||||
* 网页对象
|
||||
*/
|
||||
@Data
|
||||
public static class WebPage {
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*
|
||||
* 例如说:搜狐网
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 图标
|
||||
*/
|
||||
private String icon;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*
|
||||
* 例如说:186页|阿里巴巴:2024年环境、社会和治理(ESG)报告
|
||||
*/
|
||||
private String title;
|
||||
/**
|
||||
* URL
|
||||
*
|
||||
* 例如说:https://m.sohu.com/a/815036254_121819701/?pvid=000115_3w_a
|
||||
*/
|
||||
@SuppressWarnings("JavadocLinkAsPlainText")
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 内容的简短描述
|
||||
*/
|
||||
private String snippet;
|
||||
/**
|
||||
* 内容的文本摘要
|
||||
*/
|
||||
private String summary;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core.webserch.bocha;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchClient;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchRequest;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchResponse;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
/**
|
||||
* 博查 {@link AiWebSearchClient} 实现类
|
||||
*
|
||||
* @see <a href="https://open.bochaai.com/overview">博查 AI 开放平台</a>
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Slf4j
|
||||
public class AiBoChaWebSearchClient implements AiWebSearchClient {
|
||||
|
||||
public static final String BASE_URL = "https://api.bochaai.com";
|
||||
private static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
private static final String BEARER_PREFIX = "Bearer ";
|
||||
|
||||
private final WebClient webClient;
|
||||
|
||||
private final Predicate<HttpStatusCode> STATUS_PREDICATE = status -> !status.is2xxSuccessful();
|
||||
|
||||
private final Function<Object, Function<ClientResponse, Mono<? extends Throwable>>> EXCEPTION_FUNCTION =
|
||||
reqParam -> response -> response.bodyToMono(String.class).handle((responseBody, sink) -> {
|
||||
log.error("[AiBoChaWebSearchClient] 调用失败!请求参数:[{}],响应数据: [{}]", reqParam, responseBody);
|
||||
sink.error(new IllegalStateException("[AiBoChaWebSearchClient] 调用失败!"));
|
||||
});
|
||||
|
||||
public AiBoChaWebSearchClient(String apiKey) {
|
||||
this.webClient = WebClient.builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.defaultHeaders((headers) -> {
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.add(AUTHORIZATION_HEADER, BEARER_PREFIX + apiKey);
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiWebSearchResponse search(AiWebSearchRequest request) {
|
||||
// 转换请求参数
|
||||
WebSearchRequest webSearchRequest = new WebSearchRequest(
|
||||
request.getQuery(),
|
||||
request.getSummary(),
|
||||
request.getCount()
|
||||
);
|
||||
// 调用博查 API
|
||||
CommonResult<WebSearchResponse> response = this.webClient.post()
|
||||
.uri("/v1/web-search")
|
||||
.bodyValue(webSearchRequest)
|
||||
.retrieve()
|
||||
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(webSearchRequest))
|
||||
.bodyToMono(new ParameterizedTypeReference<CommonResult<WebSearchResponse>>() {})
|
||||
.block();
|
||||
if (response == null) {
|
||||
throw new IllegalStateException("[search][搜索结果为空]");
|
||||
}
|
||||
if (response.getData() == null) {
|
||||
throw new IllegalStateException(String.format("[search][搜索失败,code = %s, msg = %s]",
|
||||
response.getCode(), response.getMsg()));
|
||||
}
|
||||
WebSearchResponse data = response.getData();
|
||||
|
||||
// 转换结果
|
||||
AiWebSearchResponse result = new AiWebSearchResponse();
|
||||
if (data.webPages() == null || CollUtil.isEmpty(data.webPages().value())) {
|
||||
return result.setTotal(0L).setLists(List.of());
|
||||
}
|
||||
return result.setTotal(data.webPages().totalEstimatedMatches())
|
||||
.setLists(convertList(data.webPages().value(), page -> new AiWebSearchResponse.WebPage()
|
||||
.setName(page.siteName()).setIcon(page.siteIcon())
|
||||
.setTitle(page.name()).setUrl(page.url())
|
||||
.setSnippet(page.snippet()).setSummary(page.summary())));
|
||||
}
|
||||
|
||||
/**
|
||||
* 网页搜索请求参数
|
||||
*/
|
||||
@JsonInclude(value = JsonInclude.Include.NON_NULL)
|
||||
public record WebSearchRequest(
|
||||
String query,
|
||||
Boolean summary,
|
||||
Integer count
|
||||
) {
|
||||
public WebSearchRequest {
|
||||
Assert.notBlank(query, "query 不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 网页搜索响应
|
||||
*/
|
||||
@JsonInclude(value = JsonInclude.Include.NON_NULL)
|
||||
public record WebSearchResponse(
|
||||
WebSearchWebPages webPages
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 网页搜索结果
|
||||
*/
|
||||
@JsonInclude(value = JsonInclude.Include.NON_NULL)
|
||||
public record WebSearchWebPages(
|
||||
String webSearchUrl,
|
||||
Long totalEstimatedMatches,
|
||||
List<WebPageValue> value,
|
||||
Boolean someResultsRemoved
|
||||
) {
|
||||
|
||||
/**
|
||||
* 网页结果值
|
||||
*/
|
||||
@JsonInclude(value = JsonInclude.Include.NON_NULL)
|
||||
public record WebPageValue(
|
||||
String id,
|
||||
String name,
|
||||
String url,
|
||||
String displayUrl,
|
||||
String snippet,
|
||||
String summary,
|
||||
String siteName,
|
||||
String siteIcon,
|
||||
String datePublished,
|
||||
String dateLastCrawled,
|
||||
String cachedPageUrl,
|
||||
String language,
|
||||
Boolean isFamilyFriendly,
|
||||
Boolean isNavigational
|
||||
) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -2,17 +2,24 @@ package cn.iocoder.yudao.module.ai.framework.security.config;
|
|||
|
||||
import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
|
||||
import cn.iocoder.yudao.module.infra.enums.ApiConstants;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.ai.mcp.server.autoconfigure.McpServerProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* AI 模块的 Security 配置
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false, value = "aiSecurityConfiguration")
|
||||
public class SecurityConfiguration {
|
||||
|
||||
@Resource
|
||||
private Optional<McpServerProperties> serverProperties;
|
||||
|
||||
@Bean("aiAuthorizeRequestsCustomizer")
|
||||
public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {
|
||||
return new AuthorizeRequestsCustomizer() {
|
||||
|
@ -33,6 +40,12 @@ public class SecurityConfiguration {
|
|||
// TODO 芋艿:这个每个项目都需要重复配置,得捉摸有没通用的方案
|
||||
// RPC 服务的安全配置
|
||||
registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll();
|
||||
|
||||
// MCP Server
|
||||
serverProperties.ifPresent(properties -> {
|
||||
registry.requestMatchers(properties.getSseEndpoint()).permitAll();
|
||||
registry.requestMatchers(properties.getSseMessageEndpoint()).permitAll();
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package cn.iocoder.yudao.module.ai.service.chat;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.file.FileNameUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
||||
import cn.iocoder.yudao.module.ai.util.AiUtils;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
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;
|
||||
|
@ -21,6 +22,10 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
|
|||
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiToolDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper;
|
||||
import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants;
|
||||
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchClient;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchRequest;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchResponse;
|
||||
import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService;
|
||||
import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeSegmentService;
|
||||
import cn.iocoder.yudao.module.ai.service.knowledge.bo.AiKnowledgeSegmentSearchReqBO;
|
||||
|
@ -28,7 +33,11 @@ import cn.iocoder.yudao.module.ai.service.knowledge.bo.AiKnowledgeSegmentSearchR
|
|||
import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
|
||||
import cn.iocoder.yudao.module.ai.service.model.AiModelService;
|
||||
import cn.iocoder.yudao.module.ai.service.model.AiToolService;
|
||||
import javax.annotation.Resource;
|
||||
import cn.iocoder.yudao.module.ai.util.AiUtils;
|
||||
import cn.iocoder.yudao.module.ai.util.FileTypeUtils;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.modelcontextprotocol.client.McpSyncClient;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
import org.springframework.ai.chat.messages.MessageType;
|
||||
|
@ -39,6 +48,11 @@ import org.springframework.ai.chat.model.ChatResponse;
|
|||
import org.springframework.ai.chat.model.StreamingChatModel;
|
||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||
import org.springframework.ai.chat.prompt.Prompt;
|
||||
import org.springframework.ai.mcp.SyncMcpToolCallbackProvider;
|
||||
import org.springframework.ai.mcp.client.autoconfigure.properties.McpClientCommonProperties;
|
||||
import org.springframework.ai.tool.ToolCallback;
|
||||
import org.springframework.ai.tool.resolution.ToolCallbackResolver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
@ -64,6 +78,13 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_MESSAGE_N
|
|||
@Slf4j
|
||||
public class AiChatMessageServiceImpl implements AiChatMessageService {
|
||||
|
||||
/**
|
||||
* 联网搜索的结束数
|
||||
*/
|
||||
private static final Integer WEB_SEARCH_COUNT = 10;
|
||||
|
||||
// TODO @芋艿:后续优化下对话的 Prompt 整体结构
|
||||
|
||||
/**
|
||||
* 知识库转 {@link UserMessage} 的内容模版
|
||||
*/
|
||||
|
@ -71,6 +92,18 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|||
"%s\n\n" + // 多个 <Reference></Reference> 的拼接
|
||||
"回答要求:\n- 避免提及你是从 <Reference></Reference> 获取的知识。";
|
||||
|
||||
private static final String WEB_SEARCH_USER_MESSAGE_TEMPLATE = "使用 <WebSearch></WebSearch> 标记中的内容作为本次对话的参考:\n\n" +
|
||||
"%s\n\n" + // 多个 <WebSearch></WebSearch> 的拼接
|
||||
"回答要求:\n- 避免提及你是从 <WebSearch></WebSearch> 获取的知识。";
|
||||
|
||||
/**
|
||||
* 附件转 ${@link UserMessage} 的内容模版
|
||||
*/
|
||||
@SuppressWarnings("TextBlockMigration")
|
||||
private static final String Attachment_USER_MESSAGE_TEMPLATE = "使用 <Attachment></Attachment> 标记用户对话上传的附件内容:\n\n" +
|
||||
"%s\n\n" + // 多个 <Attachment></Attachment> 的拼接
|
||||
"回答要求:\n- 避免提及 <Attachment></Attachment> 附件的编码格式。";
|
||||
|
||||
@Resource
|
||||
private AiChatMessageMapper chatMessageMapper;
|
||||
|
||||
|
@ -87,6 +120,21 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|||
@Resource
|
||||
private AiToolService toolService;
|
||||
|
||||
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
|
||||
@Autowired(required = false) // 由于 yudao.ai.web-search.enable 配置项,可以关闭 AiWebSearchClient 的功能,所以这里只能不强制注入
|
||||
private AiWebSearchClient webSearchClient;
|
||||
|
||||
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
|
||||
@Autowired(required = false) // 由于 yudao.ai.mcp.client.enable 配置项,可以关闭 McpSyncClient 的功能,所以这里只能不强制注入
|
||||
private List<McpSyncClient> mcpClients;
|
||||
|
||||
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
|
||||
@Autowired(required = false) // 由于 yudao.ai.mcp.client.enable 配置项,可以关闭 McpSyncClient 的功能,所以这里只能不强制注入
|
||||
private McpClientCommonProperties mcpClientCommonProperties;
|
||||
|
||||
@Resource
|
||||
private ToolCallbackResolver toolCallbackResolver;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AiChatMessageSendRespVO sendMessage(AiChatMessageSendReqVO sendReqVO, Long userId) {
|
||||
// 1.1 校验对话存在
|
||||
|
@ -100,27 +148,35 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|||
AiModelDO model = modalService.validateModel(conversation.getModelId());
|
||||
ChatModel chatModel = modalService.getChatModel(model.getId());
|
||||
|
||||
// 2. 知识库找回
|
||||
List<AiKnowledgeSegmentSearchRespBO> knowledgeSegments = recallKnowledgeSegment(sendReqVO.getContent(), conversation);
|
||||
// 2.1 知识库召回
|
||||
List<AiKnowledgeSegmentSearchRespBO> knowledgeSegments = recallKnowledgeSegment(
|
||||
sendReqVO.getContent(), conversation);
|
||||
|
||||
// 2.2 联网搜索
|
||||
AiWebSearchResponse webSearchResponse = Boolean.TRUE.equals(sendReqVO.getUseSearch()) && webSearchClient != null ?
|
||||
webSearchClient.search(new AiWebSearchRequest().setQuery(sendReqVO.getContent())
|
||||
.setSummary(true).setCount(WEB_SEARCH_COUNT)) : null;
|
||||
|
||||
// 3. 插入 user 发送消息
|
||||
AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
|
||||
userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext(),
|
||||
null);
|
||||
null, sendReqVO.getAttachmentUrls(), null);
|
||||
|
||||
// 3.1 插入 assistant 接收消息
|
||||
// 4.1 插入 assistant 接收消息
|
||||
AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model,
|
||||
userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext(),
|
||||
knowledgeSegments);
|
||||
knowledgeSegments, null, webSearchResponse);
|
||||
|
||||
// 3.2 创建 chat 需要的 Prompt
|
||||
Prompt prompt = buildPrompt(conversation, historyMessages, knowledgeSegments, model, sendReqVO);
|
||||
// 4.2 创建 chat 需要的 Prompt
|
||||
Prompt prompt = buildPrompt(conversation, historyMessages, knowledgeSegments, webSearchResponse, model, sendReqVO);
|
||||
ChatResponse chatResponse = chatModel.call(prompt);
|
||||
|
||||
// 3.3 更新响应内容
|
||||
String newContent = chatResponse.getResult().getOutput().getText();
|
||||
chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(newContent));
|
||||
// 3.4 响应结果
|
||||
// 4.3 更新响应内容
|
||||
String newContent = AiUtils.getChatResponseContent(chatResponse);
|
||||
String newReasoningContent = AiUtils.getChatResponseReasoningContent(chatResponse);
|
||||
chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId())
|
||||
.setContent(newContent).setReasoningContent(newReasoningContent));
|
||||
// 4.4 响应结果
|
||||
Map<Long, AiKnowledgeDocumentDO> documentMap = knowledgeDocumentService.getKnowledgeDocumentMap(
|
||||
convertSet(knowledgeSegments, AiKnowledgeSegmentSearchRespBO::getDocumentId));
|
||||
List<AiChatMessageRespVO.KnowledgeSegment> segments = BeanUtils.toBean(knowledgeSegments,
|
||||
|
@ -131,7 +187,8 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|||
return new AiChatMessageSendRespVO()
|
||||
.setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class))
|
||||
.setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class)
|
||||
.setContent(newContent).setSegments(segments));
|
||||
.setContent(newContent).setSegments(segments)
|
||||
.setWebSearchPages(webSearchResponse != null ? webSearchResponse.getLists() : null));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -148,29 +205,36 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|||
AiModelDO model = modalService.validateModel(conversation.getModelId());
|
||||
StreamingChatModel chatModel = modalService.getChatModel(model.getId());
|
||||
|
||||
// 2. 知识库找回
|
||||
List<AiKnowledgeSegmentSearchRespBO> knowledgeSegments = recallKnowledgeSegment(sendReqVO.getContent(),
|
||||
conversation);
|
||||
// 2.1 知识库找回
|
||||
List<AiKnowledgeSegmentSearchRespBO> knowledgeSegments = recallKnowledgeSegment(
|
||||
sendReqVO.getContent(), conversation);
|
||||
|
||||
// 2.2 联网搜索
|
||||
AiWebSearchResponse webSearchResponse = Boolean.TRUE.equals(sendReqVO.getUseSearch()) && webSearchClient != null ?
|
||||
webSearchClient.search(new AiWebSearchRequest().setQuery(sendReqVO.getContent())
|
||||
.setSummary(true).setCount(WEB_SEARCH_COUNT)) : null;
|
||||
|
||||
// 3. 插入 user 发送消息
|
||||
AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
|
||||
userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext(),
|
||||
null);
|
||||
null, sendReqVO.getAttachmentUrls(), null);
|
||||
|
||||
// 4.1 插入 assistant 接收消息
|
||||
AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model,
|
||||
userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext(),
|
||||
knowledgeSegments);
|
||||
knowledgeSegments, null, webSearchResponse);
|
||||
|
||||
// 4.2 构建 Prompt,并进行调用
|
||||
Prompt prompt = buildPrompt(conversation, historyMessages, knowledgeSegments, model, sendReqVO);
|
||||
Prompt prompt = buildPrompt(conversation, historyMessages, knowledgeSegments, webSearchResponse, model, sendReqVO);
|
||||
Flux<ChatResponse> streamResponse = chatModel.stream(prompt);
|
||||
|
||||
// 4.3 流式返回
|
||||
StringBuffer contentBuffer = new StringBuffer();
|
||||
StringBuffer reasoningContentBuffer = new StringBuffer();
|
||||
return streamResponse.map(chunk -> {
|
||||
// 处理知识库的返回,只有首次才有
|
||||
// 仅首次:返回知识库、联网搜索
|
||||
List<AiChatMessageRespVO.KnowledgeSegment> segments = null;
|
||||
List<AiWebSearchResponse.WebPage> webSearchPages = null;
|
||||
if (StrUtil.isEmpty(contentBuffer)) {
|
||||
Map<Long, AiKnowledgeDocumentDO> documentMap = TenantUtils.executeIgnore(() ->
|
||||
knowledgeDocumentService.getKnowledgeDocumentMap(
|
||||
|
@ -179,24 +243,56 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|||
AiKnowledgeDocumentDO document = documentMap.get(segment.getDocumentId());
|
||||
segment.setDocumentName(document != null ? document.getName() : null);
|
||||
});
|
||||
if (webSearchResponse != null) {
|
||||
webSearchPages = webSearchResponse.getLists();
|
||||
}
|
||||
}
|
||||
// 响应结果
|
||||
String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getText() : null;
|
||||
newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况
|
||||
contentBuffer.append(newContent);
|
||||
String newContent = AiUtils.getChatResponseContent(chunk);
|
||||
String newReasoningContent = AiUtils.getChatResponseReasoningContent(chunk);
|
||||
if (StrUtil.isNotEmpty(newContent)) {
|
||||
contentBuffer.append(newContent);
|
||||
}
|
||||
if (StrUtil.isNotEmpty(newReasoningContent)) {
|
||||
reasoningContentBuffer.append(newReasoningContent);
|
||||
}
|
||||
return success(new AiChatMessageSendRespVO()
|
||||
.setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class))
|
||||
.setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class)
|
||||
.setContent(newContent).setSegments(segments)));
|
||||
.setContent(StrUtil.nullToDefault(newContent, "")) // 避免 null 的 情况
|
||||
.setReasoningContent(StrUtil.nullToDefault(newReasoningContent, "")) // 避免 null 的 情况
|
||||
.setSegments(segments).setWebSearchPages(webSearchPages))); // 知识库 + 联网搜索
|
||||
}).doOnComplete(() -> {
|
||||
// 忽略租户,因为 Flux 异步无法透传租户
|
||||
TenantUtils.executeIgnore(() -> chatMessageMapper.updateById(
|
||||
new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())));
|
||||
new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())
|
||||
.setReasoningContent(reasoningContentBuffer.toString())));
|
||||
}).doOnError(throwable -> {
|
||||
log.error("[sendChatMessageStream][userId({}) sendReqVO({}) 发生异常]", userId, sendReqVO, throwable);
|
||||
// 忽略租户,因为 Flux 异步无法透传租户
|
||||
TenantUtils.executeIgnore(() -> chatMessageMapper.updateById(
|
||||
new AiChatMessageDO().setId(assistantMessage.getId()).setContent(throwable.getMessage())));
|
||||
TenantUtils.executeIgnore(() -> {
|
||||
// 如果有内容,则更新内容
|
||||
if (StrUtil.isNotEmpty(contentBuffer)) {
|
||||
chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId())
|
||||
.setContent(contentBuffer.toString()).setReasoningContent(reasoningContentBuffer.toString()));
|
||||
} else {
|
||||
// 否则,则进行删除
|
||||
chatMessageMapper.deleteById(assistantMessage.getId());
|
||||
}
|
||||
});
|
||||
}).doOnCancel(() -> {
|
||||
log.info("[sendChatMessageStream][userId({}) sendReqVO({}) 取消请求]", userId, sendReqVO);
|
||||
// 忽略租户,因为 Flux 异步无法透传租户
|
||||
TenantUtils.executeIgnore(() -> {
|
||||
// 如果有内容,则更新内容
|
||||
if (StrUtil.isNotEmpty(contentBuffer)) {
|
||||
chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId())
|
||||
.setContent(contentBuffer.toString()).setReasoningContent(reasoningContentBuffer.toString()));
|
||||
} else {
|
||||
// 否则,则进行删除
|
||||
chatMessageMapper.deleteById(assistantMessage.getId());
|
||||
}
|
||||
});
|
||||
}).onErrorResume(error -> Flux.just(error(ErrorCodeConstants.CHAT_STREAM_ERROR)));
|
||||
}
|
||||
|
||||
|
@ -211,7 +307,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 2. 遍历找回
|
||||
// 2. 遍历召回
|
||||
List<AiKnowledgeSegmentSearchRespBO> knowledgeSegments = new ArrayList<>();
|
||||
for (Long knowledgeId : role.getKnowledgeIds()) {
|
||||
knowledgeSegments.addAll(knowledgeSegmentService.searchKnowledgeSegment(new AiKnowledgeSegmentSearchReqBO()
|
||||
|
@ -222,6 +318,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|||
|
||||
private Prompt buildPrompt(AiChatConversationDO conversation, List<AiChatMessageDO> messages,
|
||||
List<AiKnowledgeSegmentSearchRespBO> knowledgeSegments,
|
||||
AiWebSearchResponse webSearchResponse,
|
||||
AiModelDO model, AiChatMessageSendReqVO sendReqVO) {
|
||||
List<Message> chatMessages = new ArrayList<>();
|
||||
// 1.1 System Context 角色设定
|
||||
|
@ -231,8 +328,14 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|||
|
||||
// 1.2 历史 history message 历史消息
|
||||
List<AiChatMessageDO> contextMessages = filterContextMessages(messages, conversation, sendReqVO);
|
||||
contextMessages
|
||||
.forEach(message -> chatMessages.add(AiUtils.buildMessage(message.getType(), message.getContent())));
|
||||
contextMessages.forEach(message -> {
|
||||
chatMessages.add(AiUtils.buildMessage(message.getType(), message.getContent()));
|
||||
UserMessage attachmentUserMessage = buildAttachmentUserMessage(message.getAttachmentUrls());
|
||||
if (attachmentUserMessage != null) {
|
||||
chatMessages.add(attachmentUserMessage);
|
||||
}
|
||||
// TODO @芋艿:历史的知识库;历史的搜索,要不要拼接?
|
||||
});
|
||||
|
||||
// 1.3 当前 user message 新发送消息
|
||||
chatMessages.add(new UserMessage(sendReqVO.getContent()));
|
||||
|
@ -245,23 +348,76 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|||
chatMessages.add(new UserMessage(String.format(KNOWLEDGE_USER_MESSAGE_TEMPLATE, reference)));
|
||||
}
|
||||
|
||||
// 2.1 查询 tool 工具
|
||||
Set<String> toolNames = null;
|
||||
Map<String,Object> toolContext = Map.of();
|
||||
if (conversation.getRoleId() != null) {
|
||||
AiChatRoleDO chatRole = chatRoleService.getChatRole(conversation.getRoleId());
|
||||
if (chatRole != null && CollUtil.isNotEmpty(chatRole.getToolIds())) {
|
||||
toolNames = convertSet(toolService.getToolList(chatRole.getToolIds()), AiToolDO::getName);
|
||||
toolContext = AiUtils.buildCommonToolContext();
|
||||
// 1.5 联网搜索,通过 UserMessage 实现
|
||||
if (webSearchResponse != null && CollUtil.isNotEmpty(webSearchResponse.getLists())) {
|
||||
String webSearch = webSearchResponse.getLists().stream()
|
||||
.map(page -> {
|
||||
String summary = StrUtil.isNotEmpty(page.getSummary()) ?
|
||||
"\nSummary: " + page.getSummary() : "";
|
||||
return "<WebSearch title=\"" + page.getTitle() + "\" url=\"" + page.getUrl() + "\">"
|
||||
+ StrUtil.blankToDefault(page.getSummary(), page.getSnippet()) + "</WebSearch>";
|
||||
})
|
||||
.collect(Collectors.joining("\n\n"));
|
||||
chatMessages.add(new UserMessage(String.format(WEB_SEARCH_USER_MESSAGE_TEMPLATE, webSearch)));
|
||||
}
|
||||
|
||||
// 1.6 附件,通过 UserMessage 实现
|
||||
if (CollUtil.isNotEmpty(sendReqVO.getAttachmentUrls())) {
|
||||
UserMessage attachmentUserMessage = buildAttachmentUserMessage(sendReqVO.getAttachmentUrls());
|
||||
if (attachmentUserMessage != null) {
|
||||
chatMessages.add(attachmentUserMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// 2.1 查询 tool 工具
|
||||
List<ToolCallback> toolCallbacks = getToolCallbackListByRoleId(conversation.getRoleId());
|
||||
Map<String,Object> toolContext = CollUtil.isNotEmpty(toolCallbacks) ? AiUtils.buildCommonToolContext()
|
||||
: Map.of();
|
||||
// 2.2 构建 ChatOptions 对象
|
||||
AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform());
|
||||
ChatOptions chatOptions = AiUtils.buildChatOptions(platform, model.getModel(),
|
||||
conversation.getTemperature(), conversation.getMaxTokens(), toolNames, toolContext);
|
||||
conversation.getTemperature(), conversation.getMaxTokens(),
|
||||
toolCallbacks, toolContext);
|
||||
return new Prompt(chatMessages, chatOptions);
|
||||
}
|
||||
|
||||
private List<ToolCallback> getToolCallbackListByRoleId(Long roleId) {
|
||||
if (roleId == null) {
|
||||
return null;
|
||||
}
|
||||
AiChatRoleDO chatRole = chatRoleService.getChatRole(roleId);
|
||||
if (chatRole == null) {
|
||||
return null;
|
||||
}
|
||||
List<ToolCallback> toolCallbacks = new ArrayList<>();
|
||||
// 1. 通过 toolIds
|
||||
if (CollUtil.isNotEmpty(chatRole.getToolIds())) {
|
||||
Set<String> toolNames = convertSet(toolService.getToolList(chatRole.getToolIds()), AiToolDO::getName);
|
||||
toolNames.forEach(toolName -> {
|
||||
ToolCallback toolCallback = toolCallbackResolver.resolve(toolName);
|
||||
if (toolCallback != null) {
|
||||
toolCallbacks.add(toolCallback);
|
||||
}
|
||||
});
|
||||
}
|
||||
// 2. 通过 mcpClients
|
||||
if (CollUtil.isNotEmpty(mcpClients) && CollUtil.isNotEmpty(chatRole.getMcpClientNames())) {
|
||||
chatRole.getMcpClientNames().forEach(mcpClientName -> {
|
||||
// 2.1 标准化名字,参考 McpClientAutoConfiguration 的 connectedClientName 方法
|
||||
String finalMcpClientName = mcpClientCommonProperties.getName() + " - " + mcpClientName;
|
||||
// 2.2 匹配对应的 McpSyncClient
|
||||
mcpClients.forEach(mcpClient -> {
|
||||
if (ObjUtil.notEqual(mcpClient.getClientInfo().name(), finalMcpClientName)) {
|
||||
return;
|
||||
}
|
||||
ToolCallback[] mcpToolCallBacks = new SyncMcpToolCallbackProvider(mcpClient).getToolCallbacks();
|
||||
CollUtil.addAll(toolCallbacks, mcpToolCallBacks);
|
||||
});
|
||||
});
|
||||
}
|
||||
return toolCallbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从历史消息中,获得倒序的 n 组消息作为消息上下文
|
||||
* <p>
|
||||
|
@ -302,14 +458,56 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|||
return contextMessages;
|
||||
}
|
||||
|
||||
private UserMessage buildAttachmentUserMessage(List<String> attachmentUrls) {
|
||||
if (CollUtil.isEmpty(attachmentUrls)) {
|
||||
return null;
|
||||
}
|
||||
// 读取文件内容
|
||||
Map<String, String> attachmentContents = Maps.newLinkedHashMapWithExpectedSize(attachmentUrls.size());
|
||||
for (String attachmentUrl : attachmentUrls) {
|
||||
try {
|
||||
String name = FileNameUtil.getName(attachmentUrl);
|
||||
String mineType = FileTypeUtils.getMineType(name);
|
||||
String content;
|
||||
if (FileTypeUtils.isImage(mineType)) {
|
||||
// 特殊:图片则转为 Base64
|
||||
byte[] bytes = HttpUtil.downloadBytes(attachmentUrl);
|
||||
content = Base64.encode(bytes);
|
||||
} else {
|
||||
content = knowledgeDocumentService.readUrl(attachmentUrl);
|
||||
}
|
||||
if (StrUtil.isNotEmpty(content)) {
|
||||
attachmentContents.put(name, content);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[buildAttachmentUserMessage][读取附件({}) 发生异常]", attachmentUrl, e);
|
||||
}
|
||||
}
|
||||
if (CollUtil.isEmpty(attachmentContents)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 拼接 UserMessage 消息
|
||||
String attachment = attachmentContents.entrySet().stream()
|
||||
.map(entry -> "<Attachment name=\"" + entry.getKey() + "\">" + entry.getValue() + "</Attachment>")
|
||||
.collect(Collectors.joining("\n\n"));
|
||||
return new UserMessage(String.format(Attachment_USER_MESSAGE_TEMPLATE, attachment));
|
||||
}
|
||||
|
||||
private AiChatMessageDO createChatMessage(Long conversationId, Long replyId,
|
||||
AiModelDO model, Long userId, Long roleId,
|
||||
MessageType messageType, String content, Boolean useContext,
|
||||
List<AiKnowledgeSegmentSearchRespBO> knowledgeSegments) {
|
||||
AiModelDO model, Long userId, Long roleId,
|
||||
MessageType messageType, String content, Boolean useContext,
|
||||
List<AiKnowledgeSegmentSearchRespBO> knowledgeSegments,
|
||||
List<String> attachmentUrls,
|
||||
AiWebSearchResponse webSearchResponse) {
|
||||
AiChatMessageDO message = new AiChatMessageDO().setConversationId(conversationId).setReplyId(replyId)
|
||||
.setModel(model.getModel()).setModelId(model.getId()).setUserId(userId).setRoleId(roleId)
|
||||
.setType(messageType.getValue()).setContent(content).setUseContext(useContext)
|
||||
.setSegmentIds(convertList(knowledgeSegments, AiKnowledgeSegmentSearchRespBO::getId));
|
||||
.setSegmentIds(convertList(knowledgeSegments, AiKnowledgeSegmentSearchRespBO::getId))
|
||||
.setAttachmentUrls(attachmentUrls);
|
||||
if (webSearchResponse != null) {
|
||||
message.setWebSearchPages(webSearchResponse.getLists());
|
||||
}
|
||||
message.setCreateTime(LocalDateTime.now());
|
||||
chatMessageMapper.insert(message);
|
||||
return message;
|
||||
|
|
|
@ -9,9 +9,6 @@ import cn.hutool.core.util.ObjUtil;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageOptions;
|
||||
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;
|
||||
|
@ -24,6 +21,9 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO;
|
|||
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper;
|
||||
import cn.iocoder.yudao.module.ai.enums.image.AiImageStatusEnum;
|
||||
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageOptions;
|
||||
import cn.iocoder.yudao.module.ai.service.model.AiModelService;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageOptions;
|
||||
|
@ -89,7 +89,7 @@ public class AiImageServiceImpl implements AiImageService {
|
|||
if (CollUtil.isEmpty(ids)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return imageMapper.selectBatchIds(ids);
|
||||
return imageMapper.selectByIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,7 +18,11 @@ import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeSegmentMapper;
|
|||
import cn.iocoder.yudao.module.ai.service.knowledge.bo.AiKnowledgeSegmentSearchReqBO;
|
||||
import cn.iocoder.yudao.module.ai.service.knowledge.bo.AiKnowledgeSegmentSearchRespBO;
|
||||
import cn.iocoder.yudao.module.ai.service.model.AiModelService;
|
||||
import javax.annotation.Resource;
|
||||
import com.alibaba.cloud.ai.dashscope.rerank.DashScopeRerankOptions;
|
||||
import com.alibaba.cloud.ai.model.RerankModel;
|
||||
import com.alibaba.cloud.ai.model.RerankRequest;
|
||||
import com.alibaba.cloud.ai.model.RerankResponse;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.tokenizer.TokenCountEstimator;
|
||||
|
@ -27,6 +31,7 @@ import org.springframework.ai.transformer.splitter.TokenTextSplitter;
|
|||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.ai.vectorstore.filter.FilterExpressionBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
@ -36,6 +41,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
|
|||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_SEGMENT_CONTENT_TOO_LONG;
|
||||
import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_SEGMENT_NOT_EXISTS;
|
||||
import static org.springframework.ai.vectorstore.SearchRequest.SIMILARITY_THRESHOLD_ACCEPT_ALL;
|
||||
|
||||
/**
|
||||
* AI 知识库分片 Service 实现类
|
||||
|
@ -55,6 +61,11 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
|
|||
VECTOR_STORE_METADATA_DOCUMENT_ID, String.class,
|
||||
VECTOR_STORE_METADATA_SEGMENT_ID, String.class);
|
||||
|
||||
/**
|
||||
* Rerank 在向量检索时,检索数量 * 该系数,目的是为了提升 Rerank 的效果
|
||||
*/
|
||||
private static final Integer RERANK_RETRIEVAL_FACTOR = 4;
|
||||
|
||||
@Resource
|
||||
private AiKnowledgeSegmentMapper segmentMapper;
|
||||
|
||||
|
@ -69,6 +80,9 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
|
|||
@Resource
|
||||
private TokenCountEstimator tokenCountEstimator;
|
||||
|
||||
@Autowired(required = false) // 由于 spring.ai.model.rerank 配置项,可以关闭 RerankModel 的功能,所以这里只能不强制注入
|
||||
private RerankModel rerankModel;
|
||||
|
||||
@Override
|
||||
public PageResult<AiKnowledgeSegmentDO> getKnowledgeSegmentPage(AiKnowledgeSegmentPageReqVO pageReqVO) {
|
||||
return segmentMapper.selectPage(pageReqVO);
|
||||
|
@ -211,28 +225,16 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
|
|||
// 1. 校验
|
||||
AiKnowledgeDO knowledge = knowledgeService.validateKnowledgeExists(reqBO.getKnowledgeId());
|
||||
|
||||
// 2.1 向量检索
|
||||
VectorStore vectorStore = getVectorStoreById(knowledge);
|
||||
List<Document> documents = vectorStore.similaritySearch(SearchRequest.builder()
|
||||
.query(reqBO.getContent())
|
||||
.topK(ObjUtil.defaultIfNull(reqBO.getTopK(), knowledge.getTopK()))
|
||||
.similarityThreshold(
|
||||
ObjUtil.defaultIfNull(reqBO.getSimilarityThreshold(), knowledge.getSimilarityThreshold()))
|
||||
.filterExpression(new FilterExpressionBuilder()
|
||||
.eq(VECTOR_STORE_METADATA_KNOWLEDGE_ID, reqBO.getKnowledgeId().toString())
|
||||
.build())
|
||||
.build());
|
||||
if (CollUtil.isEmpty(documents)) {
|
||||
return ListUtil.empty();
|
||||
}
|
||||
// 2.2 段落召回
|
||||
// 2. 检索
|
||||
List<Document> documents = searchDocument(knowledge, reqBO);
|
||||
|
||||
// 3.1 段落召回
|
||||
List<AiKnowledgeSegmentDO> segments = segmentMapper
|
||||
.selectListByVectorIds(convertList(documents, Document::getId));
|
||||
if (CollUtil.isEmpty(segments)) {
|
||||
return ListUtil.empty();
|
||||
}
|
||||
|
||||
// 3. 增加召回次数
|
||||
// 3.2 增加召回次数
|
||||
segmentMapper.updateRetrievalCountIncrByIds(convertList(segments, AiKnowledgeSegmentDO::getId));
|
||||
|
||||
// 4. 构建结果
|
||||
|
@ -249,6 +251,42 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于 Embedding + Rerank Model,检索知识库中的文档
|
||||
*
|
||||
* @param knowledge 知识库
|
||||
* @param reqBO 检索请求
|
||||
* @return 文档列表
|
||||
*/
|
||||
private List<Document> searchDocument(AiKnowledgeDO knowledge, AiKnowledgeSegmentSearchReqBO reqBO) {
|
||||
VectorStore vectorStore = getVectorStoreById(knowledge);
|
||||
Integer topK = ObjUtil.defaultIfNull(reqBO.getTopK(), knowledge.getTopK());
|
||||
Double similarityThreshold = ObjUtil.defaultIfNull(reqBO.getSimilarityThreshold(), knowledge.getSimilarityThreshold());
|
||||
|
||||
// 1. 向量检索
|
||||
int searchTopK = rerankModel != null ? topK * RERANK_RETRIEVAL_FACTOR : topK;
|
||||
double searchSimilarityThreshold = rerankModel != null ? SIMILARITY_THRESHOLD_ACCEPT_ALL : similarityThreshold;
|
||||
SearchRequest.Builder searchRequestBuilder = SearchRequest.builder()
|
||||
.query(reqBO.getContent())
|
||||
.topK(searchTopK).similarityThreshold(searchSimilarityThreshold)
|
||||
.filterExpression(new FilterExpressionBuilder()
|
||||
.eq(VECTOR_STORE_METADATA_KNOWLEDGE_ID, reqBO.getKnowledgeId().toString()).build());
|
||||
List<Document> documents = vectorStore.similaritySearch(searchRequestBuilder.build());
|
||||
if (CollUtil.isEmpty(documents)) {
|
||||
return documents;
|
||||
}
|
||||
|
||||
// 2. Rerank 重排序
|
||||
if (rerankModel != null) {
|
||||
RerankResponse rerankResponse = rerankModel.call(new RerankRequest(reqBO.getContent(), documents,
|
||||
DashScopeRerankOptions.builder().withTopN(topK).build()));
|
||||
documents = convertList(rerankResponse.getResults(),
|
||||
documentWithScore -> documentWithScore.getScore() >= similarityThreshold
|
||||
? documentWithScore.getOutput() : null);
|
||||
}
|
||||
return documents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AiKnowledgeSegmentDO> splitContent(String url, Integer segmentMaxTokens) {
|
||||
// 1. 读取 URL 内容
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cn.iocoder.yudao.module.ai.service.model;
|
||||
|
||||
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.AiModelFactory;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.AiModelFactory;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package cn.iocoder.yudao.module.ai.service.model;
|
||||
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
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.model.vo.tool.AiToolPageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool.AiToolSaveReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiToolDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.mysql.model.AiToolMapper;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.ai.tool.ToolCallback;
|
||||
import org.springframework.ai.tool.resolution.ToolCallbackResolver;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
|
@ -31,6 +31,9 @@ public class AiToolServiceImpl implements AiToolService {
|
|||
@Resource
|
||||
private AiToolMapper toolMapper;
|
||||
|
||||
@Resource
|
||||
private ToolCallbackResolver toolCallbackResolver;
|
||||
|
||||
@Override
|
||||
public Long createTool(AiToolSaveReqVO createReqVO) {
|
||||
// 校验名称是否存在
|
||||
|
@ -70,9 +73,8 @@ public class AiToolServiceImpl implements AiToolService {
|
|||
}
|
||||
|
||||
private void validateToolNameExists(String name) {
|
||||
try {
|
||||
SpringUtil.getBean(name);
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
ToolCallback toolCallback = toolCallbackResolver.resolve(name);
|
||||
if (toolCallback == null) {
|
||||
throw exception(TOOL_NAME_NOT_EXISTS, name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package cn.iocoder.yudao.module.ai.service.model.tool;
|
||||
package cn.iocoder.yudao.module.ai.tool.function;
|
||||
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
|
@ -1,4 +1,4 @@
|
|||
package cn.iocoder.yudao.module.ai.service.model.tool;
|
||||
package cn.iocoder.yudao.module.ai.tool.function;
|
||||
|
||||
import cn.iocoder.yudao.module.ai.util.AiUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
|
@ -1,4 +1,4 @@
|
|||
package cn.iocoder.yudao.module.ai.service.model.tool;
|
||||
package cn.iocoder.yudao.module.ai.tool.function;
|
||||
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* 参考 <a href="https://docs.spring.io/spring-ai/reference/api/tools.html#_methods_as_tools">Tool Calling —— Methods as Tools</a>
|
||||
*/
|
||||
package cn.iocoder.yudao.module.ai.tool.function;
|
|
@ -0,0 +1,19 @@
|
|||
package cn.iocoder.yudao.module.ai.tool.method;
|
||||
|
||||
/**
|
||||
* 来自 Spring AI 官方文档
|
||||
*
|
||||
* Represents a person with basic information.
|
||||
* This is an immutable record.
|
||||
*/
|
||||
public record Person(
|
||||
int id,
|
||||
String firstName,
|
||||
String lastName,
|
||||
String email,
|
||||
String sex,
|
||||
String ipAddress,
|
||||
String jobTitle,
|
||||
int age
|
||||
) {
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package cn.iocoder.yudao.module.ai.tool.method;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 来自 Spring AI 官方文档
|
||||
*
|
||||
* Service interface for managing Person data.
|
||||
* Defines the contract for CRUD operations and search/filter functionalities.
|
||||
*/
|
||||
public interface PersonService {
|
||||
|
||||
/**
|
||||
* Creates a new Person record.
|
||||
* Assigns a unique ID to the person and stores it.
|
||||
*
|
||||
* @param personData The data for the new person (ID field is ignored). Must not be null.
|
||||
* @return The created Person record, including the generated ID.
|
||||
*/
|
||||
Person createPerson(Person personData);
|
||||
|
||||
/**
|
||||
* Retrieves a Person by their unique ID.
|
||||
*
|
||||
* @param id The ID of the person to retrieve.
|
||||
* @return An Optional containing the found Person, or an empty Optional if not found.
|
||||
*/
|
||||
Optional<Person> getPersonById(int id);
|
||||
|
||||
/**
|
||||
* Retrieves all Person records currently stored.
|
||||
*
|
||||
* @return An unmodifiable List containing all Persons. Returns an empty list if none exist.
|
||||
*/
|
||||
List<Person> getAllPersons();
|
||||
|
||||
/**
|
||||
* Updates an existing Person record identified by ID.
|
||||
* Replaces the existing data with the provided data, keeping the original ID.
|
||||
*
|
||||
* @param id The ID of the person to update.
|
||||
* @param updatedPersonData The new data for the person (ID field is ignored). Must not be null.
|
||||
* @return true if the person was found and updated, false otherwise.
|
||||
*/
|
||||
boolean updatePerson(int id, Person updatedPersonData);
|
||||
|
||||
/**
|
||||
* Deletes a Person record identified by ID.
|
||||
*
|
||||
* @param id The ID of the person to delete.
|
||||
* @return true if the person was found and deleted, false otherwise.
|
||||
*/
|
||||
boolean deletePerson(int id);
|
||||
|
||||
/**
|
||||
* Searches for Persons whose job title contains the given query string (case-insensitive).
|
||||
*
|
||||
* @param jobTitleQuery The string to search for within job titles. Can be null or blank.
|
||||
* @return An unmodifiable List of matching Persons. Returns an empty list if no matches or query is invalid.
|
||||
*/
|
||||
List<Person> searchByJobTitle(String jobTitleQuery);
|
||||
|
||||
/**
|
||||
* Filters Persons by their exact sex (case-insensitive).
|
||||
*
|
||||
* @param sex The sex to filter by (e.g., "Male", "Female"). Can be null or blank.
|
||||
* @return An unmodifiable List of matching Persons. Returns an empty list if no matches or filter is invalid.
|
||||
*/
|
||||
List<Person> filterBySex(String sex);
|
||||
|
||||
/**
|
||||
* Filters Persons by their exact age.
|
||||
*
|
||||
* @param age The age to filter by.
|
||||
* @return An unmodifiable List of matching Persons. Returns an empty list if no matches.
|
||||
*/
|
||||
List<Person> filterByAge(int age);
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue