1
0
forked from dyf/dyf-vue-ui
Files
dyf-vue-ui/src/views/homeIndex/components/DeviceUsage.vue

292 lines
7.5 KiB
Vue
Raw Normal View History

2025-09-27 16:10:17 +08:00
<template>
2025-09-28 15:28:15 +08:00
<div class="vchartPage">
<div class="btn_mounth_box">
<div class="btn_mounth" :class="{ cur: activeTab == 'month' }" @click="switchTab('month')">近一月</div>
<div class="btn_mounth" :class="{ cur: activeTab === 'halfYear' }" @click="switchTab('halfYear')">近半年</div>
</div>
2025-10-09 14:38:00 +08:00
<div ref="chartContainerRef" class="chartContainer" :class="{ 'show-scroll': showScroll }">
<div ref="chartRef" class="chartRef"></div>
</div>
2025-09-28 15:28:15 +08:00
</div>
2025-09-27 16:10:17 +08:00
</template>
2025-09-28 15:28:15 +08:00
<script setup lang="ts">
import * as echarts from 'echarts';
import { getDeviceUsageFrequency } from '@/api/homeIndex/index';
2025-09-30 10:59:31 +08:00
2025-09-28 15:28:15 +08:00
const chartRef = ref<HTMLDivElement | null>(null);
2025-10-09 14:38:00 +08:00
const chartContainerRef = ref<HTMLDivElement | null>(null);
2025-09-28 15:28:15 +08:00
const activeTab = ref('month');
2025-10-09 14:38:00 +08:00
const showScroll = ref(false); // 控制是否显示滚动条
let myChart: echarts.ECharts | null = null;
let dataTimer: NodeJS.Timeout | null = null;
2025-09-28 15:28:15 +08:00
// 根据天数获取数据并更新图表
const fetchDataAndUpdate = (days: number) => {
getDeviceUsageFrequency({ days }).then((res) => {
if (res.code === 200 && res.data && myChart) {
2025-10-09 14:38:00 +08:00
// 模拟数据(根据需求调整数量)
const dataCount = activeTab.value === 'month' ? 8 : 25; // 一月8条半年25条
const mockData = Array.from({ length: dataCount }, (_, index) => ({
deviceName: `设备${index + 1}`,
frequency: Math.floor(Math.random() * 100)
}));
2025-09-28 15:28:15 +08:00
const chartData = res.data.map(item => ({
name: item.deviceName,
value: item.frequency
}));
2025-10-09 14:38:00 +08:00
const scrollThreshold = 20;
showScroll.value = chartData.length > scrollThreshold;
// 动态计算图表高度
const baseItemHeight = 20;
const minHeight = 200;
const maxHeight = 600;
let chartHeight;
if (showScroll.value) {
chartHeight = Math.min(chartData.length * baseItemHeight, maxHeight);
} else {
chartHeight = Math.max(chartData.length * baseItemHeight, minHeight);
}
if (chartRef.value) {
chartRef.value.style.height = `${chartHeight}px`;
}
2025-09-28 15:28:15 +08:00
// 更新图表
myChart.setOption({
yAxis: {
data: chartData.map(item => item.name)
},
series: [{
data: chartData.map(item => item.value)
}]
});
2025-10-09 14:38:00 +08:00
// 数据更新后,重新调整图表尺寸
setTimeout(() => {
if (myChart) {
myChart.resize();
}
}, 0);
2025-09-28 15:28:15 +08:00
}
}).catch(err => {
2025-10-09 14:38:00 +08:00
console.error(err);
2025-09-28 15:28:15 +08:00
});
};
// 切换标签逻辑
const switchTab = (tab: string) => {
activeTab.value = tab;
const days = tab === 'month' ? 30 : 180;
fetchDataAndUpdate(days);
2025-09-30 10:59:31 +08:00
startDataTimer();
2025-10-09 14:38:00 +08:00
// 重置滚动位置
if (chartContainerRef.value) {
chartContainerRef.value.scrollTop = 10;
}
2025-09-28 15:28:15 +08:00
};
2025-09-30 10:59:31 +08:00
// 开始数据定时器
const startDataTimer = () => {
if (dataTimer) {
clearInterval(dataTimer);
}
dataTimer = setInterval(() => {
const days = activeTab.value === 'month' ? 30 : 180;
fetchDataAndUpdate(days);
}, 300000);
};
// 清除数据定时器
const clearDataTimer = () => {
if (dataTimer) {
clearInterval(dataTimer);
dataTimer = null;
}
};
// 初始化图表
const initChart = () => {
if (!chartRef.value) return;
2025-10-09 14:38:00 +08:00
2025-09-30 10:59:31 +08:00
myChart = echarts.init(chartRef.value);
const option = {
tooltip: {
trigger: 'axis',
2025-10-09 14:38:00 +08:00
axisPointer: { type: 'shadow' }
2025-09-30 10:59:31 +08:00
},
grid: {
left: '5%',
2025-10-09 14:38:00 +08:00
right: '5%',
bottom: '2%',
top: '12%',
2025-09-30 10:59:31 +08:00
containLabel: true
},
yAxis: {
type: 'category',
2025-10-09 14:38:00 +08:00
inverse: true,
data: [],
2025-09-30 10:59:31 +08:00
axisLine: {
lineStyle: {
color: '#1e3a8a',
show: false
2025-09-28 15:28:15 +08:00
}
},
2025-09-30 10:59:31 +08:00
axisLabel: {
2025-10-09 14:38:00 +08:00
color: '#DEEFFF',
fontSize: 12
},
axisTick: {
alignWithLabel: true
2025-09-30 10:59:31 +08:00
}
},
xAxis: {
type: 'value',
axisLine: { show: false },
axisLabel: { show: false },
2025-10-09 14:38:00 +08:00
splitLine: {
show: true,
lineStyle: {
color: 'rgba(30, 58, 138, 0.3)',
type: 'dashed'
}
}
2025-09-30 10:59:31 +08:00
},
series: [{
name: '使用频次',
type: 'bar',
2025-10-09 14:38:00 +08:00
data: [],
barWidth: '12px',
2025-09-30 10:59:31 +08:00
stack: 'total',
label: {
show: true,
position: 'right',
valueAnimation: true,
2025-10-09 14:38:00 +08:00
color: '#DEEFFF',
fontSize: 11
2025-09-28 15:28:15 +08:00
},
2025-09-30 10:59:31 +08:00
itemStyle: {
color: new echarts.graphic.LinearGradient(
0, 0, 1, 0,
[
{ offset: 0, color: '#0768D4' },
{ offset: 1, color: '#0EC4DF' }
]
),
borderRadius: 4
2025-10-09 14:38:00 +08:00
},
barGap: '30%',
barCategoryGap: '40%'
2025-09-30 10:59:31 +08:00
}]
};
myChart.setOption(option);
2025-10-09 14:38:00 +08:00
2025-09-30 10:59:31 +08:00
fetchDataAndUpdate(30);
startDataTimer();
};
// 处理窗口大小变化
const handleResize = () => {
if (myChart) {
myChart.resize();
}
};
onMounted(() => {
initChart();
window.addEventListener('resize', handleResize);
});
onUnmounted(() => {
clearDataTimer();
window.removeEventListener('resize', handleResize);
if (myChart) {
myChart.dispose();
myChart = null;
2025-09-28 15:28:15 +08:00
}
});
2025-09-27 16:10:17 +08:00
</script>
2025-09-28 15:28:15 +08:00
<style scoped lang="scss">
.vchartPage {
margin-top: 4.9vh;
2025-10-09 14:38:00 +08:00
position: relative;
height: 100%;
2025-09-28 15:28:15 +08:00
}
.btn_mounth_box {
display: flex;
position: absolute;
right: 1vh;
top: 0vh;
z-index: 1;
}
.btn_mounth {
2025-10-09 14:38:00 +08:00
width: 4.5vw;
height: 4.5vh;
2025-09-28 15:28:15 +08:00
background: url(@/assets/homeIndex/btn.png) no-repeat;
background-size: 100% 100%;
text-align: center;
line-height: 4.4vh;
color: #fff;
font-size: 0.8vw;
cursor: pointer;
2025-10-09 14:38:00 +08:00
margin-left: 0.5vw;
2025-09-28 15:28:15 +08:00
}
.cur {
background: url(@/assets/homeIndex/btn_cur.png) no-repeat;
background-size: 100% 100%;
}
2025-10-09 14:38:00 +08:00
.chartContainer {
width: 100%;
height: auto;
overflow-y: hidden;
overflow-x: hidden;
position: relative;
// margin-top: 2vh;
transition: all 0.3s ease;
// 当需要显示滚动条时的样式
&.show-scroll {
height: 24vh;
overflow-y: auto;
&::-webkit-scrollbar {
width: 8px;
}
&::-webkit-scrollbar-thumb {
background-color: rgba(7, 104, 212, 0.8);
border-radius: 4px;
border: 2px solid transparent;
background-clip: content-box;
}
&::-webkit-scrollbar-thumb:hover {
background-color: rgba(7, 104, 212, 1);
}
&::-webkit-scrollbar-track {
background-color: rgba(30, 58, 138, 0.1);
border-radius: 4px;
}
&::-webkit-scrollbar-track:hover {
background-color: rgba(30, 58, 138, 0.2);
}
}
}
2025-09-28 15:28:15 +08:00
.chartRef {
width: 100%;
2025-10-09 14:38:00 +08:00
min-height: 100px;
box-sizing: border-box;
2025-09-28 15:28:15 +08:00
}
</style>