Эх сурвалжийг харах

2025/5/15代码提交修复锁柜详情的列表视图渲染备注和可视化视图的点击弹窗事件

pm 5 сар өмнө
parent
commit
a2a86cc7c8

+ 54 - 35
src/views/mes/hw/lockCabinet/MapData.vue

@@ -1,6 +1,17 @@
 <template>
   <div>
     <div ref="container" style="width: 900px; height: 400px;"></div>
+    <el-dialog
+      title="异常信息"
+      :visible.sync="dialogVisible"
+      width="400px"
+    >
+      <h4 style="text-align: center;font-weight: bolder">{{ errorInfo }}</h4>
+      <div slot="footer" class="dialog-footer">
+        <el-button v-no-more-click @click="cancel">关 闭</el-button>
+      </div>
+    </el-dialog>
+
   </div>
 </template>
 
@@ -15,7 +26,10 @@ export default {
       stage: null,
       layer: null,
       cachedResults: {},
-      slotData: []
+      cachedImages: {}, // 缓存已加载的图片节点
+      slotData: [],
+      dialogVisible: false,
+      errorInfo: ''
     }
   },
   mounted() {
@@ -23,6 +37,9 @@ export default {
     this.getData()
   },
   methods: {
+    cancel() {
+      this.dialogVisible = false
+    },
     async getData() {
       const data = {
         current: 1,
@@ -48,12 +65,16 @@ export default {
           return map
         }, {})
 
+        await this.preloadImages()
         this.renderSlots()
       } catch (err) {
         console.error('获取数据失败:', err)
       }
     },
-
+    showErrorDialog(slot) {
+      this.errorInfo = slot.remark || '未知异常'
+      this.dialogVisible = true
+    },
     initKonva() {
       this.stage = new Konva.Stage({
         container: this.$refs.container,
@@ -63,45 +84,41 @@ export default {
       this.layer = new Konva.Layer()
       this.stage.add(this.layer)
     },
-
+    async preloadImages() {
+      const urls = Object.values(this.cachedResults)
+      const promises = urls.map(url => this.loadImageOnce(url))
+      await Promise.all(promises)
+    },
     async renderSlots() {
       this.layer.destroyChildren()
 
-      // 分组
       const keySlots = this.slotData.filter(item => item.slotType === '0')
       const lockSlots = this.slotData.filter(item => item.slotType === '1')
 
-      // 先渲染钥匙类
       await this.renderSlotRow(keySlots, 50)
-
-      // 再渲染挂锁类
       await this.renderSlotRow(lockSlots, 170)
 
       this.layer.draw()
     },
     async renderSlotRow(slots, boxTopY) {
-      const padding = 20 // 图片与边框的内边距
+      const padding = 20
       const boxWidth = 700
-      const boxHeight = 120 // 黑框高度
-
+      const boxHeight = 120
       const centerX = this.stage.width() / 2
       const boxStartX = centerX - boxWidth / 2
 
-      // 绘制黑色边框容器
       const box = new Konva.Rect({
         x: boxStartX,
         y: boxTopY,
         width: boxWidth,
         height: boxHeight,
         stroke: 'black',
-        strokeWidth: 2,
-        cornerRadius: 0
+        strokeWidth: 2
       })
       this.layer.add(box)
 
       const loadedImages = []
 
-      // 预加载图像(不渲染)
       for (const slot of slots) {
         const { slotType, isOccupied } = slot
         let baseKey = ''
@@ -112,10 +129,9 @@ export default {
         }
 
         const baseUrl = this.cachedResults[baseKey]
-        if (!baseUrl) continue
-
-        const imageNode = await this.loadImage(baseUrl)
+        if (!baseUrl || !this.cachedImages[baseUrl]) continue
 
+        const imageNode = this.cachedImages[baseUrl].clone()
         const width = slotType === '0' ? 110 : 40
         const height = 90
         imageNode.setAttrs({ width, height })
@@ -123,10 +139,10 @@ export default {
         loadedImages.push({ imageNode, slot, width, height })
       }
 
-      // 平均分布计算(在 box 内部)
       const totalSlots = loadedImages.length
-      const spacing = (boxWidth - 2 * padding - totalSlots * loadedImages[0].width) / (totalSlots - 1)
-
+      const spacing = totalSlots > 1
+        ? (boxWidth - 2 * padding - totalSlots * loadedImages[0].width) / (totalSlots - 1)
+        : 0
       let currentX = boxStartX + padding
 
       for (const { imageNode, slot, width, height } of loadedImages) {
@@ -136,44 +152,47 @@ export default {
         })
         this.layer.add(imageNode)
 
-        // 如果异常,添加异常图标
         if (slot.status === '1') {
-          const exceptionUrl = this.cachedResults['icon.locker.exception']
-          if (exceptionUrl) {
-            const exceptionImage = await this.loadImage(exceptionUrl)
+          const exUrl = this.cachedResults['icon.locker.exception']
+          if (exUrl && this.cachedImages[exUrl]) {
+            const exImage = this.cachedImages[exUrl].clone()
             const exWidth = 30
             const exHeight = 30
-            exceptionImage.setAttrs({
+            exImage.setAttrs({
               x: currentX + (width - exWidth) / 2,
               y: boxTopY + (boxHeight - exHeight) / 2,
               width: exWidth,
               height: exHeight
             })
-            this.layer.add(exceptionImage)
+            exImage.on('click', () => {
+              this.showErrorDialog(slot)
+            })
+            this.layer.add(exImage)
           }
         }
 
         currentX += width + spacing
       }
     },
+    loadImageOnce(url) {
+      if (this.cachedImages[url]) return Promise.resolve(this.cachedImages[url])
 
-
-
-    loadImage(url) {
       return new Promise((resolve, reject) => {
-        const image = new window.Image()
-        image.crossOrigin = 'Anonymous'
-        image.src = url
-        image.onload = () => {
-          const konvaImage = new Konva.Image({ image })
+        const img = new window.Image()
+        img.crossOrigin = 'Anonymous'
+        img.src = url
+        img.onload = () => {
+          const konvaImage = new Konva.Image({ image: img })
+          this.cachedImages[url] = konvaImage
           resolve(konvaImage)
         }
-        image.onerror = reject
+        img.onerror = reject
       })
     }
   }
 }
 </script>
 
+
 <style scoped lang="scss">
 </style>

+ 29 - 28
src/views/mes/hw/lockCabinet/lookList.vue

@@ -143,6 +143,9 @@
           ></el-switch>
           <span v-else>-</span>
         </template>
+      </el-table-column>
+      <el-table-column label="备注" align="center" prop="remark">
+
       </el-table-column>
       <el-table-column label="创建时间" align="center" prop="createTime"></el-table-column>
 
@@ -185,7 +188,7 @@
     />
     <!-- 添加或修改设备维修单对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+      <el-form ref="form" :model="form" :rules="rules" label-width="140px">
         <el-form-item label="锁柜序号" prop="cabinetId" style="width: 380px">
           <el-select v-model="form.cabinetId">
             <el-option v-for="dict in this.LockCabinetList" :value="dict.value" :label="dict.label"></el-option>
@@ -219,14 +222,14 @@
             <el-option v-for="dict in dict.type.slot_type" :value="dict.value" :label="dict.label"></el-option>
           </el-select>
         </el-form-item>
-        <el-form-item label="行" prop="row" style="width: 340px">
+        <el-form-item label="行" prop="row" style="width: 360px">
           <el-input
             v-model="form.row"
             placeholder="请输入行"
 
           />
         </el-form-item>
-        <el-form-item label="列" prop="col" style="width: 340px">
+        <el-form-item label="列" prop="col" style="width: 360px">
           <el-input
             v-model="form.col"
             placeholder="请输入列"
@@ -242,22 +245,22 @@
             </el-radio>
           </el-radio-group>
         </el-form-item>
-<!--        <el-form-item label="占用仓位的硬件" prop="hardwareId" style="width: 380px" v-if="form.isOccupied=='1'">-->
-<!--          <el-select-->
-<!--            v-model="form.hardwareId"-->
-<!--            placeholder="请选择硬件ID"-->
-<!--            clearable-->
-<!--            style="width: 100%"-->
-<!--            @change="handleSelectHardware"-->
-<!--          >-->
-<!--            <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="占用仓位的硬件Id" prop="hardwareId" style="width: 360px" v-if="form.isOccupied=='1'">
+          <el-select
+            v-model="form.hardwareId"
+            placeholder="请选择硬件ID"
+            clearable
+            style="width: 100%"
+            @change="handleSelectHardware"
+          >
+            <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="status">
           <el-radio-group v-model="form.status">
             <el-radio
@@ -269,7 +272,7 @@
           </el-radio-group>
         </el-form-item>
 
-        <el-form-item label="备注" prop="remark" style="width: 340px">
+        <el-form-item label="备注" prop="remark" style="width: 360px">
           <el-input v-model="form.remark" placeholder="请输入备注"/>
         </el-form-item>
       </el-form>
@@ -351,18 +354,16 @@ export default {
       form: {},
       // 表单校验
       rules: {
-        cabinetCode: [
+        slotCode: [
           {required: true, message: "锁柜编码不能为空", trigger: "blur"},
         ],
-        cabinetName: [
+        slotType: [
           {required: true, message: "锁柜名称不能为空", trigger: "blur"},
         ],
-        hardwareId: [
-          {required: true, message: "硬件ID不能为空", trigger: "blur"},
-        ],
-        workstationId: [
-          {required: true, message: "岗位序号不能为空", trigger: "blur"},
-        ]
+        // hardwareId: [
+        //   {required: true, message: "硬件ID不能为空", trigger: "blur"},
+        // ],
+
       },
       // 新增状态
       EditId: 0, //修改判断