물재이용 지도 하수재이용 오버레이 변경 , 온배수 항목 추가 , 주소 검색 키 변수명 변경

This commit is contained in:
leedj312
2025-09-05 16:39:02 +09:00
parent cbc7c4918f
commit 500a6b1489
9 changed files with 115 additions and 90 deletions
+1 -1
View File
@@ -28,4 +28,4 @@ NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
NEXT_PUBLIC_FINDADRESS_URL=https://business.juso.go.kr/addrlink/addrLinkApi.do NEXT_PUBLIC_FINDADRESS_URL=https://business.juso.go.kr/addrlink/addrLinkApi.do
NEXT_PUBLIC_WR_ADDRESS_KEY = devU01TX0FVVEgyMDI1MDgyNTEwMzkwNDExNjEwNTM= NEXT_PRIVATE_WR_ADDRESS_KEY = devU01TX0FVVEgyMDI1MDgyNTEwMzkwNDExNjEwNTM=
+1 -1
View File
@@ -19,7 +19,7 @@ NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_
NEXT_PUBLIC_FINDADRESS_URL=https://business.juso.go.kr/addrlink/addrLinkApi.do NEXT_PUBLIC_FINDADRESS_URL=https://business.juso.go.kr/addrlink/addrLinkApi.do
NEXT_PUBLIC_WR_ADDRESS_KEY = devU01TX0FVVEgyMDI1MDgyNTEwMzkwNDExNjEwNTM= NEXT_PRIVATE_WR_ADDRESS_KEY = devU01TX0FVVEgyMDI1MDgyNTEwMzkwNDExNjEwNTM=
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
+1 -1
View File
@@ -21,7 +21,7 @@ NEXT_PUBLIC_NGII_URL = http://10.98.25.94:18080/openapi/Gettile.do?apiKey=BDE2BE
NEXT_PUBLIC_FINDADRESS_URL=https://business.juso.go.kr/addrlink/addrLinkApi.do NEXT_PUBLIC_FINDADRESS_URL=https://business.juso.go.kr/addrlink/addrLinkApi.do
NEXT_PUBLIC_WR_ADDRESS_KEY = U01TXOFVVEgyMDI1MDgyODE0MTAxNzExNjEyMjA= NEXT_PRIVATE_WR_ADDRESS_KEY = U01TXOFVVEgyMDI1MDgyODE0MTAxNzExNjEyMjA=
@@ -93,6 +93,7 @@ const Map = () => {
return; return;
} }
// 항상 같은 select 객체 사용 // 항상 같은 select 객체 사용
const select = GisApp.Module.select as any; const select = GisApp.Module.select as any;
if (!select) return; if (!select) return;
@@ -107,6 +108,8 @@ const Map = () => {
if (popUpClick) { if (popUpClick) {
const layerName = getWrLayerNm(data); const layerName = getWrLayerNm(data);
const featurePk = getWrFeaturePk(layerName ?? ""); const featurePk = getWrFeaturePk(layerName ?? "");
// 재이용시설 // 재이용시설
if (featurePk) { if (featurePk) {
const lastPk = const lastPk =
@@ -114,6 +117,7 @@ const Map = () => {
? data[featurePk].replaceAll("-", "") ? data[featurePk].replaceAll("-", "")
: data[featurePk]; : data[featurePk];
featureId = `${layerName}.${lastPk}`; featureId = `${layerName}.${lastPk}`;
} else { } else {
console.warn("해당 피처는 선택된 레이어에서 찾을수 없습니다."); console.warn("해당 피처는 선택된 레이어에서 찾을수 없습니다.");
} }
@@ -160,7 +164,6 @@ const Map = () => {
setFeatureData(data); setFeatureData(data);
setIsOpen(true); setIsOpen(true);
setIsSearchModalOpen(false); setIsSearchModalOpen(false);
if ( if (
popUpClick && popUpClick &&
foundFeature && foundFeature &&
@@ -181,6 +184,7 @@ const Map = () => {
useEffect(() => { useEffect(() => {
if (isFeatured) { if (isFeatured) {
onFeatureSelect(isFeatured); onFeatureSelect(isFeatured);
} }
}, [isFeatured]); }, [isFeatured]);
@@ -189,6 +193,7 @@ const Map = () => {
const bc = new BroadcastChannel("mapDetailPopUp"); const bc = new BroadcastChannel("mapDetailPopUp");
bc.onmessage = (event) => { bc.onmessage = (event) => {
if (event.data.type === "SELECT_FEATURE") { if (event.data.type === "SELECT_FEATURE") {
onFeatureSelect(event.data.feature, true); onFeatureSelect(event.data.feature, true);
closePopup(); closePopup();
} }
@@ -263,8 +268,10 @@ const overlayFormatter = async (feature: any, props: any) => {
feature.getId?.() ?? p?.id ?? p?.fid ?? p?.ftrIdn ?? ''; feature.getId?.() ?? p?.id ?? p?.fid ?? p?.ftrIdn ?? '';
if (!featureId) return null; if (!featureId) return null;
const tableId = String(featureId).split('.')[0]??''; const tableId = String(featureId).split('.')[0]??'';
const fcltCd = getFeatureCd(props, tableId); const fcltCd = getFeatureCd(props, tableId);
if (!fcltCd) return null; if (!fcltCd) return null;
let data: any = null; let data: any = null;
+23 -21
View File
@@ -6,7 +6,6 @@ import {
ldrmntNodeListExport, ldrmntNodeListExport,
} from "../../matDmd/ldrmntCoSttn/headList"; } from "../../matDmd/ldrmntCoSttn/headList";
export const ldrmntMapSize = 20; export const ldrmntMapSize = 20;
export type ldrmntMapState = { export type ldrmntMapState = {
ldrmntMap: { ldrmntMap: {
@@ -26,7 +25,7 @@ type ldrmntMapActions = {
con: string, con: string,
coNm: string coNm: string
) => void; ) => void;
ldrmntMapDetile:(featureCd:string) => Promise<customLdrmnt | undefined>; ldrmntMapDetile: (featureCd: string) => Promise<customLdrmnt | undefined>;
}; };
export type ldrmntMapType = ldrmntMapState & ldrmntMapActions; export type ldrmntMapType = ldrmntMapState & ldrmntMapActions;
@@ -68,10 +67,10 @@ export const ldrmntMapActionsExport: (set: any) => ldrmntMapActions = (
} }
}, },
ldrmntMapSearch: async ( ldrmntMapSearch: async (
page: number, page: number,
total: number, total: number,
con: string, con: string,
coNm: string coNm: string
) => { ) => {
let searchUrl = ""; let searchUrl = "";
@@ -98,21 +97,24 @@ export const ldrmntMapActionsExport: (set: any) => ldrmntMapActions = (
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
},ldrmntMapDetile: async (featureCd: string) => { },
try { ldrmntMapDetile: async (featureCd: string) => {
try {
const ldrmtDetail = await getFetch(fetchType.WR, const ldrmtDetail = await getFetch(
`/reuseFc/request/temp/1/4/0/${featureCd}` ) fetchType.WR,
if(ldrmtDetail&&ldrmtDetail.length>0){ `/reuseFc/request/temp/1/4/0/${featureCd}`
);
return ldrmtDetail[0]; if (ldrmtDetail && ldrmtDetail.length > 0) {
}else{ return ldrmtDetail.find(
return null; (item: customLdrmnt) => item.dmdCoNm === featureCd
} );
} catch (error) { } else {
console.log(error); return null;
throw error; // 호출부에서 catch 가능하도록 }
} } catch (error) {
console.log(error);
throw error; // 호출부에서 catch 가능하도록
} }
},
}; };
}; };
+16 -7
View File
@@ -96,7 +96,10 @@ export const getSelectedLayers = (isFeature: any, gisMaps: any) => {
}; };
export const getClickFeatureId = (data: any) => { export const getClickFeatureId = (data: any) => {
let featureId = ""; let featureId = "";
const layerName = data.layerNm; const layerName = data.layerNm;
if (layerName === "하수재이용시설") { if (layerName === "하수재이용시설") {
// 재이용시설 // 재이용시설
@@ -116,9 +119,15 @@ export const getClickFeatureId = (data: any) => {
} else if (layerName == "수요처") { } else if (layerName == "수요처") {
//수요처 //수요처
featureId = `${layerName}.${data.dmdInfoId.replaceAll("-", "")}`; featureId = `${layerName}.${data.dmdInfoId.replaceAll("-", "")}`;
} else { }else if (layerName == "잠재수요처") {
featureId = `${layerName}.${data.fid || data.id || data.ftrIdn}`; //잠재수요처
featureId = data.id_
} else {
featureId = data.id_
} }
return featureId; return featureId;
}; };
@@ -127,6 +136,8 @@ export function featurePopUpOpen(
featureCd: string, featureCd: string,
popupDetailRef popupDetailRef
) { ) {
const url = `/mapFeaturePopup?layerNm=${encodeURIComponent(String(layerNm))}&featureCd=${encodeURIComponent(featureCd)} `; const url = `/mapFeaturePopup?layerNm=${encodeURIComponent(String(layerNm))}&featureCd=${encodeURIComponent(featureCd)} `;
const width = const width =
String(layerNm) === "tb_wr_bdst_ruse_fclt" String(layerNm) === "tb_wr_bdst_ruse_fclt"
@@ -193,11 +204,9 @@ export const getOverLayObj = (fclType: string, data: any,code?:any) => {
title = data?.bdstNm ?? '확인불가'; title = data?.bdstNm ?? '확인불가';
} else if (fclType === "온배수시설") { } else if (fclType === "온배수시설") {
newObj = { newObj = {
미정: '확인불가', '발전유형': data?.reuseBuilding[0]?.htdflObj.etgtType??'',
// '설치완료일': data?.reuseBuilding[0]?.instlCmptnDt??'', '설비용량': data?.reuseBuilding[0]?.htdflObj.fclCpct??'',
// '처리시설유무': data?.reuseBuilding[0]?.rainyObj.filtrTrtmfctYn??'', '담수화 여부': data?.reuseBuilding[0]?.htdflObj.plwtYn??'',
// '처리시설용량(m³/일)': data?.reuseBuilding[0]?.rainyObj.filtrTrtmfctCpct??'',
// '저류조용량(m³)': data?.reuseBuilding[0]?.rainyObj.pntfColArea??'',
}; };
title = data?.bdstNm ?? '확인불가'; title = data?.bdstNm ?? '확인불가';
} else if (fclType === "수요처") { } else if (fclType === "수요처") {
@@ -1,50 +1,51 @@
"use client"; "use client";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import WrOverLayTable from "../WrOverLayTable/WrOverLayTable"; import WrOverLayTable from "../WrOverLayTable/WrOverLayTable";
import { import {
Tabs, Button,
TabsContent,
TabsList,
TabsTrigger,
} from "@common/components/ui"; } from "@common/components/ui";
import { getOverLayObj } from "@/components/lib/func/mapUtil"; import { getOverLayObj } from "@/components/lib/func/mapUtil";
import { ChevronLeft, ChevronRight } from "lucide-react";
type RuseTabData = { type RuseTabData = {
data: Record<string, string>; data: Record<string, string>;
tabData:{ tabData: {
pbnstRuseFcltId: string; pbnstRuseFcltId: string;
ruseUtztnFcltNm: string; ruseUtztnFcltNm: string;
} };
} };
export default function WrOverLayRuse({ overLayData }: { overLayData: any }) { export default function WrOverLayRuse({ overLayData }: { overLayData: any }) {
const [fcltTab, setFcltTab] = useState<string>(""); const [ruseData, setRuseData] = useState<RuseTabData[]>([] as RuseTabData[]);
const [ruseData, setRuseData] = useState<RuseTabData[]>([]as RuseTabData[]); const [idx, setIdx] = useState(0);
// useEffect(() => { const loop = true;
// const detail = overLayData.find((list) => list.pbnstRuseFcltId === fcltTab); const go = (next: number) => {
// if (detail) setIsDetail(detail); if (loop) {
// }, [fcltTab, overLayData]); const n = (next + ruseData.length) % ruseData.length;
setIdx(n);
} else {
setIdx(Math.max(0, Math.min(ruseData.length - 1, next)));
}
};
const prev = () => go(idx - 1);
const next = () => go(idx + 1);
useEffect(() => { useEffect(() => {
if (overLayData && overLayData[0]) { if (overLayData && overLayData[0]) {
setFcltTab(overLayData[0].pbnstRuseFcltId);
const newRuseData= overLayData.map((ruse) =>{ const newRuseData = overLayData.map((ruse) => {
const isData = getOverLayObj( '하수재이용시설',ruse); const isData = getOverLayObj("하수재이용시설", ruse);
return { return {
data: isData.newObj, data: isData.newObj,
tabData:{ tabData: {
pbnstRuseFcltId: ruse.pbnstRuseFcltId, pbnstRuseFcltId: ruse.pbnstRuseFcltId,
ruseUtztnFcltNm: ruse.ruseUtztnFcltNm ruseUtztnFcltNm: ruse.ruseUtztnFcltNm,
} },
} };
}) });
setRuseData(newRuseData); setRuseData(newRuseData);
} }
}, [overLayData]); }, [overLayData]);
@@ -52,36 +53,42 @@ export default function WrOverLayRuse({ overLayData }: { overLayData: any }) {
return ( return (
<> <>
<div> <div>
<div className="bg-sky-600 text-white text-center font-semibold py-2 text-2xl">
{/* 커스텀 헤더: 한 칸만 보이는 슬라이더 형태 */}
<div className="mt-2 flex items-center gap-2">
<Button
variant="outline"
size="icon"
color="white"
onClick={prev}
disabled={!loop && idx === 0}
aria-label="이전"
>
<ChevronLeft className="h-4 w-4" />
</Button>
<div className="flex-1 select-none rounded-md border px-4 py-2 text-center">
{/* 가운데 이름만 노출 */}
<span className="text-xl font-medium">
{ruseData[idx]?.tabData.ruseUtztnFcltNm ?? ""}
</span>
</div> </div>
<Tabs value={fcltTab} onValueChange={setFcltTab}>
<TabsList className="mt-2 mb-2 gap-6 flex flex-wrap">
{ruseData?.map((item, index) => {
return (
<TabsTrigger
key={item.tabData.pbnstRuseFcltId + index} <Button
className="text-center !text-base size-3/12" variant="outline"
value={item.tabData.pbnstRuseFcltId} size="icon"
> onClick={next}
{item.tabData.ruseUtztnFcltNm} color="white"
</TabsTrigger> disabled={!loop && idx === ruseData.length - 1}
); aria-label="다음"
})} >
</TabsList> <ChevronRight className="h-4 w-4" />
</Button>
</div>
{ruseData?.map((item) => ( <div className="mb-4">
<TabsContent <WrOverLayTable overLayData={ruseData[idx]?.data??[{'확인불가':''}]} />
key={item.tabData.pbnstRuseFcltId} </div>
className="flex-1 px-4 py-3"
value={item.tabData.pbnstRuseFcltId}
>
<div className="mb-4">
<WrOverLayTable overLayData={item.data} />
</div>
</TabsContent>
))}
</Tabs>
</div> </div>
</> </>
); );
@@ -71,7 +71,7 @@ export default function WrOverLay({
{/* 중앙 타이틀 */} {/* 중앙 타이틀 */}
<div className="text-2xl text-center truncate"> <div className="text-2xl text-center truncate">
{typeTitle + "(" + title + ")"} {title === "하수재이용시설" ? title: typeTitle + "(" + title + ")"}
</div> </div>
{/* 우측 실제 버튼 영역 */} {/* 우측 실제 버튼 영역 */}
+1 -1
View File
@@ -11,7 +11,7 @@ const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
const REUSE_API_URL = process.env.NEXT_PUBLIC_WR_SERVER_API_URL || ""; const REUSE_API_URL = process.env.NEXT_PUBLIC_WR_SERVER_API_URL || "";
const OPERATION_API_URL = process.env.NEXT_PUBLIC_FO_SERVER_API_URL || ""; const OPERATION_API_URL = process.env.NEXT_PUBLIC_FO_SERVER_API_URL || "";
const BUSINESS_JUSO_API_URL = process.env.NEXT_PUBLIC_FINDADRESS_URL || ""; const BUSINESS_JUSO_API_URL = process.env.NEXT_PUBLIC_FINDADRESS_URL || "";
const AdressKey = process.env.NEXT_PUBLIC_WR_ADDRESS_KEY || ""; const AdressKey = process.env.NEXT_PRIVATE_WR_ADDRESS_KEY || "";
export function middleware(req: NextRequest) { export function middleware(req: NextRequest) {
const pathname = req.nextUrl.pathname; const pathname = req.nextUrl.pathname;