配置段/环境变量、Launcher、健康检查 API、OpenAPI 与前后端文案同步;兼容探测旧 SimpleLite 进程名。 Co-authored-by: Cursor <cursoragent@cursor.com>
12 KiB
12 KiB
平台 v3 重构 — 阶段 0~6 实际改动
范围:把 Simple3 WebTerminal 由"全功能浮动 Panel"模式收敛到"纯 3D Canvas",所有 UI 改由 Vue 平台前端 (
frontends/apps/simple-platform-vue) 接管;同时补齐反射 / 编辑 / 监控 / 编排 4 大业务面板与撤销栈、AI 生图、报警 SSE 等关键能力。基线:上一份方案见
ARCHITECTURE.mdv2/v3 章节;后续以本文件为准。
编译验证
dotnet build Simple3/Simple3.csproj—— 0 警告 0 错误dotnet build MiGu.Server/MiGu.Server.csproj—— 0 警告 0 错误build-platform-frontend.bat—— vite build 46.5s,无 vue-tsc / ts 错误,robocopy /MIR 已同步 MiGu.Server/wwwroot- 旧
SimpleComposer(WinForms) 在 v3 之外,不在本次构建目标里 - 旧
HttpClientHelper提升 LangVersion=latest 修通
阶段 0:后端 Simple3 平台化(已完成)
新增文件
| 文件 | 作用 |
|---|---|
Simple3/Web/MapEditApiController.cs |
写操作 8 路 API:create/delete/batch/copy-to/pick/dashboard/upload/ai-generate;阶段 6 又补:project/save、project/load、project/current、sample-sites-along-track |
Simple3/Web/ReflectionApiController.cs |
只读 + execute API;listKinds / listObjects / methods-by-type / setField / getBundle / selection 等 |
Simple3/Web/ReflectionApiDtos.cs |
反射 API DTO + 统一信封 ReflectionEnvelope<T> |
Simple3/Web/AiCompletionService.cs |
OpenAI Function Calling 调用 + map-generate 工具桥(真实 LLM,不再桩) |
Simple3/Web/AiConfigController.cs |
AI 服务配置(endpoint/apiKey/model/system prompt/temperature/maxTokens/timeout)读写 |
Simple3/Web/AlarmStreamService.cs |
1s 周期 diff car.status.enums.AlarmInfo(语义与 E:\Work\FRLD\StandardScene\Forklift.cs 的 Commons.GetCarStatus(this, "AlarmInfo") 等价),变化时通过 SSE alarm 事件推送 raise/update/clear |
Simple3/Web/ProjectionStreamModule.cs |
平台 SSE 总线,对外广播 object-created / object-deleted / object-patched / object-batch-changed / alarm / pick-result / project-saved / project-loaded |
Simple3/Web/PluginAssemblyScan.cs |
反射扫描 plugins/*.dll,把 MethodMember 标注的方法 + Car/Mission/CarProgram/Site/Track 子类型暴露给反射 API |
修改文件
| 文件 | 关键改动 |
|---|---|
Simple3/Startup.cs |
EntryPoint 第一步 EnsureImguiIniFromEmbedded();启动 AlarmStreamService、ProjectionStreamModule、AiConfig 加载 |
Simple3/UI/SimpleUI.cs |
CreateRemotePanelSetForTerminal 检测 CanvasOnly 旗标:不创建 Workbench / Toolbar / BottomBar / CAD / Welcome;保留 SelectionAction、SceneInput、SceneDrawable、2DMapView |
Simple3/Workspace/WorkspaceWebUiContext.cs |
增加 IsCanvasOnly(terminal) 旗标 + /declareCanvasOnly 注册器(与 /declareEmbedUi 互斥) |
Simple3/Web/ProjectionWebHost.cs |
/declareCanvasOnly 路由注册 |
Simple3/Web/ProjectionWebApiController.cs |
现有 projection API 上挂 selection-detail SSE hook |
Simple3/UI/ComposerDockPanel.cs |
CanvasOnly 时 PrepareWelcomePanel 返回空 |
Simple3/Props/UIHelpers.cs |
增加 UI_Image / UI_Text / UI_Model PropType。UI_Model 用于 CycleGUI 装饰物挂模型(obj/glb/gltf/cyclemodel) |
关键 API 路径
POST /projection/map-edit/objects/{kind} # site|track|bezier|arc|nurbs|image|text|model
DELETE /projection/map-edit/objects/{kind}/{id}
POST /projection/map-edit/objects/batch # create/delete/patch 混合
POST /projection/map-edit/objects/{kind}/{id}/fields/copy-to
POST /projection/map-edit/pick # 拾取会话
GET /projection/map-edit/dashboard/summary # KPI 聚合
POST /projection/map-edit/assets/upload # 图片/模型 base64
POST /projection/map-edit/ai/map-generate # 真实 LLM 生图
# 阶段 6 新增(本会话)
POST /projection/map-edit/project/save # body: { path?: string }
POST /projection/map-edit/project/load # body: { path: string }
GET /projection/map-edit/project/current
POST /projection/map-edit/objects/track/{id}/sample-sites
# body: { spacingMm, includeEndpoints?, layer? }
GET /projection/ai-config # 读 AI 服务配置
POST /projection/ai-config # 写 AI 服务配置
GET /projection/reflection/kinds | objects/{kind} | methods/{kind}/{id} | ...
SSE /projection/stream # 所有 SSE 事件
阶段 1:MapEditorView 四栏壳(已完成)
frontends/apps/simple-platform-vue/src/views/admin/MapEditorView.vue 完整重写为:
┌─────────────────────────────────────────────────────┐
│ EditTopBar:项目 / 文件 / 编辑 / 视图 / 图层 / 对齐吸附 │
│ + 撤销/重做 + AI 生图 + 保存 │
├──────┬─────────────────────────┬───────────────────┤
│ Edit │ Workspace3D │ EditPropertyPanel │
│ Tool │ (canvas-only iframe) │ 对象/类型默认/图层 │
│ Rail │ │ │
├──────┴─────────────────────────┴───────────────────┤
│ EditStatusBar:选中 / 鼠标坐标 / 工具 / 吸附 / undo │
└─────────────────────────────────────────────────────┘
新增组件
components/map-editor/EditTopBar.vue—— 6 个 dropdown 菜单(项目/文件/编辑/视图/图层/对齐吸附)+ 撤销重做按钮 + AI 生图入口 + 保存components/map-editor/EditToolRail.vue—— 6 组 CAD 工具按钮 + 吸附组(网格/对象/端点/中点 + 网格步长)components/map-editor/EditPropertyPanel.vue—— 3 Tab(对象 / 类型默认 / 图层),自动反射出getFields,每行可改可保存;多选时统一字段写入;不一致字段显示「-」;执行 reflectionApi.execute 调任何 MethodMembercomponents/map-editor/EditStatusBar.vue—— 状态栏components/map-editor/AiGenerateDialog.vue—— AI 生图对话框
反射 API 接入
api/mapEdit.ts—— MapEditApiController 全 8+4 路 API 胶水(本会话补的 4 个:projectSave / projectLoad / projectCurrent / sampleSitesAlongTrack)api/reflection.ts—— ReflectionApiController 全套胶水(含 MOCK 离线 fallback)
阶段 2:对齐 / 批量生成 / 复制字段 / 类型默认 / 图层(已完成)
composables/useAlignment.ts—— 11 种对齐模式:left/right/top/bottom/centerH/centerV/center/distributeH/distributeV/toFirst/toLastcomposables/useBatchGenerate.ts—— 横向/纵向/矩阵/环形 4 种批量生成器,输出 BatchOp[]composables/useClipboard.ts—— 对象/字段剪贴板transform.copyFields工具:MapEditorViewrunCopyFields读取多选(第 1 个为源,其余目标),prompt 字段名列表,调mapEditApi.copyFieldsTo;撤销时用前置 patch 回滚- 类型默认 Tab:站点/路径默认 layer/前缀/颜色/线宽,存 localStorage
mapEditor.defaults - 图层 Tab:图层名列表 + 可见 / 可选 / 颜色,本地状态
阶段 3:AI 生图 + 状态栏 + 项目保存/加载(已完成)
- AiGenerateDialog 通过
mapEditApi.aiMapGenerate真实调用 LLM,后端走AiCompletionService.GenerateMapAsync:用 OpenAI Function Calling 让 LLM 直接调 create_site / create_track / batch_create 等"工具",落地到 SimpleLib - 入口:EditTopBar 「AI 生图」按钮 → 弹对话框,参数:prompt / mode (sites/tracks/sites+tracks/full) / bounds / referenceImageBase64 / layer / constraints
- 项目保存/加载:EditTopBar「保存」/「另存为」/「加载项目」→ prompt 输入路径 → 调
mapEditApi.projectSave/Load→ 服务端走SimpleProject.ToFile / FromFile;最近路径缓存到 localStoragemapEditor.lastProjectPath
阶段 4:MapMonitor 浮动报警卡 + KPI + 实时列表(已完成)
frontends/apps/simple-platform-vue/src/views/admin/MapMonitorView.vue 改动:
- 删除原
AlarmTicker.vue底部滚动条 - 新增
components/map-monitor/FloatingAlarmStack.vue+FloatingAlarmCard.vue,可拖动 / 可吸边 / 可堆叠 - 报警来源走
useMapEditStream.onAlarm(订阅 SSE 的alarm事件,由 AlarmStreamService 1s diff 推送) - KPI 3 卡:在线车辆 / 运行中任务 / 排队任务
- 实时列表:左侧 Workspace3D + 右侧 VehicleMonitorPanel + SelectionDetailPanel
- 「定位」按钮通过
reflectionApi.setSelection('car', id)让 Simple3 3D 高亮该车(视觉上等效 flyTo)
阶段 5:OrchestrationView 设计与编排(已完成)
views/admin/OrchestrationView.vue 5-Tab 壳:
| Tab | 来源 |
|---|---|
| 车辆 | 复用现有 CarPanelView |
| 进程 | 复用现有 MissionEditorView |
| 脚本 | components/orchestration/ReflectionKindTable.vue(kind=script):动态列表 + 反射 method 执行 |
| 任务流 | ReflectionKindTable(kind=mission, extraFilter='taskflow') |
| 触发器 | ReflectionKindTable(kind=mission, extraFilter='trigger') |
Tab 状态缓存到 sessionStorage。
阶段 6:联调 / 撤销栈做实 / 文档(已完成)
撤销栈做实
composables/useHistory.ts 提供 run/undo/redo/composite,每个命令 apply/revert 双向。本次把 MapEditorView 里所有占位 revert 改成真实回滚:
| 命令 | 原 revert | 现 revert |
|---|---|---|
runCreateSite |
delete 创建的 id | (未变) |
handleTrackPick 创建路径 |
delete 创建的 id | (未变) |
deleteSelection |
⚠️ 仅本地撤销 | getBundle 抓快照 → batch.create 重建(id 重排) |
onSetField 字段修改 |
⚠️ 不回滚 | getBundle 抓原值 → setField 回去 |
applyAlignment |
(已用 patch 反向恢复) | (未变) |
applyBatchAsCommand |
(已用 delete 反向移除) | (未变) |
runAlongPathSampling(新增) |
—— | delete 所有采样产生的 site id |
runCopyFields(新增) |
—— | patch 反向把 targets 字段值恢复 |
沿路径采样
- 后端:
POST /projection/map-edit/objects/track/{id}/sample-sites { spacingMm, includeEndpoints?, layer? }—— 当前在 siteA → siteB 之间欧式直线均分(贝塞尔/弧的真实参数化采样留待后续 Track 子类 PR) - 前端:选中 1+ 条 track,工具栏「沿路径」→ prompt 间距和端点开关 → 调后端,撤销可回退
编译相关清理
Simple3/Recording/(之前的录制/回放实验目录)误用Simple3.Renderingnamespace、Car找不到、Start(string, out)默认参数顺序等 3 个错误 → 修Simple3/Props/UISite.cs在Simple3.Propsnamespace 下Workspace.AddProp被解析成Simple3.Workspace.AddProp→ 改为全限定CycleGUI.Workspace.AddPropSimple3/Workspace/WorkspaceBottomBar.cs缺using Simple3.Workspace;→ 补HttpClientHelper.csprojLangVersion 7.3 → latest
已知 TODO(不阻塞 v3 上线)
- 贝塞尔/弧/Nurbs 路径的真实参数化采样(当前直线均分)
- 撤销栈跨 Tab / 跨 session 共享(当前仅 MapEditor 视图局部)
- Workspace3D 真正的 postMessage 'workspace.flyTo' 双向桥(当前用 setSelection 代替)
- 复制字段 UI 支持类型化字段挑选器(当前 prompt 输入字段名)
- AI 生图 OAuth/键持久化加密(当前明文存 config)
- Recording 录制/回放模块未完工(PlaybackController 已修通编译,UI 已挂底栏,但实际录制/回放业务逻辑需要后续单独 PR 完成)
启动方式
# 1. 后端 build(Simple3 + MiGu.Server)
dotnet build Simple3\Simple3.csproj
dotnet build MiGu.Server\MiGu.Server.csproj
# 2. 前端打包并同步到 wwwroot
.\build-platform-frontend.bat
# 3. 启动平台 + Simple3
dotnet run --project MiGu.Server # 监听 0.0.0.0:8080
# Simple3 端口 8222/8223 由 Simple3 自己启动
# 4. 访问
http://127.0.0.1:8080/admin/map-editor # 地图编辑(v3 四栏壳)
http://127.0.0.1:8080/admin/map-monitor # 地图监控(驾驶舱 + 浮动报警)
http://127.0.0.1:8080/admin/orchestration # 设计与编排(5 Tab)