You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
61 lines
1.4 KiB
61 lines
1.4 KiB
import { type Component, markRaw } from 'vue'
|
|
|
|
export type WidgetSide = 'left' | 'right' | 'bottom'
|
|
|
|
export interface WidgetOption {
|
|
name: string
|
|
title?: string
|
|
icon: Component
|
|
shortcut?: string
|
|
side: WidgetSide
|
|
component: Component
|
|
order?: number
|
|
}
|
|
|
|
const _widgetMap = new Map<string, WidgetOption>()
|
|
|
|
export class WidgetInfo {
|
|
option: WidgetOption
|
|
|
|
constructor(option: WidgetOption) {
|
|
this.option = option
|
|
}
|
|
|
|
public install() {
|
|
if (!this.option.name) {
|
|
throw new Error('Widget name is required')
|
|
}
|
|
if (!this.option.component) {
|
|
throw new Error('Widget component is required')
|
|
}
|
|
if (_widgetMap.has(this.option.name)) {
|
|
console.log(`Widget ${this.option.name} already exists`)
|
|
return
|
|
}
|
|
_widgetMap.set(this.option.name, this.option)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 根据 Widget 定义的位置获取 Widget, 并按 order 排序
|
|
*/
|
|
export function getWidgetBySide(side: WidgetSide): WidgetOption[] {
|
|
return Array.from(_widgetMap.values())
|
|
.filter((widget) => widget.side === side)
|
|
.sort((a, b) => (a.order || 0) - (b.order || 0))
|
|
}
|
|
|
|
export function getWidgetByName(name: string): WidgetOption | undefined {
|
|
return _widgetMap.get(name)
|
|
}
|
|
|
|
export function getAllWidget(): WidgetOption[] {
|
|
return Array.from(_widgetMap.values()).sort((a, b) => (a.order || 0) - (b.order || 0))
|
|
}
|
|
|
|
/**
|
|
* 定义一个 Widget
|
|
*/
|
|
export function defineWidget(option: WidgetOption): WidgetInfo {
|
|
return new WidgetInfo(option)
|
|
}
|