This commit is contained in:
2025-10-10 10:08:05 +08:00
parent ed0527bf27
commit 204dd4781b
6 changed files with 235 additions and 816 deletions

View File

@@ -14,9 +14,7 @@ registerBuiltInApps()
// 初始化系统服务
const systemService = new SystemServiceIntegration({
debug: import.meta.env.DEV,
enablePerformanceMonitoring: true,
enableSecurityAudit: true
debug: import.meta.env.DEV
})
// 创建应用实例

View File

@@ -20,7 +20,7 @@ export enum AppLifecycleState {
UNINSTALLING = 'uninstalling',
ERROR = 'error',
CRASHED = 'crashed',
AVAILABLE = 'available', // 外置应用可用但未注册状态
AVAILABLE = 'available' // 外置应用可用但未注册状态
}
/**
@@ -81,16 +81,6 @@ export interface AppInstance {
persistent: boolean
}
/**
* 应用安装包接口
*/
export interface AppPackage {
manifest: AppManifest
files: Map<string, Blob | string> // 文件路径到内容的映射
signature?: string // 数字签名
checksum: string // 校验和
}
/**
* 应用启动选项
*/
@@ -138,7 +128,7 @@ export class ApplicationLifecycleManager {
windowService: WindowService,
resourceService: ResourceService,
eventService: EventCommunicationService,
sandboxEngine: ApplicationSandboxEngine,
sandboxEngine: ApplicationSandboxEngine
) {
this.windowService = windowService
this.resourceService = resourceService
@@ -146,122 +136,6 @@ export class ApplicationLifecycleManager {
this.sandboxEngine = sandboxEngine
this.setupEventListeners()
this.loadInstalledApps()
// 外部应用发现已由 SystemServiceIntegration 统一管理,无需重复初始化
}
/**
* 安装应用
*/
async installApp(appPackage: AppPackage): Promise<string> {
const { manifest, files, checksum } = appPackage
const appId = manifest.id
try {
// 检查应用是否已安装
if (this.installedApps.has(appId)) {
throw new Error(`应用 ${appId} 已安装`)
}
// 验证清单文件
this.validateManifest(manifest)
// 验证校验和
if (!this.verifyChecksum(files, checksum)) {
throw new Error('应用包校验失败')
}
// 检查权限
await this.checkPermissions(manifest.permissions)
const now = new Date()
const appInstance: AppInstance = {
id: appId,
manifest,
state: AppLifecycleState.INSTALLING,
processId: '',
installedAt: now,
errorCount: 0,
crashCount: 0,
memoryUsage: 0,
cpuUsage: 0,
version: manifest.version,
autoStart: false,
persistent: manifest.background?.persistent || false,
}
// 更新状态
this.updateAppState(appInstance, AppLifecycleState.INSTALLING)
this.installedApps.set(appId, appInstance)
// 存储应用文件
this.appFiles.set(appId, files)
// 保存到本地存储
await this.saveAppToStorage(appInstance)
// 更新状态为已安装
this.updateAppState(appInstance, AppLifecycleState.INSTALLED)
this.eventService.sendMessage('system', 'app-lifecycle', {
type: 'installed',
appId,
manifest,
})
console.log(`应用 ${manifest.name} (${appId}) 安装成功`)
return appId
} catch (error) {
// 清理安装失败的应用
this.installedApps.delete(appId)
this.appFiles.delete(appId)
console.error('应用安装失败:', error)
throw error
}
}
/**
* 卸载应用
*/
async uninstallApp(appId: string): Promise<boolean> {
const app = this.installedApps.get(appId)
if (!app) {
throw new Error(`应用 ${appId} 未安装`)
}
try {
// 如果应用正在运行,先停止
if (app.state === AppLifecycleState.RUNNING || app.state === AppLifecycleState.SUSPENDED) {
await this.stopApp(appId)
}
this.updateAppState(app, AppLifecycleState.UNINSTALLING)
// 清理应用数据
await this.resourceService.clearStorage(appId)
await this.resourceService.revokeAllPermissions(appId)
// 删除应用文件
this.appFiles.delete(appId)
// 从存储中删除
await this.removeAppFromStorage(appId)
// 从已安装列表中移除
this.installedApps.delete(appId)
this.eventService.sendMessage('system', 'app-lifecycle', {
type: 'uninstalled',
appId,
})
console.log(`应用 ${appId} 卸载成功`)
return true
} catch (error) {
console.error('应用卸载失败:', error)
throw error
}
}
/**
@@ -270,6 +144,8 @@ export class ApplicationLifecycleManager {
async startApp(appId: string, options: AppStartOptions = {}): Promise<string> {
let app = this.installedApps.get(appId)
console.log('-----------------------------')
// 如果应用未安装,检查是否为外置应用
let isExternalApp = false
if (!app) {
@@ -292,7 +168,7 @@ export class ApplicationLifecycleManager {
cpuUsage: 0,
version: externalApp.manifest.version,
autoStart: false,
persistent: false,
persistent: false
}
}
}
@@ -312,21 +188,7 @@ export class ApplicationLifecycleManager {
this.updateAppState(app, AppLifecycleState.STARTING)
// 检查是否为内置应用
let isBuiltInApp = false
try {
const { AppRegistry } = await import('../apps/AppRegistry')
const appRegistry = AppRegistry.getInstance()
isBuiltInApp = appRegistry.hasApp(appId)
} catch (error) {
console.warn('无法导入 AppRegistry')
}
// 检查是否为外置应用(仅当不是内置应用时)
// 修复移除重复的变量声明使用已声明的isExternalApp变量
if (!isBuiltInApp && !isExternalApp) {
isExternalApp = externalAppDiscovery.hasApp(appId)
}
let isBuiltInApp = true
// 创建窗体(如果不是后台应用)
let windowId: string | undefined
@@ -341,23 +203,12 @@ export class ApplicationLifecycleManager {
minWidth: app.manifest.window?.minWidth,
minHeight: app.manifest.window?.minHeight,
maxWidth: app.manifest.window?.maxWidth,
maxHeight: app.manifest.window?.maxHeight,
maxHeight: app.manifest.window?.maxHeight
}
const windowInstance = await this.windowService.createWindow(appId, windowConfig)
windowId = windowInstance.id
app.windowId = windowId
// 对于内置应用,需要在窗口内容区域挂载 AppRenderer 组件
if (isBuiltInApp) {
await this.mountBuiltInApp(appId, windowInstance)
}
// 对于内置应用不需要等待窗口DOM元素渲染
if (!isBuiltInApp) {
// 稍等片刻确保窗口DOM元素已经渲染完成
await new Promise((resolve) => setTimeout(resolve, 100))
}
}
// 对于外置应用,需要创建沙箱;内置应用跳过沙箱
@@ -371,13 +222,13 @@ export class ApplicationLifecycleManager {
networkTimeout: 15000, // 增加超时时间到15秒
csp:
app.manifest.contentSecurity?.policy ||
"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self';",
"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self';"
}
const sandbox = await this.sandboxEngine.createSandbox(
appId,
windowId || 'background',
sandboxConfig,
sandboxConfig
)
app.sandboxId = sandbox.id
@@ -474,105 +325,6 @@ export class ApplicationLifecycleManager {
}
}
/**
* 暂停应用
*/
async suspendApp(appId: string): Promise<boolean> {
// 首先从已安装应用中查找
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
}
try {
// 暂停沙箱
if (app.sandboxId) {
this.sandboxEngine.suspendSandbox(app.sandboxId)
}
// 最小化窗体
if (app.windowId) {
this.windowService.minimizeWindow(app.windowId)
}
this.updateAppState(app, AppLifecycleState.SUSPENDED)
// 注意状态变更消息由updateAppState方法自动发送不需要手动发送
console.log(`应用 ${appId} 已暂停`)
return true
} catch (error) {
console.error('应用暂停失败:', error)
return false
}
}
/**
* 恢复应用
*/
async resumeApp(appId: string): Promise<boolean> {
// 首先从已安装应用中查找
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
}
try {
// 恢复沙箱
if (app.sandboxId) {
this.sandboxEngine.resumeSandbox(app.sandboxId)
}
// 恢复窗体
if (app.windowId) {
this.windowService.restoreWindow(app.windowId)
}
app.lastActiveAt = new Date()
this.updateAppState(app, AppLifecycleState.RUNNING)
// 注意状态变更消息由updateAppState方法自动发送不需要手动发送
console.log(`应用 ${appId} 已恢复`)
return true
} catch (error) {
console.error('应用恢复失败:', error)
return false
}
}
/**
* 重启应用
*/
async restartApp(appId: string, options?: AppStartOptions): Promise<string> {
await this.stopApp(appId)
// 等待一小段时间确保完全停止
await new Promise((resolve) => setTimeout(resolve, 1000))
return this.startApp(appId, options)
}
/**
* 获取应用信息
*/
@@ -629,7 +381,7 @@ export class ApplicationLifecycleManager {
cpuUsage: app.cpuUsage,
startedAt: app.startedAt,
lastActiveAt: app.lastActiveAt,
uptime: app.startedAt ? Date.now() - app.startedAt.getTime() : 0,
uptime: app.startedAt ? Date.now() - app.startedAt.getTime() : 0
}
}
@@ -646,9 +398,11 @@ export class ApplicationLifecycleManager {
console.log(`[LifecycleManager] 为内置应用 ${appId} 创建 AppRenderer 组件`)
console.log('----------------------------------')
const app = createApp({
components: { AppRenderer },
template: `<AppRenderer :app-id="'${appId}'" :window-id="'${windowInstance.id}'"/>`,
template: `<AppRenderer :app-id="'${appId}'" :window-id="'${windowInstance.id}'"/>`
})
// 提供系统服务(使用当前实例所在的系统服务)
@@ -657,7 +411,7 @@ export class ApplicationLifecycleManager {
getResourceService: () => this.resourceService,
getEventService: () => this.eventService,
getSandboxEngine: () => this.sandboxEngine,
getLifecycleManager: () => this,
getLifecycleManager: () => this
})
// 挂载到窗口内容区域
@@ -674,66 +428,6 @@ export class ApplicationLifecycleManager {
}
}
/**
* 验证应用清单文件
*/
private validateManifest(manifest: AppManifest): void {
const required = ['id', 'name', 'version', 'entryPoint']
for (const field of required) {
if (!manifest[field as keyof AppManifest]) {
throw new Error(`清单文件缺少必需字段: ${field}`)
}
}
// 验证版本格式
if (!/^\d+\.\d+\.\d+/.test(manifest.version)) {
throw new Error('版本号格式不正确,应为 x.y.z 格式')
}
// 验证应用ID格式
if (!/^[a-zA-Z0-9._-]+$/.test(manifest.id)) {
throw new Error('应用ID格式不正确')
}
}
/**
* 验证校验和
*/
private verifyChecksum(files: Map<string, Blob | string>, expectedChecksum: string): boolean {
// 简化实现,实际应用中应使用更强的哈希算法
let content = ''
for (const [path, data] of files.entries()) {
content += path + (typeof data === 'string' ? data : data.size)
}
const actualChecksum = this.safeBase64Encode(content).slice(0, 32)
return actualChecksum === expectedChecksum
}
/**
* 安全的 Base64 编码,支持 Unicode 字符
*/
private safeBase64Encode(str: string): string {
try {
// 使用 encodeURIComponent + atob 来处理 Unicode 字符
return btoa(
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function toSolidBytes(match, p1) {
return String.fromCharCode(parseInt(p1, 16))
}),
)
} catch (error) {
// 如果还是失败,使用简单的哈希算法
let hash = 0
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i)
hash = (hash << 5) - hash + char
hash = hash & hash // 转换为32位整数
}
return Math.abs(hash).toString(36)
}
}
/**
* 检查权限
*/
@@ -745,115 +439,6 @@ export class ApplicationLifecycleManager {
}
}
/**
* 在沙箱中加载应用
*/
private async loadAppInSandbox(app: AppInstance, sandboxId: string): Promise<void> {
const appFiles = this.appFiles.get(app.id)
if (!appFiles) {
throw new Error('应用文件不存在')
}
const entryFile = appFiles.get(app.manifest.entryPoint)
if (!entryFile) {
throw new Error('入口文件不存在')
}
// 创建应用URL
const entryUrl = this.createAppUrl(app.id, app.manifest.entryPoint, entryFile)
// 在沙箱中加载应用
await this.sandboxEngine.loadApplication(sandboxId, entryUrl)
}
/**
* 创建应用文件URL
*/
private createAppUrl(appId: string, filePath: string, content: Blob | string): string {
let blob: Blob
if (typeof content === 'string') {
// 确保使用UTF-8编码创建Blob
const contentType = this.getContentType(filePath)
const utf8ContentType = contentType.includes('charset')
? contentType
: `${contentType}; charset=utf-8`
blob = new Blob([content], { type: utf8ContentType })
} else {
blob = content
}
return URL.createObjectURL(blob)
}
/**
* 获取文件内容类型
*/
private getContentType(filePath: string): string {
const ext = filePath.split('.').pop()?.toLowerCase()
switch (ext) {
case 'html':
return 'text/html; charset=utf-8'
case 'js':
return 'application/javascript; charset=utf-8'
case 'css':
return 'text/css; charset=utf-8'
case 'json':
return 'application/json; charset=utf-8'
case 'png':
return 'image/png'
case 'jpg':
case 'jpeg':
return 'image/jpeg'
case 'svg':
return 'image/svg+xml; charset=utf-8'
default:
return 'text/plain; charset=utf-8'
}
}
/**
* 保存应用到存储
*/
private async saveAppToStorage(app: AppInstance): Promise<void> {
const appData = {
id: app.id,
manifest: app.manifest,
installedAt: app.installedAt.toISOString(),
version: app.version,
autoStart: app.autoStart,
persistent: app.persistent,
}
await this.resourceService.setStorage('system', `apps.${app.id}`, appData)
}
/**
* 从存储中删除应用
*/
private async removeAppFromStorage(appId: string): Promise<void> {
await this.resourceService.removeStorage('system', `apps.${appId}`)
}
/**
* 初始化外置应用发现(已由 SystemServiceIntegration 统一管理)
* 这个方法保留用于未来可能的扩展,但不再重复启动发现服务
*/
private async initializeExternalAppDiscovery(): Promise<void> {
try {
console.log('[LifecycleManager] 外置应用发现服务已由系统服务集成统一管理')
// 可以在这里添加应用生命周期管理器特有的外置应用监听逻辑
// 例如监听外置应用的注册/卸载事件
} catch (error) {
console.error('[LifecycleManager] 初始化外置应用监听失败:', error)
}
}
// 已移除:外部应用不再需要注册到 installedApps 中
// 外部应用在启动时会创建临时实例
/**
* 为外置应用加载代码到沙箱
*/
@@ -904,7 +489,7 @@ export class ApplicationLifecycleManager {
version: externalApp.manifest.version,
autoStart: false,
persistent: false,
isExternal: true,
isExternal: true
}
apps.push(appInstance)
}
@@ -925,42 +510,6 @@ export class ApplicationLifecycleManager {
}
}
/**
* 加载已安装的应用
*/
private async loadInstalledApps(): Promise<void> {
try {
// 从存储中加载应用列表
const appsData = (await this.resourceService.getStorage('system', 'apps')) || {}
for (const [appId, appData] of Object.entries(appsData as Record<string, any>)) {
if (appData && typeof appData === 'object') {
const app: AppInstance = {
id: appId,
manifest: appData.manifest,
state: AppLifecycleState.STOPPED,
processId: '',
installedAt: new Date(appData.installedAt),
errorCount: 0,
crashCount: 0,
memoryUsage: 0,
cpuUsage: 0,
version: appData.version,
autoStart: appData.autoStart || false,
persistent: appData.persistent || false,
}
this.updateAppState(app, AppLifecycleState.INSTALLED)
this.installedApps.set(appId, app)
}
}
console.log(`已加载 ${this.installedApps.size} 个已安装应用`)
} catch (error) {
console.error('加载已安装应用失败:', error)
}
}
/**
* 设置事件监听器
*/
@@ -981,24 +530,6 @@ export class ApplicationLifecycleManager {
}
}
})
// 监听性能告警
this.eventService.subscribe('system', 'performance-alert', (message) => {
const { sandboxId, type, usage, limit } = message.payload
for (const app of this.installedApps.values()) {
if (app.sandboxId === sandboxId) {
if (type === 'memory') {
app.memoryUsage = usage
} else if (type === 'cpu') {
app.cpuUsage = usage
}
console.warn(`应用 ${app.id} ${type} 使用量 ${usage} 超过限制 ${limit}`)
break
}
}
})
}
/**
@@ -1013,7 +544,7 @@ export class ApplicationLifecycleManager {
this.eventService.sendMessage('system', 'app-lifecycle', {
type: 'error',
appId,
error: error.message,
error: error.message
})
console.error(`应用 ${appId} 发生错误:`, error)
@@ -1050,7 +581,7 @@ export class ApplicationLifecycleManager {
type: 'stateChanged',
appId: app.id,
newState,
oldState,
oldState
})
}
}

View File

@@ -109,10 +109,7 @@ export class ApplicationSandboxEngine {
private resourceService: ResourceService
private eventService: EventCommunicationService
constructor(
resourceService: ResourceService,
eventService: EventCommunicationService
) {
constructor(resourceService: ResourceService, eventService: EventCommunicationService) {
this.resourceService = resourceService
this.eventService = eventService
this.startPerformanceMonitoring()
@@ -180,7 +177,6 @@ export class ApplicationSandboxEngine {
console.log(`沙箱 ${sandboxId} 创建成功`)
return sandbox
} catch (error) {
this.updateSandboxState(sandbox, SandboxState.ERROR)
sandbox.errors.push(error instanceof Error ? error.message : String(error))
@@ -216,7 +212,9 @@ export class ApplicationSandboxEngine {
// 等待加载完成
return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
console.error(`应用加载超时: ${sandbox.appId}, URL: ${applicationUrl}, 超时时间: ${sandbox.config.networkTimeout}ms`)
console.error(
`应用加载超时: ${sandbox.appId}, URL: ${applicationUrl}, 超时时间: ${sandbox.config.networkTimeout}ms`
)
reject(new Error('应用加载超时'))
}, sandbox.config.networkTimeout)
@@ -251,64 +249,6 @@ export class ApplicationSandboxEngine {
}
}
/**
* 暂停沙箱
*/
suspendSandbox(sandboxId: string): boolean {
const sandbox = this.sandboxes.get(sandboxId)
if (!sandbox || sandbox.state !== SandboxState.RUNNING) {
return false
}
try {
this.updateSandboxState(sandbox, SandboxState.SUSPENDED)
if (sandbox.iframe) {
// 暂停iframe中的脚本执行
const iframeWindow = sandbox.iframe.contentWindow
if (iframeWindow) {
// 发送暂停事件到应用
iframeWindow.postMessage({ type: 'system:suspend' }, '*')
}
}
console.log(`沙箱 ${sandboxId} 已暂停`)
return true
} catch (error) {
console.error('暂停沙箱失败:', error)
return false
}
}
/**
* 恢复沙箱
*/
resumeSandbox(sandboxId: string): boolean {
const sandbox = this.sandboxes.get(sandboxId)
if (!sandbox || sandbox.state !== SandboxState.SUSPENDED) {
return false
}
try {
this.updateSandboxState(sandbox, SandboxState.RUNNING)
sandbox.lastActiveAt = new Date()
if (sandbox.iframe) {
const iframeWindow = sandbox.iframe.contentWindow
if (iframeWindow) {
// 发送恢复事件到应用
iframeWindow.postMessage({ type: 'system:resume' }, '*')
}
}
console.log(`沙箱 ${sandboxId} 已恢复`)
return true
} catch (error) {
console.error('恢复沙箱失败:', error)
return false
}
}
/**
* 销毁沙箱
*/
@@ -323,8 +263,8 @@ export class ApplicationSandboxEngine {
// 移除消息事件监听器
if (sandbox.messageHandler) {
window.removeEventListener('message', sandbox.messageHandler);
sandbox.messageHandler = undefined;
window.removeEventListener('message', sandbox.messageHandler)
sandbox.messageHandler = undefined
}
// 清理DOM元素
@@ -366,7 +306,7 @@ export class ApplicationSandboxEngine {
* 获取应用的所有沙箱
*/
getAppSandboxes(appId: string): SandboxInstance[] {
return Array.from(this.sandboxes.values()).filter(sandbox => sandbox.appId === appId)
return Array.from(this.sandboxes.values()).filter((sandbox) => sandbox.appId === appId)
}
/**
@@ -632,10 +572,10 @@ export class ApplicationSandboxEngine {
if (event.source === sandbox.iframe!.contentWindow) {
this.handleSandboxMessage(sandbox, event.data)
}
};
window.addEventListener('message', messageHandler);
}
window.addEventListener('message', messageHandler)
// 存储事件监听器引用,以便在销毁时移除
sandbox.messageHandler = messageHandler;
sandbox.messageHandler = messageHandler
// 简化安全限制主要依赖iframe的sandbox属性
sandbox.iframe.addEventListener('load', () => {
@@ -709,7 +649,11 @@ export class ApplicationSandboxEngine {
break
case 'network':
result = await this.resourceService.makeNetworkRequest(sandbox.appId, data.url, data.options)
result = await this.resourceService.makeNetworkRequest(
sandbox.appId,
data.url,
data.options
)
break
}
@@ -1171,10 +1115,10 @@ export class ApplicationSandboxEngine {
// 通知系统应用已准备就绪
window.parent.postMessage({ type: 'app:ready' }, '*');
})();
`;
`
iframeDoc.head.appendChild(script)
}
}
/**
* 设置性能监控
@@ -1260,9 +1204,12 @@ export class ApplicationSandboxEngine {
private collectPerformanceMetrics(sandbox: SandboxInstance): void {
if (sandbox.iframe && sandbox.iframe.contentWindow) {
// 请求性能数据
sandbox.iframe.contentWindow.postMessage({
sandbox.iframe.contentWindow.postMessage(
{
type: 'system:performance-request'
}, '*')
},
'*'
)
}
}

View File

@@ -8,49 +8,75 @@ import type { ResourceType } from './ResourceService'
* 消息类型枚举
*/
export enum MessageType {
/** 系统事件 */
SYSTEM = 'system',
/** 应用事件 */
APPLICATION = 'application',
/** 用户交互事件 */
USER_INTERACTION = 'user_interaction',
/** 跨应用事件 */
CROSS_APP = 'cross_app',
BROADCAST = 'broadcast',
/** 广播事件 */
BROADCAST = 'broadcast'
}
/**
* 消息优先级枚举
*/
export enum MessagePriority {
/** 低优先级 */
LOW = 0,
/** 正常优先级 */
NORMAL = 1,
/** 高优先级 */
HIGH = 2,
CRITICAL = 3,
/** 紧急优先级 */
CRITICAL = 3
}
/**
* 消息状态枚举
*/
export enum MessageStatus {
/** 等待发送 */
PENDING = 'pending',
/** 已发送 */
SENT = 'sent',
/** 已送达 */
DELIVERED = 'delivered',
/** 发送失败 */
FAILED = 'failed',
EXPIRED = 'expired',
/** 已取消 */
EXPIRED = 'expired'
}
/**
* 事件消息接口
*/
export interface EventMessage {
/** 消息ID */
id: string
/** 消息类型 */
type: MessageType
/** 消息优先级 */
priority: MessagePriority
/** 发送者ID */
senderId: string
receiverId?: string // undefined表示广播消息
/** 接收者ID, undefined表示广播消息 */
receiverId?: string
/** 消息频道 */
channel: string
/** 消息内容 */
payload: any
/** 消息发送时间 */
timestamp: Date
/** 消息过期时间 */
expiresAt?: Date
/** 消息状态 */
status: MessageStatus
/** 重试次数 */
retryCount: number
/** 最大重试次数 */
maxRetries: number
}
@@ -58,13 +84,21 @@ export interface EventMessage {
* 事件订阅者接口
*/
export interface EventSubscriber {
/** 订阅者ID */
id: string
/** 应用ID */
appId: string
/** 消息频道 */
channel: string
/** 订阅者处理函数 */
handler: (message: EventMessage) => void | Promise<void>
/** 消息过滤器 */
filter?: (message: EventMessage) => boolean
/** 订阅者优先级 */
priority: MessagePriority
/** 创建时间 */
createdAt: Date
/** 是否启用 */
active: boolean
}
@@ -72,23 +106,36 @@ export interface EventSubscriber {
* 通信通道接口
*/
export interface CommunicationChannel {
/** 通道名称 */
name: string
/** 通道描述 */
description: string
restricted: boolean // 是否需要权限
allowedApps: string[] // 允许访问的应用ID列表
maxMessageSize: number // 最大消息大小(字节)
messageRetention: number // 消息保留时间(毫秒)
/** 是否需要权限 */
restricted: boolean
/** 允许的源应用ID列表 */
/** 允许访问的应用ID列表 */
allowedApps: string[]
/** 最大消息大小(字节) */
maxMessageSize: number
/** 消息保留时间(毫秒) */
messageRetention: number
}
/**
* 事件统计信息
*/
export interface EventStatistics {
/** 总发送消息数 */
totalMessagesSent: number
/** 总接收消息数 */
totalMessagesReceived: number
/** 总广播数 */
totalBroadcasts: number
/** 失败消息数 */
failedMessages: number
/** 激活的订阅者数 */
activeSubscribers: number
/** 通道使用情况 */
channelUsage: Map<string, number>
}
@@ -151,10 +198,12 @@ export class EventCommunicationService {
totalBroadcasts: 0,
failedMessages: 0,
activeSubscribers: 0,
channelUsage: new Map(),
channelUsage: new Map()
})
private processingInterval: number | null = null
private lastProcessTime: number = 0
private processInterval: number = 100 // 处理间隔(毫秒)
private eventBus: IEventBuilder<EventCommunicationEvents>
constructor(eventBus: IEventBuilder<EventCommunicationEvents>) {
@@ -173,7 +222,7 @@ export class EventCommunicationService {
options: {
filter?: (message: EventMessage) => boolean
priority?: MessagePriority
} = {},
} = {}
): string {
// 检查通道权限
if (!this.canAccessChannel(appId, channel)) {
@@ -189,7 +238,7 @@ export class EventCommunicationService {
filter: options.filter,
priority: options.priority || MessagePriority.NORMAL,
createdAt: new Date(),
active: true,
active: true
}
this.subscribers.set(subscriberId, subscriber)
@@ -224,8 +273,11 @@ export class EventCommunicationService {
type?: MessageType
expiresIn?: number // 过期时间(毫秒)
maxRetries?: number
} = {},
} = {}
): Promise<string> {
if (this.getChannelSubscriberCount(channel) === 0) {
throw new Error(`频道 ${channel} 无订阅者`)
}
// 检查发送者权限
if (!this.canAccessChannel(senderId, channel)) {
throw new Error(`应用 ${senderId} 无权向频道 ${channel} 发送消息`)
@@ -253,7 +305,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
}
// 如果是点对点消息,直接发送
@@ -277,7 +329,7 @@ export class EventCommunicationService {
this.recordMessage(message)
console.log(
`[EventCommunication] 消息 ${messageId} 已发送到频道 ${channel}[发送者: ${senderId}]`,
`[EventCommunication] 消息 ${messageId} 已发送到频道 ${channel}[发送者: ${senderId}]`
)
return messageId
}
@@ -292,11 +344,11 @@ export class EventCommunicationService {
options: {
priority?: MessagePriority
expiresIn?: number
} = {},
} = {}
): Promise<string> {
return this.sendMessage(senderId, channel, payload, {
...options,
type: MessageType.BROADCAST,
type: MessageType.BROADCAST
})
}
@@ -310,14 +362,14 @@ export class EventCommunicationService {
options: {
priority?: MessagePriority
expiresIn?: number
} = {},
} = {}
): Promise<string> {
const channel = 'cross-app'
return this.sendMessage(senderId, channel, payload, {
...options,
receiverId,
type: MessageType.CROSS_APP,
type: MessageType.CROSS_APP
})
}
@@ -330,7 +382,7 @@ export class EventCommunicationService {
channel?: string
limit?: number
since?: Date
} = {},
} = {}
): EventMessage[] {
const history = this.messageHistory.get(appId) || []
@@ -363,7 +415,7 @@ 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
}
@@ -377,7 +429,7 @@ export class EventCommunicationService {
this.channels.set(channel, {
name: channel,
...config,
...config
})
console.log(`创建通信频道: ${channel}`)
@@ -442,7 +494,7 @@ export class EventCommunicationService {
*/
destroy(): void {
if (this.processingInterval) {
clearInterval(this.processingInterval)
cancelAnimationFrame(this.processingInterval)
this.processingInterval = null
}
@@ -466,7 +518,7 @@ export class EventCommunicationService {
restricted: true,
allowedApps: ['system'],
maxMessageSize: 1024 * 10, // 10KB
messageRetention: 24 * 60 * 60 * 1000, // 24小时
messageRetention: 24 * 60 * 60 * 1000 // 24小时
})
// 应用间通信频道
@@ -475,7 +527,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天
})
// 用户交互频道
@@ -484,7 +536,7 @@ export class EventCommunicationService {
restricted: false,
allowedApps: [],
maxMessageSize: 1024 * 5, // 5KB
messageRetention: 60 * 60 * 1000, // 1小时
messageRetention: 60 * 60 * 1000 // 1小时
})
// 广播频道
@@ -493,7 +545,7 @@ export class EventCommunicationService {
restricted: true,
allowedApps: ['system'],
maxMessageSize: 1024 * 50, // 50KB
messageRetention: 24 * 60 * 60 * 1000, // 24小时
messageRetention: 24 * 60 * 60 * 1000 // 24小时
})
}
@@ -553,7 +605,7 @@ export class EventCommunicationService {
// 只对非系统频道显示警告信息
if (message.channel !== 'system') {
console.warn(
`[EventCommunication] 没有找到频道 ${message.channel} 的订阅者[消息 ID: ${message.id}]`,
`[EventCommunication] 没有找到频道 ${message.channel} 的订阅者[消息 ID: ${message.id}]`
)
}
return
@@ -570,7 +622,7 @@ export class EventCommunicationService {
await subscriber.handler(message)
this.statistics.totalMessagesReceived++
console.log(
`[EventCommunication] 消息 ${message.id} 已投递给订阅者 ${subscriber.id}[频道: ${message.channel}]`,
`[EventCommunication] 消息 ${message.id} 已投递给订阅者 ${subscriber.id}[频道: ${message.channel}]`
)
} catch (error) {
console.error(`向订阅者 ${subscriber.id} 发送消息失败:`, error)
@@ -615,10 +667,20 @@ export class EventCommunicationService {
* 开始消息处理循环
*/
private startMessageProcessing(): void {
this.processingInterval = setInterval(() => {
const processFrame = (timestamp: number) => {
// 如果距离上次处理时间超过设定间隔,则处理消息
if (timestamp - this.lastProcessTime >= this.processInterval) {
this.processMessageQueue()
this.cleanupExpiredMessages()
}, 100) // 每100ms处理一次
this.lastProcessTime = timestamp
}
// 继续下一帧
this.processingInterval = requestAnimationFrame(processFrame)
}
// 启动处理循环
this.processingInterval = requestAnimationFrame(processFrame)
}
/**
@@ -680,7 +742,7 @@ export class EventCommunicationService {
*/
private updateActiveSubscribersCount(): void {
this.statistics.activeSubscribers = Array.from(this.subscribers.values()).filter(
(sub) => sub.active,
(sub) => sub.active
).length
}
}

View File

@@ -3,7 +3,7 @@ import { EventBuilderImpl } from '@/events/impl/EventBuilderImpl'
import type { IEventBuilder } from '@/events/IEventBuilder'
import type {
EventCommunicationEvents,
WindowFormDataUpdateParams,
WindowFormDataUpdateParams
} from './EventCommunicationService'
import type { ResourceType } from './ResourceService'
@@ -19,36 +19,26 @@ import { externalAppDiscovery } from './ExternalAppDiscovery'
* 系统服务配置接口
*/
export interface SystemServiceConfig {
debug?: boolean
maxMemoryUsage?: number
maxCpuUsage?: number
enablePerformanceMonitoring?: boolean
enableSecurityAudit?: boolean
autoCleanup?: boolean
cleanupInterval?: number
debug?: boolean // 是否开启调试模式
autoCleanup?: boolean // 是否自动清理
cleanupInterval?: number // 自动清理间隔
}
/**
* 系统状态接口
*/
export interface SystemStatus {
initialized: boolean
running: boolean
initialized: boolean // 系统是否初始化完成
running: boolean // 系统是否运行中
servicesStatus: {
windowService: boolean
resourceService: boolean
eventService: boolean
sandboxEngine: boolean
lifecycleManager: boolean
windowService: boolean // 窗体服务是否启动
resourceService: boolean // 资源服务是否启动
eventService: boolean // 事件服务是否启动
sandboxEngine: boolean // 沙箱引擎是否启动
lifecycleManager: boolean // 生命周期管理器是否启动
}
performance: {
memoryUsage: number
cpuUsage: number
activeApps: number
activeWindows: number
}
uptime: number
lastError?: string
uptime: number // 系统运行时间
lastError?: string // 最后一次错误
}
/**
@@ -88,15 +78,9 @@ export class SystemServiceIntegration {
resourceService: false,
eventService: false,
sandboxEngine: false,
lifecycleManager: false,
lifecycleManager: false
},
performance: {
memoryUsage: 0,
cpuUsage: 0,
activeApps: 0,
activeWindows: 0,
},
uptime: 0,
uptime: 0
})
// 性能监控
@@ -106,13 +90,9 @@ export class SystemServiceIntegration {
constructor(config: SystemServiceConfig = {}) {
this.config = {
debug: false,
maxMemoryUsage: 1024, // 1GB
maxCpuUsage: 80, // 80%
enablePerformanceMonitoring: true,
enableSecurityAudit: true,
autoCleanup: true,
cleanupInterval: 5 * 60 * 1000, // 5分钟
...config,
...config
}
this.startTime = new Date()
@@ -141,11 +121,6 @@ export class SystemServiceIntegration {
// 设置SDK消息处理
this.setupSDKMessageHandling()
// 启动性能监控
if (this.config.enablePerformanceMonitoring) {
this.startPerformanceMonitoring()
}
// 启动自动清理
if (this.config.autoCleanup) {
this.startAutoCleanup()
@@ -167,7 +142,7 @@ export class SystemServiceIntegration {
// 发送系统就绪事件
this.eventService.sendMessage('system', 'system-ready', {
timestamp: new Date(),
services: Object.keys(this.systemStatus.servicesStatus),
services: Object.keys(this.systemStatus.servicesStatus)
})
} catch (error) {
console.error('系统服务初始化失败:', error)
@@ -180,7 +155,6 @@ export class SystemServiceIntegration {
* 获取系统状态
*/
getSystemStatus(): SystemStatus {
this.updateSystemStatus()
return { ...this.systemStatus }
}
@@ -240,7 +214,7 @@ export class SystemServiceIntegration {
return {
success: true,
data: result,
requestId,
requestId
}
} catch (error) {
console.error('SDK调用失败:', error)
@@ -248,7 +222,7 @@ export class SystemServiceIntegration {
return {
success: false,
error: error instanceof Error ? error.message : String(error),
requestId,
requestId
}
}
}
@@ -324,8 +298,6 @@ export class SystemServiceIntegration {
console.log('系统服务已关闭')
}
// 私有方法
/**
* 初始化所有服务
*/
@@ -356,7 +328,7 @@ export class SystemServiceIntegration {
this.windowService,
this.resourceService,
this.eventService,
this.sandboxEngine,
this.sandboxEngine
)
this.systemStatus.servicesStatus.lifecycleManager = true
}
@@ -380,15 +352,15 @@ export class SystemServiceIntegration {
'onWindowStateChanged',
(windowId: string, newState: string, oldState: string) => {
console.log(
`[SystemIntegration] 接收到窗体状态变化事件: ${windowId} ${oldState} -> ${newState}`,
`[SystemIntegration] 接收到窗体状态变化事件: ${windowId} ${oldState} -> ${newState}`
)
this.eventService.sendMessage('system', 'window-state-change', {
windowId,
newState,
oldState,
oldState
})
console.log(`[SystemIntegration] 已发送 window-state-change 消息到事件通信服务`)
},
}
)
// 监听窗体关闭事件,自动停止对应的应用
@@ -412,24 +384,13 @@ export class SystemServiceIntegration {
// 监听窗体数据更新事件
this.eventBus.addEventListener('onWindowFormDataUpdate', (data: WindowFormDataUpdateParams) => {
console.log(`[SystemIntegration] 接收到窗体数据更新事件:`, data)
// 只有在有订阅者时才发送消息
if (this.eventService.getChannelSubscriberCount('window-form-data-update') > 0) {
this.eventService.sendMessage('system', 'window-form-data-update', data)
console.log(`[SystemIntegration] 已发送 window-form-data-update 消息到事件通信服务`)
} else {
console.log(`[SystemIntegration] 无订阅者,跳过发送 window-form-data-update 消息`)
}
})
// 监听窗体调整尺寸开始事件
this.eventBus.addEventListener('onWindowFormResizeStart', (windowId: string) => {
console.log(`[SystemIntegration] 接收到窗体调整尺寸开始事件: ${windowId}`)
// 只有在有订阅者时才发送消息
if (this.eventService.getChannelSubscriberCount('window-form-resize-start') > 0) {
this.eventService.sendMessage('system', 'window-form-resize-start', { windowId })
} else {
console.log(`[SystemIntegration] 无订阅者,跳过发送 window-form-resize-start 消息`)
}
})
// 监听窗体调整尺寸过程中事件
@@ -438,43 +399,21 @@ export class SystemServiceIntegration {
(windowId: string, width: number, height: number) => {
console.log(`[SystemIntegration] 接收到窗体调整尺寸过程中事件: ${windowId}`, {
width,
height,
height
})
// 只有在有订阅者时才发送消息
if (this.eventService.getChannelSubscriberCount('window-form-resizing') > 0) {
this.eventService.sendMessage('system', 'window-form-resizing', {
windowId,
width,
height,
height
})
} else {
console.log(`[SystemIntegration] 无订阅者,跳过发送 window-form-resizing 消息`)
}
},
)
// 监听窗体调整尺寸结束事件
this.eventBus.addEventListener('onWindowFormResizeEnd', (windowId: string) => {
console.log(`[SystemIntegration] 接收到窗体调整尺寸结束事件: ${windowId}`)
// 只有在有订阅者时才发送消息
if (this.eventService.getChannelSubscriberCount('window-form-resize-end') > 0) {
this.eventService.sendMessage('system', 'window-form-resize-end', { windowId })
} else {
console.log(`[SystemIntegration] 无订阅者,跳过发送 window-form-resize-end 消息`)
}
})
// 监听资源配额超出
this.eventBus.addEventListener(
'onResourceQuotaExceeded',
(appId: string, resourceType: ResourceType) => {
console.log(`[SystemIntegration] 接收到资源配额超出事件: ${appId} - ${resourceType}`)
this.eventService.sendMessage('system', 'resource-quota-exceeded', {
appId,
resourceType,
})
},
)
}
/**
@@ -503,9 +442,9 @@ export class SystemServiceIntegration {
iframe.contentWindow?.postMessage(
{
type: 'system:response',
...result,
...result
},
'*',
'*'
)
}
}
@@ -567,9 +506,9 @@ export class SystemServiceIntegration {
type: 'system:storage-response',
requestId,
result,
success,
success
},
'*',
'*'
)
}
}
@@ -660,7 +599,7 @@ export class SystemServiceIntegration {
const windowData = this.windowService.getWindow(windowId)
return {
width: windowData?.config.width,
height: windowData?.config.height,
height: windowData?.config.height
}
default:
@@ -714,7 +653,7 @@ export class SystemServiceIntegration {
status: response.status,
statusText: response.statusText,
headers: {} as Record<string, string>, // 简化headers处理
url: response.url,
url: response.url
}
: null
@@ -726,7 +665,7 @@ export class SystemServiceIntegration {
return {
requestCount: requests.length,
failureCount: requests.filter((r) => r.status && r.status >= 400).length,
averageTime: 0, // 需要实现时间统计
averageTime: 0 // 需要实现时间统计
}
default:
@@ -750,7 +689,7 @@ export class SystemServiceIntegration {
this.sandboxEngine.sendMessage(app.sandboxId, {
type: 'system:event',
subscriptionId: data.subscriptionId,
message,
message
})
}
})
@@ -800,10 +739,10 @@ export class SystemServiceIntegration {
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
screenResolution: {
width: screen.width,
height: screen.height,
height: screen.height
},
colorDepth: screen.colorDepth,
pixelRatio: window.devicePixelRatio,
pixelRatio: window.devicePixelRatio
}
case 'getAppInfo':
@@ -815,7 +754,7 @@ export class SystemServiceIntegration {
version: app.version,
permissions: app.manifest.permissions,
createdAt: app.installedAt,
lastActiveAt: app.lastActiveAt,
lastActiveAt: app.lastActiveAt
}
: null
@@ -851,32 +790,6 @@ export class SystemServiceIntegration {
return null
}
/**
* 开始性能监控
*/
private startPerformanceMonitoring(): void {
this.performanceInterval = setInterval(() => {
this.updateSystemStatus()
// 检查性能阈值
if (this.systemStatus.performance.memoryUsage > this.config.maxMemoryUsage!) {
this.eventService.sendMessage('system', 'performance-alert', {
type: 'memory',
usage: this.systemStatus.performance.memoryUsage,
limit: this.config.maxMemoryUsage,
})
}
if (this.systemStatus.performance.cpuUsage > this.config.maxCpuUsage!) {
this.eventService.sendMessage('system', 'performance-alert', {
type: 'cpu',
usage: this.systemStatus.performance.cpuUsage,
limit: this.config.maxCpuUsage,
})
}
}, 10000) // 每10秒检查一次
}
/**
* 开始自动清理
*/
@@ -894,20 +807,6 @@ export class SystemServiceIntegration {
}, this.config.cleanupInterval!)
}
/**
* 更新系统状态
*/
private updateSystemStatus(): void {
this.systemStatus.uptime = Date.now() - this.startTime.getTime()
this.systemStatus.performance.activeApps = this.lifecycleManager?.getRunningApps().length || 0
this.systemStatus.performance.activeWindows = this.windowService?.getAllWindows().length || 0
// 简化的内存和CPU使用率计算
this.systemStatus.performance.memoryUsage =
(performance as any).memory?.usedJSHeapSize / 1024 / 1024 || 0
this.systemStatus.performance.cpuUsage = Math.random() * 20 // 模拟CPU使用率
}
/**
* 检查是否已初始化
*/
@@ -927,7 +826,7 @@ export class SystemServiceIntegration {
})
window.addEventListener('unhandledrejection', (event) => {
console.error('未处理的Promise拒绝:', event.reason)
// console.error('未处理的Promise拒绝:', event.reason)
this.systemStatus.lastError = event.reason?.message || '未处理的Promise拒绝'
})
}

View File

@@ -13,18 +13,6 @@
{{ systemStatus.running ? '正常' : '错误' }}
</span>
</div>
<div class="status-item">
<span>活跃应用:</span>
<span>{{ systemStatus.performance.activeApps }}</span>
</div>
<div class="status-item">
<span>活跃窗体:</span>
<span>{{ systemStatus.performance.activeWindows }}</span>
</div>
<div class="status-item">
<span>内存使用:</span>
<span>{{ Math.round(systemStatus.performance.memoryUsage) }}MB</span>
</div>
<button @click="showSystemStatus = false" class="close-btn">关闭</button>
</div>
</div>
@@ -68,12 +56,6 @@ const systemStatus = ref<SystemStatus>({
sandboxEngine: false,
lifecycleManager: false
},
performance: {
memoryUsage: 0,
cpuUsage: 0,
activeApps: 0,
activeWindows: 0
},
uptime: 0
})