From 34ba09ce1b694d58e2dc01abe9b9618203887c4b Mon Sep 17 00:00:00 2001 From: mind-one001 Date: Fri, 4 Sep 2026 15:24:17 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EC=A4=80=EC=84=A4=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/DredgingDetailPopupPage.tsx | 87 +++++++++++++++---- .../components/DredgingRegisterModal.tsx | 38 +++++--- .../001-qa-SFR-010-012-준설관리-검증결과.md | 42 +++++++++ .../001-fe-SFR-010-012-준설관리-구현기록.md | 22 +++++ 4 files changed, 159 insertions(+), 30 deletions(-) diff --git a/apps/sn/app/(with-base-layout)/oper/dredging/components/DredgingDetailPopupPage.tsx b/apps/sn/app/(with-base-layout)/oper/dredging/components/DredgingDetailPopupPage.tsx index 5f0909de1..200e9203c 100644 --- a/apps/sn/app/(with-base-layout)/oper/dredging/components/DredgingDetailPopupPage.tsx +++ b/apps/sn/app/(with-base-layout)/oper/dredging/components/DredgingDetailPopupPage.tsx @@ -14,6 +14,7 @@ import { TableRow, } from "@common/components"; import { MS_SWAGE_PPL_CODES } from "@/app/(map-layout)/map/components/common/table"; +import { fileDownload } from "@/components/lib/utils/fileDownload"; import { useAlertStore } from "@/shared/lib"; import { useEffect, useMemo, useRef, useState } from "react"; @@ -119,6 +120,8 @@ const DredgingDetailPopupPage = ({ const [matchError, setMatchError] = useState(null); const [isMatching, setIsMatching] = useState(false); const [isSaving, setIsSaving] = useState(false); + // 원본 다운로드 중 연속 클릭을 막고 선택한 사진의 다운로드 진행 상태를 표시한다. + const [isDownloadingPhoto, setIsDownloadingPhoto] = useState(false); const [statusMessage, setStatusMessage] = useState(""); const uploadedAttachmentsRef = useRef(new Map()); @@ -221,6 +224,31 @@ const DredgingDetailPopupPage = ({ null) : null; + /** 저장된 사진은 공통 첨부 원본을 받고, 아직 저장하지 않은 신규 사진은 로컬 File을 내려받는다. */ + const handlePhotoDownload = async () => { + // 다운로드 중 선택을 바꾸더라도 클릭한 시점의 파일과 파일명을 함께 유지한다. + const existingPhoto = selectedExistingPhoto; + const newPhoto = selectedNewPhoto; + if (isDownloadingPhoto || (!existingPhoto && !newPhoto)) return; + + setIsDownloadingPhoto(true); + try { + if (newPhoto) { + fileDownload(newPhoto.file, newPhoto.file.name); + } else if (existingPhoto) { + const original = await fetchDredgingPhotoBlob(existingPhoto.atflId); + fileDownload( + original, + existingPhoto.originalFileName || `준설사진_${existingPhoto.photoSn}`, + ); + } + } catch { + alert("사진을 다운로드하지 못했습니다. 잠시 후 다시 시도해주세요."); + } finally { + setIsDownloadingPhoto(false); + } + }; + const pipeInfo = [ ["시도", record.ctpv || "확인불가"], ["시군구", record.sgg || "확인불가"], @@ -481,10 +509,10 @@ const DredgingDetailPopupPage = ({ } - bodyClassName="sn-dredging-register block overflow-y-auto" + bodyClassName="sn-dredging-register !overflow-hidden" > -
-