242 lines
5.5 KiB
Vue
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>
|