init info modal | 樣式修改
This commit is contained in:
parent
355fc12499
commit
bf5d6e6eb1
@ -1,2 +1,3 @@
|
||||
export const GET_SYSTEM_FLOOR_LIST_API = `/api/Device/GetFloor`;
|
||||
export const GET_SYSTEM_DEVICE_LIST_API = `/api/Device/GetDeviceList`;
|
||||
export const GET_SYSTEM_REALTIME_API = `/api/Device/GetRealTimeData`;
|
@ -1,4 +1,8 @@
|
||||
import { GET_SYSTEM_FLOOR_LIST_API, GET_SYSTEM_DEVICE_LIST_API } from "./api";
|
||||
import {
|
||||
GET_SYSTEM_FLOOR_LIST_API,
|
||||
GET_SYSTEM_DEVICE_LIST_API,
|
||||
GET_SYSTEM_REALTIME_API,
|
||||
} from "./api";
|
||||
import instance from "@/util/request";
|
||||
import apihandler from "@/util/apihandler";
|
||||
|
||||
@ -30,3 +34,11 @@ export const getSystemDevices = async ({
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getSystemRealTime = async (device_list) => {
|
||||
const res = await instance.post(GET_SYSTEM_REALTIME_API, { device_list });
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
@ -13,7 +13,7 @@ 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 ForgeInfoModal from "../../views/system/components/SystemInfoModal.vue";
|
||||
import useAlarmStore from "@/stores/useAlarmStore";
|
||||
import useForgeSprite from "@/hooks/forge/useForgeSprite";
|
||||
|
||||
@ -64,6 +64,10 @@ const initViewer = (container) => {
|
||||
let 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);
|
||||
}
|
||||
);
|
||||
@ -79,6 +83,7 @@ const loadModel = (viewer, filePath) => {
|
||||
(model) => {
|
||||
viewer.impl.invalidate(true);
|
||||
viewer.fitToView();
|
||||
updateDataVisualization(viewer)
|
||||
resolve(model);
|
||||
console.log("模型加載完成");
|
||||
},
|
||||
@ -151,6 +156,17 @@ const initForge = async () => {
|
||||
const viewer = await initViewer(forgeDom.value)
|
||||
const filePath = `${FILE_BASEURL}/upload/forge/0.svf`;
|
||||
await loadModel(viewer, filePath)
|
||||
viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT,
|
||||
async function () {
|
||||
console.log(
|
||||
"Autodesk.Viewing.GEOMETRY_LOADED_EVENT",
|
||||
viewer.isLoadDone()
|
||||
);
|
||||
// updateForgeViewer(viewer);
|
||||
createSprites()
|
||||
hideAllObjects();
|
||||
})
|
||||
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
|
@ -1,118 +0,0 @@
|
||||
<script setup>
|
||||
import { defineProps, onMounted, ref, watch } from "vue";
|
||||
import ForgeInfoModalDesktop from "./ForgeInfoModalDesktop.vue";
|
||||
import ForgeInfoModalCog from "./ForgeInfoModalCog.vue";
|
||||
|
||||
const props = defineProps({
|
||||
data: Object,
|
||||
});
|
||||
|
||||
const currentTab = ref("desktop");
|
||||
const tabs = {
|
||||
desktop: ForgeInfoModalDesktop,
|
||||
cog: ForgeInfoModalCog,
|
||||
};
|
||||
|
||||
const changeOpenKey = (key) => {
|
||||
currentTab.value = key;
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
forge_info_modal.close();
|
||||
};
|
||||
|
||||
const position = ref({
|
||||
left: "0px",
|
||||
top: "0px",
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(newValue) => {
|
||||
console.log(newValue);
|
||||
position.value = newValue.initPos;
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal
|
||||
id="forge_info_modal"
|
||||
:onCancel="onCancel"
|
||||
width="550"
|
||||
:draggable="!data?.isMobile"
|
||||
:backdrop="false"
|
||||
:modalStyle="position"
|
||||
:class="data?.isMobile ? '-translate-x-1/2 -translate-y-1/2' : ''"
|
||||
>
|
||||
<template #modalContent>
|
||||
<div class="card bg-transparent text-white">
|
||||
<div class="card-title py-2 border-b border-zinc-700 justify-between">
|
||||
<h3>{{ data?.value.full_name }}</h3>
|
||||
<div>
|
||||
<Button
|
||||
type="link"
|
||||
class="btn-link btn-text-without-border px-2"
|
||||
@click="() => changeOpenKey('desktop')"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'desktop']"
|
||||
size="lg"
|
||||
class="text-[#a5abb1]"
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
class="btn-link btn-text-without-border px-2"
|
||||
@click="() => changeOpenKey('cog')"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'cog']"
|
||||
size="lg"
|
||||
class="text-[#a5abb1]"
|
||||
/>
|
||||
</Button>
|
||||
<!-- <Button
|
||||
type="link"
|
||||
class="btn-link btn-text-without-border px-2"
|
||||
@click="() => changeOpenKey('triangle')"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'exclamation-triangle']"
|
||||
size="lg"
|
||||
class="text-[#a5abb1]"
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
class="btn-link btn-text-without-border px-2"
|
||||
@click="() => changeOpenKey('bars')"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'bars']"
|
||||
size="lg"
|
||||
class="text-[#a5abb1]"
|
||||
/>
|
||||
</Button>-->
|
||||
<Button
|
||||
type="link"
|
||||
class="btn-link btn-text-without-border px-2"
|
||||
@click="onCancel"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'times']"
|
||||
size="lg"
|
||||
class="text-[#a5abb1]"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body px-0">
|
||||
<component :is="tabs[currentTab]" :data="data"></component>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
@ -1,34 +0,0 @@
|
||||
<script setup>
|
||||
import { defineProps, watch, computed } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const props = defineProps({
|
||||
data: Object,
|
||||
});
|
||||
|
||||
const pxRoute = computed(() =>
|
||||
route.path === "/dashboard" ? "GraphicM" : "GraphicU"
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(newValue) => {
|
||||
console.log(newValue, newValue.value.device_number);
|
||||
}
|
||||
);
|
||||
const device_px_route = computed(() =>
|
||||
props.data?.value.device_number.replaceAll("_", "/")
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<iframe
|
||||
v-if="data"
|
||||
:src="`/ord?station:%7Cslot:/${device_px_route}|view:${pxRoute}?fullScreen=true`"
|
||||
style="width: 500px; height: 350px"
|
||||
></iframe>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
@ -1,4 +1,7 @@
|
||||
export default function useForgeHeatmap(){
|
||||
import { watch, inject, markRaw, ref } from "vue";
|
||||
|
||||
export default function useForgeHeatmap(dataVizExtn, forgeViewer){
|
||||
const { subscribeData } = inject("system_deviceList");
|
||||
|
||||
const createHeatMap = async (heatMapName) => {
|
||||
const {
|
||||
@ -10,7 +13,7 @@ export default function useForgeHeatmap(){
|
||||
const shadingGroup = new SurfaceShadingGroup(`iot_heatmap_${heatMapName}`);
|
||||
const rooms = new Map();
|
||||
|
||||
for (const { id, roomDbId, position, sensorTypes } of deviceList.value) {
|
||||
for (const { id, roomDbId, position, sensorTypes } of subscribeData.value) {
|
||||
if (!id || roomDbId == -1 || !roomDbId) {
|
||||
continue;
|
||||
}
|
||||
@ -28,20 +31,19 @@ export default function useForgeHeatmap(){
|
||||
shadingData.addChild(shadingGroup);
|
||||
shadingData.initialize(forgeViewer.value?.model);
|
||||
|
||||
await dataVizExtension.value.setupSurfaceShading(
|
||||
await dataVizExtn.value.setupSurfaceShading(
|
||||
forgeViewer.value.model,
|
||||
shadingData
|
||||
);
|
||||
dataVizExtension.value.registerSurfaceShadingColors(
|
||||
"temperature",
|
||||
dataVizExtn.value.registerSurfaceShadingColors(
|
||||
heatMapName,
|
||||
[0x0000ff, 0x00ff00, 0xffff00, 0xff0000]
|
||||
);
|
||||
dataVizExtension.value.renderSurfaceShading(
|
||||
dataVizExtn.value.renderSurfaceShading(
|
||||
`iot_heatmap_${heatMapName}`,
|
||||
"temperature",
|
||||
heatMapName,
|
||||
getSensorValue
|
||||
);
|
||||
|
||||
console.log(dataVizExtension.value);
|
||||
};
|
||||
}
|
@ -40,6 +40,7 @@ export default function useForgeSprite() {
|
||||
const viewableData = new DataVizCore.ViewableData();
|
||||
viewableData.spriteSize = 24; // Sprites as points of size 24 x 24 pixels
|
||||
subscribeData.value?.forEach((d, index) => {
|
||||
if (d.device_coordinate_3d) {
|
||||
const position = d.device_coordinate_3d;
|
||||
style.color = new THREE.Color(hexToRgb(d.device_normal_color));
|
||||
const viewable = new DataVizCore.SpriteViewable(
|
||||
@ -48,12 +49,13 @@ export default function useForgeSprite() {
|
||||
d.spriteDbId
|
||||
);
|
||||
viewableData.addViewable(viewable);
|
||||
}
|
||||
});
|
||||
await viewableData.finish();
|
||||
dataVizExtn.value.addViewables(viewableData);
|
||||
|
||||
NOP_VIEWER.addEventListener(DataVizCore.MOUSE_CLICK, onSpriteClicked);
|
||||
NOP_VIEWER.addEventListener(
|
||||
forgeViewer.value.addEventListener(DataVizCore.MOUSE_CLICK, onSpriteClicked);
|
||||
forgeViewer.value.addEventListener(
|
||||
Autodesk.Viewing.SELECTION_CHANGED_EVENT,
|
||||
onSpriteClicked
|
||||
);
|
||||
@ -80,17 +82,17 @@ export default function useForgeSprite() {
|
||||
};
|
||||
|
||||
const hideAllObjects = () => {
|
||||
const tree = NOP_VIEWER.model?.getData().instanceTree;
|
||||
const tree = forgeViewer.value.model.getInstanceTree();
|
||||
const allDbIdsStr = Object.keys(tree.nodeAccess.dbIdToIndex);
|
||||
for (var i = 0; i < allDbIdsStr.length; i++) {
|
||||
NOP_VIEWER.hide(parseInt(allDbIdsStr[i]));
|
||||
forgeViewer.value.hide(parseInt(allDbIdsStr[i]));
|
||||
}
|
||||
|
||||
subscribeData.value.forEach((value, index) => {
|
||||
NOP_VIEWER.show(value.forge_dbid);
|
||||
forgeViewer.value.show(value.forge_dbid);
|
||||
});
|
||||
|
||||
NOP_VIEWER.impl.invalidate(true);
|
||||
forgeViewer.value.impl.invalidate(true);
|
||||
};
|
||||
|
||||
return {
|
||||
|
@ -6,6 +6,7 @@ import useBuildingStore from "@/stores/useBuildingStore";
|
||||
import ForgeForSystem from "@/components/forge/ForgeForSystem.vue";
|
||||
import { getSystemDevices } from "@/apis/system";
|
||||
import SystemSubBar from './components/SystemSubBar.vue';
|
||||
import SystemInfoModal from './components/SystemInfoModal.vue';
|
||||
|
||||
const buildingStore = useBuildingStore()
|
||||
|
||||
@ -26,7 +27,7 @@ const statusList = computed(() => {
|
||||
})
|
||||
|
||||
const raw_data = ref([])
|
||||
const data = ref([])
|
||||
const data = ref([]) // filter data
|
||||
const route = useRoute()
|
||||
|
||||
const getData = async () => {
|
||||
@ -34,12 +35,26 @@ const getData = async () => {
|
||||
sub_system_tag: route.params.sub_system_id,
|
||||
building_tag: buildingStore.selectedBuilding?.building_tag,
|
||||
})
|
||||
const data = res.data.map(d => ({ ...d, key: d.full_name }));
|
||||
const data = res.data.map(d => ({
|
||||
...d, key: d.full_name, device_list: d.device_list.map((d, index) => ({
|
||||
...d,
|
||||
forge_dbid: parseInt(d.forge_dbid),
|
||||
device_coordinate_3d: d.device_coordinate_3d
|
||||
? JSON.parse(d.device_coordinate_3d)
|
||||
: { x: 0, y: 0 },
|
||||
alarmMsg: "",
|
||||
is_show: true,
|
||||
currentColor: d.device_normal_point_color,
|
||||
spriteDbId: 10 + index,
|
||||
sensorTypes: d.points.map(({ points }) => points),
|
||||
points: d.points.map((p) => ({ ...p, value: "" }))
|
||||
})),
|
||||
}));
|
||||
raw_data.value = data
|
||||
data.value = data
|
||||
}
|
||||
|
||||
const subscribeData = ref([]);
|
||||
const subscribeData = ref([]); // flat data
|
||||
|
||||
const getSubPoint = (normal, close, error, sub_points) => {
|
||||
let points = {
|
||||
@ -56,23 +71,7 @@ const getSubData = (value) => {
|
||||
value.forEach((device) => {
|
||||
items = [
|
||||
...items,
|
||||
...device.device_list.map((d, index) => ({
|
||||
...d,
|
||||
forge_dbid: parseInt(d.forge_dbid),
|
||||
device_coordinate_3d: d.device_coordinate_3d
|
||||
? JSON.parse(d.device_coordinate_3d)
|
||||
: { x: 0, y: 0 },
|
||||
// points: getSubPoint(
|
||||
// d.device_normal_point_name,
|
||||
// d.device_close_point_name,
|
||||
// d.device_error_point_name,
|
||||
// d.points
|
||||
// ),
|
||||
alarmMsg: "",
|
||||
is_show: true,
|
||||
currentColor: d.device_normal_point_color,
|
||||
spriteDbId: 10 + index,
|
||||
})),
|
||||
...device.device_list
|
||||
];
|
||||
});
|
||||
data.value = raw_data.value;
|
||||
@ -83,6 +82,10 @@ watch(raw_data, (newValue) => {
|
||||
updateDataByGas("all")
|
||||
});
|
||||
|
||||
watch(data, (newValue) => {
|
||||
console.log(newValue);
|
||||
})
|
||||
|
||||
const updateDataByGas = (gas) => {
|
||||
console.log(gas)
|
||||
if (gas === "all") {
|
||||
@ -112,12 +115,40 @@ const updateCurrentFloor = (floor) => {
|
||||
|
||||
provide("system_deviceList", { data, subscribeData, currentFloor, updateCurrentFloor, updateDataByGas })
|
||||
|
||||
|
||||
// 傳遞目前點擊資訊
|
||||
const currentInfoModalData = ref(null);
|
||||
const isMobile = (pointerType) => {
|
||||
// let flag =
|
||||
// /phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone/gi.test(
|
||||
// navigator.userAgent
|
||||
// );
|
||||
// console.log("isMobile", flag);
|
||||
return pointerType !== "mouse"; // is desktop
|
||||
};
|
||||
const getCurrentInfoModalData = (e, position, value) => {
|
||||
const mobile = isMobile(e.pointerType);
|
||||
selectedDevice.value = {
|
||||
initPos: mobile
|
||||
? { left: `50%`, top: `50%` }
|
||||
: { left: `${position.left}px`, top: `${position.top}px` },
|
||||
value,
|
||||
isMobile: mobile,
|
||||
};;
|
||||
document.getElementById('system_info_modal').showModal();
|
||||
};
|
||||
|
||||
const selectedDevice = ref(null);
|
||||
|
||||
provide("system_selectedDevice", { selectedDevice, getCurrentInfoModalData })
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SystemInfoModal :data="selectedDevice" />
|
||||
<SystemFloorBar />
|
||||
<div class="grid grid-cols-2 gap-5 mt-8 mb-4">
|
||||
<div class="col-span-1 h-[80vh] flex flex-col justify-between">
|
||||
<div class="col-span-1 h-[80vh] 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">
|
||||
@ -146,6 +177,7 @@ provide("system_deviceList", { data, subscribeData, currentFloor, updateCurrentF
|
||||
<ForgeForSystem :initialData="{}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style lang='scss' scoped></style>
|
@ -38,7 +38,7 @@ watch([() => currentFloor, () => asset_floor_chart], ([newValue, newChart]) => {
|
||||
asset_floor_chart.value.updateSvg(
|
||||
{
|
||||
full_name: newValue.value?.title,
|
||||
path: `${FILE_BASEURL}/upload/floor_map/${newValue.value.map_url}`,
|
||||
path: `${FILE_BASEURL}/${newValue.value.map_url}`,
|
||||
},
|
||||
|
||||
defaultOption(newValue.value?.title, subscribeData.value.filter(d => d.device_coordinate).map(d => JSON.parse(d.device_coordinate)))
|
||||
|
@ -4,6 +4,7 @@ import { inject } from "vue"
|
||||
const { data } = inject("system_deviceList")
|
||||
|
||||
|
||||
const { getCurrentInfoModalData } = inject("system_selectedDevice")
|
||||
|
||||
</script>
|
||||
|
||||
@ -23,11 +24,15 @@ const { data } = inject("system_deviceList")
|
||||
<span class="w-8 h-8" v-else></span>
|
||||
<span>{{ device.full_name }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<div class="sec03">
|
||||
<span></span>
|
||||
<span>狀態:</span>
|
||||
<span></span>
|
||||
</div>
|
||||
<button class="btn-text border-0 "
|
||||
@click.stop.prevent="(e) => getCurrentInfoModalData(e, { left: e.clientX, top: e.clientY }, device)">詳細資料</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -52,6 +57,10 @@ const { data } = inject("system_deviceList")
|
||||
|
||||
}
|
||||
|
||||
.item .btn-text {
|
||||
@apply hover:bg-transparent focus-within:bg-transparent !important;
|
||||
}
|
||||
|
||||
.equipment-show .item .sec01 span:nth-child(1) {
|
||||
font-size: 1rem;
|
||||
position: relative;
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { getSystemFloors } from "@/apis/system"
|
||||
import { getAssetFloorList } from "@/apis/asset";
|
||||
import { onMounted, ref, watch, inject } from 'vue';
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
import useActiveBtn from "@/hooks/useActiveBtn"
|
||||
@ -14,18 +14,20 @@ const { updateCurrentFloor } = inject("system_deviceList")
|
||||
|
||||
const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
|
||||
const getFloors = async () => {
|
||||
const res = await getSystemFloors(store.selectedBuilding?.building_tag, route.params.sub_system_id)
|
||||
const res = await getAssetFloorList()
|
||||
let data = res.data.find(d => d.building_tag === store.selectedBuilding?.building_tag)
|
||||
console.log(data)
|
||||
setItems([
|
||||
{
|
||||
title: "總覽",
|
||||
key: "main",
|
||||
active: route.params.floor_id ? false : true,
|
||||
},
|
||||
...res.data.map((d, idx) => ({
|
||||
title: d.floor_tag,
|
||||
...data.floors.map((d, idx) => ({
|
||||
title: d.full_name,
|
||||
key: d.floor_guid,
|
||||
active: route.params.floor_id === d.floor_guid,
|
||||
map_url: d.floor_map_name
|
||||
map_url: d.floor_map_url + ".svg"
|
||||
}))
|
||||
]);
|
||||
}
|
||||
|
31
src/views/system/components/SystemInfoModal.vue
Normal file
31
src/views/system/components/SystemInfoModal.vue
Normal file
@ -0,0 +1,31 @@
|
||||
<script setup>
|
||||
import { inject, ref, watch } from "vue";
|
||||
import SystemInfoModalContent from "./SystemInfoModalContent.vue";
|
||||
|
||||
|
||||
const { selectedDevice: data } = inject("system_selectedDevice")
|
||||
|
||||
const position = ref({
|
||||
left: "0px",
|
||||
top: "0px",
|
||||
});
|
||||
|
||||
watch(
|
||||
() => data,
|
||||
(newValue) => {
|
||||
console.log(newValue);
|
||||
position.value = newValue.initPos;
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal id="system_info_modal" :onCancel="onCancel" width="600" :draggable="!data?.isMobile" :backdrop="false"
|
||||
:modalStyle="position" :class="data?.isMobile ? '-translate-x-1/2 -translate-y-1/2' : ''">
|
||||
<template #modalContent>
|
||||
<SystemInfoModalContent />
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
73
src/views/system/components/SystemInfoModalContent.vue
Normal file
73
src/views/system/components/SystemInfoModalContent.vue
Normal file
@ -0,0 +1,73 @@
|
||||
<script setup>
|
||||
import { defineProps, inject, ref, watch } from "vue";
|
||||
import SystemInfoModalDesktop from "./SystemInfoModalDesktop.vue";
|
||||
import SystemInfoModalCog from "./SystemInfoModalCog.vue";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
|
||||
const { selectedDevice: data } = inject("system_selectedDevice")
|
||||
|
||||
|
||||
const currentTab = ref("desktop");
|
||||
const tabs = {
|
||||
desktop: SystemInfoModalDesktop,
|
||||
cog: SystemInfoModalCog,
|
||||
};
|
||||
|
||||
const changeOpenKey = (key) => {
|
||||
currentTab.value = key;
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
currentTab.value = "desktop";
|
||||
document.getElementById('system_info_modal').close();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="card bg-transparent text-white">
|
||||
<div class="card-title py-2 border-b border-zinc-700 justify-between">
|
||||
<h3>{{ data?.value.full_name }}</h3>
|
||||
<div>
|
||||
<Button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('desktop')">
|
||||
<font-awesome-icon :icon="['fas', 'desktop']" size="lg"
|
||||
:class="twMerge(currentTab === 'desktop' ? 'text-success' : 'text-[#a5abb1]')" />
|
||||
</Button>
|
||||
<Button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('cog')">
|
||||
<font-awesome-icon :icon="['fas', 'cog']" size="lg"
|
||||
:class="twMerge(currentTab === 'cog' ? 'text-success' : 'text-[#a5abb1]')" />
|
||||
</Button>
|
||||
<!-- <Button
|
||||
type="link"
|
||||
class="btn-link btn-text-without-border px-2"
|
||||
@click="() => changeOpenKey('triangle')"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'exclamation-triangle']"
|
||||
size="lg"
|
||||
class="text-[#a5abb1]"
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
class="btn-link btn-text-without-border px-2"
|
||||
@click="() => changeOpenKey('bars')"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'bars']"
|
||||
size="lg"
|
||||
class="text-[#a5abb1]"
|
||||
/>
|
||||
</Button>-->
|
||||
<Button type="link" class="btn-link btn-text-without-border px-2" @click="onCancel">
|
||||
<font-awesome-icon :icon="['fas', 'times']" size="lg" class="text-[#a5abb1]" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body px-0">
|
||||
<component :is="tabs[currentTab]" :data="[]"></component>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang='scss' scoped></style>
|
22
src/views/system/components/SystemInfoModalDesktop.vue
Normal file
22
src/views/system/components/SystemInfoModalDesktop.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<script setup>
|
||||
import { inject } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
const { selectedDevice } = inject("system_selectedDevice");
|
||||
|
||||
const columns = [{
|
||||
title: "屬性",
|
||||
key: "points"
|
||||
},
|
||||
{
|
||||
title: "值",
|
||||
key: "value"
|
||||
}]
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Table :loading="loading" :columns="columns" :dataSource="[]" :withStyle="false"></Table>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
@ -11,10 +11,11 @@ watch(() => buildingStore, (newValue) => {
|
||||
newValue.selectedSystem?.points?.length > 0 && setItems(newValue.selectedSystem.points.map(d => ({
|
||||
title: d.full_name,
|
||||
key: d.points,
|
||||
active: false,
|
||||
active: d.points === "Temp",
|
||||
})))
|
||||
}, {
|
||||
deep: true,
|
||||
immediate: true
|
||||
})
|
||||
|
||||
const onClick = (item) => {
|
||||
@ -25,9 +26,8 @@ const onClick = (item) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-if="items.length > 0">
|
||||
<template v-if="buildingStore.selectedSystem?.points?.length > 0">
|
||||
<ButtonGroup :items="items" :withLine="false" className="btn-xs rounded-md" :onclick="(e, item) => onClick(item)" />
|
||||
|
||||
</template>
|
||||
</template>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user