diff --git a/README.md b/README.md index 5492e53..3ca501b 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,11 @@ commit提交时,需使用`git commit -m 'fix: xxx'` ## 地图服务 -地图服务采用天地图数据源(https://www.tianditu.gov.cn/)。 +地图服务采用天地图数据源( https://www.tianditu.gov.cn/ )。 +时间分辨率:官方未说明 +空间分辨率:官方未说明,约为30米 ## 打包部署 -- 执行build后,使用nginx部署项目时,需将项目中的`public`目录复制到`dist`中。public包含了Cesium所需的静态资源,否则不能加载地球 +- 执行build后,需将此项目中的`public`文件夹复制到`dist`目录下,再进行nginx部署。public包含了Cesium所需的静态资源,否则不能加载地球 +- 2025.4.17 更新: `public`文件夹如果不复制到`dist`目录下,服务也可以运行,但加载航线时出现异常 diff --git a/src/assets/js/RouteManageViewer.js b/src/assets/js/RouteManageViewer.js index 76661d7..9906c12 100644 --- a/src/assets/js/RouteManageViewer.js +++ b/src/assets/js/RouteManageViewer.js @@ -56,9 +56,8 @@ export default class RouteManageViewer { outlineColor: Cesium.Color.RED, outlineWidth: 2, disableDepthTestDistance:99000000, - // heightReference:Cesium.HeightReference.CLAMP_TO_GROUND, }, - label:{ + label: (index===degreesArr.length-1 && line.isClose)? undefined : { text: "航点 " + (index+1), font: "2.5rem sans-serif", fillColor: Cesium.Color.WHITE, @@ -74,6 +73,7 @@ export default class RouteManageViewer { }); this.viewer.entities.add(vertexEntity) }) + return airlineEntity } diff --git a/src/components/RouteOptions.vue b/src/components/RouteOptions.vue index 33ba264..847fc58 100644 --- a/src/components/RouteOptions.vue +++ b/src/components/RouteOptions.vue @@ -9,9 +9,9 @@ import {defineEmits, ref} from "vue"; let emit = defineEmits(['routeDraw','cancelDraw']) let routeParams = ref({ name: '', - code: 0, + code: 1, isClose: false, - height: 0, + height: 100, routePts: [] }) let routeCode = [ diff --git a/src/components/page/RouteManagePage.vue b/src/components/page/RouteManagePage.vue index ee73ac3..9cf7e69 100644 --- a/src/components/page/RouteManagePage.vue +++ b/src/components/page/RouteManagePage.vue @@ -17,6 +17,8 @@ import {query_surface_forecast, query_upper_forecast, requireWeatherLevel} from import {setChartOptions} from "@/assets/js/weatherCharts.ts"; import type { NotificationType } from 'naive-ui' import { useNotification } from 'naive-ui' +import {useStaticStore} from "@/store/staticOptions"; +import {useRouter} from "vue-router"; let myChart: EChartsType = undefined let weatherChart: EChartsType = undefined @@ -25,7 +27,7 @@ let selectedRouteCode = ref(null) let selectedLevel = ref(null) let showPtList = ref(true) let selectedRoute = ref<Airline>(newAirline()) -let routesInstore = ref<{ value: string|number; label: string}[]>(null) +let routesListRef = ref<{ value: string|number; label: string}[]>(null) let routeViewer = null let routePtNumber = ref(1) let uiMsg = useMessage() @@ -54,6 +56,9 @@ let routeCode = [ } ] let levelOptions = ref<any[]>() +let sStore = useStaticStore(); +const router = useRouter() + const notification = useNotification() const notify = (type: NotificationType, title: string, detail: string) =>{ notification[type]({ @@ -78,7 +83,7 @@ onMounted(()=>{ routeStore.addRoute(route2) routeStore.addRoute(route3) - routesInstore.value = routeStore.flyRoute.map((route)=> { + routesListRef.value = routeStore.flyRoute.map((route)=> { return { value: route.unicode, label: route.name @@ -139,7 +144,7 @@ function checkRoute(key:number|string){ hArr.push(selectedRoute.value.points[index].alt) }) console.log(orderArr,hArr) - // 弹出图表窗口 + // 弹出地形图表 drawEcharts_RouteDetection(myChart, res.distanceArray, res.elevationArray, orderArr, hArr) }).catch((err)=>{ @@ -241,11 +246,15 @@ function queryWeather(lon:number,lat:number,level?: number) { let i = item.indexOf('T') return item.slice(i+1,i+3) + '时' }) - if(!Reflect.has(weatherData,'precip')){ - weatherData.precip = Array.from({length:timeArr.length},(v,k)=>0) + if(!Reflect.has(weatherData,'precip')){ //高空数据无precip(降水)属性,需添加数组并补0 + weatherData.precip = Array.from({length:timeArr.length},()=>0) } setChartOptions(weatherChart, timeArr.slice(0,8),weatherData.temp.slice(0,8),weatherData.windSpeed.slice(0,8), weatherData.wind360.slice(0,8), weatherData.precip.slice(0,8),weatherData.humidity.slice(0,8)) + }).catch(e=>{ + console.log() + uiMsg.error('气象信息查询失败:' + e.message,{duration:3000, keepAliveOnHover: true}) + }) } @@ -257,6 +266,31 @@ function levelChanged(key: string | number) { queryWeather(lon,lat, Number(key)) } } + +/** + * 将航线信息发送给QT端(每次发送一条航线) + * @param routeUnicode 航线唯一码 + */ +function sendRouteToQT(routeUnicode: string|number){ + let selectedRoute = routeStore.flyRoute.filter(element => element.unicode === String(routeUnicode))[0] + if(selectedRoute){ + if(sStore.webskt.ws?.readyState == WebSocket.OPEN){ + sStore.webskt.ws.send(JSON.stringify(selectedRoute)) + }else { + uiMsg.info('请先开启WebSocket') + } + }else + uiMsg.warning('未找到相应的航线') +} + +function delRoute(routeUnicode: string|number){ + +} + +function backToHomePage(){ + router.push({name: 'Home'}) +} + </script> <template> @@ -267,7 +301,7 @@ function levelChanged(key: string | number) { <n-layout-header :bordered="true"> <n-popover trigger="hover"> <template #trigger> - <n-button quaternary type="success" size="large"> + <n-button quaternary type="success" size="large" @click="backToHomePage"> <template #icon> <n-icon><ArrowBackOutline/></n-icon> </template> @@ -292,15 +326,14 @@ function levelChanged(key: string | number) { <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" + <n-space v-for="r in routesListRef" 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-group> -<!-- TODO: 下发、删除功能实现--> - <n-button secondary size="small" type="info" style="height: 1.3rem; margin: 0 3px 4px 0">下发</n-button> - <n-button secondary size="small" type="error" style="height: 1.3rem; margin-bottom: 4px">删除</n-button> + <n-button secondary size="small" type="info" style="height: 1.3rem" @click="sendRouteToQT(r.value)">下发</n-button> + <n-button secondary size="small" type="error" style="height: 1.3rem; margin-bottom: 4px" @click="delRoute(r.value)">删除</n-button> </n-button-group> </n-space> @@ -309,17 +342,13 @@ function levelChanged(key: string | number) { </n-radio-group> <n-divider style="margin: .2rem -.5rem"></n-divider> - <n-space vertical> + <n-space vertical style="margin: .2rem 1rem"> <n-space> <n-space> <n-ellipsis>开闭</n-ellipsis> <n-switch v-model:value="selectedRoute.isClose" size="small"> - <template #checked> - 闭 - </template> - <template #unchecked> - 开 - </template> + <template #checked>闭</template> + <template #unchecked>开</template> </n-switch> </n-space> <n-space style="margin-left: .5rem"> @@ -340,10 +369,10 @@ function levelChanged(key: string | number) { <n-divider style="margin: .2rem -.5rem"></n-divider> <n-ellipsis><h3>地形剖面图</h3></n-ellipsis> - <n-space justify="start"> + <n-space justify="space-evenly"> <n-ellipsis>采样间隔</n-ellipsis> <n-input-number size="tiny" placeholder="默认1000米" - style="width:8vw" :min="100" :step="100"> + style="width:8vw;" :min="100" :step="100"> </n-input-number> <n-button type="success" size="tiny">重新绘图</n-button> </n-space> @@ -447,11 +476,11 @@ function levelChanged(key: string | number) { <style scoped> #left{ - width: 20vw; + width: 22vw; height: 100vh; } #map2 { - width: 57vw; + width: 55vw; height: 100vh; position: relative; } diff --git a/src/components/toolbar.vue b/src/components/toolbar.vue index c88a4fe..3013495 100644 --- a/src/components/toolbar.vue +++ b/src/components/toolbar.vue @@ -177,9 +177,9 @@ function measureArea() { * @returns {Promise<void>} */ async function connectWebSocket() { - store.webskt.ws = new WebSocket('ws://'+store.webskt.ws_config.address+':'+store.webskt.ws_config.port); + store.webskt.ws = new WebSocket('ws://'+store.webskt.ws_config.address+':'+store.webskt.ws_config.port) store.webskt.ws.onopen = function(event){ - console.log("Connection open ...") + message.success('WebSocket已连接\n url:'+'ws://'+store.webskt.ws_config.address+':'+store.webskt.ws_config.port) store.webskt.ws.send("hello QT!") } @@ -248,15 +248,6 @@ async function connectWebSocket() { }; } -/** - * 将航线信息发送给QT端(每次发送一条航线) - * @param route 航线,Airline类型 - */ -function sendRouteToQT(route){ - if(store.webskt.ws?.readyState == WebSocket.OPEN){ - store.webskt.ws.send(JSON.stringify(route)) - } -} //关闭动态碰撞检测功能 function shutDownDetec() { if(lStore.openDetect){ @@ -291,11 +282,10 @@ function startDrawRoute(routeParams) { drawLine.routeParams.isClose =routeParams.isClose drawLine.routeParams.height = routeParams.height drawLine.start().then(result => { - console.log(result) // result是经纬度坐标数组,需转换为 AirlinePoint数组 let AirlinePoints = [] result.forEach((pt,index) => { - let AirlinePoint = {lon:pt.lon, lat:pt.lat, alt:pt.alt, ch1:routeParams.isClose? 2:0, ch2:0x03, speed:0, nPt:index} + let AirlinePoint = {lon:pt.lon, lat:pt.lat, alt:pt.alt, ch1:routeParams.isClose? 2:0, ch2:0x03, speed:0, nPt:index+1} AirlinePoints.push(AirlinePoint) }) AirlinePoints.at(-1).ch2 = 0x01; @@ -304,7 +294,8 @@ function startDrawRoute(routeParams) { code: routeParams.code, PtNum: result.length, isClose: routeParams.isClose, unicode: getUnicode(), name: routeParams.name, points: AirlinePoints, totalDistance: 0 } - useRouteStore().flyRoute.push(aRoute) + useRouteStore().addRoute(aRoute) + console.log(useRouteStore().flyRoute) // fixme: 航线加入图层管理 }).catch(reject => { @@ -367,13 +358,13 @@ function startDrawRoute(routeParams) { </n-dropdown> <n-tooltip placement="bottom" trigger="hover"> <template #trigger> - <n-button tertiary type="warning" @click="showModal = true"> + <n-button tertiary type="warning" @click="connectWebSocket"> <template #icon> <n-icon><Settings/></n-icon> </template> </n-button> </template> - <span> WebSocket配置 </span> + <span> 开启WebSocket </span> </n-tooltip> <n-popselect v-model:value="SceneValue" :options="store.menuOptions.sceneOptions" @update:value="handleSceneSelect" size="medium"> diff --git a/src/store/RouteStore.ts b/src/store/RouteStore.ts index b2b9a06..d8cd3f2 100644 --- a/src/store/RouteStore.ts +++ b/src/store/RouteStore.ts @@ -10,11 +10,11 @@ export const useRouteStore = defineStore('RouteStore', { }, actions: { /** - * 向store中添加航线,code为唯一码,如冲突,则会替换原有值 + * 向store中添加航线,unicode为唯一码,如冲突,原有航线会被覆盖(应该不会重复) * @param route */ addRoute(route:Airline){ - let index = this.flyRoute.findIndex((item: Airline)=>item.code===route.code) + let index = this.flyRoute.findIndex((item: Airline)=>item.unicode===route.unicode) if(index > -1){ this.flyRoute.splice(index,1); } diff --git a/src/store/staticOptions.js b/src/store/staticOptions.js index b345796..b1d7804 100644 --- a/src/store/staticOptions.js +++ b/src/store/staticOptions.js @@ -1,7 +1,7 @@ import {defineStore} from "pinia"; -import cesiumAirPlane from "@/assets/models/Cesium_Air.glb"; -import fp985Plane from "@/assets/models/FP-985.gltf"; -import fp98Plane from "@/assets/models/fp-98.gltf"; +import cesiumAirPlane from "@/assets/models/Cesium_Air.glb?url"; +import fp985Plane from "@/assets/models/FP-985.gltf?url"; +import fp98Plane from "@/assets/models/fp-98.gltf?url"; export const useStaticStore = defineStore('staticOptions',{ state: ()=>{ diff --git a/src/utils/map/SpatialAnalysis.ts b/src/utils/map/SpatialAnalysis.ts index 647fd48..c3af31c 100644 --- a/src/utils/map/SpatialAnalysis.ts +++ b/src/utils/map/SpatialAnalysis.ts @@ -699,10 +699,11 @@ export const drawEcharts_RouteDetection = (myChart: EChartsType,xData:number[], myChart.setOption({ backgroundColor:'#101014', grid: { - top: "17%", + containLabel: true, + top: "15%", right: "6%", - left:" 15%", - bottom: "20%", + left:" 5%", + bottom: "5%", }, legend: { show: true, @@ -726,11 +727,12 @@ export const drawEcharts_RouteDetection = (myChart: EChartsType,xData:number[], }, tooltip: { show: true, + appendToBody: true, trigger: 'axis', axisPointer: { type: 'cross' }, - formatter:'地表高度: {c0}<br> 航点高度:{c1}' + formatter:'地表高度: {c0}m<br> 航点高度:{c1}m' }, xAxis: [ { @@ -739,7 +741,7 @@ export const drawEcharts_RouteDetection = (myChart: EChartsType,xData:number[], data: xData, nameTextStyle: { fontWeight:'bolder', - fontSize: 10 + fontSize: 12 }, axisLine:{ onZero: false, @@ -749,7 +751,7 @@ export const drawEcharts_RouteDetection = (myChart: EChartsType,xData:number[], }, axisLabel: { formatter: '{value}', - margin: 7, + margin: 4, }, }, { @@ -765,20 +767,21 @@ export const drawEcharts_RouteDetection = (myChart: EChartsType,xData:number[], }, axisLabel: { formatter: '航点{value}', - margin: 7, + margin: 4, }, } ], yAxis: { type: 'value', - name: '高度/ m', + name: '高度/m', nameTextStyle: { - fontSize: 14 + fontSize: 12 }, nameLocation: 'end', position: 'left', axisLabel: { - formatter: '{value}' + formatter: '{value}', + margin: 4, }, axisLine: { show: true, diff --git a/vite.config.ts b/vite.config.ts index c88193d..b0e8e9b 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -21,6 +21,16 @@ export default defineConfig({ base: './', build: { target: ['es2015', 'chrome63'], + chunkSizeWarningLimit: 5000, + rollupOptions: { + output:{ + manualChunks(id) { + if (id.includes('node_modules')) { + return id.toString().split('node_modules/')[1].split('/')[0].toString(); + } + } + } + } }, resolve: { alias: {