Merge remote-tracking branch 'origin/main'

This commit is contained in:
dk
2026-04-07 11:14:54 +08:00
30 changed files with 1000 additions and 28 deletions

View File

@@ -7,12 +7,12 @@ spring:
username: # Nacos 账号
password: # Nacos 密码
discovery: # 【配置中心】配置项
namespace: dev # 命名空间。这里使用 dev 开发环境
namespace: 1e0fcd92-49b4-4cda-b531-828c7d36fef5 # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
metadata:
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
config: # 【注册中心】配置项
namespace: dev # 命名空间。这里使用 dev 开发环境
namespace: 1e0fcd92-49b4-4cda-b531-828c7d36fef5 # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
#################### 数据库相关配置 ####################

View File

@@ -6,12 +6,12 @@ spring:
username: # Nacos 账号
password: # Nacos 密码
discovery: # 【配置中心】配置项
namespace: dev # 命名空间。这里使用 dev 开发环境
namespace: 1e0fcd92-49b4-4cda-b531-828c7d36fef5 # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
metadata:
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
config: # 【注册中心】配置项
namespace: dev # 命名空间。这里使用 dev 开发环境
namespace: 1e0fcd92-49b4-4cda-b531-828c7d36fef5 # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
#################### 数据库相关配置 ####################
@@ -63,7 +63,7 @@ spring:
data:
redis:
host: 127.0.0.1 # 地址
port: 6379 # 端口
port: 16379 # 端口
database: 1 # 数据库索引
# password: njcnpqs # 密码,建议生产环境开启

View File

@@ -122,6 +122,10 @@ rdms:
websocket:
enable: true # 是否开启 WebSocket
path: /system/ws # WebSocket 路径
api-encrypt:
enable: true # 启用密码相关接口的请求解密能力
header: X-Api-Encrypt # 请求加密标记头
algorithm: RSA # 密码相关接口的请求体采用 RSA 非对称加密
request-key: 'MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC/aShtWjlpINa+ZZkgp4sbt2jA4tPCN1YjDLv5SZMHDd7q8lbkE0SOudbuSKp5P3tVCPZXowyZom5+l56AAIYCaG5OcbzeRUtB6JcvmuU9SZ008zw7z2BIzeIzMtJSGf6u8BocVeMo27bGyyh1ifUXbpKVU7V7DBLzYADAQ9Jqi0vsqrxDGDu+Zm3LpFwSOnv85pgC0d+9re57CIYynXVmTLAo+V5DedPsceNCAByRs1kUyFMwyoPNbmgjcpKbewD6laxR9GtnFR/bCzfnz8Up7ANtuHCPe7vfU1teU75ZR+/cW9t2GS1e1T/XkULRv5PH5gchSGQ1NHO4imIbv5dzAgMBAAECggEACTjSS051BKUh44N2mLWpxJiWEfD7vdg3rLGg3tZWIJlg+5XYbN2myG+YtNtIZ1YRJZwsbjV7Vm2WgD/i0Yz05+nLIrllHZpeEVtY6WC/ma/RxKrRZJpNq8RLmSbiLjV1aU1FHMdgjefkCvjfxqXyaoIXyt0BGeAPi6087AZ4fUyKVYgPyGr53RnD8+4nCDaRhZYMCv6zpb+YVF3llZZNhvK7+hDLZX0WhUgIAzStzFsPZhDfJxW8MQFB4FNtmnJ4kpInkgIAROlfVvKIwRKwoCH+sveGjYdlZR/wTYt6HQoKudG9Qx2IssUcVGFwAsCiWM+81rfBDd5pMUwzyGQ9OQKBgQDHOp7Eio4M6LaPO1Uz6Ozlp28evWBVPaU+wk50p5SQl//pF0VgDkmrrt3Wu9IppBL6VObIzjOsZJrEVHXheA/1qqOVYm/m6nel1EUAqbIqxREtw+GJPoKp3Ql1CxK6pvm/KxOhJvCDIUNCZ4in+rvsCvquF784iIbQ33ED3hWi2wKBgQD19DbAL1Y6/XHXX17t6yZJVsIijmSOo5tjeNHouOSP5emgc8i2ESaW4WPIzkgi7EJ2aertgUkwIOpunYvMWYfn6zrYNaSuvCCZF+6oIiYPPXEVZJTnzGA/KsJtHeH6xtiGuettw6RnPxXvNZibJhfLdOqQvZmRDRTXh/MiRuelSQKBgQC154IbNd7pTnmRYb0zvlK+hRfiW0rfyX9dRBBaVsBBHWedrY+8Wo9NYEZQ0ADd4F8rjeWCJzPrDZh59hwDl5oK1pixxsUhc6d3E89FAawZfQFoZddBdn/bFGSUJ14camTR9UTg+SrUr8Q3l0yhA0AeDxA/cJM5zP47LCiGPXpHzQKBgQDV00sGKiE9h7nBFBjjntvaRqLgiArEN1iQUimruZJ7x9YkuIR2RNLXuXuWyD/OnLfrWonzkcKfJP6qzC0Nq4iMB+VQstJJVyS/9B537bhI55G4l4kdPIEwaWw+kQw1iUoVVu1mr//uAtp+7ImP2L43E54Z17v6bvT/rCGkWyBogQKBgQC6pqnciYteAE5KmWnPM9LWoEorSBPCzbWCVwuja7NbVoADUPvAnUeDgvKs8KpWvL+X3eRGSZXOBqjBMsdDPBnQzr5yZCI3Mv6Svg9RxBfuWw1mF1w2GAwK1r7+6ZDwxFqRUiVUACRRJ8S1kBa+CvNWm7UFi/7V1D4UDyKKmBU6Sw=='
debug: false

