From 1c3f7604c9841a4731a30241f2d0596d20e006fe Mon Sep 17 00:00:00 2001 From: hubian <908234780@qq.com> Date: Mon, 27 Apr 2026 18:38:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=90=8E=E5=8F=B0=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9F=A5=E7=9C=8B=E7=94=A8=E6=88=B7=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=E8=AE=B0=E5=BD=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app.py | 30 ++++++++++ www/admin.js | 145 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) diff --git a/backend/app.py b/backend/app.py index 40ce7e7..b3afae0 100644 --- a/backend/app.py +++ b/backend/app.py @@ -641,6 +641,36 @@ def get_user_conversations(user_id): return jsonify(conversations) +@app.route('/api/user//conversations/', methods=['GET']) +def get_user_conversation_detail(user_id, conv_id): + """获取单个对话详情""" + conn = get_db() + cursor = conn.cursor() + cursor.execute(''' + SELECT id, title, agent_id, messages, created_at, updated_at + FROM conversations WHERE id = ? AND user_id = ? + ''', (conv_id, user_id)) + + row = cursor.fetchone() + conn.close() + + if not row: + return jsonify({'error': '对话不存在'}), 404 + + conv = dict(row) + try: + conv['messages'] = json.loads(conv['messages']) if conv['messages'] else [] + except: + conv['messages'] = [] + + conv['id'] = str(conv['id']) + conv['createdAt'] = int(datetime.strptime(conv['created_at'], '%Y-%m-%d %H:%M:%S').timestamp() * 1000) if conv['created_at'] else 0 + conv['updatedAt'] = int(datetime.strptime(conv['updated_at'], '%Y-%m-%d %H:%M:%S').timestamp() * 1000) if conv['updated_at'] else 0 + conv['agentId'] = conv['agent_id'] + + return jsonify(conv) + + @app.route('/api/user//conversations', methods=['POST']) def create_user_conversation(user_id): """创建新对话""" diff --git a/www/admin.js b/www/admin.js index 6ecafd3..5362cb0 100644 --- a/www/admin.js +++ b/www/admin.js @@ -250,6 +250,7 @@ async function loadUsersPage(content) {
+
@@ -396,6 +397,150 @@ async function deleteUser(id) { loadPage('users'); } +// ==================== 查看用户对话记录 ==================== + +async function showUserConversations(userId, username) { + // 加载用户对话列表 + const conversations = await fetchAPI(`/api/user/${userId}/conversations`); + + const content = document.getElementById('mainContent'); + + content.innerHTML = ` +
+

用户对话记录 - ${username}

+ +
+ +
+
+
💬
+
${conversations.length}
+
对话总数
+
+
+
🤖
+
${conversations.filter(c => c.agentId).length}
+
智能体对话
+
+
+
📝
+
${conversations.reduce((sum, c) => sum + (c.messages?.length || 0), 0)}
+
消息总数
+
+
+ +
+ + + + + + + + + + + + + + ${conversations.length === 0 ? '' : + conversations.map(conv => ` + + + + + + + + + + `).join('') + } + +
ID标题智能体消息数创建时间更新时间操作
暂无对话记录
${conv.id}${conv.title || '新对话'}${conv.agentId ? getAgentName(conv.agentId) : '普通对话'}${conv.messages?.length || 0}${formatDate(conv.createdAt || conv.created_at)}${formatDate(conv.updatedAt || conv.updated_at)} +
+ + +
+
+
+ `; +} + +function getAgentName(agentId) { + const agent = agents.find(a => a.agent_id === agentId); + return agent ? `${agent.avatar} ${agent.name}` : agentId; +} + +async function showConversationMessages(userId, convId, title) { + // 获取对话详情 + const conv = await fetchAPI(`/api/user/${userId}/conversations/${convId}`); + + const content = document.getElementById('mainContent'); + + const messages = conv.messages || []; + + content.innerHTML = ` +
+

对话详情 - ${title}

+ +
+ +
+
+ 💬 消息数: ${messages.length} + 🤖 智能体: ${conv.agentId ? getAgentName(conv.agentId) : '普通对话'} + 📅 创建: ${formatDate(conv.createdAt || conv.created_at)} +
+
+ +
+ + + + + + + + + + + ${messages.length === 0 ? '' : + messages.map((msg, idx) => ` + + + + + + + `).join('') + } + +
序号角色内容时间
暂无消息
${idx + 1} + ${msg.role === 'user' ? '👤 用户' : '🤖 AI'} + + ${escapeHtml(msg.content?.slice(0, 500) || '')}${msg.content?.length > 500 ? '...' : ''} + ${msg.thinking ? `
💭 思考: ${escapeHtml(msg.thinking?.slice(0, 200) || '')}...
` : ''} +
${formatDate(msg.timestamp || msg.createdAt)}
+
+ `; +} + +async function deleteUserConversation(userId, convId) { + if (!confirm('确定删除此对话?此操作不可恢复!')) return; + + await fetchAPI(`/api/user/${userId}/conversations/${convId}`, 'DELETE'); + showToast('删除成功'); + showUserConversations(userId, '用户'); +} + +function escapeHtml(text) { + if (!text) return ''; + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; +} + // ==================== 大模型配置页面 ==================== async function loadLLMPage(content) {