Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev

This commit is contained in:
2026-02-12 10:50:13 +09:00
126 changed files with 7051 additions and 4813 deletions
+1
View File
@@ -25,3 +25,4 @@ apps/fo/.next/**/*
pnpm-lock.yaml
settings.json
.npmrc
.cursor
-7
View File
@@ -1,7 +0,0 @@
# apps/cs/src/shared/config/env.ts 참고
NEXT_PUBLIC_PORT=3000
NEXT_PUBLIC_PROXY_HOST=http://localhost:3000
NEXT_PUBLIC_SITE_ID=CS
NEXT_PUBLIC_SUB_DOMAIN=http://localhost:3000
NEXT_PUBLIC_SERVER_API_URL=http://192.168.0.102:8000
NEXT_PUBLIC_TINY_API_KEY=t9nc4z6inquvvd5pq1vea8wcp7lb01qmqseh6egms9vpaju2
+13 -6
View File
@@ -1,7 +1,14 @@
# apps/cs/src/shared/config/env.ts 참고
NEXT_PUBLIC_PORT=3000
NEXT_PUBLIC_PROXY_HOST=http://localhost:3000
NEXT_PUBLIC_SITE_ID=CS
NEXT_PUBLIC_SUB_DOMAIN=http://localhost:3000
NEXT_PUBLIC_SERVER_API_URL=http://192.168.0.102:8000
NEXT_PUBLIC_TINY_API_KEY=t9nc4z6inquvvd5pq1vea8wcp7lb01qmqseh6egms9vpaju2
NEXT_PUBLIC_PORT=3001
NEXT_PUBLIC_PROXY_HOST=http://localhost:3001
NEXT_PUBLIC_SITE_ID=CM
NEXT_PUBLIC_SUB_DOMAIN=http://localhost:13000
# NEXT_PUBLIC_SERVER_API_URL=http://localhost:8000
NEXT_PUBLIC_SERVER_API_URL=http://dev.onasys.co.kr:8000
NEXT_PUBLIC_LINK_BACKEND_API_HOST=http://rsone.iptime.org:10014
NEXT_PUBLIC_TINY_API_KEY=t9nc4z6inquvvd5pq1vea8wcp7lb01qmqseh6egms9vpaju2
NEXT_PUBLIC_SERVER_API_URL2=http://con.mind-one.co.kr:11083
NEXT_PUBLIC_SERVER_API_URL3=https://apigateway.apps.rsonesoft.com
NEXT_PUBLIC_SN=https://devlion.hasuon.co.kr
NEXT_PUBLIC_WR=https://devtiger.hasuon.co.kr
-14
View File
@@ -1,14 +0,0 @@
# apps/cs/src/shared/config/env.ts 참고
NEXT_PUBLIC_PORT=3000
NEXT_PUBLIC_PROXY_HOST=http://localhost:3000
NEXT_PUBLIC_SITE_ID=CM
NEXT_PUBLIC_SUB_DOMAIN=http://localhost:13000
# NEXT_PUBLIC_SERVER_API_URL=http://localhost:8000
NEXT_PUBLIC_SERVER_API_URL=http://dev.onasys.co.kr:8000
NEXT_PUBLIC_LINK_BACKEND_API_HOST=http://rsone.iptime.org:10014
NEXT_PUBLIC_TINY_API_KEY=t9nc4z6inquvvd5pq1vea8wcp7lb01qmqseh6egms9vpaju2
NEXT_PUBLIC_SERVER_API_URL2=http://con.mind-one.co.kr:11083
NEXT_PUBLIC_SERVER_API_URL3=https://apigateway.apps.rsonesoft.com
NEXT_PUBLIC_SN=https://devlion.hasuon.co.kr
NEXT_PUBLIC_WR=https://devtiger.hasuon.co.kr
-11
View File
@@ -1,11 +0,0 @@
# apps/cs/src/shared/config/env.ts 참고
NEXT_PUBLIC_PORT=3000
NEXT_PUBLIC_PROXY_HOST=http://localhost:3000
NEXT_PUBLIC_SITE_ID=CS
NEXT_PUBLIC_SUB_DOMAIN=http://localhost:13000
NEXT_PUBLIC_SERVER_API_URL=http://192.168.0.102:8000
NEXT_PUBLIC_TINY_API_KEY=t9nc4z6inquvvd5pq1vea8wcp7lb01qmqseh6egms9vpaju2
NEXT_PUBLIC_SERVER_API_URL2=http://apigateway.iipbs-was.svc.cluster.local:8000
NEXT_PUBLIC_SN=https://lion.hasuon.co.kr
NEXT_PUBLIC_WR=https://tiger.hasuon.co.kr
BIN
View File
Binary file not shown.
-1
View File
@@ -15,4 +15,3 @@ export async function POST() {
cookieStore.delete(CLAIM_NAME);
return NextResponse.json({ message: "Logged out" }, { status: 200 });
}
+14 -6
View File
@@ -3,10 +3,22 @@ import type { NextConfig } from "next";
const subDomain =
process.env.NEXT_PUBLIC_SUB_DOMAIN || "http://localhost:13000";
const backendUrl = process.env.NEXT_PUBLIC_SERVER_API_URL || "http://192.168.0.102:8000";
const nextConfig: NextConfig = {
output: "standalone",
experimental: {
proxyTimeout: 600000,
},
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
},
logging: {
fetches: {
fullUrl: true,
},
},
async rewrites() {
return {
beforeFiles: [
@@ -27,10 +39,6 @@ const nextConfig: NextConfig = {
source: "/cms/:path*",
destination: `${subDomain}/cms/:path*`,
},
{
source: "/user-service/:path*",
destination: `${backendUrl}/user-service/:path*`,
},
],
fallback: [],
};
@@ -1,4 +1,4 @@
import { AUTH_USER_ID, CLAIM_NAME } from "@/shared/config";
import { ACCESS_TOKEN, AUTH_USER_ID, CLAIM_NAME, REFRESH_TOKEN } from "@/shared/config";
import { getCookie, setCookie, removeCookie } from "@/shared/lib";
export class TokenManager {
@@ -76,6 +76,8 @@ export class TokenManager {
this.removeToken(CLAIM_NAME);
this.removeToken(AUTH_USER_ID);
this.removeToken(REFRESH_TOKEN);
this.removeToken(ACCESS_TOKEN);
}
}
+10 -4
View File
@@ -3,7 +3,7 @@
import { useRouter } from "next/navigation";
import { useQuery } from "@tanstack/react-query";
import { getCoreRowModel } from "@tanstack/react-table";
import { PostApi, type MyPost } from "@/entities/post";
import { PostApi, type MyPost, type NoticePost } from "@/entities/post";
import { ENDPOINT } from "@/shared/config";
import { useDataTable } from "@/shared/lib";
import {
@@ -23,15 +23,21 @@ const MyPostList: React.FC = () => {
}),
});
const handleMyPostRowClick = (row: MyPost) => {
router.push(`/cms/${row.bbsTypeCd.toLowerCase()}/${row.bbsId}/${row.pstNo}`);
};
const { tableComponent: myPostTableComponent } = useDataTable({
query: myPostQuery,
tableOptions: {
columns: myPostTableColumns,
getCoreRowModel: getCoreRowModel(),
columns: myPostTableColumns,
getCoreRowModel: getCoreRowModel(),
},
dataTableOptions: {
variant: "line",
variant: "line",
onRowClick: handleMyPostRowClick
},
});
return (
@@ -26,7 +26,7 @@ const NoticeList: React.FC = () => {
});
const handleNoticePostRowClick = (row: NoticePost) => {
router.push(`/bbs/bbsnotice/${row.bbsId}/${row.pstNo}`);
router.push(`/cms/${row.bbsTypeCd.toLowerCase()}/${row.bbsId}/${row.pstNo}`);
};
const handleMoreClick = () => {
@@ -40,12 +40,12 @@ const NoticeList: React.FC = () => {
const { tableComponent: noticePostTableComponent } = useDataTable({
query: noticePostQuery,
tableOptions: {
columns: noticePostTableColumns,
getCoreRowModel: getCoreRowModel(),
columns: noticePostTableColumns,
getCoreRowModel: getCoreRowModel(),
},
dataTableOptions: {
variant: "line",
onRowClick: handleNoticePostRowClick,
variant: "line",
onRowClick: handleNoticePostRowClick,
},
});
+7 -2
View File
@@ -60,13 +60,18 @@ async function handler(
[AUTH_USER_ID]: userId,
});
const forwardedHost = request.headers.get("x-forwarded-host");
const host = request.headers.get("host");
const actualHost = forwardedHost || host || new URL(request.url).hostname.toString();
// 운영 환경에서 domain 설정
const domain = actualHost.includes("hasuon.or.kr") ? ".hasuon.or.kr" : actualHost;
if (refreshToken) {
cookieStore.set(REFRESH_TOKEN, refreshToken, {
httpOnly: true,
sameSite: "lax",
// domain: domain,
sameSite: "strict",
domain: domain,
path: "/",
});
}
+831
View File
@@ -0,0 +1,831 @@
# 표준단어정의서
AI 이해용으로 정리된 표준단어명, 영문약어명, 영문명 목록입니다.
| 표준단어명 | 표준단어 영문약어명 | 표준단어 영문명 |
|-----------|-------------------|----------------|
| BOD | BOD | Biochemical Oxygen Demand |
| C/N비 | CNR | Carbon-Nitrogen Ratio |
| COD | COD | Chemical Oxygen Demand |
| F/M비 | FMR | Food-Microorganism Ratio |
| GISD | GISDATA | Geographic Information System Data |
| HTML | HTML | Hypertext Markup Language |
| ID | ID | Id |
| IP | IP | Internet Protocol |
| KEY | KEY | Key |
| ND | ND | Not Detected |
| NON | NON | Non |
| NTU | NTU | Nephelometry Turbidity Unit |
| OPT | OPT | Opt |
| PAC | PAC | Polyaluminium Chloride |
| PH | PH | Hydrogen Exponent |
| PKI | PKI | Public Key Infrastructure |
| POOL | POOL | Pool |
| SS | SS | Suspended Solids (Ss) |
| TCE | TCE | Trichloroethane |
| TM | TM | Transverse Mercator |
| T-N | TN | Total Nitrogen |
| TOC | TOC | Total Organic Carbon |
| T-P | TP | Total Phosphorus |
| URL | URL | Uniform Resource Locator |
| 가구 | HSHD | Household |
| 가능 | PSBL | Possible |
| 가동 | OPR | Operation |
| 가산 | ADTN | Addition |
| 가성소다 | NAOH | Caustic Soda(Nach) |
| 가축분뇨 | ANMA | Animal Manure |
| 값 | VAL | Value |
| 강도 | IN | Intensity |
| 강우 | RAIN | Rain |
| 개방 | OPN | Opening |
| 개별 | INDIV | Individual |
| 개보수비 | RPAFEE | Repair Fee |
| 개설 | ESTBL | Establishment |
| 개시 | STRT | Start |
| 개정 | RVSN | Revision |
| 개조 | REMDEL | Remodeling |
| 개체 | INDVD | Individual |
| 개체군 | POPU | Population |
| 개폐 | RORGN | Reorganization |
| 갱신 | UPDT | Update |
| 건물 | BLDG | Building |
| 건설 | CONC | Construction |
| 건수 | NOCS | The Number Of Cases |
| 건조 | DRY | Dry |
| 검사 | INSP | Inspection |
| 검사서 | EXRPT | Examination Report |
| 검정 | RCGN | Recognition |
| 검증 | VRFC | Verification |
| 검출 | DETECT | Detection |
| 검토 | RVW | Review |
| 격자 | LATTC | Lattice |
| 결과 | RSLT | Result |
| 결의 | DCIS | Decision |
| 결정 | DCSN | Decision |
| 경계 | BNDRY | Boundary |
| 경과 | PROC | Process |
| 경도 | LOT | Longitude |
| 경보 | ALARM | Alarm |
| 경사판 | ICNTPT | Inclination plate |
| 계 | SUM | Summation |
| 계량기 | MRNR | Measuring Instrument |
| 계량기분리 | METRSPRT | Meter Separation |
| 계면 | SGLV | Sludge Level |
| 계산식 | FMUL | Formula |
| 계약 | CTRT | Contract |
| 계약기간 | CNTRPD | Contract Period |
| 계절 | SEASON | Season |
| 계획 | PLAN | Plan |
| 고도처리 | AWTR | Advanced Water Treatment |
| 고시 | ANCMNT | Announcement |
| 고액분리 | SLSPRT | Solid-Liquid Separation |
| 고형물체류시간 | SRT | Solid Retention Time |
| 공간데이터 | SPCEDATA | Space Data |
| 공공 | PUBLIC | Public |
| 공급 | SPLY | Supply |
| 공기 | AIR | Air |
| 공기여과 | ARFT | Air Filter |
| 공문 | ODOC | Official Documnet |
| 공법 | MSRC | Method Of Construction |
| 공사 | CSTRN | Construction |
| 공사비 | CONSTEXPN | Construction Expenses |
| 공업지역 | MNFTR_ARA | Manufacturing Area |
| 공용면적 | CMAR | Common Area |
| 공통 | CMMN | Commonness |
| 관 | PP | Pipe |
| 관계 | REL | Relation |
| 관련 | RLTN | Relation |
| 관로 | PPLINE | Pipe Line |
| 관리 | MNG | Management |
| 관리기관 | MGC | Management Agency |
| 관리자 | MNGR | Manager |
| 관찰 | WTCH | Watch |
| 관측 | OBSR | Observation |
| 관측소 | OBSRVT | Observatory |
| 교반기 | AGITOR | Agirator |
| 교정 | CRRC | Correction |
| 구간 | SCTN | Section |
| 구동 | DRIVE | Drive |
| 구분 | SE | Section |
| 구성 | CMPSG | Composing |
| 구역 | ZONE | Zone |
| 구조 | STRCT | Structure |
| 권역 | DSTR | District |
| 권한 | AUTH | Authority |
| 규격 | STNDRD | Standard |
| 규모 | SCAL | Scale |
| 규제 | REGL | Regulation |
| 균등 | EQLTY | Equality |
| 금액 | AMT | Amount |
| 급수 | WSP | Water Supply |
| 기간 | WHL | While |
| 기관 | INST | Institution |
| 기록 | RECD | Recording |
| 기록부 | REGI | Register |
| 기밀 | SCRET | Secret |
| 기법 | TECQU | Techniques |
| 기본 | BSIC | Basics |
| 기본정보 | BASINF | Bassinfo |
| 기본키 | PK | Primary Key |
| 기상 | WETHER | Weather |
| 기안 | DRFTG | Drafting |
| 기재 | WRIT | Write |
| 기점 | CDPNT | Cardinal Point |
| 기존 | LGCY | Legacy |
| 기준 | CRTR | Criteria |
| 기타 | ETC | Etc |
| 기한 | TERM | Term |
| 기후 | CLMT | Climate |
| 긴급 | EMRG | Emergency |
| 날개벽 | WW | Wing Wall |
| 날씨 | WETHR | Weather |
| 날짜 | DATE | DATE |
| 남조류 | BLAL | Blue-Green Algae |
| 납 | PB | Plumbum |
| 내려받기 | DWLD | Download |
| 내부반송 | ITNRCC | Internal Recycl |
| 내용 | CN | Content |
| 내용연수 | SVLF | Service Life |
| 냄새 | SMELL | Smell |
| 년 | YY | Year |
| 년간 | FAYR | For A Year |
| 노즐 | NZL | Nozzle |
| 노출 | EXPSR | Exposure |
| 농도 | DNSTY | Density |
| 농축 | TKN | Thickened |
| 누적 | ACML | Accumulate |
| 누출 | LKG | Leakage |
| 눈 | SNW | Snow |
| 단가 | UNPRC | Unit Price |
| 단기 | SRTPD | Short Period |
| 단순 | SIMPL | Simplicity |
| 단위 | UNIT | Unit |
| 대구역 | LZONE | Large Zone |
| 대분류 | LCLAS | Large Classification |
| 대장 | REGSTR | Register |
| 대장균 | COLI | Coliform, Fecal Coliform |
| 대장균군 | COLIB | Coliform Bacteria |
| 대지면적 | SIAR | Site Area |
| 대체 | RPLC | Replace |
| 덮개 | COVR | Cover |
| 데이타 | DAT | Data |
| 도구 | UNT | Unit |
| 도래 | ADVNT | Advent |
| 도로 | ROAD | Road |
| 도로명 | RN | Road Name |
| 도시 | CTY | City |
| 도엽 | MAPDMC | Map Demarcation |
| 도표 | CHART | Chart |
| 독성 | TOXCTY | Toxicity |
| 동의 | AGRE | Agreement |
| 동절기 | WSESN | The Winter Season |
| 등급 | GRD | Grade |
| 등기 | RG | Registered |
| 등록 | REG | Registration |
| 디바이스 | DVICE | Device |
| 디코딩 | DCD | Decoding |
| 레이어 | LYR | Layer |
| 로그인 | LGN | Login |
| 로우 | ROW | Row |
| 마감 | DDLN | Deadline |
| 마이크로필터 | MCRFT | Micro Filter |
| 막 | MBRN | Membrane |
| 만족도 | STFDG | Satisfaction Degree |
| 맑음 | CLAR | Clear |
| 매각 | SAL | Sale |
| 맨홀 | MH | Manhole |
| 맵 | MAP | Map |
| 메인 | MAIN | Main |
| 메일 | EMAIL | Email |
| 메탄올 | MTN | Methanol(CH3OH) |
| 명 | NM | Name |
| 모니터링 | MTRG | Monitoring |
| 모델 | MODL | Model |
| 모델링 | MODLNG | Modeling |
| 모래 | SAND | Sand |
| 목 | MOK | Mok |
| 무산소 | ANX | Anoxic |
| 무산소조 | ANX_TANK | Anoxic Tank |
| 무인센서 | MNLSENSR | Manless Sensor |
| 문서 | DCMT | Document |
| 물 | WTR | Water |
| 미급수 | NONWTRSPL | Non Water Supply |
| 미생물 | BLGC | Biological |
| 미세먼지 | PM | Particulate Matter |
| 미세목 | MCRB | Micro Bar |
| 민간위탁 | ETSVN | Entrustment To Civilian |
| 민감 | SST | Sensitive |
| 민원 | CVLCPT | Civil Complaint |
| 바이러스 | VIRS | Virus |
| 반기 | HT | Half Term |
| 반류수 | SIDSWT | Side Stream Water |
| 반송 | SNDBK | Send Back |
| 반송수 | RCCWT | Recycled Water |
| 반송슬러지 | RTNSLG | Return Sludge |
| 반영 | RFLT | Reflection |
| 반응조 | RETNK | Reactant Tank |
| 반출 | EXPRT | Export |
| 반토 | ALUM | Alumina |
| 반환 | GVBK | Giving Back |
| 받이 | INL | Inlet |
| 발생 | OCRN | Occurrence |
| 발전 | PWGNRT | Power Generation |
| 발주기관 | ORNT | Order Institution |
| 방류 | DCWTR | Discharge Water Stock Etc |
| 방류구 | DSCHG | Discharge |
| 방류수 | EFLEC | Effluence |
| 방문 | VST | Visit |
| 방문자 | VSTR | Visitor |
| 방법 | MTHD | Method |
| 방사 | RLSE | Release |
| 배관 | PLINE | Pipeline |
| 배분 | DSTRB | Distirbution |
| 배설물 | EXCRTN | Excretion |
| 배수 | DRNG | Drainage |
| 배수구역 | DRANGZN | Drainage Zone |
| 배출 | EXHST | Exhaust |
| 배출가스 | EMGA | Emission Gases |
| 배출구 | VENT | Vent |
| 배출시설 | DHGP | Discharge Equipment |
| 배출시험 | EXHTST | Exhaust Test |
| 배출자 | DCHGR | Discharge Person |
| 밸브 | VALVE | Valve |
| 번호 | NO | Number |
| 법 | LAW | Law |
| 법적 | LGL | Legal |
| 법정 | STTY | Statutory |
| 법정동 | STDG | Statutory Dong(Administrative District) |
| 법정리 | STLI | Statutory Li(Administrative District) |
| 변경 | CHG | Change |
| 변동 | FLCTN | Fluctuation |
| 변속기 | TRMIS | Transmission |
| 보고 | RPT | Report |
| 보고서 | RPOT | Report |
| 보관 | STORG | Storage |
| 보수 | MEND | Mend |
| 보유 | HOLD | Hold |
| 보정 | RVSION | Revision |
| 보조 | ASSISC | Assistance |
| 보조금 | SBSIDY | Subsidy |
| 복개 | COVE | Cover |
| 복토 | CWTH | Covering With Soil |
| 본류 | MI_RV | Main River |
| 본번 | MNO | Main Number |
| 부검 | ATPSY | Autopsy |
| 부과 | LEVY | Levy |
| 부과금 | LVYAMT | Levy Amount |
| 부기 | BUKIP | Bookkeeping |
| 부담금 | ALOTM | Allotment |
| 부번 | SNO | Sub Number |
| 부산물 | BYPRD | By-Product |
| 부서 | DEPT | Department |
| 부숙화 | DECPZ | Decomposed ~Ize |
| 부적합 | IMPPRTY | Impropriety |
| 부착 | ASN | Adhesion |
| 부품 | CMPNT | Components |
| 부하량 | LOADQTY | Load Quantity |
| 분과 | DIVSN | Division |
| 분뇨 | ENSO | Excreta, Night Soil |
| 분류 | CL | Classification |
| 분류군 | TAXON | Taxon |
| 분리막 | SPRTMBR | Separation Membrane |
| 분배 | DTRBT | Distribution |
| 분배조 | DTRBT_TANK | Distribution Tank |
| 분야 | RLM | Realm |
| 분원성 | FECL | Fecal |
| 분원성대장균군 | FCOLI | Fecal Coliform |
| 분원성연쇄상구균 | FCSTRCCI | Fecal Streptococci |
| 분할 | PRTIN | Partition |
| 비밀번호 | PSWD | Password |
| 비상 | EMGNY | Emergency |
| 비정상 | ABNRM | Abnormality |
| 사양 | SPECS | Specification |
| 사업비 | WCT | Working Cost |
| 사업장 | BPLC | Business Place |
| 사여과지 | SAND_ FILTR | Sand Filter |
| 사용 | USE | Use |
| 사용가능 | USABLE | Usable |
| 사용권 | RIOUS | Right Of Using |
| 사용량 | USG | USAGE |
| 사용자 | USER | User |
| 사위 | FDG | Four Directions Girth |
| 사유 | RESN | Reason |
| 사이클 | CYCLE | Cycle |
| 사이트 | SITE | Site |
| 사진 | PHOT | Photograph |
| 사항 | MATTR | Matter |
| 사후 | AFTFAT | After Fact |
| 삭제 | DEL | Deletion |
| 산기관 | DFS | Diffuser |
| 산업 | INDUST | Industrial |
| 산화환원전위 | ORP | Oxidation Reduction Potential |
| 살모넬라 | SLMN | Salmonella |
| 삼원촉매장치 | TWCTLC | Three Way Catalytic Converter |
| 상세 | DTL | Details |
| 상세주소 | DADDR | Detailed Address |
| 상수 | WT | Water |
| 상업지역 | CMCL_ARA | Commercial Area |
| 상태 | STUS | Status |
| 상품 | GDS | Goods |
| 상향류 | UFW | Upflow |
| 상호 | CONM | Company Name |
| 색도 | CRMTY | Chromaticity |
| 생략 | OMS | Omission |
| 생물 | LVB | Living Being |
| 생물반응조 | BIRAT | Bioreactor |
| 생물서식처 | ORGNHBT | Organism Habitat |
| 생물종 | BISP | Biological Species |
| 생성 | CRT | Creation |
| 생슬러지 | RSLG | Raw Sludge |
| 생태 | ECLGY | Ecology |
| 생태독성 | ECTOX | ecotoxicity |
| 서류 | PAPE | Papers |
| 서명 | SIGN | Signing |
| 서버 | SRVR | Server |
| 서비스 | SRVC | Service |
| 설계 | DESGN | Design |
| 설계용량 | DESGN_CPCT | Design Capacity |
| 설립 | FNDN | Foundation |
| 설정 | STNG | Setting |
| 설치 | INSTL | Installation |
| 성격 | CHTR | Character |
| 성공 | SCS | Success |
| 성능 | PRFMNC | Performance |
| 성능검사 | EFTST | Efficiency Test |
| 성적서 | SCRRP | Score Report |
| 세균 | BCLS | Bacillus |
| 세목 | FB | Fine bar |
| 세부 | DETAIL | Detail |
| 세정 | WS | Washing |
| 세정제 | CNML | Cleaning Material |
| 소 | SML | Small |
| 소독 | DSNF | Disinfection |
| 소독제 | DSINF | Disinfectant |
| 소분류 | SCLAS | Small Classification |
| 소수점 | DCPT | Decimal Point |
| 소요 | REQ | Required |
| 소유 | OWN | Own |
| 소유역 | SBASIN | Sub Basin |
| 소재지 | PLAC | Place Of Location |
| 소포 | ATFM | Antifoaming |
| 소포수 | FBW | Foam Breaking Water |
| 소포제 | ANAG | Antifoaming Agent |
| 송부 | SENDNG | Sending |
| 송신 | SNDM | Send Message |
| 송풍기 | BLW | Blower |
| 수 | CNT | Count |
| 수거 | TKAWY | Take Away |
| 수계 | WWBH | Watershed, Water Basin, Hydrosphere |
| 수동 | HOPR | Hand Operation |
| 수리학적 체류시간 | HRT | Hydraulic Retention Time |
| 수문 | Gate | Gate |
| 수산화나트륨 | SOHY | Sodium Hydroxide |
| 수소이온 | HION | Hydrogen Ion |
| 수신 | RCPTN | Reception |
| 수용가 | RCPTR | Receptor |
| 수위 | WAL | Water Level |
| 수정 | MDFCN | Modification |
| 수정자 | MDFR | Modifier |
| 수제 | SPRDIKE | Superdike |
| 수조 | Tank | Tank |
| 수질 | QTWT | Quality Of Water |
| 수질개선 | WTRQLIMP | Water Quality Improvement |
| 수질기준 | WQST | Water Quality Standards |
| 수질배출정보 | WTDI | Water Discharge Information |
| 수집 | CLCT | Collection |
| 순환 | CCL | Cycling |
| 쉬겔라 | SHIGLA | Shigella |
| 스컴 | SCM | Scum |
| 스크린 | SCR | Screen |
| 슬러지 | SLG | Sludge |
| 슬러지 밀도지수 | SDI | sludge density index |
| 슬러지 용량 지표 | SVI | Sludge Volume Index |
| 습지 | WTLN | Wetland |
| 승인 | APRV | Approval |
| 승인권 | APPRVRGT | Right Of Approval |
| 시각 | TIME | Time |
| 시간 | HR | Hour |
| 시군구 | SGG | Si/Gun/Gu |
| 시나리오 | SCEN | Scenario |
| 시도 | CTPV | Cities And Provinces |
| 시료 | SMPL | Sample |
| 시설 | FCLT | Facility |
| 시설면적 | FCAR | Facility Area |
| 시설물 | FCLTS | Facilities |
| 시스템 | SYS | System |
| 시안 | CYN | Cyaan |
| 시운전 | TSTRN | Test Run |
| 시작 | BGNG | Beginning |
| 시점 | PTM | Point Time |
| 시행 | ENFC | Enforcement |
| 시험 | TEST | Test |
| 신고 | DCLR | Declaration |
| 신고자 | DCL | Declarer |
| 신규 | NEW | New |
| 신기술 | NTCH | New Technology |
| 신뢰 | CNFDNC | Confidence |
| 신뢰성 | CRDIBLTY | Credibility |
| 실시 | OPRT | Operation |
| 실적 | ACRS | Actual Result |
| 실행 | EXCN | Execution |
| 심사 | SRNG | Screening |
| 심의 | DLBR | Deliberation |
| 아황산환원혐기성포자형성균 | SFSRA | Spore Forming Sulfite Reducing Anaerobes |
| 안정화 | STBLZT | Stabilization |
| 암롤박스(컨테이너) | ARTCT | Arm roll type container |
| 암모니아성질소 | NHN | Ammonia Nitrogen |
| 압력 | PRESSR | Pressure |
| 압송 | PUMPNG | Pumping |
| 압축 | CMPRS | Compress |
| 액비 | LQFERTLZ | Liquid Fertilizer |
| 액상 | LIQD | Liquid |
| 약 | GENTLE | Gentle |
| 약품 | CMC | Chemical |
| 약품비 | MEDFEE | Medicine Fee |
| 약품사용 | USMD | Use Medicines |
| 업로드 | UPLD | Upload |
| 업무 | DTY | Duty |
| 없음 | NOT | Nothing |
| 에너지 | ENR | Energy |
| 에틸벤젠 | ETBNZN | Ethylbenzene |
| 여과 | FILTR | Filteration |
| 여과수 | FTWT | Filtered Water |
| 여과재 | FTMTRL | Filter Material |
| 여과형 | FILTRFOM | Filter Form |
| 여부 | YN | Yes or No |
| 여시니아균 | YERSNA | Yersinia |
| 역률 | PWRER_FCT | Power Factor |
| 역세척 | BWS | Back Wash |
| 연결 | CONN | Connection |
| 연계 | LINK | Link |
| 연도 | YR | Year |
| 연락 | CNTC | Contact |
| 연령 | AGE | Age |
| 연료화 | FUELZ | Fuelize |
| 연월 | YM | Year and Month |
| 염소 | CLRN | Chlorine |
| 염소소독 | CHDI | Chlorine Disinfection |
| 염소이온 | CLION | Chlorine Ion |
| 염화제이철 | IRCLD | Iron(III) Chloride |
| 예보 | FRCST | Forecast |
| 예비 | PRPT | Preparation |
| 예산 | BGT | Budget |
| 예상 | EXPCT | Expectation |
| 예약 | RSVT | Reservation |
| 예외 | EXCPT | Exception |
| 예정 | PRNG | Prearrangement |
| 예찰 | PRDICT | Prediction |
| 오류 | ERR | Error |
| 오수받이 | HUS_INL | House Inlet |
| 오염물질 | CNTMN | Contaminant |
| 오염원 | POLUSRC | Pollution Source |
| 오존 | OZN | Ozone |
| 오프로드 | OFFRD | Off Road |
| 옥살산 | OXACID | Oxalic Acid |
| 와류 | VORTEX | Vortex |
| 와류형 | VORTXFOM | Vortex From |
| 완결 | COMPLT | Completion |
| 완료 | CMPTN | Completion |
| 완전 | PRFECT | Perfection |
| 요건 | REQSIT | Requisite |
| 요막액 | ALLNTFLD | Allantoic Fluid |
| 요청 | DMND | Demand |
| 용량 | CPCT | Capacity |
| 용역 | SERVC | Service |
| 용존산소 | DO | Dissolved Oxygen |
| 용해 | DSLV | Dissolving |
| 우량 | EXLT | Excellent |
| 우수 | ST | Storm |
| 우수받이 | STRT_INL | Street Inlet |
| 우수토구 | STM_OVFL_MUT | Storm Overflow Mouth |
| 우회 | BP | BY PASS |
| 운반 | CNVY | Conveyance |
| 운영 | OPER | Operation |
| 운영비 | OPEXP | Operation Expense |
| 운행 | OPRAT | Operation |
| 원격 | RMRT | Rmrt |
| 원격감시체계 | TMS | Tele Monitoring System |
| 원료 | MTRAL | Material |
| 원수 | ORGWT | Origin'S Water |
| 원인자 | ORGPR | The Origin Person |
| 월 | MM | Month |
| 위도 | LAT | Latitude |
| 위반 | CNTR | Contravene |
| 위촉 | ENTRST | Entrusting |
| 위치 | LOC | Location |
| 위탁 | CNSG | Consign |
| 위탁자 | CONSGNR | Consignor |
| 유기인 | ORGP | Organic Phosphorus |
| 유량 | FLUX | Flux |
| 유량조정조 | EQLZT__TANK | Equalization Tank |
| 유입 | INFlOW | Inflow |
| 유입수 | INFWTR | Influent Water |
| 유주 | SWARMG | Swarming |
| 유지 | MNTNC | Maintenance |
| 유지용수공급 | MWRS | Maintenance Water Requirement Supply |
| 유체 | FLUID | Fluid |
| 유출 | EFFLUX | Efflux |
| 유충 | LAVL | Larval |
| 유형 | TY | Type |
| 유효 | VLD | Validity |
| 음용 | DKPS | For Drinking Purpose |
| 읍면동 | EMD | Eup/Myun/Dong |
| 응답 | RSPNS | Response |
| 응집제 | COAG | Cohesive Agents |
| 이관 | TRNSF | Transfer |
| 이동 | MVMN | Movement |
| 이력 | HST | History |
| 이메일 | EML | Email |
| 이상 | ABOVE | Above |
| 이송 | TRSF | Transfer |
| 이의 | OBJC | Objection |
| 이차 | SCDR | Secondary |
| 이차침전지 | SCDR_SDMT_TANK | Secondary Sedimaentation |
| 이행 | MIG | Migratation |
| 인건비 | PEXP | Personnel Expenses{Expenditure] |
| 인계 | HNDVR | Handover |
| 인계서 | HDOVDC | Handover Document |
| 인구 | POPL | Population |
| 인산 | PHACID | Phosphoric Acid |
| 인산염인 | POP | phosphate |
| 인양기 | LFT | Lifter |
| 인원수 | NOPE | The Number of Persons |
| 인증 | CERT | Certification |
| 인처리 | PPRCS | Phosphorus Process |
| 인허가 | APVL | Approval |
| 일 | DY | Day |
| 일련번호 | SN | Serial Number |
| 일반 | GNRL | General |
| 일별 | DALY | Daily |
| 일시 | DT | Date and Time |
| 일자 | YMD | YEAR Month Day |
| 일지 | DIARY | Diary |
| 일차 | PRM | Primary |
| 일차침전지 | PST_SDMT_TANK | Primary Sedimentation Tank |
| 일평균 | DYRG | Day Average |
| 임시 | TMPR | Temporary |
| 임의 | RNDM | Random |
| 입고 | WRHS | Warehousing |
| 입력 | INPT | Input |
| 잉여 | SPS | Surplus |
| 잉여슬러지 | EC_SLG | Excess Sludge |
| 자 | MAN | Man |
| 자갈 | GRAVEL | Gravel |
| 자료 | DATA | Data |
| 자리 | DIGIT | Digit |
| 자립화 | SLFRLI | Self Reliance |
| 자연형 | NATRLFOM | Natural Form |
| 자외선 | URLI | Ultraviolet Rays, Light |
| 자재 | MTRIL | Material |
| 자체 | ITSL | Itself |
| 작성 | WRT | Writing |
| 작업 | JOB | Job |
| 잠금 | LOCK | Lock |
| 장기 | LNGTR | Long Term |
| 장소 | PLCE | Place |
| 장착 | MNTNG | Mounting |
| 재 | RE | Re |
| 재이용 | REUSE | Reuse |
| 재이용수 | | Reuse Water |
| 재활용 | RUSE | Reuse |
| 저감 | REDUC | Reduction |
| 저류조 | DTT_TANK | Detention Tank |
| 저온 | LOWTMP | Low Temperature |
| 저장 | STRG | Storage |
| 저장소 | STORGE | Storage |
| 적발 | DSCL | Disclose |
| 적산 | ADD | Addition |
| 적용 | APLCN | Application |
| 적합 | STBLT | Suitability |
| 전기 | ELCTY | Electricity |
| 전기료 | ELFEE | Electricity Fee |
| 전력 | PWRER | Power |
| 전문 | SPCY | Specially |
| 전산 | CMPUTT | Computation |
| 전송 | TRSM | Transmission |
| 전압 | VLTGE | Voltage |
| 전용 | EXUSE | Exclusive Use |
| 전원 | SELCT | Source Of Electricity |
| 전처리 | PRETR | Pretreatment |
| 점검 | CHCK | Check |
| 접속 | CNTN | Connection |
| 정밀 | PRCIS | Precision |
| 정보 | INFO | Information |
| 정산 | CLCLN | Calculation |
| 정상 | NRMLT | Normality |
| 정수장 | WPPW | Water Purification Plant, Waterworks |
| 정제 | REFINE | Refining |
| 정지 | STP | Stop |
| 제거 | RMV | Removal |
| 제수변 | SL_VALVE | Sluice Valve |
| 제작 | MNFCT | Manufacture |
| 제조사 | MKR | Maker |
| 제출 | SBMSN | Submission |
| 제한 | LIMT | Limitation |
| 조류 | ALG | Algae |
| 조목 | CSB | Coarse Bar |
| 조사 | EXMN | Examination |
| 조성 | MAKE | Make |
| 조정 | EQLT | Equalization |
| 조치 | ACTN | Action |
| 조회 | INQ | Inquiry |
| 존재 | EXST | Existence |
| 종결 | TRMN | Termination |
| 종균제 | MICBA | Microbial Agent |
| 종료 | END | End |
| 종류 | KND | Kind |
| 종목 | IEM | Item |
| 종별 | ASORT | Assortment |
| 종사자 | ENFSN | Enfilade Person |
| 종점 | TMNL | Terminal |
| 좌표 | COOR | Coordinate |
| 주간 | WIK | Week |
| 주변 | CFR | Circumference |
| 주소 | ADDR | Address |
| 주입 | IJTN | Injection |
| 주파수 | FQNC | Frequency |
| 준공 | CMCN | Completion Of Construction |
| 중권역 | MDSTRC | Medium District |
| 중복 | DPCN | Duplication |
| 중분류 | MLSFC | Middle Classification |
| 중온 | MESPH | Mesophilic |
| 중첩 | RETRTN | Reiteration |
| 중화설비 | NUTEQP | Neutralization Equipment |
| 중화제 | CNTAG | Counteragent |
| 증가 | INCRS | Increase |
| 지도점검표사본 | CITBMR | Copy of Instruction Checklist |
| 지방자치단체 | LGOV | Local Governments |
| 지번 | LOTNO | Lot Number |
| 지상 | GRND | Ground |
| 지역 | ARA | Area |
| 지질 | NTRFS | Nature Of Soil |
| 지질도 | GEOMAP | Geological Map |
| 지하 | UDGD | Underground |
| 지하수 | GROU | Groundwater |
| 지형 | TPGRPH | Topography |
| 진공 | VCM | Vacuum |
| 진단 | DGNSS | Diagnosis |
| 진동 | VIBRAT | Vibration |
| 진행 | PRGRE | Progress |
| 질산 | NIACID | Nitric Acid. |
| 질산성질소 | NO3N | Nitrate Nitrogen |
| 집계 | TOT | Total |
| 집계구 | SUMDST | Summation District |
| 집행 | IMPL | Implementation |
| 찌꺼기 | LEES | Lees |
| 차아염소산 | NAOCL | Hypochlorous Acid |
| 차집 | ITCT | Intercepting |
| 착공 | BGNCST | Begin Construction |
| 채수 | SAMWT | Sampling Of Water |
| 채수기 | WTRSMPLR | Water Sampler |
| 채수병 | WTRBOTL | Water Bottle |
| 처리 | PRCS | Process |
| 처리비 | PSSFEE | Process Fee |
| 처리수 | TRT_WT | Treated Water |
| 처리수조 | TRT_WT_TANK | Treated Water Tank |
| 처리시설 | TRTMTFCLT | Treatment Facility |
| 처리자 | PRCR | Processor |
| 처분 | DSPS | Disposition |
| 철염 | FESLT | Ferric Salt |
| 첨부 | ATCH | Attachment |
| 첨부파일 | ATFI | Attachment File |
| 초과 | EXCS | Excess |
| 초기화 | INITL | Initialization |
| 촉매 | CTLY | Catalyst |
| 총계 | TSM | Summation |
| 총대장균군 | TCOLFGRP | Total Coliform Group |
| 총량 | TQT | Total Quantity |
| 총면적 | GFA | Gross Floor Area |
| 총사업비 | TPCO | Total Project Cost |
| 총인구 | TPOPLTN | Total Population |
| 총인처리시설 | TPFCT | Total Phosphorus facility |
| 최근 | RCNT | Recent |
| 최대값 | MAXV | Maximum Value |
| 최소값 | MINV | Minimum Value |
| 최적 | BMTB | Being The Most Suitable |
| 최종 | LAST | Last |
| 최초 | FRST | First |
| 추출 | EXTR | Extraction |
| 추출정보 | EXTRINFO | Extraction Information |
| 축 | AXS | Axis |
| 출력 | OTPT | Output |
| 출발 | LVE | Leave |
| 충전기 | CHRGR | Charger |
| 취득 | ACQS | Acquisition |
| 취소 | RTRCN | Retraction |
| 측정 | MSUR | Measurement |
| 측정기 | MSRR | Measurement Instrument |
| 측정소 | MSRSTN | Measurement Station |
| 침사지 | GTCB | Grit Chamber |
| 침전 | SDMT | Sediment |
| 침전지 | SDMT_TANK | sedimentation tank |
| 컨베이어 | CVY | Conveyor |
| 컬럼 | COL | Column |
| 코드 | CD | Code |
| 크기 | SZ | Size |
| 크실렌 | XYLEN | Xylene |
| 탄화 | CARB | Carbonization |
| 탈거 | CRYOFF | Carry Off |
| 탈리액 | SPNT | Supernatant |
| 탈수 | DWTR | Dewatering |
| 탈수기 | DEHYM | Dehydration Machine |
| 탈질 | DNTFCT | Denitrificatio |
| 탈취 | DODRZ | Deodorization |
| 탈취기 | DEODRZ | Deodorizer |
| 탈취제 | DEODR | Deodorant |
| 탈황제 | DSLFA | Desulfurizing Agent |
| 터널형 | YUNLTP | Tunnel Type |
| 테이블 | TBL | Table |
| 토구 | OTFL | Outfall |
| 토지 | LAD | Land |
| 토지면적 | LDAR | Land Area |
| 통계 | STATS | Statistics |
| 통보 | NTFCTN | Notification |
| 통신 | COMM | Communication |
| 통지 | AVTSMT | Avertissement |
| 통합 | UNTY | Unity |
| 특성 | CHRT | Character |
| 특수 | SPECL | Special |
| 특정유해물질 | SHCH | Specified Hazardous Chemicals |
| 파일 | FILE | File |
| 판정 | JGMT | Judgement |
| 펌프 | PUMP | Pump |
| 펌프장 | PUMP_STT | Pump Station |
| 페놀 | PHNL | Phenol |
| 평가 | EVL | Evaluation |
| 폐기 | DSCD | Discard |
| 폐기물 | WSTE | Waste |
| 폐쇄 | CLSG | Closing |
| 폐수 | WAWA | Waste Water |
| 폐수처리 | WSWT | Wastewater Treatment |
| 폐열 | WASTHET | Waste Heat |
| 포기 | ARTN | Aeration |
| 포트 | PORT | Port |
| 폭기조 | ARTN_TANK | Aeration Tank |
| 폴리머 | PLYMR | Polymer |
| 폴리철 | FRRCSU | Ferric Sulfate |
| 표고 | AL | Altitude |
| 표기 | MARK | Mark |
| 표시 | INDCT | Indication |
| 표준 | STD | Standard |
| 표출 | EPRSS | Expression |
| 플래그 | FLAG | Flag |
| 필드 | FILD | Field |
| 필수 | ESNTL | Essential |
| 필증 | CERFIN | Certificate Of Finishing |
| 필터 | FLTER | Filter |
| 하수 | SWGE | Sewage |
| 하수도 | DRNGSYS | Drainage System |
| 하수미처리 | SEWGUNTTM | Un Sewage Treatment |
| 하수처리 | SEWGTRTM | Sewage Treatment |
| 하수처리수 | STWTR | Sewage Treatment Water |
| 하위 | LOWR | Lower |
| 하향류 | DWFW | Downflow |
| 할인 | DSCNT | Discount |
| 함수율 | MISTR_CTNT | Moisture content |
| 합계 | SMM | Summation |
| 해당 | RLVT | Relevant |
| 해석 | INTRPRTT | Interpretation |
| 해양투기 | OCDU | Ocean Dumping |
| 행망 | ADMNW | Administration Network |
| 행정 | ADMN | Administration |
| 행정구역 | ADMI | Administrative District |
| 행정동 | DONG | Dong (Administrative District) |
| 허가 | PRMSN | Permission |
| 허용 | PERM | Permission |
| 현상 | PHNMN | Phenomenon |
| 혐기 | AARB | Anaerobic |
| 혐기조 | AARB_TANK | Anaerobic tank |
| 협잡물 | CCMT | Concomitant |
| 형태 | SHAP | Shape |
| 호기 | ARB | Aerobic |
| 호기조 | ARB_TANK | Aerobic Tank |
| 호소수 | LMSHWT | Lake And Marsh Water |
| 호수 | LKE | Lake |
| 호안 | RVTMNT | Revetment |
| 호이스트 | HIST | Hoist |
| 혼합 | CMPN | Compound |
| 혼합액현탁고형물 | MLSS | Mixed liquor suspended solids |
| 혼화지 | MXG_TNAK | Mixing tank |
| 홈페이지 | HMPG | Homepage |
| 홍수 | FLOOD | Flood |
| 확인 | IDNTY | Identify |
| 확인서 | CNFRMN | Confirmation |
| 확인자 | IDFR | Identifier |
| 확장자 | EXTN | Extension |
| 확정 | CFMTN | Confirmation |
| 환경 | ENVR | Environment |
| 환경기초시설 | ENINF | Environmental Infrastructure |
| 환원 | RSTORE | Restoration |
| 활성탄 | AC | Activated Carbon |
| 활성화 | PRMT | Promote/Facilitate |
| 활용 | PRUS | Practical Use |
| 황산 | ECCBT | Encyclopaedia Britannica (H2So4) |
| 회사 | CO | Company |
| 회수 | RTRVL | Retrieval |
| 회신 | RPLY | Reply |
| 효율 | EFC | Efficiency |
| 효율성 | EFFCTV | Effectiveness |
| 휴대 | MBL | Mobile |
| 흡수정 | EXTTW | Extraction Well |
| 흡착 | ADST | Adsorption |
+14
View File
@@ -5,6 +5,20 @@ const subDomain =
const nextConfig: NextConfig = {
output: "standalone",
experimental: {
proxyTimeout: 600000,
},
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
},
logging: {
fetches: {
fullUrl: true,
},
},
async headers() {
return [
{
@@ -1,6 +1,6 @@
"use client";
import { useState } from "react";
import { useEffect, useState } from "react";
import {
keepPreviousData,
useQuery,
@@ -75,7 +75,7 @@ function AddAdminDialog() {
});
const query = useQuery({
queryKey: [ENDPOINT.USER_SERVICE.USERS, pagination, "normal-user"],
queryKey: [ENDPOINT.USER_SERVICE.USERS, "findPageUser", pagination],
queryFn: () =>
UserApi.findPageUser({
...userSearchQuery,
@@ -181,6 +181,21 @@ function AddAdminDialog() {
query.refetch();
};
useEffect(() => {
if (!open) {
setRowSelection({});
setSelectedGroupId("");
setUserSearchQuery({
keywordType: "userName",
keyword: "",
});
setPagination({ pageIndex: 0, pageSize: 10 });
queryClient.removeQueries({
queryKey: [ENDPOINT.USER_SERVICE.USERS, "findPageUser"],
});
}
}, [open]);
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
@@ -1,53 +1,22 @@
// import { client } from "@/shared/api";
// import { ENDPOINT } from "@/shared/config";
import { client } from "@/shared/api";
import { ENDPOINT } from "@/shared/config";
import {
type BoardStatisticsParams,
type BoardStatistics,
type BoardStatisticsService,
} from "../model/board-statistics-interface";
// 임시 모의 데이터
const mockBoardStatisticsData: BoardStatistics = {
totalPosts: 2456,
totalComments: 156,
averageRating: 4.2,
totalViews: 45678,
dayList: [
{ date: "1월", posts: 10, comments: 5, views: 800 },
{ date: "2월", posts: 15, comments: 8, views: 1200 },
{ date: "3월", posts: 12, comments: 10, views: 1000 },
{ date: "4월", posts: 18, comments: 15, views: 1500 },
{ date: "5월", posts: 22, comments: 20, views: 1800 },
{ date: "6월", posts: 20, comments: 18, views: 1600 },
{ date: "7월", posts: 25, comments: 22, views: 2000 },
],
boardList: [
{ boardType: "notice", boardName: "공지사항", count: 45 },
{ boardType: "faq", boardName: "FAQ", count: 120 },
{ boardType: "qna", boardName: "Q&A", count: 180 },
{ boardType: "free", boardName: "자유게시판", count: 95 },
],
statusList: [
{ status: "completed", statusName: "답변완료", count: 75 },
{ status: "waiting", statusName: "답변대기", count: 25 },
],
};
class BoardStatisticsApiService implements BoardStatisticsService {
async getBoardStatistics(
params: BoardStatisticsParams,
): Promise<BoardStatistics> {
console.log("params: ", params);
try {
// 실제 API 연동 시 아래 코드 사용
// const response = await client.get<BoardStatistics>(
// `${ENDPOINT.CMS_SERVICE.BOARD_STATISTICS}`,
// { params },
// );
// return response.data;
// 임시 모의 데이터 반환
return Promise.resolve(mockBoardStatisticsData);
const response = await client.get<BoardStatistics>(
`${ENDPOINT.BOARD_SERVICE.STATISTICS}`,
{ params },
);
return response.data;
} catch (error) {
console.error("게시판 통계 데이터 조회 실패:", error);
throw error;
@@ -12,32 +12,36 @@ export interface BoardStatisticsParams extends PageableParams {
}
export interface BoardStatistics {
totalPosts: number;
totalComments: number;
averageRating: number;
totalViews: number;
dayList: DayStatistics[];
boardList: BoardTypeStatistics[];
statusList: StatusStatistics[];
bbsTotalDto: BbsTotalDto; // 게시판 전체 통계
pstAnsList: PstAnswerStatistics[]; // 게시물 답변 상태별 통계 목록
bbsDailyList: BbsDailyStatistics[]; // 게시판 일별 통계 목록
bbsPstCntList: BbsPostCountStatistics[]; // 게시판별 게시물 건수 통계 목록
}
interface DayStatistics {
date: string;
posts: number;
comments: number;
views: number;
interface BbsTotalDto {
pstInqCnt: number; // 게시물 조회 건수
pstEvlAvg: number; // 게시물 평가 평균
pstTotCnt: number; // 게시물 총 건수
pstAnsWaitCnt: number; // 게시물 답변 대기 건수
}
interface BoardTypeStatistics {
boardType: string;
boardName: string;
count: number;
interface PstAnswerStatistics {
answerNm: string; // 답변 명
answerYn: string; // 답변 여부 (Y/N)
ansCnt: number; // 답변 건수
}
interface StatusStatistics {
status: string;
statusName: string;
count: number;
interface BbsDailyStatistics {
dayYmd: string; // 일자 (YYYY-MM-DD)
pstInqCnt: number; // 게시물 조회 건수
pstCmntCnt: number; // 게시물 댓글 건수
pstNewCnt: number; // 게시물 신규 건수
}
interface BbsPostCountStatistics {
bbsId: number; // 게시판 ID
bbsNm: string; // 게시판 명
pstCnt: number; // 게시물 건수
}
export interface BoardStatisticsService {
@@ -11,20 +11,20 @@ export const chartData = {
} => {
return {
data: {
labels: data.dayList.map((item) => item.date),
labels: data.bbsDailyList.map((item) => item.dayYmd),
datasets: [
{
type: "line",
label: "신규게시물",
data: data.dayList.map((item) => item.posts),
data: data.bbsDailyList.map((item) => item.pstNewCnt),
borderColor: getCssVariableValue("--chart-1"),
backgroundColor: "rgba(59, 130, 246, 0.1)",
tension: 0.4,
},
{
type: "line",
label: "답변대기",
data: data.dayList.map((item) => item.comments),
label: "댓글수",
data: data.bbsDailyList.map((item) => item.pstCmntCnt),
borderColor: getCssVariableValue("--chart-2"),
backgroundColor: "rgba(236, 72, 153, 0.1)",
tension: 0.4,
@@ -32,11 +32,10 @@ export const chartData = {
{
type: "line",
label: "조회수",
data: data.dayList.map((item) => item.views),
data: data.bbsDailyList.map((item) => item.pstInqCnt),
borderColor: getCssVariableValue("--chart-3"),
backgroundColor: "rgba(168, 85, 247, 0.1)",
tension: 0.4,
hidden: true,
},
],
},
@@ -67,13 +66,13 @@ export const chartData = {
} => {
return {
data: {
labels: data.boardList.map((item) => item.boardName),
labels: data.bbsPstCntList.map((item) => item.bbsNm),
datasets: [
{
type: "bar",
label: "게시판별 분포",
data: data.boardList.map((item) => item.count),
backgroundColor: data.boardList.map((_, index) =>
data: data.bbsPstCntList.map((item) => item.pstCnt),
backgroundColor: data.bbsPstCntList.map((_, index) =>
getCssVariableValue(`--chart-${(index % 5) + 1}`),
),
},
@@ -106,12 +105,12 @@ export const chartData = {
} => {
return {
data: {
labels: data.statusList.map((item) => item.statusName),
labels: data.pstAnsList.map((item) => item.answerNm),
datasets: [
{
type: "doughnut",
data: data.statusList.map((item) => item.count),
backgroundColor: data.statusList.map((_, index) =>
data: data.pstAnsList.map((item) => item.ansCnt),
backgroundColor: data.pstAnsList.map((_, index) =>
getCssVariableValue(`--chart-${(index % 5) + 1}`),
),
},
@@ -26,7 +26,7 @@ import {
SelectValue,
} from "@common/components";
import { SiteSelect } from "@/entities/site";
// import { ENDPOINT } from "@/shared/config";
import { ENDPOINT } from "@/shared/config";
import { NoData } from "@/shared/ui/no-data";
import { InputDateRangePicker } from "@/shared/ui/input-date-range-picker";
import { BoardStatisticsApi } from "../api/board-statistics-service";
@@ -66,7 +66,7 @@ function BoardStatisticsPage() {
});
const { data: boardStatisticsData } = useQuery({
queryKey: ["board-statistics", searchParams],
queryKey: [ENDPOINT.BOARD_SERVICE.STATISTICS, searchParams],
queryFn: () =>
BoardStatisticsApi.getBoardStatistics({
...searchParams,
@@ -176,7 +176,8 @@ function BoardStatisticsPage() {
<h3 className="text-lg font-medium text-gray-500">총 게시물</h3>
<div className="flex items-center justify-between">
<div className="mt-2 text-4xl font-bold">
{boardStatisticsData?.totalPosts.toLocaleString() || 0}
{boardStatisticsData?.bbsTotalDto?.pstTotCnt?.toLocaleString() ||
0}
</div>
<div className="h-16 w-24">
<Line
@@ -210,7 +211,8 @@ function BoardStatisticsPage() {
<h3 className="text-lg font-medium text-gray-500">답변대기</h3>
<div className="flex items-center justify-between">
<div className="mt-2 text-4xl font-bold">
{boardStatisticsData?.totalComments.toLocaleString() || 0}
{boardStatisticsData?.bbsTotalDto?.pstAnsWaitCnt?.toLocaleString() ||
0}
</div>
<div className="h-16 w-24">
<Line
@@ -244,7 +246,7 @@ function BoardStatisticsPage() {
<h3 className="text-lg font-medium text-gray-500">평균평점</h3>
<div className="flex items-center justify-between">
<div className="mt-2 text-4xl font-bold">
{boardStatisticsData?.averageRating.toFixed(1) || 0}
{boardStatisticsData?.bbsTotalDto?.pstEvlAvg?.toFixed(1) || 0}
</div>
<div className="h-16 w-24">
<Line
@@ -278,7 +280,8 @@ function BoardStatisticsPage() {
<h3 className="text-lg font-medium text-gray-500">총 조회수</h3>
<div className="flex items-center justify-between">
<div className="mt-2 text-4xl font-bold">
{boardStatisticsData?.totalViews.toLocaleString() || 0}
{boardStatisticsData?.bbsTotalDto?.pstInqCnt?.toLocaleString() ||
0}
</div>
<div className="h-16 w-24">
<Line
@@ -315,7 +318,7 @@ function BoardStatisticsPage() {
<h3 className="text-2xl font-medium">일별 게시물 현황</h3>
</div>
<div className="h-96 p-4">
{boardStatisticsData?.dayList?.length ? (
{boardStatisticsData?.bbsDailyList?.length ? (
<Line {...chartData.day(boardStatisticsData)} />
) : (
<NoData />
@@ -329,7 +332,7 @@ function BoardStatisticsPage() {
<h3 className="text-2xl font-medium">답변상태</h3>
</div>
<div className="h-96 p-4">
{boardStatisticsData?.statusList?.length ? (
{boardStatisticsData?.pstAnsList?.length ? (
<Doughnut {...chartData.status(boardStatisticsData)} />
) : (
<NoData />
@@ -342,7 +345,7 @@ function BoardStatisticsPage() {
<h3 className="text-2xl font-medium">게시판별 분포</h3>
</div>
<div className="h-96 p-4">
{boardStatisticsData?.boardList?.length ? (
{boardStatisticsData?.bbsPstCntList?.length ? (
<Bar {...chartData.board(boardStatisticsData)} />
) : (
<NoData />
@@ -1,4 +1,4 @@
import { memo } from "react";
import { memo, useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useQuery, useQueryClient } from "@tanstack/react-query";
@@ -140,6 +140,10 @@ const LwpoCodeManagementDialog = memo(
}
};
useEffect(() => {
if (!open) form.reset();
}, [open]);
return (
<Dialog open={open} onOpenChange={onOpenChange} {...props}>
<DialogTrigger asChild>{children}</DialogTrigger>
+5 -1
View File
@@ -1,4 +1,4 @@
import { memo } from "react";
import { memo, useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useQuery } from "@tanstack/react-query";
@@ -96,6 +96,10 @@ const UpCodeManagementDialog = memo(
if (await confirm(confirmMessage)) callback(data);
};
useEffect(() => {
if (!open) form.reset();
}, [open]);
return (
<Dialog open={open} onOpenChange={onOpenChange} {...props}>
<DialogTrigger asChild>{children}</DialogTrigger>
@@ -1,6 +1,13 @@
import { client } from "@/shared/api";
import { ENDPOINT } from "@/shared/config";
import type { Dashboard, DashboardService } from "../model/dashboard-interface";
import type {
Dashboard,
DashboardService,
NoticeUser,
Schedule,
ScheduleQueryParams,
} from "../model/dashboard-interface";
import type { PageableList } from "@/shared/model";
export class DashboardApiService implements DashboardService {
public async getDashboard(): Promise<Dashboard> {
@@ -9,6 +16,25 @@ export class DashboardApiService implements DashboardService {
);
return response.data;
}
public async getNoticeUserList(
recvUnqId: string,
): Promise<PageableList<NoticeUser>> {
const response = await client.get<PageableList<NoticeUser>>(
`${ENDPOINT.CMS_SERVICE.NOTICE_USER}/${recvUnqId}/list`,
);
return response.data;
}
public async getScheduleList(
params?: ScheduleQueryParams,
): Promise<Schedule[]> {
const response = await client.get<Schedule[]>(
ENDPOINT.CMS_SERVICE.SCHEDULES,
{ params },
);
return response.data;
}
}
export const DashboardApi = new DashboardApiService();
@@ -1,3 +1,5 @@
import type { PageableList } from "@/shared/model";
export interface SiteStatisticsContent {
siteId: string;
siteNm: string;
@@ -27,6 +29,42 @@ export interface Dashboard {
menuAccessList: MenuStatisticsContent[];
}
export interface NoticeUser {
notiId: number;
recvUnqId: string;
senderUnqId: string;
notiType: string;
notiTtl: string;
notReadYn: string;
regDt: string;
}
export interface Schedule {
schdlBgngDt: string;
schdlEndDt: string;
actualDate: string;
schdlSn: number;
siteId: string;
schdlTtl: string;
schdlSeCd: string;
schdlCn: string;
reptYn: string;
commSchdlYn: string;
atflCd: string | null;
}
export interface ScheduleQueryParams {
siteId?: string;
schdlTtl?: string;
schdlSeCd?: string;
schdlBgngYmd?: string;
schdlEndYmd?: string;
reptYn?: string;
commSchdlYn?: string;
}
export interface DashboardService {
getDashboard(): Promise<Dashboard>;
getNoticeUserList(recvUnqId: string): Promise<PageableList<NoticeUser>>;
getScheduleList(params?: ScheduleQueryParams): Promise<Schedule[]>;
}
@@ -1,5 +1,6 @@
"use client";
import dayjs from "dayjs";
import { useRouter } from "next/navigation";
import { useQuery } from "@tanstack/react-query";
import { getCoreRowModel } from "@tanstack/react-table";
@@ -17,8 +18,8 @@ import {
} from "chart.js";
import { Bar, Line } from "react-chartjs-2";
import { PostApi, type RecentPost } from "@/entities/post";
import { ENDPOINT } from "@/shared/config";
import { useDataTable } from "@/shared/lib";
import { AUTH_USER_ID, ENDPOINT, SITE_ID } from "@/shared/config";
import { getCookie, useDataTable } from "@/shared/lib";
import { DashboardApi } from "../api/dashboard-service";
import { chartData } from "../model/chart-data";
import {
@@ -39,12 +40,44 @@ ChartJS.register(
);
function DashboardPage() {
const userId = getCookie(AUTH_USER_ID) ?? "";
const router = useRouter();
const { data } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.DASHBOARD],
queryFn: () => DashboardApi.getDashboard(),
});
const { data: noticeUserList } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.NOTICE_USER],
queryFn: () => DashboardApi.getNoticeUserList(userId),
enabled: !!userId,
select: (data) => {
// 오늘 ~ 한 달 전 사이의 일정
const today = dayjs().endOf("day");
const monthAgo = dayjs().subtract(1, "month").startOf("day");
return data.content?.filter((item) => {
const regDt = dayjs(item.regDt);
return (
(regDt.isSame(monthAgo) || regDt.isAfter(monthAgo)) &&
(regDt.isSame(today) || regDt.isBefore(today))
);
});
},
});
const { data: scheduleList } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.SCHEDULES],
queryFn: () =>
DashboardApi.getScheduleList({
siteId: SITE_ID,
schdlBgngYmd: dayjs().format("YYYY-MM-DD"),
schdlEndYmd: dayjs().add(1, "month").format("YYYY-MM-DD"),
commSchdlYn: "Y",
}),
});
const noticePostQuery = useQuery({
queryKey: [ENDPOINT.BOARD_SERVICE.POSTS],
queryFn: () =>
@@ -323,22 +356,15 @@ function DashboardPage() {
</div>
<div className="p-4">
<div className="space-y-4 text-foreground">
<div className="flex items-center justify-between border-b border-border pb-4">
<span className="font-medium">신규 사용자 가입</span>
<span>{(1).toLocaleString()}분 전</span>
</div>
<div className="flex items-center justify-between border-b border-border pb-4">
<span className="font-medium">메뉴 수정 요청</span>
<span>{(5).toLocaleString()}분 전</span>
</div>
<div className="flex items-center justify-between border-b border-border pb-4">
<span className="font-medium">게시물 신고</span>
<span>{(10).toLocaleString()}분 전</span>
</div>
<div className="flex items-center justify-between">
<span className="font-medium">컨텐츠 승인 요청</span>
<span>{(15).toLocaleString()}분 전</span>
</div>
{noticeUserList?.map((item) => (
<div
key={item.notiId}
className="flex items-center justify-between border-b border-border pb-4"
>
<span className="font-medium">{item.notiTtl}</span>
<span>{dayjs(item.regDt).fromNow()}</span>
</div>
))}
</div>
</div>
</div>
@@ -349,24 +375,44 @@ function DashboardPage() {
</div>
<div className="p-4">
<div className="space-y-4 text-foreground">
<div className="flex items-center justify-between border-b border-border pb-4">
<span className="font-medium">
{(3).toLocaleString()}월 정기 시스템 점검
</span>
<span>내일</span>
</div>
<div className="flex items-center justify-between border-b border-border pb-4">
<span className="font-medium">서버 업데이트 예정</span>
<span>{(3).toLocaleString()}일 후</span>
</div>
<div className="flex items-center justify-between border-b border-border pb-4">
<span className="font-medium">백업 스케줄</span>
<span>{(5).toLocaleString()}일 후</span>
</div>
<div className="flex items-center justify-between">
<span className="font-medium">정기 보안 점검</span>
<span>{(7).toLocaleString()}일 후</span>
</div>
{scheduleList && scheduleList.length > 0 ? (
scheduleList.map((schedule, index) => {
const today = dayjs();
const scheduleDate = dayjs(schedule.actualDate);
const daysUntil = scheduleDate.diff(today, "day");
let timeText = "";
if (daysUntil === 0) {
timeText = "오늘";
} else if (daysUntil === 1) {
timeText = "내일";
} else if (daysUntil > 1) {
timeText = `${daysUntil}일 후`;
} else {
timeText = scheduleDate.format("YYYY-MM-DD");
}
return (
<div
key={schedule.schdlSn}
className={`flex items-center justify-between ${
index < scheduleList.length - 1
? "border-b border-border pb-4"
: ""
}`}
>
<span className="font-medium">
{schedule.schdlTtl}
</span>
<span>{timeText}</span>
</div>
);
})
) : (
<div className="text-center text-muted-foreground">
예정된 일정이 없습니다.
</div>
)}
</div>
</div>
</div>
@@ -1,4 +1,4 @@
import { useState, useRef } from "react";
import { useState, useRef, useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useQuery } from "@tanstack/react-query";
@@ -48,25 +48,14 @@ function MenuAuthorityDialog({ groupId }: MenuAuthorityDialogProps) {
keywordType: "",
siteId: "",
});
const handleReset = () => {
if (inputRef.current) inputRef.current.value = "";
setKeywordType("");
setSiteId("");
setSearchParams({
keyword: "",
keywordType: "",
siteId: "",
});
};
const query = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.MENU_AUTHRTS, groupId, searchParams],
queryFn: () => MenuAuthorityApi.getGroupMenuAuthorityList({
groupId,
...searchParams
}),
queryFn: () =>
MenuAuthorityApi.getGroupMenuAuthorityList({
groupId,
...searchParams,
}),
enabled: open && !!groupId,
});
@@ -117,6 +106,21 @@ function MenuAuthorityDialog({ groupId }: MenuAuthorityDialogProps) {
});
};
const handleReset = () => {
if (inputRef.current) inputRef.current.value = "";
setSiteId("");
setKeywordType("");
setSearchParams({
keyword: "",
keywordType: "",
siteId: "",
});
};
useEffect(() => {
if (!open) handleReset();
}, [open]);
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
@@ -1,4 +1,4 @@
import { useState, memo } from "react";
import { useState, memo, useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useQuery } from "@tanstack/react-query";
@@ -90,6 +90,10 @@ const ManagementAuthorityDialog = memo(
}
};
useEffect(() => {
if (!open) form.reset();
}, [open]);
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
@@ -1,4 +1,4 @@
import { useState, useRef } from "react";
import { useState, useRef, useEffect } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { getCoreRowModel, type ColumnDef } from "@tanstack/react-table";
import {
@@ -113,6 +113,10 @@ function MappingRoleDialog({
},
});
useEffect(() => {
if (!open) handleReset();
}, [open]);
return (
<Dialog open={open} onOpenChange={onOpenChange} {...props}>
<DialogTrigger asChild>
+2
View File
@@ -56,6 +56,7 @@ export const ENDPOINT = {
APILOG: "/cms-service/api/v1/api-logs",
SITE_AUTHORITY: "/cms-service/api/v1/site-authrt",
CONNECTION_LOG: "/cms-service/api/v1/cntnlog",
NOTICE_USER: "/cms-service/api/v1/noti/user",
},
BOARD_SERVICE: {
BBS: "/board-service/api/v1/bbs",
@@ -63,6 +64,7 @@ export const ENDPOINT = {
POSTS: "/board-service/api/v1/posts",
POSTS_COMMENTS: "/board-service/api/v1/posts-cmnts",
POST_EVALUATION: "/board-service/api/v1/pstEvl",
STATISTICS: "/board-service/api/v1/stat/bbs",
},
};
+6 -7
View File
@@ -4,20 +4,19 @@ NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_PORT = 3005
#NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11035
NEXT_PUBLIC_PROXY_HOST = http://localhost:3005
NEXT_PUBLIC_DM_SERVER_API_URL = http://con.mind-one.co.kr:11083/reuse-service/api/v1
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_FO_SERVER_API_URL = http://con.mind-one.co.kr:11083/operation-service/api/v1
# NEXT_PUBLIC_FO_SERVER_API_URL = http://192.168.1.222:8883/operation-service/api/v1
NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_DM_SERVER_API_URL = http://con.mind-one.co.kr:11083/reuse-service/api/v1
# NEXT_PUBLIC_FO_SERVER_API_URL = http://192.168.1.222:8883/operation-service/api/v1
NEXT_PUBLIC_FO_SERVER_API_URL = http://con.mind-one.co.kr:11083/operation-service/api/v1
NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11083/reuse-service/api/v1
NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
NEXT_PUBLIC_CS_TUS_UPLOAD = /attach-service/api/v1/tus/upload
NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11083/reuse-service/api/v1
NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr
NEXT_PUBLIC_NGII_PARAM = 04trYP9_xwLAfALjwZ-B8g&service=WMTS&request=GetTile&version=1.0.0&format=image/png&layer=korean_map&style=korean&tilematrixset=korean&tilematrix={z}&tilecol={x}&tilerow={y}
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service # 개발 서버 API
NEXT_PUBLIC_GATEWAY_URL=http://con.mind-one.co.kr:11083 # 개발 서버 API
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883/sewerage-service/api # 박이정
NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://dev.onasys.co.kr:3000/auth/login
+1
View File
@@ -14,6 +14,7 @@ NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11083/reuse-service/ap
NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr
NEXT_PUBLIC_NGII_PARAM = 04trYP9_xwLAfALjwZ-B8g&service=WMTS&request=GetTile&version=1.0.0&format=image/png&layer=korean_map&style=korean&tilematrixset=korean&tilematrix={z}&tilecol={x}&tilerow={y}
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service # 개발 서버 API
NEXT_PUBLIC_GATEWAY_URL=http://con.mind-one.co.kr:11083 # 개발 서버 API
# NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883/sewerage-service/api # 박이정
NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://dev.onasys.co.kr:3000/auth/login
+2 -1
View File
@@ -15,7 +15,8 @@ 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_WR_SERVER_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_GATEWAY_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
NEXT_PUBLIC_NGII_URL = http://172.29.143.87/poiact
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}
@@ -87,9 +87,9 @@ export default function ModalSimilarPage({ sply = 0, usageCd = '', money = 0 }:
}, [getSimilarCaseList, money, searchUseType, sply, usageCd]);
return (
<div className="align-top w-[1360px] overflow-x-auto">
<div className="align-top w-[1360px] h-full">
<Title title="유사사례 조회" />
<div className="overflow-x-auto h-[450px] w-full mt-8" tabIndex={0} aria-label="유사사례 테이블 영역">
<div className="overflow-x-auto h-[480px] w-full mt-8" tabIndex={0} aria-label="유사사례 테이블 영역">
<div className="w-[150%]">
<div className="card-header justify-self-start">
<h3 className="text-2xl font-medium text-label">유사사례</h3>
@@ -148,7 +148,7 @@ export default function ModalSimilarPage({ sply = 0, usageCd = '', money = 0 }:
</div>
</div>
</div>
<div className="overflow-x-auto h-[270px] w-full mt-8">
<div className="overflow-x-auto h-[270px] w-full mt-8 overflow-y-hidden">
<div className="w-[130%]">
<UiTable
headName={"사업비 상세정보"}
@@ -1,5 +1,11 @@
"use client";
/**
* 수요정보등록 화면
*
* 🔗 사용 API
* - 수요정보등록: POST /reuseFc/request/demandInfo
*/
import { useDmStore } from "@/app/store";
import { sdmInfoFormSchema, type DemandCompBizType, type SdmInfoFormData } from "@/app/store/sdmMng";
import { SdmInfoRegForm } from "@/components/ui/sdmInfoInsertForm/component";
@@ -60,7 +66,7 @@ function SdmInfoInsertContent() {
...prev,
sdmNm: searchParams.get("dmdCoNm") || "",
}));
if(searchParams.get("dmdInfoId")){
if (searchParams.get("dmdInfoId")) {
// const data = {
// dmdCoNm: searchParams.get("dmdCoNm") || '',
// ctpvCd: searchParams.get("ctpvCd") || '',
@@ -69,8 +75,8 @@ function SdmInfoInsertContent() {
// daddr: searchParams.get("daddr") || '',
// telno: searchParams.get("telno") || '',
// }
// sessionStorage.setItem("user", JSON.stringify(data || {}));
// sessionStorage.setItem("user", JSON.stringify(data || {}));
}
//sessionStorage.setItem("user", JSON.parse(user||'') || "");
setIsLogin(user || searchParams.get("dmdInfoId") ? true : false);
@@ -121,7 +127,7 @@ function SdmInfoInsertContent() {
const userData = JSON.parse(user);
if (userData.dmdCoNm) {
setFacilityName(userData.dmdCoNm);
form.setValue("sdmNm", userData.dmdCoNm);
form.setValue("sdmNm", userData.dmdCoNm); // 수요처명(회사명)
}
} catch (error) {
console.error("Error parsing user data:", error);
@@ -203,10 +209,10 @@ function SdmInfoInsertContent() {
tph: Number(data.tph) || null,
trbt: Number(data.trbt) || null,
ph: data.ph || "",
blgcOxygDmndQnt: Number(data.bod) ||null,
blgcOxygDmndQnt: Number(data.bod) || null,
clIonQnt: Number(data.clIonQnt) || null,
smll: data.smll || "",
cdtnv: Number(data.cdtnv) ||null,
cdtnv: Number(data.cdtnv) || null,
crmty: Number(data.crmty) || null,
rmrk: data.rmrk || "",
bzmnNo: "",
@@ -0,0 +1,22 @@
"use client";
/**
* 수요처 로그아웃 화면
*
* 🔗 사용 API
*
*/
import { useDmStore } from "@/app/store";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
export default function SdmLogout() {
const router = useRouter();
const { actionLogout } = useDmStore((state) => state);
useEffect(() => {
actionLogout();
router.push("/pages/sdmMng/sdmInfoInsert");
}, [actionLogout, router]);
return null;
}
+3
View File
@@ -1,5 +1,8 @@
"use client";
import "./globals.css";
import { setCookie } from "../src/shared/lib";
setCookie("site-id-key", process.env.NEXT_PUBLIC_SITE_ID || "DM");
export default function RootLayout({
children,
+326 -303
View File
@@ -50,8 +50,8 @@ export const sdmInfoFormSchema = z.object({
// 모든 수질 관련 필드
// 총대장균군수는 null 값을 불검출로 표시하기때문에 해당 검사에서 제외함.
const allFields: (keyof typeof data)[] = [
"tn", "combResdch", "tph",
"trbt", "ph", "bod", "clIonQnt",
"tn", "combResdch", "tph",
"trbt", "ph", "bod", "clIonQnt",
"smll", "cdtnv", "crmty",
];
@@ -104,38 +104,38 @@ export type SdmInfoFormData = z.infer<typeof sdmInfoFormSchema>;
// 수요처 정보
export type DemandCompBizType = {
index : number | '';
dmdInfoId : string | '';
dmdInfoFk : string | '';
bzmnNo : string | '';
dmdCoNm : string | '';
daddr : string | '';
telno : string | '';
rgtr : string | '';
useUsgCd : string | '';
ctpvCd : string | '';
sggCd : string | '';
dmdAplyPswd : string | '';
wntUntprc : number | '';
dmndTmng : Date | '';
dmndQty : number | '';
grssClfg : number | null //총대장균군수
tn : number | null //총질소
combResdch : number | null //결합잔류염소
tph : number | null //총인
trbt : number | null //탁도
ph : string | ''; //수소이온농
blgcOxygDmndQnt : number | null //생물학적산소요구량
clIonQnt : number | null //염화물
smll : string | ''; //냄새
cdtnv : number | null; //전기전도도
crmty : number | null //색도
rmrk : string | '';
reqDt : string | '';
dmdInfoSn : number | '';
status : string | '';
splyCndtList:SupplyCandidate[]|[],
ruseUtztnFcltNm?:string|''
index: number | '';
dmdInfoId: string | '';
dmdInfoFk: string | '';
bzmnNo: string | '';
dmdCoNm: string | '';
daddr: string | '';
telno: string | '';
rgtr: string | '';
useUsgCd: string | '';
ctpvCd: string | '';
sggCd: string | '';
dmdAplyPswd: string | '';
wntUntprc: number | '';
dmndTmng: Date | '';
dmndQty: number | '';
grssClfg: number | null //총대장균군수
tn: number | null //총질소
combResdch: number | null //결합잔류염소
tph: number | null //총인
trbt: number | null //탁도
ph: string | ''; //수소이온농
blgcOxygDmndQnt: number | null //생물학적산소요구량
clIonQnt: number | null //염화물
smll: string | ''; //냄새
cdtnv: number | null; //전기전도도
crmty: number | null //색도
rmrk: string | '';
reqDt: string | '';
dmdInfoSn: number | '';
status: string | '';
splyCndtList: SupplyCandidate[] | [],
ruseUtztnFcltNm?: string | ''
}
@@ -147,107 +147,107 @@ export type SupplyCandidate = {
export type DemandMatchings = {
splyFcltFk : string | '';
splyFcltFlg : string | '';
pbnstRuseFcltBizFk : number | '';
splyBgngDay : string | '';
splyEndDay : string | '';
splyCpct : number | '';
splyFmYn : string | '';
useUsgCd : string | '';
dmdInfoSn : number | '';
splyCndtList : string | '';
mtchnCmptnYmd : string | '';
rvwCmptnYmd : string | '';
regDt : string | '';
rgtr : string | '';
mdfcnDt : string | '';
mdfr : string | '';
splyFcltFk: string | '';
splyFcltFlg: string | '';
pbnstRuseFcltBizFk: number | '';
splyBgngDay: string | '';
splyEndDay: string | '';
splyCpct: number | '';
splyFmYn: string | '';
useUsgCd: string | '';
dmdInfoSn: number | '';
splyCndtList: string | '';
mtchnCmptnYmd: string | '';
rvwCmptnYmd: string | '';
regDt: string | '';
rgtr: string | '';
mdfcnDt: string | '';
mdfr: string | '';
}
// 유사사례
export type SimilarCaseType = {
ruseBizNm : string | '';
bizBgngDate : string | '';
bizEndDate : string | '';
splyFcltKnd : string | '';
splyFcltNm : string | '';
splyFcltCpct : string | '';
dmdFcltNm : string | '';
dmdFcltAddr : string | '';
ruseFcltCpct : string | '';
ruseFcltPplLen : string | '';
ruseFcltUsg : string | '';
ruseFcltSplyCpct : string | '';
ruseFcltPrcsMsrc : string | '';
grnteWqUsg : string | '';
grnteWqGrssClfg : string | '';
grnteWqCombResdch : string | '';
grnteWqTrbt : string | '';
grnteWqBod : string | '';
grnteWqSmll : string | '';
grnteWqCrmty : string | '';
grnteWqTn : string | '';
grnteWqTp : string | '';
grnteWqPh : string | '';
grnteWqClIonQnt : string | '';
grnteWqCndctStat : string | '';
grnteWqRmrk : string | '';
reqBizReuseFcltCst : string | '';
reqBizPplCst : string | '';
reqBizArchCst : string | '';
reqBizMchnCst : string | '';
reqBizMtrngCst : string | '';
reqBizGisCst : string | '';
reqBizCctvCst : string | '';
reqBizCmcnCst : string | '';
reqBizWstCst : string | '';
reqBizDesignCst : string | '';
reqBizSpvsCst : string | '';
reqBizSbsdCst : string | '';
reqBizEtc : string | '';
reqBizGrssCst : string | '';
prcmPlanNlep : string | '';
prcmPlanLcep : string | '';
prcmPlanBrdnCst : string | '';
prcmPlanEcqrRt : string | '';
prcmPlanGrssCst : string | '';
clclnNlep : string | '';
clclnLcep : string | '';
clclnBrdnCst : string | '';
clclnEcqrRt : string | '';
clclnGrssCst : string | '';
ruseBizNm: string | ''; // 사업명
bizBgngDate: string | '';
bizEndDate: string | '';
splyFcltKnd: string | '';
splyFcltNm: string | '';
splyFcltCpct: string | '';
dmdFcltNm: string | '';
dmdFcltAddr: string | '';
ruseFcltCpct: string | '';
ruseFcltPplLen: string | '';
ruseFcltUsg: string | '';
ruseFcltSplyCpct: string | '';
ruseFcltPrcsMsrc: string | '';
grnteWqUsg: string | '';
grnteWqGrssClfg: string | '';
grnteWqCombResdch: string | '';
grnteWqTrbt: string | '';
grnteWqBod: string | '';
grnteWqSmll: string | '';
grnteWqCrmty: string | '';
grnteWqTn: string | '';
grnteWqTp: string | '';
grnteWqPh: string | '';
grnteWqClIonQnt: string | '';
grnteWqCndctStat: string | '';
grnteWqRmrk: string | '';
reqBizReuseFcltCst: string | '';
reqBizPplCst: string | '';
reqBizArchCst: string | '';
reqBizMchnCst: string | '';
reqBizMtrngCst: string | '';
reqBizGisCst: string | '';
reqBizCctvCst: string | '';
reqBizCmcnCst: string | '';
reqBizWstCst: string | '';
reqBizDesignCst: string | '';
reqBizSpvsCst: string | '';
reqBizSbsdCst: string | '';
reqBizEtc: string | '';
reqBizGrssCst: string | '';
prcmPlanNlep: string | '';
prcmPlanLcep: string | '';
prcmPlanBrdnCst: string | '';
prcmPlanEcqrRt: string | '';
prcmPlanGrssCst: string | '';
clclnNlep: string | '';
clclnLcep: string | '';
clclnBrdnCst: string | '';
clclnEcqrRt: string | '';
clclnGrssCst: string | '';
}
// 사업비 상세정보
export type MoneyDetailType = {
reqBizGrssCst : string | '';
reqBizReuseFcltCst : string | '';
reqBizPplCst : string | '';
reqBizArchCst : string | '';
reqBizMchnCst : string | '';
reqBizMtrngCst : string | '';
reqBizGisCst : string | '';
reqBizCctvCst : string | '';
reqBizCmcnCst : string | '';
reqBizWstCst : string | '';
reqBizDesignCst : string | '';
reqBizSpvsCst : string | '';
reqBizSbsdCst : string | '';
reqBizEtc : string | '';
reqBizGrssCst: string | '';
reqBizReuseFcltCst: string | '';
reqBizPplCst: string | '';
reqBizArchCst: string | '';
reqBizMchnCst: string | '';
reqBizMtrngCst: string | '';
reqBizGisCst: string | '';
reqBizCctvCst: string | '';
reqBizCmcnCst: string | '';
reqBizWstCst: string | '';
reqBizDesignCst: string | '';
reqBizSpvsCst: string | '';
reqBizSbsdCst: string | '';
reqBizEtc: string | '';
/** 재원조달계획(백만원원) */
prcmPlanGrssCst : string | '';
prcmPlanNlep : string | '';
prcmPlanLcep : string | '';
prcmPlanBrdnCst : string | '';
prcmPlanEcqrRt : string | '';
prcmPlanGrssCst: string | '';
prcmPlanNlep: string | '';
prcmPlanLcep: string | '';
prcmPlanBrdnCst: string | '';
prcmPlanEcqrRt: string | '';
/** 사업비 정산(백만원) */
clclnGrssCst : string | '';
clclnNlep : string | '';
clclnLcep : string | '';
clclnBrdnCst : string | '';
clclnEcqrRt : string | '';
clclnGrssCst: string | '';
clclnNlep: string | '';
clclnLcep: string | '';
clclnBrdnCst: string | '';
clclnEcqrRt: string | '';
}
// 규칙 타입 선언
export type DisableRulesType = Record<string, string[]>;
@@ -255,144 +255,144 @@ export type DisableRulesType = Record<string, string[]>;
* Store - 데이터
====================================*/
// 수요처 정보
const demandCompList : DemandCompType[] = [
const demandCompList: DemandCompType[] = [
]
const disableRules: DisableRulesType = {
"청소": ["tn", 'tph',"clIonQnt" ,'cdtnv'],
"화장실용수": ["tn", 'tph',"clIonQnt" ,'cdtnv'],
"세척": ["combResdch", "crmty",'tph','tn',"clIonQnt",'cdtnv'],
"살수": ["combResdch", "crmty",'tph','tn',"clIonQnt",'cdtnv'],
"조경": ["combResdch", "crmty",'tph','cdtnv'],
"농업_간접용수": ["combResdch", "crmty",'tn','tph','clIonQnt'],
"농업_직접용수": ["combResdch", "crmty",'tn','tph','clIonQnt'],
"하천": ["combResdch", "trbt", "crmty" ,'clIonQnt','cdtnv'],
'공업':[]
};
"청소": ["tn", 'tph', "clIonQnt", 'cdtnv'],
"화장실용수": ["tn", 'tph', "clIonQnt", 'cdtnv'],
"세척": ["combResdch", "crmty", 'tph', 'tn', "clIonQnt", 'cdtnv'],
"살수": ["combResdch", "crmty", 'tph', 'tn', "clIonQnt", 'cdtnv'],
"조경": ["combResdch", "crmty", 'tph', 'cdtnv'],
"농업_간접용수": ["combResdch", "crmty", 'tn', 'tph', 'clIonQnt'],
"농업_직접용수": ["combResdch", "crmty", 'tn', 'tph', 'clIonQnt'],
"하천": ["combResdch", "trbt", "crmty", 'clIonQnt', 'cdtnv'],
'공업': []
};
const defaultRules: Record<string, object> = {
"청소": {
grssClfg: null,
combResdch:0.2,
trbt: 2,
bod: 5,
crmty: 20,
ph: "5.8~8.5",
smll:'불쾌하지않을것',
tn:null,
tph: null,
clIonQnt: null,
cdtnv: null,
const defaultRules: Record<string, object> = {
"청소": {
grssClfg: null,
combResdch: 0.2,
trbt: 2,
bod: 5,
crmty: 20,
ph: "5.8~8.5",
smll: '불쾌하지않을것',
tn: null,
tph: null,
clIonQnt: null,
cdtnv: null,
},
"화장실용수": {
grssClfg: null,
combResdch:0.2,
trbt: 2,
bod: 5,
crmty: 20,
smll:'불쾌하지않을것',
ph: "5.8~8.5",
tn:null,
tph: null,
clIonQnt: null,
cdtnv: null,
},
"세척": {
grssClfg: null,
trbt: 2,
bod: 5,
ph: "5.8~8.5",
combResdch:null,
smll:'불쾌하지않을것',
crmty:null,
tn:null,
tph: null,
clIonQnt: null,
cdtnv: null,
},
"살수": {
grssClfg: null,
trbt: 2,
bod: 5,
ph: "5.8~8.5",
smll:'불쾌하지않을것',
combResdch:null,
crmty:null,
tn:null,
tph: null,
clIonQnt: null,
cdtnv: null,
},
"조경": {
grssClfg: null,
trbt: 2,
bod: 5,
ph: "5.8~8.5",
smll:'불쾌하지않을것',
clIonQnt:250,
combResdch:null,
crmty:null,
tn:null,
tph: null,
cdtnv: null,
},
"농업_간접용수": {
grssClfg: null,
trbt: 5,
bod: 8,
ph: "5.8~8.5",
cdtnv:2000,
combResdch:null,
crmty:null,
tn:null,
tph: null,
clIonQnt: null,
},
"농업_직접용수": {
grssClfg: null,
trbt: 2,
bod: 8,
smll:'불쾌하지않을것',
ph: "5.8~8.5",
cdtnv:700,
combResdch:null,
crmty:null,
tn:null,
tph: null,
clIonQnt: null,
},
"하천": {
grssClfg: 1000,
bod: 5,
tn: 10,
tph: 0.5,
smll:'불쾌하지않을것',
ph: "5.8~8.5",
combResdch:null,
trbt:null,
crmty:null,
clIonQnt: null,
cdtnv:null
},
'공업':{
grssClfg: null,
bod: null,
tn: null,
tph: null,
ph: "~",
combResdch:null,
smll:'불쾌하지않을것',
trbt:null,
crmty:null,
clIonQnt: null,
cdtnv:null
}
};
},
"화장실용수": {
grssClfg: null,
combResdch: 0.2,
trbt: 2,
bod: 5,
crmty: 20,
smll: '불쾌하지않을것',
ph: "5.8~8.5",
tn: null,
tph: null,
clIonQnt: null,
cdtnv: null,
},
"세척": {
grssClfg: null,
trbt: 2,
bod: 5,
ph: "5.8~8.5",
combResdch: null,
smll: '불쾌하지않을것',
crmty: null,
tn: null,
tph: null,
clIonQnt: null,
cdtnv: null,
},
"살수": {
grssClfg: null,
trbt: 2,
bod: 5,
ph: "5.8~8.5",
smll: '불쾌하지않을것',
combResdch: null,
crmty: null,
tn: null,
tph: null,
clIonQnt: null,
cdtnv: null,
},
"조경": {
grssClfg: null,
trbt: 2,
bod: 5,
ph: "5.8~8.5",
smll: '불쾌하지않을것',
clIonQnt: 250,
combResdch: null,
crmty: null,
tn: null,
tph: null,
cdtnv: null,
},
"농업_간접용수": {
grssClfg: null,
trbt: 5,
bod: 8,
ph: "5.8~8.5",
cdtnv: 2000,
combResdch: null,
crmty: null,
tn: null,
tph: null,
clIonQnt: null,
},
"농업_직접용수": {
grssClfg: null,
trbt: 2,
bod: 8,
smll: '불쾌하지않을것',
ph: "5.8~8.5",
cdtnv: 700,
combResdch: null,
crmty: null,
tn: null,
tph: null,
clIonQnt: null,
},
"하천": {
grssClfg: 1000,
bod: 5,
tn: 10,
tph: 0.5,
smll: '불쾌하지않을것',
ph: "5.8~8.5",
combResdch: null,
trbt: null,
crmty: null,
clIonQnt: null,
cdtnv: null
},
'공업': {
grssClfg: null,
bod: null,
tn: null,
tph: null,
ph: "~",
combResdch: null,
smll: '불쾌하지않을것',
trbt: null,
crmty: null,
clIonQnt: null,
cdtnv: null
}
};
// 사용용도
const useTypesData : SelectDataType[] = [
const useTypesData: SelectDataType[] = [
{ text: '청소', val: "청소" },
{ text: "화장실용수", val: "화장실용수" },
{ text: "세척", val: "세척" },
@@ -440,8 +440,8 @@ export const similarCaseModalHeader: TableUpperProps[] = [
]
// 유사사례 데이터
const similarCaseList : SimilarCaseType[] = [
const similarCaseList: SimilarCaseType[] = [
]
// 사업비 상세정보 모달 헤더
@@ -477,12 +477,12 @@ export const moneyDetailModalHeader: TableUpperProps[] = [
]
// 사업비 상세정보
const moneyDetailList : MoneyDetailType[] = [
const moneyDetailList: MoneyDetailType[] = [
]
// 수요정보 신청현황 헤더
export const upHeadSdmInfoStatus: TableUpperProps[] = [
{ id: "index", title: "No."},
{ id: "index", title: "No." },
{ id: "ctpvCd", title: "시도", row: 0, rowSpan: 2 },
{ id: "sggCd", title: "시군구", row: 0, rowSpan: 2 },
{ id: "dmdCoNm", title: "회사명", row: 0, rowSpan: 2 },
@@ -501,7 +501,7 @@ export const upHeadSdmInfoStatus: TableUpperProps[] = [
const postSdmData = async (data: DemandCompType) => {
try {
await postFetch("/reuseFc/request", data);
sessionStorage.setItem("user", JSON.stringify(data) );
sessionStorage.setItem("user", JSON.stringify(data));
toast.success("수요처 등록에 성공하였습니다.");
return true;
} catch (error) {
@@ -526,16 +526,16 @@ const postSdmLoginData = async (data: DemandCompType) => {
try {
const res = await postFetch("/reuseFc/request/login", data);
const jsonData = await res.json();
const status = jsonData.status;
const loginData = jsonData.data;
let loginSuccess = false;
if(status === 200 && loginData != null) {
if (status === 200 && loginData != null) {
alert("수요처 로그인에 성공하였습니다.");
sessionStorage.setItem("user", JSON.stringify(loginData));
loginSuccess = true;
} else if(status === 401) {
alert("패스워드가 틀렸습니다.");
} else if (status === 401) {
alert("패스워드가 일치하지 않습니다.");
loginSuccess = false;
} else {
alert("등록된 수요처가 없습니다.");
@@ -553,35 +553,35 @@ const getDemandCompList = async (searchText: string, pageCnt: number) => {
try {
const url = '/reuseFc/request/' + (searchText ? searchText : '') + '/' + pageCnt;
const res = await getFetch(fetchType.WR, url);
return {
data: res?.data || [],
count: res?.count || 0
return {
data: res?.data || [],
count: res?.count || 0
}
} catch (error) {
console.error(error+' 수요처 정보를 불러오지 못했습니다.');
console.error(error + ' 수요처 정보를 불러오지 못했습니다.');
return { data: [], count: 0 };
}
}
const getSdmInfoStatusList = async (dmdInfoId : string) => {
const getSdmInfoStatusList = async (dmdInfoId: string) => {
try {
const url = '/reuseFc/request/' + dmdInfoId;
const res = await getFetch(fetchType.WR, url);
return res?.data || [];
} catch (error) {
console.error(error+' 수요정보 신청현황을 불러오지 못했습니다.');
console.error(error + ' 수요정보 신청현황을 불러오지 못했습니다.');
return [];
}
}
// 유사사례 조회
const fetchGetSimilarCaseList = async (part: string, value: number|string) => {
const fetchGetSimilarCaseList = async (part: string, value: number | string) => {
try {
const url = '/reuseFc/pubFcRuseCase/dm/' + part + '/' + (value ? value : 0);
const res = await getFetch(fetchType.WR, url);
return res?.data || [];
} catch (error) {
console.error(error+' 유사사례 조회에 실패하였습니다.');
console.error(error + ' 유사사례 조회에 실패하였습니다.');
return [];
}
}
@@ -590,23 +590,24 @@ const fetchGetSimilarCaseList = async (part: string, value: number|string) => {
* Store - expaort
====================================*/
export type SdmActions = {
initializeSdmData: () => void;
insertSdmData: (data: DemandCompType) => Promise<void>;
insertSdmInfoData: (data: DemandCompBizType) => Promise<void>;
getDemandCompList: (searchText: string, pageCnt: number) => Promise<void>;
actionLogin: (data: DemandCompType) => Promise<void>;
getSdmInfoStatusList: (dmdInfoId: string) => Promise<void>;
getSimilarCaseList: (part: string, value: number|string) => Promise<void>;
initializeSdmData: () => void;
insertSdmData: (data: DemandCompType) => Promise<void>;
insertSdmInfoData: (data: DemandCompBizType) => Promise<void>;
getDemandCompList: (searchText: string, pageCnt: number) => Promise<void>;
actionLogin: (data: DemandCompType) => Promise<void>;
getSdmInfoStatusList: (dmdInfoId: string) => Promise<void>;
getSimilarCaseList: (part: string, value: number | string) => Promise<void>;
actionLogout: () => Promise<void>;
}
export type SdmType ={
Sdm :{
export type SdmType = {
Sdm: {
isInit: boolean;
useTypesData: SelectDataType[];
demandCompList: DemandCompType[];
upHeadSimilarCaseList: TableUpperProps[];
similarCaseList: SimilarCaseType[];
upHeadMoneyDetailList : TableUpperProps[];
upHeadMoneyDetailList: TableUpperProps[];
moneyDetailList: MoneyDetailType[];
// 수요정보 신청현황
@@ -615,28 +616,28 @@ export type SdmType ={
defaultRules: Record<string, object>
disableRules: DisableRulesType;
// 로그인관련
successNextPage : boolean;
successNextPage: boolean;
successLogin: boolean;
}
}
export const SdmState: SdmType = {
Sdm:{
isInit:false,
Sdm: {
isInit: false,
useTypesData: useTypesData,
demandCompList: demandCompList,
upHeadSimilarCaseList: similarCaseModalHeader,
similarCaseList: similarCaseList,
upHeadMoneyDetailList : moneyDetailModalHeader,
upHeadMoneyDetailList: moneyDetailModalHeader,
moneyDetailList: moneyDetailList,
// 수요정보 신청현황
sdmInfoStatusList: [],
defaultRules:defaultRules,
disableRules:disableRules,
defaultRules: defaultRules,
disableRules: disableRules,
upHeadSdmInfoStatus: upHeadSdmInfoStatus,
// 로그인관련
successNextPage : false,
successNextPage: false,
successLogin: false,
}
}
@@ -648,13 +649,13 @@ export const SdmReducer = (set: any): SdmActions => {
insertSdmData: async (data: DemandCompType) => {
const preRes = await getSdmInfoStatusList(data.dmdInfoId);
if(preRes?.dmdInfoId) {
if (preRes?.dmdInfoId) {
toast.error('이미 등록된 수요처입니다.');
return;
}
const res = await postSdmData(data);
if(res) {
if (res) {
set((state: SdmType) => ({
Sdm: {
...state.Sdm,
@@ -671,7 +672,7 @@ export const SdmReducer = (set: any): SdmActions => {
// 수요처 정보
getDemandCompList: async (searchText: string, pageCnt: number) => {
const res = await getDemandCompList(searchText, pageCnt);
if(res.data.length === 0) {
if (res.data.length === 0) {
set((state: SdmType) => ({
Sdm: {
...state.Sdm,
@@ -693,7 +694,7 @@ export const SdmReducer = (set: any): SdmActions => {
getSdmInfoStatusList: async (dmdInfoId: string) => {
const res = await getSdmInfoStatusList(dmdInfoId);
if(res.length === 0) {
if (res.length === 0) {
set((state: SdmType) => ({
Sdm: {
...state.Sdm,
@@ -704,13 +705,13 @@ export const SdmReducer = (set: any): SdmActions => {
}
//const sdmInfoStatusList : DemandCompBizType[] = [];
const sdmInfoStatusList : DemandCompBizType[]= res.demandInfo.map((el: DemandCompBizType, index: number) => {
const sdmInfoStatusList: DemandCompBizType[] = res.demandInfo.map((el: DemandCompBizType, index: number) => {
const matchingInfo = res.demandMatchings.find((matching: DemandMatchings) => matching.dmdInfoSn === el.dmdInfoSn);
const status = matchingInfo?.splyFcltFlg?.trim() === 'Sub' ? '검토' : matchingInfo?.splyFcltFlg?.trim() === 'matched' ? '매칭완료' : '신청';
const ruseUtztnFcltNm = matchingInfo?.ruseUtztnFcltNm ? matchingInfo.ruseUtztnFcltNm : '';
return( {
return ({
...el,
index: ++index,
bzmnNo: res.bzmnNo,
@@ -723,8 +724,8 @@ export const SdmReducer = (set: any): SdmActions => {
sggCd: res.sggCd,
useUsgCd: el.useUsgCd,
dmndTmng: el.dmndTmng,
dmdInfoSn : el.dmdInfoSn,
status : status,
dmdInfoSn: el.dmdInfoSn,
status: status,
splyCndtList: el.splyCndtList,
ruseUtztnFcltNm: ruseUtztnFcltNm || ''
})
@@ -749,25 +750,47 @@ export const SdmReducer = (set: any): SdmActions => {
},
// 유사사례 조회
getSimilarCaseList: async (part: string, value: number|string) => {
getSimilarCaseList: async (part: string, value: number | string) => {
const res = await fetchGetSimilarCaseList(part, value);
if(res && res.length !== 0) {
const similarCaseList = res.map((el: SimilarCaseType) => {
const maskedBizNm = el.ruseBizNm
? el.ruseBizNm.replace(/^(\s*)^\S+/, "***") // 첫 단어(공백 전까지) 치환
: el.ruseBizNm;
return {
...el,
ruseBizNm: maskedBizNm,
};
});
console.log(similarCaseList);
if (similarCaseList && similarCaseList.length !== 0) {
set((state: SdmType) => ({
Sdm: {
Sdm: {
...state.Sdm,
similarCaseList: res,
similarCaseList: similarCaseList,
}
}))
return;
}else{
} else {
set((state: SdmType) => ({
Sdm: {
Sdm: {
...state.Sdm,
similarCaseList: [],
}
}))
return;
}
},
actionLogout: async () => {
sessionStorage.removeItem("user");
set((state: SdmType) => ({
Sdm: {
...state.Sdm,
successLogin: false,
}
}))
}
}
}
+6 -8
View File
@@ -85,22 +85,20 @@ export const DmStatusReducer = (set: any): DmStatusActions => {
const boardData: DmStatusBoardType[] = data.data.map(
(item: DmStatusDataType) => {
const regionText = cityCd.find((city) => item.region === city.val);
const regionText = item.sidoNm; //cityCd.find((city) => item.region === city.val);
const sewage = item.sewage;
const rainwater = item.rainwater;
const reclaimed = item.reclaimed;
const sewageCnt = item.sewageCnt;
const rainwaterCnt = item.rainwaterCnt;
const reclaimedCnt = item.reclaimedCnt;
console.log("regionText ", regionText);
if (regionText && regionText.text) {
return {
region: regionText ? regionText.text : item.region,
sewage: sewageCnt + "(" + sewage + ")",
rainwater: rainwaterCnt + "(" + rainwater + ")",
reclaimed: reclaimedCnt + "(" + reclaimed + ")",
region: regionText ? regionText : item.region,
sewage: sewageCnt + "(" + sewage.toLocaleString() + ")",
rainwater: rainwaterCnt + "(" + rainwater.toLocaleString() + ")",
reclaimed: reclaimedCnt + "(" + reclaimed.toLocaleString() + ")",
};
}
}
).filter((item): item is DmStatusBoardType => item !== undefined);
+6 -4
View File
@@ -1,14 +1,16 @@
export type DmStatusDataType = {
region: string;
sidoNm: string; // 시도명
region: string; // 시도코드
sewage: string;
rainwater: string;
reclaimed: string;
sewageCnt:string
rainwaterCnt:string
reclaimedCnt:string
sewageCnt:string;
rainwaterCnt:string;
reclaimedCnt:string;
};
export type DmStatusBoardType = {
sidoNm: string; // 시도명
region: string;
sewage: string;
rainwater: string;
+19 -6
View File
@@ -1,23 +1,33 @@
//8880
import { AUTH_USER_ID, CLAIM_NAME } from "@/src/shared/config";
import { DEV_URL_FO, DEV_URL_WR } from "../config";
import { getCookie } from "@common/components/lib/cookie";
const tokenId = getCookie(AUTH_USER_ID);
const Authorization = getCookie(CLAIM_NAME);
export const fetchType = {
COMMON: "common",
WR: "wr",
FO:'fo'
FO: "fo",
SN: "sn"
};
const API_VERSION = "/api/v1"
const servers = {
common: "",
local: "",
fo: "/operation-service" + API_VERSION,
wr: "/reuse-service" + API_VERSION,
sn: "/sewerage-service" + API_VERSION,
}
interface RequestParams {
[key: string]: unknown;
}
export const getFetch = async (type: string, url: string) => {
const baseUrl = type === fetchType.FO ? DEV_URL_FO : DEV_URL_WR;
const baseUrl = servers[type];
const response = await fetch(baseUrl + url, {
method: "GET",
headers: {
@@ -35,7 +45,8 @@ export const getFetch = async (type: string, url: string) => {
};
export const postFetch = async (url: string, params: RequestParams) => {
const response = await fetch(DEV_URL_WR + url, {
const baseUrl = servers[fetchType.WR];
const response = await fetch(baseUrl + url, {
method: "POST",
headers: {
"Content-Type": "application/json",
@@ -52,7 +63,8 @@ export const postFetch = async (url: string, params: RequestParams) => {
};
export const putFetch = async (url: string, params: RequestParams) => {
const response = await fetch(DEV_URL_WR + url, {
const baseUrl = servers[fetchType.WR];
const response = await fetch(baseUrl + url, {
method: "PUT",
headers: {
"Content-Type": "application/json",
@@ -69,7 +81,8 @@ export const putFetch = async (url: string, params: RequestParams) => {
};
export const deleteFetch = async (url: string, params: RequestParams) => {
const response = await fetch(DEV_URL_WR + url, {
const baseUrl = servers[fetchType.WR];
const response = await fetch(baseUrl + url, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
@@ -950,7 +950,7 @@ export function SdmInfoRegForm({
body={
<ModalSimilarPage sply={sply} usageCd={usageCd} money={money} />
}
bodyClass="sm:max-w-[100vw] w-[1400px] h-[900px]"
bodyClass="sm:max-w-[100vw] w-[1400px] h-[100dvh] max-h-[900px] overflow-y-auto overflow-x-hidden"
open={isSimilarCase}
onOpenChange={(open) => !open && setIsSimilarCase(false)}
noHeaderYn="Y"
+8 -15
View File
@@ -1,13 +1,13 @@
import { NextRequest, NextResponse } from "next/server";
import { CLAIM_NAME, AUTH_USER_ID } from "./src/shared/config";
import { SERVER_API_FO_URL, SERVER_API_WR_URL } from "./src/shared/config/env";
// import { SERVER_API_FO_URL, SERVER_API_WR_URL } from "./src/shared/config/env";
// const CLAIM_NAME = "Authorization";
// const AUTH_USER_ID = "token-id";
const serverApiUrl = process.env.NEXT_PUBLIC_CS_SERVER_API_URL;
const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || "";
const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || "";
const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
const GATEWAY_URL = process.env.NEXT_PUBLIC_GATEWAY_URL || "";
const BUSINESS_JUSO_API_URL = process.env.NEXT_PUBLIC_FINDADRESS_URL || "";
const AdressKey = process.env.NEXT_PRIVATE_WR_ADDRESS_KEY || "";
@@ -112,7 +112,7 @@ export function middleware(req: NextRequest) {
const url = req.nextUrl.clone();
url.searchParams.set("TYPENAME", typename.replace("hasudo:", ""));
queryParams = url.searchParams.toString();
newUrl = `${SEWERAGE_API_URL}/api/v1/map/geometry${queryParams ? `?${queryParams}` : ""}`;
newUrl = `${GATEWAY_URL}/api/v1/map/geometry${queryParams ? `?${queryParams}` : ""}`;
}
console.log(`[Middleware] Rewriting from '/geoserver' path to: ${newUrl}`);
@@ -121,24 +121,17 @@ export function middleware(req: NextRequest) {
if (pathname.startsWith("/reuse-service")) {
const queryParams = searchParams.toString();
const newUrl = `${SERVER_API_WR_URL}${pathname.replace("/reuse-service", "")}${queryParams ? `?${queryParams}` : ""
}`;
const newUrl = `${GATEWAY_URL}${pathname}${queryParams ? `?${queryParams}` : ""}`;
console.log(`[Middleware] Rewriting from '/reuse-service' path to: ${newUrl}`);
return NextResponse.rewrite(new URL(newUrl));
}
if (pathname.startsWith("/operation-service")) {
} else if (pathname.startsWith("/operation-service")) {
const queryParams = searchParams.toString();
const newUrl = `${SERVER_API_FO_URL}${pathname.replace("/operation-service", "")}${queryParams ? `?${queryParams}` : ""
}`;
const newUrl = `${GATEWAY_URL}${pathname}${queryParams ? `?${queryParams}` : ""}`;
console.log(`[Middleware] Rewriting from '/operation-service' path to: ${newUrl}`);
return NextResponse.rewrite(new URL(newUrl));
}
if (pathname.startsWith("/sewerage-service")) {
} else if (pathname.startsWith("/sewerage-service")) {
const queryParams = searchParams.toString();
const newUrl = `${SEWERAGE_API_URL}${pathname.replace("/sewerage-service", "")}${queryParams ? `?${queryParams}` : ""
}`;
const newUrl = `${GATEWAY_URL}${pathname}${queryParams ? `?${queryParams}` : ""}`;
console.log(`[Middleware] Rewriting from '/sewerage-service' path to: ${newUrl}`);
return NextResponse.rewrite(new URL(newUrl));
}
+3
View File
@@ -5,6 +5,9 @@ const subDomain =
const nextConfig: NextConfig = {
output: "standalone",
experimental: {
proxyTimeout: 600000,
},
async rewrites() {
return {
beforeFiles: [
+3 -1
View File
@@ -5,9 +5,10 @@ NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_PROXY_HOST = http://localhost:3000
NEXT_PUBLIC_SUB_DOMAIN = http://localhost:13000
#NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://localhost:3001/auth/login
NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11083/operation-service
NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11083/reuse-service/
NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11083/reuse-service
NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
@@ -17,6 +18,7 @@ NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr
NEXT_PUBLIC_NGII_PARAM = 04trYP9_xwLAfALjwZ-B8g&service=WMTS&request=GetTile&version=1.0.0&format=image/png&layer=korean_map&style=korean&tilematrixset=korean&tilematrix={z}&tilecol={x}&tilerow={y}
NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://dev.onasys.co.kr:3000/auth/login
#NEXT_PUBLIC_SERVER_API_URL = http://localhost:8883/operation-service
REACT_EDITOR=atom
+1 -1
View File
@@ -5,7 +5,7 @@ NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300
NEXT_PUBLIC_SUB_DOMAIN = http://con.mind-one.co.kr:11300
NEXT_PUBLIC_SUB_DOMAIN = http://con.mind-one.co.kr:13000
NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://dev.onasys.co.kr:3000/auth/login
#NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11082
NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11083/operation-service
+3 -4
View File
@@ -8,13 +8,12 @@ NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
#NEXT_PUBLIC_PROXY_HOST = https://devlarva.hasuon.or.kr
#NEXT_PUBLIC_CM_LOGIN_PAGE_URL = https://devqueen.hasuon.or.kr/auth/login
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000/operation-service
NEXT_PUBLIC_FO_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000/operation-service/api/v1
NEXT_PUBLIC_WR_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000/reuse-service
NEXT_PUBLIC_CS_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
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_WR_SERVER_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_DC_URL = http://apigateway.iipbs-was.svc.cluster.local:8000/dc-service
NEXT_PUBLIC_NGII_URL = http://172.29.143.87
NEXT_PUBLIC_SEWERAGE_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000/sewerage-service
NEXT_PUBLIC_NGII_URL = http://172.29.143.87/poiact
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}
@@ -9,67 +9,111 @@
* @author jsyang
*/
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");*/
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
for(let idx = 0; idx < data.length; idx++) {
export default function CalcRainEffect(data: any, weather = 'ALL') {
const rtnDataAll: any = [];
const rtnDataSunny: any = [];
const rtnDataRain: any = [];
let rtnData: any = [];
let rainEffectStd = 0;
for (let idx = 0; idx < data.length; idx++) {
const item = data[idx];
if(item){
if(item.infoRnDay && Number(item.infoRnDay) >= 3) { // 강우량이 3 이상인 경우
item.rainEffectDay = 1;
} else {
item.rainEffectDay = 0;
}
if(item.infoRnDay == 'x'){
item.infoRnDay = '0.0';
item.toBeInfoRnDay = '0.0';
}else{
item.infoRnDay = Number(item.infoRnDay).toFixed(1);
item.toBeInfoRnDay = Number(item.infoRnDay).toFixed(1);
}
if (item.infoRnDay == null || item.infoRnDay == 'x' || item.infoRnDay == '') item.infoRnDay = 0;
if (Number(item.infoRnDay) >= 3) { // 강우일
rainEffectStd = 2;
item.toBeInfoRnDay = item.infoRnDay;
} else {
rainEffectStd--;
}
}
// 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정
for(let idx = 0; idx < data.length; idx++) {
if(data[idx]) {
// 하루 전이 강우영향일(3 이상)인 경우
if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) {
data[idx]!.rainEffectDay = 1;
}
// 이틀 전이 강우영향일(3 이상)인 경우
if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) {
data[idx]!.rainEffectDay = 1;
}
}
}
for(let idx = 0; idx < data.length; idx++) {
if(data[idx] && data[idx]?.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){
if (rainEffectStd < 0) { // 청천일
item.rainEffectDay = 0;
rtnDataSunny.push(item);
} else if (rainEffectStd >= 0) { // 강우일 + 강우영향일
item.rainEffectDay = 1;
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 (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);
}
rtnDataAll.push(item);
}
let rtnData : any = [];
// // 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
// for(let idx = 0; idx < data.length; idx++) {
// const item = data[idx];
// if(item){
// if(item.infoRnDay && Number(item.infoRnDay) >= 3) { // 강우량이 3 이상인 경우
// item.rainEffectDay = 1;
// } else {
// item.rainEffectDay = 0;
// }
// if(item.infoRnDay == 'x'){
// item.infoRnDay = '0.0';
// item.toBeInfoRnDay = '0.0';
// }else{
// item.infoRnDay = Number(item.infoRnDay).toFixed(1);
// item.toBeInfoRnDay = Number(item.infoRnDay).toFixed(1);
// }
// }
// }
// // 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정
// for(let idx = 0; idx < data.length; idx++) {
// if(data[idx]) {
// // 하루 전이 강우영향일(3 이상)인 경우
// if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) {
// data[idx]!.rainEffectDay = 1;
// }
// // 이틀 전이 강우영향일(3 이상)인 경우
// if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) {
// data[idx]!.rainEffectDay = 1;
// }
// }
// }
// for(let idx = 0; idx < data.length; idx++) {
// if(data[idx] && data[idx]?.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 (weather === 'ALL') {
// rtnData = data;
// } else if (weather === 'SUNNY') {
// rtnData = data.filter((item: any) => item.rainEffectDay === 0);
// } else {
// rtnData = data.filter((item: any) => item.rainEffectDay === 1);
// }
if (weather === 'ALL') {
rtnData = data;
rtnData = rtnDataAll;
} else if (weather === 'SUNNY') {
rtnData = data.filter((item: any) => item.rainEffectDay === 0);
rtnData = rtnDataSunny;
} else {
rtnData = data.filter((item: any) => item.rainEffectDay === 1);
rtnData = rtnDataRain;
}
return rtnData;
}
+50 -23
View File
@@ -4,12 +4,39 @@
item: Record<string, unknown>;
}
export const roundNumber = (value : any, decimals: number) => {
/**
* yyyymm 형태의 문자열을 받아 해당 월의 일수를 반환
* @param {string} yyyymm - 예: "202502", "202412"
* @returns {number} 해당 월의 일수 (예: 28, 29, 30, 31)
*/
export const getDaysInMonth = (yyyymm: string) => {
if (typeof yyyymm !== 'string' || yyyymm.length !== 6) {
throw new Error("입력은 'yyyymm' 형식의 문자열이어야 합니다. 예: '202502'");
}
const year = parseInt(yyyymm.slice(0, 4), 10); // "2025" -> 2025
const month = parseInt(yyyymm.slice(4, 6), 10); // "02" -> 2
if (isNaN(year) || isNaN(month) || month < 1 || month > 12) {
throw new Error("유효한 년/월이 아닙니다.");
}
// Date(year, month, 0) -> 전달의 마지막 날
// month에 '다음달'을 넣고, 일(day)에 0을 주면 해당 월의 마지막 날짜가 됨
return new Date(year, month, 0).getDate();
}
export const roundNumber = (value: any, decimals: number) => {
if (typeof value === 'number') {
return addCommas((Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals)).toFixed(decimals));
} else if (typeof value === 'string' && !isNaN(Number(value))) {
return addCommas(Number(value).toFixed(decimals));
} else if (typeof value === 'string') {
// 콤마가 포함된 문자열 처리 ('1,083.0' 같은 경우)
const cleanedValue = value.replace(/,/g, '');
if (!isNaN(Number(cleanedValue))) {
return addCommas(Number(cleanedValue).toFixed(decimals));
}
}
return value; // 변환 불가능한 경우 원래 값 반환
}
export const addCommas = (value: string | number): any => {
@@ -18,48 +45,48 @@ export const addCommas = (value: string | number): any => {
index === 0 ? part : part.replace(/(\d{3})/g, '$1,')
).join('.');
} else if (typeof value === 'string') {
return value.includes('.')?value.split('.').map((part, index) =>
return value.includes('.') ? value.split('.').map((part, index) =>
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
).join('.'):String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
).join('.') : String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
}
export default function DataForm({ type, column, item }: DataFormProps) {
if(item) {
if (item) {
const value = item[column];
switch(type){
switch (type) {
case 'date':
if(value && typeof value === 'string' && value.length >= 8)
if (value && typeof value === 'string' && value.length >= 8 && !value.includes('-'))
item[column] = value.substring(0, 4) + "-" + value.substring(4, 6) + "-" + value.substring(6, 8);
break;
break;
case 'number':
if(value && value != '') {
if (value && value != '') {
item[column] = value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
break;
break;
case 'float0':
if(value) {
item[column] = item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 1) / 1).split('.').map((part, index) =>
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
).join('.')
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
if (value) {
item[column] = item[column] = String(value).includes('.') ? String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 1) / 1).split('.').map((part, index) =>
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
).join('.')
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
break;
break;
case 'float1':
if(value) {
if (value) {
item[column] = roundNumber(value, 1);
}
break;
break;
case 'float2':
if(value) {
if (value) {
item[column] = roundNumber(value, 2);
}
break;
break;
case 'float3':
if(value) {
if (value) {
item[column] = roundNumber(value, 3);
}
break;
break;
}
}
}
@@ -4,14 +4,14 @@ import ListDiv from '@common/business_components/ui/list_div';
import { Table, TableCell, TableHead, TableRow } from '@common/components/ui';
import { useCallback, useEffect, useRef, useState } from 'react';
type FacilityTermModalHeaderProps<T extends { msrDt: string }> = {
fcltyCd : string;
type FacilityTermModalHeaderProps<T extends { msrDt: string }> = { // T는 반드시 msrDt: string 필드를 가져야 한다
fcltyCd: string;
fcltyName: string;
tabName: string;
searchYear: string;
searchList: T[];
ref: React.RefObject<ReturnType<T>>;
queryClick:(returnType:ReturnType<T>) => void;
queryClick: (returnType: ReturnType<T>) => void;
}
export type ReturnType<T> = {
@@ -21,27 +21,28 @@ export type ReturnType<T> = {
filteredList: T[];
}
export default function FacilityTermModalHeader<T extends { msrDt: string }>({
export default function FacilityTermModalHeader<T extends { msrDt: string }>({
searchList,
fcltyName,
tabName,
fcltyName,
tabName,
searchYear,
queryClick,
ref
}: FacilityTermModalHeaderProps<T & { msrDt: string }>) {
const {Common} = useFoStore((state) => state);
const { Common } = useFoStore((state) => state);
const { selectFlowPanel } = Common;
const [startDate, setStartDate] = useState<Date>(new Date(Number(searchYear), 0, 1));
const [endDate, setEndDate] = useState<Date>(new Date(Number(searchYear), 11, 31));
const startPickerRef = useRef<HTMLDivElement>(null);
const endPickerRef = useRef<HTMLDivElement>(null);
const [flowPanel, setFlowPanel] = useState<string>(selectFlowPanel[0]?.val ?? '00');
const [flowPanel, setFlowPanel] = useState<string>(selectFlowPanel[0]?.val ?? '0'); // 강수구분 : 초기값 "전체"
const [copySearchList, setCopySearchList] = useState<T[]>(searchList);
const [standSearchList, setStandSearchList] = useState<T[]>(searchList);
const isDateInRanges = (date: Date) => {
const standYear = parseInt(searchYear);
const dateRanges:{start:Date, end:Date}[] = [];
const isLeapYear = (standYear % 4 === 0 && standYear % 100 !== 0) || (standYear % 400 === 0);
const dateRanges: { start: Date, end: Date }[] = [];
if (tabName.includes("_summer")) {
dateRanges.push({
@@ -51,7 +52,7 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
} else if (tabName.includes("_winter")) {
dateRanges.push({
start: new Date(standYear, 0, 1),
end: new Date(standYear, 1, 28)
end: new Date(standYear, 1, isLeapYear ? 29 : 28)
});
} else {
dateRanges.push({
@@ -70,67 +71,69 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
useEffect(() => {
let startDate = new Date(Number(searchYear), 0, 1);
let endDate = new Date(Number(searchYear), 11, 31);
const standYear = Number(searchYear);
const isLeapYear = (standYear % 4 === 0 && standYear % 100 !== 0) || (standYear % 400 === 0);
if(tabName.includes("_summer")) {
startDate = new Date(Number(searchYear), 5, 1);
endDate = new Date(Number(searchYear), 7, 31);
if (tabName.includes("_summer")) { // 하절기
startDate = new Date(Number(searchYear), 5, 1); // 6월 ~
endDate = new Date(Number(searchYear), 7, 31); // 8월
setStartDate(startDate);
setEndDate(endDate);
} else if (tabName.includes("_winter")) {
startDate = new Date(Number(searchYear), 0, 1);
endDate = new Date(Number(searchYear), 1, 28);
} else if (tabName.includes("_winter")) { // 동절기
startDate = new Date(Number(searchYear), 0, 1); // 1월 ~
endDate = new Date(Number(searchYear), 1, isLeapYear ? 29 : 28); // 2월
setStartDate(startDate);
setEndDate(endDate);
} else {
} else { // 연간
startDate = new Date(Number(searchYear), 0, 1);
endDate = new Date(Number(searchYear), 11, 31);
setStartDate(startDate);
setEndDate(endDate);
}
let filteredData: T[] = [];
if(tabName.includes("_rain")) {
if (tabName.includes("_rain")) { // 강우시
filteredData = searchList.filter((item) => {
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
const rainEffectDay = (item as T & { rainEffectDay: number }).rainEffectDay;
if(flowPanel === '2'){
if (flowPanel === '2') { //3~10mm미만
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 3 && infoRnDay < 10;
} else if(flowPanel === '3'){
} else if (flowPanel === '3') { //10~20mm미만
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 10 && infoRnDay < 20;
} else if(flowPanel === '4'){
} else if (flowPanel === '4') { //20~30mm미만
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 20 && infoRnDay < 30;
} else if(flowPanel === '5'){
} else if (flowPanel === '5') { //30~40mm미만
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 30 && infoRnDay < 40;
} else if(flowPanel === '6'){
} else if (flowPanel === '6') { //40~50mm미만
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 40 && infoRnDay < 50;
} else if(flowPanel === '7'){
} else if (flowPanel === '7') { //50~60mm미만
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 50 && infoRnDay < 60;
} else if(flowPanel === '8'){
} else if (flowPanel === '8') {
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 60;
} else {
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && (rainEffectDay ===1);
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && (rainEffectDay === 1);
}
});
} else if(tabName.includes("_chuncheon")) {
} else if (tabName.includes("_chuncheon")) { // 청천시
filteredData = searchList.filter((item) => {
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
const rainEffectDay = (item as T & { rainEffectDay: number }).rainEffectDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && rainEffectDay==0;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && rainEffectDay == 0;
});
} else {
filteredData = searchList.filter((item) => {
@@ -146,7 +149,7 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
}, [searchList, searchYear, tabName, flowPanel]);
const handleStartDateSelect = (day: Date | undefined) => {
if(day && day > endDate) {
if (day && day > endDate) {
alert('종료일은 시작일 이전일 수 없습니다.');
return;
}
@@ -169,7 +172,7 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
};
const handleEndDateSelect = (day: Date | undefined) => {
if(day && day < startDate) {
if (day && day < startDate) {
alert('종료일은 시작일 이후일 수 없습니다.');
return;
}
@@ -190,7 +193,7 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
});
setCopySearchList(filteredData);
};
const fncSetFilteredList = useCallback(() => {
queryClick({
startDate: startDate,
@@ -203,9 +206,9 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
useEffect(() => {
fncSetFilteredList();
}, [fncSetFilteredList]);
useEffect(() => {
if(ref && ref.current) {
if (ref && ref.current) {
const customRef = ref.current;
customRef.startDate = startDate;
customRef.endDate = endDate;
@@ -222,18 +225,18 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
<TableRow className="!h-[20px]">
<TableHead className="w-[120px]">{'시설명'}</TableHead>
{tabName === "tab_term_rain" ? <TableCell className="w-[300px]">{fcltyName}</TableCell> :
<TableCell className="w-[380px]">{fcltyName}</TableCell>}
<TableCell className="w-[380px]">{fcltyName}</TableCell>}
{tabName === "tab_term_rain" && (
<>
<TableHead className="w-[120px]">{'강수구분'}</TableHead>
<TableCell className="w-[250px]">
<div className="justify-center">
<SelectBox
selectArray={selectFlowPanel}
<SelectBox
selectArray={selectFlowPanel}
value={flowPanel}
onSelectValue={(val) => setFlowPanel(val.toString())}
className="mx-3 w-[150px]"
label=""
className="mx-3 w-[150px]"
label=""
selectClass="w-full p-1 border rounded bg-white"
/>
</div>
@@ -244,7 +247,7 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
<TableCell className="">
<div className="flex">
<div ref={startPickerRef} className="flex justify-center">
<DatePickerRange
<DatePickerRange
mode="single"
selected={startDate}
onSelect={(date) => handleStartDateSelect(date as Date)}
@@ -258,7 +261,7 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
<DatePickerRange
mode="single"
selected={endDate}
onSelect={(date) => handleEndDateSelect(date as Date)}
onSelect={(date) => handleEndDateSelect(date as Date)}
className="w-full p-1 border rounded bg-white"
disabled={(date) => !isDateInRanges(date)}
defaultMonth={endDate}
@@ -271,7 +271,7 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
(head.id === 'flowRate' && index === 0)?<TableCell rowSpan={5} className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
(head.id === 'flowRate' && index === 5)?<TableCell rowSpan={6} className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
(head.id === 'flowRate' && index === 11)?<TableCell rowSpan={2} className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
(head.id === 'groundWaterAvg'||head.id === 'groundWaterSummer'||head.id === 'groundWaterWinter')&&(index === 0)?<TableCell rowSpan={7} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
(head.id === 'groundWaterAvg'||head.id === 'groundWaterSummer'||head.id === 'groundWaterWinter')&&(index === 0)?<TableCell rowSpan={7} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{Number.isNaN(el[head.id]) ? "" : el[head.id]}</TableCell>:
(head.id === 'groundWaterAvg'||head.id === 'groundWaterSummer'||head.id === 'groundWaterWinter')&&(index === 7)?<TableCell rowSpan={6} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
(head.id === 'rdi'&&index === 0)?<TableCell rowSpan={7} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
(head.id === 'rdi'&&index === 7)?<TableCell rowSpan={6} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
@@ -6,7 +6,10 @@
"use client"
import { useFoStore } from "@/app/store";
import { ContentsDiv, downloadExcel, downloadMultipleExcel, filePickedBlobArray, MainDiv, SelectBox, UITab, type SelectDataType } from "@common/business_components";
import {
ContentsDiv, downloadExcelFormat, downloadMultipleExcel, filePickedBlobArrayFormat, MainDiv
, SelectBox, UITab, type SelectDataType
} from "@common/business_components";
import { Button, TabsContent } from "@common/components/ui";
import { useEffect, useState } from "react";
import DashBoardFclty from "../dashboardMain/page";
@@ -40,34 +43,30 @@ export const generateYearDates = (searchYear: string) => {
return dates;
}
type FacilityType = {
bscFctCd: string;
bscFctNm: string;
fcltyCpc: number | '';
trtFrfNm: string | '';
efflWqltStndrdNm: string | '';
}
export default function DashBoard() {
// 입력값 상태 관리
const { Common, initializeCommonData, searchMainGraph, searchRainManage, searchOperationStatus, OperationStatus, RainManage, MainGraph, PlanFclty } = useFoStore((state) => state);
const { Common, initializeCommonData, searchMainGraph, searchRainManage, searchOperationStatus
, OperationStatus, RainManage, MainGraph, PlanFclty } = useFoStore((state) => state);
const [activeTab, setActiveTab] = useState<string>('facilityInfo');
const [filteredSigunData, setFilteredSigunData] = useState<SelectDataType[]>([{ text: "전체", val: '0' }]);
const [sidoValue, setSidoValue] = useState<string>('0');
const [sigunValue, setSigunValue] = useState<string>('0');
const {
isInit,
selectSearchYear,
btnClass,
selectSidoData,
selectSigunData,
} = Common;
const {
planFcltyList
} = PlanFclty;
const {
operationalStatusList
} = OperationStatus;
const {
excelList
} = RainManage;
const { isInit, selectSearchYear, btnClass, selectSidoData, selectSigunData, } = Common;
const defaultSearchYear =
selectSearchYear.find((item) => item.selected)?.val ||
selectSearchYear[0]?.val ||
"0";
const { planFcltyList } = PlanFclty;
const { operationalStatusList } = OperationStatus;
const { excelList } = RainManage;
const {
chart_inflowRain,
chart_bodRain,
@@ -79,10 +78,10 @@ export default function DashBoard() {
} = MainGraph;
/******************선택된 데이터******************/
// 연도
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || '0');
const [searchYear, setSearchYear] = useState<string>(defaultSearchYear); // 연도
// 시설명
const [fcltyList, setFcltyList] = useState<{ bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | '' }>({
const [fcltyList, setFcltyList] = useState<FacilityType>({
bscFctCd: '11000SW001R',
bscFctNm: '난지',
fcltyCpc: 860000,
@@ -90,7 +89,7 @@ export default function DashBoard() {
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
});
const [searchFcltyList, setSearchFcltyList] = useState<{ bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | '' }>({
const [searchFcltyList, setSearchFcltyList] = useState<FacilityType>({
bscFctCd: '',
bscFctNm: '',
fcltyCpc: '',
@@ -111,7 +110,7 @@ export default function DashBoard() {
}
}, [isInit, initializeCommonData]);
const handleFacilityChange = (facility: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | '' }) => {
const handleFacilityChange = (facility: FacilityType) => {
setFcltyList(facility);
};
@@ -143,13 +142,11 @@ export default function DashBoard() {
}
}
const excelDownload = () => {
const excelDownload = async () => {
if (!fcltyList.bscFctCd) return;
switch (activeTab) {
case 'facilityInfo': // 시설정보 및 운영현황
searchOperationStatus(false, searchYear, fcltyList.bscFctCd).then(() => { setTimeout(() => { makeExcelData(); }, 200); });
const makeExcelData = async () => {
fetch(`/mainDashBoard.xlsx`, {}).then(async (response) => {
if (!response.ok) {
@@ -199,20 +196,27 @@ export default function DashBoard() {
headerNum: 3,
headerRange: 'A1:G2',
sheetName: '운영실태',
startCol: 'A'
startCol: 'A',
decimalRange0: 'B3:G2,B9:B11',
decimalRange1: 'B5:G5',
},
{
data: excelData2,
headerNum: 4,
headerRange: 'A1:Q3',
sheetName: '운영실태',
startCol: 'C'
startCol: 'C',
decimalRange0: 'C4:O8',
decimalRange1: 'C9:L10,M11:O11',
decimalRange3: 'C11:L16',
}
];
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
await filePickedBlobArray(blobRet, '시설정보및운영현황', sheetParameter);
await filePickedBlobArrayFormat(blobRet, '시설정보및운영현황', sheetParameter);
});
};
await searchOperationStatus(false, searchYear, fcltyList.bscFctCd);
await makeExcelData();
break;
case 'mainGraph': // 주요그래프
@@ -255,60 +259,6 @@ export default function DashBoard() {
headerRange: 'A1:J1',
sheetName: '주요그래프'
}
/* {
data: [['날짜', '강수량'],...chart_inflowRain.map((item) => [item.label, roundNumber(item.barVal0, 1)])],
headerNum: 1,
headerRange: 'A1:B1',
sheetName: '강수량'
},
{
data: [['날짜', '유입하수량'],...chart_inflowRain.map((item) => [item.label, roundNumber(item.lineVal1, 0)])],
headerNum: 1,
headerRange: 'A1:B1',
sheetName: '유입하수량'
},
{
data: [['날짜', '시설용량'],...chart_inflowRain.map((item) => [item.label, roundNumber(item.lineVal0, 0)])],
headerNum: 1,
headerRange: 'A1:B1',
sheetName: '시설용량'
},
{
data: [['날짜', '유입BOD'],...chart_bodRain.map((item) => [item.label, roundNumber(item.lineVal0, 1)])],
headerNum: 1,
headerRange: 'A1:B1',
sheetName: '유입BOD'
},
{
data: [['날짜', '유입T-P'],...chart_inflTp.map((item) => [item.label, roundNumber(item.val, 3)])],
headerNum: 1,
headerRange: 'A1:B1',
sheetName: '유입T-P'
},
{
data: [['날짜', '총인유입T-P'],...chart_chongInTp.map((item) => [item.label, roundNumber(item.val, 3)])],
headerNum: 1,
headerRange: 'A1:B1',
sheetName: '총인유입T-P'
},
{
data: [['날짜', '방류T-P'],...chart_efflTp.map((item) => [item.label, roundNumber(item.val, 3)])],
headerNum: 1,
headerRange: 'A1:B1',
sheetName: '방류T-P'
},
{
data: [['날짜', '유입T-N'],...chart_inflTn.map((item) => [item.label, roundNumber(item.val, 3)])],
headerNum: 1,
headerRange: 'A1:B1',
sheetName: '유입T-N'
},
{
data: [['날짜', '방류T-N'],...chart_efflTn.map((item) => [item.label, roundNumber(item.val, 3)])],
headerNum: 1,
headerRange: 'A1:B1',
sheetName: '방류T-N'
} */
];
downloadMultipleExcel('주요그래프', sheetParameter);
@@ -317,7 +267,15 @@ export default function DashBoard() {
case 'rainManage': // 강우일 운영현황
searchRainManage(searchYear, fcltyList.bscFctCd, true);
if (excelList && excelList.length > 0) {
downloadExcel({ data: excelList as unknown as JSON[], fileName: '강우일 운영현황', sheetNameArray: ['강우일 운영현황'], headerRange: 'A1:T1' });
downloadExcelFormat({
data: excelList as unknown as JSON[],
fileName: '강우일 운영현황',
sheetNameArray: ['강우일 운영현황'],
headerRange: 'A1:T1',
decimalArray0: [2,3],
decimalArray1: [1,4,5,6,7,10,11,12,15,16,17],
decimalArray3: [8,9,13,14,18,19],
});
}
break;
// Add other cases for different tabs as needed
@@ -342,7 +300,7 @@ export default function DashBoard() {
trtFrfNm: '표준활성슬러지법, MLE, A2O',
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
});
setSearchYear(selectSearchYear[0]?.val || '0');
setSearchYear(defaultSearchYear);
searchFcltyList.bscFctNm = '난지';
setSidoValue('0');
@@ -15,27 +15,13 @@ export type facilityInfoProps = {
fcltyList?: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string, efflWqltStndrdNm: string }[];
};
export default function RainManageTab({searchYear = '', fcltyList = []}: facilityInfoProps) {
const {
Common,
searchRainManage,
RainManage
} = useFoStore((state) => state);
export default function RainManageTab({ searchYear = '', fcltyList = [] }: facilityInfoProps) {
const { Common, searchRainManage, RainManage } = useFoStore((state) => state);
const [hasSearched, setHasSearched] = useState(false);
// 이전 시설코드 저장
const [prevFacilityCode, setPrevFacilityCode] = useState<string>('');
const {
isInit,
} = Common;
const {
upHeadListRainManage,
rainManageList,
} = RainManage;
const [prevFacilityCode, setPrevFacilityCode] = useState<string>(''); // 이전 시설코드 저장
const { isInit, } = Common;
const { upHeadListRainManage, rainManageList, } = RainManage;
const tableData = fcltyList;
useEffect(() => {
@@ -50,17 +36,17 @@ export default function RainManageTab({searchYear = '', fcltyList = []}: facilit
useEffect(() => {
setHasSearched(false);
}, [searchYear]);
return (
<div>
<UiTable
<UiTable
headName=""
tableData={rainManageList}
headlist={upHeadListRainManage}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
onPageChange={() => { }}
widthFixed={true}
>
</UiTable>
@@ -9,7 +9,7 @@ import CalcRainEffect from "@/app/components/common/CalcRainEffect";
import { roundNumber } from "@/app/components/common/DataForm";
import { useFoStore } from "@/app/store";
import type { PrecipitationPropsDetailProps } from "@/app/store/facilityPrecipitation";
import { DatePickerRange, downloadExcel, UiTable } from "@common/business_components/ui";
import { DatePickerRange, downloadExcelHeaders, UiTable } from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button, Table, TableCell, TableHead, TableRow } from "@common/components/ui";
import { useEffect, useRef, useState } from "react";
@@ -45,7 +45,7 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
const standYear = parseInt(props.searchYear);
return [{
start: new Date(standYear, 0, 1),
end: new Date(standYear, 11, 31)
end: new Date(standYear, 11, 31) //월의 index는 0부터 시작
}];
};
@@ -112,7 +112,6 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
const getTableData = () => {
const totals = calculateTotals();
totals.infoRnDay = roundNumber(totals.infoRnDay, 1);
return [
{
bscFctCd: "",
@@ -157,19 +156,26 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
const excelDownload = () => {
const totData = getTableData();
const excelDownList: any[] = [];
// 헤더 순서를 명시적으로 정의
const headers = ["날짜", "강수량(mm/일)", "강우일(일)", "강우영향일(일)"] as const;
const excelDownList: Record<string, string | number>[] = [];
if(totData.length > 0){
totData.forEach((item) => {
excelDownList.push({
"날짜": item.rainDt,
"강수량(mm/일)": roundNumber(item.infoRnDay, 1),
"강우일(일)": roundNumber(item.rainDay, 0),
"강우영향일(일)": roundNumber(item.rainEffectDay, 0),
});
// 순서를 보장하기 위해 헤더 순서대로 객체 생성
const row: Record<string, string | number> = {};
row[headers[0]] = item.rainDt;
row[headers[1]] = roundNumber(item.infoRnDay, 1);
row[headers[2]] = roundNumber(item.rainDay, 0);
row[headers[3]] = roundNumber(item.rainEffectDay, 0);
excelDownList.push(row);
});
}
if (excelDownList && excelDownList.length > 0) {
downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.searchYear+'년 '+props.fcltyName + ' 강수현황', sheetNameArray: ['지하수유입량'], headerRange: 'A1:D1' });
downloadExcelHeaders({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.searchYear+'년 '+props.fcltyName + ' 강수현황'
, sheetNameArray: ['지하수유입량'], headerRange: 'A1:D1', headers });
} else if (totData.length == 0) {
alert('다운받을 데이터가 없습니다.');
}
@@ -5,11 +5,11 @@
*/
"use client"
import { useFoStore } from "@/app/store";
import { StoreContext, useFoStore } from "@/app/store";
import type { TableUpperProps } from "@/app/store/common";
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
import { ContentsDiv, downloadExcelFormat, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
import ListDiv from "@common/business_components/ui/list_div";
import { useCallback, useEffect, useRef, useState } from "react";
import { useCallback, useContext, useEffect, useRef, useState } from "react";
import PrecipitationModal from "./modal/page";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
import UnderComment from "@/app/components/common/UnderComment";
@@ -22,6 +22,11 @@ export default function FacilityPrecipitation() {
,initializeCommonData
,searchFacilityPrecipitationList
} = useFoStore((state) => state) || { processAreaList: { processAreaList: [] }};
const store = useContext(StoreContext);
if (!store) {
throw new Error("StoreContext is not available. Ensure StoreProvider is mounted.");
}
const {
isInit,
@@ -37,6 +42,11 @@ export default function FacilityPrecipitation() {
btnClass
} = Common;
const defaultSearchYear =
selectSearchYear.find((item) => item.selected)?.val ||
selectSearchYear[0]?.val ||
"0";
const {
labelArray,
} = FacilityPrecipitationSearch;
@@ -45,7 +55,6 @@ export default function FacilityPrecipitation() {
upHeadList1,
upHeadList2,
upHeadList3,
excelList,
facilityPrecipitation,
facilityPrecipitationCount,
isLoading,
@@ -90,8 +99,9 @@ export default function FacilityPrecipitation() {
// 시설상태
const [operationValue, setOperationValue] = useState<string>("0");
// 조회기간
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYear, setSearchYear] = useState<string>(defaultSearchYear);
// 엑셀다운로드 트리거
const [isExcelDownClick, setIsExcelDownClick] = useState<boolean>(false);
/**
* 페이지 함수
*/
@@ -102,7 +112,7 @@ export default function FacilityPrecipitation() {
// 상태값 설정
setFcltCpct(selectUpdownData[0]?.val || "0");
setOperationValue(selectOperationData[0]?.val || "0");
setSearchYear(selectSearchYear[0]?.val || "0");
setSearchYear(defaultSearchYear);
// SearchInputSelect 초기화
setFcltyName("");
if (searchInputRef.current) {
@@ -111,7 +121,7 @@ export default function FacilityPrecipitation() {
input.value = "";
}
}
searchFacilityPrecipitationList(1, 10, selectSearchYear[0]?.val || "0");
searchFacilityPrecipitationList(1, 10, defaultSearchYear);
}
// 모달 닫기
@@ -134,20 +144,9 @@ export default function FacilityPrecipitation() {
useEffect(() => {
if (!isInit) {
initializeCommonData();
searchFacilityPrecipitationList(1, 10, selectSearchYear[0]?.val || "0");
searchFacilityPrecipitationList(1, 10, defaultSearchYear);
}
}, [isInit, initializeCommonData, searchFacilityPrecipitationList, selectSearchYear]);
useEffect(() => {
if (excelList && excelList.length > 0) {
downloadExcel({
data: excelList as unknown as JSON[],
fileName: '시설별 강수현황',
sheetNameArray: ['시설별 강수현황'],
headerRange: 'A1:N1'
});
}
}, [excelList]);
}, [isInit, initializeCommonData, searchFacilityPrecipitationList, defaultSearchYear]);
useEffect(() => {
if (facilityPrecipitation.length > 0) {
@@ -159,7 +158,7 @@ export default function FacilityPrecipitation() {
* 콜백함수
*/
// 조회
const searchFacilityPrecipitation = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
const searchFacilityPrecipitation = useCallback(async ({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
let nameCd, partStr
switch (partValue) {
case 'R':
@@ -177,9 +176,9 @@ export default function FacilityPrecipitation() {
break;
}
if (partStr.length > 1 || operationValue!== '0' || fcltCpct !== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
searchFacilityPrecipitationList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
await searchFacilityPrecipitationList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
} else {
searchFacilityPrecipitationList(pageNo, pageCnt, searchYear);
await searchFacilityPrecipitationList(pageNo, pageCnt, searchYear);
}
}, [operationValue, fcltyName, searchFacilityPrecipitationList, searchYear, fcltCpct]);
@@ -190,9 +189,43 @@ export default function FacilityPrecipitation() {
}, [upHeadList1, upHeadList2, upHeadList3]);
// 엑셀다운로드
const excelDownload = useCallback((searchReturn: ReturnType) => {
searchFacilityPrecipitation(searchReturn, 1, 10000);
}, [searchFacilityPrecipitation]);
const excelDownload = useCallback(async (searchReturn: ReturnType) => {
if (isExcelDownClick) 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;
// }
// }
setIsExcelDownClick(true);
try {
await searchFacilityPrecipitation(searchReturn, 1, 10000);
const latestExcelList = store.getState().FacilityPrecipitation.excelList || [];
if (latestExcelList.length > 0) {
downloadExcelFormat({
data: latestExcelList as unknown as JSON[],
fileName: '시설별 강수현황',
sheetNameArray: ['시설별 강수현황'],
headerRange: 'A1:N1',
decimalArray0: [9, 11, 12, 13],
});
} else {
alert("조회된 결과가 없습니다.");
}
} finally {
setIsExcelDownClick(false);
}
}, [isExcelDownClick, searchFacilityPrecipitation, store]);
// 페이지 변경
const handlePageChange = useCallback((page: number) => {
@@ -209,10 +242,13 @@ export default function FacilityPrecipitation() {
<ContentsDiv>
<SearchBaseForm
leftChildren={<>
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData}
onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
<SearchInput className={"col-span-3"} label={labelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
<SelectBox className="col-span-3" label={labelArray[6] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
<SelectBox className="col-span-3" label={labelArray[5] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
<SelectBox className="col-span-3" label={labelArray[6] as string} selectArray={selectSearchYear}
onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
<SelectBox className="col-span-3" label={labelArray[5] as string} selectArray={selectOperationData}
onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
</>}
rightChildren={undefined}
selectSidoData={selectSidoData}
@@ -224,18 +260,22 @@ export default function FacilityPrecipitation() {
btnClass={btnClass}
queryClick={chkVal}
excelClick={excelDownload}
excelDisabled={isExcelDownClick}
initClick={resetVal}
ref={ref} isAdmin={false}/>
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<div className="h-full w-full overflow-x-scroll min-[1200px]:overflow-x-hidden">
<div className="w-[120%] min-[1200px]:w-[100%]">
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 강수현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<div className="h-full w-full overflow-x-scroll min-[1200px]:overflow-x-hidden">
<div className="w-[120%] min-[1200px]:w-[100%]">
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)}
headName={"시설별 강수현황"}
tableData={mainList} headlist={upheadList} pageSize={10} total={total}
resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
</div>
<UnderComment divHeight={"3"} commentArray={["강우일은 3mm 이상만 해당 / 강우영향일은 강우일 및 강우일 후 연속 2일간으로 정의"]} />
</div>
<UnderComment divHeight={"3"} commentArray={["강우일은 3mm 이상만 해당 / 강우영향일은 강우일 및 강우일 후 연속 2일간으로 정의"]} />
</div>
</ListDiv>
</ContentsDiv>
</ListDiv>
</ContentsDiv>
{selectedRow !== null && (
<UiModal
body={<PrecipitationModal searchYear={searchYear} fcltyName={fcltyNm} facilityCd={fcltyCd} detailList={gridListPrecipitationDetail}></PrecipitationModal>}
@@ -248,4 +288,4 @@ export default function FacilityPrecipitation() {
)}
</MainDiv>
);
}
}
@@ -25,10 +25,10 @@ const commentArrayRain = [
"강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날"
];
type ModalProps ={
type ModalProps = {
fcltyName: string;
facilityCd : string;
searchYear : string;
facilityCd: string;
searchYear: string;
}
const tabList1 = [
@@ -50,15 +50,13 @@ const tabList3 = [
{ value: 'tab_term_winter_chongin', label: '동절기' }
];
export default function WaterQualityModal({fcltyName='', facilityCd='', searchYear=new Date().getFullYear().toString()} : ModalProps) {
export default function WaterQualityModal({ fcltyName = '', facilityCd = '', searchYear = new Date().getFullYear().toString() }: ModalProps) {
const [tabName, setTabName] = useState<string>('tab_num1');
// 그리드 관련
const {FacilityWaterQltyModal,
searchFacilityWaterQltyListHist,
Common
} = useFoStore((state) => state);
const {btnClass, COD_YEAR} = Common;
// 날짜 필터링 관련 상태
const [copyYearList, setCopyYearList] = useState<FacilityWaterQltyProps[]>([]);
const [chongInWaterQltyYearList, setChongInWaterQltyYearList] = useState<FacilityWaterQltyProps[]>([]);
const { FacilityWaterQltyModal, searchFacilityWaterQltyListHist, Common } = useFoStore((state) => state);
const { btnClass, COD_YEAR } = Common;
const {
upHeadListModalYear,
upHeadListModalYearCod,
@@ -71,7 +69,17 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
const prevExcelListRef = useRef<modalExcelType[] | null>(null);
const prevChoinginExcelListRef = useRef<modalChoinginExcelType[] | null>(null);
useEffect(() => {
searchFacilityWaterQltyListHist(searchYear, facilityCd);
}, [searchYear, facilityCd, searchFacilityWaterQltyListHist]);
useEffect(() => {
const filteredYearData = setFilterAfterData(facilityWaterQltyYearList);
setCopyYearList(filteredYearData as FacilityWaterQltyProps[]);
setChongInWaterQltyYearList(facilityWaterQltyYearList);
}, [facilityWaterQltyYearList]);
// 필터링 된 후 최대, 최소, 평균 값 계산
const setFilterAfterData = (filteredData: FacilityWaterQltyProps[]) => {
// 쉼표가 포함된 문자열을 숫자로 변환하는 함수
@@ -100,7 +108,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
let maxNoProcessInflAmnt = 0;
let maxInfoRnDay = 0;
// 초기값 설정
let minEfflWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltBod) : 0;
let minEfflWqltTn = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltTn) : 0;
@@ -108,14 +116,14 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
let minefflWqltToc = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltToc) : 0;
let minefflWqltCod = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltCod) : 0;
let minEfflWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltSs) : 0;
let mininflAssctBfrWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltBod) : 0;
let mininflAssctBfrWqltTn = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltTn) : 0;
let minInflAssctBfrWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltTp) : 0;
let mininflAssctBfrWqltToc = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltToc) : 0;
let mininflAssctBfrWqltCod = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltCod) : 0;
let mininflAssctBfrWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltSs) : 0;
let minTpInflWqltBod = 99999999;
let minTpInflWqltTp = 99999999;
let minNoProcessInflAmnt = 99999999;
@@ -143,27 +151,27 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
let noProcessInflAmntCnt = 0;
let avgInfoRnDay = 0;
filteredData.forEach((item: FacilityWaterQltyProps) => {
const efflWqltBod = parseNumber(item.efflWqltBod);
const efflWqltTn = parseNumber(item.efflWqltTn);
const efflWqltTp = parseNumber(item.efflWqltTp);
const efflWqltToc = parseNumber(item.efflWqltToc);
const efflWqltCod = parseNumber(item.efflWqltCod?item.efflWqltCod.replaceAll("(","").replaceAll(")",""):0);
const efflWqltCod = parseNumber(item.efflWqltCod ? item.efflWqltCod.replaceAll("(", "").replaceAll(")", "") : 0);
const efflWqltSs = parseNumber(item.efflWqltSs);
const inflAssctBfrWqltBod = parseNumber(item.inflAssctBfrWqltBod);
const inflAssctBfrWqltTn = parseNumber(item.inflAssctBfrWqltTn);
const inflAssctBfrWqltTp = parseNumber(item.inflAssctBfrWqltTp);
const inflAssctBfrWqltToc = parseNumber(item.inflAssctBfrWqltToc);
const inflAssctBfrWqltCod = parseNumber(item.inflAssctBfrWqltCod?item.inflAssctBfrWqltCod.replaceAll("(","").replaceAll(")",""):0);
const inflAssctBfrWqltCod = parseNumber(item.inflAssctBfrWqltCod ? item.inflAssctBfrWqltCod.replaceAll("(", "").replaceAll(")", "") : 0);
const inflAssctBfrWqltSs = parseNumber(item.inflAssctBfrWqltSs);
const tpInflWqltBod = parseNumber(item.tpInflWqltBod);
const tpInflWqltTp = parseNumber(item.tpInflWqltTp);
if(item.tpInflWqltBod != null && item.tpInflWqltBod.trim() != '' && item.tpInflWqltBod != undefined ){
if (item.tpInflWqltBod != null && item.tpInflWqltBod.trim() != '' && item.tpInflWqltBod != undefined) {
tpInflWqltBodCnt += 1;
}
if(item.tpInflWqltTp != null && item.tpInflWqltTp.trim() != '' && item.tpInflWqltTp != undefined ){
if (item.tpInflWqltTp != null && item.tpInflWqltTp.trim() != '' && item.tpInflWqltTp != undefined) {
tpInflWqltTpCnt += 1;
}
@@ -175,7 +183,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
maxefflWqltToc = Math.max(maxefflWqltToc, efflWqltToc);
maxefflWqltCod = Math.max(maxefflWqltCod, efflWqltCod);
maxEfflWqltSs = Math.max(maxEfflWqltSs, efflWqltSs);
maxinflAssctBfrWqltBod = Math.max(maxinflAssctBfrWqltBod, inflAssctBfrWqltBod);
maxinflAssctBfrWqltTn = Math.max(maxinflAssctBfrWqltTn, inflAssctBfrWqltTn);
maxInflAssctBfrWqltTp = Math.max(maxInflAssctBfrWqltTp, inflAssctBfrWqltTp);
@@ -202,11 +210,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
mininflAssctBfrWqltCod = Math.min(mininflAssctBfrWqltToc, inflAssctBfrWqltCod);
mininflAssctBfrWqltSs = Math.min(mininflAssctBfrWqltSs, inflAssctBfrWqltSs);
if(item.tpInflWqltBod != null && item.tpInflWqltBod.trim() != '' && item.tpInflWqltBod != undefined ){
if (item.tpInflWqltBod != null && item.tpInflWqltBod.trim() != '' && item.tpInflWqltBod != undefined) {
minTpInflWqltBod = Math.min(minTpInflWqltBod, tpInflWqltBod);
avgTpInflWqltBod += tpInflWqltBod;
}
if(item.tpInflWqltTp != null && item.tpInflWqltTp.trim() != '' && item.tpInflWqltTp != undefined ){
if (item.tpInflWqltTp != null && item.tpInflWqltTp.trim() != '' && item.tpInflWqltTp != undefined) {
minTpInflWqltTp = Math.min(minTpInflWqltTp, tpInflWqltTp);
avgTpInflWqltTp += tpInflWqltTp;
}
@@ -227,12 +235,12 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
avginflAssctBfrWqltCod += inflAssctBfrWqltCod;
avginflAssctBfrWqltSs += inflAssctBfrWqltSs;
if(item.noProcessInflAmnt && item.noProcessInflAmnt.toString().trim() != '' && item.noProcessInflAmnt != undefined){
const noProcessInflAmnt = Number(item.noProcessInflAmnt.toString().replaceAll(',',''));
if (item.noProcessInflAmnt && item.noProcessInflAmnt.toString().trim() != '' && item.noProcessInflAmnt != undefined) {
const noProcessInflAmnt = Number(item.noProcessInflAmnt.toString().replaceAll(',', ''));
avgNoProcessInflAmnt += noProcessInflAmnt;
maxNoProcessInflAmnt = Math.max(maxNoProcessInflAmnt, noProcessInflAmnt);
minNoProcessInflAmnt = Math.min(minNoProcessInflAmnt, noProcessInflAmnt);
noProcessInflAmntCnt +=1;
noProcessInflAmntCnt += 1;
}
avgInfoRnDay += infoRnDay;
@@ -241,18 +249,18 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
const newFilteredData = [
{
msrDt: '평균',
efflWqltBod: filteredData.length==0 || avgEfflWqltBod===0?'0.0':roundNumber((avgEfflWqltBod / filteredData.length), 1),
efflWqltToc: filteredData.length==0 || avgefflWqltToc===0?'0.0':roundNumber((avgefflWqltToc / filteredData.length), 1),
efflWqltCod: filteredData.length==0 || avgefflWqltCod===0?"(0.0)":"("+roundNumber((avgefflWqltCod / filteredData.length), 1)+")",
efflWqltSs: filteredData.length==0 || avgEfflWqltSs===0?'0.0':roundNumber((avgEfflWqltSs / filteredData.length), 1),
efflWqltTn: filteredData.length==0 || avgEfflWqltTn ===0?'0.000':roundNumber((avgEfflWqltTn / filteredData.length), 3),
efflWqltTp: filteredData.length==0 || avgEfflWqltTp ===0?'0.000':roundNumber((avgEfflWqltTp / filteredData.length), 3),
inflAssctBfrWqltBod: filteredData.length==0 || avginflAssctBfrWqltBod===0?'0.0':roundNumber((avginflAssctBfrWqltBod / filteredData.length), 1),
inflAssctBfrWqltTn: filteredData.length==0 || avginflAssctBfrWqltTn===0?'0.000':roundNumber((avginflAssctBfrWqltTn / filteredData.length), 3),
inflAssctBfrWqltTp: filteredData.length==0 || avgInflAssctBfrWqltTp===0?'0.000':roundNumber((avgInflAssctBfrWqltTp / filteredData.length), 3),
inflAssctBfrWqltToc: filteredData.length==0 || avginflAssctBfrWqltToc===0?'0.0':roundNumber((avginflAssctBfrWqltToc / filteredData.length), 1),
inflAssctBfrWqltCod: filteredData.length==0 || avginflAssctBfrWqltCod===0?'(0.0)':"("+roundNumber((avginflAssctBfrWqltCod / filteredData.length), 1)+")",
inflAssctBfrWqltSs: filteredData.length==0 || avginflAssctBfrWqltSs===0?'0.0':roundNumber((avginflAssctBfrWqltSs / filteredData.length), 1),
efflWqltBod: filteredData.length == 0 || avgEfflWqltBod === 0 ? '0.0' : roundNumber((avgEfflWqltBod / filteredData.length), 1),
efflWqltToc: filteredData.length == 0 || avgefflWqltToc === 0 ? '0.0' : roundNumber((avgefflWqltToc / filteredData.length), 1),
efflWqltCod: filteredData.length == 0 || avgefflWqltCod === 0 ? "(0.0)" : "(" + roundNumber((avgefflWqltCod / filteredData.length), 1) + ")",
efflWqltSs: filteredData.length == 0 || avgEfflWqltSs === 0 ? '0.0' : roundNumber((avgEfflWqltSs / filteredData.length), 1),
efflWqltTn: filteredData.length == 0 || avgEfflWqltTn === 0 ? '0.000' : roundNumber((avgEfflWqltTn / filteredData.length), 3),
efflWqltTp: filteredData.length == 0 || avgEfflWqltTp === 0 ? '0.000' : roundNumber((avgEfflWqltTp / filteredData.length), 3),
inflAssctBfrWqltBod: filteredData.length == 0 || avginflAssctBfrWqltBod === 0 ? '0.0' : roundNumber((avginflAssctBfrWqltBod / filteredData.length), 1),
inflAssctBfrWqltTn: filteredData.length == 0 || avginflAssctBfrWqltTn === 0 ? '0.000' : roundNumber((avginflAssctBfrWqltTn / filteredData.length), 3),
inflAssctBfrWqltTp: filteredData.length == 0 || avgInflAssctBfrWqltTp === 0 ? '0.000' : roundNumber((avgInflAssctBfrWqltTp / filteredData.length), 3),
inflAssctBfrWqltToc: filteredData.length == 0 || avginflAssctBfrWqltToc === 0 ? '0.0' : roundNumber((avginflAssctBfrWqltToc / filteredData.length), 1),
inflAssctBfrWqltCod: filteredData.length == 0 || avginflAssctBfrWqltCod === 0 ? '(0.0)' : "(" + roundNumber((avginflAssctBfrWqltCod / filteredData.length), 1) + ")",
inflAssctBfrWqltSs: filteredData.length == 0 || avginflAssctBfrWqltSs === 0 ? '0.0' : roundNumber((avginflAssctBfrWqltSs / filteredData.length), 1),
bscFctCd: "",
bscFctNm: "",
lclgvrnmntNm: "",
@@ -260,25 +268,25 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
sggNm: "",
addr: "",
fctCpc: 0,
noProcessInflAmnt : roundNumber(avgNoProcessInflAmnt / noProcessInflAmntCnt, 0),
infoRnDay: filteredData.length==0 || avgInfoRnDay===0?'0.0':roundNumber(avgInfoRnDay / filteredData.length, 1),
tpInflWqltBod: filteredData.length==0 || avgTpInflWqltBod ===0 ?'0.0':roundNumber(avgTpInflWqltBod / tpInflWqltBodCnt, 1),
tpInflWqltTp: filteredData.length==0 || avgTpInflWqltTp === 0?'0.000':roundNumber(avgTpInflWqltTp / tpInflWqltTpCnt, 3)
noProcessInflAmnt: roundNumber(avgNoProcessInflAmnt / noProcessInflAmntCnt, 0),
infoRnDay: filteredData.length == 0 || avgInfoRnDay === 0 ? '0.0' : roundNumber(avgInfoRnDay / filteredData.length, 1),
tpInflWqltBod: filteredData.length == 0 || avgTpInflWqltBod === 0 ? '0.0' : roundNumber(avgTpInflWqltBod / tpInflWqltBodCnt, 1),
tpInflWqltTp: filteredData.length == 0 || avgTpInflWqltTp === 0 ? '0.000' : roundNumber(avgTpInflWqltTp / tpInflWqltTpCnt, 3)
},
{
msrDt : '최대',
efflWqltBod : Math.round(maxEfflWqltBod * 10) / 10?roundNumber(maxEfflWqltBod, 1):'0.0',
efflWqltToc : Math.round(maxefflWqltToc * 10) / 10?roundNumber(maxefflWqltToc, 1):'0.0',
efflWqltCod : Math.round(maxefflWqltCod * 10) / 10?"("+roundNumber(maxefflWqltCod, 1)+")":'(0.0)',
efflWqltSs : Math.round(maxEfflWqltSs * 10) / 10?roundNumber(maxEfflWqltSs, 1):'0.0',
efflWqltTn : Math.round(maxEfflWqltTn * 1000) / 1000?roundNumber(maxEfflWqltTn, 3):'0.000',
efflWqltTp : Math.round(maxEfflWqltTp * 1000) / 1000?roundNumber(maxEfflWqltTp, 3):'0.000',
inflAssctBfrWqltBod : Math.round(maxinflAssctBfrWqltBod * 10) / 10?roundNumber(maxinflAssctBfrWqltBod, 1):'0.0',
inflAssctBfrWqltTn : Math.round(maxinflAssctBfrWqltTn * 1000) / 1000?roundNumber(maxinflAssctBfrWqltTn, 3):'0.000',
inflAssctBfrWqltTp : Math.round(maxInflAssctBfrWqltTp * 1000) / 1000?roundNumber(maxInflAssctBfrWqltTp, 3):'0.000',
inflAssctBfrWqltToc : Math.round(maxinflAssctBfrWqltToc * 10) / 10?roundNumber(maxinflAssctBfrWqltToc, 1):'0.0',
inflAssctBfrWqltCod : Math.round(maxinflAssctBfrWqltCod * 10) / 10?"("+roundNumber(maxinflAssctBfrWqltCod, 1)+")":'(0.0)',
inflAssctBfrWqltSs : Math.round(maxinflAssctBfrWqltSs * 10) / 10?roundNumber(maxinflAssctBfrWqltSs, 1):'0.0',
msrDt: '최대',
efflWqltBod: Math.round(maxEfflWqltBod * 10) / 10 ? roundNumber(maxEfflWqltBod, 1) : '0.0',
efflWqltToc: Math.round(maxefflWqltToc * 10) / 10 ? roundNumber(maxefflWqltToc, 1) : '0.0',
efflWqltCod: Math.round(maxefflWqltCod * 10) / 10 ? "(" + roundNumber(maxefflWqltCod, 1) + ")" : '(0.0)',
efflWqltSs: Math.round(maxEfflWqltSs * 10) / 10 ? roundNumber(maxEfflWqltSs, 1) : '0.0',
efflWqltTn: Math.round(maxEfflWqltTn * 1000) / 1000 ? roundNumber(maxEfflWqltTn, 3) : '0.000',
efflWqltTp: Math.round(maxEfflWqltTp * 1000) / 1000 ? roundNumber(maxEfflWqltTp, 3) : '0.000',
inflAssctBfrWqltBod: Math.round(maxinflAssctBfrWqltBod * 10) / 10 ? roundNumber(maxinflAssctBfrWqltBod, 1) : '0.0',
inflAssctBfrWqltTn: Math.round(maxinflAssctBfrWqltTn * 1000) / 1000 ? roundNumber(maxinflAssctBfrWqltTn, 3) : '0.000',
inflAssctBfrWqltTp: Math.round(maxInflAssctBfrWqltTp * 1000) / 1000 ? roundNumber(maxInflAssctBfrWqltTp, 3) : '0.000',
inflAssctBfrWqltToc: Math.round(maxinflAssctBfrWqltToc * 10) / 10 ? roundNumber(maxinflAssctBfrWqltToc, 1) : '0.0',
inflAssctBfrWqltCod: Math.round(maxinflAssctBfrWqltCod * 10) / 10 ? "(" + roundNumber(maxinflAssctBfrWqltCod, 1) + ")" : '(0.0)',
inflAssctBfrWqltSs: Math.round(maxinflAssctBfrWqltSs * 10) / 10 ? roundNumber(maxinflAssctBfrWqltSs, 1) : '0.0',
bscFctCd: "",
bscFctNm: "",
lclgvrnmntNm: "",
@@ -286,25 +294,25 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
sggNm: "",
addr: "",
fctCpc: 0,
noProcessInflAmnt : roundNumber(maxNoProcessInflAmnt, 0),
infoRnDay: Math.round(maxInfoRnDay * 10) / 10?roundNumber(maxInfoRnDay, 1):'0.0',
tpInflWqltBod: Math.round(maxTpInflWqltBod * 10) / 10?roundNumber(maxTpInflWqltBod, 1):'0.0',
tpInflWqltTp: Math.round(maxTpInflWqltTp * 1000) / 1000?roundNumber(maxTpInflWqltTp, 3):'0.000'
noProcessInflAmnt: roundNumber(maxNoProcessInflAmnt, 0),
infoRnDay: Math.round(maxInfoRnDay * 10) / 10 ? roundNumber(maxInfoRnDay, 1) : '0.0',
tpInflWqltBod: Math.round(maxTpInflWqltBod * 10) / 10 ? roundNumber(maxTpInflWqltBod, 1) : '0.0',
tpInflWqltTp: Math.round(maxTpInflWqltTp * 1000) / 1000 ? roundNumber(maxTpInflWqltTp, 3) : '0.000'
},
{
msrDt : '최소',
efflWqltBod : Math.round(minEfflWqltBod * 10) / 10?roundNumber(minEfflWqltBod, 1) : '0.0',
efflWqltToc : Math.round(minefflWqltToc * 10) / 10?roundNumber(minefflWqltToc, 1) : '0.0',
efflWqltCod : Math.round(minefflWqltCod * 10) / 10?"("+roundNumber(minefflWqltCod, 1)+")" : '(0.0)',
efflWqltSs : Math.round(minEfflWqltSs * 10) / 10?roundNumber(minEfflWqltSs, 1) : '0.0',
efflWqltTn : Math.round(minEfflWqltTn * 1000) / 1000?roundNumber(minEfflWqltTn, 3) : '0.000',
efflWqltTp : Math.round(minEfflWqltTp * 1000) / 1000?roundNumber(minEfflWqltTp, 3) : '0.000',
inflAssctBfrWqltBod : Math.round(mininflAssctBfrWqltBod * 10) / 10?roundNumber(mininflAssctBfrWqltBod, 1) : '0.0',
inflAssctBfrWqltTn : Math.round(mininflAssctBfrWqltTn * 1000) / 1000?roundNumber(mininflAssctBfrWqltTn, 3) : '0.000',
inflAssctBfrWqltTp : Math.round(minInflAssctBfrWqltTp * 1000) / 1000?roundNumber(minInflAssctBfrWqltTp, 3) : '0.000',
inflAssctBfrWqltToc : Math.round(mininflAssctBfrWqltToc * 10) / 10?roundNumber(mininflAssctBfrWqltToc, 1) : '0.0',
inflAssctBfrWqltCod : Math.round(mininflAssctBfrWqltCod * 10) / 10?"("+roundNumber(mininflAssctBfrWqltCod, 1)+")" : '(0.0)',
inflAssctBfrWqltSs : Math.round(mininflAssctBfrWqltSs * 10) / 10?roundNumber(mininflAssctBfrWqltSs, 1) : '0.0',
msrDt: '최소',
efflWqltBod: Math.round(minEfflWqltBod * 10) / 10 ? roundNumber(minEfflWqltBod, 1) : '0.0',
efflWqltToc: Math.round(minefflWqltToc * 10) / 10 ? roundNumber(minefflWqltToc, 1) : '0.0',
efflWqltCod: Math.round(minefflWqltCod * 10) / 10 ? "(" + roundNumber(minefflWqltCod, 1) + ")" : '(0.0)',
efflWqltSs: Math.round(minEfflWqltSs * 10) / 10 ? roundNumber(minEfflWqltSs, 1) : '0.0',
efflWqltTn: Math.round(minEfflWqltTn * 1000) / 1000 ? roundNumber(minEfflWqltTn, 3) : '0.000',
efflWqltTp: Math.round(minEfflWqltTp * 1000) / 1000 ? roundNumber(minEfflWqltTp, 3) : '0.000',
inflAssctBfrWqltBod: Math.round(mininflAssctBfrWqltBod * 10) / 10 ? roundNumber(mininflAssctBfrWqltBod, 1) : '0.0',
inflAssctBfrWqltTn: Math.round(mininflAssctBfrWqltTn * 1000) / 1000 ? roundNumber(mininflAssctBfrWqltTn, 3) : '0.000',
inflAssctBfrWqltTp: Math.round(minInflAssctBfrWqltTp * 1000) / 1000 ? roundNumber(minInflAssctBfrWqltTp, 3) : '0.000',
inflAssctBfrWqltToc: Math.round(mininflAssctBfrWqltToc * 10) / 10 ? roundNumber(mininflAssctBfrWqltToc, 1) : '0.0',
inflAssctBfrWqltCod: Math.round(mininflAssctBfrWqltCod * 10) / 10 ? "(" + roundNumber(mininflAssctBfrWqltCod, 1) + ")" : '(0.0)',
inflAssctBfrWqltSs: Math.round(mininflAssctBfrWqltSs * 10) / 10 ? roundNumber(mininflAssctBfrWqltSs, 1) : '0.0',
bscFctCd: "",
bscFctNm: "",
lclgvrnmntNm: "",
@@ -312,10 +320,10 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
sggNm: "",
addr: "",
fctCpc: 0,
noProcessInflAmnt : roundNumber(minNoProcessInflAmnt, 0),
infoRnDay: Math.round(minInfoRnDay * 10) / 10?'0.0':roundNumber(minInfoRnDay, 1),
tpInflWqltBod: Math.round(minTpInflWqltBod * 10) / 10 && minTpInflWqltBod != 99999999?roundNumber(minTpInflWqltBod, 1):'0.0',
tpInflWqltTp: Math.round(minTpInflWqltTp * 1000) / 1000 && minTpInflWqltTp != 99999999?roundNumber(minTpInflWqltTp, 3):'0.000'
noProcessInflAmnt: roundNumber(minNoProcessInflAmnt, 0),
infoRnDay: Math.round(minInfoRnDay * 10) / 10 ? roundNumber(minInfoRnDay, 1) : '0.0',
tpInflWqltBod: Math.round(minTpInflWqltBod * 10) / 10 && minTpInflWqltBod != 99999999 ? roundNumber(minTpInflWqltBod, 1) : '0.0',
tpInflWqltTp: Math.round(minTpInflWqltTp * 1000) / 1000 && minTpInflWqltTp != 99999999 ? roundNumber(minTpInflWqltTp, 3) : '0.000'
},
...filteredData
];
@@ -323,20 +331,6 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
return newFilteredData;
}
// 날짜 필터링 관련 상태
const [copyYearList, setCopyYearList] = useState<FacilityWaterQltyProps[]>([]);
const [chongInWaterQltyYearList, setChongInWaterQltyYearList] = useState<FacilityWaterQltyProps[]>([]);
useEffect(() => {
searchFacilityWaterQltyListHist(searchYear, facilityCd);
}, [searchYear, facilityCd, searchFacilityWaterQltyListHist]);
useEffect(() => {
const filteredYearData = setFilterAfterData(facilityWaterQltyYearList);
setCopyYearList(filteredYearData as FacilityWaterQltyProps[]);
setChongInWaterQltyYearList(filteredYearData as FacilityWaterQltyProps[]);
}, [facilityWaterQltyYearList]);
const yesterDay = new Date();
yesterDay.setDate(yesterDay.getDate() - 1);
const yesterDayStr = yesterDay.toISOString().split('T')[0];
@@ -350,14 +344,14 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
const filterData = useCallback((returnType: ReturnType<FacilityWaterQltyProps>) => {
const filteredData = setFilterAfterData(returnType.filteredList);
setCopyYearList(filteredData as FacilityWaterQltyProps[]);
setCopyYearList(filteredData as FacilityWaterQltyProps[]); // 처리시설/총인설비 수질현황
}, []);
const excelDownload = () => {
if(tabName === 'tab_num1'){
if (tabName === 'tab_num1') { //처리시설 수질현황
const excelDownList: modalExcelType[] = [];
if(copyYearList.length > 0){
if (copyYearList.length > 0) {
copyYearList.forEach((item) => {
excelDownList.push({
날짜: item.msrDt,
@@ -371,44 +365,48 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
"유출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"),
"강우량(mm/일)": CommaToNumber(item.infoRnDay ? item.infoRnDay.toString() : "0.0"),
});
});
}
if (excelDownList && excelDownList.length > 0) {
downloadExcelFormat(
{ data: JSON.parse(JSON.stringify(excelDownList))
, fileName: searchYear+'년 '+fcltyName + ' 수질현황'
{
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]
, 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{
} else { // 총인설비 수질현황
const excelDownList: modalChoinginExcelType[] = [];
if(chongInWaterQltyYearList.length > 0){
chongInWaterQltyYearList.forEach((item) => {
// if (chongInWaterQltyYearList.length > 0) {
// chongInWaterQltyYearList.forEach((item) => {
if (copyYearList.length > 0) {
copyYearList.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),
"유출TP(mg/L)": CommaToNumber(item.efflWqltTp),
});
});
}
if (excelDownList && excelDownList.length > 0) {
downloadExcelFormat(
{ data: JSON.parse(JSON.stringify(excelDownList))
, fileName: searchYear+'년 '+fcltyName + ' 총인설비수질현황'
{
data: JSON.parse(JSON.stringify(excelDownList))
, fileName: searchYear + '년 ' + fcltyName + ' 총인설비수질현황'
, sheetNameArray: [fcltyName + ' 총인설비수질현황']
, headerRange: 'A1:E1'
, decimalArray1: [1,3]
, decimalArray3: [2,4]
, decimalArray1: [1, 3]
, decimalArray3: [2, 4]
});
} else if (prevChoinginExcelListRef.current && prevChoinginExcelListRef.current.length > 0) {
alert('다운받을 데이터가 없습니다.');
@@ -424,168 +422,127 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
return (
<>
<UITab tabList={tabList1} defaultValue="tab_num1" onValueChange={(value) => setTabName(value)}>
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownload}>
<Button className={btnClass} style={{ float: 'right' }} color="green" onClick={excelDownload}>
{"엑셀다운로드"}
</Button>
{/* 처리시설 수질현황 */}
<TabsContent value="tab_num1">
<UITab tabList={tabList2} defaultValue="tab_term_year">
<TabsContent value="tab_term_year">
<TabsContent value="tab_term_year">{/* 연간 */}
<FacilityTermModalHeader<FacilityWaterQltyProps>
searchList={facilityWaterQltyYearList}
fcltyCd={facilityCd}
fcltyName={fcltyName}
tabName={"tab_term_year"}
searchYear={searchYear}
ref={ref}
queryClick={filterData}
fcltyCd={facilityCd} fcltyName={fcltyName} tabName="tab_term_year"
searchYear={searchYear} ref={ref} queryClick={filterData}
/>
<div className="overflow-y-auto h-[350px]">
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={Number(searchYear)<COD_YEAR?upHeadListModalYearCod:upHeadListModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[310px]"
boldArray={[0,1,2]}
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={Number(searchYear) < COD_YEAR ? upHeadListModalYearCod : upHeadListModalYear}
pageSize={0} total={0} cellClick={undefined}
onPageChange={() => { }} className="h-[310px]" boldArray={[0, 1, 2]}
>
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
</UiTable>
</div>
<div className="card-header">
<div className="card-header border-t mt-1">
<h3 className="text-2xl font-medium text-label">수질 TMS</h3>
{/*<h3 className="text-2xl font-medium text-label text-right">({msrmtDate?msrmtDate.substring(0,4)+'-'+msrmtDate.substring(4,6)+'-'+msrmtDate.substring(6,8):yesterDayStr})</h3> */}
<h3 className="text-2xl font-medium text-label text-right">
({msrmtDate ? msrmtDate.substring(0, 4) + '-' + msrmtDate.substring(4, 6) + '-' + msrmtDate.substring(6, 8) : yesterDayStr})
</h3>
</div>
<div className="overflow-y-auto h-[250px]">
<UiTable
headName={undefined}
tableData={tmsList}
headlist={upHeadListModalTms}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
boldArray={[0,1,2]}
<UiTable
headName={undefined}
tableData={tmsList}
headlist={upHeadListModalTms}
pageSize={0} total={0} cellClick={undefined}
onPageChange={() => { }} boldArray={[0, 1, 2]}
>
<HeadMakeColSpan upHeadList={upHeadListModalTms} layoutNum={4} />
</UiTable>
{msrmtDate != yesterDayStr?.replaceAll('-','') ? (
<UnderComment commentArray={["전날 데이터 결측으로 인해 가장 최근 데이터 표출함"]} divHeight="0"/>
{msrmtDate != yesterDayStr?.replaceAll('-', '') ? (
<UnderComment commentArray={["전날 데이터 결측으로 인해 가장 최근 데이터 표출함"]} divHeight="0" />
) : null}
</div>
</TabsContent>
<TabsContent value="tab_term_summer">
<TabsContent value="tab_term_summer">{/* 하절기 */}
<FacilityTermModalHeader<FacilityWaterQltyProps>
searchList={facilityWaterQltyYearList}
fcltyCd={facilityCd}
fcltyName={fcltyName}
tabName="tab_term_summer"
searchYear={searchYear}
ref={ref}
queryClick={filterData}
fcltyCd={facilityCd} fcltyName={fcltyName} tabName="tab_term_summer"
searchYear={searchYear} ref={ref} queryClick={filterData}
/>
<div className="overflow-y-auto h-[500px]">
<UiTable
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={Number(searchYear)<COD_YEAR?upHeadListModalYearCod:upHeadListModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => { } }
className="h-[500px]"
boldArray={[0,1,2]}
headlist={Number(searchYear) < COD_YEAR ? upHeadListModalYearCod : upHeadListModalYear}
pageSize={0} total={0} cellClick={undefined}
onPageChange={() => { }} className="h-[500px]" boldArray={[0, 1, 2]}
>
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
</UiTable>
</div>
</TabsContent>
<TabsContent value="tab_term_winter">
<TabsContent value="tab_term_winter">{/* 동절기 */}
<FacilityTermModalHeader<FacilityWaterQltyProps>
searchList={facilityWaterQltyYearList}
fcltyCd={facilityCd}
fcltyName={fcltyName}
tabName="tab_term_winter"
searchYear={searchYear}
ref={ref}
queryClick={filterData}
fcltyCd={facilityCd} fcltyName={fcltyName} tabName="tab_term_winter"
searchYear={searchYear} ref={ref} queryClick={filterData}
/>
<div className="overflow-y-auto h-[500px]">
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={Number(searchYear)<COD_YEAR?upHeadListModalYearCod:upHeadListModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[500px]"
boldArray={[0,1,2]}
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={Number(searchYear) < COD_YEAR ? upHeadListModalYearCod : upHeadListModalYear}
pageSize={0} total={0} cellClick={undefined}
onPageChange={() => { }} className="h-[500px]" boldArray={[0, 1, 2]}
>
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
</UiTable>
</div>
</TabsContent>
<TabsContent value="tab_term_chuncheon">
<TabsContent value="tab_term_chuncheon">{/* 청천시 */}
<FacilityTermModalHeader<FacilityWaterQltyProps>
searchList={facilityWaterQltyYearList}
fcltyCd={facilityCd}
fcltyName={fcltyName}
tabName="tab_term_chuncheon"
searchYear={searchYear}
ref={ref}
queryClick={filterData}
fcltyCd={facilityCd} fcltyName={fcltyName} tabName="tab_term_chuncheon"
searchYear={searchYear} ref={ref} queryClick={filterData}
/>
<div className="overflow-y-auto h-[500px]">
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={Number(searchYear)<COD_YEAR?upHeadListModalYearCod:upHeadListModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[500px]"
boldArray={[0,1,2]}
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={Number(searchYear) < COD_YEAR ? upHeadListModalYearCod : upHeadListModalYear}
pageSize={0} total={0} cellClick={undefined}
onPageChange={() => { }} className="h-[500px]" boldArray={[0, 1, 2]}
>
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
</UiTable>
</div>
<UnderComment commentArray={commentArrayChungchun} divHeight="10"/>
<UnderComment commentArray={commentArrayChungchun} divHeight="10" />
</TabsContent>
<TabsContent value="tab_term_rain">
<TabsContent value="tab_term_rain">{/* 강우시 */}
<FacilityTermModalHeader<FacilityWaterQltyProps>
searchList={facilityWaterQltyYearList}
fcltyCd={facilityCd}
fcltyName={fcltyName}
tabName="tab_term_rain"
searchYear={searchYear}
ref={ref}
queryClick={filterData}
fcltyCd={facilityCd} fcltyName={fcltyName} tabName="tab_term_rain"
searchYear={searchYear} ref={ref} queryClick={filterData}
/>
<div className="overflow-y-auto h-[500px]">
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={Number(searchYear)<COD_YEAR?upHeadListModalYearCod:upHeadListModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[500px]"
boldArray={[0,1,2]}
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={Number(searchYear) < COD_YEAR ? upHeadListModalYearCod : upHeadListModalYear}
pageSize={0} total={0} cellClick={undefined}
onPageChange={() => { }} className="h-[500px]" boldArray={[0, 1, 2]}
>
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
</UiTable>
</div>
<UnderComment commentArray={commentArrayRain} divHeight="10"/>
<UnderComment commentArray={commentArrayRain} divHeight="10" />
</TabsContent>
</UITab>
</TabsContent>
@@ -593,81 +550,57 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
{/* 총인설비 수질현황 */}
<TabsContent value="tab_num2" >
<UITab tabList={tabList3} defaultValue="tab_term_year_chongin">
<TabsContent value="tab_term_year_chongin">
<TabsContent value="tab_term_year_chongin">{/* 연간 */}
<FacilityTermModalHeader<FacilityWaterQltyProps>
searchList={chongInWaterQltyYearList}
fcltyCd={facilityCd}
fcltyName={fcltyName}
tabName="tab_term_year"
searchYear={searchYear}
ref={ref}
queryClick={filterData}
fcltyCd={facilityCd} fcltyName={fcltyName} tabName="tab_term_year"
searchYear={searchYear} ref={ref} queryClick={filterData}
/>
<div className="overflow-y-auto h-[550px]">
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={upHeadListModalChongIn}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[500px]"
boldArray={[0,1,2]}
>
<HeadMakeColSpan upHeadList={upHeadListModalChongIn} layoutNum={5} />
</UiTable>
</div>
</TabsContent>
<TabsContent value="tab_term_summer_chongin">
<FacilityTermModalHeader<FacilityWaterQltyProps>
searchList={chongInWaterQltyYearList}
fcltyCd={facilityCd}
fcltyName={fcltyName}
tabName="tab_term_summer"
searchYear={searchYear}
ref={ref}
queryClick={filterData}
/>
<div className="overflow-y-auto h-[550px]">
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={upHeadListModalChongIn}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[500px]"
boldArray={[0,1,2]}
>
<HeadMakeColSpan upHeadList={upHeadListModalChongIn} layoutNum={5} />
</UiTable>
</div>
</TabsContent>
<TabsContent value="tab_term_winter_chongin">
<FacilityTermModalHeader<FacilityWaterQltyProps>
searchList={chongInWaterQltyYearList}
fcltyCd={facilityCd}
fcltyName={fcltyName}
tabName="tab_term_winter"
searchYear={searchYear}
ref={ref}
queryClick={filterData}
/>
<div className="overflow-y-auto h-[550px]">
<UiTable
headName={undefined}
tableData={copyYearList}
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={upHeadListModalChongIn}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[500px]"
boldArray={[0,1,2]}
pageSize={0} total={0} cellClick={undefined}
onPageChange={() => { }} className="h-[500px]" boldArray={[0, 1, 2]}
>
<HeadMakeColSpan upHeadList={upHeadListModalChongIn} layoutNum={5} />
</UiTable>
</div>
</TabsContent>
<TabsContent value="tab_term_summer_chongin">{/* 하절기 */}
<FacilityTermModalHeader<FacilityWaterQltyProps>
searchList={chongInWaterQltyYearList}
fcltyCd={facilityCd} fcltyName={fcltyName} tabName="tab_term_summer"
searchYear={searchYear} ref={ref} queryClick={filterData}
/>
<div className="overflow-y-auto h-[550px]">
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={upHeadListModalChongIn}
pageSize={0} total={0} cellClick={undefined}
onPageChange={() => { }} className="h-[500px]" boldArray={[0, 1, 2]}
>
<HeadMakeColSpan upHeadList={upHeadListModalChongIn} layoutNum={5} />
</UiTable>
</div>
</TabsContent>
<TabsContent value="tab_term_winter_chongin">{/* 동절기 */}
<FacilityTermModalHeader<FacilityWaterQltyProps>
searchList={chongInWaterQltyYearList}
fcltyCd={facilityCd} fcltyName={fcltyName} tabName="tab_term_winter"
searchYear={searchYear} ref={ref} queryClick={filterData}
/>
<div className="overflow-y-auto h-[550px]">
<UiTable
headName={undefined}
tableData={copyYearList}
headlist={upHeadListModalChongIn}
pageSize={0} total={0} cellClick={undefined}
onPageChange={() => { }} className="h-[500px]" boldArray={[0, 1, 2]}
>
<HeadMakeColSpan upHeadList={upHeadListModalChongIn} layoutNum={5} />
</UiTable>
@@ -678,4 +611,4 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
</UITab>
</>
);
}
}
@@ -6,13 +6,13 @@
"use client"
import { useFoStore } from "@/app/store";
import { StoreContext, useFoStore } from "@/app/store";
import type { TableUpperProps } from "@/app/store/common";
import type { FacilityWaterQltyProps } from "@/app/store/facilityWaterQlty";
import { ContentsDiv, downloadExcelFormat, 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 { useCallback, useContext, useEffect, useRef, useState } from "react";
import WaterQualityModal from "./modal/page";
export default function ProcessFacilitySearch() {
@@ -21,9 +21,14 @@ export default function ProcessFacilitySearch() {
, initializeCommonData
, searchFacilityWaterQltyList
} = useFoStore((state) => state) || { FacilityWaterQltyList: { facilityWaterQltyList: [], facilityWaterQltyCount: 0 } };
const store = useContext(StoreContext);
if (!store) {
throw new Error("StoreContext is not available. Ensure StoreProvider is mounted.");
}
const {
isInit,
isInit,
selectUpdownData,
selectOperationData,
selectSidoData,
@@ -36,6 +41,11 @@ export default function ProcessFacilitySearch() {
btnClass
} = Common;
const defaultSearchYear =
selectSearchYear.find((item) => item.selected)?.val ||
selectSearchYear[0]?.val ||
"0";
const {
mainLabelArray,
upHeadList1,
@@ -43,13 +53,13 @@ export default function ProcessFacilitySearch() {
upHeadList3,
facilityWaterQltyList,
facilityWaterQltyCount,
excelList,
isLoading,
} = FacilityWaterQltyMain;
const mainList: FacilityWaterQltyProps[] = facilityWaterQltyList || [];
const [initTrigger, setInitTrigger] = useState<boolean>(false);
const [excelTrigger, setExcelTrigger] = useState<boolean>(false);
// 엑셀다운로드 트리거
const [isExcelDownClick, setIsExcelDownClick] = useState<boolean>(false);
// 그리드 관련
const [resetPage, setResetPage] = useState<boolean>(false);
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
@@ -57,7 +67,7 @@ export default function ProcessFacilitySearch() {
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
const [fcltyName, setFcltyName] = useState<string>("");
const [operationValue, setOperationValue] = useState<string>("0");
const [searchYearValue, setSearchYearValue] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYearValue, setSearchYearValue] = useState<string>(defaultSearchYear);
const [fcltCpct, setFcltCpct] = useState<string>("0");
// 모달 상태 추가
@@ -66,27 +76,27 @@ export default function ProcessFacilitySearch() {
const [fcltyCd, setFcltyCd] = useState<string>("");
const [modalYear, setModalYear] = useState<string>("");
const searchFcltyQltyList = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
const searchFcltyQltyList = useCallback(async ({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt: number = 20) => {
let nameCd, partStr;
switch (partValue) {
case 'R':
if (regionValue !== '0') {
if(unitWaterShedValue==='0') nameCd = regionValue;
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
if (unitWaterShedValue === '0') nameCd = regionValue;
else if (middleRegionValue === '0') nameCd = unitWaterShedValue;
else nameCd = middleRegionValue;
}
partStr = partValue
break;
default:
if(sidoValue !== '0') nameCd = ref.current.sidoValue!="0"?ref.current.sidoValue:sidoValue;
if(sigunValue !== '0') nameCd = sigunValue;
partStr = envPartValue !== '0' ? envPartValue:partValue;
break;
if (sidoValue !== '0') nameCd = ref.current.sidoValue != "0" ? ref.current.sidoValue : sidoValue;
if (sigunValue !== '0') nameCd = sigunValue;
partStr = envPartValue !== '0' ? envPartValue : partValue;
break;
}
if(partStr ==='G'){
searchFacilityWaterQltyList(pageNo, pageCnt, searchYearValue);
}else{
searchFacilityWaterQltyList(pageNo, pageCnt, searchYearValue, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
if (partStr === 'G') {
await searchFacilityWaterQltyList(pageNo, pageCnt, searchYearValue);
} else {
await searchFacilityWaterQltyList(pageNo, pageCnt, searchYearValue, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
}
}, [operationValue, fcltyName, searchFacilityWaterQltyList, searchYearValue, fcltCpct]);
@@ -96,7 +106,7 @@ export default function ProcessFacilitySearch() {
// 상태값 설정
setFcltCpct(selectUpdownData[0]?.val || "0");
setOperationValue(selectOperationData[0]?.val || "0");
setSearchYearValue(selectSearchYear[0]?.val || "0");
setSearchYearValue(defaultSearchYear);
// SearchInputSelect 초기화
setFcltyName("");
if (searchInputRef.current) {
@@ -138,42 +148,60 @@ export default function ProcessFacilitySearch() {
useEffect(() => {
if (!isInit) {
if(!initTrigger){
if (!initTrigger) {
initializeCommonData();
searchFcltyQltyList(ref.current, 1, 10);
setInitTrigger(true);
setInitTrigger(true);
}
}
}, [isInit, initializeCommonData, searchFacilityWaterQltyList, searchFcltyQltyList, initTrigger]);
useEffect(() => {
if(!excelTrigger) return;
if (excelList && excelList.length > 0) {
downloadExcelFormat(
{
data: excelList as unknown as JSON[],
fileName: '시설별 수질현황',
sheetNameArray: ['시설별 수질현황'],
headerRange: 'A1:T1',
decimalArray1:[10,11,12,15,16,17],
decimalArray3:[13,14,18,19]
}
);
}
}, [excelList, excelTrigger]);
const chkVal = useCallback((returntype:ReturnType) => {
const chkVal = useCallback((returntype: ReturnType) => {
// setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G' ? upHeadList3 : upHeadList1);
setResetPage(true);
}, [upHeadList1, upHeadList2, upHeadList3]);
const excelDownload = useCallback(() => {
setExcelTrigger(true);
searchFcltyQltyList(ref.current, 1, 10000);
}, [searchFcltyQltyList]);
const excelDownload = useCallback(async () => {
if (isExcelDownClick) 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;
}
}
setIsExcelDownClick(true);
try {
await searchFcltyQltyList(ref.current, 1, 10000);
const latestExcelList = store.getState().FacilityWaterQltyMain.excelList || [];
if (latestExcelList.length > 0) {
downloadExcelFormat(
{
data: latestExcelList as unknown as JSON[],
fileName: '시설별 수질현황',
sheetNameArray: ['시설별 수질현황'],
headerRange: 'A1:T1',
decimalArray0: [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
}
);
} else {
alert("조회된 결과가 없습니다.");
}
} finally {
setIsExcelDownClick(false);
}
}, [isExcelDownClick, searchFcltyQltyList, store]);
const handlePageChange = useCallback((page: number) => {
setResetPage(false);
searchFcltyQltyList(ref.current, page, 10);
@@ -201,8 +229,9 @@ export default function ProcessFacilitySearch() {
btnClass={btnClass}
queryClick={chkVal}
excelClick={excelDownload}
excelDisabled={isExcelDownClick}
initClick={resetVal}
ref={ref} isAdmin={false} initSidoValue={"11"}/>
ref={ref} isAdmin={false} initSidoValue={"11"} />
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<div className="h-full w-full overflow-x-scroll min-[1200px]:overflow-x-hidden">
@@ -215,7 +244,7 @@ export default function ProcessFacilitySearch() {
{selectedRow !== null && (
<UiModal
body={<WaterQualityModal fcltyName={fcltyNm} facilityCd={fcltyCd} searchYear={modalYear}></WaterQualityModal>}
bodyClass="sm:max-w-[90vw] w-[1300px] h-[920px]"
bodyClass="sm:max-w-[90vw] w-[1300px] h-[100dvh] max-h-[930px] overflow-y-auto"
open={selectedRow !== null}
onOpenChange={(open) => !open && closeModal()}
noHeaderYn="Y"
@@ -224,4 +253,4 @@ export default function ProcessFacilitySearch() {
)}
</MainDiv>
);
}
}
@@ -8,7 +8,8 @@
import FacilityTermModalHeader from "@/app/components/common/FacilityTermModalHeader";
import { useFoStore } from "@/app/store";
import type { FlowRateModalInterface, modalExcelType } from "@/app/store/flowRate";
import { downloadExcel, UITab, UiTable } from "@common/business_components/ui";
import { dataFormSetting } from "@/app/store/flowRate";
import { downloadExcelFormat, UITab, UiTable } from "@common/business_components/ui";
import { Button, TabsContent } from "@common/components/ui";
import { useCallback, useEffect, useRef, useState } from "react";
import type { ReturnType } from "../../../../components/common/FacilityTermModalHeader";
@@ -33,12 +34,10 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
const { btnClass } = Common;
const [copyYearList, setCopyYearList] = useState<FlowRateModalInterface[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [activeTab, setActiveTab] = useState<string>("tab_term_year");
const prevExcelListRef = useRef<modalExcelType[] | null>(null);
const {
modalFlowRateListYear,
upHeadListFlowRateModalYear,
} = FlowRateModal;
const { modalFlowRateListYear, upHeadListFlowRateModalYear, } = FlowRateModal;
const ref = useRef<ReturnType<FlowRateModalInterface>>({
startDate: new Date(),
endDate: new Date(),
@@ -52,11 +51,11 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
const filteredData = setFilterAfterData(returnType.filteredList as FlowRateModalInterface[]);
setCopyYearList(filteredData);
}, []);
// 필터링 된 후 최대, 최소, 평균 값 계산
const setFilterAfterData = (filteredData: FlowRateModalInterface[]) => {
if (!filteredData || filteredData.length === 0) return [];
// 쉼표가 포함된 문자열을 숫자로 변환하는 함수
const parseNumber = (value: string | number | null | undefined): number => {
if (value === null || value === undefined || value === '') return 0;
@@ -79,7 +78,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
let minreturnAmnt = parseNumber(filteredData[0]?.returnAmnt);
let minefflAmnt = parseNumber(filteredData[0]?.efflAmnt);
let mininfoRnDay = parseNumber(filteredData[0]?.infoRnDay && filteredData[0]?.infoRnDay.toString().trim() !== 'x' ? filteredData[0]?.infoRnDay.toString().trim() : 0);
let minNoProcessInflAmnt = 99999999;
let minNoProcessInflAmnt = 99999999; // 미처리하수 추정량
let avgtotInflAmnt = 0;
let avginflAmnt = 0;
@@ -89,7 +88,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
let avginfoRnDay = 0;
let avgNoProcessInflAmnt = 0;
let noProcessInflAmntCnt = 0;
filteredData.forEach((item: FlowRateModalInterface) => {
const totInflAmnt = parseNumber(item.totInflAmnt);
const inflAmnt = parseNumber(item.inflAmnt);
@@ -119,24 +118,30 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
avgefflAmnt += efflAmnt;
avginfoRnDay += infoRnDay;
if(item.noProcessInflAmnt && item.noProcessInflAmnt.toString().trim() != '' && item.noProcessInflAmnt != undefined){
const noProcessInflAmnt = Number(item.noProcessInflAmnt.toString().replaceAll(',',''));
if (item.noProcessInflAmnt && item.noProcessInflAmnt.toString().trim() != '' && item.noProcessInflAmnt != undefined) {
const noProcessInflAmnt = Number(item.noProcessInflAmnt.toString().replaceAll(',', ''));
avgNoProcessInflAmnt += noProcessInflAmnt;
maxNoProcessInflAmnt = Math.max(maxNoProcessInflAmnt, noProcessInflAmnt);
minNoProcessInflAmnt = Math.min(minNoProcessInflAmnt, noProcessInflAmnt);
noProcessInflAmntCnt +=1;
noProcessInflAmntCnt += 1;
}
});
const formattedData = filteredData.map((item: FlowRateModalInterface) => {
const newItem = { ...item };
dataFormSetting(newItem);
return newItem;
});
const newFilteredData = [
{
msrDt: '평균',
totInflAmnt: avgtotInflAmnt && avgtotInflAmnt!=0 ? roundUp((avgtotInflAmnt / filteredData.length), 0) : 0,
inflAmnt: avginflAmnt && avginflAmnt!=0 ? roundUp((avginflAmnt / filteredData.length), 0) : 0,
sumFlow: avgsumFlow && avgsumFlow!=0 ? roundUp((avgsumFlow / filteredData.length), 0) : 0,
returnAmnt: avgreturnAmnt && avgreturnAmnt!=0 ? roundUp((avgreturnAmnt / filteredData.length), 0) : 0,
efflAmnt: avgefflAmnt && avgefflAmnt!=0 ? roundUp((avgefflAmnt / filteredData.length), 0) : 0,
noProcessInflAmnt : roundNumber(avgNoProcessInflAmnt / noProcessInflAmntCnt, 0),
totInflAmnt: avgtotInflAmnt && avgtotInflAmnt != 0 ? roundUp((avgtotInflAmnt / filteredData.length), 0) : 0,
inflAmnt: avginflAmnt && avginflAmnt != 0 ? roundUp((avginflAmnt / filteredData.length), 0) : 0,
sumFlow: avgsumFlow && avgsumFlow != 0 ? roundUp((avgsumFlow / filteredData.length), 0) : 0,
returnAmnt: avgreturnAmnt && avgreturnAmnt != 0 ? roundUp((avgreturnAmnt / filteredData.length), 0) : 0,
efflAmnt: avgefflAmnt && avgefflAmnt != 0 ? roundUp((avgefflAmnt / filteredData.length), 0) : 0,
noProcessInflAmnt: roundNumber(avgNoProcessInflAmnt / noProcessInflAmntCnt, 0),
infoRnDay: avginfoRnDay > 0 ? roundUp((avginfoRnDay / filteredData.length), 1) : '0.0',
rainEffectDay: 0,
},
@@ -147,7 +152,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
sumFlow: roundUp(maxsumFlow, 0),
returnAmnt: roundUp(maxreturnAmnt, 0),
efflAmnt: roundUp(maxefflAmnt, 0),
noProcessInflAmnt : roundNumber(maxNoProcessInflAmnt, 0),
noProcessInflAmnt: roundNumber(maxNoProcessInflAmnt, 0),
infoRnDay: maxinfoRnDay > 0 ? roundUp(maxinfoRnDay, 1) : '0.0',
rainEffectDay: 0,
},
@@ -158,11 +163,11 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
sumFlow: roundUp(minsumFlow, 0),
returnAmnt: roundUp(minreturnAmnt, 0),
efflAmnt: roundUp(minefflAmnt, 0),
noProcessInflAmnt : roundNumber(minNoProcessInflAmnt, 0),
noProcessInflAmnt: roundNumber(minNoProcessInflAmnt, 0),
infoRnDay: mininfoRnDay > 0 ? roundUp(mininfoRnDay, 1) : '0.0',
rainEffectDay: 0,
},
...filteredData
...formattedData
];
return newFilteredData;
}
@@ -179,13 +184,9 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
fetchData();
}, [props.facilityCd, props.searchYear, searchFlowRateModalList]);
if (isLoading) {
return <div>로딩 중...</div>;
}
const excelDownload = () => {
const excelDownList: modalExcelType[] = [];
if(copyYearList.length > 0){
if (copyYearList.length > 0) {
copyYearList.forEach((item) => {
excelDownList.push({
"날짜": item.msrDt,
@@ -200,20 +201,58 @@ 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' });
downloadExcelFormat({
data: JSON.parse(JSON.stringify(excelDownList)),
fileName: props.searchYear + '년 ' + props.fcltyName + ' 유량현황',
sheetNameArray: [props.fcltyName + ' 유량현황'],
headerRange: 'A1:H1',
decimalArray0: [1, 2, 3, 4, 5, 6],
decimalArray1: [0],
});
} 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 <div>로딩 중...</div>;
}
return (
<>
<UITab tabList={tabList} defaultValue="tab_term_year">
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownload}>
<UITab tabList={tabList} defaultValue="tab_term_year" onValueChange={setActiveTab}>
<Button className={btnClass} style={{ float: 'right' }} color="green" onClick={excelDownload}>
{"엑셀다운로드"}
</Button>
<TabsContent value="tab_term_year">
<TabsContent value="tab_term_year"> {/* 연간 */}
<FacilityTermModalHeader<FlowRateModalInterface>
searchList={modalFlowRateListYear}
fcltyCd={props.facilityCd}
@@ -224,23 +263,23 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
queryClick={filterData}
/>
<div className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[370px]"
boldArray={[0,1,2]}
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => { }}
className="h-[370px]"
boldArray={[0, 1, 2]}
/>
</div>
<div className="mt-20">
<UnderComment commentArray={[commentArray]} />
</div>
</TabsContent>
<TabsContent value="tab_term_summer">
<TabsContent value="tab_term_summer"> {/* 하절기 */}
<FacilityTermModalHeader<FlowRateModalInterface>
searchList={modalFlowRateListYear}
fcltyCd={props.facilityCd}
@@ -251,23 +290,23 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
queryClick={filterData}
/>
<div className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[370px]"
boldArray={[0,1,2]}
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => { }}
className="h-[370px]"
boldArray={[0, 1, 2]}
/>
</div>
<div className="mt-20">
<UnderComment commentArray={[commentArray]} />
</div>
</TabsContent>
<TabsContent value="tab_term_winter">
<TabsContent value="tab_term_winter"> {/* 동절기 */}
<FacilityTermModalHeader<FlowRateModalInterface>
searchList={modalFlowRateListYear}
fcltyCd={props.facilityCd}
@@ -278,23 +317,23 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
queryClick={filterData}
/>
<div className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[370px]"
boldArray={[0,1,2]}
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => { }}
className="h-[370px]"
boldArray={[0, 1, 2]}
/>
</div>
<div className="mt-20">
<UnderComment commentArray={[commentArray]} />
</div>
</TabsContent>
<TabsContent value="tab_term_chuncheon">
<TabsContent value="tab_term_chuncheon"> {/* 청천시 */}
<FacilityTermModalHeader<FlowRateModalInterface>
searchList={modalFlowRateListYear}
fcltyCd={props.facilityCd}
@@ -305,23 +344,23 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
queryClick={filterData}
/>
<div className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[370px]"
boldArray={[0,1,2]}
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => { }}
className="h-[370px]"
boldArray={[0, 1, 2]}
/>
</div>
<div className="mt-20">
<UnderComment commentArray={[commentArray]} />
</div>
</TabsContent>
<TabsContent value="tab_term_rain">
<TabsContent value="tab_term_rain"> {/* 강우시 */}
<FacilityTermModalHeader<FlowRateModalInterface>
searchList={modalFlowRateListYear}
fcltyCd={props.facilityCd}
@@ -332,13 +371,15 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
queryClick={filterData}
/>
<div className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable headName="유량현황" tableData={copyYearList} headlist={upHeadListFlowRateModalYear} pageSize={0} total={0} cellClick={undefined} onPageChange={() => {}} className="h-[370px]" boldArray={[0,1,2]}/>
<UiTable headName="유량현황" tableData={copyYearList} headlist={upHeadListFlowRateModalYear} pageSize={0} total={0}
cellClick={undefined} onPageChange={() => { }} className="h-[370px]" boldArray={[0, 1, 2]}
rowClassName={rainRowClassName} />
</div>
<div className="mt-20">
<UnderComment commentArray={["미처리하수 추정량 산식 =[(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]/강우시 일별유입BOD)","강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날"]} />
<UnderComment commentArray={["미처리하수 추정량 산식 =[(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]/강우시 일별유입BOD)", "강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날"]} />
</div>
</TabsContent>
</UITab>
</>
);
}
}
@@ -5,13 +5,13 @@
*/
"use client"
import { useFoStore } from "@/app/store";
import { StoreContext, useFoStore } from "@/app/store";
import type { TableUpperProps } from "@/app/store/common";
import type { ExcelType } from "@/app/store/flowRate";
// import type { ExcelType } from "@/app/store/flowRate";
import { ContentsDiv, downloadExcelFormat, 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 { useCallback, useContext, useEffect, useRef, useState } from "react";
import FlowRateModal from "./modal/page";
export default function ProcessFacilitySearch() {
@@ -21,6 +21,11 @@ export default function ProcessFacilitySearch() {
,initializeCommonData
,searchFlowRateList
} = useFoStore((state) => state);
const store = useContext(StoreContext);
if (!store) {
throw new Error("StoreContext is not available. Ensure StoreProvider is mounted.");
}
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
@@ -38,6 +43,11 @@ export default function ProcessFacilitySearch() {
btnClass
} = Common;
const defaultSearchYear =
selectSearchYear.find((item) => item.selected)?.val ||
selectSearchYear[0]?.val ||
"0";
const {
flowRateSearchLabelArray
} = FlowRateSearch;
@@ -49,7 +59,6 @@ export default function ProcessFacilitySearch() {
upHeadList3,
flowRateList,
flowRateCount,
excelList,
isLoading,
} = FlowRateList;
@@ -57,20 +66,20 @@ export default function ProcessFacilitySearch() {
const [fcltCpct, setFcltCpct] = useState<string>("0");
const [fcltyName, setFcltyName] = useState<string>("");
const [operationValue, setOperationValue] = useState<string>("0");
const [searchYearValue, setSearchYearValue] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYearValue, setSearchYearValue] = useState<string>(defaultSearchYear);
// const [widthSize, setWidthSize] = useState<string>("w-[120%]");
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
const [resetPage, setResetPage] = useState<boolean>(false);
const prevExcelListRef = useRef<ExcelType[] | null>(null);
// const prevExcelListRef = useRef<ExcelType[] | null>(null);
// 모달 상태 추가
const [selectedRow, setSelectedRow] = useState<number | null>(null);
const [fcltyNm, setFcltyNm] = useState<string>("");
const [fcltyCd, setFcltyCd] = useState<string>("");
const [excelTrigger, setExcelTrigger] = useState<boolean>(false);
const [isExcelDownClick, setIsExcelDownClick] = useState<boolean>(false);
const [initTrigger, setInitTrigger] = useState<boolean>(false);
const searchFlowRate = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
const searchFlowRate = useCallback(async ({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
let nameCd, partStr;
switch (partValue) {
@@ -89,9 +98,9 @@ export default function ProcessFacilitySearch() {
break;
}
if(partStr==='G'){
searchFlowRateList(pageNo, pageCnt, searchYearValue);
await searchFlowRateList(pageNo, pageCnt, searchYearValue);
}else{
searchFlowRateList(pageNo, pageCnt, searchYearValue, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
await searchFlowRateList(pageNo, pageCnt, searchYearValue, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
}
}, [searchFlowRateList, searchYearValue, fcltCpct, operationValue, fcltyName]);
@@ -99,7 +108,7 @@ export default function ProcessFacilitySearch() {
// setWidthSize("w-[120%]");
setUpheadList(upHeadList1)
// 상태값 설정
setSearchYearValue(selectSearchYear[0]?.val || "0");
setSearchYearValue(defaultSearchYear);
setFcltCpct(selectUpdownData[0]?.val || "0");
setOperationValue(selectOperationData[0]?.val || "0");
// SearchInputSelect 초기화
@@ -146,17 +155,6 @@ export default function ProcessFacilitySearch() {
}
}, [isInit, initializeCommonData, searchFlowRateList, selectSearchYear, searchFlowRate, initTrigger]);
useEffect(() => {
if(!excelTrigger) 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 if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
alert('다운받을 데이터가 없습니다.');
}
prevExcelListRef.current = excelList;
}, [excelList, excelTrigger]);
const ref = useRef<ReturnType>({
partValue: '',
sidoValue: '11',
@@ -175,10 +173,37 @@ export default function ProcessFacilitySearch() {
setResetPage(true);
}, [upHeadList1, upHeadList2, upHeadList3]);
const excelDownload = useCallback(() => {
searchFlowRate(ref.current, 1, 10000);
setExcelTrigger(true);
}, [searchFlowRate]);
const excelDownload = useCallback(async () => {
if (isExcelDownClick) 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;
}
}
setIsExcelDownClick(true);
try {
await searchFlowRate(ref.current, 1, 10000);
const latestExcelList = store.getState().FlowRateList.excelList || [];
if (latestExcelList.length > 0) {
downloadExcelFormat({ data: JSON.parse(JSON.stringify(latestExcelList)), fileName: '시설별 유량현황', sheetNameArray: ['시설별 유량현황'], headerRange: 'A1:O1', decimalArray0: [9,10,11,12,13,14] });
} else {
alert('조회된 결과가 없습니다.');
}
} finally {
setIsExcelDownClick(false);
}
}, [isExcelDownClick, searchFlowRate, store]);
const total = flowRateCount;
return (
@@ -203,6 +228,7 @@ export default function ProcessFacilitySearch() {
queryClick={chkVal}
excelClick={excelDownload}
initClick={resetVal}
excelDisabled={isExcelDownClick}
ref={ref} isAdmin={false} initSidoValue={'11'}/>
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
@@ -216,7 +242,7 @@ export default function ProcessFacilitySearch() {
{selectedRow !== null && (
<UiModal
body={<FlowRateModal fcltyName={fcltyNm} facilityCd={fcltyCd} searchYear={searchYearValue}></FlowRateModal>}
bodyClass="sm:max-w-[90vw] w-[1250px] h-[780px]"
bodyClass="sm:max-w-[90vw] w-[1250px] h-[100dvh] max-h-[780px]"
open={selectedRow !== null}
onOpenChange={(open: boolean) => !open && closeModal()}
/>
@@ -5,11 +5,11 @@
*/
"use client"
import { useFoStore } from "@/app/store";
import { StoreContext, useFoStore } from "@/app/store";
import type { TableUpperProps } from "@/app/store/common";
import { downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiTable, type ReturnType } from "@common/business_components";
import { downloadExcelFormat, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiTable, type ReturnType } from "@common/business_components";
import ListDiv from "@common/business_components/ui/list_div";
import { useCallback, useEffect, useRef, useState } from "react";
import { useCallback, useContext, useEffect, useRef, useState } from "react";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
import UnderComment from "@/app/components/common/UnderComment";
@@ -20,13 +20,18 @@ const commentArray = [
]
export default function PlanSewage() {
const {Common
,PlanSewage
,PlanSewageSearch
,initializeCommonData
,searchPlanSewageList
} = useFoStore((state) => state) || { processAreaList: { processAreaList: [] }};
const { Common
, PlanSewage
, PlanSewageSearch
, initializeCommonData
, searchPlanSewageList
} = useFoStore((state) => state) || { processAreaList: { processAreaList: [] } };
const store = useContext(StoreContext);
if (!store) {
throw new Error("StoreContext is not available. Ensure StoreProvider is mounted.");
}
const {
isInit,
selectUpdownData,
@@ -41,8 +46,13 @@ export default function PlanSewage() {
btnClass
} = Common;
const defaultSearchYear =
selectSearchYear.find((item) => item.selected)?.val ||
selectSearchYear[0]?.val ||
"0";
const {
labelArray,
labelArray,
} = PlanSewageSearch;
const {
@@ -51,7 +61,6 @@ export default function PlanSewage() {
upHeadList3,
planSewageList,
planSewageCount,
excelList,
isLoading,
} = PlanSewage;
@@ -69,9 +78,9 @@ export default function PlanSewage() {
// 그리드 관련
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
// 모달 상태 추가
// 초기화 변수
const [resetPage, setResetPage] = useState<boolean>(false);
// 표 너비
@@ -85,11 +94,12 @@ export default function PlanSewage() {
// 시설상태
const [operationValue, setOperationValue] = useState<string>("0");
// 조회기간
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYear, setSearchYear] = useState<string>(defaultSearchYear);
const [initTrigger, setInitTrigger] = useState<boolean>(false);
// 엑셀다운로드 트리거
const [isExcelDownClick, setIsExcelDownClick] = useState<boolean>(false);
const [excelTrigger, setExcelTrigger] = useState<boolean>(false);
/**
* 페이지 함수
*/
@@ -100,7 +110,7 @@ export default function PlanSewage() {
// 상태값 설정
setFcltCpct(selectUpdownData[0]?.val || "0");
setOperationValue(selectOperationData[0]?.val || "0");
setSearchYear(selectSearchYear[0]?.val || "0");
setSearchYear(defaultSearchYear);
// SearchInputSelect 초기화
setFcltyName("");
if (searchInputRef.current) {
@@ -109,52 +119,39 @@ export default function PlanSewage() {
input.value = "";
}
}
ref.current.sidoValue='11';
ref.current.sidoValue = '11';
searchPlanSewage(ref.current, 1, 10);
}
useEffect(() => {
if(!excelTrigger) return;
if (excelList && excelList.length > 0) {
downloadExcel({
data: excelList as unknown as JSON[],
fileName: '계획하수량 산정지표 현황',
sheetNameArray: ['계획하수량 산정지표 현황'],
headerRange: 'A1:M1'
});
}
}, [excelList, excelTrigger]);
/**
* 콜백함수
*/
// 조회
const searchPlanSewage = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
const searchPlanSewage = useCallback(async ({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt: number = 20) => {
let nameCd, partStr
switch (partValue) {
case 'R':
if (regionValue !== '0') {
if(unitWaterShedValue==='0') nameCd = regionValue;
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
if (unitWaterShedValue === '0') nameCd = regionValue;
else if (middleRegionValue === '0') nameCd = unitWaterShedValue;
else nameCd = middleRegionValue;
}
partStr = partValue
break;
default:
if(sidoValue !== '0') nameCd = ref.current.sidoValue!="0"?ref.current.sidoValue:sidoValue;
if(sigunValue !== '0') nameCd = sigunValue;
partStr = envPartValue !== '0' ? envPartValue:partValue;
if (sidoValue !== '0') nameCd = ref.current.sidoValue != "0" ? ref.current.sidoValue : sidoValue;
if (sigunValue !== '0') nameCd = sigunValue;
partStr = envPartValue !== '0' ? envPartValue : partValue;
break;
}
if(partStr === 'G'){
partValue = partValue==='G'?'A':partValue;
searchPlanSewageList(pageNo, pageCnt, searchYear, partValue);
if (partStr === 'G') {
partValue = partValue === 'G' ? 'A' : partValue;
await searchPlanSewageList(pageNo, pageCnt, searchYear, partValue);
}
else {
await searchPlanSewageList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
}
else{
searchPlanSewageList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
}
}, [operationValue, fcltyName, searchPlanSewageList, searchYear, fcltCpct]);
/**
@@ -162,25 +159,81 @@ export default function PlanSewage() {
*/
useEffect(() => {
if (!isInit) {
if(!initTrigger){
if (!initTrigger) {
initializeCommonData();
searchPlanSewage(ref.current, 1, 10);
setInitTrigger(true);
}
}
}, [isInit, initializeCommonData, searchPlanSewageList, selectSearchYear, initTrigger, searchPlanSewage]);
}, [isInit, initializeCommonData, initTrigger, searchPlanSewage]);
const chkVal = useCallback((returntype:ReturnType) => {
const chkVal = useCallback((returntype: ReturnType) => {
// setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G' ? upHeadList3 : upHeadList1);
setResetPage(true);
}, [upHeadList1, upHeadList2, upHeadList3]);
// 엑셀다운로드
const excelDownload = useCallback((searchReturn: ReturnType) => {
searchPlanSewage(searchReturn, 1, 10000);
setExcelTrigger(true);
}, [searchPlanSewage]);
const excelDownload = useCallback(async (searchReturn: ReturnType) => {
if (isExcelDownClick) 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;
}
}
setIsExcelDownClick(true);
try {
await searchPlanSewage(searchReturn, 1, 10000);
const latestExcelList = store.getState().PlanSewage.excelList || [];
if (latestExcelList.length > 0) {
const toNumber = (value: unknown) => {
if (value === null || value === undefined || value === '') return '';
const parsed = typeof value === "number" ? value : Number(String(value).replace(/,/g, ""));
return Number.isFinite(parsed) ? parsed : '';
};
const numericKeys = [
"시설용량(m³/일)",
"여유용량(m³/일)",
"변동부하율(%)",
"분류식화율(%)",
];
const excelData = latestExcelList.map((row) => {
const nextRow = { ...row } as Record<string, unknown>;
numericKeys.forEach((key) => {
if (key in nextRow) {
nextRow[key] = toNumber(nextRow[key]);
}
});
return nextRow;
});
downloadExcelFormat({
data: excelData as unknown as JSON[],
fileName: '계획하수량 산정지표 현황',
sheetNameArray: ['계획하수량 산정지표 현황'],
headerRange: 'A1:M1',
decimalArray0: [9, 10, 11, 12]
});
} else {
alert("조회된 결과가 없습니다.");
}
} finally {
setIsExcelDownClick(false);
}
}, [isExcelDownClick, searchPlanSewage, store]);
// 페이지 변경
const handlePageChange = useCallback((page: number) => {
@@ -190,11 +243,11 @@ export default function PlanSewage() {
const mainList = planSewageList || [];
const total = planSewageCount || 0;
return (
<MainDiv>
<Title title="계획하수량 산정지표 현황" />
<SearchBaseForm
<SearchBaseForm
leftChildren={<>
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
<SearchInput className={"col-span-3"} label={labelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
@@ -211,17 +264,18 @@ export default function PlanSewage() {
btnClass={btnClass}
queryClick={chkVal}
excelClick={excelDownload}
excelDisabled={isExcelDownClick}
initClick={resetVal}
ref={ref} isAdmin={false} initSidoValue={"11"}/>
ref={ref} isAdmin={false} initSidoValue={"11"} />
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<div className="h-full w-full overflow-x-scroll min-[1200px]:overflow-x-hidden">
<div className="w-[120%] min-[1200px]:w-[100%]">
<UiTable cellClick={ undefined } headName={"계획하수량 산정지표 현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
<div className="w-[120%] min-[1200px]:w-[100%]">
<UiTable cellClick={undefined} headName={"계획하수량 산정지표 현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
</div>
<UnderComment divHeight={"5"} commentArray={commentArray} />
</div>
</ListDiv>
</MainDiv>
);
}
}
@@ -5,27 +5,36 @@
*/
"use client"
import { useFoStore } from "@/app/store";
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
import { StoreContext, useFoStore } from "@/app/store";
import { useShallow } from 'zustand/react/shallow';
import { ContentsDiv, downloadExcelFormat, MainDiv, SearchBaseForm, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
import ListDiv from "@common/business_components/ui/list_div";
import { useCallback, useEffect, useRef, useState } from "react";
import { useCallback, useContext, useEffect, useRef, useState } from "react";
import ProcessFacilityInfoModal from "./modal/page";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
export default function ProcessArea() {
const {Common,
const {
Common,
ProcessArea,
ProcessAreaSearch,
initializeCommonData,
searchProcessAreaList
} = useFoStore((state) => state) || {
Common: { isInit: false, selectSidoData: [], selectSigunData: [], selectRegionData: [], selectUnitWaterShedData: [], selectMiddleRegionData: [], selectEnvPartData: [], selectSearchYear: [{ val: "0" }], btnClass: "" },
ProcessArea: { processAreaList: [], processAreaCount: 0, excelList: [], upHeadList1: [] },
ProcessAreaSearch: { processFacilityLabelArray: [] },
initializeCommonData: () => {},
searchProcessAreaList: () => {}
};
} = useFoStore(
useShallow((state) => ({ // 다른 무관한 상태가 변경되어도 이 컴포넌트는 불필요하게 다시 렌더링 되지 않음.
Common: state.Common,
ProcessArea: state.ProcessArea,
ProcessAreaSearch: state.ProcessAreaSearch,
initializeCommonData: state.initializeCommonData,
searchProcessAreaList: state.searchProcessAreaList,
}))
);
const store = useContext(StoreContext);
if (!store) {
throw new Error("StoreContext is not available. Ensure StoreProvider is mounted.");
}
const {
isInit,
selectSidoData,
@@ -37,7 +46,12 @@ export default function ProcessArea() {
selectSearchYear,
btnClass,
} = Common;
const defaultSearchYear =
selectSearchYear.find((item) => item.selected)?.val ||
selectSearchYear[0]?.val ||
"0";
const {
processFacilityLabelArray,
} = ProcessAreaSearch;
@@ -46,7 +60,6 @@ export default function ProcessArea() {
upHeadList1,
processAreaList,
processAreaCount,
excelList,
isLoading,
} = ProcessArea;
@@ -54,13 +67,15 @@ export default function ProcessArea() {
// 그리드 관련
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
// 모달 상태 추가
// 모달 상태 추가
const [selectedRow, setSelectedRow] = useState<number | null>(null);
const [fcltyNm, setFcltyNm] = useState<string>("");
const [fcltyCd, setFcltyCd] = useState<string>("");
const [resetPage, setResetPage] = useState<boolean>(false);
const [searchYearValue, setSearchYearValue] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYearValue, setSearchYearValue] = useState<string>(defaultSearchYear);
const [isExcelDownClick, setIsExcelDownClick] = useState<boolean>(false);
const ref = useRef<ReturnType>({
partValue: '',
@@ -74,8 +89,8 @@ export default function ProcessArea() {
sigunText: '',
});
const searchProcessArea = useCallback(({ sidoText, sigunText}: ReturnType, pageNo: number, pageCnt:number=20) => {
searchProcessAreaList(pageNo, pageCnt, sidoText, sigunText, searchYearValue);
const searchProcessArea = useCallback(async ({ sidoText, sigunText }: ReturnType, pageNo: number, pageCnt: number = 20) => {
await searchProcessAreaList(pageNo, pageCnt, sidoText, sigunText, searchYearValue);
}, [searchProcessAreaList, searchYearValue]);
// 조회
@@ -91,8 +106,8 @@ export default function ProcessArea() {
input.value = "";
}
}
setSearchYearValue(selectSearchYear[0]?.val || "0");
searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val || "0");
setSearchYearValue(defaultSearchYear);
searchProcessAreaList(1, 10, '', '', defaultSearchYear);
}
// 셀 클릭 시 모달 표시
@@ -112,24 +127,49 @@ export default function ProcessArea() {
useEffect(() => {
if (!isInit) {
initializeCommonData();
searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val || "0");
searchProcessAreaList(1, 10, '', '', defaultSearchYear);
}
}, [isInit, initializeCommonData, searchProcessAreaList]);
}, [isInit, initializeCommonData, searchProcessAreaList, defaultSearchYear]);
useEffect(() => {
if (excelList && excelList.length > 0) {
downloadExcel({
data: excelList as unknown as JSON[],
fileName: '처리구역정보',
sheetNameArray: ['처리구역정보'],
headerRange: 'A1:W1'
});
const excelDownload = useCallback(async () => {
if (isExcelDownClick) 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;
// }
// }
setIsExcelDownClick(true);
try {
await searchProcessArea(ref.current, 1, 10000);
const latestExcelList = store.getState().ProcessArea.excelList || [];
if (latestExcelList.length > 0) {
downloadExcelFormat({
data: latestExcelList as unknown as JSON[],
fileName: '처리구역정보',
sheetNameArray: ['처리구역정보'],
headerRange: 'A1:W1',
decimalArray0: [3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15],
decimalArray2: [16, 17, 18, 19, 20, 21],
});
} else {
alert('조회된 결과가 없습니다.');
}
} finally {
setIsExcelDownClick(false);
}
}, [excelList]);
const excelDownload = useCallback(() => {
searchProcessArea(ref.current, 1, 10000);
}, [searchProcessArea]);
}, [isExcelDownClick, searchProcessArea, store]);
const handlePageChange = useCallback((pageNo: number) => {
setResetPage(false);
@@ -143,7 +183,7 @@ export default function ProcessArea() {
<ContentsDiv>
<SearchBaseForm
leftChildren={<>
<SelectBox className="col-span-3" label={processFacilityLabelArray[6] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYearValue(val.toString())} value={searchYearValue} selectClass={undefined}/>
<SelectBox className="col-span-3" label={processFacilityLabelArray[6] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYearValue(val.toString())} value={searchYearValue} selectClass={undefined} />
</>}
rightChildren={undefined}
selectSidoData={selectSidoData}
@@ -155,6 +195,7 @@ export default function ProcessArea() {
btnClass={btnClass}
queryClick={chkVal}
excelClick={excelDownload}
excelDisabled={isExcelDownClick}
initClick={resetVal}
ref={ref}
isAdmin={true}
@@ -163,19 +204,20 @@ export default function ProcessArea() {
<LoadingOverlay isLoading={isLoading} />
<div className="h-full w-full overflow-x-scroll min-[1900px]:overflow-x-hidden">
<div className="w-[160%] min-[1900px]:w-[100%]">
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"처리구역정보"} tableData={mainList} headlist={upHeadList1} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"처리구역정보"} tableData={mainList}
headlist={upHeadList1} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
</div>
</div>
</ListDiv>
</ContentsDiv>
{selectedRow !== null && (
<UiModal
body={<ProcessFacilityInfoModal fcltyName={fcltyNm} facilityCd={fcltyCd}></ProcessFacilityInfoModal>}
bodyClass="sm:max-w-[90vw] w-[1200px] h-[900px]"
<UiModal
body={<ProcessFacilityInfoModal fcltyName={fcltyNm} facilityCd={fcltyCd}></ProcessFacilityInfoModal>}
bodyClass="sm:max-w-[90vw] w-[1200px] h-[100dvh] max-h-[900px] overflow-y-auto"
open={selectedRow !== null}
onOpenChange={(open: boolean) => !open && closeModal()}
/>
)}
</MainDiv>
);
}
}
@@ -5,6 +5,7 @@
*/
"use client"
import { useCallback, useRef } from "react";
import { useFoStore } from "@/app/store";
import type { TableUpperProps } from "@/app/store/dashboard";
import { downloadExcelFormat, filePickedBlobArray, UITab, UiTable } from "@common/business_components/ui";
@@ -121,6 +122,21 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
const upHeadListPlanInfoChange = headMakeList(upHeadListPlanInfo, 2);
const upHeadListFcltyHistInfoChange = headMakeList(upHeadListFcltyHistInfo, 3);
const upHeadListFcltyWaterQltyInfoChange = headMakeList(upHeadListFcltyWaterQltyInfo, 4);
const historyTopScrollRef = useRef<HTMLDivElement>(null);
const historyBottomScrollRef = useRef<HTMLDivElement>(null);
const syncLockRef = useRef(false);
const syncScroll = useCallback((source: HTMLDivElement | null, target: HTMLDivElement | null) => {
if (!source || !target || syncLockRef.current) return;
syncLockRef.current = true;
const nextTop = source.scrollTop;
if (target.scrollTop !== nextTop) {
target.scrollTop = nextTop;
}
requestAnimationFrame(() => {
syncLockRef.current = false;
});
}, []);
const excelDownloadPlan = () => {
const excelDownList: any[] = [];
@@ -137,11 +153,19 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
"시운전완료일": item.trlrnCmplDt,
"가동개시일": item.rnDt,
"시설용량(m³/일)": item.fctCpc&&item.fctCpc.toString().trim()!=''?Number(item.fctCpc.toString().replaceAll(',','')):'',
"공법구분": item.trtSrsHanNm,
"공법계열": item.trtMocHanNm,
"방법": item.trtFrfHanNm,
});
});
}
if (excelDownList && excelDownList.length > 0) {
downloadExcelFormat({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.fcltyName + ' 시설이력관리', sheetNameArray: [props.fcltyName + ' 시설이력관리'], headerRange: 'A1:I1' });
downloadExcelFormat({
data: JSON.parse(JSON.stringify(excelDownList)),
fileName: props.fcltyName + ' 시설이력관리',
sheetNameArray: [props.fcltyName + ' 시설이력관리'],
decimalArray0: [8],
headerRange: 'A1:L1' });
} else if (gridListFcltyHistInfo.length == 0) {
alert('다운받을 데이터가 없습니다.');
}
@@ -182,7 +206,7 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
const sheetParameter = [
{
data: excelData,
headerNum: 2,
headerNum: 3,
headerRange: 'A1:S2',
sheetName: '시설 수질정보',
startCol: 'A'
@@ -218,7 +242,7 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
<h3 className="text-2xl font-medium text-label">시설 기본정보</h3>
</div>
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
<Table>
<Table variant="secondary">
<thead>
<TableRow className="">
<TableHead className="w-1/6">{'시설명'}</TableHead>
@@ -262,7 +286,11 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
<TabsContent value="history_info">
<ListDiv>
<div className="h-[250px] w-full overflow-y-auto overflow-x-hidden">
<div
className="h-[250px] w-full overflow-y-auto overflow-x-hidden"
ref={historyTopScrollRef}
onScroll={() => syncScroll(historyTopScrollRef.current, historyBottomScrollRef.current)}
>
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownloadPlan}>
{"엑셀다운로드"}
</Button>
@@ -274,7 +302,11 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
</div>
</ListDiv>
<ListDiv>
<div className="h-[250px] w-full overflow-y-auto overflow-x-hidden">
<div
className="h-[250px] w-full overflow-y-auto overflow-x-hidden"
ref={historyBottomScrollRef}
onScroll={() => syncScroll(historyBottomScrollRef.current, historyTopScrollRef.current)}
>
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownloadQlty}>
{"엑셀다운로드"}
</Button>
@@ -292,4 +324,4 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
</div>
</>
);
}
}
@@ -6,11 +6,11 @@
"use client"
import UnderComment from "@/app/components/common/UnderComment";
import { useFoStore } from "@/app/store";
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
import { StoreContext, useFoStore } from "@/app/store";
import { ContentsDiv, downloadExcelFormat, 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 { useCallback, useContext, useEffect, useRef, useState } from "react";
import ProcessFacilityInfoModal from "./modal/page";
export default function ProcessFacilitySearch() {
@@ -25,6 +25,11 @@ export default function ProcessFacilitySearch() {
//시설데이터 수질정보 조회
,searchProcessFacilityWaterQlty
} = useFoStore((state) => state) || { ProcessFacilityList: { processFacilityList: [], processFacilityCount: 0 }};
const store = useContext(StoreContext);
if (!store) {
throw new Error("StoreContext is not available. Ensure StoreProvider is mounted.");
}
const {
isInit,
@@ -69,7 +74,6 @@ export default function ProcessFacilitySearch() {
upHeadList1,
upHeadList2,
upHeadList3,
excelList,
isLoading,
} = ProcessFacilityList;
@@ -89,6 +93,7 @@ export default function ProcessFacilitySearch() {
const [partValue, setPartValue] = useState<string>("A");
// const [widthSize, setWidthSize] = useState<string>("w-[120%]");
const [upHeadList, setUpheadList] = useState(upHeadList1);
const [isExcelDownClick, setIsExcelDownClick] = useState<boolean>(false);
/**
* 모달 상태 변수
@@ -149,13 +154,7 @@ export default function ProcessFacilitySearch() {
}
}, [partValue, upHeadList1, upHeadList2, upHeadList3]);
useEffect(() => {
if (excelList && excelList.length > 0) {
downloadExcel({ data: excelList as unknown as JSON[], fileName: '처리시설 시설정보', sheetNameArray: ['처리시설 시설정보'], headerRange: 'A1:P1' });
}
}, [excelList]);
const searchFcltyList = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=10) => {
const searchFcltyList = useCallback(async ({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=10) => {
let nameCd, partStr
switch (partValue) {
case 'R':
@@ -172,7 +171,7 @@ export default function ProcessFacilitySearch() {
partStr = envPartValue !== '0' ? envPartValue:partValue;
break;
}
searchProcessFacility(pageNo, pageCnt, partStr, nameCd || '0', fcltCpct, operationValue, facilityPartValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
await searchProcessFacility(pageNo, pageCnt, partStr, nameCd || '0', fcltCpct, operationValue, facilityPartValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
if(isSearch) {
setIsSearch(false);
}
@@ -235,9 +234,44 @@ export default function ProcessFacilitySearch() {
}
}
const excelDownload = useCallback(() => {
searchFcltyList(ref.current, 1, 10000);
}, [searchFcltyList]);
const excelDownload = useCallback(async () => {
if (isExcelDownClick) 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;
// }
// }
setIsExcelDownClick(true);
try {
await searchFcltyList(ref.current, 1, 10000);
const latestExcelList = store.getState().ProcessFacilityList.excelList || [];
if (latestExcelList.length > 0) {
downloadExcelFormat({
data: latestExcelList as unknown as JSON[],
fileName: '처리시설 시설정보',
sheetNameArray: ['처리시설 시설정보'],
headerRange: 'A1:P1',
decimalArray0: [9, 10, 11],
});
} else {
alert('조회된 결과가 없습니다.');
}
} finally {
setIsExcelDownClick(false);
}
}, [isExcelDownClick, searchFcltyList, store]);
// 모달 닫기
const closeModal = () => {
@@ -266,6 +300,7 @@ export default function ProcessFacilitySearch() {
btnClass={btnClass}
queryClick={chkVal}
excelClick={excelDownload}
excelDisabled={isExcelDownClick}
initClick={resetVal}
ref={ref} isAdmin={false} />
<ListDiv>
@@ -292,11 +327,11 @@ export default function ProcessFacilitySearch() {
{selectedRow !== null && (
<UiModal
body={<ProcessFacilityInfoModal fcltyName={modalFcltyNm} facilityCd={modalFcltyCd} sido={modalSido} gugun={modalGugun} daddr={modalAddr} fctCpc={modalFctCpc} trtFrfNm={modalTrtFrfNm} rnDt={modalRnDt} cmplDt={modalCmplDt} trstOprEtpNm={modalTrstOprEtpNm} bscFctClsNm={modalBscFctClsNm} mnstr={modalMnstr} efflWtrrgn={modalEfflWtrrgn} lgbsn={modalLgbsn} efflWqltStndrdNm={modalEfflWqltStndrdNm} rgnNm={modalRgnNm} rvbsn={modalRvbsn}></ProcessFacilityInfoModal>}
bodyClass="sm:max-w-[70vw] sm:max-h-[95vh]"
bodyClass="sm:max-w-[100vw] w-[1300px] h-[100dvh] max-h-[800px]"
open={selectedRow !== null}
onOpenChange={(open) => !open && closeModal()}
/>
)}
</MainDiv>
);
}
}
+89 -29
View File
@@ -5,11 +5,11 @@
*/
"use client"
import { useFoStore } from "@/app/store";
import { StoreContext, useFoStore } from "@/app/store";
import type { TableUpperProps } from "@/app/store/common";
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiTable, type ReturnType } from "@common/business_components";
import { ContentsDiv, downloadExcelFormat, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiTable, type ReturnType } from "@common/business_components";
import ListDiv from "@common/business_components/ui/list_div";
import { useCallback, useEffect, useRef, useState } from "react";
import { useCallback, useContext, useEffect, useRef, useState } from "react";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
import UnderComment from "@/app/components/common/UnderComment";
@@ -26,6 +26,11 @@ export default function Rdi() {
,RdiSearch
,searchRdiList
} = useFoStore((state) => state) || { processAreaList: { processAreaList: [] }};
const store = useContext(StoreContext);
if (!store) {
throw new Error("StoreContext is not available. Ensure StoreProvider is mounted.");
}
const {
isInit,
@@ -41,6 +46,11 @@ export default function Rdi() {
btnClass
} = Common;
const defaultSearchYear =
selectSearchYear.find((item) => item.selected)?.val ||
selectSearchYear[0]?.val ||
"0";
const {
labelArray,
} = RdiSearch;
@@ -51,7 +61,6 @@ export default function Rdi() {
upHeadList3,
rdiList,
rdiCount,
excelList,
isLoading,
} = Rdi;
@@ -83,9 +92,10 @@ export default function Rdi() {
// 시설상태
const [operationValue, setOperationValue] = useState<string>("0");
// 조회기간
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYear, setSearchYear] = useState<string>(defaultSearchYear);
// 엑셀 다운로드 트리거
const [isInitExcelDownload, setIsInitExcelDownload] = useState<boolean>(false);
const [isExcelDownClick, setIsExcelDownClick] = useState<boolean>(false);
const [initTrigger, setInitTrigger] = useState<boolean>(false);
/**
@@ -99,7 +109,7 @@ export default function Rdi() {
// 상태값 설정
setFcltCpct(selectUpdownData[0]?.val || "0");
setOperationValue(selectOperationData[0]?.val || "0");
setSearchYear(selectSearchYear[0]?.val || "0");
setSearchYear(defaultSearchYear);
// SearchInputSelect 초기화
setFcltyName("");
if (searchInputRef.current) {
@@ -112,23 +122,11 @@ export default function Rdi() {
searchRdi(ref.current, 1, 10);
}
useEffect(() => {
if(!isInitExcelDownload) return ;
if (excelList && excelList.length > 0) {
downloadExcel({
data: excelList as unknown as JSON[],
fileName: 'RDII추정',
sheetNameArray: ['RDII추정'],
headerRange: 'A1:R1'
});
}
}, [excelList, isInitExcelDownload]);
/**
* 콜백함수
*/
// 조회
const searchRdi = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
const searchRdi = useCallback(async ({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
let nameCd, partStr
switch (partValue) {
case 'R':
@@ -147,10 +145,9 @@ export default function Rdi() {
}
if(partStr === 'G'){
searchRdiList(pageNo, pageCnt, searchYear);
await searchRdiList(pageNo, pageCnt, searchYear);
}else{
searchRdiList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
await searchRdiList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
}
}, [operationValue, fcltyName, searchRdiList, searchYear, fcltCpct]);
@@ -174,10 +171,71 @@ export default function Rdi() {
}, [upHeadList1, upHeadList2, upHeadList3]);
// 엑셀다운로드
const excelDownload = useCallback(() => {
searchRdi(ref.current, 1, 5000);
setIsInitExcelDownload(true);
}, [searchRdi]);
const excelDownload = useCallback(async () => {
if (isExcelDownClick) 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;
// }
// }
setIsExcelDownClick(true);
try {
await searchRdi(ref.current, 1, 5000);
const latestExcelList = store.getState().Rdi.excelList || [];
if (latestExcelList.length > 0) {
const toNumber = (value: unknown) => {
if (value === null || value === undefined || value === '') return '';
const parsed = typeof value === "number" ? value : Number(String(value).replace(/,/g, ""));
return Number.isFinite(parsed) ? parsed : '';
};
const numericKeys = [
"시설용량(m³/일)",
"청천시유입하수량(m³/일)",
"하절기강우일최저유입BOD(mg/L)",
"하절기최저유입BOD유입유량(m³/일)",
"동절기청천시유입BOD(mg/L)",
"RDII추정",
"RDII추정시일강수량(mm)",
"강우시총추정유입량(m³/일)",
];
const excelData = latestExcelList.map((row) => {
const nextRow = { ...row } as Record<string, unknown>;
numericKeys.forEach((key) => {
if (key in nextRow) {
nextRow[key] = toNumber(nextRow[key]);
}
});
return nextRow;
});
downloadExcelFormat({
data: excelData as unknown as JSON[],
fileName: 'RDII추정',
sheetNameArray: ['RDII추정'],
headerRange: 'A1:R1',
decimalArray0: [9, 10, 11, 12, 13, 14, 15, 16],
});
} else {
alert("조회된 결과가 없습니다.");
}
} finally {
setIsExcelDownClick(false);
}
}, [isExcelDownClick, searchRdi, store]);
// 페이지 변경
const handlePageChange = useCallback((page: number) => {
@@ -209,13 +267,15 @@ export default function Rdi() {
btnClass={btnClass}
queryClick={chkVal}
excelClick={excelDownload}
excelDisabled={isExcelDownClick}
initClick={resetVal}
ref={ref} isAdmin={false} initSidoValue={"11"}/>
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<div className="h-full w-full overflow-x-scroll min-[1200px]:overflow-x-hidden">
<div className="w-[120%] min-[1200px]:w-[100%]">
<UiTable cellClick={ undefined } headName={"RDII추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
<UiTable cellClick={ undefined } headName={"RDII추정"} tableData={mainList} headlist={upheadList}
pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
</div>
<UnderComment divHeight={"0"} commentArray={commentArray} />
</div>
@@ -223,4 +283,4 @@ export default function Rdi() {
</ContentsDiv>
</MainDiv>
);
}
}
@@ -8,7 +8,7 @@
import { roundNumber } from "@/app/components/common/DataForm";
import { useFoStore } from "@/app/store";
import type { modalTableType } from "@/app/store/sewageOccur";
import { DateMonthPicker, downloadExcel, UiTable } from "@common/business_components/ui";
import { DateMonthPicker, downloadExcelHeaders, UiTable } from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button, Table, TableCell, TableHead, TableRow } from "@common/components/ui";
import { useEffect, useState } from "react";
@@ -69,20 +69,25 @@ export default function SewageOccurModal(props: { fcltyName: string; facilityCd
}
}, [endYearMonth, startYearMonth]);
const excelDownload = () => {
const excelDownload = () => {
// 헤더 순서를 명시적으로 정의
const headers = ["날짜", "물사용량(m³/일)", "오수전환율(%)", "오수발생량 추정(m³/일)"] as const;
const excelDownList: any[] = [];
if(detailList.length > 0){
detailList.forEach((item) => {
excelDownList.push({
"날짜": item.msrDt,
"물사용량(m³/일)": roundNumber(item.waterUsage, 0),
"오수전환율(%)": roundNumber(item.swageChangePercent, 0),
"오수발생량 추정(m³/일)": roundNumber(item.estimationSewage, 0),
});
// 순서를 보장하기 위해 헤더 순서대로 객체 생성
const row: Record<string, string | number> = {};
row[headers[0]] = item.msrDt;
row[headers[1]] = roundNumber(item.waterUsage, 0);
row[headers[2]] = roundNumber(item.swageChangePercent, 0);
row[headers[3]] = roundNumber(item.estimationSewage, 0);
excelDownList.push(row);
});
}
if (excelDownList && excelDownList.length > 0) {
downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.searchYear+'년 '+props.fcltyName + ' 오수발생량 추정', sheetNameArray: [props.fcltyName + ' 오수발생량 추정'], headerRange: 'A1:D1' });
downloadExcelHeaders({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.searchYear+'년 '+props.fcltyName + ' 오수발생량 추정'
, sheetNameArray: [props.fcltyName + ' 오수발생량 추정'], headerRange: 'A1:D1', headers });
} else if (detailList.length == 0) {
alert('다운받을 데이터가 없습니다.');
}
@@ -6,13 +6,13 @@
*/
"use client"
import { useFoStore } from "@/app/store";
import { StoreContext, useFoStore } from "@/app/store";
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 { ContentsDiv, downloadExcelFormat, 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 { useCallback, useContext, useEffect, useRef, useState } from "react";
import SewageOccurModal from "./modal/page";
export default function PlanSewage() {
@@ -29,6 +29,11 @@ export default function PlanSewage() {
searchSewageOccurList: () => {},
calculateModalDataForAllFacilities: async () => []
};
const store = useContext(StoreContext);
if (!store) {
throw new Error("StoreContext is not available. Ensure StoreProvider is mounted.");
}
const {
isInit,
@@ -44,6 +49,11 @@ export default function PlanSewage() {
btnClass
} = Common;
const defaultSearchYear =
selectSearchYear.find((item) => item.selected)?.val ||
selectSearchYear[0]?.val ||
"0";
const {
labelArray,
} = SewageOccurSearch;
@@ -54,7 +64,6 @@ export default function PlanSewage() {
upHeadList3,
sewageOccurList,
sewageOccurCount,
excelList,
isLoading,
} = SewageOccur;
@@ -93,10 +102,9 @@ 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);
const [searchYear, setSearchYear] = useState<string>(defaultSearchYear);
// 엑셀 조회 중 상태
const [isExcelDownClick, setIsExcelDownClick] = useState<boolean>(false);
/**
* 페이지 함수
*/
@@ -107,7 +115,7 @@ export default function PlanSewage() {
// 상태값 설정
setFcltCpct(selectUpdownData[0]?.val || "0");
setOperationValue(selectOperationData[0]?.val || "0");
setSearchYear(selectSearchYear[0]?.val || "0");
setSearchYear(defaultSearchYear);
// SearchInputSelect 초기화
setFcltyName("");
if (searchInputRef.current) {
@@ -116,7 +124,7 @@ export default function PlanSewage() {
input.value = "";
}
}
searchSewageOccurList(1, 10, selectSearchYear[0]?.val || "0");
searchSewageOccurList(1, 10, defaultSearchYear);
}
// 모달 닫기
@@ -139,32 +147,15 @@ export default function PlanSewage() {
useEffect(() => {
if (!isInit) {
initializeCommonData();
searchSewageOccurList(1, 10, selectSearchYear[0]?.val || "0");
searchSewageOccurList(1, 10, defaultSearchYear);
}
}, [isInit, initializeCommonData, searchSewageOccurList, selectSearchYear]);
useEffect(() => {
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]);
}, [isInit, initializeCommonData, searchSewageOccurList, defaultSearchYear]);
/**
* 콜백함수
*/
// 조회
const searchFacilityPrecipitation = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
const searchFacilityPrecipitation = useCallback(async ({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
let nameCd, partStr
switch (partValue) {
case 'R':
@@ -182,9 +173,10 @@ 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);
await searchSewageOccurList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue
, fcltyName.trim() !== ""? fcltyName : undefined);
} else {
searchSewageOccurList(pageNo, pageCnt, searchYear);
await searchSewageOccurList(pageNo, pageCnt, searchYear);
}
}, [fcltCpct, operationValue, fcltyName, searchSewageOccurList, searchYear]);
@@ -195,10 +187,68 @@ export default function PlanSewage() {
}, [upHeadList1, upHeadList2, upHeadList3]);
// 엑셀다운로드
const excelDownload = useCallback(() => {
searchFacilityPrecipitation(ref.current, 1, 5000);
setIsInitExcelDownload(true);
}, [searchFacilityPrecipitation]);
const excelDownload = useCallback(async () => {
if (isExcelDownClick) 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;
}
}
setIsExcelDownClick(true);
try {
await searchFacilityPrecipitation(ref.current, 1, 5000);
const latestExcelList = store.getState().SewageOccur.excelList || [];
if (latestExcelList.length > 0) {
const toNumber = (value: unknown) => {
if (value === null || value === undefined || value === '') return '';
const parsed = typeof value === "number" ? value : Number(String(value).replace(/,/g, ""));
return Number.isFinite(parsed) ? parsed : '';
};
const numericKeys = [
"시설용량(m³/일)",
"물사용량(m³/일)",
"오수전환율(%)",
"오수발생량추정(m³/일)",
"연간하수유입량(m³/일)",
"청천시하수유입량(m³/일)",
];
const excelData = latestExcelList.map((row) => {
const nextRow = { ...row } as Record<string, unknown>;
numericKeys.forEach((key) => {
if (key in nextRow) {
nextRow[key] = toNumber(nextRow[key]);
}
});
return nextRow;
});
downloadExcelFormat({
data: excelData as unknown as JSON[],
fileName: '오수발생량 추정',
sheetNameArray: ['오수발생량 추정'],
headerRange: 'A1:O1',
decimalArray0: [9, 10, 11, 12, 13, 14]
});
} else {
alert("조회된 결과가 없습니다.");
}
} finally {
setIsExcelDownClick(false);
}
}, [isExcelDownClick, searchFacilityPrecipitation]);
// 페이지 변경
const handlePageChange = useCallback((page: number) => {
@@ -230,6 +280,7 @@ export default function PlanSewage() {
btnClass={btnClass}
queryClick={chkVal}
excelClick={excelDownload}
excelDisabled={isExcelDownClick}
initClick={resetVal}
ref={ref}
isAdmin={false}
@@ -250,7 +301,7 @@ export default function PlanSewage() {
facilityCd={fcltyCd}
searchYear={searchYear}
/>}
bodyClass="sm:max-w-[90vw] w-[1000px] h-[770px]"
bodyClass="sm:max-w-[90vw] w-[1000px] h-[100dvh] max-h-[770px]"
open={selectedRow !== null}
onOpenChange={(open) => !open && closeModal()}
noHeaderYn="Y"
@@ -29,7 +29,7 @@ const tabList1 = [
export default function UnderWaterInputModal({fcltyCd='', fcltyName='',searchYear=new Date().getFullYear().toString()} : ModalProps) {
// 그리드 관련
const {Common, UnderWaterDetail, unserWaterModal} = useFoStore((state) => state);
const {Common, UnderWaterDetail, underWaterModal} = useFoStore((state) => state);
const { btnClass } = Common;
const [startYmDate, setStartYmDate] = useState<string>(searchYear+'01');
const [endYmDate, setEndYmDate] = useState<string>(searchYear+'12');
@@ -74,8 +74,8 @@ export default function UnderWaterInputModal({fcltyCd='', fcltyName='',searchYea
}, [searchYear, tabTerm]);
useEffect(()=>{
unserWaterModal(fcltyCd, searchYear, searchYear+'01', searchYear+'12');
}, [fcltyCd, searchYear, unserWaterModal]);
underWaterModal(fcltyCd, searchYear, searchYear+'01', searchYear+'12');
}, [fcltyCd, searchYear, underWaterModal]);
useEffect(() => {
if(endYmDate < startYmDate) {
@@ -93,8 +93,8 @@ export default function UnderWaterInputModal({fcltyCd='', fcltyName='',searchYea
}, [startYmDate, endYmDate, gridListUnderWaterDetail, prevStartYmDate, prevEndYmDate]);
useEffect(() => {
unserWaterModal(fcltyCd, searchYear, prevStartYmDate, prevEndYmDate);
} , [fcltyCd, searchYear, unserWaterModal, prevStartYmDate, prevEndYmDate]);
underWaterModal(fcltyCd, searchYear, prevStartYmDate, prevEndYmDate);
} , [fcltyCd, searchYear, underWaterModal, prevStartYmDate, prevEndYmDate]);
const excelDownload = () => {
const excelDownList: any[] = [];
@@ -7,11 +7,11 @@
*/
"use client"
import { useFoStore } from "@/app/store";
import { StoreContext, useFoStore } from "@/app/store";
import type { TableUpperProps } from "@/app/store/common";
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
import { ContentsDiv, downloadExcelFormat, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
import ListDiv from "@common/business_components/ui/list_div";
import { useCallback, useEffect, useRef, useState } from "react";
import { useCallback, useContext, useEffect, useRef, useState } from "react";
import UnderWaterInputModal from "./modal/page";
import type { UnderWaterProps } from "@/app/store/underWaterInput/types";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
@@ -35,6 +35,11 @@ export default function UnderWaterInput() {
initializeCommonData: () => {},
searchUnderWaterList: () => {}
};
const store = useContext(StoreContext);
if (!store) {
throw new Error("StoreContext is not available. Ensure StoreProvider is mounted.");
}
const {
isInit,
@@ -50,6 +55,11 @@ export default function UnderWaterInput() {
btnClass
} = Common;
const defaultSearchYear =
selectSearchYear.find((item) => item.selected)?.val ||
selectSearchYear[0]?.val ||
"0";
const {
labelArray,
} = UnderWaterSearch;
@@ -60,7 +70,6 @@ export default function UnderWaterInput() {
upHeadList3,
underWaterList,
underWaterCount,
excelList,
isLoading,
} = UnderWater;
@@ -98,9 +107,9 @@ export default function UnderWaterInput() {
// 시설상태
const [operationValue, setOperationValue] = useState<string>("0");
// 조회기간
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYear, setSearchYear] = useState<string>(defaultSearchYear);
// 엑셀다운로드 트리거
const [isMount, setIsMount] = useState<boolean>(false);
const [isExcelDownClick, setIsExcelDownClick] = useState<boolean>(false);
/**
* 페이지 함수
@@ -112,7 +121,7 @@ export default function UnderWaterInput() {
// 상태값 설정
setFcltCpct(selectUpdownData[0]?.val || "0");
setOperationValue(selectOperationData[0]?.val || "0");
setSearchYear(selectSearchYear[0]?.val || "0");
setSearchYear(defaultSearchYear);
// SearchInputSelect 초기화
setFcltyName("");
if (searchInputRef.current) {
@@ -121,7 +130,7 @@ export default function UnderWaterInput() {
input.value = "";
}
}
searchUnderWaterList(1, 10, selectSearchYear[0]?.val || "0");
searchUnderWaterList(1, 10, defaultSearchYear);
}
// 모달 닫기
@@ -144,31 +153,15 @@ export default function UnderWaterInput() {
useEffect(() => {
if (!isInit) {
initializeCommonData();
searchUnderWaterList(1, 10, selectSearchYear[0]?.val || "0");
searchUnderWaterList(1, 10, defaultSearchYear);
}
}, [isInit, initializeCommonData, searchUnderWaterList, selectSearchYear]);
useEffect(() => {
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]);
}, [isInit, initializeCommonData, searchUnderWaterList, defaultSearchYear]);
/**
* 콜백함수
*/
// 조회
const searchFacilityPrecipitation = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
const searchFacilityPrecipitation = useCallback(async ({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
let nameCd, partStr
switch (partValue) {
case 'R':
@@ -186,9 +179,10 @@ 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);
await searchUnderWaterList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue
, fcltyName.trim() !== ""? fcltyName : undefined);
} else {
searchUnderWaterList(pageNo, pageCnt, searchYear);
await searchUnderWaterList(pageNo, pageCnt, searchYear);
}
}, [fcltCpct, operationValue, fcltyName, searchUnderWaterList, searchYear]);
@@ -199,10 +193,67 @@ export default function UnderWaterInput() {
}, [upHeadList1, upHeadList2, upHeadList3]);
// 엑셀다운로드
const excelDownload = useCallback(() => {
searchFacilityPrecipitation(ref.current, 1, 5000);
setIsMount(true);
}, [searchFacilityPrecipitation]);
const excelDownload = useCallback(async () => {
if (isExcelDownClick) 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;
}
}
setIsExcelDownClick(true);
try {
await searchFacilityPrecipitation(ref.current, 1, 5000);
const latestExcelList = store.getState().UnderWater.excelList || [];
if (latestExcelList.length > 0) {
const toNumber = (value: unknown) => {
if (value === null || value === undefined || value === '') return '';
const parsed = typeof value === "number" ? value : Number(String(value).replace(/,/g, ""));
return Number.isFinite(parsed) ? parsed : '';
};
const numericKeys = [
"시설용량(m³/일)",
"평균유입하수량(m³/일)",
"연간지하수유입량(m³/일)",
"하절기지하수유입량(m³/일)",
"동절기지하수유입량(m³/일)",
];
const excelData = latestExcelList.map((row) => {
const nextRow = { ...row } as Record<string, unknown>;
numericKeys.forEach((key) => {
if (key in nextRow) {
nextRow[key] = toNumber(nextRow[key]);
}
});
return nextRow;
});
downloadExcelFormat({
data: excelData as unknown as JSON[],
fileName: '지하수유입량 추정',
sheetNameArray: ['지하수유입량 추정'],
headerRange: 'A1:O1',
decimalArray0: [9, 10, 11, 12, 13]
});
} else {
alert("조회된 결과가 없습니다.");
}
} finally {
setIsExcelDownClick(false);
}
}, [isExcelDownClick, searchFacilityPrecipitation, store]);
// 페이지 변경
const handlePageChange = useCallback((page: number) => {
@@ -234,6 +285,7 @@ export default function UnderWaterInput() {
btnClass={btnClass}
queryClick={chkVal}
excelClick={excelDownload}
excelDisabled={isExcelDownClick}
initClick={resetVal}
ref={ref}
isAdmin={false}
@@ -251,7 +303,7 @@ export default function UnderWaterInput() {
{selectedRow !== null && (
<UiModal
body={<UnderWaterInputModal fcltyCd={fcltyCd} fcltyName={fcltyNm} searchYear={searchYear}></UnderWaterInputModal>}
bodyClass="sm:max-w-[90vw] w-[1000px] h-[770px]"
bodyClass="sm:max-w-[90vw] w-[1000px] h-[100dvh] max-h-[770px]"
open={selectedRow !== null}
onOpenChange={(open) => !open && closeModal()}
noHeaderYn="Y"
@@ -260,4 +312,4 @@ export default function UnderWaterInput() {
)}
</MainDiv>
);
}
}
+67 -59
View File
@@ -12,6 +12,8 @@ import { getFetch, getFetchAreaList } from "@/app/components/api";
export type SelectDataType = {
text: string;
val: string;
selected?: boolean;
hidden?: boolean;
}
// grid header
export type TableUpperProps = {
@@ -129,14 +131,14 @@ const selectEnvPartSigunData: SelectDataType[] = [
// ];
// 상향 하향 데이터
const selectUpdownData:SelectDataType[] = [
const selectUpdownData: SelectDataType[] = [
{ text: "전체", val: '0' },
{ text: "500미만", val: '400' },
{ text: "500이상", val: '500' },
];
// 운영 상태 데이터
const selectOperationData:SelectDataType[] = [
const selectOperationData: SelectDataType[] = [
{ text: "전체", val: '0' },
{ text: "가동중", val: '1' },
{ text: "재가동", val: '2' },
@@ -145,7 +147,7 @@ const selectOperationData:SelectDataType[] = [
];
// 시설 구분 데이터
const selectFacilityPartData:SelectDataType[] = [
const selectFacilityPartData: SelectDataType[] = [
{ text: "전체", val: '0' },
{ text: "공공하수처리시설", val: 'SW' },
{ text: "오수처리장", val: 'SS' },
@@ -158,25 +160,29 @@ const selectFacilityPartData:SelectDataType[] = [
// 년도 데이터
const getYearData = () => {
const year = new Date().getFullYear();
const year1 = year - 1;
const year2 = year - 2;
const year3 = year - 3;
const year4 = year - 4;
const year5 = year - 5;
return [
{ text: year1 + "년", val: year1.toString() },
{ text: year2 + "년", val: year2.toString() },
{ text: year3 + "년", val: year3.toString() },
{ text: year4 + "년", val: year4.toString() },
{ text: year5 + "년", val: year5.toString() },
]
const today = new Date();
const year = today.getFullYear();
const month = today.getMonth() + 1;
// 상반기(6월까지)는 2년 전, 하반기는 1년 전부터 시작
const defaultIdx = month <= 6 ? 2 : 1;
const startYear = year;
// 최근 10개년도 제공 (기본값: 첫 번째 항목 선택)
return Array.from({ length: 10 }, (_, index) => {
const targetYear = startYear - index;
return {
text: `${targetYear}년`,
val: targetYear.toString(),
selected: index === defaultIdx,
};
});
}
const selectSearchYear:SelectDataType[] = getYearData();
const selectSearchYear: SelectDataType[] = getYearData();
// 유량 기간 구분
const selectFlowTerm : SelectDataType[] = [
const selectFlowTerm: SelectDataType[] = [
{ text: "연간", val: '0' },
{ text: "하절기", val: '01' },
{ text: "동절기", val: '02' },
@@ -185,15 +191,15 @@ const selectFlowTerm : SelectDataType[] = [
];
// 유량 기간 구분
const selectFlowPanel : SelectDataType[] = [
{ text: "전체", val: '0'},
{ text: "3~10mm미만", val: '2'},
{ text: "10~20mm미만", val: '3'},
{ text: "20~30mm미만", val: '4'},
{ text: "30~40mm미만", val: '5'},
{ text: "40~50mm미만", val: '6'},
{ text: "50~60mm미만", val: '7'},
{ text: "60mm이상", val: '8'},
const selectFlowPanel: SelectDataType[] = [
{ text: "전체", val: '0' },
{ text: "3~10mm미만", val: '2' },
{ text: "10~20mm미만", val: '3' },
{ text: "20~30mm미만", val: '4' },
{ text: "30~40mm미만", val: '5' },
{ text: "40~50mm미만", val: '6' },
{ text: "50~60mm미만", val: '7' },
{ text: "60mm이상", val: '8' },
];
// 중권역 데이터
@@ -220,9 +226,9 @@ export const roundUp = (value: number, precision: number = 1): number => {
* @param day : 일수
* @param digit : 소수점 자리수
*/
export const qltyDataSetting = (value: number, day : number, digit: number) => {
const toZero = digit === 1 ? '0.0' : digit === 2 ? '0.00' : '0.000';
return value > 0 ? roundUp((value/day), digit).toFixed(digit) : toZero;
export const qltyDataSetting = (value: number, day: number, digit: number) => {
const toZero = digit === 1 ? '0.0' : digit === 2 ? '0.00' : '0.000';
return value > 0 ? roundUp((value / day), digit).toFixed(digit) : toZero;
};
export const COD_YEAR = 2021;
@@ -234,13 +240,13 @@ export const COD_YEAR = 2021;
// 처리시설 계획정보 호출 (알에스원)
export const planInfoUrl = '/dc-service/api/v1/nowDmgMtncGnsvy';
export const fetchPlanInfo = async (targetYear : string | undefined, ctpvNm : string | undefined, sggNm : string | undefined, fcltyCd : string | undefined) => {
export const fetchPlanInfo = async (targetYear: string | undefined, ctpvNm: string | undefined, sggNm: string | undefined, fcltyCd: string | undefined) => {
try {
const baseUrl = planInfoUrl;
const queryParams = new URLSearchParams();
if (ctpvNm && ctpvNm !== '전체') queryParams.append('ctpvNm', ctpvNm);
if (sggNm && sggNm !== '전체') queryParams.append('sggNm', sggNm);
if (targetYear) queryParams.append('targetYear',targetYear);
if (targetYear) queryParams.append('targetYear', targetYear);
if (fcltyCd) queryParams.append('swtrmtFcltCd', fcltyCd);
const queryString = queryParams.toString();
const url = queryString ? `${baseUrl}?${queryString}` : baseUrl;
@@ -258,16 +264,16 @@ const fetchSidoData = async (): Promise<SelectDataType[]> => {
const res = await getFetch('fo', '/addr/city');
const data = res.data;
selectSidoData = [
{ text: "전체", val: '0'},
{ text: "전체", val: '0' },
...data.map((item: sidoDataType) => ({
text: item.sido || '',
val: String(item.adstDstrCd) || ''
text: item.sido || '',
val: String(item.adstDstrCd) || ''
}))
];
return selectSidoData;
} catch (error) {
console.error('시도 데이터를 가져오는데 실패했습니다:', error);
return selectSidoData;
console.error('시도 데이터를 가져오는데 실패했습니다:', error);
return selectSidoData;
}
};
@@ -279,10 +285,10 @@ const fetchSigunData = async (): Promise<SelectDataType[]> => {
selectSigunData = [
{ text: "전체", val: '0' },
...data
.map((item: sigunDataType) => ({
.map((item: sigunDataType) => ({
text: item.gugun || '',
val: String(item.adstDstrCd) || ''
}))
}))
];
return selectSigunData;
} catch (error) {
@@ -297,7 +303,7 @@ const fetchRegionData = async (): Promise<SelectDataType[]> => {
const res = await getFetch('fo', '/addr/sarea');
const data = res.data;
return [
{ text: "전체", val: '0'},
{ text: "전체", val: '0' },
...data.map((item: regionDataType) => ({
text: item.rvbsn || '',
val: String(item.rvbsnCd) || ''
@@ -317,10 +323,10 @@ const fetchMiddleRegionData = async (): Promise<SelectDataType[]> => {
return [
{ text: "전체", val: '0' },
...data
.map((item: middleRegionDataType) => ({
text: item.mdmbsn || '',
val: String(item.rvbsnCd) || ''
}))
.map((item: middleRegionDataType) => ({
text: item.mdmbsn || '',
val: String(item.rvbsnCd) || ''
}))
];
} catch (error) {
console.error('중권역 데이터를 가져오는데 실패했습니다:', error);
@@ -336,10 +342,10 @@ const fetchUnitWaterShedData = async (): Promise<SelectDataType[]> => {
return [
{ text: "전체", val: '0' },
...data
.map((item: unitWaterShedDataType) => ({
text: item.lgbsn || '',
val: String(item.rvbsnCd) || ''
}))
.map((item: unitWaterShedDataType) => ({
text: item.lgbsn || '',
val: String(item.rvbsnCd) || ''
}))
];
} catch (error) {
console.error('단위유역 데이터를 가져오는데 실패했습니다:', error);
@@ -355,11 +361,11 @@ const fetchEnvPartData = async (): Promise<envPartSelectDataType[]> => {
selectEnvPartData = [
{ text: "전체", val: '0', adstDliStrCd: '' },
...data
.map((item: envPartDataType) => ({
text: item.lclgvrnmntNm || '',
val: String(item.lclgvrnmntCd) || '',
adstDliStrCd: item.adstDliStrCd || ''
}))
.map((item: envPartDataType) => ({
text: item.lclgvrnmntNm || '',
val: String(item.lclgvrnmntCd) || '',
adstDliStrCd: item.adstDliStrCd || ''
}))
];
return selectEnvPartData;
} catch (error) {
@@ -372,7 +378,7 @@ const fetchEnvPartData = async (): Promise<envPartSelectDataType[]> => {
* Store - expaort
====================================*/
export type CommonAction = {
getMenuAuth : (menuCd : number) => Promise<void>;
getMenuAuth: (menuCd: number) => Promise<void>;
initializeCommonData: () => Promise<void>;
}
@@ -394,7 +400,7 @@ export type CommonType = {
selectFlowPanel: SelectDataType[];
selectEnvPartData: envPartSelectDataType[];
btnClass: string;
COD_YEAR : number;
COD_YEAR: number;
};
auth: {
@@ -424,7 +430,7 @@ export const commonState: CommonType = {
selectFlowPanel: selectFlowPanel,
selectEnvPartData: selectEnvPartData,
btnClass: "p-4 m-2 !mr-10 text-white rounded-sm text-lg font-medium",
COD_YEAR : COD_YEAR,
COD_YEAR: COD_YEAR,
},
auth: {
@@ -436,10 +442,12 @@ export const commonState: CommonType = {
},
};
export const CommonReducer:(set:(fn: (state: CommonType) => CommonType) => void)=>CommonAction=(set: (fn: (state: CommonType) => CommonType) => void) => {
export const CommonReducer = (
set: (fn: (state: CommonType) => CommonType) => void
): CommonAction => {
return {
// 메뉴 권한 확인
getMenuAuth : async (menuCd : number) =>{
getMenuAuth: async (menuCd: number) => {
const response = await getFetch(
"local",
`/cms-service/api/v1/menu-authrts/pageinfo/${menuCd}`
@@ -478,4 +486,4 @@ export const CommonReducer:(set:(fn: (state: CommonType) => CommonType) => void)
}
}
export type CommonStore = CommonType & CommonAction;
export type CommonStore = CommonType & CommonAction;
File diff suppressed because it is too large Load Diff
@@ -153,7 +153,9 @@ export const fetchFacilityRainDetailList = async (searchYear: string|undefined,
}
};
const fetchFacilityPrecipitationList = async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
const fetchFacilityPrecipitationList = async (pageNo: number, pageSize: number, searchYear: string, part?: string
, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
const tailStr = '/'+pageNo + '/' + pageSize + '/' + searchYear + (part?'/' + part:'' ) + (nameCd?'/' + nameCd:'' ) + (fcltCpct?'/' + fcltCpct:'' ) + (operationValue?'/' + operationValue:'' ) + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') ;
const url = '/fclt/rain' + tailStr;
const res = await getFetch('fo', url);
+213 -202
View File
@@ -2,7 +2,7 @@
import DataForm, { roundNumber } from "@/app/components/common/DataForm";
import type { TableUpperProps } from "../dashboard";
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
import { COD_YEAR } from "../common";
import { COD_YEAR } from "../common"; // 2021년
import CommaToNumber from "@/app/components/common/CommaToNumber";
export type { TableUpperProps };
@@ -28,17 +28,19 @@ 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 | '',
inflAssctAftWqltBod: string | '',
inflAssctBfrWqltToc: string | '',
inflAssctAftWqltToc: string | '',
inflAssctBfrWqltCod : string | '',
inflAssctAftWqltCod : string | '',
inflAssctBfrWqltCod: string | '',
inflAssctAftWqltCod: string | '',
inflAssctBfrWqltSs: string | '',
inflAssctAftWqltSs: string | '',
inflAssctBfrWqltTn: string | '',
@@ -47,14 +49,14 @@ export interface FacilityWaterQltyProps {
inflAssctAftWqltTp: string | '',
efflWqltBod: string | '',
efflWqltToc: string | '',
efflWqltCod : string | '',
efflWqltCod: string | '',
efflWqltSs: string | '',
efflWqltTn: string | '',
efflWqltTp: string | '',
rgnNm:string|'',
rvbsn:string|'',
lgbsn:string|'',
mdmbsn:string|'',
rgnNm: string | '',
rvbsn: string | '',
lgbsn: string | '',
mdmbsn: string | '',
inflAmnt: number | '',
lclgvrnmntNm: string,
infoRnDay: number | string | '',
@@ -68,14 +70,14 @@ export interface FacilityWaterQltyProps {
tpInflWqltTp: string | '',
tpInflWqltEclgyTox: string | '',
tpInflWqltClfgrpcnt: string | '',
noProcessInflAmnt : string | number | '',
noProcessInflAmnt: string | number | '',
}
export interface ExcelType {
시설코드: string,
권역:string|'',
단위유역:string|'',
중권역:string|'',
환경청:string|'',
권역: string | '',
단위유역: string | '',
중권역: string | '',
환경청: string | '',
시도: string,
시군구: string,
시설이름: string,
@@ -146,74 +148,74 @@ 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: "C", title: "행정명", colSpan: 2, row: 0, widthPercent: 10 },
{ 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 },
{ id: "A", title: "유입", colSpan: 5, row: 0, widthPercent:25 },
{ id: "B", title: "방류", colSpan: 5, row: 0, widthPercent:25 },
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row: 1, widthPercent:5 },
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1, widthPercent:5 },
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1, widthPercent:5 },
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 4, align: "right", row: 1, widthPercent:5 },
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1, widthPercent:5 },
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row: 1, widthPercent:5 },
{ id: "efflWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row: 1, widthPercent:5 },
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1, widthPercent:5 },
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 4, align: "right", row: 1, widthPercent:5 },
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1, widthPercent:5 },
{ id: "fctCpc", title: "시설용량(m³/일)", align: "right", rowSpan: 2, row: 0, widthPercent: 10 },
{ id: "A", title: "유입", colSpan: 5, row: 0, widthPercent: 25 },
{ id: "B", title: "방류", colSpan: 5, row: 0, widthPercent: 25 },
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row: 1, widthPercent: 5 },
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1, widthPercent: 5 },
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1, widthPercent: 5 },
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 4, align: "right", row: 1, widthPercent: 5 },
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1, widthPercent: 5 },
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row: 1, widthPercent: 5 },
{ id: "efflWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row: 1, widthPercent: 5 },
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1, widthPercent: 5 },
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 4, align: "right", row: 1, widthPercent: 5 },
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1, widthPercent: 5 },
];
// 시설수질리스트 헤더(권역별)
const upHeadList2: TableUpperProps[] = [
{ id: "C", title: "유역", colSpan: 3, row: 0, widthPercent:15 },
{ id: "rvbsn", title: "권역", upName: "upChangeRe1", upSequnce: 1, row:1, widthPercent:5 },
{ id: "lgbsn", title: "단위유역", upName: "upChangeRe1", upSequnce: 2, row:1, widthPercent:5 },
{ id: "mdmbsn", title: "중권역", upName: "upChangeRe1", upSequnce: 3, row:1, widthPercent:5 },
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent:10 },
{ id: "addr", title: "주소", row:0, rowSpan:2 },
{ id: "fctCpc", title: "시설용량(m³/L)", align: "right", row:0, rowSpan:2, widthPercent:8 },
{ id: "A", title: "유입", colSpan: 5, row: 0, widthPercent:25 },
{ id: "B", title: "방류", colSpan: 5, row: 0, widthPercent:25 },
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1, widthPercent:5 },
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1, widthPercent:5 },
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1, widthPercent:5 },
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1, widthPercent:5 },
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1, widthPercent:5 },
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row:1, widthPercent:5 },
{ id: "efflWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1, widthPercent:5 },
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1, widthPercent:5 },
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1, widthPercent:5 },
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1, widthPercent:5 },
{ id: "C", title: "유역", colSpan: 3, row: 0, widthPercent: 15 },
{ id: "rvbsn", title: "권역", upName: "upChangeRe1", upSequnce: 1, row: 1, widthPercent: 5 },
{ id: "lgbsn", title: "단위유역", upName: "upChangeRe1", upSequnce: 2, row: 1, widthPercent: 5 },
{ id: "mdmbsn", title: "중권역", upName: "upChangeRe1", upSequnce: 3, row: 1, widthPercent: 5 },
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 10 },
{ id: "addr", title: "주소", row: 0, rowSpan: 2 },
{ id: "fctCpc", title: "시설용량(m³/L)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
{ id: "A", title: "유입", colSpan: 5, row: 0, widthPercent: 25 },
{ id: "B", title: "방류", colSpan: 5, row: 0, widthPercent: 25 },
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row: 1, widthPercent: 5 },
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1, widthPercent: 5 },
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1, widthPercent: 5 },
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1, widthPercent: 5 },
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1, widthPercent: 5 },
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row: 1, widthPercent: 5 },
{ id: "efflWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row: 1, widthPercent: 5 },
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1, widthPercent: 5 },
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row: 1, widthPercent: 5 },
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1, widthPercent: 5 },
];
// 시설수질리스트 헤더(환경청별)
const upHeadList3: TableUpperProps[] = [
{ id: "C", title: "유역", colSpan: 3, row: 0, widthPercent: 15 },
{ id: "rvbsn", title: "권역", row:1, widthPercent: 5 },
{ id: "lgbsn", title: "단위유역", row:1, widthPercent: 5 },
{ id: "mdmbsn", title: "중권역", row:1, widthPercent: 5 },
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2, widthPercent: 7 },
{ id: "rvbsn", title: "권역", row: 1, widthPercent: 5 },
{ id: "lgbsn", title: "단위유역", row: 1, widthPercent: 5 },
{ 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: "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 },
{ 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 },
{ id: "A", title: "유입", colSpan: 5, row: 0, widthPercent: 20 },
{ id: "B", title: "방류", colSpan: 5, row: 0, widthPercent: 20 },
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1, widthPercent: 4 },
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1, widthPercent: 4 },
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1, widthPercent: 4 },
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1, widthPercent: 4 },
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1, widthPercent: 4 },
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row:1, widthPercent: 4 },
{ id: "efflWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1, widthPercent: 4 },
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1, widthPercent: 4 },
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1, widthPercent: 4 },
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1, widthPercent: 4 },
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row: 1, widthPercent: 4 },
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1, widthPercent: 4 },
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1, widthPercent: 4 },
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1, widthPercent: 4 },
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1, widthPercent: 4 },
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row: 1, widthPercent: 4 },
{ id: "efflWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row: 1, widthPercent: 4 },
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1, widthPercent: 4 },
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row: 1, widthPercent: 4 },
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1, widthPercent: 4 },
];
/**
@@ -282,20 +284,24 @@ const upHeadListModalChongIn: TableUpperProps[] = [
====================================*/
// 메인페이지
// 시설정보 수질 리스트 데이터 호출
const fetchFacilityWaterQltyList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string|undefined, nameCd?: string|undefined, fcltCpct?: string|undefined, operationValue?: string|undefined, fcltyNm?: string | undefined): Promise<{ data: FacilityWaterQltyProps[], count: number }> => {
const fetchFacilityWaterQltyList = async (
pageNo: number, pageSize: number, searchYear: string, partCd?: string | undefined
, nameCd?: string | undefined, fcltCpct?: string | undefined
, operationValue?: string | undefined, fcltyNm?: string | undefined
): Promise<{ data: FacilityWaterQltyProps[], count: number, status: number }> => {
try {
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
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, status: res.status };
} catch (error) {
console.error('시설정보 수질현황 데이터를 가져오는데 실패했습니다:', error);
return { data: [], count: 0 };
return { data: [], count: 0, status: 300 };
}
}
// 시설정보 수질 리스트 데이터 호출(모달-수질TMS)
const fetchFacilityWaterQltyTmsList = async (facilityCd: string|undefined) => {
const fetchFacilityWaterQltyTmsList = async (facilityCd: string | undefined) => {
try {
const res = await getFetch('wr', '/il/getTms/' + facilityCd);
return { data: res.data, count: res.count };
@@ -306,7 +312,7 @@ const fetchFacilityWaterQltyTmsList = async (facilityCd: string|undefined) => {
};
// 시설정보 수질 리스트 데이터 호출(모달-이력)
export const fetchFacilityWaterQltyListHist = async (searchYear: string|undefined, facilityCd: string|undefined): Promise<WaterQualityHistoryResponse | null> => {
export const fetchFacilityWaterQltyListHist = async (searchYear: string | undefined, facilityCd: string | undefined): Promise<WaterQualityHistoryResponse | null> => {
try {//
const res = await getFetch('fo', '/fclt/qlty/hist/' + searchYear + '/' + facilityCd);
return res;
@@ -316,9 +322,9 @@ export const fetchFacilityWaterQltyListHist = async (searchYear: string|undefine
}
};
// 시설정보 RDII 상세 [{BOD - inflAssctBfrWqltBod, 유입유량 inflAmnt, 강우량 infoRnDay, 측정일 msrDt}]
export const fetchFacilityRdiiDetailList = async (searchYear: string|undefined, swtrmtFcltCdList: string[]): Promise<FacilityRdiiDetailProps | null> => {
export const fetchFacilityRdiiDetailList = async (searchYear: string | undefined, swtrmtFcltCdList: string[]): Promise<FacilityRdiiDetailProps | null> => {
try {
const res = await postFetch('fo', '/rdii/detail/'+searchYear, swtrmtFcltCdList);
const res = await postFetch('fo', '/rdii/detail/' + searchYear, swtrmtFcltCdList);
return res;
} catch (error) {
console.error('시설정보 RDII 상세 데이터를 가져오는데 실패했습니다:', error);
@@ -345,7 +351,7 @@ export type FacilityWaterQltyType = {
FacilityWaterQltyModal: {
// 처리시설 수질현황
upHeadListModalYear: TableUpperProps[];
upHeadListModalYearCod : TableUpperProps[];
upHeadListModalYearCod: TableUpperProps[];
facilityWaterQltyYearList: FacilityWaterQltyProps[];
upHeadListModalTms: TableUpperProps[];
facilityWaterQltyTmsList: FacilityWaterQltyTmsProps[];
@@ -432,7 +438,8 @@ const dataFormSetting = (item: FacilityWaterQltyProps) => {
export type FacilityWaterQltyStore = FacilityWaterQltyType & FacilityWaterQltyActions;
export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType) => FacilityWaterQltyType) => void): FacilityWaterQltyActions => {
type SetFunc = (fn: (state: FacilityWaterQltyType) => FacilityWaterQltyType) => void;
export const facilityWaterQltyReducer = (set: SetFunc): FacilityWaterQltyActions => {
return {
// 메인페이지
/**
@@ -446,7 +453,9 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
* @param operationValue : 운영상태코드
* @param fcltyNm : 시설명
*/
searchFacilityWaterQltyList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
searchFacilityWaterQltyList: async (pageNo: number, pageSize: number, searchYear: string, part?: string
, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
set((state: FacilityWaterQltyType) => ({
...state,
FacilityWaterQltyMain: {
@@ -454,64 +463,90 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
isLoading: true,
},
}));
const res = await fetchFacilityWaterQltyList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
const rtnData = res.data.map(item => {
// const res = await fetchFacilityWaterQltyList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
//---------
const waterQltyList: any[] = [];
let recordCount = 0;
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; // 더 이상 데이터가 없으면 중지
}
}
}
//-------
// const rtnData = res.data.map(item => {
const rtnData = waterQltyList.map(item => {
dataFormSetting(item)
if(item.inflAssctBfrWqltTn) {
item.inflAssctBfrWqltTn = Number(Math.round(Number(item.inflAssctBfrWqltTn) * 1000)/1000).toFixed(3);
if (item.inflAssctBfrWqltTn) {
item.inflAssctBfrWqltTn = Number(Math.round(Number(item.inflAssctBfrWqltTn) * 1000) / 1000).toFixed(3);
}
if(item.efflWqltTn){
item.efflWqltTn = Number(Math.round(Number(item.efflWqltTn) * 1000)/1000).toFixed(3);
if (item.efflWqltTn) {
item.efflWqltTn = Number(Math.round(Number(item.efflWqltTn) * 1000) / 1000).toFixed(3);
}
if(item.inflAssctBfrWqltTp){
item.inflAssctBfrWqltTp = Number(Math.round(Number(item.inflAssctBfrWqltTp) * 1000)/1000).toFixed(3);
if (item.inflAssctBfrWqltTp) {
item.inflAssctBfrWqltTp = Number(Math.round(Number(item.inflAssctBfrWqltTp) * 1000) / 1000).toFixed(3);
}
if(item.efflWqltTp){
item.efflWqltTp = Number(Math.round(Number(item.efflWqltTp) * 1000)/1000).toFixed(3);
if (item.efflWqltTp) {
item.efflWqltTp = Number(Math.round(Number(item.efflWqltTp) * 1000) / 1000).toFixed(3);
}
if(item.inflAssctBfrWqltToc){
item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10)/10).toFixed(1);
if (item.inflAssctBfrWqltToc) {
item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10) / 10).toFixed(1);
}
if(item.efflWqltToc){
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
if (item.efflWqltToc) {
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10) / 10).toFixed(1);
}
if(item.inflAssctBfrWqltBod){
item.inflAssctBfrWqltBod = Number(Math.round(Number(item.inflAssctBfrWqltBod) * 10)/10).toFixed(1);
if (item.inflAssctBfrWqltBod) {
item.inflAssctBfrWqltBod = Number(Math.round(Number(item.inflAssctBfrWqltBod) * 10) / 10).toFixed(1);
}
if(item.efflWqltBod){
item.efflWqltBod = Number(Math.round(Number(item.efflWqltBod) * 10)/10).toFixed(1);
if (item.efflWqltBod) {
item.efflWqltBod = Number(Math.round(Number(item.efflWqltBod) * 10) / 10).toFixed(1);
}
if(item.inflAssctBfrWqltSs){
item.inflAssctBfrWqltSs = Number(Math.round(Number(item.inflAssctBfrWqltSs) * 10)/10).toFixed(1);
if (item.inflAssctBfrWqltSs) {
item.inflAssctBfrWqltSs = Number(Math.round(Number(item.inflAssctBfrWqltSs) * 10) / 10).toFixed(1);
}
if(item.efflWqltSs){
item.efflWqltSs = Number(Math.round(Number(item.efflWqltSs) * 10)/10).toFixed(1);
if (item.efflWqltSs) {
item.efflWqltSs = Number(Math.round(Number(item.efflWqltSs) * 10) / 10).toFixed(1);
}
if(item.inflAssctBfrWqltToc){
item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10)/10).toFixed(1);
if (item.inflAssctBfrWqltToc) {
item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10) / 10).toFixed(1);
}
if(item.efflWqltToc){
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
if (item.efflWqltToc) {
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10) / 10).toFixed(1);
}
return item;
});
const excelDownList: ExcelType[] = [];
if(pageSize>5000){
res.data.forEach(item => {
if (pageSize > 5000) {
// res.data.forEach(item => {
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.inflAssctBfrWqltToc = Number(searchYear)<COD_YEAR? "("+item.inflAssctBfrWqltToc+")" : item.inflAssctBfrWqltToc;
item.efflWqltToc = Number(searchYear)<COD_YEAR? "("+item.efflWqltToc+")" : item.efflWqltToc;
// 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({
시설코드: item.bscFctCd,
권역: item.rvbsn,
단위유역: item.lgbsn,
중권역: item.mdmbsn,
환경청: item.rgnNm,
시도: item.sidoNm,
시군구: item.sggNm,
시도: item.sido,
시군구: item.gugun,
시설이름: item.bscFctNm,
주소: item.addr,
"시설용량(m³/일)": CommaToNumber(item.fctCpc),
@@ -527,27 +562,28 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
"유출TP(mg/L)": CommaToNumber(item.efflWqltTp),
});
});
}else{
res.data.forEach((item: FacilityWaterQltyProps) => {
} else {
// res.data.forEach((item: FacilityWaterQltyProps) => {
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.inflAssctBfrWqltToc = Number(searchYear)<COD_YEAR? "("+item.inflAssctBfrWqltToc+")" : item.inflAssctBfrWqltToc;
item.efflWqltToc = Number(searchYear)<COD_YEAR? "("+item.efflWqltToc+")" : item.efflWqltToc;
// 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;
});
}
set((state: FacilityWaterQltyType) => ({
...state,
FacilityWaterQltyMain: pageSize<5000?{
FacilityWaterQltyMain: pageSize < 5000 ? {
...state.FacilityWaterQltyMain,
facilityWaterQltyList: rtnData,
facilityWaterQltyCount: res.count,
isLoading : false,
}:{
facilityWaterQltyCount: recordCount,
isLoading: false,
} : {
...state.FacilityWaterQltyMain,
excelList: excelDownList,
isLoading : false,
isLoading: false,
},
}))
},
@@ -555,10 +591,10 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
searchFacilityWaterQltyListHist: async (searchYear: string, facilityCd: string) => {
const res = await fetchFacilityWaterQltyListHist(searchYear, facilityCd);
const res1 = await fetchFacilityWaterQltyTmsList(facilityCd);
let rtnMsrmtDate = '';
const rtnTmsList: FacilityWaterQltyTmsProps[] = [];
if(res1.data){
if (res1.data) {
rtnTmsList.push({
part: '평균',
toc: res1.data.tocAvgVl,
@@ -566,7 +602,6 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
tn: res1.data.tnAvgVl,
tp: res1.data.tpAvgVl,
});
rtnTmsList.push({
part: '최대',
toc: res1.data.tocMaxVl,
@@ -574,7 +609,6 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
tn: res1.data.tnMaxVl,
tp: res1.data.tpMaxVl,
});
rtnTmsList.push({
part: '최소',
toc: res1.data.tocMinVl,
@@ -584,42 +618,21 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
});
rtnMsrmtDate = res1.data.msrmtDate;
}else{
rtnTmsList.push({
part: '평균',
toc: 0,
ss: 0,
tn: 0,
tp: 0,
});
rtnTmsList.push({
part: '최대',
toc: 0,
ss: 0,
tn: 0,
tp: 0,
});
rtnTmsList.push({
part: '최소',
toc: 0,
ss: 0,
tn: 0,
tp: 0,
});
} else {
rtnTmsList.push({ part: '평균', toc: 0, ss: 0, tn: 0, tp: 0, });
rtnTmsList.push({ part: '최대', toc: 0, ss: 0, tn: 0, tp: 0, });
rtnTmsList.push({ part: '최소', toc: 0, ss: 0, tn: 0, tp: 0, });
rtnMsrmtDate = '';
}
if(Array.isArray(res) || !res || !('data' in res) || !res.data || !res.data.wqltObjs || res.data.wqltObjs.length === 0) {
if (Array.isArray(res) || !res || !('data' in res) || !res.data || !res.data.wqltObjs || res.data.wqltObjs.length === 0) {
set((state: FacilityWaterQltyType) => ({
...state,
FacilityWaterQltyModal: {
...state.FacilityWaterQltyModal,
facilityWaterQltyYearList: [],
tmsList : rtnTmsList,
msrmtDate : rtnMsrmtDate
tmsList: rtnTmsList,
msrmtDate: rtnMsrmtDate
}
}))
return;
@@ -627,19 +640,17 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
// facilityPrecipitation의 rainEffectDay 계산 로직을 적용
const data = CalcRainEffect(res.data.wqltObjs);
/**
* [(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​
/강우시 일별유입BOD)
*/
//let rainInflAmnt = 0;
let sunnyInflAmnt = 0;
let sunnyBod = 0;
//let rainDay = 0;
let sunnyDay = 0;
data.forEach(item => {
if(item.rainEffectDay == 1){
if (item.rainEffectDay == 1) {
//rainDay += 1;
//rainInflAmnt += Number(item.inflAmnt);
} else {
@@ -650,69 +661,69 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
});
//const yearRainAmnt = rainInflAmnt===0?0:rainInflAmnt / rainDay;
const yearSunnyAmnt = sunnyInflAmnt===0?0:sunnyInflAmnt / sunnyDay;
const yearSunnyBod = sunnyBod===0?0:sunnyBod / sunnyDay;
const yearSunnyAmnt = sunnyInflAmnt === 0 ? 0 : sunnyInflAmnt / sunnyDay;
const yearSunnyBod = sunnyBod === 0 ? 0 : sunnyBod / sunnyDay;
//
const rtnData = data.map((item: FacilityWaterQltyProps) => {
dataFormSetting(item)
if(item.inflAssctBfrWqltTn) {
item.inflAssctBfrWqltTn = Number(Math.round(Number(item.inflAssctBfrWqltTn) * 1000)/1000).toFixed(3);
if (item.inflAssctBfrWqltTn) {
item.inflAssctBfrWqltTn = Number(Math.round(Number(item.inflAssctBfrWqltTn) * 1000) / 1000).toFixed(3);
}
if(item.efflWqltTn){
item.efflWqltTn = Number(Math.round(Number(item.efflWqltTn) * 1000)/1000).toFixed(3);
if (item.efflWqltTn) {
item.efflWqltTn = Number(Math.round(Number(item.efflWqltTn) * 1000) / 1000).toFixed(3);
}
if(item.inflAssctBfrWqltTp){
item.inflAssctBfrWqltTp = Number(Math.round(Number(item.inflAssctBfrWqltTp) * 1000)/1000).toFixed(3);
if (item.inflAssctBfrWqltTp) {
item.inflAssctBfrWqltTp = Number(Math.round(Number(item.inflAssctBfrWqltTp) * 1000) / 1000).toFixed(3);
}
if(item.efflWqltTp){
item.efflWqltTp = Number(Math.round(Number(item.efflWqltTp) * 1000)/1000).toFixed(3);
if (item.efflWqltTp) {
item.efflWqltTp = Number(Math.round(Number(item.efflWqltTp) * 1000) / 1000).toFixed(3);
}
if(item.inflAssctBfrWqltToc){
item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10)/10).toFixed(1);
if (item.inflAssctBfrWqltToc) {
item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10) / 10).toFixed(1);
}
if(item.efflWqltToc){
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
if (item.efflWqltToc) {
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10) / 10).toFixed(1);
}
if(item.inflAssctBfrWqltCod){
item.inflAssctBfrWqltCod = "("+Number(Math.round(Number(item.inflAssctBfrWqltCod) * 10)/10).toFixed(1)+")";
if (item.inflAssctBfrWqltCod) {
item.inflAssctBfrWqltCod = "(" + Number(Math.round(Number(item.inflAssctBfrWqltCod) * 10) / 10).toFixed(1) + ")";
}
if(item.efflWqltCod){
item.efflWqltCod = "("+Number(Math.round(Number(item.efflWqltCod) * 10)/10).toFixed(1)+")";
if (item.efflWqltCod) {
item.efflWqltCod = "(" + Number(Math.round(Number(item.efflWqltCod) * 10) / 10).toFixed(1) + ")";
}
if(item.inflAssctBfrWqltBod){
item.inflAssctBfrWqltBod = Number(Math.round(Number(item.inflAssctBfrWqltBod) * 10)/10).toFixed(1);
if (item.inflAssctBfrWqltBod) {
item.inflAssctBfrWqltBod = Number(Math.round(Number(item.inflAssctBfrWqltBod) * 10) / 10).toFixed(1);
}
if(item.efflWqltBod){
item.efflWqltBod = Number(Math.round(Number(item.efflWqltBod) * 10)/10).toFixed(1);
if (item.efflWqltBod) {
item.efflWqltBod = Number(Math.round(Number(item.efflWqltBod) * 10) / 10).toFixed(1);
}
if(item.inflAssctBfrWqltSs){
item.inflAssctBfrWqltSs = Number(Math.round(Number(item.inflAssctBfrWqltSs) * 10)/10).toFixed(1);
if (item.inflAssctBfrWqltSs) {
item.inflAssctBfrWqltSs = Number(Math.round(Number(item.inflAssctBfrWqltSs) * 10) / 10).toFixed(1);
}
if(item.efflWqltSs){
item.efflWqltSs = Number(Math.round(Number(item.efflWqltSs) * 10)/10).toFixed(1);
if (item.efflWqltSs) {
item.efflWqltSs = Number(Math.round(Number(item.efflWqltSs) * 10) / 10).toFixed(1);
}
if(item.inflAssctBfrWqltToc){
item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10)/10).toFixed(1);
if (item.inflAssctBfrWqltToc) {
item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10) / 10).toFixed(1);
}
if(item.efflWqltToc){
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
if (item.efflWqltToc) {
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10) / 10).toFixed(1);
}
if(item.tpInflWqltBod){
item.tpInflWqltBod = item.tpInflWqltBod?Number(Math.round(Number(item.tpInflWqltBod) * 10)/10).toFixed(1):Number(item.tpInflWqltBod)===0?'0.0':'';
}else{
if (item.tpInflWqltBod) { // 총인 유입수질 BOD(mg/L)
item.tpInflWqltBod = item.tpInflWqltBod ? Number(Math.round(Number(item.tpInflWqltBod) * 10) / 10).toFixed(1) : Number(item.tpInflWqltBod) === 0 ? '0.0' : '';
} else {
item.tpInflWqltBod = '';
}
if(item.tpInflWqltTp){
item.tpInflWqltTp = item.tpInflWqltTp?Number(Math.round(Number(item.tpInflWqltTp) * 1000)/1000).toFixed(3): Number(item.tpInflWqltTp)===0?'0.000':'';
}else{
if (item.tpInflWqltTp) { // 총인 유입수질 TP(mg/L)
item.tpInflWqltTp = item.tpInflWqltTp ? Number(Math.round(Number(item.tpInflWqltTp) * 1000) / 1000).toFixed(3) : Number(item.tpInflWqltTp) === 0 ? '0.000' : '';
} else {
item.tpInflWqltTp = '';
}
const dayBod = Number(item.inflAssctBfrWqltBod);
const noProcessInflAmnt = roundNumber(((Number(item.inflAmnt) * dayBod) - (yearSunnyAmnt * yearSunnyBod)) / dayBod, 0)
item.noProcessInflAmnt = noProcessInflAmnt && Number(noProcessInflAmnt.replaceAll(',','')) > 0 ? noProcessInflAmnt : '';
item.noProcessInflAmnt = noProcessInflAmnt && Number(noProcessInflAmnt.replaceAll(',', '')) > 0 ? noProcessInflAmnt : '';
return item;
})
@@ -721,8 +732,8 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
FacilityWaterQltyModal: {
...state.FacilityWaterQltyModal,
facilityWaterQltyYearList: rtnData,
tmsList : rtnTmsList,
msrmtDate : rtnMsrmtDate
tmsList: rtnTmsList,
msrmtDate: rtnMsrmtDate
}
}))
},
+198 -160
View File
@@ -1,6 +1,6 @@
import { getFetch } from "@/app/components/api";
import type { TableUpperProps } from "../dashboard";
import DataForm, { roundNumber } from "@/app/components/common/DataForm";
import DataForm from "@/app/components/common/DataForm";
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
import { fetchFacilityWaterQltyListHist } from "../facilityWaterQlty";
import CommaToNumber from "@/app/components/common/CommaToNumber";
@@ -12,34 +12,34 @@ import CommaToNumber from "@/app/components/common/CommaToNumber";
/**
* (1) 메인페이지
*/
const FlowRateSearchLabelArray:string[] = ['구분', '시도', '시군구', '용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
const FlowRateSearchLabelArray: string[] = ['구분', '시도', '시군구', '용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
export type flowRateListProps = {
bscFctCd : string,
sido : string,
gugun : string,
bscFctNm : string,
daddr : string,
fctCpc : number,
lclgvrnmntNm : string,
totInflAmnt : number | '',
inflAmnt : number | '',
sumFlow : number | '',
returnAmnt : number | '',
efflAmnt : number | '',
rgnNm : string,
rvbsn : string,
lgbsn : string,
mdmbsn : string,
infoRnDay : number | '',
bscFctCd: string,
sido: string,
gugun: string,
bscFctNm: string,
daddr: string,
fctCpc: number,
lclgvrnmntNm: string,
totInflAmnt: number | '',
inflAmnt: number | '',
sumFlow: number | '',
returnAmnt: number | '',
efflAmnt: number | '',
rgnNm: string,
rvbsn: string,
lgbsn: string,
mdmbsn: string,
infoRnDay: number | '',
}
export interface ExcelType {
시설코드: string,
권역:string|'',
단위유역:string|'',
중권역:string|'',
환경청:string|'',
권역: string | '',
단위유역: string | '',
중권역: string | '',
환경청: string | '',
시도: string,
시군구: string,
시설이름: string,
@@ -66,105 +66,105 @@ export type modalExcelType = {
* (2) 모달
*/
export interface FlowRateModalInterface {
msrDt : string,
totInflAmnt : number | '',
inflAmnt : number | '',
sumFlow : number | '',
returnAmnt : number | '',
efflAmnt : number | '',
infoRnDay : number | string | '',
rainEffectDay : number | string | '' ,
noProcessInflAmnt : number | string | ''
msrDt: string,
totInflAmnt: number | '',
inflAmnt: number | '',
sumFlow: number | '',
returnAmnt: number | '',
efflAmnt: number | '',
infoRnDay: number | string | '',
rainEffectDay: number | string | '',
noProcessInflAmnt: number | string | ''
}
export type FlowRateModalProps = {
msrDt : string,
totInflAmnt : number,
inflAmnt : number,
sumFlow : number,
returnAmnt : number,
efflAmnt : number,
infoRnDay : number | string | '',
rainEffectDay : number | string | '',
noProcessInflAmnt : number | string | ''
msrDt: string,
totInflAmnt: number,
inflAmnt: number,
sumFlow: number,
returnAmnt: number,
efflAmnt: number,
infoRnDay: number | string | '',
rainEffectDay: number | string | '',
noProcessInflAmnt: number | string | ''
}
/**====================================
* Store - data
====================================*/
/**
* (1) 메인페이지
*/
/**
* (1) 메인페이지
*/
// 리스트 (행정별)
const upHeadList1:TableUpperProps[] = [
const upHeadList1: TableUpperProps[] = [
{ id: "A", title: "행정명", row: 0, colSpan: 2, widthPercent: 16 },
{ id: "sido", title: "시도", upName:"upChangeRe", row:1, widthPercent: 8 },
{ id: "gugun", title: "시군구", upName:"upChangeRe", row:1, widthPercent: 8 },
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 10},
{ id: "sido", title: "시도", upName: "upChangeRe", row: 1, widthPercent: 8 },
{ id: "gugun", title: "시군구", upName: "upChangeRe", row: 1, widthPercent: 8 },
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 10 },
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "totInflAmnt", title: "총 유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 }
{ id: "fctCpc", title: "시설용량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "totInflAmnt", title: "총 유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "efflAmnt", title: '방류량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 }
];
// 리스트 (권역별)
const upHeadList2:TableUpperProps[] = [
const upHeadList2: TableUpperProps[] = [
{ id: "A", title: "유역", row: 0, colSpan: 3, widthPercent: 24 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe", row:1, widthPercent: 8 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", row:1, widthPercent: 8 },
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", row:1, widthPercent: 8 },
{ id: "rvbsn", title: "권역", upName: "upChangeRe", row: 1, widthPercent: 8 },
{ id: "lgbsn", title: "단위유역", upName: "upChangeRe", row: 1, widthPercent: 8 },
{ id: "mdmbsn", title: "중권역", upName: "upChangeRe", row: 1, widthPercent: 8 },
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 10 },
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 10 },
{ id: "totInflAmnt", title: "총 유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 }
{ id: "fctCpc", title: "시설용량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 10 },
{ id: "totInflAmnt", title: "총 유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "efflAmnt", title: '방류량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 }
];
// 리스트 (환경청별별)
const upHeadList3:TableUpperProps[] = [
const upHeadList3: TableUpperProps[] = [
{ id: "A", title: "유역", row: 0, colSpan: 3, widthPercent: 15 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", row:1, widthPercent: 5 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", row:1, widthPercent: 5 },
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", row:1, widthPercent: 5 },
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2, widthPercent: 7 },
{ id: "B", title: "행정명", row: 0 ,colSpan: 2, widthPercent: 10 },
{ id: "sido", title: "시도", upName:"upChangeRe2", row:1, widthPercent: 5 },
{ id: "gugun", title: "시군구", upName:"upChangeRe2", row:1, widthPercent: 5 },
{ id: "rvbsn", title: "권역", upName: "upChangeRe1", row: 1, widthPercent: 5 },
{ id: "lgbsn", title: "단위유역", upName: "upChangeRe1", row: 1, widthPercent: 5 },
{ id: "mdmbsn", title: "중권역", upName: "upChangeRe1", row: 1, widthPercent: 5 },
{ id: "rgnNm", title: "환경청", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "B", title: "행정명", row: 0, colSpan: 2, widthPercent: 10 },
{ 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: 7 },
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "totInflAmnt", title: "총 유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 }
{ id: "fctCpc", title: "시설용량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "totInflAmnt", title: "총 유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "efflAmnt", title: '방류량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 }
];
const flowRateList:flowRateListProps[] = [
const flowRateList: flowRateListProps[] = [
]
/**
* (2) 모달
*/
const upHeadListFlowRateModal:TableUpperProps[] = [
{ id: "msrDt", title: "날짜"},
{ id: "totInflAmnt", title: "총 유입량(m³/일)", align:"right"},
{ id: "inflAmnt", title: "하수유입량(m³/일)", align:"right"},
{ id: "sumFlow", title: "연계처리량(m³/일)", align:"right"},
{ id: "returnAmnt", title: "총인 반류수량(m³/일)", align:"right"},
{ id: "efflAmnt", title: "방류량(m³/일)", align:"right"},
{ id: "noProcessInflAmnt", title: "미처리하수 추정량(m³/일)", align:"right"},
{ id: "infoRnDay", title: "강우량(mm/일)", align:"right"}
const upHeadListFlowRateModal: TableUpperProps[] = [
{ id: "msrDt", title: "날짜" },
{ id: "totInflAmnt", title: "총 유입량(m³/일)", align: "right" },
{ id: "inflAmnt", title: "하수유입량(m³/일)", align: "right" },
{ id: "sumFlow", title: "연계처리량(m³/일)", align: "right" },
{ id: "returnAmnt", title: "총인 반류수량(m³/일)", align: "right" },
{ id: "efflAmnt", title: "방류량(m³/일)", align: "right" },
{ id: "noProcessInflAmnt", title: "미처리하수 추정량(m³/일)", align: "right" },
{ id: "infoRnDay", title: "강우량(mm/일)", align: "right" }
]
const modalFlowRateListYear:FlowRateModalProps[] = [
const modalFlowRateListYear: FlowRateModalProps[] = [
]
/**====================================
@@ -172,13 +172,14 @@ const modalFlowRateListYear:FlowRateModalProps[] = [
====================================*/
const fetchFlowRateList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
try {
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
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 }
return { data: res.data, count: res.count, status: res.status}
} catch (error) {
console.error('시설정보 유량현황 데이터를 가져오는데 실패했습니다:', error);
return { data: [], count: 0 };
console.log(error);
return { data: [], count: 0, status: 300 };
}
}
@@ -186,12 +187,12 @@ export const fetchFlowRateModalList = async (bscFctCd: string, searchYear: strin
try {
const url = '/fclt/flow/' + bscFctCd + '/' + searchYear;
const res = await getFetch('fo', url);
// msrDt 오름차순으로 정렬
const sortedData = res.data.sort((a: FlowRateModalInterface, b: FlowRateModalInterface) => {
return new Date(a.msrDt).getTime() - new Date(b.msrDt).getTime();
});
return { data: sortedData }
} catch (error) {
console.error('시설정보 유량현황 모달 데이터를 가져오는데 실패했습니다:', error);
@@ -206,69 +207,69 @@ export const fetchFlowRateModalList = async (bscFctCd: string, searchYear: strin
export type FlowRateSearchActions = {
searchFlowRateList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
searchFlowRateModalList : (bscFctCd: string, searchYear: string) => void;
searchFlowRateModalList: (bscFctCd: string, searchYear: string) => void;
}
export type FlowRateSearchType = {
FlowRateSearch: {
isInit: boolean;
flowRateSearchLabelArray:string[];
flowRateSearchLabelArray: string[];
},
FlowRateList : {
isInit : boolean;
FlowRateList: {
isInit: boolean;
upHeadList1: TableUpperProps[];
upHeadList2: TableUpperProps[];
upHeadList3: TableUpperProps[];
flowRateList:flowRateListProps[];
flowRateList: flowRateListProps[];
flowRateCount: number;
excelList: ExcelType[];
isLoading: boolean;
},
FlowRateModal : {
isInit : boolean;
modalFlowRateListYear : FlowRateModalProps[];
upHeadListFlowRateModalYear : TableUpperProps[];
FlowRateModal: {
isInit: boolean;
modalFlowRateListYear: FlowRateModalProps[];
upHeadListFlowRateModalYear: TableUpperProps[];
}
}
export type FlowRateSearchStore = FlowRateSearchType & FlowRateSearchActions;
const dataFormSetting=(item : flowRateListProps | FlowRateModalProps)=> {
export const dataFormSetting = (item: flowRateListProps | FlowRateModalProps | FlowRateModalInterface) => {
DataForm({ type: 'date', column: 'msrDt', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'totInflAmnt', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'inflAmnt', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'sumFlow', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'efflWqltBod', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'returnAmnt', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'efflAmnt', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'totInflAmnt', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'inflAmnt', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'sumFlow', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'efflWqltBod', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'returnAmnt', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'efflAmnt', item: item as unknown as Record<string, unknown> });
}
export const flowRateSearchInitState:FlowRateSearchType = {
export const flowRateSearchInitState: FlowRateSearchType = {
FlowRateSearch: {
isInit: false,
flowRateSearchLabelArray: FlowRateSearchLabelArray,
},
FlowRateList : {
isInit : false,
upHeadList1 : upHeadList1,
upHeadList2 : upHeadList2,
upHeadList3 : upHeadList3,
flowRateList : flowRateList,
flowRateCount : 0,
FlowRateList: {
isInit: false,
upHeadList1: upHeadList1,
upHeadList2: upHeadList2,
upHeadList3: upHeadList3,
flowRateList: flowRateList,
flowRateCount: 0,
excelList: [],
isLoading: true,
},
FlowRateModal : {
isInit : false,
upHeadListFlowRateModalYear : upHeadListFlowRateModal,
modalFlowRateListYear : modalFlowRateListYear,
FlowRateModal: {
isInit: false,
upHeadListFlowRateModalYear: upHeadListFlowRateModal,
modalFlowRateListYear: modalFlowRateListYear,
}
}
export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => FlowRateSearchType) => void)=>FlowRateSearchActions=(set: (fn: (state: FlowRateSearchType) => FlowRateSearchType) => void) => {
export const flowRateSearchReducer: (set: (fn: (state: FlowRateSearchType) => FlowRateSearchType) => void) => FlowRateSearchActions = (set: (fn: (state: FlowRateSearchType) => FlowRateSearchType) => void) => {
return {
searchFlowRateList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
set((state: FlowRateSearchType) => ({
@@ -278,17 +279,50 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow
isLoading: true,
},
}));
const res = await fetchFlowRateList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
const data = res.data;
// const res = await fetchFlowRateList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
//---------
const flowRateList: any[] = [];
const results: any[] = [];
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;
//-------
// const data = res.data;
const data = flowRateList;
const excelDownList: ExcelType[] = [];
const rtnData = data.map((item: flowRateListProps) => {
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0)
item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0); // 하수유입량 + 연계처리량 + 반류수유량(m³/일)
dataFormSetting(item);
return item;
});
if(pageSize>5000){
if (pageSize > 5000) {
rtnData.forEach((item: flowRateListProps) => {
excelDownList.push({
시설코드: item.bscFctCd,
@@ -312,15 +346,15 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow
set((state: FlowRateSearchType) => ({
...state,
FlowRateList: pageSize<5000?{
FlowRateList: pageSize < 5000 ? {
...state.FlowRateList,
flowRateList: rtnData,
flowRateCount: res.count,
isLoading : false,
}:{
flowRateCount: recordCount,
isLoading: false,
} : {
...state.FlowRateList,
excelList: excelDownList,
isLoading : false,
isLoading: false,
},
}))
},
@@ -329,44 +363,48 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow
const inflData = CalcRainEffect(res.data);
const res2 = await fetchFacilityWaterQltyListHist(searchYear, bscFctCd);
const wqltData = CalcRainEffect(res2?.data.wqltObjs);
const wqltData = res2?.data.wqltObjs;
//const wqltData = CalcRainEffect(res2?.data.wqltObjs);
/**
* [(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​
/강우시 일별유입BOD)
* [(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)] / 강우시 일별유입BOD
*/
//let rainInflAmnt = 0;
let sunnyInflAmnt = 0;
let sunnyBod = 0;
//let rainDay = 0;
let sunnyInflAmnt = 0; // 청천시 일별유입유량
let sunnyBod = 0; // 청천시 일별유입BOD
let sunnyDay = 0;
inflData.forEach(item => {
if(item.rainEffectDay == 1){
//rainDay += 1;
//rainInflAmnt += Number(item.inflAmnt);
let rainEffectDay = 0;
wqltData?.forEach(item => {
if (item.infoRnDay == null) item.infoRnDay = 0;
if (Number(item.infoRnDay) >= 3) {
rainEffectDay = 2;
} else {
const msrDt = item.msrDt.replaceAll('-','');
rainEffectDay--;
}
if (rainEffectDay < 0) { //청천시
sunnyDay += 1;
sunnyInflAmnt += Number(item.inflAmnt);
sunnyBod += Number(wqltData.filter((wqitem)=>wqitem.msrDt === msrDt)[0].inflAssctBfrWqltBod);
sunnyBod += Number(item.inflAssctBfrWqltBod);
}
});
//const yearRainAmnt = rainInflAmnt===0?0:rainInflAmnt / rainDay;
const yearSunnyAmnt = sunnyInflAmnt===0?0:sunnyInflAmnt / sunnyDay;
const yearSunnyBod = sunnyBod===0?0:sunnyBod / sunnyDay;
const yearSunnyAmnt = sunnyDay > 0 ? sunnyInflAmnt / sunnyDay : 0; // 청천시 연평균유입유량
const yearSunnyBod = sunnyDay > 0 ? sunnyBod / sunnyDay : 0; // 청천시 연평균유입BOD
//console.log(inflData);
const rtnData = inflData.map((item: FlowRateModalProps) => {
const dayBod = Number(wqltData.filter(wqitem=>wqitem.msrDt === item.msrDt.replaceAll('-',''))[0].inflAssctBfrWqltBod);
const noProcessInflAmnt = roundNumber(((Number(item.inflAmnt) * dayBod) - (yearSunnyAmnt * yearSunnyBod)) / dayBod, 0)
item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0);
item.noProcessInflAmnt = noProcessInflAmnt && Number(noProcessInflAmnt.replaceAll(',','')) > 0 ? noProcessInflAmnt : '';
dataFormSetting(item);
return item;
const targetWqItem = wqltData?.find(wqitem => wqitem.msrDt === item.msrDt.replaceAll('-', ''));
const dayBod = targetWqItem ? Number(targetWqItem.inflAssctBfrWqltBod) : 0;
const noProcessInflAmnt = Math.round(((Number(item.inflAmnt) * dayBod) - (yearSunnyAmnt * yearSunnyBod)) / dayBod)
const totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0);
return {
...item,
totInflAmnt,
noProcessInflAmnt: noProcessInflAmnt && noProcessInflAmnt > 0 ? noProcessInflAmnt : '',
msrDt: (item.msrDt.length === 8 && !item.msrDt.includes('-')) ?
`${item.msrDt.slice(0, 4)}-${item.msrDt.slice(4, 6)}-${item.msrDt.slice(6, 8)}`
: item.msrDt,
};
});
//console.log(rtnData);
set((state: FlowRateSearchType) => ({
...state,
FlowRateModal: {
+41 -8
View File
@@ -4,6 +4,7 @@ import { getFetch, postFetch } from "@/app/components/api";
import { type ApiResponse } from "../underWaterInput";
// import CalcRainEffect from "@/app/components/common/CalcRainEffect";
import { roundUp } from "../common";
// import { fetchSweageOccurListFlow, fetchWtrUsgYmList } from "../sewageOccur";
export type { TableUpperProps };
/**
* 처리시설 연간 운영현황 > 계획하수량 산정지표 현황
@@ -101,14 +102,15 @@ const planSewageList: PlanSewageProps[] = [
* @param oprtngSttsCd : 운영 상태 코드
* @param facilityName : 시설명
*/
const fetchPlanSewageList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
const fetchPlanSewageList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string
, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
const tailStr = partCd ? '/' + partCd + '/' + (nameCd || '0') + '/' + (fcltCpct || '0') + '/' + (operationValue || '0') + '/0' + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
const url = '/prcsFclt/info/plan/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
const res = await getFetch('fo', url);
return { data: res.data, count: res.count }
}
// 분류식화율 구하기 위한 api 호출
// 분류식화율 구하기 위한 api 호출 : 분류식화율 = 분류식지역 면적(㎢) / 처리​구역 면적합계(㎢) × 100
const fetchPlanZoneList = async (searchYear: string, fcltCdList: string[]) => {
try {
const res = await postFetch('fo', '/prcsFclt/info/planZone/' + searchYear, fcltCdList);
@@ -251,19 +253,50 @@ export const planSewageReducer: (set: (fn: (state: PlanSewageType) => PlanSewage
const excelDownList: ExcelType[] = [];
// const data = res.data
const planZoneRes: any = await fetchPlanZoneList(searchYear, fcltCdList);
const planZoneList = planZoneRes?.data;
// 분류식화율 구하기 위한 api 호출 : 분류식화율 = 분류식지역 면적(㎢) / 처리​구역 면적합계(㎢) × 100
// const planZoneRes: any = await fetchPlanZoneList(searchYear, fcltCdList);
// const detailRes: any = await fetchFlow(searchYear, fcltCdList);
//---------
const planZoneList: any[] = [];
const flowDetailList: Record<string, any[]> = {};
// const results: any[] = [];
const flowDetailResults: any[] = [];
for (let idx = 0; idx < fcltCdList.length; idx += 100) {
const slicedItems = fcltCdList.slice(idx, idx + 100);
const result = await fetchPlanZoneList(searchYear, slicedItems); // 분류식화율 구하기 위한 api 호출 : 분류식화율 = 분류식지역 면적(㎢) / 처리​구역 면적합계(㎢) × 100
const flowResult = await fetchFlow(searchYear, slicedItems);
if (result?.status === 200 && Array.isArray(result?.data)) {
planZoneList.push(...result.data);
}
flowDetailResults.push(flowResult);
}
//console.log(results);
// 결과를 합치기
for (const res of flowDetailResults) {
if (res.status === 200 && res.data) {
for (const [key, value] of Object.entries(res.data)) {
const keyStr = String(key);
if (!flowDetailList[keyStr]) flowDetailList[keyStr] = [];
flowDetailList[keyStr].push(...(value as any[]));
}
}
}
//-------
// const planZoneList = planZoneRes?.data;
planZoneList?.forEach(item => {
const planSewageItem = planSewageList.find(item2 => item2.bscFctCd == item.bscFctCd);
if (planSewageItem) {
planSewageItem.sprtProcZoneAr = item.sprtProcZoneAr;
planSewageItem.procZoneSm = item.procZoneSm;
planSewageItem.sprtProcZoneAr = item.sprtProcZoneAr; // 처리구역면적_분류식
planSewageItem.procZoneSm = item.procZoneSm; //처리구역면적합계
}
});
const detailRes: any = await fetchFlow(searchYear, fcltCdList);
//const detailRes: any = await fetchFlow(searchYear, fcltCdList);
for (const item of planSewageList) {
const detailList = detailRes?.data[item.bscFctCd];
// const detailList = detailRes?.data[item.bscFctCd];
const detailList = flowDetailList[item.bscFctCd];
let avgInflAmnt = 0;
let sumInflAmntSunny = 0;
+262 -260
View File
@@ -12,52 +12,52 @@ export type { TableUpperProps };
*/
// 처리구역 리스트
export type ProcessAreaProps = {
swtrmtFcltCd : string,
swtrmtFcltCd: string,
ctpvNm?: string,
sggNm?: string,
swtrmtFcltNm : string,
location : string,
fctCpc : number | '',
fcltCpctSum : number | '',
ruse : boolean,
planYrDt4 : string,
planYr : string,
planYrDc1 : string,
planYrDc2 : string,
planYrDc3 : string,
planYrDc4 : string,
swtrmtFcltNm: string,
location: string,
fctCpc: number | '',
fcltCpctSum: number | '',
ruse: boolean,
planYrDt4: string,
planYr: string,
planYrDc1: string,
planYrDc2: string,
planYrDc3: string,
planYrDc4: string,
/**
* 증설계획
*/
// 기승인(당초4단계), 현재, 변경1~4
planSwageQntSumDt4 : number | '',
planSwageQntSum : number | '',
planSwageQntSumDc1 : number | '',
planSwageQntSumDc2 : number | '',
planSwageQntSumDc3 : number | '',
planSwageQntSumDc4 : number | '',
planSwageQntSumDt4: number | '',
planSwageQntSum: number | '',
planSwageQntSumDc1: number | '',
planSwageQntSumDc2: number | '',
planSwageQntSumDc3: number | '',
planSwageQntSumDc4: number | '',
/**
* 처리인구
*/
// 기승인(당초4단계), 변경1~4
swtrmtPpltnCntDt4 : number | '',
swtrmtPpltnCnt : number | '',
swtrmtPpltnCntDc1 : number | '',
swtrmtPpltnCntDc2 : number | '',
swtrmtPpltnCntDc3 : number | '',
swtrmtPpltnCntDc4 : number | '',
swtrmtPpltnCntDt4: number | '',
swtrmtPpltnCnt: number | '',
swtrmtPpltnCntDc1: number | '',
swtrmtPpltnCntDc2: number | '',
swtrmtPpltnCntDc3: number | '',
swtrmtPpltnCntDc4: number | '',
/**
* 처리구역면적
*/
// 기승인(당초4단계), 변경1~4
swtrmtZoneAreaDt4 : number | '',
swtrmtZoneArea : number | '',
swtrmtZoneAreaDc1 : number | '',
swtrmtZoneAreaDc2 : number | '',
swtrmtZoneAreaDc3 : number | '',
swtrmtZoneAreaDc4 : number | '',
swtrmtZoneAreaDt4: number | '',
swtrmtZoneArea: number | '',
swtrmtZoneAreaDc1: number | '',
swtrmtZoneAreaDc2: number | '',
swtrmtZoneAreaDc3: number | '',
swtrmtZoneAreaDc4: number | '',
// 처리구역
trtDstr : string | '',
trtDstr: string | '',
}
export interface ExcelType {
@@ -89,32 +89,32 @@ export interface ExcelType {
// (2) 처리구역 팝업
// 시설증설 계획
export type FcltyImproveInfoProps = {
planSwageQntSumDt4 : number | '',
planSwageQntSum : number | '',
planSwageQntSumDc1 : number | '',
planSwageQntSumDc2 : number | '',
planSwageQntSumDc3 : number | '',
planSwageQntSumDc4 : number | '',
planSwageQntSumDt4: number | '',
planSwageQntSum: number | '',
planSwageQntSumDc1: number | '',
planSwageQntSumDc2: number | '',
planSwageQntSumDc3: number | '',
planSwageQntSumDc4: number | '',
}
// 처리인구 계획
export type ProcessPopulationProps = {
swtrmtPpltnCntDt4 : number | '',
swtrmtPpltnCnt : number | '',
swtrmtPpltnCntDc1 : number | '',
swtrmtPpltnCntDc2 : number | '',
swtrmtPpltnCntDc3 : number | '',
swtrmtPpltnCntDc4 : number | '',
swtrmtPpltnCntDt4: number | '',
swtrmtPpltnCnt: number | '',
swtrmtPpltnCntDc1: number | '',
swtrmtPpltnCntDc2: number | '',
swtrmtPpltnCntDc3: number | '',
swtrmtPpltnCntDc4: number | '',
}
// 처리구역 계획
export type ProcessAreaPlanProps = {
swtrmtZoneAreaDt4 : number | '',
swtrmtZoneArea : number | '',
swtrmtZoneAreaDc1 : number | '',
swtrmtZoneAreaDc2 : number | '',
swtrmtZoneAreaDc3 : number | '',
swtrmtZoneAreaDc4 : number | '',
trtDstr : string,
swtrmtZoneAreaDt4: number | '',
swtrmtZoneArea: number | '',
swtrmtZoneAreaDc1: number | '',
swtrmtZoneAreaDc2: number | '',
swtrmtZoneAreaDc3: number | '',
swtrmtZoneAreaDc4: number | '',
trtDstr: string,
}
/**====================================
@@ -123,93 +123,93 @@ export type ProcessAreaPlanProps = {
/**
* (1) 메인페이지
*/
*/
// 검색단
const ProcessFacilityLabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '시설상태', '연도별', '권역', '단위유역', '중권역', '환경청별'];
const ProcessFacilityLabelArray: string[] = ['구분', '시도', '시군구', '용량별', '시설명', '시설상태', '연도별', '권역', '단위유역', '중권역', '환경청별'];
// 리스트 헤더(행정별)
const upHeadList1:TableUpperProps[] = [
{ id: "A", title: "행정구역", colSpan:2, rowSpan:2, row:0 },
{ id: "ctpvNm", title: "시도", upName:"upChangeRe", row:2, widthPercent:4 },
{ id: "sggNm", title: "시군구", upName:"upChangeRe", row:2, widthPercent:4 },
{ id: "swtrmtFcltNm", title: "시설명", rowSpan:3, row:0, widthPercent: 6 },
{ id: "location", title: "주소", rowSpan:3, row:0, widthPercent: 12 },
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", rowSpan:3, row:0, widthPercent: 5 },
{ id: "B", title: "시설계획", colSpan:19, row: 0 },
{ id: "C", title: "증설계획(m³/일)", colSpan:6, row: 1 },
{ id: "planSwageQntSumDt4", title: "기승인\n4단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "planSwageQntSum", title: "현재", row:2, align:"right", widthPercent: 3.5 },
{ id: "planSwageQntSumDc1", title: "1단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "planSwageQntSumDc2", title: "2단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "planSwageQntSumDc3", title: "3단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "planSwageQntSumDc4", title: "4단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "D", title: "처리인구(인)", colSpan:6, row:1 },
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "swtrmtPpltnCnt", title: "현재", row:2, align:"right", widthPercent: 3.5 },
{ id: "swtrmtPpltnCntDc1", title: "1단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "swtrmtPpltnCntDc2", title: "2단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "swtrmtPpltnCntDc3", title: "3단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "swtrmtPpltnCntDc4", title: "4단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "E", title: "처리구역(km²)", colSpan:7, row:1 },
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "swtrmtZoneArea", title: "현재", row:2, align:"right", widthPercent: 3.5 },
{ id: "swtrmtZoneAreaDc1", title: "1단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "swtrmtZoneAreaDc2", title: "2단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "swtrmtZoneAreaDc3", title: "3단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "swtrmtZoneAreaDc4", title: "4단계", row:2, align:"right", widthPercent: 3.5 },
{ id: "trtDstr", title: "처리구역", row:2}
const upHeadList1: TableUpperProps[] = [
{ id: "A", title: "행정구역", colSpan: 2, rowSpan: 2, row: 0 },
{ id: "ctpvNm", title: "시도", upName: "upChangeRe", row: 2, widthPercent: 4 },
{ id: "sggNm", title: "시군구", upName: "upChangeRe", row: 2, widthPercent: 4 },
{ id: "swtrmtFcltNm", title: "시설명", rowSpan: 3, row: 0, widthPercent: 6 },
{ id: "location", title: "주소", rowSpan: 3, row: 0, widthPercent: 12 },
{ id: "fctCpc", title: "시설용량(m³/일)", align: "right", rowSpan: 3, row: 0, widthPercent: 5 },
{ id: "B", title: "시설계획", colSpan: 18, row: 0 },
{ id: "C", title: "증설계획(m³/일)", colSpan: 6, row: 1 },
{ id: "planSwageQntSumDt4", title: "기승인\n4단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "planSwageQntSum", title: "현재", row: 2, align: "right", widthPercent: 3.5 },
{ id: "planSwageQntSumDc1", title: "1단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "planSwageQntSumDc2", title: "2단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "planSwageQntSumDc3", title: "3단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "planSwageQntSumDc4", title: "4단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "D", title: "처리인구(인)", colSpan: 6, row: 1 },
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "swtrmtPpltnCnt", title: "현재", row: 2, align: "right", widthPercent: 3.5 },
{ id: "swtrmtPpltnCntDc1", title: "1단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "swtrmtPpltnCntDc2", title: "2단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "swtrmtPpltnCntDc3", title: "3단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "swtrmtPpltnCntDc4", title: "4단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "E", title: "처리구역(km²)", colSpan: 6, row: 1 },
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "swtrmtZoneArea", title: "현재", row: 2, align: "right", widthPercent: 3.5 },
{ id: "swtrmtZoneAreaDc1", title: "1단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "swtrmtZoneAreaDc2", title: "2단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "swtrmtZoneAreaDc3", title: "3단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "swtrmtZoneAreaDc4", title: "4단계", row: 2, align: "right", widthPercent: 3.5 },
{ id: "trtDstr", title: "처리구역", row: 0, rowSpan: 3 } // row - header에서 몇번째 행인지
];
const processAreaList:ProcessAreaProps[] = [
const processAreaList: ProcessAreaProps[] = [
]
/**
* 처리구역정보 상세팝업
*/
*/
// 시설증설 계획 (헤더)
const upHeadListFcltyImproveInfo:TableUpperProps[] = [
{ id: "planSwageQntSumDt4", title: "기승인\n4단계(m³/일)", rowSpan:2, row:0, align:"right"},
{ id: "A", title: "증설계획(m³/일)", colSpan:5, row:0},
{ id: "planSwageQntSum", title: "현재", row:1, align:"right"},
{ id: "planSwageQntSumDc1", title: "1단계", row:1, align:"right"},
{ id: "planSwageQntSumDc2", title: "2단계", row:1, align:"right"},
{ id: "planSwageQntSumDc3", title: "3단계", row:1, align:"right"},
{ id: "planSwageQntSumDc4", title: "4단계", row:1, align:"right"},
const upHeadListFcltyImproveInfo: TableUpperProps[] = [
{ id: "planSwageQntSumDt4", title: "기승인\n4단계(m³/일)", rowSpan: 2, row: 0, align: "right" },
{ id: "A", title: "증설계획(m³/일)", colSpan: 5, row: 0 },
{ id: "planSwageQntSum", title: "현재", row: 1, align: "right" },
{ id: "planSwageQntSumDc1", title: "1단계", row: 1, align: "right" },
{ id: "planSwageQntSumDc2", title: "2단계", row: 1, align: "right" },
{ id: "planSwageQntSumDc3", title: "3단계", row: 1, align: "right" },
{ id: "planSwageQntSumDc4", title: "4단계", row: 1, align: "right" },
];
// 시설증설 계획 (리스트)
const gridListFcltyImproveInfo:FcltyImproveInfoProps[] = [
const gridListFcltyImproveInfo: FcltyImproveInfoProps[] = [
];
// 처리인구 계획 (헤더)
const upHeadListProcessPopulation:TableUpperProps[] = [
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계(인)", rowSpan:2, row:0, align:"right"},
{ id: "A", title: "처리인구(인)", colSpan:5, row:0},
{ id: "swtrmtPpltnCnt", title: "현재", row:1, align:"right"},
{ id: "swtrmtPpltnCntDc1", title: "1단계", row:1, align:"right"},
{ id: "swtrmtPpltnCntDc2", title: "2단계", row:1, align:"right"},
{ id: "swtrmtPpltnCntDc3", title: "3단계", row:1, align:"right"},
{ id: "swtrmtPpltnCntDc4", title: "4단계", row:1, align:"right"},
const upHeadListProcessPopulation: TableUpperProps[] = [
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계(인)", rowSpan: 2, row: 0, align: "right" },
{ id: "A", title: "처리인구(인)", colSpan: 5, row: 0 },
{ id: "swtrmtPpltnCnt", title: "현재", row: 1, align: "right" },
{ id: "swtrmtPpltnCntDc1", title: "1단계", row: 1, align: "right" },
{ id: "swtrmtPpltnCntDc2", title: "2단계", row: 1, align: "right" },
{ id: "swtrmtPpltnCntDc3", title: "3단계", row: 1, align: "right" },
{ id: "swtrmtPpltnCntDc4", title: "4단계", row: 1, align: "right" },
];
// 처리인구 계획 (리스트)
const gridListProcessPopulation:ProcessPopulationProps[] = [
const gridListProcessPopulation: ProcessPopulationProps[] = [
];
// 처리구역 계획 (헤더)
const upHeadListProcessAreaPlan:TableUpperProps[] = [
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계(km²)", rowSpan:2, row:0, align:"right"},
{ id: "A", title: "처리면적(km²)", colSpan:6, row:0, align:"right"},
{ id: "swtrmtZoneArea", title: "현재", row:1, align:"right"},
{ id: "swtrmtZoneAreaDc1", title: "1단계", row:1, align:"right"},
{ id: "swtrmtZoneAreaDc2", title: "2단계", row:1, align:"right"},
{ id: "swtrmtZoneAreaDc3", title: "3단계", row:1, align:"right"},
{ id: "swtrmtZoneAreaDc4", title: "4단계", row:1, align:"right"},
{ id: "trtDstr", title: "처리구역", row:1}
const upHeadListProcessAreaPlan: TableUpperProps[] = [
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계(km²)", rowSpan: 2, row: 0, align: "right" },
{ id: "A", title: "처리면적(km²)", colSpan: 5, row: 0, align: "right" },
{ id: "swtrmtZoneArea", title: "현재", row: 1, align: "right" },
{ id: "swtrmtZoneAreaDc1", title: "1단계", row: 1, align: "right" },
{ id: "swtrmtZoneAreaDc2", title: "2단계", row: 1, align: "right" },
{ id: "swtrmtZoneAreaDc3", title: "3단계", row: 1, align: "right" },
{ id: "swtrmtZoneAreaDc4", title: "4단계", row: 1, align: "right" },
// { id: "trtDstr", title: "처리구역", row: 1 }
];
// 시설증설 계획 (리스트)
const gridListProcessAreaPlan:ProcessAreaPlanProps[] = [
const gridListProcessAreaPlan: ProcessAreaPlanProps[] = [
];
/**====================================
@@ -227,113 +227,115 @@ const gridListProcessAreaPlan:ProcessAreaPlanProps[] = [
}
}; */
const fetchFacilityDetailInfo = async (pageNo:number, pageSize:number, swtrmtFcltCd: string[]) : Promise<{data:any[], count:number}> => {
try {
const res = await postFetch('fo', '/prcsFclt/ruseInfo/'+pageNo+'/'+pageSize, swtrmtFcltCd);
return {data: res.data, count:res.count};
} catch (error) {
console.error('시설정보 데이터를 가져오는데 실패했습니다:', error);
return {data:[], count:0};
}
const fetchFacilityDetailInfo = async (pageNo: number, pageSize: number, swtrmtFcltCd: string[]): Promise<{ data: any[], count: number }> => {
try {
const res = await postFetch('fo', '/prcsFclt/ruseInfo/' + pageNo + '/' + pageSize, swtrmtFcltCd);
return { data: res.data, count: res.count };
} catch (error) {
console.error('시설정보 데이터를 가져오는데 실패했습니다:', error);
return { data: [], count: 0 };
}
};
// 시설정보 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
const fetchProcessAreaList = async (pageNo : number, pageSize : number, ctpvNm : string | undefined, sggNm : string | undefined, targetYear : string | undefined, set : (fn: (state: ProcessAreaType) => ProcessAreaType) => void): Promise<{data:any[], count:number}> => {
try {
const res = await fetchPlanInfo(targetYear, ctpvNm, sggNm, undefined);
if(res && res.length > 0){
const enrichedData = await Promise.all(
res.map(async (item: ProcessAreaProps) => {
upHeadList1.forEach((head:TableUpperProps) => {
/* if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = '현재\n(' + item.planYr + '년)';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = '1단계\n(' + item.planYrDc1 + '년)';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = '2단계\n(' + item.planYrDc2 + '년)';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = '3단계\n(' + item.planYrDc3 + '년)';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = '4단계\n(' + item.planYrDc4 + '년)';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = '기승인\n4단계(' + item.planYrDt4 + '년)';
} */
if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = '현재';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = '1단계';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = '2단계';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = '3단계';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = '4단계';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = '기승인\n4단계';
}
});
return item;
const fetchProcessAreaList = async (pageNo: number, pageSize: number, ctpvNm: string | undefined, sggNm: string | undefined
, targetYear: string | undefined, set: (fn: (state: ProcessAreaType) => ProcessAreaType) => void): Promise<{ data: any[], count: number }> => {
try {
const res = await fetchPlanInfo(targetYear, ctpvNm, sggNm, undefined);
if (res && res.length > 0) {
const enrichedData = await Promise.all(
res.map(async (item: ProcessAreaProps) => {
upHeadList1.forEach((head: TableUpperProps) => {
/* if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = '현재\n(' + item.planYr + '년)';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = '1단계\n(' + item.planYrDc1 + '년)';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = '2단계\n(' + item.planYrDc2 + '년)';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = '3단계\n(' + item.planYrDc3 + '년)';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = '4단계\n(' + item.planYrDc4 + '년)';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = '기승인\n4단계(' + item.planYrDt4 + '년)';
} */
if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = '현재';
} else if (head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = '1단계';
} else if (head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = '2단계';
} else if (head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = '3단계';
} else if (head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = '4단계';
} else if (head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = '기승인\n4단계';
}
});
return item;
})
);
const startIndex = (pageNo - 1) * pageSize;
const endIndex = startIndex + pageSize;
const paginatedData = enrichedData.slice(startIndex, endIndex);
const fcltyCdList: string[] = [];
paginatedData.forEach(item => {
fcltyCdList.push(item.swtrmtFcltCd);
})
);
const startIndex = (pageNo - 1) * pageSize;
const endIndex = startIndex + pageSize;
const paginatedData = enrichedData.slice(startIndex, endIndex);
const fcltyCdList : string[]= [];
paginatedData.forEach(item => {
fcltyCdList.push(item.swtrmtFcltCd);
})
const detailFcltylist = await fetchFacilityDetailInfo(1, pageSize, fcltyCdList);
paginatedData.forEach(item => {
const filterdData = detailFcltylist.data.filter(fItem=>fItem.bscFctCd === item.swtrmtFcltCd)[0] || null;
item.fcltCpctSum = filterdData ? filterdData.fctCpc : '';
item.location = filterdData ? filterdData.addr : '';
item.ctpvNm = filterdData ? filterdData.sido : '';
item.sggNm = filterdData ? filterdData.gugun : '';
});
return {data: paginatedData, count: enrichedData.length};
}else{
return {data: [], count: 0};
}
} catch (error) {
console.error('시설계획정보를 가져오는데 실패했습니다:', error);
set((state) => ({
...state,
ProcessArea : {
...state.ProcessArea,
isLoading : false
const detailFcltylist = await fetchFacilityDetailInfo(1, pageSize, fcltyCdList);
paginatedData.forEach(item => {
const filterdData = detailFcltylist.data.filter(fItem => fItem.bscFctCd === item.swtrmtFcltCd)[0] || null;
item.fcltCpctSum = filterdData ? filterdData.fctCpc : '';
item.location = filterdData ? filterdData.addr : '';
item.ctpvNm = filterdData ? filterdData.sido : '';
item.sggNm = filterdData ? filterdData.gugun : '';
item.trtDstr = filterdData ? filterdData.trtDstr : '';
});
return { data: paginatedData, count: enrichedData.length };
} else {
return { data: [], count: 0 };
}
}));
return {data: [], count: 0};
}
} catch (error) {
console.error('시설계획정보를 가져오는데 실패했습니다:', error);
set((state) => ({
...state,
ProcessArea: {
...state.ProcessArea,
isLoading: false
}
}));
return { data: [], count: 0 };
}
};
/**====================================
* Store - expaort
=====================================*/
export type ProcessAreaActions = {
searchProcessAreaList : (pageNo: number, pageSize: number, ctpvNm?:string, sggNm?:string, targetYear?:string) => void;
initModalData : (swtrmtFcltCd:string) => void;
searchProcessAreaList: (pageNo: number, pageSize: number, ctpvNm?: string, sggNm?: string, targetYear?: string) => void;
initModalData: (swtrmtFcltCd: string) => void;
}
export type ProcessAreaType = {
ProcessAreaSearch: {
isInit: boolean;
processFacilityLabelArray:string[];
processFacilityLabelArray: string[];
},
ProcessArea : {
ProcessArea: {
isInit: boolean;
upHeadList1: TableUpperProps[];
processAreaList: ProcessAreaProps[];
processAreaCount: number;
excelList: ExcelType[];
isLoading: boolean;
},
},
ProcessAreaDetail : {
ProcessAreaDetail: {
isInit: boolean;
upHeadListFcltyImproveInfo: TableUpperProps[];
gridListFcltyImproveInfo: FcltyImproveInfoProps[]; // Changed from facilityAreaProps to ProcessAreaProps
@@ -350,23 +352,23 @@ export const processAreaInitState: ProcessAreaType = {
processFacilityLabelArray: ProcessFacilityLabelArray,
},
ProcessArea : {
isInit : false,
upHeadList1 : upHeadList1,
processAreaList : processAreaList,
processAreaCount : 0,
excelList : [],
isLoading : true,
ProcessArea: {
isInit: false,
upHeadList1: upHeadList1,
processAreaList: processAreaList,
processAreaCount: 0,
excelList: [],
isLoading: true,
},
ProcessAreaDetail : {
isInit : false,
upHeadListFcltyImproveInfo : upHeadListFcltyImproveInfo,
gridListFcltyImproveInfo : gridListFcltyImproveInfo,
upHeadListProcessPopulation : upHeadListProcessPopulation,
gridListProcessPopulation : gridListProcessPopulation,
upHeadListProcessAreaPlan : upHeadListProcessAreaPlan,
gridListProcessAreaPlan : gridListProcessAreaPlan,
ProcessAreaDetail: {
isInit: false,
upHeadListFcltyImproveInfo: upHeadListFcltyImproveInfo,
gridListFcltyImproveInfo: gridListFcltyImproveInfo,
upHeadListProcessPopulation: upHeadListProcessPopulation,
gridListProcessPopulation: gridListProcessPopulation,
upHeadListProcessAreaPlan: upHeadListProcessAreaPlan,
gridListProcessAreaPlan: gridListProcessAreaPlan,
},
}
@@ -375,14 +377,14 @@ type SetStateFunction = (state: ProcessAreaType | ((state: ProcessAreaType) => P
export type ProcessAreaStore = ProcessAreaType & ProcessAreaActions;
export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set: SetStateFunction) => {
export const processAreaReducer: (set: SetStateFunction) => ProcessAreaActions = (set: SetStateFunction) => {
return {
/**
* 시설정보 리스트 데이터 호출
* @param pageNo : 페이지 번호
* @param pageSize : 페이지 크기
*/
searchProcessAreaList: async ( pageNo:number, pageSize:number, ctpvNm?:string, sggNm?:string, targetYear?:string) => {
searchProcessAreaList: async (pageNo: number, pageSize: number, ctpvNm?: string, sggNm?: string, targetYear?: string) => {
set((state: ProcessAreaType) => ({
...state,
ProcessArea: {
@@ -391,12 +393,12 @@ export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set:
},
}));
const res = await fetchProcessAreaList(pageNo, pageSize, ctpvNm, sggNm, targetYear, set);
res.data.forEach((item:ProcessAreaProps) => {
res.data.forEach((item: ProcessAreaProps) => {
item.fctCpc = item.fcltCpctSum;
DataForm({ type: 'float1', column: 'fctCpc', item:item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
})
const excelDownList: ExcelType[] = [];
if(pageSize>5000){
if (pageSize > 5000) {
res.data.forEach(item => {
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : '';
excelDownList.push({
@@ -425,78 +427,78 @@ export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set:
처리구역: item.trtDstr
});
});
}else{
} else {
res.data.forEach(item => {
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : '';
})
}
set((state:ProcessAreaType) => ({
set((state: ProcessAreaType) => ({
...state,
ProcessArea: pageSize<5000?{
ProcessArea: pageSize < 5000 ? {
...state.ProcessArea,
processAreaList: res.data,
processAreaCount: res.count,
isLoading : false,
}:{
isLoading: false,
} : {
...state.ProcessArea,
excelList: excelDownList,
isLoading : false,
isLoading: false,
},
}))
},
initModalData: async (swtrmtFcltCd:string) => {
initModalData: async (swtrmtFcltCd: string) => {
set((state: ProcessAreaType) => {
const rtnData = state.ProcessArea.processAreaList.find((item: ProcessAreaProps) => item.swtrmtFcltCd === swtrmtFcltCd);
if (rtnData) {
upHeadListFcltyImproveInfo.forEach((head:TableUpperProps) => {
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = rtnData.planYr? '현재\n(' + rtnData.planYr + '년)':head.title = '현재';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = rtnData.planYrDc1? '1단계\n(' + rtnData.planYrDc1 + '년)':head.title = '1단계';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = rtnData.planYrDc2? '2단계\n(' + rtnData.planYrDc2 + '년)':head.title = '2단계';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = rtnData.planYrDc3? '3단계\n(' + rtnData.planYrDc3 + '년)':head.title = '3단계';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = rtnData.planYrDc4? '4단계\n(' + rtnData.planYrDc4 + '년)':head.title = '4단계';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = rtnData.planYrDt4? '기승인\n4단계(' + rtnData.planYrDt4 + '년)':head.title = '기승인\n4단계';
upHeadListFcltyImproveInfo.forEach((head: TableUpperProps) => {
if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = rtnData.planYr ? '현재\n(' + rtnData.planYr + '년)' : head.title = '현재';
} else if (head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = rtnData.planYrDc1 ? '1단계\n(' + rtnData.planYrDc1 + '년)' : head.title = '1단계';
} else if (head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = rtnData.planYrDc2 ? '2단계\n(' + rtnData.planYrDc2 + '년)' : head.title = '2단계';
} else if (head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = rtnData.planYrDc3 ? '3단계\n(' + rtnData.planYrDc3 + '년)' : head.title = '3단계';
} else if (head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = rtnData.planYrDc4 ? '4단계\n(' + rtnData.planYrDc4 + '년)' : head.title = '4단계';
} else if (head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = rtnData.planYrDt4 ? '기승인\n4단계(' + rtnData.planYrDt4 + '년)' : head.title = '기승인\n4단계';
}
});
upHeadListProcessAreaPlan.forEach((head:TableUpperProps) => {
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = rtnData.planYr? '현재\n(' + rtnData.planYr + '년)':head.title = '현재';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = rtnData.planYrDc1?'1단계\n(' + rtnData.planYrDc1 + '년)':head.title = '1단계';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = rtnData.planYrDc2?'2단계\n(' + rtnData.planYrDc2 + '년)':head.title = '2단계';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = rtnData.planYrDc3? '3단계\n(' + rtnData.planYrDc3 + '년)':head.title = '3단계';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = rtnData.planYrDc4?'4단계\n(' + rtnData.planYrDc4 + '년)':head.title = '4단계';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = rtnData.planYrDt4?'기승인\n4단계(' + rtnData.planYrDt4 + '년)':head.title = '기승인\n4단계';
upHeadListProcessAreaPlan.forEach((head: TableUpperProps) => {
if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = rtnData.planYr ? '현재\n(' + rtnData.planYr + '년)' : head.title = '현재';
} else if (head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = rtnData.planYrDc1 ? '1단계\n(' + rtnData.planYrDc1 + '년)' : head.title = '1단계';
} else if (head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = rtnData.planYrDc2 ? '2단계\n(' + rtnData.planYrDc2 + '년)' : head.title = '2단계';
} else if (head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = rtnData.planYrDc3 ? '3단계\n(' + rtnData.planYrDc3 + '년)' : head.title = '3단계';
} else if (head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = rtnData.planYrDc4 ? '4단계\n(' + rtnData.planYrDc4 + '년)' : head.title = '4단계';
} else if (head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = rtnData.planYrDt4 ? '기승인\n4단계(' + rtnData.planYrDt4 + '년)' : head.title = '기승인\n4단계';
}
});
upHeadListProcessPopulation.forEach((head:TableUpperProps) => {
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = rtnData.planYr?'현재\n(' + rtnData.planYr + '년)':head.title = '현재';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = rtnData.planYrDc1?'1단계\n(' + rtnData.planYrDc1 + '년)':head.title = '1단계';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = rtnData.planYrDc2?'2단계\n(' + rtnData.planYrDc2 + '년)':head.title = '2단계';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = rtnData.planYrDc3?'3단계\n(' + rtnData.planYrDc3 + '년)':head.title = '3단계';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = rtnData.planYrDc4?'4단계\n(' + rtnData.planYrDc4 + '년)':head.title = '4단계';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = rtnData.planYrDt4?'기승인\n4단계(' + rtnData.planYrDt4 + '년)':head.title = '기승인\n4단계';
upHeadListProcessPopulation.forEach((head: TableUpperProps) => {
if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = rtnData.planYr ? '현재\n(' + rtnData.planYr + '년)' : head.title = '현재';
} else if (head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = rtnData.planYrDc1 ? '1단계\n(' + rtnData.planYrDc1 + '년)' : head.title = '1단계';
} else if (head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = rtnData.planYrDc2 ? '2단계\n(' + rtnData.planYrDc2 + '년)' : head.title = '2단계';
} else if (head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = rtnData.planYrDc3 ? '3단계\n(' + rtnData.planYrDc3 + '년)' : head.title = '3단계';
} else if (head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = rtnData.planYrDc4 ? '4단계\n(' + rtnData.planYrDc4 + '년)' : head.title = '4단계';
} else if (head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = rtnData.planYrDt4 ? '기승인\n4단계(' + rtnData.planYrDt4 + '년)' : head.title = '기승인\n4단계';
}
});
// 시설증설 계획 데이터 생성
const fcltyImproveInfo: FcltyImproveInfoProps = {
planSwageQntSumDt4: rtnData.planSwageQntSumDt4,
+15 -4
View File
@@ -113,7 +113,10 @@ export type fcltyHistInfoProps = {
sitArea: number,
trtDstrArea: number,
swrTrtPopl: number,
fctCpc: number | ''
fctCpc: number | '',
trtSrsHanNm?: string, // 공법구분
trtMocHanNm?: string, // 공법계열
trtFrfHanNm?: string, // 방법
}
// 시설 수질정보
@@ -328,6 +331,9 @@ const upHeadListFcltyHistInfo: TableUpperProps[] = [
{ id: "trlrnCmplDt", title: "시운전완료일" },
{ id: "rnDt", title: "가동개시일" },
{ id: "fctCpc", title: "시설용량(m³/일)", align: 'right' },
{ id: "trtSrsHanNm", title: "공법구분" },
{ id: "trtMocHanNm", title: "공법계열" },
{ id: "trtFrfHanNm", title: "방법" },
];
// 시설 이력관리 (리스트)
@@ -344,7 +350,10 @@ const gridListFcltyHistInfo: fcltyHistInfoProps[] = [
sitArea: 0,
trtDstrArea: 0,
swrTrtPopl: 0,
fctCpc: 860000
fctCpc: 860000,
trtFrfHanNm: "",
trtMocHanNm: "",
trtSrsHanNm: "",
}
];
@@ -418,7 +427,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<string, unknown>) => {
@@ -900,4 +911,4 @@ export const processFacilityReducer: (set: SetStateFunction) => ProcessFacilityA
}
}
}
}
}
+25 -7
View File
@@ -322,15 +322,33 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio
fcltCdList.push(item.bscFctCd);
});
const rdiiDetailListRes : any = await fetchFacilityRdiiDetailList(searchYear, fcltCdList);
console.log(rdiiDetailListRes);
// const rdiiDetailListRes : any = await fetchFacilityRdiiDetailList(searchYear, fcltCdList);
//---------
const rainDetailList: Record<string, any[]> = {};
const results: any[] = [];
for (let idx = 0; idx < fcltCdList.length; idx += 100) {
const slicedItems = fcltCdList.slice(idx, idx + 100);
const result = await fetchFacilityRdiiDetailList(searchYear, slicedItems);
results.push(result);
}
//console.log(results);
// 결과를 합치기
for (const res of results) {
if (res.status === 200 && res.data) {
for (const [key, value] of Object.entries(res.data)) {
const keyStr = String(key);
if (!rainDetailList[keyStr]) rainDetailList[keyStr] = [];
rainDetailList[keyStr].push(...(value as any[]));
}
}
}
//-------
// console.log(rdiiDetailListRes);
for (const item of rtnData) {
//const fcltyCd = item.bscFctCd;
//const res: any = await fetchFacilityWaterQltyListHist(searchYear, fcltyCd);
//const rdiiDetailList = res.data.wqltObjs;
const rdiiDetailList = rdiiDetailListRes?.data[item.bscFctCd];
//console.log(rdiiDetailListRes);
// const rdiiDetailList = rdiiDetailListRes?.data[item.bscFctCd];
const rdiiDetailList = rainDetailList[item.bscFctCd];
let rtnWinterInflBod = 0;
let rtnSummerBodInfl = 0;
+70 -117
View File
@@ -4,6 +4,7 @@ import { roundNumber } from "@/app/components/common/DataForm";
import { OSU_PERCENT } from "../common";
import type { TableUpperProps } from "../dashboard";
import { fetchFacilityListInit } from "../processFacility";
// import { fetchFacilityRainDetailList } from "../facilityPrecipitation";
export type { TableUpperProps };
/**
@@ -29,7 +30,7 @@ export type SewageOccurProps = {
mdmbsn: string,
msrDt: string,
}
export type modalTableType = { msrDt: string, waterUsage: number, swageChangePercent: number, estimationSewage: number };
export type modalTableType = { msrDt: string, waterUsage: number, swageChangePercent: number, estimationSewage: number, }
export type SewageOccurDetailProps = {
cnt: number,
sum: number,
@@ -39,6 +40,8 @@ export type SewageOccurDetailProps = {
sumWtrUsg: number, // 물사용량 합
avgWtrUsg: number, // 일평균 물사용량
monWtrUsg: number, // 월 물사용량
maxEstSewerage: number, // 최대 오수발생량 추정
minEstSewerage: number, // 최소 오수발생량 추정
}
export type WtrUsgYmProps = {
bscFctCd: string, // 처리구역시설코드
@@ -326,16 +329,52 @@ export const sewageOccurReducer: (set: any) => SewageOccurActions = (set: any) =
});
});
const soccurDetailRes: any = await fetchSweageOccurListFlow(searchYear, fcltCdList);
const wtrUsgYmRes: any = await fetchWtrUsgYmList(searchYear, fcltCdList);
// const wtrUsgMap : Record<string, number> = {};
// wtrUsgRes.data.forEach(fclt => {
// wtrUsgMap[fclt.bscFctCd] = fclt.wtrUsg;
// });
// const soccurDetailRes: any = await fetchSweageOccurListFlow(searchYear, fcltCdList);
// const wtrUsgYmRes: any = await fetchWtrUsgYmList(searchYear, fcltCdList);
//---------
const rainDetailList: Record<string, any[]> = {};
const wtrDetailList: Record<string, any[]> = {};
const results: any[] = [];
const wtrResults: any[] = [];
for (let idx = 0; idx < fcltCdList.length; idx += 100) {
const slicedItems = fcltCdList.slice(idx, idx + 100);
const result = await fetchSweageOccurListFlow(searchYear, slicedItems);
const wtrResult = await fetchWtrUsgYmList(searchYear, slicedItems);
results.push(result);
wtrResults.push(wtrResult);
}
//console.log(results);
// 결과를 합치기
for (const res of results) {
if (res.status === 200 && res.data) {
for (const [key, value] of Object.entries(res.data)) {
const keyStr = String(key);
//rainDetailList[keyStr] = [...(rainDetailList[keyStr] || []), ...(value as any[])];
if (!rainDetailList[keyStr]) rainDetailList[keyStr] = [];
rainDetailList[keyStr].push(...(value as any[]));
}
}
}
for (const res of wtrResults) {
if (res.status === 200 && res.data) {
for (const [key, value] of Object.entries(res.data)) {
const keyStr = String(key);
// wtrDetailList[keyStr] = [...(wtrDetailList[keyStr] || []), ...(value as any[])];
if (!wtrDetailList[keyStr]) wtrDetailList[keyStr] = [];
wtrDetailList[keyStr].push(...(value as any[]));
}
}
}
//-------
let maxEstimationSewage = 0, minEstimationSewage = 999999999;
for (const item of sewageOccurPropsList) {
const detailList = soccurDetailRes?.data[item.bscFctCd];
const wtrUsgYmList = wtrUsgYmRes?.data[item.bscFctCd];
//const detailList = soccurDetailRes?.data[item.bscFctCd];
// const wtrUsgYmList = wtrUsgYmRes?.data[item.bscFctCd];
const detailList = rainDetailList[item.bscFctCd];
const wtrUsgYmList = wtrDetailList[item.bscFctCd];
item.swageChangePercent = 90;
let sumChungcunDay = 0; // 청천일수
@@ -367,18 +406,16 @@ export const sewageOccurReducer: (set: any) => SewageOccurActions = (set: any) =
// console.log("totWaterUsage:", totWaterUsage);
const count = detailList ? detailList.length : 0;
const avg = count == 0 ? 0 : totWaterUsage / count; // 일평균 유입량
item.waterUsage = parseFloat((avg * 0.65).toFixed(2)); // 물사용량 = 일평균 유입량 * 65%
const avg = count == 0 ? 0 : totWaterUsage / count; // 연간 하수유입량(m³/일)
item.waterUsage = parseFloat((avg * 0.65).toFixed(2)); // 물사용량 = 연간 하수유입량(m³/일) * 65% : 실제 수용가의 물사용량 없는 경우
if (wtrUsgYearTotal > 0 && wtrUsgYearDays > 0) {
item.waterUsage = wtrUsgYearDays > 0 ? wtrUsgYearTotal / wtrUsgYearDays : 0; // 일평균 물사용량
item.waterUsage = wtrUsgYearDays > 0 ? wtrUsgYearTotal / wtrUsgYearDays : 0; // 일평균 물사용량: 실제 수용가의 물사용량
}
item.sewageInputYear = parseFloat(avg.toFixed(2)); // 연간 하수유입량(m³/일)
item.sewageInputChungchun = parseFloat((chungcunSumFlow === 0 ? 0 : (chungcunSumFlow / sumChungcunDay)).toFixed(2)); // 청천시 하수유입량
item.estimationSewage = parseFloat((item.waterUsage * OSU_PERCENT).toFixed(2)); // 오수발생량 추정(m³/일)
if (item.bscFctCd === '11200PB001R') {
console.log('chungcunSumFlow:', chungcunSumFlow);
console.log('sumChungcunDay:', sumChungcunDay);
}
if (item.estimationSewage > maxEstimationSewage) maxEstimationSewage = item.estimationSewage;
if (item.estimationSewage < minEstimationSewage) minEstimationSewage = item.estimationSewage;
// 반올림 처리
["fctCpc", "waterUsage", "swageChangePercent", "estimationSewage", "sewageInputYear", "sewageInputChungchun"].forEach(
(key) => (item[key] = roundNumber(item[key], 0))
@@ -427,93 +464,11 @@ export const sewageOccurReducer: (set: any) => SewageOccurActions = (set: any) =
}));
}
/* 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, startYm?: string, endYm?: string) => {
const fcltCdList = [bscFctCd];
const wtrUsgRes: any = await fetchWtrUsgYmList(searchYear, fcltCdList);
const wtrUsgRes: any = await fetchWtrUsgYmList(searchYear, fcltCdList); // 수용가의 실제 물사용량
const res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear);
const monthData: SewageOccurDetailProps[] = [];
let tot = 0, cnt = 0;
@@ -554,15 +509,15 @@ export const sewageOccurReducer: (set: any) => SewageOccurActions = (set: any) =
} else {
monthData[monthIdx] = {
cnt: 1, sum: Number(item.inflAmnt), yr: item.msrDt.substring(0, 4)
, usage: 0, cntWtrUsg: 0, sumWtrUsg: 0, avgWtrUsg: 0, monWtrUsg: 0
, usage: 0, cntWtrUsg: 0, sumWtrUsg: 0, avgWtrUsg: 0, monWtrUsg: 0, maxEstSewerage: 0, minEstSewerage: 999999999
};
}
}
tot += Number(item.inflAmnt)
tot += Number(item.inflAmnt); // 연간 유입량
cnt++
});
// 물사용량
// 수용가 실제 물사용량
let totWtrUsg = 0;
let cntWtrUsg = 0;
if (wtrUsgRes && wtrUsgRes.data && wtrUsgRes.data[bscFctCd]) {
@@ -582,25 +537,23 @@ export const sewageOccurReducer: (set: any) => SewageOccurActions = (set: any) =
const tableData: modalTableType[] = []
let maxWaterUsage = 0;
let minWaterUsage = 9999999999;
let maxWaterUsage = 0, minWaterUsage = 9999999999;
let maxEstSewage = 0, minEstSewage = 9999999999;
let avgWaterUsage = 0;
monthData.forEach((item, index) => {
item.avgWtrUsg = item.sum / item.cnt * 0.65; // 일평균 물사용량 = 일평균유입수 * 0.65
if (item.sumWtrUsg > 0 && item.cntWtrUsg > 0) item.avgWtrUsg = item.sumWtrUsg / item.cntWtrUsg;
item.avgWtrUsg = item.sum / item.cnt * 0.65; // 일평균 물사용량 = 일평균유입수 * 0.65 : 수용가 실제 물사용량이 없으면
if (item.sumWtrUsg > 0 && item.cntWtrUsg > 0) item.avgWtrUsg = item.sumWtrUsg / item.cntWtrUsg; //수용가 실제 물사용량이 있는 경우
const estSewage = Math.round(item.avgWtrUsg * OSU_PERCENT * 1) / 1; // 오수발생량 추정
tableData.push({
msrDt: item.yr + '-' + (index + 1 >= 10 ? String(index + 1) : '0' + (index + 1)),
waterUsage: Math.round(item.avgWtrUsg * 1) / 1,
swageChangePercent: OSU_PERCENT * 100,//(Math.round((item.usage/item.usage*OSU_PERCENT) * 100) / 100) * 100,
estimationSewage: Math.round(item.avgWtrUsg * OSU_PERCENT * 1) / 1
swageChangePercent: OSU_PERCENT * 100, //오수전환율 (Math.round((item.usage/item.usage*OSU_PERCENT) * 100) / 100) * 100,
estimationSewage: estSewage,
})
if (item.avgWtrUsg > maxWaterUsage) {
maxWaterUsage = item.avgWtrUsg;
}
if (item.avgWtrUsg < minWaterUsage) {
minWaterUsage = item.avgWtrUsg;
}
if (item.avgWtrUsg > maxWaterUsage) maxWaterUsage = item.avgWtrUsg; // 물사용량 최대
if (item.avgWtrUsg < minWaterUsage) minWaterUsage = item.avgWtrUsg; // 물사용량 최소
if (maxEstSewage < estSewage) maxEstSewage = estSewage; // 오수발생량 최대
if (minEstSewage > estSewage) minEstSewage = estSewage; // 오수발생량 최소
});
avgWaterUsage = tot / cnt * 0.65
@@ -617,13 +570,13 @@ export const sewageOccurReducer: (set: any) => SewageOccurActions = (set: any) =
msrDt: '최대',
waterUsage: roundNumber(Math.round(maxWaterUsage * 100) / 100, 0),
swageChangePercent: OSU_PERCENT * 100,
estimationSewage: roundNumber(Math.round(maxWaterUsage * OSU_PERCENT * 1) / 1, 0),
estimationSewage: roundNumber(maxEstSewage / 1, 0),
},
{
msrDt: '최소',
waterUsage: roundNumber(Math.round(minWaterUsage * 100) / 100, 0),
swageChangePercent: OSU_PERCENT * 100,
estimationSewage: roundNumber(Math.round(minWaterUsage * OSU_PERCENT * 1) / 1, 0),
estimationSewage: roundNumber(minEstSewage / 1, 0),
},
...tableData
]
+21 -20
View File
@@ -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<FoStore>()((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<FoStore>()((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 등록하는 부분
+332 -303
View File
@@ -5,20 +5,21 @@ import type { ExcelType, UnderWaterInputModalProps, UnderWaterProps, WtrUsgYmPro
// import CalcRainEffect from "@/app/components/common/CalcRainEffect";
import { OSU_PERCENT } from "../common";
import { fetchFacilityListInit } from "../processFacility";
import { getDaysInMonth } from "@/app/components/common/DataForm";
export type { TableUpperProps };
// SewageOccurDetailProps 타입을 여기에 정의
export type SewageOccurDetailProps = {
cnt : number,
sum : number,
yr:string,
usage:number, // 일평균 유입량
sunnyCnt : number,
sunnyInflAmnt : number,
sunnyAvgInflAmnt : number, // 청천시 일평균 유입량
cntWtrUsg : number, // 물사용량 일자수
sumWtrUsg : number, // 물사용량 합
avgWtrUsg:number, // 일평균 물사용량
cnt: number,
sum: number,
yr: string,
usage: number, // 일평균 유입량
sunnyCnt: number,
sunnyInflAmnt: number,
sunnyAvgInflAmnt: number, // 청천시 일평균 유입량
cntWtrUsg: number, // 물사용량 일자수
sumWtrUsg: number, // 물사용량 합
avgWtrUsg: number, // 일평균 물사용량
}
/**====================================
* Store - 타입
@@ -35,145 +36,145 @@ export type SewageOccurDetailProps = {
/**
* (1) 메인페이지
*/
*/
// 검색단
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
const LabelArray: string[] = ['구분', '시도', '시군구', '용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
// 리스트 헤더
const upHeadList1:TableUpperProps[] = [
{ id: "A", title: "행정구역", row:0, colSpan:2 },
{ id: "sidoNm", title: "시도", row:1, widthPercent: 8 },
{ id: "sggNm", title: "시군구", row:1, widthPercent: 8 },
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
{ id: "inflAmnt", title: "연평균유입하수량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 10 },
{ id: "C", title: "지하수 유입량 추정", align:"right", row:0, colSpan:3 },
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1, widthPercent: 8 },
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1, widthPercent: 8 },
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1, widthPercent: 8 },
{ id: "properYn", title: "적정여부", row:0, rowSpan:2, widthPercent: 8 },
const upHeadList1: TableUpperProps[] = [
{ id: "A", title: "행정구역", row: 0, colSpan: 2 },
{ id: "sidoNm", title: "시도", row: 1, widthPercent: 8 },
{ id: "sggNm", title: "시군구", row: 1, widthPercent: 8 },
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 8 },
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
{ id: "fctCpc", title: "시설용량(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
{ id: "inflAmnt", title: "연평균유입하수량(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 10 },
{ id: "C", title: "지하수 유입량 추정", align: "right", row: 0, colSpan: 3 },
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align: "right", row: 1, widthPercent: 8 },
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align: "right", row: 1, widthPercent: 8 },
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align: "right", row: 1, widthPercent: 8 },
{ id: "properYn", title: "적정여부", row: 0, rowSpan: 2, widthPercent: 8 },
];
const upHeadList2:TableUpperProps[] = [
{ id: "A", title: "유역", row:0, colSpan:3 },
{ id: "rvbsn", title: "권역", row:1, widthPercent: 5 },
{ id: "lgbsn", title: "단위유역", row:1, widthPercent: 5 },
{ id: "mdmbsn", title: "중권역", row:1, widthPercent: 5 },
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
{ id: "inflAmnt", title: "연평균유입하수량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 10 },
{ id: "C", title: "지하수 유입량 추정", align:"right", row:0, colSpan:3 },
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1, widthPercent: 8 },
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1, widthPercent: 8 },
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1, widthPercent: 8 },
{ id: "properYn", title: "적정여부", row:0, rowSpan:2, widthPercent: 8 },
const upHeadList2: TableUpperProps[] = [
{ id: "A", title: "유역", row: 0, colSpan: 3 },
{ id: "rvbsn", title: "권역", row: 1, widthPercent: 5 },
{ id: "lgbsn", title: "단위유역", row: 1, widthPercent: 5 },
{ id: "mdmbsn", title: "중권역", row: 1, widthPercent: 5 },
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 8 },
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
{ id: "fctCpc", title: "시설용량(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
{ id: "inflAmnt", title: "연평균유입하수량(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 10 },
{ id: "C", title: "지하수 유입량 추정", align: "right", row: 0, colSpan: 3 },
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align: "right", row: 1, widthPercent: 8 },
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align: "right", row: 1, widthPercent: 8 },
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align: "right", row: 1, widthPercent: 8 },
{ id: "properYn", title: "적정여부", row: 0, rowSpan: 2, widthPercent: 8 },
];
const upHeadList3:TableUpperProps[] = [
{ id: "A", title: "유역", row:0, colSpan:3 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1, widthPercent: 5 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1, widthPercent: 5 },
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1, widthPercent: 5 },
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2, widthPercent: 8 },
{ id: "B", title: "행정구역", row:0, colSpan:2 },
{ id: "sidoNm", title: "시도", row:1, widthPercent: 6 },
{ id: "sggNm", title: "시군구", row:1, widthPercent: 6 },
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 6 },
{ id: "inflAmnt", title: "연평균유입하수량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 10 },
{ id: "C", title: "지하수 유입량 추정", align:"right", row:0, colSpan:3 },
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1, widthPercent: 6},
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1, widthPercent: 6 },
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1, widthPercent: 6 },
{ id: "properYn", title: "적정여부", row:0, rowSpan:2, widthPercent: 6 },
const upHeadList3: TableUpperProps[] = [
{ id: "A", title: "유역", row: 0, colSpan: 3 },
{ id: "rvbsn", title: "권역", upName: "upChangeRe1", upSequnce: 1, row: 1, widthPercent: 5 },
{ id: "lgbsn", title: "단위유역", upName: "upChangeRe1", upSequnce: 2, row: 1, widthPercent: 5 },
{ id: "mdmbsn", title: "중권역", upName: "upChangeRe1", upSequnce: 3, row: 1, widthPercent: 5 },
{ id: "rgnNm", title: "환경청", row: 0, rowSpan: 2, widthPercent: 8 },
{ id: "B", title: "행정구역", row: 0, colSpan: 2 },
{ id: "sidoNm", title: "시도", row: 1, widthPercent: 6 },
{ id: "sggNm", title: "시군구", row: 1, widthPercent: 6 },
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 8 },
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
{ id: "fctCpc", title: "시설용량(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 6 },
{ id: "inflAmnt", title: "연평균유입하수량(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 10 },
{ id: "C", title: "지하수 유입량 추정", align: "right", row: 0, colSpan: 3 },
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align: "right", row: 1, widthPercent: 6 },
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align: "right", row: 1, widthPercent: 6 },
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align: "right", row: 1, widthPercent: 6 },
{ id: "properYn", title: "적정여부", row: 0, rowSpan: 2, widthPercent: 6 },
];
// 모달
const upHeadListUnderWaterDetail:TableUpperProps[] = [
const upHeadListUnderWaterDetail: TableUpperProps[] = [
{ id: "msrDt", title: "날짜" },
{ id: "realSewageInput", title: "청천시 실제 하수유입량\n(m³/일)", align:"right" },
{ id: "sewageOccur", title: "오수발생량\n(m³/일)", align:"right" },
{ id: "underWaterInput", title: "지하수 유입량\n(m³/일)", align:"right" },
{ id: "realSewageInput", title: "청천시 실제 하수유입량\n(m³/일)", align: "right" },
{ id: "sewageOccur", title: "오수발생량\n(m³/일)", align: "right" },
{ id: "underWaterInput", title: "지하수 유입량\n(m³/일)", align: "right" },
];
const underWaterList:UnderWaterProps[] = [
const underWaterList: UnderWaterProps[] = [
]
const underWaterDetailList:UnderWaterInputModalProps[] = [
const underWaterDetailList: UnderWaterInputModalProps[] = [
{
msrDt : "2024-01",
realSewageInput : 178007,
sewageOccur : 10.5,
underWaterInput : 80.6,
msrDt: "2024-01",
realSewageInput: 178007,
sewageOccur: 10.5,
underWaterInput: 80.6,
},
{
msrDt : "2024-02",
realSewageInput : 123007,
sewageOccur : 10.7,
underWaterInput : 80.6,
msrDt: "2024-02",
realSewageInput: 123007,
sewageOccur: 10.7,
underWaterInput: 80.6,
},
{
msrDt : "2024-03",
realSewageInput : 213007,
sewageOccur : 10.1,
underWaterInput : 80.6,
msrDt: "2024-03",
realSewageInput: 213007,
sewageOccur: 10.1,
underWaterInput: 80.6,
},
{
msrDt : "2024-04",
realSewageInput : 83007,
sewageOccur : 9.57,
underWaterInput : 80.6,
msrDt: "2024-04",
realSewageInput: 83007,
sewageOccur: 9.57,
underWaterInput: 80.6,
},
{
msrDt : "2024-05",
realSewageInput : 15007,
sewageOccur : 3.57,
underWaterInput : 80.6,
msrDt: "2024-05",
realSewageInput: 15007,
sewageOccur: 3.57,
underWaterInput: 80.6,
},
{
msrDt : "2024-06",
realSewageInput : 123007,
sewageOccur : '',
underWaterInput : 80.6,
msrDt: "2024-06",
realSewageInput: 123007,
sewageOccur: '',
underWaterInput: 80.6,
},
{
msrDt : "2024-07",
realSewageInput : 101007,
sewageOccur : 1,
underWaterInput : 80.6,
msrDt: "2024-07",
realSewageInput: 101007,
sewageOccur: 1,
underWaterInput: 80.6,
},
{
msrDt : "2024-08",
realSewageInput : 103807,
sewageOccur : 10.57,
underWaterInput : '',
msrDt: "2024-08",
realSewageInput: 103807,
sewageOccur: 10.57,
underWaterInput: '',
},
{
msrDt : "2024-09",
realSewageInput : 9007,
sewageOccur : 10.57,
underWaterInput : 80.6,
msrDt: "2024-09",
realSewageInput: 9007,
sewageOccur: 10.57,
underWaterInput: 80.6,
},
{
msrDt : "2024-10",
realSewageInput : 163007,
sewageOccur : 10.57,
underWaterInput : 80.6,
msrDt: "2024-10",
realSewageInput: 163007,
sewageOccur: 10.57,
underWaterInput: 80.6,
},
{
msrDt : "2024-11",
realSewageInput : 123007,
sewageOccur : 10.57,
underWaterInput : 80.6,
msrDt: "2024-11",
realSewageInput: 123007,
sewageOccur: 10.57,
underWaterInput: 80.6,
},
{
msrDt : "2024-12",
realSewageInput : 1007,
sewageOccur : 10.57,
underWaterInput : 80.6,
msrDt: "2024-12",
realSewageInput: 1007,
sewageOccur: 10.57,
underWaterInput: 80.6,
},
]
/**====================================
@@ -185,8 +186,8 @@ export interface FlowDataItem {
inflAmnt: number | string;
infoRnDay: number;
msrDt: string;
rainEffectDay? : number;
sumFlow? : number | string | '';
rainEffectDay?: number;
sumFlow?: number | string | '';
}
export interface ApiResponse {
@@ -216,9 +217,9 @@ const fetchUnderWaterList = async (pageNo: number, pageSize: number, searchYear:
// }
// 시설들 유량 정보 조회
export const fetchDetailListFlow = async (searchYear: string|undefined, fcltCdList: string[]): Promise<UnderWaterProps | null> => {
export const fetchDetailListFlow = async (searchYear: string | undefined, fcltCdList: string[]): Promise<UnderWaterProps | null> => {
try {
const res = await postFetch('fo', '/fclt/flow/'+searchYear, fcltCdList);
const res = await postFetch('fo', '/fclt/flow/' + searchYear, fcltCdList);
return res;
} catch (error) {
console.error('시설정보 오수발생량 상세 데이터를 가져오는데 실패했습니다:', error);
@@ -226,9 +227,9 @@ export const fetchDetailListFlow = async (searchYear: string|undefined, fcltCdLi
}
};
// 시설들 월별 물사용량 정보 조회
export const fetchWtrUsgYmList = async (searchYear: string|undefined, fcltCdList: string[]): Promise<WtrUsgYmProps | null> => {
export const fetchWtrUsgYmList = async (searchYear: string | undefined, fcltCdList: string[]): Promise<WtrUsgYmProps | null> => {
try {
const res = await postFetch('fo', '/fclt/flow/wtrUsgYm/'+searchYear, fcltCdList);
const res = await postFetch('fo', '/fclt/flow/wtrUsgYm/' + searchYear, fcltCdList);
return res;
} catch (error) {
console.error('시설들 월별 물사용량 데이터를 가져오는데 실패했습니다:', error);
@@ -241,16 +242,16 @@ export const fetchWtrUsgYmList = async (searchYear: string|undefined, fcltCdList
====================================*/
export type UnderWaterActions = {
searchUnderWaterList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
unserWaterModal:(bscFctCd:string, searchYear:string, startYm:string, endYm:string)=>void
underWaterModal: (bscFctCd: string, searchYear: string, startYm: string, endYm: string) => void
}
export type UnderWaterType = {
UnderWaterSearch: {
isInit: boolean;
labelArray:string[];
labelArray: string[];
},
UnderWater : {
UnderWater: {
isInit: boolean;
upHeadList1: TableUpperProps[];
upHeadList2: TableUpperProps[];
@@ -261,7 +262,7 @@ export type UnderWaterType = {
isLoading: boolean;
},
UnderWaterDetail : {
UnderWaterDetail: {
isInit: boolean;
upHeadListUnderWaterDetail: TableUpperProps[];
gridListUnderWaterDetail: UnderWaterInputModalProps[];
@@ -274,30 +275,30 @@ export const underWaterInitState: UnderWaterType = {
labelArray: LabelArray,
},
UnderWater : {
isInit : false,
upHeadList1 : upHeadList1,
upHeadList2 : upHeadList2,
upHeadList3 : upHeadList3,
underWaterList : underWaterList,
underWaterCount : 4,
excelList : [],
isLoading : true,
UnderWater: {
isInit: false,
upHeadList1: upHeadList1,
upHeadList2: upHeadList2,
upHeadList3: upHeadList3,
underWaterList: underWaterList,
underWaterCount: 4,
excelList: [],
isLoading: true,
},
UnderWaterDetail : {
UnderWaterDetail: {
isInit: false,
upHeadListUnderWaterDetail: upHeadListUnderWaterDetail,
gridListUnderWaterDetail: underWaterDetailList,
}
}
const dataFormSetting=(item : UnderWaterProps)=> {
const dataFormSetting = (item: UnderWaterProps) => {
DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'inflAmnt', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'underWaterInputYear', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'underWaterInputSummer', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'underWaterInputWinter', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'underWaterInputYear', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'underWaterInputSummer', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'underWaterInputWinter', item: item as unknown as Record<string, unknown> });
}
// 병렬 처리 제한용 헬퍼
@@ -310,47 +311,34 @@ const dataFormSetting=(item : UnderWaterProps)=> {
// }
// return results;
// }
/**
* yyyymm 형태의 문자열을 받아 해당 월의 일수를 반환
* @param {string} yyyymm - 예: "202502", "202412"
* @returns {number} 해당 월의 일수 (예: 28, 29, 30, 31)
*/
function getDaysInMonth(yyyymm) {
if (typeof yyyymm !== 'string' || yyyymm.length !== 6) {
throw new Error("입력은 'yyyymm' 형식의 문자열이어야 합니다. 예: '202502'");
}
const year = parseInt(yyyymm.slice(0, 4), 10); // "2025" -> 2025
const month = parseInt(yyyymm.slice(4, 6), 10); // "02" -> 2
if (isNaN(year) || isNaN(month) || month < 1 || month > 12) {
throw new Error("유효한 년/월이 아닙니다.");
}
// Date(year, month, 0) -> 전달의 마지막 날
// month에 '다음달'을 넣고, 일(day)에 0을 주면 해당 월의 마지막 날짜가 됨
return new Date(year, month, 0).getDate();
}
export type UnderWaterStore = UnderWaterType & UnderWaterActions;
export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterType) => void)=>UnderWaterActions=(set: (fn: (state: UnderWaterType) => UnderWaterType) => void) => {
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){
if (pageSize < 5000) {
set((state: UnderWaterType) => ({
...state,
UnderWater: {
...state.UnderWater,
underWaterList : facilityInitData.data,
underWaterCount : facilityInitData.count,
isInit : true,
underWaterList: facilityInitData.data,
underWaterCount: facilityInitData.count,
isInit: true,
isLoading: true,
},
}));
}else{
} else {
set((state: UnderWaterType) => ({
...state,
UnderWater: {
@@ -359,43 +347,79 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
},
}));
}
const fcltylist = facilityInitData.data;
const fcltCdList : string[] = []; // 시설코드목록
const underWaterPropsList : UnderWaterProps[] = []; // 오수발생량시설목록
const fcltCdList: string[] = []; // 시설코드목록
const underWaterPropsList: UnderWaterProps[] = []; // 오수발생량시설목록
fcltylist.forEach(item => {
fcltCdList.push(item.bscFctCd);
underWaterPropsList.push({
bscFctCd : item.bscFctCd,
sidoNm : item.sido,
sggNm : item.gugun,
lclgvrnmntNm : '',
bscFctNm : item.bscFctNm,
daddr : item.daddr,
fctCpc : parseFloat(item.fctCpc.toString().replace(/,/g, '')),
inflAmnt : 0,
waterUsage : 0,
underWaterInputYear : 0,
underWaterInputSummer : 0,
underWaterInputWinter : 0,
properYn : '',
infoRnDay : 0,
rgnNm : item.rgnNm,
rvbsn : item.rvbsn,
lgbsn : item.lgbsn,
mdmbsn : item.mdmbsn,
msrDt : '',
bscFctCd: item.bscFctCd,
sidoNm: item.sido,
sggNm: item.gugun,
lclgvrnmntNm: '',
bscFctNm: item.bscFctNm,
daddr: item.daddr,
fctCpc: parseFloat(item.fctCpc.toString().replace(/,/g, '')),
inflAmnt: 0,
waterUsage: 0,
underWaterInputYear: 0,
underWaterInputSummer: 0,
underWaterInputWinter: 0,
properYn: '',
infoRnDay: 0,
rgnNm: item.rgnNm,
rvbsn: item.rvbsn,
lgbsn: item.lgbsn,
mdmbsn: item.mdmbsn,
msrDt: '',
});
});
const soccurDetailRes : any = await fetchDetailListFlow(searchYear, fcltCdList);
const wtrUsgYmRes : any = await fetchWtrUsgYmList(searchYear, fcltCdList);
// const soccurDetailRes: any = await fetchDetailListFlow(searchYear, fcltCdList);
// const wtrUsgYmRes: any = await fetchWtrUsgYmList(searchYear, fcltCdList);
//---------
const rainDetailList: Record<string, any[]> = {};
const wtrDetailList: Record<string, any[]> = {};
const results: any[] = [];
const wtrResults: any[] = [];
for (let idx = 0; idx < fcltCdList.length; idx += 100) {
const slicedItems = fcltCdList.slice(idx, idx + 100);
const result = await fetchDetailListFlow(searchYear, slicedItems);
const wtrResult = await fetchWtrUsgYmList(searchYear, slicedItems);
results.push(result);
wtrResults.push(wtrResult);
}
//console.log(results);
// 결과를 합치기
for (const res of results) {
if (res.status === 200 && res.data) {
for (const [key, value] of Object.entries(res.data)) {
const keyStr = String(key);
//rainDetailList[keyStr] = [...(rainDetailList[keyStr] || []), ...(value as any[])];
if (!rainDetailList[keyStr]) rainDetailList[keyStr] = [];
rainDetailList[keyStr].push(...(value as any[]));
}
}
}
for (const res of wtrResults) {
if (res.status === 200 && res.data) {
for (const [key, value] of Object.entries(res.data)) {
const keyStr = String(key);
// wtrDetailList[keyStr] = [...(wtrDetailList[keyStr] || []), ...(value as any[])];
if (!wtrDetailList[keyStr]) wtrDetailList[keyStr] = [];
wtrDetailList[keyStr].push(...(value as any[]));
}
}
}
//-------
for (const item of underWaterPropsList) {
const detailList = soccurDetailRes?.data[item.bscFctCd];
const wtrUsgYmList = wtrUsgYmRes?.data[item.bscFctCd];
// const detailList = soccurDetailRes?.data[item.bscFctCd];
// const wtrUsgYmList = wtrUsgYmRes?.data[item.bscFctCd];
const detailList = rainDetailList[item.bscFctCd];
const wtrUsgYmList = wtrDetailList[item.bscFctCd];
let chungcunSumFlow = 0; // 청천유입량
let sumChungcunDay = 0; // 청천일수
let sumSummerChungcunDay = 0; // 하절기 청천일수
@@ -407,39 +431,39 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
let totWinterUsage = 0; // 동절기 하수유입량
let totSummerDays = 0; // 하절기 일수
let totWinterDays = 0; // 동절기 일수
const summerMonth = ['06', '07', '08'];
const winterMonth = ['01', '02'];
let rainEffectDay = 0;
detailList?.forEach(item2 => {
if (item2.infoRnDay == null || item2.infoRnDay.trim() == 'x') item2.infoRnDay = 0;
if(Number(item2.infoRnDay) >= 3) {
if (Number(item2.infoRnDay) >= 3) {
rainEffectDay = 2;
}else{
} else {
rainEffectDay--;
}
if(rainEffectDay<0){ //청천시
if (rainEffectDay < 0) { //청천시
chungcunSumFlow += Number(item2.inflAmnt);
sumChungcunDay += 1;
if(item2.msrDt.substring(4,6) ==='06' || item2.msrDt.substring(4,6) ==='07' || item2.msrDt.substring(4,6) ==='08'){
if (item2.msrDt.substring(4, 6) === '06' || item2.msrDt.substring(4, 6) === '07' || item2.msrDt.substring(4, 6) === '08') {
// 하절기 6,7,8월
sumSummerChungcunDay += 1;
sumSummerChungcunFlow += Number(item2.inflAmnt); //item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0;
}else if(item2.msrDt.substring(4,6) ==='01' || item2.msrDt.substring(4,6) ==='02'){
} else if (item2.msrDt.substring(4, 6) === '01' || item2.msrDt.substring(4, 6) === '02') {
// 동절기 1,2월
sumWinterChungcunDay += 1;
sumWinterChungcunFlow += Number(item2.inflAmnt); //item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0;
}
}
totWaterUsage += Number(item2.inflAmnt);
if(item2.msrDt.substring(4,6) ==='06' || item2.msrDt.substring(4,6) ==='07' || item2.msrDt.substring(4,6) ==='08'){
if (item2.msrDt.substring(4, 6) === '06' || item2.msrDt.substring(4, 6) === '07' || item2.msrDt.substring(4, 6) === '08') {
// 하절기 6,7,8월
totSummerDays += 1;
totSummerUsage += Number(item2.inflAmnt); //item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0;
}else if(item2.msrDt.substring(4,6) ==='01' || item2.msrDt.substring(4,6) ==='02'){
} else if (item2.msrDt.substring(4, 6) === '01' || item2.msrDt.substring(4, 6) === '02') {
// 동절기 1,2월
totWinterDays += 1;
totWinterUsage += Number(item2.inflAmnt); //item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0;
@@ -447,8 +471,8 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
});
const count = detailList ? detailList.length : 0;
const avg = count == 0 ? 0 : totWaterUsage / count; // 일평균 유입량
const avg = count == 0 ? 0 : totWaterUsage / count; // 연간 일평균 유입량
let wtrUsgYearTotal = 0; // 연간 물사용량
let summerWtrUsgTot = 0; // 하절기 물사용량
let winterWtrUsgTot = 0; // 동절기 물사용량
@@ -459,52 +483,52 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
const days = getDaysInMonth(item3.levyYm);
wtrUsgYearTotal += Number(item3.wtrUsg);
wtrUsgYearDays += days;
if(summerMonth.includes(item3.levyYm.slice(-2))){
if (summerMonth.includes(item3.levyYm.slice(-2))) {
summerWtrUsgTot += Number(item3.wtrUsg);
summerWtrUsgDays += days;
}else if(winterMonth.includes(item3.levyYm.slice(-2))){
} else if (winterMonth.includes(item3.levyYm.slice(-2))) {
winterWtrUsgTot += Number(item3.wtrUsg);
winterWtrUsgDays += days;
}
});
if (wtrUsgYearTotal > 0) { // 물사용량이 있는 경우
const usage = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / sumChungcunDay:0; // 청천시 일평균 유입량
const summerUsage = sumSummerChungcunFlow?sumSummerChungcunFlow / sumSummerChungcunDay:0; // 하절기 청천시 일평균 유입량
const winterUsage = sumWinterChungcunFlow?sumWinterChungcunFlow / sumWinterChungcunDay:0; // 동절기 청천시 일평균 유입량
const wtrUsg = wtrUsgYearDays>0? wtrUsgYearTotal / wtrUsgYearDays: 0; // 일평균 물사용량
const summerWtrUsg = summerWtrUsgTot?summerWtrUsgTot / summerWtrUsgDays:0; // 하절기 일평균 물사용량
const winterWtrUsg = winterWtrUsgTot?winterWtrUsgTot / winterWtrUsgDays:0; // 동절기 일평균 물사용량
const usage = chungcunSumFlow && chungcunSumFlow > 0 ? chungcunSumFlow / sumChungcunDay : 0; // 청천시 일평균 유입량
const summerUsage = sumSummerChungcunFlow ? sumSummerChungcunFlow / sumSummerChungcunDay : 0; // 하절기 청천시 일평균 유입량
const winterUsage = sumWinterChungcunFlow ? sumWinterChungcunFlow / sumWinterChungcunDay : 0; // 동절기 청천시 일평균 유입량
const wtrUsg = wtrUsgYearDays > 0 ? wtrUsgYearTotal / wtrUsgYearDays : 0; // 일평균 물사용량
const summerWtrUsg = summerWtrUsgTot ? summerWtrUsgTot / summerWtrUsgDays : 0; // 하절기 일평균 물사용량
const winterWtrUsg = winterWtrUsgTot ? winterWtrUsgTot / winterWtrUsgDays : 0; // 동절기 일평균 물사용량
item.inflAmnt = roundNumber(avg, 0);
item.underWaterInputYear = Math.round((usage-(wtrUsg*OSU_PERCENT)) * 1) / 1; // 연간지하수유입량(m³/일) = 청천시 실제유입량 - (물사용량 × 오수전환율)
item.underWaterInputSummer = Math.round((summerUsage-(summerWtrUsg*OSU_PERCENT)) * 1) / 1; // 하절기지하수유입량(m³/일)
item.underWaterInputWinter = Math.round((winterUsage-(winterWtrUsg*OSU_PERCENT)) * 1) / 1; // 동절기지하수유입량(m³/일)
item.properYn = Math.round( (Number(usage-(wtrUsg*OSU_PERCENT)) / Number(item.inflAmnt)) * 100 * 1 ) / 1 > 20?'초과유입':'적정'; // 적정여부
item.underWaterInputYear = Math.round((usage - (wtrUsg * OSU_PERCENT)) * 1) / 1; // 연간지하수유입량(m³/일) = 청천시 실제유입량 - (물사용량 × 오수전환율)
item.underWaterInputSummer = Math.round((summerUsage - (summerWtrUsg * OSU_PERCENT)) * 1) / 1; // 하절기지하수유입량(m³/일)
item.underWaterInputWinter = Math.round((winterUsage - (winterWtrUsg * OSU_PERCENT)) * 1) / 1; // 동절기지하수유입량(m³/일)
item.properYn = Math.round((Number(usage - (wtrUsg * OSU_PERCENT)) / Number(item.inflAmnt)) * 100 * 1) / 1 > 20 ? '초과유입' : '적정'; // 적정여부
} else { // 물사용량이 없는 경우, 일평균 유입량으로 물사용량 추정(물사용량 = 유입량*0.65)
const usage = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / sumChungcunDay:0; // 청천시 일평균 유입량
const summerUsage = sumSummerChungcunFlow?sumSummerChungcunFlow / sumSummerChungcunDay:0; // 하절기 청천시 일평균 유입량
const winterUsage = sumWinterChungcunFlow?sumWinterChungcunFlow / sumWinterChungcunDay:0; // 동절기 청천시 일평균 유입량
const usage = chungcunSumFlow && chungcunSumFlow > 0 ? chungcunSumFlow / sumChungcunDay : 0; // 청천시 일평균 유입량
const summerUsage = sumSummerChungcunFlow ? sumSummerChungcunFlow / sumSummerChungcunDay : 0; // 하절기 청천시 일평균 유입량
const winterUsage = sumWinterChungcunFlow ? sumWinterChungcunFlow / sumWinterChungcunDay : 0; // 동절기 청천시 일평균 유입량
const wtrUsg = avg * 0.65; // 일평균 물사용량
const summerWtrUsg = totSummerDays>0? (totSummerUsage / totSummerDays)*0.65:0; // 하절기 일평균 물사용량
const winterWtrUsg = totWinterDays>0? (totWinterUsage / totWinterDays)*0.65:0; // 동절기 일평균 물사용량
const summerWtrUsg = totSummerDays > 0 ? (totSummerUsage / totSummerDays) * 0.65 : 0; // 하절기 일평균 물사용량
const winterWtrUsg = totWinterDays > 0 ? (totWinterUsage / totWinterDays) * 0.65 : 0; // 동절기 일평균 물사용량
item.inflAmnt = roundNumber(avg, 0);
//item.underWaterInputYear = Math.round((usage-(usage*0.65*OSU_PERCENT)) * 1) / 1; // 연간지하수유입량(m³/일)
item.underWaterInputYear = Math.round((usage-(wtrUsg*OSU_PERCENT)) * 1) / 1; // 연간지하수유입량(m³/일) = 청천시 실제유입량 - (물사용량 × 오수전환율)
item.underWaterInputSummer = Math.round((summerUsage-(summerWtrUsg*OSU_PERCENT)) * 1) / 1; // 하절기지하수유입량(m³/일) = 청천시 실제유입량 - (물사용량 × 오수전환율)
item.underWaterInputWinter = Math.round((winterUsage-(winterWtrUsg*OSU_PERCENT)) * 1) / 1; // 동절기지하수유입량(m³/일) = 청천시 실제유입량 - (물사용량 × 오수전환율)
item.properYn = Math.round( (Number(usage-(wtrUsg*OSU_PERCENT)) / Number(item.inflAmnt)) * 100 * 1 ) / 1 > 20?'초과유입':'적정'; // 적정여부
// 반올림 처리
// ["fctCpc", "inflAmnt", "underWaterInputYear", "underWaterInputSummer", "underWaterInputWinter"].forEach(
// (key) => (item[key] = roundNumber(item[key], 0))
// );
item.underWaterInputYear = Math.round((usage - (wtrUsg * OSU_PERCENT)) * 1) / 1; // 연간지하수유입량(m³/일) = 청천시 실제유입량 - (물사용량 × 오수전환율)
item.underWaterInputSummer = Math.round((summerUsage - (summerWtrUsg * OSU_PERCENT)) * 1) / 1; // 하절기지하수유입량(m³/일) = 청천시 실제유입량 - (물사용량 × 오수전환율)
item.underWaterInputWinter = Math.round((winterUsage - (winterWtrUsg * OSU_PERCENT)) * 1) / 1; // 동절기지하수유입량(m³/일) = 청천시 실제유입량 - (물사용량 × 오수전환율)
item.properYn = Math.round((Number(usage - (wtrUsg * OSU_PERCENT)) / Number(item.inflAmnt)) * 100 * 1) / 1 > 20 ? '초과유입' : '적정'; // 적정여부
// 반올림 처리
// ["fctCpc", "inflAmnt", "underWaterInputYear", "underWaterInputSummer", "underWaterInputWinter"].forEach(
// (key) => (item[key] = roundNumber(item[key], 0))
// );
}
}
if(pageSize>= 5000){
if (pageSize >= 5000) {
const excelDownList: ExcelType[] = [];
underWaterPropsList.forEach((item : any) => {
underWaterPropsList.forEach((item: any) => {
dataFormSetting(item)
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
excelDownList.push({
@@ -530,10 +554,10 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
UnderWater: {
...state.UnderWater,
excelList: excelDownList,
isLoading : false,
isLoading: false,
},
}));
}else{
} else {
set((state: UnderWaterType) => ({
...state,
UnderWater: {
@@ -541,21 +565,21 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
underWaterList: underWaterPropsList,
underWaterCount: facilityInitData.count,
excelList: [],
isLoading : false,
isLoading: false,
},
}));
}
},
unserWaterModal:async (bscFctCd, searchYear, startYm, endYm)=>{
underWaterModal: async (bscFctCd, searchYear, startYm, endYm) => {
const fcltCdList = [bscFctCd];
const wtrUsgRes : any = await fetchWtrUsgYmList(searchYear, fcltCdList);
const wtrUsgRes: any = await fetchWtrUsgYmList(searchYear, fcltCdList);
const res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear);
const monthData: SewageOccurDetailProps[] = [];
let tot = 0, cnt = 0;
let sunnyTot = 0, sunnyCnt = 0;
if(startYm) {
if (startYm) {
res.data = res.data.filter((item: FlowDataItem) => {
const month = item.msrDt?.substring(0, 6);
return month >= startYm;
@@ -567,7 +591,7 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
});
}
}
if(endYm) {
if (endYm) {
res.data = res.data.filter((item: FlowDataItem) => {
const month = item.msrDt?.substring(0, 6);
return month <= endYm;
@@ -582,36 +606,40 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
let rainEffectDay = 0;
res.data?.forEach(item2 => {
if (item2.infoRnDay == null || item2.infoRnDay.trim() == 'x') item2.infoRnDay = 0;
if(Number(item2.infoRnDay) >= 3) {
if (Number(item2.infoRnDay) >= 3) {
rainEffectDay = 2;
}else{
} else {
rainEffectDay--;
}
const month = item2.msrDt?.substring(4, 6);
const monthIdx = month ? Number(month) - 1 : -1;
if (monthIdx >= 0 && (monthIdx>=Number(startYm.substring(4,6))-1 && monthIdx <= Number(endYm.substring(4, 6))-1)) {
if (monthIdx >= 0 && (monthIdx >= Number(startYm.substring(4, 6)) - 1 && monthIdx <= Number(endYm.substring(4, 6)) - 1)) {
if (typeof monthData[monthIdx] === 'object') {
monthData[monthIdx].sum += Number(item2.inflAmnt); // 유입량 합
monthData[monthIdx].cnt++;
} else {
monthData[monthIdx] = {cnt:1, sum:Number(item2.inflAmnt), yr:item2.msrDt.substring(0,4)
, usage:0, sunnyCnt:0, sunnyInflAmnt:0, sunnyAvgInflAmnt: 0, cntWtrUsg:0, sumWtrUsg:0, avgWtrUsg:0};
monthData[monthIdx] = {
cnt: 1, sum: Number(item2.inflAmnt), yr: item2.msrDt.substring(0, 4)
, usage: 0, sunnyCnt: 0, sunnyInflAmnt: 0, sunnyAvgInflAmnt: 0, cntWtrUsg: 0, sumWtrUsg: 0, avgWtrUsg: 0
};
}
}
if(month >= startYm.substring(4, 6) && month <= endYm.substring(4, 6)){
}
if (month >= startYm.substring(4, 6) && month <= endYm.substring(4, 6)) {
cnt++;
tot += item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0;
}
if(rainEffectDay<0) { // 청천시
if (rainEffectDay < 0) { // 청천시
if (typeof monthData[monthIdx] === 'object') {
monthData[monthIdx].sunnyInflAmnt += Number(item2.inflAmnt); // 청천 유입량 합
monthData[monthIdx].sunnyCnt++;
}else {
monthData[monthIdx] = {cnt:1, sum:Number(item2.inflAmnt), yr:item2.msrDt.substring(0,4)
, usage:0, sunnyCnt:0, sunnyInflAmnt:0, sunnyAvgInflAmnt: 0, cntWtrUsg:0, sumWtrUsg:0, avgWtrUsg:0};
} else {
monthData[monthIdx] = {
cnt: 1, sum: Number(item2.inflAmnt), yr: item2.msrDt.substring(0, 4)
, usage: 0, sunnyCnt: 0, sunnyInflAmnt: 0, sunnyAvgInflAmnt: 0, cntWtrUsg: 0, sumWtrUsg: 0, avgWtrUsg: 0
};
}
if (month >= startYm.substring(4, 6) && month <= endYm.substring(4, 6)){
if (month >= startYm.substring(4, 6) && month <= endYm.substring(4, 6)) {
sunnyCnt++;
sunnyTot += item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0;
}
@@ -630,77 +658,78 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
if (typeof monthData[monthIdx] === 'object') {
monthData[monthIdx].sumWtrUsg += Number(item.wtrUsg);
monthData[monthIdx].cntWtrUsg += days;
}
}
}
totWtrUsg += Number(item.wtrUsg);
cntWtrUsg += days;
});
}
const tableData:UnderWaterInputModalProps[] = []
let maxWaterUsage = 0;
let minWaterUsage = 9999999999;
let avgWaterUsage = 0;
let maxSunnyInflAmnt = 0;
let minSunnyInflAmnt = 9999999999;
let avgSunnyInflAmnt = 0;
const tableData: UnderWaterInputModalProps[] = []
let maxWaterUsage = 0, minWaterUsage = 9999999999, avgWaterUsage = 0; // 물사용량
let maxSunnyInflAmnt = 0, minSunnyInflAmnt = 9999999999, avgSunnyInflAmnt = 0; // 청천 유입량
let maxUnderWaterInput = 0, minUnderWaterInput = 9999999999; // 지하수 유입량
monthData.forEach((item, index) => {
item.usage = item.sum/item.cnt; // 일평균 유입량
item.avgWtrUsg = item.sum/item.cnt * 0.65; // 일평균 물사용량
if (item.sumWtrUsg > 0 && item.cntWtrUsg > 0) item.avgWtrUsg = item.sumWtrUsg / item.cntWtrUsg; // 일평균 물사용량
item.usage = item.sum / item.cnt; // 일평균 유입량
item.avgWtrUsg = item.sum / item.cnt * 0.65; // 일평균 물사용량 : 수용가 물사용량이 없는 경우
// 일평균 물사용량 : 수용가 물사용량이 있는 경우
if (item.sumWtrUsg > 0 && item.cntWtrUsg > 0) item.avgWtrUsg = item.sumWtrUsg / item.cntWtrUsg;
item.sunnyAvgInflAmnt = item.sunnyInflAmnt / item.sunnyCnt; // 청천 일평균 유입량
const underWtrInput = Math.round((item.sunnyAvgInflAmnt - (item.avgWtrUsg * OSU_PERCENT)) * 1) / 1; // 지하수 유입량 평균
tableData.push({
msrDt: item.yr+'-'+(index+1>=10?String(index+1):'0'+(index+1)),
realSewageInput:Math.round(item.sunnyAvgInflAmnt*1) /1, // 청천 실제 하수유입량
sewageOccur:Math.round(item.avgWtrUsg*OSU_PERCENT * 1) / 1,// 오수발생량
underWaterInput:Math.round((item.sunnyAvgInflAmnt-(item.avgWtrUsg*OSU_PERCENT)) * 1) / 1, // 지하수 유입량 : 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)
msrDt: item.yr + '-' + (index + 1 >= 10 ? String(index + 1) : '0' + (index + 1)),
realSewageInput: Math.round(item.sunnyAvgInflAmnt * 1) / 1, // 청천 실제 하수유입량
sewageOccur: Math.round(item.avgWtrUsg * OSU_PERCENT * 1) / 1,// 오수발생량
underWaterInput: underWtrInput, // 지하수 유입량 : 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)
})
if (item.avgWtrUsg > maxWaterUsage) maxWaterUsage = item.avgWtrUsg;
if (item.avgWtrUsg > maxWaterUsage) maxWaterUsage = item.avgWtrUsg;
if (item.sunnyAvgInflAmnt > maxSunnyInflAmnt) maxSunnyInflAmnt = item.sunnyAvgInflAmnt;
if (item.avgWtrUsg < minWaterUsage) minWaterUsage = item.avgWtrUsg;
if (item.sunnyAvgInflAmnt < minSunnyInflAmnt) minSunnyInflAmnt = item.sunnyAvgInflAmnt;
if (underWtrInput > maxUnderWaterInput) maxUnderWaterInput = underWtrInput;
if (underWtrInput < minUnderWaterInput) minUnderWaterInput = underWtrInput;
});
if(monthData.length == 0){
maxWaterUsage = 0; minWaterUsage = 0; avgWaterUsage = 0;
if (monthData.length == 0) {
maxWaterUsage = 0; minWaterUsage = 0; avgWaterUsage = 0;
maxSunnyInflAmnt = 0; minSunnyInflAmnt = 0; avgSunnyInflAmnt = 0;
}
avgWaterUsage = cnt>0? tot/cnt * 0.65:0; // 일평균 물사용량
if (totWtrUsg > 0 && cntWtrUsg > 0) avgWaterUsage = totWtrUsg / cntWtrUsg; // 일평균 물사용량
avgSunnyInflAmnt = (sunnyCnt>0)?sunnyTot/sunnyCnt:0; // 청천 일평균 유입량
const newData= [
{
msrDt: '평균',
realSewageInput:Math.round(avgSunnyInflAmnt*1) /1, // 청천시 실제 하수유입량
sewageOccur:Math.round(avgWaterUsage*OSU_PERCENT * 1) / 1, // 오수발생량
underWaterInput: Math.round((avgSunnyInflAmnt-(avgWaterUsage*OSU_PERCENT)) * 1) / 1 // 지하수 유입량 : 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)
//underWaterInput:Math.round((avgWaterUsage-(avgWaterUsage*0.65*0.8)) * 100) / 100,
},
{
msrDt: '최대',
realSewageInput: Math.round(maxSunnyInflAmnt*1) /1, // 청천시 실제 하수유입량
sewageOccur: Math.round(maxWaterUsage*OSU_PERCENT * 1) / 1, // 오수발생량
underWaterInput: Math.round((maxSunnyInflAmnt-(maxWaterUsage*OSU_PERCENT)) * 1) / 1, // 지하수 유입량 : 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)
},
{
msrDt: '최소',
realSewageInput: Math.round(minSunnyInflAmnt*1) /1, // 청천시 실제 하수유입량
sewageOccur: Math.round(minWaterUsage*OSU_PERCENT * 1) / 1, // 오수발생량
underWaterInput: Math.round((minSunnyInflAmnt-(minWaterUsage*OSU_PERCENT)) * 1) / 1, // 지하수 유입량 : 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)
},
...tableData
avgWaterUsage = cnt > 0 ? tot / cnt * 0.65 : 0; // 일평균 물사용량
if (totWtrUsg > 0 && cntWtrUsg > 0) avgWaterUsage = totWtrUsg / cntWtrUsg; // 일평균 물사용량
avgSunnyInflAmnt = (sunnyCnt > 0) ? sunnyTot / sunnyCnt : 0; // 청천 일평균 유입량
const newData = [
{
msrDt: '평균',
realSewageInput: Math.round(avgSunnyInflAmnt * 1) / 1, // 청천시 실제 하수유입량
sewageOccur: Math.round(avgWaterUsage * OSU_PERCENT * 1) / 1, // 오수발생량
underWaterInput: Math.round((avgSunnyInflAmnt - (avgWaterUsage * OSU_PERCENT)) * 1) / 1 // 지하수 유입량 : 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)
//underWaterInput:Math.round((avgWaterUsage-(avgWaterUsage*0.65*0.8)) * 100) / 100,
},
{
msrDt: '최대',
realSewageInput: Math.round(maxSunnyInflAmnt * 1) / 1, // 청천시 실제 하수유입량
sewageOccur: Math.round(maxWaterUsage * OSU_PERCENT * 1) / 1, // 오수발생량
underWaterInput: maxUnderWaterInput, // 지하수 유입량 : 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)
},
{
msrDt: '최소',
realSewageInput: Math.round(minSunnyInflAmnt * 1) / 1, // 청천시 실제 하수유입량
sewageOccur: Math.round(minWaterUsage * OSU_PERCENT * 1) / 1, // 오수발생량
underWaterInput: minUnderWaterInput, // 지하수 유입량 : 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)
},
...tableData
]
set((state: UnderWaterType) => ({
...state,
UnderWaterDetail: {
...state.UnderWaterDetail,
gridListUnderWaterDetail:newData
gridListUnderWaterDetail: newData
}
}))
}
}
}
}
+11 -7
View File
@@ -1,7 +1,7 @@
import type { NextConfig } from "next";
const subDomain =
process.env.NEXT_PUBLIC_PROXY_HOST || "http://localhost:3000";
const domain = process.env.NEXT_PUBLIC_PROXY_HOST || "http://localhost:3000";
const subDomain = process.env.NEXT_PUBLIC_SUB_DOMAIN || "http://localhost:13000";
const nextConfig: NextConfig = {
output: "standalone",
@@ -18,7 +18,7 @@ const nextConfig: NextConfig = {
{
type: "header",
key: "referer",
value: "(.*)/pst(.*)",
value: "(.*)/cms(.*)",
},
],
},
@@ -26,19 +26,23 @@ const nextConfig: NextConfig = {
afterFiles: [
{
source: "/sewerage-service/:path*",
destination: `${subDomain}/sewerage-service/:path*`,
destination: `${domain}/sewerage-service/:path*`,
},
{
source: "/reuse-service/:path*",
destination: `${subDomain}/reuse-service/:path*`,
destination: `${domain}/reuse-service/:path*`,
},
{
source: "/operation-service/:path*",
destination: `${subDomain}/operation-service/:path*`,
destination: `${domain}/operation-service/:path*`,
},
{
source: "/ngii-server/:path*",
destination: `${subDomain}/ngii-server/:path*`,
destination: `${domain}/ngii-server/:path*`,
},
{
source: "/cms/:path*",
destination: `${subDomain}/cms/:path*`,
},
],
fallback: [],
@@ -1,7 +1,7 @@
"use client";
import { useEffect } from "react";
import { useRouter, usePathname } from "next/navigation";
import { useRouter } from "next/navigation";
import { client } from "@/src/shared/api";
import type { IUserInfo } from "@/src/shared/store";
import { useUserStore, getCookie } from "@/src/shared/lib";
@@ -12,7 +12,7 @@ const LOGIN_PAGE_URL = process.env.NEXT_PUBLIC_CM_LOGIN_PAGE_URL || "http://loca
const AuthWrapper = ({ children }: { children: React.ReactNode }) => {
const router = useRouter();
const pathname = usePathname();
// const pathname = usePathname();
const { userInfo, setUserInfo } = useUserStore((state) => state);
async function authCheck() {
@@ -53,7 +53,7 @@ const AuthWrapper = ({ children }: { children: React.ReactNode }) => {
}
}
})();
}, [pathname]);
}, []);
return <>{children}</>;
};
@@ -1,3 +1,4 @@
"use client";
import { createContext, useState } from "react";
interface PromptContext {
+1 -1
View File
@@ -5,7 +5,7 @@ NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11302
NEXT_PUBLIC_SUB_DOMAIN = http://con.mind-one.co.kr:11300
NEXT_PUBLIC_SUB_DOMAIN = http://con.mind-one.co.kr:13000
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
+1 -1
View File
@@ -11,7 +11,7 @@ NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
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_NGII_URL = http://172.29.143.87
NEXT_PUBLIC_NGII_URL = http://172.29.143.87/poiact
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}
NEXT_PUBLIC_SEWERAGE_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
NEXT_PUBLIC_DC_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
@@ -27,7 +27,8 @@ export const MsSwagePplCol = [
// { id: 'ftre_smbol_cd', title: '지형지물부호코드' },
// { id: 'lyrTypeNm', title: '레이어타입명' },
]
export const MsSwagePplCol2 = [
// 하수관로 searchModal 기본정보tab
export const MsSwagePplCol2 = [
{ id: 'rowNumber', title: '일련\n번호' },
{ id: 'fcltMngNo', title: '시설\n관리번호' },
{ id: 'instMngNo', title: '기관\n관리번호' },
@@ -44,13 +45,13 @@ export const MsSwagePplCol2 = [
{ id: 'tmptMhlMngNo', title: '시점맨홀\n관리번호' },
{ id: 'scendDpth', title: '종점깊이\n(m)' },
{ id: 'scendMhlMngNo', title: '종점맨홀\n관리번호' },
// { id: 'vrtcLen', title: '세로길이\n(m)' },
// { id: 'wdthLen', title: '가로길이\n(m)' },
// { id: 'fcltyShpCd', title: '시설물형태코드' },
{ id: 'vrtcLen', title: '세로길이\n(m)' },
{ id: 'wdthLen', title: '가로길이\n(m)' },
{ id: 'fcltyShpCd', title: '시설물형태코드' },
// { id: 'fid', title: 'FID' },
// { id: 'ftreSmbolCd', title: '지형지물부호코드' },
// { id: 'mngInstCd', title: '관리기관코드' },
// { id: 'mqltCd', title: '재질코드' },
{ id: 'mqltCd', title: '재질코드' },
// { id: 'pbadmsEmdCd', title: '행정읍면동코드' },
// { id: 'usgCd', title: '용도코드' },
// { id: 'lyrTypeNm', title: '레이어타입명' },
@@ -69,6 +70,10 @@ export const MsSwagePplExcelCol = {
'tmptMhlMngNo': '시점맨홀 관리번호',
'scendDpth': '종점 깊이(m)',
'scendMhlMngNo': '종점맨홀 관리번호',
'vrtcLen': '세로길이(m)',
'wdthLen': '가로길이(m)',
'fcltyShpCd': '시설물형태코드',
'mqltCd': '재질코드',
};
// 하수관로 용도 코드표
export const MS_SWAGE_PPL_USE_CODES = [
@@ -275,7 +280,80 @@ export const MS_SWAGE_PPL_CODES = [
{ val: "MOP977", text: "전주용입상관" },
{ val: "MOP978", text: "MD관" },
];
// 하수관로 'fcltyShpCd' '시설물형태코드'
export const MS_SWAGE_PPL_SHAPE = [
{ val: "FOR000 ", text: "미분류" },
{ val: "FOR001 ", text: "원형" },
{ val: "FOR002 ", text: "원추형" },
{ val: "FOR003 ", text: "원통형" },
{ val: "FOR004 ", text: "구형" },
{ val: "FOR005 ", text: "타원형" },
{ val: "FOR006 ", text: "난원" },
{ val: "FOR007 ", text: "반원형" },
{ val: "FOR010 ", text: "피라미드형" },
{ val: "FOR011 ", text: "사면체형" },
{ val: "FOR012 ", text: "기둥,축" },
{ val: "FOR013 ", text: "돛대,활대처럼 둥글고 긴 원재" },
{ val: "FOR014 ", text: "아치형" },
{ val: "FOR015 ", text: "다중아치형" },
{ val: "FOR016 ", text: "돔형" },
{ val: "FOR017 ", text: "고형체형" },
{ val: "FOR020 ", text: "사각형" },
{ val: "FOR021 ", text: "평방형" },
{ val: "FOR022 ", text: "다이아몬드형" },
{ val: "FOR023 ", text: "사다리꼴" },
{ val: "FOR024 ", text: "각형" },
{ val: "FOR025 ", text: "마제형관" },
{ val: "FOR026 ", text: "태형" },
{ val: "FOR030 ", text: "A형" },
{ val: "FOR031 ", text: "H형" },
{ val: "FOR032 ", text: "I형" },
{ val: "FOR033 ", text: "Y형" },
{ val: "FOR034 ", text: "T형" },
{ val: "FOR050 ", text: "불규칙한 형태" },
{ val: "FOR900 ", text: "계란형" },
{ val: "FOR901 ", text: "구(사각)형" },
{ val: "FOR902 ", text: "높이조절철개형" },
{ val: "FOR903 ", text: "박스형(RCB)" },
{ val: "FOR904 ", text: "반월개거" },
{ val: "FOR905 ", text: "반월개거(측구)" },
{ val: "FOR906 ", text: "벽돌조" },
{ val: "FOR907 ", text: "사각철판" },
{ val: "FOR908 ", text: "석축개거" },
{ val: "FOR909 ", text: "석축개거(측구)" },
{ val: "FOR910 ", text: "승수로" },
{ val: "FOR911 ", text: "옹벽개거" },
{ val: "FOR912 ", text: "옹벽개거(측구)" },
{ val: "FOR913 ", text: "이단" },
{ val: "FOR914 ", text: "이중침전형" },
{ val: "FOR915 ", text: "자연개거" },
{ val: "FOR916 ", text: "자연개거(측구)" },
{ val: "FOR917 ", text: "조립식" },
{ val: "FOR918 ", text: "지상관" },
{ val: "FOR919 ", text: "지상단구" },
{ val: "FOR920 ", text: "지상쌍구" },
{ val: "FOR921 ", text: "지하단구" },
{ val: "FOR922 ", text: "지하쌍구" },
{ val: "FOR923 ", text: "직사각형" },
{ val: "FOR924 ", text: "타설식" },
{ val: "FOR925 ", text: "토류형" },
{ val: "FOR926 ", text: "흄관원형" },
{ val: "FOR927 ", text: "L형측구" },
{ val: "FOR928 ", text: "LO형측구" },
{ val: "FOR929 ", text: "LU형측구" },
{ val: "FOR930 ", text: "PVC이중벽관" },
{ val: "FOR931 ", text: "RCB 맨홀" },
{ val: "FOR932 ", text: "U형" },
{ val: "FOR933 ", text: "U형측구(미복개)" },
{ val: "FOR934 ", text: "U형측구(복개)" },
{ val: "FOR999 ", text: "기타" }
];
// 하수처리시설
export const SwtrmtFcltCol = [
{ id: 'swtrmt_fclt_nm', title: '하수처리시설명' },
@@ -125,10 +125,9 @@ const SearchModal: React.FC = () => {
{/* 📋 결과 리스트 */}
{/* 기본정보 탭 */}
{activeTab === 'basic' && (
<div className="h-[79vh] w-full overflow-x-hidden overflow-y-auto rounded-lg border mt-4">
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<UiTable
<div className="h-[79dvh] w-full rounded-lg border mt-4 overflow-x-scroll">
<LoadingOverlay isLoading={isLoading} />
<UiTable className='w-[120%]'
headName={(() => {
const label = BASIC_TYPES.find((type) => type.val === basicType)?.text
return (<>{label} 조회 결과 ({tableCount.toLocaleString('ko-KR')})건</>);
@@ -150,66 +149,65 @@ const SearchModal: React.FC = () => {
</div>
}
/>
</div>
</div>
)}
{/* 유지관리 정보 탭 */}
{activeTab === 'operation' && (
<>
<div className="h-[39vh] w-full overflow-hidden rounded-lg border mt-4">
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<UiTable
headName={
(() => {
const label = WORK_TYPES.find((type) => type.val === workType)?.text
return (<>{label} 사업 현황 ({tableCount.toLocaleString('ko-KR')})건</>);
})()
}
tableData={tableData}
headlist={dynamicHeadlist}
pageSize={OPERATION_TABLE_SIZE}
total={tableCount}
cellClick={handleOperationCellClick}
onPageChange={setCurPage}
resetPageNo={isResetPage}
resetSelection={isResetSelection}
curPage={curPage}
headButton={
<Button className="px-4 py-2 !mr-[1.2rem] text-white rounded-sm text-sm font-medium green" size="sm" onClick={operationExcelDownload}>파일 다운로드</Button>
}
/>
</div>
<div className="h-[39dvh] w-full overflow-x-hidden overflow-y-auto rounded-lg border mt-4">
{/* <div className="flex-1 px-2 pb-2"> */}
<LoadingOverlay isLoading={isLoading} />
<UiTable
headName={
(() => {
const label = WORK_TYPES.find((type) => type.val === workType)?.text
return (<>{label} 사업 현황 ({tableCount.toLocaleString('ko-KR')})건</>);
})()
}
tableData={tableData}
headlist={dynamicHeadlist}
pageSize={OPERATION_TABLE_SIZE}
total={tableCount}
cellClick={handleOperationCellClick}
onPageChange={setCurPage}
resetPageNo={isResetPage}
resetSelection={isResetSelection}
curPage={curPage}
headButton={
<Button className="px-4 py-2 !mr-[1.2rem] text-white rounded-sm text-sm font-medium green" size="sm" onClick={operationExcelDownload}>파일 다운로드</Button>
}
/>
{/* </div> */}
</div>
<div className="h-[39vh] w-full overflow-hidden rounded-lg border">
<div className="h-[39dvh] w-full overflow-x-hidden overflow-y-auto rounded-lg border">
{/* 테이블2 영역 */}
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isDetailLoading} />
<UiTable
headName={
(() => {
const label = WORK_TYPES.find((type) => type.val === workType)?.text
return (<>{label} 결과표 ({detailTableCount.toLocaleString('ko-KR')})건</>);
})()
}
tableData={detailTableData}
headlist={dynamicHeadlist2}
pageSize={OPERATION_TABLE_SIZE}
total={detailTableCount}
cellClick={handleOperationResultCellClick}
onPageChange={setDetailCurPage}
resetPageNo={isResetDetailPage}
resetSelection={isResetDetailSelection}
curPage={detailCurPage}
headButton={
<div className='flex'>
<Button className="px-4 py-2 !mr-[1.2rem] text-white rounded-sm text-lg font-medium primary" size="sm" onClick={viewMultipleFeature}>지도에서 보기</Button>
<Button className="px-4 py-2 !mr-[1.2rem] text-white rounded-sm text-lg font-medium green" size="sm" onClick={operationResultExcelDownload}>파일 다운로드</Button>
</div>
}
/>
</div>
{/* <div className="flex-1 px-2 pb-2"> */}
<LoadingOverlay isLoading={isDetailLoading} />
<UiTable
headName={
(() => {
const label = WORK_TYPES.find((type) => type.val === workType)?.text
return (<>{label} 결과표 ({detailTableCount.toLocaleString('ko-KR')})건</>);
})()
}
tableData={detailTableData}
headlist={dynamicHeadlist2}
pageSize={OPERATION_TABLE_SIZE}
total={detailTableCount}
cellClick={handleOperationResultCellClick}
onPageChange={setDetailCurPage}
resetPageNo={isResetDetailPage}
resetSelection={isResetDetailSelection}
curPage={detailCurPage}
headButton={
<div className='flex'>
<Button className="px-4 py-2 !mr-[1.2rem] text-white rounded-sm text-lg font-medium primary" size="sm" onClick={viewMultipleFeature}>지도에서 보기</Button>
<Button className="px-4 py-2 !mr-[1.2rem] text-white rounded-sm text-lg font-medium green" size="sm" onClick={operationResultExcelDownload}>파일 다운로드</Button>
</div>
}
/>
{/* </div> */}
</div>
</>
)}
@@ -224,8 +222,8 @@ const SearchModal: React.FC = () => {
bodyClass={`
h-[100dvh]
w-[90dvw]
max-w-[1200px]
max-h-[100dvh]
max-w-[1220px]
max-h-[970px]
overflow-y-hidden
z-[101]
`}
@@ -14,7 +14,7 @@
*/
import { downloadExcelWithKoreanHeaders } from '@common/business_components/ui';
import {
MS_SWAGE_PPL_USE_CODES, MS_SWAGE_MHL_CODES, MS_SWAGE_MHL_USE_CODES,
MS_SWAGE_PPL_USE_CODES, MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_SHAPE, MS_SWAGE_MHL_CODES, MS_SWAGE_MHL_USE_CODES,
MsSwagePplExcelCol, SwtrmtFcltExcelCol, SwtrmtPrcsZoneExcelCol, MsSwageMhlExcelCol, ExclnSewagePumpExcelCol, stofcbrExcelCol
} from '../components/common/table';
import { getData } from "@/components/lib/api";
@@ -46,6 +46,7 @@ export default function useBasicTab() {
} = useSearchModalStore();
const { ctpv, sgg } = useStore();
const fetchBasicFilteredData = async () => {
let cqlFilters: string[] = [];
const queryParams = new URLSearchParams({
@@ -79,8 +80,15 @@ export default function useBasicTab() {
if (!sggCd && code) sggCd = code.slice(0, 5);
}
const matchedMhlCode = MS_SWAGE_MHL_CODES.find(code => code.val === item?.mqltCd?.trim());
const matchedMhlUsgCode = MS_SWAGE_MHL_USE_CODES.find(code => code.val === item?.usgCd);
const matchedMqltCode = basicType === 'tb_ms_swage_ppl'
? MS_SWAGE_PPL_CODES.find(code => code.val === item?.mqltCd?.trim()) // 하수관로 재질
: basicType === 'tb_ms_swage_mhl'
? MS_SWAGE_MHL_CODES.find(code => code.val === item?.mqltCd?.trim()) // 맨홀 재질
: undefined;
const matchedMhlUsgCode = MS_SWAGE_MHL_USE_CODES.find(code => code.val === item?.usgCd); // 맨홀 용도
const matchedPplShpCode = MS_SWAGE_PPL_SHAPE.find(code => code.val === item?.fcltyShpCd); // 하수관로 시설물형태코드
const ctpvNm = ctpv.find(code => code.val.trim() === ctpvCd)?.text || item?.ctpvNm;
const sggNm = sgg.find(code => code.val.trim() === sggCd)?.text || item?.sggNm;
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim());
@@ -90,15 +98,17 @@ export default function useBasicTab() {
...formattedItem,
rowNumber: (curPage - 1) * 10 + index + 1, // 1부터 시작하는 일련번호 추가
scsYn: item.scsYn === null || item.scsYn === undefined ? 'N' : item?.scsYn, // scsYn이 null이면 'N'으로 변경
mqltCd: matchedMhlCode ? matchedMhlCode.text : item?.mqltCd,
mqltCd: matchedMqltCode ? matchedMqltCode.text : item?.mqltCd,
usgCd: matchedMhlUsgCode ? matchedMhlUsgCode.text : (usgCdObj ? usgCdObj.text : item?.usgCd),
ctpvNm: ctpvNm ?? '-',
sggNm: sggNm ?? '-',
swtrmt_zone_nm: item.swtrmtZoneNm || item.swtrmt_zone_nm || '-',
fcltyShpCd: matchedPplShpCode? matchedPplShpCode.text : item?.fcltyShpCd,
};
});
setTableData(dataWithRowNumber);
// console.log(tableData);
setTableCount(res.count || []);
};
@@ -150,7 +160,7 @@ export default function useBasicTab() {
// 하수관로
cqlFilters = swagePplCqlFilters()
headerMapping = MsSwagePplExcelCol;
headerRange = "A1:M1";
headerRange = "A1:Q1";
break;
}
case 'tb_il_swage_prcs_fclt': {
@@ -196,6 +206,8 @@ export default function useBasicTab() {
const mhlUsgCdMap = new Map(MS_SWAGE_MHL_USE_CODES.map(code => [code.val?.trim(), code.text]));
const pplUsgCdMap = new Map(MS_SWAGE_PPL_USE_CODES.map(code => [code.val?.trim(), code.text]));
const pplMqltCdMap = new Map(MS_SWAGE_PPL_CODES.map(code => [code.val?.trim(), code.text]));
const pplShpCdMap = new Map(MS_SWAGE_PPL_SHAPE.map(code => [code.val?.trim(), code.text])); // 관로 시설물형태코드
const ctpvMap = new Map(ctpv.map(code => [code.val?.trim(), code.text]));
const sggMap = new Map(sgg.map(code => [code.val?.trim(), code.text]));
@@ -232,6 +244,10 @@ export default function useBasicTab() {
tmptMhlMngNo: formattedItem.tmptMhlMngNo ?? item.tmptMhlMngNo ?? '-',
scendDpth: formattedItem.scendDpth ?? item.scendDpth ?? '-',
scendMhlMngNo: formattedItem.scendMhlMngNo ?? item.scendMhlMngNo ?? '-',
vrtcLen: formattedItem.vrtcLen ?? item.vrtcLen ?? '-',
wdthLen: formattedItem.wdthLen ?? item.wdthLen ?? '-',
fcltyShpCd: pplShpCdMap.get(item?.fcltyShpCd?.trim()) || item.fcltyShpCd || formattedItem.fcltyShpCd || '-',
mqltCd: pplMqltCdMap.get(item?.mqltCd?.trim()) || item.mqltCd || formattedItem.mqltCd || '-',
};
}
case 'tb_il_swage_prcs_fclt': {
@@ -329,4 +345,4 @@ export default function useBasicTab() {
return { fetchBasicFilteredData, handleBasicCellClick, basicExcelDownload };
};
};
+4 -5
View File
@@ -19,15 +19,14 @@ import { LoginApi } from "@/entities/auth";
import { useEffect } from "react";
import { getCookie } from "@/shared/lib";
import { AUTH_USER_ID } from "@/shared/config";
import { useRouter } from "next/navigation";
export default function Home() {
const router = useRouter();
const checkToken = getCookie(AUTH_USER_ID);
useEffect(() => {
const hostname = window.location.hostname;
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr") {
if (!checkToken) {
async function doLogin() {
@@ -39,7 +38,7 @@ export default function Home() {
}
}
doLogin();
} else router.push("/map");
} else router.push("/map");
} else window.location.href = "/map";
} else window.location.href = "/map";
}, []);
}
+22 -4
View File
@@ -6,16 +6,34 @@ const subDomain =
const nextConfig: NextConfig = {
output: "standalone",
experimental: {
proxyTimeout: 600000, // 10분 (밀리초 단위)
},
typescript: {
ignoreBuildErrors: true, // 이 줄 추가
proxyTimeout: 600000,
},
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
},
logging: {
fetches: {
fullUrl: true,
},
},
async rewrites() {
return {
beforeFiles: [
{
source: "/_next/static/:path*",
destination: `${subDomain}/_next/static/:path*`,
has: [
{
type: "header",
key: "referer",
value: "(.*)/cms(.*)",
},
],
},
],
afterFiles: [
{
source: "/cms/:path*",
@@ -47,7 +47,7 @@ const AuthWrapper = ({ children }: { children: React.ReactNode }) => {
// 개발 환경에서는 localhost 도메인 사용
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr")
router.push("/"); // 개발시 홈으로 돌아가기
window.location.href = "/";
// 운영 환경에서는 서브도메인을 포함한 최상위 도메인 사용
// router.push는 같은 Next.js 앱 내에서만 작동하므로 다른 앱으로 이동할 때는 window.location.href 사용
+1 -1
View File
@@ -3,7 +3,7 @@ import { PROXY_HOST } from "./env";
// 브라우저에서는 동일 오리진으로 상대경로 호출 → CORS/localhost 고정 문제 방지
// (Next middleware가 /server/* 요청을 백엔드로 rewrite)
// 서버 환경(SSR 등)에서는 절대 URL이 필요할 수 있어 기존 PROXY_HOST 기반 유지
export const BASE_URL = typeof window === "undefined" ? `${PROXY_HOST}/server` : "/server";
export const BASE_URL = `${PROXY_HOST}/server`;
export const ENDPOINT = {
ATTACH_SERVICE: {
+1
View File
@@ -5,6 +5,7 @@ NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_PROXY_HOST = http://localhost:3001
NEXT_PUBLIC_SUB_DOMAIN = http://localhost:13000
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_FO_SERVER_API_URL = http://con.mind-one.co.kr:11083/operation-service/api/v1
NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
+1
View File
@@ -5,6 +5,7 @@ NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11301
NEXT_PUBLIC_SUB_DOMAIN = http://con.mind-one.co.kr:13000
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_FO_SERVER_API_URL = http://con.mind-one.co.kr:11083/operation-service/api/v1
NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
+1 -1
View File
@@ -15,7 +15,7 @@ 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_WR_SERVER_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_URL = http://172.29.143.87/poiact
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}
NEXT_PUBLIC_HASUDOINFO = https://www.hasudoinfo.or.kr
NEXT_PUBLIC_HASUDOINFO_IN = http://10.101.163.102:8889
+113 -115
View File
@@ -21,7 +21,7 @@ import WrOverLay from "@/components/ui/map/wrOverLay/wrOverLay";
const Map = () => {
const {code, comMap ,rainMapDetile ,rswtMapDetile,getRuseMaplListReturn,pbnMapDetaile,ldrmntMapDetile,htdfMapDetile,coSttnMapDetail} = useWrStore((state) => state);
const { code, comMap, rainMapDetile, rswtMapDetile, getRuseMaplListReturn, pbnMapDetaile, ldrmntMapDetile, htdfMapDetile, coSttnMapDetail } = useWrStore((state) => state);
const { isFeatured } = comMap;
const [treeData, setTreeData] = useState([]); // 초기값을 객체 또는 null로 설정
const gisMaps = useRef<any | null>(null);
@@ -93,7 +93,6 @@ const Map = () => {
return;
}
// 항상 같은 select 객체 사용
const select = GisApp.Module.select as any;
if (!select) return;
@@ -109,7 +108,6 @@ const Map = () => {
const layerName = getWrLayerNm(data);
const featurePk = getWrFeaturePk(layerName ?? "");
// 재이용시설
if (featurePk) {
const lastPk =
@@ -254,139 +252,139 @@ const Map = () => {
const OVERLAY_MIN_ZOOM = 16;
const OVERLAY_COORD_PRECISION = 5;
const OVERLAY_MAX_PER_VIEW = 800;
const OVERLAY_COORD_PRECISION = 5;
const OVERLAY_MAX_PER_VIEW = 800;
const overlayManagersRef = useRef<any[]>([]);
const overlayActiveRef = useRef(false);
const moveEndDebounceRef = useRef<number | null>(null);
const overlayManagersRef = useRef<any[]>([]);
const overlayActiveRef = useRef(false);
const moveEndDebounceRef = useRef<number | null>(null);
// 반환: Promise<HTMLDivElement | null>
const overlayFormatter = async (feature: any, props: any) => {
const p = props || {};
const featureId =
feature.getId?.() ?? p?.id ?? p?.fid ?? p?.ftrIdn ?? '';
if (!featureId) return null;
// 반환: Promise<HTMLDivElement | null>
const overlayFormatter = async (feature: any, props: any) => {
const p = props || {};
const featureId =
feature.getId?.() ?? p?.id ?? p?.fid ?? p?.ftrIdn ?? '';
if (!featureId) return null;
const tableId = String(featureId).split('.')[0]??'';
const fcltCd = getFeatureCd(props, tableId);
const tableId = String(featureId).split('.')[0] ?? '';
const fcltCd = getFeatureCd(props, tableId);
if (!fcltCd) return null;
if (!fcltCd) return null;
let data: any = null;
let title = '';
let data: any = null;
let title = '';
if (tableId === 'tb_il_swage_prcs_fclt') { data = await pbnMapDetaile(fcltCd); title = '하수처리시설'; }
else if (tableId === 'tb_wr_bdst_ruse_fclt') { data = await getRuseMaplListReturn(fcltCd); title = '하수재이용시설'; }
else if (tableId === 'tb_wr_rnwtr_utztn_fclt'){ data = await rainMapDetile(fcltCd); title = '빗물이용시설'; }
else if (tableId === 'tb_wr_rswtr_fclt') { data = await rswtMapDetile(fcltCd); title = '중수도시설'; }
else if (tableId === 'tb_wr_htdfl_fclt') { data = await htdfMapDetile(fcltCd); title = '온배수시설'; }
else if (tableId === 'tb_wr_ruse_fclt_dmd_co'){ data = await coSttnMapDetail(fcltCd); title = '수요처'; }
else if (tableId === 'tb_wr_tmpr_dmd_co') { data = await ldrmntMapDetile(fcltCd); title = '잠재수요처'; }
if (tableId === 'tb_il_swage_prcs_fclt') { data = await pbnMapDetaile(fcltCd); title = '하수처리시설'; }
else if (tableId === 'tb_wr_bdst_ruse_fclt') { data = await getRuseMaplListReturn(fcltCd); title = '하수재이용시설'; }
else if (tableId === 'tb_wr_rnwtr_utztn_fclt') { data = await rainMapDetile(fcltCd); title = '빗물이용시설'; }
else if (tableId === 'tb_wr_rswtr_fclt') { data = await rswtMapDetile(fcltCd); title = '중수도시설'; }
else if (tableId === 'tb_wr_htdfl_fclt') { data = await htdfMapDetile(fcltCd); title = '온배수시설'; }
else if (tableId === 'tb_wr_ruse_fclt_dmd_co') { data = await coSttnMapDetail(fcltCd); title = '수요처'; }
else if (tableId === 'tb_wr_tmpr_dmd_co') { data = await ldrmntMapDetile(fcltCd); title = '잠재수요처'; }
const empty =
data == null ||
(Array.isArray(data) && data.length === 0) ||
(typeof data === 'object' && !Array.isArray(data) && Object.keys(data).length === 0);
const empty =
data == null ||
(Array.isArray(data) && data.length === 0) ||
(typeof data === 'object' && !Array.isArray(data) && Object.keys(data).length === 0);
if (empty) return null;
if (empty) return null;
const div = document.createElement('div');
const root = createRoot(div);
(div as any).__dispose = () => { try { root.unmount(); } catch {} };
root.render(<WrOverLay title={title} data={data} code={code} />);
return div; // ← 데이터 있을 때만 HTMLElement 반환
};
const destroyAllManagers = () => {
overlayManagersRef.current.forEach(m => { try { m.destroy(); } catch {} });
overlayManagersRef.current = [];
overlayActiveRef.current = false;
};
const div = document.createElement('div');
const root = createRoot(div);
(div as any).__dispose = () => { try { root.unmount(); } catch { } };
root.render(<WrOverLay title={title} data={data} code={code} />);
return div; // ← 데이터 있을 때만 HTMLElement 반환
};
const destroyAllManagers = () => {
overlayManagersRef.current.forEach(m => { try { m.destroy(); } catch { } });
overlayManagersRef.current = [];
overlayActiveRef.current = false;
};
const mountOverlayManagers = () => {
const map = gisMaps.current;
if (!map) return;
const mountOverlayManagers = () => {
const map = gisMaps.current;
if (!map) return;
// 이전 것 정리
destroyAllManagers();
// 이전 것 정리
destroyAllManagers();
// 체크된 벡터 레이어만 골라 매니저 생성
const checkedSet = new Set(checkedLayers.map(String));
const layers: any[] = map.getLayers().getArray();
const targets = layers.filter((layer: any) => {
const src = layer.getSource?.();
const isVector = src && typeof src.getFeatures === "function";
const id = String(layer.get?.("lyrSn") ?? layer.get?.("id") ?? "");
return isVector && layer.getVisible?.() && checkedSet.has(id);
});
targets.forEach((layer: any) => {
const mgr = createOverlayManager(map, layer, overlayFormatter, {
coordPrecision: OVERLAY_COORD_PRECISION,
maxOverlaysPerViewport: OVERLAY_MAX_PER_VIEW,
// 체크된 벡터 레이어만 골라 매니저 생성
const checkedSet = new Set(checkedLayers.map(String));
const layers: any[] = map.getLayers().getArray();
const targets = layers.filter((layer: any) => {
const src = layer.getSource?.();
const isVector = src && typeof src.getFeatures === "function";
const id = String(layer.get?.("lyrSn") ?? layer.get?.("id") ?? "");
return isVector && layer.getVisible?.() && checkedSet.has(id);
});
mgr.mount(); // 리스너 1회 등록
mgr.enable(); // 표시 + 1회 sync
overlayManagersRef.current.push(mgr);
});
overlayActiveRef.current = overlayManagersRef.current.length > 0;
};
targets.forEach((layer: any) => {
const mgr = createOverlayManager(map, layer, overlayFormatter, {
coordPrecision: OVERLAY_COORD_PRECISION,
maxOverlaysPerViewport: OVERLAY_MAX_PER_VIEW,
});
mgr.mount(); // 리스너 1회 등록
mgr.enable(); // 표시 + 1회 sync
overlayManagersRef.current.push(mgr);
});
useEffect(() => {
const map = gisMaps.current;
if (!map) return;
const z = map.getView()?.getZoom?.() ?? 0;
if (z < OVERLAY_MIN_ZOOM) {
// 저줌에선 그냥 안 보이게만
overlayManagersRef.current.forEach(m => { try { m.disable({ clear:true, delayed:true }); } catch {} });
return;
}
mountOverlayManagers();
return () => { destroyAllManagers(); };
}, [checkedLayers]);
useEffect(() => {
const map = gisMaps.current;
if (!map) return;
const onMoveStart = () => {
// 숨기기만 (리스너/DOM 대량 제거 X)
overlayManagersRef.current.forEach(m => { try { m.disable({ clear:false }); } catch {} });
if (moveEndDebounceRef.current) { clearTimeout(moveEndDebounceRef.current); moveEndDebounceRef.current = null; }
overlayActiveRef.current = overlayManagersRef.current.length > 0;
};
const onMoveEnd = () => {
useEffect(() => {
const map = gisMaps.current;
if (!map) return;
const z = map.getView()?.getZoom?.() ?? 0;
const active = overlayActiveRef.current;
if (z < OVERLAY_MIN_ZOOM) {
// 저줌에선 그냥 안 보이게만
overlayManagersRef.current.forEach(m => { try { m.disable({ clear: true, delayed: true }); } catch { } });
return;
}
mountOverlayManagers();
if (moveEndDebounceRef.current) clearTimeout(moveEndDebounceRef.current);
moveEndDebounceRef.current = window.setTimeout(() => {
if (z < OVERLAY_MIN_ZOOM) {
if (active) overlayManagersRef.current.forEach(m => { try { m.disable({ clear:true, delayed:true }); } catch {} });
return;
}
if (!active) {
mountOverlayManagers();
} else {
// 다시 보이고 1회만 동기화
overlayManagersRef.current.forEach(m => { try { m.enable(); m.syncOverlays(); } catch {} });
}
}, 180) as unknown as number;
};
return () => { destroyAllManagers(); };
}, [checkedLayers]);
map.on("movestart", onMoveStart);
map.on("moveend", onMoveEnd);
return () => {
map.un("movestart", onMoveStart);
map.un("moveend", onMoveEnd);
if (moveEndDebounceRef.current) { clearTimeout(moveEndDebounceRef.current); moveEndDebounceRef.current = null; }
};
}, [checkedLayers]);
useEffect(() => {
const map = gisMaps.current;
if (!map) return;
const onMoveStart = () => {
// 숨기기만 (리스너/DOM 대량 제거 X)
overlayManagersRef.current.forEach(m => { try { m.disable({ clear: false }); } catch { } });
if (moveEndDebounceRef.current) { clearTimeout(moveEndDebounceRef.current); moveEndDebounceRef.current = null; }
};
const onMoveEnd = () => {
const z = map.getView()?.getZoom?.() ?? 0;
const active = overlayActiveRef.current;
if (moveEndDebounceRef.current) clearTimeout(moveEndDebounceRef.current);
moveEndDebounceRef.current = window.setTimeout(() => {
if (z < OVERLAY_MIN_ZOOM) {
if (active) overlayManagersRef.current.forEach(m => { try { m.disable({ clear: true, delayed: true }); } catch { } });
return;
}
if (!active) {
mountOverlayManagers();
} else {
// 다시 보이고 1회만 동기화
overlayManagersRef.current.forEach(m => { try { m.enable(); m.syncOverlays(); } catch { } });
}
}, 180) as unknown as number;
};
map.on("movestart", onMoveStart);
map.on("moveend", onMoveEnd);
return () => {
map.un("movestart", onMoveStart);
map.un("moveend", onMoveEnd);
if (moveEndDebounceRef.current) { clearTimeout(moveEndDebounceRef.current); moveEndDebounceRef.current = null; }
};
}, [checkedLayers]);
return (
<div className="bg-container">
<Gis
@@ -24,6 +24,7 @@ import { Button, Label } from "@common/components/ui";
import { useEffect, useState } from "react";
import toast, { Toaster } from "react-hot-toast";
import { useTranslation } from "react-i18next";
import * as XLSX from "xlsx";
export default function RuseCaseMng() {
const { code, ruseCaseMng, selectRuseCaseMng, ruseCaseMngInit } = useWrStore(
@@ -76,7 +77,9 @@ export default function RuseCaseMng() {
};
useEffect(() => {
if (excelList !== undefined && excelList.length === 0) {
if (!excelList) return;
if (excelList.length === 0) {
toast.error(t("excelDownErrMsg"));
return;
}
@@ -86,74 +89,93 @@ export default function RuseCaseMng() {
}
// 받은 파일 바인너리 처리
const blobRet = await response.arrayBuffer();
if (excelList) {
const excelData1 = excelList.map((item) => {
return [
item.ruseBizNm,
item.bizBgngDate,
item.bizEndDate,
item.splyFcltKnd,
item.splyFcltNm,
item.splyFcltCpct,
item.dmdFcltNm,
item.dmdFcltAddr,
item.ruseFcltCpct,
item.ruseFcltPplLen,
item.ruseFcltUsg,
item.ruseFcltSplyCpct,
item.ruseFcltPrcsMsrc,
item.grnteWqUsg,
item.grnteWqGrssClfg,
item.grnteWqCombResdch,
item.grnteWqTrbt,
item.grnteWqBod,
item.grnteWqSmll,
item.grnteWqCrmty,
item.grnteWqTn,
item.grnteWqTp,
item.grnteWqPh,
item.grnteWqClIonQnt,
item.grnteWqCndctStat,
item.grnteWqRmrk,
item.reqBizGrssCst,
item.reqBizReuseFcltCst,
item.reqBizPplCst,
item.reqBizArchCst,
item.reqBizMchnCst,
item.reqBizMtrngCst,
item.reqBizGisCst,
item.reqBizCctvCst,
item.reqBizCmcnCst,
item.reqBizWstCst,
item.reqBizDesignCst,
item.reqBizSpvsCst,
item.reqBizSbsdCst,
item.reqBizEtc,
item.prcmPlanGrssCst,
item.prcmPlanNlep,
item.prcmPlanLcep,
item.prcmPlanBrdnCst,
item.prcmPlanEcqrRt,
item.clclnGrssCst,
item.clclnNlep,
item.clclnLcep,
item.clclnBrdnCst,
item.clclnEcqrRt,
];
});
const sheetParameter: SheetParameter[] = [
{
data: excelData1,
headerNum: 2,
headerRange: "A1:AX1",
sheetName: "물재이용사례",
startCol: "A",
},
const replaceHeaderText = (text: string) =>
text
.replaceAll("사업시작일", "사업시작년")
.replaceAll("사업종료일", "사업종료년");
const wb = XLSX.read(blobRet, { type: "array" });
wb.SheetNames.forEach((sheetName) => {
const sheet = wb.Sheets[sheetName];
if (!sheet) return;
Object.keys(sheet).forEach((addr) => {
if (addr.startsWith("!")) return;
const cell = sheet[addr] as XLSX.CellObject | undefined;
if (!cell || typeof cell.v !== "string") return;
const next = replaceHeaderText(cell.v);
if (next !== cell.v) cell.v = next;
});
});
const updatedBlob = XLSX.write(wb, { bookType: "xlsx", type: "array" });
const excelData1 = excelList.map((item) => {
return [
item.ruseBizNm,
item.bizBgngDate,
item.bizEndDate,
item.splyFcltKnd,
item.splyFcltNm,
item.splyFcltCpct,
item.dmdFcltNm,
item.dmdFcltAddr,
item.ruseFcltCpct,
item.ruseFcltPplLen,
item.ruseFcltUsg,
item.ruseFcltSplyCpct,
item.ruseFcltPrcsMsrc,
item.grnteWqUsg,
item.grnteWqGrssClfg,
item.grnteWqCombResdch,
item.grnteWqTrbt,
item.grnteWqBod,
item.grnteWqSmll,
item.grnteWqCrmty,
item.grnteWqTn,
item.grnteWqTp,
item.grnteWqPh,
item.grnteWqClIonQnt,
item.grnteWqCndctStat,
item.grnteWqRmrk,
item.reqBizGrssCst,
item.reqBizReuseFcltCst,
item.reqBizPplCst,
item.reqBizArchCst,
item.reqBizMchnCst,
item.reqBizMtrngCst,
item.reqBizGisCst,
item.reqBizCctvCst,
item.reqBizCmcnCst,
item.reqBizWstCst,
item.reqBizDesignCst,
item.reqBizSpvsCst,
item.reqBizSbsdCst,
item.reqBizEtc,
item.prcmPlanGrssCst,
item.prcmPlanNlep,
item.prcmPlanLcep,
item.prcmPlanBrdnCst,
item.prcmPlanEcqrRt,
item.clclnGrssCst,
item.clclnNlep,
item.clclnLcep,
item.clclnBrdnCst,
item.clclnEcqrRt,
];
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
await filePickedBlobArray(blobRet, "물재이용사례현황", sheetParameter);
}
});
const sheetParameter: SheetParameter[] = [
{
data: excelData1,
headerNum: 2,
headerRange: "A1:AX1",
sheetName: "물재이용사례",
startCol: "A",
},
];
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
await filePickedBlobArray(updatedBlob, "물재이용사례현황", sheetParameter);
});
}, [excelList]);
@@ -299,8 +321,12 @@ export default function RuseCaseMng() {
}}
resetPageNo={resetPage}
/>
<span className="text-2xl font-bold text-gray-500">
☞ 본 사례의 사업비는 재원협의 단계의 정보이므로, 최종확정된 비용이 아닙니다.
</span>
</div>
</ListDiv>
</div>
</div>
</ContentsDiv>
@@ -1,3 +1,19 @@
/**
* 재이용시설 등록 - 하수재이용 시설등록
*
* - layout.tsx에 의해 공통 레이아웃이 적용됨
* - with-layout 적용
* - 하수처리시설에 하수재이용 시설을 등록 한다.
* - form으로 시설정보 및 차수별 정보의 컴포넌트 데이터를 관리한다
* indexMng: 시설정보
* indexBiz: 차수별 정보
* 로 하수재이용 시설에 등록된 시설 및 차수별 정보를 관리한다.
* 🔗 사용 API
* 하수재이용시설을 등록 /reuseFc/pubFc
* 첨부파일 삭제 /attach-service/api/v1/atfl/attachments/atflCd//
* 첨부파일 다운로드 /attach-service/api/v1/atflcd/download/
* */
"use client";
import {
ContentsDiv,
@@ -35,18 +51,6 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { createDefaultPbnstItem } from "./utilsZod";
import { useTranslation } from "react-i18next";
/**
* 재이용시설 등록 - 하수재이용 시설등록
*
* - layout.tsx에 의해 공통 레이아웃이 적용됨
* - with-layout 적용
* - 하수처리시설에 하수재이용 시설을 등록 한다.
* - form으로 시설정보 및 차수별 정보의 컴포넌트 데이터를 관리한다
* indexMng: 시설정보
* indexBiz: 차수별 정보
* 로 하수재이용 시설에 등록된 시설 및 차수별 정보를 관리한다.
* */
export default function PublicReuseFaciltyInsert() {
const {
auth,
@@ -104,7 +108,7 @@ export default function PublicReuseFaciltyInsert() {
useEffect(() => {
if (useInitRef.current == true && laeSeCd !== undefined) {
pubHasuInit("1", laeSeCd);
pubHasuInit("1", laeSeCd); //page: string, sggOrCity: string
}
}, [useInitRef.current, laeSeCd]);
@@ -1,5 +1,7 @@
/**
* 온배수시설 현황
*/
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import type {
@@ -34,11 +36,9 @@ import toast, { Toaster } from "react-hot-toast";
import { useTranslation } from "react-i18next";
export default function HtdflSttn() {
const { code, htdflSttn, htdflSttnSearch, initHtdfl } = useWrStore(
(state) => state
);
const { auth, code, htdflSttn, htdflSttnSearch, initHtdfl } = useWrStore((state) => state);
const { laeSeCd } = auth; // 지자체구분코드
const { htdflSttnRes, htdflSttnResCount } = htdflSttn;
const isDownloadTriggered = useRef(false);
const { t } = useTranslation('base');
const [pageNation, setPageNation] = useState(1);
@@ -57,6 +57,7 @@ export default function HtdflSttn() {
// }>({ isOpen: false, chBuilding: [] });
const [fcltNm, setFcltNm] = useState<string>("");
console.log("laeSeCd : ", laeSeCd);
useEffect(() => {
htdflSttnSearch(false, pageNation, htdflSttnSize, String(getConValue()), fcltNm, code.cityCd, code.sggCd);
isResetPage(false)
@@ -1,3 +1,12 @@
/**
* 하수재이용 시설 현황
* 재이용시설 현황 - 하수재이용시설 현황
* - layout.tsx에 의해 공통 레이아웃이 적용됨
* - with-layout 적용
* 하수처리시설. 하수재이용시설 , 하수재이용시설 실적에 대한 정보를 확인한다.
* 모달 : 테이블의 헤더를 원하는대로 조절해서 볼수 있다.
* 클릭시 해당 재이용ㅇ
* */
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
@@ -24,15 +33,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
import toast, { Toaster } from "react-hot-toast";
import { useTranslation } from "react-i18next";
/**
* 하수재이용 시설 현황
* 재이용시설 현황 - 하수재이용시설 현황
* - layout.tsx에 의해 공통 레이아웃이 적용됨
* - with-layout 적용
* 하수처리시설. 하수재이용시설 , 하수재이용시설 실적에 대한 정보를 확인한다.
* 모달 : 테이블의 헤더를 원하는대로 조절해서 볼수 있다.
* 클릭시 해당 재이용ㅇ
* */
export default function PbnstSttn() {
const {
code,
@@ -1,3 +1,6 @@
/**
* 빗물재이용시설 현황
*/
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
@@ -1,3 +1,6 @@
/**
* 중수도시설 현황
*/
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";

Some files were not shown because too many files have changed in this diff Show More