AdoSmartOpsKpiDimensionConfigController.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using System.Security.Claims;
  2. using Admin.NET.Core;
  3. using Admin.NET.Plugin.AiDOP.Dto.SmartOps;
  4. using Admin.NET.Plugin.AiDOP.Entity;
  5. using Admin.NET.Plugin.AiDOP.SmartOps;
  6. using Microsoft.AspNetCore.Authorization;
  7. using Microsoft.AspNetCore.Mvc;
  8. using SqlSugar;
  9. namespace Admin.NET.Plugin.AiDOP.Controllers;
  10. /// <summary>
  11. /// KPI 维度计算配置(DIMENSION_SQL 配置化)接口。**要求登录**——SQL 编辑/发布是高危面。
  12. /// 租户由服务端按 moduleCode 解析;操作人取自 JWT。
  13. /// </summary>
  14. [ApiController]
  15. [Route("api/[controller]")]
  16. [Authorize]
  17. public class AdoSmartOpsKpiDimensionConfigController : ControllerBase
  18. {
  19. private readonly AdoSmartOpsKpiDimensionConfigService _service;
  20. private readonly ISqlSugarClient _db;
  21. public AdoSmartOpsKpiDimensionConfigController(AdoSmartOpsKpiDimensionConfigService service, ISqlSugarClient db)
  22. {
  23. _service = service;
  24. _db = db;
  25. }
  26. private string Operator() =>
  27. User?.FindFirstValue("RealName") ?? User?.FindFirstValue("Account") ?? User?.Identity?.Name ?? "unknown";
  28. /// <summary>某 KPI 的全部维度配置版本。</summary>
  29. [HttpGet("by-metric/{metricCode}")]
  30. public async Task<IActionResult> GetByMetric(string metricCode, [FromQuery] string moduleCode)
  31. {
  32. if (string.IsNullOrWhiteSpace(moduleCode))
  33. return BadRequest(new { message = "moduleCode 必填" });
  34. return Ok(await _service.GetByMetricAsync(metricCode, moduleCode));
  35. }
  36. /// <summary>已登记数据源列表。</summary>
  37. [HttpGet("data-sources")]
  38. public IActionResult DataSources() => Ok(_service.ListDataSources());
  39. /// <summary>KPI 维度能力(驱动前端筛选/下钻可用性)。</summary>
  40. [HttpGet("capability/{metricCode}")]
  41. public async Task<IActionResult> Capability(string metricCode, [FromQuery] string moduleCode)
  42. {
  43. if (string.IsNullOrWhiteSpace(moduleCode))
  44. return BadRequest(new { message = "moduleCode 必填" });
  45. return Ok(await _service.GetCapabilityAsync(metricCode, moduleCode));
  46. }
  47. /// <summary>新增草稿。</summary>
  48. [HttpPost]
  49. public async Task<IActionResult> Create([FromBody] KpiDimensionConfigUpsertDto dto)
  50. {
  51. if (string.IsNullOrWhiteSpace(dto.MetricCode) || string.IsNullOrWhiteSpace(dto.ModuleCode))
  52. return BadRequest(new { message = "metricCode / moduleCode 必填" });
  53. return Ok(await _service.CreateDraftAsync(dto, Operator()));
  54. }
  55. /// <summary>编辑草稿。</summary>
  56. [HttpPut("{id:long}")]
  57. public async Task<IActionResult> Update(long id, [FromBody] KpiDimensionConfigUpsertDto dto)
  58. {
  59. await _service.UpdateDraftAsync(id, dto, Operator());
  60. return Ok(new { ok = true });
  61. }
  62. /// <summary>删除草稿。</summary>
  63. [HttpDelete("{id:long}")]
  64. public async Task<IActionResult> Delete(long id)
  65. {
  66. await _service.DeleteAsync(id);
  67. return Ok(new { ok = true });
  68. }
  69. /// <summary>SQL 安全校验。</summary>
  70. [HttpPost("validate")]
  71. public IActionResult Validate([FromBody] KpiSqlValidateDto dto) => Ok(_service.Validate(dto.SqlScript));
  72. /// <summary>试算(不写维度结果;服务端重校验 + 只读多行执行)。</summary>
  73. [HttpPost("preview")]
  74. public async Task<IActionResult> Preview([FromBody] KpiDimensionPreviewDto dto, CancellationToken ct)
  75. {
  76. if (string.IsNullOrWhiteSpace(dto.MetricCode) || string.IsNullOrWhiteSpace(dto.ModuleCode))
  77. return BadRequest(new { message = "metricCode / moduleCode 必填" });
  78. return Ok(await _service.PreviewAsync(dto, ct));
  79. }
  80. /// <summary>发布(事务:单生效版本 + 绑定汇总版本一致性)。</summary>
  81. [HttpPost("{id:long}/publish")]
  82. public async Task<IActionResult> Publish(long id)
  83. {
  84. await _service.PublishAsync(id, Operator());
  85. return Ok(new { ok = true });
  86. }
  87. /// <summary>激活/回滚。</summary>
  88. [HttpPost("{id:long}/activate")]
  89. public async Task<IActionResult> Activate(long id)
  90. {
  91. await _service.ActivateAsync(id, Operator());
  92. return Ok(new { ok = true });
  93. }
  94. /// <summary>停用。</summary>
  95. [HttpPost("{id:long}/retire")]
  96. public async Task<IActionResult> Retire(long id)
  97. {
  98. await _service.RetireAsync(id, Operator());
  99. return Ok(new { ok = true });
  100. }
  101. /// <summary>某 KPI 的维度运行日志(分页,脱敏,租户后端解析)。</summary>
  102. [HttpGet("run-log/{metricCode}")]
  103. public async Task<IActionResult> RunLog(
  104. string metricCode, [FromQuery] string moduleCode,
  105. [FromQuery] int page = 1, [FromQuery] int pageSize = 20, [FromQuery] string? status = null)
  106. {
  107. if (string.IsNullOrWhiteSpace(metricCode) || string.IsNullOrWhiteSpace(moduleCode))
  108. return BadRequest(new { message = "metricCode / moduleCode 必填" });
  109. var tenantId = AdoSmartOpsKpiCalcConfigService.ResolveKpiTenantId(moduleCode);
  110. RefAsync<int> total = 0;
  111. var list = await _db.Queryable<AdoSmartOpsKpiDimensionRunLog>().ClearFilter<ITenantIdFilter>()
  112. .Where(x => x.MetricCode == metricCode && x.TenantId == tenantId)
  113. .WhereIF(!string.IsNullOrWhiteSpace(status), x => x.Status == status)
  114. .OrderBy(x => x.StartedAt, OrderByType.Desc)
  115. .ToPageListAsync(page <= 0 ? 1 : page, pageSize <= 0 ? 20 : pageSize, total);
  116. return Ok(new { list, total = total.Value });
  117. }
  118. }