353 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			353 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
<template>
 | 
						|
  <div class="AiDvRender" style="width: 100%; height: 100%;">
 | 
						|
    <ai-dv-display v-if="currentType === 'display'" :title="data.title" :list="values"/>
 | 
						|
    <ai-dv-panel
 | 
						|
        style="height: 100%; width: 100%;"
 | 
						|
        v-if="currentType !== 'display'"
 | 
						|
        :title="data.title"
 | 
						|
        :theme="theme"
 | 
						|
        :border="data.border || ''">
 | 
						|
      <AiDvSummary v-if="currentType === 'summary'" :theme="theme" :summaryTitle="data.summaryTitle"
 | 
						|
                   :key="`summary${index}`" :type="data.display"
 | 
						|
                   :data="values"/>
 | 
						|
      <AiSwiper v-else-if="currentType === 'swiper'" :heigth="'100%'" :data="values" :dotIndicator="data.dotIndicator"/>
 | 
						|
      <dv-scroll-board
 | 
						|
          v-if="currentType === 'table'"
 | 
						|
          :class="'dvScrollBoard' + theme"
 | 
						|
          :config="formatTable(values, data.isShowIndex, data.rowNum)"
 | 
						|
          :key="data.height"
 | 
						|
          :theme="theme"
 | 
						|
          :style="{height: data.height + 'px', width: '100%'}"/>
 | 
						|
      <ai-echart-v2 v-else-if="/Chart/.test(currentType)"
 | 
						|
                    style="height: 100%; width: 100%;"
 | 
						|
                    :ref="'chart' + index"
 | 
						|
                    :key="`chart-${index}`"
 | 
						|
                    :theme="theme"
 | 
						|
                    :data="values"
 | 
						|
                    :ops="$echartTpls[data.config]"/>
 | 
						|
      <AiDvTable
 | 
						|
          v-else-if="currentType === 'AiDvTable'"
 | 
						|
          :heigth="'100%'"
 | 
						|
          :stripe="data.stripe"
 | 
						|
          :theme="theme"
 | 
						|
          :isShowIndex="data.isShowIndex"
 | 
						|
          :config="dvTableConfig"
 | 
						|
          :data="values">
 | 
						|
      </AiDvTable>
 | 
						|
      <AiRanking
 | 
						|
          v-else-if="currentType === 'AiRanking'"
 | 
						|
          :theme="theme"
 | 
						|
          :heigth="'100%'"
 | 
						|
          :subType="data.subType"
 | 
						|
          :data="values">
 | 
						|
      </AiRanking>
 | 
						|
      <AiDvMap v-else-if="currentType === 'AiDvMap'" style="width: 100%; height: 100%" :ref="'chart' + index"
 | 
						|
               :key="`AiDvMap${index}`" :theme="theme"></AiDvMap>
 | 
						|
      <ai-map v-else-if="currentType=='map'" :mask="data.mask === '1'" :areaId="data.areaId" :is3d="data.is3d==1"
 | 
						|
              :is3dAround="data.is3dAround === '1'"
 | 
						|
              :map-style="`amap://styles/${data.mapStyle}`" :pulseLines="data.pulseLines==1" :map.sync="map"
 | 
						|
              :lib.sync="lib"
 | 
						|
              :onlyShowArea="data.limitArea==1" :satellite="data.layers=='satellite'">
 | 
						|
        <div class="mapInfoWin" v-show="mapDialog">
 | 
						|
          <div class="corn" v-for="i in 4" :key="i"/>
 | 
						|
          <div ref="mapInfoWin"/>
 | 
						|
        </div>
 | 
						|
      </ai-map>
 | 
						|
      <ai-monitor :src="data.src" v-else-if="currentType === 'monitor'" :type="data.monitorType"/>
 | 
						|
      <video style="width: 100%; height: 100%; object-fit: fill;" loop :src="data.src" autoplay
 | 
						|
             v-else-if="currentType === 'video'"/>
 | 
						|
      <AiDvPartyOrg style="width: 100%; height: 100%;" v-else-if="currentType === 'partyOrg'" :instance="instance"/>
 | 
						|
      <!-- <ai-sprite v-else-if="/building/.test(currentType)" v-bind="data" is3D @init="mods[currentType]"/> -->
 | 
						|
      <ai-dv-plot v-else-if="currentType=='plot'" :options="data.charts" :instance="instance"/>
 | 
						|
    </ai-dv-panel>
 | 
						|
  </div>
 | 
						|
