guandu_front/src/components/dashboard/dashboardElecChart.vue
2025-05-19 12:06:36 +08:00

242 lines
5.5 KiB
Vue

<script setup>
import { ref, onMounted, onUnmounted, defineProps, watch } from "vue";
import * as echarts from "echarts";
const props = defineProps({
yesterdayTodayData: {
type: Object,
required: true,
},
weekComparisonData: {
type: Object,
required: true,
},
});
const yesterdayTodayChart = ref(null);
const weekComparisonChart = ref(null);
let yesterdayTodayEChart = null;
let weekComparisonEChart = null;
watch(
() => props.yesterdayTodayData,
(newYesterdayTodayData) => {
// 更新圖表
if (yesterdayTodayEChart) {
yesterdayTodayEChart.setOption(
generateCylinderChartOption(newYesterdayTodayData)
);
}
},
{ deep: true }
);
watch(
() => props.weekComparisonData,
(newWeekComparisonData) => {
// 更新圖表
if (weekComparisonEChart) {
weekComparisonEChart.setOption(
generateCylinderChartOption(newWeekComparisonData)
);
}
},
{ deep: true }
);
onMounted(() => {
// 初始化昨天和今天用電比較圖表
yesterdayTodayEChart = echarts.init(yesterdayTodayChart.value);
yesterdayTodayEChart.setOption(
generateCylinderChartOption(props.yesterdayTodayData)
);
// 初始化本週和上週用電比較圖表
weekComparisonEChart = echarts.init(weekComparisonChart.value);
weekComparisonEChart.setOption(
generateCylinderChartOption(props.weekComparisonData)
);
});
onUnmounted(() => {
if (yesterdayTodayEChart) {
yesterdayTodayEChart.dispose();
yesterdayTodayEChart = null;
}
if (weekComparisonEChart) {
weekComparisonEChart.dispose();
weekComparisonEChart = null;
}
});
// 生成圓柱圖表的 option
const generateCylinderChartOption = (data) => {
const dataCount = data.categories.length; // 數據筆數
let barWidth = 15; // 寬度
let symbolOffset = 0; // 偏移量
if (dataCount <= 7) {
barWidth = 15;
symbolOffset = 9;
} else if (dataCount <= 10) {
barWidth = 10;
symbolOffset = 6;
} else {
barWidth = 8;
symbolOffset = 5;
}
const color1 = {
// 今天用電量顏色
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{ offset: 0, color: "#69B0CF" }, // 左側顏色
{ offset: 0.5, color: "#acd7e4" }, // 中間顏色
{ offset: 1, color: "#69B0CF" }, // 右側顏色
],
};
const color2 = {
// 昨天用電量顏色
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{ offset: 0, color: "#E7F5A7" }, // 左側顏色
{ offset: 0.5, color: "#ebffe0" }, // 中間顏色
{ offset: 1, color: "#E7F5A7" }, // 右側顏色
],
};
return {
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
formatter: function (params) {
// 僅顯示 bar 系列的資料
const barData = params.filter((item) => item.seriesType === "bar");
const category = data.categories[params[0].dataIndex];
let tooltipContent = `${category}<br/>`;
barData.forEach((item) => {
tooltipContent += `${item.seriesName}: ${item.data}<br/>`;
});
return tooltipContent;
},
},
legend: {
data: data.values.map((item) => item.name),
bottom: "0%",
},
grid: {
left: "2%",
right: "2%",
top: "5%",
bottom: "10%",
containLabel: true,
},
xAxis: {
type: "category",
data: data.categories,
},
yAxis: {
type: "value",
},
series: [
{
name: data.values[0].name,
type: "bar",
barWidth: barWidth,
data: data.values[0].value,
itemStyle: {
color: color1,
},
},
{
name: data.values[1].name,
type: "bar",
barWidth: barWidth,
data: data.values[1].value,
itemStyle: {
color: color2,
},
},
// 圓柱頂部
{
name: null,
type: "pictorialBar",
symbolSize: [barWidth, 5],
symbolOffset: [-symbolOffset, -4], // 置中
symbolPosition: "end",
data: data.values[0].value,
z: 12,
itemStyle: {
color: "#acd7e4",
borderWidth: 0,
borderColor: "#fff",
borderType: "solid",
},
},
{
name: null,
type: "pictorialBar",
symbolSize: [barWidth, 5],
symbolOffset: [symbolOffset, -4], // 置中
symbolPosition: "end",
data: data.values[1].value,
itemStyle: {
color: "#ebffe0",
borderWidth: 1,
borderColor: "#E7F5A7",
borderType: "solid",
},
z: 12,
},
// 圓柱底部
{
name: null,
type: "pictorialBar",
symbolSize: [barWidth, 5],
symbolOffset: [-symbolOffset, 4], // 置中
symbolPosition: "start",
data: data.values[0].value,
z: 12,
itemStyle: {
color: "#69B0CF",
},
},
{
name: null,
type: "pictorialBar",
symbolSize: [barWidth, 5],
symbolOffset: [symbolOffset, 4], // 置中
symbolPosition: "start",
data: data.values[1].value,
itemStyle: {
color: "#E7F5A7",
},
z: 12,
},
],
};
};
</script>
<template>
<a-row :gutter="24" class="p-5">
<a-col :span="12">
<div ref="yesterdayTodayChart" style="width: 100%; height: 350px"></div>
</a-col>
<a-col :span="12">
<div ref="weekComparisonChart" style="width: 100%; height: 350px"></div>
</a-col>
</a-row>
</template>
<style scoped></style>