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

150 lines
7.0 KiB
C#

using Microsoft.EntityFrameworkCore;
using Tiku.Application.Catalog;
using Tiku.Application.Content;
using Tiku.Domain.Catalog;
using Tiku.Domain.Content;
using Tiku.Infrastructure.Security;
namespace Tiku.Infrastructure.Content;
public sealed partial class DirectContentService
{
public async Task<CatalogList<VocabularyUnit>> GetVocabularyUnitsAsync(
DirectContentActor actor,
AdminLimitFilter filter,
CancellationToken cancellationToken = default)
{
var scope = await RequireDataScopeAsync(actor, cancellationToken);
var regionIds = scope.RegionIds.ToArray();
var query = dbContext.VocabularyUnits.AsNoTracking()
.Where(item => item.TenantId == actor.TenantId)
.ApplyDataScope(scope, null, item => item.RegionId.HasValue && regionIds.Contains(item.RegionId.Value));
if (filter.RegionId.HasValue) query = query.Where(item => item.RegionId == filter.RegionId.Value);
if (filter.EntryId.HasValue) query = query.Where(item => item.EntryId == filter.EntryId.Value);
if (filter.ContentNodeId.HasValue)
query = query.Where(item => item.ContentNodeId == filter.ContentNodeId.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.Name.Contains(keyword) || (item.Description != null && item.Description.Contains(keyword)));
}
return new CatalogList<VocabularyUnit>(await query
.OrderBy(item => item.SortOrder)
.ThenBy(item => item.CreatedAt)
.Take(ResolveLimit(filter.Limit))
.ToArrayAsync(cancellationToken));
}
public async Task<ContentManagementResult<VocabularyUnit>> UpsertVocabularyUnitAsync(
DirectContentActor actor,
VocabularyUnitCommand command,
CancellationToken cancellationToken = default)
{
var scope = await RequireDataScopeAsync(actor, cancellationToken);
ArgumentException.ThrowIfNullOrWhiteSpace(command.Name);
await AssertReferenceAsync<Region>(actor.TenantId, command.RegionId, "region_not_found", cancellationToken);
await AssertReferenceAsync<ContentEntry>(actor.TenantId, command.EntryId, "entry_not_found", cancellationToken);
await AssertReferenceAsync<ContentNode>(actor.TenantId, command.ContentNodeId, "node_not_found",
cancellationToken);
var item = await ResolveByIdOrLegacyAsync(dbContext.VocabularyUnits, actor.TenantId, command.Id,
command.LegacyId, cancellationToken);
var isNew = item is null;
EnsureRegionWriteAllowed(scope, actor, item?.RegionId, command.RegionId, isNew, "vocabulary_unit_not_found");
item ??= new VocabularyUnit { Id = command.Id ?? Guid.NewGuid(), TenantId = actor.TenantId };
item.RegionId = command.RegionId;
item.EntryId = command.EntryId;
item.ContentNodeId = command.ContentNodeId;
item.LegacyId = Normalize(command.LegacyId);
item.Name = command.Name.Trim();
item.Description = Normalize(command.Description);
item.WordCount = command.WordCount;
item.SortOrder = command.Order ?? item.SortOrder;
item.IsActive = command.IsActive ?? item.IsActive;
item.Metadata = JsonObjectOrDefault(command.Metadata);
if (isNew) dbContext.VocabularyUnits.Add(item);
await dbContext.SaveChangesAsync(cancellationToken);
return new ContentManagementResult<VocabularyUnit>(item);
}
public async Task<CatalogList<VocabularyWord>> GetVocabularyWordsAsync(
DirectContentActor actor,
AdminLimitFilter filter,
CancellationToken cancellationToken = default)
{
var query = dbContext.VocabularyWords.AsNoTracking().Where(item => item.TenantId == actor.TenantId);
if (filter.UnitId.HasValue) query = query.Where(item => item.UnitId == filter.UnitId.Value);
if (filter.EntryId.HasValue) query = query.Where(item => item.EntryId == filter.EntryId.Value);
if (filter.ContentNodeId.HasValue)
query = query.Where(item => item.ContentNodeId == filter.ContentNodeId.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.Word.Contains(keyword) || (item.Meaning != null && item.Meaning.Contains(keyword)));
}
return new CatalogList<VocabularyWord>(await query
.OrderBy(item => item.SortOrder)
.ThenBy(item => item.Word)
.Take(ResolveLimit(filter.Limit))
.ToArrayAsync(cancellationToken));
}
public async Task<ContentManagementResult<VocabularyWord>> UpsertVocabularyWordAsync(
DirectContentActor actor,
VocabularyWordCommand command,
CancellationToken cancellationToken = default)
{
ArgumentException.ThrowIfNullOrWhiteSpace(command.Word);
await AssertReferenceAsync<VocabularyUnit>(actor.TenantId, command.UnitId, "vocabulary_unit_not_found",
cancellationToken);
await AssertReferenceAsync<ContentEntry>(actor.TenantId, command.EntryId, "entry_not_found", cancellationToken);
await AssertReferenceAsync<ContentNode>(actor.TenantId, command.ContentNodeId, "node_not_found",
cancellationToken);
var item = await ResolveByIdOrLegacyAsync(dbContext.VocabularyWords, actor.TenantId, command.Id,
command.LegacyId, cancellationToken);
var isNew = item is null;
item ??= new VocabularyWord { Id = command.Id ?? Guid.NewGuid(), TenantId = actor.TenantId };
var vocabularyNavigation = await ResolveVocabularyNavigationAsync(
actor.TenantId,
command.UnitId,
command.EntryId,
command.ContentNodeId,
cancellationToken);
item.UnitId = command.UnitId;
item.EntryId = vocabularyNavigation.EntryId;
item.ContentNodeId = vocabularyNavigation.ContentNodeId;
item.LegacyId = Normalize(command.LegacyId);
item.Word = command.Word.Trim();
item.Phonetic = Normalize(command.Phonetic);
item.Meaning = Normalize(command.Meaning);
item.Example = Normalize(command.Example);
item.ExampleTranslation = Normalize(command.ExampleTranslation);
item.Difficulty = command.Difficulty;
item.Tags = JsonArrayOrDefault(command.Tags);
item.SortOrder = command.Order ?? item.SortOrder;
item.IsActive = command.IsActive ?? item.IsActive;
item.Metadata = JsonObjectOrDefault(command.Metadata);
if (isNew) dbContext.VocabularyWords.Add(item);
await dbContext.SaveChangesAsync(cancellationToken);
return new ContentManagementResult<VocabularyWord>(item);
}
}