@ywbgn/bgl-package 1.1.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ywbgn/bgl-package
2
2
 
3
- 基于 Vue 3 与 `@arcgis/core` 的地图组件库:地图初始化、底图切换、底图卷帘、工具栏(全图、全屏、缩放、定位、测距、测面、图层管理、业务卷帘、地图标注、条件查询),业务图层加载 / Portal Token 注册,以及平移边界约束(`panBounds` / `applyPanBoundsConstraint`)。
3
+ 基于 Vue 3 与 `@arcgis/core` 的地图组件库:地图初始化、底图切换、底图卷帘、工具栏(全图、全屏、缩放、上一/下一视图、定位、测距、测面、图层管理、业务卷帘、地图标注、条件查询、TXT 画图)、**空间分析面板**(`SpatialAnalysisPanel`)、通用表格(`BglDataTable`),业务图层加载 / Portal Token 注册与续期,以及平移边界约束(`panBounds` / `applyPanBoundsConstraint`)。
4
4
 
5
5
  ## 安装依赖
6
6
 
@@ -27,18 +27,32 @@ app.use(VueArcgisMap)
27
27
  app.mount('#app')
28
28
  ```
29
29
 
30
+ 组件库自身样式:ESM 入口构建时已注入 CSS;按需 / UMD 或样式丢失时再显式引入:
31
+
32
+ ```js
33
+ import '@ywbgn/bgl-package/style.css'
34
+ ```
35
+
30
36
  按需引入(不全局注册):
31
37
 
32
38
  ```js
33
39
  import {
34
40
  ArcgisMap,
35
41
  BasemapSwitch,
42
+ LayerSwitch,
36
43
  SwipeCompare,
37
44
  MapToolbar,
45
+ SpatialAnalysisPanel,
46
+ BglInput,
47
+ BglSelect,
48
+ BglDataTable,
38
49
  provideBasemapKeys,
39
50
  loadBusinessLayers,
51
+ setPendingBusinessLayers,
40
52
  registerPortalToken,
53
+ registerPortalAccessToken,
41
54
  startPortalTokenRenewal,
55
+ startPortalTokenRenewalWithFetcher,
42
56
  applyPanBoundsConstraint,
43
57
  goToFullExtent
44
58
  } from '@ywbgn/bgl-package'
@@ -48,7 +62,10 @@ import type {
48
62
  MapReadyPayload,
49
63
  ToolbarToolId,
50
64
  LonLatExtent,
51
- PanConstraintHandle
65
+ PanConstraintHandle,
66
+ MapBounds,
67
+ BglDataTableColumn,
68
+ BglDataTableRow
52
69
  } from '@ywbgn/bgl-package'
53
70
  ```
54
71
 
@@ -56,9 +73,9 @@ import type {
56
73
 
57
74
  1. 先拿到底图密钥 / 系统参数(含 `minZoom` / `maxZoom` / 经纬度范围),再挂 `ArcgisMap`(密钥只在挂载时读一次,可用 `v-if` 等配置就绪后再渲染)。
58
75
  2. `@ready` 里用 `shallowRef` 保存 `view` / `sketchLayer` / `map`。
59
- 3. 需要时再挂 `BasemapSwitch`、`SwipeCompare`、`MapLegend`、`MapScaleBar`、`MapToolbar`。
76
+ 3. 需要时再挂 `LayerSwitch`、`BasemapSwitch`、`SwipeCompare`、`MapLegend`、`MapScaleBar`、`MapToolbar`;空间分析挂 `SpatialAnalysisPanel`(不在工具栏内)。
60
77
  4. 有经纬度范围时:给 `ArcgisMap` 传 `:pan-bounds`(自动限制拖动),给 `MapToolbar` 传 `:home-extent`(全图回到范围中心 + minZoom)。
61
- 5. 在 `ready` `startPortalTokenRenewal`(或 `registerPortalToken`)→ `loadBusinessLayers`;卸载时对续期调用 `stop()`。
78
+ 5. 在 `ready` 后登记 Portal Token(生产用 `startPortalTokenRenewalWithFetcher`,内网联调可用 `startPortalTokenRenewal`)→ `loadBusinessLayers`;默认隐藏层用 `setPendingBusinessLayers`;卸载时对续期调用 `stop()`。
62
79
  6. 切底图前同时拆除**底图卷帘**与**工具栏业务卷帘**。
63
80
 
64
81
  ```vue
