OpsController 由「假成功队列」改为经投影反射 API 真实下发 SimpleLite,按 appsettings 的 Ops:Dispatch 映射 opCode→kind:Method,并做白名单 + JWT ops claim 双重校验; 审计改用 OpsAuditStore 原子落盘(取代进程内队列,重启不丢),新增 IdempotencyKey 幂等去重; ExtractNumericId 取首段数字避免 AGV-12-3 误合并。appsettings 同步加 Ops:Dispatch 说明与 sl-route 鉴权策略。 Co-authored-by: Cursor <cursoragent@cursor.com>
MiGu.Server
「迷毂 · 智能调度平台」的后端骨架(ASP.NET Core 8 + YARP)。 对应 ARCHITECTURE.md v1.6 §1.1 中提到的「Platform 管理端」后端可执行文件。
会话 N+1(启动反转):现在
MiGu.Server.exe是主入口。 用户先启动 MiGu.Server,浏览器登录页选择「启动模式」(本地+Web / 仅Web), 后端AuthController.Login调用SimpleLiteLauncher.MaybeStart(launchMode)按所选模式拉起SimpleLite.exe, 通过--display-mode=web|web+local透传给 SimpleLite 的Configuration.displayMode。工程名
MiGu.Server/ 程序集MiGu.Server.dll保持稳定,仅用户可见前端文案改为「迷毂」。
克隆后首次部署速查(必读)
本仓库为 Migu2.0,已包含预构建的 wwwroot/ 前端,克隆后可直接编译运行 MiGu.Server。
# 1) 编译 MiGu.Server
cd MiGu.Server
dotnet build MiGu.Server.csproj -c Debug
# 2) 启动(登录后按所选模式拉起 SimpleLite)
dotnet run
# 或:.\bin\Debug\net8.0\MiGu.Server.exe
更新前端:在 Simple 仓库执行 build-platform-frontend.bat,将 frontends/apps/simple-platform-vue/dist/ 同步到本目录 wwwroot/。
配置 SimpleLite 路径(必读)
配置文件位置(无 Web 界面):
MiGu.Server/appsettings.json→ 搜索"SimpleLite"节点。
登录页选「本地 + Web / 仅 Web」后,后端在此配置的路径拉起SimpleLite.exe。
启动后可在浏览器打开http://localhost:8080/api/health/simplelite查看路径是否解析成功。
登录成功后,MiGu.Server 会按所选启动模式拉起 SimpleLite.exe。默认已在 appsettings.json 写好与 Simple 仓库并列的相对路径;开发机可用 appsettings.Development.json 覆盖为绝对路径。
本机开发(与 Simple 仓库并列)
仓库默认已在 appsettings.Development.json 中写好:
"SimpleLite": {
"Enabled": true,
"ExecutablePath": "E:\\Work\\Core\\Simple-FR\\Simple\\SimpleLite\\bin\\Debug\\SimpleLite.exe",
"WorkingDirectory": "E:\\Work\\Core\\Simple-FR\\Simple\\SimpleLite\\bin\\Debug",
"ProjectionPort": 8222,
"ReadinessTimeoutMs": 8000,
"FollowParent": false
}
请先编译 SimpleLite(在 Simple 仓库):
cd ..\Simple
dotnet build SimpleLite\SimpleLite.csproj -c Debug
若你的 Simple 不在上述绝对路径,可改为相对路径(相对 MiGu.Server 工作目录):
"ExecutablePath": "..\\..\\Simple\\SimpleLite\\bin\\Debug\\SimpleLite.exe",
"WorkingDirectory": "..\\..\\Simple\\SimpleLite\\bin\\Debug"
配置项说明
| 键 | 含义 |
|---|---|
Enabled |
false 时永不拉起 SimpleLite(只调试平台 UI) |
ExecutablePath |
SimpleLite.exe 绝对或相对路径;留空则自动探测(见 Launcher/SimpleLiteOptions.cs) |
WorkingDirectory |
子进程工作目录;留空则用 exe 所在目录(读写 simple.json / imgui.ini) |
ProjectionPort |
就绪检测端口,默认 8222 |
ReadinessTimeoutMs |
登录后等待 SimpleLite WebAPI 就绪的最长时间(毫秒) |
FollowParent |
true 时 MiGu.Server 退出会结束 SimpleLite;默认 false(两进程独立) |
环境变量覆盖
$env:SimpleLite__ExecutablePath = "D:\apps\SimpleLite.exe"
$env:SimpleLite__WorkingDirectory = "D:\apps"
$env:SimpleLite__Enabled = "true"
生产 / 合并发布
将 SimpleLite.exe 与依赖 DLL 放到 MiGu.Server 同目录,并清空 ExecutablePath(走自动探测 ./SimpleLite.exe),或在 appsettings.Production.json 写死部署路径。
浏览器访问 http://localhost:8080/login:
- 用户名 / 密码(
appsettings.json:Auth.Users默认 admin/admin、ops/ops); - 选 scope(管理员 / 运营);
- 选 SimpleLite 启动模式:
- 本地 + Web → 透传
--display-mode=web+local,桌面 ImGui 窗口 + 浏览器同时启动; - 仅 Web → 透传
--display-mode=web,只起 WebTerminal,不弹本地窗口;
- 本地 + Web → 透传
- 点登录。
AuthController.Login调用SimpleLiteLauncher.MaybeStart(...)阻塞等 Projection (:8222) 就绪后返回 LoginResponse。
如果只想跑 MiGu.Server 单进程调试(不拉 SimpleLite),把
appsettings.json:SimpleLite.Enabled改为false即可。
安全须知(生产部署必读)
重要:以下默认值仅供本地开发,切勿原样用于生产环境。
appsettings.json:Auth.Users内置admin/admin、ops/ops为弱口令演示账号;appsettings.json:Jwt.Secret、Internal.Token为占位符REPLACE_ME。生产部署务必通过环境变量或
appsettings.Production.json/ 密钥管理覆盖 (ASP.NET Core 配置优先级:环境变量 >appsettings.{Environment}.json>appsettings.json)。 环境变量示例(__双下划线表示配置层级):$env:Auth__Users__admin__Password = "<强密码>" $env:Jwt__Secret = "<不少于 32 字节的随机串>" $env:Internal__Token = "<随机串>"详见代码审核 ISSUE-03(
Doc/CODE_REVIEW_ISSUES_2026-05-29.md)。SimpleLite 8222 内部 API(RV-04):默认
simple.json:platform.allowLoopbackBypass=true,本机回环请求免 token;多租户 / 共享主机的生产环境建议设为false,强制所有请求携带X-Platform-Internal-Token(配合platform.internalToken或MiGu.Server/data/.internal-token)。详见复审Doc/CODE_REVIEW_WEEK_2026-05-29.mdRV-04。
能力清单(本轮)
- Kestrel 监听
:8080(HTTP); - 静态托管:启动时自动探测 WebRoot ——
- 开发模式:仓库内
frontends/apps/simple-platform-vue/dist/存在则直接挂为 WebRoot(pnpm build后立即生效,无需 robocopy 到 wwwroot); - 兜底/部署模式:找不到 dist 时回退到
wwwroot/(由build-platform-frontend.bat的 robocopy /MIR 填充); - SPA fallback 让
/admin/*/monitor/*/login/status等所有非 API 路径都回退到index.html,由 vue-router 接管;
- 开发模式:仓库内
- YARP 反向代理:
/api/sl/{**catch-all}→http://127.0.0.1:8222/(SimpleLite WebAPI;当前 SimpleLite 未启 WebAPI 时返回 502);/vr/{**catch-all}→http://127.0.0.1:8223/(webVRender;可用于同源 iframe 解决 X-Frame-Options 限制);
- 14 维度配置中心占位(对齐 §9):内存 +
data/config-{section}.json持久化; - Mock 鉴权:
/api/auth/login返回 Mock JWT +EffectivePermissions;LoginRequest 新增launchMode: "WebOnly" | "DesktopAndWeb"字段,登录成功后SimpleLiteLauncher据此拉起子进程; - SimpleLite 子进程编排:
Launcher/SimpleLiteLauncher.cs幂等 / Stdout 转发 / Windows JobObject 父子绑定 / 端口就绪等待,配置见appsettings.json:SimpleLite; - 运维白名单网关占位:
/api/sl/ops/execute、/api/sl/ops/audits; - 投影 API 占位:
/api/projection/{sites,tracks,cars,missions}; - 健康检查:
/api/health; - Swagger:开发环境下
/swagger。
不在本轮范围:真实 SimpleLite WebAPI、SystemMission 拉起、真实 JWT/RBAC、SQLite/EF Core 持久层。
目录结构
MiGu.Server/
├── MiGu.Server.csproj
├── Program.cs # Kestrel + YARP + CORS + StaticFiles + SPA fallback
├── appsettings.json # YARP 路由 + CORS 白名单
├── appsettings.Development.json
├── Properties/launchSettings.json
├── Controllers/
│ ├── AuthController.cs # /api/auth/login | /api/auth/logout
│ ├── ConfigController.cs # GET/PUT /api/config[/{section}]
│ ├── ProjectionController.cs # /api/projection/{sites,tracks,cars,missions}
│ ├── OpsController.cs # /api/sl/ops/{execute,audits}
│ └── HealthController.cs # /api/health
├── Configs/ # 与 ARCHITECTURE.md §9 一一对齐的强类型 record
│ ├── SystemConfig.cs
│ ├── ExternalIntegrations.cs
│ ├── RoutingPolicy.cs
│ ├── VehicleMaintenancePolicy.cs
│ ├── ChargePolicy.cs
│ ├── TaskAllocationPolicy.cs
│ ├── TrafficRule.cs
│ ├── DeviceManagementConfig.cs
│ ├── FleetLifecycleConfig.cs
│ ├── ScenarioTemplateConfig.cs
│ ├── LocationManagement.cs
│ ├── OpsConfig.cs
│ ├── CustomWidget.cs
│ ├── EffectivePermissions.cs
│ └── ConfigStore.cs # 内存 + JSON 文件持久化(占位)
├── data/ # 运行时生成的 config-{section}.json
└── wwwroot/ # 部署兜底(dev 模式优先用 frontends/.../dist;assets/ 与 index.html 已 ignore)
独立启动(仅当你不通过 SimpleLite 自启时)
# 1) 还原 + 编译 + 运行
cd MiGu.Server
dotnet run
# 等价的 build + run 一键脚本:
.\build-and-run.bat # Debug
.\build-and-run.bat release # Release
# 2) 验证
# 打开 http://localhost:8080/ 欢迎页 / 平台前端
# 打开 http://localhost:8080/swagger API 文档
# 打开 http://localhost:8080/api/health 健康检查
# 打开 http://localhost:8080/api/config/system 系统级配置
或在 IDE 中以 MiGu.Server 作为启动项目。
启动时控制台会打印
[MiGu.Server] WebRoot -> dist: ...或WebRoot -> wwwroot ...,提示当前使用哪一份产物。 单独启动且既没有跑过pnpm build也没有跑过build-platform-frontend.bat时,会看到 SPA fallback 找不到index.html。 仓库根build-platform-frontend.bat仍可用于「打部署包」场景(把 dist robocopy /MIR 同步到 wwwroot)。 SimpleLite 自启 MiGu.Server 时,Program.cs 会从bin\<Config>\net8.0\沿目录向上找 dist; 找到则使用源码区 dist,找不到则使用 bin 同级的 wwwroot——两种启动方式共用同一份前端产物。
与前端联调
- 开发模式(前端在 Simple 仓库):
- 前端:
cd ../Simple/frontends && pnpm dev(:5173),Vite 代理/api至http://127.0.0.1:8080; - 后端:
cd MiGu.Server && dotnet run(:8080); - 浏览器访问
http://localhost:5173/login。
- 前端:
- 生产/同源模式(本仓库
wwwroot/):- 默认使用
MiGu.Server/wwwroot/(已随仓库提交构建产物); - 若上级目录存在
frontends/apps/simple-platform-vue/dist/,Program.cs 会优先挂 dist; - 浏览器访问
http://localhost:8080/login等路径由 vue-router 解析。
- 默认使用
YARP 与 SimpleLite
YARP 路由配置见 appsettings.json:
{
"ReverseProxy": {
"Routes": {
"sl-route": { "Match": { "Path": "/api/sl/{**catch-all}" }, "ClusterId": "sl-cluster" },
"vrender-route": { "Match": { "Path": "/vr/{**catch-all}" }, "ClusterId": "vrender-cluster" }
},
"Clusters": {
"sl-cluster": { "Destinations": { "sl1": { "Address": "http://127.0.0.1:8222/" } } },
"vrender-cluster": { "Destinations": { "vr1": { "Address": "http://127.0.0.1:8223/" } } }
}
}
}
/api/sl/ops/{execute,audits}在本工程被OpsController显式接住(更具体的路由),用于占位测试;- 其他
/api/sl/*由 YARP 透传到 SimpleLite:8222,SimpleLite 未启时会得到 502/连接被拒。
iframe 嵌入 webVRender 的两种方式
- 直连(默认):前端 iframe 指向
http://localhost:8223/?scope=...&token=...&ro=...,跨源; - 同源代理(可选):iframe 指向
http://localhost:8080/vr/?scope=...,由本工程 YARP 反代到 8223, 可规避 X-Frame-Options 等限制。前端可通过Workspace3D组件的hostprop 传localhost:8080/vr切换。
相关文档
- ARCHITECTURE.md — v1.6 总体架构(§4 进程拓扑、§6.3 YARP 配置、§9 配置中心、§10 交互序列、§17 视觉规范)
- [(见 Simple 仓库)frontends/README.md]((见 Simple 仓库)frontends/README.md) — 前端启动与联调说明(含「迷毂」品牌与紫色主题约定)