gis 목록 에서 피처 선택시 오류 수정

This commit is contained in:
yschoi
2025-07-27 00:00:54 +09:00
parent 93e8ec1df3
commit 8a5b9ba2c3
5 changed files with 131 additions and 113 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
# NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883/sewerage-service/api # 박이정
+33 -20
View File
@@ -36,7 +36,10 @@ const Map = () => {
}, []);
// 체크된 레이어 정보를 받는 핸들러
const handleCheckedLayersChange = (checkedIds: string[], checkedNodesData: any[]) => {
const handleCheckedLayersChange = (
checkedIds: string[],
checkedNodesData: any[]
) => {
setCheckedLayers(checkedIds);
setCheckedLayersData(checkedNodesData);
};
@@ -58,28 +61,38 @@ const Map = () => {
// 2. data가 OpenLayers Feature 인스턴스인지 확인
let foundFeature: any = null;
if (
data &&
typeof data.getGeometry === "function" &&
typeof data.setStyle === "function"
let featureId = data.fid;
const layerName = data.layerNm;
if (layerName === "tb_wr_bdst_ruse_fclt") {
// 재이용시설
featureId = `${layerName}.${data.searchPk}`;
} else if ( //빗물이용시설, 중수도시설
layerName === "tb_wr_rnwtr_utztn_fclt" ||
layerName == "tb_wr_rswtr_fclt"
) {
// 이미 Feature 인스턴스라면 그대로 사용
foundFeature = data;
featureId = `${layerName}.${data.bdstInfoSn}`;
} else if (layerName === "tb_il_swage_prcs_fclt") { //하수처리시설
featureId = `${layerName}.${data.bscFctCd}`;
} else if (layerName === "tb_wr_htdfl_fclt") { //온배수시설
featureId = `${layerName}.${data.bdstRuseFcltSn}`;
} else if (layerName == "tb_wr_ruse_fclt_dmd_co") { //수요처
featureId = `${layerName}.${data.dmdInfoId.replaceAll("-", "")}`;
} else {
// 아니면 featureId로 맵에서 Feature 인스턴스를 찾아서 사용
const featureId = data.fid || data.ftrIdn || data.id;
map
.getLayers()
.getArray()
.forEach((layer: any) => {
const source = layer.getSource?.();
if (source?.getFeatureById) {
const feature = source.getFeatureById(String(featureId).trim());
if (feature) foundFeature = feature;
}
});
console.warn("해당 레이어에 대한 featureId 매핑 없음", layerName);
featureId = `${layerName}.${data.fid || data.id || data.ftrIdn}`;
}
map
.getLayers()
.getArray()
.forEach((layer: any) => {
const source = layer.getSource?.();
if (source?.getFeatureById) {
const feature = source.getFeatureById(String(featureId).trim());
if (feature) foundFeature = feature;
}
});
// 3. 피처 선택
if (foundFeature) {
const geometry = foundFeature.getGeometry();
@@ -133,7 +146,7 @@ const Map = () => {
// />
// )
// }
detailView={(props: any) =>(
detailView={(props: any) => (
<NewWindowPopup
onClose={handlePopupClose} // 메모이제이션된 함수 사용
checkedLayers={checkedLayers}
+9 -9
View File
@@ -156,15 +156,15 @@ const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
}
};
const detainSttn = async (featureCd: string, layerNm: string) => {
if (layerNm == '빗물이용시설') {
if (layerNm == 'tb_wr_rnwtr_utztn_fclt') { //빗물이용시설
const res = await getFetch(fetchType.WR, `/reuseFc/rainyInfoList/1/20/0/${featureCd}`)
setRainList(res)
}
else if (layerNm == '중수도시설') {
else if (layerNm == 'tb_wr_rswtr_fclt') { //중수도 시설
const res = await getFetch(fetchType.WR, `/reuseFc/waterreuseFc/1/20/0/${featureCd}`)
setRswtrList(res)
}
else if(layerNm =='수요처'){
else if(layerNm =='tb_wr_ruse_fclt_dmd_co'){ //수요처
const res = await getFetch(fetchType.WR, `/reuseFc/request/1/20/0/${featureCd}`)
setMngList(res)
}
@@ -505,17 +505,17 @@ const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
layerId = seletectedLayerNm || '';
}
//하수처리시설
const isPrcsFclt = layerId == '하수처리시설'
const isPrcsFclt = layerId == 'tb_il_swage_prcs_fclt'
// 재이용시설
const isPbnst = layerId == '하수재이용시설';
const isPbnst = layerId == 'tb_wr_bdst_ruse_fclt';
// 빗물이용시설
const isRain = layerId == '빗물이용시설';
const isRain = layerId == 'tb_wr_rnwtr_utztn_fclt';
// 중수도시설
const isRswt = layerId == '중수도시설';
const isRswt = layerId == 'tb_wr_rswtr_fclt';
// 온배수시설
const isHtdfl = layerId == '온배수시설';
const isHtdfl = layerId == 'tb_wr_htdfl_fclt';
// 수요처관리
const isReuseMng = layerId == '수요처';
const isReuseMng = layerId == 'tb_wr_ruse_fclt_dmd_co';
if (isPrcsFclt) {
if (viewMode == 'list') {
return (
@@ -129,90 +129,95 @@ function Gis({
// Feature Click Event
const handleFeatureSelect = useCallback((data) => {
gisMap = mapInstanceRef.current;
// gisMap = mapInstanceRef.current;
if (!gisMap) {
console.warn('지도가 초기화되지 않았습니다.');
return;
}
// if (!gisMap) {
// console.warn('지도가 초기화되지 않았습니다.');
// return;
// }
// 항상 같은 select 객체 사용
const select = GisApp.Module.select;
if (!select) return;
// // 항상 같은 select 객체 사용
// const select = GisApp.Module.select;
// if (!select) return;
// 1. 기존 선택 초기화
select.resetSelectedFeature();
// // 1. 기존 선택 초기화
// select.resetSelectedFeature();
// 2. data가 OpenLayers Feature 인스턴스인지 확인
let foundFeature = null;
if (data && typeof data.getGeometry === 'function' && typeof data.setStyle === 'function') {
// 이미 Feature 인스턴스라면 그대로 사용
foundFeature = data;
} else {
// 아니면 featureId로 맵에서 Feature 인스턴스를 찾아서 사용
let featureId = data.fid;
const layerName = layerNmRef.current
if (layerName === '하수재이용시설') {
featureId = data.searchPk;
} else if (layerName === '빗물이용시설' || layerName == '중수도시설') {
featureId = data.bdstInfoSn;
} else if (layerName === '하수처리시설') {
featureId = data.bscFctCd;
} else if (layerName === '온배수시설') {
featureId = data.bdstRuseFcltSn;
} else if(layerName == '수요처'){
featureId = data.dmdInfoId.replaceAll('-','')
}
else {
console.warn('해당 레이어에 대한 featureId 매핑 없음', layerNm);
featureId = data.fid || data.id || data.ftrIdn;
}
// gisMap.getLayers().getArray().forEach(layer => {
// const source = layer.getSource?.();
// if (source?.getFeatureById) {
// const feature = source.getFeatureById(String(featureId).trim());
// if (feature) foundFeature = feature;
// }
// });
// const [layerType, id] = String(featureId).split('.');
gisMap.getLayers().getArray().forEach(layer => {
const source = layer.getSource?.();
if (source?.getFeatures) {
const allFeatures = source.getFeatures();
for (const f of allFeatures) {
const id = String(f.getId());
// console.log('id', id, featureId)
if (id && id.split('.')[1] === String(featureId)) {
foundFeature = f;
break;
}
}
}
});
}
// // 2. data가 OpenLayers Feature 인스턴스인지 확인
// let foundFeature = null;
// if (data && typeof data.getGeometry === 'function' && typeof data.setStyle === 'function') {
// // 이미 Feature 인스턴스라면 그대로 사용
// foundFeature = data;
// } else {
// // 아니면 featureId로 맵에서 Feature 인스턴스를 찾아서 사용
// let featureId = data.fid;
// console.log(data)
// const layerName = layerNmRef.current
// data.layerNm = layerName;
// if (layerName === '하수재이용시설') {
// featureId = data.searchPk;
// } else if (layerName === '빗물이용시설' || layerName == '중수도시설') {
// featureId = data.bdstInfoSn;
// } else if (layerName === '하수처리시설') {
// featureId = data.bscFctCd;
// } else if (layerName === '온배수시설') {
// featureId = data.bdstRuseFcltSn;
// } else if(layerName == '수요처'){
// featureId = data.dmdInfoId.replaceAll('-','')
// }
// else {
// console.warn('해당 레이어에 대한 featureId 매핑 없음', layerNm);
// featureId = data.fid || data.id || data.ftrIdn;
// }
// // gisMap.getLayers().getArray().forEach(layer => {
// // const source = layer.getSource?.();
// // if (source?.getFeatureById) {
// // const feature = source.getFeatureById(String(featureId).trim());
// // if (feature) foundFeature = feature;
// // }
// // });
// // const [layerType, id] = String(featureId).split('.');
// gisMap.getLayers().getArray().forEach(layer => {
// const source = layer.getSource?.();
// if (source?.getFeatures) {
// const allFeatures = source.getFeatures();
// for (const f of allFeatures) {
// const id = String(f.getId());
// // console.log('id', id, featureId)
// if (id && id.split('.')[1] === String(featureId)) {
// foundFeature = f;
// break;
// }
// }
// }
// });
// }
// 3. 피처 선택
if (foundFeature) {
let geometry = foundFeature.getGeometry();
if (geometry) {
let extent = geometry.getExtent();
// // 3. 피처 선택
// if (foundFeature) {
// let geometry = foundFeature.getGeometry();
// if (geometry) {
// let extent = geometry.getExtent();
gisMap.getView().fit(extent, {
duration: 300,
padding: [50, 50, 50, 50],
maxZoom: 16,
constrainResolution: true,
nearest: true,
});
}
select.selectFeature(foundFeature, true);
} else {
console.warn('OpenLayers Feature를 찾을 수 없습니다:', data);
}
// gisMap.getView().fit(extent, {
// duration: 300,
// padding: [50, 50, 50, 50],
// maxZoom: 16,
// constrainResolution: true,
// nearest: true,
// });
// }
// select.selectFeature(foundFeature, true);
// } else {
// console.warn('OpenLayers Feature를 찾을 수 없습니다:', data);
// }
setFeatureData(data);
setIsOpen(true);
setIsSearchModalOpen(false);
// setFeatureData(data);
// setIsOpen(true);
// setIsSearchModalOpen(false);
const layerName = layerNmRef.current
data.layerNm = layerName;
onFeatureSelect?.(data); // 선택된 피쳐 데이터 콜백 호출
}, [mapInstanceRef]);
@@ -456,9 +461,9 @@ function Gis({
visible={tabVisible}
setVisible={setTabVisible}
onCheckedChange={handleCheckedLayersChange}
onLayerIconClick={(nodeNm) => {
layerNmRef.current = nodeNm
setLayerNm(nodeNm); setIsOpen(true); const dummyFeature = {
onLayerIconClick={(layerNm) => {
layerNmRef.current = layerNm
setLayerNm(layerNm); setIsOpen(true); const dummyFeature = {
getProperties: () => ({}), // 최소 구조
};
onFeatureSelect(dummyFeature);
@@ -188,9 +188,9 @@ export default React.memo(function GisTree({ checkedNodes = [], setCheckedNodes
image.src = canvas.toDataURL('image/png');
return image;
};
const handleLayerImgClick = (nodeNm, nodeId) => {
const handleLayerImgClick = (nodeNm, nodeId, layerNm) => {
if(!checked.includes(nodeId)) alert('시설을 선택해주세요')
else onLayerIconClick(nodeNm)
else onLayerIconClick(layerNm)
}
if (!treeData || treeData.length === 0) return null;
@@ -224,7 +224,7 @@ export default React.memo(function GisTree({ checkedNodes = [], setCheckedNodes
<input type="checkbox" checked={checked.includes(node.id)} onChange={() => handleCheck(node.id)} className="cursor-pointer" />
{node.icon && <span>{node.icon}</span>}
<span className="text-[1.3rem] font-medium text-label">{node.text}</span>
{imageVisible ? depth > 0 && <span><img className="cursor-pointer w-5 h-5" src='/images/map/layericon/Layer_Select_BTN.png' onClick={()=>{handleLayerImgClick(node.text, node.id)}} alt={node.text}></img></span> : null}
{imageVisible ? depth > 0 && <span><img className="cursor-pointer w-5 h-5" src='/images/map/layericon/Layer_Select_BTN.png' onClick={()=>{handleLayerImgClick(node.text, node.id, node.data.lyrTyNm)}} alt={node.text}></img></span> : null}
</div>
)}
sort={(a, b) => {