통수위험 행 선택 시 초단기예보격자망 자동 활성화
This commit is contained in:
@@ -256,6 +256,7 @@ const GIS_EDIT_VERTEX_LAYER_ID = "SN_GIS_EDIT_VERTEX_HANDLES";
|
||||
const WATER_RISK_AREA_LAYER_ID = "SN_WATER_RISK_AREA";
|
||||
const WATER_RISK_PIPE_LAYER_ID = "SN_WATER_RISK_PIPE";
|
||||
const WATER_RISK_MANHOLE_LAYER_ID = "SN_WATER_RISK_MANHOLE";
|
||||
const SHORT_TERM_FORECAST_GRID_LAYER_NAME = "초단기예보격자망";
|
||||
const FLOOD_HISTORY_SELECTION_PADDING: [number, number, number, number] = [
|
||||
100, 380, 120, 120,
|
||||
];
|
||||
@@ -2981,6 +2982,11 @@ const Map = () => {
|
||||
const sinkholeScope = useMemo(() => buildSinkholeScope(userInfo), [userInfo]);
|
||||
|
||||
const [treeData, setTreeData] = useState<any[]>([]); // 초기값을 객체 또는 null로 설정
|
||||
// 통수위험 결과 행을 선택할 때 기존 체크를 유지하면서 강우 격자 레이어를 켜기 위한 요청이다.
|
||||
const [checkedLayerRequest, setCheckedLayerRequest] = useState<{
|
||||
requestKey: number;
|
||||
layerNames: string[];
|
||||
} | null>(null);
|
||||
const [layerLoadError, setLayerLoadError] = useState<string | null>(null);
|
||||
const gisMaps = useRef<any | null>(null);
|
||||
const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태
|
||||
@@ -4181,6 +4187,10 @@ const Map = () => {
|
||||
...current,
|
||||
selectedAreaId: areaId,
|
||||
}));
|
||||
setCheckedLayerRequest((current) => ({
|
||||
requestKey: (current?.requestKey ?? 0) + 1,
|
||||
layerNames: [SHORT_TERM_FORECAST_GRID_LAYER_NAME],
|
||||
}));
|
||||
setIsOpen(false);
|
||||
setFeatureData(null);
|
||||
return;
|
||||
@@ -9019,6 +9029,7 @@ const Map = () => {
|
||||
/>
|
||||
<Gis
|
||||
treeData={treeData}
|
||||
checkedLayerRequest={checkedLayerRequest}
|
||||
isSearch={true}
|
||||
gisMaps={gisMaps}
|
||||
isMiniMap={false}
|
||||
|
||||
@@ -197,3 +197,18 @@
|
||||
|
||||
- 정렬 파라미터가 없는 기본 요청도 백엔드 `RAIN_BGNG_DT DESC`에 따라 2026-08-26 07:00, 2026-08-25 13:00, 10:00, 06:00 순으로 반환된다.
|
||||
- 2026-08-25 경기 가평 지역 2건은 기존 키가 1개로 충돌했지만 강우시작시간·분석기준시간을 포함한 신규 키는 2개 모두 고유하다.
|
||||
|
||||
## 15. 2026-08-31 초단기예보격자망 자동 활성화 검증
|
||||
|
||||
| 검증 항목 | 결과 | 비고 |
|
||||
|---|---|---|
|
||||
| 통수위험 선택 메시지 연계 | 정적 통과 | 유효한 결과행·mapView 수신 후 체크 요청 생성 |
|
||||
| 기존 체크 상태 보존 | 정적 통과 | 요청 레이어를 기존 배열에 추가하는 방식 |
|
||||
| 동일 기능 재실행 | 정적 통과 | 행 선택마다 `requestKey` 증가 |
|
||||
| 트리 가시성 | 정적 통과 | 대상 노드와 `강우관련` 조상 그룹 펼침 |
|
||||
| 실제 레이어 ON | 정적 통과 | 공통 `checkSpecificNode`의 지도 반영 경로 재사용 |
|
||||
| 공통 지도 패키지 빌드 | 통과 | `pnpm --filter @common/business_components run build` |
|
||||
| `sn` TypeScript 검사 | 통과 | `tsc --noEmit --incremental false`, `ignoreDeprecations=5.0` 명령줄 보정 |
|
||||
| 브라우저 수동 검증 | 대기 | 실제 결과 행 클릭 후 격자망 체크·WFS 표출 확인 필요 |
|
||||
|
||||
- Prettier 실행 파일은 현재 workspace에 설치되어 있지 않아 별도 포맷 검사는 수행하지 못했다.
|
||||
|
||||
@@ -208,3 +208,11 @@
|
||||
|
||||
- 요구사항정의서 93행은 합리식 `Q=CIA`와 Manning 공식을 요구하지만, 화면설계서 20쪽은 SWMM5 연계를 제시한다. 실제 산정 기능 설계 전에 적용 기준을 확정해야 한다.
|
||||
- 2026-08-04 실제 API 연동 시 `map/page.tsx`, 세션 타입, popup 메시지 타입에 남아 있던 설정 편집·staged 관로 호환 코드도 제거해 결과 조회와 지도보기 계약만 유지했다. 상세 구현·검증은 `002-fe-SFR-011-007-통수위험분석-실API연동및검증.md`를 따른다.
|
||||
|
||||
## 14. 2026-08-31 행 선택 시 초단기예보격자망 자동 활성화
|
||||
|
||||
- 원본 추적 근거는 요구사항정의서 `SFR-011-007` 93행과 화면설계서 21쪽 `SN_MN010202`의 결과 행 선택 후 GIS 위치 이동 흐름이다.
|
||||
- 사용자의 최신 지시에 따라 현재·과거분석이력 결과 행 선택으로 지도 결과를 표시할 때 시설물 레이어의 `강우관련 > 초단기예보격자망`을 자동으로 ON 한다.
|
||||
- 기존 사용자가 켜둔 다른 시설물 레이어는 유지하고 초단기예보격자망만 추가 체크한다.
|
||||
- 사용자가 격자망을 다시 끈 뒤 다른 결과 행을 선택해도 새 요청으로 다시 ON 한다.
|
||||
- 백엔드 API·DB·통수위험 mapView 응답은 변경하지 않는다.
|
||||
|
||||
@@ -251,3 +251,12 @@
|
||||
- 팝업 최초 조회와 현재·과거 탭 전환 시 정렬 파라미터를 비워 백엔드 기본 강우시작시간 최신순을 적용한다.
|
||||
- 사용자가 다른 정렬 열을 선택하면 기존 서버 정렬을 유지하고, 탭을 전환하면 다시 강우시작시간 최신순으로 돌아간다.
|
||||
- 동일 날짜·지역에 여러 강우이벤트가 존재해도 React 행 키가 겹치지 않도록 분석일·강우시작시간·분석기준시간·행정코드·지역번호를 조합한다.
|
||||
|
||||
## 18. 2026-08-31 통수위험 행 선택과 초단기예보격자망 연계
|
||||
|
||||
- 부모 지도에서 `WATER_RISK_SELECT_RESULT` 메시지를 정상 검증한 뒤 통수위험 결과·mapView 상태와 함께 초단기예보격자망 체크 요청을 생성한다.
|
||||
- 공통 `Gis`에 `checkedLayerRequest`를 추가하고 `GisTree`가 레이어명을 기준으로 기존 체크 상태에 대상 노드를 합치는 방식으로 구현했다.
|
||||
- 대상 노드와 조상인 `강우관련` 그룹을 펼쳐 자동 체크 결과를 사용자가 트리에서 바로 확인할 수 있게 했다.
|
||||
- 요청마다 `requestKey`를 증가시켜 사용자가 격자망을 수동 해제한 후 다른 통수위험 행을 선택해도 다시 활성화한다.
|
||||
- 지도 체크박스 DOM을 직접 조작하지 않고 기존 `checkSpecificNode` 경로를 사용해 실제 WFS 레이어와 체크 상태, `onCheckedLayersChange` 콜백을 함께 갱신한다.
|
||||
- 공통 기능은 요청이 없는 기존 `Gis` 사용 화면에서 동작하지 않으므로 타 화면의 기본 체크 계약은 유지된다.
|
||||
|
||||
@@ -54,6 +54,8 @@ function Gis({
|
||||
sinkholeLegendIconVisible = false,
|
||||
setIsSearchModalOpen,
|
||||
onCheckedLayersChange,
|
||||
// 외부 업무 흐름에서 특정 시설물 레이어를 기존 체크 상태에 추가하도록 요청한다.
|
||||
checkedLayerRequest = null,
|
||||
searchBar: SearchBar,
|
||||
waterDepth: WaterDepth = null,
|
||||
layerSettingView: LayerSettingView = null,
|
||||
@@ -309,6 +311,7 @@ function Gis({
|
||||
visible={tabVisible}
|
||||
setVisible={setTabVisible}
|
||||
onCheckedChange={handleCheckedLayersChange}
|
||||
checkedLayerRequest={checkedLayerRequest}
|
||||
onLayerIconClick={(layerNm, node) => {
|
||||
layerNmRef.current = layerNm;
|
||||
setLayerNm(layerNm);
|
||||
|
||||
@@ -19,6 +19,7 @@ import GisApp from "./lib/gis.core";
|
||||
*
|
||||
* Props 요약
|
||||
* - checkedNodes, setCheckedNodes: (선택) 외부 관리 체크 상태 (현재 내부 state 사용)
|
||||
* - checkedLayerRequest: (선택) 기존 체크 상태를 유지하면서 지정 레이어를 추가로 체크하는 요청
|
||||
* - visible, setVisible: 사이드 패널 가시성 on/off
|
||||
* - onCheckedChange(checkedIds, checkedNodesData): 체크 변경 시 콜백
|
||||
* - onLayerIconClick(nodeNm): 각 노드의 미리보기/아이콘 클릭 시 콜백
|
||||
@@ -37,6 +38,7 @@ import GisApp from "./lib/gis.core";
|
||||
export default React.memo(function GisTree({
|
||||
checkedNodes = [],
|
||||
setCheckedNodes = () => { },
|
||||
checkedLayerRequest = null,
|
||||
visible,
|
||||
setVisible,
|
||||
onCheckedChange,
|
||||
@@ -71,6 +73,8 @@ export default React.memo(function GisTree({
|
||||
const targetNodesRef = useRef([]);
|
||||
const isPausedRef = useRef(false);
|
||||
const timeoutIdRef = useRef(null);
|
||||
// 동일한 외부 체크 요청이 리렌더링마다 반복 적용되지 않도록 마지막 요청 키를 보관한다.
|
||||
const lastCheckedLayerRequestKeyRef = useRef(null);
|
||||
// 체크 후 부모 설정영역까지 다시 렌더되어도 사용자가 보던 트리 위치를 유지한다.
|
||||
const layerPanelScrollRef = useRef(null);
|
||||
const layerPanelScrollTopRef = useRef(0);
|
||||
@@ -322,6 +326,37 @@ export default React.memo(function GisTree({
|
||||
[nodes]
|
||||
);
|
||||
|
||||
/**
|
||||
* 업무 화면이 요청한 레이어를 기존 사용자 체크 상태에 추가하고 조상 그룹을 펼친다.
|
||||
* 레이어명은 공백 차이를 무시하며, 실제 지도 반영과 onCheckedChange는 수동 체크와 같은 경로를 사용한다.
|
||||
*/
|
||||
useEffect(() => {
|
||||
const requestKey = checkedLayerRequest?.requestKey;
|
||||
if (requestKey == null || nodes.length === 0) return;
|
||||
if (lastCheckedLayerRequestKeyRef.current === requestKey) return;
|
||||
|
||||
const normalizeLayerName = (value) => String(value ?? "")
|
||||
.replace(/\s+/g, "")
|
||||
.trim();
|
||||
const requestedLayerNames = new Set(
|
||||
(checkedLayerRequest?.layerNames ?? [])
|
||||
.map(normalizeLayerName)
|
||||
.filter(Boolean)
|
||||
);
|
||||
const targetNodes = nodes.filter((node) => requestedLayerNames.has(
|
||||
normalizeLayerName(node?.data?.lyrNm ?? node?.text)
|
||||
));
|
||||
if (targetNodes.length === 0) return;
|
||||
|
||||
setExpanded((current) => Array.from(new Set([
|
||||
...current,
|
||||
...targetNodes.map((node) => node.id),
|
||||
...targetNodes.flatMap((node) => getAncestors(node.id, nodes)),
|
||||
])));
|
||||
targetNodes.forEach((node) => checkSpecificNode(node.id, true));
|
||||
lastCheckedLayerRequestKeyRef.current = requestKey;
|
||||
}, [checkedLayerRequest, checkSpecificNode, nodes]);
|
||||
|
||||
// =====================
|
||||
// 자동 애니메이션: 지정된 순서/간격으로 노드 체크 상태를 순차 변경
|
||||
// =====================
|
||||
|
||||
Reference in New Issue
Block a user