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

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_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_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_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
+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_WR_ADDRESS_KEY = U01TXOFVVEgyMDI1MDgyODE0MTAxNzExNjEyMjA=
NEXT_PRIVATE_WR_ADDRESS_KEY = U01TXOFVVEgyMDI1MDgyODE0MTAxNzExNjEyMjA=
@@ -93,6 +93,7 @@ const Map = () => {
return;
}
// 항상 같은 select 객체 사용
const select = GisApp.Module.select as any;
if (!select) return;
@@ -107,6 +108,8 @@ const Map = () => {
if (popUpClick) {
const layerName = getWrLayerNm(data);
const featurePk = getWrFeaturePk(layerName ?? "");
// 재이용시설
if (featurePk) {
const lastPk =
@@ -114,6 +117,7 @@ const Map = () => {
? data[featurePk].replaceAll("-", "")
: data[featurePk];
featureId = `${layerName}.${lastPk}`;
} else {
console.warn("해당 피처는 선택된 레이어에서 찾을수 없습니다.");
}
@@ -160,7 +164,6 @@ const Map = () => {
setFeatureData(data);
setIsOpen(true);
setIsSearchModalOpen(false);
if (
popUpClick &&
foundFeature &&
@@ -181,6 +184,7 @@ const Map = () => {
useEffect(() => {
if (isFeatured) {
onFeatureSelect(isFeatured);
}
}, [isFeatured]);
@@ -189,6 +193,7 @@ const Map = () => {
const bc = new BroadcastChannel("mapDetailPopUp");
bc.onmessage = (event) => {
if (event.data.type === "SELECT_FEATURE") {
onFeatureSelect(event.data.feature, true);
closePopup();
}
@@ -263,8 +268,10 @@ const overlayFormatter = async (feature: any, props: any) => {
feature.getId?.() ?? p?.id ?? p?.fid ?? p?.ftrIdn ?? '';
if (!featureId) return null;
const tableId = String(featureId).split('.')[0]??'';
const fcltCd = getFeatureCd(props, tableId);
if (!fcltCd) return null;
let data: any = null;
+23 -21
View File
@@ -6,7 +6,6 @@ import {
ldrmntNodeListExport,
} from "../../matDmd/ldrmntCoSttn/headList";
export const ldrmntMapSize = 20;
export type ldrmntMapState = {
ldrmntMap: {
@@ -26,7 +25,7 @@ type ldrmntMapActions = {
con: string,
coNm: string
) => void;
ldrmntMapDetile:(featureCd:string) => Promise<customLdrmnt | undefined>;
ldrmntMapDetile: (featureCd: string) => Promise<customLdrmnt | undefined>;
};
export type ldrmntMapType = ldrmntMapState & ldrmntMapActions;
@@ -68,10 +67,10 @@ export const ldrmntMapActionsExport: (set: any) => ldrmntMapActions = (
}
},
ldrmntMapSearch: async (
page: number,
total: number,
con: string,
coNm: string
page: number,
total: number,
con: string,
coNm: string
) => {
let searchUrl = "";
@@ -98,21 +97,24 @@ export const ldrmntMapActionsExport: (set: any) => ldrmntMapActions = (
} catch (e) {
console.log(e);
}
},ldrmntMapDetile: async (featureCd: string) => {
try {
const ldrmtDetail = await getFetch(fetchType.WR,
`/reuseFc/request/temp/1/4/0/${featureCd}` )
if(ldrmtDetail&&ldrmtDetail.length>0){
return ldrmtDetail[0];
}else{
return null;
}
} catch (error) {
console.log(error);
throw error; // 호출부에서 catch 가능하도록
}
},
ldrmntMapDetile: async (featureCd: string) => {
try {
const ldrmtDetail = await getFetch(
fetchType.WR,
`/reuseFc/request/temp/1/4/0/${featureCd}`
);
if (ldrmtDetail && ldrmtDetail.length > 0) {
return ldrmtDetail.find(
(item: customLdrmnt) => item.dmdCoNm === featureCd
);
} else {
return null;
}
} 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) => {
let featureId = "";
const layerName = data.layerNm;
if (layerName === "하수재이용시설") {
// 재이용시설
@@ -116,9 +119,15 @@ export const getClickFeatureId = (data: any) => {
} else if (layerName == "수요처") {
//수요처
featureId = `${layerName}.${data.dmdInfoId.replaceAll("-", "")}`;
} else {
featureId = `${layerName}.${data.fid || data.id || data.ftrIdn}`;
}else if (layerName == "잠재수요처") {
//잠재수요처
featureId = data.id_
} else {
featureId = data.id_
}
return featureId;
};
@@ -127,6 +136,8 @@ export function featurePopUpOpen(
featureCd: string,
popupDetailRef
) {
const url = `/mapFeaturePopup?layerNm=${encodeURIComponent(String(layerNm))}&featureCd=${encodeURIComponent(featureCd)} `;
const width =
String(layerNm) === "tb_wr_bdst_ruse_fclt"
@@ -193,11 +204,9 @@ export const getOverLayObj = (fclType: string, data: any,code?:any) => {
title = data?.bdstNm ?? '확인불가';
} else if (fclType === "온배수시설") {
newObj = {
미정: '확인불가',
// '설치완료일': data?.reuseBuilding[0]?.instlCmptnDt??'',
// '처리시설유무': data?.reuseBuilding[0]?.rainyObj.filtrTrtmfctYn??'',
// '처리시설용량(m³/일)': data?.reuseBuilding[0]?.rainyObj.filtrTrtmfctCpct??'',
// '저류조용량(m³)': data?.reuseBuilding[0]?.rainyObj.pntfColArea??'',
'발전유형': data?.reuseBuilding[0]?.htdflObj.etgtType??'',
'설비용량': data?.reuseBuilding[0]?.htdflObj.fclCpct??'',
'담수화 여부': data?.reuseBuilding[0]?.htdflObj.plwtYn??'',
};
title = data?.bdstNm ?? '확인불가';
} else if (fclType === "수요처") {
@@ -1,50 +1,51 @@
"use client";
import { useEffect, useState } from "react";
import { useEffect, useState } from "react";
import WrOverLayTable from "../WrOverLayTable/WrOverLayTable";
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
Button,
} from "@common/components/ui";
import { getOverLayObj } from "@/components/lib/func/mapUtil";
import { ChevronLeft, ChevronRight } from "lucide-react";
type RuseTabData = {
data: Record<string, string>;
tabData:{
tabData: {
pbnstRuseFcltId: string;
ruseUtztnFcltNm: string;
}
}
};
};
export default function WrOverLayRuse({ overLayData }: { overLayData: any }) {
const [fcltTab, setFcltTab] = useState<string>("");
const [ruseData, setRuseData] = useState<RuseTabData[]>([]as RuseTabData[]);
// useEffect(() => {
// const detail = overLayData.find((list) => list.pbnstRuseFcltId === fcltTab);
// if (detail) setIsDetail(detail);
// }, [fcltTab, overLayData]);
const [ruseData, setRuseData] = useState<RuseTabData[]>([] as RuseTabData[]);
const [idx, setIdx] = useState(0);
const loop = true;
const go = (next: number) => {
if (loop) {
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(() => {
if (overLayData && overLayData[0]) {
setFcltTab(overLayData[0].pbnstRuseFcltId);
const newRuseData= overLayData.map((ruse) =>{
const isData = getOverLayObj( '하수재이용시설',ruse);
return {
data: isData.newObj,
tabData:{
pbnstRuseFcltId: ruse.pbnstRuseFcltId,
ruseUtztnFcltNm: ruse.ruseUtztnFcltNm
}
}
})
const newRuseData = overLayData.map((ruse) => {
const isData = getOverLayObj("하수재이용시설", ruse);
return {
data: isData.newObj,
tabData: {
pbnstRuseFcltId: ruse.pbnstRuseFcltId,
ruseUtztnFcltNm: ruse.ruseUtztnFcltNm,
},
};
});
setRuseData(newRuseData);
setRuseData(newRuseData);
}
}, [overLayData]);
@@ -52,36 +53,42 @@ export default function WrOverLayRuse({ overLayData }: { overLayData: any }) {
return (
<>
<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>
<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}
className="text-center !text-base size-3/12"
value={item.tabData.pbnstRuseFcltId}
>
{item.tabData.ruseUtztnFcltNm}
</TabsTrigger>
);
})}
</TabsList>
<Button
variant="outline"
size="icon"
onClick={next}
color="white"
disabled={!loop && idx === ruseData.length - 1}
aria-label="다음"
>
<ChevronRight className="h-4 w-4" />
</Button>
</div>
{ruseData?.map((item) => (
<TabsContent
key={item.tabData.pbnstRuseFcltId}
className="flex-1 px-4 py-3"
value={item.tabData.pbnstRuseFcltId}
>
<div className="mb-4">
<WrOverLayTable overLayData={item.data} />
</div>
</TabsContent>
))}
</Tabs>
<div className="mb-4">
<WrOverLayTable overLayData={ruseData[idx]?.data??[{'확인불가':''}]} />
</div>
</div>
</>
);
@@ -71,7 +71,7 @@ export default function WrOverLay({
{/* 중앙 타이틀 */}
<div className="text-2xl text-center truncate">
{typeTitle + "(" + title + ")"}
{title === "하수재이용시설" ? title: typeTitle + "(" + title + ")"}
</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 OPERATION_API_URL = process.env.NEXT_PUBLIC_FO_SERVER_API_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) {
const pathname = req.nextUrl.pathname;