diff --git a/src/Oms.Application/Dtos/Customers/CustomerPaginatedOutput.cs b/src/Oms.Application/Dtos/Customers/CustomerPaginatedOutput.cs
index 290f1d3..6ddc01a 100644
--- a/src/Oms.Application/Dtos/Customers/CustomerPaginatedOutput.cs
+++ b/src/Oms.Application/Dtos/Customers/CustomerPaginatedOutput.cs
@@ -102,8 +102,18 @@ public class CustomerPaginatedOutput
///
public DateTime CreateTime { get; set; }
+ ///
+ /// 创建人(展示名称)。
+ ///
+ public string? CreateBy { get; set; }
+
///
/// 更新时间。
///
public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 更新人(展示名称)。
+ ///
+ public string? UpdateBy { get; set; }
}
diff --git a/src/Oms.Application/Services/Channels/SalesProductService.Helpers.cs b/src/Oms.Application/Services/Channels/SalesProductService.Helpers.cs
index 18fcd22..272c38f 100644
--- a/src/Oms.Application/Services/Channels/SalesProductService.Helpers.cs
+++ b/src/Oms.Application/Services/Channels/SalesProductService.Helpers.cs
@@ -74,6 +74,9 @@ public partial class SalesProductService
.GroupBy(x => x.PriceId)
.ToDictionary(x => x.Key, x => x.OrderBy(item => item.Id).ToList());
+ var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync(
+ prices.SelectMany(x => new[] { x.CreateUserId, x.UpdateUserId }));
+
return prices.Select(price => new SalesProductPriceListOutput
{
Id = price.Id,
@@ -88,9 +91,9 @@ public partial class SalesProductService
Factors = factorMap.TryGetValue(price.Id, out var factors) ? factors.Select(MapPriceFactorOutput).ToList() : [],
Details = detailMap.TryGetValue(price.Id, out var details) ? details.Select(MapPriceDetailOutput).ToList() : [],
CreateTime = price.CreateTime,
- CreateBy = price.CreateUserId <= 0 ? null : price.CreateUserId.ToString(),
+ CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(price.CreateUserId, auditUserNameMap),
UpdateTime = OmsDocHelper.NullIfDefault(price.UpdateTime),
- UpdateBy = price.UpdateUserId <= 0 ? null : price.UpdateUserId.ToString()
+ UpdateBy = OmsRbacUserDisplayNameResolver.FormatUserId(price.UpdateUserId, auditUserNameMap)
}).ToList();
}
@@ -342,7 +345,9 @@ public partial class SalesProductService
};
}
- private static SalesProductDetailOutput MapDetailOutput(SalesProduct entity)
+ private static SalesProductDetailOutput MapDetailOutput(
+ SalesProduct entity,
+ IReadOnlyDictionary auditUserNameMap)
{
return new SalesProductDetailOutput
{
@@ -363,9 +368,9 @@ public partial class SalesProductService
IsActive = (byte)entity.IsActive,
Scheme = entity.Scheme,
CreateTime = entity.CreateTime,
- CreateBy = entity.CreateUserId <= 0 ? null : entity.CreateUserId.ToString(),
+ CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.CreateUserId, auditUserNameMap),
UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime),
- UpdateBy = entity.UpdateUserId <= 0 ? null : entity.UpdateUserId.ToString()
+ UpdateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.UpdateUserId, auditUserNameMap)
};
}
diff --git a/src/Oms.Application/Services/Channels/SalesProductService.cs b/src/Oms.Application/Services/Channels/SalesProductService.cs
index b6a023b..eb75bac 100644
--- a/src/Oms.Application/Services/Channels/SalesProductService.cs
+++ b/src/Oms.Application/Services/Channels/SalesProductService.cs
@@ -25,6 +25,8 @@ public partial class SalesProductService : ApplicationService
private IWeightRoundingRepository WeightRoundingRepository => LazyServiceProvider.GetRequiredService();
private AllocationProviderSnapshotEnricher AllocationProviderSnapshotEnricher =>
LazyServiceProvider.GetRequiredService();
+ private OmsRbacUserDisplayNameResolver UserDisplayNameResolver =>
+ LazyServiceProvider.GetRequiredService();
///
/// 查询销售产品列表。
@@ -71,7 +73,9 @@ public partial class SalesProductService : ApplicationService
public async Task GetDetailAsync([FromQuery] int id)
{
var entity = await GetProductOrThrowAsync(id);
- return MapDetailOutput(entity);
+ var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync(
+ [entity.CreateUserId, entity.UpdateUserId]);
+ return MapDetailOutput(entity, auditUserNameMap);
}
///
diff --git a/src/Oms.Application/Services/Channels/ServiceChannelService.Helpers.cs b/src/Oms.Application/Services/Channels/ServiceChannelService.Helpers.cs
index a6c1fab..d8d6500 100644
--- a/src/Oms.Application/Services/Channels/ServiceChannelService.Helpers.cs
+++ b/src/Oms.Application/Services/Channels/ServiceChannelService.Helpers.cs
@@ -329,7 +329,10 @@ public partial class ServiceChannelService
};
}
- private static ServiceChannelDetailOutput MapDetailOutput(ServiceChannel entity, IReadOnlyDictionary groupMap)
+ private static ServiceChannelDetailOutput MapDetailOutput(
+ ServiceChannel entity,
+ IReadOnlyDictionary groupMap,
+ IReadOnlyDictionary auditUserNameMap)
{
return new ServiceChannelDetailOutput
{
@@ -346,9 +349,9 @@ public partial class ServiceChannelService
PreScript = entity.PreScript,
IsActive = (byte)entity.IsActive,
CreateTime = entity.CreateTime,
- CreateBy = entity.CreateUserId <= 0 ? null : entity.CreateUserId.ToString(),
+ CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.CreateUserId, auditUserNameMap),
UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime),
- UpdateBy = entity.UpdateUserId <= 0 ? null : entity.UpdateUserId.ToString()
+ UpdateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.UpdateUserId, auditUserNameMap)
};
}
diff --git a/src/Oms.Application/Services/Channels/ServiceChannelService.cs b/src/Oms.Application/Services/Channels/ServiceChannelService.cs
index 5738ef1..6fe41cd 100644
--- a/src/Oms.Application/Services/Channels/ServiceChannelService.cs
+++ b/src/Oms.Application/Services/Channels/ServiceChannelService.cs
@@ -20,6 +20,8 @@ public partial class ServiceChannelService : ApplicationService
private IServiceChannelRepository ServiceChannelRepository => LazyServiceProvider.GetRequiredService();
private IServiceChannelGroupRepository ServiceChannelGroupRepository => LazyServiceProvider.GetRequiredService();
+ private OmsRbacUserDisplayNameResolver UserDisplayNameResolver =>
+ LazyServiceProvider.GetRequiredService();
///
/// 查询服务渠道列表。
@@ -67,7 +69,9 @@ public partial class ServiceChannelService : ApplicationService
public async Task GetDetailAsync([FromQuery] int id)
{
var entity = await GetEntityOrThrowAsync(id);
- return MapDetailOutput(entity, await GetGroupMapAsync());
+ var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync(
+ [entity.CreateUserId, entity.UpdateUserId]);
+ return MapDetailOutput(entity, await GetGroupMapAsync(), auditUserNameMap);
}
///
diff --git a/src/Oms.Application/Services/Customers/CustomerService.cs b/src/Oms.Application/Services/Customers/CustomerService.cs
index ad04976..960df8d 100644
--- a/src/Oms.Application/Services/Customers/CustomerService.cs
+++ b/src/Oms.Application/Services/Customers/CustomerService.cs
@@ -32,6 +32,9 @@ public class CustomerService : ApplicationService
private FakeRbacDbContext RbacDbContext => LazyServiceProvider.GetRequiredService();
+ private OmsRbacUserDisplayNameResolver UserDisplayNameResolver =>
+ LazyServiceProvider.GetRequiredService();
+
///
/// 查询客户列表。
///
@@ -57,7 +60,16 @@ public class CustomerService : ApplicationService
new Dictionary { [nameof(Customer.UpdateTime)] = false, [nameof(Customer.Id)] = false });
var totalCount = await CustomerRepository.CountAsync(predicate);
- var items = entities.Select(entity => ObjectMapper.Map(entity)).ToList();
+ var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync(
+ entities.SelectMany(x => new[] { x.CreateUserId, x.UpdateUserId }));
+ var items = entities.Select(entity =>
+ {
+ var output = ObjectMapper.Map(entity);
+ output.CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.CreateUserId, auditUserNameMap);
+ output.UpdateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.UpdateUserId, auditUserNameMap);
+ output.UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime);
+ return output;
+ }).ToList();
return new OmsPageResult
{
@@ -82,8 +94,10 @@ public class CustomerService : ApplicationService
{
var entity = await GetCustomerOrThrowAsync(id);
var output = ObjectMapper.Map(entity);
- output.CreateBy = entity.CreateUserId <= 0 ? null : entity.CreateUserId.ToString();
- output.UpdateBy = entity.UpdateUserId <= 0 ? null : entity.UpdateUserId.ToString();
+ var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync(
+ [entity.CreateUserId, entity.UpdateUserId]);
+ output.CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.CreateUserId, auditUserNameMap);
+ output.UpdateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.UpdateUserId, auditUserNameMap);
output.UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime);
return output;
}
diff --git a/src/Oms.Application/Services/Orders/OrderService.Helpers.cs b/src/Oms.Application/Services/Orders/OrderService.Helpers.cs
index 137f2e9..2bad69e 100644
--- a/src/Oms.Application/Services/Orders/OrderService.Helpers.cs
+++ b/src/Oms.Application/Services/Orders/OrderService.Helpers.cs
@@ -69,6 +69,9 @@ public partial class OrderService
: await CountryRepository.GetListAsync(x => countryCodes.Contains(x.CountryCode));
var countryMap = countries.ToDictionary(x => x.CountryCode, StringComparer.OrdinalIgnoreCase);
+ var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync(
+ orders.SelectMany(x => new[] { x.CreateUserId, x.UpdateUserId }));
+
return orders.Select(order =>
{
senderMap.TryGetValue(order.Id, out var sender);
@@ -127,9 +130,9 @@ public partial class OrderService
IsIntercept = order.IsIntercept > 0,
IsRemote = order.IsRemote > 0,
CreateTime = order.CreateTime,
- CreateBy = order.CreateUserId <= 0 ? null : order.CreateUserId.ToString(),
+ CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(order.CreateUserId, auditUserNameMap),
UpdateTime = OmsDocHelper.NullIfDefault(order.UpdateTime),
- UpdateBy = order.UpdateUserId <= 0 ? null : order.UpdateUserId.ToString(),
+ UpdateBy = OmsRbacUserDisplayNameResolver.FormatUserId(order.UpdateUserId, auditUserNameMap),
Sender = MapSender(sender),
Receiver = MapReceiver(recipient),
Items = (items ?? []).Select(MapDeclaration).ToList(),
diff --git a/src/Oms.Application/Services/Orders/OrderService.cs b/src/Oms.Application/Services/Orders/OrderService.cs
index ba469fa..9f8d548 100644
--- a/src/Oms.Application/Services/Orders/OrderService.cs
+++ b/src/Oms.Application/Services/Orders/OrderService.cs
@@ -28,6 +28,8 @@ public partial class OrderService : ApplicationService
private IWarehouseAddressRepository WarehouseAddressRepository => LazyServiceProvider.GetRequiredService();
private ISalesProductRepository SalesProductRepository => LazyServiceProvider.GetRequiredService();
private IWebHostEnvironment WebHostEnvironment => LazyServiceProvider.GetRequiredService();
+ private OmsRbacUserDisplayNameResolver UserDisplayNameResolver =>
+ LazyServiceProvider.GetRequiredService();
///
/// 查询订单列表。
diff --git a/src/Oms.Application/Services/System/WarehouseService.cs b/src/Oms.Application/Services/System/WarehouseService.cs
index eac127a..969501b 100644
--- a/src/Oms.Application/Services/System/WarehouseService.cs
+++ b/src/Oms.Application/Services/System/WarehouseService.cs
@@ -18,6 +18,9 @@ public class WarehouseService : ApplicationService
{
private IWarehouseAddressRepository WarehouseAddressRepository => LazyServiceProvider.GetRequiredService();
+ private OmsRbacUserDisplayNameResolver UserDisplayNameResolver =>
+ LazyServiceProvider.GetRequiredService();
+
///
/// 查询仓库列表。
///
@@ -74,8 +77,10 @@ public class WarehouseService : ApplicationService
{
var entity = await GetWarehouseOrThrowAsync(id);
var output = ObjectMapper.Map(entity);
- output.CreateBy = entity.CreateUserId <= 0 ? null : entity.CreateUserId.ToString();
- output.UpdateBy = entity.UpdateUserId <= 0 ? null : entity.UpdateUserId.ToString();
+ var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync(
+ [entity.CreateUserId, entity.UpdateUserId]);
+ output.CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.CreateUserId, auditUserNameMap);
+ output.UpdateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.UpdateUserId, auditUserNameMap);
output.UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime);
return output;
}
diff --git a/src/Oms.Application/Shared/OmsRbacUserDisplayNameResolver.cs b/src/Oms.Application/Shared/OmsRbacUserDisplayNameResolver.cs
new file mode 100644
index 0000000..8fe51d0
--- /dev/null
+++ b/src/Oms.Application/Shared/OmsRbacUserDisplayNameResolver.cs
@@ -0,0 +1,80 @@
+using Fake.DependencyInjection;
+using Fake.Rbac.Infrastructure;
+using Microsoft.EntityFrameworkCore;
+
+namespace Oms.Application.Shared;
+
+///
+/// 将 OMS 审计字段中的 RBAC mapId(user.userid)解析为展示名称。
+///
+public class OmsRbacUserDisplayNameResolver : IScopedDependency
+{
+ private readonly FakeRbacDbContext _rbacDbContext;
+
+ public OmsRbacUserDisplayNameResolver(FakeRbacDbContext rbacDbContext)
+ {
+ _rbacDbContext = rbacDbContext;
+ }
+
+ public async Task ResolveAsync(int userId, CancellationToken cancellationToken = default)
+ {
+ if (userId <= 0)
+ {
+ return null;
+ }
+
+ var map = await ResolveManyAsync([userId], cancellationToken);
+ return FormatUserId(userId, map);
+ }
+
+ public async Task> ResolveManyAsync(
+ IEnumerable userIds,
+ CancellationToken cancellationToken = default)
+ {
+ var ids = userIds.Where(x => x > 0).Distinct().ToList();
+ if (ids.Count == 0)
+ {
+ return new Dictionary();
+ }
+
+ var sql =
+ $"SELECT `userid` AS `{nameof(RbacUserNameRow.UserId)}`, `Name` AS `{nameof(RbacUserNameRow.DisplayName)}` FROM `user` WHERE `IsDeleted` = 0 AND `userid` IN ({string.Join(",", ids)})";
+ var rows = await _rbacDbContext.Database
+ .SqlQueryRaw(sql)
+ .ToListAsync(cancellationToken);
+
+ return rows.ToDictionary(
+ x => x.UserId,
+ x => NormalizeDisplayName(x.DisplayName, x.UserId));
+ }
+
+ public static string? FormatUserId(int userId, IReadOnlyDictionary? nameMap)
+ {
+ if (userId <= 0)
+ {
+ return null;
+ }
+
+ if (nameMap != null &&
+ nameMap.TryGetValue(userId, out var name) &&
+ !string.IsNullOrWhiteSpace(name))
+ {
+ return name;
+ }
+
+ return userId.ToString();
+ }
+
+ private static string NormalizeDisplayName(string? name, int userId)
+ {
+ var trimmed = name?.Trim();
+ return string.IsNullOrWhiteSpace(trimmed) ? userId.ToString() : trimmed;
+ }
+
+ private sealed class RbacUserNameRow
+ {
+ public int UserId { get; set; }
+
+ public string? DisplayName { get; set; }
+ }
+}