feat: add content assets and import persistence

This commit is contained in:
xiong
2026-07-26 05:18:17 +08:00
parent d73d8f20ca
commit c217db4597
9 changed files with 8125 additions and 31 deletions

View File

@@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Tiku.Domain.Catalog;
using Tiku.Domain.Content;
using Tiku.Domain.Identity;
using Tiku.Domain.Tenancy;
namespace Tiku.Infrastructure.Persistence.Configurations;
@@ -14,7 +15,6 @@ internal sealed class VocabularyUnitConfiguration : IEntityTypeConfiguration<Voc
builder.ConfigureTimestamps();
builder.Property(entity => entity.LegacyId).HasMaxLength(64);
builder.Property(entity => entity.Name).HasMaxLength(300);
builder.Property(entity => entity.Description).HasMaxLength(2000);
builder.Property(entity => entity.SourceHash).HasMaxLength(128);
builder.Property(entity => entity.Metadata).IsJson("{}");
builder.HasIndex(entity => new { entity.TenantId, entity.LegacyId }).IsUnique();
@@ -51,10 +51,7 @@ internal sealed class VocabularyWordConfiguration : IEntityTypeConfiguration<Voc
builder.ConfigureTimestamps();
builder.Property(entity => entity.LegacyId).HasMaxLength(64);
builder.Property(entity => entity.Word).HasMaxLength(300);
builder.Property(entity => entity.Phonetic).HasMaxLength(200);
builder.Property(entity => entity.Meaning).HasMaxLength(2000);
builder.Property(entity => entity.Example).HasMaxLength(4000);
builder.Property(entity => entity.ExampleTranslation).HasMaxLength(4000);
builder.Property(entity => entity.Phonetic).HasMaxLength(300);
builder.Property(entity => entity.SourceHash).HasMaxLength(128);
builder.Property(entity => entity.Tags).IsJson("[]");
builder.Property(entity => entity.Metadata).IsJson("{}");
@@ -98,17 +95,12 @@ internal sealed class UserWordProgressConfiguration : IEntityTypeConfiguration<U
{
builder.ConfigureTenantEntity("user_word_progress");
builder.ConfigureTimestamps();
builder.Property(entity => entity.LegacyId).HasMaxLength(64);
builder.Property(entity => entity.LegacyUserId).HasMaxLength(64);
builder.Property(entity => entity.LegacyWordId).HasMaxLength(64);
builder.Property(entity => entity.Status).HasSnakeCaseEnum();
builder.Property(entity => entity.EaseFactor).HasPrecision(4, 2).HasDefaultValue(2.50m);
builder.Property(entity => entity.LastResult).HasNullableSnakeCaseEnum();
builder.Property(entity => entity.DueLevel).HasSnakeCaseEnum();
builder.Property(entity => entity.Metadata).IsJson("{}");
builder.HasIndex(entity => new { entity.TenantId, entity.LegacyId }).IsUnique();
builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.WordId }).IsUnique();
builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.Status });
builder.HasIndex(entity => new
{
entity.TenantId,
@@ -141,11 +133,7 @@ internal sealed class UserWordFavoriteConfiguration : IEntityTypeConfiguration<U
{
builder.ConfigureTenantEntity("user_word_favorites");
builder.ConfigureTimestamps();
builder.Property(entity => entity.LegacyId).HasMaxLength(64);
builder.Property(entity => entity.LegacyUserId).HasMaxLength(64);
builder.Property(entity => entity.LegacyWordId).HasMaxLength(64);
builder.Property(entity => entity.Note).HasMaxLength(2000);
builder.HasIndex(entity => new { entity.TenantId, entity.LegacyId }).IsUnique();
builder.Property(entity => entity.Note).HasMaxLength(1000);
builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.WordId }).IsUnique();
builder.HasOne<User>().WithMany()
@@ -169,7 +157,6 @@ internal sealed class HandbookSubjectConfiguration : IEntityTypeConfiguration<Ha
builder.Property(entity => entity.Type).HasNullableSnakeCaseEnum();
builder.Property(entity => entity.Icon).HasMaxLength(2048);
builder.Property(entity => entity.Color).HasMaxLength(50);
builder.Property(entity => entity.Description).HasMaxLength(2000);
builder.Property(entity => entity.MajorLegacyIds).IsJson("[]");
builder.Property(entity => entity.SourceHash).HasMaxLength(128);
builder.Property(entity => entity.Metadata).IsJson("{}");
@@ -215,7 +202,6 @@ internal sealed class HandbookChapterConfiguration : IEntityTypeConfiguration<Ha
builder.ConfigureTimestamps();
builder.Property(entity => entity.LegacyId).HasMaxLength(64);
builder.Property(entity => entity.Name).HasMaxLength(300);
builder.Property(entity => entity.Description).HasMaxLength(2000);
builder.Property(entity => entity.SourceHash).HasMaxLength(128);
builder.Property(entity => entity.Metadata).IsJson("{}");
builder.HasIndex(entity => new { entity.TenantId, entity.LegacyId }).IsUnique();
@@ -251,8 +237,7 @@ internal sealed class HandbookEntryConfiguration : IEntityTypeConfiguration<Hand
builder.ConfigureTenantEntity("handbook_entries");
builder.ConfigureTimestamps();
builder.Property(entity => entity.LegacyId).HasMaxLength(64);
builder.Property(entity => entity.Title).HasMaxLength(300);
builder.Property(entity => entity.Summary).HasMaxLength(2000);
builder.Property(entity => entity.Title).HasMaxLength(500);
builder.Property(entity => entity.Tags).IsJson("[]");
builder.Property(entity => entity.SourceHash).HasMaxLength(128);
builder.Property(entity => entity.Metadata).IsJson("{}");
@@ -289,7 +274,7 @@ internal sealed class QuestionTypeGroupConfiguration : IEntityTypeConfiguration<
builder.ConfigureTenantEntity("question_type_groups");
builder.ConfigureTimestamps();
builder.Property(entity => entity.LegacyId).HasMaxLength(64);
builder.Property(entity => entity.DisplayName).HasMaxLength(300);
builder.Property(entity => entity.DisplayName).HasMaxLength(200);
builder.Property(entity => entity.Types).IsJson("[]");
builder.HasIndex(entity => new { entity.TenantId, entity.LegacyId }).IsUnique();
builder.HasIndex(entity => new
@@ -311,18 +296,19 @@ internal sealed class SubjectShareConfiguration : IEntityTypeConfiguration<Subje
{
public void Configure(EntityTypeBuilder<SubjectShare> builder)
{
builder.ConfigureTenantEntity("subject_shares");
builder.ConfigureTimestamps();
builder.Property(entity => entity.LegacyId).HasMaxLength(64);
builder.Property(entity => entity.LegacySourceSubjectId).HasMaxLength(64);
builder.Property(entity => entity.LegacyTargetSubjectId).HasMaxLength(64);
builder.HasIndex(entity => new { entity.TenantId, entity.LegacyId }).IsUnique();
builder.HasIndex(entity => new
builder.ToTable("subject_shares");
builder.HasKey(entity => new
{
entity.TenantId,
entity.SourceSubjectId,
entity.TargetSubjectId
}).IsUnique();
});
builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()");
builder.HasIndex(entity => new { entity.TenantId, entity.TargetSubjectId });
builder.HasOne<Tenant>().WithMany()
.HasForeignKey(entity => entity.TenantId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne<Subject>().WithMany()
.HasForeignKey(entity => new { entity.TenantId, entity.SourceSubjectId })