src/views/WorkshopSignage.vue
@@ -1,210 +1,451 @@
<template>
  <dv-full-screen-container class="full-screen-container">
    <header class="page-header">
      {{getWorkshopName}}
      <div class="header-right">
        <a-button type="primary" icon="save" size="large" @click="saveDevicePositionAndSizeByApi"
                  v-has="'home:saveDevicePositionAndSize'">保存位置
        </a-button>
      </div>
    </header>
    <div>
      <!--页头区域-->
      <header class="page-header" :style="{height: pageHeaderHeight+'px'}">
        <a-row style="height: 100%">
          <a-col :span="7" class="header-left">
            <a-space>
              <span v-if="!isSwitchChecked">开启功能</span>
              <span v-else>关闭功能</span>
              <a-switch
                checked-children="开"
                un-checked-children="关"
                @change="handleSwitchChange"
                v-model="isSwitchChecked"
                :disabled="isSwitchChecked"
              />
              <a-button type="primary" icon="save" size="large" @click="saveDevicePositionAndSizeByApi">保存位置</a-button>
            </a-space>
          </a-col>
    <dv-border-box-8 class="content-container">
      <VueDragResize v-for="(item,index) in deviceList" :key="item.equipmentId" :w="item.vw"
                     :h="item.vh" :x="item.left" :y="item.top"
                     v-on:resizing="resize($event,index)"
                     v-on:dragging="resize($event,index)"
                     :parentLimitation="true"
                     :minw="100"
                     :minh="100"
                     :id="item.equipmentId"
                     :stickSize="6"
      >
        <div class="single-device"
             :style="{width:  item.vw+ 'px',height:item.vh+'px'}">
          <div class="device-status">
            <div v-if="item.status==0"
                 :style="{backgroundImage:`url(${require('@/assets/yellow.png')})`}" class="status-image"></div>
            <div v-if="item.status==1" :style="{backgroundImage:`url(${require('@/assets/red.png')})`}"
                 class="status-image"></div>
            <div v-if="item.status==2" :style="{backgroundImage:`url(${require('@/assets/gray.png')})`}"
                 class="status-image"></div>
            <div v-if="item.status==3" :style="{backgroundImage:`url(${require('@/assets/green.png')})`}"
                 class="status-image"></div>
            <div
              :style="{backgroundImage:`url(${item.equipmentImageUrl})`}" class="device-image"></div>
          <a-col :span="10" class="workshop-name">{{ workshopDetails.workshopName }}</a-col>
          <a-col :span="7" class="device-status-info">
            <!--<a-space v-for="item in deviceStatusList" :key="item.value" class="single-status-info"-->
            <!--@click="handleScreenDevive(item)">-->
            <!--<div :style="{color:item.checked?'#1890FF':'#fff'}">{{ item.label }}</div>-->
            <!--<div class="status-square" :style="{ backgroundColor: item.color }"></div>-->
            <!--&lt;!&ndash;<a-checkbox :checked="item.checked" @change="checkboxChange(item)"></a-checkbox>&ndash;&gt;-->
            <!--<div>{{getDeviceNumberByStatus(item.value) }}</div>-->
            <!--</a-space>-->
            <a-space v-for="item in deviceStatusList" :key="item.value" class="single-status-info">
              <div :style="{color:item.checked?'#1890FF':'#fff'}">{{ item.label }}</div>
              <div class="status-square" :style="{ backgroundColor: item.color }"></div>
              <!--<a-checkbox :checked="item.checked" @change="checkboxChange(item)"></a-checkbox>-->
              <div>{{getDeviceNumberByStatus(item.value) }}</div>
            </a-space>
          </a-col>
        </a-row>
      </header>
      <!--拖拽设备区域-->
      <div class="content-container" ref="deviceContainerRef" style="overflow: auto">
        <img :src="imgSrc" width="1920" height="900">
        <div class="guideline guidelineX" :style="{top:guidelineXTop+'px',display:showGuideline}"></div>
        <div class="guideline guidelineY" :style="{left:guidelineYLeft+'px',display:showGuideline}"></div>
        <VueDragResize
          v-for="(item, index) in deviceList"
          :key="item.equipmentId"
          :w="item.vw"
          :h="item.vh"
          :x="item.coordinateLeft"
          :y="item.coordinateTop"
          v-on:resizing="resize($event, index)"
          v-on:dragging="resize($event, index)"
          :parentLimitation="parentLimitation"
          :parentH="parentH"
          :parentW="parentW"
          :minw="70"
          :minh="70"
          :isDraggable="isDraggable"
          :isResizable="isResizable"
          :stickSize="6"
          @deactivated="showGuideline = 'none'"
        >
          <div class="single-device" :style="{ width: item.vw + 'px', height: item.vh + 'px' }"
               @click="openDetail(item)">
            <div class="device-status">
              <div
                v-if="item.equipmentStatus == 2 || item.equipmentStatus == 1"
                :style="{ backgroundImage: `url(${require('@/assets/yellow.png')})` }"
                class="status-image"
              ></div>
              <div
                v-if="item.equipmentStatus == 22"
                :style="{ backgroundImage: `url(${require('@/assets/red.png')})` }"
                class="status-image"
              ></div>
              <div
                v-if="item.equipmentStatus == 0"
                :style="{ backgroundImage: `url(${require('@/assets/gray.png')})` }"
                class="status-image"
              ></div>
              <div
                v-if="item.equipmentStatus == 3"
                :style="{ backgroundImage: `url(${require('@/assets/green.png')})` }"
                class="status-image"
              ></div>
              <div
                :style="{ backgroundImage: `url(${getImgView(item.equipmentImage) || require('@/assets/8.png')})` }"
                class="device-image"
              ></div>
            </div>
            <div class="device-id" id="deviceId"
                 :style="{ color:workshopDetails.equipmentIdColor }">
              {{ item.equipmentId }}
            </div>
          </div>
          <div class="device-id" :style="{fontSize: item.fontSize+'px'}">
            {{item.equipmentId}}
          </div>
        </div>
      </VueDragResize>
      <div class="device-status-info">
        <div v-for="item in deviceStatusList" :key="item.value" class="single-status-info">
          <div>{{item.label}}</div>
          <div class="status-square" :style="{backgroundColor:item.color}"></div>
          <div>{{getDeviceNumberByStatus(item.value)}}</div>
        </div>
        </VueDragResize>
      </div>
    </dv-border-box-8>
      <EquipmentDetailModal ref="EquipmentDetailModal"></EquipmentDetailModal>
    </div>
  </dv-full-screen-container>
