215 lines
5.0 KiB
Vue
Executable File
215 lines
5.0 KiB
Vue
Executable File
<script lang="ts" setup>
|
|
import {useDataStore} from "~/strores/DataStore";
|
|
import {useMainLayoutStore} from "~/strores/UseMainLayoutStore";
|
|
|
|
import type {PropType} from "vue";
|
|
import {ref} from 'vue';
|
|
import dayjs from "dayjs";
|
|
import VChart from 'vue-echarts';
|
|
import _ from "lodash";
|
|
|
|
const dataStore = useDataStore()
|
|
const mainLayoutStore = useMainLayoutStore()
|
|
type ArbitraryKeyValuePairs = {
|
|
[key: string]: (number | string)[];
|
|
};
|
|
const values = ref<ArbitraryKeyValuePairs>({});
|
|
const chartRet = 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:'',
|
|
tooltip: {
|
|
trigger: 'axis',
|
|
axisPointer: {
|
|
type: 'cross',
|
|
label: {
|
|
backgroundColor: '#6a7985'
|
|
}
|
|
}
|
|
},
|
|
grid: {
|
|
left: '2%',
|
|
right: '50',
|
|
bottom: '10%',
|
|
containLabel: true
|
|
},
|
|
xAxis: [
|
|
{
|
|
type: 'category',
|
|
boundaryGap: false,
|
|
data: []
|
|
}
|
|
],
|
|
yAxis: [
|
|
{
|
|
type: 'value',
|
|
}
|
|
],
|
|
toolbox: {
|
|
feature: {
|
|
dataZoom: {
|
|
yAxisIndex: 'none'
|
|
},
|
|
|
|
saveAsImage: {}
|
|
}
|
|
},
|
|
dataZoom: [
|
|
{
|
|
type: 'inside',
|
|
start: 90,
|
|
end: 100,
|
|
},
|
|
{
|
|
type: 'slider',
|
|
throttle: 500,
|
|
},
|
|
{
|
|
type: 'slider',
|
|
yAxisIndex: 0,
|
|
startValue: 0,
|
|
endValue: 100,
|
|
},
|
|
],
|
|
legend: {
|
|
data: props.valueNames,
|
|
textStyle: {
|
|
fontSize: 16,
|
|
},
|
|
},
|
|
series: props.valueNames?.map((id) => {
|
|
return {
|
|
name: id,
|
|
type: 'line',
|
|
large: true,
|
|
smooth: true,
|
|
emphasis: {
|
|
focus: 'series'
|
|
},
|
|
data: [],
|
|
}
|
|
}) ?? []
|
|
}
|
|
});
|
|
let interval: NodeJS.Timeout;
|
|
onUnmounted(() => {
|
|
clearInterval(interval);
|
|
})
|
|
onMounted(() => {
|
|
let history = dataStore.dataHistory
|
|
setTimeout(() => {
|
|
isLoading.value = false;
|
|
}, 5000)
|
|
nextTick(() => {
|
|
props.valueIds?.forEach((id, index) => {
|
|
chartRet.value.appendData({
|
|
seriesIndex: index,
|
|
data: history.data[id]
|
|
})
|
|
})
|
|
const currentOption = chartRet.value.getOption();
|
|
currentOption.xAxis[0].data = history.times
|
|
chartRet.value.setOption(currentOption)
|
|
isLoading.value = false
|
|
interval = setInterval(() => {
|
|
const data = dataStore.data
|
|
props.valueIds?.forEach((id, index) => {
|
|
const newData = data[id] ?? 0
|
|
if (!values.value[id]) {
|
|
values.value[id] = []
|
|
}
|
|
chartRet.value.appendData({
|
|
seriesIndex: index,
|
|
data: [newData]
|
|
})
|
|
})
|
|
const currentOption = chartRet.value.getOption();
|
|
currentOption.xAxis[0].data.push(dayjs().format('MM-DD HH:mm:ss'))
|
|
chartRet.value.setOption(currentOption)
|
|
}, 4000 + 1000 * Math.random())
|
|
})
|
|
})
|
|
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) => {
|
|
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="chartRet" :loading="isLoading" :manual-update="true" :option="option"
|
|
autoresize
|
|
:theme="$colorMode.value"
|
|
class="chart"
|
|
@datazoom="zoom"/>
|
|
</template>
|
|
|
|
<style>
|
|
.chart {
|
|
will-change: contents, scroll-position;
|
|
}
|
|
</style>
|