DatavDesignPreview.vue 7.78 KB
<template>
  <div class="body">
    <div class="datav-preview-bg" :style="bgStyle">
      <dv-loading v-if="loading">Loading...</dv-loading>
      <div class="widget-canvas" :style="canvasStyle">
        <template v-for="(element, index) in data.list.filter((d) => d.key)">
          <DatavDesignPreviewItem :key="index" :field="element" />
        </template>
      </div>
    </div>
  </div>
</template>

<script>
  import DatavDesignPreviewItem from '@/components/datav/DatavDesignPreviewItem.vue'
  import req from '@/utils/request.js'
  import Vue from 'vue'
  import dataV from '@jiaminghi/data-view'
  Vue.use(dataV)
  export default {
    name: 'DesignPreviewPanel',
    components: {
      DatavDesignPreviewItem,
    },
    props: {
      layout: {
        type: Object,
        default() {
          return null
        },
      },
      alias: {
        type: String,
        default() {
          return ''
        },
      },
    },
    data() {
      return {
        loading: true,
        s_width: this.layout ? this.layout.config.width : 1920, //基准宽度,px
        s_height: this.layout ? this.layout.config.height : 1080, //基准高度,px
        fullscreen: false,
        data: { list: [] },
        bgStyle: {
          position: 'relative',
          background: '#000',
          justifyContent: 'center',
          alignItems: 'center',
        },
        canvasStyle: {
          position: 'relative',
          width: (this.layout ? this.layout.config.width : 1920) + 'px',
          height: (this.layout ? this.layout.config.height : 1080) + 'px',
          transformOrigin: '0 0',
        },
      }
    },
    mounted() {
      this.cancelLoading()
      window.addEventListener('keydown', this.KeyDown, true) // 监听按键事件
      let _this = this
      setTimeout(function () {
        _this.calcRatio()
      }, 0)
    },
    created() {
      if (this.alias) {
        this.initByAlias(this.alias)
      } else if (this.layout == null && this.$route.query.key) {
        this.data = JSON.parse(sessionStorage.getItem(this.$route.query.key))
        this.initBgStyle()
      }
      if (this.layout == null && this.$route.params.alias) {
        this.initByAlias(this.$route.params.alias)
      } else if (this.layout == null && this.$route.query.alias) {
        this.initByAlias(this.$route.query.alias)
      } else if (this.layout == null && this.$route.meta.alias) {
        this.initByAlias(this.$route.meta.alias)
      } else if (this.layout != null) {
        this.data = this.layout
        ;(this.s_width = this.data.config.width),
          (this.s_height = this.data.config.height),
          this.calcRatio()
        this.initBgStyle()
      }
    },
    beforeDestroy() {
      window.removeEventListener('keydown', this.KeyDown, true)
    },
    methods: {
      cancelLoading() {
        setTimeout(() => {
          this.loading = false
        }, 500)
      },
      toggle() {
        this.$fullscreen.toggle(this.$el.querySelector('.datav-preview-bg'), {
          teleport: true,
          callback: this.fullscreenChange,
        })
      },
      fullscreenChange(fullscreen) {
        this.fullscreen = fullscreen
        this.resizeCanvas()
        if (!this.$fullscreen.isFullscreen) {
          this.removeBgChild()
        }
      },
      removeBgChild() {
        let bgs = document.getElementsByClassName('datav-preview-bg')
        if (bgs.length > 0) {
          for (let i = 0; i < bgs.length; i++) {
            const bg = bgs[i]
            bg.parentNode.removeChild(bg)
          }
        }
        let bgList = document.getElementsByClassName('datav-preview-bg')
        if (bgList && bgList.length > 0) {
          this.removeBgChild()
        }
      },
      KeyDown(event) {
        if (event.keyCode === 122) {
          event.returnValue = false
          this.toggle()
        }
      },
      resizeCanvas() {
        let _this = this
        setTimeout(function () {
          _this.calcRatio()
        }, 100)
      },
      initBgStyle() {
        switch (this.data.config.backgroundType) {
          case 'color':
            this.bgStyle.background = this.data.config.backgroundColor
            break
          case 'image':
            this.bgStyle.background = `url(${require('@/assets/datav_images/datav_' +
              this.data.config.backgroundImage +
              '.png')}) 100% no-repeat`
            break
          case 'file':
            if (
              this.data.config.backgroundFile &&
              this.data.config.backgroundFile.id
            ) {
              let _this = this
              req
                .get(
                  window.context.portal +
                    '/system/file/v1/preview?fileId=' +
                    this.data.config.backgroundFile.id,
                  'blob'
                )
                .then(
                  (response) => {
                    if (response.data.size > 0) {
                      var blob = response.data
                      var reader = new FileReader()
                      reader.readAsDataURL(blob)
                      reader.onload = function (e) {
                        _this.bgStyle.background = `url(${e.target.result}) 100%  no-repeat`
                      }
                    }
                  },
                  function errorCallback() {
                    _this.$message.success('获取背景图片失败。')
                  }
                )
            }
            break
        }
        this.$set(this.bgStyle, 'opacity', this.data.config.backgroundOpacity)
      },
      calcRatio() {
        //计算缩放比例
        let currentWidth = this.fullscreen
          ? window.innerWidth
          : this.$parent.$el
          ? this.$parent.$el.offsetWidth
          : document.body.clientWidth
        let currentHeight = this.fullscreen
          ? window.innerHeight
          : this.$parent.$el
          ? this.$parent.$el.offsetHeight
          : document.body.clientHeight
        const widthRatio = currentWidth / this.s_width
        const heightRatio = currentHeight / this.s_height
        this.$set(
          this.canvasStyle,
          'transform',
          'scale(' + widthRatio + ',' + heightRatio + ')'
        )
        this.$set(this.bgStyle, 'height', currentHeight + 'px')
        this.$set(this.bgStyle, 'width', currentWidth + 'px')
      },
      initByAlias(alias) {
        let _this = this
        req
          .get(
            window.context.portal +
              '/portal/sysIndexLayoutManage/sysIndexLayoutManage/v1/getByAlias?alias=' +
              alias
          )
          .then(
            (response) => {
              if (response) {
                let designHtml
                if (response instanceof Array && response.length) {
                  designHtml = response[0].designHtml
                } else {
                  designHtml = response.designHtml
                }
                if (designHtml) {
                  _this.data = JSON.parse(Base64.decode(designHtml))
                  ;(_this.s_width = this.data.config.width),
                    (_this.s_height = this.data.config.height),
                    _this.calcRatio()
                  _this.initBgStyle()
                } else {
                  _this.$message.warning('大屏配置有问题,请联系管理员')
                }
              }
            },
            function errorCallback() {
              _this.$message.success('未获取到大屏信息。')
            }
          )
      },
    },
  }
</script>
<style lang="scss" scoped>
  .body {
    height: 100%;
    width: 100%;
    overflow: hidden;
    display: flex;
    background: #333;
  }
  .datav-preview-bg {
    padding: 0.2rem 0.2rem 0 0.2rem;
    background-size: cover;
    background-position: center center;
    height: calc(100% - 1px);
    width: calc(100% - 5px);
    overflow: hidden;
    z-index: 500;
  }
</style>