let currentQA = null; let selectedQuestions = []; let selectedAnswers = []; let selectedQAs = new Set(); // 用于批量操作 let groupList = []; // 存储群组列表 // 加载群组列表 async function loadGroupList() { try { const response = await fetch('api/groups'); const result = await response.json(); if (result.success) { groupList = result.groups || []; // 更新过滤区域的群组下拉框 const groupFilter = document.getElementById('groupFilter'); if (groupFilter) { updateGroupSelect(groupFilter); } // 更新模态框中的群组下拉框 const groupIdSelect = document.getElementById('groupId'); if (groupIdSelect) { updateGroupSelect(groupIdSelect); } } else { console.error('加载群组列表失败:', result.error); } } catch (error) { console.error('加载群组列表时出错:', error); } } // 更新群组下拉框 function updateGroupSelect(selectElement) { if (!selectElement) return; // 保存当前选中的值 const currentValue = selectElement.value; // 清空下拉框,保留第一个选项 selectElement.innerHTML = ''; // 添加群组选项 groupList.forEach(group => { const option = document.createElement('option'); option.value = group.id; option.textContent = group.name ? `${group.name} (${group.id})` : group.id; selectElement.appendChild(option); }); // 恢复之前选中的值 if (currentValue) { selectElement.value = currentValue; } } // 页面加载时获取QA列表 document.addEventListener('DOMContentLoaded', function () { loadQAList(); loadGroupList(); updateSearchHistory(); // 添加点击外部关闭搜索建议的事件 document.addEventListener('click', function(e) { const suggestionsContainer = document.getElementById('searchSuggestions'); const searchInput = document.getElementById('searchInput'); if (suggestionsContainer && searchInput && !suggestionsContainer.contains(e.target) && e.target !== searchInput) { suggestionsContainer.style.display = 'none'; } }); // 添加回车键搜索功能 const searchInput = document.getElementById('searchInput'); if (searchInput) { searchInput.addEventListener('keypress', function(e) { if (e.key === 'Enter') { advancedSearch(); } }); } }); // 加载QA列表 async function loadQAList() { try { // 获取搜索参数 const searchInput = document.getElementById('searchInput'); const groupFilter = document.getElementById('groupFilter'); const startDateFilter = document.getElementById('startDateFilter'); const endDateFilter = document.getElementById('endDateFilter'); const keyword = searchInput ? searchInput.value.trim() : ''; const groupId = groupFilter ? groupFilter.value.trim() : ''; const startTime = startDateFilter ? startDateFilter.value : ''; const endTime = endDateFilter ? endDateFilter.value : ''; // 构建查询URL let url = 'api/qa'; const params = new URLSearchParams(); if (keyword) params.append('keyword', keyword); if (groupId) params.append('group_id', groupId); if (startTime) params.append('start_time', startTime); if (endTime) params.append('end_time', endTime); if (params.toString()) { url += '?' + params.toString(); } const response = await fetch(url); const result = await response.json(); if (result.success) { // 根据后端API返回的数据结构,data字段包含qa_list const qaList = result.qa_list || []; displayQAList(qaList); // 更新统计信息 updateStats(result.total || qaList.length); } else { alert('加载QA列表失败: ' + result.error); } } catch (error) { // 修复错误:确保error.message存在,避免"Cannot read properties of undefined"错误 const errorMessage = error?.message || error?.toString() || '未知错误'; alert('加载QA列表时出错: ' + errorMessage); } } // 更新统计信息 function updateStats(total) { const statsElement = document.getElementById('statsInfo'); if (statsElement) { statsElement.textContent = `共找到 ${total} 条QA记录`; } } // 显示QA列表 async function displayQAList(qaList) { const qaListContainer = document.getElementById('qaList'); if (qaList.length === 0) { qaListContainer.innerHTML = `
📝

暂无QA记录

点击"创建新QA"按钮开始创建第一个问答记录

