8
n8n 中文网amn8n.com

我的工作流程 2

高级

这是一个Invoice Processing, AI Summarization领域的自动化工作流,包含 18 个节点。主要使用 Code, Switch, Webhook, Telegram, HttpRequest 等节点。 基于AI的发票数据提取与审批工作流程,集成ScrapeGraphAI和Telegram

前置要求
  • HTTP Webhook 端点(n8n 会自动生成)
  • Telegram Bot Token
  • 可能需要目标 API 的认证凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "VhEwspDqzu7ssFVE",
  "meta": {
    "instanceId": "f4b0efaa33080e7774e0d9285c40c7abcd2c6f7cf1a8b901fa7106170dd4cda3",
    "templateCredsSetupCompleted": true
  },
  "name": "我的工作流程 2",
  "tags": [
    {
      "id": "DxXGubfBzRKh6L8T",
      "name": "Revenue Optimization",
      "createdAt": "2025-07-25T16:24:30.370Z",
      "updatedAt": "2025-07-25T16:24:30.370Z"
    },
    {
      "id": "IxkcJ2IpYIxivoHV",
      "name": "Content Strategy",
      "createdAt": "2025-07-25T12:57:37.677Z",
      "updatedAt": "2025-07-25T12:57:37.677Z"
    },
    {
      "id": "PAKIJ2Mm9EvRcR3u",
      "name": "Trend Monitoring",
      "createdAt": "2025-07-25T12:57:37.670Z",
      "updatedAt": "2025-07-25T12:57:37.670Z"
    },
    {
      "id": "YtfXmaZk44MYedPO",
      "name": "Dynamic Pricing",
      "createdAt": "2025-07-25T16:24:30.369Z",
      "updatedAt": "2025-07-25T16:24:30.369Z"
    },
    {
      "id": "wJ30mjhtrposO8Qt",
      "name": "Simple RAG",
      "createdAt": "2025-07-28T12:55:14.424Z",
      "updatedAt": "2025-07-28T12:55:14.424Z"
    }
  ],
  "nodes": [
    {
      "id": "4d24fd12-5442-4112-b997-2e6b9ece768c",
      "name": "邮件触发器",
      "type": "n8n-nodes-base.emailReadImap",
      "position": [
        1120,
        832
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 2
    },
    {
      "id": "b32637a8-8941-4fea-b6cb-b2272d25eaa4",
      "name": "文件上传 Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        1120,
        1008
      ],
      "webhookId": "9588f200-20c0-4f26-81e0-73726abc889a",
      "parameters": {
        "path": "/invoice-upload",
        "options": {
          "rawBody": true
        },
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "4197b894-434f-42b6-a728-b6773af9b54a",
      "name": "文件处理器",
      "type": "n8n-nodes-base.code",
      "position": [
        1424,
        896
      ],
      "parameters": {
        "jsCode": "// Process incoming data from either email or webhook\nconst inputData = $input.all()[0];\nlet invoiceFiles = [];\n\n// Handle email attachments\nif (inputData.json.attachments) {\n  invoiceFiles = inputData.json.attachments\n    .filter(attachment => {\n      const fileName = attachment.filename.toLowerCase();\n      return fileName.endsWith('.pdf') || \n             fileName.endsWith('.png') || \n             fileName.endsWith('.jpg') || \n             fileName.endsWith('.jpeg') ||\n             fileName.endsWith('.tiff') ||\n             fileName.endsWith('.bmp');\n    })\n    .map(attachment => ({\n      filename: attachment.filename,\n      content: attachment.content,\n      contentType: attachment.contentType,\n      source: 'email',\n      sender: inputData.json.from?.text || 'unknown',\n      subject: inputData.json.subject || 'No subject',\n      receivedDate: inputData.json.date || new Date().toISOString()\n    }));\n}\n// Handle direct file uploads\nelse if (inputData.binary) {\n  Object.keys(inputData.binary).forEach(key => {\n    const file = inputData.binary[key];\n    invoiceFiles.push({\n      filename: file.fileName || `upload_${key}`,\n      content: file.data,\n      contentType: file.mimeType,\n      source: 'upload',\n      uploadedDate: new Date().toISOString()\n    });\n  });\n}\n\n// Return each file as separate execution\nreturn invoiceFiles.map((file, index) => ({\n  json: {\n    invoice_id: `INV_${Date.now()}_${index}`,\n    filename: file.filename,\n    source: file.source,\n    sender: file.sender || null,\n    subject: file.subject || null,\n    received_date: file.receivedDate || file.uploadedDate,\n    content_type: file.contentType,\n    processing_status: 'pending',\n    created_at: new Date().toISOString()\n  },\n  binary: {\n    invoice_file: {\n      data: file.content,\n      mimeType: file.contentType,\n      fileName: file.filename\n    }\n  }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "44e738e0-652a-40ff-8a9b-d4d8381771ef",
      "name": "ScrapeGraphAI - 发票提取器",
      "type": "n8n-nodes-scrapegraphai.scrapegraphAi",
      "position": [
        1744,
        880
      ],
      "parameters": {
        "resource": "scrapeSmartScraper"
      },
      "typeVersion": 1
    },
    {
      "id": "c891bcd4-df84-4fde-930d-e1eba7f679d0",
      "name": "数据提取器和清理器",
      "type": "n8n-nodes-base.code",
      "position": [
        2080,
        912
      ],
      "parameters": {
        "jsCode": "// Enhanced data extraction and cleaning\nconst inputData = $input.all()[0];\nconst extractedData = inputData.json.result?.invoice_data || {};\nconst originalMetadata = inputData.json;\n\nfunction cleanAndValidateData(data) {\n  // Clean and standardize extracted data\n  const cleaned = {\n    // Basic invoice info\n    invoice_number: cleanString(data.invoice_number),\n    invoice_date: standardizeDate(data.invoice_date),\n    due_date: standardizeDate(data.due_date),\n    \n    // Vendor information\n    vendor: {\n      name: cleanString(data.vendor_name),\n      address: cleanString(data.vendor_address),\n      tax_id: cleanString(data.vendor_tax_id || data.vendor_vat || data.tax_id),\n      email: cleanEmail(data.vendor_email),\n      phone: cleanPhone(data.vendor_phone)\n    },\n    \n    // Bill to information\n    bill_to: {\n      name: cleanString(data.bill_to_name),\n      address: cleanString(data.bill_to_address)\n    },\n    \n    // Financial data\n    currency: (data.currency || 'USD').toUpperCase(),\n    amounts: {\n      subtotal: parseAmount(data.subtotal),\n      tax_total: parseAmount(data.tax_total),\n      discount_amount: parseAmount(data.discount_amount || '0'),\n      shipping_amount: parseAmount(data.shipping_amount || '0'),\n      total_amount: parseAmount(data.total_amount)\n    },\n    \n    // Line items\n    line_items: cleanLineItems(data.line_items || []),\n    \n    // Additional info\n    payment_terms: cleanString(data.payment_terms),\n    purchase_order: cleanString(data.purchase_order),\n    notes: cleanString(data.notes),\n    \n    // Processing metadata\n    processing_info: {\n      extracted_at: new Date().toISOString(),\n      confidence_score: calculateConfidenceScore(data),\n      data_completeness: calculateCompleteness(data)\n    }\n  };\n  \n  return cleaned;\n}\n\nfunction cleanString(str) {\n  if (!str || str === 'null' || str === 'undefined') return null;\n  return str.toString().trim().replace(/\\s+/g, ' ');\n}\n\nfunction standardizeDate(dateStr) {\n  if (!dateStr || dateStr === 'null') return null;\n  try {\n    const date = new Date(dateStr);\n    return date.toISOString().split('T')[0]; // Return YYYY-MM-DD format\n  } catch {\n    return dateStr; // Return original if parsing fails\n  }\n}\n\nfunction cleanEmail(email) {\n  if (!email || email === 'null') return null;\n  const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n  return emailRegex.test(email) ? email.toLowerCase() : null;\n}\n\nfunction cleanPhone(phone) {\n  if (!phone || phone === 'null') return null;\n  return phone.replace(/[^\\d+\\-\\(\\)\\s]/g, '').trim();\n}\n\nfunction parseAmount(amount) {\n  if (!amount || amount === 'null') return 0;\n  const cleaned = amount.toString().replace(/[^\\d.-]/g, '');\n  return parseFloat(cleaned) || 0;\n}\n\nfunction cleanLineItems(items) {\n  if (!Array.isArray(items)) return [];\n  \n  return items.map(item => ({\n    description: cleanString(item.description),\n    quantity: parseFloat(item.quantity) || 1,\n    unit_price: parseAmount(item.unit_price),\n    total: parseAmount(item.total),\n    tax_rate: cleanString(item.tax_rate),\n    tax_amount: parseAmount(item.tax_amount || '0')\n  })).filter(item => item.description); // Remove items without description\n}\n\nfunction calculateConfidenceScore(data) {\n  let score = 0;\n  const requiredFields = ['invoice_number', 'vendor_name', 'total_amount', 'invoice_date'];\n  \n  requiredFields.forEach(field => {\n    if (data[field] && data[field] !== 'null') score += 25;\n  });\n  \n  return score;\n}\n\nfunction calculateCompleteness(data) {\n  const allFields = [\n    'invoice_number', 'invoice_date', 'due_date', 'vendor_name', \n    'vendor_address', 'total_amount', 'subtotal', 'line_items'\n  ];\n  \n  const completedFields = allFields.filter(field => \n    data[field] && data[field] !== 'null' && \n    (Array.isArray(data[field]) ? data[field].length > 0 : true)\n  ).length;\n  \n  return Math.round((completedFields / allFields.length) * 100);\n}\n\nconst cleanedData = cleanAndValidateData(extractedData);\n\nreturn [{\n  json: {\n    ...originalMetadata,\n    extracted_invoice_data: cleanedData,\n    processing_status: 'extracted',\n    updated_at: new Date().toISOString()\n  },\n  binary: inputData.binary // Preserve binary data for potential reprocessing\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "cc08bf61-cb49-4cb5-be64-a9068c7c0486",
      "name": "验证规则引擎",
      "type": "n8n-nodes-base.code",
      "position": [
        2400,
        944
      ],
      "parameters": {
        "jsCode": "// Comprehensive validation rules for invoice data\nconst inputData = $input.all()[0];\nconst invoiceData = inputData.json.extracted_invoice_data;\nconst validationResults = {\n  is_valid: true,\n  errors: [],\n  warnings: [],\n  validation_score: 0,\n  business_rules: {\n    duplicate_check: 'pending',\n    amount_threshold: 'pending',\n    vendor_verification: 'pending',\n    date_validation: 'pending'\n  }\n};\n\n// Required field validation\nconst requiredFields = [\n  { field: 'invoice_number', message: 'Invoice number is required' },\n  { field: 'vendor.name', message: 'Vendor name is required' },\n  { field: 'amounts.total_amount', message: 'Total amount is required' },\n  { field: 'invoice_date', message: 'Invoice date is required' }\n];\n\nrequiredFields.forEach(({ field, message }) => {\n  const value = getNestedValue(invoiceData, field);\n  if (!value || value === 0) {\n    validationResults.errors.push(message);\n    validationResults.is_valid = false;\n  } else {\n    validationResults.validation_score += 20;\n  }\n});\n\n// Date validation\nif (invoiceData.invoice_date && invoiceData.due_date) {\n  const invoiceDate = new Date(invoiceData.invoice_date);\n  const dueDate = new Date(invoiceData.due_date);\n  \n  if (dueDate < invoiceDate) {\n    validationResults.errors.push('Due date cannot be before invoice date');\n    validationResults.is_valid = false;\n  } else {\n    validationResults.business_rules.date_validation = 'passed';\n  }\n} else {\n  validationResults.business_rules.date_validation = 'failed';\n}\n\n// Amount validation\nconst amounts = invoiceData.amounts;\nif (amounts) {\n  // Check if total matches calculation\n  const calculatedTotal = amounts.subtotal + amounts.tax_total + amounts.shipping_amount - amounts.discount_amount;\n  const totalDifference = Math.abs(calculatedTotal - amounts.total_amount);\n  \n  if (totalDifference > 0.01) {\n    validationResults.warnings.push(`Total amount mismatch: Expected ${calculatedTotal.toFixed(2)}, got ${amounts.total_amount.toFixed(2)}`);\n  }\n  \n  // Amount threshold check (configurable)\n  const amountThreshold = 10000; // $10,000\n  if (amounts.total_amount > amountThreshold) {\n    validationResults.business_rules.amount_threshold = 'requires_approval';\n    validationResults.warnings.push(`High amount invoice requires additional approval: $${amounts.total_amount}`);\n  } else {\n    validationResults.business_rules.amount_threshold = 'passed';\n  }\n} else {\n  validationResults.errors.push('Amount information is missing');\n  validationResults.is_valid = false;\n}\n\n// Vendor validation\nif (invoiceData.vendor && invoiceData.vendor.name) {\n  // Simulate vendor verification (in real scenario, check against approved vendor list)\n  const approvedVendors = [\n    'ABC Company Ltd', 'XYZ Corporation', 'Tech Solutions Inc', \n    'Office Supplies Co', 'Consulting Partners LLC'\n  ];\n  \n  const isApprovedVendor = approvedVendors.some(vendor => \n    vendor.toLowerCase().includes(invoiceData.vendor.name.toLowerCase()) ||\n    invoiceData.vendor.name.toLowerCase().includes(vendor.toLowerCase())\n  );\n  \n  if (isApprovedVendor) {\n    validationResults.business_rules.vendor_verification = 'approved';\n    validationResults.validation_score += 15;\n  } else {\n    validationResults.business_rules.vendor_verification = 'new_vendor';\n    validationResults.warnings.push('Vendor not in approved list - requires verification');\n  }\n}\n\n// Line items validation\nif (invoiceData.line_items && invoiceData.line_items.length > 0) {\n  let lineItemErrors = [];\n  \n  invoiceData.line_items.forEach((item, index) => {\n    if (!item.description) {\n      lineItemErrors.push(`Line item ${index + 1}: Missing description`);\n    }\n    if (item.quantity <= 0) {\n      lineItemErrors.push(`Line item ${index + 1}: Invalid quantity`);\n    }\n    if (item.unit_price <= 0) {\n      lineItemErrors.push(`Line item ${index + 1}: Invalid unit price`);\n    }\n    \n    // Check line total calculation\n    const expectedTotal = item.quantity * item.unit_price;\n    if (Math.abs(expectedTotal - item.total) > 0.01) {\n      lineItemErrors.push(`Line item ${index + 1}: Total calculation error`);\n    }\n  });\n  \n  if (lineItemErrors.length > 0) {\n    validationResults.warnings.push(...lineItemErrors);\n  } else {\n    validationResults.validation_score += 10;\n  }\n} else {\n  validationResults.warnings.push('No line items found');\n}\n\n// Duplicate invoice check (simulate database lookup)\nif (invoiceData.invoice_number) {\n  // In real scenario, check against database\n  const existingInvoices = ['INV-001', 'INV-002', 'INV-003']; // Mock data\n  \n  if (existingInvoices.includes(invoiceData.invoice_number)) {\n    validationResults.errors.push('Duplicate invoice number detected');\n    validationResults.business_rules.duplicate_check = 'duplicate';\n    validationResults.is_valid = false;\n  } else {\n    validationResults.business_rules.duplicate_check = 'unique';\n    validationResults.validation_score += 15;\n  }\n}\n\n// Calculate confidence level\nlet confidenceLevel = 'low';\nif (validationResults.validation_score >= 80) confidenceLevel = 'high';\nelse if (validationResults.validation_score >= 60) confidenceLevel = 'medium';\n\n// Determine approval requirements\nlet requiresApproval = false;\nlet approvalReason = [];\n\nif (validationResults.business_rules.amount_threshold === 'requires_approval') {\n  requiresApproval = true;\n  approvalReason.push('High amount');\n}\n\nif (validationResults.business_rules.vendor_verification === 'new_vendor') {\n  requiresApproval = true;\n  approvalReason.push('New vendor');\n}\n\nif (validationResults.errors.length > 0) {\n  requiresApproval = true;\n  approvalReason.push('Validation errors');\n}\n\nfunction getNestedValue(obj, path) {\n  return path.split('.').reduce((current, key) => current?.[key], obj);\n}\n\nreturn [{\n  json: {\n    ...inputData.json,\n    validation_results: validationResults,\n    confidence_level: confidenceLevel,\n    requires_approval: requiresApproval,\n    approval_reasons: approvalReason,\n    processing_status: validationResults.is_valid ? 'validated' : 'validation_failed',\n    validated_at: new Date().toISOString()\n  },\n  binary: inputData.binary // Preserve binary data\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "7980050d-408f-4b3a-8e10-fad41c143eff",
      "name": "需要审批吗?",
      "type": "n8n-nodes-base.switch",
      "position": [
        2704,
        928
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "",
                    "rightValue": ""
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "8d543b5f-9d0a-48b0-9589-d9c9c5a0adb1",
      "name": "审批工作流生成器",
      "type": "n8n-nodes-base.code",
      "position": [
        3008,
        976
      ],
      "parameters": {
        "jsCode": "// Generate approval request with comprehensive details\nconst inputData = $input.all()[0];\nconst invoiceData = inputData.json.extracted_invoice_data;\nconst validation = inputData.json.validation_results;\n\n// Create approval request\nconst approvalRequest = {\n  approval_id: `APPR_${inputData.json.invoice_id}_${Date.now()}`,\n  invoice_id: inputData.json.invoice_id,\n  request_type: 'invoice_approval',\n  priority: determinePriority(inputData.json.approval_reasons),\n  \n  // Invoice summary\n  invoice_summary: {\n    invoice_number: invoiceData.invoice_number,\n    vendor_name: invoiceData.vendor ? invoiceData.vendor.name : 'Unknown',\n    total_amount: invoiceData.amounts ? invoiceData.amounts.total_amount : 0,\n    currency: invoiceData.currency,\n    invoice_date: invoiceData.invoice_date,\n    due_date: invoiceData.due_date\n  },\n  \n  // Approval details\n  approval_reasons: inputData.json.approval_reasons,\n  validation_score: validation.validation_score,\n  confidence_level: inputData.json.confidence_level,\n  \n  // Issues requiring attention\n  attention_required: {\n    errors: validation.errors,\n    warnings: validation.warnings,\n    business_rule_flags: Object.entries(validation.business_rules)\n      .filter(([key, value]) => value === 'requires_approval' || value === 'failed')\n      .map(([key, value]) => ({ rule: key, status: value }))\n  },\n  \n  // Approval workflow\n  workflow_steps: generateApprovalSteps(inputData.json.approval_reasons, invoiceData.amounts ? invoiceData.amounts.total_amount : 0),\n  \n  // Request metadata\n  requested_at: new Date().toISOString(),\n  requested_by: 'system',\n  status: 'pending_approval',\n  \n  // Generate approval message\n  approval_message: generateApprovalMessage(invoiceData, validation, inputData.json.approval_reasons)\n};\n\nfunction determinePriority(reasons) {\n  if (reasons.includes('Validation errors')) return 'high';\n  if (reasons.includes('High amount')) return 'medium';\n  return 'normal';\n}\n\nfunction generateApprovalSteps(reasons, amount) {\n  const steps = [];\n  \n  // Finance team review for high amounts\n  if (amount > 10000) {\n    steps.push({\n      step: 1,\n      approver_role: 'finance_manager',\n      required: true,\n      description: 'Finance manager approval for high-value invoice'\n    });\n  }\n  \n  // Procurement review for new vendors\n  if (reasons.includes('New vendor')) {\n    steps.push({\n      step: steps.length + 1,\n      approver_role: 'procurement_manager',\n      required: true,\n      description: 'Procurement verification for new vendor'\n    });\n  }\n  \n  // Department head approval\n  steps.push({\n    step: steps.length + 1,\n    approver_role: 'department_head',\n    required: true,\n    description: 'Department head final approval'\n  });\n  \n  return steps;\n}\n\nfunction generateApprovalMessage(invoiceData, validation, reasons) {\n  let message = `🧾 **INVOICE APPROVAL REQUEST**\\n\\n`;\n  message += `📋 **Invoice:** ${invoiceData.invoice_number || 'N/A'}\\n`;\n  message += `🏢 **Vendor:** ${invoiceData.vendor ? invoiceData.vendor.name : 'Unknown'}\\n`;\n  \n  const amount = invoiceData.amounts ? invoiceData.amounts.total_amount : 0;\n  const currency = invoiceData.currency || 'USD';\n  message += `💰 **Amount:** ${currency} ${amount.toLocaleString()}\\n`;\n  message += `📅 **Date:** ${invoiceData.invoice_date || 'N/A'}\\n`;\n  message += `⏰ **Due:** ${invoiceData.due_date || 'N/A'}\\n\\n`;\n  \n  message += `🚨 **Approval Required For:**\\n`;\n  reasons.forEach(reason => {\n    message += `• ${reason}\\n`;\n  });\n  \n  if (validation.errors.length > 0) {\n    message += `\\n❌ **Errors:**\\n`;\n    validation.errors.forEach(error => {\n      message += `• ${error}\\n`;\n    });\n  }\n  \n  if (validation.warnings.length > 0) {\n    message += `\\n⚠️ **Warnings:**\\n`;\n    validation.warnings.forEach(warning => {\n      message += `• ${warning}\\n`;\n    });\n  }\n  \n  message += `\\n📊 **Validation Score:** ${validation.validation_score}/100\\n`;\n  message += `🎯 **Confidence:** ${inputData.json.confidence_level.toUpperCase()}\\n\\n`;\n  message += `Please review and approve/reject this invoice.`;\n  \n  return message;\n}\n\nreturn [{\n  json: {\n    ...inputData.json,\n    approval_request: approvalRequest,\n    processing_status: 'pending_approval',\n    updated_at: new Date().toISOString()\n  },\n  binary: inputData.binary // Preserve binary data\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "92ee2ffa-df6f-447c-bc74-bc78a40e90bf",
      "name": "审批通知",
      "type": "n8n-nodes-base.telegram",
      "position": [
        3360,
        912
      ],
      "webhookId": "5075a6ac-bc09-446d-898e-f5bf9b55d10f",
      "parameters": {
        "text": "={{ $json.approval_request.approval_message }}",
        "chatId": "@invoice_approvals",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e2f6f5d5-a8b8-41df-8113-f45242fa2c9f",
      "name": "会计系统集成",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3584,
        912
      ],
      "parameters": {
        "url": "https://your-accounting-system.com/api/invoices",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "invoice_data",
              "value": "={{ JSON.stringify($json.extracted_invoice_data) }}"
            },
            {
              "name": "validation_results",
              "value": "={{ JSON.stringify($json.validation_results) }}"
            },
            {
              "name": "processing_metadata",
              "value": "={{ JSON.stringify({ invoice_id: $json.invoice_id, source: $json.source, processed_at: $json.updated_at }) }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "httpHeaderAuth"
      },
      "typeVersion": 4.2
    },
    {
      "id": "ffadff50-4b5e-4cf0-ad78-3f43b3ab9237",
      "name": "便签 - 触发器",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        -32
      ],
      "parameters": {
        "color": 2,
        "width": 320,
        "height": 1202,
        "content": "# 步骤 1:多输入触发器 📧📁"
      },
      "typeVersion": 1
    },
    {
      "id": "3a13dfe2-a654-434f-b8e0-91ddb685b7c3",
      "name": "便签 - 文件处理器",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1344,
        -32
      ],
      "parameters": {
        "color": 3,
        "width": 320,
        "height": 1202,
        "content": "# 步骤 2:文件处理 🔄"
      },
      "typeVersion": 1
    },
    {
      "id": "74fde2b5-236f-4e42-a98b-d1a7c43bc9ae",
      "name": "便签 - AI 提取",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1664,
        -32
      ],
      "parameters": {
        "color": 4,
        "width": 320,
        "height": 1202,
        "content": "# 步骤 3:AI 发票提取 🤖"
      },
      "typeVersion": 1
    },
    {
      "id": "6f42014e-fe4b-4424-9a29-e73f1fc4575f",
      "name": "便签 - 数据清理",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1984,
        -32
      ],
      "parameters": {
        "color": 5,
        "width": 320,
        "height": 1202,
        "content": "# 步骤 4:数据清理与增强 🧹"
      },
      "typeVersion": 1
    },
    {
      "id": "3950a900-13c8-4aa5-b128-e9397220ab52",
      "name": "便签 - 验证",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2304,
        -32
      ],
      "parameters": {
        "color": 6,
        "width": 320,
        "height": 1202,
        "content": "# 步骤 5:业务规则验证 ✅"
      },
      "typeVersion": 1
    },
    {
      "id": "daf3f597-b104-4c4c-abaf-5363f982a7a0",
      "name": "便签 - 审批路由",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2624,
        -32
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 1202,
        "content": "# 步骤 6:审批路由 🔀"
      },
      "typeVersion": 1
    },
    {
      "id": "b0e3beae-27ec-4543-8be6-b68b3c8ef89d",
      "name": "便签 - 审批工作流",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2944,
        -32
      ],
      "parameters": {
        "width": 320,
        "height": 1202,
        "content": "# 步骤 7:审批工作流 👥"
      },
      "typeVersion": 1
    },
    {
      "id": "cd228530-faa8-4685-a2dd-505ca1d2d2ff",
      "name": "便签 - 系统集成",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3264,
        -32
      ],
      "parameters": {
        "color": 4,
        "width": 544,
        "height": 1202,
        "content": "# 步骤 8:系统集成 🔗"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "7e6fed6c-3ee0-42af-988e-fb8c404015b5",
  "connections": {
    "Email Trigger": {
      "main": [
        [
          {
            "node": "File Processor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "File Processor": {
      "main": [
        [
          {
            "node": "ScrapeGraphAI - Invoice Extractor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Approval Required?": {
      "main": [
        [
          {
            "node": "Approval Workflow Generator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "File Upload Webhook": {
      "main": [
        [
          {
            "node": "File Processor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Approval Notification": {
      "main": [
        [
          {
            "node": "Accounting System Integration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validation Rules Engine": {
      "main": [
        [
          {
            "node": "Approval Required?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Data Extractor & Cleaner": {
      "main": [
        [
          {
            "node": "Validation Rules Engine",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Approval Workflow Generator": {
      "main": [
        [
          {
            "node": "Approval Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ScrapeGraphAI - Invoice Extractor": {
      "main": [
        [
          {
            "node": "Data Extractor & Cleaner",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

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

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

高级 - 发票处理, AI 摘要总结

需要付费吗?

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

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

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

外部链接
在 n8n.io 查看

分享此工作流