feat: 实现字典管理后端
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Security.Cryptography;
|
||||
using TakeoutSaaS.Application.Dictionary.Abstractions;
|
||||
using TakeoutSaaS.Application.Dictionary.Contracts;
|
||||
using TakeoutSaaS.Application.Dictionary.Models;
|
||||
@@ -47,8 +48,10 @@ public sealed class DictionaryAppService(
|
||||
Code = normalizedCode,
|
||||
Name = request.Name.Trim(),
|
||||
Scope = request.Scope,
|
||||
AllowOverride = request.AllowOverride,
|
||||
Description = request.Description?.Trim(),
|
||||
IsEnabled = true
|
||||
IsEnabled = true,
|
||||
RowVersion = RandomNumberGenerator.GetBytes(16)
|
||||
};
|
||||
|
||||
// 4. 持久化并返回
|
||||
@@ -71,13 +74,32 @@ public sealed class DictionaryAppService(
|
||||
var group = await RequireGroupAsync(groupId, cancellationToken);
|
||||
EnsureScopePermission(group.Scope);
|
||||
|
||||
if (request.RowVersion == null || request.RowVersion.Length == 0)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.ValidationFailed, "RowVersion 不能为空");
|
||||
}
|
||||
|
||||
if (!request.RowVersion.SequenceEqual(group.RowVersion))
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.Conflict, "字典分组已被修改,请刷新后重试");
|
||||
}
|
||||
|
||||
// 2. 更新字段
|
||||
group.Name = request.Name.Trim();
|
||||
group.Description = request.Description?.Trim();
|
||||
group.IsEnabled = request.IsEnabled;
|
||||
group.AllowOverride = request.AllowOverride;
|
||||
group.RowVersion = RandomNumberGenerator.GetBytes(16);
|
||||
|
||||
// 3. 持久化并失效缓存
|
||||
await repository.SaveChangesAsync(cancellationToken);
|
||||
try
|
||||
{
|
||||
await repository.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
catch (Exception exception) when (IsConcurrencyException(exception))
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.Conflict, "字典分组已被修改,请刷新后重试");
|
||||
}
|
||||
await InvalidateCacheAsync(group, cancellationToken);
|
||||
logger.LogInformation("更新字典分组:{GroupId}", group.Id);
|
||||
return MapGroup(group, includeItems: false);
|
||||
@@ -154,11 +176,12 @@ public sealed class DictionaryAppService(
|
||||
TenantId = group.TenantId,
|
||||
GroupId = group.Id,
|
||||
Key = request.Key.Trim(),
|
||||
Value = request.Value.Trim(),
|
||||
Value = DictionaryValueConverter.Serialize(request.Value),
|
||||
Description = request.Description?.Trim(),
|
||||
SortOrder = request.SortOrder,
|
||||
IsDefault = request.IsDefault,
|
||||
IsEnabled = request.IsEnabled
|
||||
IsEnabled = request.IsEnabled,
|
||||
RowVersion = RandomNumberGenerator.GetBytes(16)
|
||||
};
|
||||
|
||||
// 3. 持久化并失效缓存
|
||||
@@ -183,15 +206,34 @@ public sealed class DictionaryAppService(
|
||||
var group = await RequireGroupAsync(item.GroupId, cancellationToken);
|
||||
EnsureScopePermission(group.Scope);
|
||||
|
||||
if (request.RowVersion == null || request.RowVersion.Length == 0)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.ValidationFailed, "RowVersion 不能为空");
|
||||
}
|
||||
|
||||
if (!request.RowVersion.SequenceEqual(item.RowVersion))
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.Conflict, "字典项已被修改,请刷新后重试");
|
||||
}
|
||||
|
||||
// 2. 更新字段
|
||||
item.Value = request.Value.Trim();
|
||||
item.Key = request.Key.Trim();
|
||||
item.Value = DictionaryValueConverter.Serialize(request.Value);
|
||||
item.Description = request.Description?.Trim();
|
||||
item.SortOrder = request.SortOrder;
|
||||
item.IsDefault = request.IsDefault;
|
||||
item.IsEnabled = request.IsEnabled;
|
||||
item.RowVersion = RandomNumberGenerator.GetBytes(16);
|
||||
|
||||
// 3. 持久化并失效缓存
|
||||
await repository.SaveChangesAsync(cancellationToken);
|
||||
try
|
||||
{
|
||||
await repository.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
catch (Exception exception) when (IsConcurrencyException(exception))
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.Conflict, "字典项已被修改,请刷新后重试");
|
||||
}
|
||||
await InvalidateCacheAsync(group, cancellationToken);
|
||||
logger.LogInformation("更新字典项:{ItemId}", item.Id);
|
||||
return MapItem(item);
|
||||
@@ -381,10 +423,15 @@ public sealed class DictionaryAppService(
|
||||
{
|
||||
Id = group.Id,
|
||||
Code = group.Code,
|
||||
TenantId = group.TenantId,
|
||||
Name = group.Name,
|
||||
Scope = group.Scope,
|
||||
Description = group.Description,
|
||||
AllowOverride = group.AllowOverride,
|
||||
IsEnabled = group.IsEnabled,
|
||||
CreatedAt = group.CreatedAt,
|
||||
UpdatedAt = group.UpdatedAt,
|
||||
RowVersion = group.RowVersion,
|
||||
Items = includeItems ? items ?? group.Items.Select(MapItem).ToList() : Array.Empty<DictionaryItemDto>()
|
||||
};
|
||||
}
|
||||
@@ -395,10 +442,15 @@ public sealed class DictionaryAppService(
|
||||
Id = item.Id,
|
||||
GroupId = item.GroupId,
|
||||
Key = item.Key,
|
||||
Value = item.Value,
|
||||
Value = DictionaryValueConverter.Deserialize(item.Value),
|
||||
IsDefault = item.IsDefault,
|
||||
IsEnabled = item.IsEnabled,
|
||||
SortOrder = item.SortOrder,
|
||||
Description = item.Description
|
||||
Description = item.Description,
|
||||
Source = item.TenantId == 0 ? "system" : "tenant",
|
||||
RowVersion = item.RowVersion
|
||||
};
|
||||
|
||||
private static bool IsConcurrencyException(Exception exception)
|
||||
=> string.Equals(exception.GetType().Name, "DbUpdateConcurrencyException", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user