提交代码

This commit is contained in:
yuding
2026-03-16 16:13:36 +08:00
parent 507112fcf9
commit dd4600bb5b
35 changed files with 31811 additions and 9696 deletions

View File

@@ -1,7 +1,6 @@
import { BaseManager } from '../core/base-manager';
import { ManagerRegistry } from '../core/manager-registry';
import { BimCollapse } from '../components/collapse/index';
import { BimTab } from '../components/tab';
import { t } from '../services/locale';
export class ComponentDetailManager extends BaseManager {
@@ -10,7 +9,6 @@ export class ComponentDetailManager extends BaseManager {
private currentSelection: { url: string; id: string } | null = null;
private unsubscribeSelected: (() => void) | null = null;
private unsubscribeDeselected: (() => void) | null = null;
private tabInstance: BimTab | null = null;
private propertiesData: any = null;
constructor(registry: ManagerRegistry) {
@@ -98,34 +96,11 @@ export class ComponentDetailManager extends BaseManager {
private renderTabbedContent(): void {
if (!this.dialog) return;
if (this.tabInstance) {
this.tabInstance.destroy();
this.tabInstance = null;
}
const container = document.createElement('div');
container.style.cssText = 'height:100%;display:flex;flex-direction:column;';
const propertiesPanel = this.createPropertiesPanel();
const materialsPanel = this.createMaterialsPanel();
this.tabInstance = new BimTab({
container,
activeId: 'properties',
tabs: [
{
id: 'properties',
title: 'panel.property.tab.props',
content: propertiesPanel
},
{
id: 'materials',
title: 'panel.property.tab.material',
content: materialsPanel
}
]
});
this.tabInstance.init();
container.appendChild(propertiesPanel);
this.dialog.setContent(container);
}
@@ -135,13 +110,14 @@ export class ComponentDetailManager extends BaseManager {
container.style.cssText = 'height:100%;overflow-y:auto;';
const properties = this.propertiesData?.properties || [];
const reversedProperties = [...properties].reverse();
if (properties.length === 0) {
if (reversedProperties.length === 0) {
container.innerHTML = '<div style="padding:20px;text-align:center;color:var(--bim-text-secondary,#999);">无属性数据</div>';
return container;
}
const collapseItems = properties.map((category: any, index: number) => ({
const collapseItems = reversedProperties.map((category: any, index: number) => ({
id: `category-${index}`,
title: category.name || `分类 ${index + 1}`,
content: this.createCategoryContent(category.children || [])
@@ -169,45 +145,6 @@ export class ComponentDetailManager extends BaseManager {
return container;
}
private createMaterialsPanel(): HTMLElement {
const container = document.createElement('div');
container.style.cssText = 'height:100%;overflow-y:auto;';
const materials = this.propertiesData?.materials || [];
if (materials.length === 0) {
container.innerHTML = '<div style="padding:20px;text-align:center;color:var(--bim-text-secondary,#999);">无材质数据</div>';
return container;
}
const collapseItems = materials.map((material: any, index: number) => ({
id: `material-${index}`,
title: material.name || `材质 ${index + 1}`,
content: this.createCategoryContent(material.children || material.properties || [])
}));
new BimCollapse({
container,
accordion: false,
ghost: true,
activeIds: collapseItems.length > 0 ? [collapseItems[0].id] : [],
items: collapseItems
});
const style = document.createElement('style');
style.textContent = `
#${this.dialogId} .bim-collapse-header {
background-color: var(--bim-component-bg-hover) !important;
}
#${this.dialogId} .bim-collapse-header:hover {
background-color: var(--bim-component-bg-active) !important;
}
`;
container.appendChild(style);
return container;
}
private createCategoryContent(items: any[]): HTMLElement {
const container = document.createElement('div');
@@ -256,10 +193,6 @@ export class ComponentDetailManager extends BaseManager {
}
public hide(): void {
if (this.tabInstance) {
this.tabInstance.destroy();
this.tabInstance = null;
}
if (this.dialog) {
this.dialog.destroy();
this.dialog = null;

View File

@@ -0,0 +1,133 @@
/**
* 2D 图纸引擎管理器
* 负责管理 2D 图纸渲染引擎的初始化、图纸加载和生命周期
*
* 设计原则:
* - 镜像 EngineManager 的设计模式
* - Engine2dManager 只暴露面向外部用户的公共 API
* - 内部管理器通过 getEngine2dComponent() 直接访问 Engine2d 组件
*/
import { Engine2d, type Engine2dOptions, type DrawingLoadOptions, type Drawing2dLayer } from '../components/engine-2d';
import { BaseManager } from '../core/base-manager';
import { ManagerRegistry } from '../core/manager-registry';
/**
* 2D 图纸引擎管理器
* 封装底层 2D 引擎,提供图纸加载、图层控制等公共 API
*/
export class Engine2dManager extends BaseManager {
/** 容器元素 */
private container: HTMLElement;
/** 2D 引擎组件实例 */
private engineInstance: Engine2d | null = null;
constructor(container: HTMLElement, registry: ManagerRegistry) {
super(registry);
this.container = container;
}
/**
* 获取 Engine2d 组件实例
* 内部管理器通过此方法直接访问 Engine2d 组件的全部能力
* @returns Engine2d 组件实例,未初始化时返回 null
*/
public getEngine2dComponent(): Engine2d | null {
return this.engineInstance;
}
/**
* 初始化 2D 引擎
* @param options 引擎配置选项
* @returns 是否初始化成功
*/
public initialize(options?: Omit<Engine2dOptions, 'container'>): boolean {
if (this.engineInstance && this.engineInstance.isInitialized()) {
console.warn('[Engine2dManager] 2D Engine already initialized. Destroying old instance...');
this.engineInstance.destroy();
this.engineInstance = null;
}
try {
this.engineInstance = new Engine2d({
container: this.container,
...options,
}, this.registry);
this.engineInstance.init();
return this.engineInstance.isInitialized();
} catch (error) {
console.error('[Engine2dManager] Failed to initialize 2D engine:', error);
this.engineInstance = null;
return false;
}
}
/**
* 检查引擎是否已初始化
* @returns 是否已初始化
*/
public isInitialized(): boolean {
return this.engineInstance !== null && this.engineInstance.isInitialized();
}
/**
* 加载 2D 图纸
* @param url 图纸文件 URL
* @param options 加载选项
*/
public async loadDrawing(url: string, options?: DrawingLoadOptions): Promise<void> {
if (!this.engineInstance) {
console.warn('[Engine2dManager] 2D Engine not initialized.');
return;
}
await this.engineInstance.loadDrawing(url, options);
}
/**
* 获取所有图层
* @returns 图层列表
*/
public getLayers(): Drawing2dLayer[] {
if (!this.engineInstance) {
return [];
}
return this.engineInstance.getLayers();
}
/**
* 设置图层可见性
* @param name 图层名称
* @param visible 是否可见
*/
public setLayerVisible(name: string, visible: boolean): void {
if (!this.engineInstance) {
console.warn('[Engine2dManager] 2D Engine not initialized.');
return;
}
this.engineInstance.setLayerVisible(name, visible);
}
/**
* 重置视图
*/
public resetView(): void {
this.engineInstance?.resetView();
}
/**
* 适应视图
*/
public fitToView(): void {
this.engineInstance?.fitToView();
}
/** 销毁 2D 引擎管理器 */
public destroy(): void {
if (this.engineInstance) {
this.engineInstance.destroy();
this.engineInstance = null;
}
super.destroy();
}
}

View File

@@ -0,0 +1,130 @@
/**
* 720 全景引擎管理器
* 负责管理 720° 全景渲染引擎的初始化、全景加载和生命周期
*
* 设计原则:
* - 镜像 Engine2dManager 的设计模式
* - Engine720Manager 只暴露面向外部用户的公共 API
* - 内部管理器通过 getEngine720Component() 直接访问 Engine720 组件
*/
import { Engine720, type Engine720Options, type PanoramaLoadOptions } from '../components/engine-720';
import { BaseManager } from '../core/base-manager';
import { ManagerRegistry } from '../core/manager-registry';
/**
* 720 全景引擎管理器
* 封装底层 720 引擎,提供全景加载、视角控制等公共 API
*/
export class Engine720Manager extends BaseManager {
/** 容器元素 */
private container: HTMLElement;
/** 720 引擎组件实例 */
private engineInstance: Engine720 | null = null;
constructor(container: HTMLElement, registry: ManagerRegistry) {
super(registry);
this.container = container;
}
/**
* 获取 Engine720 组件实例
* 内部管理器通过此方法直接访问 Engine720 组件的全部能力
* @returns Engine720 组件实例,未初始化时返回 null
*/
public getEngine720Component(): Engine720 | null {
return this.engineInstance;
}
/**
* 初始化 720 引擎
* @param options 引擎配置选项
* @returns 是否初始化成功
*/
public initialize(options?: Omit<Engine720Options, 'container'>): boolean {
if (this.engineInstance && this.engineInstance.isInitialized()) {
console.warn('[Engine720Manager] 720 Engine already initialized. Destroying old instance...');
this.engineInstance.destroy();
this.engineInstance = null;
}
try {
this.engineInstance = new Engine720({
container: this.container,
...options,
}, this.registry);
this.engineInstance.init();
return this.engineInstance.isInitialized();
} catch (error) {
console.error('[Engine720Manager] Failed to initialize 720 engine:', error);
this.engineInstance = null;
return false;
}
}
/**
* 检查引擎是否已初始化
* @returns 是否已初始化
*/
public isInitialized(): boolean {
return this.engineInstance !== null && this.engineInstance.isInitialized();
}
/**
* 加载全景图
* @param url 全景图片 URL
* @param options 加载选项
*/
public async loadPanorama(url: string, options?: PanoramaLoadOptions): Promise<void> {
if (!this.engineInstance) {
console.warn('[Engine720Manager] 720 Engine not initialized.');
return;
}
await this.engineInstance.loadPanorama(url, options);
}
/**
* 预加载多个全景图
* @param urls 全景图 URL 列表
*/
public async preloadPanoramas(urls: string[]): Promise<void> {
if (!this.engineInstance) {
console.warn('[Engine720Manager] 720 Engine not initialized.');
return;
}
await this.engineInstance.preloadPanoramas(urls);
}
/**
* 设置视场角
* @param fov 视场角值
*/
public setFov(fov: number): void {
this.engineInstance?.setFov(fov);
}
/**
* 获取当前视场角
* @returns 当前视场角值
*/
public getFov(): number {
return this.engineInstance?.getFov() ?? 75;
}
/**
* 重置视图
*/
public resetView(): void {
this.engineInstance?.resetView();
}
/** 销毁 720 引擎管理器 */
public destroy(): void {
if (this.engineInstance) {
this.engineInstance.destroy();
this.engineInstance = null;
}
super.destroy();
}
}

View File

@@ -70,8 +70,7 @@ export class SectionAxisDialogManager extends BaseDialogManager {
}
},
onReverse: () => {
// 反向功能:第三方引擎无 API仅输出日志
console.log('[SectionAxisDialogManager] 反向剖切(暂不支持)');
this.engineComponent?.reverseSection();
},
onAxisChange: (axis) => {
console.log('[SectionAxisDialogManager] 切换轴向:', axis);
@@ -85,13 +84,13 @@ export class SectionAxisDialogManager extends BaseDialogManager {
/** 对话框创建后的回调,自适应高度 */
protected onDialogCreated(): void {
this.dialog?.fitHeight(false);
// 检查 Engine 是否已初始化
if (!this.engineComponent) {
console.error('[SectionAxisDialogManager] Engine not initialized. Call initEngine() first.');
return;
}
// 自动激活默认轴向剖切X轴
this.engineComponent.activeSection('x');
}
@@ -104,7 +103,7 @@ export class SectionAxisDialogManager extends BaseDialogManager {
/** 销毁前的清理,销毁面板实例 */
protected onBeforeDestroy(): void {
this.engineComponent?.deactivateSection();
if (this.panel) {
this.panel.destroy();
this.panel = null;

View File

@@ -61,11 +61,6 @@ export class SectionBoxDialogManager extends BaseDialogManager {
this.engineComponent?.recoverSection();
}
},
onReverseToggle: (isReversed) => {
console.log('[SectionBoxDialogManager] 反向切换:', isReversed);
// 底层 reverse() 为“切换一次”,这里不使用 isReversed 作为入参,只要用户点击就触发。
this.engineComponent?.reverseSection();
},
onFitToModel: () => {
// 对接底层 scaleBox():缩放剖切盒到场景整体包围盒
this.engineComponent?.scaleSectionBox();

View File

@@ -28,7 +28,7 @@ export class SectionPlaneDialogManager extends BaseDialogManager {
protected get dialogHeight(): number { return 120; }
/** 初始化 */
public init(): void {}
public init(): void { }
/**
* 获取对话框位置
@@ -62,10 +62,12 @@ export class SectionPlaneDialogManager extends BaseDialogManager {
}
},
onReverse: () => {
console.log('[SectionPlaneDialogManager] 反向 (not supported in new API)');
this.engineComponent?.reverseSection();
},
onReset: () => {
console.log('[SectionPlaneDialogManager] 重置 (not supported in new API)');
// 先关闭剖切再开启
this.engineComponent?.deactivateSection();
this.engineComponent?.activeSection('face');
}
});
this.panel.init();