feat(tree,menu,docs): 对接目录树三类数据并中文化文档
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user