@gis_victory/gismap 1.0.57 → 2.0.0

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,350 +1,475 @@
1
- # @gis_victory/gismap 组件库
1
+ # GISMap - 通用地图组件库
2
2
 
3
- 一个基于 Vue 3 + TypeScript + Vite 开发的 GIS 地图组件库,提供丰富的地图交互功能和移动端适配。
3
+ GISMap 是一个基于适配器模式设计的通用地图组件库,支持多种地图引擎(如 Mapbox GL、MapLibre 等),提供统一的 API 接口和丰富的功能模块。
4
4
 
5
5
  ## 特性
6
6
 
7
- - 📦 开箱即用的地图组件
8
- - 🎨 支持多种地图样式和图层
9
- - 📱 移动端适配
10
- - 🔍 地图搜索功能
11
- - 🎯 地图工具和控件
12
- - 📍 标记和弹窗
13
- - 📊 图例和数据可视化
14
- - 🔄 地图切换和扩展
7
+ - **多引擎支持**:通过适配器模式,支持不同的地图引擎
8
+ - **丰富的管理器**:提供图层、标记、雷达、地形、绘制、测量等多种管理器
9
+ - **响应式设计**:基于 Vue 3 的 Composition API,提供响应式的地图状态管理
10
+ - **模块化架构**:清晰的代码结构,易于扩展和维护
11
+ - **TypeScript 支持**:完整的类型定义,提供良好的开发体验
15
12
 
16
13
  ## 安装
17
14
 
18
15
  ```bash
19
- npm install @gis_victory/gismap
20
- #
21
- yarn add @gis_victory/gismap
16
+ # 使用 npm
17
+ npm install gismap
18
+
19
+ # 使用 yarn
20
+ yarn add gismap
21
+
22
+ # 使用 pnpm
23
+ pnpm add gismap
22
24
  ```
23
25
 
24
- ## 快速开始
26
+ ## 基本使用
25
27
 
26
- ### 基础使用
28
+ ### 1. 基础地图组件
27
29
 
