Pārlūkot izejas kodu

修改锁定站新增开关状态页面

pm 6 mēneši atpakaļ
vecāks
revīzija
ec6581607a

+ 21 - 4
src/router/index.js

@@ -248,6 +248,7 @@ export const dynamicRoutes = [
       }
     ]
   },
+  // 锁定站详情
   {
     path: '/mes/hw/lotoStation/index',
     component: Layout,
@@ -255,13 +256,14 @@ export const dynamicRoutes = [
     permissions: ['iscs:station:list'],
     children: [
       {
-        path: 'MapData',
-        component: () => import('@/views/mes/dv/lotoStation/MapData'),
-        name: 'MapData',
-        meta: { title: '预览', activeMenu: '/mes/hw/lotoStation/MapData' }
+        path: 'LookDetail',
+        component: () => import('@/views/mes/dv/lotoStation/LookDetail'),
+        name: 'LookDetail',
+        meta: { title: '预览', activeMenu: '/mes/hw/lotoStation/LookDetail' }
       }
     ]
   },
+  // 设备工艺详情
   {
     path: '/mes/dv/technology/technologyList/index',
     component: Layout,
@@ -315,6 +317,21 @@ export const dynamicRoutes = [
       }
     ]
   },
+  // 锁定站详情跳转的页面
+  {
+    path: '/system/role-auth',
+    component: Layout,
+    hidden: true,
+    permissions: ['system:role:edit'],
+    children: [
+      {
+        path: 'user/:roleId(\\d+)',
+        component: () => import('@/views/system/role/AuthUser.vue'),
+        name: 'AuthUser',
+        meta: { title: '分配用户', activeMenu: '/system/role' }
+      }
+    ]
+  },
   {
     path: '/system/role-auth',
     component: Layout,

+ 55 - 0
src/views/mes/dv/lotoStation/LookDetail.vue

@@ -0,0 +1,55 @@
+<template>
+  <div class="container">
+    <el-radio-group v-model="tabPosition" style="margin: 5px">
+      <el-radio-button label="first">锁定站</el-radio-button>
+      <el-radio-button label="second">开关状态</el-radio-button>
+      <el-radio-button label="third">隔离点列表</el-radio-button>
+    </el-radio-group>
+
+    <component :is="currentComponent" :lotoId="this.lotoId"/>
+  </div>
+</template>
+
+<script>
+import MapData from "./MapData";
+import PointList from "./PointList";
+import SwitchStatus from "./SwitchStatus";
+
+export default {
+  components: {
+    MapData,
+    PointList,
+    SwitchStatus
+  },
+  data() {
+    return {
+      tabPosition: 'first',
+      lotoId: '',
+    }
+  },
+  computed: {
+    currentComponent() {
+      const components = {
+        third: 'PointList',
+        first: 'MapData',
+        second: 'SwitchStatus'
+      }
+      return components[this.tabPosition]
+    }
+  },
+  mounted() {
+    this.lotoId = this.$route.query.lotoId;
+    console.log(this.lotoId,'this.lotoId');
+  },
+  methods: {}
+}
+</script>
+
+<style scoped>
+.container {
+  width: 100%;
+  height: 700px;
+  padding: 20px;
+  box-sizing: border-box;
+}
+</style>

+ 19 - 10
src/views/mes/dv/lotoStation/MapData.vue

@@ -4,30 +4,32 @@
     <div class="left">
       <div
         class="bottombtn"
-        style="width: 100%; height: 35px; padding: 10px 0 0"
+        style="width: 100%; height: 35px; padding: 10px;display: flex;flex-direction: column;"
       >
         <el-button
           v-no-more-click
           @click="close"
           type="primary"
           icon="el-icon-close"
-          style="float: right; height: 33px; line-height: 2px; margin: 10px 0"
+          style="align-self: flex-end;margin-top: 10px"
         >关闭
         </el-button>
+
         <el-button
           v-no-more-click
           @click="save"
           type="primary"
           icon="el-icon-check"
-          style="float: right; height: 33px; line-height: 2px; margin: 10px 0"
+          style="align-self: flex-end;margin-top: 10px"
         >保存
         </el-button>
+
         <el-button
           v-no-more-click
           @click="reset"
           type="primary"
           icon="el-icon-setting"
-          style="float: right; height: 33px; line-height: 2px; margin: 10px 0"
+          style="align-self: flex-end;margin-top: 10px"
         >重置
         </el-button>
 
@@ -90,9 +92,9 @@ import {
   updateLoto,
   updatePointsBindingLoto
 } from '@/api/mes/lotoStation/lotoStation'
-import { getIsIsolationPointPage } from '@/api/mes/spm/segregationPoint'
-import { getIsMapPointPage, selectIsMapPointById, updateMapPointList } from '@/api/system/mappoint'
-import { selectIsMapById } from '@/api/system/mapconfig'
+import {getIsIsolationPointPage} from '@/api/mes/spm/segregationPoint'
+import {getIsMapPointPage, selectIsMapPointById, updateMapPointList} from '@/api/system/mappoint'
+import {selectIsMapById} from '@/api/system/mapconfig'
 
 export default {
   name: 'KonvaExample',
@@ -129,7 +131,8 @@ export default {
       pointList: null,//接口给的所有点位数据
       newbindingPoints: [],//给地图点位界面更新的绑定隔离点
       newmovePoints: [],//给地图点位界面更新位置
-      newunbindingPoints: []//给地图点位界面更新解绑数据
+      newunbindingPoints: [],//给地图点位界面更新解绑数据
+
     }
   },
   // watch: {
@@ -272,7 +275,7 @@ export default {
           } catch (err) {
           }
         }
-        this.initKonva()
+        // this.initKonva()
       })
 
     },
