Merge commit '8b8b2a03e2c81bf38abda2986018530dd6448e72' into iipbs/wr/dev
This commit is contained in:
@@ -60,10 +60,13 @@ async function handler(
|
||||
[AUTH_USER_ID]: userId,
|
||||
});
|
||||
|
||||
|
||||
|
||||
if (refreshToken) {
|
||||
cookieStore.set(REFRESH_TOKEN, refreshToken, {
|
||||
httpOnly: true,
|
||||
sameSite: "lax",
|
||||
// domain: domain,
|
||||
path: "/",
|
||||
});
|
||||
}
|
||||
@@ -83,6 +86,7 @@ async function handler(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function POST(
|
||||
request: Request,
|
||||
props: { params: Promise<{ url: string[] }> },
|
||||
|
||||
@@ -10,6 +10,8 @@ export interface ZipSearchParams extends PageableParams {
|
||||
roadNm?: string; // 도로명
|
||||
stdgNm?: string; // 법정동명
|
||||
dongNm?: string; // 행정동명
|
||||
bldgNoMno?: number | null; // 빌딩본번
|
||||
bldgNoSno?: number | null; // 빌딩딩부번
|
||||
lotnoMno?: number | null; // 지번본번
|
||||
lotnoSno?: number | null; // 지번부번
|
||||
}
|
||||
@@ -21,6 +23,8 @@ export interface Zip {
|
||||
sggNm: string;
|
||||
emdNm: string;
|
||||
roadNm: string;
|
||||
bldgNoMno: number;
|
||||
bldgNoSno: number;
|
||||
lotnoMno: number;
|
||||
lotnoSno: number;
|
||||
lotno: string;
|
||||
|
||||
@@ -39,8 +39,8 @@ function ZipSearchDialog({ onSelectAddress }: ZipSearchDialogProps) {
|
||||
});
|
||||
const [searchQuery, setSearchQuery] = useState<ZipSearchParams>({
|
||||
roadNm: "",
|
||||
lotnoMno: null,
|
||||
lotnoSno: null,
|
||||
bldgNoMno: null,
|
||||
bldgNoSno: null,
|
||||
});
|
||||
const hasFetchedOnce = useRef(false);
|
||||
|
||||
@@ -156,17 +156,17 @@ function ZipSearchDialog({ onSelectAddress }: ZipSearchDialogProps) {
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<Label className="mb-1 text-base">지번본번</Label>
|
||||
<Label className="mb-1 text-base">건물본번</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={searchQuery.lotnoMno ?? ""}
|
||||
value={searchQuery.bldgNoMno ?? ""}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value
|
||||
? parseInt(e.target.value)
|
||||
: null;
|
||||
setSearchQuery({
|
||||
...searchQuery,
|
||||
lotnoMno: value,
|
||||
bldgNoMno: value,
|
||||
});
|
||||
}}
|
||||
placeholder="예: 123"
|
||||
@@ -175,17 +175,17 @@ function ZipSearchDialog({ onSelectAddress }: ZipSearchDialogProps) {
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<Label className="mb-1 text-base">지번부번</Label>
|
||||
<Label className="mb-1 text-base">건물부번</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={searchQuery.lotnoSno ?? ""}
|
||||
value={searchQuery.bldgNoSno ?? ""}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value
|
||||
? parseInt(e.target.value)
|
||||
: null;
|
||||
setSearchQuery({
|
||||
...searchQuery,
|
||||
lotnoSno: value,
|
||||
bldgNoSno: value,
|
||||
});
|
||||
}}
|
||||
placeholder="예: 45"
|
||||
|
||||
@@ -13,7 +13,7 @@ NEXT_PUBLIC_CS_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:80
|
||||
NEXT_PUBLIC_CS_TUS_UPLOAD = /attach-service/api/v1/tus/upload
|
||||
NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver
|
||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl
|
||||
NEXT_PUBLIC_REUSE_API_URL= http://apigateway.iipbs-was.svc.cluster.local:8000/reuse-service/api/v1
|
||||
NEXT_PUBLIC_WR_API_URL= http://apigateway.iipbs-was.svc.cluster.local:8000/reuse-service/api/v1
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000/sewerage-service
|
||||
NEXT_PUBLIC_NGII_URL = http://172.29.143.87
|
||||
NEXT_PUBLIC_NGII_PARAM = BDE2BEF39DAFEC293AB6730150F222AC&service=WMTS&request=GetTile&version=1.0.0&format=image/png&layer=korean_map&style=korean&tilematrixset=korean&tilematrix={z}&tilecol={y}&tilerow={x}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
*/
|
||||
|
||||
export default function CalcRainEffect(data : any, weather='ALL') {
|
||||
console.log("%c Calculate RainEffect !" , "background:blue;color:white");
|
||||
console.log("%c Data Length :"+data.length+" Weather : "+weather , "background:yellow;color:blue");
|
||||
/* console.log("%c Calculate RainEffect !" , "background:blue;color:white");
|
||||
console.log("%c Data Length :"+data.length+" Weather : "+weather , "background:yellow;color:blue");*/
|
||||
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
const item = data[idx];
|
||||
|
||||
@@ -145,71 +145,74 @@ export default function DashBoard() {
|
||||
|
||||
const excelDownload = () => {
|
||||
if (!fcltyList.bscFctCd) return;
|
||||
|
||||
switch (activeTab) {
|
||||
case 'facilityInfo':
|
||||
searchOperationStatus(false, searchYear, fcltyList.bscFctCd);
|
||||
searchOperationStatus(false, searchYear, fcltyList.bscFctCd).then(() => {setTimeout(() => {makeExcelData();}, 200);});
|
||||
|
||||
fetch(`/mainDashBoard.xlsx`, {}).then(async (response) => {
|
||||
if (!response.ok) {
|
||||
throw Error(response.statusText);
|
||||
}
|
||||
// 받은 파일 바인너리 처리
|
||||
const blobRet = await response.arrayBuffer();
|
||||
|
||||
const excelData1 = planFcltyList.map((item) => {
|
||||
return [
|
||||
item.item,
|
||||
Number(item.provisionalApproval.toString().replaceAll(',',''))?Number(item.provisionalApproval.toString().replaceAll(',','')):item.provisionalApproval,
|
||||
item.now,
|
||||
item.stepOne,
|
||||
item.stepTwo,
|
||||
item.stepThree,
|
||||
item.stepFour,
|
||||
];
|
||||
});
|
||||
|
||||
// operationalStatusList를 2차원 배열로 변환
|
||||
const excelData2 = operationalStatusList.map((item, index) => {
|
||||
const baseData = [
|
||||
Number(item.yearAvg?.replaceAll(',','')),
|
||||
Number(item.yearMax?.replaceAll(',','')),
|
||||
Number(item.yearMin?.replaceAll(',','')),
|
||||
Number(item.summerAll?.replaceAll(',','')),
|
||||
Number(item.summerThree?.replaceAll(',','')),
|
||||
Number(item.summerRain?.replaceAll(',','')),
|
||||
Number(item.winterAll?.replaceAll(',','')),
|
||||
Number(item.winterSunnyAvg?.replaceAll(',','')),
|
||||
Number(item.winterSunnyMax?.replaceAll(',','')),
|
||||
Number(item.winterSunnyMin?.replaceAll(',','')),
|
||||
Number(item.groundWaterAvg?.replaceAll(',','').replaceAll('%','')),
|
||||
Number(item.groundWaterSummer?.replaceAll(',','').replaceAll('%','')),
|
||||
Number(item.groundWaterWinter?.replaceAll(',','').replaceAll('%',''))
|
||||
];
|
||||
|
||||
// index가 0일 때만 rdi와 rdiRain 추가
|
||||
console.log(item.rdiRain);
|
||||
return index === 0 ? [...baseData, item.rdi&&item.rdi.toString().trim()!=''?Number(item.rdi.toString().replaceAll(',','')):'', item.rdiRain&&item.rdiRain.toString().trim()!=''?Number(item.rdiRain.toString().replaceAll(',','')):''] : baseData;
|
||||
});
|
||||
|
||||
const sheetParameter = [
|
||||
{
|
||||
data: excelData1,
|
||||
headerNum: 3,
|
||||
headerRange: 'A1:G2',
|
||||
sheetName: '운영실태',
|
||||
startCol: 'A'
|
||||
},
|
||||
{
|
||||
data: excelData2,
|
||||
headerNum: 4,
|
||||
headerRange: 'A1:Q3',
|
||||
sheetName: '운영실태',
|
||||
startCol: 'C'
|
||||
const makeExcelData = async () => {
|
||||
fetch(`/mainDashBoard.xlsx`, {}).then(async (response) => {
|
||||
if (!response.ok) {
|
||||
throw Error(response.statusText);
|
||||
}
|
||||
];
|
||||
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
|
||||
await filePickedBlobArray(blobRet, '시설정보및운영현황황', sheetParameter);
|
||||
});
|
||||
// 받은 파일 바인너리 처리
|
||||
const blobRet = await response.arrayBuffer();
|
||||
|
||||
const excelData1 = planFcltyList.map((item) => {
|
||||
return [
|
||||
item.item,
|
||||
item.provisionalApproval?Number(item.provisionalApproval.toString().replaceAll(',',''))?Number(item.provisionalApproval.toString().replaceAll(',','')):item.provisionalApproval:'',
|
||||
item.now,
|
||||
item.stepOne,
|
||||
item.stepTwo,
|
||||
item.stepThree,
|
||||
item.stepFour,
|
||||
];
|
||||
});
|
||||
|
||||
// operationalStatusList를 2차원 배열로 변환
|
||||
const excelData2 = operationalStatusList.map((item, index) => {
|
||||
console.log(item.yearAvg+' '+item.yearMax+' '+item.yearMin);
|
||||
const baseData = [
|
||||
Number(item.yearAvg?.toString().replaceAll(',','')),
|
||||
Number(item.yearMax?.toString().replaceAll(',','')),
|
||||
Number(item.yearMin?.toString().replaceAll(',','')),
|
||||
Number(item.summerAll?.toString().replaceAll(',','')),
|
||||
Number(item.summerThree?.toString().replaceAll(',','')),
|
||||
Number(item.summerRain?.toString().replaceAll(',','')),
|
||||
Number(item.winterAll?.toString().replaceAll(',','')),
|
||||
Number(item.winterSunnyAvg?.toString().replaceAll(',','')),
|
||||
Number(item.winterSunnyMax?.toString().replaceAll(',','')),
|
||||
Number(item.winterSunnyMin?.toString().replaceAll(',','')),
|
||||
Number(item.groundWaterAvg?.toString().replaceAll(',','').replaceAll('%','')),
|
||||
Number(item.groundWaterSummer?.toString().replaceAll(',','').replaceAll('%','')),
|
||||
Number(item.groundWaterWinter?.toString().replaceAll(',','').replaceAll('%',''))
|
||||
];
|
||||
|
||||
// index가 0일 때만 rdi와 rdiRain 추가
|
||||
return index === 0 ? [...baseData, item.rdi&&item.rdi.toString().trim()!=''?Number(item.rdi.toString().replaceAll(',','')):'', item.rdiRain&&item.rdiRain.toString().trim()!=''?Number(item.rdiRain.toString().replaceAll(',','')):''] : baseData;
|
||||
});
|
||||
|
||||
const sheetParameter = [
|
||||
{
|
||||
data: excelData1,
|
||||
headerNum: 3,
|
||||
headerRange: 'A1:G2',
|
||||
sheetName: '운영실태',
|
||||
startCol: 'A'
|
||||
},
|
||||
{
|
||||
data: excelData2,
|
||||
headerNum: 4,
|
||||
headerRange: 'A1:Q3',
|
||||
sheetName: '운영실태',
|
||||
startCol: 'C'
|
||||
}
|
||||
];
|
||||
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
|
||||
await filePickedBlobArray(blobRet, '시설정보및운영현황황', sheetParameter);
|
||||
});
|
||||
};
|
||||
break;
|
||||
|
||||
case 'mainGraph':
|
||||
|
||||
@@ -9,7 +9,7 @@ import CommaToNumber from "@/app/components/common/CommaToNumber";
|
||||
import { roundNumber } from "@/app/components/common/DataForm";
|
||||
import UnderComment from "@/app/components/common/UnderComment";
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { FacilityWaterQltyProps, modalExcelType } from "@/app/store/facilityWaterQlty";
|
||||
import type { FacilityWaterQltyProps, modalChoinginExcelType, modalExcelType } from "@/app/store/facilityWaterQlty";
|
||||
import { downloadExcelFormat, UITab, UiTable } from "@common/business_components/ui";
|
||||
import { Button, TabsContent } from "@common/components/ui";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
@@ -51,6 +51,8 @@ const tabList3 = [
|
||||
];
|
||||
|
||||
export default function WaterQualityModal({fcltyName='', facilityCd='', searchYear=new Date().getFullYear().toString()} : ModalProps) {
|
||||
const [tabName, setTabName] = useState<string>('tab_num1');
|
||||
|
||||
// 그리드 관련
|
||||
const {FacilityWaterQltyModal,
|
||||
searchFacilityWaterQltyListHist,
|
||||
@@ -68,6 +70,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
} = FacilityWaterQltyModal;
|
||||
|
||||
const prevExcelListRef = useRef<modalExcelType[] | null>(null);
|
||||
const prevChoinginExcelListRef = useRef<modalChoinginExcelType[] | null>(null);
|
||||
|
||||
// 필터링 된 후 최대, 최소, 평균 값 계산
|
||||
const setFilterAfterData = (filteredData: FacilityWaterQltyProps[]) => {
|
||||
@@ -351,43 +354,76 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
}, []);
|
||||
|
||||
const excelDownload = () => {
|
||||
const excelDownList: modalExcelType[] = [];
|
||||
if(copyYearList.length > 0){
|
||||
copyYearList.forEach((item) => {
|
||||
excelDownList.push({
|
||||
날짜: item.msrDt,
|
||||
"유입BOD(mg/L)": CommaToNumber(item.inflAssctBfrWqltBod),
|
||||
"유입TOC(COD)(mg/L)": CommaToNumber(item.inflAssctBfrWqltToc),
|
||||
"유입SS(mg/L)": CommaToNumber(item.inflAssctBfrWqltSs),
|
||||
"유입TN(mg/L)": CommaToNumber(item.inflAssctBfrWqltTn),
|
||||
"유입TP(mg/L)": CommaToNumber(item.inflAssctBfrWqltTp),
|
||||
"유출BOD(mg/L)": CommaToNumber(item.efflWqltBod),
|
||||
"유출TOC(COD)(mg/L)": CommaToNumber(item.efflWqltToc),
|
||||
"유출SS(mg/L)": CommaToNumber(item.efflWqltSs),
|
||||
"유출TN(mg/L)": CommaToNumber(item.efflWqltTn),
|
||||
"유출TP(mg/L)": CommaToNumber(item.efflWqltTp),
|
||||
"강우량(mm/일)": CommaToNumber(item.infoRnDay?item.infoRnDay.toString():"0.0"),
|
||||
|
||||
if(tabName === 'tab_num1'){
|
||||
const excelDownList: modalExcelType[] = [];
|
||||
if(copyYearList.length > 0){
|
||||
copyYearList.forEach((item) => {
|
||||
excelDownList.push({
|
||||
날짜: item.msrDt,
|
||||
"유입BOD(mg/L)": CommaToNumber(item.inflAssctBfrWqltBod),
|
||||
"유입TOC(COD)(mg/L)": CommaToNumber(item.inflAssctBfrWqltToc),
|
||||
"유입SS(mg/L)": CommaToNumber(item.inflAssctBfrWqltSs),
|
||||
"유입TN(mg/L)": CommaToNumber(item.inflAssctBfrWqltTn),
|
||||
"유입TP(mg/L)": CommaToNumber(item.inflAssctBfrWqltTp),
|
||||
"유출BOD(mg/L)": CommaToNumber(item.efflWqltBod),
|
||||
"유출TOC(COD)(mg/L)": CommaToNumber(item.efflWqltToc),
|
||||
"유출SS(mg/L)": CommaToNumber(item.efflWqltSs),
|
||||
"유출TN(mg/L)": CommaToNumber(item.efflWqltTn),
|
||||
"유출TP(mg/L)": CommaToNumber(item.efflWqltTp),
|
||||
"강우량(mm/일)": CommaToNumber(item.infoRnDay?item.infoRnDay.toString():"0.0"),
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
if (excelDownList && excelDownList.length > 0) {
|
||||
downloadExcelFormat(
|
||||
{ data: JSON.parse(JSON.stringify(excelDownList))
|
||||
, fileName: searchYear+'년 '+fcltyName + ' 수질현황'
|
||||
, sheetNameArray: [fcltyName + ' 수질현황']
|
||||
, headerRange: 'A1:L1'
|
||||
, decimalArray1: [1,2,3,6,7,8,11]
|
||||
, decimalArray3: [4,5,9,10]
|
||||
}
|
||||
if (excelDownList && excelDownList.length > 0) {
|
||||
downloadExcelFormat(
|
||||
{ data: JSON.parse(JSON.stringify(excelDownList))
|
||||
, fileName: searchYear+'년 '+fcltyName + ' 수질현황'
|
||||
, sheetNameArray: [fcltyName + ' 수질현황']
|
||||
, headerRange: 'A1:L1'
|
||||
, decimalArray1: [1,2,3,6,7,8,11]
|
||||
, decimalArray3: [4,5,9,10]
|
||||
});
|
||||
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
prevExcelListRef.current = excelDownList;
|
||||
}else{
|
||||
const excelDownList: modalChoinginExcelType[] = [];
|
||||
if(chongInWaterQltyYearList.length > 0){
|
||||
chongInWaterQltyYearList.forEach((item) => {
|
||||
excelDownList.push({
|
||||
날짜: item.msrDt,
|
||||
"유입BOD(mg/L)": CommaToNumber(item.tpInflWqltBod),
|
||||
"유입TP(mg/L)": CommaToNumber(item.tpInflWqltTp),
|
||||
"유출BOD(mg/L)": CommaToNumber(item.efflWqltBod),
|
||||
"유출TP(mg/L)": CommaToNumber(item.efflWqltTn),
|
||||
});
|
||||
});
|
||||
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
if (excelDownList && excelDownList.length > 0) {
|
||||
downloadExcelFormat(
|
||||
{ data: JSON.parse(JSON.stringify(excelDownList))
|
||||
, fileName: searchYear+'년 '+fcltyName + ' 총인설비수질현황'
|
||||
, sheetNameArray: [fcltyName + ' 총인설비수질현황']
|
||||
, headerRange: 'A1:E1'
|
||||
, decimalArray1: [1,3]
|
||||
, decimalArray3: [2,4]
|
||||
});
|
||||
} else if (prevChoinginExcelListRef.current && prevChoinginExcelListRef.current.length > 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
prevChoinginExcelListRef.current = excelDownList;
|
||||
}
|
||||
prevExcelListRef.current = excelDownList;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setTabName("tab_num1");
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<UITab tabList={tabList1} defaultValue="tab_num1">
|
||||
<UITab tabList={tabList1} defaultValue="tab_num1" onValueChange={(value) => setTabName(value)}>
|
||||
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownload}>
|
||||
{"엑셀다운로드"}
|
||||
</Button>
|
||||
@@ -555,7 +591,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
</TabsContent>
|
||||
|
||||
{/* 총인설비 수질현황 */}
|
||||
<TabsContent value="tab_num2">
|
||||
<TabsContent value="tab_num2" >
|
||||
<UITab tabList={tabList3} defaultValue="tab_term_year_chongin">
|
||||
<TabsContent value="tab_term_year_chongin">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
|
||||
@@ -83,10 +83,8 @@ export default function Rdi() {
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
useEffect(() => {
|
||||
console.log(isLoading);
|
||||
}, [isLoading]);
|
||||
// 엑셀 다운로드 트리거
|
||||
const [isInitExcelDownload, setIsInitExcelDownload] = useState<boolean>(false);
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
@@ -122,15 +120,16 @@ export default function Rdi() {
|
||||
}, [isInit, initializeCommonData, searchRdiList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if(!isInitExcelDownload) return ;
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: 'RDII추정',
|
||||
sheetNameArray: ['RDII추정'],
|
||||
headerRange: 'A1:O1'
|
||||
headerRange: 'A1:R1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
}, [excelList, isInitExcelDownload]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
@@ -168,7 +167,8 @@ export default function Rdi() {
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback(() => {
|
||||
searchRdi(ref.current, 1, 10000);
|
||||
searchRdi(ref.current, 1, 5000);
|
||||
setIsInitExcelDownload(true);
|
||||
}, [searchRdi]);
|
||||
|
||||
// 페이지 변경
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { type TableUpperProps } from "@/app/store/common";
|
||||
import type { SewageOccurProps } from "@/app/store/sewageOccur";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import SewageOccurModal from "./modal/page";
|
||||
import type { SewageOccurProps } from "@/app/store/sewageOccur";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
|
||||
export default function PlanSewage() {
|
||||
const {Common
|
||||
@@ -94,6 +94,8 @@ export default function PlanSewage() {
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
// 엑셀다운로드 트리거
|
||||
const [isInitExcelDownload, setIsInitExcelDownload] = useState<boolean>(false);
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
@@ -139,18 +141,24 @@ export default function PlanSewage() {
|
||||
initializeCommonData();
|
||||
searchSewageOccurList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchSewageOccurList]);
|
||||
}, [isInit, initializeCommonData, searchSewageOccurList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '오수발생량 추정',
|
||||
sheetNameArray: ['오수발생량 추정'],
|
||||
headerRange: 'A1:O1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
if(!isInitExcelDownload) return ;
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '오수발생량 추정',
|
||||
sheetNameArray: ['오수발생량 추정'],
|
||||
headerRange: 'A1:O1'
|
||||
});
|
||||
}
|
||||
}, 500); // 약간의 지연을 두고 다운로드 실행
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, [excelList, isInit, isInitExcelDownload]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
@@ -188,7 +196,8 @@ export default function PlanSewage() {
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback(() => {
|
||||
searchFacilityPrecipitation(ref.current, 1, 10000);
|
||||
searchFacilityPrecipitation(ref.current, 1, 5000);
|
||||
setIsInitExcelDownload(true);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
// 페이지 변경
|
||||
@@ -250,4 +259,4 @@ export default function PlanSewage() {
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
"use client";
|
||||
import React from "react";
|
||||
|
||||
export default function TestPage() {
|
||||
|
||||
const handleFindUser = () => {
|
||||
fetch('/operation-service/api/v1/fclt/flow/1/10/2024', {
|
||||
method: "GET",
|
||||
}).then((data) => {
|
||||
console.log(data);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="text-4xl">
|
||||
<span>여기를 click</span>
|
||||
<button onClick={handleFindUser} className="bg-blue-500 hover:bg-blue-700 text-white">
|
||||
버튼
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -93,6 +93,8 @@ export default function UnderWaterInput() {
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
// 엑셀다운로드 트리거
|
||||
const [isMount, setIsMount] = useState<boolean>(false);
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
@@ -141,15 +143,20 @@ export default function UnderWaterInput() {
|
||||
}, [isInit, initializeCommonData, searchUnderWaterList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '지하수유입량 추정',
|
||||
sheetNameArray: ['지하수유입량 추정'],
|
||||
headerRange: 'A1:V1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
if(!isMount) return ;
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '지하수유입량 추정',
|
||||
sheetNameArray: ['지하수유입량 추정'],
|
||||
headerRange: 'A1:O1'
|
||||
});
|
||||
}
|
||||
}, 1000); // 약간의 지연을 두고 다운로드 실행
|
||||
return () => clearTimeout(timer);
|
||||
}, [excelList, isMount]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
@@ -174,7 +181,7 @@ export default function UnderWaterInput() {
|
||||
}
|
||||
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);
|
||||
} else {
|
||||
} else {
|
||||
searchUnderWaterList(pageNo, pageCnt, searchYear);
|
||||
}
|
||||
}, [fcltCpct, operationValue, fcltyName, searchUnderWaterList, searchYear]);
|
||||
@@ -187,7 +194,8 @@ export default function UnderWaterInput() {
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback(() => {
|
||||
searchFacilityPrecipitation(ref.current, 1, 10000);
|
||||
searchFacilityPrecipitation(ref.current, 1, 5000);
|
||||
setIsMount(true);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
// 페이지 변경
|
||||
|
||||
@@ -252,6 +252,7 @@ export const facilityPrecipitationReducer:(set:(fn: (state: FacilityPrecipitatio
|
||||
const excelDownList: ExcelType[] = [];
|
||||
|
||||
if(pageSize>5000){
|
||||
console.log('엑셀다운로드 데이터 생성 : ', data.length);
|
||||
data.forEach((item: FacilityPrecipitationProps) => {
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
|
||||
@@ -118,6 +118,14 @@ export type modalExcelType = {
|
||||
"강우량(mm/일)": number | '';
|
||||
}
|
||||
|
||||
export type modalChoinginExcelType = {
|
||||
날짜: string;
|
||||
"유입BOD(mg/L)": number | '';
|
||||
"유입TP(mg/L)": number | '';
|
||||
"유출BOD(mg/L)": number | '';
|
||||
"유출TP(mg/L)": number | '';
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import DataForm, { roundNumber } from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
export type { TableUpperProps };
|
||||
|
||||
@@ -412,6 +412,26 @@ 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 url = '/prcsFclt/info/'+pageNo+'/'+pageSize+tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
res.data.forEach((item: Record<string, unknown>) => {
|
||||
item.daddr = item.addr ? item.addr : '';
|
||||
item.sidoNm = item.sido ? item.sido : '';
|
||||
item.sggNm = item.gugun ? item.gugun : '';
|
||||
item.fctCpc = roundNumber(item.fctCpc as number, 0);
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (error) {
|
||||
console.error('시설정보 데이터를 가져오는데 실패했습니다:', error);
|
||||
return {data: [], count: 0};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const fetchFacilityList = 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 : '') : '';
|
||||
|
||||
@@ -21,16 +21,16 @@ export type RdiProps = {
|
||||
lclgvrnmntNm : string,
|
||||
daddr : string,
|
||||
fctCpc : number,
|
||||
summerMinBodValue : number,
|
||||
summerMinBodValue : number | '',
|
||||
inflAmnt : number | string | '',
|
||||
winterAvgBodLowRainfall : number,
|
||||
rdiiValue : number,
|
||||
infoRnDay : number,
|
||||
winterAvgBodLowRainfall : number | '',
|
||||
rdiiValue : number | '',
|
||||
infoRnDay : number | '',
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
rainEffectDay : number, // 강우영향일
|
||||
rainEffectDay : number | '', // 강우영향일
|
||||
chungchunFlow : string | number | '',
|
||||
rainCalInflAmnt : string | number | '',
|
||||
properYn : string,
|
||||
@@ -174,6 +174,18 @@ const fetchRdiList = async (pageNo: number, pageSize: number, searchYear: string
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/rdii/list/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
|
||||
res.data.forEach((item: RdiProps) => {
|
||||
item.fctCpc = item.fctCpc && item.fctCpc > 0 ? Number(item.fctCpc.toString().trim()) : 0;
|
||||
item.summerMinBodValue = '';
|
||||
item.inflAmnt = '';
|
||||
item.winterAvgBodLowRainfall = '';
|
||||
item.rdiiValue = '';
|
||||
item.infoRnDay = '';
|
||||
item.properYn = '';
|
||||
item.sido = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sigungo = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
});
|
||||
return { data: res.data, count: res.count }
|
||||
}catch(error){
|
||||
console.log(error);
|
||||
@@ -185,6 +197,7 @@ const fetchRdiList = async (pageNo: number, pageSize: number, searchYear: string
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type RdiActions = {
|
||||
resetExcelList: () => void;
|
||||
searchRdiList: (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
|
||||
}
|
||||
|
||||
@@ -231,10 +244,31 @@ const dataFormSetting=(item : RdiProps)=> {
|
||||
// Add type definitions for state setter function
|
||||
type SetStateFunction = (state: RdiType | ((state: RdiType) => RdiType)) => void;
|
||||
|
||||
// 병렬 처리 제한용 헬퍼
|
||||
async function processInBatches(items, batchSize, callback) {
|
||||
const results:any = [];
|
||||
for (let i = 0; i < items.length; i += batchSize) {
|
||||
const batch = items.slice(i, i + batchSize);
|
||||
const batchResults = await Promise.all(batch.map(callback));
|
||||
results.push(...batchResults);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
export type RdiStore = RdiType & RdiActions;
|
||||
|
||||
export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunction) => {
|
||||
return {
|
||||
resetExcelList: () => {
|
||||
set((state: RdiType) => ({
|
||||
...state,
|
||||
Rdi: {
|
||||
...state.Rdi,
|
||||
excelList: [],
|
||||
},
|
||||
}));
|
||||
},
|
||||
|
||||
searchRdiList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
set((state: RdiType) => ({
|
||||
...state,
|
||||
@@ -245,8 +279,31 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio
|
||||
}));
|
||||
|
||||
const res = await fetchRdiList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
if(pageSize>=5000){
|
||||
set((state: RdiType) => ({
|
||||
...state,
|
||||
Rdi: {
|
||||
...state.Rdi,
|
||||
excelList: [],
|
||||
isLoading: true,
|
||||
},
|
||||
}));
|
||||
}
|
||||
else{
|
||||
set((state: RdiType) => ({
|
||||
...state,
|
||||
Rdi: {
|
||||
...state.Rdi,
|
||||
rdiList: res.data,
|
||||
excelList: [],
|
||||
rdiCount: res.count,
|
||||
isLoading: true,
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
const data = res.data;
|
||||
const reData = await Promise.all(data.map(async (item: RdiProps) => {
|
||||
const reData = await processInBatches(data, 15, async (item: any, index: number) => {
|
||||
const bscFctCd = item.bscFctCd;
|
||||
const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as FlowResponse;
|
||||
const calData = CalcRainEffect(res2.data, 'SUNNY');
|
||||
@@ -266,8 +323,8 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio
|
||||
avgChungcunSumFlow = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / calData.length : 0;
|
||||
item.chungchunFlow = avgChungcunSumFlow;
|
||||
item.rainCalInflAmnt = Number(avgChungcunSumFlow) + Number(item.rdiiValue);
|
||||
return item;
|
||||
}));
|
||||
return {...item, index:index}
|
||||
});
|
||||
|
||||
const excelDownList: ExcelType[] = [];
|
||||
const rtnData = reData.map((item: RdiProps) => {
|
||||
@@ -339,11 +396,6 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio
|
||||
const roundMinSummerBodInfl = Number(roundNumber(minSummerBodInfl, 0).toString().replaceAll(',',''));
|
||||
const roundMinSummerBod = Number(roundNumber(minSummerBod, 1).toString().replaceAll(',',''));
|
||||
const roundWinterBodSunny = Number(roundNumber(winterBodSunny, 1).toString().replaceAll(',',''));
|
||||
|
||||
console.log('bsccd : ', item.bscFctCd);
|
||||
console.log('roundMinSummerBodInfl : ',roundMinSummerBodInfl);
|
||||
console.log('roundMinSummerBod : ',roundMinSummerBod);
|
||||
console.log('roundWinterBodSunny : ',roundWinterBodSunny);
|
||||
|
||||
const winterBodAvg = Number(roundNumber((roundWinterBodSunny / winterCnt), 1).toString().replaceAll(',',''));
|
||||
// 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD))
|
||||
@@ -361,11 +413,11 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio
|
||||
|
||||
item.summerMinBodValue = roundNumber(rtnSummerBod,1);
|
||||
item.inflAmnt = roundNumber(rtnSummerBodInfl.toString(), 0);
|
||||
item.winterAvgBodLowRainfall = roundNumber(rtnWinterInflBod, 1);
|
||||
item.rdiiValue = roundNumber(rtnRdiValue, 0);
|
||||
item.winterAvgBodLowRainfall = rtnWinterInflBod?roundNumber(rtnWinterInflBod, 1):0;
|
||||
item.rdiiValue = rtnRdiValue?roundNumber(rtnRdiValue, 0):0;
|
||||
item.infoRnDay = roundNumber(rtnRdiRain, 0);
|
||||
item.chungchunFlow = roundNumber(chungchunFlow, 0);
|
||||
item.rainCalInflAmnt = roundNumber(Number(item.chungchunFlow.toString().replaceAll(',','')) + Number(item.rdiiValue.toString().replaceAll(',','')), 0);
|
||||
item.rainCalInflAmnt = roundNumber(Number(item.chungchunFlow.toString().replaceAll(',','')) + Number(item.rdiiValue.toString().replaceAll(',','')), 0) || 0;
|
||||
item.properYn = Number(item.rainCalInflAmnt.toString().replaceAll(',','')) > Number(item.fctCpc.toString().replaceAll(',','')) ? '초과유입' : '적정';
|
||||
|
||||
}
|
||||
@@ -374,7 +426,7 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio
|
||||
dataFormSetting(item);
|
||||
})
|
||||
|
||||
if(pageSize>5000){
|
||||
if(pageSize>=5000){
|
||||
rtnData.forEach((item: RdiProps) => {
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
|
||||
import { roundNumber } from "@/app/components/common/DataForm";
|
||||
import { OSU_PERCENT } from "../common";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { fetchFacilityListInit } from "../processFacility";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
@@ -124,18 +125,23 @@ const tempSewageOccurList:modalTableType[] = []
|
||||
* Store - API
|
||||
====================================*/
|
||||
|
||||
const fetchSewageOccurList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
/*const fetchSewageOccurList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
// 20250701임시시
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count }
|
||||
|
||||
/*
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/fclt/qlty/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count } */
|
||||
return { data: res.data, count: res.count }
|
||||
}*/
|
||||
|
||||
const fetchSweageOccurListFlow = async(fcltyCd : string, searchYear : string) => {
|
||||
const url = '/fclt/flow/' + fcltyCd + '/' + searchYear;
|
||||
const res = await getFetch('fo', url);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**====================================
|
||||
@@ -194,6 +200,17 @@ export const sewageOccurInitState: SewageOccurType = {
|
||||
}
|
||||
}
|
||||
|
||||
// 병렬 처리 제한용 헬퍼
|
||||
async function processInBatches(items, batchSize, callback) {
|
||||
const results:any = [];
|
||||
for (let i = 0; i < items.length; i += batchSize) {
|
||||
const batch = items.slice(i, i + batchSize);
|
||||
const batchResults = await Promise.all(batch.map(callback));
|
||||
results.push(...batchResults);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
export type SewageOccurStore = SewageOccurType & SewageOccurActions;
|
||||
|
||||
// Add type definitions for API responses
|
||||
@@ -213,32 +230,49 @@ export type FlowResponse = {
|
||||
export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
||||
return {
|
||||
searchSewageOccurList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
set((state: SewageOccurType) => ({
|
||||
...state,
|
||||
SewageOccur: {
|
||||
...state.SewageOccur,
|
||||
isLoading: true,
|
||||
},
|
||||
}));
|
||||
const res = await fetchSewageOccurList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const excelDownList: ExcelType[] = [];
|
||||
const data = res.data;
|
||||
// Promise.all을 사용하여 모든 비동기 작업이 완료될 때까지 기다림
|
||||
const calData = await Promise.all(data.map(async (item: SewageOccurProps) => {
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
const facilityInitData = await fetchFacilityListInit(pageNo, pageSize, part, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
if(pageSize < 5000){
|
||||
set((state: SewageOccurType) => ({
|
||||
...state,
|
||||
SewageOccur: {
|
||||
...state.SewageOccur,
|
||||
sewageOccurList : [],
|
||||
sewageOccurCount : facilityInitData.count,
|
||||
excelList : [],
|
||||
isLoading: true
|
||||
},
|
||||
}));
|
||||
}else{
|
||||
set((state: SewageOccurType) => ({
|
||||
...state,
|
||||
SewageOccur: {
|
||||
...state.SewageOccur,
|
||||
excelList : [],
|
||||
isLoading: true
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
const fcltylist = facilityInitData.data;
|
||||
|
||||
const calData = await processInBatches(fcltylist, 20, async (item: SewageOccurProps, index: number) => {
|
||||
const bscFctCd = item.bscFctCd;
|
||||
const res = await fetchSweageOccurListFlow(bscFctCd, searchYear).catch(() => {
|
||||
console.log('Error fetching flow data for facility code:', bscFctCd);
|
||||
return { data: [], count: 0 };
|
||||
});
|
||||
|
||||
item.sidoNm = item.sidoNm || '';
|
||||
item.sggNm = item.sggNm || '';
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
item.swageChangePercent = 90;
|
||||
|
||||
const bscFctCd = item.bscFctCd;
|
||||
const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as FlowResponse;
|
||||
|
||||
let sumChungcunDay = 0;
|
||||
let chungcunSumFlow = 0;
|
||||
let totWaterUsage = 0;
|
||||
|
||||
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
|
||||
const rainEffectData = CalcRainEffect(res2.data);
|
||||
const rainEffectData = CalcRainEffect(res.data);
|
||||
|
||||
rainEffectData.forEach((item: FlowDataItem) => {
|
||||
|
||||
@@ -246,27 +280,25 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
||||
chungcunSumFlow += Number(item.inflAmnt);
|
||||
sumChungcunDay += 1;
|
||||
}
|
||||
|
||||
totWaterUsage += Number(item.inflAmnt);
|
||||
});
|
||||
const avg = totWaterUsage /res2.count;
|
||||
|
||||
const avg = res.count == 0 ? 0 : totWaterUsage /res.count;
|
||||
item.waterUsage = parseFloat((avg * 0.65).toFixed(2));
|
||||
item.sewageInputYear = parseFloat(avg.toFixed(2));
|
||||
item.sewageInputChungchun = parseFloat((chungcunSumFlow===0?0:(chungcunSumFlow / sumChungcunDay)).toFixed(2));
|
||||
item.estimationSewage = parseFloat((item.waterUsage * (item.swageChangePercent/100)).toFixed(2));
|
||||
return item;
|
||||
}));
|
||||
|
||||
calData.forEach((item: SewageOccurProps) => {
|
||||
DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float0', column: 'waterUsage', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float0', column: 'swageChangePercent', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float0', column: 'estimationSewage', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float0', column: 'sewageInputYear', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float0', column: 'sewageInputChungchun', item: item as unknown as Record<string, unknown> });
|
||||
// 반올림 처리
|
||||
["fctCpc", "waterUsage", "swageChangePercent", "estimationSewage", "sewageInputYear", "sewageInputChungchun"].forEach(
|
||||
(key) => (item[key] = roundNumber(item[key], 0))
|
||||
);
|
||||
|
||||
return {...item, index:index};
|
||||
});
|
||||
|
||||
if(pageSize>5000){
|
||||
if(pageSize >= 5000){
|
||||
const excelDownList: ExcelType[] = [];
|
||||
calData.forEach((item: SewageOccurProps) => {
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
@@ -286,21 +318,109 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
||||
"청천시하수유입량(m³/일)": item.sewageInputChungchun,
|
||||
});
|
||||
});
|
||||
set((state: SewageOccurType) => ({
|
||||
...state,
|
||||
SewageOccur: {
|
||||
...state.SewageOccur,
|
||||
excelList: excelDownList,
|
||||
isLoading : false,
|
||||
},
|
||||
}));
|
||||
}else{
|
||||
set((state: SewageOccurType) => ({
|
||||
...state,
|
||||
SewageOccur: {
|
||||
...state.SewageOccur,
|
||||
sewageOccurList : calData,
|
||||
sewageOccurCount : facilityInitData.count,
|
||||
isLoading: false,
|
||||
excelList: [],
|
||||
},
|
||||
}));
|
||||
}
|
||||
// 조회 데이터 설정
|
||||
set((state: any) => ({
|
||||
...state,
|
||||
SewageOccur: pageSize<5000?{
|
||||
...state.SewageOccur,
|
||||
sewageOccurList: calData,
|
||||
sewageOccurCount: res.count,
|
||||
isLoading : false,
|
||||
}:{
|
||||
...state.SewageOccur,
|
||||
excelList: excelDownList,
|
||||
isLoading : false,
|
||||
},
|
||||
}))
|
||||
|
||||
/* fetchSewageOccurList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm).then(async (res) => {
|
||||
const excelDownList: ExcelType[] = [];
|
||||
const data = res.data;
|
||||
// Promise.all을 사용하여 모든 비동기 작업이 완료될 때까지 기다림
|
||||
const calData = await Promise.all(data.map(async (item: SewageOccurProps) => {
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
item.swageChangePercent = 90;
|
||||
|
||||
const bscFctCd = item.bscFctCd;
|
||||
const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as FlowResponse;
|
||||
|
||||
let sumChungcunDay = 0;
|
||||
let chungcunSumFlow = 0;
|
||||
let totWaterUsage = 0;
|
||||
|
||||
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
|
||||
const rainEffectData = CalcRainEffect(res2.data);
|
||||
|
||||
rainEffectData.forEach((item: FlowDataItem) => {
|
||||
|
||||
if(Number(item.rainEffectDay) === 0){
|
||||
chungcunSumFlow += Number(item.inflAmnt);
|
||||
sumChungcunDay += 1;
|
||||
}
|
||||
|
||||
totWaterUsage += Number(item.inflAmnt);
|
||||
});
|
||||
const avg = totWaterUsage /res2.count;
|
||||
item.waterUsage = parseFloat((avg * 0.65).toFixed(2));
|
||||
item.sewageInputYear = parseFloat(avg.toFixed(2));
|
||||
item.sewageInputChungchun = parseFloat((chungcunSumFlow===0?0:(chungcunSumFlow / sumChungcunDay)).toFixed(2));
|
||||
item.estimationSewage = parseFloat((item.waterUsage * (item.swageChangePercent/100)).toFixed(2));
|
||||
return item;
|
||||
}));
|
||||
|
||||
calData.forEach((item: SewageOccurProps) => {
|
||||
DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float0', column: 'waterUsage', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float0', column: 'swageChangePercent', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float0', column: 'estimationSewage', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float0', column: 'sewageInputYear', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float0', column: 'sewageInputChungchun', item: item as unknown as Record<string, unknown> });
|
||||
});
|
||||
|
||||
if(pageSize>5000){
|
||||
calData.forEach((item: SewageOccurProps) => {
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시설명: item.bscFctNm,
|
||||
시도: item.sidoNm,
|
||||
시군구: item.sggNm,
|
||||
주소: item.daddr,
|
||||
"시설용량(m³/일)": item.fctCpc,
|
||||
"물사용량(m³/일)": item.waterUsage,
|
||||
"오수전환율(%)": item.swageChangePercent,
|
||||
"오수발생량추정(m³/일)": item.estimationSewage,
|
||||
"연간하수유입량(m³/일)": item.sewageInputYear,
|
||||
"청천시하수유입량(m³/일)": item.sewageInputChungchun,
|
||||
});
|
||||
});
|
||||
}
|
||||
// 조회 데이터 설정
|
||||
set((state: any) => ({
|
||||
...state,
|
||||
SewageOccur: pageSize<5000?{
|
||||
...state.SewageOccur,
|
||||
sewageOccurList: calData,
|
||||
sewageOccurCount: res.count,
|
||||
isLoading : false,
|
||||
}:{
|
||||
...state.SewageOccur,
|
||||
excelList: excelDownList,
|
||||
isLoading : false,
|
||||
},
|
||||
}))
|
||||
}); */
|
||||
},
|
||||
|
||||
searchSewageOccurDetailList: async (bscFctCd: string, searchYear: string, startYearMonth?: string, endYearMonth?: string) => {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import DataForm, { roundNumber } from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import type { ExcelType, UnderWaterInputModalProps, UnderWaterProps } from "./types";
|
||||
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
|
||||
import { OSU_PERCENT } from "../common";
|
||||
import { fetchFacilityListInit } from "../processFacility";
|
||||
export type { TableUpperProps };
|
||||
|
||||
// SewageOccurDetailProps 타입을 여기에 정의
|
||||
@@ -187,18 +188,25 @@ export interface ApiResponse {
|
||||
count: number;
|
||||
}
|
||||
|
||||
/*
|
||||
const fetchUnderWaterList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count }
|
||||
/*
|
||||
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/fclt/qlty/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count } */
|
||||
return { data: res.data, count: res.count }
|
||||
|
||||
//return { data: underWaterList, count: 2 };
|
||||
}*/
|
||||
|
||||
const fetchUnderWaterListFlow = async(fcltyCd : string, searchYear : string) => {
|
||||
const url = '/fclt/flow/' + fcltyCd + '/' + searchYear;
|
||||
const res = await getFetch('fo', url);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**====================================
|
||||
@@ -220,7 +228,7 @@ export type UnderWaterType = {
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
underWaterList: UnderWaterProps[]; // Changed from facilityAreaProps to ProcessAreaProps
|
||||
underWaterList: any[]; // Changed from facilityAreaProps to ProcessAreaProps
|
||||
underWaterCount: number;
|
||||
excelList: ExcelType[];
|
||||
isLoading: boolean;
|
||||
@@ -265,29 +273,57 @@ const dataFormSetting=(item : UnderWaterProps)=> {
|
||||
DataForm({ type: 'float0', column: 'underWaterInputWinter', item: item as unknown as Record<string, unknown>});
|
||||
}
|
||||
|
||||
// 병렬 처리 제한용 헬퍼
|
||||
async function processInBatches(items, batchSize, callback) {
|
||||
const results :any = [];
|
||||
for (let i = 0; i < items.length; i += batchSize) {
|
||||
const batch = items.slice(i, i + batchSize);
|
||||
const batchResults = await Promise.all(batch.map(callback));
|
||||
results.push(...batchResults);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
const res = await fetchUnderWaterList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const data = res.data;
|
||||
const calData = await Promise.all(data.map(async (item: UnderWaterProps) => {
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
if(pageSize < 5000){
|
||||
set((state: UnderWaterType) => ({
|
||||
...state,
|
||||
UnderWater: {
|
||||
...state.UnderWater,
|
||||
underWaterList : facilityInitData.data,
|
||||
underWaterCount : facilityInitData.count,
|
||||
isInit : true,
|
||||
isLoading: true,
|
||||
},
|
||||
}));
|
||||
}else{
|
||||
set((state: UnderWaterType) => ({
|
||||
...state,
|
||||
UnderWater: {
|
||||
...state.UnderWater,
|
||||
isLoading: true,
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
const fcltylist = facilityInitData.data;
|
||||
|
||||
const calData = await processInBatches(fcltylist, 20, async (item: any, index: number) => {
|
||||
const bscFctCd = item.bscFctCd;
|
||||
const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as ApiResponse;
|
||||
const calData = CalcRainEffect(res2.data, 'SUNNY');
|
||||
const res = await fetchUnderWaterListFlow(bscFctCd, searchYear).catch((error) => {
|
||||
console.log('Error fetching flow data for facility code:', bscFctCd, error);
|
||||
return { data: [], count: 0 }; // 에러 발생 시 빈 데이터 반환
|
||||
});
|
||||
|
||||
item.sidoNm = item.sido || '';
|
||||
item.sggNm = item.gugun || '';
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
|
||||
let chungcunSumFlow = 0;
|
||||
|
||||
@@ -297,7 +333,8 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
|
||||
let sumWinterChungcunDay = 0;
|
||||
let sumWinterChungcunFlow = 0;
|
||||
|
||||
calData.forEach((flowItem: FlowDataItem) => {
|
||||
const rainEffectData = CalcRainEffect(res.data, 'SUNNY');
|
||||
rainEffectData.forEach((flowItem: FlowDataItem) => {
|
||||
chungcunSumFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
|
||||
|
||||
if(flowItem.msrDt.substring(4,6) ==='06' || flowItem.msrDt.substring(4,6) ==='07' || flowItem.msrDt.substring(4,6) ==='08'){
|
||||
@@ -308,25 +345,32 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
|
||||
sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
|
||||
}
|
||||
});
|
||||
const usage = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / calData.length:0;
|
||||
|
||||
let totWaterInflow = 0
|
||||
|
||||
const rainEffectTot = CalcRainEffect(res.data);
|
||||
rainEffectTot.forEach((flowItem: FlowDataItem) => {
|
||||
totWaterInflow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
|
||||
});
|
||||
|
||||
|
||||
const avg = res.count === 0 ? 0 : totWaterInflow / res.count;
|
||||
|
||||
const usage = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / rainEffectData.length:0;
|
||||
const summerUsage = sumSummerChungcunFlow?sumSummerChungcunFlow / sumSummerChungcunDay:0;
|
||||
const winterUsage = sumWinterChungcunFlow?sumWinterChungcunFlow / sumWinterChungcunDay:0;
|
||||
|
||||
//bscFctCd === '11200PB001R') 중랑 - 테스트할 때 코드넣고 해야 보기편해요~
|
||||
/* if(bscFctCd === '11200PB001R') {
|
||||
console.log('calData.length : ', calData.length);
|
||||
console.log('usage : ', usage, 'summerUsage : ', summerUsage, 'winterUsage : ', winterUsage);
|
||||
} */
|
||||
item.inflAmnt = roundNumber(avg, 0);
|
||||
item.underWaterInputYear = Math.round((usage-(usage*0.65*OSU_PERCENT)) * 1) / 1;
|
||||
item.underWaterInputSummer = Math.round((summerUsage-(summerUsage*0.65*OSU_PERCENT)) * 1) / 1;
|
||||
item.underWaterInputWinter = Math.round((winterUsage-(winterUsage*0.65*OSU_PERCENT)) * 1) / 1;
|
||||
item.properYn = Math.round( (Number(usage-(usage*0.65*OSU_PERCENT)) / Number(item.inflAmnt)) * 100 * 1 ) / 1 > 20?'초과유입':'적정';
|
||||
return item;
|
||||
}));
|
||||
return {...item, index:index};
|
||||
});
|
||||
|
||||
const excelDownList: ExcelType[] = [];
|
||||
if(pageSize>5000){
|
||||
calData.forEach(item => {
|
||||
if(pageSize>= 5000){
|
||||
const excelDownList: ExcelType[] = [];
|
||||
calData.forEach((item : any) => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
/* item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
@@ -349,27 +393,26 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
|
||||
적정여부: item.properYn,
|
||||
});
|
||||
});
|
||||
set((state: UnderWaterType) => ({
|
||||
...state,
|
||||
UnderWater: {
|
||||
...state.UnderWater,
|
||||
excelList: excelDownList,
|
||||
isLoading : false,
|
||||
},
|
||||
}));
|
||||
}else{
|
||||
data.forEach((item: UnderWaterProps) => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
/* item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; */
|
||||
});
|
||||
set((state: UnderWaterType) => ({
|
||||
...state,
|
||||
UnderWater: {
|
||||
...state.UnderWater,
|
||||
underWaterList: calData,
|
||||
underWaterCount: facilityInitData.count,
|
||||
excelList: [],
|
||||
isLoading : false,
|
||||
},
|
||||
}));
|
||||
}
|
||||
set((state: UnderWaterType) => ({
|
||||
...state,
|
||||
UnderWater: pageSize<5000?{
|
||||
...state.UnderWater,
|
||||
underWaterList: calData,
|
||||
underWaterCount: res.count,
|
||||
isLoading : false,
|
||||
}:{
|
||||
...state.UnderWater,
|
||||
isLoading : false,
|
||||
excelList: excelDownList
|
||||
},
|
||||
}))
|
||||
},
|
||||
|
||||
unserWaterModal:async (bscFctCd, searchYear, startYm, endYm)=>{
|
||||
|
||||
+16
-4
@@ -33,9 +33,20 @@ function buildAuthHeaders(req: NextRequest): Headers {
|
||||
|
||||
/** 공통: rewrite 응답 생성 (헤더 주입 여부 선택) */
|
||||
function rewriteWith(url: string, req: NextRequest, withAuth = false): NextResponse {
|
||||
return withAuth
|
||||
? NextResponse.rewrite(new URL(url), { headers: buildAuthHeaders(req) })
|
||||
: NextResponse.rewrite(new URL(url));
|
||||
|
||||
const headers = withAuth ? buildAuthHeaders(req) : new Headers(req.headers);
|
||||
|
||||
// if (url.indexOf("/operation-service") !== -1) {
|
||||
// // x-forwarded- 로 시작하는 헤더의 첫 번째 값만 남김
|
||||
// for (const [key, value] of headers.entries()) {
|
||||
// if (key.startsWith('x-forwarded-') && value.includes(',')) {
|
||||
// const first = (value?.split(',')[0] || '').trim();
|
||||
// headers.set(key, first);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return NextResponse.rewrite(new URL(url), { headers });
|
||||
}
|
||||
|
||||
export function middleware(req: NextRequest) {
|
||||
@@ -91,7 +102,8 @@ export function middleware(req: NextRequest) {
|
||||
}
|
||||
|
||||
console.log(`[Middleware] Rewriting from '/geoserver' path to: ${newUrl}`);
|
||||
return NextResponse.rewrite(new URL(newUrl));
|
||||
const rewriteRequest = rewriteWith(newUrl, req, true);
|
||||
return rewriteRequest;
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/sewerage-service")) {
|
||||
|
||||
@@ -99,7 +99,8 @@ export function middleware(req: NextRequest) {
|
||||
}
|
||||
|
||||
console.log(`[Middleware] Rewriting from '/geoserver' path to: ${newUrl}`);
|
||||
return NextResponse.rewrite(new URL(newUrl));
|
||||
const rewriteRequest = rewriteWith(newUrl, req, true);
|
||||
return rewriteRequest;
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/attach-service")
|
||||
|
||||
@@ -23,10 +23,11 @@ export default function HasuStatPage() {
|
||||
alert("Client IP:" + ip);
|
||||
|
||||
const is10 = /^10\./.test(ip);
|
||||
setStatus(is10 ? "redirect-internal" : "redirect-root");
|
||||
const is172 = /^172\./.test(ip);
|
||||
setStatus(is10||is172 ? "redirect-internal" : "redirect-root");
|
||||
|
||||
// Use location.replace so user can't go back to this page
|
||||
if (is10) {
|
||||
if (is10||is172) {
|
||||
// redirect to internal IP
|
||||
window.open('http://10.101.163.102:8888/cms/lay1/WS10000014/program.do', '_blank');
|
||||
} else {
|
||||
|
||||
@@ -2,11 +2,26 @@ import { NextResponse } from 'next/server';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const headers = request.headers;
|
||||
// Prefer x-forwarded-for (may be comma separated list)
|
||||
const xff = headers.get('x-forwarded-for') ?? headers.get('x-real-ip') ?? '';
|
||||
let ip = '';
|
||||
if (xff && xff.length > 0) {
|
||||
ip = String(xff).split(',')[0].trim();
|
||||
// 1. x-forwarded-for 또는 x-real-ip에서 IP 추출
|
||||
let ip = headers.get('x-forwarded-for') || headers.get('x-real-ip') || '';
|
||||
|
||||
// IP가 있으면 첫 번째 IP 주소만 추출
|
||||
if (ip) {
|
||||
if (ip.includes(',')) {
|
||||
ip = ip.split(',')[0]?.trim()||'';
|
||||
} else {
|
||||
ip = ip.trim();
|
||||
}
|
||||
}
|
||||
|
||||
// 3. IPv6 주소 정규화
|
||||
if (ip.startsWith('::ffff:')) {
|
||||
ip = ip.replace('::ffff:', '');
|
||||
}
|
||||
|
||||
// 4. localhost IPv6를 IPv4로 변환
|
||||
if (ip === '::1') {
|
||||
ip = '127.0.0.1';
|
||||
}
|
||||
|
||||
return NextResponse.json({ ip });
|
||||
|
||||
@@ -122,7 +122,8 @@ export function middleware(req: NextRequest) {
|
||||
}
|
||||
|
||||
//console.log(`[Middleware] Rewriting from '/geoserver' path to: ${newUrl}`);
|
||||
return NextResponse.rewrite(new URL(newUrl));
|
||||
const rewriteRequest = rewriteWith(newUrl, req, true);
|
||||
return rewriteRequest;
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/sewerage-service")) {
|
||||
|
||||
Reference in New Issue
Block a user