EMS_front/src/components/PdfContent.vue

534 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div v-loading="loading" element-loading-text="資料加載中...">
<el-row :gutter="20">
<el-col :span="6">
<el-descriptions class="margin-top" title="報表資訊" :column="1" border>
<el-descriptions-item>
<template #label>
<div class="cell-item">報表名稱</div>
</template>
{{ props.form?.name }}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">報表期間</div>
</template>
{{ dayjs(props.form?.date).format("YYYY/MM") }}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">編製日期</div>
</template>
{{ dayjs().format("YYYY/MM/DD") }}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">編製人員</div>
</template>
{{ props.form?.staff }}
</el-descriptions-item>
</el-descriptions>
</el-col>
<el-col :span="13">
<el-descriptions
class="margin-top"
:title="priceTitle"
:column="2"
border
>
<el-descriptions-item>
<template #label>
<div class="cell-item">基本電費-三相</div>
</template>
{{ Three_Phase }}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">契約容量</div>
</template>
{{ ContractUse }}
</el-descriptions-item>
<el-descriptions-item v-if="isSummerMonth != 'non-summer'">
<template #label>
<div class="cell-item">
流動電價-平日尖峰單價
<!-- {{ isSummerMonth == "half-summer" ? "(夏月)" : "" }} -->
</div>
</template>
{{ Summer_Peak_Prices }}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
基本電費-經常契約
<!-- {{ isSummerMonth == "half-summer" ? "(夏月/非夏月)" : "" }} -->
</div>
</template>
{{
isSummerMonth === "summer"
? Regular_Contract_Summer
: isSummerMonth === "non-summer"
? Regular_Contract_Non_Summer
: `${Regular_Contract_Summer} / ${Regular_Contract_Non_Summer}`
}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
流動電價-平日半尖峰單價
<!-- {{ isSummerMonth == "half-summer" ? "(夏月/非夏月)" : "" }} -->
</div>
</template>
{{
isSummerMonth === "summer"
? Summer_HalfPeak_Prices_Weekday
: isSummerMonth === "non-summer"
? Non_Summer_HalfPeak_Prices_Weekday
: `${Summer_HalfPeak_Prices_Weekday} / ${Non_Summer_HalfPeak_Prices_Weekday}`
}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
流動電價-平日離峰單價
<!-- {{ isSummerMonth == "half-summer" ? "(夏月/非夏月)" : "" }} -->
</div>
</template>
{{
isSummerMonth === "summer"
? Summer_Off_Prices_Weekday
: isSummerMonth === "non-summer"
? Non_Summer_Off_Prices_Weekday
: `${Summer_Off_Prices_Weekday} / ${Non_Summer_Off_Prices_Weekday}`
}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
流動電價-週六半尖峰單價
<!-- {{ isSummerMonth == "half-summer" ? "(夏月/非夏月)" : "" }} -->
</div>
</template>
{{
isSummerMonth === "summer"
? Summer_HalfPeak_Prices_Saturday
: isSummerMonth === "non-summer"
? Non_Summer_HalfPeak_Prices_Saturday
: `${Summer_HalfPeak_Prices_Saturday} / ${Non_Summer_HalfPeak_Prices_Saturday}`
}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
流動電價-週六離峰單價
<!-- {{ isSummerMonth == "half-summer" ? "(夏月/非夏月)" : "" }} -->
</div>
</template>
{{
isSummerMonth === "summer"
? Summer_Off_Prices_Saturday
: isSummerMonth === "non-summer"
? Non_Summer_Off_Prices_Saturday
: `${Summer_Off_Prices_Saturday} / ${Non_Summer_Off_Prices_Saturday}`
}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
流動電價-週日離峰單價
<!-- {{ isSummerMonth == "half-summer" ? "(夏月/非夏月)" : "" }} -->
</div>
</template>
{{
isSummerMonth === "summer"
? Summer_Off_Prices
: isSummerMonth === "non-summer"
? Non_Summer_Off_Prices
: `${Summer_Off_Prices} / ${Non_Summer_Off_Prices}`
}}
</el-descriptions-item>
</el-descriptions>
</el-col>
<el-col :span="5">
<el-descriptions class="margin-top" title="總計" :column="1" border>
<el-descriptions-item>
<template #label>
<div class="cell-item">基本電費</div>
</template>
{{ totalStandCost.toFixed(2) }}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">流動電費</div>
</template>
{{ totalFlowCost.toFixed(2) }}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">總費用</div>
</template>
{{ totalCost.toFixed(2) }}
</el-descriptions-item>
</el-descriptions>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<table>
<thead>
<tr>
<th colspan="2" class="bg-info">基本資料</th>
<th colspan="3" class="bg-orange">前期比較</th>
<th colspan="4" class="bg-green">用電量(kWh)</th>
<th colspan="4" class="bg-yellow">費用(NTD)</th>
</tr>
<tr>
<th class="bg-info">電表編號</th>
<th class="bg-info">區域/用途</th>
<th class="bg-orange">上月用電量(kWh)</th>
<th class="bg-orange">用電變化量(kWh)</th>
<th class="bg-orange">用電變化率(%)</th>
<th class="bg-green">總用電量</th>
<th class="bg-green">尖峰用電</th>
<th class="bg-green">半尖峰用電</th>
<th class="bg-green">離峰用電</th>
<th class="bg-yellow">尖峰費用</th>
<th class="bg-yellow">半尖峰費用</th>
<th class="bg-yellow">離峰費用</th>
<th class="bg-yellow">小計</th>
</tr>
</thead>
<tbody>
<tr
v-for="meterData in formattedElecCostSummary"
:key="meterData.name"
>
<td>{{ meterData.name }}</td>
<td>{{ meterData.area }}</td>
<td>{{ meterData.lastMonthUsage.toFixed(2) }}</td>
<td>{{ meterData.usageChange.toFixed(2) }}</td>
<td>{{ meterData.usageChangeRate.toFixed(2) }}</td>
<td>{{ meterData.totalUsage.toFixed(2) }}</td>
<td>{{ meterData.peakUsage.toFixed(2) }}</td>
<td>{{ meterData.halfPeakUsage.toFixed(2) }}</td>
<td>{{ meterData.offPeakUsage.toFixed(2) }}</td>
<td>{{ meterData.peakCost.toFixed(2) }}</td>
<td>{{ meterData.halfPeakCost.toFixed(2) }}</td>
<td>{{ meterData.offPeakCost.toFixed(2) }}</td>
<td>{{ meterData.totalCost.toFixed(2) }}</td>
</tr>
</tbody>
</table>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-card style="border-radius: 8px; height: 100%">
<h3 class="">各電表用電量比較(kWh)</h3>
<EnergyBar :chartData="elecUsageData" />
</el-card>
</el-col>
<el-col :span="12">
<el-card style="border-radius: 8px; height: 100%">
<h3 class="">各電表總費用佔比</h3>
<EnergyPie :chartData="elecCostData" />
</el-card>
</el-col>
<el-col :span="24">
<p style="margin: 0; padding-top: 15px; opacity: 0.8">
本系統所提供之時間電價計算結果係以未超過契約容量為前提所進行之估算僅供用電分析與管理參考之用
</p>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import { defineProps, computed } from "vue";
import EnergyPie from "../components/EnergyPie.vue";
import EnergyBar from "../components/EnergyBar.vue";
import useElecPriceStore from "../stores/useElecPriceStore";
import useElecReportStore from "../stores/useElecReportStore";
import useElecDemandStore from "../stores/useElecDemandStore";
import getRandomColor from "../utils/getRandomColor";
import dayjs from "dayjs";
const props = defineProps({
form: {
type: Object,
},
});
const storeElecPrice = useElecPriceStore();
const storeElecReport = useElecReportStore();
const storeDemand = useElecDemandStore();
const elecPrices = storeElecPrice.elecData;
const elecDemand = storeDemand.elecData;
const loading = computed(() => {
const summaryThisMonth = storeElecReport.elecCostSummary.thisMonth;
if (
!summaryThisMonth ||
Object.keys(summaryThisMonth).length === 0 ||
Object.values(summaryThisMonth).every((value) => value === undefined)
) {
return true;
}
return false;
});
const isSummerMonth = computed(() => {
const date = dayjs(props.form?.date);
const month = date.month() + 1; // 代表一月到十二月
if (month > 5 && month < 10) {
return "summer";
} else if (month === 5 || month === 10) {
return "half-summer";
} else {
return "non-summer";
}
});
const priceTitle = computed(() => {
if (isSummerMonth.value === "summer") {
return "單價(NTD/kWh)-夏月";
} else if (isSummerMonth.value === "non-summer") {
return "單價(NTD/kWh)-非夏月";
} else {
return "單價(NTD/kWh)-夏月/非夏月";
}
});
const formattedElecCostSummary = computed(() => {
const summaryThisMonth = storeElecReport.elecCostSummary.thisMonth;
const summaryLastMonth = storeElecReport.elecCostSummary.lastMonth;
if (!summaryThisMonth) {
return [];
}
return Object.keys(summaryThisMonth).map((key) => {
const meterDataThisMonth = summaryThisMonth[key];
const meterDataLastMonth = summaryLastMonth?.[key]; // 使用可选链
const totalUsageThisMonth = meterDataThisMonth?.totalEleCost || 0;
const totalUsageLastMonth = meterDataLastMonth?.totalEleCost || 0;
const usageChange = totalUsageThisMonth - totalUsageLastMonth;
const usageChangeRate =
totalUsageLastMonth !== 0 ? (usageChange / totalUsageLastMonth) * 100 : 0; // 避免除以 0
return {
name: meterDataThisMonth?.name,
area: meterDataThisMonth?.area,
lastMonthUsage: totalUsageLastMonth,
usageChange: usageChange,
usageChangeRate: usageChangeRate,
totalUsage: totalUsageThisMonth,
peakUsage: meterDataThisMonth?.total_peak || 0,
halfPeakUsage: meterDataThisMonth?.total_half || 0,
offPeakUsage: meterDataThisMonth?.total_Off || 0,
peakCost: meterDataThisMonth?.total_peakCost || 0,
halfPeakCost: meterDataThisMonth?.total_halfCost || 0,
offPeakCost: meterDataThisMonth?.total_OffCost || 0,
totalCost: meterDataThisMonth?.totalFlowCost || 0,
};
});
});
// 基本電費
const totalStandCost = computed(() => {
if (!storeElecReport.elecCostSummary.thisMonth) {
return 0;
}
const elecCostSummaryArray = Object.values(
storeElecReport.elecCostSummary.thisMonth
);
if (elecCostSummaryArray.length === 0) {
return 0;
}
return elecCostSummaryArray[0]?.standCost || 0;
});
const totalFlowCost = computed(() => {
if (!storeElecReport.elecCostSummary.thisMonth) {
return 0;
}
let total = 0;
Object.keys(storeElecReport.elecCostSummary.thisMonth).forEach((key) => {
// @ts-ignore
total += storeElecReport.elecCostSummary.thisMonth[key]?.totalFlowCost || 0;
});
return total;
});
const totalCost = computed(() => {
return totalStandCost.value + totalFlowCost.value;
});
const Three_Phase =
elecPrices.find((item: any) => item.displayName === "基本按戶三相")?.out || 0;
// 夏月
const Regular_Contract_Summer =
elecPrices.find((item: any) => item.displayName === "基本經常夏月")?.out || 0;
const Summer_Peak_Prices =
elecPrices.find((item: any) => item.displayName === "流動平日尖峰夏月")
?.out || 0;
const Summer_HalfPeak_Prices_Weekday =
elecPrices.find((item: any) => item.displayName === "流動平日半尖峰夏月")
?.out || 0;
const Summer_Off_Prices_Weekday =
elecPrices.find((item: any) => item.displayName === "流動平日離峰夏月")
?.out || 0;
const Summer_HalfPeak_Prices_Saturday =
elecPrices.find((item: any) => item.displayName === "流動週六半尖峰夏月")
?.out || 0;
const Summer_Off_Prices_Saturday =
elecPrices.find((item: any) => item.displayName === "流動週六離峰夏月")
?.out || 0;
const Summer_Off_Prices =
elecPrices.find((item: any) => item.displayName === "流動週日離峰夏月")
?.out || 0;
// 非夏月
const Regular_Contract_Non_Summer =
elecPrices.find((item: any) => item.displayName === "基本經常非夏月")?.out ||
0;
const Non_Summer_HalfPeak_Prices_Weekday =
elecPrices.find((item: any) => item.displayName === "流動平日半尖峰非夏月")
?.out || 0;
const Non_Summer_Off_Prices_Weekday =
elecPrices.find((item: any) => item.displayName === "流動平日離峰非夏月")
?.out || 0;
const Non_Summer_HalfPeak_Prices_Saturday =
elecPrices.find((item: any) => item.displayName === "流動週六半尖峰非夏月")
?.out || 0;
const Non_Summer_Off_Prices_Saturday =
elecPrices.find((item: any) => item.displayName === "流動週六離峰非夏月")
?.out || 0;
const Non_Summer_Off_Prices =
elecPrices.find((item: any) => item.displayName === "流動週日離峰非夏月")
?.out || 0;
const ContractUse =
elecDemand.find((item: any) => item.name === "Engel")?.out || 0;
const elecUsageData = computed(() => {
const summaryThisMonth = storeElecReport.elecCostSummary.thisMonth;
if (
!summaryThisMonth ||
Object.keys(summaryThisMonth).length === 0 ||
Object.values(summaryThisMonth).every((value) => value === undefined)
) {
return {
categories: [],
series: [],
};
}
const categories = Object.keys(summaryThisMonth);
const peakData = categories.map(
(key) => summaryThisMonth[key]?.total_peak || 0
);
const halfPeakData = categories.map(
(key) => summaryThisMonth[key]?.total_half || 0
);
const offPeakData = categories.map(
(key) => summaryThisMonth[key]?.total_Off || 0
);
return {
categories: categories.map((key) => summaryThisMonth[key]?.name || key),
series: [
{
name: "尖峰用電",
type: "bar",
data: peakData,
itemStyle: { color: "#5470c6" },
stack: "total",
},
{
name: "半尖峰用電",
type: "bar",
data: halfPeakData,
itemStyle: { color: "#91cc75" },
stack: "total",
},
{
name: "離峰用電",
type: "bar",
data: offPeakData,
itemStyle: { color: "#fac858" },
stack: "total",
},
],
};
});
const elecCostData = computed(() => {
const summaryThisMonth = storeElecReport.elecCostSummary.thisMonth;
if (
!summaryThisMonth ||
Object.keys(summaryThisMonth).length === 0 ||
Object.values(summaryThisMonth).every((value) => value === undefined)
) {
return { series: [] };
}
getRandomColor.resetIndex();
const series = Object.keys(summaryThisMonth).map((key) => {
const meterData = summaryThisMonth[key];
return {
name: meterData?.name || key,
value: meterData?.totalFlowCost.toFixed(2) || 0,
itemStyle: { color: getRandomColor() },
};
});
return { series };
});
</script>
<style scoped>
.el-row {
padding-top: 20px;
padding-right: 20px;
padding-left: 20px;
}
h3 {
margin: 0;
font-weight: 700;
font-size: 15px;
color: #141414;
}
th,
td {
border: 1px solid #ebeef5;
text-align: center;
padding: 8px 11px;
background: #fff;
color: #303133;
font-size: 12px;
text-wrap: nowrap;
}
.bg-info {
background: #add8e6;
}
.bg-orange {
background: #ffdab9;
}
.bg-green {
background: #90ee90;
}
.bg-yellow {
background: #ffd700;
}
</style>