From 1ae97953612e2b13d88bf4bbbaaf6870497ef3be Mon Sep 17 00:00:00 2001 From: xiangning Date: Fri, 3 Jul 2026 18:23:25 +0800 Subject: [PATCH] =?UTF-8?q?refactor(platform):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E8=A1=A8=E7=BB=93=E6=9E=84=E5=B9=B6=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E5=91=BD=E5=90=8D=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除旧版 PascalCase 列名的 menus 表 - 创建符合 snake_case 规范的新 menus 表结构 - 添加完整的菜单字段包括 ID、名称、路径、组件、重定向等 - 实现菜单层级关系的父子关联外键约束 - 增加菜单权限控制相关字段如角色授权、可见性等 - 统一时间戳和软删除标准字段 - 创建菜单编码唯一索引和父级关联索引 --- .../Migrations/20260703084733_AddMenuCode.cs | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/src/modules/platform/Infrastructure/Migrations/20260703084733_AddMenuCode.cs b/src/modules/platform/Infrastructure/Migrations/20260703084733_AddMenuCode.cs index a4d8c9c..cb47009 100644 --- a/src/modules/platform/Infrastructure/Migrations/20260703084733_AddMenuCode.cs +++ b/src/modules/platform/Infrastructure/Migrations/20260703084733_AddMenuCode.cs @@ -1,4 +1,5 @@ -using Microsoft.EntityFrameworkCore.Migrations; +using System; +using Microsoft.EntityFrameworkCore.Migrations; #nullable disable @@ -10,20 +11,61 @@ namespace Platform.Infrastructure.Migrations /// protected override void Up(MigrationBuilder migrationBuilder) { - migrationBuilder.AddColumn( - name: "code", - table: "menus", - type: "character varying(100)", - maxLength: 100, - nullable: false, - defaultValue: "", - comment: "菜单编码,点号分层(system / system.user),全局唯一"); + // 历史库的 menus 表由旧版本(PascalCase 列名)创建,与当前 EF 模型(snake_case) + // 完全不匹配,且数据为旧业务残留(点单台/租号监控等,path 在当前前端不存在)。 + // 菜单是配置型数据,这里 DROP 旧表并按当前 snake_case 模型重建,由 SeedMenusAsync 重新播种。 + migrationBuilder.Sql("DROP TABLE IF EXISTS menus;"); + + migrationBuilder.CreateTable( + name: "menus", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false, comment: "菜单ID"), + name = table.Column(type: "character varying(100)", maxLength: 100, nullable: false, comment: "菜单名称(路由name)"), + path = table.Column(type: "character varying(200)", maxLength: 200, nullable: false, comment: "路由路径"), + component = table.Column(type: "character varying(200)", maxLength: 200, nullable: true, comment: "前端组件路径"), + redirect = table.Column(type: "character varying(200)", maxLength: 200, nullable: true, comment: "重定向路径"), + parent_id = table.Column(type: "uuid", nullable: true, comment: "父菜单ID,null表示顶级菜单"), + title = table.Column(type: "character varying(100)", maxLength: 100, nullable: false, comment: "菜单显示标题"), + code = table.Column(type: "character varying(100)", maxLength: 100, nullable: false, comment: "菜单编码,点号分层(system / system.user),全局唯一"), + icon = table.Column(type: "character varying(100)", maxLength: 100, nullable: true, comment: "菜单图标"), + active_icon = table.Column(type: "character varying(100)", maxLength: 100, nullable: true, comment: "菜单激活状态图标"), + order = table.Column(type: "integer", nullable: false, comment: "排序序号,值越小越靠前"), + hide_in_menu = table.Column(type: "boolean", nullable: false, comment: "是否在菜单中隐藏"), + keep_alive = table.Column(type: "boolean", nullable: true, comment: "是否缓存页面状态"), + affix_tab = table.Column(type: "boolean", nullable: true, comment: "是否固定标签页"), + link = table.Column(type: "character varying(500)", maxLength: 500, nullable: true, comment: "外链地址"), + no_basic_layout = table.Column(type: "boolean", nullable: false, comment: "是否不使用基础布局"), + menu_visible_with_forbidden = table.Column(type: "boolean", nullable: false, comment: "无权限时是否仍显示菜单"), + authority = table.Column(type: "character varying(200)", maxLength: 200, nullable: true, comment: "允许访问的角色名,逗号分隔,为空表示所有已认证用户可访问"), + created_by = table.Column(type: "character varying(100)", maxLength: 100, nullable: false, comment: "创建人"), + created_at = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间"), + updated_by = table.Column(type: "character varying(100)", maxLength: 100, nullable: false, comment: "更新人"), + updated_at = table.Column(type: "timestamp with time zone", nullable: false, comment: "更新时间"), + is_deleted = table.Column(type: "boolean", nullable: false, defaultValue: false, comment: "是否已软删除"), + operator_ip = table.Column(type: "character varying(50)", maxLength: 50, nullable: false, comment: "操作者IP地址") + }, + constraints: table => + { + table.PrimaryKey("pk_menus", x => x.id); + table.ForeignKey( + name: "fk_menus_menus_parent_id", + column: x => x.parent_id, + principalTable: "menus", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); migrationBuilder.CreateIndex( name: "ix_menus_code", table: "menus", column: "code", unique: true); + + migrationBuilder.CreateIndex( + name: "ix_menus_parent_id", + table: "menus", + column: "parent_id"); } ///