using System.ComponentModel.DataAnnotations; using System.Text.Json; using Tiku.Application.Content; using Tiku.Application.QuestionBanks; using Tiku.Domain.Common; using Tiku.Domain.Content; namespace Tiku.Api.Contracts; /// /// 内容管理查询参数。 /// public sealed class ContentManagementQueryDto { /// /// 地区 ID。 /// public Guid? RegionId { get; set; } /// /// 内容入口 ID。 /// public Guid? EntryId { get; set; } /// /// 节点 ID。 /// public Guid? NodeId { get; set; } /// /// 题集 ID。 /// public Guid? CollectionId { get; set; } /// /// 父节点 ID;传 root 表示根节点。 /// [StringLength(64)] [RegularExpression("^(root|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$")] public string? ParentId { get; set; } /// /// 入口类型。 /// [StringLength(50)] public string? EntryType { get; set; } /// /// 题集类型。 /// [StringLength(50)] public string? CollectionType { get; set; } /// /// 模式。 /// [StringLength(50)] public string? Mode { get; set; } /// /// 标记类型。 /// [StringLength(50)] public string? MarkerType { get; set; } /// /// 关键字。 /// [StringLength(100)] public string? Keyword { get; set; } /// /// 是否包含停用数据。 /// public bool IncludeInactive { get; set; } /// /// 返回数量上限。 /// [Range(1, 1000)] public int? Limit { get; set; } public ContentManagementFilter ToFilter() { return new ContentManagementFilter( RegionId, EntryId, NodeId, CollectionId, ParentId, EntryType, CollectionType, Mode, MarkerType, Keyword, IncludeInactive, Limit); } } /// /// 新增或更新内容条目请求 DTO。 /// public sealed class UpsertContentEntryDto { /// /// ID。 /// public Guid? Id { get; set; } /// /// 地区 ID。 /// public Guid? RegionId { get; set; } /// /// 历史系统 ID。 /// [StringLength(64)] public string? LegacyId { get; set; } /// /// 入口键。 /// [StringLength(100)] public string? EntryKey { get; set; } /// /// 名称。 /// [Required] [StringLength(300)] public string Name { get; set; } = string.Empty; /// /// 入口类型。 /// [StringLength(50)] public string? EntryType { get; set; } /// /// 图标。 /// [StringLength(100)] public string? Icon { get; set; } /// /// 路由地址。 /// [StringLength(500)] public string? Route { get; set; } /// /// 说明。 /// [StringLength(2000)] public string? Description { get; set; } /// /// 可见性。 /// [StringLength(50)] public string? Visibility { get; set; } /// /// 访问规则。 /// public JsonElement AccessRules { get; set; } = JsonDefaults.Object(); /// /// 布局配置。 /// public JsonElement LayoutConfig { get; set; } = JsonDefaults.Object(); /// /// 显示顺序。 /// public int? Order { get; set; } /// /// 是否启用。 /// public bool? IsActive { get; set; } public UpsertContentEntryCommand ToCommand() { return new UpsertContentEntryCommand( Id, RegionId, LegacyId, EntryKey, Name, EntryType, Icon, Route, Description, Visibility, AccessRules, LayoutConfig, Order, IsActive); } } /// /// 新增或更新内容节点请求 DTO。 /// public sealed class UpsertContentNodeDto { /// /// ID。 /// public Guid? Id { get; set; } /// /// 内容入口 ID。 /// [Required] public Guid EntryId { get; set; } /// /// 地区 ID。 /// public Guid? RegionId { get; set; } /// /// 父节点 ID。 /// public Guid? ParentId { get; set; } /// /// 历史系统 ID。 /// [StringLength(64)] public string? LegacyId { get; set; } /// /// 节点键。 /// [StringLength(100)] public string? NodeKey { get; set; } /// /// 名称。 /// [Required] [StringLength(300)] public string Name { get; set; } = string.Empty; /// /// 节点Type。 /// [StringLength(50)] public string? NodeType { get; set; } /// /// 标记类型。 /// [StringLength(50)] public string? MarkerType { get; set; } /// /// 标记配置。 /// public JsonElement MarkerConfig { get; set; } = JsonDefaults.Object(); /// /// 显示顺序。 /// public int? Order { get; set; } /// /// 是否启用。 /// public bool? IsActive { get; set; } /// /// 是否可选择。 /// public bool? IsSelectable { get; set; } /// /// 是否叶子节点。 /// public bool? IsLeaf { get; set; } /// /// 访问规则。 /// public JsonElement AccessRules { get; set; } = JsonDefaults.Object(); /// /// 扩展元数据。 /// public JsonElement Metadata { get; set; } = JsonDefaults.Object(); public UpsertContentNodeCommand ToCommand() { return new UpsertContentNodeCommand( Id, EntryId, RegionId, ParentId, LegacyId, NodeKey, Name, NodeType, MarkerType, MarkerConfig, Order, IsActive, IsSelectable, IsLeaf, AccessRules, Metadata); } } /// /// 新增或更新题目题集请求 DTO。 /// public sealed class UpsertQuestionCollectionDto { /// /// ID。 /// public Guid? Id { get; set; } /// /// 地区 ID。 /// public Guid? RegionId { get; set; } /// /// 内容入口 ID。 /// public Guid? EntryId { get; set; } /// /// 节点 ID。 /// public Guid? NodeId { get; set; } /// /// 科目 ID。 /// public Guid? SubjectId { get; set; } /// /// 分类 ID。 /// public Guid? CategoryId { get; set; } /// /// 题库 ID。 /// public Guid? QuestionBankId { get; set; } /// /// 历史系统 ID。 /// [StringLength(64)] public string? LegacyId { get; set; } /// /// 名称。 /// [Required] [StringLength(300)] public string Name { get; set; } = string.Empty; /// /// 题集类型。 /// [StringLength(50)] public string? CollectionType { get; set; } /// /// 来源类型。 /// [StringLength(50)] public string? SourceType { get; set; } /// /// 筛选条件。 /// public JsonElement Filters { get; set; } = JsonDefaults.Object(); /// /// 总分。 /// public decimal? TotalScore { get; set; } /// /// 时长,单位为分钟。 /// public int? DurationMinutes { get; set; } /// /// 状态。 /// [StringLength(50)] public string? Status { get; set; } /// /// 显示顺序。 /// public int? Order { get; set; } /// /// 访问规则。 /// public JsonElement AccessRules { get; set; } = JsonDefaults.Object(); /// /// 扩展元数据。 /// public JsonElement Metadata { get; set; } = JsonDefaults.Object(); public UpsertQuestionCollectionCommand ToCommand() { return new UpsertQuestionCollectionCommand( Id, RegionId, EntryId, NodeId, SubjectId, CategoryId, QuestionBankId, LegacyId, Name, CollectionType, SourceType, Filters, TotalScore, DurationMinutes, Status, Order, AccessRules, Metadata); } } /// /// 题集题目请求 DTO。 /// public sealed class CollectionQuestionDto { /// /// 题目 ID。 /// [Required] public Guid QuestionId { get; set; } /// /// 来源。 /// [Required] public QuestionSource Source { get; set; } = QuestionSource.Tenant; /// /// 分段键。 /// [StringLength(100)] public string? SectionKey { get; set; } /// /// 显示顺序。 /// public int? Order { get; set; } /// /// 分数。 /// public decimal? Score { get; set; } /// /// 是否必填。 /// public bool? Required { get; set; } /// /// 扩展元数据。 /// public JsonElement Metadata { get; set; } = JsonDefaults.Object(); public CollectionQuestionCommand ToCommand() { return new CollectionQuestionCommand( new QuestionLocator(Source, QuestionId), SectionKey, Order, Score, Required, Metadata); } } /// /// 替换题集Items请求 DTO。 /// public sealed class ReplaceCollectionItemsDto { /// /// 题集 ID。 /// [Required] public Guid CollectionId { get; set; } /// /// 题目列表。 /// public IReadOnlyCollection Questions { get; set; } = []; public ReplaceCollectionItemsCommand ToCommand() { return new ReplaceCollectionItemsCommand( CollectionId, Questions.Select(question => question.ToCommand()).ToArray()); } } /// /// 新增或更新练习Blueprint请求 DTO。 /// public sealed class UpsertPracticeBlueprintDto { /// /// ID。 /// public Guid? Id { get; set; } /// /// 地区 ID。 /// public Guid? RegionId { get; set; } /// /// 内容入口 ID。 /// public Guid? EntryId { get; set; } /// /// 节点 ID。 /// public Guid? NodeId { get; set; } /// /// 题集 ID。 /// public Guid? CollectionId { get; set; } /// /// 历史系统 ID。 /// [StringLength(64)] public string? LegacyId { get; set; } /// /// 名称。 /// [Required] [StringLength(300)] public string Name { get; set; } = string.Empty; /// /// 模式。 /// [StringLength(50)] public string? Mode { get; set; } /// /// 组卷方式。 /// [StringLength(50)] public string? AssemblyType { get; set; } /// /// 题目数量上限。 /// public int? QuestionLimit { get; set; } /// /// 时长,单位为分钟。 /// public int? DurationMinutes { get; set; } /// /// 总分。 /// public decimal? TotalScore { get; set; } /// /// 及格分。 /// public decimal? PassScore { get; set; } /// /// 分段配置。 /// public JsonElement Sections { get; set; } = JsonDefaults.Array(); /// /// 规则配置。 /// public JsonElement Rules { get; set; } = JsonDefaults.Object(); /// /// 访问规则。 /// public JsonElement AccessRules { get; set; } = JsonDefaults.Object(); /// /// 状态。 /// [StringLength(50)] public string? Status { get; set; } /// /// 显示顺序。 /// public int? Order { get; set; } public UpsertPracticeBlueprintCommand ToCommand() { return new UpsertPracticeBlueprintCommand( Id, RegionId, EntryId, NodeId, CollectionId, LegacyId, Name, Mode, AssemblyType, QuestionLimit, DurationMinutes, TotalScore, PassScore, Sections, Rules, AccessRules, Status, Order); } } /// /// 导入Template查询参数。 /// public sealed class ImportTemplateQueryDto { /// /// 导入Type。 /// [Required] [StringLength(50)] public string ImportType { get; set; } = string.Empty; /// /// 导出格式。 /// [StringLength(10)] public string? Format { get; set; } }