Ver Fonte

Merge branch 'iscs_dev_mars' of http://192.168.0.253:3000/bozzysadmb/ISCS_Ui_Admin_Base into iscs_dev_mars

wyn há 1 mês atrás
pai
commit
dc4e024816
37 ficheiros alterados com 5347 adições e 6210 exclusões
  1. 8 0
      src/api/mes/lockCabinet/index.js
  2. 61 0
      src/api/mes/motor/index.js
  3. 59 0
      src/api/mes/switchmanagement/switchmanagement.js
  4. 30 38
      src/router/index.js
  5. 232 553
      src/views/mes/dv/lotoStation/MapData.vue
  6. 72 76
      src/views/mes/dv/lotoStation/SwitchStatus.vue
  7. 40 7
      src/views/mes/dv/lotoStation/index.vue
  8. 62 8
      src/views/mes/dv/segregationpoint/index.vue
  9. 53 0
      src/views/mes/dv/switchMotor/LookDetail.vue
  10. 320 0
      src/views/mes/dv/switchMotor/MapData.vue
  11. 121 0
      src/views/mes/dv/switchMotor/PointList.vue
  12. 416 0
      src/views/mes/dv/switchMotor/index.vue
  13. 55 0
      src/views/mes/dv/switchmanagement/LookDetail.vue
  14. 1091 0
      src/views/mes/dv/switchmanagement/MapData.vue
  15. 637 0
      src/views/mes/dv/switchmanagement/PointList.vue
  16. 1263 0
      src/views/mes/dv/switchmanagement/SwitchStatus.vue
  17. 511 0
      src/views/mes/dv/switchmanagement/index.vue
  18. 23 14
      src/views/mes/dv/technology/technologyDetail/MapData.vue
  19. 0 394
      src/views/mes/dv/technology/technologyList/MapData.vue
  20. 2 1
      src/views/mes/hw/Lock/index.vue
  21. 52 3
      src/views/mes/hw/lockCabinet/index.vue
  22. 19 17
      src/views/mes/hw/type/index.vue
  23. 13 13
      src/views/mes/job/jobm/LockDetail.vue
  24. 13 13
      src/views/mes/job/jobm/Mapdata.vue
  25. 31 28
      src/views/mes/job/jobm/NewMarsJob.vue
  26. 0 1305
      src/views/mes/job/jobm/NewOperation1.vue
  27. 0 1486
      src/views/mes/job/jobm/NewOperations.vue
  28. 0 528
      src/views/mes/job/jobm/index.vue
  29. 0 1632
      src/views/mes/job/jobm/lookWork.vue
  30. 1 1
      src/views/mes/material/lockers/DetailsIndex.vue
  31. 103 85
      src/views/mes/material/lockers/index.vue
  32. 24 3
      src/views/mes/material/replacementrecords/index.vue
  33. 1 2
      src/views/mes/md/locksettype/index.vue
  34. 0 1
      src/views/mes/md/locktype/index.vue
  35. 9 1
      src/views/system/mapconfig/index.vue
  36. 24 0
      src/views/system/mappoint/index.vue
  37. 1 1
      vue.config.js

+ 8 - 0
src/api/mes/lockCabinet/index.js

@@ -43,3 +43,11 @@ export function deleteIsLockCabinetByCabinetIds(repairId) {
 
   })
 }
+// 锁控机柜测试 发消息 /iscs/cabinet/sendDataToLoto
+export function sendDataToLoto(query) {
+  return request({
+    url: '/iscs/cabinet/sendDataToLoto',
+    method: 'get',
+    params: query
+  })
+}

+ 61 - 0
src/api/mes/motor/index.js

@@ -0,0 +1,61 @@
+import request from '@/utils/request'
+
+// 查询电机列表
+export function getIsMotorPage(query) {
+  return request({
+    url: '/iscs/motor/getIsMotorPage',
+    method: 'get',
+    params: query
+  })
+}
+// 查询电机对应的锁定站的点位列表
+export function getIsMotorListByLotoId(query) {
+  return request({
+    url: '/iscs/motor/getIsMotorListByLotoId',
+    method: 'get',
+    params: query
+  })
+}
+// 移动电机更新电机位置数据
+export function updateIsMotorMove(data) {
+  return request({
+    url: '/iscs/motor/updateIsMotorMove',
+    method: 'post',
+    data: data
+  })
+}
+
+
+// 查询电机详细
+export function selectIsMotorById(motorId) {
+  return request({
+    url: '/iscs/motor/selectIsMotorById?motorId=' + motorId,
+    method: 'get'
+  })
+}
+
+// 新增电机
+export function addMotor(data) {
+  return request({
+    url: '/iscs/motor/insertIsMotor',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改电机
+export function updateMotor(data) {
+  return request({
+    url: '/iscs/motor/updateIsMotor',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除电机
+export function delMotor(motorIds) {
+  return request({
+    url: '/iscs/motor/deleteIsMotorByMotorIds?motorIds=' + motorIds,
+    method: 'post'
+  })
+}

+ 59 - 0
src/api/mes/switchmanagement/switchmanagement.js

@@ -0,0 +1,59 @@
+import request from '@/utils/request'
+
+// 查询开关布局列表
+export function getIsLotoSwitchMapPage(query) {
+  return request({
+    url: '/iscs/switchmap/getIsLotoSwitchMapPage',
+    method: 'get',
+    params: query
+  })
+}
+// 解绑的数据集合
+export function updatePointsBindingSwitchMap(data) {
+  return request({
+    url: '/iscs/switchmap/updatePointsBindingSwitchMap',
+    method: 'post',
+    data: data
+  })
+}
+
+// 查询开关布局详细
+export function selectIsLotoSwitchMapById(switchMapId) {
+  return request({
+    url: '/iscs/switchmap/selectIsLotoSwitchMapById?switchMapId=' + switchMapId,
+    method: 'get'
+  })
+}
+// 查询开关布局地图转换数据
+export function selectLotoMapById(switchMapId) {
+  return request({
+    url: '/iscs/station/selectLotoMapById?switchMapId=' + switchMapId,
+    method: 'get'
+  })
+}
+
+// 新增开关布局
+export function insertIsLotoSwitchMap(data) {
+  return request({
+    url: '/iscs/switchmap/insertIsLotoSwitchMap',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改开关布局
+export function updateIsLotoSwitchMap(data) {
+  return request({
+    url: '/iscs/switchmap/updateIsLotoSwitchMap',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除开关布局
+export function deleteIsLotoSwitchMapBySwitchMapIds(switchMapIds) {
+  return request({
+    url: '/iscs/switchmap/deleteIsLotoSwitchMapBySwitchMapIds?switchMapIds=' + switchMapIds,
+    method: 'post'
+  })
+}

+ 30 - 38
src/router/index.js

@@ -143,37 +143,14 @@ export const dynamicRoutes = [
     hidden: true,
     permissions: ['mes:job:jobm:add'],
     children: [
-      {
-        path: 'NewOperations',
-        component: () => import('@/views/mes/job/jobm/NewOperations'),
-        name: 'NewOperations',
-        meta: { title: '作业管理-新建作业票', activeMenu: '/mes/job/jobm/NewOperations' }
-
-      },
       // mars 新建作业票流程
       {
         path: 'NewMarsJob',
         component: () => import('@/views/mes/job/jobm/NewMarsJob'),
         name: 'NewMarsJob',
         meta: { title: '作业管理-新建作业票', activeMenu: '/mes/job/jobm/NewMarsJob' }
-
-      },
-
-      {
-        path: 'NewOperationsEdit',
-        component: () => import('@/views/mes/job/jobm/NewOperations'),
-        name: 'NewOperationsEdit',
-        meta: { title: '作业管理-编辑作业票', activeMenu: '/mes/job/jobm/NewOperations' }
-
       },
-      {
-        path: 'lookWork',
-        component: () => import('@/views/mes/job/jobm/lookWork'),
-        name: 'lookWork',
-        meta: { title: '作业管理-查看作业票', activeMenu: '/mes/job/jobm/lookWork' }
-      }
-
-    ]
+      ]
   },
   {
     path: '/mes/job/jobplay',
@@ -250,7 +227,7 @@ export const dynamicRoutes = [
   },
   // 锁定站详情
   {
-    path: '/mes/hw/lotoStation/index',
+    path: '/mes/dv/lotoStation/index',
     component: Layout,
     hidden: true,
     permissions: ['iscs:station:list'],
@@ -259,37 +236,52 @@ export const dynamicRoutes = [
         path: 'LookDetail',
         component: () => import('@/views/mes/dv/lotoStation/LookDetail'),
         name: 'LookDetail',
-        meta: { title: '预览', activeMenu: '/mes/hw/lotoStation/LookDetail' }
+        meta: { title: '预览', activeMenu: '/mes/dv/lotoStation/LookDetail' }
       }
     ]
   },
-  // 硬件锁柜管理详情
+  // 开关分布详情
   {
-    path: '/mes/hw/lockCabinet',
+    path: '/mes/dv/switchmanagement/index',
     component: Layout,
     hidden: true,
-    permissions: ['iscs:station:list'],
+    permissions: ['iscs:switchmap:list'],
     children: [
       {
         path: 'LookDetail',
-        component: () => import('@/views/mes/hw/lockCabinet/lookDetail'),
+        component: () => import('@/views/mes/dv/switchmanagement/LookDetail'),
         name: 'LookDetail',
-        meta: { title: '详情', activeMenu: '/mes/hw/lockCabinet/lookDetail' }
+        meta: { title: '预览', activeMenu: '/mes/dv/switchmanagement/LookDetail' }
       }
     ]
   },
-  // 设备工艺详情
+  // 电机分布详情
   {
-    path: '/mes/dv/technology/technologyList/index',
+    path: '/mes/dv/switchMotor/index',
     component: Layout,
     hidden: true,
-    permissions: ['iscs:machinery:list'],
+    permissions: ['iscs:switchmap:list'],
     children: [
       {
-        path: 'MapData',
-        component: () => import('@/views/mes/dv/technology/technologyList/MapData'),
-        name: 'MapData',
-        meta: { title: '设置隔离点', activeMenu: '/mes/dv/technology/technologyList/MapData' }
+        path: 'LookDetail',
+        component: () => import('@/views/mes/dv/switchMotor/LookDetail'),
+        name: 'LookDetail',
+        meta: { title: '预览', activeMenu: '/mes/dv/switchMotor/LookDetail' }
+      }
+    ]
+  },
+  // 硬件锁柜管理详情
+  {
+    path: '/mes/hw/lockCabinet',
+    component: Layout,
+    hidden: true,
+    permissions: ['iscs:station:list'],
+    children: [
+      {
+        path: 'LookDetail',
+        component: () => import('@/views/mes/hw/lockCabinet/lookDetail'),
+        name: 'LookDetail',
+        meta: { title: '详情', activeMenu: '/mes/hw/lockCabinet/lookDetail' }
       }
     ]
   },

Diff do ficheiro suprimidas por serem muito extensas
+ 232 - 553
src/views/mes/dv/lotoStation/MapData.vue


+ 72 - 76
src/views/mes/dv/lotoStation/SwitchStatus.vue

@@ -124,94 +124,90 @@ export default {
         // 获取不同底图 如地图或者柜子
         selectIsMapById(response.data.mapId).then((response) => {
           console.log(response, '获取底图')
+          if (response.data) {
+            try {
+              this.value = JSON.stringify(response.data.pointList, null, 4)
+
+              this.originData = this.value
+            } catch (err) {
+              console.error(err)
+            }
+          }
           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.pointList = response.data.pointList||[]
+          const data = {
+            current: 1,
+            size: -1,
+            lotoId: this.$route.query.lotoId
+          }
+          getIsIsolationPointPage(data).then((res) => {
+            const allPoints = res.data.records || [];  // 所有可绑定点
+            const placedPointIds = new Set((this.pointList || []).map(p => String(p.entityId)));
+
+            // 过滤:只留下还没有指定位置的点
+            const unplacedPoints = allPoints.filter(item => !placedPointIds.has(item.pointId));
+
+            console.log(allPoints, '所有点');
+            console.log(this.pointList, '已绑定并有位置的点');
+            console.log(unplacedPoints, '未绑定位置的点(需要放左上角0,0)');
+            //这里与pointList相同的数据就不渲染了 因为pointList会直接渲染出来的
+            // this.leftPoints = unplacedPoints.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,
+            //     mapId: this.form.mapId,
+            //     mapType: this.mapType,
+            //     mapName: '你好4',
+            //     x: 0,
+            //     y: 0
+            //   }
+            // })
+            // this.addPointsToLeftPointsBox(this.leftPoints)
+            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,
+                mapId: this.form.mapId,
+                mapType: this.mapType,
+              }
+            })
+          })
           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() {
 

+ 40 - 7
src/views/mes/dv/lotoStation/index.vue

@@ -103,6 +103,7 @@
       />
       <el-table-column label="岗位" align="center" prop="workstationName" />
       <el-table-column label="地图名称" align="center" prop="mapName" />
+      <el-table-column label="电机地图名称" align="center" prop="motorMapName" />
       <el-table-column label="所属硬件序列号" align="center" prop="lotoSerialNumber"></el-table-column>
       <el-table-column
         label="锁定站详情"
@@ -120,6 +121,22 @@
           </el-button>
         </template>
       </el-table-column>
+      <el-table-column
+        label="电机地图详情"
+        align="center"
+        prop="create"
+        width="200"
+      >
+        <template slot-scope="scope">
+          <el-button
+            v-no-more-click
+            size="mini"
+            type="text"
+            @click="lookMotor(scope.row)"
+          >查看
+          </el-button>
+        </template>
+      </el-table-column>
 <!--      <el-table-column-->
 <!--        label="创建时间"-->
 <!--        align="center"-->
@@ -173,6 +190,18 @@
         <el-form-item label="锁定站名称" prop="lotoName">
           <el-input v-model="form.lotoName" placeholder="请输入锁定站名称" />
         </el-form-item>
+        <el-form-item label="地图名称" prop="mapId">
+          <el-select style="width:290px" v-model="form.mapId" placeholder="地图名称">
+            <el-option v-for="item in this.MapOptions" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="电机地图" prop="motorMapId">
+          <el-select style="width:290px" v-model="form.motorMapId" placeholder="电机地图">
+            <el-option v-for="item in this.MapOptions" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
 <!--        <el-row>-->
 <!--          <el-col :span="15">-->
 <!--            <el-form-item label="锁定站编码" prop="lotoCode">-->
@@ -215,12 +244,7 @@
             />
           </el-select>
         </el-form-item>
-        <el-form-item label="地图名称" prop="mapId">
-          <el-select style="width:290px" v-model="form.mapId" placeholder="地图名称">
-            <el-option v-for="item in this.MapOptions" :key="item.id" :label="item.name" :value="item.id">
-            </el-option>
-          </el-select>
-        </el-form-item>
+
         <el-form-item label="锁定站信息" prop="map">
           <el-input
             v-model="form.map"
@@ -305,6 +329,9 @@ export default {
         lotoName: [
           { required: true, message: "锁定站名称不能为空", trigger: "blur" },
         ],
+        mapId:[
+          { required: true, message: "地图名称不能为空", trigger: "blur" },
+        ]
       },
       // 日期选择
       pickerOptions: {
@@ -508,9 +535,15 @@ export default {
     look(row) {
       console.log(row, "row预览");
       const data = row.lotoId;
-      this.$router.push(`/mes/hw/lotoStation/index/LookDetail?lotoId=${data}`);
+      this.$router.push(`/mes/dv/lotoStation/index/LookDetail?lotoId=${data}`);
       // this.dialogVisibleMap = true; // 显示地图预览弹框
     },
+    //电机地图详情
+    lookMotor(row){
+      const data = row.motorMapId;
+      const data2 =row.lotoId
+      this.$router.push(`/mes/dv/switchMotor/index/LookDetail?motorMapId=${data}&lotoId=${data2}`);
+    },
     /** 删除按钮操作 */
     handleDelete(row) {
       const repairIds = row.lotoId || this.ids;

+ 62 - 8
src/views/mes/dv/segregationpoint/index.vue

@@ -48,6 +48,19 @@
           />
         </el-select>
       </el-form-item>
+      <el-form-item label="布局地图" prop="switchMapId">
+        <el-select
+          v-model="queryParams.switchMapId"
+          placeholder="请选择锁定站"
+        >
+          <el-option
+            v-for="dict in switchMapOptions"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
       <!-- <el-form-item label="状态" prop="calendarType">
         <el-select v-model="queryParams.calendarType" placeholder="状态">
           <el-option>正常</el-option>
@@ -227,6 +240,8 @@
       </el-table-column>
       <el-table-column label="锁定站" align="center" prop="lotoName">
       </el-table-column>
+      <el-table-column label="布局地图" align="center" prop="switchMapName">
+      </el-table-column>
       <el-table-column label="隔离点序列号" align="center" prop="pointSerialNumber">
       </el-table-column>
       <el-table-column label="作用" align="center" prop="remark">
@@ -411,14 +426,14 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="隔离点NFC" prop="pointNfc" >
+            <el-form-item label="隔离点NFC" prop="rfidId" >
 <!--              <el-input-->
 <!--                style="width: 300px"-->
 <!--                v-model="form.pointNfc"-->
 <!--                placeholder="请输入隔离点NFC"-->
 <!--                maxlength="16"-->
 <!--              />-->
-              <el-select v-model="form.pointNfc" style="width: 300px">
+              <el-select v-model="form.rfidId" style="width: 300px">
                 <el-option v-for="dict in this.RfidTokenData" :label="dict.label" :value="dict.value"></el-option>
               </el-select>
             </el-form-item>
@@ -443,6 +458,7 @@
                 style="width: 300px"
                 v-model="form.lotoId"
                 placeholder="请选择锁定站"
+                :disabled="this.optType=='edit'"
               >
                 <el-option
                   v-for="dict in lotoOptions"
@@ -455,14 +471,23 @@
 
           </el-col>
           <el-col :span="11">
-            <el-form-item label="作用" prop="remark">
-              <el-input
+            <el-form-item label="布局地图" prop="switchMapId">
+              <el-select
                 style="width: 300px"
-                v-model="form.remark"
-                placeholder="请输入作用"
-              />
+                v-model="form.switchMapId"
+                placeholder="请选择布局地图"
+                :disabled="this.optType=='edit'"
+              >
+                <el-option
+                  v-for="dict in switchMapOptions"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
+                />
+              </el-select>
             </el-form-item>
 
+
           </el-col>
           <!--          <el-col :span="11">-->
           <!--            <el-form-item label="挂锁类型" prop="lockTypeId">-->
@@ -525,6 +550,17 @@
           </el-form-item>
         </el-col>
         </el-row>
+        <el-row>
+          <el-col :span="8">
+            <el-form-item label="作用" prop="remark">
+              <el-input
+                style="width: 300px"
+                v-model="form.remark"
+                placeholder="请输入作用"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
         <el-row>
           <el-col :span="12">
             <el-form-item label="隔离点图标" prop="pointIcon">
@@ -561,6 +597,7 @@
             </el-form-item>
           </el-col>
         </el-row>
+
         <!--        <el-row>-->
         <!--          <el-col :span="8">-->
         <!--            <el-form-item label="挂锁类型图" prop="lockTypeImg">-->
@@ -616,6 +653,7 @@ 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 { getIsLotoSwitchMapPage } from '@/api/mes/switchmanagement/switchmanagement'
 import { listMarsDept } from '@/api/system/marsdept'
 import { listTechnology } from '@/api/system/machinery'
 import { getIsSystemAttributeByKey, selectIsSystemAttributeById } from '@/api/system/configuration'
@@ -710,6 +748,7 @@ export default {
       padLockTypeOptions: [],//挂锁类型下拉
 
       lotoOptions: [],//电柜下拉
+      switchMapOptions: [],//布局地图下拉
       // 表单校验
       rules: {
         pointCode: [
@@ -733,8 +772,14 @@ export default {
         lockTypeId: [
           { required: true, message: '挂锁类型不能为空', trigger: 'blur' }
         ],
-        pointNfc: [
+        rfidId: [
           { required: true, message: '隔离点NFC不能为空', trigger: 'blur' }
+        ],
+        switchMapId:[
+          {required: true, message: '布局地图不能为空', trigger: 'blur'}
+        ],
+        pointIcon:[
+          {required: true, message: '图标不能为空', trigger: 'blur'}
         ]
       },
       imageMap: {
@@ -865,6 +910,15 @@ export default {
           }
         })
       })
+    //   所属开关布局地图 switchMapOptions
+      getIsLotoSwitchMapPage(data).then(response => {
+        this.switchMapOptions= response.data.records.map((item) => {
+          return {
+            value: item.switchMapId,
+            label: item.switchMapName
+          }
+        })
+      })
     },
     /** 转换部门数据结构 */
     normalizer(node) {

+ 53 - 0
src/views/mes/dv/switchMotor/LookDetail.vue

@@ -0,0 +1,53 @@
+<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="third">电机点位列表</el-radio-button>
+    </el-radio-group>
+
+    <component :is="currentComponent" :motorMapId="this.motorMapId"/>
+  </div>
+</template>
+
+<script>
+import MapData from "./MapData";
+import PointList from "./PointList";
+
+
+export default {
+  components: {
+    MapData,
+    PointList,
+  },
+  data() {
+    return {
+      tabPosition: 'first',
+      motorMapId: '',
+    }
+  },
+  computed: {
+    currentComponent() {
+      const components = {
+        third: 'PointList',
+        first: 'MapData',
+        second: 'SwitchStatus'
+      }
+      return components[this.tabPosition]
+    }
+  },
+  mounted() {
+    this.motorMapId = this.$route.query.motorMapId;
+    console.log(this.motorMapId,'this.motorMapId');
+  },
+  methods: {}
+}
+</script>
+
+<style scoped>
+.container {
+  width: 100%;
+  height: 700px;
+  padding: 20px;
+  box-sizing: border-box;
+}
+</style>

+ 320 - 0
src/views/mes/dv/switchMotor/MapData.vue

@@ -0,0 +1,320 @@
+<template>
+  <div class="mapdata">
+    <div id="container" ref="container" ></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>
+
+
+      </div>
+    </div>
+
+
+  </div>
+</template>
+
+<script>
+import Konva from 'konva'
+import { getIsMotorListByLotoId, updateIsMotorMove } from '@/api/mes/motor/index'
+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: [], // 用于存储未选中的元素文本
+      value: '',
+      form: {}, //拿到单个数据
+      groups: [], //组移动数据
+      isSave: true,
+      isInitialized: false, // 添加初始化标志
+      imageUrl: '',//获取底图
+      width: '',//底图宽
+      height: '',//底图高
+      x: '',//底图横坐标
+      y: '',//底图纵坐标
+      mapId: null,//地图Id
+      mapType: 4,//地图类型
+      pointList: null,//接口给的所有点位数据
+      movePoints: [],//给地图点位界面更新位置
+      lotoId: null,
+    }
+  },
+
+  created() {
+    this.isInitialized = true
+  },
+
+  mounted() {
+    this.$nextTick(() => {
+      this.getInfo()
+    })
+  },
+
+  methods: {
+    getInfo() {
+      this.lotoId = this.$route.query.lotoId
+      const motorMapId = this.$route.query.motorMapId
+      this.mapId = motorMapId
+      const lotoId = this.$route.query.lotoId
+      const motorType=4
+
+      const mapPromise = selectIsMapById(motorMapId).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
+      })
+
+      const pointPromise = getIsMotorListByLotoId({ lotoId,motorType }).then((response) => {
+        console.log(response, '查询电机对应的锁定站的点位列表')
+        this.pointList = response.data || []
+      })
+
+      Promise.all([mapPromise, pointPromise]).then(() => {
+        // 数据准备好以后再渲染
+        this.initKonva()
+      })
+    },
+
+    close() {
+      setTimeout(() => {
+        this.getInfo()
+        this.initKonva()
+      }, 1000)
+    },
+    save() {
+      this.$confirm('请确认是否保存修改内容', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(() => {
+          let dataMap = {
+            moveList: this.movePoints
+          }
+          console.log(dataMap, '先拿到数据看看再说')
+          updateIsMotorMove(dataMap).then((res) => {
+            console.log(res, '拿到的新绑定数据')
+            this.movePoints = []
+          })
+
+          this.close()
+
+        })
+        .catch(() => {
+          // 取消操作
+        })
+    },
+
+    initKonva() {
+      // 创建舞台
+      this.stage = new Konva.Stage({
+        container: this.$refs.container, // 容器元素
+        width: 1700,
+        height: 860,
+      })
+
+      // 创建图层
+      this.layer = new Konva.Layer()
+      // 绘制隔离点等其他内容
+      this.drawGrid(10, 10, '#e0e0e0') // 每个单元格10x10,浅灰色网格
+      // 创建物资柜底图
+      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 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 = 1700
+      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)
+      }
+
+
+      this.layer.draw()
+    },
+
+    // 绘制柜内所有点
+    renderGrid() {
+      this.bgrects = {}
+      this.selectedText = []
+      this.movePoints = []
+
+      const positions = this.pointList.map(item => ({
+        entityId: item.motorId,
+        entityName: item.motorCode,
+        pointId: item.pointId,
+        mapPointId: item.mapPointId,
+        // 如果 x / y 为空则默认放置到 0,0
+        x: item.x != null ? item.x : 0,
+        y: item.y != null ? item.y : 0
+      }))
+
+      console.log(positions, 'positions')
+
+      positions.forEach(pos => {
+        const x = pos.x * 10
+        const y = pos.y * 10
+        const labelText = pos.entityName
+
+        const group = new Konva.Group({
+          x: x,
+          y: y,
+          draggable: true
+        })
+
+        // 用圆来展示点位
+        const circle = new Konva.Circle({
+          x: 15,
+          y: 15,
+          radius: 15,
+          fill: '#16af5d',
+          stroke: '#16af5d',
+          strokeWidth: 2
+        })
+
+        const text = new Konva.Text({
+          x: 0,
+          y: 0,
+          width: 30,
+          height: 30,
+          text: labelText,
+          fontSize: 12,
+          fontFamily: 'Calibri',
+          fill: 'white',
+          align: 'center',
+          verticalAlign: 'middle'
+        })
+
+        group.add(circle)
+        group.add(text)
+        this.layer.add(group)
+
+        // 监听拖动结束
+        group.on('dragend', () => {
+          const groupPos = group.getAbsolutePosition()
+
+          const newRow = Math.max(0, Math.round(groupPos.x / 10))
+          const newCol = Math.max(0, Math.round(groupPos.y / 10))
+
+          const updatedPoint = {
+            ...pos,
+            x: newRow,
+            y: newCol,
+            mapId: this.mapId,
+            mapType: this.mapType
+          }
+
+          // 更新 movePoints,用 entityId 作为唯一标识
+          const existIdx = this.movePoints.findIndex(p => p.entityId === updatedPoint.entityId)
+          if (existIdx !== -1) {
+            // 已存在 -> 替换
+            this.movePoints.splice(existIdx, 1, updatedPoint)
+          } else {
+            // 不存在 -> 添加
+            this.movePoints.push(updatedPoint)
+          }
+
+          console.log(this.movePoints, '更新后的 movePoints')
+        })
+
+
+      })
+
+      this.layer.draw()
+    }
+
+  }
+}
+</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>

+ 121 - 0
src/views/mes/dv/switchMotor/PointList.vue

@@ -0,0 +1,121 @@
+<template>
+  <div class="app-container">
+    <el-table
+      height="740"
+      v-loading="loading"
+      :data="tableList"
+    >
+      <el-table-column type="selection" width="55" align="center"/>
+      <el-table-column label="电机名称" align="center" prop="motorName"/>
+      <el-table-column label="隔离点绑定" align="center" prop="pointName" ></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 Treeselect from '@riophae/vue-treeselect'
+import '@riophae/vue-treeselect/dist/vue-treeselect.css'
+
+import { getIsMotorListByLotoId } from '@/api/mes/motor'
+
+export default {
+  name: 'Team',
+  components: { Treeselect },
+  props: {
+    switchMapId: {
+      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,
+
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      tableList:[],
+      queryParams: {
+        current: 1,
+        size: 10,
+        lotoId:null,
+      },
+
+    }
+  },
+
+  created() {
+    this.getList()
+
+  },
+
+  methods: {
+
+    /** 查询隔离点信息列表 */
+    getList() {
+      this.loading = true
+      this.queryParams.lotoId = this.$route.query.lotoId
+      getIsMotorListByLotoId(this.queryParams).then((response) => {
+        this.tableList = response.data
+        this.total = response.data.length
+        this.loading = false
+      })
+
+    },
+
+  }
+}
+</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>

+ 416 - 0
src/views/mes/dv/switchMotor/index.vue

@@ -0,0 +1,416 @@
+<template>
+  <div class="app-container">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      size="small"
+      :inline="true"
+      v-show="showSearch"
+      label-width="100px"
+      @submit.native.prevent
+    >
+      <el-row>
+        <el-form-item label="电机名称" prop="motorName">
+          <el-input
+            v-model="queryParams.motorName"
+            placeholder="请输入电机名称"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+
+        <el-form-item style="margin-left: 20px">
+          <el-button v-no-more-click
+                     type="primary"
+                     icon="el-icon-search"
+                     size="mini"
+                     @click="handleQuery"
+          >搜索
+          </el-button>
+          <el-button v-no-more-click icon="el-icon-refresh" size="mini" @click="resetQuery"
+          >重置
+          </el-button>
+        </el-form-item>
+      </el-row>
+    </el-form>
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button v-no-more-click
+                   type="primary"
+                   plain
+                   icon="el-icon-plus"
+                   size="mini"
+                   @click="handleAdd"
+                   v-hasPermi="['iscs:motor:add']"
+        >新增
+        </el-button>
+      </el-col>
+
+      <el-col :span="1.5">
+        <el-button v-no-more-click
+                   type="danger"
+                   plain
+                   icon="el-icon-delete"
+                   size="mini"
+                   :disabled="multiple"
+                   @click="handleDelete"
+                   v-hasPermi="['iscs:motor:remove']"
+        >批量删除
+        </el-button>
+      </el-col>
+      <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
+    </el-row>
+
+    <el-table
+      v-loading="loading"
+      :data="repairList"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="电机编码" align="center" prop="motorCode"/>
+      <el-table-column label="电机名称" align="center" prop="motorName"/>
+      <el-table-column label="隔离点绑定" align="center" prop="pointName" />
+      <el-table-column label="电机类型" align="center" prop="motorType">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.motor_type" :value="scope.row.motorType"/>
+        </template>
+      </el-table-column>
+
+      <el-table-column
+        label="操作"
+        align="center"
+        class-name="small-padding fixed-width"
+        fixed="right"
+      >
+        <template slot-scope="scope">
+          <el-button v-no-more-click
+                     size="mini"
+                     type="text"
+                     icon="el-icon-edit"
+                     @click="handleUpdate(scope.row)"
+                     v-hasPermi="['iscs:motor:edit','iscs:motor:query']"
+          >修改
+          </el-button>
+          <el-button v-no-more-click
+                     size="mini"
+                     type="text"
+                     icon="el-icon-delete"
+                     @click="handleDelete(scope.row)"
+                     v-hasPermi="['iscs:motor:remove']"
+          >删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.current"
+      :limit.sync="queryParams.size"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改设备维修单对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="450px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="电机编号" prop="motorCode">
+          <el-input v-model="form.motorCode" placeholder="请输入电机编号" />
+        </el-form-item>
+        <el-form-item label="电机名称" prop="motorName">
+          <el-input v-model="form.motorName" placeholder="请输入电机名称" />
+        </el-form-item>
+        <el-form-item label="隔离点绑定" prop="pointId">
+          <el-select style="width:290px" v-model="form.pointId" placeholder="隔离点绑定" clearable>
+            <el-option v-for="item in this.isolationPointOptions" :key="item.pointId" :label="item.pointName" :value="item.pointId">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="电机类型" align="center" prop="motorType" >
+          <el-select style="width:290px" v-model="form.motorType" placeholder="选择电机类型" clearable>
+            <el-option
+              v-for="dict in dict.type.motor_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button v-no-more-click type="primary" @click="submitForm">确 定</el-button>
+        <el-button v-no-more-click @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  getIsMotorPage,
+  selectIsMotorById,
+  addMotor,
+  updateMotor,
+  delMotor
+} from "@/api/mes/motor/index";
+
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+import { getIsIsolationPointPage } from '@/api/mes/spm/segregationPoint'
+export default {
+  name: "lock",
+  dicts: ["hardware_status",'motor_type'],
+  components: { Treeselect },
+  data() {
+    return {
+      autoGenFlag: false,
+      optType: undefined,
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      codes: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // mars树选项
+      marsOptions: [],
+      // 总条数
+      total: 0,
+      // 设备维修单表格数据
+      repairList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      createTime: "",
+      queryParams: {
+        current: 1,
+        size: 10,
+        motorName: null,
+        motorId:null,
+      },
+      // 表单参数
+      form: {
+      },
+      // 隔离点名称 下拉
+      isolationPointOptions: null,
+      hardWareList:[],//所属硬件
+      // 表单校验
+      rules: {
+        motorName: [
+          { required: true, message: "电机名称不能为空", trigger: "blur" },
+        ],
+        motorCode:[
+          { required: true, message: "电机编码不能为空", trigger: "blur" },
+        ],
+        // pointId: [
+        //   { required: true, message: "隔离点不能为空", trigger: "blur" },
+        // ],
+        mapId:[
+          { required: true, message: "地图名称不能为空", trigger: "blur" },
+        ]
+      },
+      // 日期选择
+      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]);
+            },
+          },
+        ],
+      },
+      EditId: 0, //修改判断
+      machinerytypeOptions: [], //锁具机构类型
+      machineryOptions:[],//查询 设备工艺数据
+    };
+  },
+  created() {
+    this.getList();
+    this.getOtherList()
+  },
+  methods: {
+
+    /** 查询设备维修单列表 */
+    getList() {
+      this.loading = true;
+
+      // 布局数据
+      getIsMotorPage(this.queryParams).then((response) => {
+        console.log(response,'布局')
+        this.repairList = response.data.records;
+        this.total = response.data.total;
+        this.loading = false;
+      });
+    },
+    getOtherList(){
+      const data={
+        current:1,
+        size:-1
+      }
+      // 获取地图类型 布局or地图
+      getIsIsolationPointPage(data).then(response => {
+        const dataValue = {
+          pointName: '空',
+          pointId: null,
+        }
+        this.isolationPointOptions = response.data.records
+        this.isolationPointOptions = [...this.isolationPointOptions, dataValue]
+      })
+
+    },
+
+
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        lotoName: null,
+        workstationId: null,
+        orderNum: null,
+        map:null,
+        lotoSerialNumber: null,
+      };
+
+      this.autoGenFlag = false;
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.current = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.queryParams.motorName = "";
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map((item) => item.motorId);
+      this.codes = selection.map((item) => item.motorName);
+      this.single = selection.length !== 1;
+      this.multiple = !selection.length;
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.EditId = null;
+      this.title = "新增电机信息";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      this.EditId = row.motorId || this.ids;
+      selectIsMotorById(this.EditId).then((response) => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改电机信息";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate((valid) => {
+        if (valid) {
+          if (this.EditId != null) {
+            updateMotor(this.form).then((response) => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            // console.log(this.form, "form");
+            addMotor(this.form).then((response) => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.EditId = null;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const repairIds = row.motorId || this.ids;
+      const repairCodes = row.motorName || this.codes;
+      this.$modal
+        .confirm('是否确认删除所选数据项?')
+        .then(function () {
+          return delMotor(repairIds);
+        })
+        .then(() => {
+          this.getList();
+          this.$modal.msgSuccess("删除成功");
+        })
+        .catch(() => {});
+    },
+  },
+};
+</script>
+<style scoped>
+.imgstatus {
+  position: relative;
+  top: 1px;
+  left: 0px;
+}
+
+/deep/ .el-radio__inner {
+  border-radius: 2px;
+}
+
+/deep/ .el-radio__input.is-checked .el-radio__inner::after {
+  content: "";
+  width: 8px;
+  height: 3px;
+  border: 1px solid white;
+  border-top: transparent;
+  border-right: transparent;
+  text-align: center;
+  display: block;
+  position: absolute;
+  top: 3px;
+  left: 2px;
+  transform: rotate(-45deg);
+  border-radius: 0pc;
+  background: none;
+}
+</style>

+ 55 - 0
src/views/mes/dv/switchmanagement/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" :switchMapId="this.switchMapId"/>
+  </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',
+      switchMapId: '',
+    }
+  },
+  computed: {
+    currentComponent() {
+      const components = {
+        third: 'PointList',
+        first: 'MapData',
+        second: 'SwitchStatus'
+      }
+      return components[this.tabPosition]
+    }
+  },
+  mounted() {
+    this.switchMapId = this.$route.query.switchMapId;
+    console.log(this.switchMapId,'this.switchMapId');
+  },
+  methods: {}
+}
+</script>
+
+<style scoped>
+.container {
+  width: 100%;
+  height: 700px;
+  padding: 20px;
+  box-sizing: border-box;
+}
+</style>

+ 1091 - 0
src/views/mes/dv/switchmanagement/MapData.vue

@@ -0,0 +1,1091 @@
+<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,
+  selectIsLotoSwitchMapById,
+  updateIsLotoSwitchMap,
+  updatePointsBindingSwitchMap
+} from '@/api/mes/switchmanagement/switchmanagement'
+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: 3,//地图类型
+      pointList: null,//接口给的所有点位数据
+      bindingPoints: [],//给地图点位界面更新的绑定隔离点
+      movePoints: [],//给地图点位界面更新位置
+      unbindingPoints: []//给地图点位界面更新解绑数据
+
+    }
+  },
+  // watch: {
+  //   bindingPointIds(newVal, oldVal) {
+  //     if (newVal) {
+  //       this.isSave = false;
+  //     }
+  //   },
+  //   unbindPointIds(newVal, oldVal) {
+  //     if (newVal) {
+  //       this.isSave = false;
+  //     }
+  //   },
+  //   // value: {
+  //   //   handler(newVal, oldVal) {
+  //   //     if (this.isInitialized && newVal) {
+  //   //       // 只有在初始化后才监听 value 变化
+  //   //       const parsedValue = JSON.parse(newVal);
+  //   //       console.log(parsedValue, "deep watch for value");
+  //   //       this.isSave = false;
+  //   //     }
+  //   //   },
+  //   //   deep: true,
+  //   // },
+  // },
+
+  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.switchMapId, 'switchMapId')
+  },
+
+  methods: {
+    getInfo() {
+      const switchMapId = this.$route.query.switchMapId
+      selectIsLotoSwitchMapById(switchMapId).then((response) => {
+        console.log(response, '作业区域信息')
+        this.form = response.data
+        this.mapId = response.data.mapId
+
+        // 获取不同底图 如地图或者柜子
+        selectIsMapById(response.data.mapId).then((response) => {
+          console.log(response, '获取底图')
+          if (response.data) {
+            try {
+              this.value = JSON.stringify(response.data.pointList, null, 4)
+
+              this.originData = this.value
+            } catch (err) {
+              console.error(err)
+            }
+          }
+          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|| []
+
+          const data = {
+            current: 1,
+            size: -1,
+            switchMapId: this.$route.query.switchMapId
+          }
+          console.log('调用getIsIsolationPointPage之前')
+          getIsIsolationPointPage(data).then((res) => {
+            const allPoints = res.data.records || [];  // 所有可绑定点
+            const placedPointIds = new Set((this.pointList || []).map(p => String(p.entityId)));
+
+            // 过滤:只留下还没有指定位置的点
+            const unplacedPoints = allPoints.filter(item => !placedPointIds.has(item.pointId));
+
+            console.log(allPoints, '所有点');
+            console.log(this.pointList, '已绑定并有位置的点');
+            console.log(unplacedPoints, '未绑定位置的点(需要放左上角0,0)');
+
+            // 左侧需要显示的数据
+            this.leftPoints = unplacedPoints.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,
+                mapId: this.form.mapId,
+                mapType: this.mapType,
+                mapName: '你好4',
+                x: 0,
+                y: 0
+              }
+            })
+
+            // 调用你已有的渲染逻辑
+            this.addPointsToLeftPointsBox(this.leftPoints)
+
+            // 保存完整数据
+            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,
+                mapId: this.form.mapId,
+                mapType: this.form.mapType
+              }
+            })
+          })
+
+          this.initKonva()
+        })
+      })
+    },
+
+    // 获取未绑定的所有隔离点
+    getIsIsolationPointPage() {
+
+      //   拿到解绑的隔离点数据
+      const data1 = {
+        current: 1,
+        size: -1,
+        switchMapId: 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.form.mapId,
+            mapType: this.form.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.form.mapId,
+            mapType: this.form.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')
+
+      setTimeout(()=>{
+        this.getInfo()
+        this.getIsIsolationPointPage()
+        this.initKonva()
+        this.addPointsToRightPointsBox()
+      },1000)
+    },
+    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')
+
+            updateIsLotoSwitchMap(formData).then((response) => {
+              console.log(response, '修改车间区域地图')
+              this.$message({
+                type: 'success',
+                message: '保存成功!'
+              })
+            })
+            let dataMap = {
+              bindingPoints: this.bindingPoints,
+              movePoints: this.movePoints,
+              unbindingPoints: this.unbindingPoints
+            }
+            console.log(dataMap, '先拿到数据看看再说')
+            updateMapPointList(dataMap).then((res) => {
+              console.log(res, '拿到的新绑定数据')
+              this.bindingPoints = []
+              this.unbindingPoints=[]
+            })
+            const data = {
+              bindingPointIds: this.bindingPointIds,
+              switchMapId: this.$route.query.switchMapId,
+              unbindPointIds: this.unbindPointIds
+            }
+            console.log(data, '解绑与绑定数据参数')
+            updatePointsBindingSwitchMap(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: 'black',
+          strokeWidth: 2,
+          fill: 'white'
+        })
+        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 = []
+
+      this.rightPoints = []
+      this.leftPoints = []
+      this.bindingPointIds = []
+      this.unbindPointIds = []
+      this.movePoints = []
+
+      const positions = this.pointList.map(item => ({
+        row: item.x,
+        col: item.y,
+        id: item.id,
+        pointId: item.entityId,
+        pointName: item.entityName,
+        entityId: item.entityId,
+        entityName: item.entityName,
+        mapId: item.mapId,
+        mapType: parseInt(item.mapType),
+        x: item.x,
+        y: item.y,
+        remark: item.remark,
+        pointIcon: item.pointIcon,
+        pointPicture: item.pointPicture
+      }))
+      console.log(positions,'positions')
+
+      positions.forEach(pos => {
+        const x = pos.x * 50
+        const y = pos.y * 50
+        const labelText = pos.entityName
+
+        const point = new Image()
+        point.src = pos.pointIcon
+
+        point.onload = () => {
+          const group = new Konva.Group({
+            x: x,
+            y: y,
+            draggable: true
+          })
+
+          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' })
+          const knovaImage = new Konva.Image({ x: 1, y: 0, image: point, width: 45, height: 45 })
+          const text = new Konva.Text({ x: 8, y: 50, fontSize: 17, text: labelText, fontFamily: 'Calibri', fill: 'red' })
+
+          group.add(bgrect)
+          group.add(rect)
+          group.add(knovaImage)
+          group.add(text)
+          this.layer.add(group)
+
+          group.on('dragend', () => {
+            const groupPos = group.getAbsolutePosition();
+
+            const rightBoxBounds = { x: 1100, y: 15, width: 200, height: 800 };
+            const cabinetBounds = { x: 0, y: 0, width: 1200, height: 860 };
+
+            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;
+
+            // 判断点的来源
+            let pointData = positions.find(p => p.entityName === labelText);
+            let fromRight = false;
+            if (!pointData) {
+              const rightIndex = this.rightPoints.findIndex(p => p.entityName === labelText);
+              if (rightIndex !== -1) {
+                pointData = this.rightPoints.splice(rightIndex, 1)[0];
+                fromRight = true;
+              }
+            }
+            if (!pointData) return;
+
+            const newRow = Math.max(0, Math.min(Math.round(groupPos.x / 50), Math.floor(1200 / 50) - 1));
+            const newCol = Math.max(0, Math.min(Math.round(groupPos.y / 50), Math.floor(860 / 50) - 1));
+
+            const updatedPoint = {
+              ...pointData,
+              row: newRow,
+              col: newCol,
+              x: newRow,
+              y: newCol,
+              mapId: this.mapId,
+              mapType: this.mapType
+            };
+
+            // ====================== 数据处理 ======================
+            if (fromRight && isInCabinet) {
+              // 右侧盒子 → 左侧画布
+              this.rightPoints = this.rightPoints.filter(p => p.entityId !== updatedPoint.entityId);
+
+              // 加入 bindingPoints
+              if (!this.bindingPoints.some(p => p.entityId === updatedPoint.entityId)) {
+                this.bindingPoints.push(updatedPoint);
+              }
+
+              // 加入 movePoints
+              const existIdx = this.movePoints.findIndex(p => p.pointId === updatedPoint.pointId);
+              if (existIdx !== -1) {
+                this.movePoints.splice(existIdx, 1, updatedPoint);
+              } else {
+                this.movePoints.push(updatedPoint);
+              }
+
+              // 加入左侧画布
+              if (!this.leftPoints.some(p => p.entityName === updatedPoint.entityName)) {
+                this.leftPoints.push(updatedPoint);
+              }
+            } else if (!fromRight && isInRightBox) {
+              // 左侧画布 → 右侧盒子
+              this.leftPoints = this.leftPoints.filter(p => p.entityId !== updatedPoint.entityId);
+
+              // 加入 unbindingPoints
+              if (!this.unbindingPoints.some(p => p.entityId === updatedPoint.entityId)) {
+                this.unbindingPoints.push(updatedPoint);
+              }
+              if (!this.unbindPointIds.includes(updatedPoint.pointId)) this.unbindPointIds.push(updatedPoint.pointId);
+              // 加入右侧盒子
+              if (!this.rightPoints.some(p => p.entityName === updatedPoint.entityName)) {
+                this.rightPoints.push(updatedPoint);
+              }
+            } else if (isInCabinet) {
+              // 左侧画布内部移动
+              const existIdx = this.movePoints.findIndex(p => p.pointId === updatedPoint.pointId);
+              if (existIdx !== -1) {
+                this.movePoints.splice(existIdx, 1, updatedPoint);
+              } else {
+                this.movePoints.push(updatedPoint);
+              }
+            }
+            // 右侧盒子内部移动:不处理数据
+
+            // 更新 positions 数组
+            const posIndex = positions.findIndex(p => p.entityName === updatedPoint.entityName);
+            if (posIndex !== -1) {
+              positions[posIndex] = updatedPoint;
+            }
+
+            this.updatePointInJson(updatedPoint, groupPos);
+
+            this.rightPoints = this.rightPoints.filter(Boolean);
+            this.leftPoints = this.leftPoints.filter(Boolean);
+
+            this.layer.draw();
+          });
+
+
+        }
+      })
+    },
+
+
+    // 左侧的列表 现在左侧列表通过地图点位接口获取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 = 0
+          point.col = 0
+
+        }
+        // 渲染该点
+        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 = () => {
+        const group = new Konva.Group({
+          x,
+          y,
+          draggable: true
+        });
+
+        // 背景矩形
+        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.add(bgrect, rect, knovaImage, text);
+        this.layer.add(group);
+
+        // 右侧盒子范围
+        const rightBoxBounds = { x: 1100, y: 15, width: 200, height: 800 };
+
+        group.on('dragend', () => {
+          const groupPos = group.getAbsolutePosition();
+          const rightBoxBounds = { x: 1100, y: 15, width: 200, height: 800 };
+          const isInRightBox =
+            groupPos.x >= rightBoxBounds.x &&
+            groupPos.x <= rightBoxBounds.x + rightBoxBounds.width &&
+            groupPos.y >= rightBoxBounds.y &&
+            groupPos.y <= rightBoxBounds.y + rightBoxBounds.height;
+
+          const newRow = Math.max(0, Math.round(groupPos.x / 50));
+          const newCol = Math.max(0, Math.round(groupPos.y / 50));
+
+          const updatedPoint = {
+            ...point,
+            row: newRow,
+            col: newCol,
+            x: newRow,
+            y: newCol,
+            mapId: this.mapId,
+            mapType: this.mapType,
+            entityId: point.pointId,
+            entityName: point.pointName
+          };
+
+          const fromRight = this.rightPoints.some(p => p.pointId === updatedPoint.pointId);
+          const fromLeft = this.leftPoints.some(p => p.pointId === updatedPoint.pointId);
+
+          // ===== 数据处理 =====
+          if (fromRight && !isInRightBox) {
+            // 右 → 左画布
+            this.rightPoints = this.rightPoints.filter(p => p.pointId !== updatedPoint.pointId);
+
+            if (!this.leftPoints.some(p => p.pointId === updatedPoint.pointId)) {
+              this.leftPoints.push(updatedPoint);
+            }
+            if (!this.bindingPoints.some(p => p.pointId === updatedPoint.pointId)) {
+              this.bindingPoints.push(updatedPoint);
+            }
+
+            const existIdx = this.movePoints.findIndex(p => p.pointId === updatedPoint.pointId);
+            if (existIdx !== -1) this.movePoints.splice(existIdx, 1, updatedPoint);
+            else this.movePoints.push(updatedPoint);
+
+          } else if (fromLeft && isInRightBox) {
+            // 左 → 右盒子
+            this.leftPoints = this.leftPoints.filter(p => p.pointId !== updatedPoint.pointId);
+
+            if (!this.rightPoints.some(p => p.pointId === updatedPoint.pointId)) {
+              this.rightPoints.push(updatedPoint);
+            }
+            if (!this.unbindingPoints.some(p => p.pointId === updatedPoint.pointId)) {
+              this.unbindingPoints.push(updatedPoint);
+            }
+            if (!this.unbindPointIds.some(p => p.pointId === updatedPoint.pointId)) {
+              this.unbindPointIds.push(updatedPoint.entityId);
+            }
+          } else if (fromLeft && !isInRightBox) {
+            // 左内部移动
+            const existIdx = this.movePoints.findIndex(p => p.pointId === updatedPoint.pointId);
+            if (existIdx !== -1) this.movePoints.splice(existIdx, 1, updatedPoint);
+            else this.movePoints.push(updatedPoint);
+          }
+          // 右盒子内部移动:不操作
+
+          // 更新 JSON
+          let positions = JSON.parse(this.value || '[]');
+          const posIndex = positions.findIndex(p => p.pointId === updatedPoint.pointId);
+          if (posIndex !== -1) positions[posIndex] = updatedPoint;
+          else positions.push(updatedPoint);
+          this.value = JSON.stringify(positions, null, 4);
+
+          this.layer.draw();
+
+          console.log('bindingPoints:', this.bindingPoints);
+          console.log('movePoints:', this.movePoints);
+          console.log('unbindingPoints:', this.unbindingPoints);
+        });
+
+
+        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,
+        mapId: this.mapId,
+        mapType: this.mapType,
+        mapName: '你好5'
+      }
+
+      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-1')
+        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) return;
+
+      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 initialLocation = 'right';
+
+        const pointData = {
+          ...point,
+          entityId: point.entityId || point.pointId,
+          entityName: point.entityName || point.pointName,
+          mapId: point.mapId || this.mapId,
+          mapType: point.mapType || this.mapType
+        };
+
+        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 pos = group.getAbsolutePosition();
+            group.x(pos.x);
+            group.y(pos.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 updatedPoint = { ...pointData, row, col, x: col, y: row };
+
+            const inRightBox =
+              snappedX >= rightBoxBounds.x &&
+              snappedX <= rightBoxBounds.x + rightBoxBounds.width &&
+              snappedY >= rightBoxBounds.y &&
+              snappedY <= rightBoxBounds.y + rightBoxBounds.height;
+
+            const inCabinet =
+              snappedX >= cabinetBounds.x &&
+              snappedX <= cabinetBounds.x + cabinetBounds.width &&
+              snappedY >= cabinetBounds.y &&
+              snappedY <= cabinetBounds.y + cabinetBounds.height;
+
+            // ===== 数据处理 =====
+            if (initialLocation === 'right' && inCabinet) {
+              // 右 → 左
+              this.rightPoints = this.rightPoints.filter(p => p.pointId !== point.pointId);
+              if (!this.leftPoints.some(p => p.pointId === updatedPoint.pointId)) this.leftPoints.push(updatedPoint);
+              if (!this.bindingPoints.some(p => p.pointId === updatedPoint.pointId)) this.bindingPoints.push(updatedPoint);
+              if (!this.bindingPointIds) this.bindingPointIds = [];
+              if (!this.bindingPointIds.includes(updatedPoint.pointId)) this.bindingPointIds.push(updatedPoint.pointId);
+
+              const existIdx = this.movePoints.findIndex(p => p.pointId === updatedPoint.pointId);
+              if (existIdx !== -1) this.movePoints.splice(existIdx, 1, updatedPoint);
+              else this.movePoints.push(updatedPoint);
+
+            } else if (initialLocation === 'left' && inRightBox) {
+              // 左 → 右盒子
+              this.leftPoints = this.leftPoints.filter(p => p.pointId !== point.pointId);
+              if (!this.rightPoints.some(p => p.pointId === updatedPoint.pointId)) this.rightPoints.push(updatedPoint);
+              if (!this.unbindingPoints.some(p => p.pointId === updatedPoint.pointId)) this.unbindingPoints.push(updatedPoint);
+              if (!this.unbindPointIds) this.unbindPointIds = [];
+              if (!this.unbindPointIds.includes(updatedPoint.pointId)) this.unbindPointIds.push(updatedPoint.pointId);
+
+            } else if (initialLocation === 'left' && inCabinet) {
+              // 左内部移动
+              const existIdx = this.movePoints.findIndex(p => p.pointId === updatedPoint.pointId);
+              if (existIdx !== -1) this.movePoints.splice(existIdx, 1, updatedPoint);
+              else this.movePoints.push(updatedPoint);
+            }
+
+            // 更新 JSON
+            let valueArray = [];
+            try { valueArray = JSON.parse(this.value || '[]'); } catch (e) { valueArray = []; }
+            const valIdx = valueArray.findIndex(p => p.pointId === updatedPoint.pointId);
+            if (valIdx !== -1) valueArray[valIdx] = updatedPoint;
+            else valueArray.push(updatedPoint);
+            this.value = JSON.stringify(valueArray, null, 4);
+
+            this.layer.draw();
+
+            console.log('bindingPoints:', this.bindingPoints);
+            console.log('bindingPointIds:', this.bindingPointIds);
+            console.log('movePoints:', this.movePoints);
+            console.log('unbindingPoints:', this.unbindingPoints);
+            console.log('unbindPointIds:', this.unbindPointIds);
+          });
+
+          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>

