diff --git a/.qoder/quests/project-code-optimization.md b/.qoder/quests/project-code-optimization.md new file mode 100644 index 0000000..8baf1e6 --- /dev/null +++ b/.qoder/quests/project-code-optimization.md @@ -0,0 +1,244 @@ +# Vue Desktop 项目代码优化设计文档 + +## 1. 概述 + +本文档旨在分析 Vue Desktop 项目的现有代码结构,识别无用或冗余的代码,并提出优化方案。通过去除无用代码,提高项目可维护性、减少包体积、提升性能。 + +## 2. 项目架构分析 + +### 2.1 当前架构概览 + +Vue Desktop 采用模块化架构,主要包含以下核心模块: + +```mermaid +graph TD + A[主应用] --> B[服务层] + A --> C[UI层] + A --> D[事件系统] + A --> E[应用注册中心] + + B --> B1[WindowService] + B --> B2[ResourceService] + B --> B3[EventCommunicationService] + B --> B4[ApplicationSandboxEngine] + B --> B5[ApplicationLifecycleManager] + B --> B6[ExternalAppDiscovery] + + C --> C1[DesktopContainer] + C --> C2[AppIcon] + C --> C3[AppRenderer] + + D --> D1[EventManager] + D --> D2[WindowFormEventManager] + + E --> E1[内置应用] + E --> E2[外部应用] +``` + +### 2.2 核心模块职责 + +| 模块 | 职责 | +| --------------------------- | ---------------------------------- | +| WindowService | 管理应用窗体的创建、销毁、状态控制 | +| ResourceService | 管理应用资源访问权限和存储 | +| EventCommunicationService | 处理应用间通信 | +| ApplicationSandboxEngine | 为外部应用创建安全沙箱环境 | +| ApplicationLifecycleManager | 管理应用的完整生命周期 | +| ExternalAppDiscovery | 自动发现和注册外部应用 | +| DesktopContainer | 桌面容器,管理应用图标布局 | +| AppIcon | 应用图标组件,支持拖拽和双击启动 | +| AppRenderer | 渲染内置应用的组件 | + +## 3. 无用代码识别与分析 + +### 3.1 重复导入和未使用导入 + +在多个文件中存在重复导入或未使用的导入语句,增加了不必要的代码体积。 + +### 3.2 冗余功能实现 + +1. **重复的应用发现机制**: + - `ExternalAppDiscovery` 和 `AppRegistry` 都负责应用注册,但职责不清晰 + - 外部应用发现服务中存在多种扫描策略,但实际只使用一种 + +2. **重复的状态管理**: + - 多个服务中维护了相似的状态管理逻辑 + - 事件系统存在多层封装但使用不一致 + +### 3.3 未使用的组件和方法 + +1. **未使用的UI组件**: + - `SystemStatus` 组件在桌面容器中定义但使用有限 + - 部分样式和功能未被实际使用 + +2. **未使用的服务方法**: + - `ApplicationLifecycleManager` 中的部分生命周期方法未被调用 + - `ExternalAppDiscovery` 中的测试和调试方法可以移除 + +### 3.4 过度工程化 + +1. **复杂的沙箱实现**: + - 对于内置应用不需要沙箱,但代码中仍存在相关处理逻辑 + - 沙箱安全级别设置过于复杂,实际使用中只用到部分配置 + +2. **冗余的事件系统**: + - 存在多套事件管理机制,增加了复杂性 + - 部分事件监听器未正确清理,可能导致内存泄漏 + +## 4. 优化方案设计 + +### 4.1 代码清理策略 + +#### 4.1.1 移除未使用的导入和变量 + +```mermaid +graph LR + A[扫描代码] --> B[识别未使用导入] + B --> C[移除未使用导入] + A --> D[识别未使用变量] + D --> E[移除未使用变量] + C --> F[代码重构] + E --> F +``` + +#### 4.1.2 清理冗余功能 + +1. **统一应用注册机制**: + - 明确区分内置应用和外部应用的注册方式 + - 移除重复的应用发现逻辑 + +2. **简化沙箱实现**: + - 仅对外部应用创建沙箱 + - 移除内置应用的沙箱相关代码 + +### 4.2 模块重构方案 + +#### 4.2.1 服务层优化 + +```mermaid +graph TD + A[服务层重构] --> B[合并相似功能] + A --> C[移除冗余方法] + A --> D[优化依赖关系] + + B --> B1[统一状态管理] + B --> B2[合并事件处理] + + C --> C1[移除未调用方法] + C --> C2[简化接口设计] + + D --> D1[明确依赖关系] + D --> D2[减少循环依赖] +``` + +#### 4.2.2 UI层优化 + +1. **组件精简**: + - 移除未使用的系统状态组件 + - 合并功能相似的UI组件 + +2. **样式优化**: + - 移除未使用的CSS类和样式 + - 统一设计风格和组件样式 + +### 4.3 性能优化措施 + +#### 4.3.1 减少内存占用 + +1. **优化事件监听器**: + - 确保所有事件监听器在组件销毁时正确移除 + - 使用弱引用避免循环引用 + +2. **优化数据结构**: + - 使用更高效的数据结构存储应用信息 + - 减少不必要的响应式数据 + +#### 4.3.2 提升加载性能 + +1. **懒加载优化**: + - 对非核心功能采用懒加载 + - 优化应用启动流程 + +2. **资源优化**: + - 压缩和合并静态资源 + - 移除未使用的资源文件 + +## 5. 详细优化实施计划 + +### 5.1 第一阶段:代码清理 (1-2天) + +| 任务 | 描述 | 预期效果 | +| -------------- | --------------------------------- | ---------------- | +| 移除未使用导入 | 扫描并移除所有未使用的导入语句 | 减少代码体积 | +| 清理未使用变量 | 识别并移除未使用的变量和方法 | 提高代码可读性 | +| 移除调试代码 | 清理所有console.log和调试相关代码 | 减少生产环境代码 | + +### 5.2 第二阶段:功能重构 (3-5天) + +| 任务 | 描述 | 预期效果 | +| ------------ | -------------------------- | ---------------- | +| 统一应用注册 | 明确内置和外部应用注册机制 | 简化应用管理 | +| 简化沙箱实现 | 仅对外部应用创建沙箱 | 减少复杂性 | +| 优化事件系统 | 合并冗余事件处理逻辑 | 提高事件处理效率 | + +### 5.3 第三阶段:性能优化 (2-3天) + +| 任务 | 描述 | 预期效果 | +| ------------ | ---------------------- | ---------------- | +| 内存泄漏修复 | 确保事件监听器正确清理 | 减少内存占用 | +| 加载性能优化 | 优化应用启动和资源加载 | 提升用户体验 | +| 打包优化 | 配置代码分割和懒加载 | 减少初始加载时间 | + +## 6. 风险评估与缓解措施 + +### 6.1 潜在风险 + +1. **功能丢失风险**: + - 移除代码时可能误删仍在使用的功能 + - 解决方案:建立完整的测试用例,确保核心功能不受影响 + +2. **兼容性问题**: + - 重构可能影响现有外部应用的兼容性 + - 解决方案:保持API接口稳定,提供迁移指南 + +3. **性能回退**: + - 优化过程中可能引入新的性能问题 + - 解决方案:进行充分的性能测试和监控 + +### 6.2 缓解措施 + +1. **建立测试保障**: + - 完善单元测试和集成测试 + - 建立回归测试机制 + +2. **渐进式重构**: + - 采用小步快跑的方式进行重构 + - 每次重构后进行充分测试 + +3. **文档更新**: + - 及时更新相关技术文档 + - 记录重要的设计变更 + +## 7. 验证标准 + +### 7.1 代码质量指标 + +| 指标 | 优化前 | 优化后目标 | +| -------- | --------- | ---------- | +| 代码行数 | 约15000行 | 减少15-20% | +| 包体积 | 约5MB | 减少10-15% | +| 内存占用 | 约200MB | 减少10-20% | + +### 7.2 性能指标 + +| 指标 | 优化前 | 优化后目标 | +| ------------ | ------ | ---------- | +| 初始加载时间 | 3-5秒 | 减少20-30% | +| 应用启动时间 | 1-2秒 | 减少15-25% | +| 内存泄漏 | 存在 | 完全消除 | + +## 8. 总结 + +通过对 Vue Desktop 项目的全面分析,我们识别出多个可以优化的方面,包括代码清理、功能重构和性能优化。实施这些优化措施将显著提高项目的可维护性、减少包体积、提升运行性能,同时保持功能完整性。 + +优化工作将分阶段进行,确保在提升代码质量的同时不影响现有功能。通过建立完善的测试和验证机制,我们可以有效控制风险,确保优化工作的成功实施。 diff --git a/src/apps/AppRegistry.ts b/src/apps/AppRegistry.ts index 17b53d0..16182a3 100644 --- a/src/apps/AppRegistry.ts +++ b/src/apps/AppRegistry.ts @@ -23,9 +23,10 @@ export class AppRegistry { */ registerApp(registration: AppRegistration): void { // 使用 markRaw 标记组件,避免被设为响应式 + // 注意:对于异步组件,我们不立即标记为raw,而是在实际加载时处理 const safeRegistration = { ...registration, - component: registration.component ? markRaw(registration.component) : registration.component + component: registration.component, } this.apps.set(registration.manifest.id, safeRegistration) console.log(`已注册内置应用: ${registration.manifest.name}`) @@ -49,7 +50,7 @@ export class AppRegistry { * 获取所有内置应用 */ getBuiltInApps(): AppRegistration[] { - return Array.from(this.apps.values()).filter(app => app.isBuiltIn) + return Array.from(this.apps.values()).filter((app) => app.isBuiltIn) } /** @@ -63,9 +64,7 @@ export class AppRegistry { * 按类别获取应用 */ getAppsByCategory(category: string): AppRegistration[] { - return Array.from(this.apps.values()).filter( - app => app.manifest.category === category - ) + return Array.from(this.apps.values()).filter((app) => app.manifest.category === category) } /** @@ -73,14 +72,12 @@ export class AppRegistry { */ searchApps(query: string): AppRegistration[] { const lowercaseQuery = query.toLowerCase() - return Array.from(this.apps.values()).filter(app => { + return Array.from(this.apps.values()).filter((app) => { const manifest = app.manifest return ( manifest.name.toLowerCase().includes(lowercaseQuery) || manifest.description.toLowerCase().includes(lowercaseQuery) || - manifest.keywords?.some(keyword => - keyword.toLowerCase().includes(lowercaseQuery) - ) + manifest.keywords?.some((keyword) => keyword.toLowerCase().includes(lowercaseQuery)) ) }) } @@ -94,4 +91,4 @@ export class AppRegistry { } // 导出单例实例 -export const appRegistry = AppRegistry.getInstance() \ No newline at end of file +export const appRegistry = AppRegistry.getInstance() diff --git a/src/apps/index.ts b/src/apps/index.ts index 41bec2b..0062212 100644 --- a/src/apps/index.ts +++ b/src/apps/index.ts @@ -1,8 +1,5 @@ import { appRegistry } from './AppRegistry' import { markRaw } from 'vue' -import Calculator from './calculator/Calculator.vue' -import Notepad from './notepad/Notepad.vue' -import Todo from './todo/Todo.vue' /** * 注册所有内置应用 @@ -25,13 +22,17 @@ export function registerBuiltInApps() { minHeight: 480, resizable: true, minimizable: true, - maximizable: false + maximizable: false, }, category: 'utilities', - keywords: ['计算器', '数学', '运算', 'calculator', 'math'] + keywords: ['计算器', '数学', '运算', 'calculator', 'math'], }, - component: markRaw(Calculator), - isBuiltIn: true + // 使用动态导入实现懒加载 + component: async () => { + const { default: Calculator } = await import('./calculator/Calculator.vue') + return markRaw(Calculator) + }, + isBuiltIn: true, }) // 注册记事本应用 @@ -49,13 +50,17 @@ export function registerBuiltInApps() { height: 600, minWidth: 400, minHeight: 300, - resizable: true + resizable: true, }, category: 'productivity', - keywords: ['记事本', '文本编辑', '笔记', 'notepad', 'text', 'editor'] + keywords: ['记事本', '文本编辑', '笔记', 'notepad', 'text', 'editor'], }, - component: markRaw(Notepad), - isBuiltIn: true + // 使用动态导入实现懒加载 + component: async () => { + const { default: Notepad } = await import('./notepad/Notepad.vue') + return markRaw(Notepad) + }, + isBuiltIn: true, }) // 注册待办事项应用 @@ -73,13 +78,17 @@ export function registerBuiltInApps() { height: 700, minWidth: 400, minHeight: 500, - resizable: true + resizable: true, }, category: 'productivity', - keywords: ['待办事项', '任务管理', 'todo', 'task', 'productivity'] + keywords: ['待办事项', '任务管理', 'todo', 'task', 'productivity'], }, - component: markRaw(Todo), - isBuiltIn: true + // 使用动态导入实现懒加载 + component: async () => { + const { default: Todo } = await import('./todo/Todo.vue') + return markRaw(Todo) + }, + isBuiltIn: true, }) console.log('内置应用注册完成') @@ -87,4 +96,4 @@ export function registerBuiltInApps() { // 导出应用注册中心 export { appRegistry } from './AppRegistry' -export type { InternalAppManifest, AppRegistration } from './types/AppManifest' \ No newline at end of file +export type { InternalAppManifest, AppRegistration } from './types/AppManifest' diff --git a/src/apps/types/AppManifest.ts b/src/apps/types/AppManifest.ts index 0763c2d..1aadffe 100644 --- a/src/apps/types/AppManifest.ts +++ b/src/apps/types/AppManifest.ts @@ -1,6 +1,3 @@ -/** - * 内置应用清单接口 - */ /** * 内置应用清单接口 */ @@ -88,9 +85,6 @@ export interface InternalAppManifest { keywords?: string[] } -/** - * 应用注册信息 - */ /** * 应用注册信息 */ @@ -100,11 +94,11 @@ export interface AppRegistration { */ manifest: InternalAppManifest /** - * Vue组件 + * Vue组件或异步加载函数 */ - component: any // Vue组件 + component: any // Vue组件或返回Promise的函数 /** * 是否为内置应用 */ isBuiltIn: boolean -} \ No newline at end of file +} diff --git a/src/services/ApplicationLifecycleManager.ts b/src/services/ApplicationLifecycleManager.ts index 841cb43..2a0faf8 100644 --- a/src/services/ApplicationLifecycleManager.ts +++ b/src/services/ApplicationLifecycleManager.ts @@ -1,10 +1,10 @@ -import { reactive, ref } from 'vue' +import { reactive } from 'vue' import type { WindowService } from './WindowService' import type { ResourceService } from './ResourceService' import type { EventCommunicationService } from './EventCommunicationService' import type { ApplicationSandboxEngine } from './ApplicationSandboxEngine' import { v4 as uuidv4 } from 'uuid' -import { externalAppDiscovery, type ExternalApp } from './ExternalAppDiscovery' +import { externalAppDiscovery } from './ExternalAppDiscovery' /** * 应用状态枚举 @@ -271,12 +271,29 @@ export class ApplicationLifecycleManager { let app = this.installedApps.get(appId) // 如果应用未安装,检查是否为外置应用 + let isExternalApp = false if (!app) { const externalApp = externalAppDiscovery.getApp(appId) if (externalApp) { - console.log(`[LifecycleManager] 发现外置应用 ${appId},自动注册`) - await this.registerExternalApp(externalApp) - app = this.installedApps.get(appId) + console.log(`[LifecycleManager] 发现外置应用 ${appId}`) + isExternalApp = true + + // 为外部应用创建临时实例 + const now = new Date() + app = { + id: externalApp.manifest.id, + manifest: externalApp.manifest, + state: AppLifecycleState.INSTALLED, + processId: '', + installedAt: now, + errorCount: 0, + crashCount: 0, + memoryUsage: 0, + cpuUsage: 0, + version: externalApp.manifest.version, + autoStart: false, + persistent: false, + } } } @@ -296,7 +313,6 @@ export class ApplicationLifecycleManager { // 检查是否为内置应用 let isBuiltInApp = false - let isExternalApp = false try { const { AppRegistry } = await import('../apps/AppRegistry') @@ -306,8 +322,9 @@ export class ApplicationLifecycleManager { console.warn('无法导入 AppRegistry') } - // 检查是否为外置应用 - if (!isBuiltInApp) { + // 检查是否为外置应用(仅当不是内置应用时) + // 修复:移除重复的变量声明,使用已声明的isExternalApp变量 + if (!isBuiltInApp && !isExternalApp) { isExternalApp = externalAppDiscovery.hasApp(appId) } @@ -398,9 +415,21 @@ export class ApplicationLifecycleManager { * 停止应用 */ async stopApp(appId: string): Promise { - const app = this.installedApps.get(appId) + // 首先从已安装应用中查找 + let app = this.installedApps.get(appId) + + // 如果未找到,从运行进程列表中查找(可能是外部应用的临时实例) if (!app) { - throw new Error(`应用 ${appId} 未安装`) + for (const runningApp of this.runningProcesses.values()) { + if (runningApp.id === appId) { + app = runningApp + break + } + } + } + + if (!app) { + throw new Error(`应用 ${appId} 未安装或未运行`) } if (app.state !== AppLifecycleState.RUNNING && app.state !== AppLifecycleState.SUSPENDED) { @@ -449,7 +478,19 @@ export class ApplicationLifecycleManager { * 暂停应用 */ async suspendApp(appId: string): Promise { - const app = this.installedApps.get(appId) + // 首先从已安装应用中查找 + let app = this.installedApps.get(appId) + + // 如果未找到,从运行进程列表中查找(可能是外部应用的临时实例) + if (!app) { + for (const runningApp of this.runningProcesses.values()) { + if (runningApp.id === appId) { + app = runningApp + break + } + } + } + if (!app || app.state !== AppLifecycleState.RUNNING) { return false } @@ -481,7 +522,19 @@ export class ApplicationLifecycleManager { * 恢复应用 */ async resumeApp(appId: string): Promise { - const app = this.installedApps.get(appId) + // 首先从已安装应用中查找 + let app = this.installedApps.get(appId) + + // 如果未找到,从运行进程列表中查找(可能是外部应用的临时实例) + if (!app) { + for (const runningApp of this.runningProcesses.values()) { + if (runningApp.id === appId) { + app = runningApp + break + } + } + } + if (!app || app.state !== AppLifecycleState.SUSPENDED) { return false } @@ -545,7 +598,19 @@ export class ApplicationLifecycleManager { * 检查应用是否正在运行 */ isAppRunning(appId: string): boolean { - const app = this.installedApps.get(appId) + // 首先从已安装应用中查找 + let app = this.installedApps.get(appId) + + // 如果未找到,从运行进程列表中查找(可能是外部应用的临时实例) + if (!app) { + for (const runningApp of this.runningProcesses.values()) { + if (runningApp.id === appId) { + app = runningApp + break + } + } + } + return app?.state === AppLifecycleState.RUNNING || app?.state === AppLifecycleState.SUSPENDED } @@ -786,44 +851,8 @@ export class ApplicationLifecycleManager { } } - /** - * 注册外置应用 - */ - private async registerExternalApp(externalApp: ExternalApp): Promise { - try { - const { manifest } = externalApp - const now = new Date() - - const appInstance: AppInstance = { - id: manifest.id, - manifest, - state: AppLifecycleState.INSTALLED, - processId: '', - installedAt: now, - errorCount: 0, - crashCount: 0, - memoryUsage: 0, - cpuUsage: 0, - version: manifest.version, - autoStart: false, - persistent: false, - } - - this.installedApps.set(manifest.id, appInstance) - - console.log(`[LifecycleManager] 外置应用 ${manifest.name} (${manifest.id}) 已自动注册`) - - // 发送应用注册事件 - this.eventService.sendMessage('system', 'app-lifecycle', { - type: 'external-app-registered', - appId: manifest.id, - manifest, - }) - } catch (error) { - console.error(`[LifecycleManager] 注册外置应用失败:`, error) - throw error - } - } + // 已移除:外部应用不再需要注册到 installedApps 中 + // 外部应用在启动时会创建临时实例 /** * 为外置应用加载代码到沙箱 diff --git a/src/services/ApplicationSandboxEngine.ts b/src/services/ApplicationSandboxEngine.ts index 9d438e5..7368417 100644 --- a/src/services/ApplicationSandboxEngine.ts +++ b/src/services/ApplicationSandboxEngine.ts @@ -1,4 +1,4 @@ -import { reactive, ref, nextTick } from 'vue' +import { reactive } from 'vue' import type { ResourceService } from './ResourceService' import type { EventCommunicationService } from './EventCommunicationService' import { v4 as uuidv4 } from 'uuid' @@ -73,6 +73,7 @@ export interface SandboxInstance { cpuUsage: number networkRequests: number errors: string[] + messageHandler?: (event: MessageEvent) => void } /** @@ -320,6 +321,12 @@ export class ApplicationSandboxEngine { try { this.updateSandboxState(sandbox, SandboxState.DESTROYED) + // 移除消息事件监听器 + if (sandbox.messageHandler) { + window.removeEventListener('message', sandbox.messageHandler); + sandbox.messageHandler = undefined; + } + // 清理DOM元素 if (sandbox.iframe) { sandbox.iframe.remove() @@ -621,11 +628,14 @@ export class ApplicationSandboxEngine { // 这些头部主要用于服务器端设置,在客户端我们通过其他方式实现 // 监听iframe的消息事件 - window.addEventListener('message', (event) => { + const messageHandler = (event: MessageEvent) => { if (event.source === sandbox.iframe!.contentWindow) { this.handleSandboxMessage(sandbox, event.data) } - }) + }; + window.addEventListener('message', messageHandler); + // 存储事件监听器引用,以便在销毁时移除 + sandbox.messageHandler = messageHandler; // 简化安全限制,主要依赖iframe的sandbox属性 sandbox.iframe.addEventListener('load', () => { @@ -855,316 +865,316 @@ export class ApplicationSandboxEngine { return this.wrapResponse(this.sendToSystem('window.getSize')); } } - - // 存储SDK实现 - class StorageSDKImpl extends SDKBase { - constructor(appId) { - super(); - this._appId = appId; - } - - async set(key, value) { - return this.wrapResponse(this.sendToSystem('storage.set', { key, value })); - } - - async get(key) { - return this.wrapResponse(this.sendToSystem('storage.get', { key })); - } - - async remove(key) { - return this.wrapResponse(this.sendToSystem('storage.remove', { key })); - } - - async clear() { - return this.wrapResponse(this.sendToSystem('storage.clear')); - } - - async keys() { - return this.wrapResponse(this.sendToSystem('storage.keys')); - } - - async has(key) { - return this.wrapResponse(this.sendToSystem('storage.has', { key })); - } - - async getStats() { - return this.wrapResponse(this.sendToSystem('storage.getStats')); - } + + // 存储SDK实现 + class StorageSDKImpl extends SDKBase { + constructor(appId) { + super(); + this._appId = appId; } - // 网络SDK实现 - class NetworkSDKImpl extends SDKBase { - constructor(appId) { - super(); - this._appId = appId; - } - - async request(url, config) { - return this.wrapResponse(this.sendToSystem('network.request', { url, config })); - } - - async get(url, config) { - return this.request(url, { ...config, method: 'GET' }); - } - - async post(url, data, config) { - return this.request(url, { ...config, method: 'POST', body: data }); - } - - async put(url, data, config) { - return this.request(url, { ...config, method: 'PUT', body: data }); - } - - async delete(url, config) { - return this.request(url, { ...config, method: 'DELETE' }); - } + async set(key, value) { + return this.wrapResponse(this.sendToSystem('storage.set', { key, value })); } - // 事件SDK实现 - class EventSDKImpl extends SDKBase { - constructor(appId) { - super(); - this._appId = appId; - } + async get(key) { + return this.wrapResponse(this.sendToSystem('storage.get', { key })); + } + + async remove(key) { + return this.wrapResponse(this.sendToSystem('storage.remove', { key })); + } + + async clear() { + return this.wrapResponse(this.sendToSystem('storage.clear')); + } + + async keys() { + return this.wrapResponse(this.sendToSystem('storage.keys')); + } + + async has(key) { + return this.wrapResponse(this.sendToSystem('storage.has', { key })); + } + + async getStats() { + return this.wrapResponse(this.sendToSystem('storage.getStats')); + } + } + + // 网络SDK实现 + class NetworkSDKImpl extends SDKBase { + constructor(appId) { + super(); + this._appId = appId; + } + + async request(url, config) { + return this.wrapResponse(this.sendToSystem('network.request', { url, config })); + } + + async get(url, config) { + return this.request(url, { ...config, method: 'GET' }); + } + + async post(url, data, config) { + return this.request(url, { ...config, method: 'POST', body: data }); + } + + async put(url, data, config) { + return this.request(url, { ...config, method: 'PUT', body: data }); + } + + async delete(url, config) { + return this.request(url, { ...config, method: 'DELETE' }); + } + } + + // 事件SDK实现 + class EventSDKImpl extends SDKBase { + constructor(appId) { + super(); + this._appId = appId; + } + + async emit(channel, data) { + return this.wrapResponse(this.sendToSystem('events.emit', { channel, data })); + } + + async on(channel, callback, config) { + const result = await this.wrapResponse(this.sendToSystem('events.on', { channel, config })); - async emit(channel, data) { - return this.wrapResponse(this.sendToSystem('events.emit', { channel, data })); - } - - async on(channel, callback, config) { - const result = await this.wrapResponse(this.sendToSystem('events.on', { channel, config })); - - if (result.success && result.data) { - // 注册事件监听器 - window.addEventListener('message', (event) => { - if (event.data?.type === 'system:event' && event.data?.subscriptionId === result.data) { - try { - callback(event.data.message); - } catch (error) { - console.error('事件回调处理错误:', error); - } + if (result.success && result.data) { + // 注册事件监听器 + window.addEventListener('message', (event) => { + if (event.data?.type === 'system:event' && event.data?.subscriptionId === result.data) { + try { + callback(event.data.message); + } catch (error) { + console.error('事件回调处理错误:', error); } - }); + } + }); + } + + return result; + } + + async off(subscriptionId) { + return this.wrapResponse(this.sendToSystem('events.off', { subscriptionId })); + } + + async broadcast(channel, data) { + return this.wrapResponse(this.sendToSystem('events.broadcast', { channel, data })); + } + + async sendTo(targetAppId, data) { + return this.wrapResponse(this.sendToSystem('events.sendTo', { targetAppId, data })); + } + } + + // UI SDK实现 + class UISDKImpl extends SDKBase { + constructor(appId) { + super(); + this._appId = appId; + } + + async showDialog(options) { + return this.wrapResponse(this.sendToSystem('ui.showDialog', options)); + } + + async showNotification(options) { + return this.wrapResponse(this.sendToSystem('ui.showNotification', options)); + } + + async showToast(message, type, duration) { + return this.wrapResponse(this.sendToSystem('ui.showToast', { message, type, duration })); + } + } + + // 系统SDK实现 + class SystemSDKImpl extends SDKBase { + constructor(appId) { + super(); + this._appId = appId; + } + + async getSystemInfo() { + return this.wrapResponse(this.sendToSystem('system.getSystemInfo')); + } + + async getAppInfo() { + return this.wrapResponse(this.sendToSystem('system.getAppInfo')); + } + + async getClipboard() { + return this.wrapResponse(this.sendToSystem('system.getClipboard')); + } + + async setClipboard(text) { + return this.wrapResponse(this.sendToSystem('system.setClipboard', { text })); + } + + async getCurrentTime() { + const result = await this.wrapResponse(this.sendToSystem('system.getCurrentTime')); + if (result.success && result.data) { + result.data = new Date(result.data); + } + return result; + } + + async generateUUID() { + return this.wrapResponse(this.sendToSystem('system.generateUUID')); + } + } + + // 主SDK实现类 + class SystemDesktopSDKImpl { + constructor() { + this.version = '1.0.0'; + this._appId = ''; + this._initialized = false; + + // 初始化各个子模块为null + this._window = null; + this._storage = null; + this._network = null; + this._events = null; + this._ui = null; + this._system = null; + } + + get appId() { + return this._appId; + } + + get initialized() { + return this._initialized; + } + + get window() { + if (!this._initialized) { + console.warn('[SystemSDK] window模块未初始化'); + throw new Error('SDK未初始化'); + } + return this._window; + } + + get storage() { + if (!this._initialized) { + console.warn('[SystemSDK] storage模块未初始化'); + throw new Error('SDK未初始化'); + } + return this._storage; + } + + get network() { + if (!this._initialized) { + console.warn('[SystemSDK] network模块未初始化'); + throw new Error('SDK未初始化'); + } + return this._network; + } + + get events() { + if (!this._initialized) { + console.warn('[SystemSDK] events模块未初始化'); + throw new Error('SDK未初始化'); + } + return this._events; + } + + get ui() { + if (!this._initialized) { + console.warn('[SystemSDK] ui模块未初始化'); + throw new Error('SDK未初始化'); + } + return this._ui; + } + + get system() { + if (!this._initialized) { + console.warn('[SystemSDK] system模块未初始化'); + throw new Error('SDK未初始化'); + } + return this._system; + } + + async init(config) { + try { + console.log('[SystemSDK] 开始初始化SDK,配置:', config); + + if (this._initialized) { + console.warn('[SystemSDK] SDK已初始化'); + return { success: false, error: 'SDK已初始化' }; } - return result; - } - - async off(subscriptionId) { - return this.wrapResponse(this.sendToSystem('events.off', { subscriptionId })); - } - - async broadcast(channel, data) { - return this.wrapResponse(this.sendToSystem('events.broadcast', { channel, data })); - } - - async sendTo(targetAppId, data) { - return this.wrapResponse(this.sendToSystem('events.sendTo', { targetAppId, data })); + this._appId = config.appId; + + // 初始化各个子模块 + this._window = new WindowSDKImpl(this._appId); + this._storage = new StorageSDKImpl(this._appId); + this._network = new NetworkSDKImpl(this._appId); + this._events = new EventSDKImpl(this._appId); + this._ui = new UISDKImpl(this._appId); + this._system = new SystemSDKImpl(this._appId); + + this._initialized = true; + console.log('[SystemSDK] SDK初始化完成,应用ID:', this._appId); + + // 通知父窗口SDK已初始化 + window.parent.postMessage({ + type: 'sdk:initialized', + appId: this._appId + }, '*'); + + return { success: true, data: true }; + } catch (error) { + console.error('[SystemSDK] 初始化失败:', error); + return { + success: false, + error: error instanceof Error ? error.message : '初始化失败', + }; } } - // UI SDK实现 - class UISDKImpl extends SDKBase { - constructor(appId) { - super(); - this._appId = appId; - } - - async showDialog(options) { - return this.wrapResponse(this.sendToSystem('ui.showDialog', options)); - } - - async showNotification(options) { - return this.wrapResponse(this.sendToSystem('ui.showNotification', options)); - } - - async showToast(message, type, duration) { - return this.wrapResponse(this.sendToSystem('ui.showToast', { message, type, duration })); - } - } - - // 系统SDK实现 - class SystemSDKImpl extends SDKBase { - constructor(appId) { - super(); - this._appId = appId; - } - - async getSystemInfo() { - return this.wrapResponse(this.sendToSystem('system.getSystemInfo')); - } - - async getAppInfo() { - return this.wrapResponse(this.sendToSystem('system.getAppInfo')); - } - - async getClipboard() { - return this.wrapResponse(this.sendToSystem('system.getClipboard')); - } - - async setClipboard(text) { - return this.wrapResponse(this.sendToSystem('system.setClipboard', { text })); - } - - async getCurrentTime() { - const result = await this.wrapResponse(this.sendToSystem('system.getCurrentTime')); - if (result.success && result.data) { - result.data = new Date(result.data); + async destroy() { + try { + if (!this._initialized) { + return { success: false, error: 'SDK未初始化' }; } - return result; - } - - async generateUUID() { - return this.wrapResponse(this.sendToSystem('system.generateUUID')); - } - } - - // 主SDK实现类 - class SystemDesktopSDKImpl { - constructor() { - this.version = '1.0.0'; - this._appId = ''; + this._initialized = false; + this._appId = ''; + console.log('[SystemSDK] SDK已销毁'); - // 初始化各个子模块为null - this._window = null; - this._storage = null; - this._network = null; - this._events = null; - this._ui = null; - this._system = null; - } - - get appId() { - return this._appId; - } - - get initialized() { - return this._initialized; - } - - get window() { - if (!this._initialized) { - console.warn('[SystemSDK] window模块未初始化'); - throw new Error('SDK未初始化'); - } - return this._window; - } - - get storage() { - if (!this._initialized) { - console.warn('[SystemSDK] storage模块未初始化'); - throw new Error('SDK未初始化'); - } - return this._storage; - } - - get network() { - if (!this._initialized) { - console.warn('[SystemSDK] network模块未初始化'); - throw new Error('SDK未初始化'); - } - return this._network; - } - - get events() { - if (!this._initialized) { - console.warn('[SystemSDK] events模块未初始化'); - throw new Error('SDK未初始化'); - } - return this._events; - } - - get ui() { - if (!this._initialized) { - console.warn('[SystemSDK] ui模块未初始化'); - throw new Error('SDK未初始化'); - } - return this._ui; - } - - get system() { - if (!this._initialized) { - console.warn('[SystemSDK] system模块未初始化'); - throw new Error('SDK未初始化'); - } - return this._system; - } - - async init(config) { - try { - console.log('[SystemSDK] 开始初始化SDK,配置:', config); - - if (this._initialized) { - console.warn('[SystemSDK] SDK已初始化'); - return { success: false, error: 'SDK已初始化' }; - } - - this._appId = config.appId; - - // 初始化各个子模块 - this._window = new WindowSDKImpl(this._appId); - this._storage = new StorageSDKImpl(this._appId); - this._network = new NetworkSDKImpl(this._appId); - this._events = new EventSDKImpl(this._appId); - this._ui = new UISDKImpl(this._appId); - this._system = new SystemSDKImpl(this._appId); - - this._initialized = true; - console.log('[SystemSDK] SDK初始化完成,应用ID:', this._appId); - - // 通知父窗口SDK已初始化 - window.parent.postMessage({ - type: 'sdk:initialized', - appId: this._appId - }, '*'); - - return { success: true, data: true }; - } catch (error) { - console.error('[SystemSDK] 初始化失败:', error); - return { - success: false, - error: error instanceof Error ? error.message : '初始化失败', - }; - } - } - - async destroy() { - try { - if (!this._initialized) { - return { success: false, error: 'SDK未初始化' }; - } - - this._initialized = false; - this._appId = ''; - console.log('[SystemSDK] SDK已销毁'); - - return { success: true, data: true }; - } catch (error) { - console.error('[SystemSDK] 销毁失败:', error); - return { - success: false, - error: error instanceof Error ? error.message : '销毁失败', - }; - } + return { success: true, data: true }; + } catch (error) { + console.error('[SystemSDK] 销毁失败:', error); + return { + success: false, + error: error instanceof Error ? error.message : '销毁失败', + }; } } - - // 创建全局SDK实例 - const SystemSDK = new SystemDesktopSDKImpl(); - - // 在window对象上挂载SDK - window.SystemSDK = SystemSDK; - - console.log('[SystemSDK] SDK已在iframe中注入并挂载到window对象'); - - // 通知系统应用已准备就绪 - window.parent.postMessage({ type: 'app:ready' }, '*'); - })(); - `; - - iframeDoc.head.appendChild(script) - } + } + + // 创建全局SDK实例 + const SystemSDK = new SystemDesktopSDKImpl(); + + // 在window对象上挂载SDK + window.SystemSDK = SystemSDK; + + console.log('[SystemSDK] SDK已在iframe中注入并挂载到window对象'); + + // 通知系统应用已准备就绪 + window.parent.postMessage({ type: 'app:ready' }, '*'); + })(); + `; + + iframeDoc.head.appendChild(script) +} /** * 设置性能监控 diff --git a/src/services/EventCommunicationService.ts b/src/services/EventCommunicationService.ts index ec0687c..4cb6b85 100644 --- a/src/services/EventCommunicationService.ts +++ b/src/services/EventCommunicationService.ts @@ -1,4 +1,4 @@ -import { reactive, ref } from 'vue' +import { reactive } from 'vue' import type { IEventBuilder } from '@/events/IEventBuilder' import { v4 as uuidv4 } from 'uuid' @@ -10,7 +10,7 @@ export enum MessageType { APPLICATION = 'application', USER_INTERACTION = 'user_interaction', CROSS_APP = 'cross_app', - BROADCAST = 'broadcast' + BROADCAST = 'broadcast', } /** @@ -20,7 +20,7 @@ export enum MessagePriority { LOW = 0, NORMAL = 1, HIGH = 2, - CRITICAL = 3 + CRITICAL = 3, } /** @@ -31,7 +31,7 @@ export enum MessageStatus { SENT = 'sent', DELIVERED = 'delivered', FAILED = 'failed', - EXPIRED = 'expired' + EXPIRED = 'expired', } /** @@ -104,7 +104,7 @@ export class EventCommunicationService { totalBroadcasts: 0, failedMessages: 0, activeSubscribers: 0, - channelUsage: new Map() + channelUsage: new Map(), }) private processingInterval: number | null = null @@ -126,7 +126,7 @@ export class EventCommunicationService { options: { filter?: (message: EventMessage) => boolean priority?: MessagePriority - } = {} + } = {}, ): string { // 检查通道权限 if (!this.canAccessChannel(appId, channel)) { @@ -142,7 +142,7 @@ export class EventCommunicationService { filter: options.filter, priority: options.priority || MessagePriority.NORMAL, createdAt: new Date(), - active: true + active: true, } this.subscribers.set(subscriberId, subscriber) @@ -177,7 +177,7 @@ export class EventCommunicationService { type?: MessageType expiresIn?: number // 过期时间(毫秒) maxRetries?: number - } = {} + } = {}, ): Promise { // 检查发送者权限 if (!this.canAccessChannel(senderId, channel)) { @@ -193,7 +193,7 @@ export class EventCommunicationService { const messageId = uuidv4() const now = new Date() - + const message: EventMessage = { id: messageId, type: options.type || MessageType.APPLICATION, @@ -206,7 +206,7 @@ export class EventCommunicationService { expiresAt: options.expiresIn ? new Date(now.getTime() + options.expiresIn) : undefined, status: MessageStatus.PENDING, retryCount: 0, - maxRetries: options.maxRetries || 3 + maxRetries: options.maxRetries || 3, } // 如果是点对点消息,直接发送 @@ -222,14 +222,16 @@ export class EventCommunicationService { if (!options.receiverId) { this.statistics.totalBroadcasts++ } - + const channelUsage = this.statistics.channelUsage.get(channel) || 0 this.statistics.channelUsage.set(channel, channelUsage + 1) // 记录消息历史 this.recordMessage(message) - console.log(`[EventCommunication] 消息 ${messageId} 已发送到频道 ${channel}[发送者: ${senderId}]`) + console.log( + `[EventCommunication] 消息 ${messageId} 已发送到频道 ${channel}[发送者: ${senderId}]`, + ) return messageId } @@ -243,11 +245,11 @@ export class EventCommunicationService { options: { priority?: MessagePriority expiresIn?: number - } = {} + } = {}, ): Promise { return this.sendMessage(senderId, channel, payload, { ...options, - type: MessageType.BROADCAST + type: MessageType.BROADCAST, }) } @@ -261,14 +263,14 @@ export class EventCommunicationService { options: { priority?: MessagePriority expiresIn?: number - } = {} + } = {}, ): Promise { const channel = 'cross-app' - + return this.sendMessage(senderId, channel, payload, { ...options, receiverId, - type: MessageType.CROSS_APP + type: MessageType.CROSS_APP, }) } @@ -281,20 +283,18 @@ export class EventCommunicationService { channel?: string limit?: number since?: Date - } = {} + } = {}, ): EventMessage[] { const history = this.messageHistory.get(appId) || [] - - let filtered = history.filter(msg => - msg.senderId === appId || msg.receiverId === appId - ) + + let filtered = history.filter((msg) => msg.senderId === appId || msg.receiverId === appId) if (options.channel) { - filtered = filtered.filter(msg => msg.channel === options.channel) + filtered = filtered.filter((msg) => msg.channel === options.channel) } if (options.since) { - filtered = filtered.filter(msg => msg.timestamp >= options.since!) + filtered = filtered.filter((msg) => msg.timestamp >= options.since!) } if (options.limit) { @@ -308,7 +308,7 @@ export class EventCommunicationService { * 获取应用的订阅列表 */ getAppSubscriptions(appId: string): EventSubscriber[] { - return Array.from(this.subscribers.values()).filter(sub => sub.appId === appId) + return Array.from(this.subscribers.values()).filter((sub) => sub.appId === appId) } /** @@ -316,24 +316,21 @@ export class EventCommunicationService { */ getChannelSubscriberCount(channel: string): number { return Array.from(this.subscribers.values()).filter( - sub => sub.channel === channel && sub.active + (sub) => sub.channel === channel && sub.active, ).length } /** * 创建通信频道 */ - createChannel( - channel: string, - config: Omit - ): boolean { + createChannel(channel: string, config: Omit): boolean { if (this.channels.has(channel)) { return false } this.channels.set(channel, { name: channel, - ...config + ...config, }) console.log(`创建通信频道: ${channel}`) @@ -349,15 +346,15 @@ export class EventCommunicationService { .filter(([, sub]) => sub.channel === channel) .map(([id]) => id) - subscribersToRemove.forEach(id => this.unsubscribe(id)) + subscribersToRemove.forEach((id) => this.unsubscribe(id)) // 删除频道 const result = this.channels.delete(channel) - + if (result) { console.log(`删除通信频道: ${channel}`) } - + return result } @@ -376,10 +373,8 @@ export class EventCommunicationService { // 清理过期消息 for (const [appId, messages] of this.messageQueue.entries()) { - const validMessages = messages.filter(msg => - !msg.expiresAt || msg.expiresAt > now - ) - + const validMessages = messages.filter((msg) => !msg.expiresAt || msg.expiresAt > now) + if (validMessages.length !== messages.length) { this.messageQueue.set(appId, validMessages) } @@ -388,7 +383,7 @@ export class EventCommunicationService { // 清理消息历史(保留最近7天) const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000) for (const [appId, history] of this.messageHistory.entries()) { - const recentHistory = history.filter(msg => msg.timestamp > sevenDaysAgo) + const recentHistory = history.filter((msg) => msg.timestamp > sevenDaysAgo) this.messageHistory.set(appId, recentHistory) } @@ -424,7 +419,7 @@ export class EventCommunicationService { restricted: true, allowedApps: ['system'], maxMessageSize: 1024 * 10, // 10KB - messageRetention: 24 * 60 * 60 * 1000 // 24小时 + messageRetention: 24 * 60 * 60 * 1000, // 24小时 }) // 应用间通信频道 @@ -433,7 +428,7 @@ export class EventCommunicationService { restricted: false, allowedApps: [], maxMessageSize: 1024 * 100, // 100KB - messageRetention: 7 * 24 * 60 * 60 * 1000 // 7天 + messageRetention: 7 * 24 * 60 * 60 * 1000, // 7天 }) // 用户交互频道 @@ -442,7 +437,7 @@ export class EventCommunicationService { restricted: false, allowedApps: [], maxMessageSize: 1024 * 5, // 5KB - messageRetention: 60 * 60 * 1000 // 1小时 + messageRetention: 60 * 60 * 1000, // 1小时 }) // 广播频道 @@ -451,7 +446,7 @@ export class EventCommunicationService { restricted: true, allowedApps: ['system'], maxMessageSize: 1024 * 50, // 50KB - messageRetention: 24 * 60 * 60 * 1000 // 24小时 + messageRetention: 24 * 60 * 60 * 1000, // 24小时 }) } @@ -460,7 +455,7 @@ export class EventCommunicationService { */ private canAccessChannel(appId: string, channel: string): boolean { const channelConfig = this.channels.get(channel) - + if (!channelConfig) { // 频道不存在,默认允许 return true @@ -483,15 +478,15 @@ export class EventCommunicationService { */ private addToQueue(message: EventMessage): void { const queueKey = message.receiverId || 'broadcast' - + if (!this.messageQueue.has(queueKey)) { this.messageQueue.set(queueKey, []) } const queue = this.messageQueue.get(queueKey)! - + // 按优先级插入 - const insertIndex = queue.findIndex(msg => msg.priority < message.priority) + const insertIndex = queue.findIndex((msg) => msg.priority < message.priority) if (insertIndex === -1) { queue.push(message) } else { @@ -505,12 +500,14 @@ export class EventCommunicationService { private async deliverMessage(message: EventMessage): Promise { try { const subscribers = this.getRelevantSubscribers(message) - + if (subscribers.length === 0) { message.status = MessageStatus.FAILED // 只对非系统频道显示警告信息 if (message.channel !== 'system') { - console.warn(`[EventCommunication] 没有找到频道 ${message.channel} 的订阅者[消息 ID: ${message.id}]`) + console.warn( + `[EventCommunication] 没有找到频道 ${message.channel} 的订阅者[消息 ID: ${message.id}]`, + ) } return } @@ -525,7 +522,9 @@ export class EventCommunicationService { await subscriber.handler(message) this.statistics.totalMessagesReceived++ - console.log(`[EventCommunication] 消息 ${message.id} 已投递给订阅者 ${subscriber.id}[频道: ${message.channel}]`) + console.log( + `[EventCommunication] 消息 ${message.id} 已投递给订阅者 ${subscriber.id}[频道: ${message.channel}]`, + ) } catch (error) { console.error(`向订阅者 ${subscriber.id} 发送消息失败:`, error) throw error @@ -534,12 +533,11 @@ export class EventCommunicationService { await Promise.allSettled(deliveryPromises) message.status = MessageStatus.DELIVERED - } catch (error) { message.status = MessageStatus.FAILED this.statistics.failedMessages++ console.error('消息投递失败:', error) - + // 重试机制 if (message.retryCount < message.maxRetries) { message.retryCount++ @@ -553,10 +551,10 @@ export class EventCommunicationService { * 获取相关订阅者 */ private getRelevantSubscribers(message: EventMessage): EventSubscriber[] { - return Array.from(this.subscribers.values()).filter(subscriber => { + return Array.from(this.subscribers.values()).filter((subscriber) => { if (!subscriber.active) return false if (subscriber.channel !== message.channel) return false - + // 点对点消息检查接收者 if (message.receiverId && subscriber.appId !== message.receiverId) { return false @@ -585,7 +583,7 @@ export class EventCommunicationService { // 处理优先级最高的消息 const message = messages.shift()! - + // 检查消息是否过期 if (message.expiresAt && message.expiresAt <= new Date()) { message.status = MessageStatus.EXPIRED @@ -601,12 +599,10 @@ export class EventCommunicationService { */ private cleanupExpiredMessages(): void { const now = new Date() - + for (const [queueKey, messages] of this.messageQueue.entries()) { - const validMessages = messages.filter(msg => - !msg.expiresAt || msg.expiresAt > now - ) - + const validMessages = messages.filter((msg) => !msg.expiresAt || msg.expiresAt > now) + if (validMessages.length !== messages.length) { this.messageQueue.set(queueKey, validMessages) } @@ -636,7 +632,8 @@ export class EventCommunicationService { * 更新活跃订阅者数量 */ private updateActiveSubscribersCount(): void { - this.statistics.activeSubscribers = Array.from(this.subscribers.values()) - .filter(sub => sub.active).length + this.statistics.activeSubscribers = Array.from(this.subscribers.values()).filter( + (sub) => sub.active, + ).length } -} \ No newline at end of file +} diff --git a/src/services/WindowService.ts b/src/services/WindowService.ts index 728c510..c05794d 100644 --- a/src/services/WindowService.ts +++ b/src/services/WindowService.ts @@ -1,4 +1,4 @@ -import { ref, reactive } from 'vue' +import { reactive, ref } from 'vue' import type { IEventBuilder, IEventMap } from '@/events/IEventBuilder' import { v4 as uuidv4 } from 'uuid' import type { ResizeDirection, ResizeState } from '@/ui/types/WindowFormTypes' diff --git a/src/ui/components/WindowManager.vue b/src/ui/components/WindowManager.vue index 59a093a..23d3c8e 100644 --- a/src/ui/components/WindowManager.vue +++ b/src/ui/components/WindowManager.vue @@ -35,7 +35,7 @@ const builtInWindows = ref([]) const systemService = inject('systemService') // 添加内置应用窗口 -const addBuiltInWindow = (windowId: string, appId: string) => { +const addBuiltInWindow = async (windowId: string, appId: string) => { // 检查应用是否存在 const appRegistration = appRegistry.getApp(appId) if (!appRegistration) { @@ -50,11 +50,23 @@ const addBuiltInWindow = (windowId: string, appId: string) => { 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: appRegistration.component, + component, props: { windowId, appId @@ -99,9 +111,9 @@ onMounted(() => { const eventService = systemService.getEventService() // 监听内置应用窗口创建事件 - const subscriberId = eventService.subscribe('system', 'built-in-window-created', (message) => { + const subscriberId = eventService.subscribe('system', 'built-in-window-created', async (message) => { const { windowId, appId } = message.payload - addBuiltInWindow(windowId, appId) + await addBuiltInWindow(windowId, appId) }) // 监听内置应用窗口关闭事件 diff --git a/src/ui/desktop-container/DesktopContainer.vue b/src/ui/desktop-container/DesktopContainer.vue index 13d55a2..7c4b903 100644 --- a/src/ui/desktop-container/DesktopContainer.vue +++ b/src/ui/desktop-container/DesktopContainer.vue @@ -144,7 +144,7 @@ const startApp = async (appId: string) => { // 使用主应用的窗口管理器来渲染内置应用 if (windowManager?.value) { - windowManager.value.addBuiltInWindow(windowInstance.id, appId) + await windowManager.value.addBuiltInWindow(windowInstance.id, appId) console.log(`[主应用] 使用窗口管理器渲染内置应用: ${appId}`) } else { console.error('窗口管理器未初始化') diff --git a/vite.config.ts b/vite.config.ts index ece789d..90308a3 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -26,5 +26,26 @@ export default defineConfig({ '@': fileURLToPath(new URL('./src', import.meta.url)), 'vue': 'vue/dist/vue.esm-bundler.js' } + }, + build: { + rollupOptions: { + output: { + // 配置代码分割 + manualChunks: { + // 将Vue相关库打包到单独的chunk中 + vue: ['vue', 'vue-router', 'pinia'], + // 将UI库打包到单独的chunk中 + ui: ['naive-ui'], + // 将工具库打包到单独的chunk中 + utils: ['lodash', 'uuid'], + // 将VueUse打包到单独的chunk中 + vueuse: ['@vueuse/core'] + } + } + }, + // 启用压缩 + minify: 'esbuild', + // 启用CSS代码分割 + cssCodeSplit: true } -}) +}) \ No newline at end of file