This commit is contained in:
zlwu committed 2026-10-17 11:46:53 +08:00
1 parent 48dcf991dc
commit be2226e4ca
100 files changed
+61340 -40975

No files matched your search

@@ -0,0 +1,46 @@
-- =============================================================================
-- 弱密码刷新说明:111111 → Zkxw@123
-- 日期:2026-10-16
-- =============================================================================
--
-- 重要:sys_user.password 存储 bcrypt 哈希(每次盐随机),
-- 不能用下列语句命中弱密码用户:
-- WHERE password = '111111' -- 无效
-- WHERE password LIKE '%111111%' -- 无效
--
-- 推荐:用 Python 脚本,并通过变量指定目标库(勿依赖本机默认 .env 误连生产)。
--
-- cd backend && source venv/bin/activate
--
-- # 方式 A:完整 URL
-- python scripts/reset_weak_password_111111.py \
-- --database-url 'mysql+pymysql://USER:PASS@HOST:3306/DBNAME' --dry-run
--
-- # 方式 B:分项变量
-- python scripts/reset_weak_password_111111.py \
-- --db-host HOST --db-port 3306 --db-user USER --db-password 'PASS' --db-name DBNAME --dry-run
--
-- # 方式 C:指定环境文件
-- python scripts/reset_weak_password_111111.py --env-file ./.env.test --dry-run
--
-- # 正式写入:去掉 --dry-run
--
-- 脚本行为:校验 del_flag=0 的用户口令是否为明文 111111(含停用账号),
-- 命中则更新为 Zkxw@123 的新 bcrypt 哈希。
--
-- =============================================================================
-- 以下仅为「已知单个用户 id」时的手工 UPDATE 模板。
-- 哈希由本机生成示例(明文 Zkxw@123,bcrypt cost 12),部署前请用 Python 重新生成:
-- python -c "from app.core.security import get_password_hash; print(get_password_hash('Zkxw@123'))"
-- =============================================================================
-- 示例哈希(仅供手工单用户更新参考;批量请用脚本):
-- $2b$12$ULvPCr6g9IUmI8K7nlGU5emk7hupaAz4WgFdEoQBe935Wh1pVYKCK
-- UPDATE sys_user
-- SET password = '$2b$12$ULvPCr6g9IUmI8K7nlGU5emk7hupaAz4WgFdEoQBe935Wh1pVYKCK',
-- update_time = NOW()
-- WHERE id = '<user_id>'
-- AND del_flag = 0;
-- 执行前请备份 sys_user;执行后通知用户使用新密码并建议登录后自行修改。
@@ -0,0 +1,161 @@
-- =============================================================================
-- 打开全部 OA 审批应用的「审批人去重」,并强制重新发布(2026-10-16)
-- MySQL 5.7
--
-- 行为:
-- 1. 每个已有「最新已发布」版本的应用:无论 approverDedup 当前是否已为 true,
-- 一律复制为新的 published 行(表单、流程不变,开关强制 true),
-- 旧的 is_latest_published 改为 0。
-- 已在途实例仍指向旧 version id;新发起走新版本。
-- 2. 全部未删除草稿:就地把 approverDedup 设为 true(不把草稿未完成改动一并发布)。
-- 3. 从未发布过的应用:把版本号最大的那条草稿标为已发布,并打开开关。
--
-- 注意:本脚本会为每个已发布应用再升一版;短时间内重复执行会连续升版。
-- =============================================================================
DROP PROCEDURE IF EXISTS sp_oa_enable_approver_dedup;
DELIMITER $$
CREATE PROCEDURE sp_oa_enable_approver_dedup()
BEGIN
DECLARE v_done INT DEFAULT 0;
DECLARE v_src_id VARCHAR(64);
DECLARE v_app_id VARCHAR(64);
DECLARE v_tenant VARCHAR(64);
DECLARE v_next_no INT;
DECLARE v_new_id VARCHAR(64);
DECLARE v_advanced TEXT;
-- 强制:所有当前最新已发布版本都重新发布一版
DECLARE cur CURSOR FOR
SELECT id, app_id, tenant_no
FROM oa_app_version
WHERE del_flag = 0
AND is_latest_published = '1';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = 1;
OPEN cur;
read_loop: LOOP
FETCH cur INTO v_src_id, v_app_id, v_tenant;
IF v_done = 1 THEN
LEAVE read_loop;
END IF;
SELECT IFNULL(MAX(version_no), 0) + 1
INTO v_next_no
FROM oa_app_version
WHERE app_id = v_app_id
AND tenant_no = v_tenant;
SET v_new_id = UPPER(REPLACE(UUID(), '-', ''));
SELECT CAST(
JSON_SET(
CASE
WHEN advanced_settings_json IS NULL
OR advanced_settings_json = ''
OR JSON_VALID(advanced_settings_json) = 0
THEN CAST('{}' AS JSON)
ELSE CAST(advanced_settings_json AS JSON)
END,
'$.approverDedup',
CAST('true' AS JSON)
) AS CHAR
)
INTO v_advanced
FROM oa_app_version
WHERE id = v_src_id;
INSERT INTO oa_app_version (
id, app_id, version_no, status, is_latest_published,
form_schema_json, flow_tree_json, advanced_settings_json,
tenant_no, order_num, remark,
create_by, create_dept_id, create_time,
update_by, update_time, del_flag
)
SELECT
v_new_id, app_id, v_next_no, 'published', '1',
form_schema_json, flow_tree_json, v_advanced,
tenant_no, order_num, remark,
create_by, create_dept_id, NOW(),
'sql-approver-dedup', NOW(), 0
FROM oa_app_version
WHERE id = v_src_id;
UPDATE oa_app_version
SET is_latest_published = '0',
update_by = 'sql-approver-dedup',
update_time = NOW()
WHERE id = v_src_id;
END LOOP;
CLOSE cur;
-- 草稿只改开关,避免把未完成的表单/流程改动一起发布
UPDATE oa_app_version
SET advanced_settings_json = CAST(
JSON_SET(
CASE
WHEN advanced_settings_json IS NULL
OR advanced_settings_json = ''
OR JSON_VALID(advanced_settings_json) = 0
THEN CAST('{}' AS JSON)
ELSE CAST(advanced_settings_json AS JSON)
END,
'$.approverDedup',
CAST('true' AS JSON)
) AS CHAR
),
update_by = 'sql-approver-dedup',
update_time = NOW()
WHERE del_flag = 0
AND status = 'draft';
-- 从未发布:提升当前最大版本号草稿
UPDATE oa_app_version d
INNER JOIN (
SELECT app_id, tenant_no, MAX(version_no) AS version_no
FROM oa_app_version
WHERE del_flag = 0
AND status = 'draft'
GROUP BY app_id, tenant_no
) latest_draft
ON latest_draft.app_id = d.app_id
AND latest_draft.tenant_no = d.tenant_no
AND latest_draft.version_no = d.version_no
LEFT JOIN (
SELECT app_id, tenant_no
FROM oa_app_version
WHERE del_flag = 0
AND is_latest_published = '1'
GROUP BY app_id, tenant_no
) published
ON published.app_id = d.app_id
AND published.tenant_no = d.tenant_no
SET d.status = 'published',
d.is_latest_published = '1',
d.update_by = 'sql-approver-dedup',
d.update_time = NOW()
WHERE d.del_flag = 0
AND d.status = 'draft'
AND published.app_id IS NULL;
END$$
DELIMITER ;
CALL sp_oa_enable_approver_dedup();
DROP PROCEDURE IF EXISTS sp_oa_enable_approver_dedup;
-- 核对:最新已发布应由本脚本生成,且开关为 true
SELECT app_id,
tenant_no,
version_no,
status,
is_latest_published,
update_by,
JSON_UNQUOTE(JSON_EXTRACT(advanced_settings_json, '$.approverDedup')) AS approver_dedup
FROM oa_app_version
WHERE del_flag = 0
AND is_latest_published = '1'
ORDER BY tenant_no, app_id;
@@ -0,0 +1,322 @@
-- 采集协议单 / 科研捐赠:状态变更历史表(追加写,同类型不覆盖)
-- 对齐 docs/superpowers/plans/2026-10-17-protocol-status-change-history.md
CREATE TABLE IF NOT EXISTS biz_protocol_status_change (
id VARCHAR(64) NOT NULL COMMENT '主键ID',
collection_protocol_id VARCHAR(64) NOT NULL COMMENT '采集协议单ID',
change_type VARCHAR(32) NOT NULL COMMENT '变更类型 activate/expire/void/to_research',
from_status VARCHAR(16) DEFAULT NULL COMMENT '变更前状态码',
to_status VARCHAR(16) NOT NULL COMMENT '变更后状态码',
change_time DATETIME NOT NULL COMMENT '业务变更时间',
change_desc VARCHAR(512) DEFAULT NULL COMMENT '变更描述',
void_type VARCHAR(32) DEFAULT NULL COMMENT '作废类型(字典 xyzflx)',
operator_user_id VARCHAR(64) DEFAULT NULL COMMENT '操作人用户ID',
tenant_no VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
order_num INT DEFAULT NULL COMMENT '排序号',
remark VARCHAR(512) DEFAULT NULL COMMENT '备注',
create_by VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
create_dept_id VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
create_time DATETIME NOT NULL COMMENT '创建时间',
update_by VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
update_time DATETIME NOT NULL COMMENT '更新时间',
del_flag SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (id),
KEY idx_bpsc_protocol_time (tenant_no, collection_protocol_id, del_flag, change_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采集协议单状态变更记录';
CREATE TABLE IF NOT EXISTS biz_donation_status_change (
id VARCHAR(64) NOT NULL COMMENT '主键ID',
research_donation_id VARCHAR(64) NOT NULL COMMENT '科研捐赠单ID',
change_type VARCHAR(32) NOT NULL COMMENT '变更类型 activate/expire/void/to_storage',
from_status VARCHAR(16) DEFAULT NULL COMMENT '变更前状态码',
to_status VARCHAR(16) NOT NULL COMMENT '变更后状态码',
change_time DATETIME NOT NULL COMMENT '业务变更时间',
change_desc VARCHAR(512) DEFAULT NULL COMMENT '变更描述',
void_type VARCHAR(32) DEFAULT NULL COMMENT '作废类型(字典 xyzflx)',
operator_user_id VARCHAR(64) DEFAULT NULL COMMENT '操作人用户ID',
tenant_no VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
order_num INT DEFAULT NULL COMMENT '排序号',
remark VARCHAR(512) DEFAULT NULL COMMENT '备注',
create_by VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
create_dept_id VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
create_time DATETIME NOT NULL COMMENT '创建时间',
update_by VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
update_time DATETIME NOT NULL COMMENT '更新时间',
del_flag SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (id),
KEY idx_bdsc_donation_time (tenant_no, research_donation_id, del_flag, change_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='科研捐赠状态变更记录';
-- 回填:主表已有快照各插 1 条(幂等:同协议同 change_type 尚无历史时)
INSERT INTO biz_protocol_status_change (
id, collection_protocol_id, change_type, from_status, to_status,
change_time, change_desc, void_type, operator_user_id,
tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
UPPER(MD5(CONCAT(p.id, '|activate'))),
p.id,
'activate',
NULL,
'sxz',
p.effective_time,
p.effective_desc,
NULL,
p.update_by,
p.tenant_no,
0,
NULL,
p.update_by,
'',
IFNULL(p.effective_time, NOW()),
p.update_by,
IFNULL(p.effective_time, NOW()),
0
FROM biz_collection_protocol p
WHERE p.del_flag = 0
AND p.effective_time IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM biz_protocol_status_change c
WHERE c.collection_protocol_id = p.id
AND c.change_type = 'activate'
AND c.del_flag = 0
);
INSERT INTO biz_protocol_status_change (
id, collection_protocol_id, change_type, from_status, to_status,
change_time, change_desc, void_type, operator_user_id,
tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
UPPER(MD5(CONCAT(p.id, '|expire'))),
p.id,
'expire',
NULL,
'ygq',
p.expire_time,
p.expire_desc,
NULL,
p.update_by,
p.tenant_no,
0,
NULL,
p.update_by,
'',
IFNULL(p.expire_time, NOW()),
p.update_by,
IFNULL(p.expire_time, NOW()),
0
FROM biz_collection_protocol p
WHERE p.del_flag = 0
AND p.expire_time IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM biz_protocol_status_change c
WHERE c.collection_protocol_id = p.id
AND c.change_type = 'expire'
AND c.del_flag = 0
);
INSERT INTO biz_protocol_status_change (
id, collection_protocol_id, change_type, from_status, to_status,
change_time, change_desc, void_type, operator_user_id,
tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
UPPER(MD5(CONCAT(p.id, '|void'))),
p.id,
'void',
NULL,
'yzf',
p.void_time,
p.void_desc,
p.void_type,
p.update_by,
p.tenant_no,
0,
NULL,
p.update_by,
'',
IFNULL(p.void_time, NOW()),
p.update_by,
IFNULL(p.void_time, NOW()),
0
FROM biz_collection_protocol p
WHERE p.del_flag = 0
AND p.void_time IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM biz_protocol_status_change c
WHERE c.collection_protocol_id = p.id
AND c.change_type = 'void'
AND c.del_flag = 0
);
INSERT INTO biz_protocol_status_change (
id, collection_protocol_id, change_type, from_status, to_status,
change_time, change_desc, void_type, operator_user_id,
tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
UPPER(MD5(CONCAT(p.id, '|to_research'))),
p.id,
'to_research',
NULL,
'zky',
p.to_research_time,
p.to_research_desc,
NULL,
p.update_by,
p.tenant_no,
0,
NULL,
p.update_by,
'',
IFNULL(p.to_research_time, NOW()),
p.update_by,
IFNULL(p.to_research_time, NOW()),
0
FROM biz_collection_protocol p
WHERE p.del_flag = 0
AND p.to_research_time IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM biz_protocol_status_change c
WHERE c.collection_protocol_id = p.id
AND c.change_type = 'to_research'
AND c.del_flag = 0
);
INSERT INTO biz_donation_status_change (
id, research_donation_id, change_type, from_status, to_status,
change_time, change_desc, void_type, operator_user_id,
tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
UPPER(MD5(CONCAT(d.id, '|activate'))),
d.id,
'activate',
NULL,
'sxz',
d.effective_time,
d.effective_desc,
NULL,
d.update_by,
d.tenant_no,
0,
NULL,
d.update_by,
'',
IFNULL(d.effective_time, NOW()),
d.update_by,
IFNULL(d.effective_time, NOW()),
0
FROM biz_research_donation d
WHERE d.del_flag = 0
AND d.effective_time IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM biz_donation_status_change c
WHERE c.research_donation_id = d.id
AND c.change_type = 'activate'
AND c.del_flag = 0
);
INSERT INTO biz_donation_status_change (
id, research_donation_id, change_type, from_status, to_status,
change_time, change_desc, void_type, operator_user_id,
tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
UPPER(MD5(CONCAT(d.id, '|expire'))),
d.id,
'expire',
NULL,
'ygq',
d.expire_time,
d.expire_desc,
NULL,
d.update_by,
d.tenant_no,
0,
NULL,
d.update_by,
'',
IFNULL(d.expire_time, NOW()),
d.update_by,
IFNULL(d.expire_time, NOW()),
0
FROM biz_research_donation d
WHERE d.del_flag = 0
AND d.expire_time IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM biz_donation_status_change c
WHERE c.research_donation_id = d.id
AND c.change_type = 'expire'
AND c.del_flag = 0
);
INSERT INTO biz_donation_status_change (
id, research_donation_id, change_type, from_status, to_status,
change_time, change_desc, void_type, operator_user_id,
tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
UPPER(MD5(CONCAT(d.id, '|void'))),
d.id,
'void',
NULL,
'yzf',
d.void_time,
d.void_desc,
d.void_type,
d.update_by,
d.tenant_no,
0,
NULL,
d.update_by,
'',
IFNULL(d.void_time, NOW()),
d.update_by,
IFNULL(d.void_time, NOW()),
0
FROM biz_research_donation d
WHERE d.del_flag = 0
AND d.void_time IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM biz_donation_status_change c
WHERE c.research_donation_id = d.id
AND c.change_type = 'void'
AND c.del_flag = 0
);
INSERT INTO biz_donation_status_change (
id, research_donation_id, change_type, from_status, to_status,
change_time, change_desc, void_type, operator_user_id,
tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
UPPER(MD5(CONCAT(d.id, '|to_storage'))),
d.id,
'to_storage',
NULL,
'zckc',
d.to_storage_time,
d.to_storage_desc,
NULL,
d.update_by,
d.tenant_no,
0,
NULL,
d.update_by,
'',
IFNULL(d.to_storage_time, NOW()),
d.update_by,
IFNULL(d.to_storage_time, NOW()),
0
FROM biz_research_donation d
WHERE d.del_flag = 0
AND d.to_storage_time IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM biz_donation_status_change c
WHERE c.research_donation_id = d.id
AND c.change_type = 'to_storage'
AND c.del_flag = 0
);