Files
SmartChat/static/js/qa.js
2026-01-08 01:06:27 +08:00

1015 lines
35 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 = '<option value="">' + (selectElement.id === 'groupFilter' ? '全部群组' : '选择群组(可选)') + '</option>';
// 添加群组选项
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 = `
<div class="empty-state">
<div>📝</div>
<h3>暂无QA记录</h3>
<p>点击"创建新QA"按钮开始创建第一个问答记录</p>
</div>
`;
// 隐藏批量操作按钮
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 `
<div class="qa-item ${isSelected ? 'selected' : ''}" data-qa-id="${qa.id}">
<div class="qa-header">
<div class="qa-checkbox">
<input type="checkbox" class="qa-select" ${isSelected ? 'checked' : ''} onchange="toggleQASelection(${qa.id}, this.checked)">
</div>
<div class="qa-id">QA #${qa.id}</div>
<div class="qa-group">${qa.groupId || '无群组'}</div>
</div>
<div class="qa-content">
<div class="qa-question">
<strong>问题:</strong> ${questionContent}
</div>
<div class="qa-stats">
<span class="stat">问题: ${questionIds.length}条</span>
<span class="stat">答案: ${answerIds.length}条</span>
</div>
</div>
<div class="qa-actions">
<button class="btn btn-primary" onclick="previewQA(${qa.id})">预览</button>
<button class="btn" onclick="editQA(${qa.id})">编辑</button>
<button class="btn btn-danger" onclick="deleteQA(${qa.id})">删除</button>
</div>
</div>
`;
}).join('');
// 更新批量操作按钮状态
updateBatchActions();
}
// 搜索消息
async function searchMessages() {
const keyword = document.getElementById('searchInput').value.trim();
if (!keyword) {
alert('请输入搜索关键词');
return;
}
try {
// 显示搜索中状态
const qaListContainer = document.getElementById('qaList');
qaListContainer.innerHTML = '<div class="loading">搜索中...</div>';
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 = '<div class="loading">搜索中...</div>';
// 构建查询参数
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 = `
<div class="search-history-header">
<span>搜索历史</span>
<button class="btn-clear-history" onclick="clearSearchHistory()">清空</button>
</div>
<div class="search-history-items">
${searchHistory.map(item => `
<div class="search-history-item" onclick="fillSearchInput('${item.replace(/'/g, "\\'")}')">
${item}
</div>
`).join('')}
</div>
`;
}
// 填充搜索输入框
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 => `
<div class="search-suggestion-item" onclick="selectSearchSuggestion('${item.replace(/'/g, "\\'")}')">
${item}
</div>
`).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 = `
<div class="empty-state">
<div>🔍</div>
<h3>未找到相关消息</h3>
<p>请尝试其他搜索关键词或调整搜索条件</p>
</div>
`;
return;
}
qaListContainer.innerHTML = `
<div class="search-results-header">
<h3>搜索结果 (${messages.length} 条)</h3>
<div class="search-summary">
搜索关键词: "${keyword}"
</div>
</div>
${messages.map(msg => `
<div class="qa-item search-result-item">
<div class="qa-header">
<div class="qa-id">消息ID: ${msg.id}</div>
<div class="qa-group">${msg.formatted_time || '未知时间'}</div>
</div>
<div class="qa-content">
<div class="message-item">
<strong>类型:</strong> ${msg.type} |
<strong>发送者:</strong> ${msg.sender_name || '未知'} |
<strong>接收者:</strong> ${msg.receiver || '未知'}
</div>
<div class="message-item" style="margin-top: 10px;">
<strong>内容:</strong>
<div class="message-content">
${msg.highlighted_content ? msg.highlighted_content : (msg.display_content || '无内容')}
</div>
</div>
</div>
<div class="qa-actions">
<button class="btn btn-primary" onclick="addToQuestion('${msg.id}')">设为问题</button>
<button class="btn btn-success" onclick="addToAnswer('${msg.id}')">设为答案</button>
<button class="btn btn-info" onclick="viewMessageDetail('${msg.id}')">查看详情</button>
</div>
</div>
`).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 => `
<div class="search-result-item" onclick="selectQuestion('${msg.id}', '${msg.content.replace(/'/g, "\\'").substring(0, 100)}')">
<div><strong>ID:</strong> ${msg.id}</div>
<div><strong>内容:</strong> ${msg.content ? msg.content.substring(0, 100) + (msg.content.length > 100 ? '...' : '') : '无内容'}</div>
<div><strong>时间:</strong> ${msg.formatted_time || '未知'}</div>
</div>
`).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 => `
<div class="search-result-item" onclick="selectAnswer('${msg.id}', '${msg.content.replace(/'/g, "\\'").substring(0, 100)}')">
<div><strong>ID:</strong> ${msg.id}</div>
<div><strong>内容:</strong> ${msg.content ? msg.content.substring(0, 100) + (msg.content.length > 100 ? '...' : '') : '无内容'}</div>
<div><strong>时间:</strong> ${msg.formatted_time || '未知'}</div>
</div>
`).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 => `
<div class="selected-message">
<span>消息ID: ${id}</span>
<button class="btn btn-danger" onclick="removeQuestion('${id}')" style="padding: 2px 8px; font-size: 12px;">移除</button>
</div>
`).join('');
document.getElementById('selectedAnswers').innerHTML = selectedAnswers.map(id => `
<div class="selected-message">
<span>消息ID: ${id}</span>
<button class="btn btn-danger" onclick="removeAnswer('${id}')" style="padding: 2px 8px; font-size: 12px;">移除</button>
</div>
`).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 = `
<div class="chat-preview">
<div class="chat-header">
<h3>QA #${qa.id} - 聊天记录预览</h3>
<div class="chat-info">群组: ${qa.groupId || '无群组'} | 消息数量: ${sortedMessages.length}</div>
</div>
<div class="chat-container">
${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 `
<div class="chat-message ${messageType}">
<div class="message-avatar">
${messageType === 'question' ? '❓' : (messageType === 'answer' ? '💬' : '📝')}
</div>
<div class="message-content">
<div class="message-header">
<span class="sender">${msg.sender_name || msg.sender}</span>
<span class="time">${msg.formatted_time || '未知时间'}</span>
<span class="message-type-badge ${messageType}">${messageType === 'question' ? '问题' : (messageType === 'answer' ? '答案' : '其他')}</span>
</div>
<div class="message-text">${msg.display_content || '无内容'}</div>
<div class="message-meta">
<span class="message-id">消息ID: ${msg.id}</span>
<span class="message-type">类型: ${msg.type || '未知'}</span>
</div>
</div>
</div>
`;
}).join('')}
</div>
<div class="chat-summary">
<div class="summary-item">
<span class="summary-label">问题数量:</span>
<span class="summary-value">${qa.question_list.length}</span>
</div>
<div class="summary-item">
<span class="summary-label">答案数量:</span>
<span class="summary-value">${qa.answer_list.length}</span>
</div>
<div class="summary-item">
<span class="summary-label">总消息数:</span>
<span class="summary-value">${sortedMessages.length}</span>
</div>
</div>
</div>
`;
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';
}
}