胶料快检添加离线模式

This commit is contained in:
2026-06-30 11:28:04 +08:00
parent efcd73a565
commit 840e68a450
19 changed files with 1053 additions and 343 deletions

View File

@@ -54,35 +54,20 @@ public class RubberQuickTestStdService : IRubberQuickTestStdService, ISingletonD
LoadCacheFromDisk();
_logger.Information($"[快检实验标准] 服务初始化,缓存={_localCache.Count},在线={_networkMonitor.IsOnline}");
_networkMonitor.StatusChanged += OnNetworkStatusChanged;
if (_networkMonitor.IsOnline)
_ = Task.Run(() => SyncFromRemoteAsync(CancellationToken.None));
}
private string BaseUrl => (_configuration.GetValue<string>("JeecgIntegration:BaseUrl") ?? "http://localhost:8080/jeecg-boot").TrimEnd('/');
private int DefaultTenantId => (int?)_configuration.GetValue<long?>("JeecgIntegration:DefaultTenantId") ?? 1002;
private HttpClient CreateClient() => _httpClientFactory.CreateClient("JeecgApi");
public async Task<RubberQuickTestStdPageResult> PageAsync(
public Task<RubberQuickTestStdPageResult> PageAsync(
int pageNo, int pageSize,
string? stdName = null,
string? rubberMaterialName = null,
string? enableStatus = null,
CancellationToken ct = default)
{
if (_networkMonitor.IsOnline)
{
try
{
await SyncFromRemoteAsync(ct).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.Warning($"[快检实验标准] 列表拉取失败,使用本地缓存:{ex.Message}");
}
}
ct.ThrowIfCancellationRequested();
List<MesXslRubberQuickTestStd> source;
lock (_cacheLock)
source = _localCache.Select(CloneMain).ToList();
@@ -93,7 +78,7 @@ public class RubberQuickTestStdService : IRubberQuickTestStdService, ISingletonD
.Skip(Math.Max(0, (pageNo - 1) * pageSize))
.Take(pageSize)
.ToList();
return new RubberQuickTestStdPageResult(records, total, pageNo, pageSize);
return Task.FromResult(new RubberQuickTestStdPageResult(records, total, pageNo, pageSize));
}
public async Task<MesXslRubberQuickTestStd?> GetByIdAsync(string id, CancellationToken ct = default)
@@ -199,6 +184,8 @@ public class RubberQuickTestStdService : IRubberQuickTestStdService, ISingletonD
lock (_cacheLock)
localSnapshot = _localCache.Select(CloneMain).ToList();
await HydrateStdLinesAsync(records, localSnapshot, ct).ConfigureAwait(false);
var (merged, stats) = MesReadOnlyCacheMergeHelper.Merge(
localSnapshot,
records,
@@ -233,18 +220,76 @@ public class RubberQuickTestStdService : IRubberQuickTestStdService, ISingletonD
}
}
private void OnNetworkStatusChanged(bool isOnline)
private async Task HydrateStdLinesAsync(
List<MesXslRubberQuickTestStd> remoteRecords,
List<MesXslRubberQuickTestStd> localSnapshot,
CancellationToken ct)
{
if (!isOnline) return;
_ = Task.Run(async () =>
{
if (!await SyncFromRemoteAsync(CancellationToken.None).ConfigureAwait(false))
return;
_eventAggregator.GetEvent<RubberQuickTestStdChangedEvent>()
.Publish(new RubberQuickTestStdChangedPayload { Action = "reconnect" });
});
var localById = localSnapshot
.Where(x => !string.IsNullOrWhiteSpace(x.Id))
.ToDictionary(x => x.Id!, StringComparer.OrdinalIgnoreCase);
using var gate = new SemaphoreSlim(8);
var tasks = remoteRecords
.Where(r => !string.IsNullOrWhiteSpace(r.Id))
.Select(async record =>
{
await gate.WaitAsync(ct).ConfigureAwait(false);
try
{
localById.TryGetValue(record.Id!, out var local);
if (local != null
&& IsStdListContentEqual(record, local)
&& local.LineList is { Count: > 0 })
{
record.LineList = local.LineList.Select(CloneStdLine).ToList();
return;
}
var lines = await FetchLinesByStdIdAsync(record.Id!, ct).ConfigureAwait(false);
record.LineList = lines.Count > 0
? lines
: local?.LineList?.Select(CloneStdLine).ToList();
}
finally
{
gate.Release();
}
});
await Task.WhenAll(tasks).ConfigureAwait(false);
}
private async Task<List<MesXslRubberQuickTestStdLine>> FetchLinesByStdIdAsync(string stdId, CancellationToken ct)
{
var url = $"{BaseUrl}/xslmes/mesXslRubberQuickTestStd/anon/queryLineListByStdId?id={Uri.EscapeDataString(stdId)}";
using var client = CreateClient();
using var resp = await client.GetAsync(url, ct).ConfigureAwait(false);
if (!resp.IsSuccessStatusCode)
return [];
var json = await resp.Content.ReadAsStringAsync(ct).ConfigureAwait(false);
using var doc = JsonDocument.Parse(json);
if (!doc.RootElement.TryGetProperty("result", out var resultEl))
return [];
return resultEl.Deserialize<List<MesXslRubberQuickTestStdLine>>(_jsonOpts) ?? [];
}
private static MesXslRubberQuickTestStdLine CloneStdLine(MesXslRubberQuickTestStdLine l) => new()
{
Id = l.Id,
StdId = l.StdId,
DataPointId = l.DataPointId,
PointName = l.PointName,
LowerLimit = l.LowerLimit,
UpperLimit = l.UpperLimit,
LowerWarn = l.LowerWarn,
UpperWarn = l.UpperWarn,
TargetValue = l.TargetValue,
SortNo = l.SortNo
};
private static List<MesXslRubberQuickTestStd> ApplyFilters(
List<MesXslRubberQuickTestStd> source,
string? stdName,