diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx index 4d6cf3532..d22d72828 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx @@ -177,6 +177,9 @@ const FeatureClickEventPopup = ({ const [chmbrYdnts, setChmbrYdnts] = useState(""); // 로딩 상태 const linkedFacilityFeatureRef = useRef(null); const linkedFacilityOriginalStyleRef = useRef(null); + const flowDirectionBasisRequestCacheRef = useRef( + new Map>(), + ); const [mngInstOptions, setMngInstOptions] = useState([]); const { ctpv, sgg, fetchCtpv, fetchSgg } = useStore(); @@ -637,6 +640,7 @@ const FeatureClickEventPopup = ({ formattedData.instlYmd = "확인불가"; } } + let mergedDetailData = formattedData; setFetchData(formattedData); setTableData(formattedData); @@ -742,11 +746,11 @@ const FeatureClickEventPopup = ({ const result = await getData(apiEndpoint); if (result) { - const mergedData = mergeDetailData(formattedData, result); + mergedDetailData = mergeDetailData(mergedDetailData, result); const processedApiData = withMngInstName( codeMapper({ layerName: selectedLayerName, - data: mergedData, + data: mergedDetailData, }), ); @@ -759,6 +763,61 @@ const FeatureClickEventPopup = ({ } } + if (selectedLayerName === "하수관로" && canRequestDetail) { + try { + const escapeCqlLiteral = (value: string) => + value.replace(/'/g, "''"); + const requestCacheKey = `${fcltMngNo}::${mngInstCd}`; + const params = new URLSearchParams({ + lyrTypeNm: "tb_ms_swage_ppl", + includeFlowDirectionBasis: "true", + cqlFiter: + `fclt_mng_no='${escapeCqlLiteral(fcltMngNo)}' and ` + + `mng_inst_cd='${escapeCqlLiteral(mngInstCd)}'`, + page: "0", + size: "1", + }); + let flowDirectionRequest = + flowDirectionBasisRequestCacheRef.current.get(requestCacheKey); + if (!flowDirectionRequest) { + flowDirectionRequest = getData(`v1/fclts?${params.toString()}`) + .then((response) => + Array.isArray(response?.data) ? response.data[0] : null, + ) + .catch((error) => { + flowDirectionBasisRequestCacheRef.current.delete( + requestCacheKey, + ); + throw error; + }); + flowDirectionBasisRequestCacheRef.current.set( + requestCacheKey, + flowDirectionRequest, + ); + } + const enrichedPipe = await flowDirectionRequest; + if (enrichedPipe) { + mergedDetailData = mergeDetailData( + mergedDetailData, + enrichedPipe, + ); + const processedPipeData = withMngInstName( + codeMapper({ + layerName: selectedLayerName, + data: mergedDetailData, + }), + ); + setFetchData(processedPipeData); + setTableData(processedPipeData); + } + } catch (flowDirectionError) { + console.warn( + "관로 유하방향 근거 조회 실패, 기존 상세정보를 유지합니다.", + flowDirectionError, + ); + } + } + if (selectedLayerName === "침수흔적도" && featureId) { try { const normalizedFloodMapFid = diff --git a/apps/sn/app/(map-layout)/map/page.tsx b/apps/sn/app/(map-layout)/map/page.tsx index 002da74ed..6d84a83da 100644 --- a/apps/sn/app/(map-layout)/map/page.tsx +++ b/apps/sn/app/(map-layout)/map/page.tsx @@ -5991,7 +5991,7 @@ const Map = () => { ); const handlePipeAnalysisRowSelect = useCallback( - async (row: Pick) => { + async (row: PipeAnalysisDetailRow) => { // 관로현황 팝업에서 선택한 경우 메시지를 받은 최상위 지도창을 먼저 앞으로 가져온다. window.focus(); try { diff --git a/apps/sn/docs/작업검증/SFR-011-002-관로분석/001-qa-SFR-011-002-관로분석-통합검증결과.md b/apps/sn/docs/작업검증/SFR-011-002-관로분석/001-qa-SFR-011-002-관로분석-통합검증결과.md index 31d82cf8b..d70d513a3 100644 --- a/apps/sn/docs/작업검증/SFR-011-002-관로분석/001-qa-SFR-011-002-관로분석-통합검증결과.md +++ b/apps/sn/docs/작업검증/SFR-011-002-관로분석/001-qa-SFR-011-002-관로분석-통합검증결과.md @@ -63,3 +63,23 @@ - 최종 구현은 상세창·중간창 `blur()`와 이름 기반 지도창 `focus()`, 지도창 메시지 처리 전후 self-focus를 함께 적용했다. - 자동화 제어는 창 전환 순간 기존 상세창 제어가 종료되어 OS 전경창 최종 상태의 재확인이 제한됐다. 실제 사용자 클릭 기준 수동 포커스 확인은 남은 검증 항목이다. - SN 전체 TypeScript와 `git diff --check` 통과. `map/page.tsx` 전체 Prettier는 기존 파일의 선행 포맷 차이로 통과하지 않았고 이번 추가 구문은 기존 스타일에 맞췄다. + +## 11. 2026-08-26 관로 상세 유하방향 근거 검증 + +- 수정 전 Chrome 지도 상세에서 관로 `118529`의 유하방향 근거가 `-`로 표출되는 것을 확인했다. +- 같은 관로의 유하방향 포함 API 응답은 `flowDirectionBasis=GIS 작도순서`, `flowDirectionBasisCode=GEOMETRY_FALLBACK`, `flowDirectionRuleLabel=geometry 시점->종점 fallback`을 반환했다. +- 관로현황 행과 보강 API 응답의 병합 결과에 위 세 필드가 유지되는 것을 확인했다. +- `map/page.tsx` 변경 구문 TypeScript 파서와 `git diff --check`는 통과했다. +- SN 전체 TypeScript는 동시 변경된 기존 `event.source.postMessage` 타입 오류 1건으로 차단됐으며 이번 유하방향 보강 코드의 추가 오류는 없었다. +- Chrome 입력 제어가 관로행 클릭 단계에서 시간 초과되어 수정 후 최종 화면 표출은 사용자 수동 확인 항목으로 남긴다. + +## 12. 2026-08-28 하수관로 상세 공통 보강 재검증 + +- 재현 관로: 시설관리번호 `2015303665`, 관리기관코드 `5690000`, FID `tb_ms_swage_ppl.1135978`. +- 실 API 응답: `flowDirectionBasis=시종점 관저고`, `flowDirectionBasisCode=DEPTH`, `flowDirectionRuleLabel=맨홀 표고-관로 깊이 관저고 높은 쪽->낮은 쪽`, 조회건수 1건. +- 로컬 브라우저에서 같은 관로를 지도 상세 흐름으로 열어 우측 기본정보의 `유하방향 근거`가 `시종점 관저고`로 표시되는 것을 확인했다. +- 검증 화면: `COMMON_DOCS_ROOT/작업내용/SFR-012-005-하수관로유하방향표출/검증/20260828-관로-2015303665-유하방향근거.png`. +- 변경 컴포넌트 Prettier와 TypeScript 구문검사, `git diff --check` 통과. +- SN 전체 TypeScript는 기존 `map/page.tsx:3659`의 `postMessage` 타입 오류 1건만 남았고 이번 공통 보강 코드의 추가 오류는 없다. +- ESLint는 설치 상태에서 `eslint-plugin-react-hooks`를 찾지 못해 실행 환경 오류로 완료하지 못했다. +- 판정: PASS. diff --git a/apps/sn/docs/작업내용/SFR-011-002-관로분석/001-fe-SFR-011-002-관로분석-통합구현기록.md b/apps/sn/docs/작업내용/SFR-011-002-관로분석/001-fe-SFR-011-002-관로분석-통합구현기록.md index f4351bf67..5f8f934fb 100644 --- a/apps/sn/docs/작업내용/SFR-011-002-관로분석/001-fe-SFR-011-002-관로분석-통합구현기록.md +++ b/apps/sn/docs/작업내용/SFR-011-002-관로분석/001-fe-SFR-011-002-관로분석-통합구현기록.md @@ -67,3 +67,20 @@ - 상세창과 중간 관로분석창을 `blur()`한 뒤 지도창을 활성화해 중간 팝업에 포커스가 머무는 경우를 방지한다. - 최상위 지도창도 메시지 처리 시작과 지도 이동·상세 패널 렌더링 완료 시점에 각각 `window.focus()`를 요청한다. - 기존 관로 지도 이동, 강조와 우측 상세정보 표출은 그대로 유지한다. + +## 11. 2026-08-26 관로현황 선택 관로 유하방향 근거 보강 + +- 관로현황 상세 API 행에는 `flowDirectionBasis`가 없어 지도 상세 패널을 행 데이터로 갱신하면 유하방향 근거가 `-`로 표출됐다. +- 관로행 클릭 시 시설관리번호와 관리기관코드로 `v1/fclts` 한 건을 `includeFlowDirectionBasis=true` 조건으로 조회한다. +- 조회 결과를 기존 관로현황 행에 병합한 뒤 지도 상세 패널에 전달한다. +- 보강 API가 실패하면 지도 이동과 기존 행 상세는 유지하고 경고 로그만 남긴다. +- 하수관로 유하방향 레이어 계산과 DB 구조는 변경하지 않는다. + +## 12. 2026-08-28 하수관로 상세 공통 유하방향 근거 보강 + +- 사용자 재확인에서 관로분석 행 선택 외의 지도 피처 클릭 경로는 여전히 `유하방향 근거`가 `-`로 표시되는 것을 확인했다. +- 관로분석 메시지 처리 함수에 두었던 한정 보강을 제거하고 `FeatureClickEventPopup`의 하수관로 상세 공통 로딩 흐름으로 이동했다. +- 지도 피처 클릭, 정보검색/관로현황 연계 등 진입 경로와 관계없이 시설관리번호·관리기관코드가 유효하면 `v1/fclts?includeFlowDirectionBasis=true` 한 건을 조회한다. +- 기존 피처 정보와 자체입력정보를 먼저 병합한 뒤 유하방향 응답을 최종 병합해 기존 상세 필드를 잃지 않도록 했다. +- 대상 관로 `2015303665`의 화면 표출값은 `시종점 관저고`이며, 계산코드는 `DEPTH`이다. +- 수정 파일은 `app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx`이며, `map/page.tsx`는 관로 선택 행을 그대로 상세 컴포넌트에 전달한다.