forked from github/dataease
Merge pull request #8573 from dataease/pr@dev-v2@perf_iframe_embedded
perf: iframe嵌入式验证
This commit is contained in:
commit
34c17e4499
@ -1,77 +0,0 @@
|
||||
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, '/')
|
||||
})
|
||||
}
|
@ -1,12 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { shallowRef, defineAsyncComponent, ref, onBeforeUnmount } from 'vue'
|
||||
import { shallowRef, defineAsyncComponent, ref, onBeforeUnmount, onBeforeMount } from 'vue'
|
||||
import { debounce } from 'lodash-es'
|
||||
import { useEmbedded } from '@/store/modules/embedded'
|
||||
import { useAppStoreWithOut } from '@/store/modules/app'
|
||||
import { onBeforeMount } from 'vue'
|
||||
import { communicationInit, EmbeddedData } from '@/utils/communication'
|
||||
const embeddedStore = useEmbedded()
|
||||
const appStore = useAppStoreWithOut()
|
||||
import { XpackComponent } from '@/components/plugin'
|
||||
|
||||
const currentComponent = shallowRef()
|
||||
|
||||
@ -44,11 +39,6 @@ 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()
|
||||
})
|
||||
@ -56,9 +46,16 @@ onBeforeMount(() => {
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', setStyle)
|
||||
})
|
||||
const initIframe = (name: string) => {
|
||||
currentComponent.value = componentMap[name || 'ViewWrapper']
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<XpackComponent
|
||||
jsname="L2NvbXBvbmVudC9lbWJlZGRlZC1pZnJhbWUvRW50cmFuY2Vz"
|
||||
@init-iframe="initIframe"
|
||||
/>
|
||||
<div :style="iframeStyle">
|
||||
<component :is="currentComponent"></component>
|
||||
</div>
|
||||
|
@ -19,8 +19,8 @@ import _ from 'lodash'
|
||||
import DeResourceCreateOptV2 from '@/views/common/DeResourceCreateOptV2.vue'
|
||||
import { useCache } from '@/hooks/web/useCache'
|
||||
import { findParentIdByChildIdRecursive } from '@/utils/canvasUtils'
|
||||
import { XpackComponent } from '@/components/plugin'
|
||||
import treeSort from '@/utils/treeSortUtils'
|
||||
import { initOpenHandler } from '@/utils/communication'
|
||||
const { wsCache } = useCache()
|
||||
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
@ -296,7 +296,7 @@ const operation = (cmd: string, data: BusiTreeNode, nodeType: string) => {
|
||||
? `#/dvCanvas?opt=copy&pid=${params.pid}&dvId=${data.data}`
|
||||
: `#/dashboard?opt=copy&pid=${params.pid}&resourceId=${data.data}`
|
||||
const newWindow = window.open(baseUrl, '_blank')
|
||||
initOpenHandler(newWindow, embeddedStore.getIframeData)
|
||||
initOpenHandler(newWindow)
|
||||
})
|
||||
} else {
|
||||
resourceGroupOpt.value.optInit(nodeType, data, cmd, ['copy'].includes(cmd))
|
||||
@ -319,7 +319,7 @@ const addOperation = (
|
||||
} else {
|
||||
newWindow = window.open(baseUrl, '_blank')
|
||||
}
|
||||
initOpenHandler(newWindow, embeddedStore.getIframeData)
|
||||
initOpenHandler(newWindow)
|
||||
} else if (cmd === 'newFromTemplate') {
|
||||
// state.templateCreatePid = data?.id
|
||||
// // newFromTemplate
|
||||
@ -342,7 +342,7 @@ function createNewObject() {
|
||||
const resourceEdit = resourceId => {
|
||||
const baseUrl = curCanvasType.value === 'dataV' ? '#/dvCanvas?dvId=' : '#/dashboard?resourceId='
|
||||
const newWindow = window.open(baseUrl + resourceId, '_blank')
|
||||
initOpenHandler(newWindow, embeddedStore.getIframeData)
|
||||
initOpenHandler(newWindow)
|
||||
}
|
||||
|
||||
const resourceOptFinish = () => {
|
||||
@ -362,7 +362,7 @@ const resourceCreateFinish = templateData => {
|
||||
} else {
|
||||
newWindow = window.open(baseUrl, '_blank')
|
||||
}
|
||||
initOpenHandler(newWindow, embeddedStore.getIframeData)
|
||||
initOpenHandler(newWindow)
|
||||
}
|
||||
|
||||
const getParentKeys = (tree, targetKey, parentKeys = []) => {
|
||||
@ -399,6 +399,16 @@ watch(filterText, val => {
|
||||
resourceListTree.value.filter(val)
|
||||
})
|
||||
|
||||
const openHandler = ref(null)
|
||||
const initOpenHandler = newWindow => {
|
||||
if (openHandler?.value) {
|
||||
const pm = {
|
||||
methodName: 'initOpenHandler',
|
||||
args: newWindow
|
||||
}
|
||||
openHandler.value.invokeMethod(pm)
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
getTree()
|
||||
})
|
||||
@ -579,6 +589,7 @@ defineExpose({
|
||||
></de-resource-create-opt-v2>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<XpackComponent ref="openHandler" jsname="L2NvbXBvbmVudC9lbWJlZGRlZC1pZnJhbWUvT3BlbkhhbmRsZXI=" />
|
||||
</template>
|
||||
<style lang="less" scoped>
|
||||
.insert-filter {
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, onBeforeMount, onUnmounted, reactive, ref } from 'vue'
|
||||
import { computed, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import findComponent from '../../utils/components'
|
||||
@ -22,9 +22,7 @@ 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()
|
||||
import { XpackComponent } from '@/components/plugin'
|
||||
const interactiveStore = interactiveStoreWithOut()
|
||||
const embeddedStore = useEmbedded()
|
||||
const { wsCache } = useCache()
|
||||
@ -96,12 +94,28 @@ const onMobileConfig = () => {
|
||||
mobileConfig.value = true
|
||||
})
|
||||
}
|
||||
|
||||
const loadFinish = ref(false)
|
||||
const newWindowHandler = ref(null)
|
||||
|
||||
let p = null
|
||||
const XpackLoaded = () => {
|
||||
const pm = {
|
||||
methodName: 'newWindowReady',
|
||||
args: null
|
||||
}
|
||||
if (newWindowHandler?.value) {
|
||||
newWindowHandler.value.invokeMethod(pm)
|
||||
p(true)
|
||||
}
|
||||
}
|
||||
// 全局监听按键事件
|
||||
onBeforeMount(async () => {
|
||||
await newWindowReady((data: EmbeddedData) => {
|
||||
embeddedStore.setIframeData(data)
|
||||
appStore.setIsIframe(true)
|
||||
onMounted(async () => {
|
||||
await new Promise(r => {
|
||||
if (!newWindowHandler?.value) {
|
||||
return r(null)
|
||||
}
|
||||
p = r
|
||||
})
|
||||
loadFinish.value = true
|
||||
useEmitt({
|
||||
@ -246,6 +260,11 @@ onUnmounted(() => {
|
||||
@pcMode="mobileConfig = false"
|
||||
v-else-if="loadFinish && mobileConfig"
|
||||
></MobileConfigPanel>
|
||||
<XpackComponent
|
||||
ref="newWindowHandler"
|
||||
jsname="L2NvbXBvbmVudC9lbWJlZGRlZC1pZnJhbWUvTmV3V2luZG93SGFuZGxlcg=="
|
||||
@loaded="XpackLoaded"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
|
@ -28,9 +28,7 @@ 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()
|
||||
import { XpackComponent } from '@/components/plugin'
|
||||
const interactiveStore = interactiveStoreWithOut()
|
||||
const embeddedStore = useEmbedded()
|
||||
const { wsCache } = useCache()
|
||||
@ -200,11 +198,29 @@ const checkPer = async resourceId => {
|
||||
await interactiveStore.setInteractive(request)
|
||||
return check(wsCache.get('screen-weight'), resourceId, 4)
|
||||
}
|
||||
|
||||
const loadFinish = ref(false)
|
||||
const newWindowHandler = ref(null)
|
||||
|
||||
let p = null
|
||||
const XpackLoaded = () => {
|
||||
const pm = {
|
||||
methodName: 'newWindowReady',
|
||||
args: null
|
||||
}
|
||||
if (newWindowHandler?.value) {
|
||||
newWindowHandler.value.invokeMethod(pm)
|
||||
p(true)
|
||||
}
|
||||
}
|
||||
onMounted(async () => {
|
||||
await newWindowReady((data: EmbeddedData) => {
|
||||
embeddedStore.setIframeData(data)
|
||||
appStore.setIsIframe(true)
|
||||
await new Promise(r => {
|
||||
if (!newWindowHandler?.value) {
|
||||
return r(null)
|
||||
}
|
||||
p = r
|
||||
})
|
||||
loadFinish.value = true
|
||||
window.addEventListener('blur', releaseAttachKey)
|
||||
if (editMode.value === 'edit') {
|
||||
window.addEventListener('storage', eventCheck)
|
||||
@ -292,8 +308,9 @@ eventBus.on('handleNew', handleNew)
|
||||
<template>
|
||||
<div ref="dvLayout" class="dv-common-layout">
|
||||
<DvToolbar />
|
||||
<div class="custom-dv-divider"></div>
|
||||
<div class="custom-dv-divider" />
|
||||
<el-container
|
||||
v-if="loadFinish"
|
||||
class="dv-layout-container"
|
||||
:class="{ 'preview-layout-container': previewStatus }"
|
||||
>
|
||||
@ -369,6 +386,11 @@ eventBus.on('handleNew', handleNew)
|
||||
</div>
|
||||
</el-container>
|
||||
</div>
|
||||
<XpackComponent
|
||||
ref="newWindowHandler"
|
||||
jsname="L2NvbXBvbmVudC9lbWJlZGRlZC1pZnJhbWUvTmV3V2luZG93SGFuZGxlcg=="
|
||||
@loaded="XpackLoaded"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
|
2
de-xpack
2
de-xpack
@ -1 +1 @@
|
||||
Subproject commit c7ce3cd1164f89f42603f7e1c301df841f8d129d
|
||||
Subproject commit 6fcd9f491e16f8ea015723a5230449a12b6eec18
|
@ -4,8 +4,10 @@ import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
||||
import io.dataease.api.permissions.embedded.dto.EmbeddedCreator;
|
||||
import io.dataease.api.permissions.embedded.dto.EmbeddedEditor;
|
||||
import io.dataease.api.permissions.embedded.dto.EmbeddedOrigin;
|
||||
import io.dataease.api.permissions.embedded.dto.EmbeddedResetRequest;
|
||||
import io.dataease.api.permissions.embedded.vo.EmbeddedGridVO;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
@ -51,4 +53,8 @@ public interface EmbeddedApi {
|
||||
@Operation(summary = "嵌入式应用域名集合", hidden = true)
|
||||
@GetMapping("/domainList")
|
||||
List<String> domainList();
|
||||
|
||||
@Hidden
|
||||
@PostMapping("/initIframe")
|
||||
void initIframe(@RequestBody EmbeddedOrigin origin);
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
package io.dataease.api.permissions.embedded.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class EmbeddedOrigin implements Serializable {
|
||||
|
||||
private String token;
|
||||
|
||||
private String origin;
|
||||
}
|
@ -40,6 +40,7 @@ public class WhitelistUtils {
|
||||
"/sysParameter/requestTimeOut",
|
||||
"/setting/authentication/status",
|
||||
"/sysParameter/ui",
|
||||
"/embedded/initIframe",
|
||||
"/");
|
||||
|
||||
public static boolean match(String requestURI) {
|
||||
|
Loading…
Reference in New Issue
Block a user