diff --git a/src/components/navbar/NavbarBuilding.vue b/src/components/navbar/NavbarBuilding.vue index f17dfd5..5664ca7 100644 --- a/src/components/navbar/NavbarBuilding.vue +++ b/src/components/navbar/NavbarBuilding.vue @@ -1,27 +1,20 @@ - + \ No newline at end of file diff --git a/src/components/navbar/NavbarItem.vue b/src/components/navbar/NavbarItem.vue index 4b8a892..2ad7d4b 100644 --- a/src/components/navbar/NavbarItem.vue +++ b/src/components/navbar/NavbarItem.vue @@ -46,11 +46,11 @@ const getSubPage = async (system_type) => { const res = await getSideBar(system_type); menu_array.value = res.data; }; -const showDrawer = (authCode) => { +const showDrawer = async (authCode) => { if (authCode === "PF1") { - getSubMonitorPage(); + await getSubMonitorPage(); } else if (authCode === "PF2" || authCode === "PF11") { - getSubPage(authCode === "PF2" ? "Energy" : "Setting"); + await getSubPage(authCode === "PF2" ? "Energy" : "Setting"); } currentAuthCode.value = authCode; open.value = true; diff --git a/src/config/cn.json b/src/config/cn.json index d13b297..81ec44f 100644 --- a/src/config/cn.json +++ b/src/config/cn.json @@ -101,7 +101,37 @@ "total_amount": "金额总计", "elec_price_list": "电价表", "residential": "住宅型", - "standard": "标准型" + "standard": "标准型", + "simple_elec_price_two_stage": "简易型时间电价二段式", + "simple_elec_price_three_stage": "简易型时间电价三段式", + "classification": "分类", + "summer_months": "夏月", + "non_summer_months": "非夏月", + "time_outside_summer_months": "夏月以外的时间", + "basic_elec_charge": "基本电费", + "charged_per_household": "按户计收", + "per_household_month": "每户每月", + "mon_to_friday": "周一~周五", + "peak_hours": "尖峰时间", + "semi_peak_hours": "半尖峰时间", + "off_peak_hours": "离峰时间", + "price_per_kwh": "每度", + "all_day": "全日", + "sat_sun_off_peak_days": "周六、周日及离峰日", + "usage_over_2000kwh": "每月总度数超过2000度之部分", + "add": "加", + "standard_time_of_use_tariff_2_stage": "标准型时间电价二段式", + "standard_time_of_use_tariff_3_stage": "标准型时间电价三段式", + "single_phase": "单相", + "three_phase": "三相", + "frequent_contract": "经常契约", + "per_kw_per_month": "每瓩每月", + "non_summer_contract": "非夏日契约", + "saturday_semi_peak_contract": "周六半尖峰契约", + "off_peak_contract": "离峰契约", + "variable_electricity_charge": "流动电费", + "saturday": "周六", + "sunday_and_off_peak_days": "周日及离峰日" }, "alarm": { "title": "显示警告", diff --git a/src/config/tw.json b/src/config/tw.json index 26f3444..64e3de3 100644 --- a/src/config/tw.json +++ b/src/config/tw.json @@ -101,7 +101,37 @@ "total_amount": "金額總計", "elec_price_list": "電價表", "residential": "住宅型", - "standard": "標準型" + "standard": "標準型", + "simple_elec_price_two_stage":"簡易型時間電價二段式", + "simple_elec_price_three_stage":"簡易型時間電價三段式", + "classification":"分類", + "summer_months":"夏月", + "non_summer_months":"非夏月", + "time_outside_summer_months":"夏月以外的時間", + "basic_elec_charge": "基本電費", + "charged_per_household": "按戶計收", + "per_household_month": "每戶每月", + "mon_to_friday": "週一~週五", + "peak_hours": "尖峰時間", + "semi_peak_hours": "半尖峰時間", + "off_peak_hours": "離峰時間", + "price_per_kwh": "每度", + "all_day": "全日", + "sat_sun_off_peak_days": "週六、週日及離峰日", + "usage_over_2000kwh": "每月總度數超過2000度之部分", + "add": "加", + "standard_time_of_use_tariff_2_stage": "標準型時間電價二段式", + "standard_time_of_use_tariff_3_stage": "標準型時間電價三段式", + "single_phase": "單相", + "three_phase": "三相", + "frequent_contract": "經常契約", + "per_kw_per_month": "每瓩每月", + "non_summer_contract": "非夏日契約", + "saturday_semi_peak_contract": "週六半尖峰契約", + "off_peak_contract": "離峰契約", + "variable_electricity_charge": "流動電費", + "saturday": "週六", + "sunday_and_off_peak_days": "週日及離峰日" }, "alarm": { "title": "顯示警告", diff --git a/src/config/us.json b/src/config/us.json index 9411804..8d9f962 100644 --- a/src/config/us.json +++ b/src/config/us.json @@ -101,7 +101,37 @@ "total_amount": "Total amount", "elec_price_list": "Electricity Price List", "residential": "Residential", - "standard": "Standard" + "standard": "Standard", + "simple_elec_price_two_stage": "Simple Time-of-Use Electricity Price (Two-Tier)", + "simple_elec_price_three_stage": "Simple Time-of-Use Electricity Price (Three-Tier)", + "classification": "Classification", + "summer_months": "Summer Months", + "non_summer_months": "Non-Summer Months", + "time_outside_summer_months": "Time Outside Summer Months", + "basic_elec_charge": "Basic Electricity Charge", + "charged_per_household": "Charged Per Household", + "per_household_month": "Per Household Per Month", + "mon_to_friday": "Monday to Friday", + "peak_hours": "Peak Hours", + "semi_peak_hours": "Semi-Peak Hours", + "off_peak_hours": "Off-Peak Hours", + "price_per_kwh": "Price Per kWh", + "all_day": "All Day", + "sat_sun_off_peak_days": "Saturday, Sunday, and Off-Peak Days", + "usage_over_2000kwh": "Usage Over 2000 kWh Per Month", + "add": "Add", + "standard_time_of_use_tariff_2_stage": "Standard Time-of-Use Tariff (Two-Tier)", + "standard_time_of_use_tariff_3_stage": "Standard Time-of-Use Tariff (Three-Tier)", + "single_phase": "Single Phase", + "three_phase": "Three Phase", + "frequent_contract": "Demand Charge", + "per_kw_per_month": "Per kW Per Month", + "non_summer_contract": "Non-Summer Demand Charge", + "saturday_semi_peak_contract": "Saturday Semi-Peak Demand Charge", + "off_peak_contract": "Off-Peak Demand Charge", + "variable_electricity_charge": "Variable Electricity Charge", + "saturday": "Saturday", + "sunday_and_off_peak_days": "Sunday and Off-Peak Days" }, "alarm": { "title": "Warning", diff --git a/src/fontawsomeIconRegister.js b/src/fontawsomeIconRegister.js index 01f3966..9939954 100644 --- a/src/fontawsomeIconRegister.js +++ b/src/fontawsomeIconRegister.js @@ -61,6 +61,7 @@ import { faDownload, faStream, faSave, + faCrown } from "@fortawesome/free-solid-svg-icons"; /* add icons to the library */ @@ -122,7 +123,8 @@ library.add( faGlobe, faDownload, faStream, - faSave + faSave, + faCrown ); export default library; diff --git a/src/stores/useBuildingStore.js b/src/stores/useBuildingStore.js index 5a6987c..6f9c69d 100644 --- a/src/stores/useBuildingStore.js +++ b/src/stores/useBuildingStore.js @@ -1,17 +1,18 @@ import { defineStore } from "pinia"; -import { ref, computed } from "vue"; +import { ref, computed, watch } from "vue"; import { useRoute } from "vue-router"; +import { getBuildings } from "@/apis/building"; +import { getAssetFloorList, getDepartmentList } from "@/apis/asset"; const useBuildingStore = defineStore("buildingInfo", () => { - // 所有棟別 + // 狀態定義 const buildings = ref([]); - const selectedBuilding = ref(null); - - // 所有大小類系統 + const floorList = ref([]); + const deptList = ref([]); const mainSubSys = ref([]); - // 所有大類 + // 計算屬性 const mainSys = computed(() => mainSubSys.value.map(({ main_system_tag, full_name }) => ({ main_system_tag, @@ -21,7 +22,6 @@ const useBuildingStore = defineStore("buildingInfo", () => { const subSys = computed(() => { let subPages = []; - mainSubSys.value.forEach(({ main_system_tag, history_Sub_systems }) => { subPages = [ ...subPages, @@ -32,7 +32,6 @@ const useBuildingStore = defineStore("buildingInfo", () => { })), ]; }); - return subPages; }); @@ -44,14 +43,60 @@ const useBuildingStore = defineStore("buildingInfo", () => { return null; }); + // 獲取所有建築物 + const fetchBuildings = async () => { + const res = await getBuildings(); + buildings.value = res.data; + if (res.data.length > 0 && !selectedBuilding.value) { + selectedBuilding.value = res.data[0]; // 預設選第一個建築 + } + }; + + // 獲取樓層資料 + const fetchFloorList = async () => { + const res = await getAssetFloorList(); + floorList.value = res.data[0]?.floors.map((d) => ({ + ...d, + title: d.full_name, + key: d.floor_guid, + })) || []; + }; + + // 獲取部門資料 + const fetchDepartmentList = async () => { + const res = await getDepartmentList(); + deptList.value = res.data.map((d) => ({ + ...d, + title: d.name, + key: d.id, + })) || []; + }; + + // 當 selectedBuilding 改變時,更新 floorList 和 deptList + watch(selectedBuilding, async (newBuilding) => { + if (newBuilding) { + await Promise.all([fetchFloorList(), fetchDepartmentList()]); + } + }); + + // 初始化資料 + const initialize = async () => { + await fetchBuildings(); + }; + return { buildings, selectedBuilding, + floorList, + deptList, mainSubSys, mainSys, subSys, selectedSystem, + fetchBuildings, + fetchFloorList, + fetchDepartmentList, + initialize, }; }); - export default useBuildingStore; diff --git a/src/views/AssetManagement/AssetManagement.vue b/src/views/AssetManagement/AssetManagement.vue index beaaa18..38d2b9e 100644 --- a/src/views/AssetManagement/AssetManagement.vue +++ b/src/views/AssetManagement/AssetManagement.vue @@ -4,8 +4,10 @@ import AssetMainList from "./components/AssetMainList.vue"; import AssetSubList from "./components/AssetSubList.vue"; import AssetTable from "./components/AssetTable.vue"; import { getOperationCompanyList } from "@/apis/operation"; -import { getDepartmentList, getIOTSchema, getElecTypeList, getAssetFloorList } from "@/apis/asset"; +import { getIOTSchema, getElecTypeList } from "@/apis/asset"; import useSearchParam from "@/hooks/useSearchParam"; +import useBuildingStore from "@/stores/useBuildingStore"; +const storeBuild = useBuildingStore(); const { searchParams, changeParams } = useSearchParam(); const companyOptions = ref([]); const iotSchemaOptions = ref([]); @@ -24,20 +26,12 @@ const getElecType = async () => { const res = await getElecTypeList(); elecTypeOptions.value = res.data.map((d) => ({ ...d, key: d.id })); }; -const getDepartment = async () => { - const res = await getDepartmentList(); - departmentList.value = res.data.map((d) => ({ ...d, key: d.id })); -}; -const getFloors = async () => { - const res = await getAssetFloorList(); - floors.value = res.data[0]?.floors.map((d) => ({ ...d, key: d.floor_guid })); -}; onMounted(() => { getCompany(); getElecType(); - getDepartment(); - getFloors(); + floors.value = storeBuild.floorList; + departmentList.value = storeBuild.deptList; }); watch( diff --git a/src/views/dashboard/Dashboard.vue b/src/views/dashboard/Dashboard.vue index ddf5fb9..cde1b07 100644 --- a/src/views/dashboard/Dashboard.vue +++ b/src/views/dashboard/Dashboard.vue @@ -1,11 +1,13 @@ + + + + diff --git a/src/views/dashboard/components/DashboardElecRank.vue b/src/views/dashboard/components/DashboardElecRank.vue new file mode 100644 index 0000000..b1f96bc --- /dev/null +++ b/src/views/dashboard/components/DashboardElecRank.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/src/views/dashboard/components/DashboardElecTrends.vue b/src/views/dashboard/components/DashboardElecTrends.vue new file mode 100644 index 0000000..7a4e9ec --- /dev/null +++ b/src/views/dashboard/components/DashboardElecTrends.vue @@ -0,0 +1,181 @@ + + + + + diff --git a/src/views/dashboard/components/DashboardStat.vue b/src/views/dashboard/components/DashboardStat.vue index f4a3cab..a8d5572 100644 --- a/src/views/dashboard/components/DashboardStat.vue +++ b/src/views/dashboard/components/DashboardStat.vue @@ -41,7 +41,7 @@ const mockData = [ diff --git a/src/views/energyManagement/components/EnergyChart/EnergyChart.vue b/src/views/energyManagement/components/EnergyChart/EnergyChart.vue index fbbf781..97b006a 100644 --- a/src/views/energyManagement/components/EnergyChart/EnergyChart.vue +++ b/src/views/energyManagement/components/EnergyChart/EnergyChart.vue @@ -1,4 +1,5 @@ diff --git a/src/views/energyManagement/components/EnergyReport/EnergyReportSearch.vue b/src/views/energyManagement/components/EnergyReport/EnergyReportSearch.vue index a086252..b294d75 100644 --- a/src/views/energyManagement/components/EnergyReport/EnergyReportSearch.vue +++ b/src/views/energyManagement/components/EnergyReport/EnergyReportSearch.vue @@ -3,13 +3,12 @@ import { ref, onMounted, watch, inject } from "vue"; import { useRoute } from "vue-router"; import useActiveBtn from "@/hooks/useActiveBtn"; import EnergyReportTimeRange from "./EnergyReportTimeRange.vue"; -import { - getDepartmentList, - getAssetFloorList, - getElecTypeList, -} from "@/apis/asset"; +import { getElecTypeList } from "@/apis/asset"; import { getReport, getExcel } from "@/apis/energy"; import { useI18n } from "vue-i18n"; +import useBuildingStore from "@/stores/useBuildingStore"; + +const storeBuild = useBuildingStore(); const { t } = useI18n(); const route = useRoute(); const { tableData, loading } = inject("energy_table_data"); @@ -43,39 +42,16 @@ const { selectedBtn: selectedFloorItems, } = useActiveBtn("multiple"); -const getDepartment = async () => { - const res = await getDepartmentList(); - const dept = res.data.map((d, index) => ({ - ...d, - title: d.name, - key: d.id, - active: index === 0, - })); - setDeptItems(dept); -}; - const getElecType = async () => { const res = await getElecTypeList(); const elecType = res.data.map((d, index) => ({ ...d, title: d.name, - key: d.id, - active: index === 0, + key: d.id })); setElecItems(elecType); }; -const getFloor = async () => { - const res = await getAssetFloorList(); - const Floor = res.data[0]?.floors.map((d, index) => ({ - ...d, - title: d.full_name, - key: d.floor_guid, - active: index === 0, - })); - setFloorItems(Floor); -}; - const onSearch = async () => { loading.value = true; const res = await getReport(formState.value); @@ -124,9 +100,9 @@ watch( ); onMounted(() => { - getDepartment(); + setDeptItems(storeBuild.deptList); + setFloorItems(storeBuild.floorList); getElecType(); - getFloor(); }); diff --git a/src/views/history/components/HistorySearch.vue b/src/views/history/components/HistorySearch.vue index 031880e..7e49339 100644 --- a/src/views/history/components/HistorySearch.vue +++ b/src/views/history/components/HistorySearch.vue @@ -26,6 +26,13 @@ import dayjs from "dayjs"; const { searchParams, changeParams } = useSearchParam(); const store = useBuildingStore(); +// 選部門 +const { + items: sysDeptItems, + changeActiveBtn: changeDeptActiveBtn, + setItems: setDeptItems, + selectedBtn: selectedDeptItems, +} = useActiveBtn("multiple"); // 選大類 const { items: sysMainTagItems, @@ -40,6 +47,13 @@ const { setItems: setSysItems, selectedBtn: selectedSysItems, } = useActiveBtn(); +// 設定點位 +const { + items: points, + changeActiveBtn: changeActivePoint, + setItems: setPoints, + selectedBtn: selectedPoints, +} = useActiveBtn("multiple"); watch( () => store.mainSys, @@ -60,11 +74,13 @@ watch( () => selectedMainSysItems, (newVal, oldVal) => { setSysItems( - store.subSys.filter((s) => s.main_system_tag === newVal.value?.key).map(({ full_name, sub_system_tag }, index) => ({ - title: full_name, - key: sub_system_tag, - active: index === 0, - })) + store.subSys + .filter((s) => s.main_system_tag === newVal.value?.key) + .map(({ full_name, sub_system_tag }, index) => ({ + title: full_name, + key: sub_system_tag, + active: index === 0, + })) ); }, { @@ -93,14 +109,6 @@ watch( } ); -// 設定點位 -const { - items: points, - changeActiveBtn: changeActivePoint, - setItems: setPoints, - selectedBtn: selectedPoints, -} = useActiveBtn("multiple"); - const getPoint = async (deviceList) => { const res = await getHistoryPoints(deviceList); setPoints( @@ -126,6 +134,19 @@ watch( } ); +watch( + selectedDeptItems, + (newVal, oldVal) => { + changeParams({ + ...searchParams.value, + Dept: newVal.map((d) => d.id), + }); + }, + { + immediate: true, + } +); + const form = ref(null); watch(searchParams, (newVal, oldValue) => { @@ -149,6 +170,13 @@ onMounted(() => { active: index === 0, })) ); + setDeptItems( + store.deptList.map((d, index) => ({ + ...d, + title: d.name, + key: d.id, + })) + ); }); onBeforeMount(() => { @@ -159,6 +187,20 @@ onBeforeMount(() => {