feature: 气象信息图表显示

devzpx
zhaipx 2 months ago
parent 30c586d9c0
commit 1974872153

@ -26,6 +26,7 @@
"axios": "^1.6.7", "axios": "^1.6.7",
"cesium": "1.108", "cesium": "1.108",
"cesium-navigation-es6": "^3.0.8", "cesium-navigation-es6": "^3.0.8",
"crypto-js": "^4.2.0",
"echarts": "^5.5.0", "echarts": "^5.5.0",
"fs": "0.0.1-security", "fs": "0.0.1-security",
"kml-geojson": "^2.0.1", "kml-geojson": "^2.0.1",

@ -32,6 +32,9 @@ dependencies:
cesium-navigation-es6: cesium-navigation-es6:
specifier: ^3.0.8 specifier: ^3.0.8
version: 3.0.8 version: 3.0.8
crypto-js:
specifier: ^4.2.0
version: 4.2.0
echarts: echarts:
specifier: ^5.5.0 specifier: ^5.5.0
version: 5.5.0 version: 5.5.0
@ -3003,6 +3006,10 @@ packages:
which: 2.0.2 which: 2.0.2
dev: true dev: true
/crypto-js@4.2.0:
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==, tarball: https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz}
dev: false
/css-functions-list@3.2.1: /css-functions-list@3.2.1:
resolution: {integrity: sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==} resolution: {integrity: sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==}
engines: {node: '>=12 || >=16'} engines: {node: '>=12 || >=16'}

