优化桌面端无用菜单和地磅数据可手动功能。
This commit is contained in:
@@ -121,6 +121,11 @@ namespace YY.Admin.Services
|
||||
/// 是否固定
|
||||
/// </summary>
|
||||
public bool IsAffix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 桌面端登录后作为默认首页打开的菜单
|
||||
/// </summary>
|
||||
public bool IsDefaultDesktopHome { get; set; }
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// 菜单子项
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user