【类 型】:feat

【原  因】:创建集群控制组件页面 添加到版本管理
【过  程】:
【影  响】:

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
This commit is contained in:
szdot 2025-06-22 15:19:51 +08:00
parent 6126b9d137
commit 3b4940ac4a

View File

@ -0,0 +1,246 @@
<template>
<div class="h-100">
<!-- 地图组件 -->
<map-box ref="mapbox" :enableShowNofly="true" :enableGuided="true" :enableFollow="true"
:enblueScale="!$store.state.app.isWideScreen" @longPress="handleLongPress" @map-ready="onMapReady">
<template #content>
<div v-show="mapReady">
<BatteryStatus :plane="plane" />
<PlaneStatus :plane="plane" />
<ControllerTabs :plane="plane" @mapXOffset="mapXOffset" @makeRoute="makeRoute" @clearRoute="clearRoute" />
</div>
</template>
</map-box>
<!-- 弹出框 -->
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="320px" top="30vh" @close="closeCallback"
@open="openCallback">
<!-- 点飞设置弹出框 -->
<template v-if="dialogItem == 'guidedBox'">
<el-form label-position="left">
<el-form-item label="纬度" label-width="80px">
<el-input v-model="guidedLonLat.lat" placeholder="请输维度" label="纬度"></el-input>
</el-form-item>
<el-form-item label="经度" label-width="80px">
<el-input v-model="guidedLonLat.lon" placeholder="请输经度" label="经度"></el-input>
</el-form-item>
<el-form-item label="高度设置" label-width="80px">
<el-input-number v-model="guidedAlt" label="高度设置"></el-input-number>
<font class="m-l-5"></font>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button size="medium" @click="dialogVisible = false">关闭</el-button>
<el-button size="medium" type="primary"
@click="publishFun(`{guidedMode:{lon:${guidedLonLat.lon},lat:${guidedLonLat.lat},alt:${guidedAlt}}`); isReserveGuidedMaker = true; dialogVisible = false">飞至</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script>
import MapBox from '@/components/MapBox'
import ControllerTabs from '@/components/ControllerTabs'
import BatteryStatus from '@/components/BatteryStatus'
import PlaneStatus from '@/components/PlaneStatus'
import mqtt from '@/utils/mqtt'
import { waitForMapCanvasReady } from '@/utils'
export default {
name: 'Planes',
data () {
return {
dialogTitle: '', //
dialogItem: '', //
dialogVisible: false, //
guidedLonLat: {}, //
guidedAlt: '', //
isReserveGuidedMaker: false, //
planesId: this.$route.params.id,
localCount: 0, //
mapReady: false//
}
},
components: {
MapBox,
ControllerTabs,
BatteryStatus,
PlaneStatus
},
computed: {
plane () {
if (this.$store.state.airList.length > 0) {
return this.$store.state.airList.find(plane => plane.id === this.planesId)
}
return null
},
position () {
if (this.plane) {
if (this.plane.planeState.position.length > 0) {
return this.plane.planeState.position
} else {
return []
}
} else {
return []
}
},
noflyData () {
return this.$store.state.noflyData
},
ADSBList () {
return this.$store.state.ADSBList
},
/**
* @description: 侧边栏显隐
*/
isCollapse () {
return this.$store.state.app.isCollapse
}
},
methods: {
/** 弹出框 关闭事件回调 */
closeCallback () {
if (this.dialogItem === 'guidedBox' && this.isReserveGuidedMaker === false) { //
this.$refs.mapbox.delGuidedMarker()//
}
this.dialogVisible = false
this.dialogItem = ''
},
/** 弹出框 打开事件回调 */
openCallback () {
},
//
handleLongPress (lonLat) {
this.isReserveGuidedMaker = false
this.dialogTitle = '指点飞行'
this.dialogVisible = true
this.dialogItem = 'guidedBox'
this.guidedLonLat = lonLat //
//
let height = 0
if (this.plane && this.plane.planeState && Array.isArray(this.plane.planeState.position)) {
const posLen = this.plane.planeState.position.length
if (posLen > 0 && Array.isArray(this.plane.planeState.position[posLen - 1])) {
height = this.plane.planeState.position[posLen - 1][2] || 0
}
}
this.guidedAlt = height
},
//
onMapReady () {
this.mapReady = true//
this.makePlane(this.plane)
},
/**
* @description: 创建飞机图标
*/
makePlane (plane) {
let planeDefaultLonLat
if (localStorage.getItem(plane.name)) { //
planeDefaultLonLat = JSON.parse(localStorage.getItem(plane.name))
plane.lon = planeDefaultLonLat.lon
plane.lat = planeDefaultLonLat.lat
} else {
// 10
plane.lon = 100 + Number((Math.random() * 0.01).toFixed(5))
plane.lat = 40 + Number((Math.random() * 0.01).toFixed(5))
}
this.$refs.mapbox.removePlanes()//
this.$refs.mapbox.makePlane(plane)//
this.$refs.mapbox.goto({ lon: plane.lon, lat: plane.lat })//
},
/**
* @description: 创建航线
*/
makeRoute (routeData) {
this.$refs.mapbox.makeRoute(routeData)
},
/**
* @description: 清楚航线
*/
clearRoute () {
this.$refs.mapbox.clearRoute()
},
/**
* @description: 屏幕横移
* @param {*} val 正数向左移动 负数向右移动
* @param {*} y 正数向上移动 负数向下移动
*/
mapXOffset (x, y) {
this.$refs.mapbox.mapXOffset(x, y)
},
/**
* @description: 发布 mqtt 信息
* @param {*} jsonData {'item':val} // item: questAss setQuestState resetQuestState chan11 chan22 chan33 chan44 hookConteroller cameraController
*/
publishFun (jsonData) {
if (this.plane) {
mqtt.publishFun(`cmd/${this.plane.macadd}`, jsonData)
} else {
this.$message.warning('与飞机通信未接通,请稍后')
}
}
},
mounted () {
},
watch: {
plane: {
async handler () {
try {
//
await waitForMapCanvasReady(this.map)
//
this.onMapReady()
} catch (err) {
console.debug('等待地图画布准备超时', err)
}
},
immediate: true
},
/**
* @description: 更新飞机位置 并画出轨迹 跟随飞机
*/
position: {
handler (val) {
const len = val.length
if (len > 2) {
const lon = val[len - 1][0]
const lat = val[len - 1][1]
this.localCount++//
if (this.localCount % 100 === 1) {
localStorage.setItem(this.plane.name, `{ "lon": ${lon}, "lat": ${lat} }`)
}
this.$refs.mapbox.setPlaneLonLat({ lon: lon, lat: lat }, 0, val)//
}
},
deep: true
},
ADSBList: {
handler (newList) {
if (this.$refs.mapbox && typeof this.$refs.mapbox.makeADSBPlanes === 'function') {
this.$refs.mapbox.makeADSBPlanes(newList)
}
},
immediate: true,
deep: true
},
/**
* @description: 侧边栏缩进有变化时 地图重新自适应
*/
isCollapse: {
handler (val) {
if (val) {
this.$nextTick(() => {
this.$refs.mapbox.handleResize()
})
}
}
}
}
}
</script>
<style lang="scss" scoped></style>