@@ -352,7 +355,9 @@ export default {
     //   }
     // },
     close() {
-      this.$router.push('/mes/dv/lotoStation')
+      // this.$router.push('/mes/dv/lotoStation')
+      this.getInfo()
+      // this.initKonva()
     },
     save() {
       this.$confirm('请确认是否保存修改内容', '提示', {
@@ -564,6 +569,7 @@ export default {
       console.log(positions, 'positions')
       positions.forEach((pos, index) => {
         // console.log(pos,'单条数据');
+
         const x = pos.x * 50 // 每个单元格宽度为50
         const y = pos.y * 50 // 每个单元格高度为50
         const labelText = pos.entityName // 对应的文字
@@ -623,9 +629,11 @@ export default {
           })
 
           // 将所有元素添加到group中
+
           group.add(bgrect)
           group.add(rect)
           group.add(knovaImage)
+
           group.add(text)
 
           // 将group添加到layer
@@ -944,6 +952,7 @@ export default {
             // 重新绘制图层
             this.layer.draw()
           })
+
         }
       })
     },

+ 673 - 0
src/views/mes/dv/lotoStation/PointList.vue

@@ -0,0 +1,673 @@
+<template>
+  <div class="app-container">
+    <el-table
+      height="800"
+      v-loading="loading"
+      :data="isolationList"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" align="center"/>
+      <!-- <el-table-column label="隔离点ID" align="center" prop="pointId">
+        <template slot-scope="scope">
+          <el-button v-no-more-click
+            type="text"
+            @click="handleView(scope.row)"
+            v-hasPermi="['mes:md:seg:query']"
+            >{{ scope.row.pointId }}
+          </el-button>
+        </template>
+      </el-table-column> -->
+      <el-table-column label="隔离点编号" align="center" prop="pointCode" width="100">
+        <template slot-scope="scope">
+          <el-button
+            v-no-more-click
+            type="text"
+            @click="handleView(scope.row)"
+            v-hasPermi="['iscs:point:list']"
+          >{{ scope.row.pointCode }}
+          </el-button>
+        </template>
+      </el-table-column>
+      <el-table-column label="隔离点名称" align="center" prop="pointName"/>
+      <el-table-column
+        label="隔离点图标"
+        align="center"
+        prop="pointIcon"
+        width="90"
+      >
+        <template slot-scope="scope">
+          <img
+            v-if="scope.row.pointIcon"
+            :src="scope.row.pointIcon"
+            alt=""
+            style="width: 50px; height: 50px"
+          />
+          <span v-else>-</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="开关状态" align="center" prop="switchStatus">
+        <template slot-scope="scope">
+          <!--          <dict-tag :options="dict.type.switch_status" :value="scope.row.switchStatus"></dict-tag>-->
+          <el-switch
+            style="pointer-events: none;"
+            v-if="scope.row.switchStatus!==null"
+            v-model="scope.row.switchStatus"
+            active-value="1"
+            inactive-value="0"
+            active-color="#13ce66"
+            inactive-color="grey"
+          ></el-switch>
+          <span v-else>-</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="隔离点NFC" align="center" prop="pointNfc" ></el-table-column>
+      <el-table-column label="岗位" align="center" prop="workstationName">
+      </el-table-column>
+      <el-table-column label="设备/工艺" align="center" prop="machineryName">
+      </el-table-column>
+      <el-table-column label="锁定站" align="center" prop="lotoName">
+      </el-table-column>
+      <el-table-column label="作用" align="center" prop="remark">
+      </el-table-column>
+      <el-table-column
+        label="隔离点图片"
+        align="center"
+        prop="pointPicture"
+        width="90"
+      >
+        <template slot-scope="scope">
+          <img
+            v-if="scope.row.pointPicture"
+            :src="scope.row.pointPicture"
+            alt=""
+            style="width: 50px; height: 50px"
+          />
+          <span v-else>-</span>
+        </template>
+      </el-table-column>
+
+      <el-table-column label="能量源" align="center" prop="powerType">
+        <template slot-scope="scope">
+          <dict-tag
+            :options="dict.type.power_type"
+            :value="scope.row.powerType"
+          />
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.current"
+      :limit.sync="queryParams.size"
+      @pagination="getList"
+    />
+
+  </div>
+</template>
+
+<script>
+import {
+  getIsIsolationPointPage,
+  addinsertIsIsolationPoint,
+  updateIsIsolationPoint,
+  workshoplistAll,
+  getIsWorkareaList,
+  selectIsIsolationPointById,
+  deleteIsIsolationPointByPointIds
+} from '@/api/mes/spm/segregationPoint'
+import { genCode } from '@/api/system/autocode/rule'
+import Treeselect from '@riophae/vue-treeselect'
+import '@riophae/vue-treeselect/dist/vue-treeselect.css'
+import { listWorkarea } from '@/api/mes/wa/workarea'
+import { listLockType } from '@/api/mes/locktype/locktype'
+import { listPadLockTypeAPI } from '@/api/mes/padLockType/padLockType'
+import { listLoto } from '@/api/mes/lotoStation/lotoStation'
+import { listMarsDept } from '@/api/system/marsdept'
+import { listTechnology } from '@/api/system/machinery'
+import { getIsSystemAttributeByKey, selectIsSystemAttributeById } from '@/api/system/configuration'
+
+export default {
+  name: 'Team',
+  components: { Treeselect },
+  props: {
+    lotoId: {
+      type: String, // 或 Number,根据你的实际类型
+      required: true
+    }
+  },
+  dicts: ['power_type', 'point_type', 'lock_type','switch_status'],
+  data() {
+    return {
+      //自动生成编码
+      autoGenFlag: false,
+      optType: undefined,
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      codes: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 部门树选项
+      deptOptions: [],
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 班组表格数据
+      isolationList: [],
+      // 弹出层标题
+      title: '',
+      // 是否显示弹出层
+      open: false,
+      // 车间数据
+      workshopList: [],
+      // 作业区域数据
+      workareaList: [],
+      // 新增或修改
+      pointId: null,
+      // 查询参数
+      createTime: '',
+      queryParams: {
+        current: 1,
+        size: 10,
+        pointCode: '',
+        pointName: '',
+        delFlag: '',
+        pointType: '',
+        powerType: '',
+        startTime: '',
+        endTime: '',
+        lotoId:null,
+      },
+      pickerOptions: {
+        shortcuts: [
+          {
+            text: '最近一周',
+            onClick(picker) {
+              const end = new Date()
+              const start = new Date()
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
+              picker.$emit('pick', [start, end])
+            }
+          },
+          {
+            text: '最近一个月',
+            onClick(picker) {
+              const end = new Date()
+              const start = new Date()
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
+              picker.$emit('pick', [start, end])
+            }
+          },
+          {
+            text: '最近三个月',
+            onClick(picker) {
+              const end = new Date()
+              const start = new Date()
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
+              picker.$emit('pick', [start, end])
+            }
+          }
+        ]
+      },
+      // 表单参数
+      form: {},
+      //工艺树
+      machineryOptions: [],
+      LockTypeOptions: [],//锁具机构类型下拉
+      padLockTypeOptions: [],//挂锁类型下拉
+
+      lotoOptions: [],//电柜下拉
+      // 表单校验
+      rules: {
+        pointCode: [
+          { required: true, message: '隔离点编号不能为空', trigger: 'blur' }
+        ],
+        pointName: [
+          { required: true, message: '隔离点名称不能为空', trigger: 'blur' }
+        ],
+        workshopId: [
+          { required: true, message: '所属车间不能为空', trigger: 'blur' }
+        ],
+        workareaId: [
+          { required: true, message: '作业区域不能为空', trigger: 'blur' }
+        ],
+        lotoId: [
+          { required: true, message: '锁定站不能为空', trigger: 'blur' }
+        ],
+        pointType: [
+          { required: true, message: '隔离点类型不能为空', trigger: 'blur' }
+        ],
+        lockTypeId: [
+          { required: true, message: '挂锁类型不能为空', trigger: 'blur' }
+        ],
+        pointNfc: [
+          { required: true, message: '隔离点NFC不能为空', trigger: 'blur' }
+        ]
+      },
+      imageMap: {
+        0: '', //电能
+        1: '', //阀门
+        2: '', //空气能
+        3: '' //急停开关
+      },
+      selectedImageIndex: -1 // 用于记录选中的图片索引
+    }
+  },
+  watch:{
+    lotoId(newVal) {
+      console.log('lotoId changed:', newVal);
+      // 这里可以执行需要的逻辑
+      this.queryParams.lotoId = newVal;
+      this.getList()
+    }
+  },
+  created() {
+    this.getList()
+    this.getworkShop()
+    this.getworkArea()
+  },
+
+  methods: {
+    // 格式化日期查询数据
+    formatDate(date) {
+      if (date && date instanceof Date && !isNaN(date)) {
+        // 使用本地时间
+        return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
+          2,
+          '0'
+        )}-${String(date.getDate()).padStart(2, '0')}`
+      }
+      return null
+    },
+    // 选择隔离点图标
+    selectIcon(imageUrl, index) {
+      this.form.pointIcon = imageUrl
+      this.selectedImageIndex = index
+    },
+    /** 查询隔离点信息列表 */
+    getList() {
+      this.loading = true
+      // 格式化日期并更新queryParams
+      if (Array.isArray(this.createTime) && this.createTime.length === 2) {
+        this.queryParams.startTime = this.formatDate(this.createTime[0])
+        this.queryParams.endTime = this.formatDate(this.createTime[1])
+      }
+      this.queryParams.lotoId=this.lotoId
+      console.log(this.queryParams,'查询参数')
+      getIsIsolationPointPage(this.queryParams).then((response) => {
+        // console.log(response, "接口返回结果");
+        this.isolationList = response.data.records
+        this.total = response.data.total
+        this.loading = false
+      })
+      // 获取隔离点图标组合
+      const sysAttrKey1 = 'sys.icon_set.isolation' // 隔离点集合图标
+
+// 获取 ID 列表
+      getIsSystemAttributeByKey(sysAttrKey1).then((response) => {
+        const Values = response.data.sysAttrValue.split(',').map(Value => Value.trim())
+        console.log(Values, 'Values')
+        // 创建一个 Promise 数组,每个 Promise 处理一个 ID
+        const promises = Values.map(Value => {
+          return getIsSystemAttributeByKey(Value)
+        })
+
+        // 等待所有请求完成
+        return Promise.all(promises)
+      }).then((responses) => {
+        // responses 是一个数组,包含每个请求的响应
+        responses.forEach((response, index) => {
+          // 假设每个响应包含一个图片地址
+          this.imageMap[index] = response.data.sysAttrValue // 根据实际响应结构调整
+        })
+
+        console.log(this.imageMap, 'imageMap')
+      }).catch(error => {
+        console.error('Error fetching images:', error)
+      })
+      // 获取作业区域数据
+      const data = {
+        current: 1,
+        size: -1
+      }
+      // listWorkarea(data).then((response) => {
+      //   this.deptOptions = this.handleTree(
+      //     response.data.records,
+      //     'workareaId',
+      //     'parentId',
+      //     'children'
+      //   )
+      // })
+      // 岗位
+      listMarsDept(data).then(response => {
+        this.deptOptions = this.handleTree(response.data.records, 'workstationId', 'parentId')
+      })
+      // 设备/工艺
+      listTechnology(data).then((response) => {
+        const data = response.data.records.filter((item) => item.machineryType == '工艺')
+        this.machineryOptions = this.handleTree(
+          data,
+          'machineryId',
+          'parentId'
+        )
+
+      })
+      // 锁具机构类型
+      listLockType(data).then((response) => {
+        this.LockTypeOptions = this.handleTree(response.data.records, 'locksetTypeId')
+      })
+      //   挂锁类型
+      listPadLockTypeAPI(data).then((response) => {
+        this.padLockTypeOptions = this.handleTree(response.data.records, 'lockTypeId')
+      })
+
+      //   所属电柜
+      listLoto(data).then((response) => {
+        console.log(response, '电柜数据')
+        this.lotoOptions = response.data.records.map((item) => {
+          return {
+            value: item.lotoId,
+            label: item.lotoName
+          }
+        })
+      })
+    },
+    /** 转换部门数据结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children
+      }
+      return {
+        id: node.workstationId,
+        label: node.workstationName,
+        children: node.children
+      }
+    },
+    Machinerynormalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children
+      }
+      return {
+        id: node.machineryId,
+        label: node.machineryName,
+        children: node.children
+      }
+    },
+
+    // 取消按钮
+    cancel() {
+      this.open = false
+      this.reset()
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        pointCode: null,
+        pointName: null,
+        pointIcon: null,
+        pointPicture: null,
+        pointType: null,
+        powerType: null,
+        createTime: null
+      }
+      this.autoGenFlag = false
+      this.resetForm('form')
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.current = 1
+      if (Array.isArray(this.createTime) && this.createTime.length === 2) {
+        this.queryParams.startTime = this.formatDate(this.createTime[0])
+        this.queryParams.endTime = this.formatDate(this.createTime[1])
+      }
+      getIsIsolationPointPage(this.queryParams).then((response) => {
+        // console.log(response, "接口返回结果");
+        this.isolationList = response.data.records
+        this.total = response.data.total
+        this.loading = false
+      })
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.createTime = '';
+      (this.queryParams.startTime = ''),
+        (this.queryParams.endTime = ''),
+        this.resetForm('queryForm')
+      if (Array.isArray(this.createTime) && this.createTime.length === 2) {
+        this.queryParams.startTime = this.formatDate(this.createTime[0])
+        this.queryParams.endTime = this.formatDate(this.createTime[1])
+      }
+      getIsIsolationPointPage(this.queryParams).then((response) => {
+        // console.log(response, "接口返回结果");
+        this.isolationList = response.data.records
+        this.total = response.data.total
+        this.loading = false
+      })
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map((item) => item.pointId)
+      this.codes = selection.map((item) => item.pointCode)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset()
+      this.open = true
+      this.title = '新增隔离点'
+      this.optType = 'add'
+      this.pointId = null
+      this.form.workshopId = 0
+      this.selectedImageIndex=null//为了初始化不选中任何图标
+      this.getworkShop()
+    },
+
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset()
+      this.pointId = row.pointId || this.ids
+      selectIsIsolationPointById(this.pointId).then((response) => {
+        this.form = response.data
+        // 确定选中的图片索引
+        this.selectedImageIndex = this.getImageIndexByIcon(response.data.pointIcon);
+        this.open = true
+        this.title = '修改隔离点信息'
+        this.optType = 'edit'
+      })
+    },
+    // 编辑的时候回显选中的隔离点图标
+    getImageIndexByIcon(iconUrl) {
+      for (const [index, imageUrl] of Object.entries(this.imageMap)) {
+        if (imageUrl === iconUrl) {
+          return index;
+        }
+      }
+      return -1; // 如果没有找到匹配的图片,返回 -1
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs['form'].validate((valid) => {
+        if (valid) {
+          console.log(this.pointId, 'this.pointId')
+          if (this.pointId != null) {
+            console.log(this.form, '隔离点修改form')
+            updateIsIsolationPoint(this.form).then((response) => {
+              this.$modal.msgSuccess('修改成功')
+              this.open = false
+              this.getList()
+            })
+          } else {
+            console.log(this.form, '新增参数')
+            addinsertIsIsolationPoint(this.form).then((response) => {
+              this.$modal.msgSuccess('新增成功')
+              this.open = false
+              this.getList()
+              this.pointId = null
+            })
+          }
+        }
+      })
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const teamIds = row.pointId || this.ids
+      // const pointcodes = row.pointCode || this.codes
+      // '是否确认删除隔离点编号为"' + pointcodes + '"的数据项?'
+      this.$modal
+        .confirm('是否确认删除所选数据项?')
+        .then(function() {
+          return deleteIsIsolationPointByPointIds(teamIds)
+        })
+        .then(() => {
+          this.getList()
+          this.$modal.msgSuccess('删除成功')
+        })
+        .catch(() => {
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      this.download(
+        'cal/team/export',
+        {
+          ...this.queryParams
+        },
+        `team_${new Date().getTime()}.xlsx`
+      )
+    },
+    //自动生成编码
+    handleAutoGenChange(autoGenFlag) {
+      if (autoGenFlag) {
+        genCode('ISOLATION_POINT_CODE').then((response) => {
+          this.form.pointCode = response
+        })
+      } else {
+        this.form.pointCode = null
+      }
+    },
+    // 获取车间数据
+    getworkShop() {
+      workshoplistAll().then((response) => {
+        // console.log(response, "获取车间数据");
+        this.workshopList = response.data.map((item) => {
+          return {
+            label: item.workshopName,
+            value: item.workshopId,
+            key: item.workshopCode
+          }
+        })
+      })
+    },
+    // 所属车间下拉改变作业区域内容
+    workShopChange() {
+      this.getworkArea()
+    },
+    // 获取作业区域数据
+    getworkArea() {
+      const workshopId = this.form.workshopId
+
+      if (workshopId) {
+        getIsWorkareaList(workshopId).then((response) => {
+          console.log(response, '获取作业区域数据')
+          this.workareaList = response.data.map((item) => {
+            return {
+              label: item.workareaName,
+              value: item.workareaId,
+              key: item.workareaCode
+            }
+          })
+        })
+      }
+    },
+    normalizerLockset(node) {
+      if (node.children && !node.children.length) {
+        delete node.children
+      }
+      return {
+        id: node.locksetTypeId,
+        label: node.locksetTypeName,
+        children: node.children
+      }
+    },
+    normalizerpadLock(node) {
+      if (node.children && !node.children.length) {
+        delete node.children
+      }
+      return {
+        id: node.lockTypeId,
+        label: node.lockTypeName,
+        children: node.children
+      }
+    },
+    //图片上传成功
+    handleImgUplaoded(imgUrl) {
+      this.form.pointPicture = imgUrl[0].url
+    },
+    //图片移除
+    handleImgRemoved(imgUrl) {
+      this.form.pointPicture = null
+    },
+    //图标上传成功
+    handleIconUplaoded(imgUrl) {
+      this.form.pointIcon = imgUrl[0].url
+    },
+    // 图标移除
+    handleIconRemoved(imgUrl) {
+      this.form.pointIcon = null
+    },
+    //图标上传成功
+    lockTypeImgUplaoded(imgUrl) {
+      this.form.lockTypeImg = imgUrl[0].url
+    },
+    // 图标移除
+    lockTypeImgRemoved(imgUrl) {
+      this.form.lockTypeImg = null
+    },
+    //图标上传成功
+    locksetTypeImgUplaoded(imgUrl) {
+      this.form.locksetType = imgUrl[0].url
+    },
+    // 图标移除
+    locksetTypeImgRemoved(imgUrl) {
+      this.form.locksetType = null
+    },
+  }
+}
+</script>
+<style lang="scss" src="@/assets/styles/dialog-title.scss" scoped>
+.el-input-width {
+  width: 380px !important;
+}
+
+</style>
+<style lang="scss" scoped>
+
+.image-grid {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.image-item {
+  margin: 5px;
+  height: 55px;
+  //background: pink;
+  cursor: pointer;
+  border: 2px solid transparent;
+  transition: border-color 0.3s;
+  position: relative;
+}
+
+.image-item.selected {
+  height: 55px;
+  border-color: rgb(2, 86, 255);
+  border-width: 2px;
+}
+
+
+</style>

+ 1429 - 0
src/views/mes/dv/lotoStation/SwitchStatus.vue

@@ -0,0 +1,1429 @@
+<template>
+  <div class="mapdata">
+    <div id="container" ref="container" style="width: 1600px"></div>
+<!--    <div class="left">-->
+<!--      <div-->
+<!--        class="bottombtn"-->
+<!--        style="width: 100%; height: 35px; padding: 10px;display: flex;flex-direction: column;"-->
+<!--      >-->
+<!--        <el-button-->
+<!--          v-no-more-click-->
+<!--          @click="close"-->
+<!--          type="primary"-->
+<!--          icon="el-icon-close"-->
+<!--          style="align-self: flex-end;margin-top: 10px"-->
+<!--        >关闭-->
+<!--        </el-button>-->
+
+<!--        <el-button-->
+<!--          v-no-more-click-->
+<!--          @click="save"-->
+<!--          type="primary"-->
+<!--          icon="el-icon-check"-->
+<!--          style="align-self: flex-end;margin-top: 10px"-->
+<!--        >保存-->
+<!--        </el-button>-->
+
+<!--        <el-button-->
+<!--          v-no-more-click-->
+<!--          @click="reset"-->
+<!--          type="primary"-->
+<!--          icon="el-icon-setting"-->
+<!--          style="align-self: flex-end;margin-top: 10px"-->
+<!--        >重置-->
+<!--        </el-button>-->
+
+<!--      </div>-->
+<!--    </div>-->
+  </div>
+</template>
+
+<script>
+import Konva from 'konva'
+import {
+  selectLotoMapById,
+  selectIsLotoStationById,
+  updateLoto,
+  updatePointsBindingLoto
+} from '@/api/mes/lotoStation/lotoStation'
+import {getIsIsolationPointPage} from '@/api/mes/spm/segregationPoint'
+import {getIsMapPointPage, selectIsMapPointById, updateMapPointList} from '@/api/system/mappoint'
+import {selectIsMapById} from '@/api/system/mapconfig'
+
+export default {
+  name: 'KonvaExample',
+  data() {
+    return {
+      stage: null,
+      layer: null,
+      selectedStates: [], // 用于存储每个元素的选中状态
+      selectedText: [], // 用于存储未选中的元素文本
+      rects: [], // 白色rect合集
+      texts: [], // 白色text合集
+      redrects: [], // 红色rect合集
+      redtexts: [], // 白色text合集
+      value: '',
+      form: {}, //拿到单个数据
+      originData: null, //原始数据
+      filterData: null, //用来过滤掉已经渲染出来的隔离点
+      leftPoints: [], //绑定的但未指定位置的集合
+      orgLeftPoints: [], //原始左边数据
+      rightPoints: [], //解绑的数据集合
+      orgRightPoints: [], //原始右边数据
+      groups: [], //组移动数据
+      bindingPointIds: [], //存放从未绑定中放入物资柜的数据 id集合
+      unbindPointIds: [], //解绑的数据接口参数 id集合
+      isSave: true,
+      isInitialized: false, // 添加初始化标志
+      imageUrl: '',//获取底图
+      width: '',//底图宽
+      height: '',//底图高
+      x: '',//底图横坐标
+      y: '',//底图纵坐标
+      mapId: null,//地图Id
+      mapType: 2,//地图类型
+      pointList: null,//接口给的所有点位数据
+      newbindingPoints: [],//给地图点位界面更新的绑定隔离点
+      newmovePoints: [],//给地图点位界面更新位置
+      newunbindingPoints: [],//给地图点位界面更新解绑数据
+      blinkLights : [], // 所有需要闪烁的 light 节点
+      globalBlinkTimer : null
+    }
+  },
+
+
+  created() {
+    // this.getIsIsolationPointPage()
+    this.isInitialized = true
+  },
+  beforeRouteEnter(to, from, next) {
+    next((vm) => {
+      // vm.getIsIsolationPointPage()
+      vm.addPointsToRightPointsBox()
+    })
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.getInfo()
+      this.getIsIsolationPointPage()
+      this.addPointsToRightPointsBox()
+    })
+    console.log(this.$route.query.lotoId, 'lotoId')
+  },
+
+  methods: {
+    getInfo() {
+      const lotoId = this.$route.query.lotoId
+      const sopId = ''
+      const ticketId = ''
+      selectIsLotoStationById(lotoId).then((response) => {
+        console.log(response, '作业区域信息')
+        this.form = response.data
+        this.mapId = response.data.mapId
+
+        // 获取不同底图 如地图或者柜子
+        selectIsMapById(response.data.mapId).then((response) => {
+          console.log(response, '获取底图')
+          this.imageUrl = response.data.imageUrl
+          this.width = response.data.width
+          this.height = response.data.height
+          this.x = response.data.x
+          this.y = response.data.y
+          this.pointList = response.data.pointList
+          this.initKonva()
+        })
+
+      })
+
+      // 获取map-json
+      selectLotoMapById(lotoId, sopId, ticketId).then((response) => {
+        console.log(response, '作业区域预览接口调用')
+        this.form.map = response.data
+        this.filterData = response.data
+        const data = {
+          current: 1,
+          size: -1,
+          lotoId: this.$route.query.lotoId
+        }
+        getIsIsolationPointPage(data).then((res) => {
+          const data1 = res.data.records
+          const data2 = this.filterData
+          console.log(data1, '该柜子或地图所有点', data2, '该柜子里json拿到的点位')
+
+          // 创建一个 Set 来存储 data2 中的 pointId
+          const data2PointIds = new Set(data2.map((item) => item.pointId))
+
+          // 创建一个 Set 来存储 this.pointList 中的 pointId
+          const pointListIds = new Set(this.pointList.map((item) => item.pointId))
+
+          // 过滤掉 data2 和 this.pointList 中已经存在的点位
+          const filterData = data1.filter(
+            (item) => !data2PointIds.has(item.pointId) && !pointListIds.has(item.pointId)
+          )
+
+          console.log(filterData, 'filterData-交叉数据')
+          //这里与pointList相同的数据就不渲染了 因为pointList会直接渲染出来的
+          // this.leftPoints = filterData.map((item) => {
+          //   return {
+          //     pointId: item.pointId,
+          //     entityId: item.pointId,
+          //     entityName: item.pointName,
+          //     pointName: item.pointName,
+          //     remark: item.remark,
+          //     prePointId: item.prePointId,
+          //     pointType: item.pointType,
+          //     pointTypeName: item.pointTypeName,
+          //     powerType: item.powerType,
+          //     powerTypeName: item.powerTypeName,
+          //     pointIcon: item.pointIcon,
+          //     status: false,
+          //     pointPicture: item.pointPicture,
+          //     mapImg: null
+          //   }
+          // })
+          // this.addPointsToLeftPointsBox(filterData)
+          this.orgLeftPoints = res.data.records.map((item) => {
+            return {
+              pointId: item.pointId,
+              entityId: item.pointId,
+              entityName: item.pointName,
+              pointName: item.pointName,
+              remark: item.remark,
+              prePointId: item.prePointId,
+              pointType: item.pointType,
+              pointTypeName: item.pointTypeName,
+              powerType: item.powerType,
+              powerTypeName: item.powerTypeName,
+              pointIcon: item.pointIcon,
+              status: false,
+              pointPicture: item.pointPicture,
+              mapImg: null
+            }
+          })
+        })
+        if (response.data) {
+          try {
+            this.value = JSON.stringify(response.data, null, 4)
+            this.originData = this.value
+          } catch (err) {
+          }
+        }
+        this.initKonva()
+      })
+
+    },
+    // 获取未绑定的所有隔离点
+    getIsIsolationPointPage() {
+
+      //   拿到解绑的隔离点数据
+      const data1 = {
+        current: 1,
+        size: -1,
+        lotoId: 0
+      }
+      getIsIsolationPointPage(data1).then((res) => {
+        this.rightPoints = res.data.records.map((item) => {
+          return {
+            entityId: item.pointId,
+            entityName: item.pointName,
+            pointId: item.pointId,
+            pointName: item.pointName,
+            remark: item.remark,
+            prePointId: item.prePointId,
+            pointType: item.pointType,
+            pointTypeName: item.pointTypeName,
+            powerType: item.powerType,
+            powerTypeName: item.powerTypeName,
+            pointIcon: item.pointIcon,
+            status: false,
+            pointPicture: item.pointPicture,
+            mapImg: null,
+            mapId: this.mapId,
+            mapType: this.mapType
+          }
+        })
+        this.orgRightPoints = res.data.records.map((item) => {
+          return {
+            entityId: item.pointId,
+            entityName: item.pointName,
+            pointId: item.pointId,
+            pointName: item.pointName,
+            remark: item.remark,
+            prePointId: item.prePointId,
+            pointType: item.pointType,
+            pointTypeName: item.pointTypeName,
+            powerType: item.powerType,
+            powerTypeName: item.powerTypeName,
+            pointIcon: item.pointIcon,
+            status: false,
+            pointPicture: item.pointPicture,
+            mapImg: null,
+            mapId: this.mapId,
+            mapType: this.mapType
+          }
+        })
+      })
+    },
+    // 重置
+    reset() {
+      this.value = this.originData
+      // 清空并重新赋值
+      this.rightPoints = JSON.parse(JSON.stringify(this.orgRightPoints)) // 深拷贝
+      this.leftPoints = JSON.parse(JSON.stringify(this.orgLeftPoints)) // 深拷贝
+      this.initKonva() // 重新初始化 Konva
+    },
+
+    close() {
+      this.$router.push('/mes/dv/lotoStation')
+    },
+    save() {
+      this.$confirm('请确认是否保存修改内容', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(() => {
+          // 校验 this.value 是否为有效的 JSON
+          if (this.isJson(this.value)) {
+            const mapData =
+              typeof this.value === 'string'
+                ? this.value
+                : JSON.stringify(this.value)
+            const formData = {
+              ...this.form,
+              map: mapData
+            }
+            console.log(formData, 'map')
+
+            updateLoto(formData).then((response) => {
+              console.log(response, '修改车间区域地图')
+              this.$message({
+                type: 'success',
+                message: '保存成功!'
+              })
+            })
+
+            let dataMap = {
+              bindingPoints: this.leftPoints,
+              movePoints: JSON.parse(this.value),
+              unbindingPoints: this.rightPoints
+            }
+            console.log(dataMap, '先拿到数据看看再说')
+            updateMapPointList(dataMap).then((res) => {
+              console.log(res, '拿到的新绑定数据')
+            })
+            const data = {
+              bindingPointIds: this.bindingPointIds,
+              lotoId: this.$route.query.lotoId,
+              unbindPointIds: this.unbindPointIds
+            }
+            console.log(data, '解绑与绑定数据参数')
+            updatePointsBindingLoto(data).then((res) => {
+              console.log(res, '解绑接口返回值')
+              this.bindingPointIds = []
+              this.unbindPointIds = []
+            })
+            this.close()
+          } else {
+            this.$message({
+              type: 'error',
+              message: '地图数据格式不正确,请输入有效的 JSON 格式!'
+            })
+          }
+        })
+        .catch(() => {
+          // 取消操作
+        })
+    },
+
+    // 校验字符串是否为有效的 JSON
+    isJson(str) {
+      try {
+        JSON.parse(str)
+        return true
+      } catch (e) {
+        return false
+      }
+    },
+    initKonva() {
+
+      // 创建舞台
+      this.stage = new Konva.Stage({
+        container: this.$refs.container, // 容器元素
+        width: 1600,
+        height: 860
+      })
+
+      // 创建图层
+      this.layer = new Konva.Layer()
+      // 绘制隔离点等其他内容
+      this.drawGrid(50, 50, '#e0e0e0') // 每个单元格50x50,浅灰色网格
+      // 创建物资柜底图
+      const bgImage = new Image()
+      const imageConfig = {
+        x: this.x,
+        y: this.y,
+        width: this.width,
+        height: this.height,
+        draggable: false
+      }
+      bgImage.src = this.imageUrl
+      bgImage.onload = () => {
+        const knovaImage = new Konva.Image({
+          ...imageConfig,
+          image: bgImage
+        })
+        this.layer.add(knovaImage)
+
+        // 创建背景图并添加到图层
+        // 创建所有隔离点父盒子 放置于网格线上
+        const rightPointsBox = new Konva.Rect({
+          x: 1100,
+          y: 15,
+          width: 200,
+          height: 800,
+          cornerRadius: 5,
+          stroke: 'transparent',
+          strokeWidth: 2,
+          fill: 'transparent'
+        })
+        // const rightnoLoto = new Konva.Text({
+        //   x: 1110, // 调整位置以适应网格
+        //   y: 20, // 调整位置以适应网格
+        //   text: '未绑定锁定站的隔离点数据',
+        //   fontSize: 15,
+        //   fill: 'black'
+        // })
+
+        this.layer.add(rightPointsBox)
+        // this.layer.add(rightnoLoto)
+
+
+        // 将隔离点添加到 rightPointsBox
+        // this.addPointsToRightPointsBox(rightPointsBox)
+
+        // 渲染数据
+        const imageSrc = require('@/assets/images/localSetIcon.jpg') // 图片路径
+        this.renderGrid(imageSrc, 6, 3, 450, 100, 120, 100, 50, 50, 60, 25)
+
+        // 将图层添加到舞台
+        this.stage.add(this.layer)
+        this.layer.draw()
+      }
+
+      // 禁止舞台拖拽
+      this.stage.draggable(false)
+    },
+
+    // 绘制无限网格
+    drawGrid(cellWidth, cellHeight, gridColor) {
+      const width = 1600
+      const height = 860
+
+      // 绘制竖线
+      for (let i = 0; i <= width; i += cellWidth) {
+        const verticalLine = new Konva.Line({
+          points: [i, 0, i, height],
+          stroke: gridColor,
+          strokeWidth: 1
+        })
+        this.layer.add(verticalLine)
+      }
+
+      // 绘制横线
+      for (let j = 0; j <= height; j += cellHeight) {
+        const horizontalLine = new Konva.Line({
+          points: [0, j, width, j],
+          stroke: gridColor,
+          strokeWidth: 1
+        })
+        this.layer.add(horizontalLine)
+      }
+
+      // 添加网格坐标文本
+      // for (let row = 0; row < height / cellHeight; row++) {
+      //   for (let col = 0; col < width / cellWidth; col++) {
+      //     const text = new Konva.Text({
+      //       x: col * cellWidth + 5, // 调整位置以适应网格
+      //       y: row * cellHeight + 5, // 调整位置以适应网格
+      //       text: `(${col},${row})`,
+      //       fontSize: 10,
+      //       fill: 'gray',
+      //     });
+      //     this.layer.add(text);
+      //   }
+      // }
+
+      this.layer.draw()
+    },
+
+    // 绘制柜内所有点
+    renderGrid(imageSrc) {
+      this.selectedStates = [] // 用数组来存储选中状态
+      this.rects = []
+      this.texts = []
+      this.bgrects = {}
+      this.redrects = []
+      this.redtexts = []
+      this.selectedText = []
+
+      // const positions = JSON.parse(this.value)
+      const positions = this.pointList.map(item => ({
+        row: item.x, // 假设 row 是一个固定的值,如果不是,请根据实际情况调整
+        col: item.y, // 假设 col 是一个固定的值,如果不是,请根据实际情况调整
+        id: item.id,
+        pointId: item.entityId, // 假设 pointId 对应的是 entityId,如果不是,请根据实际情况调整
+        pointName: item.entityName, // 假设 pointName 对应的是 entityName,如果不是,请根据实际情况调整
+        entityId: item.entityId,
+        entityName: item.entityName,
+        mapId: item.mapId,
+        mapType: parseInt(item.mapType), // 假设 mapType 需要转换为数字类型
+        x: item.x, // 假设 x 需要转换为数字类型
+        y: item.y, // 假设 y 需要转换为数字类型
+        remark: item.remark,
+        pointIcon: item.pointIcon,
+        pointPicture: item.pointPicture,
+        switchStatus: item.switchStatus,
+      }))
+      console.log(positions, 'positions')
+      positions.forEach((pos, index) => {
+        // console.log(pos,'单条数据');
+
+        const x = pos.x * 50 // 每个单元格宽度为50
+        const y = pos.y * 50 // 每个单元格高度为50
+        const labelText = pos.entityName // 对应的文字
+
+        const point = new Image()
+        point.src = pos.pointIcon
+
+        point.onload = () => {
+          // 创建一个新的Group来包含整个隔离点
+          const group = new Konva.Group({
+            x: x,
+            y: y,
+            draggable: false // 设置为可拖拽
+          })
+
+          // 底部白色背景
+          const bgrect = new Konva.Rect({
+            x: -1,
+            y: -5,
+            width: 50,
+            height: 78,
+            cornerRadius: 5,
+            stroke: 'white',
+            strokeWidth: 2,
+            fill: 'white'
+          })
+
+          // 普通矩形红色边框
+          const rect = new Konva.Rect({
+            x: 1,
+            y: -1,
+            width: 45,
+            height: 70,
+            cornerRadius: 5,
+            stroke: 'red',
+            strokeWidth: 2,
+            fill: 'white'
+          })
+
+          // 确定灯的颜色
+          let lightColor, shadowColor, stroke;
+
+          if (pos.switchStatus == "0") {
+            // lightColor = '#ff000d';     // Red
+            // shadowColor = '#ffcae8';
+            // stroke = '#ffcae8';
+            lightColor = '#e0e0e0';     // Gray (unknown)
+            shadowColor = '#e0e0e0';
+            stroke = '#e0e0e0';
+          } else if (pos.switchStatus == "1") {
+            lightColor = '#0ea562';     // Green
+            shadowColor = '#3ab890';
+            stroke = '#3ab890';
+          } else {
+            lightColor = 'white';
+            shadowColor="white";
+            stroke="white"
+            // lightColor = '#e0e0e0';     // Gray (unknown)
+            // shadowColor = '#e0e0e0';
+            // stroke = '#e0e0e0';
+          }
+          const isRed = pos.switchStatus == "0";
+          const isGrey = pos.switchStatus == null;
+// Create the light
+          const light = new Konva.Circle({
+            x: 22.5, // Circle center position
+            y: 25,  // Circle center position
+            radius: 12,
+            fill: lightColor,
+            stroke: stroke,
+            strokeWidth: 2,
+            shadow: {
+              color: shadowColor,
+              blur: 5,
+              offset: {x: 0, y: 0},
+              opacity: 0.8
+            }
+          });
+          // 文字
+          const text = new Konva.Text({
+            x: 8,
+            y: 50,
+            fontSize: 17,
+            text: labelText,
+            fontFamily: 'Calibri',
+            fill: 'red'
+          })
+
+          // 将所有元素添加到group中
+
+          group.add(bgrect)
+          group.add(rect)
+          // group.add(knovaImage)
+          group.add(light)
+          group.add(text)
+
+          // 将group添加到layer
+          this.layer.add(group)
+          // 定义右侧盒子的范围
+          // const rightBoxBounds = {
+          //   x: 1100,
+          //   y: 15,
+          //   width: 200,
+          //   height: 800
+          // }
+          // 定义物资柜的范围
+          // const cabinetBounds = {
+          //   x: 330, // 物资柜的 x 坐标
+          //   y: 10, // 物资柜的 y 坐标
+          //   width: 500, // 物资柜的宽度
+          //   height: 790 // 物资柜的高度
+          // }
+
+//           group.on('dragend', () => {
+//             // 获取拖拽的内容对应的点名称
+//             const labelText = group.findOne('Text').text()
+//
+//             // 获取 group 的位置
+//             const groupPos = group.getAbsolutePosition()
+//
+//             // 检查是否仍在物资柜范围内
+//             const isInCabinet =
+//               groupPos.x >= cabinetBounds.x &&
+//               groupPos.x <= cabinetBounds.x + cabinetBounds.width &&
+//               groupPos.y >= cabinetBounds.y &&
+//               groupPos.y <= cabinetBounds.y + cabinetBounds.height
+//
+//             // 检查是否在右侧盒子范围内
+//             const isInRightBox =
+//               groupPos.x >= rightBoxBounds.x &&
+//               groupPos.x <= rightBoxBounds.x + rightBoxBounds.width &&
+//               groupPos.y >= rightBoxBounds.y &&
+//               groupPos.y <= rightBoxBounds.y + rightBoxBounds.height
+//
+//             // 查找并删除对应的点数据
+//             const indexToRemove = positions.findIndex(
+//               (item) => item.entityName === labelText
+//             )
+//
+//             if (indexToRemove !== -1) {
+//               // 从 positions 中移除并获取移动的点
+//               // const movedPoint = positions.splice(indexToRemove, 1)[0];
+//               const movedPoint = positions.find((item) => item.entityName == labelText)
+//
+//               if (movedPoint) {
+//                 // 如果点位在物资柜外但不在右侧列表中,进行位置更新
+//                 if (!isInCabinet && !isInRightBox) {
+//                   // 更新位置为新的列和行
+//                   const newCol = Math.round(groupPos.y / 50) // 四舍五入到最近的列
+//                   const newRow = Math.round(groupPos.x / 50) // 四舍五入到最近的行
+//
+//                   // 限制列和行的范围,防止超出网格边界
+//                   const maxCols = Math.floor(860 / 50) - 1 // 最大列索引
+//                   const maxRows = Math.floor(1200 / 50) - 1 // 最大行索引
+//
+//                   const boundedCol = Math.max(0, Math.min(newCol, maxCols)) // 限制列范围
+//                   const boundedRow = Math.max(0, Math.min(newRow, maxRows)) // 限制行范围
+//
+//                   // 更新点位数据
+//                   const updatedPosition = {
+//                     row: boundedRow,
+//                     col: boundedCol,
+//                     id: movedPoint.id,
+//                     pointId: movedPoint.entityId,
+//                     entityId: movedPoint.entityId,
+//                     entityName: movedPoint.entityName,
+//                     pointName: movedPoint.entityName,
+//                     mapId: this.mapId,
+//                     mapType: this.mapType,
+//                     x: boundedRow,
+//                     y: boundedCol,
+//                     pointType: movedPoint.pointType,
+//                     pointTypeName: movedPoint.pointTypeName,
+//                     powerType: movedPoint.powerType,
+//                     powerTypeName: movedPoint.powerTypeName,
+//                     state: movedPoint.state,
+//                     pointIcon: movedPoint.pointIcon,
+//                     pointPicture: movedPoint.pointPicture,
+//                     mapImg: movedPoint.mapImg
+//                   }
+//
+//                   // 更新 positions 数组中的点位
+//                   const updatedPositionCopy = JSON.parse(JSON.stringify(updatedPosition))
+//                   positions[indexToRemove] = updatedPositionCopy
+//
+//                   console.log(updatedPositionCopy, positions[indexToRemove], 'updatedPosition')
+//                   this.value = JSON.stringify(positions, null, 4)
+//
+//                 }
+//
+//                 // 如果从物资柜外移动到右侧列表
+//                 else if (isInRightBox) {
+//                   console.log(isInRightBox, '进入右侧盒子')
+//                   // 确保点位没有被重复添加到 rightPoints 中
+//                   if (
+//                     !this.rightPoints.find(
+//                       (point) => point.entityName == movedPoint.entityName
+//                     )
+//                   ) {
+//                     // console.log(isInRightBox,'进入右侧盒子');
+//                     // // 从 positions 中删除该点
+//                     // const updatedPositions = positions.filter(
+//                     //   (item) => item.pointName !== movedPoint.pointName
+//                     // );
+//                     // console.log(updatedPositions, 'updatedPositions');
+//                     // this.value = JSON.stringify(updatedPositions, null, 4);
+// // 遍历 positions 数组
+//                     for (let i = 0; i < positions.length; i++) {
+//                       // 找到当前移动的元素
+//                       if (positions[i].entityName === movedPoint.entityName) {
+//                         // 使用 splice 删除该元素
+//                         positions.splice(i, 1)
+//
+//                         console.log('Removed item:', movedPoint)  // 输出被删除的元素
+//                         this.value = JSON.stringify(positions, null, 4) // 更新值
+//
+//                         break // 找到并删除后退出循环
+//                       }
+//                     }
+//                     // 将 movedPoint 添加到 rightPoints 数组
+//                     this.rightPoints.push(movedPoint)
+//
+//                     // 将 pointId 添加到 unbindPointIds 数组
+//                     this.unbindPointIds.push(movedPoint.entityId)
+//                     // 从 bindingPointIds 中移除该 pointId
+//                     const bindingIndex = this.bindingPointIds.indexOf(
+//                       movedPoint.entityId
+//                     )
+//                     if (bindingIndex !== -1) {
+//                       this.bindingPointIds.splice(bindingIndex, 1)
+//                     }
+//                   }
+//                 }
+//                 // 如果是从物资柜内拿出来并移到柜外但不进入右侧列表
+//                 else if (isInCabinet && !isInRightBox) {
+//                   // 更新位置并保存
+//                   const newCol = Math.round(groupPos.y / 50) // 四舍五入到最近的列
+//                   const newRow = Math.round(groupPos.x / 50) // 四舍五入到最近的行
+//
+//                   // 限制列和行的范围,防止超出网格边界
+//                   const maxCols = Math.floor(860 / 50) - 1 // 最大列索引
+//                   const maxRows = Math.floor(1200 / 50) - 1 // 最大行索引
+//
+//                   const boundedCol = Math.max(0, Math.min(newCol, maxCols)) // 限制列范围
+//                   const boundedRow = Math.max(0, Math.min(newRow, maxRows)) // 限制行范围
+//
+//                   // 更新点位数据
+//                   const updatedPosition = {
+//                     row: boundedRow,
+//                     col: boundedCol,
+//                     id: movedPoint.id,
+//                     pointId: movedPoint.entityId,
+//                     pointName: movedPoint.entityName,
+//                     entityId: movedPoint.entityId,
+//                     entityName: movedPoint.entityName,
+//                     mapId: this.mapId,
+//                     mapType: this.mapType,
+//                     x: boundedRow,
+//                     y: boundedCol,
+//                     remark: movedPoint.remark,
+//                     prePointId: movedPoint.prePointId,
+//                     pointType: movedPoint.pointType,
+//                     pointTypeName: movedPoint.pointTypeName,
+//                     powerType: movedPoint.powerType,
+//                     powerTypeName: movedPoint.powerTypeName,
+//                     state: movedPoint.state,
+//                     pointIcon: movedPoint.pointIcon,
+//                     pointPicture: movedPoint.pointPicture,
+//                     mapImg: movedPoint.mapImg
+//                   }
+//
+//                   // 更新 positions 数组中的点位
+//                   // 使用深拷贝确保不影响原始数据
+//                   const updatedPositionCopy = JSON.parse(JSON.stringify(updatedPosition))
+//                   positions[indexToRemove] = updatedPositionCopy
+//
+//                   console.log(updatedPositionCopy, positions[indexToRemove], 'updatedPosition')
+//                   this.value = JSON.stringify(positions, null, 4)
+//                 }
+//               }
+//             } else {
+//               // 如果点不在 positions 中,从柜子移动到右侧
+//               const rightIndex = this.rightPoints.findIndex(
+//                 (item) => item.entityName === labelText
+//               )
+//
+//               if (rightIndex !== -1) {
+//                 // 从右侧拖拽到物资柜外或物资柜内
+//                 const movedPoint = this.rightPoints.splice(rightIndex, 1)[0]
+//
+//                 // 如果点不在右侧列表中且不在物资柜中,更新位置
+//                 if (!isInRightBox && !isInCabinet) {
+//                   // 更新位置为新的列和行
+//                   const newCol = Math.round(groupPos.y / 50) // 四舍五入到最近的列
+//                   const newRow = Math.round(groupPos.x / 50) // 四舍五入到最近的行
+//
+//                   // 限制列和行的范围,防止超出网格边界
+//                   const maxCols = Math.floor(860 / 50) - 1 // 最大列索引
+//                   const maxRows = Math.floor(1200 / 50) - 1 // 最大行索引
+//
+//                   const boundedCol = Math.max(0, Math.min(newCol, maxCols)) // 限制列范围
+//                   const boundedRow = Math.max(0, Math.min(newRow, maxRows)) // 限制行范围
+//
+//                   // 更新点位数据
+//                   const updatedPosition = {
+//                     row: boundedRow,
+//                     col: boundedCol,
+//                     id: movedPoint.id,
+//                     pointId: movedPoint.entityId,
+//                     pointName: movedPoint.entityName,
+//                     entityId: movedPoint.entityId,
+//                     entityName: movedPoint.entityName,
+//                     mapId: this.mapId,
+//                     mapType: this.mapType,
+//                     x: boundedRow,
+//                     y: boundedCol,
+//                     remark: movedPoint.remark,
+//                     prePointId: movedPoint.prePointId,
+//                     pointType: movedPoint.pointType,
+//                     pointTypeName: movedPoint.pointTypeName,
+//                     powerType: movedPoint.powerType,
+//                     powerTypeName: movedPoint.powerTypeName,
+//                     state: movedPoint.state,
+//                     pointIcon: movedPoint.pointIcon,
+//                     pointPicture: movedPoint.pointPicture,
+//                     mapImg: movedPoint.mapImg
+//                   }
+//
+//                   // 更新 positions 数组中的点位
+//                   const updatedPositionCopy = JSON.parse(JSON.stringify(updatedPosition))
+//                   positions[indexToRemove] = updatedPositionCopy
+//
+//                   console.log(updatedPositionCopy, positions[indexToRemove], 'updatedPosition')
+//                   this.value = JSON.stringify(positions, null, 4)
+//
+//                 }
+//
+//                 // 如果点从右侧拖拽到物资柜内
+//                 if (isInCabinet) {
+//                   // 更新位置为新的列和行
+//                   const newCol = Math.round(groupPos.y / 50) // 四舍五入到最近的列
+//                   const newRow = Math.round(groupPos.x / 50) // 四舍五入到最近的行
+//
+//                   // 限制列和行的范围,防止超出网格边界
+//                   const maxCols = Math.floor(860 / 50) - 1 // 最大列索引
+//                   const maxRows = Math.floor(1200 / 50) - 1 // 最大行索引
+//
+//                   const boundedCol = Math.max(0, Math.min(newCol, maxCols)) // 限制列范围
+//                   const boundedRow = Math.max(0, Math.min(newRow, maxRows)) // 限制行范围
+//
+//                   // 更新点位数据
+//                   const updatedPosition = {
+//                     row: boundedRow,
+//                     col: boundedCol,
+//                     id: movedPoint.id,
+//                     pointId: movedPoint.entityId,
+//                     pointName: movedPoint.entityName,
+//                     entityId: movedPoint.entityId,
+//                     entityName: movedPoint.entityName,
+//                     mapId: this.mapId,
+//                     mapType: this.mapType,
+//                     x: boundedRow,
+//                     y: boundedCol,
+//                     remark: movedPoint.remark,
+//                     prePointId: movedPoint.prePointId,
+//                     pointType: movedPoint.pointType,
+//                     pointTypeName: movedPoint.pointTypeName,
+//                     powerType: movedPoint.powerType,
+//                     powerTypeName: movedPoint.powerTypeName,
+//                     state: movedPoint.state,
+//                     pointIcon: movedPoint.pointIcon,
+//                     pointPicture: movedPoint.pointPicture,
+//                     mapImg: movedPoint.mapImg
+//                   }
+//
+//                   // 更新 positions 数组中的点位
+//                   positions.push(updatedPosition)
+//                   this.value = JSON.stringify(positions, null, 4)
+//
+//                   // 确保点位没有被重复添加到 leftPoints 中
+//                   if (
+//                     !this.leftPoints.find(
+//                       (point) => point.entityName === movedPoint.entityName
+//                     )
+//                   ) {
+//                     this.leftPoints.push(movedPoint)
+//                   }
+//                   // 从 unbindPointIds 中移除该 pointId
+//                   const unbindIndex = this.unbindPointIds.indexOf(
+//                     movedPoint.entityId
+//                   )
+//                   if (unbindIndex !== -1) {
+//                     this.unbindPointIds.splice(unbindIndex, 1)
+//                   }
+//
+//                   // 将 pointId 添加到 bindingPointIds 数组
+//                   this.bindingPointIds.push(movedPoint.entityId)
+//                 }
+//               }
+//             }
+//
+//             // 清理 undefined 数据
+//             this.rightPoints = this.rightPoints.filter(Boolean)
+//
+//             // 打印调试信息
+//             console.log('Updated positions:', positions)
+//             console.log('Right Points:', this.rightPoints)
+//             console.log('Left Points:', this.leftPoints)
+//
+//             // 重新绘制图层
+//             this.layer.draw()
+//           })
+          // 添加绿灯或红灯闪烁动画
+          this.addBlinkAnimation(light, isRed,isGrey);
+        }
+      })
+    },
+    // 全局控制闪烁频率同步函数
+    startGlobalBlinkTimer() {
+      if (this.globalBlinkTimer) return; // 已经启动了
+
+      this.globalBlinkTimer = setInterval(() => {
+        const currentSecond = Math.floor(Date.now() / 200) % 2;
+        const isOn = currentSecond === 1;
+
+        this.blinkLights.forEach(light => {
+          light.opacity(isOn ? 1 : 0.6);
+          light.scale({ x: isOn ? 1 : 1.1, y: isOn ? 1 : 1.1 });
+        });
+
+        if (this.blinkLights.length > 0) {
+          this.blinkLights[0].getLayer().batchDraw(); // 统一刷新一次就行
+        }
+      }, 50);
+    },
+    // 绿灯动画
+    addBlinkAnimation(light, isRed, isGrey) {
+      if (!isGrey&&!isRed) {
+        if (!this.blinkLights.includes(light)) {
+          this.blinkLights.push(light);
+        }
+        this.startGlobalBlinkTimer();
+      }
+    },
+
+    // 左侧的列表 现在左侧列表通过地图点位接口获取pointList里直接有左侧的数据 不用再去隔离点管理接口拿数据
+    addPointsToLeftPointsBox(filterData) {
+      // 获取接口返回的 leftPoints 数据
+      const pointsData = filterData
+
+      let row = 1 // 当前行
+      let col = 1 // 当前列
+
+      // 遍历 pointsData 并根据是否存在于 this.value 中来决定位置
+      pointsData.forEach((point) => {
+        const existingPoint = JSON.parse(this.value).find(
+          (item) => item.pointId == point.pointId
+        )
+
+        // 如果该点在 this.value 中,使用它的原始位置
+        if (existingPoint) {
+          point.row = existingPoint.row
+          point.col = existingPoint.col
+        } else {
+          // 否则,按顺序从 (0, 0) 位置开始,每行三个点
+          point.row = row
+          point.col = col * 2
+
+          // 每行最多三个点,换行处理
+          col++
+          if (col >= 3) {
+            col = 0
+            row++
+          }
+        }
+        // 渲染该点
+        this.renderPoint(point)
+      })
+    },
+
+    // 渲染每个点
+    renderPoint(point) {
+
+      const x = point.col * 50 // 每个单元格宽度为50
+      const y = point.row * 50 // 每个单元格高度为50
+
+      const labelText = point.pointName // 对应的文字
+      const pointImage = new Image()
+      pointImage.src = point.pointIcon
+
+      pointImage.onload = () => {
+        // 创建一个新的 Group 来包含整个隔离点
+        const group = new Konva.Group({
+          x: x,
+          y: y,
+          draggable: false // 设置为可拖拽
+        })
+
+        // 背景矩形
+        const bgrect = new Konva.Rect({
+          x: -6,
+          y: -5,
+          width: 62,
+          height: 80,
+          cornerRadius: 5,
+          stroke: 'white',
+          strokeWidth: 2,
+          fill: 'white'
+        })
+
+        // 普通矩形
+        const rect = new Konva.Rect({
+          x: 0,
+          y: -1,
+          width: 50,
+          height: 72,
+          cornerRadius: 5,
+          stroke: 'red',
+          strokeWidth: 2,
+          fill: 'white'
+        })
+
+        // 图片
+        const knovaImage = new Konva.Image({
+          x: 0,
+          y: 0,
+          image: pointImage,
+          width: 50,
+          height: 50
+        })
+
+        // 文字
+        const text = new Konva.Text({
+          x: 8,
+          y: 50,
+          fontSize: 17,
+          text: labelText,
+          fontFamily: 'Calibri',
+          fill: 'red'
+        })
+
+        // 将所有元素添加到 group 中
+        group.add(bgrect)
+        group.add(rect)
+        group.add(knovaImage)
+        group.add(text)
+
+        // 将 group 添加到 layer
+        this.layer.add(group)
+
+        // 定义右侧盒子的范围
+        const rightBoxBounds = {
+          x: 1100,
+          y: 15,
+          width: 200,
+          height: 800
+        }
+
+        // 定义物资柜的范围
+        const cabinetBounds = {
+          x: 330,
+          y: 10,
+          width: 500,
+          height: 790
+        }
+
+        // 处理拖拽事件
+        // group.on('dragend', () => {
+        //   const groupPos = group.getAbsolutePosition()
+        //   const isInRightBox =
+        //     groupPos.x >= rightBoxBounds.x &&
+        //     groupPos.x <= rightBoxBounds.x + rightBoxBounds.width &&
+        //     groupPos.y >= rightBoxBounds.y &&
+        //     groupPos.y <= rightBoxBounds.y + rightBoxBounds.height
+        //
+        //   const isInCabinet =
+        //     groupPos.x >= cabinetBounds.x &&
+        //     groupPos.x <= cabinetBounds.x + cabinetBounds.width &&
+        //     groupPos.y >= cabinetBounds.y &&
+        //     groupPos.y <= cabinetBounds.y + cabinetBounds.height
+        //
+        //   // 如果点进入右侧列表,执行删除操作
+        //   if (isInRightBox) {
+        //     this.removePointFromJson(point)
+        //   } else if (isInCabinet) {
+        //     // 如果点回到物资柜,执行更新操作
+        //     this.updatePointInJson(point, groupPos)
+        //   } else if (!isInCabinet && !isInRightBox) {
+        //     // 如果点位在物资柜外但不在右侧列表中,进行位置更新
+        //     this.updatePointInJson(point, groupPos)
+        //   }
+        // })
+
+        this.layer.draw()
+      }
+    },
+
+    // 从 json 删除对应的点
+    removePointFromJson(point) {
+      // 更新 leftPoints 和 rightPoints
+      this.rightPoints.push(point)
+      this.unbindPointIds.push(point.pointId) // 给接口传递需要解绑的数据Id
+
+      // 删除 JSON 中对应的点
+      const updatedData = JSON.parse(this.value).filter(
+        (item) => item.pointId !== point.pointId
+      )
+      this.value = JSON.stringify(updatedData, null, 4)
+
+      // console.log('Updated value after removal:', this.value)
+      console.log('removePointFromJson', updatedData)
+    },
+
+    // 更新 JSON 中对应点的位置
+    updatePointInJson(point, groupPos) {
+      // 计算新的位置
+      const newCol = Math.round(groupPos.x / 50)
+      const newRow = Math.round(groupPos.y / 50)
+
+      // 更新 positions 数组中的点位
+      const updatedPosition = {
+        row: newRow,
+        col: newCol,
+        x: newRow,
+        y: newCol,
+        pointId: point.pointId,
+        pointName: point.pointName,
+        entityId: point.pointId,
+        entityName: point.pointName,
+        remark: point.remark,
+        prePointId: point.prePointId,
+        pointType: point.pointType,
+        pointTypeName: point.pointTypeName,
+        powerType: point.powerType,
+        powerTypeName: point.powerTypeName,
+        state: point.state,
+        pointIcon: point.pointIcon,
+        pointPicture: point.pointPicture,
+        mapImg: point.mapImg
+      }
+
+      let positions = JSON.parse(this.value)
+      const index = positions.findIndex(
+        (item) => item.pointId === point.pointId
+      )
+      if (index !== -1) {
+        // positions[index] = updatedPosition;
+        // this.value = JSON.stringify(positions, null, 4);
+        const updatedPositionCopy = JSON.parse(JSON.stringify(updatedPosition))
+        positions[index] = updatedPositionCopy
+
+        console.log(updatedPositionCopy, positions[index], 'updatedPosition')
+        this.value = JSON.stringify(positions, null, 4)
+      } else {
+        // 如果点位不在 this.value 中,则重新插入
+        positions.push(updatedPosition)
+        this.value = JSON.stringify(positions, null, 4)
+      }
+
+      // console.log('Updated value after update:', this.value)
+    },
+    // 解绑隔离点函数
+    addPointsToRightPointsBox(rightPointsBox) {
+      if (this.rightPoints && this.rightPoints.length > 0) {
+        const boxWidth = rightPointsBox.width()
+        const boxHeight = rightPointsBox.height()
+        const boxX = rightPointsBox.x()
+        const boxY = rightPointsBox.y()
+        const padding = 10 // 每个隔离点之间的间距
+        const pointWidth = 50 // 每个隔离点的宽度
+        const pointHeight = 70 // 每个隔离点的高度(包括图片和文字)
+
+        let currentX = boxX + padding
+        let currentY = boxY + padding
+        const rightBoxBounds = {
+          x: 1100,
+          y: 15,
+          width: 200,
+          height: 800
+        }
+        const cabinetBounds = {
+          x: 330,
+          y: 10,
+          width: 500,
+          height: 790
+        }
+
+        this.rightPoints.forEach((point) => {
+          // 创建一个组来组合红色边框、图片和文字
+          const group = new Konva.Group({
+            x: currentX,
+            y: currentY + 14,
+            draggable: true // 启用拖拽功能
+          })
+
+          // 创建红色边框
+          const borderRect = new Konva.Rect({
+            x: 0,
+            y: 0,
+            width: pointWidth,
+            height: pointHeight,
+            cornerRadius: 5,
+            stroke: 'red',
+            strokeWidth: 2,
+            fill: 'white'
+          })
+          group.add(borderRect)
+
+          // 创建图片
+          const image = new Image()
+          image.src = point.pointIcon
+          image.onload = () => {
+            const knovaImage = new Konva.Image({
+              x: 1, // 图片在组内的位置
+              y: 5, // 图片在组内的位置
+              image: image,
+              width: 50, // 图片宽度
+              height: 50 // 图片高度
+            })
+            group.add(knovaImage)
+
+            // 创建文字
+            const pointText = new Konva.Text({
+              x: 12, // 文字在组内的位置
+              y: 53, // 文字在组内的位置
+              text: point.pointName,
+              fontSize: 12,
+              fill: 'red'
+            })
+            group.add(pointText)
+
+            // 将组添加到图层
+            this.layer.add(group)
+            this.groups[point.pointName] = group // 用文字作为键存储
+
+            // 监听组的拖拽移动事件
+            group.on('dragmove', () => {
+              // 获取当前组的位置
+              const groupPos = group.getAbsolutePosition()
+              // 更新组的位置
+              group.x(groupPos.x)
+              group.y(groupPos.y)
+            })
+
+            // 监听组的拖拽结束事件
+            group.on('dragend', () => {
+              const gridX = 50 // 网格单元格宽度
+              const gridY = 50 // 网格单元格高度
+
+              // 计算最近的网格点位置
+              const snappedX = Math.round(group.x() / gridX) * gridX
+              const snappedY = Math.round(group.y() / gridY) * gridY
+
+              // 设置组到最近的网格点位置
+              group.x(snappedX)
+              group.y(snappedY)
+
+              // 计算网格坐标
+              const row = Math.floor(snappedY / gridY)
+              const col = Math.floor(snappedX / gridX)
+
+              // 更新点位数据
+              const updatedPointData = {
+                row: row,
+                col: col,
+                pointId: point.pointId,
+                entityId: point.entityId,
+                entityName: point.entityName,
+                pointName: point.pointName,
+                remark: point.remark,
+                prePointId: point.prePointId,
+                pointType: point.pointType,
+                pointTypeName: point.pointTypeName,
+                powerType: point.powerType,
+                powerTypeName: point.powerTypeName,
+                state: point.status,
+                pointIcon: point.pointIcon,
+                pointPicture: point.pointPicture,
+                mapImg: null
+              }
+
+              // 解析 this.value 为数组
+              let valueArray = []
+              try {
+                valueArray = JSON.parse(this.value)
+              } catch (e) {
+                console.error('Failed to parse value:', e)
+              }
+
+              // 判断拖拽目标区域
+              if (
+                snappedX >= rightBoxBounds.x &&
+                snappedX <= rightBoxBounds.x + rightBoxBounds.width &&
+                snappedY >= rightBoxBounds.y &&
+                snappedY <= rightBoxBounds.y + rightBoxBounds.height
+              ) {
+                // 进入右侧盒子区域
+                console.log('进入右侧盒子区域')
+// 更新 point 对象的 col 和 row 值
+                point.row = col
+                point.col = row
+                point.x = col
+                point.y = row
+                // 如果之前已在右侧区域,需要移除值,并更新绑定点ID
+                const index = valueArray.findIndex(
+                  (item) => item.pointId === point.pointId
+                )
+                if (index !== -1) {
+                  valueArray.splice(index, 1) // 从 valueArray 中删除该点
+                }
+                this.value = JSON.stringify(valueArray, null, 4)
+
+                // 删除绑定点
+                this.bindingPointIds = this.bindingPointIds.filter(
+                  (id) => id !== point.pointId
+                )
+
+                // 将该点加入解绑点ID
+                this.unbindPointIds.push(point.pointId)
+
+                // 将点重新添加到 rightPoints
+                this.rightPoints.push(point)
+              }
+                //   这里的if判断是为了 移动在物资柜内部才做的操作 现在我只要离开右侧 就做这个操作
+                //    if (
+                //   snappedX >= cabinetBounds.x &&
+                //   snappedX <= cabinetBounds.x + cabinetBounds.width &&
+                //   snappedY >= cabinetBounds.y &&
+                //   snappedY <= cabinetBounds.y + cabinetBounds.height
+              // )
+              else if (snappedX < rightBoxBounds.x ||
+                snappedX > rightBoxBounds.x + rightBoxBounds.width ||
+                snappedY < rightBoxBounds.y ||
+                snappedY > rightBoxBounds.y + rightBoxBounds.height
+              ) {
+
+                // 进入物资柜区域
+                console.log('进入物资柜区域')
+                // 更新 point 对象的 col 和 row 值
+                point.row = col
+                point.col = row
+                point.x = col
+                point.y = row
+                // 检查点是否已经存在于 valueArray 中
+                const index = valueArray.findIndex(
+                  (item) => item.pointId === point.pointId
+                )
+                if (index === -1) {
+                  // 如果点位不存在,则新增
+                  valueArray.push(updatedPointData)
+                  this.value = JSON.stringify(valueArray, null, 4)
+                }
+
+                // 添加到绑定点ID数组
+                this.bindingPointIds.push(point.pointId)
+
+                // 从右侧盒子移除点
+                this.rightPoints = this.rightPoints.filter(
+                  (item) => item.pointId !== point.pointId
+                )
+                this.leftPoints.push(point)
+                console.log(point, '进入左侧区域进行隔离点绑定操作!')
+              } else {
+                // 未进入任何目标区域,保持原状态
+                console.log('未进入目标区域,保持原状态')
+// 更新 point 对象的 col 和 row 值
+                point.row = col
+                point.col = row
+                point.x = col
+                point.y = row
+                // 如果点不在目标区域,从 valueArray 中移除
+                // this.value = JSON.stringify(
+                //   valueArray.filter((item) => item.pointId !== point.pointId),
+                //   null,
+                //   4
+                // );
+                // 检查点是否已经存在于 valueArray 中
+                const index = valueArray.findIndex(
+                  (item) => item.pointId === point.pointId
+                )
+                if (index === -1) {
+                  // 如果点位不存在,则新增
+                  valueArray.push(updatedPointData)
+                  this.value = JSON.stringify(valueArray, null, 4)
+                }
+
+                // 添加到绑定点ID数组
+                this.bindingPointIds.push(point.pointId)
+
+                // 从右侧盒子移除点
+                this.rightPoints = this.rightPoints.filter(
+                  (item) => item.pointId !== point.pointId
+                )
+                // 如果点不在目标区域,重新添加到 rightPoints
+                this.rightPoints.push(point)
+              }
+
+              // 重新绘制图层
+              this.layer.draw()
+            })
+
+            // 重新绘制图层
+            this.layer.draw()
+          }
+
+          // 更新下一个隔离点的位置
+          currentX += pointWidth + padding
+          if (currentX + pointWidth > boxX + boxWidth) {
+            currentX = boxX + padding
+            currentY += pointHeight + padding
+          }
+        })
+      }
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+#container {
+  width: 100%;
+  height: 100%;
+}
+
+.mapdata {
+  width: 100%;
+  height: 100%;
+  display: flex;
+}
+
+.left {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-start;
+  margin-bottom: 20px;
+}
+</style>

+ 1 - 1
src/views/mes/dv/lotoStation/index.vue

@@ -481,7 +481,7 @@ export default {
     look(row) {
       console.log(row, "row预览");
       const data = row.lotoId;
-      this.$router.push(`/mes/hw/lotoStation/index/MapData?lotoId=${data}`);
+      this.$router.push(`/mes/hw/lotoStation/index/LookDetail?lotoId=${data}`);
       // this.dialogVisibleMap = true; // 显示地图预览弹框
     },
     /** 删除按钮操作 */

+ 20 - 3
src/views/mes/dv/segregationpoint/index.vue

@@ -189,8 +189,25 @@
           <span v-else>-</span>
         </template>
       </el-table-column>
-      <!--      <el-table-column label="隔离点NFC" align="center" prop="pointNfc" >-->
-      <!--      </el-table-column>-->
+      <el-table-column label="开关状态" align="center" prop="switchStatus">
+        <template slot-scope="scope">
+<!--          <dict-tag :options="dict.type.switch_status" :value="scope.row.switchStatus"></dict-tag>-->
+          <el-switch
+            style="pointer-events: none"
+            v-if="scope.row.switchStatus!==null"
+            v-model="scope.row.switchStatus"
+            active-value="1"
+            inactive-value="0"
+            active-text="ON"
+            inactive-text="OFF"
+          active-color="#13ce66"
+          inactive-color="#ff4949"
+          ></el-switch>
+          <span v-else>-</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="隔离点NFC" align="center" prop="pointNfc" >
+      </el-table-column>
       <el-table-column label="岗位" align="center" prop="workstationName">
       </el-table-column>
       <el-table-column label="设备/工艺" align="center" prop="machineryName">
@@ -578,7 +595,7 @@ import { getIsSystemAttributeByKey, selectIsSystemAttributeById } from '@/api/sy
 export default {
   name: 'Team',
   components: { Treeselect },
-  dicts: ['power_type', 'point_type', 'lock_type'],
+  dicts: ['power_type', 'point_type', 'lock_type','switch_status'],
   data() {
     return {
       //自动生成编码

+ 15 - 0
src/views/mes/job/jobplay/jobPlayDetail.vue

@@ -151,6 +151,21 @@
                 </div>
               </template>
             </el-table-column>
+            <el-table-column label="开关状态" align="center" prop="switchStatus">
+              <template slot-scope="scope">
+                <!--          <dict-tag :options="dict.type.switch_status" :value="scope.row.switchStatus"></dict-tag>-->
+                <el-switch
+                  style="pointer-events: none;"
+                  v-if="scope.row.switchStatus!==null"
+                  v-model="scope.row.switchStatus"
+                  active-value="1"
+                  inactive-value="0"
+                  active-color="#13ce66"
+                  inactive-color="grey"
+                ></el-switch>
+                <span v-else>-</span>
+              </template>
+            </el-table-column>
             <el-table-column label="挂锁名称" prop="lockName">
             </el-table-column>
             <el-table-column label="锁具机构" prop="locksetName"></el-table-column>

+ 12 - 5
src/views/mes/material/lockers/index.vue

@@ -87,14 +87,14 @@
 
         </div>
 <!--        左侧警告部分内容-->
-        <img style="width: 40px;height: 40px;position: absolute;top:2%;right: -4%" src="@/assets/images/警告.png" alt=""
+        <img style="width: 40px;height: 40px;position: absolute;top:2%;right: -4%" :src="this.ExceptionTableImage" alt=""
              @click="showExTable"
         >
         <div v-if="exceptionTableVisible"
              style="width: 430px;height: 300px;position: absolute;top:2%;right:0;background: white "
         >
           <div style="display: flex">
-            <img src="@/assets/images/警告2.png" style="width: 20px;height: 20px;margin: 10px" alt="">
+            <img :src="this.ExceptionTableImage2" style="width: 20px;height: 20px;margin: 10px" alt="">
             <span style="margin: 10px">异常信息</span>
           </div>
 
@@ -511,6 +511,8 @@ export default {
         label: 'label'
       },
       sysAttrValue:null,//从基础数据接口里拿到物资柜底图的mapId
+      ExceptionTableImage:'',//列表异常的图标
+      ExceptionTableImage2:'',//列表异常的图标2
     }
   },
 
@@ -556,16 +558,21 @@ export default {
       const sysAttrKey1 = 'icon.cabinet.normal';
       const sysAttrKey2 = 'icon.cabinet.borrowed';
       const sysAttrKey3 = 'icon.cabinet.abnormal';
-
+      const sysAttrKey4='sys.exception.icon';
+      const sysAttrKey5='sys.exception2.icon';
       Promise.all([
         getIsSystemAttributeByKey(sysAttrKey1),
         getIsSystemAttributeByKey(sysAttrKey2),
-        getIsSystemAttributeByKey(sysAttrKey3)
+        getIsSystemAttributeByKey(sysAttrKey3),
+        getIsSystemAttributeByKey(sysAttrKey4),
+        getIsSystemAttributeByKey(sysAttrKey5)
       ]).then((responses) => {
         this.imageMap[0] = responses[0].data.sysAttrValue; // 正常
         this.imageMap[1] = responses[1].data.sysAttrValue; // 使用中
         this.imageMap[2] = responses[2].data.sysAttrValue; // 异常
-        console.log(this.imageMap,'imageMap');
+        this.ExceptionTableImage=responses[3].data.sysAttrValue
+        this.ExceptionTableImage2=responses[4].data.sysAttrValue
+        console.log(this.imageMap,this.ExceptionTableImage,this.ExceptionTableImage2,'imageMap');
       });
     },
 

+ 1 - 1
vue.config.js

@@ -36,7 +36,7 @@ module.exports = {
       // detail: https://cli.vuejs.org/config/#devserver-proxy
       [process.env.VUE_APP_BASE_API]: {
         // http://36.133.174.236:9090  http://192.168.1.127:9090 http://192.168.31.110:9090(动感光波) 192.168.28.97:9090(车总GRKJ)
-        target: `http://36.133.174.236:9190`,
+        target: `http://192.168.1.121:9190`,
         changeOrigin: true,
         pathRewrite: {
           ['^' + process.env.VUE_APP_BASE_API]: ''