`; // 隐藏批量操作按钮 const batchActions = document.getElementById('batchActions'); if (batchActions) batchActions.style.display = 'none'; return; } // 显示批量操作按钮 const batchActions = document.getElementById('batchActions'); if (batchActions) batchActions.style.display = 'block'; // 获取所有消息的详细内容 let allMessageIds = []; qaList.forEach(qa => { // 解析JSON格式的question和answer字段 let questionIds = []; let answerIds = []; try { questionIds = typeof qa.question === 'string' ? JSON.parse(qa.question) : qa.question || []; answerIds = typeof qa.answer === 'string' ? JSON.parse(qa.answer) : qa.answer || []; } catch (e) { console.error('解析QA数据时出错:', e); questionIds = []; answerIds = []; } allMessageIds = [...allMessageIds, ...questionIds, ...answerIds]; }); let messageMap = {}; if (allMessageIds.length > 0) { try { const response = await fetch('api/messages_by_ids', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({message_ids: allMessageIds}) }); const result = await response.json(); if (result.success) { result.messages.forEach(msg => { messageMap[msg.id] = msg; }); } } catch (error) { console.error('获取消息详情时出错:', error); } } qaListContainer.innerHTML = qaList.map(qa => { // 解析JSON格式的question和answer字段 let questionIds = []; let answerIds = []; try { questionIds = typeof qa.question === 'string' ? JSON.parse(qa.question) : qa.question || []; answerIds = typeof qa.answer === 'string' ? JSON.parse(qa.answer) : qa.answer || []; } catch (e) { console.error('解析QA数据时出错:', e); questionIds = []; answerIds = []; } // 获取第一个问题的内容作为显示 let questionContent = '暂无问题内容'; if (questionIds.length > 0) { const firstQuestionId = questionIds[0]; const message = messageMap[firstQuestionId]; if (message && message.content) { questionContent = message.content; } else { questionContent = `问题消息ID: ${firstQuestionId}`; } } // 截取问题内容,超过30个字用省略号 if (questionContent.length > 30) { questionContent = questionContent.substring(0, 30) + '...'; } const isSelected = selectedQAs.has(qa.id); return `
QA #${qa.id}
${qa.groupId || '无群组'}
问题: ${questionContent}
问题: ${questionIds.length}条 答案: ${answerIds.length}条
`; }).join(''); // 更新批量操作按钮状态 updateBatchActions(); } // 搜索消息 async function searchMessages() { const keyword = document.getElementById('searchInput').value.trim(); if (!keyword) { alert('请输入搜索关键词'); return; } try { // 显示搜索中状态 const qaListContainer = document.getElementById('qaList'); qaListContainer.innerHTML = '
搜索中...
'; const response = await fetch(`api/search_messages?keyword=${encodeURIComponent(keyword)}`); const result = await response.json(); if (result.success) { displaySearchResults(result.messages); // 保存搜索历史 saveSearchHistory(keyword); } else { alert('搜索失败: ' + result.error); } } catch (error) { // 修复错误:确保error.message存在,避免"Cannot read properties of undefined"错误 const errorMessage = error?.message || error?.toString() || '未知错误'; alert('搜索时出错: ' + errorMessage); } } // 高级搜索 async function advancedSearch() { const keyword = document.getElementById('searchInput').value.trim(); const groupFilter = document.getElementById('groupFilter').value.trim(); const startDate = document.getElementById('startDateFilter').value; const endDate = document.getElementById('endDateFilter').value; if (!keyword && !groupFilter && !startDate && !endDate) { alert('请输入至少一个搜索条件'); return; } try { // 显示搜索中状态 const qaListContainer = document.getElementById('qaList'); qaListContainer.innerHTML = '
搜索中...
'; // 构建查询参数 const params = new URLSearchParams(); if (keyword) params.append('keyword', keyword); if (groupFilter) params.append('group_id', groupFilter); if (startDate) params.append('start_time', startDate); if (endDate) params.append('end_time', endDate); const response = await fetch(`api/qa?${params.toString()}`); const result = await response.json(); if (result.success) { displayQAList(result.qa_list || []); // 保存搜索历史 if (keyword) saveSearchHistory(keyword); } else { alert('搜索失败: ' + result.error); } } catch (error) { const errorMessage = error?.message || error?.toString() || '未知错误'; alert('搜索时出错: ' + errorMessage); } } // 保存搜索历史 function saveSearchHistory(keyword) { let searchHistory = JSON.parse(localStorage.getItem('qa_search_history') || '[]'); // 移除重复项 searchHistory = searchHistory.filter(item => item !== keyword); // 添加到开头 searchHistory.unshift(keyword); // 限制历史记录数量 if (searchHistory.length > 10) { searchHistory = searchHistory.slice(0, 10); } localStorage.setItem('qa_search_history', JSON.stringify(searchHistory)); // 更新搜索历史显示 updateSearchHistory(); } // 更新搜索历史显示 function updateSearchHistory() { const searchHistory = JSON.parse(localStorage.getItem('qa_search_history') || '[]'); const historyContainer = document.getElementById('searchHistory'); if (!historyContainer) return; if (searchHistory.length === 0) { historyContainer.style.display = 'none'; return; } historyContainer.style.display = 'block'; historyContainer.innerHTML = `
搜索历史
${searchHistory.map(item => `
${item}
`).join('')}
`; } // 填充搜索输入框 function fillSearchInput(keyword) { document.getElementById('searchInput').value = keyword; } // 清空搜索历史 function clearSearchHistory() { if (confirm('确定要清空搜索历史吗?')) { localStorage.removeItem('qa_search_history'); updateSearchHistory(); } } // 智能搜索建议 async function showSearchSuggestions() { const keyword = document.getElementById('searchInput').value.trim(); const suggestionsContainer = document.getElementById('searchSuggestions'); if (!keyword) { suggestionsContainer.style.display = 'none'; return; } try { // 调用后端API获取搜索建议 const response = await fetch(`api/search_suggestions?keyword=${encodeURIComponent(keyword)}`); const result = await response.json(); if (result.success && result.suggestions.length > 0) { suggestionsContainer.innerHTML = result.suggestions.map(item => `
${item}
`).join(''); suggestionsContainer.style.display = 'block'; } else { suggestionsContainer.style.display = 'none'; } } catch (error) { suggestionsContainer.style.display = 'none'; } } // 选择搜索建议 function selectSearchSuggestion(suggestion) { document.getElementById('searchInput').value = suggestion; document.getElementById('searchSuggestions').style.display = 'none'; searchMessages(); } // 显示搜索结果 function displaySearchResults(messages) { const qaListContainer = document.getElementById('qaList'); const keyword = document.getElementById('searchInput').value.trim(); if (messages.length === 0) { qaListContainer.innerHTML = `
🔍

