2D/3D暫時設定 | VITE_FORGE_BASEURL改成VITE_FILE_API_BASEURL | 首頁語言更新

This commit is contained in:
koko 2025-06-04 17:14:21 +08:00
parent 14187ad9bc
commit 5d02cffcf4
9 changed files with 421 additions and 300 deletions

View File

@ -1,4 +1,4 @@
VITE_API_BASEURL = "https://ibms-cvilux-api.production.mjmtech.com.tw" VITE_API_BASEURL = "https://ibms-cvilux-api.production.mjmtech.com.tw"
VITE_FILE_API_BASEURL = "https://cgems.cvilux-group.com:8088" VITE_FILE_API_BASEURL = "https://cgems.cvilux-group.com:8088"
VITE_MQTT_BASEURL = "wss://mqttwss.mjm-staging.developers-homelab.net" 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"

View File

@ -93,8 +93,8 @@ const createSprites = async (dataVizExtn) => {
const DataVizCore = Autodesk.DataVisualization.Core; const DataVizCore = Autodesk.DataVisualization.Core;
const viewableType = DataVizCore.ViewableType.SPRITE; const viewableType = DataVizCore.ViewableType.SPRITE;
let spriteColor = new THREE.Color(0xffffff); let spriteColor = new THREE.Color(0xffffff);
const BASEURL = import.meta.env.VITE_FORGE_BASEURL; const BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
const spriteIconUrl = `${BASEURL}/hotspot.svg`; const spriteIconUrl = `${BASEURL}/dist/hotspot.svg`;
const style = new DataVizCore.ViewableStyle( const style = new DataVizCore.ViewableStyle(
viewableType, viewableType,
spriteColor, spriteColor,

View File

@ -72,8 +72,8 @@ export default function useForgeSprite() {
const DataVizCore = Autodesk.DataVisualization.Core; const DataVizCore = Autodesk.DataVisualization.Core;
const viewableType = DataVizCore.ViewableType.SPRITE; const viewableType = DataVizCore.ViewableType.SPRITE;
let spriteColor = new THREE.Color(0xffffff); let spriteColor = new THREE.Color(0xffffff);
const BASEURL = import.meta.env.VITE_FORGE_BASEURL; const BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
const spriteIconUrl = `${BASEURL}/hotspot.svg`; const spriteIconUrl = `${BASEURL}/dist/hotspot.svg`;
const style = new DataVizCore.ViewableStyle( const style = new DataVizCore.ViewableStyle(
viewableType, viewableType,
spriteColor, spriteColor,

View File

@ -22,6 +22,8 @@ const formState = ref({
floor_guid: "all", floor_guid: "all",
department_id: "all", department_id: "all",
}); });
// 2D/3D
const showForgeArea = ref(true);
const getEnergyCostData = async (params) => { const getEnergyCostData = async (params) => {
const res = await getEnergyCost(params); const res = await getEnergyCost(params);
@ -67,18 +69,20 @@ watch(
); );
onMounted(() => { onMounted(() => {
setItems([ if (showForgeArea.value) {
{ setItems([
title: "2D", {
key: "2D", title: "2D",
active: false, key: "2D",
}, active: false,
{ },
title: "3D", {
key: "3D", title: "3D",
active: true, key: "3D",
}, active: true,
]); },
]);
}
}); });
onUnmounted(() => { onUnmounted(() => {
@ -90,31 +94,45 @@ onUnmounted(() => {
<div class="flex flex-wrap items-center"> <div class="flex flex-wrap items-center">
<!-- 建築圖 --> <!-- 建築圖 -->
<div class="w-full xl:w-1/3 relative"> <div class="w-full xl:w-1/3 relative">
<ButtonConnectedGroup <template v-if="showForgeArea">
:items="items" <ButtonConnectedGroup
className="btn-xs absolute right-3 top-6 z-20 bg-slate-800 p-0 rounded-lg " :items="items"
:onclick="(e, item) => changeActiveBtn(item)" 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'
)
"
/> />
</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>
<div class="w-full xl:w-2/3"> <div class="w-full xl:w-2/3">

View File

@ -1,10 +1,10 @@
<script setup> <script setup>
import { ref, onMounted, watch } from "vue"; import { ref, onMounted, watch, computed } from "vue";
import * as echarts from "echarts"; import * as echarts from "echarts";
import BarChart from "@/components/chart/BarChart.vue"; import BarChart from "@/components/chart/BarChart.vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
const { t } = useI18n(); const { locale, t } = useI18n();
const props = defineProps({ const props = defineProps({
energyCostData: { energyCostData: {
type: Object, type: Object,
@ -14,7 +14,7 @@ const props = defineProps({
const chartData = ref([]); // const chartData = ref([]); //
const labels = [ const labels = computed(() => [
t("dashboard.today"), t("dashboard.today"),
t("dashboard.yesterday"), t("dashboard.yesterday"),
t("dashboard.this_week"), t("dashboard.this_week"),
@ -23,7 +23,7 @@ const labels = [
t("dashboard.last_month"), t("dashboard.last_month"),
t("dashboard.this_year"), t("dashboard.this_year"),
t("dashboard.last_year"), t("dashboard.last_year"),
]; ]);
const barWidth = 30; // Set barWidth const barWidth = 30; // Set barWidth
const barChartOptions = ref({ const barChartOptions = ref({
@ -33,22 +33,13 @@ const barChartOptions = ref({
axisLine: { lineStyle: { color: "#fff" } }, axisLine: { lineStyle: { color: "#fff" } },
}, },
yAxis: { type: "value", show: false }, yAxis: { type: "value", show: false },
grid: {
left: "-10%",
right: "0%",
bottom: "3%",
top: "10%",
containLabel: true,
},
series: [], // series: [], //
tooltip: { tooltip: {
trigger: "axis", trigger: "axis",
axisPointer: { type: "shadow" }, axisPointer: { type: "shadow" },
formatter: function (params) { formatter: function (params) {
let tooltipText = `<div>${params[0].axisValueLabel}</div>`; let tooltipText = `<div>${params[0].axisValueLabel}</div>`;
const filteredParams = params.filter( const filteredParams = params.filter((item) => item.seriesType === "bar");
(item) => item.seriesType === "bar"
);
filteredParams.forEach((item) => { filteredParams.forEach((item) => {
tooltipText += `<div>${item.marker} ${ tooltipText += `<div>${item.marker} ${
item.value ? item.value : "-" 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 energyCostData
watch( watch(
() => props.energyCostData, () => props.energyCostData,
(newEnergyCostData) => { (newEnergyCostData) => {
if (newEnergyCostData && newEnergyCostData.compare) { updateChartData(newEnergyCostData);
// 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;
},
},
};
}
}, },
{ immediate: true } // { immediate: true } //
); );
watch(locale, () => {
updateChartData(props.energyCostData);
});
</script> </script>
<template> <template>
<div class="flex flex-wrap"> <div class="flex flex-wrap">
<div class="w-full chart-data relative px-8 py-3"> <div class="w-full chart-data relative px-8 py-3">
<div class="flex flex-wrap items-center justify-between"> <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>
<div class="h-[180px]"> <div class="h-[180px]">
<BarChart <BarChart
@ -302,4 +302,4 @@ watch(
content: ""; content: "";
background: url(@ASSET/img/chart-data-background02.svg) center center; background: url(@ASSET/img/chart-data-background02.svg) center center;
} }
</style> </style>

View File

@ -96,9 +96,9 @@ const generateCylinderChartOption = (data) => {
], ],
grid: { grid: {
left: "0%", left: "0%",
right: "0%", right: "1%",
bottom: "3%", bottom: "3%",
top: "15%", top: "10%",
containLabel: true, containLabel: true,
}, },
tooltip: { tooltip: {
@ -118,7 +118,9 @@ const processEnergyData = () => {
return; 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) => ({ chartData.value = dailyData.map((item) => ({
date: dayjs(item.time).format("MM/DD"), date: dayjs(item.time).format("MM/DD"),

View File

@ -5,7 +5,7 @@ import useBuildingStore from "@/stores/useBuildingStore";
import { twMerge } from "tailwind-merge"; import { twMerge } from "tailwind-merge";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
const { t } = useI18n(); const { locale, t } = useI18n();
const store = useBuildingStore(); const store = useBuildingStore();
const energyData = ref([]); const energyData = ref([]);
let intervalId = null; let intervalId = null;
@ -63,6 +63,29 @@ watch(
{ immediate: true } { 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(() => { onUnmounted(() => {
clearInterval(intervalId); clearInterval(intervalId);
}); });

View File

@ -1,25 +1,25 @@
<script setup> <script setup>
import { RouterView, useRoute } from 'vue-router'; import { RouterView, useRoute } from "vue-router";
import { computed, watch, provide, ref, onMounted, onBeforeUnmount } from "vue"; import { computed, watch, provide, ref, onMounted, onBeforeUnmount } from "vue";
import SystemFloorBar from './components/SystemFloorBar.vue'; import SystemFloorBar from "./components/SystemFloorBar.vue";
import SystemDeptBar from './components/SystemDeptBar.vue'; import SystemDeptBar from "./components/SystemDeptBar.vue";
import useBuildingStore from "@/stores/useBuildingStore"; import useBuildingStore from "@/stores/useBuildingStore";
import ForgeForSystem from "@/components/forge/ForgeForSystem.vue"; import ForgeForSystem from "@/components/forge/ForgeForSystem.vue";
import { getSystemDevices, getSystemRealTime } from "@/apis/system"; import { getSystemDevices, getSystemRealTime } from "@/apis/system";
import { getOperationCompanyList } from "@/apis/operation"; import { getOperationCompanyList } from "@/apis/operation";
import { getAssetSingle, getAssetFloorList } from "@/apis/asset"; import { getAssetSingle, getAssetFloorList } from "@/apis/asset";
import SystemSubBar from './components/SystemSubBar.vue'; import SystemSubBar from "./components/SystemSubBar.vue";
import SystemInfoModal from './components/SystemInfoModal.vue'; import SystemInfoModal from "./components/SystemInfoModal.vue";
import SystemMain from "./SystemMain.vue"; import SystemMain from "./SystemMain.vue";
import SystemMode from './components/SystemMode.vue'; import SystemMode from "./components/SystemMode.vue";
import SystemFloor from './SystemFloor.vue'; import SystemFloor from "./SystemFloor.vue";
import { twMerge } from 'tailwind-merge'; import { twMerge } from "tailwind-merge";
import dayjs from "dayjs"; import dayjs from "dayjs";
const buildingStore = useBuildingStore() const buildingStore = useBuildingStore();
const statusList = computed(() => { const statusList = computed(() => {
const sub = buildingStore.selectedSystem const sub = buildingStore.selectedSystem;
if (sub) { if (sub) {
return { return {
@ -28,11 +28,11 @@ const statusList = computed(() => {
device_close_color: sub.device_close_color, device_close_color: sub.device_close_color,
device_close_text: sub.device_close_text, device_close_text: sub.device_close_text,
device_error_color: sub.device_error_color, 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 raw_data = ref([]);
const data = ref([]); // filter data const data = ref([]); // filter data
@ -41,6 +41,7 @@ const floors = ref([]);
const deptData = ref([]); const deptData = ref([]);
const companyOptions = ref([]); const companyOptions = ref([]);
const selected_dbid = ref([]); const selected_dbid = ref([]);
const showForgeArea = ref(true); // 2D/3D
const getFloors = async () => { const getFloors = async () => {
const res = await getAssetFloorList(); const res = await getAssetFloorList();
@ -53,77 +54,75 @@ const getCompany = async () => {
}; };
const getData = async () => { const getData = async () => {
if (!route.params.sub_system_id) return if (!route.params.sub_system_id) return;
const res = await getSystemDevices({ const res = await getSystemDevices({
sub_system_tag: route.params.sub_system_id, sub_system_tag: route.params.sub_system_id,
building_guid: buildingStore.selectedBuilding?.building_guid, building_guid: buildingStore.selectedBuilding?.building_guid,
department_id_list:deptData.value, department_id_list: deptData.value,
}) });
const devices = res.data.map(d => ({ const devices = res.data.map((d) => ({
...d, ...d,
key: d.full_name, key: d.full_name,
device_list: d.device_list.map((dev, index) => ({ device_list: d.device_list.map((dev, index) => ({
...dev, ...dev,
forge_dbid: parseInt(dev.forge_dbid), forge_dbid: parseInt(dev.forge_dbid),
room_dbid: parseInt(dev.room_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: "", alarmMsg: "",
is_show: true, is_show: true,
currentColor: dev.device_normal_point_color, currentColor: dev.device_normal_point_color,
spriteDbId: 10 + dev.main_id, spriteDbId: 10 + dev.main_id,
sensorTypes: dev.points ? dev.points.map(({ points }) => points) : [], sensorTypes: dev.points ? dev.points.map(({ points }) => points) : [],
floor_guid: d.floor_guid, floor_guid: d.floor_guid,
is2DActive: false is2DActive: false,
})), })),
})); }));
raw_data.value = devices raw_data.value = devices;
data.value = devices data.value = devices;
console.log("devices", res.data,devices) console.log("devices", res.data, devices);
} };
const subscribeData = ref([]); // flat data const subscribeData = ref([]); // flat data
const getSubData = (value) => { const getSubData = (value) => {
let items = []; let items = [];
value.forEach((device) => { value.forEach((device) => {
items = [ items = [...items, ...device.device_list];
...items,
...device.device_list
];
}); });
return items return items;
} };
watch(raw_data, (newValue) => { watch(raw_data, (newValue) => {
if (route.query.gas) { if (route.query.gas) {
updateDataByGas(route.query.gas) updateDataByGas(route.query.gas);
} else { } else {
const items = getSubData(newValue) const items = getSubData(newValue);
data.value = newValue; data.value = newValue;
subscribeData.value = items; subscribeData.value = items;
} }
}); });
const updateDataByGas = (gas) => { const updateDataByGas = (gas) => {
let update_values = [];
let update_values = []
if (gas === "all") { if (gas === "all") {
update_values = raw_data.value update_values = raw_data.value;
} else { } else {
update_values = raw_data.value.map((d) => ({ update_values = raw_data.value.map((d) => ({
...d, ...d,
device_list: d.device_list.filter(({ points }) => { device_list: d.device_list.filter(({ points }) => {
if (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); subscribeData.value = getSubData(update_values);
} };
watch( watch(
() => buildingStore.selectedBuilding, () => buildingStore.selectedBuilding,
@ -169,14 +168,16 @@ const currentFloor = ref(null);
const updateCurrentFloor = (floor) => { const updateCurrentFloor = (floor) => {
currentFloor.value = floor; currentFloor.value = floor;
} };
const realtimeData = ref([]) const realtimeData = ref([]);
const timeId = ref(null) const timeId = ref(null);
const getAllDeviceRealtime = async () => { const getAllDeviceRealtime = async () => {
// //
const fetchData = async () => { const fetchData = async () => {
const res = await getSystemRealTime(subscribeData.value.map(d => d.device_number)); const res = await getSystemRealTime(
subscribeData.value.map((d) => d.device_number)
);
console.log(res.data); console.log(res.data);
realtimeData.value = res.data; realtimeData.value = res.data;
}; };
@ -184,14 +185,25 @@ const getAllDeviceRealtime = async () => {
// 10 // 10
timeId.value = setInterval(fetchData, 10000); timeId.value = setInterval(fetchData, 10000);
} };
watch(subscribeData, (newValue) => { watch(
timeId.value && clearInterval(timeId.value) subscribeData,
newValue.length > 0 && getAllDeviceRealtime() (newValue) => {
}, { deep: true, immediate: true }) 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 selectedDevice = ref(null);
const selectedDeviceCog = ref({}); const selectedDeviceCog = ref({});
@ -227,7 +239,6 @@ const getCurrentInfoModalData = async (e, position, value) => {
: "", : "",
}; };
} }
} }
const mobile = isMobile(e); const mobile = isMobile(e);
selectedDevice.value = { selectedDevice.value = {
@ -235,17 +246,30 @@ const getCurrentInfoModalData = async (e, position, value) => {
value, value,
isMobile: mobile, 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 = () => { const clearSelectedDeviceInfo = () => {
selectedDevice.value.value = null; 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(() => { onBeforeUnmount(() => {
clearInterval(timeId.value); clearInterval(timeId.value);
@ -255,7 +279,9 @@ onBeforeUnmount(() => {
<template> <template>
<SystemInfoModal :data="selectedDevice" /> <SystemInfoModal :data="selectedDevice" />
<div class="border border-info px-4 py-2"> <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 /> <SystemFloorBar />
<SystemDeptBar /> <SystemDeptBar />
</div> </div>
@ -263,19 +289,34 @@ onBeforeUnmount(() => {
<div class="col-span-1 h-[calc(100vh-170px)] flex flex-col justify-start"> <div class="col-span-1 h-[calc(100vh-170px)] flex flex-col justify-start">
<div> <div>
<div class="flex mb-4 items-center"> <div class="flex mb-4 items-center">
<span class="flex items-center mr-3" v-if="statusList?.device_normal_text"> <span
<span class="w-7 h-7 rounded-full inline-block mr-1" class="flex items-center mr-3"
:style="{ backgroundColor: statusList.device_normal_color }"></span> 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>{{ statusList.device_normal_text }}</span>
</span> </span>
<span class="flex items-center mr-3" v-if="statusList?.device_close_text"> <span
<span class="w-7 h-7 rounded-full inline-block mr-1" class="flex items-center mr-3"
:style="{ backgroundColor: statusList.device_close_color }"></span> 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>{{ statusList.device_close_text }}</span>
</span> </span>
<span class="flex items-center mr-3" v-if="statusList?.device_error_text"> <span
<span class="w-7 h-7 rounded-full inline-block mr-1" class="flex items-center mr-3"
:style="{ backgroundColor: statusList.device_error_color }"></span> 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>{{ statusList.device_error_text }}</span>
</span> </span>
</div> </div>
@ -286,18 +327,57 @@ onBeforeUnmount(() => {
</div> </div>
</div> </div>
<div class="col-span-1 h-full flex flex-col justify-between"> <div class="col-span-1 h-full flex flex-col justify-between">
<SystemMode /> <template v-if="showForgeArea">
<div class="h-full relative"> <SystemMode />
<SystemFloor <div class="h-full relative">
:class="twMerge('absolute h-full w-full', route.query.mode === '2D' ? 'opacity-100 z-10' : 'opacity-0 z-0')" /> <SystemFloor
<div :class="
:class="twMerge('absolute h-full w-full', route.query.mode === '3D' ? 'opacity-100 z-10' : 'opacity-0 z-0')"> twMerge(
<ForgeForSystem :initialData="{}" /> '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>
</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>
</div> </div>
</template> </template>
<style lang='scss' scoped></style> <style lang="scss" scoped></style>

View File

@ -47,8 +47,6 @@ watch(
() => store.floorList, () => store.floorList,
(newValue) => { (newValue) => {
if (newValue) { if (newValue) {
console.log('newValue',newValue);
const floorList = [ const floorList = [
{ {
title: "All", title: "All",