From 4866f29644dfd42987c672036f608b547fbc1005 Mon Sep 17 00:00:00 2001 From: kicer Date: Wed, 22 Jul 2026 10:36:53 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E4=B8=8A=E4=B8=A2=E6=8E=89=E7=9A=84AI?= =?UTF-8?q?=E5=BA=94=E7=AD=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/server.js | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/server/server.js b/server/server.js index a87205c..d763a57 100644 --- a/server/server.js +++ b/server/server.js @@ -108,12 +108,14 @@ app.get('/api/rooms/:roomId/messages', auth, (req, res) => { res.json(msgs); }); -// 发送消息(统一入口) -app.post('/api/rooms/:roomId/messages', auth, (req, res) => { +// 发送消息(统一入口,并触发 AI) +app.post('/api/rooms/:roomId/messages', auth, async (req, res) => { const { text, attachments } = req.body; const roomId = req.params.roomId; const username = req.user.username; const timestamp = new Date().toLocaleString('zh-CN', { hour12: false }); + + // 存储消息 const result = db.prepare('INSERT INTO messages (room_id, user, text, attachments, timestamp) VALUES (?,?,?,?,?)').run( roomId, username, text || '', attachments ? JSON.stringify(attachments) : null, timestamp ); @@ -134,7 +136,7 @@ app.post('/api/rooms/:roomId/messages', auth, (req, res) => { last_time: lastMsg ? lastMsg.timestamp : '' }; - // 广播给房间内其他成员,但不包括发送者自己 + // 广播给房间内其他成员(排除自己) broadcastToRoomExcludeSelf(roomId, username, { type: 'new_message', message: msg, @@ -144,8 +146,20 @@ app.post('/api/rooms/:roomId/messages', auth, (req, res) => { // 加入对话历史 addToHistory(roomId, 'user', `${username}: ${text || '图片'}`); - // 返回消息给发送者 + // 先响应客户端 res.json(msg); + + // 异步触发 AI 分析 + try { + const history = getHistory(roomId); + const historyMessages = history.map(e => ({ role: e.role, content: e.content })); + const aiResponse = await analyzeWithDeepSeek(text || '', historyMessages, username); + if (aiResponse && aiResponse.action !== 'ignore') { + handleAIResult(aiResponse, roomId, username, text || '', attachments || []); + } + } catch (e) { + console.error('AI 分析失败:', e); + } }); app.post('/api/upload', auth, upload.single('file'), (req, res) => { @@ -192,7 +206,7 @@ app.get('/api/rooms/:roomId/purchases/export', auth, (req, res) => { }); // WebSocket 管理 -const clients = new Map(); // ws -> { username, roomId } +const clients = new Map(); wss.on('connection', (ws, req) => { console.log('✅ WebSocket 客户端已连接'); @@ -218,7 +232,7 @@ wss.on('connection', (ws, req) => { ws.roomId = msg.roomId; clients.set(ws, { username, roomId: msg.roomId }); } - // 不再处理 message 类型,消息通过 HTTP API 发送 + // 不再处理 message 类型 } catch (e) {} }); @@ -227,7 +241,6 @@ wss.on('connection', (ws, req) => { }); }); -// 广播给房间内所有成员,排除指定用户 function broadcastToRoomExcludeSelf(roomId, excludeUsername, data) { const message = JSON.stringify(data); clients.forEach((info, ws) => { @@ -237,7 +250,6 @@ function broadcastToRoomExcludeSelf(roomId, excludeUsername, data) { }); } -// 广播给房间内所有人 function broadcastToRoom(roomId, data) { const message = JSON.stringify(data); clients.forEach((info, ws) => { @@ -247,7 +259,6 @@ function broadcastToRoom(roomId, data) { }); } -// 全局广播 function broadcast(data) { const message = JSON.stringify(data); clients.forEach((ws) => { @@ -255,7 +266,7 @@ function broadcast(data) { }); } -// 内部消息存储并广播(用于 AI 回复等) +// 内部消息存储并广播(用于 AI 回复) function storeAndBroadcastText(roomId, user, text) { const timestamp = new Date().toLocaleString('zh-CN', { hour12: false }); const result = db.prepare('INSERT INTO messages (room_id, user, text, timestamp) VALUES (?,?,?,?)').run(roomId, user, text, timestamp); @@ -285,7 +296,7 @@ function addToHistory(roomId, role, content) { if (history.length > 60) conversationHistory.set(roomId, history.slice(-40)); } -// AI 处理(保持原逻辑) +// AI 分析 async function analyzeWithDeepSeek(text, historyMessages, username) { const systemPrompt = `你是智能财务助手“小财”。结合对话历史理解用户意图。只返回JSON。 @@ -308,13 +319,16 @@ async function analyzeWithDeepSeek(text, historyMessages, username) { { role: 'user', content: `${username}: ${text}` } ]; + console.log('🤖 调用 DeepSeek...'); const res = await fetch('https://api.deepseek.com/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${DEEPSEEK_API_KEY}` }, body: JSON.stringify({ model: 'deepseek-v4-flash', messages, temperature: 0.1, stream: false }) }); const data = await res.json(); - return JSON.parse(data.choices[0].message.content.replace(/```json|```/g, '').trim()); + const content = data.choices[0].message.content; + console.log('🤖 AI 返回:', content); + return JSON.parse(content.replace(/```json|```/g, '').trim()); } function handleAIResult(aiResult, roomId, username, originalText, attachments) {