From 803a27fb84f90e6fe9c60282efb68c0df7d9873f Mon Sep 17 00:00:00 2001 From: iven Date: Wed, 27 May 2026 11:04:45 +0800 Subject: [PATCH] =?UTF-8?q?fix(db):=20=E7=9F=A5=E8=AF=86=E5=BA=93=20V2=20?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E8=BF=81=E7=A7=BB=20=E2=80=94=20PL/pgSQL=20?= =?UTF-8?q?=E5=AE=89=E5=85=A8=E6=A3=80=E6=9F=A5=20sys=5Fmenu=20=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 迁移 168 引用 sys_menu 表但在无基础 ERP 数据的数据库中不存在。 改用 DO $$ block + information_schema 检查,表不存在时安全跳过。 --- .../m20260527_000168_ai_knowledge_v2_menu.rs | 87 ++++++++++--------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/crates/erp-server/migration/src/m20260527_000168_ai_knowledge_v2_menu.rs b/crates/erp-server/migration/src/m20260527_000168_ai_knowledge_v2_menu.rs index 779f3ca..d545e3d 100644 --- a/crates/erp-server/migration/src/m20260527_000168_ai_knowledge_v2_menu.rs +++ b/crates/erp-server/migration/src/m20260527_000168_ai_knowledge_v2_menu.rs @@ -6,56 +6,65 @@ pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - // 在"AI 知识库"同级位置添加"知识库 V2"菜单 - // parent_id 取旧 ai-knowledge 菜单的 parent_id + // 安全插入:仅在 sys_menu 表存在且有 ai-knowledge 菜单时添加 V2 菜单 let sql = r#" - INSERT INTO sys_menu (id, parent_id, name, path, icon, sort, permission, component, is_external, is_cached, status, visible, created_at, updated_at, deleted_at) - SELECT - gen_random_uuid(), - parent_id, - '知识库 V2', - '/health/ai-knowledge-v2', - 'DatabaseOutlined', - 54, - 'ai.knowledge.list', - 'ai/KnowledgeV2Page', - false, - false, - 'active', - true, - now(), - now(), - NULL - FROM sys_menu - WHERE path = '/health/ai-knowledge' AND deleted_at IS NULL - LIMIT 1 - ON CONFLICT DO NOTHING + DO $$ + BEGIN + IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'sys_menu') THEN + INSERT INTO sys_menu (id, parent_id, name, path, icon, sort, permission, component, is_external, is_cached, status, visible, created_at, updated_at, deleted_at) + SELECT + gen_random_uuid(), + parent_id, + '知识库 V2', + '/health/ai-knowledge-v2', + 'DatabaseOutlined', + 54, + 'ai.knowledge.list', + 'ai/KnowledgeV2Page', + false, + false, + 'active', + true, + now(), + now(), + NULL + FROM sys_menu + WHERE path = '/health/ai-knowledge' AND deleted_at IS NULL + LIMIT 1 + ON CONFLICT DO NOTHING; + + IF FOUND THEN + INSERT INTO sys_role_menu (role_id, menu_id) + SELECT r.id, m.id + FROM sys_role r, sys_menu m + WHERE r.code = 'admin' AND r.deleted_at IS NULL + AND m.path = '/health/ai-knowledge-v2' AND m.deleted_at IS NULL + ON CONFLICT DO NOTHING; + END IF; + END IF; + END; + $$ LANGUAGE plpgsql "#; manager.get_connection().execute_unprepared(sql).await?; - // 绑定到 admin 角色 - let role_sql = r#" - INSERT INTO sys_role_menu (role_id, menu_id) - SELECT r.id, m.id - FROM sys_role r, sys_menu m - WHERE r.code = 'admin' AND r.deleted_at IS NULL - AND m.path = '/health/ai-knowledge-v2' AND m.deleted_at IS NULL - ON CONFLICT DO NOTHING - "#; - - manager - .get_connection() - .execute_unprepared(role_sql) - .await?; - Ok(()) } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { manager .get_connection() - .execute_unprepared("DELETE FROM sys_menu WHERE path = '/health/ai-knowledge-v2'") + .execute_unprepared( + r#" + DO $$ + BEGIN + IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'sys_menu') THEN + DELETE FROM sys_menu WHERE path = '/health/ai-knowledge-v2'; + END IF; + END; + $$ LANGUAGE plpgsql + "#, + ) .await?; Ok(()) }