<script setup lang="ts"> import SceneViewer from "@/components/SceneViewer.vue"; import BottomBar from "@/components/BottomBar.vue"; import {ArrowBackOutline,ArrowForwardOutline,Save,Add, SaveOutline} from "@vicons/ionicons5"; import {nextTick, onMounted, ref} from "vue"; import {darkTheme, useMessage} from "naive-ui"; import {route,route2,route3} from "@/assets/js/testData.ts"; import {useRouteStore} from "@/store/RouteStore.ts"; import {Airline} from "@/types/entityoptions.ts"; import {newAirline, newAirlinePt} from "@/assets/js/TypeInitial.ts"; import * as echarts from "echarts"; import {EChartsType} from "echarts"; import {transLonlat2Car3} from "@/utils/map/geocomputation.ts"; import {drawEcharts_RouteDetection, profileAnalyse} from "@/utils/map/SpatialAnalysis.ts"; import RouteManageViewer from "@/assets/js/RouteManageViewer.js"; let myChart: EChartsType = undefined let routeStore = useRouteStore() let selectedRouteCode = ref(null) let showPtList = ref(true) let selectedRoute = ref<Airline>(newAirline()) let routesInstore = ref<{ value: string|number; label: string}[]>(null) let routeViewer = null let routePtNumber = ref(1) let uiMsg = useMessage() let PtOptions = [ {label: '删除航点', key: 'deletePt'}, {label: '插入航点', key: 'insertPt'}, ] let routeCode = [ { label: "任务航线1", value: 1, },{ label: "任务航线2", value: 2, },{ label: "任务航线3", value: 3, },{ label: "任务航线4", value: 4, },{ label: "任务航线5", value: 5, } ] onMounted(()=>{ myChart = echarts.init(document.getElementById('echarts-profile'),'dark') routeStore.addRoute(route) routeStore.addRoute(route2) routeStore.addRoute(route3) routesInstore.value = routeStore.flyRoute.map((route)=> { return { value: route.unicode, label: route.name } }) }) // 航线选择回调 function checkRoute(key:number|string){ new Promise((resolve,reject)=>{ selectedRoute.value = routeStore.flyRoute.filter(element => element.unicode === String(key))[0] if(selectedRoute.value == null) reject('未找到航线') routeViewer = new RouteManageViewer(window.viewer,selectedRoute.value.isClose) window.viewer.flyTo(routeViewer.addAirLine(selectedRoute.value), {duration: 2}) setTimeout(()=>resolve('success'),2500) }).then((result)=>{ //绘制图表 let Cartain3 = transLonlat2Car3(selectedRoute.value.points) // 计算地形剖面,默认采样间隔为1km let res = profileAnalyse(window.viewer, Cartain3, 1000) // 计算航线距离数组 let orderArr = [] let hArr = [] Cartain3.forEach((_,index) => { orderArr.push(index + 1) hArr.push(selectedRoute.value.points[index].alt) }) console.log(orderArr,hArr) // 弹出图表窗口 drawEcharts_RouteDetection(myChart, res.distanceArray, res.elevationArray, orderArr, hArr) }).catch((err)=>{ uiMsg.error(err) }) } // 在尾部添加航点 function addPtToTail() { let newPt = newAirlinePt() newPt.nPt = selectedRoute.value.points.at(-1).nPt + 1 selectedRoute.value.points.push(newPt) } // 保存航点编辑 // 1 重新编辑航点的ch2属性 // 2 刷新航线属性 // 3 将改动更新到store中 function savePt() { selectedRoute.value.points.forEach((pt,index) => { pt.ch2 = 3 pt.nPt = index+1 //航点序号从1起 }) selectedRoute.value.points.at(-1).ch2 = 1 selectedRoute.value.PtNum = selectedRoute.value.points.length routeStore.addRoute(selectedRoute.value) } /** 删除或在此前插入航点 * * @param key 下拉菜单key * @param index 航点索引 */ function handlePtSelect(key:any, index:number) { if(key=='deletePt'){ selectedRoute.value.points.splice(index,1) selectedRoute.value.points.forEach((pt,i) => { pt.nPt = i+1 }) showPtList.value = false nextTick(()=>{ showPtList.value = true }) } else if(key=='insertPt'){ selectedRoute.value.points.forEach((pt,i) => { if(i>=index) pt.nPt = i + 2 }) let newPt = newAirlinePt() newPt.nPt = index + 1 showPtList.value = false nextTick(()=>{ selectedRoute.value.points.splice(index,0,newPt) showPtList.value = true }) } } //查询上一航点的气象信息 function prevPtWeather() { routePtNumber.value -= 1 //TODO: 查询气象接口,使用返回值promise } //查询下一航点的气象信息 function nextPtWeather() { routePtNumber.value += 1 console.log(selectedRoute.value.points.length) //TODO: 查询气象接口,使用返回值promise } </script> <template> <n-config-provider :theme="darkTheme"> <div style="display: flex;"> <div id="left"> <n-layout style="height: 100%;"> <n-layout-header :bordered="true"> <n-popover trigger="hover"> <template #trigger> <n-button quaternary type="success" size="large"> <template #icon> <n-icon><ArrowBackOutline/></n-icon> </template> </n-button> </template> 返回 </n-popover> <n-popover trigger="hover"> <template #trigger> <n-button quaternary type="success" size="large"> <template #icon> <n-icon><Save/></n-icon> </template> </n-button> </template> 保存编辑 </n-popover> </n-layout-header> <n-layout-content> <n-flex vertical style="margin-left: 1.2rem; margin-top: .5rem;overflow: hidden"> <n-ellipsis><h3>航线列表</h3></n-ellipsis> <n-radio-group v-model:value="selectedRouteCode" name="radiogroup" @update:value="checkRoute"> <n-scrollbar style="height: 20vh"> <n-space vertical> <n-space v-for="r in routesInstore" justify="space-between" style="margin-right: 2rem; border-bottom: #383737 1px solid"> <n-radio :key="r.value" :value="r.value"> {{ r.label }} </n-radio> <n-button size="small" type="error" style="height: 1.5rem; padding-top: 1px">删除</n-button> </n-space> </n-space> </n-scrollbar> </n-radio-group> <n-divider style="margin: .2rem -.5rem"></n-divider> <n-space vertical> <n-space> <n-space> <n-ellipsis>开闭</n-ellipsis> <n-switch v-model:value="selectedRoute.isClose" size="small"> <template #checked> 闭 </template> <template #unchecked> 开 </template> </n-switch> </n-space> <n-space style="margin-left: .5rem"> <n-ellipsis>航点数</n-ellipsis> <n-input-number :show-button="false" disabled size="tiny" style="width: 5rem" v-model:value="selectedRoute.PtNum"></n-input-number> </n-space> </n-space> <n-space> <n-ellipsis style="width: 4rem">航线名称</n-ellipsis> <n-input size="tiny" style="width:10rem" v-model:value="selectedRoute.name"></n-input> </n-space> <n-space> <n-ellipsis style="width: 4rem">航线类型</n-ellipsis> <n-select style="width:10rem" size="tiny" v-model:value="selectedRoute.code" :options="routeCode"/> </n-space> </n-space> <n-divider style="margin: .2rem -.5rem"></n-divider> <n-ellipsis><h3>地形剖面图</h3></n-ellipsis> <n-space justify="start"> <n-ellipsis>采样间隔</n-ellipsis> <n-input-number size="tiny" placeholder="默认1000米" style="width:8vw" :min="100" :step="100"> </n-input-number> <n-button type="success" size="tiny">重新绘图</n-button> </n-space> <div id="echarts-profile"> <!-- Echarts绘图区 --> </div> </n-flex> </n-layout-content> </n-layout> </div> <div id="map2"> <SceneViewer id="scene-viewer-route"></SceneViewer> <BottomBar></BottomBar> </div> <div id="right"> <n-layout style="height: 100%"> <n-layout-header :bordered="true"> <n-space justify="center"> <n-button quaternary type="default" size="large"><h4>航点详情 {{'— '+selectedRoute.name}}</h4></n-button> </n-space> </n-layout-header> <n-layout-content> <n-flex vertical > <n-space justify="space-around" style="margin-top:.5rem;"> <n-ellipsis style="margin-left:.2rem; width: 2rem">序号</n-ellipsis> <n-ellipsis style="width: 5.5rem">经度</n-ellipsis> <n-ellipsis style="width: 5.5rem">纬度</n-ellipsis> <n-ellipsis style="width: 3rem">高度</n-ellipsis> </n-space> <n-scrollbar style="height: 30vh"> <div v-if="selectedRoute.points.length>0 && showPtList" > <n-space justify="space-around" style="margin: .2rem 0" v-for="(pt,index) in selectedRoute.points" > <n-dropdown trigger="hover" size="small" placement="top-start" :show-arrow="true" :options="PtOptions" @select="handlePtSelect($event,index)"> <n-button secondary type="info" size="tiny" style="margin-left:.2rem; width: 1.7rem">{{ pt.nPt }}</n-button> </n-dropdown> <n-input-number size="tiny" v-model:value="pt.lon" :show-button="false" style="width: 5.5rem" placeholder="经度" max="180" min="-180"></n-input-number> <n-input-number size="tiny" v-model:value="pt.lat" :show-button="false" style="width: 5.5rem" placeholder="纬度" max="90" min="-90"></n-input-number> <n-input-number size="tiny" v-model:value="pt.alt" :show-button="false" style="width: 3rem" placeholder="高度" max="12000" min="-500"></n-input-number> </n-space> <n-space justify="center" style="margin: .5rem 0"> <n-button type="info" size="small" @click="addPtToTail"> <template #icon> <Add/> </template> 添加点 </n-button> <n-button type="info" size="small" @click="savePt"> <template #icon> <SaveOutline/> </template> 保存编辑 </n-button> </n-space> </div> <n-space v-else justify="space-around"> <n-empty style="margin-top:3rem " description="无内容"> </n-empty> </n-space> </n-scrollbar> </n-flex> <n-divider style="margin: .2rem -.5rem"></n-divider> <n-flex vertical style="height: 45vh; margin-left: 1rem; margin-top: .5rem;" > <n-row><n-ellipsis><h3>气象信息</h3></n-ellipsis></n-row> <n-space justify="space-around" class="routePtSelector"> <n-button size="small" @click="prevPtWeather" :disabled="routePtNumber<=1"> <template #icon><ArrowBackOutline/></template> </n-button> <n-ellipsis>航点 {{routePtNumber}}</n-ellipsis> <n-button size="small" @click="nextPtWeather" :disabled="selectedRoute.points.length<=routePtNumber"> <template #icon><ArrowForwardOutline/></template> </n-button> </n-space> </n-flex> </n-layout-content> </n-layout> </div> </div> </n-config-provider> </template> <style scoped> #left{ width: 20vw; height: 100vh; } #map2 { width: 60vw; height: 100vh; position: relative; } #right{ width: 20vw; height: 100vh; } #echarts-profile{ margin-left: -1rem; margin-top: -.5rem; height: 40vh; } #scene-viewer-route { width: 100%; height: 100%; overflow: hidden; } .routePtSelector { width: 110%; color: #63e2b7; font-weight: bold; margin-left: -1rem } .routePtSelector:hover{ background: rgb(24, 24, 28); } </style>