From 5cb225e9cd6b0ba2f52572a3afa0de6e5b2a2ece Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Fri, 18 Jul 2025 16:32:22 +0900
Subject: 파일첨부 API 처리, 텍스트 변경
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/[lng]/admin/approval-test/page.tsx | 6 ++--
components/knox/approval/ApprovalDetail.tsx | 54 +++++++++++++++++++++++++++--
components/knox/approval/ApprovalSubmit.tsx | 46 ++++++++++++++++++++----
3 files changed, 94 insertions(+), 12 deletions(-)
diff --git a/app/[lng]/admin/approval-test/page.tsx b/app/[lng]/admin/approval-test/page.tsx
index de0e2b5a..f044d87d 100644
--- a/app/[lng]/admin/approval-test/page.tsx
+++ b/app/[lng]/admin/approval-test/page.tsx
@@ -3,7 +3,7 @@ import ApprovalManager from '@/components/knox/approval/ApprovalManager';
export const metadata: Metadata = {
title: 'Knox 결재 시스템 테스트 | Admin',
- description: 'Knox API를 사용한 결재 시스템의 모든 기능을 테스트할 수 있는 페이지입니다.',
+ description: 'Knox API를 사용한 결재 시스템 기능 테스트용',
};
export default function ApprovalTestPage() {
@@ -14,9 +14,9 @@ export default function ApprovalTestPage() {
Knox 결재 시스템 테스트
- Knox API를 사용한 결재 시스템의 모든 기능을 테스트할 수 있습니다.
+ Knox API를 사용한 결재 시스템 컴포넌트입니다.
- 테스트 모드가 기본적으로 활성화되어 있으며, 실제 API 대신 가짜 데이터를 사용합니다.
+ 테스트 모드가 기본적으로 활성화되어 있으며, 테스트 모드에서는 실제 API 대신 모킹 데이터를 사용
diff --git a/components/knox/approval/ApprovalDetail.tsx b/components/knox/approval/ApprovalDetail.tsx
index 034bde7d..6db43cbe 100644
--- a/components/knox/approval/ApprovalDetail.tsx
+++ b/components/knox/approval/ApprovalDetail.tsx
@@ -28,6 +28,15 @@ interface ApprovalDetailData {
content: ApprovalContentResponse['data'];
}
+// 첨부파일 타입 (가이드에 명확히 정의되어 있지 않아 필드 일부 추정)
+interface ApprovalAttachment {
+ fileName?: string;
+ fileSize?: string;
+ downloadUrl?: string;
+ fileId?: string;
+ [key: string]: unknown; // 기타 필드 허용
+}
+
export default function ApprovalDetail({
useFakeData = false,
systemId = 'EVCP_SYSTEM',
@@ -126,6 +135,43 @@ export default function ApprovalDetail({
}
};
+ // 첨부파일 다운로드 헬퍼
+ const handleDownload = async (attachment: ApprovalAttachment) => {
+ try {
+ // 1) downloadUrl 이 이미 포함된 경우
+ if (attachment.downloadUrl) {
+ window.open(attachment.downloadUrl, '_blank');
+ return;
+ }
+
+ // 2) fileId + 별도 엔드포인트 조합 (가이드에 명시되지 않았으므로 best-effort 처리)
+ if (attachment.fileId) {
+ const url = `${process.env.KNOX_API_BASE_URL}/approval/api/v2.0/attachments/${attachment.fileId}`;
+ const resp = await fetch(url, {
+ method: 'GET',
+ headers: {
+ 'System-ID': systemId,
+ },
+ });
+ if (!resp.ok) throw new Error('다운로드 실패');
+
+ // blob 생성 후 브라우저 다운로드
+ const blob = await resp.blob();
+ const link = document.createElement('a');
+ link.href = URL.createObjectURL(blob);
+ link.download = attachment.fileName || 'attachment';
+ link.click();
+ URL.revokeObjectURL(link.href);
+ return;
+ }
+
+ toast.error('다운로드 URL 정보를 찾을 수 없습니다.');
+ } catch (err) {
+ console.error('첨부파일 다운로드 오류:', err);
+ toast.error('첨부파일 다운로드 중 오류가 발생했습니다.');
+ }
+ };
+
// 초기 로딩 (initialApInfId가 있는 경우)
useEffect(() => {
if (initialApInfId) {
@@ -338,14 +384,18 @@ export default function ApprovalDetail({