fix: 修复生成日报 configId 未定义错误
Coze-Commit-Type: user Coze-User-ID: 3722323274763196 Coze-Conversation-ID: 9894087
This commit is contained in:
@@ -2115,220 +2115,65 @@
|
||||
}
|
||||
|
||||
const resultDiv = document.getElementById('generate-result');
|
||||
resultDiv.innerHTML = '<div class="alert alert-info">正在生成日报,请稍候...</div>';
|
||||
resultDiv.innerHTML = '<div class="alert alert-info">正在批量生成日报,请稍候...</div>';
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/report/generate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
config_id: parseInt(configId),
|
||||
start_time: startTime.replace('T', ' ') + ':00',
|
||||
end_time: endTime.replace('T', ' ') + ':00'
|
||||
})
|
||||
});
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
let results = [];
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
resultDiv.innerHTML = `
|
||||
<div class="alert alert-success">
|
||||
<strong>✓ 日报生成成功!</strong><br><br>
|
||||
<div style="margin-left: 20px;">
|
||||
<strong>统计信息:</strong><br>
|
||||
• 订单数量: ${result.total_orders} 条<br>
|
||||
• 总金额: ¥${result.total_amount.toFixed(2)}<br>
|
||||
${result.sum_results && Object.keys(result.sum_results).length > 0 ?
|
||||
'<strong>求和结果:</strong><br>' +
|
||||
Object.entries(result.sum_results).map(([field, value]) =>
|
||||
`• ${field}: ${typeof value === 'number' ? value.toFixed(2) : value}`
|
||||
).join('<br>')
|
||||
: ''}
|
||||
</div>
|
||||
<br>
|
||||
<div style="display: flex; gap: 10px; margin-top: 15px;">
|
||||
<a href="/api/download?path=${result.file_path}" target="_blank" class="btn btn-success">
|
||||
📥 立即下载Excel文件
|
||||
</a>
|
||||
<button class="btn btn-primary" onclick="switchTab('history'); document.querySelectorAll('.tab')[2].click();">
|
||||
📋 查看历史记录
|
||||
</button>
|
||||
</div>
|
||||
<br>
|
||||
<div style="font-size: 12px; color: #666; margin-top: 10px;">
|
||||
💡 提示:生成的日报也会保存在"历史记录"标签页中,可以随时下载。
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
resultDiv.innerHTML = `
|
||||
<div class="alert alert-error">
|
||||
<strong>✗ 生成失败</strong><br><br>
|
||||
<strong>错误信息:</strong><br>
|
||||
${result.message}<br><br>
|
||||
<strong>可能的原因:</strong><br>
|
||||
• 选择的时间范围内没有符合条件的订单<br>
|
||||
• 数据库连接失败<br>
|
||||
• 配置信息有误<br><br>
|
||||
<strong>建议:</strong><br>
|
||||
• 检查时间范围是否正确<br>
|
||||
• 确认配置中的企业/用户是否有订单数据<br>
|
||||
• 查看服务器日志获取详细错误信息
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.innerHTML = `<div class="alert alert-error">生成失败: ${error.message}</div>`;
|
||||
}
|
||||
}
|
||||
for (const cb of checkboxes) {
|
||||
const configId = parseInt(cb.value);
|
||||
const configName = cb.dataset.name;
|
||||
|
||||
// 加载历史记录
|
||||
async function loadHistory(page = 1) {
|
||||
console.log('[loadHistory] 开始加载,page:', page);
|
||||
currentPage = page;
|
||||
|
||||
const tbody = document.getElementById('history-list');
|
||||
if (tbody) {
|
||||
tbody.innerHTML = '<tr><td colspan="8" class="loading">加载中...</td></tr>';
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('[loadHistory] 发送请求...');
|
||||
const response = await fetch(`/api/report/history?page=${page}&page_size=${pageSize}`);
|
||||
console.log('[loadHistory] 响应状态:', response.status);
|
||||
const result = await response.json();
|
||||
console.log('[loadHistory] 响应数据:', result);
|
||||
|
||||
if (result.success) {
|
||||
console.log('[loadHistory] 渲染历史记录...');
|
||||
renderHistory(result.data.list);
|
||||
renderPagination(result.data.total, page);
|
||||
} else {
|
||||
console.error('[loadHistory] API返回失败:', result.error);
|
||||
if (tbody) {
|
||||
tbody.innerHTML = '<tr><td colspan="8" class="empty">加载失败: ' + (result.error || '未知错误') + '</td></tr>';
|
||||
try {
|
||||
const response = await fetch('/api/report/generate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
config_id: configId,
|
||||
start_time: startTime.replace('T', ' ') + ':00',
|
||||
end_time: endTime.replace('T', ' ') + ':00'
|
||||
})
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
successCount++;
|
||||
results.push({ name: configName, success: true, ...result });
|
||||
} else {
|
||||
failCount++;
|
||||
results.push({ name: configName, success: false, message: result.message });
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[loadHistory] 错误:', error);
|
||||
if (tbody) {
|
||||
tbody.innerHTML = '<tr><td colspan="8" class="empty">加载失败: ' + error.message + '</td></tr>';
|
||||
} catch (error) {
|
||||
failCount++;
|
||||
results.push({ name: configName, success: false, message: error.message });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染历史记录
|
||||
function renderHistory(history) {
|
||||
const tbody = document.getElementById('history-list');
|
||||
// 显示结果
|
||||
let html = '<div class="alert alert-info"><strong>生成完成</strong><br><br>';
|
||||
html += `成功:${successCount} 个,失败:${failCount} 个<br><br>`;
|
||||
|
||||
if (history.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="8" class="empty">暂无历史记录<br><br>生成日报后,记录会显示在这里</td></tr>';
|
||||
return;
|
||||
}
|
||||
|
||||
tbody.innerHTML = history.map(item => {
|
||||
// 调试信息
|
||||
console.log('历史记录项:', item);
|
||||
console.log(' status:', item.status, '类型:', typeof item.status);
|
||||
console.log(' file_path:', item.file_path, '类型:', typeof item.file_path);
|
||||
console.log(' 是否有文件:', !!(item.status === 1 && item.file_path));
|
||||
|
||||
const hasFile = item.status === 1 && item.file_path && item.file_path.trim() !== '';
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<td><input type="checkbox" class="history-checkbox" value="${item.id}"></td>
|
||||
<td>${formatDateDisplay(item.report_date)}</td>
|
||||
<td style="font-size: 12px;">${formatDateTimeDisplay(item.start_time)}<br>至<br>${formatDateTimeDisplay(item.end_time)}</td>
|
||||
<td>${item.config_name || '-'}</td>
|
||||
<td>${item.split_name || item.split_value}</td>
|
||||
<td><strong>${item.total_orders}</strong></td>
|
||||
<td><strong>¥${parseFloat(item.total_amount || 0).toFixed(2)}</strong></td>
|
||||
<td>
|
||||
<span class="status-badge ${item.status === 1 ? 'status-active' : 'status-inactive'}">
|
||||
${item.status === 1 ? '✓ 成功' : '✗ 失败'}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
${hasFile ?
|
||||
`<a href="/api/download?path=${encodeURIComponent(item.file_path)}" target="_blank" class="btn btn-sm btn-success">📥 下载</a>` :
|
||||
`<span style="color: #999;" title="文件路径: ${item.file_path || '无'}">-</span>`}
|
||||
<button onclick="deleteHistory(${item.id})" class="btn btn-sm btn-danger" style="margin-left: 5px;">🗑️ 删除</button>
|
||||
</td>
|
||||
</tr>
|
||||
`}).join('');
|
||||
}
|
||||
|
||||
// 渲染分页
|
||||
function renderPagination(total, currentPage) {
|
||||
const totalPages = Math.ceil(total / pageSize);
|
||||
const pagination = document.getElementById('pagination');
|
||||
|
||||
if (totalPages <= 1) {
|
||||
pagination.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
pagination.innerHTML = `
|
||||
<button ${currentPage === 1 ? 'disabled' : ''} onclick="loadHistory(${currentPage - 1})">上一页</button>
|
||||
<span>第 ${currentPage} / ${totalPages} 页,共 ${total} 条</span>
|
||||
<button ${currentPage === totalPages ? 'disabled' : ''} onclick="loadHistory(${currentPage + 1})">下一页</button>
|
||||
`;
|
||||
}
|
||||
|
||||
// 刷新历史记录
|
||||
function refreshHistory() {
|
||||
loadHistory(currentPage);
|
||||
}
|
||||
|
||||
// 全选/取消全选
|
||||
function toggleSelectAll() {
|
||||
const selectAll = document.getElementById('select-all');
|
||||
const checkboxes = document.querySelectorAll('.history-checkbox');
|
||||
checkboxes.forEach(cb => cb.checked = selectAll.checked);
|
||||
}
|
||||
|
||||
// 获取选中的ID列表
|
||||
function getSelectedIds() {
|
||||
const checkboxes = document.querySelectorAll('.history-checkbox:checked');
|
||||
return Array.from(checkboxes).map(cb => parseInt(cb.value));
|
||||
}
|
||||
|
||||
// 批量删除
|
||||
async function batchDeleteHistory() {
|
||||
const ids = getSelectedIds();
|
||||
if (ids.length === 0) {
|
||||
alert('请先选择要删除的记录');
|
||||
return;
|
||||
}
|
||||
if (!confirm(`确定要删除选中的 ${ids.length} 条记录吗?`)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const response = await fetch('/api/report/history/batch-delete', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ ids })
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
alert(`成功删除 ${result.deleted_count} 条记录`);
|
||||
loadHistory(currentPage);
|
||||
results.forEach(r => {
|
||||
if (r.success) {
|
||||
html += `<div style="margin: 10px 0; padding: 10px; background: #f0f8ff; border-radius: 4px;">`;
|
||||
html += `<strong>✓ ${r.name}</strong><br>`;
|
||||
html += `订单数量:${r.total_orders} 条,总金额:¥${r.total_amount.toFixed(2)}<br>`;
|
||||
html += `<a href="/api/download?path=${r.file_path}" target="_blank" class="btn btn-sm btn-success" style="margin-top: 5px;">📥 下载</a>`;
|
||||
html += `</div>`;
|
||||
} else {
|
||||
alert('批量删除失败: ' + (result.error || '未知错误'));
|
||||
html += `<div style="margin: 10px 0; padding: 10px; background: #fff0f0; border-radius: 4px;">`;
|
||||
html += `<strong>✗ ${r.name}</strong><br>`;
|
||||
html += `错误:${r.message}`;
|
||||
html += `</div>`;
|
||||
}
|
||||
} catch (error) {
|
||||
alert('批量删除失败: ' + error.message);
|
||||
}
|
||||
});
|
||||
|
||||
html += '</div>';
|
||||
resultDiv.innerHTML = html;
|
||||
}
|
||||
|
||||
// 批量下载
|
||||
function batchDownloadHistory() {
|
||||
const ids = getSelectedIds();
|
||||
if (ids.length === 0) {
|
||||
alert('请先选择要下载的记录');
|
||||
return;
|
||||
}
|
||||
// 逐个下载
|
||||
ids.forEach(id => {
|
||||
window.open(`/api/download?id=${id}`, '_blank');
|
||||
|
||||
Reference in New Issue
Block a user