1253 lines
47 KiB
SQL
1253 lines
47 KiB
SQL
-- iMeeting legacy DB upgrade
|
||
-- Goal: upgrade an old schema to the latest application-facing structure
|
||
-- Strategy:
|
||
-- 1) standardize system tables to sys_* base tables
|
||
-- 2) align shared table columns/indexes
|
||
-- 3) create missing configuration tables
|
||
-- 4) migrate legacy configuration/hot-word data into new tables
|
||
-- 5) rebuild menu tree and role permissions needed by the latest backend
|
||
-- 6) recreate compatibility views
|
||
|
||
-- ----------------------------------------------------------------------
|
||
-- 1. Rename legacy system tables to sys_* base tables when needed
|
||
-- ----------------------------------------------------------------------
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.tables
|
||
WHERE table_schema = DATABASE() AND table_name = 'users' AND table_type = 'BASE TABLE'
|
||
) AND NOT EXISTS (
|
||
SELECT 1 FROM information_schema.tables
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_users'
|
||
),
|
||
'RENAME TABLE users TO sys_users',
|
||
'SELECT 1'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.tables
|
||
WHERE table_schema = DATABASE() AND table_name = 'roles' AND table_type = 'BASE TABLE'
|
||
) AND NOT EXISTS (
|
||
SELECT 1 FROM information_schema.tables
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_roles'
|
||
),
|
||
'RENAME TABLE roles TO sys_roles',
|
||
'SELECT 1'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.tables
|
||
WHERE table_schema = DATABASE() AND table_name = 'menus' AND table_type = 'BASE TABLE'
|
||
) AND NOT EXISTS (
|
||
SELECT 1 FROM information_schema.tables
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_menus'
|
||
),
|
||
'RENAME TABLE menus TO sys_menus',
|
||
'SELECT 1'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.tables
|
||
WHERE table_schema = DATABASE() AND table_name = 'role_menu_permissions' AND table_type = 'BASE TABLE'
|
||
) AND NOT EXISTS (
|
||
SELECT 1 FROM information_schema.tables
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_role_menu_permissions'
|
||
),
|
||
'RENAME TABLE role_menu_permissions TO sys_role_menu_permissions',
|
||
'SELECT 1'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.tables
|
||
WHERE table_schema = DATABASE() AND table_name = 'dict_data' AND table_type = 'BASE TABLE'
|
||
) AND NOT EXISTS (
|
||
SELECT 1 FROM information_schema.tables
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_dict_data'
|
||
),
|
||
'RENAME TABLE dict_data TO sys_dict_data',
|
||
'SELECT 1'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.tables
|
||
WHERE table_schema = DATABASE() AND table_name = 'system_parameters' AND table_type = 'BASE TABLE'
|
||
) AND NOT EXISTS (
|
||
SELECT 1 FROM information_schema.tables
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_system_parameters'
|
||
),
|
||
'RENAME TABLE system_parameters TO sys_system_parameters',
|
||
'SELECT 1'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- ----------------------------------------------------------------------
|
||
-- 2. Align existing sys_* tables
|
||
-- ----------------------------------------------------------------------
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.statistics
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_users' AND index_name = 'idx_role_id'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_users ADD KEY idx_role_id (role_id)'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.statistics
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_roles' AND index_name = 'uk_role_name'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_roles ADD UNIQUE KEY uk_role_name (role_name)'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.columns
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_menus' AND column_name = 'menu_level'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_menus ADD COLUMN menu_level TINYINT(3) NOT NULL DEFAULT 1 COMMENT ''菜单层级(根节点为1)'' AFTER parent_id'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.columns
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_menus' AND column_name = 'tree_path'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_menus ADD COLUMN tree_path VARCHAR(255) DEFAULT NULL COMMENT ''树路径(如 /3/6)'' AFTER menu_level'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.columns
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_menus' AND column_name = 'is_visible'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_menus ADD COLUMN is_visible TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''是否在侧边菜单显示'' AFTER is_active'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.statistics
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_menus' AND index_name = 'idx_menu_level'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_menus ADD KEY idx_menu_level (menu_level)'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.statistics
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_menus' AND index_name = 'idx_tree_path'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_menus ADD KEY idx_tree_path (tree_path)'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.statistics
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_menus' AND index_name = 'idx_is_visible'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_menus ADD KEY idx_is_visible (is_visible)'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.statistics
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_menus' AND index_name = 'idx_menus_visible_tree'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_menus ADD KEY idx_menus_visible_tree (is_active, is_visible, parent_id, sort_order, menu_id)'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.columns
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_role_menu_permissions' AND column_name = 'granted_by'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_role_menu_permissions ADD COLUMN granted_by INT(11) DEFAULT NULL COMMENT ''授权操作人ID'' AFTER menu_id'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.columns
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_role_menu_permissions' AND column_name = 'granted_at'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_role_menu_permissions ADD COLUMN granted_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP COMMENT ''授权时间'' AFTER granted_by'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.statistics
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_role_menu_permissions' AND index_name = 'idx_granted_by'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_role_menu_permissions ADD KEY idx_granted_by (granted_by)'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.statistics
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_role_menu_permissions' AND index_name = 'idx_granted_at'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_role_menu_permissions ADD KEY idx_granted_at (granted_at)'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.statistics
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_role_menu_permissions' AND index_name = 'idx_rmp_role'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_role_menu_permissions ADD KEY idx_rmp_role (role_id)'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.statistics
|
||
WHERE table_schema = DATABASE() AND table_name = 'sys_role_menu_permissions' AND index_name = 'idx_rmp_menu'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE sys_role_menu_permissions ADD KEY idx_rmp_menu (menu_id)'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
ALTER TABLE `terminals`
|
||
MODIFY COLUMN `current_user_id` INT(11) DEFAULT NULL COMMENT '终端绑定账号';
|
||
|
||
-- prompts: add is_system and composite index
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.columns
|
||
WHERE table_schema = DATABASE() AND table_name = 'prompts' AND column_name = 'is_system'
|
||
),
|
||
'SELECT 1',
|
||
'ALTER TABLE prompts ADD COLUMN is_system TINYINT(1) NOT NULL DEFAULT 0 AFTER creator_id'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @sql := (
|
||
SELECT IF(
|
||
EXISTS (
|
||
SELECT 1 FROM information_schema.statistics
|
||
WHERE table_schema = DATABASE() AND table_name = 'prompts' AND index_name = 'idx_prompts_task_scope_active'
|
||
),
|
||
'SELECT 1',
|
||
'CREATE INDEX idx_prompts_task_scope_active ON prompts (task_type, is_system, creator_id, is_active, is_default)'
|
||
)
|
||
);
|
||
PREPARE stmt FROM @sql;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
UPDATE prompts
|
||
SET is_system = 1
|
||
WHERE creator_id = 1;
|
||
|
||
-- ----------------------------------------------------------------------
|
||
-- 3. Create missing tables with latest structure
|
||
-- ----------------------------------------------------------------------
|
||
CREATE TABLE IF NOT EXISTS `sys_system_parameters` (
|
||
`param_id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||
`param_key` varchar(128) NOT NULL,
|
||
`param_name` varchar(255) NOT NULL,
|
||
`param_value` text,
|
||
`value_type` varchar(32) NOT NULL DEFAULT 'string',
|
||
`category` varchar(64) NOT NULL DEFAULT 'system',
|
||
`description` varchar(500) DEFAULT NULL,
|
||
`is_active` tinyint(1) NOT NULL DEFAULT '1',
|
||
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
|
||
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (`param_id`),
|
||
UNIQUE KEY `uk_param_key` (`param_key`),
|
||
KEY `idx_param_category` (`category`),
|
||
KEY `idx_param_active` (`is_active`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
|
||
CREATE TABLE IF NOT EXISTS `ai_model_configs` (
|
||
`model_id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||
`model_code` varchar(128) NOT NULL,
|
||
`model_name` varchar(255) NOT NULL,
|
||
`model_type` varchar(32) NOT NULL,
|
||
`provider` varchar(64) DEFAULT NULL,
|
||
`endpoint_url` varchar(512) DEFAULT NULL,
|
||
`api_key` varchar(512) DEFAULT NULL,
|
||
`llm_model_name` varchar(128) DEFAULT NULL,
|
||
`llm_timeout` int(11) DEFAULT NULL,
|
||
`llm_temperature` decimal(5,2) DEFAULT NULL,
|
||
`llm_top_p` decimal(5,2) DEFAULT NULL,
|
||
`llm_max_tokens` int(11) DEFAULT NULL,
|
||
`llm_system_prompt` text,
|
||
`asr_model_name` varchar(128) DEFAULT NULL,
|
||
`asr_vocabulary_id` varchar(255) DEFAULT NULL,
|
||
`asr_speaker_count` int(11) DEFAULT NULL,
|
||
`asr_language_hints` varchar(255) DEFAULT NULL,
|
||
`asr_disfluency_removal_enabled` tinyint(1) DEFAULT NULL,
|
||
`asr_diarization_enabled` tinyint(1) DEFAULT NULL,
|
||
`config_json` json DEFAULT NULL,
|
||
`description` varchar(500) DEFAULT NULL,
|
||
`is_active` tinyint(1) NOT NULL DEFAULT '1',
|
||
`is_default` tinyint(1) NOT NULL DEFAULT '0',
|
||
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
|
||
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (`model_id`),
|
||
UNIQUE KEY `uk_model_code` (`model_code`),
|
||
KEY `idx_model_type` (`model_type`),
|
||
KEY `idx_model_active` (`is_active`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
|
||
CREATE TABLE IF NOT EXISTS `llm_model_config` (
|
||
`config_id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||
`model_code` varchar(128) NOT NULL,
|
||
`model_name` varchar(255) NOT NULL,
|
||
`provider` varchar(64) DEFAULT NULL,
|
||
`endpoint_url` varchar(512) DEFAULT NULL,
|
||
`api_key` varchar(512) DEFAULT NULL,
|
||
`llm_model_name` varchar(128) NOT NULL,
|
||
`llm_timeout` int(11) NOT NULL DEFAULT '120',
|
||
`llm_temperature` decimal(5,2) NOT NULL DEFAULT '0.70',
|
||
`llm_top_p` decimal(5,2) NOT NULL DEFAULT '0.90',
|
||
`llm_max_tokens` int(11) NOT NULL DEFAULT '2048',
|
||
`llm_system_prompt` text,
|
||
`description` varchar(500) DEFAULT NULL,
|
||
`is_active` tinyint(1) NOT NULL DEFAULT '1',
|
||
`is_default` tinyint(1) NOT NULL DEFAULT '0',
|
||
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
|
||
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (`config_id`),
|
||
UNIQUE KEY `uk_llm_model_code` (`model_code`),
|
||
KEY `idx_llm_active` (`is_active`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
|
||
CREATE TABLE IF NOT EXISTS `audio_model_config` (
|
||
`config_id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||
`model_code` varchar(128) NOT NULL,
|
||
`model_name` varchar(255) NOT NULL,
|
||
`audio_scene` varchar(32) NOT NULL,
|
||
`provider` varchar(64) DEFAULT NULL,
|
||
`endpoint_url` varchar(512) DEFAULT NULL,
|
||
`api_key` varchar(512) DEFAULT NULL,
|
||
`asr_model_name` varchar(128) DEFAULT NULL,
|
||
`asr_vocabulary_id` varchar(255) DEFAULT NULL,
|
||
`hot_word_group_id` int(11) DEFAULT NULL COMMENT '关联热词组ID',
|
||
`extra_config` json DEFAULT NULL COMMENT '音频模型差异化配置(JSON)',
|
||
`asr_speaker_count` int(11) DEFAULT NULL,
|
||
`asr_language_hints` varchar(255) DEFAULT NULL,
|
||
`asr_disfluency_removal_enabled` tinyint(1) DEFAULT NULL,
|
||
`asr_diarization_enabled` tinyint(1) DEFAULT NULL,
|
||
`vp_template_text` text,
|
||
`vp_duration_seconds` int(11) DEFAULT NULL,
|
||
`vp_sample_rate` int(11) DEFAULT NULL,
|
||
`vp_channels` int(11) DEFAULT NULL,
|
||
`vp_max_size_bytes` bigint(20) DEFAULT NULL,
|
||
`description` varchar(500) DEFAULT NULL,
|
||
`is_active` tinyint(1) NOT NULL DEFAULT '1',
|
||
`is_default` tinyint(1) NOT NULL DEFAULT '0',
|
||
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
|
||
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (`config_id`),
|
||
UNIQUE KEY `uk_audio_model_code` (`model_code`),
|
||
KEY `idx_audio_scene` (`audio_scene`),
|
||
KEY `idx_audio_active` (`is_active`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
|
||
CREATE TABLE IF NOT EXISTS `hot_word_group` (
|
||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '热词组名称',
|
||
`description` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '描述',
|
||
`vocabulary_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '阿里云 DashScope 词表ID',
|
||
`last_sync_time` datetime DEFAULT NULL COMMENT '最后同步时间',
|
||
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1:启用 0:停用',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='热词组主表';
|
||
|
||
CREATE TABLE IF NOT EXISTS `hot_word_item` (
|
||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||
`group_id` int(11) NOT NULL COMMENT '热词组ID',
|
||
`text` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '热词内容',
|
||
`weight` int(11) NOT NULL DEFAULT '4' COMMENT '权重 1-10',
|
||
`lang` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'zh' COMMENT 'zh/en',
|
||
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1:启用 0:停用',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `idx_group_text` (`group_id`,`text`),
|
||
KEY `idx_group_id` (`group_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='热词条目从表';
|
||
|
||
CREATE TABLE IF NOT EXISTS `prompt_config` (
|
||
`config_id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||
`user_id` int(11) NOT NULL,
|
||
`task_type` enum('MEETING_TASK','KNOWLEDGE_TASK') NOT NULL,
|
||
`prompt_id` int(11) NOT NULL,
|
||
`is_enabled` tinyint(1) NOT NULL DEFAULT '1',
|
||
`sort_order` int(11) NOT NULL DEFAULT '0',
|
||
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
|
||
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (`config_id`),
|
||
UNIQUE KEY `uk_user_task_prompt` (`user_id`,`task_type`,`prompt_id`),
|
||
KEY `idx_user_task_order` (`user_id`,`task_type`,`sort_order`),
|
||
KEY `idx_prompt_id` (`prompt_id`),
|
||
CONSTRAINT `fk_upc_prompt` FOREIGN KEY (`prompt_id`) REFERENCES `prompts` (`id`) ON DELETE CASCADE,
|
||
CONSTRAINT `fk_upc_user` FOREIGN KEY (`user_id`) REFERENCES `sys_users` (`user_id`) ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
|
||
CREATE TABLE IF NOT EXISTS `sys_user_mcp` (
|
||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||
`user_id` int(11) NOT NULL,
|
||
`bot_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||
`bot_secret` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||
`status` tinyint(1) NOT NULL DEFAULT '1',
|
||
`last_used_at` datetime DEFAULT NULL,
|
||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_sys_user_mcp_user_id` (`user_id`),
|
||
UNIQUE KEY `uk_sys_user_mcp_bot_id` (`bot_id`),
|
||
KEY `idx_sys_user_mcp_status` (`status`),
|
||
CONSTRAINT `fk_sys_user_mcp_user` FOREIGN KEY (`user_id`) REFERENCES `sys_users` (`user_id`) ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户MCP接入凭证';
|
||
|
||
-- ----------------------------------------------------------------------
|
||
-- 4. Migrate legacy system config data into new parameter/model tables
|
||
-- ----------------------------------------------------------------------
|
||
INSERT INTO `sys_system_parameters`
|
||
(`param_key`, `param_name`, `param_value`, `value_type`, `category`, `description`, `is_active`)
|
||
SELECT
|
||
CASE
|
||
WHEN d.`dict_code` = 'timeline_pagesize' THEN 'page_size'
|
||
WHEN d.`dict_code` = 'branding_app_name' THEN 'app_name'
|
||
WHEN d.`dict_code` = 'branding_console_subtitle' THEN 'console_subtitle'
|
||
WHEN d.`dict_code` = 'branding_preview_title' THEN 'preview_title'
|
||
WHEN d.`dict_code` = 'branding_login_welcome' THEN 'login_welcome'
|
||
WHEN d.`dict_code` = 'branding_footer_text' THEN 'footer_text'
|
||
ELSE d.`dict_code`
|
||
END,
|
||
d.`label_cn`,
|
||
JSON_UNQUOTE(JSON_EXTRACT(d.`extension_attr`, '$.value')),
|
||
'string',
|
||
CASE
|
||
WHEN d.`dict_code` IN (
|
||
'timeline_pagesize',
|
||
'page_size',
|
||
'branding_app_name',
|
||
'app_name',
|
||
'branding_console_subtitle',
|
||
'console_subtitle',
|
||
'branding_preview_title',
|
||
'preview_title',
|
||
'branding_login_welcome',
|
||
'login_welcome',
|
||
'branding_footer_text',
|
||
'footer_text',
|
||
'max_audio_size',
|
||
'max_image_size'
|
||
) THEN 'public'
|
||
ELSE 'system'
|
||
END,
|
||
CONCAT('migrated from dict_data.system_config(', d.`dict_code`, ')'),
|
||
CASE WHEN d.`status` = 1 THEN 1 ELSE 0 END
|
||
FROM `sys_dict_data` d
|
||
WHERE d.`dict_type` = 'system_config'
|
||
AND d.`dict_code` NOT IN ('llm_model', 'voiceprint')
|
||
AND JSON_EXTRACT(d.`extension_attr`, '$.value') IS NOT NULL
|
||
ON DUPLICATE KEY UPDATE
|
||
`param_name` = VALUES(`param_name`),
|
||
`param_value` = VALUES(`param_value`),
|
||
`category` = VALUES(`category`),
|
||
`description` = VALUES(`description`),
|
||
`is_active` = VALUES(`is_active`);
|
||
|
||
INSERT INTO `ai_model_configs`
|
||
(`model_code`, `model_name`, `model_type`, `provider`, `endpoint_url`, `api_key`,
|
||
`llm_model_name`, `llm_timeout`, `llm_temperature`, `llm_top_p`, `llm_max_tokens`, `llm_system_prompt`,
|
||
`config_json`, `description`, `is_active`, `is_default`)
|
||
SELECT
|
||
'llm_model',
|
||
'默认文本模型',
|
||
'llm',
|
||
'dashscope',
|
||
'https://dashscope.aliyuncs.com/compatible-mode/v1',
|
||
NULL,
|
||
COALESCE(JSON_UNQUOTE(JSON_EXTRACT(d.`extension_attr`, '$.model_name')), 'qwen-plus'),
|
||
COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(d.`extension_attr`, '$.time_out')) AS UNSIGNED), 120),
|
||
COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(d.`extension_attr`, '$.temperature')) AS DECIMAL(5,2)), 0.70),
|
||
COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(d.`extension_attr`, '$.top_p')) AS DECIMAL(5,2)), 0.90),
|
||
COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(d.`extension_attr`, '$.max_tokens')) AS UNSIGNED), 2048),
|
||
JSON_UNQUOTE(JSON_EXTRACT(d.`extension_attr`, '$.system_prompt')),
|
||
d.`extension_attr`,
|
||
'migrated from dict_data.system_config.llm_model',
|
||
CASE WHEN d.`status` = 1 THEN 1 ELSE 0 END,
|
||
1
|
||
FROM `sys_dict_data` d
|
||
WHERE d.`dict_type` = 'system_config'
|
||
AND d.`dict_code` = 'llm_model'
|
||
LIMIT 1
|
||
ON DUPLICATE KEY UPDATE
|
||
`model_name` = VALUES(`model_name`),
|
||
`provider` = VALUES(`provider`),
|
||
`endpoint_url` = VALUES(`endpoint_url`),
|
||
`llm_model_name` = VALUES(`llm_model_name`),
|
||
`llm_timeout` = VALUES(`llm_timeout`),
|
||
`llm_temperature` = VALUES(`llm_temperature`),
|
||
`llm_top_p` = VALUES(`llm_top_p`),
|
||
`llm_max_tokens` = VALUES(`llm_max_tokens`),
|
||
`llm_system_prompt` = VALUES(`llm_system_prompt`),
|
||
`config_json` = VALUES(`config_json`),
|
||
`description` = VALUES(`description`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_default` = VALUES(`is_default`);
|
||
|
||
INSERT INTO `ai_model_configs`
|
||
(`model_code`, `model_name`, `model_type`, `provider`, `endpoint_url`, `api_key`,
|
||
`asr_model_name`, `asr_vocabulary_id`, `asr_speaker_count`, `asr_language_hints`,
|
||
`asr_disfluency_removal_enabled`, `asr_diarization_enabled`,
|
||
`config_json`, `description`, `is_active`, `is_default`)
|
||
SELECT
|
||
'audio_model',
|
||
'默认音频识别模型',
|
||
'audio',
|
||
'dashscope',
|
||
'https://dashscope.aliyuncs.com/api/v1/services/audio/asr/transcription',
|
||
NULL,
|
||
'paraformer-v2',
|
||
(
|
||
SELECT JSON_UNQUOTE(JSON_EXTRACT(d2.`extension_attr`, '$.value'))
|
||
FROM `sys_dict_data` d2
|
||
WHERE d2.`dict_type` = 'system_config' AND d2.`dict_code` = 'asr_vocabulary_id'
|
||
LIMIT 1
|
||
),
|
||
10,
|
||
'zh, en',
|
||
1,
|
||
1,
|
||
JSON_OBJECT(
|
||
'model', 'paraformer-v2',
|
||
'vocabulary_id', (
|
||
SELECT JSON_UNQUOTE(JSON_EXTRACT(d3.`extension_attr`, '$.value'))
|
||
FROM `sys_dict_data` d3
|
||
WHERE d3.`dict_type` = 'system_config' AND d3.`dict_code` = 'asr_vocabulary_id'
|
||
LIMIT 1
|
||
),
|
||
'speaker_count', 10,
|
||
'language_hints', 'zh, en',
|
||
'disfluency_removal_enabled', TRUE,
|
||
'diarization_enabled', TRUE
|
||
),
|
||
'migrated default ASR config',
|
||
1,
|
||
1
|
||
FROM DUAL
|
||
ON DUPLICATE KEY UPDATE
|
||
`model_name` = VALUES(`model_name`),
|
||
`provider` = VALUES(`provider`),
|
||
`endpoint_url` = VALUES(`endpoint_url`),
|
||
`asr_model_name` = VALUES(`asr_model_name`),
|
||
`asr_vocabulary_id` = VALUES(`asr_vocabulary_id`),
|
||
`asr_speaker_count` = VALUES(`asr_speaker_count`),
|
||
`asr_language_hints` = VALUES(`asr_language_hints`),
|
||
`asr_disfluency_removal_enabled` = VALUES(`asr_disfluency_removal_enabled`),
|
||
`asr_diarization_enabled` = VALUES(`asr_diarization_enabled`),
|
||
`config_json` = VALUES(`config_json`),
|
||
`description` = VALUES(`description`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_default` = VALUES(`is_default`);
|
||
|
||
INSERT INTO `ai_model_configs`
|
||
(`model_code`, `model_name`, `model_type`, `provider`, `endpoint_url`, `api_key`,
|
||
`config_json`, `description`, `is_active`, `is_default`)
|
||
SELECT
|
||
'voiceprint_model',
|
||
'默认声纹模型',
|
||
'audio',
|
||
'funasr',
|
||
'http://127.0.0.1:10095',
|
||
NULL,
|
||
d.`extension_attr`,
|
||
'migrated from dict_data.system_config.voiceprint',
|
||
CASE WHEN d.`status` = 1 THEN 1 ELSE 0 END,
|
||
0
|
||
FROM `sys_dict_data` d
|
||
WHERE d.`dict_type` = 'system_config'
|
||
AND d.`dict_code` = 'voiceprint'
|
||
LIMIT 1
|
||
ON DUPLICATE KEY UPDATE
|
||
`model_name` = VALUES(`model_name`),
|
||
`provider` = VALUES(`provider`),
|
||
`endpoint_url` = VALUES(`endpoint_url`),
|
||
`config_json` = VALUES(`config_json`),
|
||
`description` = VALUES(`description`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_default` = VALUES(`is_default`);
|
||
|
||
INSERT INTO `llm_model_config`
|
||
(`model_code`, `model_name`, `provider`, `endpoint_url`, `api_key`, `llm_model_name`, `llm_timeout`,
|
||
`llm_temperature`, `llm_top_p`, `llm_max_tokens`, `llm_system_prompt`, `description`, `is_active`, `is_default`)
|
||
SELECT
|
||
`model_code`,
|
||
`model_name`,
|
||
`provider`,
|
||
`endpoint_url`,
|
||
`api_key`,
|
||
COALESCE(`llm_model_name`, JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.model_name')), 'qwen-plus'),
|
||
COALESCE(`llm_timeout`, CAST(JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.time_out')) AS UNSIGNED), 120),
|
||
COALESCE(`llm_temperature`, CAST(JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.temperature')) AS DECIMAL(5,2)), 0.70),
|
||
COALESCE(`llm_top_p`, CAST(JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.top_p')) AS DECIMAL(5,2)), 0.90),
|
||
COALESCE(`llm_max_tokens`, CAST(JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.max_tokens')) AS UNSIGNED), 2048),
|
||
COALESCE(`llm_system_prompt`, JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.system_prompt'))),
|
||
`description`,
|
||
`is_active`,
|
||
`is_default`
|
||
FROM `ai_model_configs`
|
||
WHERE `model_type` = 'llm'
|
||
ON DUPLICATE KEY UPDATE
|
||
`model_name` = VALUES(`model_name`),
|
||
`provider` = VALUES(`provider`),
|
||
`endpoint_url` = VALUES(`endpoint_url`),
|
||
`api_key` = VALUES(`api_key`),
|
||
`llm_model_name` = VALUES(`llm_model_name`),
|
||
`llm_timeout` = VALUES(`llm_timeout`),
|
||
`llm_temperature` = VALUES(`llm_temperature`),
|
||
`llm_top_p` = VALUES(`llm_top_p`),
|
||
`llm_max_tokens` = VALUES(`llm_max_tokens`),
|
||
`llm_system_prompt` = VALUES(`llm_system_prompt`),
|
||
`description` = VALUES(`description`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_default` = VALUES(`is_default`);
|
||
|
||
INSERT INTO `audio_model_config`
|
||
(`model_code`, `model_name`, `audio_scene`, `provider`, `endpoint_url`, `api_key`, `asr_model_name`, `asr_vocabulary_id`,
|
||
`asr_speaker_count`, `asr_language_hints`, `asr_disfluency_removal_enabled`, `asr_diarization_enabled`,
|
||
`description`, `is_active`, `is_default`)
|
||
SELECT
|
||
`model_code`,
|
||
`model_name`,
|
||
'asr',
|
||
`provider`,
|
||
`endpoint_url`,
|
||
`api_key`,
|
||
COALESCE(`asr_model_name`, JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.model')), 'paraformer-v2'),
|
||
COALESCE(`asr_vocabulary_id`, JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.vocabulary_id'))),
|
||
COALESCE(`asr_speaker_count`, CAST(JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.speaker_count')) AS UNSIGNED), 10),
|
||
COALESCE(`asr_language_hints`, 'zh, en'),
|
||
COALESCE(`asr_disfluency_removal_enabled`, 1),
|
||
COALESCE(`asr_diarization_enabled`, 1),
|
||
`description`,
|
||
`is_active`,
|
||
`is_default`
|
||
FROM `ai_model_configs`
|
||
WHERE `model_code` = 'audio_model'
|
||
ON DUPLICATE KEY UPDATE
|
||
`model_name` = VALUES(`model_name`),
|
||
`provider` = VALUES(`provider`),
|
||
`endpoint_url` = VALUES(`endpoint_url`),
|
||
`api_key` = VALUES(`api_key`),
|
||
`asr_model_name` = VALUES(`asr_model_name`),
|
||
`asr_vocabulary_id` = VALUES(`asr_vocabulary_id`),
|
||
`asr_speaker_count` = VALUES(`asr_speaker_count`),
|
||
`asr_language_hints` = VALUES(`asr_language_hints`),
|
||
`asr_disfluency_removal_enabled` = VALUES(`asr_disfluency_removal_enabled`),
|
||
`asr_diarization_enabled` = VALUES(`asr_diarization_enabled`),
|
||
`description` = VALUES(`description`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_default` = VALUES(`is_default`);
|
||
|
||
INSERT INTO `audio_model_config`
|
||
(`model_code`, `model_name`, `audio_scene`, `provider`, `endpoint_url`, `api_key`,
|
||
`vp_template_text`, `vp_duration_seconds`, `vp_sample_rate`, `vp_channels`, `vp_max_size_bytes`,
|
||
`description`, `is_active`, `is_default`)
|
||
SELECT
|
||
`model_code`,
|
||
`model_name`,
|
||
'voiceprint',
|
||
`provider`,
|
||
`endpoint_url`,
|
||
`api_key`,
|
||
JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.template_text')),
|
||
CAST(JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.duration_seconds')) AS UNSIGNED),
|
||
CAST(JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.sample_rate')) AS UNSIGNED),
|
||
CAST(JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.channels')) AS UNSIGNED),
|
||
CAST(JSON_UNQUOTE(JSON_EXTRACT(`config_json`, '$.voiceprint_max_size')) AS UNSIGNED),
|
||
`description`,
|
||
`is_active`,
|
||
`is_default`
|
||
FROM `ai_model_configs`
|
||
WHERE `model_code` = 'voiceprint_model'
|
||
ON DUPLICATE KEY UPDATE
|
||
`model_name` = VALUES(`model_name`),
|
||
`provider` = VALUES(`provider`),
|
||
`endpoint_url` = VALUES(`endpoint_url`),
|
||
`api_key` = VALUES(`api_key`),
|
||
`vp_template_text` = VALUES(`vp_template_text`),
|
||
`vp_duration_seconds` = VALUES(`vp_duration_seconds`),
|
||
`vp_sample_rate` = VALUES(`vp_sample_rate`),
|
||
`vp_channels` = VALUES(`vp_channels`),
|
||
`vp_max_size_bytes` = VALUES(`vp_max_size_bytes`),
|
||
`description` = VALUES(`description`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_default` = VALUES(`is_default`);
|
||
|
||
-- Backfill extra_config JSON for audio model configs
|
||
UPDATE `audio_model_config`
|
||
SET `extra_config` = CASE
|
||
WHEN `audio_scene` = 'asr' THEN JSON_OBJECT(
|
||
'model', `asr_model_name`,
|
||
'vocabulary_id', `asr_vocabulary_id`,
|
||
'speaker_count', `asr_speaker_count`,
|
||
'language_hints', `asr_language_hints`,
|
||
'disfluency_removal_enabled', `asr_disfluency_removal_enabled`,
|
||
'diarization_enabled', `asr_diarization_enabled`
|
||
)
|
||
WHEN `audio_scene` = 'voiceprint' THEN JSON_OBJECT(
|
||
'model', `model_name`,
|
||
'template_text', `vp_template_text`,
|
||
'duration_seconds', `vp_duration_seconds`,
|
||
'sample_rate', `vp_sample_rate`,
|
||
'channels', `vp_channels`,
|
||
'max_size_bytes', `vp_max_size_bytes`
|
||
)
|
||
ELSE JSON_OBJECT()
|
||
END
|
||
WHERE `extra_config` IS NULL;
|
||
|
||
-- ----------------------------------------------------------------------
|
||
-- 5. Hot-word migration: old hot_words -> group/item
|
||
-- ----------------------------------------------------------------------
|
||
INSERT INTO `hot_word_group` (`name`, `description`, `status`)
|
||
SELECT '默认热词组', '从旧 hot_words 表迁移的热词', 1
|
||
FROM DUAL
|
||
WHERE EXISTS (SELECT 1 FROM `hot_words` LIMIT 1)
|
||
AND NOT EXISTS (SELECT 1 FROM `hot_word_group` WHERE `name` = '默认热词组');
|
||
|
||
UPDATE `hot_word_group` g
|
||
JOIN (
|
||
SELECT JSON_UNQUOTE(JSON_EXTRACT(`extension_attr`, '$.value')) AS vocab_id
|
||
FROM `sys_dict_data`
|
||
WHERE `dict_type` = 'system_config' AND `dict_code` = 'asr_vocabulary_id'
|
||
LIMIT 1
|
||
) p ON 1 = 1
|
||
SET g.`vocabulary_id` = p.`vocab_id`,
|
||
g.`last_sync_time` = COALESCE(g.`last_sync_time`, NOW())
|
||
WHERE g.`name` = '默认热词组'
|
||
AND (g.`vocabulary_id` IS NULL OR g.`vocabulary_id` = '');
|
||
|
||
INSERT INTO `hot_word_item`
|
||
(`group_id`, `text`, `weight`, `lang`, `status`, `create_time`, `update_time`)
|
||
SELECT
|
||
g.`id`,
|
||
hw.`text`,
|
||
hw.`weight`,
|
||
hw.`lang`,
|
||
hw.`status`,
|
||
hw.`create_time`,
|
||
hw.`update_time`
|
||
FROM `hot_words` hw
|
||
JOIN `hot_word_group` g ON g.`name` = '默认热词组'
|
||
LEFT JOIN `hot_word_item` i
|
||
ON i.`group_id` = g.`id`
|
||
AND i.`text` = hw.`text`
|
||
WHERE i.`id` IS NULL;
|
||
|
||
UPDATE `audio_model_config` a
|
||
JOIN `hot_word_group` g ON g.`name` = '默认热词组'
|
||
SET a.`hot_word_group_id` = g.`id`
|
||
WHERE a.`audio_scene` = 'asr'
|
||
AND a.`hot_word_group_id` IS NULL
|
||
AND a.`asr_vocabulary_id` IS NOT NULL
|
||
AND a.`asr_vocabulary_id` <> '';
|
||
|
||
-- ----------------------------------------------------------------------
|
||
-- 6. Rebuild menu tree for the latest backend
|
||
-- ----------------------------------------------------------------------
|
||
-- Reuse legacy root rows when possible
|
||
SET @has_dashboard := (SELECT COUNT(*) FROM `sys_menus` WHERE `menu_code` = 'dashboard');
|
||
UPDATE `sys_menus`
|
||
SET
|
||
`menu_code` = 'dashboard',
|
||
`menu_name` = 'Dashboard',
|
||
`menu_icon` = 'DashboardOutlined',
|
||
`menu_url` = '/dashboard',
|
||
`menu_type` = 'link',
|
||
`parent_id` = NULL,
|
||
`sort_order` = 1,
|
||
`is_active` = 1,
|
||
`is_visible` = 1,
|
||
`description` = '管理员桌面'
|
||
WHERE `menu_code` = 'account_settings'
|
||
AND @has_dashboard = 0;
|
||
|
||
SET @has_desktop := (SELECT COUNT(*) FROM `sys_menus` WHERE `menu_code` = 'desktop');
|
||
UPDATE `sys_menus`
|
||
SET
|
||
`menu_code` = 'desktop',
|
||
`menu_name` = 'Desktop',
|
||
`menu_icon` = 'DesktopOutlined',
|
||
`menu_url` = '/dashboard',
|
||
`menu_type` = 'link',
|
||
`parent_id` = NULL,
|
||
`sort_order` = 2,
|
||
`is_active` = 1,
|
||
`is_visible` = 1,
|
||
`description` = '普通用户桌面'
|
||
WHERE `menu_code` = 'logout'
|
||
AND @has_desktop = 0;
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
VALUES
|
||
('dashboard', 'Dashboard', 'DashboardOutlined', '/dashboard', 'link', NULL, 1, NULL, 1, 1, 1, '管理员桌面')
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
VALUES
|
||
('desktop', 'Desktop', 'DesktopOutlined', '/dashboard', 'link', NULL, 1, NULL, 2, 1, 1, '普通用户桌面')
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
VALUES
|
||
('platform_admin', '平台管理', 'Shield', '/admin/management/hot-word-management', 'link', NULL, 1, NULL, 3, 1, 1, '平台管理员后台'),
|
||
('system_management', '系统管理', 'Setting', '/admin/management/user-management', 'link', NULL, 1, NULL, 4, 1, 1, '系统基础配置管理(用户、权限、字典、参数)'),
|
||
('meeting_manage', '会议管理', 'CalendarOutlined', '/meetings/center', 'link', NULL, 1, NULL, 2, 1, 1, '普通用户会议菜单')
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'prompt_management', '提示词库', 'BookText', '/prompt-management', 'link',
|
||
p.`menu_id`, 2, NULL, 3, 1, 1, '管理AI提示词模版'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'platform_admin'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'hot_word_management', '热词管理', 'Text', '/admin/management/hot-word-management', 'link',
|
||
p.`menu_id`, 2, NULL, 1, 1, 1, 'ASR 热词与同步'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'platform_admin'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'model_management', '模型管理', 'Appstore', '/admin/management/model-management', 'link',
|
||
p.`menu_id`, 2, NULL, 2, 1, 1, '音频/LLM模型配置管理'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'platform_admin'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'client_management', '客户端管理', 'Smartphone', '/admin/management/client-management', 'link',
|
||
p.`menu_id`, 2, NULL, 5, 1, 1, '版本、下载地址、发布状态'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'platform_admin'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'external_app_management', '外部应用管理', 'AppWindow', '/admin/management/external-app-management', 'link',
|
||
p.`menu_id`, 2, NULL, 6, 1, 1, '外部系统入口与图标配置'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'platform_admin'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'terminal_management', '终端管理', 'Monitor', '/admin/management/terminal-management', 'link',
|
||
p.`menu_id`, 2, NULL, 7, 1, 1, '专用设备、激活和绑定状态'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'platform_admin'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'user_management', '用户管理', 'Users', '/admin/management/user-management', 'link',
|
||
p.`menu_id`, 2, NULL, 1, 1, 1, '账号、角色、密码重置'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'system_management'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'permission_management', '权限管理', 'KeyRound', '/admin/management/permission-management', 'link',
|
||
p.`menu_id`, 2, NULL, 2, 1, 1, '菜单与角色授权矩阵'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'system_management'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'dict_management', '字典管理', 'BookMarked', '/admin/management/dict-management', 'link',
|
||
p.`menu_id`, 2, NULL, 3, 1, 1, '码表、平台类型、扩展属性'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'system_management'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'parameter_management', '参数管理', 'Setting', '/admin/management/parameter-management', 'link',
|
||
p.`menu_id`, 2, NULL, 8, 1, 1, '系统参数管理'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'system_management'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'permission_menu_tree', '菜单树维护', 'AppstoreAdd', '/admin/management/permission-management', 'link',
|
||
p.`menu_id`, 3, NULL, 20, 1, 0, '权限管理中的菜单树维护入口(隐藏于侧栏)'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'permission_management'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'meeting_center', '会议中心', 'CalendarOutlined', '/meetings/center', 'link',
|
||
p.`menu_id`, 2, NULL, 1, 1, 1, '普通用户会议中心'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'meeting_manage'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'prompt_config', '提示词配置', 'Book', '/prompt-config', 'link',
|
||
p.`menu_id`, 2, NULL, 2, 1, 1, '用户可配置启用提示词与排序'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'meeting_manage'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
INSERT INTO `sys_menus`
|
||
(`menu_code`, `menu_name`, `menu_icon`, `menu_url`, `menu_type`, `parent_id`, `menu_level`, `tree_path`, `sort_order`, `is_active`, `is_visible`, `description`)
|
||
SELECT
|
||
'personal_prompt_library', '个人提示词仓库', 'ReadOutlined', '/personal-prompts', 'link',
|
||
p.`menu_id`, 2, NULL, 3, 0, 1, '普通用户个人提示词仓库'
|
||
FROM `sys_menus` p
|
||
WHERE p.`menu_code` = 'meeting_manage'
|
||
ON DUPLICATE KEY UPDATE
|
||
`menu_name` = VALUES(`menu_name`),
|
||
`menu_icon` = VALUES(`menu_icon`),
|
||
`menu_url` = VALUES(`menu_url`),
|
||
`menu_type` = VALUES(`menu_type`),
|
||
`parent_id` = VALUES(`parent_id`),
|
||
`sort_order` = VALUES(`sort_order`),
|
||
`is_active` = VALUES(`is_active`),
|
||
`is_visible` = VALUES(`is_visible`),
|
||
`description` = VALUES(`description`);
|
||
|
||
-- Menu tree metadata (supports current depth 3)
|
||
UPDATE `sys_menus`
|
||
SET `menu_level` = 1,
|
||
`tree_path` = CONCAT('/', `menu_id`)
|
||
WHERE `parent_id` IS NULL;
|
||
|
||
UPDATE `sys_menus` c
|
||
JOIN `sys_menus` p ON c.`parent_id` = p.`menu_id`
|
||
SET c.`menu_level` = p.`menu_level` + 1,
|
||
c.`tree_path` = CONCAT(p.`tree_path`, '/', c.`menu_id`);
|
||
|
||
UPDATE `sys_menus` c
|
||
JOIN `sys_menus` p ON c.`parent_id` = p.`menu_id`
|
||
SET c.`menu_level` = p.`menu_level` + 1,
|
||
c.`tree_path` = CONCAT(p.`tree_path`, '/', c.`menu_id`);
|
||
|
||
-- ----------------------------------------------------------------------
|
||
-- 7. Align role-menu permissions for latest menu model
|
||
-- ----------------------------------------------------------------------
|
||
-- Keep existing role-menu permissions unchanged.
|
||
-- The upgrade must preserve current grants instead of rebuilding defaults,
|
||
-- so repeated execution will not auto-complete or reset menu permissions.
|
||
|
||
-- ----------------------------------------------------------------------
|
||
-- 8. Recreate compatibility views
|
||
-- ----------------------------------------------------------------------
|
||
DROP VIEW IF EXISTS `users`;
|
||
DROP VIEW IF EXISTS `roles`;
|
||
DROP VIEW IF EXISTS `menus`;
|
||
DROP VIEW IF EXISTS `role_menu_permissions`;
|
||
DROP VIEW IF EXISTS `dict_data`;
|
||
DROP VIEW IF EXISTS `system_parameters`;
|
||
|
||
CREATE VIEW `users` AS SELECT * FROM `sys_users`;
|
||
CREATE VIEW `roles` AS SELECT * FROM `sys_roles`;
|
||
CREATE VIEW `menus` AS SELECT * FROM `sys_menus`;
|
||
CREATE VIEW `role_menu_permissions` AS SELECT * FROM `sys_role_menu_permissions`;
|
||
CREATE VIEW `dict_data` AS SELECT * FROM `sys_dict_data`;
|
||
CREATE VIEW `system_parameters` AS SELECT * FROM `sys_system_parameters`;
|