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.

195 lines
5.8 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div
v-loading="loading"
class="bs-remote-wrap"
element-loading-text="..."
>
<component
:is="remoteComponent"
:config="config"
@linkage="linkEvent"
/>
</div>
</template>
<script>
import linkageMixins from 'packages/js/mixins/linkageMixins'
import commonMixins from 'packages/js/mixins/commonMixins'
import remoteVueLoader from 'remote-vue2-loader'
import { mapMutations, mapState } from 'vuex'
import _ from 'lodash'
import innerRemoteComponents, { getRemoteComponents } from 'packages/RemoteComponents/remoteComponentsList'
import { getBizComponentInfo } from 'packages/js/api/bigScreenApi'
export default {
name: 'LcdpRemoteComponent',
mixins: [linkageMixins, commonMixins],
props: {
config: {
type: Object,
default: () => ({})
}
},
computed: {
...mapState('bigScreen', {
pageInfo: state => state.pageInfo,
customTheme: state => state.pageInfo.pageConfig.customTheme
}),
isPreview () {
return (this.$route.path === window?.BS_CONFIG?.routers?.previewUrl) || (this.$route.path === '/big-screen/preview')
}
},
data () {
return {
loading: false,
remoteComponent: null
}
},
created () {
this.getRemoteComponent()
},
mounted () {
this.chartInit()
},
methods: {
...mapMutations('bigScreen', ['changeChartConfig']),
// 尝试渲染远程文件或远程字符串
getRemoteComponent () {
this.loading = true
// 1. 系统组件 通过配置获取
if (this.config.customize.vueSysComponentDirName) {
const remoteComponentList = [...innerRemoteComponents, ...getRemoteComponents()]
// 获得系统组件最新的配置, 同步
const config = remoteComponentList?.find(item => item.customize.vueSysComponentDirName === this.config.customize.vueSysComponentDirName)
const vueFile = config?.customize?.vueFile
const option = config?.option
const setting = config?.setting
// 同步配置
this.synchConfig(option, setting)
this.remoteComponent = vueFile
this.loading = false
return
}
// 2. 业务组件 通过请求获取
if (this.config.customize.vueBizComponentCode) {
getBizComponentInfo(this.config.customize.vueBizComponentCode).then(data => {
const vueContent = data.vueContent
const settingContent = data.settingContent
if (!this.config?.option?.data) {
this.resolveStrSetting(settingContent)
this.config = this.buildOption(this.config, { success: false })
}
this.remoteComponent = remoteVueLoader('data:text/plain,' + encodeURIComponent(vueContent))
}).finally(() => {
this.loading = false
})
}
},
chartInit () {
// key和code相等说明是一进来刷新调用/chart/data/list
if (this.config.code === this.config.key || this.isPreview) {
// 再根据数据更新组件
this.updateChart()
}
},
linkEvent (formData) {
this.linkage(formData)
},
/**
* 处理当前组件的字符串配置
*/
resolveStrSetting (settingContent) {
// 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
settingContent = settingContent.replaceAll('const ', '')
// 去掉 export default及后面代码
settingContent = settingContent.replace(/export default[\s\S]*/, '')
eval(settingContent)
this.config.option = {
...this.config.option,
...option
}
this.config.setting = setting
return {
option,
setting
}
},
/**
* @description: 只更新数据
*/
updateData () {
this.updateChart()
},
/**
* 更新组件
*/
updateChart () {
if (this.isPreview) {
this.getCurrentOption().then(({ data, config }) => {
if (data.success) {
// 成功后更新数据
config = this.buildOption(config, data)
this.changeChartConfig(config)
}
})
} else {
this.updateChartData(this.config)
}
},
/**
* 组件的配置
* @returns {Promise<unknown>}
*/
buildOption (config, data) {
config = _.cloneDeep(config)
// 遍历config.setting将config.setting中的值赋值给config.option中对应的optionField
config.setting.forEach(set => {
if (set.optionField) {
const optionField = set.optionField.split('.')
let option = config.option
optionField.forEach((field, index) => {
if (index === optionField.length - 1) {
// 数据配置时,必须有值才更新
if ((set.tabName === 'data' && set.value) || set.tabName === 'custom') {
option[field] = set.value
}
} else {
option = option[field]
}
})
}
})
// eslint-disable-next-line no-unused-vars
const option = config.option
// eslint-disable-next-line no-unused-vars
const setting = config.setting
if (data?.success) {
data = data.data
config.option = option
config.option.data = data
}
return config
},
// 同步配置
synchConfig (option, setting) {
// 对比this.config.setting 和 setting进行合并数据以this.config.option对象的value为准
// TODO
}
}
}
</script>
<style lang="scss" scoped>
.bs-remote-wrap {
width: 100%;
}
</style>