diff --git a/src/core/XSystem.ts b/src/core/XSystem.ts index 5bc4901..e588e08 100644 --- a/src/core/XSystem.ts +++ b/src/core/XSystem.ts @@ -11,6 +11,10 @@ import type { IProcess } from '@/core/process/IProcess.ts' import type { IProcessInfo } from '@/core/process/IProcessInfo.ts' import { ObservableWeakRefImpl } from '@/core/state/impl/ObservableWeakRefImpl.ts' import type { IObservable } from '@/core/state/IObservable.ts' +import { NotificationService } from '@/core/service/services/NotificationService.ts' +import { SettingsService } from '@/core/service/services/SettingsService.ts' +import { WindowFormService } from '@/core/service/services/WindowFormService.ts' +import { UserService } from '@/core/service/services/UserService.ts' interface IGlobalState { isLogin: boolean @@ -28,6 +32,10 @@ export default class XSystem { constructor() { console.log('XSystem') + new NotificationService() + new SettingsService() + new WindowFormService() + new UserService() } public static get instance() { diff --git a/src/core/process/IProcessManage.ts b/src/core/process/IProcessManage.ts index be8dac1..c189d31 100644 --- a/src/core/process/IProcessManage.ts +++ b/src/core/process/IProcessManage.ts @@ -9,10 +9,10 @@ export interface IProcessManage { /** 所有进程信息 */ get processInfos(): IProcessInfo[]; /** - * 添加进程 + * 注册进程 * @param process 进程 */ - addProcess(process: IProcess): void; + registerProcess(process: IProcess): void; /** * 通过进程id查找进程 * @param id 进程id diff --git a/src/core/process/impl/ProcessImpl.ts b/src/core/process/impl/ProcessImpl.ts index 07bc25f..cb0de53 100644 --- a/src/core/process/impl/ProcessImpl.ts +++ b/src/core/process/impl/ProcessImpl.ts @@ -30,7 +30,7 @@ export default class ProcessImpl implements IProcess { const startName = info.startName; - XSystem.instance.processManage.addProcess(this); + XSystem.instance.processManage.registerProcess(this); // 通过设置 isJustProcess 为 true,则不会创建窗体 if (!info.isJustProcess) { this.openWindowForm(startName) diff --git a/src/core/process/impl/ProcessManageImpl.ts b/src/core/process/impl/ProcessManageImpl.ts index 5f04529..8ef9784 100644 --- a/src/core/process/impl/ProcessManageImpl.ts +++ b/src/core/process/impl/ProcessManageImpl.ts @@ -36,7 +36,7 @@ export default class ProcessManageImpl implements IProcessManage { } // 添加进程 - public addProcess(process: ProcessImpl) { + public registerProcess(process: ProcessImpl) { this._processPool.set(process.id, process); } diff --git a/src/core/service/kernel/AService.ts b/src/core/service/kernel/AService.ts new file mode 100644 index 0000000..3774415 --- /dev/null +++ b/src/core/service/kernel/AService.ts @@ -0,0 +1,21 @@ +import { serviceManager, type ServiceManager } from '@/core/service/kernel/ServiceManager.ts' + +/** + * 服务基类 - 抽象类 + */ +export abstract class AService { + private readonly _id: string; + private _sm: ServiceManager = serviceManager; + + get id() { + return this._id; + } + get sm() { + return this._sm; + } + + protected constructor(id: string) { + this._id = id; + this._sm.registerService(this); + } +} diff --git a/src/core/service/kernel/EventService.ts b/src/core/service/kernel/EventService.ts new file mode 100644 index 0000000..e177c4a --- /dev/null +++ b/src/core/service/kernel/EventService.ts @@ -0,0 +1,98 @@ +/** + * 事件定义 + * @interface IEventMap 事件定义 键是事件名称,值是事件处理函数 + */ +export interface IEventMap { + [key: string]: (...args: any[]) => void +} + +interface HandlerWrapper any> { + fn: T + once: boolean +} + +export class EventService { + private _eventHandlers = new Map>>() + + /** + * 添加事件监听器 + * @param eventName 事件名称 + * @param handler 监听器 + * @param options { immediate: 立即执行一次 immediateArgs: 立即执行的参数 once: 只监听一次 } + * @example + * eventBus.addEventListener('noArgs', () => {}) + * eventBus.addEventListener('greet', name => {}, { immediate: true, immediateArgs: ['abc'] }) + * eventBus.addEventListener('onResize', (w, h) => {}, { immediate: true, immediateArgs: [1, 2] }) + */ + addEventListener( + eventName: E, + handler: F, + options?: { + immediate?: boolean; + immediateArgs?: Parameters; + once?: boolean; + }, + ) { + if (!handler) return + if (!this._eventHandlers.has(eventName)) { + this._eventHandlers.set(eventName, new Set>()) + } + + const set = this._eventHandlers.get(eventName)! + if (![...set].some((wrapper) => wrapper.fn === handler)) { + set.add({ fn: handler, once: options?.once ?? false }) + } + + if (options?.immediate) { + try { + handler(...(options.immediateArgs ?? [])) + } catch (e) { + console.error(e) + } + } + } + + /** + * 移除事件监听器 + * @param eventName 事件名称 + * @param handler 监听器 + * @example + * eventBus.removeEventListener('noArgs', () => {}) + */ + removeEventListener(eventName: E, handler: F) { + const set = this._eventHandlers.get(eventName) + if (!set) return + + for (const wrapper of set) { + if (wrapper.fn === handler) { + set.delete(wrapper) + } + } + } + + /** + * 通知事件 + * @param eventName 事件名称 + * @param args 参数 + * @example + * eventBus.notifyEvent('noArgs') + * eventBus.notifyEvent('greet', 'Alice') + * eventBus.notifyEvent('onResize', 1, 2) + */ + notifyEvent(eventName: E, ...args: Parameters) { + if (!this._eventHandlers.has(eventName)) return + + const set = this._eventHandlers.get(eventName)! + for (const wrapper of set) { + try { + wrapper.fn(...args) + } catch (e) { + console.error(e) + } + + if (wrapper.once) { + set.delete(wrapper) + } + } + } +} diff --git a/src/core/service/kernel/ServiceManager.ts b/src/core/service/kernel/ServiceManager.ts new file mode 100644 index 0000000..8e8dba4 --- /dev/null +++ b/src/core/service/kernel/ServiceManager.ts @@ -0,0 +1,41 @@ +import type { AService } from '@/core/service/kernel/AService.ts' + +/** + * 服务管理 + */ +export class ServiceManager { + private _services: Map = new Map(); + + get services(): Map { + return this._services + } + + /** + * 注册服务 + * @param service + */ + registerService(service: AService): void { + if (this._services.has(service.id)) { + throw new Error(`服务 ${service.id} 已存在`) + } + this._services.set(service.id, service) + } + + /** + * 通过id获取服务 + * @param id + */ + getService(id: string): T | undefined { + return this._services.get(id) as T | undefined + } + + /** + * 广播 + * @param event + * @param data + */ + broadcast(event: string, data?: any): void { + } +} + +export const serviceManager = new ServiceManager() diff --git a/src/core/service/services/NotificationService.ts b/src/core/service/services/NotificationService.ts new file mode 100644 index 0000000..97fd2be --- /dev/null +++ b/src/core/service/services/NotificationService.ts @@ -0,0 +1,8 @@ +import { AService } from '@/core/service/kernel/AService.ts' + +export class NotificationService extends AService { + constructor() { + super('NotificationService'); + console.log('NotificationService - 服务注册') + } +} \ No newline at end of file diff --git a/src/core/service/services/SettingsService.ts b/src/core/service/services/SettingsService.ts new file mode 100644 index 0000000..c560680 --- /dev/null +++ b/src/core/service/services/SettingsService.ts @@ -0,0 +1,8 @@ +import { AService } from '@/core/service/kernel/AService.ts' + +export class SettingsService extends AService { + constructor() { + super('SettingsService') + console.log('SettingsService - 服务注册') + } +} \ No newline at end of file diff --git a/src/core/service/services/UserService.ts b/src/core/service/services/UserService.ts new file mode 100644 index 0000000..f6c87b9 --- /dev/null +++ b/src/core/service/services/UserService.ts @@ -0,0 +1,8 @@ +import { AService } from '@/core/service/kernel/AService.ts' + +export class UserService extends AService { + constructor() { + super("UserService"); + console.log("UserService - 服务注册") + } +} \ No newline at end of file diff --git a/src/core/service/services/WindowFormService.ts b/src/core/service/services/WindowFormService.ts new file mode 100644 index 0000000..f71bf8b --- /dev/null +++ b/src/core/service/services/WindowFormService.ts @@ -0,0 +1,112 @@ +import { AService } from '@/core/service/kernel/AService.ts' + +interface IWindow { + id: string; + title: string; + x: number; + y: number; + width: number; + height: number; + zIndex: number; + minimized: boolean; + maximized: boolean; +} + +export class WindowFormService extends AService { + private windows: Map = new Map(); + private zCounter = 1; + + constructor() { + super("WindowForm"); + console.log('WindowFormService - 服务注册') + } + + createWindow(title: string, config?: Partial): IWindow { + const id = `win-${Date.now()}-${Math.random()}`; + const win: IWindow = { + id, + title, + x: config?.x ?? 100, + y: config?.y ?? 100, + width: config?.width ?? 400, + height: config?.height ?? 300, + zIndex: this.zCounter++, + minimized: false, + maximized: false + }; + this.windows.set(id, win); + this.sm.broadcast("WindowFrom:created", win); + return win; + } + + closeWindow(id: string) { + if (this.windows.has(id)) { + this.windows.delete(id); + this.sm.broadcast("WindowFrom:closed", id); + } + } + + focusWindow(id: string) { + const win = this.windows.get(id); + if (win) { + win.zIndex = this.zCounter++; + this.sm.broadcast("WindowFrom:focused", win); + } + } + + minimizeWindow(id: string) { + const win = this.windows.get(id); + if (win) { + win.minimized = true; + this.sm.broadcast("WindowFrom:minimized", win); + } + } + + maximizeWindow(id: string) { + const win = this.windows.get(id); + if (win) { + win.maximized = !win.maximized; + this.sm.broadcast("WindowFrom:maximized", win); + } + } + + getWindows(): IWindow[] { + return Array.from(this.windows.values()).sort((a, b) => a.zIndex - b.zIndex); + } + + onMessage(event: string, data?: any) { + console.log(`[WindowService] 收到事件:`, event, data); + } +} + +// ==================== DesktopProcess ==================== +// class DesktopProcess implements IProcess { +// id = "desktop"; +// private windows: IWindow[] = []; +// +// constructor(private sm: ServiceManager) { +// sm.registerProcess(this); +// } +// +// render() { +// console.log("\n[Desktop 渲染]"); +// this.windows +// .sort((a, b) => a.zIndex - b.zIndex) +// .forEach(win => { +// console.log( +// `- ${win.title} (${win.id}) at (${win.x},${win.y}) size(${win.width}x${win.height}) z=${win.zIndex} ${win.minimized ? "[最小化]" : win.maximized ? "[最大化]" : ""}` +// ); +// }); +// } +// +// onMessage(event: string, data?: any) { +// if (event.startsWith("window:")) { +// // 更新桌面维护的窗口列表 +// const ws = this.sm.getService("window"); +// if (ws) { +// this.windows = ws.getWindows(); +// this.render(); +// } +// } +// } +// } \ No newline at end of file