feat(tree,menu,docs): 对接目录树三类数据并中文化文档

This commit is contained in:
yuding
2026-01-28 17:19:36 +08:00
parent 3ab9d4b0ea
commit 0b8dcd36fa
32 changed files with 4060 additions and 3302 deletions

View File

@@ -1,35 +1,56 @@
import { BaseManager } from '../core/base-manager';
import { BimCollapse } from '../components/collapse/index';
import { BimDescription } from '../components/description/index';
import { BimTab } from '../components/tab';
import { t } from '../services/locale';
export class ComponentDetailManager extends BaseManager {
private dialogId = 'component-detail-dialog';
private dialog: any = null;
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() {
super();
}
public show(modelUrl: string, componentId: string): void {
public init(): void {
this.unsubscribeSelected = this.registry.on('component:selected', (payload) => {
this.currentSelection = payload;
if (this.isOpen()) {
this.loadAndRenderContent();
}
});
this.unsubscribeDeselected = this.registry.on('component:deselected', () => {
this.currentSelection = null;
if (this.isOpen()) {
this.renderNoSelection();
}
});
}
public show(): void {
if (!this.registry.dialog) {
console.warn('[ComponentDetailManager] Dialog manager not initialized');
return;
}
if (this.isOpen()) {
this.hide();
if (!this.isOpen()) {
this.createDialog();
}
this.createDialog();
this.showLoading();
this.registry.engine3d?.getComponentProperties(modelUrl, componentId, (data) => {
this.renderProperties(data, componentId);
});
if (this.currentSelection) {
this.loadAndRenderContent();
} else {
this.renderNoSelection();
}
}
private createDialog(): void {
const width = 400;
const width = 300;
const x = document.body.clientWidth - width - 40;
this.dialog = this.registry.dialog?.create({
@@ -44,27 +65,81 @@ export class ComponentDetailManager extends BaseManager {
} as any);
}
private loadAndRenderContent(): void {
if (!this.dialog || !this.currentSelection) return;
this.showLoading();
this.registry.engine3d?.getComponentProperties(
this.currentSelection.url,
this.currentSelection.id,
(data) => {
this.propertiesData = data;
this.renderTabbedContent();
}
);
}
private showLoading(): void {
const container = document.createElement('div');
container.style.padding = '20px';
container.style.textAlign = 'center';
container.style.cssText = 'height:100%;display:flex;align-items:center;justify-content:center;';
container.textContent = '加载中...';
this.dialog?.setContent(container);
}
private renderProperties(data: any, _componentId: string): void {
private renderNoSelection(): void {
if (!this.dialog) return;
const container = document.createElement('div');
container.style.height = '100%';
container.style.overflowY = 'auto';
container.style.cssText = 'height:100%;display:flex;align-items:center;justify-content:center;color:var(--bim-text-secondary,#999);';
container.textContent = t('panel.componentDetail.noSelection') || '请先选中构件';
this.dialog.setContent(container);
}
const properties = data?.properties || [];
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();
this.dialog.setContent(container);
}
private createPropertiesPanel(): HTMLElement {
const container = document.createElement('div');
container.style.cssText = 'height:100%;overflow-y:auto;';
const properties = this.propertiesData?.properties || [];
if (properties.length === 0) {
container.innerHTML = '<div style="padding:20px;text-align:center;">无属性数据</div>';
this.dialog.setContent(container);
return;
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) => ({
@@ -76,26 +151,102 @@ export class ComponentDetailManager extends BaseManager {
new BimCollapse({
container,
accordion: false,
ghost: true,
activeIds: collapseItems.length > 0 ? [collapseItems[0].id] : [],
items: collapseItems
});
this.dialog.setContent(container);
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 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');
const descItems = items.map((item: any) => ({
label: item.name || '-',
value: String(item.value ?? '-')
}));
items.forEach((item: any, index: number) => {
const row = document.createElement('div');
row.style.cssText = `
display: flex;
border-bottom: 1px solid var(--bim-border-default, rgba(255,255,255,0.15));
`;
new BimDescription({
container,
labelWidth: '120px',
bordered: true,
items: descItems
if (index === items.length - 1) {
row.style.borderBottom = 'none';
}
const label = document.createElement('div');
label.style.cssText = `
width: 120px;
flex-shrink: 0;
color: var(--bim-text-secondary, #999);
font-size: 13px;
padding: 8px 12px;
border-right: 1px solid var(--bim-border-default, rgba(255,255,255,0.15));
`;
label.textContent = item.name || '-';
const value = document.createElement('div');
value.style.cssText = `
flex: 1;
color: var(--bim-text-primary, #fff);
font-size: 13px;
padding: 8px 12px;
word-break: break-all;
`;
value.textContent = String(item.value ?? '-');
row.appendChild(label);
row.appendChild(value);
container.appendChild(row);
});
return container;
@@ -106,6 +257,10 @@ 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;
@@ -113,6 +268,14 @@ export class ComponentDetailManager extends BaseManager {
}
public destroy(): void {
if (this.unsubscribeSelected) {
this.unsubscribeSelected();
this.unsubscribeSelected = null;
}
if (this.unsubscribeDeselected) {
this.unsubscribeDeselected();
this.unsubscribeDeselected = null;
}
this.hide();
super.destroy();
}