255 lines
7.5 KiB
Vue
255 lines
7.5 KiB
Vue
<template>
|
|
<section class="AiDvViewer">
|
|
<div v-if="!component">
|
|
<div class="component-item"
|
|
:style="{
|
|
width: item.width + 'px',
|
|
height: item.height + 'px',
|
|
left: item.left * scale + 'px',
|
|
top: item.top * scale + 'px',
|
|
position: 'absolute',
|
|
zIndex: item.zIndex,
|
|
transform: `scale(${scale})`
|
|
}"
|
|
v-for="(item, index) in componentList"
|
|
:key="index" @click="handleClick(item)">
|
|
<ai-dv-render :instance="instance" :key="index" :data="item" :index="index" :theme="dashboard.theme"/>
|
|
</div>
|
|
</div>
|
|
<components v-else :is="component" :dict="dict" :instance="instance" :nav="meta"/>
|
|
<ai-dv-dialog ref="dvDialog" v-bind="dialog">
|
|
<div v-if="dialog.content" v-html="dialog.content"/>
|
|
</ai-dv-dialog>
|
|
</section>
|
|
</template>
|
|
|
|
<script>
|
|
import AiDvDialog from "./AiDvDialog.vue";
|
|
|
|
export default {
|
|
name: 'AiDvViewer',
|
|
components: {AiDvDialog},
|
|
label: '大屏预览',
|
|
props: {
|
|
instance: Function,
|
|
dict: Object,
|
|
id: String,
|
|
urlPrefix: {
|
|
type: String,
|
|
default: '/app'
|
|
}
|
|
},
|
|
watch: {
|
|
id: {
|
|
handler(v) {
|
|
v && this.getInfo(v)
|
|
},
|
|
immediate: true
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
component: '',
|
|
dashboard: {
|
|
title: '大屏',
|
|
width: 1920,
|
|
height: 1080,
|
|
backgroundColor: '',
|
|
theme: '0',
|
|
backgroundImage: []
|
|
},
|
|
componentList: [],
|
|
scale: 1,
|
|
meta: {},
|
|
dialog: {}
|
|
}
|
|
},
|
|
mounted() {
|
|
this.$nextTick(() => {
|
|
let content = document.querySelector('#dv-full-screen-container')
|
|
if (content) {
|
|
const transform = content.style.transform
|
|
const scale = transform.replace('scale', '').replace('(', '').replace(')', '')
|
|
if (scale == 1) {
|
|
this.scale = document.body.clientWidth / 1920
|
|
}
|
|
}
|
|
})
|
|
},
|
|
methods: {
|
|
getInfo(id) {
|
|
this.component = null
|
|
id && this.instance.post(`${this.urlPrefix}/appdiylargescreen/queryLargeScreenDetailById?id=${id}`).then(res => {
|
|
if (res?.data) {
|
|
const config = JSON.parse(res.data.config)
|
|
if (config.custom) {
|
|
this.component = config.custom
|
|
this.meta = config?.meta || {}
|
|
} else {
|
|
const layers = JSON.parse(res.data.config).config
|
|
this.dashboard = JSON.parse(res.data.config).dashboard
|
|
Promise.all(layers.map(item => Promise.resolve().then(() => {
|
|
if (item.dataType !== 'staticData' && ((item.type.indexOf('Chart') > -1) || ['display', 'table', 'map', 'summary', 'AiRanking', 'AiDvTable'].includes(item.type))) {
|
|
return this.getSourceData(item)
|
|
}
|
|
if (item.type === 'monitor' && item.monitorType === 'cmcc') {
|
|
return item.moniterId && this.instance.post(`${this.urlPrefix}/appzyvideoequipment/getWebSdkUrl?deviceId=${item.moniterId}`).then(res => {
|
|
if (res.code == 0) {
|
|
return item.src = JSON.parse(res.data).url
|
|
}
|
|
})
|
|
}
|
|
if (item.type === 'monitor' && item.monitorType === 'slw') {
|
|
return item.moniterId && this.instance.post(`${this.urlPrefix}/appzyvideoequipment/getWebSdkUrl?deviceId=${item.moniterId}`).then(res => {
|
|
if (res.code == 0) {
|
|
return item.src = res.data
|
|
}
|
|
})
|
|
}
|
|
}))).then(() => {
|
|
this.componentList = layers
|
|
})
|
|
}
|
|
}
|
|
})
|
|
},
|
|
getSourceData(item) {
|
|
const api = item.dataType === 'apiData' ? item.api : `${this.urlPrefix}/appdiylargescreen/statisticsByLsid?id=${item.sourceDataId}`
|
|
return this.instance.post(api).then(res => {
|
|
if (res?.data) {
|
|
if (res.data.length) {
|
|
const keys = Object.keys(res.data[0])
|
|
const list = res.data
|
|
let dynamicData = []
|
|
if (item.type === 'table' || item.type === 'AiDvTable') {
|
|
dynamicData = keys.map(v => {
|
|
let obj = {}
|
|
list.forEach((item, index) => {
|
|
obj[`v${index}`] = item[v]
|
|
})
|
|
|
|
return {
|
|
row: v,
|
|
...obj
|
|
}
|
|
})
|
|
} else if (item.type === 'summary') {
|
|
if (item.display === 'summary9') {
|
|
dynamicData = res.data
|
|
} else {
|
|
dynamicData = Object.keys(res.data[0]).map(item => {
|
|
return {
|
|
key: item,
|
|
value: res.data[0][item]
|
|
}
|
|
})
|
|
}
|
|
} else if (item.dataType === 'dynamicData' && !item.dataX && !item.dataY.length) {
|
|
dynamicData = Object.keys(res.data[0]).map(item => {
|
|
return {
|
|
label: item,
|
|
value: res.data[0][item]
|
|
}
|
|
})
|
|
} else {
|
|
if (item.dataX && item.dataY.length) {
|
|
list.forEach(i => {
|
|
let obj = {}
|
|
item.dataY.forEach(v => {
|
|
obj[v] = i[v]
|
|
})
|
|
dynamicData.push({
|
|
[item.dataX]: i[item.dataX],
|
|
...obj
|
|
})
|
|
})
|
|
} else {
|
|
dynamicData = res.data
|
|
}
|
|
}
|
|
item[item.dataType] = dynamicData
|
|
} else {
|
|
item[item.dataType] = []
|
|
}
|
|
}
|
|
})
|
|
},
|
|
handleClick(item = {}) {
|
|
const {dialogTitle, dialogContent} = item
|
|
if (dialogTitle) {
|
|
this.dialog = {title: dialogTitle, content: dialogContent, ...this.getStaticDataProps(item.staticData)}
|
|
this.$refs.dvDialog.show()
|
|
}
|
|
},
|
|
//新版静态数据处理
|
|
getStaticDataProps(meta = []) {
|
|
const columnProp = "name"
|
|
let columns = [], tableData = []
|
|
meta.map((row, i) => {
|
|
const prop = `c${i || ""}`
|
|
columns.push({label: row[columnProp], prop})
|
|
Object.entries(row).map(([k, v]) => {
|
|
if (/^v/.test(k)) {
|
|
const item = tableData[k.substring(1) || 0] || {}
|
|
item[prop] = v
|
|
tableData[k.substring(1) || 0] = item
|
|
} else if (k != columnProp) {
|
|
const index = columns.findIndex(e => k == e)
|
|
if (index > -1) {
|
|
const item = tableData[index] || {}
|
|
item[prop] = v
|
|
tableData[index] = item
|
|
} else {
|
|
columns.push(k)
|
|
const newIndex = columns.length - 1
|
|
const item = tableData[newIndex] || {}
|
|
item[prop] = v
|
|
tableData[newIndex] = item
|
|
}
|
|
}
|
|
})
|
|
})
|
|
tableData = tableData.map(e => ({...e, $cellEdit: false}))
|
|
return {columns, tableData}
|
|
},
|
|
close() {
|
|
this.$emit('close')
|
|
}
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.AiDvViewer {
|
|
position: relative;
|
|
height: 100%;
|
|
background: transparent !important;
|
|
|
|
.component-item {
|
|
transform-origin: 0 0;
|
|
}
|
|
|
|
.dv-scroll-board {
|
|
height: calc(100%) !important;
|
|
|
|
.header-item {
|
|
color: #7e8697;
|
|
font-size: 16px;
|
|
}
|
|
|
|
.index {
|
|
display: inline-block;
|
|
width: 26px;
|
|
height: 26px;
|
|
line-height: 26px;
|
|
font-size: 16px;
|
|
background-color: #4F57FF !important;
|
|
}
|
|
}
|
|
|
|
.vdr {
|
|
border: none;
|
|
}
|
|
}
|
|
</style>
|