8
n8n 中文网amn8n.com

从ClickUp文档到Airtable记录的自动化内容迁移

高级

这是一个Content Creation, Multimodal AI领域的自动化工作流,包含 16 个节点。主要使用 Code, ClickUp, Airtable, HttpRequest, ClickUpTrigger 等节点。 从ClickUp文档到Airtable记录的自动化内容迁移

前置要求
  • Airtable API Key
  • 可能需要目标 API 的认证凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "meta": {
    "instanceId": "43bcb00c7c923df4e36c0bf713549f86f2dbcd6776a5aa1796b3cf9b1cdd7b7e"
  },
  "nodes": [
    {
      "id": "54d8ddeb-a96a-45d9-82f6-092f4fe2b738",
      "name": "遍历页面",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -368,
        224
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "cacb5309-604f-43d1-b173-d99268f2571d",
      "name": "获取所有基础",
      "type": "n8n-nodes-base.airtable",
      "position": [
        -144,
        144
      ],
      "parameters": {
        "options": {},
        "resource": "base"
      },
      "credentials": {
        "airtableTokenApi": {
          "id": "g8X0PZu8dIVZ4LyX",
          "name": "Airtable Personal Access Token account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "0372b7b0-5c72-437d-afcb-669b2b28bd26",
      "name": "新 Clickup 任务触发",
      "type": "n8n-nodes-base.clickUpTrigger",
      "position": [
        -1712,
        224
      ],
      "webhookId": "ffa9e6e1-45a2-4be0-93c8-1435de0bd7cf",
      "parameters": {
        "team": "9014329600",
        "events": [
          "taskCreated"
        ],
        "filters": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "clickUpOAuth2Api": {
          "id": "cpNaV1HxXYDutqlG",
          "name": "ClickUp account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "db22385e-cd6a-4b74-83d1-7cd81ec46666",
      "name": "获取任务详情",
      "type": "n8n-nodes-base.clickUp",
      "position": [
        -1456,
        224
      ],
      "parameters": {
        "id": "={{ $json.task_id }}",
        "operation": "get",
        "authentication": "oAuth2"
      },
      "credentials": {
        "clickUpOAuth2Api": {
          "id": "cpNaV1HxXYDutqlG",
          "name": "ClickUp account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2794d633-ffd8-4821-abca-0b82858a0852",
      "name": "从 URL 提取文档和工作区 ID",
      "type": "n8n-nodes-base.code",
      "position": [
        -1248,
        224
      ],
      "parameters": {
        "jsCode": "const results = [];\n\nfor (const item of $input.all()) {\n  const url = item.json.name;\n\n  const regex = /clickup\\.com\\/(\\d+)\\/v\\/dc\\/([^/]+)/;\n  const match = url.match(regex);\n\n  if (match) {\n    results.push({\n      json: {\n        clickupUrl: url,\n        workspaceId: match[1],\n        docId: match[2],\n      }\n    });\n  }\n}\n\nreturn results;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "323e614d-7ad9-4265-8981-0cd444a42a67",
      "name": "获取 ClickUp 文档详情",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1024,
        224
      ],
      "parameters": {
        "url": "=https://api.clickup.com/api/v3/workspaces/{{$json.workspaceId}}/docs/{{$json.docId}}",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "max_page_depth",
              "value": "-2"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "accept",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "clickUpApi"
      },
      "credentials": {
        "clickUpOAuth2Api": {
          "id": "cpNaV1HxXYDutqlG",
          "name": "ClickUp account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "b80b1a8d-c8dd-4f62-8475-850408a43abb",
      "name": "获取文档中的所有页面",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -800,
        224
      ],
      "parameters": {
        "url": "=https://api.clickup.com/api/v3/workspaces/{{$json.workspace_id}}/docs/{{$json.id}}/pages",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "max_page_depth",
              "value": "-2"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "accept",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "clickUpOAuth2Api"
      },
      "credentials": {
        "clickUpOAuth2Api": {
          "id": "cpNaV1HxXYDutqlG",
          "name": "ClickUp account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "ae7a5381-c1de-4417-9472-fc7478b1bdab",
      "name": "从文档页面解析内容",
      "type": "n8n-nodes-base.code",
      "position": [
        -576,
        224
      ],
      "parameters": {
        "jsCode": "const output = [];\n\nfor (const item of $input.all()) {\n  const pages = item.json.pages || [];\n  const tableName = item.json.name;\n  const baseName = $('Get ClickUp Doc Details').first().json.name;\n\n  for (const page of pages) {\n    const rawContent = page.content || \"\";\n    const content = rawContent.trim();\n\n    if (content.includes(\"* * *\")) {\n      const splitContents = content.split(\"* * *\");\n\n      for (const part of splitContents) {\n        const trimmed = part.trim();\n        if (!trimmed) continue;\n\n        let contentText = trimmed;\n        let notesText = \"\";\n\n        if (trimmed.toLowerCase().includes(\"notes:\")) {\n          const [main, ...notesParts] = trimmed.split(/notes:/i);\n          contentText = main.trim();\n          notesText = notesParts.join(\"notes:\").trim();\n        }\n\n        // Remove all '*' and re-trim\n        contentText = contentText.replace(/\\*/g, '').trim();\n\n        output.push({\n          json: {\n            base: baseName,\n            table: tableName,\n            name: page.name,\n            content: contentText,\n            notes: notesText\n          }\n        });\n      }\n    } else {\n      let contentText = content;\n      let notesText = \"\";\n\n      if (content.toLowerCase().includes(\"notes:\")) {\n        const [main, ...notesParts] = content.split(/notes:/i);\n        contentText = main.trim();\n        notesText = notesParts.join(\"notes:\").trim();\n      }\n\n      // Remove all '*' and re-trim\n      contentText = contentText.replace(/\\*/g, '').trim();\n\n      output.push({\n        json: {\n          base: baseName,\n          table: tableName,\n          name: page.name,\n          content: contentText,\n          notes: notesText\n        }\n      });\n    }\n  }\n}\n\nreturn output;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "9c8d6ff9-3f60-4576-886a-6ac21a38e247",
      "name": "按名称匹配 Airtable 基础",
      "type": "n8n-nodes-base.code",
      "position": [
        80,
        144
      ],
      "parameters": {
        "jsCode": "const baseRaw = $('Loop Over Pages').first().json.base.trim().toLowerCase();\nconst base = baseRaw.endsWith(' (new)')\n  ? baseRaw.slice(0, -6)\n  : baseRaw;\n\n\n\nconst output = [];\n\nfor (const item of $input.all()) {\nlet itemNameRaw = item.json.name?.trim().toLowerCase();\nconst itemName = itemNameRaw?.endsWith(' (new)')\n  ? itemNameRaw.slice(0, -6)\n  : itemNameRaw;\n  if (base === itemName) {\n    output.push(item);\n  }\n}\n\nreturn output;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "48f0e7b2-eb72-424f-9525-49777ca4dbdf",
      "name": "获取选定基础中的所有表",
      "type": "n8n-nodes-base.airtable",
      "position": [
        304,
        144
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "resource": "base",
        "operation": "getSchema"
      },
      "credentials": {
        "airtableTokenApi": {
          "id": "g8X0PZu8dIVZ4LyX",
          "name": "Airtable Personal Access Token account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "fdc103b4-55a5-401d-93d9-31a586527e9c",
      "name": "按名称匹配 Airtable 表",
      "type": "n8n-nodes-base.code",
      "position": [
        528,
        144
      ],
      "parameters": {
        "jsCode": "const table = $('Loop Over Pages').first().json.table.trim().toLowerCase();\n\nconst output = [];\n\nfor (const item of $input.all()) {\n  const itemName = item.json.name?.trim().toLowerCase();\n\n if (table === itemName) {\n    output.push(item);\n  }\n }\n\nreturn output;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "b55b9fb5-3457-4eb0-8d8c-8ec5c0ef68cf",
      "name": "查找相应的“垂直”记录",
      "type": "n8n-nodes-base.airtable",
      "position": [
        752,
        144
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Match Airtable Base by Name').item.json.id }}"
        },
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Get All Tables in Selected Base').first().json.id }}"
        },
        "options": {
          "fields": [
            "Name"
          ]
        },
        "operation": "search",
        "filterByFormula": "={Name} = '{{ $('Loop Over Pages').item.json.name }}'"
      },
      "credentials": {
        "airtableTokenApi": {
          "id": "g8X0PZu8dIVZ4LyX",
          "name": "Airtable Personal Access Token account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "74d12946-602f-4064-927f-e3be32329a3a",
      "name": "在 Airtable 中创建新记录",
      "type": "n8n-nodes-base.airtable",
      "position": [
        960,
        224
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Match Airtable Base by Name').item.json.id }}"
        },
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Match Airtable Table by Name').item.json.id }}"
        },
        "columns": {
          "value": {
            "Text": "={{ $('Loop Over Pages').item.json.content }}",
            "Notes": "={{ $('Loop Over Pages').item.json.notes }}",
            "Status": "Testing",
            "Vertical": "={{ $json.Name }}",
            "Created Date": "={{ $now }}"
          },
          "schema": [
            {
              "id": "Text",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Text",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Vertical",
              "type": "array",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Vertical",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "options",
              "display": true,
              "options": [
                {
                  "name": "Testing",
                  "value": "Testing"
                },
                {
                  "name": "Winner",
                  "value": "Winner"
                },
                {
                  "name": "Non-Compliant (Buyer)",
                  "value": "Non-Compliant (Buyer)"
                },
                {
                  "name": "Rejected (FB)",
                  "value": "Rejected (FB)"
                },
                {
                  "name": "Account Mover",
                  "value": "Account Mover"
                },
                {
                  "name": "Loser",
                  "value": "Loser"
                },
                {
                  "name": "Rejected (Appealed)",
                  "value": "Rejected (Appealed)"
                }
              ],
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Notes",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Notes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Created Date",
              "type": "dateTime",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Created Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "typecast": true
        },
        "operation": "create"
      },
      "credentials": {
        "airtableTokenApi": {
          "id": "g8X0PZu8dIVZ4LyX",
          "name": "Airtable Personal Access Token account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "a65db100-fb6b-46c0-b69f-8b005428e1c6",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2544,
        -1184
      ],
      "parameters": {
        "width": 688,
        "height": 1264,
        "content": "## 从新的 ClickUp 文档页面创建 Airtable 记录"
      },
      "typeVersion": 1
    },
    {
      "id": "d1610a6f-0ed6-4060-a25a-35562abb42ab",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1760,
        128
      ],
      "parameters": {
        "color": 4,
        "width": 1328,
        "height": 256,
        "content": "## 获取 Clickup 任务、文档和页面内容"
      },
      "typeVersion": 1
    },
    {
      "id": "f8ef9da3-4581-4974-9c5d-3fb55cb4cf8c",
      "name": "便签2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -224,
        80
      ],
      "parameters": {
        "color": 4,
        "width": 1360,
        "height": 352,
        "content": "## 将所有内容移动到 Airtable"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "Get All Base": {
      "main": [
        [
          {
            "node": "Match Airtable Base by Name",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Pages": {
      "main": [
        [],
        [
          {
            "node": "Get All Base",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Task Details": {
      "main": [
        [
          {
            "node": "Extract Doc & Workspace IDs from URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch All Pages in Doc": {
      "main": [
        [
          {
            "node": "Parse Content from Doc Pages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get ClickUp Doc Details": {
      "main": [
        [
          {
            "node": "Fetch All Pages in Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Match Airtable Base by Name": {
      "main": [
        [
          {
            "node": "Get All Tables in Selected Base",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger on New Clickup Task": {
      "main": [
        [
          {
            "node": "Get Task Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Match Airtable Table by Name": {
      "main": [
        [
          {
            "node": "Find Corresponding \"Vertical\" Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Content from Doc Pages": {
      "main": [
        [
          {
            "node": "Loop Over Pages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create New Record in Airtable": {
      "main": [
        [
          {
            "node": "Loop Over Pages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get All Tables in Selected Base": {
      "main": [
        [
          {
            "node": "Match Airtable Table by Name",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Doc & Workspace IDs from URL": {
      "main": [
        [
          {
            "node": "Get ClickUp Doc Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Corresponding \"Vertical\" Record": {
      "main": [
        [
          {
            "node": "Create New Record in Airtable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

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

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

高级 - 内容创作, 多模态 AI

需要付费吗?

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

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

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

作者
Fahmi Fahreza

Fahmi Fahreza

@fahmiiireza

Backend Developer turns to AI Automation Developer

外部链接
在 n8n.io 查看

分享此工作流