+ 637 - 0
src/views/mes/dv/switchmanagement/PointList.vue

@@ -0,0 +1,637 @@
+<template>
+  <div class="app-container">
+    <el-table
+      height="740"
+      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="switchMapName">
+      </el-table-column>
+      <el-table-column label="隔离点序列号" align="center" prop="pointSerialNumber">
+      </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: {
+    switchMapId: {
+      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: '',
+        switchMapId:null,
+      },
+
+      // 表单参数
+      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' }
+        ],
+        switchMapId: [
+          { required: true, message: '开关点位Id不能为空', 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:{
+    switchMapId(newVal) {
+      console.log('switchMapId changed:', newVal);
+      // 这里可以执行需要的逻辑
+      this.queryParams.switchMapId = 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.switchMapId=this.switchMapId
+      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
+      }
+    },
+
+    // 取消按钮
+    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>

+ 1263 - 0
src/views/mes/dv/switchmanagement/SwitchStatus.vue

@@ -0,0 +1,1263 @@
+<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,
+  selectIsLotoSwitchMapById,
+  updateIsLotoSwitchMap,
+  updatePointsBindingSwitchMap
+} from '@/api/mes/switchmanagement/switchmanagement'
+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,//接口给的所有点位数据
+      bindingPoints: [],//给地图点位界面更新的绑定隔离点
+      movePoints: [],//给地图点位界面更新位置
+      unbindingPoints: [],//给地图点位界面更新解绑数据
+      blinkLights : [], // 所有需要闪烁的 light 节点
+      globalBlinkTimer : null
+    }
+  },
+  // watch: {
+  //   bindingPointIds(newVal, oldVal) {
+  //     if (newVal) {
+  //       this.isSave = false;
+  //     }
+  //   },
+  //   unbindPointIds(newVal, oldVal) {
+  //     if (newVal) {
+  //       this.isSave = false;
+  //     }
+  //   },
+  //   // value: {
+  //   //   handler(newVal, oldVal) {
+  //   //     if (this.isInitialized && newVal) {
+  //   //       // 只有在初始化后才监听 value 变化
+  //   //       const parsedValue = JSON.parse(newVal);
+  //   //       console.log(parsedValue, "deep watch for value");
+  //   //       this.isSave = false;
+  //   //     }
+  //   //   },
+  //   //   deep: true,
+  //   // },
+  // },
+
+  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.switchMapId, 'switchMapId')
+  },
+
+  methods: {
+    getInfo() {
+      const switchMapId = this.$route.query.switchMapId
+      selectIsLotoSwitchMapById(switchMapId).then((response) => {
+        console.log(response, '作业区域信息')
+        this.form = response.data
+        this.mapId = response.data.mapId
+
+        // 获取不同底图 如地图或者柜子
+        selectIsMapById(response.data.mapId).then((response) => {
+          console.log(response, '获取底图')
+          if (response.data) {
+            try {
+              this.value = JSON.stringify(response.data.pointList, null, 4)
+
+              this.originData = this.value
+            } catch (err) {
+              console.error(err)
+            }
+          }
+          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
+
+          const data = {
+            current: 1,
+            size: -1,
+            switchMapId: this.$route.query.switchMapId
+          }
+
+          getIsIsolationPointPage(data).then((res) => {
+            const data1 = res.data.records // 该柜子或地图所有点
+            const data2 = this.pointList   // 该柜子里 json 拿到的点位(已渲染)
+
+            console.log(data1, '该柜子或地图所有点')
+            console.log(data2, '柜子里json拿到的点位')
+
+            // 当前柜子已经存在的点位 id
+            const pointListIds = new Set(this.pointList.map((item) => item.pointId))
+
+            // 过滤掉已经在 pointList 里的点
+            const filterData = data1.filter(item => !pointListIds.has(item.pointId))
+
+            console.log([...pointListIds], '已有点位 ID')
+            console.log(filterData, 'filterData-需要显示在左侧的数据')
+
+            // 左侧需要显示的数据
+            // 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,
+            //     mapId:this.form.mapId,
+            //     mapType: 2,
+            //     mapName:'你好4',
+            //     x: 0,
+            //     y: 0,
+            //   }
+            // })
+
+            // 调用你已有的渲染逻辑
+            // 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,
+                mapId:this.form.mapId,
+                mapType: this.form.mapType,
+              }
+            })
+          })
+
+          this.initKonva()
+        })
+      })
+    },
+
+    // 获取未绑定的所有隔离点
+    getIsIsolationPointPage() {
+
+      //   拿到解绑的隔离点数据
+      const data1 = {
+        current: 1,
+        size: -1,
+        switchMapId: 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')
+      this.getInfo()
+      // this.initKonva()
+    },
+    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')
+
+            updateIsLotoSwitchMap(formData).then((response) => {
+              console.log(response, '修改车间区域地图')
+              this.$message({
+                type: 'success',
+                message: '保存成功!'
+              })
+            })
+
+            let dataMap = {
+              bindingPoints: this.leftPoints,
+              movePoints: this.movePoints,
+              unbindingPoints: this.rightPoints
+            }
+            console.log(dataMap, '先拿到数据看看再说')
+            updateMapPointList(dataMap).then((res) => {
+              console.log(res, '拿到的新绑定数据')
+            })
+            const data = {
+              bindingPointIds: this.bindingPointIds,
+              switchMapId: this.$route.query.switchMapId,
+              unbindPointIds: this.unbindPointIds
+            }
+            console.log(data, '解绑与绑定数据参数')
+            updatePointsBindingSwitchMap(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: 'black',
+        //   strokeWidth: 2,
+        //   fill: 'white'
+        // })
+        // 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 = []
+
+      // ✅ 每次渲染前清空
+      this.rightPoints = []
+      this.leftPoints = []
+      this.bindingPointIds = []
+      this.unbindPointIds = []
+      this.movePoints = []
+
+      // 点位数据
+      const positions = (this.pointList || []).map(item => ({
+        row: item.x,
+        col: item.y,
+        id: item.id,
+        pointId: item.entityId,
+        pointName: item.entityName,
+        entityId: item.entityId,
+        entityName: item.entityName,
+        mapId: item.mapId,
+        mapType: parseInt(item.mapType),
+        x: item.x,
+        y: item.y,
+        remark: item.remark,
+        pointIcon: item.pointIcon,
+        pointPicture: item.pointPicture,
+        pointSerialNumber:item.pointSerialNumber,
+        switchStatus: item.switchStatus,
+        switchLastUpdateTime:item.switchLastUpdateTime
+      }))
+      console.log(positions, 'positions')
+
+      positions.forEach((pos) => {
+        const x = pos.x * 50
+        const y = pos.y * 50
+        const labelText = pos.entityName
+
+        const point = new Image()
+        point.src = pos.pointIcon
+
+        point.onload = () => {
+          const group = new Konva.Group({
+            x: x,
+            y: y,
+            draggable: true
+          })
+
+          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;
+console.log(pos,'点位')
+          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 knovaImage = new Konva.Image({
+          //   x: 1,
+          //   y: 0,
+          //   image: point,
+          //   width: 45,
+          //   height: 45
+          // })
+
+          const text = new Konva.Text({
+            x: 8,
+            y: 50,
+            fontSize: 17,
+            text: labelText,
+            fontFamily: 'Calibri',
+            fill: 'red'
+          })
+
+          group.add(bgrect)
+          group.add(rect)
+          // group.add(knovaImage)
+          // 添加灯闪
+          group.add(light)
+          group.add(text)
+
+          this.layer.add(group)
+
+          // 定义右侧盒子的范围
+          // const rightBoxBounds = { x: 1100, y: 15, width: 200, height: 800 }
+
+          // group.on('dragend', () => {
+          //   const groupPos = group.getAbsolutePosition()
+          //   const movedLabel = labelText
+          //
+          //   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 ? positions.findIndex(item => item.entityName === movedLabel) : -1
+          //
+          //   if (indexToRemove !== -1) {
+          //     const movedPoint = positions[indexToRemove]
+          //     if (isInRightBox) {
+          //       // 移动到右侧
+          //       positions.splice(indexToRemove, 1)
+          //       if (!this.rightPoints.some(p => p.entityName === movedPoint.entityName)) {
+          //         this.rightPoints.push(movedPoint)
+          //         this.unbindPointIds.push(movedPoint.entityId)
+          //         this.bindingPointIds = this.bindingPointIds.filter(id => id !== movedPoint.entityId)
+          //       }
+          //     } else {
+          //       // 在柜子内/外更新位置
+          //       const newCol = Math.round(groupPos.y / 50)
+          //       const newRow = Math.round(groupPos.x / 50)
+          //
+          //       const boundedCol = Math.max(0, Math.min(newCol, Math.floor(860 / 50) - 1))
+          //       const boundedRow = Math.max(0, Math.min(newRow, Math.floor(1200 / 50) - 1))
+          //
+          //       const updatedPoint = {
+          //         ...movedPoint,
+          //         row: boundedRow,
+          //         col: boundedCol,
+          //         x: boundedRow,
+          //         y: boundedCol,
+          //         mapId: this.form.mapId,
+          //         mapType: this.form.mapType,
+          //       }
+          //
+          //       positions[indexToRemove] = updatedPoint
+          //
+          //       // ✅ 只有位置不为 0 才加入 movePoints
+          //       if (!(updatedPoint.row == 0 && updatedPoint.col == 0 && updatedPoint.x == 0 && updatedPoint.y == 0)) {
+          //         if (!this.movePoints) this.movePoints = []
+          //         // 防止重复 push,先找一下
+          //         const existIdx = this.movePoints.findIndex(p => p.pointId === updatedPoint.pointId)
+          //         if (existIdx !== -1) {
+          //           this.movePoints.splice(existIdx, 1, updatedPoint) // 覆盖旧的
+          //         } else {
+          //           this.movePoints.push(updatedPoint)
+          //         }
+          //       }
+          //     }
+          //   } else {
+          //     // movedLabel 不在 positions,可能是从右侧拖出来
+          //     const rightIndex = this.rightPoints.findIndex(item => item.entityName === movedLabel)
+          //     if (rightIndex !== -1) {
+          //       const movedPoint = this.rightPoints.splice(rightIndex, 1)[0]
+          //       const newCol = Math.round(groupPos.y / 50)
+          //       const newRow = Math.round(groupPos.x / 50)
+          //       const boundedCol = Math.max(0, Math.min(newCol, Math.floor(860 / 50) - 1))
+          //       const boundedRow = Math.max(0, Math.min(newRow, Math.floor(1200 / 50) - 1))
+          //
+          //       const newPoint = {
+          //         ...movedPoint,
+          //         row: boundedRow,
+          //         col: boundedCol,
+          //         x: boundedRow,
+          //         y: boundedCol,
+          //         mapId: this.form.mapId,
+          //         mapType: this.form.mapType,
+          //       }
+          //
+          //       positions.push(newPoint)
+          //
+          //       if (!this.leftPoints.some(p => p.entityName === movedPoint.entityName)) {
+          //         this.leftPoints.push(movedPoint)
+          //       }
+          //       this.bindingPointIds.push(movedPoint.entityId)
+          //       this.unbindPointIds = this.unbindPointIds.filter(id => id !== movedPoint.entityId)
+          //
+          //       // ✅ 判断 row/col/x/y 不为 0 再 push
+          //       if (!(newPoint.row == 0 && newPoint.col == 0 && newPoint.x == 0 && newPoint.y == 0)) {
+          //         if (!this.movePoints) this.movePoints = []
+          //         const existIdx = this.movePoints.findIndex(p => p.pointId === newPoint.pointId)
+          //         if (existIdx !== -1) {
+          //           this.movePoints.splice(existIdx, 1, newPoint)
+          //         } else {
+          //           this.movePoints.push(newPoint)
+          //         }
+          //       }
+          //     }
+          //   }
+          //
+          //   // 清理无效数据
+          //   this.rightPoints = (this.rightPoints || []).filter(Boolean)
+          //   this.leftPoints = (this.leftPoints || []).filter(Boolean)
+          //
+          //   this.value = JSON.stringify(positions, null, 4)
+          //   this.layer.draw()
+          //
+          //   console.log('Updated positions:', positions)
+          //   console.log('MovePoints:', this.movePoints)
+          // })
+// 添加绿灯或红灯闪烁动画
+          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 = 0
+          point.col = 0
+
+        }
+        // 渲染该点
+        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: true // 设置为可拖拽
+        })
+
+        // 背景矩形
+        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,
+        mapId: this.form.mapId,
+        mapType: this.form.mapType,
+        mapName:'你好5'
+      }
+
+      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-1')
+        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,
+                mapId: point.mapId,
+                mapName:'你好6',
+                mapType: point.mapType,
+              }
+
+              // 解析 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>

+ 511 - 0
src/views/mes/dv/switchmanagement/index.vue

@@ -0,0 +1,511 @@
+<template>
+  <div class="app-container">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      size="small"
+      :inline="true"
+      v-show="showSearch"
+      label-width="100px"
+      @submit.native.prevent
+    >
+      <el-row>
+        <el-form-item label="布局名称" prop="switchMapName">
+          <el-input
+            v-model="queryParams.switchMapName"
+            placeholder="请输入布局名称"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="岗位" prop="workstationId" >
+          <treeselect style="width: 200px" v-model="queryParams.workstationId" :options="marsOptions" :normalizer="Marsnormalizer" placeholder="请选择岗位"/>
+        </el-form-item>
+
+        <el-form-item style="margin-left: 20px">
+          <el-button v-no-more-click
+                     type="primary"
+                     icon="el-icon-search"
+                     size="mini"
+                     @click="handleQuery"
+          >搜索
+          </el-button>
+          <el-button v-no-more-click icon="el-icon-refresh" size="mini" @click="resetQuery"
+          >重置
+          </el-button>
+        </el-form-item>
+      </el-row>
+    </el-form>
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button v-no-more-click
+                   type="primary"
+                   plain
+                   icon="el-icon-plus"
+                   size="mini"
+                   @click="handleAdd"
+                   v-hasPermi="['iscs:switchmap:add']"
+        >新增
+        </el-button>
+      </el-col>
+
+      <el-col :span="1.5">
+        <el-button v-no-more-click
+                   type="danger"
+                   plain
+                   icon="el-icon-delete"
+                   size="mini"
+                   :disabled="multiple"
+                   @click="handleDelete"
+                   v-hasPermi="['iscs:switchmap:remove']"
+        >批量删除
+        </el-button>
+      </el-col>
+      <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
+    </el-row>
+
+    <el-table
+      v-loading="loading"
+      :data="repairList"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" align="center" />
+<!--      <el-table-column-->
+<!--        label="布局编码"-->
+<!--        width="150px"-->
+<!--        align="center"-->
+<!--        prop="lotoCode"-->
+<!--      />-->
+      <el-table-column
+        label="布局名称"
+        width="180px"
+        align="center"
+        prop="switchMapName"
+      />
+      <el-table-column
+        label="排序"
+        width="180px"
+        align="center"
+        prop="orderNum"
+      />
+      <el-table-column label="岗位" align="center" prop="workstationName" />
+      <el-table-column label="地图名称" align="center" prop="mapName" />
+      <el-table-column label="所属硬件序列号" align="center" prop="serialNumber"></el-table-column>
+      <el-table-column
+        label="布局详情"
+        align="center"
+        prop="create"
+        width="200"
+      >
+        <template slot-scope="scope">
+          <el-button
+            v-no-more-click
+            size="mini"
+            type="text"
+            @click="look(scope.row)"
+          >查看
+          </el-button>
+        </template>
+      </el-table-column>
+
+      <el-table-column
+        label="操作"
+        align="center"
+        class-name="small-padding fixed-width"
+        fixed="right"
+      >
+        <template slot-scope="scope">
+          <el-button v-no-more-click
+                     size="mini"
+                     type="text"
+                     icon="el-icon-edit"
+                     @click="handleUpdate(scope.row)"
+                     v-hasPermi="['iscs:switchmap:edit','iscs:switchmap:query']"
+          >修改
+          </el-button>
+          <el-button v-no-more-click
+                     size="mini"
+                     type="text"
+                     icon="el-icon-delete"
+                     @click="handleDelete(scope.row)"
+                     v-hasPermi="['iscs:switchmap:remove']"
+          >删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.current"
+      :limit.sync="queryParams.size"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改设备维修单对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="450px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="布局名称" prop="switchMapName">
+          <el-input v-model="form.switchMapName" placeholder="请输入布局名称" />
+        </el-form-item>
+        <el-form-item label="地图名称" prop="mapId">
+          <el-select style="width:290px" v-model="form.mapId" placeholder="地图名称">
+            <el-option v-for="item in this.MapOptions" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="排序" prop="orderNum">
+          <el-input-number type="number" v-model="form.orderNum" />
+        </el-form-item>
+
+        <el-form-item label="岗位" prop="workstationId" >
+          <treeselect v-model="form.workstationId" :options="marsOptions" :normalizer="Marsnormalizer" placeholder="选择岗位"/>
+        </el-form-item>
+        <el-form-item label="所属硬件" prop="serialNumber">
+          <el-select
+            v-model="form.serialNumber"
+            placeholder="请选择所属硬件"
+            clearable
+          >
+            <el-option
+              v-for="dict in this.hardWareList"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="布局信息" prop="map">
+          <el-input
+            v-model="form.map"
+            placeholder="请输入布局信息"
+
+          />
+        </el-form-item>
+
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button v-no-more-click type="primary" @click="submitForm">确 定</el-button>
+        <el-button v-no-more-click @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  getIsLotoSwitchMapPage,
+  selectIsLotoSwitchMapById,
+  insertIsLotoSwitchMap,
+  updateIsLotoSwitchMap,
+  deleteIsLotoSwitchMapBySwitchMapIds
+} from "@/api/mes/switchmanagement/switchmanagement";
+import { genCode } from "@/api/system/autocode/rule";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import { listMarsDept } from '@/api/system/marsdept'
+import { listTechnology } from '@/api/system/machinery'
+import { getIsMapPage } from '@/api/system/mapconfig'
+import { listHardware } from '@/api/mes/hw/hardwareinfo'
+export default {
+  name: "lock",
+  dicts: ["hardware_status"],
+  components: { Treeselect },
+  data() {
+    return {
+      autoGenFlag: false,
+      optType: undefined,
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      codes: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // mars树选项
+      marsOptions: [],
+      // 总条数
+      total: 0,
+      // 设备维修单表格数据
+      repairList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      createTime: "",
+      queryParams: {
+        current: 1,
+        size: 10,
+        switchMapCode: null,
+        switchMapName: null,
+
+      },
+      // 表单参数
+      form: {
+      },
+      // 地图名称 下拉
+      MapOptions: null,
+      hardWareList:[],//所属硬件
+      // 表单校验
+      rules: {
+        switchMapCode: [
+          { required: true, message: "布局编码不能为空", trigger: "blur" },
+        ],
+        switchMapName: [
+          { required: true, message: "布局名称不能为空", trigger: "blur" },
+        ],
+        mapId:[
+          { required: true, message: "地图名称不能为空", trigger: "blur" },
+        ]
+      },
+      // 日期选择
+      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]);
+            },
+          },
+        ],
+      },
+      EditId: 0, //修改判断
+      machinerytypeOptions: [], //锁具机构类型
+      machineryOptions:[],//查询 设备工艺数据
+    };
+  },
+  created() {
+    this.getList();
+    this.getOtherList()
+  },
+  methods: {
+
+    //自动生成编码
+    handleAutoGenChange(autoGenFlag) {
+      if (autoGenFlag) {
+        genCode("LOTO_STATION_CODE").then((response) => {
+          this.form.lotoCode = response;
+        });
+      } else {
+        this.form.lotoCode = null;
+      }
+    },
+    /** 查询设备维修单列表 */
+
+    getList() {
+      this.loading = true;
+
+      // 布局数据
+      getIsLotoSwitchMapPage(this.queryParams).then((response) => {
+        console.log(response,'布局')
+        this.repairList = response.data.records;
+        this.total = response.data.total;
+        this.loading = false;
+      });
+    },
+    getOtherList(){
+      const data={
+        current:1,
+        size:-1
+      }
+      // 获取地图类型 布局or地图
+      getIsMapPage(data).then(response => {
+        this.MapOptions = response.data.records
+      })
+      // 岗位
+      listMarsDept(data).then(response => {
+        this.marsOptions = 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"
+        );
+
+      });
+      listHardware(data).then((response) => {
+        this.hardWareList = response.data.records.map((item) => {
+          return {
+            value: item.serialNumber,
+            label: item.hardwareName,
+          };
+        });
+      })
+
+    },
+    /** 转换部门数据结构 */
+    Marsnormalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children
+      }
+      return {
+        id: node.workstationId,
+        label: node.workstationName,
+        children: node.children
+      }
+    },
+
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        lotoName: null,
+        workstationId: null,
+        orderNum: null,
+        map:null,
+        lotoSerialNumber: null,
+      };
+
+      this.autoGenFlag = false;
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.current = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.queryParams.switchMapName = "";
+      this.queryParams.switchMapId = "";
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map((item) => item.switchMapId);
+      this.codes = selection.map((item) => item.switchMapName);
+      this.single = selection.length !== 1;
+      this.multiple = !selection.length;
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.EditId = null;
+      this.title = "新增布局信息";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      this.EditId = row.switchMapId || this.ids;
+      selectIsLotoSwitchMapById(this.EditId).then((response) => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改布局信息";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate((valid) => {
+        if (valid) {
+          if (this.EditId != null) {
+            updateIsLotoSwitchMap(this.form).then((response) => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            // console.log(this.form, "form");
+            insertIsLotoSwitchMap(this.form).then((response) => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.EditId = null;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    // 地图预览
+    look(row) {
+      console.log(row, "row预览");
+      const data = row.switchMapId;
+      this.$router.push(`/mes/dv/switchmanagement/index/LookDetail?switchMapId=${data}`);
+      // this.dialogVisibleMap = true; // 显示地图预览弹框
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const repairIds = row.switchMapId || this.ids;
+      const repairCodes = row.switchMapName || this.codes;
+      this.$modal
+        .confirm('是否确认删除所选数据项?')
+        .then(function () {
+          return deleteIsLotoSwitchMapBySwitchMapIds(repairIds);
+        })
+        .then(() => {
+          this.getList();
+          this.$modal.msgSuccess("删除成功");
+        })
+        .catch(() => {});
+    },
+  },
+};
+</script>
+<style scoped>
+.imgstatus {
+  position: relative;
+  top: 1px;
+  left: 0px;
+}
+
+/deep/ .el-radio__inner {
+  border-radius: 2px;
+}
+
+/deep/ .el-radio__input.is-checked .el-radio__inner::after {
+  content: "";
+  width: 8px;
+  height: 3px;
+  border: 1px solid white;
+  border-top: transparent;
+  border-right: transparent;
+  text-align: center;
+  display: block;
+  position: absolute;
+  top: 3px;
+  left: 2px;
+  transform: rotate(-45deg);
+  border-radius: 0pc;
+  background: none;
+}
+</style>

+ 23 - 14
src/views/mes/dv/technology/technologyDetail/MapData.vue

@@ -79,26 +79,35 @@ export default {
       const machineryId = this.machineryId
       getTechnologyInfo(machineryId).then((response) => {
         const lotoId = response.data.lotoId
-        const sopId = ''
-        const ticketId = ''
-        selectLotoMapById(lotoId, sopId, ticketId).then(response => {
-          console.log(response, '电柜预览接口调用')
-          this.form.map = response.data
-          if (response.data) {
-            try {
-              this.value = JSON.stringify(response.data, null, 4)
-              this.orignData = this.value
-              this.initKonva()
-            } catch (err) {
-            }
-          }
-        })
+        // const sopId = ''
+        // const ticketId = ''
+        // selectLotoMapById(lotoId, sopId, ticketId).then(response => {
+        //   console.log(response, '电柜预览接口调用')
+        //   this.form.map = response.data
+        //   if (response.data) {
+        //     try {
+        //       this.value = JSON.stringify(response.data, null, 4)
+        //       this.orignData = this.value
+        //       this.initKonva()
+        //     } catch (err) {
+        //     }
+        //   }
+        // })
         selectIsLotoStationById(lotoId).then((response) => {
           console.log(response, '电柜信息')
           this.form = response.data
           // 获取不同底图 如地图或者柜子
           selectIsMapById(response.data.mapId).then((response) => {
             console.log(response, '获取底图')
+            if (response.data) {
+              try {
+                this.value = JSON.stringify(response.data.pointList, null, 4)
+
+                this.originData = this.value
+              } catch (err) {
+                console.error(err)
+              }
+            }
             this.imageUrl = response.data.imageUrl
             this.width = response.data.width
             this.height = response.data.height

+ 0 - 394
src/views/mes/dv/technology/technologyList/MapData.vue

@@ -1,394 +0,0 @@
-<template>
-  <div class="mapdata">
-    <div id="container" ref="container" style="width:1200px"></div>
-    <div class="left">
-      <el-card class="box-card">
-        <div slot="header" class="clearfix">
-          <span style="font-size: 18px">电柜信息展示</span>
-          <span
-            style="
-                float: right;
-                padding: 1px 0;
-                font-size: 22px;
-                cursor: pointer;
-              "
-            type="text"
-            @click="goBack"
-          >×</span
-          >
-        </div>
-        <div style="height: 100%;padding-bottom:10px">
-          <el-input v-model="value" type="textarea" :rows="34" disabled></el-input>
-
-        </div>
-        <div class="bottombtn" style="width:100%;height: 35px;padding: 10px 0 0">
-          <el-button v-no-more-click @click="save" type="primary" icon="el-icon-edit" style="float: right; height: 33px; line-height: 2px">保存</el-button>
-          <el-button v-no-more-click @click="close" type="primary" icon="el-icon-close"  style="float: right; height: 33px; line-height: 2px;margin: 0 10px">关闭</el-button>
-<!--          <el-button v-no-more-click @click="reset" type="primary" icon="el-icon-refresh"  style="float: right; height: 33px; line-height: 2px;margin: 0 10px">重置</el-button>-->
-<!--          <el-button v-no-more-click @click="view" type="primary" icon="el-icon-view" style="float: right; height: 33px; line-height: 2px">预览</el-button>-->
-        </div>
-      </el-card>
-
-    </div>
-  </div>
-
-</template>
-
-<script>
-import Konva from "konva";
-import {selectLotoMapById,selectIsLotoStationById,updateLoto} from '@/api/mes/lotoStation/lotoStation'
-import { getTechnologyInfo, saveMachineryPoints } from '@/api/system/machinery'
-
-export default {
-  name: "KonvaExample",
-  data() {
-    return {
-      stage: null,
-      layer: null,
-      selectedStates: [], // 用于存储每个元素的选中状态
-      selectedText: [], // 用于存储未选中的元素文本
-      rects: [], // 白色r        ect合集
-      texts: [], // 白色text合集
-      redrects: [], // 红色rect合集
-      redtexts: [], // 白色text合集
-      value:'',
-      form:{},//拿到单个数据
-      orignData:null,//原始数据
-      pointIdList:[],//选中的隔离点
-      selectPoints:[],//回显之前选中的隔离点
-    };
-  },
-  watch:{
-    '$route.query.lotoId':{
-      handler(newValue){
-        if(newValue){
-          this.selectIsLotoStationById()
-          this.initKonva();
-        }
-      }
-    }
-  },
-  mounted() {
-    this.$nextTick(()=>{
-      this.selectIsLotoStationById()
-    })
-    console.log(this.$route.query.lotoId,'lotoId');
-  },
-
-  methods: {
-    goBack(){
-      this.$router.push('/technology/technologyList');
-    },
-    close(){
-      this.$router.push('/technology/technologyList');
-    },
-    selectIsLotoStationById(){
-      const lotoId=this.$route.query.lotoId;
-      const sopId=''
-      const ticketId=''
-      selectIsLotoStationById(lotoId).then((response) => {
-        console.log(response,'电柜信息')
-        this.form=response.data
-      })
-      selectLotoMapById(lotoId,sopId,ticketId).then(response => {
-        console.log(response,'电柜预览接口调用');
-        this.form.map=response.data;
-
-        if (response.data) {
-          try {
-            this.value = JSON.stringify(response.data, null, 4);
-            this.orignData=this.value
-          } catch (err) {}
-        }
-        this.initKonva();
-      })
-    //   设备工艺详情
-      getTechnologyInfo(this.$route.query.machineryId).then(response => {
-        console.log(response,'设备/工艺详情');
-        this.selectPoints=response.data.pointIdList;
-      })
-    },
-    // 重置
-    reset(){
-      this.value = this.orignData;
-      this.initKonva(); // 重新初始化 Konva
-    },
-    // 预览
-    view(){
-      if(this.isJson(this.value)){
-        this.form.map=this.value
-        this.initKonva();
-      }else {
-        this.$message({
-          type: 'error',
-          message: '地图数据格式不正确,请输入有效的 JSON 格式!'
-        });
-      }
-    },
-    save() {
-      this.$confirm('请确认是否保存修改内容', '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(() => {
-        // 校验 this.value 是否为有效的 JSON
-        if (this.isJson(this.value)) {
-          const machineryId=this.$route.query.machineryId
-          const formData = {
-            machineryId:machineryId,
-            pointIdList:this.pointIdList,
-          };
-          console.log(this.form, formData,'map')
-          saveMachineryPoints(formData).then(response => {
-            console.log(response, '修改设备/工艺地图');
-            this.$router.push('/technology/technologyList');
-            this.$message({
-              type: 'success',
-              message: '保存成功!'
-            });
-          });
-        } 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: 1200,
-        height: 860,
-      });
-
-      // 创建图层
-      this.layer = new Konva.Layer();
-
-      // 创建底图
-      const bgImage = new Image();
-      bgImage.src = require("@/assets/images/table.png");
-      bgImage.onload = () => {
-        const knovaImage = new Konva.Image({
-          x: 330,
-          y: 10,
-          image: bgImage,
-          width: 500,
-          height: 790,
-          draggable: false,
-        });
-        this.layer.add(knovaImage);
-        this.layer.draw();
-      };
-
-      // 绘制无限网格
-      this.drawGrid(50, 50, "#e0e0e0"); // 每个单元格50x50,浅灰色网格
-
-      // 渲染数据
-      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 = 1200;
-      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);
-      }
-
-      this.layer.draw();
-    },
-
-    renderGrid(imageSrc) {
-      this.selectedStates = []; // 用数组来存储选中状态
-      this.rects = {};
-      this.texts = {};
-      this.bgrects = {};
-      this.redrects = {};
-      this.redtexts = {};
-      this.selectedText = [];
-      this.pointIdList = []; // 初始化选中的点ID列表
-
-      const positions = JSON.parse(this.value);
-
-      positions.forEach((pos, index) => {
-        const x = pos.col * 50; // 每个单元格宽度为50
-        const y = pos.row * 50; // 每个单元格高度为50
-        const labelText = pos.pointName; // 对应的文字
-
-        const point = new Image();
-        point.src = pos.pointIcon;
-        point.onload = () => {
-          const knovaImage = new Konva.Image({
-            x: x,
-            y: y,
-            image: point,
-            width: 50,
-            height: 50,
-            draggable: false,
-          });
-
-          // 添加点击事件监听器
-          knovaImage.on('click', () => {
-            const isCurrentlySelected = this.redrects[labelText].visible();
-
-            if (isCurrentlySelected) {
-              // 如果当前已选中,则取消选中
-              this.redrects[labelText].visible(false);
-              this.redtexts[labelText].visible(false);
-              this.pointIdList = this.pointIdList.filter(id => id !== pos.pointId); // 移除ID
-            } else {
-              // 如果当前未选中,则选中
-              this.redrects[labelText].visible(true);
-              this.redtexts[labelText].visible(true);
-              this.pointIdList.push(pos.pointId); // 添加ID
-            }
-
-            this.layer.batchDraw(); // 更新图层显示
-          });
-
-          // 底部白色背景
-          const bgrect = new Konva.Rect({
-            x: x - 6,
-            y: y - 5,
-            width: 62,
-            height: 80,
-            cornerRadius: 5,
-            stroke: 'white',
-            strokeWidth: 2,
-            fill: 'white'
-          });
-          this.layer.add(bgrect);
-          this.bgrects[labelText] = bgrect; // 用文字作为键存储
-
-          // 普通矩形
-          const rect = new Konva.Rect({
-            x: x + 0,
-            y: y - 1,
-            width: 50,
-            height: 72,
-            cornerRadius: 5,
-            stroke: 'red',
-            strokeWidth: 2,
-            fill: 'white'
-          });
-          this.layer.add(rect);
-          this.rects[labelText] = rect; // 用文字作为键存储
-
-          // 先加底部白色 再添加图片
-          this.layer.add(knovaImage);
-
-          // 普通文字
-          const text = new Konva.Text({
-            x: x + 8,
-            y: y + 50,
-            fontSize: 17,
-            text: labelText,
-            fontFamily: 'Calibri',
-            fill: 'red'
-          });
-          this.layer.add(text);
-          this.texts[labelText] = text; // 用文字作为键存储
-
-          // 覆盖层(表示选中状态)
-          const redrect = new Konva.Rect({
-            x: x - 7,
-            y: y - 6,
-            width: 64.1,
-            height: 82,
-            cornerRadius: 5,
-            fill: 'rgba(97, 97, 97, 0.5)', // 半透明灰色
-            visible: false, // 初始状态隐藏
-            listening: false
-          });
-          this.layer.add(redrect);
-          this.redrects[labelText] = redrect; // 用文字作为键存储
-
-          // 创建对号文本
-          const redtext = new Konva.Text({
-            x: x - 5 + 42 / 2, // 水平居中
-            y: y + 62 / 2, // 垂直居中
-            fontSize: 24, // 根据需要调整字体大小
-            text: '✔',
-            fontFamily: 'Arial',
-            fill: 'white',
-            align: 'center',
-            verticalAlign: 'middle',
-            visible: false, // 初始隐藏状态
-            listening: false,
-          });
-          this.layer.add(redtext);
-          this.redtexts[labelText] = redtext; // 用文字作为键存储
-
-          // 检查 selectPoints 是否存在并且不为空
-          if (Array.isArray(this.selectPoints) && this.selectPoints.length > 0) {
-            if (this.selectPoints.includes(pos.pointId)) {
-              // 设置选中状态
-              this.redrects[labelText].visible(true);
-              this.redtexts[labelText].visible(true);
-              this.pointIdList.push(pos.pointId); // 添加ID
-            }
-          }
-
-          this.layer.draw();
-        };
-      });
-    }
-  },
-};
-</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;
-}
-</style>

+ 2 - 1
src/views/mes/hw/Lock/index.vue

@@ -133,7 +133,8 @@
             v-hasPermi="['mes:hw:lk:edit']"
             >编辑
           </el-button>
-          <el-button v-no-more-click
+          <el-button
+            v-no-more-click
             size="mini"
             type="text"
             icon="el-icon-delete"

+ 52 - 3
src/views/mes/hw/lockCabinet/index.vue

@@ -116,7 +116,6 @@
       <el-table-column label="硬件ID" align="center" prop="hardwareId"></el-table-column>
       <el-table-column label="硬件序列号" align="center" prop="serialNumber"></el-table-column>
       <el-table-column label="岗位" align="center" prop="workstationName">
-
       </el-table-column>
       <el-table-column label="图片" align="left" prop="cabinetPicture">
         <template slot-scope="scope">
@@ -185,6 +184,11 @@
           <el-button type="text" @click="lookDetail(scope.row)">查看</el-button>
         </template>
       </el-table-column>
+      <el-table-column label="测试" align="center" prop="detail" v-hasPermi="['iscs:cabinet:test']">
+        <template slot-scope="scope">
+          <el-button type="text" @click="openDialogFunction(scope.row)">查看</el-button>
+        </template>
+      </el-table-column>
       <el-table-column
         label="操作"
         align="center"
@@ -328,6 +332,27 @@
         <el-button v-no-more-click @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
+<!--    测试弹框-->
+    <el-dialog title="测试" :visible.sync="openDialog" width="650px" append-to-body>
+      <el-form ref="form" :model="DialogData"  label-width="100px">
+        <el-form-item label="类型">
+          <el-input v-model="DialogData.type" placeholder="请输入type"></el-input>
+        </el-form-item>
+        <el-form-item label="序列号">
+          <el-input v-model="DialogData.lotoSerialNumber"  placeholder="请输入lotoSerialNumber"></el-input>
+        </el-form-item>
+        <el-form-item label="内容">
+          <el-input v-model="DialogData.content"  placeholder="请输入content"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button v-no-more-click type="primary" @click="submitTestForm"
+        >确 定
+        </el-button
+        >
+        <el-button v-no-more-click @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -340,9 +365,9 @@ import {
   deleteIsLockCabinetByCabinetIds,
   getIsLockCabinetPage,
   insertIsLockCabinet,
-  selectIsLockCabinetById,
+  selectIsLockCabinetById, sendDataToLoto,
   updateIsLockCabinet
-} from "@/api/mes/lockCabinet";
+} from '@/api/mes/lockCabinet'
 
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
@@ -377,6 +402,9 @@ export default {
       title: "",
       // 是否显示弹出层
       open: false,
+      openDialog: false,
+      DialogData:[],
+      TestRow:null,
       // 查询参数
       createTime: "",
       queryParams: {
@@ -490,6 +518,7 @@ export default {
     // 取消按钮
     cancel() {
       this.open = false;
+      this.openDialog = false;
       this.reset();
     },
     // 表单重置
@@ -567,6 +596,26 @@ export default {
         }
       });
     },
+    // 测试
+    openDialogFunction(row) {
+      this.openDialog = true;
+      this.TestRow=row
+    },
+    // 测试提交数据
+    submitTestForm(){
+      const params={
+        type:this.DialogData.type,
+        lotoSerialNumber:this.DialogData.lotoSerialNumber,
+        content:this.DialogData.content,
+      }
+      sendDataToLoto(params).then(response => {
+        this.$modal.msgSuccess('测试成功');
+        this.openDialog=false;
+        this.DialogData.type=''
+        this.DialogData.lotoSerialNumber=''
+        this.DialogData.content=''
+      })
+    },
     //图片上传成功
     handleImgUplaoded(imgUrl) {
       console.log(imgUrl);

+ 19 - 17
src/views/mes/hw/type/index.vue

@@ -8,10 +8,10 @@
       v-show="showSearch"
       label-width="100px"
     >
-      <el-form-item label="硬件编号" prop="hardwareTypeCode">
+      <el-form-item label="硬件类型编号" prop="hardwareTypeCode">
         <el-input
           v-model="queryParams.hardwareTypeCode"
-          placeholder="请输入硬件编号"
+          placeholder="请输入硬件类型编号"
           clearable
           @keyup.enter.native="handleQuery"
         />
@@ -60,15 +60,15 @@
         >
       </el-form-item>
     </el-form>
-<!--    <el-button-->
-<!--      v-no-more-click-->
-<!--      size="mini"-->
-<!--      type="primary"-->
-<!--      icon="el-icon-plus"-->
-<!--      @click="handleAdd"-->
-<!--      v-hasPermi="['mes:hw:type:add']"-->
-<!--    >新增</el-button-->
-<!--    >-->
+    <el-button
+      v-no-more-click
+      size="mini"
+      type="primary"
+      icon="el-icon-plus"
+      @click="handleAdd"
+      v-hasPermi="['mes:hw:type:add']"
+    >新增</el-button
+    >
     <el-table
       v-loading="loading"
       :data="machinerytypeList"
@@ -77,7 +77,7 @@
       :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
     >
       <el-table-column
-        label="硬件编号"
+        label="硬件类型编号"
         width="220"
         align="center"
         prop="hardwareTypeCode"
@@ -138,9 +138,10 @@
             v-hasPermi="['mes:hw:type:add']"
             >新增</el-button
           >
+<!--           v-if="scope.row.parentTypeId != 0"-->
           <el-button
             v-no-more-click
-            v-if="scope.row.parentTypeId != 0"
+
             size="mini"
             type="text"
             icon="el-icon-delete"
@@ -169,10 +170,10 @@
         </el-row>
         <el-row>
           <el-col :span="18">
-            <el-form-item label="硬件编号" prop="hardwareTypeCode">
+            <el-form-item label="硬件类型编号" prop="hardwareTypeCode">
               <el-input
                 v-model="form.hardwareTypeCode"
-                placeholder="请输入硬件编号"
+                placeholder="请输入硬件类型编号"
               />
             </el-form-item>
           </el-col>
@@ -190,10 +191,10 @@
         </el-row>
         <el-row>
           <el-col :span="12">
-            <el-form-item label="硬件名称" prop="machineryTypeName">
+            <el-form-item label="类型名称" prop="hardwareTypeName">
               <el-input
                 v-model="form.hardwareTypeName"
-                placeholder="请输入硬件名称"
+                placeholder="请输入类型名称"
               />
             </el-form-item>
           </el-col>
@@ -286,6 +287,7 @@ export default {
         hardwareTypeName: [
           { required: true, message: "硬件名称不能为空", trigger: "blur" },
         ],
+
       },
     };
   },

+ 13 - 13
src/views/mes/job/jobm/LockDetail.vue

@@ -85,19 +85,19 @@ export default {
             this.initKonva()
           })
         })
-        selectLotoMapById(lotoId, sopId, ticketId).then(response => {
-          console.log(response, '电柜预览接口调用')
-          this.form.map = response.data
-
-          if (response.data) {
-            try {
-              this.value = JSON.stringify(response.data, null, 4)
-              this.orignData = this.value
-            } catch (err) {
-            }
-          }
-          this.initKonva()
-        })
+        // selectLotoMapById(lotoId, sopId, ticketId).then(response => {
+        //   console.log(response, '电柜预览接口调用')
+        //   this.form.map = response.data
+        //
+        //   if (response.data) {
+        //     try {
+        //       this.value = JSON.stringify(response.data, null, 4)
+        //       this.orignData = this.value
+        //     } catch (err) {
+        //     }
+        //   }
+        //   this.initKonva()
+        // })
       })
 
       //   设备工艺详情

