const Export = (() => { async function render() { setTimeout(bindEvents, 0); return `
📤 数据导出
📋 数据预览
请选择数据类型查看预览
`; } function bindEvents() { const typeSelect = document.getElementById('export-type'); const excelBtn = document.getElementById('export-excel'); const pdfBtn = document.getElementById('export-pdf'); // 类型改变时更新预览 if (typeSelect) { typeSelect.addEventListener('change', updatePreview); // 初始加载预览 updatePreview(); } // Excel导出 if (excelBtn) { excelBtn.addEventListener('click', async () => { const type = typeSelect.value; await exportData(type, 'excel'); }); } // PDF导出 if (pdfBtn) { pdfBtn.addEventListener('click', async () => { const type = typeSelect.value; await exportData(type, 'pdf'); }); } } async function updatePreview() { const type = document.getElementById('export-type').value; const preview = document.getElementById('export-preview'); try { preview.innerHTML = '
加载中...
'; let data; switch(type) { case 'stats': data = await API.listStats(); renderStatsPreview(data.list || []); break; case 'mac': data = await API.listMac(); renderMacPreview(data.list || []); break; case 'repairs': data = await API.listRepairs(); renderRepairsPreview(data.list || []); break; case 'defects': data = await API.listDefects(); renderDefectsPreview(data.list || []); break; case 'shipments': data = await API.listShipments(); renderShipmentsPreview(data.list || []); break; case 'devices': data = await API.devices(); renderDevicesPreview(data.list || []); break; case 'environment': data = await API.environment(); renderEnvironmentPreview(data); break; case 'personnel': data = await API.personnel(); renderPersonnelPreview(data.list || []); break; case 'qa': data = await API.qa(); renderQaPreview(data.list || []); break; case 'production': data = await API.production(); renderProductionPreview(data.list || []); break; } } catch (e) { preview.innerHTML = '
加载失败
'; } } function renderStatsPreview(list) { const preview = document.getElementById('export-preview'); if (list.length === 0) { preview.innerHTML = '
暂无数据
'; return; } preview.innerHTML = ` ${list.slice(0, 50).map(item => ` `).join('')}
直通良品数 良品数 不良品数 时间
${item.fpy_good || 0} ${item.good} ${item.bad} ${new Date(item.ts).toLocaleString('zh-CN')}
${list.length > 50 ? `
仅显示前50条,导出时将包含全部 ${list.length} 条数据
` : ''} `; } function renderMacPreview(list) { const preview = document.getElementById('export-preview'); if (list.length === 0) { preview.innerHTML = '
暂无数据
'; return; } preview.innerHTML = ` ${list.slice(0, 50).map(item => ` `).join('')}
MAC地址 批次号 时间
${item.mac} ${item.batch} ${new Date(item.ts).toLocaleString('zh-CN')}
${list.length > 50 ? `
仅显示前50条,导出时将包含全部 ${list.length} 条数据
` : ''} `; } function renderRepairsPreview(list) { const preview = document.getElementById('export-preview'); if (list.length === 0) { preview.innerHTML = '
暂无数据
'; return; } preview.innerHTML = ` ${list.slice(0, 50).map(item => ` `).join('')}
返修数量 备注 时间
${item.qty} ${item.note || '无'} ${new Date(item.ts).toLocaleString('zh-CN')}
${list.length > 50 ? `
仅显示前50条,导出时将包含全部 ${list.length} 条数据
` : ''} `; } function renderDefectsPreview(list) { const preview = document.getElementById('export-preview'); if (list.length === 0) { preview.innerHTML = '
暂无数据
'; return; } preview.innerHTML = ` ${list.slice(0, 50).map(item => ` `).join('')}
MAC地址 批次号 时间
${item.mac} ${item.batch} ${new Date(item.ts).toLocaleString('zh-CN')}
${list.length > 50 ? `
仅显示前50条,导出时将包含全部 ${list.length} 条数据
` : ''} `; } function renderShipmentsPreview(list) { const preview = document.getElementById('export-preview'); if (list.length === 0) { preview.innerHTML = '
暂无数据
'; return; } preview.innerHTML = ` ${list.slice(0, 50).map(item => ` `).join('')}
日期 数量 收货方 时间
${item.date} ${item.qty} ${item.receiver} ${new Date(item.ts).toLocaleString('zh-CN')}
${list.length > 50 ? `
仅显示前50条,导出时将包含全部 ${list.length} 条数据
` : ''} `; } function renderDevicesPreview(list) { const preview = document.getElementById('export-preview'); if (list.length === 0) { preview.innerHTML = '
暂无数据
'; return; } preview.innerHTML = ` ${list.map(item => ` `).join('')}
设备名称 状态
${item.name} ${item.status}
`; } function renderEnvironmentPreview(data) { const preview = document.getElementById('export-preview'); preview.innerHTML = `
参数
温度 ${data.temp || '—'}
湿度 ${data.hum || '—'}
`; } function renderPersonnelPreview(list) { const preview = document.getElementById('export-preview'); if (list.length === 0) { preview.innerHTML = '
暂无数据
'; return; } preview.innerHTML = ` ${list.map(item => ` `).join('')}
姓名 角色
${item.name} ${item.role || '—'}
`; } function renderQaPreview(list) { const preview = document.getElementById('export-preview'); if (list.length === 0) { preview.innerHTML = '
暂无数据
'; return; } preview.innerHTML = ` ${list.map(item => ` `).join('')}
标题 日期
${item.title} ${item.date}
`; } function renderProductionPreview(list) { const preview = document.getElementById('export-preview'); if (list.length === 0) { preview.innerHTML = '
暂无数据
'; return; } preview.innerHTML = ` ${list.map(item => ` `).join('')}
批次 时长
${item.batch} ${item.duration}
`; } async function exportData(type, format) { const statusEl = document.getElementById('export-status'); try { statusEl.style.display = 'block'; statusEl.style.background = 'rgba(79,140,255,0.1)'; statusEl.style.color = 'var(--primary)'; statusEl.textContent = `正在导出${format.toUpperCase()}...`; // 调用导出API并下载文件 const endpoint = format === 'excel' ? '/api/export/excel' : '/api/export/pdf'; const response = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ type }) }); if (!response.ok) { throw new Error('导出失败'); } // 获取文件名 const contentDisposition = response.headers.get('Content-Disposition'); let filename = `export_${type}_${Date.now()}.${format === 'excel' ? 'xlsx' : 'pdf'}`; if (contentDisposition) { const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/); if (filenameMatch && filenameMatch[1]) { filename = filenameMatch[1].replace(/['"]/g, ''); } } // 下载文件 const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = filename; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); statusEl.style.background = 'rgba(34,197,94,0.1)'; statusEl.style.color = 'var(--success)'; statusEl.textContent = `✓ ${format.toUpperCase()}导出成功!文件已下载`; setTimeout(() => { statusEl.style.display = 'none'; }, 3000); } catch (e) { statusEl.style.background = 'rgba(239,68,68,0.1)'; statusEl.style.color = 'var(--danger)'; statusEl.textContent = `✗ 导出失败: ${e.message}`; } } Router.register('/export', render); })();