View File

@@ -0,0 +1,127 @@
-- permission-v2 stage 1 schema for MySQL 8.0
-- execution target: existing rdms system schema
-- execution mode: manual
--
-- purpose:
-- 1. add target-model columns
-- 2. create visibility relation tables
-- 3. keep legacy fields temporarily for subsequent code migration
--
-- note:
-- 1. run this script before stage 2/3 code changes
-- 2. do not drop leader_user_id / post_ids / data_scope in this stage
START TRANSACTION;
ALTER TABLE system_dept
ADD COLUMN org_type VARCHAR(20) NOT NULL DEFAULT 'dept' COMMENT '组织节点类型company/dept/direction/team' AFTER parent_id,
ADD COLUMN path VARCHAR(1024) CHARACTER SET ascii NOT NULL DEFAULT '/' COMMENT '组织物化路径,格式如 /1/2/3/' AFTER org_type,
ADD COLUMN level INT NOT NULL DEFAULT 1 COMMENT '组织层级,根节点为 1' AFTER path,
ADD COLUMN code VARCHAR(64) NULL COMMENT '组织编码' AFTER level;
ALTER TABLE system_users
ADD COLUMN position_id BIGINT NULL COMMENT '主岗位ID' AFTER dept_id,
ADD COLUMN resigned_at DATETIME NULL COMMENT '离职时间' AFTER position_id;
ALTER TABLE system_post
ADD COLUMN post_type VARCHAR(20) NULL COMMENT '岗位类型management/technical/business' AFTER code,
ADD COLUMN level_rank INT NULL COMMENT '岗位等级排序,越大级别越高' AFTER post_type;
ALTER TABLE system_dept
ADD KEY idx_system_dept_parent_id (parent_id),
ADD KEY idx_system_dept_org_type (org_type),
ADD KEY idx_system_dept_path (path(191)),
ADD UNIQUE KEY uk_system_dept_code (code);
ALTER TABLE system_users
ADD KEY idx_system_users_dept_id (dept_id),
ADD KEY idx_system_users_position_id (position_id);
ALTER TABLE system_post
ADD KEY idx_system_post_type (post_type),
ADD KEY idx_system_post_level_rank (level_rank);
CREATE TABLE system_org_leader_relation (
id BIGINT NOT NULL COMMENT '主键ID',
dept_id BIGINT NOT NULL COMMENT '组织节点ID',
user_id BIGINT NOT NULL COMMENT '负责人用户ID',
effective_from DATETIME NULL COMMENT '生效开始时间,空表示立即长期生效',
effective_until DATETIME NULL COMMENT '生效结束时间,空表示长期有效',
remark VARCHAR(500) NULL COMMENT '备注',
creator VARCHAR(64) NULL DEFAULT '' COMMENT '创建者',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updater VARCHAR(64) NULL DEFAULT '' COMMENT '更新者',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
deleted BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (id),
KEY idx_org_leader_user (user_id, deleted, effective_from, effective_until),
KEY idx_org_leader_dept (dept_id, deleted, effective_from, effective_until),
UNIQUE KEY uk_org_leader_once (dept_id, user_id, effective_from)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='组织负责人关系表';
CREATE TABLE system_user_management_relation (
id BIGINT NOT NULL COMMENT '主键ID',
manager_user_id BIGINT NOT NULL COMMENT '管理者用户ID',
subordinate_user_id BIGINT NOT NULL COMMENT '被管理用户ID',
effective_from DATETIME NULL COMMENT '生效开始时间,空表示立即长期生效',
effective_until DATETIME NULL COMMENT '生效结束时间,空表示长期有效',
remark VARCHAR(500) NULL COMMENT '备注',
creator VARCHAR(64) NULL DEFAULT '' COMMENT '创建者',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updater VARCHAR(64) NULL DEFAULT '' COMMENT '更新者',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
deleted BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (id),
KEY idx_mgr_user (manager_user_id, deleted, effective_from, effective_until),
KEY idx_sub_user (subordinate_user_id, deleted, effective_from, effective_until),
UNIQUE KEY uk_mgr_sub_once (manager_user_id, subordinate_user_id, effective_from)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户直接管理关系表';
CREATE TABLE system_user_visibility_config (
id BIGINT NOT NULL COMMENT '主键ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
visibility_type VARCHAR(20) NOT NULL COMMENT '可见范围类型all/directions/projects',
visible_direction_ids JSON NULL COMMENT '补充可见方向ID集合',
visible_project_ids JSON NULL COMMENT '补充可见项目ID集合',
remark VARCHAR(500) NULL COMMENT '备注',
creator VARCHAR(64) NULL DEFAULT '' COMMENT '创建者',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updater VARCHAR(64) NULL DEFAULT '' COMMENT '更新者',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
deleted BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (id),
UNIQUE KEY uk_visibility_user (user_id),
KEY idx_visibility_type (visibility_type),
CONSTRAINT chk_visibility_type CHECK (visibility_type IN ('all', 'directions', 'projects'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户补充可见范围配置表';
CREATE TABLE system_project_member (
id BIGINT NOT NULL COMMENT '主键ID',
project_id BIGINT NOT NULL COMMENT '项目ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
project_role VARCHAR(20) NOT NULL COMMENT '项目角色pm/product/developer/tester/viewer',
member_type VARCHAR(20) NOT NULL DEFAULT 'core' COMMENT '成员类型core/support',
joined_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '加入时间',
left_at DATETIME NULL COMMENT '退出时间,空表示仍在项目中',
remark VARCHAR(500) NULL COMMENT '备注',
creator VARCHAR(64) NULL DEFAULT '' COMMENT '创建者',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updater VARCHAR(64) NULL DEFAULT '' COMMENT '更新者',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
deleted BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
active_user_id BIGINT GENERATED ALWAYS AS (
CASE WHEN left_at IS NULL THEN user_id ELSE NULL END
) STORED,
active_pm_project_id BIGINT GENERATED ALWAYS AS (
CASE WHEN project_role = 'pm' AND left_at IS NULL THEN project_id ELSE NULL END
) STORED,
PRIMARY KEY (id),
UNIQUE KEY uk_project_active_member (project_id, active_user_id),
UNIQUE KEY uk_project_active_pm (active_pm_project_id),
KEY idx_pm_user_active (user_id, left_at),
KEY idx_pm_project_role_active (project_id, project_role, left_at),
CONSTRAINT chk_project_role CHECK (project_role IN ('pm', 'product', 'developer', 'tester', 'viewer')),
CONSTRAINT chk_member_type CHECK (member_type IN ('core', 'support'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目成员关系表';
COMMIT;

View File

@@ -0,0 +1,44 @@
-- permission-v2 stage 1 organization backfill for MySQL 8.0
-- purpose:
-- 1. initialize org_type
-- 2. backfill path and level from parent_id
--
-- assumption:
-- 1. root organization nodes satisfy parent_id = 0
-- 2. system_dept currently has no parent cycle
START TRANSACTION;
UPDATE system_dept
SET org_type = 'dept'
WHERE org_type IS NULL OR org_type = '';
WITH RECURSIVE dept_tree AS (
SELECT
id,
parent_id,
CAST(CONCAT('/', id, '/') AS CHAR(1024)) AS new_path,
1 AS new_level
FROM system_dept
WHERE parent_id = 0
UNION ALL
SELECT
child.id,
child.parent_id,
CAST(CONCAT(parent.new_path, child.id, '/') AS CHAR(1024)) AS new_path,
parent.new_level + 1 AS new_level
FROM system_dept child
INNER JOIN dept_tree parent ON child.parent_id = parent.id
)
UPDATE system_dept d
INNER JOIN dept_tree t ON d.id = t.id
SET
d.path = t.new_path,
d.level = t.new_level;
COMMIT;
-- verification:
-- SELECT id, name, parent_id, org_type, path, level FROM system_dept ORDER BY parent_id, sort, id;

View File

@@ -0,0 +1,69 @@
-- permission-v2 stage 1 seed for MySQL 8.0
-- purpose:
-- 1. ensure there is at least one root organization node for user association
-- 2. ensure there is at least one available post for user association
-- 3. bind admin user to an organization and a primary position
--
-- note:
-- 1. the reserved ids below are only for cold-start initialization
-- 2. adjust them before execution if your database already uses the same ids
START TRANSACTION;
INSERT INTO system_dept (
id, name, parent_id, sort, org_type, path, level, code, phone, email, status,
creator, create_time, updater, update_time, deleted
)
SELECT
900000000000000001, '平台根组织', 0, 0, 'company', '/900000000000000001/', 1, 'ROOT',
NULL, NULL, 0,
'system', NOW(), 'system', NOW(), b'0'
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM system_dept WHERE parent_id = 0 AND deleted = b'0'
);
INSERT INTO system_post (
id, name, code, post_type, level_rank, sort, status, remark,
creator, create_time, updater, update_time, deleted
)
SELECT
900000000000000101, '系统管理员岗', 'SYS_ADMIN_POST', 'management', 100, 0, 0, 'permission-v2 cold-start seed',
'system', NOW(), 'system', NOW(), b'0'
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM system_post WHERE deleted = b'0'
);
UPDATE system_users
SET
dept_id = COALESCE(
dept_id,
(SELECT root_dept.id
FROM (
SELECT id
FROM system_dept
WHERE parent_id = 0 AND deleted = b'0'
ORDER BY sort ASC, id ASC
LIMIT 1
) root_dept)
),
position_id = COALESCE(
position_id,
(SELECT chosen_post.id
FROM (
SELECT id
FROM system_post
WHERE deleted = b'0'
ORDER BY sort ASC, id ASC
LIMIT 1
) chosen_post)
),
update_time = NOW(),
updater = 'system'
WHERE username = 'admin';
COMMIT;
-- verification:
-- SELECT id, username, dept_id, position_id FROM system_users WHERE username = 'admin';

View File

@@ -0,0 +1,29 @@
-- permission-v2 stage 1 finalize for MySQL 8.0
-- purpose:
-- 1. verify required user-position data is complete
-- 2. convert system_users.position_id to NOT NULL
--
-- execute this script only after:
-- 1. 01/02/03 have completed successfully
-- 2. every existing user has a valid position_id
SELECT COUNT(*) AS missing_position_count
FROM system_users
WHERE position_id IS NULL;
SET @missing_position_count := (
SELECT COUNT(*) FROM system_users WHERE position_id IS NULL
);
SET @finalize_sql := IF(
@missing_position_count = 0,
'ALTER TABLE system_users MODIFY COLUMN position_id BIGINT NOT NULL COMMENT ''主岗位ID''',
'SELECT ''skip finalize: system_users.position_id still has NULL rows'' AS message'
);
PREPARE stmt FROM @finalize_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- verification:
-- SHOW CREATE TABLE system_users;

View File

@@ -702,4 +702,9 @@ SET `component` = 'view.iframe-page',
`route_props_json` = '{\"url\":\"https://cn.vuejs.org/\"}'
WHERE `id` = 900016;
INSERT INTO `system_menu` VALUES (1036, '组织负责人查询', 'system:org-leader:query', 3, 5, 103, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2026-03-25 00:00:00', 'admin', '2026-03-25 00:00:00', b'0');
INSERT INTO `system_menu` VALUES (1037, '组织负责人新增', 'system:org-leader:create', 3, 6, 103, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2026-03-25 00:00:00', 'admin', '2026-03-25 00:00:00', b'0');
INSERT INTO `system_menu` VALUES (1038, '组织负责人修改', 'system:org-leader:update', 3, 7, 103, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2026-03-25 00:00:00', 'admin', '2026-03-25 00:00:00', b'0');
INSERT INTO `system_menu` VALUES (1039, '组织负责人删除', 'system:org-leader:delete', 3, 8, 103, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2026-03-25 00:00:00', 'admin', '2026-03-25 00:00:00', b'0');
SET FOREIGN_KEY_CHECKS = 1;