|
@@ -0,0 +1,555 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="app">
|
|
|
|
|
+ <el-container class="container" @mousedown="startDrag" @mousemove="drag" @mouseup="endDrag" @mouseleave="endDrag" @contextmenu.prevent>
|
|
|
|
|
+ <BorderBox1 class="cs">
|
|
|
|
|
+ <div style="margin: 20px 0 10px 0;">在线设备:{{onlineData.online}}</div>
|
|
|
|
|
+ <div style="margin: 0 0 20px 0;">总设备:{{onlineData.total}}</div>
|
|
|
|
|
+ <el-progress type="dashboard" :percentage="percentage" :color="colors" />
|
|
|
|
|
+ </BorderBox1>
|
|
|
|
|
+ <div/>
|
|
|
|
|
+ <img ref="map" :src="imageSrc" alt="Map" @dragstart.prevent />
|
|
|
|
|
+ <el-button v-for="(button, index) in buttons" :key="index" class="button" :style="button.style" @click="openRegionDrawer(button)">
|
|
|
|
|
+ {{ button.text }}
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </el-container>
|
|
|
|
|
+ <el-drawer
|
|
|
|
|
+ v-model="table"
|
|
|
|
|
+ :title="regionName"
|
|
|
|
|
+ direction="rtl"
|
|
|
|
|
+ size="90%"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-header>
|
|
|
|
|
+ <el-button type="primary" @click="openAddDevice = true">添加设备</el-button>
|
|
|
|
|
+ <el-button type="primary" :disabled="!selectedDevices.length" @click="openDeviceTiming=true">设备定时</el-button>
|
|
|
|
|
+ <el-button type="primary" :disabled="selectedDevices.length !== 1" @click="openLoopTiming=true">单设备回路定时</el-button>
|
|
|
|
|
+ <el-button type="success" :disabled="!selectedDevices.length" @click="batchDeviceSwitch(1)">开</el-button>
|
|
|
|
|
+ <el-button type="danger" :disabled="!selectedDevices.length" @click="batchDeviceSwitch(0)">关</el-button>
|
|
|
|
|
+ </el-header>
|
|
|
|
|
+ <el-main>
|
|
|
|
|
+ <el-table :data="deviceData" @selection-change="handleSelectionChange">
|
|
|
|
|
+ <el-table-column type="selection" width="55" />
|
|
|
|
|
+ <el-table-column label="编号" prop="id" width="100" align="center"/>
|
|
|
|
|
+ <el-table-column label="设备sn" prop="sn" width="200" align="center"/>
|
|
|
|
|
+ <el-table-column label="名称" prop="name" width="150" align="center"/>
|
|
|
|
|
+ <el-table-column label="类型" prop="genre" width="150" align="center"/>
|
|
|
|
|
+ <el-table-column label="回路" prop="deviceLoops" width="250" align="center">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <span v-for="(item2, index) in scope.row.deviceLoops" :key="index">
|
|
|
|
|
+ <el-tooltip
|
|
|
|
|
+ class="item"
|
|
|
|
|
+ effect="dark"
|
|
|
|
|
+ :content="`时控1:${item2.timeCondition1OnTime}-${item2.timeCondition1OffTime},时控2:${item2.timeCondition2OnTime}-${item2.timeCondition2OffTime}`"
|
|
|
|
|
+ placement="top-start"
|
|
|
|
|
+ >
|
|
|
|
|
+<!-- ${item2}-${scope.row.relayTimeStr[index]}-->
|
|
|
|
|
+ <el-icon
|
|
|
|
|
+ v-if="item2.state"
|
|
|
|
|
+ style="color: green;"
|
|
|
|
|
+ @click="switchLoop(item2)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <CircleCheckFilled />
|
|
|
|
|
+ </el-icon>
|
|
|
|
|
+ <el-icon
|
|
|
|
|
+ v-if="!item2.state"
|
|
|
|
|
+ @click="switchLoop(item2)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <SwitchButton />
|
|
|
|
|
+ </el-icon>
|
|
|
|
|
+ </el-tooltip>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column >
|
|
|
|
|
+ <el-table-column label="状态" prop="state" width="150" align="center">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <el-tag type="success" v-if="scope.row.state">
|
|
|
|
|
+ 在线
|
|
|
|
|
+ </el-tag>
|
|
|
|
|
+ <el-tag type="info" v-if="!scope.row.state">离线</el-tag>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="是否外接" prop="isSun" width="150" align="center">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <el-switch
|
|
|
|
|
+ v-model="scope.row.isSun"
|
|
|
|
|
+ class="ml-2"
|
|
|
|
|
+ style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
|
|
|
|
|
+ @change="save"
|
|
|
|
|
+ />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="操作" prop="action" width="400" align="center">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <el-button type="success" @click="switchDevice(scope.row,1)">开</el-button>
|
|
|
|
|
+ <el-button type="danger" @click="switchDevice(scope.row,0)">关</el-button>
|
|
|
|
|
+ <el-button type="primary" v-if="scope.row.isSun" @click="">太阳能数据</el-button>
|
|
|
|
|
+ <el-button type="primary" @click="openUpdateDevice(scope.row)">编辑</el-button>
|
|
|
|
|
+ <el-button type="danger" @click="deleteDevice(scope.$index)">删除</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+ </el-main>
|
|
|
|
|
+ <el-dialog
|
|
|
|
|
+ v-model="openAddDevice"
|
|
|
|
|
+ title="新增"
|
|
|
|
|
+ width="400"
|
|
|
|
|
+ align-center
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-form label-width="auto">
|
|
|
|
|
+ <el-form-item label="ID" label-position="left">
|
|
|
|
|
+ <el-input placeholder="ID" v-model.number="addDeviceData.id"></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="Sn" label-position="left">
|
|
|
|
|
+ <el-input placeholder="Sn" v-model="addDeviceData.sn"></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="名称" label-position="left">
|
|
|
|
|
+ <el-input placeholder="名称" v-model="addDeviceData.name"></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="类型" label-position="left">
|
|
|
|
|
+ <el-input placeholder="四路控制" v-model="addDeviceData.genre"></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="回路数" label-position="left">
|
|
|
|
|
+ <el-input placeholder="4" v-model.number="addDeviceData.loopNumber"></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item>
|
|
|
|
|
+ <el-button type="primary" @click="addDevice">提交</el-button>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ <el-dialog
|
|
|
|
|
+ v-model="isUpdateDevice"
|
|
|
|
|
+ title="编辑"
|
|
|
|
|
+ width="400"
|
|
|
|
|
+ align-center
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-form label-width="auto">
|
|
|
|
|
+ <el-form-item label="ID" label-position="left">
|
|
|
|
|
+ <el-input placeholder="ID" v-model.number="updateDeviceData.id"></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="Sn" label-position="left">
|
|
|
|
|
+ <el-input placeholder="Sn" v-model="updateDeviceData.sn"></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="名称" label-position="left">
|
|
|
|
|
+ <el-input placeholder="名称" v-model="updateDeviceData.name"></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item v-for="item in updateDeviceData.deviceLoops" label="回路名" label-position="left">
|
|
|
|
|
+ <el-input placeholder="回路名" v-model="item.name"></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item>
|
|
|
|
|
+ <el-button type="primary" @click="updateDevice">提交</el-button>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ <el-dialog
|
|
|
|
|
+ v-model="openDeviceTiming"
|
|
|
|
|
+ title="设备定时"
|
|
|
|
|
+ width="800"
|
|
|
|
|
+ align-center
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-form ref="elFormRefTime" :model="formDataTime" label-position="right" :rules="rule" label-width="80px">
|
|
|
|
|
+ <deviceReplayTimeSet :selected-devices="selectedDevices" @save="save" />
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ <el-dialog
|
|
|
|
|
+ v-model="openLoopTiming"
|
|
|
|
|
+ title="设备定时"
|
|
|
|
|
+ width="800"
|
|
|
|
|
+ align-center
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-form ref="elFormRefTime" :model="formDataTime" label-position="right" :rules="rule" label-width="80px">
|
|
|
|
|
+ <deviceLoopReplayTimeSet :selected-devices="selectedDevices" @save="save" />
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ </el-drawer>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import {ref, onMounted, reactive, computed} from 'vue';
|
|
|
|
|
+import {BorderBox1,BorderBox3 } from '@dataview/datav-vue3';
|
|
|
|
|
+import {ElContainer, ElButton, ElMessage, ElMessageBox} from 'element-plus';
|
|
|
|
|
+import {deviceBatchSwitch, deviceLoopSwitch, deviceSwitch, getOnlineDevice, queryData, saveData} from "@/api/device.js";
|
|
|
|
|
+import DeviceReplayTimeSet from "@/comm/deviceReplayTimeSet.vue";
|
|
|
|
|
+import DeviceLoopReplayTimeSet from "@/comm/deviceLoopReplayTimeSet.vue";
|
|
|
|
|
+
|
|
|
|
|
+const imageSrc = '/src/static/jx4.png'; // 替换为你的图片路径
|
|
|
|
|
+const map = ref(null);
|
|
|
|
|
+let isDragging = false;
|
|
|
|
|
+let dragStartX = 0;
|
|
|
|
|
+let dragStartY = 0;
|
|
|
|
|
+let currentMapLeft = 0;
|
|
|
|
|
+let currentMapTop = 0;
|
|
|
|
|
+const dragSpeed = 0.1; // 控制拖动速度,值越小速度越慢
|
|
|
|
|
+
|
|
|
|
|
+const buttons = ref([
|
|
|
|
|
+ { text: '生活区', initialLeft: 500, initialTop: 1800 },
|
|
|
|
|
+ { text: '股份公司进场上坡', initialLeft: 500, initialTop: 1550 },
|
|
|
|
|
+ { text: '地磅房至污泥厂门口', initialLeft: 1150, initialTop: 1500 },
|
|
|
|
|
+ { text: '三角花园至油库', initialLeft: 1500, initialTop: 1250 },
|
|
|
|
|
+ { text: '地磅房至搅拌站', initialLeft: 950, initialTop: 1900 },
|
|
|
|
|
+ { text: '搅拌站至三岔路口', initialLeft: 2100, initialTop: 1200 },
|
|
|
|
|
+ { text: '垃圾堆体道路', initialLeft: 2300, initialTop: 600 },
|
|
|
|
|
+ { text: '污水进场道路', initialLeft: 2200, initialTop: 300 }
|
|
|
|
|
+]);
|
|
|
|
|
+
|
|
|
|
|
+function startDrag(event) {
|
|
|
|
|
+ isDragging = true;
|
|
|
|
|
+ dragStartX = event.clientX;
|
|
|
|
|
+ dragStartY = event.clientY;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function drag(event) {
|
|
|
|
|
+ if (!isDragging) return;
|
|
|
|
|
+
|
|
|
|
|
+ const containerRect = map.value.parentElement.getBoundingClientRect();
|
|
|
|
|
+ const mapRect = map.value.getBoundingClientRect();
|
|
|
|
|
+
|
|
|
|
|
+ const deltaX = (event.clientX - dragStartX) * dragSpeed;
|
|
|
|
|
+ const deltaY = (event.clientY - dragStartY) * dragSpeed;
|
|
|
|
|
+
|
|
|
|
|
+ const newX = currentMapLeft + deltaX;
|
|
|
|
|
+ const newY = currentMapTop + deltaY;
|
|
|
|
|
+
|
|
|
|
|
+ // 计算边界限制
|
|
|
|
|
+ const minX = -(mapRect.width - containerRect.width); // 左侧边缘不能完全移出容器
|
|
|
|
|
+ const maxX = 0; // 右侧边缘可以超过容器
|
|
|
|
|
+ const minY = -(mapRect.height - containerRect.height); // 顶部边缘不能完全移出容器
|
|
|
|
|
+ const maxY = 0; // 底部边缘可以超过容器
|
|
|
|
|
+
|
|
|
|
|
+ // 应用边界限制
|
|
|
|
|
+ const finalX = Math.max(minX, Math.min(maxX, newX));
|
|
|
|
|
+ const finalY = Math.max(minY, Math.min(maxY, newY));
|
|
|
|
|
+
|
|
|
|
|
+ currentMapLeft = finalX;
|
|
|
|
|
+ currentMapTop = finalY;
|
|
|
|
|
+
|
|
|
|
|
+ map.value.style.left = `${finalX}px`;
|
|
|
|
|
+ map.value.style.top = `${finalY}px`;
|
|
|
|
|
+
|
|
|
|
|
+ // 更新按钮位置
|
|
|
|
|
+ updateButtonPositions();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function endDrag() {
|
|
|
|
|
+ isDragging = false;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function updateButtonPositions() {
|
|
|
|
|
+ buttons.value.forEach((button) => {
|
|
|
|
|
+ button.style = {
|
|
|
|
|
+ left: `${button.initialLeft + currentMapLeft}px`,
|
|
|
|
|
+ top: `${button.initialTop + currentMapTop}px`
|
|
|
|
|
+ };
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const regionData = ref()
|
|
|
|
|
+const onlineData = ref({
|
|
|
|
|
+ online: 0,
|
|
|
|
|
+ total:0
|
|
|
|
|
+})
|
|
|
|
|
+const getData = async() => {
|
|
|
|
|
+ await queryData().then(res => {
|
|
|
|
|
+ console.log(res)
|
|
|
|
|
+ regionData.value = res.data
|
|
|
|
|
+ })
|
|
|
|
|
+ await getOnlineDevice().then(res => {
|
|
|
|
|
+ console.log(res.data)
|
|
|
|
|
+ onlineData.value = res.data
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const percentage = computed(() => {
|
|
|
|
|
+ if (onlineData.value.total === 0) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ const result = (onlineData.value.online / onlineData.value.total) * 100;
|
|
|
|
|
+ return Math.round(result);
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const colors = [
|
|
|
|
|
+ { color: '#778899', percentage: 20 },
|
|
|
|
|
+ { color: '#DC143C', percentage: 40 },
|
|
|
|
|
+ { color: '#FFD700', percentage: 60 },
|
|
|
|
|
+ { color: '#1989fa', percentage: 80 },
|
|
|
|
|
+ { color: '#00FF7F', percentage: 100 },
|
|
|
|
|
+]
|
|
|
|
|
+
|
|
|
|
|
+const table = ref(false)
|
|
|
|
|
+
|
|
|
|
|
+const regionName = ref()
|
|
|
|
|
+const deviceData = ref()
|
|
|
|
|
+const openRegionDrawer = (val) => {
|
|
|
|
|
+ table.value = true;
|
|
|
|
|
+ regionName.value = val.text;
|
|
|
|
|
+
|
|
|
|
|
+ for (let i = 0; i < regionData.value.length; i++) {
|
|
|
|
|
+ if (regionData.value[i].name === regionName.value) {
|
|
|
|
|
+ deviceData.value = regionData.value[i].devices
|
|
|
|
|
+ addDeviceData.value.regionId = regionData.value[i].id
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+//新增
|
|
|
|
|
+const openAddDevice = ref(false)
|
|
|
|
|
+const addDeviceData = ref({
|
|
|
|
|
+ id: null,
|
|
|
|
|
+ sn: '',
|
|
|
|
|
+ name: '',
|
|
|
|
|
+ regionId: null,
|
|
|
|
|
+ genre: "八回路控制",
|
|
|
|
|
+ state: 1,
|
|
|
|
|
+ isSun: false,
|
|
|
|
|
+ loopNumber : 8,
|
|
|
|
|
+ deviceLoops: []
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const addDevice = () => {
|
|
|
|
|
+ if (addDeviceData.value.id === null || addDeviceData.value.sn === null) {
|
|
|
|
|
+ ElMessage.error("数据不能为空")
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ for (let i = 0; i < addDeviceData.value.loopNumber; i++) {
|
|
|
|
|
+ const loop = {
|
|
|
|
|
+ id: i+1,
|
|
|
|
|
+ deviceId: addDeviceData.value.sn,
|
|
|
|
|
+ state: 0,
|
|
|
|
|
+ name: "回路"+(i+1),
|
|
|
|
|
+ timeCondition1OnTime: '关闭',
|
|
|
|
|
+ timeCondition1OffTime: '关闭',
|
|
|
|
|
+ timeCondition2OnTime: '关闭',
|
|
|
|
|
+ timeCondition2OffTime: '关闭',
|
|
|
|
|
+ }
|
|
|
|
|
+ addDeviceData.value.deviceLoops.push(loop)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ deviceData.value.push(addDeviceData.value)
|
|
|
|
|
+ save()
|
|
|
|
|
+ ElMessage.success("添加成功")
|
|
|
|
|
+ openAddDevice.value = false
|
|
|
|
|
+ // 新增设备逻辑
|
|
|
|
|
+}
|
|
|
|
|
+//编辑
|
|
|
|
|
+const isUpdateDevice = ref(false)
|
|
|
|
|
+const updateDeviceData = ref()
|
|
|
|
|
+const openUpdateDevice = (val) => {
|
|
|
|
|
+ updateDeviceData.value = val
|
|
|
|
|
+ isUpdateDevice.value = true
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const updateDevice = () => {
|
|
|
|
|
+ if (updateDeviceData.value.id === null || updateDeviceData.value.sn === null) {
|
|
|
|
|
+ ElMessage.error("数据不能为空")
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ save()
|
|
|
|
|
+ isUpdateDevice.value = false
|
|
|
|
|
+ ElMessage.success("修改成功")
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+//删除
|
|
|
|
|
+const deleteDevice = (index) => {
|
|
|
|
|
+ ElMessageBox.confirm(
|
|
|
|
|
+ '将永久删除该数据,确定吗?',
|
|
|
|
|
+ '删除',
|
|
|
|
|
+ {
|
|
|
|
|
+ confirmButtonText: '确定',
|
|
|
|
|
+ cancelButtonText: '取消',
|
|
|
|
|
+ type: 'warning',
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+ .then(() => {
|
|
|
|
|
+ deviceData.value.splice(index,1)
|
|
|
|
|
+ ElMessage({
|
|
|
|
|
+ type: 'success',
|
|
|
|
|
+ message: '删除成功',
|
|
|
|
|
+ })
|
|
|
|
|
+ save()
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(() => {
|
|
|
|
|
+ ElMessage({
|
|
|
|
|
+ type: 'info',
|
|
|
|
|
+ message: '删除已取消',
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 开关回路
|
|
|
|
|
+const switchLoop = async(val) => {
|
|
|
|
|
+ val.state = val.state === 1 ? 0 : 1
|
|
|
|
|
+ console.log(val)
|
|
|
|
|
+ await deviceLoopSwitch(val).then(res => {
|
|
|
|
|
+ console.log(res)
|
|
|
|
|
+ // 开关回路
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+// 开关设备
|
|
|
|
|
+const switchDevice = async(val, state) => {
|
|
|
|
|
+ if (val.state === 0) {
|
|
|
|
|
+ ElMessage.error("设备离线")
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ await deviceSwitch({
|
|
|
|
|
+ device: val,
|
|
|
|
|
+ state: state
|
|
|
|
|
+ }).then(res => {
|
|
|
|
|
+ console.log(res)
|
|
|
|
|
+ // 开关设备
|
|
|
|
|
+ for (let i = 0; i < val.deviceLoops.length; i++) {
|
|
|
|
|
+ val.deviceLoops[i].state = state
|
|
|
|
|
+ }
|
|
|
|
|
+ save()
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const batchDeviceSwitch = async (state) => {
|
|
|
|
|
+ await deviceBatchSwitch({
|
|
|
|
|
+ devices: selectedDevices.value,
|
|
|
|
|
+ state: state
|
|
|
|
|
+ }).then(res => {
|
|
|
|
|
+ if (res.code === 0) {
|
|
|
|
|
+ ElMessage.success("批量操作成功")
|
|
|
|
|
+ openDeviceTiming.value = false
|
|
|
|
|
+ // 批量开关设备
|
|
|
|
|
+ deviceData.value
|
|
|
|
|
+ for (let i = 0; i < deviceData.value.length; i++) {
|
|
|
|
|
+ for (let j = 0; j < selectedDevices.value.length; j++) {
|
|
|
|
|
+ if (deviceData.value[i].sn === selectedDevices.value[j].sn) {
|
|
|
|
|
+ for (let k = 0; k < deviceData.value[i].deviceLoops.length; k++) {
|
|
|
|
|
+ if (deviceData.value[i].deviceLoops[k].deviceId === selectedDevices.value[j].sn) {
|
|
|
|
|
+ deviceData.value[i].deviceLoops[k].state = state
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ save()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ElMessage.error(res.msg)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 批量开关设备
|
|
|
|
|
+
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const selectedDevices = ref([])
|
|
|
|
|
+const handleSelectionChange = (val) => {
|
|
|
|
|
+ selectedDevices.value = val
|
|
|
|
|
+ console.log(val)
|
|
|
|
|
+ // 选中设备
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 设备定时
|
|
|
|
|
+const openDeviceTiming = ref(false)
|
|
|
|
|
+
|
|
|
|
|
+const formDataTime = ref({
|
|
|
|
|
+ timeCondition1OnTime: '关闭',
|
|
|
|
|
+ timeCondition1OffTime: '关闭',
|
|
|
|
|
+ timeCondition2OnTime: '关闭',
|
|
|
|
|
+ timeCondition2OffTime: '关闭',
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// 验证规则
|
|
|
|
|
+const rule = reactive({
|
|
|
|
|
+ deviceSn: [{
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ message: '',
|
|
|
|
|
+ trigger: ['input', 'blur'],
|
|
|
|
|
+ }],
|
|
|
|
|
+ deviceId: [{
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ message: '',
|
|
|
|
|
+ trigger: ['input', 'blur'],
|
|
|
|
|
+ }],
|
|
|
|
|
+ circuitNum: [{
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ message: '',
|
|
|
|
|
+ trigger: ['input', 'blur'],
|
|
|
|
|
+ }],
|
|
|
|
|
+ status: [{
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ message: '',
|
|
|
|
|
+ trigger: ['input', 'blur'],
|
|
|
|
|
+ }],
|
|
|
|
|
+ module: [{
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ message: '',
|
|
|
|
|
+ trigger: ['input', 'blur'],
|
|
|
|
|
+ }],
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// 回路定时
|
|
|
|
|
+const openLoopTiming = ref(false)
|
|
|
|
|
+
|
|
|
|
|
+//保存
|
|
|
|
|
+const save = () => {
|
|
|
|
|
+ saveData(regionData.value)
|
|
|
|
|
+}
|
|
|
|
|
+// 定时查询
|
|
|
|
|
+setInterval(() => {
|
|
|
|
|
+ getData()
|
|
|
|
|
+}, 300000);
|
|
|
|
|
+
|
|
|
|
|
+onMounted(() => {
|
|
|
|
|
+ // 初始化地图位置
|
|
|
|
|
+ map.value.style.left = `${currentMapLeft}px`;
|
|
|
|
|
+ map.value.style.top = `${currentMapTop}px`;
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化按钮位置
|
|
|
|
|
+ updateButtonPositions();
|
|
|
|
|
+ getData()
|
|
|
|
|
+});
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+.app {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ width: 100vw;
|
|
|
|
|
+ height: 100vh;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.container {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ background-color: #f4f4f4;
|
|
|
|
|
+ border: 1px solid #ccc;
|
|
|
|
|
+ cursor: move;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+img {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ max-width: none; /* 确保图片不受最大宽度限制 */
|
|
|
|
|
+ max-height: none; /* 确保图片不受最大高度限制 */
|
|
|
|
|
+ user-select: none;
|
|
|
|
|
+ -webkit-user-drag: none; /* 禁止图片拖动 */
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.button {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ padding: 5px 10px;
|
|
|
|
|
+ background-color: rgba(0, 0, 0, 0.5);
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ border-radius: 5px;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ user-select: none;
|
|
|
|
|
+}
|
|
|
|
|
+.cs {
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+ width: 200px;
|
|
|
|
|
+ height: 230px;
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+}
|
|
|
|
|
+.cs1 {
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+ width: 200px;
|
|
|
|
|
+ height: 100px;
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|