能源圖表串接
This commit is contained in:
		
							parent
							
								
									ca522b8b94
								
							
						
					
					
						commit
						59bf0fa00b
					
				
							
								
								
									
										136
									
								
								src/stores/useElecTotalMeterStore.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								src/stores/useElecTotalMeterStore.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,136 @@
 | 
			
		||||
import { ref } from "vue";
 | 
			
		||||
import { defineStore } from "pinia";
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
import type { NiagaraElecData, ElecCostSummary } from "../utils/types";
 | 
			
		||||
import { CalcuEleCost } from "../utils/CalcuEleCost";
 | 
			
		||||
 | 
			
		||||
const useElecStore = defineStore("elecData", () => {
 | 
			
		||||
  const elecData = ref<NiagaraElecData[]>([]);
 | 
			
		||||
  // @ts-ignore
 | 
			
		||||
  let timerId = null;
 | 
			
		||||
  const elecCostSummary = ref<ElecCostSummary | null>(null);
 | 
			
		||||
 | 
			
		||||
  // 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:Total_kwh|bql:select slotPath,parent.displayName,displayName,NumericInterval.historyConfig.id,out`;
 | 
			
		||||
 | 
			
		||||
        // 執行各電表的 BQL 查詢
 | 
			
		||||
        fetchElecData(baja, Total_kwhBql);
 | 
			
		||||
      });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const fetchElecData = (baja: any, bql: string) => {
 | 
			
		||||
    let eleclist: NiagaraElecData[] = [];
 | 
			
		||||
    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,
 | 
			
		||||
            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: NiagaraElecData) => {
 | 
			
		||||
    const id = item.id;
 | 
			
		||||
    const startTime = dayjs(
 | 
			
		||||
      `${dayjs().year()}-01-01T00:00:00.000+08:00`
 | 
			
		||||
    ).format("YYYY-MM-DDTHH:mm:ss.000+08:00");
 | 
			
		||||
    const endTime = dayjs().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: any) => {
 | 
			
		||||
        console.log("進入 bajaSubscriber 準備執行 BQL 訂閱");
 | 
			
		||||
        const dataMap = new Map<string, number>(); // key: timestamp string, value: energy diff
 | 
			
		||||
        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: () => {
 | 
			
		||||
              console.log("⏱️ 每小時差值 map:", dataMap);
 | 
			
		||||
              elecCostSummary.value = CalcuEleCost(dataMap);
 | 
			
		||||
            },
 | 
			
		||||
            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,
 | 
			
		||||
    elecCostSummary,
 | 
			
		||||
  };
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default useElecStore;
 | 
			
		||||
@ -0,0 +1,133 @@
 | 
			
		||||
import type { DailyResult, ElecCostSummary, DailyEntry } from "../utils/types";
 | 
			
		||||
import useElecPriceStore from "../stores/useElecPriceStore";
 | 
			
		||||
const storeElecPrice = useElecPriceStore();
 | 
			
		||||
 | 
			
		||||
