整理iframe事件

This commit is contained in:
kuaifan 2022-06-11 19:35:23 +08:00
parent cae7184a7e
commit e7cb48f0b1
13 changed files with 93 additions and 63 deletions

View File

@ -70,8 +70,7 @@ class FileContent extends AbstractModel
'fullfilename' => $fullFileName 'fullfilename' => $fullFileName
]); ]);
} }
$previewType = $fileSize < 10 * 1024 * 1024 ? 'pdf' : 'image'; // 10M以下使用pdf预览模式 return Base::fillUrl("fileview/onlinePreview?url=" . urlencode(base64_encode($url)));
return Base::fillUrl("fileview/onlinePreview?url=" . urlencode(base64_encode($url)) . "&officePreviewType=" . $previewType);
} }
/** /**

View File

@ -102,7 +102,7 @@ services:
fileview: fileview:
container_name: "dootask-fileview-${APP_ID}" container_name: "dootask-fileview-${APP_ID}"
image: "kuaifan/fileview:4.1.0-SNAPSHOT-RC5" image: "kuaifan/fileview:4.1.0-SNAPSHOT-RC9"
environment: environment:
TZ: "Asia/Shanghai" TZ: "Asia/Shanghai"
KK_CONTEXT_PATH: "/fileview" KK_CONTEXT_PATH: "/fileview"

View File

@ -11,10 +11,10 @@
window.localStorage.removeItem('ui-theme-id') window.localStorage.removeItem('ui-theme-id')
} catch (e) {} } catch (e) {}
// //
window._toolbarClick = function(el, type) { window._toolbarClick = function(el, action) {
window.parent.postMessage({ window.parent.postMessage({
source: 'onlyoffice', source: 'onlyoffice',
act: type, action: action,
rect: el.getBoundingClientRect() rect: el.getBoundingClientRect()
}, "*"); }, "*");
}; };

File diff suppressed because one or more lines are too long

View File

@ -6,5 +6,5 @@
/*# sourceMappingURL=app.css.map */ /*# sourceMappingURL=app.css.map */
body{margin-top:-26px;height:calc(100% + 26px)} body .navbar.main-navbar.navbar-with-logo{height:0px}
body .settings-popup{margin-top:26px;height:calc(100% - 26px} body .page.page-with-subnavbar.page-with-logo .page-content{--f7-page-subnavbar-offset:0px}

View File

@ -7,5 +7,5 @@
/*# sourceMappingURL=app.css.map */ /*# sourceMappingURL=app.css.map */
body{margin-top:-26px;height:calc(100% + 26px)} body .navbar.main-navbar.navbar-with-logo{height:0px}
body .settings-popup{margin-top:26px;height:calc(100% - 26px} body .page.page-with-subnavbar.page-with-logo .page-content{--f7-page-subnavbar-offset:0px}

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="drawio-content"> <div class="drawio-content">
<iframe ref="myFlow" class="drawio-iframe" :src="url"></iframe> <IFrame ref="frame" class="drawio-iframe" :src="url" @on-message="onMessage"/>
<div v-if="loadIng" class="drawio-loading"><Loading/></div> <div v-if="loadIng" class="drawio-loading"><Loading/></div>
</div> </div>
</template> </template>
@ -36,9 +36,11 @@
</style> </style>
<script> <script>
import {mapState} from "vuex"; import {mapState} from "vuex";
import IFrame from "../pages/manage/components/IFrame";
export default { export default {
name: "Drawio", name: "Drawio",
components: {IFrame},
props: { props: {
value: { value: {
type: Object, type: Object,
@ -109,20 +111,15 @@ export default {
}, },
updateContent() { updateContent() {
this.$refs.myFlow.contentWindow.postMessage(JSON.stringify({ this.$refs.frame.postMessage(JSON.stringify({
action: "load", action: "load",
autosave: 1, autosave: 1,
xml: this.value.xml, xml: this.value.xml,
}), "*"); }));
}, },
handleMessage(event) { onMessage(data) {
const editWindow = this.$refs.myFlow.contentWindow; switch (data.event) {
if (event.source !== editWindow) {
return;
}
const payload = $A.jsonParse(event.data);
switch (payload.event) {
case "init": case "init":
this.loadIng = false; this.loadIng = false;
this.updateContent(); this.updateContent();
@ -130,15 +127,15 @@ export default {
case "load": case "load":
if (typeof this.value.xml === "undefined") { if (typeof this.value.xml === "undefined") {
editWindow.postMessage(JSON.stringify({ this.$refs.frame.postMessage(JSON.stringify({
action: "template" action: "template"
}), "*"); }));
} }
break; break;
case "autosave": case "autosave":
const content = { const content = {
xml: payload.xml, xml: data.xml,
} }
this.bakData = $A.jsonStringify(content); this.bakData = $A.jsonStringify(content);
this.$emit('input', content); this.$emit('input', content);

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="component-only-office"> <div class="component-only-office">
<iframe v-if="isPreviewAndMobile" ref="myPreview" class="preview-iframe" :src="mobilePreviewUrl"></iframe> <IFrame v-if="isPreviewAndMobile" class="preview-iframe" :src="mobilePreviewUrl" @on-message="onMessage"/>
<template v-else> <template v-else>
<Alert v-if="loadError" class="load-error" type="error" show-icon>{{$L('组件加载失败!')}}</Alert> <Alert v-if="loadError" class="load-error" type="error" show-icon>{{$L('组件加载失败!')}}</Alert>
<div :id="id" class="placeholder"></div> <div :id="id" class="placeholder"></div>
@ -62,9 +62,11 @@
<script> <script>
import {mapState} from "vuex"; import {mapState} from "vuex";
import IFrame from "../pages/manage/components/IFrame";
export default { export default {
name: "OnlyOffice", name: "OnlyOffice",
components: {IFrame},
props: { props: {
id: { id: {
type: String, type: String,
@ -106,7 +108,6 @@ export default {
if (this.isPreviewAndMobile) { if (this.isPreviewAndMobile) {
this.loading = true; this.loading = true;
} }
window.addEventListener('message', this.handleMessage)
}, },
@ -115,7 +116,6 @@ export default {
this.docEditor.destroyEditor(); this.docEditor.destroyEditor();
this.docEditor = null; this.docEditor = null;
} }
window.removeEventListener('message', this.handleMessage)
}, },
computed: { computed: {
@ -181,9 +181,8 @@ export default {
}, },
methods: { methods: {
handleMessage(event) { onMessage(data) {
const data = event.data; switch (data.action) {
switch (data.act) {
case 'ready': case 'ready':
this.loading = false; this.loading = false;
break break

View File

@ -1,6 +1,6 @@
<template> <template>
<div v-if="ready" class="file-content"> <div v-if="ready" class="file-content">
<iframe v-if="isPreview" ref="myPreview" class="preview-iframe" :src="previewUrl"></iframe> <IFrame v-if="isPreview" class="preview-iframe" :src="previewUrl" @on-message="onMessage"/>
<template v-else> <template v-else>
<EPopover <EPopover
v-if="['word', 'excel', 'ppt'].includes(file.type)" v-if="['word', 'excel', 'ppt'].includes(file.type)"
@ -115,6 +115,7 @@ import Vue from 'vue'
import Minder from '../../../components/Minder' import Minder from '../../../components/Minder'
import {mapState} from "vuex"; import {mapState} from "vuex";
import FileHistory from "./FileHistory"; import FileHistory from "./FileHistory";
import IFrame from "./IFrame";
Vue.use(Minder) Vue.use(Minder)
const MDEditor = () => import('../../../components/MDEditor/index'); const MDEditor = () => import('../../../components/MDEditor/index');
@ -125,7 +126,7 @@ const Drawio = () => import('../../../components/Drawio');
export default { export default {
name: "FileContent", name: "FileContent",
components: {FileHistory, AceEditor, TEditor, MDEditor, OnlyOffice, Drawio}, components: {IFrame, FileHistory, AceEditor, TEditor, MDEditor, OnlyOffice, Drawio},
props: { props: {
value: { value: {
type: Boolean, type: Boolean,
@ -167,7 +168,7 @@ export default {
mounted() { mounted() {
document.addEventListener('keydown', this.keySave) document.addEventListener('keydown', this.keySave)
window.addEventListener('message', this.handleMessage) window.addEventListener('message', this.handleOfficeMessage)
// //
if (this.$isSubElectron) { if (this.$isSubElectron) {
window.__onBeforeUnload = () => { window.__onBeforeUnload = () => {
@ -188,7 +189,7 @@ export default {
beforeDestroy() { beforeDestroy() {
document.removeEventListener('keydown', this.keySave) document.removeEventListener('keydown', this.keySave)
window.removeEventListener('message', this.handleMessage) window.removeEventListener('message', this.handleOfficeMessage)
}, },
watch: { watch: {
@ -277,8 +278,7 @@ export default {
previewUrl() { previewUrl() {
if (this.isPreview) { if (this.isPreview) {
const previewType = this.file.size < 10 * 1024 * 1024 ? 'pdf' : 'image'; // 10M使pdf return $A.apiUrl("../fileview/onlinePreview?url=" + encodeURIComponent(this.contentDetail.url))
return $A.apiUrl(`../fileview/onlinePreview?url=${encodeURIComponent(this.contentDetail.url)}&officePreviewType=${previewType}`)
} else { } else {
return ''; return '';
} }
@ -286,10 +286,9 @@ export default {
}, },
methods: { methods: {
handleMessage (event) { handleOfficeMessage({data}) {
const data = event.data;
if (data.source === 'onlyoffice') { if (data.source === 'onlyoffice') {
switch (data.act) { switch (data.action) {
case 'link': case 'link':
this.handleClick('link') this.handleClick('link')
break; break;
@ -304,9 +303,11 @@ export default {
} }
break; break;
} }
return
} }
switch (data.act) { },
onMessage(data) {
switch (data.action) {
case 'ready': case 'ready':
this.loadPreview = false; this.loadPreview = false;
break break

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="file-preview"> <div class="file-preview">
<iframe v-if="isPreview" ref="myPreview" class="preview-iframe" :src="previewUrl"></iframe> <IFrame v-if="isPreview" class="preview-iframe" :src="previewUrl" @on-message="onMessage"/>
<template v-else> <template v-else>
<div v-show="!['word', 'excel', 'ppt'].includes(file.type)" class="edit-header"> <div v-show="!['word', 'excel', 'ppt'].includes(file.type)" class="edit-header">
<div class="header-title"> <div class="header-title">
@ -11,10 +11,11 @@
<Icon v-else type="ios-refresh" @click="getContent" /> <Icon v-else type="ios-refresh" @click="getContent" />
</div> </div>
</div> </div>
<Dropdown v-if="file.type=='mind'" <Dropdown
trigger="click" v-if="file.type=='mind'"
class="header-hint" trigger="click"
@on-click="exportMenu"> class="header-hint"
@on-click="exportMenu">
<a href="javascript:void(0)">{{$L('导出')}}<Icon type="ios-arrow-down"></Icon></a> <a href="javascript:void(0)">{{$L('导出')}}<Icon type="ios-arrow-down"></Icon></a>
<DropdownMenu slot="list"> <DropdownMenu slot="list">
<DropdownItem name="png">{{$L('导出PNG图片')}}</DropdownItem> <DropdownItem name="png">{{$L('导出PNG图片')}}</DropdownItem>
@ -40,6 +41,7 @@
<script> <script>
import Vue from 'vue' import Vue from 'vue'
import Minder from '../../../components/Minder' import Minder from '../../../components/Minder'
import IFrame from "./IFrame";
Vue.use(Minder) Vue.use(Minder)
const MDPreview = () => import('../../../components/MDEditor/preview'); const MDPreview = () => import('../../../components/MDEditor/preview');
@ -50,7 +52,7 @@ const Drawio = () => import('../../../components/Drawio');
export default { export default {
name: "FilePreview", name: "FilePreview",
components: {AceEditor, TEditor, MDPreview, OnlyOffice, Drawio}, components: {IFrame, AceEditor, TEditor, MDPreview, OnlyOffice, Drawio},
props: { props: {
code: { code: {
type: String, type: String,
@ -76,13 +78,6 @@ export default {
} }
}, },
mounted() {
window.addEventListener('message', this.handleMessage)
},
beforeDestroy() {
window.removeEventListener('message', this.handleMessage)
},
watch: { watch: {
'file.id': { 'file.id': {
handler(id) { handler(id) {
@ -111,8 +106,7 @@ export default {
previewUrl() { previewUrl() {
if (this.isPreview) { if (this.isPreview) {
const previewType = this.file.size < 10 * 1024 * 1024 ? 'pdf' : 'image'; // 10M使pdf return $A.apiUrl("../fileview/onlinePreview?url=" + encodeURIComponent(this.contentDetail.url))
return $A.apiUrl(`../fileview/onlinePreview?url=${encodeURIComponent(this.contentDetail.url)}&officePreviewType=${previewType}`)
} else { } else {
return ''; return '';
} }
@ -120,9 +114,8 @@ export default {
}, },
methods: { methods: {
handleMessage (event) { onMessage(data) {
const data = event.data; switch (data.action) {
switch (data.act) {
case 'ready': case 'ready':
this.loadPreview = false; this.loadPreview = false;
break break

View File

@ -0,0 +1,43 @@
<template>
<iframe v-if="src" ref="iframe" :src="src"></iframe>
</template>
<script>
export default {
name: "IFrame",
props: {
src: {
type: String,
default: ''
},
},
mounted() {
window.addEventListener('message', this.handleMessage)
},
beforeDestroy() {
window.removeEventListener('message', this.handleMessage)
},
methods: {
handleMessage({data, source}) {
if (source !== this.$refs.iframe?.contentWindow) {
return;
}
data = $A.jsonParse(data);
if (data.source === 'fileView' && data.action === 'picture') {
this.$store.state.previewImageIndex = data.params.index;
this.$store.state.previewImageList = data.params.array;
}
this.$emit("on-message", data)
},
postMessage(message, targetOrigin = "*") {
if (this.$refs.iframe) {
this.$refs.iframe.contentWindow.postMessage(message, targetOrigin);
}
}
}
}
</script>

View File

@ -134,8 +134,7 @@ export default {
}, },
previewUrl() { previewUrl() {
const previewType = this.msgDetail.msg.size < 10 * 1024 * 1024 ? 'pdf' : 'image'; // 10M使pdf return $A.apiUrl("../fileview/onlinePreview?url=" + encodeURIComponent(this.msgDetail.content.url))
return $A.apiUrl(`../fileview/onlinePreview?url=${encodeURIComponent(this.msgDetail.content.url)}&officePreviewType=${previewType}`)
} }
}, },
methods: { methods: {

View File

@ -121,8 +121,7 @@ export default {
}, },
previewUrl() { previewUrl() {
const previewType = this.fileDetail.size < 10 * 1024 * 1024 ? 'pdf' : 'image'; // 10M使pdf return $A.apiUrl("../fileview/onlinePreview?url=" + encodeURIComponent(this.fileDetail.content.url))
return $A.apiUrl(`../fileview/onlinePreview?url=${encodeURIComponent(this.fileDetail.content.url)}&officePreviewType=${previewType}`)
} }
}, },
methods: { methods: {