Files
vue-desktop/src/services/SystemServiceIntegration.ts

764 lines
20 KiB
TypeScript
Raw Normal View History

2025-09-24 16:43:10 +08:00
import { reactive, ref } from 'vue'
import { EventBuilderImpl } from '@/events/impl/EventBuilderImpl'
2025-10-10 10:28:36 +08:00
import type { IEventBuilder, IEventMap, WindowFormDataUpdateParams } from '@/events/IEventBuilder'
2025-09-28 12:34:28 +08:00
import type { ResourceType } from './ResourceService'
2025-09-24 16:43:10 +08:00
// 导入所有服务
import { WindowService } from './WindowService'
import { ResourceService } from './ResourceService'
import { ApplicationSandboxEngine } from './ApplicationSandboxEngine'
import { ApplicationLifecycleManager } from './ApplicationLifecycleManager'
import { externalAppDiscovery } from './ExternalAppDiscovery'
2025-09-28 12:05:59 +08:00
2025-09-24 16:43:10 +08:00
/**
*
*/
export interface SystemServiceConfig {
2025-10-10 10:08:05 +08:00
debug?: boolean // 是否开启调试模式
autoCleanup?: boolean // 是否自动清理
cleanupInterval?: number // 自动清理间隔
2025-09-24 16:43:10 +08:00
}
/**
*
*/
export interface SystemStatus {
2025-10-10 10:08:05 +08:00
initialized: boolean // 系统是否初始化完成
running: boolean // 系统是否运行中
2025-09-24 16:43:10 +08:00
servicesStatus: {
2025-10-10 10:08:05 +08:00
windowService: boolean // 窗体服务是否启动
resourceService: boolean // 资源服务是否启动
sandboxEngine: boolean // 沙箱引擎是否启动
lifecycleManager: boolean // 生命周期管理器是否启动
2025-09-24 16:43:10 +08:00
}
2025-10-10 10:08:05 +08:00
uptime: number // 系统运行时间
lastError?: string // 最后一次错误
2025-09-24 16:43:10 +08:00
}
/**
* SDK调用接口
*/
export interface SDKCall {
requestId: string
method: string
data?: any
appId: string
}
/**
*
*
*/
export class SystemServiceIntegration {
private initialized = ref(false)
private running = ref(false)
private config: SystemServiceConfig
private startTime: Date
// 核心服务实例
2025-10-10 10:28:36 +08:00
private eventBus: IEventBuilder<any>
2025-09-24 16:43:10 +08:00
private windowService!: WindowService
private resourceService!: ResourceService
private sandboxEngine!: ApplicationSandboxEngine
private lifecycleManager!: ApplicationLifecycleManager
// 系统状态
private systemStatus = reactive<SystemStatus>({
initialized: false,
running: false,
servicesStatus: {
windowService: false,
resourceService: false,
sandboxEngine: false,
2025-10-10 10:08:05 +08:00
lifecycleManager: false
2025-09-24 16:43:10 +08:00
},
2025-10-10 10:08:05 +08:00
uptime: 0
2025-09-24 16:43:10 +08:00
})
// 性能监控
private cleanupInterval: number | null = null
private performanceInterval: number | null = null
constructor(config: SystemServiceConfig = {}) {
this.config = {
debug: false,
autoCleanup: true,
cleanupInterval: 5 * 60 * 1000, // 5分钟
2025-10-10 10:08:05 +08:00
...config
2025-09-24 16:43:10 +08:00
}
this.startTime = new Date()
2025-10-10 10:28:36 +08:00
this.eventBus = new EventBuilderImpl<any>()
2025-09-24 16:43:10 +08:00
this.setupGlobalErrorHandling()
}
/**
*
*/
2025-10-10 10:28:36 +08:00
private async initialize(): Promise<void> {
2025-09-24 16:43:10 +08:00
if (this.initialized.value) {
throw new Error('系统服务已初始化')
}
try {
console.log('开始初始化系统服务...')
// 按依赖顺序初始化服务
await this.initializeServices()
// 设置服务间通信
this.setupServiceCommunication()
// 设置SDK消息处理
this.setupSDKMessageHandling()
// 启动自动清理
if (this.config.autoCleanup) {
this.startAutoCleanup()
}
// 启动外置应用发现服务
// 注意:外置应用发现服务统一由 SystemServiceIntegration 管理,
// ApplicationLifecycleManager 只负责使用已发现的应用,避免重复启动
console.log('启动外置应用发现服务...')
await externalAppDiscovery.startDiscovery()
this.initialized.value = true
this.running.value = true
this.systemStatus.initialized = true
this.systemStatus.running = true
console.log('系统服务初始化完成')
} catch (error) {
console.error('系统服务初始化失败:', error)
this.systemStatus.lastError = error instanceof Error ? error.message : String(error)
throw error
}
}
/**
*
*/
getSystemStatus(): SystemStatus {
return { ...this.systemStatus }
}
/**
*
*/
getWindowService(): WindowService {
this.checkInitialized()
return this.windowService
}
/**
*
*/
getResourceService(): ResourceService {
this.checkInitialized()
return this.resourceService
}
/**
*
*/
getSandboxEngine(): ApplicationSandboxEngine {
this.checkInitialized()
return this.sandboxEngine
}
/**
*
*/
getLifecycleManager(): ApplicationLifecycleManager {
this.checkInitialized()
return this.lifecycleManager
}
/**
* SDK调用
*/
async handleSDKCall(call: SDKCall): Promise<any> {
this.checkInitialized()
const { requestId, method, data, appId } = call
try {
this.debugLog(`处理SDK调用: ${method}`, { appId, data })
const result = await this.executeSDKMethod(method, data, appId)
return {
success: true,
data: result,
2025-10-10 10:08:05 +08:00
requestId
2025-09-24 16:43:10 +08:00
}
} catch (error) {
console.error('SDK调用失败:', error)
return {
success: false,
error: error instanceof Error ? error.message : String(error),
2025-10-10 10:08:05 +08:00
requestId
2025-09-24 16:43:10 +08:00
}
}
}
/**
*
*/
async restart(): Promise<void> {
console.log('重启系统服务...')
await this.shutdown()
await new Promise((resolve) => setTimeout(resolve, 1000))
await this.initialize()
console.log('系统服务重启完成')
}
/**
*
*/
2025-10-10 10:28:36 +08:00
private async shutdown(): Promise<void> {
2025-09-24 16:43:10 +08:00
console.log('关闭系统服务...')
this.running.value = false
this.systemStatus.running = false
// 停止定时器
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval)
this.cleanupInterval = null
}
if (this.performanceInterval) {
clearInterval(this.performanceInterval)
this.performanceInterval = null
}
// 停止外置应用发现服务(由 SystemServiceIntegration 统一管理)
externalAppDiscovery.stopDiscovery()
// 按相反顺序关闭服务
try {
if (this.lifecycleManager) {
// 停止所有运行中的应用
const runningApps = this.lifecycleManager.getRunningApps()
for (const app of runningApps) {
await this.lifecycleManager.stopApp(app.id)
}
}
if (this.sandboxEngine) {
this.sandboxEngine.destroy()
}
if (this.windowService) {
// 关闭所有窗体
const windows = this.windowService.getAllWindows()
for (const window of windows) {
await this.windowService.destroyWindow(window.id)
}
}
} catch (error) {
console.error('关闭服务时发生错误:', error)
}
this.initialized.value = false
this.systemStatus.initialized = false
console.log('系统服务已关闭')
}
/**
*
*/
private async initializeServices(): Promise<void> {
// 1. 初始化资源服务
console.log('初始化资源服务...')
this.resourceService = new ResourceService(this.eventBus)
this.systemStatus.servicesStatus.resourceService = true
// 3. 初始化窗体服务
console.log('初始化窗体服务...')
this.windowService = new WindowService(this.eventBus)
this.systemStatus.servicesStatus.windowService = true
// 4. 初始化沙箱引擎
console.log('初始化沙箱引擎...')
2025-10-10 10:28:36 +08:00
this.sandboxEngine = new ApplicationSandboxEngine(this.resourceService)
2025-09-24 16:43:10 +08:00
this.systemStatus.servicesStatus.sandboxEngine = true
// 5. 初始化生命周期管理器
console.log('初始化生命周期管理器...')
this.lifecycleManager = new ApplicationLifecycleManager(
this.windowService,
this.resourceService,
2025-10-10 10:08:05 +08:00
this.sandboxEngine
2025-09-24 16:43:10 +08:00
)
this.systemStatus.servicesStatus.lifecycleManager = true
}
/**
*
*/
private setupServiceCommunication(): void {
// 监听窗体状态变化(来自 WindowService 的 onStateChange 事件)
this.eventBus.addEventListener(
2025-09-28 12:34:28 +08:00
'onWindowStateChanged',
2025-09-24 16:43:10 +08:00
(windowId: string, newState: string, oldState: string) => {
console.log(
2025-10-10 10:08:05 +08:00
`[SystemIntegration] 接收到窗体状态变化事件: ${windowId} ${oldState} -> ${newState}`
2025-09-24 16:43:10 +08:00
)
2025-10-10 10:08:05 +08:00
}
2025-09-24 16:43:10 +08:00
)
// 监听窗体关闭事件,自动停止对应的应用
2025-09-28 12:34:28 +08:00
this.eventBus.addEventListener('onWindowClose', async (windowId: string) => {
2025-09-24 16:43:10 +08:00
console.log(`[SystemIntegration] 接收到窗体关闭事件: ${windowId}`)
// 查找对应的应用
const runningApps = this.lifecycleManager.getRunningApps()
for (const app of runningApps) {
if (app.windowId === windowId) {
try {
console.log(`窗口关闭,自动停止应用: ${app.id}`)
await this.lifecycleManager.stopApp(app.id)
} catch (error) {
console.error(`停止应用 ${app.id} 失败:`, error)
}
break
}
}
})
2025-09-25 13:36:38 +08:00
// 监听窗体数据更新事件
2025-09-28 14:32:07 +08:00
this.eventBus.addEventListener('onWindowFormDataUpdate', (data: WindowFormDataUpdateParams) => {
console.log(`[SystemIntegration] 接收到窗体数据更新事件:`, data)
})
2025-09-25 13:36:38 +08:00
// 监听窗体调整尺寸开始事件
2025-09-28 12:34:28 +08:00
this.eventBus.addEventListener('onWindowFormResizeStart', (windowId: string) => {
2025-09-25 13:36:38 +08:00
console.log(`[SystemIntegration] 接收到窗体调整尺寸开始事件: ${windowId}`)
})
// 监听窗体调整尺寸过程中事件
this.eventBus.addEventListener(
2025-09-28 12:34:28 +08:00
'onWindowFormResizing',
2025-09-25 13:36:38 +08:00
(windowId: string, width: number, height: number) => {
console.log(`[SystemIntegration] 接收到窗体调整尺寸过程中事件: ${windowId}`, {
width,
2025-10-10 10:08:05 +08:00
height
2025-09-25 13:36:38 +08:00
})
2025-10-10 10:08:05 +08:00
}
2025-09-25 13:36:38 +08:00
)
// 监听窗体调整尺寸结束事件
2025-09-28 12:34:28 +08:00
this.eventBus.addEventListener('onWindowFormResizeEnd', (windowId: string) => {
2025-09-25 13:36:38 +08:00
console.log(`[SystemIntegration] 接收到窗体调整尺寸结束事件: ${windowId}`)
})
2025-09-24 16:43:10 +08:00
}
/**
* SDK消息处理
*/
private setupSDKMessageHandling(): void {
// 监听来自iframe的SDK调用
window.addEventListener('message', async (event) => {
const data = event.data
if (!data) return
// 处理安全存储消息
if (data.type?.startsWith('sdk:storage:')) {
await this.handleStorageMessage(event)
return
}
// 处理其他SDK调用
if (data.type === 'sdk:call') {
const call: SDKCall = data
const result = await this.handleSDKCall(call)
// 发送响应回iframe
const iframe = this.findIframeBySource(event.source as Window)
if (iframe) {
iframe.contentWindow?.postMessage(
{
type: 'system:response',
2025-10-10 10:08:05 +08:00
...result
2025-09-24 16:43:10 +08:00
},
2025-10-10 10:08:05 +08:00
'*'
2025-09-24 16:43:10 +08:00
)
}
}
})
}
/**
*
*/
private async handleStorageMessage(event: MessageEvent): Promise<void> {
const { type, requestId, appId, key, value } = event.data
if (!requestId || !appId) {
console.warn('存储消息缺少必需参数')
return
}
// 验证应用权限
const app = this.lifecycleManager.getApp(appId)
if (!app) {
console.warn(`未找到应用: ${appId}`)
return
}
let result: any = null
let success = false
try {
switch (type) {
case 'sdk:storage:get':
result = await this.resourceService.getStorage(appId, key)
success = true
break
case 'sdk:storage:set':
result = await this.resourceService.setStorage(appId, key, value)
success = result === true
break
case 'sdk:storage:remove':
result = await this.resourceService.removeStorage(appId, key)
success = result === true
break
default:
console.warn(`未知的存储操作: ${type}`)
return
}
} catch (error) {
console.error('存储操作失败:', error)
success = false
}
// 发送响应回iframe
const iframe = this.findIframeBySource(event.source as Window)
if (iframe?.contentWindow) {
iframe.contentWindow.postMessage(
{
type: 'system:storage-response',
requestId,
result,
2025-10-10 10:08:05 +08:00
success
2025-09-24 16:43:10 +08:00
},
2025-10-10 10:08:05 +08:00
'*'
2025-09-24 16:43:10 +08:00
)
}
}
/**
* SDK方法
*/
private async executeSDKMethod(method: string, data: any, appId: string): Promise<any> {
const [service, action] = method.split('.')
switch (service) {
case 'window':
return this.executeWindowMethod(action, data, appId)
case 'storage':
return this.executeStorageMethod(action, data, appId)
case 'network':
return this.executeNetworkMethod(action, data, appId)
case 'events':
return this.executeEventMethod(action, data, appId)
case 'ui':
return this.executeUIMethod(action, data, appId)
case 'system':
return this.executeSystemMethod(action, data, appId)
case 'sdk':
return this.executeSDKMethod(action, data, appId)
default:
throw new Error(`未知的服务: ${service}`)
}
}
/**
*
*/
private async executeWindowMethod(action: string, data: any, appId: string): Promise<any> {
// 查找应用的窗体
const app = this.lifecycleManager.getApp(appId)
if (!app?.windowId) {
throw new Error('应用窗体不存在')
}
const windowId = app.windowId
switch (action) {
case 'setTitle':
return this.windowService.setWindowTitle(windowId, data.title)
case 'resize':
return this.windowService.setWindowSize(windowId, data.width, data.height)
case 'move':
2025-09-25 13:36:38 +08:00
// 实现窗体移动功能
2025-09-28 12:05:59 +08:00
const window = this.windowService.getWindow(windowId)
2025-09-25 13:36:38 +08:00
if (window && window.element) {
// 更新窗体位置
2025-09-28 12:05:59 +08:00
window.config.x = data.x
window.config.y = data.y
window.element.style.left = `${data.x}px`
window.element.style.top = `${data.y}px`
window.element.style.transform = 'none' // 确保移除transform
return true
2025-09-25 13:36:38 +08:00
}
2025-09-28 12:05:59 +08:00
return false
2025-09-24 16:43:10 +08:00
case 'minimize':
return this.windowService.minimizeWindow(windowId)
case 'maximize':
return this.windowService.maximizeWindow(windowId)
case 'restore':
return this.windowService.restoreWindow(windowId)
case 'close':
return this.lifecycleManager.stopApp(appId)
case 'getState':
2025-09-25 13:36:38 +08:00
const windowInfo = this.windowService.getWindow(windowId)
return windowInfo?.state
2025-09-24 16:43:10 +08:00
case 'getSize':
2025-09-25 13:36:38 +08:00
const windowData = this.windowService.getWindow(windowId)
2025-09-24 16:43:10 +08:00
return {
2025-09-25 13:36:38 +08:00
width: windowData?.config.width,
2025-10-10 10:08:05 +08:00
height: windowData?.config.height
2025-09-24 16:43:10 +08:00
}
default:
throw new Error(`未知的窗体操作: ${action}`)
}
}
/**
*
*/
private async executeStorageMethod(action: string, data: any, appId: string): Promise<any> {
switch (action) {
case 'set':
return this.resourceService.setStorage(appId, data.key, data.value)
case 'get':
return this.resourceService.getStorage(appId, data.key)
case 'remove':
return this.resourceService.removeStorage(appId, data.key)
case 'clear':
return this.resourceService.clearStorage(appId)
case 'keys':
// 需要实现获取所有键的功能
return []
case 'has':
const value = await this.resourceService.getStorage(appId, data.key)
return value !== null
case 'getStats':
return this.resourceService.getStorageUsage(appId)
default:
throw new Error(`未知的存储操作: ${action}`)
}
}
/**
*
*/
private async executeNetworkMethod(action: string, data: any, appId: string): Promise<any> {
switch (action) {
case 'request':
const response = await this.resourceService.makeNetworkRequest(appId, data.url, data.config)
return response
? {
data: await response.text(),
status: response.status,
statusText: response.statusText,
headers: {} as Record<string, string>, // 简化headers处理
2025-10-10 10:08:05 +08:00
url: response.url
2025-09-24 16:43:10 +08:00
}
: null
case 'isOnline':
return navigator.onLine
case 'getStats':
const requests = this.resourceService.getNetworkRequests(appId)
return {
requestCount: requests.length,
failureCount: requests.filter((r) => r.status && r.status >= 400).length,
2025-10-10 10:08:05 +08:00
averageTime: 0 // 需要实现时间统计
2025-09-24 16:43:10 +08:00
}
default:
throw new Error(`未知的网络操作: ${action}`)
}
}
/**
*
*/
private async executeEventMethod(action: string, data: any, appId: string): Promise<any> {
2025-10-10 10:28:36 +08:00
throw new Error('事件服务已被移除')
2025-09-24 16:43:10 +08:00
}
/**
* UI相关方法
*/
private async executeUIMethod(action: string, data: any, appId: string): Promise<any> {
switch (action) {
case 'showNotification':
return this.resourceService.showNotification(appId, data.title, data)
case 'showToast':
// 需要实现Toast功能
console.log(`[Toast] ${data.message}`)
return 'toast-' + Date.now()
default:
throw new Error(`未知的UI操作: ${action}`)
}
}
/**
*
*/
private async executeSystemMethod(action: string, data: any, appId: string): Promise<any> {
switch (action) {
case 'getSystemInfo':
return {
platform: navigator.platform,
userAgent: navigator.userAgent,
language: navigator.language,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
screenResolution: {
width: screen.width,
2025-10-10 10:08:05 +08:00
height: screen.height
2025-09-24 16:43:10 +08:00
},
colorDepth: screen.colorDepth,
2025-10-10 10:08:05 +08:00
pixelRatio: window.devicePixelRatio
2025-09-24 16:43:10 +08:00
}
case 'getAppInfo':
const app = this.lifecycleManager.getApp(appId)
return app
? {
id: app.id,
name: app.manifest.name,
version: app.version,
permissions: app.manifest.permissions,
createdAt: app.installedAt,
2025-10-10 10:08:05 +08:00
lastActiveAt: app.lastActiveAt
2025-09-24 16:43:10 +08:00
}
: null
case 'getClipboard':
return this.resourceService.getClipboard(appId)
case 'setClipboard':
return this.resourceService.setClipboard(appId, data.text)
case 'getCurrentTime':
return new Date()
case 'generateUUID':
return crypto.randomUUID()
default:
throw new Error(`未知的系统操作: ${action}`)
}
}
/**
* iframe
*/
private findIframeBySource(source: Window): HTMLIFrameElement | null {
const iframes = Array.from(document.querySelectorAll('iframe'))
for (const iframe of iframes) {
if (iframe.contentWindow === source) {
return iframe
}
}
return null
}
/**
*
*/
private startAutoCleanup(): void {
2025-10-10 10:28:36 +08:00
if (!this.config.cleanupInterval) return
2025-09-24 16:43:10 +08:00
this.cleanupInterval = setInterval(() => {
this.debugLog('执行自动清理...')
2025-10-10 10:28:36 +08:00
// 移除资源服务清理(方法不存在)
// this.resourceService.cleanup()
// 移除事件服务清理
// this.eventService.cleanup()
2025-09-24 16:43:10 +08:00
// 清理沙箱引擎缓存
// this.sandboxEngine.cleanup()
this.debugLog('自动清理完成')
}, this.config.cleanupInterval!)
}
/**
*
*/
private checkInitialized(): void {
if (!this.initialized.value) {
throw new Error('系统服务未初始化')
}
}
/**
*
*/
private setupGlobalErrorHandling(): void {
window.addEventListener('error', (event) => {
console.error('全局错误:', event.error)
this.systemStatus.lastError = event.error?.message || '未知错误'
})
window.addEventListener('unhandledrejection', (event) => {
2025-10-10 10:08:05 +08:00
// console.error('未处理的Promise拒绝:', event.reason)
2025-09-24 16:43:10 +08:00
this.systemStatus.lastError = event.reason?.message || '未处理的Promise拒绝'
})
}
/**
*
*/
private debugLog(message: string, data?: any): void {
if (this.config.debug) {
console.log(`[SystemService] ${message}`, data)
}
}
2025-09-28 12:05:59 +08:00
}