346 lines
7.2 KiB
C#
346 lines
7.2 KiB
C#
using System.ComponentModel.DataAnnotations;
|
|
using System.Text.Json;
|
|
using Tiku.Application.Learning;
|
|
using Tiku.Application.QuestionBanks;
|
|
using Tiku.Domain.Common;
|
|
using Tiku.Domain.Content;
|
|
|
|
namespace Tiku.Api.Contracts;
|
|
|
|
/// <summary>
|
|
/// 学习Limit查询参数。
|
|
/// </summary>
|
|
public sealed class LearningLimitQueryDto
|
|
{
|
|
/// <summary>
|
|
/// 返回数量上限。
|
|
/// </summary>
|
|
[Range(1, 500)]
|
|
public int? Limit { get; set; }
|
|
|
|
/// <summary>
|
|
/// 状态。
|
|
/// </summary>
|
|
[StringLength(50)]
|
|
public string? Status { get; set; }
|
|
|
|
/// <summary>
|
|
/// 单元 ID。
|
|
/// </summary>
|
|
public Guid? UnitId { get; set; }
|
|
|
|
public LearningLimitFilter ToFilter()
|
|
{
|
|
return new LearningLimitFilter(Limit, Status, UnitId);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 练习会话查询参数。
|
|
/// </summary>
|
|
public sealed class PracticeSessionQueryDto
|
|
{
|
|
/// <summary>
|
|
/// 练习会话 ID。
|
|
/// </summary>
|
|
public Guid? PracticeSessionId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 练习蓝图 ID。
|
|
/// </summary>
|
|
public Guid? BlueprintId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 模式。
|
|
/// </summary>
|
|
[StringLength(50)]
|
|
public string? Mode { get; set; }
|
|
|
|
/// <summary>
|
|
/// 状态。
|
|
/// </summary>
|
|
[StringLength(50)]
|
|
public string? Status { get; set; }
|
|
|
|
/// <summary>
|
|
/// 返回数量上限。
|
|
/// </summary>
|
|
[Range(1, 200)]
|
|
public int? Limit { get; set; }
|
|
|
|
public PracticeSessionFilter ToFilter(Guid? routePracticeSessionId = null)
|
|
{
|
|
return new PracticeSessionFilter(
|
|
routePracticeSessionId ?? PracticeSessionId,
|
|
BlueprintId,
|
|
Mode,
|
|
Status,
|
|
Limit);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建练习会话请求 DTO。
|
|
/// </summary>
|
|
public sealed class CreatePracticeSessionDto
|
|
{
|
|
/// <summary>
|
|
/// 模式。
|
|
/// </summary>
|
|
[StringLength(50)]
|
|
public string? Mode { get; set; }
|
|
|
|
/// <summary>
|
|
/// 目标类型。
|
|
/// </summary>
|
|
[StringLength(50)]
|
|
public string? TargetType { get; set; }
|
|
|
|
/// <summary>
|
|
/// 目标 ID。
|
|
/// </summary>
|
|
public Guid? TargetId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 练习蓝图 ID。
|
|
/// </summary>
|
|
public Guid? BlueprintId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 题集 ID。
|
|
/// </summary>
|
|
public Guid? CollectionId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 内容入口 ID。
|
|
/// </summary>
|
|
public Guid? EntryId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 内容节点 ID。
|
|
/// </summary>
|
|
public Guid? ContentNodeId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 题目数量上限。
|
|
/// </summary>
|
|
[Range(1, 500)]
|
|
public int? QuestionLimit { get; set; }
|
|
|
|
/// <summary>
|
|
/// 时长,单位为分钟。
|
|
/// </summary>
|
|
[Range(1, 1440)]
|
|
public int? DurationMinutes { get; set; }
|
|
|
|
/// <summary>
|
|
/// 总分。
|
|
/// </summary>
|
|
[Range(typeof(decimal), "0", "99999")]
|
|
public decimal? TotalScore { get; set; }
|
|
|
|
/// <summary>
|
|
/// 扩展元数据。
|
|
/// </summary>
|
|
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
|
|
|
public PracticeSessionCommand ToCommand()
|
|
{
|
|
return new PracticeSessionCommand(
|
|
Mode,
|
|
TargetType,
|
|
TargetId,
|
|
BlueprintId,
|
|
CollectionId,
|
|
EntryId,
|
|
ContentNodeId,
|
|
QuestionLimit,
|
|
DurationMinutes,
|
|
TotalScore,
|
|
Metadata);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 提交练习会话请求 DTO。
|
|
/// </summary>
|
|
public sealed class SubmitPracticeSessionDto
|
|
{
|
|
/// <summary>
|
|
/// 练习会话 ID。
|
|
/// </summary>
|
|
[Required]
|
|
public Guid PracticeSessionId { get; set; }
|
|
|
|
public PracticeSessionFilter ToFilter()
|
|
{
|
|
return new PracticeSessionFilter(PracticeSessionId);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 提交答案请求 DTO。
|
|
/// </summary>
|
|
public sealed class SubmitAnswerDto
|
|
{
|
|
/// <summary>
|
|
/// 会话题目 ID。
|
|
/// </summary>
|
|
[Required]
|
|
public Guid SessionQuestionId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 已选选项。
|
|
/// </summary>
|
|
public IReadOnlyCollection<string>? SelectedOptions { get; set; }
|
|
|
|
/// <summary>
|
|
/// 文字答案。
|
|
/// </summary>
|
|
[StringLength(10000)]
|
|
public string? AnswerText { get; set; }
|
|
|
|
/// <summary>
|
|
/// 主观题自评是否正确。
|
|
/// </summary>
|
|
public bool? SelfJudgedCorrect { get; set; }
|
|
|
|
public SubmitAnswerCommand ToCommand()
|
|
{
|
|
return new SubmitAnswerCommand(
|
|
SessionQuestionId,
|
|
SelectedOptions,
|
|
AnswerText,
|
|
SelfJudgedCorrect);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 题目Action请求 DTO。
|
|
/// </summary>
|
|
public sealed class QuestionActionDto
|
|
{
|
|
/// <summary>
|
|
/// 题目 ID。
|
|
/// </summary>
|
|
[Required]
|
|
public Guid QuestionId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 来源。
|
|
/// </summary>
|
|
[Required]
|
|
public QuestionSource Source { get; set; } = QuestionSource.Tenant;
|
|
|
|
/// <summary>
|
|
/// 是否收藏。
|
|
/// </summary>
|
|
public bool? Favorite { get; set; }
|
|
|
|
public QuestionActionCommand ToCommand()
|
|
{
|
|
return new QuestionActionCommand(new QuestionLocator(Source, QuestionId), Favorite);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 单词Progress请求 DTO。
|
|
/// </summary>
|
|
public sealed class WordProgressDto
|
|
{
|
|
/// <summary>
|
|
/// 单词 ID。
|
|
/// </summary>
|
|
[Required]
|
|
public Guid WordId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 状态。
|
|
/// </summary>
|
|
[StringLength(50)]
|
|
public string? Status { get; set; }
|
|
|
|
/// <summary>
|
|
/// 答对数量变化。
|
|
/// </summary>
|
|
[Range(0, 100)]
|
|
public int? CorrectDelta { get; set; }
|
|
|
|
/// <summary>
|
|
/// 答错数量变化。
|
|
/// </summary>
|
|
[Range(0, 100)]
|
|
public int? WrongDelta { get; set; }
|
|
|
|
/// <summary>
|
|
/// 下次复习时间。
|
|
/// </summary>
|
|
public DateTimeOffset? NextReviewAt { get; set; }
|
|
|
|
public WordProgressCommand ToCommand()
|
|
{
|
|
return new WordProgressCommand(
|
|
WordId,
|
|
Status,
|
|
CorrectDelta,
|
|
WrongDelta,
|
|
NextReviewAt);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 收藏单词请求 DTO。
|
|
/// </summary>
|
|
public sealed class FavoriteWordDto
|
|
{
|
|
/// <summary>
|
|
/// 单词 ID。
|
|
/// </summary>
|
|
[Required]
|
|
public Guid WordId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 是否收藏。
|
|
/// </summary>
|
|
public bool? Favorite { get; set; }
|
|
|
|
/// <summary>
|
|
/// 备注。
|
|
/// </summary>
|
|
[StringLength(1000)]
|
|
public string? Note { get; set; }
|
|
|
|
public FavoriteWordCommand ToCommand()
|
|
{
|
|
return new FavoriteWordCommand(WordId, Favorite, Note);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 单词Review请求 DTO。
|
|
/// </summary>
|
|
public sealed class WordReviewDto
|
|
{
|
|
/// <summary>
|
|
/// 单词 ID。
|
|
/// </summary>
|
|
[Required]
|
|
public Guid WordId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 结果。
|
|
/// </summary>
|
|
[StringLength(50)]
|
|
public string? Result { get; set; }
|
|
|
|
/// <summary>
|
|
/// 下次复习时间。
|
|
/// </summary>
|
|
public DateTimeOffset? NextReviewAt { get; set; }
|
|
|
|
public WordReviewCommand ToCommand()
|
|
{
|
|
return new WordReviewCommand(WordId, Result, NextReviewAt);
|
|
}
|
|
}
|