Files
黄兆尉andCursor 3686abdc78 将调度内核标识从 SimpleLite 全面重命名为 Simple3。
配置段/环境变量、Launcher、健康检查 API、OpenAPI 与前后端文案同步;兼容探测旧 SimpleLite 进程名。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 17:46:52 +08:00

148 lines
5.9 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MiGu.Server.Configs;
using MiGu.Server.Launcher;
namespace MiGu.Server.Controllers;
/// <summary>
/// 配置向导 API。登录后若 <c>deployment.Configured=false</c>(见 <c>LoginResponse.NeedsWizard</c>),
/// 前端进入向导:
/// <list type="bullet">
/// <item><c>GET /api/wizard/options</c>:可选项目录(导航方式 / 模块 / 业务场景模板)。</item>
/// <item><c>GET /api/wizard/profile</c>:回显当前部署画像(含由导航选型推导的激活场景 id)。</item>
/// <item><c>PUT /api/wizard/profile</c>:保存并置 <c>Configured=true</c>(仅 Platform scope)。</item>
/// <item><c>POST /api/wizard/reset</c>:把 <c>Configured</c> 置回 false 以重新引导(仅 Platform scope)。</item>
/// </list>
/// 说明:保存时即把选型固化为单一事实来源 <c>deployment</c> section,并同步联动 Launcher ——
/// <see cref="SaveProfile"/> 调 <c>WriteActiveScenes</c> 写 <c>plugins/active-scenes.json</c> / 透传 <c>--scenes</c>
/// 驱动 Simple3 下次启动选择性加载选定的导航场景插件。
/// </summary>
[ApiController]
[Authorize]
[Route("api/wizard")]
public class WizardController : ControllerBase
{
private readonly ConfigStore _store;
private readonly Simple3Launcher _launcher;
private readonly ILogger<WizardController> _log;
public WizardController(ConfigStore store, Simple3Launcher launcher, ILogger<WizardController> log)
{
_store = store;
_launcher = launcher;
_log = log;
}
[HttpGet("options")]
public IActionResult Options()
{
return Ok(new
{
navigationKinds = DeploymentCatalog.NavigationKinds,
modules = DeploymentCatalog.Modules,
scenarios = _store.Get("scenario").Payload
});
}
[HttpGet("profile")]
public IActionResult GetProfile() => Ok(Project(_store.GetDeployment()));
/// <summary>当前部署画像对菜单的裁剪结果(供前端做面板/能力级裁剪与排查)。</summary>
[HttpGet("effective-pages")]
public IActionResult EffectivePages()
{
var dp = _store.GetDeployment();
return Ok(new
{
configured = dp.Configured,
tailorablePages = DeploymentCatalog.TailorablePages(),
enabledPages = DeploymentCatalog.EnabledPages(dp),
hiddenPages = DeploymentCatalog.HiddenPages(dp)
});
}
[HttpPut("profile")]
[Authorize(Policy = "PlatformScope")]
public IActionResult SaveProfile([FromBody] SaveWizardRequest req)
{
if (req == null)
return BadRequest(new { message = "请求体不能为空" });
var user = User.Identity?.Name ?? User.FindFirstValue(ClaimTypes.NameIdentifier) ?? "";
var profile = new DeploymentProfile(
Configured: true,
PlatformType: string.IsNullOrWhiteSpace(req.PlatformType) ? "standard" : req.PlatformType.Trim(),
Modules: Clean(req.Modules),
NavigationKinds: Clean(req.NavigationKinds),
Scenarios: Clean(req.Scenarios),
UpdatedBy: user);
_store.PutDeployment(profile);
// 平台 → 内核联动:把导航选型写入 Simple3 的 plugins/active-scenes.json(下次启动选择性加载;
// 已运行实例可由前端再调 POST /api/sl/projection/scenes/apply 触发增量 reload)。
// scene.device(门/充电桩/按钮盒驱动)为各类项目通用能力,向导暂无独立选项,固定并入激活集合;
// 选 SPS / Pack 时 ToLauncherSceneIds 会并入 scene.signalPLC 握手)。
var sceneIds = profile.ToLauncherSceneIds();
var write = _launcher.WriteActiveScenes(sceneIds, alwaysLoad: null, source: "deployment-profile");
_log.LogInformation("部署向导已保存 by={User} nav=[{Nav}] scenes=[{Scenes}] activeScenesWritten={Ok}",
user, string.Join(",", profile.NavigationKinds), string.Join(",", sceneIds), write.Ok);
return Ok(Project(profile, write));
}
[HttpPost("reset")]
[Authorize(Policy = "PlatformScope")]
public IActionResult Reset()
{
var reset = _store.GetDeployment() with { Configured = false };
_store.PutDeployment(reset);
return Ok(Project(reset));
}
/// <summary>
/// 统一对外投影:camelCase 字段 + 推导出的 activeSceneIds(导航选型 → 内核场景 id)+
/// hiddenPages(被裁剪的菜单页)+ 可选的 activeScenesWrite(保存时写 active-scenes.json 的结果)。
/// </summary>
private static object Project(DeploymentProfile dp, Simple3Launcher.ActiveScenesWriteResult? write = null) => new
{
configured = dp.Configured,
platformType = dp.PlatformType,
modules = dp.Modules,
navigationKinds = dp.NavigationKinds,
scenarios = dp.Scenarios,
updatedBy = dp.UpdatedBy,
activeSceneIds = dp.ToLauncherSceneIds(),
hiddenPages = DeploymentCatalog.HiddenPages(dp),
activeScenesWrite = write == null ? null : new
{
ok = write.Value.Ok,
path = write.Value.Path,
error = write.Value.Error
}
};
/// <summary>去空白、去重(大小写不敏感)、保持顺序。</summary>
private static List<string> Clean(List<string>? items)
{
var result = new List<string>();
if (items == null) return result;
foreach (var s in items)
{
var t = s?.Trim();
if (!string.IsNullOrEmpty(t) && !result.Contains(t, StringComparer.OrdinalIgnoreCase))
result.Add(t!);
}
return result;
}
public record SaveWizardRequest(
string? PlatformType,
List<string>? Modules,
List<string>? NavigationKinds,
List<string>? Scenarios);
}