278 lines
6.6 KiB
Vue
278 lines
6.6 KiB
Vue
<script lang="ts" setup>
|
||
import type { EchartsUIType } from '@vben/plugins/echarts';
|
||
|
||
import { computed, onMounted, ref } from 'vue';
|
||
|
||
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||
|
||
const props = withDefaults(defineProps<{ type: string }>(), {
|
||
type: () => 'week',
|
||
});
|
||
|
||
const chartRef = ref<EchartsUIType>();
|
||
const { renderEcharts } = useEcharts(chartRef);
|
||
|
||
// 生成随机数据的函数
|
||
const generateRandomData = (count: number, min: number, max: number) => {
|
||
return Array.from(
|
||
{ length: count },
|
||
() => Math.floor(Math.random() * (max - min + 1)) + min,
|
||
);
|
||
};
|
||
|
||
// 生成日期标签的函数
|
||
const generateDateLabels = (type: string) => {
|
||
const today = new Date();
|
||
const labels: string[] = [];
|
||
|
||
switch (type) {
|
||
case 'halfyear': {
|
||
// 半年(180天,每10天一个数据点)
|
||
for (let i = 179; i >= 0; i--) {
|
||
const date = new Date(today);
|
||
date.setDate(date.getDate() - i);
|
||
labels.push(
|
||
`${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`,
|
||
);
|
||
}
|
||
break;
|
||
}
|
||
case 'month': {
|
||
// 近一个月(30天)
|
||
for (let i = 29; i >= 0; i--) {
|
||
const date = new Date(today);
|
||
date.setDate(date.getDate() - i);
|
||
labels.push(
|
||
`${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`,
|
||
);
|
||
}
|
||
break;
|
||
}
|
||
case 'week': {
|
||
// 近7天
|
||
for (let i = 6; i >= 0; i--) {
|
||
const date = new Date(today);
|
||
date.setDate(date.getDate() - i);
|
||
labels.push(
|
||
`${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`,
|
||
);
|
||
}
|
||
break;
|
||
}
|
||
default: {
|
||
// 默认近7天
|
||
for (let i = 6; i >= 0; i--) {
|
||
const date = new Date(today);
|
||
date.setDate(date.getDate() - i);
|
||
labels.push(
|
||
`${(date.getMonth() + 1).toString().padStart(2, '0')}.${date.getDate().toString().padStart(2, '0')}`,
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
return labels;
|
||
};
|
||
|
||
// 根据类型生成数据
|
||
const chartData = computed(() => {
|
||
const labels = generateDateLabels(props.type);
|
||
const dataCount = labels.length;
|
||
|
||
let trafficData: number[];
|
||
let deviceData: number[];
|
||
let maxValue: number;
|
||
|
||
switch (props.type) {
|
||
case 'halfyear': {
|
||
trafficData = generateRandomData(dataCount, 1000, 10_000);
|
||
deviceData = generateRandomData(dataCount, 10, 100);
|
||
maxValue = 1500;
|
||
break;
|
||
}
|
||
case 'month': {
|
||
trafficData = generateRandomData(dataCount, 800, 6000);
|
||
deviceData = generateRandomData(dataCount, 10, 100);
|
||
maxValue = 1200;
|
||
break;
|
||
}
|
||
case 'week': {
|
||
trafficData = generateRandomData(dataCount, 1000, 5000);
|
||
deviceData = generateRandomData(dataCount, 10, 100);
|
||
maxValue = 1000;
|
||
break;
|
||
}
|
||
default: {
|
||
trafficData = generateRandomData(dataCount, 1000, 5000);
|
||
deviceData = generateRandomData(dataCount, 10, 100);
|
||
maxValue = 1000;
|
||
}
|
||
}
|
||
|
||
return {
|
||
labels,
|
||
trafficData,
|
||
deviceData,
|
||
maxValue,
|
||
};
|
||
});
|
||
|
||
onMounted(() => {
|
||
const data = chartData.value;
|
||
|
||
renderEcharts({
|
||
title: {
|
||
text: '设备流量',
|
||
left: '0%',
|
||
textStyle: {
|
||
fontSize: '1.25rem',
|
||
},
|
||
},
|
||
grid: {
|
||
bottom: 0,
|
||
containLabel: true,
|
||
left: '1%',
|
||
right: '1%',
|
||
top: '20%',
|
||
},
|
||
legend: {
|
||
data: ['流量', '设备数'],
|
||
top: '3%',
|
||
},
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
axisPointer: {
|
||
type: 'cross',
|
||
},
|
||
textStyle: {
|
||
align: 'left', // 关键配置:文字左对齐
|
||
},
|
||
formatter(params: any) {
|
||
let result = `${params[0].name}<br/>`;
|
||
params.forEach((item: any) => {
|
||
result += `${item.marker + item.seriesName}: ${item.value}<br/>`;
|
||
});
|
||
return result;
|
||
},
|
||
},
|
||
xAxis: {
|
||
type: 'category',
|
||
data: data.labels,
|
||
boundaryGap: false, // 关键配置:取消坐标轴两边的留白
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: '#e0e0e0',
|
||
},
|
||
},
|
||
axisTick: {
|
||
show: false,
|
||
},
|
||
axisLabel: {
|
||
color: '#666',
|
||
},
|
||
},
|
||
yAxis: [
|
||
{
|
||
type: 'value',
|
||
name: '流量',
|
||
min: 0,
|
||
},
|
||
// {
|
||
// type: 'value',
|
||
// name: '设备数',
|
||
// min: 0,
|
||
// position: 'right',
|
||
// },
|
||
],
|
||
series: [
|
||
{
|
||
name: '流量',
|
||
type: 'line',
|
||
data: data.trafficData,
|
||
smooth: true,
|
||
symbol: 'emptyCircle',
|
||
symbolSize: 6,
|
||
showSymbol: false,
|
||
lineStyle: {
|
||
color: '#2D72FF',
|
||
width: 3,
|
||
// 阴影设置
|
||
shadowBlur: 20, // 阴影模糊程度
|
||
shadowColor: 'rgba(45, 114, 255, 0.5)', // 阴影颜色(带透明度)
|
||
shadowOffsetX: 0, // 阴影水平偏移
|
||
shadowOffsetY: 10, // 阴影垂直偏移(向下4px)
|
||
},
|
||
itemStyle: {
|
||
color: '#2D72FF',
|
||
},
|
||
// yAxisIndex: 0,
|
||
// areaStyle: {
|
||
// color: {
|
||
// type: 'linear',
|
||
// x: 0,
|
||
// y: 0,
|
||
// x2: 0,
|
||
// y2: 1,
|
||
// colorStops: [
|
||
// {
|
||
// offset: 0,
|
||
// color: 'rgba(45,114,255, 0.3.5)',
|
||
// },
|
||
// {
|
||
// offset: 1,
|
||
// color: 'rgba(45,114,255, 0.1)',
|
||
// },
|
||
// ],
|
||
// },
|
||
// },
|
||
},
|
||
{
|
||
name: '设备数',
|
||
type: 'line',
|
||
data: data.deviceData,
|
||
smooth: true,
|
||
symbol: 'emptyCircle',
|
||
symbolSize: 6,
|
||
showSymbol: false,
|
||
lineStyle: {
|
||
color: '#1FC5AE',
|
||
width: 3,
|
||
// 第二条线的阴影
|
||
shadowBlur: 20,
|
||
shadowColor: 'rgba(31, 197, 174, 0.5)',
|
||
shadowOffsetX: 0,
|
||
shadowOffsetY: 10,
|
||
},
|
||
itemStyle: {
|
||
color: '#1FC5AE',
|
||
},
|
||
// yAxisIndex: 1,
|
||
// areaStyle: {
|
||
// color: {
|
||
// type: 'linear',
|
||
// x: 0,
|
||
// y: 0,
|
||
// x2: 0,
|
||
// y2: 1,
|
||
// colorStops: [
|
||
// {
|
||
// offset: 0,
|
||
// color: 'rgba(31,197,174, 0.3)',
|
||
// },
|
||
// {
|
||
// offset: 1,
|
||
// color: 'rgba(31,197,174, 0.1)',
|
||
// },
|
||
// ],
|
||
// },
|
||
// },
|
||
},
|
||
],
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<EchartsUI ref="chartRef" style="height: 390px" />
|
||
</template>
|