本文档说明了如何将外部 AI 工作流平台与前端聊天功能集成,实现"输入文字 → 生成文档 → 返回链接"的完整流程。
用户输入: "生成一个地质报告"
↓
前端检测关键词 (chatStore.ts)
↓
调用工作流 API (workflowService.ts)
↓
工作流平台处理
↓
工作流调用本地后端 API
↓
返回导出记录 JSON
↓
前端解析并显示文档卡片 (MessageItem.tsx)
↓
用户点击卡片
↓
打开文档预览 (DocumentViewerLayout.tsx)
# 本地后端 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 后必须重启开发服务器!
# 停止服务器
Ctrl+C
# 重新启动
npm run dev
# 清除浏览器缓存
Ctrl+Shift+Delete
位置: src/services/workflowService.ts
功能:
shouldTriggerWorkflow)triggerDocumentWorkflow)extractReportType)关键函数:
// 检测是否应该触发工作流
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 };
};
位置: src/stores/chatStore.ts
集成点: sendMessage 函数
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('✅ 文档已生成,点击下方卡片查看');
}
}
位置: src/components/ChatPanel/MessageItem.tsx
功能:
exportRecord,显示可点击的文档卡片onDocumentClick 回调const MessageItem: React.FC<MessageItemProps> = ({
message,
onDocumentClick
}) => {
const { content, exportRecord } = message;
return (
<div>
{/* 消息气泡 */}
<div>{content}</div>
{/* 文档卡片(如果有 exportRecord) */}
{exportRecord && (
<Card
onClick={() => onDocumentClick?.(exportRecord)}
hoverable
>
<FileWordOutlined />
<div>
<Text>📄 {exportRecord.fileName}</Text>
<Text>点击预览文档</Text>
</div>
<EyeOutlined />
</Card>
)}
</div>
);
};
位置: src/services/documentContentService.ts
更新内容: 现在真实下载并解析 Word 文档
export const fetchDocumentStructure = async (
recordId: string,
userId: string
): Promise<DocumentStructure> => {
// 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 中安装)
工作流平台可能返回以下格式之一:
{
"content": "{\"records\":[{\"recordId\":\"rec-xxx\",\"fileName\":\"地质报告.doc\",\"downloadUrl\":\"http://...\",\"documentId\":\"doc-xxx\"}]}",
"choices": [...]
}
{
"content": "文档已生成",
"exportRecord": {
"recordId": "rec-xxx",
"fileName": "地质报告.doc",
"downloadUrl": "http://...",
"documentId": "doc-xxx"
}
}
{
"content": "文档已生成",
"records": [
{
"recordId": "rec-xxx",
"fileName": "地质报告.doc",
"downloadUrl": "http://...",
"documentId": "doc-xxx"
}
]
}
workflowService.ts 会自动处理所有这些格式!
GET http://192.168.0.195:8000/api/v1/export/records?userId=default-user&page=1&pageSize=20
响应:
{
"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": { ... }
}
GET http://192.168.0.195:8000/api/v1/export/records/{recordId}/download?userId={userId}
响应: Word 文档二进制数据 (application/vnd.openxmlformats-officedocument.wordprocessingml.document)
export interface ExportRecordInfo {
recordId: string; // 导出记录 ID
fileName: string; // 文件名
downloadUrl: string; // 下载 URL
documentId: string; // 文档 ID
}
export interface ChatMessage {
id: string;
role: 'user' | 'assistant';
content: string;
timestamp: number;
documentId?: string;
exportRecord?: ExportRecordInfo; // 关键字段!
}
cd ax-backend-shell
python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
确保后端运行在 http://192.168.0.195:8000
cd ax-frontend-app
npm run dev
前端运行在 http://localhost:5173
在聊天面板输入:
触发工作流后,应该看到:
点击文档卡片后:
A: Vite 不会热重载环境变量,必须重启开发服务器:
# 停止
Ctrl+C
# 启动
npm run dev
# 清除浏览器缓存
Ctrl+Shift+Delete → 清除缓存和 Cookie → 清除数据
A: 检查关键词匹配逻辑:
// 必须同时包含"生成类"词汇和"文档类"词汇
生成 + 报告 ✅
创建 + 文档 ✅
制作 + 方案 ✅
生成 + 什么 ❌ (没有文档类词汇)
报告 + 是什么 ❌ (没有生成类词汇)
A: 可能的原因:
网络问题: 检查后端 API 是否可访问
curl http://192.168.0.195:8000/api/v1/export/records/{recordId}/download?userId=default-user
CORS 问题: 检查浏览器控制台是否有 CORS 错误
文档格式问题: mammoth.js 只支持 .docx 格式,不支持旧的 .doc 格式
A: workflowService.ts 支持多种格式:
content 字段exportRecord 字段records 字段如果都不匹配,检查实际返回数据:
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.0
最后更新: 2026-06-25
维护者: AX Team