Merge pull request #8549 from dataease/pr@dev-v2@perf_iframe_embedded

perf: iframe嵌入式新增资源
This commit is contained in:
fit2cloud-chenyw 2024-03-15 17:55:06 +08:00 committed by GitHub
commit d9e31523ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 143 additions and 30 deletions

View File

@ -23,7 +23,7 @@ const { start, done } = useNProgress()
const { loadStart, loadDone } = usePageLoading()
const whiteList = ['/login', '/de-link', '/chart-view'] // 不重定向白名单
const embeddedWhiteList = ['/dvCanvas', '/dashboard']
router.beforeEach(async (to, from, next) => {
start()
loadStart()
@ -99,7 +99,11 @@ router.beforeEach(async (to, from, next) => {
next(nextData)
}
} else {
if (whiteList.indexOf(to.path) !== -1 || to.path.startsWith('/de-link/')) {
if (
embeddedWhiteList.includes(to.path) ||
whiteList.indexOf(to.path) !== -1 ||
to.path.startsWith('/de-link/')
) {
permissionStore.setCurrentPath(to.path)
next()
} else {

View File

@ -48,6 +48,16 @@ export const userStore = defineStore('embedded', {
},
getResourceId(): string {
return this.resourceId
},
getIframeData(): any {
return {
embeddedToken: this.token,
busiFlag: this.busiFlag,
type: this.type,
dvId: this.dvId,
chartId: this.chartId,
pid: this.pid
}
}
},
actions: {
@ -74,6 +84,14 @@ export const userStore = defineStore('embedded', {
},
setResourceId(resourceId: string) {
this.resourceId = resourceId
},
setIframeData(data: any) {
this.type = data['type']
this.token = data['embeddedToken']
this.busiFlag = data['busiFlag']
this.dvId = data['dvId']
this.chartId = data['chartId']
this.pid = data['pid']
}
}
})

View File

@ -0,0 +1,77 @@
export interface EmbeddedData {
'de-embedded': boolean
embeddedToken?: string
busiFlag?: string
type?: string
dvId?: string
chartId?: string
pid: string
}
export const communicationInit = cb => {
window.addEventListener('message', event => {
if (!event.data['de-embedded']) {
return
}
const origin = event.origin
console.log(origin)
const embeddedData: EmbeddedData = event.data
// validate origin
if (cb) {
cb(embeddedData)
}
})
const readyData = {
ready: true,
msgOrigin: 'de-fit2cloud'
}
window.parent.postMessage(readyData, '*')
}
export const initOpenHandler = (newWindow, data) => {
if (!data.embeddedToken) {
return
}
window['uuid'] = new Date().getTime()
newWindow['uuid'] = window['uuid'] + 1
newWindow['name'] = 'de-new-resource-window'
window.addEventListener('message', event => {
if (
event.data?.msgOrigin !== 'de-inner-fit2cloud' ||
event.origin !== window.origin ||
event.source['uuid'] !== newWindow['uuid']
) {
return
}
data['de-inner-embedded'] = true
if (event.data.ready) {
newWindow.postMessage(data, '/')
}
})
}
export const newWindowReady = async cb => {
return new Promise((resolve, reject) => {
if (!window.opener || window['name'] !== 'de-new-resource-window') {
return resolve(null)
}
window.addEventListener('message', event => {
if (
!event.data['de-inner-embedded'] ||
event.origin !== window.origin ||
window['uuid'] !== event.source['uuid'] - 1
) {
return
}
if (cb) {
cb(event.data)
resolve(true)
}
})
const readyData = {
ready: true,
msgOrigin: 'de-inner-fit2cloud'
}
window.opener.postMessage(readyData, '/')
})
}

View File

@ -3,9 +3,8 @@ import { shallowRef, defineAsyncComponent, ref, onBeforeUnmount } from 'vue'
import { debounce } from 'lodash-es'
import { useEmbedded } from '@/store/modules/embedded'
import { useAppStoreWithOut } from '@/store/modules/app'
import { useRoute } from 'vue-router'
import { onBeforeMount } from 'vue'
const route = useRoute()
import { communicationInit, EmbeddedData } from '@/utils/communication'
const embeddedStore = useEmbedded()
const appStore = useAppStoreWithOut()
@ -37,21 +36,6 @@ const componentMap = {
ScreenPanel,
DashboardPanel
}
const init = () => {
appStore.setIsIframe(true)
const busiFlag = route.query.busiFlag as string
const dvId = route.query.dvId as string
const chartId = route.query.chartId as string
const type = route.query.type as string
const embeddedToken = route.query.embeddedToken as string
embeddedStore.setBusiFlag(busiFlag)
embeddedStore.setToken(embeddedToken)
embeddedStore.setChartId(chartId)
embeddedStore.setDvId(dvId)
embeddedStore.setType(type)
currentComponent.value = componentMap[type || 'ViewWrapper']
}
const iframeStyle = ref(null)
const setStyle = debounce(() => {
iframeStyle.value = {
@ -60,9 +44,13 @@ const setStyle = debounce(() => {
}
}, 300)
onBeforeMount(() => {
communicationInit((data: EmbeddedData) => {
embeddedStore.setIframeData(data)
appStore.setIsIframe(true)
currentComponent.value = componentMap[data.type || 'ViewWrapper']
})
window.addEventListener('resize', setStyle)
setStyle()
init()
})
onBeforeUnmount(() => {

View File

@ -20,6 +20,7 @@ import DeResourceCreateOpt from '@/views/common/DeResourceCreateOpt.vue'
import DeResourceCreateOptV2 from '@/views/common/DeResourceCreateOptV2.vue'
import { useCache } from '@/hooks/web/useCache'
import { findParentIdByChildIdRecursive } from '@/utils/canvasUtils'
import { initOpenHandler } from '@/utils/communication'
const { wsCache } = useCache()
const dvMainStore = dvMainStoreWithOut()
@ -275,7 +276,8 @@ const operation = (cmd: string, data: BusiTreeNode, nodeType: string) => {
curCanvasType.value === 'dataV'
? `#/dvCanvas?opt=copy&pid=${params.pid}&dvId=${data.data}`
: `#/dashboard?opt=copy&pid=${params.pid}&resourceId=${data.data}`
window.open(baseUrl, '_blank')
const newWindow = window.open(baseUrl, '_blank')
initOpenHandler(newWindow, embeddedStore.getIframeData)
})
} else {
resourceGroupOpt.value.optInit(nodeType, data, cmd, ['copy'].includes(cmd))
@ -292,11 +294,13 @@ const addOperation = (
if (cmd === 'newLeaf') {
const baseUrl =
curCanvasType.value === 'dataV' ? '#/dvCanvas?opt=create' : '#/dashboard?opt=create'
let newWindow = null
if (data?.id) {
window.open(baseUrl + `&pid=${data.id}`, '_blank')
newWindow = window.open(baseUrl + `&pid=${data.id}`, '_blank')
} else {
window.open(baseUrl, '_blank')
newWindow = window.open(baseUrl, '_blank')
}
initOpenHandler(newWindow, embeddedStore.getIframeData)
} else if (cmd === 'newFromTemplate') {
// state.templateCreatePid = data?.id
// // newFromTemplate
@ -318,7 +322,8 @@ function createNewObject() {
const resourceEdit = resourceId => {
const baseUrl = curCanvasType.value === 'dataV' ? '#/dvCanvas?dvId=' : '#/dashboard?resourceId='
window.open(baseUrl + resourceId, '_blank')
const newWindow = window.open(baseUrl + resourceId, '_blank')
initOpenHandler(newWindow, embeddedStore.getIframeData)
}
const resourceOptFinish = () => {
@ -332,11 +337,13 @@ const resourceCreateFinish = templateData => {
curCanvasType.value === 'dataV'
? '#/dvCanvas?opt=create&createType=template'
: '#/dashboard?opt=create&createType=template'
let newWindow = null
if (state.templateCreatePid) {
window.open(baseUrl + `&pid=${state.templateCreatePid}`, '_blank')
newWindow = window.open(baseUrl + `&pid=${state.templateCreatePid}`, '_blank')
} else {
window.open(baseUrl, '_blank')
newWindow = window.open(baseUrl, '_blank')
}
initOpenHandler(newWindow, embeddedStore.getIframeData)
}
const getParentKeys = (tree, targetKey, parentKeys = []) => {

View File

@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'
import { computed, nextTick, onBeforeMount, onUnmounted, reactive, ref } from 'vue'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia'
import findComponent from '../../utils/components'
@ -22,6 +22,9 @@ import { useEmbedded } from '@/store/modules/embedded'
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
import { interactiveStoreWithOut } from '@/store/modules/interactive'
import { watermarkFind } from '@/api/watermark'
import { newWindowReady, EmbeddedData } from '@/utils/communication'
import { useAppStoreWithOut } from '@/store/modules/app'
const appStore = useAppStoreWithOut()
const interactiveStore = interactiveStoreWithOut()
const embeddedStore = useEmbedded()
const { wsCache } = useCache()
@ -93,8 +96,14 @@ const onMobileConfig = () => {
mobileConfig.value = true
})
}
const loadFinish = ref(false)
//
onMounted(async () => {
onBeforeMount(async () => {
await newWindowReady((data: EmbeddedData) => {
embeddedStore.setIframeData(data)
appStore.setIsIframe(true)
})
loadFinish.value = true
useEmitt({
name: 'mobileConfig',
callback: () => {
@ -167,7 +176,7 @@ onUnmounted(() => {
</script>
<template>
<div class="dv-common-layout dv-teleport-query" v-if="!mobileConfig">
<div class="dv-common-layout dv-teleport-query" v-if="loadFinish && !mobileConfig">
<DbToolbar />
<el-container
class="dv-layout-container"
@ -233,7 +242,10 @@ onUnmounted(() => {
</dv-sidebar>
</el-container>
</div>
<MobileConfigPanel @pcMode="mobileConfig = false" v-else></MobileConfigPanel>
<MobileConfigPanel
@pcMode="mobileConfig = false"
v-else-if="loadFinish && mobileConfig"
></MobileConfigPanel>
</template>
<style lang="less">

View File

@ -28,6 +28,9 @@ import { useCache } from '@/hooks/web/useCache'
import RealTimeListTree from '@/components/data-visualization/RealTimeListTree.vue'
import { interactiveStoreWithOut } from '@/store/modules/interactive'
import { watermarkFind } from '@/api/watermark'
import { newWindowReady, EmbeddedData } from '@/utils/communication'
import { useAppStoreWithOut } from '@/store/modules/app'
const appStore = useAppStoreWithOut()
const interactiveStore = interactiveStoreWithOut()
const embeddedStore = useEmbedded()
const { wsCache } = useCache()
@ -198,6 +201,10 @@ const checkPer = async resourceId => {
return check(wsCache.get('screen-weight'), resourceId, 4)
}
onMounted(async () => {
await newWindowReady((data: EmbeddedData) => {
embeddedStore.setIframeData(data)
appStore.setIsIframe(true)
})
window.addEventListener('blur', releaseAttachKey)
if (editMode.value === 'edit') {
window.addEventListener('storage', eventCheck)