init system

codex/dev
mula.liu 2026-04-13 14:55:33 +08:00
parent e71bd889b1
commit 60b4c1f3a6
7 changed files with 1448 additions and 766 deletions

7
.gitignore vendored
View File

@ -29,7 +29,11 @@ backend/uploads/
backend/logs/
backend/venv/
backend/test/
backend/sql/
# Only keep the latest full-deploy SQL entrypoints in repo
backend/sql/*
!backend/sql/imeeting-schema-latest.sql
!backend/sql/imeeting-seed-latest.sql
backend/sql/migrations/
backend/scripts/
资料/
@ -150,4 +154,3 @@ lerna-debug.log*
.pnp.*
pids/
logs/

View File

@ -0,0 +1,643 @@
-- iMeeting latest schema initialization script
-- 用途:
-- 1. 面向当前最新代码结构的全新部署
-- 2. 不再兼容或保留旧 users / roles / menus 等历史结构
-- 3. 仅负责建表,不写入基础角色/用户/菜单/参数等种子数据
-- 4. 本文件即为全量建表入口,无需执行历史 migrations 目录脚本
--
-- 执行顺序:
-- 1. 先执行本文件
-- 2. 再执行 imeeting-seed-latest.sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- 兼容旧迁移中创建的 legacy 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`;
-- 清理旧结构与当前结构
DROP TABLE IF EXISTS `sys_role_menu_permissions`;
DROP TABLE IF EXISTS `prompt_config`;
DROP TABLE IF EXISTS `sys_user_mcp`;
DROP TABLE IF EXISTS `user_logs`;
DROP TABLE IF EXISTS `user_voiceprint`;
DROP TABLE IF EXISTS `client_downloads`;
DROP TABLE IF EXISTS `external_apps`;
DROP TABLE IF EXISTS `terminals`;
DROP TABLE IF EXISTS `knowledge_base_tasks`;
DROP TABLE IF EXISTS `knowledge_bases`;
DROP TABLE IF EXISTS `llm_tasks`;
DROP TABLE IF EXISTS `transcript_segments`;
DROP TABLE IF EXISTS `transcript_tasks`;
DROP TABLE IF EXISTS `audio_files`;
DROP TABLE IF EXISTS `attachments`;
DROP TABLE IF EXISTS `attendees`;
DROP TABLE IF EXISTS `meetings`;
DROP TABLE IF EXISTS `tags`;
DROP TABLE IF EXISTS `prompts`;
DROP TABLE IF EXISTS `audio_model_config`;
DROP TABLE IF EXISTS `llm_model_config`;
DROP TABLE IF EXISTS `hot_word_item`;
DROP TABLE IF EXISTS `hot_word_group`;
DROP TABLE IF EXISTS `sys_system_parameters`;
DROP TABLE IF EXISTS `sys_dict_data`;
DROP TABLE IF EXISTS `sys_menus`;
DROP TABLE IF EXISTS `sys_users`;
DROP TABLE IF EXISTS `sys_roles`;
-- 历史阶段遗留表,一并清理
DROP TABLE IF EXISTS `meeting_summaries`;
DROP TABLE IF EXISTS `sys_user_prompt_config`;
DROP TABLE IF EXISTS `ai_model_configs`;
DROP TABLE IF EXISTS `ai_model_config`;
DROP TABLE IF EXISTS `llm_model_configs`;
DROP TABLE IF EXISTS `audio_model_configs`;
DROP TABLE IF EXISTS `hot_words`;
DROP TABLE IF EXISTS `system_parameters`;
DROP TABLE IF EXISTS `dict_data`;
DROP TABLE IF EXISTS `role_menu_permissions`;
DROP TABLE IF EXISTS `menus`;
DROP TABLE IF EXISTS `users`;
DROP TABLE IF EXISTS `roles`;
SET FOREIGN_KEY_CHECKS = 1;
-- =====================================================================
-- 1. 基础系统表
-- =====================================================================
CREATE TABLE `sys_roles` (
`role_id` INT NOT NULL AUTO_INCREMENT,
`role_name` VARCHAR(50) NOT NULL COMMENT '角色名称',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`role_id`),
UNIQUE KEY `uk_sys_roles_name` (`role_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统角色表';
CREATE TABLE `sys_users` (
`user_id` INT NOT NULL AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL COMMENT '登录账号',
`caption` VARCHAR(50) NOT NULL COMMENT '显示名称',
`email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱,可为空',
`avatar_url` VARCHAR(255) DEFAULT NULL COMMENT '头像地址',
`password_hash` VARCHAR(255) NOT NULL COMMENT '密码哈希',
`role_id` INT NOT NULL DEFAULT 2 COMMENT '角色ID',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`user_id`),
UNIQUE KEY `uk_sys_users_username` (`username`),
UNIQUE KEY `uk_sys_users_email` (`email`),
KEY `idx_sys_users_role_id` (`role_id`),
KEY `idx_sys_users_created_at` (`created_at`),
CONSTRAINT `fk_sys_users_role_id`
FOREIGN KEY (`role_id`) REFERENCES `sys_roles` (`role_id`)
ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统用户表';
CREATE TABLE `sys_menus` (
`menu_id` INT NOT NULL AUTO_INCREMENT,
`menu_code` VARCHAR(50) NOT NULL COMMENT '菜单编码',
`menu_name` VARCHAR(100) NOT NULL COMMENT '菜单名称',
`menu_icon` VARCHAR(100) DEFAULT NULL COMMENT '菜单图标',
`menu_url` VARCHAR(255) DEFAULT NULL COMMENT '前端路由',
`menu_type` ENUM('action', 'link', 'divider') NOT NULL DEFAULT 'link' COMMENT '菜单类型',
`parent_id` INT DEFAULT NULL COMMENT '父菜单ID',
`menu_level` TINYINT NOT NULL DEFAULT 1 COMMENT '菜单层级根节点为1',
`tree_path` VARCHAR(255) DEFAULT NULL COMMENT '树路径(如 /1/5',
`sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序号',
`is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
`is_visible` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否在侧边栏显示',
`description` VARCHAR(255) DEFAULT NULL COMMENT '菜单说明',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`menu_id`),
UNIQUE KEY `uk_sys_menus_code` (`menu_code`),
KEY `idx_sys_menus_parent_id` (`parent_id`),
KEY `idx_sys_menus_menu_level` (`menu_level`),
KEY `idx_sys_menus_tree_path` (`tree_path`),
KEY `idx_sys_menus_is_active` (`is_active`),
KEY `idx_sys_menus_is_visible` (`is_visible`),
CONSTRAINT `fk_sys_menus_parent_id`
FOREIGN KEY (`parent_id`) REFERENCES `sys_menus` (`menu_id`)
ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统菜单表';
CREATE TABLE `sys_dict_data` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`dict_type` VARCHAR(64) NOT NULL DEFAULT 'client_platform' COMMENT '字典类型',
`dict_code` VARCHAR(64) NOT NULL COMMENT '业务编码',
`parent_code` VARCHAR(64) NOT NULL DEFAULT 'ROOT' COMMENT '父级编码',
`tree_path` VARCHAR(255) DEFAULT NULL COMMENT '树路径',
`label_cn` VARCHAR(128) NOT NULL COMMENT '中文名称',
`label_en` VARCHAR(128) DEFAULT NULL COMMENT '英文名称',
`sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序',
`extension_attr` LONGTEXT DEFAULT NULL COMMENT '扩展属性(JSON字符串)',
`is_default` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否默认',
`status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '状态',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sys_dict_data_type_code` (`dict_type`, `dict_code`),
KEY `idx_sys_dict_data_type_parent` (`dict_type`, `parent_code`),
KEY `idx_sys_dict_data_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统字典数据表';
CREATE TABLE `sys_system_parameters` (
`param_id` BIGINT NOT NULL AUTO_INCREMENT,
`param_key` VARCHAR(128) NOT NULL COMMENT '参数键',
`param_name` VARCHAR(255) NOT NULL COMMENT '参数名称',
`param_value` TEXT DEFAULT NULL COMMENT '参数值',
`value_type` VARCHAR(32) NOT NULL DEFAULT 'string' COMMENT '值类型',
`category` VARCHAR(64) NOT NULL DEFAULT 'system' COMMENT '参数分类',
`description` VARCHAR(500) DEFAULT NULL COMMENT '参数说明',
`is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`param_id`),
UNIQUE KEY `uk_sys_system_parameters_key` (`param_key`),
KEY `idx_sys_system_parameters_category` (`category`),
KEY `idx_sys_system_parameters_active` (`is_active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统参数表';
CREATE TABLE `hot_word_group` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL COMMENT '热词组名称',
`description` VARCHAR(500) DEFAULT NULL COMMENT '描述',
`vocabulary_id` VARCHAR(255) DEFAULT NULL COMMENT '阿里云词表ID',
`last_sync_time` DATETIME DEFAULT NULL COMMENT '最后同步时间',
`status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '状态',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hot_word_group_name` (`name`),
KEY `idx_hot_word_group_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='热词组主表';
CREATE TABLE `llm_model_config` (
`config_id` BIGINT NOT NULL AUTO_INCREMENT,
`model_code` VARCHAR(128) NOT NULL COMMENT '模型编码',
`model_name` VARCHAR(255) NOT NULL COMMENT '模型名称',
`provider` VARCHAR(64) DEFAULT NULL COMMENT '供应商',
`endpoint_url` VARCHAR(512) DEFAULT NULL COMMENT '模型接口地址',
`api_key` VARCHAR(512) DEFAULT NULL COMMENT '接口密钥',
`llm_model_name` VARCHAR(128) NOT NULL COMMENT '供应商模型名',
`llm_timeout` INT NOT NULL DEFAULT 120 COMMENT '超时时间(秒)',
`llm_temperature` DECIMAL(5,2) NOT NULL DEFAULT 0.70 COMMENT 'temperature',
`llm_top_p` DECIMAL(5,2) NOT NULL DEFAULT 0.90 COMMENT 'top_p',
`llm_max_tokens` INT NOT NULL DEFAULT 2048 COMMENT '最大token数',
`llm_system_prompt` TEXT DEFAULT NULL COMMENT '系统提示词',
`description` VARCHAR(500) DEFAULT NULL COMMENT '说明',
`is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
`is_default` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否默认',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`config_id`),
UNIQUE KEY `uk_llm_model_config_code` (`model_code`),
KEY `idx_llm_model_config_active` (`is_active`),
KEY `idx_llm_model_config_default` (`is_default`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='LLM模型配置表';
CREATE TABLE `audio_model_config` (
`config_id` BIGINT NOT NULL AUTO_INCREMENT,
`model_code` VARCHAR(128) NOT NULL COMMENT '模型编码',
`model_name` VARCHAR(255) NOT NULL COMMENT '模型名称',
`audio_scene` VARCHAR(32) NOT NULL COMMENT 'asr / voiceprint',
`provider` VARCHAR(64) DEFAULT NULL COMMENT '供应商',
`endpoint_url` VARCHAR(512) DEFAULT NULL COMMENT '接口地址',
`api_key` VARCHAR(512) DEFAULT NULL COMMENT '接口密钥',
`request_timeout_seconds` INT NOT NULL DEFAULT 300 COMMENT '请求超时(秒)',
`hot_word_group_id` INT DEFAULT NULL COMMENT '关联热词组',
`extra_config` JSON DEFAULT NULL COMMENT '音频模型差异化配置',
`description` VARCHAR(500) DEFAULT NULL COMMENT '说明',
`is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
`is_default` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否默认',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`config_id`),
UNIQUE KEY `uk_audio_model_config_code` (`model_code`),
KEY `idx_audio_model_config_scene` (`audio_scene`),
KEY `idx_audio_model_config_active` (`is_active`),
KEY `idx_audio_model_config_default` (`is_default`),
KEY `idx_audio_model_config_hot_word_group_id` (`hot_word_group_id`),
CONSTRAINT `fk_audio_model_config_hot_word_group_id`
FOREIGN KEY (`hot_word_group_id`) REFERENCES `hot_word_group` (`id`)
ON DELETE SET NULL ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='音频模型配置表';
CREATE TABLE `hot_word_item` (
`id` INT NOT NULL AUTO_INCREMENT,
`group_id` INT NOT NULL COMMENT '热词组ID',
`text` VARCHAR(255) NOT NULL COMMENT '热词内容',
`weight` INT NOT NULL DEFAULT 4 COMMENT '权重',
`lang` VARCHAR(20) NOT NULL DEFAULT 'zh' COMMENT '语言',
`status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '状态',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hot_word_item_group_text` (`group_id`, `text`),
KEY `idx_hot_word_item_group_id` (`group_id`),
KEY `idx_hot_word_item_status` (`status`),
CONSTRAINT `fk_hot_word_item_group_id`
FOREIGN KEY (`group_id`) REFERENCES `hot_word_group` (`id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='热词条目表';
CREATE TABLE `prompts` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL COMMENT '提示词名称',
`task_type` ENUM('MEETING_TASK', 'KNOWLEDGE_TASK') NOT NULL COMMENT '任务类型',
`content` LONGTEXT NOT NULL COMMENT '提示词内容',
`desc` VARCHAR(500) DEFAULT NULL COMMENT '模版简介',
`is_default` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否默认',
`is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
`creator_id` INT NOT NULL COMMENT '创建者',
`is_system` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否系统模版',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `idx_prompts_creator_id` (`creator_id`),
KEY `idx_prompts_task_scope_active` (`task_type`, `is_system`, `creator_id`, `is_active`, `is_default`),
CONSTRAINT `fk_prompts_creator_id`
FOREIGN KEY (`creator_id`) REFERENCES `sys_users` (`user_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='提示词模版表';
CREATE TABLE `prompt_config` (
`config_id` BIGINT NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL COMMENT '用户ID',
`task_type` ENUM('MEETING_TASK', 'KNOWLEDGE_TASK') NOT NULL COMMENT '任务类型',
`prompt_id` INT NOT NULL COMMENT '模版ID',
`is_enabled` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
`sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`config_id`),
UNIQUE KEY `uk_prompt_config_user_task_prompt` (`user_id`, `task_type`, `prompt_id`),
KEY `idx_prompt_config_user_task_order` (`user_id`, `task_type`, `sort_order`),
KEY `idx_prompt_config_prompt_id` (`prompt_id`),
CONSTRAINT `fk_prompt_config_user_id`
FOREIGN KEY (`user_id`) REFERENCES `sys_users` (`user_id`)
ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT `fk_prompt_config_prompt_id`
FOREIGN KEY (`prompt_id`) REFERENCES `prompts` (`id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户提示词配置表';
CREATE TABLE `sys_role_menu_permissions` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`role_id` INT NOT NULL COMMENT '角色ID',
`menu_id` INT NOT NULL COMMENT '菜单ID',
`granted_by` INT DEFAULT NULL COMMENT '授权人ID',
`granted_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '授权时间',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sys_role_menu_permissions_role_menu` (`role_id`, `menu_id`),
KEY `idx_sys_role_menu_permissions_role_id` (`role_id`),
KEY `idx_sys_role_menu_permissions_menu_id` (`menu_id`),
KEY `idx_sys_role_menu_permissions_granted_by` (`granted_by`),
KEY `idx_sys_role_menu_permissions_granted_at` (`granted_at`),
CONSTRAINT `fk_sys_role_menu_permissions_role_id`
FOREIGN KEY (`role_id`) REFERENCES `sys_roles` (`role_id`)
ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT `fk_sys_role_menu_permissions_menu_id`
FOREIGN KEY (`menu_id`) REFERENCES `sys_menus` (`menu_id`)
ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT `fk_sys_role_menu_permissions_granted_by`
FOREIGN KEY (`granted_by`) REFERENCES `sys_users` (`user_id`)
ON DELETE SET NULL ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色菜单授权表';
CREATE TABLE `sys_user_mcp` (
`id` INT NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL COMMENT '用户ID',
`bot_id` VARCHAR(64) NOT NULL COMMENT '机器人ID',
`bot_secret` VARCHAR(128) NOT NULL COMMENT '机器人密钥',
`status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '状态',
`last_used_at` DATETIME DEFAULT NULL COMMENT '最后使用时间',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
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_id`
FOREIGN KEY (`user_id`) REFERENCES `sys_users` (`user_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户MCP接入凭证表';
-- =====================================================================
-- 2. 业务表
-- =====================================================================
CREATE TABLE `tags` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL COMMENT '标签名称',
`color` VARCHAR(7) NOT NULL DEFAULT '#409EFF' COMMENT '标签颜色',
`creator_id` INT DEFAULT NULL COMMENT '创建人',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tags_name` (`name`),
KEY `idx_tags_creator_id` (`creator_id`),
CONSTRAINT `fk_tags_creator_id`
FOREIGN KEY (`creator_id`) REFERENCES `sys_users` (`user_id`)
ON DELETE SET NULL ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='标签表';
CREATE TABLE `meetings` (
`meeting_id` INT NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL COMMENT '创建人',
`title` VARCHAR(255) NOT NULL COMMENT '会议标题',
`tags` VARCHAR(255) DEFAULT NULL COMMENT '逗号分隔标签',
`meeting_time` DATETIME DEFAULT NULL COMMENT '会议时间',
`access_password` VARCHAR(32) DEFAULT NULL COMMENT '访问密码',
`prompt_id` INT DEFAULT 0 COMMENT '选用提示词ID0表示未指定',
`user_prompt` TEXT DEFAULT NULL COMMENT '用户额外提示',
`summary` LONGTEXT DEFAULT NULL COMMENT '会议总结',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`meeting_id`),
KEY `idx_meetings_user_id` (`user_id`),
KEY `idx_meetings_meeting_time` (`meeting_time`),
KEY `idx_meetings_created_at` (`created_at`),
KEY `idx_meetings_prompt_id` (`prompt_id`),
CONSTRAINT `fk_meetings_user_id`
FOREIGN KEY (`user_id`) REFERENCES `sys_users` (`user_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='会议表';
CREATE TABLE `attendees` (
`attendee_id` INT NOT NULL AUTO_INCREMENT,
`meeting_id` INT NOT NULL COMMENT '会议ID',
`user_id` INT NOT NULL COMMENT '参会用户ID',
PRIMARY KEY (`attendee_id`),
UNIQUE KEY `uk_attendees_meeting_user` (`meeting_id`, `user_id`),
KEY `idx_attendees_meeting_id` (`meeting_id`),
KEY `idx_attendees_user_id` (`user_id`),
CONSTRAINT `fk_attendees_meeting_id`
FOREIGN KEY (`meeting_id`) REFERENCES `meetings` (`meeting_id`)
ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT `fk_attendees_user_id`
FOREIGN KEY (`user_id`) REFERENCES `sys_users` (`user_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='会议参会人表';
CREATE TABLE `attachments` (
`attachment_id` INT NOT NULL AUTO_INCREMENT,
`meeting_id` INT NOT NULL COMMENT '会议ID',
`file_name` VARCHAR(255) NOT NULL COMMENT '文件名',
`file_path` VARCHAR(512) NOT NULL COMMENT '文件路径',
`file_type` VARCHAR(100) DEFAULT NULL COMMENT '文件类型',
`uploaded_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上传时间',
PRIMARY KEY (`attachment_id`),
KEY `idx_attachments_meeting_id` (`meeting_id`),
CONSTRAINT `fk_attachments_meeting_id`
FOREIGN KEY (`meeting_id`) REFERENCES `meetings` (`meeting_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='会议附件表';
CREATE TABLE `audio_files` (
`audio_id` INT NOT NULL AUTO_INCREMENT,
`meeting_id` INT NOT NULL COMMENT '会议ID',
`file_path` VARCHAR(512) NOT NULL COMMENT '音频相对路径',
`file_name` VARCHAR(255) DEFAULT NULL COMMENT '原始文件名',
`file_size` BIGINT DEFAULT NULL COMMENT '文件大小(字节)',
`duration` DECIMAL(10,2) DEFAULT NULL COMMENT '音频时长(秒)',
`upload_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上传时间',
`processing_status` VARCHAR(20) NOT NULL DEFAULT 'uploaded' COMMENT '处理状态',
`error_message` TEXT DEFAULT NULL COMMENT '错误信息',
`task_id` VARCHAR(255) DEFAULT NULL COMMENT '最新转写任务ID',
PRIMARY KEY (`audio_id`),
UNIQUE KEY `uk_audio_files_meeting_id` (`meeting_id`),
KEY `idx_audio_files_task_id` (`task_id`),
KEY `idx_audio_files_processing_status` (`processing_status`),
CONSTRAINT `fk_audio_files_meeting_id`
FOREIGN KEY (`meeting_id`) REFERENCES `meetings` (`meeting_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='会议音频表';
CREATE TABLE `transcript_tasks` (
`task_id` VARCHAR(100) NOT NULL COMMENT '业务任务ID',
`paraformer_task_id` VARCHAR(100) DEFAULT NULL COMMENT '云端任务ID',
`meeting_id` INT NOT NULL COMMENT '会议ID',
`status` ENUM('pending', 'processing', 'completed', 'failed') NOT NULL DEFAULT 'pending' COMMENT '任务状态',
`progress` INT NOT NULL DEFAULT 0 COMMENT '任务进度',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`completed_at` DATETIME DEFAULT NULL COMMENT '完成时间',
`error_message` TEXT DEFAULT NULL COMMENT '错误信息',
PRIMARY KEY (`task_id`),
KEY `idx_transcript_tasks_meeting_id` (`meeting_id`),
KEY `idx_transcript_tasks_status` (`status`),
KEY `idx_transcript_tasks_created_at` (`created_at`),
KEY `idx_transcript_tasks_paraformer_task_id` (`paraformer_task_id`),
CONSTRAINT `fk_transcript_tasks_meeting_id`
FOREIGN KEY (`meeting_id`) REFERENCES `meetings` (`meeting_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='转写任务表';
CREATE TABLE `transcript_segments` (
`segment_id` BIGINT NOT NULL AUTO_INCREMENT,
`meeting_id` INT NOT NULL COMMENT '会议ID',
`speaker_id` INT NOT NULL DEFAULT 0 COMMENT '说话人编号',
`speaker_tag` VARCHAR(50) DEFAULT NULL COMMENT '说话人标签',
`start_time_ms` INT NOT NULL COMMENT '开始时间(毫秒)',
`end_time_ms` INT NOT NULL COMMENT '结束时间(毫秒)',
`text_content` LONGTEXT NOT NULL COMMENT '转写文本',
PRIMARY KEY (`segment_id`),
KEY `idx_transcript_segments_meeting_id` (`meeting_id`),
KEY `idx_transcript_segments_speaker_id` (`speaker_id`),
KEY `idx_transcript_segments_start_time_ms` (`start_time_ms`),
CONSTRAINT `fk_transcript_segments_meeting_id`
FOREIGN KEY (`meeting_id`) REFERENCES `meetings` (`meeting_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='转写分段表';
CREATE TABLE `llm_tasks` (
`task_id` VARCHAR(100) NOT NULL COMMENT '总结任务ID',
`meeting_id` INT NOT NULL COMMENT '会议ID',
`user_prompt` TEXT DEFAULT NULL COMMENT '用户额外提示',
`prompt_id` INT DEFAULT NULL COMMENT '使用的模版ID',
`model_code` VARCHAR(128) DEFAULT NULL COMMENT '使用的模型编码',
`status` ENUM('pending', 'processing', 'completed', 'failed') NOT NULL DEFAULT 'pending' COMMENT '任务状态',
`progress` INT NOT NULL DEFAULT 0 COMMENT '任务进度',
`result` LONGTEXT DEFAULT NULL COMMENT '总结结果',
`error_message` TEXT DEFAULT NULL COMMENT '错误信息',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`completed_at` DATETIME DEFAULT NULL COMMENT '完成时间',
PRIMARY KEY (`task_id`),
KEY `idx_llm_tasks_meeting_id` (`meeting_id`),
KEY `idx_llm_tasks_status` (`status`),
KEY `idx_llm_tasks_created_at` (`created_at`),
KEY `idx_llm_tasks_prompt_id` (`prompt_id`),
KEY `idx_llm_tasks_model_code` (`model_code`),
CONSTRAINT `fk_llm_tasks_meeting_id`
FOREIGN KEY (`meeting_id`) REFERENCES `meetings` (`meeting_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='会议总结任务表';
CREATE TABLE `knowledge_bases` (
`kb_id` INT NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOT NULL COMMENT '知识标题',
`prompt_id` INT DEFAULT 0 COMMENT '使用的模版ID',
`user_prompt` TEXT DEFAULT NULL COMMENT '用户额外提示',
`content` LONGTEXT DEFAULT NULL COMMENT '知识内容',
`creator_id` INT NOT NULL COMMENT '创建人',
`is_shared` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否共享',
`source_meeting_ids` VARCHAR(255) DEFAULT NULL COMMENT '来源会议ID列表',
`tags` VARCHAR(255) DEFAULT NULL COMMENT '标签',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`kb_id`),
KEY `idx_knowledge_bases_creator_id` (`creator_id`),
KEY `idx_knowledge_bases_prompt_id` (`prompt_id`),
KEY `idx_knowledge_bases_updated_at` (`updated_at`),
KEY `idx_knowledge_bases_is_shared` (`is_shared`),
CONSTRAINT `fk_knowledge_bases_creator_id`
FOREIGN KEY (`creator_id`) REFERENCES `sys_users` (`user_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='知识库表';
CREATE TABLE `knowledge_base_tasks` (
`task_id` VARCHAR(100) NOT NULL COMMENT '知识库任务ID',
`user_id` INT NOT NULL COMMENT '发起人',
`kb_id` INT NOT NULL COMMENT '知识库ID',
`prompt_id` INT DEFAULT NULL COMMENT '使用的模版ID',
`user_prompt` TEXT DEFAULT NULL COMMENT '用户额外提示',
`status` ENUM('pending', 'processing', 'completed', 'failed') NOT NULL DEFAULT 'pending' COMMENT '任务状态',
`progress` INT NOT NULL DEFAULT 0 COMMENT '任务进度',
`error_message` TEXT DEFAULT NULL COMMENT '错误信息',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`completed_at` DATETIME DEFAULT NULL COMMENT '完成时间',
PRIMARY KEY (`task_id`),
KEY `idx_knowledge_base_tasks_user_id` (`user_id`),
KEY `idx_knowledge_base_tasks_kb_id` (`kb_id`),
KEY `idx_knowledge_base_tasks_status` (`status`),
KEY `idx_knowledge_base_tasks_created_at` (`created_at`),
CONSTRAINT `fk_knowledge_base_tasks_user_id`
FOREIGN KEY (`user_id`) REFERENCES `sys_users` (`user_id`)
ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT `fk_knowledge_base_tasks_kb_id`
FOREIGN KEY (`kb_id`) REFERENCES `knowledge_bases` (`kb_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='知识库生成任务表';
CREATE TABLE `client_downloads` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`platform_type` VARCHAR(50) DEFAULT NULL COMMENT '平台类型(兼容字段)',
`platform_name` VARCHAR(50) DEFAULT NULL COMMENT '平台名称(兼容字段)',
`platform_code` VARCHAR(64) NOT NULL COMMENT '平台编码',
`version` VARCHAR(50) NOT NULL COMMENT '版本号',
`version_code` INT NOT NULL COMMENT '版本序号',
`download_url` VARCHAR(512) NOT NULL COMMENT '下载地址',
`file_size` BIGINT DEFAULT NULL COMMENT '文件大小',
`release_notes` TEXT DEFAULT NULL COMMENT '更新说明',
`is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
`is_latest` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否最新',
`min_system_version` VARCHAR(50) DEFAULT NULL COMMENT '最低系统版本',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`created_by` INT DEFAULT NULL COMMENT '创建人',
PRIMARY KEY (`id`),
KEY `idx_client_downloads_platform_code` (`platform_code`),
KEY `idx_client_downloads_platform_type_name` (`platform_type`, `platform_name`),
KEY `idx_client_downloads_is_latest` (`is_latest`),
KEY `idx_client_downloads_is_active` (`is_active`),
KEY `idx_client_downloads_platform_code_version` (`platform_code`, `version_code`),
CONSTRAINT `fk_client_downloads_created_by`
FOREIGN KEY (`created_by`) REFERENCES `sys_users` (`user_id`)
ON DELETE SET NULL ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户端下载管理表';
CREATE TABLE `external_apps` (
`id` INT NOT NULL AUTO_INCREMENT,
`app_name` VARCHAR(100) NOT NULL COMMENT '应用名称',
`app_type` ENUM('native', 'web') NOT NULL COMMENT '应用类型',
`app_info` TEXT DEFAULT NULL COMMENT '应用信息(JSON字符串)',
`icon_url` TEXT DEFAULT NULL COMMENT '图标地址',
`description` TEXT DEFAULT NULL COMMENT '应用说明',
`sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序',
`is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`created_by` INT DEFAULT NULL COMMENT '创建人',
PRIMARY KEY (`id`),
KEY `idx_external_apps_type` (`app_type`),
KEY `idx_external_apps_active` (`is_active`),
KEY `idx_external_apps_sort_order` (`sort_order`),
KEY `idx_external_apps_type_active` (`app_type`, `is_active`),
CONSTRAINT `fk_external_apps_created_by`
FOREIGN KEY (`created_by`) REFERENCES `sys_users` (`user_id`)
ON DELETE SET NULL ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='外部应用管理表';
CREATE TABLE `terminals` (
`id` INT NOT NULL AUTO_INCREMENT,
`imei` VARCHAR(64) NOT NULL COMMENT '终端唯一标识',
`terminal_name` VARCHAR(100) DEFAULT NULL COMMENT '终端名称',
`terminal_type` VARCHAR(50) NOT NULL COMMENT '终端类型编码',
`description` VARCHAR(500) DEFAULT NULL COMMENT '说明',
`status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '启用状态',
`is_activated` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '激活状态',
`activated_at` DATETIME DEFAULT NULL COMMENT '激活时间',
`firmware_version` VARCHAR(50) DEFAULT NULL COMMENT '固件版本',
`last_online_at` DATETIME DEFAULT NULL COMMENT '最后在线时间',
`ip_address` VARCHAR(50) DEFAULT NULL COMMENT '最近在线IP',
`mac_address` VARCHAR(64) DEFAULT NULL COMMENT 'MAC地址',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`created_by` INT DEFAULT NULL COMMENT '创建人',
`current_user_id` INT DEFAULT NULL COMMENT '当前绑定用户',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_terminals_imei` (`imei`),
KEY `idx_terminals_terminal_type` (`terminal_type`),
KEY `idx_terminals_status` (`status`),
KEY `idx_terminals_created_by` (`created_by`),
KEY `idx_terminals_current_user_id` (`current_user_id`),
KEY `idx_terminals_last_online_at` (`last_online_at`),
CONSTRAINT `fk_terminals_created_by`
FOREIGN KEY (`created_by`) REFERENCES `sys_users` (`user_id`)
ON DELETE SET NULL ON UPDATE RESTRICT,
CONSTRAINT `fk_terminals_current_user_id`
FOREIGN KEY (`current_user_id`) REFERENCES `sys_users` (`user_id`)
ON DELETE SET NULL ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='专用终端设备表';
CREATE TABLE `user_logs` (
`log_id` BIGINT NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL COMMENT '用户ID',
`action_type` VARCHAR(50) NOT NULL COMMENT '行为类型',
`ip_address` VARCHAR(50) DEFAULT NULL COMMENT 'IP地址',
`user_agent` TEXT DEFAULT NULL COMMENT 'User-Agent',
`metadata` LONGTEXT DEFAULT NULL COMMENT '扩展元数据(JSON字符串)',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`log_id`),
KEY `idx_user_logs_user_id` (`user_id`),
KEY `idx_user_logs_action_type` (`action_type`),
KEY `idx_user_logs_created_at` (`created_at`),
KEY `idx_user_logs_user_action` (`user_id`, `action_type`),
CONSTRAINT `fk_user_logs_user_id`
FOREIGN KEY (`user_id`) REFERENCES `sys_users` (`user_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户行为日志表';
CREATE TABLE `user_voiceprint` (
`vp_id` INT NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL COMMENT '用户ID',
`file_path` VARCHAR(255) NOT NULL COMMENT '声纹文件路径',
`file_size` BIGINT DEFAULT NULL COMMENT '文件大小',
`duration_seconds` DECIMAL(5,2) DEFAULT 10.00 COMMENT '音频时长',
`vector_data` LONGTEXT DEFAULT NULL COMMENT '声纹向量(JSON字符串)',
`collected_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '采集时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`vp_id`),
UNIQUE KEY `uk_user_voiceprint_user_id` (`user_id`),
KEY `idx_user_voiceprint_collected_at` (`collected_at`),
CONSTRAINT `fk_user_voiceprint_user_id`
FOREIGN KEY (`user_id`) REFERENCES `sys_users` (`user_id`)
ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户声纹表';
SELECT 'imeeting-schema-latest.sql executed successfully' AS `message`;

View File

@ -0,0 +1,800 @@
-- iMeeting latest seed initialization script
-- 用途:
-- 1. 面向“已执行最新全量建表脚本”的全新部署
-- 2. 仅初始化系统基础数据,不包含历史会议、附件、任务、知识库等业务数据
-- 3. 尽量支持重复执行(幂等),便于新库初始化或回放
--
-- 重要前提:
-- 1. 已先执行 imeeting-schema-latest.sql
-- 2. 当前库已存在以下最新结构:
-- sys_roles / sys_users / sys_menus / sys_role_menu_permissions
-- prompts(desc,is_system) / prompt_config
-- sys_system_parameters / llm_model_config / audio_model_config
-- hot_word_group / hot_word_item / sys_dict_data
--
-- 默认账号:
-- admin / admin123
-- demo / 123456
--
-- 说明:
-- 1. 模型 API Key 默认留空,优先走环境变量配置
-- 2. ASR 默认绑定“默认热词组”,首次执行后仍可在后台继续同步词表
SET NAMES utf8mb4;
START TRANSACTION;
-- =====================================================================
-- 1. 基础角色
-- =====================================================================
INSERT INTO `sys_roles` (`role_id`, `role_name`, `created_at`)
VALUES
(1, '平台管理员', NOW()),
(2, '普通用户', NOW())
ON DUPLICATE KEY UPDATE
`role_name` = VALUES(`role_name`);
-- =====================================================================
-- 2. 基础用户
-- 密码说明:
-- admin -> admin123
-- demo -> 123456
-- =====================================================================
INSERT INTO `sys_users`
(`user_id`, `username`, `caption`, `email`, `avatar_url`, `password_hash`, `role_id`, `created_at`)
VALUES
(1, 'admin', '系统管理员', 'admin@imeeting.local', NULL, '240be518fabd2724ddb6f04eeb1da5967448d7e831c08c8fa822809f74c720a9', 1, NOW()),
(2, 'demo', '演示用户', 'demo@imeeting.local', NULL, '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', 2, NOW())
ON DUPLICATE KEY UPDATE
`username` = VALUES(`username`),
`caption` = VALUES(`caption`),
`email` = VALUES(`email`),
`avatar_url` = VALUES(`avatar_url`),
`password_hash` = VALUES(`password_hash`),
`role_id` = VALUES(`role_id`);
-- =====================================================================
-- 3. 系统默认提示词模版
-- =====================================================================
INSERT INTO `prompts`
(`id`, `name`, `task_type`, `content`, `desc`, `is_default`, `is_active`, `creator_id`, `is_system`, `created_at`)
VALUES
(
1,
'系统默认会议总结',
'MEETING_TASK',
'你是一名专业的会议纪要助手。请基于会议转写内容输出结构化 Markdown总结以下内容
## 会议概览
-
## 核心讨论
-
## 决策事项
-
## 待办事项
- 使
## 风险与建议
-
1.
2.
3. ',
'会议转写默认总结模板',
1,
1,
1,
1,
NOW()
),
(
2,
'系统默认知识整理',
'KNOWLEDGE_TASK',
'你是一名专业的知识整理助手。请基于输入材料生成一篇适合归档到知识库的 Markdown 文档,包含以下部分:
## 标题
-
## 摘要
- 3 5
## 关键事实
-
## 操作步骤或处理方案
-
## 风险与注意事项
-
## 相关名词与标签
-
1.
2.
3. 便',
'知识库整理默认模板',
1,
1,
1,
1,
NOW()
)
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`task_type` = VALUES(`task_type`),
`content` = VALUES(`content`),
`desc` = VALUES(`desc`),
`is_default` = VALUES(`is_default`),
`is_active` = VALUES(`is_active`),
`creator_id` = VALUES(`creator_id`),
`is_system` = VALUES(`is_system`);
-- 为初始化账号补充默认模版启用配置
INSERT INTO `prompt_config`
(`user_id`, `task_type`, `prompt_id`, `is_enabled`, `sort_order`, `created_at`, `updated_at`)
VALUES
(1, 'MEETING_TASK', 1, 1, 1, NOW(), NOW()),
(1, 'KNOWLEDGE_TASK', 2, 1, 1, NOW(), NOW()),
(2, 'MEETING_TASK', 1, 1, 1, NOW(), NOW()),
(2, 'KNOWLEDGE_TASK', 2, 1, 1, NOW(), NOW())
ON DUPLICATE KEY UPDATE
`is_enabled` = VALUES(`is_enabled`),
`sort_order` = VALUES(`sort_order`),
`updated_at` = VALUES(`updated_at`);
-- =====================================================================
-- 4. 系统参数
-- =====================================================================
INSERT INTO `sys_system_parameters`
(`param_key`, `param_name`, `param_value`, `value_type`, `category`, `description`, `is_active`, `created_at`, `updated_at`)
VALUES
('token_expire_days', 'Token过期时间', '7', 'number', 'system', '控制登录 token 的过期时间,单位:天。', 1, NOW(), NOW()),
('default_reset_password', '默认重置密码', '123456', 'string', 'system', '管理员重置用户密码时使用的默认密码。', 1, NOW(), NOW()),
('page_size', '系统分页大小', '10', 'number', 'public', '系统通用分页数量。', 1, NOW(), NOW()),
('max_audio_size', '音频上传大小限制', '100', 'number', 'public', '音频上传大小限制单位MB。', 1, NOW(), NOW()),
('max_image_size', '图片上传大小限制', '10', 'number', 'public', '图片上传大小限制单位MB。', 1, NOW(), NOW()),
('app_name', '系统名称', 'iMeeting', 'string', 'public', '前端应用标题。', 1, NOW(), NOW()),
('console_subtitle', '控制台副标题', '智能会议协作平台', 'string', 'public', '登录后控制台副标题。', 1, NOW(), NOW()),
('preview_title', '会议预览标题', '会议预览', 'string', 'public', '会议预览页标题。', 1, NOW(), NOW()),
('login_welcome', '登录欢迎语', '欢迎登录 iMeeting请输入您的账号信息。', 'string', 'public', '登录页欢迎语。', 1, NOW(), NOW()),
('footer_text', '页脚文案', '©2026 iMeeting', 'string', 'public', '系统页脚文案。', 1, NOW(), NOW())
ON DUPLICATE KEY UPDATE
`param_name` = VALUES(`param_name`),
`param_value` = VALUES(`param_value`),
`value_type` = VALUES(`value_type`),
`category` = VALUES(`category`),
`description` = VALUES(`description`),
`is_active` = VALUES(`is_active`),
`updated_at` = VALUES(`updated_at`);
-- =====================================================================
-- 5. 默认热词组与热词
-- =====================================================================
INSERT INTO `hot_word_group` (`name`, `description`, `status`, `create_time`, `update_time`)
SELECT '默认热词组', '系统初始化热词组,供默认 ASR 模型绑定使用。', 1, NOW(), NOW()
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `hot_word_group` WHERE `name` = '默认热词组'
);
UPDATE `hot_word_group`
SET
`description` = '系统初始化热词组,供默认 ASR 模型绑定使用。',
`status` = 1,
`update_time` = NOW()
WHERE `name` = '默认热词组';
SET @default_hot_word_group_id := (
SELECT `id`
FROM `hot_word_group`
WHERE `name` = '默认热词组'
ORDER BY `id`
LIMIT 1
);
INSERT INTO `hot_word_item`
(`group_id`, `text`, `weight`, `lang`, `status`, `create_time`, `update_time`)
SELECT @default_hot_word_group_id, 'iMeeting', 8, 'zh', 1, NOW(), NOW()
FROM DUAL
WHERE @default_hot_word_group_id IS NOT NULL
ON DUPLICATE KEY UPDATE
`weight` = VALUES(`weight`),
`lang` = VALUES(`lang`),
`status` = VALUES(`status`),
`update_time` = VALUES(`update_time`);
INSERT INTO `hot_word_item`
(`group_id`, `text`, `weight`, `lang`, `status`, `create_time`, `update_time`)
SELECT @default_hot_word_group_id, '会议纪要', 7, 'zh', 1, NOW(), NOW()
FROM DUAL
WHERE @default_hot_word_group_id IS NOT NULL
ON DUPLICATE KEY UPDATE
`weight` = VALUES(`weight`),
`lang` = VALUES(`lang`),
`status` = VALUES(`status`),
`update_time` = VALUES(`update_time`);
INSERT INTO `hot_word_item`
(`group_id`, `text`, `weight`, `lang`, `status`, `create_time`, `update_time`)
SELECT @default_hot_word_group_id, '语音转写', 6, 'zh', 1, NOW(), NOW()
FROM DUAL
WHERE @default_hot_word_group_id IS NOT NULL
ON DUPLICATE KEY UPDATE
`weight` = VALUES(`weight`),
`lang` = VALUES(`lang`),
`status` = VALUES(`status`),
`update_time` = VALUES(`update_time`);
-- =====================================================================
-- 6. 默认模型配置
-- =====================================================================
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`, `created_at`, `updated_at`)
VALUES
(
'llm_model',
'默认文本模型',
'dashscope',
'https://dashscope.aliyuncs.com/compatible-mode/v1',
NULL,
'qwen-plus',
120,
0.70,
0.90,
2048,
'你是一名专业的会议与知识整理助手,请基于输入内容给出准确、结构化、可复用的输出。',
'系统初始化的默认 LLM 模型配置API Key 优先使用环境变量。',
1,
1,
NOW(),
NOW()
)
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`),
`updated_at` = VALUES(`updated_at`);
INSERT INTO `audio_model_config`
(`model_code`, `model_name`, `audio_scene`, `provider`, `endpoint_url`, `api_key`,
`request_timeout_seconds`, `hot_word_group_id`, `extra_config`, `description`,
`is_active`, `is_default`, `created_at`, `updated_at`)
SELECT
'audio_model',
'默认语音识别模型',
'asr',
'dashscope',
'https://dashscope.aliyuncs.com',
NULL,
300,
g.`id`,
JSON_OBJECT(
'model', 'paraformer-v2',
'vocabulary_id', g.`vocabulary_id`,
'speaker_count', 10,
'language_hints', JSON_ARRAY('zh', 'en'),
'disfluency_removal_enabled', TRUE,
'diarization_enabled', TRUE
),
'系统初始化的默认 ASR 模型配置。',
1,
1,
NOW(),
NOW()
FROM `hot_word_group` g
WHERE g.`id` = @default_hot_word_group_id
ON DUPLICATE KEY UPDATE
`model_name` = VALUES(`model_name`),
`audio_scene` = VALUES(`audio_scene`),
`provider` = VALUES(`provider`),
`endpoint_url` = VALUES(`endpoint_url`),
`api_key` = VALUES(`api_key`),
`request_timeout_seconds` = VALUES(`request_timeout_seconds`),
`hot_word_group_id` = VALUES(`hot_word_group_id`),
`extra_config` = VALUES(`extra_config`),
`description` = VALUES(`description`),
`is_active` = VALUES(`is_active`),
`is_default` = VALUES(`is_default`),
`updated_at` = VALUES(`updated_at`);
INSERT INTO `audio_model_config`
(`model_code`, `model_name`, `audio_scene`, `provider`, `endpoint_url`, `api_key`,
`request_timeout_seconds`, `hot_word_group_id`, `extra_config`, `description`,
`is_active`, `is_default`, `created_at`, `updated_at`)
VALUES
(
'voiceprint_model',
'默认声纹配置',
'voiceprint',
'funasr',
NULL,
NULL,
120,
NULL,
JSON_OBJECT(
'template_text', '我正在进行声纹采集,这段语音将用于身份识别和验证。声纹技术能够准确识别每个人独特的声音特征。',
'duration_seconds', 12,
'sample_rate', 16000,
'channels', 1,
'max_size_bytes', 5242880
),
'系统初始化的默认声纹采集配置。',
1,
1,
NOW(),
NOW()
)
ON DUPLICATE KEY UPDATE
`model_name` = VALUES(`model_name`),
`audio_scene` = VALUES(`audio_scene`),
`provider` = VALUES(`provider`),
`endpoint_url` = VALUES(`endpoint_url`),
`api_key` = VALUES(`api_key`),
`request_timeout_seconds` = VALUES(`request_timeout_seconds`),
`hot_word_group_id` = VALUES(`hot_word_group_id`),
`extra_config` = VALUES(`extra_config`),
`description` = VALUES(`description`),
`is_active` = VALUES(`is_active`),
`is_default` = VALUES(`is_default`),
`updated_at` = VALUES(`updated_at`);
-- =====================================================================
-- 7. 基础字典数据
-- =====================================================================
INSERT INTO `sys_dict_data`
(`dict_type`, `dict_code`, `parent_code`, `tree_path`, `label_cn`, `label_en`, `sort_order`,
`extension_attr`, `is_default`, `status`, `create_time`, `update_time`)
VALUES
('client_platform', 'DESKTOP', 'ROOT', NULL, '桌面端', 'Desktop', 1, JSON_OBJECT('icon', 'monitor'), 0, 1, NOW(), NOW()),
('client_platform', 'MOBILE', 'ROOT', NULL, '移动端', 'Mobile', 2, JSON_OBJECT('icon', 'phone'), 0, 1, NOW(), NOW()),
('client_platform', 'TERMINAL', 'ROOT', NULL, '专用终端', 'Terminal', 3, JSON_OBJECT('icon', 'router'), 0, 1, NOW(), NOW()),
('client_platform', 'WIN', 'DESKTOP', NULL, 'Windows', 'Windows', 1, JSON_OBJECT('suffix', '.exe', 'arch_support', JSON_ARRAY('x86', 'x64')), 0, 1, NOW(), NOW()),
('client_platform', 'MAC', 'DESKTOP', NULL, 'macOS', 'macOS', 2, JSON_OBJECT('suffix', '.dmg', 'arch_support', JSON_ARRAY('x64', 'arm64')), 0, 1, NOW(), NOW()),
('client_platform', 'LINUX', 'DESKTOP', NULL, 'Linux', 'Linux', 3, JSON_OBJECT('suffix', '.deb', 'arch_support', JSON_ARRAY('x64', 'arm64')), 0, 1, NOW(), NOW()),
('client_platform', 'IOS', 'MOBILE', NULL, '苹果iOS', 'iOS', 1, JSON_OBJECT('suffix', '.ipa', 'store_link', TRUE), 0, 1, NOW(), NOW()),
('client_platform', 'ANDROID', 'MOBILE', NULL, '安卓', 'Android', 2, JSON_OBJECT('suffix', '.apk'), 0, 1, NOW(), NOW()),
('client_platform', 'TERM_STD', 'TERMINAL', NULL, '通用终端', 'Standard Terminal', 1, JSON_OBJECT('vendor', 'Generic', 'os', 'Android'), 1, 1, NOW(), NOW()),
('client_platform', 'TERM_S100','TERMINAL', NULL, '中兴 S100', 'ZTE S100', 2, JSON_OBJECT('vendor', 'ZTE', 'os', 'Android'), 0, 1, NOW(), NOW()),
('client_platform', 'TERM_A133','TERMINAL', NULL, '全志 A133', 'Allwinner A133', 3, JSON_OBJECT('vendor', 'Allwinner', 'os', 'Android'), 0, 1, NOW(), NOW()),
('terminal_type', 'TERM_STD', 'ROOT', NULL, '通用终端', 'Standard Terminal', 1, NULL, 1, 1, NOW(), NOW()),
('terminal_type', 'TERM_S100','ROOT', NULL, '中兴 S100', 'ZTE S100', 2, NULL, 0, 1, NOW(), NOW()),
('terminal_type', 'TERM_A133','ROOT', NULL, '全志 A133', 'Allwinner A133', 3, NULL, 0, 1, NOW(), NOW()),
('task_type', 'MEETING_TASK', 'ROOT', NULL, '会议任务', 'Meeting Task', 1, NULL, 0, 1, NOW(), NOW()),
('task_type', 'KNOWLEDGE_TASK', 'ROOT', NULL, '知识库任务', 'Knowledge Task', 2, NULL, 0, 1, NOW(), NOW()),
('external_apps', 'NATIVE', 'ROOT', NULL, '原生应用', 'Native App', 1, JSON_OBJECT('protocol', 'apk'), 0, 1, NOW(), NOW()),
('external_apps', 'WEB', 'ROOT', NULL, 'Web应用', 'Web App', 2, JSON_OBJECT('protocol', 'https'), 0, 1, NOW(), NOW())
ON DUPLICATE KEY UPDATE
`parent_code` = VALUES(`parent_code`),
`tree_path` = VALUES(`tree_path`),
`label_cn` = VALUES(`label_cn`),
`label_en` = VALUES(`label_en`),
`sort_order` = VALUES(`sort_order`),
`extension_attr` = VALUES(`extension_attr`),
`is_default` = VALUES(`is_default`),
`status` = VALUES(`status`),
`update_time` = VALUES(`update_time`);
-- =====================================================================
-- 8. 菜单定义
-- 最终菜单树:
-- dashboard
-- desktop
-- meeting_manage
-- ├─ meeting_center
-- └─ prompt_config
-- platform_admin
-- ├─ hot_word_management
-- ├─ model_management
-- ├─ prompt_management
-- ├─ client_management
-- ├─ external_app_management
-- └─ terminal_management
-- system_management
-- ├─ user_management
-- ├─ permission_management
-- │ └─ permission_menu_tree (隐藏)
-- ├─ dict_management
-- └─ parameter_management
-- =====================================================================
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`, `created_at`, `updated_at`)
VALUES
('dashboard', 'Dashboard', 'DashboardOutlined', '/dashboard', 'link', NULL, 1, NULL, 1, 1, 1, '管理员桌面', NOW(), NOW()),
('desktop', 'Desktop', 'DesktopOutlined', '/dashboard', 'link', NULL, 1, NULL, 2, 1, 1, '普通用户桌面', NOW(), NOW()),
('meeting_manage', '会议管理', 'CalendarOutlined', '/meetings/center', 'link', NULL, 1, NULL, 3, 1, 1, '普通用户会议功能入口', NOW(), NOW()),
('platform_admin', '平台管理', 'Shield', '/admin/management/hot-word-management', 'link', NULL, 1, NULL, 4, 1, 1, '平台能力配置入口', NOW(), NOW()),
('system_management', '系统管理', 'Setting', '/admin/management/system-overview', 'link', NULL, 1, NULL, 5, 1, 1, '系统治理入口', NOW(), NOW())
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
SET @meeting_manage_id := (SELECT `menu_id` FROM `sys_menus` WHERE `menu_code` = 'meeting_manage' LIMIT 1);
SET @platform_admin_id := (SELECT `menu_id` FROM `sys_menus` WHERE `menu_code` = 'platform_admin' LIMIT 1);
SET @system_management_id := (SELECT `menu_id` FROM `sys_menus` WHERE `menu_code` = 'system_management' LIMIT 1);
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`, `created_at`, `updated_at`)
SELECT
'meeting_center', '会议中心', 'CalendarOutlined', '/meetings/center', 'link',
@meeting_manage_id, 2, NULL, 1, 1, 1, '普通用户会议中心', NOW(), NOW()
FROM DUAL
WHERE @meeting_manage_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
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`, `created_at`, `updated_at`)
SELECT
'prompt_config', '提示词配置', 'Book', '/prompt-config', 'link',
@meeting_manage_id, 2, NULL, 2, 1, 1, '用户提示词启用与排序配置', NOW(), NOW()
FROM DUAL
WHERE @meeting_manage_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
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`, `created_at`, `updated_at`)
SELECT
'hot_word_management', '热词管理', 'Text', '/admin/management/hot-word-management', 'link',
@platform_admin_id, 2, NULL, 1, 1, 1, 'ASR 热词管理与同步', NOW(), NOW()
FROM DUAL
WHERE @platform_admin_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
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`, `created_at`, `updated_at`)
SELECT
'model_management', '模型管理', 'Appstore', '/admin/management/model-management', 'link',
@platform_admin_id, 2, NULL, 2, 1, 1, '音频模型与 LLM 模型配置', NOW(), NOW()
FROM DUAL
WHERE @platform_admin_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
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`, `created_at`, `updated_at`)
SELECT
'prompt_management', '提示词库', 'BookText', '/prompt-management', 'link',
@platform_admin_id, 2, NULL, 3, 1, 1, '系统提示词库管理', NOW(), NOW()
FROM DUAL
WHERE @platform_admin_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
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`, `created_at`, `updated_at`)
SELECT
'client_management', '客户端管理', 'Smartphone', '/admin/management/client-management', 'link',
@platform_admin_id, 2, NULL, 4, 1, 1, '客户端下载与版本管理', NOW(), NOW()
FROM DUAL
WHERE @platform_admin_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
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`, `created_at`, `updated_at`)
SELECT
'external_app_management', '外部应用管理', 'AppWindow', '/admin/management/external-app-management', 'link',
@platform_admin_id, 2, NULL, 5, 1, 1, '外部系统入口管理', NOW(), NOW()
FROM DUAL
WHERE @platform_admin_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
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`, `created_at`, `updated_at`)
SELECT
'terminal_management', '终端管理', 'Monitor', '/admin/management/terminal-management', 'link',
@platform_admin_id, 2, NULL, 6, 1, 1, '专用终端管理', NOW(), NOW()
FROM DUAL
WHERE @platform_admin_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
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`, `created_at`, `updated_at`)
SELECT
'user_management', '用户管理', 'Users', '/admin/management/user-management', 'link',
@system_management_id, 2, NULL, 1, 1, 1, '账号、角色、密码管理', NOW(), NOW()
FROM DUAL
WHERE @system_management_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
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`, `created_at`, `updated_at`)
SELECT
'permission_management', '权限管理', 'KeyRound', '/admin/management/permission-management', 'link',
@system_management_id, 2, NULL, 2, 1, 1, '菜单与角色授权管理', NOW(), NOW()
FROM DUAL
WHERE @system_management_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
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`, `created_at`, `updated_at`)
SELECT
'dict_management', '字典管理', 'BookMarked', '/admin/management/dict-management', 'link',
@system_management_id, 2, NULL, 3, 1, 1, '平台字典与码表管理', NOW(), NOW()
FROM DUAL
WHERE @system_management_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
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`, `created_at`, `updated_at`)
SELECT
'parameter_management', '参数管理', 'Setting', '/admin/management/parameter-management', 'link',
@system_management_id, 2, NULL, 4, 1, 1, '系统参数管理', NOW(), NOW()
FROM DUAL
WHERE @system_management_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
SET @permission_management_id := (
SELECT `menu_id`
FROM `sys_menus`
WHERE `menu_code` = 'permission_management'
LIMIT 1
);
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`, `created_at`, `updated_at`)
SELECT
'permission_menu_tree', '菜单树维护', 'AppstoreAdd', '/admin/management/permission-management', 'link',
@permission_management_id, 3, NULL, 20, 1, 0, '权限管理中的隐藏入口,用于菜单树维护。', NOW(), NOW()
FROM DUAL
WHERE @permission_management_id IS NOT NULL
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`),
`menu_level` = VALUES(`menu_level`),
`sort_order` = VALUES(`sort_order`),
`is_active` = VALUES(`is_active`),
`is_visible` = VALUES(`is_visible`),
`description` = VALUES(`description`),
`updated_at` = VALUES(`updated_at`);
-- 回填本次初始化菜单的树结构
UPDATE `sys_menus`
SET
`menu_level` = 1,
`tree_path` = CONCAT('/', `menu_id`)
WHERE `menu_code` IN ('dashboard', 'desktop', 'meeting_manage', 'platform_admin', 'system_management');
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`)
WHERE c.`menu_code` IN (
'meeting_center',
'prompt_config',
'hot_word_management',
'model_management',
'prompt_management',
'client_management',
'external_app_management',
'terminal_management',
'user_management',
'permission_management',
'dict_management',
'parameter_management'
);
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`)
WHERE c.`menu_code` IN ('permission_menu_tree');
-- =====================================================================
-- 9. 角色授权
-- 管理员: 所有启用菜单
-- 普通用户: dashboard / desktop / meeting_manage / meeting_center / prompt_config
-- =====================================================================
INSERT INTO `sys_role_menu_permissions`
(`role_id`, `menu_id`, `granted_by`, `granted_at`)
SELECT
1,
m.`menu_id`,
1,
NOW()
FROM `sys_menus` m
WHERE m.`is_active` = 1
ON DUPLICATE KEY UPDATE
`granted_by` = VALUES(`granted_by`),
`granted_at` = VALUES(`granted_at`);
INSERT INTO `sys_role_menu_permissions`
(`role_id`, `menu_id`, `granted_by`, `granted_at`)
SELECT
2,
m.`menu_id`,
1,
NOW()
FROM `sys_menus` m
WHERE m.`is_active` = 1
AND m.`menu_code` IN ('dashboard', 'desktop', 'meeting_manage', 'meeting_center', 'prompt_config')
ON DUPLICATE KEY UPDATE
`granted_by` = VALUES(`granted_by`),
`granted_at` = VALUES(`granted_at`);
-- =====================================================================
-- 10. 自增游标兜底
-- =====================================================================
COMMIT;
ALTER TABLE `sys_roles` AUTO_INCREMENT = 3;
ALTER TABLE `sys_users` AUTO_INCREMENT = 3;
ALTER TABLE `prompts` AUTO_INCREMENT = 3;

View File

@ -1,222 +0,0 @@
# iMeeting 按钮统一规范
## 目标
统一平台内业务操作按钮的视觉语言、尺寸层级和使用方式,避免同一场景中出现不同形态的编辑、删除、查看、复制等操作按钮。
当前平台按钮分为两套标准:
1. 业务操作按钮:统一通过 [ActionButton](/Users/jiliu/工作/projects/imeeting/frontend/src/components/ActionButton.jsx) 承载。
2. 表单操作条按钮:统一使用 Ant Design `Button` 家族,不与 `ActionButton` 混用。
## 设计原则
1. 语义和尺寸分离。
语义只表达动作类型,例如查看、编辑、删除;尺寸只表达场景层级,例如列表操作、面板次级操作。
2. 同一场景只选一种尺寸档。
不要在同一条记录、同一个卡片头部、同一个面板操作区里混用大图标、小图标、大文字、小文字。
3. 删除按钮只保留颜色差异。
删除按钮和其它按钮使用同一套圆角、边框、阴影和尺寸,不再使用额外的危险态造型。
4. 业务操作、表单操作、功能控件分开。
- 业务操作统一走 `ActionButton`
- 表单操作条统一走标准 `Button`
- 编辑器工具栏、播放器控制等功能控件不强行复用这套规范
5. 同一操作条内外框语言必须一致。
如果一组按钮里已经采用普通 `Button`,就不要混入胶囊式 `ActionButton`;如果一组按钮采用 `ActionButton`,就不要再塞入默认 `Button`
## 标准尺寸
### 1. 带文字(大)
- 组件参数:`variant="textLg"`
- 典型场景:面板内次级操作、详情弹窗中的补充动作、信息面板中的“下载结果 / 复制链接 / 编辑当前菜单”
- 示例:`编辑`、`删除`、`下载转录结果 (JSON)`、`复制链接`
### 2. 带文字(小)
- 组件参数:`variant="textSm"`
- 典型场景:卡片头部轻量动作、模块内局部切换动作
- 示例:`标签`、`编辑`、`查看详情`、`清空已选`
### 3. 仅图标(大)
- 组件参数:`variant="iconLg"`
- 典型场景:输入框组合控件右侧操作、需要更高点击面的紧凑操作
- 示例:分享密码区的 `复制 / 保存`
### 4. 仅图标(小)
- 组件参数:`variant="iconSm"`
- 典型场景:列表行操作、卡片角落操作、悬浮于内容边缘的轻量动作
- 示例:`编辑 / 删除 / 查看 / 同步 / 更多`
## 标准语义
### `tone="view"`
- 用于查看、打开、复制、下载、预览
- 颜色语义:蓝色系
### `tone="neutral"`
- 用于更多、清空、重置筛选、非强调型辅助动作
- 颜色语义:中性色
### `tone="edit"`
- 用于编辑、设置、修改
- 颜色语义:蓝色系,与查看同体系但文义偏编辑
### `tone="accent"`
- 用于需要强调但非危险的特殊动作
- 颜色语义:强调色
- 当前典型场景:`重置密码`
### `tone="delete"`
- 用于删除、移除、关闭会话等不可逆动作
- 颜色语义:红色系
## 场景映射
### 列表行操作
- 一律使用 `iconSm`
- 常见组合:`编辑 / 删除`、`查看 / 编辑 / 删除`
- 示例页面:
- 热词管理
- 用户管理
- 参数管理
- 模型管理
- 客户端管理
- 外部应用管理
### 卡片角落操作
- 一律使用 `iconSm`
- 常见组合:`编辑 / 删除`、`更多`
- 示例页面:
- 会议中心卡片
- 时间线卡片
- 知识库左侧列表
### 卡片或模块头部的轻量动作
- 一律使用 `textSm`
- 常见组合:`标签`、`编辑`、`查看详情`
### 面板或 Drawer 的次级操作
- 一律使用 `textLg`
- 常见组合:`编辑`、`删除`、`复制链接`、`下载转录结果`
### 表单操作条
- 一律使用标准 `Button`
- 常见组合:`删除 / 取消 / 保存`
- 视觉规范:
- `删除``className="btn-soft-red"`
- `取消`:默认 `Button`
- `保存``type="primary"`
- 说明:
- 这类按钮属于提交与撤销控制,不使用 `ActionButton`
- 同一条内不要出现 `ActionButton tone="delete"` 与普通 `Button` 并排
### 输入框附属操作
- 一律使用 `iconLg`
- 常见组合:输入框后缀的 `复制 / 保存`
## 禁止项
1. 不要在业务操作中直接裸用 `EditOutlined`、`DeleteOutlined` 作为可点击入口。
2. 不要在同一场景混用:
- `shape="circle"` 图标按钮
- 旧的 `btn-icon-soft-*`
- 默认 `danger` 样式按钮
- 新的 `ActionButton`
- 普通 `Button``ActionButton` 的不同外框语言
3. 不要为了“删除更危险”单独给删除按钮换不同形状、尺寸或阴影。
4. 不要在业务操作中继续手写 `Tooltip + Button + btn-text-* + btn-action-*`
优先使用 `ActionButton`
## 推荐写法
```jsx
import ActionButton from '../components/ActionButton';
<ActionButton
tone="edit"
variant="iconSm"
tooltip="编辑"
icon={<EditOutlined />}
onClick={handleEdit}
/>
```
```jsx
<ActionButton
tone="delete"
variant="textLg"
icon={<DeleteOutlined />}
onClick={handleDelete}
>
删除
</ActionButton>
```
```jsx
<ActionButton
tone="view"
variant="iconLg"
tooltip="复制密码"
icon={<CopyOutlined />}
onClick={handleCopy}
/>
```
```jsx
<Space>
<Button className="btn-soft-red" icon={<DeleteOutlined />} onClick={handleDelete}>
删除
</Button>
<Button icon={<CloseOutlined />} onClick={handleCancel}>
取消
</Button>
<Button type="primary" icon={<SaveOutlined />} onClick={handleSave}>
保存
</Button>
</Space>
```
## 落地约束
1. 新增按钮时,先判断是不是业务动作还是表单提交动作。
- 业务动作优先使用 `ActionButton`
- 表单操作条优先使用标准 `Button`
2. 新页面开发时,先确定场景,再选尺寸档。
不要先凭感觉挑样式。
3. 旧页面调整时,如果涉及编辑、删除、查看、更多、复制、下载等业务动作,顺手迁移到 `ActionButton`
4. 如果删除按钮和取消、保存并排出现,优先按表单操作条处理,不要单独给删除套胶囊业务按钮。
## 现状说明
当前平台中的主要业务操作按钮已基本迁移到 `ActionButton`,主要表单操作条也开始统一为 `删除 / 取消 / 保存` 的标准按钮组合。
未纳入本规范的主要是两类控件:
- Markdown 编辑器工具栏按钮
- 会议详情中的音频工具栏按钮
这两类属于功能控件,不按业务操作按钮规范处理。

View File

@ -1,292 +0,0 @@
# 客户端下载管理模块
## 概述
本模块实现了一个完整的客户端下载管理系统,支持移动端(iOS/Android)和桌面端(Windows/Mac/Linux)的版本管理和下载。
## 功能特性
### 1. 管理员功能
- ✅ 创建/编辑/删除客户端版本
- ✅ 管理版本号和版本代码
- ✅ 设置最新版本标记
- ✅ 启用/禁用特定版本
- ✅ 添加更新说明和系统要求
- ✅ 平台分类管理(移动端/桌面端)
- ✅ 搜索和过滤功能
### 2. 用户功能
- ✅ 查看所有平台的最新客户端
- ✅ 按平台分类展示
- ✅ 显示版本信息和文件大小
- ✅ 一键下载
### 3. API功能
- ✅ 获取所有客户端列表(支持分页和过滤)
- ✅ 获取最新版本客户端
- ✅ 按平台获取最新版本(用于客户端版本检查)
- ✅ CRUD操作(仅管理员)
## 数据库设计
### 表结构: `client_downloads`
```sql
CREATE TABLE client_downloads (
id INT AUTO_INCREMENT PRIMARY KEY,
platform_type ENUM('mobile', 'desktop') NOT NULL,
platform_name VARCHAR(50) NOT NULL,
version VARCHAR(50) NOT NULL,
version_code INT NOT NULL DEFAULT 1,
download_url TEXT NOT NULL,
file_size BIGINT,
release_notes TEXT,
is_active BOOLEAN DEFAULT TRUE,
is_latest BOOLEAN DEFAULT FALSE,
min_system_version VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
created_by INT,
FOREIGN KEY (created_by) REFERENCES users(user_id) ON DELETE SET NULL,
INDEX idx_platform (platform_type, platform_name),
INDEX idx_version (version_code),
INDEX idx_active (is_active, is_latest)
);
```
### 字段说明
- `platform_type`: 平台类型(mobile/desktop)
- `platform_name`: 具体平台(ios/android/windows/mac_intel/mac_m/linux)
- `version`: 版本号字符串(如: 1.0.0)
- `version_code`: 版本代码数字(用于版本比较,如: 1000)
- `download_url`: 下载链接
- `file_size`: 文件大小(字节)
- `release_notes`: 更新说明
- `is_active`: 是否启用
- `is_latest`: 是否为最新版本
- `min_system_version`: 最低系统版本要求
## API接口
### 公开接口(无需认证)
#### 1. 获取客户端列表
```
GET /api/clients/downloads
Query参数:
- platform_type: mobile|desktop (可选)
- platform_name: ios|android|windows|mac_intel|mac_m|linux (可选)
- is_active: true|false (可选)
- page: 页码 (默认1)
- size: 每页数量 (默认50)
```
#### 2. 获取所有最新版本
```
GET /api/clients/downloads/latest
返回: { mobile: [...], desktop: [...] }
```
#### 3. 获取指定平台最新版本
```
GET /api/clients/downloads/{platform_name}/latest
示例: GET /api/clients/downloads/ios/latest
```
#### 4. 获取指定ID的客户端
```
GET /api/clients/downloads/{id}
```
### 管理员接口(需要管理员权限)
#### 5. 创建客户端版本
```
POST /api/clients/downloads
Body: {
"platform_type": "mobile",
"platform_name": "ios",
"version": "1.0.0",
"version_code": 1000,
"download_url": "https://...",
"file_size": 52428800,
"release_notes": "初始版本...",
"is_active": true,
"is_latest": false,
"min_system_version": "iOS 13.0"
}
```
#### 6. 更新客户端版本
```
PUT /api/clients/downloads/{id}
Body: {
"version": "1.0.1",
"version_code": 1001,
"is_latest": true,
...
}
```
#### 7. 删除客户端版本
```
DELETE /api/clients/downloads/{id}
```
## 前端组件
### 1. ClientManagement (管理员页面)
位置: `frontend/src/pages/ClientManagement.jsx`
功能:
- 客户端版本CRUD操作
- 平台筛选和搜索
- 版本状态管理
- 响应式卡片布局
### 2. ClientDownloads (用户下载组件)
位置: `frontend/src/components/ClientDownloads.jsx`
功能:
- 展示最新客户端版本
- 按平台分类
- 一键下载
- 可嵌入任何页面
## 安装和部署
### 1. 数据库初始化
```bash
# 执行SQL文件
mysql -u your_user -p your_database < backend/sql/client_downloads.sql
```
### 2. 后端启动
后端会自动加载新的路由,无需额外配置。
### 3. 前端使用
#### 在管理员页面添加客户端管理:
```jsx
import ClientManagement from './pages/ClientManagement';
// 在管理员路由中添加
<Route path="/admin/clients" element={<ClientManagement user={user} />} />
```
#### 在首页添加下载组件:
```jsx
import ClientDownloads from './components/ClientDownloads';
// 在Dashboard或任何页面中添加
<ClientDownloads />
```
## 使用示例
### 管理员创建新版本
1. 访问管理后台的"客户端管理"页面
2. 点击"新增客户端"按钮
3. 填写版本信息:
- 选择平台类型和具体平台
- 输入版本号和版本代码
- 填写下载链接
- 添加更新说明
- 勾选"设为最新版本"(如果是最新)
4. 点击"创建"保存
### 用户下载客户端
1. 在首页查看"下载客户端"区域
2. 选择对应平台
3. 点击卡片即可下载
### 客户端版本检查
客户端可以调用API检查是否有新版本:
```javascript
// 检查iOS最新版本
const response = await fetch('/api/clients/downloads/ios/latest');
const latest = await response.json();
if (latest.data.version_code > currentVersionCode) {
// 提示用户更新
showUpdateDialog(latest.data);
}
```
## 版本号规范
- **版本号**: 采用语义化版本(Semantic Versioning),格式: `主版本.次版本.修订号`
- 例如: 1.0.0, 1.2.3, 2.0.0
- **版本代码**: 纯数字,用于程序化比较
- 推荐格式: 主版本(2位) + 次版本(2位) + 修订号(2位)
- 例如: 1.0.0 -> 10000, 1.2.3 -> 10203, 2.0.0 -> 20000
## 平台支持
### 移动端
- **iOS**: App Store链接或企业分发链接
- **Android**: Google Play链接或APK直接下载
### 桌面端
- **Windows**: .exe安装包
- **Mac (Intel)**: Intel架构的.dmg安装包
- **Mac (M系列)**: Apple Silicon原生支持的.dmg安装包
- **Linux**: .AppImage或.deb/.rpm包
## 注意事项
1. **下载链接**: 确保下载链接长期有效,建议使用CDN或对象存储
2. **文件大小**: 建议填写准确的文件大小,方便用户了解下载时间
3. **版本管理**:
- 同一平台只能有一个"最新版本"
- 设置新版本为最新时,会自动将旧版本的最新标记<E6A087><E8AEB0>
4. **权限控制**: CRUD操作仅管理员可执行,查询接口公开访问
## 扩展建议
1. **统计功能**: 添加下载次数统计
2. **发布计划**: 支持定时发布新版本
3. **灰度发布**: 按百分比或用户组逐步推送新版本
4. **更新检查**: 提供SDK方便客户端集成版本检查
5. **更新强制**: 支持强制更新标记
## 文件清单
### 后端
- `backend/sql/client_downloads.sql` - 数据库表结构和初始数据
- `backend/app/models/models.py` - Pydantic数据模型
- `backend/app/api/endpoints/client_downloads.py` - API路由和业务逻辑
- `backend/main.py` - 路由注册
### 前端
- `frontend/src/pages/ClientManagement.jsx` - 管理员管理页面
- `frontend/src/pages/ClientManagement.css` - 管理页面样式
- `frontend/src/components/ClientDownloads.jsx` - 用户下载组件
- `frontend/src/components/ClientDownloads.css` - 下载组件样式
- `frontend/src/config/api.js` - API配置
## 技术栈
### 后端
- FastAPI
- MySQL
- Pydantic
### 前端
- React
- Lucide React Icons
- CSS3
## 作者
Generated with Claude Code

View File

@ -1,121 +0,0 @@
# 会议总结模板变量说明
## 概述
会议总结提示词模板支持使用变量占位符。只有在模板内容中显式写入变量时,系统才会替换对应值;未使用的变量不会自动追加到提示词中。
当前会议总结链路的推荐组装方式如下:
- `base_system_prompt`:放全局稳定规则,例如准确性要求、格式遵循、禁止编造;不要放会议业务指令
- 会议模板(`MEETING_TASK`):放任务级总结模板,会作为会议总结专用的 `system` 指令
- `user_prompt`:放本次用户的临时补充要求,例如侧重点、篇幅、风格
- 会议转录:单独作为用户消息输入,作为总结事实来源
这样可以把“规则”和“材料”分层,减少模型将转录内容误当成指令的概率。
## 支持的变量
### 1. 会议 ID
```text
{{meeting_id}}
```
输出当前会议的唯一 ID。
### 2. 会议标题
```text
{{meeting_title}}
```
输出当前会议标题。
### 3. 会议时间
默认格式输出:
```text
{{meeting_time}}
```
默认格式示例:
```text
2026-04-07 14:30:00
```
自定义格式输出:
```text
{{meeting_time:%Y年%m月%d日 %H:%M}}
```
自定义格式示例:
```text
2026年04月07日 14:30
```
如果未设置自定义格式,则使用默认格式。若自定义格式无法解析,系统会回退到默认时间值。
### 4. 会议创建人
```text
{{meeting_creator}}
```
输出会议创建人名称。
### 5. 参会人员
```text
{{meeting_attendees}}
```
输出参会人员名称列表,多个名字使用 `、` 连接。
## 可直接复制的变量列表
```text
{{meeting_id}}
{{meeting_title}}
{{meeting_time}}
{{meeting_time:%Y年%m月%d日 %H:%M}}
{{meeting_creator}}
{{meeting_attendees}}
```
## 模板示例
### 示例一:正式会议纪要
```text
请根据会议转录内容生成正式会议纪要。
会议标题:{{meeting_title}}
会议时间:{{meeting_time:%Y年%m月%d日 %H:%M}}
创建人:{{meeting_creator}}
参会人员:{{meeting_attendees}}
请输出:
1. 会议背景
2. 核心讨论
3. 决议事项
4. 待办事项
```
### 示例二:简洁总结
```text
请用简洁风格总结本次会议。
会议:{{meeting_title}}
时间:{{meeting_time}}
```
## 使用规则
- 变量必须使用双大括号包裹
- 仅当模板中写入变量时,系统才会替换对应内容
- `meeting_time` 支持自定义时间格式
- 未填写的字段可能返回空字符串

View File

@ -1,129 +0,0 @@
# iMeeting `imeeting_qy` 数据库升级报告
## 1. 升级目标
- 源旧库:`imeeting_qy`
- 对标最新结构库:`imeeting`
- 升级日期:`2026-04-03`
- 执行方式:先在临时测试库 `imeeting_qy_upgrade_test` 演练,再正式执行到 `imeeting_qy`
## 2. 备份信息
- 正式升级前已创建完整备份库:`imeeting_qy_backup_20260403_004354`
- 备份方式:同服务器整库复制全部 `BASE TABLE`
## 3. 本次执行内容
本次升级使用迁移脚本:
- `backend/sql/migrations/upgrade_imeeting_qy_to_latest.sql`
核心动作如下:
1. 将旧系统表标准化为 `sys_*` 体系:
- `users -> sys_users`
- `roles -> sys_roles`
- `menus -> sys_menus`
- `role_menu_permissions -> sys_role_menu_permissions`
- `dict_data -> sys_dict_data`
2. 重建兼容视图:
- `users`
- `roles`
- `menus`
- `role_menu_permissions`
- `dict_data`
- `system_parameters`
3. 对齐旧系统表字段与索引:
- `sys_users` 补齐 `idx_role_id`
- `sys_roles` 补齐 `uk_role_name`
- `sys_menus` 补齐 `menu_level/tree_path/is_visible` 及相关索引
- `sys_role_menu_permissions` 补齐 `granted_by/granted_at` 及相关索引
- `prompts` 补齐 `is_system` 字段及组合索引
- `terminals.current_user_id` 字段注释对齐到最新结构
4. 新增并初始化最新配置表:
- `sys_system_parameters`
- `ai_model_configs`
- `llm_model_config`
- `audio_model_config`
- `hot_word_group`
- `hot_word_item`
- `prompt_config`
- `sys_user_mcp`
5. 迁移旧配置数据:
- 从 `sys_dict_data(dict_type='system_config')` 迁移系统参数到 `sys_system_parameters`
- 迁移 LLM / ASR / 声纹配置到 `ai_model_configs`
- 拆分生成 `llm_model_config`、`audio_model_config`
- 从旧 `hot_words` 迁移到 `hot_word_group` / `hot_word_item`
6. 重建最新菜单树与角色授权模型:
- 新增 `dashboard`、`desktop`、`meeting_manage`、`system_management` 等最新菜单结构
- 规范平台管理、系统管理、会议管理三套菜单层级
- 管理员角色授予全部启用菜单
- 普通用户保留 `desktop/meeting_manage/meeting_center/prompt_config`
## 4. 升级结果
升级后关键表数据如下:
| 表名 | 行数 |
|---|---:|
| `sys_users` | 44 |
| `sys_roles` | 2 |
| `sys_menus` | 19 |
| `sys_role_menu_permissions` | 22 |
| `sys_system_parameters` | 4 |
| `ai_model_configs` | 3 |
| `llm_model_config` | 1 |
| `audio_model_config` | 2 |
| `hot_word_group` | 1 |
| `hot_word_item` | 20 |
| `prompt_config` | 0 |
| `sys_user_mcp` | 0 |
迁移后的系统参数:
| 参数键 | 参数值 |
|---|---|
| `asr_vocabulary_id` | `vocab-imeeting-734e93f5bd8a4f3bb665dd526d584516` |
| `default_reset_password` | `123456` |
| `max_audio_size` | `500` |
| `timeline_pagesize` | `20` |
迁移后的模型配置:
- `llm_model_config`1 条默认模型,`model_code=llm_model`
- `audio_model_config`2 条配置
- `audio_model` / `asr`
- `voiceprint_model` / `voiceprint`
迁移后的热词配置:
- `hot_word_group`1 个默认热词组
- `hot_word_item`20 条热词条目
## 5. 角色菜单结果
- 平台管理员:
- `dashboard, hot_word_management, user_management, meeting_center, desktop, meeting_manage, model_management, permission_management, prompt_config, prompt_management, platform_admin, dict_management, system_management, client_management, external_app_management, terminal_management, parameter_management, permission_menu_tree`
- 普通用户:
- `meeting_center, desktop, meeting_manage, prompt_config`
## 6. 结构校验结论
`imeeting_qy``imeeting` 进行了 `information_schema.tables` + `information_schema.columns` 级别的最终校验,结果如下:
- 缺失表:`0`
- 多余表:`0`
- 表类型差异:`0`
- 字段差异:`0`
结论:
- `imeeting_qy` 已完成升级
- 当前库结构已与 `imeeting` 对齐
- 本次升级为“结构对齐 + 必要配置数据迁移”,未删除旧业务数据