-- 银城大喇叭最小消息与阅读审计:仅租户公开已发布消息,不复用 sys_notice。 -- 可重复执行;不包含定向目标、附件、AI 摘要或问答上下文。 CREATE TABLE IF NOT EXISTS `aihr_broadcast_message` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '消息ID', `tenant_id` varchar(20) NOT NULL COMMENT '租户编号', `title` varchar(200) NOT NULL COMMENT '消息标题', `content` text NOT NULL COMMENT '消息正文', `status` varchar(20) NOT NULL DEFAULT 'PUBLISHED' COMMENT 'PUBLISHED/WITHDRAWN', `published_by` bigint NOT NULL COMMENT '发布人用户ID', `published_time` datetime NOT NULL COMMENT '发布时间', `publish_request_key` varchar(100) DEFAULT NULL COMMENT '发布幂等键', `publish_request_hash` char(64) DEFAULT NULL COMMENT '发布载荷SHA-256', `withdrawn_by` bigint DEFAULT NULL COMMENT '撤回人用户ID', `withdrawn_time` datetime DEFAULT NULL COMMENT '撤回时间', `withdraw_reason` varchar(500) DEFAULT NULL COMMENT '撤回原因', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_aihr_broadcast_message_publish_request` (`tenant_id`, `published_by`, `publish_request_key`), KEY `idx_aihr_broadcast_message_public` (`tenant_id`, `status`, `published_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='银城大喇叭租户公开消息'; -- 兼容已执行过 B0 建表的环境:历史消息没有请求键或撤回原因,保留 NULL。 SET @has_broadcast_publish_request_key := ( SELECT COUNT(*) FROM information_schema.COLUMNS WHERE table_schema = DATABASE() AND table_name = 'aihr_broadcast_message' AND column_name = 'publish_request_key' ); SET @broadcast_ddl := IF( @has_broadcast_publish_request_key = 0, 'ALTER TABLE aihr_broadcast_message ADD COLUMN publish_request_key varchar(100) DEFAULT NULL COMMENT ''发布幂等键'' AFTER published_time', 'SELECT 1' ); PREPARE aihr_broadcast_stmt FROM @broadcast_ddl; EXECUTE aihr_broadcast_stmt; DEALLOCATE PREPARE aihr_broadcast_stmt; SET @has_broadcast_publish_request_hash := ( SELECT COUNT(*) FROM information_schema.COLUMNS WHERE table_schema = DATABASE() AND table_name = 'aihr_broadcast_message' AND column_name = 'publish_request_hash' ); SET @broadcast_ddl := IF( @has_broadcast_publish_request_hash = 0, 'ALTER TABLE aihr_broadcast_message ADD COLUMN publish_request_hash char(64) DEFAULT NULL COMMENT ''发布载荷SHA-256'' AFTER publish_request_key', 'SELECT 1' ); PREPARE aihr_broadcast_stmt FROM @broadcast_ddl; EXECUTE aihr_broadcast_stmt; DEALLOCATE PREPARE aihr_broadcast_stmt; SET @has_broadcast_withdraw_reason := ( SELECT COUNT(*) FROM information_schema.COLUMNS WHERE table_schema = DATABASE() AND table_name = 'aihr_broadcast_message' AND column_name = 'withdraw_reason' ); SET @broadcast_ddl := IF( @has_broadcast_withdraw_reason = 0, 'ALTER TABLE aihr_broadcast_message ADD COLUMN withdraw_reason varchar(500) DEFAULT NULL COMMENT ''撤回原因'' AFTER withdrawn_time', 'SELECT 1' ); PREPARE aihr_broadcast_stmt FROM @broadcast_ddl; EXECUTE aihr_broadcast_stmt; DEALLOCATE PREPARE aihr_broadcast_stmt; SET @has_broadcast_publish_request_index := ( SELECT COUNT(*) FROM information_schema.STATISTICS WHERE table_schema = DATABASE() AND table_name = 'aihr_broadcast_message' AND index_name = 'uk_aihr_broadcast_message_publish_request' ); SET @broadcast_publish_request_index_valid := ( SELECT COUNT(*) FROM ( SELECT index_name FROM information_schema.STATISTICS WHERE table_schema = DATABASE() AND table_name = 'aihr_broadcast_message' AND index_name = 'uk_aihr_broadcast_message_publish_request' GROUP BY index_name HAVING MIN(non_unique) = 0 AND COUNT(*) = 3 AND SUM(sub_part IS NOT NULL) = 0 AND GROUP_CONCAT(column_name ORDER BY seq_in_index SEPARATOR ',') = 'tenant_id,published_by,publish_request_key' ) valid_broadcast_publish_request_index ); SET @broadcast_ddl := CASE WHEN @broadcast_publish_request_index_valid > 0 THEN 'SELECT 1' WHEN @has_broadcast_publish_request_index > 0 THEN 'ALTER TABLE aihr_broadcast_message DROP INDEX uk_aihr_broadcast_message_publish_request, ADD UNIQUE KEY uk_aihr_broadcast_message_publish_request (tenant_id, published_by, publish_request_key)' ELSE 'ALTER TABLE aihr_broadcast_message ADD UNIQUE KEY uk_aihr_broadcast_message_publish_request (tenant_id, published_by, publish_request_key)' END; PREPARE aihr_broadcast_stmt FROM @broadcast_ddl; EXECUTE aihr_broadcast_stmt; DEALLOCATE PREPARE aihr_broadcast_stmt; -- 只追加首发快照;B1 没有修订入口,应用代码不会更新或删除版本记录。 CREATE TABLE IF NOT EXISTS `aihr_broadcast_version` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '消息版本ID', `tenant_id` varchar(20) NOT NULL COMMENT '租户编号', `message_id` bigint NOT NULL COMMENT '消息ID', `version` int NOT NULL COMMENT '消息版本,首版为1', `title` varchar(200) NOT NULL COMMENT '消息标题快照', `content` text NOT NULL COMMENT '消息正文快照', `published_by` bigint NOT NULL COMMENT '发布人用户ID', `published_time` datetime NOT NULL COMMENT '发布时间', `create_time` datetime NOT NULL COMMENT '快照创建时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_aihr_broadcast_version` (`tenant_id`, `message_id`, `version`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='银城大喇叭消息不可变版本快照'; CREATE TABLE IF NOT EXISTS `aihr_broadcast_read` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '阅读记录ID', `tenant_id` varchar(20) NOT NULL COMMENT '租户编号', `message_id` bigint NOT NULL COMMENT '消息ID', `user_id` bigint NOT NULL COMMENT '阅读用户ID', `first_read_time` datetime NOT NULL COMMENT '首次阅读时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_aihr_broadcast_read` (`tenant_id`, `message_id`, `user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='银城大喇叭阅读审计'; -- 与租户事实表保持同一排序规则,兼容历史库 general_ci 与新 MySQL 8 库 0900_ai_ci。 SET @broadcast_target_collation := ( SELECT collation_name FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'aihr_knowledge_info' AND column_name = 'tenant_id' LIMIT 1 ); SET @broadcast_target_collation := COALESCE(@broadcast_target_collation, @@collation_database); SET @broadcast_message_collation := ( SELECT table_collation FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'aihr_broadcast_message' LIMIT 1 ); SET @broadcast_ddl := IF( @broadcast_message_collation = @broadcast_target_collation, 'SELECT 1', CONCAT('ALTER TABLE aihr_broadcast_message CONVERT TO CHARACTER SET utf8mb4 COLLATE ', @broadcast_target_collation) ); PREPARE aihr_broadcast_stmt FROM @broadcast_ddl; EXECUTE aihr_broadcast_stmt; DEALLOCATE PREPARE aihr_broadcast_stmt; SET @broadcast_version_collation := ( SELECT table_collation FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'aihr_broadcast_version' LIMIT 1 ); SET @broadcast_ddl := IF( @broadcast_version_collation = @broadcast_target_collation, 'SELECT 1', CONCAT('ALTER TABLE aihr_broadcast_version CONVERT TO CHARACTER SET utf8mb4 COLLATE ', @broadcast_target_collation) ); PREPARE aihr_broadcast_stmt FROM @broadcast_ddl; EXECUTE aihr_broadcast_stmt; DEALLOCATE PREPARE aihr_broadcast_stmt; SET @broadcast_read_collation := ( SELECT table_collation FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'aihr_broadcast_read' LIMIT 1 ); SET @broadcast_ddl := IF( @broadcast_read_collation = @broadcast_target_collation, 'SELECT 1', CONCAT('ALTER TABLE aihr_broadcast_read CONVERT TO CHARACTER SET utf8mb4 COLLATE ', @broadcast_target_collation) ); PREPARE aihr_broadcast_stmt FROM @broadcast_ddl; EXECUTE aihr_broadcast_stmt; DEALLOCATE PREPARE aihr_broadcast_stmt; -- 兼容已执行过 B0 建表的环境:原有消息只补一次 v1 快照。 INSERT INTO aihr_broadcast_version ( tenant_id, message_id, `version`, title, content, published_by, published_time, create_time ) SELECT m.tenant_id, m.id, 1, m.title, m.content, m.published_by, m.published_time, m.create_time FROM aihr_broadcast_message m WHERE NOT EXISTS ( SELECT 1 FROM aihr_broadcast_version v WHERE v.tenant_id = m.tenant_id AND v.message_id = m.id AND v.`version` = 1 ); SET @broadcast_target_collation := NULL; SET @broadcast_message_collation := NULL; SET @broadcast_version_collation := NULL; SET @broadcast_read_collation := NULL; SET @has_broadcast_publish_request_key := NULL; SET @has_broadcast_publish_request_hash := NULL; SET @has_broadcast_withdraw_reason := NULL; SET @has_broadcast_publish_request_index := NULL; SET @broadcast_publish_request_index_valid := NULL; SET @broadcast_ddl := NULL;