feat(aihr): finalize practice growth and access boundaries

This commit is contained in:
2026-07-25 00:42:19 +08:00
parent a90f40e4d8
commit c9d2012ec1
87 changed files with 6804 additions and 2538 deletions
+53 -1
View File
@@ -32,6 +32,15 @@ CREATE TABLE IF NOT EXISTS `aihr_practice_session` (
`trainee_name` varchar(100) DEFAULT NULL COMMENT '学员名称',
`scenario_id` varchar(80) DEFAULT NULL COMMENT '场景ID',
`scenario_name` varchar(100) DEFAULT NULL COMMENT '场景名称',
`position_snapshot` varchar(80) DEFAULT NULL COMMENT '训练开始时岗位快照',
`project_type_snapshot` varchar(80) DEFAULT NULL COMMENT '训练开始时项目类型快照',
`growth_level` varchar(20) DEFAULT NULL COMMENT '训练开始时成长层级快照',
`competency_code` varchar(100) DEFAULT NULL COMMENT '训练开始时能力项快照',
`collaboration_positions` varchar(500) DEFAULT NULL COMMENT '训练开始时协同岗位快照',
`curriculum_version` varchar(30) DEFAULT NULL COMMENT '训练开始时成长目录版本快照',
`growth_confirmation_level` varchar(20) DEFAULT NULL COMMENT '主管确认可进入的训练层级',
`growth_confirmed_by` varchar(100) DEFAULT NULL COMMENT '训练层级确认主管',
`growth_confirmed_time` datetime DEFAULT NULL COMMENT '训练层级确认时间',
`mode` varchar(30) DEFAULT 'text' COMMENT '训练模式',
`total_score` int DEFAULT NULL COMMENT '总分',
`dim_task_completion` int DEFAULT NULL COMMENT '任务完成度分',
@@ -181,6 +190,17 @@ CREATE TABLE IF NOT EXISTS `aihr_practice_scenario` (
`scenario_type` varchar(50) NOT NULL COMMENT '场景类型',
`project_type` varchar(80) DEFAULT NULL COMMENT '项目类型',
`difficulty` tinyint DEFAULT 1 COMMENT '难度',
`growth_level` varchar(20) NOT NULL DEFAULT '初级' COMMENT '训练成长层级:初级/中级/高级',
`competency_code` varchar(100) NOT NULL DEFAULT '待归类' COMMENT '岗位能力项编码;由内容运营归入固定矩阵',
`collaboration_positions` varchar(500) NOT NULL DEFAULT '' COMMENT '协同岗位,使用中文顿号分隔',
`review_status` varchar(20) NOT NULL DEFAULT '草稿' COMMENT '内容状态:草稿/待业务审核/已发布/已下线',
`risk_level` varchar(20) NOT NULL DEFAULT '待评估' COMMENT '内容风险:待评估/常规/高风险',
`reviewer` varchar(100) DEFAULT NULL COMMENT '首位内容审核操作人',
`reviewer_user_id` bigint DEFAULT NULL COMMENT '首位内容审核人稳定用户ID',
`reviewed_time` datetime DEFAULT NULL COMMENT '首位内容审核时间',
`second_reviewer` varchar(100) DEFAULT NULL COMMENT '高风险内容第二位审核操作人',
`second_reviewer_user_id` bigint DEFAULT NULL COMMENT '高风险内容第二位审核人稳定用户ID',
`second_reviewed_time` datetime DEFAULT NULL COMMENT '高风险内容第二位审核时间',
`customer_persona` varchar(500) DEFAULT NULL COMMENT '业主人设',
`opening_text` varchar(500) DEFAULT NULL COMMENT '开场白',
`explicit_need` varchar(300) DEFAULT NULL COMMENT '显性诉求',
@@ -191,17 +211,21 @@ CREATE TABLE IF NOT EXISTS `aihr_practice_scenario` (
`success_criteria` varchar(500) DEFAULT NULL COMMENT '成功条件',
`strategy` varchar(500) DEFAULT NULL COMMENT '训练策略',
`goal` varchar(500) DEFAULT NULL COMMENT '训练目标',
`curriculum_version` varchar(30) NOT NULL DEFAULT '住宅五岗-v1' COMMENT '成长目录版本',
`trainee_name` varchar(100) DEFAULT '张三' COMMENT '默认学员',
`trust_start` int DEFAULT 60 COMMENT '起始信任',
`trust_end` int DEFAULT 80 COMMENT '目标信任',
`rounds_json` text DEFAULT NULL COMMENT '回合seed JSON',
`content_version` varchar(30) NOT NULL DEFAULT 'v1.0' COMMENT '内容版本',
`content_hash` char(64) DEFAULT NULL COMMENT '内容快照哈希',
`enabled` tinyint DEFAULT 1 COMMENT '是否启用',
`sort_order` int DEFAULT 0 COMMENT '排序',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_aihr_practice_scenario` (`tenant_id`, `scenario_code`),
KEY `idx_aihr_practice_scenario_filter` (`tenant_id`, `position`, `scenario_type`, `enabled`, `sort_order`)
KEY `idx_aihr_practice_scenario_filter` (`tenant_id`, `position`, `scenario_type`, `enabled`, `sort_order`),
KEY `idx_aihr_practice_scenario_curriculum` (`tenant_id`, `position`, `growth_level`, `competency_code`, `review_status`, `enabled`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='AI HR 对练场景';
CREATE TABLE IF NOT EXISTS `aihr_practice_rubric` (
@@ -398,6 +422,34 @@ ON DUPLICATE KEY UPDATE
`sort_order` = VALUES(`sort_order`),
`update_time` = VALUES(`update_time`);
-- 此文件仅用于全新开发库初始化;内置种子只是待审核素材,不能从 enabled 推断为正式发布。
-- 新增/编辑内容必须走审核状态流转后才向员工可见。
UPDATE `aihr_practice_scenario`
SET `risk_level` = CASE
WHEN CONCAT_WS('\n', `scenario_name`, `scenario_type`, `customer_persona`, `opening_text`, `explicit_need`, `hidden_need`,
`irritants`, `delights`, `sop_refs`, `success_criteria`, `strategy`, `goal`, `rounds_json`)
REGEXP '投诉|客诉|纠纷|收费|催费|费用|停车费|退款|减免|安全|事故|消防|燃气|漏电|电梯|高空|受伤|人身伤害|舆情' THEN '高风险'
WHEN `risk_level` IS NULL OR `risk_level` = '' OR `risk_level` NOT IN ('待评估', '常规', '高风险') THEN '待评估'
ELSE `risk_level`
END,
`review_status` = CASE
WHEN `review_status` IS NULL OR `review_status` = '' OR `review_status` = '草稿' THEN '待业务审核'
WHEN `review_status` = '已发布' AND (`competency_code` IS NULL OR `competency_code` = '' OR `competency_code` = '待归类'
OR `risk_level` = '待评估'
OR (`risk_level` = '高风险' AND (`reviewer_user_id` IS NULL OR `second_reviewer_user_id` IS NULL))) THEN '待业务审核'
ELSE `review_status`
END,
-- 重跑初始化脚本时不得清空“待业务审核”中的首审记录;高风险场景可能正等待第二人复核。
-- 草稿没有有效审核结论,才允许清除其历史审核字段。
`reviewer` = CASE WHEN `review_status` = '草稿' THEN NULL ELSE `reviewer` END,
`reviewer_user_id` = CASE WHEN `review_status` = '草稿' THEN NULL ELSE `reviewer_user_id` END,
`reviewed_time` = CASE WHEN `review_status` = '草稿' THEN NULL ELSE `reviewed_time` END,
`second_reviewer` = CASE WHEN `review_status` = '草稿' THEN NULL ELSE `second_reviewer` END,
`second_reviewer_user_id` = CASE WHEN `review_status` = '草稿' THEN NULL ELSE `second_reviewer_user_id` END,
`second_reviewed_time` = CASE WHEN `review_status` = '草稿' THEN NULL ELSE `second_reviewed_time` END,
`curriculum_version` = COALESCE(NULLIF(`curriculum_version`, ''), '住宅五岗-v1')
WHERE `tenant_id` = '000000';
INSERT INTO `aihr_practice_rubric`
(`tenant_id`, `rubric_code`, `scenario_code`, `rubric_name`, `version`, `enabled`, `description`, `create_time`, `update_time`)
SELECT
@@ -0,0 +1,362 @@
-- 阶段一陪练成长目录:场景的岗位/层级/能力项/审核语义及新会话快照。
-- 不创建第二套课程引擎;只扩展 aihr_practice_scenario 与 aihr_practice_session。
-- 可重复执行。历史会话不回填推测出的课程归属,避免改写历史训练事实。
SET @aihr_schema = DATABASE();
SET @growth_level_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario' AND column_name = 'growth_level'
);
SET @growth_level_ddl = IF(@growth_level_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD COLUMN growth_level varchar(20) NOT NULL DEFAULT ''初级'' COMMENT ''训练成长层级:初级/中级/高级'' AFTER difficulty',
'SELECT 1');
PREPARE aihr_growth_level_stmt FROM @growth_level_ddl;
EXECUTE aihr_growth_level_stmt;
DEALLOCATE PREPARE aihr_growth_level_stmt;
SET @competency_code_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario' AND column_name = 'competency_code'
);
SET @competency_code_ddl = IF(@competency_code_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD COLUMN competency_code varchar(100) NOT NULL DEFAULT ''待归类'' COMMENT ''岗位能力项编码;由内容运营归入固定矩阵'' AFTER growth_level',
'SELECT 1');
PREPARE aihr_competency_code_stmt FROM @competency_code_ddl;
EXECUTE aihr_competency_code_stmt;
DEALLOCATE PREPARE aihr_competency_code_stmt;
SET @collaboration_positions_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario' AND column_name = 'collaboration_positions'
);
SET @collaboration_positions_ddl = IF(@collaboration_positions_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD COLUMN collaboration_positions varchar(500) NOT NULL DEFAULT '''' COMMENT ''协同岗位,使用中文顿号分隔'' AFTER competency_code',
'SELECT 1');
PREPARE aihr_collaboration_positions_stmt FROM @collaboration_positions_ddl;
EXECUTE aihr_collaboration_positions_stmt;
DEALLOCATE PREPARE aihr_collaboration_positions_stmt;
SET @review_status_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario' AND column_name = 'review_status'
);
SET @review_status_ddl = IF(@review_status_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD COLUMN review_status varchar(20) NOT NULL DEFAULT ''草稿'' COMMENT ''内容状态:草稿/待业务审核/已发布/已下线'' AFTER collaboration_positions',
'SELECT 1');
PREPARE aihr_review_status_stmt FROM @review_status_ddl;
EXECUTE aihr_review_status_stmt;
DEALLOCATE PREPARE aihr_review_status_stmt;
SET @risk_level_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario' AND column_name = 'risk_level'
);
SET @risk_level_ddl = IF(@risk_level_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD COLUMN risk_level varchar(20) NOT NULL DEFAULT ''待评估'' COMMENT ''内容风险:待评估/常规/高风险'' AFTER review_status',
'SELECT 1');
PREPARE aihr_risk_level_stmt FROM @risk_level_ddl;
EXECUTE aihr_risk_level_stmt;
DEALLOCATE PREPARE aihr_risk_level_stmt;
SET @curriculum_version_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario' AND column_name = 'curriculum_version'
);
SET @curriculum_version_ddl = IF(@curriculum_version_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD COLUMN curriculum_version varchar(30) NOT NULL DEFAULT ''住宅五岗-v1'' COMMENT ''成长目录版本'' AFTER goal',
'SELECT 1');
PREPARE aihr_curriculum_version_stmt FROM @curriculum_version_ddl;
EXECUTE aihr_curriculum_version_stmt;
DEALLOCATE PREPARE aihr_curriculum_version_stmt;
SET @reviewer_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario' AND column_name = 'reviewer'
);
SET @reviewer_ddl = IF(@reviewer_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD COLUMN reviewer varchar(100) DEFAULT NULL COMMENT ''首位内容审核操作人'' AFTER risk_level',
'SELECT 1');
PREPARE aihr_reviewer_stmt FROM @reviewer_ddl;
EXECUTE aihr_reviewer_stmt;
DEALLOCATE PREPARE aihr_reviewer_stmt;
SET @reviewer_user_id_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario' AND column_name = 'reviewer_user_id'
);
SET @reviewer_user_id_ddl = IF(@reviewer_user_id_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD COLUMN reviewer_user_id bigint DEFAULT NULL COMMENT ''首位内容审核人稳定用户ID'' AFTER reviewer',
'SELECT 1');
PREPARE aihr_reviewer_user_id_stmt FROM @reviewer_user_id_ddl;
EXECUTE aihr_reviewer_user_id_stmt;
DEALLOCATE PREPARE aihr_reviewer_user_id_stmt;
SET @reviewed_time_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario' AND column_name = 'reviewed_time'
);
SET @reviewed_time_ddl = IF(@reviewed_time_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD COLUMN reviewed_time datetime DEFAULT NULL COMMENT ''首位内容审核时间'' AFTER reviewer_user_id',
'SELECT 1');
PREPARE aihr_reviewed_time_stmt FROM @reviewed_time_ddl;
EXECUTE aihr_reviewed_time_stmt;
DEALLOCATE PREPARE aihr_reviewed_time_stmt;
SET @second_reviewer_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario' AND column_name = 'second_reviewer'
);
SET @second_reviewer_ddl = IF(@second_reviewer_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD COLUMN second_reviewer varchar(100) DEFAULT NULL COMMENT ''高风险内容第二位审核操作人'' AFTER reviewed_time',
'SELECT 1');
PREPARE aihr_second_reviewer_stmt FROM @second_reviewer_ddl;
EXECUTE aihr_second_reviewer_stmt;
DEALLOCATE PREPARE aihr_second_reviewer_stmt;
SET @second_reviewer_user_id_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario' AND column_name = 'second_reviewer_user_id'
);
SET @second_reviewer_user_id_ddl = IF(@second_reviewer_user_id_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD COLUMN second_reviewer_user_id bigint DEFAULT NULL COMMENT ''高风险内容第二位审核人稳定用户ID'' AFTER second_reviewer',
'SELECT 1');
PREPARE aihr_second_reviewer_user_id_stmt FROM @second_reviewer_user_id_ddl;
EXECUTE aihr_second_reviewer_user_id_stmt;
DEALLOCATE PREPARE aihr_second_reviewer_user_id_stmt;
SET @second_reviewed_time_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario' AND column_name = 'second_reviewed_time'
);
SET @second_reviewed_time_ddl = IF(@second_reviewed_time_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD COLUMN second_reviewed_time datetime DEFAULT NULL COMMENT ''高风险内容第二位审核时间'' AFTER second_reviewer_user_id',
'SELECT 1');
PREPARE aihr_second_reviewed_time_stmt FROM @second_reviewed_time_ddl;
EXECUTE aihr_second_reviewed_time_stmt;
DEALLOCATE PREPARE aihr_second_reviewed_time_stmt;
-- 既有场景必须重新进入业务审核,不能从旧的 enabled 状态推断“已发布”。
-- 同时收口曾由早期脚本自动标记为已发布、但仍未归类能力项的场景。
-- 注意:这份 migration 可以重复执行。不得清空已完成首审、正在等待第二人复核的待审记录。
-- 对于本次新增稳定审核人 ID 前已发布的旧内容,一律退回待业务审核,重新建立可审计链路。
UPDATE aihr_practice_scenario
SET growth_level = CASE
WHEN @growth_level_exists = 0 OR growth_level IS NULL OR growth_level = '' THEN CASE
WHEN difficulty >= 3 THEN '高级'
WHEN difficulty = 2 THEN '中级'
ELSE '初级'
END
ELSE growth_level
END,
competency_code = CASE WHEN competency_code IS NULL OR competency_code = '' THEN '待归类' ELSE competency_code END,
collaboration_positions = COALESCE(collaboration_positions, ''),
risk_level = CASE
-- 旧表刚新增风险字段时,没有可信的既有分类,必须等待运营重新评估。
WHEN @risk_level_exists = 0 THEN '待评估'
-- 兼容早期紧凑表:只依赖其已存在的编码和目标字段;完整内容由服务端保存时逐字段复核。
WHEN CONCAT_WS('\n', scenario_code, goal)
REGEXP '投诉|客诉|纠纷|收费|催费|费用|停车费|退款|减免|安全|事故|消防|燃气|漏电|电梯|高空|受伤|人身伤害|舆情' THEN '高风险'
WHEN risk_level IS NULL OR risk_level = '' OR risk_level NOT IN ('待评估', '常规', '高风险') THEN '待评估'
ELSE risk_level
END,
review_status = CASE
WHEN @review_status_exists = 0 THEN '待业务审核'
WHEN review_status IS NULL OR review_status = '' THEN '待业务审核'
WHEN @risk_level_exists = 0 AND review_status = '已发布' THEN '待业务审核'
WHEN @reviewer_user_id_exists = 0 AND review_status = '已发布' THEN '待业务审核'
WHEN review_status = '已发布' AND (competency_code IS NULL OR competency_code = '' OR competency_code = '待归类') THEN '待业务审核'
WHEN review_status = '已发布' AND risk_level = '待评估' THEN '待业务审核'
WHEN review_status = '已发布' AND risk_level = '高风险'
AND (reviewer_user_id IS NULL OR second_reviewer_user_id IS NULL) THEN '待业务审核'
ELSE review_status
END,
curriculum_version = CASE
WHEN @curriculum_version_exists = 0 OR curriculum_version IS NULL OR curriculum_version = '' THEN '住宅五岗-v1'
ELSE curriculum_version
END;
SET @position_snapshot_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_session' AND column_name = 'position_snapshot'
);
SET @position_snapshot_ddl = IF(@position_snapshot_exists = 0,
'ALTER TABLE aihr_practice_session ADD COLUMN position_snapshot varchar(80) DEFAULT NULL COMMENT ''训练开始时岗位快照'' AFTER scenario_name',
'SELECT 1');
PREPARE aihr_position_snapshot_stmt FROM @position_snapshot_ddl;
EXECUTE aihr_position_snapshot_stmt;
DEALLOCATE PREPARE aihr_position_snapshot_stmt;
SET @project_type_snapshot_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_session' AND column_name = 'project_type_snapshot'
);
SET @project_type_snapshot_ddl = IF(@project_type_snapshot_exists = 0,
'ALTER TABLE aihr_practice_session ADD COLUMN project_type_snapshot varchar(80) DEFAULT NULL COMMENT ''训练开始时项目类型快照'' AFTER position_snapshot',
'SELECT 1');
PREPARE aihr_project_type_snapshot_stmt FROM @project_type_snapshot_ddl;
EXECUTE aihr_project_type_snapshot_stmt;
DEALLOCATE PREPARE aihr_project_type_snapshot_stmt;
SET @session_growth_level_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_session' AND column_name = 'growth_level'
);
SET @session_growth_level_ddl = IF(@session_growth_level_exists = 0,
'ALTER TABLE aihr_practice_session ADD COLUMN growth_level varchar(20) DEFAULT NULL COMMENT ''训练开始时成长层级快照'' AFTER project_type_snapshot',
'SELECT 1');
PREPARE aihr_session_growth_level_stmt FROM @session_growth_level_ddl;
EXECUTE aihr_session_growth_level_stmt;
DEALLOCATE PREPARE aihr_session_growth_level_stmt;
SET @session_competency_code_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_session' AND column_name = 'competency_code'
);
SET @session_competency_code_ddl = IF(@session_competency_code_exists = 0,
'ALTER TABLE aihr_practice_session ADD COLUMN competency_code varchar(100) DEFAULT NULL COMMENT ''训练开始时能力项快照'' AFTER growth_level',
'SELECT 1');
PREPARE aihr_session_competency_code_stmt FROM @session_competency_code_ddl;
EXECUTE aihr_session_competency_code_stmt;
DEALLOCATE PREPARE aihr_session_competency_code_stmt;
SET @session_collaboration_positions_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_session' AND column_name = 'collaboration_positions'
);
SET @session_collaboration_positions_ddl = IF(@session_collaboration_positions_exists = 0,
'ALTER TABLE aihr_practice_session ADD COLUMN collaboration_positions varchar(500) DEFAULT NULL COMMENT ''训练开始时协同岗位快照'' AFTER competency_code',
'SELECT 1');
PREPARE aihr_session_collaboration_positions_stmt FROM @session_collaboration_positions_ddl;
EXECUTE aihr_session_collaboration_positions_stmt;
DEALLOCATE PREPARE aihr_session_collaboration_positions_stmt;
SET @session_curriculum_version_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_session' AND column_name = 'curriculum_version'
);
SET @session_curriculum_version_ddl = IF(@session_curriculum_version_exists = 0,
'ALTER TABLE aihr_practice_session ADD COLUMN curriculum_version varchar(30) DEFAULT NULL COMMENT ''训练开始时成长目录版本快照'' AFTER collaboration_positions',
'SELECT 1');
PREPARE aihr_session_curriculum_version_stmt FROM @session_curriculum_version_ddl;
EXECUTE aihr_session_curriculum_version_stmt;
DEALLOCATE PREPARE aihr_session_curriculum_version_stmt;
-- 主管只可在复盘时确认“可进入下一训练层级”。确认附着于原训练会话,
-- 不改变人事职级、薪酬、上岗资格或历史训练快照。
SET @growth_confirmation_level_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_session' AND column_name = 'growth_confirmation_level'
);
SET @growth_confirmation_level_ddl = IF(@growth_confirmation_level_exists = 0,
'ALTER TABLE aihr_practice_session ADD COLUMN growth_confirmation_level varchar(20) DEFAULT NULL COMMENT ''主管确认可进入的训练层级'' AFTER curriculum_version',
'SELECT 1');
PREPARE aihr_growth_confirmation_level_stmt FROM @growth_confirmation_level_ddl;
EXECUTE aihr_growth_confirmation_level_stmt;
DEALLOCATE PREPARE aihr_growth_confirmation_level_stmt;
SET @growth_confirmed_by_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_session' AND column_name = 'growth_confirmed_by'
);
SET @growth_confirmed_by_ddl = IF(@growth_confirmed_by_exists = 0,
'ALTER TABLE aihr_practice_session ADD COLUMN growth_confirmed_by varchar(100) DEFAULT NULL COMMENT ''训练层级确认主管'' AFTER growth_confirmation_level',
'SELECT 1');
PREPARE aihr_growth_confirmed_by_stmt FROM @growth_confirmed_by_ddl;
EXECUTE aihr_growth_confirmed_by_stmt;
DEALLOCATE PREPARE aihr_growth_confirmed_by_stmt;
SET @growth_confirmed_time_exists = (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_session' AND column_name = 'growth_confirmed_time'
);
SET @growth_confirmed_time_ddl = IF(@growth_confirmed_time_exists = 0,
'ALTER TABLE aihr_practice_session ADD COLUMN growth_confirmed_time datetime DEFAULT NULL COMMENT ''训练层级确认时间'' AFTER growth_confirmed_by',
'SELECT 1');
PREPARE aihr_growth_confirmed_time_stmt FROM @growth_confirmed_time_ddl;
EXECUTE aihr_growth_confirmed_time_stmt;
DEALLOCATE PREPARE aihr_growth_confirmed_time_stmt;
SET @scenario_curriculum_index_exists = (
SELECT COUNT(*) FROM information_schema.statistics
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_scenario'
AND index_name = 'idx_aihr_practice_scenario_curriculum'
);
SET @scenario_curriculum_index_ddl = IF(@scenario_curriculum_index_exists = 0,
'ALTER TABLE aihr_practice_scenario ADD KEY idx_aihr_practice_scenario_curriculum (tenant_id, position, growth_level, competency_code, review_status, enabled)',
'SELECT 1');
PREPARE aihr_scenario_curriculum_index_stmt FROM @scenario_curriculum_index_ddl;
EXECUTE aihr_scenario_curriculum_index_stmt;
DEALLOCATE PREPARE aihr_scenario_curriculum_index_stmt;
-- 派发请求的重放依赖稳定唯一键;最近内容过滤依赖其复合索引。
-- 这两项由正式迁移维护,运行环境不能依赖服务启动时补 DDL。
SET @assignment_request_index_count = (
SELECT COUNT(*) FROM information_schema.statistics
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_assignment'
AND index_name = 'uk_aihr_assignment_request'
);
SET @assignment_request_index_non_unique = (
SELECT COALESCE(MIN(non_unique), 1) FROM information_schema.statistics
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_assignment'
AND index_name = 'uk_aihr_assignment_request'
);
SET @assignment_request_index_columns = (
SELECT GROUP_CONCAT(column_name ORDER BY seq_in_index) FROM information_schema.statistics
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_assignment'
AND index_name = 'uk_aihr_assignment_request'
);
SET @assignment_request_index_prefixes = (
SELECT COUNT(*) FROM information_schema.statistics
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_assignment'
AND index_name = 'uk_aihr_assignment_request' AND sub_part IS NOT NULL
);
SET @assignment_request_index_ddl = IF(
@assignment_request_index_count = 3
AND @assignment_request_index_non_unique = 0
AND @assignment_request_index_columns = 'tenant_id,request_key,ext_party_id'
AND @assignment_request_index_prefixes = 0,
'SELECT 1',
IF(@assignment_request_index_count = 0,
'ALTER TABLE aihr_practice_assignment ADD UNIQUE KEY uk_aihr_assignment_request (tenant_id, request_key, ext_party_id)',
'ALTER TABLE aihr_practice_assignment DROP INDEX uk_aihr_assignment_request, ADD UNIQUE KEY uk_aihr_assignment_request (tenant_id, request_key, ext_party_id)'
)
);
PREPARE aihr_assignment_request_index_stmt FROM @assignment_request_index_ddl;
EXECUTE aihr_assignment_request_index_stmt;
DEALLOCATE PREPARE aihr_assignment_request_index_stmt;
SET @assignment_recent_index_count = (
SELECT COUNT(*) FROM information_schema.statistics
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_assignment'
AND index_name = 'idx_aihr_assignment_recent_content'
);
SET @assignment_recent_index_non_unique = (
SELECT COALESCE(MIN(non_unique), 1) FROM information_schema.statistics
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_assignment'
AND index_name = 'idx_aihr_assignment_recent_content'
);
SET @assignment_recent_index_columns = (
SELECT GROUP_CONCAT(column_name ORDER BY seq_in_index) FROM information_schema.statistics
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_assignment'
AND index_name = 'idx_aihr_assignment_recent_content'
);
SET @assignment_recent_index_prefixes = (
SELECT COUNT(*) FROM information_schema.statistics
WHERE table_schema = @aihr_schema AND table_name = 'aihr_practice_assignment'
AND index_name = 'idx_aihr_assignment_recent_content' AND sub_part IS NOT NULL
);
SET @assignment_recent_index_ddl = IF(
@assignment_recent_index_count = 5
AND @assignment_recent_index_non_unique = 1
AND @assignment_recent_index_columns = 'tenant_id,ext_party_id,source,content_hash,create_time'
AND @assignment_recent_index_prefixes = 0,
'SELECT 1',
IF(@assignment_recent_index_count = 0,
'ALTER TABLE aihr_practice_assignment ADD KEY idx_aihr_assignment_recent_content (tenant_id, ext_party_id, source, content_hash, create_time)',
'ALTER TABLE aihr_practice_assignment DROP INDEX idx_aihr_assignment_recent_content, ADD KEY idx_aihr_assignment_recent_content (tenant_id, ext_party_id, source, content_hash, create_time)'
)
);
PREPARE aihr_assignment_recent_index_stmt FROM @assignment_recent_index_ddl;
EXECUTE aihr_assignment_recent_index_stmt;
DEALLOCATE PREPARE aihr_assignment_recent_index_stmt;