<template>
|
<div class="water-velocity-content">
|
<!-- 提示信息 -->
|
<div v-if="showSelectPrompt" style=" font-weight: bold;">
|
请在地图中选取唯一测量点
|
</div>
|
|
<!-- 正常内容 -->
|
<div v-else>
|
<!-- 位置信息 -->
|
<div class="location-info">
|
<h3>位置信息</h3>
|
<p class="coordinates">
|
经度: <strong>{{ safeCurrentInfo.longitude.toFixed(3) }} </strong>
|
纬度:<strong>{{ safeCurrentInfo.latitude.toFixed(3) }}</strong>
|
</p>
|
</div>
|
|
<!-- 流速信息 -->
|
<div class="velocity-info">
|
<h3>流速信息 (m/s)</h3>
|
<p>
|
平均:<strong>1.25</strong>
|
最大:<strong>1.80</strong>
|
最小:<strong>0.70</strong>
|
</p>
|
</div>
|
</div>
|
|
<!-- 图表区域 -->
|
<div class="chart-placeholder">
|
<div ref="chartDom" style="width: 100%; height: 300px;"></div>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, onMounted, watch, computed, onBeforeUnmount,onBeforeMount } from 'vue';
|
import * as echarts from 'echarts';
|
import { useSimStore } from "@/store/simulation";
|
import { storeToRefs } from "pinia";
|
import { EventBus } from "@/eventBus"; // 引入事件总线
|
|
const simStore = useSimStore();
|
const { currentInfo } = storeToRefs(simStore);
|
|
// 定义图表的 DOM 元素引用
|
const chartDom = ref(null);
|
let myChart = null;
|
|
// 计算属性:安全获取经纬度
|
const safeCurrentInfo = computed(() => {
|
const info = currentInfo.value || {};
|
return {
|
longitude: info.longitude !== undefined ? info.longitude : 0.0,
|
latitude: info.latitude !== undefined ? info.latitude : 0.0
|
};
|
});
|
|
// 判断是否需要显示选择提示
|
const showSelectPrompt = computed(() => {
|
const info = safeCurrentInfo.value;
|
return info.longitude === 0.0 && info.latitude === 0.0;
|
});
|
|
// 防抖函数
|
function debounce(func, wait) {
|
let timeout;
|
return function () {
|
const context = this;
|
const args = arguments;
|
clearTimeout(timeout);
|
timeout = setTimeout(() => {
|
func.apply(context, args);
|
}, wait);
|
};
|
}
|
|
// 简化数据源
|
function generateSampleData() {
|
const now = new Date();
|
const data = [];
|
// 生成7个数据点,每10分钟一个
|
for (let i = 100; i >= 0; i--) {
|
const time = new Date(now.getTime() - i * 10 * 60 * 1000);
|
// 随机生成0.7-1.8之间的流速数据
|
const velocity = (0.7 + Math.random() * 3).toFixed(2);
|
data.push({
|
time: time,
|
value: parseFloat(velocity)
|
});
|
}
|
return data;
|
}
|
|
function initChart(chart) {
|
const data = generateSampleData();
|
|
const option = {
|
// grid: {
|
// top: '5%', // 上边距减少 => 折线图变高
|
// bottom: '%', // 下边距减少 => 折线图变高
|
// left: '10%', // 左边距减少 => 折线图变宽
|
// right: '10%' // 右边距减少 => 折线图变宽
|
// },
|
title: {
|
text: '流速变化趋势',
|
textStyle: {
|
color: '#fff',
|
fontSize: 16
|
},
|
// 将标题向左移动 1%
|
left: '-1%'
|
},
|
tooltip: {
|
trigger: 'axis',
|
formatter: (params) => {
|
const date = new Date(params[0].value[0]);
|
return `${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}<br/>流速:${params[0].value[1]} m/s`;
|
},
|
backgroundColor: 'rgba(0,0,0,0.7)',
|
textStyle: {
|
color: '#fff',
|
fontSize: 14
|
}
|
},
|
xAxis: {
|
type: 'time',
|
// 取消 X 轴单位
|
name: '',
|
axisLabel: {
|
color: '#fff',
|
fontSize: 12,
|
formatter: function (value) {
|
const date = new Date(value);
|
return `${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}`;
|
},
|
interval: 'auto', // 自动计算间隔防止重叠
|
rotate: 45 // 倾斜45度防止重叠
|
},
|
nameTextStyle: {
|
color: '#fff',
|
fontSize: 14
|
}
|
},
|
yAxis: {
|
type: 'value',
|
name: '流速(m/s)',
|
min: 0.5, // 设置最小值
|
max: 6.0, // 设置最大值
|
axisLabel: {
|
color: '#fff',
|
fontSize: 12,
|
},
|
nameTextStyle: {
|
color: '#fff',
|
fontSize: 14
|
},
|
},
|
series: [{
|
name: '流速',
|
type: 'line',
|
data: data.map(item => [item.time, item.value]),
|
showSymbol: true,
|
lineStyle: {
|
color: '#f97316', // 橙色
|
width: 2
|
},
|
itemStyle: {
|
color: '#f97316'
|
},
|
smooth: true // 平滑曲线
|
}],
|
// dataZoom: [{
|
// type: 'slider',
|
// start: 0,
|
// end: 100,
|
// textStyle: {
|
// color: '#fff',
|
// fontSize: 12
|
// },
|
// filterMode: 'filter', // 避免重复渲染
|
// // 缩放控件向下移动 2%
|
// bottom: '0%'
|
// }],
|
// 全局文字样式
|
textStyle: {
|
color: '#fff',
|
fontSize: 14
|
},
|
animation: false // 禁用动画,提高性能
|
};
|
|
chart.setOption(option);
|
|
// 添加防抖的resize监听
|
window.addEventListener('resize', debounce(() => {
|
chart.resize();
|
}, 200));
|
}
|
|
watch(
|
() => currentInfo.value,
|
(newVal) => {
|
if (!newVal || showSelectPrompt.value || !chartDom.value) return;
|
|
console.log('经度:', newVal.longitude);
|
console.log('纬度:', newVal.latitude);
|
console.log('服务名称:', newVal.serviceInfo);
|
|
// 销毁旧图表
|
if (myChart) {
|
myChart.dispose();
|
}
|
|
// 创建新图表
|
myChart = echarts.init(chartDom.value);
|
initChart(myChart);
|
},
|
{ deep: true }
|
);
|
|
onMounted(() => {
|
if (!showSelectPrompt.value && chartDom.value) {
|
myChart = echarts.init(chartDom.value);
|
initChart(myChart);
|
}
|
});
|
onBeforeMount(() => {
|
EventBus.on('clear-water-velocity', clear);
|
});
|
onBeforeUnmount(() => {
|
if (myChart) {
|
myChart.dispose();
|
myChart = null;
|
}
|
EventBus.off('clear-water-velocity', clear);
|
|
});
|
function clear() {
|
// 清空 store 中的经纬度信息
|
currentInfo.value.longitude = 0.0;
|
currentInfo.value.latitude = 0.0;
|
|
// 清除 ECharts 图表
|
if (myChart) {
|
myChart.clear(); // 清除图表数据和图形
|
myChart.dispose(); // 销毁实例,释放资源
|
myChart = null;
|
}
|
}
|
// 添加 resizeChart 方法
|
function resizeChart() {
|
if (myChart) {
|
myChart.resize();
|
}
|
}
|
|
// 暴露方法给父组件调用
|
defineExpose({ resizeChart });
|
</script>
|
|
<style scoped>
|
.water-velocity-content {
|
padding-left: 8px;
|
padding-top: 8px;
|
padding-bottom: -8px;
|
border-radius: 6px;
|
}
|
|
.location-info,
|
.velocity-info {
|
margin-bottom: 10px;
|
}
|
|
.coordinates {
|
font-size: 15px;
|
color: #fff;
|
user-select: all;
|
display: inline-block;
|
border-radius: 4px;
|
transition: background-color 0.2s ease;
|
}
|
|
.velocity-info p {
|
font-size: 14px;
|
color: #fff;
|
}
|
|
.velocity-info strong {
|
color: #fff;
|
margin: 0 4px;
|
}
|
|
.chart-placeholder {
|
overflow: hidden;
|
height: 284px;
|
/* margin-top: 10px; */
|
}
|
</style>
|