(() => { // 注入样式 const style = document.createElement('style'); style.textContent = ` .tree-select-menu { max-height: 500px; overflow-y: auto; min-width: 250px; font-family: Arial, sans-serif; font-size: 12px; user-select: none; border: 1px solid #dee2e6; padding-left: 4px; } .tree-node { cursor: default; padding: 4px 8px; display: block; white-space: nowrap; position: relative; text-align: left; } .tree-node::before { content: ''; position: absolute; top: 0; left: 0px; bottom: 0; width: 1px; border-left: 1px dashed #ccc; } .tree-node:not(.leaf) [data-level="0"] >.tree-label { font-weight: bold; } .tree-node[data-level="0"]::before, .tree-node[data-level="0"]::after { display: none !important; } .tree-node::after { content: ''; position: absolute; top: 14px; left: 0px; width: 10px; height: 1px; background-color: #ccc; } .tree-node:last-child::before { height: 14px; } .tree-node.leaf { cursor: pointer; color: #007bff; background-color: #fff; } .tree-node.leaf:hover { background-color: #e9ecef; } .tree-label { display: inline-block; vertical-align: middle; } .tree-toggle { display: inline-block; width: 14px; text-align: center; margin-right: 6px; user-select: none; font-size: 12px; vertical-align: middle; } .tree-children { display: none; margin-left: 18px; padding-left: 8px; } .tree-expanded > .tree-children { display: block; } .tree-select button { color: #495057; border: 1px solid #ced4da; padding: .25rem .5rem; } .tree-select button:active { color: #6c757d !important; border: 1px solid #ced4da; background-color: #fff !important; } #tree-container .show>.btn-outline-secondary.dropdown-toggle { color: #6c757d !important; border: 1px solid #80bdff; background-color: #fff !important; box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25); } #tree-container .show>.btn-outline-secondary.dropdown-toggle:focus { border-color: #80bdff; box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25); } .tree-select .btn-outline-secondary:hover { color: #6c757d; border: 1px solid #ced4da; background-color: #fff; } .tree-select .btn-outline-secondary:focus { border-color: #80bdff; box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25); } `; document.head.appendChild(style); class TreeSelect { constructor({ element, data, selected, onSelect }) { this.container = typeof element === 'string' ? document.querySelector(element) : element; this.onSelect = onSelect; this.selectedId = selected; this.data = this.buildTree(data); this.selectedNode = this.findNodeById(this.data, this.selectedId); this.render(); } // ✅ flat → tree 转换函数 buildTree(data, parentId = '-1') { // 找出所有属于 parentId 的节点 const children = data .filter(item => item.tree_pid === parentId) .sort((a, b) => a.tree_order - b.tree_order); // ✅ 按 tree_order 升序排序 return children.map(item => { const nodeChildren = this.buildTree(data, item.id); return { id: item.id, label: item.name, selected: item.id === this.selectedId, children: nodeChildren.length ? nodeChildren : undefined }; }); } findNodeById(nodes, id) { for (const node of nodes) { if (node.id === id) return node; if (node.children) { const found = this.findNodeById(node.children, id); if (found) return found; } } return null; } render() { this.container.innerHTML = `