+ 13 - 13
src/views/mes/job/jobm/Mapdata.vue

@@ -87,19 +87,19 @@ export default {
             this.initKonva()
           })
         })
-        selectLotoMapById(lotoId, sopId, ticketId).then((response) => {
-          console.log(response, '电柜预览接口调用')
-          this.form.map = response.data
-
-          if (response.data) {
-            try {
-              this.value = JSON.stringify(response.data, null, 4)
-              this.orignData = this.value
-            } catch (err) {
-            }
-          }
-          this.initKonva()
-        })
+        // selectLotoMapById(lotoId, sopId, ticketId).then((response) => {
+        //   console.log(response, '电柜预览接口调用')
+        //   this.form.map = response.data
+        //
+        //   if (response.data) {
+        //     try {
+        //       this.value = JSON.stringify(response.data, null, 4)
+        //       this.orignData = this.value
+        //     } catch (err) {
+        //     }
+        //   }
+        //   this.initKonva()
+        // })
       })
 
       //   设备工艺详情

+ 31 - 28
src/views/mes/job/jobm/NewMarsJob.vue

@@ -833,18 +833,17 @@
       append-to-body
       class="elDialog"
     >
-      <!--      这里为了没有地图数据而设置的-->
       <el-row>
         <el-col :span="6">
           <div>
             <el-table :data="selectPointList" :show-header="false" style="width: 200px;height: 175px;">
               <el-table-column
-                prop="pointName"
-                label=""
+                prop="entityName"
+                label="隔离点名称"
               ></el-table-column>
               <el-table-column
                 prop="remark"
-                label=""
+                label="作用"
               ></el-table-column>
             </el-table>
           </div>
