feat: add EF column comments for all entities, docker-compose with init SQL

This commit is contained in:
向宁 2026-05-25 20:33:20 +08:00
parent ca7463d42b
commit d742ed93ce
20 changed files with 4103 additions and 217 deletions

View File

@ -1,7 +1,9 @@
services:
# --- PostgreSQL (pgvector) ---
postgres:
image: pgvector/pgvector:pg17
container_name: rag-postgres
restart: unless-stopped
environment:
POSTGRES_DB: rag
POSTGRES_USER: rag
@ -19,9 +21,11 @@ services:
timeout: 5s
retries: 5
# --- Redis ---
redis:
image: redis:7-alpine
container_name: rag-redis
restart: unless-stopped
ports:
- "6379:6379"
volumes:
@ -34,9 +38,11 @@ services:
timeout: 5s
retries: 5
# --- RabbitMQ ---
rabbitmq:
image: rabbitmq:3-management
container_name: rag-rabbitmq
restart: unless-stopped
environment:
RABBITMQ_DEFAULT_USER: rag
RABBITMQ_DEFAULT_PASS: rag123
@ -53,10 +59,55 @@ services:
timeout: 10s
retries: 5
# --- MongoDB (im-system) ---
mongo:
image: mongo:7
container_name: rag-mongo
restart: unless-stopped
environment:
MONGO_INITDB_ROOT_USERNAME: mongo
MONGO_INITDB_ROOT_PASSWORD: mongo123
ports:
- "27017:27017"
volumes:
- mongodata:/data/db
networks:
- rag-network
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 5s
timeout: 5s
retries: 5
# --- RustFS (S3 compatible, file-system) ---
rustfs:
image: rustfs/rustfs:latest
container_name: rag-rustfs
restart: unless-stopped
environment:
RUSTFS_ROOT_USER: minioadmin
RUSTFS_ROOT_PASSWORD: minioadmin
command: server /data --console-address ":9001"
ports:
- "9000:9000"
- "9001:9001"
volumes:
- rustfsdata:/data
networks:
- rag-network
healthcheck:
test: ["CMD", "sh", "-c", "nc -z localhost 9000"]
interval: 5s
timeout: 5s
retries: 5
start_period: 10s
volumes:
pgdata:
redisdata:
rabbitdata:
mongodata:
rustfsdata:
networks:
rag-network:

View File

@ -1 +1,19 @@
-- pgvector for rag database
\c rag;
CREATE EXTENSION IF NOT EXISTS vector;
-- Create databases for other services (idempotent)
\c postgres;
DO $$
BEGIN
IF NOT EXISTS (SELECT FROM pg_database WHERE datname = 'im_system') THEN
PERFORM dblink_exec('dbname=postgres', 'CREATE DATABASE im_system');
END IF;
IF NOT EXISTS (SELECT FROM pg_database WHERE datname = 'workflow') THEN
PERFORM dblink_exec('dbname=postgres', 'CREATE DATABASE workflow');
END IF;
IF NOT EXISTS (SELECT FROM pg_database WHERE datname = 'file_system') THEN
PERFORM dblink_exec('dbname=postgres', 'CREATE DATABASE file_system');
END IF;
END
$$;

View File

@ -7,11 +7,12 @@ using Volo.Abp.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// OTel 日志导出
var otlpEndpoint = builder.Configuration["OpenTelemetry:OtlpEndpoint"] ?? "http://localhost:4316";
builder.Logging.AddOpenTelemetry(logging =>
{
logging.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("http://192.168.1.154:4316");
options.Endpoint = new Uri(otlpEndpoint);
});
});

View File

@ -27,6 +27,7 @@ public class RAGApiModule : AbpModule
var config = services.GetConfiguration();
// OpenTelemetry
var otlpEndpoint = config["OpenTelemetry:OtlpEndpoint"] ?? "http://localhost:4316";
services.AddOpenTelemetry()
.ConfigureResource(r => r
.AddService(serviceName: "rag-backend", serviceVersion: "1.0.0"))
@ -36,7 +37,7 @@ public class RAGApiModule : AbpModule
.AddEntityFrameworkCoreInstrumentation()
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("http://192.168.1.154:4316");
options.Endpoint = new Uri(otlpEndpoint);
}))
.WithMetrics(metrics => metrics
.AddAspNetCoreInstrumentation()
@ -44,7 +45,7 @@ public class RAGApiModule : AbpModule
.AddRuntimeInstrumentation()
.AddOtlpExporter((exporterOptions, readerOptions) =>
{
exporterOptions.Endpoint = new Uri("http://192.168.1.154:4316");
exporterOptions.Endpoint = new Uri(otlpEndpoint);
}));
// FastEndpoints + Swagger

View File

