You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

204 lines
6.2 KiB
Vue

<template>
<div
v-loading="loading"
class="bs-remote-preview"
element-loading-text="远程组件加载中..."
>
<div class="remote-preview-inner-wrap">
<component
:is="remoteComponent"
:config="config"
/>
</div>
</div>
</template>
<script>
import remoteVueLoader from 'remote-vue-loader'
import { getBizComponentInfo } from 'data-room-ui/js/api/bigScreenApi'
import innerRemoteComponents, { getRemoteComponents } from 'data-room-ui/RemoteComponents/remoteComponentsList'
export default {
name: 'BsComponentPreview',
props: {
vueContent: {
type: String,
default: ''
},
settingContent: {
type: String,
default: ''
}
},
computed: {
config: {
get () {
// eslint-disable-next-line prefer-const
let option = {}
// eslint-disable-next-line prefer-const
let setting = []
// eslint-disable-next-line prefer-const, no-unused-vars
let title = ''
// eslint-disable-next-line prefer-const, no-unused-vars
let data = []
// eslint-disable-next-line prefer-const
let settingContent = this.settingContentInner?.replaceAll('const ', '')
// 去掉 export default及后面代码
settingContent = settingContent?.replace(/export default[\s\S]*/, '')
eval(settingContent)
return {
title,
option,
setting
}
},
set (val) {}
}
},
watch: {
settingContentInner () {
this.getRemoteComponent()
},
vueContentInner () {
this.getRemoteComponent()
},
vueContent (newVal) {
this.vueContentInner = newVal
},
settingContent (newVal) {
this.settingContentInner = newVal
}
},
data () {
return {
loading: false,
remoteComponent: null,
vueContentInner: this.vueContent,
settingContentInner: this.settingContent?.replaceAll('const ', '')
}
},
created () {
this.viewComponent()
},
methods: {
async viewComponent () {
// 如果有编码,则获取组件信息
if (this.$route.query?.code) {
const data = await getBizComponentInfo(this.$route.query?.code)
this.vueContentInner = data.vueContent
this.settingContentInner = data.settingContent
this.config = this.dataFormatting(this.config)
this.remoteComponent = remoteVueLoader('data:text/plain,' + encodeURIComponent(this.vueContentInner))
this.loading = false
}
// 如果有组件的dirName则获取系统组件信息
if (this.$route.query?.dirName) {
const dirName = this.$route.query?.dirName
const remoteComponentList = [...innerRemoteComponents, ...getRemoteComponents()]
const config = remoteComponentList?.find(item => item.customize.vueSysComponentDirName === dirName)
this.config.option = config?.option
this.config.title = config?.title
const vueFile = config.customize?.vueFile
this.remoteComponent = vueFile
this.loading = false
}
},
// 尝试渲染远程文件或远程字符串
getRemoteComponent () {
this.loading = true
this.config = this.dataFormatting(this.config, { success: false })
this.remoteComponent = remoteVueLoader('data:text/plain,' + encodeURIComponent(this.vueContentInner))
this.loading = false
},
/**
* 组件的配置
* @returns {Promise<unknown>}
*/
// 将config.setting的配置转化为option里的配置这里之所以将转化的方法提出来是因为在改变维度指标和样式的时候都需要转化
transformSettingToOption (config, type) {
let option = null
config.setting.forEach(set => {
if (set.optionField) {
const optionField = set.optionField.split('.')
option = config.option
optionField.forEach((field, index) => {
if (index === optionField.length - 1) {
// 数据配置时,必须有值才更新
if ((set.tabName === type && type === 'data' && set.value) || (set.tabName === type && type === 'custom')) {
option[field] = set.value
}
} else {
option = option[field]
}
})
}
})
config.option = { ...config.option, ...option }
return config
},
dataFormatting (config, data) {
// 数据返回成功则赋值
if (data?.success) {
data = data.data
config = this.transformSettingToOption(config, 'data')
// 获取到后端返回的数据,有则赋值
// const option = config.option
// const setting = config.setting
if (config.dataHandler) {
try {
// 此处函数处理data
eval(config.dataHandler)
} catch (e) {
console.error(e)
}
}
config.option.data = data
} else {
// 数据返回失败则赋前端的模拟数据
config.option.data = this.plotList?.find(plot => plot.name === config.name)?.option?.data || config.option.data
}
return config
},
// 组件的样式改变返回改变后的config
changeStyle (config) {
config = { ...this.config, ...config }
config = this.transformSettingToOption(config, 'custom')
// 这里定义了option和setting是为了保证在执行eval时,optionHandler、dataHandler里面可能会用到
// const option = config.option
// const setting = config.setting
if (this.config.optionHandler) {
try {
// 此处函数处理config
eval(this.config.optionHandler)
} catch (e) {
console.error(e)
}
}
if (this.chart) {
this.chart.update(config.option)
}
this.changeChartConfig(config)
return config
}
}
}
</script>
<style lang="scss" scoped>
.bs-remote-preview {
position: absolute;
min-height: 100%;
min-width: 100%;
overflow: hidden;
box-sizing: border-box;
.remote-preview-inner-wrap {
position: absolute;
height: 100%;
width: 100%;
overflow: auto;
padding: 20px;
background-color: var(--bs-background-1);
}
}
</style>