rtc-voice-chat/java-mock/routes/conversationRoutes.js
2026-04-02 20:15:15 +08:00

132 lines
4.4 KiB
JavaScript

const express = require('express');
const { v4: uuidv4 } = require('uuid');
const { readTable, writeTable } = require('../utils/db');
const authMiddleware = require('../middleware/auth');
const router = express.Router();
// POST /api/ai/conversations — 保存一次对话
router.post('/', authMiddleware, (req, res) => {
const { sceneId, roomId, messages } = req.body || {};
if (!sceneId || !Array.isArray(messages)) {
return res.status(400).json({ code: 400, message: 'sceneId 和 messages 不能为空' });
}
const conversations = readTable('conversations');
const now = new Date().toISOString();
// 统一存为 role/content 格式,兼容旧的 { userId, text } 格式
const formattedMessages = messages.map((m) => ({
role: (m.role === 'user' || m.role === 'assistant')
? m.role
: (m.userId === req.user.userId ? 'user' : 'assistant'),
content: m.content || m.text || '',
createdAt: m.time || now,
}));
// 推断会话开始/结束时间
const startedAt = formattedMessages[0]?.createdAt || now;
const endedAt = formattedMessages[formattedMessages.length - 1]?.createdAt || now;
const session = {
id: uuidv4(),
userId: req.user.userId,
sceneId,
roomId: roomId || '',
startedAt,
endedAt,
createdAt: now,
messages: formattedMessages,
};
conversations.push(session);
writeTable('conversations', conversations);
return res.json({ code: 200, data: { sessionId: session.id } });
});
// GET /api/ai/conversations — 分页列表(仅当前用户)
router.get('/', authMiddleware, (req, res) => {
const page = Math.max(1, parseInt(req.query.page) || 1);
const size = Math.max(1, Math.min(100, parseInt(req.query.size) || 20));
const all = readTable('conversations').filter((c) => c.userId === req.user.userId);
// 按时间倒序
all.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
const total = all.length;
const list = all.slice((page - 1) * size, page * size).map((c) => ({
id: c.id,
sceneId: c.sceneId,
roomId: c.roomId,
startedAt: c.startedAt,
endedAt: c.endedAt,
messageCount: c.messages.length,
firstMessage: c.messages.find((m) => m.role === 'user')?.content || '',
}));
return res.json({ code: 200, data: { total, page, size, list } });
});
// GET /api/ai/conversations/:id — 详情(含消息)
router.get('/:id', authMiddleware, (req, res) => {
const conversations = readTable('conversations');
const conv = conversations.find((c) => c.id === req.params.id);
if (!conv) {
return res.status(404).json({ code: 404, message: '对话记录不存在' });
}
if (conv.userId !== req.user.userId) {
return res.status(403).json({ code: 403, message: '无权访问该对话' });
}
return res.json({ code: 200, data: conv });
});
// POST /api/ai/conversations/:id/append — 继续对话追加消息
router.post('/:id/append', authMiddleware, (req, res) => {
const { messages } = req.body || {};
if (!Array.isArray(messages)) {
return res.status(400).json({ code: 400, message: 'messages 不能为空' });
}
const conversations = readTable('conversations');
const conv = conversations.find((c) => c.id === req.params.id);
if (!conv) return res.status(404).json({ code: 404, message: '对话记录不存在' });
if (conv.userId !== req.user.userId) return res.status(403).json({ code: 403, message: '无权操作该对话' });
const now = new Date().toISOString();
const newFormatted = messages.map((m) => ({
role: m.role === 'user' || m.role === 'assistant' ? m.role : 'assistant',
content: m.content || '',
createdAt: m.time || now,
}));
conv.messages.push(...newFormatted);
conv.endedAt = newFormatted[newFormatted.length - 1]?.createdAt || now;
writeTable('conversations', conversations);
return res.json({ code: 200, data: { sessionId: conv.id } });
});
// DELETE /api/ai/conversations/:id — 删除(仅本人)
router.delete('/:id', authMiddleware, (req, res) => {
const conversations = readTable('conversations');
const idx = conversations.findIndex((c) => c.id === req.params.id);
if (idx === -1) {
return res.status(404).json({ code: 404, message: '对话记录不存在' });
}
if (conversations[idx].userId !== req.user.userId) {
return res.status(403).json({ code: 403, message: '无权删除该对话' });
}
conversations.splice(idx, 1);
writeTable('conversations', conversations);
return res.json({ code: 200, data: null });
});
module.exports = router;