MQTT publish topic 名稱修改 |
系統監控switch功能 | 總部地圖功能
This commit is contained in:
parent
e05e83bb03
commit
3427058cd2
7
package-lock.json
generated
7
package-lock.json
generated
@ -22,6 +22,7 @@
|
|||||||
"echarts": "^5.4.3",
|
"echarts": "^5.4.3",
|
||||||
"jquery-ui": "^1.14.1",
|
"jquery-ui": "^1.14.1",
|
||||||
"json-schema-generator": "^2.0.6",
|
"json-schema-generator": "^2.0.6",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
"mqtt": "^5.10.3",
|
"mqtt": "^5.10.3",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"requirejs": "^2.3.6",
|
"requirejs": "^2.3.6",
|
||||||
@ -3350,6 +3351,12 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/leaflet": {
|
||||||
|
"version": "1.9.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
|
||||||
|
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
"node_modules/libphonenumber-js": {
|
"node_modules/libphonenumber-js": {
|
||||||
"version": "1.10.60",
|
"version": "1.10.60",
|
||||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.60.tgz",
|
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.60.tgz",
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"build:staging": "vite build --mode staging"
|
"build:staging": "vite build --mode staging"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons-vue": "^7.0.1",
|
"@ant-design/icons-vue": "^7.0.1",
|
||||||
@ -24,6 +24,7 @@
|
|||||||
"echarts": "^5.4.3",
|
"echarts": "^5.4.3",
|
||||||
"jquery-ui": "^1.14.1",
|
"jquery-ui": "^1.14.1",
|
||||||
"json-schema-generator": "^2.0.6",
|
"json-schema-generator": "^2.0.6",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
"mqtt": "^5.10.3",
|
"mqtt": "^5.10.3",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"requirejs": "^2.3.6",
|
"requirejs": "^2.3.6",
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export const GET_SYSTEM_FLOOR_LIST_API = `/api/Device/GetFloor`;
|
export const GET_SYSTEM_FLOOR_LIST_API = `/api/Device/GetFloor`;
|
||||||
export const GET_SYSTEM_DEVICE_LIST_API = `/api/Device/GetDeviceList`;
|
export const GET_SYSTEM_DEVICE_LIST_API = `/api/Device/GetDeviceList`;
|
||||||
export const GET_SYSTEM_REALTIME_API = `/api/Device/GetRealTimeData`;
|
export const GET_SYSTEM_REALTIME_API = `/api/Device/GetRealTimeData`;
|
||||||
|
export const GET_SYSTEM_DEVICE_POWER_TOGGLE_API = `/api/device-events/power-toggle`;
|
@ -2,6 +2,7 @@ import {
|
|||||||
GET_SYSTEM_FLOOR_LIST_API,
|
GET_SYSTEM_FLOOR_LIST_API,
|
||||||
GET_SYSTEM_DEVICE_LIST_API,
|
GET_SYSTEM_DEVICE_LIST_API,
|
||||||
GET_SYSTEM_REALTIME_API,
|
GET_SYSTEM_REALTIME_API,
|
||||||
|
GET_SYSTEM_DEVICE_POWER_TOGGLE_API
|
||||||
} from "./api";
|
} from "./api";
|
||||||
import instance from "@/util/request";
|
import instance from "@/util/request";
|
||||||
import apihandler from "@/util/apihandler";
|
import apihandler from "@/util/apihandler";
|
||||||
@ -42,3 +43,16 @@ export const getSystemRealTime = async (device_list) => {
|
|||||||
code: res.code,
|
code: res.code,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const toggleDevicePower = async ({topic_publish, device_item_id,new_value}) => {
|
||||||
|
const res = await instance.post(GET_SYSTEM_DEVICE_POWER_TOGGLE_API, {
|
||||||
|
topic_publish,
|
||||||
|
device_item_id,
|
||||||
|
new_value,
|
||||||
|
});
|
||||||
|
|
||||||
|
return apihandler(res.code, res.data, {
|
||||||
|
msg: res.msg,
|
||||||
|
code: res.code,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -84,7 +84,7 @@ const useBuildingStore = defineStore("buildingInfo", () => {
|
|||||||
// 獲取2D、3D顯示與否
|
// 獲取2D、3D顯示與否
|
||||||
const fetchDashboard2D3D = async (BuildingId) => {
|
const fetchDashboard2D3D = async (BuildingId) => {
|
||||||
const res = await getDashboard2D3D(BuildingId);
|
const res = await getDashboard2D3D(BuildingId);
|
||||||
showForgeArea.value = res.data.is3DEnabled;
|
showForgeArea.value = res.data.is3DEnabled || false;
|
||||||
previewImageExt.value = res.data.previewImageExt || "";
|
previewImageExt.value = res.data.previewImageExt || "";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,7 +6,9 @@ import AssetTableModalLeft from "./AssetTableModalLeft.vue";
|
|||||||
import AssetTableModalRight from "./AssetTableModalRight.vue";
|
import AssetTableModalRight from "./AssetTableModalRight.vue";
|
||||||
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
const { openToast } = inject("app_toast");
|
const { openToast } = inject("app_toast");
|
||||||
const { searchParams, changeParams } = useSearchParam();
|
const { searchParams, changeParams } = useSearchParam();
|
||||||
|
|
||||||
@ -75,8 +77,11 @@ const onOk = async () => {
|
|||||||
main_id: props.editRecord ? props.editRecord.main_id : 0,
|
main_id: props.editRecord ? props.editRecord.main_id : 0,
|
||||||
});
|
});
|
||||||
if (res.isSuccess) {
|
if (res.isSuccess) {
|
||||||
|
openToast("success", t("msg.send_successfully"), "#asset_add_table_item");
|
||||||
props.getData();
|
props.getData();
|
||||||
closeModal();
|
setTimeout(() => {
|
||||||
|
closeModal();
|
||||||
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
openToast("error", res.msg, "#asset_add_table_item");
|
openToast("error", res.msg, "#asset_add_table_item");
|
||||||
}
|
}
|
||||||
@ -102,12 +107,20 @@ const closeModal = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button class="btn btn-sm btn-add mr-3" @click.stop.prevent="openModal" :disabled="!searchParams.subSys_id">
|
<button
|
||||||
|
class="btn btn-sm btn-add mr-3"
|
||||||
|
@click.stop.prevent="openModal"
|
||||||
|
:disabled="!searchParams.subSys_id"
|
||||||
|
>
|
||||||
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
|
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
|
||||||
</button>
|
</button>
|
||||||
<Modal
|
<Modal
|
||||||
id="asset_add_table_item"
|
id="asset_add_table_item"
|
||||||
:title="editRecord?.main_id ? $t('assetManagement.edit_device') : $t('assetManagement.add_device')"
|
:title="
|
||||||
|
editRecord?.main_id
|
||||||
|
? $t('assetManagement.edit_device')
|
||||||
|
: $t('assetManagement.add_device')
|
||||||
|
"
|
||||||
:onCancel="closeModal"
|
:onCancel="closeModal"
|
||||||
:width="1600"
|
:width="1600"
|
||||||
>
|
>
|
||||||
|
@ -96,7 +96,7 @@ const onCancel = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
const Topic = formState.value.topic;
|
const Topic = formState.value.topic_publish;
|
||||||
let Payload = "";
|
let Payload = "";
|
||||||
try {
|
try {
|
||||||
Payload = JSON.stringify(JSON.parse(formState.value.publish_message));
|
Payload = JSON.stringify(JSON.parse(formState.value.publish_message));
|
||||||
@ -130,7 +130,7 @@ const onSubmit = async () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col col-span-2 border-t-gray-400 border-t py-5">
|
<div class="flex flex-col col-span-2 border-t-gray-400 border-t py-5">
|
||||||
<Input :value="formState" name="topic">
|
<Input :value="formState" name="topic_publish">
|
||||||
<template #topLeft>MQTT publish topic</template>
|
<template #topLeft>MQTT publish topic</template>
|
||||||
</Input>
|
</Input>
|
||||||
<Textarea :value="formState" name="publish_message">
|
<Textarea :value="formState" name="publish_message">
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch, onUnmounted } from "vue";
|
import { ref, computed, watch, onUnmounted } from "vue";
|
||||||
|
import SysMap from "./components/SysMap.vue";
|
||||||
import SysProgress from "./components/SysProgress.vue";
|
import SysProgress from "./components/SysProgress.vue";
|
||||||
import ElecRank from "./components/ElecRank.vue";
|
import ElecRank from "./components/ElecRank.vue";
|
||||||
import ElecTrends from "./components/ElecTrends.vue";
|
import ElecTrends from "./components/ElecTrends.vue";
|
||||||
@ -27,11 +28,7 @@ import ElecCompare from "./components/ElecCompare.vue";
|
|||||||
<SysProgress />
|
<SysProgress />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-2 h-full border border-cyan-400 shadow-md shadow-cyan-500/40">
|
<div class="col-span-2 h-full border border-cyan-400 shadow-md shadow-cyan-500/40">
|
||||||
<img
|
<SysMap />
|
||||||
src="/CviLux_globalmap.png"
|
|
||||||
alt=""
|
|
||||||
class="w-full h-full object-cover "
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-1 grid grid-cols-1 xl:grid-rows-3 gap-4">
|
<div class="col-span-1 grid grid-cols-1 xl:grid-rows-3 gap-4">
|
||||||
<ElecRank />
|
<ElecRank />
|
||||||
|
139
src/views/headquarters/components/SysMap.vue
Normal file
139
src/views/headquarters/components/SysMap.vue
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<script setup>
|
||||||
|
import L from "leaflet";
|
||||||
|
import "leaflet/dist/leaflet.css";
|
||||||
|
import { onMounted, ref } from "vue";
|
||||||
|
import { nextTick } from "vue";
|
||||||
|
|
||||||
|
const leafletmapContainer = ref(null);
|
||||||
|
const selectedFactory = ref("");
|
||||||
|
let map = null;
|
||||||
|
let markerRefs = [];
|
||||||
|
|
||||||
|
const customOptions = {
|
||||||
|
minWidth: 250,
|
||||||
|
};
|
||||||
|
|
||||||
|
const markers = [
|
||||||
|
{
|
||||||
|
position: [31.29834, 120.58319],
|
||||||
|
popup: {
|
||||||
|
title: "CCT瀚荃蘇州廠",
|
||||||
|
img: "https://picsum.photos/id/700/600/400",
|
||||||
|
deviceNumber: 10,
|
||||||
|
online: 8,
|
||||||
|
offline: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
position: [29.56301, 106.55156],
|
||||||
|
popup: {
|
||||||
|
title: "CCT瀚荃重慶廠",
|
||||||
|
img: "https://picsum.photos/id/701/600/400",
|
||||||
|
deviceNumber: 20,
|
||||||
|
online: 15,
|
||||||
|
offline: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
position: [23.02067, 113.75179],
|
||||||
|
popup: {
|
||||||
|
title: "CCT瀚荃東莞廠",
|
||||||
|
img: "https://picsum.photos/id/702/600/400",
|
||||||
|
deviceNumber: 30,
|
||||||
|
online: 25,
|
||||||
|
offline: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
position: [25.16742, 121.44587],
|
||||||
|
popup: {
|
||||||
|
title: "CCT瀚荃淡水廠",
|
||||||
|
img: "https://picsum.photos/id/703/600/400",
|
||||||
|
deviceNumber: 46,
|
||||||
|
online: 25,
|
||||||
|
offline: 21,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
map = L.map(leafletmapContainer.value, {
|
||||||
|
center: [31.35, 113.4],
|
||||||
|
zoom: 5,
|
||||||
|
});
|
||||||
|
|
||||||
|
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||||
|
attribution:
|
||||||
|
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
markerRefs = markers.map(({ position, popup }) => {
|
||||||
|
const marker = L.marker(position)
|
||||||
|
.bindPopup(
|
||||||
|
`
|
||||||
|
<div class="font-bold text-lg mb-2">${popup.title}</div>
|
||||||
|
<img src="${popup.img}" class="w-full rounded mb-2" />
|
||||||
|
<div class="flex justify-between text-base mt-2">
|
||||||
|
<div class="text-center">
|
||||||
|
設備總數<br><span class="text-white text-2xl">${popup.deviceNumber}</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
在線設備<br><span class="text-green-500 text-2xl">${popup.online}</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
離線設備<br><span class="text-red-600 text-2xl">${popup.offline}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
customOptions
|
||||||
|
)
|
||||||
|
.addTo(map);
|
||||||
|
return marker;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function focusFactory(idx) {
|
||||||
|
if (!map || !markerRefs[idx]) return;
|
||||||
|
const pos = markers[idx].position;
|
||||||
|
map.flyTo(pos, 6, { animate: true });
|
||||||
|
markerRefs[idx].openPopup();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="relative w-full h-full">
|
||||||
|
<div class="absolute top-4 right-4 z-20 flex items-center gap-2">
|
||||||
|
<select
|
||||||
|
id="factory-select"
|
||||||
|
v-model="selectedFactory"
|
||||||
|
class="select select-sm bg-cyan-950 rounded-md border-info focus-within:border-info"
|
||||||
|
@change="focusFactory(selectedFactory)"
|
||||||
|
>
|
||||||
|
<option value="" disabled>下屬共計 5 家子企業</option>
|
||||||
|
<option v-for="(m, idx) in markers" :key="idx" :value="idx">
|
||||||
|
{{ m.popup.title }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="leafletmapContainer z-10" ref="leafletmapContainer"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style lang="scss">
|
||||||
|
.leafletmapContainer {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-popup-content-wrapper,
|
||||||
|
.leaflet-popup-tip {
|
||||||
|
background: #164e63 !important; // 你要的顏色
|
||||||
|
color: #ffffff;
|
||||||
|
box-shadow: 0 3px 14px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-container a.leaflet-popup-close-button{
|
||||||
|
color: #fff;
|
||||||
|
font-size: 1rem;
|
||||||
|
padding-top: 0.4rem;
|
||||||
|
}
|
||||||
|
</style>
|
@ -9,10 +9,7 @@ import { useI18n } from "vue-i18n";
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const store = useBuildingStore();
|
const store = useBuildingStore();
|
||||||
const equipmentData = ref({
|
const equipmentData = ref([]);
|
||||||
title: t("dashboard.system_status"),
|
|
||||||
items: [],
|
|
||||||
});
|
|
||||||
const modalData = ref({});
|
const modalData = ref({});
|
||||||
let intervalId = null;
|
let intervalId = null;
|
||||||
|
|
||||||
@ -35,7 +32,7 @@ const getAlarmsInfos = async () => {
|
|||||||
|
|
||||||
// 轉換 equipmentData 的資料格式
|
// 轉換 equipmentData 的資料格式
|
||||||
if (apiData && apiData.alarm) {
|
if (apiData && apiData.alarm) {
|
||||||
equipmentData.value.items = apiData.alarm.map((item) => ({
|
equipmentData.value = apiData.alarm.map((item) => ({
|
||||||
label: item.system_name,
|
label: item.system_name,
|
||||||
online: item.online || 0,
|
online: item.online || 0,
|
||||||
offline: item.offline || 0,
|
offline: item.offline || 0,
|
||||||
@ -75,7 +72,7 @@ onUnmounted(() => {
|
|||||||
<div class="state-box">
|
<div class="state-box">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img class="state-title01" src="@ASSET/img/state-title01.svg" />
|
<img class="state-title01" src="@ASSET/img/state-title01.svg" />
|
||||||
<span class="">{{ equipmentData.title }}</span>
|
<span class="">{{$t("dashboard.system_status")}}</span>
|
||||||
<img class="state-title02" src="@ASSET/img/state-title02.svg" />
|
<img class="state-title02" src="@ASSET/img/state-title02.svg" />
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-sm text-center">
|
<table class="table table-sm text-center">
|
||||||
@ -89,7 +86,7 @@ onUnmounted(() => {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr
|
<tr
|
||||||
v-for="(item, index) in equipmentData.items"
|
v-for="(item, index) in equipmentData"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="border-cyan-400 cursor-pointer hover:text-info"
|
class="border-cyan-400 cursor-pointer hover:text-info"
|
||||||
@click.stop.prevent="openModal(item)"
|
@click.stop.prevent="openModal(item)"
|
||||||
|
@ -262,13 +262,13 @@ const getCurrentInfoModalData = async (e, position, value) => {
|
|||||||
document.getElementById("system_info_modal").showModal();
|
document.getElementById("system_info_modal").showModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectedDeviceRealtime = computed(
|
const selectedDeviceRealtime = computed(() => {
|
||||||
() =>
|
const deviceNumber = selectedDevice.value?.value?.device_number;
|
||||||
realtimeData.value?.find(
|
if (!deviceNumber) return [];
|
||||||
({ device_number }) =>
|
return realtimeData.value
|
||||||
device_number === selectedDevice.value?.value?.device_number
|
.filter(item => item.device_number === deviceNumber && Array.isArray(item.data))
|
||||||
)?.data
|
.flatMap(item => item.data.map(dataItem => ({ ...dataItem, topic_publish: item.topic_publish })));
|
||||||
);
|
});
|
||||||
|
|
||||||
const clearSelectedDeviceInfo = () => {
|
const clearSelectedDeviceInfo = () => {
|
||||||
selectedDevice.value.value = null;
|
selectedDevice.value.value = null;
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, inject, watch } from "vue";
|
import { ref, computed, inject, watch } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { toggleDevicePower } from "@/apis/system";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
const { openToast } = inject("app_toast");
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { selectedDevice, selectedDeviceRealtime } = inject(
|
const { selectedDevice, selectedDeviceRealtime } = inject(
|
||||||
"system_selectedDevice"
|
"system_selectedDevice"
|
||||||
@ -13,7 +14,7 @@ const groupedData = computed(() => {
|
|||||||
|
|
||||||
if (selectedDeviceRealtime?.value) {
|
if (selectedDeviceRealtime?.value) {
|
||||||
selectedDeviceRealtime.value.forEach((record) => {
|
selectedDeviceRealtime.value.forEach((record) => {
|
||||||
const { ori_device_number, time } = record;
|
const { ori_device_number, time, topic_publish } = record;
|
||||||
|
|
||||||
if (!grouped[ori_device_number]) {
|
if (!grouped[ori_device_number]) {
|
||||||
grouped[ori_device_number] = {
|
grouped[ori_device_number] = {
|
||||||
@ -26,6 +27,8 @@ const groupedData = computed(() => {
|
|||||||
if (record.point === d.points) {
|
if (record.point === d.points) {
|
||||||
grouped[ori_device_number].data.push({
|
grouped[ori_device_number].data.push({
|
||||||
...d,
|
...d,
|
||||||
|
device_item_id: record.device_item_id,
|
||||||
|
topic_publish: record.topic_publish,
|
||||||
value: record.value,
|
value: record.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -36,9 +39,19 @@ const groupedData = computed(() => {
|
|||||||
return grouped;
|
return grouped;
|
||||||
});
|
});
|
||||||
|
|
||||||
const togglePowerSwitch = (e, val) => {
|
const togglePowerSwitch = async (e, device_item_id, topic_publish) => {
|
||||||
const isChecked = e.target.checked;
|
const isChecked = e.target.checked;
|
||||||
console.log("Power Switch", e, val, "狀態:", isChecked);
|
const res = await toggleDevicePower({
|
||||||
|
device_item_id,
|
||||||
|
topic_publish,
|
||||||
|
new_value: isChecked,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.isSuccess) {
|
||||||
|
openToast("success", t("msg.edit_successfully"), "#system_info_modal");
|
||||||
|
} else {
|
||||||
|
openToast("error", res.msg, "#system_info_modal");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -64,21 +77,23 @@ const togglePowerSwitch = (e, val) => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="(group, index) in group.data" :key="index">
|
<tr v-for="(items, index) in group.data" :key="index">
|
||||||
<td class="border text-white text-lg text-center">
|
<td class="border text-white text-lg text-center">
|
||||||
{{ group.full_name }}
|
{{ items.full_name }}
|
||||||
</td>
|
</td>
|
||||||
<td class="border text-white text-lg text-center">
|
<td class="border text-white text-lg text-center">
|
||||||
<template v-if="group.full_name === 'Power Switch'">
|
<template v-if="items.full_name === 'Power Switch'">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="toggle toggle-success"
|
class="toggle toggle-success"
|
||||||
:checked="group.value"
|
:checked="items.value"
|
||||||
@change="togglePowerSwitch($event, group.value)"
|
@change="
|
||||||
|
togglePowerSwitch($event, items.device_item_id, items.topic_publish)
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
{{ group.value }}
|
{{ items.value }}
|
||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
Loading…
Reference in New Issue
Block a user