From 05eab73a5bb76ffea2e9de1680e5a541a74942b5 Mon Sep 17 00:00:00 2001 From: "B.E.N.S.O.N" Date: Fri, 20 Mar 2026 15:25:44 +0800 Subject: [PATCH] StockItemConsumptionTrendReport Excel Version --- src/app/(main)/report/page.tsx | 79 +++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/src/app/(main)/report/page.tsx b/src/app/(main)/report/page.tsx index df24b3b..e99c2f3 100644 --- a/src/app/(main)/report/page.tsx +++ b/src/app/(main)/report/page.tsx @@ -131,19 +131,26 @@ export default function ReportPage() { setDynamicOptions({}); }, [selectedReportId]); - const handlePrint = async () => { - if (!currentReport) return; + const validateRequiredFields = () => { + if (!currentReport) return true; - // 1. Mandatory Field Validation + // Mandatory Field Validation const missingFields = currentReport.fields .filter(field => field.required && !criteria[field.name]) .map(field => field.label); if (missingFields.length > 0) { alert(`缺少必填條件:\n- ${missingFields.join('\n- ')}`); - return; + return false; } + return true; + }; + + const handlePrint = async () => { + if (!currentReport) return; + if (!validateRequiredFields()) return; + // For rep-005, the print logic is handled by SemiFGProductionAnalysisReport component if (currentReport.id === 'rep-005') return; @@ -156,12 +163,51 @@ export default function ReportPage() { await executePrint(); }; + const handleExcelPrint = async () => { + if (!currentReport) return; + if (!validateRequiredFields()) return; + await executeExcelReport(); + }; + const executeExcelReport = async () => { if (!currentReport) return; setLoading(true); try { if (currentReport.id === 'rep-014') { await generateGrnReportExcel(criteria, currentReport.title); + } else { + // Backend returns actual .xlsx bytes for this Excel endpoint. + const queryParams = new URLSearchParams(criteria).toString(); + const excelUrl = `${currentReport.apiEndpoint}-excel?${queryParams}`; + + const response = await clientAuthFetch(excelUrl, { + method: 'GET', + headers: { Accept: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }, + }); + + if (response.status === 401 || response.status === 403) return; + if (!response.ok) { + const errorText = await response.text(); + console.error("Response error:", errorText); + throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`); + } + + const blob = await response.blob(); + const downloadUrl = window.URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = downloadUrl; + + const contentDisposition = response.headers.get('Content-Disposition'); + let fileName = `${currentReport.title}.xlsx`; + if (contentDisposition?.includes('filename=')) { + fileName = contentDisposition.split('filename=')[1].split(';')[0].replace(/"/g, ''); + } + + link.setAttribute('download', fileName); + document.body.appendChild(link); + link.click(); + link.remove(); + window.URL.revokeObjectURL(downloadUrl); } setShowConfirmDialog(false); } catch (error) { @@ -438,7 +484,7 @@ export default function ReportPage() { })} - + {currentReport.id === 'rep-005' ? ( + ) : currentReport.id === 'rep-006' ? ( + <> + + + ) : currentReport.responseType === 'excel' ? (