forked from xiongyuxing/tiku-backend.net
feat: add content assets and import persistence
This commit is contained in:
243
Tiku.Domain/Content/AssetEntities.cs
Normal file
243
Tiku.Domain/Content/AssetEntities.cs
Normal file
@@ -0,0 +1,243 @@
|
||||
using System.Text.Json;
|
||||
using Tiku.Domain.Common;
|
||||
|
||||
namespace Tiku.Domain.Content;
|
||||
|
||||
public sealed class ContentAsset : AuditableTenantEntity
|
||||
{
|
||||
public Guid? RegionId { get; set; }
|
||||
public Guid? SubjectId { get; set; }
|
||||
public Guid? CategoryId { get; set; }
|
||||
public Guid? ContentNodeId { get; set; }
|
||||
public Guid? CreatedBy { get; set; }
|
||||
public Guid? UpdatedBy { get; set; }
|
||||
public Guid? VerifiedBy { get; set; }
|
||||
public string? LegacyId { get; set; }
|
||||
public string? AssetKey { get; set; }
|
||||
public string? Title { get; set; }
|
||||
public string? Category { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? FileName { get; set; }
|
||||
public string? CdnUrl { get; set; }
|
||||
public bool IsPublic { get; set; }
|
||||
public ContentAssetType AssetType { get; set; } = ContentAssetType.Document;
|
||||
public AssetStorageProvider StorageProvider { get; set; } = AssetStorageProvider.ExternalUrl;
|
||||
public string? Bucket { get; set; }
|
||||
public string? ObjectKey { get; set; }
|
||||
public string? MimeType { get; set; }
|
||||
public long? FileSizeBytes { get; set; }
|
||||
public string? ChecksumSha256 { get; set; }
|
||||
public ContentVisibility Visibility { get; set; } = ContentVisibility.Members;
|
||||
public string? PreviewUrl { get; set; }
|
||||
public ContentStatus Status { get; set; } = ContentStatus.Active;
|
||||
public int SortOrder { get; set; }
|
||||
public JsonElement AccessRules { get; set; } = JsonDefaults.Object();
|
||||
public string Source { get; set; } = "manual";
|
||||
public int DownloadCount { get; set; }
|
||||
public AssetUploadStatus UploadStatus { get; set; } = AssetUploadStatus.NotRequired;
|
||||
public DateTimeOffset? VerifiedAt { get; set; }
|
||||
public long? VerifiedSizeBytes { get; set; }
|
||||
public string? VerifiedChecksumSha256 { get; set; }
|
||||
public JsonElement VerificationDetails { get; set; } = JsonDefaults.Object();
|
||||
public string? PreviewObjectKey { get; set; }
|
||||
public AssetPreviewStatus PreviewStatus { get; set; } = AssetPreviewStatus.None;
|
||||
public JsonElement SecurityFlags { get; set; } = JsonDefaults.Object();
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
}
|
||||
|
||||
public sealed class ContentImportJob : AuditableTenantEntity
|
||||
{
|
||||
public Guid? CreatedBy { get; set; }
|
||||
public Guid? TargetRegionId { get; set; }
|
||||
public Guid? TargetSubjectId { get; set; }
|
||||
public Guid? TargetCategoryId { get; set; }
|
||||
public Guid? TargetContentNodeId { get; set; }
|
||||
public Guid? TargetQuestionBankId { get; set; }
|
||||
public ContentImportType ImportType { get; set; } = ContentImportType.Questions;
|
||||
public ImportSourceFormat SourceFormat { get; set; } = ImportSourceFormat.Json;
|
||||
public ContentImportStatus Status { get; set; } = ContentImportStatus.Preview;
|
||||
public string? SourceName { get; set; }
|
||||
public string? SourceHash { get; set; }
|
||||
public bool DryRun { get; set; } = true;
|
||||
public int TotalCount { get; set; }
|
||||
public int ValidCount { get; set; }
|
||||
public int ErrorCount { get; set; }
|
||||
public int WarningCount { get; set; }
|
||||
public int InsertedCount { get; set; }
|
||||
public int UpdatedCount { get; set; }
|
||||
public int SkippedCount { get; set; }
|
||||
public JsonElement Summary { get; set; } = JsonDefaults.Object();
|
||||
public JsonElement RawPayload { get; set; } = JsonDefaults.Array();
|
||||
public JsonElement NormalizedPayload { get; set; } = JsonDefaults.Array();
|
||||
public string? ErrorMessage { get; set; }
|
||||
public DateTimeOffset? StartedAt { get; set; }
|
||||
public DateTimeOffset? FinishedAt { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ContentImportItem : AuditableTenantEntity
|
||||
{
|
||||
public Guid JobId { get; set; }
|
||||
public int RowNo { get; set; }
|
||||
public string? ExternalId { get; set; }
|
||||
public ContentImportItemStatus Status { get; set; } = ContentImportItemStatus.Valid;
|
||||
public string? TargetType { get; set; }
|
||||
public Guid? TargetId { get; set; }
|
||||
public JsonElement SourcePayload { get; set; } = JsonDefaults.Object();
|
||||
public JsonElement NormalizedPayload { get; set; } = JsonDefaults.Object();
|
||||
public string? ContentHash { get; set; }
|
||||
public int IssuesCount { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ContentImportIssue : AuditableTenantEntity
|
||||
{
|
||||
public Guid JobId { get; set; }
|
||||
public Guid? ItemId { get; set; }
|
||||
public int? RowNo { get; set; }
|
||||
public ImportIssueSeverity Severity { get; set; } = ImportIssueSeverity.Error;
|
||||
public string Code { get; set; } = string.Empty;
|
||||
public string? FieldPath { get; set; }
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public JsonElement Details { get; set; } = JsonDefaults.Object();
|
||||
}
|
||||
|
||||
public sealed class ImageAsset : AuditableTenantEntity
|
||||
{
|
||||
public string? LegacyId { get; set; }
|
||||
public string? Title { get; set; }
|
||||
public string? Category { get; set; }
|
||||
public string? FileName { get; set; }
|
||||
public bool IsPublic { get; set; }
|
||||
public string? CdnUrl { get; set; }
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
}
|
||||
|
||||
public sealed class AppAsset : AuditableTenantEntity
|
||||
{
|
||||
public string? LegacyId { get; set; }
|
||||
public string AssetKey { get; set; } = string.Empty;
|
||||
public string? FileName { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
}
|
||||
|
||||
public sealed class VideoExplanation : AuditableTenantEntity
|
||||
{
|
||||
public Guid? SubjectId { get; set; }
|
||||
public string? LegacyId { get; set; }
|
||||
public string? LegacySubjectId { get; set; }
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public string? VideoUrl { get; set; }
|
||||
public string? ThumbnailUrl { get; set; }
|
||||
public int? DurationSeconds { get; set; }
|
||||
public JsonElement KnowledgeTags { get; set; } = JsonDefaults.Array();
|
||||
public bool IsGeneral { get; set; }
|
||||
public int? Difficulty { get; set; }
|
||||
public int SortOrder { get; set; }
|
||||
public bool IsActive { get; set; } = true;
|
||||
public string? SourceHash { get; set; }
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
}
|
||||
|
||||
public sealed class QuestionVideo : AuditableTenantEntity
|
||||
{
|
||||
public Guid? QuestionId { get; set; }
|
||||
public Guid? VideoId { get; set; }
|
||||
public string? LegacyId { get; set; }
|
||||
public string? LegacyQuestionId { get; set; }
|
||||
public string? LegacyVideoId { get; set; }
|
||||
public QuestionVideoType VideoType { get; set; } = QuestionVideoType.Specific;
|
||||
public int SortOrder { get; set; }
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
}
|
||||
|
||||
public enum ContentAssetType
|
||||
{
|
||||
Pdf,
|
||||
Video,
|
||||
Image,
|
||||
Audio,
|
||||
Document,
|
||||
Package,
|
||||
Link,
|
||||
Other
|
||||
}
|
||||
|
||||
public enum AssetStorageProvider
|
||||
{
|
||||
ExternalUrl,
|
||||
SupabaseStorage,
|
||||
AliyunOss,
|
||||
TencentCos,
|
||||
QiniuKodo,
|
||||
LocalDev
|
||||
}
|
||||
|
||||
public enum AssetUploadStatus
|
||||
{
|
||||
NotRequired,
|
||||
Pending,
|
||||
Verified,
|
||||
Failed
|
||||
}
|
||||
|
||||
public enum AssetPreviewStatus
|
||||
{
|
||||
None,
|
||||
Pending,
|
||||
Ready,
|
||||
Failed
|
||||
}
|
||||
|
||||
public enum ContentImportType
|
||||
{
|
||||
Questions,
|
||||
Vocabulary,
|
||||
Handbook,
|
||||
Scoreline,
|
||||
Assets,
|
||||
Videos
|
||||
}
|
||||
|
||||
public enum ImportSourceFormat
|
||||
{
|
||||
Json,
|
||||
Excel,
|
||||
Csv,
|
||||
Pocketbase,
|
||||
Api
|
||||
}
|
||||
|
||||
public enum ContentImportStatus
|
||||
{
|
||||
Preview,
|
||||
Pending,
|
||||
Importing,
|
||||
Completed,
|
||||
CompletedWithErrors,
|
||||
Failed,
|
||||
Rejected
|
||||
}
|
||||
|
||||
public enum ContentImportItemStatus
|
||||
{
|
||||
Valid,
|
||||
Invalid,
|
||||
Inserted,
|
||||
Updated,
|
||||
Skipped,
|
||||
Failed
|
||||
}
|
||||
|
||||
public enum ImportIssueSeverity
|
||||
{
|
||||
Error,
|
||||
Warning
|
||||
}
|
||||
|
||||
public enum QuestionVideoType
|
||||
{
|
||||
Specific,
|
||||
General,
|
||||
Related
|
||||
}
|
||||
@@ -130,8 +130,8 @@ public sealed class QuestionTypeGroup : AuditableTenantEntity
|
||||
|
||||
public sealed class SubjectShare : AuditableTenantEntity
|
||||
{
|
||||
public Guid? SourceSubjectId { get; set; }
|
||||
public Guid? TargetSubjectId { get; set; }
|
||||
public Guid SourceSubjectId { get; set; }
|
||||
public Guid TargetSubjectId { get; set; }
|
||||
public string? LegacyId { get; set; }
|
||||
public string? LegacySourceSubjectId { get; set; }
|
||||
public string? LegacyTargetSubjectId { get; set; }
|
||||
|
||||
Reference in New Issue
Block a user