using F9WebAiTest.Application.Common.Exceptions; using F9WebAiTest.Application.Interfaces.SnowflakeID; using F9WebAiTest.Domain.Entities.SYS.Registries; using F9WebAiTest.Domain.Interfaces.SYS.Registries; using MediatR; namespace F9WebAiTest.Application.CQRS.SYS.Registries.Commands; /// 注册表支持的数据类型(与前端下拉、F9 的 IRegistryService 保持一致) public static class RegistryDataTypes { public static readonly string[] All = { "string", "int", "decimal", "bool", "json", "array" }; /// 归一化为小写并校验(如 F9 历史数据里的 "Array" → "array") public static string Normalize(string dataType) { var value = (dataType ?? "").Trim().ToLowerInvariant(); if (value.Length == 0) return "string"; if (!All.Contains(value)) throw new F9OperationException($"数据类型[{dataType}]不支持,可选:{string.Join(" / ", All)}"); return value; } } /// /// 新增配置项(存在同"命名空间 + 键名"的记录时自动改为更新,对应 F9 的 BASE-REGISTRY-RULE-1) /// public record Registry_CreateCommand(string Category, string KeyName, string Value, string DataType, string Description, bool IsActive) : IRequest; public class CreateRegistryCommandHandler( IRegistryWriteRepository registryRepository, ISnowflakeIdGenerator snowflakeIdGenerator, IPublisher eventBus) : IRequestHandler { public async Task Handle(Registry_CreateCommand command, CancellationToken cancellationToken) { var category = (command.Category ?? "").Trim(); var keyName = (command.KeyName ?? "").Trim(); if (string.IsNullOrEmpty(category)) throw new F9OperationException("命名空间不能为空"); if (string.IsNullOrEmpty(keyName)) throw new F9OperationException("键名不能为空"); var dataType = RegistryDataTypes.Normalize(command.DataType); var value = command.Value ?? string.Empty; var description = command.Description ?? string.Empty; // 已存在同命名空间 + 键名的配置:直接更新(供 SetRegistry 之类的"设置值"场景复用) var exist = await registryRepository.GetByCategoryAndKeyAsync(category, keyName); if (exist != null) { exist.Update(category, keyName, value, dataType, description, command.IsActive); var updated = await registryRepository.UpdateAsync(exist); if (updated == false) throw new F9OperationException("注册表配置", "修改"); foreach (var de in exist.DomainEvents) await eventBus.Publish(de, cancellationToken); exist.ClearDomainEvents(); return exist.Id; } var entity = new Registry(snowflakeIdGenerator.CreateId(), category, keyName, value, dataType, description, command.IsActive); var result = await registryRepository.AddAsync(entity); if (result == false) throw new F9OperationException("注册表配置", "新增"); foreach (var de in entity.DomainEvents) await eventBus.Publish(de, cancellationToken); entity.ClearDomainEvents(); return entity.Id; } } /// 修改配置项 public record Registry_UpdateCommand(long Id, string Category, string KeyName, string Value, string DataType, string Description, bool IsActive) : IRequest; public class UpdateRegistryCommandHandler( IRegistryWriteRepository registryRepository, IPublisher eventBus) : IRequestHandler { public async Task Handle(Registry_UpdateCommand command, CancellationToken cancellationToken) { var entity = await registryRepository.GetByIdAsync(command.Id, cancellationToken) ?? throw new F9NotFoundException("注册表配置不存在"); var category = (command.Category ?? "").Trim(); var keyName = (command.KeyName ?? "").Trim(); if (string.IsNullOrEmpty(category)) throw new F9OperationException("命名空间不能为空"); if (string.IsNullOrEmpty(keyName)) throw new F9OperationException("键名不能为空"); // 同一命名空间下键名不能重复 var duplicate = await registryRepository.GetByCategoryAndKeyAsync(category, keyName); if (duplicate != null && duplicate.Id != command.Id) throw new F9OperationException($"命名空间[{category}]下已存在键名[{keyName}]"); entity.Update(category, keyName, command.Value ?? string.Empty, RegistryDataTypes.Normalize(command.DataType), command.Description ?? string.Empty, command.IsActive); var result = await registryRepository.UpdateAsync(entity); if (result == false) throw new F9OperationException("注册表配置", "修改"); foreach (var de in entity.DomainEvents) await eventBus.Publish(de, cancellationToken); entity.ClearDomainEvents(); return true; } } /// 只修改值("设置注册表值"场景) public record Registry_SetValueCommand(long Id, string Value) : IRequest; public class SetValueRegistryCommandHandler( IRegistryWriteRepository registryRepository, IPublisher eventBus) : IRequestHandler { public async Task Handle(Registry_SetValueCommand command, CancellationToken cancellationToken) { var entity = await registryRepository.GetByIdAsync(command.Id, cancellationToken) ?? throw new F9NotFoundException("注册表配置不存在"); entity.SetValue(command.Value ?? string.Empty); var result = await registryRepository.UpdateAsync(entity); if (result == false) throw new F9OperationException("注册表配置", "修改"); foreach (var de in entity.DomainEvents) await eventBus.Publish(de, cancellationToken); entity.ClearDomainEvents(); return true; } } /// 删除配置项 public record Registry_DelCommand(long Id) : IRequest; public class DelRegistryCommandHandler( IRegistryWriteRepository registryRepository, IPublisher eventBus) : IRequestHandler { public async Task Handle(Registry_DelCommand command, CancellationToken cancellationToken) { var entity = await registryRepository.GetByIdAsync(command.Id, cancellationToken) ?? throw new F9NotFoundException("注册表配置不存在"); var result = await registryRepository.SoftDeleteAsync(command.Id); if (result == false) throw new F9OperationException("注册表配置", "删除"); entity.Deleted(); foreach (var de in entity.DomainEvents) await eventBus.Publish(de, cancellationToken); entity.ClearDomainEvents(); return true; } }