|
@@ -153,12 +153,18 @@ export default [
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- // AI 对话接口
|
|
|
|
|
|
|
+ // AI 对话接口 (SSE 流式输出)
|
|
|
{
|
|
{
|
|
|
url: "/api/upms/ai/chat",
|
|
url: "/api/upms/ai/chat",
|
|
|
method: "post",
|
|
method: "post",
|
|
|
- response: ({ body }) => {
|
|
|
|
|
- const { question } = body;
|
|
|
|
|
|
|
+ rawResponse: async (req, res) => {
|
|
|
|
|
+ const body = await new Promise<string>((resolve) => {
|
|
|
|
|
+ let data = '';
|
|
|
|
|
+ req.on('data', (chunk) => data += chunk);
|
|
|
|
|
+ req.on('end', () => resolve(data));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const { question } = JSON.parse(body);
|
|
|
|
|
|
|
|
// AI 回复知识库
|
|
// AI 回复知识库
|
|
|
const knowledgeBase: Record<string, string> = {
|
|
const knowledgeBase: Record<string, string> = {
|
|
@@ -171,25 +177,39 @@ export default [
|
|
|
"帮助": "我可以帮您:\n- 解答系统使用问题\n- 提供操作指导\n- 解释功能说明\n请直接输入您的问题!"
|
|
"帮助": "我可以帮您:\n- 解答系统使用问题\n- 提供操作指导\n- 解释功能说明\n请直接输入您的问题!"
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- // 模糊匹配
|
|
|
|
|
|
|
+ // 查找回复
|
|
|
|
|
+ let reply = '';
|
|
|
for (const key in knowledgeBase) {
|
|
for (const key in knowledgeBase) {
|
|
|
if (question.includes(key) || key.includes(question)) {
|
|
if (question.includes(key) || key.includes(question)) {
|
|
|
- return {
|
|
|
|
|
- code: 200,
|
|
|
|
|
- message: "success",
|
|
|
|
|
- data: { reply: knowledgeBase[key] }
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ reply = knowledgeBase[key];
|
|
|
|
|
+ break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 默认回复
|
|
// 默认回复
|
|
|
- return {
|
|
|
|
|
- code: 200,
|
|
|
|
|
- message: "success",
|
|
|
|
|
- data: {
|
|
|
|
|
- reply: `感谢您的提问!关于"${question}",我建议您:\n\n1. 查看相关功能模块的说明文档\n2. 联系系统管理员获取帮助\n3. 或者尝试在快捷问题中寻找类似问题\n\n如果您需要更详细的帮助,请联系技术支持。`
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ if (!reply) {
|
|
|
|
|
+ reply = `感谢您的提问!关于"${question}",我建议您:\n\n1. 查看相关功能模块的说明文档\n2. 联系系统管理员获取帮助\n3. 或者尝试在快捷问题中寻找类似问题\n\n如果您需要更详细的帮助,请联系技术支持。`;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 设置 SSE 响应头
|
|
|
|
|
+ res.setHeader('Content-Type', 'text/event-stream');
|
|
|
|
|
+ res.setHeader('Cache-Control', 'no-cache');
|
|
|
|
|
+ res.setHeader('Connection', 'keep-alive');
|
|
|
|
|
+
|
|
|
|
|
+ // 流式发送回复,每个字延迟 50ms
|
|
|
|
|
+ const chars = reply.split('');
|
|
|
|
|
+ for (let i = 0; i < chars.length; i++) {
|
|
|
|
|
+ const data = {
|
|
|
|
|
+ content: chars[i],
|
|
|
|
|
+ index: i,
|
|
|
|
|
+ total: chars.length,
|
|
|
|
|
+ done: i === chars.length - 1
|
|
|
|
|
+ };
|
|
|
|
|
+ res.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 50));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ res.end();
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
] as MockMethod[];
|
|
] as MockMethod[];
|