feat: 微应用支持iframe模式

This commit is contained in:
kuaifan 2025-06-05 07:15:34 +08:00
parent 4c34fe9b85
commit 750d3429e0
4 changed files with 90 additions and 27 deletions

View File

@ -96,7 +96,7 @@ services:
appstore:
container_name: "dootask-appstore-${APP_ID}"
privileged: true
image: "dootask/appstore:0.1.0"
image: "dootask/appstore:0.1.1"
volumes:
- shared_data:/usr/share/dootask
- /var/run/docker.sock:/var/run/docker.sock

View File

@ -0,0 +1,67 @@
<template>
<iframe
ref="iframe"
class="micro-app-iframe"
:src="src"
sandbox="allow-scripts allow-forms allow-same-origin allow-popups allow-popups-to-escape-sandbox"/>
</template>
<style lang="scss" scoped>
.micro-app-iframe {
border: none;
width: 100%;
height: 100%;
}
</style>
<script>
export default {
name: "MicroIFrame",
props: {
name: {
type: String,
default: ''
},
url: {
type: String,
default: ''
},
},
data() {
return {
src: this.url,
}
},
mounted() {
this.$refs.iframe.addEventListener('load', this.handleLoad.bind(this))
this.$refs.iframe.addEventListener('error', this.handleError.bind(this))
},
beforeDestroy() {
this.$refs.iframe.removeEventListener('load', this.handleLoad.bind(this))
this.$refs.iframe.removeEventListener('error', this.handleError.bind(this))
},
methods: {
handleLoad(e) {
this.$emit('mounted', {
...e,
detail: {
name: this.name,
}
})
},
handleError(e) {
this.$emit('error', {
...e,
detail: {
name: this.name,
error: e,
}
})
}
}
}
</script>

View File

@ -9,17 +9,20 @@
:transparent="app.transparent"
:autoDarkTheme="app.auto_dark_theme"
:beforeClose="async () => { await onBeforeClose(app.name) }">
<MicroIFrame
v-if="app.url_type === 'iframe' && app.isOpen && app.url"
:name="app.name"
:url="app.url"
@mounted="mounted"
@error="error"/>
<micro-app
v-if="app.isOpen && app.url"
v-else-if="app.isOpen && app.url"
:name="app.name"
:url="app.url"
:keep-alive="app.keep_alive"
:disable-scopecss="app.disable_scope_css"
:data="appData(app.name)"
@created="created"
@beforemount="beforemount"
@mounted="mounted"
@unmount="unmount"
@error="error"/>
<div v-if="app.isLoading" class="micro-app-loader">
<Loading/>
@ -86,11 +89,12 @@ import emitter from "../../store/events";
import TransferDom from "../../directives/transfer-dom";
import store from "../../store";
import MicroModal from "./modal.vue";
import MicroIFrame from "./iframe.vue";
export default {
name: "MicroApps",
directives: {TransferDom},
components: {MicroModal, UserSelect},
components: {MicroModal, UserSelect, MicroIFrame},
props: {
windowType: {
@ -149,26 +153,14 @@ export default {
},
methods: {
//
created() {
},
//
beforemount() {
},
//
mounted(e) {
this.finish(e)
},
//
unmount() {
this.finish(e.detail.name)
},
//
error(e) {
this.finish(e)
this.finish(e.detail.name)
$A.modalError({
language: false,
title: this.$L('应用加载失败'),
@ -180,8 +172,8 @@ export default {
},
//
finish(e) {
const app = this.apps.find(({name}) => name == e.detail.name);
finish(name) {
const app = this.apps.find(app => app.name == name);
if (app) {
app.isLoading = false
}

View File

@ -4675,11 +4675,15 @@ export default {
if (!data.id || !data.name || !data.url) {
return
}
data.url = data.url.replace(/\{window[._]location[._](\w+)}/ig, (match, property) => {
if (property in window.location) {
return window.location[property];
}
})
data.url = data.url
.replace(/^\:(\d+)/ig, (_, port) => {
return window.location.protocol + '//' + window.location.hostname + ':' + port;
})
.replace(/\{window[._]location[._](\w+)}/ig, (_, property) => {
if (property in window.location) {
return window.location[property];
}
})
const config = {
id: data.id,
name: data.name,