diff --git a/apps/fo/app/components/common/CalcRainEffect.tsx b/apps/fo/app/components/common/CalcRainEffect.tsx index 3ea198016..898bea0ba 100644 --- a/apps/fo/app/components/common/CalcRainEffect.tsx +++ b/apps/fo/app/components/common/CalcRainEffect.tsx @@ -30,18 +30,18 @@ export default function CalcRainEffect(data: any, weather = 'ALL') { rtnDataSunny.push(item); } else if (rainEffectStd >= 0) { // 강우일 + 강우영향일 item.rainEffectDay = 1; - if (idx > 1) { - // 전날 비가 왔고 오늘 강우량 3미만인 경우 전날 강우량이 3이상이면 오늘 toBeInfoRnDay을 전날 강우량으로 설정 - if (data[idx - 1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx - 1]?.infoRnDay.toString().trim()) >= 3) { - data[idx]!.toBeInfoRnDay = data[idx - 1]!.infoRnDay; - } - } if (idx > 2) { // 전전날 비가 왔고 오늘 강우량 3미만인 경우 전전날 강우량이 3이상이면 오늘 toBeInfoRnDay을 전전날 강우량으로 설정 if (data[idx - 2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx - 2]?.infoRnDay.toString().trim()) >= 3) { data[idx]!.toBeInfoRnDay = data[idx - 2]!.infoRnDay; } } + if (idx > 1) { + // 전날 비가 왔고 오늘 강우량 3미만인 경우 전날 강우량이 3이상이면 오늘 toBeInfoRnDay을 전날 강우량으로 설정 + if (data[idx - 1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx - 1]?.infoRnDay.toString().trim()) >= 3) { + data[idx]!.toBeInfoRnDay = data[idx - 1]!.infoRnDay; + } + } rtnDataRain.push(item); } diff --git a/apps/fo/app/pages/(with-layout)/facilityPrecipitation/page.tsx b/apps/fo/app/pages/(with-layout)/facilityPrecipitation/page.tsx index 0f29a28c4..42dbb1be1 100644 --- a/apps/fo/app/pages/(with-layout)/facilityPrecipitation/page.tsx +++ b/apps/fo/app/pages/(with-layout)/facilityPrecipitation/page.tsx @@ -96,7 +96,9 @@ export default function FacilityPrecipitation() { const [operationValue, setOperationValue] = useState("0"); // 조회기간 const [searchYear, setSearchYear] = useState(defaultSearchYear); - + // 엑셀다운로드 트리거 + const [isExcelDownClick, setIsExcelDownClick] = useState(false); + const excelWaitRef = useRef(false); /** * 페이지 함수 */ @@ -144,6 +146,17 @@ export default function FacilityPrecipitation() { }, [isInit, initializeCommonData, searchFacilityPrecipitationList, defaultSearchYear]); useEffect(() => { + if (!isExcelDownClick) return; + + if (isLoading) { + excelWaitRef.current = true; + return; + } + + if (!excelWaitRef.current) { + return; + } + if (excelList && excelList.length > 0) { downloadExcel({ data: excelList as unknown as JSON[], @@ -151,8 +164,12 @@ export default function FacilityPrecipitation() { sheetNameArray: ['시설별 강수현황'], headerRange: 'A1:N1' }); + } else { + alert("조회된 결과가 없습니다."); } - }, [excelList]); + setIsExcelDownClick(false); + excelWaitRef.current = false; + }, [excelList, isExcelDownClick, isLoading]); useEffect(() => { if (facilityPrecipitation.length > 0) { @@ -196,23 +213,25 @@ export default function FacilityPrecipitation() { // 엑셀다운로드 const excelDownload = useCallback((searchReturn: ReturnType) => { - if (ref.current.partValue === 'A') { // 행정별 - if (!ref.current.sidoValue || ref.current.sidoValue === '0') { - alert('엑셀 다운로드는 시도 조건을 선택한 후 이용 가능합니다.'); - return; - } - } else if (ref.current.partValue === 'R') { // 유역별 - if (!ref.current.regionValue || ref.current.regionValue === '0') { - alert('엑셀 다운로드는 유역 조건을 선택한 후 이용 가능합니다.'); - return; - } - } else if (ref.current.partValue === 'G') { // 환경청별 - if (!ref.current.envPartValue || ref.current.envPartValue === '0') { - alert('엑셀 다운로드는 환경청 조건을 선택한 후 이용 가능합니다.'); - return; - } - } + // if (ref.current.partValue === 'A') { // 행정별 + // if (!ref.current.sidoValue || ref.current.sidoValue === '0') { + // alert('엑셀 다운로드는 시도 조건을 선택한 후 이용 가능합니다.'); + // return; + // } + // } else if (ref.current.partValue === 'R') { // 유역별 + // if (!ref.current.regionValue || ref.current.regionValue === '0') { + // alert('엑셀 다운로드는 유역 조건을 선택한 후 이용 가능합니다.'); + // return; + // } + // } else if (ref.current.partValue === 'G') { // 환경청별 + // if (!ref.current.envPartValue || ref.current.envPartValue === '0') { + // alert('엑셀 다운로드는 환경청 조건을 선택한 후 이용 가능합니다.'); + // return; + // } + // } + excelWaitRef.current = false; searchFacilityPrecipitation(searchReturn, 1, 10000); + setIsExcelDownClick(true); }, [searchFacilityPrecipitation]); // 페이지 변경 diff --git a/apps/fo/app/pages/(with-layout)/facilityWaterQlty/modal/page.tsx b/apps/fo/app/pages/(with-layout)/facilityWaterQlty/modal/page.tsx index 470a44e4c..c1a6afdf8 100644 --- a/apps/fo/app/pages/(with-layout)/facilityWaterQlty/modal/page.tsx +++ b/apps/fo/app/pages/(with-layout)/facilityWaterQlty/modal/page.tsx @@ -447,7 +447,9 @@ export default function WaterQualityModal({ fcltyName = '', facilityCd = '', sea

수질 TMS

-

({msrmtDate ? msrmtDate.substring(0, 4) + '-' + msrmtDate.substring(4, 6) + '-' + msrmtDate.substring(6, 8) : yesterDayStr})

+

+ ({msrmtDate ? msrmtDate.substring(0, 4) + '-' + msrmtDate.substring(4, 6) + '-' + msrmtDate.substring(6, 8) : yesterDayStr}) +

(false); - const [excelTrigger, setExcelTrigger] = useState(false); + // 엑셀다운로드 트리거 + const [isExcelDownClick, setIsExcelDownClick] = useState(false); + const excelWaitRef = useRef(false); // 그리드 관련 const [resetPage, setResetPage] = useState(false); const searchInputRef = useRef(null); @@ -152,7 +154,16 @@ export default function ProcessFacilitySearch() { }, [isInit, initializeCommonData, searchFacilityWaterQltyList, searchFcltyQltyList, initTrigger]); useEffect(() => { - if (!excelTrigger) return; + if (!isExcelDownClick) return; + + if (isLoading) { + excelWaitRef.current = true; + return; + } + + if (!excelWaitRef.current) { + return; + } if (excelList && excelList.length > 0) { downloadExcelFormat( @@ -165,8 +176,12 @@ export default function ProcessFacilitySearch() { decimalArray3: [13, 14, 18, 19] } ); + } else { + alert("조회된 결과가 없습니다."); } - }, [excelList, excelTrigger]); + setIsExcelDownClick(false); + excelWaitRef.current = false; + }, [excelList, isExcelDownClick, isLoading]); const chkVal = useCallback((returntype: ReturnType) => { // setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]") @@ -192,8 +207,9 @@ export default function ProcessFacilitySearch() { } } - setExcelTrigger(true); + excelWaitRef.current = false; searchFcltyQltyList(ref.current, 1, 10000); + setIsExcelDownClick(true); }, [searchFcltyQltyList]); const handlePageChange = useCallback((page: number) => { diff --git a/apps/fo/app/pages/(with-layout)/flowRate/modal/page.tsx b/apps/fo/app/pages/(with-layout)/flowRate/modal/page.tsx index 4e0fffeb5..b214e0a48 100644 --- a/apps/fo/app/pages/(with-layout)/flowRate/modal/page.tsx +++ b/apps/fo/app/pages/(with-layout)/flowRate/modal/page.tsx @@ -34,6 +34,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st const { btnClass } = Common; const [copyYearList, setCopyYearList] = useState([]); const [isLoading, setIsLoading] = useState(true); + const [activeTab, setActiveTab] = useState("tab_term_year"); const prevExcelListRef = useRef(null); const { modalFlowRateListYear, upHeadListFlowRateModalYear, } = FlowRateModal; @@ -183,10 +184,6 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st fetchData(); }, [props.facilityCd, props.searchYear, searchFlowRateModalList]); - if (isLoading) { - return
로딩 중...
; - } - const excelDownload = () => { const excelDownList: modalExcelType[] = []; if (copyYearList.length > 0) { @@ -206,14 +203,45 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st if (excelDownList && excelDownList.length > 0) { downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.searchYear + '년 ' + props.fcltyName + ' 유량현황', sheetNameArray: [props.fcltyName + ' 유량현황'], headerRange: 'A1:H1' }); } else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) { - alert('다운받을 데이터가 없습니다.'); + alert('조회된 결과가 없습니다.'); } prevExcelListRef.current = excelDownList; } + // const rainCellClassName = useCallback( + // (row: FlowRateModalInterface, headId: string, rowIndex: number) => { + // if (activeTab !== "tab_term_rain") return ""; + // if (headId !== "infoRnDay") return ""; + // if (rowIndex < 3) return ""; + + // const raw = row.infoRnDay; + // const value = typeof raw === "string" ? Number(raw.replace(/,/g, "").trim()) : Number(raw); + // if (!Number.isFinite(value)) return ""; + // return value > 3 ? "bg-red-50 font-semibold" : ""; + // }, + // [activeTab], + // ); + + const rainRowClassName = useCallback( + (row: FlowRateModalInterface, rowIndex: number) => { + if (activeTab !== "tab_term_rain") return ""; + if (rowIndex < 3) return ""; + + const raw = row.infoRnDay; + const value = typeof raw === "string" ? Number(raw.replace(/,/g, "").trim()) : Number(raw); + if (!Number.isFinite(value)) return ""; + return value > 3 ? "bg-slate-50" : ""; + }, + [activeTab], + ); + + if (isLoading) { + return
로딩 중...
; + } + return ( <> - + @@ -337,7 +365,8 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st />
{ }} className="h-[370px]" boldArray={[0, 1, 2]} /> + cellClick={undefined} onPageChange={() => { }} className="h-[370px]" boldArray={[0, 1, 2]} + rowClassName={rainRowClassName} />
@@ -346,4 +375,4 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st ); -} \ No newline at end of file +} diff --git a/apps/fo/app/pages/(with-layout)/flowRate/page.tsx b/apps/fo/app/pages/(with-layout)/flowRate/page.tsx index c80d46699..527c8d45e 100644 --- a/apps/fo/app/pages/(with-layout)/flowRate/page.tsx +++ b/apps/fo/app/pages/(with-layout)/flowRate/page.tsx @@ -73,6 +73,7 @@ export default function ProcessFacilitySearch() { const [fcltyNm, setFcltyNm] = useState(""); const [fcltyCd, setFcltyCd] = useState(""); const [isExcelDownClick, setIsExcelDownClick] = useState(false); + const excelWaitRef = useRef(false); const [initTrigger, setInitTrigger] = useState(false); const searchFlowRate = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => { @@ -154,15 +155,23 @@ export default function ProcessFacilitySearch() { useEffect(() => { if(!isExcelDownClick) return; - const timer = setTimeout(() => { - if (excelList && excelList.length > 0) { - downloadExcelFormat({ data: JSON.parse(JSON.stringify(excelList)), fileName: '시설별 유량현황', sheetNameArray: ['시설별 유량현황'], headerRange: 'A1:O1', decimalArray0: [9,10,11,12,13,14] }); - } else { - alert('조회된 결과가 없습니다.'); - } - }, 1000); // 약간의 지연을 두고 다운로드 실행 - return () => clearTimeout(timer); - }, [excelList, isExcelDownClick]); + if (isLoading) { + excelWaitRef.current = true; + return; + } + + if (!excelWaitRef.current) { + return; + } + + if (excelList && excelList.length > 0) { + downloadExcelFormat({ data: JSON.parse(JSON.stringify(excelList)), fileName: '시설별 유량현황', sheetNameArray: ['시설별 유량현황'], headerRange: 'A1:O1', decimalArray0: [9,10,11,12,13,14] }); + } else { + alert('조회된 결과가 없습니다.'); + } + setIsExcelDownClick(false); + excelWaitRef.current = false; + }, [excelList, isExcelDownClick, isLoading]); const ref = useRef({ partValue: '', @@ -200,6 +209,7 @@ export default function ProcessFacilitySearch() { } } + excelWaitRef.current = false; searchFlowRate(ref.current, 1, 10000); setIsExcelDownClick(true); }, [searchFlowRate]); diff --git a/apps/fo/app/pages/(with-layout)/planSewage/page.tsx b/apps/fo/app/pages/(with-layout)/planSewage/page.tsx index 41b541ce9..3ad19c1bb 100644 --- a/apps/fo/app/pages/(with-layout)/planSewage/page.tsx +++ b/apps/fo/app/pages/(with-layout)/planSewage/page.tsx @@ -93,8 +93,10 @@ export default function PlanSewage() { const [searchYear, setSearchYear] = useState(defaultSearchYear); const [initTrigger, setInitTrigger] = useState(false); + // 엑셀다운로드 트리거 + const [isExcelDownClick, setIsExcelDownClick] = useState(false); + const excelWaitRef = useRef(false); - const [excelTrigger, setExcelTrigger] = useState(false); /** * 페이지 함수 */ @@ -119,7 +121,16 @@ export default function PlanSewage() { } useEffect(() => { - if (!excelTrigger) return; + if (!isExcelDownClick) return; + + if (isLoading) { + excelWaitRef.current = true; + return; + } + + if (!excelWaitRef.current) { + return; + } if (excelList && excelList.length > 0) { downloadExcel({ @@ -128,8 +139,12 @@ export default function PlanSewage() { sheetNameArray: ['계획하수량 산정지표 현황'], headerRange: 'A1:M1' }); + } else { + alert("조회된 결과가 없습니다."); } - }, [excelList, excelTrigger]); + setIsExcelDownClick(false); + excelWaitRef.current = false; + }, [excelList, isExcelDownClick, isLoading]); /** * 콜백함수 @@ -200,8 +215,9 @@ export default function PlanSewage() { } } + excelWaitRef.current = false; searchPlanSewage(searchReturn, 1, 10000); - setExcelTrigger(true); + setIsExcelDownClick(true); }, [searchPlanSewage]); // 페이지 변경 diff --git a/apps/fo/app/pages/(with-layout)/processArea/page.tsx b/apps/fo/app/pages/(with-layout)/processArea/page.tsx index e3b6fc3da..d4fb0e973 100644 --- a/apps/fo/app/pages/(with-layout)/processArea/page.tsx +++ b/apps/fo/app/pages/(with-layout)/processArea/page.tsx @@ -70,6 +70,9 @@ export default function ProcessArea() { const [resetPage, setResetPage] = useState(false); const [searchYearValue, setSearchYearValue] = useState(defaultSearchYear); + + const [isExcelDownClick, setIsExcelDownClick] = useState(false); + const excelWaitRef = useRef(false); const ref = useRef({ partValue: '', @@ -126,6 +129,17 @@ export default function ProcessArea() { }, [isInit, initializeCommonData, searchProcessAreaList, defaultSearchYear]); useEffect(() => { + if(!isExcelDownClick) return; + + if (isLoading) { + excelWaitRef.current = true; + return; + } + + if (!excelWaitRef.current) { + return; + } + if (excelList && excelList.length > 0) { downloadExcel({ data: excelList as unknown as JSON[], @@ -133,28 +147,34 @@ export default function ProcessArea() { sheetNameArray: ['처리구역정보'], headerRange: 'A1:W1' }); + } else { + alert('조회된 결과가 없습니다.'); } - }, [excelList]); + setIsExcelDownClick(false); + excelWaitRef.current = false; + }, [excelList, isExcelDownClick, isLoading]); const excelDownload = useCallback(() => { - if (ref.current.partValue === 'A') { // 행정별 - if (!ref.current.sidoValue || ref.current.sidoValue === '0') { - alert('엑셀 다운로드는 시도 조건을 선택한 후 이용 가능합니다.'); - return; - } - } else if (ref.current.partValue === 'R') { // 유역별 - if (!ref.current.regionValue || ref.current.regionValue === '0') { - alert('엑셀 다운로드는 유역 조건을 선택한 후 이용 가능합니다.'); - return; - } - } else if (ref.current.partValue === 'G') { // 환경청별 - if (!ref.current.envPartValue || ref.current.envPartValue === '0') { - alert('엑셀 다운로드는 환경청 조건을 선택한 후 이용 가능합니다.'); - return; - } - } + // if (ref.current.partValue === 'A') { // 행정별 + // if (!ref.current.sidoValue || ref.current.sidoValue === '0') { + // alert('엑셀 다운로드는 시도 조건을 선택한 후 이용 가능합니다.'); + // return; + // } + // } else if (ref.current.partValue === 'R') { // 유역별 + // if (!ref.current.regionValue || ref.current.regionValue === '0') { + // alert('엑셀 다운로드는 유역 조건을 선택한 후 이용 가능합니다.'); + // return; + // } + // } else if (ref.current.partValue === 'G') { // 환경청별 + // if (!ref.current.envPartValue || ref.current.envPartValue === '0') { + // alert('엑셀 다운로드는 환경청 조건을 선택한 후 이용 가능합니다.'); + // return; + // } + // } + excelWaitRef.current = false; searchProcessArea(ref.current, 1, 10000); + setIsExcelDownClick(true); }, [searchProcessArea]); const handlePageChange = useCallback((pageNo: number) => { diff --git a/apps/fo/app/pages/(with-layout)/processFacility/page.tsx b/apps/fo/app/pages/(with-layout)/processFacility/page.tsx index b239970e0..995f2e8e9 100644 --- a/apps/fo/app/pages/(with-layout)/processFacility/page.tsx +++ b/apps/fo/app/pages/(with-layout)/processFacility/page.tsx @@ -89,6 +89,8 @@ export default function ProcessFacilitySearch() { const [partValue, setPartValue] = useState("A"); // const [widthSize, setWidthSize] = useState("w-[120%]"); const [upHeadList, setUpheadList] = useState(upHeadList1); + const [isExcelDownClick, setIsExcelDownClick] = useState(false); + const excelWaitRef = useRef(false); /** * 모달 상태 변수 @@ -150,10 +152,25 @@ export default function ProcessFacilitySearch() { }, [partValue, upHeadList1, upHeadList2, upHeadList3]); useEffect(() => { + if (!isExcelDownClick) return; + + if (isLoading) { + excelWaitRef.current = true; + return; + } + + if (!excelWaitRef.current) { + return; + } + if (excelList && excelList.length > 0) { downloadExcel({ data: excelList as unknown as JSON[], fileName: '처리시설 시설정보', sheetNameArray: ['처리시설 시설정보'], headerRange: 'A1:P1' }); + } else { + alert('조회된 결과가 없습니다.'); } - }, [excelList]); + setIsExcelDownClick(false); + excelWaitRef.current = false; + }, [excelList, isExcelDownClick, isLoading]); const searchFcltyList = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=10) => { let nameCd, partStr @@ -236,24 +253,26 @@ export default function ProcessFacilitySearch() { } const excelDownload = useCallback(() => { - if (ref.current.partValue === 'A') { // 행정별 - if (!ref.current.sidoValue || ref.current.sidoValue === '0') { - alert('엑셀 다운로드는 시도 조건을 선택한 후 이용 가능합니다.'); - return; - } - } else if (ref.current.partValue === 'R') { // 유역별 - if (!ref.current.regionValue || ref.current.regionValue === '0') { - alert('엑셀 다운로드는 유역 조건을 선택한 후 이용 가능합니다.'); - return; - } - } else if (ref.current.partValue === 'G') { // 환경청별 - if (!ref.current.envPartValue || ref.current.envPartValue === '0') { - alert('엑셀 다운로드는 환경청 조건을 선택한 후 이용 가능합니다.'); - return; - } - } + // if (ref.current.partValue === 'A') { // 행정별 + // if (!ref.current.sidoValue || ref.current.sidoValue === '0') { + // alert('엑셀 다운로드는 시도 조건을 선택한 후 이용 가능합니다.'); + // return; + // } + // } else if (ref.current.partValue === 'R') { // 유역별 + // if (!ref.current.regionValue || ref.current.regionValue === '0') { + // alert('엑셀 다운로드는 유역 조건을 선택한 후 이용 가능합니다.'); + // return; + // } + // } else if (ref.current.partValue === 'G') { // 환경청별 + // if (!ref.current.envPartValue || ref.current.envPartValue === '0') { + // alert('엑셀 다운로드는 환경청 조건을 선택한 후 이용 가능합니다.'); + // return; + // } + // } + excelWaitRef.current = false; searchFcltyList(ref.current, 1, 10000); + setIsExcelDownClick(true); }, [searchFcltyList]); // 모달 닫기 @@ -316,4 +335,4 @@ export default function ProcessFacilitySearch() { )} ); -} \ No newline at end of file +} diff --git a/apps/fo/app/pages/(with-layout)/rdi/page.tsx b/apps/fo/app/pages/(with-layout)/rdi/page.tsx index d166e01a3..8f601c299 100644 --- a/apps/fo/app/pages/(with-layout)/rdi/page.tsx +++ b/apps/fo/app/pages/(with-layout)/rdi/page.tsx @@ -90,7 +90,9 @@ export default function Rdi() { // 조회기간 const [searchYear, setSearchYear] = useState(defaultSearchYear); // 엑셀 다운로드 트리거 - const [isInitExcelDownload, setIsInitExcelDownload] = useState(false); + const [isExcelDownClick, setIsExcelDownClick] = useState(false); + const excelWaitRef = useRef(false); + const [initTrigger, setInitTrigger] = useState(false); /** @@ -118,7 +120,17 @@ export default function Rdi() { } useEffect(() => { - if(!isInitExcelDownload) return ; + if(!isExcelDownClick) return ; + + if (isLoading) { + excelWaitRef.current = true; + return; + } + + if (!excelWaitRef.current) { + return; + } + if (excelList && excelList.length > 0) { downloadExcel({ data: excelList as unknown as JSON[], @@ -126,8 +138,12 @@ export default function Rdi() { sheetNameArray: ['RDII추정'], headerRange: 'A1:R1' }); + } else { + alert("조회된 결과가 없습니다."); } - }, [excelList, isInitExcelDownload]); + setIsExcelDownClick(false); + excelWaitRef.current = false; + }, [excelList, isExcelDownClick, isLoading]); /** * 콜백함수 @@ -180,25 +196,26 @@ export default function Rdi() { // 엑셀다운로드 const excelDownload = useCallback(() => { - if (ref.current.partValue === 'A') { // 행정별 - if (!ref.current.sidoValue || ref.current.sidoValue === '0') { - alert('엑셀 다운로드는 시도 조건을 선택한 후 이용 가능합니다.'); - return; - } - } else if (ref.current.partValue === 'R') { // 유역별 - if (!ref.current.regionValue || ref.current.regionValue === '0') { - alert('엑셀 다운로드는 유역 조건을 선택한 후 이용 가능합니다.'); - return; - } - } else if (ref.current.partValue === 'G') { // 환경청별 - if (!ref.current.envPartValue || ref.current.envPartValue === '0') { - alert('엑셀 다운로드는 환경청 조건을 선택한 후 이용 가능합니다.'); - return; - } - } + // if (ref.current.partValue === 'A') { // 행정별 + // if (!ref.current.sidoValue || ref.current.sidoValue === '0') { + // alert('엑셀 다운로드는 시도 조건을 선택한 후 이용 가능합니다.'); + // return; + // } + // } else if (ref.current.partValue === 'R') { // 유역별 + // if (!ref.current.regionValue || ref.current.regionValue === '0') { + // alert('엑셀 다운로드는 유역 조건을 선택한 후 이용 가능합니다.'); + // return; + // } + // } else if (ref.current.partValue === 'G') { // 환경청별 + // if (!ref.current.envPartValue || ref.current.envPartValue === '0') { + // alert('엑셀 다운로드는 환경청 조건을 선택한 후 이용 가능합니다.'); + // return; + // } + // } + excelWaitRef.current = false; searchRdi(ref.current, 1, 5000); - setIsInitExcelDownload(true); + setIsExcelDownClick(true); }, [searchRdi]); // 페이지 변경 diff --git a/apps/fo/app/pages/(with-layout)/sewageOccur/page.tsx b/apps/fo/app/pages/(with-layout)/sewageOccur/page.tsx index a7ff0df71..a9e990e82 100644 --- a/apps/fo/app/pages/(with-layout)/sewageOccur/page.tsx +++ b/apps/fo/app/pages/(with-layout)/sewageOccur/page.tsx @@ -101,6 +101,7 @@ export default function PlanSewage() { const [searchYear, setSearchYear] = useState(defaultSearchYear); // 엑셀다운로드 트리거 const [isExcelDownClick, setIsExcelDownClick] = useState(false); + const excelWaitRef = useRef(false); /** * 페이지 함수 @@ -151,21 +152,28 @@ export default function PlanSewage() { useEffect(() => { if(!isExcelDownClick) return ; - const timer = setTimeout(() => { - if (excelList && excelList.length > 0) { - downloadExcel({ - data: excelList as unknown as JSON[], - fileName: '오수발생량 추정', - sheetNameArray: ['오수발생량 추정'], - headerRange: 'A1:O1' - }); - } else { - alert("조회된 결과가 없습니다."); - } - }, 500); // 약간의 지연을 두고 다운로드 실행 + if (isLoading) { + excelWaitRef.current = true; + return; + } - return () => clearTimeout(timer); - }, [excelList, isInit, isExcelDownClick]); + if (!excelWaitRef.current) { + return; + } + + if (excelList && excelList.length > 0) { + downloadExcel({ + data: excelList as unknown as JSON[], + fileName: '오수발생량 추정', + sheetNameArray: ['오수발생량 추정'], + headerRange: 'A1:O1' + }); + } else { + alert("조회된 결과가 없습니다."); + } + setIsExcelDownClick(false); + excelWaitRef.current = false; + }, [excelList, isExcelDownClick, isLoading]); /** * 콜백함수 @@ -189,7 +197,8 @@ export default function PlanSewage() { break; } if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) { - searchSewageOccurList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined); + searchSewageOccurList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue + , fcltyName.trim() !== ""? fcltyName : undefined); } else { searchSewageOccurList(pageNo, pageCnt, searchYear); } @@ -219,6 +228,7 @@ export default function PlanSewage() { return; } } + excelWaitRef.current = false; searchFacilityPrecipitation(ref.current, 1, 5000); setIsExcelDownClick(true); }, [searchFacilityPrecipitation]); diff --git a/apps/fo/app/pages/(with-layout)/underWaterInput/page.tsx b/apps/fo/app/pages/(with-layout)/underWaterInput/page.tsx index 849689312..1b90b4584 100644 --- a/apps/fo/app/pages/(with-layout)/underWaterInput/page.tsx +++ b/apps/fo/app/pages/(with-layout)/underWaterInput/page.tsx @@ -106,6 +106,7 @@ export default function UnderWaterInput() { const [searchYear, setSearchYear] = useState(defaultSearchYear); // 엑셀다운로드 트리거 const [isExcelDownClick, setIsExcelDownClick] = useState(false); + const excelWaitRef = useRef(false); /** * 페이지 함수 @@ -156,20 +157,28 @@ export default function UnderWaterInput() { useEffect(() => { if(!isExcelDownClick) return ; - const timer = setTimeout(() => { - if (excelList && excelList.length > 0) { - downloadExcel({ - data: excelList as unknown as JSON[], - fileName: '지하수유입량 추정', - sheetNameArray: ['지하수유입량 추정'], - headerRange: 'A1:O1' - }); - } else { - alert("조회된 결과가 없습니다."); - } - }, 1000); // 약간의 지연을 두고 다운로드 실행 - return () => clearTimeout(timer); - }, [excelList, isExcelDownClick]); + if (isLoading) { + excelWaitRef.current = true; + return; + } + + if (!excelWaitRef.current) { + return; + } + + if (excelList && excelList.length > 0) { + downloadExcel({ + data: excelList as unknown as JSON[], + fileName: '지하수유입량 추정', + sheetNameArray: ['지하수유입량 추정'], + headerRange: 'A1:O1' + }); + } else { + alert("조회된 결과가 없습니다."); + } + setIsExcelDownClick(false); + excelWaitRef.current = false; + }, [excelList, isExcelDownClick, isLoading]); /** * 콜백함수 @@ -193,7 +202,8 @@ export default function UnderWaterInput() { break; } if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) { - searchUnderWaterList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined); + searchUnderWaterList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue + , fcltyName.trim() !== ""? fcltyName : undefined); } else { searchUnderWaterList(pageNo, pageCnt, searchYear); } @@ -223,6 +233,7 @@ export default function UnderWaterInput() { return; } } + excelWaitRef.current = false; searchFacilityPrecipitation(ref.current, 1, 5000); setIsExcelDownClick(true); }, [searchFacilityPrecipitation]); diff --git a/apps/fo/app/store/facilityWaterQlty/index.tsx b/apps/fo/app/store/facilityWaterQlty/index.tsx index 4a08b429a..676c0624c 100644 --- a/apps/fo/app/store/facilityWaterQlty/index.tsx +++ b/apps/fo/app/store/facilityWaterQlty/index.tsx @@ -28,9 +28,11 @@ export interface FacilityRdiiDetailProps { export interface FacilityWaterQltyProps { bscFctCd: string, bscFctNm: string, - msrDt: string - sidoNm: string, - sggNm: string, + msrDt: string, + sido: string, + gugun: string, + // sidoNm: string, + // sggNm: string, addr: string, fctCpc: number, inflAssctBfrWqltBod: string | '', @@ -147,8 +149,8 @@ const mainLabelArray: string[] = ['구분', '시도', '시군구', '용량별', // 시설수질리스트 헤더(행정별) const upHeadList1: TableUpperProps[] = [ { id: "C", title: "행정명", colSpan: 2, row: 0, widthPercent: 10 }, - { id: "sidoNm", title: "시도", row: 1, widthPercent: 5 }, - { id: "sggNm", title: "시군구", row: 1, widthPercent: 5 }, + { id: "sido", title: "시도", row: 1, widthPercent: 5 }, + { id: "gugun", title: "시군구", row: 1, widthPercent: 5 }, { id: "bscFctNm", title: "시설명", rowSpan: 2, row: 0, widthPercent: 10 }, { id: "addr", title: "주소", rowSpan: 2, row: 0 }, { id: "fctCpc", title: "시설용량(m³/일)", align: "right", rowSpan: 2, row: 0, widthPercent: 10 }, @@ -197,8 +199,8 @@ const upHeadList3: TableUpperProps[] = [ { id: "mdmbsn", title: "중권역", row: 1, widthPercent: 5 }, { id: "rgnNm", title: "환경청", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "D", title: "행정명", colSpan: 2, row: 0, widthPercent: 10 }, - { id: "sidoNm", title: "시도", upName: "upChangeRe2", row: 1, widthPercent: 5 }, - { id: "sggNm", title: "시군구", upName: "upChangeRe2", row: 1, widthPercent: 5 }, + { id: "sido", title: "시도", upName: "upChangeRe2", row: 1, widthPercent: 5 }, + { id: "gugun", title: "시군구", upName: "upChangeRe2", row: 1, widthPercent: 5 }, { id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 8 }, { id: "addr", title: "주소", row: 0, rowSpan: 2 }, { id: "fctCpc", title: "시설용량(m³/L)", align: "right", row: 0, rowSpan: 2, widthPercent: 5 }, @@ -466,16 +468,22 @@ export const facilityWaterQltyReducer = (set: SetFunc): FacilityWaterQltyActions //--------- const waterQltyList: any[] = []; let recordCount = 0; - for (let idx = 0; idx < pageSize; idx += 100) { - const tmpPageNo = Math.floor(idx / 100) + 1; - const tmpPageSize = Math.min(100, pageSize - idx); - const result = await fetchFacilityWaterQltyList(tmpPageNo, tmpPageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm); - if (result?.status === 200 && Array.isArray(result?.data)) { - waterQltyList.push(...result.data); - } - recordCount = result?.count || 0; - if (result?.count < tmpPageNo * tmpPageSize) { - break; // 더 이상 데이터가 없으면 중지 + if (pageSize < 5000) { + const res = await fetchFacilityWaterQltyList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm); + waterQltyList.push(...res.data); + recordCount = res.count; + } else { + for (let idx = 0; idx < pageSize; idx += 100) { + const tmpPageNo = Math.floor(idx / 100) + 1; + const tmpPageSize = Math.min(100, pageSize - idx); + const result = await fetchFacilityWaterQltyList(tmpPageNo, tmpPageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm); + if (result?.status === 200 && Array.isArray(result?.data)) { + waterQltyList.push(...result.data); + } + recordCount = result?.count || 0; + if (result?.count < tmpPageNo * tmpPageSize) { + break; // 더 이상 데이터가 없으면 중지 + } } } //------- @@ -527,8 +535,8 @@ export const facilityWaterQltyReducer = (set: SetFunc): FacilityWaterQltyActions waterQltyList.forEach(item => { dataFormSetting(item) item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, '')); - item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || ''; - item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; + // item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || ''; + // item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; item.inflAssctBfrWqltToc = Number(searchYear) < COD_YEAR ? "(" + item.inflAssctBfrWqltToc + ")" : item.inflAssctBfrWqltToc; item.efflWqltToc = Number(searchYear) < COD_YEAR ? "(" + item.efflWqltToc + ")" : item.efflWqltToc; excelDownList.push({ @@ -537,8 +545,8 @@ export const facilityWaterQltyReducer = (set: SetFunc): FacilityWaterQltyActions 단위유역: item.lgbsn, 중권역: item.mdmbsn, 환경청: item.rgnNm, - 시도: item.sidoNm, - 시군구: item.sggNm, + 시도: item.sido, + 시군구: item.gugun, 시설이름: item.bscFctNm, 주소: item.addr, "시설용량(m³/일)": CommaToNumber(item.fctCpc), @@ -559,8 +567,8 @@ export const facilityWaterQltyReducer = (set: SetFunc): FacilityWaterQltyActions waterQltyList.forEach((item: FacilityWaterQltyProps) => { dataFormSetting(item) item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, '')); - item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || ''; - item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; + // item.sidoNm = item.; + // item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; item.inflAssctBfrWqltToc = Number(searchYear) < COD_YEAR ? "(" + item.inflAssctBfrWqltToc + ")" : item.inflAssctBfrWqltToc; item.efflWqltToc = Number(searchYear) < COD_YEAR ? "(" + item.efflWqltToc + ")" : item.efflWqltToc; }); diff --git a/apps/fo/app/store/flowRate/index.tsx b/apps/fo/app/store/flowRate/index.tsx index 232755c1d..b097fc234 100644 --- a/apps/fo/app/store/flowRate/index.tsx +++ b/apps/fo/app/store/flowRate/index.tsx @@ -285,23 +285,30 @@ export const flowRateSearchReducer: (set: (fn: (state: FlowRateSearchType) => Fl //--------- const flowRateList: any[] = []; const results: any[] = []; - for (let idx = 0; idx < pageSize; idx += 100) { - const tmpPageNo = Math.floor(idx / 100) + 1; - const tmpPageSize = Math.min(100, pageSize - idx); - const result = await fetchFlowRateList( tmpPageNo, tmpPageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm); - results.push(result); - if (result?.count < tmpPageNo * tmpPageSize) { - break; // 더 이상 데이터가 없으면 중지 - } - } - console.log(results); - // 결과를 합치기 - - for (const res of results) { - if (res?.status === 200 && Array.isArray(res?.data)) { - flowRateList.push(...res.data); + if (pageSize < 5000) { + const res = await fetchFlowRateList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm); + flowRateList.push(...res.data); + results.push(res); + } else { + for (let idx = 0; idx < pageSize; idx += 100) { + const tmpPageNo = Math.floor(idx / 100) + 1; + const tmpPageSize = Math.min(100, pageSize - idx); + const result = await fetchFlowRateList( tmpPageNo, tmpPageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm); + results.push(result); + if (result?.count < tmpPageNo * tmpPageSize) { + break; // 더 이상 데이터가 없으면 중지 + } + } + // console.log(results); + // 결과를 합치기 + + for (const res of results) { + if (res?.status === 200 && Array.isArray(res?.data)) { + flowRateList.push(...res.data); + } } } + //--------- const recordCount = results[0]?.count || 0; //------- @@ -381,7 +388,7 @@ export const flowRateSearchReducer: (set: (fn: (state: FlowRateSearchType) => Fl const yearSunnyAmnt = sunnyDay > 0 ? sunnyInflAmnt / sunnyDay : 0; // 청천시 연평균유입유량 const yearSunnyBod = sunnyDay > 0 ? sunnyBod / sunnyDay : 0; // 청천시 연평균유입BOD - console.log(inflData); + //console.log(inflData); const rtnData = inflData.map((item: FlowRateModalProps) => { const targetWqItem = wqltData?.find(wqitem => wqitem.msrDt === item.msrDt.replaceAll('-', '')); const dayBod = targetWqItem ? Number(targetWqItem.inflAssctBfrWqltBod) : 0; @@ -397,7 +404,7 @@ export const flowRateSearchReducer: (set: (fn: (state: FlowRateSearchType) => Fl : item.msrDt, }; }); - console.log(rtnData); + //console.log(rtnData); set((state: FlowRateSearchType) => ({ ...state, FlowRateModal: { diff --git a/apps/fo/app/store/processFacility/index.tsx b/apps/fo/app/store/processFacility/index.tsx index 8fa38e5bc..240ad2d4d 100644 --- a/apps/fo/app/store/processFacility/index.tsx +++ b/apps/fo/app/store/processFacility/index.tsx @@ -418,7 +418,9 @@ const gridListFcltyWaterQltyInfo: fcltyWaterQltyInfoProps[] = [ */ export const fetchFacilityListInit = async (pageNo: number, pageSize: number, partValue?: string, nameCd?: string, fcltCpct?: string, oprtngSttsCd?: string, facilityPartValue?: string, facilityName?: string): Promise<{ data: facilityListProps[], count: number }> => { try { - const tailStr = partValue ? '/' + (partValue === 'G' ? 'A' : partValue) + '/' + nameCd + '/' + fcltCpct + '/' + oprtngSttsCd + '/' + facilityPartValue + (facilityName && facilityName !== '' ? '/' + facilityName : '') : ''; + const tailStr = partValue ? '/' + (partValue === 'G' ? 'A' : partValue) + '/' + nameCd + '/' + fcltCpct + '/' + oprtngSttsCd + + (facilityPartValue && facilityPartValue !== ''? '/' + facilityPartValue : '') + + (facilityName && facilityName !== ''? '/' + facilityName : '') : ''; const url = '/prcsFclt/info/' + pageNo + '/' + pageSize + tailStr; const res = await getFetch('fo', url); res.data.forEach((item: Record) => { diff --git a/apps/fo/app/store/underWaterInput/index.tsx b/apps/fo/app/store/underWaterInput/index.tsx index d4d4c39e2..806b12e2b 100644 --- a/apps/fo/app/store/underWaterInput/index.tsx +++ b/apps/fo/app/store/underWaterInput/index.tsx @@ -317,6 +317,14 @@ export type UnderWaterStore = UnderWaterType & UnderWaterActions; export const underWaterReducer: (set: (fn: (state: UnderWaterType) => UnderWaterType) => void) => UnderWaterActions = (set: (fn: (state: UnderWaterType) => UnderWaterType) => void) => { return { searchUnderWaterList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { + set((state: UnderWaterType) => ({ + ...state, + UnderWater: { + ...state.UnderWater, + isLoading: true, + }, + })); + const facilityInitData = await fetchFacilityListInit(pageNo, pageSize, part, nameCd, fcltCpct, operationValue, fcltyNm); if (pageSize < 5000) { @@ -724,4 +732,4 @@ export const underWaterReducer: (set: (fn: (state: UnderWaterType) => UnderWater })) } } -} \ No newline at end of file +} diff --git a/apps/fo/src/shared/providers/prompt-provider.tsx b/apps/fo/src/shared/providers/prompt-provider.tsx index 10338c338..7724d0326 100644 --- a/apps/fo/src/shared/providers/prompt-provider.tsx +++ b/apps/fo/src/shared/providers/prompt-provider.tsx @@ -1,3 +1,4 @@ +"use client"; import { createContext, useState } from "react"; interface PromptContext { diff --git a/packages/common/business_components/src/ui/table/index.tsx b/packages/common/business_components/src/ui/table/index.tsx index 1a0fc57c0..d2fd81de6 100644 --- a/packages/common/business_components/src/ui/table/index.tsx +++ b/packages/common/business_components/src/ui/table/index.tsx @@ -16,14 +16,16 @@ export type ChkClass = { chk: boolean; readonly: boolean; }; -type UiTableProps = { +type UiTableProps = { headName: React.ReactNode | undefined; - tableData: { [key: string]: any }[]; + tableData: T[]; headlist: UiHeadProps[]; pageSize: number; total: number; cellClick: ((index: number | undefined, headId: string) => void) | undefined; onPageChange: (page: number) => void; + cellClassName?: (row: T, headId: string, rowIndex: number) => string; + rowClassName?: (row: T, rowIndex: number) => string; className?: string; resetPageNo?: boolean; children?: React.ReactNode | undefined; @@ -46,7 +48,7 @@ type UiHeadProps = { colSpan?: number; }; -export function UiTable({ +export function UiTable>({ tableData, headlist, pageSize, @@ -55,6 +57,8 @@ export function UiTable({ children, cellClick, onPageChange, + cellClassName, + rowClassName, className = "", resetPageNo = false, boldArray = [], @@ -63,7 +67,7 @@ export function UiTable({ curPage = 1, headButton = undefined, widthFixed = false -}: UiTableProps) { +}: UiTableProps) { const [cur, setCur] = useState(curPage); const [idx, setIdx] = useState(index); const [headerHeight, setHeaderHeight] = useState(0); @@ -148,8 +152,8 @@ export function UiTable({ {tableData.length > 0 ? ( - tableData?.map((el: Record, index) => ( - + tableData?.map((el: T, index) => ( + {headlist .filter((item) => item.visible != false) .map( @@ -163,29 +167,32 @@ export function UiTable({ : cellClick ? "cursor-pointer" : "" - } sticky top-20 z-40 bg-secondary !font-bold whitespace-pre-line`} + } ${cellClassName ? cellClassName(el, head.id, index) : ""} sticky top-20 z-40 bg-secondary !font-bold whitespace-pre-line`} style={{ top: `${headerHeight + index * 32 - 4}px` }} onClick={() => handleCellClick(index, head.id)} key={`cell-${head.id}-${index}`} > - {typeof el[head.id] !== "number" - ? String(el[head.id] ?? "") - : String(el[head.id]).includes(".") - ? String(el[head.id]) - .split(".") - .map((part, index) => - index === 0 - ? part.replace( - /\B(?=(\d{3})+(?!\d))/g, - ",", - ) - : part, - ) - .join(".") - : String(el[head.id] ?? "").replace( - /\B(?=(\d{3})+(?!\d))/g, - ",", - )} + {(() => { + const cellValue = (el as Record)[head.id]; + return typeof cellValue !== "number" + ? String(cellValue ?? "") + : String(cellValue).includes(".") + ? String(cellValue) + .split(".") + .map((part, index) => + index === 0 + ? part.replace( + /\B(?=(\d{3})+(?!\d))/g, + ",", + ) + : part, + ) + .join(".") + : String(cellValue ?? "").replace( + /\B(?=(\d{3})+(?!\d))/g, + ",", + ); + })()} ) : ( handleCellClick(index, head.id)} key={`cell-${head.id}-${index}`} > { //체크박스 유형애서 readOnly가 필요한 경우를 위해서 ChkClass 를 사용해서 readOnly 처리함. - typeof el[head.id] === "object" && - el[head.id] !== null && - "chk" in (el[head.id] as object) && - "readonly" in (el[head.id] as object) ? ( + (() => { + const cellValue = (el as Record)[head.id]; + return typeof cellValue === "object" && + cellValue !== null && + "chk" in (cellValue as object) && + "readonly" in (cellValue as object) ? ( { { - console.log(el[head.id]); + console.log(cellValue); } if ( - (el[head.id] as ChkClass).readonly == true + (cellValue as ChkClass).readonly == true ) return; - (el[head.id] as ChkClass).chk = + (cellValue as ChkClass).chk = Boolean(checked); }} > - ) : typeof el[head.id] === "boolean" ? ( + ) : typeof cellValue === "boolean" ? ( { - el[head.id] = checked; + (el as Record)[head.id] = checked; }} > - ) : typeof el[head.id] !== "number" ? ( - String(el[head.id] ?? "") - ) : String(el[head.id]).includes(".") ? ( - String(el[head.id]) + ) : typeof cellValue !== "number" ? ( + String(cellValue ?? "") + ) : String(cellValue).includes(".") ? ( + String(cellValue) .split(".") .map((part, index) => index === 0 @@ -246,11 +255,12 @@ export function UiTable({ ) .join(".") ) : ( - String(el[head.id] ?? "").replace( + String(cellValue ?? "").replace( /\B(?=(\d{3})+(?!\d))/g, ",", ) - ) + ); + })() } )),