</template>
 | 
						|
 | 
						|
<script>
 | 
						|
import {scrollBoard} from '@jiaminghi/data-view'
 | 
						|
import Vue from "vue"
 | 
						|
import {mapState} from 'vuex'
 | 
						|
import AiDvMap from "./AiDvMap";
 | 
						|
import AiMonitor from "./AiMonitor/AiMonitor";
 | 
						|
import AiSwiper from './AiSwiper.vue'
 | 
						|
import AiDvDisplay from "./layout/AiDvDisplay/AiDvDisplay";
 | 
						|
import AiDvPanel from "./layout/AiDvPanel/AiDvPanel";
 | 
						|
import AiDvSummary from "./layout/AiDvSummary/AiDvSummary";
 | 
						|
import AiDvPlot from "./layout/AiDvPlot/AiDvPlot.vue";
 | 
						|
 | 
						|
Vue.use(scrollBoard)
 | 
						|
 | 
						|
export default {
 | 
						|
  name: 'AiDvRender',
 | 
						|
  props: ['data', 'index', 'theme', 'instance'],
 | 
						|
  components: {
 | 
						|
    AiDvPlot,
 | 
						|
    // AiSprite,
 | 
						|
    AiDvSummary,
 | 
						|
    AiDvDisplay,
 | 
						|
    AiDvPanel,
 | 
						|
    AiMonitor,
 | 
						|
    AiSwiper,
 | 
						|
    AiDvMap
 | 
						|
  },
 | 
						|
  data() {
 | 
						|
    return {
 | 
						|
      // mods,
 | 
						|
      map: null,
 | 
						|
      lib: null,
 | 
						|
      timer: null,
 | 
						|
      dvTableConfig: [],
 | 
						|
      mapDialog: false
 | 
						|
    }
 | 
						|
  },
 | 
						|
  computed: {
 | 
						|
    ...mapState(['user']),
 | 
						|
    values: v => v.data?.[v.data?.dataType] || [],
 | 
						|
    currentType: v => v.data.type
 | 
						|
  },
 | 
						|
  watch: {
 | 
						|
    values: {
 | 
						|
      immediate: true,
 | 
						|
      deep: true, handler() {
 | 
						|
        if (this.currentType == 'map') {
 | 
						|
          this.renderMap()
 | 
						|
        } else if (this.currentType === 'AiDvTable') {
 | 
						|
          this.dvTableConfig = this.data[this.data.dataType].map((v, i) => {
 | 
						|
            return {
 | 
						|
              color: this.data.config[i] ? (this.data.config[i].color || '') : '',
 | 
						|
              width: this.data.config[i] ? (this.data.config[i].width || '') : '',
 | 
						|
              align: this.data.config[i] ? (this.data.config[i].align || '') : ''
 | 
						|
            }
 | 
						|
          })
 | 
						|
          this.data.config = this.dvTableConfig
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  },
 | 
						|
  methods: {
 | 
						|
    formatTable(data, isShowIndex, rowNum) {
 | 
						|
      const tableStyle = {
 | 
						|
        headerBGC: 'transparent',
 | 
						|
        evenRowBGC: 'transparent',
 | 
						|
        oddRowBGC: 'rgba(0, 133, 255, 0.2)',
 | 
						|
        headerHeight: 42,
 | 
						|
        align: 'center'
 | 
						|
      }
 | 
						|
      if (!data.length) {
 | 
						|
        return {
 | 
						|
          header: [],
 | 
						|
          data: []
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (this.data.tableConfig) {
 | 
						|
        const {x, y} = this.data.tableConfig, dataMap = {}
 | 
						|
        const header = [...new Set(Object.entries(data.find(e => e.row == x) || null)?.filter(e => e[0] != 'row').map(e => e[1]) || [])],
 | 
						|
            rows = [...new Set(Object.entries(data.find(e => e.row == y) || null)?.filter(e => e[0] != 'row').map(e => e[1]) || [])]
 | 
						|
        data.map(e => Object.keys(e).map(k => k != 'row' && (dataMap[k] = (dataMap[k] || "") + "#" + e[k])))
 | 
						|
        const tableData = Object.values(dataMap).map(e => e.split("#"))
 | 
						|
        return {
 | 
						|
          ...tableStyle,
 | 
						|
          header: ["", ...header],
 | 
						|
          data: rows.map(y => [y, ...header.map(x => {
 | 
						|
            return tableData.find(m => m.includes(x) && m.includes(y)).at(-1)
 | 
						|
          })])
 | 
						|
        }
 | 
						|
      }
 | 
						|
      let rows = []
 | 
						|
      const header = data.map(v => {
 | 
						|
        return v[Object.keys(v)[0]]
 | 
						|
      })
 | 
						|
      Object.keys(data[0]).forEach((item, index) => {
 | 
						|
        if (index !== 0) {
 | 
						|
          rows.push(item)
 | 
						|
        }
 | 
						|
      })
 | 
						|
      return {
 | 
						|
        header: header,
 | 
						|
        data: rows.map(item => {
 | 
						|
          return data.map(v => {
 | 
						|
            return v[item]
 | 
						|
          })
 | 
						|
        }),
 | 
						|
        ...tableStyle,
 | 
						|
        rowNum: rowNum || 7,
 | 
						|
        index: isShowIndex === '1',
 | 
						|
        waitTime: 8000,
 | 
						|
        carousel: 'page',
 | 
						|
        indexHeader: '排名',
 | 
						|
        align: ['center', 'center', 'center', 'center', 'center']
 | 
						|
      }
 | 
						|
    },
 | 
						|
    renderMap(count = 0) {
 | 
						|
      let {lib: AMap, map} = this
 | 
						|
      this.timer && clearInterval(this.timer)
 | 
						|
      if (AMap && map) {
 | 
						|
        map.clearMap()
 | 
						|
        const center = map.getCenter()
 | 
						|
        map.on('click', () => {
 | 
						|
          map.setZoomAndCenter(10, center)
 | 
						|
          map.setPitch(0)
 | 
						|
          this.mapDialog = false
 | 
						|
        })
 | 
						|
        const markers = Array.isArray(this.values) ? this.values : this.values.markers
 | 
						|
        const polylines = Array.isArray(this.values) ? [] : this.values.polylines || []
 | 
						|
        markers.map(e => ({lng: e['经度'], lat: e['纬度'], label: e['地区名称'], ...e})).filter(e => e.lng).map((e) => {
 | 
						|
          const {icon = "https://cdn.cunwuyun.cn/dvcp/h5/Location2.png"} = e
 | 
						|
          return new AMap.Marker({
 | 
						|
            map,
 | 
						|
            content: e.content || `<div class="marker ${this.data.alwaysShow ? 'showLabel' : ''}">
 | 
						|
                        <img src="${icon}"/>
 | 
						|
                        <span>${e.label}</span>
 | 
						|
                      </div>`,
 | 
						|
            position: [e.lng, e.lat]
 | 
						|
          }).on('click', () => {
 | 
						|
            this.mapDialog = true
 | 
						|
            this.$nextTick(() => {
 | 
						|
              this.$refs.mapInfoWin.innerHTML = e.infoWindowHtml || [`<div class="infoWin">`, `<b>${e.label}</b>`, '</div>'].join('')
 | 
						|
              map.setZoomAndCenter(16, [e.lng, e.lat])
 | 
						|
              map.setPitch(60)
 | 
						|
            })
 | 
						|
          })
 | 
						|
        })
 | 
						|
        polylines.filter(e => e.path?.length > 0)?.map(e => new AMap.Polyline({
 | 
						|
          map, strokeColor: "#00FFAE", ...e, path: e.path.map(p => new AMap.LngLat(p[1], p[0]))
 | 
						|
        }))
 | 
						|
        this.data.is3d > 0 && map.setPitch(65)
 | 
						|
        if (this.data.is3dAround == 1) {
 | 
						|
          this.timer = setInterval(() => map?.setRotation(360, false, 16000))
 | 
						|
        }
 | 
						|
      } else if (count < 10) {
 | 
						|
        console.log("正在加载...%s", count)
 | 
						|
        setTimeout(() => this.renderMap(++count), 1000)
 | 
						|
      }
 | 
						|
    }
 | 
						|
  },
 | 
						|
  mounted() {
 | 
						|
    if (this.currentType == 'table') {
 | 
						|
      // this.$injectLib("https://cdn.cunwuyun.cn/datav.map.vue.js")
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
</script>
 | 
						|
 | 
						|
<style lang="scss" scoped>
 | 
						|
.AiDvRender {
 | 
						|
  :deep(.dvScrollBoard1 ) {
 | 
						|
 | 
						|
    .header {
 | 
						|
      background: rgba(0, 0, 0, 0.1) !important;
 | 
						|
 | 
						|
      .header-item {
 | 
						|
        color: #FFBB73 !important;
 | 
						|
        font-size: 16px !important;
 | 
						|
        font-weight: 600;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    .rows {
 | 
						|
      font-size: 16px;
 | 
						|
      font-weight: 600;
 | 
						|
      color: #FFFFFF;
 | 
						|
      line-height: 21px;
 | 
						|
      text-shadow: 0px 2px 4px rgba(117, 9, 9, 0.5);
 | 
						|
      background: linear-gradient(180deg, #FFF6C7 0%, #FF9A02 100%);
 | 
						|
      -webkit-background-clip: text;
 | 
						|
      -webkit-text-fill-color: transparent;
 | 
						|
 | 
						|
      & > div:nth-of-type(2n - 1) {
 | 
						|
        background-color: transparent !important;
 | 
						|
      }
 | 
						|
 | 
						|
      & > div:nth-of-type(2n) {
 | 
						|
        background-color: rgba(0, 0, 0, 0.1) !important;
 | 
						|
      }
 | 
						|
 | 
						|
      .index {
 | 
						|
        color: #fff;
 | 
						|
        text-shadow: none;
 | 
						|
        background: #BD4921 !important;
 | 
						|
        -webkit-background-clip: inherit;
 | 
						|
        -webkit-text-fill-color: #fff;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  :deep(.marker) {
 | 
						|
    position: relative;
 | 
						|
 | 
						|
    & > img {
 | 
						|
      width: 30px;
 | 
						|
      height: 30px;
 | 
						|
    }
 | 
						|
 | 
						|
    & > span {
 | 
						|
      display: none;
 | 
						|
    }
 | 
						|
 | 
						|
    &:hover > span, &.showLabel > span {
 | 
						|
      position: absolute;
 | 
						|
      left: 50%;
 | 
						|
      bottom: 0;
 | 
						|
      transform: translate(-50%, 100%);
 | 
						|
      display: block;
 | 
						|
      color: #fff;
 | 
						|
      font-size: 14px;
 | 
						|
      white-space: nowrap;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  :deep(.mapInfoWin) {
 | 
						|
    $borderColor: #245D8E;
 | 
						|
    $borderCorn: url("https://cdn.cunwuyun.cn/dvcp/dv/mapDialogCorn.png");
 | 
						|
    position: absolute;
 | 
						|
    left: 50%;
 | 
						|
    top: 40%;
 | 
						|
    transform: translate(-50%, -50%);
 | 
						|
    padding: 16px 20px;
 | 
						|
    max-width: 800px;
 | 
						|
    background-color: rgba(#0A1B3E, 0.8);
 | 
						|
    backdrop-filter: blur(6px);
 | 
						|
    border: 1px solid $borderColor;
 | 
						|
    box-shadow: 10px 10px 10px inset rgba($borderColor, .8), -10px -10px 10px inset rgba($borderColor, .8);
 | 
						|
    border-radius: 4px;
 | 
						|
    color: white;
 | 
						|
 | 
						|
    .corn {
 | 
						|
      $offset: -2px;
 | 
						|
      background-image: $borderCorn;
 | 
						|
      background-repeat: no-repeat;
 | 
						|
      position: absolute;
 | 
						|
      width: 14px;
 | 
						|
      height: 14px;
 | 
						|
      background-size: 100% 100%;
 | 
						|
 | 
						|
      &:nth-of-type(1) {
 | 
						|
        left: $offset;
 | 
						|
        top: $offset;
 | 
						|
        transform: rotate(-90deg);
 | 
						|
      }
 | 
						|
 | 
						|
      &:nth-of-type(2) {
 | 
						|
        right: $offset;
 | 
						|
        top: $offset;
 | 
						|
        transform: none;
 | 
						|
      }
 | 
						|
 | 
						|
      &:nth-of-type(3) {
 | 
						|
        right: $offset;
 | 
						|
        bottom: $offset;
 | 
						|
        transform: rotate(90deg);
 | 
						|
      }
 | 
						|
 | 
						|
      &:nth-of-type(4) {
 | 
						|
        left: $offset;
 | 
						|
        bottom: $offset;
 | 
						|
        transform: rotate(180deg);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
</style>
 |