地图字段(MapField)设计方案¶
地图字段用于在表单中嵌入交互式地图,支持用户在地图上标记点位、绘制路径与区域、填写地址与备注,并将结果以 JSON 字符串形式持久化到文档 Item 中。
| 层次 | 实现位置 |
|---|---|
| 后端 / Java | cn.myapps.core.runtime.dynaform.form.ejb.MapField(obpm-core/.../form/ejb/MapField.java) |
| 表单设计器 | MapField.js(scope: mapField,obpm-designer-vue3 字段模块) |
| 前端运行时(PC) | <o-map>(obpm-runtime-web/portal/vue3/src/components/field/o_map.vue) |
| 前端运行时(移动端) | o_map.vue(obpm-runtime-mobile-vue3/src/components/o_map.vue) |
表单 XML 中字段标签名为 mapfield,解析时映射到 MapField 类;运行时通过 toAttributes 将配置下发至 o-map 组件。
后端定义(Java)¶
MapField 继承 FormField,实现 ValueStoreField 接口,表示该字段值会写入文档 Item 并持久化到数据库。
专有属性¶
| 属性 | 类型 | 说明 |
|---|---|---|
openType |
String |
地图打开/展示方式。dialog:弹窗模式;其他值(默认 iframe):内嵌模式 |
valueType |
String |
数据存储类型(几何语义),决定字段值 JSON 的结构与地图交互模式。可选:Point、MultiPoint、LineString、Bounds、Polygon;默认 Point。后端常量见 MapField.VALUE_TYPE_* |
defaultCenterAddress |
String |
默认中心地址。字符串存储,整段地址文本,格式如「中国北京市市辖区东城区」。地图初次打开时作为 geocoder 关键字定位初始中心;为空时使用固定默认坐标 |
level |
String |
默认缩放级别。天地图 zoom,取值 1–18;未配置时 getter 兜底 "4" |
valueType 取值说明¶
| valueType | 含义 | 典型场景 | 目标 JSON type |
|---|---|---|---|
Point |
单坐标点 / 单标记点 | 地址选点、单点定位 | "Point" |
MultiPoint |
多坐标点 / 多标记点 | 批量标注、门店分布、巡检点位 | "MultiPoint" |
LineString |
路径 / 轨迹 | 路线规划、移动轨迹、道路 | "LineString" |
Bounds |
矩形可视范围 | 地图视口、矩形围栏 | "Bounds" |
Polygon |
多边形区域 | 不规则围栏、行政区范围 | "Polygon" |
设计器配置 valueType 后,后端通过 toAttributes / toPrintAttributes 将 valueType 下发至运行时;o-map 据此限制可绘制的几何类型,并按对应结构读写 value。旧版标记点数组在读取时兼容为 MultiPoint。
默认缩放级别(level)¶
| 规则 | 说明 |
|---|---|
| 存储 | 字符串,如 "4"、"12" |
| 取值范围 | 1–18,与天地图 zoom 一致 |
| getter | 未配置或无效时返回 "4" |
| 设计器 UI | el-select 绑定 levelNumber,选项来自 zoomLevels(1–18),选项文案 i18n 键 view.zoom_level_options.{level};变更时通过 onLevelChange 写回 level |
继承自 FormField 的常用属性¶
| 属性 | 说明 |
|---|---|
name |
字段名,对应文档 Item 名称 |
fieldtype |
值类型,设计器默认为 VALUE_TYPE_TEXT(文本) |
discript |
字段描述 |
hiddenScript / hiddenValue |
隐藏条件脚本及隐藏时显示值 |
hiddenPrintScript / printHiddenValue |
打印隐藏条件及打印隐藏显示值 |
readonlyScript |
只读条件脚本 |
calculateOnRefresh / onlyCalculate |
重计算相关 |
mobile |
移动端适配 |
instantValidate / validateLibs |
即时校验 |
渲染输出¶
MapField 在不同场景下输出不同 HTML / 属性:
| 方法 | 场景 | 行为 |
|---|---|---|
toHtmlTemplate |
Vue3 表单模板 | 输出 <o-map id="..."></o-map> |
toAttributes |
Vue3 运行时属性 | 输出 id、name、value、openType、displayType 等属性 Map |
toHtml / toPreviewHtml |
传统 HTML 模式 | 输出 type='hidden' 的 <input moduleType='mapField'>,携带 openType、displayType、value 等 |
toGridHtmlText |
列表/网格视图 | 不支持,显示红色提示 {*[cn.myapps.runtime.dynaform.view.GridNotSupportMapField]*} |
toPrintHtmlTxt |
打印 | 隐藏时返回 printHiddenValue,否则为空 |
toPdfHtmlTxt |
PDF 导出 | 输出地图图标 <img src=".../mapfield/img.png"> |
openType 与 HTML 属性映射¶
if (openType == "dialog" || openType.equals("dialog")) {
html.append("display='true'"); // 弹窗模式
} else {
html.append("nodialog='true'"); // 内嵌模式(默认 iframe)
}
toAttributes 输出字段¶
运行时前端通过 toAttributes 获取以下关键属性:
id、divId、docId、formIdname、fieldtype、layoutTypedisplayType(权限显示类型)value(文档 Item 值,JSON 字符串)openTypevalueType(数据存储类型,Point/MultiPoint/LineString/Bounds/Polygon,默认Point)defaultCenterAddress(默认中心地址,整段地址字符串)level(默认缩放级别,天地图 zoom 1–18,默认"4")hiddenValue、hiddenScriptformField(固定为MapField)mobile、instantValidate、validateLibs、calculateOnRefresh
权限显示类型(displayType)¶
getDisplayType 按以下优先级判定:
- HIDDEN(隐藏):流程字段权限为隐藏,或隐藏脚本返回 true
- DISABLED(屏蔽):文档不可编辑
- READONLY(只读):流程字段权限为只读,或只读脚本返回 true
- MODIFY(修改):默认可编辑
前端 o-map 组件根据 displayType 分别渲染:隐藏占位、只读/屏蔽地图、可编辑地图(含弹窗/内嵌两种 openType)。
设计器配置¶
表单设计器字段模块为 MapField.js(scope: mapField),在表单「内容」页签拖拽或插入地图字段后,于属性面板配置以下项:
| 属性 | 默认值 | 说明 |
|---|---|---|
name |
地图{N} |
字段名称 |
opentype |
iframe |
打开方式:iframe(嵌入到页面)/ dialog(弹窗) |
maptype |
tianditu |
地图插件,固定为天地图(tianditu) |
valueType |
Point |
数据存储类型:Point / MultiPoint / LineString / Bounds / Polygon(表单 XML 属性 valuetype,后端已实现) |
defaultCenterAddress |
空 | 默认中心地址,整段文本字符串(如 中国北京市市辖区东城区) |
level |
'4' |
默认缩放级别。el-select 下拉选择,选项 1–18(zoomLevels),文案 i18n 键 view.zoom_level_options.{level};保存至 MapField.level |
calculateonrefresh |
false |
刷新时重计算 |
onlyCalculate |
false |
仅计算不存值 |
discript |
空 | 描述 |
hiddenscript / hiddenvalue |
空 | 隐藏条件与隐藏显示值 |
hiddenprintscript / printhiddenvalue |
空 | 打印隐藏条件与显示值 |
设计器属性名与后端 Java 属性存在大小写差异(如 opentype → openType),保存至表单 XML 时由字段模块映射。
前端运行时(PC)¶
PC 端运行时组件为 <o-map>(o_map.vue),由 NormalForm 动态模板渲染;移动端为独立 o_map.vue 实现,部分能力与 PC 存在差异(见 已知限制与注意事项)。
后端配置在前端的消费¶
| 后端 / 设计器来源 | 前端行为 |
|---|---|
displayType |
隐藏占位 / 只读屏蔽 / 可编辑地图 |
openType |
dialog 弹窗打开地图;其他值内嵌 iframe |
valueType |
限制可绘制几何类型,决定读写 JSON 结构 |
defaultCenterAddress + level |
初始视口中心与缩放级别 |
value |
文档 Item 中的 JSON 字符串,解析后渲染几何与标记 |
地图引擎¶
- PC 端:天地图 API 4.0(矢量
vec/ 影像img) - 移动端:天地图(
obpm-runtime-mobile-vue3/src/components/o_map.vue)
初始视口¶
地图加载前,前端读取 defaultCenterAddress 作为关键字,调用天地图 geocoder API 定位初始中心,并使用 level 作为初始 zoom(无效或未配置时兜底 "4");若未配置默认地址或 geocoder 无结果,则使用固定默认坐标(广州附近)及 level 作为 zoom。
openType 展示差异¶
| openType | 展示方式 |
|---|---|
dialog |
显示按钮,点击后弹出对话框内嵌地图 |
其他(iframe) |
直接在表单中内嵌地图区域 |
交互操作¶
可编辑模式(displayType = MODIFY)下,地图上方显示操作栏。选点模式外显示 添加,选点模式内显示 添加完成(二者互斥,按状态切换);其后为 清除、查询。不使用右键添加。
| 按钮 | 说明 |
|---|---|
| 添加 | 非选点模式时显示。点击进入选点模式,**左键点击地图**添加或继续编辑几何数据;点类型标记会逆地理编码获取地址 |
| 添加完成 | 选点模式时显示。退出选点模式。Polygon 且顶点 ≥ 3 时确认保存当前多边形;未完成的 Bounds 选点(仅第一点)会被取消 |
| 清除 | 清空当前字段全部几何数据并退出选点模式 |
按 valueType 的选点行为:
| valueType | 选点模式下的地图左键点击行为 |
|---|---|
Point |
设置/替换单个标记点,点击「添加完成」退出选点模式 |
MultiPoint |
添加一个标记点,可连续点击地图追加多点,点击「添加完成」退出 |
LineString |
按顺序追加路径节点,点击「添加完成」退出 |
Bounds |
依次选择对角两点确定矩形范围,点击「添加完成」退出 |
Polygon |
依次追加顶点(至少 3 个),首尾自然连线闭合;点击「添加完成」保存并退出 |
Point、MultiPoint 标记点在地图上 常驻显示标题(title)与内容(detail)(有值时以文字标签显示在标记点上方,两行换行展示);点击标记仍可打开信息窗口编辑标题与内容。标记点以及 LineString、Bounds、Polygon 的几何顶点,在可编辑模式下均 可拖动;拖动后更新坐标(标记点同步逆地理编码地址)并写回字段值。其中 LineString、Bounds、Polygon 的顶点以 圆形句点 样式显示;点击句点选中**后句点高亮,并在句点 **右侧显示删除图标,点击删除图标可移除对应节点(Bounds 删除角点即清除整个矩形范围)。点击地图空白处取消选中。
其他操作¶
- 点击标记:弹出信息窗口,可编辑标题(
title)、内容(detail);确认后更新地图上的标题与内容标签 - 搜索:支持经纬度定位、关键字地址搜索(天地图 geocoder API)
- 地图/混合:切换矢量底图与卫星影像
当前 value 存储格式¶
字段值以 JSON 字符串 存入文档 Item(fieldtype = VALUE_TYPE_TEXT)。
当前运行时(o_map.vue)实际使用的是 标记点数组(语义上对应 MultiPoint),而非下方规划中的 GeoJSON 结构:
[
{
"id": 1,
"lng": 113.27,
"lat": 23.13,
"address": "广东省广州市天河区...",
"title": "标记标题",
"detail": "标记详细内容",
"isShow": true
}
]
| 字段 | 类型 | 说明 |
|---|---|---|
id |
Number |
标记唯一 ID,前端自增 |
lng |
Number |
经度(WGS84 / GCJ-02,取决于地图 API) |
lat |
Number |
纬度 |
address |
String |
逆地理编码地址 |
title |
String |
用户填写的标记标题 |
detail |
String |
用户填写的标记内容 |
isShow |
Boolean |
是否显示 |
空值或未标记时存储为空字符串 "" 或空数组 []。
目标 value 存储格式(规划)¶
按 valueType 区分五类几何数据:单点、多点、路径(线)、矩形范围、多边形区域。
以下为 规划中的统一 JSON 结构,由字段专有属性 valueType 指定;MapField 后端已支持 valueType 定义与下发,o-map 组件尚未按类型读写,迁移时需兼容上方当前标记点数组格式。
| valueType | JSON 根字段 type |
说明 |
|---|---|---|
Point |
"Point" |
单个坐标点 |
MultiPoint |
"MultiPoint" |
多个坐标点集合 |
LineString |
"LineString" |
有序路径点列 |
Bounds |
"Bounds" |
min_lng / min_lat / max_lng / max_lat 矩形 |
Polygon |
"Polygon" |
多边形顶点序列(首尾自然连线闭合,不重复存储闭合点) |
基础几何定义(统一标准)¶
采用 WGS84 经纬度(lng 经度,lat 纬度),统一单位:十进制小数。
- 单点:
Point(lng, lat) - 多点:无序或有序点集合
MultiPoint[(lng1,lat1),(lng2,lat2)...] - 路径 / 轨迹:有序点集合
LineString[(lng1,lat1),(lng2,lat2)...] - 地图范围:
- 矩形边界(可视框):
min_lng, min_lat, max_lng, max_lat - 多边形区域(行政 / 围栏):
Polygon[(lng,lat)...],按顺序连线,最后一个点与第一个点自然闭合
坐标点/点位 Point(单点)¶
通用结构体:
extra 为扩展字段,可存放高度、速度、地址等。
多点 MultiPoint(多标记点)¶
多个独立坐标点,每点可携带独立扩展信息;与当前运行时标记点数组语义一致:
{
"type": "MultiPoint",
"data": {
"points": [
{
"id": 1,
"lng": 113.27,
"lat": 23.13,
"extra": {
"address": "广东省广州市天河区...",
"title": "标记标题",
"detail": "标记详细内容",
"isShow": true
}
},
{
"id": 2,
"lng": 113.28,
"lat": 23.14,
"extra": {
"address": "广东省广州市越秀区...",
"title": "标记标题 2",
"detail": "标记详细内容 2",
"isShow": true
}
}
]
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
id |
Number |
标记唯一 ID,前端自增 |
lng |
Number |
经度 |
lat |
Number |
纬度 |
extra.address |
String |
逆地理编码地址 |
extra.title |
String |
用户填写的标记标题 |
extra.detail |
String |
用户填写的标记内容 |
extra.isShow |
Boolean |
是否显示 |
points 为空数组时表示无标记。
地图路径 LineString(轨迹 / 路线 / 道路)¶
路径是有序连续点,必须保留顺序,支持分段、里程、时间序列:
{
"type": "LineString",
"data": {
"points": [
{
"lng": 113.27,
"lat": 23.13,
"time": 1786000000
},
{
"lng": 113.28,
"lat": 23.14,
"time": 1786000010
}
],
"distance": 1250.3,
"start_point": {
"lng": 113.27,
"lat": 23.13
},
"end_point": {
"lng": 113.28,
"lat": 23.14
},
"bounds": {
"min_lng": 113.27,
"min_lat": 23.13,
"max_lng": 113.28,
"max_lat": 23.14
},
"extra": {}
}
}
distance:总长度(米)bounds:路径自身包围盒extra:路况、速度、路线类型等
矩形可视范围 Bounds¶
{
"type": "Bounds",
"data": {
"min_lng": 113.26,
"min_lat": 23.11,
"max_lng": 113.30,
"max_lat": 23.16,
"zoom": 12,
"source": "前端视口/区域围栏"
}
}
多边形区域 Polygon(不规则围栏、行政区)¶
{
"type": "Polygon",
"data": {
"points": [
[113.26, 23.11],
[113.30, 23.11],
[113.30, 23.16],
[113.26, 23.16]
],
"bounds": {
"min_lng": 113.26,
"min_lat": 23.11,
"max_lng": 113.30,
"max_lat": 23.16
}
}
}
多边形 points 按顺序存储顶点,不在末尾重复第一个点;地图渲染与几何计算时,最后一个点与第一个点自动连线形成闭合区域。bounds 为多边形外接矩形,用于快速过滤。
当前格式 → 目标格式映射¶
| 当前字段 | valueType | 目标结构 |
|---|---|---|
标记点数组 [{lng, lat, address, title, detail}] |
MultiPoint |
{ "type": "MultiPoint", "data": { "points": [{ "id", "lng", "lat", "extra": { "address", "title", "detail", "isShow" } }] } } |
| 单点选点(规划) | Point |
{ "type": "Point", "data": { "lng", "lat", "extra": { "address", "title", "detail" } } } |
| 无路径支持 | LineString |
见上文 LineString 结构 |
| 无视口/围栏 | Bounds / Polygon |
见上文 Bounds / Polygon 结构 |
已知限制与注意事项¶
- 列表视图不支持:
toGridHtmlText直接返回不支持提示,视图中无法展示地图字段内容 - 打印/PDF:打印模式不渲染地图,PDF 仅显示地图图标
- 移动端只读/屏蔽:移动端
o-map在只读和屏蔽状态下不渲染地图区域 - 格式演进:
o-mapPC 端已按valueType读写;移动端尚未同步;旧版标记点数组读取时兼容为MultiPoint