feat: 完成管理端聊天工作台收口

- 新增管理端聊天工作台与会话级额外知识库持久化

- 补齐发布态聊天、历史会话只读判断与答案版本切换

- 新增 chat_round 热数据与主线消息读取支撑
This commit is contained in:
2026-05-14 20:22:46 +08:00
parent 2ad8935a61
commit 47c2bad839
63 changed files with 8609 additions and 136 deletions

View File

@@ -0,0 +1,2 @@
ALTER TABLE `chat_session`
ADD COLUMN `ext_json` json NULL COMMENT '会话扩展信息' AFTER `title`;

View File

@@ -0,0 +1,20 @@
SET NAMES utf8mb4;
INSERT INTO `tb_sys_menu` (
`id`, `parent_id`, `menu_type`, `menu_title`, `menu_url`, `component`, `menu_icon`,
`is_show`, `permission_tag`, `sort_no`, `status`, `created`, `created_by`, `modified`, `modified_by`, `remark`
)
SELECT
367200000000000001, 0, 0, 'menus.ai.chat', '/ai/chat', '/ai/chat/index', 'svg:talk',
1, '', 12, 0, '2026-05-12 10:00:00', 1, '2026-05-12 10:00:00', 1, '管理端聊天工作台菜单'
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `tb_sys_menu` WHERE `id` = 367200000000000001
);
INSERT INTO `tb_sys_role_menu` (`id`, `role_id`, `menu_id`)
SELECT 367200000000000101, 1, 367200000000000001
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `tb_sys_role_menu` WHERE `id` = 367200000000000101
);

View File

@@ -0,0 +1,162 @@
CREATE TABLE IF NOT EXISTS `chat_round`
(
`id` bigint UNSIGNED NOT NULL COMMENT '轮次ID',
`session_id` bigint UNSIGNED NOT NULL COMMENT '会话ID',
`round_no` int NOT NULL COMMENT '轮次序号',
`user_message_id` bigint UNSIGNED NULL DEFAULT NULL COMMENT '用户消息ID',
`selected_assistant_message_id` bigint UNSIGNED NULL DEFAULT NULL COMMENT '当前选中的助手答案消息ID',
`selected_variant_index` int NOT NULL DEFAULT 0 COMMENT '当前选中的答案版本序号',
`variant_count` int NOT NULL DEFAULT 0 COMMENT '答案版本总数',
`status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'READY' COMMENT '轮次状态',
`created` datetime NOT NULL COMMENT '创建时间',
`modified` datetime NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_chat_round_session_round_no` (`session_id`, `round_no`) USING BTREE,
KEY `idx_chat_round_session_modified` (`session_id`, `modified`, `id`) USING BTREE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '聊天轮次热数据表';
SET @chat_log_template_alter = (
SELECT CASE
WHEN COUNT(1) = 0 THEN 'SELECT 1'
ELSE CONCAT(
'ALTER TABLE `chat_log_template` ',
GROUP_CONCAT(stmt ORDER BY ord SEPARATOR ', ')
)
END
FROM (
SELECT 1 AS ord,
'ADD COLUMN `round_id` bigint UNSIGNED NULL DEFAULT NULL COMMENT ''轮次ID'' AFTER `assistant_id`' AS stmt
WHERE NOT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = 'chat_log_template'
AND column_name = 'round_id'
)
UNION ALL
SELECT 2 AS ord,
'ADD COLUMN `round_no` int NULL DEFAULT NULL COMMENT ''轮次序号'' AFTER `round_id`' AS stmt
WHERE NOT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = 'chat_log_template'
AND column_name = 'round_no'
)
UNION ALL
SELECT 3 AS ord,
'ADD COLUMN `message_kind` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT ''消息类型'' AFTER `sender_role`' AS stmt
WHERE NOT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = 'chat_log_template'
AND column_name = 'message_kind'
)
UNION ALL
SELECT 4 AS ord,
'ADD COLUMN `variant_index` int NULL DEFAULT NULL COMMENT ''答案版本序号'' AFTER `message_kind`' AS stmt
WHERE NOT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = 'chat_log_template'
AND column_name = 'variant_index'
)
) changes
);
PREPARE stmt_chat_log_template_alter FROM @chat_log_template_alter;
EXECUTE stmt_chat_log_template_alter;
DEALLOCATE PREPARE stmt_chat_log_template_alter;
DROP PROCEDURE IF EXISTS migrate_chat_round_log_columns;
DELIMITER $$
CREATE PROCEDURE migrate_chat_round_log_columns()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v_table_name varchar(128);
DECLARE v_sql LONGTEXT;
DECLARE table_cursor CURSOR FOR
SELECT table_name
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name LIKE 'chat_log\\_%'
AND table_name <> 'chat_log_template';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN table_cursor;
table_loop:
LOOP
FETCH table_cursor INTO v_table_name;
IF done = 1 THEN
LEAVE table_loop;
END IF;
SET v_sql = (
SELECT CASE
WHEN COUNT(1) = 0 THEN 'SELECT 1'
ELSE CONCAT(
'ALTER TABLE `', v_table_name, '` ',
GROUP_CONCAT(stmt ORDER BY ord SEPARATOR ', ')
)
END
FROM (
SELECT 1 AS ord,
'ADD COLUMN `round_id` bigint UNSIGNED NULL DEFAULT NULL COMMENT ''轮次ID'' AFTER `assistant_id`' AS stmt
WHERE NOT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = v_table_name
AND column_name = 'round_id'
)
UNION ALL
SELECT 2 AS ord,
'ADD COLUMN `round_no` int NULL DEFAULT NULL COMMENT ''轮次序号'' AFTER `round_id`' AS stmt
WHERE NOT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = v_table_name
AND column_name = 'round_no'
)
UNION ALL
SELECT 3 AS ord,
'ADD COLUMN `message_kind` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT ''消息类型'' AFTER `sender_role`' AS stmt
WHERE NOT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = v_table_name
AND column_name = 'message_kind'
)
UNION ALL
SELECT 4 AS ord,
'ADD COLUMN `variant_index` int NULL DEFAULT NULL COMMENT ''答案版本序号'' AFTER `message_kind`' AS stmt
WHERE NOT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = v_table_name
AND column_name = 'variant_index'
)
) changes
);
SET @chat_round_log_table_alter = v_sql;
PREPARE stmt_chat_round_log_alter FROM @chat_round_log_table_alter;
EXECUTE stmt_chat_round_log_alter;
DEALLOCATE PREPARE stmt_chat_round_log_alter;
END LOOP;
CLOSE table_cursor;
END $$
DELIMITER ;
CALL migrate_chat_round_log_columns();
DROP PROCEDURE IF EXISTS migrate_chat_round_log_columns;

