Przeglądaj źródła

Merge branch 'lixin' of gitadmin/tuoheng_lc_web into develop

tags/v1.2.0
lixin 1 rok temu
rodzic
commit
3ec9a07bf0
5 zmienionych plików z 248 dodań i 99 usunięć
  1. +30
    -0
      src/api/task/index.js
  2. +7
    -4
      src/views/dashboard/components/FireAlarm.vue
  3. +12
    -4
      src/views/dashboard/components/OneMap.vue
  4. +114
    -72
      src/views/dashboard/components/Underlay.vue
  5. +85
    -19
      src/views/dashboard/components/WarningDrawer.vue

+ 30
- 0
src/api/task/index.js Wyświetl plik

@@ -163,3 +163,33 @@ export function getQuestions(params) {
params
})
}

/**
* 控制无人机
* @param { } params
* @returns
*/
export function controlAir(params) {
return request({
url: `/airport/drone/control`,
method: 'POST',
params
})
}

// 根据应急任务ID查询预警记录
export function emergencyRecord(params) {
return request({
url: `/warning/record/one/by/emergencyMissionId`,
method: 'GET',
params
})
}

// 获取无人机数据
export function uavInfo(id) {
return request({
url: `/airport/drone/data/${id}`,
method: 'GET'
})
}

+ 7
- 4
src/views/dashboard/components/FireAlarm.vue Wyświetl plik

