<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>知识图谱可视化</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/layui/2.8.12/css/layui.min.css">
    <style>
        body {
            background: #f0f2f5;
            font-family: 'Microsoft YaHei', sans-serif;
        }

        .kg-container {
            height: 100vh;
            display: flex;
            overflow: hidden;
        }

        .kg-sidebar {
            width: 350px;
            background: #fff;
            border-right: 1px solid #e6e6e6;
            display: flex;
            flex-direction: column;
            box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
            min-width: 200px;
            max-width: 600px;
        }

        .kg-sidebar-header {
            padding: 15px 20px;
            background: linear-gradient(135deg, #1E9FFF, #5FB878);
            color: white;
            font-size: 16px;
            font-weight: bold;
            text-align: center;
        }

        .kg-resizer {
            width: 5px;
            background: #e6e6e6;
            cursor: col-resize;
            position: relative;
            transition: background-color 0.2s;
        }

        .kg-resizer:hover {
            background: #1E9FFF;
        }

        .kg-main {
            flex: 1;
            padding: 15px;
            overflow-y: auto;
            background: #f0f2f5;
        }

        /* 自定义滚动条 */
        .kg-sidebar::-webkit-scrollbar,
        .kg-main::-webkit-scrollbar {
            width: 6px;
        }

        .kg-sidebar::-webkit-scrollbar-track,
        .kg-main::-webkit-scrollbar-track {
            background: #f1f1f1;
        }

        .kg-sidebar::-webkit-scrollbar-thumb,
        .kg-main::-webkit-scrollbar-thumb {
            background: #c1c1c1;
            border-radius: 3px;
        }

        .kg-sidebar::-webkit-scrollbar-thumb:hover,
        .kg-main::-webkit-scrollbar-thumb:hover {
            background: #a8a8a8;
        }
        
        /* 调整表格样式 */
        .layui-table-cell {
            height: auto;
            line-height: 28px;
        }
        
        /* 节点头部样式 */
        .node-header {
            background: linear-gradient(135deg, #1E9FFF, #5FB878);
            color: white;
            padding: 20px;
            border-radius: 6px;
            margin-bottom: 15px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .node-header-left {
            flex: 1;
        }

        .node-header-right {
            margin-left: 20px;
        }

        /* 树节点选中状态 */
        .layui-tree-entry.selected {
            background-color: #e6f7ff !important;
            border-left: 3px solid #1E9FFF;
        }

        .layui-tree-entry.selected .layui-tree-txt {
            color: #1E9FFF !important;
            font-weight: bold;
        }

        /* 工具条样式 */
        .table-toolbar {
            margin-bottom: 10px;
            padding: 10px;
            background: #fff;
            border-radius: 4px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
        }

        .column-filter {
            display: inline-block;
            margin-right: 10px;
        }

        .column-filter .layui-form-checkbox {
            margin-right: 5px;
        }

        .project-division-tree {
            width: 100%;
            overflow: auto;
            margin-top: 10px;
        }

        .project-division-table {
            width: 100%;
            border-collapse: collapse;
            table-layout: fixed;
        }

        .project-division-table tr {
            border-bottom: 1px solid #e6e6e6;
        }

        .project-division-table td {
            padding: 8px;
            vertical-align: middle;
        }

        .tree-node {
            width: 60%;
            text-align: left;
        }

        .tree-price {
            width: 20%;
            text-align: right;
        }

        .tree-indent {
            display: flex;
            align-items: center;
        }

        .tree-toggle {
            cursor: pointer;
            margin-right: 5px;
            display: inline-block;
            width: 16px;
            height: 16px;
            text-align: center;
            line-height: 16px;
        }

        .tree-row:hover {
            background-color: #f2f2f2;
        }

        .tree-children {
            width: 100%;
        }
    </style>
</head>
<body>
    <div class="kg-container">
        <!-- 左侧边栏 -->
        <div class="kg-sidebar">
            <div class="kg-sidebar-header">
                <i class="layui-icon layui-icon-tree"></i>
                知识图谱目录
            </div>
            <!-- 左侧树形菜单容器 -->
            <div id="left-tree" style="padding: 10px; overflow-y: auto; flex: 1;"></div>
        </div>

        <!-- 拖拽分隔条 -->
        <div class="kg-resizer" id="resizer"></div>

        <!-- 右侧主内容 -->
        <div class="kg-main">
            <!-- 欢迎页 -->
            <div id="welcome-container" class="layui-text" style="text-align: center; margin-top: 100px;">
                <i class="layui-icon layui-icon-tree" style="font-size: 64px; color: #d2d2d2;"></i>
                    <h2>欢迎使用知识图谱可视化系统</h2>
                    <p>点击左侧树状结构中的任意节点，查看详细信息</p>
            </div>
            
            <!-- 节点详情容器 -->
            <div id="node-details" style="display: none;">
                <!-- 节点头部信息 -->
                <div class="node-header">
                    <div class="node-header-left">
                        <h2 id="node-title"></h2>
                        <p id="node-id"></p>
                    </div>
                    <div class="node-header-right">
                        <button class="layui-btn layui-btn-normal" id="cost-preview-btn">
                            <i class="layui-icon layui-icon-rmb"></i> 费用预览
                        </button>
                        <button class="layui-btn layui-btn-normal" id="export-excel-btn" style="margin-left: 10px;">
                            <i class="layui-icon layui-icon-download-circle"></i> 导出工程Excel
                        </button>
                    </div>
                </div>
                
                <!-- 树状结构容器 -->
                <div class="layui-card">
                    <div class="layui-card-body">
                        <div id="tree-structure-container"></div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/layui/2.8.12/layui.min.js"></script>
    <script>
        layui.use(['layer', 'element', 'table', 'treeTable', 'tree', 'util', 'form'], function() {
            const layer = layui.layer;
            const element = layui.element;
            const table = layui.table;
            const treeTable = layui.treeTable;
            const tree = layui.tree;
            const util = layui.util;
            const form = layui.form;

            class KnowledgeGraphUI {
                constructor() {
                    this.selectedNodeId = null;
                    this.costPreviewData = new Map(); // 存储费用预览数据
                    this.selectedTreeNode = null; // 存储当前选中的树节点DOM
                    this.projectPropertyChildrenData = new Map(); // 存储工程属性节点的子节点数据
                    this.init();
                    this.initResizer();
                    this.initColumnConfig();
                    this.initToolbar();
                }

                // 初始化列配置
                initColumnConfig() {
                    // 不同节点类型的列配置
                    this.columnConfigs = {
                        'default': {
                            children: [
                                {field: 'title', title: '节点类型', minWidth: 200, show: true},
                                {field: 'name', title: '名称', minWidth: 150, show: true},
                                {field: 'guid', title: 'GUID', minWidth: 280, show: true},
                                {field: 'type', title: '类型', minWidth: 100, show: true}
                            ],
                            costPreview: [
                                {field: 'name', title: '费用项名称', minWidth: 200, show: true},
                                {field: 'amount', title: '数量', width: 100, show: true},
                                {field: 'unit', title: '单位', width: 80, show: true},
                                {field: 'unitPrice', title: '单价', width: 120, show: true},
                                {field: 'totalPrice', title: '合计', width: 120, show: true}
                            ]
                        },
                        'ProjectDivision': {
                            children: [
                                {field: 'title', title: '节点类型', minWidth: 200, show: true},
                                {field: 'name', title: '项目名称', minWidth: 200, show: true},
                                {field: 'guid', title: 'GUID', minWidth: 280, show: false},
                                {field: 'code', title: '项目编码', minWidth: 120, show: true},
                                {field: 'description', title: '描述', minWidth: 300, show: true}
                            ]
                        },
                        'ProjectDivisionSet': {
                            children: [
                                {field: 'name', title: '项目名称', minWidth: 300, show: true},
                                {field: 'totalPriceWithTax', title: '合价含税', width: 150, show: true},
                                {field: 'totalPriceWithoutTax', title: '合价不含税', width: 150, show: true}
                            ]
                        },
                        'Equipment': {
                            children: [
                                {field: 'title', title: '设备类型', minWidth: 150, show: true},
                                {field: 'name', title: '设备名称', minWidth: 200, show: true},
                                {field: 'model', title: '型号', minWidth: 150, show: true},
                                {field: 'specification', title: '规格', minWidth: 200, show: true},
                                {field: 'manufacturer', title: '厂家', minWidth: 150, show: true}
                            ]
                        },
                        'MaterialandmachineCostItem': {
                            costPreview: [
                                {field: 'name', title: '费用项名称', minWidth: 200, show: true},
                                {field: 'type', title: '类型', width: 100, show: true},
                                {field: 'supply', title: '供货方', width: 120, show: true},
                                {field: 'code', title: '编码', width: 120, show: true},
                                {field: 'unit', title: '单位', width: 80, show: true},
                                {field: 'amount', title: '数量', width: 100, show: true},
                                {field: 'budgetPrice', title: '预算价', width: 120, show: true},
                                {field: 'marketPrice', title: '市场价', width: 120, show: true},
                                {field: 'totalBudget', title: '预算合价', width: 120, show: true},
                                {field: 'totalMarket', title: '市场合价', width: 120, show: true},
                                {field: 'priceDiff', title: '价差', width: 120, show: true}
                            ]
                        },
                        'CostItem': {
                            costPreview: [
                                {field: 'name', title: '费用项名称', minWidth: 200, show: true},
                                {field: 'cost', title: '费用', width: 120, show: true},
                                {field: 'unique_id', title: '唯一ID', width: 280, show: false},
                                {field: 'id', title: 'ID', width: 100, show: false}
                            ]
                        }
                    };
                }

                // 初始化工具条事件
                initToolbar() {
                    // 子节点列设置
                    document.getElementById('column-filter-btn').addEventListener('click', () => {
                        this.toggleColumnFilters('children');
                    });

                    // 费用预览列设置
                    document.getElementById('cost-column-filter-btn').addEventListener('click', () => {
                        this.toggleColumnFilters('costPreview');
                    });

                    // 刷新按钮
                    document.getElementById('refresh-btn').addEventListener('click', () => {
                        if (this.selectedNodeId) {
                            this.selectNode(this.selectedNodeId, this.selectedTreeNode);
                        }
                    });

                    document.getElementById('cost-refresh-btn').addEventListener('click', () => {
                        if (this.selectedNodeId && this.costPreviewData.has(this.selectedNodeId)) {
                            this.renderCostPreviewData(this.costPreviewData.get(this.selectedNodeId));
                        }
                    });
                    
                    // 费用预览按钮
                    document.getElementById('cost-item-btn').addEventListener('click', () => {
                        if (this.selectedNodeId && this.costPreviewData.has(this.selectedNodeId)) {
                            // 更新按钮状态
                            document.getElementById('cost-item-btn').classList.add('layui-btn-disabled');
                            document.getElementById('material-machine-btn').classList.remove('layui-btn-disabled');
                            
                            // 渲染费用项数据
                            this.renderCostPreviewTable(this.costPreviewData.get(this.selectedNodeId), 'CostItem');
                        }
                    });
                    
                    // 材机列表按钮
                    document.getElementById('material-machine-btn').addEventListener('click', () => {
                        if (this.selectedNodeId && this.costPreviewData.has(this.selectedNodeId)) {
                            // 更新按钮状态
                            document.getElementById('material-machine-btn').classList.add('layui-btn-disabled');
                            document.getElementById('cost-item-btn').classList.remove('layui-btn-disabled');
                            
                            // 渲染材机列表数据
                            this.renderCostPreviewTable(this.costPreviewData.get(this.selectedNodeId), 'MaterialandmachineCostItem');
                        }
                    });
                }

                // 切换列过滤器显示
                toggleColumnFilters(type) {
                    const filterId = type === 'children' ? 'column-filters' : 'cost-column-filters';
                    const filterDiv = document.getElementById(filterId);
                    
                    if (filterDiv.style.display === 'none') {
                        this.renderColumnFilters(type);
                        filterDiv.style.display = 'block';
                    } else {
                        filterDiv.style.display = 'none';
                    }
                }

                // 渲染列过滤器
                renderColumnFilters(type) {
                    const nodeType = this.getCurrentNodeType();
                    const config = this.columnConfigs[nodeType] || this.columnConfigs['default'];
                    const columns = config[type] || [];
                    
                    const filterId = type === 'children' ? 'column-filters' : 'cost-column-filters';
                    const filterDiv = document.getElementById(filterId);
                    
                    let html = '<div class="layui-form">';
                    columns.forEach((col, index) => {
                        const checked = col.show ? 'checked' : '';
                        html += `
                            <div class="column-filter">
                                <input type="checkbox" name="col_${type}_${index}" title="${col.title}" ${checked} lay-filter="column-filter">
                            </div>
                        `;
                    });
                    html += '</div>';
                    
                    filterDiv.innerHTML = html;
                    form.render('checkbox');
                    
                    // 监听复选框变化
                    form.on('checkbox(column-filter)', (data) => {
                        const match = data.elem.name.match(/col_(\w+)_(\d+)/);
                        if (match) {
                            const tableType = match[1];
                            const colIndex = parseInt(match[2]);
                            const isChecked = data.elem.checked;
                            
                            this.updateColumnVisibility(tableType, colIndex, isChecked);
                        }
                    });
                }

                // 更新列可见性
                updateColumnVisibility(type, colIndex, isVisible) {
                    const nodeType = this.getCurrentNodeType();
                    const config = this.columnConfigs[nodeType] || this.columnConfigs['default'];
                    
                    if (config[type] && config[type][colIndex]) {
                        config[type][colIndex].show = isVisible;
                        
                        // 重新渲染表格
                        if (type === 'children') {
                            this.renderChildrenTreeTable(this.currentChildrenData || []);
                        } else if (type === 'costPreview') {
                            // 使用当前选中的节点ID获取费用数据
                            const costData = this.costPreviewData.get(this.selectedNodeId);
                            if (costData) {
                                // 检查当前显示的是哪种类型的费用数据
                                const costItemBtn = document.getElementById('cost-item-btn');
                                const materialMachineBtn = document.getElementById('material-machine-btn');
                                
                                if (costItemBtn.classList.contains('layui-btn-disabled')) {
                                    this.renderCostPreviewTable(costData, 'CostItem');
                                } else if (materialMachineBtn.classList.contains('layui-btn-disabled')) {
                                    this.renderCostPreviewTable(costData, 'MaterialandmachineCostItem');
                                } else {
                                    this.renderCostPreviewTable(costData);
                                }
                            } else {
                                this.renderCostPreviewTable(null);
                            }
                        }
                    }
                }

                // 获取当前节点类型
                getCurrentNodeType() {
                    // 检查当前选中节点的类型
                    if (this.selectedNodeId) {
                        const node = this.allNodes ? this.allNodes[this.selectedNodeId] : null;
                        if (node) {
                            // 根据节点类型返回对应的配置
                            if (node.type === 'ProjectDivisionSet' || 
                                (node.name && (node.name.includes('项目划分') || node.name.includes('工程量')))
                            ) {
                                return 'ProjectDivisionSet';
                            } else if (node.type === 'ProjectPropertySet' || 
                                (node.name && node.name === '工程属性')
                            ) {
                                return 'ProjectPropertySet';
                            } else if (node.type === 'Equipment') {
                                return 'Equipment';
                            } else if (node.type === 'ProjectDivision') {
                                return 'ProjectDivision';
                            }
                        }
                    }
                    // 默认返回default配置
                    return 'default';
                }

                async init() {
                    await this.loadTree();
                }

                // 初始化拖拽功能
                initResizer() {
                    const resizer = document.getElementById('resizer');
                    const sidebar = document.querySelector('.kg-sidebar');
                    let isResizing = false;

                    resizer.addEventListener('mousedown', (e) => {
                        isResizing = true;
                        document.addEventListener('mousemove', handleMouseMove);
                        document.addEventListener('mouseup', handleMouseUp);
                        e.preventDefault();
                    });

                    function handleMouseMove(e) {
                        if (!isResizing) return;
                        const newWidth = e.clientX;
                        if (newWidth >= 200 && newWidth <= 600) {
                            sidebar.style.width = newWidth + 'px';
                        }
                    }

                    function handleMouseUp() {
                        isResizing = false;
                        document.removeEventListener('mousemove', handleMouseMove);
                        document.removeEventListener('mouseup', handleMouseUp);
                    }
                }

                async loadTree() {
                    try {
                        // 显示加载层
                        const loadIndex = layer.load(2);
                        
                        const response = await fetch('/api/tree');
                        const data = await response.json();
                        
                        // 关闭加载层
                        layer.close(loadIndex);
                        
                        if (data.error) {
                            layer.msg('加载失败: ' + data.error, {icon: 2});
                            return;
                        }

                        // 存储所有节点数据，用于父节点查找
                        this.allNodes = data.all_nodes;
                        
                        // 预处理费用预览数据
                        this.processCostPreviewData(data.roots);

                        this.renderLayuiTree(data.roots);
                    } catch (error) {
                        layer.msg('网络错误: ' + error.message, {icon: 2});
                    }
                }

                // 预处理费用预览数据
                processCostPreviewData(nodes) {
                    nodes.forEach(node => {
                        if (node.children) {
                            // 查找费用预览节点
                            const costPreviewNode = node.children.find(child => 
                                child.name && child.name.includes('费用预览')
                            );
                            
                            if (costPreviewNode && costPreviewNode.children) {
                                // 将费用预览数据存储到当前节点
                                this.costPreviewData.set(node.id, costPreviewNode.children);
                            }
                            
                            // 递归处理子节点
                            this.processCostPreviewData(node.children);
                        }
                    });
                }

                renderLayuiTree(nodes) {
                    // 将API返回的数据转换为Layui tree组件所需的格式
                    const treeData = this.formatTreeData(nodes, 1);
                    
                    // 渲染树组件
                    tree.render({
                        elem: '#left-tree',
                        data: treeData,
                        showLine: true,
                        click: (obj) => {
                            this.selectNode(obj.data.id, obj.elem);
                        }
                    });
                }
                
                formatTreeData(nodes, level = 1) {
                    return nodes.map(node => {
                        // 检查是否是费用预览节点
                        if (node.name && node.name.includes('费用预览')) {
                            // 将费用预览数据存储到父节点
                            if (node.children) {
                                // 找到父节点ID（这里需要根据实际数据结构调整）
                                const parentId = this.findParentNodeId(node.id);
                                if (parentId) {
                                    this.costPreviewData.set(parentId, node.children);
                                }
                            }
                            return null; // 不显示费用预览节点
                        }

                        const item = {
                            title: node.name || node.label, // 只显示名称
                            id: node.id,
                            spread: level <= 3 // 自动展开到第三层级
                        };

                        // 检查是否是工程属性节点
                        const isProjectPropertyNode = node.type === 'ProjectPropertySet' || (node.name && node.name === '工程属性');
                        // 检查是否是项目划分集节点
                        const isProjectDivisionSet = node.type === 'ProjectDivisionSet' || (node.name && (node.name.includes('项目划分') || node.name.includes('工程量')));

                        if (node.children && node.children.length > 0) {
                            // 如果是工程属性节点，不在树中显示其子节点，而是存储起来
                            if (isProjectPropertyNode) {
                                // 存储工程属性节点的子节点，以便在右侧显示
                                this.projectPropertyChildrenData.set(node.id, node.children);
                                
                                // 检查是否有费用预览子节点
                                const costPreviewChild = node.children.find(child => 
                                    child.name && child.name.includes('费用预览')
                                );
                                if (costPreviewChild && costPreviewChild.children) {
                                    this.costPreviewData.set(node.id, costPreviewChild.children);
                                }
                            } else if (isProjectDivisionSet) {
                                // 对于项目划分集节点，正常处理子节点
                                const filteredChildren = this.formatTreeData(node.children, level + 1).filter(child => child !== null);
                                if (filteredChildren.length > 0) {
                                    item.children = filteredChildren;
                                }
                                
                                // 检查是否有费用预览子节点
                                const costPreviewChild = node.children.find(child => 
                                    child.name && child.name.includes('费用预览')
                                );
                                if (costPreviewChild && costPreviewChild.children) {
                                    this.costPreviewData.set(node.id, costPreviewChild.children);
                                }
                            } else {
                                // 对于非工程属性节点，正常处理子节点
                                const filteredChildren = this.formatTreeData(node.children, level + 1).filter(child => child !== null);
                                if (filteredChildren.length > 0) {
                                    item.children = filteredChildren;
                                }
                                
                                // 检查是否有费用预览子节点
                                const costPreviewChild = node.children.find(child => 
                                    child.name && child.name.includes('费用预览')
                                );
                                if (costPreviewChild && costPreviewChild.children) {
                                    this.costPreviewData.set(node.id, costPreviewChild.children);
                                }
                            }
                        }
                        
                        return item;
                    }).filter(item => item !== null);
                }

                // 查找父节点ID的辅助方法
                findParentNodeId(nodeId) {
                    // 遍历所有节点，查找包含该节点作为子节点的父节点
                    for (const [parentId, node] of Object.entries(this.allNodes || {})) {
                        if (node.children && node.children.some(child => child.id === nodeId)) {
                            return parseInt(parentId);
                        }
                    }
                    return null;
                }

                async selectNode(nodeId, elem) {
                    this.selectedNodeId = nodeId;
                    this.selectedTreeNode = elem;

                    // 更新选中状态
                    this.updateSelectedState(elem);

                    // 显示加载层
                    const loadIndex = layer.load(2);

                    try {
                        // 获取节点基本信息
                        const response = await fetch(`/api/node/${nodeId}`);
                        const data = await response.json();
                        
                        if (data.error) {
                            layer.msg('加载失败: ' + data.error, {icon: 2});
                            layer.close(loadIndex);
                            return;
                        }
                        
                        // 获取节点费用信息
                        const costResponse = await fetch(`/api/node/${nodeId}/cost`);
                        const costData = await costResponse.json();
                        
                        // 存储费用数据
                        if (!costData.error) {
                            this.costPreviewData.set(nodeId, costData);
                        }

                        // 检查是否是工程属性节点，如果是则使用已存储的子节点数据
                        const isProjectPropertyNode = 
                            data.node && data.node.labels && 
                            data.node.labels.includes('ProjectPropertySet');
                        
                        if (isProjectPropertyNode && this.projectPropertyChildrenData.has(nodeId)) {
                            // 使用预先存储的工程属性子节点数据
                            const storedChildren = this.projectPropertyChildrenData.get(nodeId);
                            // 将存储的子节点数据转换为API返回的格式
                            const formattedChildren = storedChildren.map(child => {
                                return {
                                    id: child.id,
                                    labels: [child.type],
                                    properties: {
                                        name: child.name,
                                        ...child
                                    }
                                };
                            });
                            
                            // 合并API返回的子节点和存储的子节点
                            const allChildren = [...(data.children || []), ...formattedChildren];
                            
                            // 递归获取所有子节点
                            const fullChildren = await this.getAllChildrenRecursively(allChildren);
                            
                            // 关闭加载层
                            layer.close(loadIndex);
                            
                            this.renderNodeDetails(data.node, fullChildren);
                        } else {
                            // 对于非工程属性节点，递归获取所有子节点
                            const fullChildren = await this.getAllChildrenRecursively(data.children || []);
                            
                            // 关闭加载层
                            layer.close(loadIndex);
                            
                            this.renderNodeDetails(data.node, fullChildren);
                        }
                    } catch (error) {
                        layer.close(loadIndex);
                        layer.msg('网络错误: ' + error.message, {icon: 2});
                    }
                }

                updateSelectedState(elem) {
                    // 移除所有选中状态
                    document.querySelectorAll('.layui-tree-entry.selected').forEach(entry => {
                        entry.classList.remove('selected');
                    });
                    
                    // 添加当前选中状态
                    if (elem && elem[0]) {
                        elem[0].classList.add('selected');
                    }
                }

                renderNodeDetails(node, children) {
                    // 隐藏欢迎页，显示节点详情
                    document.getElementById('welcome-container').style.display = 'none';
                    document.getElementById('node-details').style.display = 'block';
                    
                    // 设置节点标题和ID
                    document.getElementById('node-title').innerText = node.labels ? node.labels.join(', ') : '节点';
                    document.getElementById('node-id').innerHTML = `<i class="layui-icon layui-icon-key"></i> 节点ID: ${node.id}`;
                    
                    // 存储当前子节点数据
                    this.currentChildrenData = children || [];
                    
                    // 渲染树状结构
                    this.renderTreeStructure(node, this.currentChildrenData);
                    
                    // 添加费用预览按钮点击事件
                    document.getElementById('cost-preview-btn').addEventListener('click', () => {
                        this.showCostPreviewDialog(node.id);
                    });
                    
                    // 添加导出Excel按钮点击事件
                    document.getElementById('export-excel-btn').addEventListener('click', () => {
                        this.exportToExcel(node.id);
                    });
                }
                
                renderTreeStructure(node, children) {
                    // 获取表格容器
                    const container = document.getElementById('tree-structure-container');
                    
                    // 清空容器
                    container.innerHTML = '';
                    
                    // 检查是否是项目划分集节点或其子节点
                    const nodeType = this.getCurrentNodeType();
                    let isProjectDivisionSet = nodeType === 'ProjectDivisionSet';
                    
                    // 检查当前节点是否为项目划分集的子节点
                    if (!isProjectDivisionSet && this.selectedNodeId) {
                        // 尝试查找父节点
                        const parentId = this.findParentNodeId(this.selectedNodeId);
                        if (parentId) {
                            const parentNode = this.allNodes[parentId];
                            if (parentNode && (parentNode.type === 'ProjectDivisionSet' || 
                                (parentNode.name && (parentNode.name.includes('项目划分') || parentNode.name.includes('工程量'))))) {
                                isProjectDivisionSet = true;
                            }
                        }
                    }
                    
                    // 准备树表格数据
                    const treeData = this.buildTreeStructureData(node, children);
                    
                    // 创建树状表格容器
                    const treeContainer = document.createElement('div');
                    treeContainer.className = 'project-division-tree';
                    
                    // 创建表格
                    const table = document.createElement('table');
                    table.className = 'project-division-table';
                    
                    // 添加表格内容
                    const tableBody = document.createElement('tbody');
                    tableBody.innerHTML = this.buildTreeStructureHTML(treeData);
                    table.appendChild(tableBody);
                    
                    // 添加到容器
                    treeContainer.appendChild(table);
                    container.appendChild(treeContainer);
                    
                    // 添加样式
                    this.addTreeStructureStyles();
                    
                    // 添加展开/折叠事件监听
                    this.addTreeToggleListeners();
                }
                
                showCostPreviewDialog(nodeId) {
                    // 获取费用预览数据
                    const costData = this.costPreviewData.get(parseInt(nodeId));
                    
                    if (!costData) {
                        layer.msg('该节点没有费用预览数据');
                        return;
                    }
                    
                    // 创建弹窗
                    layer.open({
                        type: 1,
                        title: '费用预览',
                        area: ['800px', '600px'],
                        content: '<div class="layui-tab layui-tab-card">' +
                            '<ul class="layui-tab-title">' +
                            '<li class="layui-this">费用项</li>' +
                            '<li>材机列表</li>' +
                            '</ul>' +
                            '<div class="layui-tab-content">' +
                            '<div class="layui-tab-item layui-show">' +
                            '<div id="cost-preview-container"></div>' +
                            '</div>' +
                            '<div class="layui-tab-item">' +
                            '<div id="material-machine-container"></div>' +
                            '</div>' +
                            '</div>' +
                            '</div>',
                        success: () => {
                            // 渲染费用预览表格
                            this.renderCostPreviewTable(costData, 'CostItem', 'cost-preview-container');
                            this.renderCostPreviewTable(costData, 'MaterialandmachineCostItem', 'material-machine-container');
                            
                            // 初始化Tab
                            element.render('tab');
                        }
                    });
                }
                
                renderPropertyTable(node) {
                    const propertyData = [];
                    
                    if (node.properties && Object.keys(node.properties).length > 0) {
                        Object.entries(node.properties).forEach(([key, value]) => {
                            propertyData.push({
                                key: key,
                                value: this.formatValue(value)
                            });
                        });
                    }
                    
                    // 使用Layui表格组件渲染属性
                    table.render({
                        elem: '#property-table-container',
                        data: propertyData,
                        cols: [[
                            {field: 'key', title: '属性名', width: '30%', sort: true},
                            {field: 'value', title: '属性值', width: '70%'}
                        ]],
                        skin: 'line',
                        even: true,
                        text: {
                            none: '该节点没有属性'
                        }
                    });
                }
                
                renderChildrenTreeTable(children) {
                    // 获取当前节点类型的列配置
                    const nodeType = this.getCurrentNodeType();
                    
                    // 检查是否是项目划分集节点或其子节点
                    let isProjectDivisionSet = nodeType === 'ProjectDivisionSet';
                    
                    // 检查当前节点是否为项目划分集的子节点
                    if (!isProjectDivisionSet && this.selectedNodeId) {
                        // 尝试查找父节点
                        const parentId = this.findParentNodeId(this.selectedNodeId);
                        if (parentId) {
                            const parentNode = this.allNodes[parentId];
                            if (parentNode && (parentNode.type === 'ProjectDivisionSet' || 
                                (parentNode.name && (parentNode.name.includes('项目划分') || parentNode.name.includes('工程量'))))) {
                                isProjectDivisionSet = true;
                            }
                        }
                    }
                    
                    // 获取适用的列配置
                    const config = isProjectDivisionSet ? 
                        this.columnConfigs['ProjectDivisionSet'] : 
                        (this.columnConfigs[nodeType] || this.columnConfigs['default']);
                    
                    const columnConfig = config.children || this.columnConfigs['default'].children;
                    
                    // 获取表格容器
                    const container = document.getElementById('children-table-container');
                    
                    // 清空容器
                    container.innerHTML = '';
                    
                    // 如果是项目划分集节点或其子节点，使用自定义树状表格渲染
                    if (isProjectDivisionSet) {
                        // 准备树表格数据
                        const treeData = this.buildProjectDivisionTreeData(children);
                        
                        // 使用自定义方法渲染项目划分集树状表格
                        this.renderProjectDivisionAsTree(treeData);
                    } else {
                        // 对于非项目划分集节点，使用原有的渲染方式
                        // 准备树表格数据
                        const treeData = [];
                        
                        // 处理子节点数据
                        for (const child of children) {
                            const item = {
                                id: child.id,
                                name: child.properties ? child.properties.name : '',
                                title: child.labels ? child.labels.join(', ') : '子节点'
                            };
                            
                            // 添加属性
                            if (child.properties) {
                                // 根据配置添加属性
                                columnConfig.forEach(col => {
                                    if (child.properties[col.field]) {
                                        item[col.field] = child.properties[col.field];
                                    }
                                });
                                
                                // 添加常用属性
                                if (child.properties.name) item.name = child.properties.name;
                                if (child.properties.GUID) item.guid = child.properties.GUID;
                                if (child.properties.type) item.type = child.properties.type;
                                if (child.properties.code) item.code = child.properties.code;
                                if (child.properties.description) item.description = child.properties.description;
                                
                                // 将所有属性序列化为JSON存储，用于详情查看
                                item.allProperties = JSON.stringify(child.properties);
                            }
                            
                            treeData.push(item);
                        }
                        
                        // 构建列配置
                        const cols = [];
                        
                        // 添加可见的列
                        columnConfig.forEach(col => {
                            if (col.show) {
                                cols.push({
                                    field: col.field,
                                    title: col.title,
                                    minWidth: col.minWidth || col.width || 150,
                                    width: col.width
                                });
                            }
                        });
                        
                        // 添加操作列
                        cols.push({
                            title: '操作',
                            width: 150,
                            templet: d => {
                                return `<div class="layui-btn-group">
                                    <button class="layui-btn layui-btn-xs" lay-event="view">查看</button>
                                    <button class="layui-btn layui-btn-xs layui-btn-normal" lay-event="detail">详情</button>
                                </div>`;
                            }
                        });
                        
                        // 使用 treeTable 渲染
                        treeTable.render({
                            elem: '#children-table-container',
                            data: treeData,
                            tree: {
                                iconIndex: 0,
                                isPidData: false,
                                idName: 'id',
                                childName: 'children',
                                view: {
                                    showIcon: true,
                                    showLine: true,
                                    indent: 20,
                                    dblClickExpand: false
                                }
                            },
                            cols: [cols],
                            text: {
                                none: '该节点没有子节点'
                            },
                            page: false
                        });
                        
                        // 监听表格操作
                        treeTable.on('tool(children-table-container)', obj => {
                            const data = obj.data;
                            if (obj.event === 'view') {
                                this.selectNode(data.id);
                            } else if (obj.event === 'detail') {
                                this.showNodeDetailLayer(data);
                            }
                        });
                    }
                }

                renderProjectDivisionAsTree(treeData) {
                    const container = document.getElementById('children-table-container');
                    
                    // 创建树状表格容器
                    const treeContainer = document.createElement('div');
                    treeContainer.className = 'project-division-tree';
                    
                    // 创建表格
                    const table = document.createElement('table');
                    table.className = 'project-division-table';
                    
                    // 添加表格内容
                    const tableBody = document.createElement('tbody');
                    tableBody.innerHTML = this.buildProjectDivisionTreeHTML(treeData);
                    table.appendChild(tableBody);
                    
                    // 添加到容器
                    treeContainer.appendChild(table);
                    container.appendChild(treeContainer);
                    
                    // 添加样式
                    this.addProjectDivisionTreeStyles();
                    
                    // 添加展开/折叠事件监听
                    this.addTreeToggleListeners();
                }

                buildProjectDivisionTreeData(children) {
                    const treeData = [];
                    
                    // 处理子节点数据
                    for (const child of children) {
                        const item = {
                            id: child.id,
                            children: []
                        };
                        
                        // 添加属性
                        if (child.properties) {
                            // 添加标准属性
                            item.mark = child.properties.mark || '';
                            item.code = child.properties.code || '';
                            item.name = child.properties.name || '';
                            item.specification = child.properties.specification || child.properties.规格型号 || '';
                            item.unit = child.properties.unit || child.properties.单位 || '';
                            item.formula = child.properties.formula || child.properties.计算式 || '';
                            item.amount = child.properties.amount || child.properties.数量 || '';
                            item.unitPriceWithTax = child.properties.unitPriceWithTax || child.properties.单价含税 || '';
                            item.unitPriceWithoutTax = child.properties.unitPriceWithoutTax || child.properties.单价不含税 || '';
                            item.totalPriceWithTax = child.properties.totalPriceWithTax || child.properties.合价含税 || '';
                            item.totalPriceWithoutTax = child.properties.totalPriceWithoutTax || child.properties.合价不含税 || '';
                            item.taxIndex = child.properties.taxIndex || child.properties.取费索引 || '';
                            item.remark = child.properties.remark || child.properties.备注 || '';
                            
                            // 将所有属性序列化为JSON存储，用于详情查看
                            item.allProperties = JSON.stringify(child.properties);
                        }
                        
                        // 处理子节点
                        if (child.children && child.children.length > 0) {
                            item.children = this.buildProjectDivisionTreeData(child.children);
                        }
                        
                        treeData.push(item);
                    }
                    
                    return treeData;
                }

                buildProjectDivisionTreeHTML(treeData, level = 0) {
                    let html = '';
                    
                    // 添加表头行
                    if (level === 0) {
                        html += `<tr class="tree-header">
                            <th class="tree-col-name">项目名称</th>
                            <th class="tree-col-spec">规格型号</th>
                            <th class="tree-col-unit">单位</th>
                            <th class="tree-col-formula">计算式</th>
                            <th class="tree-col-amount">数量</th>
                            <th class="tree-col-price">单价含税</th>
                            <th class="tree-col-price">单价不含税</th>
                            <th class="tree-col-total">合价含税</th>
                            <th class="tree-col-total">合价不含税</th>
                            <th class="tree-col-tax">取费表</th>
                            <th class="tree-col-remark">备注</th>
                        </tr>`;
                    }
                    
                    // 生成行数据
                    treeData.forEach((item, index) => {
                        const hasChildren = item.children && item.children.length > 0;
                        const toggleClass = hasChildren ? 'tree-toggle' : '';
                        const toggleIcon = hasChildren ? '<i class="layui-icon layui-icon-triangle-d"></i>' : '<i class="layui-icon layui-icon-file"></i>';
                        const nodeClass = hasChildren ? 'parent-node' : 'leaf-node';
                        
                        // 创建行
                        html += `<tr class="tree-row ${nodeClass}" data-id="${item.id}" data-level="${level}">`;
                        
                        // 项目名称列（带缩进和图标）
                        html += `<td class="tree-col-name">
                            <div class="tree-indent" style="padding-left: ${level * 20}px">
                                <span class="${toggleClass}">${toggleIcon}</span>
                                <span class="node-code">${item.code ? item.code : ''}</span>
                                <span class="node-name">${item.name || '未命名项目'}</span>
                            </div>
                        </td>`;
                        
                        // 规格型号列
                        html += `<td class="tree-col-spec">${item.specification || ''}</td>`;
                        
                        // 单位列
                        html += `<td class="tree-col-unit">${item.unit || ''}</td>`;
                        
                        // 计算式列
                        html += `<td class="tree-col-formula">${item.formula || ''}</td>`;
                        
                        // 数量列
                        html += `<td class="tree-col-amount">${item.amount || ''}</td>`;
                        
                        // 单价含税列
                        html += `<td class="tree-col-price">${item.unitPriceWithTax || ''}</td>`;
                        
                        // 单价不含税列
                        html += `<td class="tree-col-price">${item.unitPriceWithoutTax || ''}</td>`;
                        
                        // 合价含税列
                        html += `<td class="tree-col-total">${item.totalPriceWithTax || ''}</td>`;
                        
                        // 合价不含税列
                        html += `<td class="tree-col-total">${item.totalPriceWithoutTax || ''}</td>`;
                        
                        // 取费表列
                        html += `<td class="tree-col-tax">${item.taxIndex || ''}</td>`;
                        
                        // 备注列
                        html += `<td class="tree-col-remark">${item.remark || ''}</td>`;
                        
                        html += '</tr>';
                        
                        // 递归处理子节点
                        if (hasChildren) {
                            html += this.buildProjectDivisionTreeHTML(item.children, level + 1);
                        }
                    });
                    
                    return html;
                }

                addTreeToggleListeners() {
                    // 为所有可展开/折叠的节点添加点击事件
                    document.querySelectorAll('.tree-toggle').forEach(toggle => {
                        toggle.addEventListener('click', (e) => {
                            const icon = e.currentTarget.querySelector('i');
                            const row = e.currentTarget.closest('tr');
                            const level = parseInt(row.dataset.level);
                            const nodeId = row.dataset.id;
                            
                            // 找到所有下一级节点
                            let nextRow = row.nextElementSibling;
                            let childrenVisible = icon.classList.contains('layui-icon-triangle-d');
                            
                            while (nextRow && parseInt(nextRow.dataset.level) > level) {
                                if (parseInt(nextRow.dataset.level) === level + 1) {
                                    // 直接子节点的显示/隐藏状态切换
                                    if (childrenVisible) {
                                        nextRow.style.display = 'none';
                                        
                                        // 同时隐藏所有子节点的子节点
                                        let childRow = nextRow.nextElementSibling;
                                        while (childRow && parseInt(childRow.dataset.level) > level + 1) {
                                            childRow.style.display = 'none';
                                            childRow = childRow.nextElementSibling;
                                        }
                                    } else {
                                        nextRow.style.display = '';
                                    }
                                }
                                nextRow = nextRow.nextElementSibling;
                            }
                            
                            // 切换图标
                            if (childrenVisible) {
                                icon.classList.remove('layui-icon-triangle-d');
                                icon.classList.add('layui-icon-triangle-r');
                            } else {
                                icon.classList.remove('layui-icon-triangle-r');
                                icon.classList.add('layui-icon-triangle-d');
                            }
                            
                            e.stopPropagation();
                        });
                    });
                    
                    // 为行添加点击事件，显示详细信息
                    document.querySelectorAll('.tree-row').forEach(row => {
                        row.addEventListener('click', (e) => {
                            if (!e.target.closest('.tree-toggle')) {
                                const nodeId = row.dataset.id;
                                if (nodeId) {
                                    this.selectNode(nodeId);
                                }
                            }
                        });
                    });
                }

                addProjectDivisionTreeStyles() {
                    // 检查是否已经添加了样式
                    if (!document.getElementById('project-division-tree-styles')) {
                        const style = document.createElement('style');
                        style.id = 'project-division-tree-styles';
                        style.textContent = `
                            .project-division-tree {
                                width: 100%;
                                overflow: auto;
                                margin-top: 10px;
                            }
                            
                            .project-division-table {
                                width: 100%;
                                border-collapse: collapse;
                                table-layout: fixed;
                            }
                            
                            .project-division-table tr {
                                border-bottom: 1px solid #e6e6e6;
                                height: 40px;
                            }
                            
                            .project-division-table td {
                                padding: 8px;
                                vertical-align: middle;
                            }
                            
                            .tree-node {
                                width: 70%;
                                text-align: left;
                            }
                            
                            .tree-price {
                                width: 30%;
                                text-align: right;
                            }
                            
                            .price-item {
                                color: #666;
                                font-size: 13px;
                                margin-bottom: 3px;
                            }
                            
                            .tree-indent {
                                display: flex;
                                align-items: center;
                                position: relative;
                            }
                            
                            .tree-toggle {
                                cursor: pointer;
                                margin-right: 8px;
                                display: inline-block;
                                width: 16px;
                                height: 16px;
                                text-align: center;
                                line-height: 16px;
                            }
                            
                            .node-code {
                                color: #999;
                                font-size: 12px;
                                margin-right: 5px;
                            }
                            
                            .node-name {
                                font-weight: normal;
                                margin-right: 10px;
                            }
                            
                            .parent-node .node-name {
                                font-weight: bold;
                                color: #1E9FFF;
                            }
                            
                            .tree-row:hover {
                                background-color: #f2f2f2;
                            }
                            
                            /* 树状连接线样式 */
                            .tree-row .tree-indent {
                                position: relative;
                            }
                            
                            .tree-row[data-level="1"] .tree-indent:before,
                            .tree-row[data-level="2"] .tree-indent:before,
                            .tree-row[data-level="3"] .tree-indent:before,
                            .tree-row[data-level="4"] .tree-indent:before,
                            .tree-row[data-level="5"] .tree-indent:before {
                                content: '';
                                position: absolute;
                                left: 7px;
                                top: -8px;
                                height: calc(100% + 16px);
                                border-left: 1px dotted #ccc;
                            }
                            
                            .tree-row[data-level="1"] .tree-indent:after,
                            .tree-row[data-level="2"] .tree-indent:after,
                            .tree-row[data-level="3"] .tree-indent:after,
                            .tree-row[data-level="4"] .tree-indent:after,
                            .tree-row[data-level="5"] .tree-indent:after {
                                content: '';
                                position: absolute;
                                left: 7px;
                                top: 50%;
                                width: 12px;
                                border-top: 1px dotted #ccc;
                            }
                            
                            /* 颜色标记 */
                            .leaf-node .layui-icon-file {
                                color: #5FB878;
                            }
                            
                            .parent-node .layui-icon-triangle-d,
                            .parent-node .layui-icon-triangle-r {
                                color: #1E9FFF;
                            }
                        `;
                        document.head.appendChild(style);
                    }
                }

                // 导出Excel方法
                exportToExcel(nodeId) {
                    // 显示加载层
                    const loadIndex = layer.load(2, {shade: [0.3, '#fff']});
                    
                    // 请求导出API（传入任意节点ID，后端会忽略）
                    fetch(`/api/export/${nodeId}`)
                        .then(response => {
                            if (!response.ok) {
                                throw new Error('导出失败');
                            }
                            return response.blob();
                        })
                        .then(blob => {
                            // 创建下载链接
                            const url = window.URL.createObjectURL(blob);
                            const a = document.createElement('a');
                            a.href = url;
                            a.download = '工程知识图谱.xlsx';
                            document.body.appendChild(a);
                            a.click();
                            window.URL.revokeObjectURL(url);
                            
                            // 关闭加载层
                            layer.close(loadIndex);
                            layer.msg('导出成功', {icon: 1});
                        })
                        .catch(error => {
                            // 关闭加载层
                            layer.close(loadIndex);
                            layer.msg('导出失败: ' + error.message, {icon: 2});
                        });
                }

                renderRelationTable(relationships) {
                    table.render({
                        elem: '#relation-table-container',
                        data: relationships || [],
                        cols: [[
                            {type: 'numbers', title: '序号', width: 60},
                            {field: 'type', title: '关系类型', minWidth: 150},
                            {field: 'direction', title: '方向', width: 80, templet: d => {
                                return d.direction === 'OUTGOING' ? '出' : '入';
                            }},
                            {field: 'targetNodeId', title: '目标节点ID', minWidth: 150},
                            {field: 'targetNodeLabels', title: '目标节点类型', minWidth: 150},
                            {title: '操作', width: 80, templet: d => {
                                return '<button class="layui-btn layui-btn-xs" lay-event="navigate">查看</button>';
                            }}
                        ]],
                        text: {
                            none: '该节点没有关系数据'
                        }
                    });
                    
                    // 监听表格操作
                    table.on('tool(relation-table-container)', obj => {
                        if (obj.event === 'navigate') {
                            this.selectNode(obj.data.targetNodeId);
                        }
                    });
                }
                
                showNodeDetailLayer(data) {
                    let properties = {};
                    try {
                        if (data.allProperties) {
                            properties = JSON.parse(data.allProperties);
                        }
                    } catch (e) {
                        console.error('解析属性JSON失败:', e);
                    }
                    
                    // 构建详情表格数据
                    const detailData = [
                        {key: 'ID', value: data.id},
                        {key: '节点类型', value: data.title}
                    ];
                    
                    // 添加所有属性
                    Object.entries(properties).forEach(([key, value]) => {
                        detailData.push({key, value: this.formatValue(value)});
                    });
                    
                    // 创建弹出层
                    layer.open({
                        type: 1,
                        title: '节点详情',
                        area: ['600px', '500px'],
                        content: '<div id="detail-table-container" style="padding: 15px;"></div>',
                        success: () => {
                            // 渲染详情表格
                            table.render({
                                elem: '#detail-table-container',
                                data: detailData,
                                cols: [[
                                    {field: 'key', title: '属性名', width: '30%'},
                                    {field: 'value', title: '属性值', width: '70%'}
                                ]],
                                skin: 'line',
                                even: true
                            });
                        }
                    });
                }

                formatValue(value) {
                    if (value === null || value === undefined) {
                        return '-';
                    }
                    if (typeof value === 'object') {
                        return JSON.stringify(value);
                    }
                    return String(value);
                }

                // 新增方法：渲染费用预览数据（包括费用集信息和默认表格）
                renderCostPreviewData(costData) {
                    // 清除之前的费用集信息卡片
                    const costInfoContainer = document.getElementById('cost-info-container');
                    costInfoContainer.innerHTML = '';
                    
                    // 重置按钮状态
                    document.getElementById('cost-item-btn').classList.add('layui-btn-disabled');
                    document.getElementById('material-machine-btn').classList.remove('layui-btn-disabled');
                    
                    if (!costData || (!costData.cost_items && !costData.cost_sets)) {
                        // 如果没有费用数据，渲染空表格
                        this.renderCostPreviewTable(null);
                        return;
                    }
                    
                    // 如果有CostSet信息，在表格上方显示
                    if (costData.cost_sets && costData.cost_sets.length > 0) {
                        const costSetInfo = document.createElement('div');
                        costSetInfo.className = 'layui-card';
                        costSetInfo.style.marginBottom = '10px';
                        costSetInfo.innerHTML = `
                            <div class="layui-card-header">费用集信息</div>
                            <div class="layui-card-body">
                                ${costData.cost_sets.map(set => `
                                    <p><strong>名称:</strong> ${set.name || '未命名费用集'}</p>
                                    ${set.properties && set.properties.GUID ? `<p><strong>GUID:</strong> ${set.properties.GUID}</p>` : ''}
                                `).join('')}
                            </div>
                        `;
                        
                        costInfoContainer.appendChild(costSetInfo);
                    }
                    
                    // 默认渲染CostItem类型的费用预览表格
                    this.renderCostPreviewTable(costData, 'CostItem');
                }

                // 新增方法：渲染费用预览表格
                renderCostPreviewTable(costData, filterType = null, containerId = 'cost-preview-container') {
                    if (!costData || (!costData.cost_items && !costData.cost_sets)) {
                        // 如果没有费用数据，渲染空表格
                        table.render({
                            elem: `#${containerId}`,
                            data: [],
                            cols: [[
                                {type: 'numbers', title: '序号', width: 60},
                                {field: 'name', title: '费用项名称', minWidth: 200},
                                {field: 'cost', title: '费用', width: 120}
                            ]],
                            skin: 'line',
                            even: true,
                            text: {
                                none: '该节点没有费用预览数据'
                            }
                        });
                        return;
                    }
                    
                    // 准备费用预览表格数据
                    let costItems = costData.cost_items || [];
                    
                    // 如果指定了过滤类型，只显示该类型的费用项
                    if (filterType) {
                        costItems = costItems.filter(item => {
                            const itemType = item.labels && item.labels.length > 0 ? item.labels[0] : '';
                            return itemType === filterType;
                        });
                    }
                    
                    // 处理费用项数据
                    const tableData = costItems.map(item => {
                        const props = item.properties || {};
                        const itemType = item.labels && item.labels.length > 0 ? item.labels[0] : '';
                        
                        // 基本数据结构
                        const tableItem = {
                            id: item.id,
                            name: props.name || '未命名费用项',
                            type: props.type || itemType
                        };
                        
                        // 根据节点类型添加不同的属性
                        if (itemType === 'MaterialandmachineCostItem') {
                            // 材料机械费用项
                            tableItem.supply = props.供货方 || '';
                            tableItem.code = props.编码 || '';
                            tableItem.unit = props.单位 || '';
                            tableItem.amount = props.数量 || 0;
                            tableItem.budgetPrice = props.预算价不含税 || 0;
                            tableItem.marketPrice = props.市场价不含税 || 0;
                            tableItem.totalBudget = props.预算价合价 || 0;
                            tableItem.totalMarket = props.市场价合价 || 0;
                            tableItem.priceDiff = props.价差 || 0;
                        } else if (itemType === 'CostItem') {
                            // 普通费用项
                            tableItem.cost = props.cost || 0;
                            tableItem.unique_id = props.unique_id || '';
                        } else {
                            // 其他类型的费用项
                            if (props.amount !== undefined) tableItem.amount = props.amount;
                            if (props.unit !== undefined) tableItem.unit = props.unit;
                            if (props.unitPrice !== undefined) tableItem.unitPrice = props.unitPrice;
                            if (props.totalPrice !== undefined) tableItem.totalPrice = props.totalPrice;
                            if (props.cost !== undefined) tableItem.cost = props.cost;
                        }
                        
                        return tableItem;
                    });
                    
                    // 获取适合的列配置
                    let columnConfig;
                    if (filterType && this.columnConfigs[filterType]) {
                        // 使用指定类型的列配置
                        columnConfig = this.columnConfigs[filterType].costPreview;
                    } else if (tableData.length > 0) {
                        // 根据第一个项目的类型决定使用哪种列配置
                        const firstItemType = tableData[0].type;
                        if (this.columnConfigs[firstItemType]) {
                            columnConfig = this.columnConfigs[firstItemType].costPreview;
                        } else {
                            columnConfig = this.columnConfigs['default'].costPreview;
                        }
                    } else {
                        columnConfig = this.columnConfigs['default'].costPreview;
                    }
                    
                    // 构建列配置
                    const cols = [
                        {type: 'numbers', title: '序号', width: 60}
                    ];
                    
                    // 添加可见的列
                    columnConfig.forEach(col => {
                        if (col.show) {
                            cols.push({
                                field: col.field,
                                title: col.title,
                                minWidth: col.minWidth || col.width || 100,
                                width: col.width
                            });
                        }
                    });
                    
                    // 渲染费用预览表格
                    table.render({
                        elem: `#${containerId}`,
                        data: tableData,
                        cols: [cols],
                        skin: 'line',
                        even: true,
                        text: {
                            none: filterType === 'CostItem' ? 
                                  '该节点没有费用预览数据' : 
                                  '该节点没有材机列表数据'
                        }
                    });
                }

                buildTreeStructureData(node, children) {
                    // 处理子节点数据
                    const treeData = [];
                    
                    // 处理子节点数据
                    for (const child of children) {
                        // 增强过滤条件，过滤掉费用预览相关节点
                        if (
                            (child.name && child.name.includes('费用预览')) ||
                            (child.properties && child.properties.name && child.properties.name.includes('费用预览')) ||
                            (child.labels && child.labels.some(label => label.includes('Cost'))) ||
                            (child.type && child.type.includes('Cost'))
                        ) {
                            continue;
                        }
                        
                        const item = {
                            id: child.id,
                            children: []
                        };
                        
                        // 添加属性
                        if (child.properties) {
                            // 添加标准属性
                            item.code = child.properties.code || '';
                            item.name = child.properties.name || '';
                            item.specification = child.properties.specification || child.properties.规格型号 || '';
                            item.unit = child.properties.unit || child.properties.单位 || '';
                            item.formula = child.properties.formula || child.properties.计算式 || '';
                            item.amount = child.properties.amount || child.properties.数量 || '';
                            item.unitPriceWithTax = child.properties.unitPriceWithTax || child.properties.单价含税 || '';
                            item.unitPriceWithoutTax = child.properties.unitPriceWithoutTax || child.properties.单价不含税 || '';
                            item.totalPriceWithTax = child.properties.totalPriceWithTax || child.properties.合价含税 || '';
                            item.totalPriceWithoutTax = child.properties.totalPriceWithoutTax || child.properties.合价不含税 || '';
                            item.taxIndex = child.properties.taxIndex || child.properties.取费索引 || '';
                            item.remark = child.properties.remark || child.properties.备注 || '';
                            
                            // 将所有属性序列化为JSON存储，用于详情查看
                            item.allProperties = JSON.stringify(child.properties);
                        }
                        
                        // 处理子节点
                        if (child.children && child.children.length > 0) {
                            item.children = this.buildTreeStructureData(child, child.children);
                        }
                        
                        treeData.push(item);
                    }
                    
                    return treeData;
                }
                
                buildTreeStructureHTML(treeData, level = 0) {
                    let html = '';
                    
                    // 添加表头行
                    if (level === 0) {
                        html += `<tr class="tree-header">
                            <th class="tree-col-name">项目名称</th>
                            <th class="tree-col-spec">规格型号</th>
                            <th class="tree-col-unit">单位</th>
                            <th class="tree-col-formula">计算式</th>
                            <th class="tree-col-amount">数量</th>
                            <th class="tree-col-price">单价含税</th>
                            <th class="tree-col-price">单价不含税</th>
                            <th class="tree-col-total">合价含税</th>
                            <th class="tree-col-total">合价不含税</th>
                            <th class="tree-col-tax">取费表</th>
                            <th class="tree-col-remark">备注</th>
                        </tr>`;
                    }
                    
                    // 生成行数据
                    treeData.forEach((item, index) => {
                        const hasChildren = item.children && item.children.length > 0;
                        const toggleClass = hasChildren ? 'tree-toggle' : '';
                        const toggleIcon = hasChildren ? '<i class="layui-icon layui-icon-triangle-d"></i>' : '<i class="layui-icon layui-icon-file"></i>';
                        const nodeClass = hasChildren ? 'parent-node' : 'leaf-node';
                        
                        // 创建行
                        html += `<tr class="tree-row ${nodeClass}" data-id="${item.id}" data-level="${level}">`;
                        
                        // 项目名称列（带缩进和图标）
                        html += `<td class="tree-col-name">
                            <div class="tree-indent" style="padding-left: ${level * 20}px">
                                <span class="${toggleClass}">${toggleIcon}</span>
                                <span class="node-code">${item.code ? item.code : ''}</span>
                                <span class="node-name">${item.name || '未命名项目'}</span>
                            </div>
                        </td>`;
                        
                        // 规格型号列
                        html += `<td class="tree-col-spec">${item.specification || ''}</td>`;
                        
                        // 单位列
                        html += `<td class="tree-col-unit">${item.unit || ''}</td>`;
                        
                        // 计算式列
                        html += `<td class="tree-col-formula">${item.formula || ''}</td>`;
                        
                        // 数量列
                        html += `<td class="tree-col-amount">${item.amount || ''}</td>`;
                        
                        // 单价含税列
                        html += `<td class="tree-col-price">${item.unitPriceWithTax || ''}</td>`;
                        
                        // 单价不含税列
                        html += `<td class="tree-col-price">${item.unitPriceWithoutTax || ''}</td>`;
                        
                        // 合价含税列
                        html += `<td class="tree-col-total">${item.totalPriceWithTax || ''}</td>`;
                        
                        // 合价不含税列
                        html += `<td class="tree-col-total">${item.totalPriceWithoutTax || ''}</td>`;
                        
                        // 取费表列
                        html += `<td class="tree-col-tax">${item.taxIndex || ''}</td>`;
                        
                        // 备注列
                        html += `<td class="tree-col-remark">${item.remark || ''}</td>`;
                        
                        html += '</tr>';
                        
                        // 递归处理子节点
                        if (hasChildren) {
                            html += this.buildTreeStructureHTML(item.children, level + 1);
                        }
                    });
                    
                    return html;
                }

                addTreeStructureStyles() {
                    // 检查是否已经添加了样式
                    if (!document.getElementById('tree-structure-styles')) {
                        const style = document.createElement('style');
                        style.id = 'tree-structure-styles';
                        style.textContent = `
                            .project-division-tree {
                                width: 100%;
                                overflow: auto;
                                margin-top: 10px;
                            }
                            
                            .project-division-table {
                                width: 100%;
                                border-collapse: collapse;
                                table-layout: fixed;
                            }
                            
                            .project-division-table tr {
                                border-bottom: 1px solid #e6e6e6;
                                height: 40px;
                            }
                            
                            .project-division-table td, .project-division-table th {
                                padding: 8px;
                                vertical-align: middle;
                                border-right: 1px solid #e6e6e6;
                                overflow: hidden;
                                text-overflow: ellipsis;
                                white-space: nowrap;
                            }
                            
                            .tree-header {
                                background-color: #f2f2f2;
                                font-weight: bold;
                            }
                            
                            .tree-col-name {
                                width: 200px;
                                text-align: left;
                            }
                            
                            .tree-col-spec {
                                width: 100px;
                                text-align: center;
                            }
                            
                            .tree-col-unit {
                                width: 60px;
                                text-align: center;
                            }
                            
                            .tree-col-formula {
                                width: 100px;
                                text-align: center;
                            }
                            
                            .tree-col-amount {
                                width: 80px;
                                text-align: right;
                            }
                            
                            .tree-col-price {
                                width: 100px;
                                text-align: right;
                            }
                            
                            .tree-col-total {
                                width: 120px;
                                text-align: right;
                            }
                            
                            .tree-col-tax {
                                width: 100px;
                                text-align: center;
                            }
                            
                            .tree-col-remark {
                                width: 100px;
                                text-align: left;
                            }
                            
                            .tree-indent {
                                display: flex;
                                align-items: center;
                                position: relative;
                            }
                            
                            .tree-toggle {
                                cursor: pointer;
                                margin-right: 8px;
                                display: inline-block;
                                width: 16px;
                                height: 16px;
                                text-align: center;
                                line-height: 16px;
                            }
                            
                            .node-code {
                                color: #999;
                                font-size: 12px;
                                margin-right: 5px;
                            }
                            
                            .node-name {
                                font-weight: normal;
                                margin-right: 10px;
                            }
                            
                            .parent-node .node-name {
                                font-weight: bold;
                                color: #1E9FFF;
                            }
                            
                            .tree-row:hover {
                                background-color: #f2f2f2;
                            }
                            
                            /* 树状连接线样式 */
                            .tree-row .tree-indent {
                                position: relative;
                            }
                            
                            .tree-row[data-level="1"] .tree-indent:before,
                            .tree-row[data-level="2"] .tree-indent:before,
                            .tree-row[data-level="3"] .tree-indent:before,
                            .tree-row[data-level="4"] .tree-indent:before,
                            .tree-row[data-level="5"] .tree-indent:before {
                                content: '';
                                position: absolute;
                                left: 7px;
                                top: -8px;
                                height: calc(100% + 16px);
                                border-left: 1px dotted #ccc;
                            }
                            
                            .tree-row[data-level="1"] .tree-indent:after,
                            .tree-row[data-level="2"] .tree-indent:after,
                            .tree-row[data-level="3"] .tree-indent:after,
                            .tree-row[data-level="4"] .tree-indent:after,
                            .tree-row[data-level="5"] .tree-indent:after {
                                content: '';
                                position: absolute;
                                left: 7px;
                                top: 50%;
                                width: 12px;
                                border-top: 1px dotted #ccc;
                            }
                            
                            /* 颜色标记 */
                            .leaf-node .layui-icon-file {
                                color: #5FB878;
                            }
                            
                            .parent-node .layui-icon-triangle-d,
                            .parent-node .layui-icon-triangle-r {
                                color: #1E9FFF;
                            }
                            
                            /* 费用预览按钮样式 */
                            .cost-preview-btn {
                                padding: 0 10px;
                            }
                        `;
                        document.head.appendChild(style);
                    }
                }

                async getAllChildrenRecursively(children) {
                    const allChildren = [...children];
                    
                    for (const child of allChildren) {
                        if (child.id) {
                            try {
                                // 获取子节点的子节点
                                const response = await fetch(`/api/node/${child.id}`);
                                const data = await response.json();
                                
                                if (data.children && data.children.length > 0) {
                                    // 递归获取子节点的子节点
                                    const grandChildren = await this.getAllChildrenRecursively(data.children);
                                    
                                    // 将子节点的子节点添加到子节点的children属性中
                                    child.children = grandChildren;
                                }
                            } catch (error) {
                                console.error('获取子节点失败:', error);
                            }
                        }
                    }
                    
                    return allChildren;
                }
            }

            // 初始化应用
            new KnowledgeGraphUI();
        });
    </script>
</body>
</html>