You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

784 lines
26 KiB

<template>
<div class="tabs">
<div :class="{'active': currentTab === 'MWR'}" class="tab-item" @click="onTabClick('MWR')">
质控对比
<img v-if="currentTab === 'MWR'" src="/images/line.png"/>
</div>
<div :class="{'active': currentTab === 'boundary-layer-height'}" class="tab-item" @click="onTabClick('boundary-layer-height')">
水汽
<img v-if="currentTab === 'boundary-layer-height'" src="/images/line.png"/>
</div>
<div :class="{'active': currentTab === 'optical-property'}" class="tab-item" @click="onTabClick('optical-property')">
光学特性
<img v-if="currentTab === 'optical-property'" src="/images/line.png"/>
</div>
<div :class="{'active': currentTab === 'aerosol-product'}" class="tab-item" @click="onTabClick('aerosol-product')">
气溶胶产品
<img v-if="currentTab === 'aerosol-product'" src="/images/line.png"/>
</div>
<div :class="{'active': currentTab === 'BingoCloud'}" class="tab-item" @click="onTabClick('BingoCloud')">
云产品
<img v-if="currentTab === 'BingoCloud'" src="/images/line.png"/>
</div>
</div>
<div class="main">
<div class="menu panel">
<div class="menu-item">
<h2 class="tip">区域选择</h2>
<el-row :gutter="12">
<el-col :span="8"><span @click="onRegionClick('jiangning')"
:class="{'active': currentRegion === 'jiangning'}">江宁</span></el-col>
<el-col :span="8"><span @click="onRegionClick('liuhe')"
:class="{'active': currentRegion === 'liuhe'}">六合</span></el-col>
<el-col :span="8"><span @click="onRegionClick('pukou')"
:class="{'active': currentRegion === 'pukou'}">浦口</span></el-col>
</el-row>
</div>
<!-- layertype -->
<div class="menu-item">
<h2 class="tip">要素选择</h2>
<!-- <el-row :gutter="12">-->
<!-- <el-col :span="24"><span @click="onElementClick('PBLH', '边界层高度')"-->
<!-- :class="{'active': currentElement === 'PBLH'}">边界层高度</span></el-col>-->
<!-- <el-col :span="24"><span @click="onElementClick('opticalthickness', '光学厚度')"-->
<!-- :class="{'active': currentElement === 'opticalthickness'}">光学厚度</span></el-col>-->
<!-- <el-col :span="24"><span @click="onElementClick('Lidar_ratio', '激光雷达比')"-->
<!-- :class="{'active': currentElement === 'Lidar_ratio'}">激光雷达比</span></el-col>-->
<!-- <el-col :span="24"><span @click="onElementClick('PM', '气溶胶PM')" :class="{'active': currentElement === 'PM'}">气溶胶PM</span>-->
<!-- </el-col>-->
<!-- <el-col :span="24"><span @click="onElementClick('ext_plot', '消光系数')"-->
<!-- :class="{'active': currentElement === 'ext_plot'}">消光系数</span></el-col>-->
<!-- <el-col :span="24"><span @click="onElementClick('layertype', '云气溶胶分类')"-->
<!-- :class="{'active': currentElement === 'layertype'}">云气溶胶分类</span></el-col>-->
<!-- <el-col :span="24"><span @click="onElementClick('wv_plot', '水汽')"-->
<!-- :class="{'active': currentElement === 'wv_plot'}">水汽</span></el-col>-->
<!-- <el-col :span="24"><span @click="onElementClick('cloudheight', '云高')"-->
<!-- :class="{'active': currentElement === 'cloudheight'}">云高</span></el-col>-->
<!-- </el-row>-->
</div>
</div>
<div class="container panel">
<div class="toolbar day-toolbar">
<div class="times">
<div class="time-item" v-for="(time, index) in times" :key="index"
:class="{'active': currentTime === time.date}">
<span class="time" @click="onTimeClick(time, index)">{{ time.day }}</span>
</div>
</div>
<el-date-picker v-model="date" type="date" placeholder="请选择" :clearable="false" :editable="false"
class="date-picker" @change="onChange">
</el-date-picker>
<div class="control-btn">
<span @click="onPrevDayClick"><img src="/images/prev.png"/></span>
<span @click="onNextDayClick"><img src="/images/next.png"/></span>
</div>
<!-- <div class="refresh-btn" @click="onRefreshClick">-->
<!-- <img src="/images/refresh.png"/>-->
<!-- </div>-->
<!-- <div class="btns-group">-->
<!-- <span @click="onPlayClick">{{ isPlay ? '暂停动画' : '播放动画' }}</span>-->
<!-- <a @click="onDownloadClick">下载动画</a>-->
<!-- <a id="radarDownload" :href="downloadSrc" download style="display: none;">下载隐藏层</a>-->
<!-- </div>-->
</div>
<div class="picture-view">
<!-- <span class="arrow arrow-prev" @click="onPrevImgClick"><img src="/images/prev-btn.png" /></span>-->
<!-- <span class="arrow arrow-next" @click="onNextImgClick"><img src="/images/next-btn.png" /></span>-->
<!-- &lt;!&ndash; <span class="save-btn" @click="onSaveClick" v-if="currentElement === 'PBLH'"><img src="/images/save.png" /></span> &ndash;&gt;-->
<!-- <a :href="downloadImgUrl" download class="save-btn" v-if="currentElement !== 'PBLH'"><img src="/images/save.png" /></a>-->
<!-- <div class="download-pictures hide" id="pictures">-->
<!-- <a v-for="(url, index) in urls" :key="index" download></a>-->
<!-- </div>-->
<div class="picture-container raman-picture-container" v-show="currentTab === 'boundary-layer-height'">
<div class="picture">
<h2>水汽</h2>
</div>
</div>
<div class="picture-container raman-picture-container" v-show="currentTab === 'optical-property'">
<div class="picture">
<h2 class="title">激光雷达比</h2>
<div id="LidarRatio" style="width: 650px;height: 450px"></div>
</div>
<div class="picture">
<h2 class="title">光学厚度</h2>
</div>
<div class="picture">
<h2 class="title">消光系数</h2>
</div>
</div>
<div class="picture-container raman-picture-container" v-show="currentTab === 'aerosol-product'">
<div class="picture">
<h2 class="title">边界层高度</h2>
<div id="BoundaryLayerHeight" style="width: 650px;height: 450px"></div>
</div>
<div class="picture">
<h2 class="title">气溶胶PM</h2>
</div>
<div class="picture">
<h2 class="title">边界层特征值</h2>
</div>
</div>
<div class="picture-container raman-picture-container" v-show="currentTab === 'BingoCloud'">
<div class="picture">
<h2 class="title">云气溶胶分类</h2>
</div>
<div class="picture">
<h2 class="title">云层高度</h2>
<div id="cloudsHeight" style="width: 650px;height: 450px"></div>
</div>
<div class="picture">
<h2 class="title">云顶高度</h2>
<div id="cloudTopHeight" style="width: 650px;height: 450px"></div>
</div>
</div>
<div class="picture-container raman-picture-container" v-show="currentTab === 'MWR'">
<div class="picture">
<h2 class="title">云的识别</h2>
</div>
<div class="picture">
<h2 class="title">消光系数</h2>
</div>
<div class="picture">
<h2 class="title">水汽</h2>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import {onMounted, reactive, toRefs} from 'vue';
import moment, {min} from "moment";
import {RamanLidarConfig} from '../uilts/Config';
import {post} from '../uilts/axios';
import {ElMessage} from "element-plus";
import * as Highcharts from 'highcharts';
import {ConstantRamanLidar} from "../model/constant";
import {get} from '../uilts/axios';
import {HighChartCreate} from "../model/high-chart-create";
import {BoxDrawer, ColorChart, createEmptyCanvas} from "../uilts/box-drawer";
export default {
name: 'RamanLidar',
setup() {
let timer = null;
let creates: {
boundaryLayerHeight: HighChartCreate
cloudsHeight: HighChartCreate
cloudTopHeight: HighChartCreate
LidarRatio: HighChartCreate
} = {
boundaryLayerHeight: null,
cloudsHeight: null,
cloudTopHeight: null,
LidarRatio: null
}
let options = reactive({
currentTab: 'MWR',
currentRegion: 'jiangning',
currentElement: 'PBLH',
currentType: '边界层高度',
date: moment('2021-12-14').format('YYYY-MM-DD'),
times: [],
currentTime: null,
downloadImgUrl: '/images/default-picture.png',
imgUrl: '/images/default-picture.png',
signalPBLHImgUrl: '/images/default-picture.png',
previewUrl: [],
signalPBLHPreviewUrl: [],
isPlay: false,
title: null,
index: 0,
downloadSrc: null,
urls: [],
boundaryLayerHeightList: [],
LidarRatioList: [],
cloudsHeightList: [],
cloudTopHeightList: []
})
onMounted(() => {
initTimeLine();
setTitle(moment(options.date, 'YYYY-MM-DD'));
setTimeout(() => {
activeImage();
}, 50)
})
//边界层高度
const boundaryLayerHeightInit = () => {
creates.boundaryLayerHeight = new HighChartCreate('BoundaryLayerHeight');
creates.boundaryLayerHeight.setChart();
creates.boundaryLayerHeight.setXAxis('时间(分钟)', false);
creates.boundaryLayerHeight.setYAxis('边界层高度(米)', 3000, 0, 500, 7);
creates.boundaryLayerHeight.setLegend();
creates.boundaryLayerHeight.setTooltip('{point.category}: {point.y}(m)');
creates.boundaryLayerHeight.setSeries('边界层高度')
creates.boundaryLayerHeight.init();
}
//云层高度
const cloudsHeightInit = () => {
creates.cloudsHeight = new HighChartCreate('cloudsHeight');
creates.cloudsHeight.setChart(false,'scatter');
creates.cloudsHeight.setXAxis('时间(分钟)', false);
creates.cloudsHeight.setYAxis('高度(米)', 14000, 0, 2000, 8);
creates.cloudsHeight.setLegend();
creates.cloudsHeight.setTooltip('{point.category}: {point.y}(m)');
creates.cloudsHeight.setSeries('云层高度')
creates.cloudsHeight.init();
}
//云顶高度
const cloudTopHeightInit = () => {
creates.cloudTopHeight = new HighChartCreate('cloudTopHeight');
creates.cloudTopHeight.setChart(false,'scatter');
creates.cloudTopHeight.setXAxis('时间(分钟)', false);
creates.cloudTopHeight.setYAxis('高度(米)', 14000, 0, 2000, 8);
creates.cloudTopHeight.setLegend();
creates.cloudTopHeight.setTooltip('{point.category}: {point.y}(m)');
creates.cloudTopHeight.setSeries('云顶高度')
creates.cloudTopHeight.init();
}
//激光雷达比
const LidarRatioInit = () => {
creates.LidarRatio = new HighChartCreate('LidarRatio');
creates.LidarRatio.setChart();
creates.LidarRatio.setXAxis('时间(分钟)', false);
creates.LidarRatio.setYAxis('边界层高度(米)', 3000, 0, 500, 7);
creates.LidarRatio.setLegend();
creates.LidarRatio.setTooltip('{point.category}: {point.y}(m)');
creates.LidarRatio.setSeries('激光雷达比')
creates.LidarRatio.init();
}
const onTabClick = (name) => {
options.currentTab = name;
setTimeout(() => {
initEcharts(name)
reloadChangeData()
}, 500)
}
const reloadChangeData = () => {
if (options.currentTab === 'boundary-layer-height') {
} else if (options.currentTab === 'optical-property') {
LidarRatioApi()
} else if (options.currentTab === 'aerosol-product') {
boundaryLayerHeightDate()
// boundaryCharacteristicApi()
//aerosolApi()
} else if (options.currentTab === 'BingoCloud') {
//layerTypeApi()
cloudsHeightApi()
cloudTopHeightApi()
} else if (options.currentTab === 'MWR') {
// waterVapourApi()
}
}
const initEcharts = (name) => {
if (name === 'boundary-layer-height') {
} else if (name === 'optical-property') {
LidarRatioInit()
} else if (name === 'aerosol-product') {
boundaryLayerHeightInit()
} else if (name === 'BingoCloud') {
cloudsHeightInit()
cloudTopHeightInit()
}
}
//区域切换
const onRegionClick = (region) => {
options.currentRegion = region;
options.date = options.currentTime;
cancelActive();
setTitle(moment(options.date));
activeImage();
setTimeout(() => {
}, 500)
}
//要素选择
// const onElementClick = (element, type) => {
// options.currentElement = element;
// options.currentType = type;
// options.date = options.currentTime;
// setTimeout(() => {
// }, 500)
// cancelActive();
// setTitle(moment(options.date));
// activeImage();
// }
const setTitle = (date) => {
options.title = date.format('YYYY.MM.DD') + ' ' + options.currentType;
}
const activeImage = () => {
options.imgUrl = RamanLidarConfig.getUrl(options.currentRegion, options.currentElement, moment(options.currentTime, 'YYYY-MM-DD'));
options.previewUrl = [options.imgUrl];
options.signalPBLHImgUrl = RamanLidarConfig.getUrl(options.currentRegion, 'signal_' + options.currentElement, moment(options.currentTime, 'YYYY-MM-DD'));
options.signalPBLHPreviewUrl = [options.signalPBLHImgUrl];
}
const onImageLoad = (event) => {
if (event.currentTarget.getAttribute('src') !== '/images/default-picture.png')
converToBase64(options.imgUrl);
else
return
}
const onDownloadClick = () => {
post("/image/createGif", prepareParams(), 'application/json').then((response: any) => {
if (response.error != 0) {
console.log(response.message);
return;
}
fetch(response.data).then(res => {
return res.blob();
}).then(blob => {
let reader = new FileReader();
reader.onloadend = function () {
options.downloadSrc = reader.result;
setTimeout(() => {
document.getElementById("radarDownload").click();
options.downloadSrc = null;
}, 500);
};
reader.readAsDataURL(blob);
}).catch(console.error);
})
}
//参数准备
const prepareParams = () => {
return {
model: 'radar',
station: options.currentRegion,
elementCode: options.currentElement,
type: null,
time: moment(options.times[0].date).format("YYYYMMDDHHmmss") + '-' + moment(options.times[options.times.length - 1].date).format("YYYYMMDDHHmmss"),
urls: prepareUrls()
}
}
const prepareUrls = () => {
let urls = [];
for (let index = 0, len = options.times.length; index < len; index++) {
let time = moment(options.times[index].date);
if (options.currentElement === 'PBLH') {
urls.push(
RamanLidarConfig.getUrl(options.currentRegion, options.currentElement, time),
RamanLidarConfig.getUrl(options.currentRegion, 'signal_' + options.currentElement, time)
);
} else
urls.push(RamanLidarConfig.getUrl(options.currentRegion, options.currentElement, time));
}
console.log(urls)
return urls;
}
const converToBase64 = (path) => {
let img = new Image();
img.src = path;
let canvas = document.createElement("canvas") as HTMLCanvasElement;
canvas.width = img.width;
canvas.height = img.height;
let ctx = canvas.getContext("2d");
let base64 = '';
img.setAttribute("crossOrigin", 'Anonymous')
img.onload = function () {
ctx.drawImage(img, 0, 0);
base64 = canvas.toDataURL("image/png");
options.downloadImgUrl = base64;
};
}
//初始化时间轴
const initTimeLine = () => {
options.times = [];
options.currentTime = moment(options.date).format('YYYY-MM-DD');
let now = moment(options.date).add(1, 'day');
for (let i = 0; i < 15; i++) {
options.times.push({
day: now.add(-1, 'day').format('DD'),
date: now.format('YYYY-MM-DD'),
})
}
options.times.reverse();
options.index = options.times.length - 1;
}
//时间选择
const onTimeClick = (time, index) => {
options.currentTime = time.date;
options.date = time.date;
reloadChangeData()
options.index = index;
cancelActive();
setTitle(moment(time.date, 'YYYY-MM-DD'));
activeImage();
}
const cancelActive = () => {
clearTimer();
options.isPlay = false;
}
//上一天
const onPrevDayClick = () => {
let element = getCurrentElement();
options.date = moment(options.date).add(-1, 'day').format('YYYY-MM-DD');
options.currentTime = options.date;
options.index--;
if (options.index < 0) {
options.index = element.childElementCount - 1;
options.date = options.times[options.times.length - 1].date
}
initTimeLine()
cancelActive();
setCurrentPlayElement(element)
reloadChangeData()
}
const onNextDayClick = () => {
options.date = moment(options.date).add(1, 'day').format('YYYY-MM-DD')
initTimeLine()
reloadChangeData()
}
//上一张图片
const onPrevImgClick = () => {
let element = getCurrentElement();
options.index--;
if (options.index < 0)
options.index = element.childElementCount - 1;
setCurrentPlayElement(element);
}
const onNextImgClick = () => {
let element = getCurrentElement();
options.index++;
if (options.index > element.childElementCount - 1)
options.index = 0;
setCurrentPlayElement(element);
}
//重置
const onRefreshClick = () => {
options.date = moment('2021-11-15').format('YYYY-MM-DD');
options.currentTime = options.times[options.times.length - 1].date;
cancelActive();
activeImage();
}
const onPlayClick = () => {
options.isPlay = !options.isPlay;
if (options.isPlay) {
timeExcute();
} else {
clearTimer();
}
}
const timeExcute = () => {
clearTimer();
let element = getCurrentElement();
timer = setInterval(() => {
options.index++;
if (options.index > element.childElementCount - 1)
options.index = 0;
setCurrentPlayElement(element);
}, 3000)
}
const clearTimer = () => {
if (timer)
clearInterval(timer);
}
const getCurrentElement = () => {
return document.querySelector('.times');
}
const setCurrentPlayElement = (element) => {
for (let i = 0; i < element.childElementCount; i++)
element.children[i].classList.remove('active');
element.children[options.index].classList.add('active');
options.currentTime = options.times[options.index].date;
setTitle(moment(options.times[options.index].date, 'YYYY-MM-DD'));
activeImage();
}
const onChange = () => {
initTimeLine();
setTitle(moment(options.date));
activeImage();
}
const onSaveClick = () => {
let pictures = document.getElementById('pictures');
options.urls = [options.imgUrl, options.signalPBLHImgUrl];
for (let i = 0; i < options.urls.length; i++) {
let img = new Image();
img.src = options.urls[i];
let canvas = document.createElement("canvas") as HTMLCanvasElement;
canvas.width = img.width;
canvas.height = img.height;
let ctx = canvas.getContext("2d");
let base64 = "";
img.setAttribute("crossOrigin", 'Anonymous');
img.onload = () => {
ctx.drawImage(img, 0, 0);
base64 = canvas.toDataURL("image/png");
pictures.children[i].setAttribute('href', base64);
setTimeout(() => {
let button: HTMLElement = pictures.children[i] as HTMLElement;
button.click();
pictures.children[i].setAttribute('href', null);
}, 500);
};
}
}
//边界层高度
const boundaryLayerHeightDate = () => {
options.boundaryLayerHeightList = []
const time = moment(options.date).format('MM_DD')
const params = prepareApiParams(time, 'pblh')
get('/njqxj/lmlidar', params, ConstantRamanLidar.baseUrl).then((response: any) => {
if (response.length <= 0) {
verify()
return;
}
for (let i in response) {
for (let val in response[i]) {
options.boundaryLayerHeightList.push(response[i][val])
}
}
creates.boundaryLayerHeight.updateSeries(0, options.boundaryLayerHeightList)
})
}
//边界层特征值
const boundaryCharacteristicApi = () => {
const time = moment(options.date).format('MM_DD')
const params = prepareApiParams(time, 'pblhfeatures')
get('/njqxj/lmlidar', params, ConstantRamanLidar.baseUrl).then((response) => {
console.log(response)
})
}
//光学特性
//激光雷达比
const LidarRatioApi = () => {
options.LidarRatioList = []
const time = moment(options.date).format('MM_DD')
const params = prepareApiParams(time, 'lidarratio')
get('/njqxj/lmlidar', params, ConstantRamanLidar.baseUrl).then((response: any) => {
if (response.length <= 0) {
verify()
return;
}
for (let i in response[18]) {
if (response[18][i] === null) {
response[18][i] = 0
}
options.LidarRatioList.push(response[18][i])
}
creates.LidarRatio.updateSeries(0, options.LidarRatioList)
})
}
//消光系数
// const extinctionApi = () => {
// const time = moment(options.date).format('MM_DD')
// const params = prepareApiParams(time ,'extinction')
// get('/njqxj/lmlidar', params, ConstantRamanLidar.baseUrl).then((response :any) => {
//
// })
// }
//水汽
const waterVapourApi = () => {
const time = moment(options.date).format('MM_DD')
const params = prepareApiParams(time,'watervapor')
get('/njqxj/lmlidar', params, ConstantRamanLidar.baseUrl).then((response :any) => {
console.log(response)
})
}
//气溶胶PM
//粗颗粒
const aerosolApi = () => {
const time = moment(options.date).format('MM_DD')
const params = prepareApiParams(time,'pm10')
get('/njqxj/lmlidar', params, ConstantRamanLidar.baseUrl).then((response :any) => {
console.log(response)
})
}
//云气溶胶分类
const layerTypeApi = () => {
const time = moment(options.date).format('MM_DD')
const params = prepareApiParams(time,'layertype')
get('/njqxj/lmlidar', params, ConstantRamanLidar.baseUrl).then((response :any) => {
})
}
//云层高度
const cloudsHeightApi = () => {
options.cloudsHeightList = []
const time = moment(options.date).format('MM_DD')
const params = prepareApiParams(time,'cloudbaseheight')
get('/njqxj/lmlidar', params, ConstantRamanLidar.baseUrl).then((response :any) => {
if (response.length <= 0) {
verify()
return;
}
for (let i in response) {
for (let val in response[i]) {
if (response[i][val] === null) {
response[i][val] = 0
}
options.cloudsHeightList.push([parseInt(i),response[i][val]])
}
}
creates.cloudsHeight.updateSeries(0, options.cloudsHeightList)
})
}
//云顶高度
const cloudTopHeightApi = () => {
options.cloudTopHeightList = []
const time = moment(options.date).format('MM_DD')
const params = prepareApiParams(time,'cloudtopheight')
get('/njqxj/lmlidar', params, ConstantRamanLidar.baseUrl).then((response :any) => {
if (response.length <= 0) {
verify()
return;
}
for (let i in response) {
for (let val in response[i]) {
if (response[i][val] === null) {
response[i][val] = 0
}
options.cloudTopHeightList.push([parseInt(i),response[i][val]])
}
}
creates.cloudTopHeight.updateSeries(0, options.cloudTopHeightList)
})
}
const prepareApiParams = (time, variableName) => {
return {
date: time,
var: variableName,
}
}
const verify = () => {
ElMessage({
showClose: true,
message: '请求接口无数据',
icon: '',
type: null,
grouping: true,
duration: 1500
})
}
return {
...toRefs(options),
onRegionClick,
// onElementClick,
onTimeClick,
onPrevDayClick,
onNextDayClick,
onPrevImgClick,
onNextImgClick,
onRefreshClick,
onPlayClick,
onChange,
onImageLoad,
onDownloadClick,
onSaveClick,
onTabClick
}
}
}
</script>
<style lang="less" scoped>
.main {
.container {
.toolbar {
padding: 0.15rem 0;
.times {
padding-bottom: 0;
}
}
.raman-picture-container {
width: calc(~"100% - 1rem");
margin: 0 auto;
.picture {
position: relative;
margin-top: 30px;
.title {
width: 100%;
font-size: 0.22rem;
position: absolute;
left: 3.10rem;
top: 0.30rem;
z-index: 100;
}
.pblh-image {
width: 50%;
}
}
}
}
}
</style>