能源管理api串接

This commit is contained in:
koko 2024-11-04 18:11:13 +08:00
parent 3c876607ef
commit c5345db462
11 changed files with 354 additions and 206 deletions

2
src/apis/energy/api.js Normal file
View File

@ -0,0 +1,2 @@
export const GET_ELECUSE_DAY_API = `/api/Energe/GetElecUseDay`;
export const GET_TAI_POWER_API = `/api/Energe/GetTaipower`;

24
src/apis/energy/index.js Normal file
View File

@ -0,0 +1,24 @@
import {
GET_ELECUSE_DAY_API,
GET_TAI_POWER_API,
} from "./api";
import instance from "@/util/request";
import apihandler from "@/util/apihandler";
export const getElecUseDay = async () => {
const res = await instance.post(GET_ELECUSE_DAY_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getTaipower = async () => {
const res = await instance.post(GET_TAI_POWER_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};

View File

@ -61,7 +61,14 @@
"monthly_elec_consumption": "每月用电分析",
"monthly_carbon_emission_and_reduction": "每月碳排当量 (kgCO2e)",
"monthly_bill_power": "每月计费度数 (kWh)",
"interval_bill_degree": "区间计费度数"
"interval_bill_degree": "区间计费度数",
"peak": "尖峰",
"semi_peak": "半尖峰",
"off_peak": "离峰",
"var_elec_cost": "流动电费",
"fixed_elec_cost": "基本电费",
"total_elec_cost": "总电费",
"carbon_equivalent": "碳排当量"
},
"alarm": {
"title": "显示警告",

View File

@ -61,7 +61,14 @@
"monthly_elec_consumption": "每月用電分析",
"monthly_carbon_emission_and_reduction": "每月碳排當量 (kgCO2e)",
"monthly_bill_power": "每月計費度數 (kWh)",
"interval_bill_degree": "區間計費度數"
"interval_bill_degree": "區間計費度數",
"peak": "尖峰",
"semi_peak": "半尖峰",
"off_peak": "離峰",
"var_elec_cost": "流動電費",
"fixed_elec_cost": "基本電費",
"total_elec_cost": "總電費",
"carbon_equivalent": "碳排當量"
},
"alarm": {
"title": "顯示警告",

View File

@ -61,7 +61,14 @@
"monthly_elec_consumption": "Monthly electricity consumption analysis",
"monthly_carbon_emission_and_reduction": "Monthly carbon emission equivalent (kgCO2e)",
"monthly_bill_power": "Monthly billing power (kWh)",
"interval_bill_degree": "Interval billing degree"
"interval_bill_degree": "Interval billing degree",
"peak": "Peak",
"semi_peak": "Semi-Peak",
"off_peak": "Off-Peak",
"var_elec_cost": "Var. Elec. Cost",
"fixed_elec_cost": "Fixed Elec. Cost",
"total_elec_cost": "Total Elec. Cost",
"carbon_equivalent": "Carbon Equivalent"
},
"alarm": {
"title": "Warning",

View File

@ -6,6 +6,22 @@ import MonthlyElecBillChart from "./components/MonthlyElecBillChart.vue";
import CarbonEmissionChart from "./components/CarbonEmissionChart.vue";
import BillingDegreeChart from "./components/BillingDegreeChart.vue";
import IntervalBillChart from "./components/IntervalBillChart.vue";
import { getTaipower } from "@/apis/energy";
import { ref, onMounted, provide } from "vue";
const taipower_data = ref([]);
const getData = async () => {
const res = await getTaipower();
if (res.isSuccess) {
taipower_data.value = res.data;
}
};
onMounted(() => {
getData();
});
provide("energy_data", { taipower_data });
</script>
<template>

View File

@ -1,6 +1,10 @@
<script setup>
import BarChart from "@/components/chart/BarChart.vue";
import { ref, onMounted } from "vue";
import { ref, onMounted, inject, watch } from "vue";
import { useI18n } from "vue-i18n";
const { t, locale } = useI18n();
const { taipower_data } = inject("energy_data");
const defaultChartOption = ref({
tooltip: {
@ -10,7 +14,7 @@ const defaultChartOption = ref({
},
},
legend: {
data: ["Peak", "Semi-Peak", "Off-Peak"],
data: [ t("energy.peak"), t("energy.semi_peak"), t("energy.off_peak")],
textStyle: {
color: "#ffffff",
fontSize: 14,
@ -21,26 +25,13 @@ const defaultChartOption = ref({
grid: {
top: "5%",
left: "0%",
right: "0%",
right: "2%",
bottom: "15%",
containLabel: true,
},
xAxis: {
type: "category",
data: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
],
data: [],
axisLabel: {
color: "#ffffff",
},
@ -53,35 +44,28 @@ const defaultChartOption = ref({
},
series: [
{
name: "Peak",
name: t("energy.peak"),
type: "bar",
stack: "total",
data: [
5000, 5500, 7000, 7500, 9000, 9500, 11000, 11500, 11000, 7500, 6500,
5500,
],
data: [],
itemStyle: {
color: "#45f4ef",
},
},
{
name: "Semi-Peak",
name: t("energy.semi_peak"),
type: "bar",
stack: "total",
data: [
3000, 3200, 4500, 4800, 5200, 5800, 6000, 6100, 6200, 5300, 4500, 4000,
],
data: [],
itemStyle: {
color: "#ffd345",
},
},
{
name: "Off-Peak",
name: t("energy.off_peak"),
type: "bar",
stack: "total",
data: [
2000, 2500, 3500, 4000, 4500, 5000, 5200, 5300, 5400, 4500, 4000, 3500,
],
data: [],
itemStyle: {
color: "#64ed81",
},
@ -89,9 +73,24 @@ const defaultChartOption = ref({
],
});
onMounted(() => {
//
});
// taipower_data
watch(
taipower_data,
() => {
//
const months = taipower_data.value.map(item => item.month);
const kWhPeak = taipower_data.value.map((item) => item.kWhPeak);
const kWhHalfPeak = taipower_data.value.map((item) => item.kWhHalfPeak);
const kWhOffPeak = taipower_data.value.map((item) => item.kWhOffPeak);
//
defaultChartOption.value.xAxis.data = months;
defaultChartOption.value.series[0].data = kWhPeak;
defaultChartOption.value.series[1].data = kWhHalfPeak;
defaultChartOption.value.series[2].data = kWhOffPeak;
},
{ deep: true }
);
</script>
<template>

View File

@ -1,6 +1,10 @@
<script setup>
import BarChart from "@/components/chart/BarChart.vue";
import { ref, onMounted } from "vue";
import { ref, inject, watch } from "vue";
import { useI18n } from "vue-i18n";
const { t, locale } = useI18n();
const { taipower_data } = inject("energy_data");
const defaultChartOption = ref({
tooltip: {
@ -10,7 +14,7 @@ const defaultChartOption = ref({
},
},
legend: {
data: ["Carbon Equivalent"],
data: [t("energy.carbon_equivalent")],
textStyle: {
color: "#ffffff",
fontSize: 14,
@ -21,26 +25,13 @@ const defaultChartOption = ref({
grid: {
top: "5%",
left: "0%",
right: "0%",
right: "2%",
bottom: "15%",
containLabel: true,
},
xAxis: {
type: "category",
data: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
],
data: [],
axisLabel: {
color: "#ffffff",
},
@ -53,22 +44,30 @@ const defaultChartOption = ref({
},
series: [
{
name: "Carbon Equivalent",
name: t("energy.carbon_equivalent"),
type: "bar",
data: [
5400, 6500, 7200, 7500, 9800, 9500, 11200, 11500, 11800, 7500, 6500,
5500,
],
data: [],
itemStyle: {
color: "#45f4ef",
},
}
},
],
});
onMounted(() => {
//
});
// taipower_data
watch(
taipower_data,
() => {
//
const months = taipower_data.value.map(item => item.month);
const carbonTotal = taipower_data.value.map(item => item.carbon);
// xAxis series
defaultChartOption.value.xAxis.data = months;
defaultChartOption.value.series[0].data = carbonTotal;
},
{ deep: true }
);
</script>
<template>

View File

@ -1,107 +1,144 @@
<script setup>
import BarChart from "@/components/chart/BarChart.vue";
import { ref, onMounted } from "vue";
import { ref, onMounted, computed } from "vue";
import { getElecUseDay } from "@/apis/energy";
import { useI18n } from "vue-i18n";
const generateDateRange = () => {
const dates = [];
for (let day = 1; day <= 15; day++) {
const formattedDay = day < 10 ? `0${day}` : day;
dates.push(`11 / ${formattedDay}`);
}
return dates;
};
const defaultChartOption = ref({
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
legend: {
data: ["Peak", "Semi-Peak", "Off-Peak"],
textStyle: {
color: "#ffffff",
fontSize: 14,
},
orient: "horizontal",
bottom: "0%",
},
grid: {
top: "5%",
left: "0%",
right: "0%",
bottom: "15%",
containLabel: true,
},
xAxis: {
type: "category",
data: generateDateRange(),
axisLabel: {
color: "#ffffff",
},
},
yAxis: {
type: "value",
axisLabel: {
color: "#ffffff",
},
},
series: [
{
name: "Peak",
type: "bar",
stack: "total",
data: [
5000, 5500, 7000, 7500, 9000, 9500, 11000, 11500, 11000, 7500, 6500,
5500, 6000, 6200, 5800,
],
itemStyle: {
color: "#3c50e0",
},
},
{
name: "Semi-Peak",
type: "bar",
stack: "total",
data: [
3000, 3200, 4500, 4800, 5200, 5800, 6000, 6100, 6200, 5300, 4500, 4000,
4200, 4300, 4100,
],
itemStyle: {
color: "#6577f3",
},
},
{
name: "Off-Peak",
type: "bar",
stack: "total",
data: [
2000, 2500, 3500, 4000, 4500, 5000, 5200, 5300, 5400, 4500, 4000, 3500,
3700, 3800, 3600,
],
itemStyle: {
color: "#8fd0ef",
},
},
],
const { t } = useI18n();
const dataSource = ref([]);
const dateRange = ref({
min: null,
max: null,
});
//
const chartConfig = {
colors: {
peak: "#3c50e0",
semiPeak: "#6577f3",
offPeak: "#8fd0ef",
},
textColor: "#ffffff",
fontSize: 14,
};
const processedData = computed(() => {
if (!dataSource.value.length) return null;
const dates = dataSource.value.map((d) => {
const [year, month, day] = d.time.split(" ")[0].split("-");
return `${month}-${day}`;
});
return {
dates,
peak: dataSource.value.map((d) => d.degreePeak),
semiPeak: dataSource.value.map((d) => d.degreeHalfPeak),
offPeak: dataSource.value.map((d) => d.degreeOffPeak),
};
});
const chartOption = computed(() => {
if (!processedData.value) return {};
return {
tooltip: {
trigger: "axis",
axisPointer: { type: "shadow" },
},
legend: {
data: [t("energy.peak"), t("energy.semi_peak"), t("energy.off_peak")],
textStyle: {
color: chartConfig.textColor,
fontSize: chartConfig.fontSize,
},
orient: "horizontal",
bottom: "0%",
},
grid: {
top: "5%",
left: "0%",
right: "0%",
bottom: "15%",
containLabel: true,
},
xAxis: {
type: "category",
data: processedData.value.dates,
axisLabel: {
color: chartConfig.textColor,
},
},
yAxis: {
type: "value",
axisLabel: {
color: chartConfig.textColor,
},
},
series: [
{
name: t("energy.peak"),
type: "bar",
stack: "total",
data: processedData.value.peak,
itemStyle: {
color: chartConfig.colors.peak,
},
},
{
name: t("energy.semi_peak"),
type: "bar",
stack: "total",
data: processedData.value.semiPeak,
itemStyle: {
color: chartConfig.colors.semiPeak,
},
},
{
name: t("energy.off_peak"),
type: "bar",
stack: "total",
data: processedData.value.offPeak,
itemStyle: {
color: chartConfig.colors.offPeak,
},
},
],
};
});
const loadData = async () => {
const res = await getElecUseDay();
if (res.isSuccess) {
dataSource.value = res.data.map((d) => ({ ...d, key: d.id }));
const dates = res.data.map((d) => d.time.split(" ")[0]);
dateRange.value = {
min: dates[0],
max: dates[dates.length - 1],
};
}
};
onMounted(() => {
//
loadData();
});
</script>
<template>
<div class="bg-slate-700 p-3">
<div class="text-white mb-3 text-base">
{{ $t("energy.interval_bill_degree") }} 2024 / 11 / 01 ~ 2024 / 11 / 15
<div
class="text-white mb-3 text-base"
v-if="dateRange.min && dateRange.max"
>
{{ $t("energy.interval_bill_degree") }} {{ dateRange.min }} ~
{{ dateRange.max }}
</div>
<div class="bar-box">
<BarChart
id="billing_degree_chart"
class="min-h-[200px] w-full h-full"
:option="defaultChartOption"
:option="chartOption"
ref="degree_chart"
/>
</div>

View File

@ -1,7 +1,12 @@
<script setup>
import BarChart from "@/components/chart/BarChart.vue";
import { ref, onMounted } from "vue";
import { ref, onMounted, inject, watch } from "vue";
import { useI18n } from "vue-i18n";
const { t, locale } = useI18n();
const { taipower_data } = inject("energy_data");
//
const defaultChartOption = ref({
tooltip: {
trigger: "axis",
@ -10,7 +15,11 @@ const defaultChartOption = ref({
},
},
legend: {
data: ["Var. Elec. Cost", "Fixed Elec. Cost", "Total Elec. Cost"],
data: [
t("energy.fixed_elec_cost"),
t("energy.var_elec_cost"),
t("energy.total_elec_cost"),
],
textStyle: {
color: "#ffffff",
fontSize: 14,
@ -21,26 +30,13 @@ const defaultChartOption = ref({
grid: {
top: "5%",
left: "0%",
right: "0%",
right: "2%",
bottom: "15%",
containLabel: true,
},
xAxis: {
type: "category",
data: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
],
data: [],
axisLabel: {
color: "#ffffff",
},
@ -53,38 +49,28 @@ const defaultChartOption = ref({
},
series: [
{
name: "Var. Elec. Cost",
name: t("energy.fixed_elec_cost"),
type: "bar",
stack: "total",
data: [
15000, 16000, 20000, 21000, 25000, 26000, 30000, 31000, 35000, 27600,
16500, 15000,
],
data: [],
itemStyle: {
color: "#ffd345",
},
},
{
name: t("energy.var_elec_cost"),
type: "bar",
stack: "total",
data: [],
itemStyle: {
color: "#45f4ef",
},
},
{
name: "Fixed Elec. Cost",
name: t("energy.total_elec_cost"),
type: "bar",
stack: "total",
data: [
5000, 5500, 7000, 7500, 9000, 9500, 11000, 11500, 11000, 7500, 6500,
5500,
],
itemStyle: {
color: "#ffd345",
},
},
{
name: "Total Elec. Cost",
type: "bar",
stack: "total",
data: [
3000, 3000, 4000, 5000, 12000, 17000, 20000, 20000, 12000, 12000, 5000,
0,
],
data: [],
itemStyle: {
color: "#64ed81",
},
@ -92,9 +78,24 @@ const defaultChartOption = ref({
],
});
onMounted(() => {
//
});
// taipower_data
watch(
taipower_data,
() => {
//
const months = taipower_data.value.map(item => item.month);
const costTotal = taipower_data.value.map((item) => item.costTotal);
const costBase = taipower_data.value.map((item) => item.costBase);
const costChange = taipower_data.value.map((item) => item.costChange);
//
defaultChartOption.value.xAxis.data = months;
defaultChartOption.value.series[0].data = costBase;
defaultChartOption.value.series[1].data = costChange;
defaultChartOption.value.series[2].data = costTotal;
},
{ deep: true }
);
</script>
<template>

View File

@ -1,33 +1,82 @@
<script setup>
import { ref, watch } from "vue";
import { ref, watch, inject } from "vue";
import { twMerge } from "tailwind-merge";
import { useI18n } from "vue-i18n";
const { t, locale } = useI18n();
const updateDataItems = () => {
const { t, locale } = useI18n();
const { taipower_data } = inject("energy_data");
const daysInMonth = (month) => {
const [year, monthNumber] = month.split("-");
return new Date(year, monthNumber, 0).getDate(); //
};
//
const calculateData = () => {
const currentYear = new Date().getFullYear().toString(); //
//
const filteredData = taipower_data.value.filter((item) =>
item.month.startsWith(currentYear)
);
const totalElecBills = filteredData.reduce((sum, item) => sum + item.kWh, 0);
const latestMonthData = filteredData[filteredData.length - 1];
const latestMonth = latestMonthData ? latestMonthData.month : "";
const monthDays = latestMonth ? daysInMonth(latestMonth) : 0;
const monthTxt = latestMonth
? `${latestMonth}-01~${latestMonth}-${monthDays}`
: "";
const totalCarbonEmission = filteredData.reduce(
(sum, item) => sum + item.carbon,
0
);
const totalElecConsumption = filteredData.reduce(
(sum, item) => sum + item.kWh,
0
);
return [
{ title: t("energy.elec_bills"), data: "3,255,458" },
{ title: t("energy.interval_elec_charges"), data: "205,110" },
{ title: t("energy.year_carbon_emission"), data: "455,128" },
{ title: t("energy.elec_bills"), data: totalElecBills.toLocaleString() },
{
title: t("energy.interval_elec_charges"),
time: monthTxt,
data: latestMonthData ? latestMonthData.costTotal.toLocaleString() : 0,
},
{
title: t("energy.year_carbon_emission"),
data: totalCarbonEmission.toLocaleString(),
},
{
title: t("energy.interval_carbon_emission"),
time: "2023-11-01~2023-11-19",
data: "25,351",
time: monthTxt,
data: latestMonthData ? latestMonthData.carbon.toLocaleString() : 0,
},
{
title: t("energy.year_elec_consumption"),
data: totalElecConsumption.toLocaleString(),
},
{ title: t("energy.year_elec_consumption"), data: "864,830" },
{
title: t("energy.interval_elec_consumption"),
time: "2023-11-01~2023-11-19",
data: "50,355",
time: monthTxt,
data: latestMonthData ? latestMonthData.kWh.toLocaleString() : 0,
},
];
};
const dataItems = ref(updateDataItems());
const dataItems = ref(calculateData());
watch(locale, () => {
dataItems.value = updateDataItems();
dataItems.value = calculateData();
});
watch(
taipower_data,
() => {
dataItems.value = calculateData();
},
{ deep: true }
);
</script>
<template>