8
n8n 中文网amn8n.com

带附件的自动化 Slack 到 Jira 问题创建

高级

这是一个Content Creation, Multimodal AI领域的自动化工作流,包含 19 个节点。主要使用 If, Code, Jira, Slack, HttpRequest 等节点。 带附件的自动化Slack到Jira问题创建

前置要求
  • Slack Bot Token 或 Webhook URL
  • 可能需要目标 API 的认证凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "UWaBGGumTuGmryJq",
  "meta": {
    "instanceId": "8443f10082278c46aa5cf3acf8ff0f70061a2c58bce76efac814b16290845177",
    "templateCredsSetupCompleted": true
  },
  "name": "带附件的自动化 Slack 到 Jira 问题创建",
  "tags": [
    {
      "id": "SHQpff6D2VUAhiBO",
      "name": "slack-integration",
      "createdAt": "2025-09-03T10:01:17.871Z",
      "updatedAt": "2025-09-03T10:01:17.871Z"
    },
    {
      "id": "us8CC0JZKBaYTMbE",
      "name": "automation",
      "createdAt": "2025-09-03T10:01:17.853Z",
      "updatedAt": "2025-09-03T10:01:17.853Z"
    }
  ],
  "nodes": [
    {
      "id": "9a2f9325-f367-4178-b57f-da06ce268aa3",
      "name": "便签7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        2544
      ],
      "parameters": {
        "color": 5,
        "height": 320,
        "content": "目的:将下载的文件附加到创建的 Jira 问题"
      },
      "typeVersion": 1
    },
    {
      "id": "45ca44bb-fcf5-4892-8915-b5b561d489ee",
      "name": "便签8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        2240
      ],
      "parameters": {
        "color": 3,
        "height": 320,
        "content": "目的:使用私有 URL 从 Slack 下载文件"
      },
      "typeVersion": 1
    },
    {
      "id": "a9b50384-69f7-4325-b209-9b8b0980d4fd",
      "name": "### 替换 Airtable 连接",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -96,
        3088
      ],
      "parameters": {
        "color": 6,
        "height": 272,
        "content": "目的:使用解析后的数据创建新的 Jira 问题"
      },
      "typeVersion": 1
    },
    {
      "id": "89199791-4879-47be-8d99-f6b5be1eb3e2",
      "name": "便签10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -336,
        2480
      ],
      "parameters": {
        "color": 2,
        "height": 384,
        "content": "目的:从 Slack 消息文本中提取结构化问题详情"
      },
      "typeVersion": 1
    },
    {
      "id": "618371b4-bf61-4a9e-b76a-8081716eef8c",
      "name": "便签11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -896,
        2544
      ],
      "parameters": {
        "height": 352,
        "content": "目的:监控特定 Slack 频道的新消息"
      },
      "typeVersion": 1
    },
    {
      "id": "bcabc988-0058-4e65-8e1e-cf7d32dacfec",
      "name": "便签12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        848,
        2976
      ],
      "parameters": {
        "color": 4,
        "height": 224,
        "content": "目的:发送确认消息回 Slack"
      },
      "typeVersion": 1
    },
    {
      "id": "31b4df31-3567-40b3-b44d-06a2f9e5abcd",
      "name": "便签13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        2592
      ],
      "parameters": {
        "color": 3,
        "height": 288,
        "content": "目的:将多个附件拆分为单独项目进行处理"
      },
      "typeVersion": 1
    },
    {
      "id": "9c766474-c73f-4579-a938-e7a02e7e88e2",
      "name": "便签 - 拆分文件",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        512,
        2512
      ],
      "parameters": {
        "color": 5,
        "height": 240,
        "content": "新增:将所有文件拆分为单独批次"
      },
      "typeVersion": 1
    },
    {
      "id": "df70376c-d7cd-48ae-a90d-f9ae05647257",
      "name": "Slack 触发器",
      "type": "n8n-nodes-base.slackTrigger",
      "position": [
        -720,
        2912
      ],
      "webhookId": "7cadf9c3-f927-4738-aa85-11fb035ffcf5",
      "parameters": {
        "options": {},
        "trigger": [
          "message"
        ],
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09CVLMSF3R",
          "cachedResultName": "issue-smarteremr"
        }
      },
      "credentials": {
        "slackApi": {
          "id": "rNqvWj9TfChPVRYY",
          "name": "Slack account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "65a9703b-d356-442c-99a5-8d2351843374",
      "name": "准备处理文件",
      "type": "n8n-nodes-base.code",
      "position": [
        400,
        2784
      ],
      "parameters": {
        "jsCode": "// Extract files from Parse Message and prepare them for batch processing\nconst parseMessageData = $('Parse Message into Jira Format').first().json;\nconst jiraIssueData = $('Create Jira Issue').first().json;\n\nconsole.log('Parse Message Data:', JSON.stringify(parseMessageData, null, 2));\nconsole.log('Jira Issue Data:', JSON.stringify(jiraIssueData, null, 2));\n\n// Extract files from the attachments array (not files array)\nconst files = parseMessageData.attachments || [];\nconst jiraIssueKey = jiraIssueData.key;\n\nconsole.log(`Found ${files.length} files to process`);\nconsole.log('Jira Issue Key:', jiraIssueKey);\n\n// Return each file as a separate item with the Jira issue key\nconst items = files.map((file, index) => {\n  return {\n    fileId: file.id,\n    fileName: file.name || file.title || `file_${index}`,\n    fileUrl: file.url, // Use the url property from your attachments\n    jiraIssueKey: jiraIssueKey,\n    fileIndex: index,\n    totalFiles: files.length,\n    originalFile: file\n  };\n});\n\nconsole.log('Prepared items for batch processing:', JSON.stringify(items, null, 2));\n\nreturn items;"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "3b52b68f-beb7-4f72-a1db-439761d9235a",
      "name": "将文件拆分为批次",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        624,
        2784
      ],
      "parameters": {
        "options": {
          "reset": false
        }
      },
      "typeVersion": 3
    },
    {
      "id": "23c27f8e-283e-4247-9103-1cf5b8052801",
      "name": "上传附件到 Jira",
      "type": "n8n-nodes-base.jira",
      "position": [
        1296,
        2736
      ],
      "parameters": {
        "issueKey": "={{ $('Split Files into Batches').item.json.jiraIssueKey }}",
        "resource": "issueAttachment"
      },
      "credentials": {
        "jiraSoftwareCloudApi": {
          "id": "Q6d7sLBVOfGWmaLw",
          "name": "Jira SW Cloud account 3"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "749ae50d-dec2-4245-a560-24b689250fdc",
      "name": "检查消息",
      "type": "n8n-nodes-base.if",
      "position": [
        -496,
        2912
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "0eb704ae-11e8-4588-a0fb-02b1f7c1cde7",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.text }}",
              "rightValue": "title"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "e74b893a-4c33-4de3-bc1e-d82f2f792e7a",
      "name": "在 Slack 上回复频道",
      "type": "n8n-nodes-base.slack",
      "position": [
        848,
        2784
      ],
      "webhookId": "326747fc-4f09-4a30-9836-ead0ec1316c1",
      "parameters": {
        "text": "=✅ Jira Issue Created Successfully!\n\n🎫 Issue Key: https://herevivekpatidar.atlassian.net/browse/{{ $('Create Jira Issue').item.json.key }}\n\n📝 Title: {{ $('Parse Message into Jira Format').item.json.summary }} \n\n📝 Description:{{ $('Parse Message into Jira Format').item.json.extractedData.descriptionMatch }}\n\n📋 issueType: {{ $('Parse Message into Jira Format').item.json.issueTypeName }}\n\n⚡Priority: {{ $('Parse Message into Jira Format').item.json.priority }}\n\n📎 Attachments: {{ $('Parse Message into Jira Format').item.json.files.length }} file(s) uploaded\n\nThank you for reporting this issue!",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09D7N4MXFF",
          "cachedResultName": "tickets"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "DCKcEblxPx2EbUUX",
          "name": "Slack account 3"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "68fa2a54-85a5-42cb-99c1-3a6c398a7226",
      "name": "将消息解析为 Jira 格式",
      "type": "n8n-nodes-base.code",
      "position": [
        -272,
        2912
      ],
      "parameters": {
        "jsCode": "// Enhanced Parse Slack message - handles both plain text and rich text blocks\nconst message = $input.first().json;\nlet text = message.text || '';\nconst user = message.user || '';\nconst channel = message.channel || '';\nconst files = message.files || [];\nconst timestamp = message.ts || '';\nconst blocks = message.blocks || [];\n\nconsole.log('Original text length:', text.length);\nconsole.log('Blocks found:', blocks.length);\nconsole.log('Files found:', files.length);\n\n// Extract text from rich text blocks if available (this gives us complete text)\nif (blocks && blocks.length > 0) {\n  let richText = '';\n  \n  blocks.forEach(block => {\n    if (block.type === 'rich_text' && block.elements) {\n      block.elements.forEach(element => {\n        if (element.type === 'rich_text_section' && element.elements) {\n          element.elements.forEach(textElement => {\n            if (textElement.type === 'text') {\n              richText += textElement.text || '';\n            }\n          });\n        } else if (element.type === 'rich_text_list' && element.elements) {\n          // Handle bullet points and lists\n          element.elements.forEach(listItem => {\n            if (listItem.elements) {\n              richText += '\\n• ';\n              listItem.elements.forEach(listTextElement => {\n                if (listTextElement.type === 'text') {\n                  richText += listTextElement.text || '';\n                }\n              });\n            }\n          });\n        }\n      });\n    }\n  });\n  \n  // Use rich text if it's longer and contains more content\n  if (richText.length > text.length) {\n    console.log('Using rich text content (length:', richText.length, ')');\n    text = richText;\n  }\n}\n\nconsole.log('Final text length:', text.length);\nconsole.log('Text preview:', text.substring(0, 200) + '...');\n\n// Log file details for debugging\nfiles.forEach((file, index) => {\n  console.log(`File ${index}:`, {\n    id: file.id,\n    name: file.name,\n    mimetype: file.mimetype,\n    size: file.size,\n    filetype: file.filetype\n  });\n});\n\n// Robust regex patterns for title*:* format with flexible spacing\nconst titleMatch = text.match(/title\\s*\\*?\\s*:\\s*\\*?\\s*([^\\n]*?)(?=\\s*(?:\\n|$))/i);\n\n// For description, capture everything after description*:* until we hit priority: or type:\nconst descriptionMatch = text.match(/description\\s*\\*?\\s*:\\s*\\*?\\s*([\\s\\S]*?)(?=\\s*priority\\s*\\*?\\s*:\\s*\\*?|$)/i);\n\n// Priority - capture just the value after priority:\nconst priorityMatch = text.match(/priority\\s*\\*?\\s*:\\s*\\*?\\s*([^\\n]*?)(?=\\s*(?:\\n|$))/i);\n\n// Type - capture just the value after type:\nconst typeMatch = text.match(/type\\s*\\*?\\s*:\\s*\\*?\\s*([^\\n]*?)(?=\\s*(?:\\n|$))/i);\n\n// Enhanced text cleaning function\nconst cleanText = (str) => {\n  if (!str) return null;\n  \n  return str\n    .replace(/^\\s*[\\*_\\-\\+=]*\\s*/, '') // Remove leading special characters\n    .replace(/\\s*[\\*_\\-\\+=]*\\s*$/, '') // Remove trailing special characters\n    .replace(/\\*+/g, '') // Remove asterisks\n    .replace(/_{2,}/g, '') // Remove multiple underscores\n    .replace(/^\\s+/gm, '') // Remove leading whitespace from lines\n    .replace(/\\s+$/gm, '') // Remove trailing whitespace from lines\n    .replace(/\\n\\s*\\n+/g, '\\n\\n') // Normalize multiple newlines\n    .trim();\n};\n\n// Clean and extract values\nconst extractedTitle = titleMatch ? cleanText(titleMatch[1]) : null;\nconst extractedDescription = descriptionMatch ? cleanText(descriptionMatch[1]) : null;\nconst extractedPriority = priorityMatch ? cleanText(priorityMatch[1]) : null;\nconst extractedType = typeMatch ? cleanText(typeMatch[1]) : null;\n\n// Enhanced logging\nconsole.log('=== EXTRACTION RESULTS ===');\nconsole.log('Title match:', !!titleMatch, '- Value:', extractedTitle);\nconsole.log('Description match:', !!descriptionMatch, '- Length:', extractedDescription ? extractedDescription.length : 0);\nconsole.log('Priority match:', !!priorityMatch, '- Value:', extractedPriority);\nconsole.log('Type match:', !!typeMatch, '- Value:', extractedType);\n\n// Smart fallback logic\nconst summary = (extractedTitle && extractedTitle.length > 3) ? \n               extractedTitle : 'Issue reported from Slack';\n\nconst description = (extractedDescription && extractedDescription.length > 5) ? \n                   extractedDescription : 'No description provided';\n\n// Enhanced priority parsing\nconst determinePriority = (priorityText) => {\n  if (!priorityText) return 'medium';\n  \n  const lowerPriority = priorityText.toLowerCase().trim();\n  const cleanPriority = lowerPriority.replace(/[^\\w\\s]/g, '').trim();\n  \n  if (['critical', 'urgent', 'highest', 'blocker'].includes(cleanPriority)) return 'critical';\n  if (['high'].includes(cleanPriority)) return 'high';\n  if (['medium', 'med', 'normal', 'moderate'].includes(cleanPriority)) return 'medium';\n  if (['low', 'lowest', 'minor'].includes(cleanPriority)) return 'low';\n  \n  if (cleanPriority.includes('critical') || cleanPriority.includes('urgent')) return 'critical';\n  if (cleanPriority.includes('high')) return 'high';\n  if (cleanPriority.includes('low')) return 'low';\n  \n  return 'medium';\n};\n\n// Enhanced issue type parsing\nconst determineIssueType = (typeText) => {\n  if (!typeText) return 'enhancement';\n  \n  const lowerType = typeText.toLowerCase().trim();\n  const cleanType = lowerType.replace(/[^\\w\\s]/g, '').trim();\n  \n  const typeMapping = {\n    'bug': 'bug', 'issue': 'bug', 'defect': 'bug', 'error': 'bug', 'problem': 'bug',\n    'feature': 'feature', 'story': 'feature', 'request': 'feature', 'new': 'feature',\n    'enhancement': 'enhancement', 'improvement': 'enhancement', 'modify': 'enhancement', \n    'change': 'enhancement', 'update': 'enhancement', 'enhance': 'enhancement',\n    'task': 'task', 'todo': 'task', 'work': 'task', 'chore': 'task',\n    'epic': 'epic'\n  };\n  \n  if (typeMapping[cleanType]) return typeMapping[cleanType];\n  \n  for (const [key, value] of Object.entries(typeMapping)) {\n    if (cleanType.includes(key)) return value;\n  }\n  \n  return 'enhancement';\n};\n\nconst priority = determinePriority(extractedPriority);\nconst issueType = determineIssueType(extractedType);\n\n// Map to Jira values with IDs\nconst priorityMapping = {\n  'critical': { name: 'Highest', id: '1' },\n  'high': { name: 'High', id: '2' },\n  'medium': { name: 'Medium', id: '3' },\n  'low': { name: 'Low', id: '4' }\n};\nconst jiraPriorityObj = priorityMapping[priority] || priorityMapping['medium'];\nconst jiraPriority = jiraPriorityObj.name;\nconst jiraPriorityId = jiraPriorityObj.id;\n\nconst issueTypeMapping = {\n  'bug': '10041',\n  'feature': '10004',\n  'enhancement': '10008',\n  'task': '10008',\n  'epic': '10000'\n};\nconst jiraIssueType = issueTypeMapping[issueType] || '10008';\n\n// Enhanced file processing\nconst attachments = files.map(file => {\n  let downloadUrl = null;\n  \n  if (file.url_private_download && file.url_private_download.startsWith('https://')) {\n    downloadUrl = file.url_private_download;\n  } else if (file.url_private && file.url_private.startsWith('https://')) {\n    downloadUrl = file.url_private;\n  } else if (file.permalink && file.permalink.startsWith('https://')) {\n    downloadUrl = file.permalink;\n  } else if (file.url_download && file.url_download.startsWith('https://')) {\n    downloadUrl = file.url_download;\n  }\n  \n  const isVideo = file.mimetype && file.mimetype.startsWith('video/') || \n                  ['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm', 'mkv'].includes(file.filetype?.toLowerCase());\n  const isLargeFile = file.size && file.size > 10485760;\n  \n  return {\n    id: file.id || 'unknown',\n    name: file.name || file.title || 'unnamed_file',\n    url: downloadUrl,\n    size: file.size || 0,\n    mimetype: file.mimetype || 'application/octet-stream',\n    filetype: file.filetype || 'unknown',\n    isVideo: isVideo,\n    isLargeFile: isLargeFile,\n    sizeFormatted: file.size ? `${(file.size / 1024 / 1024).toFixed(2)} MB` : 'Unknown size'\n  };\n}).filter(att => att.url);\n\n// Create clean Jira description\nlet jiraDescription = '';\n\nif (extractedDescription) {\n  jiraDescription = extractedDescription + '\\n\\n';\n}\n\n// Add metadata\njiraDescription += `**Reported by:** <@${user}>\\n`;\njiraDescription += `**Channel:** <#${channel}>\\n`;\njiraDescription += `**Timestamp:** ${new Date(parseFloat(timestamp) * 1000).toISOString()}`;\n\n// Add attachments info if present\nif (attachments.length > 0) {\n  jiraDescription += '\\n\\n**Attachments:**\\n';\n  attachments.forEach((att, index) => {\n    jiraDescription += `${index + 1}. ${att.name} (${att.sizeFormatted})`;\n    if (att.isVideo) jiraDescription += ' [VIDEO]';\n    if (att.isLargeFile) jiraDescription += ' [LARGE FILE]';\n    jiraDescription += '\\n';\n  });\n}\n\nreturn {\n  summary,\n  description: jiraDescription,\n  priority: jiraPriority,\n  priorityId: jiraPriorityId,\n  issueType: jiraIssueType,\n  issueTypeName: issueType,\n  reporter: user,\n  attachments,\n  originalText: text,\n  \n  // Clear extraction results\n  extractedData: {\n    titleMatch: extractedTitle,\n    descriptionMatch: extractedDescription,\n    priorityMatch: extractedPriority,\n    typeMatch: extractedType,\n    \n    // Debugging info\n    parsing: {\n      titleFound: !!titleMatch,\n      descriptionFound: !!descriptionMatch,\n      priorityFound: !!priorityMatch,\n      typeFound: !!typeMatch,\n      titleLength: extractedTitle ? extractedTitle.length : 0,\n      descriptionLength: extractedDescription ? extractedDescription.length : 0,\n      usedRichText: blocks.length > 0\n    }\n  },\n  \n  files: {\n    totalFiles: files.length,\n    validAttachments: attachments.length,\n    videoFiles: attachments.filter(att => att.isVideo).length,\n    largeFiles: attachments.filter(att => att.isLargeFile).length,\n    attachmentDetails: attachments.map(att => ({\n      name: att.name,\n      size: att.sizeFormatted,\n      type: att.filetype,\n      isVideo: att.isVideo,\n      isLarge: att.isLargeFile\n    }))\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "a16fadd8-597b-4791-9737-14a22a578d55",
      "name": "创建 Jira 问题",
      "type": "n8n-nodes-base.jira",
      "position": [
        -48,
        2912
      ],
      "parameters": {
        "project": {
          "__rl": true,
          "mode": "list",
          "value": "10001",
          "cachedResultName": "Kanban"
        },
        "summary": "={{ $('Parse Message into Jira Format').item.json.summary }}",
        "issueType": {
          "__rl": true,
          "mode": "list",
          "value": "10006",
          "cachedResultName": "Task"
        },
        "additionalFields": {
          "assignee": {
            "__rl": true,
            "mode": "list",
            "value": "712020:d36fa274-fdb6-45c4-a2c5-8c53a89342d4",
            "cachedResultName": "Vivek Patidar"
          },
          "reporter": {
            "__rl": true,
            "mode": "list",
            "value": "712020:d36fa274-fdb6-45c4-a2c5-8c53a89342d4",
            "cachedResultName": "Vivek Patidar"
          },
          "description": "={{ $('Parse Message into Jira Format').item.json.extractedData.descriptionMatch }}"
        }
      },
      "credentials": {
        "jiraSoftwareCloudApi": {
          "id": "Q6d7sLBVOfGWmaLw",
          "name": "Jira SW Cloud account 3"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a543ed0b-81a9-4391-a239-82d6d5b06cc1",
      "name": "检查附件",
      "type": "n8n-nodes-base.if",
      "position": [
        176,
        2912
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition1",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $('Parse Message into Jira Format').item.json.files.totalFiles }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "cbe776cf-6812-43d0-a9d3-034688b23f98",
      "name": "获取文件信息",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        848,
        2592
      ],
      "parameters": {
        "url": "=https://slack.com/api/files.info?file={{ $json.fileId }}",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{$credentials.slackApi.accessToken}}"
            }
          ]
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "29408946-d34e-46d6-90fc-50e8477e8f2f",
      "name": "下载附件",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1072,
        2592
      ],
      "parameters": {
        "url": "={{ $json.file.url_private_download }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{$credentials.slackApi.accessToken}}"
            }
          ]
        }
      },
      "typeVersion": 4.1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "9d97b85d-0648-470a-8c5a-ed257f4ac92d",
  "connections": {
    "Get File Info": {
      "main": [
        [
          {
            "node": "Download Attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack Trigger": {
      "main": [
        [
          {
            "node": "checking message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "checking message": {
      "main": [
        [
          {
            "node": "Parse Message into Jira Format",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Attachments": {
      "main": [
        [
          {
            "node": "Prepare Files for Processing",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Reply to Channel On Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Jira Issue": {
      "main": [
        [
          {
            "node": "Check Attachments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Attachment": {
      "main": [
        [
          {
            "node": "Upload Attachment to Jira",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Files into Batches": {
      "main": [
        [
          {
            "node": "Reply to Channel On Slack",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get File Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Attachment to Jira": {
      "main": [
        [
          {
            "node": "Split Files into Batches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Files for Processing": {
      "main": [
        [
          {
            "node": "Split Files into Batches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Message into Jira Format": {
      "main": [
        [
          {
            "node": "Create Jira Issue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

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

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

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

需要付费吗?

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

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

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

作者
Rahul Joshi

Rahul Joshi

@rahul08

Rahul Joshi is a seasoned technology leader specializing in the n8n automation tool and AI-driven workflow automation. With deep expertise in building open-source workflow automation and self-hosted automation platforms, he helps organizations eliminate manual processes through intelligent n8n ai agent automation solutions.

外部链接
在 n8n.io 查看

分享此工作流