feat: 实现可扩展的字段编辑器系统与专业资产选择器 (#227)

This commit is contained in:
YHH
2025-11-19 14:54:03 +08:00
committed by GitHub
parent caed5428d5
commit ecfef727c8
18 changed files with 1330 additions and 11 deletions

View File

@@ -0,0 +1,50 @@
import { IService, createLogger } from '@esengine/ecs-framework';
import { IFieldEditor, IFieldEditorRegistry, FieldEditorContext } from './IFieldEditor';
const logger = createLogger('FieldEditorRegistry');
export class FieldEditorRegistry implements IFieldEditorRegistry, IService {
private editors: Map<string, IFieldEditor> = new Map();
register(editor: IFieldEditor): void {
if (this.editors.has(editor.type)) {
logger.warn(`Overwriting existing field editor: ${editor.type}`);
}
this.editors.set(editor.type, editor);
logger.debug(`Registered field editor: ${editor.name} (${editor.type})`);
}
unregister(type: string): void {
if (this.editors.delete(type)) {
logger.debug(`Unregistered field editor: ${type}`);
}
}
getEditor(type: string, context?: FieldEditorContext): IFieldEditor | undefined {
const editor = this.editors.get(type);
if (editor) {
return editor;
}
const editors = Array.from(this.editors.values())
.sort((a, b) => (b.priority || 0) - (a.priority || 0));
for (const editor of editors) {
if (editor.canHandle(type, context)) {
return editor;
}
}
return undefined;
}
getAllEditors(): IFieldEditor[] {
return Array.from(this.editors.values());
}
dispose(): void {
this.editors.clear();
logger.debug('FieldEditorRegistry disposed');
}
}

View File

@@ -0,0 +1,45 @@
import { ReactElement } from 'react';
export interface FieldEditorContext {
readonly?: boolean;
projectPath?: string;
decimalPlaces?: number;
metadata?: Record<string, any>;
}
export interface FieldEditorProps<T = any> {
label: string;
value: T;
onChange: (value: T) => void;
context: FieldEditorContext;
}
export interface IFieldEditor<T = any> {
readonly type: string;
readonly name: string;
readonly priority?: number;
canHandle(fieldType: string, context?: FieldEditorContext): boolean;
render(props: FieldEditorProps<T>): ReactElement;
}
export interface IFieldEditorRegistry {
register(editor: IFieldEditor): void;
unregister(type: string): void;
getEditor(type: string, context?: FieldEditorContext): IFieldEditor | undefined;
getAllEditors(): IFieldEditor[];
}
export interface FieldMetadata {
type: string;
options?: {
fileExtension?: string;
enumValues?: Array<{ value: string; label: string }>;
min?: number;
max?: number;
step?: number;
language?: string;
multiline?: boolean;
placeholder?: string;
};
}

View File

@@ -33,6 +33,8 @@ export * from './Services/IInspectorProvider';
export * from './Services/InspectorRegistry';
export * from './Services/IPropertyRenderer';
export * from './Services/PropertyRendererRegistry';
export * from './Services/IFieldEditor';
export * from './Services/FieldEditorRegistry';
export * from './Module/IEventBus';
export * from './Module/ICommandRegistry';