</template>
<script>
  import VueDragResize from 'vue-drag-resize'
  import api from '@/api/mdc'
  import { getFileAccessHttpUrl } from '@/api/manage'
  import EquipmentDetailModal from './mdc/base/modules/WorkshopSignage/EquipmentDetailModal'
  import { message } from 'ant-design-vue'
  message.config({
    maxCount: 3
  })
  export default {
    components: {
      VueDragResize
      VueDragResize,
      EquipmentDetailModal
    },
    data() {
      return {
        // 设备信息列表
        pageHeaderHeight: 80,// 页头高度
        workshopDetails: {}, //  车间详细信息,
        isDraggable: false, // 是否开启拖拽
        isResizable: false, // 是否开启缩放
        isSwitchChecked: false, // 是否开启功能
        timingAcquisition: null, // 定时刷新是否开启
        parentH: 5000,//父级高度
        parentW: 1920,//父级宽度
        showGuideline: 'none',
        guidelineXTop: 0,
        guidelineYLeft: 0,
        deviceList: [
          {
            equipmentId: '123213213123232',// 设备ID
            equipmentImageUrl: require('@/assets/8.png'), // 设备图片
            top: 200, // 拖拽元素距盒子顶距离
            left: 100, // 拖拽元素距盒子左侧距离
            vw: 100,  // 缩放元素宽度
            vh: 100, // 缩放元素高度
            fontSize: 12, // 缩放元素字体大小
            status: 1 // 设备状态 0:待机 1:报警 2:关机 3:运行
          },
          {
            equipmentId: '512346789561232',
            equipmentImageUrl: require('@/assets/8.png'),
            top: 500,
            left: 753,
            vw: 100,
            vh: 100,
            fontSize: 12,
            status: 0
          },
          {
            equipmentId: '64746965647653',
            equipmentImageUrl: require('@/assets/8.png'),
            top: 300,
            left: 860,
            vw: 100,
            vh: 100,
            fontSize: 12,
            status: 2
          },
          {
            equipmentId: '33548976965462',
            equipmentImageUrl: require('@/assets/8.png'),
            top: 100,
            left: 380,
            vw: 100,
            vh: 100,
            fontSize: 12,
            status: 3
          },
          {
            equipmentId: '85484913549253',
            equipmentImageUrl: require('@/assets/8.png'),
            top: 200,
            left: 1500,
            vw: 100,
            vh: 100,
            fontSize: 12,
            status: 2
          }
        ],
        // 设备状态指示灯列表
          // {
          //   equipmentId: '123213213123232',// 设备ID
          //   equipmentImage: require('@/assets/8.png'), // 设备图片
          //   coordinateTop: 200, // 拖拽元素距盒子顶距离
          //   coordinateLeft: 100, // 拖拽元素距盒子左侧距离
          //   vw: 100,  // 缩放元素宽度
          //   vh: 100, // 缩放元素高度
          //   equipmentStatus: 1 // 设备状态 0:关机 22:报警 2:待机 3:运行 开机:1(没有四色灯标识归为待机)
          // }
        ], // 设备信息列表
        deviceList_copy: [],
        deviceStatusList: [
          // {
          //   label: '全部',
          //   value: 99,
          //   color: '#fff',
          //   checked: true
          // },
          {
            label: '关机',
            value: 2,
            color: '#A8A8A8'
            value: 0,
            color: '#A8A8A8',
            checked: false
          },
          {
            label: '待机',
            value: 0,
            color: '#FFFF00'
            value: 2,
            color: '#FFFF00',
            checked: false
          },
          {
            label: '运行',
            value: 3,
            color: '#00EE00'
            color: '#00EE00',
            checked: false
          },
          {
            label: '报警',
            value: 1,
            color: '#FF0000'
            value: 22,
            color: '#FF0000',
            checked: false
          }
        ]
        ],// 设备状态指示灯列表,
        windowHeight: null,// 当前浏览器可视区域高度((不包括工具栏、书签、底部任务栏)
        isFullScreen: false,// 进入看板页面时是否为全屏模式,不包括正常模式进入后切换为全屏模式
        parentLimitation: false,// 拖拽区域是否限制在父元素区域内,
        checkedStatusCount: null,// 已勾选筛选状态个数
        imgSrc: ''// 车间图纸地址
      }
    },
    computed: {
      getWorkshopName() {
        switch (this.$route.params.workshopId) {
          case '5321':
            return '长沙车间'
          case '6312':
            return '天津车间'
          case '3463':
            return '武汉车间'
          case '8421':
            return '北京车间'
          default:
            return '测试车间'
        }
    watch: {
      isSwitchChecked: {
        handler(newVal) {
          if (!newVal) {
            console.log('定时器开启中')
            this.timingAcquisition = setInterval(() => {
              this.getDeviceListByApi(this.$route.params.id)
            }, 2000)
          } else {
            console.log('关闭定时器')
            clearInterval(this.timingAcquisition)
            this.timingAcquisition = null
          }
        },
        immediate: true
      }
    },
    methods: {
      /**
       * 通过车间Id调用接口获取设备信息列表
       * @param workshopId 车间Id
       * @param id 车间Id
       */
      getDeviceListByApi(workshopId) {
        console.log('车间Id', workshopId)
      getDeviceListByApi(id) {
        console.log('重新刷新')
        api.getDeviceListInWorkshopSignagePageApi(id).then((res) => {
          if (res.result && res.result.length > 0) {
            this.deviceList = res.result
            this.deviceList_copy = res.result
          }
        })
      },
      /**
       * 通过车间Id调用接口获取车间详细信息
       * @param id 车间Id
       */
      getWorkshopDetailsByApi(id) {
        api.getWorkshopDetailByWorkshopIdApi(id).then((res) => {
          this.workshopDetails = res.result
          // this.$refs.deviceContainerRef.style.backgroundImage = `url(${this.getImgView(
          //   this.workshopDetails.backgroundImage
          // )})`
          this.imgSrc = this.getImgView(this.workshopDetails.backgroundImage)
          this.$refs.deviceContainerRef.style.height = (this.windowHeight - this.pageHeaderHeight) + 'px'
          // this.parentH = this.windowHeight - this.pageHeaderHeight
          this.parentH = 900
          this.parentLimitation = true // 在父元素高度设置后再设置限制拖拽区域,不这样有概率导致父元素高度未设置就限制拖拽
        })
      },
      /**
       * 图片预览
       * @param text 图片地址
       */
      getImgView(text) {
        if (text && text.indexOf(',') > 0) {
          text = text.substring(0, text.indexOf(','))
        }
        return getFileAccessHttpUrl(text)
      },
      /**
       * 点击保存按钮调用接口保存拖拽后的位置与设备图标尺寸
       */
      saveDevicePositionAndSizeByApi() {
        console.log('保存位置')
        console.log('触发保存')
        if (this.isOperatingDevice) {
          api.saveDevicePositionAndSizeApi(this.deviceList).then((res) => {
            if (res.code === 200) {
              this.$notification.success({
                message: '消息',
                description: res.message
              })
              this.isOperatingDevice = false
              if (this.isSwitchChecked) {
                this.isSwitchChecked = false
                this.isResizable = !this.isResizable
                this.isDraggable = !this.isDraggable
              }
              this.getDeviceListByApi(this.$route.params.id)
            }
          })
        } else {
          this.$notification.warning({
            message: '消息',
            description: '请开启功能后再进行保存'
          })
        }
      },
      /**
       * 设备拖拽或缩放时触发事件
       * @param newRect 拖拽或缩放后的尺寸及距离
       * @param index 拖拽设备在数组中的下标
       */
      resize(newRect, index) {
        console.log('newRect', newRect)
        if (newRect.width > 100) {
          if (newRect.width / newRect.height < 2) {
            this.deviceList[index].fontSize = newRect.width / 10
          } else {
            this.deviceList[index].fontSize = newRect.height / 5
          }
        } else {
          this.deviceList[index].fontSize = 12
        }
        // if (newRect.width > 100) {
        //   if (newRect.width / newRect.height < 2) {
        //     this.deviceList[index].fontSize = newRect.width / 10
        //   } else {
        //     this.deviceList[index].fontSize = newRect.height / 5
        //   }
        // } else {
        //   this.deviceList[index].fontSize = 12
        // }
        this.showGuideline = 'block'
        this.deviceList[index].vw = newRect.width
        this.deviceList[index].vh = newRect.height
        this.deviceList[index].top = newRect.top
        this.deviceList[index].left = newRect.left
        this.deviceList[index].coordinateTop = newRect.top
        this.deviceList[index].coordinateLeft = newRect.left
        this.guidelineXTop = newRect.top + newRect.height / 2
        this.guidelineYLeft = newRect.left + newRect.width / 2
      },
      /**
       * 根据设备状态值获取对应设备数量
       * @param value 设备状态值
       * @returns {number} 设备数量
       */
      getDeviceNumberByStatus(value) {
        return this.deviceList.filter(item => item.status === value).length
        if (value === 99) return this.deviceList_copy.length
        return this.deviceList_copy.filter((item) => item.equipmentStatus === value).length
      },
      /**
       * 开启功能触发事件
       * @param checked 当前switch状态,是否开启,初始为false
       */
      handleSwitchChange(checked) {
        this.isOperatingDevice = true
        this.isResizable = !this.isResizable
        this.isDraggable = !this.isDraggable
      },
      openDetail(item) {
        if (!this.isSwitchChecked) {
          if (item.equipmentStatus == 0) {
            this.$message.warning('设备处于关机状态!')
            return false
          }
          console.log(item)
          console.log(this.$refs.EquipmentDetailModal)
          this.$refs.EquipmentDetailModal.initData(item.equId)
          this.$refs.EquipmentDetailModal.timerModel(item.equId)
          // this.equipMessageTimer = setInterval(() => {
          //   setTimeout( this.$refs.equmentDetaiModel.initData(item.equipmentId),0)
          // },1000*10)
        }
      },
      /**
       * 浏览器尺寸发生改变时触发
       */
      handleWindowSizeChange() {
        // this.isFullScreen = !this.isFullScreen
        // if (!this.isFullScreen) location.reload() // 如果为全屏模式,则在切换模式时重新加载页面以重新获取浏览器可视区域高度
        const windowHeight =
          window.innerHeight ||
          document.documentElement.clientHeight ||
          document.body.clientHeight
        // this.parentH = 99999
        // const scaleRate = windowHeight / this.windowHeight
        // this.windowHeight = windowHeight
        this.$refs.deviceContainerRef.style.height = (windowHeight - this.pageHeaderHeight) + 'px'
        // const timer = setTimeout(() => {
        //   this.deviceList.forEach(item => {
        //     item.coordinateTop = item.coordinateTop * scaleRate
        //     item.vh = item.vh * scaleRate
        //     console.log('vh', item.vh)
        //   })
        //   this.parentH = windowHeight - this.pageHeaderHeight
        //   console.log('changeDeviceList', this.deviceList)
        // }, 500)
        // console.log('scaleRate', scaleRate)
      },
      checkboxChange(obj) {
        //需要判断是否开启功能,目的是为了关闭定时器避免筛选后设备被定时刷新的新设备覆盖
        if (this.isOperatingDevice) {
          obj.checked = !obj.checked
          if (obj.value !== 99) {
            if (obj.checked) this.checkedStatusCount++
            else this.checkedStatusCount--
          }
          if (obj.value == 99) {
            this.deviceStatusList.forEach(item => {
              if (item.value !== obj.value) item.checked = obj.checked
            })
            if (obj.checked) {
              this.deviceList = this.deviceList_copy
              this.checkedStatusCount = this.deviceStatusList.length - 1
            } else {
              this.deviceList = []
              this.checkedStatusCount = 0
            }
          } else {
            this.deviceStatusList.forEach(item => {
              if (item.value === 99) {
                if (this.checkedStatusCount !== this.deviceStatusList.length - 1 || this.checkedStatusCount === 0) item.checked = false
                if (this.checkedStatusCount === this.deviceStatusList.length - 1) item.checked = true
              }
            })
            if (obj.checked) {
              this.deviceList.push(...this.deviceList_copy.filter(item => item.equipmentStatus === obj.value))
            } else {
              this.deviceList = this.deviceList.filter(item => item.equipmentStatus !== obj.value)
            }
          }
        } else {
          this.$notification.warning({
            message: '消息',
            description: '请开启功能后再进行筛选'
          })
        }
      },
      handleScreenDevive(obj) {
        //需要判断是否开启功能,目的是为了关闭定时器避免筛选后设备被定时刷新的新设备覆盖
        if (this.isOperatingDevice) {
          obj.checked = true
          this.deviceList = this.deviceList_copy
          this.deviceStatusList.forEach(item => {
            if (item.value !== obj.value) item.checked = false
          })
          if (obj.value == 99) this.deviceList = this.deviceList_copy
          else this.deviceList = this.deviceList.filter(item => item.equipmentStatus === obj.value)
        } else {
          this.$notification.warning({
            message: '消息',
            description: '请开启功能后再进行筛选'
          })
        }
      }
    },
    created() {
      if (this.$route.params.id) {
        this.getDeviceListByApi(this.$route.params.id)
        this.getWorkshopDetailsByApi(this.$route.params.id)
      }
      this.checkedStatusCount = this.deviceStatusList.length - 1
    },
    mounted() {
      // 禁止用户选中内容
      document.onselectstart = () => false
      this.windowHeight =
        window.innerHeight ||
        document.documentElement.clientHeight ||
        document.body.clientHeight
      // 判断浏览器可视区域高度是否等于分辨率,若相等则表示进入时浏览器为全屏模式
      // if (this.windowHeight === screen.height) this.isFullScreen = true
      window.addEventListener('resize', this.handleWindowSizeChange)
    },
    created() {
      if (this.$route.params.workshopId) {
        this.getDeviceListByApi(this.$route.params.workshopId)
      }
    beforeDestroy() {
      // 确保销毁定时器、事件及回收资源
      clearInterval(this.timingAcquisition)
      this.timingAcquisition = null
    }
  }
</script>
@@ -216,43 +457,65 @@
    color: #fff;
    .page-header {
      height: 80px;
      font-size: 50px;
      text-align: center;
      position: relative;
      /*font-size: 50px;*/
      /*text-align: center;*/
      /*position: relative;*/
      .header-right {
        position: absolute;
        right: 200px;
        top: 0;
      .header-left {
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        padding-top: 20px;
      }
    }
    .content-container {
      position: relative;
      .workshop-name {
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 50px;
      }
      .device-status-info {
        width: 400px;
        position: absolute;
        top: 5px;
        right: 5px;
        height: 100%;
        display: flex;
        justify-content: flex-end;
        align-items: center;
        justify-content: space-between;
        padding-top: 20px;
        .single-status-info {
          width: 60px;
          display: flex;
          align-items: center;
          justify-content: space-between;
          margin: 10px;
          cursor: pointer;
          .status-square {
            width: 14px;
            height: 14px;
            border: 1px solid #fff;
            border-radius: 2px;
            border-radius: 3px;
          }
        }
      }
    }
    .content-container {
      width: 100%;
      background-repeat: no-repeat;
      background-size: 100% 100%;
      position: relative;
      .guideline{
        position: absolute;
        border: 1px dashed #ccc;
      }
      .guidelineX {
        width: 1920px;
        left: 0;
      }
      .guidelineY {
        top: 0;
        height: 900px;
      }
      .single-device {
@@ -273,13 +536,16 @@
          width: 100%;
          height: 100%;
          display: flex;
          justify-content: space-between;
          -webkit-align-items: flex-end;
          -moz-align-items: flex-end;
          -ms-align-items: flex-end;
          .status-image {
            background-size: 100% 100%;
            background-repeat: no-repeat;
            width: 45px;
            margin-right: 10px;
            width: 10px;
            height: 60%;
            margin-right: 5px;
          }
          .device-image {
@@ -290,7 +556,11 @@
          }
        }
      }
    }
  }
  /deep/ .ant-checkbox-inner {
    background-color: transparent;
    border-color: #fff;
  }
</style>