@@ -76,6 +93,7 @@ import type {
76
93
  @ready="onReady"
77
94
  />
78
95
  <template v-if="view && sketchLayer">
96
+ <LayerSwitch :view="view" />
79
97
  <BasemapSwitch :view="view" @before-change="onBeforeBasemapChange" />
80
98
  <SwipeCompare ref="swipeCompareRef" :view="view" />
81
99
  <MapLegend :view="view" position="left" :offset-x="12" :offset-y="14" />
@@ -97,6 +115,7 @@ import type GraphicsLayer from '@arcgis/core/layers/GraphicsLayer.js'
97
115
  import {
98
116
  ArcgisMap,
99
117
  BasemapSwitch,
118
+ LayerSwitch,
100
119
  MapLegend,
101
120
  MapScaleBar,
102
121
  MapToolbar,
@@ -165,6 +184,168 @@ const onBeforeBasemapChange = () => {
165
184
 
166
185
  ## 组件说明
167
186
 
187
+ ### 通用输入组件
188
+
189
+ 组件库提供统一深色主题样式的 `BglInput`、`BglSelect` 和 `BglDataTable`,支持全局注册或按需引入。使用组件前请引入组件库样式:
190
+
191
+ ```ts
192
+ import '@ywbgn/bgl-package/style.css'
193
+ ```
194
+
195
+ 使用 `app.use(VueArcgisMap)` 全局注册后,可以直接在模板中使用:
196
+
197
+ ```vue
198
+ <template>
199
+ <BglInput v-model="keyword" placeholder="请输入关键字" />
200
+ <BglSelect v-model="status" :options="statusOptions" placeholder="请选择状态" />
201
+ </template>
202
+
203
+ <script setup lang="ts">
204
+ import { ref } from 'vue'
205
+
206
+ const keyword = ref('')
207
+ const status = ref('')
208
+ const statusOptions = [
209
+ { value: 'active', label: '有效' },
210
+ { value: 'inactive', label: '无效' }
211
+ ]
212
+ </script>
213
+ ```
214
+
215
+ 按需引入时,在页面组件中直接导入:
216
+
217
+ ```ts
218
+ import { BglInput, BglSelect, BglDataTable } from '@ywbgn/bgl-package'
219
+ ```
220
+
221
+ #### BglInput
222
+
223
+ ```vue
224
+ <BglInput
225
+ v-model="year"
226
+ type="number"
227
+ min="1900"
228
+ max="2200"
229
+ placeholder="请输入年份"
230
+ :disabled="loading"
231
+ />
232
+ ```
233
+
234
+ | 属性 | 类型 | 默认值 | 说明 |
235
+ | --- | --- | --- | --- |
236
+ | `modelValue` | `string \| number` | `''` | `v-model` 双向绑定值 |
237
+ | `type` | `string` | `'text'` | 原生输入类型,例如 `text`、`number` |
238
+ | `placeholder` | `string` | `''` | 占位文案 |
239
+ | `disabled` | `boolean` | `false` | 是否禁用输入框 |
240
+ | `min` / `max` | `string \| number` | 无 | 原生数值范围属性 |
241
+
242
+ 输入内容变化时触发 `update:modelValue` 事件。即使 `type="number"`,组件发出的值仍是输入框产生的字符串,需要数值时请在业务侧自行转换。
243
+
244
+ #### BglSelect
245
+
246
+ 选项值和当前绑定值均使用字符串:
247
+
248
+ ```vue
249
+ <BglSelect
250
+ v-model="selectedStatus"
251
+ :options="statusOptions"
252
+ placeholder="请选择状态"
253
+ :disabled="loading"
254
+ />
255
+ ```
256
+
257
+ ```ts
258
+ const selectedStatus = ref('')
259
+ const statusOptions = [
260
+ { value: 'active', label: '有效' },
261
+ { value: 'inactive', label: '无效', disabled: true }
262
+ ]
263
+ ```
264
+
265
+ | 属性 | 类型 | 默认值 | 说明 |
266
+ | --- | --- | --- | --- |
267
+ | `modelValue` | `string` | `''` | 当前选中值,支持 `v-model` |
268
+ | `options` | `{ value: string; label: string; disabled?: boolean }[]` | `[]` | 下拉选项 |
269
+ | `placeholder` | `string` | `'请选择'` | 没有匹配选中值时的占位文案 |
270
+ | `open` | `boolean` | `false` | 是否展开下拉框,可用于受控展开 |
271
+ | `disabled` | `boolean` | `false` | 是否禁用下拉框 |
272
+
273
+ 组件事件:
274
+
275
+ - `update:modelValue(value)`:选中选项时触发,可通过 `v-model` 接收。
276
+ - `select(value)`:选中选项时触发,参数为选项的 `value`。
277
+ - `update:open(open)`:展开状态变化时触发。点击触发按钮、按 `Esc` 或点击组件外部时会更新为 `false`。
278
+
279
+ 需要由业务侧控制展开状态时:
280
+
281
+ ```vue
282
+ <BglSelect
283
+ :model-value="selectedStatus"
284
+ :options="statusOptions"
285
+ :open="selectOpen"
286
+ @select="selectedStatus = $event"
287
+ @update:open="selectOpen = $event"
288
+ />
289
+ ```
290
+
291
+ #### BglDataTable
292
+
293
+ 通用数据表格:固定表头 + 可滚动表体 + 可选底部固定区。表头与表体分表渲染,纵向滚动时表头不跟着动;列宽按内容测量后对齐。空间分析面板结果表即使用此组件,业务侧也可单独用于统计排行等场景。
294
+
295
+ 父容器需要有明确高度(或处于 flex 列布局且 `min-height: 0`),表体才能内部滚动。
296
+
297
+ ```vue
298
+ <BglDataTable
299
+ v-model:active-index="activeIndex"
300
+ :columns="columns"
301
+ :rows="rows"
302
+ align="center"
303
+ >
304
+ <template #footer>
305
+ <span>共 {{ rows.length }} 条</span>
306
+ </template>
307
+ </BglDataTable>
308
+ ```
309
+
310
+ ```ts
311
+ import { ref } from 'vue'
312
+ import type { BglDataTableColumn, BglDataTableRow } from '@ywbgn/bgl-package'
313
+
314
+ const activeIndex = ref(-1)
315
+ const columns: BglDataTableColumn[] = [
316
+ { title: '序号', key: 'index', width: '56px', render: (_row, index) => index + 1 },
317
+ { title: '名称', key: 'name' },
318
+ { title: '面积(亩)', key: 'area', render: (row) => Number(row.area || 0).toFixed(2) }
319
+ ]
320
+ const rows = ref<BglDataTableRow[]>([
321
+ { name: '示例牧户', area: 12.5 }
322
+ ])
323
+ ```
324
+
325
+ | 属性 | 类型 | 默认值 | 说明 |
326
+ | --- | --- | --- | --- |
327
+ | `columns` | `BglDataTableColumn[]` | `[]` | 列定义 |
328
+ | `rows` | `BglDataTableRow[]` | `[]` | 行数据 |
329
+ | `align` | `'left' \| 'center'` | `'left'` | 表头与单元格对齐 |
330
+ | `activeIndex` | `number` | `-1` | 当前高亮行下标,`-1` 表示无;支持 `v-model:active-index` |
331
+
332
+ `BglDataTableColumn`:
333
+
334
+ | 字段 | 类型 | 说明 |
335
+ | --- | --- | --- |
336
+ | `title` | `string` | 表头文案 |
337
+ | `key` | `string` | 列标识;默认从行对象取 `row[key]`,也作为单元格插槽名 |
338
+ | `width` | `string` | 可选列宽,如 `'48px'`;未测量前作为最小宽度 |
339
+ | `render` | `(row, index) => string \| number` | 可选单元格渲染;传入后优先于 `row[key]` |
340
+
341
+ 组件事件与插槽:
342
+
343
+ - `update:activeIndex(index)`:点击行时触发,可通过 `v-model:active-index` 接收。
344
+ - `#footer`:底部固定区;不传则不渲染。
345
+ - `#cell-<key>`:按列覆盖单元格内容,作用域为 `{ row, index, column, value }`。
346
+
347
+ 暴露方法:`scrollToTop()`,将表体滚回左上角(切换 Tab 等场景使用)。
348
+
168
349
  ### ArcgisMap
169
350
 
170
351
  | Prop / 能力 | 说明 |
@@ -180,10 +361,31 @@ const onBeforeBasemapChange = () => {
180
361
  - `panBounds` 在 view ready 后自动调用 `applyPanBoundsConstraint` + `wrapViewGoTo`;组件卸载时自动清理
181
362
  - 有 `panBounds` 时,初始会定位到范围中心 + `minZoom`(与「全图」一致)
182
363
 
364
+ ### LayerSwitch(图层显隐,独立入口)
365
+
366
+ 停靠在底图按钮**正上方**,与底图/卷帘同款 50×50 入口。点击弹出业务图层列表,用眼睛切换显隐。再点按钮或点击外部关闭。
367
+
368
+ 与工具栏「图层管理」独立:本组件只做显隐,不含排序 / 透明度 / 定位。
369
+
370
+ ```vue
371
+ <LayerSwitch :view="view" appearance="frame" />
372
+ ```
373
+
374
+ | Prop | 说明 |
375
+ | -------------- | ---------------------------------------------------------------- |
376
+ | `view` | 必填 |
377
+ | `idPrefix` | 业务层前缀,默认`bgl-biz-`(需与 `loadBusinessLayers` 一致) |
378
+ | `appearance` | `'plain'` \| `'frame'`,默认 `frame`。`plain` 为纯色圆角面板;`frame` 用切图九宫格铺背景 |
379
+
380
+ 待创建隐藏层会出现在列表中,点眼睛显示后才真正上图(与图层管理勾选行为一致)。
381
+
382
+ 默认 `left: 16px`、`bottom: 390px`(底图默认 330px 之上留 50+10 空隙),可用 `--bgl-layer-left` / `--bgl-layer-bottom` / `--bgl-layer-z` 覆盖。
383
+
183
384
  ### BasemapSwitch(底图切换)
184
385
 
185
386
  - 必填 `view`
186
387
  - 可选 `keys`
388
+ - 可选 `appearance`:`'plain'` \| `'frame'`,默认 `frame`(切图背景;工具栏弹框仍为 plain)
187
389
  - 事件 `before-change`:成功切换底图**前**触发(用于拆卷帘)
188
390
 
189
391
  可选底图:天地图影像 / 矢量、星图地球、吉林一号、ArcGIS 影像。缺 Key 时可选中,切换时会提示。
@@ -191,11 +393,12 @@ const onBeforeBasemapChange = () => {
191
393
  ### SwipeCompare(底图卷帘)
192
394
 
193
395
  - 左下角入口,对比**底图影像**
396
+ - 可选 `appearance`:`'plain'` \| `'frame'`,默认 `frame`(与底图弹框一致)
194
397
  - 方法 `destroySwipe()`:拆除 Swipe 并移除左侧对比层
195
398
 
196
399
  ### MapToolbar(工具栏)
197
400
 
198
- 内置工具:全图、全屏、放大、缩小、坐标定位、距离测量、面积测量、图层管理、业务图层卷帘、地图标注、条件查询。
401
+ 内置工具:全图、全屏、放大、缩小、上一视图、下一视图、坐标定位、距离测量、面积测量、图层管理、业务图层卷帘、地图标注、条件查询、TXT 画图。
199
402
 
200
403
  | Prop / 能力 | 说明 |
201
404
  | -------------------------- | ------------------------------------------------------------------------ |
@@ -214,7 +417,7 @@ const onBeforeBasemapChange = () => {
214
417
 
215
418
  工具 id(`ToolbarToolId`):
216
419
 
217
- `fullExtent` | `fullscreen` | `zoomIn` | `zoomOut` | `coordinateLocate` | `distanceMeasure` | `areaMeasure` | `layerManage` | `layerSwipe` | `mapLabel` | `conditionQuery`
420
+ `fullExtent` | `fullscreen` | `zoomIn` | `zoomOut` | `prevExtent` | `nextExtent` | `coordinateLocate` | `distanceMeasure` | `areaMeasure` | `layerManage` | `layerSwipe` | `mapLabel` | `conditionQuery` | `txtDraw`
218
421
 
219
422
  ```vue
220
423
  <MapToolbar
@@ -248,22 +451,25 @@ const coordinateSystemConfig = {
248
451
 
249
452
  | 工具 | 行为 |
250
453
  | ---- | ------------------------------------------------------------------------------------------------- |
251
- | 全图 | 有`homeExtent` 时:`goToFullExtent`(范围中心 + minZoom);否则用 `homeCenter` / 仅 minZoom |
252
- | 全屏 | 对`document.documentElement` 请求整页全屏(接近 F11),再次点击或 Esc 退出 |
454
+ | 全图 | 有`homeExtent` 时:`goToFullExtent`(范围中心 + minZoom);否则用 `homeCenter` / 仅 minZoom |
455
+ | 全屏 | 对`document.documentElement` 请求整页全屏(接近 F11),再次点击或 Esc 退出 |
456
+ | 上一视图 | 回退到上一次静止视野(平移 / 缩放后入栈,最多 30 条);无历史时按钮禁用 |
457
+ | 下一视图 | 前进到回退前的视野;无可前进记录时按钮禁用 |
253
458
 
254
459
  #### 内置面板说明
255
460
 
256
461
  | 工具 | 作用 | 注意 |
257
462
  | -------- | ---------------------------------------- | ---------------------------------------------------- |
258
- | 图层管理 | 业务层显隐、透明度、排序、定位 | 仅识别`layerIdPrefix` 前缀图层;若加载时做过坐标系校验,不一致图层会标记「坐标系不一致」 |
463
+ | 图层管理 | 业务层显隐、透明度、排序、定位 | 仅识别`layerIdPrefix` 前缀图层;待创建隐藏层会出现在列表中,勾选后才真正上图;若加载时做过坐标系校验,不一致图层会标记「坐标系不一致」 |
259
464
  | 卷帘对比 | 选左右**业务层**做 Swipe | 与底图卷帘互斥(应用时自动拆另一侧) |
260
465
  | 坐标定位 | 按所选坐标系输入或拾取坐标后定位 | `coordinateSystemConfig` 可由业务系统动态下发默认坐标系与可选项 |
261
466
  | 地图标注 | 按字段设置`labelingInfo` | 仅**FeatureLayer**;MapImageLayer 不出现在列表 |
262
467
  | 条件查询 | 拼 WHERE →`queryFeatures` → 定位高亮 | 仅 FeatureLayer;字段值去重最多约 1000 条 |
468
+ | TXT 画图 | 上传经纬度 txt,在地图上绘面并计算亩数 | 仅 `.txt`,≤ 10MB;自动识别「经度,纬度」或「纬度,经度」;打开面板期间会暂停 `panBounds`,关闭约 3 秒后恢复 |
263
469
 
264
470
  ### MapLegend(图例,独立常开)
265
471
 
266
- 与底图切换、卷帘一样单独挂载,**不在工具栏内**;默认常开,基于 ArcGIS `Legend` 微件。
472
+ 与底图切换、卷帘一样单独挂载,**不在工具栏内**;默认常开,基于 ArcGIS `LegendViewModel` 渲染。
267
473
 
268
474
  - 只展示业务图层(`idPrefix` 前缀,默认 `bgl-biz-`)
269
475
  - 排除 `listMode === 'hide'` 的图层(如绘制层)
@@ -275,19 +481,33 @@ const coordinateSystemConfig = {
275
481
  position="left"
276
482
  :offset-x="12"
277
483
  :offset-y="14"
484
+ appearance="plain"
278
485
  />
279
486
  ```
280
487
 
281
- | Prop | 说明 |
282
- | ------------ | ---------------------------------------------------------------- |
283
- | `view` | 必填 |
284
- | `idPrefix` | 业务层前缀,默认`bgl-biz-`(需与 `loadBusinessLayers` 一致) |
285
- | `position` | `'left'` \| `'right'`,默认 `left`(右侧有业务抽屉时用左) |
286
- | `offsetX` | 水平边距(px),默认`12` |
287
- | `offsetY` | 相对地图底边抬高(px),默认`14` |
488
+ 切图背景模式:
489
+
490
+ ```vue
491
+ <MapLegend
492
+ :view="view"
493
+ position="left"
494
+ :offset-x="12"
495
+ :offset-y="14"
496
+ appearance="frame"
497
+ />
498
+ ```
499
+
500
+ | Prop | 说明 |
501
+ | -------------- | ---------------------------------------------------------------- |
502
+ | `view` | 必填 |
503
+ | `idPrefix` | 业务层前缀,默认`bgl-biz-`(需与 `loadBusinessLayers` 一致) |
504
+ | `position` | `'left'` \| `'right'`,默认 `left`(右侧有业务抽屉时用左) |
505
+ | `offsetX` | 水平边距(px),默认`12` |
506
+ | `offsetY` | 相对地图底边抬高(px),默认`14` |
507
+ | `appearance` | `'plain'` \| `'frame'`,默认 `plain`。`plain` 为纯色圆角面板;`frame` 用切图九宫格铺背景 |
288
508
 
289
509
  默认尺寸 **150×240px**(可用 CSS 变量 `--bgl-legend-width` / `--bgl-legend-height` 覆盖)。
290
- 层级默认约 `1050`,可用 `--bgl-legend-z` 覆盖。
510
+ 层级默认 `100`(与底图切换、工具栏、比例尺一致),可用 `--bgl-legend-z` 覆盖。
291
511
 
292
512
  与比例尺同侧时,建议比例尺加大 `offsetX`(例如图例 `12`、比例尺 `170`),避免重叠。
293
513
 
@@ -342,6 +562,89 @@ const coordinateSystemConfig = {
342
562
  - 容器 `pointer-events: none`,不挡地图拖拽
343
563
  - 层级默认 `100`(与底图切换、图例、工具栏一致),可用 `--bgl-scalebar-z` 覆盖
344
564
 
565
+ ### SpatialAnalysisPanel(空间分析)
566
+
567
+ 独立面板,**不在工具栏内**。用于上传图斑、与九类业务图层叠加比对、统计压占面积,并导出 Word / TXT。可用工具栏 `#extra` 按钮控制显隐。
568
+
569
+ 叠加勾选项与图层 `title`(`BusinessLayerConfig.mapServiceName`)必须一致:
570
+
571
+ | 面板勾选 | 图层 title |
572
+ | -------- | ---------- |
573
+ | 确权 | 草场确权 |
574
+ | 草地 | 草地分布 |
575
+ | 林地 | 林地分布 |
576
+ | 湿地 | 湿地分布 |
577
+ | 耕地 | 耕地分布 |
578
+ | 保护区 | 保护区 |
579
+ | 林保图 | 林保图 |
580
+ | 生态红线 | 生态红线 |
581
+ | 基本草原 | 基本草原 |
582
+
583
+ 默认勾选「确权」。勾选时按 title 显示图层;若该层尚未上图(已用 `setPendingBusinessLayers` 登记),会现场物化后再显示。找不到图层时控制台警告,不中断。
584
+
585
+ ```vue
586
+ <SpatialAnalysisPanel
587
+ v-if="showAnalysis && map && view"
588
+ :map="map"
589
+ :view="view"
590
+ :system-coordinate-wkid="systemCoordinateWkid"
591
+ :map-bounds="mapBounds"
592
+ />
593
+ ```
594
+
595
+ ```ts
596
+ import type Map from '@arcgis/core/Map.js'
597
+ import type { MapBounds, MapReadyPayload } from '@ywbgn/bgl-package'
598
+
599
+ const showAnalysis = ref(false)
600
+ const map = shallowRef<Map | null>(null)
601
+ const systemCoordinateWkid = ref<number | null>(null)
602
+ const mapBounds = ref<MapBounds | null>(null)
603
+
604
+ const onReady = async (payload: MapReadyPayload) => {
605
+ map.value = payload.map
606
+ view.value = payload.view
607
+ // mapBounds.value = { jwXMin, jwXMax, jwYMin, jwYMax }
608
+ }
609
+ ```
610
+
611
+ | Prop | 说明 |
612
+ | ---- | ---- |
613
+ | `map` / `view` | 必填;用 `shallowRef`,不要 `ref()` |
614
+ | `systemCoordinateWkid` | 系统参数坐标系;`8848` 按 CGCS2000_Albers,其他按 WKID |
615
+ | `mapBounds` | `{ jwXMin, jwXMax, jwYMin, jwYMax }`,分析范围约束;不传则全球范围 |
616
+
617
+ 操作流程:
618
+
619
+ 1. 勾选叠加类型(默认确权)。
620
+ 2. 「选择文件」→ 填数据类型(面 / 线 / 点);线、点需填缓冲距离(米)。
621
+ 3. 上传 `.txt`(CGCS2000 经纬度 / `GCS_China_Geodetic_Coordinate_System_2000`,每行「经度,纬度」)或带 `.shp` / `.prj` / `.dbf` 的 `.zip`。TXT ≤ 10MB,ZIP ≤ 500MB。
622
+ 4. 上图后可编辑折点。
623
+ 5. 「分析」:与勾选图层求交,输出压占面积、牧户及分类明细。
624
+ 6. 「导出」Word(含地图截图)或 TXT 坐标。
625
+ 7. 「重置」清空图斑、结果与勾选(回到默认确权)。关闭面板会释放 Sketch 与分析图层。
626
+
627
+ #### 结果区
628
+
629
+ 分析完成后,结果区按叠加类型分 Tab(左右箭头可滚动)。分析前展示全部 Tab;分析后只保留当前勾选类型。表格使用 `BglDataTable`(居中对齐),点击行高亮;切换 Tab 时滚动回到顶部。
630
+
631
+ 底部固定汇总:
632
+
633
+ | 指标 | 说明 |
634
+ | ---- | ---- |
635
+ | 分析面积(亩) | 图斑面积;确权压占面积更大时取确权合计 |
636
+ | 牧户/集体(个) | 当前 Tab 行数 |
637
+ | 确权面积(亩) / 资源面积(亩) | 确权 Tab 汇总 `occupiedArea`;其余 Tab 汇总「小计」 |
638
+
639
+ 各 Tab 列概要(数字列保留两位小数):
640
+
641
+ | Tab | 列 |
642
+ | --- | --- |
643
+ | 确权 | 序号、牧户名称、覆盖面积(亩)、苏木镇、嘎查村 |
644
+ | 草地 / 林地 / 湿地 / 耕地 / 基本草原 / 生态红线 | 序号、牧户名称、苏木镇、嘎查村、小计、各分类面积 |
645
+ | 保护区 | 上列基础字段 + 保护区名称、核心区、缓冲区 |
646
+ | 林保图 | 上列基础字段 + 乔木林地、灌木林地、宜林荒山荒地、其他 |
647
+
345
648
  ## 平移边界约束
346
649
 
347
650
  基于 ArcGIS `view.constraints.geometry`(只约束**视图中心点**):按当前可视范围反推中心点合法活动区域,效果上等价于「经纬度矩形始终不拖出屏幕」。所有缩放级别均生效;拖到边缘直接停住,不做回弹。
@@ -351,7 +654,9 @@ const coordinateSystemConfig = {
351
654
  ```ts
352
655
  import {
353
656
  applyPanBoundsConstraint,
354
- goToFullExtent
657
+ goToFullExtent,
658
+ suspendPanBounds,
659
+ resumePanBounds
355
660
  } from '@ywbgn/bgl-package'
356
661
  import type { LonLatExtent, PanConstraintHandle } from '@ywbgn/bgl-package'
357
662
 
@@ -378,6 +683,8 @@ handle.remove()
378
683
  | `applyPanBoundsConstraint(view, extent)` | 挂平移约束并初始定位到全图;返回`PanConstraintHandle` |
379
684
  | `handle.wrapViewGoTo(view)` | 包装`view.goTo`,定位期间临时放开约束 |
380
685
  | `handle.remove()` | 释放 watch,恢复原始`goTo`,清空 `constraints.geometry` |
686
+ | `handle.suspend()` / `handle.resume()` | 长期暂停 / 恢复约束(如 TXT 画图打开面板) |
687
+ | `suspendPanBounds(view)` / `resumePanBounds(view)` | 按 view 查找已登记句柄后暂停 / 恢复 |
381
688
  | `goToFullExtent(view, extent)` | 定位到范围中心 +`constraints.minZoom` |
382
689
 
383
690
  ## 两套卷帘(务必区分)
@@ -402,6 +709,7 @@ const layers = loadBusinessLayers({
402
709
  layers: configs,
403
710
  reverse: true,
404
711
  idPrefix: BUSINESS_LAYER_ID_PREFIX,
712
+ // accessToken, // 已登记 Portal token 时建议传入,保证首轮元数据请求带 token
405
713
  // labelConfigs: [...] // 见下文「业务图层注记」
406
714
  // expectedSpatialReferenceWkid: 8848, // 系统参数;8848=CGCS2000_Albers,其他为 WKID
407
715
  })
@@ -428,6 +736,37 @@ const layers = loadBusinessLayers({
428
736
  - 不一致记录会登记到组件内,图层管理面板会显示「坐标系不一致」标记,并在顶部汇总数量
429
737
  - 注意:`systemCoordinate` 表示业务图层期望坐标系;坐标定位面板默认输入坐标系仍优先使用 `latitudeLongitude`(经纬度)
430
738
 
739
+ ### 默认隐藏层(延迟上图)
740
+
741
+ `layerVisible` 为假的图层不要立刻 `loadBusinessLayers`,用 `setPendingBusinessLayers` 登记。图层管理勾选显示、或空间分析勾选对应叠加类型时,才会真正请求服务并 `reorderBusinessLayers`。
742
+
743
+ ```ts
744
+ import {
745
+ loadBusinessLayers,
746
+ setPendingBusinessLayers,
747
+ clearPendingBusinessLayers,
748
+ resolveLayerVisible
749
+ } from '@ywbgn/bgl-package'
750
+
751
+ const visible = configs.filter((item) => resolveLayerVisible(item.layerVisible))
752
+ const pending = configs.filter((item) => !resolveLayerVisible(item.layerVisible))
753
+
754
+ loadBusinessLayers({
755
+ map,
756
+ layers: visible,
757
+ reverse: true,
758
+ accessToken
759
+ })
760
+ setPendingBusinessLayers(pending, {
761
+ allConfigs: configs,
762
+ accessToken,
763
+ reverse: true
764
+ })
765
+
766
+ // 页面卸载或重新上图前
767
+ clearPendingBusinessLayers()
768
+ ```
769
+
431
770
  ### 业务图层注记(地图上显示属性字段)
432
771
 
433
772
  对齐 forestpests:前端配置指定图层的 `labelingInfo`(Arcade + 描边样式),**不依赖**后端 mapServiceSettings。
@@ -471,7 +810,41 @@ loadBusinessLayers({
471
810
 
472
811
  注意:仅 **FeatureLayer** 生效;与工具栏「地图标注」可并存(手动标注会覆盖该层 `labelingInfo`)。
473
812
 
474
- ### registerPortalToken / startPortalTokenRenewal
813
+ ### Portal Token
814
+
815
+ 生产不要在前端持有 Portal 账号密码。由后端签发短期 token,前端只登记 / 续期。
816
+
817
+ **生产推荐:后端代签 + 自动续期**
818
+
819
+ ```ts
820
+ const renewal = await startPortalTokenRenewalWithFetcher({
821
+ portalUrl: 'https://example.com',
822
+ extraServers: ['https://gis.example.com/server'],
823
+ fetchToken: async () => {
824
+ const res = await fetch('/api/portal-token')
825
+ const data = await res.json()
826
+ // token 必填;expires 为毫秒时间戳,有则按此调度续期
827
+ return { token: data.token, expires: data.expires }
828
+ },
829
+ // expirationMinutes: 60, // fetch 未返回 expires 时的兜底有效期
830
+ onRenewError: (err) => console.error(err)
831
+ })
832
+
833
+ // 组件卸载时
834
+ renewal.stop()
835
+ ```
836
+
837
+ 已有 token、无需续期时:
838
+
839
+ ```ts
840
+ registerPortalAccessToken({
841
+ portalUrl: 'https://example.com',
842
+ token: accessToken,
843
+ extraServers: ['https://gis.example.com/server']
844
+ })
845
+ ```
846
+
847
+ **内网联调:前端 generateToken(勿用于生产)**
475
848
 
476
849
  单次注册:
477
850
 
@@ -505,11 +878,10 @@ const renewal = await startPortalTokenRenewal({
505
878
  onRenewError: (err) => console.error(err)
506
879
  })
507
880
 
508
- // 组件卸载时
509
881
  renewal.stop()
510
882
  ```
511
883
 
512
- 注意:前端持有账号密码仅适合内网联调;生产应由后端签发 token。
884
+ 续期失败时库内会节流通知(首次立即,之后同一失败串最多约每 15 分钟一次),并每 5 分钟重试。`onRenewError` 仍建议业务侧做提示。
513
885
 
514
886
  ### 密钥怎么传
515
887
 
@@ -529,7 +901,7 @@ provideBasemapKeys(basemapKeys)
529
901
 
530
902
  也可给组件传 `:keys`(优先于 inject)。
531
903
 
532
- 导出:`BasemapKeys`、`BASEMAP_KEYS_KEY`、`provideBasemapKeys`、`useBasemapKeys`、`BASEMAP_OPTIONS`、`ToolbarToolId`、`DEFAULT_TOOLBAR_TOOLS`、`LonLatExtent`、`PanConstraintHandle`、`applyPanBoundsConstraint`、`goToFullExtent`。
904
+ 导出:`BasemapKeys`、`BASEMAP_KEYS_KEY`、`provideBasemapKeys`、`useBasemapKeys`、`BASEMAP_OPTIONS`、`ToolbarToolId`、`DEFAULT_TOOLBAR_TOOLS`、`LonLatExtent`、`PanConstraintHandle`、`applyPanBoundsConstraint`、`goToFullExtent`、`suspendPanBounds`、`resumePanBounds`、`registerPortalAccessToken`、`startPortalTokenRenewalWithFetcher`、`setPendingBusinessLayers`、`MapBounds`、`BglDataTable`、`BglDataTableColumn`、`BglDataTableRow`。
533
905
 
534
906
  ## 样式定制
535
907
 
@@ -539,19 +911,22 @@ provideBasemapKeys(basemapKeys)
539
911
 
540
912
  | 变量 | 作用对象 | 默认 |
541
913
  | --------------------------- | ---------------------- | -------------------- |
914
+ | `--bgl-layer-left` | 图层入口 | `16px` |
915
+ | `--bgl-layer-bottom` | 图层入口 | `390px` |
916
+ | `--bgl-layer-z` | 图层入口 | `100` |
542
917
  | `--bgl-basemap-left` | 底图入口 | `16px` |
543
918
  | `--bgl-basemap-bottom` | 底图入口 | `160px` |
544
- | `--bgl-basemap-z` | 底图入口 | `1100` |
919
+ | `--bgl-basemap-z` | 底图入口 | `100` |
545
920
  | `--bgl-swipe-left` | 底图卷帘入口 | `16px` |
546
921
  | `--bgl-swipe-bottom` | 底图卷帘入口 | `100px` |
547
- | `--bgl-swipe-z` | 底图卷帘入口 | `1100` |
922
+ | `--bgl-swipe-z` | 底图卷帘入口 | `100` |
548
923
  | `--bgl-toolbar-left` | 工具栏整体(含经纬度) | `50%` |
549
924
  | `--bgl-toolbar-bottom` | 工具栏整体 | `14px` |
550
925
  | `--bgl-toolbar-transform` | 工具栏整体 | `translateX(-50%)` |
551
- | `--bgl-toolbar-z` | 工具栏整体 | `1000` |
926
+ | `--bgl-toolbar-z` | 工具栏整体 | `100` |
552
927
  | `--bgl-legend-width` | 图例宽度 | `150px` |
553
928
  | `--bgl-legend-height` | 图例高度 | `240px` |
554
- | `--bgl-legend-z` | 图例层级 | `1050` |
929
+ | `--bgl-legend-z` | 图例层级 | `100` |
555
930
  | `--bgl-scalebar-z` | 比例尺层级 | `100` |
556
931
 
557
932
  **背景与强调色**
@@ -568,12 +943,15 @@ provideBasemapKeys(basemapKeys)
568
943
 
569
944
  | class | 说明 |
570
945
  | -------------------------------------------------------------- | ------------ |
946
+ | `.layer-switch-wrap` / `.layer-switch-trigger` / `.layer-switch-panel` | 图层显隐 |
571
947
  | `.basemap-switch-wrap` / `.basemap-switch-trigger` | 底图 |
572
948
  | `.swipe-compare-wrap` / `.swipe-compare-trigger` | 底图卷帘 |
573
949
  | `.toolbar-wrap` / `.coordinate-display` / `.toolbar-box` | 工具栏 |
574
950
  | `.map-tool-panel` | 通用浮层面板 |
575
- | `.map-legend` / `.map-legend__body` | 图例 |
951
+ | `.map-legend` / `.map-legend--plain` / `.map-legend--frame` / `.map-legend__body` | 图例 |
576
952
  | `.map-scale-bar` / `.map-scale-bar__body` | 比例尺 |
953
+ | `.spatial-analysis-panel` | 空间分析面板 |
954
+ | `.bgl-data-table` / `.bgl-data-table__head` / `.bgl-data-table__wrap` / `.bgl-data-table__footer` | 通用数据表格 |
577
955
 
578
956
  ## TypeScript
579
957
 
@@ -588,7 +966,11 @@ import type {
588
966
  LonLatExtent,
589
967
  PanConstraintHandle,
590
968
  SpatialReferenceMismatchInfo,
591
- CoordinateSystemConfig
969
+ CoordinateSystemConfig,
970
+ MapBounds,
971
+ PortalTokenRenewalHandle,
972
+ BglDataTableColumn,
973
+ BglDataTableRow
592
974
  } from '@ywbgn/bgl-package'
593
975
  ```
594
976