Files
tiku-backend.net/Tiku.Infrastructure/Content/Videos/DirectContentService.Videos.cs
xiong c497a3ca8d
Some checks failed
ci / release-gate (push) Has been cancelled
清理代码
2026-08-03 12:31:39 +08:00

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));
}
}