28
30
  ```vue
29
31
  <template>
30
- <MapContainer
31
- :mapViewData="mapViewData"
32
- :switchData="switchData"
33
- :layerData="layerData"
34
- :toolsData="toolsData"
35
- :searchData="searchData"
36
- @load="onMapLoad"
37
- >
38
- <!-- 自定义插槽内容 -->
39
- <template #bottom-left>
40
- <GisMapCompass />
41
- </template>
42
- </MapContainer>
32
+ <div style="width: 100vw; height: 100vh;">
33
+ <GisMapContainer
34
+ :center="[120, 30]"
35
+ :zoom="10"
36
+ :access-token="'your-mapbox-access-token'"
37
+ :init-icons="initIcons"
38
+ >
39
+ <!-- 可以在这里添加地图控件 -->
40
+ </GisMapContainer>
41
+ </div>
43
42
  </template>
44
43
 
45
44
  <script setup lang="ts">
46
- import { ref, reactive } from 'vue';
47
- import { MapContainer, GisMapCompass, GSMap } from '@gis_victory/gismap';
48
-
49
- const mapViewData = reactive({
50
- zoom: 9,
51
- center: [120.65677441301864, 29.745141743380103],
52
- style: {
53
- glyphs: "http://www.gisx.work/map-assets/fonts/{fontstack}/{range}.pbf",
45
+ import { GisMapContainer } from 'gismap';
46
+
47
+ // 初始化图标配置
48
+ const initIcons = [
49
+ {
50
+ name: 'marker-icon',
51
+ url: 'https://example.com/marker.png'
54
52
  },
55
- icons: [
56
- {
57
- name: 'point',
58
- label: "点",
59
- url: 'assets/icons/point.png',
53
+ {
54
+ name: 'icon-2',
55
+ url: 'https://example.com/icon2.png'
56
+ }
57
+ ];
58
+ </script>
59
+ ```
60
+
61
+ ### 2. 使用组合式函数
62
+
63
+ ```vue
64
+ <template>
65
+ <div style="width: 100vw; height: 100vh;">
66
+ <GisMapContainer @ready="handleMapReady">
67
+ <button @click="addMarker" style="position: absolute; top: 10px; left: 10px; z-index: 1000;">
68
+ 添加标记
69
+ </button>
70
+ </GisMapContainer>
71
+ </div>
72
+ </template>
73
+
74
+ <script setup lang="ts">
75
+ import { GisMapContainer } from 'gismap';
76
+ import { useMap, useMarker, useLayer } from 'gismap';
77
+
78
+ const { map, layers, markers } = useMap();
79
+
80
+ const handleMapReady = () => {
81
+ console.log('地图就绪');
82
+ };
83
+
84
+ const addMarker = () => {
85
+ // 添加标记
86
+ markers.value.add({
87
+ id: `marker-${Date.now()}`,
88
+ position: [120, 30],
89
+ options: {
90
+ draggable: true
91
+ }
92
+ });
93
+ };
94
+ </script>
95
+ ```
96
+
97
+ ## 核心功能
98
+
99
+ ### 1. 图层管理
100
+
101
+ ```typescript
102
+ import { useLayers } from 'gismap';
103
+
104
+ const { addLayer, removeLayer, layers } = useLayers();
105
+
106
+ // 添加 GeoJSON 图层
107
+ const layer = addLayer({
108
+ id: 'points',
109
+ type: 'circle',
110
+ source: {
111
+ type: 'geojson',
112
+ data: {
113
+ type: 'FeatureCollection',
114
+ features: [
115
+ {
116
+ type: 'Feature',
117
+ geometry: {
118
+ type: 'Point',
119
+ coordinates: [120, 30]
120
+ }
121
+ }
122
+ ]
60
123
  }
61
- // 更多图标配置...
62
- ]
124
+ },
125
+ paint: {
126
+ 'circle-radius': 10,
127
+ 'circle-color': '#ff0000'
128
+ }
63
129
  });
64
130
 
65
- const switchData = reactive({
66
- layers: [{
67
- name: "tdt-vec",
68
- label: "标准地图",
69
- iconName: "vector",
70
- checked: true
71
- }, {
72
- name: "tdt-img",
73
- label: "卫星影像",
74
- iconName: "satellite",
75
- checked: false
76
- }],
77
- extensions: [{
78
- name: "tdt-cia",
79
- label: "注记",
80
- checked: true,
81
- }]
131
+ // 移除图层
132
+ removeLayer(layer.id);
133
+ ```
134
+
135
+ ### 2. 标记管理
136
+
137
+ ```typescript
138
+ import { useMarkers } from 'gismap';
139
+
140
+ const { add, remove, getAll } = useMarkers();
141
+
142
+ // 添加标记
143
+ const marker = add({
144
+ id: 'marker-1',
145
+ position: [120, 30],
146
+ options: {
147
+ draggable: true,
148
+ anchor: 'bottom'
149
+ }
82
150
  });
83
151
 
84
- const layerData = ref([]);
85
- const toolsData = ref([]);
86
- const searchData = ref([]);
152
+ // 移除标记
153
+ remove('marker-1');
87
154
 
88
- const onMapLoad = (map: GSMap) => {
89
- console.log('地图加载完成:', map);
90
- // 地图操作逻辑...
91
- };
92
- </script>
155
+ // 获取所有标记
156
+ const allMarkers = getAll();
93
157
  ```
94
158
 
95
- ## 组件列表
159
+ ### 3. 绘制功能
96
160
 
97
- ### 核心组件
161
+ ```typescript
162
+ import { useDraw } from 'gismap';
98
163
 
99
- | 组件名 | 描述 | 示例 |
100
- |-------|------|------|
101
- | `MapContainer` | 地图容器,包含所有地图组件 | `<MapContainer :mapViewData="mapViewData" @load="onMapLoad" />` |
102
- | `GisMapView` | 地图视图组件 | `<GisMapView :mapViewData="mapViewData" />` |
103
- | `GisMapLayer` | 地图图层管理组件 | `<GisMapLayer :layerData="layerData" />` |
104
- | `GisMapLegend` | 地图图例组件 | `<GisMapLegend />` |
105
- | `GisMapTools` | 地图工具组件 | `<GisMapTools :toolsData="toolsData" />` |
106
- | `GisMapSwitch` | 地图切换组件 | `<GisMapSwitch :switchData="switchData" />` |
107
- | `GisMapSearch` | 地图搜索组件 | `<GisMapSearch :searchData="searchData" />` |
164
+ const { startDraw, stopDraw, isDrawing, selected } = useDraw();
108
165
 
109
- ### 工具组件
166
+ // 开始绘制多边形
167
+ startDraw('polygon', (type, geoJson, wkt, feature) => {
168
+ console.log('绘制完成:', type, geoJson, wkt);
169
+ });
110
170
 
111
- | 组件名 | 描述 | 示例 |
112
- |-------|------|------|
113
- | `GisMapCompass` | 地图指南针组件 | `<GisMapCompass />` |
114
- | `GisMapPopupBar` | 弹窗工具栏组件 | `<GisMapPopupBar>` |
115
- | `GisMapPopupBarItem` | 弹窗工具栏项组件 | `<GisMapPopupBarItem label="示例" />` |
171
+ // 停止绘制
172
+ stopDraw();
173
+ ```
116
174
 
