From 1e8c0659e550c91f454a864a258288e29c55acbd Mon Sep 17 00:00:00 2001 From: htlee Date: Wed, 18 Mar 2026 09:34:51 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20S&P=20Global=20=EC=82=AC=EC=A7=84=20?= =?UTF-8?q?URL=20=EB=AA=A9=EB=A1=9D=20API=20=EC=97=B0=EB=8F=99=20+=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20DEMO=20=ED=91=9C=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ShipLayer: IMO 기반 /signal-batch/api/v1/shipimg/{imo} API로 실제 이미지 목록 조회 - 각 이미지 path + _2.jpg(원본) 사용 (기존 잘못된 _1→_2→_3 번호 패턴 제거) - IMO별 이미지 목록 캐시(spgImageCache) 적용 - LoginPage: KCG 로고 우측 하단에 DEMO 문구 오버레이 Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/components/auth/LoginPage.tsx | 17 ++++- frontend/src/components/layers/ShipLayer.tsx | 65 ++++++++++++-------- 2 files changed, 56 insertions(+), 26 deletions(-) diff --git a/frontend/src/components/auth/LoginPage.tsx b/frontend/src/components/auth/LoginPage.tsx index 9742506..0703a47 100644 --- a/frontend/src/components/auth/LoginPage.tsx +++ b/frontend/src/components/auth/LoginPage.tsx @@ -104,7 +104,22 @@ const LoginPage = ({ onGoogleLogin, onDevLogin }: LoginPageProps) => { > {/* Title */}
- KCG +
+ KCG + + DEMO + +

(); + +async function fetchSpgImages(imo: string): Promise { + if (spgImageCache.has(imo)) return spgImageCache.get(imo) || []; + try { + const res = await fetch(`/signal-batch/api/v1/shipimg/${imo}`); + if (!res.ok) throw new Error(`${res.status}`); + const data: SpgImageInfo[] = await res.json(); + spgImageCache.set(imo, data); + return data; + } catch { + spgImageCache.set(imo, null); + return []; + } +} + +function VesselPhoto({ mmsi, imo, shipImagePath }: VesselPhotoProps) { const localUrl = LOCAL_SHIP_PHOTOS[mmsi]; const hasSPGlobal = !!shipImagePath; - // 항상 S&P Global 우선 (모달 열릴 때마다 리셋) const [activeTab, setActiveTab] = useState(hasSPGlobal ? 'spglobal' : 'marinetraffic'); const [spgSlideIdx, setSpgSlideIdx] = useState(0); const [spgErrors, setSpgErrors] = useState>(new Set()); + const [spgImages, setSpgImages] = useState([]); - // 모달이 다른 선박으로 변경될 때 탭/슬라이드 리셋 + // 모달이 다른 선박으로 변경될 때 리셋 + 이미지 목록 조회 useEffect(() => { setActiveTab(hasSPGlobal ? 'spglobal' : 'marinetraffic'); setSpgSlideIdx(0); setSpgErrors(new Set()); - }, [mmsi, hasSPGlobal]); + setSpgImages([]); - // S&P Global slide URLs + if (imo && hasSPGlobal) { + fetchSpgImages(imo).then(setSpgImages); + } else if (shipImagePath) { + // IMO 없으면 shipImagePath 단일 이미지 사용 + setSpgImages([{ picId: 0, path: shipImagePath.replace(/_[12]\.\w+$/, ''), copyright: '', date: '' }]); + } + }, [mmsi, imo, hasSPGlobal, shipImagePath]); + + // S&P Global slide URLs: 각 이미지의 path + _2.jpg (원본) const spgUrls = useMemo( - () => shipImagePath ? buildSpgUrls(shipImagePath, shipImageCount ?? 1) : [], - [shipImagePath, shipImageCount], + () => spgImages.map(img => `${img.path}_2.jpg`), + [spgImages], ); const validSpgCount = spgUrls.length; @@ -188,7 +204,6 @@ function VesselPhoto({ mmsi, shipImagePath, shipImageCount }: VesselPhotoProps) }); useEffect(() => { - // 새 선박이면 캐시 확인 setMtPhoto(vesselPhotoCache.has(mmsi) ? vesselPhotoCache.get(mmsi) : undefined); }, [mmsi]); From 0deb55b44a9f0b2aa18f19d205830b582913104a Mon Sep 17 00:00:00 2001 From: htlee Date: Wed, 18 Mar 2026 09:35:15 +0900 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=EB=A6=B4=EB=A6=AC=EC=A6=88=20?= =?UTF-8?q?=EB=85=B8=ED=8A=B8=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/RELEASE-NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/RELEASE-NOTES.md b/docs/RELEASE-NOTES.md index 96d4f84..1362318 100644 --- a/docs/RELEASE-NOTES.md +++ b/docs/RELEASE-NOTES.md @@ -23,6 +23,10 @@ ### 수정 - 센서 API(/api/sensor/*) 인증 예외 처리 (공개 데이터) - 선박 모달 열 때마다 S&P Global 우선 탭 리셋 (MarineTraffic 포커스 유지 버그) +- S&P Global 사진 URL: IMO 기반 이미지 목록 API 연동 (잘못된 번호 패턴 제거) + +### 기타 +- 로그인 화면 KCG 로고에 DEMO 문구 오버레이 ## [2026-03-18.2]