diff --git a/MiGu.Server/Auth/PageCatalog.cs b/MiGu.Server/Auth/PageCatalog.cs index bc807ab..df82dc2 100644 --- a/MiGu.Server/Auth/PageCatalog.cs +++ b/MiGu.Server/Auth/PageCatalog.cs @@ -33,6 +33,7 @@ public static class PageCatalog new("admin-playback", "调度回放", "概览", ScopePlatform), // ── 管理端 / Platform:设计与编排 ── + new("admin-maps", "地图管理", "设计与编排", ScopePlatform), new("admin-map-editor", "地图编辑", "设计与编排", ScopePlatform), new("admin-project-properties", "项目属性", "设计与编排", ScopePlatform), new("admin-tracks", "场景管理", "设计与编排", ScopePlatform), diff --git a/MiGu.Server/Configs/ConfigStore.cs b/MiGu.Server/Configs/ConfigStore.cs index 8eb8523..1fcb379 100644 --- a/MiGu.Server/Configs/ConfigStore.cs +++ b/MiGu.Server/Configs/ConfigStore.cs @@ -5,7 +5,7 @@ namespace MiGu.Server.Configs; /// /// 配置中心存储(内存 + JSON 文件持久化占位)。 -/// 14 个 section 对应 ARCHITECTURE.md §9 的 13+1 维度。 +/// 前 14 个 section 对应 ARCHITECTURE.md §9 的 13+1 维度;外加 deployment —— 登录后「配置向导」的部署画像。 /// 真实落地时由 SimpleShared.Persistence 接入 EF Core,并配合 YARP 下发至 SimpleLite。 /// public sealed class ConfigStore @@ -13,7 +13,8 @@ public sealed class ConfigStore public static readonly string[] AllSections = { "system", "integrations", "routing", "vehicle", "charge", "task", - "traffic", "auth", "device", "fleet", "scenario", "location", "ops", "widget" + "traffic", "auth", "device", "fleet", "scenario", "location", "ops", "widget", + "deployment" }; public sealed record Envelope(string Section, int Version, DateTimeOffset UpdatedAt, object Payload); @@ -67,6 +68,46 @@ public sealed class ConfigStore public IEnumerable List() => AllSections.Select(Get); + /// + /// 强类型读取部署画像(deployment section)。兼容 Payload 为 (默认值场景) + /// 或 (已持久化场景)两种形态,并把 null 列表/空字符串规整为安全默认值, + /// 供 AuthController(NeedsWizard)/ WizardController / Launcher 直接使用。 + /// + public DeploymentProfile GetDeployment() + { + var env = Get("deployment"); + var dp = env.Payload switch + { + DeploymentProfile d => d, + JsonElement el => SafeDeserializeDeployment(el), + _ => DeploymentProfile.Default() + }; + return new DeploymentProfile( + dp.Configured, + string.IsNullOrWhiteSpace(dp.PlatformType) ? "standard" : dp.PlatformType, + dp.Modules ?? new List(), + dp.NavigationKinds ?? new List(), + dp.Scenarios ?? new List(), + dp.UpdatedBy ?? ""); + } + + /// 以强类型保存部署画像(统一经 走版本/持久化/camelCase 序列化)。 + public Envelope PutDeployment(DeploymentProfile profile) + { + var el = JsonSerializer.SerializeToElement(profile, _jsonOpts); + return Put("deployment", el); + } + + private DeploymentProfile SafeDeserializeDeployment(JsonElement el) + { + try { return el.Deserialize(_jsonOpts) ?? DeploymentProfile.Default(); } + catch (Exception ex) + { + _logger.LogWarning(ex, "反序列化 deployment 失败,回退默认值"); + return DeploymentProfile.Default(); + } + } + private static object JsonElementToObject(JsonElement el) { // 简化:直接保留 JsonElement,让 STJ 在响应时再原样写回 @@ -126,6 +167,7 @@ public sealed class ConfigStore "location" => LocationManagement.Default(), "ops" => OpsConfig.Default(), "widget" => CustomWidgetConfig.Default(), + "deployment" => DeploymentProfile.Default(), _ => new { } }; diff --git a/MiGu.Server/Configs/DeploymentCatalog.cs b/MiGu.Server/Configs/DeploymentCatalog.cs new file mode 100644 index 0000000..ed31c68 --- /dev/null +++ b/MiGu.Server/Configs/DeploymentCatalog.cs @@ -0,0 +1,74 @@ +namespace MiGu.Server.Configs; + +/// +/// 配置向导「可选项目录」与「选型 → 平台能力」映射的单一事实来源。 +/// +/// 前端向导从 GET /api/wizard/options 拿到这些可选项渲染勾选框;后端 +/// 在「按选型裁剪菜单」时把模块 +/// 映射为 PageCatalog 的可见页 id。集中定义,避免前后端各写一份导致漂移。 +/// +public static class DeploymentCatalog +{ + /// 一个可勾选项。 是稳定机器标识, 用于前端分组展示。 + public record Option(string Id, string Name, string Group, string Description); + + /// 导航方式(多选,一等维度)。id 与 的 key 对齐。 + public static readonly IReadOnlyList