@ -1,4 +1,5 @@
import axios from "axios"; import axios from "axios";
import CryptoJS from "crypto-js"
type WeatherResponse = { type WeatherResponse = {
success: boolean, success: boolean,
@ -7,13 +8,22 @@ type WeatherResponse = {
data: any //响应数据 data: any //响应数据
} }
//查询未来24小时指定位置的地面气象变量信息 /**24
function query_surface_forecast(lat:number, lon: number) *
* @param lon
* @param lat
*/
function query_surface_forecast(lon: number,lat:number)
{ {
let timestamp = Date.now().toString()
return axios({ return axios({
method: "POST", method: "POST",
url: "/onlinetest/htfp/weather/v1surface/querySurfaceForecast", url: "/onlinetest/htfp/weather/v1/surface/querySurfaceForecast",
headers: {"Content-Type": "application/json"}, headers: {
"Content-Type": "application/json",
"timestamp": timestamp,
"signature": CryptoJS.HmacSHA1('/htfp/weather/v1/surface/querySurfaceForecast', timestamp)
},
data: { data: {
latitude: lat, latitude: lat,
longitude: lon, longitude: lon,
@ -23,10 +33,15 @@ function query_surface_forecast(lat:number, lon: number)
//查询未来24小时指定位置和高度的高空气象变量信息 //查询未来24小时指定位置和高度的高空气象变量信息
function query_upper_forecast(lat:number, lon: number, level:number){ function query_upper_forecast(lat:number, lon: number, level:number){
let timestamp = Date.now().toString()
return axios({ return axios({
method: "POST", method: "POST",
url: "/onlinetest/htfp/weather/v1upper/queryUpperForecast", url: "/onlinetest/htfp/weather/v1/upper/queryUpperForecast",
headers: {"Content-Type": "application/json"}, headers: {
"Content-Type": "application/json",
"timestamp": timestamp,
"signature": CryptoJS.HmacSHA1('/htfp/weather/v1/upper/queryUpperForecast', timestamp)
},
data: { data: {
latitude: lat, latitude: lat,
longitude:lon, longitude:lon,

@ -2,7 +2,7 @@
import SceneViewer from "@/components/SceneViewer.vue"; import SceneViewer from "@/components/SceneViewer.vue";
import BottomBar from "@/components/BottomBar.vue"; import BottomBar from "@/components/BottomBar.vue";
import {ArrowBackOutline,ArrowForwardOutline,Save,Add, SaveOutline} from "@vicons/ionicons5"; import {ArrowBackOutline,ArrowForwardOutline,Save,Add, SaveOutline} from "@vicons/ionicons5";
import {nextTick, onMounted, ref} from "vue"; import {nextTick, onBeforeUnmount, onMounted, ref} from "vue";
import {darkTheme, useMessage} from "naive-ui"; import {darkTheme, useMessage} from "naive-ui";
import {route,route2,route3} from "@/assets/js/testData.ts"; import {route,route2,route3} from "@/assets/js/testData.ts";
import {useRouteStore} from "@/store/RouteStore.ts"; import {useRouteStore} from "@/store/RouteStore.ts";
@ -13,8 +13,10 @@ import {EChartsType} from "echarts";
import {transLonlat2Car3} from "@/utils/map/geocomputation.ts"; import {transLonlat2Car3} from "@/utils/map/geocomputation.ts";
import {drawEcharts_RouteDetection, profileAnalyse} from "@/utils/map/SpatialAnalysis.ts"; import {drawEcharts_RouteDetection, profileAnalyse} from "@/utils/map/SpatialAnalysis.ts";
import RouteManageViewer from "@/assets/js/RouteManageViewer.js"; import RouteManageViewer from "@/assets/js/RouteManageViewer.js";
import {query_surface_forecast} from "@/assets/js/weatherRequest.ts";
let myChart: EChartsType = undefined let myChart: EChartsType = undefined
let weatherChart: EChartsType = undefined
let routeStore = useRouteStore() let routeStore = useRouteStore()
let selectedRouteCode = ref(null) let selectedRouteCode = ref(null)
let showPtList = ref(true) let showPtList = ref(true)
@ -23,7 +25,8 @@ let routesInstore = ref<{ value: string|number; label: string}[]>(null)
let routeViewer = null let routeViewer = null
let routePtNumber = ref(1) let routePtNumber = ref(1)
let uiMsg = useMessage() let uiMsg = useMessage()
let nowTime = ref('')
let timer = null
let PtOptions = [ let PtOptions = [
{label: '删除航点', key: 'deletePt'}, {label: '删除航点', key: 'deletePt'},
{label: '插入航点', key: 'insertPt'}, {label: '插入航点', key: 'insertPt'},
@ -46,10 +49,14 @@ let routeCode = [
value: 5, value: 5,
} }
] ]
let levelOptions :any[] = []
onBeforeUnmount(()=>{
clearInterval(timer)
})
onMounted(()=>{ onMounted(()=>{
getTime()
myChart = echarts.init(document.getElementById('echarts-profile'),'dark') myChart = echarts.init(document.getElementById('echarts-profile'),'dark')
weatherChart = echarts.init(document.getElementById('weatherChart'),'dark')
routeStore.addRoute(route) routeStore.addRoute(route)
routeStore.addRoute(route2) routeStore.addRoute(route2)
routeStore.addRoute(route3) routeStore.addRoute(route3)
@ -63,6 +70,23 @@ onMounted(()=>{
}) })
function getTime(){
timer = setInterval(getTimesInterval, 1000);
}
function getTimesInterval() {
let now = new Date();
let year = now.getFullYear(); //
let month = (now.getMonth() + 1).toString().padStart(2, '0'); //
let day = now.getDate().toString().padStart(2, '0'); //
let hours = now.getHours().toString().padStart(2, '0'); //
let minutes = now.getMinutes().toString().padStart(2, '0'); //
let seconds = now.getSeconds().toString().padStart(2, '0'); //
//
nowTime.value = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
// 线 // 线
function checkRoute(key:number|string){ function checkRoute(key:number|string){
new Promise((resolve,reject)=>{ new Promise((resolve,reject)=>{
@ -141,22 +165,184 @@ function handlePtSelect(key:any, index:number) {
selectedRoute.value.points.splice(index,0,newPt) selectedRoute.value.points.splice(index,0,newPt)
showPtList.value = true showPtList.value = true
}) })
} }
} }
// //
function prevPtWeather() { function prevPtWeather() {
routePtNumber.value -= 1 routePtNumber.value -= 1
//TODO: 使promise let lat = selectedRoute.value.points[routePtNumber.value-1].lat
let lon = selectedRoute.value.points[routePtNumber.value-1].lon
if(lat && lon){
queryWeather(lon,lat)
}
} }
// //
function nextPtWeather() { function nextPtWeather() {
routePtNumber.value += 1 routePtNumber.value += 1
console.log(selectedRoute.value.points.length) let lat = selectedRoute.value.points[routePtNumber.value-1].lat
//TODO: 使promise let lon = selectedRoute.value.points[routePtNumber.value-1].lon
if(lat && lon){
queryWeather(lon,lat)
}
// TODO:
}
function queryWeather(lon:number,lat:number,level?: number) {
query_surface_forecast(lon,lat)
.then(res=>{
let weatherData = res.data.data
let timeArr = weatherData.time.map(item=>{
let i = item.indexOf('T')
return item.slice(i+1,i+3) + '时'
})
setChartOptions(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))
})
} }
function setChartOptions(timeSeries:string[], temp: number[], windSpeed:number[], wind360: number[], precip:number[], humidity?:number[]) {
let windDirection = wind360.map(item=>{
let arr = [22.5, 22.5+45, 22.5+45*2, 22.5+45*3, 22.5+45*4, 22.5+45*5, 22.5+45*6, 22.5+45*7]
let str = ['北风','东北风','东风','东南风','南风','西南风','西风','西北风']
if(item<=arr[0] || item>arr[7]){
return str[0]+': '+ Math.round(item)+'°'
}else if(arr[0] <=item && item<=arr[1]){
return str[1]+' : '+ Math.round(item)+'°'
}else if(arr[1] <=item && item<=arr[2]){
return str[2]+' : '+ Math.round(item)+'°'
}else if(arr[2] <=item && item<=arr[3]){
return str[3]+' : '+ Math.round(item)+'°'
}else if(arr[3] <=item && item<=arr[4]){
return str[4]+' : '+ Math.round(item)+'°'
}else if(arr[4] <=item && item<=arr[5]){
return str[5]+' : '+ Math.round(item)+'°'
}else if(arr[5] <=item && item<=arr[6]){
return str[6]+' : '+ Math.round(item)+'°'
}else if(arr[6] <=item && item<=arr[7]){
return str[7]+' : '+ Math.round(item)+'°'
}
})
let colors = ['#5470C6', '#91CC75', '#EE6666'];
weatherChart.setOption({
backgroundColor:'#101014',
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
}
},
color: colors,
grid: [
{x: '7%', y: '7%', height: '40%', left: '12%',right: '15%'},
{x: '7%', y2: '7%', height: '38%', left: '12%',right: '15%', bottom: '10%'}
],
legend: {
data:['风速','降水','温度']
},
xAxis: [
{
show: false,//x
type: 'category',
gridIndex: 0,//grid
axisTick: {
alignWithLabel: true
},
data: windDirection,
},
{
type: 'category',
gridIndex: 1, //grid
axisTick: {
alignWithLabel: true
},
data: timeSeries,
}
],
//yxygrid
yAxis: [
{
type: 'value',
gridIndex: 1,//grid
splitLine: {show: false},
position: 'right',
axisLine: {
lineStyle: {
color: colors[1]
}
},
axisLabel: {
formatter: '{value}ml'
}
},
{
type: 'value',
gridIndex: 1,
nameLocation: 'middle',
name: '温度',
nameTextStyle: {
padding: 25
},
splitLine: {show: false},
position: 'left',
axisLine: {
lineStyle: {
color: colors[2]
}
},
axisLabel: {
formatter: '{value}°C'
}
},
{
type: 'value',
gridIndex: 0,
name: '风速',
nameTextStyle: {
padding: 25
},
position: 'left',
splitLine: {show: false},
axisLine: {
lineStyle: {
color: colors[0]
}
},
axisLabel: {
formatter: '{value}',
textStyle: {
fontSize: 12//y
}
}
}
],
series: [
{
name:'风速',
type: "line",
xAxisIndex: 0,
yAxisIndex: 2,
data: windSpeed,
},
{
name:'降水',
type:'bar',
xAxisIndex: 1,
yAxisIndex: 0,
data: precip
},
{
name:'温度',
type:'line',
xAxisIndex: 1,
yAxisIndex: 1,
data:temp
}
]
})
}
</script> </script>
<template> <template>
@ -311,8 +497,8 @@ function nextPtWeather() {
</n-flex> </n-flex>
<n-divider style="margin: .2rem -.5rem"></n-divider> <n-divider style="margin: .2rem -.5rem"></n-divider>
<n-flex vertical style="height: 45vh; margin-left: 1rem; margin-top: .5rem;" > <n-flex vertical class="border">
<n-row><n-ellipsis><h3>气象信息</h3></n-ellipsis></n-row> <n-row style="margin-left: 1rem; margin-top: .5rem;"><n-ellipsis><h3>气象信息</h3></n-ellipsis></n-row>
<n-space justify="space-around" class="routePtSelector"> <n-space justify="space-around" class="routePtSelector">
<n-button size="small" @click="prevPtWeather" :disabled="routePtNumber<=1"> <n-button size="small" @click="prevPtWeather" :disabled="routePtNumber<=1">
<template #icon><ArrowBackOutline/></template> <template #icon><ArrowBackOutline/></template>
@ -322,6 +508,26 @@ function nextPtWeather() {
<template #icon><ArrowForwardOutline/></template> <template #icon><ArrowForwardOutline/></template>
</n-button> </n-button>
</n-space> </n-space>
<n-space justify="center">
<n-ellipsis>{{nowTime}}</n-ellipsis>
<n-select style="width: 7rem" size="tiny" :options="levelOptions" placeholder="选择高度层"></n-select>
</n-space>
<n-scrollbar x-scrollable id="weatherChart" style="height:41.5vh; width: 100%">
<!-- <n-card class="wCard" size="small" title="卡片">-->
<!-- </n-card>-->
<!-- <n-card class="wCard" size="small" title="卡片">-->
<!-- </n-card>-->
<!-- <n-card class="wCard" size="small" title="卡片">-->
<!-- </n-card>-->
<!-- <n-card class="wCard" size="small" title="卡片">-->
<!-- </n-card>-->
<!-- <n-card class="wCard" size="small" title="卡片">-->
<!-- </n-card>-->
<!-- <n-card class="wCard" size="small" title="卡片">-->
<!-- </n-card>-->
</n-scrollbar>
</n-flex> </n-flex>
</n-layout-content> </n-layout-content>
</n-layout> </n-layout>
@ -338,12 +544,12 @@ function nextPtWeather() {
height: 100vh; height: 100vh;
} }
#map2 { #map2 {
width: 60vw; width: 57vw;
height: 100vh; height: 100vh;
position: relative; position: relative;
} }
#right{ #right{
width: 20vw; width: 23vw;
height: 100vh; height: 100vh;
} }
@ -362,9 +568,16 @@ function nextPtWeather() {
color: #63e2b7; color: #63e2b7;
font-weight: bold; font-weight: bold;
margin-left: -1rem margin-left: -1rem
} }
.routePtSelector:hover{ .routePtSelector:hover{
background: rgb(24, 24, 28); background: rgb(24, 24, 28);
} }
.wCard {
width: 4vw;
height: 39vh;
display: inline-block
}
.border{
border: #22ee22 solid 1px;
}
</style> </style>

@ -22,10 +22,9 @@ import RouteManageViewer from "@/assets/js/RouteManageViewer.js";
import RouteOptions from "@/components/RouteOptions.vue"; import RouteOptions from "@/components/RouteOptions.vue";
import {useRouteStore} from "@/store/RouteStore"; import {useRouteStore} from "@/store/RouteStore";
import MarkerDialog from "@/components/MarkerDialog.vue"; import MarkerDialog from "@/components/MarkerDialog.vue";
import { useRouter, useRoute } from 'vue-router' import { useRouter } from 'vue-router'
import {getUnicode} from "@/types/entityoptions.ts"; import {getUnicode} from "@/types/entityoptions.ts";
const router = useRouter() const router = useRouter()
const route = useRoute()
const emit = defineEmits(['resizeMap']) const emit = defineEmits(['resizeMap'])
const message = useMessage(); const message = useMessage();

@ -30,7 +30,7 @@ export default defineConfig({
server: { server: {
proxy: { proxy: {
'/onlinetest': { '/onlinetest': {
target: 'http://123.57.54.1:8048/', target: 'http://123.57.54.1:10323/',
changeOrigin: true, changeOrigin: true,
rewrite: path => path.replace(/^\/onlinetest/,'') rewrite: path => path.replace(/^\/onlinetest/,'')
} }

Loading…
Cancel
Save