forked from xiongyuxing/tiku-backend.net
feat: add student video and profile experience
This commit is contained in:
80
Tiku.Application/Assets/VideoPlaybackModels.cs
Normal file
80
Tiku.Application/Assets/VideoPlaybackModels.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System.Text.Json;
|
||||
using Tiku.Application.Catalog;
|
||||
using Tiku.Domain.Content;
|
||||
|
||||
namespace Tiku.Application.Assets;
|
||||
|
||||
public sealed record VideoPlaybackActor(Guid TenantId, Guid UserId);
|
||||
|
||||
public sealed record VideoSearchQuery(
|
||||
string? Keyword = null,
|
||||
Guid? SubjectId = null,
|
||||
int? Limit = null);
|
||||
|
||||
public sealed record QuestionVideoQuery(
|
||||
Guid? QuestionId = null,
|
||||
IReadOnlyCollection<Guid>? QuestionIds = null,
|
||||
int? Limit = null);
|
||||
|
||||
public sealed record VideoPlayCommand(Guid VideoId, Guid? QuestionId = null);
|
||||
|
||||
public sealed record VideoProgressCommand(
|
||||
Guid VideoId,
|
||||
Guid? QuestionId,
|
||||
int PositionSeconds,
|
||||
int? DurationSeconds,
|
||||
int? WatchedSeconds,
|
||||
bool? IsCompleted,
|
||||
JsonElement Metadata);
|
||||
|
||||
public sealed record VideoPlaybackItem(
|
||||
Guid VideoId,
|
||||
Guid? QuestionId,
|
||||
string Title,
|
||||
string? Description,
|
||||
string? PlayUrl,
|
||||
string? ThumbnailUrl,
|
||||
int? DurationSeconds,
|
||||
VideoProgressItem? Progress,
|
||||
JsonElement Metadata);
|
||||
|
||||
public sealed record VideoProgressItem(
|
||||
Guid Id,
|
||||
Guid VideoId,
|
||||
Guid? QuestionId,
|
||||
int PositionSeconds,
|
||||
int? DurationSeconds,
|
||||
int WatchedSeconds,
|
||||
bool IsCompleted,
|
||||
DateTimeOffset? CompletedAt,
|
||||
DateTimeOffset LastPlayedAt,
|
||||
int PlayCount,
|
||||
JsonElement Metadata);
|
||||
|
||||
public interface IVideoPlaybackService
|
||||
{
|
||||
Task<CatalogList<VideoExplanationCatalogItem>> SearchAsync(
|
||||
VideoPlaybackActor actor,
|
||||
VideoSearchQuery query,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<VideoPlaybackItem> PlayAsync(
|
||||
VideoPlaybackActor actor,
|
||||
VideoPlayCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<VideoProgressItem> ReportProgressAsync(
|
||||
VideoPlaybackActor actor,
|
||||
VideoProgressCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<CatalogList<QuestionVideoCatalogItem>> GetQuestionVideosAsync(
|
||||
VideoPlaybackActor actor,
|
||||
QuestionVideoQuery query,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public sealed class VideoPlaybackException(string message, string code) : Exception(message)
|
||||
{
|
||||
public string Code { get; } = code;
|
||||
}
|
||||
@@ -346,6 +346,7 @@ public interface IDirectContentService
|
||||
Task<ContentManagementResult<OperationContentItem>> UpsertOperationContentAsync(DirectContentActor actor, string kind, OperationContentCommand command, CancellationToken cancellationToken = default);
|
||||
Task<SimpleImportResult> PreviewImportAsync(DirectContentActor actor, SimpleImportCommand command, CancellationToken cancellationToken = default);
|
||||
Task<SimpleImportResult> ExecuteImportAsync(DirectContentActor actor, SimpleImportCommand command, CancellationToken cancellationToken = default);
|
||||
Task<ContentImportJobDetail> GetImportJobAsync(DirectContentActor actor, Guid jobId, CancellationToken cancellationToken = default);
|
||||
Task<CatalogList<ContentImportIssueModel>> GetImportIssuesAsync(DirectContentActor actor, Guid jobId, CancellationToken cancellationToken = default);
|
||||
Task<ImportPostCheckResult> RunImportPostCheckAsync(DirectContentActor actor, Guid jobId, CancellationToken cancellationToken = default);
|
||||
Task<ImportPostCheckResult> GetImportPostCheckAsync(DirectContentActor actor, Guid jobId, CancellationToken cancellationToken = default);
|
||||
|
||||
@@ -6,6 +6,12 @@ public sealed record ProfileActor(Guid TenantId, Guid UserId);
|
||||
|
||||
public sealed record ProfileQuery(int? RecentLimit = null, int? Limit = null);
|
||||
|
||||
public sealed record ProfileScoreEventQuery(
|
||||
int? Limit = null,
|
||||
string? SourceType = null,
|
||||
DateTimeOffset? From = null,
|
||||
DateTimeOffset? To = null);
|
||||
|
||||
public sealed record UpdateProfileCommand(
|
||||
string? Name,
|
||||
string? AvatarPreset,
|
||||
@@ -144,6 +150,26 @@ public sealed record SubmitFeedbackCommand(
|
||||
JsonElement Attachments,
|
||||
JsonElement Metadata);
|
||||
|
||||
public sealed record CheckInResult(
|
||||
DateOnly CheckInDate,
|
||||
bool AlreadyCheckedIn,
|
||||
int Points,
|
||||
int BalanceAfter,
|
||||
Guid? ClaimId,
|
||||
Guid? ScoreEventId);
|
||||
|
||||
public sealed record ProfileScoreEventItem(
|
||||
Guid Id,
|
||||
string EventType,
|
||||
int Points,
|
||||
int BalanceAfter,
|
||||
string? SourceType,
|
||||
Guid? SourceId,
|
||||
JsonElement Metadata,
|
||||
DateTimeOffset CreatedAt);
|
||||
|
||||
public sealed record ProfileScoreEventList(IReadOnlyCollection<ProfileScoreEventItem> Items);
|
||||
|
||||
public interface IProfileService
|
||||
{
|
||||
Task<StudentProfileItem> GetMeAsync(ProfileActor actor, ProfileQuery query, CancellationToken cancellationToken = default);
|
||||
@@ -154,4 +180,6 @@ public interface IProfileService
|
||||
Task<BadgeList> GetBadgesAsync(ProfileActor actor, BadgeQuery query, CancellationToken cancellationToken = default);
|
||||
Task<IReadOnlyCollection<FeedbackItem>> GetFeedbacksAsync(ProfileActor actor, FeedbackQuery query, CancellationToken cancellationToken = default);
|
||||
Task<FeedbackItem> SubmitFeedbackAsync(ProfileActor actor, SubmitFeedbackCommand command, CancellationToken cancellationToken = default);
|
||||
Task<CheckInResult> CheckInAsync(ProfileActor actor, CancellationToken cancellationToken = default);
|
||||
Task<ProfileScoreEventList> GetScoreEventsAsync(ProfileActor actor, ProfileScoreEventQuery query, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user