153 lines
6.8 KiB
C#
153 lines
6.8 KiB
C#
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;
|
||
|
||
/// <summary>注册表支持的数据类型(与前端下拉、F9 的 IRegistryService 保持一致)</summary>
|
||
public static class RegistryDataTypes
|
||
{
|
||
public static readonly string[] All = { "string", "int", "decimal", "bool", "json", "array" };
|
||
|
||
/// <summary>归一化为小写并校验(如 F9 历史数据里的 "Array" → "array")</summary>
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 新增配置项(存在同"命名空间 + 键名"的记录时自动改为更新,对应 F9 的 BASE-REGISTRY-RULE-1)
|
||
/// </summary>
|
||
public record Registry_CreateCommand(string Category, string KeyName, string Value, string DataType, string Description, bool IsActive)
|
||
: IRequest<long>;
|
||
|
||
public class CreateRegistryCommandHandler(
|
||
IRegistryWriteRepository registryRepository,
|
||
ISnowflakeIdGenerator snowflakeIdGenerator,
|
||
IPublisher eventBus) : IRequestHandler<Registry_CreateCommand, long>
|
||
{
|
||
public async Task<long> 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;
|
||
}
|
||
}
|
||
|
||
/// <summary>修改配置项</summary>
|
||
public record Registry_UpdateCommand(long Id, string Category, string KeyName, string Value, string DataType, string Description, bool IsActive)
|
||
: IRequest<bool>;
|
||
|
||
public class UpdateRegistryCommandHandler(
|
||
IRegistryWriteRepository registryRepository,
|
||
IPublisher eventBus) : IRequestHandler<Registry_UpdateCommand, bool>
|
||
{
|
||
public async Task<bool> 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;
|
||
}
|
||
}
|
||
|
||
/// <summary>只修改值("设置注册表值"场景)</summary>
|
||
public record Registry_SetValueCommand(long Id, string Value) : IRequest<bool>;
|
||
|
||
public class SetValueRegistryCommandHandler(
|
||
IRegistryWriteRepository registryRepository,
|
||
IPublisher eventBus) : IRequestHandler<Registry_SetValueCommand, bool>
|
||
{
|
||
public async Task<bool> 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;
|
||
}
|
||
}
|
||
|
||
/// <summary>删除配置项</summary>
|
||
public record Registry_DelCommand(long Id) : IRequest<bool>;
|
||
|
||
public class DelRegistryCommandHandler(
|
||
IRegistryWriteRepository registryRepository,
|
||
IPublisher eventBus) : IRequestHandler<Registry_DelCommand, bool>
|
||
{
|
||
public async Task<bool> 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;
|
||
}
|
||
}
|