refactor: 代码规范化与依赖清理 (#317)

* refactor(deps): 统一编辑器包依赖配置 & 优化分层架构

- 将 ecs-engine-bindgen 提升为 Layer 1 核心包
- 统一 9 个编辑器包的依赖声明模式
- 清理废弃的包目录 (ui, ui-editor, network-*)

* refactor(tokens): 修复 PrefabService 令牌冲突 & 补充 module.json

- 将 editor-core 的 PrefabServiceToken 改名为 EditorPrefabServiceToken
  避免与 asset-system 的 PrefabServiceToken 冲突 (Symbol.for 冲突)
- 为 mesh-3d 添加 module.json
- 为 world-streaming 添加 module.json

* refactor(editor-core): 整理导出结构 & 添加 blueprint tokens.ts

- 按功能分组整理 editor-core 的 65 行导出
- 添加清晰的分组注释 (中英双语)
- 为 blueprint 添加占位符 tokens.ts

* chore(editor): 为 14 个编辑器插件包添加 module.json

统一编辑器包的模块配置,包含:
- isEditorPlugin 标识
- runtimeModule 关联
- exports 导出清单 (inspectors, panels, gizmos)

* refactor(core): 改进类型安全 - 减少 as any 使用

- 添加 GlobalTypes.ts 定义小游戏平台和 Chrome API 类型
- SoAStorage 使用 IComponentTypeMetadata 替代 as any
- PlatformDetector 使用类型安全的平台检测
- 添加 ISoAStorageStats/ISoAFieldStats 接口

* feat(editor): 添加 EditorServicesContext 解决 prop drilling

- 新增 contexts/EditorServicesContext.tsx 提供统一服务访问
- App.tsx 包裹 EditorServicesProvider
- 提供 useEditorServices/useMessageHub 等便捷 hooks
- SceneHierarchy 添加迁移注释,后续可移除 props

* docs(editor): 澄清 inspector 目录架构关系

- inspector/ 标记为内部实现,添加 @deprecated 警告
- inspectors/ 标记为公共 API 入口点
- 添加架构说明文档

* refactor(editor): 添加全局类型声明消除 window as any

- 创建 editor-app/src/global.d.ts 声明 Window 接口扩展
- 创建 editor-core/src/global.d.ts 声明 Window 接口扩展
- 更新 App.tsx 使用类型安全的 window 属性访问
- 更新 PluginLoader.ts 使用 window.__ESENGINE_PLUGINS__
- 更新 PluginSDKRegistry.ts 使用 window.__ESENGINE_SDK__
- 更新 UserCodeService.ts 使用类型安全的全局变量访问

* refactor(editor): 提取项目和场景操作到独立 hooks

- 创建 useProjectActions hook 封装项目操作
- 创建 useSceneActions hook 封装场景操作
- 为渐进式重构 App.tsx 做准备

* refactor(editor): 清理冗余代码和未使用文件

删除的目录和文件:
- application/state/ - 重复的状态管理(与 stores/ 重复)
- 8 个孤立 CSS 文件(对应组件不存在)
- AssetBrowser.tsx - 仅为 ContentBrowser 的向后兼容包装
- AssetPicker.tsx - 未被使用
- AssetPickerDialog.tsx (顶级) - 已被 dialogs/ 版本取代
- EntityInspector.tsx (顶级) - 已被 inspectors/views/ 版本取代

修复:
- 移除 App.tsx 中未使用的导入
- 更新 application/index.ts 移除已删除模块
- 修复 useProjectActions.ts 的 MutableRefObject 类型

* refactor(editor): 统一 inspectors 模块导出结构

- 在 inspectors/index.ts 重新导出 PropertyInspector
- 创建 inspectors/fields/index.ts barrel export
- 导出 views、fields、common 子模块
- 更新 EntityInspector 使用统一入口导入

* refactor(editor): 删除废弃的 Profiler 组件

删除未使用的组件(共 1059 行):
- ProfilerPanel.tsx (229 行)
- ProfilerWindow.tsx (589 行)
- ProfilerDockPanel.tsx (241 行)
- ProfilerPanel.css
- ProfilerDockPanel.css

保留:AdvancedProfiler + AdvancedProfilerWindow(正在使用)

* refactor(runtime-core): 统一依赖处理与插件状态管理

- 新增 DependencyUtils 统一拓扑排序和依赖验证
- 新增 PluginState 定义插件生命周期状态机
- 合并 UnifiedPluginLoader 到 PluginLoader
- 清理 index.ts 移除不必要的 Token re-exports
- 新增 RuntimeMode/UserCodeRealm/ImportMapGenerator

* refactor(editor-core): 使用统一的 ImportMapGenerator

- WebBuildPipeline 使用 runtime-core 的 generateImportMap
- UserCodeService 添加 ImportMap 相关接口

* feat(compiler): 增强 esbuild 查找策略

- 支持本地 node_modules、pnpm exec、npx、全局多种来源
- EngineService 使用 RuntimeMode

* refactor(runtime-core): 简化 GameRuntime 代码

- 合并 _disableGameLogicSystems/_enableGameLogicSystems 为 _setGameLogicSystemsEnabled
- 精简本地 Token 定义的注释

* refactor(editor-core): 引入 BaseRegistry 基类消除代码重复

- 新增 BaseRegistry 和 PrioritizedRegistry 基类
- 重构 CompilerRegistry, InspectorRegistry, FieldEditorRegistry
- 统一注册表的日志记录和错误处理

* refactor(editor-core): 扩展 BaseRegistry 重构

- ComponentInspectorRegistry 继承 PrioritizedRegistry
- EditorComponentRegistry 继承 BaseRegistry
- EntityCreationRegistry 继承 BaseRegistry
- PropertyRendererRegistry 继承 PrioritizedRegistry
- 导出 BaseRegistry 基类供外部使用
- 统一双语注释格式

* refactor(editor-core): 代码优雅性优化

CommandManager:
- 提取 tryMergeWithLast() 和 pushToUndoStack() 消除重复代码
- 统一双语注释格式

FileActionRegistry:
- 提取 normalizeExtension() 消除扩展名规范化重复
- 统一私有属性命名风格(_前缀)
- 使用 createRegistryToken 统一 Token 创建

BaseRegistry:
- 添加 IOrdered 接口
- 添加 sortByOrder() 排序辅助方法

EntityCreationRegistry:
- 使用 sortByOrder() 简化排序逻辑

* refactor(editor-core): 统一日志系统 & 代码规范优化

- GizmoRegistry: 使用 createLogger 替代 console.warn
- VirtualNodeRegistry: 使用 createLogger 替代 console.warn
- WindowRegistry: 使用 logger、添加 _ 前缀、导出 IWindowRegistry token
- EditorViewportService: 使用 createLogger 替代 console.warn
- ComponentActionRegistry: 使用 logger、添加 _ 前缀、返回值改进
- SettingsRegistry: 使用 logger、提取 ensureCategory/ensureSection 方法
- 添加 WindowRegistry 到主导出

* refactor(editor-core): ModuleRegistry 使用 logger 替代 console

* refactor(editor-core): SerializerRegistry/UIRegistry 添加 token 和 _ 前缀

* refactor(editor-core): UIRegistry 代码优雅性 & Token 命名统一

- UIRegistry: 提取 _sortByOrder 消除 6 处重复排序逻辑
- UIRegistry: 添加分节注释和双语文档
- FieldEditorRegistry: Token 重命名为 FieldEditorRegistryToken
- PropertyRendererRegistry: Token 重命名为 PropertyRendererRegistryToken

* refactor(core): 统一日志系统 - console 替换为 logger

- ComponentSerializer: 使用 logger 替代 console.warn
- ComponentRegistry: console.warn → logger.warn (已有 logger)
- SceneSerializer: 添加 logger,替换 console.warn/error
- SystemScheduler: 添加 logger,替换 console.warn
- VersionMigration: 添加 logger,替换所有 console.warn
- RuntimeModeService: console.error → logger.error
- Core.ts: _logger 改为 readonly,双语错误消息
- SceneSerializer 修复:使用 getComponentTypeName 替代 constructor.name

* fix(core): 修复 constructor.name 压缩后失效问题

- Scene.ts: 使用 system.systemName 替代 system.constructor.name
- CommandBuffer.ts: 使用 getComponentTypeName() 替代 constructor.name

* refactor(editor-core): 代码规范优化 - 私有方法命名 & 日志统一

- BuildService: console → logger
- FileActionRegistry: 添加 logger, 私有方法 _ 前缀
- SettingsRegistry: 私有方法 _ 前缀 (ensureCategory → _ensureCategory)

* refactor(core): Scene.ts 私有变量命名规范化

- logger → _logger (遵循私有变量 _ 前缀规范)

* refactor(editor-core): 服务类私有成员命名规范化

- CommandManager: 私有变量/方法添加 _ 前缀
  - undoStack/redoStack/config/isExecuting
  - tryMergeWithLast/pushToUndoStack
- LocaleService: 私有变量/方法添加 _ 前缀
  - currentLocale/translations/changeListeners
  - deepMerge/getNestedValue/loadSavedLocale/saveLocale

* refactor(core): 私有成员命名规范化 & 单例模式优化

- Component.ts: _idGenerator 私有静态变量规范化
- PlatformManager.ts: _instance, _adapter, _logger 规范化
- AutoProfiler.ts: _instance, _config 及所有私有方法规范化
- ProfilerSDK.ts: _instance, _config 及所有私有方法规范化
- ComponentPoolManager: _instance, _pools, _usageTracker 规范化
- GlobalEventBus: _instance 规范化
- 添加中英双语 JSDoc 注释

* refactor(editor-app,behavior-tree-editor): 私有成员 & 单例模式命名规范化

editor-app:
- EngineService: private static instance → _instance
- EditorEngineSync: 所有私有成员添加 _ 前缀
- RuntimeResolver: 所有私有成员和方法添加 _ 前缀
- SettingsService: 所有私有成员和方法添加 _ 前缀

behavior-tree-editor:
- GlobalBlackboardService: 所有私有成员和方法添加 _ 前缀
- NotificationService: private static instance → _instance
- NodeRegistryService: 所有私有成员和方法添加 _ 前缀
- TreeStateAdapter: private static instance → _instance

* fix(editor-runtime): 添加 editor-core 到 external 避免传递依赖问题

将 @esengine/editor-core 添加到 vite external 配置,
避免 editor-core → runtime-core → ecs-engine-bindgen 的传递依赖
被错误地打包进 editor-runtime.js,导致 CI 构建失败。

* fix(core): 修复空接口 lint 错误

将 IByteDanceMiniGameAPI、IAlipayMiniGameAPI、IBaiduMiniGameAPI 从空接口改为类型别名,修复 no-empty-object-type 规则报错
This commit is contained in:
YHH
2025-12-24 20:57:08 +08:00
committed by GitHub
parent 58f70a5783
commit dbc6793dc4
133 changed files with 6880 additions and 9141 deletions

View File

@@ -0,0 +1,301 @@
/**
* @zh 通用注册表基类
* @en Generic Registry Base Class
*
* @zh 提供注册表的通用实现,消除 16+ 个 Registry 类中的重复代码。
* @en Provides common registry implementation, eliminating duplicate code in 16+ Registry classes.
*
* @example
* ```typescript
* interface IMyItem { id: string; name: string; }
*
* class MyRegistry extends BaseRegistry<IMyItem> {
* constructor() {
* super('MyRegistry');
* }
*
* protected getItemId(item: IMyItem): string {
* return item.id;
* }
* }
* ```
*/
import { IService, createLogger, type ILogger } from '@esengine/ecs-framework';
/**
* @zh 可注册项的基础接口
* @en Base interface for registrable items
*/
export interface IRegistrable {
/** @zh 唯一标识符 @en Unique identifier */
readonly id?: string;
}
/**
* @zh 带优先级的可注册项
* @en Registrable item with priority
*/
export interface IPrioritized {
/** @zh 优先级(越高越先匹配) @en Priority (higher = matched first) */
readonly priority?: number;
}
/**
* @zh 带顺序的可注册项
* @en Registrable item with order
*/
export interface IOrdered {
/** @zh 排序权重(越小越靠前) @en Sort order (lower = first) */
readonly order?: number;
}
/**
* @zh 注册表配置
* @en Registry configuration
*/
export interface RegistryOptions {
/** @zh 是否允许覆盖已存在的项 @en Allow overwriting existing items */
allowOverwrite?: boolean;
/** @zh 是否在覆盖时发出警告 @en Warn when overwriting */
warnOnOverwrite?: boolean;
}
/**
* @zh 通用注册表基类
* @en Generic Registry Base Class
*
* @typeParam T - @zh 注册项类型 @en Registered item type
* @typeParam K - @zh 键类型(默认 string @en Key type (default string)
*/
export abstract class BaseRegistry<T, K extends string = string> implements IService {
protected readonly _items: Map<K, T> = new Map();
protected readonly _logger: ILogger;
protected readonly _options: Required<RegistryOptions>;
constructor(
protected readonly _name: string,
options: RegistryOptions = {}
) {
this._logger = createLogger(_name);
this._options = {
allowOverwrite: options.allowOverwrite ?? true,
warnOnOverwrite: options.warnOnOverwrite ?? true
};
}
/**
* @zh 获取项的键
* @en Get item key
*/
protected abstract getItemKey(item: T): K;
/**
* @zh 获取项的显示名称(用于日志)
* @en Get item display name (for logging)
*/
protected getItemDisplayName(item: T): string {
const key = this.getItemKey(item);
return String(key);
}
// ========== 核心 CRUD 操作 | Core CRUD Operations ==========
/**
* @zh 注册项
* @en Register item
*/
register(item: T): boolean {
const key = this.getItemKey(item);
const displayName = this.getItemDisplayName(item);
if (this._items.has(key)) {
if (this._options.warnOnOverwrite) {
this._logger.warn(`Overwriting: ${displayName}`);
}
if (!this._options.allowOverwrite) {
return false;
}
}
this._items.set(key, item);
this._logger.debug(`Registered: ${displayName}`);
return true;
}
/**
* @zh 批量注册
* @en Register multiple items
*/
registerMany(items: T[]): number {
let count = 0;
for (const item of items) {
if (this.register(item)) count++;
}
return count;
}
/**
* @zh 注销项
* @en Unregister item
*/
unregister(key: K): boolean {
if (this._items.delete(key)) {
this._logger.debug(`Unregistered: ${key}`);
return true;
}
return false;
}
/**
* @zh 获取项
* @en Get item
*/
get(key: K): T | undefined {
return this._items.get(key);
}
/**
* @zh 检查是否存在
* @en Check if exists
*/
has(key: K): boolean {
return this._items.has(key);
}
// ========== 查询操作 | Query Operations ==========
/**
* @zh 获取所有项
* @en Get all items
*/
getAll(): T[] {
return Array.from(this._items.values());
}
/**
* @zh 获取所有键
* @en Get all keys
*/
getAllKeys(): K[] {
return Array.from(this._items.keys());
}
/**
* @zh 获取项数量
* @en Get item count
*/
get size(): number {
return this._items.size;
}
/**
* @zh 是否为空
* @en Is empty
*/
get isEmpty(): boolean {
return this._items.size === 0;
}
/**
* @zh 按条件过滤
* @en Filter by predicate
*/
filter(predicate: (item: T, key: K) => boolean): T[] {
const result: T[] = [];
for (const [key, item] of this._items) {
if (predicate(item, key)) {
result.push(item);
}
}
return result;
}
/**
* @zh 查找第一个匹配项
* @en Find first matching item
*/
find(predicate: (item: T, key: K) => boolean): T | undefined {
for (const [key, item] of this._items) {
if (predicate(item, key)) {
return item;
}
}
return undefined;
}
// ========== 排序操作 | Sorting Operations ==========
/**
* @zh 按 order 字段排序(越小越靠前)
* @en Sort items by order field (lower = first)
*/
protected sortByOrder<U extends IOrdered>(items: U[], defaultOrder = 0): U[] {
return items.sort((a, b) => (a.order ?? defaultOrder) - (b.order ?? defaultOrder));
}
// ========== 生命周期 | Lifecycle ==========
/**
* @zh 清空注册表
* @en Clear registry
*/
clear(): void {
this._items.clear();
this._logger.debug('Cleared');
}
/**
* @zh 释放资源
* @en Dispose resources
*/
dispose(): void {
this.clear();
this._logger.debug('Disposed');
}
}
/**
* @zh 带优先级查找的注册表基类
* @en Registry base class with priority-based lookup
*
* @zh 适用于需要按优先级匹配的场景(如 Inspector、FieldEditor
* @en For scenarios requiring priority-based matching (e.g., Inspector, FieldEditor)
*/
export abstract class PrioritizedRegistry<T extends IPrioritized, K extends string = string>
extends BaseRegistry<T, K> {
/**
* @zh 按优先级排序获取所有项
* @en Get all items sorted by priority
*/
getAllSorted(): T[] {
return this.getAll().sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
}
/**
* @zh 查找第一个能处理目标的项
* @en Find first item that can handle the target
*
* @param canHandle - @zh 判断函数 @en Predicate function
*/
findByPriority(canHandle: (item: T) => boolean): T | undefined {
for (const item of this.getAllSorted()) {
if (canHandle(item)) {
return item;
}
}
return undefined;
}
}
/**
* @zh 创建注册表服务标识符
* @en Create registry service identifier
*
* @zh 使用 Symbol.for 确保跨包共享同一个 Symbol
* @en Uses Symbol.for to ensure same Symbol is shared across packages
*/
export function createRegistryToken<T>(name: string): symbol {
return Symbol.for(`IRegistry:${name}`);
}