8
n8n 中文网amn8n.com

CAD-BIM 工程量提取 HTML 报告生成器

高级

这是一个Engineering领域的自动化工作流,包含 18 个节点。主要使用 If, Set, Function, ManualTrigger, ExecuteCommand 等节点。 从Revit模型生成交互式墙体工程量HTML报告

前置要求
  • 无特殊前置要求,导入即可使用

分类

工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "Hta5FU7DD54QKxUK",
  "meta": {
    "instanceId": "5ba872643a08525d217680a9bbff49bd9855bd3fe8ccba4458b363643e613bee"
  },
  "name": "CAD-BIM 工程量提取 HTML 报告生成器",
  "tags": [],
  "nodes": [
    {
      "id": "fe089e9a-bb16-440b-900d-21c5cf782286",
      "name": "开始 - 点击启动",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -1780,
        580
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "e56f9ca7-214a-4c90-a6fa-657d6c875e26",
      "name": "设置 - 定义文件路径",
      "type": "n8n-nodes-base.set",
      "position": [
        -1580,
        580
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "9cbd4ec9-df24-41e8-b47a-720a4cdb733b",
              "name": "path_to_revit_converter",
              "type": "string",
              "value": "C:\\DDC\\DDC_Converter\\Release\\Community\\DDC_Converter_Revit_Community\\DDC_Converter_Revit_Community\\RvtExporter.exe"
            },
            {
              "id": "aa834467-80fb-476a-bac1-6728478834f0",
              "name": "revit_file",
              "type": "string",
              "value": "C:\\DDC\\DDC_Converter\\Release\\Community\\DDC_Converter_Revit_Community\\RVT_sample\\2023 racbasicsampleproject.rvt"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "5493ccd6-3126-4a7a-a2fa-ca286a69935b",
      "name": "提取 - 运行 Revit 转换器",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        -1380,
        580
      ],
      "parameters": {
        "command": "=\"{{$json[\"path_to_revit_converter\"]}}\" \"{{$json[\"revit_file\"]}}\""
      },
      "typeVersion": 1,
      "continueOnFail": true
    },
    {
      "id": "433af16e-b5b4-4b02-989b-7c140afa52b7",
      "name": "检查 - 提取是否成功?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1180,
        580
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition1",
              "operator": {
                "type": "object",
                "operation": "exists",
                "rightType": "any"
              },
              "leftValue": "={{ $node[\"Extract - Run Revit converter\"].json.error }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "de432702-44fb-4cf0-90f0-78fb50206721",
      "name": "成功 - 创建 Excel 文件名",
      "type": "n8n-nodes-base.set",
      "position": [
        -980,
        580
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "9cbd4ec9-df24-41e8-b47a-720a4cdb733b",
              "name": "xlsx_filename",
              "type": "string",
              "value": "={{ $node[\"Setup - Define file paths\"].json[\"revit_file\"].slice(0, -4) + \"_rvt.xlsx\" }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "419aaa9e-7edc-43b4-a666-2700de939884",
      "name": "错误 - 显示问题详情",
      "type": "n8n-nodes-base.set",
      "position": [
        -980,
        380
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "error-message-id",
              "name": "error_message",
              "type": "string",
              "value": "=Extraction failed: {{ $node[\"Extract - Run Revit converter\"].json.error || \"Unknown error\" }}"
            },
            {
              "id": "error-code-id",
              "name": "error_code",
              "type": "number",
              "value": "={{ $node[\"Extract - Run Revit converter\"].json.code || -1 }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "673bbba9-1537-4852-8d4e-b67c4991253c",
      "name": "提取 - 从磁盘读取 Excel 文件",
      "type": "n8n-nodes-base.readBinaryFile",
      "position": [
        -780,
        580
      ],
      "parameters": {
        "filePath": "={{ $json[\"xlsx_filename\"] }}"
      },
      "typeVersion": 1
    },
    {
      "id": "c4b05b5b-6d0b-4ab8-89fb-a54fe86899d9",
      "name": "提取 - 将 Excel 解析为数据",
      "type": "n8n-nodes-base.spreadsheetFile",
      "position": [
        -580,
        580
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "5d2bdce5-75d2-40a2-b10b-fd443a982118",
      "name": "转换 - 仅筛选 OST_Walls",
      "type": "n8n-nodes-base.if",
      "position": [
        -380,
        580
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json[\"Category : String\"] }}",
              "value2": "OST_Walls"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5c2ac481-8340-4221-afdb-a3c7ca520abb",
      "name": "转换 - 清理墙体数据",
      "type": "n8n-nodes-base.set",
      "position": [
        -180,
        580
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "wall-type-name",
              "name": "type_name",
              "type": "string",
              "value": "={{ $json[\"Type Name : String\"] || \"Unknown Type\" }}"
            },
            {
              "id": "wall-volume",
              "name": "volume",
              "type": "number",
              "value": "={{ parseFloat($json[\"Volume : Double\"]) || 0 }}"
            },
            {
              "id": "processed-date",
              "name": "processed_date",
              "type": "string",
              "value": "={{ new Date().toISOString() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "74b0b328-820d-4f85-bc8a-c6bb6d983d97",
      "name": "转换 - 按类型名称分组并汇总体积",
      "type": "n8n-nodes-base.function",
      "position": [
        40,
        580
      ],
      "parameters": {
        "functionCode": "// Group walls by Type Name and sum Volume\n// Using only built-in JavaScript functions\n\n// Get all wall elements\nconst allWalls = $input.all().map(item => item.json);\n\n// Group by type_name using reduce\nconst grouped = allWalls.reduce((acc, wall) => {\n  const typeName = wall.type_name;\n  if (!acc[typeName]) {\n    acc[typeName] = [];\n  }\n  acc[typeName].push(wall);\n  return acc;\n}, {});\n\n// Create grouping results\nconst groupedResults = Object.keys(grouped).map(typeName => {\n  const walls = grouped[typeName];\n  const totalVolume = walls.reduce((sum, wall) => sum + (wall.volume || 0), 0);\n  const count = walls.length;\n  \n  return {\n    type_name: typeName,\n    wall_count: count,\n    total_volume: Math.round(totalVolume * 1000) / 1000, // round to 3 decimal places\n    average_volume: count > 0 ? Math.round((totalVolume / count) * 1000) / 1000 : 0,\n    processed_date: new Date().toISOString()\n  };\n});\n\n// Sort by total volume descending\nconst sortedResults = groupedResults.sort((a, b) => b.total_volume - a.total_volume);\n\nreturn sortedResults.map(item => ({ json: item }));"
      },
      "typeVersion": 1
    },
    {
      "id": "1ab073ee-de46-4224-a4b1-cee2e92dfe20",
      "name": "转换 - 生成 HTML 报告",
      "type": "n8n-nodes-base.function",
      "position": [
        240,
        580
      ],
      "parameters": {
        "functionCode": "// Generate HTML report from grouped wall data\nconst groupedData = $input.all().map(item => item.json);\n\n// Create summary statistics\nconst totalWallTypes = groupedData.length;\nconst totalWalls = groupedData.reduce((sum, item) => sum + item.wall_count, 0);\nconst totalVolume = groupedData.reduce((sum, item) => sum + item.total_volume, 0);\nconst avgVolumePerWall = totalWalls > 0 ? Math.round((totalVolume / totalWalls) * 1000) / 1000 : 0;\n\nconst sourceFile = $node[\"Setup - Define file paths\"].json[\"revit_file\"];\nconst processedDate = new Date().toLocaleString();\n\n// Generate wall type cards HTML\nconst wallTypeCards = groupedData.map((wallType, index) => {\n  const percentage = totalVolume > 0 ? (wallType.total_volume / totalVolume) * 100 : 0;\n  return `\n    <div class=\"wall-type-card\" style=\"animation-delay: ${index * 0.1}s;\">\n      <div class=\"wall-type-header\">\n        <div class=\"wall-type-name\">${wallType.type_name}</div>\n        <div class=\"wall-count\">${wallType.wall_count} walls</div>\n      </div>\n      <div class=\"wall-metrics\">\n        <div class=\"metric\">\n          <div class=\"metric-label\">Total Volume</div>\n          <div class=\"metric-value\">${wallType.total_volume.toFixed(3)} m³</div>\n        </div>\n        <div class=\"metric\">\n          <div class=\"metric-label\">Average Volume</div>\n          <div class=\"metric-value\">${wallType.average_volume.toFixed(3)} m³</div>\n        </div>\n        <div class=\"metric\">\n          <div class=\"metric-label\">Percentage</div>\n          <div class=\"metric-value\">${percentage.toFixed(1)}%</div>\n        </div>\n      </div>\n      <div class=\"volume-bar\">\n        <div class=\"volume-fill\" style=\"width: ${percentage}%;\"></div>\n      </div>\n    </div>`;\n}).join('');\n\n// Generate complete HTML\nconst htmlContent = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Quantity Take Off Report</title>\n    <style>\n        * {\n            margin: 0;\n            padding: 0;\n            box-sizing: border-box;\n        }\n\n        body {\n            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n            min-height: 100vh;\n            padding: 20px;\n        }\n\n        .container {\n            max-width: 1000px;\n            margin: 0 auto;\n            background: rgba(255, 255, 255, 0.95);\n            border-radius: 20px;\n            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);\n            overflow: hidden;\n            backdrop-filter: blur(10px);\n        }\n\n        .header {\n            background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%);\n            color: white;\n            padding: 30px;\n            text-align: center;\n        }\n\n        .header h1 {\n            font-size: 2.2rem;\n            margin-bottom: 8px;\n        }\n\n        .header p {\n            font-size: 1rem;\n            opacity: 0.9;\n        }\n\n        .summary-cards {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n            gap: 15px;\n            padding: 30px;\n            background: #f8f9fa;\n        }\n\n        .summary-card {\n            background: white;\n            padding: 20px;\n            border-radius: 12px;\n            text-align: center;\n            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);\n            transition: transform 0.3s ease;\n            border-left: 4px solid;\n        }\n\n        .summary-card:hover {\n            transform: translateY(-3px);\n        }\n\n        .summary-card.types { border-left-color: #e74c3c; }\n        .summary-card.walls { border-left-color: #3498db; }\n        .summary-card.volume { border-left-color: #2ecc71; }\n        .summary-card.average { border-left-color: #f39c12; }\n\n        .summary-card h3 {\n            color: #2c3e50;\n            font-size: 0.8rem;\n            text-transform: uppercase;\n            letter-spacing: 1px;\n            margin-bottom: 8px;\n        }\n\n        .summary-card .value {\n            font-size: 1.8rem;\n            font-weight: bold;\n            color: #2c3e50;\n            margin-bottom: 4px;\n        }\n\n        .summary-card .unit {\n            color: #7f8c8d;\n            font-size: 0.8rem;\n        }\n\n        .content {\n            padding: 30px;\n        }\n\n        .section-title {\n            font-size: 1.5rem;\n            color: #2c3e50;\n            margin-bottom: 20px;\n            text-align: center;\n            position: relative;\n        }\n\n        .section-title::after {\n            content: '';\n            position: absolute;\n            bottom: -8px;\n            left: 50%;\n            transform: translateX(-50%);\n            width: 60px;\n            height: 3px;\n            background: linear-gradient(135deg, #3498db, #e74c3c);\n            border-radius: 2px;\n        }\n\n        .wall-types-grid {\n            display: grid;\n            gap: 15px;\n            margin-top: 20px;\n        }\n\n        .wall-type-card {\n            background: white;\n            border-radius: 12px;\n            padding: 20px;\n            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);\n            transition: all 0.3s ease;\n            border-left: 4px solid #3498db;\n        }\n\n        .wall-type-card:hover {\n            transform: translateY(-2px);\n            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);\n        }\n\n        .wall-type-header {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            margin-bottom: 15px;\n        }\n\n        .wall-type-name {\n            font-size: 1.1rem;\n            font-weight: bold;\n            color: #2c3e50;\n        }\n\n        .wall-count {\n            background: linear-gradient(135deg, #3498db, #2980b9);\n            color: white;\n            padding: 6px 12px;\n            border-radius: 15px;\n            font-size: 0.8rem;\n            font-weight: bold;\n        }\n\n        .wall-metrics {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n            gap: 10px;\n        }\n\n        .metric {\n            text-align: center;\n            padding: 12px;\n            background: #f8f9fa;\n            border-radius: 8px;\n        }\n\n        .metric-label {\n            font-size: 0.7rem;\n            color: #6c757d;\n            text-transform: uppercase;\n            letter-spacing: 0.5px;\n            margin-bottom: 4px;\n        }\n\n        .metric-value {\n            font-size: 1rem;\n            font-weight: bold;\n            color: #2c3e50;\n        }\n\n        .volume-bar {\n            width: 100%;\n            height: 6px;\n            background: #e9ecef;\n            border-radius: 3px;\n            margin-top: 12px;\n            overflow: hidden;\n        }\n\n        .volume-fill {\n            height: 100%;\n            background: linear-gradient(90deg, #3498db, #2ecc71);\n            border-radius: 3px;\n            transition: width 0.8s ease;\n        }\n\n        .footer {\n            background: #2c3e50;\n            color: white;\n            padding: 20px;\n            text-align: center;\n            font-size: 0.9rem;\n        }\n\n        .footer-info {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n            gap: 15px;\n            margin-bottom: 15px;\n        }\n\n        .footer-item strong {\n            display: block;\n            margin-bottom: 4px;\n            color: #3498db;\n        }\n\n        @media (max-width: 768px) {\n            .header h1 { font-size: 1.8rem; }\n            .summary-cards { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); padding: 20px; }\n            .content { padding: 20px; }\n            .wall-type-header { flex-direction: column; align-items: flex-start; gap: 8px; }\n        }\n    </style>\n</head>\n<body>\n    <div class=\"container\">\n        <div class=\"header\">\n            <h1>📊 Quantity Take Off Report</h1>\n            <p>Wall analysis and volume calculations from Revit data</p>\n        </div>\n\n        <div class=\"summary-cards\">\n            <div class=\"summary-card types\">\n                <h3>Wall Types</h3>\n                <div class=\"value\">${totalWallTypes}</div>\n                <div class=\"unit\">Different Types</div>\n            </div>\n            <div class=\"summary-card walls\">\n                <h3>Total Walls</h3>\n                <div class=\"value\">${totalWalls}</div>\n                <div class=\"unit\">Wall Elements</div>\n            </div>\n            <div class=\"summary-card volume\">\n                <h3>Total Volume</h3>\n                <div class=\"value\">${totalVolume.toFixed(3)}</div>\n                <div class=\"unit\">m³</div>\n            </div>\n            <div class=\"summary-card average\">\n                <h3>Average Volume</h3>\n                <div class=\"value\">${avgVolumePerWall.toFixed(3)}</div>\n                <div class=\"unit\">m³ per wall</div>\n            </div>\n        </div>\n\n        <div class=\"content\">\n            <h2 class=\"section-title\">Wall Types Breakdown</h2>\n            <div class=\"wall-types-grid\">\n                ${wallTypeCards}\n            </div>\n        </div>\n\n        <div class=\"footer\">\n            <div class=\"footer-info\">\n                <div class=\"footer-item\">\n                    <strong>Source File:</strong>\n                    ${sourceFile.split('\\\\').pop()}\n                </div>\n                <div class=\"footer-item\">\n                    <strong>Processed Date:</strong>\n                    ${processedDate}\n                </div>\n                <div class=\"footer-item\">\n                    <strong>Generated By:</strong>\n                    n8n Workflow Pipeline\n                </div>\n            </div>\n            <p style=\"margin-top: 15px; opacity: 0.7;\">\n                Data extracted from Revit and processed through automated ETL pipeline.\n            </p>\n        </div>\n    </div>\n</body>\n</html>`;\n\n// Create filename based on source file\nconst sourceBasename = sourceFile.replace(/\\.[^/.]+$/, \"\"); // Remove extension\nconst outputFilename = sourceBasename + \"_quantity_takeoff_report.html\";\n\n// Create proper binary data structure for n8n writeBinaryFile node\nconst binaryData = {\n  data: Buffer.from(htmlContent, 'utf8'),\n  mimeType: 'text/html',\n  fileName: outputFilename.split('\\\\').pop() // Get just filename without path\n};\n\n// Return data with proper binary structure\nreturn [{\n  json: {\n    filename: outputFilename,\n    summary: {\n      total_wall_types: totalWallTypes,\n      total_walls: totalWalls,\n      total_volume: Math.round(totalVolume * 1000) / 1000,\n      average_volume_per_wall: avgVolumePerWall,\n      processed_at: new Date().toISOString(),\n      source_file: sourceFile\n    },\n    grouped_data: groupedData,\n    message: `Generated HTML report for ${totalWallTypes} wall types (${totalWalls} total walls)`,\n    htmlContent: htmlContent\n  },\n  binary: {\n    data: binaryData\n  }\n}];"
      },
      "typeVersion": 1
    },
    {
      "id": "a33f33de-dc6d-4fe7-bf27-86156906827b",
      "name": "加载 - 保存 HTML 报告",
      "type": "n8n-nodes-base.writeBinaryFile",
      "position": [
        460,
        580
      ],
      "parameters": {
        "options": {},
        "fileName": "={{ $json.filename }}"
      },
      "typeVersion": 1
    },
    {
      "id": "feb89705-054c-446a-940b-60ba849fcdfe",
      "name": "成功 - 最终结果",
      "type": "n8n-nodes-base.set",
      "position": [
        660,
        580
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "success-message",
              "name": "success",
              "type": "boolean",
              "value": true
            },
            {
              "id": "final-message",
              "name": "final_message",
              "type": "string",
              "value": "={{ $node[\"Transform - Generate HTML Report\"].json.message }}. File saved as: {{ $node[\"Transform - Generate HTML Report\"].json.filename }}"
            },
            {
              "id": "summary-data",
              "name": "summary",
              "type": "object",
              "value": "={{ $node[\"Transform - Generate HTML Report\"].json.summary }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "d7749dcd-349f-455c-aeb6-3cbfeccaf26b",
      "name": "提取阶段说明",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1840,
        240
      ],
      "parameters": {
        "color": 6,
        "width": 1400,
        "height": 520,
        "content": "## 🔷 提取阶段"
      },
      "typeVersion": 1
    },
    {
      "id": "eaa62f9b-20cf-4aa6-afd9-c51dab8d3dd4",
      "name": "转换阶段说明",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -420,
        240
      ],
      "parameters": {
        "color": 4,
        "width": 800,
        "height": 520,
        "content": "## 🔷 转换阶段"
      },
      "typeVersion": 1
    },
    {
      "id": "fb894369-4cb2-42a2-abf8-e0c61ba8493c",
      "name": "加载阶段说明",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        240
      ],
      "parameters": {
        "width": 520,
        "height": 520,
        "content": "## 🔷 加载阶段"
      },
      "typeVersion": 1
    },
    {
      "id": "bd19674e-a352-48fc-8c06-88ad296e000f",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1860,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 2800,
        "height": 720,
        "content": "# CAD (BIM) 的 ETL 流程"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {
    "Start - Click to begin": [
      {
        "json": {}
      }
    ]
  },
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "f166c01d-5ae5-418e-af24-d11c81839f53",
  "connections": {
    "Start - Click to begin": {
      "main": [
        [
          {
            "node": "Setup - Define file paths",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Setup - Define file paths": {
      "main": [
        [
          {
            "node": "Extract - Run Revit converter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transform - Clean wall data": {
      "main": [
        [
          {
            "node": "Transform - Group by Type Name & sum Volume",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract - Parse Excel to data": {
      "main": [
        [
          {
            "node": "Transform - Filter only OST_Walls",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract - Run Revit converter": {
      "main": [
        [
          {
            "node": "Check - Did extraction succeed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check - Did extraction succeed?": {
      "main": [
        [
          {
            "node": "Error - Show what went wrong",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Success - Create Excel filename",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Success - Create Excel filename": {
      "main": [
        [
          {
            "node": "Extract - Read Excel file from disk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transform - Generate HTML Report": {
      "main": [
        [
          {
            "node": "Load - Save HTML Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transform - Filter only OST_Walls": {
      "main": [
        [
          {
            "node": "Transform - Clean wall data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract - Read Excel file from disk": {
      "main": [
        [
          {
            "node": "Extract - Parse Excel to data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transform - Group by Type Name & sum Volume": {
      "main": [
        [
          {
            "node": "Transform - Generate HTML Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

高级 - 工程

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量18
分类1
节点类型9
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

外部链接
在 n8n.io 查看

分享此工作流