export const CalcuEleCost = (
 | 
			
		||||
  input: Map<string, number>
 | 
			
		||||
): ElecCostSummary => {
 | 
			
		||||
  const dailyData: Map<string, DailyEntry[]> = 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: 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;
 | 
			
		||||
  // 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,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
@ -57,7 +57,7 @@
 | 
			
		||||
    </el-col>
 | 
			
		||||
    <el-col :span="16">
 | 
			
		||||
      <el-card style="border-radius: 8px">
 | 
			
		||||
        <h3 class="">區間計費度數 2025-03-01 ~ 2025-03-12</h3>
 | 
			
		||||
        <h3 class="">區間計費度數 {{ billingDateRange }}</h3>
 | 
			
		||||
        <EnergyBar :chartData="areaBillingData" />
 | 
			
		||||
      </el-card>
 | 
			
		||||
    </el-col>
 | 
			
		||||
@ -65,151 +65,245 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import { onMounted, ref, computed, onUnmounted } from "vue";
 | 
			
		||||
import { onMounted, ref, watch, computed, onUnmounted } from "vue";
 | 
			
		||||
import EnergySankey from "../components/EnergySankey.vue";
 | 
			
		||||
import EnergyLine from "../components/EnergyLine.vue";
 | 
			
		||||
import EnergyBar from "../components/EnergyBar.vue";
 | 
			
		||||
import useElecTotalMeterStore from "../stores/useElecTotalMeterStore";
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
 | 
			
		||||
const statisticData = ref([
 | 
			
		||||
  { title: "今年電費累計", value: 58792.56, unit: "元" },
 | 
			
		||||
  { title: "區間電費", value: 1234.78, unit: "元" },
 | 
			
		||||
  { title: "今年碳排當量累計", value: 3456.23, unit: "公斤" },
 | 
			
		||||
  { title: "區間碳排當量", value: 15.67, unit: "公斤" },
 | 
			
		||||
  { title: "今年用電度數", value: 1890.45, unit: "kWh" },
 | 
			
		||||
  { title: "區間用電度數", value: 123.9, unit: "kWh" },
 | 
			
		||||
]);
 | 
			
		||||
const storeElecTotal = useElecTotalMeterStore();
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
  () => storeElecTotal.elecCostSummary,
 | 
			
		||||
  (newElecData) => {
 | 
			
		||||
    console.log("elecCostSummary", newElecData);
 | 
			
		||||
  },
 | 
			
		||||
  { deep: true }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
onMounted(async () => {
 | 
			
		||||
  await storeElecTotal.getElecDataFromBaja();
 | 
			
		||||
  storeElecTotal.startTimer();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onUnmounted(() => {
 | 
			
		||||
  storeElecTotal.stopTimer();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const statisticData = computed(() => {
 | 
			
		||||
  const currentMonth = dayjs().format("YYYY-MM");
 | 
			
		||||
 | 
			
		||||
  let intervalFlowCost = 0;
 | 
			
		||||
  let intervalEleCost = 0;
 | 
			
		||||
 | 
			
		||||
  if (storeElecTotal.elecCostSummary?.dailyResults) {
 | 
			
		||||
    storeElecTotal.elecCostSummary.dailyResults.forEach((dailyResult) => {
 | 
			
		||||
      if (dailyResult.dateStr.startsWith(currentMonth)) {
 | 
			
		||||
        intervalFlowCost += dailyResult.dailyFlowCost;
 | 
			
		||||
        intervalEleCost += dailyResult.dailyEleCost;
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return [
 | 
			
		||||
    {
 | 
			
		||||
      title: "今年電費累計",
 | 
			
		||||
      value: storeElecTotal.elecCostSummary?.totalFlowCost || 0,
 | 
			
		||||
      unit: "元",
 | 
			
		||||
    },
 | 
			
		||||
    { title: "區間電費", value: intervalFlowCost, unit: "元" },
 | 
			
		||||
    {
 | 
			
		||||
      title: "今年碳排當量累計",
 | 
			
		||||
      value: storeElecTotal.elecCostSummary?.totalEleCost * 0.424,
 | 
			
		||||
      unit: "公斤 CO2e/度",
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: "區間碳排當量",
 | 
			
		||||
      value: intervalEleCost * 0.424,
 | 
			
		||||
      unit: "公斤 CO2e/度",
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: "今年用電度數",
 | 
			
		||||
      value: storeElecTotal.elecCostSummary?.totalEleCost || 0,
 | 
			
		||||
      unit: "kWh",
 | 
			
		||||
    },
 | 
			
		||||
    { title: "區間用電度數", value: intervalEleCost, unit: "kWh" },
 | 
			
		||||
  ];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function groupByMonth(dailyResults) {
 | 
			
		||||
  const grouped = {};
 | 
			
		||||
  dailyResults.forEach((result) => {
 | 
			
		||||
    const month = dayjs(result.dateStr).format("MMM"); // Get abbreviated month name
 | 
			
		||||
    if (!grouped[month]) {
 | 
			
		||||
      grouped[month] = {
 | 
			
		||||
        off: 0,
 | 
			
		||||
        half: 0,
 | 
			
		||||
        peak: 0,
 | 
			
		||||
        total: 0,
 | 
			
		||||
        offcost: 0,
 | 
			
		||||
        halfcost: 0,
 | 
			
		||||
        peakcost: 0,
 | 
			
		||||
        totalCost: 0,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
    grouped[month].off += result.off;
 | 
			
		||||
    grouped[month].half += result.half;
 | 
			
		||||
    grouped[month].peak += result.peak;
 | 
			
		||||
    grouped[month].offcost += result.offcost;
 | 
			
		||||
    grouped[month].halfcost += result.halfcost;
 | 
			
		||||
    grouped[month].peakcost += result.peakcost;
 | 
			
		||||
    grouped[month].total += result.dailyEleCost;
 | 
			
		||||
    grouped[month].totalCost += result.dailyFlowCost;
 | 
			
		||||
  });
 | 
			
		||||
  return grouped;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 每月用電分析
 | 
			
		||||
const monthlyElectricityData = ref({
 | 
			
		||||
  categories: [
 | 
			
		||||
    "Jan",
 | 
			
		||||
    "Feb",
 | 
			
		||||
    "Mar",
 | 
			
		||||
    "Apr",
 | 
			
		||||
    "May",
 | 
			
		||||
    "Jun",
 | 
			
		||||
    "Jul",
 | 
			
		||||
    "Aug",
 | 
			
		||||
    "Sep",
 | 
			
		||||
    "Oct",
 | 
			
		||||
    "Nov",
 | 
			
		||||
    "Dec",
 | 
			
		||||
  ],
 | 
			
		||||
  series: [
 | 
			
		||||
    {
 | 
			
		||||
      name: "基本電量",
 | 
			
		||||
      type: "bar",
 | 
			
		||||
      data: [120, 100, 110, 130, 150, 160, 140, 150, 130, 120, 110, 130],
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: "流動電量",
 | 
			
		||||
      type: "bar",
 | 
			
		||||
      data: [80, 60, 70, 90, 100, 110, 90, 100, 80, 70, 60, 80],
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: "總電量",
 | 
			
		||||
      type: "bar",
 | 
			
		||||
      data: [200, 160, 180, 220, 250, 270, 230, 250, 210, 190, 170, 210],
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
const monthlyElectricityData = computed(() => {
 | 
			
		||||
  if (!storeElecTotal.elecCostSummary?.dailyResults) {
 | 
			
		||||
    return { categories: [], series: [] };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const groupedData = groupByMonth(storeElecTotal.elecCostSummary.dailyResults);
 | 
			
		||||
  const categories = Object.keys(groupedData);
 | 
			
		||||
  const sortedCategories = _.sortBy(categories, (month) =>
 | 
			
		||||
    dayjs().month(month).valueOf()
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const baseElecData = sortedCategories.map((month) => groupedData[month].offcost);
 | 
			
		||||
  const flowElecData = sortedCategories.map(
 | 
			
		||||
    (month) => groupedData[month].totalCost
 | 
			
		||||
  );
 | 
			
		||||
  const totalElecData = sortedCategories.map((month, index) => { 
 | 
			
		||||
    return (baseElecData[index] || 0) + (flowElecData[index] || 0); 
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    categories: sortedCategories,
 | 
			
		||||
    series: [
 | 
			
		||||
      {
 | 
			
		||||
        name: "基本電費",
 | 
			
		||||
        type: "bar",
 | 
			
		||||
        data: baseElecData,
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        name: "流動電費",
 | 
			
		||||
        type: "bar",
 | 
			
		||||
        data: flowElecData,
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        name: "總電量",
 | 
			
		||||
        type: "bar",
 | 
			
		||||
        data: totalElecData,
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  };
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 每月碳排當量
 | 
			
		||||
const monthlyCarbonData = ref({
 | 
			
		||||
  categories: [
 | 
			
		||||
    "Jan",
 | 
			
		||||
    "Feb",
 | 
			
		||||
    "Mar",
 | 
			
		||||
    "Apr",
 | 
			
		||||
    "May",
 | 
			
		||||
    "Jun",
 | 
			
		||||
    "Jul",
 | 
			
		||||
    "Aug",
 | 
			
		||||
    "Sep",
 | 
			
		||||
    "Oct",
 | 
			
		||||
    "Nov",
 | 
			
		||||
    "Dec",
 | 
			
		||||
  ],
 | 
			
		||||
  series: [
 | 
			
		||||
    {
 | 
			
		||||
      name: "碳排當量",
 | 
			
		||||
      type: "bar",
 | 
			
		||||
      data: [50, 40, 45, 55, 60, 65, 55, 60, 50, 45, 40, 50],
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
const monthlyCarbonData = computed(() => {
 | 
			
		||||
  if (!storeElecTotal.elecCostSummary?.dailyResults) {
 | 
			
		||||
    return { categories: [], series: [] };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const groupedData = groupByMonth(storeElecTotal.elecCostSummary.dailyResults);
 | 
			
		||||
  const categories = Object.keys(groupedData);
 | 
			
		||||
  const sortedCategories = _.sortBy(categories, (month) =>
 | 
			
		||||
    dayjs().month(month).valueOf()
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const carbonData = sortedCategories.map((month) =>
 | 
			
		||||
    (groupedData[month].total * 0.424).toFixed(2)
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    categories: sortedCategories,
 | 
			
		||||
    series: [
 | 
			
		||||
      {
 | 
			
		||||
        name: "碳排當量",
 | 
			
		||||
        type: "bar",
 | 
			
		||||
        data: carbonData,
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  };
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 每月計費度數 (kWh)
 | 
			
		||||
const monthlyBillingData = ref({
 | 
			
		||||
  categories: [
 | 
			
		||||
    "Jan",
 | 
			
		||||
    "Feb",
 | 
			
		||||
    "Mar",
 | 
			
		||||
    "Apr",
 | 
			
		||||
    "May",
 | 
			
		||||
    "Jun",
 | 
			
		||||
    "Jul",
 | 
			
		||||
    "Aug",
 | 
			
		||||
    "Sep",
 | 
			
		||||
    "Oct",
 | 
			
		||||
    "Nov",
 | 
			
		||||
    "Dec",
 | 
			
		||||
  ],
 | 
			
		||||
  series: [
 | 
			
		||||
    {
 | 
			
		||||
      name: "尖峰",
 | 
			
		||||
      type: "bar",
 | 
			
		||||
      data: [120, 100, 110, 130, 150, 160, 140, 150, 130, 120, 110, 130],
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: "半尖峰",
 | 
			
		||||
      type: "bar",
 | 
			
		||||
      data: [80, 60, 70, 90, 100, 110, 90, 100, 80, 70, 60, 80],
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: "離峰",
 | 
			
		||||
      type: "bar",
 | 
			
		||||
      data: [200, 160, 180, 220, 250, 270, 230, 250, 210, 190, 170, 210],
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
const monthlyBillingData = computed(() => {
 | 
			
		||||
  if (!storeElecTotal.elecCostSummary?.dailyResults) {
 | 
			
		||||
    return { categories: [], series: [] };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const billingData = groupByMonth(storeElecTotal.elecCostSummary.dailyResults);
 | 
			
		||||
  const categories = Object.keys(billingData);
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    categories: sortedCategories,
 | 
			
		||||
    series: [
 | 
			
		||||
      { name: "尖峰", type: "bar", data: peakData },
 | 
			
		||||
      { name: "半尖峰", type: "bar", data: halfData },
 | 
			
		||||
      { name: "離峰", type: "bar", data: offData }
 | 
			
		||||
    ]
 | 
			
		||||
  };
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 區間計費度數
 | 
			
		||||
const areaBillingData = ref({
 | 
			
		||||
  categories: [
 | 
			
		||||
    "03-01",
 | 
			
		||||
    "03-02",
 | 
			
		||||
    "03-03",
 | 
			
		||||
    "03-04",
 | 
			
		||||
    "03-05",
 | 
			
		||||
    "03-06",
 | 
			
		||||
    "03-07",
 | 
			
		||||
    "03-08",
 | 
			
		||||
    "03-09",
 | 
			
		||||
    "03-10",
 | 
			
		||||
    "03-11",
 | 
			
		||||
    "03-12",
 | 
			
		||||
  ],
 | 
			
		||||
  series: [
 | 
			
		||||
    {
 | 
			
		||||
      name: "尖峰",
 | 
			
		||||
      type: "bar",
 | 
			
		||||
      data: [120, 100, 110, 130, 150, 160, 140, 150, 130, 120, 110, 130],
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: "半尖峰",
 | 
			
		||||
      type: "bar",
 | 
			
		||||
      data: [80, 60, 70, 90, 100, 110, 90, 100, 80, 70, 60, 80],
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: "離峰",
 | 
			
		||||
      type: "bar",
 | 
			
		||||
      data: [200, 160, 180, 220, 250, 270, 230, 250, 210, 190, 170, 210],
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
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) {
 | 
			
		||||
    return { categories: [], series: [] };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const today = dayjs();
 | 
			
		||||
  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');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // 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
 | 
			
		||||
    transformedData[date] = {
 | 
			
		||||
      peak: result.peak,
 | 
			
		||||
      half: result.half,
 | 
			
		||||
      off: result.off
 | 
			
		||||
    };
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const categories = Object.keys(transformedData);
 | 
			
		||||
  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);
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    categories: sortedCategories,
 | 
			
		||||
    series: [
 | 
			
		||||
      { name: "尖峰", type: "bar", data: peakData },
 | 
			
		||||
      { name: "半尖峰", type: "bar", data: halfData },
 | 
			
		||||
      { name: "離峰", type: "bar", data: offData }
 | 
			
		||||
    ]
 | 
			
		||||
  };
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user