99 lines
4.7 KiB
C#
99 lines
4.7 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Tiku.Application.Catalog;
|
|
using Tiku.Application.Content;
|
|
using Tiku.Domain.Catalog;
|
|
using Tiku.Domain.Content;
|
|
using Tiku.Domain.QuestionBanks;
|
|
|
|
namespace Tiku.Infrastructure.Content;
|
|
|
|
public sealed partial class DirectContentService
|
|
{
|
|
public async Task<CatalogList<VideoManagementItem>> GetVideosAsync(
|
|
DirectContentActor actor,
|
|
AdminLimitFilter filter,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var query = dbContext.VideoExplanations.AsNoTracking().Where(item => item.TenantId == actor.TenantId);
|
|
if (filter.SubjectId.HasValue) query = query.Where(item => item.SubjectId == filter.SubjectId.Value);
|
|
|
|
if (!string.Equals(filter.Status, "all", StringComparison.OrdinalIgnoreCase))
|
|
query = query.Where(item => item.IsActive);
|
|
|
|
if (!string.IsNullOrWhiteSpace(filter.Keyword))
|
|
{
|
|
var keyword = filter.Keyword.Trim();
|
|
query = query.Where(item =>
|
|
item.Title.Contains(keyword) || (item.Description != null && item.Description.Contains(keyword)));
|
|
}
|
|
|
|
var items = await query
|
|
.OrderBy(item => item.SortOrder)
|
|
.ThenByDescending(item => item.CreatedAt)
|
|
.Take(ResolveLimit(filter.Limit))
|
|
.Select(item => ToVideoItem(item))
|
|
.ToArrayAsync(cancellationToken);
|
|
return new CatalogList<VideoManagementItem>(items);
|
|
}
|
|
|
|
public async Task<ContentManagementResult<VideoManagementItem>> UpsertVideoAsync(
|
|
DirectContentActor actor,
|
|
VideoExplanationCommand command,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(command.Title);
|
|
await AssertReferenceAsync<Subject>(actor.TenantId, command.SubjectId, "subject_not_found", cancellationToken);
|
|
var item = await ResolveByIdOrLegacyAsync(dbContext.VideoExplanations, actor.TenantId, command.Id,
|
|
command.LegacyId, cancellationToken);
|
|
var isNew = item is null;
|
|
item ??= new VideoExplanation { Id = command.Id ?? Guid.NewGuid(), TenantId = actor.TenantId };
|
|
item.SubjectId = command.SubjectId;
|
|
item.LegacyId = Normalize(command.LegacyId);
|
|
item.Title = command.Title.Trim();
|
|
item.Description = Normalize(command.Description);
|
|
item.VideoUrl = Normalize(command.VideoUrl);
|
|
item.ThumbnailUrl = Normalize(command.ThumbnailUrl);
|
|
item.DurationSeconds = command.DurationSeconds;
|
|
item.KnowledgeTags = JsonArrayOrDefault(command.KnowledgeTags);
|
|
item.IsGeneral = command.IsGeneral ?? item.IsGeneral;
|
|
item.Difficulty = command.Difficulty;
|
|
item.SortOrder = command.Order ?? item.SortOrder;
|
|
item.IsActive = command.IsActive ?? item.IsActive;
|
|
item.Metadata = JsonObjectOrDefault(command.Metadata);
|
|
if (isNew) dbContext.VideoExplanations.Add(item);
|
|
|
|
await dbContext.SaveChangesAsync(cancellationToken);
|
|
return new ContentManagementResult<VideoManagementItem>(ToVideoItem(item));
|
|
}
|
|
|
|
public async Task<ContentManagementResult<QuestionVideoManagementItem>> BindQuestionVideoAsync(
|
|
DirectContentActor actor,
|
|
QuestionVideoCommand command,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
await AssertReferenceAsync<Question>(actor.TenantId, command.QuestionId, "question_not_found",
|
|
cancellationToken);
|
|
await AssertReferenceAsync<VideoExplanation>(actor.TenantId, command.VideoId, "video_not_found",
|
|
cancellationToken);
|
|
var item = await dbContext.QuestionVideos.SingleOrDefaultAsync(
|
|
link => link.TenantId == actor.TenantId && link.QuestionId == command.QuestionId &&
|
|
link.VideoId == command.VideoId,
|
|
cancellationToken);
|
|
var isNew = item is null;
|
|
item ??= new QuestionVideo { TenantId = actor.TenantId };
|
|
item.QuestionId = command.QuestionId;
|
|
item.VideoId = command.VideoId;
|
|
item.LegacyId = Normalize(command.LegacyId);
|
|
item.VideoType = Parse(command.VideoType, QuestionVideoType.Specific, "question_video_type_invalid");
|
|
item.SortOrder = command.Order ?? item.SortOrder;
|
|
item.Metadata = JsonObjectOrDefault(command.Metadata);
|
|
if (isNew) dbContext.QuestionVideos.Add(item);
|
|
|
|
var question = await dbContext.Questions.SingleAsync(
|
|
question => question.TenantId == actor.TenantId && question.Id == command.QuestionId,
|
|
cancellationToken);
|
|
question.HasVideoExplanation = true;
|
|
await dbContext.SaveChangesAsync(cancellationToken);
|
|
return new ContentManagementResult<QuestionVideoManagementItem>(ToQuestionVideoItem(item));
|
|
}
|
|
} |