会议纪要和行动项跟踪器
高级
这是一个Content Creation, Multimodal AI领域的自动化工作流,包含 38 个节点。主要使用 If, Set, Code, Gmail, Merge 等节点。 基于AI的会议纪要:使用GPT-4、任务分配和多渠道分发
前置要求
- •Google 账号和 Gmail API 凭证
- •Slack Bot Token 或 Webhook URL
- •HTTP Webhook 端点(n8n 会自动生成)
- •Google Drive API 凭证
- •可能需要目标 API 的认证凭证
- •OpenAI API Key
使用的节点 (38)
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "MU89lcZkW3CjD9nU",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "会议纪要和行动项跟踪器",
"tags": [],
"nodes": [
{
"id": "022280e9-fc0f-4148-827f-14143ba4c11a",
"name": "接收会议数据",
"type": "n8n-nodes-base.webhook",
"position": [
-160,
0
],
"webhookId": "9e0d22e1-8b66-4438-a6b5-4748a168cc11",
"parameters": {
"path": "meeting-minutes",
"options": {},
"httpMethod": "POST",
"responseMode": "lastNode"
},
"typeVersion": 2.1
},
{
"id": "81191e4b-f548-46b1-b8ca-8560653a33ab",
"name": "提取会议元数据",
"type": "n8n-nodes-base.set",
"position": [
112,
0
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "1ccc5df3-8c52-4ac8-a4b9-19e037022817",
"name": "meetingTitle",
"type": "string",
"value": "={{ $json.body.title|| \"Untitled Meeting\" }}"
},
{
"id": "ca5a8fed-69dc-4c24-85d5-d6860f192b05",
"name": "meetingDate",
"type": "string",
"value": "={{ $json.body.date || $now.format('yyyy-MM-dd') }}"
},
{
"id": "f44440f2-80ab-4f1e-a79d-8d4d5b347703",
"name": "participants",
"type": "array",
"value": "={{$json.body.participants || [] }}"
},
{
"id": "46dff8c2-8c56-4d9c-9508-b9a280fca602",
"name": "duration",
"type": "string",
"value": "={{ $json.duration || \"Not specified\" }}"
},
{
"id": "87b3fa3a-a5fd-4cf9-8436-7a5a0870a15a",
"name": "rawTranscript",
"type": "string",
"value": "={{ $json.transcript || $json.body.transcript || \"\" }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "1d1d508e-f9b2-4175-83fc-3ab883990d8b",
"name": "清理转录文本",
"type": "n8n-nodes-base.code",
"position": [
416,
0
],
"parameters": {
"jsCode": "// Get the input data\nconst items = $input.all();\n\n// Process each item\nconst processedItems = items.map(item => {\n const data = item.json;\n \n // Clean the transcript\n let cleanedTranscript = data.rawTranscript || '';\n \n // Remove multiple spaces\n cleanedTranscript = cleanedTranscript.replace(/\\s+/g, ' ');\n \n // Remove common timestamp patterns (e.g., [00:01:23] or (00:01:23))\n cleanedTranscript = cleanedTranscript.replace(/[\\[\\(]\\d{2}:\\d{2}:\\d{2}[\\]\\)]/g, '');\n \n // Remove speaker labels if formatted as \"Speaker 1:\", \"Speaker 2:\", etc.\n cleanedTranscript = cleanedTranscript.replace(/Speaker \\d+:/g, '');\n \n // Trim whitespace\n cleanedTranscript = cleanedTranscript.trim();\n \n // Count words for context\n const wordCount = cleanedTranscript.split(/\\s+/).length;\n \n // Estimate reading time (average 200 words per minute)\n const estimatedMinutes = Math.ceil(wordCount / 200);\n \n return {\n json: {\n ...data,\n cleanedTranscript: cleanedTranscript,\n transcriptWordCount: wordCount,\n estimatedReadingTime: `${estimatedMinutes} minutes`,\n processingTimestamp: new Date().toISOString()\n }\n };\n});\n\nreturn processedItems;"
},
"typeVersion": 2
},
{
"id": "2f05b28e-8aab-4f5f-b6ec-a61e96ec12de",
"name": "验证转录文本长度",
"type": "n8n-nodes-base.if",
"position": [
720,
0
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "296bb329-fa1e-4660-9976-5462a0f3ae21",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.cleanedTranscript }}",
"rightValue": ""
},
{
"id": "c754bcd2-dd4e-4c2b-b3ae-a024c71bf6de",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $json.transcriptWordCount }}",
"rightValue": 50
}
]
}
},
"typeVersion": 2.2
},
{
"id": "8ce8541c-951c-4c43-9471-3c55f8fe0be1",
"name": "生成会议摘要",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
960,
-128
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4",
"cachedResultName": "GPT-4"
},
"options": {
"topP": 1,
"maxTokens": 1000,
"temperature": 0.3,
"presence_penalty": 0,
"frequency_penalty": 0
},
"messages": {
"values": [
{
"role": "system",
"content": "=You are an expert executive assistant specializing in creating professional meeting summaries. \n\nYour summaries should:\n1. Be concise but comprehensive (200-300 words)\n2. Highlight key discussion points in order of importance\n3. Note important decisions made during the meeting\n4. Capture the overall meeting context and objectives\n5. Use clear, professional business language\n6. Organize information logically with smooth flow\n\nFormat your summary in 3-4 clear paragraphs, NOT bullet points. Write in third person (e.g., \"The team discussed...\" not \"We discussed...\")."
},
{
"content": "=Create a professional meeting summary for the following:\n\nMeeting Title: {{ $json.meetingTitle }}\nDate: {{ $json.meetingDate }}\nDuration: {{ $json.duration }}\nParticipants: {{ $json.participants.join(', ') }}\n\nTranscript:\n{{ $json.cleanedTranscript }}\n\nGenerate a comprehensive summary that captures the essence of this meeting."
}
]
}
},
"credentials": {
"openAiApi": {
"id": "5n856jvI80lSEErZ",
"name": "Klinsman OpenAI"
}
},
"typeVersion": 1.8
},
{
"id": "89d1da2f-2eb8-4c87-b10d-74cccf6c0c2e",
"name": "提取行动项",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
960,
128
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4",
"cachedResultName": "GPT-4"
},
"options": {
"maxTokens": 1500,
"temperature": 0.2
},
"messages": {
"values": [
{
"content": "=Extract all action items from this meeting transcript:\n\nMeeting Title: {{ $json.meetingTitle }}\nMeeting Date: {{ $json.meetingDate }}\n\nTranscript:\n{{ $json.cleanedTranscript }}\n\nReturn ONLY the JSON object with the action_items array. Do not include any other text, markdown formatting, or code blocks."
},
{
"role": "system",
"content": "=You are an expert at extracting action items from meeting transcripts. \n\nFor each action item, identify:\n1. **task**: Clear, actionable description of what needs to be done\n2. **assignee**: Person responsible (use their exact name from transcript)\n3. **deadline**: Due date if mentioned (format: YYYY-MM-DD), or null if not specified\n4. **priority**: Either 'urgent', 'high', 'normal', or 'low' based on context\n5. **context**: Brief note about why this task matters (1 sentence)\n\nRules:\n- Only extract clear, actionable tasks (not discussion points or general notes)\n- If no assignee is mentioned, set to \"Unassigned\"\n- Detect urgency from keywords: \"ASAP\", \"urgent\", \"immediately\", \"critical\", \"by end of day\"\n- If deadline isn't specific, infer from context clues (e.g., \"next week\" = meeting date + 7 days)\n- If someone says \"I'll do X\", that person is the assignee for X\n\nReturn ONLY a valid JSON object (no markdown, no code blocks) in this exact format:\n{\n \"action_items\": [\n {\n \"task\": \"string\",\n \"assignee\": \"string\",\n \"deadline\": \"YYYY-MM-DD or null\",\n \"priority\": \"urgent|high|normal|low\",\n \"context\": \"string\"\n }\n ]\n}"
}
]
}
},
"credentials": {
"openAiApi": {
"id": "5n856jvI80lSEErZ",
"name": "Klinsman OpenAI"
}
},
"typeVersion": 1.8
},
{
"id": "d5564407-0f3b-4128-aa3a-3db3f6b271a5",
"name": "合并 AI 响应",
"type": "n8n-nodes-base.merge",
"position": [
1360,
0
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "9a4f0d20-75e6-4c83-8cf0-4d374485bc03",
"name": "解析和丰富数据",
"type": "n8n-nodes-base.code",
"position": [
1632,
0
],
"parameters": {
"jsCode": "// Get ALL items from Merge (Append gives us an array of items)\nconst items = $input.all();\n\nconsole.log('=== STARTING PARSE ===');\nconsole.log('Total items:', items.length);\n\n// Get metadata from earlier nodes\nlet codeData = {};\ntry {\n codeData = $('Clean Transcript').first().json;\n console.log('✓ Got metadata from Code node');\n} catch (error) {\n console.log('✗ Could not access Code node:', error.message);\n}\n\n// Initialize with metadata\nlet meetingData = {\n meetingTitle: codeData.meetingTitle || 'Untitled Meeting',\n meetingDate: codeData.meetingDate || new Date().toISOString().split('T')[0],\n participants: codeData.participants || [],\n duration: codeData.duration || 'Not specified',\n rawTranscript: codeData.rawTranscript || '',\n cleanedTranscript: codeData.cleanedTranscript || '',\n transcriptWordCount: codeData.transcriptWordCount || 0,\n estimatedReadingTime: codeData.estimatedReadingTime || 'Unknown',\n processingTimestamp: codeData.processingTimestamp || new Date().toISOString(),\n summary: '',\n actionItems: []\n};\n\nconsole.log('\\n=== PROCESSING', items.length, 'OPENAI RESPONSES ===');\n\n// Process each item from Merge\nitems.forEach((item, index) => {\n console.log(`\\nItem ${index}:`);\n \n const data = item.json;\n \n // OpenAI node returns: { message: { role, content } }\n if (data.message && data.message.content) {\n const content = data.message.content;\n console.log(' Content length:', content.length);\n console.log(' Preview:', content.substring(0, 80));\n \n // Check if action items JSON\n if (content.includes('\"action_items\"')) {\n console.log(' → ACTION ITEMS');\n try {\n const parsed = JSON.parse(content);\n meetingData.actionItems = parsed.action_items || [];\n console.log(' ✓ Parsed:', meetingData.actionItems.length, 'items');\n } catch (error) {\n console.error(' ✗ Parse error:', error.message);\n }\n } else {\n console.log(' → SUMMARY');\n meetingData.summary = content.trim();\n console.log(' ✓ Length:', meetingData.summary.length);\n }\n }\n});\n\nconsole.log('\\n=== RESULTS ===');\nconsole.log('Summary:', meetingData.summary ? `${meetingData.summary.length} chars` : 'EMPTY');\nconsole.log('Action Items:', meetingData.actionItems.length);\n\n// Enrich action items\nmeetingData.actionItems = meetingData.actionItems.map((item, index) => {\n let formattedDeadline = 'TBD';\n let daysUntil = null;\n let deadlineStatus = 'no-deadline';\n \n if (item.deadline && item.deadline !== 'null' && item.deadline !== null) {\n try {\n const deadlineDate = new Date(item.deadline);\n if (!isNaN(deadlineDate.getTime())) {\n formattedDeadline = deadlineDate.toISOString().split('T')[0];\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n deadlineDate.setHours(0, 0, 0, 0);\n daysUntil = Math.ceil((deadlineDate - today) / (1000 * 60 * 60 * 24));\n \n if (daysUntil < 0) deadlineStatus = 'overdue';\n else if (daysUntil === 0) deadlineStatus = 'today';\n else if (daysUntil <= 3) deadlineStatus = 'urgent';\n else if (daysUntil <= 7) deadlineStatus = 'upcoming';\n else deadlineStatus = 'future';\n }\n } catch (e) {}\n }\n \n return {\n id: `AI-${Date.now()}-${index}`,\n number: index + 1,\n task: item.task || 'No task description',\n assignee: item.assignee || 'Unassigned',\n deadline: formattedDeadline,\n deadlineOriginal: item.deadline,\n daysUntilDeadline: daysUntil,\n deadlineStatus: deadlineStatus,\n priority: (item.priority || 'normal').toLowerCase(),\n context: item.context || '',\n status: 'pending',\n createdAt: new Date().toISOString(),\n meetingReference: meetingData.meetingTitle,\n meetingDate: meetingData.meetingDate\n };\n});\n\n// Sort\nconst priorityOrder = { urgent: 0, high: 1, normal: 2, low: 3 };\nconst statusOrder = { overdue: 0, today: 1, urgent: 2, upcoming: 3, future: 4, 'no-deadline': 5 };\n\nmeetingData.actionItems.sort((a, b) => {\n const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];\n if (priorityDiff !== 0) return priorityDiff;\n const statusDiff = statusOrder[a.deadlineStatus] - statusOrder[b.deadlineStatus];\n if (statusDiff !== 0) return statusDiff;\n if (a.deadline === 'TBD' && b.deadline !== 'TBD') return 1;\n if (a.deadline !== 'TBD' && b.deadline === 'TBD') return -1;\n if (a.deadline !== 'TBD' && b.deadline !== 'TBD') {\n return new Date(a.deadline) - new Date(b.deadline);\n }\n return 0;\n});\n\nmeetingData.actionItems = meetingData.actionItems.map((item, index) => ({\n ...item,\n number: index + 1\n}));\n\n// Generate metadata\nconst urgentCount = meetingData.actionItems.filter(i => i.priority === 'urgent').length;\nconst highCount = meetingData.actionItems.filter(i => i.priority === 'high').length;\nconst normalCount = meetingData.actionItems.filter(i => i.priority === 'normal').length;\nconst lowCount = meetingData.actionItems.filter(i => i.priority === 'low').length;\nconst assigneeBreakdown = meetingData.actionItems.reduce((acc, item) => {\n acc[item.assignee] = (acc[item.assignee] || 0) + 1;\n return acc;\n}, {});\nconst overdueCount = meetingData.actionItems.filter(i => i.deadlineStatus === 'overdue').length;\nconst todayCount = meetingData.actionItems.filter(i => i.deadlineStatus === 'today').length;\nconst urgentDeadlineCount = meetingData.actionItems.filter(i => i.deadlineStatus === 'urgent').length;\nconst upcomingCount = meetingData.actionItems.filter(i => i.deadlineStatus === 'upcoming').length;\n\nmeetingData.summaryMetadata = {\n generatedAt: new Date().toISOString(),\n actionItemCount: meetingData.actionItems.length,\n participantCount: meetingData.participants.length,\n hasUrgentItems: urgentCount > 0,\n hasHighPriorityItems: highCount > 0,\n hasUnassignedItems: meetingData.actionItems.some(i => i.assignee === 'Unassigned'),\n hasOverdueItems: overdueCount > 0,\n hasTodayItems: todayCount > 0,\n priorityBreakdown: { urgent: urgentCount, high: highCount, normal: normalCount, low: lowCount },\n assigneeBreakdown: assigneeBreakdown,\n itemsWithDeadlines: meetingData.actionItems.filter(i => i.deadline !== 'TBD').length,\n itemsWithoutDeadlines: meetingData.actionItems.filter(i => i.deadline === 'TBD').length,\n deadlineStatus: {\n overdue: overdueCount,\n today: todayCount,\n urgent: urgentDeadlineCount,\n upcoming: upcomingCount,\n future: meetingData.actionItems.filter(i => i.deadlineStatus === 'future').length,\n noDeadline: meetingData.actionItems.filter(i => i.deadlineStatus === 'no-deadline').length\n },\n upcomingDeadlines: upcomingCount + urgentDeadlineCount + todayCount,\n overdueItems: overdueCount\n};\n\nconsole.log('\\n=== COMPLETE ===');\nconsole.log('Meeting:', meetingData.meetingTitle);\nconsole.log('Summary:', meetingData.summary.length, 'chars');\nconsole.log('Action Items:', meetingData.actionItems.length);\n\nreturn [{ json: meetingData }];"
},
"typeVersion": 2
},
{
"id": "fc46776e-2b89-4a64-9145-7755101a5138",
"name": "生成 PDF 文档",
"type": "n8n-nodes-htmlcsstopdf.htmlcsstopdf",
"position": [
2000,
-144
],
"parameters": {
"css_content": "=* { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif; line-height: 1.6; color: #1f2937; background: #ffffff; } .container { max-width: 900px; margin: 0 auto; padding: 60px 40px; } .header { border-bottom: 4px solid #3b82f6; padding-bottom: 30px; margin-bottom: 40px; background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%); padding: 40px; border-radius: 12px 12px 0 0; color: white; margin: -60px -40px 40px -40px; } .header h1 { font-size: 32px; font-weight: 700; margin-bottom: 12px; color: white; } .header .subtitle { font-size: 16px; opacity: 0.95; font-weight: 400; } .meta-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-top: 30px; padding: 25px; background: rgba(255, 255, 255, 0.1); border-radius: 8px; } .meta-item { display: flex; flex-direction: column; } .meta-label { font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; opacity: 0.8; margin-bottom: 6px; font-weight: 600; } .meta-value { font-size: 15px; font-weight: 500; } .section { margin: 50px 0; } .section-header { display: flex; align-items: center; margin-bottom: 20px; padding-bottom: 12px; border-bottom: 2px solid #e5e7eb; } .section-header h2 { font-size: 24px; color: #1e40af; font-weight: 700; margin: 0; } .section-header .icon { font-size: 28px; margin-right: 12px; } .summary-box { background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%); padding: 30px; border-radius: 10px; line-height: 1.8; font-size: 15px; color: #1f2937; border-left: 5px solid #3b82f6; box-shadow: 0 2px 8px rgba(59, 130, 246, 0.1); } .participants-box { background: #f9fafb; padding: 20px; border-radius: 8px; margin-bottom: 30px; } .participants-label { font-weight: 600; color: #374151; margin-bottom: 12px; font-size: 14px; text-transform: uppercase; letter-spacing: 0.5px; } .participant-tag { background: #f3f4f6; padding: 6px 12px; border-radius: 6px; font-size: 13px; color: #374151; margin-right: 8px; display: inline-block; margin-bottom: 6px; } table { width: 100%; border-collapse: collapse; background: white; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); border-radius: 8px; overflow: hidden; } thead { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); color: white; } th { padding: 18px 12px; text-align: left; font-weight: 600; font-size: 13px; text-transform: uppercase; letter-spacing: 0.5px; } tbody tr { border-bottom: 1px solid #e5e7eb; } tbody tr:hover { background: #f9fafb; } td { padding: 16px 12px; } .task-cell { font-weight: 500; color: #1f2937; margin-bottom: 4px; } .task-context { font-size: 13px; color: #6b7280; font-style: italic; } .assignee-badge { background: #eff6ff; color: #1e40af; padding: 6px 12px; border-radius: 6px; font-size: 13px; font-weight: 500; display: inline-block; } .priority-urgent { background: #ef4444; color: white; padding: 4px 10px; border-radius: 4px; font-size: 11px; font-weight: 600; text-transform: uppercase; } .priority-high { background: #f97316; color: white; padding: 4px 10px; border-radius: 4px; font-size: 11px; font-weight: 600; text-transform: uppercase; } .priority-normal { background: #3b82f6; color: white; padding: 4px 10px; border-radius: 4px; font-size: 11px; font-weight: 600; text-transform: uppercase; } .priority-low { background: #6b7280; color: white; padding: 4px 10px; border-radius: 4px; font-size: 11px; font-weight: 600; text-transform: uppercase; } .deadline-overdue { color: #dc2626; font-weight: 600; } .deadline-today { color: #ea580c; font-weight: 600; } .deadline-urgent { color: #f59e0b; font-weight: 600; } .deadline-upcoming { color: #3b82f6; } .deadline-future { color: #6b7280; } .urgent-banner { background: #fef2f2; border-left: 4px solid #ef4444; padding: 16px 20px; border-radius: 6px; margin-bottom: 20px; display: flex; align-items: center; } .urgent-banner-icon { font-size: 24px; margin-right: 12px; } .urgent-banner-text { color: #991b1b; font-weight: 600; font-size: 14px; } .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 20px; margin-top: 30px; } .stat-card { background: white; padding: 24px; border-radius: 10px; border: 2px solid #e5e7eb; text-align: center; } .stat-number { font-size: 36px; font-weight: 700; color: #3b82f6; margin-bottom: 8px; } .stat-label { font-size: 13px; color: #6b7280; text-transform: uppercase; letter-spacing: 0.5px; font-weight: 600; } .footer { margin-top: 60px; padding-top: 30px; border-top: 2px solid #e5e7eb; text-align: center; color: #6b7280; font-size: 13px; }",
"html_content": "=<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>{{ $json.meetingTitle }} - Meeting Minutes</title>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"header\">\n <h1>📋 {{ $json.meetingTitle }}</h1>\n <div class=\"subtitle\">Official Meeting Minutes & Action Items</div>\n <div class=\"meta-grid\">\n <div class=\"meta-item\">\n <div class=\"meta-label\">📅 Date</div>\n <div class=\"meta-value\">{{ $json.meetingDate }}</div>\n </div>\n <div class=\"meta-item\">\n <div class=\"meta-label\">⏱️ Duration</div>\n <div class=\"meta-value\">{{ $json.duration }}</div>\n </div>\n <div class=\"meta-item\">\n <div class=\"meta-label\">👥 Attendees</div>\n <div class=\"meta-value\">{{ $json.participants.length }} participants</div>\n </div>\n <div class=\"meta-item\">\n <div class=\"meta-label\">📊 Action Items</div>\n <div class=\"meta-value\">{{ $json.actionItems.length }} tasks</div>\n </div>\n </div>\n </div>\n\n {{ $json.summaryMetadata.hasOverdueItems || $json.summaryMetadata.hasTodayItems ? '<div class=\"urgent-banner\"><div class=\"urgent-banner-icon\">⚠️</div><div class=\"urgent-banner-text\">This meeting contains urgent action items requiring immediate attention!</div></div>' : '' }}\n\n <div class=\"participants-box\">\n <div class=\"participants-label\">Meeting Participants</div>\n {{ $json.participants.map(p => `<span class=\"participant-tag\">${p}</span>`).join('') }}\n </div>\n\n <div class=\"section\">\n <div class=\"section-header\">\n <span class=\"icon\">📝</span>\n <h2>Meeting Summary</h2>\n </div>\n <div class=\"summary-box\">{{ $json.summary }}</div>\n </div>\n\n <div class=\"section\">\n <div class=\"section-header\">\n <span class=\"icon\">✅</span>\n <h2>Action Items</h2>\n </div>\n <table>\n <thead>\n <tr>\n <th style=\"width:60px;text-align:center;\">#</th>\n <th>Task</th>\n <th style=\"width:180px;\">Assignee</th>\n <th style=\"width:120px;text-align:center;\">Deadline</th>\n <th style=\"width:120px;text-align:center;\">Priority</th>\n </tr>\n </thead>\n <tbody>\n {{ $json.actionItems.map(item => `\n <tr>\n <td style=\"text-align:center;font-weight:600;color:#3b82f6;\">#${item.number}</td>\n <td>\n <div class=\"task-cell\">${item.task}</div>\n ${item.context ? `<div class=\"task-context\">${item.context}</div>` : ''}\n </td>\n <td><span class=\"assignee-badge\">${item.assignee}</span></td>\n <td style=\"text-align:center;\">\n <span class=\"deadline-${item.deadlineStatus}\">\n ${item.deadlineStatus === 'overdue' ? '⚠️ OVERDUE' : \n item.deadlineStatus === 'today' ? '📅 TODAY' :\n item.deadlineStatus === 'urgent' ? `⏰ ${item.daysUntilDeadline} days` :\n item.daysUntilDeadline ? `${item.daysUntilDeadline} days` : 'TBD'}\n </span>\n </td>\n <td style=\"text-align:center;\">\n <span class=\"priority-${item.priority}\">\n ${item.priority === 'urgent' ? '🔥 URGENT' :\n item.priority === 'high' ? '⚡ HIGH' :\n item.priority === 'normal' ? '📋 NORMAL' : 'LOW'}\n </span>\n </td>\n </tr>\n `).join('') }}\n </tbody>\n </table>\n </div>\n\n <div class=\"section\">\n <div class=\"section-header\">\n <span class=\"icon\">📊</span>\n <h2>Summary Statistics</h2>\n </div>\n <div class=\"stats-grid\">\n <div class=\"stat-card\">\n <div class=\"stat-number\">{{ $json.summaryMetadata.actionItemCount }}</div>\n <div class=\"stat-label\">Total Tasks</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-number\">{{ $json.summaryMetadata.priorityBreakdown.high }}</div>\n <div class=\"stat-label\">High Priority</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-number\">{{ $json.summaryMetadata.upcomingDeadlines }}</div>\n <div class=\"stat-label\">Due This Week</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-number\">{{ $json.transcriptWordCount }}</div>\n <div class=\"stat-label\">Transcript Words</div>\n </div>\n </div>\n </div>\n\n <div class=\"footer\">\n <div style=\"font-size:20px;margin-bottom:12px;\">📋</div>\n Generated automatically on {{ new Date().toLocaleString() }}<br>\n Meeting Minutes Tracker · Powered by AI\n </div>\n </div>\n</body>\n</html>",
"response_format_html": "base64"
},
"credentials": {
"htmlcsstopdfApi": {
"id": "i5YZc3zx5V2RWZsk",
"name": "HtmlcsstopdfApi account"
}
},
"typeVersion": 1
},
{
"id": "dd362d07-117f-4069-9028-761e4105bf57",
"name": "邮件通知所有参与者",
"type": "n8n-nodes-base.gmail",
"position": [
2336,
-144
],
"webhookId": "e607a916-4f74-406a-9cc8-892c0b6b7568",
"parameters": {
"sendTo": "={{ $('Parse and Enrich Data').item.json.participants.join(',') }}",
"message": "=<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; color: #1f2937;\">\n <div style=\"background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%); padding: 30px; border-radius: 8px 8px 0 0; color: white;\">\n <h2 style=\"margin: 0; font-size: 24px;\">📋 {{ $('Parse and Enrich Data').item.json.meetingTitle }} </h2>\n <p style=\"margin: 10px 0 0 0; opacity: 0.9;\">Meeting Minutes & Action Items</p>\n </div>\n \n <div style=\"background: #ffffff; padding: 30px; border: 1px solid #e5e7eb; border-top: none;\">\n <p style=\"margin-top: 0;\">Hi team,</p>\n \n <p>The minutes from our meeting held on <strong>{{ $('Parse and Enrich Data').item.json.meetingDate }}</strong> are now available.</p>\n \n <div style=\"text-align: center; margin: 30px 0;\">\n <a href=\"{{ $json.pdf_url }}\" style=\"display: inline-block; background: #3b82f6; color: white; padding: 14px 32px; text-decoration: none; border-radius: 6px; font-weight: 600; font-size: 16px;\">\n 📥 Download Meeting Minutes PDF\n </a>\n </div>\n \n <div style=\"background: #f9fafb; border-left: 4px solid #3b82f6; padding: 20px; margin: 30px 0; border-radius: 4px;\">\n <h3 style=\"color: #1e40af; margin-top: 0; font-size: 18px;\">Action Items Summary</h3>\n <ul style=\"line-height: 2; margin: 15px 0; padding-left: 20px;\">\n {{ $('Parse and Enrich Data').item.json.actionItems.map(item => `\n <li style=\"margin-bottom: 10px;\">\n <strong>${item.task}</strong><br>\n <span style=\"color: #6b7280; font-size: 14px;\">\n Assigned to: ${item.assignee} | \n Due: ${item.deadline} | \n Priority: <span style=\"color: ${item.priority === 'high' || item.priority === 'urgent' ? '#ef4444' : '#3b82f6'};\">${item.priority.toUpperCase()}</span>\n </span>\n </li>\n `).join('') }}\n </ul>\n </div>\n \n <div style=\"background: #eff6ff; padding: 15px; border-radius: 6px; margin: 20px 0;\">\n <p style=\"margin: 0; font-size: 14px; color: #1e40af;\">\n <strong>📊 Meeting Stats:</strong> \n {{ $('Parse and Enrich Data').item.json.actionItems.length }} action items | \n {{ $('Parse and Enrich Data').item.json.summaryMetadata.priorityBreakdown.high}} high priority | \n {{$('Parse and Enrich Data').item.json.participants.length }} participants\n </p>\n </div>\n \n <p style=\"margin-top: 30px;\">The complete meeting minutes with full context and details are available in the PDF.</p>\n \n <p>Please review your assigned action items and reach out if you have any questions.</p>\n \n <p style=\"margin-bottom: 0;\">Best regards,<br><strong>Meeting Minutes Tracker</strong></p>\n </div>\n \n <div style=\"background: #f9fafb; padding: 20px; border: 1px solid #e5e7eb; border-top: none; border-radius: 0 0 8px 8px; text-align: center;\">\n <p style=\"margin: 0; color: #6b7280; font-size: 13px;\">\n Generated automatically on {{ $now.format('MMMM d, yyyy [at] h:mm a') }}<br>\n Powered by AI\n </p>\n </div>\n</div>",
"options": {},
"subject": "=📋 Meeting Minutes - {{ $('Parse and Enrich Data').item.json.meetingTitle }} ({{ $('Parse and Enrich Data').item.json.meetingDate }})"
},
"credentials": {
"gmailOAuth2": {
"id": "6XrYdrG9HaDZyzGH",
"name": "Gmail account - Akshita"
}
},
"typeVersion": 2.1
},
{
"id": "fd293c09-5c23-49eb-9766-c95ee3eb88df",
"name": "从 URL 下载 PDF",
"type": "n8n-nodes-base.httpRequest",
"position": [
2352,
144
],
"parameters": {
"url": "={{ $json.pdf_url }}",
"options": {
"response": {
"response": {
"responseFormat": "file"
}
}
}
},
"typeVersion": 4.2
},
{
"id": "64259b9e-7983-4239-aae2-07542f928e6a",
"name": "保存 PDF 到 Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
2640,
144
],
"parameters": {
"name": "=Meeting_Minutes_{{ $('Parse and Enrich Data').item.json.meetingTitle.replace(/ /g, '_') }}_{{ $('Parse and Enrich Data').item.json.meetingDate }}.pdf",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "1bYMdPQZm3Z4ChhZ6UjLMJb5BJKFOhp8R",
"cachedResultUrl": "https://drive.google.com/drive/folders/1bYMdPQZm3Z4ChhZ6UjLMJb5BJKFOhp8R",
"cachedResultName": "Minutes of Meeting"
},
"inputDataFieldName": "=data"
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "cHZ7WuviBMkjVwrb",
"name": "Google Drive account"
}
},
"typeVersion": 3
},
{
"id": "994f49a2-c94d-4982-b827-a9be5c56b5a1",
"name": "添加 PDF 下载链接",
"type": "n8n-nodes-base.set",
"position": [
2912,
144
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "9c0c1e1f-c4e4-4db6-add0-e97e768ec0d9",
"name": "pdfUrl",
"type": "string",
"value": "={{ $json.webViewLink }}"
},
{
"id": "6efe7494-9032-4a94-a3f8-c35d5f80865b",
"name": "pdfFileName",
"type": "string",
"value": "={{ $json.name }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "49568bb8-c40b-4229-873d-d3bb2695b95b",
"name": "通知 Slack 频道",
"type": "n8n-nodes-base.slack",
"position": [
3280,
-64
],
"webhookId": "1dcd2233-c899-440c-ab08-1c6fb69f484b",
"parameters": {
"text": "=:clipboard: *New Meeting Minutes Available*\n\n*Meeting:* {{ $('Parse and Enrich Data').item.json.meetingTitle }}\n*Date:* {{ $('Parse and Enrich Data').item.json.meetingDate }}\n*Participants:* {{ $('Parse and Enrich Data').item.json.participants .length }} attendees\n\n*Action Items Summary:*\n{{ $('Parse and Enrich Data').item.json.actionItems.map((item, i) => `${i + 1}. ${item.task} - ${item.assignee} (${item.deadline}) [${item.priority.toUpperCase()}]`).join('\\n') }}\n\n:link: *Download PDF:* {{ $json.pdfUrl }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09GHQ8CL82",
"cachedResultName": "leads"
},
"otherOptions": {
"includeLinkToWorkflow": true
},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"id": "iEf25ruXA6CT1PJH",
"name": "Slack account 3 - Akshita"
}
},
"typeVersion": 2.3
},
{
"id": "76e76682-b710-4239-910f-9d464e04479b",
"name": "按负责人分组任务",
"type": "n8n-nodes-base.code",
"position": [
3264,
304
],
"parameters": {
"jsCode": "const parseData = $('Parse and Enrich Data').first().json;\nconst actionItems = parseData.actionItems || [];\nconst pdfUrl = $json.pdfUrl || $json.webViewLink || '';\n\nif (actionItems.length === 0) {\n return [];\n}\n\n// Group tasks by assignee\nconst grouped = {};\nactionItems.forEach(item => {\n if (!grouped[item.assignee]) {\n grouped[item.assignee] = [];\n }\n grouped[item.assignee].push(item);\n});\n\n// Return one item per assignee\nreturn Object.keys(grouped).map(assignee => ({\n json: {\n assignee: assignee,\n tasks: grouped[assignee],\n taskCount: grouped[assignee].length,\n meetingTitle: parseData.meetingTitle,\n meetingDate: parseData.meetingDate,\n pdfUrl: pdfUrl\n }\n}));"
},
"typeVersion": 2
},
{
"id": "b4a682ee-58a8-4bf4-a915-a4ac51d0f8dc",
"name": "发送个人任务邮件",
"type": "n8n-nodes-base.gmail",
"position": [
3632,
304
],
"webhookId": "229e1653-aac1-4a82-b2f8-a95d9536ea85",
"parameters": {
"sendTo": "={{ $json.assignee }}@yourcompany.com",
"message": "=<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;\">\n <div style=\"background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%); padding: 30px; border-radius: 8px 8px 0 0; color: white;\">\n <h2 style=\"margin: 0; font-size: 24px;\">📋 {{ $json.meetingTitle }}</h2>\n <p style=\"margin: 10px 0 0 0; opacity: 0.9;\">Action Items Assigned to You</p>\n </div>\n \n <div style=\"background: white; padding: 30px; border: 1px solid #e5e7eb; border-top: none;\">\n <p style=\"margin-top: 0;\">Hi <strong>{{ $json.assignee }}</strong>,</p>\n \n <p>You have <strong>{{ $json.taskCount }}</strong> action {{ $json.taskCount === 1 ? 'item' : 'items' }} from the meeting held on <strong>{{ $json.meetingDate }}</strong>:</p>\n \n {{ $json.tasks.map((task, i) => `\n <div style=\"background: ${task.priority === 'high' || task.priority === 'urgent' ? '#fef2f2' : '#f0f9ff'}; border-left: 4px solid ${task.priority === 'high' || task.priority === 'urgent' ? '#ef4444' : '#3b82f6'}; padding: 20px; margin: 20px 0; border-radius: 4px;\">\n <div style=\"display: flex; justify-content: space-between; align-items: start; margin-bottom: 10px;\">\n <h3 style=\"margin: 0; color: #1e40af; font-size: 16px;\">Task ${i + 1}</h3>\n <span style=\"background: ${task.priority === 'high' || task.priority === 'urgent' ? '#ef4444' : task.priority === 'normal' ? '#3b82f6' : '#6b7280'}; color: white; padding: 4px 10px; border-radius: 4px; font-size: 11px; font-weight: 600; text-transform: uppercase;\">\n ${task.priority === 'high' ? '⚡ HIGH' : task.priority === 'urgent' ? '🔥 URGENT' : task.priority === 'normal' ? '📋 NORMAL' : 'LOW'}\n </span>\n </div>\n \n <p style=\"font-size: 15px; font-weight: 600; color: #1f2937; margin: 10px 0; line-height: 1.5;\">\n ${task.task}\n </p>\n \n <div style=\"margin: 12px 0; padding: 12px; background: white; border-radius: 4px;\">\n <p style=\"margin: 5px 0; color: #374151; font-size: 14px;\">\n <strong>📅 Deadline:</strong> ${task.deadline} \n ${task.daysUntilDeadline !== null ? `<span style=\"color: ${task.deadlineStatus === 'overdue' ? '#dc2626' : task.deadlineStatus === 'urgent' ? '#f59e0b' : '#6b7280'};\">(${task.daysUntilDeadline} day${task.daysUntilDeadline === 1 ? '' : 's'})</span>` : ''}\n </p>\n <p style=\"margin: 5px 0; color: #374151; font-size: 14px;\">\n <strong>📌 Status:</strong> ${task.status}\n </p>\n </div>\n \n ${task.context ? `<p style=\"margin-top: 12px; font-style: italic; color: #6b7280; font-size: 13px; line-height: 1.5; padding-top: 12px; border-top: 1px dashed #d1d5db;\">${task.context}</p>` : ''}\n </div>\n `).join('') }}\n \n <div style=\"text-align: center; margin: 35px 0;\">\n <a href=\"{{ $json.pdfUrl }}\" style=\"display: inline-block; background: #3b82f6; color: white; padding: 14px 28px; text-decoration: none; border-radius: 6px; font-weight: 600; font-size: 15px; box-shadow: 0 2px 4px rgba(59, 130, 246, 0.3);\">\n 📥 Download Full Meeting Minutes\n </a>\n </div>",
"options": {},
"subject": "=⚡ {{ $json.taskCount }} Action {{ $json.taskCount === 1 ? 'Item' : 'Items' }} from {{ $json.meetingTitle }}"
},
"credentials": {
"gmailOAuth2": {
"id": "6XrYdrG9HaDZyzGH",
"name": "Gmail account - Akshita"
}
},
"typeVersion": 2.1
},
{
"id": "a75840d6-4c1f-4940-8a9b-9f05f121c754",
"name": "拆分任务以创建",
"type": "n8n-nodes-base.code",
"position": [
2000,
528
],
"parameters": {
"jsCode": "const actionItems = $json.actionItems || [];\nconst meetingTitle = $json.meetingTitle;\nconst meetingDate = $json.meetingDate;\nconst pdfUrl = $json.pdfUrl || '';\n\nif (actionItems.length === 0) {\n return [];\n}\n\n// Return one item per action item for task creation\nreturn actionItems.map(item => ({\n json: {\n task: item.task,\n assignee: item.assignee,\n deadline: item.deadline,\n priority: item.priority,\n context: item.context,\n meetingTitle: meetingTitle,\n meetingDate: meetingDate,\n status: item.status,\n daysUntilDeadline: item.daysUntilDeadline\n }\n}));"
},
"typeVersion": 2
},
{
"id": "59146f07-6b6c-4c0b-a31c-37afa7b01ef7",
"name": "在 Google Tasks 中创建任务",
"type": "n8n-nodes-base.googleTasks",
"position": [
2304,
528
],
"parameters": {
"task": "MTYxODQ3NTU3ODAzODc5Njg1NTk6MDow",
"title": "={{ $json.task }}",
"additionalFields": {
"notes": "={{ $json.context }} \nMeeting: {{ $json.meetingTitle }} \nDate: {{ $json.meetingDate }} \nAssignee: {{ $json.assignee }} \nPriority: {{ $json.priority }}",
"dueDate": "={{ $json.deadline ? new Date($json.deadline + 'T12:00:00Z').toISOString() : null }}"
}
},
"credentials": {
"googleTasksOAuth2Api": {
"id": "2DSvIyWd57G4NTCB",
"name": "Google Tasks account 2 - Akshita"
}
},
"typeVersion": 1
},
{
"id": "063a6dc6-cf1c-4a4a-9994-2fb1e9e8f291",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-304,
-224
],
"parameters": {
"color": 7,
"width": 288,
"height": 352,
"content": "## WEBHOOK 端点"
},
"typeVersion": 1
},
{
"id": "22ca0f0e-3fc2-4dbc-b5d2-86fcc508c93b",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
16,
-288
],
"parameters": {
"color": 7,
"width": 304,
"height": 464,
"content": "## 数据规范化"
},
"typeVersion": 1
},
{
"id": "5173480f-55d9-4786-a46d-8f9ce7a7ef5d",
"name": "便签2",
"type": "n8n-nodes-base.stickyNote",
"position": [
352,
-336
],
"parameters": {
"color": 7,
"height": 480,
"content": "## 转录文本清理"
},
"typeVersion": 1
},
{
"id": "ba992adf-ec87-48bb-b130-b41af85ad4c4",
"name": "便签3",
"type": "n8n-nodes-base.stickyNote",
"position": [
624,
-256
],
"parameters": {
"color": 7,
"width": 272,
"height": 400,
"content": "## 质量门控"
},
"typeVersion": 1
},
{
"id": "66f5fafa-740b-4a27-893e-d4bcc4db9fcb",
"name": "便签4",
"type": "n8n-nodes-base.stickyNote",
"position": [
928,
-336
],
"parameters": {
"color": 7,
"width": 288,
"height": 320,
"content": "## OPENAI 摘要 (GPT-4)"
},
"typeVersion": 1
},
{
"id": "5b0681a7-fd69-4f62-b881-2f27891871ef",
"name": "便签5",
"type": "n8n-nodes-base.stickyNote",
"position": [
928,
112
],
"parameters": {
"color": 7,
"width": 288,
"height": 400,
"content": "## OPENAI 行动项提取 (GPT-4)"
},
"typeVersion": 1
},
{
"id": "0723ad57-23fb-41dc-9b95-71b4efda99d2",
"name": "便签6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1296,
-240
],
"parameters": {
"color": 7,
"height": 384,
"content": "## 合并 AI 响应"
},
"typeVersion": 1
},
{
"id": "b63e42ec-dd33-4b4b-853c-126a905ef376",
"name": "便签7",
"type": "n8n-nodes-base.stickyNote",
"position": [
1568,
-368
],
"parameters": {
"color": 7,
"width": 272,
"height": 496,
"content": "## 数据结构化"
},
"typeVersion": 1
},
{
"id": "96e5ac65-f844-45f2-b598-2f2d23667122",
"name": "便签8",
"type": "n8n-nodes-base.stickyNote",
"position": [
1904,
-448
],
"parameters": {
"color": 7,
"width": 304,
"height": 464,
"content": "## PDF 转换"
},
"typeVersion": 1
},
{
"id": "9e64cb89-011d-407f-b046-66f2b2723f04",
"name": "便签9",
"type": "n8n-nodes-base.stickyNote",
"position": [
2288,
-368
],
"parameters": {
"color": 7,
"width": 352,
"height": 368,
"content": "## 批量邮件通知"
},
"typeVersion": 1
},
{
"id": "e0f7c258-a987-4667-8eee-702336525b23",
"name": "便签10",
"type": "n8n-nodes-base.stickyNote",
"position": [
2016,
80
],
"parameters": {
"color": 7,
"width": 480,
"height": 208,
"content": "## PDF URL 获取"
},
"typeVersion": 1
},
{
"id": "5c473a51-227c-4483-b064-d12c20482212",
"name": "便签11",
"type": "n8n-nodes-base.stickyNote",
"position": [
2544,
128
],
"parameters": {
"color": 7,
"width": 288,
"height": 432,
"content": "## 云存储"
},
"typeVersion": 1
},
{
"id": "649ba897-6e40-42c8-bbb1-e4dc1545f383",
"name": "便签12",
"type": "n8n-nodes-base.stickyNote",
"position": [
2848,
-80
],
"parameters": {
"color": 7,
"height": 384,
"content": "## URL 提取"
},
"typeVersion": 1
},
{
"id": "2c634a33-5e61-4a88-b6ba-1488dca2cab8",
"name": "便签13",
"type": "n8n-nodes-base.stickyNote",
"position": [
3184,
-304
],
"parameters": {
"color": 7,
"width": 320,
"height": 384,
"content": "## 团队频道更新"
},
"typeVersion": 1
},
{
"id": "ff75e3fe-540c-4c7d-be9e-3c6b4b4d03b1",
"name": "便签14",
"type": "n8n-nodes-base.stickyNote",
"position": [
3152,
288
],
"parameters": {
"color": 7,
"width": 320,
"height": 416,
"content": "## 负责人分组"
},
"typeVersion": 1
},
{
"id": "d7d7e9b6-16b5-4db2-be87-20501af66bef",
"name": "便签15",
"type": "n8n-nodes-base.stickyNote",
"position": [
3568,
16
],
"parameters": {
"color": 7,
"width": 336,
"height": 464,
"content": "## 个性化任务通知"
},
"typeVersion": 1
},
{
"id": "b26bb8e7-6955-42e2-997a-139105fcd227",
"name": "便签16",
"type": "n8n-nodes-base.stickyNote",
"position": [
1888,
512
],
"parameters": {
"color": 7,
"width": 320,
"height": 400,
"content": "## 任务项分离"
},
"typeVersion": 1
},
{
"id": "b7dd2f52-cc18-4636-846b-0038e3b23eb8",
"name": "便签17",
"type": "n8n-nodes-base.stickyNote",
"position": [
2240,
512
],
"parameters": {
"color": 7,
"width": 272,
"height": 544,
"content": "## 任务管理集成"
},
"typeVersion": 1
},
{
"id": "756c055c-ef44-4368-8531-44faa8ebb6a1",
"name": "便签18",
"type": "n8n-nodes-base.stickyNote",
"position": [
-816,
-352
],
"parameters": {
"color": 7,
"width": 464,
"height": 1184,
"content": "## 会议纪要和行动项跟踪器 - 概述"
},
"typeVersion": 1
},
{
"id": "2828c58b-106b-4131-8e52-7baf1478b85b",
"name": "便签19",
"type": "n8n-nodes-base.stickyNote",
"position": [
-288,
512
],
"parameters": {
"color": 7,
"width": 592,
"height": 1136,
"content": "## 设置说明"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "ff824dc2-123e-4310-a036-d320361fffe1",
"connections": {
"Clean Transcript": {
"main": [
[
{
"node": "Validate Transcript Length",
"type": "main",
"index": 0
}
]
]
},
"Save PDF to Drive": {
"main": [
[
{
"node": "Add PDF Download Link",
"type": "main",
"index": 0
}
]
]
},
"Combine AI Responses": {
"main": [
[
{
"node": "Parse and Enrich Data",
"type": "main",
"index": 0
}
]
]
},
"Extract Action Items": {
"main": [
[
{
"node": "Combine AI Responses",
"type": "main",
"index": 1
}
]
]
},
"Notify Slack Channel": {
"main": [
[]
]
},
"Receive Meeting Data": {
"main": [
[
{
"node": "Extract Meeting Metadata",
"type": "main",
"index": 0
}
]
]
},
"Add PDF Download Link": {
"main": [
[
{
"node": "Notify Slack Channel",
"type": "main",
"index": 0
},
{
"node": "Group Tasks by Assignee",
"type": "main",
"index": 0
}
]
]
},
"Download PDF from URL": {
"main": [
[
{
"node": "Save PDF to Drive",
"type": "main",
"index": 0
}
]
]
},
"Generate PDF Document": {
"main": [
[
{
"node": "Email All Participants",
"type": "main",
"index": 0
},
{
"node": "Download PDF from URL",
"type": "main",
"index": 0
}
]
]
},
"Parse and Enrich Data": {
"main": [
[
{
"node": "Generate PDF Document",
"type": "main",
"index": 0
},
{
"node": "Split Tasks for Creation",
"type": "main",
"index": 0
}
]
]
},
"Email All Participants": {
"main": [
[]
]
},
"Group Tasks by Assignee": {
"main": [
[
{
"node": "Send Individual Task Emails",
"type": "main",
"index": 0
}
]
]
},
"Extract Meeting Metadata": {
"main": [
[
{
"node": "Clean Transcript",
"type": "main",
"index": 0
}
]
]
},
"Generate Meeting Summary": {
"main": [
[
{
"node": "Combine AI Responses",
"type": "main",
"index": 0
}
]
]
},
"Split Tasks for Creation": {
"main": [
[
{
"node": "Create Task in Google Tasks",
"type": "main",
"index": 0
}
]
]
},
"Validate Transcript Length": {
"main": [
[
{
"node": "Generate Meeting Summary",
"type": "main",
"index": 0
},
{
"node": "Extract Action Items",
"type": "main",
"index": 0
}
]
]
},
"Send Individual Task Emails": {
"main": [
[]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 内容创作, 多模态 AI
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
客户支持工单工作流自动化
使用GPT-4、PDF和Google Drive将支持工单转换为AI文档
If
Set
Code
+8
28 节点Jitesh Dugar
内容创作
防欺诈潜在客户捕获与培育系统
通过AI评分、表格跟踪和多渠道提醒捕获和培育防欺诈潜在客户
If
Set
Code
+11
28 节点Jitesh Dugar
内容创作
发票和收据生成器(HTML转PDF)
自动发票生成器 - 从Shopify到PDF,支持Google Drive存储和邮件发送
If
Code
Gmail
+6
19 节点Jitesh Dugar
内容创作
客户入职工作流
使用PDF、Trello、Slack、Gmail和Airtable简化客户入职流程
If
Code
Gmail
+10
22 节点Jitesh Dugar
内容创作
自动化推荐工作流
使用GPT-4处理推荐信,并通过Google表格自动生成社交媒体卡片
If
Set
Code
+9
34 节点Jitesh Dugar
社交媒体
已验证产品退货指南生成器
使用邮件验证、PDF/图片生成和二维码自动化电商退货指南
Set
Code
Gmail
+10
23 节点Jitesh Dugar
内容创作
工作流信息
难度等级
高级
节点数量38
分类2
节点类型13
作者
Jitesh Dugar
@jiteshdugarAI Automation Specialist - OpenAI, CRM & Automation Expert with a solid understanding of various tools that include Zapier, Make, Zoho CRM, Hubspot, Google Sheets, Airtable, Pipedrive, Google Analytics, and more.
外部链接
在 n8n.io 查看 →
分享此工作流