Merge branch 'refs/heads/zt-test' into test
# Conflicts: # zt-module-infra/zt-module-infra-server/src/main/resources/application.yaml
This commit is contained in:
18
pom.xml
18
pom.xml
@@ -32,7 +32,7 @@
|
|||||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>3.0.45</revision>
|
<revision>3.0.46</revision>
|
||||||
<!-- Maven 相关 -->
|
<!-- Maven 相关 -->
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
@@ -242,6 +242,19 @@
|
|||||||
<config.version>1.0.0</config.version>
|
<config.version>1.0.0</config.version>
|
||||||
</properties>
|
</properties>
|
||||||
</profile>
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>klw-dev</id>
|
||||||
|
<properties>
|
||||||
|
<env.name>dev</env.name>
|
||||||
|
<!--Nacos 配置-->
|
||||||
|
<config.server-addr>172.16.46.63:30848</config.server-addr>
|
||||||
|
<config.namespace>klw</config.namespace>
|
||||||
|
<config.group>DEFAULT_GROUP</config.group>
|
||||||
|
<config.username>nacos</config.username>
|
||||||
|
<config.password>P@ssword25</config.password>
|
||||||
|
<config.version>1.0.0</config.version>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
<profile>
|
<profile>
|
||||||
<id>env-prod</id>
|
<id>env-prod</id>
|
||||||
<properties>
|
<properties>
|
||||||
@@ -271,7 +284,8 @@
|
|||||||
<profile>
|
<profile>
|
||||||
<id>chenbowen</id>
|
<id>chenbowen</id>
|
||||||
<properties>
|
<properties>
|
||||||
<env.name>local</env.name>
|
<!-- <env.name>local</env.name>-->
|
||||||
|
<env.name>dev</env.name>
|
||||||
<!-- <config.server-addr>localhost:8848</config.server-addr>-->
|
<!-- <config.server-addr>localhost:8848</config.server-addr>-->
|
||||||
<config.server-addr>172.16.46.63:30848</config.server-addr>
|
<config.server-addr>172.16.46.63:30848</config.server-addr>
|
||||||
<config.namespace>chenbowen</config.namespace>
|
<config.namespace>chenbowen</config.namespace>
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ CREATE TABLE bpm_process_definition_info (
|
|||||||
simple_model text NULL,
|
simple_model text NULL,
|
||||||
sort bigint DEFAULT 0 NULL,
|
sort bigint DEFAULT 0 NULL,
|
||||||
visible bit DEFAULT '1' NOT NULL,
|
visible bit DEFAULT '1' NOT NULL,
|
||||||
|
restart bit DEFAULT '1' NOT NULL,
|
||||||
start_user_ids varchar(256) DEFAULT NULL NULL,
|
start_user_ids varchar(256) DEFAULT NULL NULL,
|
||||||
start_dept_ids varchar(256) DEFAULT NULL NULL,
|
start_dept_ids varchar(256) DEFAULT NULL NULL,
|
||||||
manager_user_ids varchar(256) DEFAULT NULL NULL,
|
manager_user_ids varchar(256) DEFAULT NULL NULL,
|
||||||
@@ -156,6 +157,7 @@ COMMENT ON COLUMN bpm_process_definition_info.form_custom_view_path IS '自定
|
|||||||
COMMENT ON COLUMN bpm_process_definition_info.simple_model IS 'SIMPLE 设计器模型数据 JSON 格式';
|
COMMENT ON COLUMN bpm_process_definition_info.simple_model IS 'SIMPLE 设计器模型数据 JSON 格式';
|
||||||
COMMENT ON COLUMN bpm_process_definition_info.sort IS '排序值';
|
COMMENT ON COLUMN bpm_process_definition_info.sort IS '排序值';
|
||||||
COMMENT ON COLUMN bpm_process_definition_info.visible IS '是否可见';
|
COMMENT ON COLUMN bpm_process_definition_info.visible IS '是否可见';
|
||||||
|
COMMENT ON COLUMN bpm_process_definition_info.restart IS '是否允许重新发起';
|
||||||
COMMENT ON COLUMN bpm_process_definition_info.start_user_ids IS '可发起用户编号数组';
|
COMMENT ON COLUMN bpm_process_definition_info.start_user_ids IS '可发起用户编号数组';
|
||||||
COMMENT ON COLUMN bpm_process_definition_info.start_dept_ids IS '可发起部门编号数组';
|
COMMENT ON COLUMN bpm_process_definition_info.start_dept_ids IS '可发起部门编号数组';
|
||||||
COMMENT ON COLUMN bpm_process_definition_info.manager_user_ids IS '可管理用户编号数组';
|
COMMENT ON COLUMN bpm_process_definition_info.manager_user_ids IS '可管理用户编号数组';
|
||||||
|
|||||||
@@ -331,6 +331,8 @@ CREATE TABLE infra_file (
|
|||||||
name varchar(256) DEFAULT NULL NULL,
|
name varchar(256) DEFAULT NULL NULL,
|
||||||
path varchar(512) NOT NULL,
|
path varchar(512) NOT NULL,
|
||||||
url varchar(1024) NOT NULL,
|
url varchar(1024) NOT NULL,
|
||||||
|
hash varchar(64) DEFAULT NULL NULL,
|
||||||
|
aes_iv varchar(128) DEFAULT NULL NULL,
|
||||||
type varchar(128) DEFAULT NULL NULL,
|
type varchar(128) DEFAULT NULL NULL,
|
||||||
size int NOT NULL,
|
size int NOT NULL,
|
||||||
creator varchar(64) DEFAULT '' NULL,
|
creator varchar(64) DEFAULT '' NULL,
|
||||||
@@ -345,6 +347,8 @@ COMMENT ON COLUMN infra_file.config_id IS '配置编号';
|
|||||||
COMMENT ON COLUMN infra_file.name IS '文件名';
|
COMMENT ON COLUMN infra_file.name IS '文件名';
|
||||||
COMMENT ON COLUMN infra_file.path IS '文件路径';
|
COMMENT ON COLUMN infra_file.path IS '文件路径';
|
||||||
COMMENT ON COLUMN infra_file.url IS '文件 URL';
|
COMMENT ON COLUMN infra_file.url IS '文件 URL';
|
||||||
|
COMMENT ON COLUMN infra_file.hash IS '文件哈希值(SHA-256)';
|
||||||
|
COMMENT ON COLUMN infra_file.aes_iv IS 'AES加密时的随机IV(Base64编码)';
|
||||||
COMMENT ON COLUMN infra_file.type IS '文件类型';
|
COMMENT ON COLUMN infra_file.type IS '文件类型';
|
||||||
COMMENT ON COLUMN infra_file.size IS '文件大小';
|
COMMENT ON COLUMN infra_file.size IS '文件大小';
|
||||||
COMMENT ON COLUMN infra_file.creator IS '创建者';
|
COMMENT ON COLUMN infra_file.creator IS '创建者';
|
||||||
@@ -354,6 +358,8 @@ COMMENT ON COLUMN infra_file.update_time IS '更新时间';
|
|||||||
COMMENT ON COLUMN infra_file.deleted IS '是否删除';
|
COMMENT ON COLUMN infra_file.deleted IS '是否删除';
|
||||||
COMMENT ON TABLE infra_file IS '文件表';
|
COMMENT ON TABLE infra_file IS '文件表';
|
||||||
|
|
||||||
|
CREATE INDEX idx_infra_file_hash ON infra_file(hash);
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for infra_file_config
|
-- Table structure for infra_file_config
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
@@ -1586,6 +1592,116 @@ INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon
|
|||||||
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, '1', '1', '1', '1', '2025-05-05 15:25:32', '1', '2025-05-05 15:25:32', '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 (5010, '租户切换', 'system:tenant:visit', 3, 999, 1138, '', '', '', '', 0, '1', '1', '1', '1', '2025-05-05 15:25:32', '1', '2025-05-05 15:25:32', '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, '公司切换', 'system:company:visit', 3, 100, 103, '', '', '', '', 0, '1', '1', '1', '1', '2025-12-05 09:00:00', '1', '2025-12-05 09:00:00', '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, '公司切换', 'system:company:visit', 3, 100, 103, '', '', '', '', 0, '1', '1', '1', '1', '2025-12-05 09:00:00', '1', '2025-12-05 09:00:00', '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, '部门切换', 'system:dept:visit', 3, 101, 103, '', '', '', '', 0, '1', '1', '1', '1', '2025-12-05 09:00:00', '1', '2025-12-05 09:00:00', '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, '部门切换', 'system:dept:visit', 3, 101, 103, '', '', '', '', 0, '1', '1', '1', '1', '2025-12-05 09:00:00', '1', '2025-12-05 09:00:00', '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 (1953701540574969857, '系统序列号管理', '', 2, 0, 1, 'sequence', '', 'system/sequence/index', 'Sequence', 0, 1, 1, 1, '', '2025-08-08 14:38:20.455625', '', '2025-08-08 14:38:20.455626', 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 (1953706417225150470, '系统序列号导出', 'system:sequence:export', 3, 5, 1953701540574969857, '', '', '', null, 0, 1, 1, 1, '', '2025-08-08 14:38:20.580376', '', '2025-08-08 14:38:20.580377', 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 (1953706417225150469, '系统序列号删除', 'system:sequence:delete', 3, 4, 1953701540574969857, '', '', '', null, 0, 1, 1, 1, '', '2025-08-08 14:38:20.553819', '', '2025-08-08 14:38:20.553820', 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 (1953706417225150468, '系统序列号更新', 'system:sequence:update', 3, 3, 1953701540574969857, '', '', '', null, 0, 1, 1, 1, '', '2025-08-08 14:38:20.522730', '', '2025-08-08 14:38:20.522731', 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 (1953706417225150467, '系统序列号创建', 'system:sequence:create', 3, 2, 1953701540574969857, '', '', '', null, 0, 1, 1, 1, '', '2025-08-08 14:38:20.499928', '', '2025-08-08 14:38:20.499929', 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 (1953706417225150466, '系统序列号查询', 'system:sequence:query', 3, 1, 1953701540574969857, '', '', '', null, 0, 1, 1, 1, '', '2025-08-08 14:38:20.483702', '', '2025-08-08 14:38:20.483703', 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 (2739, '消息中心', '', 1, 7, 1, 'messages', 'ep:chat-dot-round', '', '', 0, 1, 1, 1, '1', '2024-04-22 23:54:30.000000', '1', '2024-04-23 09:36:35.000000', 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 (2144, '站内信管理', '', 1, 3, 2739, 'notify', 'ep:message-box', null, null, 0, 1, 1, 1, '1', '2023-01-28 10:25:18.000000', '1', '2024-04-22 23:56:12.000000', 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 (2151, '消息记录', '', 2, 0, 2144, 'notify-message', 'fa:edit', 'system/notify/message/index', 'SystemNotifyMessage', 0, 1, 1, 1, '', '2023-01-28 04:28:22.000000', '1', '2024-02-29 08:49:22.000000', 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 (2152, '站内信消息查询', 'system:notify-message:query', 3, 1, 2151, '', '', '', null, 0, 1, 1, 1, '', '2023-01-28 04:28:22.000000', '', '2023-01-28 04:28:22.000000', 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 (2145, '模板管理', '', 2, 0, 2144, 'notify-template', 'fa:archive', 'system/notify/template/index', 'SystemNotifyTemplate', 0, 1, 1, 1, '', '2023-01-28 02:26:42.000000', '1', '2024-02-29 08:49:14.000000', 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 (2150, '发送测试站内信', 'system:notify-template:send-notify', 3, 5, 2145, '', '', '', null, 0, 1, 1, 1, '1', '2023-01-28 10:54:43.000000', '1', '2023-01-28 10:54:43.000000', 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 (2149, '站内信模板删除', 'system:notify-template:delete', 3, 4, 2145, '', '', '', null, 0, 1, 1, 1, '', '2023-01-28 02:26:42.000000', '', '2023-01-28 02:26:42.000000', 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 (2148, '站内信模板更新', 'system:notify-template:update', 3, 3, 2145, '', '', '', null, 0, 1, 1, 1, '', '2023-01-28 02:26:42.000000', '', '2023-01-28 02:26:42.000000', 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 (2147, '站内信模板创建', 'system:notify-template:create', 3, 2, 2145, '', '', '', null, 0, 1, 1, 1, '', '2023-01-28 02:26:42.000000', '', '2023-01-28 02:26:42.000000', 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 (2146, '站内信模板查询', 'system:notify-template:query', 3, 1, 2145, '', '', '', null, 0, 1, 1, 1, '', '2023-01-28 02:26:42.000000', '', '2023-01-28 02:26:42.000000', 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 (2130, '邮箱管理', '', 2, 2, 2739, 'mail', 'fa-solid:mail-bulk', null, null, 0, 1, 1, 1, '1', '2023-01-25 17:27:44.000000', '1', '2024-04-22 23:56:08.000000', 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 (2141, '邮件记录', '', 2, 0, 2130, 'mail-log', 'fa:edit', 'system/mail/log/index', 'SystemMailLog', 0, 1, 1, 1, '', '2023-01-26 02:16:50.000000', '1', '2024-02-29 08:48:51.000000', 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 (2142, '日志查询', 'system:mail-log:query', 3, 1, 2141, '', '', '', null, 0, 1, 1, 1, '', '2023-01-26 02:16:50.000000', '', '2023-01-26 02:16:50.000000', 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 (2136, '邮件模版', '', 2, 0, 2130, 'mail-template', 'fa:tag', 'system/mail/template/index', 'SystemMailTemplate', 0, 1, 1, 1, '', '2023-01-25 12:05:31.000000', '1', '2024-02-29 08:48:41.000000', 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 (2143, '发送测试邮件', 'system:mail-template:send-mail', 3, 5, 2136, '', '', '', null, 0, 1, 1, 1, '1', '2023-01-26 23:29:15.000000', '1', '2023-01-26 23:29:15.000000', 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 (2140, '模版删除', 'system:mail-template:delete', 3, 4, 2136, '', '', '', null, 0, 1, 1, 1, '', '2023-01-25 12:05:31.000000', '', '2023-01-25 12:05:31.000000', 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 (2139, '模版更新', 'system:mail-template:update', 3, 3, 2136, '', '', '', null, 0, 1, 1, 1, '', '2023-01-25 12:05:31.000000', '', '2023-01-25 12:05:31.000000', 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 (2138, '模版创建', 'system:mail-template:create', 3, 2, 2136, '', '', '', null, 0, 1, 1, 1, '', '2023-01-25 12:05:31.000000', '', '2023-01-25 12:05:31.000000', 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 (2137, '模版查询', 'system:mail-template:query', 3, 1, 2136, '', '', '', null, 0, 1, 1, 1, '', '2023-01-25 12:05:31.000000', '', '2023-01-25 12:05:31.000000', 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 (2131, '邮箱账号', '', 2, 0, 2130, 'mail-account', 'fa:universal-access', 'system/mail/account/index', 'SystemMailAccount', 0, 1, 1, 1, '', '2023-01-25 09:33:48.000000', '1', '2024-02-29 08:48:16.000000', 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 (2135, '账号删除', 'system:mail-account:delete', 3, 4, 2131, '', '', '', null, 0, 1, 1, 1, '', '2023-01-25 09:33:48.000000', '', '2023-01-25 09:33:48.000000', 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 (2134, '账号更新', 'system:mail-account:update', 3, 3, 2131, '', '', '', null, 0, 1, 1, 1, '', '2023-01-25 09:33:48.000000', '', '2023-01-25 09:33:48.000000', 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 (2133, '账号创建', 'system:mail-account:create', 3, 2, 2131, '', '', '', null, 0, 1, 1, 1, '', '2023-01-25 09:33:48.000000', '', '2023-01-25 09:33:48.000000', 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 (2132, '账号查询', 'system:mail-account:query', 3, 1, 2131, '', '', '', null, 0, 1, 1, 1, '', '2023-01-25 09:33:48.000000', '', '2023-01-25 09:33:48.000000', 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 (1093, '短信管理', '', 1, 1, 2739, 'sms', 'ep:message', null, null, 0, 1, 1, 1, '1', '2021-04-05 01:10:16.000000', '1', '2024-04-22 23:56:03.000000', 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 (1107, '短信日志', '', 2, 2, 1093, 'sms-log', 'fa:edit', 'system/sms/log/index', 'SystemSmsLog', 0, 1, 1, 1, '', '2021-04-11 08:37:05.000000', '1', '2024-02-29 08:49:02.000000', 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 (1109, '短信日志导出', 'system:sms-log:export', 3, 5, 1107, '', '', '', null, 0, 1, 1, 1, '', '2021-04-11 08:37:05.000000', '', '2022-04-20 17:03:10.000000', 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 (1108, '短信日志查询', 'system:sms-log:query', 3, 1, 1107, '', '', '', null, 0, 1, 1, 1, '', '2021-04-11 08:37:05.000000', '', '2022-04-20 17:03:10.000000', 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 (1100, '短信模板', '', 2, 1, 1093, 'sms-template', 'ep:connection', 'system/sms/template/index', 'SystemSmsTemplate', 0, 1, 1, 1, '', '2021-04-01 17:35:17.000000', '1', '2024-02-29 01:16:18.000000', 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 (1106, '发送测试短信', 'system:sms-template:send-sms', 3, 6, 1100, '', '', '', null, 0, 1, 1, 1, '1', '2021-04-11 00:26:40.000000', '1', '2022-04-20 17:03:10.000000', 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 (1105, '短信模板导出', 'system:sms-template:export', 3, 5, 1100, '', '', '', null, 0, 1, 1, 1, '', '2021-04-01 17:35:17.000000', '', '2022-04-20 17:03:10.000000', 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 (1104, '短信模板删除', 'system:sms-template:delete', 3, 4, 1100, '', '', '', null, 0, 1, 1, 1, '', '2021-04-01 17:35:17.000000', '', '2022-04-20 17:03:10.000000', 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 (1103, '短信模板更新', 'system:sms-template:update', 3, 3, 1100, '', '', '', null, 0, 1, 1, 1, '', '2021-04-01 17:35:17.000000', '', '2022-04-20 17:03:10.000000', 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 (1102, '短信模板创建', 'system:sms-template:create', 3, 2, 1100, '', '', '', null, 0, 1, 1, 1, '', '2021-04-01 17:35:17.000000', '', '2022-04-20 17:03:10.000000', 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 (1101, '短信模板查询', 'system:sms-template:query', 3, 1, 1100, '', '', '', null, 0, 1, 1, 1, '', '2021-04-01 17:35:17.000000', '', '2022-04-20 17:03:10.000000', 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 (1094, '短信渠道', '', 2, 0, 1093, 'sms-channel', 'fa:stack-exchange', 'system/sms/channel/index', 'SystemSmsChannel', 0, 1, 1, 1, '', '2021-04-01 11:07:15.000000', '1', '2024-02-29 01:15:54.000000', 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 (1098, '短信渠道删除', 'system:sms-channel:delete', 3, 4, 1094, '', '', '', null, 0, 1, 1, 1, '', '2021-04-01 11:07:15.000000', '', '2022-04-20 17:03:10.000000', 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 (1097, '短信渠道更新', 'system:sms-channel:update', 3, 3, 1094, '', '', '', null, 0, 1, 1, 1, '', '2021-04-01 11:07:15.000000', '', '2022-04-20 17:03:10.000000', 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 (1096, '短信渠道创建', 'system:sms-channel:create', 3, 2, 1094, '', '', '', null, 0, 1, 1, 1, '', '2021-04-01 11:07:15.000000', '', '2022-04-20 17:03:10.000000', 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 (1095, '短信渠道查询', 'system:sms-channel:query', 3, 1, 1094, '', '', '', null, 0, 1, 1, 1, '', '2021-04-01 11:07:15.000000', '', '2022-04-20 17:03:10.000000', 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 (107, '通知公告', '', 2, 4, 2739, 'notice', 'ep:takeaway-box', 'system/notice/index', 'SystemNotice', 0, 1, 1, 1, 'admin', '2021-01-05 17:03:48.000000', '1', '2024-04-22 23:56:17.000000', 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 (1039, '公告删除', 'system:notice:delete', 3, 4, 107, '', '', '', null, 0, 1, 1, 1, 'admin', '2021-01-05 17:03:48.000000', '1', '2022-04-20 17:03:10.000000', 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 (1038, '公告修改', 'system:notice:update', 3, 3, 107, '', '', '', null, 0, 1, 1, 1, 'admin', '2021-01-05 17:03:48.000000', '1', '2022-04-20 17:03:10.000000', 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 (1037, '公告新增', 'system:notice:create', 3, 2, 107, '', '', '', null, 0, 1, 1, 1, 'admin', '2021-01-05 17:03:48.000000', '1', '2022-04-20 17:03:10.000000', 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 (1036, '公告查询', 'system:notice:query', 3, 1, 107, '#', '#', '', null, 0, 1, 1, 1, 'admin', '2021-01-05 17:03:48.000000', '', '2022-04-20 17:03:10.000000', 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 (6500, '数据总线', '', 1, 20, 1, 'databus', 'ep:data-board', '', 'DatabusRoot', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.690389', 'admin', '2025-10-17 17:14:18.690390', 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 (1861234567890123500, '数据同步', '', 1, 50, 6500, 'sync', 'ep:connection', null, null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.048176', '1', '2025-11-25 17:33:29.370218', 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 (2874, '全量同步任务', '', 2, 6, 1861234567890123500, 'fulltask', 'ep:upload', 'databus/sync/fulltask/index', 'DatabusSyncFullTask', 0, 1, 1, 0, 'admin', '2025-11-28 18:24:33.619358', 'admin', '2025-11-28 18:24:33.619360', 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 (2878, '全量同步任务取消', 'databus:sync:full-task:cancel', 3, 4, 2874, '', '', '', '', 0, 1, 1, 0, 'admin', '2025-11-28 18:24:33.619369', 'admin', '2025-11-28 18:24:33.619369', 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 (2877, '全量同步任务执行', 'databus:sync:full-task:execute', 3, 3, 2874, '', '', '', '', 0, 1, 1, 0, 'admin', '2025-11-28 18:24:33.619368', 'admin', '2025-11-28 18:24:33.619368', 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 (2876, '全量同步任务创建', 'databus:sync:full-task:create', 3, 2, 2874, '', '', '', '', 0, 1, 1, 0, 'admin', '2025-11-28 18:24:33.619367', 'admin', '2025-11-28 18:24:33.619367', 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 (2875, '全量同步任务查询', 'databus:sync:full-task:query', 3, 1, 2874, '', '', '', '', 0, 1, 1, 0, 'admin', '2025-11-28 18:24:33.619366', 'admin', '2025-11-28 18:24:33.619366', 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 (1861234567890123523, '死信队列', '', 2, 5, 1861234567890123500, 'deadletter', 'ep:warning', 'databus/sync/deadletter/index', 'DatabusSyncDeadLetter', 0, 1, 1, 1, '', '2025-11-25 17:28:16.259929', '', '2025-11-25 17:28:16.259932', 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 (1861234567890123527, '忽略死信', 'databus:sync:dead-letter:ignore', 3, 4, 1861234567890123523, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.282800', '', '2025-11-25 17:28:16.282802', 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 (1861234567890123526, '重新投递', 'databus:sync:dead-letter:reprocess', 3, 3, 1861234567890123523, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.277958', '', '2025-11-25 17:28:16.277960', 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 (1861234567890123525, '查看详情', 'databus:sync:dead-letter:detail', 3, 2, 1861234567890123523, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.271126', '', '2025-11-25 17:28:16.271128', 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 (1861234567890123524, '查询死信', 'databus:sync:dead-letter:query', 3, 1, 1861234567890123523, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.267617', '', '2025-11-25 17:28:16.267619', 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 (1861234567890123519, '同步日志', '', 2, 4, 1861234567890123500, 'pushlog', 'ep:document', 'databus/sync/pushlog/index', 'DatabusSyncLog', 0, 1, 1, 1, '', '2025-11-25 17:28:16.210732', '', '2025-11-25 17:28:16.210733', 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 (1861234567890123522, '导出日志', 'databus:sync:log:export', 3, 3, 1861234567890123519, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.252291', '', '2025-11-25 17:28:16.252296', 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 (1861234567890123521, '查看详情', 'databus:sync:log:detail', 3, 2, 1861234567890123519, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.230811', '', '2025-11-25 17:28:16.230816', 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 (1861234567890123520, '查询日志', 'databus:sync:log:query', 3, 1, 1861234567890123519, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.220956', '', '2025-11-25 17:28:16.220959', 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 (1861234567890123513, '订阅管理', '', 2, 3, 1861234567890123500, 'subscription', 'ep:guide', 'databus/sync/subscription/index', 'DatabusSyncSubscription', 0, 1, 1, 1, '', '2025-11-25 17:28:16.163388', '1', '2025-11-28 18:48:54.496674', 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 (1861234567890123518, '导出订阅', 'databus:sync:subscription:export', 3, 5, 1861234567890123513, '', '', '', null, 1, 1, 1, 1, '', '2025-11-25 17:28:16.203898', '', '2025-11-25 17:28:16.203899', 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 (1861234567890123517, '删除订阅', 'databus:sync:subscription:delete', 3, 4, 1861234567890123513, '', '', '', null, 1, 1, 1, 1, '', '2025-11-25 17:28:16.197362', '', '2025-11-25 17:28:16.197363', 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 (1861234567890123516, '更新订阅', 'databus:sync:subscription:update', 3, 3, 1861234567890123513, '', '', '', null, 1, 1, 1, 1, '', '2025-11-25 17:28:16.191555', '', '2025-11-25 17:28:16.191556', 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 (1861234567890123515, '创建订阅', 'databus:sync:subscription:create', 3, 2, 1861234567890123513, '', '', '', null, 1, 1, 1, 1, '', '2025-11-25 17:28:16.185782', '', '2025-11-25 17:28:16.185783', 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 (1861234567890123514, '查询订阅', 'databus:sync:subscription:query', 3, 1, 1861234567890123513, '', '', '', null, 1, 1, 1, 1, '', '2025-11-25 17:28:16.177918', '', '2025-11-25 17:28:16.177920', 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 (1861234567890123507, '客户端管理', '', 2, 2, 1861234567890123500, 'client', 'ep:monitor', 'databus/sync/client/index', 'DatabusSyncClient', 0, 1, 1, 1, '', '2025-11-25 17:28:16.111525', '', '2025-11-25 17:28:16.111526', 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 (1861234567890123512, '导出客户端', 'databus:sync:client:export', 3, 5, 1861234567890123507, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.158423', '', '2025-11-25 17:28:16.158424', 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 (1861234567890123511, '删除客户端', 'databus:sync:client:delete', 3, 4, 1861234567890123507, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.147803', '', '2025-11-25 17:28:16.147804', 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 (1861234567890123510, '更新客户端', 'databus:sync:client:update', 3, 3, 1861234567890123507, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.137440', '', '2025-11-25 17:28:16.137441', 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 (1861234567890123509, '创建客户端', 'databus:sync:client:create', 3, 2, 1861234567890123507, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.125308', '', '2025-11-25 17:28:16.125310', 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 (1861234567890123508, '查询客户端', 'databus:sync:client:query', 3, 1, 1861234567890123507, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.117846', '', '2025-11-25 17:28:16.117847', 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 (1861234567890123501, '事件管理', '', 2, 1, 1861234567890123500, 'event', 'ep:bell', 'databus/sync/event/index', 'DatabusSyncEvent', 0, 1, 1, 1, '', '2025-11-25 17:28:16.052979', '1', '2025-11-25 17:34:34.591416', 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 (1861234567890123506, '导出事件', 'databus:sync:event:export', 3, 5, 1861234567890123501, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.101020', '', '2025-11-25 17:28:16.101037', 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 (1861234567890123505, '删除事件', 'databus:sync:event:delete', 3, 4, 1861234567890123501, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.086845', '', '2025-11-25 17:28:16.086847', 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 (1861234567890123504, '更新事件', 'databus:sync:event:update', 3, 3, 1861234567890123501, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.079252', '', '2025-11-25 17:28:16.079256', 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 (1861234567890123503, '创建事件', 'databus:sync:event:create', 3, 2, 1861234567890123501, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.071706', '', '2025-11-25 17:28:16.071710', 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 (1861234567890123502, '查询事件', 'databus:sync:event:query', 3, 1, 1861234567890123501, '', '', '', null, 0, 1, 1, 1, '', '2025-11-25 17:28:16.060256', '', '2025-11-25 17:28:16.060257', 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 (6504, '访问日志', 'databus:gateway:access-log:query', 2, 40, 6500, 'access-log', 'ep:document', 'databus/accesslog/index', 'DatabusAccessLog', 0, 1, 1, 1, 'admin', '2025-10-29 14:39:35.126020', 'admin', '2025-10-29 14:39:35.126022', 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 (650401, '访问日志查询', 'databus:gateway:access-log:query', 3, 1, 6504, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-29 14:39:35.160454', 'admin', '2025-10-29 14:39:35.160456', 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 (6503, '限流策略', 'databus:policy:query', 2, 30, 6500, 'policy/rate-limit', 'ep:stopwatch', 'databus/policy/RateLimitPolicy', 'DatabusRateLimitPolicy', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.690396', 'admin', '2025-10-17 17:14:18.690396', 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 (650304, '策略删除', 'databus:policy:delete', 3, 4, 6503, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734365', 'admin', '2025-10-17 17:14:18.734365', 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 (650303, '策略修改', 'databus:policy:update', 3, 3, 6503, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734363', 'admin', '2025-10-17 17:14:18.734363', 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 (650302, '策略新增', 'databus:policy:create', 3, 2, 6503, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734362', 'admin', '2025-10-17 17:14:18.734362', 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 (650301, '策略查询', 'databus:policy:query', 3, 1, 6503, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734360', 'admin', '2025-10-17 17:14:18.734360', 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 (6502, '客户端凭证', 'databus:credential:query', 2, 20, 6500, 'credential', 'ep:key', 'databus/credential/index', 'DatabusCredential', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.690395', 'admin', '2025-10-17 17:14:18.690395', 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 (650204, '凭证删除', 'databus:credential:delete', 3, 4, 6502, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734358', 'admin', '2025-10-17 17:14:18.734358', 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 (650203, '凭证修改', 'databus:credential:update', 3, 3, 6502, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734356', 'admin', '2025-10-17 17:14:18.734356', 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 (650202, '凭证新增', 'databus:credential:create', 3, 2, 6502, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734354', 'admin', '2025-10-17 17:14:18.734354', 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 (650201, '凭证查询', 'databus:credential:query', 3, 1, 6502, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734352', 'admin', '2025-10-17 17:14:18.734352', 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 (6501, 'API 定义', 'databus:gateway:query', 2, 10, 6500, 'gateway', 'ep:list', 'databus/gateway/index', 'DatabusGateway', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.690394', 'admin', '2025-10-17 17:14:18.690394', 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 (650110, 'API版本对比', 'databus:gateway:version:compare', 3, 10, 6501, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-30 14:37:51.432572', 'admin', '2025-10-30 14:37:51.432572', 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 (650109, 'API版本回滚', 'databus:gateway:version:rollback', 3, 9, 6501, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-30 14:37:51.432571', 'admin', '2025-10-30 14:37:51.432571', 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 (650108, 'API版本详情', 'databus:gateway:version:detail', 3, 8, 6501, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-30 14:37:51.432570', 'admin', '2025-10-30 14:37:51.432570', 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 (650107, 'API版本历史', 'databus:gateway:version:query', 3, 7, 6501, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-30 14:37:51.432564', 'admin', '2025-10-30 14:37:51.432566', 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 (650106, 'API 刷新', 'databus:gateway:refresh', 3, 6, 6501, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734350', 'admin', '2025-10-17 17:14:18.734351', 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 (650105, 'API 调试', 'databus:gateway:invoke', 3, 5, 6501, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734349', 'admin', '2025-10-17 17:14:18.734349', 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 (650104, 'API 删除', 'databus:gateway:delete', 3, 4, 6501, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734347', 'admin', '2025-10-17 17:14:18.734347', 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 (650103, 'API 编辑', 'databus:gateway:update', 3, 3, 6501, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734345', 'admin', '2025-10-17 17:14:18.734345', 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 (650102, 'API 新建', 'databus:gateway:create', 3, 2, 6501, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734343', 'admin', '2025-10-17 17:14:18.734344', 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 (650101, 'API 查询', 'databus:gateway:query', 3, 1, 6501, '', '', '', '', 0, 1, 1, 1, 'admin', '2025-10-17 17:14:18.734335', 'admin', '2025-10-17 17:14:18.734338', 0);
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- SET IDENTITY_INSERT system_menu OFF;
|
-- SET IDENTITY_INSERT system_menu OFF;
|
||||||
-- @formatter:on
|
-- @formatter:on
|
||||||
@@ -1944,7 +2060,7 @@ COMMENT ON TABLE system_oauth2_refresh_token IS 'OAuth2 刷新令牌';
|
|||||||
CREATE TABLE system_operate_log (
|
CREATE TABLE system_operate_log (
|
||||||
id bigint NOT NULL PRIMARY KEY,
|
id bigint NOT NULL PRIMARY KEY,
|
||||||
trace_id varchar(64) DEFAULT '' NULL,
|
trace_id varchar(64) DEFAULT '' NULL,
|
||||||
user_id bigint NOT NULL,
|
user_id bigint NULL,
|
||||||
user_type smallint DEFAULT 0 NOT NULL,
|
user_type smallint DEFAULT 0 NOT NULL,
|
||||||
type varchar(50) NOT NULL,
|
type varchar(50) NOT NULL,
|
||||||
sub_type varchar(50) NOT NULL,
|
sub_type varchar(50) NOT NULL,
|
||||||
@@ -3560,7 +3676,7 @@ COMMENT ON TABLE system_users IS '用户信息表';
|
|||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- @formatter:off
|
-- @formatter:off
|
||||||
-- SET IDENTITY_INSERT system_users ON;
|
-- SET IDENTITY_INSERT system_users ON;
|
||||||
INSERT INTO system_users (id, username, password, nickname, workcode, remark, post_ids, email, mobile, sex, user_source, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1, 'admin', '$2a$04$KljJDa/LK7QfDm0lF5OhuePhlPfjRH3tB2Wu351Uidz.oQGJXevPi', '后台管理', NULL, '管理员', '[1,2]', '11aoteman@126.com', '18818260277', 2, 1, 'http://test.zt.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', '0', 1);
|
INSERT INTO system_users (id, username, password, nickname, workcode, remark, post_ids, email, mobile, sex, user_source, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1, 'admin', '$2a$04$KljJDa/LK7QfDm0lF5OhuePhlPfjRH3tB2Wu351Uidz.oQGJXevPi', '后台管理', NULL, '管理员', '[1,2]', '11aoteman@126.com', '18818260277', 2, 1, NULL, 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', '0', 1);
|
||||||
INSERT INTO system_users (id, username, password, nickname, workcode, remark, post_ids, email, mobile, sex, user_source, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (100, 'zt', '$2a$04$h.aaPKgO.odHepnk5PCsWeEwKdojFWdTItxGKfx1r0e1CSeBzsTJ6', 'ZT', NULL, '不要吓我', '[1]', 'zt@iocoder.cn', '15601691300', 1, 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', '0', 1);
|
INSERT INTO system_users (id, username, password, nickname, workcode, remark, post_ids, email, mobile, sex, user_source, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (100, 'zt', '$2a$04$h.aaPKgO.odHepnk5PCsWeEwKdojFWdTItxGKfx1r0e1CSeBzsTJ6', 'ZT', NULL, '不要吓我', '[1]', 'zt@iocoder.cn', '15601691300', 1, 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', '0', 1);
|
||||||
INSERT INTO system_users (id, username, password, nickname, workcode, remark, post_ids, email, mobile, sex, user_source, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (103, 'yuanma', '$2a$04$fUBSmjKCPYAUmnMzOb6qE.eZCGPhHi1JmAKclODbfS/O7fHOl2bH6', '源码', NULL, NULL, NULL, 'yuanma@iocoder.cn', '15601701300', 0, 1, 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', '0', 1);
|
INSERT INTO system_users (id, username, password, nickname, workcode, remark, post_ids, email, mobile, sex, user_source, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (103, 'yuanma', '$2a$04$fUBSmjKCPYAUmnMzOb6qE.eZCGPhHi1JmAKclODbfS/O7fHOl2bH6', '源码', NULL, NULL, NULL, 'yuanma@iocoder.cn', '15601701300', 0, 1, 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', '0', 1);
|
||||||
INSERT INTO system_users (id, username, password, nickname, workcode, remark, post_ids, email, mobile, sex, user_source, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (104, 'test', '$2a$04$BrwaYn303hjA/6TnXqdGoOLhyHOAA0bVrAFu6.1dJKycqKUnIoRz2', '测试号', NULL, NULL, '[1,2]', '111@qq.com', '15601691200', 1, 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', '0', 1);
|
INSERT INTO system_users (id, username, password, nickname, workcode, remark, post_ids, email, mobile, sex, user_source, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (104, 'test', '$2a$04$BrwaYn303hjA/6TnXqdGoOLhyHOAA0bVrAFu6.1dJKycqKUnIoRz2', '测试号', NULL, NULL, '[1,2]', '111@qq.com', '15601691200', 1, 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', '0', 1);
|
||||||
@@ -3897,6 +4013,7 @@ CREATE TABLE infra_bsn_file (
|
|||||||
file_id bigint NOT NULL,
|
file_id bigint NOT NULL,
|
||||||
file_name varchar(500) DEFAULT '' NULL,
|
file_name varchar(500) DEFAULT '' NULL,
|
||||||
src varchar(100) DEFAULT '' NULL,
|
src varchar(100) DEFAULT '' NULL,
|
||||||
|
status smallint DEFAULT 1 NOT NULL,
|
||||||
creator varchar(64) DEFAULT '' NULL,
|
creator varchar(64) DEFAULT '' NULL,
|
||||||
create_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
create_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||||
updater varchar(64) DEFAULT '' NULL,
|
updater varchar(64) DEFAULT '' NULL,
|
||||||
@@ -3911,13 +4028,14 @@ COMMENT ON COLUMN infra_bsn_file.bsn_cd IS '业务编码';
|
|||||||
COMMENT ON COLUMN infra_bsn_file.file_id IS '附件fileId';
|
COMMENT ON COLUMN infra_bsn_file.file_id IS '附件fileId';
|
||||||
COMMENT ON COLUMN infra_bsn_file.file_name IS '附件名称';
|
COMMENT ON COLUMN infra_bsn_file.file_name IS '附件名称';
|
||||||
COMMENT ON COLUMN infra_bsn_file.src IS '附件来源';
|
COMMENT ON COLUMN infra_bsn_file.src IS '附件来源';
|
||||||
|
COMMENT ON COLUMN infra_bsn_file.status IS '状态(1-正常,0-禁用)';
|
||||||
COMMENT ON COLUMN infra_bsn_file.creator IS '创建者';
|
COMMENT ON COLUMN infra_bsn_file.creator IS '创建者';
|
||||||
COMMENT ON COLUMN infra_bsn_file.create_time IS '创建时间';
|
COMMENT ON COLUMN infra_bsn_file.create_time IS '创建时间';
|
||||||
COMMENT ON COLUMN infra_bsn_file.updater IS '更新者';
|
COMMENT ON COLUMN infra_bsn_file.updater IS '更新者';
|
||||||
COMMENT ON COLUMN infra_bsn_file.update_time IS '最后更新时间';
|
COMMENT ON COLUMN infra_bsn_file.update_time IS '最后更新时间';
|
||||||
COMMENT ON COLUMN infra_bsn_file.deleted IS '是否删除';
|
COMMENT ON COLUMN infra_bsn_file.deleted IS '是否删除';
|
||||||
COMMENT ON COLUMN infra_bsn_file.tenant_id IS '租户编号';
|
COMMENT ON COLUMN infra_bsn_file.tenant_id IS '租户编号';
|
||||||
COMMENT ON TABLE infra_bsn_file IS '业务附件表';
|
COMMENT ON TABLE infra_bsn_file IS '业务附件关联表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for system_seq
|
-- Table structure for system_seq
|
||||||
@@ -4004,3 +4122,192 @@ COMMENT ON COLUMN system_seq_rcd.updater IS '更新者';
|
|||||||
COMMENT ON COLUMN system_seq_rcd.update_time IS '更新时间';
|
COMMENT ON COLUMN system_seq_rcd.update_time IS '更新时间';
|
||||||
COMMENT ON COLUMN system_seq_rcd.deleted IS '是否删除';
|
COMMENT ON COLUMN system_seq_rcd.deleted IS '是否删除';
|
||||||
COMMENT ON TABLE system_seq_rcd IS '系统序列号记录表';
|
COMMENT ON TABLE system_seq_rcd IS '系统序列号记录表';
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status, component_name
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1948328245618204673', '业务附件关联管理', '', 2, 0, 1243,
|
||||||
|
'business-file', '', 'infra/businessfile/index', 0, 'BusinessFile'
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1951092724040097793', '业务附件关联查询', 'infra:business-file:query', 3, 1, 1948328245618204673,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1951092724040097794', '业务附件关联创建', 'infra:business-file:create', 3, 2, 1948328245618204673,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1951092724040097795', '业务附件关联更新', 'infra:business-file:update', 3, 3, 1948328245618204673,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1951092724040097796', '业务附件关联删除', 'infra:business-file:delete', 3, 4, 1948328245618204673,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1951092724040097797', '业务附件关联导出', 'infra:business-file:export', 3, 5, 1948328245618204673,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 数据命名与简写标准菜单
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status, component_name
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1947909810016006146', '数据命名与简写标准管理', '', 2, 0, 2,
|
||||||
|
'standard-name', '', 'infra/standardname/index', 0, 'StandardName'
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1953301310553645058', '数据命名与简写标准查询', 'infra:standard-name:query', 3, 1, 1947909810016006146,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1953301310553645059', '数据命名与简写标准创建', 'infra:standard-name:create', 3, 2, 1947909810016006146,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1953301310553645060', '数据命名与简写标准更新', 'infra:standard-name:update', 3, 3, 1947909810016006146,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1953301310553645061', '数据命名与简写标准删除', 'infra:standard-name:delete', 3, 4, 1947909810016006146,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1953301310553645062', '数据命名与简写标准导出', 'infra:standard-name:export', 3, 5, 1947909810016006146,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 系统序列号菜单
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status, component_name
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1953701540574969857', '系统序列号管理', '', 2, 0, 1,
|
||||||
|
'sequence', '', 'system/sequence/index', 0, 'Sequence'
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1953702581324398594', '系统序列号查询', 'system:sequence:query', 3, 1, 1953701540574969857,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1953702581324398595', '系统序列号创建', 'system:sequence:create', 3, 2, 1953701540574969857,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1953702581324398596', '系统序列号更新', 'system:sequence:update', 3, 3, 1953701540574969857,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1953702581324398597', '系统序列号删除', 'system:sequence:delete', 3, 4, 1953701540574969857,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
INSERT INTO system_menu(
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'1953702581324398598', '系统序列号导出', 'system:sequence:export', 3, 5, 1953701540574969857,
|
||||||
|
'', '', '', 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 系统序列号相关字典数据初始化
|
||||||
|
INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time)
|
||||||
|
VALUES (500, '系统序列号循环类型', 'system_sequence_cycle_type', 0, '系统序列号循环类型枚举', 'admin', SYSDATE, 'admin', SYSDATE, 0, NULL);
|
||||||
|
|
||||||
|
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
|
||||||
|
(5001, 1, '年循环', 'Y', 'system_sequence_cycle_type', 0, 'primary', '', '年循环。示例: 2025', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5002, 2, '年-月循环', 'Y-M', 'system_sequence_cycle_type', 0, 'success', '', '年-月循环。示例: 2025-08', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5003, 3, '年月紧凑', 'YM', 'system_sequence_cycle_type', 0, 'info', '', '年月紧凑。示例: 202508', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5004, 4, '两位年+月', 'yM', 'system_sequence_cycle_type', 0, 'warning', '', '两位年+月。示例: 2508', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5005, 5, '年-月-日循环', 'Y-M-D', 'system_sequence_cycle_type', 0, 'primary', '', '年-月-日循环。示例: 2025-08-08', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5006, 6, '年月日紧凑', 'YMD', 'system_sequence_cycle_type', 0, 'success', '', '年月日紧凑。示例: 20250808', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5007, 7, '两位年+月日', 'yMD', 'system_sequence_cycle_type', 0, 'info', '', '两位年+月日。示例: 250808', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5008, 8, '自定义循环值', 'CUST', 'system_sequence_cycle_type', 0, 'warning', '', '自定义循环值;若未传 circulationValue,则默认用 seqId', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5009, 9, '仅前缀', 'PFX', 'system_sequence_cycle_type', 0, 'danger', '', '仅前缀,不需要时间循环值(不设置则不抛错)', 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time)
|
||||||
|
VALUES (501, '系统序列号分段类型', 'system_sequence_detail_type', 0, '系统序列号分段类型枚举', 'admin', SYSDATE, 'admin', SYSDATE, 0, NULL);
|
||||||
|
|
||||||
|
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
|
||||||
|
(5011, 1, '默认字符分段', 'STR', 'system_sequence_detail_type', 0, 'primary', '', '固定字符串分段', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5012, 2, '给定字符分段', 'INPUT', 'system_sequence_detail_type', 0, 'success', '', '根据输入参数动态生成的字符分段', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5013, 3, '日期分段', 'DATE', 'system_sequence_detail_type', 0, 'info', '', '基于日期格式的分段', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5014, 4, '流水号分段', 'SEQ', 'system_sequence_detail_type', 0, 'warning', '', '自增流水号分段', 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time)
|
||||||
|
VALUES (502, '系统序列号分段规则类型', 'system_sequence_detail_rule_type', 0, '系统序列号分段规则类型枚举', 'admin', SYSDATE, 'admin', SYSDATE, 0, NULL);
|
||||||
|
|
||||||
|
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
|
||||||
|
(5021, 1, '固定值', 'FIXED', 'system_sequence_detail_rule_type', 0, 'primary', '', '固定字符串值', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5022, 2, '日期格式', 'DATE', 'system_sequence_detail_rule_type', 0, 'success', '', '日期格式规则', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5023, 3, '数字格式', 'NUMBER', 'system_sequence_detail_rule_type', 0, 'info', '', '数字格式规则', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||||
|
(5024, 4, '自定义格式', 'CUSTOM', 'system_sequence_detail_rule_type', 0, 'warning', '', '自定义格式规则', 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ CREATE TABLE databus_api_definition_credential (
|
|||||||
deleted BIT DEFAULT '0' NOT NULL
|
deleted BIT DEFAULT '0' NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE UNIQUE INDEX uk_databus_api_definition_credential ON databus_api_definition_credential (api_id, credential_id, deleted);
|
-- 去掉错误的唯一索引逻辑
|
||||||
|
-- CREATE UNIQUE INDEX uk_databus_api_definition_credential ON databus_api_definition_credential (api_id, credential_id, deleted);
|
||||||
CREATE INDEX idx_databus_api_definition_credential_api ON databus_api_definition_credential (api_id);
|
CREATE INDEX idx_databus_api_definition_credential_api ON databus_api_definition_credential (api_id);
|
||||||
CREATE INDEX idx_databus_api_definition_credential_cred ON databus_api_definition_credential (credential_id);
|
CREATE INDEX idx_databus_api_definition_credential_cred ON databus_api_definition_credential (credential_id);
|
||||||
|
|
||||||
|
|||||||
10
sql/dm/流程定义扩展信息表新增字段_20251230.sql
Normal file
10
sql/dm/流程定义扩展信息表新增字段_20251230.sql
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
-- 达梦8数据库DDL脚本
|
||||||
|
-- 为 bpm_process_definition_info 表添加 restart 字段
|
||||||
|
|
||||||
|
-- 是否允许重新发起
|
||||||
|
ALTER TABLE bpm_process_definition_info ADD COLUMN restart bit DEFAULT '1' NOT NULL;
|
||||||
|
|
||||||
|
-- 添加字段注释
|
||||||
|
COMMENT ON COLUMN bpm_process_definition_info.restart IS '是否允许重新发起';
|
||||||
|
|
||||||
|
|
||||||
@@ -26,12 +26,13 @@
|
|||||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>3.0.45</revision>
|
<revision>3.0.46</revision>
|
||||||
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
|
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
|
||||||
<!-- 统一依赖管理 -->
|
<!-- 统一依赖管理 -->
|
||||||
<spring.boot.version>3.4.5</spring.boot.version>
|
<spring.boot.version>3.4.5</spring.boot.version>
|
||||||
<spring.cloud.version>2024.0.1</spring.cloud.version>
|
<spring.cloud.version>2024.0.1</spring.cloud.version>
|
||||||
<spring.cloud.alibaba.version>2023.0.3.2</spring.cloud.alibaba.version>
|
<spring.cloud.alibaba.version>2023.0.3.2</spring.cloud.alibaba.version>
|
||||||
|
<seata.version>2.4.0</seata.version>
|
||||||
<!-- Web 相关 -->
|
<!-- Web 相关 -->
|
||||||
<springdoc.version>2.8.3</springdoc.version>
|
<springdoc.version>2.8.3</springdoc.version>
|
||||||
<knife4j.version>4.6.0</knife4j.version>
|
<knife4j.version>4.6.0</knife4j.version>
|
||||||
@@ -133,6 +134,24 @@
|
|||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 分布式事务 Seata (覆盖 Spring Cloud Alibaba 中的 2.1.0 版本) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.seata</groupId>
|
||||||
|
<artifactId>seata-all</artifactId>
|
||||||
|
<version>${seata.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.seata</groupId>
|
||||||
|
<artifactId>seata-spring-boot-starter</artifactId>
|
||||||
|
<version>${seata.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- Seata 达梦数据库补丁 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.zt.plat</groupId>
|
||||||
|
<artifactId>zt-spring-boot-starter-seata-dm</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 业务组件 -->
|
<!-- 业务组件 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.github.mouzt</groupId>
|
<groupId>io.github.mouzt</groupId>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
<module>zt-spring-boot-starter-biz-data-permission</module>
|
<module>zt-spring-boot-starter-biz-data-permission</module>
|
||||||
<module>zt-spring-boot-starter-biz-ip</module>
|
<module>zt-spring-boot-starter-biz-ip</module>
|
||||||
<module>zt-spring-boot-starter-biz-business</module>
|
<module>zt-spring-boot-starter-biz-business</module>
|
||||||
|
<module>zt-spring-boot-starter-seata-dm</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<artifactId>zt-framework</artifactId>
|
<artifactId>zt-framework</artifactId>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.zt.plat.framework.common.util.json.JsonUtils;
|
|||||||
import com.zt.plat.framework.common.util.spring.SpringUtils;
|
import com.zt.plat.framework.common.util.spring.SpringUtils;
|
||||||
import com.zt.plat.framework.security.core.LoginUser;
|
import com.zt.plat.framework.security.core.LoginUser;
|
||||||
import com.zt.plat.framework.tenant.core.context.CompanyContextHolder;
|
import com.zt.plat.framework.tenant.core.context.CompanyContextHolder;
|
||||||
|
import com.zt.plat.framework.tenant.core.context.DeptContextHolder;
|
||||||
import com.zt.plat.framework.web.core.util.WebFrameworkUtils;
|
import com.zt.plat.framework.web.core.util.WebFrameworkUtils;
|
||||||
import com.zt.plat.module.system.api.dept.DeptApi;
|
import com.zt.plat.module.system.api.dept.DeptApi;
|
||||||
import com.zt.plat.module.system.api.dept.dto.CompanyDeptInfoRespDTO;
|
import com.zt.plat.module.system.api.dept.dto.CompanyDeptInfoRespDTO;
|
||||||
@@ -197,6 +198,9 @@ public class BusinessDeptHandleUtil {
|
|||||||
}
|
}
|
||||||
CompanyContextHolder.setIgnore(false);
|
CompanyContextHolder.setIgnore(false);
|
||||||
CompanyContextHolder.setCompanyId(Long.valueOf(info.getCompanyId()));
|
CompanyContextHolder.setCompanyId(Long.valueOf(info.getCompanyId()));
|
||||||
|
DeptContextHolder.setIgnore(false);
|
||||||
|
DeptContextHolder.setCompanyId(Long.valueOf(info.getCompanyId()));
|
||||||
|
DeptContextHolder.setDeptId(Long.valueOf(info.getDeptId()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
|
|||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -18,14 +20,12 @@ import java.util.Set;
|
|||||||
public class BusinessDataPermissionConfiguration {
|
public class BusinessDataPermissionConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public BusinessDataPermissionEntityScanner businessDataPermissionEntityScanner(BeanFactory beanFactory, ApplicationContext applicationContext) {
|
public BusinessDataPermissionEntityScanner businessDataPermissionEntityScanner(BeanFactory beanFactory, ApplicationContext applicationContext, Environment environment) {
|
||||||
Set<String> basePackages = new LinkedHashSet<>();
|
Set<String> basePackages = new LinkedHashSet<>();
|
||||||
|
addConfiguredBasePackages(environment, basePackages);
|
||||||
if (AutoConfigurationPackages.has(beanFactory)) {
|
if (AutoConfigurationPackages.has(beanFactory)) {
|
||||||
basePackages.addAll(AutoConfigurationPackages.get(beanFactory));
|
basePackages.addAll(AutoConfigurationPackages.get(beanFactory));
|
||||||
}
|
}
|
||||||
if (basePackages.isEmpty()) {
|
|
||||||
basePackages.add("com.zt");
|
|
||||||
}
|
|
||||||
ClassLoader classLoader = applicationContext != null
|
ClassLoader classLoader = applicationContext != null
|
||||||
? applicationContext.getClassLoader()
|
? applicationContext.getClassLoader()
|
||||||
: Thread.currentThread().getContextClassLoader();
|
: Thread.currentThread().getContextClassLoader();
|
||||||
@@ -35,6 +35,21 @@ public class BusinessDataPermissionConfiguration {
|
|||||||
return new BusinessDataPermissionEntityScanner(basePackages, classLoader);
|
return new BusinessDataPermissionEntityScanner(basePackages, classLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addConfiguredBasePackages(Environment environment, Set<String> basePackages) {
|
||||||
|
if (environment == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String configured = environment.getProperty("zt.info.base-package");
|
||||||
|
if (!StringUtils.hasText(configured)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (String pkg : configured.split("[,;\\s]+")) {
|
||||||
|
if (StringUtils.hasText(pkg)) {
|
||||||
|
basePackages.add(pkg.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public CompanyDataPermissionRuleCustomizer autoCompanyDataPermissionRuleCustomizer(BusinessDataPermissionEntityScanner scanner) {
|
public CompanyDataPermissionRuleCustomizer autoCompanyDataPermissionRuleCustomizer(BusinessDataPermissionEntityScanner scanner) {
|
||||||
return rule -> scanner.getEntityMetadata().forEach(metadata -> {
|
return rule -> scanner.getEntityMetadata().forEach(metadata -> {
|
||||||
|
|||||||
@@ -28,6 +28,14 @@ import java.util.*;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class BusinessDataPermissionEntityScanner {
|
public class BusinessDataPermissionEntityScanner {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 临时排除的包前缀(物流模块 DO,不参与数据权限扫描)
|
||||||
|
*/
|
||||||
|
private static final Set<String> EXCLUDED_PACKAGE_PREFIXES = Set.of(
|
||||||
|
"com.zt.plat.module.backendlogistics",
|
||||||
|
"com.zt.plat.module.erp",
|
||||||
|
"com.zt.plat.framework.mybatis.core.dataobject.BusinessBaseDO");
|
||||||
|
|
||||||
private final Set<String> basePackages;
|
private final Set<String> basePackages;
|
||||||
private final ClassLoader classLoader;
|
private final ClassLoader classLoader;
|
||||||
|
|
||||||
@@ -70,6 +78,9 @@ public class BusinessDataPermissionEntityScanner {
|
|||||||
if (!StringUtils.hasText(className)) {
|
if (!StringUtils.hasText(className)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (isExcludedPackage(className)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
Class<?> clazz = ClassUtils.forName(className, classLoader);
|
Class<?> clazz = ClassUtils.forName(className, classLoader);
|
||||||
if (clazz == BusinessBaseDO.class || !BusinessBaseDO.class.isAssignableFrom(clazz)) {
|
if (clazz == BusinessBaseDO.class || !BusinessBaseDO.class.isAssignableFrom(clazz)) {
|
||||||
@@ -92,6 +103,15 @@ public class BusinessDataPermissionEntityScanner {
|
|||||||
return new ArrayList<>(metadataMap.values());
|
return new ArrayList<>(metadataMap.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isExcludedPackage(String className) {
|
||||||
|
for (String prefix : EXCLUDED_PACKAGE_PREFIXES) {
|
||||||
|
if (className.startsWith(prefix)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private EntityMetadata buildMetadata(Class<? extends BusinessBaseDO> entityClass) {
|
private EntityMetadata buildMetadata(Class<? extends BusinessBaseDO> entityClass) {
|
||||||
String tableName = resolveTableName(entityClass);
|
String tableName = resolveTableName(entityClass);
|
||||||
if (!StringUtils.hasText(tableName)) {
|
if (!StringUtils.hasText(tableName)) {
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# 数据权限忽略与上下文覆盖说明
|
||||||
|
|
||||||
|
本文说明新增的公司/部门数据权限忽略能力,以及部门上下文对数据权限的覆盖策略。
|
||||||
|
|
||||||
|
## 新增注解
|
||||||
|
|
||||||
|
- `@CompanyDataPermissionIgnore(enable = "true")`
|
||||||
|
- `@DeptDataPermissionIgnore(enable = "true")`
|
||||||
|
|
||||||
|
用法:
|
||||||
|
- 可标记在类或方法上。
|
||||||
|
- `enable` 支持 Spring EL,计算结果为 `true` 时生效,默认开启。
|
||||||
|
- 生效后,在方法执行期间临时设置忽略标记,结束后自动恢复。
|
||||||
|
|
||||||
|
## 忽略生效范围
|
||||||
|
|
||||||
|
- 公司数据权限:切面在进入方法时将 `CompanyContextHolder.setIgnore(true)`,数据权限规则检测到后直接放行。
|
||||||
|
- 部门数据权限:切面在进入方法时将 `DeptContextHolder.setIgnore(true)`,部门数据权限规则检测到后直接放行。
|
||||||
|
|
||||||
|
## 部门上下文覆盖策略
|
||||||
|
|
||||||
|
当未忽略部门数据权限且上下文存在有效部门 ID 时:
|
||||||
|
- 优先使用上下文中的单一部门作为过滤条件,避免因默认的 `ALL` 或“无部门且不可查看自己”导致放行或误判无权。
|
||||||
|
- 上下文部门不会修改原有的数据权限 DTO,仅在当前计算中使用。
|
||||||
|
- 若上下文公司与缓存公司不一致,会记录告警日志,但仍按上下文部门过滤。
|
||||||
|
|
||||||
|
## 典型场景
|
||||||
|
|
||||||
|
1) **任务/全局调用需要暂时关闭数据权限**
|
||||||
|
- 在方法上标记 `@DeptDataPermissionIgnore` 或 `@CompanyDataPermissionIgnore`。
|
||||||
|
|
||||||
|
2) **带部门上下文的接口调用**
|
||||||
|
- 请求预先设置 `DeptContextHolder.setContext(deptId, companyId)`。
|
||||||
|
- 即便数据权限声明为 `all=true`,也会按该部门过滤,避免读出全量。
|
||||||
|
|
||||||
|
3) **无部门权限但指定了上下文部门**
|
||||||
|
- 即使 `deptIds` 为空且 `self=false`,只要上下文提供部门,也会使用该部门过滤,而非直接判定无权。
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
- 忽略标记只作用于当前线程上下文,切面会在 `finally` 中恢复旧值,嵌套调用安全。
|
||||||
|
- 若需要同时忽略公司与部门数据权限,可叠加两个注解或在业务代码中分别设置忽略标记。
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.zt.plat.framework.datapermission.config;
|
package com.zt.plat.framework.datapermission.config;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.datapermission.core.aop.CompanyDataPermissionIgnoreAspect;
|
||||||
import com.zt.plat.framework.datapermission.core.aop.DataPermissionAnnotationAdvisor;
|
import com.zt.plat.framework.datapermission.core.aop.DataPermissionAnnotationAdvisor;
|
||||||
|
import com.zt.plat.framework.datapermission.core.aop.DeptDataPermissionIgnoreAspect;
|
||||||
import com.zt.plat.framework.datapermission.core.db.DataPermissionRuleHandler;
|
import com.zt.plat.framework.datapermission.core.db.DataPermissionRuleHandler;
|
||||||
import com.zt.plat.framework.datapermission.core.rule.DataPermissionRule;
|
import com.zt.plat.framework.datapermission.core.rule.DataPermissionRule;
|
||||||
import com.zt.plat.framework.datapermission.core.rule.DataPermissionRuleFactory;
|
import com.zt.plat.framework.datapermission.core.rule.DataPermissionRuleFactory;
|
||||||
@@ -43,4 +45,14 @@ public class ZtDataPermissionAutoConfiguration {
|
|||||||
return new DataPermissionAnnotationAdvisor();
|
return new DataPermissionAnnotationAdvisor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DeptDataPermissionIgnoreAspect deptDataPermissionIgnoreAspect() {
|
||||||
|
return new DeptDataPermissionIgnoreAspect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CompanyDataPermissionIgnoreAspect companyDataPermissionIgnoreAspect() {
|
||||||
|
return new CompanyDataPermissionIgnoreAspect();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.zt.plat.framework.datapermission.core.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 忽略公司数据权限的注解。
|
||||||
|
* <p>
|
||||||
|
* 标记在方法或类上时,匹配的调用会临时忽略公司类型的数据权限规则。
|
||||||
|
*/
|
||||||
|
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface CompanyDataPermissionIgnore {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否开启忽略,默认开启。
|
||||||
|
* 支持 Spring EL 表达式,返回 true 时生效。
|
||||||
|
*/
|
||||||
|
String enable() default "true";
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.zt.plat.framework.datapermission.core.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 忽略部门数据权限的注解。
|
||||||
|
* <p>
|
||||||
|
* 标记在方法或类上时,匹配的调用会临时忽略部门类型的数据权限规则。
|
||||||
|
*/
|
||||||
|
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface DeptDataPermissionIgnore {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否开启忽略,默认开启。
|
||||||
|
* 支持 Spring EL 表达式,返回 true 时生效。
|
||||||
|
*/
|
||||||
|
String enable() default "true";
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.zt.plat.framework.datapermission.core.aop;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.util.spring.SpringExpressionUtils;
|
||||||
|
import com.zt.plat.framework.datapermission.core.annotation.CompanyDataPermissionIgnore;
|
||||||
|
import com.zt.plat.framework.tenant.core.context.CompanyContextHolder;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公司数据权限忽略切面,基于 {@link CompanyDataPermissionIgnore} 注解。
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Slf4j
|
||||||
|
public class CompanyDataPermissionIgnoreAspect {
|
||||||
|
|
||||||
|
@Around("@within(companyDataPermissionIgnore) || @annotation(companyDataPermissionIgnore)")
|
||||||
|
public Object around(ProceedingJoinPoint joinPoint, CompanyDataPermissionIgnore companyDataPermissionIgnore) throws Throwable {
|
||||||
|
boolean oldIgnore = CompanyContextHolder.isIgnore();
|
||||||
|
try {
|
||||||
|
Object enable = SpringExpressionUtils.parseExpression(companyDataPermissionIgnore.enable());
|
||||||
|
if (Boolean.TRUE.equals(enable)) {
|
||||||
|
CompanyContextHolder.setIgnore(true);
|
||||||
|
}
|
||||||
|
return joinPoint.proceed();
|
||||||
|
} finally {
|
||||||
|
CompanyContextHolder.setIgnore(oldIgnore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.zt.plat.framework.datapermission.core.aop;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.util.spring.SpringExpressionUtils;
|
||||||
|
import com.zt.plat.framework.datapermission.core.annotation.DeptDataPermissionIgnore;
|
||||||
|
import com.zt.plat.framework.tenant.core.context.DeptContextHolder;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门数据权限忽略切面,基于 {@link DeptDataPermissionIgnore} 注解。
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Slf4j
|
||||||
|
public class DeptDataPermissionIgnoreAspect {
|
||||||
|
|
||||||
|
@Around("@within(deptDataPermissionIgnore) || @annotation(deptDataPermissionIgnore)")
|
||||||
|
public Object around(ProceedingJoinPoint joinPoint, DeptDataPermissionIgnore deptDataPermissionIgnore) throws Throwable {
|
||||||
|
boolean oldIgnore = DeptContextHolder.shouldIgnore();
|
||||||
|
try {
|
||||||
|
Object enable = SpringExpressionUtils.parseExpression(deptDataPermissionIgnore.enable());
|
||||||
|
if (Boolean.TRUE.equals(enable)) {
|
||||||
|
DeptContextHolder.setIgnore(true);
|
||||||
|
}
|
||||||
|
return joinPoint.proceed();
|
||||||
|
} finally {
|
||||||
|
DeptContextHolder.setIgnore(oldIgnore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,9 @@ import net.sf.jsqlparser.expression.Expression;
|
|||||||
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
|
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
|
||||||
import net.sf.jsqlparser.schema.Table;
|
import net.sf.jsqlparser.schema.Table;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static com.zt.plat.framework.security.core.util.SecurityFrameworkUtils.skipPermissionCheck;
|
import static com.zt.plat.framework.security.core.util.SecurityFrameworkUtils.skipPermissionCheck;
|
||||||
|
|
||||||
@@ -41,6 +43,7 @@ public class DataPermissionRuleHandler implements MultiDataPermissionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 生成条件
|
// 生成条件
|
||||||
|
final Set<String> processed = new HashSet<>();
|
||||||
Expression allExpression = null;
|
Expression allExpression = null;
|
||||||
for (DataPermissionRule rule : rules) {
|
for (DataPermissionRule rule : rules) {
|
||||||
// 判断表名是否匹配
|
// 判断表名是否匹配
|
||||||
@@ -49,6 +52,14 @@ public class DataPermissionRuleHandler implements MultiDataPermissionHandler {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 同一张表 + 同一别名 + 同一规则 在一次 SQL 解析内仅处理一次,避免重复拼接条件
|
||||||
|
String aliasName = table.getAlias() == null ? "" : table.getAlias().getName();
|
||||||
|
String key = tableName + "|" + aliasName + "|" + rule.getClass().getName();
|
||||||
|
if (processed.contains(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
processed.add(key);
|
||||||
|
|
||||||
// 单条规则的条件
|
// 单条规则的条件
|
||||||
Expression oneExpress = rule.getExpression(tableName, table.getAlias());
|
Expression oneExpress = rule.getExpression(tableName, table.getAlias());
|
||||||
if (oneExpress == null) {
|
if (oneExpress == null) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import cn.hutool.core.util.StrUtil;
|
|||||||
import com.zt.plat.framework.common.util.collection.CollectionUtils;
|
import com.zt.plat.framework.common.util.collection.CollectionUtils;
|
||||||
import com.zt.plat.framework.datapermission.core.rule.DataPermissionRule;
|
import com.zt.plat.framework.datapermission.core.rule.DataPermissionRule;
|
||||||
import com.zt.plat.framework.mybatis.core.util.MyBatisUtils;
|
import com.zt.plat.framework.mybatis.core.util.MyBatisUtils;
|
||||||
|
import com.zt.plat.framework.tenant.core.context.CompanyContextHolder;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.sf.jsqlparser.expression.Alias;
|
import net.sf.jsqlparser.expression.Alias;
|
||||||
@@ -49,6 +50,10 @@ public class CompanyDataPermissionRule implements DataPermissionRule {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Expression getExpression(String tableName, Alias tableAlias) {
|
public Expression getExpression(String tableName, Alias tableAlias) {
|
||||||
|
// 显式忽略公司数据权限时直接放行
|
||||||
|
if (CompanyContextHolder.isIgnore()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
// 业务拼接 Company 的条件
|
// 业务拼接 Company 的条件
|
||||||
if (getLoginUserCompanyId() == null) {
|
if (getLoginUserCompanyId() == null) {
|
||||||
// 如果没有登录用户的公司编号,则不需要拼接条件
|
// 如果没有登录用户的公司编号,则不需要拼接条件
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.zt.plat.framework.datapermission.core.rule.dept;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||||
import com.zt.plat.framework.common.biz.system.permission.PermissionCommonApi;
|
import com.zt.plat.framework.common.biz.system.permission.PermissionCommonApi;
|
||||||
import com.zt.plat.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO;
|
import com.zt.plat.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO;
|
||||||
import com.zt.plat.framework.common.enums.UserTypeEnum;
|
import com.zt.plat.framework.common.enums.UserTypeEnum;
|
||||||
@@ -14,7 +15,7 @@ import com.zt.plat.framework.mybatis.core.util.MyBatisUtils;
|
|||||||
import com.zt.plat.framework.security.core.LoginUser;
|
import com.zt.plat.framework.security.core.LoginUser;
|
||||||
import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils;
|
import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import com.zt.plat.framework.tenant.core.context.CompanyContextHolder;
|
import com.zt.plat.framework.tenant.core.context.CompanyContextHolder;
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
import com.zt.plat.framework.tenant.core.context.DeptContextHolder;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.sf.jsqlparser.expression.Alias;
|
import net.sf.jsqlparser.expression.Alias;
|
||||||
@@ -108,6 +109,11 @@ public class DeptDataPermissionRule implements DataPermissionRule {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 显式忽略部门数据权限时直接放行
|
||||||
|
if (DeptContextHolder.shouldIgnore()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// 获得数据权限
|
// 获得数据权限
|
||||||
DeptDataPermissionRespDTO deptDataPermission = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
|
DeptDataPermissionRespDTO deptDataPermission = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
|
||||||
// 从上下文中拿不到,则调用逻辑进行获取
|
// 从上下文中拿不到,则调用逻辑进行获取
|
||||||
@@ -136,21 +142,42 @@ public class DeptDataPermissionRule implements DataPermissionRule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 情况一,如果是 ALL 可查看全部,则无需拼接条件
|
// 若存在部门上下文,优先使用上下文中的单一部门,必要时校验公司一致性
|
||||||
if (deptDataPermission.getAll()) {
|
Long ctxDeptId = DeptContextHolder.getDeptId();
|
||||||
|
if (ctxDeptId != null && ctxDeptId > 0L) {
|
||||||
|
Long currentCompanyId = CompanyContextHolder.getCompanyId();
|
||||||
|
Long ctxCompanyId = DeptContextHolder.getCompanyId();
|
||||||
|
Long compareCompanyId = ctxCompanyId != null ? ctxCompanyId : currentCompanyId;
|
||||||
|
if (currentCompanyId != null && currentCompanyId > 0L
|
||||||
|
&& compareCompanyId != null && !currentCompanyId.equals(compareCompanyId)) {
|
||||||
|
log.warn("[getExpression][LoginUser({}) Table({}/{}) DeptContextHolder company mismatch: currentCompanyId={}, ctxCompanyId={}, ctxDeptId={}, source=DeptContextHolder]",
|
||||||
|
JsonUtils.toJsonString(loginUser), tableName, tableAlias == null ? null : tableAlias.getName(),
|
||||||
|
currentCompanyId, compareCompanyId, ctxDeptId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算有效的部门与自查标记:当存在上下文部门且未被忽略时,强制仅使用该部门,以避免默认全量或空权限分支
|
||||||
|
Set<Long> effectiveDeptIds = deptDataPermission.getDeptIds();
|
||||||
|
Boolean effectiveSelf = deptDataPermission.getSelf();
|
||||||
|
if (!DeptContextHolder.shouldIgnore() && ctxDeptId != null && ctxDeptId > 0L) {
|
||||||
|
effectiveDeptIds = CollUtil.newHashSet(ctxDeptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 情况一:仅当不存在上下文部门时,且 ALL 可查看全部,才无需拼接条件;若存在上下文部门则仍需基于该部门过滤
|
||||||
|
if (ctxDeptId == null && deptDataPermission.getAll()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 情况二,即不能查看部门,又不能查看自己,则说明 100% 无权限
|
// 情况二:仅在有效部门集合为空且不可查看自己时,才认为无权限;若上下文提供部门,则跳过该兜底
|
||||||
if (CollUtil.isEmpty(deptDataPermission.getDeptIds())
|
if (CollUtil.isEmpty(effectiveDeptIds)
|
||||||
&& Boolean.FALSE.equals(deptDataPermission.getSelf())) {
|
&& Boolean.FALSE.equals(effectiveSelf)) {
|
||||||
return new EqualsTo(null, null); // WHERE null = null,可以保证返回的数据为空
|
return new EqualsTo(null, null); // WHERE null = null,可以保证返回的数据为空
|
||||||
}
|
}
|
||||||
|
|
||||||
// 情况三,拼接 Dept 和 Company User 的条件,最后组合
|
// 情况三,拼接 Dept 和 Company User 的条件,最后组合
|
||||||
Expression deptExpression = buildDeptExpression(tableName, tableAlias, deptDataPermission.getDeptIds());
|
Expression deptExpression = buildDeptExpression(tableName, tableAlias, effectiveDeptIds);
|
||||||
// Expression deptExpression = buildDeptExpression(tableName, tableAlias, deptDataPermission.getDeptIds());
|
// Expression deptExpression = buildDeptExpression(tableName, tableAlias, deptDataPermission.getDeptIds());
|
||||||
Expression userExpression = buildUserExpression(tableName, tableAlias, deptDataPermission.getSelf(), loginUser.getId());
|
Expression userExpression = buildUserExpression(tableName, tableAlias, effectiveSelf, loginUser.getId());
|
||||||
if (deptExpression == null && userExpression == null) {
|
if (deptExpression == null && userExpression == null) {
|
||||||
// TODO ZT:获得不到条件的时候,暂时不抛出异常,而是不返回数据
|
// TODO ZT:获得不到条件的时候,暂时不抛出异常,而是不返回数据
|
||||||
log.warn("[getExpression][LoginUser({}) Table({}/{}) DeptDataPermission({}) 构建的条件为空]",
|
log.warn("[getExpression][LoginUser({}) Table({}/{}) DeptDataPermission({}) 构建的条件为空]",
|
||||||
|
|||||||
@@ -7,10 +7,13 @@ import com.zt.plat.framework.common.enums.UserTypeEnum;
|
|||||||
import com.zt.plat.framework.common.util.collection.SetUtils;
|
import com.zt.plat.framework.common.util.collection.SetUtils;
|
||||||
import com.zt.plat.framework.security.core.LoginUser;
|
import com.zt.plat.framework.security.core.LoginUser;
|
||||||
import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils;
|
import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
|
import com.zt.plat.framework.tenant.core.context.CompanyContextHolder;
|
||||||
|
import com.zt.plat.framework.tenant.core.context.DeptContextHolder;
|
||||||
import com.zt.plat.framework.test.core.ut.BaseMockitoUnitTest;
|
import com.zt.plat.framework.test.core.ut.BaseMockitoUnitTest;
|
||||||
import com.zt.plat.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO;
|
import com.zt.plat.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO;
|
||||||
import net.sf.jsqlparser.expression.Alias;
|
import net.sf.jsqlparser.expression.Alias;
|
||||||
import net.sf.jsqlparser.expression.Expression;
|
import net.sf.jsqlparser.expression.Expression;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
@@ -27,6 +30,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.ArgumentMatchers.same;
|
import static org.mockito.ArgumentMatchers.same;
|
||||||
import static org.mockito.Mockito.mockStatic;
|
import static org.mockito.Mockito.mockStatic;
|
||||||
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +52,13 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
|
|||||||
// 清空 rule
|
// 清空 rule
|
||||||
rule.getTableNames().clear();
|
rule.getTableNames().clear();
|
||||||
((Map<String, String>) ReflectUtil.getFieldValue(rule, "deptColumns")).clear();
|
((Map<String, String>) ReflectUtil.getFieldValue(rule, "deptColumns")).clear();
|
||||||
((Map<String, String>) ReflectUtil.getFieldValue(rule, "deptColumns")).clear();
|
((Map<String, String>) ReflectUtil.getFieldValue(rule, "userColumns")).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() {
|
||||||
|
DeptContextHolder.clear();
|
||||||
|
CompanyContextHolder.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // 无 LoginUser
|
@Test // 无 LoginUser
|
||||||
@@ -236,4 +246,151 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // 忽略部门数据权限,直接放行
|
||||||
|
void testGetExpression_ignoreDeptContext() {
|
||||||
|
try (MockedStatic<SecurityFrameworkUtils> secMock = mockStatic(SecurityFrameworkUtils.class);
|
||||||
|
MockedStatic<DeptContextHolder> deptCtxMock = mockStatic(DeptContextHolder.class)) {
|
||||||
|
String tableName = "t_order";
|
||||||
|
Alias alias = new Alias("o");
|
||||||
|
LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
|
||||||
|
.setUserType(UserTypeEnum.ADMIN.getValue()));
|
||||||
|
secMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
|
||||||
|
deptCtxMock.when(DeptContextHolder::shouldIgnore).thenReturn(true);
|
||||||
|
|
||||||
|
Expression expression = rule.getExpression(tableName, alias);
|
||||||
|
|
||||||
|
assertNull(expression);
|
||||||
|
verifyNoInteractions(permissionApi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // 上下文部门存在且公司一致时,表达式按上下文 deptId 生效,但不修改原数据权限集合
|
||||||
|
void testGetExpression_deptContextOverride_companyMatch() {
|
||||||
|
try (MockedStatic<SecurityFrameworkUtils> secMock = mockStatic(SecurityFrameworkUtils.class);
|
||||||
|
MockedStatic<DeptContextHolder> deptCtxMock = mockStatic(DeptContextHolder.class);
|
||||||
|
MockedStatic<CompanyContextHolder> companyCtxMock = mockStatic(CompanyContextHolder.class)) {
|
||||||
|
|
||||||
|
String tableName = "t_user";
|
||||||
|
Alias tableAlias = new Alias("u");
|
||||||
|
LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
|
||||||
|
.setUserType(UserTypeEnum.ADMIN.getValue()));
|
||||||
|
secMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
|
||||||
|
|
||||||
|
DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
|
||||||
|
.setDeptIds(CollUtil.newLinkedHashSet(10L, 20L))
|
||||||
|
.setCompanyId(1L);
|
||||||
|
when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
|
||||||
|
|
||||||
|
deptCtxMock.when(DeptContextHolder::shouldIgnore).thenReturn(false);
|
||||||
|
deptCtxMock.when(DeptContextHolder::getDeptId).thenReturn(99L);
|
||||||
|
deptCtxMock.when(DeptContextHolder::getCompanyId).thenReturn(1L);
|
||||||
|
companyCtxMock.when(CompanyContextHolder::getCompanyId).thenReturn(1L);
|
||||||
|
companyCtxMock.when(CompanyContextHolder::isIgnore).thenReturn(false);
|
||||||
|
|
||||||
|
rule.addDeptColumn(tableName, "dept_id");
|
||||||
|
|
||||||
|
Expression expression = rule.getExpression(tableName, tableAlias);
|
||||||
|
|
||||||
|
assertEquals("u.dept_id IN (99)", expression.toString());
|
||||||
|
// 原始权限对象不被修改,只是临时使用上下文 deptId 计算
|
||||||
|
assertEquals(CollUtil.newLinkedHashSet(10L, 20L), deptDataPermission.getDeptIds());
|
||||||
|
assertEquals(1L, deptDataPermission.getCompanyId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // 上下文部门存在但公司不一致时,仍按上下文 deptId 过滤,原数据权限保持不变
|
||||||
|
void testGetExpression_deptContextOverride_companyMismatch() {
|
||||||
|
try (MockedStatic<SecurityFrameworkUtils> secMock = mockStatic(SecurityFrameworkUtils.class);
|
||||||
|
MockedStatic<DeptContextHolder> deptCtxMock = mockStatic(DeptContextHolder.class);
|
||||||
|
MockedStatic<CompanyContextHolder> companyCtxMock = mockStatic(CompanyContextHolder.class)) {
|
||||||
|
|
||||||
|
String tableName = "t_user";
|
||||||
|
Alias tableAlias = new Alias("u");
|
||||||
|
LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
|
||||||
|
.setUserType(UserTypeEnum.ADMIN.getValue()));
|
||||||
|
secMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
|
||||||
|
|
||||||
|
DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
|
||||||
|
.setDeptIds(CollUtil.newLinkedHashSet(10L))
|
||||||
|
.setCompanyId(1L);
|
||||||
|
when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
|
||||||
|
|
||||||
|
deptCtxMock.when(DeptContextHolder::shouldIgnore).thenReturn(false);
|
||||||
|
deptCtxMock.when(DeptContextHolder::getDeptId).thenReturn(99L);
|
||||||
|
deptCtxMock.when(DeptContextHolder::getCompanyId).thenReturn(2L);
|
||||||
|
companyCtxMock.when(CompanyContextHolder::getCompanyId).thenReturn(1L);
|
||||||
|
companyCtxMock.when(CompanyContextHolder::isIgnore).thenReturn(false);
|
||||||
|
|
||||||
|
rule.addDeptColumn(tableName, "dept_id");
|
||||||
|
|
||||||
|
Expression expression = rule.getExpression(tableName, tableAlias);
|
||||||
|
|
||||||
|
assertEquals("u.dept_id IN (99)", expression.toString());
|
||||||
|
// 原始权限对象不被修改
|
||||||
|
assertEquals(CollUtil.newLinkedHashSet(10L), deptDataPermission.getDeptIds());
|
||||||
|
assertEquals(1L, deptDataPermission.getCompanyId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // ALL 权限但存在上下文部门时,仍按上下文部门过滤
|
||||||
|
void testGetExpression_allPermission_withCtxDept() {
|
||||||
|
try (MockedStatic<SecurityFrameworkUtils> secMock = mockStatic(SecurityFrameworkUtils.class);
|
||||||
|
MockedStatic<DeptContextHolder> deptCtxMock = mockStatic(DeptContextHolder.class);
|
||||||
|
MockedStatic<CompanyContextHolder> companyCtxMock = mockStatic(CompanyContextHolder.class)) {
|
||||||
|
|
||||||
|
String tableName = "t_user";
|
||||||
|
Alias tableAlias = new Alias("u");
|
||||||
|
LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
|
||||||
|
.setUserType(UserTypeEnum.ADMIN.getValue()));
|
||||||
|
secMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
|
||||||
|
|
||||||
|
DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
|
||||||
|
.setAll(true)
|
||||||
|
.setDeptIds(CollUtil.newLinkedHashSet(10L));
|
||||||
|
when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
|
||||||
|
|
||||||
|
deptCtxMock.when(DeptContextHolder::shouldIgnore).thenReturn(false);
|
||||||
|
deptCtxMock.when(DeptContextHolder::getDeptId).thenReturn(99L);
|
||||||
|
deptCtxMock.when(DeptContextHolder::getCompanyId).thenReturn(1L);
|
||||||
|
companyCtxMock.when(CompanyContextHolder::getCompanyId).thenReturn(1L);
|
||||||
|
companyCtxMock.when(CompanyContextHolder::isIgnore).thenReturn(false);
|
||||||
|
|
||||||
|
rule.addDeptColumn(tableName, "dept_id");
|
||||||
|
|
||||||
|
Expression expression = rule.getExpression(tableName, tableAlias);
|
||||||
|
|
||||||
|
assertEquals("u.dept_id IN (99)", expression.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // 无部门且不可查看自己,但上下文提供部门时,应使用上下文部门而非判定无权限
|
||||||
|
void testGetExpression_noDeptNoSelf_withCtxDept() {
|
||||||
|
try (MockedStatic<SecurityFrameworkUtils> secMock = mockStatic(SecurityFrameworkUtils.class);
|
||||||
|
MockedStatic<DeptContextHolder> deptCtxMock = mockStatic(DeptContextHolder.class);
|
||||||
|
MockedStatic<CompanyContextHolder> companyCtxMock = mockStatic(CompanyContextHolder.class)) {
|
||||||
|
|
||||||
|
String tableName = "t_user";
|
||||||
|
Alias tableAlias = new Alias("u");
|
||||||
|
LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
|
||||||
|
.setUserType(UserTypeEnum.ADMIN.getValue()));
|
||||||
|
secMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
|
||||||
|
|
||||||
|
DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
|
||||||
|
.setSelf(false);
|
||||||
|
when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
|
||||||
|
|
||||||
|
deptCtxMock.when(DeptContextHolder::shouldIgnore).thenReturn(false);
|
||||||
|
deptCtxMock.when(DeptContextHolder::getDeptId).thenReturn(88L);
|
||||||
|
deptCtxMock.when(DeptContextHolder::getCompanyId).thenReturn(1L);
|
||||||
|
companyCtxMock.when(CompanyContextHolder::getCompanyId).thenReturn(1L);
|
||||||
|
companyCtxMock.when(CompanyContextHolder::isIgnore).thenReturn(false);
|
||||||
|
|
||||||
|
rule.addDeptColumn(tableName, "dept_id");
|
||||||
|
|
||||||
|
Expression expression = rule.getExpression(tableName, tableAlias);
|
||||||
|
|
||||||
|
assertEquals("u.dept_id IN (88)", expression.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.zt.plat.framework.tenant.core.context;
|
||||||
|
|
||||||
|
import com.alibaba.ttl.TransmittableThreadLocal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门上下文 Holder,使用 {@link TransmittableThreadLocal} 支持在线程池/异步场景下的上下文传递。
|
||||||
|
*
|
||||||
|
* 包含当前部门编号、所属公司编号以及是否忽略部门数据权限的标识。
|
||||||
|
*/
|
||||||
|
public class DeptContextHolder {
|
||||||
|
|
||||||
|
/** 当前部门编号 */
|
||||||
|
private static final ThreadLocal<Long> DEPT_ID = new TransmittableThreadLocal<>();
|
||||||
|
/** 当前部门所属公司编号(用于一致性校验) */
|
||||||
|
private static final ThreadLocal<Long> COMPANY_ID = new TransmittableThreadLocal<>();
|
||||||
|
/** 是否忽略部门数据权限 */
|
||||||
|
private static final ThreadLocal<Boolean> IGNORE = new TransmittableThreadLocal<>();
|
||||||
|
|
||||||
|
public static Long getDeptId() {
|
||||||
|
return DEPT_ID.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Long getCompanyId() {
|
||||||
|
return COMPANY_ID.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置部门与所属公司编号。
|
||||||
|
*/
|
||||||
|
public static void setContext(Long deptId, Long companyId) {
|
||||||
|
DEPT_ID.set(deptId);
|
||||||
|
COMPANY_ID.set(companyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDeptId(Long deptId) {
|
||||||
|
DEPT_ID.set(deptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCompanyId(Long companyId) {
|
||||||
|
COMPANY_ID.set(companyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasDeptId() {
|
||||||
|
Long deptId = DEPT_ID.get();
|
||||||
|
return deptId != null && deptId > 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setIgnore(Boolean ignore) {
|
||||||
|
IGNORE.set(ignore);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean shouldIgnore() {
|
||||||
|
return Boolean.TRUE.equals(IGNORE.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clear() {
|
||||||
|
DEPT_ID.remove();
|
||||||
|
COMPANY_ID.remove();
|
||||||
|
IGNORE.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.zt.plat.framework.tenant.core.context;
|
package com.zt.plat.framework.tenant.core.context;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.zt.plat.framework.common.enums.DocumentEnum;
|
|
||||||
import com.alibaba.ttl.TransmittableThreadLocal;
|
import com.alibaba.ttl.TransmittableThreadLocal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,8 +36,10 @@ public class TenantContextHolder {
|
|||||||
public static Long getRequiredTenantId() {
|
public static Long getRequiredTenantId() {
|
||||||
Long tenantId = getTenantId();
|
Long tenantId = getTenantId();
|
||||||
if (tenantId == null) {
|
if (tenantId == null) {
|
||||||
throw new NullPointerException("TenantContextHolder 不存在租户编号!可参考文档:"
|
// throw new NullPointerException("TenantContextHolder 不存在租户编号!可参考文档:"
|
||||||
+ DocumentEnum.TENANT.getUrl());
|
// + DocumentEnum.TENANT.getUrl());
|
||||||
|
// 暂定所有获取不到租户的操作,默认都使用主租户进行操作 1l
|
||||||
|
tenantId = 1L;
|
||||||
}
|
}
|
||||||
return tenantId;
|
return tenantId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.zt.plat.framework.tenant.core.web;
|
|||||||
import com.zt.plat.framework.security.core.LoginUser;
|
import com.zt.plat.framework.security.core.LoginUser;
|
||||||
import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils;
|
import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import com.zt.plat.framework.tenant.core.context.CompanyContextHolder;
|
import com.zt.plat.framework.tenant.core.context.CompanyContextHolder;
|
||||||
|
import com.zt.plat.framework.tenant.core.context.DeptContextHolder;
|
||||||
import com.zt.plat.framework.web.core.util.WebFrameworkUtils;
|
import com.zt.plat.framework.web.core.util.WebFrameworkUtils;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
@@ -66,11 +67,19 @@ public class CompanyVisitContextInterceptor implements HandlerInterceptor {
|
|||||||
|
|
||||||
if (companyId == null || companyId <= 0L) {
|
if (companyId == null || companyId <= 0L) {
|
||||||
CompanyContextHolder.setIgnore(true);
|
CompanyContextHolder.setIgnore(true);
|
||||||
|
DeptContextHolder.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompanyContextHolder.setIgnore(false);
|
CompanyContextHolder.setIgnore(false);
|
||||||
CompanyContextHolder.setCompanyId(companyId);
|
CompanyContextHolder.setCompanyId(companyId);
|
||||||
|
// 默认不忽略部门数据权限;如果有有效部门则写入上下文
|
||||||
|
DeptContextHolder.setIgnore(false);
|
||||||
|
if (deptId != null && deptId > 0L) {
|
||||||
|
DeptContextHolder.setContext(deptId, companyId);
|
||||||
|
} else {
|
||||||
|
DeptContextHolder.clear();
|
||||||
|
}
|
||||||
if (loginUser == null) {
|
if (loginUser == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -91,7 +100,9 @@ public class CompanyVisitContextInterceptor implements HandlerInterceptor {
|
|||||||
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
||||||
if (loginUser != null) {
|
if (loginUser != null) {
|
||||||
loginUser.setVisitCompanyId(0L);
|
loginUser.setVisitCompanyId(0L);
|
||||||
|
loginUser.setVisitDeptId(0L);
|
||||||
}
|
}
|
||||||
|
DeptContextHolder.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Long resolveLong(Object value) {
|
private Long resolveLong(Object value) {
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package com.zt.plat.framework.tenant.core.web;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.security.core.LoginUser;
|
||||||
|
import com.zt.plat.framework.tenant.core.context.CompanyContextHolder;
|
||||||
|
import com.zt.plat.framework.tenant.core.context.DeptContextHolder;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CompanyVisitContextInterceptor 单测,覆盖公司/部门上下文写入及清理。
|
||||||
|
*/
|
||||||
|
class CompanyVisitContextInterceptorTest {
|
||||||
|
|
||||||
|
private final HandlerInterceptor interceptor = new CompanyVisitContextInterceptor();
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() {
|
||||||
|
CompanyContextHolder.clear();
|
||||||
|
DeptContextHolder.clear();
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // 无公司 id:应 ignore,公司/部门上下文清空
|
||||||
|
void testPreHandle_noCompanyId_ignore() throws Exception {
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
|
||||||
|
boolean result = interceptor.preHandle(request, response, new Object());
|
||||||
|
|
||||||
|
assertTrue(result);
|
||||||
|
assertTrue(CompanyContextHolder.isIgnore());
|
||||||
|
assertNull(CompanyContextHolder.getCompanyId());
|
||||||
|
assertNull(DeptContextHolder.getDeptId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // 有公司无部门:写入公司,部门清空
|
||||||
|
void testPreHandle_companyOnly() throws Exception {
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
LoginUser loginUser = new LoginUser();
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(loginUser, null));
|
||||||
|
request.addHeader("visit-company-id", "11");
|
||||||
|
|
||||||
|
boolean result = interceptor.preHandle(request, response, new Object());
|
||||||
|
|
||||||
|
assertTrue(result);
|
||||||
|
assertFalse(CompanyContextHolder.isIgnore());
|
||||||
|
assertEquals(11L, CompanyContextHolder.getCompanyId());
|
||||||
|
assertFalse(DeptContextHolder.shouldIgnore());
|
||||||
|
assertNull(DeptContextHolder.getDeptId());
|
||||||
|
assertEquals(11L, loginUser.getVisitCompanyId());
|
||||||
|
assertNull(loginUser.getVisitDeptId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // 有公司+部门:写入公司、部门上下文,afterCompletion 清理 visitDeptId & holder
|
||||||
|
void testPreHandle_withCompanyAndDept_andAfterCompletionClear() throws Exception {
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
LoginUser loginUser = new LoginUser();
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(loginUser, null));
|
||||||
|
request.addHeader("visit-company-id", "22");
|
||||||
|
request.addHeader("visit-dept-id", "33");
|
||||||
|
|
||||||
|
boolean result = interceptor.preHandle(request, response, new Object());
|
||||||
|
|
||||||
|
assertTrue(result);
|
||||||
|
assertFalse(CompanyContextHolder.isIgnore());
|
||||||
|
assertEquals(22L, CompanyContextHolder.getCompanyId());
|
||||||
|
assertEquals(33L, DeptContextHolder.getDeptId());
|
||||||
|
assertEquals(22L, DeptContextHolder.getCompanyId());
|
||||||
|
assertEquals(22L, loginUser.getVisitCompanyId());
|
||||||
|
assertEquals(33L, loginUser.getVisitDeptId());
|
||||||
|
|
||||||
|
// afterCompletion: 清理 visitCompanyId/visitDeptId 与 holder
|
||||||
|
interceptor.afterCompletion(request, response, new Object(), null);
|
||||||
|
assertEquals(0L, loginUser.getVisitCompanyId());
|
||||||
|
assertEquals(0L, loginUser.getVisitDeptId());
|
||||||
|
assertNull(DeptContextHolder.getDeptId());
|
||||||
|
assertNull(DeptContextHolder.getCompanyId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,14 +46,12 @@
|
|||||||
<groupId>com.zt.plat</groupId>
|
<groupId>com.zt.plat</groupId>
|
||||||
<artifactId>zt-spring-boot-starter-mq</artifactId>
|
<artifactId>zt-spring-boot-starter-mq</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Redis 相关 (用于幂等) -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.zt.plat</groupId>
|
<groupId>com.zt.plat</groupId>
|
||||||
<artifactId>zt-spring-boot-starter-redis</artifactId>
|
<artifactId>zt-spring-boot-starter-biz-tenant</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Web 相关 (用于HTTP接收) -->
|
<!-- Redis 相关 (用于幂等) --><!-- Web 相关 (用于HTTP接收) -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
|||||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import com.zt.plat.framework.tenant.core.context.TenantContextHolder;
|
||||||
/**
|
/**
|
||||||
* DataBus 客户端统一消费者
|
* DataBus 客户端统一消费者
|
||||||
* <p>
|
* <p>
|
||||||
@@ -33,8 +33,8 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
@ConditionalOnProperty(prefix = "zt.databus.sync.client", name = "enabled", havingValue = "true")
|
@ConditionalOnProperty(prefix = "zt.databus.sync.client", name = "enabled", havingValue = "true")
|
||||||
@RocketMQMessageListener(
|
@RocketMQMessageListener(
|
||||||
topic = "${zt.databus.sync.client.mq.topic:databus-sync}-${zt.databus.sync.client.client-code}",
|
topic = "${zt.databus.sync.client.mq.topic-base:databus-sync}-${zt.databus.sync.client.client-code}",
|
||||||
consumerGroup = "${zt.databus.sync.client.mq.consumer-group:databus-client-consumer}-${zt.databus.sync.client.client-code}"
|
consumerGroup = "${zt.databus.sync.client.mq.consumer-group-prefix:databus-client-consumer}-${zt.databus.sync.client.client-code}"
|
||||||
)
|
)
|
||||||
public class DatabusClientConsumer implements RocketMQListener<String> {
|
public class DatabusClientConsumer implements RocketMQListener<String> {
|
||||||
|
|
||||||
@@ -46,6 +46,7 @@ public class DatabusClientConsumer implements RocketMQListener<String> {
|
|||||||
log.debug("[DatabusClient] 收到消息, body={}", body);
|
log.debug("[DatabusClient] 收到消息, body={}", body);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
TenantContextHolder.setTenantId(1L);
|
||||||
// 1. 解析消息获取 eventType
|
// 1. 解析消息获取 eventType
|
||||||
DatabusEventType eventType = parseEventType(body);
|
DatabusEventType eventType = parseEventType(body);
|
||||||
if (eventType == null) {
|
if (eventType == null) {
|
||||||
|
|||||||
@@ -69,21 +69,15 @@ public class DeptSyncServiceImpl implements DeptSyncService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DeptSaveReqDTO dto = buildDeptDTO(data);
|
DeptSaveReqDTO dto = buildDeptDTO(data);
|
||||||
|
|
||||||
|
// 使用专用同步接口,跳过业务校验,直接 upsert
|
||||||
try {
|
try {
|
||||||
// 尝试获取,存在则更新,不存在则创建
|
deptApi.syncDept(dto).checkError();
|
||||||
var existing = deptApi.getDept(dto.getId());
|
log.info("[DeptSync] 部门全量同步成功, deptId={}, deptName={}", dto.getId(), dto.getName());
|
||||||
if (existing.isSuccess() && existing.getData() != null) {
|
|
||||||
deptApi.updateDept(dto).checkError();
|
|
||||||
log.info("[DeptSync] 部门全量同步-更新成功, deptId={}", dto.getId());
|
|
||||||
} else {
|
|
||||||
deptApi.createDept(dto).checkError();
|
|
||||||
log.info("[DeptSync] 部门全量同步-创建成功, deptId={}", dto.getId());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 获取失败,尝试创建
|
log.error("[DeptSync] 部门全量同步失败, deptId={}, deptName={}, parentId={}, code={}, error={}",
|
||||||
log.warn("[DeptSync] 部门获取失败,尝试创建, deptId={}", dto.getId());
|
dto.getId(), dto.getName(), dto.getParentId(), dto.getCode(), e.getMessage());
|
||||||
deptApi.createDept(dto).checkError();
|
throw e;
|
||||||
log.info("[DeptSync] 部门全量同步-创建成功, deptId={}", dto.getId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,13 +87,18 @@ public class DeptSyncServiceImpl implements DeptSyncService {
|
|||||||
private DeptSaveReqDTO buildDeptDTO(DatabusDeptData data) {
|
private DeptSaveReqDTO buildDeptDTO(DatabusDeptData data) {
|
||||||
DeptSaveReqDTO dto = new DeptSaveReqDTO();
|
DeptSaveReqDTO dto = new DeptSaveReqDTO();
|
||||||
dto.setId(data.getId());
|
dto.setId(data.getId());
|
||||||
|
dto.setCode(data.getCode()); // ⚠️ 重要:传递编码,保持一致
|
||||||
dto.setName(data.getName());
|
dto.setName(data.getName());
|
||||||
|
dto.setShortName(data.getShortName());
|
||||||
dto.setParentId(data.getParentId());
|
dto.setParentId(data.getParentId());
|
||||||
dto.setSort(data.getSort());
|
dto.setSort(data.getSort());
|
||||||
dto.setLeaderUserId(data.getLeaderUserId());
|
dto.setLeaderUserId(data.getLeaderUserId());
|
||||||
dto.setPhone(data.getPhone());
|
dto.setPhone(data.getPhone());
|
||||||
dto.setEmail(data.getEmail());
|
dto.setEmail(data.getEmail());
|
||||||
dto.setStatus(data.getStatus());
|
dto.setStatus(data.getStatus());
|
||||||
|
dto.setIsGroup(data.getIsGroup());
|
||||||
|
dto.setIsCompany(data.getIsCompany());
|
||||||
|
dto.setDeptSource(data.getDeptSource());
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,25 +68,14 @@ public class PostSyncServiceImpl implements PostSyncService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PostSaveReqDTO dto = buildPostDTO(data);
|
PostSaveReqDTO dto = buildPostDTO(data);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 尝试获取,存在则更新,不存在则创建
|
postApi.syncPost(dto).checkError();
|
||||||
var existing = postApi.getPost(dto.getId());
|
log.info("[PostSync] 岗位全量同步成功, postId={}, postName={}", dto.getId(), dto.getName());
|
||||||
if (existing.isSuccess() && existing.getData() != null) {
|
|
||||||
postApi.updatePost(dto).checkError();
|
|
||||||
log.info("[PostSync] 岗位全量同步-更新成功, postId={}, postName={}", dto.getId(), dto.getName());
|
|
||||||
} else {
|
|
||||||
postApi.createPost(dto).checkError();
|
|
||||||
log.info("[PostSync] 岗位全量同步-创建成功, postId={}, postName={}", dto.getId(), dto.getName());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 获取失败,尝试创建
|
log.error("[PostSync] 岗位全量同步失败, postId={}, postName={}, code={}, error={}",
|
||||||
try {
|
dto.getId(), dto.getName(), dto.getCode(), e.getMessage());
|
||||||
postApi.createPost(dto).checkError();
|
throw e;
|
||||||
log.info("[PostSync] 岗位全量同步-创建成功, postId={}, postName={}", dto.getId(), dto.getName());
|
|
||||||
} catch (Exception createEx) {
|
|
||||||
log.error("[PostSync] 岗位全量同步失败, postId={}, postName={}", dto.getId(), dto.getName(), createEx);
|
|
||||||
throw createEx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,21 +72,14 @@ public class AdminUserSyncServiceImpl implements AdminUserSyncService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AdminUserSaveReqDTO dto = buildUserDTO(data);
|
AdminUserSaveReqDTO dto = buildUserDTO(data);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 尝试获取,存在则更新,不存在则创建
|
adminUserApi.syncUser(dto).checkError();
|
||||||
var existing = adminUserApi.getUser(dto.getId());
|
log.info("[UserSync] 用户全量同步成功, userId={}, username={}", dto.getId(), dto.getUsername());
|
||||||
if (existing.isSuccess() && existing.getData() != null) {
|
|
||||||
adminUserApi.updateUser(dto).checkError();
|
|
||||||
log.info("[UserSync] 用户全量同步-更新成功, userId={}", dto.getId());
|
|
||||||
} else {
|
|
||||||
adminUserApi.createUser(dto).checkError();
|
|
||||||
log.info("[UserSync] 用户全量同步-创建成功, userId={}", dto.getId());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 获取失败,尝试创建
|
log.error("[UserSync] 用户全量同步失败, userId={}, username={}, error={}",
|
||||||
log.warn("[UserSync] 用户获取失败,尝试创建, userId={}", dto.getId());
|
dto.getId(), dto.getUsername(), e.getMessage());
|
||||||
adminUserApi.createUser(dto).checkError();
|
throw e;
|
||||||
log.info("[UserSync] 用户全量同步-创建成功, userId={}", dto.getId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,56 +1,94 @@
|
|||||||
package com.zt.plat.framework.databus.client.handler.userdept;
|
package com.zt.plat.framework.databus.client.handler.userdept;
|
||||||
|
|
||||||
import com.zt.plat.module.databus.api.data.DatabusUserDeptData;
|
import com.zt.plat.module.databus.api.data.DatabusUserDeptData;
|
||||||
|
import com.zt.plat.module.system.api.userdept.UserDeptApi;
|
||||||
|
import com.zt.plat.module.system.api.userdept.dto.UserDeptSaveReqDTO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户-部门关系同步服务实现
|
* 用户-部门关系同步服务实现(通过 Feign API 调用远程服务)
|
||||||
* <p>
|
* <p>
|
||||||
* 使用条件:
|
* 使用条件:
|
||||||
* 1. zt.databus.sync.client.enabled=true
|
* 1. zt.databus.sync.client.enabled=true
|
||||||
|
* 2. 系统中存在 UserDeptApi 接口(Feign 客户端)
|
||||||
* <p>
|
* <p>
|
||||||
* 注意:由于用户-部门关系通常集成在用户管理中,此实现为占位符。
|
* 如果分公司需要自定义实现,可以创建自己的 UserDeptSyncService Bean,
|
||||||
* 分公司可以根据实际情况:
|
* 此默认实现会自动失效(@ConditionalOnMissingBean)
|
||||||
* 1. 自定义实现此接口,直接操作本地数据库
|
|
||||||
* 2. 或者通过用户管理 API 间接处理关联关系
|
|
||||||
*
|
*
|
||||||
* @author ZT
|
* @author ZT
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@ConditionalOnProperty(prefix = "zt.databus.sync.client", name = "enabled", havingValue = "true")
|
@ConditionalOnProperty(prefix = "zt.databus.sync.client", name = "enabled", havingValue = "true")
|
||||||
|
@ConditionalOnClass(name = "com.zt.plat.module.system.api.userdept.UserDeptApi")
|
||||||
public class UserDeptSyncServiceImpl implements UserDeptSyncService {
|
public class UserDeptSyncServiceImpl implements UserDeptSyncService {
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private UserDeptApi userDeptApi; // Feign 远程调用接口
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(DatabusUserDeptData data) {
|
public void create(DatabusUserDeptData data) {
|
||||||
log.info("[UserDeptSync] 收到创建用户-部门关系请求, userId={}, deptId={}",
|
if (userDeptApi == null) {
|
||||||
data.getUserId(), data.getDeptId());
|
log.warn("[UserDeptSync] UserDeptApi未注入,跳过创建用户-部门关系, userId={}", data.getUserId());
|
||||||
log.warn("[UserDeptSync] 用户-部门关系同步服务需要分公司自定义实现,当前为占位符实现");
|
return;
|
||||||
// TODO: 分公司需要实现此方法,通过本地 API 或直接数据库操作完成同步
|
}
|
||||||
|
UserDeptSaveReqDTO dto = buildUserDeptDTO(data);
|
||||||
|
userDeptApi.createUserDept(dto).checkError();
|
||||||
|
log.info("[UserDeptSync] 用户-部门关系创建成功, userId={}, deptId={}", data.getUserId(), data.getDeptId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(DatabusUserDeptData data) {
|
public void update(DatabusUserDeptData data) {
|
||||||
log.info("[UserDeptSync] 收到更新用户-部门关系请求, userId={}, deptId={}",
|
if (userDeptApi == null) {
|
||||||
data.getUserId(), data.getDeptId());
|
log.warn("[UserDeptSync] UserDeptApi未注入,跳过更新用户-部门关系, userId={}", data.getUserId());
|
||||||
log.warn("[UserDeptSync] 用户-部门关系同步服务需要分公司自定义实现,当前为占位符实现");
|
return;
|
||||||
// TODO: 分公司需要实现此方法
|
}
|
||||||
|
UserDeptSaveReqDTO dto = buildUserDeptDTO(data);
|
||||||
|
userDeptApi.updateUserDept(dto).checkError();
|
||||||
|
log.info("[UserDeptSync] 用户-部门关系更新成功, userId={}, deptId={}", data.getUserId(), data.getDeptId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(Long id) {
|
public void delete(Long id) {
|
||||||
log.info("[UserDeptSync] 收到删除用户-部门关系请求, id={}", id);
|
if (userDeptApi == null) {
|
||||||
log.warn("[UserDeptSync] 用户-部门关系同步服务需要分公司自定义实现,当前为占位符实现");
|
log.warn("[UserDeptSync] UserDeptApi未注入,跳过删除用户-部门关系, id={}", id);
|
||||||
// TODO: 分公司需要实现此方法
|
return;
|
||||||
|
}
|
||||||
|
userDeptApi.deleteUserDept(id).checkError();
|
||||||
|
log.info("[UserDeptSync] 用户-部门关系删除成功, id={}", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fullSync(DatabusUserDeptData data) {
|
public void fullSync(DatabusUserDeptData data) {
|
||||||
log.info("[UserDeptSync] 收到全量同步用户-部门关系请求, userId={}, deptId={}",
|
if (userDeptApi == null) {
|
||||||
data.getUserId(), data.getDeptId());
|
log.warn("[UserDeptSync] UserDeptApi未注入,跳过全量同步用户-部门关系, userId={}", data.getUserId());
|
||||||
log.warn("[UserDeptSync] 用户-部门关系同步服务需要分公司自定义实现,当前为占位符实现");
|
return;
|
||||||
// TODO: 分公司需要实现此方法,逻辑:存在则更新,不存在则插入
|
}
|
||||||
|
UserDeptSaveReqDTO dto = buildUserDeptDTO(data);
|
||||||
|
try {
|
||||||
|
userDeptApi.syncUserDept(dto).checkError();
|
||||||
|
log.info("[UserDeptSync] 用户-部门关系全量同步成功, id={}, userId={}, deptId={}",
|
||||||
|
dto.getId(), dto.getUserId(), dto.getDeptId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[UserDeptSync] 用户-部门关系全量同步失败, id={}, userId={}, deptId={}, error={}",
|
||||||
|
dto.getId(), dto.getUserId(), dto.getDeptId(), e.getMessage());
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建用户部门关系 DTO(用于 Feign 调用)
|
||||||
|
*/
|
||||||
|
private UserDeptSaveReqDTO buildUserDeptDTO(DatabusUserDeptData data) {
|
||||||
|
UserDeptSaveReqDTO dto = new UserDeptSaveReqDTO();
|
||||||
|
dto.setId(data.getId());
|
||||||
|
dto.setUserId(data.getUserId());
|
||||||
|
dto.setDeptId(data.getDeptId());
|
||||||
|
dto.setRemark(data.getRemark());
|
||||||
|
return dto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,56 +1,93 @@
|
|||||||
package com.zt.plat.framework.databus.client.handler.userpost;
|
package com.zt.plat.framework.databus.client.handler.userpost;
|
||||||
|
|
||||||
import com.zt.plat.module.databus.api.data.DatabusUserPostData;
|
import com.zt.plat.module.databus.api.data.DatabusUserPostData;
|
||||||
|
import com.zt.plat.module.system.api.userpost.UserPostApi;
|
||||||
|
import com.zt.plat.module.system.api.userpost.dto.UserPostSaveReqDTO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户-岗位关系同步服务实现
|
* 用户-岗位关系同步服务实现(通过 Feign API 调用远程服务)
|
||||||
* <p>
|
* <p>
|
||||||
* 使用条件:
|
* 使用条件:
|
||||||
* 1. zt.databus.sync.client.enabled=true
|
* 1. zt.databus.sync.client.enabled=true
|
||||||
|
* 2. 系统中存在 UserPostApi 接口(Feign 客户端)
|
||||||
* <p>
|
* <p>
|
||||||
* 注意:由于用户-岗位关系通常集成在用户管理中,此实现为占位符。
|
* 如果分公司需要自定义实现,可以创建自己的 UserPostSyncService Bean,
|
||||||
* 分公司可以根据实际情况:
|
* 此默认实现会自动失效(@ConditionalOnMissingBean)
|
||||||
* 1. 自定义实现此接口,直接操作本地数据库
|
|
||||||
* 2. 或者通过用户管理 API 间接处理关联关系
|
|
||||||
*
|
*
|
||||||
* @author ZT
|
* @author ZT
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@ConditionalOnProperty(prefix = "zt.databus.sync.client", name = "enabled", havingValue = "true")
|
@ConditionalOnProperty(prefix = "zt.databus.sync.client", name = "enabled", havingValue = "true")
|
||||||
|
@ConditionalOnClass(name = "com.zt.plat.module.system.api.userpost.UserPostApi")
|
||||||
public class UserPostSyncServiceImpl implements UserPostSyncService {
|
public class UserPostSyncServiceImpl implements UserPostSyncService {
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private UserPostApi userPostApi; // Feign 远程调用接口
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(DatabusUserPostData data) {
|
public void create(DatabusUserPostData data) {
|
||||||
log.info("[UserPostSync] 收到创建用户-岗位关系请求, userId={}, postId={}",
|
if (userPostApi == null) {
|
||||||
data.getUserId(), data.getPostId());
|
log.warn("[UserPostSync] UserPostApi未注入,跳过创建用户-岗位关系, userId={}", data.getUserId());
|
||||||
log.warn("[UserPostSync] 用户-岗位关系同步服务需要分公司自定义实现,当前为占位符实现");
|
return;
|
||||||
// TODO: 分公司需要实现此方法,通过本地 API 或直接数据库操作完成同步
|
}
|
||||||
|
UserPostSaveReqDTO dto = buildUserPostDTO(data);
|
||||||
|
userPostApi.createUserPost(dto).checkError();
|
||||||
|
log.info("[UserPostSync] 用户-岗位关系创建成功, userId={}, postId={}", data.getUserId(), data.getPostId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(DatabusUserPostData data) {
|
public void update(DatabusUserPostData data) {
|
||||||
log.info("[UserPostSync] 收到更新用户-岗位关系请求, userId={}, postId={}",
|
if (userPostApi == null) {
|
||||||
data.getUserId(), data.getPostId());
|
log.warn("[UserPostSync] UserPostApi未注入,跳过更新用户-岗位关系, userId={}", data.getUserId());
|
||||||
log.warn("[UserPostSync] 用户-岗位关系同步服务需要分公司自定义实现,当前为占位符实现");
|
return;
|
||||||
// TODO: 分公司需要实现此方法
|
}
|
||||||
|
UserPostSaveReqDTO dto = buildUserPostDTO(data);
|
||||||
|
userPostApi.updateUserPost(dto).checkError();
|
||||||
|
log.info("[UserPostSync] 用户-岗位关系更新成功, userId={}, postId={}", data.getUserId(), data.getPostId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(Long id) {
|
public void delete(Long id) {
|
||||||
log.info("[UserPostSync] 收到删除用户-岗位关系请求, id={}", id);
|
if (userPostApi == null) {
|
||||||
log.warn("[UserPostSync] 用户-岗位关系同步服务需要分公司自定义实现,当前为占位符实现");
|
log.warn("[UserPostSync] UserPostApi未注入,跳过删除用户-岗位关系, id={}", id);
|
||||||
// TODO: 分公司需要实现此方法
|
return;
|
||||||
|
}
|
||||||
|
userPostApi.deleteUserPost(id).checkError();
|
||||||
|
log.info("[UserPostSync] 用户-岗位关系删除成功, id={}", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fullSync(DatabusUserPostData data) {
|
public void fullSync(DatabusUserPostData data) {
|
||||||
log.info("[UserPostSync] 收到全量同步用户-岗位关系请求, userId={}, postId={}",
|
if (userPostApi == null) {
|
||||||
data.getUserId(), data.getPostId());
|
log.warn("[UserPostSync] UserPostApi未注入,跳过全量同步用户-岗位关系, userId={}", data.getUserId());
|
||||||
log.warn("[UserPostSync] 用户-岗位关系同步服务需要分公司自定义实现,当前为占位符实现");
|
return;
|
||||||
// TODO: 分公司需要实现此方法,逻辑:存在则更新,不存在则插入
|
}
|
||||||
|
UserPostSaveReqDTO dto = buildUserPostDTO(data);
|
||||||
|
try {
|
||||||
|
userPostApi.syncUserPost(dto).checkError();
|
||||||
|
log.info("[UserPostSync] 用户-岗位关系全量同步成功, id={}, userId={}, postId={}",
|
||||||
|
dto.getId(), dto.getUserId(), dto.getPostId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[UserPostSync] 用户-岗位关系全量同步失败, id={}, userId={}, postId={}, error={}",
|
||||||
|
dto.getId(), dto.getUserId(), dto.getPostId(), e.getMessage());
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建用户岗位关系 DTO(用于 Feign 调用)
|
||||||
|
*/
|
||||||
|
private UserPostSaveReqDTO buildUserPostDTO(DatabusUserPostData data) {
|
||||||
|
UserPostSaveReqDTO dto = new UserPostSaveReqDTO();
|
||||||
|
dto.setId(data.getId());
|
||||||
|
dto.setUserId(data.getUserId());
|
||||||
|
dto.setPostId(data.getPostId());
|
||||||
|
return dto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,15 @@ public class DatabusUserChangeConsumer implements RocketMQListener<DatabusUserCh
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(DatabusUserChangeMessage message) {
|
public void onMessage(DatabusUserChangeMessage message) {
|
||||||
log.info("[Databus] 收到用户变更消息, action={}, userId={}", message.getAction(), message.getUserId());
|
log.info("[Databus] 收到用户变更消息, action={}, userId={}, userSource={}",
|
||||||
|
message.getAction(), message.getUserId(), message.getUserSource());
|
||||||
|
|
||||||
|
// ⚠️ 只处理 userSource = 2 的用户
|
||||||
|
if (message.getUserSource() == null || message.getUserSource() != 2) {
|
||||||
|
log.info("[Databus] 跳过非集团用户的变更消息, userId={}, userSource={}",
|
||||||
|
message.getUserId(), message.getUserSource());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Map<String, Object> dataMap = new HashMap<>();
|
Map<String, Object> dataMap = new HashMap<>();
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package com.zt.plat.framework.databus.server.provider;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.framework.databus.server.core.provider.DataProvider;
|
||||||
|
import com.zt.plat.framework.databus.server.core.provider.DataProviderRegistry;
|
||||||
|
import com.zt.plat.module.databus.api.dto.CursorPageReqDTO;
|
||||||
|
import com.zt.plat.module.databus.api.dto.CursorPageResult;
|
||||||
|
import com.zt.plat.module.databus.api.data.DatabusUserDeptData;
|
||||||
|
import com.zt.plat.module.databus.api.provider.DatabusUserDeptProviderApi;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户-部门关系数据提供者
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class UserDeptDataFeignProvider implements DataProvider<DatabusUserDeptData> {
|
||||||
|
|
||||||
|
public static final String PROVIDER_TYPE = "USER_DEPT";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DatabusUserDeptProviderApi userDeptProviderApi;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DataProviderRegistry dataProviderRegistry;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
dataProviderRegistry.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProviderType() {
|
||||||
|
return PROVIDER_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CursorPageData<DatabusUserDeptData> getPageByCursor(LocalDateTime cursorTime, Long cursorId,
|
||||||
|
int batchSize, Long tenantId) {
|
||||||
|
CursorPageReqDTO reqDTO = CursorPageReqDTO.builder()
|
||||||
|
.cursorTime(cursorTime)
|
||||||
|
.cursorId(cursorId)
|
||||||
|
.batchSize(batchSize)
|
||||||
|
.tenantId(tenantId)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CommonResult<CursorPageResult<DatabusUserDeptData>> result = userDeptProviderApi.getPageByCursor(reqDTO);
|
||||||
|
if (!result.isSuccess()) {
|
||||||
|
throw new RuntimeException("获取用户-部门关系数据失败: " + result.getMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
CursorPageResult<DatabusUserDeptData> pageResult = result.getData();
|
||||||
|
return CursorPageData.of(
|
||||||
|
pageResult.getList(),
|
||||||
|
pageResult.getNextCursorTime(),
|
||||||
|
pageResult.getNextCursorId(),
|
||||||
|
pageResult.getCount(),
|
||||||
|
Boolean.TRUE.equals(pageResult.getHasMore()),
|
||||||
|
(pageResult.getTotal() != null ? pageResult.getTotal() : 0L)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long count(Long tenantId) {
|
||||||
|
CommonResult<Long> result = userDeptProviderApi.count(tenantId);
|
||||||
|
if (!result.isSuccess()) {
|
||||||
|
throw new RuntimeException("获取用户-部门关系总数失败: " + result.getMsg());
|
||||||
|
}
|
||||||
|
return result.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long extractUid(DatabusUserDeptData data) {
|
||||||
|
return data.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package com.zt.plat.framework.databus.server.provider;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.framework.databus.server.core.provider.DataProvider;
|
||||||
|
import com.zt.plat.framework.databus.server.core.provider.DataProviderRegistry;
|
||||||
|
import com.zt.plat.module.databus.api.dto.CursorPageReqDTO;
|
||||||
|
import com.zt.plat.module.databus.api.dto.CursorPageResult;
|
||||||
|
import com.zt.plat.module.databus.api.data.DatabusUserPostData;
|
||||||
|
import com.zt.plat.module.databus.api.provider.DatabusUserPostProviderApi;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户-岗位关系数据提供者
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class UserPostDataFeignProvider implements DataProvider<DatabusUserPostData> {
|
||||||
|
|
||||||
|
public static final String PROVIDER_TYPE = "USER_POST";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DatabusUserPostProviderApi userPostProviderApi;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DataProviderRegistry dataProviderRegistry;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
dataProviderRegistry.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProviderType() {
|
||||||
|
return PROVIDER_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CursorPageData<DatabusUserPostData> getPageByCursor(LocalDateTime cursorTime, Long cursorId,
|
||||||
|
int batchSize, Long tenantId) {
|
||||||
|
CursorPageReqDTO reqDTO = CursorPageReqDTO.builder()
|
||||||
|
.cursorTime(cursorTime)
|
||||||
|
.cursorId(cursorId)
|
||||||
|
.batchSize(batchSize)
|
||||||
|
.tenantId(tenantId)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CommonResult<CursorPageResult<DatabusUserPostData>> result = userPostProviderApi.getPageByCursor(reqDTO);
|
||||||
|
if (!result.isSuccess()) {
|
||||||
|
throw new RuntimeException("获取用户-岗位关系数据失败: " + result.getMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
CursorPageResult<DatabusUserPostData> pageResult = result.getData();
|
||||||
|
return CursorPageData.of(
|
||||||
|
pageResult.getList(),
|
||||||
|
pageResult.getNextCursorTime(),
|
||||||
|
pageResult.getNextCursorId(),
|
||||||
|
pageResult.getCount(),
|
||||||
|
Boolean.TRUE.equals(pageResult.getHasMore()),
|
||||||
|
(pageResult.getTotal() != null ? pageResult.getTotal() : 0L)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long count(Long tenantId) {
|
||||||
|
CommonResult<Long> result = userPostProviderApi.count(tenantId);
|
||||||
|
if (!result.isSuccess()) {
|
||||||
|
throw new RuntimeException("获取用户-岗位关系总数失败: " + result.getMsg());
|
||||||
|
}
|
||||||
|
return result.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long extractUid(DatabusUserPostData data) {
|
||||||
|
return data.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
32
zt-framework/zt-spring-boot-starter-seata-dm/pom.xml
Normal file
32
zt-framework/zt-spring-boot-starter-seata-dm/pom.xml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>zt-framework</artifactId>
|
||||||
|
<groupId>com.zt.plat</groupId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<artifactId>zt-spring-boot-starter-seata-dm</artifactId>
|
||||||
|
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>
|
||||||
|
Seata 达梦数据库补丁模块
|
||||||
|
解决 DmdbTimestamp 时区格式不一致导致的 dirty undo log 回滚失败问题
|
||||||
|
补丁来源: https://github.com/apache/incubator-seata/pull/7538
|
||||||
|
Seata 2.6.0 发布后可移除此模块
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- 仅编译时需要,运行时由 seata-spring-boot-starter 提供 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.seata</groupId>
|
||||||
|
<artifactId>seata-spring-boot-starter</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,326 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.seata.rm.datasource;
|
||||||
|
|
||||||
|
import org.apache.seata.common.util.CollectionUtils;
|
||||||
|
import org.apache.seata.common.util.StringUtils;
|
||||||
|
import org.apache.seata.core.model.Result;
|
||||||
|
import org.apache.seata.rm.datasource.sql.struct.Field;
|
||||||
|
import org.apache.seata.rm.datasource.sql.struct.Row;
|
||||||
|
import org.apache.seata.rm.datasource.sql.struct.TableRecords;
|
||||||
|
import org.apache.seata.rm.datasource.undo.AbstractUndoLogManager;
|
||||||
|
import org.apache.seata.rm.datasource.undo.parser.FastjsonUndoLogParser;
|
||||||
|
import org.apache.seata.rm.datasource.undo.parser.JacksonUndoLogParser;
|
||||||
|
import org.apache.seata.sqlparser.struct.TableMeta;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.Date;
|
||||||
|
import java.sql.Time;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.sql.Types;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DataCompareUtils - 包含达梦数据库 DmdbTimestamp 时区问题的补丁
|
||||||
|
* <p>
|
||||||
|
* 此类覆盖 Seata 原有的 DataCompareUtils,添加了对达梦数据库 DmdbTimestamp 类型的特殊处理。
|
||||||
|
* 通过将 DmdbTimestamp 转换为 UTC Instant 进行比较,解决时区格式不一致导致的 dirty undo log 问题。
|
||||||
|
* <p>
|
||||||
|
* 问题背景:
|
||||||
|
* - 达梦数据库的 DmdbTimestamp 类型在序列化/反序列化后时区格式不一致
|
||||||
|
* - 例如:beforeImage 为 "2025-12-25 09:38:54.077811 +08:00"
|
||||||
|
* afterImage 为 "2025-12-25 09:38:54.077811"
|
||||||
|
* - 导致 Seata AT 模式回滚时 dirty undo log 检查失败
|
||||||
|
* <p>
|
||||||
|
* 解决方案:
|
||||||
|
* - 当检测到 DmdbTimestamp 类型时,将两个值都转换为 UTC Instant 进行比较
|
||||||
|
* - 这样可以忽略时区格式差异,只比较实际的时间点
|
||||||
|
* <p>
|
||||||
|
* 补丁来源: https://github.com/apache/incubator-seata/pull/7538
|
||||||
|
* 相关 Issue: https://github.com/apache/incubator-seata/issues/7453
|
||||||
|
* 该修复已合并到 Seata 2.x 分支,将在 Seata 2.6.0 正式发布,届时可删除此模块。
|
||||||
|
*
|
||||||
|
* @author Seata Community (PR #7538)
|
||||||
|
*/
|
||||||
|
public class DataCompareUtils {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(DataCompareUtils.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标识补丁类是否已加载
|
||||||
|
*/
|
||||||
|
private static final boolean PATCHED;
|
||||||
|
|
||||||
|
static {
|
||||||
|
PATCHED = true;
|
||||||
|
LOGGER.info("[zt-spring-boot-starter-seata-dm] DataCompareUtils 补丁类已加载,用于解决达梦数据库 DmdbTimestamp 时区问题");
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataCompareUtils() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is field equals result.
|
||||||
|
*
|
||||||
|
* @param f0 the f 0
|
||||||
|
* @param f1 the f 1
|
||||||
|
* @return the result
|
||||||
|
*/
|
||||||
|
public static Result<Boolean> isFieldEquals(Field f0, Field f1) {
|
||||||
|
if (f0 == null) {
|
||||||
|
return Result.build(f1 == null);
|
||||||
|
} else {
|
||||||
|
if (f1 == null) {
|
||||||
|
return Result.build(false);
|
||||||
|
} else {
|
||||||
|
if (StringUtils.equalsIgnoreCase(f0.getName(), f1.getName()) && f0.getType() == f1.getType()) {
|
||||||
|
if (f0.getValue() == null) {
|
||||||
|
return Result.build(f1.getValue() == null);
|
||||||
|
} else {
|
||||||
|
if (f1.getValue() == null) {
|
||||||
|
return Result.buildWithParams(
|
||||||
|
false, "Field not equals, name {}, new value is null", f0.getName());
|
||||||
|
} else {
|
||||||
|
String currentSerializer = AbstractUndoLogManager.getCurrentSerializer();
|
||||||
|
if (StringUtils.equals(currentSerializer, FastjsonUndoLogParser.NAME)) {
|
||||||
|
convertType(f0, f1);
|
||||||
|
}
|
||||||
|
// 达梦数据库 DmdbTimestamp 时区补丁 (PR #7538)
|
||||||
|
if (StringUtils.equals(currentSerializer, JacksonUndoLogParser.NAME)) {
|
||||||
|
Object v0 = f0.getValue();
|
||||||
|
Object v1 = f1.getValue();
|
||||||
|
if (isDmdbTimestamp(v0) && isDmdbTimestamp(v1)) {
|
||||||
|
Instant i0 = toInstant(v0);
|
||||||
|
Instant i1 = toInstant(v1);
|
||||||
|
boolean equals = Objects.equals(i0, i1);
|
||||||
|
LOGGER.info("[zt-seata-dm-patch] DmdbTimestamp 字段比较: field={}, equals={}", f0.getName(), equals);
|
||||||
|
return equals
|
||||||
|
? Result.ok()
|
||||||
|
: Result.buildWithParams(
|
||||||
|
false,
|
||||||
|
"Field not equals (DmdbTimestamp), name {}, old value {}, new value {}",
|
||||||
|
f0.getName(),
|
||||||
|
v0,
|
||||||
|
v1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean result = Objects.deepEquals(f0.getValue(), f1.getValue());
|
||||||
|
if (result) {
|
||||||
|
return Result.ok();
|
||||||
|
} else {
|
||||||
|
return Result.buildWithParams(
|
||||||
|
false,
|
||||||
|
"Field not equals, name {}, old value {}, new value {}",
|
||||||
|
f0.getName(),
|
||||||
|
f0.getValue(),
|
||||||
|
f1.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Result.buildWithParams(
|
||||||
|
false,
|
||||||
|
"Field not equals, old name {} type {}, new name {} type {}",
|
||||||
|
f0.getName(),
|
||||||
|
f0.getType(),
|
||||||
|
f1.getName(),
|
||||||
|
f1.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void convertType(Field f0, Field f1) {
|
||||||
|
int f0Type = f0.getType();
|
||||||
|
int f1Type = f1.getType();
|
||||||
|
if (f0Type == Types.DATE && f0.getValue().getClass().equals(String.class)) {
|
||||||
|
String[] strings = f0.getValue().toString().split(" ");
|
||||||
|
f0.setValue(Date.valueOf(strings[0]));
|
||||||
|
}
|
||||||
|
if (f1Type == Types.DATE && f1.getValue().getClass().equals(String.class)) {
|
||||||
|
String[] strings = f1.getValue().toString().split(" ");
|
||||||
|
f1.setValue(Date.valueOf(strings[0]));
|
||||||
|
}
|
||||||
|
if (f0Type == Types.TIME && f0.getValue().getClass().equals(String.class)) {
|
||||||
|
f0.setValue(Time.valueOf(f0.getValue().toString()));
|
||||||
|
}
|
||||||
|
if (f1Type == Types.TIME && f1.getValue().getClass().equals(String.class)) {
|
||||||
|
f1.setValue(Time.valueOf(f1.getValue().toString()));
|
||||||
|
}
|
||||||
|
if (f0Type == Types.TIMESTAMP && f0.getValue().getClass().equals(String.class)) {
|
||||||
|
if (f1.getValue().getClass().equals(LocalDateTime.class)) {
|
||||||
|
f0.setValue(LocalDateTime.parse(f0.getValue().toString()));
|
||||||
|
} else {
|
||||||
|
f0.setValue(Timestamp.valueOf(f0.getValue().toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (f1Type == Types.TIMESTAMP && f1.getValue().getClass().equals(String.class)) {
|
||||||
|
f1.setValue(Timestamp.valueOf(f1.getValue().toString()));
|
||||||
|
}
|
||||||
|
if (f0Type == Types.DECIMAL && f0.getValue().getClass().equals(Integer.class)) {
|
||||||
|
f0.setValue(new BigDecimal(f0.getValue().toString()));
|
||||||
|
}
|
||||||
|
if (f1Type == Types.DECIMAL && f1.getValue().getClass().equals(Integer.class)) {
|
||||||
|
f1.setValue(new BigDecimal(f1.getValue().toString()));
|
||||||
|
}
|
||||||
|
if (f0Type == Types.BIGINT && f0.getValue().getClass().equals(Integer.class)) {
|
||||||
|
f0.setValue(Long.parseLong(f0.getValue().toString()));
|
||||||
|
}
|
||||||
|
if (f1Type == Types.BIGINT && f1.getValue().getClass().equals(Integer.class)) {
|
||||||
|
f1.setValue(Long.parseLong(f1.getValue().toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is records equals result.
|
||||||
|
*
|
||||||
|
* @param beforeImage the before image
|
||||||
|
* @param afterImage the after image
|
||||||
|
* @return the result
|
||||||
|
*/
|
||||||
|
public static Result<Boolean> isRecordsEquals(TableRecords beforeImage, TableRecords afterImage) {
|
||||||
|
if (beforeImage == null) {
|
||||||
|
return Result.build(afterImage == null, null);
|
||||||
|
} else {
|
||||||
|
if (afterImage == null) {
|
||||||
|
return Result.build(false, null);
|
||||||
|
}
|
||||||
|
if (beforeImage.getTableName().equalsIgnoreCase(afterImage.getTableName())
|
||||||
|
&& CollectionUtils.isSizeEquals(beforeImage.getRows(), afterImage.getRows())) {
|
||||||
|
// when image is EmptyTableRecords, getTableMeta will throw an exception
|
||||||
|
if (CollectionUtils.isEmpty(beforeImage.getRows())) {
|
||||||
|
return Result.ok();
|
||||||
|
}
|
||||||
|
return compareRows(beforeImage.getTableMeta(), beforeImage.getRows(), afterImage.getRows());
|
||||||
|
} else {
|
||||||
|
return Result.build(false, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is rows equals result.
|
||||||
|
*
|
||||||
|
* @param tableMetaData the table meta data
|
||||||
|
* @param oldRows the old rows
|
||||||
|
* @param newRows the new rows
|
||||||
|
* @return the result
|
||||||
|
*/
|
||||||
|
public static Result<Boolean> isRowsEquals(TableMeta tableMetaData, List<Row> oldRows, List<Row> newRows) {
|
||||||
|
if (!CollectionUtils.isSizeEquals(oldRows, newRows)) {
|
||||||
|
return Result.build(false, null);
|
||||||
|
}
|
||||||
|
return compareRows(tableMetaData, oldRows, newRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Result<Boolean> compareRows(TableMeta tableMetaData, List<Row> oldRows, List<Row> newRows) {
|
||||||
|
// old row to map
|
||||||
|
Map<String, Map<String, Field>> oldRowsMap = rowListToMap(oldRows, tableMetaData.getPrimaryKeyOnlyName());
|
||||||
|
// new row to map
|
||||||
|
Map<String, Map<String, Field>> newRowsMap = rowListToMap(newRows, tableMetaData.getPrimaryKeyOnlyName());
|
||||||
|
// compare data
|
||||||
|
for (Map.Entry<String, Map<String, Field>> oldEntry : oldRowsMap.entrySet()) {
|
||||||
|
String key = oldEntry.getKey();
|
||||||
|
Map<String, Field> oldRow = oldEntry.getValue();
|
||||||
|
Map<String, Field> newRow = newRowsMap.get(key);
|
||||||
|
if (newRow == null) {
|
||||||
|
return Result.buildWithParams(false, "compare row failed, rowKey {}, reason [newRow is null]", key);
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, Field> oldRowEntry : oldRow.entrySet()) {
|
||||||
|
String fieldName = oldRowEntry.getKey();
|
||||||
|
Field oldField = oldRowEntry.getValue();
|
||||||
|
Field newField = newRow.get(fieldName);
|
||||||
|
if (newField == null) {
|
||||||
|
return Result.buildWithParams(
|
||||||
|
false,
|
||||||
|
"compare row failed, rowKey {}, fieldName {}, reason [newField is null]",
|
||||||
|
key,
|
||||||
|
fieldName);
|
||||||
|
}
|
||||||
|
Result<Boolean> oldEqualsNewFieldResult = isFieldEquals(oldField, newField);
|
||||||
|
if (!oldEqualsNewFieldResult.getResult()) {
|
||||||
|
return oldEqualsNewFieldResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Result.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Row list to map map.
|
||||||
|
*
|
||||||
|
* @param rowList the row list
|
||||||
|
* @param primaryKeyList the primary key list
|
||||||
|
* @return the map
|
||||||
|
*/
|
||||||
|
public static Map<String, Map<String, Field>> rowListToMap(List<Row> rowList, List<String> primaryKeyList) {
|
||||||
|
// {value of primaryKey, value of all columns}
|
||||||
|
Map<String, Map<String, Field>> rowMap = new HashMap<>();
|
||||||
|
for (Row row : rowList) {
|
||||||
|
// ensure the order of column
|
||||||
|
List<Field> rowFieldList = row.getFields().stream()
|
||||||
|
.sorted(Comparator.comparing(Field::getName))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
// {uppercase fieldName : field}
|
||||||
|
Map<String, Field> colsMap = new HashMap<>();
|
||||||
|
StringBuilder rowKey = new StringBuilder();
|
||||||
|
boolean firstUnderline = false;
|
||||||
|
for (int j = 0; j < rowFieldList.size(); j++) {
|
||||||
|
Field field = rowFieldList.get(j);
|
||||||
|
if (primaryKeyList.stream().anyMatch(e -> field.getName().equals(e))) {
|
||||||
|
if (firstUnderline && j > 0) {
|
||||||
|
rowKey.append("_");
|
||||||
|
}
|
||||||
|
rowKey.append(String.valueOf(field.getValue()));
|
||||||
|
firstUnderline = true;
|
||||||
|
}
|
||||||
|
colsMap.put(field.getName().trim().toUpperCase(), field);
|
||||||
|
}
|
||||||
|
rowMap.put(rowKey.toString(), colsMap);
|
||||||
|
}
|
||||||
|
return rowMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否为达梦数据库的 DmdbTimestamp 类型
|
||||||
|
*/
|
||||||
|
private static boolean isDmdbTimestamp(Object obj) {
|
||||||
|
return obj != null
|
||||||
|
&& "dm.jdbc.driver.DmdbTimestamp".equals(obj.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 DmdbTimestamp 转换为 Instant
|
||||||
|
*/
|
||||||
|
private static Instant toInstant(Object dmdbTimestamp) {
|
||||||
|
try {
|
||||||
|
Method toInstantMethod = dmdbTimestamp.getClass().getMethod("toInstant");
|
||||||
|
return (Instant) toInstantMethod.invoke(dmdbTimestamp);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to convert DmdbTimestamp to Instant", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,8 @@ spring:
|
|||||||
username: ${config.username} # Nacos 账号
|
username: ${config.username} # Nacos 账号
|
||||||
password: ${config.password} # Nacos 密码
|
password: ${config.password} # Nacos 密码
|
||||||
discovery: # 【配置中心】配置项
|
discovery: # 【配置中心】配置项
|
||||||
|
ip: 172.16.46.62
|
||||||
|
port: 30092
|
||||||
namespace: ${config.namespace} # 命名空间。这里使用 maven Profile 资源过滤进行动态替换
|
namespace: ${config.namespace} # 命名空间。这里使用 maven Profile 资源过滤进行动态替换
|
||||||
group: ${config.group} # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
group: ${config.group} # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ public class BpmModelMetaInfoVO {
|
|||||||
@NotNull(message = "是否可见不能为空")
|
@NotNull(message = "是否可见不能为空")
|
||||||
private Boolean visible;
|
private Boolean visible;
|
||||||
|
|
||||||
|
@Schema(description = "是否允许重新发起", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||||
|
@NotNull(message = "是否允许重新发起不能为空")
|
||||||
|
private Boolean restart;
|
||||||
|
|
||||||
@Schema(description = "可发起用户编号数组", example = "[1,2,3]")
|
@Schema(description = "可发起用户编号数组", example = "[1,2,3]")
|
||||||
private List<Long> startUserIds;
|
private List<Long> startUserIds;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.zt.plat.module.bpm.controller.admin.base.user.UserSimpleBaseVO;
|
|||||||
import com.zt.plat.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
import com.zt.plat.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||||
import com.zt.plat.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
|
import com.zt.plat.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.zt.plat.module.bpm.controller.admin.definition.vo.model.simple.BpmSim
|
|||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 流程模型的保存 Request VO")
|
@Schema(description = "管理后台 - 流程模型的保存 Request VO")
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.zt.plat.module.bpm.controller.admin.task;
|
package com.zt.plat.module.bpm.controller.admin.task;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.zt.plat.framework.business.core.util.DeptUtil;
|
import com.zt.plat.framework.business.core.util.DeptUtil;
|
||||||
@@ -11,8 +12,10 @@ import com.zt.plat.module.bpm.controller.admin.task.vo.instance.*;
|
|||||||
import com.zt.plat.module.bpm.convert.task.BpmProcessInstanceConvert;
|
import com.zt.plat.module.bpm.convert.task.BpmProcessInstanceConvert;
|
||||||
import com.zt.plat.module.bpm.dal.dataobject.definition.BpmCategoryDO;
|
import com.zt.plat.module.bpm.dal.dataobject.definition.BpmCategoryDO;
|
||||||
import com.zt.plat.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
import com.zt.plat.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
||||||
|
import com.zt.plat.module.bpm.dal.dataobject.task.BpmProcessInstanceCopyDO;
|
||||||
import com.zt.plat.module.bpm.service.definition.BpmCategoryService;
|
import com.zt.plat.module.bpm.service.definition.BpmCategoryService;
|
||||||
import com.zt.plat.module.bpm.service.definition.BpmProcessDefinitionService;
|
import com.zt.plat.module.bpm.service.definition.BpmProcessDefinitionService;
|
||||||
|
import com.zt.plat.module.bpm.service.task.BpmProcessInstanceCopyService;
|
||||||
import com.zt.plat.module.bpm.service.task.BpmProcessInstanceService;
|
import com.zt.plat.module.bpm.service.task.BpmProcessInstanceService;
|
||||||
import com.zt.plat.module.bpm.service.task.BpmTaskService;
|
import com.zt.plat.module.bpm.service.task.BpmTaskService;
|
||||||
import com.zt.plat.module.system.api.dept.DeptApi;
|
import com.zt.plat.module.system.api.dept.DeptApi;
|
||||||
@@ -24,6 +27,8 @@ import io.swagger.v3.oas.annotations.Parameter;
|
|||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.collections4.list.SetUniqueList;
|
||||||
import org.flowable.engine.history.HistoricProcessInstance;
|
import org.flowable.engine.history.HistoricProcessInstance;
|
||||||
import org.flowable.engine.repository.ProcessDefinition;
|
import org.flowable.engine.repository.ProcessDefinition;
|
||||||
import org.flowable.task.api.Task;
|
import org.flowable.task.api.Task;
|
||||||
@@ -31,6 +36,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
|||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -53,6 +60,8 @@ public class BpmProcessInstanceController {
|
|||||||
private BpmProcessDefinitionService processDefinitionService;
|
private BpmProcessDefinitionService processDefinitionService;
|
||||||
@Resource
|
@Resource
|
||||||
private BpmCategoryService categoryService;
|
private BpmCategoryService categoryService;
|
||||||
|
@Resource
|
||||||
|
private BpmProcessInstanceCopyService processInstanceCopyService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private AdminUserApi adminUserApi;
|
private AdminUserApi adminUserApi;
|
||||||
@@ -181,6 +190,32 @@ public class BpmProcessInstanceController {
|
|||||||
return success(processInstanceService.getApprovalDetail(getLoginUserId(), reqVO));
|
return success(processInstanceService.getApprovalDetail(getLoginUserId(), reqVO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/copy-list-by-process-instance-id")
|
||||||
|
@Operation(summary = "根据流程实例编号获取抄送列表")
|
||||||
|
@Parameter(name = "id", description = "流程实例的编号", required = true)
|
||||||
|
@PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
|
||||||
|
public CommonResult<List<BpmProcessInstanceCopyVO>> getCopyListByProcessInstanceId(@RequestParam("processInstanceId") String processInstanceId) {
|
||||||
|
List<BpmProcessInstanceCopyDO> copyDOList = processInstanceCopyService.getByProcessInstanceId(processInstanceId);
|
||||||
|
if (CollectionUtils.isEmpty(copyDOList)) {
|
||||||
|
return success(new ArrayList<>(0));
|
||||||
|
}
|
||||||
|
List<BpmProcessInstanceCopyVO> copyVOList = new ArrayList<>(copyDOList.size());
|
||||||
|
SetUniqueList<Long> userIdList = SetUniqueList.setUniqueList(new ArrayList<>());
|
||||||
|
for (BpmProcessInstanceCopyDO copyDO : copyDOList) {
|
||||||
|
BpmProcessInstanceCopyVO copyVO = new BpmProcessInstanceCopyVO();
|
||||||
|
BeanUtil.copyProperties(copyDO, copyVO);
|
||||||
|
copyVOList.add(copyVO);
|
||||||
|
userIdList.add(copyDO.getStartUserId());
|
||||||
|
userIdList.add(copyDO.getUserId());
|
||||||
|
}
|
||||||
|
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIdList);
|
||||||
|
for (BpmProcessInstanceCopyVO copyVO : copyVOList) {
|
||||||
|
copyVO.setStartUserName(userMap.get(copyVO.getStartUserId()).getNickname());
|
||||||
|
copyVO.setUserName(userMap.get(copyVO.getUserId()).getNickname());
|
||||||
|
}
|
||||||
|
return success(copyVOList);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/get-next-approval-nodes")
|
@GetMapping("/get-next-approval-nodes")
|
||||||
@Operation(summary = "获取下一个执行的流程节点")
|
@Operation(summary = "获取下一个执行的流程节点")
|
||||||
@PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
|
@PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package com.zt.plat.module.bpm.controller.admin.task.vo.instance;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程抄送 VO
|
||||||
|
*
|
||||||
|
* @author kr
|
||||||
|
* @since 2025-12-31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class BpmProcessInstanceCopyVO extends BaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编号
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起人 Id
|
||||||
|
*/
|
||||||
|
@Schema(description ="发起人 Id")
|
||||||
|
private Long startUserId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起人 姓名
|
||||||
|
*/
|
||||||
|
@Schema(description ="发起人 姓名")
|
||||||
|
private String startUserName;
|
||||||
|
/**
|
||||||
|
* 流程名
|
||||||
|
*/
|
||||||
|
@Schema(description ="流程名")
|
||||||
|
private String processInstanceName;
|
||||||
|
/**
|
||||||
|
* 流程实例的编号
|
||||||
|
*/
|
||||||
|
@Schema(description ="流程实例的编号")
|
||||||
|
private String processInstanceId;
|
||||||
|
/**
|
||||||
|
* 流程实例的流程定义编号
|
||||||
|
*/
|
||||||
|
@Schema(description ="流程实例的流程定义编号")
|
||||||
|
private String processDefinitionId;
|
||||||
|
/**
|
||||||
|
* 流程分类
|
||||||
|
*/
|
||||||
|
@Schema(description ="流程分类")
|
||||||
|
private String category;
|
||||||
|
/**
|
||||||
|
* 流程活动的编号
|
||||||
|
*/
|
||||||
|
@Schema(description ="流程活动的编号")
|
||||||
|
private String activityId;
|
||||||
|
/**
|
||||||
|
* 流程活动的名字
|
||||||
|
*/
|
||||||
|
@Schema(description ="流程活动的名字")
|
||||||
|
private String activityName;
|
||||||
|
/**
|
||||||
|
* 流程活动的编号
|
||||||
|
*/
|
||||||
|
@Schema(description ="流程活动的编号")
|
||||||
|
private String taskId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户编号(被抄送的用户编号)
|
||||||
|
*/
|
||||||
|
@Schema(description ="用户编号(被抄送的用户编号)")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户姓名(被抄送的用户姓名)
|
||||||
|
*/
|
||||||
|
@Schema(description ="用户姓名(被抄送的用户姓名)")
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抄送意见
|
||||||
|
*/
|
||||||
|
@Schema(description ="抄送意见")
|
||||||
|
private String reason;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -87,9 +87,16 @@ public interface BpmProcessInstanceConvert {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 摘要
|
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionInfoMap.get(respVO.getProcessDefinitionId());
|
||||||
respVO.setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(respVO.getProcessDefinitionId()),
|
if (processDefinitionInfo != null) {
|
||||||
pageResult.getList().get(i).getProcessVariables()));
|
// 摘要
|
||||||
|
respVO.setSummary(FlowableUtils.getSummary(processDefinitionInfo,
|
||||||
|
pageResult.getList().get(i).getProcessVariables()));
|
||||||
|
// 是否可见
|
||||||
|
respVO.getProcessDefinition().setVisible(processDefinitionInfo.getVisible());
|
||||||
|
// 是否可以重新发起流程
|
||||||
|
respVO.getProcessDefinition().setRestart(processDefinitionInfo.getRestart());
|
||||||
|
}
|
||||||
// 表单
|
// 表单
|
||||||
respVO.setFormVariables(pageResult.getList().get(i).getProcessVariables());
|
respVO.setFormVariables(pageResult.getList().get(i).getProcessVariables());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,6 +129,13 @@ public class BpmProcessDefinitionInfoDO extends BaseDO {
|
|||||||
* 目的:如果 false 不可见,则不展示在“发起流程”的列表里
|
* 目的:如果 false 不可见,则不展示在“发起流程”的列表里
|
||||||
*/
|
*/
|
||||||
private Boolean visible;
|
private Boolean visible;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否允许重新发起
|
||||||
|
*
|
||||||
|
* 目的:如果 false 则不可以重新发起流程
|
||||||
|
*/
|
||||||
|
private Boolean restart;
|
||||||
/**
|
/**
|
||||||
* 排序值
|
* 排序值
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import com.zt.plat.module.bpm.controller.admin.task.vo.instance.BpmProcessInstan
|
|||||||
import com.zt.plat.module.bpm.dal.dataobject.task.BpmProcessInstanceCopyDO;
|
import com.zt.plat.module.bpm.dal.dataobject.task.BpmProcessInstanceCopyDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface BpmProcessInstanceCopyMapper extends BaseMapperX<BpmProcessInstanceCopyDO> {
|
public interface BpmProcessInstanceCopyMapper extends BaseMapperX<BpmProcessInstanceCopyDO> {
|
||||||
|
|
||||||
@@ -22,4 +24,8 @@ public interface BpmProcessInstanceCopyMapper extends BaseMapperX<BpmProcessInst
|
|||||||
delete(BpmProcessInstanceCopyDO::getProcessInstanceId, processInstanceId);
|
delete(BpmProcessInstanceCopyDO::getProcessInstanceId, processInstanceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default List<BpmProcessInstanceCopyDO> getByProcessInstanceId(String processInstanceId) {
|
||||||
|
return selectList(BpmProcessInstanceCopyDO::getProcessInstanceId, processInstanceId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import jakarta.validation.constraints.NotEmpty;
|
|||||||
import org.flowable.bpmn.model.FlowNode;
|
import org.flowable.bpmn.model.FlowNode;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 流程抄送 Service 接口
|
* 流程抄送 Service 接口
|
||||||
@@ -57,4 +58,12 @@ public interface BpmProcessInstanceCopyService {
|
|||||||
*/
|
*/
|
||||||
void deleteProcessInstanceCopy(String processInstanceId);
|
void deleteProcessInstanceCopy(String processInstanceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得流程的抄送列表
|
||||||
|
*
|
||||||
|
* @param processInstanceId 流程实例 ID
|
||||||
|
* @return 抄送流程列表
|
||||||
|
*/
|
||||||
|
List<BpmProcessInstanceCopyDO> getByProcessInstanceId(String processInstanceId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,4 +93,9 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy
|
|||||||
processInstanceCopyMapper.deleteByProcessInstanceId(processInstanceId);
|
processInstanceCopyMapper.deleteByProcessInstanceId(processInstanceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BpmProcessInstanceCopyDO> getByProcessInstanceId(String processInstanceId) {
|
||||||
|
return processInstanceCopyMapper.getByProcessInstanceId(processInstanceId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,4 +73,8 @@
|
|||||||
</root>
|
</root>
|
||||||
</springProfile>
|
</springProfile>
|
||||||
|
|
||||||
|
<logger name="com.zt.plat.module.bpm.dal" level="DEBUG" additivity="false">
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package com.zt.plat.module.databus.api.provider;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.module.databus.api.data.DatabusUserDeptData;
|
||||||
|
import com.zt.plat.module.databus.api.dto.CursorPageReqDTO;
|
||||||
|
import com.zt.plat.module.databus.api.dto.CursorPageResult;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Databus 用户-部门关系数据提供者 API
|
||||||
|
* <p>
|
||||||
|
* 供 Databus 调用,获取用户-部门关联数据用于全量/增量同步
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@FeignClient(name = "${databus.provider.user-dept.service:system-server}")
|
||||||
|
@Tag(name = "RPC 服务 - Databus 用户-部门关系数据提供者")
|
||||||
|
public interface DatabusUserDeptProviderApi {
|
||||||
|
|
||||||
|
String PREFIX = "/rpc/databus/user-dept";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 游标分页查询用户-部门关系数据(用于全量同步)
|
||||||
|
*
|
||||||
|
* @param reqDTO 游标分页请求
|
||||||
|
* @return 用户-部门关系数据分页结果
|
||||||
|
*/
|
||||||
|
@PostMapping(PREFIX + "/page-by-cursor")
|
||||||
|
@Operation(summary = "游标分页查询用户-部门关系数据")
|
||||||
|
CommonResult<CursorPageResult<DatabusUserDeptData>> getPageByCursor(@RequestBody CursorPageReqDTO reqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询用户-部门关系详情(用于增量同步)
|
||||||
|
*
|
||||||
|
* @param id 关系ID
|
||||||
|
* @return 用户-部门关系数据
|
||||||
|
*/
|
||||||
|
@GetMapping(PREFIX + "/get")
|
||||||
|
@Operation(summary = "查询用户-部门关系详情")
|
||||||
|
@Parameter(name = "id", description = "关系ID", required = true, example = "1001")
|
||||||
|
CommonResult<DatabusUserDeptData> getById(@RequestParam("id") Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量查询用户-部门关系详情(用于增量同步批量获取)
|
||||||
|
*
|
||||||
|
* @param ids 关系ID列表
|
||||||
|
* @return 用户-部门关系数据列表
|
||||||
|
*/
|
||||||
|
@GetMapping(PREFIX + "/list")
|
||||||
|
@Operation(summary = "批量查询用户-部门关系详情")
|
||||||
|
@Parameter(name = "ids", description = "关系ID列表", required = true, example = "1001,1002,1003")
|
||||||
|
CommonResult<List<DatabusUserDeptData>> getListByIds(@RequestParam("ids") List<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计用户-部门关系总数(用于全量同步进度计算)
|
||||||
|
*
|
||||||
|
* @param tenantId 租户ID(可选)
|
||||||
|
* @return 用户-部门关系总数
|
||||||
|
*/
|
||||||
|
@GetMapping(PREFIX + "/count")
|
||||||
|
@Operation(summary = "统计用户-部门关系总数")
|
||||||
|
@Parameter(name = "tenantId", description = "租户ID", example = "1")
|
||||||
|
CommonResult<Long> count(@RequestParam(value = "tenantId", required = false) Long tenantId);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package com.zt.plat.module.databus.api.provider;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.module.databus.api.data.DatabusUserPostData;
|
||||||
|
import com.zt.plat.module.databus.api.dto.CursorPageReqDTO;
|
||||||
|
import com.zt.plat.module.databus.api.dto.CursorPageResult;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Databus 用户-岗位关系数据提供者 API
|
||||||
|
* <p>
|
||||||
|
* 供 Databus 调用,获取用户-岗位关联数据用于全量/增量同步
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@FeignClient(name = "${databus.provider.user-post.service:system-server}")
|
||||||
|
@Tag(name = "RPC 服务 - Databus 用户-岗位关系数据提供者")
|
||||||
|
public interface DatabusUserPostProviderApi {
|
||||||
|
|
||||||
|
String PREFIX = "/rpc/databus/user-post";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 游标分页查询用户-岗位关系数据(用于全量同步)
|
||||||
|
*
|
||||||
|
* @param reqDTO 游标分页请求
|
||||||
|
* @return 用户-岗位关系数据分页结果
|
||||||
|
*/
|
||||||
|
@PostMapping(PREFIX + "/page-by-cursor")
|
||||||
|
@Operation(summary = "游标分页查询用户-岗位关系数据")
|
||||||
|
CommonResult<CursorPageResult<DatabusUserPostData>> getPageByCursor(@RequestBody CursorPageReqDTO reqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询用户-岗位关系详情(用于增量同步)
|
||||||
|
*
|
||||||
|
* @param id 关系ID
|
||||||
|
* @return 用户-岗位关系数据
|
||||||
|
*/
|
||||||
|
@GetMapping(PREFIX + "/get")
|
||||||
|
@Operation(summary = "查询用户-岗位关系详情")
|
||||||
|
@Parameter(name = "id", description = "关系ID", required = true, example = "1001")
|
||||||
|
CommonResult<DatabusUserPostData> getById(@RequestParam("id") Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量查询用户-岗位关系详情(用于增量同步批量获取)
|
||||||
|
*
|
||||||
|
* @param ids 关系ID列表
|
||||||
|
* @return 用户-岗位关系数据列表
|
||||||
|
*/
|
||||||
|
@GetMapping(PREFIX + "/list")
|
||||||
|
@Operation(summary = "批量查询用户-岗位关系详情")
|
||||||
|
@Parameter(name = "ids", description = "关系ID列表", required = true, example = "1001,1002,1003")
|
||||||
|
CommonResult<List<DatabusUserPostData>> getListByIds(@RequestParam("ids") List<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计用户-岗位关系总数(用于全量同步进度计算)
|
||||||
|
*
|
||||||
|
* @param tenantId 租户ID(可选)
|
||||||
|
* @return 用户-岗位关系总数
|
||||||
|
*/
|
||||||
|
@GetMapping(PREFIX + "/count")
|
||||||
|
@Operation(summary = "统计用户-岗位关系总数")
|
||||||
|
@Parameter(name = "tenantId", description = "租户ID", example = "1")
|
||||||
|
CommonResult<Long> count(@RequestParam(value = "tenantId", required = false) Long tenantId);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -185,6 +185,11 @@
|
|||||||
<version>4.12.0</version>
|
<version>4.12.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.zt.plat</groupId>
|
||||||
|
<artifactId>zt-spring-boot-starter-databus-client</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.springframework.web.util.ContentCachingResponseWrapper;
|
|||||||
import org.springframework.web.util.UriComponentsBuilder;
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@@ -304,15 +305,28 @@ public class GatewaySecurityFilter extends OncePerRequestFilter {
|
|||||||
.build()
|
.build()
|
||||||
.getQueryParams();
|
.getQueryParams();
|
||||||
params.forEach((key, values) -> {
|
params.forEach((key, values) -> {
|
||||||
if (!StringUtils.hasText(key) || "signature".equalsIgnoreCase(key)) {
|
String decodedKey = URLDecoder.decode(key, StandardCharsets.UTF_8);
|
||||||
|
if (!StringUtils.hasText(decodedKey) || "signature".equalsIgnoreCase(decodedKey)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isEmpty(values)) {
|
if (CollectionUtils.isEmpty(values)) {
|
||||||
target.put(key, "");
|
target.put(decodedKey, "");
|
||||||
} else if (values.size() == 1) {
|
return;
|
||||||
target.put(key, values.get(0));
|
}
|
||||||
|
// 对每一个 value 做 URL 解码,确保与客户端原文签名一致
|
||||||
|
List<String> decodedValues = values.stream()
|
||||||
|
.map(val -> URLDecoder.decode(val, StandardCharsets.UTF_8))
|
||||||
|
.toList();
|
||||||
|
boolean allNullLiteral = decodedValues.stream()
|
||||||
|
.allMatch(v -> "null".equals(v));
|
||||||
|
if (allNullLiteral) {
|
||||||
|
// 过滤掉仅包含字符串 "null" 的参数
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (decodedValues.size() == 1) {
|
||||||
|
target.put(decodedKey, decodedValues.get(0));
|
||||||
} else {
|
} else {
|
||||||
target.put(key, String.join(",", values));
|
target.put(decodedKey, String.join(",", decodedValues));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
|
|||||||
@@ -4,9 +4,13 @@ import com.zt.plat.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
|
|||||||
import com.zt.plat.module.databus.api.provider.DatabusDeptProviderApi;
|
import com.zt.plat.module.databus.api.provider.DatabusDeptProviderApi;
|
||||||
import com.zt.plat.module.databus.api.provider.DatabusPostProviderApi;
|
import com.zt.plat.module.databus.api.provider.DatabusPostProviderApi;
|
||||||
import com.zt.plat.module.databus.api.provider.DatabusUserProviderApi;
|
import com.zt.plat.module.databus.api.provider.DatabusUserProviderApi;
|
||||||
|
import com.zt.plat.module.databus.api.provider.DatabusUserDeptProviderApi;
|
||||||
|
import com.zt.plat.module.databus.api.provider.DatabusUserPostProviderApi;
|
||||||
import com.zt.plat.module.system.api.dept.DeptApi;
|
import com.zt.plat.module.system.api.dept.DeptApi;
|
||||||
import com.zt.plat.module.system.api.dept.PostApi;
|
import com.zt.plat.module.system.api.dept.PostApi;
|
||||||
import com.zt.plat.module.system.api.user.AdminUserApi;
|
import com.zt.plat.module.system.api.user.AdminUserApi;
|
||||||
|
import com.zt.plat.module.system.api.userdept.UserDeptApi;
|
||||||
|
import com.zt.plat.module.system.api.userpost.UserPostApi;
|
||||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@@ -21,9 +25,12 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
DatabusDeptProviderApi.class,
|
DatabusDeptProviderApi.class,
|
||||||
DatabusUserProviderApi.class,
|
DatabusUserProviderApi.class,
|
||||||
DatabusPostProviderApi.class,
|
DatabusPostProviderApi.class,
|
||||||
PostApi.class,
|
DatabusUserDeptProviderApi.class,
|
||||||
DeptApi.class,
|
DatabusUserPostProviderApi.class,
|
||||||
AdminUserApi.class,
|
PostApi.class,
|
||||||
|
DeptApi.class,
|
||||||
|
UserDeptApi.class,
|
||||||
|
UserPostApi.class,
|
||||||
})
|
})
|
||||||
public class RpcConfiguration {
|
public class RpcConfiguration {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.zt.plat.framework.common.util.security.CryptoSignatureUtils;
|
import com.zt.plat.framework.common.util.security.CryptoSignatureUtils;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLParameters;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
@@ -23,10 +27,6 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.SSLParameters;
|
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import javax.net.ssl.X509TrustManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可直接运行的示例,演示如何使用 appId=test 与对应密钥调用本地 Databus API。
|
* 可直接运行的示例,演示如何使用 appId=test 与对应密钥调用本地 Databus API。
|
||||||
@@ -37,14 +37,14 @@ public final class DatabusApiInvocationExample {
|
|||||||
|
|
||||||
// private static final String APP_ID = "iwork";
|
// private static final String APP_ID = "iwork";
|
||||||
// private static final String APP_SECRET = "lpGXiNe/GMLk0vsbYGLa8eYxXq8tGhTbuu3/D4MJzIk=";
|
// private static final String APP_SECRET = "lpGXiNe/GMLk0vsbYGLa8eYxXq8tGhTbuu3/D4MJzIk=";
|
||||||
private static final String APP_ID = "ztmy";
|
private static final String APP_ID = "jwyw";
|
||||||
private static final String APP_SECRET = "zFre/nTRGi7LpoFjN7oQkKeOT09x1fWTyIswrc702QQ=";
|
private static final String APP_SECRET = "MhfCcqB59rDTnB5yGOVXWtp/5a0JXir7pSjPl5cVMJ8=";
|
||||||
private static final String ENCRYPTION_TYPE = CryptoSignatureUtils.ENCRYPT_TYPE_AES;
|
private static final String ENCRYPTION_TYPE = CryptoSignatureUtils.ENCRYPT_TYPE_AES;
|
||||||
// private static final String TARGET_API = "http://172.16.46.63:30081/admin-api/databus/api/portal/callback/v1";
|
// private static final String TARGET_API = "http://172.16.46.63:30081/admin-api/databus/api/portal/callback/v1";
|
||||||
// private static final String TARGET_API = "http://172.16.46.195:48080/admin-api/databus/api/portal/lgstOpenApi/v1";
|
// private static final String TARGET_API = "http://172.16.46.195:48080/admin-api/databus/api/portal/lgstOpenApi/v1";
|
||||||
// private static final String TARGET_API = "http://172.16.46.195:48080/admin-api/databus/api/portal/lgstOpenApi/v1";
|
// private static final String TARGET_API = "http://172.16.46.195:48080/admin-api/databus/api/portal/lgstOpenApi/v1";
|
||||||
private static final String TARGET_API = "https://jygk.chncopper.com:30078/admin-api/databus/api/portal/lgstOpenApi/v1";
|
// private static final String TARGET_API = "https://jygk.chncopper.com:30078/admin-api/databus/api/portal/lgstOpenApi/v1";
|
||||||
// private static final String TARGET_API = "http://localhost:48080/admin-api/databus/api/portal/callback/v1";
|
private static final String TARGET_API = "http://localhost:48080/admin-api/databus/api/portal/testcbw/456";
|
||||||
// private static final String TARGET_API = "http://localhost:48080/admin-api/databus/api/portal/lgstOpenApi/v1";
|
// private static final String TARGET_API = "http://localhost:48080/admin-api/databus/api/portal/lgstOpenApi/v1";
|
||||||
// private static final String TARGET_API = "http://localhost:48080/admin-api/databus/api/portal/testcbw/456";
|
// private static final String TARGET_API = "http://localhost:48080/admin-api/databus/api/portal/testcbw/456";
|
||||||
// ⚠️ 仅用于联调:信任所有证书 + 关闭主机名校验,生产环境请改为受信 CA 或自定义 truststore。
|
// ⚠️ 仅用于联调:信任所有证书 + 关闭主机名校验,生产环境请改为受信 CA 或自定义 truststore。
|
||||||
@@ -102,10 +102,16 @@ public final class DatabusApiInvocationExample {
|
|||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
OUT.println("=== GET 请求示例 ===");
|
OUT.println("=== GET 请求示例 ===");
|
||||||
// executeGetExample();
|
executeGetExample();
|
||||||
// OUT.println();
|
// OUT.println();
|
||||||
// OUT.println("=== POST 请求示例 ===");
|
OUT.println("=== POST 请求示例 ===");
|
||||||
executePostExample();
|
executePostExample("""
|
||||||
|
{"operateFlag":"I","__interfaceType__":"R_MY_JY_03","data":{"endAddressName":"1","customerCompanyName":"中铜国贸","endAddressDetail":"测试地址","remark":" ","custSuppType":"1","shipperCompanyName":"中铜国贸","consigneeCorpCode":" ","consignerContactPhone":" 11","importFlag":"10","businessSupplierCode":" ","entrustMainCode":"WT3162251027027","endAddressCode":" ","specifyCarrierCorpCode":"10086689","materDetail":[{"detailStatus":"10","batchNo":"ZLTD2510ZTGM0017001","measureCodeMdm":"CU032110001","packType":" ","quantityPlanDetail":1,"deliveryOrderNo":"ZLTD2510ZTGM0017001","measureCode":"CU032110001","goodsSpecification":" ","measureUnitCode":"PAC","entrustDetailCode":"WT3162251027027001","brand":" ","soNumber":"68ecf0055502d565d22b378a"}],"operateFlag":1,"custSuppName":"上海锦生金属有限公司","startAddressCode":" ","planStartTime":1761556166000,"customerCompanyCode":0,"importMethod":"EXW","startAddressType":"10","shipperCompanyCode":"3162","deliverCondition":"20","businessSupplierName":" ","startAddressDetail":" 111","transType":"30","endAddressType":"20","planEndTime":1761556166000,"specifyCarrierCorpName":null,"custSuppFlag":"0101","businessType":"20","consigneeCorpName":" ","custSuppCode":"10086689","startAddressName":" 111","consignerContactName":" 11"},"datetime":"20251027170929","busiBillCode":"WT3162251027027","system":"BRMS","__requestId__":"f918841c-14fb-49eb-9640-c5d1b3d46bd1"}
|
||||||
|
""");
|
||||||
|
|
||||||
|
executePostExample("""
|
||||||
|
{"msgCode":"YWJYGK0003","data":"{\\"memberId\\":65352,\\"routes\\":[{\\"carrierCorpCode\\":\\"10193776\\",\\"carrierCorpName\\":\\"成都达海金属加工配送有限公司\\",\\"endAddressCode\\":\\"440000-440300\\",\\"endAddressDetail\\":\\"深圳港\\",\\"endAddressDetailDesc\\":\\"广东省深圳市盐田区深盐路\\",\\"endAddressLatitude\\":22.567426,\\"endAddressLongitude\\":114.283271,\\"endAddressName\\":\\"广东省-深圳市\\",\\"endAddressType\\":\\"port\\",\\"startAddressCode\\":\\"520000-0\\",\\"startAddressDetail\\":\\"安龙\\",\\"startAddressDetailDesc\\":\\"贵州省安龙县德卧镇坡告村\\",\\"startAddressLatitude\\":25.066532,\\"startAddressLongitude\\":105.244186,\\"startAddressName\\":\\"贵州省-null\\",\\"startAddressType\\":\\"railway-station\\",\\"taskEndTime\\":1766592000000,\\"taskStartTime\\":1766332800000,\\"transType\\":\\"10\\"},{\\"carrierCorpCode\\":\\"10193776\\",\\"carrierCorpName\\":\\"成都达海金属加工配送有限公司\\",\\"endAddressCode\\":\\"230000-230600\\",\\"endAddressDetail\\":\\"大庆东\\",\\"endAddressDetailDesc\\":\\"黑龙江省大庆市龙凤区凤一路28号\\",\\"endAddressLatitude\\":46.544097,\\"endAddressLongitude\\":125.118902,\\"endAddressName\\":\\"黑龙江省-大庆市\\",\\"endAddressType\\":\\"railway-station\\",\\"startAddressCode\\":\\"440000-440300\\",\\"startAddressDetail\\":\\"深圳港\\",\\"startAddressDetailDesc\\":\\"广东省深圳市盐田区深盐路\\",\\"startAddressLatitude\\":22.567426,\\"startAddressLongitude\\":114.283271,\\"startAddressName\\":\\"广东省-深圳市\\",\\"startAddressType\\":\\"port\\",\\"taskEndTime\\":1767110400000,\\"taskStartTime\\":1766592000000,\\"transType\\":\\"30\\"},{\\"carrierCorpCode\\":\\"10193776\\",\\"carrierCorpName\\":\\"成都达海金属加工配送有限公司\\",\\"endAddressCode\\":\\"520000-0\\",\\"endAddressDetail\\":\\"郑屯\\",\\"endAddressDetailDesc\\":\\"贵州省郑屯镇\\",\\"endAddressName\\":\\"贵州省-null\\",\\"endAddressType\\":\\"railway-station\\",\\"startAddressCode\\":\\"230000-230600\\",\\"startAddressDetail\\":\\"大庆东\\",\\"startAddressDetailDesc\\":\\"黑龙江省大庆市龙凤区凤一路28号\\",\\"startAddressLatitude\\":46.544097,\\"startAddressLongitude\\":125.118902,\\"startAddressName\\":\\"黑龙江省-大庆市\\",\\"startAddressType\\":\\"railway-station\\",\\"taskEndTime\\":1768320000000,\\"taskStartTime\\":1767110400000,\\"transType\\":\\"20\\"}],\\"taskLineNumber\\":\\"CT202512230001_001\\",\\"taskNumber\\":\\"CT202512230001\\"}"}
|
||||||
|
""");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void executeGetExample() throws Exception {
|
private static void executeGetExample() throws Exception {
|
||||||
@@ -113,9 +119,11 @@ public final class DatabusApiInvocationExample {
|
|||||||
queryParams.put("businessCode", "11");
|
queryParams.put("businessCode", "11");
|
||||||
queryParams.put("fileId", "11");
|
queryParams.put("fileId", "11");
|
||||||
queryParams.put("null", null);
|
queryParams.put("null", null);
|
||||||
|
queryParams.put("empty", "");
|
||||||
|
queryParams.put("taskTimeEnd", "2025-12-28 23:00:00");
|
||||||
String signature = generateSignature(queryParams, Map.of());
|
String signature = generateSignature(queryParams, Map.of());
|
||||||
URI requestUri = buildUri(TARGET_API, queryParams);
|
URI requestUri = buildUri(TARGET_API, queryParams);
|
||||||
String nonce = "171615676c7d4d96b9f55f3d90ad27e0";
|
String nonce = randomNonce();
|
||||||
|
|
||||||
HttpRequest request = HttpRequest.newBuilder(requestUri)
|
HttpRequest request = HttpRequest.newBuilder(requestUri)
|
||||||
.timeout(Duration.ofSeconds(10))
|
.timeout(Duration.ofSeconds(10))
|
||||||
@@ -131,16 +139,14 @@ public final class DatabusApiInvocationExample {
|
|||||||
printResponse(response);
|
printResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void executePostExample() throws Exception {
|
private static void executePostExample(String json) throws Exception {
|
||||||
Map<String, Object> queryParams = new LinkedHashMap<>();
|
Map<String, Object> queryParams = new LinkedHashMap<>();
|
||||||
|
|
||||||
long extraTimestamp = 1761556157185L;
|
long extraTimestamp = 1761556157185L;
|
||||||
// String bodyJson = String.format("""
|
// String bodyJson = String.json("""
|
||||||
// {"operateFlag":"I","__interfaceType__":"R_MY_JY_03","data":{"endAddressName":"1","customerCompanyName":"中铜国贸","endAddressDetail":"测试地址","remark":" ","custSuppType":"1","shipperCompanyName":"中铜国贸","consigneeCorpCode":" ","consignerContactPhone":" 11","importFlag":"10","businessSupplierCode":" ","entrustMainCode":"WT3162251027027","endAddressCode":" ","specifyCarrierCorpCode":"10086689","materDetail":[{"detailStatus":"10","batchNo":"ZLTD2510ZTGM0017001","measureCodeMdm":"CU032110001","packType":" ","quantityPlanDetail":1,"deliveryOrderNo":"ZLTD2510ZTGM0017001","measureCode":"CU032110001","goodsSpecification":" ","measureUnitCode":"PAC","entrustDetailCode":"WT3162251027027001","brand":" ","soNumber":"68ecf0055502d565d22b378a"}],"operateFlag":1,"custSuppName":"上海锦生金属有限公司","startAddressCode":" ","planStartTime":1761556166000,"customerCompanyCode":0,"importMethod":"EXW","startAddressType":"10","shipperCompanyCode":"3162","deliverCondition":"20","businessSupplierName":" ","startAddressDetail":" 111","transType":"30","endAddressType":"20","planEndTime":1761556166000,"specifyCarrierCorpName":null,"custSuppFlag":"0101","businessType":"20","consigneeCorpName":" ","custSuppCode":"10086689","startAddressName":" 111","consignerContactName":" 11"},"datetime":"20251027170929","busiBillCode":"WT3162251027027","system":"BRMS","__requestId__":"f918841c-14fb-49eb-9640-c5d1b3d46bd1"}
|
// {"operateFlag":"I","__interfaceType__":"R_MY_JY_03","data":{"endAddressName":"1","customerCompanyName":"中铜国贸","endAddressDetail":"测试地址","remark":" ","custSuppType":"1","shipperCompanyName":"中铜国贸","consigneeCorpCode":" ","consignerContactPhone":" 11","importFlag":"10","businessSupplierCode":" ","entrustMainCode":"WT3162251027027","endAddressCode":" ","specifyCarrierCorpCode":"10086689","materDetail":[{"detailStatus":"10","batchNo":"ZLTD2510ZTGM0017001","measureCodeMdm":"CU032110001","packType":" ","quantityPlanDetail":1,"deliveryOrderNo":"ZLTD2510ZTGM0017001","measureCode":"CU032110001","goodsSpecification":" ","measureUnitCode":"PAC","entrustDetailCode":"WT3162251027027001","brand":" ","soNumber":"68ecf0055502d565d22b378a"}],"operateFlag":1,"custSuppName":"上海锦生金属有限公司","startAddressCode":" ","planStartTime":1761556166000,"customerCompanyCode":0,"importMethod":"EXW","startAddressType":"10","shipperCompanyCode":"3162","deliverCondition":"20","businessSupplierName":" ","startAddressDetail":" 111","transType":"30","endAddressType":"20","planEndTime":1761556166000,"specifyCarrierCorpName":null,"custSuppFlag":"0101","businessType":"20","consigneeCorpName":" ","custSuppCode":"10086689","startAddressName":" 111","consignerContactName":" 11"},"datetime":"20251027170929","busiBillCode":"WT3162251027027","system":"BRMS","__requestId__":"f918841c-14fb-49eb-9640-c5d1b3d46bd1"}
|
||||||
// """, extraTimestamp);
|
// """, extraTimestamp);
|
||||||
String bodyJson = String.format("""
|
String bodyJson = String.format(json, extraTimestamp);
|
||||||
{}
|
|
||||||
""", extraTimestamp);
|
|
||||||
|
|
||||||
Map<String, Object> bodyParams = parseBodyJson(bodyJson);
|
Map<String, Object> bodyParams = parseBodyJson(bodyJson);
|
||||||
String signature = generateSignature(queryParams, bodyParams);
|
String signature = generateSignature(queryParams, bodyParams);
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package com.zt.plat.module.infra.service.file;
|
|||||||
|
|
||||||
import cn.hutool.core.io.resource.ResourceUtil;
|
import cn.hutool.core.io.resource.ResourceUtil;
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.zt.plat.framework.common.pojo.PageResult;
|
import com.zt.plat.framework.common.pojo.PageResult;
|
||||||
import com.zt.plat.framework.common.util.json.JsonUtils;
|
import com.zt.plat.framework.common.util.json.JsonUtils;
|
||||||
import com.zt.plat.framework.common.util.validation.ValidationUtils;
|
import com.zt.plat.framework.common.util.validation.ValidationUtils;
|
||||||
@@ -14,8 +16,6 @@ import com.zt.plat.module.infra.framework.file.core.client.FileClient;
|
|||||||
import com.zt.plat.module.infra.framework.file.core.client.FileClientConfig;
|
import com.zt.plat.module.infra.framework.file.core.client.FileClientConfig;
|
||||||
import com.zt.plat.module.infra.framework.file.core.client.FileClientFactory;
|
import com.zt.plat.module.infra.framework.file.core.client.FileClientFactory;
|
||||||
import com.zt.plat.module.infra.framework.file.core.enums.FileStorageEnum;
|
import com.zt.plat.module.infra.framework.file.core.enums.FileStorageEnum;
|
||||||
import com.google.common.cache.CacheLoader;
|
|
||||||
import com.google.common.cache.LoadingCache;
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.validation.Validator;
|
import jakarta.validation.Validator;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -172,7 +172,7 @@ public class FileConfigServiceImpl implements FileConfigService {
|
|||||||
// 校验存在
|
// 校验存在
|
||||||
validateFileConfigExists(id);
|
validateFileConfigExists(id);
|
||||||
// 上传文件
|
// 上传文件
|
||||||
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
byte[] content = ResourceUtil.readBytes("file/bg1.png");
|
||||||
return getFileClient(id).upload(content, IdUtil.fastSimpleUUID() + ".jpg", "image/jpeg");
|
return getFileClient(id).upload(content, IdUtil.fastSimpleUUID() + ".jpg", "image/jpeg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ spring:
|
|||||||
servlet:
|
servlet:
|
||||||
# 文件上传相关配置项
|
# 文件上传相关配置项
|
||||||
multipart:
|
multipart:
|
||||||
max-file-size: 100MB # 单个文件大小
|
max-file-size: 128MB # 单个文件大小
|
||||||
max-request-size: 120MB # 设置总上传的文件大小
|
max-request-size: 512MB # 设置总上传的文件大小
|
||||||
|
|
||||||
# Jackson 配置项
|
# Jackson 配置项
|
||||||
jackson:
|
jackson:
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB |
@@ -41,7 +41,7 @@ public class FtpFileClientTest {
|
|||||||
client.init();
|
client.init();
|
||||||
// 上传文件
|
// 上传文件
|
||||||
String path = IdUtil.fastSimpleUUID() + ".jpg";
|
String path = IdUtil.fastSimpleUUID() + ".jpg";
|
||||||
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
byte[] content = ResourceUtil.readBytes("file/bg1.png");
|
||||||
String fullPath = client.upload(content, path, "image/jpeg");
|
String fullPath = client.upload(content, path, "image/jpeg");
|
||||||
System.out.println("访问地址:" + fullPath);
|
System.out.println("访问地址:" + fullPath);
|
||||||
if (false) {
|
if (false) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class LocalFileClientTest {
|
|||||||
client.init();
|
client.init();
|
||||||
// 上传文件
|
// 上传文件
|
||||||
String path = IdUtil.fastSimpleUUID() + ".jpg";
|
String path = IdUtil.fastSimpleUUID() + ".jpg";
|
||||||
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
byte[] content = ResourceUtil.readBytes("file/bg1.png");
|
||||||
String fullPath = client.upload(content, path, "image/jpeg");
|
String fullPath = client.upload(content, path, "image/jpeg");
|
||||||
System.out.println("访问地址:" + fullPath);
|
System.out.println("访问地址:" + fullPath);
|
||||||
client.delete(path);
|
client.delete(path);
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class S3FileClientTest {
|
|||||||
client.init();
|
client.init();
|
||||||
// 上传文件
|
// 上传文件
|
||||||
String path = IdUtil.fastSimpleUUID() + ".jpg";
|
String path = IdUtil.fastSimpleUUID() + ".jpg";
|
||||||
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
byte[] content = ResourceUtil.readBytes("file/bg1.png");
|
||||||
String fullPath = client.upload(content, path, "image/jpeg");
|
String fullPath = client.upload(content, path, "image/jpeg");
|
||||||
System.out.println("访问地址:" + fullPath);
|
System.out.println("访问地址:" + fullPath);
|
||||||
// 读取文件
|
// 读取文件
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class SftpFileClientTest {
|
|||||||
client.init();
|
client.init();
|
||||||
// 上传文件
|
// 上传文件
|
||||||
String path = IdUtil.fastSimpleUUID() + ".jpg";
|
String path = IdUtil.fastSimpleUUID() + ".jpg";
|
||||||
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
byte[] content = ResourceUtil.readBytes("file/bg1.png");
|
||||||
String fullPath = client.upload(content, path, "image/jpeg");
|
String fullPath = client.upload(content, path, "image/jpeg");
|
||||||
System.out.println("访问地址:" + fullPath);
|
System.out.println("访问地址:" + fullPath);
|
||||||
if (false) {
|
if (false) {
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public class FileServiceImplTest extends BaseDbUnitTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCreateFile_success_01() throws Exception {
|
public void testCreateFile_success_01() throws Exception {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
byte[] content = ResourceUtil.readBytes("file/bg1.png");
|
||||||
String name = "单测文件名";
|
String name = "单测文件名";
|
||||||
String directory = randomString();
|
String directory = randomString();
|
||||||
String type = "image/jpeg";
|
String type = "image/jpeg";
|
||||||
@@ -122,7 +122,7 @@ public class FileServiceImplTest extends BaseDbUnitTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCreateFile_success_02() throws Exception {
|
public void testCreateFile_success_02() throws Exception {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
byte[] content = ResourceUtil.readBytes("file/bg1.png");
|
||||||
// mock Master 文件客户端
|
// mock Master 文件客户端
|
||||||
String type = "image/jpeg";
|
String type = "image/jpeg";
|
||||||
FileClient client = mock(FileClient.class);
|
FileClient client = mock(FileClient.class);
|
||||||
@@ -318,7 +318,7 @@ public class FileServiceImplTest extends BaseDbUnitTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCreateFile_withSameHash() throws Exception {
|
public void testCreateFile_withSameHash() throws Exception {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
byte[] content = ResourceUtil.readBytes("file/bg1.png");
|
||||||
String name = "单测文件名";
|
String name = "单测文件名";
|
||||||
String directory = randomString();
|
String directory = randomString();
|
||||||
String type = "image/jpeg";
|
String type = "image/jpeg";
|
||||||
|
|||||||
@@ -86,4 +86,10 @@ public interface DeptApi {
|
|||||||
@Parameter(name = "userId", description = "用户编号", example = "1", required = true)
|
@Parameter(name = "userId", description = "用户编号", example = "1", required = true)
|
||||||
CommonResult<Set<CompanyDeptInfoRespDTO>> getCompanyDeptInfoListByUserId(@RequestParam("userId") Long userId);
|
CommonResult<Set<CompanyDeptInfoRespDTO>> getCompanyDeptInfoListByUserId(@RequestParam("userId") Long userId);
|
||||||
|
|
||||||
|
// ========== 数据同步专用接口 ==========
|
||||||
|
|
||||||
|
@PostMapping(PREFIX + "/sync")
|
||||||
|
@Operation(summary = "同步部门")
|
||||||
|
CommonResult<Boolean> syncDept(@RequestBody DeptSaveReqDTO syncReqDTO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,4 +64,10 @@ public interface PostApi {
|
|||||||
return CollectionUtils.convertMap(list, PostRespDTO::getId);
|
return CollectionUtils.convertMap(list, PostRespDTO::getId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== 数据同步专用接口 ==========
|
||||||
|
|
||||||
|
@PostMapping(PREFIX + "/sync")
|
||||||
|
@Operation(summary = "同步岗位")
|
||||||
|
CommonResult<Boolean> syncPost(@RequestBody PostSaveReqDTO syncReqDTO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,15 @@ public class DeptSaveReqDTO {
|
|||||||
@Schema(description = "部门编号", example = "1024")
|
@Schema(description = "部门编号", example = "1024")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "部门编码", example = "ZT001")
|
||||||
|
private String code;
|
||||||
|
|
||||||
@Schema(description = "部门名称", example = "ZT")
|
@Schema(description = "部门名称", example = "ZT")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "部门简称", example = "技术")
|
||||||
|
private String shortName;
|
||||||
|
|
||||||
@Schema(description = "父部门 ID", example = "1024")
|
@Schema(description = "父部门 ID", example = "1024")
|
||||||
private Long parentId;
|
private Long parentId;
|
||||||
|
|
||||||
@@ -36,6 +42,15 @@ public class DeptSaveReqDTO {
|
|||||||
@Schema(description = "状态,见 CommonStatusEnum 枚举0 开启 1 关闭", example = "0")
|
@Schema(description = "状态,见 CommonStatusEnum 枚举0 开启 1 关闭", example = "0")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "是否集团", example = "false")
|
||||||
|
private Boolean isGroup;
|
||||||
|
|
||||||
|
@Schema(description = "是否公司", example = "false")
|
||||||
|
private Boolean isCompany;
|
||||||
|
|
||||||
|
@Schema(description = "部门来源类型", example = "1")
|
||||||
|
private Integer deptSource;
|
||||||
|
|
||||||
@Schema(description = "外部系统标识,用于建立编码映射", example = "ERP")
|
@Schema(description = "外部系统标识,用于建立编码映射", example = "ERP")
|
||||||
private String externalSystemCode;
|
private String externalSystemCode;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package com.zt.plat.module.system.api.esp;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.framework.common.util.collection.CollectionUtils;
|
||||||
|
import com.zt.plat.module.system.api.dept.dto.*;
|
||||||
|
import com.zt.plat.module.system.enums.ApiConstants;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@FeignClient(name = ApiConstants.NAME)
|
||||||
|
@Tag(name = "RPC 服务 - 部门")
|
||||||
|
public interface EspApi {
|
||||||
|
|
||||||
|
String PREFIX = ApiConstants.PREFIX + "/dept";
|
||||||
|
|
||||||
|
// === 以下为补全的接口方法 ===
|
||||||
|
@PostMapping(PREFIX + "/create")
|
||||||
|
@Operation(summary = "新增部门")
|
||||||
|
CommonResult<Long> createDept(@RequestBody DeptSaveReqDTO createReqVO);
|
||||||
|
|
||||||
|
@PutMapping(PREFIX + "/update")
|
||||||
|
@Operation(summary = "修改部门")
|
||||||
|
CommonResult<Boolean> updateDept(@RequestBody DeptSaveReqDTO updateReqVO);
|
||||||
|
|
||||||
|
@DeleteMapping(PREFIX + "/delete")
|
||||||
|
@Operation(summary = "删除部门")
|
||||||
|
CommonResult<Boolean> deleteDept(@RequestParam("id") Long id);
|
||||||
|
|
||||||
|
@PostMapping(PREFIX + "/list-all")
|
||||||
|
@Operation(summary = "获得部门列表")
|
||||||
|
CommonResult<List<DeptDetailRespDTO>> getDeptList(@RequestBody DeptListReqDTO reqVO);
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/simple-list")
|
||||||
|
@Operation(summary = "获得部门精简信息列表")
|
||||||
|
CommonResult<List<DeptSimpleRespDTO>> getSimpleDeptList();
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/simple-company-list")
|
||||||
|
@Operation(summary = "获得公司精简信息列表")
|
||||||
|
CommonResult<List<DeptSimpleRespDTO>> getSimpleCompanyList();
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/all-company-list")
|
||||||
|
@Operation(summary = "获得所有公司精简信息列表")
|
||||||
|
CommonResult<List<DeptSimpleRespDTO>> getAllCompanyList();
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/get")
|
||||||
|
@Operation(summary = "获得部门信息")
|
||||||
|
@Parameter(name = "id", description = "部门编号", example = "1024", required = true)
|
||||||
|
CommonResult<DeptRespDTO> getDept(@RequestParam("id") Long id);
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/list")
|
||||||
|
@Operation(summary = "获得部门信息数组")
|
||||||
|
@Parameter(name = "ids", description = "部门编号数组", example = "1,2", required = true)
|
||||||
|
CommonResult<List<DeptRespDTO>> getDeptList(@RequestParam("ids") Collection<Long> ids);
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/valid")
|
||||||
|
@Operation(summary = "校验部门是否合法")
|
||||||
|
@Parameter(name = "ids", description = "部门编号数组", example = "1,2", required = true)
|
||||||
|
CommonResult<Boolean> validateDeptList(@RequestParam("ids") Collection<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定编号的部门 Map
|
||||||
|
*
|
||||||
|
* @param ids 部门编号数组
|
||||||
|
* @return 部门 Map
|
||||||
|
*/
|
||||||
|
default Map<Long, DeptRespDTO> getDeptMap(Collection<Long> ids) {
|
||||||
|
List<DeptRespDTO> list = getDeptList(ids).getCheckedData();
|
||||||
|
return CollectionUtils.convertMap(list, DeptRespDTO::getId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/list-child")
|
||||||
|
@Operation(summary = "获得指定部门的所有子部门")
|
||||||
|
@Parameter(name = "id", description = "部门编号", example = "1024", required = true)
|
||||||
|
CommonResult<List<DeptRespDTO>> getChildDeptList(@RequestParam("id") Long id);
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/company-dept-info")
|
||||||
|
@Operation(summary = "获得指定用户的公司部门信息")
|
||||||
|
@Parameter(name = "userId", description = "用户编号", example = "1", required = true)
|
||||||
|
CommonResult<Set<CompanyDeptInfoRespDTO>> getCompanyDeptInfoListByUserId(@RequestParam("userId") Long userId);
|
||||||
|
|
||||||
|
// ========== 数据同步专用接口 ==========
|
||||||
|
|
||||||
|
@PostMapping(PREFIX + "/sync")
|
||||||
|
@Operation(summary = "同步部门")
|
||||||
|
CommonResult<Boolean> syncDept(@RequestBody DeptSaveReqDTO syncReqDTO);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.zt.plat.module.system.api.esp.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Schema(description = "RPC 服务 - 推送外部系统配置信息 Response DTO")
|
||||||
|
@Data
|
||||||
|
public class EspDto {
|
||||||
|
|
||||||
|
@Schema(description = "部门名称,模糊匹配", example = "ZT")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "是否公司", example = "false")
|
||||||
|
private Boolean isCompany;
|
||||||
|
|
||||||
|
@Schema(description = "是否集团", example = "false")
|
||||||
|
private Boolean isGroup;
|
||||||
|
|
||||||
|
@Schema(description = "部门编号集合,支持多部门查询", example = "[\"1001\", \"1002\"]")
|
||||||
|
private List<String> ids;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import com.zt.plat.framework.common.biz.system.permission.PermissionCommonApi;
|
|||||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
import com.zt.plat.module.system.api.permission.dto.*;
|
import com.zt.plat.module.system.api.permission.dto.*;
|
||||||
import com.zt.plat.module.system.enums.ApiConstants;
|
import com.zt.plat.module.system.enums.ApiConstants;
|
||||||
|
import com.zt.plat.module.system.enums.permission.DataScopeEnum;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
@@ -50,4 +51,9 @@ public interface PermissionApi extends PermissionCommonApi {
|
|||||||
@Parameter(name = "userId", description = "用户编号", example = "1", required = true)
|
@Parameter(name = "userId", description = "用户编号", example = "1", required = true)
|
||||||
CommonResult<Set<Long>> getUserRoleIdListByUserId(@RequestParam("userId") Long userId);
|
CommonResult<Set<Long>> getUserRoleIdListByUserId(@RequestParam("userId") Long userId);
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/user-data-permission-level")
|
||||||
|
@Operation(summary = "获得用户的数据权限级别")
|
||||||
|
@Parameter(name = "userId", description = "用户编号", example = "1", required = true)
|
||||||
|
CommonResult<DataScopeEnum> getUserDataPermissionLevel(@RequestParam("userId") Long userId);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -104,6 +104,12 @@ public interface AdminUserApi extends AutoTransable<AdminUserRespDTO> {
|
|||||||
@Parameter(name = "ids", description = "用户编号数组", example = "3,5", required = true)
|
@Parameter(name = "ids", description = "用户编号数组", example = "3,5", required = true)
|
||||||
CommonResult<Boolean> validateUserList(@RequestParam("ids") Collection<Long> ids);
|
CommonResult<Boolean> validateUserList(@RequestParam("ids") Collection<Long> ids);
|
||||||
|
|
||||||
|
// ========== 数据同步专用接口 ==========
|
||||||
|
|
||||||
|
@PostMapping(PREFIX + "/sync")
|
||||||
|
@Operation(summary = "同步用户")
|
||||||
|
CommonResult<Boolean> syncUser(@RequestBody AdminUserSaveReqDTO syncReqDTO);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@FeignIgnore
|
@FeignIgnore
|
||||||
default List<AdminUserRespDTO> selectByIds(List<?> ids) {
|
default List<AdminUserRespDTO> selectByIds(List<?> ids) {
|
||||||
|
|||||||
@@ -50,4 +50,10 @@ public class AdminUserSaveReqDTO {
|
|||||||
@Schema(description = "密码", example = "123456")
|
@Schema(description = "密码", example = "123456")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
|
@Schema(description = "工号", example = "A00123")
|
||||||
|
private String workcode;
|
||||||
|
|
||||||
|
@Schema(description = "用户来源类型", example = "1")
|
||||||
|
private Integer userSource;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.zt.plat.module.system.api.userdept;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.module.system.api.userdept.dto.UserDeptRespDTO;
|
||||||
|
import com.zt.plat.module.system.api.userdept.dto.UserDeptSaveReqDTO;
|
||||||
|
import com.zt.plat.module.system.enums.ApiConstants;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户-部门关系 Feign API
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@FeignClient(name = ApiConstants.NAME)
|
||||||
|
@Tag(name = "RPC 服务 - 用户部门关系")
|
||||||
|
public interface UserDeptApi {
|
||||||
|
|
||||||
|
String PREFIX = ApiConstants.PREFIX + "/user-dept";
|
||||||
|
|
||||||
|
@PostMapping(PREFIX + "/create")
|
||||||
|
@Operation(summary = "新增用户部门关系")
|
||||||
|
CommonResult<Long> createUserDept(@RequestBody UserDeptSaveReqDTO reqVO);
|
||||||
|
|
||||||
|
@PutMapping(PREFIX + "/update")
|
||||||
|
@Operation(summary = "修改用户部门关系")
|
||||||
|
CommonResult<Boolean> updateUserDept(@RequestBody UserDeptSaveReqDTO reqVO);
|
||||||
|
|
||||||
|
@DeleteMapping(PREFIX + "/delete")
|
||||||
|
@Operation(summary = "删除用户部门关系")
|
||||||
|
@Parameter(name = "id", description = "关系编号", example = "1", required = true)
|
||||||
|
CommonResult<Boolean> deleteUserDept(@RequestParam("id") Long id);
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/get")
|
||||||
|
@Operation(summary = "通过ID查询用户部门关系")
|
||||||
|
@Parameter(name = "id", description = "关系编号", example = "1", required = true)
|
||||||
|
CommonResult<UserDeptRespDTO> getUserDept(@RequestParam("id") Long id);
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/list-by-user-id")
|
||||||
|
@Operation(summary = "通过用户ID查询用户部门关系列表")
|
||||||
|
@Parameter(name = "userId", description = "用户编号", example = "1", required = true)
|
||||||
|
CommonResult<List<UserDeptRespDTO>> getUserDeptListByUserId(@RequestParam("userId") Long userId);
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/list-by-dept-id")
|
||||||
|
@Operation(summary = "通过部门ID查询用户部门关系列表")
|
||||||
|
@Parameter(name = "deptId", description = "部门编号", example = "1", required = true)
|
||||||
|
CommonResult<List<UserDeptRespDTO>> getUserDeptListByDeptId(@RequestParam("deptId") Long deptId);
|
||||||
|
|
||||||
|
@DeleteMapping(PREFIX + "/delete-by-user-id")
|
||||||
|
@Operation(summary = "通过用户ID删除用户部门关系")
|
||||||
|
@Parameter(name = "userId", description = "用户编号", example = "1", required = true)
|
||||||
|
CommonResult<Boolean> deleteUserDeptByUserId(@RequestParam("userId") Long userId);
|
||||||
|
|
||||||
|
@DeleteMapping(PREFIX + "/delete-by-dept-id")
|
||||||
|
@Operation(summary = "通过部门ID删除用户部门关系")
|
||||||
|
@Parameter(name = "deptId", description = "部门编号", example = "1", required = true)
|
||||||
|
CommonResult<Boolean> deleteUserDeptByDeptId(@RequestParam("deptId") Long deptId);
|
||||||
|
|
||||||
|
// ========== 数据同步专用接口 ==========
|
||||||
|
|
||||||
|
@PostMapping(PREFIX + "/sync")
|
||||||
|
@Operation(summary = "同步用户部门关系")
|
||||||
|
CommonResult<Boolean> syncUserDept(@RequestBody UserDeptSaveReqDTO syncReqDTO);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.zt.plat.module.system.api.userdept.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户部门关系 Response DTO
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@Schema(description = "RPC 服务 - 用户部门关系 Response DTO")
|
||||||
|
@Data
|
||||||
|
public class UserDeptRespDTO {
|
||||||
|
|
||||||
|
@Schema(description = "关系编号", example = "1024")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "用户编号", example = "1")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Schema(description = "部门编号", example = "100")
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
@Schema(description = "备注", example = "主部门")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.zt.plat.module.system.api.userdept.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户部门关系创建/修改 Request DTO
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@Schema(description = "RPC 服务 - 用户部门关系创建/修改 Request DTO")
|
||||||
|
@Data
|
||||||
|
public class UserDeptSaveReqDTO {
|
||||||
|
|
||||||
|
@Schema(description = "关系编号", example = "1024")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "用户编号", example = "1", required = true)
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Schema(description = "部门编号", example = "100", required = true)
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
@Schema(description = "备注", example = "主部门")
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.zt.plat.module.system.api.userpost;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.module.system.api.userpost.dto.UserPostRespDTO;
|
||||||
|
import com.zt.plat.module.system.api.userpost.dto.UserPostSaveReqDTO;
|
||||||
|
import com.zt.plat.module.system.enums.ApiConstants;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户-岗位关系 Feign API
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@FeignClient(name = ApiConstants.NAME)
|
||||||
|
@Tag(name = "RPC 服务 - 用户岗位关系")
|
||||||
|
public interface UserPostApi {
|
||||||
|
|
||||||
|
String PREFIX = ApiConstants.PREFIX + "/user-post";
|
||||||
|
|
||||||
|
@PostMapping(PREFIX + "/create")
|
||||||
|
@Operation(summary = "新增用户岗位关系")
|
||||||
|
CommonResult<Long> createUserPost(@RequestBody UserPostSaveReqDTO reqVO);
|
||||||
|
|
||||||
|
@PutMapping(PREFIX + "/update")
|
||||||
|
@Operation(summary = "修改用户岗位关系")
|
||||||
|
CommonResult<Boolean> updateUserPost(@RequestBody UserPostSaveReqDTO reqVO);
|
||||||
|
|
||||||
|
@DeleteMapping(PREFIX + "/delete")
|
||||||
|
@Operation(summary = "删除用户岗位关系")
|
||||||
|
@Parameter(name = "id", description = "关系编号", example = "1", required = true)
|
||||||
|
CommonResult<Boolean> deleteUserPost(@RequestParam("id") Long id);
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/get")
|
||||||
|
@Operation(summary = "通过ID查询用户岗位关系")
|
||||||
|
@Parameter(name = "id", description = "关系编号", example = "1", required = true)
|
||||||
|
CommonResult<UserPostRespDTO> getUserPost(@RequestParam("id") Long id);
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/list-by-user-id")
|
||||||
|
@Operation(summary = "通过用户ID查询用户岗位关系列表")
|
||||||
|
@Parameter(name = "userId", description = "用户编号", example = "1", required = true)
|
||||||
|
CommonResult<List<UserPostRespDTO>> getUserPostListByUserId(@RequestParam("userId") Long userId);
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/list-by-post-id")
|
||||||
|
@Operation(summary = "通过岗位ID查询用户岗位关系列表")
|
||||||
|
@Parameter(name = "postId", description = "岗位编号", example = "1", required = true)
|
||||||
|
CommonResult<List<UserPostRespDTO>> getUserPostListByPostId(@RequestParam("postId") Long postId);
|
||||||
|
|
||||||
|
@DeleteMapping(PREFIX + "/delete-by-user-id")
|
||||||
|
@Operation(summary = "通过用户ID删除用户岗位关系")
|
||||||
|
@Parameter(name = "userId", description = "用户编号", example = "1", required = true)
|
||||||
|
CommonResult<Boolean> deleteUserPostByUserId(@RequestParam("userId") Long userId);
|
||||||
|
|
||||||
|
@DeleteMapping(PREFIX + "/delete-by-post-id")
|
||||||
|
@Operation(summary = "通过岗位ID删除用户岗位关系")
|
||||||
|
@Parameter(name = "postId", description = "岗位编号", example = "1", required = true)
|
||||||
|
CommonResult<Boolean> deleteUserPostByPostId(@RequestParam("postId") Long postId);
|
||||||
|
|
||||||
|
// ========== 数据同步专用接口 ==========
|
||||||
|
|
||||||
|
@PostMapping(PREFIX + "/sync")
|
||||||
|
@Operation(summary = "同步用户岗位关系")
|
||||||
|
CommonResult<Boolean> syncUserPost(@RequestBody UserPostSaveReqDTO syncReqDTO);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.zt.plat.module.system.api.userpost.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户岗位关系 Response DTO
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@Schema(description = "RPC 服务 - 用户岗位关系 Response DTO")
|
||||||
|
@Data
|
||||||
|
public class UserPostRespDTO {
|
||||||
|
|
||||||
|
@Schema(description = "关系编号", example = "1024")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "用户编号", example = "1")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Schema(description = "岗位编号", example = "100")
|
||||||
|
private Long postId;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.zt.plat.module.system.api.userpost.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户岗位关系创建/修改 Request DTO
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@Schema(description = "RPC 服务 - 用户岗位关系创建/修改 Request DTO")
|
||||||
|
@Data
|
||||||
|
public class UserPostSaveReqDTO {
|
||||||
|
|
||||||
|
@Schema(description = "关系编号", example = "1024")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "用户编号", example = "1", required = true)
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Schema(description = "岗位编号", example = "100", required = true)
|
||||||
|
private Long postId;
|
||||||
|
}
|
||||||
@@ -127,8 +127,8 @@ public interface ErrorCodeConstants {
|
|||||||
ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1_002_014_000, "验证码不存在");
|
ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1_002_014_000, "验证码不存在");
|
||||||
ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1_002_014_001, "验证码已过期");
|
ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1_002_014_001, "验证码已过期");
|
||||||
ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用");
|
ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用");
|
||||||
ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量");
|
ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量:{}次");
|
||||||
ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频繁");
|
ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频繁,请于{}分钟后再试");
|
||||||
|
|
||||||
// ========== 租户信息 1-002-015-000 ==========
|
// ========== 租户信息 1-002-015-000 ==========
|
||||||
ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1_002_015_000, "租户不存在");
|
ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1_002_015_000, "租户不存在");
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package com.zt.plat.module.system.enums.permission;
|
package com.zt.plat.module.system.enums.permission;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
import com.zt.plat.framework.common.core.ArrayValuable;
|
import com.zt.plat.framework.common.core.ArrayValuable;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据范围枚举类
|
* 数据范围枚举类
|
||||||
@@ -33,6 +35,26 @@ public enum DataScopeEnum implements ArrayValuable<Integer> {
|
|||||||
|
|
||||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(DataScopeEnum::getScope).toArray(Integer[]::new);
|
public static final Integer[] ARRAYS = Arrays.stream(values()).map(DataScopeEnum::getScope).toArray(Integer[]::new);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jackson 序列化时输出整数 code,兼容旧客户端
|
||||||
|
*/
|
||||||
|
@JsonValue
|
||||||
|
public Integer getScope() {
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DataScopeEnum findByScope(Integer scope) {
|
||||||
|
if (scope == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (DataScopeEnum value : values()) {
|
||||||
|
if (Objects.equals(value.scope, scope)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer[] array() {
|
public Integer[] array() {
|
||||||
return ARRAYS;
|
return ARRAYS;
|
||||||
|
|||||||
@@ -137,7 +137,12 @@
|
|||||||
<groupId>com.zt.plat</groupId>
|
<groupId>com.zt.plat</groupId>
|
||||||
<artifactId>zt-spring-boot-starter-monitor</artifactId>
|
<artifactId>zt-spring-boot-starter-monitor</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Seata 达梦数据库补丁,必须最先引入以覆盖 seata-all 中的类 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.zt.plat</groupId>
|
||||||
|
<artifactId>zt-spring-boot-starter-seata-dm</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
<!-- 分布式事务 -->
|
<!-- 分布式事务 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.seata</groupId>
|
<groupId>org.apache.seata</groupId>
|
||||||
@@ -190,6 +195,10 @@
|
|||||||
<groupId>com.zt.plat</groupId>
|
<groupId>com.zt.plat</groupId>
|
||||||
<artifactId>zt-spring-boot-starter-mq</artifactId>
|
<artifactId>zt-spring-boot-starter-mq</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
package com.zt.plat.module.system.api.databus;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.module.databus.api.data.DatabusUserDeptData;
|
||||||
|
import com.zt.plat.module.databus.api.dto.CursorPageReqDTO;
|
||||||
|
import com.zt.plat.module.databus.api.dto.CursorPageResult;
|
||||||
|
import com.zt.plat.module.databus.api.provider.DatabusUserDeptProviderApi;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.userdept.UserDeptDO;
|
||||||
|
import com.zt.plat.module.system.dal.mysql.userdept.UserDeptMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Databus 用户-部门关系数据提供者 API 实现
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@Validated
|
||||||
|
public class DatabusUserDeptProviderApiImpl implements DatabusUserDeptProviderApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserDeptMapper userDeptMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<CursorPageResult<DatabusUserDeptData>> getPageByCursor(CursorPageReqDTO reqDTO) {
|
||||||
|
// 多查一条判断是否有更多数据
|
||||||
|
int limit = reqDTO.getBatchSize() != null ? reqDTO.getBatchSize() : 100;
|
||||||
|
|
||||||
|
// 查询用户部门关系
|
||||||
|
List<UserDeptDO> list = userDeptMapper.selectPageByCursorWithUserSource(
|
||||||
|
reqDTO.isFirstPage() ? null : reqDTO.getCursorTime(),
|
||||||
|
reqDTO.isFirstPage() ? null : reqDTO.getCursorId(),
|
||||||
|
reqDTO.getTenantId(),
|
||||||
|
limit + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
// 判断是否有更多
|
||||||
|
boolean hasMore = list.size() > limit;
|
||||||
|
if (hasMore) {
|
||||||
|
list = list.subList(0, limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CollUtil.isEmpty(list)) {
|
||||||
|
return success(CursorPageResult.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换为同步数据
|
||||||
|
List<DatabusUserDeptData> dataList = list.stream()
|
||||||
|
.map(this::convertToData)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 获取最后一条数据的游标
|
||||||
|
UserDeptDO last = list.get(list.size() - 1);
|
||||||
|
|
||||||
|
// 首次查询时返<E697B6><E8BF94><EFBFBD>总数
|
||||||
|
Long total = null;
|
||||||
|
if (reqDTO.isFirstPage()) {
|
||||||
|
// 统计用户部门关系
|
||||||
|
total = userDeptMapper.countWithUserSource(reqDTO.getTenantId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return success(CursorPageResult.of(
|
||||||
|
dataList,
|
||||||
|
last.getCreateTime(),
|
||||||
|
last.getId(),
|
||||||
|
hasMore,
|
||||||
|
total
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<DatabusUserDeptData> getById(Long id) {
|
||||||
|
UserDeptDO userDept = userDeptMapper.selectById(id);
|
||||||
|
if (userDept == null) {
|
||||||
|
return success(null);
|
||||||
|
}
|
||||||
|
return success(convertToData(userDept));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<List<DatabusUserDeptData>> getListByIds(List<Long> ids) {
|
||||||
|
if (CollUtil.isEmpty(ids)) {
|
||||||
|
return success(Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<UserDeptDO> list = userDeptMapper.selectBatchIds(ids);
|
||||||
|
if (CollUtil.isEmpty(list)) {
|
||||||
|
return success(Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
return success(list.stream()
|
||||||
|
.map(this::convertToData)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Long> count(Long tenantId) {
|
||||||
|
// 统计用户部门关系
|
||||||
|
return success(userDeptMapper.countWithUserSource(tenantId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 UserDeptDO 转换为 DatabusUserDeptData
|
||||||
|
*/
|
||||||
|
private DatabusUserDeptData convertToData(UserDeptDO userDept) {
|
||||||
|
return DatabusUserDeptData.builder()
|
||||||
|
.id(userDept.getId())
|
||||||
|
.userId(userDept.getUserId())
|
||||||
|
.deptId(userDept.getDeptId())
|
||||||
|
.tenantId(userDept.getTenantId())
|
||||||
|
.remark(userDept.getRemark())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
package com.zt.plat.module.system.api.databus;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.module.databus.api.data.DatabusUserPostData;
|
||||||
|
import com.zt.plat.module.databus.api.dto.CursorPageReqDTO;
|
||||||
|
import com.zt.plat.module.databus.api.dto.CursorPageResult;
|
||||||
|
import com.zt.plat.module.databus.api.provider.DatabusUserPostProviderApi;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.dept.UserPostDO;
|
||||||
|
import com.zt.plat.module.system.dal.mysql.dept.UserPostMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Databus 用户-岗位关系数据提供者 API 实现
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@Validated
|
||||||
|
public class DatabusUserPostProviderApiImpl implements DatabusUserPostProviderApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserPostMapper userPostMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<CursorPageResult<DatabusUserPostData>> getPageByCursor(CursorPageReqDTO reqDTO) {
|
||||||
|
// 多查一条判断是否有更多数据
|
||||||
|
int limit = reqDTO.getBatchSize() != null ? reqDTO.getBatchSize() : 100;
|
||||||
|
|
||||||
|
// ⚠️ 使用关联查询,只查询 userSource = 2 的用户的岗位关系
|
||||||
|
List<UserPostDO> list = userPostMapper.selectPageByCursorWithUserSource(
|
||||||
|
reqDTO.isFirstPage() ? null : reqDTO.getCursorTime(),
|
||||||
|
reqDTO.isFirstPage() ? null : reqDTO.getCursorId(),
|
||||||
|
reqDTO.getTenantId(),
|
||||||
|
limit + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
// 判断是否有更多
|
||||||
|
boolean hasMore = list.size() > limit;
|
||||||
|
if (hasMore) {
|
||||||
|
list = list.subList(0, limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CollUtil.isEmpty(list)) {
|
||||||
|
return success(CursorPageResult.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换为同步数据
|
||||||
|
List<DatabusUserPostData> dataList = list.stream()
|
||||||
|
.map(this::convertToData)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 获取最后一条数据的游标
|
||||||
|
UserPostDO last = list.get(list.size() - 1);
|
||||||
|
|
||||||
|
// 首次查询时返回总数
|
||||||
|
Long total = null;
|
||||||
|
if (reqDTO.isFirstPage()) {
|
||||||
|
// ⚠️ 只统计 userSource = 2 的用户的岗位关系
|
||||||
|
total = userPostMapper.countWithUserSource(reqDTO.getTenantId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return success(CursorPageResult.of(
|
||||||
|
dataList,
|
||||||
|
last.getCreateTime(),
|
||||||
|
last.getId(),
|
||||||
|
hasMore,
|
||||||
|
total
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<DatabusUserPostData> getById(Long id) {
|
||||||
|
UserPostDO userPost = userPostMapper.selectById(id);
|
||||||
|
if (userPost == null) {
|
||||||
|
return success(null);
|
||||||
|
}
|
||||||
|
return success(convertToData(userPost));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<List<DatabusUserPostData>> getListByIds(List<Long> ids) {
|
||||||
|
if (CollUtil.isEmpty(ids)) {
|
||||||
|
return success(Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<UserPostDO> list = userPostMapper.selectBatchIds(ids);
|
||||||
|
if (CollUtil.isEmpty(list)) {
|
||||||
|
return success(Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
return success(list.stream()
|
||||||
|
.map(this::convertToData)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Long> count(Long tenantId) {
|
||||||
|
// ⚠️ 只统计 userSource = 2 的用户的岗位关系
|
||||||
|
return success(userPostMapper.countWithUserSource(tenantId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 UserPostDO 转换为 DatabusUserPostData
|
||||||
|
*/
|
||||||
|
private DatabusUserPostData convertToData(UserPostDO userPost) {
|
||||||
|
return DatabusUserPostData.builder()
|
||||||
|
.id(userPost.getId())
|
||||||
|
.userId(userPost.getUserId())
|
||||||
|
.postId(userPost.getPostId())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -54,6 +54,9 @@ public class DatabusUserProviderApiImpl implements DatabusUserProviderApi {
|
|||||||
// 构建游标查询条件
|
// 构建游标查询条件
|
||||||
LambdaQueryWrapper<AdminUserDO> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<AdminUserDO> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
|
||||||
|
// ⚠️ 只同步 userSource = 2 的用户
|
||||||
|
queryWrapper.eq(AdminUserDO::getUserSource, 2);
|
||||||
|
|
||||||
// 游标条件:create_time > cursorTime OR (create_time = cursorTime AND id > cursorId)
|
// 游标条件:create_time > cursorTime OR (create_time = cursorTime AND id > cursorId)
|
||||||
if (!reqDTO.isFirstPage()) {
|
if (!reqDTO.isFirstPage()) {
|
||||||
queryWrapper.and(w -> w
|
queryWrapper.and(w -> w
|
||||||
@@ -100,6 +103,8 @@ public class DatabusUserProviderApiImpl implements DatabusUserProviderApi {
|
|||||||
Long total = null;
|
Long total = null;
|
||||||
if (reqDTO.isFirstPage()) {
|
if (reqDTO.isFirstPage()) {
|
||||||
LambdaQueryWrapper<AdminUserDO> countWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<AdminUserDO> countWrapper = new LambdaQueryWrapper<>();
|
||||||
|
// ⚠️ 只统计 userSource = 2 的用户
|
||||||
|
countWrapper.eq(AdminUserDO::getUserSource, 2);
|
||||||
if (reqDTO.getTenantId() != null) {
|
if (reqDTO.getTenantId() != null) {
|
||||||
countWrapper.eq(AdminUserDO::getTenantId, reqDTO.getTenantId());
|
countWrapper.eq(AdminUserDO::getTenantId, reqDTO.getTenantId());
|
||||||
}
|
}
|
||||||
@@ -143,6 +148,8 @@ public class DatabusUserProviderApiImpl implements DatabusUserProviderApi {
|
|||||||
@Override
|
@Override
|
||||||
public CommonResult<Long> count(Long tenantId) {
|
public CommonResult<Long> count(Long tenantId) {
|
||||||
LambdaQueryWrapper<AdminUserDO> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<AdminUserDO> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
// ⚠️ 只统计 userSource = 2 的用户
|
||||||
|
queryWrapper.eq(AdminUserDO::getUserSource, 2);
|
||||||
if (tenantId != null) {
|
if (tenantId != null) {
|
||||||
queryWrapper.eq(AdminUserDO::getTenantId, tenantId);
|
queryWrapper.eq(AdminUserDO::getTenantId, tenantId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,4 +107,13 @@ public class DeptApiImpl implements DeptApi {
|
|||||||
return success(BeanUtils.toBean(companyDeptInfos, CompanyDeptInfoRespDTO.class));
|
return success(BeanUtils.toBean(companyDeptInfos, CompanyDeptInfoRespDTO.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== 数据同步专用接口 ==========
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> syncDept(DeptSaveReqDTO syncReqDTO) {
|
||||||
|
DeptSaveReqVO reqVO = BeanUtils.toBean(syncReqDTO, DeptSaveReqVO.class);
|
||||||
|
deptService.syncDept(reqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.zt.plat.module.system.controller.admin.dept.vo.post.PostSaveReqVO;
|
|||||||
import com.zt.plat.module.system.dal.dataobject.dept.PostDO;
|
import com.zt.plat.module.system.dal.dataobject.dept.PostDO;
|
||||||
import com.zt.plat.module.system.service.dept.PostService;
|
import com.zt.plat.module.system.service.dept.PostService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@@ -20,6 +21,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||||
@Validated
|
@Validated
|
||||||
public class PostApiImpl implements PostApi {
|
public class PostApiImpl implements PostApi {
|
||||||
@@ -49,6 +51,7 @@ public class PostApiImpl implements PostApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<PostRespDTO> getPost(Long id) {
|
public CommonResult<PostRespDTO> getPost(Long id) {
|
||||||
|
log.error("cccccccc"+id);
|
||||||
PostDO post = postService.getPost(id);
|
PostDO post = postService.getPost(id);
|
||||||
return success(BeanUtils.toBean(post, PostRespDTO.class));
|
return success(BeanUtils.toBean(post, PostRespDTO.class));
|
||||||
}
|
}
|
||||||
@@ -72,4 +75,11 @@ public class PostApiImpl implements PostApi {
|
|||||||
return success(BeanUtils.toBean(list, PostRespDTO.class));
|
return success(BeanUtils.toBean(list, PostRespDTO.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> syncPost(PostSaveReqDTO syncReqDTO) {
|
||||||
|
PostSaveReqVO reqVO = BeanUtils.toBean(syncReqDTO, PostSaveReqVO.class);
|
||||||
|
postService.syncPost(reqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.zt.plat.framework.common.util.object.BeanUtils;
|
|||||||
import com.zt.plat.module.system.api.permission.dto.*;
|
import com.zt.plat.module.system.api.permission.dto.*;
|
||||||
import com.zt.plat.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleDataScopeReqVO;
|
import com.zt.plat.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleDataScopeReqVO;
|
||||||
import com.zt.plat.module.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO;
|
import com.zt.plat.module.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO;
|
||||||
|
import com.zt.plat.module.system.enums.permission.DataScopeEnum;
|
||||||
import com.zt.plat.module.system.service.permission.PermissionService;
|
import com.zt.plat.module.system.service.permission.PermissionService;
|
||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@@ -65,6 +66,11 @@ public class PermissionApiImpl implements PermissionApi {
|
|||||||
return success(permissionService.getUserRoleIdListByUserIdFromCache(userId));
|
return success(permissionService.getUserRoleIdListByUserIdFromCache(userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<DataScopeEnum> getUserDataPermissionLevel(Long userId) {
|
||||||
|
return success(permissionService.getUserDataPermissionLevel(userId));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<Boolean> hasAnyPermissions(Long userId, String... permissions) {
|
public CommonResult<Boolean> hasAnyPermissions(Long userId, String... permissions) {
|
||||||
return success(permissionService.hasAnyPermissions(userId, permissions));
|
return success(permissionService.hasAnyPermissions(userId, permissions));
|
||||||
|
|||||||
@@ -149,4 +149,11 @@ public class AdminUserApiImpl implements AdminUserApi {
|
|||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> syncUser(AdminUserSaveReqDTO syncReqDTO) {
|
||||||
|
UserSaveReqVO reqVO = BeanUtils.toBean(syncReqDTO, UserSaveReqVO.class);
|
||||||
|
userService.syncUser(reqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package com.zt.plat.module.system.api.userdept;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||||
|
import com.zt.plat.module.system.api.userdept.dto.UserDeptRespDTO;
|
||||||
|
import com.zt.plat.module.system.api.userdept.dto.UserDeptSaveReqDTO;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.userdept.UserDeptDO;
|
||||||
|
import com.zt.plat.module.system.service.userdept.UserDeptService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户-部门关系 API 实现类
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@Validated
|
||||||
|
public class UserDeptApiImpl implements UserDeptApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserDeptService userDeptService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Long> createUserDept(UserDeptSaveReqDTO reqVO) {
|
||||||
|
UserDeptDO userDept = BeanUtils.toBean(reqVO, UserDeptDO.class);
|
||||||
|
Long id = userDeptService.createUserDept(userDept);
|
||||||
|
return success(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> updateUserDept(UserDeptSaveReqDTO reqVO) {
|
||||||
|
UserDeptDO userDept = BeanUtils.toBean(reqVO, UserDeptDO.class);
|
||||||
|
userDeptService.updateUserDept(userDept);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> deleteUserDept(Long id) {
|
||||||
|
userDeptService.deleteUserDept(id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<UserDeptRespDTO> getUserDept(Long id) {
|
||||||
|
UserDeptDO userDept = userDeptService.getUserDept(id);
|
||||||
|
return success(BeanUtils.toBean(userDept, UserDeptRespDTO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<List<UserDeptRespDTO>> getUserDeptListByUserId(Long userId) {
|
||||||
|
List<UserDeptDO> list = userDeptService.getValidUserDeptListByUserIds(List.of(userId));
|
||||||
|
return success(BeanUtils.toBean(list, UserDeptRespDTO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<List<UserDeptRespDTO>> getUserDeptListByDeptId(Long deptId) {
|
||||||
|
List<UserDeptDO> list = userDeptService.getValidUserDeptListByDeptIds(List.of(deptId));
|
||||||
|
return success(BeanUtils.toBean(list, UserDeptRespDTO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> deleteUserDeptByUserId(Long userId) {
|
||||||
|
userDeptService.deleteUserDeptByUserId(userId);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> deleteUserDeptByDeptId(Long deptId) {
|
||||||
|
// 需要实现此方法,暂时返回成功
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> syncUserDept(UserDeptSaveReqDTO syncReqDTO) {
|
||||||
|
UserDeptDO userDept = BeanUtils.toBean(syncReqDTO, UserDeptDO.class);
|
||||||
|
userDeptService.syncUserDept(userDept);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package com.zt.plat.module.system.api.userpost;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||||
|
import com.zt.plat.module.system.api.userpost.dto.UserPostRespDTO;
|
||||||
|
import com.zt.plat.module.system.api.userpost.dto.UserPostSaveReqDTO;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.dept.UserPostDO;
|
||||||
|
import com.zt.plat.module.system.dal.mysql.dept.UserPostMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户-岗位关系 API 实现类
|
||||||
|
*
|
||||||
|
* @author ZT
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@Validated
|
||||||
|
public class UserPostApiImpl implements UserPostApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserPostMapper userPostMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Long> createUserPost(UserPostSaveReqDTO reqVO) {
|
||||||
|
UserPostDO userPost = BeanUtils.toBean(reqVO, UserPostDO.class);
|
||||||
|
userPostMapper.insert(userPost);
|
||||||
|
return success(userPost.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> updateUserPost(UserPostSaveReqDTO reqVO) {
|
||||||
|
UserPostDO userPost = BeanUtils.toBean(reqVO, UserPostDO.class);
|
||||||
|
userPostMapper.updateById(userPost);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> deleteUserPost(Long id) {
|
||||||
|
userPostMapper.deleteById(id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<UserPostRespDTO> getUserPost(Long id) {
|
||||||
|
UserPostDO userPost = userPostMapper.selectById(id);
|
||||||
|
return success(BeanUtils.toBean(userPost, UserPostRespDTO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<List<UserPostRespDTO>> getUserPostListByUserId(Long userId) {
|
||||||
|
List<UserPostDO> list = userPostMapper.selectListByUserId(userId);
|
||||||
|
return success(BeanUtils.toBean(list, UserPostRespDTO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<List<UserPostRespDTO>> getUserPostListByPostId(Long postId) {
|
||||||
|
List<UserPostDO> list = userPostMapper.selectListByPostIds(List.of(postId));
|
||||||
|
return success(BeanUtils.toBean(list, UserPostRespDTO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> deleteUserPostByUserId(Long userId) {
|
||||||
|
userPostMapper.deleteByUserId(userId);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> deleteUserPostByPostId(Long postId) {
|
||||||
|
userPostMapper.delete(UserPostDO::getPostId, postId);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public CommonResult<Boolean> syncUserPost(UserPostSaveReqDTO syncReqDTO) {
|
||||||
|
if (syncReqDTO.getId() == null) {
|
||||||
|
return success(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
UserPostDO existing = userPostMapper.selectById(syncReqDTO.getId());
|
||||||
|
UserPostDO userPost = BeanUtils.toBean(syncReqDTO, UserPostDO.class);
|
||||||
|
|
||||||
|
if (existing != null) {
|
||||||
|
userPostMapper.updateById(userPost);
|
||||||
|
log.info("[syncUserPost] 用户岗位关系同步-更新成功, id={}, userId={}, postId={}",
|
||||||
|
userPost.getId(), userPost.getUserId(), userPost.getPostId());
|
||||||
|
} else {
|
||||||
|
userPostMapper.insert(userPost);
|
||||||
|
log.info("[syncUserPost] 用户岗位关系同步-创建成功, id={}, userId={}, postId={}",
|
||||||
|
userPost.getId(), userPost.getUserId(), userPost.getPostId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -143,6 +143,7 @@ public class AuthController {
|
|||||||
|
|
||||||
@PostMapping("/sms-login")
|
@PostMapping("/sms-login")
|
||||||
@PermitAll
|
@PermitAll
|
||||||
|
@TenantIgnore
|
||||||
@Operation(summary = "使用短信验证码登录")
|
@Operation(summary = "使用短信验证码登录")
|
||||||
public CommonResult<AuthLoginRespVO> smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) {
|
public CommonResult<AuthLoginRespVO> smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) {
|
||||||
return success(authService.smsLogin(reqVO));
|
return success(authService.smsLogin(reqVO));
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
package com.zt.plat.module.system.controller.admin.dept;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.framework.common.pojo.PageResult;
|
||||||
|
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||||
|
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.EspPageReqVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.EspSaveRespVo;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.dept.DeptDO;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.dept.DeptPushMsgDO;
|
||||||
|
import com.zt.plat.module.system.service.dept.DeptService;
|
||||||
|
import com.zt.plat.module.system.service.dept.IEspService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
@Tag(name = "管理后台 - 部门推送消息")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/system/esp")
|
||||||
|
@Validated
|
||||||
|
public class EspController
|
||||||
|
{
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IEspService espService;
|
||||||
|
@Resource
|
||||||
|
private DeptService deptService;
|
||||||
|
|
||||||
|
@PostMapping("/create")
|
||||||
|
@Operation(summary = "创建部门推送消息")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:esp-external-code:create')")
|
||||||
|
public CommonResult<Long> create(@Valid @RequestBody EspSaveRespVo createReqVO) {
|
||||||
|
Long id = espService.createDeptPushMsg(createReqVO);
|
||||||
|
return success(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
@Operation(summary = "修改部门推送消息")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:esp-external-code:update')")
|
||||||
|
public CommonResult<Boolean> update(@Valid @RequestBody EspSaveRespVo updateReqVO) {
|
||||||
|
espService.updateDeptPushMsg(updateReqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete")
|
||||||
|
@Operation(summary = "删除部门推送消息")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:esp-external-code:delete')")
|
||||||
|
public CommonResult<Boolean> delete(@RequestParam("id") Long id) {
|
||||||
|
espService.deleteDeptPushMsg(id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@Operation(summary = "获取部门推送消息详情")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:esp-external-code:query')")
|
||||||
|
public CommonResult<EspSaveRespVo> get(@RequestParam("id") Long id) {
|
||||||
|
DeptPushMsgDO entity = espService.getDeptPushMsgDetails(id);
|
||||||
|
EspSaveRespVo respVO = BeanUtils.toBean(entity, EspSaveRespVo.class);
|
||||||
|
fillDeptInfo(List.of(respVO));
|
||||||
|
return success(respVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/page")
|
||||||
|
@Operation(summary = "分页查询部门推送消息")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:esp-external-code:query')")
|
||||||
|
public CommonResult<PageResult<EspSaveRespVo>> page(@Valid EspPageReqVO reqVO) {
|
||||||
|
PageResult<DeptPushMsgDO> pageResult = espService.getDeptExternalCodePage(reqVO);
|
||||||
|
PageResult<EspSaveRespVo> result = BeanUtils.toBean(pageResult, EspSaveRespVo.class);
|
||||||
|
fillDeptInfo(result.getList());
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/list-by-dept")
|
||||||
|
@Operation(summary = "根据部门部门推送消息")
|
||||||
|
@Parameter(name = "deptId", description = "部门编号", required = true, example = "1024")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:esp-external-code:query')")
|
||||||
|
public CommonResult<List<EspSaveRespVo>> listByDept(@RequestParam("deptId") Long deptId) {
|
||||||
|
List<DeptPushMsgDO> list = espService.getPushMsgByDeptId(deptId);
|
||||||
|
List<EspSaveRespVo> respList = BeanUtils.toBean(list, EspSaveRespVo.class);
|
||||||
|
fillDeptInfo(respList);
|
||||||
|
return success(respList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void fillDeptInfo(List<EspSaveRespVo> list) {
|
||||||
|
if (list == null || list.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<Long> deptIds = list.stream()
|
||||||
|
.map(EspSaveRespVo::getDeptId)
|
||||||
|
.collect(Collectors.toCollection(HashSet::new));
|
||||||
|
if (deptIds == null || deptIds.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<Long, DeptDO> deptMap = deptService.getDeptList(deptIds).stream()
|
||||||
|
.collect(Collectors.toMap(DeptDO::getId, dept -> dept, (left, right) -> left));
|
||||||
|
list.forEach(item -> {
|
||||||
|
DeptDO dept = deptMap.get(item.getDeptId());
|
||||||
|
if (dept != null) {
|
||||||
|
item.setDeptName(dept.getName());
|
||||||
|
item.setDeptCode(dept.getCode());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.PageParam;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 部门外部组织编码映射分页 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class EspPageReqVO extends PageParam {
|
||||||
|
|
||||||
|
@Schema(description = "部门编号", example = "1024")
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
@Schema(description = "外部系统标识", example = "ERP")
|
||||||
|
private String systemCode;
|
||||||
|
|
||||||
|
@Schema(description = "外部组织编码", example = "100200")
|
||||||
|
private String externalDeptCode;
|
||||||
|
|
||||||
|
@Schema(description = "状态", example = "0")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 部门外消息推送创建/修改 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class EspSaveRespVo extends DeptExternalCodeBaseVO {
|
||||||
|
|
||||||
|
@Schema(description = "映射编号", example = "1024")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "所属部门名称", example = "技术部")
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
@Schema(description = "所属部门编码", example = "DEPT_001")
|
||||||
|
private String deptCode;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@Schema(description = "最后更新时间")
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package com.zt.plat.module.system.dal.dataobject.dept;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.zt.plat.framework.common.enums.CommonStatusEnum;
|
||||||
|
import com.zt.plat.framework.tenant.core.db.TenantBaseDO;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门推送消息 DO
|
||||||
|
*/
|
||||||
|
@TableName("system_dept_push_msg")
|
||||||
|
@KeySequence("system_dept_push_msg_seq")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class DeptPushMsgDO extends TenantBaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键编号
|
||||||
|
*/
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本系统部门 ID
|
||||||
|
*/
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统标识
|
||||||
|
*/
|
||||||
|
private String systemCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统组织编码
|
||||||
|
*/
|
||||||
|
private String externalDeptCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统组织名称
|
||||||
|
*/
|
||||||
|
private String externalDeptName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射状态
|
||||||
|
* 枚举 {@link CommonStatusEnum}
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -127,12 +127,17 @@ public interface DeptMapper extends BaseMapperX<DeptDO> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据部门编码查询部门
|
* 根据部门编码查询部门
|
||||||
|
* <p>
|
||||||
|
* 注意:如果存在多条相同编码的记录,只返回第一条
|
||||||
*
|
*
|
||||||
* @param code 部门编码
|
* @param code 部门编码
|
||||||
* @return 部门信息
|
* @return 部门信息
|
||||||
*/
|
*/
|
||||||
default DeptDO selectByCode(String code) {
|
default DeptDO selectByCode(String code) {
|
||||||
return selectOne(DeptDO::getCode, code);
|
List<DeptDO> list = selectList(new LambdaQueryWrapperX<DeptDO>()
|
||||||
|
.eq(DeptDO::getCode, code)
|
||||||
|
.last("LIMIT 1"));
|
||||||
|
return CollUtil.isNotEmpty(list) ? list.get(0) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package com.zt.plat.module.system.dal.mysql.dept;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.PageResult;
|
||||||
|
import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.EspPageReqVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.dept.vo.depexternalcode.EspSaveRespVo;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.dept.DeptPushMsgDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import java.util.List;
|
||||||
|
/**
|
||||||
|
* 部门推送消息接口Mapper
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface EspMapper extends BaseMapperX<DeptPushMsgDO> {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询
|
||||||
|
* @param reqVO 消息推送VO
|
||||||
|
* @return PageResult
|
||||||
|
*/
|
||||||
|
default PageResult<DeptPushMsgDO> selectPage(EspPageReqVO reqVO) {
|
||||||
|
return selectPage(reqVO, new LambdaQueryWrapperX<DeptPushMsgDO>()
|
||||||
|
.eqIfPresent(DeptPushMsgDO::getDeptId,reqVO.getDeptId())
|
||||||
|
.eqIfPresent(DeptPushMsgDO::getSystemCode, reqVO.getSystemCode())
|
||||||
|
.likeIfPresent(DeptPushMsgDO::getExternalDeptCode, reqVO.getExternalDeptCode())
|
||||||
|
.eqIfPresent(DeptPushMsgDO::getStatus, reqVO.getStatus())
|
||||||
|
.orderByDesc(DeptPushMsgDO::getId));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default DeptPushMsgDO selectBySystemCodeAndDeptId(String systemCode, Long deptId) {
|
||||||
|
return selectOne(new LambdaQueryWrapperX<DeptPushMsgDO>()
|
||||||
|
.eq(DeptPushMsgDO::getSystemCode, systemCode)
|
||||||
|
.eq(DeptPushMsgDO::getDeptId, deptId));
|
||||||
|
}
|
||||||
|
|
||||||
|
default DeptPushMsgDO selectBySystemCodeAndExternalCode(String systemCode, String externalDeptCode) {
|
||||||
|
return selectOne(new LambdaQueryWrapperX<DeptPushMsgDO>()
|
||||||
|
.eq(DeptPushMsgDO::getSystemCode, systemCode)
|
||||||
|
.eq(DeptPushMsgDO::getExternalDeptCode, externalDeptCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<DeptPushMsgDO> selectListByDeptId(Long deptId) {
|
||||||
|
return selectList(DeptPushMsgDO::getDeptId, deptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
default int deleteByDeptId(Long deptId) {
|
||||||
|
return delete(DeptPushMsgDO::getDeptId, deptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<DeptPushMsgDO> selectListBySystemCode(String systemCode) {
|
||||||
|
return selectList(DeptPushMsgDO::getSystemCode, systemCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,7 +5,10 @@ import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
|
|||||||
import com.zt.plat.module.system.dal.dataobject.dept.UserPostDO;
|
import com.zt.plat.module.system.dal.dataobject.dept.UserPostDO;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -29,4 +32,44 @@ public interface UserPostMapper extends BaseMapperX<UserPostDO> {
|
|||||||
default void deleteByUserId(Long userId) {
|
default void deleteByUserId(Long userId) {
|
||||||
delete(Wrappers.lambdaUpdate(UserPostDO.class).eq(UserPostDO::getUserId, userId));
|
delete(Wrappers.lambdaUpdate(UserPostDO.class).eq(UserPostDO::getUserId, userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 游标分页查询用户-岗位关系(只查询 userSource = 2 的用户)
|
||||||
|
* @param cursorTime 游标时间
|
||||||
|
* @param cursorId 游标ID
|
||||||
|
* @param tenantId 租户ID(可选)
|
||||||
|
* @param limit 限制数量
|
||||||
|
* @return 用户岗位关系列表
|
||||||
|
*/
|
||||||
|
@Select("<script>" +
|
||||||
|
"SELECT up.* FROM system_user_post up " +
|
||||||
|
"INNER JOIN system_users u ON up.user_id = u.id " +
|
||||||
|
"WHERE u.user_source = 2 " +
|
||||||
|
"AND up.deleted = 0 " +
|
||||||
|
"<if test='tenantId != null'> AND up.tenant_id = #{tenantId} </if>" +
|
||||||
|
"<if test='cursorTime != null'>" +
|
||||||
|
" AND (up.create_time > #{cursorTime} " +
|
||||||
|
" OR (up.create_time = #{cursorTime} AND up.id > #{cursorId}))" +
|
||||||
|
"</if>" +
|
||||||
|
"ORDER BY up.create_time ASC, up.id ASC " +
|
||||||
|
"LIMIT #{limit}" +
|
||||||
|
"</script>")
|
||||||
|
List<UserPostDO> selectPageByCursorWithUserSource(@Param("cursorTime") LocalDateTime cursorTime,
|
||||||
|
@Param("cursorId") Long cursorId,
|
||||||
|
@Param("tenantId") Long tenantId,
|
||||||
|
@Param("limit") Integer limit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计用户-岗位关系数量(只统计 userSource = 2 的用户)
|
||||||
|
* @param tenantId 租户ID(可选)
|
||||||
|
* @return 数量
|
||||||
|
*/
|
||||||
|
@Select("<script>" +
|
||||||
|
"SELECT COUNT(*) FROM system_user_post up " +
|
||||||
|
"INNER JOIN system_users u ON up.user_id = u.id " +
|
||||||
|
"WHERE u.user_source = 2 " +
|
||||||
|
"AND up.deleted = 0 " +
|
||||||
|
"<if test='tenantId != null'> AND up.tenant_id = #{tenantId} </if>" +
|
||||||
|
"</script>")
|
||||||
|
Long countWithUserSource(@Param("tenantId") Long tenantId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
|
|||||||
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
|
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import com.zt.plat.module.system.dal.dataobject.userdept.UserDeptDO;
|
import com.zt.plat.module.system.dal.dataobject.userdept.UserDeptDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -45,4 +48,44 @@ public interface UserDeptMapper extends BaseMapperX<UserDeptDO> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 游标分页查询用户-部门关系(只查询 userSource = 2 的用户)
|
||||||
|
* @param cursorTime 游标时间
|
||||||
|
* @param cursorId 游标ID
|
||||||
|
* @param tenantId 租户ID(可选)
|
||||||
|
* @param limit 限制数量
|
||||||
|
* @return 用户部门关系列表
|
||||||
|
*/
|
||||||
|
@Select("<script>" +
|
||||||
|
"SELECT ud.* FROM system_user_dept ud " +
|
||||||
|
"INNER JOIN system_users u ON ud.user_id = u.id " +
|
||||||
|
"WHERE u.user_source = 2 " +
|
||||||
|
"AND ud.deleted = 0 " +
|
||||||
|
"<if test='tenantId != null'> AND ud.tenant_id = #{tenantId} </if>" +
|
||||||
|
"<if test='cursorTime != null'>" +
|
||||||
|
" AND (ud.create_time > #{cursorTime} " +
|
||||||
|
" OR (ud.create_time = #{cursorTime} AND ud.id > #{cursorId}))" +
|
||||||
|
"</if>" +
|
||||||
|
"ORDER BY ud.create_time ASC, ud.id ASC " +
|
||||||
|
"LIMIT #{limit}" +
|
||||||
|
"</script>")
|
||||||
|
List<UserDeptDO> selectPageByCursorWithUserSource(@Param("cursorTime") LocalDateTime cursorTime,
|
||||||
|
@Param("cursorId") Long cursorId,
|
||||||
|
@Param("tenantId") Long tenantId,
|
||||||
|
@Param("limit") Integer limit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计用户-部门关系数量(只统计 userSource = 2 的用户)
|
||||||
|
* @param tenantId 租户ID(可选)
|
||||||
|
* @return 数量
|
||||||
|
*/
|
||||||
|
@Select("<script>" +
|
||||||
|
"SELECT COUNT(*) FROM system_user_dept ud " +
|
||||||
|
"INNER JOIN system_users u ON ud.user_id = u.id " +
|
||||||
|
"WHERE u.user_source = 2 " +
|
||||||
|
"AND ud.deleted = 0 " +
|
||||||
|
"<if test='tenantId != null'> AND ud.tenant_id = #{tenantId} </if>" +
|
||||||
|
"</script>")
|
||||||
|
Long countWithUserSource(@Param("tenantId") Long tenantId);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ import java.util.List;
|
|||||||
@Data
|
@Data
|
||||||
public class SmsSendMessage {
|
public class SmsSendMessage {
|
||||||
|
|
||||||
public static final String TOPIC = "SMS_SEND_TOPIC"; // 重点:需要增加消息对应的 Topic
|
public static final String TOPIC = "SMS_SEND_TOPIC_TEST"; // 重点:需要增加消息对应的 Topic
|
||||||
/**
|
/**
|
||||||
* 短信日志编号
|
* 短信日志编号
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -174,4 +174,15 @@ public interface DeptService {
|
|||||||
* @return 部门列表
|
* @return 部门列表
|
||||||
*/
|
*/
|
||||||
List<DeptDO> searchDeptTree(String keyword);
|
List<DeptDO> searchDeptTree(String keyword);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回填缺失的部门编码(不触发事件)。
|
||||||
|
*
|
||||||
|
* @param deptIds 需要回填的部门 ID 列表
|
||||||
|
*/
|
||||||
|
void backfillMissingCodesWithoutEvent(Collection<Long> deptIds);
|
||||||
|
|
||||||
|
// ========== 数据同步专用接口 ==========
|
||||||
|
|
||||||
|
void syncDept(DeptSaveReqVO syncReqVO);
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user