Files
vue-desktop/src/ui/components/WindowManager.vue
2025-09-25 15:31:11 +08:00

150 lines
3.9 KiB
Vue

<template>
<div class="window-manager">
<!-- 所有已打开的内置应用窗口 -->
<teleport
v-for="window in builtInWindows"
:key="window.id"
:to="`#app-container-${window.appId}`"
>
<component
:is="window.component"
:key="window.id"
v-bind="window.props"
@close="closeWindow(window.id)"
/>
</teleport>
</div>
</template>
<script setup lang="ts">
import { ref, inject, onMounted, onUnmounted } from 'vue'
import type { SystemServiceIntegration } from '@/services/SystemServiceIntegration'
import { appRegistry } from '@/apps'
interface BuiltInWindow {
id: string
appId: string
component: any
props: Record<string, any>
}
// 存储所有已打开的内置应用窗口
const builtInWindows = ref<BuiltInWindow[]>([])
// 注入系统服务
const systemService = inject<SystemServiceIntegration>('systemService')
// 添加内置应用窗口
const addBuiltInWindow = async (windowId: string, appId: string) => {
// 检查应用是否存在
const appRegistration = appRegistry.getApp(appId)
if (!appRegistration) {
console.error(`内置应用 ${appId} 不存在`)
return
}
// 检查窗口是否已存在
const existingWindow = builtInWindows.value.find(w => w.id === windowId)
if (existingWindow) {
console.warn(`窗口 ${windowId} 已存在`)
return
}
// 处理异步组件加载
let component = appRegistration.component
if (typeof component === 'function') {
try {
// 如果是函数,调用它来获取组件
component = await component()
} catch (error) {
console.error(`加载应用组件失败: ${appId}`, error)
return
}
}
// 添加窗口
const window: BuiltInWindow = {
id: windowId,
appId,
component,
props: {
windowId,
appId
}
}
builtInWindows.value.push(window)
console.log(`[WindowManager] 添加内置应用窗口: ${appId} (${windowId})`)
}
// 关闭内置应用窗口
const closeWindow = (windowId: string) => {
const index = builtInWindows.value.findIndex(w => w.id === windowId)
if (index > -1) {
const window = builtInWindows.value[index]
builtInWindows.value.splice(index, 1)
console.log(`[WindowManager] 关闭内置应用窗口: ${window.appId} (${windowId})`)
// 通知系统服务关闭窗口
if (systemService) {
const windowService = systemService.getWindowService()
windowService.destroyWindow(windowId)
}
}
}
// 移除内置应用窗口(不关闭系统窗口)
const removeBuiltInWindow = (windowId: string) => {
const index = builtInWindows.value.findIndex(w => w.id === windowId)
if (index > -1) {
const window = builtInWindows.value[index]
builtInWindows.value.splice(index, 1)
console.log(`[WindowManager] 移除内置应用窗口: ${window.appId} (${windowId})`)
}
}
// 监听窗口事件
let eventUnsubscriber: (() => void) | null = null
onMounted(() => {
if (systemService) {
const eventService = systemService.getEventService()
// 监听内置应用窗口创建事件
const subscriberId = eventService.subscribe('system', 'built-in-window-created', async (message) => {
const { windowId, appId } = message.payload
await addBuiltInWindow(windowId, appId)
})
// 监听内置应用窗口关闭事件
const closeSubscriberId = eventService.subscribe('system', 'built-in-window-closed', (message) => {
const { windowId } = message.payload
removeBuiltInWindow(windowId)
})
eventUnsubscriber = () => {
eventService.unsubscribe(subscriberId)
eventService.unsubscribe(closeSubscriberId)
}
}
})
onUnmounted(() => {
if (eventUnsubscriber) {
eventUnsubscriber()
}
})
// 暴露给全局使用
defineExpose({
addBuiltInWindow,
removeBuiltInWindow,
closeWindow
})
</script>
<style scoped>
.window-manager {
/* 这个组件本身不需要样式,它只是用来管理 teleport */
}
</style>