优化桌面端无用菜单和地磅数据可手动功能。

This commit is contained in:
geht
2026-05-18 15:55:11 +08:00
parent 5800b6b61c
commit c11f3104cb
18 changed files with 628 additions and 118 deletions

View File

@@ -121,6 +121,11 @@ namespace YY.Admin.Services
/// 是否固定
/// </summary>
public bool IsAffix { get; set; }
/// <summary>
/// 桌面端登录后作为默认首页打开的菜单
/// </summary>
public bool IsDefaultDesktopHome { get; set; }
#endregion
/// <summary>
/// 菜单子项

View File

@@ -157,6 +157,9 @@ namespace YY.Admin.Services.Service.Menu
if (n <= 0)
return (false, "保存失败", 0);
if (input.IsDefaultDesktopHome)
await ClearDefaultDesktopHomeExceptAsync(input.Id);
await TryLinkCurrentTenantMenuAsync(id);
return (true, "保存成功", id);
}
@@ -180,6 +183,9 @@ namespace YY.Admin.Services.Service.Menu
if (NewParentIsInsideMenuSubtree(input.Id, input.Pid, all))
return (false, "不能将父级设为当前菜单或其子菜单");
if (input.IsDefaultDesktopHome)
await ClearDefaultDesktopHomeExceptAsync(input.Id);
existing.Pid = input.Pid;
existing.Type = input.Type;
existing.Name = input.Name;
@@ -194,13 +200,17 @@ namespace YY.Admin.Services.Service.Menu
existing.IsHide = input.IsHide;
existing.IsKeepAlive = input.IsKeepAlive;
existing.IsAffix = input.IsAffix;
existing.IsDefaultDesktopHome = input.IsDefaultDesktopHome;
existing.OrderNo = input.OrderNo;
existing.Status = input.Status;
existing.Remark = input.Remark;
existing.UpdateTime = DateTime.Now;
var n = await _dbContext.Updateable(existing).ExecuteCommandAsync();
return n > 0 ? (true, "保存成功") : (false, "更新失败");
if (n <= 0)
return (false, "更新失败");
await TryLinkCurrentTenantMenuAsync(input.Id);
return (true, "保存成功");
}
/// <inheritdoc />
@@ -219,6 +229,17 @@ namespace YY.Admin.Services.Service.Menu
return n > 0 ? (true, "已删除") : (false, "删除失败");
}
/// <summary>
/// 保证全表仅一条菜单为桌面默认首页(当前保留项除外全部置 false
/// </summary>
private async Task ClearDefaultDesktopHomeExceptAsync(long keepMenuId)
{
await _dbContext.Updateable<SysMenu>()
.SetColumns(m => new SysMenu { IsDefaultDesktopHome = false })
.Where(m => m.Id != keepMenuId && m.IsDefaultDesktopHome)
.ExecuteCommandAsync();
}
private async Task TryLinkCurrentTenantMenuAsync(long menuId)
{
var tenantId = AppSession.CurrentUser?.TenantId;

View File

@@ -10,8 +10,7 @@ using YY.Admin.Core.Services;
namespace YY.Admin.Services.Service.Warehouse;
/// <summary>
/// 仓库数据只读服务:启动时从后端拉取全量列表并缓存到磁盘,断网时回退本地缓存
/// 仅供其他模块的下拉筛选使用,不提供 CRUD。
/// 仓库数据只读服务:启动与重连时后台刷新远端写入缓存GetAllAsync 优先读缓存,避免库区等业务每次打开都全量拉仓库
/// </summary>
public class WarehouseService : IWarehouseService, ISingletonDependency
{
@@ -20,6 +19,7 @@ public class WarehouseService : IWarehouseService, ISingletonDependency
private readonly INetworkMonitor _networkMonitor;
private readonly ILoggerService _logger;
private readonly object _cacheLock = new();
private readonly SemaphoreSlim _emptyLoadGate = new(1, 1);
private readonly string _cacheFilePath;
private List<MesXslWarehouse> _localCache = new();
@@ -64,19 +64,44 @@ public class WarehouseService : IWarehouseService, ISingletonDependency
public async Task<List<MesXslWarehouse>> GetAllAsync(CancellationToken ct = default)
{
if (_networkMonitor.IsOnline)
lock (_cacheLock)
{
if (_localCache.Count > 0 || !_networkMonitor.IsOnline)
return _localCache.ToList();
}
// 缓存为空且在线:仅此时阻塞拉远端(首次安装或清缓存后)
await _emptyLoadGate.WaitAsync(ct).ConfigureAwait(false);
try
{
lock (_cacheLock)
{
if (_localCache.Count > 0)
return _localCache.ToList();
}
if (!_networkMonitor.IsOnline)
{
lock (_cacheLock)
return _localCache.ToList();
}
try
{
await RefreshFromRemoteAsync(ct).ConfigureAwait(false);
}
catch { }
catch
{
/* 登录前拉取失败等场景,仍返回当前缓存(可能仍为空) */
}
}
finally
{
_emptyLoadGate.Release();
}
lock (_cacheLock)
{
return _localCache.ToList();
}
}
private async Task RefreshFromRemoteAsync(CancellationToken ct)

View File

@@ -197,12 +197,12 @@ public class WeightRecordService : IWeightRecordService, ISingletonDependency
public async Task<bool> AddAsync(MesXslWeightRecord entity, CancellationToken ct = default)
{
SanitizeWeightsBeforePersist(entity);
if (!entity.TenantId.HasValue || entity.TenantId.Value <= 0)
entity.TenantId = DefaultTenantId;
if (string.IsNullOrWhiteSpace(entity.BillNo))
entity.BillNo = GenerateBillNo();
if (string.IsNullOrWhiteSpace(entity.BillType))
entity.BillType = ResolveBillType(entity);
entity.BillType = ResolveBillType(entity);
var local = Clone(entity);
if (string.IsNullOrWhiteSpace(local.Id))
@@ -246,21 +246,41 @@ public class WeightRecordService : IWeightRecordService, ISingletonDependency
/// <summary>
/// 根据称重数据推导单据类型:仅毛重=已称毛重;仅皮重=已称皮重;毛重+皮重=称重完成。
/// 注意:皮重/毛重为 0 时按「未称」处理(避免 NumericUpDown/JSON 占位 0 误判为称重完成)。
/// </summary>
private static string? ResolveBillType(MesXslWeightRecord entity)
{
if (entity.GrossWeight.HasValue && entity.TareWeight.HasValue) return "2";
if (entity.GrossWeight.HasValue) return "1";
if (entity.TareWeight.HasValue) return "3";
var g = HasEffectiveWeighKg(entity.GrossWeight);
var t = HasEffectiveWeighKg(entity.TareWeight);
if (g && t) return "2";
if (g) return "1";
if (t) return "3";
return null;
}
private static bool HasEffectiveWeighKg(double? kg) => kg.HasValue && kg.Value > 0;
/// <summary>
/// 将 ≤0 的重量视为未录入并清空净重,防止上传 payload 带 0 误判。
/// </summary>
private static void SanitizeWeightsBeforePersist(MesXslWeightRecord entity)
{
if (entity.GrossWeight.HasValue && entity.GrossWeight.Value <= 0)
entity.GrossWeight = null;
if (entity.TareWeight.HasValue && entity.TareWeight.Value <= 0)
entity.TareWeight = null;
if (HasEffectiveWeighKg(entity.GrossWeight) && HasEffectiveWeighKg(entity.TareWeight))
entity.NetWeight = Math.Round(entity.GrossWeight!.Value - entity.TareWeight!.Value, 2);
else
entity.NetWeight = null;
}
public async Task<bool> EditAsync(MesXslWeightRecord entity, CancellationToken ct = default)
{
SanitizeWeightsBeforePersist(entity);
if (!entity.TenantId.HasValue || entity.TenantId.Value <= 0)
entity.TenantId = DefaultTenantId;
if (string.IsNullOrWhiteSpace(entity.BillType))
entity.BillType = ResolveBillType(entity);
entity.BillType = ResolveBillType(entity);
var local = Clone(entity);
if (IsLocalTempId(local.Id))