@@ -1165,23 +1164,26 @@ export default {
 
       getStepInfo(this.ticketId).then((res) => {
         this.EightStepForm = res.data
-        console.log(res, '作业票-详细信息')
+        console.log(res, '作业票步骤-详细信息')
       })
       this.machineryId = data.machineryId
       // 获取设备工艺图
       getTechnologyInfo(data.machineryId).then((res) => {
+        console.log(res,'工艺信息')
         this.machineryImg = res.data.machineryImg
         // 获取电柜选中隔离点
         const lotoId = res.data.lotoId
         const selectPointsIds = res.data.pointIdList
-
-        selectLotoMapById(lotoId).then((response) => {
-          console.log(response, '电柜信息--NewMarsJob')
-          this.selectPointList = response.data.filter((item) =>
-            selectPointsIds.includes(item.pointId)
-          )
-          console.log(this.selectPointList, '拿到的选中隔离点数据')
+        selectIsLotoStationById(lotoId).then((res) => {
+          selectIsMapById(res.data.mapId).then((response) => {
+            console.log(response, '电柜信息--NewMarsJob')
+            this.selectPointList = response.data.pointList.filter((item) =>
+              selectPointsIds.includes(item.entityId)
+            )
+            console.log(this.selectPointList, '拿到的选中隔离点数据')
+          })
         })
+
       })
     },
     getList() {
@@ -1243,6 +1245,15 @@ export default {
       const sysAttrKey = 'sys.map.permit'
       getIsSystemAttributeByKey(sysAttrKey).then((response) => {
         const sysAttrValue = response.data.sysAttrValue
+        const dataMap = {
+          pages: 1,
+          size: -1,
+          mapId: sysAttrValue
+        }
+        getIsMapPointPage(dataMap).then((res) => {
+          console.log(res, '作业票地图岗位位置信息接口')
+          this.jobconfigPoint = res.data
+        })
         // 这里获取全局配置地图参数里的作业票地图
         selectIsMapById(sysAttrValue).then((res) => {
           console.log(res, '作业票地图 图片数据')
@@ -1250,15 +1261,7 @@ export default {
         })
       })
 
-      const dataMap = {
-        pages: 1,
-        size: -1,
-        mapId: 1
-      }
-      getIsMapPointPage(dataMap).then((res) => {
-        console.log(res, '作业票地图岗位位置信息接口')
-        this.jobconfigPoint = res.data
-      })
+
     },
     // sop类型 el-radio
     handleSopchange(data) {
@@ -1324,13 +1327,13 @@ export default {
               // 获取电柜选中隔离点
               const lotoId = res.data.lotoId
               const selectPointsIds = res.data.pointIdList
-
-              selectLotoMapById(lotoId).then((response) => {
-                console.log(response, '电柜信息--NewMarsJob')
-                this.selectPointList = response.data.filter((item) =>
-                  selectPointsIds.includes(item.pointId)
-                )
-                console.log(this.selectPointList, '拿到的选中隔离点数据')
+              selectIsLotoStationById(lotoId).then((res) => {
+                selectIsMapById(res.data.mapId).then((response) => {
+                  this.selectPointList = response.data.filter((item) =>
+                    selectPointsIds.includes(item.pointId)
+                  )
+                  console.log(this.selectPointList, '拿到的选中隔离点数据')
+                })
               })
             })
           })

+ 0 - 1305
src/views/mes/job/jobm/NewOperation1.vue

@@ -1,1305 +0,0 @@
-<template>
-  <div class="newOperations">
-    <!--    newOperations盒子开始-->
-    <div class="left">
-      <!--        左边第一个是隔离点组件-->
-      <!--        第二个是车间组件-->
-
-      <SeparationPoint
-        v-show="this.activeName == 'second'"
-        @selection-changed="handleSelectPoint"
-        :points="points"
-      ></SeparationPoint>
-      <keep-alive>
-        <WorkShop
-          v-show="this.activeName == 'first' || this.activeName == 'third'"
-          @product-line-selected="handleProductLineSelected"
-          @work-shop-selected="handleWorkshopSelected"
-          :jobProps="jobProps"
-        ></WorkShop>
-      </keep-alive>
-    </div>
-    <div class="right">
-      <div class="right_top">
-        <el-card class="box-card">
-          <div slot="header" class="clearfix">
-            <span style="font-size: 18px">{{ this.getTicketTitle }}</span>
-            <span
-              style="
-                float: right;
-                padding: 1px 0;
-                font-size: 22px;
-                cursor: pointer;
-              "
-              type="text"
-              @click="goBack"
-            >×</span
-            >
-          </div>
-          <div class="text item">
-            <el-tabs v-model="activeName" @tab-click="handleClick">
-              <el-tab-pane label="作业票信息" name="first">
-                <!--                  新增作业票信息-->
-                <el-form ref="form" :model="form" label-width="90px">
-                  <el-form-item label="选择SOP" prop="sop">
-                    <el-select
-                      :disabled="this.getSopLook"
-                      v-model="form.sopId"
-                      placeholder="请选择sop"
-                      clearable
-                      style="width: 100%"
-                      @clear="handleClearSop"
-                      @change="handleSelectSOP"
-                    >
-                      <el-option
-                        v-for="dict in this.sopOptions"
-                        :key="dict.sopId"
-                        :label="dict.sopName"
-                        :value="dict.sopId"
-                      />
-                    </el-select>
-                  </el-form-item>
-                  <el-row>
-                    <el-col :span="16">
-                      <el-form-item label="作业票编号" prop="ticketCode">
-                        <el-input
-                          :disabled="this.getSopLook"
-                          v-model="form.ticketCode"
-                          placeholder="请输入作业票编号"
-                          style="width: 100%"
-                        />
-                      </el-form-item>
-                    </el-col>
-                    <el-col :span="8">
-                      <el-form-item label-width="80">
-                        <el-switch
-                          :disabled="this.getSopLook"
-                          v-model="autoGenFlag"
-                          active-color="#13ce66"
-                          active-text="自动生成"
-                          @change="handleAutoGenChange(autoGenFlag)"
-                        >
-                        </el-switch>
-                      </el-form-item>
-                    </el-col>
-                  </el-row>
-
-                  <el-form-item label="作业票名称" prop="ticketName">
-                    <el-input
-                      :disabled="this.getSopLook"
-                      v-model="form.ticketName"
-                      placeholder="请输入作业票名称"
-                      style="width: 100%"
-                    />
-                  </el-form-item>
-                  <el-form-item label="作业票类型" prop="ticketType">
-                    <el-select
-                      :disabled="this.getSopLook"
-                      v-model="form.ticketType"
-                      placeholder="请选择作业类型"
-                      clearable
-                      style="width: 100%"
-                    >
-                      <el-option
-                        v-for="dict in dict.type.ticket_type"
-                        :key="dict.value"
-                        :label="dict.label"
-                        :value="dict.value"
-                      />
-                    </el-select>
-                  </el-form-item>
-                  <el-form-item label="作业内容" prop="ticketContent">
-                    <el-input
-                      :disabled="this.getSopLook"
-                      type="textarea"
-                      v-model="form.ticketContent"
-                      :rows="4"
-                    ></el-input>
-                  </el-form-item>
-                  <el-form-item label="" prop="" style="margin-top: 80%">
-                    <el-button v-no-more-click
-                      type="primary"
-                      class="workTicket_btn"
-                      @click="nextStep('second')"
-                    >下一步
-                    </el-button>
-                  </el-form-item>
-                </el-form>
-              </el-tab-pane>
-              <el-tab-pane label="选择隔离点" name="second">
-                <!-- 隔离点信息-->
-                <el-form ref="form" :model="form" label-width="90px">
-                  <el-form-item label="车间名称" prop="workshopName">
-                    <el-input
-                      v-model="form.workshopName"
-                      placeholder="请输入车间名称"
-                      style="width: 100%"
-                      disabled
-                    />
-                  </el-form-item>
-                  <el-form-item label="区域" prop="workline">
-                    <el-input
-                      v-model="form.workline"
-                      placeholder="请输入区域"
-                      style="width: 100%"
-                      disabled
-                    />
-                  </el-form-item>
-                  <div class="text item">
-                    <p
-                      style="color: #606266; font-weight: 600; font-size: 14px"
-                    >
-                      已选隔离点
-                    </p>
-                    <el-table
-                      :data="tableData"
-                      stripe
-                      height="480"
-                      style="width: 100%"
-                    >
-                      <el-table-column prop="pointId" label="序号" width="60">
-                      </el-table-column>
-                      <el-table-column prop="pointName" label="已选隔离点">
-                        <template slot-scope="scope">
-                          <span style="color: #2a87ff">{{
-                              scope.row.pointName
-                            }}</span>
-                        </template>
-                      </el-table-column>
-                      <el-table-column prop="pointType" label="隔离点类型">
-                        <template slot-scope="scope">
-                          {{ scope.row.pointType }}
-                          <!--                          <dict-tag-->
-                          <!--                            :options="dict.type.point_type"-->
-                          <!--                            :value="scope.row.pointType"-->
-                          <!--                          />-->
-                        </template>
-                      </el-table-column>
-                      <el-table-column
-                        prop="powerType"
-                        label="危险能量类型"
-                        width="100"
-                      >
-                        <template slot-scope="scope">
-                          {{ scope.row.powerType }}
-                          <!--                          <dict-tag-->
-                          <!--                            :options="dict.type.power_type"-->
-                          <!--                            :value="scope.row.powerType"-->
-                          <!--                          />-->
-                        </template>
-                      </el-table-column>
-                    </el-table>
-                  </div>
-                  <el-form-item label="" prop="">
-                    <el-button v-no-more-click
-                      style="float: right; height: 30px; line-height: 10px"
-                      type="primary"
-                      @click="nextStep('third')"
-                    >下一步
-                    </el-button>
-                    <el-button v-no-more-click
-                      plain
-                      style="
-                        float: right;
-                        height: 30px;
-                        line-height: 10px;
-                        margin-right: 19%;
-                      "
-                      type="primary"
-                      @click="previousStep('first')"
-                    >上一步
-                    </el-button>
-                  </el-form-item>
-                </el-form>
-              </el-tab-pane>
-              <el-tab-pane label="人员选择" name="third">
-                <!--人员选择-->
-                <el-form ref="form" :model="form" label-width="70px">
-                  <el-form-item label="开始时间" prop="ticketStartTime">
-                    <el-date-picker
-                      :disabled="this.getSopLook"
-                      v-model="form.ticketStartTime"
-                      type="datetime"
-                      placeholder="选择日期时间"
-                      align="right"
-                      :picker-options="pickerOptions"
-                      style="width: 100%"
-                      @change="ticketStartTimeChange"
-                    >
-                    </el-date-picker>
-                  </el-form-item>
-                  <el-form-item label="结束时间" prop="ticketEndTime">
-                    <el-date-picker
-                      :disabled="this.getSopLook"
-                      v-model="form.ticketEndTime"
-                      type="datetime"
-                      placeholder="选择日期时间"
-                      align="right"
-                      :picker-options="pickerOptions"
-                      style="width: 100%"
-                      @change="ticketEndTimeChange"
-                    >
-                    </el-date-picker>
-                  </el-form-item>
-                  <el-form-item label="上锁人" prop="locker">
-                    <el-select
-                      :disabled="this.getSopLook"
-                      v-model="form.locker"
-                      placeholder="上锁人"
-                      clearable
-                      style="width: 100%"
-                      @change="handlelockerChage"
-                    >
-                      <el-option
-                        v-for="dict in this.listUserOption"
-                        :key="dict.value"
-                        :label="dict.label"
-                        :value="dict.value"
-                      />
-                    </el-select>
-                  </el-form-item>
-                  <!--
-                  <el-form-item label="共锁人" prop="coLocker">
-                    <el-select
-                      v-model="form.coLocker"
-                      placeholder="共锁人"
-                      clearable
-                      multiple
-                      style="width: 100%"
-                      @change="handleCoLockerChange"
-                      ref="coLockerSelect"
-                    >
-                      <el-option
-                        v-for="dict in sortedTicketUserDTOList"
-                        :key="dict.userId"
-                        :label="dict.username"
-                        :value="dict.username"
-                      >
-                      </el-option>
-                    </el-select>
-                  </el-form-item> -->
-                  <el-form-item label="共锁人" prop="coLocker">
-                    <el-button v-no-more-click
-                      type="primary"
-                      @click="addInside"
-                      class="gsr"
-                      size="mini"
-                    >添加内部人员
-                    </el-button>
-                    <el-button v-no-more-click type="primary" @click="addOutside" size="mini"
-                    >添加外部人员
-                    </el-button>
-                  </el-form-item>
-                  <div class="text item">
-                    <el-table
-                      :data="sortedTicketUserDTOList"
-                      stripe
-                      height="400"
-                      style="width: 100%"
-                    >
-                      <el-table-column prop="userId" label="序号" width="50">
-                      </el-table-column>
-                      <el-table-column
-                        prop="userName"
-                        label="共锁人"
-                        width="120"
-                      >
-                        <template slot-scope="scope">
-                          <span style="color: #2a87ff">{{
-                              scope.row.userName
-                            }}</span>
-                        </template>
-                      </el-table-column>
-                      <el-table-column prop="userRole" label="共锁人来源">
-                        <template slot-scope="scope">
-                          <span>{{
-                              scope.row.userRole == "0" ? "内部" : "外部"
-                            }}</span>
-                        </template>
-                      </el-table-column>
-                      <el-table-column label="" width="80">
-                        <template slot-scope="scope">
-                          <el-button v-no-more-click
-                            @click.native.prevent="
-                              deleteRow(scope.$index, sortedTicketUserDTOList)
-                            "
-                            type="text"
-                            size="small"
-                          >
-                            移除
-                          </el-button>
-                        </template>
-                      </el-table-column>
-                    </el-table>
-                  </div>
-
-                  <el-form-item label="" prop="">
-                    <el-button v-no-more-click
-                      style="float: right; height: 30px; line-height: 10px"
-                      type="primary"
-                      @click="confirm"
-                    >完 成
-                    </el-button>
-                  </el-form-item>
-                </el-form>
-              </el-tab-pane>
-            </el-tabs>
-          </div>
-        </el-card>
-      </div>
-    </div>
-    <!-- 添加或修改设备维修单对话框 -->
-    <el-dialog
-      :visible.sync="open"
-      width="450px"
-      append-to-body
-      style="margin-top: 13%"
-    >
-      <div slot="title" class="dialog-title">
-        <i></i>
-        <span class="title">{{ title }}</span>
-      </div>
-      <el-form
-        ref="dialogForm"
-        :model="dialogForm"
-        :rules="rules"
-        label-width="70px"
-      >
-        <el-form-item label="部门" prop="deptId" v-if="insideMumber">
-          <el-select
-            v-model="dialogForm.deptId"
-            placeholder="请选择部门"
-            clearable
-            style="width: 100%"
-            @change="DeptChage"
-          >
-            <el-option
-              v-for="dict in this.listDeptOption"
-              :key="dict.value"
-              :label="dict.label"
-              :value="dict.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="选择人员" prop="nickName" v-if="insideMumber">
-          <el-select
-            v-model="dialogForm.nickName"
-            placeholder="请选择人员"
-            clearable
-            style="width: 100%"
-            multiple
-            @change="changeInsideUser"
-          >
-            <el-option
-              v-for="dict in this.listUserOption"
-              :key="dict.value"
-              :label="dict.label"
-              :value="dict.value"
-            />
-          </el-select>
-        </el-form-item>
-
-        <el-form-item label="人员ID" prop="mumberId" v-if="outsideMumber">
-          <el-input
-            v-model="dialogForm.username"
-            placeholder="请输入人员ID"
-            style="width: 100%"
-            @change="outSideUserInput"
-          />
-        </el-form-item>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button v-no-more-click type="primary" @click="cancel">确认</el-button>
-        <el-button v-no-more-click @click="cancel">取 消</el-button>
-      </div>
-    </el-dialog>
-    <!--    newOperations盒子结束-->
-  </div>
-</template>
-
-
-<script>
-import SeparationPoint from "@/components/separationPoint/index1.vue";
-import WorkShop from "@/components/separationPoint/workshop.vue";
-import {
-  listJobTicket,
-  getJobTicketInfo,
-  addJobTicket,
-  updateJobTicket,
-  deleteIsJobTicket,
-  getworkareaList,
-} from "@/api/mes/job/job";
-
-import { mapGetters, mapActions } from "vuex";
-
-import { listWorkshop } from "@/api/mes/md/workshop";
-import { listWorkarea } from "@/api/mes/wa/workarea";
-import { getIsSopPage } from "@/api/mes/sop/sopindex-booz";
-import { listUser } from "@/api/system/user";
-import { listDept } from "@/api/system/dept";
-import IsolationLeftVue from "@/components/separationPoint/index1.vue";
-import { genCode } from "@/api/system/autocode/rule";
-
-export default {
-  name: "addView",
-  dicts: ["ticket_type", "power_type", "point_type", "is_user_type"],
-  components: {
-    IsolationLeftVue,
-    SeparationPoint,
-    WorkShop,
-  },
-  data() {
-    return {
-      //自动生成编码
-      autoGenFlag: false,
-      activeName: "first",
-      form: {
-        sopId: "",
-        pointIds: "",
-        ticketId: "",
-        ticketType: "",
-        ticketName: "",
-        ticketCode: "",
-        ticketContent: "",
-        workshopName: "", //车间名称
-        workline: "", //区域
-        spoint: [], //已选隔离点
-        locker: "", //上锁人
-        coLocker: "", //共锁人
-        ticketStartTime: "", //开始时间
-        ticketEndTime: "", //结束时间
-        ticketUserDTOList: [
-          // {
-          //   userId: '',
-          //   userName: '',
-          //   userRole: '',//作业票角色 暂时不传递 内部人还是外部人
-          //   userType: ''//用户类型 上锁人或共锁人
-          // }
-        ], //所选择的用户
-      },
-      // 用来清空form
-      initialFormState: {
-        // 初始状态对象
-        sopId: "",
-        pointIds: "",
-        ticketId: "",
-        ticketType: "",
-        ticketName: "",
-        ticketCode: "",
-        ticketContent: "",
-        workshopName: "", //车间名称
-        workline: "", //区域
-        spoint: [], //已选隔离点
-        locker: "", //上锁人
-        coLocker: "", //共锁人
-        ticketStartTime: "", //开始时间
-        ticketEndTime: "", //结束时间
-        ticketUserDTOList: [
-          // {
-          //   userId: '',
-          //   userName: '',
-          //   userRole: '',//作业票角色 暂时不传递 内部人还是外部人
-          //   userType: ''//用户类型 上锁人或共锁人
-          // }
-        ], //所选择的用户
-      },
-      dialogForm: {
-        deptId: "",
-        nickName: "",
-        username: "",
-      },
-      listUserOption: null,
-      listDeptOption: null,
-      // 已选隔离点
-      tableData: [],
-      pickerOptions: {
-        shortcuts: [
-          {
-            text: "今天",
-            onClick(picker) {
-              picker.$emit("pick", new Date());
-            },
-          },
-          {
-            text: "昨天",
-            onClick(picker) {
-              const date = new Date();
-              date.setTime(date.getTime() - 3600 * 1000 * 24);
-              picker.$emit("pick", date);
-            },
-          },
-          {
-            text: "一周前",
-            onClick(picker) {
-              const date = new Date();
-              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
-              picker.$emit("pick", date);
-            },
-          },
-        ],
-      },
-      // 是否显示弹出层
-      open: false,
-      // 弹出层标题
-      title: "",
-      // 弹框中显示的form表单内容
-      insideMumber: false,
-      outsideMumber: false,
-      points: null, //逆向传递拿到隔离点的数据
-      sopOptions: [], //sop下拉
-      jobProps: [], //正向传递给车间components
-
-      // 表单校验
-      rules: {
-        teamCode: [
-          { required: true, message: "班组编号不能为空", trigger: "blur" },
-        ],
-        teamName: [
-          { required: true, message: "班组名称不能为空", trigger: "blur" },
-        ],
-        calendarType: [
-          { required: true, message: "清选择班组类型", trigger: "blur" },
-        ],
-      },
-      newticketUserDTOList: [], //为了上锁人单独传递数据
-    };
-  },
-  watch: {
-    tableData: {
-      handler(newVal) {
-        // 将 pointId 提取出来并连接成一个字符串
-        if (newVal && newVal.length > 0) {
-          this.form.pointIds = this.tableData
-            .map((item) => item.pointId)
-            .join(",");
-          // console.log(this.form.pointIds, this.tableData, 'pointIds')
-        }
-      },
-      deep: true,
-    },
-    "form.ticketStartTime": {
-      handler(newVal) {
-        if (newVal && newVal.length > 0) {
-          console.log(newVal, "编辑监听开始时间");
-          this.ticketStartTimeChange(newVal);
-        }
-      },
-    },
-  },
-  computed: {
-    ...mapGetters("sopSelectPoints", [
-      "getPointTableData",
-      "getSelectSopPoints",
-      "getSopEdit",
-      "getTicketTitle",
-      "getSopLook",
-    ]),
-    // 排序 ticketUserDTOList,将 userRole 为 0 的选项放在前面
-    sortedTicketUserDTOList() {
-      return this.form.ticketUserDTOList.sort(
-        (a, b) => Number(a.userRole) - Number(b.userRole)
-      );
-    },
-  },
-  mounted() {
-    this.getSopList();
-    this.getUser();
-    if (this.$route.query.ticketId !== "null") {
-      this.getTicket();
-      this.form.ticketId = this.$route.query.ticketId;
-      if (this.getSopLook) {
-        this.setTicketTitle("查看作业票");
-      } else {
-        this.setTicketTitle("编辑作业票");
-      }
-    } else {
-      this.setSelectSopPoints([]);
-      this.setPointTableData([]);
-      this.setTicketTitle("新建作业票");
-    }
-    // console.log(this.getPointTableData, 'this.getPointTableData')
-    if (this.getPointTableData) {
-      this.tableData = this.getPointTableData.pointDetailVOList.map((item) => {
-        return {
-          pointId: item.pointId,
-          pointName: item.pointName,
-          pointType: item.pointType,
-          powerType: item.powerType,
-        };
-      });
-    }
-  },
-
-  methods: {
-    // 编辑的时候给隔离点重新存储值
-    ...mapActions("sopSelectPoints", [
-      "setSelectSopPoints",
-      "setPointTableData",
-      "setSopEdit",
-      "setTicketTitle",
-    ]),
-    formatDateTime(date) {
-      const year = date.getFullYear().toString().padStart(2, "0");
-      const month = (date.getMonth() + 1).toString().padStart(2, "0");
-      const day = date.getDate().toString().padStart(2, "0");
-      const hours = date.getHours().toString().padStart(2, "0");
-      const minutes = date.getMinutes().toString().padStart(2, "0");
-      const seconds = date.getSeconds().toString().padStart(2, "0");
-
-      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
-    },
-    getTicket() {
-      this.getUser();
-
-      const ticketId = this.$route.query.ticketId;
-      getJobTicketInfo(ticketId).then((response) => {
-        console.log(response, "编辑拿到路由参数");
-        this.form = {
-          ...this.form,
-          workshopId: response.data.workshopId,
-          workareaId: response.data.workareaId,
-          sopId: response.data.sopId,
-          ticketCode: response.data.ticketCode,
-          ticketContent: response.data.ticketContent,
-          spoint: response.data.pointDetailVOList,
-          ticketUserDTOList: response.data.jobTicketUserList
-            .filter((item) => item.userType !== "0")
-            .map((item) => ({
-              userName: item.userName,
-              userType: item.userType,
-              userRole: item.userRole,
-              userId: item.userId,
-            })),
-          // ticketUserDTOList: response.data.jobTicketUserList.map((item) => {
-          //   return {
-          //     userName: item.userName,
-          //     userType: item.userType,
-          //     userRole: item.userRole,
-          //     userId: item.userId
-          //   }
-          // }),
-          locker: response.data.jobTicketUserList
-            .filter((item) => item.userType == "0")
-            .map((item) => item.userName),
-          coLocker: response.data.jobTicketUserList.map((item) => {
-            return item.userType !== "0" ? item.userName : null;
-          }),
-          ticketStartTime: response.data.ticketStartTime,
-          ticketEndTime: response.data.ticketEndTime,
-          ticketId: response.data.ticketId,
-          ticketName: response.data.ticketName,
-          ticketStatus: response.data.ticketStatus,
-          ticketType: response.data.ticketType,
-          EditBool: true,
-        };
-        this.jobProps = [this.form];
-        // this.listUserOption = response.data.jobTicketUserList
-        console.log(this.form, "form");
-      });
-    },
-
-    getSopList() {
-      const query = {
-        current: 1,
-        size: 100000,
-      };
-      getIsSopPage(query).then((res) => {
-        console.log(res, "sop列表接口");
-        // 插入一个默认的空选项
-        const defaultOption = {
-          sopId: null,
-          sopName: "不使用sop模板  ",
-        };
-
-        // 将默认选项添加到结果的最前面
-        this.sopOptions = [defaultOption, ...res.data.records];
-      });
-    },
-    getUser() {
-      const query = {
-        pageNum: 1,
-        pageSize: 100000,
-      };
-      listUser(query).then((res) => {
-        // console.log(res, '用户列表')
-        this.listUserOption = res.rows.map((item) => {
-          return {
-            label: item.nickName,
-            value: item.userId,
-          };
-        });
-      }),
-        listDept(query).then((res) => {
-          // console.log(res, '部门列表')
-          this.listDeptOption = res.data.map((item) => {
-            return {
-              label: item.deptName,
-              value: item.deptId,
-            };
-          });
-        });
-    },
-    // 添加内部人员 部门下拉的chage事件
-    DeptChage(val) {
-      console.log(val, " 部门下拉");
-      // 每次选中先清空用户下拉
-      // this.listUserOption = []
-      this.dialogForm.nickName = null;
-      const query = {
-        pageNum: 1,
-        pageSize: 100000,
-        deptId: this.dialogForm.deptId,
-      };
-      listUser(query).then((res) => {
-        console.log(res, "用户列表");
-        this.listUserOption = res.rows.map((item) => {
-          return {
-            label: item.nickName,
-            value: item.userId,
-          };
-        });
-      });
-    },
-    // sop下拉change事件 可以传递sopOptions一整个对象过去
-    handleSelectSOP(value) {
-      if (value == null) {
-        this.jobProps = [];
-        console.log(this.form.sopId, this.form, "sop下拉change事件");
-      } else {
-        this.jobProps = this.sopOptions.filter((item) => item.sopId == value);
-        this.form.ticketType = this.jobProps[0].sopType;
-        this.form.ticketName = "sop_";
-        console.log(this.jobProps, "父组件jobProps");
-      }
-    },
-    // 清除sop下拉框
-    handleClearSop() {
-      this.form.ticketType = "";
-      this.form.ticketName = "";
-    },
-    // 上锁人下拉选择change事件
-    handlelockerChage(val) {
-      console.log(val, "上锁人chage");
-      const user = this.listUserOption.find((item) => item.value === val);
-
-      if (user && this.form.locker !== "") {
-        const existingUser = this.form.ticketUserDTOList.find(
-          (u) => u.userName === user.label
-        );
-        if (!existingUser) {
-          this.newticketUserDTOList.push({
-            userName: user.label,
-            userId: user.value,
-            userType: 0,
-            userRole: "0",
-          });
-          // this.form.ticketUserDTOList.push({
-          //   userName: user.label,
-          //   userId: user.value,
-          //   userType: 0,
-          //   userRole: '0',
-          // })
-          console.log(this.newticketUserDTOList, "用户");
-        } else {
-          // console.log('用户已存在', user.label)
-        }
-      }
-    },
-
-    // 添加内部人员的用户新增到ticketUserDTOList这个数据里
-    changeInsideUser(values) {
-      const usersinside = values
-        .map((value) =>
-          this.listUserOption.find((item) => item.value === value)
-        )
-        .filter(Boolean);
-      usersinside.forEach((user) => {
-        const existingUser = this.form.ticketUserDTOList.find(
-          (u) => u.userName === user.label
-        );
-        // console.log(usersinside, 'usersinside----67')
-        if (!existingUser) {
-          this.form.ticketUserDTOList.push({
-            userName: user.label,
-            userId: user.value,
-            userType: 1,
-            userRole: 0,
-            bgColor: "green",
-          });
-          console.log(this.form.ticketUserDTOList, "用户");
-        } else {
-          // console.log('用户已存在', user.label)
-        }
-      });
-      this.updateCoLocker();
-
-      // console.log(this.form.ticketUserDTOList, '用户')
-    },
-    // 添加外部人员 输入名称 userType==1是共锁人 0是上锁人 userId==0
-    outSideUserInput(value) {
-      // console.log(value, '外部人员名称')
-      const existingUser = this.form.ticketUserDTOList.find(
-        (u) => u.userName === value
-      );
-
-      if (!existingUser) {
-        this.form.ticketUserDTOList.push({
-          userName: value,
-          userId: 0,
-          userType: 1,
-          userRole: 1,
-          bgColor: "red",
-        });
-        console.log(this.form.ticketUserDTOList, "用户");
-      } else {
-        // console.log('用户已存在', value)
-      }
-      this.updateCoLocker();
-    },
-    // 更新界面中共锁人下拉框显示的内容
-    // 更新 coLocker 数据
-    updateCoLocker() {
-      // 获取现有的 coLocker 数据
-      const existingCoLocker = new Set(this.form.coLocker);
-      // console.log(existingCoLocker, 'existingCoLocker----1');
-
-      // 将 ticketUserDTOList 中的新用户名字添加到 existingCoLocker 中
-
-      this.form.ticketUserDTOList.forEach((user) => {
-        existingCoLocker.add(user.userName);
-      });
-      // console.log(this.form.ticketUserDTOList, 'this.form.ticketUserDTOList----2');
-
-      // 将 Set 转换回数组
-      this.form.coLocker = Array.from(existingCoLocker);
-      // console.log(this.form.coLocker, 'this.form.coLocker----3');
-
-      // 检查并补充 ticketUserDTOList 中缺少的用户
-      this.form.coLocker.forEach((name) => {
-        const existingUser = this.form.ticketUserDTOList.find(
-          (u) => u.userName === name
-        );
-
-        if (!existingUser) {
-          this.form.ticketUserDTOList.push({
-            userName: name,
-            userId: 0,
-            userType: 1,
-            userRole: 1,
-            bgColor: "red",
-          });
-        }
-      });
-
-      console.log(this.form.ticketUserDTOList, "最终的 ticketUserDTOList");
-    },
-    // 设置多选下拉框样式
-    // updateTagBackgrounds() {
-    //   this.$nextTick(() => {
-    //     const elTags = this.$refs.coLockerSelect.$el.querySelectorAll('.el-tag')
-    //
-    //     elTags.forEach(tag => {
-    //       const tagText = tag.textContent.trim()
-    //       const option = this.form.ticketUserDTOList.find(dict => dict.userName === tagText)
-    //
-    //       if (option) {
-    //         tag.style.backgroundColor = option.bgColor
-    //
-    //       }
-    //     })
-    //   })
-    // },
-    // 共锁人下拉框删除事件
-    // handleCoLockerChange(newValues) {
-    //   console.log(newValues, 'ticketUserDTOList-newsValue')
-    //
-    //   // 根据新值更新 this.form.ticketUserDTOList
-    //   this.form.ticketUserDTOList = this.form.ticketUserDTOList.filter((user) =>
-    //     newValues.includes(user.userName)
-    //   )
-    //
-    //   // 更新 coLocker 显示的内容
-    //   this.updateCoLocker()
-    // },
-    handleClick(tab, event) {
-      // console.log(tab, event);
-    },
-    previousStep(val) {
-      this.activeName = val;
-    },
-    nextStep(val) {
-      console.log(val, "nextStep");
-      this.activeName = val;
-      console.log("我点击了下一步");
-    },
-    async getWorkareaId(query) {
-      try {
-        const res = await listWorkarea(query);
-        console.log(res, "作业区域page");
-        return res.data.records[0].workareaId;
-      } catch (error) {
-        console.error("获取作业区域ID失败", error);
-        throw error;
-      }
-    },
-
-    async getWorkshopId(query) {
-      try {
-        const res = await listWorkshop(query);
-        console.log(res, "车间id");
-        return res.rows[0].workshopId;
-      } catch (error) {
-        console.error("获取车间ID失败", error);
-        throw error;
-      }
-    },
-
-    async confirm() {
-      try {
-        // 格式化时间
-        this.form.ticketStartTime = this.formatDateTime(
-          new Date(this.form.ticketStartTime)
-        );
-        this.form.ticketEndTime = this.formatDateTime(
-          new Date(this.form.ticketEndTime)
-        );
-        console.log(this.form, "拿到的所有参数确认");
-
-        const query = {
-          current: 1,
-          size: 100000,
-          workareaName: this.form.workline,
-        };
-
-        const query1 = {
-          current: 1,
-          size: 100000,
-          workshopName: this.form.workshopName,
-        };
-
-        const workareaId = await this.getWorkareaId(query);
-        const workshopId = await this.getWorkshopId(query1);
-
-        // 合并 newticketUserDTOList 到 this.form.ticketUserDTOList
-        if (this.form.locker) {
-          const selectedUser = this.listUserOption.find(
-            (option) => option.label === this.form.locker
-          );
-          if (selectedUser) {
-            this.form.ticketUserDTOList.push({
-              userName: selectedUser.label,
-              userId: selectedUser.value,
-              userType: "0",
-              userRole: "0",
-            });
-          }
-        }
-        this.form.ticketUserDTOList.push(...this.newticketUserDTOList);
-        const data = {
-          pointIds: this.form.pointIds,
-          sopId: this.form.sopId,
-          ticketCode: this.form.ticketCode,
-          ticketContent: this.form.ticketContent,
-          ticketEndTime: this.form.ticketEndTime,
-          ticketName: this.form.ticketName,
-          ticketStartTime: this.form.ticketStartTime,
-          ticketType: this.form.ticketType,
-          ticketUserDTOList: this.form.ticketUserDTOList,
-          workareaId: workareaId,
-          workshopId: workshopId,
-        };
-        const editdata = {
-          pointIds: this.form.spoint.join(","),
-          sopId: this.form.sopId,
-          ticketCode: this.form.ticketCode,
-          ticketContent: this.form.ticketContent,
-          ticketId: this.form.ticketId,
-          ticketEndTime: this.form.ticketEndTime,
-          ticketName: this.form.ticketName,
-          ticketStartTime: this.form.ticketStartTime,
-          ticketType: this.form.ticketType,
-          ticketUserDTOList: this.form.ticketUserDTOList,
-          workareaId: workareaId,
-          workshopId: workshopId,
-        };
-
-        // 检查 route.query.ticketId 是否为 null
-        console.log(this.$route.query.ticketId, "this.$route.query.ticketId");
-        if (this.$route.query.ticketId !== "null") {
-          // 调用编辑接口
-          const res = await updateJobTicket(editdata);
-          if (res.code === 200) {
-            // this.$router.go(-1);
-            this.$router.push("/job/jobm");
-            localStorage.removeItem("workshopId");
-            localStorage.removeItem("workareaId");
-          } else {
-            console.error("编辑工单失败", res);
-          }
-        } else {
-          // 调用新增接口
-          const res = await addJobTicket(data);
-          if (res.code === 200) {
-            // this.$router.go(-1);
-            this.$router.push("/job/jobm");
-          } else {
-            console.error("提交工单失败", res);
-          }
-        }
-      } catch (error) {
-        console.error("确认过程中发生错误", error);
-      }
-
-      console.log("确认");
-    },
-    // 子组件逆向传递选中的隔离点
-
-    handleSelectPoint(points) {
-      // console.log(points, '父组件接收逆向传递选中的隔离点')
-
-      // 使用 Set 来存储传递过来的点值
-      const newValues = new Set(points.map((point) => point.pointId));
-
-      // 1. 删除取消选中的点
-      this.tableData = this.tableData.filter((item) =>
-        newValues.has(item.pointId)
-      );
-
-      // 2. 确保新增点不会重复
-      const existingValues = new Set(
-        this.tableData.map((item) => item.pointId)
-      );
-
-      points.forEach((point) => {
-        // 如果当前传递的点不在已有的点集中,则添加
-        if (!existingValues.has(point.pointId)) {
-          this.tableData.push({
-            pointName: point.pointName, // 显示的名称
-            pointId: point.pointId, // 对应的值
-            pointType: point.pointType,
-            powerType: point.powerType,
-          });
-          // 将新点值添加到 Set 中
-          existingValues.add(point.value);
-        }
-      });
-
-      // 更新 form.spoint 为最新选中的隔离点数组
-      this.form.spoint = points.map((point) => point.pointId);
-    },
-    // 车间你逆向传递拿到的隔离点数据产线
-    handleProductLineSelected(selectedOption) {
-      // console.log(selectedOption, '父组件接收到的 selectedOption');
-      this.points = selectedOption;
-      this.form.workline = selectedOption.label;
-    },
-    // 车间子组件逆传递车间相关数据车间
-    handleWorkshopSelected(selectedOption) {
-      console.log(selectedOption, "handleWorkshopSelected");
-      this.emitWorkShop = selectedOption;
-      this.form.workshopName = selectedOption.label;
-    },
-    // 添加内部人员
-    addInside() {
-      this.open = true;
-      this.title = "添加内部人员";
-      this.insideMumber = true;
-      this.outsideMumber = false;
-      // this.form.ticketUserDTOList = [];
-      this.dialogForm.deptId = "";
-      this.dialogForm.nickName = "";
-    },
-    addOutside() {
-      this.open = true;
-      this.title = "添加外部人员";
-      this.insideMumber = false;
-      this.outsideMumber = true;
-      this.dialogForm.username = null;
-    },
-    // 取消按钮
-    cancel() {
-      this.open = false;
-    },
-    // 人员列表删除
-    // deleteRow(index, rows) {
-    //   console.log(index, rows, '删除的行')
-    //   rows.splice(index, 1)
-    //   this.form.ticketUserDTOList.splice(index, 1)
-    // },
-    deleteRow(index, rows) {
-      console.log(index, rows, "删除的行");
-      const deletedItem = rows[index]; // 获取要删除的项
-      rows.splice(index, 1); // 从显示的列表中删除
-      const formIndex = this.form.ticketUserDTOList.findIndex(
-        (item) => item.userId === deletedItem.userId
-      );
-      if (formIndex !== -1) {
-        this.form.ticketUserDTOList.splice(formIndex, 1); // 从 form.ticketUserDTOList 中删除
-      }
-    },
-    //   时间选项
-    ticketStartTimeChange(value) {
-      this.form.ticketStartTime = value;
-      // 更新 pickerOptions 中的 disabledDate 方法
-      this.updatePickerOptions();
-    },
-    ticketEndTimeChange(value) {
-      this.form.ticketEndTime = value;
-    },
-    disabledDate(time) {
-      const startTime = new Date(this.form.ticketStartTime);
-      return startTime && !isNaN(startTime.getTime())
-        ? time.getTime() < startTime.getTime()
-        : false;
-    },
-    updatePickerOptions() {
-      this.pickerOptions.disabledDate = this.disabledDate;
-    },
-
-    reset() {
-      (this.form = {
-        sopId: "",
-        pointIds: "",
-        ticketType: "",
-        ticketName: "",
-        ticketCode: "",
-        ticketContent: "",
-        workshopName: "", //车间名称
-        workline: "", //区域
-        spoint: [], //已选隔离点
-        locker: "", //上锁人
-        coLocker: "", //共锁人
-        ticketStartTime: "", //开始时间
-        ticketEndTime: "", //结束时间
-        ticketUserDTOList: [
-          // {
-          //   userId: '',
-          //   userName: '',
-          //   userRole: '',//作业票角色 暂时不传递
-          //   userType: ''//用户类型 上锁人或共锁人
-          // }
-        ],
-      }),
-        (this.autoGenFlag = false);
-    },
-
-    // 侧边x关闭函数
-    goBack() {
-      this.$router.push("/job/jobm");
-    },
-    //自动生成编码
-    handleAutoGenChange(autoGenFlag) {
-      if (autoGenFlag) {
-        genCode("JOB_TICKET_CODE").then((response) => {
-          this.form.ticketCode = response;
-        });
-      } else {
-        this.form.ticketCode = null;
-      }
-    },
-  },
-};
-</script>
-
-
-<style scoped lang="scss">
-.newOperations {
-  width: 99%;
-  height: 100%;
-  //background: pink;
-  margin: 10px;
-  display: flex;
-
-  .left {
-    width: 75%;
-    height: 830px;
-    // background: #eee;
-    margin-right: 10px;
-  }
-
-  .right {
-    height: 100%;
-    flex: 1;
-
-    .right_top {
-      height: 550px;
-    }
-
-    .workTicket_btn {
-      position: relative;
-      left: 63%;
-      height: 30px;
-      line-height: 10px;
-    }
-
-    .gsr {
-      margin-left: 60px;
-    }
-  }
-}
-
-//右侧卡片样式开始
-.text {
-  font-size: 14px;
-}
-
-.item {
-  margin-bottom: 18px;
-
-  p {
-    font-size: 18px;
-    font-weight: bolder;
-    font-family: SourceHanSansSC-bold;
-  }
-}
-
-.clearfix:before,
-.clearfix:after {
-  display: table;
-  content: "";
-  width: 320px;
-}
-
-.clearfix:after {
-  clear: both;
-}
-
-.box-card {
-  // width: 390px;
-  width: 95%;
-  height: 850px;
-}
-
-//右侧卡片样式结束
-//隔离点多选框样式
-.selects {
-  .el-input.el-input--medium.el-input--suffix {
-    // 调整箭头符号块的宽度
-    width: 175px !important;
-  }
-
-  .el-input.el-input--medium.el-input--suffix {
-    .el-input__inner {
-      // 调整输入框的宽高
-      height: 36px !important;
-      width: 220px !important;
-    }
-
-    .el-input__suffix-inner {
-      // 调整箭头符号的位置
-      position: absolute;
-      right: -45px;
-    }
-  }
-
-  .el-select__tags {
-    // 调整输入框里面的多选不换行
-    flex-wrap: nowrap !important;
-  }
-}
-
-//隔离点多选框样式结束
-</style>
-
-<style scoped lang="scss" src="@/assets/styles/dialog-title.scss">
-</style>

+ 0 - 1486
src/views/mes/job/jobm/NewOperations.vue

@@ -1,1486 +0,0 @@
-<template>
-  <div class="newOperations">
-    <!--    newOperations盒子开始-->
-    <div class="left">
-      <!--        左边第一个是隔离点组件-->
-      <!--        第二个是车间组件-->
-
-      <SeparationPoint
-        v-show="this.activeName == 'second'"
-        @selection-changed="handleSelectPoint"
-        :points="points"
-      ></SeparationPoint>
-      <keep-alive>
-        <WorkShop
-          v-show="this.activeName == 'first' || this.activeName == 'third'"
-          @product-line-selected="handleProductLineSelected"
-          @work-shop-selected="handleWorkshopSelected"
-          :jobProps="jobProps"
-        ></WorkShop>
-      </keep-alive>
-    </div>
-    <div class="right">
-      <div class="right_top">
-        <el-card class="box-card">
-          <div slot="header" class="clearfix">
-            <span style="font-size: 18px">{{ this.getTicketTitle }}</span>
-            <span
-              style="
-                float: right;
-                padding: 1px 0;
-                font-size: 22px;
-                cursor: pointer;
-              "
-              type="text"
-              @click="goBack"
-            >×</span
-            >
-
-          </div>
-          <div class="text item">
-            <el-tabs v-model="activeName" @tab-click="handleClick">
-              <el-tab-pane label="作业票信息" name="first">
-                <!--                  新增作业票信息-->
-                <el-form ref="form" :rules="rules" :model="form" label-width="100px">
-                  <!--                 getVisibleSopSelect是vuex判断新增是自定义还是建SOP作业票 第二个是编辑的时候如果有sopId就渲染 -->
-
-                  <el-form-item label="选择SOP" prop="sop" v-if="this.getVisibleSopSelect&&this.form.sopId!==null">
-                    <el-select
-                      :disabled="this.getSopLook"
-                      v-model="form.sopId"
-                      placeholder="请选择sop"
-                      clearable
-                      style="width: 100%"
-                      @clear="handleClearSop"
-                      @change="handleSelectSOP"
-                    >
-                      <el-option
-                        v-for="dict in this.sopOptions"
-                        :key="dict.sopId"
-                        :label="dict.sopName"
-                        :value="dict.sopId"
-                      />
-                    </el-select>
-                  </el-form-item>
-
-                  <el-form-item label="作业票名称" prop="ticketName">
-                    <el-input
-                      :disabled="this.getSopLook"
-                      v-model="form.ticketName"
-                      placeholder="请输入作业票名称"
-                      style="width: 100%"
-                    />
-                  </el-form-item>
-                  <el-row>
-                    <el-col :span="16">
-                      <el-form-item label="作业票编号" prop="ticketCode">
-                        <el-input
-                          :disabled="this.getSopLook"
-                          v-model="form.ticketCode"
-                          placeholder="请输入作业票编号"
-                          style="width: 100%"
-                        />
-                      </el-form-item>
-                    </el-col>
-                    <el-col :span="8">
-                      <el-form-item label-width="80">
-                        <el-switch
-                          :disabled="this.getSopLook"
-                          v-model="autoGenFlag"
-                          active-color="#13ce66"
-                          active-text="自动生成"
-                          @change="handleAutoGenChange(autoGenFlag)"
-                        >
-                        </el-switch>
-                      </el-form-item>
-                    </el-col>
-                  </el-row>
-
-                  <el-form-item label="作业票类型" prop="ticketType">
-                    <el-select
-                      :disabled="this.getSopLook"
-                      v-model="form.ticketType"
-                      placeholder="请选择作业类型"
-                      clearable
-                      style="width: 100%"
-                    >
-                      <el-option
-                        v-for="dict in dict.type.ticket_type"
-                        :key="dict.value"
-                        :label="dict.label"
-                        :value="dict.value"
-                      />
-                    </el-select>
-                  </el-form-item>
-                  <el-form-item label="作业内容" prop="ticketContent">
-                    <el-input
-                      :disabled="this.getSopLook"
-                      type="textarea"
-                      v-model="form.ticketContent"
-                      :rows="4"
-                    ></el-input>
-                  </el-form-item>
-                  <el-form-item label="" prop="" style="margin-top: 80%">
-                    <el-button v-no-more-click
-                               type="primary"
-                               class="workTicket_btn"
-                               @click="nextStep('second')"
-                    >下一步
-                    </el-button>
-                  </el-form-item>
-                </el-form>
-              </el-tab-pane>
-              <el-tab-pane label="隔离点信息" name="second">
-                <!-- 隔离点信息-->
-                <el-form ref="form" :model="form" label-width="90px">
-                  <el-form-item label="作业区域" prop="workline">
-                    <el-input
-                      v-model="form.workline"
-                      style="width: 100%"
-                      disabled
-                    />
-                  </el-form-item>
-                  <div class="text item">
-                    <p
-                      style="color: #606266; font-weight: 600; font-size: 14px"
-                    >
-                      已选隔离点
-                    </p>
-                    <el-table
-                      :data="tableData"
-                      stripe
-                      height="480"
-                      style="width: 100%"
-                    >
-                      <!--                      <el-table-column prop="pointId" label="序号" width="60">-->
-                      <!--                      </el-table-column>-->
-                      <el-table-column prop="pointName" label="隔离点" width="60">
-                        <template slot-scope="scope">
-                          <span style="color: #2a87ff">{{
-                              scope.row.pointName
-                            }}</span>
-                        </template>
-                      </el-table-column>
-                      <el-table-column prop="pointType" label="隔离点类型">
-                        <template slot-scope="scope">
-                          {{ scope.row.pointType }}
-
-                        </template>
-                      </el-table-column>
-                      <el-table-column
-                        prop="powerType"
-                        label="危险能量类型"
-                        width="100"
-                      >
-                        <template slot-scope="scope">
-                          {{ scope.row.powerType }}
-                        </template>
-                      </el-table-column>
-                      <el-table-column
-                        prop="prePointId"
-                        label="前置隔离点"
-
-                      >
-                        <template slot-scope="scope">
-<!--                          选择了sop之后不允许切换前置隔离点-->
-                          <el-select size="mini" v-model="scope.row.prePointId" @change="prePointIdChange(scope.row)"
-                                     @visible-change="onDropdownVisibleChange(scope.row)" clearable
-                                     @clear="clearprePointId"
-                                     :disabled="form.sopId!==''"
-                          >
-                            <el-option v-for="item in prePointIdOptions"
-                                       :key="item.pointId"
-                                       :label="item.pointName"
-                                       :value="item.pointId"
-                            >
-                            </el-option>
-                          </el-select>
-                        </template>
-                      </el-table-column>
-                    </el-table>
-                  </div>
-                  <el-form-item label="" prop="">
-                    <el-button v-no-more-click
-                               style="float: right; height: 30px; line-height: 10px"
-                               type="primary"
-                               @click="nextStep('third')"
-                    >下一步
-                    </el-button>
-                    <el-button v-no-more-click
-                               plain
-                               style="
-                        float: right;
-                        height: 30px;
-                        line-height: 10px;
-                        margin-right: 19%;
-                      "
-                               type="primary"
-                               @click="previousStep('first')"
-                    >上一步
-                    </el-button>
-                  </el-form-item>
-                </el-form>
-              </el-tab-pane>
-              <el-tab-pane label="人员选择" name="third">
-                <!--人员选择-->
-                <el-form ref="form" :model="form" label-width="70px">
-                  <el-form-item label="开始时间" prop="ticketStartTime">
-                    <el-date-picker
-                      :disabled="this.getSopLook"
-                      v-model="form.ticketStartTime"
-                      type="datetime"
-                      placeholder="选择日期时间"
-                      align="right"
-                      :picker-options="pickerOptions"
-                      style="width: 100%"
-                      @change="ticketStartTimeChange"
-                    >
-                    </el-date-picker>
-                  </el-form-item>
-                  <el-form-item label="结束时间" prop="ticketEndTime">
-                    <el-date-picker
-                      :disabled="this.getSopLook"
-                      v-model="form.ticketEndTime"
-                      type="datetime"
-                      placeholder="选择日期时间"
-                      align="right"
-                      :picker-options="pickerOptions"
-                      style="width: 100%"
-                      @change="ticketEndTimeChange"
-                    >
-                    </el-date-picker>
-                  </el-form-item>
-                  <el-form-item label="上锁人" prop="locker">
-                    <el-select
-                      :disabled="this.getSopLook"
-                      v-model="form.locker"
-                      placeholder="上锁人"
-                      clearable
-                      style="width: 100%"
-                      @change="handlelockerChage"
-                    >
-                      <el-option
-                        v-for="dict in this.listLockerOption"
-                        :key="dict.value"
-                        :label="dict.label"
-                        :value="dict.value"
-                      />
-                    </el-select>
-                  </el-form-item>
-
-                  <el-form-item label="共锁人" prop="coLocker">
-                    <el-button v-no-more-click
-                               type="primary"
-                               @click="addInside"
-                               class="gsr"
-                               size="mini"
-                    >添加内部人员
-                    </el-button>
-                    <el-button v-no-more-click type="primary" @click="addOutside" size="mini"
-                    >添加外部人员
-                    </el-button>
-                  </el-form-item>
-                  <div class="text item">
-                    <el-table
-                      :data="sortedTicketUserDTOList"
-                      stripe
-                      height="400"
-                      style="width: 100%"
-                    >
-                      <el-table-column prop="userId" label="序号" width="50">
-                      </el-table-column>
-                      <el-table-column
-                        prop="userName"
-                        label="共锁人"
-                        width="120"
-                      >
-                        <template slot-scope="scope">
-                          <span style="color: #2a87ff">{{
-                              scope.row.userName
-                            }}</span>
-                        </template>
-                      </el-table-column>
-                      <el-table-column prop="userType" label="共锁人来源">
-                        <template slot-scope="scope">
-                          <span>{{
-                              scope.row.userType == '0' ? '内部' : '外部'
-                            }}</span>
-                        </template>
-                      </el-table-column>
-                      <el-table-column label="" width="80">
-                        <template slot-scope="scope">
-                          <el-button v-no-more-click
-                                     @click.native.prevent="
-                              deleteRow(scope.$index, sortedTicketUserDTOList)
-                            "
-                                     type="text"
-                                     size="small"
-                          >
-                            移除
-                          </el-button>
-                        </template>
-                      </el-table-column>
-                    </el-table>
-                  </div>
-
-                  <el-form-item label="" prop="">
-                    <el-button v-no-more-click
-                               style="float: right; height: 30px; line-height: 10px"
-                               type="primary"
-                               @click="confirm"
-                    >完 成
-                    </el-button>
-                  </el-form-item>
-                </el-form>
-              </el-tab-pane>
-            </el-tabs>
-          </div>
-        </el-card>
-      </div>
-    </div>
-    <!-- 添加或修改设备维修单对话框 -->
-    <el-dialog
-      :visible.sync="open"
-      width="450px"
-      append-to-body
-      style="margin-top: 13%"
-    >
-      <div slot="title" class="dialog-title">
-        <i></i>
-        <span class="title">{{ title }}</span>
-      </div>
-      <el-form
-        ref="dialogForm"
-        :model="dialogForm"
-        label-width="70px"
-      >
-        <el-form-item label="选择人员" prop="nickName" v-if="insideMumber">
-          <el-select
-            v-model="dialogForm.nickName"
-            placeholder="请选择人员"
-            clearable
-            style="width: 100%"
-            multiple
-            @change="changeInsideUser"
-          >
-            <el-option
-              v-for="dict in this.listCoLockerOption"
-              :key="dict.value"
-              :label="dict.label"
-              :value="dict.value"
-            />
-          </el-select>
-        </el-form-item>
-
-        <el-form-item label="人员ID" prop="username" v-if="outsideMumber">
-          <el-row>
-            <el-col :span="16">
-              <el-input
-                v-model="dialogForm.username"
-                placeholder="请输入人员ID"
-                clearable
-                style="width: 80%"
-                @change="outSideUserInput"
-              />
-            </el-col>
-            <el-col :span="4">
-              <el-button v-no-more-click type="primary" @click="insertOutSideTable">添加</el-button>
-            </el-col>
-          </el-row>
-        </el-form-item>
-        <el-row>
-          <el-table :data="OutSideUserTableData"
-                    stripe
-                    height="200"
-                    v-if="outsideMumber"
-          >
-            <el-table-column prop="userId" label="序号">
-            </el-table-column>
-            <el-table-column
-              prop="userName"
-              label="人员ID"
-
-            >
-              <template slot-scope="scope">
-                          <span style="color: #2a87ff">{{
-                              scope.row.userName
-                            }}</span>
-              </template>
-            </el-table-column>
-            <el-table-column label="操作" width="80">
-              <template slot-scope="scope">
-                <el-button v-no-more-click
-                           @click.native.prevent="
-                              deleteRow(scope.$index, OutSideUserTableData)
-                            "
-                           type="text"
-                           size="small"
-                >
-                  移除
-                </el-button>
-              </template>
-            </el-table-column>
-          </el-table>
-        </el-row>
-
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <!--  内部人员确认-->
-        <el-button v-no-more-click type="primary" @click="cancel" v-if="insideMumber">确认</el-button>
-        <!--        外部人员确认-->
-        <el-button v-no-more-click type="primary" @click="outSideDialogConfirm" v-if="outsideMumber">确认</el-button>
-        <el-button v-no-more-click @click="cancel">取 消</el-button>
-      </div>
-    </el-dialog>
-    <!--    newOperations盒子结束-->
-  </div>
-</template>
-
-
-<script>
-import SeparationPoint from '@/components/separationPoint/index.vue'
-import WorkShop from '@/components/separationPoint/workshop.vue'
-import {
-  listJobTicket,
-  getJobTicketInfo,
-  addJobTicket,
-  updateJobTicket,
-  deleteIsJobTicket,
-  getworkareaList
-} from '@/api/mes/job/job'
-import { selectIsSopById, SopUser } from '@/api/mes/sop/sopindex-booz'
-import { mapGetters, mapActions } from 'vuex'
-import { getIsSopPage } from '@/api/mes/sop/sopindex-booz'
-import { genCode } from '@/api/system/autocode/rule'
-
-export default {
-  name: 'addView',
-  dicts: ['ticket_type', 'power_type', 'point_type', 'is_user_type'],
-  components: {
-    SeparationPoint,
-    WorkShop
-  },
-  data() {
-    return {
-      //自动生成编码
-      autoGenFlag: false,
-      openStaffing: true,
-      activeName: 'first',
-      form: {
-        sopId: '',
-        pointIds: '',
-        ticketId: '',
-        ticketType: '',
-        ticketName: '',
-        ticketCode: '',
-        ticketContent: '',
-        workshopName: '', //车间名称
-        workline: '', //区域
-        spoint: [], //已选隔离点
-        locker: '', //上锁人
-        coLocker: '', //共锁人
-        ticketStartTime: '', //开始时间
-        ticketEndTime: '', //结束时间
-        workareaId: null,//作业区域id
-        ticketUserDTOList: [
-          // {
-          //   userId: '',
-          //   userName: '',
-          //   userRole: '',//作业票角色 暂时不传递 内部人还是外部人
-          //   userType: ''//用户类型 上锁人或共锁人
-          // }
-        ] //所选择的用户
-      },
-      // 用来清空form
-      initialFormState: {
-        // 初始状态对象
-        sopId: '',
-        pointIds: '',
-        ticketId: '',
-        ticketType: '',
-        ticketName: '',
-        ticketCode: '',
-        ticketContent: '',
-        workshopName: '', //车间名称
-        workline: '', //区域
-        spoint: [], //已选隔离点
-        locker: '', //上锁人
-        coLocker: '', //共锁人
-        ticketStartTime: '', //开始时间
-        ticketEndTime: '', //结束时间
-        pointDetailVOList: [],//隔离点数据
-        ticketUserDTOList: [
-          // {
-          //   userId: '',
-          //   userName: '',
-          //   userRole: '',//作业票角色 暂时不传递 内部人还是外部人
-          //   userType: ''//用户类型 上锁人或共锁人
-          // }
-        ] //所选择的用户
-      },
-
-      dialogForm: {
-        nickName: '',
-        username: ''
-      },
-      // 已选隔离点
-      tableData: [],
-      orderTableData: [],//原始数据顺序
-      pickerOptions: {
-        shortcuts: [
-          {
-            text: '今天',
-            onClick(picker) {
-              picker.$emit('pick', new Date())
-            }
-          },
-          {
-            text: '昨天',
-            onClick(picker) {
-              const date = new Date()
-              date.setTime(date.getTime() - 3600 * 1000 * 24)
-              picker.$emit('pick', date)
-            }
-          },
-          {
-            text: '一周前',
-            onClick(picker) {
-              const date = new Date()
-              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
-              picker.$emit('pick', date)
-            }
-          }
-        ]
-      },
-      // 是否显示弹出层
-      open: false,
-      // 弹出层标题
-      title: '',
-      // 弹框中显示的form表单内容
-      insideMumber: false,
-      outsideMumber: false,
-      points: null, //逆向传递拿到隔离点的数据
-      emitWorkShop: null, //车间逆向传递拿到车间相关数据
-      emitworklineId: null,//生产线逆向传递拿到数据
-      sopOptions: [], //sop下拉
-      jobProps: [], //正向传递给车间components
-      // 表单校验
-      rules: {
-        ticketName: [
-          { required: true, message: '作业票名称不能为空', trigger: 'blur' }
-        ],
-        ticketCode: [
-          { required: true, message: '作业票编码不能为空', trigger: 'blur' }
-        ]
-      },
-      newticketUserDTOList: [], //为了上锁人单独传递数据
-      prePointIdOptions: [],//前置节点的下拉选项
-      initprePointIdOptions: [],//前置节点初始化数据选项
-      prePointId: null,//回显选中的前置节点id
-      relations: [],//维护父子关系的前置节点
-      listLockerOption: null,//上锁人下拉数据
-      listCoLockerOption: null,//共锁人下拉数据
-      OutSideUserTableData: [],//添加外部人员多个表格
-      nextUserId: 0,//新增外部人员表格序号自定义
-      worklineMap: null//作业区域拿到的mapjson
-    }
-  },
-  watch: {
-    tableData: {
-      handler(newVal) {
-        // 将 pointId 提取出来并连接成一个字符串
-        if (newVal && newVal.length > 0) {
-          this.form.pointIds = this.tableData
-            .map((item) => item.pointId)
-            .join(',')
-          // console.log(this.form.pointIds, this.tableData, 'pointIds')
-        }
-      },
-      deep: true
-    },
-    'form.ticketStartTime': {
-      handler(newVal) {
-        if (newVal && newVal.length > 0) {
-          console.log(newVal, '编辑监听开始时间')
-          this.ticketStartTimeChange(newVal)
-        }
-      }
-
-    },
-    'form.ticketEndTime': {
-      handler(newVal) {
-        if (newVal && newVal.length > 0) {
-          this.ticketEndTimeChange(newVal)
-        }
-      }
-    }
-  },
-  computed: {
-    ...mapGetters('sopSelectPoints', [
-      'getPointTableData',
-      'getSelectSopPoints',
-      'getSopEdit',
-      'getTicketTitle',
-      'getSopLook',
-      'getVisibleSopSelect'
-    ]),
-    // 排序 ticketUserDTOList,将 userRole 为 0 的选项放在前面
-    sortedTicketUserDTOList() {
-      return this.form.ticketUserDTOList.sort(
-        (a, b) => Number(a.userRole) - Number(b.userRole)
-      )
-    }
-  },
-  mounted() {
-    this.getSopList()
-    this.handleOpenStaffing()
-    if (this.$route.query.ticketId !== 'null') {
-      this.getTicket()
-      this.form.ticketId = this.$route.query.ticketId
-      if (this.getSopLook) {
-        this.setTicketTitle('查看作业票')
-      } else {
-        this.setTicketTitle('编辑作业票')
-      }
-    } else {
-      this.handleAutoGenChange(true)
-      this.autoGenFlag=true
-      this.setSelectSopPoints([])
-      this.setPointTableData([])
-      this.setTicketTitle('新建作业票')
-    }
-    // console.log(this.getPointTableData, 'this.getPointTableData')
-    if (this.getPointTableData) {
-      this.tableData = this.getPointTableData.pointDetailVOList.map((item) => {
-        return {
-          pointId: item.pointId,
-          pointName: item.pointName,
-          pointType: item.pointType,
-          powerType: item.powerType
-
-        }
-      })
-    }
-  },
-
-  methods: {
-    // 编辑的时候给隔离点重新存储值
-    ...mapActions('sopSelectPoints', [
-      'setSelectSopPoints',
-      'setPointTableData',
-      'setSopEdit',
-      'setTicketTitle'
-    ]),
-    formatDateTime(date) {
-      const year = date.getFullYear().toString().padStart(2, '0')
-      const month = (date.getMonth() + 1).toString().padStart(2, '0')
-      const day = date.getDate().toString().padStart(2, '0')
-      const hours = date.getHours().toString().padStart(2, '0')
-      const minutes = date.getMinutes().toString().padStart(2, '0')
-      const seconds = date.getSeconds().toString().padStart(2, '0')
-
-      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
-    },
-    getTicket() {
-      const ticketId = this.$route.query.ticketId
-      getJobTicketInfo(ticketId).then((response) => {
-        console.log(response, '编辑拿到路由参数')
-        this.orderTableData = response.data.pointDetailVOList.map((point) => {
-          return {
-            pointName: point.pointName, // 显示的名称
-            pointId: point.pointId, // 对应的值
-            pointType: point.pointType,
-            powerType: point.powerType,
-            prePointId: point.prePointId
-          }
-        })
-
-        this.form = {
-          ...this.form,
-          workareaId: response.data.workareaId,
-          sopId: response.data.sopId,
-          ticketCode: response.data.ticketCode,
-          ticketContent: response.data.ticketContent,
-          spoint: response.data.pointDetailVOList,
-          ticketUserDTOList: response.data.jobTicketUserList
-            .filter((item) => item.userRole !== 'jtlocker')
-            .map((item) => ({
-              userName: item.userName,
-              userType: item.userType,
-              userRole: item.userRole,
-              userId: item.userId
-            })),
-
-          locker: response.data.jobTicketUserList
-            .filter((item) => item.userRole == 'jtlocker')
-            .map((item) => item.userName)[0],
-          coLocker: response.data.jobTicketUserList.map((item) => {
-            return item.userRole !== 'jtlocker' ? item.userName : null
-          }),
-          ticketStartTime: response.data.ticketStartTime,
-          ticketEndTime: response.data.ticketEndTime,
-          ticketId: response.data.ticketId,
-          ticketName: response.data.ticketName,
-          ticketStatus: response.data.ticketStatus,
-          ticketType: response.data.ticketType,
-          EditBool: true
-        }
-        this.newticketUserDTOList = response.data.jobTicketUserList
-          .filter((item) => item.userRole == 'jtlocker')
-          .map((item) => ({
-            userName: item.userName,
-            userType: item.userType,
-            userRole: item.userRole,
-            userId: item.userId
-          })),
-          this.jobProps = [this.form]
-        // this.listUserOption = response.data.jobTicketUserList
-        console.log(this.form, 'form')
-      })
-    },
-
-    getSopList() {
-      const query = {
-        current: 1,
-        size: 100000
-      }
-      getIsSopPage(query).then((res) => {
-        console.log(res, 'sop列表接口')
-        // 插入一个默认的空选项
-        // const defaultOption = {
-        //   sopId: null,
-        //   sopName: "不使用sop模板  ",
-        // };
-
-        // 将默认选项添加到结果的最前面
-        // this.sopOptions = [defaultOption, ...res.data.records];
-        this.sopOptions = [...res.data.records]
-      })
-    },
-    // sop下拉change事件 可以传递sopOptions一整个对象过去
-    handleSelectSOP(value) {
-      if (value == null) {
-        this.jobProps = []
-        console.log(this.form.sopId, this.form, 'sop下拉change事件')
-      } else {
-        this.jobProps = this.sopOptions.filter((item) => item.sopId == value)
-
-        this.form.ticketType = this.jobProps[0].sopType
-
-        this.form.ticketName = 'sop_'
-        selectIsSopById(value).then((response) => {
-          console.log(response, 'sop-父组件')
-          this.orderTableData = response.data.pointDetailVOList.map((point) => {
-            return {
-              pointName: point.pointName, // 显示的名称
-              pointId: point.pointId, // 对应的值
-              pointType: point.pointType,
-              powerType: point.powerType,
-              prePointId: point.prePointId
-            }
-          })
-          // console.log(this.orderTableData,'选中sop之后赋值的orderTableData')
-          const value = response.data.ticketUserDTOList //找到上锁人  这里一定要先筛选locker再去给表格筛选 否则表格筛选之后直接不会有上锁人数据了
-            .filter(item => item.userRole == 'jtlocker')
-            .map(item => item.userName)
-          this.form.locker = value[0],//map返回的是数字 所以这样写
-            // console.log(value,response.data.ticketUserDTOList,'form.locker')
-            this.form.ticketUserDTOList = response.data.ticketUserDTOList.filter((item) => {
-              return item.userRole !== 'jtlocker'
-            })//过滤上锁人
-          this.tableData = response.data.pointDetailVOList
-
-          this.form.workareaId = response.data.workareaId
-          this.newticketUserDTOList = response.data.ticketUserDTOList.filter((item) => {
-            return item.userRole == 'jtlocker'
-          })
-        })
-        this.setSopEdit(false)//如果是选择sop的话 就不让再选隔离点
-        console.log(this.jobProps, '父组件jobProps')
-      }
-    },
-    // 清除sop下拉框
-    handleClearSop() {
-      this.form.ticketType = ''
-      this.form.ticketName = ''
-
-    },
-    handleClick(tab, event) {
-      // console.log(tab, event);
-    },
-    previousStep(val) {
-      this.activeName = val
-    },
-    nextStep(val) {
-      console.log(val, 'nextStep')
-      if (val == 'second' && this.form.ticketName == '') {
-        this.$message.error('作业票名称不能为空')
-        return
-      } else if (val == 'second' && this.form.ticketCode == '') {
-        this.$message.error('作业票编码不能为空')
-        return
-      }
-      this.activeName = val
-      console.log('我点击了下一步')
-    },
-    // 作业票确认
-    async confirm() {
-      try {
-        // 格式化时间
-        this.form.ticketStartTime = this.formatDateTime(
-          new Date(this.form.ticketStartTime)
-        )
-        this.form.ticketEndTime = this.formatDateTime(
-          new Date(this.form.ticketEndTime)
-        )
-        // console.log(this.form, "拿到的所有参数确认");
-        const UserList = [...(this.form.ticketUserDTOList || []), ...(this.newticketUserDTOList || [])]
-        const pointsList = this.tableData.map((item) => {
-          return {
-            pointId: item.pointId,
-            prePointId: item.prePointId
-          }
-        })
-        const data = {
-          pointIds: this.form.pointIds,
-          sopId: this.form.sopId,
-          ticketCode: this.form.ticketCode,
-          ticketContent: this.form.ticketContent,
-          ticketEndTime: this.form.ticketEndTime,
-          ticketName: this.form.ticketName,
-          ticketStartTime: this.form.ticketStartTime,
-          ticketType: this.form.ticketType,
-          ticketUserDTOList: UserList,
-          workareaId: this.emitworklineId,
-          pointsList: pointsList
-        }
-        const editdata = {
-          pointIds: this.form.spoint.join(','),
-          sopId: this.form.sopId,
-          ticketCode: this.form.ticketCode,
-          ticketContent: this.form.ticketContent,
-          ticketId: this.form.ticketId,
-          ticketEndTime: this.form.ticketEndTime,
-          ticketName: this.form.ticketName,
-          ticketStartTime: this.form.ticketStartTime,
-          ticketType: this.form.ticketType,
-          ticketUserDTOList: UserList,
-          workareaId: this.emitworklineId,
-          pointsList: pointsList
-
-        }
-
-        // 检查 route.query.ticketId 是否为 null
-        console.log(this.$route.query.ticketId, 'this.$route.query.ticketId')
-        if (this.$route.query.ticketId !== 'null') {
-          // 调用编辑接口
-
-          const res = await updateJobTicket(editdata)
-          if (res.code === 200) {
-            // this.$router.go(-1);
-            this.$router.push('/job/jobm')
-
-          } else {
-            console.error('编辑工单失败', res)
-          }
-        } else {
-          console.log(data, '新增的参数')
-          // 调用新增接口
-          const res = await addJobTicket(data)
-          if (res.code === 200) {
-            // this.$router.go(-1);
-            this.$router.push('/job/jobm')
-          } else {
-            console.error('提交工单失败', res)
-          }
-        }
-      } catch (error) {
-        console.error('确认过程中发生错误', error)
-      }
-
-      console.log('确认')
-    },
-    // 选中隔离点 前置节点的change函数
-    onDropdownVisibleChange(row) {
-      console.log(row, '我执行这里拉')
-
-      // 当前节点 ID
-      const currentPointId = row.pointId
-
-      // 获取当前行的 prePointId
-      const currentPrePointId = row.prePointId
-
-      // 已经被选为前置节点的 ID 集合
-      const selectedPrePointIds = new Set(
-        this.tableData
-          .filter((item) => item.prePointId !== null)
-          .map((item) => item.prePointId)
-      )
-
-      // console.log(selectedPrePointIds, 'selectedPrePointIds')
-      // 构建 form.prePointId 数组对象
-      this.form.prePointId = this.tableData.map((item) => ({
-        pointId: item.pointId,
-        prePointId: item.prePointId || null
-      }))
-      // 每次都从原始数据开始过滤
-      let filteredOptions = [...this.initprePointIdOptions]
-
-      // 过滤规则:
-      // 1. 排除自身
-      // 2. 排除已经被选为前置节点的隔离点
-      // 3. 排除所有已经选为前置节点的节点及其前置节点
-      const allExcludedPoints = new Set([currentPointId])
-      this.getAllExcludedPoints(currentPointId, allExcludedPoints)
-
-      filteredOptions = filteredOptions.filter((option) => {
-        return !allExcludedPoints.has(option.pointId)
-      })
-
-      this.prePointIdOptions = filteredOptions
-
-      console.log('过滤后的前置节点选项', this.prePointIdOptions)
-    },
-
-    // 递归获取所有需要排除的节点
-    getAllExcludedPoints(pointId, excludedPoints) {
-      const relatedRows = this.tableData.filter(item => item.prePointId === pointId)
-      for (const row of relatedRows) {
-        excludedPoints.add(row.pointId)
-        this.getAllExcludedPoints(row.pointId, excludedPoints)
-      }
-    },
-
-    // 前置节点改变时的处理函数
-    prePointIdChange(row) {
-      console.log(row, '前置节点改变')
-
-      // 更新 tableData 中对应行的 prePointId
-      const index = this.tableData.findIndex(item => item.pointId === row.pointId)
-      if (index !== -1) {
-        this.$set(this.tableData, index, row)
-      }
-
-      // 重新调用 onDropdownVisibleChange 确保其他节点的选项更新
-      this.onDropdownVisibleChange(row)
-    },
-    // 前置节点清除操作
-    clearprePointId(row) {
-      console.log(row, '清除前置节点')
-
-      // 重置当前行的 prePointId 为 null
-      row.prePointId = null
-
-      // 更新 tableData 中对应行的 prePointId
-      const index = this.tableData.findIndex(item => item.pointId === row.pointId)
-      if (index !== -1) {
-        this.$set(this.tableData, index, row)
-      }
-
-      // 恢复下拉选项为原始未过滤状态
-      this.prePointIdOptions = [...this.initprePointIdOptions]
-
-      // 调用 onDropdownVisibleChange 以刷新其他选项
-      this.onDropdownVisibleChange(row)
-    },
-    // 定义一个排序函数,根据 orderTableData 中 pointName 的顺序对 tableData 进行排序
-    sortTableDataByOrder(tableData, orderTableData) {
-      // 构建 orderMap,使用 pointName 作为键,索引作为值
-      const orderMap = new Map(orderTableData.map((item, index) => [item.pointName, index]))
-
-      return tableData.sort((a, b) => {
-        // 如果 pointName 在 orderMap 中,按 orderMap 的索引排序
-        // 如果 pointName 不在 orderMap 中,排在最后,并按 pointName 的自然顺序排列
-        const indexA = orderMap.has(a.pointName) ? orderMap.get(a.pointName) : Infinity
-        const indexB = orderMap.has(b.pointName) ? orderMap.get(b.pointName) : Infinity
-
-        if (indexA === indexB) {
-          // 当两者都不在 orderMap 中时,按 pointName 的自然顺序排列
-          return a.pointName.localeCompare(b.pointName)
-        }
-
-        return indexA - indexB
-      })
-    },
-
-// 子组件逆向传递选中的隔离点
-    handleSelectPoint(points) {
-      console.log(points, this.orderTableData, '父组件接收逆向传递选中的隔离点')
-
-      // 1. 去除重复的点,使用 Set 确保每个 pointId 唯一
-      const uniquePoints = Array.from(
-        new Set(points.map(point => point.pointId))
-      ).map(id => points.find(point => point.pointId === id))
-
-      if (this.$route.query.ticketId == 'null'&&this.form.sopId=='') {
-        this.tableData = uniquePoints // 子组件传递过来的选中节点(去重后)
-      } else {
-        this.tableData = this.sortTableDataByOrder(uniquePoints, this.orderTableData)//去重并排序
-
-      }
-      // this.tableData = uniquePoints; // 子组件传递过来的选中节点(去重后)
-
-      // 使用 Set 来存储传递过来的点值
-      const newValues = new Set(uniquePoints.map((point) => point.pointId))
-
-      // 2. 删除取消选中的点
-      const removedPoints = this.tableData
-        .filter((item) => !newValues.has(item.pointId))
-        .map((item) => item.pointId) // 记录被删除的点
-
-      this.tableData = this.tableData.filter((item) =>
-        newValues.has(item.pointId)
-      )
-
-      // 3. 确保新增点不会重复
-      const existingValues = new Set(this.tableData.map((item) => item.pointId))
-
-      uniquePoints.forEach((point) => {
-        // 如果当前传递的点不在已有的点集中,则添加
-        if (!existingValues.has(point.pointId)) {
-          this.tableData.push({
-            pointName: point.pointName, // 显示的名称
-            pointId: point.pointId, // 对应的值
-            pointType: point.pointType,
-            powerType: point.powerType,
-            prePointId: null
-          })
-
-          this.prePointIdOptions.push({
-            pointName: point.pointName, // 显示的名称
-            pointId: point.pointId // 对应的值
-          })
-          this.initprePointIdOptions = [...this.prePointIdOptions]
-          console.log(this.prePointIdOptions, '前置节点设置下拉')
-          existingValues.add(point.pointId)
-        }
-      })
-
-      // 4. 处理被删除的点,如果这些点作为父节点绑定,则将对应的 prePointId 设置为 null
-      this.tableData.forEach((item) => {
-        if (removedPoints.includes(item.prePointId)) {
-          item.prePointId = null
-        }
-      })
-
-      // 5. 从下拉选项中移除被删除的点
-      this.prePointIdOptions = this.prePointIdOptions.filter(
-        (option) => !removedPoints.includes(option.pointId)
-      )
-      this.initprePointIdOptions = [...this.prePointIdOptions]
-
-      // 6. 确保下拉选项中仍然保留所有未被删除的点
-      const allPoints = uniquePoints.map((point) => ({
-        pointName: point.pointName,
-        pointId: point.pointId
-      }))
-
-      this.prePointIdOptions = allPoints.filter(
-        (option) => !removedPoints.includes(option.pointId)
-      )
-      this.initprePointIdOptions = [...this.prePointIdOptions]
-
-      // 更新 form.spoint 为最新选中的隔离点数组
-      this.form.spoint = uniquePoints.map((point) => point.pointId)
-    },
-    // 车间逆向传递拿到的隔离点数据产线
-    handleProductLineSelected(selectedOption) {
-      // console.log(selectedOption, "父组件接收到的 selectedOption");
-      this.points = selectedOption
-      this.form.workline = selectedOption.label
-      // console.log(this.worklineMap.length, '父组件接收到的 worklineMap')
-    },
-    // 车间子组件逆传递车间相关数据车间
-    handleWorkshopSelected(selectedOption) {
-      console.log(selectedOption, 'handleWorkshopSelected')
-      // this.emitWorkShop = selectedOption
-      // this.form.workshopName = selectedOption.label;//这里是回显车间的 暂时不需要
-      this.form.workline = selectedOption.label//这里是回显作业区域的
-      this.emitworklineId = selectedOption.id
-      this.worklineMap = selectedOption.map
-    },
-    //   时间选项
-    ticketStartTimeChange(value) {
-      this.form.ticketStartTime = value
-      // 更新 pickerOptions 中的 disabledDate 方法
-      this.updatePickerOptions()
-    },
-    ticketEndTimeChange(value) {
-      this.form.ticketEndTime = value
-      this.updatePickerOptions()
-    },
-
-    disabledDate(time) {
-      const startTime = new Date(this.form.ticketStartTime)
-      const endTime = new Date(this.form.ticketEndTime)
-
-      // 如果有结束时间且开始时间大于结束时间,则开始时间不能大于结束时间
-      if (!isNaN(endTime.getTime()) && startTime > endTime) {
-        return time.getTime() > endTime.getTime()
-      }
-
-      // 如果开始时间是当天,则结束时间可以选择今天及之后的日期
-      if (!isNaN(startTime.getTime()) && startTime.toDateString() === new Date().toDateString()) {
-        return time.getTime() < startTime.getTime()
-      }
-
-      // 如果开始时间不是当天,则结束时间不能小于开始时间
-      if (!isNaN(startTime.getTime())) {
-        return time.getTime() < startTime.getTime()
-      }
-
-      // 如果有结束时间,则开始时间不能晚于结束时间
-      if (!isNaN(endTime.getTime())) {
-        return time.getTime() > endTime.getTime()
-      }
-
-      return false
-    },
-    updatePickerOptions() {
-      this.pickerOptions.disabledDate = this.disabledDate
-    },
-
-    reset() {
-      (this.form = {
-        sopId: '',
-        pointIds: '',
-        ticketType: '',
-        ticketName: '',
-        ticketCode: '',
-        ticketContent: '',
-        workshopName: '', //车间名称
-        workline: '', //区域
-        spoint: [], //已选隔离点
-        locker: '', //上锁人
-        coLocker: '', //共锁人
-        ticketStartTime: '', //开始时间
-        ticketEndTime: '', //结束时间
-        ticketUserDTOList: [
-          // {
-          //   userId: '',
-          //   userName: '',
-          //   userRole: '',//作业票角色 暂时不传递
-          //   userType: ''//用户类型 上锁人或共锁人
-          // }
-        ]
-      }),
-        (this.autoGenFlag = false)
-    },
-
-    // 侧边x关闭函数
-    goBack() {
-      this.$router.push('/job/jobm')
-    },
-    // 添加内部人员
-    addInside() {
-      this.open = true
-      this.title = '添加内部人员'
-      this.insideMumber = true
-      this.outsideMumber = false
-      // this.form.ticketUserDTOList = [];
-      this.dialogForm.nickName = ''
-    },
-    addOutside() {
-      this.open = true
-      this.title = '添加外部人员'
-      this.OutSideUserTableData=[]
-      this.insideMumber = false
-      this.outsideMumber = true
-      this.dialogForm.username = null
-    },
-    // 取消按钮
-    cancel() {
-      this.open = false
-    },
-    // 人员列表删除
-    deleteRow(index, rows) {
-      console.log(index, rows, '删除的行')
-      const deletedItem = rows[index] // 获取要删除的项
-      rows.splice(index, 1) // 从显示的列表中删除
-      // const formIndex = this.form.ticketUserDTOList.findIndex(
-      //   (item) => item.userId === deletedItem.userId
-      // )
-      const formIndex = this.form.ticketUserDTOList.findIndex(
-        (item) => item.userName == deletedItem.userName
-      )
-      if (formIndex !== -1) {
-        this.form.ticketUserDTOList.splice(formIndex, 1) // 从 form.ticketUserDTOList 中删除
-      }
-    },
-    // 上锁人下拉选择change事件
-    handlelockerChage(val) {
-      console.log(val, '上锁人chage')
-      const user = this.listLockerOption.find((item) => item.value === val)
-
-      if (user && this.form.locker !== '') {
-        const existingUser = this.form.ticketUserDTOList.find(
-          (u) => u.userName === user.label
-        )
-        if (!existingUser) {
-          this.newticketUserDTOList.push({
-            userName: user.label,
-            userId: user.value,
-            userType: 0,
-            userRole: 'jtlocker'
-          })
-
-          console.log(this.newticketUserDTOList, '用户')
-        } else {
-          // console.log('用户已存在', user.label)
-        }
-      }
-    },
-
-    // 添加内部人员的用户新增到ticketUserDTOList这个数据里
-    changeInsideUser(values) {
-      const usersinside = values
-        .map((value) =>
-          this.listCoLockerOption.find((item) => item.value === value)
-        )
-        .filter(Boolean)
-
-      usersinside.forEach((user) => {
-        const existingUser = this.form.ticketUserDTOList.find(
-          (u) => u.userName === user.label
-        )
-        // console.log(usersinside, 'usersinside----67')
-        if (!existingUser) {
-          this.form.ticketUserDTOList.push({
-            userName: user.label,
-            userId: user.value,
-            userType: 0,
-            userRole: 'jtcolocker'
-
-          })
-          console.log(this.form.ticketUserDTOList, '用户')
-        } else {
-          // console.log('用户已存在', user.label)
-        }
-      })
-      this.updateCoLocker()
-
-      // console.log(this.form.ticketUserDTOList, '用户')
-    },
-    // 添加外部人员 输入名称 userType==1是共锁人 0是上锁人 userId==0
-    outSideUserInput(event) {
-      this.dialogForm.username = event
-    },
-    // 添加外部人员弹窗 添加给表格数据的按钮事件
-    insertOutSideTable() {
-      const newUserName = this.dialogForm.username.trim()
-      if (newUserName === '') {
-        this.$message.warning('请输入用户名')
-        return
-      }
-      // 检查新用户是否已存在于表格中
-      const existingUser = this.OutSideUserTableData.find(user => user.userName === newUserName)
-      if (existingUser) {
-        this.$message.warning('该用户已存在')
-        return
-      }
-      // 添加新用户
-      this.OutSideUserTableData.push({
-        userName: newUserName,
-        userId: this.nextUserId++
-      })
-
-      // 清空对话框表单
-      this.dialogForm.username = ''
-
-      // 打印当前的外部人员表格数据
-      console.log(this.OutSideUserTableData, 'OutSideUserTableData')
-    },
-    // 添加外部人员 确认弹窗
-    outSideDialogConfirm() {
-      this.updateCoLocker()
-      this.open = false
-    },
-    // 更新界面中共锁人下拉框显示的内容
-    updateCoLocker() {
-      // 检查并补充 ticketUserDTOList 中缺少的用户
-      this.OutSideUserTableData.forEach((item) => {
-        const existingUser = this.form.ticketUserDTOList.find(
-          (u) => u.userName === item.userName
-        )
-        if (!existingUser) {
-          this.form.ticketUserDTOList.push({
-            userName: item.userName,
-            userId: 0,
-            userType: 1,
-            userRole: 'jtcolocker'
-
-          })
-        }
-      })
-
-      console.log(this.form.ticketUserDTOList, '最终的 ticketUserDTOList')
-    },
-    //自动生成编码
-    handleAutoGenChange(autoGenFlag) {
-      if (autoGenFlag) {
-        genCode('JOB_TICKET_CODE').then((response) => {
-          this.form.ticketCode = response
-        })
-      } else {
-        this.form.ticketCode = null
-      }
-
-    },
-    //是否开启人员配置界面
-    handleOpenStaffing(openStaffing) {
-      // 定义一个函数来封装接口调用逻辑
-      const fetchUserData = (roleKey) => {
-        const data = {
-          pageNum: 1,
-          pageSize: 10000,
-          roleKey: roleKey
-        }
-        return SopUser(data).then((res) => {
-          // console.log(res, `上锁人 - ${roleKey}`);
-          return res // 返回结果以便后续处理
-        }).catch((err) => {
-          // console.error(err, `请求失败 - ${roleKey}`);
-          throw err // 抛出错误以便捕获
-        })
-      }
-
-      // 调用两次接口,分别传递不同的 roleKey
-      Promise.all([
-        fetchUserData('jtlocker'),
-        fetchUserData('jtcolocker')
-      ]).then((results) => {
-        // 处理两次调用的结果
-        const [jtlockerResult, jtcolockerResult] = results
-        console.log(jtlockerResult, jtcolockerResult, 'jtlocker 结果')
-        this.listLockerOption = jtlockerResult.rows.map((item) => {
-          return {
-            label: item.nickName,
-            value: item.userId
-          }
-        })
-        this.listCoLockerOption = jtcolockerResult.rows.map((item) => {
-          return {
-            label: item.nickName,
-            value: item.userId
-          }
-        })
-
-      }).catch((err) => {
-        console.error(err, '其中一个请求失败')
-      })
-      if (openStaffing) {
-        console.log(openStaffing, '开启人员配置')
-        this.openStaffing = openStaffing
-
-      } else {
-        console.log(openStaffing, '关闭人员配置')
-        this.openStaffing = openStaffing
-        this.activeName = 'first'
-      }
-    }
-  }
-}
-</script>
-
-
-<style scoped lang="scss">
-.newOperations {
-  width: 99%;
-  height: 100%;
-  //background: pink;
-  margin: 10px;
-  display: flex;
-
-  .left {
-    width: 75%;
-    height: 830px;
-    // background: #eee;
-    margin-right: 10px;
-  }
-
-  .right {
-    height: 100%;
-    flex: 1;
-
-    .right_top {
-      height: 550px;
-    }
-
-    .workTicket_btn {
-      position: relative;
-      left: 63%;
-      height: 30px;
-      line-height: 10px;
-    }
-
-    .gsr {
-      margin-left: 60px;
-    }
-  }
-}
-
-//右侧卡片样式开始
-.text {
-  font-size: 14px;
-}
-
-.item {
-  margin-bottom: 18px;
-
-  p {
-    font-size: 18px;
-    font-weight: bolder;
-    font-family: SourceHanSansSC-bold;
-  }
-}
-
-.clearfix:before,
-.clearfix:after {
-  display: table;
-  content: "";
-  width: 320px;
-}
-
-.clearfix:after {
-  clear: both;
-}
-
-.box-card {
-  // width: 390px;
-  width: 95%;
-  height: 850px;
-}
-
-//右侧卡片样式结束
-//隔离点多选框样式
-.selects {
-  .el-input.el-input--medium.el-input--suffix {
-    // 调整箭头符号块的宽度
-    width: 175px !important;
-  }
-
-  .el-input.el-input--medium.el-input--suffix {
-    .el-input__inner {
-      // 调整输入框的宽高
-      height: 36px !important;
-      width: 220px !important;
-    }
-
-    .el-input__suffix-inner {
-      // 调整箭头符号的位置
-      position: absolute;
-      right: -45px;
-    }
-  }
-
-  .el-select__tags {
-    // 调整输入框里面的多选不换行
-    flex-wrap: nowrap !important;
-  }
-}
-
-//隔离点多选框样式结束
-</style>
-
-<style scoped lang="scss" src="@/assets/styles/dialog-title.scss">
-</style>

+ 0 - 528
src/views/mes/job/jobm/index.vue

@@ -1,528 +0,0 @@
-  <div class="app-container">
-    <el-form
-      :model="queryParams"
-      ref="queryForm"
-      size="small"
-      :inline="true"
-      v-show="showSearch"
-      label-width="100px"
-    >
-
-      <el-form-item label="作业票名称" prop="ticketName">
-        <el-input
-          v-model="queryParams.ticketName"
-          placeholder="请输入作业票名称"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="设备/工艺" prop="machineryId">
-        <treeselect
-          style="width: 218px"
-          v-model="queryParams.machineryId"
-          :options="TechnologyOptions"
-          :normalizer="Technologynormalizer"
-          placeholder="选择设备工艺"
-        />
-      </el-form-item>
-      <el-form-item label="岗位" prop="workstationId">
-        <treeselect
-          style="width: 218px"
-          v-model="queryParams.workstationId"
-          :options="marsOptions"
-          :normalizer="normalizer"
-          placeholder="选择岗位"
-        />
-      </el-form-item>
-      <el-form-item label="状态" prop="ticketStatus">
-        <el-select v-model="queryParams.ticketStatus" placeholder="状态">
-          <el-option
-            v-for="dict in dict.type.ticket_status"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="创建时间">
-        <el-date-picker
-          style="width: 218px"
-          v-model="createTime"
-          type="daterange"
-          align="right"
-          unlink-panels
-          range-separator="至"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
-          :picker-options="pickerOptions"
-        >
-        </el-date-picker>
-      </el-form-item>
-      <el-form-item label="作业类型" prop="ticketType">
-        <el-select
-          v-model="queryParams.ticketType"
-          placeholder="请选择作业类型"
-        >
-          <el-option
-            v-for="dict in dict.type.ticket_type"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item>
-        <el-button v-no-more-click
-          type="primary"
-          icon="el-icon-search"
-          size="mini"
-          @click="handleQuery"
-          >搜索</el-button
-        >
-        <el-button v-no-more-click icon="el-icon-refresh" size="mini" @click="resetQuery"
-          >重置</el-button
-        >
-      </el-form-item>
-    </el-form>
-
-    <el-row :gutter="10" class="mb8">
-      <el-col :span="1.5">
-        <el-button v-no-more-click
-          type="primary"
-          plain
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd('hasSop')"
-          v-hasPermi="['mes:job:jobm:add']"
-          >新增sop作业票
-        </el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button v-no-more-click
-          type="primary"
-          plain
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd('noSop')"
-          v-hasPermi="['mes:job:jobm:add']"
-          >新增自定义作业票
-        </el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button v-no-more-click
-          type="danger"
-          plain
-          icon="el-icon-delete"
-          size="mini"
-          :disabled="multiple"
-          @click="handleDelete"
-          v-hasPermi="['mes:sop:sopm:batchremove']"
-          >批量删除
-        </el-button>
-      </el-col>
-      <right-toolbar
-        :showSearch.sync="showSearch"
-        @queryTable="getList"
-      ></right-toolbar>
-    </el-row>
-
-    <el-table
-      v-loading="loading"
-      :data="jobList"
-      @selection-change="handleSelectionChange"
-    >
-      <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="作业票名称" align="center" prop="ticketName" width="270"/>
-      <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="ticketStatus">
-        <template slot-scope="scope">
-          <dict-tag
-            :options="dict.type.ticket_status"
-            :value="scope.row.ticketStatus"
-          />
-        </template>
-      </el-table-column>
-      <el-table-column label="作业类型" align="center" prop="ticketType">
-        <template slot-scope="scope">
-          <dict-tag
-            :options="dict.type.ticket_type"
-            :value="scope.row.ticketType"
-          />
-        </template>
-      </el-table-column>
-      <el-table-column label="隔离点总数" align="center" prop="pointCount">
-      </el-table-column>
-      <el-table-column label="创建时间" align="center" prop="createTime">
-      </el-table-column>
-      <el-table-column
-        label="操作"
-        align="center"
-        class-name="small-padding fixed-width"
-      >
-        <template slot-scope="scope">
-          <el-button v-no-more-click
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['mes:job:jobm:edit']"
-            >编辑
-          </el-button>
-          <el-button v-no-more-click
-            size="mini"
-            type="text"
-            icon="el-icon-view"
-            @click="handleLook(scope.row)"
-            v-hasPermi="['mes:job:jobm:progress']"
-            >查看
-          </el-button>
-          <el-button v-no-more-click
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['mes:job:jobm:remove']"
-            >删除
-          </el-button>
-        </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 {
-  getJobTicketInfo,
-  listJobTicket,
-  deleteIsJobTicket,
-} from "@/api/mes/job/job";
-
-import { genCode } from "@/api/system/autocode/rule";
-import { mapActions } from "vuex";
-
-import Treeselect from "@riophae/vue-treeselect";
-import "@riophae/vue-treeselect/dist/vue-treeselect.css";
-
-import { listMarsDept } from '@/api/system/marsdept'
-import { listTechnology } from '@/api/system/machinery'
-export default {
-  name: "Team",
-  components: { Treeselect },
-  dicts: ["ticket_type", "ticket_status"],
-  data() {
-    return {
-      //自动生成编码
-      autoGenFlag: false,
-      optType: undefined,
-      // 遮罩层
-      loading: true,
-      // 选中数组
-      ids: [],
-      codes: [],
-      // 非单个禁用
-      single: true,
-      // 非多个禁用
-      multiple: true,
-      // 显示搜索条件
-      showSearch: true,
-      // 总条数
-      total: 0,
-      // 班组表格数据
-      jobList: [],
-      //mars岗位树选项
-      marsOptions: [],
-      // 弹出层标题
-      title: "",
-      // 是否显示弹出层
-      open: false,
-      // 车间数据
-      workshopList: [],
-      // 作业区域数据
-      workareaList: [],
-      // 查询参数
-      createTime: "",
-      queryParams: {
-        current: 1,
-        size: 10,
-        ticketCode: null,
-        ticketName: null,
-        ticketStatus: null,
-        workshopId: null,
-        workareaId: null,
-        ticketType: null,
-        startTime: "",
-        endTime: "",
-      },
-      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: {},
-      TechnologyOptions:[],//设备工艺查询下拉
-    //
-    };
-  },
-  created() {
-    this.getList();
-    this.getOtherList()
-  },
-
-  methods: {
-    ...mapActions("sopSelectPoints", [
-      "setSopEdit",
-      "setSopLook",
-      "setJobLook",
-      "selectSopPoints",
-      "PointTableData",
-      "PointTableData",
-      "setMapData",
-      'setVisibleSopSelect'
-    ]),
-    // 格式化日期查询数据
-    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;
-    },
-    /** 查询班组列表 */
-    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]);
-      }
-      listJobTicket(this.queryParams).then((response) => {
-        console.log(response, "response--作业票列表");
-        this.jobList = response.data.records;
-        this.total = response.data.total;
-        this.loading = false;
-      });
-
-
-    },
-    getOtherList(){
-      const data={
-        pasge:1,
-        size:-1
-      }
-      listMarsDept(data).then(response => {
-        this.marsOptions = this.handleTree(response.data.records,"workstationId","parentId")
-      })
-      listTechnology(data).then((response) => {
-        this.TechnologyOptions = this.handleTree(response.data.records,"machineryId","parentId")
-      })
-    },
-    /** 转换部门数据结构 */
-    normalizer(node) {
-      if (node.children && !node.children.length) {
-        delete node.children;
-      }
-      return {
-        id: node.workstationId,
-        label: node.workstationName,
-        children: node.children,
-      };
-    },
-    Technologynormalizer(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 = {
-        ticketCode: null,
-        ticketName: null,
-        ticketStatus: null,
-        workstationId: null,
-        workstationName: null,
-        ticketType: null,
-        pointCount: null,
-        createTime: null,
-      };
-      this.resetForm("form");
-    },
-    /** 搜索按钮操作 */
-    handleQuery() {
-      this.queryParams.current = 1;
-      this.getList();
-    },
-    /** 重置按钮操作 */
-    resetQuery() {
-      this.createTime = "";
-      (this.queryParams.startTime = ""),
-        (this.queryParams.endTime = ""),
-
-        this.resetForm("queryForm");
-      this.handleQuery();
-    },
-    // 多选框选中数据
-    handleSelectionChange(selection) {
-      this.ids = selection.map((item) => item.ticketId);
-      this.codes = selection.map((item) => item.ticketCode);
-      this.single = selection.length !== 1;
-      this.multiple = !selection.length;
-    },
-    /** 新增按钮操作 */
-    handleAdd(val) {
-      if(val=='hasSop'){
-        this.setVisibleSopSelect(true)
-      }else {
-        this.setVisibleSopSelect(false)
-      }
-      this.reset();
-      this.open = true;
-      this.selectSopPoints(null);
-      this.PointTableData(null);
-      // this.$router.push(`/mes/job/jobm/NewOperations?ticketId=null`);//黄总原来的作业票新增
-      this.$router.push({
-        name:'NewMarsJob'
-      });
-      this.title = "添加隔离点";
-      this.optType = "add";
-      this.setSopLook(false);
-      this.setMapData(null);
-    },
-    // 查看
-    handleLook(row) {
-      // 设置为true表示作业票里查看不可以点击隔离点
-      this.setSopLook(true);
-      this.$router.push(`/mes/job/jobm/lookWork?ticketId=${row.ticketId}`);
-    },
-
-    /** 修改按钮操作 */
-    handleUpdate(row) {
-      console.log(row,'作业票编辑拿到的row');
-      this.reset();
-      const teamId = row.ticketId || this.ids;
-      this.setSopLook(false);
-      // 如果编辑的是带有sop模板的 就不允许点击 新增或者删除隔离点
-
-      this.$router.push(
-        `/mes/job/jobm/NewOperationsEdit?ticketId=${row.ticketId}`
-      );
-      getJobTicketInfo(teamId).then((response) => {
-        this.form = response.data;
-        this.open = true;
-        this.title = "修改隔离点信息";
-        this.optType = "edit";
-      });
-    },
-    /** 提交按钮 */
-    submitForm() {
-      this.$refs["form"].validate((valid) => {
-        if (valid) {
-          if (this.form.teamId != null) {
-            updateTeam(this.form).then((response) => {
-              this.$modal.msgSuccess("修改成功");
-              this.open = false;
-              this.getList();
-            });
-          } else {
-            addTeam(this.form).then((response) => {
-              this.$modal.msgSuccess("新增成功");
-              this.open = false;
-              this.getList();
-            });
-          }
-        }
-      });
-    },
-    /** 删除按钮操作 */
-    handleDelete(row) {
-      const teamIds = row.ticketId || this.ids;
-      const titcketCodes = row.ticketCode || this.codes;
-      this.$modal
-        .confirm('是否确认删除作业票编号为"' + titcketCodes + '"的数据项?')
-        .then(function () {
-          return deleteIsJobTicket(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("CAL_TEAM_CODE").then((response) => {
-          this.form.teamCode = response;
-        });
-      } else {
-        this.form.teamCode = null;
-      }
-    },
-  },
-};
-</script>
-<style lang="scss" src="@/assets/styles/dialog-title.scss" scoped>
-.el-input-width {
-  width: 380px !important;
-}
-</style>

+ 0 - 1632
src/views/mes/job/jobm/lookWork.vue

@@ -1,1632 +0,0 @@
-<template>
-  <div class="newOperations">
-    <!--    newOperations盒子开始-->
-    <div class="left">
-      <!-- 左边第一个是隔离点组件 第二个是车间组件-->
-      <SeparationPoint
-        v-show="this.activeName == 'second'"
-        @selection-changed="handleSelectPoint"
-        :points="points"
-      ></SeparationPoint>
-      <keep-alive>
-        <WorkShop
-          v-show="this.activeName == 'first' || this.activeName == 'third'"
-          @product-line-selected="handleProductLineSelected"
-          @work-shop-selected="handleWorkshopSelected"
-          :jobProps="jobProps"
-        ></WorkShop>
-      </keep-alive>
-    </div>
-    <!-- 作业区域  -->
-    <div class="lefttree">
-      <el-card class="lefttree-card" v-if="this.showWorkEare == true">
-        <b class="title">作业区域</b>
-        <div class="head-container">
-          <el-input
-            v-model="workareaName"
-            placeholder="请输入作业区域"
-            clearable
-            size="small"
-            prefix-icon="el-icon-search"
-            style="margin-bottom: 20px"
-            @input="handleInputChange"
-          />
-        </div>
-        <div class="head-container">
-          <el-tree
-            :data="deptOptions"
-            :props="defaultProps"
-            :expand-on-click-node="false"
-            :filter-node-method="filterNode"
-            ref="tree"
-            node-key="id"
-            default-expand-all
-            @node-click="handleNodeClick"
-            highlight-current
-          />
-        </div>
-      </el-card>
-      <!-- 收起 -->
-      <el-tooltip
-        class="item"
-        effect="dark"
-        content="收起作业区域内容"
-        placement="top-start"
-      >
-        <el-button
-          type="primary"
-          icon="el-icon-s-fold"
-          class="btnwork"
-          v-if="this.showWorkEare == true"
-          @click="openWorkEare"
-        ></el-button>
-      </el-tooltip>
-
-      <!-- 打开 -->
-      <el-tooltip
-        class="item"
-        effect="dark"
-        content="展开作业区域内容"
-        placement="top-start"
-      >
-        <el-button
-          type="primary"
-          icon="el-icon-s-unfold"
-          class="btnwork"
-          v-if="this.showWorkEare == false"
-          @click="closeWorkEare"
-        ></el-button>
-      </el-tooltip>
-    </div>
-    <div class="right">
-      <div class="right_top">
-        <el-card class="box-card">
-          <div slot="header" class="clearfix">
-            <span style="font-size: 18px">{{ this.getTicketTitle }}</span>
-            <span
-              style="
-                padding: 1px 10px 1px 15%;
-                font-size: 22px;
-                cursor: pointer;
-              "
-              type="text"
-              @click="goBack"
-              >×</span
-            >
-          </div>
-          <div class="text item">
-            <!-- 新增作业票信息-->
-            <b class="title">基本信息</b>
-            <el-form ref="form" :model="form" label-width="90px">
-              <!--getVisibleSopSelect是vuex判断新增是自定义还是建SOP作业票 第二个是编辑的时候如果有sopId就渲染 -->
-
-              <el-form-item
-                label="选择SOP"
-                prop="sop"
-                v-if="this.getVisibleSopSelect && this.form.sopId !== null"
-              >
-                <el-select
-                  :disabled="this.getSopLook"
-                  v-model="form.sopId"
-                  placeholder="请选择sop"
-                  clearable
-                  style="width: 100%"
-                  @clear="handleClearSop"
-                  @change="handleSelectSOP"
-                >
-                  <el-option
-                    v-for="dict in this.sopOptions"
-                    :key="dict.sopId"
-                    :label="dict.sopName"
-                    :value="dict.sopId"
-                  />
-                </el-select>
-              </el-form-item>
-
-              <el-form-item label="作业票名称" prop="ticketName">
-                <el-input
-                  :disabled="this.getSopLook"
-                  v-model="form.ticketName"
-                  placeholder="请输入作业票名称"
-                  style="width: 100%"
-                />
-              </el-form-item>
-              <el-row>
-                <el-col :span="16">
-                  <el-form-item label="作业票编号" prop="ticketCode">
-                    <el-input
-                      :disabled="this.getSopLook"
-                      v-model="form.ticketCode"
-                      placeholder="请输入作业票编号"
-                      style="width: 100%"
-                    />
-                  </el-form-item>
-                </el-col>
-                <el-col :span="8">
-                  <el-form-item label-width="80">
-                    <el-switch
-                      :disabled="this.getSopLook"
-                      v-model="autoGenFlag"
-                      active-color="#13ce66"
-                      active-text="自动生成"
-                      @change="handleAutoGenChange(autoGenFlag)"
-                    >
-                    </el-switch>
-                  </el-form-item>
-                </el-col>
-              </el-row>
-
-              <el-form-item label="作业票类型" prop="ticketType">
-                <el-select
-                  :disabled="this.getSopLook"
-                  v-model="form.ticketType"
-                  placeholder="请选择作业类型"
-                  clearable
-                  style="width: 100%"
-                >
-                  <el-option
-                    v-for="dict in dict.type.ticket_type"
-                    :key="dict.value"
-                    :label="dict.label"
-                    :value="dict.value"
-                  />
-                </el-select>
-              </el-form-item>
-              <el-form-item label="作业内容" prop="ticketContent">
-                <el-input
-                  :disabled="this.getSopLook"
-                  type="textarea"
-                  v-model="form.ticketContent"
-                  :rows="2"
-                ></el-input>
-              </el-form-item>
-            </el-form>
-
-            <!-- 隔离点信息-->
-            <b class="title">隔离点信息</b>
-            <el-form ref="form" :model="form" label-width="90px">
-              <!-- <el-form-item label="作业区域" prop="workline">
-                <el-input
-                  v-model="form.workline"
-                  style="width: 100%"
-                  disabled
-                />
-              </el-form-item> -->
-              <div class="text item">
-                <el-table
-                  :data="tableData"
-                  stripe
-                  height="300"
-                  style="width: 100%; overflow: -moz-scrollbars-none"
-                  class="tabData"
-                >
-                  <el-table-column prop="pointName" label="隔离点" width="60">
-                    <template slot-scope="scope">
-                      <span style="color: #2a87ff">{{
-                        scope.row.pointName
-                      }}</span>
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    prop="pointType"
-                    label="隔离点类型"
-                    width="85"
-                  >
-                    <template slot-scope="scope">
-                      {{ scope.row.pointType }}
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    prop="powerType"
-                    label="危险能量类型"
-                    width="100"
-                  >
-                    <template slot-scope="scope">
-                      {{ scope.row.powerType }}
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    prop="prePointId"
-                    label="前置隔离点"
-
-                  >
-                    <template slot-scope="scope">
-                      <el-select
-                        size="mini"
-                        v-model="scope.row.prePointId"
-                        @change="prePointIdChange(scope.row)"
-                        @visible-change="onDropdownVisibleChange(scope.row)"
-                        disabled
-                        clearable
-                      >
-                        <el-option
-                          v-for="item in prePointIdOptions"
-                          :key="item.pointId"
-                          :label="item.pointName"
-                          :value="item.pointId"
-                        >
-                        </el-option>
-                      </el-select>
-                    </template>
-                  </el-table-column>
-                </el-table>
-              </div>
-            </el-form>
-            <!--人员选择-->
-            <b class="title">人员信息</b>
-            <el-form ref="form" :model="form" label-width="70px">
-              <el-form-item label="开始时间" prop="ticketStartTime">
-                <el-date-picker
-                  :disabled="this.getSopLook"
-                  v-model="form.ticketStartTime"
-                  type="datetime"
-                  placeholder="选择日期时间"
-                  align="right"
-                  :picker-options="pickerOptions"
-                  style="width: 100%"
-                  @change="ticketStartTimeChange"
-                >
-                </el-date-picker>
-              </el-form-item>
-              <el-form-item label="结束时间" prop="ticketEndTime">
-                <el-date-picker
-                  :disabled="this.getSopLook"
-                  v-model="form.ticketEndTime"
-                  type="datetime"
-                  placeholder="选择日期时间"
-                  align="right"
-                  :picker-options="pickerOptions"
-                  style="width: 100%"
-                  @change="ticketEndTimeChange"
-                >
-                </el-date-picker>
-              </el-form-item>
-              <el-form-item label="上锁人" prop="locker">
-                <el-select
-                  :disabled="this.getSopLook"
-                  v-model="form.locker"
-                  placeholder="上锁人"
-                  clearable
-                  style="width: 100%"
-                  @change="handlelockerChage"
-                >
-                  <el-option
-                    v-for="dict in this.listLockerOption"
-                    :key="dict.value"
-                    :label="dict.label"
-                    :value="dict.value"
-                  />
-                </el-select>
-              </el-form-item>
-
-              <el-form-item label="共锁人" prop="coLocker">
-                <el-button
-                  type="primary"
-                  @click="addInside"
-                  class="gsr"
-                  size="mini"
-                  disabled
-                  >添加内部人员
-                </el-button>
-                <el-button
-                  type="primary"
-                  @click="addOutside"
-                  size="mini"
-                  disabled
-                  >添加外部人员
-                </el-button>
-              </el-form-item>
-              <div class="text item">
-                <el-table
-                  :data="sortedTicketUserDTOList"
-                  stripe
-                  height="300"
-                  style="width: 100%; overflow: -moz-scrollbars-none"
-                  class="tabData"
-                >
-                  <el-table-column prop="userId" label="序号" width="50">
-                  </el-table-column>
-                  <el-table-column prop="userName" label="共锁人" width="110">
-                    <template slot-scope="scope">
-                      <span style="color: #2a87ff">{{
-                        scope.row.userName
-                      }}</span>
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    prop="userType"
-                    label="共锁人来源"
-                    width="100"
-                  >
-                    <template slot-scope="scope">
-                      <span>{{
-                        scope.row.userType == "0" ? "内部" : "外部"
-                      }}</span>
-                    </template>
-                  </el-table-column>
-                  <el-table-column label="" width="80">
-                    <template slot-scope="scope">
-                      <el-button
-                        @click.native.prevent="
-                          deleteRow(scope.$index, sortedTicketUserDTOList)
-                        "
-                        type="text"
-                        size="small"
-                        disabled
-                      >
-                        移除
-                      </el-button>
-                    </template>
-                  </el-table-column>
-                </el-table>
-              </div>
-            </el-form>
-          </div>
-        </el-card>
-      </div>
-    </div>
-    <!-- 添加或修改设备维修单对话框 -->
-    <el-dialog
-      :visible.sync="open"
-      width="450px"
-      append-to-body
-      style="margin-top: 13%"
-    >
-      <div slot="title" class="dialog-title">
-        <i></i>
-        <span class="title">{{ title }}</span>
-      </div>
-      <el-form ref="dialogForm" :model="dialogForm" label-width="70px">
-        <el-form-item label="选择人员" prop="nickName" v-if="insideMumber">
-          <el-select
-            v-model="dialogForm.nickName"
-            placeholder="请选择人员"
-            clearable
-            style="width: 100%"
-            multiple
-            @change="changeInsideUser"
-          >
-            <el-option
-              v-for="dict in this.listCoLockerOption"
-              :key="dict.value"
-              :label="dict.label"
-              :value="dict.value"
-            />
-          </el-select>
-        </el-form-item>
-
-        <el-form-item label="人员ID" prop="username" v-if="outsideMumber">
-          <el-row>
-            <el-col :span="16">
-              <el-input
-                v-model="dialogForm.username"
-                placeholder="请输入人员ID"
-                clearable
-                style="width: 80%"
-                @change="outSideUserInput"
-              />
-            </el-col>
-            <el-col :span="4">
-              <el-button type="primary" @click="insertOutSideTable"
-                >添加</el-button
-              >
-            </el-col>
-          </el-row>
-        </el-form-item>
-        <el-row>
-          <el-table
-            :data="OutSideUserTableData"
-            stripe
-            height="200"
-            v-if="outsideMumber"
-          >
-            <el-table-column prop="userId" label="序号"> </el-table-column>
-            <el-table-column prop="userName" label="人员ID">
-              <template slot-scope="scope">
-                <span style="color: #2a87ff">{{ scope.row.userName }}</span>
-              </template>
-            </el-table-column>
-            <el-table-column label="操作" width="80">
-              <template slot-scope="scope">
-                <el-button
-                  @click.native.prevent="
-                    deleteRow(scope.$index, OutSideUserTableData)
-                  "
-                  type="text"
-                  size="small"
-                >
-                  移除
-                </el-button>
-              </template>
-            </el-table-column>
-          </el-table>
-        </el-row>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <!--  内部人员确认-->
-        <el-button type="primary" @click="cancel" v-if="insideMumber"
-          >确认</el-button
-        >
-        <!--        外部人员确认-->
-        <el-button
-          type="primary"
-          @click="outSideDialogConfirm"
-          v-if="outsideMumber"
-          >确认</el-button
-        >
-        <el-button @click="cancel">取 消</el-button>
-      </div>
-    </el-dialog>
-    <!--    newOperations盒子结束-->
-    <!-- 加载 -->
-    <div class="loadbox" v-if="isVisible">
-      <h5>加载中</h5>
-      <i class="el-icon-loading"></i>
-    </div>
-  </div>
-</template>
-
-
-<script>
-import SeparationPoint from "@/components/separationPoint/index.vue";
-import WorkShop from "@/components/separationPoint/workshop.vue";
-import {
-  listJobTicket,
-  getJobTicketInfo,
-  addJobTicket,
-  updateJobTicket,
-  deleteIsJobTicket,
-  getworkareaList,
-} from "@/api/mes/job/job";
-import { selectIsSopById, SopUser } from "@/api/mes/sop/sopindex-booz";
-import { mapGetters, mapActions } from "vuex";
-import { getIsSopPage } from "@/api/mes/sop/sopindex-booz";
-import { genCode } from "@/api/system/autocode/rule";
-import { listWorkarea } from "@/api/mes/wa/workarea";
-import "@riophae/vue-treeselect/dist/vue-treeselect.css";
-import Treeselect from "@riophae/vue-treeselect";
-
-export default {
-  name: "addView",
-  dicts: ["ticket_type", "power_type", "point_type", "is_user_type"],
-  props: {
-    sopProps: {
-      type: Array,
-      default: () => [],
-    },
-    jobProps: {
-      type: Array,
-      default: () => [],
-    },
-  },
-  components: {
-    SeparationPoint,
-    WorkShop,
-    Treeselect,
-  },
-  data() {
-    return {
-      //自动生成编码
-      autoGenFlag: false,
-      openStaffing: true,
-      activeName: "second",
-      form: {
-        sopId: "",
-        pointIds: "",
-        ticketId: "",
-        ticketType: "",
-        ticketName: "",
-        ticketCode: "",
-        ticketContent: "",
-        workshopName: "", //车间名称
-        workline: "", //区域
-        spoint: [], //已选隔离点
-        locker: "", //上锁人
-        coLocker: "", //共锁人
-        ticketStartTime: "", //开始时间
-        ticketEndTime: "", //结束时间
-        workareaId: null, //作业区域id
-        ticketUserDTOList: [
-          // {
-          //   userId: '',
-          //   userName: '',
-          //   userRole: '',//作业票角色 暂时不传递 内部人还是外部人
-          //   userType: ''//用户类型 上锁人或共锁人
-          // }
-        ], //所选择的用户
-      },
-      // 用来清空form
-      initialFormState: {
-        // 初始状态对象
-        sopId: "",
-        pointIds: "",
-        ticketId: "",
-        ticketType: "",
-        ticketName: "",
-        ticketCode: "",
-        ticketContent: "",
-        workshopName: "", //车间名称
-        workline: "", //区域
-        spoint: [], //已选隔离点
-        locker: "", //上锁人
-        coLocker: "", //共锁人
-        ticketStartTime: "", //开始时间
-        ticketEndTime: "", //结束时间
-        pointDetailVOList: [], //隔离点数据
-        ticketUserDTOList: [
-          // {
-          //   userId: '',
-          //   userName: '',
-          //   userRole: '',//作业票角色 暂时不传递 内部人还是外部人
-          //   userType: ''//用户类型 上锁人或共锁人
-          // }
-        ], //所选择的用户
-      },
-      dialogForm: {
-        nickName: "",
-        username: "",
-      },
-      // 已选隔离点
-      tableData: [],
-      orderTableData:[],//排序
-      pickerOptions: {
-        shortcuts: [
-          {
-            text: "今天",
-            onClick(picker) {
-              picker.$emit("pick", new Date());
-            },
-          },
-          {
-            text: "昨天",
-            onClick(picker) {
-              const date = new Date();
-              date.setTime(date.getTime() - 3600 * 1000 * 24);
-              picker.$emit("pick", date);
-            },
-          },
-          {
-            text: "一周前",
-            onClick(picker) {
-              const date = new Date();
-              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
-              picker.$emit("pick", date);
-            },
-          },
-        ],
-      },
-      // 是否显示弹出层
-      open: false,
-      // 弹出层标题
-      title: "",
-      // 弹框中显示的form表单内容
-      insideMumber: false,
-      outsideMumber: false,
-      points: null, //逆向传递拿到隔离点的数据
-      emitWorkShop: null, //车间逆向传递拿到车间相关数据
-      emitworklineId: null, //生产线逆向传递拿到数据
-      sopOptions: [], //sop下拉
-      jobProps: [], //正向传递给车间components
-      // 表单校验
-      rules: {
-        teamCode: [
-          { required: true, message: "班组编号不能为空", trigger: "blur" },
-        ],
-        teamName: [
-          { required: true, message: "班组名称不能为空", trigger: "blur" },
-        ],
-        calendarType: [
-          { required: true, message: "清选择班组类型", trigger: "blur" },
-        ],
-      },
-      newticketUserDTOList: [], //为了上锁人单独传递数据
-      prePointIdOptions: [], //前置节点的下拉选项
-      initprePointIdOptions: [], //前置节点初始化数据选项
-      prePointId: null, //回显选中的前置节点id
-      relations: [], //维护父子关系的前置节点
-      listLockerOption: null, //上锁人下拉数据
-      listCoLockerOption: null, //共锁人下拉数据
-      OutSideUserTableData: [], //添加外部人员多个表格
-      nextUserId: 0, //新增外部人员表格序号自定义
-      worklineMap: null, //作业区域拿到的mapjson
-      // 部门树选项
-      deptOptions: undefined,
-      defaultProps: {
-        children: "children",
-        label: "label",
-      },
-      showWorkEare: true, //作业区域是否展示
-      isVisible: true, // 控制盒子显示状态
-    };
-  },
-  watch: {
-    tableData: {
-      handler(newVal) {
-        // 将 pointId 提取出来并连接成一个字符串
-        if (newVal && newVal.length > 0) {
-          this.form.pointIds = this.tableData
-            .map((item) => item.pointId)
-            .join(",");
-          // console.log(this.form.pointIds, this.tableData, 'pointIds')
-        }
-      },
-      deep: true,
-    },
-    "form.ticketStartTime": {
-      handler(newVal) {
-        if (newVal && newVal.length > 0) {
-          console.log(newVal, "编辑监听开始时间");
-          this.ticketStartTimeChange(newVal);
-        }
-      },
-    },
-  },
-  computed: {
-    ...mapGetters("sopSelectPoints", [
-      "getPointTableData",
-      "getSelectSopPoints",
-      "getSopEdit",
-      "getTicketTitle",
-      "getSopLook",
-      "getVisibleSopSelect",
-    ]),
-    // 排序 ticketUserDTOList,将 userRole 为 0 的选项放在前面
-    sortedTicketUserDTOList() {
-      return this.form.ticketUserDTOList.sort(
-        (a, b) => Number(a.userRole) - Number(b.userRole)
-      );
-    },
-  },
-  mounted() {
-    // // 5秒后隐藏盒子
-    setTimeout(() => {
-      this.isVisible = false;
-    }, 1000);
-
-    this.getTreeselect(); //获取作业区域下拉de
-    this.getSopList();
-    this.handleOpenStaffing();
-    if (this.$route.query.ticketId !== "null") {
-      this.getTicket();
-      this.form.ticketId = this.$route.query.ticketId;
-      if (this.getSopLook) {
-        this.setTicketTitle("查看作业票");
-      } else {
-        this.setTicketTitle("编辑作业票");
-      }
-    } else {
-      this.setSelectSopPoints([]);
-      this.setPointTableData([]);
-      this.setTicketTitle("新建作业票");
-    }
-    // console.log(this.getPointTableData, 'this.getPointTableData')
-    if (this.getPointTableData) {
-      this.tableData = this.getPointTableData.pointDetailVOList.map((item) => {
-        return {
-          pointId: item.pointId,
-          pointName: item.pointName,
-          pointType: item.pointType,
-          powerType: item.powerType,
-        };
-      });
-    }
-  },
-
-  methods: {
-    // 编辑的时候给隔离点重新存储值
-    ...mapActions("sopSelectPoints", [
-      "setSelectSopPoints",
-      "setPointTableData",
-      "setSopEdit",
-      "setTicketTitle",
-    ]),
-    // 作业区域打开关闭
-    openWorkEare() {
-      this.showWorkEare = false;
-    },
-    closeWorkEare() {
-      this.showWorkEare = true;
-    },
-    formatDateTime(date) {
-      const year = date.getFullYear().toString().padStart(2, "0");
-      const month = (date.getMonth() + 1).toString().padStart(2, "0");
-      const day = date.getDate().toString().padStart(2, "0");
-      const hours = date.getHours().toString().padStart(2, "0");
-      const minutes = date.getMinutes().toString().padStart(2, "0");
-      const seconds = date.getSeconds().toString().padStart(2, "0");
-
-      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
-    },
-    getTicket() {
-      const ticketId = this.$route.query.ticketId;
-      getJobTicketInfo(ticketId).then((response) => {
-        console.log(response, "编辑拿到路由参数");
-        this.orderTableData=response.data.pointDetailVOList.map((point)=>{
-          return{
-            pointName: point.pointName, // 显示的名称
-            pointId: point.pointId, // 对应的值
-            pointType: point.pointType,
-            powerType: point.powerType,
-            prePointId: point.prePointId
-          }
-        })
-        this.workareaName = response.data.workareaName;
-
-        this.form = {
-          ...this.form,
-          workareaId: response.data.workareaId,
-          sopId: response.data.sopId,
-          ticketCode: response.data.ticketCode,
-          ticketContent: response.data.ticketContent,
-          spoint: response.data.pointDetailVOList,
-          ticketUserDTOList: response.data.jobTicketUserList
-            .filter((item) => item.userRole !== "jtlocker")
-            .map((item) => ({
-              userName: item.userName,
-              userType: item.userType,
-              userRole: item.userRole,
-              userId: item.userId,
-            })),
-
-          locker: response.data.jobTicketUserList
-            .filter((item) => item.userRole == "jtlocker")
-            .map((item) => item.userName)[0],
-          coLocker: response.data.jobTicketUserList.map((item) => {
-            return item.userRole !== "jtlocker" ? item.userName : null;
-          }),
-          ticketStartTime: response.data.ticketStartTime,
-          ticketEndTime: response.data.ticketEndTime,
-          ticketId: response.data.ticketId,
-          ticketName: response.data.ticketName,
-          ticketStatus: response.data.ticketStatus,
-          ticketType: response.data.ticketType,
-          EditBool: true,
-        };
-        (this.newticketUserDTOList = response.data.jobTicketUserList
-          .filter((item) => item.userRole == "jtlocker")
-          .map((item) => ({
-            userName: item.userName,
-            userType: item.userType,
-            userRole: item.userRole,
-            userId: item.userId,
-          }))),
-          (this.jobProps = [this.form]);
-        // this.listUserOption = response.data.jobTicketUserList
-        console.log(this.form, "form");
-      });
-    },
-
-    getSopList() {
-      const query = {
-        current: 1,
-        size: 100000,
-      };
-      getIsSopPage(query).then((res) => {
-        console.log(res, "sop列表接口");
-        // 插入一个默认的空选项
-        const defaultOption = {
-          sopId: null,
-          sopName: "不使用sop模板  ",
-        };
-
-        // 将默认选项添加到结果的最前面
-        this.sopOptions = [defaultOption, ...res.data.records];
-      });
-    },
-    // sop下拉change事件 可以传递sopOptions一整个对象过去
-    handleSelectSOP(value) {
-      if (value == null) {
-        this.jobProps = [];
-        console.log(this.form.sopId, this.form, "sop下拉change事件");
-      } else {
-        this.jobProps = this.sopOptions.filter((item) => item.sopId == value);
-
-        this.form.ticketType = this.jobProps[0].sopType;
-
-        this.form.ticketName = "sop_";
-        selectIsSopById(value).then((response) => {
-          console.log(response, "sop-父组件");
-          const value = response.data.ticketUserDTOList //找到上锁人  这里一定要先筛选locker再去给表格筛选 否则表格筛选之后直接不会有上锁人数据了
-            .filter((item) => item.userRole == "jtlocker")
-            .map((item) => item.userName);
-          (this.form.locker = value[0]), //map返回的是数字 所以这样写
-            // console.log(value,response.data.ticketUserDTOList,'form.locker')
-            (this.form.ticketUserDTOList =
-              response.data.ticketUserDTOList.filter((item) => {
-                return item.userRole == "jtlocker";
-              })); //过滤上锁人
-          this.tableData = response.data.pointDetailVOList;
-          this.form.workareaId = response.data.workareaId;
-        });
-
-        console.log(this.jobProps, "父组件jobProps");
-      }
-    },
-    // 清除sop下拉框
-    handleClearSop() {
-      this.form.ticketType = "";
-      this.form.ticketName = "";
-    },
-    /** 查询作业区域下拉树结构 */
-    getTreeselect() {
-      const data = {
-        current: 1,
-        size: -1,
-      };
-      listWorkarea(data).then((response) => {
-        // console.log(response.data.records, '作业区域下拉树形结构');
-        // 转换为树形结构
-        this.deptOptions = this.transformToTree(response.data.records);
-        // console.log(this.deptOptions, 'deptOptions')
-        // 使用递归函数查找匹配的节点
-        console.log(this.workareaName, "name");
-        const selectedTreeNode = this.findNodeById(
-          this.deptOptions,
-          this.workareaName
-        );
-        // 调用 handleNodeClick 方法
-        if (selectedTreeNode) {
-          this.handleNodeClick(selectedTreeNode);
-        } else {
-          console.log("未找到匹配的节点");
-        }
-      });
-    },
-    // 深层次遍历
-    findNodeById(nodes, targetId) {
-      for (let i = 0; i < nodes.length; i++) {
-        const node = nodes[i];
-        if (node.id === targetId) {
-          return node;
-        }
-        if (node.children && node.children.length > 0) {
-          const foundNode = this.findNodeById(node.children, targetId);
-          if (foundNode) {
-            return foundNode;
-          }
-        }
-      }
-      return null;
-    },
-    /** 转换数据为树形结构 */
-    transformToTree(records) {
-      const recordMap = {}; // 创建一个 Map 以存储所有记录
-      const tree = []; // 最终返回的树形结构
-
-      // 初始化所有记录到 Map
-      records.forEach((record) => {
-        recordMap[record.workareaId] = {
-          id: record.workareaId,
-          label: record.workareaName,
-          map: record.map,
-          mapImg: record.mapImg,
-          children: [],
-        };
-      });
-
-      // 遍历记录并构建树
-      records.forEach((record) => {
-        const parentId = record.parentId;
-
-        if (parentId === "0") {
-          // 如果是顶层节点,直接添加到树中
-          tree.push(recordMap[record.workareaId]);
-        } else if (recordMap[parentId]) {
-          // 如果有父节点,则将当前节点加入父节点的 children 中
-          recordMap[parentId].children.push(recordMap[record.workareaId]);
-        }
-      });
-
-      return tree;
-    },
-
-    // 树节点筛选逻辑
-    filterNode(value, data) {
-      if (!value) return true; // 如果没有输入值,显示所有节点
-      return data.label.indexOf(value) !== -1; // 判断节点 label 是否包含输入值
-    },
-    // 监听输入框变化
-    handleInputChange() {
-      this.$refs.tree.filter(this.workareaName); // 调用树的 filter 方法
-    },
-    // 作业票确认
-    async confirm() {
-      try {
-        // 格式化时间
-        this.form.ticketStartTime = this.formatDateTime(
-          new Date(this.form.ticketStartTime)
-        );
-        this.form.ticketEndTime = this.formatDateTime(
-          new Date(this.form.ticketEndTime)
-        );
-        // console.log(this.form, "拿到的所有参数确认");
-        const UserList = [
-          ...(this.form.ticketUserDTOList || []),
-          ...(this.newticketUserDTOList || []),
-        ];
-        const pointsList = this.tableData.map((item) => {
-          return {
-            pointId: item.pointId,
-            prePointId: item.prePointId,
-          };
-        });
-        const data = {
-          pointIds: this.form.pointIds,
-          sopId: this.form.sopId,
-          ticketCode: this.form.ticketCode,
-          ticketContent: this.form.ticketContent,
-          ticketEndTime: this.form.ticketEndTime,
-          ticketName: this.form.ticketName,
-          ticketStartTime: this.form.ticketStartTime,
-          ticketType: this.form.ticketType,
-          ticketUserDTOList: UserList,
-          workareaId: this.emitworklineId,
-          pointsList: pointsList,
-        };
-        const editdata = {
-          pointIds: this.form.spoint.join(","),
-          sopId: this.form.sopId,
-          ticketCode: this.form.ticketCode,
-          ticketContent: this.form.ticketContent,
-          ticketId: this.form.ticketId,
-          ticketEndTime: this.form.ticketEndTime,
-          ticketName: this.form.ticketName,
-          ticketStartTime: this.form.ticketStartTime,
-          ticketType: this.form.ticketType,
-          ticketUserDTOList: UserList,
-          workareaId: this.emitworklineId,
-          pointsList: pointsList,
-        };
-
-        // 检查 route.query.ticketId 是否为 null
-        console.log(this.$route.query.ticketId, "this.$route.query.ticketId");
-        if (this.$route.query.ticketId !== "null") {
-          // 调用编辑接口
-
-          const res = await updateJobTicket(editdata);
-          if (res.code === 200) {
-            // this.$router.go(-1);
-            this.$router.push("/job/jobm");
-          } else {
-            console.error("编辑工单失败", res);
-          }
-        } else {
-          console.log(data, "新增的参数");
-          // 调用新增接口
-          const res = await addJobTicket(data);
-          if (res.code === 200) {
-            // this.$router.go(-1);
-            this.$router.push("/job/jobm");
-          } else {
-            console.error("提交工单失败", res);
-          }
-        }
-      } catch (error) {
-        console.error("确认过程中发生错误", error);
-      }
-
-      console.log("确认");
-    },
-    // 选中隔离点 前置节点的change函数
-    onDropdownVisibleChange(row) {
-      console.log(row, "我执行这里拉");
-
-      // 当前节点 ID
-      const currentPointId = row.pointId;
-
-      // 获取当前行的 prePointId
-      const currentPrePointId = row.prePointId;
-
-      // 已经被选为前置节点的 ID 集合
-      const selectedPrePointIds = new Set(
-        this.tableData
-          .filter((item) => item.prePointId !== null)
-          .map((item) => item.prePointId)
-      );
-
-      // console.log(selectedPrePointIds, 'selectedPrePointIds')
-      // 构建 form.prePointId 数组对象
-      this.form.prePointId = this.tableData.map((item) => ({
-        pointId: item.pointId,
-        prePointId: item.prePointId || null,
-      }));
-      // 每次都从原始数据开始过滤
-      let filteredOptions = [...this.initprePointIdOptions];
-
-      // 过滤规则:
-      // 1. 排除自身
-      // 2. 排除已经被选为前置节点的隔离点
-      // 3. 排除所有已经选为前置节点的节点及其前置节点
-      const allExcludedPoints = new Set([currentPointId]);
-      this.getAllExcludedPoints(currentPointId, allExcludedPoints);
-
-      filteredOptions = filteredOptions.filter((option) => {
-        return !allExcludedPoints.has(option.pointId);
-      });
-
-      this.prePointIdOptions = filteredOptions;
-
-      console.log("过滤后的前置节点选项", this.prePointIdOptions);
-    },
-
-    // 递归获取所有需要排除的节点
-    getAllExcludedPoints(pointId, excludedPoints) {
-      const relatedRows = this.tableData.filter(
-        (item) => item.prePointId === pointId
-      );
-      for (const row of relatedRows) {
-        excludedPoints.add(row.pointId);
-        this.getAllExcludedPoints(row.pointId, excludedPoints);
-      }
-    },
-
-    // 前置节点改变时的处理函数
-    prePointIdChange(row) {
-      console.log(row, "前置节点改变");
-
-      // 更新 tableData 中对应行的 prePointId
-      const index = this.tableData.findIndex(
-        (item) => item.pointId === row.pointId
-      );
-      if (index !== -1) {
-        this.$set(this.tableData, index, row);
-      }
-
-      // 重新调用 onDropdownVisibleChange 确保其他节点的选项更新
-      this.onDropdownVisibleChange(row);
-    },
-    // 定义一个排序函数,根据 orderTableData 中 pointName 的顺序对 tableData 进行排序
-    sortTableDataByOrder(tableData, orderTableData) {
-      // 构建 orderMap,使用 pointName 作为键,索引作为值
-      const orderMap = new Map(orderTableData.map((item, index) => [item.pointName, index]))
-
-      return tableData.sort((a, b) => {
-        // 如果 pointName 在 orderMap 中,按 orderMap 的索引排序
-        // 如果 pointName 不在 orderMap 中,排在最后,并按 pointName 的自然顺序排列
-        const indexA = orderMap.has(a.pointName) ? orderMap.get(a.pointName) : Infinity
-        const indexB = orderMap.has(b.pointName) ? orderMap.get(b.pointName) : Infinity
-
-        if (indexA === indexB) {
-          // 当两者都不在 orderMap 中时,按 pointName 的自然顺序排列
-          return a.pointName.localeCompare(b.pointName)
-        }
-
-        return indexA - indexB
-      })
-    },
-    // 子组件逆向传递选中的隔离点
-    handleSelectPoint(points) {
-      // console.log(points, '父组件接收逆向传递选中的隔离点');
-
-      // 1. 去除重复的点,使用 Set 确保每个 pointId 唯一
-      const uniquePoints = Array.from(
-        new Set(points.map((point) => point.pointId))
-      ).map((id) => points.find((point) => point.pointId === id));
-
-      // console.log(uniquePoints, '去重后的选中节点');
-      this.tableData = this.sortTableDataByOrder(uniquePoints, this.orderTableData);//去重并排序
-      // this.tableData = uniquePoints; // 子组件传递过来的选中节点(去重后)
-
-      // 使用 Set 来存储传递过来的点值
-      const newValues = new Set(uniquePoints.map((point) => point.pointId));
-
-      // 2. 删除取消选中的点
-      const removedPoints = this.tableData
-        .filter((item) => !newValues.has(item.pointId))
-        .map((item) => item.pointId); // 记录被删除的点
-
-      this.tableData = this.tableData.filter((item) =>
-        newValues.has(item.pointId)
-      );
-
-      // 3. 确保新增点不会重复
-      const existingValues = new Set(
-        this.tableData.map((item) => item.pointId)
-      );
-
-      uniquePoints.forEach((point) => {
-        // 如果当前传递的点不在已有的点集中,则添加
-        if (!existingValues.has(point.pointId)) {
-          this.tableData.push({
-            pointName: point.pointName, // 显示的名称
-            pointId: point.pointId, // 对应的值
-            pointType: point.pointType,
-            powerType: point.powerType,
-            prePointId: null,
-          });
-
-          this.prePointIdOptions.push({
-            pointName: point.pointName, // 显示的名称
-            pointId: point.pointId, // 对应的值
-          });
-          this.initprePointIdOptions = [...this.prePointIdOptions];
-          console.log(this.prePointIdOptions, "前置节点设置下拉");
-          existingValues.add(point.pointId);
-        }
-      });
-
-      // 4. 处理被删除的点,如果这些点作为父节点绑定,则将对应的 prePointId 设置为 null
-      this.tableData.forEach((item) => {
-        if (removedPoints.includes(item.prePointId)) {
-          item.prePointId = null;
-        }
-      });
-
-      // 5. 从下拉选项中移除被删除的点
-      this.prePointIdOptions = this.prePointIdOptions.filter(
-        (option) => !removedPoints.includes(option.pointId)
-      );
-      this.initprePointIdOptions = [...this.prePointIdOptions];
-
-      // 6. 确保下拉选项中仍然保留所有未被删除的点
-      const allPoints = uniquePoints.map((point) => ({
-        pointName: point.pointName,
-        pointId: point.pointId,
-      }));
-
-      this.prePointIdOptions = allPoints.filter(
-        (option) => !removedPoints.includes(option.pointId)
-      );
-      this.initprePointIdOptions = [...this.prePointIdOptions];
-
-      // 更新 form.spoint 为最新选中的隔离点数组
-      this.form.spoint = uniquePoints.map((point) => point.pointId);
-    },
-    // 车间逆向传递拿到的隔离点数据产线
-    handleProductLineSelected(selectedOption) {
-      // console.log(selectedOption, "父组件接收到的 selectedOption");
-      this.points = selectedOption;
-      this.form.workline = selectedOption.label;
-      // console.log(this.worklineMap.length, '父组件接收到的 worklineMap')
-    },
-    // 车间子组件逆传递车间相关数据车间
-    handleWorkshopSelected(selectedOption) {
-      console.log(selectedOption, "handleWorkshopSelected");
-      // this.emitWorkShop = selectedOption
-      // this.form.workshopName = selectedOption.label;//这里是回显车间的 暂时不需要
-      this.form.workline = selectedOption.label; //这里是回显作业区域的
-      this.emitworklineId = selectedOption.id;
-      this.worklineMap = selectedOption.map;
-    },
-    //   时间选项
-    ticketStartTimeChange(value) {
-      this.form.ticketStartTime = value;
-      // 更新 pickerOptions 中的 disabledDate 方法
-      this.updatePickerOptions();
-    },
-    ticketEndTimeChange(value) {
-      this.form.ticketEndTime = value;
-    },
-    disabledDate(time) {
-      const startTime = new Date(this.form.ticketStartTime);
-      return startTime && !isNaN(startTime.getTime())
-        ? time.getTime() < startTime.getTime()
-        : false;
-    },
-    updatePickerOptions() {
-      this.pickerOptions.disabledDate = this.disabledDate;
-    },
-
-    reset() {
-      (this.form = {
-        sopId: "",
-        pointIds: "",
-        ticketType: "",
-        ticketName: "",
-        ticketCode: "",
-        ticketContent: "",
-        workshopName: "", //车间名称
-        workline: "", //区域
-        spoint: [], //已选隔离点
-        locker: "", //上锁人
-        coLocker: "", //共锁人
-        ticketStartTime: "", //开始时间
-        ticketEndTime: "", //结束时间
-        ticketUserDTOList: [
-          // {
-          //   userId: '',
-          //   userName: '',
-          //   userRole: '',//作业票角色 暂时不传递
-          //   userType: ''//用户类型 上锁人或共锁人
-          // }
-        ],
-      }),
-        (this.autoGenFlag = false);
-    },
-
-    // 侧边x关闭函数
-    goBack() {
-      this.$router.push("/job/jobm");
-    },
-    // 添加内部人员
-    addInside() {
-      this.open = true;
-      this.title = "添加内部人员";
-      this.insideMumber = true;
-      this.outsideMumber = false;
-      // this.form.ticketUserDTOList = [];
-      this.dialogForm.nickName = "";
-    },
-    addOutside() {
-      this.open = true;
-      this.title = "添加外部人员";
-      this.insideMumber = false;
-      this.outsideMumber = true;
-      this.dialogForm.username = null;
-    },
-    // 取消按钮
-    cancel() {
-      this.open = false;
-    },
-    // 人员列表删除
-    deleteRow(index, rows) {
-      console.log(index, rows, "删除的行");
-      const deletedItem = rows[index]; // 获取要删除的项
-      rows.splice(index, 1); // 从显示的列表中删除
-      const formIndex = this.form.ticketUserDTOList.findIndex(
-        (item) => item.userId === deletedItem.userId
-      );
-      if (formIndex !== -1) {
-        this.form.ticketUserDTOList.splice(formIndex, 1); // 从 form.ticketUserDTOList 中删除
-      }
-    },
-    // 上锁人下拉选择change事件
-    handlelockerChage(val) {
-      console.log(val, "上锁人chage");
-      const user = this.listLockerOption.find((item) => item.value === val);
-
-      if (user && this.form.locker !== "") {
-        const existingUser = this.form.ticketUserDTOList.find(
-          (u) => u.userName === user.label
-        );
-        if (!existingUser) {
-          this.newticketUserDTOList.push({
-            userName: user.label,
-            userId: user.value,
-            userType: 0,
-            userRole: "jtlocker",
-          });
-
-          console.log(this.newticketUserDTOList, "用户");
-        } else {
-          // console.log('用户已存在', user.label)
-        }
-      }
-    },
-
-    // 添加内部人员的用户新增到ticketUserDTOList这个数据里
-    changeInsideUser(values) {
-      const usersinside = values
-        .map((value) =>
-          this.listCoLockerOption.find((item) => item.value === value)
-        )
-        .filter(Boolean);
-
-      usersinside.forEach((user) => {
-        const existingUser = this.form.ticketUserDTOList.find(
-          (u) => u.userName === user.label
-        );
-        // console.log(usersinside, 'usersinside----67')
-        if (!existingUser) {
-          this.form.ticketUserDTOList.push({
-            userName: user.label,
-            userId: user.value,
-            userType: 0,
-            userRole: "jtcolocker",
-          });
-          console.log(this.form.ticketUserDTOList, "用户");
-        } else {
-          // console.log('用户已存在', user.label)
-        }
-      });
-      this.updateCoLocker();
-
-      // console.log(this.form.ticketUserDTOList, '用户')
-    },
-    // 添加外部人员 输入名称 userType==1是共锁人 0是上锁人 userId==0
-    outSideUserInput(event) {
-      this.dialogForm.username = event;
-    },
-    // 添加外部人员弹窗 添加给表格数据的按钮事件
-    insertOutSideTable() {
-      const newUserName = this.dialogForm.username.trim();
-      if (newUserName === "") {
-        this.$message.warning("请输入用户名");
-        return;
-      }
-      // 检查新用户是否已存在于表格中
-      const existingUser = this.OutSideUserTableData.find(
-        (user) => user.userName === newUserName
-      );
-      if (existingUser) {
-        this.$message.warning("该用户已存在");
-        return;
-      }
-      // 添加新用户
-      this.OutSideUserTableData.push({
-        userName: newUserName,
-        userId: this.nextUserId++,
-      });
-
-      // 清空对话框表单
-      this.dialogForm.username = "";
-
-      // 打印当前的外部人员表格数据
-      console.log(this.OutSideUserTableData, "OutSideUserTableData");
-    },
-    // 添加外部人员 确认弹窗
-    outSideDialogConfirm() {
-      this.updateCoLocker();
-      this.open = false;
-    },
-    // 更新界面中共锁人下拉框显示的内容
-    updateCoLocker() {
-      // 检查并补充 ticketUserDTOList 中缺少的用户
-      this.OutSideUserTableData.forEach((item) => {
-        const existingUser = this.form.ticketUserDTOList.find(
-          (u) => u.userName === item.userName
-        );
-        if (!existingUser) {
-          this.form.ticketUserDTOList.push({
-            userName: item.userName,
-            userId: 0,
-            userType: 1,
-            userRole: "jtcolocker",
-          });
-        }
-      });
-
-      console.log(this.form.ticketUserDTOList, "最终的 ticketUserDTOList");
-    },
-    //自动生成编码
-    handleAutoGenChange(autoGenFlag) {
-      if (autoGenFlag) {
-        genCode("JOB_TICKET_CODE").then((response) => {
-          this.form.ticketCode = response;
-        });
-      } else {
-        this.form.ticketCode = null;
-      }
-    },
-    //是否开启人员配置界面
-    handleOpenStaffing(openStaffing) {
-      // 定义一个函数来封装接口调用逻辑
-      const fetchUserData = (roleKey) => {
-        const data = {
-          pageNum: 1,
-          pageSize: 10000,
-          roleKey: roleKey,
-        };
-        return SopUser(data)
-          .then((res) => {
-            // console.log(res, `上锁人 - ${roleKey}`);
-            return res; // 返回结果以便后续处理
-          })
-          .catch((err) => {
-            // console.error(err, `请求失败 - ${roleKey}`);
-            throw err; // 抛出错误以便捕获
-          });
-      };
-
-      // 调用两次接口,分别传递不同的 roleKey
-      Promise.all([fetchUserData("jtlocker"), fetchUserData("jtcolocker")])
-        .then((results) => {
-          // 处理两次调用的结果
-          const [jtlockerResult, jtcolockerResult] = results;
-          console.log(jtlockerResult, jtcolockerResult, "jtlocker 结果");
-          this.listLockerOption = jtlockerResult.rows.map((item) => {
-            return {
-              label: item.nickName,
-              value: item.userId,
-            };
-          });
-          this.listCoLockerOption = jtcolockerResult.rows.map((item) => {
-            return {
-              label: item.nickName,
-              value: item.userId,
-            };
-          });
-        })
-        .catch((err) => {
-          console.error(err, "其中一个请求失败");
-        });
-      if (openStaffing) {
-        console.log(openStaffing, "开启人员配置");
-        this.openStaffing = openStaffing;
-      } else {
-        console.log(openStaffing, "关闭人员配置");
-        this.openStaffing = openStaffing;
-        // this.activeName = "first";
-      }
-    },
-  },
-};
-</script>
-
-
-<style scoped lang="scss">
-.newOperations {
-  width: 99%;
-  height: 100%;
-  //background: pink;
-  margin: 10px;
-  display: flex;
-  position: relative;
-  .left {
-    width: 75%;
-    height: 830px;
-    // background: #eee;
-    margin-right: 10px;
-  }
-  .lefttree {
-    width: 18%;
-    height: 100%;
-    position: absolute;
-    left: 0;
-    top: 2%;
-    display: flex;
-    // background: pink;
-    .lefttree-card {
-      height: 98%;
-      .title {
-        display: block;
-        width: 30%;
-        height: 30px;
-        text-align: center;
-        margin: 0 0 5%;
-        border-bottom: 2px solid #1684fc;
-        color: rgb(22, 132, 252);
-      }
-    }
-    .item {
-      width: 30px;
-      height: 30px;
-      font-size: 20px;
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      // .btnwork {
-      //   width: 100%;
-      //   height: 100%;
-      //   display: flex; /* 使用 flex 布局 */
-      //   justify-content: center; /* 水平居中 */
-      //   align-items: center; /* 垂直居中 */
-      //   font-size: 20px;
-      //   box-sizing: border-box;
-      // }
-    }
-  }
-  .right {
-    height: 100%;
-    flex: 1;
-
-    .right_top {
-      // height: 550px;
-      height: 840px;
-      // background: pink;
-    }
-
-    .workTicket_btn {
-      position: relative;
-      left: 63%;
-      height: 30px;
-      line-height: 10px;
-    }
-
-    .gsr {
-      margin-left: 15%;
-    }
-    .box-card {
-      height: 100%;
-      overflow-y: auto;
-      .clearfix {
-        width: 100%;
-        position: absolute;
-        top: 0;
-        line-height: 25px;
-        padding: 12px 0 0;
-        box-sizing: border-box;
-        background: #fff;
-        z-index: 10;
-      }
-    }
-    .box-card::-webkit-scrollbar {
-      display: none;
-    }
-    .title {
-      display: block;
-      width: 25%;
-      height: 30px;
-      text-align: center;
-      margin: 0 0 5%;
-      border-bottom: 2px solid #1684fc;
-      color: rgb(22, 132, 252);
-    }
-  }
-}
-.newOperations::-webkit-scrollbar {
-  display: none;
-}
-
-//右侧卡片样式开始
-.text {
-  font-size: 14px;
-}
-
-.item {
-  margin-bottom: 18px;
-
-  p {
-    font-size: 18px;
-    font-weight: bolder;
-    font-family: SourceHanSansSC-bold;
-  }
-}
-
-.clearfix:before,
-.clearfix:after {
-  display: table;
-  content: "";
-  width: 320px;
-}
-
-.clearfix:after {
-  clear: both;
-}
-
-.box-card {
-  // width: 390px;
-  width: 95%;
-  height: 850px;
-}
-
-//右侧卡片样式结束
-//隔离点多选框样式
-.selects {
-  .el-input.el-input--medium.el-input--suffix {
-    // 调整箭头符号块的宽度
-    width: 175px !important;
-  }
-
-  .el-input.el-input--medium.el-input--suffix {
-    .el-input__inner {
-      // 调整输入框的宽高
-      height: 36px !important;
-      width: 220px !important;
-    }
-
-    .el-input__suffix-inner {
-      // 调整箭头符号的位置
-      position: absolute;
-      right: -45px;
-    }
-  }
-
-  .el-select__tags {
-    // 调整输入框里面的多选不换行
-    flex-wrap: nowrap !important;
-  }
-}
-.loadbox {
-  width: 100%;
-  height: 100%;
-  background: rgba($color: #fff, $alpha: 0.9);
-  position: absolute;
-  left: 0;
-  top: 0;
-  z-index: 200;
-  padding: 18% 45%;
-  box-sizing: border-box;
-  h5 {
-    font-size: 30px;
-  }
-  .el-icon-loading {
-    font-size: 50px;
-    margin-left: 12%;
-  }
-}
-//隔离点多选框样式结束
-</style>
-
-<style scoped lang="scss" src="@/assets/styles/dialog-title.scss">
-</style>

+ 1 - 1
src/views/mes/material/lockers/DetailsIndex.vue

@@ -5,7 +5,7 @@
       <el-radio-button label="second">领取记录</el-radio-button>
       <el-radio-button label="third">检查计划</el-radio-button>
       <el-radio-button label="fourth">检查记录</el-radio-button>
-      <el-radio-button label="fifth">更换记录</el-radio-button>
+      <el-radio-button label="fifth">维修/更换记录</el-radio-button>
     </el-radio-group>
     <!-- 物资清单 -->
     <div v-if="tabPosition == 'first'" class="materialsListcon">

+ 103 - 85
src/views/mes/material/lockers/index.vue

@@ -4,13 +4,27 @@
       <el-radio-button label="first">物资柜位置</el-radio-button>
       <el-radio-button label="second">物资柜列表</el-radio-button>
     </el-radio-group>
+    <!-- 优化后带样式的无数据提示盒子 -->
     <div
+      v-if="jobconfig.imageUrl==''"
       style="
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        position: relative;
-      "
+    position: absolute;
+    top: 40%;
+    left: 40%;
+    font-size: 18px;
+    color: #666;
+    text-align: center;
+  "
+    >
+      暂无数据,请到基础数据菜单进行配置
+    </div>
+    <div
+      style="
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            position: relative;
+          "
       v-show="tabPosition == 'first'"
     >
 
@@ -18,12 +32,12 @@
       <div
         ref="mapContainer"
         :style="{
-          transform: `scale(${scaleFactor})`,
-          transformOrigin: 'top left',
-          width: '1250px',
-          height: '700px',
-          position: 'relative',
-        }"
+              transform: `scale(${scaleFactor})`,
+              transformOrigin: 'top left',
+              width: '1250px',
+              height: '700px',
+              position: 'relative',
+            }"
       >
 
         <img
