首頁能源圖表串接
This commit is contained in:
parent
be68eb3568
commit
7599b7fa3a
@ -1,67 +1,73 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ref, onMounted, onUnmounted, defineProps, watch } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
|
||||
// 定義用電比較資料
|
||||
const yesterdayTodayData = {
|
||||
categories: [
|
||||
"00:00",
|
||||
"01:00",
|
||||
"02:00",
|
||||
"03:00",
|
||||
"04:00",
|
||||
"05:00",
|
||||
"06:00",
|
||||
"07:00",
|
||||
"08:00",
|
||||
"09:00",
|
||||
"10:00",
|
||||
"11:00",
|
||||
],
|
||||
values: [
|
||||
{
|
||||
name: `2025.01.8 用電量`,
|
||||
value: [8, 8, 8, 8, 8, 15, 25, 65, 75, 60, 70, 65],
|
||||
const props = defineProps({
|
||||
yesterdayTodayData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: `2025.01.7 用電量`,
|
||||
value: [10, 10, 10, 10, 10, 20, 30, 80, 90, 70, 80, 85],
|
||||
weekComparisonData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// 本週與上週用電比較資料
|
||||
const weekComparisonData = {
|
||||
categories: ["Fri", "Sat", "Sun", "Mon", "Tue", "Wed", "Thu"],
|
||||
values: [
|
||||
{
|
||||
name: "本週用電量",
|
||||
value: [850, 200, 350, 850, 950, 950, 900],
|
||||
},
|
||||
{
|
||||
name: "上週用電量",
|
||||
value: [800, 150, 300, 750, 900, 900, 800],
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
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(() => {
|
||||
// 初始化昨天和今天用電比較圖表
|
||||
const yesterdayTodayEChart = echarts.init(yesterdayTodayChart.value);
|
||||
yesterdayTodayEChart = echarts.init(yesterdayTodayChart.value);
|
||||
yesterdayTodayEChart.setOption(
|
||||
generateCylinderChartOption(yesterdayTodayData)
|
||||
generateCylinderChartOption(props.yesterdayTodayData)
|
||||
);
|
||||
|
||||
// 初始化本週和上週用電比較圖表
|
||||
const weekComparisonEChart = echarts.init(weekComparisonChart.value);
|
||||
weekComparisonEChart = echarts.init(weekComparisonChart.value);
|
||||
weekComparisonEChart.setOption(
|
||||
generateCylinderChartOption(weekComparisonData)
|
||||
generateCylinderChartOption(props.weekComparisonData)
|
||||
);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (yesterdayTodayEChart) {
|
||||
yesterdayTodayEChart.dispose();
|
||||
yesterdayTodayEChart = null;
|
||||
}
|
||||
if (weekComparisonEChart) {
|
||||
weekComparisonEChart.dispose();
|
||||
weekComparisonEChart = null;
|
||||
}
|
||||
});
|
||||
|
||||
// 生成圓柱圖表的 option
|
||||
const generateCylinderChartOption = (data) => {
|
||||
const barWidth = 15;
|
||||
@ -101,9 +107,12 @@ const generateCylinderChartOption = (data) => {
|
||||
formatter: function (params) {
|
||||
// 僅顯示 bar 系列的資料
|
||||
const barData = params.filter((item) => item.seriesType === "bar");
|
||||
return barData
|
||||
.map((item) => `${item.seriesName}: ${item.data}`)
|
||||
.join("<br/>");
|
||||
const category = data.categories[params[0].dataIndex];
|
||||
let tooltipContent = `${category}<br/>`;
|
||||
barData.forEach((item) => {
|
||||
tooltipContent += `${item.seriesName}: ${item.data}<br/>`;
|
||||
});
|
||||
return tooltipContent;
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
|
@ -1,35 +1,15 @@
|
||||
<script setup>
|
||||
const mockData = [
|
||||
{
|
||||
value: 305.5,
|
||||
label: "今日用電量",
|
||||
unit: "kWH",
|
||||
icon: "leaf",
|
||||
import { defineProps } from "vue";
|
||||
const props = defineProps({
|
||||
elecData: {
|
||||
type: Object,
|
||||
},
|
||||
{
|
||||
value: 886.75,
|
||||
label: "昨日用電量",
|
||||
unit: "kWH",
|
||||
icon: "leaf",
|
||||
},
|
||||
{
|
||||
value: 7.84,
|
||||
label: "即時功率",
|
||||
unit: "kW",
|
||||
icon: "bolt",
|
||||
},
|
||||
{
|
||||
value: 20.96,
|
||||
label: "容積占比",
|
||||
unit: "%",
|
||||
icon: "charging-station",
|
||||
},
|
||||
];
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-row :gutter="24">
|
||||
<a-col v-for="(item, index) in mockData" :key="index" :span="6" class="mb-5">
|
||||
<a-col v-for="(item, index) in elecData" :key="index" :span="6" class="mb-5">
|
||||
<a-card class="number">
|
||||
<a-row :gutter="24" align="middle" justify="space-between">
|
||||
<a-col :span="18">
|
||||
|
106
src/stores/useElecDemandStore.js
Normal file
106
src/stores/useElecDemandStore.js
Normal file
@ -0,0 +1,106 @@
|
||||
import { ref } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
const useElecDemandStore = defineStore("elecDemand", () => {
|
||||
const elecData = ref([]);
|
||||
const subscribers = ref([]);
|
||||
|
||||
// get data from baja
|
||||
const getElecDemandFromBaja = () => {
|
||||
// @ts-ignore
|
||||
window.require &&
|
||||
// @ts-ignore
|
||||
window.requirejs(["baja!"], (baja) => {
|
||||
let eleclist = [];
|
||||
baja.Ord.make(
|
||||
`local:|foxs:4918|station:|neql:EMS:kw|bql:select slotPath,parent.displayName,name,out`
|
||||
).get({
|
||||
cursor: {
|
||||
before: () => {},
|
||||
each: (record) => {
|
||||
const newItem = {
|
||||
slotPath: record.get("slotPath"),
|
||||
displayName: record.get("parent$2edisplayName"),
|
||||
name: record.get("name"),
|
||||
out: record.get("out")?.get("value") ?? 0,
|
||||
};
|
||||
eleclist.push(newItem);
|
||||
},
|
||||
after: () => {
|
||||
elecData.value = [];
|
||||
elecData.value.push(...eleclist);
|
||||
eleclist.forEach((item, index) => {
|
||||
subscribeToHistory(item, index);
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const subscribeToHistory = (item, index) => {
|
||||
const slotPath = item.slotPath;
|
||||
const ordString = `local:|foxs:4918|station:|${slotPath}`;
|
||||
|
||||
// @ts-ignore
|
||||
window.require &&
|
||||
// @ts-ignore
|
||||
window.requirejs(["baja!"], (baja) => {
|
||||
// 建立訂閱器
|
||||
const subscriber = new baja.Subscriber();
|
||||
|
||||
// 定義 changed 事件的處理函數
|
||||
subscriber.attach("changed", (prop) => {
|
||||
try {
|
||||
if (prop && prop.getName() === "out") {
|
||||
// 取得 out 的新值
|
||||
const match = prop.$display.match(/^(\d+(\.\d+)?)/);
|
||||
const newValue = match ? parseFloat(match[0]) : 0;
|
||||
// 更新 elecData 中對應的 out 值
|
||||
const updatedIndex = elecData.value.findIndex(
|
||||
(data) => data.slotPath === item.slotPath
|
||||
);
|
||||
|
||||
if (updatedIndex !== -1) {
|
||||
elecData.value[updatedIndex].out = Number(newValue);
|
||||
console.log(`Niagara 用電需求 ${item.name} 更新:`, newValue);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`處理 ${item.name || index} 告警變化失敗: ${error.message}`,
|
||||
error
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
baja.Ord.make(ordString)
|
||||
.get({ subscriber })
|
||||
.then(() => {
|
||||
console.log(`Successfuly subscribed to ${item.name}`);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`訂閱 ${item.name || index} 失敗: ${err.message}`);
|
||||
subscriber.detach("changed"); // 移除事件監聽器
|
||||
});
|
||||
subscribers.value.push(subscriber);
|
||||
});
|
||||
};
|
||||
|
||||
const clearAllSubscriber = () => {
|
||||
subscribers.value.forEach((subscriber) => {
|
||||
subscriber.detach("changed");
|
||||
subscriber.unsubscribeAll(); // 移除所有訂閱
|
||||
});
|
||||
subscribers.value = [];
|
||||
console.log("所有訂閱已清除");
|
||||
};
|
||||
|
||||
return {
|
||||
getElecDemandFromBaja,
|
||||
elecData,
|
||||
clearAllSubscriber,
|
||||
};
|
||||
});
|
||||
|
||||
export default useElecDemandStore;
|
194
src/stores/useElecTotalMeterStore.js
Normal file
194
src/stores/useElecTotalMeterStore.js
Normal file
@ -0,0 +1,194 @@
|
||||
import { ref } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import { calcuEleCost } from "@/utils";
|
||||
|
||||
const useElecStore = defineStore("elecData", () => {
|
||||
const elecData = ref([]);
|
||||
const elecPriceData = ref([]);
|
||||
let timerId = null;
|
||||
const todayelecdata = ref(new Map());
|
||||
const yesterdayelecdata = ref(new Map());
|
||||
const elecFlowCostSummary = ref(null);
|
||||
|
||||
const getElecDataFromBaja = () => {
|
||||
window.require &&
|
||||
window.requirejs(["baja!"], (baja) => {
|
||||
console.log("進入 bajaSubscriber 準備執行用電價 BQL 訂閱");
|
||||
|
||||
// 定義BQL 查詢
|
||||
const price_kwhBql = `local:|foxs:4918|station:|neql:EMS:parameter|bql:select slotPath,parent.displayName,displayName,NumericInterval.historyConfig.id,out`;
|
||||
|
||||
// 執行查詢
|
||||
let pricelist = [];
|
||||
baja.Ord.make(price_kwhBql).get({
|
||||
cursor: {
|
||||
before: () => {},
|
||||
each: (record) => {
|
||||
pricelist.push({
|
||||
slotPath: record.get("slotPath"),
|
||||
displayName: record.get("displayName"),
|
||||
id: record.get("NumericInterval$2ehistoryConfig$2eid").$cEncStr,
|
||||
out: record.get("out")?.get("value") ?? 0,
|
||||
});
|
||||
},
|
||||
after: () => {
|
||||
elecPriceData.value = [];
|
||||
elecPriceData.value.push(...pricelist);
|
||||
},
|
||||
limit: -1,
|
||||
offset: 0,
|
||||
},
|
||||
});
|
||||
|
||||
console.log("進入 bajaSubscriber 準備執行用電度數 BQL 訂閱");
|
||||
|
||||
// 定義BQL 查詢
|
||||
const Total_kwhBql = `local:|foxs:4918|station:|neql:EMS:Total_kwh|bql:select slotPath,parent.displayName,displayName,NumericInterval.historyConfig.id,out`;
|
||||
|
||||
// 執行各電表的 BQL 查詢
|
||||
let eleclist = [];
|
||||
baja.Ord.make(Total_kwhBql).get({
|
||||
cursor: {
|
||||
before: () => {},
|
||||
each: (record) => {
|
||||
eleclist.push({
|
||||
slotPath: record.get("slotPath"),
|
||||
displayName: record.get("parent$2edisplayName"),
|
||||
id: record.get("NumericInterval$2ehistoryConfig$2eid").$cEncStr,
|
||||
out: record.get("out")?.get("value") ?? null,
|
||||
});
|
||||
},
|
||||
after: () => {
|
||||
const validElecList = eleclist.filter(
|
||||
(item) => item.id !== undefined
|
||||
);
|
||||
elecData.value = [];
|
||||
elecData.value.push(...validElecList);
|
||||
validElecList.forEach((item) => {
|
||||
gettimeToHistory(item);
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const gettimeToHistory = (item) => {
|
||||
const id = item.id;
|
||||
const startTime = dayjs()
|
||||
.subtract(13, "day")
|
||||
.startOf("day")
|
||||
.format("YYYY-MM-DDTHH:mm:ss.000+08:00");
|
||||
const endTime = dayjs()
|
||||
.endOf("day")
|
||||
.format("YYYY-MM-DDTHH:mm:ss.000+08:00");
|
||||
|
||||
const ordString = `local:|foxs:4918|history:${id}?period=timerange;;start=${startTime};end=${endTime}|bql:history:HistoryRollup.rollup(baja:RelTime '3600000')`; //每小时一个rollup
|
||||
console.log(ordString);
|
||||
// @ts-ignore
|
||||
window.require &&
|
||||
// @ts-ignore
|
||||
window.requirejs(["baja!"], (baja) => {
|
||||
console.log("進入 bajaSubscriber 準備執行 BQL 訂閱");
|
||||
const dataMap = new Map();
|
||||
let lastTimestamp = null;
|
||||
let lastValue = null;
|
||||
baja.Ord.make(ordString).get({
|
||||
cursor: {
|
||||
before: () => {
|
||||
console.log(`開始訂閱 ${id} 的歷史資料`);
|
||||
},
|
||||
each: (record) => {
|
||||
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: () => {
|
||||
console.log("⏱️ 每小時差值 map:", dataMap);
|
||||
// 清空之前的數據,避免累積
|
||||
todayelecdata.value = new Map();
|
||||
yesterdayelecdata.value = new Map();
|
||||
|
||||
// 提取今天和昨天的数据
|
||||
for (const [timestamp, value] of dataMap) {
|
||||
const date = dayjs(timestamp).format("YYYY-MM-DD");
|
||||
const today = dayjs().format("YYYY-MM-DD");
|
||||
const yesterday = dayjs().subtract(1, "day").format("YYYY-MM-DD");
|
||||
|
||||
if (date === today) {
|
||||
todayelecdata.value.set(timestamp, value);
|
||||
} else if (date === yesterday) {
|
||||
yesterdayelecdata.value.set(timestamp, value);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("今天每小時差值 map:", todayelecdata.value);
|
||||
console.log("昨天每小時差值 map:", yesterdayelecdata.value);
|
||||
elecFlowCostSummary.value = calcuEleCost(
|
||||
dataMap,
|
||||
elecPriceData.value
|
||||
);
|
||||
},
|
||||
limit: -1,
|
||||
offset: 0,
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 定時更新資料的函數
|
||||
const updateHistoryData = () => {
|
||||
console.log("定時器觸發,重新獲取歷史資料");
|
||||
if (elecData.value && elecData.value.length > 0) {
|
||||
elecData.value.forEach((item) => {
|
||||
gettimeToHistory(item);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 啟動定時器
|
||||
const startTimer = () => {
|
||||
timerId = setInterval(() => {
|
||||
updateHistoryData();
|
||||
}, 60 * 60 * 1000); // 每小時執行一次
|
||||
};
|
||||
|
||||
// 停止定時器
|
||||
const stopTimer = () => {
|
||||
// @ts-ignore
|
||||
if (timerId) {
|
||||
clearInterval(timerId);
|
||||
timerId = null;
|
||||
console.log("計時器已停止");
|
||||
}
|
||||
};
|
||||
return {
|
||||
getElecDataFromBaja,
|
||||
startTimer,
|
||||
stopTimer,
|
||||
elecData,
|
||||
elecPriceData,
|
||||
elecFlowCostSummary,
|
||||
todayelecdata,
|
||||
yesterdayelecdata,
|
||||
};
|
||||
});
|
||||
|
||||
export default useElecStore;
|
140
src/utils/calcuEleCost.js
Normal file
140
src/utils/calcuEleCost.js
Normal file
@ -0,0 +1,140 @@
|
||||
export const calcuEleCost = (input, elecPriceData) => {
|
||||
const dailyData = new Map();
|
||||
let totalFlowCost = 0; // 總電價
|
||||
let totalEleCost = 0; //總用電
|
||||
let total_Off = 0; //總離峰用電
|
||||
let total_half = 0; //總半尖峰用電
|
||||
let total_peak = 0; //總尖峰用電
|
||||
let total_OffCost = 0; //總離峰電價
|
||||
let total_halfCost = 0; //總半尖峰電價
|
||||
let total_peakCost = 0; //總尖峰電價
|
||||
|
||||
const dailyResults = [];
|
||||
const elecPrices = elecPriceData;
|
||||
const Summer_Off_Prices =
|
||||
elecPrices.find((item) => item.displayName === "流動週日離峰夏月")
|
||||
?.out || 0;
|
||||
const Summer_HalfPeak_Prices_Saturday =
|
||||
elecPrices.find((item) => item.displayName === "流動週六半尖峰夏月")
|
||||
?.out || 0;
|
||||
const Summer_HalfPeak_Prices_Weekday =
|
||||
elecPrices.find((item) => item.displayName === "流動平日半尖峰夏月")
|
||||
?.out || 0;
|
||||
const Summer_Peak_Prices =
|
||||
elecPrices.find((item) => item.displayName === "流動平日尖峰夏月")
|
||||
?.out || 0;
|
||||
const Non_Summer_Off_Prices =
|
||||
elecPrices.find((item) => item.displayName === "流動週日離峰非夏月")
|
||||
?.out || 0;
|
||||
const Non_Summer_HalfPeak_Prices_Saturday =
|
||||
elecPrices.find((item) => item.displayName === "流動週六半尖峰非夏月")
|
||||
?.out || 0;
|
||||
const Non_Summer_HalfPeak_Prices_Weekday =
|
||||
elecPrices.find((item) => item.displayName === "流動平日半尖峰非夏月")
|
||||
?.out || 0;
|
||||
// 1. 將輸入資料按日期分組
|
||||
input.forEach((value, key) => {
|
||||
const dateStr = key.substring(0, 10);
|
||||
if (!dailyData.has(dateStr)) {
|
||||
dailyData.set(dateStr, []);
|
||||
}
|
||||
dailyData.get(dateStr)?.push({ time: new Date(key), value });
|
||||
});
|
||||
|
||||
for (const [dateStr, entries] of dailyData.entries()) {
|
||||
if (!entries || entries.length === 0) continue;
|
||||
|
||||
const sampleDate = entries[0].time;
|
||||
const dayOfWeek = sampleDate.getDay();
|
||||
const month = sampleDate.getMonth() + 1;
|
||||
|
||||
let off = 0; //離峰用電
|
||||
let half = 0; //半尖峰用電
|
||||
let peak = 0; //尖峰用電
|
||||
let offcost = 0; //離峰電價
|
||||
let halfcost = 0; //半尖峰電價
|
||||
let peakcost = 0; //尖峰電價
|
||||
let dailyFlowCost = 0; //當日電價
|
||||
let dailyEleCost = 0; //當日用電
|
||||
|
||||
const isSummer = month >= 6 && month <= 9;
|
||||
|
||||
entries.forEach(({ time, value }) => {
|
||||
const hour = time.getHours();
|
||||
|
||||
if (isSummer) {
|
||||
if (dayOfWeek === 0) {
|
||||
off += value;
|
||||
} else if (dayOfWeek === 6) {
|
||||
if (hour < 9) off += value;
|
||||
else half += value;
|
||||
} else {
|
||||
if (hour >= 16 && hour < 22) peak += value;
|
||||
else if ((hour >= 9 && hour < 16) || hour >= 22) half += value;
|
||||
else off += value;
|
||||
}
|
||||
} else {
|
||||
if (dayOfWeek === 0) {
|
||||
off += value;
|
||||
} else {
|
||||
if (hour < 6 || (hour >= 11 && hour < 14)) off += value;
|
||||
else half += value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (isSummer) {
|
||||
console.log("夏月計費");
|
||||
const summerHalfPeakRate =
|
||||
dayOfWeek === 6
|
||||
? Summer_HalfPeak_Prices_Saturday
|
||||
: Summer_HalfPeak_Prices_Weekday;
|
||||
offcost = off * Summer_Off_Prices;
|
||||
halfcost = half * summerHalfPeakRate;
|
||||
peakcost = peak * Summer_Peak_Prices;
|
||||
dailyFlowCost = offcost + halfcost + peakcost;
|
||||
dailyEleCost = off + half + peak;
|
||||
} else {
|
||||
console.log("非夏月計費");
|
||||
const nonSummerHalfPeakRate =
|
||||
dayOfWeek === 6
|
||||
? Non_Summer_HalfPeak_Prices_Saturday
|
||||
: Non_Summer_HalfPeak_Prices_Weekday;
|
||||
offcost = off * Non_Summer_Off_Prices;
|
||||
halfcost = half * nonSummerHalfPeakRate;
|
||||
dailyFlowCost = offcost + halfcost;
|
||||
dailyEleCost = off + half;
|
||||
}
|
||||
|
||||
totalFlowCost += dailyFlowCost;
|
||||
totalEleCost += dailyEleCost;
|
||||
total_Off += off;
|
||||
total_half += half;
|
||||
total_peak += peak;
|
||||
total_OffCost += offcost;
|
||||
total_halfCost += halfcost;
|
||||
total_peakCost += peakcost;
|
||||
dailyResults.push({
|
||||
dateStr,
|
||||
off,
|
||||
half,
|
||||
peak,
|
||||
offcost,
|
||||
halfcost,
|
||||
peakcost,
|
||||
dailyEleCost,
|
||||
dailyFlowCost,
|
||||
});
|
||||
}
|
||||
return {
|
||||
dailyResults,
|
||||
totalEleCost,
|
||||
totalFlowCost,
|
||||
total_Off,
|
||||
total_half,
|
||||
total_peak,
|
||||
total_OffCost,
|
||||
total_halfCost,
|
||||
total_peakCost,
|
||||
};
|
||||
};
|
1
src/utils/index.js
Normal file
1
src/utils/index.js
Normal file
@ -0,0 +1 @@
|
||||
export * from './calcuEleCost';
|
@ -1,10 +1,237 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import { ref, onMounted, onUnmounted, watch } from "vue";
|
||||
import DashboardStat from "@/components/dashboard/dashboardStat.vue";
|
||||
import DashboardBuild from "@/components/dashboard/dashboardBuild.vue";
|
||||
import DashboardElecChart from "@/components/dashboard/dashboardElecChart.vue";
|
||||
import DashboardTag from "@/components/dashboard/dashboardTag.vue";
|
||||
import DashboardAlert from "@/components/dashboard/dashboardAlert.vue";
|
||||
import useElecTotalMeterStore from "@/stores/useElecTotalMeterStore";
|
||||
import useElecDemandStore from "@/stores/useElecDemandStore";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const elecDataStore = useElecTotalMeterStore();
|
||||
const elecDemandStore = useElecDemandStore();
|
||||
const elecStat = ref([
|
||||
{
|
||||
value: 0,
|
||||
label: "今日用電量",
|
||||
unit: "kWH",
|
||||
icon: "leaf",
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
label: "昨日用電量",
|
||||
unit: "kWH",
|
||||
icon: "leaf",
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
label: "即時功率",
|
||||
unit: "kW",
|
||||
icon: "bolt",
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
label: "容積占比",
|
||||
unit: "%",
|
||||
icon: "charging-station",
|
||||
},
|
||||
]);
|
||||
const elecDemand_P = ref(0); // 即時趨勢
|
||||
const elecDemand_Engel = ref(0); // 契約容量
|
||||
const yesterdayTodayData = ref({
|
||||
categories: [],
|
||||
values: [
|
||||
{
|
||||
name: `${dayjs().format("YYYY-MM-DD")} 用電量`,
|
||||
value: [],
|
||||
},
|
||||
{
|
||||
name: `${dayjs().subtract(1, "day").format("YYYY-MM-DD")} 用電量`,
|
||||
value: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const weekComparisonData = ref({
|
||||
categories: [],
|
||||
values: [
|
||||
{
|
||||
name: "本週用電量",
|
||||
value: [0, 0, 0, 0, 0, 0, 0],
|
||||
},
|
||||
{
|
||||
name: "上週用電量",
|
||||
value: [0, 0, 0, 0, 0, 0, 0],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const generateWeekCategories = () => {
|
||||
const today = dayjs();
|
||||
const currentDay = today.day();
|
||||
const daysOfWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
||||
const dynamicCategories = [];
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const dayIndex = (currentDay - i + 7) % 7;
|
||||
dynamicCategories.unshift(daysOfWeek[dayIndex]);
|
||||
}
|
||||
|
||||
return dynamicCategories;
|
||||
};
|
||||
|
||||
weekComparisonData.value = {
|
||||
...weekComparisonData.value,
|
||||
categories: generateWeekCategories(),
|
||||
};
|
||||
|
||||
watch(
|
||||
() => elecDataStore.elecFlowCostSummary,
|
||||
(newElecData) => {
|
||||
console.log("elecStandCostSummary", newElecData);
|
||||
if (newElecData && newElecData.dailyResults) {
|
||||
const today = dayjs().format("YYYY-MM-DD");
|
||||
const yesterday = dayjs().subtract(1, "day").format("YYYY-MM-DD");
|
||||
|
||||
const todayData = newElecData.dailyResults.find(
|
||||
(item) => item.dateStr === today
|
||||
);
|
||||
const yesterdayData = newElecData.dailyResults.find(
|
||||
(item) => item.dateStr === yesterday
|
||||
);
|
||||
|
||||
const todayElecCost = todayData ? todayData.dailyEleCost : 0;
|
||||
const yesterdayElecCost = yesterdayData ? yesterdayData.dailyEleCost : 0;
|
||||
|
||||
elecStat.value = [
|
||||
{
|
||||
...elecStat.value[0],
|
||||
value: todayElecCost,
|
||||
},
|
||||
{
|
||||
...elecStat.value[1],
|
||||
value: yesterdayElecCost,
|
||||
},
|
||||
{
|
||||
...elecStat.value[2],
|
||||
},
|
||||
{
|
||||
...elecStat.value[3],
|
||||
},
|
||||
];
|
||||
|
||||
const thisWeekData = newElecData.dailyResults
|
||||
.slice(-7)
|
||||
.map((item) => item.dailyEleCost || 0);
|
||||
const lastWeekData = newElecData.dailyResults
|
||||
.slice(-14, -7)
|
||||
.map((item) => item.dailyEleCost || 0);
|
||||
|
||||
weekComparisonData.value = {
|
||||
...weekComparisonData.value,
|
||||
values: [
|
||||
{
|
||||
name: "本週用電量",
|
||||
value: thisWeekData,
|
||||
},
|
||||
{
|
||||
name: "上週用電量",
|
||||
value: lastWeekData,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => [elecDataStore.todayelecdata, elecDataStore.yesterdayelecdata],
|
||||
([newTodayData, newYesterdayData]) => {
|
||||
console.log("todayyesterday", newTodayData, newYesterdayData);
|
||||
|
||||
const todayDate = dayjs().format("YYYY-MM-DD");
|
||||
const yesterdayDate = dayjs().subtract(1, "day").format("YYYY-MM-DD");
|
||||
|
||||
const categories = [];
|
||||
const todayValues = [];
|
||||
|
||||
for (const [timestamp, value] of newTodayData) {
|
||||
const hour = dayjs(timestamp).format("HH:00");
|
||||
categories.push(hour);
|
||||
todayValues.push(value);
|
||||
}
|
||||
|
||||
categories.sort();
|
||||
|
||||
const filledYesterdayValues = categories.map((hour) => {
|
||||
const timestamp = dayjs(
|
||||
`${yesterdayDate} ${hour}`,
|
||||
"YYYY-MM-DD HH:00"
|
||||
).format("YYYY-MM-DDTHH:mm:ss.000+08:00");
|
||||
return newYesterdayData.get(timestamp) || 0;
|
||||
});
|
||||
|
||||
console.log("todayValues", todayValues, filledYesterdayValues);
|
||||
yesterdayTodayData.value = {
|
||||
categories: categories,
|
||||
values: [
|
||||
{
|
||||
name: `${todayDate} 用電量`,
|
||||
value: todayValues,
|
||||
},
|
||||
{
|
||||
name: `${yesterdayDate} 用電量`,
|
||||
value: filledYesterdayValues,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => elecDemandStore.elecData,
|
||||
(newElecData) => {
|
||||
console.log("elecDemandStore.elecData updated:", newElecData);
|
||||
|
||||
const newElecDemand_P =
|
||||
newElecData.find((item) => item.name === "P")?.out || 0;
|
||||
const newElecDemand_Engel =
|
||||
newElecData.find((item) => item.name === "Engel")?.out || 0;
|
||||
|
||||
elecDemand_P.value = newElecDemand_P;
|
||||
elecDemand_Engel.value = newElecDemand_Engel;
|
||||
|
||||
elecStat.value = [
|
||||
...elecStat.value.slice(0, 2),
|
||||
{
|
||||
...elecStat.value[2],
|
||||
value: newElecDemand_P,
|
||||
},
|
||||
{
|
||||
...elecStat.value[3],
|
||||
value: newElecDemand_Engel
|
||||
? ((newElecDemand_P / newElecDemand_Engel) * 100).toFixed(2)
|
||||
: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
await elecDataStore.getElecDataFromBaja();
|
||||
elecDataStore.startTimer();
|
||||
|
||||
await elecDemandStore.getElecDemandFromBaja();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
elecDataStore.stopTimer();
|
||||
elecDemandStore.clearAllSubscriber();
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<a-row :gutter="24" class="px-5 py-2">
|
||||
@ -14,9 +241,12 @@ import DashboardAlert from "@/components/dashboard/dashboardAlert.vue";
|
||||
</a-col>
|
||||
<a-col :span="16" class="">
|
||||
<!-- 用電數據 -->
|
||||
<DashboardStat />
|
||||
<DashboardStat :elecData="elecStat" />
|
||||
<!-- 用電圖表 -->
|
||||
<DashboardElecChart />
|
||||
<DashboardElecChart
|
||||
:yesterdayTodayData="yesterdayTodayData"
|
||||
:weekComparisonData="weekComparisonData"
|
||||
/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user