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.
105 lines
2.9 KiB
105 lines
2.9 KiB
import type { GmPanelFactory, IGmCommand } from './GmTypes';
|
|
|
|
/**
|
|
* GM 命令与内容面板注册表(普通对象,避免 Map)。
|
|
*/
|
|
export class GmRegistry {
|
|
private static _cmds: { [id: string]: IGmCommand } = {};
|
|
private static _panels: { [id: string]: GmPanelFactory } = {};
|
|
private static _order: string[] = [];
|
|
|
|
/**
|
|
* 批量注册命令;同 id 覆盖并告警。
|
|
*/
|
|
static register(cmds: IGmCommand[]): void {
|
|
for (let i = 0; i < cmds.length; i++) {
|
|
const c = cmds[i];
|
|
if (!c?.id) {
|
|
console.warn('[GmRegistry] 跳过无 id 命令');
|
|
continue;
|
|
}
|
|
if (this._cmds[c.id]) {
|
|
console.warn('[GmRegistry] 覆盖命令', c.id);
|
|
} else {
|
|
this._order.push(c.id);
|
|
}
|
|
this._cmds[c.id] = c;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 注销单条命令。
|
|
*/
|
|
static unregister(id: string): void {
|
|
if (!this._cmds[id]) {
|
|
console.warn('[GmRegistry] 注销不存在的命令', id);
|
|
return;
|
|
}
|
|
delete this._cmds[id];
|
|
const idx = this._order.indexOf(id);
|
|
if (idx >= 0) this._order.splice(idx, 1);
|
|
}
|
|
|
|
/**
|
|
* 注册内容面板工厂。
|
|
*/
|
|
static registerPanel(panelId: string, factory: GmPanelFactory): void {
|
|
if (!panelId || !factory) {
|
|
console.warn('[GmRegistry] registerPanel 参数无效');
|
|
return;
|
|
}
|
|
if (this._panels[panelId]) {
|
|
console.warn('[GmRegistry] 覆盖面板', panelId);
|
|
}
|
|
this._panels[panelId] = factory;
|
|
}
|
|
|
|
/**
|
|
* 取面板工厂。
|
|
*/
|
|
static getPanelFactory(panelId: string): GmPanelFactory | null {
|
|
return this._panels[panelId] ?? null;
|
|
}
|
|
|
|
/**
|
|
* 按分组取出命令(已排序)。
|
|
*/
|
|
static listByGroup(group: string): IGmCommand[] {
|
|
const out: IGmCommand[] = [];
|
|
for (let i = 0; i < this._order.length; i++) {
|
|
const c = this._cmds[this._order[i]];
|
|
if (c && c.group === group) out.push(c);
|
|
}
|
|
out.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* 所有出现过的分组名(保持首次注册顺序)。
|
|
*/
|
|
static listGroups(): string[] {
|
|
const groups: string[] = [];
|
|
for (let i = 0; i < this._order.length; i++) {
|
|
const c = this._cmds[this._order[i]];
|
|
if (!c) continue;
|
|
if (groups.indexOf(c.group) < 0) groups.push(c.group);
|
|
}
|
|
return groups;
|
|
}
|
|
|
|
/**
|
|
* 是否已有命令。
|
|
*/
|
|
static hasCommands(): boolean {
|
|
return this._order.length > 0;
|
|
}
|
|
|
|
/**
|
|
* 清空(测试 / 热重载)。
|
|
*/
|
|
static clear(): void {
|
|
this._cmds = {};
|
|
this._panels = {};
|
|
this._order = [];
|
|
}
|
|
}
|
|
|