From e06913008f124ce8e7389fbdc1e57206ce9bbb2b Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Tue, 9 Sep 2025 03:19:41 +0000 Subject: (김준회) 협력업체관리 업체분류, 정규업체등록현황 부 수정, 파일다운로드 오류 수정, 업데이트 시트 수정 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/vendors/service.ts | 37 ++-------- lib/vendors/table/attachmentButton.tsx | 7 +- lib/vendors/table/update-vendor-sheet.tsx | 6 +- lib/vendors/table/vendors-table-columns.tsx | 101 +++++++++++++++++++++++++++- lib/vendors/validations.ts | 2 +- 5 files changed, 115 insertions(+), 38 deletions(-) (limited to 'lib') diff --git a/lib/vendors/service.ts b/lib/vendors/service.ts index 0c8254f2..a22a1551 100644 --- a/lib/vendors/service.ts +++ b/lib/vendors/service.ts @@ -1376,43 +1376,18 @@ interface CreateCompanyInput { export async function downloadVendorAttachments(vendorId: number, fileId?: number) { try { // API 경로 생성 (단일 파일 또는 모든 파일) - const url = fileId + const path = fileId ? `/api/vendors/attachments/download?id=${fileId}&vendorId=${vendorId}` : `/api/vendors/attachments/download-all?vendorId=${vendorId}`; - // fetch 요청 (기본적으로 Blob으로 응답 받기) - const response = await fetch(url, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }); - - if (!response.ok) { - throw new Error(`Server responded with ${response.status}: ${response.statusText}`); - } - - // 파일명 가져오기 (Content-Disposition 헤더에서) - const contentDisposition = response.headers.get('content-disposition'); - let fileName = fileId ? `file-${fileId}.zip` : `vendor-${vendorId}-files.zip`; - - if (contentDisposition) { - const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(contentDisposition); - if (matches && matches[1]) { - fileName = matches[1].replace(/['"]/g, ''); - } - } - - // Blob으로 응답 변환 - const blob = await response.blob(); - - // Blob URL 생성 - const blobUrl = window.URL.createObjectURL(blob); + // 서버에서는 URL만 반환하고, 클라이언트에서 실제 다운로드 처리 + // 파일명도 기본값으로 설정 + const fileName = fileId ? `file-${fileId}.zip` : `vendor-${vendorId}-attachments.zip`; return { - url: blobUrl, + url: path, // 상대 경로 반환 fileName, - blob + isServerAction: true // 서버 액션임을 표시 }; } catch (error) { console.error('Download API error:', error); diff --git a/lib/vendors/table/attachmentButton.tsx b/lib/vendors/table/attachmentButton.tsx index 3ffa9c5f..86cf992b 100644 --- a/lib/vendors/table/attachmentButton.tsx +++ b/lib/vendors/table/attachmentButton.tsx @@ -35,9 +35,14 @@ export function AttachmentsButton({ vendorId, hasAttachments, attachmentsList = // 파일 다운로드 트리거 toast.success('첨부파일 다운로드가 시작되었습니다.'); + // 서버 액션에서 상대 URL을 반환하므로 절대 URL로 변환 + const downloadUrl = result.isServerAction + ? `${window.location.origin}${result.url}` + : result.url; + // 다운로드 링크 열기 const a = document.createElement('a'); - a.href = result.url; + a.href = downloadUrl; a.download = result.fileName || '첨부파일.zip'; a.style.display = 'none'; document.body.appendChild(a); diff --git a/lib/vendors/table/update-vendor-sheet.tsx b/lib/vendors/table/update-vendor-sheet.tsx index 5138d299..d8d4ad67 100644 --- a/lib/vendors/table/update-vendor-sheet.tsx +++ b/lib/vendors/table/update-vendor-sheet.tsx @@ -201,7 +201,7 @@ export function UpdateVendorSheet({ vendor, ...props }: UpdateVendorSheetProps) cashFlowRating: vendor?.cashFlowRating ?? "", status: (vendor?.status as any) ?? "ACTIVE", vendorTypeId: vendor?.vendorTypeId ?? undefined, - isAssociationMember: (vendor as any)?.isAssociationMember || "NONE", + isAssociationMember: (vendor as any)?.isAssociationMember ?? "NONE", // 대표자 정보 representativeName: (vendor as any)?.representativeName ?? "", @@ -240,7 +240,7 @@ export function UpdateVendorSheet({ vendor, ...props }: UpdateVendorSheetProps) cashFlowRating: vendor?.cashFlowRating ?? "", status: (vendor?.status as any) ?? "ACTIVE", vendorTypeId: vendor?.vendorTypeId ?? undefined, - isAssociationMember: (vendor as any)?.isAssociationMember || "NONE", + isAssociationMember: (vendor as any)?.isAssociationMember ?? "NONE", // 대표자 정보 representativeName: (vendor as any)?.representativeName ?? "", @@ -547,7 +547,7 @@ export function UpdateVendorSheet({ vendor, ...props }: UpdateVendorSheetProps)