【类 型】:factor
【原 因】:完善 飞行数据统计的1.架次统计 2.飞行轨迹的bug修复 【过 程】: 【影 响】: # 类型 包含: # feat:新功能(feature) # fix:修补bug # docs:文档(documentation) # style: 格式(不影响代码运行的变动) # refactor:重构(即不是新增功能,也不是修改bug的代码变动) # test:增加测试 # chore:构建过程或辅助工具的变动
This commit is contained in:
parent
bc6bf29da2
commit
6126b9d137
@ -123,8 +123,17 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
onChange (val) {
|
||||
this.$emit('input', val)
|
||||
this.$emit('change', val)
|
||||
if (Array.isArray(val) && val.length === 2) {
|
||||
const start = val[0]
|
||||
const end = new Date(val[1])
|
||||
end.setHours(23, 59, 59, 999) // 把结束时间改为当天最后一毫秒
|
||||
this.internalValue = [start, end]
|
||||
this.$emit('input', [start, end])
|
||||
this.$emit('change', [start, end])
|
||||
} else {
|
||||
this.$emit('input', val)
|
||||
this.$emit('change', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ export default {
|
||||
|
||||
// 判断地图开启了点飞功能
|
||||
if (this.enableGuided) {
|
||||
// 长按事件 传longPress到组件外部调用
|
||||
// 长按事件 传longPress到组件外部调用
|
||||
let pressTimer = null
|
||||
let isLongPress = false // 标记是否为长按
|
||||
let startPoint = null // 记录按下时的位置
|
||||
@ -605,7 +605,146 @@ export default {
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @description: 创建飞机轨迹 ps:原理删除之前的轨迹 重新绘制
|
||||
* @description 清除历史轨迹所有轨迹线和轨迹点的图层与数据源
|
||||
* @param {Array<string>} lineLayerIds - 轨迹线图层ID数组
|
||||
* @param {Array<string>} pointLayerIds - 轨迹点图层ID数组
|
||||
*/
|
||||
clearHistoryPaths (lineLayerIds = [], pointLayerIds = []) {
|
||||
if (!this.map) return
|
||||
|
||||
// 清除轨迹线图层及对应数据源
|
||||
lineLayerIds.forEach(id => {
|
||||
if (this.map.getLayer(id)) {
|
||||
this.map.removeLayer(id)
|
||||
}
|
||||
if (this.map.getSource(id)) {
|
||||
this.map.removeSource(id)
|
||||
}
|
||||
})
|
||||
|
||||
// 清除轨迹点图层及对应数据源
|
||||
pointLayerIds.forEach(id => {
|
||||
if (this.map.getLayer(id)) {
|
||||
this.map.removeLayer(id)
|
||||
}
|
||||
if (this.map.getSource(id)) {
|
||||
this.map.removeSource(id)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 根据索引绘制一条历史轨迹的轨迹线和起点圆点
|
||||
* @param {Array<Array<number>>} pathArray - GPS坐标数组,格式为 [[lon, lat, ...], ...]
|
||||
* @param {number} index - 用于生成图层ID的索引,确保每条轨迹ID唯一
|
||||
*/
|
||||
drawHistoryPathByIndex (pathArray, index) {
|
||||
if (!this.map) return
|
||||
if (!pathArray || pathArray.length === 0) return
|
||||
|
||||
const zoomThreshold = 12 // 缩放等级阈值,决定显示轨迹线还是起点圆点
|
||||
const pointRadius = 6 // 起点圆点半径
|
||||
|
||||
// 轨迹线GeoJSON对象
|
||||
const lineGeojson = {
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'LineString',
|
||||
coordinates: pathArray
|
||||
}
|
||||
}
|
||||
|
||||
// 起点圆点GeoJSON对象,取轨迹的第一个坐标点
|
||||
const pointGeojson = {
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: pathArray[0]
|
||||
}
|
||||
}
|
||||
|
||||
// 图层ID,保证唯一
|
||||
const lineLayerId = `path${index}`
|
||||
const pointLayerId = `path${index}-point`
|
||||
|
||||
// 绘制轨迹线
|
||||
const drawLine = () => {
|
||||
if (this.map.getSource(lineLayerId)) return
|
||||
this.map.addSource(lineLayerId, {
|
||||
type: 'geojson',
|
||||
data: lineGeojson
|
||||
})
|
||||
this.map.addLayer({
|
||||
id: lineLayerId,
|
||||
type: 'line',
|
||||
source: lineLayerId,
|
||||
layout: {
|
||||
'line-join': 'round',
|
||||
'line-cap': 'round'
|
||||
},
|
||||
paint: {
|
||||
'line-color': '#3388ff',
|
||||
'line-width': 3
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 绘制起点圆点
|
||||
const drawPoint = () => {
|
||||
if (this.map.getSource(pointLayerId)) return
|
||||
this.map.addSource(pointLayerId, {
|
||||
type: 'geojson',
|
||||
data: pointGeojson
|
||||
})
|
||||
this.map.addLayer({
|
||||
id: pointLayerId,
|
||||
type: 'circle',
|
||||
source: pointLayerId,
|
||||
paint: {
|
||||
'circle-radius': pointRadius,
|
||||
'circle-color': '#3388ff',
|
||||
'circle-stroke-color': '#fff',
|
||||
'circle-stroke-width': 2
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 根据缩放等级切换显示轨迹线还是起点圆点
|
||||
const updateDisplay = () => {
|
||||
const zoom = this.map.getZoom()
|
||||
|
||||
// 起点圆点一直显示,先确保点图层存在
|
||||
if (!this.map.getSource(pointLayerId)) {
|
||||
drawPoint()
|
||||
}
|
||||
|
||||
// 轨迹线根据缩放决定显示或隐藏
|
||||
if (zoom >= zoomThreshold) {
|
||||
// 放大,显示轨迹线
|
||||
if (!this.map.getSource(lineLayerId)) {
|
||||
drawLine()
|
||||
}
|
||||
} else {
|
||||
// 缩小时隐藏轨迹线
|
||||
if (this.map.getLayer(lineLayerId)) {
|
||||
this.map.removeLayer(lineLayerId)
|
||||
}
|
||||
if (this.map.getSource(lineLayerId)) {
|
||||
this.map.removeSource(lineLayerId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 首次渲染轨迹显示
|
||||
updateDisplay()
|
||||
|
||||
// 监听缩放事件,动态切换显示
|
||||
this.map.on('zoom', () => {
|
||||
updateDisplay()
|
||||
})
|
||||
},
|
||||
/**
|
||||
* @description: 创建飞机轨迹 ps:原理删除之前的轨迹 重新绘制 用于实时轨迹
|
||||
* @param {arr} coordinatesArray 飞机经纬高度数组
|
||||
*/
|
||||
createPathWithArray (coordinatesArray) {
|
||||
@ -842,6 +981,7 @@ export default {
|
||||
/**
|
||||
* @description: 镜头跳转
|
||||
* @param {obj} lonLat {lon:lon,lat:lat} 经纬度
|
||||
* @param {Number} zoom 地图放大率
|
||||
*/
|
||||
goto (lonLat, zoom = 18) {
|
||||
this.map.flyTo({
|
||||
|
@ -4,6 +4,7 @@
|
||||
<div class="top-bar">
|
||||
<DateRangePicker v-model="dateRange" class="m-r-20 m-b-20" />
|
||||
<el-radio-group v-model="radioClass">
|
||||
<el-radio-button label="作业架次"></el-radio-button>
|
||||
<el-radio-button label="飞行时长"></el-radio-button>
|
||||
<el-radio-button label="飞行距离"></el-radio-button>
|
||||
<el-radio-button label="消耗电量"></el-radio-button>
|
||||
@ -13,7 +14,7 @@
|
||||
|
||||
<div class="chart-area" v-if="flyDataList.length">
|
||||
<div v-if="boxShow" id="main" class="chart-container"></div>
|
||||
<map-box v-else ref="mapbox" @map-ready="onMapReady" :enableSaveToFile="true" :getData="() => flyDataList"/>
|
||||
<map-box v-else ref="mapbox" @map-ready="onMapReady" :enableSaveToFile="true" :getData="() => flyDataList" />
|
||||
</div>
|
||||
<div v-else class="no-data-tip">暂无数据</div>
|
||||
</div>
|
||||
@ -39,7 +40,7 @@ export default {
|
||||
flyDataList: [],
|
||||
selectedPlaneIdArr: this.$store.state.app.toFlyDataIdArr,
|
||||
dateRange: [start, end],
|
||||
radioClass: '飞行时长',
|
||||
radioClass: '作业架次',
|
||||
boxShow: true
|
||||
}
|
||||
},
|
||||
@ -88,6 +89,7 @@ export default {
|
||||
const groupedData = {}
|
||||
|
||||
const keyMap = {
|
||||
作业架次: () => 1,
|
||||
飞行时长: (item) => {
|
||||
if (!item.start_time || !item.end_time) return 0
|
||||
return Math.round((item.end_time - item.start_time) / 60)
|
||||
@ -199,41 +201,73 @@ export default {
|
||||
methods: {
|
||||
// 地图组件回调地图加载完成后 执行
|
||||
onMapReady () {
|
||||
this.drawAllPathsOnMap()
|
||||
this.drawAllHistoricalPaths()
|
||||
},
|
||||
// 地图轨迹绘制
|
||||
drawAllPathsOnMap () {
|
||||
// 地图组件 历史轨迹绘制
|
||||
drawAllHistoricalPaths () {
|
||||
if (!this.$refs.mapbox) return
|
||||
if (this.flyDataList.length === 0) return
|
||||
|
||||
// 清理旧轨迹
|
||||
this.$refs.mapbox.clearMapElements(['path'], ['path'])
|
||||
// 准备要清除的所有轨迹图层和点图层id
|
||||
const lineLayerIds = []
|
||||
const pointLayerIds = []
|
||||
|
||||
// 遍历所有飞行数据,绘制轨迹
|
||||
this.flyDataList.forEach(item => {
|
||||
if (!item.gps_path) return
|
||||
// 解析所有轨迹
|
||||
this.flyDataList.forEach((item, index) => {
|
||||
let pathArray = item.gps_path
|
||||
try {
|
||||
const pathArray = JSON.parse(item.gps_path)
|
||||
if (Array.isArray(pathArray) && pathArray.length > 0) {
|
||||
this.$refs.mapbox.createPathWithArray(pathArray)
|
||||
if (typeof pathArray === 'string') {
|
||||
pathArray = JSON.parse(pathArray)
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('gps_path 解析失败', item.gps_path)
|
||||
console.warn(`第${index + 1}条轨迹 gps_path 解析失败`, e)
|
||||
return
|
||||
}
|
||||
|
||||
// 添加图层id
|
||||
lineLayerIds.push(`path${index}`)
|
||||
pointLayerIds.push(`path${index}-point`)
|
||||
})
|
||||
|
||||
// 清除所有轨迹图层和数据源
|
||||
this.$refs.mapbox.clearHistoryPaths(lineLayerIds, pointLayerIds)
|
||||
|
||||
// 逐条绘制轨迹
|
||||
this.flyDataList.forEach((item, index) => {
|
||||
let pathArray = item.gps_path
|
||||
if (typeof pathArray === 'string') {
|
||||
try {
|
||||
pathArray = JSON.parse(pathArray)
|
||||
} catch (e) {
|
||||
console.warn(`第${index + 1}条轨迹 gps_path 解析失败`, e)
|
||||
return
|
||||
}
|
||||
}
|
||||
if (Array.isArray(pathArray) && pathArray.length > 0) {
|
||||
this.$refs.mapbox.drawHistoryPathByIndex(pathArray, index)
|
||||
}
|
||||
})
|
||||
|
||||
// 跳转到第一个轨迹的起点(经纬度)
|
||||
if (this.flyDataList.length > 0 && this.flyDataList[0].gps_path) {
|
||||
try {
|
||||
const firstPath = JSON.parse(this.flyDataList[0].gps_path)
|
||||
if (Array.isArray(firstPath) && firstPath.length > 0) {
|
||||
const [lon, lat] = firstPath[0]
|
||||
this.$refs.mapbox.goto({ lon, lat })
|
||||
// 跳转到第一条轨迹的第一个点
|
||||
const firstPath = this.flyDataList[0]?.gps_path
|
||||
let firstPoint = null
|
||||
if (firstPath) {
|
||||
if (typeof firstPath === 'string') {
|
||||
try {
|
||||
firstPoint = JSON.parse(firstPath)[0]
|
||||
} catch {
|
||||
firstPoint = null
|
||||
}
|
||||
} catch (e) {
|
||||
// 解析失败不跳转
|
||||
} else if (Array.isArray(firstPath)) {
|
||||
firstPoint = firstPath[0]
|
||||
}
|
||||
}
|
||||
if (firstPoint && Array.isArray(firstPoint) && firstPoint.length >= 2) {
|
||||
const [lon, lat] = firstPoint
|
||||
this.$refs.mapbox.goto({ lon, lat })
|
||||
}
|
||||
},
|
||||
|
||||
// 获取飞行数据
|
||||
async loadFlyData () {
|
||||
if (this.selectedPlaneIdArr.length === 0) {
|
||||
@ -280,7 +314,13 @@ export default {
|
||||
xAxis: { type: 'category' },
|
||||
yAxis: {
|
||||
gridIndex: 0,
|
||||
name: this.radioClass === '飞行时长' ? '分钟' : this.radioClass === '飞行距离' ? '米' : '毫安'
|
||||
name: this.radioClass === '飞行时长'
|
||||
? '分钟'
|
||||
: this.radioClass === '飞行距离'
|
||||
? '米'
|
||||
: this.radioClass === '消耗电量'
|
||||
? '毫安'
|
||||
: '架次'
|
||||
},
|
||||
grid: { top: '55%' },
|
||||
series: [
|
||||
|
Loading…
Reference in New Issue
Block a user