refactor: 重构 Manager 架构,引入 ManagerRegistry 和 BaseManager 基类

- 新增 ManagerRegistry 单例注册表,统一管理所有 Manager 实例
- 新增 BaseManager 基类,自动管理事件订阅清理
- 新增 BaseDialogManager 基类,统一对话框生命周期管理
- 重构 15 个 Manager 使用新基类
- 重构 Toolbar 按钮和 Menu 按钮移除 engine 参数依赖
- 删除 BimComponent 基类(已不再使用)
- 为所有 Manager 和核心模块添加中文 JSDoc 注释
This commit is contained in:
yuding
2026-01-22 15:23:57 +08:00
parent f2460fb981
commit 31b60e84ce
47 changed files with 5580 additions and 5341 deletions

View File

@@ -1,114 +1,100 @@
import { BimComponent } from '../core/component';
import { BimEngine } from '../bim-engine';
import { BimDialog } from "../components/dialog";
/**
* 测量对话框管理器
* 负责管理测量工具对话框的显示、隐藏和测量面板的交互
*/
import { BaseDialogManager } from '../core/base-dialog-manager';
import { MeasurePanel } from '../components/measure-panel';
import type { MeasureConfig, MeasureMode, MeasureResult } from '../components/measure-panel/types';
/**
* 测量弹窗管理器
* 测量对话框管理器
* 继承自 BaseDialogManager提供测量工具的对话框管理功能
*/
export class MeasureDialogManager extends BimComponent {
private dialogId = 'measure-dialog';
private dialog: BimDialog | null = null;
export class MeasureDialogManager extends BaseDialogManager {
/** 测量面板实例 */
private panel: MeasurePanel | null = null;
/**
* 测量配置项(单位/精度)
* 说明MeasurePanel 会自行从缓存加载默认配置Manager 这里只做“对外读取/设置”的镜像。
*/
/** 测量配置(单位、精度等) */
private config: MeasureConfig | null = null;
constructor(engine: BimEngine) {
super(engine);
/** 对话框唯一标识 */
protected get dialogId(): string {
return 'measure-dialog';
}
public init(): void {
// 可以在这里监听事件
/** 对话框标题(国际化 key */
protected get dialogTitle(): string {
return 'measure.dialogTitle';
}
/** 对话框宽度 */
protected get dialogWidth(): number {
return 250;
}
/**
* 显示测量弹窗
* 创建对话框内容
* 初始化测量面板并设置回调
*/
public show() {
if (!this.engine.dialog || !this.engine.container) {
console.warn('Dialog manager or container is not initialized');
return;
}
const dialogWidth = 250;
const dialogHeight = 300;
const paddingRight = 20; // 你想要的右边距
const container = this.engine.container;
const containerWidth = container.clientWidth;
const containerHeight = container.clientHeight;
const x = containerWidth - dialogWidth - paddingRight;
const y = (containerHeight - dialogHeight) / 2;
// 如果已打开过,先销毁旧实例,避免重复创建/重复订阅
this.destroy();
// 创建测量面板(只做 UI不实现真实测量
protected createContent(): HTMLElement {
this.panel = new MeasurePanel({
defaultMode: 'distance', // 默认展示前四个,且默认选中"距离"
defaultMode: 'distance',
defaultExpanded: false,
onModeChange: (mode) => {
console.log('[MeasureDialogManager] 当前测量方式已切换:', mode);
this.engine.engine?.activateMeasure(mode);
this.registry.engine3d?.activateMeasure(mode);
},
onClearAll: () => {
// 预留:未来可清理引擎测量绘制/标注
console.log('[MeasureDialogManager] 删除全部(仅 UI 清空,本次不清理引擎侧内容)');
console.log('[MeasureDialogManager] 删除全部');
},
onSettings: () => {
// 预留:未来可打开设置弹窗/面板
console.log('[MeasureDialogManager] 打开设置(仅预留接口)');
console.log('[MeasureDialogManager] 打开设置');
},
onExpandedChange: () => {
// 展开/收起时,动态适配 Dialog 高度,避免遮挡底部操作按钮
this.dialog?.fitHeight(false);
}
});
this.panel.init();
// 同步一次当前配置(由组件从缓存/默认加载)
this.config = this.panel.getConfig();
// 注意:你要求“组件本身不加边距”,因此在 Manager 这里用 wrapper 增加左右内边距
// 这样 MeasurePanel 可以保持通用性,避免在不同场景复用时产生多余 padding。
const panelWrapper = document.createElement('div');
panelWrapper.style.padding = '12px';
panelWrapper.appendChild(this.panel.element);
this.dialog = this.engine.dialog.create({
id: this.dialogId,
title: 'measure.dialogTitle',
content: panelWrapper,
width: dialogWidth,
// 高度交给 fitHeight 动态计算(避免内容展开后遮挡底部操作区)
height: 'auto',
position: {
x: x,
y: y
},
onClose: () => {
this.engine.toolbar?.setBtnActive('measure', false)
this.destroy()
}
});
this.dialog.init();
return panelWrapper;
}
// 初次打开时也执行一次自适应高度(收起态)
this.dialog.fitHeight(false);
/** 对话框创建后的回调,自适应高度 */
protected onDialogCreated(): void {
this.dialog?.fitHeight(false);
}
/** 对话框关闭时的回调,取消工具栏按钮激活状态 */
protected onDialogClose(): void {
this.registry.toolbar?.setBtnActive('measure', false);
}
/** 销毁前的清理,停用测量功能并销毁面板 */
protected onBeforeDestroy(): void {
if (this.registry.engine3d) {
this.registry.engine3d.deactivateMeasure();
}
if (this.panel) {
this.panel.destroy();
this.panel = null;
}
}
/**
* 获取当前测量
* 说明:如果面板未创建,则返回 null
* 获取当前激活的测量
* @returns 当前测量模式,如 'distance'、'angle' 等
*/
public getActiveMode(): MeasureMode | null {
return this.panel ? this.panel.getActiveMode() : null;
}
/**
* 切换测量方式(你要求的“切换类型的方法”)
* @param mode 测量
* 切换测量模式
* @param mode 目标测量
*/
public switchMode(mode: MeasureMode): void {
if (!this.panel) return;
@@ -116,22 +102,17 @@ export class MeasureDialogManager extends BimComponent {
}
/**
* 设置测量结果(推荐使用的新方法名)
* 说明:内部直接调用 MeasurePanel.setResult()
* @param result 测量结果;传 null 表示清空
* 设置测量结果
* @param result 测量结果对象
*/
public setMeasureResult(result: MeasureResult | null): void {
// 按你的要求:仅当 panel 存在时才调用,不做缓存
if (!this.panel) {
return;
}
if (!this.panel) return;
this.panel.setResult(result);
}
/**
* 获取测量配置(单位/精度)
* - 如果面板存在:返回面板当前配置
* - 否则:返回 Manager 缓存的最后一次配置(可能为 null
* 获取测量配置
* @returns 测量配置副本
*/
public getConfig(): MeasureConfig | null {
if (this.panel) {
@@ -141,63 +122,35 @@ export class MeasureDialogManager extends BimComponent {
}
/**
* 设置测量配置(单位/精度)
* @param partial 部分更新
* @param persist 是否写入缓存(默认 true
* 设置测量配置
* @param partial 部分配置
* @param persist 是否持久化
*/
public setConfig(partial: Partial<MeasureConfig>, persist: boolean = true): void {
// 面板存在则直接设置面板;否则仅更新 Manager 缓存
if (this.panel) {
this.panel.setConfig(partial, persist);
this.config = this.panel.getConfig();
// 配置变化可能影响高度(比如设置面板显示/隐藏),安全起见做一次 fit
this.dialog?.fitHeight(false);
return;
}
// 面板未创建:只更新本地缓存
const prev = this.config;
const next: MeasureConfig = {
unit: partial.unit ?? prev?.unit ?? 'mm',
precision: partial.precision ?? prev?.precision ?? 2
};
this.config = next;
// 注意:缓存写入由 MeasurePanel 负责(你要求默认维护在组件里)
// 这里不写 localStorage避免重复逻辑。
}
/**
* 删除全部(仅清空 UI真实测量清理逻辑后续再接
*/
/** 清除所有测量结果 */
public clearAll(): void {
if (!this.panel) return;
this.panel.clearAll();
}
/**
* 打开设置(仅预留方法/回调)
*/
/** 打开测量设置面板 */
public openSettings(): void {
if (!this.panel) return;
this.panel.openSettings();
}
public destroy(): void {
// 停用测量功能
if (this.engine.engine) {
this.engine.engine.deactivateMeasure();
}
// 关闭弹窗
if (this.dialog) {
this.dialog.destroy();
this.dialog = null;
}
// 销毁测量面板(清理订阅与 DOM
if (this.panel) {
this.panel.destroy();
this.panel = null;
}
}
}