LoongPanel-Asp/web/components/Charts/AreaChart.vue

225 lines
5.4 KiB
Vue

<script lang="ts" setup>
import {useDataStore} from "~/strores/DataStore";
import {useMainLayoutStore} from "~/strores/UseMainLayoutStore";
import type {PropType} from "vue";
import {ref} from 'vue';
import VChart from 'vue-echarts';
import _ from "lodash";
import {useSessionSignalRStore} from "~/strores/HubStore";
const dataStore = useDataStore()
const hubStore = useSessionSignalRStore()
const mainLayoutStore = useMainLayoutStore()
const chartRef = ref<any>(null)
const isLoading = ref<boolean>(true)
const props = defineProps({
valueIds: {
type: Array as PropType<string[]>,
required: true,
},
valueNames: {
type: Array as PropType<string[]>,
required: true,
},
rangeNum: {
type: Number,
default: 6,
},
})
const option = computed(() => {
return {
backgroundColor: '',
//关闭动画
// animation: false,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
grid: {
left: '0',
right: '50',
bottom: '38',
top: '15',
containLabel: true
},
xAxis: [
{
type: 'time',
boundaryGap: false,
axisLabel: {
showMinLabel: true,
showMaxLabel: true,
}
},
],
yAxis: [
{
type: 'value',
}
],
dataZoom: [
{
type: 'inside',
start: 99.5,
end: 100,
},
{
type: 'slider',
},
{
type: 'slider',
yAxisIndex: 0,
},
],
legend: {
data: props.valueNames,
},
series: props.valueNames?.map((id) => {
return {
name: id,
type: 'line',
areaStyle: {},
large: true,
smooth: true,
largeThreshold: 10000,
sampling: 'lttb',
emphasis: {
focus: 'series'
},
markPoint: {
data: [
{type: 'max', name: 'Max'},
{type: 'min', name: 'Min'}
]
},
markLine: {
data: [{type: 'average', name: 'Avg'}]
},
data: [],
}
}) ?? []
}
});
let interval: NodeJS.Timeout;
onUnmounted(() => {
clearInterval(interval);
})
let maxValue = 100;
onMounted(() => {
if (!chartRef.value) {
console.error('ECharts instance is not initialized');
return;
}
hubStore.connection?.on("ReceiveDataHistory", (type: string, values: [number,string][], done: boolean) => {
chartRef.value.appendData({
seriesIndex: props.valueIds?.indexOf(type),
data: values
})
if (done) {
//设置y轴最大值为数据最大值的140%
// const currentOption = chartRef.value.getOption();
// const maxData = Math.max(...values.map(item =>item[1]));
// if (maxData > maxValue) {
// maxValue = maxData
// currentOption.yAxis[0].max = maxData * 1.4;
// chartRef.value.setOption(currentOption);
// }
}
isLoading.value = false;
})
setTimeout(() => {
$fetch('/Api/Server/GetServerHistoryDate', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + useCookie('token').value
},
params: {
ServerId: mainLayoutStore.SelectServer.value,
DataTypes: props.valueIds,
StartIndex: 0,
},
baseURL: useRuntimeConfig().public.baseUrl,
})
}, 2000)
})
// let endIndex = dataStore.dataHistory.times ? dataStore.dataHistory.times.length : 0
// let startTemp = 0;
// let done = false;
// type Data = {
// times: string[]; // 时间轴
// data: { [key: string]: string[] }; // 数据,键是字符串,值是字符串数组的数组
// endIndex: number; // 结束索引
// done: boolean; // 是否完成加载
// };
// const zoom = _.throttle((e: any) => {
// console.log(e)
// let start = e.start ?? e.batch[0].start
// if (done) return
// if (start <= 50 && start !== startTemp) {
// startTemp = e.start
// isLoading.value = true
// setTimeout(() => {
// isLoading.value = false
// }, 5000)
// $fetch('/Api/Server/GetServerHistoryDate', {
// method: 'GET',
// headers: {
// 'Authorization': 'Bearer ' + useCookie('token').value
// },
// params: {
// ServerId: mainLayoutStore.SelectServer.value,
// DataTypes: props.valueIds,
// StartIndex: endIndex,
// },
// baseURL: useRuntimeConfig().public.baseUrl,
// }).then((res) => {
// console.log(res)
// const data = res as Data;
// if (data.done) {
// isLoading.value = false
// done = true
// return
// }
// endIndex = data.endIndex
// //获得图表data
// const currentOption = chartRet.value.getOption();
// currentOption.series.map((series: any, index: number) => {
// series.data = [...data.data[props.valueIds[index]], ...series.data]
// })
// currentOption.xAxis[0].data = [...data.times, ...currentOption.xAxis[0].data]
// //start 为5
// currentOption.dataZoom[0].start = 55
// chartRet.value.setOption(currentOption)
// setTimeout(() => {
// isLoading.value = false
// }, 1000)
// })
// }
// }, 1000)
</script>
<template>
<v-chart ref="chartRef" :loading="isLoading" :manual-update="true" :option="option"
autoresize
:theme="$colorMode.value"
class="chart"
/>
</template>
<style>
.chart {
will-change: contents, scroll-position;
}
</style>