diff --git a/apps/fo/app/pages/map/searchBar/searchBar.tsx b/apps/fo/app/pages/map/searchBar/searchBar.tsx
index 9b0800399..e9084870a 100644
--- a/apps/fo/app/pages/map/searchBar/searchBar.tsx
+++ b/apps/fo/app/pages/map/searchBar/searchBar.tsx
@@ -2,6 +2,7 @@
import { SelectBox, type SelectDataType } from "@common/business_components/ui";
import { Button } from "@common/components/ui";
import { useCallback, useEffect, useState } from "react";
+import { GEOSERVER_URL } from "@/src/shared/config/env";
interface SearchBarProps {
onFeatureSelect: (feature: any) => void;
@@ -18,7 +19,7 @@ export function SearchBar({ onFeatureSelect, gisMaps }: SearchBarProps) {
const [facilityValue, setFacilityValue] = useState("0");
const fetchSido = async () => {
- const url = `http://rsone.iptime.org:10010/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_ctpv&outputFormat=application/json&propertyName=mctpv_korn_nm,mctpv_cd`;
+ const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_ctpv&outputFormat=application/json&propertyName=mctpv_korn_nm,mctpv_cd`;
const res = await fetch(url);
const json = await res.json();
@@ -30,7 +31,7 @@ export function SearchBar({ onFeatureSelect, gisMaps }: SearchBarProps) {
};
const fetchSigun = async () => {
- const url = `http://rsone.iptime.org:10010/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_sgg&outputFormat=application/json&propertyName=sgg_cd,sgg_korn_nm`;
+ const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_sgg&outputFormat=application/json&propertyName=sgg_cd,sgg_korn_nm`;
const res = await fetch(url);
const json = await res.json();
@@ -43,7 +44,7 @@ export function SearchBar({ onFeatureSelect, gisMaps }: SearchBarProps) {
const fetchFacilitiesBySggNm = async (sggNm: string) => {
const encodedSggNm = encodeURIComponent(sggNm);
- const url = `http://rsone.iptime.org:10010/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_il_swage_prcs_fclt&outputFormat=application/json&cql_filter=sgg_nm='${encodedSggNm}'`;
+ const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_il_swage_prcs_fclt&outputFormat=application/json&cql_filter=sgg_nm='${encodedSggNm}'`;
const res = await fetch(url);
const json = await res.json();
diff --git a/apps/wr/.env.local b/apps/wr/.env.local
index 2543a96ad..4d00d1cab 100644
--- a/apps/wr/.env.local
+++ b/apps/wr/.env.local
@@ -10,6 +10,8 @@ NEXT_PUBLIC_CLAIM_NAME = Authorization
NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
+NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
+NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
diff --git a/apps/wr/app/map/mainMap/page.tsx b/apps/wr/app/map/mainMap/page.tsx
index 8cfb27e2f..420dfdfb0 100644
--- a/apps/wr/app/map/mainMap/page.tsx
+++ b/apps/wr/app/map/mainMap/page.tsx
@@ -5,6 +5,7 @@ import { useEffect, useRef, useState, useCallback } from "react";
import { mapService } from "../service";
import NewWindowPopup from "../newWindowPopup";
import GisApp from "@common/business_components/ui/map/lib/gis.core";
+import { SearchBar } from "../searchBar/searchBar";
const Map = () => {
const [treeData, setTreeData] = useState([]); // 초기값을 객체 또는 null로 설정
@@ -61,24 +62,28 @@ const Map = () => {
// 2. data가 OpenLayers Feature 인스턴스인지 확인
let foundFeature: any = null;
- console.log(data)
+ console.log(data);
//console.log(data.getId())
let featureId = data.fid;
const layerName = data.layerNm;
-
+
if (layerName === "재이용시설") {
// 재이용시설
featureId = `${layerName}.${data.searchPk}`;
- } else if ( //빗물이용시설, 중수도시설
+ } else if (
+ //빗물이용시설, 중수도시설
layerName === "빗물이용시설" ||
layerName == "tb_wr_rswtr_fclt"
) {
featureId = `${layerName}.${data.bdstInfoSn}`;
- } else if (layerName === "tb_il_swage_prcs_fclt") { //하수처리시설
+ } else if (layerName === "tb_il_swage_prcs_fclt") {
+ //하수처리시설
featureId = `${layerName}.${data.bscFctCd}`;
- } else if (layerName === "tb_wr_htdfl_fclt") { //온배수시설
+ } else if (layerName === "tb_wr_htdfl_fclt") {
+ //온배수시설
featureId = `${layerName}.${data.bdstRuseFcltSn}`;
- } else if (layerName == "tb_wr_ruse_fclt_dmd_co") { //수요처
+ } else if (layerName == "tb_wr_ruse_fclt_dmd_co") {
+ //수요처
featureId = `${layerName}.${data.dmdInfoId.replaceAll("-", "")}`;
} else {
console.warn("해당 레이어에 대한 featureId 매핑 없음", layerName);
@@ -120,17 +125,6 @@ const Map = () => {
setIsSearchModalOpen(false);
};
- // MapSearchBar 래퍼 컴포넌트
- // const CustomMapSearchBar = (props: any) => {
- // return (
- //
- // );
- // };
-
return (
{
isSearchModalOpen={isSearchModalOpen}
onCheckedLayersChange={handleCheckedLayersChange}
imgVisble={true}
- searchBar={undefined}
+ searchBar={(props: any) => {
+ const facilityTypes = [
+ { text: "하수처리시설", val: "tb_il_swage_prcs_fclt" },
+ { text: "하수재이용시설", val: "tb_wr_bdst_ruse_fclt" },
+ { text: "빗물이용시설", val: "tb_wr_rnwtr_utztn_fclt" },
+ { text: "중수도시설", val: "tb_wr_rswtr_fclt" },
+ { text: "온배수시설", val: "tb_wr_htdfl_fclt" },
+ { text: "수요처", val: "tb_wr_ruse_fclt_dmd_co" },
+ { text: "잠재수요처", val: "tb_wr_tmpr_dmd_co" },
+ ];
+ return (
+
+ );
+ }}
/>
);
diff --git a/apps/wr/app/map/searchBar/searchBar.tsx b/apps/wr/app/map/searchBar/searchBar.tsx
new file mode 100644
index 000000000..7502daf94
--- /dev/null
+++ b/apps/wr/app/map/searchBar/searchBar.tsx
@@ -0,0 +1,299 @@
+"use client";
+import { SelectBox, type SelectDataType } from "@common/business_components/ui";
+import { Button } from "@common/components/ui";
+import { useCallback, useEffect, useState } from "react";
+import { SERVER_API_WR_URL } from "@/src/shared/config";
+
+const geoserverUrl =
+ "/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&outputFormat=application/json";
+
+const FACILITY_TYPE_URL_MAP: Record = {
+ tb_il_swage_prcs_fclt: geoserverUrl, //하수처리시설
+ tb_wr_bdst_ruse_fclt:
+ "/reuse-service/reuseFc/pubDetailList/{year}/{sggCd}/1/1000", //재이용시설 post
+ tb_wr_rnwtr_utztn_fclt: "/reuse-service/reuseFc/rainyInfoList/1/1000/{sggCd}", //빗물이용시설 get
+ tb_wr_rswtr_fclt: "/reuse-service/reuseFc/waterreuseFc/1/1000/{sggCd}", //중수도시설 get
+ tb_wr_htdfl_fclt: "/reuse-service/drain/facilityList/1/1000/{sggCd}", //온배수시설 get
+ tb_wr_ruse_fclt_dmd_co: "/reuse-service/reuseFc/request/1/1000/{sggCd}", //수요처 get
+ tb_wr_tmpr_dmd_co:
+ "/reuse-service/reuseFc/request/temp/1/1000/{sidoNm} {sggNm}", //잠재수요처 get
+};
+
+interface SearchBarProps {
+ onFeatureSelect: (feature: any) => void;
+ gisMaps: React.RefObject;
+ facilityTypes: { text: string; val: string }[];
+}
+
+export function SearchBar({
+ onFeatureSelect,
+ gisMaps,
+ facilityTypes,
+}: SearchBarProps) {
+ const [sidoValue, setSidoValue] = useState("0");
+ const [sigunValue, setSigunValue] = useState("0");
+ const [sidoData, setSidoData] = useState([
+ { text: "선택", val: "0" },
+ ]);
+ const [sigunData, setSigunData] = useState([
+ { text: "선택", val: "0" },
+ ]);
+ const [filteredSigunData, setFilteredSigunData] = useState([
+ { text: "선택", val: "0" },
+ ]);
+
+ const [facilityData, setFacilityData] = useState([
+ { text: "선택", val: "0" },
+ ]);
+ const [facilityValue, setFacilityValue] = useState("0");
+
+ const [facilityType, setFacilityType] = useState(
+ facilityTypes?.length === 1 && facilityTypes[0] ? facilityTypes[0].val : "0"
+ );
+
+ //시도, 시군구 조회
+ const fetchSido = async () => {
+ const url = `/cms-service/api/v1/code/cache/ADSTDSTRCD/Y`;
+ const res = await fetch(url);
+ const json = await res.json();
+ const sidoList = json
+ .filter(
+ (item: any) =>
+ typeof item.lwpoCd === "string" && item.lwpoCd.length === 2
+ )
+ .map((feature: any) => ({
+ val: feature.lwpoCd,
+ text: feature.lwpoCdNm,
+ }));
+ setSidoData([{ text: "선택", val: "0" }, ...sidoList]);
+
+ const sigunList = json
+ .filter(
+ (item: any) =>
+ typeof item.lwpoCd === "string" && item.lwpoCd.length !== 2
+ )
+ .map((feature: any) => ({
+ val: feature.lwpoCd,
+ text: feature.lwpoCdNm,
+ }));
+ setSigunData(sigunList);
+ };
+
+ //시설명 콤보박스 조회
+ const fetchFacilitiesBySggNm = async (
+ sggCd: string,
+ sggNm: string,
+ sidoNm: string,
+ currentFacilityType?: string
+ ) => {
+ const type = currentFacilityType ?? facilityType;
+ if (!type || type === "0") return;
+
+ const baseUrlTemplate = FACILITY_TYPE_URL_MAP[type];
+ if (!baseUrlTemplate) return;
+
+ const year = new Date().getFullYear().toString();
+ let url = baseUrlTemplate
+ .replace("{year}", year)
+ .replace("{sggCd}", sggCd)
+ .replace("{sidoNm}", encodeURIComponent(sidoNm))
+ .replace("{sggNm}", encodeURIComponent(sggNm));
+
+ let list: SelectDataType[] = [];
+
+ if (
+ type === "tb_il_swage_prcs_fclt" //하수처리시설
+ ) {
+ const cqlFilter = `ctpv_nm='${encodeURIComponent(sidoNm)}' AND sgg_nm='${encodeURIComponent(sggNm)}'`;
+ url = `${url}&typeName=hasudo:${type}&cql_filter=${cqlFilter}`;
+ const res = await fetch(url);
+ const json = await res.json();
+ list = json.features.map((f: any) => ({
+ text: f.properties.swtrmt_fclt_nm ?? "(이름없음)",
+ val: f.id,
+ }));
+ } else if (
+ type === "tb_wr_bdst_ruse_fclt" // 재이용시설
+ ) {
+ //재용에서 참조하는 하수처리시설 목록
+ const paramsRes = await fetch("/reuse-service/reuseFc/pubFc");
+ const paramsJson = await paramsRes.json();
+ const params = paramsJson.data;
+
+ const res = await fetch(url, {
+ method: "POST",
+ headers: {
+ accept: "application/json",
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(params),
+ });
+ const json = await res.json();
+ list = (json.data || []).map((item: any) => ({
+ text: item.ruseUtztnFcltNm ?? "(이름없음)",
+ val: item.pbnstRuseFcltId,
+ }));
+ } else if (
+ type === "tb_wr_ruse_fclt_dmd_co" //수요처
+ ) {
+ const res = await fetch(url);
+ const json = await res.json();
+ list = (json.data || []).map((item: any) => ({
+ text: item.dmdCoNm ?? "(이름없음)",
+ val: item.dmdInfoId,
+ }));
+ } else if (
+ type === "tb_wr_tmpr_dmd_co" //잠재수요처
+ ) {
+ // GET 방식
+ const res = await fetch(url);
+ const json = await res.json();
+ list = (json.data || []).map((item: any) => ({
+ text: item.dmdCoNm ?? "(이름없음)",
+ val: item.fctryMngSn,
+ }));
+ } else {
+ // GET 방식
+ const res = await fetch(url);
+ const json = await res.json();
+ list = (json.data || []).map((item: any) => ({
+ text: item.bdstNm ?? "(이름없음)",
+ val: item.bdstInfoSn,
+ }));
+ }
+
+ setFacilityData([{ text: "선택", val: "0" }, ...list]);
+ setFacilityValue("0");
+ };
+
+ //시도, 시군구 초기 데이터 조회
+ useEffect(() => {
+ fetchSido();
+ }, []);
+
+ //시군구 데이터 초기화
+ const initializeSigunData = useCallback(
+ (sidoCd: string) => {
+ if (sidoCd === "0") {
+ setFilteredSigunData([{ text: "선택", val: "0" }]);
+ setSigunValue("0");
+ return;
+ }
+ const prefix = sidoCd.substring(0, 2);
+ const filtered = sigunData.filter((item) => item.val.startsWith(prefix));
+ setFilteredSigunData([{ text: "선택", val: "0" }, ...filtered]);
+ setSigunValue("0");
+ },
+ [sigunData]
+ );
+
+ //콤보박스 선택시 연관 콤보박스 처리
+ const onSelectValue = useCallback(
+ (val: string, type: string) => {
+ if (type === "ctpvCd") {
+ setSidoValue(val);
+ initializeSigunData(val);
+ setFacilityData([{ text: "선택", val: "0" }]);
+ setFacilityValue("0");
+ } else if (type === "sggCd") {
+ setSigunValue(val);
+ const sidoNm =
+ sidoData.find((item) => item.val === sidoValue)?.text || "";
+ const sggNm = sigunData.find((item) => item.val === val)?.text || "";
+ const sggCd = sigunData.find((item) => item.val === val)?.val || "";
+ if (sggNm && sidoNm)
+ fetchFacilitiesBySggNm(sggCd, sggNm, sidoNm, facilityType);
+ } else if (type === "facilityType") {
+ setFacilityType(val);
+ setFacilityValue("0");
+ setFacilityData([{ text: "선택", val: "0" }]);
+ const sidoNm =
+ sidoData.find((item) => item.val === sidoValue)?.text || "";
+ const sggNm =
+ sigunData.find((item) => item.val === sigunValue)?.text || "";
+ const sggCd =
+ sigunData.find((item) => item.val === sigunValue)?.val || "";
+ if (sggNm && sidoNm) fetchFacilitiesBySggNm(sggCd, sggNm, sidoNm, val);
+ } else if (type === "fcltCd") {
+ setFacilityValue(val);
+ }
+ },
+ [initializeSigunData, sigunData, sigunValue, sidoData, sidoValue]
+ );
+
+ //조회 버튼 클릭
+ const handleSearch = () => {
+ if (!gisMaps.current || facilityValue === "0") return;
+ const layers = gisMaps.current.getLayers().getArray();
+ for (const layer of layers) {
+ const source = layer.getSource?.();
+ const feature = source?.getFeatureById?.(facilityValue);
+ if (feature) {
+ onFeatureSelect(feature);
+ return;
+ }
+ }
+ alert("해당 처리시설을 지도에서 찾을 수 없습니다.");
+ };
+
+ return (
+
+
+
+
+ {facilityTypes.length > 1 && (
+
+ onSelectValue(val.toString(), "facilityType")
+ }
+ value={facilityType}
+ />
+ )}
+ onSelectValue(val.toString(), "ctpvCd")}
+ value={sidoValue}
+ />
+ onSelectValue(val.toString(), "sggCd")}
+ value={sigunValue}
+ />
+ onSelectValue(val.toString(), "fcltCd")}
+ value={facilityValue}
+ />
+
+
+
+
+
+
+
+ );
+}
diff --git a/apps/wr/middleware.ts b/apps/wr/middleware.ts
index 61f41d634..1a90a5591 100644
--- a/apps/wr/middleware.ts
+++ b/apps/wr/middleware.ts
@@ -8,6 +8,7 @@ const serverApiUrl = CS_URL;
const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || "";
const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || "";
const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
+const REUSE_API_URL = process.env.NEXT_PUBLIC_WR_SERVER_API_URL || "";
export function middleware(req: NextRequest) {
const pathname = req.nextUrl.pathname;
@@ -135,6 +136,15 @@ export function middleware(req: NextRequest) {
return NextResponse.rewrite(new URL(newUrl));
}
+ if (pathname.startsWith("/reuse-service")) {
+ const queryParams = searchParams.toString();
+ const newUrl = `${REUSE_API_URL}${pathname.replace("/reuse-service", "")}${
+ queryParams ? `?${queryParams}` : ""
+ }`;
+ console.log(`[Middleware] Rewriting from '/reuse-service' path to: ${newUrl}`);
+ return NextResponse.rewrite(new URL(newUrl));
+ }
+
return NextResponse.next();
}
@@ -146,6 +156,7 @@ export const config = {
"/attach-service/:path*",
"/geoserver/:path*",
"/sewerage-service/:path*",
+ "/reuse-service/:path*",
"/"
],
};
diff --git a/packages/common/business_components/src/ui/map/Gis.js b/packages/common/business_components/src/ui/map/Gis.js
index 079506aca..013288df4 100644
--- a/packages/common/business_components/src/ui/map/Gis.js
+++ b/packages/common/business_components/src/ui/map/Gis.js
@@ -326,8 +326,7 @@ function Gis({
{/* 시도/시군구 조회 영역 */}
{SearchBar && (
diff --git a/packages/common/business_components/src/ui/map/lib/gis.layer.js b/packages/common/business_components/src/ui/map/lib/gis.layer.js
index 412b0d8b9..f7bb7b3ac 100644
--- a/packages/common/business_components/src/ui/map/lib/gis.layer.js
+++ b/packages/common/business_components/src/ui/map/lib/gis.layer.js
@@ -143,11 +143,11 @@ GisOlLayer.prototype = {
let source;
let lyrTyNm = option.lyrTyNm;
- if(lyrTyNm == 'tb_ms_flood_dngr_map'
- || lyrTyNm == 'tb_ms_sbmrg_dngr_map'
- || lyrTyNm == 'tb_ms_swage_mhl'
- || lyrTyNm == 'tb_ms_swage_ppl'
- || lyrTyNm == 'tb_ms_swage_pmstn'
+ if(lyrTyNm == 'tb_ms_flood_dngr_map' //침수위험지도
+ || lyrTyNm == 'tb_ms_sbmrg_dngr_map' //도시침수지도
+ || lyrTyNm == 'tb_ms_swage_mhl' //맨홀
+ || lyrTyNm == 'tb_ms_swage_ppl' //관로
+ || lyrTyNm == 'tb_ms_swage_pmstn' //펌프장
) {
source = this.getVectorSourceBbox(option);
}else {