Files
vue-desktop/src/ui/desktop-container/DesktopContainer.vue
2025-10-10 10:37:11 +08:00

256 lines
6.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="desktop-icons-container" :style="gridStyle">
<AppIcon v-for="(appIcon, i) in appIconsRef" :key="i" :iconInfo="appIcon" :gridTemplate="gridTemplate"
@dblclick="runApp(appIcon)" />
<!-- 系统状态显示 -->
<div v-if="showSystemStatus" class="system-status-overlay">
<div class="status-panel">
<h3>系统状态</h3>
<div class="status-item">
<span>运行状态:</span>
<span :class="{ 'status-ok': systemStatus.running, 'status-error': !systemStatus.running }">
{{ systemStatus.running ? '正常' : '错误' }}
</span>
</div>
<button @click="showSystemStatus = false" class="close-btn">关闭</button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { inject, ref, onMounted, onUnmounted } from 'vue'
import AppIcon from '@/ui/desktop-container/AppIcon.vue'
import type { IDesktopAppIcon } from '@/ui/types/IDesktopAppIcon.ts'
import { useDesktopContainerInit } from '@/ui/desktop-container/useDesktopContainerInit.ts'
import { useDynamicAppIcons, getAppIdFromIcon } from '@/ui/desktop-container/useDynamicAppIcons.ts'
import type { SystemServiceIntegration } from '@/services/SystemServiceIntegration'
import type { SystemStatus } from '@/services/SystemServiceIntegration'
import { appRegistry } from '@/apps'
import { externalAppDiscovery } from '@/services/ExternalAppDiscovery'
const { appIconsRef, gridStyle, gridTemplate } = useDesktopContainerInit('.desktop-icons-container')
const { getAppIconsWithPositions, saveIconPositions, refreshApps } = useDynamicAppIcons()
// 使用动态应用图标替换静态列表
const updateAppIcons = () => {
const dynamicIcons = getAppIconsWithPositions()
appIconsRef.value = dynamicIcons
}
// 初始加载应用图标
updateAppIcons()
// 注入系统服务和窗口管理器
const systemService = inject<SystemServiceIntegration>('systemService')
const windowManager = inject<any>('windowManager')
const showSystemStatus = ref(false)
const systemStatus = ref<SystemStatus>({
initialized: false,
running: false,
servicesStatus: {
windowFormService: false,
resourceService: false,
sandboxEngine: false,
lifecycleManager: false
},
uptime: 0
})
let statusUpdateInterval: number | null = null
// 更新系统状态
const updateSystemStatus = async () => {
if (!systemService) return
try {
const status = await systemService.getSystemStatus()
systemStatus.value = status
} catch (error) {
console.error('获取系统状态失败:', error)
}
}
// 运行应用
const runApp = async (appIcon: IDesktopAppIcon) => {
if (!systemService) {
console.error('系统服务未初始化')
return
}
try {
if (appIcon.name === '系统状态') {
showSystemStatus.value = true
updateSystemStatus()
} else {
const appId = getAppIdFromIcon(appIcon)
await startApp(appId)
}
} catch (error) {
console.error('启动应用失败:', error)
}
}
// 启动应用(支持内置和外部应用)
const startApp = async (appId: string) => {
if (!systemService) return
try {
const lifecycleManager = systemService.getLifecycleManager()
// 检查是否为内置应用
if (appRegistry.hasApp(appId)) {
// 内置应用:使用主应用的窗口管理器
const appRegistration = appRegistry.getApp(appId)!
// 检查是否已在运行
if (lifecycleManager.isAppRunning(appId)) {
console.log(`应用 ${appRegistration.manifest.name} 已在运行`)
return
}
// 创建窗口
const windowService = systemService.getWindowFormService()
const windowConfig = {
title: appRegistration.manifest.name,
width: appRegistration.manifest.window.width,
height: appRegistration.manifest.window.height,
minWidth: appRegistration.manifest.window.minWidth,
minHeight: appRegistration.manifest.window.minHeight,
resizable: appRegistration.manifest.window.resizable !== false
}
const windowInstance = await windowService.createWindow(appId, windowConfig)
// 使用主应用的窗口管理器来渲染内置应用
if (windowManager?.value) {
await windowManager.value.addBuiltInWindow(windowInstance.id, appId)
console.log(`[主应用] 使用窗口管理器渲染内置应用: ${appId}`)
} else {
console.error('窗口管理器未初始化')
}
} else if (externalAppDiscovery.hasApp(appId)) {
// 外置应用直接使用ApplicationLifecycleManager
console.log(`启动外置应用: ${appId}`)
if (!lifecycleManager.isAppRunning(appId)) {
await lifecycleManager.startApp(appId)
console.log(`外置应用 ${appId} 启动成功`)
} else {
console.log(`外置应用 ${appId} 已在运行`)
}
} else {
console.error(`未知的应用: ${appId}`)
}
} catch (error) {
console.error('启动应用失败:', error)
}
}
// 手动刷新应用列表(通过右键菜单调用)
const manualRefreshApps = async () => {
try {
await refreshApps()
updateAppIcons()
console.log('[DesktopContainer] 应用列表已手动刷新')
} catch (error) {
console.error('[DesktopContainer] 手动刷新应用列表失败:', error)
}
}
// 暴露手动刷新方法给父组件使用
defineExpose({
manualRefreshApps
})
// 初始化和清理
onMounted(async () => {
// 开始系统状态更新
statusUpdateInterval = setInterval(updateSystemStatus, 5000)
updateSystemStatus()
// 不再设置自动刷新定时器,只在需要时手动刷新
})
onUnmounted(() => {
if (statusUpdateInterval) {
clearInterval(statusUpdateInterval)
statusUpdateInterval = null
}
})
</script>
<style scoped>
.desktop-icons-container {
position: relative;
width: 100%;
height: 100%;
}
.system-status-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.status-panel {
background: white;
border-radius: 8px;
padding: 24px;
min-width: 300px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}
.status-panel h3 {
margin: 0 0 16px 0;
color: #333;
text-align: center;
}
.status-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid #f0f0f0;
}
.status-item:last-of-type {
border-bottom: none;
}
.status-ok {
color: #28a745;
font-weight: 500;
}
.status-error {
color: #dc3545;
font-weight: 500;
}
.close-btn {
width: 100%;
padding: 8px 16px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin-top: 16px;
transition: background 0.2s;
}
.close-btn:hover {
background: #0056b3;
}
</style>