未找到相关消息

请尝试其他搜索关键词或调整搜索条件

`; return; } qaListContainer.innerHTML = `

搜索结果 (${messages.length} 条)

搜索关键词: "${keyword}"
${messages.map(msg => `
消息ID: ${msg.id}
${msg.formatted_time || '未知时间'}
类型: ${msg.type} | 发送者: ${msg.sender_name || '未知'} | 接收者: ${msg.receiver || '未知'}
内容:
${msg.highlighted_content ? msg.highlighted_content : (msg.display_content || '无内容')}
`).join('')} `; } // 查看消息详情 function viewMessageDetail(messageId) { // 这里可以打开一个模态框显示消息的完整详情 alert(`查看消息详情: ${messageId}\n此功能可以进一步扩展显示完整消息内容`); } // 打开创建模态框 function openCreateModal() { currentQA = null; selectedQuestions = []; selectedAnswers = []; document.getElementById('modalTitle').textContent = '创建QA记录'; document.getElementById('groupId').value = ''; updateSelectedMessages(); document.getElementById('qaModal').style.display = 'block'; } // 编辑QA async function editQA(qaId) { try { const response = await fetch(`api/qa/${qaId}`); const result = await response.json(); if (result.success) { currentQA = result.qa; selectedQuestions = [...currentQA.question_list]; selectedAnswers = [...currentQA.answer_list]; document.getElementById('modalTitle').textContent = '编辑QA记录'; document.getElementById('groupId').value = currentQA.groupId || ''; updateSelectedMessages(); document.getElementById('qaModal').style.display = 'block'; } else { alert('加载QA详情失败: ' + result.error); } } catch (error) { // 修复错误:确保error.message存在,避免"Cannot read properties of undefined"错误 const errorMessage = error?.message || error?.toString() || '未知错误'; alert('加载QA详情时出错: ' + errorMessage); } } // 清空过滤器 function clearFilters() { document.getElementById('searchInput').value = ''; document.getElementById('groupFilter').value = ''; document.getElementById('startDateFilter').value = ''; document.getElementById('endDateFilter').value = ''; loadQAList(); } // 切换QA选择状态 function toggleQASelection(qaId, isSelected) { if (isSelected) { selectedQAs.add(qaId); } else { selectedQAs.delete(qaId); } // 更新UI const qaItem = document.querySelector(`[data-qa-id="${qaId}"]`); if (qaItem) { if (isSelected) { qaItem.classList.add('selected'); } else { qaItem.classList.remove('selected'); } } updateBatchActions(); } // 全选/取消全选 function toggleSelectAll() { const selectAllCheckbox = document.getElementById('selectAll'); const qaItems = document.querySelectorAll('.qa-item'); if (selectAllCheckbox.checked) { // 全选 qaItems.forEach(item => { const qaId = parseInt(item.getAttribute('data-qa-id')); selectedQAs.add(qaId); item.classList.add('selected'); const checkbox = item.querySelector('.qa-select'); if (checkbox) checkbox.checked = true; }); } else { // 取消全选 selectedQAs.clear(); qaItems.forEach(item => { item.classList.remove('selected'); const checkbox = item.querySelector('.qa-select'); if (checkbox) checkbox.checked = false; }); } updateBatchActions(); } // 更新批量操作按钮状态 function updateBatchActions() { const selectedCount = selectedQAs.size; const batchInfo = document.getElementById('batchInfo'); const batchDeleteBtn = document.getElementById('batchDeleteBtn'); if (batchInfo) { batchInfo.textContent = `已选择 ${selectedCount} 条记录`; } if (batchDeleteBtn) { batchDeleteBtn.disabled = selectedCount === 0; } } // 批量删除QA记录 async function batchDeleteQA() { const selectedCount = selectedQAs.size; if (selectedCount === 0) { alert('请先选择要删除的QA记录'); return; } if (!confirm(`确定要删除选中的 ${selectedCount} 条QA记录吗?此操作不可恢复。`)) { return; } try { const response = await fetch('api/qa/batch', { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({qa_ids: Array.from(selectedQAs)}) }); if (response.status === 404) { // 404状态码表示删除成功 alert('批量删除成功'); selectedQAs.clear(); loadQAList(); } else if (response.status === 500) { // 500状态码表示删除失败 const result = await response.json(); alert('批量删除失败: ' + (result.error || '服务器内部错误')); } else { // 其他状态码处理 const result = await response.json(); if (result.success) { alert(result.data.message); selectedQAs.clear(); loadQAList(); } else { alert('批量删除失败: ' + result.error); } } } catch (error) { // 修复错误:确保error.message存在,避免"Cannot read properties of undefined"错误 const errorMessage = error?.message || error?.toString() || '未知错误'; alert('批量删除时出错: ' + errorMessage); } } // 搜索问题消息 async function searchQuestionMessages() { const keyword = document.getElementById('questionSearch').value.trim(); if (!keyword) { document.getElementById('questionResults').innerHTML = ''; return; } const groupIdSelect = document.getElementById('groupId'); const groupId = groupIdSelect.value; try { const url = `api/search_messages?keyword=${encodeURIComponent(keyword)}&limit=20${groupId ? `&group_id=${groupId}` : ''}`; const response = await fetch(url); const result = await response.json(); if (result.success) { displayQuestionResults(result.messages); } } catch (error) { console.error('搜索问题消息时出错:', error); } } // 添加回车键搜索功能 document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('searchInput'); if (searchInput) { searchInput.addEventListener('keypress', function(e) { if (e.key === 'Enter') { loadQAList(); } }); } const groupFilter = document.getElementById('groupFilter'); if (groupFilter) { groupFilter.addEventListener('keypress', function(e) { if (e.key === 'Enter') { loadQAList(); } }); } }); // 显示问题搜索结果 function displayQuestionResults(messages) { const resultsContainer = document.getElementById('questionResults'); console.log(messages); resultsContainer.innerHTML = messages.map(msg => `
ID: ${msg.id}
内容: ${msg.content ? msg.content.substring(0, 100) + (msg.content.length > 100 ? '...' : '') : '无内容'}
时间: ${msg.formatted_time || '未知'}
`).join(''); } // 搜索答案消息 async function searchAnswerMessages() { const keyword = document.getElementById('answerSearch').value.trim(); if (!keyword) { document.getElementById('answerResults').innerHTML = ''; return; } const groupIdSelect = document.getElementById('groupId'); const groupId = groupIdSelect.value; try { const url = `api/search_messages?keyword=${encodeURIComponent(keyword)}&limit=20${groupId ? `&group_id=${groupId}` : ''}`; const response = await fetch(url); const result = await response.json(); if (result.success) { displayAnswerResults(result.messages); } } catch (error) { console.error('搜索答案消息时出错:', error); } } // 显示答案搜索结果 function displayAnswerResults(messages) { const resultsContainer = document.getElementById('answerResults'); resultsContainer.innerHTML = messages.map(msg => `
ID: ${msg.id}
内容: ${msg.content ? msg.content.substring(0, 100) + (msg.content.length > 100 ? '...' : '') : '无内容'}
时间: ${msg.formatted_time || '未知'}
`).join(''); } // 选择问题消息 function selectQuestion(messageId, content) { if (!selectedQuestions.includes(messageId)) { selectedQuestions.push(messageId); updateSelectedMessages(); } } // 选择答案消息 function selectAnswer(messageId, content) { if (!selectedAnswers.includes(messageId)) { selectedAnswers.push(messageId); updateSelectedMessages(); } } // 从搜索结果添加为问题 function addToQuestion(messageId) { if (!selectedQuestions.includes(messageId)) { selectedQuestions.push(messageId); alert('已添加到问题列表'); } } // 从搜索结果添加为答案 function addToAnswer(messageId) { if (!selectedAnswers.includes(messageId)) { selectedAnswers.push(messageId); alert('已添加到答案列表'); } } // 更新已选择的消息显示 function updateSelectedMessages() { document.getElementById('selectedQuestions').innerHTML = selectedQuestions.map(id => `
消息ID: ${id}
`).join(''); document.getElementById('selectedAnswers').innerHTML = selectedAnswers.map(id => `
消息ID: ${id}
`).join(''); } // 移除问题消息 function removeQuestion(messageId) { selectedQuestions = selectedQuestions.filter(id => id !== messageId); updateSelectedMessages(); } // 移除答案消息 function removeAnswer(messageId) { selectedAnswers = selectedAnswers.filter(id => id !== messageId); updateSelectedMessages(); } // 保存QA记录 async function saveQA() { const groupIdSelect = document.getElementById('groupId'); const groupId = groupIdSelect.value; if (selectedQuestions.length === 0) { alert('请至少选择一个问题消息'); return; } if (selectedAnswers.length === 0) { alert('请至少选择一个答案消息'); return; } const qaData = { groupId: groupId, question: selectedQuestions, answer: selectedAnswers }; try { const url = currentQA ? `api/qa/${currentQA.id}` : '/api/qa'; const method = currentQA ? 'PUT' : 'POST'; const response = await fetch(url, { method: method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(qaData) }); const result = await response.json(); if (result.success) { alert(currentQA ? 'QA记录更新成功' : 'QA记录创建成功'); closeModal(); loadQAList(); } else { alert('保存失败: ' + result.error); } } catch (error) { // 修复错误:确保error.message存在,避免"Cannot read properties of undefined"错误 const errorMessage = error?.message || error?.toString() || '未知错误'; alert('保存时出错: ' + errorMessage); } } // 预览QA async function previewQA(qaId) { try { const response = await fetch(`api/qa/${qaId}`); const result = await response.json(); if (result.success) { displayPreview(result.qa); } else { alert('加载QA详情失败: ' + result.error); } } catch (error) { // 修复错误:确保error.message存在,避免"Cannot read properties of undefined"错误 const errorMessage = error?.message || error?.toString() || '未知错误'; alert('加载QA详情时出错: ' + errorMessage); } } // 显示预览 async function displayPreview(qa) { const previewContent = document.getElementById('previewContent'); // 获取所有消息的详细内容 let allMessages = []; const allMessageIds = [...qa.question_list, ...qa.answer_list]; if (allMessageIds.length > 0) { try { const response = await fetch('api/messages_by_ids', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({message_ids: allMessageIds}) }); const result = await response.json(); if (result.success) { allMessages = result.messages; } } catch (error) { console.error('获取消息详情时出错:', error); } } // 创建消息映射 const messageMap = {}; allMessages.forEach(msg => { messageMap[msg.id] = msg; }); // 按时间排序所有消息 const sortedMessages = allMessages.sort((a, b) => { return new Date(a.time) - new Date(b.time); }); previewContent.innerHTML = `

