保存
This commit is contained in:
@@ -16,6 +16,7 @@ export function registerBuiltInApps() {
|
|||||||
icon: '🧮',
|
icon: '🧮',
|
||||||
permissions: ['storage'],
|
permissions: ['storage'],
|
||||||
window: {
|
window: {
|
||||||
|
title: '计算器',
|
||||||
width: 400,
|
width: 400,
|
||||||
height: 600,
|
height: 600,
|
||||||
minWidth: 320,
|
minWidth: 320,
|
||||||
@@ -46,6 +47,7 @@ export function registerBuiltInApps() {
|
|||||||
icon: '📝',
|
icon: '📝',
|
||||||
permissions: ['storage', 'notification'],
|
permissions: ['storage', 'notification'],
|
||||||
window: {
|
window: {
|
||||||
|
title: '记事本',
|
||||||
width: 800,
|
width: 800,
|
||||||
height: 600,
|
height: 600,
|
||||||
minWidth: 400,
|
minWidth: 400,
|
||||||
@@ -74,6 +76,7 @@ export function registerBuiltInApps() {
|
|||||||
icon: '✅',
|
icon: '✅',
|
||||||
permissions: ['storage', 'notification'],
|
permissions: ['storage', 'notification'],
|
||||||
window: {
|
window: {
|
||||||
|
title: '待办事项',
|
||||||
width: 600,
|
width: 600,
|
||||||
height: 700,
|
height: 700,
|
||||||
minWidth: 400,
|
minWidth: 400,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import type { WindowConfig } from '@/services/WindowFormService.ts'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 内置应用清单接口
|
* 内置应用清单接口
|
||||||
*/
|
*/
|
||||||
@@ -33,48 +35,7 @@ export interface InternalAppManifest {
|
|||||||
/**
|
/**
|
||||||
* 窗体配置信息
|
* 窗体配置信息
|
||||||
*/
|
*/
|
||||||
window: {
|
window: WindowConfig
|
||||||
/**
|
|
||||||
* 窗体宽度
|
|
||||||
*/
|
|
||||||
width: number
|
|
||||||
/**
|
|
||||||
* 窗体高度
|
|
||||||
*/
|
|
||||||
height: number
|
|
||||||
/**
|
|
||||||
* 窗体最小宽度
|
|
||||||
*/
|
|
||||||
minWidth?: number
|
|
||||||
/**
|
|
||||||
* 窗体最小高度
|
|
||||||
*/
|
|
||||||
minHeight?: number
|
|
||||||
/**
|
|
||||||
* 窗体最大宽度
|
|
||||||
*/
|
|
||||||
maxWidth?: number
|
|
||||||
/**
|
|
||||||
* 窗体最大高度
|
|
||||||
*/
|
|
||||||
maxHeight?: number
|
|
||||||
/**
|
|
||||||
* 是否可调整大小
|
|
||||||
*/
|
|
||||||
resizable?: boolean
|
|
||||||
/**
|
|
||||||
* 是否可最小化
|
|
||||||
*/
|
|
||||||
minimizable?: boolean
|
|
||||||
/**
|
|
||||||
* 是否可最大化
|
|
||||||
*/
|
|
||||||
maximizable?: boolean
|
|
||||||
/**
|
|
||||||
* 是否可关闭
|
|
||||||
*/
|
|
||||||
closable?: boolean
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* 应用分类
|
* 应用分类
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import type { ResourceType } from '@/services/ResourceService'
|
|||||||
/**
|
/**
|
||||||
* 窗体数据更新参数
|
* 窗体数据更新参数
|
||||||
*/
|
*/
|
||||||
export interface WindowFormDataUpdateParams {
|
export interface IWindowFormDataUpdateParams {
|
||||||
/** 窗口id */
|
/** 窗口id */
|
||||||
id: string
|
id: string
|
||||||
/** 窗口状态 */
|
/** 窗口状态 */
|
||||||
@@ -25,12 +25,19 @@ export interface WindowFormDataUpdateParams {
|
|||||||
* @interface IEventMap 事件定义 键是事件名称,值是事件处理函数
|
* @interface IEventMap 事件定义 键是事件名称,值是事件处理函数
|
||||||
*/
|
*/
|
||||||
export interface IEventMap {
|
export interface IEventMap {
|
||||||
|
/**
|
||||||
|
* 事件处理函数映射
|
||||||
|
*/
|
||||||
|
[key: string]: (...args: any[]) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISystemBuiltInEventMap extends IEventMap {
|
||||||
// 系统就绪事件
|
// 系统就绪事件
|
||||||
onSystemReady: (data: { timestamp: Date; services: string[] }) => void
|
onSystemReady: (data: { timestamp: Date; services: string[] }) => void
|
||||||
|
|
||||||
// 窗体相关事件
|
// 窗体相关事件
|
||||||
onWindowStateChanged: (windowId: string, newState: string, oldState: string) => void
|
onWindowStateChanged: (windowId: string, newState: string, oldState: string) => void
|
||||||
onWindowFormDataUpdate: (data: WindowFormDataUpdateParams) => void
|
onWindowFormDataUpdate: (data: IWindowFormDataUpdateParams) => void
|
||||||
onWindowFormResizeStart: (windowId: string) => void
|
onWindowFormResizeStart: (windowId: string) => void
|
||||||
onWindowFormResizing: (windowId: string, width: number, height: number) => void
|
onWindowFormResizing: (windowId: string, width: number, height: number) => void
|
||||||
onWindowFormResizeEnd: (windowId: string) => void
|
onWindowFormResizeEnd: (windowId: string) => void
|
||||||
@@ -42,11 +49,6 @@ export interface IEventMap {
|
|||||||
// 资源相关事件
|
// 资源相关事件
|
||||||
onResourceQuotaExceeded: (appId: string, resourceType: ResourceType) => void
|
onResourceQuotaExceeded: (appId: string, resourceType: ResourceType) => void
|
||||||
onPerformanceAlert: (data: { type: 'memory' | 'cpu'; usage: number; limit: number }) => void
|
onPerformanceAlert: (data: { type: 'memory' | 'cpu'; usage: number; limit: number }) => void
|
||||||
|
|
||||||
/**
|
|
||||||
* 事件处理函数映射
|
|
||||||
*/
|
|
||||||
[key: string]: (...args: any[]) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { reactive } from 'vue'
|
import { reactive, ref } from 'vue'
|
||||||
import type { ResourceService } from './ResourceService'
|
import type { ResourceService } from './ResourceService'
|
||||||
import type { ApplicationSandboxEngine } from './ApplicationSandboxEngine'
|
import type { ApplicationSandboxEngine } from './ApplicationSandboxEngine'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { externalAppDiscovery } from './ExternalAppDiscovery'
|
import { externalAppDiscovery } from './ExternalAppDiscovery'
|
||||||
import type { WindowFormService } from '@/services/WindowFormService.ts'
|
import type { WindowFormService } from '@/services/WindowFormService.ts'
|
||||||
|
import { type AppRegistration, appRegistry } from '@/apps'
|
||||||
|
import windowManager from '@/ui/components/WindowManager.vue'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用状态枚举
|
* 应用状态枚举
|
||||||
@@ -110,13 +112,20 @@ export interface AppLifecycleEvents {
|
|||||||
onStateChanged: (appId: string, newState: AppLifecycleState, oldState: AppLifecycleState) => void
|
onStateChanged: (appId: string, newState: AppLifecycleState, oldState: AppLifecycleState) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface BuiltInWindowForm {
|
||||||
|
id: string
|
||||||
|
appId: string
|
||||||
|
component: any
|
||||||
|
props: Record<string, any>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用生命周期管理器
|
* 应用生命周期管理器
|
||||||
*/
|
*/
|
||||||
export class ApplicationLifecycleManager {
|
export class ApplicationLifecycleManager {
|
||||||
private installedApps = reactive(new Map<string, AppInstance>())
|
private installedApps = reactive(new Map<string, AppInstance>())
|
||||||
private runningProcesses = reactive(new Map<string, AppInstance>())
|
private runningProcesses = reactive(new Map<string, AppInstance>())
|
||||||
private appFiles = new Map<string, Map<string, Blob | string>>() // 应用文件存储
|
private builtInWindowForms = reactive(new Map<string, BuiltInWindowForm>())
|
||||||
|
|
||||||
private windowFormService: WindowFormService
|
private windowFormService: WindowFormService
|
||||||
private resourceService: ResourceService
|
private resourceService: ResourceService
|
||||||
@@ -132,10 +141,65 @@ export class ApplicationLifecycleManager {
|
|||||||
this.sandboxEngine = sandboxEngine
|
this.sandboxEngine = sandboxEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getBuiltInWindowForms() {
|
||||||
|
return this.builtInWindowForms
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动应用
|
* 启动应用
|
||||||
*/
|
*/
|
||||||
async startApp(appId: string, options: AppStartOptions = {}): Promise<string> {
|
async startApp(appId: string, options: AppStartOptions = {}) {
|
||||||
|
// 检查应用是否是内置应用
|
||||||
|
if (appRegistry.hasApp(appId)) {
|
||||||
|
await this.startBuiltInApp(appId, options)
|
||||||
|
} else {
|
||||||
|
await this.startExternalApp(appId, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async startBuiltInApp(appId: string, options: AppStartOptions = {}) {
|
||||||
|
const appRegistration = appRegistry.getApp(appId)
|
||||||
|
if (!appRegistration) {
|
||||||
|
console.error(`内置应用 ${appId} 不存在`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否已在运行
|
||||||
|
if (this.isAppRunning(appId)) {
|
||||||
|
console.log(`应用 ${appRegistration.manifest.name} 已在运行`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const windowInstance = await this.windowFormService.createWindow(appId, appRegistration.manifest.window)
|
||||||
|
|
||||||
|
// 处理异步组件加载
|
||||||
|
let component = appRegistration.component
|
||||||
|
if (typeof component === 'function') {
|
||||||
|
try {
|
||||||
|
// 如果是函数,调用它来获取组件
|
||||||
|
component = await component()
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`加载应用组件失败: ${appId}`, error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加窗口
|
||||||
|
const windowForm: BuiltInWindowForm = {
|
||||||
|
id: windowInstance.id,
|
||||||
|
appId,
|
||||||
|
component,
|
||||||
|
props: {
|
||||||
|
windowId: windowInstance.id,
|
||||||
|
appId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.builtInWindowForms.set(windowInstance.id, windowForm)
|
||||||
|
console.log(this.builtInWindowForms)
|
||||||
|
}
|
||||||
|
|
||||||
|
private async startExternalApp(appId: string, options: AppStartOptions = {}) {
|
||||||
let app = this.installedApps.get(appId)
|
let app = this.installedApps.get(appId)
|
||||||
|
|
||||||
console.log('-----------------------------')
|
console.log('-----------------------------')
|
||||||
@@ -344,20 +408,15 @@ export class ApplicationLifecycleManager {
|
|||||||
* 检查应用是否正在运行
|
* 检查应用是否正在运行
|
||||||
*/
|
*/
|
||||||
isAppRunning(appId: string): boolean {
|
isAppRunning(appId: string): boolean {
|
||||||
// 首先从已安装应用中查找
|
let app;
|
||||||
let app = this.installedApps.get(appId)
|
|
||||||
|
|
||||||
// 如果未找到,从运行进程列表中查找(可能是外部应用的临时实例)
|
for (const runningApp of this.runningProcesses.values()) {
|
||||||
if (!app) {
|
if (runningApp.id === appId) {
|
||||||
for (const runningApp of this.runningProcesses.values()) {
|
app = runningApp
|
||||||
if (runningApp.id === appId) {
|
break
|
||||||
app = runningApp
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return app?.state === AppLifecycleState.RUNNING
|
||||||
return app?.state === AppLifecycleState.RUNNING || app?.state === AppLifecycleState.SUSPENDED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
/**
|
|
||||||
* 全局错误处理器接口
|
|
||||||
* 负责统一处理系统中的所有错误
|
|
||||||
*/
|
|
||||||
export interface IErrorHandler {
|
|
||||||
/**
|
|
||||||
* 处理应用错误
|
|
||||||
* @param error 错误对象
|
|
||||||
* @param context 错误上下文信息
|
|
||||||
* @returns 是否成功处理了错误
|
|
||||||
*/
|
|
||||||
handleError(error: Error | any, context?: ErrorContext): boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理未捕获的异常
|
|
||||||
*/
|
|
||||||
setupGlobalErrorHandlers(): void
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取最近的错误记录
|
|
||||||
* @param limit 获取的最大数量
|
|
||||||
*/
|
|
||||||
getRecentErrors(limit?: number): ErrorRecord[]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 错误上下文信息
|
|
||||||
*/
|
|
||||||
export interface ErrorContext {
|
|
||||||
/**
|
|
||||||
* 错误来源组件或服务名称
|
|
||||||
*/
|
|
||||||
source?: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 错误发生的操作
|
|
||||||
*/
|
|
||||||
operation?: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 相关的应用ID
|
|
||||||
*/
|
|
||||||
appId?: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 其他自定义信息
|
|
||||||
*/
|
|
||||||
[key: string]: any
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 错误记录
|
|
||||||
*/
|
|
||||||
export interface ErrorRecord {
|
|
||||||
/**
|
|
||||||
* 错误ID
|
|
||||||
*/
|
|
||||||
id: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 错误对象
|
|
||||||
*/
|
|
||||||
error: Error | any
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 错误上下文
|
|
||||||
*/
|
|
||||||
context?: ErrorContext
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 错误发生时间
|
|
||||||
*/
|
|
||||||
timestamp: Date
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否已处理
|
|
||||||
*/
|
|
||||||
handled: boolean
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
import { reactive, ref } from 'vue'
|
import { reactive, ref } from 'vue'
|
||||||
import { EventBuilderImpl } from '@/events/impl/EventBuilderImpl'
|
import { EventBuilderImpl } from '@/events/impl/EventBuilderImpl'
|
||||||
import type { IEventBuilder, IEventMap, WindowFormDataUpdateParams } from '@/events/IEventBuilder'
|
import type {
|
||||||
|
IEventBuilder,
|
||||||
|
ISystemBuiltInEventMap,
|
||||||
|
IWindowFormDataUpdateParams
|
||||||
|
} from '@/events/IEventBuilder'
|
||||||
import type { ResourceType } from './ResourceService'
|
import type { ResourceType } from './ResourceService'
|
||||||
|
|
||||||
// 导入所有服务
|
// 导入所有服务
|
||||||
@@ -56,7 +60,7 @@ export class SystemServiceIntegration {
|
|||||||
private startTime: Date
|
private startTime: Date
|
||||||
|
|
||||||
// 核心服务实例
|
// 核心服务实例
|
||||||
private eventBus: IEventBuilder<any>
|
private eventBus: IEventBuilder<ISystemBuiltInEventMap>
|
||||||
private windowFormService!: WindowFormService
|
private windowFormService!: WindowFormService
|
||||||
private resourceService!: ResourceService
|
private resourceService!: ResourceService
|
||||||
private sandboxEngine!: ApplicationSandboxEngine
|
private sandboxEngine!: ApplicationSandboxEngine
|
||||||
@@ -88,7 +92,7 @@ export class SystemServiceIntegration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.startTime = new Date()
|
this.startTime = new Date()
|
||||||
this.eventBus = new EventBuilderImpl<any>()
|
this.eventBus = new EventBuilderImpl<ISystemBuiltInEventMap>()
|
||||||
|
|
||||||
this.setupGlobalErrorHandling()
|
this.setupGlobalErrorHandling()
|
||||||
}
|
}
|
||||||
@@ -334,7 +338,7 @@ export class SystemServiceIntegration {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 监听窗体数据更新事件
|
// 监听窗体数据更新事件
|
||||||
this.eventBus.addEventListener('onWindowFormDataUpdate', (data: WindowFormDataUpdateParams) => {
|
this.eventBus.addEventListener('onWindowFormDataUpdate', (data: IWindowFormDataUpdateParams) => {
|
||||||
console.log(`[SystemIntegration] 接收到窗体数据更新事件:`, data)
|
console.log(`[SystemIntegration] 接收到窗体数据更新事件:`, data)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,6 @@ export enum WindowState {
|
|||||||
ERROR = 'error'
|
ERROR = 'error'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 窗体配置接口
|
|
||||||
*/
|
|
||||||
/**
|
/**
|
||||||
* 窗体配置接口
|
* 窗体配置接口
|
||||||
*/
|
*/
|
||||||
@@ -28,7 +25,7 @@ export interface WindowConfig {
|
|||||||
/**
|
/**
|
||||||
* 窗体标题
|
* 窗体标题
|
||||||
*/
|
*/
|
||||||
title: string
|
title?: string
|
||||||
/**
|
/**
|
||||||
* 窗体宽度(像素)
|
* 窗体宽度(像素)
|
||||||
*/
|
*/
|
||||||
@@ -570,7 +567,7 @@ export class WindowFormService {
|
|||||||
// 窗体标题
|
// 窗体标题
|
||||||
const title = document.createElement('span')
|
const title = document.createElement('span')
|
||||||
title.className = 'window-title'
|
title.className = 'window-title'
|
||||||
title.textContent = windowInstance.config.title
|
title.textContent = windowInstance.config.title || ''
|
||||||
title.style.cssText = `
|
title.style.cssText = `
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
/**
|
|
||||||
* 服务容器接口
|
|
||||||
* 负责管理和提供所有系统服务的实例
|
|
||||||
*/
|
|
||||||
export interface IServiceContainer {
|
|
||||||
/**
|
|
||||||
* 注册服务
|
|
||||||
* @param id 服务唯一标识符
|
|
||||||
* @param factory 服务工厂函数
|
|
||||||
* @param dependencies 依赖的服务ID数组
|
|
||||||
*/
|
|
||||||
register<T>(id: string, factory: ServiceFactory<T>, dependencies?: string[]): void
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取服务实例
|
|
||||||
* @param id 服务唯一标识符
|
|
||||||
* @returns 服务实例
|
|
||||||
* @throws 当服务未注册时抛出错误
|
|
||||||
*/
|
|
||||||
getService<T>(id: string): T
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查服务是否已注册
|
|
||||||
* @param id 服务唯一标识符
|
|
||||||
* @returns 是否已注册
|
|
||||||
*/
|
|
||||||
has(id: string): boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化所有服务
|
|
||||||
* 按照依赖关系顺序初始化服务
|
|
||||||
*/
|
|
||||||
initialize(): void
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务工厂函数类型
|
|
||||||
* @param container 服务容器实例
|
|
||||||
* @returns 服务实例
|
|
||||||
*/
|
|
||||||
export type ServiceFactory<T> = (container: IServiceContainer) => T
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
import type { IServiceContainer, ServiceFactory } from './IServiceContainer'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务注册信息接口
|
|
||||||
*/
|
|
||||||
interface ServiceRegistration<T> {
|
|
||||||
factory: ServiceFactory<T>
|
|
||||||
dependencies: string[]
|
|
||||||
instance: T | null
|
|
||||||
initialized: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务容器实现
|
|
||||||
* 使用工厂模式和依赖注入模式管理服务实例
|
|
||||||
*/
|
|
||||||
export class ServiceContainerImpl implements IServiceContainer {
|
|
||||||
private services = new Map<string, ServiceRegistration<any>>()
|
|
||||||
private initializationStack: string[] = []
|
|
||||||
private initialized = false
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册服务
|
|
||||||
* @param id 服务唯一标识符
|
|
||||||
* @param factory 服务工厂函数
|
|
||||||
* @param dependencies 依赖的服务ID数组
|
|
||||||
*/
|
|
||||||
public register<T>(id: string, factory: ServiceFactory<T>, dependencies: string[] = []): void {
|
|
||||||
if (this.initialized) {
|
|
||||||
throw new Error(`无法在容器初始化后注册服务: ${id}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.services.set(id, {
|
|
||||||
factory,
|
|
||||||
dependencies,
|
|
||||||
instance: null,
|
|
||||||
initialized: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取服务实例
|
|
||||||
* @param id 服务唯一标识符
|
|
||||||
* @returns 服务实例
|
|
||||||
* @throws 当服务未注册或发生循环依赖时抛出错误
|
|
||||||
*/
|
|
||||||
public getService<T>(id: string): T {
|
|
||||||
const registration = this.services.get(id)
|
|
||||||
|
|
||||||
if (!registration) {
|
|
||||||
throw new Error(`未注册的服务: ${id}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测循环依赖
|
|
||||||
if (this.initializationStack.includes(id)) {
|
|
||||||
throw new Error(`检测到循环依赖: ${this.initializationStack.join(' -> ')} -> ${id}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果服务实例尚未创建,则创建它
|
|
||||||
if (!registration.instance) {
|
|
||||||
this.initializationStack.push(id)
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 首先确保所有依赖都已初始化
|
|
||||||
for (const dependencyId of registration.dependencies) {
|
|
||||||
this.getService(dependencyId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建服务实例
|
|
||||||
registration.instance = registration.factory(this)
|
|
||||||
registration.initialized = true
|
|
||||||
} finally {
|
|
||||||
this.initializationStack.pop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return registration.instance
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查服务是否已注册
|
|
||||||
* @param id 服务唯一标识符
|
|
||||||
* @returns 是否已注册
|
|
||||||
*/
|
|
||||||
public has(id: string): boolean {
|
|
||||||
return this.services.has(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化所有服务
|
|
||||||
* 按照依赖关系顺序初始化服务
|
|
||||||
*/
|
|
||||||
public initialize(): void {
|
|
||||||
if (this.initialized) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 初始化所有服务(按依赖顺序)
|
|
||||||
this.services.forEach((_, id) => {
|
|
||||||
this.getService(id)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.initialized = true
|
|
||||||
} catch (error) {
|
|
||||||
console.error('服务容器初始化失败:', error)
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有已注册服务的ID列表
|
|
||||||
* @returns 服务ID列表
|
|
||||||
*/
|
|
||||||
public getRegisteredServices(): string[] {
|
|
||||||
return Array.from(this.services.keys())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清除服务实例(用于测试)
|
|
||||||
* @param id 服务ID,如果不提供则清除所有服务
|
|
||||||
*/
|
|
||||||
public clear(id?: string): void {
|
|
||||||
if (id) {
|
|
||||||
const registration = this.services.get(id)
|
|
||||||
if (registration) {
|
|
||||||
registration.instance = null
|
|
||||||
registration.initialized = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.services.forEach((registration) => {
|
|
||||||
registration.instance = null
|
|
||||||
registration.initialized = false
|
|
||||||
})
|
|
||||||
this.initialized = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
import { ServiceRegistry, ServiceIds } from './ServiceRegistry'
|
|
||||||
import type { IServiceContainer } from './IServiceContainer'
|
|
||||||
import { initializePendingServices } from './decorators'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务提供者
|
|
||||||
* 提供静态方法访问所有系统服务
|
|
||||||
*/
|
|
||||||
export class ServiceProvider {
|
|
||||||
private static container: IServiceContainer | null = null
|
|
||||||
private static initialized = false
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化服务提供者
|
|
||||||
* 注册并初始化所有服务
|
|
||||||
*/
|
|
||||||
public static initialize(): void {
|
|
||||||
if (this.initialized) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const registry = ServiceRegistry.getInstance()
|
|
||||||
registry.registerAllServices()
|
|
||||||
|
|
||||||
this.container = registry.getContainer()
|
|
||||||
this.container.initialize()
|
|
||||||
|
|
||||||
// 初始化所有使用@Service装饰器的服务
|
|
||||||
initializePendingServices()
|
|
||||||
|
|
||||||
this.initialized = true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取服务实例
|
|
||||||
* @param id 服务ID
|
|
||||||
* @returns 服务实例
|
|
||||||
*/
|
|
||||||
public static getService<T>(id: string): T {
|
|
||||||
if (!this.container) {
|
|
||||||
throw new Error('服务提供者尚未初始化')
|
|
||||||
}
|
|
||||||
return this.container.getService<T>(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取资源服务
|
|
||||||
*/
|
|
||||||
public static getResourceService(): any {
|
|
||||||
return this.getService(ServiceIds.RESOURCE_SERVICE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取窗口表单服务
|
|
||||||
*/
|
|
||||||
public static getWindowFormService(): any {
|
|
||||||
return this.getService(ServiceIds.WINDOW_FORM_SERVICE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取沙箱引擎
|
|
||||||
*/
|
|
||||||
public static getSandboxEngine(): any {
|
|
||||||
return this.getService(ServiceIds.SANDBOX_ENGINE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取生命周期管理器
|
|
||||||
*/
|
|
||||||
public static getLifecycleManager(): any {
|
|
||||||
return this.getService(ServiceIds.LIFECYCLE_MANAGER)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取系统服务
|
|
||||||
*/
|
|
||||||
public static getSystemService(): any {
|
|
||||||
return this.getService(ServiceIds.SYSTEM_SERVICE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取事件构建器
|
|
||||||
*/
|
|
||||||
public static getEventBuilder(): any {
|
|
||||||
return this.getService(ServiceIds.EVENT_BUILDER)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取外部应用发现服务
|
|
||||||
*/
|
|
||||||
public static getExternalAppDiscovery(): any {
|
|
||||||
return this.getService(ServiceIds.EXTERNAL_APP_DISCOVERY)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取错误处理服务
|
|
||||||
*/
|
|
||||||
public static getErrorHandler(): any {
|
|
||||||
return this.getService(ServiceIds.ERROR_HANDLER)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查是否已初始化
|
|
||||||
*/
|
|
||||||
public static isInitialized(): boolean {
|
|
||||||
return this.initialized
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取服务容器(仅用于高级场景)
|
|
||||||
*/
|
|
||||||
public static getContainer(): IServiceContainer | null {
|
|
||||||
return this.container
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建服务工厂函数
|
|
||||||
* @param constructor 服务构造函数
|
|
||||||
* @param dependencyIds 依赖的服务ID数组
|
|
||||||
* @returns 服务工厂函数
|
|
||||||
*/
|
|
||||||
export function createServiceFactory<T>(
|
|
||||||
constructor: new (...args: any[]) => T,
|
|
||||||
dependencyIds: string[] = []
|
|
||||||
): (container: IServiceContainer) => T {
|
|
||||||
return (container: IServiceContainer) => {
|
|
||||||
const dependencies = dependencyIds.map((id) => container.getService(id))
|
|
||||||
return new constructor(...dependencies)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务装饰器,用于标记需要注入的服务
|
|
||||||
*/
|
|
||||||
export function Inject(serviceId: string): PropertyDecorator {
|
|
||||||
return (target: Object, propertyKey: string | symbol) => {
|
|
||||||
const descriptor = {
|
|
||||||
get: () => {
|
|
||||||
return ServiceProvider.getService(serviceId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Object.defineProperty(target, propertyKey, descriptor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
import type { IServiceContainer, ServiceFactory } from './IServiceContainer'
|
|
||||||
import { ServiceContainerImpl } from './ServiceContainerImpl'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务ID常量
|
|
||||||
*/
|
|
||||||
export enum ServiceIds {
|
|
||||||
RESOURCE_SERVICE = 'resourceService',
|
|
||||||
WINDOW_FORM_SERVICE = 'windowFormService',
|
|
||||||
SANDBOX_ENGINE = 'sandboxEngine',
|
|
||||||
LIFECYCLE_MANAGER = 'lifecycleManager',
|
|
||||||
SYSTEM_SERVICE = 'systemService',
|
|
||||||
EVENT_BUILDER = 'eventBuilder',
|
|
||||||
EXTERNAL_APP_DISCOVERY = 'externalAppDiscovery',
|
|
||||||
ERROR_HANDLER = 'errorHandler'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务注册表
|
|
||||||
* 负责注册所有系统服务
|
|
||||||
*/
|
|
||||||
export class ServiceRegistry {
|
|
||||||
private static instance: ServiceRegistry
|
|
||||||
private container: IServiceContainer
|
|
||||||
|
|
||||||
private constructor() {
|
|
||||||
this.container = new ServiceContainerImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取服务注册表单例
|
|
||||||
*/
|
|
||||||
public static getInstance(): ServiceRegistry {
|
|
||||||
if (!ServiceRegistry.instance) {
|
|
||||||
ServiceRegistry.instance = new ServiceRegistry()
|
|
||||||
}
|
|
||||||
return ServiceRegistry.instance
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取服务容器实例
|
|
||||||
*/
|
|
||||||
public getContainer(): IServiceContainer {
|
|
||||||
return this.container
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册所有服务
|
|
||||||
* 注意:服务注册顺序应按照依赖关系排列
|
|
||||||
*/
|
|
||||||
public registerAllServices(): void {
|
|
||||||
// 注册基本服务 - 这些服务没有其他依赖
|
|
||||||
this.registerEventBuilder()
|
|
||||||
this.registerExternalAppDiscovery()
|
|
||||||
this.registerResourceService()
|
|
||||||
this.registerErrorHandler()
|
|
||||||
|
|
||||||
// 注册核心服务 - 按照依赖关系顺序注册
|
|
||||||
this.registerWindowFormService()
|
|
||||||
this.registerSandboxEngine()
|
|
||||||
this.registerLifecycleManager()
|
|
||||||
this.registerSystemService()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册事件构建器服务
|
|
||||||
*/
|
|
||||||
private registerEventBuilder(): void {
|
|
||||||
this.container.register(ServiceIds.EVENT_BUILDER, async () => {
|
|
||||||
const { EventBuilderImpl } = await import('@/events/impl/EventBuilderImpl')
|
|
||||||
return new EventBuilderImpl()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册外部应用发现服务
|
|
||||||
*/
|
|
||||||
private registerExternalAppDiscovery(): void {
|
|
||||||
this.container.register(ServiceIds.EXTERNAL_APP_DISCOVERY, async () => {
|
|
||||||
// 延迟导入避免循环依赖
|
|
||||||
const { externalAppDiscovery } = await import('../ExternalAppDiscovery')
|
|
||||||
return externalAppDiscovery
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册资源服务
|
|
||||||
*/
|
|
||||||
private registerResourceService(): void {
|
|
||||||
this.container.register(
|
|
||||||
ServiceIds.RESOURCE_SERVICE,
|
|
||||||
async (container) => {
|
|
||||||
// 延迟导入避免循环依赖
|
|
||||||
const { ResourceService } = await import('../ResourceService')
|
|
||||||
return new ResourceService(container.getService(ServiceIds.EVENT_BUILDER))
|
|
||||||
},
|
|
||||||
[ServiceIds.EVENT_BUILDER]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册窗口表单服务
|
|
||||||
*/
|
|
||||||
private registerWindowFormService(): void {
|
|
||||||
this.container.register(
|
|
||||||
ServiceIds.WINDOW_FORM_SERVICE,
|
|
||||||
async (container) => {
|
|
||||||
// 延迟导入避免循环依赖
|
|
||||||
const { WindowFormService } = await import('../WindowFormService')
|
|
||||||
return new WindowFormService(container.getService(ServiceIds.EVENT_BUILDER))
|
|
||||||
},
|
|
||||||
[ServiceIds.EVENT_BUILDER]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册沙箱引擎服务
|
|
||||||
*/
|
|
||||||
private registerSandboxEngine(): void {
|
|
||||||
this.container.register(
|
|
||||||
ServiceIds.SANDBOX_ENGINE,
|
|
||||||
async (container) => {
|
|
||||||
// 延迟导入避免循环依赖
|
|
||||||
const { ApplicationSandboxEngine } = await import('../ApplicationSandboxEngine')
|
|
||||||
return new ApplicationSandboxEngine(
|
|
||||||
container.getService(ServiceIds.RESOURCE_SERVICE),
|
|
||||||
container
|
|
||||||
)
|
|
||||||
},
|
|
||||||
[ServiceIds.RESOURCE_SERVICE]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册生命周期管理器服务
|
|
||||||
*/
|
|
||||||
private registerLifecycleManager(): void {
|
|
||||||
this.container.register(
|
|
||||||
ServiceIds.LIFECYCLE_MANAGER,
|
|
||||||
async (container) => {
|
|
||||||
// 延迟导入避免循环依赖
|
|
||||||
const { ApplicationLifecycleManager } = await import('../ApplicationLifecycleManager')
|
|
||||||
return new ApplicationLifecycleManager(
|
|
||||||
container.getService(ServiceIds.RESOURCE_SERVICE),
|
|
||||||
container.getService(ServiceIds.SANDBOX_ENGINE),
|
|
||||||
container.getService(ServiceIds.WINDOW_FORM_SERVICE)
|
|
||||||
)
|
|
||||||
},
|
|
||||||
[
|
|
||||||
ServiceIds.RESOURCE_SERVICE,
|
|
||||||
ServiceIds.SANDBOX_ENGINE,
|
|
||||||
ServiceIds.WINDOW_FORM_SERVICE,
|
|
||||||
ServiceIds.EXTERNAL_APP_DISCOVERY
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册系统服务集成服务
|
|
||||||
*/
|
|
||||||
private registerSystemService(): void {
|
|
||||||
this.container.register(
|
|
||||||
ServiceIds.SYSTEM_SERVICE,
|
|
||||||
async (container) => {
|
|
||||||
// 延迟导入避免循环依赖
|
|
||||||
const { SystemServiceIntegration } = await import('../SystemServiceIntegration')
|
|
||||||
return new SystemServiceIntegration(container)
|
|
||||||
},
|
|
||||||
[
|
|
||||||
ServiceIds.RESOURCE_SERVICE,
|
|
||||||
ServiceIds.WINDOW_FORM_SERVICE,
|
|
||||||
ServiceIds.SANDBOX_ENGINE,
|
|
||||||
ServiceIds.LIFECYCLE_MANAGER,
|
|
||||||
ServiceIds.EVENT_BUILDER,
|
|
||||||
ServiceIds.ERROR_HANDLER
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册错误处理服务
|
|
||||||
*/
|
|
||||||
private registerErrorHandler(): void {
|
|
||||||
this.container.register(
|
|
||||||
ServiceIds.ERROR_HANDLER,
|
|
||||||
async () => {
|
|
||||||
// 延迟导入避免循环依赖
|
|
||||||
const { ErrorHandlerImpl } = await import('../impl/ErrorHandlerImpl')
|
|
||||||
return new ErrorHandlerImpl()
|
|
||||||
},
|
|
||||||
[] // 错误处理服务应尽量减少依赖,避免在错误处理过程中出现循环依赖
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,179 +0,0 @@
|
|||||||
import { ServiceRegistry } from './ServiceRegistry'
|
|
||||||
import { ServiceProvider } from './ServiceProvider'
|
|
||||||
import { SystemServiceIntegration } from '../SystemServiceIntegration'
|
|
||||||
import { ServiceContainerImpl } from './ServiceContainerImpl'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 系统启动器
|
|
||||||
* 负责初始化整个系统,包括服务容器、服务注册和启动核心服务
|
|
||||||
*/
|
|
||||||
export class SystemBootstrapper {
|
|
||||||
private static instance: SystemBootstrapper
|
|
||||||
private serviceContainer: ServiceContainerImpl
|
|
||||||
private systemService: SystemServiceIntegration | null = null
|
|
||||||
private initialized = false
|
|
||||||
|
|
||||||
private constructor() {
|
|
||||||
this.serviceContainer = new ServiceContainerImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取系统启动器实例
|
|
||||||
*/
|
|
||||||
public static getInstance(): SystemBootstrapper {
|
|
||||||
if (!SystemBootstrapper.instance) {
|
|
||||||
SystemBootstrapper.instance = new SystemBootstrapper()
|
|
||||||
}
|
|
||||||
return SystemBootstrapper.instance
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 启动整个系统
|
|
||||||
* @param config 系统配置参数
|
|
||||||
* @returns 启动成功返回true,失败返回false
|
|
||||||
*/
|
|
||||||
public async bootstrap(config?: {
|
|
||||||
debug?: boolean
|
|
||||||
autoCleanup?: boolean
|
|
||||||
cleanupInterval?: number
|
|
||||||
}): Promise<boolean> {
|
|
||||||
if (this.initialized) {
|
|
||||||
console.warn('系统已经启动')
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
console.log('开始启动系统...', config)
|
|
||||||
|
|
||||||
// 1. 初始化服务提供者
|
|
||||||
this.initializeServiceProvider()
|
|
||||||
|
|
||||||
// 2. 初始化系统服务集成层
|
|
||||||
this.initializeSystemService(config || {})
|
|
||||||
|
|
||||||
// 3. 启动所有服务
|
|
||||||
await this.startAllServices()
|
|
||||||
|
|
||||||
this.initialized = true
|
|
||||||
console.log('系统启动成功')
|
|
||||||
return true
|
|
||||||
} catch (error) {
|
|
||||||
console.error('系统启动失败:', error)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化服务提供者
|
|
||||||
* 注册并初始化所有服务
|
|
||||||
*/
|
|
||||||
private initializeServiceProvider(): void {
|
|
||||||
console.log('初始化服务提供者...')
|
|
||||||
|
|
||||||
// 初始化服务提供者,这会注册并初始化所有服务
|
|
||||||
ServiceProvider.initialize()
|
|
||||||
console.log('服务提供者初始化完成')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化系统服务集成层
|
|
||||||
* 创建并配置SystemServiceIntegration实例
|
|
||||||
*/
|
|
||||||
private initializeSystemService(config: {
|
|
||||||
debug?: boolean
|
|
||||||
autoCleanup?: boolean
|
|
||||||
cleanupInterval?: number
|
|
||||||
}): void {
|
|
||||||
console.log('初始化系统服务集成层...')
|
|
||||||
|
|
||||||
// 获取服务容器
|
|
||||||
const container = ServiceRegistry.getInstance().getContainer()
|
|
||||||
|
|
||||||
// 创建系统服务集成实例,使用传入的配置
|
|
||||||
this.systemService = new SystemServiceIntegration(container, {
|
|
||||||
debug: config.debug ?? true,
|
|
||||||
autoCleanup: config.autoCleanup ?? true,
|
|
||||||
cleanupInterval: config.cleanupInterval ?? 5 * 60 * 1000 // 默认5分钟
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log('系统服务集成层初始化完成')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 启动所有服务
|
|
||||||
*/
|
|
||||||
private async startAllServices(): Promise<void> {
|
|
||||||
console.log('启动所有服务...')
|
|
||||||
|
|
||||||
if (!this.systemService) {
|
|
||||||
throw new Error('系统服务集成层未初始化')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化系统服务
|
|
||||||
await this.systemService.initialize()
|
|
||||||
|
|
||||||
console.log('所有服务启动完成')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取系统服务实例
|
|
||||||
*/
|
|
||||||
public getSystemService(): SystemServiceIntegration | null {
|
|
||||||
return this.systemService
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查系统是否已初始化
|
|
||||||
*/
|
|
||||||
public isInitialized(): boolean {
|
|
||||||
return this.initialized
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关闭系统
|
|
||||||
*/
|
|
||||||
public async shutdown(): Promise<void> {
|
|
||||||
if (!this.initialized) {
|
|
||||||
console.warn('系统未启动')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('开始关闭系统...')
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 关闭系统服务
|
|
||||||
if (this.systemService) {
|
|
||||||
await this.systemService.shutdown()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置状态
|
|
||||||
this.systemService = null
|
|
||||||
this.initialized = false
|
|
||||||
|
|
||||||
console.log('系统已关闭')
|
|
||||||
} catch (error) {
|
|
||||||
console.error('关闭系统时发生错误:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重启系统
|
|
||||||
*/
|
|
||||||
public async restart(): Promise<boolean> {
|
|
||||||
console.log('重启系统...')
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.shutdown()
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
||||||
return await this.bootstrap()
|
|
||||||
} catch (error) {
|
|
||||||
console.error('重启系统失败:', error)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出系统启动器单例实例
|
|
||||||
*/
|
|
||||||
export const systemBootstrapper = SystemBootstrapper.getInstance()
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
/**
|
|
||||||
* 装饰器式依赖注入示例
|
|
||||||
* 展示如何使用@Service和@Inject装饰器实现类似Java的自动依赖注入
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Service, Inject } from './decorators'
|
|
||||||
import { ServiceIds } from './ServiceRegistry'
|
|
||||||
|
|
||||||
// 示例1: 基本的服务定义和注入
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户服务接口
|
|
||||||
*/
|
|
||||||
interface IUserService {
|
|
||||||
getUserName(): string
|
|
||||||
setUserName(name: string): void
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户服务实现
|
|
||||||
* 使用@Service装饰器标记为可注入服务
|
|
||||||
*/
|
|
||||||
@Service() // 自动使用类名"UserService"作为服务ID
|
|
||||||
export class UserService implements IUserService {
|
|
||||||
private userName = 'Default User'
|
|
||||||
|
|
||||||
getUserName(): string {
|
|
||||||
return this.userName
|
|
||||||
}
|
|
||||||
|
|
||||||
setUserName(name: string): void {
|
|
||||||
this.userName = name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 示例2: 带自定义ID和依赖的服务
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 日志服务
|
|
||||||
*/
|
|
||||||
@Service({
|
|
||||||
id: 'customLoggerService', // 自定义服务ID
|
|
||||||
dependencies: [] // 无依赖
|
|
||||||
})
|
|
||||||
export class LoggerService {
|
|
||||||
log(message: string): void {
|
|
||||||
console.log(`[Logger] ${new Date().toISOString()}: ${message}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
error(message: string, error?: Error): void {
|
|
||||||
console.error(`[Logger] ERROR ${new Date().toISOString()}: ${message}`, error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 示例3: 具有依赖的服务
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 认证服务
|
|
||||||
* 依赖于UserService和LoggerService
|
|
||||||
*/
|
|
||||||
@Service({
|
|
||||||
dependencies: [UserService, 'customLoggerService'] // 可以混合使用类和服务ID
|
|
||||||
})
|
|
||||||
export class AuthService {
|
|
||||||
// 按类型自动注入
|
|
||||||
@Inject()
|
|
||||||
private userService!: UserService
|
|
||||||
|
|
||||||
// 按服务ID注入
|
|
||||||
@Inject('customLoggerService')
|
|
||||||
private logger!: LoggerService
|
|
||||||
|
|
||||||
// 注入系统内置服务(使用ServiceIds)
|
|
||||||
@Inject(ServiceIds.EVENT_BUILDER)
|
|
||||||
private eventBuilder!: any
|
|
||||||
|
|
||||||
authenticate(userName: string): boolean {
|
|
||||||
this.logger.log(`尝试认证用户: ${userName}`)
|
|
||||||
|
|
||||||
if (userName) {
|
|
||||||
this.userService.setUserName(userName)
|
|
||||||
this.logger.log(`认证成功: ${userName}`)
|
|
||||||
|
|
||||||
// 使用事件构建器发送认证成功事件
|
|
||||||
if (this.eventBuilder) {
|
|
||||||
try {
|
|
||||||
this.eventBuilder.build('auth.success', { userName })
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error('发送认证事件失败', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
this.logger.error('认证失败: 用户名不能为空')
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 示例4: 在组件或业务类中使用
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户控制器
|
|
||||||
* 展示如何在业务类中使用注入的服务
|
|
||||||
*/
|
|
||||||
export class UserController {
|
|
||||||
// 按类型自动注入
|
|
||||||
@Inject()
|
|
||||||
private authService!: AuthService
|
|
||||||
|
|
||||||
// 按类型自动注入
|
|
||||||
@Inject()
|
|
||||||
private userService!: UserService
|
|
||||||
|
|
||||||
login(userName: string): boolean {
|
|
||||||
if (this.authService.authenticate(userName)) {
|
|
||||||
console.log(`用户控制器: ${this.userService.getUserName()} 已登录`)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 示例5: 复杂的依赖链
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据访问服务
|
|
||||||
*/
|
|
||||||
@Service()
|
|
||||||
export class DataAccessService {
|
|
||||||
save(data: any): void {
|
|
||||||
console.log('保存数据:', data)
|
|
||||||
}
|
|
||||||
|
|
||||||
get(id: string): any {
|
|
||||||
console.log(`获取数据ID: ${id}`)
|
|
||||||
return { id, name: '示例数据' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户管理服务
|
|
||||||
* 依赖于DataAccessService、UserService和LoggerService
|
|
||||||
*/
|
|
||||||
@Service({
|
|
||||||
dependencies: [DataAccessService, UserService, LoggerService]
|
|
||||||
})
|
|
||||||
export class UserManagementService {
|
|
||||||
@Inject()
|
|
||||||
private dataAccessService!: DataAccessService
|
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private userService!: UserService
|
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private loggerService!: LoggerService
|
|
||||||
|
|
||||||
updateUserProfile(userId: string, profile: any): boolean {
|
|
||||||
try {
|
|
||||||
this.loggerService.log(`更新用户${userId}的资料`)
|
|
||||||
const currentUser = this.userService.getUserName()
|
|
||||||
|
|
||||||
const userData = {
|
|
||||||
...profile,
|
|
||||||
userId,
|
|
||||||
updatedBy: currentUser,
|
|
||||||
updatedAt: new Date()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dataAccessService.save(userData)
|
|
||||||
this.loggerService.log(`用户${userId}资料更新成功`)
|
|
||||||
return true
|
|
||||||
} catch (error) {
|
|
||||||
this.loggerService.error('更新用户资料失败', error)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 运行示例
|
|
||||||
* 注意:此函数需要在ServiceProvider初始化后调用
|
|
||||||
*/
|
|
||||||
export async function runDecoratorExample(): Promise<void> {
|
|
||||||
try {
|
|
||||||
console.log('\n=== 开始运行装饰器式DI示例 ===')
|
|
||||||
|
|
||||||
// 创建控制器实例
|
|
||||||
const userController = new UserController()
|
|
||||||
|
|
||||||
// 测试登录功能
|
|
||||||
userController.login('张三')
|
|
||||||
|
|
||||||
// 测试用户管理服务
|
|
||||||
const userManagementService = new UserManagementService()
|
|
||||||
userManagementService.updateUserProfile('user123', {
|
|
||||||
displayName: '张三',
|
|
||||||
email: 'zhangsan@example.com'
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log('=== 装饰器式DI示例运行完成 ===\n')
|
|
||||||
} catch (error) {
|
|
||||||
console.error('示例运行失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
/**
|
|
||||||
* 依赖注入装饰器
|
|
||||||
* 提供类似Java的自动注入功能
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { ServiceProvider } from './ServiceProvider'
|
|
||||||
import { ServiceRegistry } from './ServiceRegistry'
|
|
||||||
import 'reflect-metadata';
|
|
||||||
|
|
||||||
// 定义构造函数类型
|
|
||||||
type Constructor<T = any> = new (...args: any[]) => T
|
|
||||||
|
|
||||||
// 存储类到服务ID的映射
|
|
||||||
const classToServiceIdMap = new Map<Constructor, string>()
|
|
||||||
// 存储服务ID到类的映射
|
|
||||||
const serviceIdToClassMap = new Map<string, Constructor>()
|
|
||||||
// 存储需要延迟注册的服务
|
|
||||||
const pendingServices: Array<{
|
|
||||||
serviceClass: Constructor
|
|
||||||
serviceId: string
|
|
||||||
dependencies: Array<string | Constructor>
|
|
||||||
}> = []
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务装饰器
|
|
||||||
* 用于标记一个类作为可注入的服务
|
|
||||||
* @param options 服务配置选项
|
|
||||||
*/
|
|
||||||
export function Service(options?: {
|
|
||||||
/** 自定义服务ID,如果不提供则使用类名 */
|
|
||||||
id?: string
|
|
||||||
/** 服务依赖,可以是服务ID字符串或依赖类 */
|
|
||||||
dependencies?: Array<string | Constructor>
|
|
||||||
/** 是否为单例模式,默认为true */
|
|
||||||
singleton?: boolean
|
|
||||||
}): ClassDecorator {
|
|
||||||
return (target: Function) => {
|
|
||||||
// 断言target为Constructor类型
|
|
||||||
const serviceClass = target as Constructor
|
|
||||||
const serviceId = options?.id || target.name
|
|
||||||
const dependencies = options?.dependencies || []
|
|
||||||
|
|
||||||
// 保存映射关系
|
|
||||||
classToServiceIdMap.set(serviceClass, serviceId)
|
|
||||||
serviceIdToClassMap.set(serviceId, serviceClass)
|
|
||||||
|
|
||||||
// 将服务添加到待注册列表
|
|
||||||
pendingServices.push({
|
|
||||||
serviceClass,
|
|
||||||
serviceId,
|
|
||||||
dependencies
|
|
||||||
})
|
|
||||||
|
|
||||||
// 尝试注册服务
|
|
||||||
tryRegisterPendingServices()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注入装饰器
|
|
||||||
* 用于自动注入服务实例
|
|
||||||
* @param dependency 依赖的服务类或服务ID
|
|
||||||
*/
|
|
||||||
export function Inject(dependency?: Function | string): PropertyDecorator {
|
|
||||||
return (target: Object, propertyKey: string | symbol) => {
|
|
||||||
// 获取属性的类型(如果使用了TypeScript)
|
|
||||||
const propertyType = Reflect.getMetadata('design:type', target, propertyKey)
|
|
||||||
|
|
||||||
const descriptor = {
|
|
||||||
get: () => {
|
|
||||||
try {
|
|
||||||
let serviceId: string
|
|
||||||
|
|
||||||
if (typeof dependency === 'string') {
|
|
||||||
// 直接使用提供的服务ID
|
|
||||||
serviceId = dependency
|
|
||||||
} else if (dependency) {
|
|
||||||
// 使用提供的类获取服务ID
|
|
||||||
serviceId = getServiceIdForClass(dependency)
|
|
||||||
} else if (propertyType) {
|
|
||||||
// 使用属性类型获取服务ID
|
|
||||||
serviceId = getServiceIdForClass(propertyType)
|
|
||||||
} else {
|
|
||||||
throw new Error(`无法确定属性 ${String(propertyKey)} 的注入类型`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ServiceProvider.getService(serviceId)
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`注入服务失败: ${String(propertyKey)}`, error)
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(target, propertyKey, descriptor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取类对应的服务ID
|
|
||||||
* @param cls 服务类
|
|
||||||
*/
|
|
||||||
function getServiceIdForClass(cls: Function): string {
|
|
||||||
const serviceId = classToServiceIdMap.get(cls)
|
|
||||||
if (!serviceId) {
|
|
||||||
throw new Error(`类 ${cls.name} 未注册为服务`)
|
|
||||||
}
|
|
||||||
return serviceId
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 尝试注册所有待注册的服务
|
|
||||||
*/
|
|
||||||
function tryRegisterPendingServices(): void {
|
|
||||||
if (pendingServices.length === 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const registry = ServiceRegistry.getInstance()
|
|
||||||
const container = registry.getContainer()
|
|
||||||
|
|
||||||
// 处理所有待注册的服务
|
|
||||||
for (const pendingService of pendingServices.slice()) {
|
|
||||||
// 解析依赖的服务ID
|
|
||||||
const resolvedDependencies: string[] = []
|
|
||||||
for (const dep of pendingService.dependencies) {
|
|
||||||
if (typeof dep === 'string') {
|
|
||||||
resolvedDependencies.push(dep)
|
|
||||||
} else if (typeof dep === 'function') {
|
|
||||||
const depServiceId = classToServiceIdMap.get(dep)
|
|
||||||
if (depServiceId) {
|
|
||||||
resolvedDependencies.push(depServiceId)
|
|
||||||
} else {
|
|
||||||
// 依赖尚未注册,跳过当前服务
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查所有依赖是否都已注册
|
|
||||||
const allDependenciesRegistered = resolvedDependencies.every(depId =>
|
|
||||||
container.has(depId)
|
|
||||||
)
|
|
||||||
|
|
||||||
if (allDependenciesRegistered) {
|
|
||||||
// 注册服务
|
|
||||||
container.register(
|
|
||||||
pendingService.serviceId,
|
|
||||||
(container) => {
|
|
||||||
// 创建服务实例
|
|
||||||
const ServiceClass = pendingService.serviceClass
|
|
||||||
// 使用依赖注入创建实例
|
|
||||||
const instance = new ServiceClass()
|
|
||||||
return instance
|
|
||||||
},
|
|
||||||
resolvedDependencies
|
|
||||||
)
|
|
||||||
|
|
||||||
// 从待注册列表中移除
|
|
||||||
const index = pendingServices.indexOf(pendingService)
|
|
||||||
if (index > -1) {
|
|
||||||
pendingServices.splice(index, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// 服务注册表可能尚未初始化,稍后再试
|
|
||||||
console.debug('服务注册暂时失败,将在初始化时重试:')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化所有待注册的服务
|
|
||||||
* 在ServiceProvider初始化后调用
|
|
||||||
*/
|
|
||||||
export function initializePendingServices(): void {
|
|
||||||
// 重试注册所有剩余的服务
|
|
||||||
while (pendingServices.length > 0) {
|
|
||||||
const beforeCount = pendingServices.length
|
|
||||||
tryRegisterPendingServices()
|
|
||||||
|
|
||||||
// 如果没有服务被注册,可能存在循环依赖,跳出循环
|
|
||||||
if (beforeCount === pendingServices.length) {
|
|
||||||
console.warn('以下服务无法注册,可能存在循环依赖:',
|
|
||||||
pendingServices.map(s => s.serviceId).join(', '))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有已注册的服务信息
|
|
||||||
*/
|
|
||||||
export function getRegisteredServices(): Array<{
|
|
||||||
serviceId: string
|
|
||||||
serviceClass: Function
|
|
||||||
}> {
|
|
||||||
return Array.from(classToServiceIdMap.entries()).map(([cls, id]) => ({
|
|
||||||
serviceId: id,
|
|
||||||
serviceClass: cls
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
/**
|
|
||||||
* 依赖注入系统使用示例
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 1. 系统启动示例 - 通常在应用入口文件中使用
|
|
||||||
import { systemBootstrapper } from './SystemBootstrapper'
|
|
||||||
import { ServiceProvider, Inject } from './ServiceProvider'
|
|
||||||
import { ServiceIds } from './ServiceRegistry'
|
|
||||||
|
|
||||||
// 启动系统(通常在应用入口点调用一次)
|
|
||||||
async function startApplication() {
|
|
||||||
try {
|
|
||||||
console.log('正在启动应用...')
|
|
||||||
|
|
||||||
// 启动整个系统,包括初始化服务容器和所有服务
|
|
||||||
const success = await systemBootstrapper.bootstrap()
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
throw new Error('系统启动失败')
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('应用启动成功!')
|
|
||||||
|
|
||||||
// 应用初始化完成后,可以开始使用各种服务
|
|
||||||
initializeApplication()
|
|
||||||
} catch (error) {
|
|
||||||
console.error('应用启动失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 应用初始化
|
|
||||||
function initializeApplication() {
|
|
||||||
// 2. 使用静态服务提供者访问服务
|
|
||||||
const windowService = ServiceProvider.getWindowFormService()
|
|
||||||
const resourceService = ServiceProvider.getResourceService()
|
|
||||||
|
|
||||||
console.log('访问服务示例:', {
|
|
||||||
windowServiceAvailable: !!windowService,
|
|
||||||
resourceServiceAvailable: !!resourceService
|
|
||||||
})
|
|
||||||
|
|
||||||
// 3. 创建并初始化一个使用依赖注入的组件
|
|
||||||
const appComponent = new ApplicationComponent()
|
|
||||||
appComponent.initialize()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 在组件中使用依赖注入
|
|
||||||
class ApplicationComponent {
|
|
||||||
// 使用装饰器自动注入服务
|
|
||||||
@Inject(ServiceIds.WINDOW_FORM_SERVICE)
|
|
||||||
private windowFormService: any
|
|
||||||
|
|
||||||
@Inject(ServiceIds.RESOURCE_SERVICE)
|
|
||||||
private resourceService: any
|
|
||||||
|
|
||||||
@Inject(ServiceIds.LIFECYCLE_MANAGER)
|
|
||||||
private lifecycleManager: any
|
|
||||||
|
|
||||||
initialize() {
|
|
||||||
console.log('组件初始化,服务已注入:', {
|
|
||||||
windowFormService: !!this.windowFormService,
|
|
||||||
resourceService: !!this.resourceService,
|
|
||||||
lifecycleManager: !!this.lifecycleManager
|
|
||||||
})
|
|
||||||
|
|
||||||
// 使用注入的服务
|
|
||||||
this.setupComponent()
|
|
||||||
}
|
|
||||||
|
|
||||||
private setupComponent() {
|
|
||||||
// 示例:使用窗口服务创建一个新窗口
|
|
||||||
// 注意:这只是示例代码,实际使用时需要根据具体服务API调整
|
|
||||||
console.log('组件正在使用注入的服务设置UI...')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. 动态获取服务示例
|
|
||||||
function dynamicServiceExample(serviceId: string) {
|
|
||||||
// 使用get方法动态获取服务
|
|
||||||
try {
|
|
||||||
const service = ServiceProvider.getService(serviceId as any)
|
|
||||||
console.log(`动态获取服务[${serviceId}]:`, !!service)
|
|
||||||
return service
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`无法获取服务[${serviceId}]:`, error)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出示例函数供其他文件使用
|
|
||||||
export { startApplication, dynamicServiceExample, ApplicationComponent }
|
|
||||||
|
|
||||||
// 注意:在实际应用中,你会在main.ts或应用入口文件中调用startApplication()
|
|
||||||
// startApplication(); // 取消注释以启动应用
|
|
||||||
105
src/services/di/types.d.ts
vendored
105
src/services/di/types.d.ts
vendored
@@ -1,105 +0,0 @@
|
|||||||
import { IServiceContainer } from './IServiceContainer'
|
|
||||||
import { ServiceIds } from './ServiceRegistry'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 定义所有服务类型映射
|
|
||||||
* 这个接口用于在ServiceProvider中提供强类型的服务访问
|
|
||||||
*/
|
|
||||||
export interface ServiceTypeMap {
|
|
||||||
[ServiceIds.RESOURCE_SERVICE]: any // ResourceService
|
|
||||||
[ServiceIds.WINDOW_FORM_SERVICE]: any // WindowFormService
|
|
||||||
[ServiceIds.SANDBOX_ENGINE]: any // ApplicationSandboxEngine
|
|
||||||
[ServiceIds.LIFECYCLE_MANAGER]: any // ApplicationLifecycleManager
|
|
||||||
[ServiceIds.SYSTEM_SERVICE]: any // SystemServiceIntegration
|
|
||||||
[ServiceIds.EVENT_BUILDER]: any // IEventBuilder<any>
|
|
||||||
[ServiceIds.EXTERNAL_APP_DISCOVERY]: any // 外部应用发现服务
|
|
||||||
[ServiceIds.ERROR_HANDLER]: any // 错误处理服务
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 扩展IServiceContainer接口,提供强类型的get方法
|
|
||||||
*/
|
|
||||||
declare module './IServiceContainer' {
|
|
||||||
export interface IServiceContainer {
|
|
||||||
/**
|
|
||||||
* 获取服务实例(带类型支持)
|
|
||||||
* @param id 服务ID
|
|
||||||
* @returns 服务实例,类型根据服务ID自动推断
|
|
||||||
*/
|
|
||||||
getService<T extends keyof ServiceTypeMap>(id: T): ServiceTypeMap[T]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 扩展ServiceProvider类的静态方法类型
|
|
||||||
*/
|
|
||||||
declare module './ServiceProvider' {
|
|
||||||
// 仅扩展现有ServiceProvider类,不重新声明
|
|
||||||
interface ServiceProvider {
|
|
||||||
/**
|
|
||||||
* 获取服务实例(带类型支持)
|
|
||||||
* @param id 服务ID
|
|
||||||
* @returns 服务实例,类型根据服务ID自动推断
|
|
||||||
*/
|
|
||||||
static getService<T extends keyof ServiceTypeMap>(id: T): ServiceTypeMap[T]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取资源服务
|
|
||||||
*/
|
|
||||||
static getResourceService(): ServiceTypeMap[typeof ServiceIds.RESOURCE_SERVICE]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取窗口表单服务
|
|
||||||
*/
|
|
||||||
static getWindowFormService(): ServiceTypeMap[typeof ServiceIds.WINDOW_FORM_SERVICE]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取沙箱引擎
|
|
||||||
*/
|
|
||||||
static getSandboxEngine(): ServiceTypeMap[typeof ServiceIds.SANDBOX_ENGINE]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取生命周期管理器
|
|
||||||
*/
|
|
||||||
static getLifecycleManager(): ServiceTypeMap[typeof ServiceIds.LIFECYCLE_MANAGER]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取系统服务
|
|
||||||
*/
|
|
||||||
static getSystemService(): ServiceTypeMap[typeof ServiceIds.SYSTEM_SERVICE]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取事件构建器
|
|
||||||
*/
|
|
||||||
static getEventBuilder(): ServiceTypeMap[typeof ServiceIds.EVENT_BUILDER]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取外部应用发现服务
|
|
||||||
*/
|
|
||||||
static getExternalAppDiscovery(): ServiceTypeMap[typeof ServiceIds.EXTERNAL_APP_DISCOVERY]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取错误处理服务
|
|
||||||
*/
|
|
||||||
static getErrorHandler(): ServiceTypeMap[typeof ServiceIds.ERROR_HANDLER]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 声明Inject装饰器类型
|
|
||||||
*/
|
|
||||||
declare function Inject<T extends keyof ServiceTypeMap>(serviceId: T): PropertyDecorator
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 声明新的Inject装饰器类型,支持类注入
|
|
||||||
*/
|
|
||||||
declare function Inject<T>(dependency?: Function | string): PropertyDecorator
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 声明Service装饰器类型
|
|
||||||
*/
|
|
||||||
declare function Service(options?: {
|
|
||||||
id?: string
|
|
||||||
dependencies?: Array<string | Function>
|
|
||||||
singleton?: boolean
|
|
||||||
}): ClassDecorator
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
import { ServiceProvider } from '../di/ServiceProvider'
|
|
||||||
import { ServiceIds } from '../di/ServiceRegistry'
|
|
||||||
import type { IErrorHandler, ErrorContext } from '../IErrorHandler'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 错误处理服务使用示例
|
|
||||||
*/
|
|
||||||
export class ErrorHandlerExample {
|
|
||||||
private errorHandler: IErrorHandler
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
// 通过服务提供者获取错误处理器实例
|
|
||||||
this.errorHandler = ServiceProvider.getService<IErrorHandler>(ServiceIds.ERROR_HANDLER)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 演示不同类型错误的处理
|
|
||||||
*/
|
|
||||||
public demonstrateErrorHandling(): void {
|
|
||||||
console.log('=== 开始演示错误处理服务 ===')
|
|
||||||
|
|
||||||
// 1. 处理标准Error对象
|
|
||||||
try {
|
|
||||||
throw new Error('这是一个标准错误')
|
|
||||||
} catch (error) {
|
|
||||||
const context: ErrorContext = {
|
|
||||||
source: 'ErrorHandlerExample',
|
|
||||||
operation: 'demonstrateStandardError',
|
|
||||||
appId: 'example-app-123'
|
|
||||||
}
|
|
||||||
this.errorHandler.handleError(error, context)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 处理类型错误
|
|
||||||
try {
|
|
||||||
const obj: any = null
|
|
||||||
obj.method() // 这会抛出TypeError
|
|
||||||
} catch (error) {
|
|
||||||
this.errorHandler.handleError(error, {
|
|
||||||
source: 'ErrorHandlerExample',
|
|
||||||
operation: 'demonstrateTypeError',
|
|
||||||
additionalInfo: '尝试在null上调用方法'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 处理未捕获的Promise错误
|
|
||||||
console.log('演示未捕获的Promise错误...')
|
|
||||||
// 注意:这个错误会被全局错误处理器捕获
|
|
||||||
Promise.reject(new Error('这是一个未处理的Promise错误'))
|
|
||||||
|
|
||||||
// 4. 获取最近的错误记录
|
|
||||||
setTimeout(() => {
|
|
||||||
const recentErrors = this.errorHandler.getRecentErrors(2)
|
|
||||||
console.log('\n=== 最近的错误记录 ===')
|
|
||||||
recentErrors.forEach(record => {
|
|
||||||
console.log(`错误ID: ${record.id}`)
|
|
||||||
console.log(`时间: ${record.timestamp.toISOString()}`)
|
|
||||||
console.log(`处理状态: ${record.handled ? '已处理' : '未处理'}`)
|
|
||||||
console.log(`上下文:`, record.context)
|
|
||||||
})
|
|
||||||
}, 100)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 在组件或服务中使用错误处理器的示例
|
|
||||||
*/
|
|
||||||
export function useErrorHandlerInComponent() {
|
|
||||||
const errorHandler = ServiceProvider.getService<IErrorHandler>(ServiceIds.ERROR_HANDLER)
|
|
||||||
|
|
||||||
// 在组件方法中使用
|
|
||||||
function performRiskyOperation() {
|
|
||||||
try {
|
|
||||||
// 执行可能失败的操作
|
|
||||||
if (Math.random() > 0.5) {
|
|
||||||
throw new Error('操作随机失败')
|
|
||||||
}
|
|
||||||
return '操作成功'
|
|
||||||
} catch (error) {
|
|
||||||
// 使用错误处理器记录和处理错误
|
|
||||||
errorHandler.handleError(error, {
|
|
||||||
source: 'MyComponent',
|
|
||||||
operation: 'performRiskyOperation',
|
|
||||||
componentProps: { /* 组件属性信息 */ }
|
|
||||||
})
|
|
||||||
|
|
||||||
// 可以选择返回一个默认值或重新抛出
|
|
||||||
return '操作失败,但已正确处理'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { performRiskyOperation }
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出一个立即执行的示例函数,方便直接测试
|
|
||||||
export function runErrorHandlerExample() {
|
|
||||||
try {
|
|
||||||
const example = new ErrorHandlerExample()
|
|
||||||
example.demonstrateErrorHandling()
|
|
||||||
} catch (error) {
|
|
||||||
console.error('示例执行失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
import type { IErrorHandler, ErrorContext, ErrorRecord } from '../IErrorHandler'
|
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 全局错误处理器实现
|
|
||||||
*/
|
|
||||||
export class ErrorHandlerImpl implements IErrorHandler {
|
|
||||||
private errorRecords: ErrorRecord[] = []
|
|
||||||
private maxRecords = 100
|
|
||||||
private isGlobalHandlersSetup = false
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
// 初始化时可以设置全局错误处理器
|
|
||||||
this.setupGlobalErrorHandlers()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理应用错误
|
|
||||||
* @param error 错误对象
|
|
||||||
* @param context 错误上下文信息
|
|
||||||
* @returns 是否成功处理了错误
|
|
||||||
*/
|
|
||||||
public handleError(error: Error | any, context: ErrorContext = {}): boolean {
|
|
||||||
try {
|
|
||||||
// 创建错误记录
|
|
||||||
const errorRecord: ErrorRecord = {
|
|
||||||
id: uuidv4(),
|
|
||||||
error,
|
|
||||||
context,
|
|
||||||
timestamp: new Date(),
|
|
||||||
handled: false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存错误记录
|
|
||||||
this.addErrorRecord(errorRecord)
|
|
||||||
|
|
||||||
// 根据错误类型进行处理
|
|
||||||
if (error instanceof Error) {
|
|
||||||
this.logError(error, context)
|
|
||||||
this.reportError(error, context)
|
|
||||||
} else {
|
|
||||||
// 非标准错误对象
|
|
||||||
this.logUnknownError(error, context)
|
|
||||||
}
|
|
||||||
|
|
||||||
errorRecord.handled = true
|
|
||||||
return true
|
|
||||||
} catch (handlerError) {
|
|
||||||
console.error('错误处理器自身出错:', handlerError)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理未捕获的异常
|
|
||||||
*/
|
|
||||||
public setupGlobalErrorHandlers(): void {
|
|
||||||
if (this.isGlobalHandlersSetup) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 捕获未处理的Promise错误
|
|
||||||
window.addEventListener('unhandledrejection', (event) => {
|
|
||||||
this.handleError(event.reason, {
|
|
||||||
source: 'unhandledrejection',
|
|
||||||
operation: 'Promise处理'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// 捕获全局错误
|
|
||||||
window.addEventListener('error', (event) => {
|
|
||||||
const error = event.error || new Error(event.message)
|
|
||||||
this.handleError(error, {
|
|
||||||
source: 'window.error',
|
|
||||||
operation: event.filename || window.location.pathname,
|
|
||||||
lineNumber: event.lineno,
|
|
||||||
columnNumber: event.colno
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Vue应用的错误处理可以在main.ts中配置
|
|
||||||
|
|
||||||
this.isGlobalHandlersSetup = true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取最近的错误记录
|
|
||||||
* @param limit 获取的最大数量
|
|
||||||
*/
|
|
||||||
public getRecentErrors(limit: number = 10): ErrorRecord[] {
|
|
||||||
return this.errorRecords
|
|
||||||
.slice()
|
|
||||||
.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime())
|
|
||||||
.slice(0, limit)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加错误记录到历史
|
|
||||||
*/
|
|
||||||
private addErrorRecord(record: ErrorRecord): void {
|
|
||||||
this.errorRecords.unshift(record)
|
|
||||||
|
|
||||||
// 限制记录数量
|
|
||||||
if (this.errorRecords.length > this.maxRecords) {
|
|
||||||
this.errorRecords = this.errorRecords.slice(0, this.maxRecords)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 记录标准错误
|
|
||||||
*/
|
|
||||||
private logError(error: Error, context: ErrorContext): void {
|
|
||||||
console.error(`[错误处理] ${context.source || '未知来源'}: ${error.message}`, {
|
|
||||||
error,
|
|
||||||
stack: error.stack,
|
|
||||||
context
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 记录未知类型错误
|
|
||||||
*/
|
|
||||||
private logUnknownError(error: any, context: ErrorContext): void {
|
|
||||||
console.error(`[错误处理] ${context.source || '未知来源'}: 发生未知类型错误`, {
|
|
||||||
error,
|
|
||||||
context
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 报告错误(可以扩展为发送到错误监控服务)
|
|
||||||
*/
|
|
||||||
private reportError(error: Error, context: ErrorContext): void {
|
|
||||||
// 在实际项目中,这里可以将错误发送到远程监控服务
|
|
||||||
// 例如:sentry、logrocket等
|
|
||||||
// 现在只是记录到控制台
|
|
||||||
console.debug('[错误报告] 准备发送错误信息...')
|
|
||||||
|
|
||||||
// 模拟异步错误报告
|
|
||||||
setTimeout(() => {
|
|
||||||
console.debug(`[错误报告] 错误已记录,ID: ${context.source || 'unknown'}`)
|
|
||||||
}, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建单例实例
|
|
||||||
let instance: ErrorHandlerImpl | null = null
|
|
||||||
|
|
||||||
export function getErrorHandlerInstance(): ErrorHandlerImpl {
|
|
||||||
if (!instance) {
|
|
||||||
instance = new ErrorHandlerImpl()
|
|
||||||
}
|
|
||||||
return instance
|
|
||||||
}
|
|
||||||
@@ -1,289 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="app-renderer" :class="`app-${appId}`">
|
|
||||||
<!-- 内置Vue应用 - 立即渲染,无加载状态 -->
|
|
||||||
<component
|
|
||||||
v-if="isBuiltInApp && appComponent"
|
|
||||||
:is="appComponent"
|
|
||||||
:key="appId"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 外部iframe应用 -->
|
|
||||||
<iframe
|
|
||||||
v-else-if="!isBuiltInApp && iframeUrl"
|
|
||||||
:src="iframeUrl"
|
|
||||||
:sandbox="sandboxAttributes"
|
|
||||||
class="external-app-iframe"
|
|
||||||
@load="onIframeLoad"
|
|
||||||
@error="onIframeError"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 加载中状态(仅用于外部应用) -->
|
|
||||||
<div v-else-if="!isBuiltInApp && isLoading" class="loading-state">
|
|
||||||
<div class="loading-spinner"></div>
|
|
||||||
<p>正在加载应用...</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 错误状态 -->
|
|
||||||
<div v-else-if="hasError" class="error-state">
|
|
||||||
<div class="error-icon">⚠️</div>
|
|
||||||
<h3>应用加载失败</h3>
|
|
||||||
<p>{{ errorMessage }}</p>
|
|
||||||
<button @click="retry" class="retry-btn">重试</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 内置应用未找到的后备显示 -->
|
|
||||||
<div v-else-if="isBuiltInApp && !appComponent" class="error-state">
|
|
||||||
<div class="error-icon">📱</div>
|
|
||||||
<h3>应用不存在</h3>
|
|
||||||
<p>内置应用 "{{ appId }}" 未找到</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed, onMounted, onUnmounted, inject, watch } from 'vue'
|
|
||||||
import { appRegistry } from '@/apps'
|
|
||||||
import { externalAppDiscovery } from '@/services/ExternalAppDiscovery'
|
|
||||||
import type { SystemServiceIntegration } from '@/services/SystemServiceIntegration'
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
appId: string
|
|
||||||
windowId?: string
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
loaded: []
|
|
||||||
error: [error: Error]
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const systemService = inject<SystemServiceIntegration>('systemService')
|
|
||||||
|
|
||||||
// 检查是否为内置应用
|
|
||||||
const isBuiltInApp = computed(() => {
|
|
||||||
return appRegistry.hasApp(props.appId)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 检查是否为外置应用
|
|
||||||
const isExternalApp = computed(() => {
|
|
||||||
return externalAppDiscovery.hasApp(props.appId)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 内置应用组件 - 立即获取,无需异步
|
|
||||||
const appComponent = computed(() => {
|
|
||||||
if (isBuiltInApp.value) {
|
|
||||||
const appRegistration = appRegistry.getApp(props.appId)
|
|
||||||
return appRegistration?.component
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
})
|
|
||||||
|
|
||||||
// 外部应用相关状态
|
|
||||||
const isLoading = ref(false) // 默认不loading,只有外部应用需要
|
|
||||||
const hasError = ref(false)
|
|
||||||
const errorMessage = ref('')
|
|
||||||
const iframeUrl = ref('')
|
|
||||||
|
|
||||||
// 沙箱属性(仅用于外部应用)
|
|
||||||
const sandboxAttributes = computed(() => {
|
|
||||||
return 'allow-scripts allow-forms allow-popups'
|
|
||||||
})
|
|
||||||
|
|
||||||
// 初始化应用
|
|
||||||
const initializeApp = async () => {
|
|
||||||
try {
|
|
||||||
if (isBuiltInApp.value) {
|
|
||||||
// 内置应用立即可用,无需异步加载
|
|
||||||
if (appComponent.value) {
|
|
||||||
emit('loaded')
|
|
||||||
} else {
|
|
||||||
hasError.value = true
|
|
||||||
errorMessage.value = '内置应用未找到'
|
|
||||||
emit('error', new Error('内置应用未找到'))
|
|
||||||
}
|
|
||||||
} else if (isExternalApp.value) {
|
|
||||||
// 外置应用需要异步加载
|
|
||||||
isLoading.value = true
|
|
||||||
hasError.value = false
|
|
||||||
errorMessage.value = ''
|
|
||||||
await loadExternalApp()
|
|
||||||
} else {
|
|
||||||
throw new Error(`应用 ${props.appId} 未找到(不是内置也不是外置应用)`)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('应用初始化失败:', error)
|
|
||||||
hasError.value = true
|
|
||||||
errorMessage.value = (error as Error).message
|
|
||||||
isLoading.value = false
|
|
||||||
emit('error', error as Error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载外部应用
|
|
||||||
const loadExternalApp = async () => {
|
|
||||||
try {
|
|
||||||
console.log(`[AppRenderer] 加载外置应用: ${props.appId}`)
|
|
||||||
|
|
||||||
// 直接从外置应用发现服务获取应用信息
|
|
||||||
const externalApp = externalAppDiscovery.getApp(props.appId)
|
|
||||||
if (!externalApp) {
|
|
||||||
throw new Error('外置应用未找到')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 直接使用外置应用的入口路径
|
|
||||||
iframeUrl.value = externalApp.entryPath
|
|
||||||
console.log(`[AppRenderer] 外置应用加载路径: ${iframeUrl.value}`)
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`[AppRenderer] 外置应用加载失败:`, error)
|
|
||||||
throw new Error(`外部应用加载失败: ${(error as Error).message}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// iframe加载完成
|
|
||||||
const onIframeLoad = () => {
|
|
||||||
isLoading.value = false
|
|
||||||
emit('loaded')
|
|
||||||
}
|
|
||||||
|
|
||||||
// iframe加载错误
|
|
||||||
const onIframeError = (event: Event) => {
|
|
||||||
hasError.value = true
|
|
||||||
errorMessage.value = '外部应用加载失败'
|
|
||||||
isLoading.value = false
|
|
||||||
emit('error', new Error('iframe加载失败'))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重试加载
|
|
||||||
const retry = () => {
|
|
||||||
initializeApp()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听内置应用组件的可用性,立即发送loaded事件
|
|
||||||
watch(appComponent, (newComponent) => {
|
|
||||||
if (isBuiltInApp.value && newComponent) {
|
|
||||||
emit('loaded')
|
|
||||||
}
|
|
||||||
}, { immediate: true })
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// 内置应用无需额外初始化,只处理外部应用
|
|
||||||
if (!isBuiltInApp.value) {
|
|
||||||
if (isExternalApp.value) {
|
|
||||||
initializeApp()
|
|
||||||
} else {
|
|
||||||
// 应用不存在
|
|
||||||
hasError.value = true
|
|
||||||
errorMessage.value = `应用 ${props.appId} 未找到`
|
|
||||||
emit('error', new Error('应用未找到'))
|
|
||||||
}
|
|
||||||
} else if (!appComponent.value) {
|
|
||||||
// 内置应用不存在
|
|
||||||
hasError.value = true
|
|
||||||
errorMessage.value = '内置应用未找到'
|
|
||||||
emit('error', new Error('内置应用未找到'))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
// 清理iframe URL(只有当是blob URL时才需要清理)
|
|
||||||
if (iframeUrl.value && iframeUrl.value.startsWith('blob:')) {
|
|
||||||
URL.revokeObjectURL(iframeUrl.value)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.app-renderer {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
background: white;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.external-app-iframe {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border: none;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-state {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
height: 100%;
|
|
||||||
color: #6c757d;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-spinner {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
border: 4px solid #f3f3f3;
|
|
||||||
border-top: 4px solid #007bff;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-state {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
height: 100%;
|
|
||||||
text-align: center;
|
|
||||||
padding: 40px;
|
|
||||||
color: #6c757d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-icon {
|
|
||||||
font-size: 48px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-state h3 {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
color: #dc3545;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-state p {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.retry-btn {
|
|
||||||
padding: 8px 16px;
|
|
||||||
background: #007bff;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 14px;
|
|
||||||
transition: background 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.retry-btn:hover {
|
|
||||||
background: #0056b3;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 应用特定样式 */
|
|
||||||
.app-calculator {
|
|
||||||
background: #f8f9fa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-notepad {
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-todo {
|
|
||||||
background: #f8f9fa;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes spin {
|
|
||||||
0% { transform: rotate(0deg); }
|
|
||||||
100% { transform: rotate(360deg); }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,139 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="window-manager">
|
<div class="window-manager">
|
||||||
<!-- 所有已打开的内置应用窗口 -->
|
<!-- 所有已打开的内置应用窗口 -->
|
||||||
<teleport v-for="window in builtInWindows" :key="window.id" :to="`#app-container-${window.appId}`">
|
<teleport v-for="window in builtInWindows?.values()" :key="window.id" :to="`#app-container-${window.appId}`">
|
||||||
<component :is="window.component" :key="window.id" v-bind="window.props" @close="closeWindow(window.id)" />
|
<component :is="window.component" :key="window.id" v-bind="window.props" />
|
||||||
</teleport>
|
</teleport>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, inject, onMounted, onUnmounted } from 'vue'
|
import { inject } from 'vue'
|
||||||
import type { SystemServiceIntegration } from '@/services/SystemServiceIntegration'
|
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 systemService = inject<SystemServiceIntegration>('systemService')
|
||||||
|
|
||||||
// 添加内置应用窗口
|
// 存储所有已打开的内置应用窗口
|
||||||
const addBuiltInWindow = async (windowId: string, appId: string) => {
|
const builtInWindows = systemService?.getLifecycleManager().getBuiltInWindowForms()
|
||||||
// 检查应用是否存在
|
|
||||||
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.getWindowFormService()
|
|
||||||
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>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import { useDynamicAppIcons, getAppIdFromIcon } from '@/ui/desktop-container/use
|
|||||||
import type { SystemServiceIntegration } from '@/services/SystemServiceIntegration'
|
import type { SystemServiceIntegration } from '@/services/SystemServiceIntegration'
|
||||||
import type { SystemStatus } from '@/services/SystemServiceIntegration'
|
import type { SystemStatus } from '@/services/SystemServiceIntegration'
|
||||||
import { appRegistry } from '@/apps'
|
import { appRegistry } from '@/apps'
|
||||||
import { externalAppDiscovery } from '@/services/ExternalAppDiscovery'
|
import { externalAppDiscovery } from '@/services/ExternalAppDiscovery.ts'
|
||||||
|
|
||||||
const { appIconsRef, gridStyle, gridTemplate } = useDesktopContainerInit('.desktop-icons-container')
|
const { appIconsRef, gridStyle, gridTemplate } = useDesktopContainerInit('.desktop-icons-container')
|
||||||
const { getAppIconsWithPositions, saveIconPositions, refreshApps } = useDynamicAppIcons()
|
const { getAppIconsWithPositions, saveIconPositions, refreshApps } = useDynamicAppIcons()
|
||||||
@@ -98,52 +98,7 @@ const startApp = async (appId: string) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const lifecycleManager = systemService.getLifecycleManager()
|
const lifecycleManager = systemService.getLifecycleManager()
|
||||||
|
await lifecycleManager.startApp(appId)
|
||||||
// 检查是否为内置应用
|
|
||||||
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) {
|
} catch (error) {
|
||||||
console.error('启动应用失败:', error)
|
console.error('启动应用失败:', error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { computed, watch } from 'vue'
|
import { computed, watch } from 'vue'
|
||||||
import type { IDesktopAppIcon } from '@/ui/types/IDesktopAppIcon.ts'
|
import type { IDesktopAppIcon } from '@/ui/types/IDesktopAppIcon.ts'
|
||||||
import { appRegistry } from '@/apps'
|
import { appRegistry } from '@/apps'
|
||||||
import { externalAppDiscovery } from '@/services/ExternalAppDiscovery'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态应用图标管理
|
* 动态应用图标管理
|
||||||
@@ -31,20 +30,20 @@ export function useDynamicAppIcons() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 添加外置应用
|
// 添加外置应用
|
||||||
const externalApps = externalAppDiscovery.getDiscoveredApps()
|
// const externalApps = []
|
||||||
for (const app of externalApps) {
|
// for (const app of externalApps) {
|
||||||
const x = ((position - 1) % 4) + 1
|
// const x = ((position - 1) % 4) + 1
|
||||||
const y = Math.floor((position - 1) / 4) + 1
|
// const y = Math.floor((position - 1) / 4) + 1
|
||||||
|
//
|
||||||
icons.push({
|
// icons.push({
|
||||||
name: app.manifest.name,
|
// name: app.manifest.name,
|
||||||
icon: app.manifest.icon || '📱', // 默认图标
|
// icon: app.manifest.icon || '📱', // 默认图标
|
||||||
path: app.manifest.id,
|
// path: app.manifest.id,
|
||||||
x,
|
// x,
|
||||||
y
|
// y
|
||||||
})
|
// })
|
||||||
position++
|
// position++
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 添加系统状态应用
|
// 添加系统状态应用
|
||||||
icons.push({
|
icons.push({
|
||||||
@@ -111,12 +110,6 @@ export function useDynamicAppIcons() {
|
|||||||
const refreshApps = async () => {
|
const refreshApps = async () => {
|
||||||
try {
|
try {
|
||||||
// 只有在系统服务已启动的情况下才刷新
|
// 只有在系统服务已启动的情况下才刷新
|
||||||
if (externalAppDiscovery['hasStarted']) {
|
|
||||||
await externalAppDiscovery.refresh()
|
|
||||||
console.log('[DynamicAppIcons] 应用列表已刷新')
|
|
||||||
} else {
|
|
||||||
console.log('[DynamicAppIcons] 系统服务未启动,跳过刷新')
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[DynamicAppIcons] 刷新应用列表失败:', error)
|
console.error('[DynamicAppIcons] 刷新应用列表失败:', error)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user