using System.Text.Json; using System.Text.Json.Nodes; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using MiGu.Server.Configs; using MiGu.Server.Signal; namespace MiGu.Server.Controllers; /// /// 迷毂「数据中心」:把 scene.signal 的 Model JSON 以表格读写(PLC 握手 / 磁条交管)。 /// 文件落在 SimpleLite 工作目录 Config/Signal/*.json,不依赖 SimpleLite 进程是否在跑。 /// [ApiController] [Authorize(Policy = "PlatformScope")] [Route("api/signal-data")] public sealed class SignalDataController : ControllerBase { private readonly SignalDataStore _store; private readonly ConfigStore _config; public SignalDataController(SignalDataStore store, ConfigStore config) { _store = store; _config = config; } [HttpGet] public IActionResult List([FromQuery] bool summary = false) { var enabled = SignalEnabled(); var tables = summary ? _store.GetTables().Select(ProjectSummary).ToList() : _store.GetTables().Select(ProjectTable).ToList(); return Ok(new { signalEnabled = enabled, workingDirectory = _store.ResolveWorkingDirectory(), tables }); } [HttpGet("{id}")] public IActionResult Get(string id) { var table = _store.Find(id); if (table == null) return NotFound(new { message = $"未知数据表:{id}" }); return Ok(ProjectTable(table)); } [HttpPut("{id}")] public IActionResult Save(string id, [FromBody] JsonElement body) { var table = _store.Find(id); if (table == null) return NotFound(new { message = $"未知数据表:{id}" }); if (!body.TryGetProperty("rows", out var rowsEl) || rowsEl.ValueKind != JsonValueKind.Array) return BadRequest(new { message = "请求体需要 rows 数组" }); JsonArray rows; try { rows = JsonNode.Parse(rowsEl.GetRawText()) as JsonArray ?? new JsonArray(); } catch (Exception ex) { return BadRequest(new { message = $"rows 不是合法 JSON 数组:{ex.Message}" }); } try { _store.SaveRows(table, rows); } catch (Exception ex) { return StatusCode(500, new { message = $"保存失败:{ex.Message}" }); } return Ok(ProjectTable(table)); } private object ProjectSummary(SignalTableDef table) => new { id = table.Id, title = table.Title, category = table.Category, fileName = table.FileName }; private object ProjectTable(SignalTableDef table) { var (path, error) = _store.ResolveFile(table, createDir: false); var exists = path != null && System.IO.File.Exists(path); return new { id = table.Id, title = table.Title, category = table.Category, fileName = table.FileName, exists, error, columns = table.Columns, rows = _store.LoadRows(table) }; } private bool SignalEnabled() => _config.GetDeployment().ToLauncherSceneIds() .Contains(DeploymentProfile.SignalSceneId, StringComparer.OrdinalIgnoreCase); }