@@ -32,28 +46,28 @@
           alt=""
         />
 
-<!--        <img-->
-<!--          v-for="(cabinet, index) in TicketListPage"-->
-<!--          :key="cabinet.cabinetId"-->
-<!--          :style="{-->
-<!--            width: '35px',-->
-<!--            height: '35px',-->
-<!--            position: 'absolute',-->
-<!--            cursor: 'pointer',-->
-<!--            // 图标垂直居中-->
-<!--            top: `${deptXLGCenter.top - 53}px`,-->
-<!--            // 图标水平居中,动态计算偏移-->
-<!--            left: `${-->
-<!--              deptXLGCenter.left - -->
-<!--              (TicketListPage.length * 35 + (TicketListPage.length - 1) * 5) /-->
-<!--                2 +-->
-<!--              index * 40-->
-<!--            }px`,-->
-<!--          }"-->
-<!--          :src="require(`@/assets/images/${imageMap[cabinet.status]}.jpg`)"-->
-<!--          alt=""-->
-<!--          @click="handleCabinetClick(cabinet)"-->
-<!--        />-->
+        <!--        <img-->
+        <!--          v-for="(cabinet, index) in TicketListPage"-->
+        <!--          :key="cabinet.cabinetId"-->
+        <!--          :style="{-->
+        <!--            width: '35px',-->
+        <!--            height: '35px',-->
+        <!--            position: 'absolute',-->
+        <!--            cursor: 'pointer',-->
+        <!--            // 图标垂直居中-->
+        <!--            top: `${deptXLGCenter.top - 53}px`,-->
+        <!--            // 图标水平居中,动态计算偏移-->
+        <!--            left: `${-->
+        <!--              deptXLGCenter.left - -->
+        <!--              (TicketListPage.length * 35 + (TicketListPage.length - 1) * 5) /-->
+        <!--                2 +-->
+        <!--              index * 40-->
+        <!--            }px`,-->
+        <!--          }"-->
+        <!--          :src="require(`@/assets/images/${imageMap[cabinet.status]}.jpg`)"-->
+        <!--          alt=""-->
+        <!--          @click="handleCabinetClick(cabinet)"-->
+        <!--        />-->
 
         <div v-for="(item, index) in jobconfigPoint.records" :key="item.id">
           <div