117
- ### 移动端组件
175
+ ### 4. 测量功能
118
176
 
119
- | 组件名 | 描述 | 示例 |
120
- |-------|------|------|
121
- | `MobileMapLayer` | 移动端地图图层组件 | `<MobileMapLayer>` |
122
- | `MobileBaseLayerSwitch` | 移动端底图切换组件 | `<MobileBaseLayerSwitch :data="layersData" />` |
177
+ ```typescript
178
+ import { useMeasure } from 'gismap';
123
179
 
124
- ## API 文档
180
+ const { startMeasure, stopMeasure, isMeasuring, results } = useMeasure();
125
181
 
126
- ### MapContainer 组件
182
+ // 开始测量距离
183
+ startMeasure('line', (result) => {
184
+ console.log('测量结果:', result.value, result.unit);
185
+ });
127
186
 
128
- #### Props
187
+ // 停止测量
188
+ stopMeasure();
189
+ ```
129
190
 
130
- | 属性名 | 类型 | 描述 | 默认值 |
131
- |-------|------|------|--------|
132
- | `mapViewData` | `Object` | 地图视图配置 | `{}` |
133
- | `switchData` | `Object` | 地图切换配置 | `{}` |
134
- | `layerData` | `Array` | 图层数据 | `[]` |
135
- | `toolsData` | `Array` | 工具数据 | `[]` |
136
- | `searchData` | `Array` | 搜索数据 | `[]` |
191
+ ### 5. 雷达图层
137
192
 
138
- #### Events
193
+ ```typescript
194
+ import { useMap } from 'gismap';
139
195
 
140
- | 事件名 | 参数 | 描述 |
141
- |-------|------|------|
142
- | `load` | `map: GSMap` | 地图加载完成事件 |
196
+ const { radarManager } = useMap();
143
197
 
144
- #### Slots
198
+ // 添加雷达
199
+ radarManager.value?.add({
200
+ center: [120, 30],
201
+ radius: 500,
202
+ sectorVisible: true,
203
+ sectorAngle: 45
204
+ });
145
205
 
146
- | 插槽名 | 描述 |
147
- |-------|------|
148
- | `bottom-left` | 地图左下角插槽 |
149
- | `bottom-right` | 地图右下角插槽 |
150
- | `top-left` | 地图左上角插槽 |
151
- | `top-right` | 地图右上角插槽 |
206
+ // 开始扫描
207
+ radarManager.value?.startScan();
152
208
 
153
- ### GSMap 实例
209
+ // 停止扫描
210
+ radarManager.value?.stopScan();
154
211
 
155
- #### 方法
212
+ // 移除雷达
213
+ radarManager.value?.remove();
214
+ ```
156
215
 
157
- | 方法名 | 参数 | 描述 |
158
- |-------|------|------|
159
- | `pubsub.on` | `event: string, callback: Function` | 订阅地图事件 |
160
- | `pubsub.emit` | `event: string, data: any` | 发布地图事件 |
161
- | `manager.templateManager.add` | `id: string, template: string` | 添加模板 |
162
- | `manager.maskManager.add` | `data: string` | 添加遮罩 |
216
+ ### 6. 地形管理
163
217
 
