持久层重构为独立 MiGu.DB 工程并优化集成

- 新增 MiGu.DB 项目,迁移所有领域实体与枚举,统一模型约定
- 实现 Entity/Repository/UoW/Provider/Exception 等接口与实现
- 支持数据修补机制,完善 Sqlite 初始迁移与数据库管理
- Server 侧移除 EF Core 相关,依赖 MiGu.DB,PlatformPersistence 适配
- 业务服务注入 UoW/Repository,状态字段统一用 enum 及辅助类
- 统一异常处理,Controller 映射 HTTP 状态码
- 配置项与文档补充数据库启动、SchemaMode、迁移说明
- 新增 GlobalUsings.Db.cs、WmsStatusAliases.cs 简化类型引用
- 新增 HttpActorContextMiddleware 支持操作者上下文一致性
- 新增 MiGuDbContextModelSnapshot 追踪数据库结构
- 优化代码结构,解耦领域与持久层,提升扩展性与安全性
This commit is contained in:
2026-07-27 14:26:04 +08:00
parent bdcd88608c
commit 51c3fc1994
57 changed files with 6663 additions and 1396 deletions
+19 -12
View File
@@ -13,11 +13,12 @@ public sealed class WmsTransportPlanner
public async Task<TransportCandidatePreview> PreviewAsync(WmsTransportRequest request)
{
if (!WmsTransportTriggerTypes.All.Contains(request.TriggerType))
if (!WmsTransportTriggerTypes.IsDefined(request.TriggerType))
throw new InvalidOperationException("触发类型无效");
var trigger = WmsTransportTriggerTypes.ParseOr(request.TriggerType);
var ctx = await BuildContextAsync();
var rules = await LoadRulesAsync(request);
var rules = await LoadRulesAsync(request, trigger);
var ruleResults = new List<RulePreviewResult>();
var candidates = new List<TransportCandidatePair>();
@@ -26,7 +27,7 @@ public sealed class WmsTransportPlanner
var sourceSelector = TransportSelectorParser.ParseSelector(rule.SourceSelectorJson);
var targetSelector = TransportSelectorParser.ParseSelector(rule.TargetSelectorJson);
var options = TransportSelectorParser.ParseTaskOptions(rule.TaskOptionsJson);
var ruleCandidates = BuildCandidates(ctx, request, rule, sourceSelector, targetSelector, options);
var ruleCandidates = BuildCandidates(ctx, request, trigger, rule, sourceSelector, targetSelector, options);
var rejectReasons = ruleCandidates.Count == 0
? new List<string> { "未找到满足条件的起点/终点组合" }
: new List<string>();
@@ -52,10 +53,10 @@ public sealed class WmsTransportPlanner
return preview.Candidates.FirstOrDefault();
}
private async Task<List<WmsTransportRule>> LoadRulesAsync(WmsTransportRequest request)
private async Task<List<WmsTransportRule>> LoadRulesAsync(WmsTransportRequest request, WmsTransportTriggerType trigger)
{
var query = _db.WmsTransportRules.AsNoTracking()
.Where(x => x.Enabled && x.TriggerType == request.TriggerType);
.Where(x => x.Enabled && x.TriggerType == trigger);
if (request.RuleId.HasValue)
query = query.Where(x => x.Id == request.RuleId.Value);
return await query.OrderByDescending(x => x.Priority).ThenBy(x => x.Code).ToListAsync();
@@ -94,17 +95,18 @@ public sealed class WmsTransportPlanner
private List<TransportCandidatePair> BuildCandidates(
PlannerContext ctx,
WmsTransportRequest request,
WmsTransportTriggerType trigger,
WmsTransportRule rule,
TransportSelector sourceSelector,
TransportSelector targetSelector,
TransportTaskOptions options)
{
var results = new List<TransportCandidatePair>();
var sources = BuildSourceCandidates(ctx, request, sourceSelector, options);
var sources = BuildSourceCandidates(ctx, request, trigger, sourceSelector, options);
foreach (var src in sources)
{
var targets = BuildTargetCandidates(ctx, request, targetSelector, options, src.StorageId);
var targets = BuildTargetCandidates(ctx, request, trigger, targetSelector, options, src.StorageId);
foreach (var tgt in targets)
{
var score = rule.Priority * 1000 + src.Score + tgt.Score;
@@ -124,6 +126,7 @@ public sealed class WmsTransportPlanner
private List<SourceCandidate> BuildSourceCandidates(
PlannerContext ctx,
WmsTransportRequest request,
WmsTransportTriggerType trigger,
TransportSelector selector,
TransportTaskOptions options)
{
@@ -145,7 +148,7 @@ public sealed class WmsTransportPlanner
continue;
if (request.RequestSiteId is { Length: > 0 } siteId &&
string.Equals(request.TriggerType, WmsTransportTriggerTypes.FinishedGoodsOffline, StringComparison.OrdinalIgnoreCase) &&
trigger == WmsTransportTriggerTypes.FinishedGoodsOffline &&
!string.Equals(storage.SiteId, siteId, StringComparison.OrdinalIgnoreCase))
continue;
@@ -162,6 +165,7 @@ public sealed class WmsTransportPlanner
private List<TargetCandidate> BuildTargetCandidates(
PlannerContext ctx,
WmsTransportRequest request,
WmsTransportTriggerType trigger,
TransportSelector selector,
TransportTaskOptions options,
Guid sourceStorageId)
@@ -176,7 +180,7 @@ public sealed class WmsTransportPlanner
if (ctx.ReservedTargetStorages.Contains(storage.Id)) continue;
if (request.RequestSiteId is { Length: > 0 } siteId &&
string.Equals(request.TriggerType, WmsTransportTriggerTypes.MaterialCall, StringComparison.OrdinalIgnoreCase) &&
trigger == WmsTransportTriggerTypes.MaterialCall &&
selector.Storage?.SiteIds is { Count: 0 } &&
!string.Equals(storage.SiteId, siteId, StringComparison.OrdinalIgnoreCase))
continue;
@@ -200,7 +204,8 @@ public sealed class WmsTransportPlanner
{
if (request.MaterialId.HasValue && row.MaterialId != request.MaterialId.Value) continue;
if (filter?.MaterialIds is { Count: > 0 } ids && !ids.Contains(row.MaterialId.ToString("D"))) continue;
if (filter?.StatusIn is { Count: > 0 } st && !st.Contains(row.Status, StringComparer.OrdinalIgnoreCase)) continue;
if (filter?.StatusIn is { Count: > 0 } st &&
!st.Contains(row.Status.ToString(), StringComparer.OrdinalIgnoreCase)) continue;
if (filter?.MinQuantity is { } min && row.Quantity < min) continue;
if (request.Quantity is { } reqQty && row.Quantity < reqQty) continue;
if (request.BatchNo is { Length: > 0 } batch && !string.Equals(row.BatchNo, batch, StringComparison.OrdinalIgnoreCase)) continue;
@@ -220,7 +225,8 @@ public sealed class WmsTransportPlanner
if (filter.AreaIds is { Count: > 0 } && !filter.AreaIds.Contains(storage.AreaId.ToString("D"))) return false;
if (filter.StorageTypes is { Count: > 0 } && !filter.StorageTypes.Contains(storage.StorageType, StringComparer.OrdinalIgnoreCase)) return false;
if (filter.ZoneCodes is { Count: > 0 } && !filter.ZoneCodes.Contains(storage.ZoneCode, StringComparer.OrdinalIgnoreCase)) return false;
if (filter.StatusIn is { Count: > 0 } && !filter.StatusIn.Contains(storage.Status, StringComparer.OrdinalIgnoreCase)) return false;
if (filter.StatusIn is { Count: > 0 } &&
!filter.StatusIn.Contains(storage.Status.ToString(), StringComparer.OrdinalIgnoreCase)) return false;
if (filter.SiteIds is { Count: > 0 } && !filter.SiteIds.Contains(storage.SiteId, StringComparer.OrdinalIgnoreCase)) return false;
if (filter.AllowInbound == true && !storage.AllowInbound) return false;
if (filter.AllowOutbound == true && !storage.AllowOutbound) return false;
@@ -236,7 +242,8 @@ public sealed class WmsTransportPlanner
{
if (filter == null) return true;
if (filter.ContainerTypes is { Count: > 0 } && !filter.ContainerTypes.Contains(container.ContainerType, StringComparer.OrdinalIgnoreCase)) return false;
if (filter.StatusIn is { Count: > 0 } && !filter.StatusIn.Contains(container.Status, StringComparer.OrdinalIgnoreCase)) return false;
if (filter.StatusIn is { Count: > 0 } &&
!filter.StatusIn.Contains(container.Status.ToString(), StringComparer.OrdinalIgnoreCase)) return false;
if (filter.ExcludeReserved &&
(ctx.ReservedContainers.Contains(container.Id) || ctx.TaskReservedContainers.Contains(container.Id)))
return false;