Skip to content

tactics-sim-engine 开发规范

适用于 products/tactics-sim-engine — 旗舰产品应用。 这是整个 monorepo 的最终集成层,消费所有 @nexa/* 组件库。

定位

战术仿真引擎是一个基于可停靠面板(Dockview)的桌面级 SPA,集成:

  • GIS 视图:Cesium 3D 地球(通过 earth-viewer
  • 面板系统:可拖拽/停靠/分组的 Dockview 布局
  • Ribbon 工具栏:Office 风格的功能区
  • 实体管理:场景树 + 属性编辑 + 动作编排
  • 时间轴:仿真时间控制 + 轨道
  • 场景配置:底图/地形/相机管理

目录结构

products/tactics-sim-engine/
├── package.json              # private: true
├── index.html                # SPA 入口,标题: 战术仿真引擎 - NexaGIS
├── vite.config.ts            # dev 时 alias 所有子包到 src/lib 源码
├── build.sh                  # 全量构建脚本(依赖 → 产品)
├── src/
│   ├── main.ts               # 入口:createApp + Pinia + Naive UI
│   ├── App.vue               # 根组件(Naive UI Config Provider 包裹)
│   ├── components/           # 产品级 UI 组件
│   │   ├── header/           # 顶部 Ribbon 工具栏
│   │   ├── ribbon/           # 功能区按钮组
│   │   ├── panels/           # 各功能面板(wrapper 引入 apps/ 组件)
│   │   ├── workarea/         # Dockview 布局宿主
│   │   ├── status/           # 底部状态栏
│   │   └── mobile/           # 移动端适配组件
│   ├── layouts/              # 布局组件
│   │   ├── MainLayout.vue    # 桌面端布局(Dockview + Ribbon + StatusBar)
│   │   └── MobileLayout.vue  # 移动端布局
│   ├── stores/               # Pinia stores
│   │   ├── module.ts         # 模块/面板注册
│   │   ├── project.ts        # 项目状态
│   │   ├── scene.ts          # 场景配置
│   │   ├── status.ts         # 状态栏信息
│   │   ├── theme.ts          # 主题配置
│   │   └── window.ts         # 窗口/面板布局
│   ├── services/             # 服务层
│   │   ├── index.ts          # ServiceRegistry
│   │   └── gis/              # GIS 服务
│   ├── composables/          # 产品级 composable
│   ├── types/                # 产品级类型
│   ├── modules/              # 功能模块
│   ├── core/                 # 核心逻辑
│   │   └── event-bus.ts      # 事件总线
│   ├── commands/             # 命令系统
│   ├── data/                 # 静态数据
│   ├── themes/               # 主题定义
│   └── assets/               # 静态资源

架构约束

面板引入规范

产品中的面板组件(panels/)是对 apps/ 组件库的轻量 wrapper,不允许在此处复制业务逻辑

vue
<!-- components/panels/BaseMapPanel.vue -->
<script setup lang="ts">
// ✅ 正确:直接引入 apps 组件,embedded=true 嵌入
import { BaseMapPanel } from '@nexa/base-map-manager'
</script>

<template>
  <BaseMapPanel embedded />
</template>
vue
<!-- ❌ 错误:在 products 中重新实现底图管理逻辑 -->
<script setup lang="ts">
const basemaps = ref([])
// 不要在这里写业务逻辑...
</script>

状态管理

  • 全局状态:使用 Pinia stores(stores/
  • 面板间通信:通过 Pinia stores 或事件总线(core/event-bus.ts
  • 避免 prop drilling:跨层级数据通过 store 共享

服务层

  • GIS 相关操作通过 services/gis/ 封装
  • 服务通过 ServiceRegistry 注册和获取
  • 组件不应直接操作底层 CesiumViewer 实例(应通过服务层)

开发约束

必须遵守

  • 使用 <script setup lang="ts">
  • 组件分层清晰components/ 只放产品级组件,通用功能下沉到 apps/
  • Vite 配置维护好 alias:dev 时 alias 子包到源码,确保 HMR 正常工作
  • 页面标题战术仿真引擎 - NexaGIS
  • Layout 响应式MainLayout.vue(桌面)和 MobileLayout.vue(移动端)必须同时维护

禁止事项

  • ❌ 在 products 中重新实现 apps/ 已有的功能
  • ❌ 绕过 Pinia store 直接操作全局状态
  • ❌ 在组件中硬编码面板布局(应由用户拖拽配置)
  • ❌ 引入未在 @nexa/* 公共 API 中导出的模块
  • ❌ 修改 node_modules 或直接依赖 packages/gis-cesium/src/lib/ 内部文件

依赖管理

依赖方向

products/tactics-sim-engine
  → apps/* (workspace:*)
  → packages/* (workspace:*)
  → cesium / vue / naive-ui / pinia / dockview-core

Vite 配置关键点

typescript
// vite.config.ts 必须配置:
export default defineConfig({
  resolve: {
    alias: {
      // dev 时子包 alias 到源码,确保 HMR
      '@nexa/schema-form': 'path/to/apps/schema-form/src/lib/index.ts',
      // ...
    },
    dedupe: ['naive-ui', 'vue', 'cesium'],  // 避免多实例
  },
})

新增功能流程

  1. 判断归属:这个功能是通用组件(→ apps/)还是产品逻辑(→ products/)?
  2. 如果是通用组件:先在 apps/ 开发,再在 products/ 中引入
  3. 如果是产品逻辑:确定放在 components/ / composables/ / stores/ / services/ 哪个目录
  4. 更新状态管理:如需全局状态,在 stores/ 中添加
  5. 如果是新面板:在 components/panels/ 创建 wrapper,注册到 Dockview 面板列表

验收标准

  • [ ] 页面标题为 战术仿真引擎 - NexaGIS
  • [ ] pnpm dev 正常启动,HMR 正常工作
  • [ ] 所有面板通过 Dockview 可正常拖拽/停靠
  • [ ] 无直接引用 packages/gis-cesium/src/lib/ 内部路径
  • [ ] 新增通用功能已下沉到 apps/
  • [ ] 无 TypeScript 错误