@@ -68,17 +82,17 @@
             v-for="(cabinet, index) in TicketListPage[item.entityId] || []"
             :key="cabinet.cabinetId"
             :style="{
-    width: '35px',
-    height: '35px',
-    position: 'absolute',
-    cursor: 'pointer',
-    top: (item.y - 40) + 'px',  // 让图标浮在岗位的上方
-    left: (
-      item.x -
-      ((TicketListPage[item.entityId] ? TicketListPage[item.entityId].length * 35 : 0) - 53) / 2 +  // 计算总宽度并居中,减去单个图标宽度,确保居中
-      index * 40  // 处理图标间隔
-    ) + 'px'
-  }"
+        width: '35px',
+        height: '35px',
+        position: 'absolute',
+        cursor: 'pointer',
+        top: (item.y - 40) + 'px',  // 让图标浮在岗位的上方
+        left: (
+          item.x -
+          ((TicketListPage[item.entityId] ? TicketListPage[item.entityId].length * 35 : 0) - 53) / 2 +  // 计算总宽度并居中,减去单个图标宽度,确保居中
+          index * 40  // 处理图标间隔
+        ) + 'px'
+      }"
             :src="imageMap[cabinet.status]"
             alt=""
             @click="handleCabinetClick(cabinet)"
@@ -86,8 +100,9 @@
 
 
         </div>