@ -25,8 +25,8 @@
"RabbitMq": {
"Host": "localhost",
"Port": 5672,
"Username": "guest",
"Password": "guest"
"Username": "rag",
"Password": "rag123"
},
"Jwt": {
"SigningKey": "RagJwtSecretKey2026MustBeAtLeast32CharsLong!",
@ -36,6 +36,9 @@
"Cookie": {
"Secure": false
},
"OpenTelemetry": {
"OtlpEndpoint": "http://localhost:4316"
},
"Ai": {
"BaseUrl": "http://localhost:1234/v1",
"ApiKey": "lm-studio",

View File

@ -10,12 +10,17 @@ public class ChatMessageConfiguration : IEntityTypeConfiguration<ChatMessage>
{
builder.ToTable("chat_messages");
builder.HasKey(m => m.Id);
builder.Property(m => m.Id).ValueGeneratedNever();
builder.Property(m => m.Id).ValueGeneratedNever().HasComment("消息ID");
builder.Property(m => m.Content).IsRequired();
builder.Property(m => m.Role).IsRequired();
builder.Property(m => m.ConversationId).HasComment("所属会话ID");
builder.Property(m => m.Role).IsRequired().HasComment("消息角色System=0, User=1, Assistant=2");
builder.Property(m => m.Content).IsRequired().HasComment("消息内容");
builder.Property(m => m.TokenUsage).HasComment("本次消息消耗的Token数");
builder.Property(m => m.CreatedBy).HasMaxLength(100);
builder.Property(m => m.UpdatedBy).HasMaxLength(100);
// IAuditable
builder.Property(m => m.CreatedBy).HasMaxLength(100).HasComment("创建人");
builder.Property(m => m.CreatedAt).HasComment("创建时间");
builder.Property(m => m.UpdatedBy).HasMaxLength(100).HasComment("更新人");
builder.Property(m => m.UpdatedAt).HasComment("更新时间");
}
}

View File

@ -10,15 +10,23 @@ public class ConversationConfiguration : IEntityTypeConfiguration<Conversation>
{
builder.ToTable("conversations");
builder.HasKey(c => c.Id);
builder.Property(c => c.Id).ValueGeneratedNever();
builder.Property(c => c.Id).ValueGeneratedNever().HasComment("会话ID");
builder.Property(c => c.Title).HasMaxLength(200).IsRequired();
builder.Property(c => c.KnowledgeBaseId).IsRequired(false);
builder.Property(c => c.Title).HasMaxLength(200).IsRequired().HasComment("会话标题");
builder.Property(c => c.UserId).HasComment("所属用户ID");
builder.Property(c => c.KnowledgeBaseId).IsRequired(false).HasComment("关联知识库IDnull表示普通对话");
builder.Property(c => c.CreatedBy).HasMaxLength(100);
builder.Property(c => c.UpdatedBy).HasMaxLength(100);
builder.Property(c => c.IsDeleted).HasDefaultValue(false);
builder.Property(c => c.OperatorIP).HasMaxLength(50);
// IAuditable
builder.Property(c => c.CreatedBy).HasMaxLength(100).HasComment("创建人");
builder.Property(c => c.CreatedAt).HasComment("创建时间");
builder.Property(c => c.UpdatedBy).HasMaxLength(100).HasComment("更新人");
builder.Property(c => c.UpdatedAt).HasComment("更新时间");
// ISoftDelete
builder.Property(c => c.IsDeleted).HasDefaultValue(false).HasComment("是否已软删除");
// IHasOperatorIP
builder.Property(c => c.OperatorIP).HasMaxLength(50).HasComment("操作者IP地址");
builder.HasOne(c => c.User)
.WithMany()

View File

@ -10,13 +10,19 @@ public class DocumentChunkConfiguration : IEntityTypeConfiguration<DocumentChunk
{
builder.ToTable("document_chunks");
builder.HasKey(c => c.Id);
builder.Property(c => c.Id).ValueGeneratedNever();
builder.Property(c => c.Id).ValueGeneratedNever().HasComment("文档分块ID");
builder.Property(c => c.Content).IsRequired();
builder.Ignore(c => c.Embedding);
builder.Property(c => c.DocumentId).HasComment("所属文档ID");
builder.Property(c => c.Content).IsRequired().HasComment("分块文本内容");
builder.Property(c => c.ChunkIndex).HasComment("分块序号从0开始");
builder.Property(c => c.TokenCount).HasComment("分块Token数量");
builder.Ignore(c => c.Embedding); // 向量字段使用pgvector不通过EF Core映射
builder.Property(c => c.CreatedBy).HasMaxLength(100);
builder.Property(c => c.UpdatedBy).HasMaxLength(100);
// IAuditable
builder.Property(c => c.CreatedBy).HasMaxLength(100).HasComment("创建人");
builder.Property(c => c.CreatedAt).HasComment("创建时间");
builder.Property(c => c.UpdatedBy).HasMaxLength(100).HasComment("更新人");
builder.Property(c => c.UpdatedAt).HasComment("更新时间");
builder.HasIndex(c => c.DocumentId);
}

View File

@ -10,17 +10,28 @@ public class DocumentConfiguration : IEntityTypeConfiguration<Document>
{
builder.ToTable("documents");
builder.HasKey(d => d.Id);
builder.Property(d => d.Id).ValueGeneratedNever();
builder.Property(d => d.Id).ValueGeneratedNever().HasComment("文档ID");
builder.Property(d => d.Title).HasMaxLength(500).IsRequired();
builder.Property(d => d.FileName).HasMaxLength(500).IsRequired();
builder.Property(d => d.FilePath).HasMaxLength(1000).IsRequired();
builder.Property(d => d.ContentType).HasMaxLength(100).IsRequired();
builder.Property(d => d.KnowledgeBaseId).HasComment("所属知识库ID");
builder.Property(d => d.Title).HasMaxLength(500).IsRequired().HasComment("文档标题");
builder.Property(d => d.FileName).HasMaxLength(500).IsRequired().HasComment("原始文件名");
builder.Property(d => d.FilePath).HasMaxLength(1000).IsRequired().HasComment("文件存储路径");
builder.Property(d => d.FileSize).HasComment("文件大小(字节)");
builder.Property(d => d.ContentType).HasMaxLength(100).IsRequired().HasComment("文件MIME类型");
builder.Property(d => d.ChunkCount).HasComment("分块数量");
builder.Property(d => d.Status).HasComment("文档状态Pending=0, Processing=1, Completed=2, Failed=3");
builder.Property(d => d.CreatedBy).HasMaxLength(100);
builder.Property(d => d.UpdatedBy).HasMaxLength(100);
builder.Property(d => d.IsDeleted).HasDefaultValue(false);
builder.Property(d => d.OperatorIP).HasMaxLength(50);
// IAuditable
builder.Property(d => d.CreatedBy).HasMaxLength(100).HasComment("创建人");
builder.Property(d => d.CreatedAt).HasComment("创建时间");
builder.Property(d => d.UpdatedBy).HasMaxLength(100).HasComment("更新人");
builder.Property(d => d.UpdatedAt).HasComment("更新时间");
// ISoftDelete
builder.Property(d => d.IsDeleted).HasDefaultValue(false).HasComment("是否已软删除");
// IHasOperatorIP
builder.Property(d => d.OperatorIP).HasMaxLength(50).HasComment("操作者IP地址");
builder.HasMany(d => d.Chunks)
.WithOne(c => c.Document)

View File

@ -10,16 +10,26 @@ public class KnowledgeBaseConfiguration : IEntityTypeConfiguration<KnowledgeBase
{
builder.ToTable("knowledge_bases");
builder.HasKey(k => k.Id);
builder.Property(k => k.Id).ValueGeneratedNever();
builder.Property(k => k.Id).ValueGeneratedNever().HasComment("知识库ID");
builder.Property(k => k.Name).HasMaxLength(200).IsRequired();
builder.Property(k => k.Description).HasMaxLength(1000);
builder.Property(k => k.EmbeddingModel).HasMaxLength(100).IsRequired();
builder.Property(k => k.Name).HasMaxLength(200).IsRequired().HasComment("知识库名称");
builder.Property(k => k.Description).HasMaxLength(1000).HasComment("知识库描述");
builder.Property(k => k.EmbeddingModel).HasMaxLength(100).IsRequired().HasComment("嵌入模型名称");
builder.Property(k => k.ChunkSize).HasComment("分块大小(字符数)");
builder.Property(k => k.ChunkOverlap).HasComment("分块重叠大小(字符数)");
builder.Property(k => k.Status).HasComment("知识库状态Active=0, Inactive=1");
builder.Property(k => k.CreatedBy).HasMaxLength(100);
builder.Property(k => k.UpdatedBy).HasMaxLength(100);
builder.Property(k => k.IsDeleted).HasDefaultValue(false);
builder.Property(k => k.OperatorIP).HasMaxLength(50);
// IAuditable
builder.Property(k => k.CreatedBy).HasMaxLength(100).HasComment("创建人");
builder.Property(k => k.CreatedAt).HasComment("创建时间");
builder.Property(k => k.UpdatedBy).HasMaxLength(100).HasComment("更新人");
builder.Property(k => k.UpdatedAt).HasComment("更新时间");
// ISoftDelete
builder.Property(k => k.IsDeleted).HasDefaultValue(false).HasComment("是否已软删除");
// IHasOperatorIP
builder.Property(k => k.OperatorIP).HasMaxLength(50).HasComment("操作者IP地址");
builder.HasMany(k => k.Documents)
.WithOne(d => d.KnowledgeBase)

View File

@ -10,27 +10,36 @@ public class MenuConfiguration : IEntityTypeConfiguration<Menu>
{
builder.ToTable("menus");
builder.HasKey(m => m.Id);
builder.Property(m => m.Id).ValueGeneratedNever();
builder.Property(m => m.Id).ValueGeneratedNever().HasComment("菜单ID");
builder.Property(m => m.Name).HasMaxLength(100).IsRequired();
builder.Property(m => m.Path).HasMaxLength(200).IsRequired();
builder.Property(m => m.Component).HasMaxLength(200);
builder.Property(m => m.Redirect).HasMaxLength(200);
builder.Property(m => m.Title).HasMaxLength(100).IsRequired();
builder.Property(m => m.Icon).HasMaxLength(100);
builder.Property(m => m.ActiveIcon).HasMaxLength(100);
builder.Property(m => m.Link).HasMaxLength(500);
builder.Property(m => m.Authority).HasMaxLength(200);
builder.Property(m => m.Name).HasMaxLength(100).IsRequired().HasComment("菜单名称路由name");
builder.Property(m => m.Path).HasMaxLength(200).IsRequired().HasComment("路由路径");
builder.Property(m => m.Component).HasMaxLength(200).HasComment("前端组件路径");
builder.Property(m => m.Redirect).HasMaxLength(200).HasComment("重定向路径");
builder.Property(m => m.ParentId).HasComment("父菜单IDnull表示顶级菜单");
builder.Property(m => m.Title).HasMaxLength(100).IsRequired().HasComment("菜单显示标题");
builder.Property(m => m.Icon).HasMaxLength(100).HasComment("菜单图标");
builder.Property(m => m.ActiveIcon).HasMaxLength(100).HasComment("菜单激活状态图标");
builder.Property(m => m.Order).HasComment("排序序号,值越小越靠前");
builder.Property(m => m.HideInMenu).HasComment("是否在菜单中隐藏");
builder.Property(m => m.KeepAlive).HasComment("是否缓存页面状态");
builder.Property(m => m.AffixTab).HasComment("是否固定标签页");
builder.Property(m => m.Link).HasMaxLength(500).HasComment("外链地址");
builder.Property(m => m.NoBasicLayout).HasComment("是否不使用基础布局");
builder.Property(m => m.MenuVisibleWithForbidden).HasComment("无权限时是否仍显示菜单");
builder.Property(m => m.Authority).HasMaxLength(200).HasComment("允许访问的角色名,逗号分隔,为空表示所有已认证用户可访问");
// IAuditable
builder.Property(m => m.CreatedBy).HasMaxLength(100);
builder.Property(m => m.UpdatedBy).HasMaxLength(100);
builder.Property(m => m.CreatedBy).HasMaxLength(100).HasComment("创建人");
builder.Property(m => m.CreatedAt).HasComment("创建时间");
builder.Property(m => m.UpdatedBy).HasMaxLength(100).HasComment("更新人");
builder.Property(m => m.UpdatedAt).HasComment("更新时间");
// ISoftDelete
builder.Property(m => m.IsDeleted).HasDefaultValue(false);
builder.Property(m => m.IsDeleted).HasDefaultValue(false).HasComment("是否已软删除");
// IHasOperatorIP
builder.Property(m => m.OperatorIP).HasMaxLength(50);
builder.Property(m => m.OperatorIP).HasMaxLength(50).HasComment("操作者IP地址");
// 自引用:父菜单
builder.HasOne(m => m.Parent)

View File

@ -10,21 +10,23 @@ public class PermissionConfiguration : IEntityTypeConfiguration<Permission>
{
builder.ToTable("permissions");
builder.HasKey(p => p.Id);
builder.Property(p => p.Id).ValueGeneratedNever();
builder.Property(p => p.Name).HasMaxLength(100).IsRequired();
builder.Property(p => p.Code).HasMaxLength(50).IsRequired();
builder.Property(p => p.Description).HasMaxLength(200);
builder.Property(p => p.Group).HasMaxLength(50);
builder.Property(p => p.Id).ValueGeneratedNever().HasComment("权限ID");
builder.Property(p => p.Name).HasMaxLength(100).IsRequired().HasComment("权限名称");
builder.Property(p => p.Code).HasMaxLength(50).IsRequired().HasComment("权限编码,如 user:create唯一");
builder.Property(p => p.Description).HasMaxLength(200).HasComment("权限描述");
builder.Property(p => p.Group).HasMaxLength(50).HasComment("权限分组");
// IAuditable
builder.Property(p => p.CreatedBy).HasMaxLength(100);
builder.Property(p => p.UpdatedBy).HasMaxLength(100);
builder.Property(p => p.CreatedBy).HasMaxLength(100).HasComment("创建人");
builder.Property(p => p.CreatedAt).HasComment("创建时间");
builder.Property(p => p.UpdatedBy).HasMaxLength(100).HasComment("更新人");
builder.Property(p => p.UpdatedAt).HasComment("更新时间");
// ISoftDelete
builder.Property(p => p.IsDeleted).HasDefaultValue(false);
builder.Property(p => p.IsDeleted).HasDefaultValue(false).HasComment("是否已软删除");
// IHasOperatorIP
builder.Property(p => p.OperatorIP).HasMaxLength(50);
builder.Property(p => p.OperatorIP).HasMaxLength(50).HasComment("操作者IP地址");
builder.HasIndex(p => p.Code).IsUnique();

View File

@ -10,12 +10,17 @@ public class RefreshTokenConfiguration : IEntityTypeConfiguration<RefreshToken>
{
builder.ToTable("refresh_tokens");
builder.HasKey(rt => rt.Id);
builder.Property(rt => rt.Id).ValueGeneratedNever();
builder.Property(rt => rt.Token).HasMaxLength(200).IsRequired();
builder.Property(rt => rt.Id).ValueGeneratedNever().HasComment("刷新令牌ID");
builder.Property(rt => rt.UserId).HasComment("关联用户ID");
builder.Property(rt => rt.Token).HasMaxLength(200).IsRequired().HasComment("刷新令牌值,唯一");
builder.Property(rt => rt.ExpiresAt).HasComment("令牌过期时间");
builder.Property(rt => rt.IsRevoked).HasComment("是否已撤销");
// IAuditable
builder.Property(rt => rt.CreatedBy).HasMaxLength(100);
builder.Property(rt => rt.UpdatedBy).HasMaxLength(100);
builder.Property(rt => rt.CreatedBy).HasMaxLength(100).HasComment("创建人");
builder.Property(rt => rt.CreatedAt).HasComment("创建时间");
builder.Property(rt => rt.UpdatedBy).HasMaxLength(100).HasComment("更新人");
builder.Property(rt => rt.UpdatedAt).HasComment("更新时间");
builder.HasIndex(rt => rt.Token).IsUnique();

View File

@ -10,19 +10,21 @@ public class RoleConfiguration : IEntityTypeConfiguration<Role>
{
builder.ToTable("roles");
builder.HasKey(r => r.Id);
builder.Property(r => r.Id).ValueGeneratedNever();
builder.Property(r => r.Name).HasMaxLength(50).IsRequired();
builder.Property(r => r.Description).HasMaxLength(200);
builder.Property(r => r.Id).ValueGeneratedNever().HasComment("角色ID");
builder.Property(r => r.Name).HasMaxLength(50).IsRequired().HasComment("角色名称,唯一");
builder.Property(r => r.Description).HasMaxLength(200).HasComment("角色描述");
// IAuditable
builder.Property(r => r.CreatedBy).HasMaxLength(100);
builder.Property(r => r.UpdatedBy).HasMaxLength(100);
builder.Property(r => r.CreatedBy).HasMaxLength(100).HasComment("创建人");
builder.Property(r => r.CreatedAt).HasComment("创建时间");
builder.Property(r => r.UpdatedBy).HasMaxLength(100).HasComment("更新人");
builder.Property(r => r.UpdatedAt).HasComment("更新时间");
// ISoftDelete
builder.Property(r => r.IsDeleted).HasDefaultValue(false);
builder.Property(r => r.IsDeleted).HasDefaultValue(false).HasComment("是否已软删除");
// IHasOperatorIP
builder.Property(r => r.OperatorIP).HasMaxLength(50);
builder.Property(r => r.OperatorIP).HasMaxLength(50).HasComment("操作者IP地址");
builder.HasIndex(r => r.Name).IsUnique();

View File

@ -10,9 +10,13 @@ public class RolePermissionConfiguration : IEntityTypeConfiguration<RolePermissi
{
builder.ToTable("role_permissions");
builder.HasKey(rp => new { rp.RoleId, rp.PermissionId });
builder.Property(rp => rp.RoleId).HasComment("角色ID");
builder.Property(rp => rp.PermissionId).HasComment("权限ID");
// IAuditable
builder.Property(rp => rp.CreatedBy).HasMaxLength(100);
builder.Property(rp => rp.UpdatedBy).HasMaxLength(100);
builder.Property(rp => rp.CreatedBy).HasMaxLength(100).HasComment("创建人");
builder.Property(rp => rp.CreatedAt).HasComment("创建时间");
builder.Property(rp => rp.UpdatedBy).HasMaxLength(100).HasComment("更新人");
builder.Property(rp => rp.UpdatedAt).HasComment("更新时间");
}
}

View File

@ -10,21 +10,23 @@ public class UserConfiguration : IEntityTypeConfiguration<User>
{
builder.ToTable("users");
builder.HasKey(u => u.Id);
builder.Property(u => u.Id).ValueGeneratedNever();
builder.Property(u => u.Username).HasMaxLength(50).IsRequired();
builder.Property(u => u.Email).HasMaxLength(100).IsRequired();
builder.Property(u => u.PasswordHash).HasMaxLength(200).IsRequired();
builder.Property(u => u.IsActive).HasDefaultValue(true);
builder.Property(u => u.Id).ValueGeneratedNever().HasComment("用户ID");
builder.Property(u => u.Username).HasMaxLength(50).IsRequired().HasComment("用户名,唯一");
builder.Property(u => u.Email).HasMaxLength(100).IsRequired().HasComment("邮箱地址,唯一");
builder.Property(u => u.PasswordHash).HasMaxLength(200).IsRequired().HasComment("密码哈希值");
builder.Property(u => u.IsActive).HasDefaultValue(true).HasComment("是否启用,停用后禁止登录");
// IAuditable
builder.Property(u => u.CreatedBy).HasMaxLength(100);
builder.Property(u => u.UpdatedBy).HasMaxLength(100);
builder.Property(u => u.CreatedBy).HasMaxLength(100).HasComment("创建人");
builder.Property(u => u.CreatedAt).HasComment("创建时间");
builder.Property(u => u.UpdatedBy).HasMaxLength(100).HasComment("更新人");
builder.Property(u => u.UpdatedAt).HasComment("更新时间");
// ISoftDelete
builder.Property(u => u.IsDeleted).HasDefaultValue(false);
builder.Property(u => u.IsDeleted).HasDefaultValue(false).HasComment("是否已软删除");
// IHasOperatorIP
builder.Property(u => u.OperatorIP).HasMaxLength(50);
builder.Property(u => u.OperatorIP).HasMaxLength(50).HasComment("操作者IP地址");
builder.HasIndex(u => u.Username).IsUnique();
builder.HasIndex(u => u.Email).IsUnique();

View File

@ -10,9 +10,13 @@ public class UserRoleConfiguration : IEntityTypeConfiguration<UserRole>
{
builder.ToTable("user_roles");
builder.HasKey(ur => new { ur.UserId, ur.RoleId });
builder.Property(ur => ur.UserId).HasComment("用户ID");
builder.Property(ur => ur.RoleId).HasComment("角色ID");
// IAuditable
builder.Property(ur => ur.CreatedBy).HasMaxLength(100);
builder.Property(ur => ur.UpdatedBy).HasMaxLength(100);
builder.Property(ur => ur.CreatedBy).HasMaxLength(100).HasComment("创建人");
builder.Property(ur => ur.CreatedAt).HasComment("创建时间");
builder.Property(ur => ur.UpdatedBy).HasMaxLength(100).HasComment("更新人");
builder.Property(ur => ur.UpdatedAt).HasComment("更新时间");
}
}

View File

@ -0,0 +1,942 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using RAG.Infrastructure.Persistence;
#nullable disable
namespace RAG.Infrastructure.Persistence.Migrations
{
[DbContext(typeof(RagDbContext))]
[Migration("20260525062123_AddColumnComments")]
partial class AddColumnComments
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "vector");
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("RAG.Domain.Entities.ChatMessage", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasComment("消息ID");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("text")
.HasComment("消息内容");
b.Property<Guid>("ConversationId")
.HasColumnType("uuid")
.HasComment("所属会话ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<int>("Role")
.HasColumnType("integer")
.HasComment("消息角色System=0, User=1, Assistant=2");
b.Property<int?>("TokenUsage")
.HasColumnType("integer")
.HasComment("本次消息消耗的Token数");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
b.HasIndex("ConversationId");
b.ToTable("chat_messages", (string)null);
});
modelBuilder.Entity("RAG.Domain.Entities.Conversation", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasComment("会话ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<Guid?>("KnowledgeBaseId")
.HasColumnType("uuid")
.HasComment("关联知识库IDnull表示普通对话");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("会话标题");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.Property<Guid>("UserId")
.HasColumnType("uuid")
.HasComment("所属用户ID");
b.HasKey("Id");
b.HasIndex("KnowledgeBaseId");
b.HasIndex("UserId");
b.ToTable("conversations", (string)null);
});
modelBuilder.Entity("RAG.Domain.Entities.Document", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasComment("文档ID");
b.Property<int>("ChunkCount")
.HasColumnType("integer")
.HasComment("分块数量");
b.Property<string>("ContentType")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("文件MIME类型");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<string>("FileName")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("原始文件名");
b.Property<string>("FilePath")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("character varying(1000)")
.HasComment("文件存储路径");
b.Property<long>("FileSize")
.HasColumnType("bigint")
.HasComment("文件大小(字节)");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<Guid>("KnowledgeBaseId")
.HasColumnType("uuid")
.HasComment("所属知识库ID");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<int>("Status")
.HasColumnType("integer")
.HasComment("文档状态Pending=0, Processing=1, Completed=2, Failed=3");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("文档标题");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
b.HasIndex("KnowledgeBaseId");
b.ToTable("documents", (string)null);
});
modelBuilder.Entity("RAG.Domain.Entities.DocumentChunk", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasComment("文档分块ID");
b.Property<int>("ChunkIndex")
.HasColumnType("integer")
.HasComment("分块序号从0开始");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("text")
.HasComment("分块文本内容");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<Guid>("DocumentId")
.HasColumnType("uuid")
.HasComment("所属文档ID");
b.Property<int>("TokenCount")
.HasColumnType("integer")
.HasComment("分块Token数量");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
b.HasIndex("DocumentId");
b.ToTable("document_chunks", (string)null);
});
modelBuilder.Entity("RAG.Domain.Entities.KnowledgeBase", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasComment("知识库ID");
b.Property<int>("ChunkOverlap")
.HasColumnType("integer")
.HasComment("分块重叠大小(字符数)");
b.Property<int>("ChunkSize")
.HasColumnType("integer")
.HasComment("分块大小(字符数)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<string>("Description")
.HasMaxLength(1000)
.HasColumnType("character varying(1000)")
.HasComment("知识库描述");
b.Property<string>("EmbeddingModel")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("嵌入模型名称");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("知识库名称");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<int>("Status")
.HasColumnType("integer")
.HasComment("知识库状态Active=0, Inactive=1");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
b.ToTable("knowledge_bases", (string)null);
});
modelBuilder.Entity("RAG.Domain.Entities.Menu", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasComment("菜单ID");
b.Property<string>("ActiveIcon")
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("菜单激活状态图标");
b.Property<bool?>("AffixTab")
.HasColumnType("boolean")
.HasComment("是否固定标签页");
b.Property<string>("Authority")
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("允许访问的角色名,逗号分隔,为空表示所有已认证用户可访问");
b.Property<string>("Component")
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("前端组件路径");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<bool>("HideInMenu")
.HasColumnType("boolean")
.HasComment("是否在菜单中隐藏");
b.Property<string>("Icon")
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("菜单图标");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<bool?>("KeepAlive")
.HasColumnType("boolean")
.HasComment("是否缓存页面状态");
b.Property<string>("Link")
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("外链地址");
b.Property<bool>("MenuVisibleWithForbidden")
.HasColumnType("boolean")
.HasComment("无权限时是否仍显示菜单");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("菜单名称路由name");
b.Property<bool>("NoBasicLayout")
.HasColumnType("boolean")
.HasComment("是否不使用基础布局");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<int>("Order")
.HasColumnType("integer")
.HasComment("排序序号,值越小越靠前");
b.Property<Guid?>("ParentId")
.HasColumnType("uuid")
.HasComment("父菜单IDnull表示顶级菜单");
b.Property<string>("Path")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("路由路径");
b.Property<string>("Redirect")
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("重定向路径");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("菜单显示标题");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
b.HasIndex("ParentId");
b.ToTable("menus", (string)null);
});
modelBuilder.Entity("RAG.Domain.Entities.Permission", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasComment("权限ID");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("权限编码,如 user:create唯一");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<string>("Description")
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("权限描述");
b.Property<string>("Group")
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("权限分组");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("权限名称");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("permissions", (string)null);
});
modelBuilder.Entity("RAG.Domain.Entities.RefreshToken", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasComment("刷新令牌ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<DateTime>("ExpiresAt")
.HasColumnType("timestamp with time zone")
.HasComment("令牌过期时间");
b.Property<bool>("IsRevoked")
.HasColumnType("boolean")
.HasComment("是否已撤销");
b.Property<string>("Token")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("刷新令牌值,唯一");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.Property<Guid>("UserId")
.HasColumnType("uuid")
.HasComment("关联用户ID");
b.HasKey("Id");
b.HasIndex("Token")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("refresh_tokens", (string)null);
});
modelBuilder.Entity("RAG.Domain.Entities.Role", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasComment("角色ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<string>("Description")
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("角色描述");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("角色名称,唯一");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("roles", (string)null);
});
modelBuilder.Entity("RAG.Domain.Entities.RolePermission", b =>
{
b.Property<Guid>("RoleId")
.HasColumnType("uuid")
.HasComment("角色ID");
b.Property<Guid>("PermissionId")
.HasColumnType("uuid")
.HasComment("权限ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("RoleId", "PermissionId");
b.HasIndex("PermissionId");
b.ToTable("role_permissions", (string)null);
});
modelBuilder.Entity("RAG.Domain.Entities.User", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasComment("用户ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("邮箱地址,唯一");
b.Property<bool>("IsActive")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true)
.HasComment("是否启用,停用后禁止登录");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<string>("PasswordHash")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("密码哈希值");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.Property<string>("Username")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("用户名,唯一");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.HasIndex("Username")
.IsUnique();
b.ToTable("users", (string)null);
});
modelBuilder.Entity("RAG.Domain.Entities.UserRole", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uuid")
.HasComment("用户ID");
b.Property<Guid>("RoleId")
.HasColumnType("uuid")
.HasComment("角色ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("user_roles", (string)null);
});
modelBuilder.Entity("RAG.Domain.Entities.ChatMessage", b =>
{
b.HasOne("RAG.Domain.Entities.Conversation", "Conversation")
.WithMany("Messages")
.HasForeignKey("ConversationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Conversation");
});
modelBuilder.Entity("RAG.Domain.Entities.Conversation", b =>
{
b.HasOne("RAG.Domain.Entities.KnowledgeBase", "KnowledgeBase")
.WithMany()
.HasForeignKey("KnowledgeBaseId");
b.HasOne("RAG.Domain.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("KnowledgeBase");
b.Navigation("User");
});
modelBuilder.Entity("RAG.Domain.Entities.Document", b =>
{
b.HasOne("RAG.Domain.Entities.KnowledgeBase", "KnowledgeBase")
.WithMany("Documents")
.HasForeignKey("KnowledgeBaseId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("KnowledgeBase");
});
modelBuilder.Entity("RAG.Domain.Entities.DocumentChunk", b =>
{
b.HasOne("RAG.Domain.Entities.Document", "Document")
.WithMany("Chunks")
.HasForeignKey("DocumentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Document");
});
modelBuilder.Entity("RAG.Domain.Entities.Menu", b =>
{
b.HasOne("RAG.Domain.Entities.Menu", "Parent")
.WithMany("Children")
.HasForeignKey("ParentId")
.OnDelete(DeleteBehavior.Cascade);
b.Navigation("Parent");
});
modelBuilder.Entity("RAG.Domain.Entities.RefreshToken", b =>
{
b.HasOne("RAG.Domain.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("RAG.Domain.Entities.RolePermission", b =>
{
b.HasOne("RAG.Domain.Entities.Permission", "Permission")
.WithMany("RolePermissions")
.HasForeignKey("PermissionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("RAG.Domain.Entities.Role", "Role")
.WithMany("RolePermissions")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Permission");
b.Navigation("Role");
});
modelBuilder.Entity("RAG.Domain.Entities.UserRole", b =>
{
b.HasOne("RAG.Domain.Entities.Role", "Role")
.WithMany("UserRoles")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("RAG.Domain.Entities.User", "User")
.WithMany("UserRoles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
b.Navigation("User");
});
modelBuilder.Entity("RAG.Domain.Entities.Conversation", b =>
{
b.Navigation("Messages");
});
modelBuilder.Entity("RAG.Domain.Entities.Document", b =>
{
b.Navigation("Chunks");
});
modelBuilder.Entity("RAG.Domain.Entities.KnowledgeBase", b =>
{
b.Navigation("Documents");
});
modelBuilder.Entity("RAG.Domain.Entities.Menu", b =>
{
b.Navigation("Children");
});
modelBuilder.Entity("RAG.Domain.Entities.Permission", b =>
{
b.Navigation("RolePermissions");
});
modelBuilder.Entity("RAG.Domain.Entities.Role", b =>
{
b.Navigation("RolePermissions");
b.Navigation("UserRoles");
});
modelBuilder.Entity("RAG.Domain.Entities.User", b =>
{
b.Navigation("UserRoles");
});
#pragma warning restore 612, 618
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -26,36 +26,45 @@ namespace RAG.Infrastructure.Persistence.Migrations
modelBuilder.Entity("RAG.Domain.Entities.ChatMessage", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("消息ID");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("text");
.HasColumnType("text")
.HasComment("消息内容");
b.Property<Guid>("ConversationId")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("所属会话ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<int>("Role")
.HasColumnType("integer");
.HasColumnType("integer")
.HasComment("消息角色System=0, User=1, Assistant=2");
b.Property<int?>("TokenUsage")
.HasColumnType("integer");
.HasColumnType("integer")
.HasComment("本次消息消耗的Token数");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
@ -67,44 +76,54 @@ namespace RAG.Infrastructure.Persistence.Migrations
modelBuilder.Entity("RAG.Domain.Entities.Conversation", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("会话ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<Guid?>("KnowledgeBaseId")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("关联知识库IDnull表示普通对话");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)");
.HasColumnType("character varying(200)")
.HasComment("会话标题");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("所属用户ID");
b.HasKey("Id");
@ -118,65 +137,80 @@ namespace RAG.Infrastructure.Persistence.Migrations
modelBuilder.Entity("RAG.Domain.Entities.Document", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("文档ID");
b.Property<int>("ChunkCount")
.HasColumnType("integer");
.HasColumnType("integer")
.HasComment("分块数量");
b.Property<string>("ContentType")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("文件MIME类型");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<string>("FileName")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)");
.HasColumnType("character varying(500)")
.HasComment("原始文件名");
b.Property<string>("FilePath")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("character varying(1000)");
.HasColumnType("character varying(1000)")
.HasComment("文件存储路径");
b.Property<long>("FileSize")
.HasColumnType("bigint");
.HasColumnType("bigint")
.HasComment("文件大小(字节)");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<Guid>("KnowledgeBaseId")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("所属知识库ID");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<int>("Status")
.HasColumnType("integer");
.HasColumnType("integer")
.HasComment("文档状态Pending=0, Processing=1, Completed=2, Failed=3");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)");
.HasColumnType("character varying(500)")
.HasComment("文档标题");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
@ -188,36 +222,45 @@ namespace RAG.Infrastructure.Persistence.Migrations
modelBuilder.Entity("RAG.Domain.Entities.DocumentChunk", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("文档分块ID");
b.Property<int>("ChunkIndex")
.HasColumnType("integer");
.HasColumnType("integer")
.HasComment("分块序号从0开始");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("text");
.HasColumnType("text")
.HasComment("分块文本内容");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<Guid>("DocumentId")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("所属文档ID");
b.Property<int>("TokenCount")
.HasColumnType("integer");
.HasColumnType("integer")
.HasComment("分块Token数量");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
@ -229,56 +272,69 @@ namespace RAG.Infrastructure.Persistence.Migrations
modelBuilder.Entity("RAG.Domain.Entities.KnowledgeBase", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("知识库ID");
b.Property<int>("ChunkOverlap")
.HasColumnType("integer");
.HasColumnType("integer")
.HasComment("分块重叠大小(字符数)");
b.Property<int>("ChunkSize")
.HasColumnType("integer");
.HasColumnType("integer")
.HasComment("分块大小(字符数)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<string>("Description")
.HasMaxLength(1000)
.HasColumnType("character varying(1000)");
.HasColumnType("character varying(1000)")
.HasComment("知识库描述");
b.Property<string>("EmbeddingModel")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("嵌入模型名称");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)");
.HasColumnType("character varying(200)")
.HasComment("知识库名称");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<int>("Status")
.HasColumnType("integer");
.HasColumnType("integer")
.HasComment("知识库状态Active=0, Inactive=1");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
@ -288,93 +344,116 @@ namespace RAG.Infrastructure.Persistence.Migrations
modelBuilder.Entity("RAG.Domain.Entities.Menu", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("菜单ID");
b.Property<string>("ActiveIcon")
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("菜单激活状态图标");
b.Property<bool?>("AffixTab")
.HasColumnType("boolean");
.HasColumnType("boolean")
.HasComment("是否固定标签页");
b.Property<string>("Authority")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
.HasColumnType("character varying(200)")
.HasComment("允许访问的角色名,逗号分隔,为空表示所有已认证用户可访问");
b.Property<string>("Component")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
.HasColumnType("character varying(200)")
.HasComment("前端组件路径");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<bool>("HideInMenu")
.HasColumnType("boolean");
.HasColumnType("boolean")
.HasComment("是否在菜单中隐藏");
b.Property<string>("Icon")
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("菜单图标");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<bool?>("KeepAlive")
.HasColumnType("boolean");
.HasColumnType("boolean")
.HasComment("是否缓存页面状态");
b.Property<string>("Link")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
.HasColumnType("character varying(500)")
.HasComment("外链地址");
b.Property<bool>("MenuVisibleWithForbidden")
.HasColumnType("boolean");
.HasColumnType("boolean")
.HasComment("无权限时是否仍显示菜单");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("菜单名称路由name");
b.Property<bool>("NoBasicLayout")
.HasColumnType("boolean");
.HasColumnType("boolean")
.HasComment("是否不使用基础布局");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<int>("Order")
.HasColumnType("integer");
.HasColumnType("integer")
.HasComment("排序序号,值越小越靠前");
b.Property<Guid?>("ParentId")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("父菜单IDnull表示顶级菜单");
b.Property<string>("Path")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)");
.HasColumnType("character varying(200)")
.HasComment("路由路径");
b.Property<string>("Redirect")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
.HasColumnType("character varying(200)")
.HasComment("重定向路径");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("菜单显示标题");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
@ -386,51 +465,62 @@ namespace RAG.Infrastructure.Persistence.Migrations
modelBuilder.Entity("RAG.Domain.Entities.Permission", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("权限ID");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
.HasColumnType("character varying(50)")
.HasComment("权限编码,如 user:create唯一");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<string>("Description")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
.HasColumnType("character varying(200)")
.HasComment("权限描述");
b.Property<string>("Group")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
.HasColumnType("character varying(50)")
.HasComment("权限分组");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("权限名称");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
@ -443,37 +533,46 @@ namespace RAG.Infrastructure.Persistence.Migrations
modelBuilder.Entity("RAG.Domain.Entities.RefreshToken", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("刷新令牌ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<DateTime>("ExpiresAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("令牌过期时间");
b.Property<bool>("IsRevoked")
.HasColumnType("boolean");
.HasColumnType("boolean")
.HasComment("是否已撤销");
b.Property<string>("Token")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)");
.HasColumnType("character varying(200)")
.HasComment("刷新令牌值,唯一");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("关联用户ID");
b.HasKey("Id");
@ -488,42 +587,51 @@ namespace RAG.Infrastructure.Persistence.Migrations
modelBuilder.Entity("RAG.Domain.Entities.Role", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("角色ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<string>("Description")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
.HasColumnType("character varying(200)")
.HasComment("角色描述");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
.HasColumnType("character varying(50)")
.HasComment("角色名称,唯一");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("Id");
@ -536,26 +644,32 @@ namespace RAG.Infrastructure.Persistence.Migrations
modelBuilder.Entity("RAG.Domain.Entities.RolePermission", b =>
{
b.Property<Guid>("RoleId")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("角色ID");
b.Property<Guid>("PermissionId")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("权限ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("RoleId", "PermissionId");
@ -567,53 +681,64 @@ namespace RAG.Infrastructure.Persistence.Migrations
modelBuilder.Entity("RAG.Domain.Entities.User", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("用户ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("邮箱地址,唯一");
b.Property<bool>("IsActive")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
.HasDefaultValue(true)
.HasComment("是否启用,停用后禁止登录");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
.HasDefaultValue(false)
.HasComment("是否已软删除");
b.Property<string>("OperatorIP")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
.HasColumnType("character varying(50)")
.HasComment("操作者IP地址");
b.Property<string>("PasswordHash")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)");
.HasColumnType("character varying(200)")
.HasComment("密码哈希值");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.Property<string>("Username")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
.HasColumnType("character varying(50)")
.HasComment("用户名,唯一");
b.HasKey("Id");
@ -629,26 +754,32 @@ namespace RAG.Infrastructure.Persistence.Migrations
modelBuilder.Entity("RAG.Domain.Entities.UserRole", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("用户ID");
b.Property<Guid>("RoleId")
.HasColumnType("uuid");
.HasColumnType("uuid")
.HasComment("角色ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("创建人");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
.HasColumnType("character varying(100)")
.HasComment("更新人");
b.HasKey("UserId", "RoleId");