DatavDesignPreview.vue 7.43 KB
<template>
  <div class="body">
    <div class="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 && data.list.filter(d => d.key)">
          <DatavDesignPreviewItem :field="element" :key="index" />
        </template>
        <div class="no-data-card" v-if="!data.list">
          <el-image :src="tableNoDataImg"></el-image>
          <p class="no-data-text">暂无数据</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import DatavDesignPreviewItem from '@/components/portal/DatavDesignPreviewItem.vue'
import req from '@/request.js'
export default {
  name: 'design-preview-panel',
  components: {
    DatavDesignPreviewItem
  },
  props: {
    layout: {
      type: Object,
      default() {
        return null
      }
    },
    lessWidth: {
      //偏差宽度
      type: Number,
      default() {
        return 0
      }
    },
    lessHeight: {
      //偏差高度
      type: Number,
      default() {
        return 0
      }
    }
  },
  data() {
    return {
      tableNoDataImg: require('@/assets/nodata_images/no-data.png'),
      loading: true,
      s_width: 1920, //基准宽度,px
      s_height: 1080, //基准高度,px
      fullscreen: false,
      data: {list: []},
      bgStyle: {
        position: 'relative',
        background: '#000',
        justifyContent: 'center',
        alignItems: 'center'
      },
      canvasStyle: {
        position: 'relative',
        width: '1920px',
        height: '1080px',
        transformOrigin: '0 0'
      }
    }
  },
  mounted() {
    
    window.addEventListener('keydown', this.KeyDown, true) // 监听按键事件
    let _this = this
    setTimeout(function() {
      _this.calcRatio()
    }, 0)
  },
  methods: {
    cancelLoading() {
      this.loading = true
      setTimeout(() => {
        this.loading = false
      }, 500)
    },
    toggle() {
      this.$fullscreen.toggle(this.$el.querySelector('.bg'), {
        wrap: false,
        callback: this.fullscreenChange
      })
    },
    fullscreenChange(fullscreen) {
      this.fullscreen = fullscreen
      this.resizeCanvas()
    },
    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 && this.data.config.backgroundType) {
        case 'color':
          this.bgStyle.background = this.data.config.backgroundColor
          break
        case 'image':
          this.bgStyle.background = `url(${require('@/assets/img/datav/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
        default: 
          this.bgStyle.background = '#000'
      }
      this.$set(this.bgStyle, 'opacity', this.data.config.backgroundOpacity)
    },
    getParentHeight(el) {
      if (el.$parent && el.$parent.$el.offsetHeight > window.innerHeight) {
        return getParentHeight(el.$parent)
      } else {
        return el.$parent.$el.offsetHeight
      }
    },
    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
      if (currentHeight > window.innerHeight && this.$parent.$parent) {
        currentHeight = this.getParentHeight(this.$parent)
      }
      if (!this.fullscreen) {
        currentWidth = currentWidth - this.lessWidth
        currentHeight = currentHeight - this.lessHeight
      }
      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')
    },
    initData() {
      this.cancelLoading()
      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) {
        let _this = this
        req
          .get(
            window.context.portal +
              '/portal/sysIndexLayoutManage/sysIndexLayoutManage/v1/getByAlias?alias=' +
              this.$route.params.alias
          )
          .then(
            response => {
              if (response.data && response.data.length) {
                _this.data = JSON.parse(
                  Base64.decode(response.data[0].designHtml)
                )
                ;(_this.s_width = this.data.config.width),
                  (_this.s_height = this.data.config.height),
                  _this.initBgStyle()
              } else {
                _this.data = {}
                _this.initBgStyle()
              }
            },
            function errorCallback() {
              _this.$message.success('未获取到大屏信息。')
            }
          )
      } else if (this.layout != null) {
        this.data = this.layout
        ;(this.s_width = this.data.config.width),
          (this.s_height = this.data.config.height),
          this.initBgStyle()
      }
    }
  },
  created() {
    this.initData()
  },
  beforeRouteUpdate(to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
    next();
    this.initData()
  },
}
</script>
<style lang="scss" scoped>
.body {
  height: 100%;
  width: 100%;
  overflow: hidden;
  display: flex;
  background: #333;
}
.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;
}
.no-data-card {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
</style>