215 lines
6.9 KiB
JavaScript
215 lines
6.9 KiB
JavaScript
// static/history.js
|
||
|
||
// 页面加载完成后加载历史记录
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
loadHistory();
|
||
});
|
||
|
||
async function loadHistory() {
|
||
const fileList = document.getElementById('fileList');
|
||
|
||
try {
|
||
const response = await fetch('/api/history', {
|
||
method: 'POST'
|
||
});
|
||
if (!response.ok) {
|
||
throw new Error('获取历史记录失败');
|
||
}
|
||
|
||
const data = await response.json();
|
||
|
||
if (data.files && data.files.length > 0) {
|
||
displayFileList(data.files);
|
||
} else {
|
||
fileList.innerHTML = `
|
||
<div class="no-records">
|
||
<div style="font-size: 48px; margin-bottom: 20px;">📁</div>
|
||
<h3>暂无历史记录</h3>
|
||
<p>还没有上传过STP文件</p>
|
||
<button class="upload-btn" onclick="location.href='/upload'">
|
||
上传第一个文件
|
||
</button>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
} catch (error) {
|
||
fileList.innerHTML = `
|
||
<div class="no-records">
|
||
<div style="font-size: 48px; margin-bottom: 20px;">❌</div>
|
||
<h3>加载失败</h3>
|
||
<p>${error.message}</p>
|
||
<button class="upload-btn" onclick="loadHistory()">
|
||
重试
|
||
</button>
|
||
</div>
|
||
`;
|
||
}
|
||
}
|
||
|
||
function displayFileList(files) {
|
||
const fileList = document.getElementById('fileList');
|
||
|
||
fileList.innerHTML = files.map(file => `
|
||
<div class="file-item" id="file-${file.filename}">
|
||
<div class="file-header" onclick="toggleFileRecords('${file.filename}')">
|
||
<div class="file-info">
|
||
<div class="file-name">📄 ${file.filename}</div>
|
||
<div class="file-meta">
|
||
总记录: ${file.record_count} 条 |
|
||
最后上传: ${formatDateTime(file.last_upload)}
|
||
</div>
|
||
</div>
|
||
<button class="expand-btn" onclick="event.stopPropagation(); toggleFileRecords('${file.filename}')">
|
||
➕
|
||
</button>
|
||
</div>
|
||
<div class="record-list" id="records-${file.filename}">
|
||
<div class="loading">
|
||
<div class="spinner"></div>
|
||
<p>正在加载记录详情...</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`).join('');
|
||
}
|
||
|
||
async function toggleFileRecords(filename) {
|
||
const fileItem = document.getElementById(`file-${filename}`);
|
||
const recordList = document.getElementById(`records-${filename}`);
|
||
const expandBtn = fileItem.querySelector('.expand-btn');
|
||
|
||
// 切换展开状态
|
||
if (fileItem.classList.contains('expanded')) {
|
||
fileItem.classList.remove('expanded');
|
||
expandBtn.textContent = '➕';
|
||
return;
|
||
}
|
||
|
||
// 先设置展开状态
|
||
fileItem.classList.add('expanded');
|
||
expandBtn.textContent = '➖';
|
||
|
||
// 如果已经加载过数据,直接显示
|
||
if (recordList.dataset.loaded === 'true') {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`/api/history/${encodeURIComponent(filename)}`, {
|
||
method: 'POST'
|
||
});
|
||
if (!response.ok) {
|
||
throw new Error('获取记录详情失败');
|
||
}
|
||
|
||
const records = await response.json();
|
||
|
||
if (records.length > 0) {
|
||
recordList.innerHTML = records.map(record => `
|
||
<div class="record-item" onclick="viewRecordDetails('${record.task_id}')">
|
||
<div class="record-header">
|
||
<div class="record-time">
|
||
📅 ${formatDateTime(record.upload_time)}
|
||
</div>
|
||
<div class="record-status status-${record.status}">
|
||
${getStatusText(record.status)}
|
||
</div>
|
||
</div>
|
||
<div class="record-details">
|
||
<div>文件大小: ${formatFileSize(record.file_size)}</div>
|
||
<div>任务ID: ${record.task_id}</div>
|
||
<div>状态: ${record.status}</div>
|
||
${record.completed_at ? `<div>完成时间: ${formatDateTime(record.completed_at)}</div>` : ''}
|
||
</div>
|
||
</div>
|
||
`).join('');
|
||
} else {
|
||
recordList.innerHTML = `
|
||
<div class="no-records">
|
||
<p>暂无详细记录</p>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
recordList.dataset.loaded = 'true';
|
||
|
||
} catch (error) {
|
||
recordList.innerHTML = `
|
||
<div class="no-records">
|
||
<p>❌ 加载失败: ${error.message}</p>
|
||
<button class="upload-btn" onclick="toggleFileRecords('${filename}')">
|
||
重试
|
||
</button>
|
||
</div>
|
||
`;
|
||
}
|
||
}
|
||
|
||
async function viewRecordDetails(taskId) {
|
||
// 直接跳转到结果页面,由后端从数据库加载完整数据
|
||
window.location.href = `/result/${taskId}`;
|
||
}
|
||
|
||
async function reanalyzeTask(taskId) {
|
||
try {
|
||
const response = await fetch(`/api/reanalyze/${taskId}`, {
|
||
method: 'POST'
|
||
});
|
||
|
||
if (response.ok) {
|
||
alert('重新分析任务已启动,请稍后查看结果');
|
||
// 跳转到分析状态页面
|
||
window.location.href = `/status/${taskId}`;
|
||
} else {
|
||
throw new Error('重新分析失败');
|
||
}
|
||
} catch (error) {
|
||
alert(`重新分析失败: ${error.message}`);
|
||
}
|
||
}
|
||
|
||
function getStatusText(status) {
|
||
const statusMap = {
|
||
'completed': '已完成',
|
||
'processing': '处理中',
|
||
'failed': '失败'
|
||
};
|
||
return statusMap[status] || status;
|
||
}
|
||
|
||
function formatFileSize(bytes) {
|
||
if (!bytes || bytes === 0) return '0 Bytes';
|
||
const k = 1024;
|
||
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||
}
|
||
|
||
function formatDateTime(dateString) {
|
||
if (!dateString) return 'N/A';
|
||
// 后端已经返回格式化的时间字符串,直接返回
|
||
return dateString;
|
||
}
|
||
|
||
// 跳转到上传页面
|
||
async function goToUpload() {
|
||
try {
|
||
// 上传页面需要GET请求,直接跳转
|
||
window.location.href = '/';
|
||
} catch (error) {
|
||
console.error('跳转失败:', error);
|
||
window.location.href = '/';
|
||
}
|
||
}
|
||
|
||
// 跳转到主页
|
||
async function goToHome() {
|
||
try {
|
||
// 主页需要GET请求,直接跳转
|
||
window.location.href = '/';
|
||
} catch (error) {
|
||
console.error('跳转失败:', error);
|
||
window.location.href = '/';
|
||
}
|
||
} |