【类 型】:feat

【原  因】:地图组件 添加一个保存数据到本地的控件  的功能
【过  程】:飞行数据统计-飞行轨迹 把数据传到地图组件  有控件把数据保存到本地文件
【影  响】:

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
This commit is contained in:
air 2025-06-16 16:41:03 +08:00
parent 8b7a2161ba
commit 99e7caffd5
3 changed files with 93 additions and 2 deletions

View File

@ -6,7 +6,7 @@
<script> <script>
import mapboxgl from 'mapbox-gl' import mapboxgl from 'mapbox-gl'
import { MapboxStyleSwitcherControl, FollowControl, CustomFullscreenControl, NoFlyControl } from '@/utils/mapboxgl_plugs' import { MapboxStyleSwitcherControl, FollowControl, CustomFullscreenControl, NoFlyControl, SaveToFileControl } from '@/utils/mapboxgl_plugs'
import planeIcon from '@/assets/svg/plane.svg' import planeIcon from '@/assets/svg/plane.svg'
export default { export default {
@ -160,6 +160,14 @@ export default {
type: Boolean, type: Boolean,
default: false default: false
}, },
enableSaveToFile: { //
type: Boolean,
default: false
},
getData: { //
type: Function,
default: null
},
enableNofly: { // enableNofly: { //
type: Boolean, type: Boolean,
default: false default: false
@ -321,6 +329,16 @@ export default {
}), 'top-right') }), 'top-right')
} }
// :1.线
if (this.enableSaveToFile && typeof this.getData === 'function') {
this.map.addControl(new SaveToFileControl({
Data: this.getData,
filename: `export_${Date.now()}.json`,
title: '保存当前数据',
icon: '💾'
}), 'top-left')
}
// //
if (this.enableNofly) { if (this.enableNofly) {
const defaultPolygons = [ const defaultPolygons = [

View File

@ -368,3 +368,76 @@ export class NoFlyControl {
this._onSave(polygons) this._onSave(polygons)
} }
} }
// 保存数据到文件控件
export class SaveToFileControl {
constructor (options = {}) {
// 获取数据的方法,必须是一个函数,返回要保存的数据数组
this.getData = options.Data || (() => [])
// 保存时的默认文件名,可以通过传参自定义
this.filename = options.filename || `data_${Date.now()}.json`
// 按钮悬停时显示的提示文本
this.title = options.title || '保存数据'
// 按钮图标,可以是 emoji 或 HTML 字符
this.icon = options.icon || '💾'
}
// Mapbox 会调用该方法,将控件添加到地图上
onAdd (map) {
this._map = map
// 创建控件容器 div
this._container = document.createElement('div')
this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group'
// 创建按钮元素
const button = document.createElement('button')
button.className = 'mapboxgl-ctrl-icon'
button.type = 'button'
button.innerHTML = this.icon // 设置图标
button.title = this.title // 设置悬浮提示
button.onclick = () => this._saveToFile() // 点击事件处理:执行保存
// 将按钮添加到控件容器中
this._container.appendChild(button)
// 返回控件 DOM 元素Mapbox 会将其插入地图
return this._container
}
// 保存数据为 JSON 文件的核心方法
_saveToFile () {
const data = this.getData() // 调用传入的 getData 方法获取数据
// 若数据为空,则提示并返回
if (!data || data.length === 0) {
alert('数据为空')
return
}
// 将数据序列化为 JSON 字符串(格式化缩进)
const content = JSON.stringify(data, null, 2)
// 创建一个 Blob 对象,用于生成文件下载链接
const blob = new Blob([content], { type: 'application/json' })
// 创建一个临时链接元素用于触发浏览器下载
const link = document.createElement('a')
link.href = URL.createObjectURL(blob) // 生成临时 URL
link.download = this.filename // 设置下载文件名
link.click() // 触发下载
URL.revokeObjectURL(link.href) // 释放临时 URL
}
// Mapbox 会调用该方法移除控件
onRemove () {
// 从地图中移除 DOM 元素
this._container.parentNode.removeChild(this._container)
// 清除对 map 实例的引用,防止内存泄漏
this._map = null
}
}

View File

@ -13,7 +13,7 @@
<div class="chart-area" v-if="flyDataList.length"> <div class="chart-area" v-if="flyDataList.length">
<div v-if="boxShow" id="main" class="chart-container"></div> <div v-if="boxShow" id="main" class="chart-container"></div>
<map-box v-else ref="mapbox" @map-ready="onMapReady"/> <map-box v-else ref="mapbox" @map-ready="onMapReady" :enableSaveToFile="true" :getData="() => flyDataList"/>
</div> </div>
<div v-else class="no-data-tip">暂无数据</div> <div v-else class="no-data-tip">暂无数据</div>
</div> </div>