164
- ## 配置项
218
+ ```typescript
219
+ import { useMap } from 'gismap';
165
220
 
166
- ### mapViewData 配置
221
+ const { terrainManager } = useMap();
167
222
 
168
- ```javascript
169
- {
170
- zoom: 9, // 初始缩放级别
171
- center: [120.65677441301864, 29.745141743380103], // 初始中心点坐标
172
- style: {
173
- glyphs: "http://www.gisx.work/map-assets/fonts/{fontstack}/{range}.pbf", // 字体配置
223
+ // 添加地形
224
+ terrainManager.value?.add({
225
+ source: {
226
+ tiles: ['https://example.com/terrain/{z}/{x}/{y}.png'],
227
+ minzoom: 0,
228
+ maxzoom: 14
174
229
  },
175
- icons: [ // 图标配置
176
- {
177
- name: 'point', // 图标名称
178
- label: "点", // 图标标签
179
- url: 'assets/icons/point.png', // 图标路径
180
- }
181
- ]
182
- }
230
+ layer: {
231
+ exaggeration: 1.5
232
+ }
233
+ });
234
+
235
+ // 添加山体阴影
236
+ terrainManager.value?.addHillshade();
237
+
238
+ // 移除地形
239
+ terrainManager.value?.remove();
183
240
  ```
184
241
 
185
- ### switchData 配置
242
+ ### 7. 图标管理
186
243
 
187
- ```javascript
188
- {
189
- layers: [ // 底图配置
190
- {
191
- name: "tdt-vec", // 图层名称
192
- label: "标准地图", // 图层标签
193
- iconName: "vector", // 图标名称
194
- checked: true // 是否默认选中
195
- }
196
- ],
197
- extensions: [ // 扩展配置
198
- {
199
- name: "tdt-cia", // 扩展名称
200
- label: "注记", // 扩展标签
201
- checked: true, // 是否默认选中
202
- config: { // 扩展配置
203
- source: {
204
- tiles: ["http://www.gisx.work/tiles/dem/{z}_{x}_{y}.webp"]
244
+ #### 最佳实践:在地图初始化完成后立即加载图标
245
+
246
+ 为了确保地图能够正确读取图标,应该在地图初始化完成后立即加载图标。推荐使用 `useMapReady` 组合式函数来监听地图就绪事件:
247
+
248
+ ```typescript
249
+ import { useMapReady } from 'gismap';
250
+
251
+ // 在地图就绪后立即加载图标
252
+ useMapReady(async (context) => {
253
+ try {
254
+ // 批量加载图标
255
+ await context.iconManager?.load([
256
+ {
257
+ name: 'marker-icon',
258
+ url: 'https://example.com/marker.png'
259
+ },
260
+ {
261
+ name: 'icon-2',
262
+ url: 'https://example.com/icon2.png'
263
+ }
264
+ ], {
265
+ batchSize: 5, // 每批加载5个图标
266
+ batchInterval: 100, // 每批间隔100毫秒
267
+ onProgress: (loaded, total) => {
268
+ console.log(`加载进度: ${loaded}/${total}`);
269
+ }
270
+ });
271
+
272
+ console.log('图标加载完成');
273
+
274
+ // 图标加载完成后,再添加使用图标的图层
275
+ addIconLayer(context);
276
+ } catch (error) {
277
+ console.error('图标加载失败:', error);
278
+ }
279
+ });
280
+
281
+ // 添加使用图标的图层
282
+ function addIconLayer(context) {
283
+ if (context?.layerManager) {
284
+ context.layerManager.addLayer({
285
+ id: 'icon-layer',
286
+ type: 'symbol',
287
+ source: {
288
+ type: 'geojson',
289
+ data: {
290
+ type: 'FeatureCollection',
291
+ features: [
292
+ {
293
+ type: 'Feature',
294
+ geometry: {
295
+ type: 'Point',
296
+ coordinates: [120, 30]
297
+ }
298
+ }
299
+ ]
205
300
  }
301
+ },
302
+ layout: {
303
+ 'icon-image': 'marker-icon', // 使用已加载的图标
304
+ 'icon-size': 1.5
206
305
  }
207
- }
208
- ]
306
+ });
307
+ }
209
308
  }
210
309
  ```
211
310
 
212
- ## 示例
311
+ #### 其他用法
213
312
 
214
- ### 完整示例
313
+ ```typescript
314
+ import { useMap } from 'gismap';
215
315
 
216
- ```vue
217
- <template>
218
- <MapContainer
219
- :mapViewData="mapViewData"
220
- :switchData="switchData"
221
- :layerData="layerData"
222
- :toolsData="toolsData"
223
- :searchData="searchData"
224
- @load="onMapLoad"
225
- >
226
- <template #bottom-left>
227
- <GisMapCompass />
228
- </template>
229
- <template #top-right>
230
- <MobileMapLayer>
231
- <MobileBaseLayerSwitch :data="switchData.layers" />
232
- </MobileMapLayer>
233
- </template>
234
- </MapContainer>
235
- </template>
316
+ const { iconManager } = useMap();
236
317
 
237
- <script setup lang="ts">
238
- import { ref, reactive, onMounted } from 'vue';
239
- import { MapContainer, GisMapCompass, GSMap, MobileMapLayer, MobileBaseLayerSwitch } from '@gis_victory/gismap';
240
-
241
- const mapViewData = reactive({
242
- zoom: 9,
243
- center: [120.65677441301864, 29.745141743380103],
244
- style: {
245
- glyphs: "http://www.gisx.work/map-assets/fonts/{fontstack}/{range}.pbf",
318
+ // 批量加载图标(基本用法)
319
+ iconManager.value?.load([
320
+ {
321
+ name: 'marker-icon',
322
+ url: 'https://example.com/marker.png'
246
323
  },
247
- icons: [
248
- {
249
- name: 'point',
250
- label: "点",
251
- url: 'assets/icons/point.png',
252
- }
253
- ]
324
+ {
325
+ name: 'icon-2',
326
+ url: 'https://example.com/icon2.png'
327
+ }
328
+ ]).then(() => {
329
+ console.log('图标加载完成');
254
330
  });
255
331
 
256
- const switchData = reactive({
257
- layers: [{
258
- name: "tdt-vec",
259
- label: "标准地图",
260
- iconName: "vector",
261
- checked: true
262
- }, {
263
- name: "tdt-img",
264
- label: "卫星影像",
265
- iconName: "satellite",
266
- checked: false
267
- }],
268
- extensions: [{
269
- name: "tdt-cia",
270
- label: "注记",
271
- checked: true,
272
- }]
332
+ // 加载单个图标
333
+ iconManager.value?.loadOne({
334
+ name: 'single-icon',
335
+ url: 'https://example.com/single.png'
336
+ }).then(() => {
337
+ console.log('单个图标加载完成');
273
338
  });
274
339
 
275
- const layerData = ref([]);
276
- const toolsData = ref([]);
277
- const searchData = ref([]);
278
-
279
- let map: GSMap;
280
- const onMapLoad = (_map: GSMap) => {
281
- map = _map;
282
- // 地图加载完成后的操作
283
- map.pubsub.on('layer:click', ({ templateId, feature }: { templateId: string, feature: any }) => {
284
- const template = map.manager?.templateManager?.renderHtml(templateId, feature.properties);
285
- if (template) {
286
- map.manager?.popupManager.show({
287
- position: feature.geometry.coordinates,
288
- html: template,
289
- });
290
- }
291
- });
292
- };
340
+ // 检查图标是否已加载
341
+ if (iconManager.value?.hasIcon('marker-icon')) {
342
+ console.log('图标已加载');
343
+ }
293
344
 
294
- // 初始化数据
295
- onMounted(() => {
296
- // 这里可以加载图层数据、工具数据和搜索数据
297
- });
298
- </script>
345
+ // 移除图标
346
+ iconManager.value?.removeIcon('marker-icon');
347
+
348
+ // 清除所有图标记录
349
+ iconManager.value?.clear();
299
350
  ```
300
351
 
301
- ## 开发指南
352
+ ## 高级功能
302
353
 
303
- ### 本地开发
354
+ ### 1. 自定义适配器
304
355
 
305
- 1. 克隆仓库
356
+ 您可以通过实现 `MapAdapter` 或 `VectorTileAdapter` 接口来创建自定义适配器,支持其他地图引擎。
306
357
 
307
- ```bash
308
- git clone <repository-url>
309
- cd gismap
310
- ```
358
+ ```typescript
359
+ import type { MapAdapter, MapInitOptions, MapViewState } from 'gismap';
311
360
 
312
- 2. 安装依赖
361
+ export class MyCustomAdapter implements MapAdapter {
362
+ private map: any = null;
313
363
 
314
- ```bash
315
- npm install
364
+ async initialize(container: HTMLElement, options: MapInitOptions): Promise<void> {
365
+ // 初始化您的地图引擎
366
+ // this.map = new MyMapEngine(container, options);
367
+ }
368
+
369
+ dispose(): void {
370
+ // 清理资源
371
+ }
372
+
373
+ getMap(): any {
374
+ return this.map;
375
+ }
376
+
377
+ // 实现其他必要的方法...
378
+ }
379
+
380
+ // 使用自定义适配器
381
+ <GisMapContainer :adapter="new MyCustomAdapter()" />
316
382
  ```
317
383
 
318
- 3. 启动开发服务器
384
+ ### 2. 扩展管理器
319
385
 
320
- ```bash
321
- npm run dev
386
+ 您可以通过继承现有管理器或创建新的管理器来扩展功能。
387
+
388
+ ```typescript
389
+ import { VectorTileAdapter } from 'gismap';
390
+
391
+ export class CustomManager {
392
+ private adapter: VectorTileAdapter;
393
+
394
+ constructor(adapter: VectorTileAdapter) {
395
+ this.adapter = adapter;
396
+ }
397
+
398
+ // 实现您的自定义功能
399
+ doSomething() {
400
+ // 使用 this.adapter 操作地图
401
+ }
402
+ }
322
403
  ```
323
404
 
324
- 4. 构建生产版本
405
+ ### 3. 事件系统
325
406
 
326
- ```bash
327
- npm run build
407
+ GISMap 提供了完善的事件系统,您可以监听各种地图事件。
408
+
409
+ ```typescript
410
+ import { useMapEvent } from 'gismap';
411
+
412
+ // 监听地图点击事件
413
+ useMapEvent('click', (event) => {
414
+ console.log('地图点击:', event.coordinates);
415
+ });
416
+
417
+ // 监听视图变化事件
418
+ useMapEvent('viewChange', (view) => {
419
+ console.log('视图变化:', view);
420
+ });
328
421
  ```
329
422
 
330
- ### 发布版本
423
+ ## 项目结构
331
424
 
332
- ```bash
333
- # 更新版本号
334
- npm version patch
335
- # 构建
336
- npm run build
337
- # 发布
338
- npm publish
425
+ ```
426
+ src/
427
+ ├── adapters/ # 地图适配器
428
+ │ ├── mapbox/ # Mapbox GL 适配器
429
+ │ ├── types.ts # 适配器类型定义
430
+ │ └── index.ts # 适配器统一导出
431
+ ├── components/ # Vue 组件
432
+ │ ├── MapContainer/ # 地图容器组件
433
+ │ └── ...
434
+ ├── composables/ # 组合式函数
435
+ │ ├── useMap.ts # 地图核心组合式函数
436
+ │ ├── useLayer.ts # 图层组合式函数
437
+ │ └── ...
438
+ ├── core/ # 核心功能
439
+ │ ├── event.ts # 事件系统
440
+ │ ├── StateStore.ts # 状态管理
441
+ │ └── ...
442
+ ├── domain/ # 领域服务
443
+ │ ├── LayerService.ts # 图层服务
444
+ │ ├── MarkerService.ts # 标记服务
445
+ │ └── ...
446
+ ├── manager/ # 管理器
447
+ │ ├── mapbox/ # Mapbox 专用管理器
448
+ │ ├── layer/ # 图层相关
449
+ │ ├── LayerManager.ts # 图层管理器
450
+ │ ├── RadarManager.ts # 雷达管理器
451
+ │ └── ...
452
+ ├── services/ # 服务
453
+ │ ├── MapContext.ts # 地图上下文
454
+ │ └── ...
455
+ └── index.ts # 主入口
339
456
  ```
340
457
 
341
458
  ## 浏览器兼容性
342
459
 
343
- - Chrome (最新版本)
344
- - Firefox (最新版本)
345
- - Safari (最新版本)
346
- - Edge (最新版本)
460
+ - Chrome/Edge >= 88
461
+ - Firefox >= 85
462
+ - Safari >= 14
347
463
 
348
464
  ## 许可证
349
465
 
350
466
  MIT
467
+
468
+ ## 贡献
469
+
470
+ 欢迎提交 Issue 和 Pull Request!
471
+
472
+ ## 联系方式
473
+
474
+ - 项目地址:https://github.com/your-username/gismap
475
+ - 问题反馈:https://github.com/your-username/gismap/issues