This commit is contained in:
2025-10-10 11:25:50 +08:00
parent 0ca5daad3b
commit acecffb055
2 changed files with 39 additions and 63 deletions

View File

@@ -6,18 +6,8 @@ import { reactive } from 'vue'
* 管理所有内置应用的注册和获取 * 管理所有内置应用的注册和获取
*/ */
export class AppRegistry { export class AppRegistry {
private static instance: AppRegistry | null = null
private apps = reactive(new Map<string, AppRegistration>()) private apps = reactive(new Map<string, AppRegistration>())
private constructor() {}
static getInstance(): AppRegistry {
if (!AppRegistry.instance) {
AppRegistry.instance = new AppRegistry()
}
return AppRegistry.instance
}
/** /**
* 注册内置应用 * 注册内置应用
*/ */
@@ -26,7 +16,7 @@ export class AppRegistry {
// 注意对于异步组件我们不立即标记为raw而是在实际加载时处理 // 注意对于异步组件我们不立即标记为raw而是在实际加载时处理
const safeRegistration = { const safeRegistration = {
...registration, ...registration,
component: registration.component, component: registration.component
} }
this.apps.set(registration.manifest.id, safeRegistration) this.apps.set(registration.manifest.id, safeRegistration)
console.log(`已注册内置应用: ${registration.manifest.name}`) console.log(`已注册内置应用: ${registration.manifest.name}`)
@@ -91,4 +81,4 @@ export class AppRegistry {
} }
// 导出单例实例 // 导出单例实例
export const appRegistry = AppRegistry.getInstance() export const appRegistry = new AppRegistry()

View File

@@ -2,6 +2,7 @@ import { reactive, ref } from 'vue'
import type { IEventBuilder, IEventMap } from '@/events/IEventBuilder' import type { IEventBuilder, IEventMap } from '@/events/IEventBuilder'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import type { ResizeDirection, ResizeState } from '@/ui/types/WindowFormTypes' import type { ResizeDirection, ResizeState } from '@/ui/types/WindowFormTypes'
import { appRegistry } from '@/apps/AppRegistry'
/** /**
* 窗体状态枚举 * 窗体状态枚举
@@ -14,7 +15,7 @@ export enum WindowState {
MAXIMIZED = 'maximized', MAXIMIZED = 'maximized',
CLOSING = 'closing', CLOSING = 'closing',
DESTROYED = 'destroyed', DESTROYED = 'destroyed',
ERROR = 'error', ERROR = 'error'
} }
/** /**
@@ -90,9 +91,6 @@ export interface WindowConfig {
y?: number y?: number
} }
/**
* 窗体实例接口
*/
/** /**
* 窗体实例接口 * 窗体实例接口
*/ */
@@ -158,7 +156,7 @@ export interface WindowEvents extends IEventMap {
* 窗体管理服务类 * 窗体管理服务类
*/ */
export class WindowFormService { export class WindowFormService {
private windows = reactive(new Map<string, WindowInstance>()) private windowsForm = reactive(new Map<string, WindowInstance>())
private activeWindowId = ref<string | null>(null) private activeWindowId = ref<string | null>(null)
private nextZIndex = 1000 private nextZIndex = 1000
private eventBus: IEventBuilder<WindowEvents> private eventBus: IEventBuilder<WindowEvents>
@@ -182,10 +180,10 @@ export class WindowFormService {
state: WindowState.CREATING, state: WindowState.CREATING,
zIndex: this.nextZIndex++, zIndex: this.nextZIndex++,
createdAt: now, createdAt: now,
updatedAt: now, updatedAt: now
} }
this.windows.set(windowId, windowInstance) this.windowsForm.set(windowId, windowInstance)
try { try {
// 创建窗体DOM元素 // 创建窗体DOM元素
@@ -212,7 +210,7 @@ export class WindowFormService {
* 销毁窗体 * 销毁窗体
*/ */
async destroyWindow(windowId: string): Promise<boolean> { async destroyWindow(windowId: string): Promise<boolean> {
const window = this.windows.get(windowId) const window = this.windowsForm.get(windowId)
if (!window) return false if (!window) return false
try { try {
@@ -224,13 +222,13 @@ export class WindowFormService {
} }
// 从集合中移除 // 从集合中移除
this.windows.delete(windowId) this.windowsForm.delete(windowId)
// 更新活跃窗体 // 更新活跃窗体
if (this.activeWindowId.value === windowId) { if (this.activeWindowId.value === windowId) {
this.activeWindowId.value = null this.activeWindowId.value = null
// 激活最后一个窗体 // 激活最后一个窗体
const lastWindow = Array.from(this.windows.values()).pop() const lastWindow = Array.from(this.windowsForm.values()).pop()
if (lastWindow) { if (lastWindow) {
this.setActiveWindow(lastWindow.id) this.setActiveWindow(lastWindow.id)
} }
@@ -248,7 +246,7 @@ export class WindowFormService {
* 最小化窗体 * 最小化窗体
*/ */
minimizeWindow(windowId: string): boolean { minimizeWindow(windowId: string): boolean {
const window = this.windows.get(windowId) const window = this.windowsForm.get(windowId)
if (!window || window.state === WindowState.MINIMIZED) return false if (!window || window.state === WindowState.MINIMIZED) return false
this.updateWindowState(windowId, WindowState.MINIMIZED) this.updateWindowState(windowId, WindowState.MINIMIZED)
@@ -267,7 +265,7 @@ export class WindowFormService {
* 最大化窗体 * 最大化窗体
*/ */
maximizeWindow(windowId: string): boolean { maximizeWindow(windowId: string): boolean {
const window = this.windows.get(windowId) const window = this.windowsForm.get(windowId)
if (!window || window.state === WindowState.MAXIMIZED) return false if (!window || window.state === WindowState.MAXIMIZED) return false
const oldState = window.state const oldState = window.state
@@ -288,7 +286,7 @@ export class WindowFormService {
width: '100vw', width: '100vw',
height: 'calc(100vh - 40px)', // 减去任务栏高度 height: 'calc(100vh - 40px)', // 减去任务栏高度
display: 'block', display: 'block',
transform: 'none', // 确保移除transform transform: 'none' // 确保移除transform
}) })
} }
@@ -304,7 +302,7 @@ export class WindowFormService {
* 还原窗体 * 还原窗体
*/ */
restoreWindow(windowId: string): boolean { restoreWindow(windowId: string): boolean {
const window = this.windows.get(windowId) const window = this.windowsForm.get(windowId)
if (!window) return false if (!window) return false
const targetState = const targetState =
@@ -331,7 +329,7 @@ export class WindowFormService {
height: originalHeight ? `${originalHeight}px` : `${window.config.height}px`, height: originalHeight ? `${originalHeight}px` : `${window.config.height}px`,
left: originalX ? `${originalX}px` : '0px', left: originalX ? `${originalX}px` : '0px',
top: originalY ? `${originalY}px` : '0px', top: originalY ? `${originalY}px` : '0px',
transform: 'none', // 确保移除transform transform: 'none' // 确保移除transform
}) })
// 更新配置中的位置 // 更新配置中的位置
@@ -352,7 +350,7 @@ export class WindowFormService {
* 设置窗体标题 * 设置窗体标题
*/ */
setWindowTitle(windowId: string, title: string): boolean { setWindowTitle(windowId: string, title: string): boolean {
const window = this.windows.get(windowId) const window = this.windowsForm.get(windowId)
if (!window) return false if (!window) return false
window.config.title = title window.config.title = title
@@ -376,7 +374,7 @@ export class WindowFormService {
* 设置窗体尺寸 * 设置窗体尺寸
*/ */
setWindowSize(windowId: string, width: number, height: number): boolean { setWindowSize(windowId: string, width: number, height: number): boolean {
const window = this.windows.get(windowId) const window = this.windowsForm.get(windowId)
if (!window) return false if (!window) return false
// 检查尺寸限制 // 检查尺寸限制
@@ -384,7 +382,7 @@ export class WindowFormService {
const finalHeight = this.clampDimension( const finalHeight = this.clampDimension(
height, height,
window.config.minHeight, window.config.minHeight,
window.config.maxHeight, window.config.maxHeight
) )
window.config.width = finalWidth window.config.width = finalWidth
@@ -408,14 +406,14 @@ export class WindowFormService {
* 获取窗体实例 * 获取窗体实例
*/ */
getWindow(windowId: string): WindowInstance | undefined { getWindow(windowId: string): WindowInstance | undefined {
return this.windows.get(windowId) return this.windowsForm.get(windowId)
} }
/** /**
* 获取所有窗体 * 获取所有窗体
*/ */
getAllWindows(): WindowInstance[] { getAllWindows(): WindowInstance[] {
return Array.from(this.windows.values()) return Array.from(this.windowsForm.values())
} }
/** /**
@@ -429,7 +427,7 @@ export class WindowFormService {
* 设置活跃窗体 * 设置活跃窗体
*/ */
setActiveWindow(windowId: string): boolean { setActiveWindow(windowId: string): boolean {
const window = this.windows.get(windowId) const window = this.windowsForm.get(windowId)
if (!window) return false if (!window) return false
this.activeWindowId.value = windowId this.activeWindowId.value = windowId
@@ -453,16 +451,6 @@ export class WindowFormService {
private async createWindowElement(windowInstance: WindowInstance): Promise<void> { private async createWindowElement(windowInstance: WindowInstance): Promise<void> {
const { id, config, appId } = windowInstance const { id, config, appId } = windowInstance
// 检查是否为内置应用
let isBuiltInApp = false
try {
const { AppRegistry } = await import('../apps/AppRegistry')
const appRegistry = AppRegistry.getInstance()
isBuiltInApp = appRegistry.hasApp(appId)
} catch (error) {
console.warn('无法导入 AppRegistry')
}
// 创建窗体容器 // 创建窗体容器
const windowElement = document.createElement('div') const windowElement = document.createElement('div')
windowElement.className = 'system-window' windowElement.className = 'system-window'
@@ -482,7 +470,7 @@ export class WindowFormService {
// 设置基本样式 // 设置基本样式
Object.assign(windowElement.style, { Object.assign(windowElement.style, {
position: 'fixed', position: 'absolute',
width: `${config.width}px`, width: `${config.width}px`,
height: `${config.height}px`, height: `${config.height}px`,
left: `${left}px`, left: `${left}px`,
@@ -492,7 +480,7 @@ export class WindowFormService {
border: '1px solid #ccc', border: '1px solid #ccc',
borderRadius: '8px', borderRadius: '8px',
boxShadow: '0 4px 20px rgba(0,0,0,0.15)', boxShadow: '0 4px 20px rgba(0,0,0,0.15)',
overflow: 'hidden', overflow: 'hidden'
}) })
// 保存初始位置到配置中 // 保存初始位置到配置中
@@ -512,7 +500,8 @@ export class WindowFormService {
overflow: hidden; overflow: hidden;
` `
if (isBuiltInApp) { // 检查是否为内置应用
if (appRegistry.hasApp(appId)) {
// 内置应用:创建普通 div 容器AppRenderer 组件会在这里渲染内容 // 内置应用:创建普通 div 容器AppRenderer 组件会在这里渲染内容
const appContainer = document.createElement('div') const appContainer = document.createElement('div')
appContainer.className = 'built-in-app-container' appContainer.className = 'built-in-app-container'
@@ -765,7 +754,7 @@ export class WindowFormService {
startWidth: 0, startWidth: 0,
startHeight: 0, startHeight: 0,
startXPosition: 0, startXPosition: 0,
startYPosition: 0, startYPosition: 0
} }
// 创建8个调整尺寸的手柄 // 创建8个调整尺寸的手柄
@@ -801,7 +790,7 @@ export class WindowFormService {
'bottomRight', 'bottomRight',
'bottom', 'bottom',
'bottomLeft', 'bottomLeft',
'left', 'left'
] ]
directions.forEach((direction) => { directions.forEach((direction) => {
@@ -884,7 +873,7 @@ export class WindowFormService {
private addResizeHandleEvents( private addResizeHandleEvents(
handle: HTMLElement, handle: HTMLElement,
windowElement: HTMLElement, windowElement: HTMLElement,
windowInstance: WindowInstance, windowInstance: WindowInstance
): void { ): void {
const direction = handle.className const direction = handle.className
.split(' ') .split(' ')
@@ -941,7 +930,7 @@ export class WindowFormService {
private updateCursorForResize( private updateCursorForResize(
e: MouseEvent, e: MouseEvent,
windowElement: HTMLElement, windowElement: HTMLElement,
windowInstance: WindowInstance, windowInstance: WindowInstance
): void { ): void {
if (!windowInstance.resizeState) return if (!windowInstance.resizeState) return
@@ -1016,8 +1005,8 @@ export class WindowFormService {
*/ */
private handleResizeMouseMove(e: MouseEvent): void { private handleResizeMouseMove(e: MouseEvent): void {
// 找到正在调整尺寸的窗体 // 找到正在调整尺寸的窗体
const resizingWindow = Array.from(this.windows.values()).find( const resizingWindow = Array.from(this.windowsForm.values()).find(
(window) => window.resizeState?.isResizing, (window) => window.resizeState?.isResizing
) )
// 如果没有正在调整尺寸的窗体,直接返回 // 如果没有正在调整尺寸的窗体,直接返回
@@ -1076,12 +1065,12 @@ export class WindowFormService {
newWidth = this.clampDimension( newWidth = this.clampDimension(
newWidth, newWidth,
resizingWindow.config.minWidth, resizingWindow.config.minWidth,
resizingWindow.config.maxWidth, resizingWindow.config.maxWidth
) )
newHeight = this.clampDimension( newHeight = this.clampDimension(
newHeight, newHeight,
resizingWindow.config.minHeight, resizingWindow.config.minHeight,
resizingWindow.config.maxHeight, resizingWindow.config.maxHeight
) )
// 应用新尺寸和位置 // 应用新尺寸和位置
@@ -1110,8 +1099,8 @@ export class WindowFormService {
*/ */
private handleResizeMouseUp(): void { private handleResizeMouseUp(): void {
// 找到正在调整尺寸的窗体 // 找到正在调整尺寸的窗体
const resizingWindow = Array.from(this.windows.values()).find( const resizingWindow = Array.from(this.windowsForm.values()).find(
(window) => window.resizeState?.isResizing, (window) => window.resizeState?.isResizing
) )
if (!resizingWindow || !resizingWindow.resizeState || !resizingWindow.element) return if (!resizingWindow || !resizingWindow.resizeState || !resizingWindow.element) return
@@ -1140,7 +1129,7 @@ export class WindowFormService {
* 发送窗体数据更新事件 * 发送窗体数据更新事件
*/ */
private notifyWindowFormDataUpdate(windowId: string): void { private notifyWindowFormDataUpdate(windowId: string): void {
const window = this.windows.get(windowId) const window = this.windowsForm.get(windowId)
if (!window || !window.element) return if (!window || !window.element) return
// 获取窗体数据 // 获取窗体数据
@@ -1151,7 +1140,7 @@ export class WindowFormService {
width: window.config.width, width: window.config.width,
height: window.config.height, height: window.config.height,
x: window.config.x !== undefined ? window.config.x : rect.left, x: window.config.x !== undefined ? window.config.x : rect.left,
y: window.config.y !== undefined ? window.config.y : rect.top, y: window.config.y !== undefined ? window.config.y : rect.top
} }
// 发送事件到事件总线 // 发送事件到事件总线
@@ -1164,9 +1153,6 @@ export class WindowFormService {
private async loadApplication(windowInstance: WindowInstance): Promise<void> { private async loadApplication(windowInstance: WindowInstance): Promise<void> {
// 动态导入 AppRegistry 检查是否为内置应用 // 动态导入 AppRegistry 检查是否为内置应用
try { try {
const { AppRegistry } = await import('../apps/AppRegistry')
const appRegistry = AppRegistry.getInstance()
// 如果是内置应用,直接返回,不需要等待 // 如果是内置应用,直接返回,不需要等待
if (appRegistry.hasApp(windowInstance.appId)) { if (appRegistry.hasApp(windowInstance.appId)) {
console.log(`[WindowService] 内置应用 ${windowInstance.appId} 无需等待加载`) console.log(`[WindowService] 内置应用 ${windowInstance.appId} 无需等待加载`)
@@ -1199,7 +1185,7 @@ export class WindowFormService {
} }
console.log(`[WindowService] 外部应用 ${windowInstance.appId} 加载完成`) console.log(`[WindowService] 外部应用 ${windowInstance.appId} 加载完成`)
resolve() resolve()
}, 200) // 改为200ms即使是外部应用也不需要这么长的时间 }, 200)
}) })
} }
@@ -1207,7 +1193,7 @@ export class WindowFormService {
* 更新窗体状态 * 更新窗体状态
*/ */
private updateWindowState(windowId: string, newState: WindowState): void { private updateWindowState(windowId: string, newState: WindowState): void {
const window = this.windows.get(windowId) const window = this.windowsForm.get(windowId)
if (!window) return if (!window) return
const oldState = window.state const oldState = window.state