Files
tiku-backend.net/Tiku.Infrastructure/Assets/Catalog/AssetCatalogManagementService.cs
xiong 33375a38d7
Some checks failed
ci / release-gate (push) Has been cancelled
refactor(architecture): harden module boundaries
2026-08-04 12:10:36 +08:00

120 lines
6.0 KiB
C#

using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Tiku.Application.Assets;
using Tiku.Application.Catalog;
using Tiku.Application.Content;
using Tiku.Domain.Content;
namespace Tiku.Infrastructure.Assets;
internal sealed class AssetCatalogManagementService(AssetManagementDependencies dependencies)
: AssetManagementServiceBase(dependencies), IAssetCatalogManagementService
{
public async Task<CatalogList<ContentAssetManagementItem>> GetAssetsAsync(
AssetManagementActor actor,
AssetManagementFilter filter,
CancellationToken cancellationToken = default)
{
var query = contentAssetPersistence.ContentAssets
.AsNoTracking()
.Where(asset => asset.TenantId == actor.TenantId);
if (filter.RegionId.HasValue) query = query.Where(asset => asset.RegionId == filter.RegionId.Value);
if (filter.SubjectId.HasValue) query = query.Where(asset => asset.SubjectId == filter.SubjectId.Value);
if (filter.CategoryId.HasValue) query = query.Where(asset => asset.CategoryId == filter.CategoryId.Value);
if (filter.ContentNodeId.HasValue)
query = query.Where(asset => asset.ContentNodeId == filter.ContentNodeId.Value);
if (!string.IsNullOrWhiteSpace(filter.AssetType) &&
Enum.TryParse<ContentAssetType>(filter.AssetType, true, out var assetType))
query = query.Where(asset => asset.AssetType == assetType);
if (!string.IsNullOrWhiteSpace(filter.UploadStatus) &&
Enum.TryParse<AssetUploadStatus>(filter.UploadStatus, true, out var uploadStatus))
query = query.Where(asset => asset.UploadStatus == uploadStatus);
if (!string.IsNullOrWhiteSpace(filter.SecurityScanStatus) &&
Enum.TryParse<AssetSecurityScanStatus>(filter.SecurityScanStatus, true, out var securityScanStatus))
query = query.Where(asset => asset.SecurityScanStatus == securityScanStatus);
if (!string.IsNullOrWhiteSpace(filter.Category))
{
var category = filter.Category.Trim();
query = query.Where(asset => asset.Category == category);
}
if (!string.IsNullOrWhiteSpace(filter.Keyword))
{
var keyword = filter.Keyword.Trim();
query = query.Where(asset =>
(asset.Title != null && asset.Title.Contains(keyword)) ||
(asset.FileName != null && asset.FileName.Contains(keyword)) ||
(asset.Description != null && asset.Description.Contains(keyword)) ||
(asset.AssetKey != null && asset.AssetKey.Contains(keyword)));
}
var items = await query
.OrderBy(asset => asset.SortOrder)
.ThenByDescending(asset => asset.CreatedAt)
.Take(ResolveLimit(filter.Limit))
.Select(asset => ToItem(asset))
.ToArrayAsync(cancellationToken);
return new CatalogList<ContentAssetManagementItem>(items);
}
public async Task<ContentManagementResult<ContentAssetManagementItem>> UpsertAssetAsync(
AssetManagementActor actor,
UpsertAssetCommand command,
CancellationToken cancellationToken = default)
{
var asset = await ResolveManagementAssetAsync(actor, command, cancellationToken);
var accountedBytesBefore = AccountedStorageBytes(asset);
asset.RegionId = command.RegionId;
asset.SubjectId = command.SubjectId;
asset.CategoryId = command.CategoryId;
asset.ContentNodeId = command.ContentNodeId;
asset.LegacyId = NormalizeOptional(command.LegacyId);
asset.AssetKey = NormalizeOptional(command.AssetKey);
asset.Title = NormalizeOptional(command.Title) ?? NormalizeOptional(command.FileName) ?? asset.Title ?? "未命名资源";
asset.Category = NormalizeOptional(command.Category);
asset.Description = NormalizeOptional(command.Description);
asset.FileName = NormalizeOptional(command.FileName);
asset.CdnUrl = NormalizeOptional(command.CdnUrl);
asset.IsPublic = command.IsPublic ?? asset.IsPublic;
asset.AssetType = ParseEnum(command.AssetType, asset.AssetType);
asset.Visibility = ResolveVisibility(command.Visibility, asset.IsPublic);
asset.Status = ParseEnum(command.Status, asset.Status);
asset.StorageProvider =
ToAssetStorageProvider(objectStorageService.NormalizeProvider(command.Provider,
ToObjectStorageProvider(asset.StorageProvider)));
asset.Bucket = string.IsNullOrWhiteSpace(command.Bucket) ? asset.Bucket : command.Bucket.Trim();
asset.ObjectKey = string.IsNullOrWhiteSpace(command.ObjectKey)
? asset.ObjectKey
: objectStorageService.ValidateObjectKey(actor.TenantId, command.ObjectKey.Trim());
asset.MimeType = string.IsNullOrWhiteSpace(command.MimeType)
? asset.MimeType
: objectStorageService.ValidateMimeType(command.MimeType.Trim());
asset.FileSizeBytes = objectStorageService.ValidateFileSize(command.FileSizeBytes ?? asset.FileSizeBytes);
asset.ChecksumSha256 = NormalizeChecksum(command.ChecksumSha256) ?? asset.ChecksumSha256;
asset.PreviewUrl = NormalizeOptional(command.PreviewUrl);
asset.PreviewObjectKey = NormalizeOptional(command.PreviewObjectKey) ?? asset.PreviewObjectKey;
asset.SortOrder = command.Order ?? asset.SortOrder;
asset.AccessRules = command.AccessRules.ValueKind == JsonValueKind.Undefined
? asset.AccessRules
: command.AccessRules;
asset.Metadata = command.Metadata.ValueKind == JsonValueKind.Undefined ? asset.Metadata : command.Metadata;
asset.UpdatedBy = actor.UserId;
var accountedBytesAfter = AccountedStorageBytes(asset);
await SaveWithStorageQuotaAdjustmentAsync(
actor.TenantId,
accountedBytesAfter - accountedBytesBefore,
cancellationToken);
return new ContentManagementResult<ContentAssetManagementItem>(ToItem(asset));
}
}