AidopKanbanController.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. using Admin.NET.Plugin.AiDOP.Entity;
  2. using SqlSugar;
  3. namespace Admin.NET.Plugin.AiDOP.Controllers;
  4. [ApiController]
  5. [Route("api/[controller]")]
  6. [AllowAnonymous]
  7. [NonUnify]
  8. public class AidopKanbanController : ControllerBase
  9. {
  10. private readonly ISqlSugarClient _db;
  11. public AidopKanbanController(ISqlSugarClient db)
  12. {
  13. _db = db;
  14. }
  15. [HttpGet("home-l1")]
  16. public async Task<IActionResult> GetHomeL1([FromQuery] long tenantId = 1, [FromQuery] long factoryId = 1)
  17. {
  18. const string sql = """
  19. SELECT module_code AS ModuleCode, metric_code AS MetricCode, metric_value AS MetricValue,
  20. target_value AS TargetValue, status_color AS StatusColor, trend_flag AS TrendFlag
  21. FROM ado_s9_kpi_value_l1_day
  22. WHERE tenant_id=@tenantId AND factory_id=@factoryId AND is_deleted=0
  23. ORDER BY module_code
  24. """;
  25. var rows = await _db.Ado.SqlQueryAsync<HomeL1Dto>(sql, new { tenantId, factoryId });
  26. return Ok(rows);
  27. }
  28. [HttpGet("s8-alerts")]
  29. public async Task<IActionResult> GetS8Alerts([FromQuery] long tenantId = 1, [FromQuery] long factoryId = 1)
  30. {
  31. const string sql = """
  32. SELECT DATE_FORMAT(alert_time, '%H:%i') AS Time,
  33. IFNULL(SUBSTRING_INDEX(metric_code, '_', 1), 'S8') AS Module,
  34. IFNULL(message, '异常告警') AS Message,
  35. IFNULL(level_code, 'medium') AS LevelCode
  36. FROM ado_s8_alert_record
  37. WHERE tenant_id=@tenantId AND factory_id=@factoryId AND is_deleted=0
  38. ORDER BY alert_time DESC
  39. LIMIT 6
  40. """;
  41. var rows = await _db.Ado.SqlQueryAsync<S8AlertDto>(sql, new { tenantId, factoryId });
  42. return Ok(rows.Select(x => new
  43. {
  44. time = x.Time,
  45. module = x.Module,
  46. message = x.Message,
  47. level = x.LevelCode,
  48. levelLabel = x.LevelCode switch
  49. {
  50. "critical" => "严重",
  51. "high" => "高",
  52. "medium" => "中",
  53. _ => "一般"
  54. }
  55. }));
  56. }
  57. [HttpGet("module-detail")]
  58. public async Task<IActionResult> GetModuleDetail([FromQuery] string moduleCode = "S1", [FromQuery] long tenantId = 1, [FromQuery] long factoryId = 1)
  59. {
  60. moduleCode = string.IsNullOrWhiteSpace(moduleCode) ? "S1" : moduleCode.ToUpperInvariant();
  61. const string l2Sql = """
  62. SELECT module_code AS ModuleCode, metric_code AS MetricCode, metric_code AS MetricName, metric_value AS MetricValue,
  63. target_value AS TargetValue, status_color AS StatusColor, trend_flag AS TrendFlag, NULL AS StatDate
  64. FROM ado_s9_kpi_value_l2_day
  65. WHERE tenant_id=@tenantId AND factory_id=@factoryId AND is_deleted=0 AND module_code=@moduleCode
  66. ORDER BY id DESC, metric_code
  67. LIMIT 30
  68. """;
  69. const string l3Sql = """
  70. SELECT module_code AS ModuleCode, metric_code AS MetricCode, metric_code AS MetricName, metric_value AS MetricValue,
  71. target_value AS TargetValue, status_color AS StatusColor, trend_flag AS TrendFlag, NULL AS StatDate
  72. FROM ado_s9_kpi_value_l3_day
  73. WHERE tenant_id=@tenantId AND factory_id=@factoryId AND is_deleted=0 AND module_code=@moduleCode
  74. ORDER BY id DESC, metric_code
  75. LIMIT 60
  76. """;
  77. const string alertSql = """
  78. SELECT DATE_FORMAT(alert_time, '%H:%i:%s') AS Time,
  79. IFNULL(level_code, 'medium') AS LevelCode,
  80. IFNULL(message, '异常告警') AS Message
  81. FROM ado_s8_alert_record
  82. WHERE tenant_id=@tenantId AND factory_id=@factoryId AND is_deleted=0
  83. AND (UPPER(IFNULL(module_code,''))=@moduleCode OR UPPER(IFNULL(SUBSTRING_INDEX(metric_code, '_', 1), ''))=@moduleCode)
  84. ORDER BY alert_time DESC
  85. LIMIT 20
  86. """;
  87. const string l2FallbackSql = """
  88. SELECT '' AS ModuleCode, metric_code AS MetricCode, metric_code AS MetricName, metric_value AS MetricValue,
  89. target_value AS TargetValue, status_color AS StatusColor, trend_flag AS TrendFlag, NULL AS StatDate
  90. FROM ado_s9_kpi_value_l2_day
  91. WHERE tenant_id=@tenantId AND factory_id=@factoryId AND is_deleted=0
  92. ORDER BY id DESC
  93. LIMIT 30
  94. """;
  95. const string l3FallbackSql = """
  96. SELECT '' AS ModuleCode, metric_code AS MetricCode, metric_code AS MetricName, metric_value AS MetricValue,
  97. target_value AS TargetValue, status_color AS StatusColor, trend_flag AS TrendFlag, NULL AS StatDate
  98. FROM ado_s9_kpi_value_l3_day
  99. WHERE tenant_id=@tenantId AND factory_id=@factoryId AND is_deleted=0
  100. ORDER BY id DESC
  101. LIMIT 60
  102. """;
  103. var l2 = new List<KpiDetailDto>();
  104. var l3 = new List<KpiDetailDto>();
  105. var alerts = new List<S8AlertDto>();
  106. try { l2 = await _db.Ado.SqlQueryAsync<KpiDetailDto>(l2Sql, new { moduleCode, tenantId, factoryId }); }
  107. catch { l2 = await _db.Ado.SqlQueryAsync<KpiDetailDto>(l2FallbackSql, new { tenantId, factoryId }); }
  108. try { l3 = await _db.Ado.SqlQueryAsync<KpiDetailDto>(l3Sql, new { moduleCode, tenantId, factoryId }); }
  109. catch { l3 = await _db.Ado.SqlQueryAsync<KpiDetailDto>(l3FallbackSql, new { tenantId, factoryId }); }
  110. try { alerts = await _db.Ado.SqlQueryAsync<S8AlertDto>(alertSql, new { moduleCode, tenantId, factoryId }); }
  111. catch { alerts = new List<S8AlertDto>(); }
  112. return Ok(new
  113. {
  114. moduleCode,
  115. l2,
  116. l3,
  117. alerts = alerts.Select(x => new
  118. {
  119. time = x.Time,
  120. message = x.Message,
  121. level = x.LevelCode
  122. })
  123. });
  124. }
  125. /// <summary>
  126. /// 智慧运营看板基础查询下拉:产品、订单号、产线(来自 Demo 业务表;无租户列时忽略 tenant/factory)。
  127. /// </summary>
  128. [HttpGet("smart-ops-filter-options")]
  129. public async Task<IActionResult> GetSmartOpsFilterOptions([FromQuery] long tenantId = 1, [FromQuery] long factoryId = 1)
  130. {
  131. _ = tenantId;
  132. _ = factoryId;
  133. var products = new HashSet<string>(StringComparer.Ordinal);
  134. var orderNos = new HashSet<string>(StringComparer.Ordinal);
  135. var lines = new HashSet<string>(StringComparer.Ordinal);
  136. try
  137. {
  138. var op = await _db.Queryable<AdoOrder>()
  139. .Where(x => x.Product != null && x.Product != "")
  140. .Select(x => x.Product)
  141. .Distinct()
  142. .ToListAsync();
  143. foreach (var s in op.Where(s => !string.IsNullOrWhiteSpace(s)))
  144. products.Add(s.Trim());
  145. }
  146. catch
  147. {
  148. // ignored
  149. }
  150. try
  151. {
  152. var on = await _db.Queryable<AdoOrder>()
  153. .Where(x => x.OrderNo != null && x.OrderNo != "")
  154. .Select(x => x.OrderNo)
  155. .Distinct()
  156. .ToListAsync();
  157. foreach (var s in on.Where(s => !string.IsNullOrWhiteSpace(s)))
  158. orderNos.Add(s.Trim());
  159. }
  160. catch
  161. {
  162. // ignored
  163. }
  164. try
  165. {
  166. var woP = await _db.Queryable<AdoWorkOrder>()
  167. .Where(x => x.Product != null && x.Product != "")
  168. .Select(x => x.Product)
  169. .Distinct()
  170. .ToListAsync();
  171. foreach (var s in woP.Where(s => !string.IsNullOrWhiteSpace(s)))
  172. products.Add(s.Trim());
  173. var wc = await _db.Queryable<AdoWorkOrder>()
  174. .Where(x => x.WorkCenter != null && x.WorkCenter != "")
  175. .Select(x => x.WorkCenter)
  176. .Distinct()
  177. .ToListAsync();
  178. foreach (var s in wc.Where(s => !string.IsNullOrWhiteSpace(s)))
  179. lines.Add(s.Trim());
  180. }
  181. catch
  182. {
  183. // ignored
  184. }
  185. try
  186. {
  187. var pn = await _db.Queryable<AdoPlan>()
  188. .Where(x => x.ProductName != null && x.ProductName != "")
  189. .Select(x => x.ProductName)
  190. .Distinct()
  191. .ToListAsync();
  192. foreach (var s in pn.Where(s => !string.IsNullOrWhiteSpace(s)))
  193. products.Add(s.Trim());
  194. }
  195. catch
  196. {
  197. // ignored
  198. }
  199. return Ok(new
  200. {
  201. products = products.OrderBy(x => x, StringComparer.Ordinal).ToList(),
  202. orderNos = orderNos.OrderBy(x => x, StringComparer.Ordinal).ToList(),
  203. productionLines = lines.OrderBy(x => x, StringComparer.Ordinal).ToList()
  204. });
  205. }
  206. private sealed class HomeL1Dto
  207. {
  208. public string? ModuleCode { get; set; }
  209. public string? MetricCode { get; set; }
  210. public decimal? MetricValue { get; set; }
  211. public decimal? TargetValue { get; set; }
  212. public string? StatusColor { get; set; }
  213. public string? TrendFlag { get; set; }
  214. }
  215. private sealed class S8AlertDto
  216. {
  217. public string? Time { get; set; }
  218. public string? Module { get; set; }
  219. public string? Message { get; set; }
  220. public string? LevelCode { get; set; }
  221. }
  222. private sealed class KpiDetailDto
  223. {
  224. public string? ModuleCode { get; set; }
  225. public string? MetricCode { get; set; }
  226. public string? MetricName { get; set; }
  227. public decimal? MetricValue { get; set; }
  228. public decimal? TargetValue { get; set; }
  229. public string? StatusColor { get; set; }
  230. public string? TrendFlag { get; set; }
  231. public DateTime? StatDate { get; set; }
  232. }
  233. }