diff --git a/apps/sn/app/(map-layout)/map/components/common/table.ts b/apps/sn/app/(map-layout)/map/components/common/table.ts
index 6818b45e4..6441b99c6 100644
--- a/apps/sn/app/(map-layout)/map/components/common/table.ts
+++ b/apps/sn/app/(map-layout)/map/components/common/table.ts
@@ -478,6 +478,60 @@ export const SwtrmtPrcsZoneExcelCol = {
'swtrmtFcltNm': '하수처리시설명'
};
+// 침수흔적도
+export const FldngWtlvMapCol = [
+ { id: 'fldng_yr', title: '침수년도' },
+ { id: 'fldng_dstr_nm', title: '침수재해명' },
+ { id: 'ctpv_nm', title: '시도명' },
+ { id: 'sgg_nm', title: '시군구명' },
+ { id: 'bgng_ymd', title: '침수시작일자' },
+ { id: 'fldng_bgng_hm', title: '침수시작시분' },
+ { id: 'end_ymd', title: '침수종료일자' },
+ { id: 'fldng_end_hm', title: '침수종료시분' },
+ { id: 'fldng_hr', title: '침수시간' },
+ { id: 'fldng_dstrct_nm', title: '침수지구명' },
+ { id: 'fldng_cs_dtl_cd', title: '침수원인상세코드' },
+ { id: 'avg_fldng_wtlv', title: '평균침수위' },
+ { id: 'fldng_area', title: '침수면적' },
+ { id: 'exmn_yr', title: '조사년도' },
+ { id: 'dam_amt', title: '피해금액' },
+];
+export const FldngWtlvMapCol2 = [
+ { id: 'rowNumber', title: '일련번호' },
+ { id: 'fldngYr', title: '침수년도' },
+ { id: 'fldngDstrNm', title: '침수재해명' },
+ { id: 'ctpvNm', title: '시도' },
+ { id: 'sggNm', title: '시군구' },
+ { id: 'bgngYmd', title: '침수시작일자' },
+ { id: 'fldngBgngHm', title: '침수시작시분' },
+ { id: 'endYmd', title: '침수종료일자' },
+ { id: 'fldngEndHm', title: '침수종료시분' },
+ { id: 'fldngHr', title: '침수시간' },
+ { id: 'fldngDstrctNm', title: '침수지구명' },
+ { id: 'fldngCsDtlCd', title: '침수원인상세코드' },
+ { id: 'avgFldngWtlv', title: '평균침수위' },
+ { id: 'fldngArea', title: '침수면적' },
+ { id: 'exmnYr', title: '조사년도' },
+ { id: 'damAmt', title: '피해금액' },
+];
+export const FldngWtlvMapExcelCol = {
+ 'fldngYr': '침수년도',
+ 'fldngDstrNm': '침수재해명',
+ 'ctpvNm': '시도',
+ 'sggNm': '시군구',
+ 'bgngYmd': '침수시작일자',
+ 'fldngBgngHm': '침수시작시분',
+ 'endYmd': '침수종료일자',
+ 'fldngEndHm': '침수종료시분',
+ 'fldngHr': '침수시간',
+ 'fldngDstrctNm': '침수지구명',
+ 'fldngCsDtlCd': '침수원인상세코드',
+ 'avgFldngWtlv': '평균침수위',
+ 'fldngArea': '침수면적',
+ 'exmnYr': '조사년도',
+ 'damAmt': '피해금액'
+};
+
// 하수맨홀
export const MsSwageMhlCol = [
// { id: 'fid', title: 'FID' },
@@ -819,7 +873,8 @@ export const dateFields = [
'instlYmd', 'lastDrdgnYmd', 'cmcnYmd', 'oprtngStrtYmd', 'clsgYmd',
'mesureBeginDt', 'mesureEndDt', 'qltwtrBeginDt', 'qltwtrEndDt',
'rainBeginDt', 'rainEndDt',
- 'flfmtBgngYmd', 'flfmtEndYmd', 'flfmtYr'
+ 'flfmtBgngYmd', 'flfmtEndYmd', 'flfmtYr',
+ 'bgng_ymd', 'end_ymd', 'bgngYmd', 'endYmd'
];
// 🎯 연월 필드들 (yyyymm -> yyyy년 m월)
@@ -848,5 +903,7 @@ export const numberFields = [
'precdngDry', 'rainFall', 'cntncTime', 'rainIn',
'mesureIntrvl', 'qltwtrCo', 'rnysnFvlc', 'clarFvlc',
'bizAmt', 'count',
- 'chmbr_xcnts', 'chmbr_ydnts'
+ 'chmbr_xcnts', 'chmbr_ydnts',
+ 'fldng_hr', 'avg_fldng_wtlv', 'fldng_area', 'dam_amt',
+ 'fldngHr', 'avgFldngWtlv', 'fldngArea', 'damAmt'
];
diff --git a/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts b/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts
index 94da67e29..4743f83a0 100644
--- a/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts
+++ b/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts
@@ -4,7 +4,8 @@ import type { UiHeadProps, UiTableSort } from "@common/business_components/ui";
export const FLOOD_HISTORY_POPUP_KEY = "fldngHstryPopup";
export const FLDNG_HSTRY_ROW_SELECT_MESSAGE = "SN_FLOOD_HISTORY_ROW_SELECT";
-export const FLOOD_HISTORY_LAYER_TYPE = "tb_sn_flood_trace_mock";
+export const FLOOD_HISTORY_LAYER_TYPE = "tb_ms_fldng_wtlv_map";
+export const FLOOD_HISTORY_PREVIEW_LAYER_TYPE = "tb_sn_flood_trace_mock";
export const FLOOD_HISTORY_LAYER_NAME = "침수흔적도";
export const FLOOD_HISTORY_AREA_LAYER_ID = "SN_FLOOD_HISTORY_AREA";
export const FLOOD_HISTORY_DEPTH_LAYER_ID = "SN_FLOOD_HISTORY_DEPTH";
@@ -442,7 +443,9 @@ const resolveFldngHstryLayerType = (node: any) =>
export const isFldngHstryNode = (node: any) => {
const name = resolveFldngHstryNodeName(node);
const layerType = resolveFldngHstryLayerType(node);
- return name === FLOOD_HISTORY_LAYER_NAME || layerType === FLOOD_HISTORY_LAYER_TYPE;
+ return name === FLOOD_HISTORY_LAYER_NAME
+ || layerType === FLOOD_HISTORY_LAYER_TYPE
+ || layerType === FLOOD_HISTORY_PREVIEW_LAYER_TYPE;
};
export const isFloodHistoryNode = isFldngHstryNode;
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 202f4e338..3a75126fa 100644
--- a/apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx
+++ b/apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx
@@ -32,7 +32,7 @@ import Fill from "ol/style/Fill.js";
import Stroke from "ol/style/Stroke.js";
import CircleStyle from "ol/style/Circle.js";
import { getLayerContentComponent } from "../common";
-import { SwtrmtFcltCol, SwtrmtFcltCol2, SwtrmtPrcsZoneCol, SwtrmtPrcsZoneCol2, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, MsSwagePplCol2, ExclnSewagePumpCol, ExclnSewagePumpCol2, DrtwSewagePumpCol, DrtwSewagePumpCol2, MsSwageMhlCol, MsSwageMhlCol2, stofcbrCol, stofcbrCol2, MS_SWAGE_MHL_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from "../common/table";
+import { FldngWtlvMapCol, FldngWtlvMapCol2, SwtrmtFcltCol, SwtrmtFcltCol2, SwtrmtPrcsZoneCol, SwtrmtPrcsZoneCol2, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, MsSwagePplCol2, ExclnSewagePumpCol, ExclnSewagePumpCol2, DrtwSewagePumpCol, DrtwSewagePumpCol2, MsSwageMhlCol, MsSwageMhlCol2, stofcbrCol, stofcbrCol2, MS_SWAGE_MHL_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from "../common/table";
import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue';
import { codeMapper } from "../common/codeMapper";
import LoadingOverlay from '@/components/ui/LoadingBar';
@@ -61,6 +61,12 @@ const linkedFacilityHighlightStyle = new Style({
zIndex: 9999,
});
+const normalizeFldngWtlvMapDisplayId = (value: unknown) => {
+ const normalized = String(value ?? "").trim();
+ const prefix = "tb_ms_fldng_wtlv_map.";
+ return normalized.startsWith(prefix) ? normalized.slice(prefix.length) : normalized;
+};
+
type MngInstOption = {
mngInstCd: string;
lwrInstNm: string;
@@ -318,6 +324,12 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
setLayerSpecificNm(featureData.values_.swtrmt_fclt_cd);
break;
}
+ case 'tb_ms_fldng_wtlv_map': {
+ result = '침수흔적도';
+ setHeadlist(FldngWtlvMapCol);
+ setLayerSpecificNm(normalizeFldngWtlvMapDisplayId(featureData.values_.fid ?? featureId));
+ break;
+ }
case 'tb_ms_stofcbr': {
result = '우수토실';
setHeadlist(stofcbrCol);
@@ -381,6 +393,12 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
setLayerSpecificNm(featureData.swtrmtFcltCd);
break;
}
+ case 'tb_ms_fldng_wtlv_map': {
+ result = '침수흔적도';
+ setHeadlist(FldngWtlvMapCol2);
+ setLayerSpecificNm(normalizeFldngWtlvMapDisplayId(featureData.fid));
+ break;
+ }
case 'tb_ms_stofcbr': {
result = '우수토실';
setHeadlist(stofcbrCol2)
@@ -478,6 +496,9 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
case '하수처리구역':
setButtonChk(false)
break;
+ case '침수흔적도':
+ setButtonChk(false)
+ break;
case '우수토실':
setButtonChk(true)
setIsMainSsc(false)
diff --git a/apps/sn/app/(map-layout)/map/page.tsx b/apps/sn/app/(map-layout)/map/page.tsx
index 83e99f778..d1fd26184 100644
--- a/apps/sn/app/(map-layout)/map/page.tsx
+++ b/apps/sn/app/(map-layout)/map/page.tsx
@@ -113,6 +113,7 @@ import {
import {
FLOOD_HISTORY_AREA_LAYER_ID,
FLOOD_HISTORY_DEPTH_LAYER_ID,
+ FLOOD_HISTORY_PREVIEW_LAYER_TYPE,
FLOOD_HISTORY_LAYER_TYPE,
FLOOD_HISTORY_POPUP_KEY,
FLDNG_HSTRY_ROW_SELECT_MESSAGE,
@@ -141,6 +142,7 @@ const AnalysisPopupMenu = dynamic(
const AGED_PIPE_CONTROL_NODE_ID = "SN_AGED_PIPE";
const AGED_PIPE_HIGHLIGHT_LAYER_ID = "SN_AGED_PIPE_HIGHLIGHT";
+const FLDNG_HSTRY_WFS_LAYER_ID = "SN_FLDNG_HSTRY_WFS";
const AGED_PIPE_ROW_SELECT_MESSAGE = "SN_AGED_PIPE_ROW_SELECT";
const AGED_PIPE_POPUP_MINIMIZE_MESSAGE = "SN_AGED_PIPE_POPUP_MINIMIZE";
const AGED_PIPE_FILTER_SYNC_MESSAGE = "SN_AGED_PIPE_FILTER_SYNC";
@@ -911,12 +913,14 @@ const getRightPanelFeatureTitle = (data: any) => {
return "펌프장";
case "tb_ms_stofcbr":
return "우수토실";
- case "tb_il_swage_prcs_fclt":
- return "처리시설";
- case "tb_ms_swage_prcs_zone":
- return "처리구역";
- case "om_dt_untrt_swg_rain":
- return "중점우수";
+ case "tb_il_swage_prcs_fclt":
+ return "처리시설";
+ case "tb_ms_swage_prcs_zone":
+ return "처리구역";
+ case "tb_ms_fldng_wtlv_map":
+ return "침수흔적도";
+ case "om_dt_untrt_swg_rain":
+ return "중점우수";
default:
return String(data?.lyrNm ?? data?.values_?.lyrNm ?? "상세").trim() || "상세";
}
@@ -4300,7 +4304,7 @@ const Map = () => {
});
layer.set("id", FLOOD_HISTORY_AREA_LAYER_ID);
layer.set("lyrNm", "침수흔적도");
- layer.set("lyrTyNm", FLOOD_HISTORY_LAYER_TYPE);
+ layer.set("lyrTyNm", FLOOD_HISTORY_PREVIEW_LAYER_TYPE);
layer.set("clickPsblYn", "N");
gisMaps.current.addLayer(layer);
fldngHstryAreaLayerRef.current = layer;
@@ -4320,7 +4324,7 @@ const Map = () => {
});
layer.set("id", FLOOD_HISTORY_DEPTH_LAYER_ID);
layer.set("lyrNm", "침수흔적도");
- layer.set("lyrTyNm", FLOOD_HISTORY_LAYER_TYPE);
+ layer.set("lyrTyNm", FLOOD_HISTORY_PREVIEW_LAYER_TYPE);
layer.set("clickPsblYn", "N");
gisMaps.current.addLayer(layer);
fldngHstryDepthLayerRef.current = layer;
@@ -5409,6 +5413,43 @@ const Map = () => {
};
}, [appliedAgedPipeFilters, isAgedPipeChecked, mapReady]);
+ useEffect(() => {
+ if (!mapReady || !gisMaps.current) return;
+
+ const core = GisApp.Module.core as any;
+ core?.deleteLayer?.(FLDNG_HSTRY_WFS_LAYER_ID);
+
+ if (!isFldngHstryChecked) return;
+
+ const baseLayerCode = Object.values(GisApp.layerCode ?? {}).find(
+ (item: any) => item?.lyrTyNm === FLOOD_HISTORY_LAYER_TYPE && item?.actlLyrYn === "Y",
+ ) as any;
+
+ if (!baseLayerCode) return;
+
+ const layerCode = {
+ ...baseLayerCode,
+ id: FLDNG_HSTRY_WFS_LAYER_ID,
+ lyrSn: FLDNG_HSTRY_WFS_LAYER_ID,
+ lyrNm: "침수흔적도",
+ lyrTyNm: FLOOD_HISTORY_LAYER_TYPE,
+ actlLyrYn: "Y",
+ exprsYn: "Y",
+ clickPsblYn: "Y",
+ cmncNm: "bbox",
+ srvcNm: "wfs",
+ };
+
+ const layer = core?.addWfsLayer?.(layerCode);
+ layer?.set?.("id", FLDNG_HSTRY_WFS_LAYER_ID);
+ layer?.set?.("lyrNm", "침수흔적도");
+ layer?.set?.("lyrTyNm", FLOOD_HISTORY_LAYER_TYPE);
+
+ return () => {
+ core?.deleteLayer?.(FLDNG_HSTRY_WFS_LAYER_ID);
+ };
+ }, [isFldngHstryChecked, mapReady]);
+
const openAnalysisPopup = useCallback((popupKey: WindowPopupKey) => {
const popup = openWindowPopup(popupKey);
if (!popup) {
diff --git a/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx b/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx
index 631ba12fb..f15cce8b0 100644
--- a/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx
+++ b/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx
@@ -14,6 +14,7 @@ import { Label } from '@common/components';
import SwagePpl from './swagePpl';
import SwagePrcsFclt from './swagePrcsFclt';
import SwagePrcsZone from './swagePrcsZone';
+import FldngWtlvMap from './fldngWtlvMap';
import SwageMhl from './swageMhl';
import SwagePmstn from './swagePmstn';
import Stofcbr from './stofcbr';
@@ -25,6 +26,7 @@ export const BASIC_TYPES = [
{ val: "tb_ms_swage_ppl", text: "하수관로" },
{ val: "tb_il_swage_prcs_fclt", text: "하수처리시설" },
{ val: "tb_ms_swage_prcs_zone", text: "하수처리구역" },
+ { val: "tb_ms_fldng_wtlv_map", text: "침수흔적도" },
{ val: "tb_ms_swage_mhl", text: "하수맨홀" },
{ val: "tb_ms_swage_pmstn", text: "하수펌프장" },
{ val: "tb_ms_stofcbr", text: "우수토실" },
@@ -56,6 +58,7 @@ const BasicTab: React.FC = () => {
{basicType === "tb_ms_swage_ppl" && (