using System.Security.Claims; using Admin.NET.Plugin.AiDOP.Dto.SmartOps; using Admin.NET.Plugin.AiDOP.SmartOps; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace Admin.NET.Plugin.AiDOP.Controllers; /// /// KPI 计算配置(SQL 配置化)接口。**要求登录**(区别于其它 AiDOP 匿名接口)——SQL 编辑/发布是高危面。 /// tenant/权限不信任前端:租户由服务端按 moduleCode 解析;操作人取自 JWT。 /// [ApiController] [Route("api/[controller]")] [Authorize] public class AdoSmartOpsKpiCalcConfigController : ControllerBase { private readonly AdoSmartOpsKpiCalcConfigService _service; public AdoSmartOpsKpiCalcConfigController(AdoSmartOpsKpiCalcConfigService service) { _service = service; } private string Operator() => User?.FindFirstValue("RealName") ?? User?.FindFirstValue("Account") ?? User?.Identity?.Name ?? "unknown"; /// 某 KPI 的全部配置版本。 [HttpGet("by-metric/{metricCode}")] public async Task GetByMetric(string metricCode, [FromQuery] string moduleCode) { if (string.IsNullOrWhiteSpace(moduleCode)) return BadRequest(new { message = "moduleCode 必填" }); var list = await _service.GetByMetricAsync(metricCode, moduleCode); return Ok(list); } /// 已登记数据源列表。 [HttpGet("data-sources")] public IActionResult DataSources() => Ok(_service.ListDataSources()); /// 新增草稿。 [HttpPost] public async Task Create([FromBody] KpiCalcConfigUpsertDto dto) { if (string.IsNullOrWhiteSpace(dto.MetricCode) || string.IsNullOrWhiteSpace(dto.ModuleCode)) return BadRequest(new { message = "metricCode / moduleCode 必填" }); var created = await _service.CreateDraftAsync(dto, Operator()); return Ok(created); } /// 编辑草稿。 [HttpPut("{id:long}")] public async Task Update(long id, [FromBody] KpiCalcConfigUpsertDto dto) { await _service.UpdateDraftAsync(id, dto, Operator()); return Ok(new { ok = true }); } /// 删除草稿。 [HttpDelete("{id:long}")] public async Task Delete(long id) { await _service.DeleteAsync(id); return Ok(new { ok = true }); } /// SQL 安全校验。 [HttpPost("validate")] public IActionResult Validate([FromBody] KpiSqlValidateDto dto) => Ok(_service.Validate(dto.SqlScript)); /// 试算(不写正式 KPI 值;服务端重校验 + 只读执行)。 [HttpPost("preview")] public async Task Preview([FromBody] KpiSqlPreviewDto dto, CancellationToken ct) { if (string.IsNullOrWhiteSpace(dto.MetricCode) || string.IsNullOrWhiteSpace(dto.ModuleCode)) return BadRequest(new { message = "metricCode / moduleCode 必填" }); var res = await _service.PreviewAsync(dto, ct); return Ok(res); } /// 发布(事务:单生效版本)。 [HttpPost("{id:long}/publish")] public async Task Publish(long id) { await _service.PublishAsync(id, Operator()); return Ok(new { ok = true }); } /// 激活/回滚(把某已发布历史版本设为当前生效)。 [HttpPost("{id:long}/activate")] public async Task Activate(long id) { await _service.ActivateAsync(id, Operator()); return Ok(new { ok = true }); } /// 停用。 [HttpPost("{id:long}/retire")] public async Task Retire(long id) { await _service.RetireAsync(id, Operator()); return Ok(new { ok = true }); } }