This workflow follows the Datatable → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "DEEPP AUTO P1 V3 - Worker (Front)",
"nodes": [
{
"parameters": {
"url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/getFile",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "file_id",
"value": "={{ $json.file_id }}"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
-20768,
-3648
],
"id": "aacb2a2e-3158-469b-9f14-28bc371e0cff",
"name": "HTTP Request - Telegram Get File"
},
{
"parameters": {
"url": "=https://api.telegram.org/file/bot{{ $env.TELEGRAM_BOT_TOKEN }}/{{ $json.result.file_path }}",
"options": {
"response": {
"response": {
"responseFormat": "file"
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
-20624,
-3648
],
"id": "ab3a58f1-b81b-4211-98e0-33bbee07e2e2",
"name": "HTTP Request - Telegram Download File"
},
{
"parameters": {
"jsCode": "// \u8d70\u5230\u8fd9\u4e00\u6b65\u7684binary,\u4e0d\u7ba1\u6765\u6e90\u662f\u539f\u59cb\u7167\u7247\u3001\u8fd8\u662fPDF\u8f6c\u51fa\u6765\u7684\u9875\u9762\u56fe\u7247,\n// \u5168\u90e8\u90fd\u5df2\u7ecf\u662fJPG\u4e86,\u4e0d\u7528\u518d\u56de\u5934\u5224\u65ad\u539f\u59cbmime_type\u662f\u4ec0\u4e48\nconst items = $input.all();\n\nfor (const item of items) {\n if (item.binary) {\n for (const key of Object.keys(item.binary)) {\n item.binary[key].mimeType = 'image/jpeg';\n }\n }\n}\n\nreturn items;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-19488,
-3312
],
"id": "a33c9529-7c45-4738-8192-5e1cb92fb642",
"name": "\u4fee\u6b63\u56fe\u7247MimeType"
},
{
"parameters": {
"jsCode": "// \u628a\u591a\u4e2a\"\u5404\u81ea\u5e26\u4e00\u4e2a\u6863\u6848(\u56fe\u7247\u6216PDF)\"\u7684item,\u5408\u5e76\u6210\"\u4e00\u4e2aitem\u3001\u5185\u542b\u591a\u4e2a\u6863\u6848\"\n// (\u7eaf\u6587\u5b57\u60c5\u5883\u4e0b,items\u91cc\u53ef\u80fd\u5b8c\u5168\u6ca1\u6709binary,\u8981\u80fd\u6b63\u786e\u5904\u7406)\nconst items = $input.all();\n\nconst mergedBinary = {};\nitems.forEach((item, index) => {\n if (item.binary && item.binary.data) {\n mergedBinary[`file_${index}`] = item.binary.data;\n }\n});\n\n// \u56de\u5934\u6307\u540d\u53bb\u6293\u6700\u65e9\u90a3\u4e2anode,\u62ffchat_id\u8ddftext_content\nconst sourceData = $('\u89e3\u6790Router\u4f20\u6765\u7684items').first().json;\n\nreturn [{\n json: {\n chat_id: sourceData.chat_id,\n text_content: sourceData.text_content,\n fileCount: Object.keys(mergedBinary).length\n },\n binary: mergedBinary\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-19120,
-3680
],
"id": "5f0fde74-0052-4f84-83db-e2838c58c87e",
"name": "\u6c47\u5408\u6210\u4e00\u4e2aitem\u7684Code node"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "d49faa9c-ca86-41c6-9124-24cb929683f8",
"leftValue": "={{ $('\u89e3\u6790Router\u4f20\u6765\u7684items').item.json.mime_type }}",
"rightValue": "application/pdf",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
-20480,
-3648
],
"id": "967f38ca-0cb2-407d-b2a5-eba4cfdc5683",
"name": "\u662f\u5426\u4e3aPDF"
},
{
"parameters": {
"operation": "write",
"fileName": "=/home/node/files/{{ $('\u89e3\u6790Router\u4f20\u6765\u7684items').item.json.file_id }}.pdf",
"options": {}
},
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1.1,
"position": [
-20224,
-3664
],
"id": "1acd87f0-4e59-4408-9faf-63c56a26405a",
"name": "\u5199\u5165PDF\u5230\u78c1\u76d8"
},
{
"parameters": {
"command": "=pdftoppm -jpeg -r 150 /home/node/files/{{ $('\u89e3\u6790Router\u4f20\u6765\u7684items').item.json.file_id }}.pdf /home/node/files/{{ $('\u89e3\u6790Router\u4f20\u6765\u7684items').item.json.file_id }}"
},
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
-20016,
-3664
],
"id": "bfc1a9c8-e274-4c13-8082-cafee379d79f",
"name": "Execute Command"
},
{
"parameters": {
"fileSelector": "=/home/node/files/{{ $('\u89e3\u6790Router\u4f20\u6765\u7684items').item.json.file_id }}-*.jpg",
"options": {}
},
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1.1,
"position": [
-19808,
-3664
],
"id": "fd7affcc-af05-4e24-bd18-2d0f2d808985",
"name": "Read/Write Files from Disk"
},
{
"parameters": {
"jsCode": "// \u56fa\u5b9a\u7ed9\u8fd9\u4e2aworkflow\u7684\u4ee3\u53f7,\u4e4b\u540e\u590d\u5236\u6210worker2/worker3\u65f6,\u53ea\u9700\u8981\u6539\u8fd9\u4e00\u884c\nconst BOT_ID = 'worker1';\n\n// \u7528\u9a6c\u6765\u897f\u4e9a\u65f6\u95f4\u53d6\"\u4eca\u5929\"\u7684\u65e5\u671f(\u7c97\u7565\u5bf9\u9f50,\u4e0d\u8ffd\u6c42\u8ddfGoogle\u90a3\u8fb9\u7cbe\u786e\u540c\u6b65\u91cd\u7f6e\u65f6\u95f4)\nconst now = new Date();\nconst malaysiaDate = new Intl.DateTimeFormat('en-CA', {\n timeZone: 'Asia/Kuala_Lumpur',\n year: 'numeric', month: '2-digit', day: '2-digit'\n}).format(now); // \u683c\u5f0f\u7c7b\u4f3c 2026-07-24\n\nconst usageKey = `${BOT_ID}_${malaysiaDate}`;\n\nconst items = $input.all();\nfor (const item of items) {\n item.json.bot_id = BOT_ID;\n item.json.usage_date = malaysiaDate;\n item.json.usage_key = usageKey;\n}\n\nreturn items;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-18960,
-3680
],
"id": "942fdc04-a7c5-496c-be2f-b889649affdd",
"name": "\u7b97\u51fausage_key"
},
{
"parameters": {
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "xe1tWUcTzVf19IBn",
"mode": "list",
"cachedResultName": "daily_usage",
"cachedResultUrl": "/projects/W1Bzh2H8JZecMoTf/datatables/xe1tWUcTzVf19IBn"
},
"filters": {
"conditions": [
{
"keyName": "usage_key",
"keyValue": "={{ $json.usage_key }}"
}
]
}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-18784,
-3680
],
"id": "0786aa20-f33b-4559-b295-5c1563ed51b2",
"name": "\u67e5\u770busage_key",
"alwaysOutputData": true
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "ceec15b3-1123-4f7b-81cf-e8bceeb5f46b",
"leftValue": "={{ $json.over_limit }}",
"rightValue": "",
"operator": {
"type": "boolean",
"operation": "false",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
-18400,
-3680
],
"id": "516bd72c-1dd5-4c92-8425-728568ea96a2",
"name": "\u662f\u5426\u591f\u6b21\u6570"
},
{
"parameters": {
"jsCode": "// \u67e5usage_key\u7684\u7ed3\u679c:\u5982\u679c\u4eca\u5929\u7b2c\u4e00\u6b21\u7528,Data Table\u91cc\u8fd8\u6ca1\u6709\u8fd9\u884c\u8d44\u6599,\n// Get\u4f1a\u67e5\u52300\u7b14,\u8fd9\u91cc\u5f53\u4f5ccount=0\u5904\u7406\nconst usageRows = $input.all();\nconst currentCount = usageRows.length > 0 ? (usageRows[0].json.count || 0) : 0;\n\nconst THRESHOLD = 15; // \u6bcf\u65e5\u4e0a\u9650,\u5148\u6293\u4fdd\u5b88\u4e00\u70b9\n\n// \u771f\u6b63\u8981\u7ee7\u7eed\u5f80\u4e0b\u8d70\u7684\u8d44\u6599(chat_id\u3001text_content\u3001\u56fe\u7247binary),\n// \u8981\u56de\u5934\u53bb\u6293\"\u7b97\u51fausage_key\"\u90a3\u4e00\u6b65\u7684\u8f93\u51fa,\u4e0d\u80fd\u76f4\u63a5\u7528\u8fd9\u91cc\u7684$input\n// (\u56e0\u4e3aData Table\u8282\u70b9\u4f1a\u628abinary\u6863\u6848\u5f04\u4e22,\u53ea\u7559json)\nconst sourceItems = $('\u7b97\u51fausage_key').all();\n\nfor (const item of sourceItems) {\n item.json.current_count = currentCount;\n item.json.over_limit = currentCount >= THRESHOLD;\n}\n\nreturn sourceItems;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-18592,
-3680
],
"id": "e180fbd6-0967-46b5-9a9d-f552a01fb652",
"name": "\u5224\u65ad\u662f\u5426\u591f\u6b21\u6570",
"alwaysOutputData": false
},
{
"parameters": {
"url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "chat_id",
"value": "={{ $json.chat_id }}"
},
{
"name": "text",
"value": "\u300c\u4eca\u65e5\u5904\u7406\u91cf\u5df2\u8fbe\u4e0a\u9650\uff0c\u8bf7\u660e\u5929\u518d\u8bd5 \ud83d\ude4f\u300d"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
-18144,
-3264
],
"id": "8ed45370-550b-44c1-ac3e-7d12aeff812a",
"name": "\u53d1\u9001\u989d\u5ea6\u5df2\u6ee1\u8baf\u606f"
},
{
"parameters": {
"jsCode": "const item = $input.first();\nconst sourceData = $('\u6c47\u5408\u6210\u4e00\u4e2aitem\u7684Code node').first().json; // chat_id, text_content\nconst usageData = $('\u5224\u65ad\u662f\u5426\u591f\u6b21\u6570').first().json; // bot_id\n\nconst binaryKeys = Object.keys(item.binary || {});\nconst parts = [];\n\nfor (const key of binaryKeys) {\n const buffer = await this.helpers.getBinaryDataBuffer(0, key);\n const base64Data = buffer.toString('base64');\n const mimeType = item.binary[key].mimeType || 'image/jpeg';\n parts.push({\n inline_data: {\n mime_type: mimeType,\n data: base64Data\n }\n });\n}\n\nconst captionText = sourceData.text_content\n ? `\u5546\u5bb6\u5907\u6ce8\uff1a${sourceData.text_content}`\n : '\uff08\u5546\u5bb6\u8fd9\u6b21\u6ca1\u6709\u63d0\u4f9b\u989d\u5916\u5907\u6ce8\uff09';\n\n// \u53ea\u5728\u8bc4\u5206\"\u786e\u5b9e\u504f\u4f4e\"(<=2\u661f)\u7684\u65f6\u5019\u624d\u63d0\u9192AI\u66f4\u4ed4\u7ec6\u2014\u2014\n// \u5546\u5bb6\u5fd8\u8bb0\u8bc4\u5206\u3001\u6216\u8bc4\u52063\u661f\u4ee5\u4e0a,\u4e00\u5f8b\u5f53\u4f5c\u6ca1\u8fd9\u56de\u4e8b,\u4e0d\u989d\u5916\u52a0\u63d0\u793a\u8bed,\n// \u4e0d\u80fd\u8ba9AI\u56e0\u4e3a\"\u4ee5\u4e3a\u81ea\u5df1\u4e0a\u6b21\u8868\u73b0\u4e0d\u597d\"\u800c\u4ea7\u751f\u4e0d\u5fc5\u8981\u7684\u8d1f\u9762\u504f\u5dee\nconst ratingRow = $('\u67e5\u5546\u5bb6\u8bc4\u5206').first().json;\nconst stars = ratingRow.stars;\nconst qualityHint = (typeof stars === 'number' && stars <= 2)\n ? '\\n\\n\u63d0\u9192\uff1a\u8fd9\u4f4d\u5546\u5bb6\u4e0a\u6b21\u7ed9\u7684\u8bc4\u4ef7\u4e0d\u9ad8,\u8fd9\u6b21\u8bf7\u7279\u522b\u4ed4\u7ec6\u6838\u5bf9\u6bcf\u4e2a\u54c1\u9879\u7684\u540d\u79f0\u3001\u5206\u7c7b\u3001\u4ef7\u683c,\u786e\u4fdd\u4fe1\u606f\u51c6\u786e\u5b8c\u6574\u3002'\n : '';\n\nconst promptText = `\u4f60\u662f\"Heng_MenuTransfer_bot\"\uff0c\u4e13\u95e8\u5e2e\u52a9\u9910\u996e\u5546\u5bb6\u628a\u83dc\u5355\u8f6c\u6362\u6210POS\u7cfb\u7edf\u53ef\u5bfc\u5165\u7684Excel\u6587\u4ef6\u3002\n\n\u4f60\u4f1a\u6536\u5230\u4e00\u5f20\u6216\u591a\u5f20\u83dc\u5355\u56fe\u7247(\u4e5f\u53ef\u80fd\u5b8c\u5168\u6ca1\u6709\u56fe\u7247,\u5546\u5bb6\u76f4\u63a5\u7528\u6587\u5b57\u63cf\u8ff0\u6574\u4efd\u83dc\u5355)\uff0c\u4ee5\u53ca\u5546\u5bb6\u53ef\u80fd\u63d0\u4f9b\u7684\u989d\u5916\u5907\u6ce8\u6587\u5b57\u3002\n\n\u4f60\u7684\u4efb\u52a1\uff1a\n1. \u4ed4\u7ec6\u9605\u8bfb\u6240\u6709\u56fe\u7247\u5185\u5bb9\uff0c\u8bc6\u522b\u51fa\u5168\u90e8\u5546\u54c1\uff0c\u6574\u7406\u51fa\u6bcf\u4e2a\u5546\u54c1\u7684\uff1a\n name(\u540d\u79f0)\u3001category(\u5206\u7c7b)\u3001spec(\u89c4\u683c\uff0c\u9009\u586b)\u3001stock_qty(\u5e93\u5b58\u91cf\uff0c\u9009\u586b)\u3001\n cost_price(\u8fdb\u8d27\u4ef7\uff0c\u9009\u586b\uff0c\u7f3a\u4e86\u76f4\u63a5\u7559\u7a7a\u5373\u53ef)\u3001sell_price(\u9500\u552e\u4ef7)\n2. \u5224\u65adname\u3001category\u3001sell_price\u8fd9\u4e09\u4e2a\u680f\u4f4d\uff0c\u662f\u5426\u6bcf\u4e2a\u54c1\u9879\u90fd\u586b\u5f97\u51fa\u6765\n3. \u5982\u679c\u5546\u5bb6\u63d0\u4f9b\u4e86\u989d\u5916\u5907\u6ce8\uff08\u6bd4\u5982\u5916\u5e26\u52a0\u4ef7\u3001\u5206\u7c7b\u89c4\u5219\u7b49\uff09\uff0c\u7eb3\u5165\u5224\u65ad\uff1b\n \u5982\u679c\u5907\u6ce8\u8ddf\u5546\u54c1\u8d44\u6599\u6709\u51b2\u7a81\u6216\u770b\u4e0d\u61c2\u8be5\u600e\u4e48\u5957\u7528\uff0c\u4e00\u6837\u5f52\u7c7b\u4e3a\u4fe1\u606f\u4e0d\u5b8c\u6574\n\n${captionText}${qualityHint}\n\n\u8bf7\u4e25\u683c\u53ea\u8f93\u51fa\u4ee5\u4e0bJSON\u683c\u5f0f\uff0c\u4e0d\u8981\u4efb\u4f55\u89e3\u91ca\u6587\u5b57\u3001\u4e0d\u8981markdown\u4ee3\u7801\u5757\u6807\u8bb0\uff1a\n{\n \"status\": \"complete \u6216 incomplete\",\n \"items\": [{\"name\":\"\u5546\u54c1\u540d\",\"category\":\"\u5206\u7c7b\",\"spec\":\"\u89c4\u683c\",\"stock_qty\":0,\"cost_price\":0,\"sell_price\":0.00}],\n \"question\": \"\u53ea\u6709status\u662fincomplete\u65f6\u624d\u9700\u8981\u8fd9\u4e2a\u680f\u4f4d\uff0c\u9488\u5bf9\u6027\u5730\u95ee\u7528\u6237\u7f3a\u7684\u662f\u4ec0\u4e48\"\n}`;\n\nconst geminiRequest = {\n contents: [{\n parts: [\n { text: promptText },\n ...parts\n ]\n }]\n};\n\nreturn [{\n json: {\n chat_id: sourceData.chat_id,\n bot_id: usageData.bot_id,\n geminiRequest: geminiRequest\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-18192,
-3696
],
"id": "731b484e-5c87-4473-87e6-455593416b43",
"name": "\u7ec4\u88c5Gemini\u8bf7\u6c42"
},
{
"parameters": {
"method": "POST",
"url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-flash:generateContent",
"authentication": "genericCredentialType",
"genericAuthType": "httpQueryAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ $json.geminiRequest }}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
-18016,
-3696
],
"id": "b34fb1c5-fca2-42fb-9e1b-aea3148c4de2",
"name": "HTTP Request",
"credentials": {
"httpQueryAuth": {
"name": "<your credential>"
}
},
"onError": "continueRegularOutput"
},
{
"parameters": {
"jsCode": "const item = $input.first().json;\nconst chatId = $('\u7ec4\u88c5Gemini\u8bf7\u6c42').first().json.chat_id;\nconst botId = $('\u7ec4\u88c5Gemini\u8bf7\u6c42').first().json.bot_id;\n\nconst notifyFailure = async (reason) => {\n await this.helpers.httpRequest({\n method: 'POST',\n url: `https://api.telegram.org/bot${$env.TELEGRAM_BOT_TOKEN}/sendMessage`,\n headers: { 'Content-Type': 'application/json' },\n body: { chat_id: chatId, text: `\u274c \u5904\u7406\u5931\u8d25\uff1a${reason}` },\n json: true\n });\n};\n\n// \u68c0\u67e5\u8bf7\u6c42\u672c\u8eab\u662f\u5426\u5931\u8d25(\u7f51\u7edc\u9519\u8bef\u3001Gemini\u62d2\u7edd\u7b49)\nif (item.error || !item.candidates || item.candidates.length === 0) {\n const errMsg = item.error?.message || '';\n let reason = 'AI \u670d\u52a1\u6682\u65f6\u51fa\u73b0\u95ee\u9898\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5\u3002';\n if (errMsg.includes('quota') || errMsg.includes('rate') || errMsg.includes('429')) {\n reason = 'AI \u8bf7\u6c42\u6b21\u6570\u5df2\u8fbe\u4e0a\u9650\uff0c\u8bf7\u7b49\u5f85\u7ea61\u5206\u949f\u540e\u91cd\u65b0\u53d1\u9001\u3002';\n } else if (errMsg.includes('unavailable') || errMsg.includes('overload') || errMsg.includes('high demand') || errMsg.includes('503')) {\n reason = 'AI \u670d\u52a1\u5668\u76ee\u524d\u6d41\u91cf\u8fc7\u9ad8\uff0c\u8bf7\u7b49\u5f85\u7ea61\u5206\u949f\u540e\u91cd\u65b0\u53d1\u9001\u3002';\n }\n await notifyFailure(reason);\n return []; // \u5931\u8d25\u65f6\u4e0d\u5f80\u4e0b\u8d70,\u589e\u52a0\u4eca\u65e5\u6b21\u6570\u4e5f\u4e0d\u4f1a\u88ab\u89e6\u53d1\n}\n\nlet parsed;\ntry {\n const rawText = item.candidates[0].content.parts[0].text;\n const cleaned = rawText.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\n parsed = JSON.parse(cleaned);\n} catch (err) {\n // Gemini\u5076\u5c14\u4f1a\u5939\u5e26\u89e3\u91ca\u6587\u5b57\u3001\u6216\u56de\u5e94\u7ed3\u6784\u8ddf\u9884\u671f\u4e0d\u4e00\u6837,JSON.parse\u4f1a\u76f4\u63a5throw,\n // \u4e00\u5f8b\u63a5\u4f4f,\u4e0d\u8ba9\u6574\u4e2anode\u5d29\u6389\u3001\u5546\u5bb6\u6536\u4e0d\u5230\u4efb\u4f55\u56de\u5e94\n await notifyFailure('AI\u56de\u5e94\u683c\u5f0f\u5f02\u5e38\uff0c\u8bf7\u91cd\u65b0\u53d1\u9001\u4e00\u6b21\u3002');\n return [];\n}\n\nconst fileCount = $('\u6c47\u5408\u6210\u4e00\u4e2aitem\u7684Code node').first().json.fileCount;\nconst imagePaths = Array.from({length: fileCount}, (_, i) => `/home/node/files/session_${chatId}_${i}.jpg`);\n\nreturn [{\n json: {\n chat_id: chatId,\n bot_id: botId,\n status: parsed.status,\n items: parsed.items || [],\n question: parsed.question || '',\n image_paths: JSON.stringify(imagePaths)\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-17840,
-3696
],
"id": "77fb4801-12fc-403a-a92e-1dedcfde6cbc",
"name": "\u89e3\u6790Gemini\u56de\u5e94"
},
{
"parameters": {
"operation": "upsert",
"dataTableId": {
"__rl": true,
"value": "xe1tWUcTzVf19IBn",
"mode": "list",
"cachedResultName": "daily_usage",
"cachedResultUrl": "/projects/W1Bzh2H8JZecMoTf/datatables/xe1tWUcTzVf19IBn"
},
"filters": {
"conditions": [
{
"keyName": "usage_key",
"keyValue": "={{ $('\u5224\u65ad\u662f\u5426\u591f\u6b21\u6570').first().json.usage_key }}"
}
]
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"usage_key": "={{ $('\u5224\u65ad\u662f\u5426\u591f\u6b21\u6570').first().json.usage_key }}",
"bot_id": "={{ $('\u5224\u65ad\u662f\u5426\u591f\u6b21\u6570').first().json.bot_id }}",
"date": "={{ $('\u5224\u65ad\u662f\u5426\u591f\u6b21\u6570').first().json.usage_date }}",
"count": "={{ $('\u5224\u65ad\u662f\u5426\u591f\u6b21\u6570').first().json.current_count + 1 }}"
},
"matchingColumns": [],
"schema": [
{
"id": "usage_key",
"displayName": "usage_key",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "bot_id",
"displayName": "bot_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "date",
"displayName": "date",
"required": false,
"defaultMatch": false,
"display": true,
"type": "dateTime",
"readOnly": false,
"removed": false
},
{
"id": "count",
"displayName": "count",
"required": false,
"defaultMatch": false,
"display": true,
"type": "number",
"readOnly": false,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-17664,
-3696
],
"id": "ae1af804-bfcb-4730-b048-70bca22b9e3d",
"name": "\u589e\u52a0\u4eca\u65e5\u6b21\u6570"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "6510c025-e112-4112-9429-6cfb9fb605f6",
"leftValue": "={{ $json.status }}",
"rightValue": "complete",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
-17488,
-3696
],
"id": "73b1fa22-64f9-42de-bd68-191d4d530622",
"name": "If"
},
{
"parameters": {
"workflowId": {
"__rl": true,
"value": "5m7xS062vlea0Cv3",
"mode": "list",
"cachedResultUrl": "/workflow/5m7xS062vlea0Cv3",
"cachedResultName": "Tool - generate_excel_summary (V3)"
},
"workflowInputs": {
"mappingMode": "defineBelow",
"value": {
"chat_id": "={{ $('If').item.json.chat_id }}",
"items": "={{ JSON.stringify($('If').item.json.items) }}",
"usage_count": "={{ $('If').item.json.usage_count }}",
"usage_limit": "={{ $('If').item.json.usage_limit }}"
},
"matchingColumns": [],
"schema": [
{
"id": "chat_id",
"displayName": "chat_id",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string"
},
{
"id": "items",
"displayName": "items",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string"
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": true
},
"options": {}
},
"type": "n8n-nodes-base.executeWorkflow",
"typeVersion": 1.3,
"position": [
-17296,
-3712
],
"id": "b6a4cedd-fbf8-4d9d-a37c-1e35a2944899",
"name": "Call 'Tool - generate_excel_summary'"
},
{
"parameters": {
"workflowId": {
"__rl": true,
"value": "YRTFbyL20UDGMdPX",
"mode": "list",
"cachedResultUrl": "/workflow/YRTFbyL20UDGMdPX",
"cachedResultName": "Tool - ask_clarifying_question (V3)"
},
"workflowInputs": {
"mappingMode": "defineBelow",
"value": {
"chat_id": "={{ $json.chat_id }}",
"question": "={{ $json.question }}",
"context": "={{ JSON.stringify($json.items) }}",
"bot_id": "={{ $json.bot_id }}",
"image_paths": "={{ $json.image_paths }}"
},
"matchingColumns": [],
"schema": [
{
"id": "chat_id",
"displayName": "chat_id",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string"
},
{
"id": "question",
"displayName": "question",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string"
},
{
"id": "context",
"displayName": "context",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string"
},
{
"id": "bot_id",
"displayName": "bot_id",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string"
},
{
"id": "image_paths",
"displayName": "image_paths",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string"
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": true
},
"options": {}
},
"type": "n8n-nodes-base.executeWorkflow",
"typeVersion": 1.3,
"position": [
-17280,
-3312
],
"id": "0759c438-cc4b-4595-88fc-826fe4b12848",
"name": "Call 'Tool - ask_clarifying_question'"
},
{
"parameters": {
"inputSource": "passthrough"
},
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1.2,
"position": [
-21152,
-3648
],
"id": "f3e68155-fdae-4460-bad8-15032e09f1c7",
"name": "When Executed by Another Workflow"
},
{
"parameters": {
"jsCode": "// \u4eceTrigger\u62ff\u5230Router\u6574\u7406\u597d\u7684\u6570\u636e\nconst chatId = $json.chat_id;\nconst caption = $json.caption;\nconst items = JSON.parse($json.items);\n\n// \u62c6\u5f00:photo/pdf\u9700\u8981\u4e0b\u8f7dbinary,text\u4e0d\u7528,\u53ea\u662f\u4e00\u6bb5\u6587\u5b57\u8bf4\u660e\nconst fileItems = items.filter(i => i.type === 'photo' || i.type === 'pdf' || i.type === 'excel');\nconst textItems = items.filter(i => i.type === 'text');\n\n// \u628a\u6240\u6709\u6587\u5b57\u7c7b\u578b\u7684\u5185\u5bb9,\u8ddfcaption(\u5907\u6ce8)\u5408\u5e76\u6210\u4e00\u6bb5\u8bf4\u660e,\n// \u4e4b\u540e\u8981\u585e\u8fdbGemini\u7684Prompt\u91cc,\u8ba9AI knows\u6709\u8fd9\u4e9b\u989d\u5916\u4fe1\u606f\nconst textContent = [caption, ...textItems.map(i => i.text_content)]\n .filter(Boolean)\n .join('\\n');\n\n// \u6709\u6863\u6848:\u6bcf\u4e2a\u9700\u8981\u4e0b\u8f7d\u7684\u6863\u6848\u5404\u81ea\u8f93\u51fa\u4e00\u4e2aitem,\u8ba9Get File\u81ea\u52a8\u4e00\u4e2a\u4e2a\u8dd1\nif (fileItems.length > 0) {\n return fileItems.map(f => ({\n json: {\n chat_id: chatId,\n text_content: textContent,\n file_id: f.file_id,\n mime_type: f.mime_type\n }\n }));\n}\n\n// \u7eaf\u6587\u5b57\u83dc\u5355,\u4e00\u5f20\u56fe/PDF\u90fd\u6ca1\u6709:\u8f93\u51fa\u4e00\u4e2a\u4e0d\u5e26\u6863\u6848\u7684item,\n// \u8ba9\u540e\u9762\u7684\u4e0b\u8f7d/PDF\u8f6c\u6863/\u5b58\u56fe\u8fd9\u6574\u6bb5\u539f\u6837\u8df3\u8fc7,\u76f4\u63a5\u8fdb\u6c47\u5408\u90a3\u6b65\nreturn [{\n json: {\n chat_id: chatId,\n text_content: textContent,\n file_id: null,\n mime_type: null\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-20976,
-3648
],
"id": "c4207497-add4-4e11-97a2-c95550570491",
"name": "\u89e3\u6790Router\u4f20\u6765\u7684items"
},
{
"parameters": {
"operation": "write",
"fileName": "=/home/node/files/session_{{ $('\u89e3\u6790Router\u4f20\u6765\u7684items').first().json.chat_id }}_{{ $itemIndex }}.jpg",
"options": {}
},
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1.1,
"position": [
-19344,
-3312
],
"id": "8a202f84-4be1-4133-aee0-0f8efd82076a",
"name": "\u4fdd\u5b58\u539f\u56fe\u5230\u78c1\u76d8"
},
{
"parameters": {
"jsCode": "// \u6539\u7528$json\u76f4\u63a5\u6293,\u4e0d\u518d\u786c\u6307\u540dnode\u2014\u2014\u56e0\u4e3a\u8fd9\u4e00\u6b65\u5728Gemini\u8def\u5f84\u8ddfExcel\u8def\u5f84\n// \u90fd\u4f1a\u88ab\u6267\u884c\u5230,\u4e24\u6761\u8def\u5f84\u7684\u4e0a\u6e38node\u4e0d\u4e00\u6837,\u6307\u540d\u6293\u4f1a\u5728\u5176\u4e2d\u4e00\u6761\u8def\u5f84\u4e0a\u70b8\u6389\nconst decision = $json;\n\nreturn [{\n json: {\n chat_id: decision.chat_id,\n bot_id: decision.bot_id,\n items: JSON.stringify(decision.items),\n image_paths: decision.image_paths, // \u4e0a\u6e38(\u89e3\u6790Gemini\u56de\u5e94/\u89e3\u6790Excel\u6a21\u677f)\u5df2\u7ecf\u662fJSON\u5b57\u7b26\u4e32,\u76f4\u63a5\u6cbf\u7528\n awaiting_modification: true\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-17120,
-3712
],
"id": "79be4868-9b71-4e1f-888a-17009b288c05",
"name": "\u7ec4\u88c5last_generation\u8d44\u6599"
},
{
"parameters": {
"operation": "upsert",
"dataTableId": {
"__rl": true,
"value": "F8XZDNOad3tXgoQJ",
"mode": "list",
"cachedResultName": "last_generation"
},
"filters": {
"conditions": [
{
"keyName": "chat_id",
"keyValue": "={{ $json.chat_id }}"
},
{
"keyName": "bot_id",
"keyValue": "={{ $json.bot_id }}"
}
]
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"chat_id": "={{ $json.chat_id }}",
"bot_id": "={{ $json.bot_id }}",
"items": "={{ $json.items }}",
"image_paths": "={{ $json.image_paths }}",
"awaiting_modification": true,
"flagged_at": "={{ new Date().toISOString() }}"
},
"matchingColumns": [],
"schema": [
{
"id": "chat_id",
"displayName": "chat_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "bot_id",
"displayName": "bot_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "items",
"displayName": "items",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "image_paths",
"displayName": "image_paths",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "awaiting_modification",
"displayName": "awaiting_modification",
"required": false,
"defaultMatch": false,
"display": true,
"type": "boolean",
"readOnly": false,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-16912,
-3712
],
"id": "d74fa99e-d5e1-4f52-a246-fbd9fa8b21be",
"name": "\u5199\u5165last_generation"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "87d4a921-b3f7-42f9-a9be-37dd8d23fa77",
"leftValue": "={{ $json.file_id }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
-20768,
-3648
],
"id": "670a46ec-e89f-4604-b427-8e64f5d9f276",
"name": "\u662f\u5426\u6709\u6863\u6848"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "9258d83c-dcf6-46cf-b8eb-d08f0252f18c",
"leftValue": "={{ $('\u89e3\u6790Router\u4f20\u6765\u7684items').item.json.mime_type }}",
"rightValue": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
-20272,
-3776
],
"id": "9d47c975-69ac-4789-8fe0-368435fd0318",
"name": "\u662f\u5426\u4e3aExcel"
},
{
"parameters": {
"jsCode": "let items = [];\nlet missingList = [];\nlet parseError = null;\nlet needsAIMapping = false;\nlet headerRowRaw = null;\nlet rawRows = null;\n\ntry {\n const buffer = await this.helpers.getBinaryDataBuffer(0, 'data');\n const ExcelJS = require('exceljs');\n const workbook = new ExcelJS.Workbook();\n await workbook.xlsx.load(buffer);\n\n // \u7528\u4f4d\u7f6e\u6293\u7b2c\u4e00\u4e2asheet,\u4e0d\u8981\u7528getWorksheet(1)\u2014\u2014\n // getWorksheet(id)\u6293\u7684\u662fsheet\u7684\"\u5185\u90e8id\",\u4e0d\u662f\"\u7b2c\u4e00\u4e2asheet\"\u7684\u610f\u601d\u3002\n // \u6709\u4e9b\u6863\u6848(\u5c24\u5176\u88ab\u522b\u7684\u5de5\u5177\u6c47\u51fa/\u7f16\u8f91\u8fc7\u7684)sheet id\u4e0d\u662f\u4ece1\u5f00\u59cb,\n // getWorksheet(1)\u4f1a\u6293\u5230undefined,\u540e\u9762.getRow()\u5c31\u76f4\u63a5\u70b8\u3002\n const ws = workbook.worksheets[0];\n\n if (!ws) {\n parseError = '\u6863\u6848\u91cc\u6ca1\u6709\u627e\u5230\u4efb\u4f55\u5de5\u4f5c\u8868(sheet),\u8bf7\u786e\u8ba4\u6863\u6848\u6ca1\u6709\u635f\u574f\u3002';\n } else {\n const headerRowValues = ws.getRow(1).values;\n const headerMap = {};\n headerRowValues.forEach((h, idx) => {\n if (h) headerMap[h.toString().trim()] = idx;\n });\n\n const requiredHeaders = ['\u540d\u79f0\uff08\u5fc5\u586b\uff09', '\u5206\u7c7b\uff08\u5fc5\u586b\uff09', '\u9500\u552e\u4ef7\uff08\u5fc5\u586b\uff09'];\n const hasAllRequired = requiredHeaders.every(h => headerMap[h]);\n\n if (hasAllRequired) {\n // \u8868\u5934\u6587\u5b57\u8ddf\u5b98\u65b9\u6a21\u677f\u5b8c\u5168\u5bf9\u4e0a,\u8d70\u539f\u672c\u7684\u5b57\u7b26\u4e32\u6bd4\u5bf9\u903b\u8f91,\u96f6AI\u6210\u672c\n const getCell = (row, headerName) => {\n const col = headerMap[headerName];\n return col ? row.getCell(col).value : null;\n };\n\n for (let r = 2; r <= ws.rowCount; r++) {\n const row = ws.getRow(r);\n const name = getCell(row, '\u540d\u79f0\uff08\u5fc5\u586b\uff09');\n if (!name) continue; // \u8df3\u8fc7\u7a7a\u884c\n\n const category = getCell(row, '\u5206\u7c7b\uff08\u5fc5\u586b\uff09') || '';\n const sell_price = getCell(row, '\u9500\u552e\u4ef7\uff08\u5fc5\u586b\uff09') ?? 0;\n\n const missingFields = [];\n if (!category) missingFields.push('\u5206\u7c7b');\n if (!sell_price) missingFields.push('\u9500\u552e\u4ef7');\n if (missingFields.length > 0) {\n missingList.push(`\u7b2c${r}\u884c\u300c${name}\u300d\u7f3a\u5c11\uff1a${missingFields.join('\u3001')}`);\n }\n\n items.push({\n name: name,\n category: category,\n spec: getCell(row, '\u89c4\u683c') || '',\n stock_qty: getCell(row, '\u5e93\u5b58\u91cf') ?? '',\n cost_price: getCell(row, '\u8fdb\u8d27\u4ef7\uff08\u5fc5\u586b\uff09') ?? 0,\n sell_price: sell_price\n });\n }\n } else {\n // \u8868\u5934\u6587\u5b57\u8ddf\u5b98\u65b9\u6a21\u677f\u5bf9\u4e0d\u4e0a,\u4e0d\u76f4\u63a5\u653e\u5f03,\u4ea4\u7ed9\u4e0b\u4e00\u6b65AI\u505a\u680f\u4f4d\u5bf9\u7167\n // \u8fd9\u91cc\u53ea\u62ff\u8868\u5934+\u5168\u90e8\u8d44\u6599\u5217(\u7eaf\u6587\u5b57/\u6570\u5b57),\u4e0d\u542b\u56fe\u7247/binary,\u8d44\u6599\u91cf\u5f88\u5c0f\n needsAIMapping = true;\n headerRowRaw = headerRowValues.slice(1); // \u53bb\u6389ExcelJS\u5f00\u5934\u90a3\u4e2a\u7a7a\u4f4d,\u53d8\u6210\u5e72\u51c0\u76840-index\u9635\u5217\n rawRows = [];\n for (let r = 2; r <= ws.rowCount; r++) {\n const rowValues = ws.getRow(r).values.slice(1);\n if (rowValues.some(v => v !== null && v !== undefined && v !== '')) {\n rawRows.push(rowValues); // \u8df3\u8fc7\u5b8c\u5168\u7a7a\u767d\u7684\u5217\n }\n }\n }\n }\n} catch (err) {\n // xlsx.load\u672c\u8eab\u4e5f\u53ef\u80fdthrow(\u6863\u6848\u635f\u574f\u3001\u52a0\u5bc6\u3001\u6839\u672c\u4e0d\u662fxlsx\u683c\u5f0f\u7b49),\n // \u4e00\u5f8b\u63a5\u4f4f,\u4e0d\u8ba9\u6574\u4e2anode\u5d29\u6389\u3001\u5546\u5bb6\u6536\u4e0d\u5230\u4efb\u4f55\u56de\u5e94\n parseError = err.message || '\u6863\u6848\u8bfb\u53d6\u5931\u8d25,\u683c\u5f0f\u53ef\u80fd\u4e0d\u652f\u63f4';\n}\n\nconst sourceData = $('\u89e3\u6790Router\u4f20\u6765\u7684items').first().json;\n\nlet status = '';\nlet question = '';\n\nif (!needsAIMapping) {\n if (parseError) {\n status = 'incomplete';\n question = `\u274c \u6863\u6848\u5904\u7406\u5931\u8d25\uff1a${parseError}\\n\\n\u8bf7\u786e\u8ba4\u4f7f\u7528\u5b98\u65b9\u6a21\u677f\u3001\u6863\u6848\u6ca1\u6709\u635f\u574f,\u91cd\u65b0\u4e0a\u4f20,\u8c22\u8c22\uff01`;\n } else {\n const isComplete = items.length > 0 && missingList.length === 0;\n status = isComplete ? 'complete' : 'incomplete';\n if (items.length === 0) {\n question = '\u6ca1\u6709\u5728\u6863\u6848\u4e2d\u8bc6\u522b\u5230\u4efb\u4f55\u5546\u54c1,\u8bf7\u786e\u8ba4\u4f7f\u7528\u7684\u662f\u5b98\u65b9\u6a21\u677f\u3001\u4e14\u8868\u5934\u540d\u79f0\u6ca1\u6709\u88ab\u4fee\u6539\u8fc7,\u8c22\u8c22\uff01';\n } else if (!isComplete) {\n const MAX_LIST = 15;\n const shown = missingList.slice(0, MAX_LIST);\n const remain = missingList.length - shown.length;\n question = `\u83dc\u5355\u4e2d\u6709\u4e9b\u5fc5\u586b\u680f\u4f4d\u8fd8\u6ca1\u586b\u9f50\uff1a\\n${shown.join('\\n')}`\n + (remain > 0 ? `\\n...\u8fd8\u6709 ${remain} \u9879\u4e5f\u9700\u8981\u8865\u5145` : '')\n + `\\n\\n\u8bf7\u76f4\u63a5\u56de\u8986\u8865\u5145,\u6216\u8865\u5145\u5b8c\u6574\u540e\u91cd\u65b0\u4e0a\u4f20,\u8c22\u8c22\uff01`;\n }\n }\n}\n\nreturn [{\n json: {\n chat_id: sourceData.chat_id,\n bot_id: 'worker1', // Excel\u8fd9\u6761\u8def\u8df3\u8fc7\u4e86\u8282\u6d41\u6d41\u7a0b,\u8fd9\u91cc\u8981\u91cd\u590d\u5b9a\u4e49\u540c\u4e00\u4e2a\u5e38\u6570\n needsAIMapping: needsAIMapping,\n headerRowRaw: headerRowRaw,\n rawRows: rawRows,\n status: status,\n items: items,\n question: question,\n image_paths: '[]' // Excel\u8fd9\u6761\u8def\u6ca1\u6709\u56fe\u7247,\u7ed9\u7a7a\u9635\u5217,\u8ddfGemini\u90a3\u6761\u8def\u8f93\u51fa\u683c\u5f0f\u4fdd\u6301\u4e00\u81f4\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-19952,
-3920
],
"id": "4c09ce24-4836-4353-8d1a-7be2e641f393",
"name": "\u89e3\u6790Excel\u6a21\u677f"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "9f03b078-4bee-435d-91cd-b55b5b0a4cd6",
"leftValue": "={{ $json.needsAIMapping }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
-19692,
-3920
],
"id": "8fd461a4-6801-4cad-92da-2465f3b1ac2b",
"name": "\u662f\u5426\u9700\u8981AI\u680f\u4f4d\u5bf9\u7167"
},
{
"parameters": {
"jsCode": "const trigger = $json;\n\nconst promptText = `\u4f60\u662f\u4e00\u4e2aExcel\u8868\u5934\u5bf9\u7167\u52a9\u624b\u3002\u4ee5\u4e0b\u662f\u4e00\u4efdExcel\u6863\u6848\u7684\u8868\u5934\u680f\u4f4d,\u4ee5\u53ca\u90e8\u5206\u6837\u672c\u8d44\u6599\u3002\n\n\u8868\u5934\u680f\u4f4d\uff08\u4f9d\u5e8f,index\u4ece0\u5f00\u59cb\uff09\uff1a\n${JSON.stringify(trigger.headerRowRaw)}\n\n\u6837\u672c\u8d44\u6599\uff08\u524d\u51e0\u884c,\u4f9d\u5e8f\u5bf9\u5e94\u4e0a\u9762\u680f\u4f4d\uff09\uff1a\n${JSON.stringify(trigger.rawRows.slice(0, 3))}\n\n\u8bf7\u5224\u65ad\u8fd9\u4efd\u8868\u683c\u91cc,\u54ea\u4e00\u680f\u5bf9\u5e94\u4ee5\u4e0b\u6211\u4eec\u9700\u8981\u7684\u680f\u4f4d,\u7528\u680f\u4f4d\u5728\u9635\u5217\u4e2d\u7684index\u8868\u793a\uff08\u4ece0\u5f00\u59cb\uff09\uff1b\n\u5982\u679c\u8fd9\u4efd\u8868\u683c\u6839\u672c\u6ca1\u6709\u5bf9\u5e94\u7684\u680f\u4f4d,\u8be5\u9879\u76ee\u586b-1,\u4e0d\u8981\u4e71\u731c\uff1a\n- name: \u5546\u54c1/\u54c1\u9879\u540d\u79f0\n- category: \u5546\u54c1\u5206\u7c7b\n- sell_price: \u9500\u552e\u4ef7\u683c/\u5355\u4ef7\n- spec: \u89c4\u683c(\u9009\u586b)\n- stock_qty: \u5e93\u5b58\u6570\u91cf(\u9009\u586b)\n- cost_price: \u8fdb\u8d27\u4ef7/\u6210\u672c\u4ef7(\u9009\u586b)\n\n\u8bf7\u4e25\u683c\u53ea\u8f93\u51fa\u4ee5\u4e0bJSON\u683c\u5f0f,\u4e0d\u8981\u4efb\u4f55\u89e3\u91ca\u6587\u5b57\u3001\u4e0d\u8981markdown\u4ee3\u7801\u5757\u6807\u8bb0\uff1a\n{\n \"name\": 0,\n \"category\": -1,\n \"sell_price\": 2,\n \"spec\": -1,\n \"stock_qty\": -1,\n \"cost_price\": -1\n}`;\n\nconst geminiRequest = { contents: [{ parts: [{ text: promptText }] }] };\n\nreturn [{\n json: {\n chat_id: trigger.chat_id,\n bot_id: trigger.bot_id,\n headerRowRaw: trigger.headerRowRaw,\n rawRows: trigger.rawRows,\n geminiRequest: geminiRequest\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-19692,
-3680
],
"id": "ab3bf70e-22a6-42e3-aeb2-70df083a2e72",
"name": "\u7ec4\u88c5\u8868\u5934\u5bf9\u7167\u8bf7\u6c42"
},
{
"parameters": {
"method": "POST",
"url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-flash:generateContent",
"authentication": "genericCredentialType",
"genericAuthType": "httpQueryAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ $json.geminiRequest }}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
-19452,
-3680
],
"id": "91c0a7be-d8e2-47e0-8b4c-847c55fdf429",
"name": "HTTP Request \u8868\u5934\u5bf9\u7167Gemini",
"credentials": {
"httpQueryAuth": {
"name": "<your credential>"
}
},
"onError": "continueRegularOutput"
},
{
"parameters": {
"jsCode": "const source = $('\u7ec4\u88c5\u8868\u5934\u5bf9\u7167\u8bf7\u6c42').first().json;\nconst item = $input.first().json;\n\nlet mapping = null;\nlet aiError = null;\n\nif (item.error || !item.candidates) {\n aiError = item.error?.message || 'AI\u670d\u52a1\u6682\u65f6\u65e0\u6cd5\u4f7f\u7528';\n} else {\n try {\n const rawText = item.candidates[0].content.parts[0].text;\n const cleaned = rawText.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\n mapping = JSON.parse(cleaned);\n } catch (e) {\n aiError = 'AI\u56de\u5e94\u683c\u5f0f\u65e0\u6cd5\u89e3\u6790';\n }\n}\n\nconst hasRequiredMapping = mapping &&\n mapping.name >= 0 && mapping.category >= 0 && mapping.sell_price >= 0;\n\nlet items = [];\nlet missingList = [];\nlet question = '';\nlet status = 'incomplete';\n\nif (!hasRequiredMapping) {\n // AI\u4e5f\u5224\u65ad\u4e0d\u51fa\u5bf9\u5e94\u680f\u4f4d(\u6216AI\u547c\u53eb\u672c\u8eab\u5931\u8d25\u4e86),\u4e0d\u786c\u731c,\u793c\u8c8c\u62d2\u7edd,\u4e0d\u4ea7\u751f\u9519\u8bef\u8d44\u6599\n question = aiError\n ? `\u6863\u6848\u8868\u5934\u65e0\u6cd5\u81ea\u52a8\u8bc6\u522b(${aiError}),\u8bf7\u4f7f\u7528\u5b98\u65b9\u6a21\u677f\u91cd\u65b0\u4e0a\u4f20,\u8c22\u8c22\uff01`\n : '\u6ca1\u6709\u5728\u6863\u6848\u4e2d\u8bc6\u522b\u5230\u5546\u54c1\u540d\u79f0/\u5206\u7c7b/\u9500\u552e\u4ef7\u5bf9\u5e94\u7684\u680f\u4f4d,\u8bf7\u786e\u8ba4\u4f7f\u7528\u7684\u662f\u5b98\u65b9\u6a21\u677f,\u8c22\u8c22\uff01';\n} else {\n const rawRows = source.rawRows;\n for (let i = 0; i < rawRows.length; i++) {\n const row = rawRows[i];\n const name = mapping.name >= 0 ? row[mapping.name] : null;\n if (!name) continue; // \u8df3\u8fc7\u7a7a\u884c\n\n const category = mapping.category >= 0 ? (row[mapping.category] || '') : '';\n const sell_price = mapping.sell_price >= 0 ? (row[mapping.sell_price] ?? 0) : 0;\n\n const missingFields = [];\n if (!category) missingFields.push('\u5206\u7c7b');\n if (!sell_price) missingFields.push('\u9500\u552e\u4ef7');\n if (missingFields.length > 0) {\n missingList.push(`\u7b2c${i + 2}\u884c\u300c${name}\u300d\u7f3a\u5c11\uff1a${missingFields.join('\u3001')}`);\n }\n\n items.push({\n name: name,\n category: category,\n spec: mapping.spec >= 0 ? (row[mapping.spec] || '') : '',\n stock_qty: mapping.stock_qty >= 0 ? (row[mapping.stock_qty] ?? '') : '',\n cost_price: mapping.cost_price >= 0 ? (row[mapping.cost_price] ?? 0) : 0,\n sell_price: sell_price\n });\n }\n\n const isComplete = items.length > 0 && missingList.length === 0;\n status = isComplete ? 'complete' : 'incomplete';\n\n if (items.length === 0) {\n question = '\u867d\u7136AI\u8bc6\u522b\u51fa\u4e86\u680f\u4f4d\u5bf9\u7167,\u4f46\u6863\u6848\u5185\u5bb9\u662f\u7a7a\u7684,\u8bf7\u786e\u8ba4\u6863\u6848\u5185\u5bb9,\u8c22\u8c22\uff01';\n } else if (!isComplete) {\n const MAX_LIST = 15;\n const shown = missingList.slice(0, MAX_LIST);\n const remain = missingList.length - shown.length;\n question = `\u8fd9\u4efd\u6863\u6848\u7684\u8868\u5934\u683c\u5f0f\u8ddf\u5b98\u65b9\u6a21\u677f\u4e0d\u540c,\u5df2\u7ecf\u81ea\u52a8\u5e2e\u60a8\u5bf9\u7167\u680f\u4f4d\u3002\u83dc\u5355\u4e2d\u6709\u4e9b\u5fc5\u586b\u680f\u4f4d\u8fd8\u6ca1\u586b\u9f50\uff1a\\n${shown.join('\\n')}`\n + (remain > 0 ? `\\n...\u8fd8\u6709 ${remain} \u9879\u4e5f\u9700\u8981\u8865\u5145` : '')\n + `\\n\\n\u8bf7\u76f4\u63a5\u56de\u8986\u8865\u5145,\u6216\u8865\u5145\u5b8c\u6574\u540e\u91cd\u65b0\u4e0a\u4f20,\u8c22\u8c22\uff01`;\n }\n}\n\nreturn [{\n json: {\n chat_id: source.chat_id,\n bot_id: source.bot_id,\n status: status,\n items: items,\n question: question,\n image_paths: '[]'\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-19212,
-3680
],
"id": "1a940671-d310-4460-87b0-0344b2539266",
"name": "\u89e3\u6790\u8868\u5934\u5bf9\u7167\u56de\u5e94"
},
{
"parameters": {
"jsCode": "return [{ json: { ...$('\u89e3\u6790Gemini\u56de\u5e94').item.json, usage_count: $json.count, usage_limit: 15 } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-17444,
-3696
],
"id": "84fc2413-99e7-4d94-b15c-efa8177e2156",
"name": "\u8fd8\u539fGemini\u5224\u65ad\u7ed3\u679c"
},
{
"parameters": {
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "hzaSbVDXvHGFBfh7",
"mode": "list",
"cachedResultName": "merchant_feedback"
},
"filters": {
"conditions": [
{
"keyName": "chat_id",
"keyValue": "={{ $('\u6c47\u5408\u6210\u4e00\u4e2aitem\u7684Code node').first().json.chat_id }}"
}
]
}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-18412,
-3696
],
"id": "420293e6-3aa3-4f8d-a012-26f5e3ddd376",
"name": "\u67e5\u5546\u5bb6\u8bc4\u5206",
"alwaysOutputData": true
}
],
"connections": {
"HTTP Request - Telegram Get File": {
"main": [
[
{
"node": "HTTP Request - Telegram Download File",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request - Telegram Download File": {
"main": [
[
{
"node": "\u662f\u5426\u4e3aExcel",
"type": "main",
"index": 0
}
]
]
},
"\u4fee\u6b63\u56fe\u7247MimeType": {
"main": [
[
{
"node": "\u4fdd\u5b58\u539f\u56fe\u5230\u78c1\u76d8",
"type": "main",
"index": 0
}
]
]
},
"\u6c47\u5408\u6210\u4e00\u4e2aitem\u7684Code node": {
"main": [
[
{
"node": "\u7b97\u51fausage_key",
"type": "main",
"index": 0
}
]
]
},
"\u662f\u5426\u4e3aPDF": {
"main": [
[
{
"node": "\u5199\u5165PDF\u5230\u78c1\u76d8",
"type": "main",
"index": 0
}
],
[
{
"node": "\u4fee\u6b63\u56fe\u7247MimeType",
"type": "main",
"index": 0
}
]
]
},
"\u5199\u5165PDF\u5230\u78c1\u76d8": {
"main": [
[
{
"node": "Execute Command",
"type": "main",
"index": 0
}
]
]
},
"Execute Command": {
"main": [
[
{
"node": "Read/Write Files from Disk",
"type": "main",
"index": 0
}
]
]
},
"Read/Write Files from Disk": {
"main": [
[
{
"node": "\u4fee\u6b63\u56fe\u7247MimeType",
"type": "main",
"index": 0
}
]
]
},
"\u7b97\u51fausage_key": {
"main": [
[
{
"node": "\u67e5\u770busage_key",
"type": "main",
"index": 0
}
]
]
},
"\u67e5\u770busage_key": {
"main": [
[
{
"node": "\u5224\u65ad\u662f\u5426\u591f\u6b21\u6570",
"type": "main",
"index": 0
}
]
]
},
"\u662f\u5426\u591f\u6b21\u6570": {
"main": [
[
{
"node": "\u7ec4\u88c5Gemini\u8bf7\u6c42",
"type": "main",
"index": 0
},
{
"node": "\u67e5\u5546\u5bb6\u8bc4\u5206",
"type": "main",
"index": 0
}
],
[
{
"node": "\u53d1\u9001\u989d\u5ea6\u5df2\u6ee1\u8baf\u606f",
"type": "main",
"index": 0
}
]
]
},
"\u5224\u65ad\u662f\u5426\u591f\u6b21\u6570": {
"main": [
[
{
"node": "\u662f\u5426\u591f\u6b21\u6570",
"type": "main",
"index": 0
}
]
]
},
"\u7ec4\u88c5Gemini\u8bf7\u6c42": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "\u89e3\u6790Gemini\u56de\u5e94",
"type": "main",
"index": 0
}
]
]
},
"\u89e3\u6790Gemini\u56de\u5e94": {
"main": [
[
{
"node": "\u589e\u52a0\u4eca\u65e5\u6b21\u6570",
"type": "main",
"index": 0
}
]
]
},
"\u589e\u52a0\u4eca\u65e5\u6b21\u6570": {
"main": [
[
{
"node": "\u8fd8\u539fGemini\u5224\u65ad\u7ed3\u679c",
"type": "main",
"index": 0
}
]
]
},
"If": {
"main": [
[
{
"node": "\u7ec4\u88c5last_generation\u8d44\u6599",
"type": "main",
"index": 0
}
],
[
{
"node": "Call 'Tool - ask_clarifying_question'",
"type": "main",
"index": 0
}
]
]
},
"When Executed by Another Workflow": {
"main": [
[
{
"node": "\u89e3\u6790Router\u4f20\u6765\u7684items",
"type": "main",
"index": 0
}
]
]
},
"\u89e3\u6790Router\u4f20\u6765\u7684items": {
"main": [
[
{
"node": "\u662f\u5426\u6709\u6863\u6848",
"type": "main",
"index": 0
}
]
]
},
"\u4fdd\u5b58\u539f\u56fe\u5230\u78c1\u76d8": {
"main": [
[
{
"node": "\u6c47\u5408\u6210\u4e00\u4e2aitem\u7684Code node",
"type": "main",
"index": 0
}
]
]
},
"\u7ec4\u88c5last_generation\u8d44\u6599": {
"main": [
[
{
"node": "\u5199\u5165last_generation",
"type": "main",
"index": 0
}
]
]
},
"\u662f\u5426\u6709\u6863\u6848": {
"main": [
[
{
"node": "HTTP Request - Telegram Get File",
"type": "main",
"index": 0
}
],
[
{
"node": "\u6c47\u5408\u6210\u4e00\u4e2aitem\u7684Code node",
"type": "main",
"index": 0
}
]
]
},
"\u662f\u5426\u4e3aExcel": {
"main": [
[
{
"node": "\u89e3\u6790Excel\u6a21\u677f",
"type": "main",
"index": 0
}
],
[
{
"node": "\u662f\u5426\u4e3aPDF",
"type": "main",
"index": 0
}
]
]
},
"\u89e3\u6790Excel\u6a21\u677f": {
"main": [
[
{
"node": "\u662f\u5426\u9700\u8981AI\u680f\u4f4d\u5bf9\u7167",
"type": "main",
"index": 0
}
]
]
},
"\u662f\u5426\u9700\u8981AI\u680f\u4f4d\u5bf9\u7167": {
"main": [
[
{
"node": "\u7ec4\u88c5\u8868\u5934\u5bf9\u7167\u8bf7\u6c42",
"type": "main",
"index": 0
}
],
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"\u7ec4\u88c5\u8868\u5934\u5bf9\u7167\u8bf7\u6c42": {
"main": [
[
{
"node": "HTTP Request \u8868\u5934\u5bf9\u7167Gemini",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request \u8868\u5934\u5bf9\u7167Gemini": {
"main": [
[
{
"node": "\u89e3\u6790\u8868\u5934\u5bf9\u7167\u56de\u5e94",
"type": "main",
"index": 0
}
]
]
},
"\u89e3\u6790\u8868\u5934\u5bf9\u7167\u56de\u5e94": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"\u8fd8\u539fGemini\u5224\u65ad\u7ed3\u679c": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"\u5199\u5165last_generation": {
"main": [
[
{
"node": "Call 'Tool - generate_excel_summary'",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate",
"availableInMCP": false
},
"versionId": "3653b343-5989-4987-8d5b-bc65389acc26",
"meta": {
"templateCredsSetupCompleted": true
},
"nodeGroups": [],
"id": "oyJXEnSwAiux2k4C",
"tags": [
{
"updatedAt": "2026-07-27T07:50:01.682Z",
"createdAt": "2026-07-27T07:50:01.682Z",
"id": "oulTjbe8ViVdh1V7",
"name": "AUTO-P1-V3"
},
{
"updatedAt": "2026-07-20T07:40:54.445Z",
"createdAt": "2026-07-20T07:40:54.445Z",
"id": "sBao71AvdSJ3hx2O",
"name": "3FS"
}
]
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
httpQueryAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
DEEPP AUTO P1 V3 - Worker (Front). Uses httpRequest, readWriteFile, executeCommand, dataTable. Event-driven trigger; 34 nodes.
Source: https://github.com/Heng1028/pos-telegrambot-v3/blob/main/worker-front-workflow.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
DEEPP AUTO P1 V3 - Worker (Back). Uses executeWorkflowTrigger, readWriteFile, httpRequest, dataTable. Event-driven trigger; 20 nodes.
Transcript. Uses httpRequest, telegram, telegramTrigger, readWriteFile. Event-driven trigger; 37 nodes.
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
A — Приём и перевод (Челлендж 200 дней). Uses executeWorkflowTrigger, telegram, httpRequest, executeCommand. Event-driven trigger; 32 nodes.
Template was created in n8n v1.90.2 Execute Sub-workflow Trigger node Chat Trigger node Redis node Postgres node Telegram node HTTP Request node If node, Code node, Edit Fields (Set) Execute Sub-workf