2026-01-22 15:23:57 +08:00
|
|
|
import type { ButtonGroupColors, ButtonConfig } from '../components/button-group/index.type';
|
|
|
|
|
import { BaseManager } from '../core/base-manager';
|
|
|
|
|
import { BimButtonGroup } from '../components/button-group';
|
|
|
|
|
import { BimTree } from '../components/tree';
|
|
|
|
|
import { TreeNodeConfig } from '../components/tree/types';
|
|
|
|
|
import { BimDialog } from '../components/dialog';
|
|
|
|
|
import { BimTab } from '../components/tab';
|
|
|
|
|
import { getIcon } from '../utils/icon-manager';
|
|
|
|
|
|
2026-01-28 17:19:36 +08:00
|
|
|
function transformTreeData(apiData: any[]): TreeNodeConfig[] {
|
|
|
|
|
if (!apiData || apiData.length === 0) return [];
|
|
|
|
|
|
|
|
|
|
return apiData.map((model, modelIndex) => {
|
|
|
|
|
const transformNode = (node: any, index: number): TreeNodeConfig => {
|
|
|
|
|
const hasChildren = node.children && node.children.length > 0;
|
|
|
|
|
return {
|
|
|
|
|
id: node.id || `node-${modelIndex}-${index}`,
|
|
|
|
|
label: node.name || node.label || '未命名',
|
2025-12-16 11:57:44 +08:00
|
|
|
expanded: false,
|
2026-01-28 17:19:36 +08:00
|
|
|
clickAction: hasChildren ? 'expand' : 'select',
|
|
|
|
|
children: hasChildren
|
|
|
|
|
? node.children.map((child: any, childIndex: number) => transformNode(child, childIndex))
|
|
|
|
|
: undefined,
|
|
|
|
|
data: node
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const hasChildren = model.children && model.children.length > 0;
|
|
|
|
|
return {
|
|
|
|
|
id: `model-${modelIndex}`,
|
|
|
|
|
label: model.name || '模型',
|
|
|
|
|
expanded: true,
|
|
|
|
|
clickAction: 'expand',
|
|
|
|
|
children: hasChildren
|
|
|
|
|
? model.children.map((child: any, childIndex: number) => transformNode(child, childIndex))
|
|
|
|
|
: undefined
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-12-16 11:57:44 +08:00
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
export class ConstructTreeManagerBtn extends BaseManager {
|
|
|
|
|
/** 按钮组实例 */
|
|
|
|
|
private toolbar: BimButtonGroup | null = null;
|
|
|
|
|
/** 按钮容器元素 */
|
2025-12-16 11:57:44 +08:00
|
|
|
private toolbarContainer: HTMLElement | null = null;
|
2026-01-22 15:23:57 +08:00
|
|
|
/** 主容器元素 */
|
2025-12-16 11:57:44 +08:00
|
|
|
private container: HTMLElement;
|
2026-01-22 15:23:57 +08:00
|
|
|
/** 构件树对话框实例 */
|
2025-12-16 11:57:44 +08:00
|
|
|
private dialog: BimDialog | null = null;
|
|
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
constructor(container: HTMLElement) {
|
|
|
|
|
super();
|
2025-12-16 11:57:44 +08:00
|
|
|
this.container = container;
|
|
|
|
|
this.init();
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
/** 初始化按钮 */
|
2025-12-16 11:57:44 +08:00
|
|
|
private init() {
|
|
|
|
|
this.toolbarContainer = document.createElement('div');
|
|
|
|
|
this.toolbarContainer.id = 'bim-construct-tree';
|
|
|
|
|
this.container.appendChild(this.toolbarContainer);
|
|
|
|
|
this.toolbar = new BimButtonGroup({
|
|
|
|
|
container: this.toolbarContainer,
|
|
|
|
|
showLabel: false,
|
|
|
|
|
direction: 'column',
|
2026-01-22 15:23:57 +08:00
|
|
|
position: 'top-left',
|
|
|
|
|
align: 'vertical',
|
|
|
|
|
expand: 'up'
|
2025-12-16 11:57:44 +08:00
|
|
|
});
|
|
|
|
|
this.toolbar.init();
|
|
|
|
|
this.toolbar.addGroup('construct-tree');
|
|
|
|
|
this.toolbar.addButton({
|
|
|
|
|
id: 'construct-tree-btn',
|
|
|
|
|
groupId: 'construct-tree',
|
|
|
|
|
type: 'button',
|
|
|
|
|
label: 'construct-tree',
|
2025-12-25 18:57:09 +08:00
|
|
|
icon: getIcon('目录树'),
|
2025-12-16 11:57:44 +08:00
|
|
|
onClick: () => {
|
2026-01-22 15:23:57 +08:00
|
|
|
this.openConstructTreeDialog();
|
2025-12-16 11:57:44 +08:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
this.toolbar.render();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public openConstructTreeDialog() {
|
2025-12-22 14:31:23 +08:00
|
|
|
this.setVisible(false);
|
|
|
|
|
|
2026-01-28 17:19:36 +08:00
|
|
|
const levelTreeData = this.registry.engine3d?.getLevelTreeData() ?? [];
|
|
|
|
|
const typeTreeData = this.registry.engine3d?.getTypeTreeData() ?? [];
|
|
|
|
|
const majorTreeData = this.registry.engine3d?.getMajorTreeData() ?? [];
|
|
|
|
|
|
|
|
|
|
console.log('[ConstructTree] 构件树数据 (Level):', levelTreeData);
|
|
|
|
|
console.log('[ConstructTree] 类型树数据 (Type):', typeTreeData);
|
|
|
|
|
console.log('[ConstructTree] 专业树数据 (Major):', majorTreeData);
|
2025-12-22 14:31:23 +08:00
|
|
|
|
2026-01-28 17:19:36 +08:00
|
|
|
const createTree = (data: any[]) => {
|
|
|
|
|
const tree = new BimTree({
|
|
|
|
|
data: transformTreeData(data),
|
|
|
|
|
checkable: true,
|
|
|
|
|
indent: 0,
|
|
|
|
|
enableSearch: true,
|
|
|
|
|
checkStrictly: true,
|
|
|
|
|
defaultExpandAll: true,
|
|
|
|
|
onNodeCheck: (node) => {
|
|
|
|
|
console.log('onNodeCheck', node);
|
|
|
|
|
},
|
|
|
|
|
onNodeSelect: (node) => {
|
|
|
|
|
console.log('onNodeSelect', node);
|
|
|
|
|
},
|
|
|
|
|
onNodeExpand: () => {
|
|
|
|
|
this.dialog?.fitWidth();
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
tree.init();
|
|
|
|
|
return tree;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const componentTree = createTree(levelTreeData);
|
|
|
|
|
const typeTree = createTree(typeTreeData);
|
|
|
|
|
const majorTree = createTree(majorTreeData);
|
2025-12-22 14:31:23 +08:00
|
|
|
|
|
|
|
|
const componentPanel = document.createElement('div');
|
|
|
|
|
componentPanel.className = 'construct-tab__panel-content';
|
2026-01-28 17:19:36 +08:00
|
|
|
componentPanel.appendChild(componentTree.element);
|
|
|
|
|
|
|
|
|
|
const typePanel = document.createElement('div');
|
|
|
|
|
typePanel.className = 'construct-tab__panel-content';
|
|
|
|
|
typePanel.appendChild(typeTree.element);
|
|
|
|
|
|
|
|
|
|
const majorPanel = document.createElement('div');
|
|
|
|
|
majorPanel.className = 'construct-tab__panel-content';
|
|
|
|
|
majorPanel.appendChild(majorTree.element);
|
2025-12-22 14:31:23 +08:00
|
|
|
|
|
|
|
|
const tabMount = document.createElement('div');
|
|
|
|
|
tabMount.className = 'construct-tab__container';
|
|
|
|
|
tabMount.style.height = '100%';
|
|
|
|
|
tabMount.style.overflow = 'hidden';
|
|
|
|
|
const tab = new BimTab({
|
|
|
|
|
container: tabMount,
|
|
|
|
|
tabs: [
|
2026-01-22 15:23:57 +08:00
|
|
|
{ id: 'component', title: 'tab.component', content: componentPanel },
|
2026-01-28 17:19:36 +08:00
|
|
|
{ id: 'type', title: 'tab.type', content: typePanel },
|
|
|
|
|
{ id: 'major', title: 'tab.major', content: majorPanel },
|
2025-12-22 14:31:23 +08:00
|
|
|
],
|
|
|
|
|
activeId: 'component',
|
|
|
|
|
onChange: () => {
|
|
|
|
|
this.dialog?.fitWidth();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
tab.init();
|
|
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
this.dialog = this.registry.dialog!.create({
|
2025-12-16 11:57:44 +08:00
|
|
|
title: 'constructTree.title',
|
2025-12-22 14:31:23 +08:00
|
|
|
minWidth: 320,
|
|
|
|
|
height: 420,
|
|
|
|
|
content: tabMount,
|
2026-01-22 15:23:57 +08:00
|
|
|
position: { x: 20, y: 20 },
|
2025-12-16 11:57:44 +08:00
|
|
|
resizable: false,
|
|
|
|
|
onClose: () => {
|
2025-12-22 14:31:23 +08:00
|
|
|
tab.destroy();
|
2026-01-28 17:19:36 +08:00
|
|
|
componentTree.destroy();
|
|
|
|
|
typeTree.destroy();
|
|
|
|
|
majorTree.destroy();
|
2025-12-22 14:31:23 +08:00
|
|
|
this.setVisible(true);
|
2025-12-16 11:57:44 +08:00
|
|
|
}
|
|
|
|
|
});
|
2025-12-22 14:31:23 +08:00
|
|
|
this.dialog?.fitWidth();
|
2025-12-16 11:57:44 +08:00
|
|
|
}
|
|
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
/** 刷新渲染 */
|
2025-12-16 11:57:44 +08:00
|
|
|
public refresh() {
|
|
|
|
|
this.toolbar?.render();
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
/** 销毁管理器 */
|
2025-12-16 11:57:44 +08:00
|
|
|
public destroy() {
|
|
|
|
|
this.toolbar?.destroy();
|
|
|
|
|
this.toolbar = null;
|
2026-01-22 15:23:57 +08:00
|
|
|
super.destroy();
|
2025-12-16 11:57:44 +08:00
|
|
|
}
|
|
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
/**
|
|
|
|
|
* 添加按钮组
|
|
|
|
|
* @param groupId 组 ID
|
|
|
|
|
* @param beforeGroupId 插入位置
|
|
|
|
|
*/
|
2025-12-16 11:57:44 +08:00
|
|
|
public addGroup(groupId: string, beforeGroupId?: string) {
|
|
|
|
|
this.toolbar?.addGroup(groupId, beforeGroupId);
|
|
|
|
|
this.toolbar?.render();
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
/**
|
|
|
|
|
* 添加按钮
|
|
|
|
|
* @param config 按钮配置
|
|
|
|
|
*/
|
2025-12-16 11:57:44 +08:00
|
|
|
public addButton(config: ButtonConfig) {
|
|
|
|
|
this.toolbar?.addButton(config);
|
|
|
|
|
this.toolbar?.render();
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
/**
|
|
|
|
|
* 设置按钮可见性
|
|
|
|
|
* @param id 按钮 ID
|
|
|
|
|
* @param v 是否可见
|
|
|
|
|
*/
|
2025-12-16 11:57:44 +08:00
|
|
|
public setButtonVisibility(id: string, v: boolean) {
|
|
|
|
|
this.toolbar?.updateButtonVisibility(id, v);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
/**
|
|
|
|
|
* 设置是否显示标签
|
|
|
|
|
* @param show 是否显示
|
|
|
|
|
*/
|
2025-12-16 11:57:44 +08:00
|
|
|
public setShowLabel(show: boolean) {
|
|
|
|
|
this.toolbar?.setShowLabel(show);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
/**
|
|
|
|
|
* 设置按钮组可见性
|
|
|
|
|
* @param visible 是否可见
|
|
|
|
|
*/
|
2025-12-16 11:57:44 +08:00
|
|
|
public setVisible(visible: boolean) {
|
|
|
|
|
if (this.toolbarContainer) {
|
|
|
|
|
this.toolbarContainer.style.visibility = visible ? 'visible' : 'hidden';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
/**
|
|
|
|
|
* 设置背景颜色
|
|
|
|
|
* @param color 颜色值
|
|
|
|
|
*/
|
2025-12-16 11:57:44 +08:00
|
|
|
public setBackgroundColor(color: string) {
|
|
|
|
|
this.toolbar?.setBackgroundColor(color);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 15:23:57 +08:00
|
|
|
/**
|
|
|
|
|
* 设置按钮组颜色
|
|
|
|
|
* @param colors 颜色配置
|
|
|
|
|
*/
|
2025-12-16 11:57:44 +08:00
|
|
|
public setColors(colors: ButtonGroupColors) {
|
|
|
|
|
this.toolbar?.setColors(colors);
|
|
|
|
|
}
|
|
|
|
|
}
|