-<!--        左侧警告部分内容-->
-        <img style="width: 40px;height: 40px;position: absolute;top:2%;right: -4%" :src="this.ExceptionTableImage" alt=""
+        <!--        左侧警告部分内容-->
+        <img style="width: 40px;height: 40px;position: absolute;top:2%;right: -4%" :src="this.ExceptionTableImage"
+             alt=""
              @click="showExTable"
         >
         <div v-if="exceptionTableVisible"
@@ -399,7 +414,8 @@ import { listMaterials } from '@/api/mes/material/information'
 import { MaterialsLoanExceptionPage } from '@/api/mes/material/exception'
 import { selectIsMapById } from '@/api/system/mapconfig'
 import { getIsMapPointPage } from '@/api/system/mappoint'
-import { getIsSystemAttributeByKey} from '@/api/system/configuration'
+import { getIsSystemAttributeByKey } from '@/api/system/configuration'
+
 export default {
   name: 'Team',
   components: {
@@ -510,9 +526,9 @@ export default {
         children: 'children',
         label: 'label'
       },
-      sysAttrValue:null,//从基础数据接口里拿到物资柜底图的mapId
-      ExceptionTableImage:'',//列表异常的图标
-      ExceptionTableImage2:'',//列表异常的图标2
+      sysAttrValue: null,//从基础数据接口里拿到物资柜底图的mapId
+      ExceptionTableImage: '',//列表异常的图标
+      ExceptionTableImage2: ''//列表异常的图标2
     }
   },
 
