diff --git a/components.d.ts b/components.d.ts
index 99c46df..2c07aec 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -13,8 +13,12 @@ declare module 'vue' {
ElCard: typeof import('element-plus/es')['ElCard']
ElCol: typeof import('element-plus/es')['ElCol']
ElContainer: typeof import('element-plus/es')['ElContainer']
+ ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
+ ElDialog: typeof import('element-plus/es')['ElDialog']
+ ElForm: typeof import('element-plus/es')['ElForm']
+ ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElHeader: typeof import('element-plus/es')['ElHeader']
ElInput: typeof import('element-plus/es')['ElInput']
ElMain: typeof import('element-plus/es')['ElMain']
@@ -24,6 +28,7 @@ declare module 'vue' {
ElStatistic: typeof import('element-plus/es')['ElStatistic']
EnergyBar: typeof import('./src/components/EnergyBar.vue')['default']
EnergyLine: typeof import('./src/components/EnergyLine.vue')['default']
+ EnergyModal: typeof import('./src/components/EnergyModal.vue')['default']
EnergyPie: typeof import('./src/components/EnergyPie.vue')['default']
EnergySankey: typeof import('./src/components/EnergySankey.vue')['default']
Navbar: typeof import('./src/components/Navbar.vue')['default']
diff --git a/src/components/EnergyModal.vue b/src/components/EnergyModal.vue
new file mode 100644
index 0000000..9fdb692
--- /dev/null
+++ b/src/components/EnergyModal.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/EnergyPie.vue b/src/components/EnergyPie.vue
index a854b16..33981fe 100644
--- a/src/components/EnergyPie.vue
+++ b/src/components/EnergyPie.vue
@@ -1,30 +1,18 @@
diff --git a/src/stores/useElecPriceStore.ts b/src/stores/useElecPriceStore.ts
index a362c19..8a0736d 100644
--- a/src/stores/useElecPriceStore.ts
+++ b/src/stores/useElecPriceStore.ts
@@ -1,6 +1,7 @@
import { ref } from "vue";
import { defineStore } from "pinia";
import type { NiagaraElecData } from "../utils/types";
+import axios from "axios";
const useElecPriceStore = defineStore("elecPriceData", () => {
const elecData = ref([]);
@@ -101,6 +102,30 @@ const useElecPriceStore = defineStore("elecPriceData", () => {
});
};
+ const updatePrice = async (slotPath: string, out: number) => {
+ const domain = window.location.origin;
+ try {
+ console.log("updatePrice",`${domain}/obix/config/${slotPath}/in2/value`)
+ const res = await axios.put(
+ `${domain}/obix/config/${slotPath}/in2/value`,
+ ` `,
+ {
+ headers: { "Content-Type": "text/xml" },
+ }
+ );
+ if (res.status === 200) {
+ console.log(`成功更新 ${slotPath} 為 ${out}`);
+ return true;
+ } else {
+ console.error(`更新 ${slotPath} 失敗,狀態碼: ${res.status}`);
+ return false;
+ }
+ } catch (error) {
+ console.error(`更新 ${slotPath} 出錯:`, error);
+ return false;
+ }
+ };
+
const clearAllSubscriber = () => {
subscribers.value.forEach((subscriber) => {
subscriber.detach("changed");
@@ -112,6 +137,7 @@ const useElecPriceStore = defineStore("elecPriceData", () => {
return {
getElecDataFromBaja,
+ updatePrice,
clearAllSubscriber,
elecData,
};
diff --git a/src/stores/useElecReportStore.ts b/src/stores/useElecReportStore.ts
new file mode 100644
index 0000000..eb0224d
--- /dev/null
+++ b/src/stores/useElecReportStore.ts
@@ -0,0 +1,202 @@
+import { ref } from "vue";
+import { defineStore } from "pinia";
+import dayjs from "dayjs";
+import type { ElecCostSummaryMap } from "../utils/types";
+import { CalcuEleCost, CalcuEleStandCost } from "../utils/CalcuEleCost";
+
+
+
+const useElecReportStore = defineStore("elecReportData", () => {
+ const elecData = ref([]);
+ // @ts-ignore
+ let timerId = null;
+
+ // 初始化為空物件,並定義類型
+ const elecCostSummary = ref({
+ thisMonth: {},
+ lastMonth: {},
+ });
+
+ // 儲存每個電表的 dataMap
+ const elecDataMaps = ref<{
+ [id: string]: {
+ thisMonth: Map;
+ lastMonth: Map;
+ };
+ }>({});
+
+ const startTime = ref("");
+ const endTime = ref("");
+
+ // get data from baja
+ const getElecDataFromBaja = () => {
+ // @ts-ignore
+ window.require &&
+ // @ts-ignore
+ window.requirejs(["baja!"], (baja: any) => {
+ console.log("進入 bajaSubscriber 準備執行用電度數 BQL 訂閱");
+
+ // 定義BQL 查詢
+ const Total_kwhBql = `local:|foxs:4918|station:|neql:EMS:SubSys_kwh|bql:select slotPath,parent.displayName,displayName,NumericInterval.historyConfig.id,out`;
+
+ // 執行各電表的 BQL 查詢
+ fetchElecData(baja, Total_kwhBql);
+ });
+ };
+
+ const fetchElecData = (baja: any, bql: string) => {
+ let eleclist: any[] = [];
+ baja.Ord.make(bql).get({
+ cursor: {
+ before: () => {},
+ each: (record: any) => {
+ eleclist.push({
+ slotPath: record.get("slotPath"),
+ displayName: record.get("parent$2edisplayName"),
+ id: record.get("NumericInterval$2ehistoryConfig$2eid").$cEncStr,
+ area: record.get("out")?.get("value") ?? "",
+ });
+ },
+ after: () => {
+ const validElecList = eleclist.filter(
+ (item) => item.id !== undefined
+ );
+ const menoElecList = eleclist.filter((item) => item.id == undefined);
+ const displayNameToAreaMap = new Map();
+ menoElecList.forEach((item) => {
+ displayNameToAreaMap.set(item.displayName, item.area);
+ });
+ validElecList.forEach((item) => {
+ const area = displayNameToAreaMap.get(item.displayName);
+ if (area) {
+ item.area = area; // 將 area 賦值給 validElecList 中的 item
+ }
+ });
+ elecData.value = [];
+ elecData.value.push(...validElecList);
+ validElecList.forEach((item) => {
+ const id = item.id;
+ elecDataMaps.value[id] = {
+ thisMonth: new Map(),
+ lastMonth: new Map(),
+ };
+ // 初始化每个 slotPath 的值为 undefined 或 null
+ elecCostSummary.value.thisMonth[id] = undefined;
+ elecCostSummary.value.lastMonth[id] = undefined;
+ getTimeToHistory(item, 'thisMonth'); // 獲取本月
+ getTimeToHistory(item, 'lastMonth'); // 獲取上個月
+ });
+ },
+ },
+ });
+ };
+
+ const getTimeToHistory = (item: any, month: 'thisMonth' | 'lastMonth') => {
+ const id = item.id;
+ let startTimeValue = startTime.value;
+ let endTimeValue = endTime.value;
+
+ if (month === 'lastMonth') {
+ startTimeValue = dayjs(startTime.value).subtract(1, 'month').startOf('month').format("YYYY-MM-DDTHH:mm:ss.000+08:00");
+ endTimeValue = dayjs(endTime.value).subtract(1, 'month').endOf('month').format("YYYY-MM-DDTHH:mm:ss.000+08:00");
+ }
+
+ const ordString = `local:|foxs:4918|history:${id}?period=timerange;start=${startTimeValue};end=${endTimeValue}|bql:history:HistoryRollup.rollup(baja:RelTime '3600000')`; //每小时一个rollup
+ console.log(ordString);
+ // @ts-ignore
+ window.require &&
+ // @ts-ignore
+ window.requirejs(["baja!"], (baja: any) => {
+ // 使用對應電表的 dataMap
+ const dataMap = elecDataMaps.value[id][month];
+ if (!dataMap) {
+ console.warn(`未找到電表 ${id} (${month}) 的 dataMap`);
+ return;
+ }
+ let lastTimestamp: string | null = null;
+ let lastValue: number | null = null;
+ baja.Ord.make(ordString).get({
+ cursor: {
+ before: () => {
+ console.log(`開始訂閱 ${id} 的歷史資料`);
+ },
+ each: (record: any) => {
+ const currentValue = record.get("min");
+ const timestamp = record.get("timestamp").$cEncStr;
+ if (
+ currentValue !== null &&
+ currentValue !== 0 &&
+ timestamp !== null
+ ) {
+ if (
+ lastTimestamp !== null &&
+ lastValue !== null &&
+ lastValue !== 0
+ ) {
+ const diff = currentValue - lastValue;
+ dataMap.set(lastTimestamp, diff);
+ }
+ lastValue = currentValue;
+ lastTimestamp = timestamp;
+ }
+ },
+ after: () => {
+ const elecCost = CalcuEleCost(dataMap);
+ const eleceStandCost = CalcuEleStandCost(dataMap);
+ console.log(`⏱️ 電表 ${id} 每小時差值 map:`, dataMap);
+ if (item.slotPath) {
+ // 确保 slotPath 存在
+ elecCostSummary.value[month][id] = {
+ ...elecCost,
+ standCost: eleceStandCost.StandCost,
+ name: item.displayName,
+ area: item.area,
+ };
+ console.log(
+ `電表 ${item.displayName} 的電費計算結果 (${month}):`,
+ elecCostSummary.value[month][id]
+ );
+ } else {
+ console.warn(
+ `電表 ${id} 的 slotPath 為空,無法儲存電費計算結果 (${month})`
+ );
+ }
+ },
+ limit: -1,
+ offset: 0,
+ },
+ });
+ });
+ };
+
+
+ // 定時更新資料的函數
+ const updateHistoryData = () => {
+ console.log("重新獲取歷史資料");
+ if (elecData.value && elecData.value.length > 0) {
+ elecCostSummary.value.thisMonth = {};
+ elecCostSummary.value.lastMonth = {};
+
+ elecData.value.forEach((item) => {
+ const id = item.id;
+ elecDataMaps.value[id] = {
+ thisMonth: new Map(),
+ lastMonth: new Map(),
+ };
+ getTimeToHistory(item, 'thisMonth');
+ getTimeToHistory(item, 'lastMonth');
+ });
+ }
+ };
+
+ return {
+ getElecDataFromBaja,
+ elecData,
+ elecCostSummary,
+ startTime,
+ endTime,
+ updateHistoryData,
+ };
+});
+
+export default useElecReportStore;
diff --git a/src/stores/useElecTotalMeterStore.ts b/src/stores/useElecTotalMeterStore.ts
index 5c20d7a..3624ef4 100644
--- a/src/stores/useElecTotalMeterStore.ts
+++ b/src/stores/useElecTotalMeterStore.ts
@@ -1,14 +1,19 @@
import { ref } from "vue";
import { defineStore } from "pinia";
import dayjs from "dayjs";
-import type { NiagaraElecData, ElecCostSummary } from "../utils/types";
-import { CalcuEleCost } from "../utils/CalcuEleCost";
+import type {
+ NiagaraElecData,
+ ElecCostSummary,
+ ElecStandCostSummary,
+} from "../utils/types";
+import { CalcuEleCost, CalcuEleStandCost } from "../utils/CalcuEleCost";
const useElecStore = defineStore("elecData", () => {
const elecData = ref([]);
// @ts-ignore
let timerId = null;
- const elecCostSummary = ref(null);
+ const elecFlowCostSummary = ref(null);
+ const elecStandCostSummary = ref(null);
// get data from baja
const getElecDataFromBaja = () => {
@@ -78,18 +83,27 @@ const useElecStore = defineStore("elecData", () => {
each: (record: any) => {
const currentValue = record.get("min");
const timestamp = record.get("timestamp").$cEncStr;
- if (currentValue !== null && currentValue !== 0 && timestamp !== null) {
- if (lastTimestamp !== null && lastValue !== null && lastValue !== 0) {
+ if (
+ currentValue !== null &&
+ currentValue !== 0 &&
+ timestamp !== null
+ ) {
+ if (
+ lastTimestamp !== null &&
+ lastValue !== null &&
+ lastValue !== 0
+ ) {
const diff = currentValue - lastValue;
dataMap.set(lastTimestamp, diff);
}
lastValue = currentValue;
lastTimestamp = timestamp;
- }
+ }
},
after: () => {
console.log("⏱️ 每小時差值 map:", dataMap);
- elecCostSummary.value = CalcuEleCost(dataMap);
+ elecFlowCostSummary.value = CalcuEleCost(dataMap);
+ elecStandCostSummary.value = CalcuEleStandCost(dataMap);
},
limit: -1,
offset: 0,
@@ -129,7 +143,8 @@ const useElecStore = defineStore("elecData", () => {
startTimer,
stopTimer,
elecData,
- elecCostSummary,
+ elecFlowCostSummary,
+ elecStandCostSummary,
};
});
diff --git a/src/utils/CalcuEleCost.ts b/src/utils/CalcuEleCost.ts
index 70addc5..b16baa0 100644
--- a/src/utils/CalcuEleCost.ts
+++ b/src/utils/CalcuEleCost.ts
@@ -1,10 +1,18 @@
-import type { DailyResult, ElecCostSummary, DailyEntry } from "../utils/types";
+import type {
+ DailyResult,
+ ElecCostSummary,
+ DailyEntry,
+ StandEntry,
+ ElecStandCostSummary,
+ StandResult,
+} from "../utils/types";
import useElecPriceStore from "../stores/useElecPriceStore";
-const storeElecPrice = useElecPriceStore();
+import useElecDemandStore from "../stores/useElecDemandStore";
-export const CalcuEleCost = (
- input: Map
-): ElecCostSummary => {
+const storeElecPrice = useElecPriceStore();
+const ContractUseValue = useElecDemandStore();
+
+export const CalcuEleCost = (input: Map): ElecCostSummary => {
const dailyData: Map = new Map();
let totalFlowCost = 0; // 總電價
let totalEleCost = 0; //總用電
@@ -17,13 +25,27 @@ export const CalcuEleCost = (
const dailyResults: DailyResult[] = [];
const elecPrices = storeElecPrice.elecData;
- const Summer_Off_Prices = elecPrices.find((item:any) => item.displayName === "流動週日離峰夏月")?.out || 0;
- const Summer_HalfPeak_Prices_Saturday = elecPrices.find((item:any) => item.displayName === "流動週六半尖峰夏月")?.out || 0;
- const Summer_HalfPeak_Prices_Weekday = elecPrices.find((item:any) => item.displayName === "流動平日半尖峰夏月")?.out || 0;
- const Summer_Peak_Prices = elecPrices.find((item:any) => item.displayName === "流動平日尖峰夏月")?.out || 0;
- const Non_Summer_Off_Prices = 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_HalfPeak_Prices_Weekday = elecPrices.find((item:any) => item.displayName === "流動平日半尖峰非夏月")?.out || 0;
+ const Summer_Off_Prices =
+ elecPrices.find((item: any) => item.displayName === "流動週日離峰夏月")
+ ?.out || 0;
+ const Summer_HalfPeak_Prices_Saturday =
+ elecPrices.find((item: any) => item.displayName === "流動週六半尖峰夏月")
+ ?.out || 0;
+ const Summer_HalfPeak_Prices_Weekday =
+ elecPrices.find((item: any) => item.displayName === "流動平日半尖峰夏月")
+ ?.out || 0;
+ const Summer_Peak_Prices =
+ elecPrices.find((item: any) => item.displayName === "流動平日尖峰夏月")
+ ?.out || 0;
+ const Non_Summer_Off_Prices =
+ 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_HalfPeak_Prices_Weekday =
+ elecPrices.find((item: any) => item.displayName === "流動平日半尖峰非夏月")
+ ?.out || 0;
// 1. 將輸入資料按日期分組
input.forEach((value, key) => {
const dateStr = key.substring(0, 10);
@@ -117,7 +139,6 @@ export const CalcuEleCost = (
dailyEleCost,
dailyFlowCost,
});
-
}
return {
dailyResults,
@@ -131,3 +152,72 @@ export const CalcuEleCost = (
total_peakCost,
};
};
+
+export const CalcuEleStandCost = (
+ input: Map
+): ElecStandCostSummary => {
+ const elecPrices = storeElecPrice.elecData;
+ const ContractUseData = ContractUseValue.elecData;
+
+ const Three_Phase =
+ elecPrices.find((item: any) => item.displayName === "基本按戶三相")?.out ||
+ 0;
+ const Summer_Regular_Use =
+ elecPrices.find((item: any) => item.displayName === "基本經常夏月")?.out ||
+ 0;
+ const Non_Summer_Regular_Use =
+ elecPrices.find((item: any) => item.displayName === "基本經常非夏月")
+ ?.out || 0;
+ const ContractUse =
+ ContractUseData.find((item: any) => item.name === "Engel")?.out || 0;
+
+ const monthMap = new Map(); // key: yyyy-MM
+
+ // 將資料依據年月分組
+ input.forEach((value, key) => {
+ const date = new Date(key);
+ const year = date.getFullYear();
+ const month = date.getMonth() + 1;
+ const ymKey = `${year}-${month.toString().padStart(2, "0")}`;
+
+ if (!monthMap.has(ymKey)) {
+ monthMap.set(ymKey, []);
+ }
+ monthMap.get(ymKey)?.push({ time: date, value });
+ });
+
+ const StandResults: StandResult[] = [];
+ let totalStandCost = 0;
+
+ for (const [ym, entries] of monthMap.entries()) {
+ if (!entries || entries.length === 0) continue;
+
+ const sampleDate = entries[0].time;
+ const month = sampleDate.getMonth() + 1;
+ const isSummer = month >= 6 && month <= 9;
+
+ let Phase = Three_Phase;
+ let Contract = isSummer ? Summer_Regular_Use : Non_Summer_Regular_Use;
+
+ const StandCost = Phase + Contract * ContractUse;
+
+ StandResults.push({
+ Phase,
+ Contract,
+ ContractUse,
+ StandCost,
+ });
+
+ totalStandCost += StandCost;
+ console.log(`=== ${ym} ===`);
+ console.log(` 按戶類別: ${Phase.toFixed(2)}`);
+ console.log(` 契約類型: $${Contract.toFixed(2)}`);
+ console.log(` 契約度數: $${ContractUse.toFixed(2)}`);
+ console.log(` 基本電價: $${StandCost.toFixed(2)}`);
+ }
+
+ return {
+ StandResults,
+ StandCost: totalStandCost,
+ };
+};
diff --git a/src/utils/getRandomColor.ts b/src/utils/getRandomColor.ts
new file mode 100644
index 0000000..feeec0f
--- /dev/null
+++ b/src/utils/getRandomColor.ts
@@ -0,0 +1,21 @@
+const predefinedColors = ["#5470c6", "#91cc75", "#fac858"];
+let colorIndex = 0;
+
+const getRandomColor = () => {
+ if (colorIndex < predefinedColors.length) {
+ return predefinedColors[colorIndex++];
+ } else {
+ const letters = "0123456789ABCDEF";
+ let color = "#";
+ for (let i = 0; i < 6; i++) {
+ color += letters[Math.floor(Math.random() * 16)];
+ }
+ return color;
+ }
+};
+
+getRandomColor.resetIndex = () => {
+ colorIndex = 0;
+};
+
+export default getRandomColor;
diff --git a/src/utils/types.ts b/src/utils/types.ts
index 3d62def..4f5f714 100644
--- a/src/utils/types.ts
+++ b/src/utils/types.ts
@@ -3,14 +3,14 @@ export interface NiagaraElecData {
slotPath: string;
displayName: string;
id: string;
- out: number;
+ out: number;
}
export interface NiagaraElecDemandData {
slotPath: string;
displayName: string;
name: string;
- out: number;
+ out: number;
}
export interface DailyResult {
@@ -18,9 +18,9 @@ export interface DailyResult {
off: number;
half: number;
peak: number;
- offcost:number;
- halfcost:number;
- peakcost:number;
+ offcost: number;
+ halfcost: number;
+ peakcost: number;
dailyEleCost: number;
dailyFlowCost: number;
}
@@ -35,9 +35,38 @@ export interface ElecCostSummary {
total_OffCost: number;
total_halfCost: number;
total_peakCost: number;
+ standCost?:number;
+ name?: string;
+ area?: string;
+}
+
+export interface ElecCostSummaryMap {
+ thisMonth: {
+ [slotPath: string]: ElecCostSummary | null | undefined;
+ };
+ lastMonth: {
+ [slotPath: string]: ElecCostSummary | null | undefined;
+ };
}
export interface DailyEntry {
time: Date;
value: number;
+}
+
+export interface StandEntry {
+ time: Date;
+ value: number;
+}
+
+export interface StandResult {
+ Phase : number ;
+ Contract : number ;
+ ContractUse : number;
+ StandCost :number ;
+}
+
+export interface ElecStandCostSummary {
+ StandResults: StandResult[];
+ StandCost :number ;
}
\ No newline at end of file
diff --git a/src/views/EnergyChart.vue b/src/views/EnergyChart.vue
index 63f4c36..0866531 100644
--- a/src/views/EnergyChart.vue
+++ b/src/views/EnergyChart.vue
@@ -73,11 +73,19 @@ import useElecTotalMeterStore from "../stores/useElecTotalMeterStore";
import dayjs from "dayjs";
const storeElecTotal = useElecTotalMeterStore();
+const billingDateRange = ref("");
watch(
- () => storeElecTotal.elecCostSummary,
+ () => storeElecTotal.elecFlowCostSummary,
(newElecData) => {
- console.log("elecCostSummary", newElecData);
+ console.log("elecFlowCostSummary", newElecData);
+ },
+ { deep: true }
+);
+watch(
+ () => storeElecTotal.elecStandCostSummary,
+ (newElecData) => {
+ console.log("elecStandCostSummary", newElecData);
},
{ deep: true }
);
@@ -85,6 +93,11 @@ watch(
onMounted(async () => {
await storeElecTotal.getElecDataFromBaja();
storeElecTotal.startTimer();
+
+ // 區間計費時間區段
+ billingDateRange.value = `${dayjs()
+ .startOf("month")
+ .format("YYYY/MM/DD")} - ${dayjs().format("YYYY/MM/DD")}`;
});
onUnmounted(() => {
@@ -97,8 +110,8 @@ const statisticData = computed(() => {
let intervalFlowCost = 0;
let intervalEleCost = 0;
- if (storeElecTotal.elecCostSummary?.dailyResults) {
- storeElecTotal.elecCostSummary.dailyResults.forEach((dailyResult) => {
+ if (storeElecTotal.elecFlowCostSummary?.dailyResults) {
+ storeElecTotal.elecFlowCostSummary.dailyResults.forEach((dailyResult) => {
if (dailyResult.dateStr.startsWith(currentMonth)) {
intervalFlowCost += dailyResult.dailyFlowCost;
intervalEleCost += dailyResult.dailyEleCost;
@@ -109,13 +122,13 @@ const statisticData = computed(() => {
return [
{
title: "今年電費累計",
- value: storeElecTotal.elecCostSummary?.totalFlowCost || 0,
+ value: storeElecTotal.elecFlowCostSummary?.totalFlowCost || 0,
unit: "元",
},
{ title: "區間電費", value: intervalFlowCost, unit: "元" },
{
title: "今年碳排當量累計",
- value: storeElecTotal.elecCostSummary?.totalEleCost * 0.424,
+ value: storeElecTotal.elecFlowCostSummary?.totalEleCost * 0.424,
unit: "公斤 CO2e/度",
},
{
@@ -125,7 +138,7 @@ const statisticData = computed(() => {
},
{
title: "今年用電度數",
- value: storeElecTotal.elecCostSummary?.totalEleCost || 0,
+ value: storeElecTotal.elecFlowCostSummary?.totalEleCost || 0,
unit: "kWh",
},
{ title: "區間用電度數", value: intervalEleCost, unit: "kWh" },
@@ -162,22 +175,24 @@ function groupByMonth(dailyResults) {
// 每月用電分析
const monthlyElectricityData = computed(() => {
- if (!storeElecTotal.elecCostSummary?.dailyResults) {
+ if (!storeElecTotal.elecFlowCostSummary?.dailyResults) {
return { categories: [], series: [] };
}
- const groupedData = groupByMonth(storeElecTotal.elecCostSummary.dailyResults);
+ const groupedData = groupByMonth(
+ storeElecTotal.elecFlowCostSummary.dailyResults
+ );
const categories = Object.keys(groupedData);
const sortedCategories = _.sortBy(categories, (month) =>
dayjs().month(month).valueOf()
);
- const baseElecData = sortedCategories.map((month) => groupedData[month].offcost);
+ const baseElecData = storeElecTotal.elecStandCostSummary.StandCost;
const flowElecData = sortedCategories.map(
(month) => groupedData[month].totalCost
);
- const totalElecData = sortedCategories.map((month, index) => {
- return (baseElecData[index] || 0) + (flowElecData[index] || 0);
+ const totalElecData = sortedCategories.map((month, index) => {
+ return baseElecData + (flowElecData[index] || 0);
});
return {
@@ -186,7 +201,7 @@ const monthlyElectricityData = computed(() => {
{
name: "基本電費",
type: "bar",
- data: baseElecData,
+ data: Array(sortedCategories.length).fill(baseElecData),
},
{
name: "流動電費",
@@ -194,7 +209,7 @@ const monthlyElectricityData = computed(() => {
data: flowElecData,
},
{
- name: "總電量",
+ name: "總電費",
type: "bar",
data: totalElecData,
},
@@ -204,11 +219,13 @@ const monthlyElectricityData = computed(() => {
// 每月碳排當量
const monthlyCarbonData = computed(() => {
- if (!storeElecTotal.elecCostSummary?.dailyResults) {
+ if (!storeElecTotal.elecFlowCostSummary?.dailyResults) {
return { categories: [], series: [] };
}
- const groupedData = groupByMonth(storeElecTotal.elecCostSummary.dailyResults);
+ const groupedData = groupByMonth(
+ storeElecTotal.elecFlowCostSummary.dailyResults
+ );
const categories = Object.keys(groupedData);
const sortedCategories = _.sortBy(categories, (month) =>
dayjs().month(month).valueOf()
@@ -232,76 +249,82 @@ const monthlyCarbonData = computed(() => {
// 每月計費度數 (kWh)
const monthlyBillingData = computed(() => {
- if (!storeElecTotal.elecCostSummary?.dailyResults) {
+ if (!storeElecTotal.elecFlowCostSummary?.dailyResults) {
return { categories: [], series: [] };
}
- const billingData = groupByMonth(storeElecTotal.elecCostSummary.dailyResults);
+ const billingData = groupByMonth(
+ storeElecTotal.elecFlowCostSummary.dailyResults
+ );
const categories = Object.keys(billingData);
- const sortedCategories = _.sortBy(categories, month => dayjs().month(month).valueOf());
+ const sortedCategories = _.sortBy(categories, (month) =>
+ dayjs().month(month).valueOf()
+ );
- const peakData = sortedCategories.map(date => billingData[date].peak);
- const halfData = sortedCategories.map(date => billingData[date].half);
- const offData = sortedCategories.map(date => billingData[date].off);
+ const peakData = sortedCategories.map((date) => billingData[date].peak);
+ const halfData = sortedCategories.map((date) => billingData[date].half);
+ const offData = sortedCategories.map((date) => billingData[date].off);
return {
categories: sortedCategories,
series: [
{ name: "尖峰", type: "bar", data: peakData },
{ name: "半尖峰", type: "bar", data: halfData },
- { name: "離峰", type: "bar", data: offData }
- ]
+ { name: "離峰", type: "bar", data: offData },
+ ],
};
});
-// 區間計費度數
-const billingDateRange = computed(() => {
- const startOfMonth = dayjs().startOf('month').format('YYYY-MM-DD');
- const today = dayjs().format('YYYY-MM-DD');
- return `${startOfMonth} - ${today}`;
-});
-
const areaBillingData = computed(() => {
- if (!storeElecTotal.elecCostSummary?.dailyResults) {
+ if (!storeElecTotal.elecFlowCostSummary?.dailyResults) {
return { categories: [], series: [] };
}
const today = dayjs();
- const currentMonth = today.format('YYYY-MM');
+ const currentMonth = today.format("YYYY-MM");
const startDate = dayjs(`${currentMonth}-01`); // Get the first day of the current month
const endDate = today;
// Filter daily results within the specified date range
- const areaResults = storeElecTotal.elecCostSummary.dailyResults.filter(result => {
- const resultDate = dayjs(result.dateStr);
- return resultDate.isSame(startDate, 'day') || (resultDate.isAfter(startDate, 'day') && resultDate.isBefore(endDate, 'day')) || resultDate.isSame(endDate, 'day');
- });
+ const areaResults = storeElecTotal.elecFlowCostSummary.dailyResults.filter(
+ (result) => {
+ const resultDate = dayjs(result.dateStr);
+ return (
+ resultDate.isSame(startDate, "day") ||
+ (resultDate.isAfter(startDate, "day") &&
+ resultDate.isBefore(endDate, "day")) ||
+ resultDate.isSame(endDate, "day")
+ );
+ }
+ );
// Transform the filtered data for billing
const transformedData = {};
- areaResults.forEach(result => {
- const date = dayjs(result.dateStr).format('MM-DD'); // Format the date for the category
+ areaResults.forEach((result) => {
+ const date = dayjs(result.dateStr).format("MM-DD"); // Format the date for the category
transformedData[date] = {
peak: result.peak,
half: result.half,
- off: result.off
+ off: result.off,
};
});
const categories = Object.keys(transformedData);
- const sortedCategories = _.sortBy(categories, date => dayjs(date, 'MM-DD').valueOf());
+ const sortedCategories = _.sortBy(categories, (date) =>
+ dayjs(date, "MM-DD").valueOf()
+ );
- const peakData = sortedCategories.map(date => transformedData[date].peak);
- const halfData = sortedCategories.map(date => transformedData[date].half);
- const offData = sortedCategories.map(date => transformedData[date].off);
+ const peakData = sortedCategories.map((date) => transformedData[date].peak);
+ const halfData = sortedCategories.map((date) => transformedData[date].half);
+ const offData = sortedCategories.map((date) => transformedData[date].off);
return {
categories: sortedCategories,
series: [
{ name: "尖峰", type: "bar", data: peakData },
{ name: "半尖峰", type: "bar", data: halfData },
- { name: "離峰", type: "bar", data: offData }
- ]
+ { name: "離峰", type: "bar", data: offData },
+ ],
};
});
diff --git a/src/views/EnergyPricing.vue b/src/views/EnergyPricing.vue
index 1381746..f4ffe1d 100644
--- a/src/views/EnergyPricing.vue
+++ b/src/views/EnergyPricing.vue
@@ -311,7 +311,6 @@
import { ref, watch } from "vue";
import { Edit, CircleClose, CircleCheck } from "@element-plus/icons-vue";
import useElecPriceStore from "../stores/useElecPriceStore";
-import axios from "axios";
const storeElecPrice = useElecPriceStore();
@@ -360,30 +359,6 @@ const resetStand3Values = () => {
}
};
-const updatePrice = async (slotPath: string, out: number) => {
- const domain = window.location.origin;
- try {
- console.log("updatePrice",`${domain}/obix/config/${slotPath}/in2/value`)
- const res = await axios.put(
- `${domain}/obix/config/${slotPath}/in2/value`,
- ` `,
- {
- headers: { "Content-Type": "text/xml" },
- }
- );
- if (res.status === 200) {
- console.log(`成功更新 ${slotPath} 為 ${out}`);
- return true;
- } else {
- console.error(`更新 ${slotPath} 失敗,狀態碼: ${res.status}`);
- return false;
- }
- } catch (error) {
- console.error(`更新 ${slotPath} 出錯:`, error);
- return false;
- }
-};
-
const confirmChanges = async () => {
stand3isEditing.value = false;
@@ -419,7 +394,7 @@ const confirmChanges = async () => {
? item.slotPath.slice(6) // 移除 "slot:/"
: item.slotPath; // 如果没有前綴,則保持不變
// 更新 Niagara
- const success = await updatePrice(slotPath, stand3Value.value[i]);
+ const success = await storeElecPrice.updatePrice(slotPath, stand3Value.value[i]);
if (!success) {
failedUpdates.push({
slotPath: item.slotPath,
diff --git a/src/views/MonthlyReport.vue b/src/views/MonthlyReport.vue
index 6eac371..87ec679 100644
--- a/src/views/MonthlyReport.vue
+++ b/src/views/MonthlyReport.vue
@@ -1,17 +1,52 @@
-
+
-
+ 設定報表
+
+ 列印報表
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+