From ac3acbb0f43264329fe6c0d1fc7f00cd636025c2 Mon Sep 17 00:00:00 2001 From: dongsilove Date: Sun, 4 Jan 2026 20:45:08 +0900 Subject: [PATCH] =?UTF-8?q?fo:=20dashboard=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/fo/app/store/dashboard/index.tsx | 160 ++++++++++++++++++-------- apps/fo/app/store/store.tsx | 41 +++---- 2 files changed, 136 insertions(+), 65 deletions(-) diff --git a/apps/fo/app/store/dashboard/index.tsx b/apps/fo/app/store/dashboard/index.tsx index b2778e3d8..081da3839 100644 --- a/apps/fo/app/store/dashboard/index.tsx +++ b/apps/fo/app/store/dashboard/index.tsx @@ -699,6 +699,7 @@ const drainageEquipmentList: DrainageEquipmentListProps[] = [ } ]; +type ApiRes = { data: any; count: any; } /**==================================== * Store - api (데이터 호출) ====================================*/ @@ -722,7 +723,7 @@ const fetchFacilityPlan = async (targetYear: string | undefined, fcltyCd: string }; /* 시설정보 및 운영현황 - 운영실태 */ -const fetchOperationStatus = async (searchYear: string | undefined, fcltyCd: string | undefined) => { +const fetchOperationStatus = async (searchYear: string | undefined, fcltyCd: string | undefined): Promise => { try { const url = '/dashBoard/mngInfo/' + (searchYear ? searchYear : '2023') + '/' + (fcltyCd ? fcltyCd : ''); const res = await getFetch('fo', url); @@ -746,14 +747,15 @@ const fetchMainGraph = async (searchYear: string | undefined, fcltyCd: string | } // 수질 데이터 청천시, 강우시 재계산 -const calcWaterQltyData = async (data: any[], searchYear: string | undefined, fcltyCd: string | undefined) => { +const calcWaterQltyData = async (data: any[], searchYear: string | undefined, fcltyCd: string | undefined, mainGraphData: any) => { const nullToZero = (value: any) => { return value === null || value === undefined || value === '' ? 0 : Number(value); }; const orgData = data; - const res = await fetchMainGraph(searchYear, fcltyCd); + // const res = await fetchMainGraph(searchYear, fcltyCd); // /fclt/qlty/hist/{year}/{fcltyCd} + const res = mainGraphData; if (res.data.wqltObjs.length > 0) { // const clone = (arr: any[]) => arr?.map(v => ({ ...v })) ?? []; const qltyData = res.data.wqltObjs; @@ -761,7 +763,7 @@ const calcWaterQltyData = async (data: any[], searchYear: string | undefined, fc // 강우시 변수 const rainEffectDayArray: string[] = []; - + // (0) 전체변수 let summerDay = 0, noNullSummerDay = 0; let totalInflBodAvgSummer = 0, totalInflTnAvgSummer = 0, totalInflTpAvgSummer = 0; @@ -1064,6 +1066,9 @@ export type DashBoardType = { rainManageList: RainManageListProps[]; excelList: RainManageExcelType[]; isLoadingRainManage: boolean; + mainGraphData: any; + mainGraphYear: string; + mainGraphFcltyCd: string; }, DrainageEquipment: { @@ -1127,6 +1132,9 @@ export const dashBoardInitState: DashBoardType = { rainManageList: rainManageList, excelList: [], isLoadingRainManage: false, + mainGraphData: null, + mainGraphYear: '', + mainGraphFcltyCd: '', }, DrainageEquipment: { @@ -1251,7 +1259,8 @@ const searchWaterUsage = async (searchYear: string, fcltyCd: string) => { } export const dashBoardReducer = ( - set: (fn: (state: DashBoardType) => DashBoardType) => void + set: (fn: (state: DashBoardType) => DashBoardType) => void, + get: () => DashBoardType ): DashBoardActions => { return { initializeDashBoardData: async () => { @@ -1275,7 +1284,7 @@ export const dashBoardReducer = ( })); let waterUsage = [0, 0, 0]; waterUsage = await searchWaterUsage(targetYear, fcltyCd); // /fclt/flow/{fcltyCd}/{year} -console.log(waterUsage); + set((state: DashBoardType) => ({ ...state, PlanFclty: { @@ -1355,6 +1364,26 @@ console.log(waterUsage); /** 시설정보 및 운영현황 - 운영실태 */ searchOperationStatus: async (isExcel: boolean, searchYear: string, fcltyCd: string) => { + const state = get(); + let mainGraphData: ApiRes = { data: [], count: 0 }; + + // 이미 조회된 데이터가 있는지 확인 (연도와 시설코드가 같을 때만) + if (state.RainManage.mainGraphYear === searchYear && state.RainManage.mainGraphFcltyCd === fcltyCd && state.RainManage.mainGraphData) { + mainGraphData = state.RainManage.mainGraphData; + } else { + mainGraphData = await fetchMainGraph(searchYear, fcltyCd); + // 조회된 데이터 저장 + set((state: DashBoardType) => ({ + ...state, + RainManage: { + ...state.RainManage, + mainGraphData: mainGraphData, + mainGraphYear: searchYear, + mainGraphFcltyCd: fcltyCd, + } + })); + } + set((state: DashBoardType) => ({ ...state, OperationStatus: { @@ -1630,52 +1659,55 @@ console.log(waterUsage); // 오염물질 // RDII 추정 = 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD)) - const resp = await fetchMainGraph(searchYear, fcltyCd); - const wqltData = resp.data.wqltObjs; - const wqltDataTot = CalcRainEffect(clone(wqltData)); - const wqltDataSunny = CalcRainEffect(clone(wqltData), 'SUNNY'); + // const resp = await fetchMainGraph(searchYear, fcltyCd); + const resp = mainGraphData; + if (resp && resp.data && resp.data.wqltObjs) { + const wqltData = resp.data.wqltObjs; + const wqltDataTot = CalcRainEffect(clone(wqltData)); + const wqltDataSunny = CalcRainEffect(clone(wqltData), 'SUNNY'); - let minSummerBod = 99999999; - let minSummerBodInfl = 99999999; - let winterCnt = 0; - let winterBodSunny = 0; - let rdiRain = 0; + let minSummerBod = 99999999; + let minSummerBodInfl = 99999999; + let winterCnt = 0; + let winterBodSunny = 0; + let rdiRain = 0; - const summerMonth = ['06', '07', '08']; - const winterMonth = ['01', '02']; + const summerMonth = ['06', '07', '08']; + const winterMonth = ['01', '02']; - wqltDataTot.filter(item => summerMonth.includes(item.msrDt.toString().replaceAll('-', '').substring(4, 6))).forEach(item2 => { - if (Number(item2.infoRnDay) >= 3) { - const inflBod = Number(item2.inflAssctBfrWqltBod); - const infl = Number(item2.inflAmnt); - const rain = Number(item2.infoRnDay); - if (inflBod < minSummerBod) { - minSummerBodInfl = infl; - minSummerBod = inflBod; - rdiRain = rain; + wqltDataTot.filter(item => summerMonth.includes(item.msrDt.toString().replaceAll('-', '').substring(4, 6))).forEach(item2 => { + if (Number(item2.infoRnDay) >= 3) { + const inflBod = Number(item2.inflAssctBfrWqltBod); + const infl = Number(item2.inflAmnt); + const rain = Number(item2.infoRnDay); + if (inflBod < minSummerBod) { + minSummerBodInfl = infl; + minSummerBod = inflBod; + rdiRain = rain; + } } - } - }); + }); - wqltDataSunny.filter(item => winterMonth.includes(item.msrDt.toString().replaceAll('-', '').substring(4, 6))).forEach(item2 => { - winterBodSunny += Number(item2.inflAssctBfrWqltBod); - winterCnt += 1; - }); + wqltDataSunny.filter(item => winterMonth.includes(item.msrDt.toString().replaceAll('-', '').substring(4, 6))).forEach(item2 => { + winterBodSunny += Number(item2.inflAssctBfrWqltBod); + winterCnt += 1; + }); - const roundMinSummerBodInfl = Number(roundNumber(minSummerBodInfl, 0).toString().replaceAll(',', '')); - const roundMinSummerBod = Number(roundNumber(minSummerBod, 1).toString().replaceAll(',', '')); - const roundWinterBodSunny = Number(roundNumber(winterBodSunny, 1).toString().replaceAll(',', '')); + const roundMinSummerBodInfl = Number(roundNumber(minSummerBodInfl, 0).toString().replaceAll(',', '')); + const roundMinSummerBod = Number(roundNumber(minSummerBod, 1).toString().replaceAll(',', '')); + const roundWinterBodSunny = Number(roundNumber(winterBodSunny, 1).toString().replaceAll(',', '')); - const winterBodAvg = Number(roundNumber((roundWinterBodSunny / winterCnt), 1).toString().replaceAll(',', '')); - // 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD)) - const winMinusSum = winterBodAvg - roundMinSummerBod; + const winterBodAvg = Number(roundNumber((roundWinterBodSunny / winterCnt), 1).toString().replaceAll(',', '')); + // 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD)) + const winMinusSum = winterBodAvg - roundMinSummerBod; - const rdiValue = winMinusSum === 0 ? 0 : roundMinSummerBodInfl * (winMinusSum / winterBodAvg); + const rdiValue = winMinusSum === 0 ? 0 : roundMinSummerBodInfl * (winMinusSum / winterBodAvg); - rdiPercent = (rdiValue / minSummerBodInfl) * 100; + rdiPercent = (rdiValue / minSummerBodInfl) * 100; - operationalStatusList[0].rdi = rdiValue; - operationalStatusList[0].rdiRain = rdiRain; + operationalStatusList[0].rdi = rdiValue; + operationalStatusList[0].rdiRain = rdiRain; + } /* const summerLowFlow = data.summerBod&&data.summerBod.INFL_AMNT&&data.summerBod.INFL_AMNT!='null'?Number(data.summerBod.INFL_AMNT):0; const winterAvgBod = data.winterSunny&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD):0; const summerLowBod = data.summerBod&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD):0; @@ -1792,7 +1824,7 @@ console.log(waterUsage); } } - const rtnData = await calcWaterQltyData(operationalStatusList, searchYear, fcltyCd); // 수질 데이터 청천시, 강우시 재계산 + const rtnData = await calcWaterQltyData(operationalStatusList, searchYear, fcltyCd, mainGraphData); // 수질 데이터 청천시, 강우시 재계산 // 총인설비가 없을 경우 제외 // console.log('총인시설 여부 : ', data.yearData?.TP_FCT_YN); @@ -1815,6 +1847,26 @@ console.log(waterUsage); }, searchMainGraph: async (searchYear: string, fcltyCd: string) => { + const state = get(); + let res: any = null; + + // 이미 조회된 데이터가 있는지 확인 + if (state.RainManage.mainGraphYear === searchYear && state.RainManage.mainGraphFcltyCd === fcltyCd && state.RainManage.mainGraphData) { + res = state.RainManage.mainGraphData; + } else { + res = await fetchMainGraph(searchYear, fcltyCd); + // 데이터 저장 + set((state: DashBoardType) => ({ + ...state, + RainManage: { + ...state.RainManage, + mainGraphData: res, + mainGraphYear: searchYear, + mainGraphFcltyCd: fcltyCd, + } + })); + } + set((state: DashBoardType) => ({ ...state, MainGraph: { @@ -1822,7 +1874,7 @@ console.log(waterUsage); isLoadingMainGraph: true, }, })); - const res = await fetchMainGraph(searchYear, fcltyCd); + // const res = await fetchMainGraph(searchYear, fcltyCd); const res2 = await fetchFacilityWaterQltyInfo(fcltyCd); let chungcunSumFlow = 0; @@ -1944,6 +1996,24 @@ console.log(waterUsage); }, searchRainManage: async (searchYear: string, fcltyCd: string, isExcel: boolean) => { + const state = get(); + let res: any = null; + + if (state.RainManage.mainGraphYear === searchYear && state.RainManage.mainGraphFcltyCd === fcltyCd && state.RainManage.mainGraphData) { + res = state.RainManage.mainGraphData; + } else { + res = await fetchMainGraph(searchYear, fcltyCd); + set((state: DashBoardType) => ({ + ...state, + RainManage: { + ...state.RainManage, + mainGraphData: res, + mainGraphYear: searchYear, + mainGraphFcltyCd: fcltyCd, + } + })); + } + set((state: DashBoardType) => ({ ...state, RainManage: { @@ -1951,7 +2021,7 @@ console.log(waterUsage); isLoadingRainManage: true, }, })); - const res = await fetchMainGraph(searchYear, fcltyCd); + // const res = await fetchMainGraph(searchYear, fcltyCd); if (res == null || res.data.wqltObjs == null || res.data.wqltObjs.length === 0) { set((state: DashBoardType) => ({ ...state, diff --git a/apps/fo/app/store/store.tsx b/apps/fo/app/store/store.tsx index f7f2222c6..c7064a40e 100644 --- a/apps/fo/app/store/store.tsx +++ b/apps/fo/app/store/store.tsx @@ -42,8 +42,9 @@ import { export type FoStore = CommonStore & tableType & DashBoardStore & ProcessFacilityStore & ProcessAreaStore & FlowRateSearchStore & FacilityPrecipitationStore & FacilityWaterQltyStore & PlanSewageStore & SewageOccurStore & UnderWaterStore & RdiStore; export type FoState = CommonType & tableState & ProcessFacilityType & ProcessAreaType & FacilityPrecipitationType & FlowRateSearchType & DashBoardType & FacilityWaterQltyType & PlanSewageType & SewageOccurType & UnderWaterType & RdiType; -export const StoreZus = - (initState: FoState = { ...commonState, +export const StoreZus = + (initState: FoState = { + ...commonState, ...tableStateExport , ...processFacilityInitState , ...processAreaInitState @@ -57,22 +58,22 @@ export const StoreZus = , ...rdiInitState } ) => { - return createStore()((set) => { - return { - ...initState, - ...CommonReducer(set), - ...tableActionsExport(set), - ...dashBoardReducer(set), - ...processFacilityReducer(set), - ...processAreaReducer(set), - ...facilityPrecipitationReducer(set), - ...flowRateSearchReducer(set), - ...facilityWaterQltyReducer(set), - ...planSewageReducer(set), - ...sewageOccurReducer(set), - ...underWaterReducer(set), - ...rdiReducer(set), - } - }) -} + return createStore()((set, get) => { + return { + ...initState, + ...CommonReducer(set), + ...tableActionsExport(set), + ...dashBoardReducer(set, get), + ...processFacilityReducer(set), + ...processAreaReducer(set), + ...facilityPrecipitationReducer(set), + ...flowRateSearchReducer(set), + ...facilityWaterQltyReducer(set), + ...planSewageReducer(set), + ...sewageOccurReducer(set), + ...underWaterReducer(set), + ...rdiReducer(set), + } + }) + } //store 등록하는 부분 \ No newline at end of file