@@ -555,11 +571,11 @@ export default {
         this.total = response.data.total
         this.loading = false
       })
-      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';
+      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),
@@ -567,13 +583,13 @@ export default {
         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; // 异常
-        this.ExceptionTableImage=responses[3].data.sysAttrValue
-        this.ExceptionTableImage2=responses[4].data.sysAttrValue
-        console.log(this.imageMap,this.ExceptionTableImage,this.ExceptionTableImage2,'imageMap');
-      });
+        this.imageMap[0] = responses[0].data.sysAttrValue // 正常
+        this.imageMap[1] = responses[1].data.sysAttrValue // 使用中
+        this.imageMap[2] = responses[2].data.sysAttrValue // 异常
+        this.ExceptionTableImage = responses[3].data.sysAttrValue
+        this.ExceptionTableImage2 = responses[4].data.sysAttrValue
+        console.log(this.imageMap, this.ExceptionTableImage, this.ExceptionTableImage2, 'imageMap')
+      })
     },
 
     getExpection() {
@@ -692,49 +708,51 @@ export default {
       })
 
       //   获取物资柜地图与物资柜对应状态的柜子图片
-      const sysAttrKey='sys.map.cabinet'
+      const sysAttrKey = 'sys.map.cabinet'
       getIsSystemAttributeByKey(sysAttrKey).then(response => {
-        console.log(response,'获取物资柜底图')
-        this.sysAttrValue=response.data.sysAttrValue
+        console.log(response, '获取物资柜底图')
+        this.sysAttrValue = response.data.sysAttrValue
         // 这里获取全局配置地图参数里的作业票地图
         selectIsMapById(this.sysAttrValue).then((res) => {
           console.log(res, '作业票地图 图片数据')
           this.jobconfig = res.data
         })
+        const dataMap = {
+          pages: 1,
+          size: -1,
+          mapId: this.sysAttrValue
+        }
+        console.log(dataMap,'chaxuncanshu ')
+        getIsMapPointPage(dataMap).then((res) => {
+          console.log(res, '作业票地图岗位位置信息接口')
+          this.jobconfigPoint = res.data
+        })
       })
 
-      const dataMap={
-        pages: 1,
-        size: -1,
-        mapId:4
-      }
-      getIsMapPointPage(dataMap).then((res) => {
-        console.log(res, '作业票地图岗位位置信息接口')
-        this.jobconfigPoint = res.data
-      })
+
     },
     //辅助函数计算超时时间
     calculateTimeDifference(occurTime) {
-      if (!occurTime) return '未知';
+      if (!occurTime) return '未知'
 
       // 将时间字符串转换为 Date 对象
-      const occurDate = new Date(occurTime);
+      const occurDate = new Date(occurTime)
       if (isNaN(occurDate.getTime())) {
-        console.error('Invalid date format:', occurTime);
-        return '未知';
+        console.error('Invalid date format:', occurTime)
+        return '未知'
       }
 
-      const currentTime = new Date().getTime();
-      const timeDifference = (currentTime - occurDate.getTime()) / (1000 * 60); // 转换为分钟
+      const currentTime = new Date().getTime()
+      const timeDifference = (currentTime - occurDate.getTime()) / (1000 * 60) // 转换为分钟
 
       if (timeDifference < 1) {
-        return `${(timeDifference * 60).toFixed(0)}秒`;
+        return `${(timeDifference * 60).toFixed(0)}秒`
       } else if (timeDifference < 60) {
-        return `${timeDifference.toFixed(1)}分钟`;
+        return `${timeDifference.toFixed(1)}分钟`
       } else {
-        const hours = Math.floor(timeDifference / 60);
-        const minutes = (timeDifference % 60).toFixed(0);
-        return `${hours}小时${minutes}分钟`;
+        const hours = Math.floor(timeDifference / 60)
+        const minutes = (timeDifference % 60).toFixed(0)
+        return `${hours}小时${minutes}分钟`
       }
     },
 

+ 24 - 3
src/views/mes/material/replacementrecords/index.vue

@@ -26,7 +26,7 @@
       </el-form-item>
       <el-form-item label="物资类型" prop="materialsTypeId">
         <treeselect
-          style="width: 215px"
+          style="width: 210px"
           v-model="queryParams.materialsTypeId"
           :options="materialstypeOptions"
           :normalizer="materialnormalizer"
@@ -92,6 +92,16 @@
         >
         </el-date-picker>
       </el-form-item>
+      <el-form-item label="操作类型" prop="operateType">
+        <el-select v-model="queryParams.operateType" placeholder="请选择操作类型">
+          <el-option
+            v-for="dict in dict.type.material_change_type"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
       <el-form-item>
         <el-button
           v-no-more-click
@@ -192,6 +202,16 @@
           <span v-else>-</span>
         </template>
       </el-table-column>
+      <el-table-column
+        label="操作类型"
+        align="center"
+        prop="operateType"
+      >
+        <template slot-scope="scope">
+          <span v-if="scope.row.operateType==3">维修</span>
+          <span v-else>更换</span>
+        </template>
+      </el-table-column>
 <!--      <el-table-column-->
 <!--        label="操作"-->
 <!--        align="center"-->
@@ -376,7 +396,7 @@ export default {
     }
 
   },
-  dicts: ['material_status','checking_status'],
+  dicts: ['material_status','checking_status','material_change_type'],
   data() {
     return {
       //自动生成编码
@@ -415,7 +435,8 @@ export default {
         newMaterialsId:'',
         newMaterialsRfid:'',
         changeUserName:'',
-        recordId:''
+        recordId:'',
+        operateType:'',//操作类型
       },
       title:'',
       // 表单参数

+ 1 - 2
src/views/mes/md/locksettype/index.vue

@@ -155,10 +155,9 @@
             v-hasPermi="['mes:md:locksettype:add']"
             >新增
           </el-button>
-
+<!--           v-if="scope.row.parentTypeId != 0"-->
           <el-button
             v-no-more-click
-            v-if="scope.row.parentTypeId != 0"
             size="mini"
             type="text"
             icon="el-icon-delete"

+ 0 - 1
src/views/mes/md/locktype/index.vue

@@ -148,7 +148,6 @@
           </el-button>
           <el-button
             v-no-more-click
-            v-if="scope.row.parentTypeId != 0"
             size="mini"
             type="text"
             icon="el-icon-delete"

+ 9 - 1
src/views/system/mapconfig/index.vue

@@ -52,13 +52,18 @@
     </el-row>
 
     <el-table v-loading="loading" :data="List" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column type="selection" width="35" align="center" w/>
       <el-table-column label="地图编号" align="center"  prop="id" ></el-table-column>
       <el-table-column label="地图名称" align="center"  prop="name" >
         <template slot-scope="scope">
           <span>{{ scope.row.name }}</span>
         </template>
       </el-table-column>
+      <el-table-column label="地图简称" align="center"  prop="shortName" >
+        <template slot-scope="scope">
+          <span>{{ scope.row.shortName }}</span>
+        </template>
+      </el-table-column>
       <el-table-column label="地图图片" align="left" prop="imageUrl" :show-overflow-tooltip="true" >
         <template slot-scope="scope">
           <div class="img-box" v-if="scope.row.imageUrl">
@@ -137,6 +142,9 @@
         <el-form-item label="地图名称" prop="name">
           <el-input v-model="form.name" placeholder="请输入地图名称" />
         </el-form-item>
+        <el-form-item label="地图简称" prop="shortName">
+          <el-input v-model="form.shortName" placeholder="请输入地图名称" />
+        </el-form-item>
         <el-form-item label="地图图片" prop="imageUrl">
           <ImageUploadSingle
             :limit="1"

+ 24 - 0
src/views/system/mappoint/index.vue

@@ -51,6 +51,11 @@
 
     <el-table v-loading="loading" :data="List" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center"/>
+      <el-table-column label="地图点位编号" align="center" width="210px" prop="id">
+        <template slot-scope="scope">
+          <span>{{ scope.row.id }}</span>
+        </template>
+      </el-table-column>
       <el-table-column label="地图名称" align="center" width="210px" prop="mapName">
         <template slot-scope="scope">
           <span>{{ scope.row.mapName }}</span>
@@ -64,6 +69,7 @@
           />
         </template>
       </el-table-column>
+
       <el-table-column label="实体名称" align="center" width="210px" prop="entityName">
         <template slot-scope="scope">
           <span>{{ scope.row.entityName }}</span>
@@ -143,6 +149,18 @@
             </el-option>
           </el-select>
         </el-form-item>
+        <el-form-item v-if="form.mapType=='3'" label="实体" prop="entityId">
+          <el-select style="width: 280px" v-model="form.entityId" placeholder="实体">
+            <el-option v-for="item in this.spmOptions" :key="item.pointId" :label="item.pointName" :value="item.pointId">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item v-if="form.mapType=='4'" label="实体" prop="entityId">
+          <el-select style="width: 280px" v-model="form.entityId" placeholder="实体">
+            <el-option v-for="item in this.motorOptions" :key="item.motorId" :label="item.motorName" :value="item.motorId">
+            </el-option>
+          </el-select>
+        </el-form-item>
         <el-form-item label="横坐标" prop="x">
           <el-input v-model="form.x" placeholder="请输入横坐标"/>
         </el-form-item>
@@ -208,6 +226,7 @@ import '@riophae/vue-treeselect/dist/vue-treeselect.css'
 import { listMarsDept } from '@/api/system/marsdept'
 import { getIsIsolationPointPage } from '@/api/mes/spm/segregationPoint'
 import { getToken } from '@/utils/auth'
+import { getIsMotorPage } from '@/api/mes/motor'
 
 export default {
   name: 'autoCodeRule',
@@ -247,6 +266,7 @@ export default {
       deptOptions: null,
       // 隔离点下拉
       spmOptions: null,
+      motorOptions: null,
       // 用户导入参数
       upload: {
         // 是否显示弹出层(用户导入)
@@ -332,6 +352,10 @@ export default {
         console.log(response,'隔离点数据')
         this.spmOptions = response.data.records
       })
+      getIsMotorPage(data).then(response => {
+        console.log(response,'电机点位')
+        this.motorOptions=response.data.records
+      })
     },
     /** 转换mars岗位数据结构 */
     Marsnormalizer(node) {

+ 1 - 1
vue.config.js

@@ -35,7 +35,7 @@ module.exports = {
     proxy: {
       // 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) 120.27.232.27:9190(东上阿里云)
+        // http://36.133.174.236:9090  http://192.168.0.10:9190 http://192.168.31.110:9090(动感光波) 192.168.28.97:9090(车总GRKJ) 120.27.232.27:9190(东上阿里云)
         target: `http://192.168.0.10:9190`,
         changeOrigin: true,
         pathRewrite: {

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff