using Admin.NET.Plugin.AiDOP.Entity;
using Admin.NET.Plugin.AiDOP.Infrastructure;
using SqlSugar;
namespace Admin.NET.Plugin.AiDOP.Controllers;
public partial class AidopKanbanController
{
// S4.cs 中的 FormatGapLabel / ResolveMaxBizDateAsync 是 private,在同一 partial 类里可直接复用
///
/// 通用运营布局(L1/L2/L3)。moduleCode 指定模块;S4 也可走这个端点。
///
[HttpGet("operation-layout/{moduleCode}")]
public async Task GetOperationLayoutGeneric(string moduleCode, [FromQuery] long factoryId = 1)
{
var mc = (moduleCode ?? "").ToUpperInvariant();
if (string.IsNullOrWhiteSpace(mc)) return BadRequest(new { message = "moduleCode 必填" });
var tenantId = AidopTenantHelper.GetTenantId(HttpContext);
var hm = (await _db.Queryable()
.Where(x => x.TenantId == tenantId && x.FactoryId == factoryId && x.ModuleCode == mc)
.ToListAsync()).FirstOrDefault();
var items = await _db.Queryable()
.Where(x => x.TenantId == tenantId && x.FactoryId == factoryId && x.ModuleCode == mc && x.IsEnabled == 1)
.OrderBy(x => x.SortNo)
.ToListAsync();
var kpi = await _db.Queryable()
.Where(x => x.TenantId == tenantId && x.ModuleCode == mc)
.ToListAsync();
var kpiByCode = kpi.ToDictionary(x => x.MetricCode, StringComparer.OrdinalIgnoreCase);
object Row(AdoSmartOpsLayoutItem r)
{
kpiByCode.TryGetValue(r.MetricCode, out var k);
return new
{
rowId = r.RowId,
metricCode = r.MetricCode,
metricLevel = r.MetricLevel,
displayName = string.IsNullOrWhiteSpace(r.DisplayName) ? k?.MetricName : r.DisplayName,
sortNo = r.SortNo,
parentRowId = r.ParentRowId,
formulaText = r.FormulaText,
panelZone = r.PanelZone,
unit = k?.Unit,
direction = k?.Direction
};
}
return Ok(new
{
moduleCode = mc,
layoutPattern = hm?.LayoutPattern ?? "card_grid",
l1 = items.Where(x => x.MetricLevel == 1).Select(Row).ToList(),
l2 = items.Where(x => x.MetricLevel >= 2).Select(Row).ToList()
});
}
///
/// 通用九宫格/首页(L1 合并日表)。moduleCode 指定模块。
///
[HttpGet("home-grid/{moduleCode}")]
public async Task GetHomeGridGeneric(string moduleCode, [FromQuery] long factoryId = 1)
{
var mc = (moduleCode ?? "").ToUpperInvariant();
if (string.IsNullOrWhiteSpace(mc)) return BadRequest(new { message = "moduleCode 必填" });
var tenantId = AidopTenantHelper.GetTenantId(HttpContext);
var layout = await _db.Queryable()
.Where(x => x.TenantId == tenantId && x.FactoryId == factoryId && x.ModuleCode == mc && x.IsEnabled == 1 && x.MetricLevel == 1)
.OrderBy(x => x.SortNo)
.ToListAsync();
var kpi = await _db.Queryable()
.Where(x => x.TenantId == tenantId && x.ModuleCode == mc)
.ToListAsync();
var kpiBy = kpi.ToDictionary(x => x.MetricCode, StringComparer.OrdinalIgnoreCase);
var bizDate = await ResolveMaxBizDateGenericAsync("ado_s9_kpi_value_l1_day", tenantId, factoryId, mc);
const string valSql = """
SELECT metric_code AS MetricCode, metric_value AS MetricValue, target_value AS TargetValue
FROM ado_s9_kpi_value_l1_day
WHERE tenant_id=@t AND factory_id=@f AND module_code=@m AND is_deleted=0 AND biz_date=@d
""";
var vals = await _db.Ado.SqlQueryAsync(valSql, new { t = tenantId, f = factoryId, m = mc, d = bizDate });
var valBy = vals.ToDictionary(x => x.MetricCode ?? "", StringComparer.OrdinalIgnoreCase);
var hm = (await _db.Queryable()
.Where(x => x.TenantId == tenantId && x.FactoryId == factoryId && x.ModuleCode == mc)
.ToListAsync()).FirstOrDefault();
var items = new List