2D/3D暫時設定 | VITE_FORGE_BASEURL改成VITE_FILE_API_BASEURL | 首頁語言更新
This commit is contained in:
parent
14187ad9bc
commit
5d02cffcf4
@ -1,4 +1,4 @@
|
||||
VITE_API_BASEURL = "https://ibms-cvilux-api.production.mjmtech.com.tw"
|
||||
VITE_FILE_API_BASEURL = "https://cgems.cvilux-group.com:8088"
|
||||
VITE_MQTT_BASEURL = "wss://mqttwss.mjm-staging.developers-homelab.net"
|
||||
VITE_FORGE_BASEURL = "https://cgems.cvilux-group.com:8088/dist"
|
||||
# VITE_FORGE_BASEURL = "https://cgems.cvilux-group.com:8088/dist"
|
@ -93,8 +93,8 @@ const createSprites = async (dataVizExtn) => {
|
||||
const DataVizCore = Autodesk.DataVisualization.Core;
|
||||
const viewableType = DataVizCore.ViewableType.SPRITE;
|
||||
let spriteColor = new THREE.Color(0xffffff);
|
||||
const BASEURL = import.meta.env.VITE_FORGE_BASEURL;
|
||||
const spriteIconUrl = `${BASEURL}/hotspot.svg`;
|
||||
const BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||
const spriteIconUrl = `${BASEURL}/dist/hotspot.svg`;
|
||||
const style = new DataVizCore.ViewableStyle(
|
||||
viewableType,
|
||||
spriteColor,
|
||||
|
@ -72,8 +72,8 @@ export default function useForgeSprite() {
|
||||
const DataVizCore = Autodesk.DataVisualization.Core;
|
||||
const viewableType = DataVizCore.ViewableType.SPRITE;
|
||||
let spriteColor = new THREE.Color(0xffffff);
|
||||
const BASEURL = import.meta.env.VITE_FORGE_BASEURL;
|
||||
const spriteIconUrl = `${BASEURL}/hotspot.svg`;
|
||||
const BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||
const spriteIconUrl = `${BASEURL}/dist/hotspot.svg`;
|
||||
const style = new DataVizCore.ViewableStyle(
|
||||
viewableType,
|
||||
spriteColor,
|
||||
|
@ -22,6 +22,8 @@ const formState = ref({
|
||||
floor_guid: "all",
|
||||
department_id: "all",
|
||||
});
|
||||
// 控制顯示2D/3D切換與內容
|
||||
const showForgeArea = ref(true);
|
||||
|
||||
const getEnergyCostData = async (params) => {
|
||||
const res = await getEnergyCost(params);
|
||||
@ -67,18 +69,20 @@ watch(
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
setItems([
|
||||
{
|
||||
title: "2D",
|
||||
key: "2D",
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
title: "3D",
|
||||
key: "3D",
|
||||
active: true,
|
||||
},
|
||||
]);
|
||||
if (showForgeArea.value) {
|
||||
setItems([
|
||||
{
|
||||
title: "2D",
|
||||
key: "2D",
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
title: "3D",
|
||||
key: "3D",
|
||||
active: true,
|
||||
},
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
@ -90,31 +94,45 @@ onUnmounted(() => {
|
||||
<div class="flex flex-wrap items-center">
|
||||
<!-- 建築圖 -->
|
||||
<div class="w-full xl:w-1/3 relative">
|
||||
<ButtonConnectedGroup
|
||||
:items="items"
|
||||
className="btn-xs absolute right-3 top-6 z-20 bg-slate-800 p-0 rounded-lg "
|
||||
:onclick="(e, item) => changeActiveBtn(item)"
|
||||
/>
|
||||
<div class="area-img-box relative">
|
||||
<img
|
||||
alt="build"
|
||||
src="/build_img.jpg"
|
||||
:class="
|
||||
twMerge(
|
||||
'absolute w-full h-full transition-opacity duration-300',
|
||||
selectedBtn?.key == '2D' ? 'opacity-100 z-10' : 'opacity-0 z-0'
|
||||
)
|
||||
"
|
||||
/>
|
||||
<Forge
|
||||
:class="
|
||||
twMerge(
|
||||
'absolute transition-opacity duration-300',
|
||||
selectedBtn?.key == '3D' ? 'opacity-100 z-10' : 'opacity-0 z-0'
|
||||
)
|
||||
"
|
||||
<template v-if="showForgeArea">
|
||||
<ButtonConnectedGroup
|
||||
:items="items"
|
||||
className="btn-xs absolute right-3 top-6 z-20 bg-slate-800 p-0 rounded-lg "
|
||||
:onclick="(e, item) => changeActiveBtn(item)"
|
||||
/>
|
||||
</div>
|
||||
<div class="area-img-box relative">
|
||||
<!-- setting頁面要新增讓他能上傳圖片 -->
|
||||
<img
|
||||
alt="build"
|
||||
src="/build_img.jpg"
|
||||
:class="
|
||||
twMerge(
|
||||
'absolute w-full h-full transition-opacity duration-300',
|
||||
selectedBtn?.key == '2D'
|
||||
? 'opacity-100 z-10'
|
||||
: 'opacity-0 z-0'
|
||||
)
|
||||
"
|
||||
/>
|
||||
<Forge
|
||||
:class="
|
||||
twMerge(
|
||||
'absolute transition-opacity duration-300',
|
||||
selectedBtn?.key == '3D'
|
||||
? 'opacity-100 z-10'
|
||||
: 'opacity-0 z-0'
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<img
|
||||
alt="build"
|
||||
src="/build_img.jpg"
|
||||
class="area-img-box w-full h-[460px] block relative rounded-sm mt-3"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="w-full xl:w-2/3">
|
||||
|
@ -1,10 +1,10 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import { ref, onMounted, watch, computed } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
import BarChart from "@/components/chart/BarChart.vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
const { locale, t } = useI18n();
|
||||
const props = defineProps({
|
||||
energyCostData: {
|
||||
type: Object,
|
||||
@ -14,7 +14,7 @@ const props = defineProps({
|
||||
|
||||
const chartData = ref([]); // 初始化為空陣列
|
||||
|
||||
const labels = [
|
||||
const labels = computed(() => [
|
||||
t("dashboard.today"),
|
||||
t("dashboard.yesterday"),
|
||||
t("dashboard.this_week"),
|
||||
@ -23,7 +23,7 @@ const labels = [
|
||||
t("dashboard.last_month"),
|
||||
t("dashboard.this_year"),
|
||||
t("dashboard.last_year"),
|
||||
];
|
||||
]);
|
||||
const barWidth = 30; // Set barWidth
|
||||
|
||||
const barChartOptions = ref({
|
||||
@ -33,22 +33,13 @@ const barChartOptions = ref({
|
||||
axisLine: { lineStyle: { color: "#fff" } },
|
||||
},
|
||||
yAxis: { type: "value", show: false },
|
||||
grid: {
|
||||
left: "-10%",
|
||||
right: "0%",
|
||||
bottom: "3%",
|
||||
top: "10%",
|
||||
containLabel: true,
|
||||
},
|
||||
series: [], // 初始化為空陣列
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: { type: "shadow" },
|
||||
formatter: function (params) {
|
||||
let tooltipText = `<div>${params[0].axisValueLabel}</div>`;
|
||||
const filteredParams = params.filter(
|
||||
(item) => item.seriesType === "bar"
|
||||
);
|
||||
const filteredParams = params.filter((item) => item.seriesType === "bar");
|
||||
filteredParams.forEach((item) => {
|
||||
tooltipText += `<div>${item.marker} ${
|
||||
item.value ? item.value : "-"
|
||||
@ -60,178 +51,187 @@ const barChartOptions = ref({
|
||||
},
|
||||
});
|
||||
|
||||
function updateChartData(newEnergyCostData) {
|
||||
if (newEnergyCostData && newEnergyCostData.compare) {
|
||||
// 從 props.energyCostData.compare 中提取資料
|
||||
const compareData = newEnergyCostData.compare;
|
||||
|
||||
// 轉換資料格式
|
||||
chartData.value = [
|
||||
{
|
||||
category: t("dashboard.daily_relative_change"),
|
||||
this: compareData.day.current,
|
||||
last: compareData.day.last,
|
||||
change: compareData.day.percentage,
|
||||
},
|
||||
{
|
||||
category: t("dashboard.weekly_relative_change"),
|
||||
this: compareData.week.current,
|
||||
last: compareData.week.last,
|
||||
change: compareData.week.percentage,
|
||||
},
|
||||
{
|
||||
category: t("dashboard.monthly_relative_change"),
|
||||
this: compareData.month.current,
|
||||
last: compareData.month.last,
|
||||
change: compareData.month.percentage,
|
||||
},
|
||||
{
|
||||
category: t("dashboard.yearly_relative_change"),
|
||||
this: compareData.year.current,
|
||||
last: compareData.year.last,
|
||||
change: compareData.year.percentage,
|
||||
},
|
||||
];
|
||||
|
||||
// 更新 barChartOptions
|
||||
barChartOptions.value = {
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: chartData.value.map((item) => item.category),
|
||||
axisLine: { lineStyle: { color: "#fff" } },
|
||||
},
|
||||
yAxis: { type: "value", show: false },
|
||||
grid: {
|
||||
left: "-10%",
|
||||
right: "1%",
|
||||
bottom: "3%",
|
||||
top: "4%",
|
||||
containLabel: true,
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "當前週期",
|
||||
data: chartData.value.map((item) => item.this),
|
||||
type: "bar",
|
||||
barWidth: barWidth,
|
||||
barGap: "-10%",
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: "#186B80" },
|
||||
{ offset: 1, color: "#50C3E3" },
|
||||
]),
|
||||
shadowBlur: 5,
|
||||
shadowColor: "rgba(0, 0, 0, 0.3)",
|
||||
shadowOffsetY: 2,
|
||||
shadowOffsetX: 5,
|
||||
},
|
||||
z: 3,
|
||||
},
|
||||
{
|
||||
name: "對比週期",
|
||||
data: chartData.value.map((item) => item.last),
|
||||
type: "bar",
|
||||
barWidth: barWidth,
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: "#988F2C" },
|
||||
{ offset: 1, color: "#FFF26D" },
|
||||
]),
|
||||
shadowBlur: 5,
|
||||
shadowColor: "rgba(0, 0, 0, 0.3)",
|
||||
shadowOffsetY: 2,
|
||||
shadowOffsetX: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
// this top
|
||||
z: 6,
|
||||
type: "pictorialBar",
|
||||
symbolPosition: "end",
|
||||
data: chartData.value.map((item) => item.this),
|
||||
symbol: "diamond",
|
||||
symbolOffset: ["-45%", "-50%"],
|
||||
symbolSize: [barWidth, barWidth * 0.5],
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
color: "#50C3E3",
|
||||
},
|
||||
},
|
||||
{
|
||||
// this bot
|
||||
z: 6,
|
||||
type: "pictorialBar",
|
||||
symbolPosition: "start",
|
||||
data: chartData.value.map((item) => item.this),
|
||||
symbol: "diamond",
|
||||
symbolOffset: ["-45%", "50%"],
|
||||
symbolSize: [barWidth, barWidth * 0.5],
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
color: "#50C3E3",
|
||||
},
|
||||
},
|
||||
{
|
||||
// last top
|
||||
z: 3,
|
||||
type: "pictorialBar",
|
||||
symbolPosition: "end",
|
||||
data: chartData.value.map((item) => item.last),
|
||||
symbol: "diamond",
|
||||
symbolOffset: ["45%", "-50%"],
|
||||
symbolSize: [barWidth, barWidth * 0.5],
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
color: "#FFF26D",
|
||||
},
|
||||
},
|
||||
{
|
||||
// last bot
|
||||
z: 3,
|
||||
type: "pictorialBar",
|
||||
symbolPosition: "start",
|
||||
data: chartData.value.map((item) => item.last),
|
||||
symbol: "diamond",
|
||||
symbolOffset: ["45%", "50%"],
|
||||
symbolSize: [barWidth, barWidth * 0.5],
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
color: "#FFF26D",
|
||||
},
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: { type: "shadow" },
|
||||
formatter: function (params) {
|
||||
let tooltipText = `<div>${params[0].axisValueLabel}</div>`;
|
||||
const filteredParams = params.filter(
|
||||
(item) => item.seriesType === "bar"
|
||||
);
|
||||
filteredParams.forEach((item) => {
|
||||
tooltipText += `<div>${item.marker} ${
|
||||
item.value ? item.value : "-"
|
||||
}</div>`;
|
||||
});
|
||||
|
||||
return tooltipText;
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
// 使用 watch 監聽 energyCostData 的變化
|
||||
watch(
|
||||
() => props.energyCostData,
|
||||
(newEnergyCostData) => {
|
||||
if (newEnergyCostData && newEnergyCostData.compare) {
|
||||
// 從 props.energyCostData.compare 中提取資料
|
||||
const compareData = newEnergyCostData.compare;
|
||||
|
||||
// 轉換資料格式
|
||||
chartData.value = [
|
||||
{
|
||||
category: t("dashboard.daily_relative_change"),
|
||||
this: compareData.day.current,
|
||||
last: compareData.day.last,
|
||||
change: compareData.day.percentage,
|
||||
},
|
||||
{
|
||||
category: t("dashboard.weekly_relative_change"),
|
||||
this: compareData.week.current,
|
||||
last: compareData.week.last,
|
||||
change: compareData.week.percentage,
|
||||
},
|
||||
{
|
||||
category: t("dashboard.monthly_relative_change"),
|
||||
this: compareData.month.current,
|
||||
last: compareData.month.last,
|
||||
change: compareData.month.percentage,
|
||||
},
|
||||
{
|
||||
category: t("dashboard.yearly_relative_change"),
|
||||
this: compareData.year.current,
|
||||
last: compareData.year.last,
|
||||
change: compareData.year.percentage,
|
||||
},
|
||||
];
|
||||
|
||||
// 更新 barChartOptions
|
||||
barChartOptions.value = {
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: chartData.value.map((item) => item.category),
|
||||
axisLine: { lineStyle: { color: "#fff" } },
|
||||
},
|
||||
yAxis: { type: "value", show: false },
|
||||
grid: {
|
||||
left: "-10%",
|
||||
right: "0%",
|
||||
bottom: "3%",
|
||||
top: "10%",
|
||||
containLabel: true,
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "當前週期",
|
||||
data: chartData.value.map((item) => item.this),
|
||||
type: "bar",
|
||||
barWidth: barWidth,
|
||||
barGap: "-10%",
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: "#186B80" },
|
||||
{ offset: 1, color: "#50C3E3" },
|
||||
]),
|
||||
shadowBlur: 5,
|
||||
shadowColor: "rgba(0, 0, 0, 0.3)",
|
||||
shadowOffsetY: 2,
|
||||
shadowOffsetX: 5,
|
||||
},
|
||||
z: 3,
|
||||
},
|
||||
{
|
||||
name: "對比週期",
|
||||
data: chartData.value.map((item) => item.last),
|
||||
type: "bar",
|
||||
barWidth: barWidth,
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: "#988F2C" },
|
||||
{ offset: 1, color: "#FFF26D" },
|
||||
]),
|
||||
shadowBlur: 5,
|
||||
shadowColor: "rgba(0, 0, 0, 0.3)",
|
||||
shadowOffsetY: 2,
|
||||
shadowOffsetX: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
// this top
|
||||
z: 6,
|
||||
type: "pictorialBar",
|
||||
symbolPosition: "end",
|
||||
data: chartData.value.map((item) => item.this),
|
||||
symbol: "diamond",
|
||||
symbolOffset: ["-45%", "-50%"],
|
||||
symbolSize: [barWidth, barWidth * 0.5],
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
color: "#50C3E3",
|
||||
},
|
||||
},
|
||||
{
|
||||
// this bot
|
||||
z: 6,
|
||||
type: "pictorialBar",
|
||||
symbolPosition: "start",
|
||||
data: chartData.value.map((item) => item.this),
|
||||
symbol: "diamond",
|
||||
symbolOffset: ["-45%", "50%"],
|
||||
symbolSize: [barWidth, barWidth * 0.5],
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
color: "#50C3E3",
|
||||
},
|
||||
},
|
||||
{
|
||||
// last top
|
||||
z: 3,
|
||||
type: "pictorialBar",
|
||||
symbolPosition: "end",
|
||||
data: chartData.value.map((item) => item.last),
|
||||
symbol: "diamond",
|
||||
symbolOffset: ["45%", "-50%"],
|
||||
symbolSize: [barWidth, barWidth * 0.5],
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
color: "#FFF26D",
|
||||
},
|
||||
},
|
||||
{
|
||||
// last bot
|
||||
z: 3,
|
||||
type: "pictorialBar",
|
||||
symbolPosition: "start",
|
||||
data: chartData.value.map((item) => item.last),
|
||||
symbol: "diamond",
|
||||
symbolOffset: ["45%", "50%"],
|
||||
symbolSize: [barWidth, barWidth * 0.5],
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
color: "#FFF26D",
|
||||
},
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: { type: "shadow" },
|
||||
formatter: function (params) {
|
||||
let tooltipText = `<div>${params[0].axisValueLabel}</div>`;
|
||||
const filteredParams = params.filter(
|
||||
(item) => item.seriesType === "bar"
|
||||
);
|
||||
filteredParams.forEach((item) => {
|
||||
tooltipText += `<div>${item.marker} ${
|
||||
item.value ? item.value : "-"
|
||||
}</div>`;
|
||||
});
|
||||
|
||||
return tooltipText;
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
updateChartData(newEnergyCostData);
|
||||
},
|
||||
{ immediate: true } // 立即執行一次,確保初始資料載入
|
||||
);
|
||||
|
||||
watch(locale, () => {
|
||||
updateChartData(props.energyCostData);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full chart-data relative px-8 py-3">
|
||||
<div class="flex flex-wrap items-center justify-between">
|
||||
<h2 class="font-light">{{ $t("dashboard.relative_energy_consumption") }}</h2>
|
||||
<h2 class="font-light">
|
||||
{{ $t("dashboard.relative_energy_consumption") }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="h-[180px]">
|
||||
<BarChart
|
||||
@ -302,4 +302,4 @@ watch(
|
||||
content: "";
|
||||
background: url(@ASSET/img/chart-data-background02.svg) center center;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
@ -96,9 +96,9 @@ const generateCylinderChartOption = (data) => {
|
||||
],
|
||||
grid: {
|
||||
left: "0%",
|
||||
right: "0%",
|
||||
right: "1%",
|
||||
bottom: "3%",
|
||||
top: "15%",
|
||||
top: "10%",
|
||||
containLabel: true,
|
||||
},
|
||||
tooltip: {
|
||||
@ -118,7 +118,9 @@ const processEnergyData = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const dailyData = props.energyCostData.trend;
|
||||
const dailyData = [...props.energyCostData.trend].sort(
|
||||
(a, b) => new Date(a.time) - new Date(b.time)
|
||||
);
|
||||
|
||||
chartData.value = dailyData.map((item) => ({
|
||||
date: dayjs(item.time).format("MM/DD"),
|
||||
|
@ -5,7 +5,7 @@ import useBuildingStore from "@/stores/useBuildingStore";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
const { locale, t } = useI18n();
|
||||
const store = useBuildingStore();
|
||||
const energyData = ref([]);
|
||||
let intervalId = null;
|
||||
@ -63,6 +63,29 @@ watch(
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(locale, () => {
|
||||
if (energyData.value.length) {
|
||||
energyData.value = [
|
||||
{
|
||||
...energyData.value[0],
|
||||
label: t("dashboard.today_electricity_consumption"),
|
||||
},
|
||||
{
|
||||
...energyData.value[1],
|
||||
label: t("dashboard.yesterday_electricity_consumption"),
|
||||
},
|
||||
{
|
||||
...energyData.value[2],
|
||||
label: t("dashboard.instant_power"),
|
||||
},
|
||||
{
|
||||
...energyData.value[3],
|
||||
label: t("dashboard.instant_contract_capacity_ratio"),
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(intervalId);
|
||||
});
|
||||
|
@ -1,25 +1,25 @@
|
||||
<script setup>
|
||||
import { RouterView, useRoute } from 'vue-router';
|
||||
import { RouterView, useRoute } from "vue-router";
|
||||
import { computed, watch, provide, ref, onMounted, onBeforeUnmount } from "vue";
|
||||
import SystemFloorBar from './components/SystemFloorBar.vue';
|
||||
import SystemDeptBar from './components/SystemDeptBar.vue';
|
||||
import SystemFloorBar from "./components/SystemFloorBar.vue";
|
||||
import SystemDeptBar from "./components/SystemDeptBar.vue";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
import ForgeForSystem from "@/components/forge/ForgeForSystem.vue";
|
||||
import { getSystemDevices, getSystemRealTime } from "@/apis/system";
|
||||
import { getOperationCompanyList } from "@/apis/operation";
|
||||
import { getAssetSingle, getAssetFloorList } from "@/apis/asset";
|
||||
import SystemSubBar from './components/SystemSubBar.vue';
|
||||
import SystemInfoModal from './components/SystemInfoModal.vue';
|
||||
import SystemSubBar from "./components/SystemSubBar.vue";
|
||||
import SystemInfoModal from "./components/SystemInfoModal.vue";
|
||||
import SystemMain from "./SystemMain.vue";
|
||||
import SystemMode from './components/SystemMode.vue';
|
||||
import SystemFloor from './SystemFloor.vue';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import SystemMode from "./components/SystemMode.vue";
|
||||
import SystemFloor from "./SystemFloor.vue";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const buildingStore = useBuildingStore()
|
||||
const buildingStore = useBuildingStore();
|
||||
|
||||
const statusList = computed(() => {
|
||||
const sub = buildingStore.selectedSystem
|
||||
const sub = buildingStore.selectedSystem;
|
||||
|
||||
if (sub) {
|
||||
return {
|
||||
@ -28,11 +28,11 @@ const statusList = computed(() => {
|
||||
device_close_color: sub.device_close_color,
|
||||
device_close_text: sub.device_close_text,
|
||||
device_error_color: sub.device_error_color,
|
||||
device_error_text: sub.device_error_text
|
||||
}
|
||||
device_error_text: sub.device_error_text,
|
||||
};
|
||||
}
|
||||
return null
|
||||
})
|
||||
return null;
|
||||
});
|
||||
|
||||
const raw_data = ref([]);
|
||||
const data = ref([]); // filter data
|
||||
@ -41,6 +41,7 @@ const floors = ref([]);
|
||||
const deptData = ref([]);
|
||||
const companyOptions = ref([]);
|
||||
const selected_dbid = ref([]);
|
||||
const showForgeArea = ref(true); // 控制2D/3D切換與內容顯示
|
||||
|
||||
const getFloors = async () => {
|
||||
const res = await getAssetFloorList();
|
||||
@ -53,77 +54,75 @@ const getCompany = async () => {
|
||||
};
|
||||
|
||||
const getData = async () => {
|
||||
if (!route.params.sub_system_id) return
|
||||
if (!route.params.sub_system_id) return;
|
||||
const res = await getSystemDevices({
|
||||
sub_system_tag: route.params.sub_system_id,
|
||||
building_guid: buildingStore.selectedBuilding?.building_guid,
|
||||
department_id_list:deptData.value,
|
||||
})
|
||||
const devices = res.data.map(d => ({
|
||||
department_id_list: deptData.value,
|
||||
});
|
||||
const devices = res.data.map((d) => ({
|
||||
...d,
|
||||
key: d.full_name,
|
||||
device_list: d.device_list.map((dev, index) => ({
|
||||
...dev,
|
||||
forge_dbid: parseInt(dev.forge_dbid),
|
||||
room_dbid: parseInt(dev.room_dbid),
|
||||
device_coordinate_3d: dev.device_coordinate_3d ? JSON.parse(dev.device_coordinate_3d) : "",
|
||||
device_coordinate_3d: dev.device_coordinate_3d
|
||||
? JSON.parse(dev.device_coordinate_3d)
|
||||
: "",
|
||||
alarmMsg: "",
|
||||
is_show: true,
|
||||
currentColor: dev.device_normal_point_color,
|
||||
spriteDbId: 10 + dev.main_id,
|
||||
sensorTypes: dev.points ? dev.points.map(({ points }) => points) : [],
|
||||
floor_guid: d.floor_guid,
|
||||
is2DActive: false
|
||||
is2DActive: false,
|
||||
})),
|
||||
}));
|
||||
|
||||
raw_data.value = devices
|
||||
data.value = devices
|
||||
console.log("devices", res.data,devices)
|
||||
}
|
||||
raw_data.value = devices;
|
||||
data.value = devices;
|
||||
console.log("devices", res.data, devices);
|
||||
};
|
||||
|
||||
const subscribeData = ref([]); // flat data
|
||||
|
||||
const getSubData = (value) => {
|
||||
let items = [];
|
||||
value.forEach((device) => {
|
||||
items = [
|
||||
...items,
|
||||
...device.device_list
|
||||
];
|
||||
items = [...items, ...device.device_list];
|
||||
});
|
||||
return items
|
||||
}
|
||||
return items;
|
||||
};
|
||||
|
||||
watch(raw_data, (newValue) => {
|
||||
if (route.query.gas) {
|
||||
updateDataByGas(route.query.gas)
|
||||
updateDataByGas(route.query.gas);
|
||||
} else {
|
||||
const items = getSubData(newValue)
|
||||
const items = getSubData(newValue);
|
||||
data.value = newValue;
|
||||
subscribeData.value = items;
|
||||
}
|
||||
});
|
||||
|
||||
const updateDataByGas = (gas) => {
|
||||
|
||||
let update_values = []
|
||||
let update_values = [];
|
||||
if (gas === "all") {
|
||||
update_values = raw_data.value
|
||||
update_values = raw_data.value;
|
||||
} else {
|
||||
update_values = raw_data.value.map((d) => ({
|
||||
...d,
|
||||
device_list: d.device_list.filter(({ points }) => {
|
||||
if (points) {
|
||||
return points.some(({ points: p }) => p === gas)
|
||||
return points.some(({ points: p }) => p === gas);
|
||||
}
|
||||
return false
|
||||
})
|
||||
}))
|
||||
return false;
|
||||
}),
|
||||
}));
|
||||
}
|
||||
data.value = update_values
|
||||
data.value = update_values;
|
||||
subscribeData.value = getSubData(update_values);
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => buildingStore.selectedBuilding,
|
||||
@ -169,14 +168,16 @@ const currentFloor = ref(null);
|
||||
|
||||
const updateCurrentFloor = (floor) => {
|
||||
currentFloor.value = floor;
|
||||
}
|
||||
};
|
||||
|
||||
const realtimeData = ref([])
|
||||
const timeId = ref(null)
|
||||
const realtimeData = ref([]);
|
||||
const timeId = ref(null);
|
||||
const getAllDeviceRealtime = async () => {
|
||||
// 立即執行一次
|
||||
const fetchData = async () => {
|
||||
const res = await getSystemRealTime(subscribeData.value.map(d => d.device_number));
|
||||
// 立即執行一次
|
||||
const fetchData = async () => {
|
||||
const res = await getSystemRealTime(
|
||||
subscribeData.value.map((d) => d.device_number)
|
||||
);
|
||||
console.log(res.data);
|
||||
realtimeData.value = res.data;
|
||||
};
|
||||
@ -184,14 +185,25 @@ const getAllDeviceRealtime = async () => {
|
||||
|
||||
// 然後設定每 10 秒更新一次
|
||||
timeId.value = setInterval(fetchData, 10000);
|
||||
}
|
||||
};
|
||||
|
||||
watch(subscribeData, (newValue) => {
|
||||
timeId.value && clearInterval(timeId.value)
|
||||
newValue.length > 0 && getAllDeviceRealtime()
|
||||
}, { deep: true, immediate: true })
|
||||
watch(
|
||||
subscribeData,
|
||||
(newValue) => {
|
||||
timeId.value && clearInterval(timeId.value);
|
||||
newValue.length > 0 && getAllDeviceRealtime();
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
|
||||
provide("system_deviceList", { data, subscribeData, currentFloor, updateCurrentFloor, updateDataByGas, realtimeData })
|
||||
provide("system_deviceList", {
|
||||
data,
|
||||
subscribeData,
|
||||
currentFloor,
|
||||
updateCurrentFloor,
|
||||
updateDataByGas,
|
||||
realtimeData,
|
||||
});
|
||||
|
||||
const selectedDevice = ref(null);
|
||||
const selectedDeviceCog = ref({});
|
||||
@ -227,7 +239,6 @@ const getCurrentInfoModalData = async (e, position, value) => {
|
||||
: "",
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
const mobile = isMobile(e);
|
||||
selectedDevice.value = {
|
||||
@ -235,17 +246,30 @@ const getCurrentInfoModalData = async (e, position, value) => {
|
||||
value,
|
||||
isMobile: mobile,
|
||||
};
|
||||
document.getElementById('system_info_modal').showModal();
|
||||
document.getElementById("system_info_modal").showModal();
|
||||
};
|
||||
|
||||
const selectedDeviceRealtime = computed(() => realtimeData.value?.find(({ device_number }) => device_number === selectedDevice.value?.value?.device_number)?.data)
|
||||
const selectedDeviceRealtime = computed(
|
||||
() =>
|
||||
realtimeData.value?.find(
|
||||
({ device_number }) =>
|
||||
device_number === selectedDevice.value?.value?.device_number
|
||||
)?.data
|
||||
);
|
||||
|
||||
const clearSelectedDeviceInfo = () => {
|
||||
|
||||
selectedDevice.value.value = null;
|
||||
}
|
||||
};
|
||||
|
||||
provide("system_selectedDevice", { selectedDeviceRealtime, selectedDevice, getCurrentInfoModalData, clearSelectedDeviceInfo, selectedDeviceCog, selected_dbid, deptData })
|
||||
provide("system_selectedDevice", {
|
||||
selectedDeviceRealtime,
|
||||
selectedDevice,
|
||||
getCurrentInfoModalData,
|
||||
clearSelectedDeviceInfo,
|
||||
selectedDeviceCog,
|
||||
selected_dbid,
|
||||
deptData,
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
clearInterval(timeId.value);
|
||||
@ -255,7 +279,9 @@ onBeforeUnmount(() => {
|
||||
<template>
|
||||
<SystemInfoModal :data="selectedDevice" />
|
||||
<div class="border border-info px-4 py-2">
|
||||
<h5 class="text-md font-extrabold me-4">{{ buildingStore.selectedSystem?.full_name }}</h5>
|
||||
<h5 class="text-md font-extrabold me-4">
|
||||
{{ buildingStore.selectedSystem?.full_name }}
|
||||
</h5>
|
||||
<SystemFloorBar />
|
||||
<SystemDeptBar />
|
||||
</div>
|
||||
@ -263,19 +289,34 @@ onBeforeUnmount(() => {
|
||||
<div class="col-span-1 h-[calc(100vh-170px)] flex flex-col justify-start">
|
||||
<div>
|
||||
<div class="flex mb-4 items-center">
|
||||
<span class="flex items-center mr-3" v-if="statusList?.device_normal_text">
|
||||
<span class="w-7 h-7 rounded-full inline-block mr-1"
|
||||
:style="{ backgroundColor: statusList.device_normal_color }"></span>
|
||||
<span
|
||||
class="flex items-center mr-3"
|
||||
v-if="statusList?.device_normal_text"
|
||||
>
|
||||
<span
|
||||
class="w-7 h-7 rounded-full inline-block mr-1"
|
||||
:style="{ backgroundColor: statusList.device_normal_color }"
|
||||
></span>
|
||||
<span>{{ statusList.device_normal_text }}</span>
|
||||
</span>
|
||||
<span class="flex items-center mr-3" v-if="statusList?.device_close_text">
|
||||
<span class="w-7 h-7 rounded-full inline-block mr-1"
|
||||
:style="{ backgroundColor: statusList.device_close_color }"></span>
|
||||
<span
|
||||
class="flex items-center mr-3"
|
||||
v-if="statusList?.device_close_text"
|
||||
>
|
||||
<span
|
||||
class="w-7 h-7 rounded-full inline-block mr-1"
|
||||
:style="{ backgroundColor: statusList.device_close_color }"
|
||||
></span>
|
||||
<span>{{ statusList.device_close_text }}</span>
|
||||
</span>
|
||||
<span class="flex items-center mr-3" v-if="statusList?.device_error_text">
|
||||
<span class="w-7 h-7 rounded-full inline-block mr-1"
|
||||
:style="{ backgroundColor: statusList.device_error_color }"></span>
|
||||
<span
|
||||
class="flex items-center mr-3"
|
||||
v-if="statusList?.device_error_text"
|
||||
>
|
||||
<span
|
||||
class="w-7 h-7 rounded-full inline-block mr-1"
|
||||
:style="{ backgroundColor: statusList.device_error_color }"
|
||||
></span>
|
||||
<span>{{ statusList.device_error_text }}</span>
|
||||
</span>
|
||||
</div>
|
||||
@ -286,18 +327,57 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-span-1 h-full flex flex-col justify-between">
|
||||
<SystemMode />
|
||||
<div class="h-full relative">
|
||||
<SystemFloor
|
||||
:class="twMerge('absolute h-full w-full', route.query.mode === '2D' ? 'opacity-100 z-10' : 'opacity-0 z-0')" />
|
||||
<div
|
||||
:class="twMerge('absolute h-full w-full', route.query.mode === '3D' ? 'opacity-100 z-10' : 'opacity-0 z-0')">
|
||||
<ForgeForSystem :initialData="{}" />
|
||||
<template v-if="showForgeArea">
|
||||
<SystemMode />
|
||||
<div class="h-full relative">
|
||||
<SystemFloor
|
||||
:class="
|
||||
twMerge(
|
||||
'absolute h-full w-full',
|
||||
route.query.mode === '2D' ? 'opacity-100 z-10' : 'opacity-0 z-0'
|
||||
)
|
||||
"
|
||||
/>
|
||||
<div
|
||||
:class="
|
||||
twMerge(
|
||||
'absolute h-full w-full',
|
||||
route.query.mode === '3D' ? 'opacity-100 z-10' : 'opacity-0 z-0'
|
||||
)
|
||||
"
|
||||
>
|
||||
<ForgeForSystem :initialData="{}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="h-full relative">
|
||||
<img
|
||||
alt="build"
|
||||
src="/build_img.jpg"
|
||||
:class="
|
||||
twMerge(
|
||||
'absolute w-full h-full transition-opacity duration-300',
|
||||
route.params.floor_id === 'main'
|
||||
? 'opacity-100 z-10'
|
||||
: 'opacity-0 z-0'
|
||||
)
|
||||
"
|
||||
/>
|
||||
<SystemFloor
|
||||
:class="
|
||||
twMerge(
|
||||
'absolute h-full w-full',
|
||||
route.params.floor_id !== 'main'
|
||||
? 'opacity-100 z-10'
|
||||
: 'opacity-0 z-0'
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style lang='scss' scoped></style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
@ -47,8 +47,6 @@ watch(
|
||||
() => store.floorList,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
console.log('newValue',newValue);
|
||||
|
||||
const floorList = [
|
||||
{
|
||||
title: "All",
|
||||
|
Loading…
Reference in New Issue
Block a user