`
This commit is contained in:
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user