1. 页面概览
地图视图是 LightGotham 的空间情报展示页,路由 /gotham/map,对应源码 action/web/src/views/GothamMapPage.vue。页面用 Leaflet + OpenStreetMap 渲染地理要素(GET /map/features):点要素以彩色圆点(divIcon,免图片资源)、线要素以红色 polyline、面要素以紫色 polygon 展示,点击要素弹出详情(名称/描述/类型/区域/属性)。
左侧为操作面板:bbox 包围盒查询、新增要素(point/linestring/polygon)、要素列表(编辑/删除)、区域聚合统计(条形图)、图层控制(时空增强)——图层显隐、热力图(leaflet.heat,按当前视野)、轨迹回放(polyline + marker 动画)。一句话总结:地图视图是"要素浏览 + 空间检索 + 时空增强 + 要素维护"的地理情报工作台。
2. 访问入口
- 路由与菜单:
/gotham布局子路由path: 'map',nameGothamMap,标题「Gotham 地图视图」,requiresAuth: true;侧边栏第二项「地图视图」({ path: '/gotham/map', label: '地图视图' })。 - 认证与权限:请求经
gothamClient.js(baseURL/gotham-api/v1)附aip_token,401 自动 refresh 重放;/map/*在 protected 组,无 admin 角色限制。 - 端口与 API 前缀:Gotham 后端 18083,前端前缀
/gotham-api。
3. 界面布局
+------------------------------+------------------------------+
| 页头:Gotham 地图视图 要素<n> 取回条数▾ [刷新要素] alert |
+------------------------------+------------------------------+
| 左面板(map-sidebar 340px) | 右地图(map-wrap 640px) |
| bbox 包围盒查询[框选查询] | Leaflet 地图:点要素彩色圆点 |
| minLng/minLat/maxLng/maxLat| / 线要素红色polyline / 面要素|
| 新增要素(名称/类型/区域/坐标)| 紫色polygon / 热力 / 轨迹 |
| 属性JSON [新增要素] | |
| 要素列表(n):每行[编辑][删除] | |
| 区域聚合统计(区域名+条形+数量)| |
| 图层控制:图层显隐/热力图/ | |
| 轨迹回放(实体ID+回放/停止) | |
+------------------------------+------------------------------+
┌ 要素编辑弹窗:名称/描述/类型/坐标/区域/属性JSON ┐
│ [保存修改][取消] │
└──────────────────────────────────────────────────┘
各板块职责:
- 取回条数选择器:页头
取回条数下拉(200/500/1000,默认 200),作为GET /map/features的limit参数。 - bbox 包围盒查询:默认四角
115,39,118,41,按框选范围重拉要素并fitBounds。 - 新增要素:point 输入
lng,lat;linestring 输入lng,lat;lng,lat多段;polygon 以|分隔环、环内以;分隔点;成功后并入并刷新。 - 要素列表(编辑/删除):卡片列出当前已加载要素,每行「编辑」(弹窗修改,
PUT /map/features/:id)与「删除」(confirm后DELETE /map/features/:id);两者成功后重拉要素与图层。 - 区域聚合统计:
/map/aggregate/regions各区域计数,按最大值归一化成进度条。 - 图层控制(时空增强):图层显隐(
PUT /map/layers/:id);热力图按当前视野与网格数(默认 32)调/map/heatmap;轨迹回放按实体 ID 做 800ms 步进动画。
4. 交互元素
| 控件 | 位置 | 含义与作用 |
|---|---|---|
| 取回条数下拉 | 页头 | 选择 200/500/1000 作为 limit,切换即重拉 /map/features(后端默认 100,无上限) |
| 刷新要素按钮 | 页头 | 重拉 /map/features(带当前 limit)并渲染,随后刷新区域聚合 |
| bbox 框选查询 | 左侧面板 | 四个数值框必填,命中要素渲染并 fitBounds |
| 新增要素表单 | 左侧面板 | 名称*、geometry_type(point(点)/linestring(线)/polygon(面))、区域、坐标*、属性 JSON,提交 POST /map/features |
| 要素列表 | 左侧面板 | 列出已加载要素(名称/类型/区域),每行「编辑」「删除」按钮 |
| 要素编辑弹窗 | 要素列表 | 回填名称/描述/类型/坐标/区域/属性 JSON,保存时 PUT /map/features/:id;source_id/entity_id 为可选透传字段 |
| 要素删除 | 要素列表 | confirm 确认后 DELETE /map/features/:id,成功后重拉要素列表与图层 |
| 区域聚合统计 | 左侧面板 | 区域名 + 蓝色条形(归一化)+ 数量;空态「暂无聚合数据,点击刷新要素。」 |
| 图层列表 | 图层控制 | 勾选/取消即时 PUT /map/layers/:id 切 visible;空态「暂无图层,请新增。」 |
| 新增图层 | 图层控制 | 名称必填 + 类型(point/line/heat/entity),POST /map/layers |
| 热力图开关 + 刷新热力 | 图层控制 | 勾选「启用热力图(按当前视野)」后按 grid_size 拉 /map/heatmap;取消移除热力层 |
| 轨迹回放 / 停止回放 | 图层控制 | 实体 ID(默认 graph:person:zhy)「回放」红色虚线 polyline + marker 800ms 步进;「停止回放」清理 |
5. 后端关联
API 客户端:gothamClient.js,axios.create({ baseURL: '/gotham-api/v1', timeout: 30000 });请求拦截器注入 Bearer token,响应 401 自动 refresh 重放。
端点表:
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | /map/features | 要素列表,params limit(默认 100)/offset(默认 0);后端未设上限 |
| POST | /map/features | 新增要素 {name, description, geometry_type, coordinates, properties, region} |
| PUT | /map/features/:id | 更新要素(geo.UpdateFeatureRequest:name/description/geometry_type/coordinates/properties/source_id/entity_id/region;指针字段缺省不改、空串即清空) |
| DELETE | /map/features/:id | 删除要素 |
| GET | /map/features/bbox | bbox 框选,params minLng/minLat/maxLng/maxLat |
| GET | /map/aggregate/regions | 区域聚合统计 {region, count} |
| GET | /map/layers | 图层列表 |
| POST | /map/layers | 新增图层 {name, layer_type, visible: true} |
| PUT | /map/layers/:id | 更新图层 {visible}(显隐切换) |
| GET | /map/heatmap | 热力网格,params min_lng/max_lng/min_lat/max_lat/grid_size,返回 {lat, lng, intensity} |
| GET | /map/trajectory/:entity_id | 实体轨迹点列表 |
关键机制:
- divIcon 免图片资源:点要素用
L.divIcon+ 全局.g-dot样式画彩色圆点,颜色按properties.entity_type判定(org 橙 / ship 绿 / 其余蓝);popup 内容escapeHtml转义。 - 坐标解析(GeoJSON 语义):point 为
[lng, lat]逆转为 Leaflet[lat, lng];linestring 逐点映射;polygon 逐环逐点映射;fitBounds(pad 0.2)自动适配。 - 要素维护(编辑/删除):编辑弹窗只暴露后端
UpdateFeatureRequest支持的字段,提交PUT /map/features/:id;删除经confirm后DELETE /map/features/:id,两者成功后重拉要素列表与图层;失败弹出后端返回的error文案。 - 热力图按视野联动:
heatBounds()取当前地图getBounds()东南西北;grid_size默认 32(1~200),L.heatLayer(radius 30 / blur 18 / minOpacity 0.35)。 - 轨迹回放动画:
setInterval800ms 步进移动 marker 并setView(max(zoom,6)),结束/停止时清理定时器与图层。
6. 权限与安全
- 认证:全部请求走
aip_tokenBearer,401 自动 refresh 换发重放;刷新失效清 token 跳/login。 - 角色限制:
/map/*全部在 protected 组,无 admin 细分。 - 写操作防护:新增要素校验名称/坐标必填、坐标格式、属性 JSON;图层名称必填;编辑弹窗只暴露后端可更新字段。
7. 常见问题与排错
问题 1:地图底图空白但要素能显示
现象:地图区域空白,只有彩色圆点。
原因:OpenStreetMap 在线瓦片加载失败(无外网)。
处理:确认可访问 {s}.tile.openstreetmap.org;内网环境需替换 tileLayer 为内网瓦片源。
问题 2:新增要素报「点坐标格式:lng,lat」
现象:提交被前端拦截。
原因:坐标输入与 geometry_type 不匹配。
处理:point 输入如 116.4,39.9;linestring 输入如 116.4,39.9;121.4,31.2。
问题 3:热力图点了「刷新热力」没反应
现象:地图不出现热力层。
原因:未勾选「启用热力图(按当前视野)」,loadHeatmap 开头直接 return;或该视野无数据。
处理:先勾选启用热力图再点「刷新热力」;确认 /map/heatmap 返回非空网格。
问题 4:轨迹回放提示「该实体暂无轨迹点」
现象:实体 ID 正确但无轨迹。
原因:/map/trajectory/:entity_id 返回空数组。
处理:换成有轨迹数据的实体(如默认 graph:person:zhy),或先在「情报工作台」确认实体存在。
8. 已知缺陷与边界
| 项 | 说明 |
|---|---|
| 依赖在线瓦片 | 底图为 OpenStreetMap,离线/内网环境底图空白 |
| bbox 默认值写死 | 初始 bbox 为华北四角,不感知当前视野 |
| 要素列表无翻页 | 页头「取回条数」只调 limit(200/500/1000),后端虽接受 offset 但页面未做上一页/下一页 |
source_id/entity_id 未展示 | 编辑弹窗可透传这两个字段,但列表不显示其当前值(后端 GeoFeature 有这两个字段) |
注:图层勾选不真正过滤要素已于 2026-09-06 修复(按图层归属过滤并真实重绘,heat 联动)。
注:地图 popup 内容转义已于 2026-09-10 修复(动态字段 HTML 转义,XSS 防护)。
注:2026-09-13 要素维护修订——新增「要素列表(编辑/删除)」卡片(PUT/DELETE /map/features/:id,路由见 server/server.go:556-558;编辑字段取 geo.UpdateFeatureRequest,见 geo/service.go:65-74);页头新增「取回条数」下拉(limit 200/500/1000,后端默认 100、无上限,见 server/handlers_geo.go:18-38);新增/编辑/渲染补齐 polygon 面要素。