Merge branch 'main' into feature/system
@ -1,3 +1,3 @@
|
|||||||
VITE_API_BASEURL = "http://192.168.0.206:8060"
|
VITE_API_BASEURL = "http://192.168.0.206:8060"
|
||||||
VITE_FILE_API_BASEURL = ""
|
VITE_FILE_API_BASEURL = "http://192.168.0.206:8088"
|
||||||
VITE_FORGE_BASEURL = "http://localhost:5173"
|
VITE_FORGE_BASEURL = "http://localhost:5173"
|
@ -1,3 +1,3 @@
|
|||||||
VITE_API_BASEURL = "http://220.132.206.5:8060"
|
VITE_API_BASEURL = "http://192.168.0.206:8060"
|
||||||
VITE_FILE_API_BASEURL = "http://220.132.206.5:8085/file"
|
VITE_FILE_API_BASEURL = "http://192.168.0.206:8088"
|
||||||
VITE_FORGE_BASEURL = "http://202.39.218.221:8080/file/netzero"
|
VITE_FORGE_BASEURL = "http://202.39.218.221:8080/file/netzero"
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@ -1,221 +1,79 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import { ref, onMounted, onUnmounted } from "vue";
|
||||||
ref,
|
|
||||||
onMounted,
|
|
||||||
defineProps,
|
|
||||||
computed,
|
|
||||||
onUnmounted,
|
|
||||||
watch,
|
|
||||||
provide,
|
|
||||||
} from "vue";
|
|
||||||
import { getUrn, getAccessToken } from "@/apis/forge";
|
|
||||||
import { twMerge } from "tailwind-merge";
|
|
||||||
import hexToRgb from "@/util/hexToRgb";
|
|
||||||
import getModalPosition from "@/util/getModalPosition";
|
|
||||||
import useSystemStatusByBaja from "@/hooks/baja/useSystemStatusByBaja";
|
|
||||||
import ForgeInfoModal from "./ForgeInfoModal.vue";
|
|
||||||
import useAlarmStore from "@/stores/useAlarmStore";
|
|
||||||
|
|
||||||
const props = defineProps({
|
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||||
initialData: Object,
|
|
||||||
cubeStyle: {
|
|
||||||
type: Object,
|
|
||||||
default: {
|
|
||||||
right: 25,
|
|
||||||
top: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const heat_bar_isShow = ref(false);
|
|
||||||
const updateHeatBarIsShow = (isShow) => {
|
|
||||||
heat_bar_isShow.value = isShow;
|
|
||||||
};
|
|
||||||
|
|
||||||
const {
|
|
||||||
subscribeData,
|
|
||||||
visibleDbid,
|
|
||||||
updateDbidPosition,
|
|
||||||
hideAllObjects,
|
|
||||||
updateForgeViewer,
|
|
||||||
urn,
|
|
||||||
loadModel,
|
|
||||||
updateInitialData,
|
|
||||||
subComponents,
|
|
||||||
} = useSystemStatusByBaja(updateHeatBarIsShow);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.initialData,
|
|
||||||
(newValue) => {
|
|
||||||
newValue && updateInitialData(newValue);
|
|
||||||
},
|
|
||||||
{
|
|
||||||
deep: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const store = useAlarmStore();
|
|
||||||
const subscribeDataWithErrorMsg = computed(() => {
|
|
||||||
let data = { ...subscribeData.value };
|
|
||||||
|
|
||||||
for (let [key, value] of Object.entries(subscribeData.value)) {
|
|
||||||
const alarm = store.alarmData.find(
|
|
||||||
({ device_number }) => device_number === key
|
|
||||||
);
|
|
||||||
data[key].alarmMsg = alarm ? alarm.msg : "";
|
|
||||||
}
|
|
||||||
console.log("baja update data: ", data);
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
|
|
||||||
const forgeDom = ref(null);
|
const forgeDom = ref(null);
|
||||||
|
let viewer = null;
|
||||||
|
|
||||||
|
// 初始化 Forge Viewer
|
||||||
const initViewer = (container) => {
|
const initViewer = (container) => {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
Autodesk.Viewing.Initializer({ getAccessToken }, function () {
|
Autodesk.Viewing.Initializer(
|
||||||
const config = {
|
{
|
||||||
extensions: ["Autodesk.DataVisualization", "Autodesk.DocumentBrowser"],
|
env: "Local",
|
||||||
};
|
language: "en",
|
||||||
let viewer = new Autodesk.Viewing.GuiViewer3D(container, config);
|
},
|
||||||
Autodesk.Viewing.Private.InitParametersSetting.alpha = true;
|
function () {
|
||||||
viewer.start();
|
const config = {
|
||||||
resolve(viewer);
|
extensions: [
|
||||||
});
|
"Autodesk.DataVisualization",
|
||||||
|
"Autodesk.DocumentBrowser",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
viewer = new Autodesk.Viewing.GuiViewer3D(container, config);
|
||||||
|
Autodesk.Viewing.Private.InitParametersSetting.alpha = true;
|
||||||
|
viewer.start();
|
||||||
|
viewer.setGroundShadow(false);
|
||||||
|
viewer.impl.renderer().setClearAlpha(0);
|
||||||
|
viewer.impl.glrenderer().setClearColor(0xffffff, 0);
|
||||||
|
viewer.impl.invalidate(true);
|
||||||
|
resolve(viewer);
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const initForge = () => {
|
// 使用本地 .svf 文件加載模型
|
||||||
getUrn().then((res) => {
|
const loadModel = (filePath) => {
|
||||||
if (!res.isSuccess) return;
|
return new Promise((resolve, reject) => {
|
||||||
urn.value = res.data[0].urn_3D;
|
viewer.loadModel(
|
||||||
initViewer(forgeDom.value).then((viewer) => {
|
filePath,
|
||||||
loadModel(viewer, res.data[0].urn_3D).then(() => {
|
{},
|
||||||
viewer.addEventListener(
|
(model) => {
|
||||||
Autodesk.Viewing.GEOMETRY_LOADED_EVENT,
|
viewer.impl.invalidate(true);
|
||||||
async function () {
|
viewer.fitToView();
|
||||||
console.log(
|
resolve(model);
|
||||||
"Autodesk.Viewing.GEOMETRY_LOADED_EVENT",
|
console.log("模型加載完成");
|
||||||
viewer.isLoadDone()
|
},
|
||||||
);
|
reject
|
||||||
updateForgeViewer(viewer);
|
);
|
||||||
|
|
||||||
const tree = viewer.model.getData().instanceTree;
|
|
||||||
hideAllObjects(tree, visibleDbid.value);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
viewer.addEventListener(
|
|
||||||
Autodesk.Viewing.CAMERA_CHANGE_EVENT,
|
|
||||||
function (e) {
|
|
||||||
viewer.isLoadDone() &&
|
|
||||||
updateDbidPosition(this, subscribeData.value);
|
|
||||||
console.log(
|
|
||||||
"camera position changed: ",
|
|
||||||
NOP_VIEWER.navigation.getTarget(),
|
|
||||||
e.camera.position
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
console.log("Forge 加載");
|
console.log("Forge 加載");
|
||||||
initForge();
|
await initViewer(forgeDom.value);
|
||||||
|
const filePath = `${FILE_BASEURL}/upload/forge/0.svf`;
|
||||||
|
loadModel(filePath);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 傳遞目前點擊資訊
|
|
||||||
const currentInfoModalData = ref(null);
|
|
||||||
const isMobile = (pointerType) => {
|
|
||||||
return pointerType !== "mouse"; // is desktop
|
|
||||||
};
|
|
||||||
const getCurrentInfoModalData = (e, position, value) => {
|
|
||||||
const mobile = isMobile(e.pointerType);
|
|
||||||
currentInfoModalData.value = {
|
|
||||||
initPos: mobile
|
|
||||||
? { left: `50%`, top: `50%` }
|
|
||||||
: { left: `${position.left}px`, top: `${position.top}px` },
|
|
||||||
value,
|
|
||||||
isMobile: mobile,
|
|
||||||
};
|
|
||||||
forge_info_modal.showModal();
|
|
||||||
};
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
console.log("Forge 銷毀");
|
console.log("Forge 銷毀");
|
||||||
console.log("sub", subComponents);
|
if (viewer) {
|
||||||
subComponents.value?.unsubscribeAll();
|
viewer.tearDown();
|
||||||
subComponents.value?.detach();
|
viewer.finish();
|
||||||
updateForgeViewer(null);
|
viewer = null;
|
||||||
NOP_VIEWER.tearDown();
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ForgeInfoModal :data="currentInfoModalData" />
|
<div
|
||||||
<div
|
id="forge-preview"
|
||||||
id="forge-preview"
|
ref="forgeDom"
|
||||||
ref="forgeDom"
|
class="relative w-full h-full min-h-full"
|
||||||
class="relative w-full h-full min-h-full"
|
></div>
|
||||||
>
|
|
||||||
<div v-show="heat_bar_isShow" class="absolute z-10 heatbar">
|
|
||||||
<div class="w-40 flex justify-between text-[10px] mb-1">
|
|
||||||
<span class="text-gradient-1">10 °C</span>
|
|
||||||
<span class="text-gradient-2">20 °C</span>
|
|
||||||
<span class="text-gradient-3">30 °C</span>
|
|
||||||
<span class="text-gradient-4">40 °C</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="w-40 h-3"
|
|
||||||
style="
|
|
||||||
background: linear-gradient(
|
|
||||||
to right,
|
|
||||||
#0000ff 0%,
|
|
||||||
#00ff00 33%,
|
|
||||||
#ffff00 66%,
|
|
||||||
#ff0000 100%
|
|
||||||
);
|
|
||||||
"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
<!-- label -->
|
|
||||||
<!-- https://github.com/augustogoncalves/forge-plant-operation/blob/master/forgeSample/wwwroot/js/iconExtension.js -->
|
|
||||||
<!-- https://github.com/dukedhx/viewer-iot-react-feathersjs/blob/master/src/client/iconExtension.js -->
|
|
||||||
|
|
||||||
<label
|
|
||||||
v-for="(value, key) in subscribeDataWithErrorMsg"
|
|
||||||
:key="key"
|
|
||||||
:data-dbid="value.forge_dbid"
|
|
||||||
:class="
|
|
||||||
twMerge(
|
|
||||||
`after:border-t-[${value.currentColor}]`,
|
|
||||||
'flex items-center justify-center h-12 -translate-x-1/2 -translate-y-1/5 absolute z-50 px-5 py-4 text-center rounded-md text-lg border-2 border-white',
|
|
||||||
'after:absolute after:border-t-[10px] after:border-x-[12px] after:border-x-transparent after:-bottom-[8px] after:left-1/2 after:-translate-x-1/2 ',
|
|
||||||
'before:absolute before:border-t-[12px] before:border-x-[14px] before:border-x-transparent before:-bottom-[12px] before:left-1/2 before:-translate-x-1/2 before:border-white'
|
|
||||||
)
|
|
||||||
"
|
|
||||||
:style="{
|
|
||||||
left: `${Math.floor(value.device_coordinate_3d.x)}px`,
|
|
||||||
top: `${Math.floor(value.device_coordinate_3d.y) - 100}px`,
|
|
||||||
display: value.is_show,
|
|
||||||
backgroundColor: value.currentColor,
|
|
||||||
}"
|
|
||||||
@click.prevent="
|
|
||||||
(e) =>
|
|
||||||
getCurrentInfoModalData(
|
|
||||||
e,
|
|
||||||
{ left: e.clientX, top: e.clientY },
|
|
||||||
value
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span class="mr-2">{{ value.full_name }}</span>
|
|
||||||
<span v-if="value.alarmMsg">{{ value.alarmMsg }}</span>
|
|
||||||
<span v-else>{{ value.show_value }}</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="css">
|
<style lang="css">
|
||||||
@ -228,17 +86,4 @@ onUnmounted(() => {
|
|||||||
bottom: 200px;
|
bottom: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.viewcubeWrapper {
|
|
||||||
right: v-bind("`${props.cubeStyle.right}%`") !important;
|
|
||||||
top: v-bind("`${props.cubeStyle.top}%`") !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.homeViewWrapper {
|
|
||||||
transform: scale(1.5) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.heatbar {
|
|
||||||
right: v-bind("`${props.cubeStyle.right + 2}%`") !important;
|
|
||||||
top: 0% !important;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -51,7 +51,7 @@ const mockData = ref([
|
|||||||
<div class="w-20">
|
<div class="w-20">
|
||||||
<img
|
<img
|
||||||
class="w-14 p-2 m-auto"
|
class="w-14 p-2 m-auto"
|
||||||
:src="`./src/assets/img/icon/${item.icon}.png`"
|
:src="`./icon/${item.icon}.png`"
|
||||||
alt="icon"
|
alt="icon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -80,7 +80,7 @@ const getProgressValue = (group) => {
|
|||||||
<span>{{ group[1].value }}</span>
|
<span>{{ group[1].value }}</span>
|
||||||
</div>
|
</div>
|
||||||
<progress
|
<progress
|
||||||
class="progress progress-error"
|
class="progress [&::-webkit-progress-value]:bg-red-600 [&::-moz-progress-bar]:bg-red-600"
|
||||||
:value="getProgressValue(group)"
|
:value="getProgressValue(group)"
|
||||||
max="100"
|
max="100"
|
||||||
size=""
|
size=""
|
||||||
|
@ -2,39 +2,37 @@
|
|||||||
import ImmediateDemandChart from "./components/ImmediateDemandChart.vue";
|
import ImmediateDemandChart from "./components/ImmediateDemandChart.vue";
|
||||||
import ElecConsumption from "./components/ElecConsumption.vue";
|
import ElecConsumption from "./components/ElecConsumption.vue";
|
||||||
import UsageInformation from "./components/UsageInformation.vue";
|
import UsageInformation from "./components/UsageInformation.vue";
|
||||||
import ElectricityBillChart from "./components/ElectricityBillChart.vue";
|
import MonthlyElecBillChart from "./components/MonthlyElecBillChart.vue";
|
||||||
|
import CarbonEmissionChart from "./components/CarbonEmissionChart.vue";
|
||||||
import BillingDegreeChart from "./components/BillingDegreeChart.vue";
|
import BillingDegreeChart from "./components/BillingDegreeChart.vue";
|
||||||
|
import IntervalBillChart from "./components/IntervalBillChart.vue";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="grid gap-4 grid-cols-5 mb-4">
|
<div class="flex flex-wrap items-center mb-4">
|
||||||
<div class="col-span-2">
|
<div class="w-full xl:w-5/12 lg:w-1/2">
|
||||||
<ElecConsumption />
|
<ElecConsumption />
|
||||||
</div>
|
|
||||||
<div class="col-span-3">
|
|
||||||
<ImmediateDemandChart />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="grid gap-4 grid-cols-3 mb-4">
|
<div class="w-full xl:w-7/12 lg:w-1/2">
|
||||||
<div class="col-span-1">
|
<ImmediateDemandChart />
|
||||||
<UsageInformation />
|
|
||||||
</div>
|
|
||||||
<div class="col-span-1">
|
|
||||||
<ElectricityBillChart />
|
|
||||||
</div>
|
|
||||||
<div class="col-span-1">
|
|
||||||
<BillingDegreeChart />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="grid gap-4 grid-cols-3">
|
<div class="w-full xl:w-1/3 px-3">
|
||||||
<div class="col-span-1">
|
<UsageInformation />
|
||||||
<BillingDegreeChart />
|
|
||||||
</div>
|
|
||||||
<div class="col-span-2">
|
|
||||||
<ElectricityBillChart />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="w-full xl:w-1/3 px-3">
|
||||||
|
<MonthlyElecBillChart />
|
||||||
|
</div>
|
||||||
|
<div class="w-full xl:w-1/3 px-3">
|
||||||
|
<CarbonEmissionChart />
|
||||||
|
</div>
|
||||||
|
<div class="w-full xl:w-1/3 px-3">
|
||||||
|
<BillingDegreeChart />
|
||||||
|
</div>
|
||||||
|
<div class="w-full xl:w-2/3 px-3">
|
||||||
|
<IntervalBillChart />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid gap-4 grid-cols-3"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
@ -6,81 +6,101 @@ const defaultChartOption = ref({
|
|||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: "axis",
|
trigger: "axis",
|
||||||
axisPointer: {
|
axisPointer: {
|
||||||
type: "shadow"
|
type: "shadow",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
data: ['尖峰', '半尖峰', '離峰度數'],
|
data: ["尖峰", "半尖峰", "離峰度數"],
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: "#ffffff",
|
color: "#ffffff",
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
},
|
},
|
||||||
orient: "horizontal",
|
orient: "horizontal",
|
||||||
bottom: "0%",
|
bottom: "0%",
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
top: '5%',
|
top: "5%",
|
||||||
left: '0%',
|
left: "0%",
|
||||||
right: '0%',
|
right: "0%",
|
||||||
bottom: '10%',
|
bottom: "15%",
|
||||||
containLabel: true
|
containLabel: true,
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: "category",
|
||||||
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
data: [
|
||||||
|
"1月",
|
||||||
|
"2月",
|
||||||
|
"3月",
|
||||||
|
"4月",
|
||||||
|
"5月",
|
||||||
|
"6月",
|
||||||
|
"7月",
|
||||||
|
"8月",
|
||||||
|
"9月",
|
||||||
|
"10月",
|
||||||
|
"11月",
|
||||||
|
"12月",
|
||||||
|
],
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
color: "#ffffff",
|
color: "#ffffff",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
type: 'value',
|
type: "value",
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
color: "#ffffff",
|
color: "#ffffff",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '尖峰',
|
name: "尖峰",
|
||||||
type: 'bar',
|
type: "bar",
|
||||||
stack: 'total',
|
stack: "total",
|
||||||
data: [5000, 5500, 7000, 7500, 9000, 9500, 11000, 11500, 11000, 7500, 6500, 5500],
|
data: [
|
||||||
|
5000, 5500, 7000, 7500, 9000, 9500, 11000, 11500, 11000, 7500, 6500,
|
||||||
|
5500,
|
||||||
|
],
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#3c50e0',
|
color: "#45f4ef",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '半尖峰',
|
name: "半尖峰",
|
||||||
type: 'bar',
|
type: "bar",
|
||||||
stack: 'total',
|
stack: "total",
|
||||||
data: [3000, 3200, 4500, 4800, 5200, 5800, 6000, 6100, 6200, 5300, 4500, 4000],
|
data: [
|
||||||
|
3000, 3200, 4500, 4800, 5200, 5800, 6000, 6100, 6200, 5300, 4500, 4000,
|
||||||
|
],
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#6577f3',
|
color: "#ffd345",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '離峰度數',
|
name: "離峰度數",
|
||||||
type: 'bar',
|
type: "bar",
|
||||||
stack: 'total',
|
stack: "total",
|
||||||
data: [2000, 2500, 3500, 4000, 4500, 5000, 5200, 5300, 5400, 4500, 4000, 3500],
|
data: [
|
||||||
|
2000, 2500, 3500, 4000, 4500, 5000, 5200, 5300, 5400, 4500, 4000, 3500,
|
||||||
|
],
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#8fd0ef',
|
color: "#64ed81",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
//
|
//
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="card bg-slate-800 w-full h-full rounded-md">
|
<div class="bg-slate-800 p-3">
|
||||||
<div class="card-body">
|
<div class="text-white mb-3 text-base">每月計費度數 (kWh)</div>
|
||||||
<h2 class="card-title">每月計費度數 (kWh)</h2>
|
<div class="bar-box">
|
||||||
<BarChart
|
<BarChart
|
||||||
id="billing_degree_chart"
|
id="billing_degree_chart"
|
||||||
class="min-h-[250px]"
|
class="min-h-[200px] w-full h-full"
|
||||||
:option="defaultChartOption"
|
:option="defaultChartOption"
|
||||||
ref="degree_chart"
|
ref="degree_chart"
|
||||||
/>
|
/>
|
||||||
|
@ -0,0 +1,99 @@
|
|||||||
|
<script setup>
|
||||||
|
import BarChart from "@/components/chart/BarChart.vue";
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
|
||||||
|
const defaultChartOption = ref({
|
||||||
|
tooltip: {
|
||||||
|
trigger: "axis",
|
||||||
|
axisPointer: {
|
||||||
|
type: "shadow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ["碳排當量", "減量目標"],
|
||||||
|
textStyle: {
|
||||||
|
color: "#ffffff",
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
|
orient: "horizontal",
|
||||||
|
bottom: "0%",
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: "5%",
|
||||||
|
left: "0%",
|
||||||
|
right: "0%",
|
||||||
|
bottom: "15%",
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: [
|
||||||
|
"1月",
|
||||||
|
"2月",
|
||||||
|
"3月",
|
||||||
|
"4月",
|
||||||
|
"5月",
|
||||||
|
"6月",
|
||||||
|
"7月",
|
||||||
|
"8月",
|
||||||
|
"9月",
|
||||||
|
"10月",
|
||||||
|
"11月",
|
||||||
|
"12月",
|
||||||
|
],
|
||||||
|
axisLabel: {
|
||||||
|
color: "#ffffff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "value",
|
||||||
|
axisLabel: {
|
||||||
|
color: "#ffffff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: "碳排當量",
|
||||||
|
type: "bar",
|
||||||
|
data: [
|
||||||
|
5400, 6500, 7200, 7500, 9800, 9500, 11200, 11500, 11800, 7500, 6500,
|
||||||
|
5500,
|
||||||
|
],
|
||||||
|
itemStyle: {
|
||||||
|
color: "#45f4ef",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "減量目標",
|
||||||
|
type: "bar",
|
||||||
|
data: [
|
||||||
|
5000, 6000, 6000, 7000, 9500, 9000, 10000, 11000, 10000, 7200, 6000,
|
||||||
|
5000,
|
||||||
|
],
|
||||||
|
itemStyle: {
|
||||||
|
color: "#ffd345",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="bg-slate-800 p-3">
|
||||||
|
<div class="text-white mb-3 text-base">
|
||||||
|
每月碳排當量 (kgCO2e) 與減量目標
|
||||||
|
</div>
|
||||||
|
<div class="bar-box">
|
||||||
|
<BarChart
|
||||||
|
id="electricity_bill_chart"
|
||||||
|
class="min-h-[200px] w-full h-full"
|
||||||
|
:option="defaultChartOption"
|
||||||
|
ref="bill_chart"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -59,19 +59,34 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="card bg-gray-800 h-full rounded-sm">
|
<div class="p-3">
|
||||||
<div class="card-body">
|
<h2 class="text text-lg text-white mb-5 relative">用電即時分佈</h2>
|
||||||
<h2 class="card-title relative mb-4">用電即時分佈</h2>
|
<div class="chart-container">
|
||||||
<div class="chart-container">
|
<div ref="chartDiv" class="w-full min-h-[190px] h-full"></div>
|
||||||
<div ref="chartDiv" class="w-full min-h-[250px]"></div>
|
</div>
|
||||||
</div>
|
<div class="text-sm mt-3.5">
|
||||||
|
<ul class="flex flex-wrap items-center text-white">
|
||||||
|
<li class="pr-5 relative z-20">
|
||||||
|
<span class="pr-3.5">總用電 (kWh)</span>
|
||||||
|
<span class="pr-3.5">160.05</span>
|
||||||
|
</li>
|
||||||
|
<li class="pr-5 relative z-20">
|
||||||
|
<span class="pr-3.5">綠電 (kWh)</span>
|
||||||
|
<span class="pr-3.5">39.50</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.card-title::after {
|
.text::after {
|
||||||
@apply absolute -bottom-2 left-0 h-[1px] w-[60%] bg-slate-400;
|
@apply absolute -bottom-2.5 left-0 block w-3/5 h-[1px] bg-slate-600;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
ul li:last-child:after {
|
||||||
|
@apply absolute top-0 bottom-0 left-full block w-full h-[1px] bg-slate-600 m-auto z-10;
|
||||||
content: "";
|
content: "";
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import BarChart from "@/components/chart/BarChart.vue";
|
|
||||||
import { ref, onMounted } from "vue";
|
|
||||||
|
|
||||||
const defaultChartOption = ref({
|
|
||||||
tooltip: {
|
|
||||||
trigger: "axis",
|
|
||||||
axisPointer: {
|
|
||||||
type: "shadow"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
data: ['基本電費', '流動電費'],
|
|
||||||
textStyle: {
|
|
||||||
color: "#ffffff",
|
|
||||||
fontSize: 16,
|
|
||||||
},
|
|
||||||
orient: "horizontal",
|
|
||||||
bottom: "0%",
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
top: '5%',
|
|
||||||
left: '0%',
|
|
||||||
right: '0%',
|
|
||||||
bottom: '10%',
|
|
||||||
containLabel: true
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
|
||||||
axisLabel: {
|
|
||||||
color: "#ffffff",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
axisLabel: {
|
|
||||||
color: "#ffffff",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '基本電費',
|
|
||||||
type: 'bar',
|
|
||||||
stack: 'total',
|
|
||||||
data: [5000, 5500, 7000, 7500, 9000, 9500, 11000, 11500, 11000, 7500, 6500, 5500],
|
|
||||||
itemStyle: {
|
|
||||||
color: '#37c640',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '流動電費',
|
|
||||||
type: 'bar',
|
|
||||||
stack: 'total',
|
|
||||||
data: [15000, 16000, 20000, 21000, 25000, 26000, 30000, 31000, 35000, 27600, 16500, 15000],
|
|
||||||
itemStyle: {
|
|
||||||
color: '#8ee894',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
//
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="card bg-slate-800 w-full h-full rounded-md">
|
|
||||||
<div class="card-body">
|
|
||||||
<h2 class="card-title">每月電費分析</h2>
|
|
||||||
<BarChart
|
|
||||||
id="electricity_bill_chart"
|
|
||||||
class="min-h-[250px]"
|
|
||||||
:option="defaultChartOption"
|
|
||||||
ref="bill_chart"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
@ -113,19 +113,29 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="card bg-slate-700 h-full relative rounded-sm">
|
<div class="p-3">
|
||||||
<div class="card-body">
|
<div class="flex text-white mb-5">
|
||||||
<h2 class="card-title flex justify-between">
|
<div class="flex items-end text-base relative text mr-32">
|
||||||
<div class="title">即時需量<span>279.09</span>Kw</div>
|
即時需量
|
||||||
</h2>
|
<span class="text-2xl px-2.5">245.48 kw</span>
|
||||||
<LineChart
|
</div>
|
||||||
id="immediate_demand_chart"
|
<div class="flex items-end text-base">
|
||||||
class="min-h-[250px]"
|
平均需量
|
||||||
:option="defaultChartOption"
|
<span class="text-2xl px-2.5">230.8 kw</span>
|
||||||
ref="demand_chart"
|
</div>
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
<LineChart
|
||||||
|
id="immediate_demand_chart"
|
||||||
|
class="w-full h-full min-h-[220px]"
|
||||||
|
:option="defaultChartOption"
|
||||||
|
ref="demand_chart"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped>
|
||||||
|
.text:after {
|
||||||
|
@apply absolute top-0 -bottom-2.5 left-full block w-28 h-[1px] bg-slate-600 m-auto z-10;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
111
src/views/energyManagement/components/IntervalBillChart.vue
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
<script setup>
|
||||||
|
import BarChart from "@/components/chart/BarChart.vue";
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
|
||||||
|
const generateDateRange = () => {
|
||||||
|
const dates = [];
|
||||||
|
for (let day = 1; day <= 15; day++) {
|
||||||
|
const formattedDay = day < 10 ? `0${day}` : day;
|
||||||
|
dates.push(`11 / ${formattedDay}`);
|
||||||
|
}
|
||||||
|
return dates;
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultChartOption = ref({
|
||||||
|
tooltip: {
|
||||||
|
trigger: "axis",
|
||||||
|
axisPointer: {
|
||||||
|
type: "shadow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ["尖峰", "半尖峰", "離峰度數"],
|
||||||
|
textStyle: {
|
||||||
|
color: "#ffffff",
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
|
orient: "horizontal",
|
||||||
|
bottom: "0%",
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: "5%",
|
||||||
|
left: "0%",
|
||||||
|
right: "0%",
|
||||||
|
bottom: "10%",
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: generateDateRange(),
|
||||||
|
axisLabel: {
|
||||||
|
color: "#ffffff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "value",
|
||||||
|
axisLabel: {
|
||||||
|
color: "#ffffff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: "尖峰",
|
||||||
|
type: "bar",
|
||||||
|
stack: "total",
|
||||||
|
data: [
|
||||||
|
5000, 5500, 7000, 7500, 9000, 9500, 11000, 11500, 11000, 7500, 6500,
|
||||||
|
5500, 6000, 6200, 5800,
|
||||||
|
],
|
||||||
|
itemStyle: {
|
||||||
|
color: "#3c50e0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "半尖峰",
|
||||||
|
type: "bar",
|
||||||
|
stack: "total",
|
||||||
|
data: [
|
||||||
|
3000, 3200, 4500, 4800, 5200, 5800, 6000, 6100, 6200, 5300, 4500, 4000,
|
||||||
|
4200, 4300, 4100,
|
||||||
|
],
|
||||||
|
itemStyle: {
|
||||||
|
color: "#6577f3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "離峰度數",
|
||||||
|
type: "bar",
|
||||||
|
stack: "total",
|
||||||
|
data: [
|
||||||
|
2000, 2500, 3500, 4000, 4500, 5000, 5200, 5300, 5400, 4500, 4000, 3500,
|
||||||
|
3700, 3800, 3600,
|
||||||
|
],
|
||||||
|
itemStyle: {
|
||||||
|
color: "#8fd0ef",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="bg-slate-700 p-3">
|
||||||
|
<div class="text-white mb-3 text-base">
|
||||||
|
區間計費度數 2024 / 11 / 01 ~ 2024 / 11 / 15
|
||||||
|
</div>
|
||||||
|
<div class="bar-box">
|
||||||
|
<BarChart
|
||||||
|
id="billing_degree_chart"
|
||||||
|
class="min-h-[200px] w-full h-full"
|
||||||
|
:option="defaultChartOption"
|
||||||
|
ref="degree_chart"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
112
src/views/energyManagement/components/MonthlyElecBillChart.vue
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
<script setup>
|
||||||
|
import BarChart from "@/components/chart/BarChart.vue";
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
|
||||||
|
const defaultChartOption = ref({
|
||||||
|
tooltip: {
|
||||||
|
trigger: "axis",
|
||||||
|
axisPointer: {
|
||||||
|
type: "shadow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: [ "流動電費","基本電費", "電費總額"],
|
||||||
|
textStyle: {
|
||||||
|
color: "#ffffff",
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
|
orient: "horizontal",
|
||||||
|
bottom: "0%",
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: "5%",
|
||||||
|
left: "0%",
|
||||||
|
right: "0%",
|
||||||
|
bottom: "15%",
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: [
|
||||||
|
"1月",
|
||||||
|
"2月",
|
||||||
|
"3月",
|
||||||
|
"4月",
|
||||||
|
"5月",
|
||||||
|
"6月",
|
||||||
|
"7月",
|
||||||
|
"8月",
|
||||||
|
"9月",
|
||||||
|
"10月",
|
||||||
|
"11月",
|
||||||
|
"12月",
|
||||||
|
],
|
||||||
|
axisLabel: {
|
||||||
|
color: "#ffffff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "value",
|
||||||
|
axisLabel: {
|
||||||
|
color: "#ffffff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: "流動電費",
|
||||||
|
type: "bar",
|
||||||
|
stack: "total",
|
||||||
|
data: [
|
||||||
|
15000, 16000, 20000, 21000, 25000, 26000, 30000, 31000, 35000, 27600,
|
||||||
|
16500, 15000,
|
||||||
|
],
|
||||||
|
itemStyle: {
|
||||||
|
color: "#45f4ef",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "基本電費",
|
||||||
|
type: "bar",
|
||||||
|
stack: "total",
|
||||||
|
data: [
|
||||||
|
5000, 5500, 7000, 7500, 9000, 9500, 11000, 11500, 11000, 7500, 6500,
|
||||||
|
5500,
|
||||||
|
],
|
||||||
|
itemStyle: {
|
||||||
|
color: "#ffd345",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "電費總額",
|
||||||
|
type: "bar",
|
||||||
|
stack: "total",
|
||||||
|
data: [
|
||||||
|
3000, 3000, 4000, 5000, 12000, 17000, 20000, 20000, 12000, 12000, 5000,
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
itemStyle: {
|
||||||
|
color: "#64ed81",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="bg-slate-800 p-3">
|
||||||
|
<div class="text-white mb-3 text-base">每月用電分析</div>
|
||||||
|
<div class="bar-box">
|
||||||
|
<BarChart
|
||||||
|
id="electricity_bill_chart"
|
||||||
|
class="min-h-[200px] w-full h-full"
|
||||||
|
:option="defaultChartOption"
|
||||||
|
ref="bill_chart"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -1,35 +1,60 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
|
// 假資料
|
||||||
|
const dataItems = ref([
|
||||||
|
{ title: "今年電費累計(元)", data: "3,255,458" },
|
||||||
|
{ title: "區間電費(元)", data: "205,110" },
|
||||||
|
{ title: "今年碳排當量累計(公斤)", data: "455,128" },
|
||||||
|
{ title: "區間碳排當量", time: "2023-11-01~2023-11-19", data: "25,351" },
|
||||||
|
{ title: "今年用電度數(kWh)", data: "864,830" },
|
||||||
|
{ title: "區間用電度數(kWh)", time: "2023-11-01~2023-11-19", data: "50,355" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 背景顏色處理
|
||||||
|
const getItemBackground = (index) => {
|
||||||
|
return index === 0 || index === 3 || index === 4
|
||||||
|
? "bg-slate-600"
|
||||||
|
: "bg-slate-800";
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div className="stats w-full h-[48%] p-2 mb-4 bg-slate-900 rounded-lg border border-cyan-200/20 shadow-md shadow-cyan-500/20">
|
<div class="six-data">
|
||||||
<!-- 電壓資訊 -->
|
<div
|
||||||
<div className="stat place-items-start">
|
v-for="(item, index) in dataItems"
|
||||||
<div className="stat-title text-gray-200 3xl:text-[2rem]">今年電費總計 (元)</div>
|
:key="index"
|
||||||
<div className="stat-value text-success text-5xl 3xl:text-[6rem]">516,519</div>
|
:class="
|
||||||
<div className="stat-desc text-gray-400 3xl:text-[2rem]">2024-01-01 ~ 2024-08-08</div>
|
twMerge(
|
||||||
</div>
|
'item w-1/2 py-0 px-5 h-[85px] text-white flex justify-center flex-col',
|
||||||
<div className="stat place-items-start">
|
index == 0 || index == 3 || index == 4
|
||||||
<div className="stat-title text-gray-200 3xl:text-[2rem]">區間電費總計 (元)</div>
|
? 'bg-slate-800'
|
||||||
<div className="stat-value text-success text-5xl 3xl:text-[6rem]">22,432</div>
|
: 'bg-slate-700'
|
||||||
<div className="stat-desc text-gray-400 3xl:text-[2rem]">2024-07-01 ~ 2024-07-31</div>
|
)
|
||||||
</div>
|
"
|
||||||
</div>
|
>
|
||||||
|
<div class="title">{{ item.title }}</div>
|
||||||
<div className="stats w-full h-[48%] p-2 mb-4 bg-slate-900 rounded-lg border border-cyan-200/20 shadow-md shadow-cyan-500/20">
|
<div v-if="item.time" class="time">{{ item.time }}</div>
|
||||||
<!-- 電流資訊 -->
|
<div class="data">{{ item.data }}</div>
|
||||||
<div className="stat place-items-start">
|
|
||||||
<div className="stat-title text-gray-200 3xl:text-[2rem]">今年用電度數 (kWh)</div>
|
|
||||||
<div className="stat-value text-success text-5xl 3xl:text-[6rem]">172,173</div>
|
|
||||||
<div className="stat-desc text-gray-400 3xl:text-[2rem]">2024-01-01 ~ 2024-08-08</div>
|
|
||||||
</div>
|
|
||||||
<div className="stat place-items-start">
|
|
||||||
<div className="stat-title text-gray-200 3xl:text-[2rem]">區間用電度數 (kWh)</div>
|
|
||||||
<div className="stat-value text-success text-5xl 3xl:text-[6rem]">7,477</div>
|
|
||||||
<div className="stat-desc text-gray-400 3xl:text-[2rem]">2024-07-01 ~ 2024-07-31</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped>
|
||||||
|
.six-data {
|
||||||
|
@apply flex flex-wrap mb-2.5;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
@apply text-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
@apply text-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data {
|
||||||
|
@apply text-2xl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -132,7 +132,7 @@ const changeSelected = (Device_list, renew = false) => {
|
|||||||
:icon="['fas', 'search']"
|
:icon="['fas', 'search']"
|
||||||
class="w-6 h-6 mr-2 text-info"
|
class="w-6 h-6 mr-2 text-info"
|
||||||
/>
|
/>
|
||||||
<input type="text" :placeholder="t('buttton.enter_text')"
|
<input type="text" :placeholder="t('button.enter_text')"
|
||||||
class="text-white bg-transparent w-full" />
|
class="text-white bg-transparent w-full" />
|
||||||
</label>
|
</label>
|
||||||
<template v-for="d in deviceData" :key="d.building_tag">
|
<template v-for="d in deviceData" :key="d.building_tag">
|
||||||
|
@ -16,7 +16,7 @@ export default defineConfig({
|
|||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
'/upload': {
|
'/upload': {
|
||||||
target: "http://220.132.206.5:8008",
|
target: "http://192.168.0.206:8088/upload",
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
},
|
},
|
||||||
|