<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>

<script>
import Konva from 'konva'
import { getIsSystemAttributeByKey } from '@/api/system/configuration'
import { getIsLockCabinetSlotsPage } from '@/api/mes/lockCabinet/slots'

export default {
  data() {
    return {
      stage: null,
      layer: null,
      cachedResults: {},
      cachedImages: {}, // 缓存已加载的图片节点
      slotData: [],
      dialogVisible: false,
      errorInfo: ''
    }
  },
  mounted() {
    this.initKonva()
    this.getData()
  },
  methods: {
    cancel() {
      this.dialogVisible = false
    },
    async getData() {
      const data = {
        current: 1,
        size: -1,
        cabinetId: this.$route.query.cabinetId
      }

      try {
        const res = await getIsLockCabinetSlotsPage(data)
        this.slotData = res.data?.records || []

        const icons = [
          'icon.locker.normal',
          'icon.locker.out',
          'icon.padlock.normal',
          'icon.padlock.out',
          'icon.locker.exception'
        ]

        const results = await Promise.all(icons.map(key => getIsSystemAttributeByKey(key)))
        this.cachedResults = icons.reduce((map, key, idx) => {
          map[key] = results[idx].data?.sysAttrValue || ''
          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,
        width: 1800,
        height: 400
      })
      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 boxWidth = 700
      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
      })
      this.layer.add(box)

      const loadedImages = []

      for (const slot of slots) {
        const { slotType, isOccupied } = slot
        let baseKey = ''
        if (slotType === '0') {
          baseKey = isOccupied === '1' ? 'icon.locker.normal' : 'icon.locker.out'
        } else {
          baseKey = isOccupied === '1' ? 'icon.padlock.normal' : 'icon.padlock.out'
        }

        const baseUrl = this.cachedResults[baseKey]
        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 })

        loadedImages.push({ imageNode, slot, width, height })
      }

      const totalSlots = loadedImages.length
      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) {
        imageNode.setAttrs({
          x: currentX,
          y: boxTopY + (boxHeight - height) / 2
        })
        this.layer.add(imageNode)

        if (slot.status === '1') {
          const exUrl = this.cachedResults['icon.locker.exception']
          if (exUrl && this.cachedImages[exUrl]) {
            const exImage = this.cachedImages[exUrl].clone()
            const exWidth = 30
            const exHeight = 30
            exImage.setAttrs({
              x: currentX + (width - exWidth) / 2,
              y: boxTopY + (boxHeight - exHeight) / 2,
              width: exWidth,
              height: exHeight
            })
            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])

      return new Promise((resolve, reject) => {
        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)
        }
        img.onerror = reject
      })
    }
  }
}
</script>


<style scoped lang="scss">
</style>
