From d5c967e9ad47b5ab91ddf0a5e5b068d70325b386 Mon Sep 17 00:00:00 2001 From: swcho Date: Wed, 23 Jul 2025 17:45:06 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat,=20remove:=20-=20SelectBox=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=EC=97=90=20selectContentClass=20pro?= =?UTF-8?q?ps=20=EC=B6=94=EA=B0=80=20(=EB=93=9C=EB=A1=AD=EB=8B=A4=EC=9A=B4?= =?UTF-8?q?=EC=97=90=20z=20index=20=EA=B0=92=EC=9D=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=A8)=20-=20SelectBox2=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/select/index-2.tsx | 45 ------------------- .../src/ui/select/index.tsx | 4 +- 2 files changed, 3 insertions(+), 46 deletions(-) delete mode 100644 packages/common/business_components/src/ui/select/index-2.tsx diff --git a/packages/common/business_components/src/ui/select/index-2.tsx b/packages/common/business_components/src/ui/select/index-2.tsx deleted file mode 100644 index 8ff1f4582..000000000 --- a/packages/common/business_components/src/ui/select/index-2.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @remarks - * 이 버전은 SearchModal에서 사용하기 위해 `SelectContent`의 z-index를 `z-[101]`로 수정하였습니다. - */ -import { Label } from "@common/components"; -import React from "react"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./lib/selectBox"; - -/** 차트 기본 스타일 */ -interface SelectBox1 { - text:string, - val:string|number -} - -const SelectBox2 = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes & { - label:string, - selectClass:string|undefined, - className:string, - selectArray:SelectBox1[], - onSelectValue:(val:string|number)=>void, - value?: string|number - } ->(({ label, className, selectClass, selectArray, onSelectValue, value }, ref)=>{ - const placeHolder = selectArray?.[0]?.text ?? ""; - - return ( -
- {label && } - -
- ) -}) - -export { SelectBox2 }; diff --git a/packages/common/business_components/src/ui/select/index.tsx b/packages/common/business_components/src/ui/select/index.tsx index d09e3023a..82db6da45 100644 --- a/packages/common/business_components/src/ui/select/index.tsx +++ b/packages/common/business_components/src/ui/select/index.tsx @@ -27,6 +27,7 @@ const SelectBox = React.forwardRef< onSelectValue: (val: string | number) => void; value?: string | number; readOnly?: boolean; // readOnly 속성 추가 + selectContentClass?: string; } >( ( @@ -38,6 +39,7 @@ const SelectBox = React.forwardRef< onSelectValue, value, readOnly = false, + selectContentClass, }, ref, ) => { @@ -87,7 +89,7 @@ const SelectBox = React.forwardRef< > - + {visibleItems.map((selectArray) => ( {selectArray.text} From 523925459c6fac939f611d2ade69e73a5cd21ae7 Mon Sep 17 00:00:00 2001 From: jyha00 Date: Thu, 24 Jul 2025 19:28:20 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=EB=B0=94=EC=B0=A8=ED=8A=B8=20=ED=8F=AC?= =?UTF-8?q?=EB=A7=A4=ED=84=B0=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business_components/src/ui/chart/BarChart.tsx | 2 ++ .../src/ui/chart/lib/function.tsx | 12 ++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 packages/common/business_components/src/ui/chart/lib/function.tsx diff --git a/packages/common/business_components/src/ui/chart/BarChart.tsx b/packages/common/business_components/src/ui/chart/BarChart.tsx index 218ebac34..79aa61c98 100644 --- a/packages/common/business_components/src/ui/chart/BarChart.tsx +++ b/packages/common/business_components/src/ui/chart/BarChart.tsx @@ -6,6 +6,7 @@ import { type ChartConfig } from "./lib/chart"; import type { CSSProperties } from "react"; +import { formatCommaNumber } from "./lib/function"; const customStyles = { legendContainer: { @@ -119,6 +120,7 @@ export default function Chart({chartConfig=undefined, chartData=[], chartTitle=' fontWeight={500} domain={[0, globalMax]} ticks={ticks} + tickFormatter={(value) => formatCommaNumber(value)} label={yFieldText ? { value: yFieldText, className:"text-[15px] font-bold", position: 'insideLeft', angle: -90, offset: -30 } : undefined} /> }/> diff --git a/packages/common/business_components/src/ui/chart/lib/function.tsx b/packages/common/business_components/src/ui/chart/lib/function.tsx new file mode 100644 index 000000000..dc1921f0a --- /dev/null +++ b/packages/common/business_components/src/ui/chart/lib/function.tsx @@ -0,0 +1,12 @@ +// 숫자입력시 , 삽입 +export const formatCommaNumber = ( + value: number | string | undefined | null +): string => { + if (value === undefined || value === null || value === "") return ""; + const num = Number(value); + // 숫자로 변환할 수 없는 값이 들어올 경우 빈 문자열을 반환하여 예상치 못한 "NaN" 출력을 방지합니다. + if (isNaN(num)) { + return ""; + } + return num.toLocaleString(); +}; \ No newline at end of file From 6492ad5500dce7ed8c425fcaead726afc5eaa6bc Mon Sep 17 00:00:00 2001 From: swcho Date: Thu, 24 Jul 2025 20:01:41 +0900 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20Gis.js=20featureId=20=EC=B0=BE?= =?UTF-8?q?=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business_components/src/ui/map/Gis.js | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/common/business_components/src/ui/map/Gis.js b/packages/common/business_components/src/ui/map/Gis.js index a723b2340..5386207d8 100644 --- a/packages/common/business_components/src/ui/map/Gis.js +++ b/packages/common/business_components/src/ui/map/Gis.js @@ -86,20 +86,28 @@ function Gis({ foundFeature = data; } else { // 아니면 featureId로 맵에서 Feature 인스턴스를 찾아서 사용 - let featureId + let featureId = data.fid; const layerName = layerNmRef.current if (layerName === '하수재이용시설') { featureId = data.searchPk; - } else if (layerName === '빗물이용시설'|| layerName == '중수도시설') { + } else if (layerName === '빗물이용시설' || layerName == '중수도시설') { featureId = data.bdstInfoSn; - } else if (layerName === '하수처리시설') { + } else if (layerName === '하수처리시설') { featureId = data.bscFctCd; - } else if (layerName === '온배수시설' ) { + } else if (layerName === '온배수시설') { featureId = data.bdstRuseFcltSn; - } else { + } 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) { From 8353800dace5262de6276e24566640cb1a0d7bde Mon Sep 17 00:00:00 2001 From: ljpark Date: Thu, 24 Jul 2025 22:00:58 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20LineBarChar.tsx=20Null=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/business_components/src/ui/chart/LineBarChart.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/common/business_components/src/ui/chart/LineBarChart.tsx b/packages/common/business_components/src/ui/chart/LineBarChart.tsx index 64a7d5bce..d81d6e2c8 100644 --- a/packages/common/business_components/src/ui/chart/LineBarChart.tsx +++ b/packages/common/business_components/src/ui/chart/LineBarChart.tsx @@ -94,6 +94,7 @@ export default function LineBarchart({ // 데이터의 최대값 계산 const getMaxValue = (data: any[], keyPrefix: string) => { + if (!data || data.length === 0) return 0; return Math.max(...data.map(item => Object.keys(item) .filter(key => key.includes(keyPrefix)) From a4467394329463ffbdf27f6225f7068ea060ccdb Mon Sep 17 00:00:00 2001 From: swcho Date: Fri, 25 Jul 2025 00:21:07 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20-=20gis.select.js=20=ED=94=BC?= =?UTF-8?q?=EC=B2=98=20=EB=8B=A4=EC=A4=91=20=EC=85=80=EB=A0=89=ED=8A=B8=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20-=20Gis.js=20?= =?UTF-8?q?=EC=83=81=EB=A5=98=EA=B4=80=EB=A1=9C=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80=20-=20GisLonLa?= =?UTF-8?q?t=20=EC=A3=BC=EC=84=9D=20=EC=B2=98=EB=A6=AC(=EC=9C=84=EA=B2=BD?= =?UTF-8?q?=EB=8F=84=20=ED=91=9C=EC=8B=9CX)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business_components/src/ui/map/Gis.js | 58 ++++++++++++++++++- .../src/ui/map/lib/gis.select.js | 13 +++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/packages/common/business_components/src/ui/map/Gis.js b/packages/common/business_components/src/ui/map/Gis.js index 5386207d8..fb0529828 100644 --- a/packages/common/business_components/src/ui/map/Gis.js +++ b/packages/common/business_components/src/ui/map/Gis.js @@ -20,6 +20,62 @@ import GisApp from './lib/gis.core'; export const GisContext = createContext({ gisCore: null, gisMap: null, treeData: null, checkedLayerIds: null }); export const useGisContext = () => useContext(GisContext); +export async function searchUpperPpls(fcltMngNo) { + const BASE_URL = process.env.NEXT_PUBLIC_SERVER_API_URL || ''; + + const res = await fetch(`${BASE_URL}/v1/fcltmhl/upperPpls/${fcltMngNo}`, { + method: "GET", + }); + if (res.ok) { + const data = await res.json(); + return data; + } + throw new Error('Failed to fetch data'); + console.log('상류관로 조회 결과:', res); + + const select = GisApp.Module.select; + if (!select || !Array.isArray(res)) return; + + const gisMap = GisApp.Module.core?.map; + if (!gisMap) return; + + let foundFeature = null; + + res.forEach(item => { + const pplMngNo = item.ppl_mng_no.trim(); + + gisMap.getLayers().getArray().filter(e => e.get("lyrTyNm") == 'tb_ms_swage_ppl').forEach(layer => { + const source = layer.getSource?.(); + if (source?.getFeatures) { + const features = source.getFeatures(); + for (const f of features) { + if (f.values_.fclt_mng_no.trim() === pplMngNo) { + foundFeature = f; + break; + } + } + } + }); + + if (foundFeature) select.selectMultiFeature(foundFeature, true); + }); + + console.log('찾은 피쳐:', foundFeature); + if (!foundFeature) alert(`해당 맨홀의 상류관로를 찾을 수 없습니다.`); + + let geometry = foundFeature?.getGeometry(); + if (geometry) { + let extent = geometry.getExtent(); + + gisMap.getView().fit(extent, { + duration: 300, + padding: [50, 50, 50, 50], + maxZoom: 14, + constrainResolution: true, + nearest: true, + }); + } +} function Gis({ isOpen, @@ -418,7 +474,7 @@ function Gis({ onFeatureSelect={handleFeatureSelect} /> )} - + {/* */} diff --git a/packages/common/business_components/src/ui/map/lib/gis.select.js b/packages/common/business_components/src/ui/map/lib/gis.select.js index 21ab39609..d0209a6ed 100644 --- a/packages/common/business_components/src/ui/map/lib/gis.select.js +++ b/packages/common/business_components/src/ui/map/lib/gis.select.js @@ -429,6 +429,19 @@ GisOlSelect.prototype = { auto: auto, }); }, + /** + * 피처 다중 셀렉트 + */ + selectMultiFeature: function (feature, auto) { + let me = this; + me.selectedFeatures.push(feature); + me.selectInteraction.dispatchEvent({ + type: 'select', + selected: me.selectedFeatures, + deselected: [], + auto: auto, + }); + }, }; export default GisOlSelect; From 2862fdc9fdac63d3699e761607b249ef867048ec Mon Sep 17 00:00:00 2001 From: swcho Date: Fri, 25 Jul 2025 00:50:03 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20Gis.js=20fetch=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business_components/src/ui/map/Gis.js | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/packages/common/business_components/src/ui/map/Gis.js b/packages/common/business_components/src/ui/map/Gis.js index fb0529828..90bd50fa4 100644 --- a/packages/common/business_components/src/ui/map/Gis.js +++ b/packages/common/business_components/src/ui/map/Gis.js @@ -20,28 +20,39 @@ import GisApp from './lib/gis.core'; export const GisContext = createContext({ gisCore: null, gisMap: null, treeData: null, checkedLayerIds: null }); export const useGisContext = () => useContext(GisContext); -export async function searchUpperPpls(fcltMngNo) { - const BASE_URL = process.env.NEXT_PUBLIC_SERVER_API_URL || ''; +export const searchUpperPpls = async (fcltMngNo) => { + const BASE_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || ''; const res = await fetch(`${BASE_URL}/v1/fcltmhl/upperPpls/${fcltMngNo}`, { method: "GET", }); + + let data = null; if (res.ok) { - const data = await res.json(); - return data; + try { + // 응답이 비어있는지 확인 + const contentLength = res.headers.get('content-length'); + if (contentLength === '0') alert(`해당 맨홀의 상류관로를 찾을 수 없습니다.`); + + // 응답 텍스트를 먼저 가져와서 빈 문자열인지 확인 + const text = await res.text(); + if (!text || text.trim() === '') alert(`해당 맨홀의 상류관로를 찾을 수 없습니다.`); + + // JSON 파싱 시도 + data = JSON.parse(text); + } catch (error) { + console.error('JSON parsing error:', error); + alert(`해당 맨홀의 상류관로를 찾을 수 없습니다.`); + } } - throw new Error('Failed to fetch data'); - console.log('상류관로 조회 결과:', res); const select = GisApp.Module.select; - if (!select || !Array.isArray(res)) return; const gisMap = GisApp.Module.core?.map; - if (!gisMap) return; let foundFeature = null; - res.forEach(item => { + data.forEach(item => { const pplMngNo = item.ppl_mng_no.trim(); gisMap.getLayers().getArray().filter(e => e.get("lyrTyNm") == 'tb_ms_swage_ppl').forEach(layer => { @@ -60,7 +71,6 @@ export async function searchUpperPpls(fcltMngNo) { if (foundFeature) select.selectMultiFeature(foundFeature, true); }); - console.log('찾은 피쳐:', foundFeature); if (!foundFeature) alert(`해당 맨홀의 상류관로를 찾을 수 없습니다.`); let geometry = foundFeature?.getGeometry(); @@ -75,7 +85,8 @@ export async function searchUpperPpls(fcltMngNo) { nearest: true, }); } -} +}; + function Gis({ isOpen,