refactor(measure): centralize measure type config and migrate API

- Add unified MEASURE_TYPES config in types/measure.ts
- Export MEASURE_MODES_ORDERED, ENGINE_TYPE_TO_MODE, MODE_TO_ENGINE_TYPE
- Refactor measure-dialog-manager to use centralized config
- Refactor measure-panel to use MEASURE_TYPES for icons/order/valueType
- Simplify engine/index.ts measureMap with dynamic key access
- Add measure settings API (saveMeasureSetting) with cache sync
- Add direct engine event listening for measure-changed and section-move
- Update i18n keys for 8 measure modes
This commit is contained in:
yuding
2026-02-02 18:18:36 +08:00
parent 316f42ae6b
commit 044cd0e034
14 changed files with 5566 additions and 5539 deletions

View File

@@ -6,6 +6,7 @@ import { Engine, type EngineOptions, type ModelLoadOptions } from '../components
import { BaseManager } from '../core/base-manager';
import { RightKeyManager } from './right-key-manager';
import type { MeasureMode } from '../types/measure';
import type { MeasureUnit, MeasurePrecision } from '../components/measure-panel/types';
import type { SectionBoxRange } from '../components/section-box-panel/types';
import type { MenuItemConfig } from '../components/menu/item';
import { ManagerRegistry } from '../core/manager-registry';
@@ -246,7 +247,6 @@ export class EngineManager extends BaseManager {
return this.engineInstance.getCurrentMeasureType();
}
/** 清除所有测量标注 */
public clearAllMeasures(): void {
if (!this.engineInstance) {
return;
@@ -254,11 +254,13 @@ export class EngineManager extends BaseManager {
this.engineInstance.clearAllMeasures();
}
/**
* 激活剖切功能(统一入口)
* @param mode 剖切模式: 'x' | 'y' | 'z' (轴向剖切) | 'box' (剖切盒) | 'face' (拾取面剖切)
* @remarks 代理调用 Engine.activeSection(mode)
*/
public saveMeasureSetting(setting: { unit: MeasureUnit; precision: MeasurePrecision }): void {
if (!this.engineInstance) {
return;
}
this.engineInstance.saveMeasureSetting(setting);
}
public activeSection(mode: 'x' | 'y' | 'z' | 'box' | 'face'): void {
if (!this.engineInstance) {
console.warn('[EngineManager] 3D Engine not initialized.');

View File

@@ -1,40 +1,35 @@
/**
* 测量对话框管理器
* 负责管理测量工具对话框的显示、隐藏和测量面板的交互
*/
import { BaseDialogManager } from '../core/base-dialog-manager';
import { MeasurePanel } from '../components/measure-panel';
import type { MeasureConfig, MeasureMode, MeasureResult } from '../components/measure-panel/types';
import type { MeasureConfig, MeasureResult } from '../components/measure-panel/types';
import { ENGINE_TYPE_TO_MODE, MEASURE_TYPES, type MeasureMode } from '../types/measure';
interface EngineMeasureData {
id: string;
point1?: { x: number; y: number; z: number };
point2?: { x: number; y: number; z: number };
text: number;
type: string;
isSelect: boolean;
container: any;
}
/**
* 测量对话框管理器
* 继承自 BaseDialogManager提供测量工具的对话框管理功能
*/
export class MeasureDialogManager extends BaseDialogManager {
/** 测量面板实例 */
private panel: MeasurePanel | null = null;
/** 测量配置(单位、精度等) */
private config: MeasureConfig | null = null;
private unsubscribeMeasureChanged: (() => void) | null = null;
/** 对话框唯一标识 */
protected get dialogId(): string {
return 'measure-dialog';
}
/** 对话框标题(国际化 key */
protected get dialogTitle(): string {
return 'measure.dialogTitle';
}
/** 对话框宽度 */
protected get dialogWidth(): number {
return 250;
}
/**
* 创建对话框内容
* 初始化测量面板并设置回调
*/
protected createContent(): HTMLElement {
this.panel = new MeasurePanel({
defaultMode: 'distance',
@@ -52,10 +47,25 @@ export class MeasureDialogManager extends BaseDialogManager {
},
onExpandedChange: () => {
this.dialog?.fitHeight(false);
},
onConfigSave: (config) => {
console.log('[MeasureDialogManager] 保存设置:', config);
this.registry.engine3d?.saveMeasureSetting({
unit: config.unit,
precision: config.precision
});
}
});
this.panel.init();
this.config = this.panel.getConfig();
if (this.config) {
console.log('[MeasureDialogManager] 同步缓存设置到引擎:', this.config);
this.registry.engine3d?.saveMeasureSetting({
unit: this.config.unit,
precision: this.config.precision
});
}
const panelWrapper = document.createElement('div');
panelWrapper.style.padding = '12px';
@@ -64,18 +74,66 @@ export class MeasureDialogManager extends BaseDialogManager {
return panelWrapper;
}
/** 对话框创建后的回调,自适应高度 */
protected onDialogCreated(): void {
this.dialog?.fitHeight(false);
const engine = this.registry.engine3d?.getEngine();
if (engine?.events) {
const handler = (data: EngineMeasureData) => {
console.log('[MeasureDialogManager] 测量值变化:', data);
if (data && this.panel) {
this.handleMeasureChanged(data);
}
};
engine.events.on('measure-changed', handler);
this.unsubscribeMeasureChanged = () => engine.events.off('measure-changed', handler);
}
}
private handleMeasureChanged(data: EngineMeasureData): void {
if (!this.panel) return;
const targetMode = ENGINE_TYPE_TO_MODE[data.type];
if (!targetMode) {
console.warn('[MeasureDialogManager] 未知测量类型:', data.type);
return;
}
const currentMode = this.panel.getActiveMode();
if (currentMode !== targetMode) {
this.panel.switchMode(targetMode, false);
}
const result = this.convertToMeasureResult(data, targetMode);
this.panel.setResult(result);
}
private convertToMeasureResult(data: EngineMeasureData, mode: MeasureMode): MeasureResult {
const config = MEASURE_TYPES[mode];
const result: MeasureResult = {};
if (config.valueType === 'point' && data.point1) {
result.xyz = { x: data.point1.x, y: data.point1.y, z: data.point1.z };
} else {
(result as any)[config.resultField] = data.text;
}
return result;
}
/** 对话框关闭时的回调,取消工具栏按钮激活状态 */
protected onDialogClose(): void {
if (this.unsubscribeMeasureChanged) {
this.unsubscribeMeasureChanged();
this.unsubscribeMeasureChanged = null;
}
this.registry.toolbar?.setBtnActive('measure', false);
}
/** 销毁前的清理,停用测量功能并销毁面板 */
protected onBeforeDestroy(): void {
if (this.unsubscribeMeasureChanged) {
this.unsubscribeMeasureChanged();
this.unsubscribeMeasureChanged = null;
}
if (this.registry.engine3d) {
this.registry.engine3d.deactivateMeasure();
}
@@ -85,36 +143,20 @@ export class MeasureDialogManager extends BaseDialogManager {
}
}
/**
* 获取当前激活的测量模式
* @returns 当前测量模式,如 'distance'、'angle' 等
*/
public getActiveMode(): MeasureMode | null {
return this.panel ? this.panel.getActiveMode() : null;
}
/**
* 切换测量模式
* @param mode 目标测量模式
*/
public switchMode(mode: MeasureMode): void {
if (!this.panel) return;
this.panel.switchMode(mode);
}
/**
* 设置测量结果
* @param result 测量结果对象
*/
public setMeasureResult(result: MeasureResult | null): void {
if (!this.panel) return;
this.panel.setResult(result);
}
/**
* 获取测量配置
* @returns 测量配置副本
*/
public getConfig(): MeasureConfig | null {
if (this.panel) {
this.config = this.panel.getConfig();
@@ -122,11 +164,6 @@ export class MeasureDialogManager extends BaseDialogManager {
return this.config ? { ...this.config } : null;
}
/**
* 设置测量配置
* @param partial 部分配置
* @param persist 是否持久化
*/
public setConfig(partial: Partial<MeasureConfig>, persist: boolean = true): void {
if (this.panel) {
this.panel.setConfig(partial, persist);
@@ -143,13 +180,11 @@ export class MeasureDialogManager extends BaseDialogManager {
this.config = next;
}
/** 清除所有测量结果 */
public clearAll(): void {
if (!this.panel) return;
this.panel.clearAll();
}
/** 打开测量设置面板 */
public openSettings(): void {
if (!this.panel) return;
this.panel.openSettings();

View File

@@ -1,18 +1,10 @@
/**
* 剖切盒对话框管理器
* 负责管理剖切盒工具对话框的显示、隐藏和剖切盒面板的交互
*/
import { BaseDialogManager } from '../core/base-dialog-manager';
import { SectionBoxPanel } from '../components/section-box-panel';
import type { SectionBoxRange } from '../components/section-box-panel/types';
/**
* 剖切盒对话框管理器
* 继承自 BaseDialogManager提供六面体剖切盒的对话框管理功能
*/
export class SectionBoxDialogManager extends BaseDialogManager {
/** 剖切盒面板实例 */
private panel: SectionBoxPanel | null = null;
private unsubscribeSectionMove: (() => void) | null = null;
/** 对话框唯一标识 */
protected get dialogId(): string {
@@ -82,19 +74,35 @@ export class SectionBoxDialogManager extends BaseDialogManager {
return this.panel.element;
}
/** 对话框创建后的回调,激活剖切盒并自适应高度 */
protected onDialogCreated(): void {
this.registry.engine3d?.activeSection('box');
this.dialog?.fitHeight(false);
const engine = this.registry.engine3d?.getEngine();
if (engine?.events) {
const handler = (data: any) => {
if (data && this.panel) {
this.panel.setRange(data as Partial<SectionBoxRange>);
}
};
engine.events.on('section-move', handler);
this.unsubscribeSectionMove = () => engine.events.off('section-move', handler);
}
}
/** 对话框关闭时的回调,取消工具栏按钮激活状态 */
protected onDialogClose(): void {
if (this.unsubscribeSectionMove) {
this.unsubscribeSectionMove();
this.unsubscribeSectionMove = null;
}
this.registry.toolbar?.setBtnActive('section-box', false);
}
/** 销毁前的清理,停用剖切盒并销毁面板实例 */
protected onBeforeDestroy(): void {
if (this.unsubscribeSectionMove) {
this.unsubscribeSectionMove();
this.unsubscribeSectionMove = null;
}
this.registry.engine3d?.deactivateSection();
if (this.panel) {
this.panel.destroy();