diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.Designer.cs
new file mode 100644
index 0000000..d7309a7
--- /dev/null
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.Designer.cs
@@ -0,0 +1,548 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using TakeoutSaaS.Infrastructure.Identity.Persistence;
+
+#nullable disable
+
+namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb
+{
+ [DbContext(typeof(IdentityDbContext))]
+ [Migration("20251204070039_AddRoleTemplateTables")]
+ partial class AddRoleTemplateTables
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.0")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Account")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("登录账号。");
+
+ b.Property("Avatar")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("头像地址。");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("展示名称。");
+
+ b.Property("MerchantId")
+ .HasColumnType("bigint")
+ .HasComment("所属商户(平台管理员为空)。");
+
+ b.Property("PasswordHash")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("密码哈希。");
+
+ b.Property("TenantId")
+ .HasColumnType("bigint")
+ .HasComment("所属租户 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.HasIndex("TenantId", "Account")
+ .IsUnique();
+
+ b.ToTable("identity_users", null, t =>
+ {
+ t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Avatar")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("头像地址。");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("Nickname")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("昵称。");
+
+ b.Property("OpenId")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)")
+ .HasComment("微信 OpenId。");
+
+ b.Property("TenantId")
+ .HasColumnType("bigint")
+ .HasComment("所属租户 ID。");
+
+ b.Property("UnionId")
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)")
+ .HasComment("微信 UnionId,可能为空。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.HasIndex("TenantId", "OpenId")
+ .IsUnique();
+
+ b.ToTable("mini_users", null, t =>
+ {
+ t.HasComment("小程序用户实体。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Permission", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)")
+ .HasComment("权限编码(租户内唯一)。");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("Description")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("描述。");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("权限名称。");
+
+ b.Property("TenantId")
+ .HasColumnType("bigint")
+ .HasComment("所属租户 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.HasIndex("TenantId", "Code")
+ .IsUnique();
+
+ b.ToTable("permissions", null, t =>
+ {
+ t.HasComment("权限定义。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Role", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("角色编码(租户内唯一)。");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("Description")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("描述。");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("角色名称。");
+
+ b.Property("TenantId")
+ .HasColumnType("bigint")
+ .HasComment("所属租户 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.HasIndex("TenantId", "Code")
+ .IsUnique();
+
+ b.ToTable("roles", null, t =>
+ {
+ t.HasComment("角色定义。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RolePermission", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("PermissionId")
+ .HasColumnType("bigint")
+ .HasComment("权限 ID。");
+
+ b.Property("RoleId")
+ .HasColumnType("bigint")
+ .HasComment("角色 ID。");
+
+ b.Property("TenantId")
+ .HasColumnType("bigint")
+ .HasComment("所属租户 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.HasIndex("TenantId", "RoleId", "PermissionId")
+ .IsUnique();
+
+ b.ToTable("role_permissions", null, t =>
+ {
+ t.HasComment("角色-权限关系。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplate", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("Description")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("模板描述。");
+
+ b.Property("IsActive")
+ .HasColumnType("boolean")
+ .HasComment("是否启用。");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)")
+ .HasComment("模板名称。");
+
+ b.Property("TemplateCode")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("模板编码(唯一)。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TemplateCode")
+ .IsUnique();
+
+ b.ToTable("role_templates", null, t =>
+ {
+ t.HasComment("角色模板定义(平台级)。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplatePermission", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("PermissionCode")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)")
+ .HasComment("权限编码。");
+
+ b.Property("RoleTemplateId")
+ .HasColumnType("bigint")
+ .HasComment("模板 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleTemplateId", "PermissionCode")
+ .IsUnique();
+
+ b.ToTable("role_template_permissions", null, t =>
+ {
+ t.HasComment("角色模板-权限关系(平台级)。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.UserRole", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("RoleId")
+ .HasColumnType("bigint")
+ .HasComment("角色 ID。");
+
+ b.Property("TenantId")
+ .HasColumnType("bigint")
+ .HasComment("所属租户 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("UserId")
+ .HasColumnType("bigint")
+ .HasComment("用户 ID。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.HasIndex("TenantId", "UserId", "RoleId")
+ .IsUnique();
+
+ b.ToTable("user_roles", null, t =>
+ {
+ t.HasComment("用户-角色关系。");
+ });
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.cs
new file mode 100644
index 0000000..c540868
--- /dev/null
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070039_AddRoleTemplateTables.cs
@@ -0,0 +1,82 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb
+{
+ ///
+ public partial class AddRoleTemplateTables : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "role_template_permissions",
+ columns: table => new
+ {
+ Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。")
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ RoleTemplateId = table.Column(type: "bigint", nullable: false, comment: "模板 ID。"),
+ PermissionCode = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "权限编码。"),
+ CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"),
+ UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"),
+ DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"),
+ CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"),
+ UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"),
+ DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。")
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_role_template_permissions", x => x.Id);
+ },
+ comment: "角色模板-权限关系(平台级)。");
+
+ migrationBuilder.CreateTable(
+ name: "role_templates",
+ columns: table => new
+ {
+ Id = table.Column(type: "bigint", nullable: false, comment: "实体唯一标识。")
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ TemplateCode = table.Column(type: "character varying(64)", maxLength: 64, nullable: false, comment: "模板编码(唯一)。"),
+ Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false, comment: "模板名称。"),
+ Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true, comment: "模板描述。"),
+ IsActive = table.Column(type: "boolean", nullable: false, comment: "是否启用。"),
+ CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间(UTC)。"),
+ UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "最近一次更新时间(UTC),从未更新时为 null。"),
+ DeletedAt = table.Column(type: "timestamp with time zone", nullable: true, comment: "软删除时间(UTC),未删除时为 null。"),
+ CreatedBy = table.Column(type: "bigint", nullable: true, comment: "创建人用户标识,匿名或系统操作时为 null。"),
+ UpdatedBy = table.Column(type: "bigint", nullable: true, comment: "最后更新人用户标识,匿名或系统操作时为 null。"),
+ DeletedBy = table.Column(type: "bigint", nullable: true, comment: "删除人用户标识(软删除),未删除时为 null。")
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_role_templates", x => x.Id);
+ },
+ comment: "角色模板定义(平台级)。");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_role_template_permissions_RoleTemplateId_PermissionCode",
+ table: "role_template_permissions",
+ columns: new[] { "RoleTemplateId", "PermissionCode" },
+ unique: true);
+
+ migrationBuilder.CreateIndex(
+ name: "IX_role_templates_TemplateCode",
+ table: "role_templates",
+ column: "TemplateCode",
+ unique: true);
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "role_template_permissions");
+
+ migrationBuilder.DropTable(
+ name: "role_templates");
+ }
+ }
+}
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.Designer.cs
new file mode 100644
index 0000000..641de90
--- /dev/null
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.Designer.cs
@@ -0,0 +1,548 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using TakeoutSaaS.Infrastructure.Identity.Persistence;
+
+#nullable disable
+
+namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb
+{
+ [DbContext(typeof(IdentityDbContext))]
+ [Migration("20251204070108_AddRoleTemplateModel")]
+ partial class AddRoleTemplateModel
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.0")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.IdentityUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Account")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("登录账号。");
+
+ b.Property("Avatar")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("头像地址。");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("展示名称。");
+
+ b.Property("MerchantId")
+ .HasColumnType("bigint")
+ .HasComment("所属商户(平台管理员为空)。");
+
+ b.Property("PasswordHash")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("密码哈希。");
+
+ b.Property("TenantId")
+ .HasColumnType("bigint")
+ .HasComment("所属租户 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.HasIndex("TenantId", "Account")
+ .IsUnique();
+
+ b.ToTable("identity_users", null, t =>
+ {
+ t.HasComment("管理后台账户实体(平台管理员、租户管理员或商户员工)。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.MiniUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Avatar")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("头像地址。");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("Nickname")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("昵称。");
+
+ b.Property("OpenId")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)")
+ .HasComment("微信 OpenId。");
+
+ b.Property("TenantId")
+ .HasColumnType("bigint")
+ .HasComment("所属租户 ID。");
+
+ b.Property("UnionId")
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)")
+ .HasComment("微信 UnionId,可能为空。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.HasIndex("TenantId", "OpenId")
+ .IsUnique();
+
+ b.ToTable("mini_users", null, t =>
+ {
+ t.HasComment("小程序用户实体。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Permission", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)")
+ .HasComment("权限编码(租户内唯一)。");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("Description")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("描述。");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("权限名称。");
+
+ b.Property("TenantId")
+ .HasColumnType("bigint")
+ .HasComment("所属租户 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.HasIndex("TenantId", "Code")
+ .IsUnique();
+
+ b.ToTable("permissions", null, t =>
+ {
+ t.HasComment("权限定义。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.Role", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("角色编码(租户内唯一)。");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("Description")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("描述。");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("角色名称。");
+
+ b.Property("TenantId")
+ .HasColumnType("bigint")
+ .HasComment("所属租户 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.HasIndex("TenantId", "Code")
+ .IsUnique();
+
+ b.ToTable("roles", null, t =>
+ {
+ t.HasComment("角色定义。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RolePermission", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("PermissionId")
+ .HasColumnType("bigint")
+ .HasComment("权限 ID。");
+
+ b.Property("RoleId")
+ .HasColumnType("bigint")
+ .HasComment("角色 ID。");
+
+ b.Property("TenantId")
+ .HasColumnType("bigint")
+ .HasComment("所属租户 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.HasIndex("TenantId", "RoleId", "PermissionId")
+ .IsUnique();
+
+ b.ToTable("role_permissions", null, t =>
+ {
+ t.HasComment("角色-权限关系。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplate", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("Description")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("模板描述。");
+
+ b.Property("IsActive")
+ .HasColumnType("boolean")
+ .HasComment("是否启用。");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)")
+ .HasComment("模板名称。");
+
+ b.Property("TemplateCode")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("模板编码(唯一)。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TemplateCode")
+ .IsUnique();
+
+ b.ToTable("role_templates", null, t =>
+ {
+ t.HasComment("角色模板定义(平台级)。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplatePermission", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("PermissionCode")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)")
+ .HasComment("权限编码。");
+
+ b.Property("RoleTemplateId")
+ .HasColumnType("bigint")
+ .HasComment("模板 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleTemplateId", "PermissionCode")
+ .IsUnique();
+
+ b.ToTable("role_template_permissions", null, t =>
+ {
+ t.HasComment("角色模板-权限关系(平台级)。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.UserRole", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("RoleId")
+ .HasColumnType("bigint")
+ .HasComment("角色 ID。");
+
+ b.Property("TenantId")
+ .HasColumnType("bigint")
+ .HasComment("所属租户 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("UserId")
+ .HasColumnType("bigint")
+ .HasComment("用户 ID。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.HasIndex("TenantId", "UserId", "RoleId")
+ .IsUnique();
+
+ b.ToTable("user_roles", null, t =>
+ {
+ t.HasComment("用户-角色关系。");
+ });
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.cs
new file mode 100644
index 0000000..c3d38e4
--- /dev/null
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251204070108_AddRoleTemplateModel.cs
@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb
+{
+ ///
+ public partial class AddRoleTemplateModel : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+
+ }
+ }
+}
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/IdentityDbContextModelSnapshot.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/IdentityDbContextModelSnapshot.cs
index a98f3c3..01f7f4a 100644
--- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/IdentityDbContextModelSnapshot.cs
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/IdentityDbContextModelSnapshot.cs
@@ -363,6 +363,125 @@ namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb
});
});
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplate", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("Description")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)")
+ .HasComment("模板描述。");
+
+ b.Property("IsActive")
+ .HasColumnType("boolean")
+ .HasComment("是否启用。");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)")
+ .HasComment("模板名称。");
+
+ b.Property("TemplateCode")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasComment("模板编码(唯一)。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TemplateCode")
+ .IsUnique();
+
+ b.ToTable("role_templates", null, t =>
+ {
+ t.HasComment("角色模板定义(平台级)。");
+ });
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.RoleTemplatePermission", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasComment("实体唯一标识。");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("创建时间(UTC)。");
+
+ b.Property("CreatedBy")
+ .HasColumnType("bigint")
+ .HasComment("创建人用户标识,匿名或系统操作时为 null。");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("软删除时间(UTC),未删除时为 null。");
+
+ b.Property("DeletedBy")
+ .HasColumnType("bigint")
+ .HasComment("删除人用户标识(软删除),未删除时为 null。");
+
+ b.Property("PermissionCode")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)")
+ .HasComment("权限编码。");
+
+ b.Property("RoleTemplateId")
+ .HasColumnType("bigint")
+ .HasComment("模板 ID。");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("最近一次更新时间(UTC),从未更新时为 null。");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("bigint")
+ .HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleTemplateId", "PermissionCode")
+ .IsUnique();
+
+ b.ToTable("role_template_permissions", null, t =>
+ {
+ t.HasComment("角色模板-权限关系(平台级)。");
+ });
+ });
+
modelBuilder.Entity("TakeoutSaaS.Domain.Identity.Entities.UserRole", b =>
{
b.Property("Id")