44 lines
1.8 KiB
JavaScript
44 lines
1.8 KiB
JavaScript
function StructureTree({ items, selectedItemId, setSelectedItemId }) {
|
|
|
|
const buildTree = (parentId) => {
|
|
const children = Object.values(items)
|
|
.filter(item => item.parentId === parentId)
|
|
.sort((a,b) => a.id.localeCompare(b.id, undefined, { numeric: true }));
|
|
|
|
return children.map(item => ({
|
|
...item,
|
|
children: buildTree(item.id)
|
|
}));
|
|
};
|
|
|
|
const treeData = buildTree(null);
|
|
|
|
const renderTree = (nodes) => {
|
|
return React.createElement('ul', { className: 'space-y-1' },
|
|
nodes.map(node => {
|
|
const isRoot = node.id === '__ROOT__';
|
|
const isSelected = selectedItemId === node.id;
|
|
|
|
const nodeClasses = `tree-item ${isSelected ? 'selected' : ''} ${isRoot ? 'font-semibold' : ''}`;
|
|
const iconClasses = `lucide mr-2 w-4 h-4 ${isSelected ? 'text-blue-600' : 'text-gray-500'} ${isRoot ? 'lucide-folder-root' : 'lucide-file-text'}`;
|
|
|
|
return React.createElement('li', { key: node.id },
|
|
React.createElement('div', {
|
|
className: nodeClasses,
|
|
onClick: () => setSelectedItemId(node.id)
|
|
},
|
|
React.createElement('i', { className: iconClasses }),
|
|
React.createElement('span', {}, isRoot ? node.name : `${node.id} ${node.name}`)
|
|
),
|
|
node.children.length > 0 && React.createElement('div', { className: 'pl-6' }, renderTree(node.children))
|
|
)
|
|
})
|
|
);
|
|
};
|
|
|
|
return React.createElement('div', { className: 'workspace-panel p-4 h-full overflow-y-auto' },
|
|
React.createElement('h2', { className: 'text-lg font-semibold mb-3' }, '层级结构'),
|
|
renderTree(treeData)
|
|
);
|
|
}
|