# Map 模块说明（通用组件）

## 1. 操作使用说明（业务集成）
### 引入示例
```vue
<AfMap
  ref="mapTool"
  mapConfigName="GisHomeConfig" // 必填：配置名
  serviceName="af-linepatrol"     // 可选：默认取 VUE_APP_SYSTEM_NAME
  @inited="onInited"
  @loading-change="onLoading"
  @dock-click="onDockClick"       // 仅 custom=true 的 dock 会上抛
  @button-click="onButtonClick"   // 仅 custom=true 的业务按钮会上抛
  @wms-click="onWmsClick"         // WMS 点击查询结果
/>
```

### 事件说明
- `inited`：地图初始化完成。
- `loading-change(loading)`：内部加载态。
- `engine-change(engine)`：引擎切换完成。
- `dock-click(payload)`：当按钮配置 `custom: true` 时抛给父组件，payload 形如 `{ click, text, visible, custom, ...btn }`。
- `button-click(item)`：当业务按钮配置 `custom: true` 时抛给父组件。
- `wms-click(data)`：WMS 点击查询返回的特征信息。

### 内外职责
- **内部处理**：所有非 `custom=true` 的 dock/业务按钮（测量、底图、选择、定位、图幅定位等），组件内完成逻辑与 UI（含业务卡片、定位卡片）。
- **父组件处理**：`custom=true` 的功能（如设备图层面板）透传到父组件，由父组件决定 UI/行为。

### ref 常用方法
- 数据：`addMarker`、`drawPolygon`、`addWmsLayer`、`clearLayer`
- 视图：`fitView`、`zoomIn/Out`、`enableZoomToBox/disableZoomToBox`、`setMapViewMode`
- 底图：`switchBaseMap('gaode'|'gaodeSat'|'tdtVec'|'tdtImg')`（AMap 仅支持前两种）
- 组：`setGroupVisible`、`getGroups` / `getGroupsByType` / `getGroupsByGroupType`
- 选择/测量：`startRectangleSelect`、`startCircleSelect`、`startPolygonSelect`、`startDistanceMeasure`、`startAreaMeasure`、`clearSelectResults`、`clearMeasureResults`
- WMS 点击：`setWmsClickEnabled(enabled)`（开启后内部处理并通过 `wms-click` 上抛结果）

### 配置要求（mapConfig）
- `MAP_ENGINE`: `AMAP` / `OPENLAYERS`
- `MAP_OPTIONS`: 初始化视图参数（center/zoom 等）
- `toolButton`: dock/按钮配置，支持 `custom` 字段决定是否上抛父组件

### 快速排查
- 看不到数据：确认 `groupId/groupName` 与添加时一致；切换引擎后需要重新 add 数据。
- 底图异常：AMap 不支持 `tdtVec/tdtImg`。
- WMS 查询无结果：检查 `getWmsFeatureInfoUrl` 是否可访问及 CORS。

## 2.（实现/扩展）
### 架构
- 双内核：AMap / OpenLayers，经 `mapKernelFactory` 创建 adapter（`AMapAdapter`、`OLAdapter`），统一接口定义在 `MapAdapter`。
- `mapService`：单例外观，封装所有对内核的调用与状态。
- 组件 `index.vue`：负责 UI & 事件分发，核心操作调用 `mapService`。

### 事件与 custom 约定
- Dock/按钮配置里的 `custom: true` 直接 `$emit` 给父组件；否则在组件内部处理。
- `handleDockClick` 用 `willOpen = this.activeDock !== action` 判断本次点击是"打开"还是"关闭"，同步 `activeDock`、业务卡片、定位卡片。
- 内部业务按钮完成后按需清空 `activeButton`，避免状态残留。

### 状态管理与关闭逻辑
- **基础组件（map/index.vue）**：
  - `closeAllActiveTools()`：统一关闭所有激活的工具和状态（测量、选择、业务卡片、定位卡片等）
  - `cancelActiveTool()`：关闭当前激活的工具功能（框选、测量、选择等）
  - 每次点击新的 dock 按钮时，`handleDockClick` 会先调用 `closeAllActiveTools()` 清理之前的状态

- **父组件（业务层）**：
  - `closeAllActiveBusiness()`：统一关闭所有激活的业务功能（ModeManager、业务卡片、数据筛选面板等）
  - `cancelActiveTool()`：关闭当前激活的业务功能（保留用于向后兼容）
  - 每次接收到 dock 点击事件时，`handleDockClick` 会先调用 `closeAllActiveBusiness()` 清理之前的状态

- **关闭流程**：
  1. 用户点击 dock 按钮 → 基础组件 `handleDockClick` 先调用 `closeAllActiveTools()` 清理内部状态
  2. 如果是 `custom=true`，事件上抛到父组件 → 父组件 `handleDockClick` 先调用 `closeAllActiveBusiness()` 清理业务状态
  3. 然后根据配置打开新的功能，确保状态干净，避免残留

### 重要 Props
- `mapConfigName`：必填，从 `getConfigByNameAsync(mapConfigName, serviceName)` 读取。
- `serviceName`：可选，默认 `process.env.VUE_APP_SYSTEM_NAME`，用于多系统区分配置源。

### 扩展指引
- 新增业务按钮：在配置 `toolButton` 中添加。若需父组件处理设 `custom: true`；否则在 `handleButtonAction` 实现逻辑。
- 新增 dock：同上，按 `custom` 决定归属；若内部处理需补充对应动作。
- WMS 查询：`setWmsClickEnabled` + `getWmsFeatureInfoUrl`；必要时在 adapter 扩展 URL 拼装/坐标系处理。

### 注意事项
- AMap 仅支持 `gaode/gaodeSat` 底图。
- 引擎切换会清理测距数据，业务层需重新添加业务层数据。
- 组刷新依赖 `getDataFn`，需保证可并发且返回最新数据。
- 服务端需支持跨域（WMS/瓦片）或走同源代理。

### 快速排查
- 显隐异常：确认 `setGroupVisible` 的 `groupId` 与添加时一致。
- 选择/测量残留：调用 `clearSelectResults` / `clearMeasureResults`。
- custom 功能无响应：检查配置是否设 `custom: true`，以及父组件事件监听是否到位。