QA #${qa.id} - 聊天记录预览

群组: ${qa.groupId || '无群组'} | 消息数量: ${sortedMessages.length}
${sortedMessages.map(msg => { const isQuestion = qa.question_list.includes(msg.id); const isAnswer = qa.answer_list.includes(msg.id); const messageType = isQuestion ? 'question' : (isAnswer ? 'answer' : 'other'); return `
${messageType === 'question' ? '❓' : (messageType === 'answer' ? '💬' : '📝')}
${msg.sender_name || msg.sender} ${msg.formatted_time || '未知时间'} ${messageType === 'question' ? '问题' : (messageType === 'answer' ? '答案' : '其他')}
${msg.display_content || '无内容'}
消息ID: ${msg.id} 类型: ${msg.type || '未知'}
`; }).join('')}
问题数量: ${qa.question_list.length}
答案数量: ${qa.answer_list.length}
总消息数: ${sortedMessages.length}
`; document.getElementById('previewModal').style.display = 'block'; } // 删除QA async function deleteQA(qaId) { if (!confirm('确定要删除这个QA记录吗?此操作不可恢复。')) { return; } try { const response = await fetch(`api/qa/${qaId}`, { method: 'DELETE' }); const result = await response.json(); if (result.success) { alert('QA记录删除成功'); loadQAList(); } else { alert('删除失败: ' + result.error); } } catch (error) { // 修复错误:确保error.message存在,避免"Cannot read properties of undefined"错误 const errorMessage = error?.message || error?.toString() || '未知错误'; alert('删除时出错: ' + errorMessage); } } // 关闭模态框 function closeModal() { document.getElementById('qaModal').style.display = 'none'; } // 关闭预览模态框 function closePreviewModal() { document.getElementById('previewModal').style.display = 'none'; } // 点击模态框外部关闭 window.onclick = function (event) { const modal = document.getElementById('qaModal'); const previewModal = document.getElementById('previewModal'); if (event.target === modal) { modal.style.display = 'none'; } if (event.target === previewModal) { previewModal.style.display = 'none'; } }