@@ -32,7 +32,7 @@
<span>飞行高度:</span>
<n-slider v-model:value="flyHeight" :default-value="100" :format-tooltip="formatHeight" :max="600" @update:value="limitMin" />
</p>
<p class="execute-btn" @click="test">立即执行</p>
<p class="execute-btn" @click="executeNow">立即执行</p>
<p class="alarm-title">任务记录</p>
<div class="task-log">
<ul>
@@ -94,6 +94,7 @@
import { reactive, toRefs, watch } from 'vue'
import { EARLY_SOURCE, TASK_STATUS } from '@/utils/dictionary.js'
import { getWarningRecord, getWarningInfo, ignoreWarning, confirmWarning, pointflight } from '@/api/dashboard/index.js'
import { useInspectionStore } from '@/store/modules/inspection.js'
// turf 用于简单的空间计算
import * as turf from '@turf/turf'
export default {
@@ -111,6 +112,7 @@ export default {
},
emits: ['start'],
setup(props, { emit }) {
const inspectionStore = useInspectionStore()
const data = reactive({
airpotOptions: [],
airport: {},
@@ -242,7 +244,7 @@ export default {
data.warningShow = false
}

const test = async() => {
const executeNow = async() => {
var airportName = ''
data.airpotOptions?.map((item) => {
if (item.value === data.airportId) {
@@ -261,7 +263,7 @@ export default {

if (res.code === 0) {
getRecord(parseInt(data.warningInfo?.id))
handleExecute()
handleExecute(res.data?.emergencyMissionId)
}
}

@@ -290,6 +292,7 @@ export default {
return value + 'm'
}

// 立即执行 传入应急任务id
const handleExecute = (id) => {
emit('start', id)
}
@@ -299,7 +302,7 @@ export default {
formatHeight,
checkAirport,
closeAirport,
test,
executeNow,
closeWarning,
ignore,
confirm,

+ 12
- 4
src/views/dashboard/components/OneMap.vue Wyświetl plik

@@ -54,7 +54,7 @@ import { Point } from 'ol/geom'
import {
airportList, getWarning
} from '@/api/dashboard/index.js'
import { getQuestions } from '@/api/task/index.js'
import { getTaskDetail } from '@/api/task/index.js'
import { gcj02towgs84 } from '@/utils/coordinate-util.js'
import AirInfo from './AirInfo.vue'
import ProblemInfo from './ProblemInfo.vue'
@@ -678,8 +678,15 @@ export default {
monitorVideo.value?.disposeVideo()
}

const handleExecute = () => {
data.drawerShow = true
const handleExecute = async(value) => {
const res = await getTaskDetail(value)
if (res.code === 0) {
inspectionStore.setList(res.data)
}
}

const refreshRecord = () => {

}

watch(() => inspectionStore.getList, (val) => {
@@ -716,7 +723,8 @@ export default {
hideProblemInfo,
getMaxZOverlay,
Warning,
handleExecute
handleExecute,
refreshRecord
}
}
}

+ 114
- 72
src/views/dashboard/components/Underlay.vue Wyświetl plik

@@ -14,6 +14,7 @@ import Point from 'ol/geom/Point'
import { XYZ, Vector as VectorSource } from 'ol/source'
import { transform, fromLonLat } from 'ol/proj'
import { getVectorContext } from 'ol/render'
import VectorContext from 'ol/render/VectorContext'
import * as control from 'ol/control'
import { styleList } from '@/utils/style.js'
import { getTrackList } from '@/api/task/index.js'
@@ -31,38 +32,22 @@ export default {
const inspectionStore = useInspectionStore()
const data = reactive({
map: null,
view: null,
drawerShow: false,
trackLayer: null,
trackInfo: null,
// 轨迹数据
trackList: []
trackList: [],
socket: null,
liveTrackLayer: null
})

console.log(inspectionStore.getList)

const getMapOptions = computed(() => {
return {
id: props.id
}
})

// watch(() => props.idd, (value) => {
// if (value) {
// console.log('hhh', value)
// } else {
// console.log('hhh', value)
// }

// })

// if (props.ttest) {
// getTrackData(props.ttest.missionId).then(res => {
// if (res.trackList.length > 0) {
// initTrack(formatTradeList(res.trackList), 'route')
// }
// })
// }

/**
* 初始化地图
*/
@@ -80,14 +65,16 @@ export default {
params: { LAYERS: 'jiangning:town' }
})
})

data.view = new View({
center: transform([118.773136, 31.828065], 'EPSG:4326', 'EPSG:3857'),
zoom: 11,
maxZoom: 17
})
data.map = new Map({
// 地图容器
target: props.id,
view: new View({
center: transform([118.773136, 31.828065], 'EPSG:4326', 'EPSG:3857'),
zoom: 11,
maxZoom: 17
}),
view: data.view,
layers: [tdtImgMap],
controls: control.defaults({
attribution: false,
@@ -100,72 +87,123 @@ export default {
}

/* 获取轨迹数据 */
const getTrackData = async function(id) {
const res = await getTrackList(id)
const getTrackData = async function() {
const res = await getTrackList(inspectionStore.getList.id)
const trackList = res.data
data.trackList = trackList
// const trackList = data.trackList
return Promise.resolve({
trackList
})
}

/* 处理轨迹列表 */
const formatTradeList = function(trackList) {
return trackList.map((item) =>
fromLonLat([parseFloat(item.lng), parseFloat(item.lat)])
)
if (inspectionStore.getList.id) {
if (!data.map) {
getTrackData().then(({ trackList }) => {
setLiveTrack(formatTradeList(trackList))
})
}
}

/* 加载实时轨迹 */
const setLiveTrack = function(hisTrackList) {
data.animating = false
data.disdance = 0
var changeTrack
if (hisTrackList.length > 1) {
data.trackInfo = initTrack(hisTrackList, 'liveTrackLayer', 'route')
if (data.trackInfo.vectorLayer) {
data.liveTrackLayer.on('change', changeTrack)
}
}

/* 轨迹改变 */
changeTrack = (event) => {
try {
const vectorContext = getVectorContext(event)
vectorContext.setStyle(styleList['geoMarker'])
VectorContext.drawGeometry(data.trackInfo.position)
vectorContext.drawGeometry(data.trackInfo.route)
data.map.render()
} catch {
console.log(event)
}
}

// 两秒钟获取一次数据
data.socket = setInterval(() => {
getTrackData().then(({ trackList }) => {
const len = trackList.length
const obj = trackList[len - 1]
const coordinate = fromLonLat([obj?.lng, obj?.lat])
if (data.trackInfo) {
data.trackInfo.route.appendCoordinate(coordinate)
data.trackInfo.vectorLayer.getSource().changed()
data.trackInfo.position.setCoordinates(coordinate)
}
})
}, 2000)
}

/* 初始化轨迹 */
const initTrack = function(coordinate, routeType) {
const initTrack = function(coordinate, layer, routeType) {
let vectorLayer = null
// 路线
const route = new LineString(coordinate)
const routeFeature = new Feature({
type: routeType,
geometry: route
})
const startMarker = new Feature({
const endMarker = new Feature({
type: 'icon',
geometry: new Point(route.getFirstCoordinate())
geometry: new Point(route.getLastCoordinate())
})
const position = startMarker.getGeometry().clone()
const geoMarker = new Feature({
type: 'geoMarker',
geometry: position
})
geoMarker.setProperties({ type: 'geoMarker' }, false)
if (data.trackLayer) {
data.trackLayer.setSource(
new VectorSource({
features: [geoMarker, routeFeature]
})
)
vectorLayer = data.trackLayer
} else {
vectorLayer = new VectorLayer({
source: new VectorSource({
features: [geoMarker, routeFeature]
}),
style: function(feature) {
return styleList[feature.get('type')]
}
const position = endMarker.getGeometry().clone()
if (routeType === 'route') { // 轨迹数据
const geoMarker = new Feature({
type: 'geoMarker',
geometry: position
})
geoMarker.setProperties({ type: 'geoMarker' }, false)
if (data.liveTrackLayer) {
data.liveTrackLayer.setSource(
new VectorSource({
features: [geoMarker, routeFeature]
})
)
vectorLayer = data.liveTrackLayer
} else {
vectorLayer = new VectorLayer({
source: new VectorSource({
features: [geoMarker, routeFeature]
}),
style: function(feature) {
return styleList[feature.get('type')]
}
})
}
data[layer] = vectorLayer
data.map.addLayer(data[layer])
data.view.fit(route, { padding: [50, 50, 50, 50] })
return {
vectorLayer,
geoMarker,
route,
position
}
}
data.mapData.addLayer(vectorLayer)
data.mapView.fit(route, { padding: [50, 50, 50, 50] })
vectorLayer.on('postrender', moveFeature.bind())
function moveFeature(event) {
/* 计算飞行的百分比 */
const percent = data.videoInfo.currentTime / data.videoInfo.duration
const currentCoordinate = route.getCoordinateAt(percent)
position.setCoordinates(currentCoordinate)
geoMarker.setGeometry(null)
const vectorContext = getVectorContext(event)
vectorContext.setStyle(styleList['geoMarker'])
vectorContext.drawGeometry(position)
data.mapData?.render()
}
}

/* 处理轨迹列表 */
const formatTradeList = function(trackList) {
return trackList.map((item) =>
fromLonLat([parseFloat(item.lng), parseFloat(item.lat)])
)
}

// 结束直播飞行
const endLiveFly = () => {
clearInterval(data.socket)
data.socket = null
}

onMounted(() => {
@@ -173,11 +211,15 @@ export default {
})

onBeforeUnmount(() => {
clearInterval(data.socket)
data.socket = null
})

return {
...toRefs(data),
getMapOptions
getMapOptions,
endLiveFly,
initTrack
}
}
}

+ 85
- 19
src/views/dashboard/components/WarningDrawer.vue Wyświetl plik

@@ -1,6 +1,6 @@
<template>
<n-drawer v-bind="getDrawerOptions" @update:show="handleDrawerColse">
<n-drawer-content closable title="报告详情">
<n-drawer-content closable title="机场调度">
<div ref="containerRef" class="warning__container">

<div class="warning__side">
@@ -48,32 +48,38 @@
</div>

<div class="control__panel">
<SpeedChart :data="chartData" />
<ControlPanel v-if="showControl" mode="camera" @start="startOrder" @reset="endOrder" />
<ControlPanel v-if="showControl" mode="locus" @start="startOrder" @reset="endOrder" />
<!-- <SpeedChart :data="chartData" /> -->
<ControlPanel v-if="showControl" mode="camera" @instruct="sendControl" />
<ControlPanel v-if="showControl" mode="locus" @instruct="sendControl" />
</div>

</div>
<div ref="mapRef" class="warn__back">
<Underlay />
<Underlay ref="baseMap" />
</div>
<div ref="videoRef" class="inner">
111111111111
<VideoPlayer
id="emergency-video"
ref="emergencyVideo"
style="position: absolute;left: 0;top: 0"
/>
</div>
</n-drawer-content>
</n-drawer>
</template>

<script>
import { defineComponent, ref, reactive, toRefs, computed, watch, nextTick } from 'vue'
import { defineComponent, ref, reactive, toRefs, computed, watch, nextTick, onBeforeUnmount } from 'vue'
import Underlay from './Underlay.vue'
import ControlPanel from './ControlPanel.vue'
import SpeedChart from './SpeedChart.vue'
import { useInspectionStore } from '@/store/modules/inspection.js'
import VideoPlayer from '@/components/VideoPlayer/index.vue'
import { controlAir, emergencyRecord, uavInfo } from '@/api/task/index.js'

export default defineComponent({
name: 'WarningDrawer',
components: { Underlay, ControlPanel, SpeedChart },
components: { Underlay, ControlPanel, SpeedChart, VideoPlayer },
props: {
/* 可见 */
visible: {
@@ -84,17 +90,24 @@ export default defineComponent({
data: {
type: Object,
default: () => {}
},
id: {
type: Number,
default: 0
}
},
emits: {
'update:visible': null
'update:visible': null,
'refresh:id': null
},
setup(props, { emit }) {
const inspectionStore = useInspectionStore()
const containerRef = ref()
const sideRef = ref()
const mapRef = ref()
const baseMap = ref()
const videoRef = ref()
const emergencyVideo = ref()
const data = reactive({
hasChanged: false,
showControl: false,
@@ -114,7 +127,23 @@ export default defineComponent({
/* 关闭抽屉 */
function handleDrawerColse() {
emit('update:visible', false)
inspectionStore.resetList()
getEmergencyRecord(inspectionStore.getList.id)
// inspectionStore.resetList()
// 结束直播飞行
// baseMap.value?.endLiveFly()
// 关闭视频播放
emergencyVideo.value?.disposeVideo()

// emit('refresh:id')
}

const getEmergencyRecord = async(id) => {
const res = await emergencyRecord({
emergencyMissionId: id
})
if (res.code === 0) {
console.log(res.data)
}
}

const handleChange = () => {
@@ -140,11 +169,7 @@ export default defineComponent({
}
}

const startOrder = (params) => {
console.log(params)
}

const endOrder = (params) => {
const sendControl = (params) => {
console.log(params)
}

@@ -161,6 +186,25 @@ export default defineComponent({
}
})

watch(() => inspectionStore.getList, (value) => {
if (value?.aiplayUrl) {
setTimeout(() => {
initOriginPlayer(value)
}, 3000)
}
})

/* 初始化播放器 */
function initOriginPlayer(value) {
const origin = {
width: '100%',
height: '100%',
source: value.aiplayUrl,
isLive: true
}
emergencyVideo.value?.init(origin)
}

const handleOperate = () => {
data.operate = data.operate === '悬停' ? '继续飞行' : '悬停'
}
@@ -178,12 +222,34 @@ export default defineComponent({
showIcon: false,
content: `是否返航`,
confirm: () => {
emit('update:visible', false)
airBack()
}
}
)
}

/**
* 飞机返仓 zhilin03
*/
const airBack = async() => {
const res = await controlAir({
value: {
'zhilin': '03',
'taskId': inspectionStore.getList?.id,
'airportId': inspectionStore.getList?.airportId,
'msg': '飞行任务'
}
})

if (res.code === 0) {
console.log('返航成功')
}
}

onBeforeUnmount(() => {
emergencyVideo.value?.disposeVideo()
})

return {
containerRef,
sideRef,
@@ -197,8 +263,9 @@ export default defineComponent({
handleControl,
handleBack,
fanhang,
startOrder,
endOrder
sendControl,
baseMap,
emergencyVideo
}
}
})
@@ -296,7 +363,6 @@ export default defineComponent({
position: absolute;
width: calc(100% - 40px);
height: calc(100% - 20px);
background: blue;
}

.container__back{

Ładowanie…
Anuluj
Zapisz