AGENTS.md — AI / 协作者开发指南
本文面向 AI 编码助手 与人类贡献者,说明
@m-tech/gis-core的架构、代码风格与扩展方式。
改代码前先读本文;新增能力时按「扩展清单」落地,并同步 demo / 文档导出。
1. 项目定位
- 是什么:Cesium 二次封装的三维 GIS 核心 SDK(npm 包
@m-tech/gis-core)。 - 不是什么:不是完整业务应用;Vue 业务组件在
packages/biz,演示在apps/demo。 - 目标用户:平台业务前端、大屏、工具站,通过 Viewer + Layer + Overlay 快速搭三维场景。
- 技术栈:TypeScript(部分 material 仍为 JS)、Vite 库模式、Cesium 1.x、Turf / proj4 / wellknown 等。
工作区若在 monorepo 根:packages/core 即本包。当前包版本见 package.json。
2. 架构心智模型
2.1 对象关系
Position / Color # 基础值对象
│
Overlay ──► Layer ──► Viewer (extends Cesium.Viewer)
Effect ───────────► Viewer
Widget ───────────► Viewer
Analysis / Measure / Plot 构造注入 Viewer,内部自建临时 Layer 或 Entity| 概念 | 职责 | 挂载方式 |
|---|---|---|
Viewer | 场景中枢:缓存 Layer/Effect/Widget,事件总线,相机与底图 | new Viewer(container, options) |
Layer | 一组 Overlay 的容器;_delegate 多为 DataSource / PrimitiveCollection / ImageryLayer | layer.addToViewer(viewer) |
Overlay | 单个图元;_delegate 多为 Entity / Primitive | overlay.addToLayer(layer) |
Effect | 后处理等场景特效 | effect.addToViewer(viewer) |
Widget | DOM UI 控件 | widget.addToViewer(viewer) |
Analysis | 分析算法 + 可视化 | new XxxAnalysis(viewer, options) |
2.2 生命周期与事件
- 构造:创建
_delegate,设置type,注册内部ADD/REMOVE监听。 - 挂载:
addTo*→ 触发事件 →_addHandler/_mountedHook/_addedHook。 - 卸载:
remove→_removeHandler/_removedHook,清理缓存与监听。
状态常量见 event/EventEnums.ts 的 State(initialized / added / removed …)。
事件基类 event/Event.ts:on / off / fire / once / clear,内部是 Cesium.Event 字典。
常用事件枚举(均从包入口导出或经 event 模块):
MouseEventType:CLICK、RIGHT_CLICK、MOUSE_OVER …ViewerEventType:ADD_LAYER、REMOVE_LAYER、ADD_EFFECT …LayerEventType/OverlayEventType/SceneEventType/PrimitiveOverlayEventType
2.3 坐标与 Transform
- 对外 API 一律优先
Position,不要直接让业务传裸Cartesian3(内部再转)。 utils/convertor/Transform.ts:cartographicToCartesian/cartesianToCartographic等。Position:经纬度为度;setter 的 heading/pitch/roll 入参是度,内部存弧度,getter 再转回度。- 数组视角:
defaultView: [lng, lat, alt, heading, pitch, roll]。
2.4 单例工具 liteUtils
CameraUtil / LayerUtil / ImageryUtil / EntityUtil 在 Viewer 构造时 new XxxUtil(this) 初始化,后续静态方法操作当前 Viewer。扩展时注意 destroy / 重绑,避免多 Viewer 场景串台。
2.5 导出入口
index.ts 是唯一公共 API 表面:
- 新增 public 类 → 在对应模块
index.ts导出 → 再写入根index.ts的 import 与 export 列表。 - 未在根
index.ts导出的类视为内部实现(如部分 Effect、CacheDB、WKTLayer2)。
3. 目录职责(改哪里)
| 目录 | 何时改 |
|---|---|
viewer/ | Viewer 选项、相机模式、图层/特效缓存、全局行为 |
base/ | Position、Color、帧循环 Loop |
overlay/entity/ | Entity 类图元(点线面体…) |
overlay/primitive/ | Primitive / 3D Tiles / 水面等 |
overlay/html/ | DOM 叠加 |
layer/ | 新图层类型、影像/地形 Provider |
material/ | MaterialProperty + 与 effects/shader 联动 |
effects/ + effects/shader/ | 后处理、天气、扫描;GLSL 放 shader/ |
analysis/ | 空间分析 |
geomatics/ | 量测、标绘、拾取 |
widget/ | 地图周边 UI |
event/ | 新事件类型、事件基类 |
utils/ | 纯工具、坐标转换、Suggestion |
liteUtils/ | 面向 Viewer 的快捷 API |
assets/css/ | 控件与覆盖物样式 |
plugin/ | 可选插件(如 CacheDB) |
不要把业务 Vue 组件、接口请求写进 core;那属于 packages/biz 或 apps/*。
4. 代码风格与约定
4.1 命名
| 类别 | 约定 | 示例 |
|---|---|---|
| 类 | PascalCase | EntityLayer, ViewShed |
| 实例私有字段 | _ 前缀 | _delegate, _viewer, _style |
| 钩子 | _xxxHook / _xxxHandler / _xxxCallback | _mountedHook |
| 类型枚举对象 | 模块内常量 + registerType | Overlay.registerType('point') |
| 文件 | 与主类同名 | Point.ts → export default Point |
| 模块出口 | index.ts 具名 re-export | export { default as Point } from '...' |
4.2 类模板(Overlay 子类)
参考 overlay/entity/Point.ts:
// 1. import Cesium 类型/类、Position、Util、Transform、父类
// 2. interface OPT extends CesiumXxx.ConstructorOptions { id?: string | number }
// 3. const DEF_OPT: OPT = { ...defaults }
// 4. class Xxx extends Overlay {
// constructor(position|positions, options = DEF_OPT) {
// 校验参数 → super(options.id)
// this._options = { ...DEF_OPT, ...options }
// this._delegate = new Entity({ ... })
// this.setStyle(this._options)
// this.type = Overlay.getOverlayType('xxx')
// }
// set/get position(s)
// _mountedHook() { 写 position;Util.merge(this._delegate.xxx, this._style) }
// setStyle(style) { merge;return this }
// static fromEntity?(entity) { ... }
// }
// 5. Overlay.registerType('xxx')
// 6. export default Xxx必须遵守:
- 构造参数非法时
throw new Error('...')(中英文均可,与邻近文件一致)。 setStyle删除不应进 style 的字段(如position),Util.merge合并到_delegate对应图形属性,return this。- 文件末尾
Overlay.registerType('snake_or_lower'),与getOverlayType使用同一字符串。 - JSDoc 写清
@public、参数、示例(demo 里可抄);利于 TypeDoc。
4.3 Layer 子类要点
参考 layer/EntityLayer.ts / layer/Layer.ts:
super(options)后设置this._delegate(CustomDataSource / PrimitiveCollection 等)。this.type = LayerType.Xxx(LayerType字典需同步增加键)。- 通过
layerEvent的 ADD/REMOVE 挂到 Viewer;Viewer 用_layerCache[type][id]索引。 - Overlay 加入:Entity 走
entities.add,Primitive 走collection.add(见Overlay._addHandler)。
4.4 Effect / Analysis / Widget
- Effect:继承
effects/Effect.ts;_prepareDelegate创建postProcessStage;addToViewer。 - Analysis:继承
analysis/Analysis.ts;构造函数(viewer, options);资源销毁方法尽量提供destroy/clear。 - Widget:继承
widget/Widget.ts;实现_init/install;需要跟随屏幕坐标时设_positionChangeAble。
4.5 Material(历史 JS)
material/仍以 JavaScript 为主,基类MaterialProperty.js。- 新材质:继承
MaterialProperty,实现getType/getValue/equals,在material/index.js注册,GLSL 可放effects/shader/。 - 若改为 TS,保持与现有 Property 接口一致,避免破坏
Material命名空间导出。
4.6 类型与 any
- 历史代码大量
any;新代码尽量写清接口(options、style),至少补全 public 方法参数。 - 允许
@ts-ignore仅用于 Cesium 私有 API(如 globe shader),需简短注释原因。 - 不引入与现有风格冲突的严格 eslint 大重构,除非任务明确要求。
4.7 注释与语言
- 对外 API 注释:中文为主(与现有文件一致)。
- 复杂算法可中英混合;避免无意义注释。
4.8 链式 API
公共变更方法尽量 return this:addToLayer / addToViewer / setStyle / on 等。
5. 扩展清单(Checklist)
新增 Overlay
- 在
overlay/entity|primitive|html/新建类文件(按 4.2 模板)。 Overlay.registerType('name')。overlay/index.ts导出。- 根
index.tsimport + export。 apps/demo/src/overlay/...增加演示页并挂路由/菜单。apps/docs/core/overlay/...增加 md(可选但推荐)。- 跑
pnpm run core:lib确认类型与打包通过。
新增 Layer
- 继承
Layer,设置_delegate与LayerType。 layer/index.ts+ 根index.ts。- demo + docs。
- 若依赖新 Provider,注意异步
_addHandler(参考 TerrainLayer)。
新增 Analysis
- 继承
Analysis,文件放analysis/。 analysis/index.ts+ 根index.ts。- 注意:分析类通常不走 Layer 缓存,自行管理 Entity/Primitive,并在销毁时释放。
新增 Effect
- 继承
Effect,shader 放effects/shader/。 effects/index.ts导出;若需对外公开再写入根index.ts(当前仅部分 Effect 对外导出)。
新增 Widget
- 继承
Widget,样式放assets/css/。 widget/index.ts+ 根index.ts。- 需要默认随 Viewer 创建时改
viewer/Viewer.ts/config.ts(谨慎)。
修改 Viewer 默认行为
- 默认 options 只改
viewer/config.ts的DEF_OPTS。 - 构造副作用写在
Viewer构造函数或_init,保持幂等与可配置开关。
6. 依赖与构建注意
- Cesium:由 monorepo 根
dependencies提供;core 的 vite 构建会 打进包(未 external),并 copycesiumStatic。 - 运行时:
index.ts会import 'cesium/.../widgets.css'与assets/css/index.scss,并尝试globalThis.Cesium = Cesium。 - 新依赖:写入
packages/core/package.json;优先精确版本(与仓库习惯一致)。 - 脚本:
pnpm run lib/ 根目录pnpm run core:lib:构建pnpm run check:vue-tsctypedoc:build:API 文档
- 包导出字段:
mainUMD、moduleES、types、style;exports["."]指向 ES + types。
SuperMap
superMap/ 为可选静态集成,经 exports["./superMap/*"] 与构建 copy 提供,不要与 Cesium 主路径强耦合逻辑混写,除非任务明确要求。
7. 测试与验证
- 当前 几乎无自动化单测;验证手段:
pnpm run core:lib构建成功pnpm run demo:serve手测对应页面- 开发模式 Viewer 挂到
globalThis.viewer/Store.viewer,便于控制台调试
- 新增复杂算法(分析、转换)时,鼓励补最小单测或 demo 可复现步骤;不要只改实现不给验证路径。
8. 反模式(不要做)
- 在 Overlay 里直接
viewer.entities.add,绕过 Layer。 - 业务侧到处使用
Cartesian3而不用Position。 - 忘记
registerType/ 忘记根index.ts导出导致「写了却 import 不到」。 - 在 core 内引入 element-plus、axios 业务接口、Vue 组件。
- 删除或改名 public API 而不做兼容说明(semver:破坏性变更应升版本并在 monorepo changelog/changeset 体现)。
- 大范围格式化无关文件、无关重构与任务混在同一提交。
- 把密钥、内网 token 写进仓库;影像 key 走配置/环境变量。
9. 常用代码锚点
| 需求 | 先读 |
|---|---|
| 改默认底图/控件 | viewer/config.ts, viewer/Viewer.ts |
| 新点线面 | overlay/entity/Point.ts 等 |
| 3D Tiles | overlay/primitive/Tileset.ts |
| 图层基类 | layer/Layer.ts |
| 事件枚举 | event/EventEnums.ts |
| 坐标转换 | utils/convertor/Transform.ts |
| 材质 | material/MaterialProperty.js, material/index.js |
| 公共导出 | index.ts |
| 演示写法 | apps/demo/src/** |
10. 提交与协作建议
- monorepo 使用 pnpm workspace + changesets;core 发包脚本
pub指向私有 registry。 - 文档三件套:
README.md— 人类快速上手AGENTS.md— AI/协作者扩展约定(本文)TODO.md— 已知缺口与规划
完成功能后自检:导出?demo?类型?销毁路径?是否破坏现有链式 API?