256 lines
6.8 KiB
Vue
256 lines
6.8 KiB
Vue
<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> |