# Workflow Integration Summary ## 概述 本文档说明了如何将外部 AI 工作流平台与前端聊天功能集成,实现"输入文字 → 生成文档 → 返回链接"的完整流程。 --- ## 功能流程 ``` 用户输入: "生成一个地质报告" ↓ 前端检测关键词 (chatStore.ts) ↓ 调用工作流 API (workflowService.ts) ↓ 工作流平台处理 ↓ 工作流调用本地后端 API ↓ 返回导出记录 JSON ↓ 前端解析并显示文档卡片 (MessageItem.tsx) ↓ 用户点击卡片 ↓ 打开文档预览 (DocumentViewerLayout.tsx) ``` --- ## 核心组件 ### 1. 环境变量配置 (.env) ```env # 本地后端 API VITE_API_BASE_URL=http://192.168.0.195:8000 # 工作流 API VITE_WORKFLOW_API_URL=http://114.242.25.27:3000/api/v2/chat/completions VITE_WORKFLOW_API_KEY=XAgent-mWHBqQw06psUYRqx6PrHWiKdfY05ebt7I9drDBHzaG9QQesIkVEICj ``` **重要**: 修改 `.env` 后必须重启开发服务器! ```bash # 停止服务器 Ctrl+C # 重新启动 npm run dev # 清除浏览器缓存 Ctrl+Shift+Delete ``` --- ### 2. 工作流服务 (workflowService.ts) **位置**: `src/services/workflowService.ts` **功能**: - 检测用户输入是否需要生成文档 (`shouldTriggerWorkflow`) - 调用外部工作流 API (`triggerDocumentWorkflow`) - 解析返回的导出记录信息 - 提取文档类型 (`extractReportType`) **关键函数**: ```typescript // 检测是否应该触发工作流 export const shouldTriggerWorkflow = (input: string): boolean => { const lowerInput = input.toLowerCase().trim(); const generatePatterns = ['生成', '创建', '制作', '编写']; const documentPatterns = ['报告', '文档', '方案', '总结']; const hasGenerateAction = generatePatterns.some(p => lowerInput.includes(p)); const hasDocumentType = documentPatterns.some(p => lowerInput.includes(p)); return hasGenerateAction && hasDocumentType; }; // 调用工作流生成文档 export const triggerDocumentWorkflow = async ( userInput: string, chatId: string ): Promise<{ content: string; exportRecord?: ExportRecordInfo }> => { // 调用外部 API const response = await fetch(config.apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${config.apiKey}`, }, body: JSON.stringify({ chatId, stream: false, detail: false, messages: [{ role: 'user', content: userInput }], }), }); const data = await response.json(); // 解析导出记录 // 可能在 data.content (JSON字符串) // 或 data.exportRecord (对象) // 或 data.records (数组) return { content, exportRecord }; }; ``` --- ### 3. 聊天状态管理 (chatStore.ts) **位置**: `src/stores/chatStore.ts` **集成点**: `sendMessage` 函数 ```typescript sendMessage: async (content: string) => { // 创建用户消息 const userMessage = { ... }; // 检查是否需要触发工作流 const shouldUseWorkflow = shouldTriggerWorkflow(content); let aiResponse: string; let exportRecord: ExportRecordInfo | undefined; if (shouldUseWorkflow) { // 使用工作流生成文档 const result = await triggerDocumentWorkflow(content, sessionId); aiResponse = result.content; exportRecord = result.exportRecord; } else { // 使用普通 AI 聊天 const result = await getAIResponse(content, sessionId, messages); aiResponse = result.response; } // 创建 AI 消息(带有 exportRecord) const aiMessage = { id: uuidv4(), role: 'assistant', content: aiResponse, timestamp: Date.now(), exportRecord: exportRecord, // 关键! }; // 添加到消息列表 set(state => ({ messages: [...state.messages, aiMessage], })); // 如果有文档生成,显示成功提示 if (exportRecord) { message.success('✅ 文档已生成,点击下方卡片查看'); } } ``` --- ### 4. 消息显示组件 (MessageItem.tsx) **位置**: `src/components/ChatPanel/MessageItem.tsx` **功能**: - 显示聊天消息气泡 - 如果消息包含 `exportRecord`,显示可点击的文档卡片 - 点击卡片触发 `onDocumentClick` 回调 ```typescript const MessageItem: React.FC = ({ message, onDocumentClick }) => { const { content, exportRecord } = message; return (
{/* 消息气泡 */}
{content}
{/* 文档卡片(如果有 exportRecord) */} {exportRecord && ( onDocumentClick?.(exportRecord)} hoverable >
📄 {exportRecord.fileName} 点击预览文档
)}
); }; ``` --- ### 5. 文档内容解析 (documentContentService.ts) **位置**: `src/services/documentContentService.ts` **更新内容**: 现在真实下载并解析 Word 文档 ```typescript export const fetchDocumentStructure = async ( recordId: string, userId: string ): Promise => { // 1. 构建下载 URL const baseUrl = import.meta.env.VITE_API_BASE_URL; const downloadUrl = `${baseUrl}/api/v1/export/records/${recordId}/download?userId=${userId}`; // 2. 下载 Word 文件 const response = await fetch(downloadUrl); const blob = await response.blob(); const arrayBuffer = await blob.arrayBuffer(); // 3. 使用 mammoth.js 解析 const mammoth = await import('mammoth'); const result = await mammoth.convertToHtml({ arrayBuffer }); // 4. 解析 HTML 提取结构 const parser = new DOMParser(); const doc = parser.parseFromString(result.value, 'text/html'); // 5. 提取标题、段落、表格 const outline: OutlineItem[] = []; const content: ContentBlock[] = []; doc.body.querySelectorAll('*').forEach(element => { if (element.tagName.match(/^H[1-6]$/)) { // 处理标题 } else if (element.tagName === 'P') { // 处理段落 } else if (element.tagName === 'TABLE') { // 处理表格 } }); return { recordId, fileName, outline, content, metadata }; }; ``` **依赖**: mammoth.js (已在 package.json 中安装) --- ## 工作流 API 响应格式 工作流平台可能返回以下格式之一: ### 格式 1: JSON 字符串在 content 中 ```json { "content": "{\"records\":[{\"recordId\":\"rec-xxx\",\"fileName\":\"地质报告.doc\",\"downloadUrl\":\"http://...\",\"documentId\":\"doc-xxx\"}]}", "choices": [...] } ``` ### 格式 2: 顶层 exportRecord 对象 ```json { "content": "文档已生成", "exportRecord": { "recordId": "rec-xxx", "fileName": "地质报告.doc", "downloadUrl": "http://...", "documentId": "doc-xxx" } } ``` ### 格式 3: 顶层 records 数组 ```json { "content": "文档已生成", "records": [ { "recordId": "rec-xxx", "fileName": "地质报告.doc", "downloadUrl": "http://...", "documentId": "doc-xxx" } ] } ``` **workflowService.ts 会自动处理所有这些格式!** --- ## 后端 API 端点 ### 1. 获取导出记录列表 ``` GET http://192.168.0.195:8000/api/v1/export/records?userId=default-user&page=1&pageSize=20 ``` **响应**: ```json { "records": [ { "recordId": "rec-xxx", "userId": "default-user", "fileName": "地质报告.doc", "fileSize": 39076, "downloadUrl": "http://192.168.0.195:8000/api/v1/export/records/rec-xxx/download?userId=default-user", "documentId": "doc-xxx", "styleId": "default", "createdAt": 1782369497764 } ], "pagination": { ... } } ``` ### 2. 下载文档 ``` GET http://192.168.0.195:8000/api/v1/export/records/{recordId}/download?userId={userId} ``` **响应**: Word 文档二进制数据 (application/vnd.openxmlformats-officedocument.wordprocessingml.document) --- ## 类型定义 ### ExportRecordInfo ```typescript export interface ExportRecordInfo { recordId: string; // 导出记录 ID fileName: string; // 文件名 downloadUrl: string; // 下载 URL documentId: string; // 文档 ID } ``` ### ChatMessage ```typescript export interface ChatMessage { id: string; role: 'user' | 'assistant'; content: string; timestamp: number; documentId?: string; exportRecord?: ExportRecordInfo; // 关键字段! } ``` --- ## 测试流程 ### 1. 启动后端服务 ```bash cd ax-backend-shell python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 ``` 确保后端运行在 `http://192.168.0.195:8000` ### 2. 启动前端服务 ```bash cd ax-frontend-app npm run dev ``` 前端运行在 `http://localhost:5173` ### 3. 测试工作流集成 在聊天面板输入: - ✅ "生成一个地质报告" → 应触发工作流 - ✅ "创建技术文档" → 应触发工作流 - ✅ "制作项目方案" → 应触发工作流 - ❌ "你好" → 不触发工作流,普通聊天 - ❌ "什么是地质报告" → 不触发工作流,普通聊天 ### 4. 验证文档显示 1. 触发工作流后,应该看到: - AI 回复消息 - 下方显示文档卡片 - 卡片包含文件名和"点击预览文档" 2. 点击文档卡片后: - 打开文档查看器 - 左侧显示文档大纲 - 中间显示文档内容(标题、段落、表格) - 右侧显示写入/预览切换 --- ## 常见问题 ### Q1: 修改 .env 后没有生效? **A**: Vite 不会热重载环境变量,必须重启开发服务器: ```bash # 停止 Ctrl+C # 启动 npm run dev # 清除浏览器缓存 Ctrl+Shift+Delete → 清除缓存和 Cookie → 清除数据 ``` ### Q2: 工作流没有被触发? **A**: 检查关键词匹配逻辑: ```typescript // 必须同时包含"生成类"词汇和"文档类"词汇 生成 + 报告 ✅ 创建 + 文档 ✅ 制作 + 方案 ✅ 生成 + 什么 ❌ (没有文档类词汇) 报告 + 是什么 ❌ (没有生成类词汇) ``` ### Q3: 文档内容显示为空? **A**: 可能的原因: 1. **网络问题**: 检查后端 API 是否可访问 ```bash curl http://192.168.0.195:8000/api/v1/export/records/{recordId}/download?userId=default-user ``` 2. **CORS 问题**: 检查浏览器控制台是否有 CORS 错误 3. **文档格式问题**: mammoth.js 只支持 .docx 格式,不支持旧的 .doc 格式 ### Q4: 工作流返回的数据格式不对? **A**: workflowService.ts 支持多种格式: 1. JSON 字符串在 `content` 字段 2. 对象在 `exportRecord` 字段 3. 数组在 `records` 字段 如果都不匹配,检查实际返回数据: ```typescript console.log('[workflowService] Response:', data); ``` --- ## 架构图 ``` ┌─────────────────────────────────────────────────────────────────┐ │ Frontend (React) │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ │ │ ChatPanel │─────▶│ chatStore │────▶│ MessageItem │ │ │ │ (用户输入) │ │ (状态管理) │ │ (显示卡片) │ │ │ └──────────────┘ └──────┬───────┘ └─────────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────┐ │ │ │ workflowService │ │ │ │ (检测&调用工作流) │ │ │ └─────────┬────────┘ │ └──────────────────────────────┼─────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ External AI Platform (工作流平台) │ │ http://114.242.25.27:3000/api/v2/chat/completions │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. 接收用户请求 │ │ 2. 生成文档内容 │ │ 3. 调用本地后端 API │ │ 4. 返回导出记录 │ │ │ └──────────────────────────────┬──────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Local Backend API (FastAPI) │ │ http://192.168.0.195:8000 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ GET /api/v1/export/records │ │ GET /api/v1/export/records/{recordId}/download │ │ POST /api/v1/export │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 文件清单 ### 核心文件 - ✅ `.env` - 环境变量配置 - ✅ `src/services/workflowService.ts` - 工作流服务 - ✅ `src/stores/chatStore.ts` - 聊天状态管理 - ✅ `src/components/ChatPanel/MessageItem.tsx` - 消息显示 - ✅ `src/services/documentContentService.ts` - 文档内容解析 - ✅ `src/types/chat.ts` - 类型定义 ### 文档 - ✅ `docs/WORKFLOW_INTEGRATION_SUMMARY.md` - 本文档 --- ## 下一步改进 1. **错误处理增强** - 工作流 API 失败时的友好提示 - 文档解析失败时的降级方案 2. **性能优化** - 文档缓存机制 - 大文档分页加载 3. **功能扩展** - 支持更多文档格式 (PDF, Excel) - 文档编辑功能 - 版本历史 --- **文档版本**: 1.0 **最后更新**: 2026-06-25 **维护者**: AX Team