【类 型】:feat
【原 因】: 【过 程】:1.优化飞机状态组件 在飞将列表里面加入 在线字段 解锁字段 2.增加概况多架飞机 状态组件 【影 响】: # 类型 包含: # feat:新功能(feature) # fix:修补bug # docs:文档(documentation) # style: 格式(不影响代码运行的变动) # refactor:重构(即不是新增功能,也不是修改bug的代码变动) # test:增加测试 # chore:构建过程或辅助工具的变动
This commit is contained in:
parent
e7506728af
commit
e14aa9a975
@ -8,6 +8,7 @@
|
||||
import mapboxgl from 'mapbox-gl'
|
||||
import { MapboxStyleSwitcherControl, FollowControl, CustomFullscreenControl, NoFlyControl, RestrictflyControl, SaveToFileControl, PolygonToggleControl } from '@/utils/mapboxgl_plugs'
|
||||
import planeIcon from '@/assets/svg/plane.svg'
|
||||
// import unlineIcon from '@/assets/svg/plane_unline.svg'
|
||||
import civilIcon from '@/assets/svg/civil.svg'
|
||||
|
||||
export default {
|
||||
|
@ -1,15 +1,16 @@
|
||||
<template>
|
||||
<div class="mainBox flex column no-select">
|
||||
<!-- 心跳 -->
|
||||
<!-- 心跳 ps:黑色只网络通 绿色飞控有效心跳-->
|
||||
<div class="flex">
|
||||
<div class="tag flex mac mc iconfont"
|
||||
:class="online ? heartAnimation ? 'icon-heart online' : 'icon-heart1 online' : 'icon-xinsui offline'">
|
||||
<div class="tag flex mac mc iconfont" :class="[
|
||||
online ? (heartAnimation ? 'icon-heart online' : 'icon-heart1 online') : 'icon-xinsui offline',
|
||||
plane.heartBeat ? 'useful-heart' : ''
|
||||
]">
|
||||
</div>
|
||||
</div>
|
||||
<!-- 锁定状态 -->
|
||||
<!-- 解锁状态 -->
|
||||
<div class="flex">
|
||||
<div class="tag flex mac mc iconfont" :class="isLockState ? 'icon-suoding' : 'icon-jiesuo'">
|
||||
</div>
|
||||
<div class="tag flex mac mc iconfont" :class="isUnlock ? 'icon-jiesuo' : 'icon-suoding'"></div>
|
||||
</div>
|
||||
<!-- 飞机模式 -->
|
||||
<div class="flex">
|
||||
@ -22,7 +23,7 @@
|
||||
<!-- 卫星 -->
|
||||
<div class="flex">
|
||||
<div v-if="satCount" class="plane-mode p-l-5 p-r-5 mc mac">
|
||||
<font class="plane-mode-text">{{ fixType }} {{ satCount }}颗</font>
|
||||
<font class="plane-mode-text">{{ fixType }} {{ satCount }}颗</font>
|
||||
</div>
|
||||
<div class="tag flex mac mc iconfont icon-weixing">
|
||||
</div>
|
||||
@ -62,7 +63,9 @@
|
||||
<!-- 飞机载重 钩子状态 -->
|
||||
<div class="flex">
|
||||
<div v-if="loadweight" class="plane-mode p-l-5 p-r-5 mc mac">
|
||||
<font class="plane-mode-text">{{hookstatus}} {{ loadweight }}克</font>
|
||||
<font class="plane-mode-text" v-if="hookstatus || loadweight">
|
||||
{{ hookstatus || '' }} {{ loadweight ? loadweight + '克' : '' }}
|
||||
</font>
|
||||
</div>
|
||||
<div class="tag flex mac mc iconfont icon-mianxingdiaogou">
|
||||
</div>
|
||||
@ -78,9 +81,7 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
/* 心跳 */
|
||||
heartAnimation: false, // 控制心跳动画图标
|
||||
online: false,
|
||||
isOnlineSetTimeout: null
|
||||
heartAnimation: false // 控制心跳动画图标
|
||||
}
|
||||
},
|
||||
props: {
|
||||
@ -92,6 +93,10 @@ export default {
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
// 飞机在线状态
|
||||
online () {
|
||||
return this.plane?.online ?? false
|
||||
},
|
||||
// 心跳随机数
|
||||
heartRandom () {
|
||||
if (this.plane && this.plane.planeState) {
|
||||
@ -99,14 +104,9 @@ export default {
|
||||
}
|
||||
return null
|
||||
},
|
||||
// 锁定状态
|
||||
isLockState () {
|
||||
if (this.plane && this.plane.planeState) {
|
||||
if (Number(this.plane.planeState.heartBeat) & 128) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
// 解锁状态
|
||||
isUnlock () {
|
||||
return this.plane?.planeState?.isUnlock ?? false
|
||||
},
|
||||
// 飞机模式
|
||||
getPlaneMode () {
|
||||
@ -180,20 +180,11 @@ export default {
|
||||
watch: {
|
||||
heartRandom: {
|
||||
handler () {
|
||||
console.log('心跳:', this.plane.heartBeat)
|
||||
// 心跳动画
|
||||
this.heartAnimation = true
|
||||
setTimeout(() => {
|
||||
this.heartAnimation = false
|
||||
}, 500)
|
||||
// 在线状态
|
||||
if (this.isOnlineSetTimeout) { // 进入本次心跳 删除掉线计时 既以下会重新计时
|
||||
clearInterval(this.isOnlineSetTimeout)
|
||||
}
|
||||
this.online = true
|
||||
this.isOnlineSetTimeout = setTimeout(() => { // 计时10秒后 掉线
|
||||
this.online = false
|
||||
}, 10000)
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -203,9 +194,6 @@ export default {
|
||||
created () {
|
||||
},
|
||||
destroyed () {
|
||||
if (this.isOnlineSetTimeout) {
|
||||
clearInterval(this.isOnlineSetTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -249,6 +237,11 @@ export default {
|
||||
|
||||
.plane-mode-text {
|
||||
display: inline-block;
|
||||
white-space: nowrap; /* 防止内容换行 */
|
||||
white-space: nowrap;
|
||||
/* 防止内容换行 */
|
||||
}
|
||||
|
||||
.useful-heart {
|
||||
color: $success-color;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,17 +1,44 @@
|
||||
<template>
|
||||
<div class="mainBox flex column no-select">
|
||||
<!-- 心跳 -->
|
||||
<!-- <div class="flex">
|
||||
<div class="tag flex mac mc iconfont"
|
||||
:class="online ? heartAnimation ? 'icon-heart online' : 'icon-heart1 online' : 'icon-xinsui offline'">
|
||||
<div class="flex stat-row">
|
||||
<div class="plane-mode p-l-5 p-r-5 mc mac">
|
||||
<font class="plane-mode-text">总架数:{{ totalCount }}</font>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="tag flex mac mc iconfont icon-zongshu"></div>
|
||||
</div>
|
||||
|
||||
<div class="flex stat-row">
|
||||
<div class="plane-mode p-l-5 p-r-5 mc mac">
|
||||
<font class="plane-mode-text">在线数:{{ onlineCount }}</font>
|
||||
</div>
|
||||
<div class="tag flex mac mc iconfont icon-zaixian1"></div>
|
||||
</div>
|
||||
|
||||
<div class="flex stat-row">
|
||||
<div class="plane-mode p-l-5 p-r-5 mc mac">
|
||||
<font class="plane-mode-text">总作业架数:{{ unlockedCount }}</font>
|
||||
</div>
|
||||
<div class="tag flex mac mc iconfont icon-wurenjijiesuo"></div>
|
||||
</div>
|
||||
|
||||
<div class="flex stat-row">
|
||||
<div class="plane-mode p-l-5 p-r-5 mc mac">
|
||||
<font class="plane-mode-text">总作业时长:{{ formattedDuration }}</font>
|
||||
</div>
|
||||
<div class="tag flex mac mc iconfont icon-shichang"></div>
|
||||
</div>
|
||||
|
||||
<div class="flex stat-row">
|
||||
<div class="plane-mode p-l-5 p-r-5 mc mac">
|
||||
<font class="plane-mode-text">作业总数:{{ totalWorkingDistance.toFixed(1) }} 米</font>
|
||||
</div>
|
||||
<div class="tag flex mac mc iconfont icon-pin-distance-line"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import geodist from 'geodist'
|
||||
|
||||
export default {
|
||||
name: 'Statistics',
|
||||
@ -20,7 +47,7 @@ export default {
|
||||
}
|
||||
},
|
||||
props: {
|
||||
plane: {
|
||||
planes: {
|
||||
type: Object,
|
||||
deep: true
|
||||
}
|
||||
@ -28,6 +55,52 @@ export default {
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
totalCount () {
|
||||
return Object.keys(this.planes || {}).length
|
||||
},
|
||||
onlineCount () {
|
||||
return Object.values(this.planes || {}).filter(p => p.planeState?.online).length
|
||||
},
|
||||
totalWorkingDuration () {
|
||||
// 所有处于解锁状态的飞机,加上当前时长(当前时间 - startTime)
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
return Object.values(this.planes || {}).reduce((total, p) => {
|
||||
const s = p.planeState?.flyDataSave?.startTime
|
||||
const isUnlock = p.planeState?.isUnlock
|
||||
if (isUnlock && s) {
|
||||
return total + (now - s)
|
||||
}
|
||||
return total
|
||||
}, 0)
|
||||
},
|
||||
totalWorkingDistance () {
|
||||
let totalDistance = 0
|
||||
Object.values(this.planes || {}).forEach(p => {
|
||||
const path = p.planeState?.flyDataSave?.path || []
|
||||
for (let i = 1; i < path.length; i++) {
|
||||
const prev = path[i - 1]
|
||||
const curr = path[i]
|
||||
if (prev && curr) {
|
||||
totalDistance += geodist(
|
||||
{ lat: prev[1], lon: prev[0] },
|
||||
{ lat: curr[1], lon: curr[0] },
|
||||
{ exact: true, unit: 'meters' }
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
return totalDistance
|
||||
},
|
||||
unlockedCount () {
|
||||
return Object.values(this.planes || {}).filter(p => p.planeState?.isUnlock).length
|
||||
},
|
||||
formattedDuration () {
|
||||
const sec = this.totalWorkingDuration
|
||||
const h = Math.floor(sec / 3600).toString().padStart(2, '0')
|
||||
const m = Math.floor((sec % 3600) / 60).toString().padStart(2, '0')
|
||||
const s = (sec % 60).toString().padStart(2, '0')
|
||||
return `${h}:${m}:${s}`
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
@ -83,4 +156,11 @@ export default {
|
||||
display: inline-block;
|
||||
white-space: nowrap; /* 防止内容换行 */
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 0 6px;
|
||||
height: 29px;
|
||||
line-height: 29px;
|
||||
font-size: 13px;
|
||||
}
|
||||
</style>
|
||||
|
@ -65,7 +65,7 @@ const routes = [
|
||||
redirect: '/model/index',
|
||||
meta: {
|
||||
title: '机型管理',
|
||||
icon: 'el-icon-edit-outline',
|
||||
icon: 'iconfont icon-chuiqigudingyi',
|
||||
roles: ['admin', 'editor'],
|
||||
tapName: 'plane'
|
||||
},
|
||||
|
@ -348,7 +348,7 @@ const store = new Vuex.Store({
|
||||
const res = await api.get('getAirList')
|
||||
res.data.airList.forEach(plane => {
|
||||
plane.planeState = { // 飞机状态初始化字段
|
||||
flyDataMark: false, // 飞机解锁标记成真
|
||||
isUnlock: false, // 飞机解锁标记成真
|
||||
flyDataSave: { // 飞机加锁截至 待上传飞行数据之后 再清空此值
|
||||
startTime: null, // 解锁时的时间戳(秒)
|
||||
endTime: null, // 加锁时的时间戳(秒)
|
||||
@ -358,6 +358,8 @@ const store = new Vuex.Store({
|
||||
},
|
||||
heartBeat: null, // 心跳
|
||||
heartRandom: null, // 每次接收到心跳创建一个随机数 用于watch监听
|
||||
online: false, // 是否在线
|
||||
onlineTimeout: null, // 存放定时器引用
|
||||
voltagBattery: null, // 电压信息
|
||||
currentBattery: null, // 电流信息
|
||||
batteryRemaining: null, // 电池电量
|
||||
|
@ -1 +1 @@
|
||||
@import 'https://at.alicdn.com/t/c/font_3703467_cqwk36imkj.css'; //iconfont阿里巴巴
|
||||
@import 'https://at.alicdn.com/t/c/font_3703467_17bw22w7wt3g.css'; //iconfont阿里巴巴
|
@ -3,7 +3,7 @@
|
||||
<map-box ref="mapbox" @map-ready="onMapReady">
|
||||
<template #content>
|
||||
<div v-show="mapReady">
|
||||
<!-- <Statistics :plane="plane" /> -->
|
||||
<Statistics :planes="airList" />
|
||||
</div>
|
||||
</template>
|
||||
</map-box>
|
||||
@ -13,7 +13,7 @@
|
||||
<script>
|
||||
import MapBox from '@/components/MapBox'
|
||||
import { waitForMapCanvasReady } from '@/utils'
|
||||
// import Statistics from '@/components/Statistics'
|
||||
import Statistics from '@/components/Statistics'
|
||||
|
||||
export default {
|
||||
name: 'Home',
|
||||
@ -23,8 +23,8 @@ export default {
|
||||
}
|
||||
},
|
||||
components: {
|
||||
MapBox
|
||||
// Statistics
|
||||
MapBox,
|
||||
Statistics
|
||||
},
|
||||
computed: {
|
||||
airList () {
|
||||
|
@ -6,7 +6,7 @@
|
||||
<template #content>
|
||||
<div v-show="mapReady">
|
||||
<!-- <SwarmStatus :planes="planeList" /> -->
|
||||
<SwarmControllerTabs :planes="planeList" @mapXOffset="mapXOffset" @makeRoute="makeRoute" @clearRoute="clearRoute" />
|
||||
<SwarmControllerTabs :planes="planeList"/>
|
||||
</div>
|
||||
</template>
|
||||
</map-box>
|
||||
|
@ -151,13 +151,26 @@ export default {
|
||||
plane.planeState.heartRandom = Math.random()
|
||||
plane.planeState.heartBeat = jsonData.heartBeat
|
||||
|
||||
const oldMark = plane.planeState.flyDataMark
|
||||
/* 判断飞机是否在线 */
|
||||
// 设置为在线
|
||||
plane.planeState.online = true
|
||||
// 清除旧的离线定时器
|
||||
if (plane.planeState.onlineTimeout) {
|
||||
clearTimeout(plane.planeState.onlineTimeout)
|
||||
}
|
||||
// 重新设定掉线判断定时器(如10秒内无心跳,则为离线)
|
||||
plane.planeState.onlineTimeout = setTimeout(() => {
|
||||
plane.planeState.online = false
|
||||
}, 10000)
|
||||
|
||||
/* 飞行数据上传 */
|
||||
const oldMark = plane.planeState.isUnlock
|
||||
const newMark = (Number(jsonData.heartBeat) & 128) !== 0
|
||||
|
||||
// 解锁状态变更检测:用于控制飞行数据的采集与上传
|
||||
if (!oldMark && newMark) {
|
||||
// 从加锁切换为解锁:初始化飞行数据记录
|
||||
plane.planeState.flyDataMark = true
|
||||
plane.planeState.isUnlock = true
|
||||
plane.planeState.flyDataSave = {
|
||||
startTime: Math.floor(Date.now() / 1000), // 解锁时间(秒)
|
||||
startBattery: plane.planeState.batteryRemaining,
|
||||
@ -166,7 +179,7 @@ export default {
|
||||
path: []
|
||||
}
|
||||
} else if (oldMark && !newMark) {
|
||||
plane.planeState.flyDataMark = false
|
||||
plane.planeState.isUnlock = false
|
||||
|
||||
this.handleFlightDataUpload(plane) // 上传飞行数据
|
||||
|
||||
@ -192,7 +205,7 @@ export default {
|
||||
plane.planeState.position.shift() // 删除最早的经纬度
|
||||
}
|
||||
// 如果是解锁状态,记录轨迹用于上传
|
||||
if (plane.planeState.flyDataMark && plane.planeState.flyDataSave?.path) {
|
||||
if (plane.planeState.isUnlock && plane.planeState.flyDataSave?.path) {
|
||||
plane.planeState.flyDataSave.path.push([
|
||||
position.lon / 10e6,
|
||||
position.lat / 10e6,
|
||||
|
Loading…
Reference in New Issue
Block a user