View File

@@ -0,0 +1,58 @@
SET @chat_log_template_round_variant_index = (
SELECT CASE
WHEN COUNT(1) > 0 THEN 'SELECT 1'
ELSE 'ALTER TABLE `chat_log_template` ADD INDEX `idx_chat_log_round_variant` (`session_id`, `round_id`, `message_kind`, `variant_index`, `created`, `id`)'
END
FROM information_schema.statistics
WHERE table_schema = DATABASE()
AND table_name = 'chat_log_template'
AND index_name = 'idx_chat_log_round_variant'
);
PREPARE stmt_chat_log_template_round_variant_index FROM @chat_log_template_round_variant_index;
EXECUTE stmt_chat_log_template_round_variant_index;
DEALLOCATE PREPARE stmt_chat_log_template_round_variant_index;
DROP PROCEDURE IF EXISTS migrate_chat_log_round_variant_index;
CREATE PROCEDURE migrate_chat_log_round_variant_index()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v_table_name VARCHAR(128);
DECLARE table_cursor CURSOR FOR
SELECT table_name
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name LIKE 'chat_log\_%'
AND table_name <> 'chat_log_template';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN table_cursor;
read_loop: LOOP
FETCH table_cursor INTO v_table_name;
IF done = 1 THEN
LEAVE read_loop;
END IF;
IF NOT EXISTS (
SELECT 1
FROM information_schema.statistics
WHERE table_schema = DATABASE()
AND table_name = v_table_name
AND index_name = 'idx_chat_log_round_variant'
) THEN
SET @chat_log_round_variant_index = CONCAT(
'ALTER TABLE `',
v_table_name,
'` ADD INDEX `idx_chat_log_round_variant` (`session_id`, `round_id`, `message_kind`, `variant_index`, `created`, `id`)'
);
PREPARE stmt_chat_log_round_variant_index FROM @chat_log_round_variant_index;
EXECUTE stmt_chat_log_round_variant_index;
DEALLOCATE PREPARE stmt_chat_log_round_variant_index;
END IF;
END LOOP;
CLOSE table_cursor;
END;
CALL migrate_chat_log_round_variant_index();
DROP PROCEDURE IF EXISTS migrate_chat_log_round_variant_index;