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

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

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


const test = async() => {
const executeNow = async() => {
var airportName = '' var airportName = ''
data.airpotOptions?.map((item) => { data.airpotOptions?.map((item) => {
if (item.value === data.airportId) { if (item.value === data.airportId) {


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


return value + 'm' return value + 'm'
} }


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

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

import { import {
airportList, getWarning airportList, getWarning
} from '@/api/dashboard/index.js' } 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 { gcj02towgs84 } from '@/utils/coordinate-util.js'
import AirInfo from './AirInfo.vue' import AirInfo from './AirInfo.vue'
import ProblemInfo from './ProblemInfo.vue' import ProblemInfo from './ProblemInfo.vue'
monitorVideo.value?.disposeVideo() 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) => { watch(() => inspectionStore.getList, (val) => {
hideProblemInfo, hideProblemInfo,
getMaxZOverlay, getMaxZOverlay,
Warning, Warning,
handleExecute
handleExecute,
refreshRecord
} }
} }
} }

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

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


console.log(inspectionStore.getList)

const getMapOptions = computed(() => { const getMapOptions = computed(() => {
return { return {
id: props.id 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')
// }
// })
// }

/** /**
* 初始化地图 * 初始化地图
*/ */
params: { LAYERS: 'jiangning:town' } 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({ data.map = new Map({
// 地图容器 // 地图容器
target: props.id, 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], layers: [tdtImgMap],
controls: control.defaults({ controls: control.defaults({
attribution: false, attribution: false,
} }


/* 获取轨迹数据 */ /* 获取轨迹数据 */
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 const trackList = res.data
data.trackList = trackList data.trackList = trackList
// const trackList = data.trackList
return Promise.resolve({ return Promise.resolve({
trackList 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 let vectorLayer = null
// 路线
const route = new LineString(coordinate) const route = new LineString(coordinate)
const routeFeature = new Feature({ const routeFeature = new Feature({
type: routeType, type: routeType,
geometry: route geometry: route
}) })
const startMarker = new Feature({
const endMarker = new Feature({
type: 'icon', 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(() => { onMounted(() => {
}) })


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


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

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

<template> <template>
<n-drawer v-bind="getDrawerOptions" @update:show="handleDrawerColse"> <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 ref="containerRef" class="warning__container">


<div class="warning__side"> <div class="warning__side">
</div> </div>


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


<script> <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 Underlay from './Underlay.vue'
import ControlPanel from './ControlPanel.vue' import ControlPanel from './ControlPanel.vue'
import SpeedChart from './SpeedChart.vue' import SpeedChart from './SpeedChart.vue'
import { useInspectionStore } from '@/store/modules/inspection.js' 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({ export default defineComponent({
name: 'WarningDrawer', name: 'WarningDrawer',
components: { Underlay, ControlPanel, SpeedChart },
components: { Underlay, ControlPanel, SpeedChart, VideoPlayer },
props: { props: {
/* 可见 */ /* 可见 */
visible: { visible: {
data: { data: {
type: Object, type: Object,
default: () => {} default: () => {}
},
id: {
type: Number,
default: 0
} }
}, },
emits: { emits: {
'update:visible': null
'update:visible': null,
'refresh:id': null
}, },
setup(props, { emit }) { setup(props, { emit }) {
const inspectionStore = useInspectionStore() const inspectionStore = useInspectionStore()
const containerRef = ref() const containerRef = ref()
const sideRef = ref() const sideRef = ref()
const mapRef = ref() const mapRef = ref()
const baseMap = ref()
const videoRef = ref() const videoRef = ref()
const emergencyVideo = ref()
const data = reactive({ const data = reactive({
hasChanged: false, hasChanged: false,
showControl: false, showControl: false,
/* 关闭抽屉 */ /* 关闭抽屉 */
function handleDrawerColse() { function handleDrawerColse() {
emit('update:visible', false) 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 = () => { const handleChange = () => {
} }
} }


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

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


} }
}) })


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 = () => { const handleOperate = () => {
data.operate = data.operate === '悬停' ? '继续飞行' : '悬停' data.operate = data.operate === '悬停' ? '继续飞行' : '悬停'
} }
showIcon: false, showIcon: false,
content: `是否返航`, content: `是否返航`,
confirm: () => { 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 { return {
containerRef, containerRef,
sideRef, sideRef,
handleControl, handleControl,
handleBack, handleBack,
fanhang, fanhang,
startOrder,
endOrder
sendControl,
baseMap,
emergencyVideo
} }
} }
}) })
position: absolute; position: absolute;
width: calc(100% - 40px); width: calc(100% - 40px);
height: calc(100% - 20px); height: calc(100% - 20px);
background: blue;
} }


.container__back{ .container__back{

Ładowanie…
Anuluj
Zapisz