Merge branch 'main' into eunsun
This commit is contained in:
@@ -5,6 +5,7 @@ NEXT_PUBLIC_AUTH_USER_ID = token-id
|
|||||||
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||||
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300
|
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300
|
||||||
|
NEXT_PUBLIC_SUB_DOMAIN = http://con.mind-one.co.kr:11300
|
||||||
NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://dev.onasys.co.kr:3000/auth/login
|
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:11082
|
||||||
NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11083/operation-service
|
NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11083/operation-service
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from "next/server";
|
|||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
const hostname = request.nextUrl.hostname;
|
const hostname = request.nextUrl.hostname;
|
||||||
const redirectUrl = process.env.NEXT_PUBLIC_CM_LOGIN_PAGE_URL || "https://queen.hasuon.or.kr";
|
const redirectUrl = process.env.NEXT_PUBLIC_CM_LOGIN_PAGE_URL || "https://portal.hasuon.or.kr";
|
||||||
|
|
||||||
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr") {
|
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr") {
|
||||||
return NextResponse.redirect(new URL("/", request.url)); // 로컬 및 개발 환경
|
return NextResponse.redirect(new URL("/", request.url)); // 로컬 및 개발 환경
|
||||||
|
|||||||
+13
-18
@@ -11,25 +11,20 @@ export default function Home() {
|
|||||||
const checkToken = getCookie(AUTH_USER_ID);
|
const checkToken = getCookie(AUTH_USER_ID);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const hostname = window.location.hostname;
|
||||||
|
|
||||||
if (!checkToken) {
|
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr") {
|
||||||
// 외부 URL로 이동해야 할 경우 location.replace를 사용합니다.
|
if (!checkToken) {
|
||||||
if (window.location.hostname.includes("hasuon.or.kr")) {
|
async function doLogin() {
|
||||||
location.replace(process.env.NEXT_PUBLIC_CM_LOGIN_PAGE_URL||'/pages/dashboard');
|
try {
|
||||||
return; // 페이지 이동 후에는 더 이상 로직을 실행하지 않습니다.
|
await LoginApi.login({ userId: "CLEANWATER", password: "gktneh12!@" });
|
||||||
}
|
window.location.href = "/pages/dashboard";
|
||||||
|
} catch (err) {
|
||||||
async function doLogin() {
|
console.error("로그인 실패", err);
|
||||||
try {
|
}
|
||||||
await LoginApi.login({ userId: "CLEANWATER", password: "gktneh12!@" });
|
|
||||||
router.push("/pages/dashboard"); // location.href 대신 router.push 사용
|
|
||||||
} catch (err) {
|
|
||||||
console.error("로그인 실패", err);
|
|
||||||
}
|
}
|
||||||
}
|
doLogin();
|
||||||
doLogin();
|
} else router.push("/pages/dashboard");
|
||||||
} else {
|
} else router.push("/pages/dashboard");
|
||||||
router.push("/pages/dashboard");
|
|
||||||
}
|
|
||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ import { roundNumber } from "@/app/components/common/DataForm";
|
|||||||
|
|
||||||
const tabList = [
|
const tabList = [
|
||||||
{ value: 'facilityInfo', label: '시설정보 및 운영현황' },
|
{ value: 'facilityInfo', label: '시설정보 및 운영현황' },
|
||||||
{ value: 'mainGraph', label: '주요그래프' },
|
{ value: 'mainGraph', label: '주요그래프' },
|
||||||
{ value: 'rainManage', label: '강우일 운영현황' },
|
{ value: 'rainManage', label: '강우일 운영현황' },
|
||||||
//{ value: 'drainageEquipment', label: '배수설비 정비현황' }
|
//{ value: 'drainageEquipment', label: '배수설비 정비현황' }
|
||||||
];
|
];
|
||||||
@@ -42,7 +42,7 @@ export const generateYearDates = (searchYear: string) => {
|
|||||||
|
|
||||||
export default function DashBoard() {
|
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 [activeTab, setActiveTab] = useState<string>('facilityInfo');
|
||||||
|
|
||||||
const [filteredSigunData, setFilteredSigunData] = useState<SelectDataType[]>([{ text: "전체", val: '0' }]);
|
const [filteredSigunData, setFilteredSigunData] = useState<SelectDataType[]>([{ text: "전체", val: '0' }]);
|
||||||
@@ -82,7 +82,7 @@ export default function DashBoard() {
|
|||||||
// 연도
|
// 연도
|
||||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || '0');
|
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || '0');
|
||||||
// 시설명
|
// 시설명
|
||||||
const [fcltyList, setFcltyList] = useState<{bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | ''}>({
|
const [fcltyList, setFcltyList] = useState<{ bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | '' }>({
|
||||||
bscFctCd: '11000SW001R',
|
bscFctCd: '11000SW001R',
|
||||||
bscFctNm: '난지',
|
bscFctNm: '난지',
|
||||||
fcltyCpc: 860000,
|
fcltyCpc: 860000,
|
||||||
@@ -90,7 +90,7 @@ export default function DashBoard() {
|
|||||||
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
|
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
|
||||||
});
|
});
|
||||||
|
|
||||||
const [searchFcltyList, setSearchFcltyList] = useState<{bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | ''}>({
|
const [searchFcltyList, setSearchFcltyList] = useState<{ bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | '' }>({
|
||||||
bscFctCd: '',
|
bscFctCd: '',
|
||||||
bscFctNm: '',
|
bscFctNm: '',
|
||||||
fcltyCpc: '',
|
fcltyCpc: '',
|
||||||
@@ -116,7 +116,7 @@ export default function DashBoard() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onSelectValue = (val: string, type: string) => {
|
const onSelectValue = (val: string, type: string) => {
|
||||||
switch(type) {
|
switch (type) {
|
||||||
case 'sido':
|
case 'sido':
|
||||||
setSidoValue(val);
|
setSidoValue(val);
|
||||||
initializeSigunData(val);
|
initializeSigunData(val);
|
||||||
@@ -147,8 +147,8 @@ export default function DashBoard() {
|
|||||||
if (!fcltyList.bscFctCd) return;
|
if (!fcltyList.bscFctCd) return;
|
||||||
|
|
||||||
switch (activeTab) {
|
switch (activeTab) {
|
||||||
case 'facilityInfo':
|
case 'facilityInfo': // 시설정보 및 운영현황
|
||||||
searchOperationStatus(false, searchYear, fcltyList.bscFctCd).then(() => {setTimeout(() => {makeExcelData();}, 200);});
|
searchOperationStatus(false, searchYear, fcltyList.bscFctCd).then(() => { setTimeout(() => { makeExcelData(); }, 200); });
|
||||||
|
|
||||||
const makeExcelData = async () => {
|
const makeExcelData = async () => {
|
||||||
fetch(`/mainDashBoard.xlsx`, {}).then(async (response) => {
|
fetch(`/mainDashBoard.xlsx`, {}).then(async (response) => {
|
||||||
@@ -161,7 +161,7 @@ export default function DashBoard() {
|
|||||||
const excelData1 = planFcltyList.map((item) => {
|
const excelData1 = planFcltyList.map((item) => {
|
||||||
return [
|
return [
|
||||||
item.item,
|
item.item,
|
||||||
item.provisionalApproval?Number(item.provisionalApproval.toString().replaceAll(',',''))?Number(item.provisionalApproval.toString().replaceAll(',','')):item.provisionalApproval:'',
|
item.provisionalApproval ? Number(item.provisionalApproval.toString().replaceAll(',', '')) ? Number(item.provisionalApproval.toString().replaceAll(',', '')) : item.provisionalApproval : '',
|
||||||
item.now,
|
item.now,
|
||||||
item.stepOne,
|
item.stepOne,
|
||||||
item.stepTwo,
|
item.stepTwo,
|
||||||
@@ -172,25 +172,25 @@ export default function DashBoard() {
|
|||||||
|
|
||||||
// operationalStatusList를 2차원 배열로 변환
|
// operationalStatusList를 2차원 배열로 변환
|
||||||
const excelData2 = operationalStatusList.map((item, index) => {
|
const excelData2 = operationalStatusList.map((item, index) => {
|
||||||
console.log(item.yearAvg+' '+item.yearMax+' '+item.yearMin);
|
console.log(item.yearAvg + ' ' + item.yearMax + ' ' + item.yearMin);
|
||||||
const baseData = [
|
const baseData = [
|
||||||
Number(item.yearAvg?.toString().replaceAll(',','')),
|
Number(item.yearAvg?.toString().replaceAll(',', '')),
|
||||||
Number(item.yearMax?.toString().replaceAll(',','')),
|
Number(item.yearMax?.toString().replaceAll(',', '')),
|
||||||
Number(item.yearMin?.toString().replaceAll(',','')),
|
Number(item.yearMin?.toString().replaceAll(',', '')),
|
||||||
Number(item.summerAll?.toString().replaceAll(',','')),
|
Number(item.summerAll?.toString().replaceAll(',', '')),
|
||||||
Number(item.summerThree?.toString().replaceAll(',','')),
|
Number(item.summerThree?.toString().replaceAll(',', '')),
|
||||||
Number(item.summerRain?.toString().replaceAll(',','')),
|
Number(item.summerRain?.toString().replaceAll(',', '')),
|
||||||
Number(item.winterAll?.toString().replaceAll(',','')),
|
Number(item.winterAll?.toString().replaceAll(',', '')),
|
||||||
Number(item.winterSunnyAvg?.toString().replaceAll(',','')),
|
Number(item.winterSunnyAvg?.toString().replaceAll(',', '')),
|
||||||
Number(item.winterSunnyMax?.toString().replaceAll(',','')),
|
Number(item.winterSunnyMax?.toString().replaceAll(',', '')),
|
||||||
Number(item.winterSunnyMin?.toString().replaceAll(',','')),
|
Number(item.winterSunnyMin?.toString().replaceAll(',', '')),
|
||||||
Number(item.groundWaterAvg?.toString().replaceAll(',','').replaceAll('%','')),
|
Number(item.groundWaterAvg?.toString().replaceAll(',', '').replaceAll('%', '')),
|
||||||
Number(item.groundWaterSummer?.toString().replaceAll(',','').replaceAll('%','')),
|
Number(item.groundWaterSummer?.toString().replaceAll(',', '').replaceAll('%', '')),
|
||||||
Number(item.groundWaterWinter?.toString().replaceAll(',','').replaceAll('%',''))
|
Number(item.groundWaterWinter?.toString().replaceAll(',', '').replaceAll('%', ''))
|
||||||
];
|
];
|
||||||
|
|
||||||
// index가 0일 때만 rdi와 rdiRain 추가
|
// index가 0일 때만 rdi와 rdiRain 추가
|
||||||
return index === 0 ? [...baseData, item.rdi&&item.rdi.toString().trim()!=''?Number(item.rdi.toString().replaceAll(',','')):'', item.rdiRain&&item.rdiRain.toString().trim()!=''?Number(item.rdiRain.toString().replaceAll(',','')):''] : baseData;
|
return index === 0 ? [...baseData, item.rdi && item.rdi.toString().trim() != '' ? Number(item.rdi.toString().replaceAll(',', '')) : '', item.rdiRain && item.rdiRain.toString().trim() != '' ? Number(item.rdiRain.toString().replaceAll(',', '')) : ''] : baseData;
|
||||||
});
|
});
|
||||||
|
|
||||||
const sheetParameter = [
|
const sheetParameter = [
|
||||||
@@ -215,32 +215,32 @@ export default function DashBoard() {
|
|||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'mainGraph':
|
case 'mainGraph': // 주요그래프
|
||||||
searchMainGraph(searchYear, fcltyList.bscFctCd);
|
searchMainGraph(searchYear, fcltyList.bscFctCd);
|
||||||
const yearData = generateYearDates(searchYear);
|
const yearData = generateYearDates(searchYear);
|
||||||
const yearValueData : any = [];
|
const yearValueData: any = [];
|
||||||
|
|
||||||
for (const i in yearData){
|
for (const i in yearData) {
|
||||||
const rowArray: string[] = [];
|
const rowArray: string[] = [];
|
||||||
rowArray.push(yearData[i] ?? "");
|
rowArray.push(yearData[i] ?? "");
|
||||||
//강수량
|
//강수량
|
||||||
rowArray.push(roundNumber(chart_inflowRain.filter(item=>{return yearData[i] === item.label})[0]?.barVal0?.toString(), 1) || '');
|
rowArray.push(roundNumber(chart_inflowRain.filter(item => { return yearData[i] === item.label })[0]?.barVal0?.toString(), 1) || '');
|
||||||
//유입하수량
|
//유입하수량
|
||||||
rowArray.push(roundNumber(chart_inflowRain.filter(item=>{return yearData[i] === item.label})[0]?.lineVal1?.toString(), 0) || '');
|
rowArray.push(roundNumber(chart_inflowRain.filter(item => { return yearData[i] === item.label })[0]?.lineVal1?.toString(), 0) || '');
|
||||||
//시설용량
|
//시설용량
|
||||||
rowArray.push(roundNumber(chart_inflowRain.filter(item=>{return yearData[i] === item.label})[0]?.lineVal0?.toString(), 0) || '');
|
rowArray.push(roundNumber(chart_inflowRain.filter(item => { return yearData[i] === item.label })[0]?.lineVal0?.toString(), 0) || '');
|
||||||
//유입BOD
|
//유입BOD
|
||||||
rowArray.push(roundNumber(chart_bodRain.filter(item=>{return yearData[i] === item.label})[0]?.lineVal0?.toString(), 1) || '');
|
rowArray.push(roundNumber(chart_bodRain.filter(item => { return yearData[i] === item.label })[0]?.lineVal0?.toString(), 1) || '');
|
||||||
//유입T-P
|
//유입T-P
|
||||||
rowArray.push(roundNumber(chart_inflTp.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || '');
|
rowArray.push(roundNumber(chart_inflTp.filter(item => { return yearData[i] === item.label })[0]?.val?.toString(), 3) || '');
|
||||||
//총인유입T-P
|
//총인유입T-P
|
||||||
rowArray.push(roundNumber(chart_chongInTp.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || '');
|
rowArray.push(roundNumber(chart_chongInTp.filter(item => { return yearData[i] === item.label })[0]?.val?.toString(), 3) || '');
|
||||||
//방류T-P
|
//방류T-P
|
||||||
rowArray.push(roundNumber(chart_efflTp.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || '');
|
rowArray.push(roundNumber(chart_efflTp.filter(item => { return yearData[i] === item.label })[0]?.val?.toString(), 3) || '');
|
||||||
//유입T-N
|
//유입T-N
|
||||||
rowArray.push(roundNumber(chart_inflTn.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || '');
|
rowArray.push(roundNumber(chart_inflTn.filter(item => { return yearData[i] === item.label })[0]?.val?.toString(), 3) || '');
|
||||||
//방류T-N
|
//방류T-N
|
||||||
rowArray.push(roundNumber(chart_efflTn.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || '');
|
rowArray.push(roundNumber(chart_efflTn.filter(item => { return yearData[i] === item.label })[0]?.val?.toString(), 3) || '');
|
||||||
|
|
||||||
yearValueData.push(
|
yearValueData.push(
|
||||||
rowArray
|
rowArray
|
||||||
@@ -250,7 +250,7 @@ export default function DashBoard() {
|
|||||||
|
|
||||||
const sheetParameter = [
|
const sheetParameter = [
|
||||||
{
|
{
|
||||||
data: [['날짜', '강수량', '유입하수량', '지하수유입량', '유입BOD', '유입T-P','총인유입T-P', '방류T-P', '유입T-N', '방류T-N'],...yearValueData],
|
data: [['날짜', '강수량', '유입하수량', '지하수유입량', '유입BOD', '유입T-P', '총인유입T-P', '방류T-P', '유입T-N', '방류T-N'], ...yearValueData],
|
||||||
headerNum: 1,
|
headerNum: 1,
|
||||||
headerRange: 'A1:J1',
|
headerRange: 'A1:J1',
|
||||||
sheetName: '주요그래프'
|
sheetName: '주요그래프'
|
||||||
@@ -314,7 +314,7 @@ export default function DashBoard() {
|
|||||||
downloadMultipleExcel('주요그래프', sheetParameter);
|
downloadMultipleExcel('주요그래프', sheetParameter);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'rainManage':
|
case 'rainManage': // 강우일 운영현황
|
||||||
searchRainManage(searchYear, fcltyList.bscFctCd, true);
|
searchRainManage(searchYear, fcltyList.bscFctCd, true);
|
||||||
if (excelList && excelList.length > 0) {
|
if (excelList && excelList.length > 0) {
|
||||||
downloadExcel({ data: excelList as unknown as JSON[], fileName: '강우일 운영현황', sheetNameArray: ['강우일 운영현황'], headerRange: 'A1:T1' });
|
downloadExcel({ data: excelList as unknown as JSON[], fileName: '강우일 운영현황', sheetNameArray: ['강우일 운영현황'], headerRange: 'A1:T1' });
|
||||||
@@ -351,7 +351,7 @@ export default function DashBoard() {
|
|||||||
|
|
||||||
const searchVal = () => {
|
const searchVal = () => {
|
||||||
setSearchFcltyList(fcltyList);
|
setSearchFcltyList(fcltyList);
|
||||||
if(searchFcltyList.bscFctCd) {
|
if (searchFcltyList.bscFctCd) {
|
||||||
searchOperationStatus(false, searchYear, fcltyList.bscFctCd);
|
searchOperationStatus(false, searchYear, fcltyList.bscFctCd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -361,11 +361,11 @@ export default function DashBoard() {
|
|||||||
<ContentsDiv>
|
<ContentsDiv>
|
||||||
<div className="flex card card-border !mt-6">
|
<div className="flex card card-border !mt-6">
|
||||||
<div className="grid grid-cols-12 gap-5 w-8/12 m-4">
|
<div className="grid grid-cols-12 gap-5 w-8/12 m-4">
|
||||||
<SelectBox className="col-span-2" label={'연도'} selectArray={selectSearchYear} onSelectValue={ (val) => setSearchYear(val.toString()) } value={searchYear} selectClass={undefined}/>
|
<SelectBox className="col-span-2" label={'연도'} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
|
||||||
<SelectBox className="col-span-3" label={'시도'} selectArray={selectSidoData} onSelectValue={(val) => onSelectValue(val.toString(), 'sido')} value={sidoValue} selectClass={undefined}/>
|
<SelectBox className="col-span-3" label={'시도'} selectArray={selectSidoData} onSelectValue={(val) => onSelectValue(val.toString(), 'sido')} value={sidoValue} selectClass={undefined} />
|
||||||
<SelectBox className="col-span-3" label={'시군구'} selectArray={filteredSigunData} onSelectValue={(val) => onSelectValue(val.toString(), 'sigun')} value={sigunValue} selectClass={undefined}/>
|
<SelectBox className="col-span-3" label={'시군구'} selectArray={filteredSigunData} onSelectValue={(val) => onSelectValue(val.toString(), 'sigun')} value={sigunValue} selectClass={undefined} />
|
||||||
<div className="col-span-4 flex">
|
<div className="col-span-4 flex">
|
||||||
<DashBoardFclty onFacilityChange={handleFacilityChange} sidoSigun={sigunValue!='0'?sigunValue:sidoValue!='0'?sidoValue:''} facilityNm={searchFcltyList.bscFctNm}></DashBoardFclty>
|
<DashBoardFclty onFacilityChange={handleFacilityChange} sidoSigun={sigunValue != '0' ? sigunValue : sidoValue != '0' ? sidoValue : ''} facilityNm={searchFcltyList.bscFctNm}></DashBoardFclty>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-4/12 mx-5 flex items-center justify-end space-x-2">
|
<div className="w-4/12 mx-5 flex items-center justify-end space-x-2">
|
||||||
@@ -385,13 +385,13 @@ export default function DashBoard() {
|
|||||||
<ProcessFacilitySearch searchYear={searchYear} fcltyList={[searchFcltyList]} onFacilityChange={handleFacilityChange} />
|
<ProcessFacilitySearch searchYear={searchYear} fcltyList={[searchFcltyList]} onFacilityChange={handleFacilityChange} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="mainGraph">
|
<TabsContent value="mainGraph">
|
||||||
<DashBoardChart searchYear={searchYear} fcltyList={[searchFcltyList]}/>
|
<DashBoardChart searchYear={searchYear} fcltyList={[searchFcltyList]} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="rainManage">
|
<TabsContent value="rainManage">
|
||||||
<RainManageTab searchYear={searchYear} fcltyList={[searchFcltyList]}/>
|
<RainManageTab searchYear={searchYear} fcltyList={[searchFcltyList]} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="drainageEquipment">
|
<TabsContent value="drainageEquipment">
|
||||||
<DrainageEquipment searchYear={searchYear} fcltyList={[searchFcltyList]}/>
|
<DrainageEquipment searchYear={searchYear} fcltyList={[searchFcltyList]} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</UITab>
|
</UITab>
|
||||||
</ContentsDiv>
|
</ContentsDiv>
|
||||||
|
|||||||
@@ -1,37 +1,33 @@
|
|||||||
import DataForm from "@/app/components/common/DataForm";
|
import DataForm from "@/app/components/common/DataForm";
|
||||||
import type { TableUpperProps } from "../dashboard";
|
import type { TableUpperProps } from "../dashboard";
|
||||||
import { getFetch } from "@/app/components/api";
|
import { getFetch, postFetch } from "@/app/components/api";
|
||||||
import { type ApiResponse, type FlowDataItem } from "../underWaterInput";
|
import { type ApiResponse } from "../underWaterInput";
|
||||||
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
|
// import CalcRainEffect from "@/app/components/common/CalcRainEffect";
|
||||||
import { roundUp } from "../common";
|
import { roundUp } from "../common";
|
||||||
export type { TableUpperProps };
|
export type { TableUpperProps };
|
||||||
/**====================================
|
|
||||||
* Store - 타입
|
|
||||||
====================================*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (1) 메인페이지
|
* 처리시설 연간 운영현황 > 계획하수량 산정지표 현황
|
||||||
*/
|
*/
|
||||||
// 시설별 강수현황
|
// 시설별 강수현황
|
||||||
type PlanSewageProps = {
|
type PlanSewageProps = {
|
||||||
bscFctCd : string,
|
bscFctCd: string,
|
||||||
sido : string,
|
sido: string,
|
||||||
gugun : string,
|
gugun: string,
|
||||||
bscFctNm : string,
|
bscFctNm: string,
|
||||||
daddr : string,
|
daddr: string,
|
||||||
fctCpc : number,
|
fctCpc: number,
|
||||||
spareCapacity : number,
|
spareCapacity: number,
|
||||||
variableLoadPercent : number,
|
variableLoadPercent: number,
|
||||||
classifiedSewerPercent : number,
|
classifiedSewerPercent: number,
|
||||||
rgnNm : string,
|
rgnNm: string,
|
||||||
rvbsn : string,
|
rvbsn: string,
|
||||||
lgbsn : string,
|
lgbsn: string,
|
||||||
mdmbsn : string,
|
mdmbsn: string,
|
||||||
sprtProcZoneAr : number,
|
sprtProcZoneAr: number,
|
||||||
procZoneSm : number,
|
procZoneSm: number,
|
||||||
avgInflAmnt : number,
|
avgInflAmnt: number,
|
||||||
avgInflAmntSunny : number,
|
avgInflAmntSunny: number,
|
||||||
maxInflAmntSunny : number,
|
maxInflAmntSunny: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**====================================
|
/**====================================
|
||||||
@@ -42,88 +38,133 @@ type PlanSewageProps = {
|
|||||||
* (1) 메인페이지
|
* (1) 메인페이지
|
||||||
*/
|
*/
|
||||||
// 검색단
|
// 검색단
|
||||||
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
const LabelArray: string[] = ['구분', '시도', '시군구', '용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
||||||
|
|
||||||
// 리스트 헤더
|
// 리스트 헤더
|
||||||
const upHeadList1:TableUpperProps[] = [
|
const upHeadList1: TableUpperProps[] = [
|
||||||
{ id: "A", title: "행정구역", upSequnce:1, row:0, colSpan:2 },
|
{ id: "A", title: "행정구역", upSequnce: 1, row: 0, colSpan: 2 },
|
||||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row:1, widthPercent: 10 },
|
{ id: "sido", title: "시도", upName: "upChangeRe", upSequnce: 1, row: 1, widthPercent: 10 },
|
||||||
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1, widthPercent: 10 },
|
{ id: "gugun", title: "시군구", upName: "upChangeRe", upSequnce: 2, row: 1, widthPercent: 10 },
|
||||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 10 },
|
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 10 },
|
||||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||||
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2, align: 'right', widthPercent: 8 },
|
||||||
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
{ id: "spareCapacity", title: "여유용량(m³/일)", row: 0, rowSpan: 2, align: 'right', widthPercent: 8 },
|
||||||
{ id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
{ id: "variableLoadPercent", title: "변동부하율(%)", row: 0, rowSpan: 2, align: 'right', widthPercent: 8 },
|
||||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row: 0, rowSpan: 2, align: 'right', widthPercent: 8 },
|
||||||
];
|
];
|
||||||
|
|
||||||
const upHeadList2:TableUpperProps[] = [
|
const upHeadList2: TableUpperProps[] = [
|
||||||
{ id: "A", title: "유역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:3 },
|
{ id: "A", title: "유역", upName: "upChangeRe", upSequnce: 1, row: 0, colSpan: 3 },
|
||||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1, widthPercent: 8 },
|
{ id: "rvbsn", title: "권역", upName: "upChangeRe", upSequnce: 1, row: 1, widthPercent: 8 },
|
||||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1, widthPercent: 8},
|
{ id: "lgbsn", title: "단위유역", upName: "upChangeRe", upSequnce: 2, row: 1, widthPercent: 8 },
|
||||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row:1, widthPercent: 8},
|
{ id: "mdmbsn", title: "중권역", upName: "upChangeRe", upSequnce: 3, row: 1, widthPercent: 8 },
|
||||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 10 },
|
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 10 },
|
||||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||||
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2, align: 'right', widthPercent: 8 },
|
||||||
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
{ id: "spareCapacity", title: "여유용량(m³/일)", row: 0, rowSpan: 2, align: 'right', widthPercent: 8 },
|
||||||
{ id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
{ id: "variableLoadPercent", title: "변동부하율(%)", row: 0, rowSpan: 2, align: 'right', widthPercent: 8 },
|
||||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row: 0, rowSpan: 2, align: 'right', widthPercent: 8 },
|
||||||
];
|
];
|
||||||
|
|
||||||
const upHeadList3:TableUpperProps[] = [
|
const upHeadList3: TableUpperProps[] = [
|
||||||
{ id: "A", title: "유역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:3 },
|
{ id: "A", title: "유역", upName: "upChangeRe", upSequnce: 1, row: 0, colSpan: 3 },
|
||||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1, widthPercent: 5 },
|
{ id: "rvbsn", title: "권역", upName: "upChangeRe1", upSequnce: 1, row: 1, widthPercent: 5 },
|
||||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, 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: "mdmbsn", title: "중권역", upName: "upChangeRe1", upSequnce: 3, row: 1, widthPercent: 5 },
|
||||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "rgnNm", title: "환경청", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "B", title: "행정구역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:2 },
|
{ id: "B", title: "행정구역", upName: "upChangeRe", upSequnce: 1, row: 0, colSpan: 2 },
|
||||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1, widthPercent: 5 },
|
{ id: "sido", title: "시도", upName: "upChangeRe2", upSequnce: 1, row: 1, widthPercent: 5 },
|
||||||
{ id: "gugun", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1, widthPercent: 5 },
|
{ id: "gugun", title: "시군구", upName: "upChangeRe2", upSequnce: 2, row: 1, widthPercent: 5 },
|
||||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 10 },
|
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 10 },
|
||||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||||
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2, align: 'right', widthPercent: 8 },
|
||||||
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
{ id: "spareCapacity", title: "여유용량(m³/일)", row: 0, rowSpan: 2, align: 'right', widthPercent: 8 },
|
||||||
{ id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
{ id: "variableLoadPercent", title: "변동부하율(%)", row: 0, rowSpan: 2, align: 'right', widthPercent: 8 },
|
||||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row: 0, rowSpan: 2, align: 'right', widthPercent: 8 },
|
||||||
];
|
];
|
||||||
|
|
||||||
const planSewageList:PlanSewageProps[] = [
|
const planSewageList: PlanSewageProps[] = [
|
||||||
]
|
]
|
||||||
|
|
||||||
/**====================================
|
/**====================================
|
||||||
* Store - api
|
* Store - api
|
||||||
====================================*/
|
====================================*/
|
||||||
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 : '') : '';
|
/**
|
||||||
|
* 계획시설정보 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
|
||||||
|
* @param pageNo : 페이지 번호
|
||||||
|
* @param pageSize : 페이지 크기
|
||||||
|
* @param searchYear : 검색년도
|
||||||
|
* @param partCd : 구분코드
|
||||||
|
* @param nameCd : 행정코드(시도명, 시군구명, 단위유역)
|
||||||
|
* @param fcltCpct : 시설용량
|
||||||
|
* @param oprtngSttsCd : 운영 상태 코드
|
||||||
|
* @param facilityName : 시설명
|
||||||
|
*/
|
||||||
|
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 url = '/prcsFclt/info/plan/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||||
const res = await getFetch('fo', url);
|
const res = await getFetch('fo', url);
|
||||||
return { data: res.data, count: res.count }
|
return { data: res.data, count: res.count }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 분류식화율 구하기 위한 api 호출
|
||||||
|
const fetchPlanZoneList = async (searchYear: string, fcltCdList: string[]) => {
|
||||||
|
try {
|
||||||
|
const res = await postFetch('fo', '/prcsFclt/info/planZone/' + searchYear, fcltCdList);
|
||||||
|
return res;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('시설정보 오수발생량 상세 데이터를 가져오는데 실패했습니다:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 시설들 유량 정보 조회
|
||||||
|
// export const fetchFlow = async (searchYear: string | undefined, fcltCdList: string[]): Promise<ApiResponse | null> => {
|
||||||
|
// try {
|
||||||
|
// const params = new URLSearchParams();
|
||||||
|
// fcltCdList.forEach(cd => params.append('fcltCds', cd));
|
||||||
|
// const res = await getFetch('fo', '/fclt/flow/' + searchYear + '?' + params.toString());
|
||||||
|
// return res;
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error('시설정보 유량 데이터를 가져오는데 실패했습니다:', error);
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// 시설들 유량 정보 조회
|
||||||
|
export const fetchFlow = async (searchYear: string | undefined, fcltCdList: string[]): Promise<ApiResponse | null> => {
|
||||||
|
try {
|
||||||
|
const res = await postFetch('fo', '/fclt/flow/' + searchYear, fcltCdList);
|
||||||
|
return res;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('시설정보 유량 데이터를 가져오는데 실패했습니다:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
/**====================================
|
/**====================================
|
||||||
* Store - expaort
|
* Store - expaort
|
||||||
====================================*/
|
====================================*/
|
||||||
export type ExcelType = {
|
export type ExcelType = {
|
||||||
시설코드: string;
|
시설코드: string;
|
||||||
권역:string|'',
|
권역: string | '',
|
||||||
단위유역:string|'',
|
단위유역: string | '',
|
||||||
중권역:string|'',
|
중권역: string | '',
|
||||||
환경청:string|'',
|
환경청: string | '',
|
||||||
시도: string;
|
시도: string;
|
||||||
시군구: string;
|
시군구: string;
|
||||||
시설이름: string;
|
시설이름: string;
|
||||||
주소: string;
|
주소: string;
|
||||||
"시설용량(m³/일)": number;
|
"시설용량(m³/일)": number;
|
||||||
"여유용량(m³/일)": number;
|
"여유용량(m³/일)": number;
|
||||||
"변동부하율(%)" : number;
|
"변동부하율(%)": number;
|
||||||
"분류식화율(%)" : number;
|
"분류식화율(%)": number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataFormSetting=(item : PlanSewageProps)=> {
|
const dataFormSetting = (item: PlanSewageProps) => {
|
||||||
DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||||
DataForm({ type: 'float0', column: 'spareCapacity', item: item as unknown as Record<string, unknown>});
|
DataForm({ type: 'float0', column: 'spareCapacity', item: item as unknown as Record<string, unknown> });
|
||||||
DataForm({ type: 'float2', column: 'variableLoadPercent', item: item as unknown as Record<string, unknown>});
|
DataForm({ type: 'float2', column: 'variableLoadPercent', item: item as unknown as Record<string, unknown> });
|
||||||
DataForm({ type: 'float1', column: 'classifiedSewerPercent', item: item as unknown as Record<string, unknown>});
|
DataForm({ type: 'float1', column: 'classifiedSewerPercent', item: item as unknown as Record<string, unknown> });
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PlanSewageActions = {
|
export type PlanSewageActions = {
|
||||||
@@ -133,10 +174,10 @@ export type PlanSewageActions = {
|
|||||||
export type PlanSewageType = {
|
export type PlanSewageType = {
|
||||||
PlanSewageSearch: {
|
PlanSewageSearch: {
|
||||||
isInit: boolean;
|
isInit: boolean;
|
||||||
labelArray:string[];
|
labelArray: string[];
|
||||||
},
|
},
|
||||||
|
|
||||||
PlanSewage : {
|
PlanSewage: {
|
||||||
isInit: boolean;
|
isInit: boolean;
|
||||||
upHeadList1: TableUpperProps[];
|
upHeadList1: TableUpperProps[];
|
||||||
upHeadList2: TableUpperProps[];
|
upHeadList2: TableUpperProps[];
|
||||||
@@ -154,21 +195,21 @@ export const planSewageInitState: PlanSewageType = {
|
|||||||
labelArray: LabelArray,
|
labelArray: LabelArray,
|
||||||
},
|
},
|
||||||
|
|
||||||
PlanSewage : {
|
PlanSewage: {
|
||||||
isInit : false,
|
isInit: false,
|
||||||
upHeadList1 : upHeadList1,
|
upHeadList1: upHeadList1,
|
||||||
upHeadList2 : upHeadList2,
|
upHeadList2: upHeadList2,
|
||||||
upHeadList3 : upHeadList3,
|
upHeadList3: upHeadList3,
|
||||||
planSewageList : planSewageList,
|
planSewageList: planSewageList,
|
||||||
planSewageCount : 0,
|
planSewageCount: 0,
|
||||||
excelList : [],
|
excelList: [],
|
||||||
isLoading : true,
|
isLoading: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PlanSewageStore = PlanSewageType & PlanSewageActions;
|
export type PlanSewageStore = PlanSewageType & PlanSewageActions;
|
||||||
|
|
||||||
export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageType) => void)=>PlanSewageActions=(set: (fn: (state: PlanSewageType) => PlanSewageType) => void) => {
|
export const planSewageReducer: (set: (fn: (state: PlanSewageType) => PlanSewageType) => void) => PlanSewageActions = (set: (fn: (state: PlanSewageType) => PlanSewageType) => void) => {
|
||||||
return {
|
return {
|
||||||
searchPlanSewageList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
searchPlanSewageList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||||
set((state: PlanSewageType) => ({
|
set((state: PlanSewageType) => ({
|
||||||
@@ -179,28 +220,101 @@ export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageTy
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
const res = await fetchPlanSewageList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
|
const res = await fetchPlanSewageList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||||
const excelDownList: ExcelType[] = [];
|
const fcltylist = res.data; // 시설목록
|
||||||
const data = res.data
|
|
||||||
const processedData = await Promise.all(data.map(async (item:PlanSewageProps) => {
|
|
||||||
const res2 = await getFetch('fo', '/fclt/flow/' + item.bscFctCd + '/' + searchYear) as ApiResponse;
|
|
||||||
const calData = CalcRainEffect(res2.data, 'SUNNY');
|
|
||||||
|
|
||||||
|
const fcltCdList: string[] = []; // 시설코드목록
|
||||||
|
const planSewageList: PlanSewageProps[] = []; // 오수발생량시설목록
|
||||||
|
fcltylist.forEach(item => {
|
||||||
|
fcltCdList.push(item.bscFctCd);
|
||||||
|
planSewageList.push({
|
||||||
|
bscFctCd: item.bscFctCd,
|
||||||
|
sido: item.sido,
|
||||||
|
gugun: item.gugun,
|
||||||
|
bscFctNm: item.bscFctNm,
|
||||||
|
daddr: item.daddr,
|
||||||
|
fctCpc: parseFloat(item.fctCpc.toString().replace(/,/g, '')),
|
||||||
|
spareCapacity: 0,
|
||||||
|
variableLoadPercent: 0,
|
||||||
|
classifiedSewerPercent: 0,
|
||||||
|
rgnNm: item.rgnNm, //환경청
|
||||||
|
rvbsn: item.rvbsn, //단위유역
|
||||||
|
lgbsn: item.lgbsn, //권역
|
||||||
|
mdmbsn: item.mdmbsn, //중권역
|
||||||
|
sprtProcZoneAr: 0, // 분류식지역 면적(㎢)
|
||||||
|
procZoneSm: 0, // 처리구역 면적합계(㎢)
|
||||||
|
avgInflAmnt: 0,
|
||||||
|
avgInflAmntSunny: 0,
|
||||||
|
maxInflAmntSunny: 0,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const excelDownList: ExcelType[] = [];
|
||||||
|
// const data = res.data
|
||||||
|
|
||||||
|
const planZoneRes: any = await fetchPlanZoneList(searchYear, fcltCdList);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const detailRes: any = await fetchFlow(searchYear, fcltCdList);
|
||||||
|
for (const item of planSewageList) {
|
||||||
|
const detailList = detailRes?.data[item.bscFctCd];
|
||||||
|
|
||||||
|
let avgInflAmnt = 0;
|
||||||
let sumInflAmntSunny = 0;
|
let sumInflAmntSunny = 0;
|
||||||
let avgInflAmntSunny = 0;
|
let avgInflAmntSunny = 0;
|
||||||
let maxInflAmntSunny = 0;
|
let maxInflAmntSunny = 0;
|
||||||
calData.forEach((flowItem:FlowDataItem) => {
|
let cntSunny = 0;
|
||||||
sumInflAmntSunny += Number(flowItem.inflAmnt);
|
let rainEffectDay = 0;
|
||||||
|
detailList?.forEach(item2 => {
|
||||||
|
|
||||||
if(Number(flowItem.inflAmnt) > maxInflAmntSunny){
|
if (item2.infoRnDay == null || item2.infoRnDay == 'x') item2.infoRnDay = 0;
|
||||||
maxInflAmntSunny = Number(flowItem.inflAmnt);
|
if (item2.infoRnDay >= 3) { // 강우량이 3이상이면 그 후 2일이 강후영향일임.
|
||||||
|
rainEffectDay = 2;
|
||||||
|
} else {
|
||||||
|
rainEffectDay--;
|
||||||
}
|
}
|
||||||
});
|
if (rainEffectDay < 0) { //청천시
|
||||||
|
sumInflAmntSunny += Number(item2.inflAmnt);
|
||||||
|
cntSunny++;
|
||||||
|
|
||||||
avgInflAmntSunny = sumInflAmntSunny / calData.length;
|
if (Number(item2.inflAmnt) > maxInflAmntSunny) {
|
||||||
|
maxInflAmntSunny = Number(item2.inflAmnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avgInflAmnt += Number(item2.inflAmnt);
|
||||||
|
});
|
||||||
|
avgInflAmntSunny = sumInflAmntSunny / cntSunny;
|
||||||
|
item.avgInflAmnt = roundUp(avgInflAmnt, 0);
|
||||||
item.avgInflAmntSunny = roundUp(avgInflAmntSunny, 0);
|
item.avgInflAmntSunny = roundUp(avgInflAmntSunny, 0);
|
||||||
item.maxInflAmntSunny = roundUp(maxInflAmntSunny, 0);
|
item.maxInflAmntSunny = roundUp(maxInflAmntSunny, 0);
|
||||||
return item;
|
}
|
||||||
}));
|
|
||||||
|
// const processedData = await Promise.all(data.map(async (item: PlanSewageProps) => {
|
||||||
|
// const res2 = await getFetch('fo', '/fclt/flow/' + item.bscFctCd + '/' + searchYear) as ApiResponse;
|
||||||
|
// const calData = CalcRainEffect(res2.data, 'SUNNY');
|
||||||
|
|
||||||
|
// let sumInflAmntSunny = 0; // 청천시 유입량 합계
|
||||||
|
// let avgInflAmntSunny = 0; // 청천시 유입량 평균
|
||||||
|
// let maxInflAmntSunny = 0; // 청천시 유입량 최대값
|
||||||
|
// calData.forEach((flowItem: FlowDataItem) => {
|
||||||
|
// sumInflAmntSunny += Number(flowItem.inflAmnt);
|
||||||
|
|
||||||
|
// if (Number(flowItem.inflAmnt) > maxInflAmntSunny) {
|
||||||
|
// maxInflAmntSunny = Number(flowItem.inflAmnt);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// avgInflAmntSunny = sumInflAmntSunny / calData.length;
|
||||||
|
// item.avgInflAmntSunny = roundUp(avgInflAmntSunny, 0);
|
||||||
|
// item.maxInflAmntSunny = roundUp(maxInflAmntSunny, 0);
|
||||||
|
// return item;
|
||||||
|
// }));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 결과데이터 계산
|
* 결과데이터 계산
|
||||||
@@ -208,19 +322,19 @@ export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageTy
|
|||||||
* (2) 변동부하율 = 건기시 일최대 유량/일평균유량(기준 최근 3개년)
|
* (2) 변동부하율 = 건기시 일최대 유량/일평균유량(기준 최근 3개년)
|
||||||
* (3) 분류식화율 = 분류식지역 면적(㎢)/처리구역 면적합계(㎢) ×100
|
* (3) 분류식화율 = 분류식지역 면적(㎢)/처리구역 면적합계(㎢) ×100
|
||||||
*/
|
*/
|
||||||
const resultData = processedData.map((item:PlanSewageProps) => {
|
const resultData = planSewageList.map((item: PlanSewageProps) => {
|
||||||
item.spareCapacity = Number(item.fctCpc) - Number(item.avgInflAmntSunny);
|
item.spareCapacity = Number(item.fctCpc) - Number(item.avgInflAmntSunny);
|
||||||
item.variableLoadPercent = item.maxInflAmntSunny && item.maxInflAmntSunny!==0 ? Number(item.maxInflAmntSunny) / Number(item.avgInflAmntSunny) : 0;
|
item.variableLoadPercent = item.maxInflAmntSunny && item.maxInflAmntSunny !== 0 ? Number(item.maxInflAmntSunny) / Number(item.avgInflAmntSunny) : 0;
|
||||||
item.classifiedSewerPercent = item.sprtProcZoneAr && item.sprtProcZoneAr!==0 ? Number(item.sprtProcZoneAr) / Number(item.procZoneSm) * 100 : 0;
|
item.classifiedSewerPercent = item.sprtProcZoneAr && item.sprtProcZoneAr !== 0 ? Number(item.sprtProcZoneAr) / Number(item.procZoneSm) * 100 : 0; // 분류식화율
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
|
|
||||||
resultData.forEach((item:PlanSewageProps) => {
|
resultData.forEach((item: PlanSewageProps) => {
|
||||||
dataFormSetting(item)
|
dataFormSetting(item)
|
||||||
})
|
})
|
||||||
|
|
||||||
if(pageSize>5000){
|
if (pageSize > 5000) {
|
||||||
resultData.forEach((item:PlanSewageProps) => {
|
resultData.forEach((item: PlanSewageProps) => {
|
||||||
excelDownList.push({
|
excelDownList.push({
|
||||||
시설코드: item.bscFctCd,
|
시설코드: item.bscFctCd,
|
||||||
권역: item.lgbsn,
|
권역: item.lgbsn,
|
||||||
@@ -239,17 +353,17 @@ export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageTy
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
set((state:PlanSewageType) => ({
|
set((state: PlanSewageType) => ({
|
||||||
...state,
|
...state,
|
||||||
PlanSewage: pageSize<5000?{
|
PlanSewage: pageSize < 5000 ? {
|
||||||
...state.PlanSewage,
|
...state.PlanSewage,
|
||||||
planSewageList: resultData,
|
planSewageList: resultData,
|
||||||
planSewageCount: res.count,
|
planSewageCount: res.count,
|
||||||
isLoading : false,
|
isLoading: false,
|
||||||
}:{
|
} : {
|
||||||
...state.PlanSewage,
|
...state.PlanSewage,
|
||||||
excelList: excelDownList,
|
excelList: excelDownList,
|
||||||
isLoading : false,
|
isLoading: false,
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -5,58 +5,55 @@ import { OSU_PERCENT } from "../common";
|
|||||||
import type { TableUpperProps } from "../dashboard";
|
import type { TableUpperProps } from "../dashboard";
|
||||||
import { fetchFacilityListInit } from "../processFacility";
|
import { fetchFacilityListInit } from "../processFacility";
|
||||||
export type { TableUpperProps };
|
export type { TableUpperProps };
|
||||||
/**====================================
|
|
||||||
* Store - 타입
|
|
||||||
====================================*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (1) 메인페이지
|
* 운영실태 >오수발생량 추정
|
||||||
*/
|
*/
|
||||||
// 시설별 강수현황
|
// 시설별 강수현황
|
||||||
export type SewageOccurProps = {
|
export type SewageOccurProps = {
|
||||||
bscFctCd : string,
|
bscFctCd: string,
|
||||||
sidoNm : string,
|
sidoNm: string,
|
||||||
sggNm : string,
|
sggNm: string,
|
||||||
lclgvrnmntNm : string,
|
lclgvrnmntNm: string,
|
||||||
bscFctNm : string,
|
bscFctNm: string,
|
||||||
daddr : string,
|
daddr: string,
|
||||||
fctCpc : number,
|
fctCpc: number,
|
||||||
waterUsage : number,
|
waterUsage: number,
|
||||||
swageChangePercent : number,
|
swageChangePercent: number,
|
||||||
estimationSewage : number,
|
estimationSewage: number,
|
||||||
sewageInputYear : number,
|
sewageInputYear: number,
|
||||||
sewageInputChungchun : number,
|
sewageInputChungchun: number,
|
||||||
rgnNm : string,
|
rgnNm: string,
|
||||||
rvbsn : string,
|
rvbsn: string,
|
||||||
lgbsn : string,
|
lgbsn: string,
|
||||||
mdmbsn : string,
|
mdmbsn: string,
|
||||||
msrDt : 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 = {
|
export type SewageOccurDetailProps = {
|
||||||
cnt : number,
|
cnt: number,
|
||||||
sum : number,
|
sum: number,
|
||||||
yr:string,
|
yr: string,
|
||||||
usage:number, // 일평균 유입량
|
usage: number, // 일평균 유입량
|
||||||
cntWtrUsg : number, // 물사용량 일자수
|
cntWtrUsg: number, // 물사용량 일자수
|
||||||
sumWtrUsg : number, // 물사용량 합
|
sumWtrUsg: number, // 물사용량 합
|
||||||
avgWtrUsg:number, // 일평균 물사용량
|
avgWtrUsg: number, // 일평균 물사용량
|
||||||
monWtrUsg:number, // 월 물사용량
|
monWtrUsg: number, // 월 물사용량
|
||||||
}
|
}
|
||||||
export type WtrUsgYmProps = {
|
export type WtrUsgYmProps = {
|
||||||
bscFctCd : string, // 처리구역시설코드
|
bscFctCd: string, // 처리구역시설코드
|
||||||
levyYm : string, // 부과년월
|
levyYm: string, // 부과년월
|
||||||
wtrUsg : number, // 월별 물사용량(m³/월)
|
wtrUsg: number, // 월별 물사용량(m³/월)
|
||||||
}
|
}
|
||||||
// 검색단
|
// 검색단
|
||||||
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
const LabelArray: string[] = ['구분', '시도', '시군구', '용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
||||||
|
|
||||||
export interface ExcelType {
|
export interface ExcelType {
|
||||||
시설코드: string,
|
시설코드: string,
|
||||||
권역:string|'',
|
권역: string | '',
|
||||||
단위유역:string|'',
|
단위유역: string | '',
|
||||||
중권역:string|'',
|
중권역: string | '',
|
||||||
환경청:string|'',
|
환경청: string | '',
|
||||||
시도: string,
|
시도: string,
|
||||||
시군구: string,
|
시군구: string,
|
||||||
시설명: string,
|
시설명: string,
|
||||||
@@ -70,64 +67,64 @@ export interface ExcelType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 리스트 헤더
|
// 리스트 헤더
|
||||||
const upHeadList1:TableUpperProps[] = [
|
const upHeadList1: TableUpperProps[] = [
|
||||||
{ id: "A", title: "행정구역", row:0, colSpan:2 },
|
{ id: "A", title: "행정구역", row: 0, colSpan: 2 },
|
||||||
{ id: "sidoNm", title: "시도", row:1, widthPercent: 8 },
|
{ id: "sidoNm", title: "시도", row: 1, widthPercent: 8 },
|
||||||
{ id: "sggNm", title: "시군구", row:1, widthPercent: 8 },
|
{ id: "sggNm", title: "시군구", row: 1, widthPercent: 8 },
|
||||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "fctCpc", title: "시설용량(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "waterUsage", title: "물사용량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "waterUsage", title: "물사용량(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "swageChangePercent", title: "오수전환율\n(%)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "swageChangePercent", title: "오수전환율\n(%)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "estimationSewage", title: "오수발생량 추정\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "estimationSewage", title: "오수발생량 추정\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "sewageInputYear", title: "연간 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "sewageInputYear", title: "연간 하수유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
];
|
];
|
||||||
|
|
||||||
const upHeadList2:TableUpperProps[] = [
|
const upHeadList2: TableUpperProps[] = [
|
||||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
{ id: "A", title: "유역", row: 0, colSpan: 3 },
|
||||||
{ id: "rvbsn", title: "권역", row:1, widthPercent: 6 },
|
{ id: "rvbsn", title: "권역", row: 1, widthPercent: 6 },
|
||||||
{ id: "lgbsn", title: "단위유역", row:1, widthPercent: 6 },
|
{ id: "lgbsn", title: "단위유역", row: 1, widthPercent: 6 },
|
||||||
{ id: "mdmbsn", title: "중권역", row:1, widthPercent: 6 },
|
{ id: "mdmbsn", title: "중권역", row: 1, widthPercent: 6 },
|
||||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "fctCpc", title: "시설용량(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "waterUsage", title: "물사용량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "waterUsage", title: "물사용량(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "swageChangePercent", title: "오수전환율", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "swageChangePercent", title: "오수전환율", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "estimationSewage", title: "오수발생량 추정\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "estimationSewage", title: "오수발생량 추정\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "sewageInputYear", title: "연간 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "sewageInputYear", title: "연간 하수유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
];
|
];
|
||||||
|
|
||||||
const upHeadList3:TableUpperProps[] = [
|
const upHeadList3: TableUpperProps[] = [
|
||||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
{ id: "A", title: "유역", row: 0, colSpan: 3 },
|
||||||
{ id: "rvbsn", title: "권역", row:1, widthPercent: 5 },
|
{ id: "rvbsn", title: "권역", row: 1, widthPercent: 5 },
|
||||||
{ id: "lgbsn", title: "단위유역", row:1, widthPercent: 5 },
|
{ id: "lgbsn", title: "단위유역", row: 1, widthPercent: 5 },
|
||||||
{ id: "mdmbsn", title: "중권역", row:1, widthPercent: 5 },
|
{ id: "mdmbsn", title: "중권역", row: 1, widthPercent: 5 },
|
||||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "rgnNm", title: "환경청", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "B", title: "행정구역", row:0, colSpan:2 },
|
{ id: "B", title: "행정구역", row: 0, colSpan: 2 },
|
||||||
{ id: "sidoNm", title: "시도", row:1, widthPercent: 6 },
|
{ id: "sidoNm", title: "시도", row: 1, widthPercent: 6 },
|
||||||
{ id: "sggNm", title: "시군구", row:1, widthPercent: 6 },
|
{ id: "sggNm", title: "시군구", row: 1, widthPercent: 6 },
|
||||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
|
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 6 },
|
{ id: "fctCpc", title: "시설용량(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 6 },
|
||||||
{ id: "waterUsage", title: "물사용량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 6 },
|
{ id: "waterUsage", title: "물사용량(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 6 },
|
||||||
{ id: "swageChangePercent", title: "오수전환율", align:"right", row:0, rowSpan:2, widthPercent: 6 },
|
{ id: "swageChangePercent", title: "오수전환율", align: "right", row: 0, rowSpan: 2, widthPercent: 6 },
|
||||||
{ id: "estimationSewage", title: "오수발생량 추정\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 6 },
|
{ id: "estimationSewage", title: "오수발생량 추정\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 6 },
|
||||||
{ id: "sewageInputYear", title: "연간 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 6 },
|
{ id: "sewageInputYear", title: "연간 하수유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 6 },
|
||||||
{ id: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 6 },
|
{ id: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 6 },
|
||||||
];
|
];
|
||||||
|
|
||||||
const upHeadListSewageOccurDetail:TableUpperProps[] = [
|
const upHeadListSewageOccurDetail: TableUpperProps[] = [
|
||||||
{ id: "msrDt", title: "년월" },
|
{ id: "msrDt", title: "년월" },
|
||||||
{ id: "waterUsage", title: "물사용량(m³/일)", align:"right" },
|
{ id: "waterUsage", title: "물사용량(m³/일)", align: "right" },
|
||||||
{ id: "swageChangePercent", title: "오수전환율(%)", align:"right" },
|
{ id: "swageChangePercent", title: "오수전환율(%)", align: "right" },
|
||||||
{ id: "estimationSewage", title: "오수발생량 추정(m³/일)", row:0, rowSpan:2, align:"right" },
|
{ id: "estimationSewage", title: "오수발생량 추정(m³/일)", row: 0, rowSpan: 2, align: "right" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const sewageOccurList:SewageOccurProps[] = []
|
const sewageOccurList: SewageOccurProps[] = []
|
||||||
|
|
||||||
const tempSewageOccurList:modalTableType[] = []
|
const tempSewageOccurList: modalTableType[] = []
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* yyyymm 형태의 문자열을 받아 해당 월의 일수를 반환
|
* yyyymm 형태의 문자열을 받아 해당 월의 일수를 반환
|
||||||
@@ -135,20 +132,20 @@ const tempSewageOccurList:modalTableType[] = []
|
|||||||
* @returns {number} 해당 월의 일수 (예: 28, 29, 30, 31)
|
* @returns {number} 해당 월의 일수 (예: 28, 29, 30, 31)
|
||||||
*/
|
*/
|
||||||
function getDaysInMonth(yyyymm) {
|
function getDaysInMonth(yyyymm) {
|
||||||
if (typeof yyyymm !== 'string' || yyyymm.length !== 6) {
|
if (typeof yyyymm !== 'string' || yyyymm.length !== 6) {
|
||||||
throw new Error("입력은 'yyyymm' 형식의 문자열이어야 합니다. 예: '202502'");
|
throw new Error("입력은 'yyyymm' 형식의 문자열이어야 합니다. 예: '202502'");
|
||||||
}
|
}
|
||||||
|
|
||||||
const year = parseInt(yyyymm.slice(0, 4), 10); // "2025" -> 2025
|
const year = parseInt(yyyymm.slice(0, 4), 10); // "2025" -> 2025
|
||||||
const month = parseInt(yyyymm.slice(4, 6), 10); // "02" -> 2
|
const month = parseInt(yyyymm.slice(4, 6), 10); // "02" -> 2
|
||||||
|
|
||||||
if (isNaN(year) || isNaN(month) || month < 1 || month > 12) {
|
if (isNaN(year) || isNaN(month) || month < 1 || month > 12) {
|
||||||
throw new Error("유효한 년/월이 아닙니다.");
|
throw new Error("유효한 년/월이 아닙니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Date(year, month, 0) -> 전달의 마지막 날
|
// Date(year, month, 0) -> 전달의 마지막 날
|
||||||
// month에 '다음달'을 넣고, 일(day)에 0을 주면 해당 월의 마지막 날짜가 됨
|
// month에 '다음달'을 넣고, 일(day)에 0을 주면 해당 월의 마지막 날짜가 됨
|
||||||
return new Date(year, month, 0).getDate();
|
return new Date(year, month, 0).getDate();
|
||||||
}
|
}
|
||||||
/**====================================
|
/**====================================
|
||||||
* Store - API
|
* Store - API
|
||||||
@@ -174,9 +171,9 @@ function getDaysInMonth(yyyymm) {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// 시설들 유량 정보 조회
|
// 시설들 유량 정보 조회
|
||||||
export const fetchSweageOccurListFlow = async (searchYear: string|undefined, fcltCdList: string[]): Promise<SewageOccurProps | null> => {
|
export const fetchSweageOccurListFlow = async (searchYear: string | undefined, fcltCdList: string[]): Promise<SewageOccurProps | null> => {
|
||||||
try {
|
try {
|
||||||
const res = await postFetch('fo', '/fclt/flow/'+searchYear, fcltCdList);
|
const res = await postFetch('fo', '/fclt/flow/' + searchYear, fcltCdList);
|
||||||
return res;
|
return res;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('시설정보 오수발생량 상세 데이터를 가져오는데 실패했습니다:', error);
|
console.error('시설정보 오수발생량 상세 데이터를 가져오는데 실패했습니다:', error);
|
||||||
@@ -184,9 +181,9 @@ export const fetchSweageOccurListFlow = async (searchYear: string|undefined, fcl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 시설별 물사용량 정보 조회
|
// 시설별 물사용량 정보 조회
|
||||||
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 {
|
try {
|
||||||
const res = await postFetch('fo', '/fclt/flow/wtrUsgYm/'+searchYear, fcltCdList);
|
const res = await postFetch('fo', '/fclt/flow/wtrUsgYm/' + searchYear, fcltCdList);
|
||||||
return res;
|
return res;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('시설들 월별 물사용량 데이터를 가져오는데 실패했습니다:', error);
|
console.error('시설들 월별 물사용량 데이터를 가져오는데 실패했습니다:', error);
|
||||||
@@ -205,10 +202,10 @@ export type SewageOccurActions = {
|
|||||||
export type SewageOccurType = {
|
export type SewageOccurType = {
|
||||||
SewageOccurSearch: {
|
SewageOccurSearch: {
|
||||||
isInit: boolean;
|
isInit: boolean;
|
||||||
labelArray:string[];
|
labelArray: string[];
|
||||||
},
|
},
|
||||||
|
|
||||||
SewageOccur : {
|
SewageOccur: {
|
||||||
isInit: boolean;
|
isInit: boolean;
|
||||||
upHeadList1: TableUpperProps[];
|
upHeadList1: TableUpperProps[];
|
||||||
upHeadList2: TableUpperProps[];
|
upHeadList2: TableUpperProps[];
|
||||||
@@ -219,7 +216,7 @@ export type SewageOccurType = {
|
|||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
},
|
},
|
||||||
|
|
||||||
SewageOccurDetail : {
|
SewageOccurDetail: {
|
||||||
isInit: boolean;
|
isInit: boolean;
|
||||||
upHeadListSewageOccurDetail: TableUpperProps[];
|
upHeadListSewageOccurDetail: TableUpperProps[];
|
||||||
gridListSewageOccurDetail: modalTableType[];
|
gridListSewageOccurDetail: modalTableType[];
|
||||||
@@ -232,18 +229,18 @@ export const sewageOccurInitState: SewageOccurType = {
|
|||||||
labelArray: LabelArray,
|
labelArray: LabelArray,
|
||||||
},
|
},
|
||||||
|
|
||||||
SewageOccur : {
|
SewageOccur: {
|
||||||
isInit : false,
|
isInit: false,
|
||||||
upHeadList1 : upHeadList1,
|
upHeadList1: upHeadList1,
|
||||||
upHeadList2 : upHeadList2,
|
upHeadList2: upHeadList2,
|
||||||
upHeadList3 : upHeadList3,
|
upHeadList3: upHeadList3,
|
||||||
sewageOccurList : sewageOccurList,
|
sewageOccurList: sewageOccurList,
|
||||||
sewageOccurCount : 2,
|
sewageOccurCount: 2,
|
||||||
excelList : [],
|
excelList: [],
|
||||||
isLoading : true,
|
isLoading: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
SewageOccurDetail : {
|
SewageOccurDetail: {
|
||||||
isInit: false,
|
isInit: false,
|
||||||
upHeadListSewageOccurDetail: upHeadListSewageOccurDetail,
|
upHeadListSewageOccurDetail: upHeadListSewageOccurDetail,
|
||||||
gridListSewageOccurDetail: tempSewageOccurList,
|
gridListSewageOccurDetail: tempSewageOccurList,
|
||||||
@@ -277,60 +274,60 @@ export type FlowResponse = {
|
|||||||
count: number;
|
count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
export const sewageOccurReducer: (set: any) => SewageOccurActions = (set: any) => {
|
||||||
return {
|
return {
|
||||||
searchSewageOccurList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
searchSewageOccurList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||||
const facilityInitData = await fetchFacilityListInit(pageNo, pageSize, part, nameCd, fcltCpct, operationValue, fcltyNm);
|
const facilityInitData = await fetchFacilityListInit(pageNo, pageSize, part, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||||
if(pageSize < 5000){
|
if (pageSize < 5000) {
|
||||||
set((state: SewageOccurType) => ({
|
set((state: SewageOccurType) => ({
|
||||||
...state,
|
...state,
|
||||||
SewageOccur: {
|
SewageOccur: {
|
||||||
...state.SewageOccur,
|
...state.SewageOccur,
|
||||||
sewageOccurList : [],
|
sewageOccurList: [],
|
||||||
sewageOccurCount : facilityInitData.count,
|
sewageOccurCount: facilityInitData.count,
|
||||||
excelList : [],
|
excelList: [],
|
||||||
isLoading: true
|
isLoading: true
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
}else{
|
} else {
|
||||||
set((state: SewageOccurType) => ({
|
set((state: SewageOccurType) => ({
|
||||||
...state,
|
...state,
|
||||||
SewageOccur: {
|
SewageOccur: {
|
||||||
...state.SewageOccur,
|
...state.SewageOccur,
|
||||||
excelList : [],
|
excelList: [],
|
||||||
isLoading: true
|
isLoading: true
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
const fcltylist = facilityInitData.data; // 시설목록
|
const fcltylist = facilityInitData.data; // 시설목록
|
||||||
const fcltCdList : string[] = []; // 시설코드목록
|
const fcltCdList: string[] = []; // 시설코드목록
|
||||||
const sewageOccurPropsList : SewageOccurProps[] = []; // 오수발생량시설목록
|
const sewageOccurPropsList: SewageOccurProps[] = []; // 오수발생량시설목록
|
||||||
fcltylist.forEach(item => {
|
fcltylist.forEach(item => {
|
||||||
fcltCdList.push(item.bscFctCd);
|
fcltCdList.push(item.bscFctCd);
|
||||||
sewageOccurPropsList.push({
|
sewageOccurPropsList.push({
|
||||||
bscFctCd : item.bscFctCd,
|
bscFctCd: item.bscFctCd,
|
||||||
sidoNm : item.sido,
|
sidoNm: item.sido,
|
||||||
sggNm : item.gugun,
|
sggNm: item.gugun,
|
||||||
lclgvrnmntNm : '',
|
lclgvrnmntNm: '',
|
||||||
bscFctNm : item.bscFctNm,
|
bscFctNm: item.bscFctNm,
|
||||||
daddr : item.daddr,
|
daddr: item.daddr,
|
||||||
fctCpc : parseFloat(item.fctCpc.toString().replace(/,/g, '')),
|
fctCpc: parseFloat(item.fctCpc.toString().replace(/,/g, '')),
|
||||||
waterUsage : 0,
|
waterUsage: 0,
|
||||||
swageChangePercent : 0,
|
swageChangePercent: 0,
|
||||||
estimationSewage : 0,
|
estimationSewage: 0,
|
||||||
sewageInputYear : 0,
|
sewageInputYear: 0,
|
||||||
sewageInputChungchun : 0,
|
sewageInputChungchun: 0,
|
||||||
rgnNm : item.rgnNm,
|
rgnNm: item.rgnNm,
|
||||||
rvbsn : item.rvbsn,
|
rvbsn: item.rvbsn,
|
||||||
lgbsn : item.lgbsn,
|
lgbsn: item.lgbsn,
|
||||||
mdmbsn : item.mdmbsn,
|
mdmbsn: item.mdmbsn,
|
||||||
msrDt : '',
|
msrDt: '',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const soccurDetailRes : any = await fetchSweageOccurListFlow(searchYear, fcltCdList);
|
const soccurDetailRes: any = await fetchSweageOccurListFlow(searchYear, fcltCdList);
|
||||||
const wtrUsgYmRes : any = await fetchWtrUsgYmList(searchYear, fcltCdList);
|
const wtrUsgYmRes: any = await fetchWtrUsgYmList(searchYear, fcltCdList);
|
||||||
// const wtrUsgMap : Record<string, number> = {};
|
// const wtrUsgMap : Record<string, number> = {};
|
||||||
// wtrUsgRes.data.forEach(fclt => {
|
// wtrUsgRes.data.forEach(fclt => {
|
||||||
// wtrUsgMap[fclt.bscFctCd] = fclt.wtrUsg;
|
// wtrUsgMap[fclt.bscFctCd] = fclt.wtrUsg;
|
||||||
@@ -348,12 +345,12 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
|||||||
detailList?.forEach(item2 => {
|
detailList?.forEach(item2 => {
|
||||||
|
|
||||||
if (item2.infoRnDay == null || item2.infoRnDay == 'x') item2.infoRnDay = 0;
|
if (item2.infoRnDay == null || item2.infoRnDay == 'x') item2.infoRnDay = 0;
|
||||||
if(item2.infoRnDay >= 3) {
|
if (item2.infoRnDay >= 3) {
|
||||||
rainEffectDay = 2;
|
rainEffectDay = 2;
|
||||||
}else{
|
} else {
|
||||||
rainEffectDay--;
|
rainEffectDay--;
|
||||||
}
|
}
|
||||||
if(rainEffectDay<0){ //청천시
|
if (rainEffectDay < 0) { //청천시
|
||||||
chungcunSumFlow += item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0;//Number(item2.inflAmnt);
|
chungcunSumFlow += item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0;//Number(item2.inflAmnt);
|
||||||
sumChungcunDay += 1;
|
sumChungcunDay += 1;
|
||||||
}
|
}
|
||||||
@@ -372,13 +369,13 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
|||||||
const count = detailList ? detailList.length : 0;
|
const count = detailList ? detailList.length : 0;
|
||||||
const avg = count == 0 ? 0 : totWaterUsage / count; // 일평균 유입량
|
const avg = count == 0 ? 0 : totWaterUsage / count; // 일평균 유입량
|
||||||
item.waterUsage = parseFloat((avg * 0.65).toFixed(2)); // 물사용량 = 일평균 유입량 * 65%
|
item.waterUsage = parseFloat((avg * 0.65).toFixed(2)); // 물사용량 = 일평균 유입량 * 65%
|
||||||
if(wtrUsgYearTotal > 0 && wtrUsgYearDays > 0) {
|
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.sewageInputYear = parseFloat(avg.toFixed(2)); // 연간 하수유입량(m³/일)
|
||||||
item.sewageInputChungchun = parseFloat((chungcunSumFlow===0?0:(chungcunSumFlow / sumChungcunDay)).toFixed(2)); // 청천시 하수유입량
|
item.sewageInputChungchun = parseFloat((chungcunSumFlow === 0 ? 0 : (chungcunSumFlow / sumChungcunDay)).toFixed(2)); // 청천시 하수유입량
|
||||||
item.estimationSewage = parseFloat((item.waterUsage * OSU_PERCENT).toFixed(2)); // 오수발생량 추정(m³/일)
|
item.estimationSewage = parseFloat((item.waterUsage * OSU_PERCENT).toFixed(2)); // 오수발생량 추정(m³/일)
|
||||||
if ( item.bscFctCd === '11200PB001R' ) {
|
if (item.bscFctCd === '11200PB001R') {
|
||||||
console.log('chungcunSumFlow:', chungcunSumFlow);
|
console.log('chungcunSumFlow:', chungcunSumFlow);
|
||||||
console.log('sumChungcunDay:', sumChungcunDay);
|
console.log('sumChungcunDay:', sumChungcunDay);
|
||||||
}
|
}
|
||||||
@@ -388,7 +385,7 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pageSize >= 5000){
|
if (pageSize >= 5000) {
|
||||||
const excelDownList: ExcelType[] = [];
|
const excelDownList: ExcelType[] = [];
|
||||||
sewageOccurPropsList.forEach((item: SewageOccurProps) => {
|
sewageOccurPropsList.forEach((item: SewageOccurProps) => {
|
||||||
excelDownList.push({
|
excelDownList.push({
|
||||||
@@ -414,16 +411,16 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
|||||||
SewageOccur: {
|
SewageOccur: {
|
||||||
...state.SewageOccur,
|
...state.SewageOccur,
|
||||||
excelList: excelDownList,
|
excelList: excelDownList,
|
||||||
isLoading : false,
|
isLoading: false,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
}else{
|
} else {
|
||||||
set((state: SewageOccurType) => ({
|
set((state: SewageOccurType) => ({
|
||||||
...state,
|
...state,
|
||||||
SewageOccur: {
|
SewageOccur: {
|
||||||
...state.SewageOccur,
|
...state.SewageOccur,
|
||||||
sewageOccurList : sewageOccurPropsList,
|
sewageOccurList: sewageOccurPropsList,
|
||||||
sewageOccurCount : facilityInitData.count,
|
sewageOccurCount: facilityInitData.count,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
excelList: [],
|
excelList: [],
|
||||||
},
|
},
|
||||||
@@ -516,12 +513,12 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
|||||||
|
|
||||||
searchSewageOccurDetailList: async (bscFctCd: string, searchYear: string, startYm?: string, endYm?: string) => {
|
searchSewageOccurDetailList: async (bscFctCd: string, searchYear: string, startYm?: string, endYm?: string) => {
|
||||||
const fcltCdList = [bscFctCd];
|
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 res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear);
|
||||||
const monthData: SewageOccurDetailProps[] = [];
|
const monthData: SewageOccurDetailProps[] = [];
|
||||||
let tot = 0, cnt= 0;
|
let tot = 0, cnt = 0;
|
||||||
|
|
||||||
if(startYm) {
|
if (startYm) {
|
||||||
res.data = res.data.filter((item: FlowDataItem) => {
|
res.data = res.data.filter((item: FlowDataItem) => {
|
||||||
const month = item.msrDt?.substring(0, 6);
|
const month = item.msrDt?.substring(0, 6);
|
||||||
return month >= startYm;
|
return month >= startYm;
|
||||||
@@ -533,7 +530,7 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(endYm) {
|
if (endYm) {
|
||||||
res.data = res.data.filter((item: FlowDataItem) => {
|
res.data = res.data.filter((item: FlowDataItem) => {
|
||||||
const month = item.msrDt?.substring(0, 6);
|
const month = item.msrDt?.substring(0, 6);
|
||||||
return month <= endYm;
|
return month <= endYm;
|
||||||
@@ -555,8 +552,10 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
|||||||
monthData[monthIdx].sum += Number(item.inflAmnt);
|
monthData[monthIdx].sum += Number(item.inflAmnt);
|
||||||
monthData[monthIdx].cnt++;
|
monthData[monthIdx].cnt++;
|
||||||
} else {
|
} else {
|
||||||
monthData[monthIdx] = {cnt:1, sum:Number(item.inflAmnt), yr:item.msrDt.substring(0,4)
|
monthData[monthIdx] = {
|
||||||
, usage:0, cntWtrUsg:0, sumWtrUsg:0, avgWtrUsg:0, monWtrUsg:0};
|
cnt: 1, sum: Number(item.inflAmnt), yr: item.msrDt.substring(0, 4)
|
||||||
|
, usage: 0, cntWtrUsg: 0, sumWtrUsg: 0, avgWtrUsg: 0, monWtrUsg: 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tot += Number(item.inflAmnt)
|
tot += Number(item.inflAmnt)
|
||||||
@@ -581,19 +580,19 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const tableData:modalTableType[] = []
|
const tableData: modalTableType[] = []
|
||||||
|
|
||||||
let maxWaterUsage = 0;
|
let maxWaterUsage = 0;
|
||||||
let minWaterUsage = 9999999999;
|
let minWaterUsage = 9999999999;
|
||||||
let avgWaterUsage = 0;
|
let avgWaterUsage = 0;
|
||||||
monthData.forEach((item, index) => {
|
monthData.forEach((item, index) => {
|
||||||
item.avgWtrUsg = item.sum/item.cnt *0.65; // 일평균 물사용량 = 일평균유입수 * 0.65
|
item.avgWtrUsg = item.sum / item.cnt * 0.65; // 일평균 물사용량 = 일평균유입수 * 0.65
|
||||||
if (item.sumWtrUsg > 0 && item.cntWtrUsg > 0) item.avgWtrUsg = item.sumWtrUsg / item.cntWtrUsg;
|
if (item.sumWtrUsg > 0 && item.cntWtrUsg > 0) item.avgWtrUsg = item.sumWtrUsg / item.cntWtrUsg;
|
||||||
tableData.push({
|
tableData.push({
|
||||||
msrDt: item.yr+'-'+(index+1>=10?String(index+1):'0'+(index+1)),
|
msrDt: item.yr + '-' + (index + 1 >= 10 ? String(index + 1) : '0' + (index + 1)),
|
||||||
waterUsage: Math.round(item.avgWtrUsg*1) /1,
|
waterUsage: Math.round(item.avgWtrUsg * 1) / 1,
|
||||||
swageChangePercent: OSU_PERCENT*100,//(Math.round((item.usage/item.usage*OSU_PERCENT) * 100) / 100) * 100,
|
swageChangePercent: OSU_PERCENT * 100,//(Math.round((item.usage/item.usage*OSU_PERCENT) * 100) / 100) * 100,
|
||||||
estimationSewage: Math.round(item.avgWtrUsg*OSU_PERCENT * 1) / 1
|
estimationSewage: Math.round(item.avgWtrUsg * OSU_PERCENT * 1) / 1
|
||||||
})
|
})
|
||||||
if (item.avgWtrUsg > maxWaterUsage) {
|
if (item.avgWtrUsg > maxWaterUsage) {
|
||||||
maxWaterUsage = item.avgWtrUsg;
|
maxWaterUsage = item.avgWtrUsg;
|
||||||
@@ -604,29 +603,29 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
avgWaterUsage = tot/cnt*0.65
|
avgWaterUsage = tot / cnt * 0.65
|
||||||
if (totWtrUsg > 0 && cntWtrUsg > 0) avgWaterUsage = totWtrUsg / cntWtrUsg;
|
if (totWtrUsg > 0 && cntWtrUsg > 0) avgWaterUsage = totWtrUsg / cntWtrUsg;
|
||||||
|
|
||||||
const newData= [
|
const newData = [
|
||||||
{
|
{
|
||||||
msrDt: '평균',
|
msrDt: '평균',
|
||||||
waterUsage: roundNumber(Math.round(avgWaterUsage*1) /1,0),
|
waterUsage: roundNumber(Math.round(avgWaterUsage * 1) / 1, 0),
|
||||||
swageChangePercent: OSU_PERCENT*100,
|
swageChangePercent: OSU_PERCENT * 100,
|
||||||
estimationSewage: roundNumber(Math.round(avgWaterUsage*OSU_PERCENT*1) /1,0),
|
estimationSewage: roundNumber(Math.round(avgWaterUsage * OSU_PERCENT * 1) / 1, 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msrDt: '최대',
|
msrDt: '최대',
|
||||||
waterUsage: roundNumber(Math.round(maxWaterUsage*100) /100,0),
|
waterUsage: roundNumber(Math.round(maxWaterUsage * 100) / 100, 0),
|
||||||
swageChangePercent: OSU_PERCENT*100,
|
swageChangePercent: OSU_PERCENT * 100,
|
||||||
estimationSewage: roundNumber(Math.round(maxWaterUsage*OSU_PERCENT*1) /1, 0),
|
estimationSewage: roundNumber(Math.round(maxWaterUsage * OSU_PERCENT * 1) / 1, 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msrDt: '최소',
|
msrDt: '최소',
|
||||||
waterUsage: roundNumber(Math.round(minWaterUsage*100) /100,0),
|
waterUsage: roundNumber(Math.round(minWaterUsage * 100) / 100, 0),
|
||||||
swageChangePercent: OSU_PERCENT*100,
|
swageChangePercent: OSU_PERCENT * 100,
|
||||||
estimationSewage: roundNumber(Math.round(minWaterUsage*OSU_PERCENT*1) /1,0),
|
estimationSewage: roundNumber(Math.round(minWaterUsage * OSU_PERCENT * 1) / 1, 0),
|
||||||
},
|
},
|
||||||
...tableData
|
...tableData
|
||||||
]
|
]
|
||||||
|
|
||||||
set((state: SewageOccurType) => ({
|
set((state: SewageOccurType) => ({
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
export { LoginApi } from "./api/login-service";
|
export { LoginApi } from "./api/login-service";
|
||||||
//export { AuthWrapper } from "./lib/auth-wrapper";
|
export { AuthWrapper } from "./lib/auth-wrapper";
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter, usePathname } from "next/navigation";
|
||||||
//import { usePathname } from "next/navigation";
|
|
||||||
import { client } from "@/src/shared/api";
|
import { client } from "@/src/shared/api";
|
||||||
import type { IUserInfo } from "@/src/shared/store";
|
import type { IUserInfo } from "@/src/shared/store";
|
||||||
import { useUserStore, getCookie } from "@/src/shared/lib";
|
import { useUserStore, getCookie } from "@/src/shared/lib";
|
||||||
@@ -13,7 +12,7 @@ const LOGIN_PAGE_URL = process.env.NEXT_PUBLIC_CM_LOGIN_PAGE_URL || "http://loca
|
|||||||
|
|
||||||
const AuthWrapper = ({ children }: { children: React.ReactNode }) => {
|
const AuthWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
//const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const { userInfo, setUserInfo } = useUserStore((state) => state);
|
const { userInfo, setUserInfo } = useUserStore((state) => state);
|
||||||
|
|
||||||
async function authCheck() {
|
async function authCheck() {
|
||||||
@@ -42,7 +41,7 @@ const AuthWrapper = ({ children }: { children: React.ReactNode }) => {
|
|||||||
console.error("Token refresh failed:", refreshError);
|
console.error("Token refresh failed:", refreshError);
|
||||||
setUserInfo(null);
|
setUserInfo(null);
|
||||||
|
|
||||||
const hostname = location.hostname;
|
const hostname = window.location.hostname;
|
||||||
|
|
||||||
// 개발 환경에서는 localhost 도메인 사용
|
// 개발 환경에서는 localhost 도메인 사용
|
||||||
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr")
|
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr")
|
||||||
@@ -50,11 +49,11 @@ const AuthWrapper = ({ children }: { children: React.ReactNode }) => {
|
|||||||
|
|
||||||
// 운영 환경에서는 서브도메인을 포함한 최상위 도메인 사용
|
// 운영 환경에서는 서브도메인을 포함한 최상위 도메인 사용
|
||||||
// router.push는 같은 Next.js 앱 내에서만 작동하므로 다른 앱으로 이동할 때는 window.location.href 사용
|
// router.push는 같은 Next.js 앱 내에서만 작동하므로 다른 앱으로 이동할 때는 window.location.href 사용
|
||||||
if (hostname.includes("hasuon.or.kr")) location.href = LOGIN_PAGE_URL; // 세션 만료 시 CM 로그인 페이지로 리다이렉트
|
if (hostname.includes("hasuon.or.kr")) window.location.href = LOGIN_PAGE_URL; // 세션 만료 시 CM 로그인 페이지로 리다이렉트
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}, []);
|
}, [pathname]);
|
||||||
|
|
||||||
return <>{children}</>;
|
return <>{children}</>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
|||||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||||
NEXT_PUBLIC_PORT = 3002
|
NEXT_PUBLIC_PORT = 3002
|
||||||
NEXT_PUBLIC_PROXY_HOST = http://localhost:3002
|
NEXT_PUBLIC_PROXY_HOST = http://localhost:3002
|
||||||
|
NEXT_PUBLIC_SUB_DOMAIN = http://localhost:13000
|
||||||
NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver
|
NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver
|
||||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
|
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
|
||||||
#NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&layer=korean_map&style=korean&tilematrixset=EPSG:5179&TileMatrix={z}&TileCol={x}&TileRow={y}
|
#NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&layer=korean_map&style=korean&tilematrixset=EPSG:5179&TileMatrix={z}&TileCol={x}&TileRow={y}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ NEXT_PUBLIC_AUTH_USER_ID = token-id
|
|||||||
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||||
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11302
|
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11302
|
||||||
|
NEXT_PUBLIC_SUB_DOMAIN = http://con.mind-one.co.kr:11300
|
||||||
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||||
NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver
|
NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver
|
||||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
|
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ NEXT_PUBLIC_AUTH_USER_ID = token-id
|
|||||||
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||||
#NEXT_PUBLIC_PROXY_HOST = https://devlion.hasuon.or.kr
|
#NEXT_PUBLIC_PROXY_HOST = https://devlion.hasuon.or.kr
|
||||||
|
#NEXT_PUBLIC_SUB_DOMAIN = http://front-sn-feature.iipbs-web.svc.cluster.local:13000
|
||||||
#NEXT_PUBLIC_CM_LOGIN_PAGE_URL = https://devqueen.hasuon.or.kr/auth/login
|
#NEXT_PUBLIC_CM_LOGIN_PAGE_URL = https://devqueen.hasuon.or.kr/auth/login
|
||||||
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
|
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_GEOSERVER_URL = http://172.29.143.87:8080/geoserver
|
||||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl
|
NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl
|
||||||
|
|||||||
@@ -87,6 +87,13 @@ export const codeMapper = ({ layerName, data }: CodeMapperProps): any => {
|
|||||||
if (processedData.manage_no) {
|
if (processedData.manage_no) {
|
||||||
processedData.mqlt_cd = processedData.manage_no;
|
processedData.mqlt_cd = processedData.manage_no;
|
||||||
}
|
}
|
||||||
|
if (processedData.mesure_spot_se) {
|
||||||
|
const mesureSpotSe = [{ id: '0', text: '합류식' }, { id: '1', text: '분류식' }];
|
||||||
|
const mesureSpotSeItem = mesureSpotSe.find(
|
||||||
|
code => code.id === processedData.mesure_spot_se.trim()
|
||||||
|
);
|
||||||
|
if (mesureSpotSeItem) processedData.mesure_spot_se = mesureSpotSeItem.text;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -686,7 +686,7 @@ export const untrtSwgRainCol1 = [
|
|||||||
|
|
||||||
// 중점우수토실 측정지점 시설현황
|
// 중점우수토실 측정지점 시설현황
|
||||||
export const untrtSwgRainCol2 = [
|
export const untrtSwgRainCol2 = [
|
||||||
{ id: 'flwmtr_mesure_tp_etc', title: '구분' },
|
{ id: 'mesure_spot_se', title: '구분' }, // 유량계측정방식 기타
|
||||||
{ id: 'discharge_pipe_spec', title: '방류관로 규격(m)' },
|
{ id: 'discharge_pipe_spec', title: '방류관로 규격(m)' },
|
||||||
{ id: 'swr_ppl_eqp_ar', title: '배수구역 면적(m²)' },
|
{ id: 'swr_ppl_eqp_ar', title: '배수구역 면적(m²)' },
|
||||||
{ id: 'swr_trt_popl', title: '하수처리 인구(인)' },
|
{ id: 'swr_trt_popl', title: '하수처리 인구(인)' },
|
||||||
@@ -722,7 +722,7 @@ export const untrtSwgRainCol4 = [
|
|||||||
export const untrtSwgRainCol5 = [
|
export const untrtSwgRainCol5 = [
|
||||||
{ id: 'odr', title: '회차' },
|
{ id: 'odr', title: '회차' },
|
||||||
{ id: 'mesureDt', title: '측정일자' },
|
{ id: 'mesureDt', title: '측정일자' },
|
||||||
{ id: 'mesureQy', title: '수량(m)' },
|
{ id: 'mesureQy', title: '수량(m³)' },
|
||||||
{ id: 'mesureBod', title: 'BOD(mg/L)' },
|
{ id: 'mesureBod', title: 'BOD(mg/L)' },
|
||||||
{ id: 'mesureToc', title: 'TOC(mg/L)' },
|
{ id: 'mesureToc', title: 'TOC(mg/L)' },
|
||||||
{ id: 'mesureLoad', title: '오염부하량(kg)' }
|
{ id: 'mesureLoad', title: '오염부하량(kg)' }
|
||||||
|
|||||||
@@ -100,15 +100,20 @@ const Ssc = ({ featureData, isMainSsc, chmbrXcnts, chmbrYdnts, onSaveClick }: {
|
|||||||
const processedDataArray: any[] = result.content.map((data: any) => {
|
const processedDataArray: any[] = result.content.map((data: any) => {
|
||||||
// 🎯 formatDisplayData로 기본 포맷팅 적용
|
// 🎯 formatDisplayData로 기본 포맷팅 적용
|
||||||
const formattedItem = formatDisplayData(data);
|
const formattedItem = formatDisplayData(data);
|
||||||
|
const flwmtrInstTp = data.flwmtrInstTp === 'R' ? '이동식' : data.flwmtrInstTp === 'S' ? '고정식' : '-';
|
||||||
|
const flwmtrMesureTp = data.flwmtrMesureTp === 'R' ? '레이더' : data.flwmtrMesureTp === 'P' ? '플륨'
|
||||||
|
: data.flwmtrMesureTp === 'U' ? '초음파' : data.flwmtrMesureTp === 'E' ? '기타' : '-';
|
||||||
|
const flwmtrCombined = `${flwmtrInstTp}, ${flwmtrMesureTp}`;
|
||||||
// 🎯 추가 데이터 조합
|
// 🎯 추가 데이터 조합
|
||||||
return {
|
return {
|
||||||
...formattedItem,
|
...formattedItem,
|
||||||
flwmtrCombined: `${data.flwmtrMesureTpEtc || '-'} / ${data.flwmtrKnd || '-'}`,
|
rainInfo: `${data.rainInfo === '0' ? '강우량계' : data.observatory || '-'}`, // 강우정보 0: 강우량계,1: 관측기관 이면 OBSERVATORY 이값사용
|
||||||
mesureBeginDt: data.mesureBeginDt ? formatNoYearNoSec(data.mesureBeginDt) : '-',
|
mesureIntrvl: `${data.mesureIntrvlGbn === '1' ? '1분' : (data.mesureIntrvlGbn === '0' ? data.mesureIntrvl + '분' : '-')}`, // 측정간격
|
||||||
mesureEndDt: data.mesureEndDt ? formatNoYearNoSec(data.mesureEndDt) : '-',
|
flwmtrCombined: `${flwmtrCombined} / ${data.flwmtrKnd || '-'}`, // 유량계종류 및 모델명
|
||||||
qltwtrBeginDt: data.qltwtrBeginDt ? formatNoYearNoSec(data.qltwtrBeginDt) : '-',
|
mesureBeginDt: data.mesureBeginDt ? formatNoYearNoSec(data.mesureBeginDt) : '-', // 수량 측정시작일
|
||||||
qltwtrEndDt: data.qltwtrEndDt ? formatNoYearNoSec(data.qltwtrEndDt) : '-',
|
mesureEndDt: data.mesureEndDt ? formatNoYearNoSec(data.mesureEndDt) : '-', // 수량 측정종료일
|
||||||
|
qltwtrBeginDt: data.qltwtrBeginDt ? formatNoYearNoSec(data.qltwtrBeginDt) : '-', // 수질 측정시작일(채수시작일)
|
||||||
|
qltwtrEndDt: data.qltwtrEndDt ? formatNoYearNoSec(data.qltwtrEndDt) : '-', // 수질 측정종료일(채수종료일)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
setRainMeasureData(processedDataArray);
|
setRainMeasureData(processedDataArray);
|
||||||
|
|||||||
@@ -235,6 +235,17 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
|||||||
);
|
);
|
||||||
if (materialCodeItem) data.mqlt_cd = `${materialCodeItem.text}`;
|
if (materialCodeItem) data.mqlt_cd = `${materialCodeItem.text}`;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// 중점우수토실인 경우 구분 값
|
||||||
|
if (selectedLayerName === '중점우수토실' && data) {
|
||||||
|
if (data.mesure_spot_se) {
|
||||||
|
const mesureSpotSe = [{id:'0', text: '합류식'}, {id:'1', text: '분류식'}]
|
||||||
|
const mesureSpotSeItem = mesureSpotSe.find(
|
||||||
|
code => code.id === data.mesure_spot_se.trim()
|
||||||
|
);
|
||||||
|
if (mesureSpotSeItem) data.mesure_spot_se = mesureSpotSeItem.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🎯 기본 데이터 포맷팅
|
// 🎯 기본 데이터 포맷팅
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ export async function searchUpperPpls(gisMap: any, fcltMngNo: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// JSON 파싱 시도
|
// JSON 파싱 시도
|
||||||
data = JSON.parse(text);
|
const response = JSON.parse(text);
|
||||||
|
data = response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("JSON parsing error:", error);
|
console.error("JSON parsing error:", error);
|
||||||
alert(`해당 맨홀의 상류관로를 찾을 수 없습니다.`);
|
alert(`해당 맨홀의 상류관로를 찾을 수 없습니다.`);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const BasicTab: React.FC = () => {
|
|||||||
const { basicType, setBasicType } = useSearchModalStore();
|
const { basicType, setBasicType } = useSearchModalStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative border rounded-lg p-5 w-full h-[10vh]">
|
<div className="relative border rounded-lg pt-5 px-5 w-full min-h-[10vh]">
|
||||||
{/* 구분 */}
|
{/* 구분 */}
|
||||||
<div className="mb-3 flex items-center justify-between gap-4">
|
<div className="mb-3 flex items-center justify-between gap-4">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const OperationTab: React.FC = () => {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative flex flex-col border rounded-lg p-5 w-full h-[10vh]">
|
<div className="relative flex flex-col border rounded-lg pt-5 px-5 w-full min-h-[10vh]">
|
||||||
<div className="flex items-center mb-3">
|
<div className="flex items-center mb-3">
|
||||||
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">업무구분</Label>
|
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">업무구분</Label>
|
||||||
<SelectBox
|
<SelectBox
|
||||||
|
|||||||
@@ -92,10 +92,10 @@ const ReportFilesModal: React.FC<ModalOpenProp> = ({ clsfSystmSn }: ModalOpenPro
|
|||||||
onOpenChange={setIsModalOpen}
|
onOpenChange={setIsModalOpen}
|
||||||
headerTitle=""
|
headerTitle=""
|
||||||
bodyClass={`
|
bodyClass={`
|
||||||
min-h-[50vh] h-[570px]
|
min-h-[50vh] max-h-[90dvh]
|
||||||
min-w-[35vw] w-[400px]
|
max-w-[750px]
|
||||||
max-w-none max-h-none
|
h-auto w-auto
|
||||||
overflow-visible
|
overflow-auto
|
||||||
z-[5000]
|
z-[5000]
|
||||||
flex items-start
|
flex items-start
|
||||||
`}
|
`}
|
||||||
|
|||||||
@@ -76,11 +76,11 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
|
|||||||
setIsOpen: setIsReportFilesModalOpen,
|
setIsOpen: setIsReportFilesModalOpen,
|
||||||
dcTree: reportOriginData,
|
dcTree: reportOriginData,
|
||||||
fetchDcTree
|
fetchDcTree
|
||||||
} = useReportTabStore(); // 모달 상태 관리 스토어
|
} = useReportTabStore(); // 모달 상태 관리 스토어
|
||||||
const { REPORT_TYPES, flattenFolders, addFileName } = useReportTab();
|
const { REPORT_TYPES, flattenFolders, addFileName } = useReportTab();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchDcTree("기본계획"); // 하수정비기본계획 report
|
fetchDcTree("기본계획"); // 하수정비기본계획 report
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -206,7 +206,7 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={`relative flex flex-col border rounded-lg p-5 w-full ${isSearch ? "h-[10vh]" : "h-[6vh]"}`}>
|
<div className={`relative flex flex-col border rounded-lg pt-5 px-5 w-full ${isSearch ? "min-h-[10vh]" : "min-h-[6vh]"}`}>
|
||||||
{isSearch && (
|
{isSearch && (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center mb-3">
|
<div className="flex items-center mb-3">
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ const SearchModal: React.FC = () => {
|
|||||||
{/* 📋 결과 리스트 */}
|
{/* 📋 결과 리스트 */}
|
||||||
{/* 기본정보 탭 */}
|
{/* 기본정보 탭 */}
|
||||||
{activeTab === 'basic' && (
|
{activeTab === 'basic' && (
|
||||||
<div className="h-[79vh] w-full overflow-hidden rounded-lg border">
|
<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">
|
<div className="flex-1 px-2 pb-2">
|
||||||
<LoadingOverlay isLoading={isLoading} />
|
<LoadingOverlay isLoading={isLoading} />
|
||||||
<UiTable
|
<UiTable
|
||||||
@@ -156,7 +156,7 @@ const SearchModal: React.FC = () => {
|
|||||||
{/* 유지관리 정보 탭 */}
|
{/* 유지관리 정보 탭 */}
|
||||||
{activeTab === 'operation' && (
|
{activeTab === 'operation' && (
|
||||||
<>
|
<>
|
||||||
<div className="h-[39vh] w-full overflow-hidden rounded-lg border">
|
<div className="h-[39vh] w-full overflow-hidden rounded-lg border mt-4">
|
||||||
<div className="flex-1 px-2 pb-2">
|
<div className="flex-1 px-2 pb-2">
|
||||||
<LoadingOverlay isLoading={isLoading} />
|
<LoadingOverlay isLoading={isLoading} />
|
||||||
<UiTable
|
<UiTable
|
||||||
@@ -217,23 +217,23 @@ const SearchModal: React.FC = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className='overflow-x-auto overflow-y-hidden'>
|
||||||
<UiModal
|
<UiModal
|
||||||
open={isSearchModalOpen}
|
open={isSearchModalOpen}
|
||||||
onOpenChange={setIsSearchModalOpen}
|
onOpenChange={setIsSearchModalOpen}
|
||||||
bodyClass={`
|
bodyClass={`
|
||||||
h-[100dvh]
|
h-[100dvh]
|
||||||
w-[60dvw]
|
w-[90dvw]
|
||||||
max-w-[100dvw]
|
max-w-[1200px]
|
||||||
max-h-[100dvh]
|
max-h-[100dvh]
|
||||||
overflow-hidden
|
overflow-y-hidden
|
||||||
z-[101]
|
z-[101]
|
||||||
`}
|
`}
|
||||||
body={renderBody()}
|
body={renderBody()}
|
||||||
useDirectRender={true}
|
useDirectRender={true}
|
||||||
/>
|
/>
|
||||||
<Toaster position="top-center"></Toaster>
|
<Toaster position="top-center"></Toaster>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ const Result = () => {
|
|||||||
const [sggCd, setSggCd] = useState<string>('0'); // 시군구 코드 상태
|
const [sggCd, setSggCd] = useState<string>('0'); // 시군구 코드 상태
|
||||||
const [sggName, setSggName] = useState<string>(''); // 시군구 이름 상태
|
const [sggName, setSggName] = useState<string>(''); // 시군구 이름 상태
|
||||||
|
|
||||||
const {ctpv, sgg} = useStore();
|
const { ctpv, sgg } = useStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// setCurPage(1);
|
// setCurPage(1);
|
||||||
@@ -166,7 +166,7 @@ const Result = () => {
|
|||||||
sggNm: sggOne ? sggOne.text : item.sggCd,
|
sggNm: sggOne ? sggOne.text : item.sggCd,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter((item: any) => item.scsYn === 'Y');
|
.filter((item: any) => item.scsYn === 'Y');
|
||||||
|
|
||||||
// 선택된 행 초기화
|
// 선택된 행 초기화
|
||||||
setSelectedRowData(null);
|
setSelectedRowData(null);
|
||||||
@@ -304,9 +304,9 @@ const Result = () => {
|
|||||||
onDeleteFile={handleFileDelete}
|
onDeleteFile={handleFileDelete}
|
||||||
selectedRowData={selectedRowData}
|
selectedRowData={selectedRowData}
|
||||||
>
|
>
|
||||||
{[<div key='table1' className="h-[58vh] flex flex-col border rounded-lg bg-white shadow-md">
|
{[<div key='table1' className="flex-1 flex flex-col border rounded-lg bg-white shadow-md min-h-0">
|
||||||
{/* <div className="mb-[1.2rem] text-xl font-medium">○ RDII 분석결과 현황</div> */}
|
{/* <div className="mb-[1.2rem] text-xl font-medium">○ RDII 분석결과 현황</div> */}
|
||||||
<div className="flex-grow overflow-auto">
|
<div className="flex-1 min-h-0">
|
||||||
<UiTable
|
<UiTable
|
||||||
headName=''
|
headName=''
|
||||||
headlist={tableColumn}
|
headlist={tableColumn}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ const Result = () => {
|
|||||||
const [ctpvCd, setCtpvCd] = useState<string>('0'); // 시도 코드 상태
|
const [ctpvCd, setCtpvCd] = useState<string>('0'); // 시도 코드 상태
|
||||||
const [sggCd, setSggCd] = useState<string>('0'); // 시군구 코드 상태
|
const [sggCd, setSggCd] = useState<string>('0'); // 시군구 코드 상태
|
||||||
const [sggName, setSggName] = useState<string>(''); // 시군구 이름 상태
|
const [sggName, setSggName] = useState<string>(''); // 시군구 이름 상태
|
||||||
const {ctpv, sgg} = useStore();
|
const { ctpv, sgg } = useStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// setCurPage(1);
|
// setCurPage(1);
|
||||||
@@ -159,7 +159,7 @@ const Result = () => {
|
|||||||
sggNm: sggOne ? sggOne.text : item.sggCd,
|
sggNm: sggOne ? sggOne.text : item.sggCd,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter((item: any) => item.scsYn === 'Y');
|
.filter((item: any) => item.scsYn === 'Y');
|
||||||
|
|
||||||
// 선택된 행 초기화
|
// 선택된 행 초기화
|
||||||
setSelectedRowData(null);
|
setSelectedRowData(null);
|
||||||
@@ -296,9 +296,9 @@ const Result = () => {
|
|||||||
onDeleteFile={handleFileDelete}
|
onDeleteFile={handleFileDelete}
|
||||||
selectedRowData={selectedRowData}
|
selectedRowData={selectedRowData}
|
||||||
>
|
>
|
||||||
{[<div key='table1' className="h-[58vh] flex flex-col border rounded-lg bg-white shadow-md">
|
{[<div key='table1' className="flex-1 flex flex-col border rounded-lg bg-white shadow-md min-h-0">
|
||||||
{/* <div className="mb-[1.2rem] text-xl font-medium">○ 침입수 산정결과 현황</div> */}
|
{/* <div className="mb-[1.2rem] text-xl font-medium">○ 침입수 산정결과 현황</div> */}
|
||||||
<div className="flex-grow overflow-auto">
|
<div className="flex-1 min-h-0">
|
||||||
<UiTable
|
<UiTable
|
||||||
headName=''
|
headName=''
|
||||||
headlist={tableColumn}
|
headlist={tableColumn}
|
||||||
|
|||||||
@@ -281,6 +281,7 @@ const Page = () => {
|
|||||||
max-h-[100dvh]
|
max-h-[100dvh]
|
||||||
overflow-hidden
|
overflow-hidden
|
||||||
z-[101]
|
z-[101]
|
||||||
|
flex flex-col gap-[10px]
|
||||||
`}
|
`}
|
||||||
body={<TableModal fileNm={fileNm} atflId={atflId} />}
|
body={<TableModal fileNm={fileNm} atflId={atflId} />}
|
||||||
useDirectRender={true}
|
useDirectRender={true}
|
||||||
|
|||||||
@@ -219,10 +219,10 @@ const TableModal: React.FC<TableModalProps> = ({ fileNm, atflId }) => {
|
|||||||
/>
|
/>
|
||||||
{/* 관리SHEET 탭 */}
|
{/* 관리SHEET 탭 */}
|
||||||
{activeTab === 'management' && (
|
{activeTab === 'management' && (
|
||||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
<div className="h-[79vh] rounded-lg border flex flex-col">
|
||||||
<div className="flex-1 px-2 pb-2">
|
<div className="flex-1 min-w-[50vw] max-w-[100vw] overflow-auto">
|
||||||
<LoadingOverlay isLoading={isLoading} />
|
<LoadingOverlay isLoading={isLoading} />
|
||||||
<div className="min-w-[550%]">
|
<div className="min-w-max">
|
||||||
<UiTable
|
<UiTable
|
||||||
headName={'관리SHEET'}
|
headName={'관리SHEET'}
|
||||||
tableData={managementTableData}
|
tableData={managementTableData}
|
||||||
@@ -231,6 +231,7 @@ const TableModal: React.FC<TableModalProps> = ({ fileNm, atflId }) => {
|
|||||||
total={0}
|
total={0}
|
||||||
cellClick={undefined}
|
cellClick={undefined}
|
||||||
onPageChange={() => { }}
|
onPageChange={() => { }}
|
||||||
|
className="whitespace-nowrap"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -276,6 +276,7 @@ const Page = () => {
|
|||||||
max-h-[100dvh]
|
max-h-[100dvh]
|
||||||
overflow-hidden
|
overflow-hidden
|
||||||
z-[101]
|
z-[101]
|
||||||
|
flex flex-col gap-[10px]
|
||||||
`}
|
`}
|
||||||
body={<TableModal fileNm={fileNm} atflId={atflId} />}
|
body={<TableModal fileNm={fileNm} atflId={atflId} />}
|
||||||
useDirectRender={true}
|
useDirectRender={true}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* 노후 하수관로 엑셀 데이터 테이블 모달 컴포넌트
|
* 노후 하수관로 엑셀 데이터 테이블 모달 컴포넌트
|
||||||
*
|
*
|
||||||
* - 엑셀 파일 다운로드 및 특정 시트 파싱 기능
|
* - 엑셀 파일 다운로드 및 특정 시트 파싱 기능
|
||||||
* - 탭 기반 테이블 표시 (row data, 정밀조사, 정비사업 등)
|
* - 탭 기반 테이블 표시 (raw data, 정밀조사, 정비사업 등)
|
||||||
* - 데이터 필터링 및 빈 행 제거 처리
|
* - 데이터 필터링 및 빈 행 제거 처리
|
||||||
* - 로딩 오버레이 및 에러 핸들링 지원
|
* - 로딩 오버레이 및 에러 핸들링 지원
|
||||||
* - XLSX 라이브러리를 통한 엑셀 데이터 변환
|
* - XLSX 라이브러리를 통한 엑셀 데이터 변환
|
||||||
@@ -21,7 +21,7 @@ import { HeadMakeColSpan } from '@common/business_components/ui/table/HeadMakeCo
|
|||||||
import { oldPpTable2HeadList, oldPpTable2NodeList, oldPpTable6HeadList, oldPpTable6NodeList } from './headList';
|
import { oldPpTable2HeadList, oldPpTable2NodeList, oldPpTable6HeadList, oldPpTable6NodeList } from './headList';
|
||||||
|
|
||||||
const TABS = [
|
const TABS = [
|
||||||
{ val: "1", text: "row data" },
|
{ val: "1", text: "raw data" },
|
||||||
{ val: "2", text: "1.정밀조사" },
|
{ val: "2", text: "1.정밀조사" },
|
||||||
{ val: "3", text: "2.정밀조사_정비사업연계" },
|
{ val: "3", text: "2.정밀조사_정비사업연계" },
|
||||||
{ val: "4", text: " 3.정비사업" },
|
{ val: "4", text: " 3.정비사업" },
|
||||||
@@ -74,15 +74,15 @@ const TableModal: React.FC<TableModalProps> = ({ fileNm, atflId }) => {
|
|||||||
type: blob.type || 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
type: blob.type || 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||||
});
|
});
|
||||||
|
|
||||||
const targetSheets = ['row data', '1.정밀조사', '2.정밀조사_정비사업연계', ' 3.정비사업', '4.정비사업요약', '4.정비사업최종'];
|
const targetSheets = ['raw data', '1.정밀조사', '2.정밀조사_정비사업연계', ' 3.정비사업', '4.정비사업요약', '4.정비사업최종'];
|
||||||
const jsonDataBySheet = await filePickedSelectedSheets(file, 0, targetSheets);
|
const jsonDataBySheet = await filePickedSelectedSheets(file, 0, targetSheets);
|
||||||
|
|
||||||
const header1 = jsonDataBySheet['row data']?.[1] || [];
|
const header1 = jsonDataBySheet['raw data']?.[1] || [];
|
||||||
const header2 = jsonDataBySheet['1.정밀조사']?.[1] || [];
|
const header2 = jsonDataBySheet['1.정밀조사']?.[1] || [];
|
||||||
const header4 = jsonDataBySheet[' 3.정비사업']?.[1] || [];
|
const header4 = jsonDataBySheet[' 3.정비사업']?.[1] || [];
|
||||||
const header5 = jsonDataBySheet['4.정비사업요약']?.[2] || [];
|
const header5 = jsonDataBySheet['4.정비사업요약']?.[2] || [];
|
||||||
|
|
||||||
// row data
|
// raw data
|
||||||
const allEntries1 = Object.entries(header1);
|
const allEntries1 = Object.entries(header1);
|
||||||
const filteredHeader1 = [
|
const filteredHeader1 = [
|
||||||
allEntries1[0],
|
allEntries1[0],
|
||||||
@@ -111,8 +111,8 @@ const TableModal: React.FC<TableModalProps> = ({ fileNm, atflId }) => {
|
|||||||
});
|
});
|
||||||
setTableHeader1(filteredHeader1);
|
setTableHeader1(filteredHeader1);
|
||||||
|
|
||||||
const data1 = Array.isArray(jsonDataBySheet['row data'])
|
const data1 = Array.isArray(jsonDataBySheet['raw data'])
|
||||||
? jsonDataBySheet['row data'].slice(2)
|
? jsonDataBySheet['raw data'].slice(2)
|
||||||
: [];
|
: [];
|
||||||
const filteredData1 = filterEmptyRows(data1).map((item: any, index: number) => ({
|
const filteredData1 = filterEmptyRows(data1).map((item: any, index: number) => ({
|
||||||
...item,
|
...item,
|
||||||
@@ -177,303 +177,303 @@ const TableModal: React.FC<TableModalProps> = ({ fileNm, atflId }) => {
|
|||||||
rowNumber: index + 1
|
rowNumber: index + 1
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
setTableData3(filteredData3);
|
setTableData3(filteredData3);
|
||||||
|
|
||||||
// 3.정비사업
|
// 3.정비사업
|
||||||
const allEntries4 = Object.entries(header4);
|
const allEntries4 = Object.entries(header4);
|
||||||
const filteredHeader4 = allEntries4.filter((e): e is [string, any] => Boolean(e))
|
const filteredHeader4 = allEntries4.filter((e): e is [string, any] => Boolean(e))
|
||||||
.map(([key, value]) => ({
|
.map(([key, value]) => ({
|
||||||
id: key,
|
id: key,
|
||||||
title: String(value).replace(/\r\n/g, '\n')
|
title: String(value).replace(/\r\n/g, '\n')
|
||||||
}));
|
}));
|
||||||
|
|
||||||
filteredHeader4.splice(0, 0, {
|
filteredHeader4.splice(0, 0, {
|
||||||
id: "rowNumber",
|
id: "rowNumber",
|
||||||
title: '일련번호'
|
title: '일련번호'
|
||||||
});
|
});
|
||||||
setTableHeader4(filteredHeader4);
|
setTableHeader4(filteredHeader4);
|
||||||
|
|
||||||
const data4 = Array.isArray(jsonDataBySheet[' 3.정비사업'])
|
const data4 = Array.isArray(jsonDataBySheet[' 3.정비사업'])
|
||||||
? jsonDataBySheet[' 3.정비사업'].slice(2)
|
? jsonDataBySheet[' 3.정비사업'].slice(2)
|
||||||
: [];
|
: [];
|
||||||
const filteredData4 = filterEmptyRows(data4).map((item: any, index: number) => ({
|
const filteredData4 = filterEmptyRows(data4).map((item: any, index: number) => ({
|
||||||
...item,
|
|
||||||
rowNumber: index + 1,
|
|
||||||
__EMPTY_2: item?.__EMPTY_2 || '-',
|
|
||||||
__EMPTY_11: item?.__EMPTY_11 || '-',
|
|
||||||
}));
|
|
||||||
setTableData4(filteredData4);
|
|
||||||
|
|
||||||
// 4.정비사업요약
|
|
||||||
const allEntries5 = Object.entries(header5);
|
|
||||||
const excludeKeys5 = [
|
|
||||||
": \"정비사업\"sheet에서 사업코드 ctrl+c, Ctrl+v 한 다음 중복된 데이터 제거실시",
|
|
||||||
"__EMPTY",
|
|
||||||
"__EMPTY_8",
|
|
||||||
"__EMPTY_15"
|
|
||||||
];
|
|
||||||
const filteredHeader5 = allEntries5
|
|
||||||
.filter(([key]) => !excludeKeys5.includes(key))
|
|
||||||
.filter((e): e is [string, any] => Boolean(e))
|
|
||||||
.map(([key, value]) => ({
|
|
||||||
id: key,
|
|
||||||
title: String(value).replace(/\r\n/g, '\n'),
|
|
||||||
}));
|
|
||||||
filteredHeader5.splice(0, 0, {
|
|
||||||
id: "rowNumber",
|
|
||||||
title: '일련번호'
|
|
||||||
});
|
|
||||||
setTableHeader5(filteredHeader5);
|
|
||||||
|
|
||||||
const data5 = Array.isArray(jsonDataBySheet['4.정비사업요약'])
|
|
||||||
? jsonDataBySheet['4.정비사업요약'].slice(3)
|
|
||||||
: [];
|
|
||||||
const filteredData5 =
|
|
||||||
filterEmptyRows(data5).map((item: any, index: number) => ({
|
|
||||||
...item,
|
...item,
|
||||||
rowNumber: index + 1,
|
rowNumber: index + 1,
|
||||||
|
__EMPTY_2: item?.__EMPTY_2 || '-',
|
||||||
|
__EMPTY_11: item?.__EMPTY_11 || '-',
|
||||||
}));
|
}));
|
||||||
setTableData5(filteredData5);
|
setTableData4(filteredData4);
|
||||||
|
|
||||||
// 4.정비사업최종 (헤더는 import)
|
// 4.정비사업요약
|
||||||
const data6 = Array.isArray(jsonDataBySheet['4.정비사업최종'])
|
const allEntries5 = Object.entries(header5);
|
||||||
? jsonDataBySheet['4.정비사업최종'].slice(6)
|
const excludeKeys5 = [
|
||||||
: [];
|
": \"정비사업\"sheet에서 사업코드 ctrl+c, Ctrl+v 한 다음 중복된 데이터 제거실시",
|
||||||
const filteredData6 =
|
"__EMPTY",
|
||||||
filterEmptyRows(data6).map((item: any, index: number) => ({
|
"__EMPTY_8",
|
||||||
...item,
|
"__EMPTY_15"
|
||||||
rowNumber: index + 1,
|
];
|
||||||
}));
|
const filteredHeader5 = allEntries5
|
||||||
setTableData6(filteredData6);
|
.filter(([key]) => !excludeKeys5.includes(key))
|
||||||
} catch (error) {
|
.filter((e): e is [string, any] => Boolean(e))
|
||||||
console.error('파일 처리 중 오류 발생:', error);
|
.map(([key, value]) => ({
|
||||||
alert('파일 처리 중 오류가 발생했습니다.');
|
id: key,
|
||||||
} finally {
|
title: String(value).replace(/\r\n/g, '\n'),
|
||||||
setIsLoading(false);
|
}));
|
||||||
|
filteredHeader5.splice(0, 0, {
|
||||||
|
id: "rowNumber",
|
||||||
|
title: '일련번호'
|
||||||
|
});
|
||||||
|
setTableHeader5(filteredHeader5);
|
||||||
|
|
||||||
|
const data5 = Array.isArray(jsonDataBySheet['4.정비사업요약'])
|
||||||
|
? jsonDataBySheet['4.정비사업요약'].slice(3)
|
||||||
|
: [];
|
||||||
|
const filteredData5 =
|
||||||
|
filterEmptyRows(data5).map((item: any, index: number) => ({
|
||||||
|
...item,
|
||||||
|
rowNumber: index + 1,
|
||||||
|
}));
|
||||||
|
setTableData5(filteredData5);
|
||||||
|
|
||||||
|
// 4.정비사업최종 (헤더는 import)
|
||||||
|
const data6 = Array.isArray(jsonDataBySheet['4.정비사업최종'])
|
||||||
|
? jsonDataBySheet['4.정비사업최종'].slice(6)
|
||||||
|
: [];
|
||||||
|
const filteredData6 =
|
||||||
|
filterEmptyRows(data6).map((item: any, index: number) => ({
|
||||||
|
...item,
|
||||||
|
rowNumber: index + 1,
|
||||||
|
}));
|
||||||
|
setTableData6(filteredData6);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('파일 처리 중 오류 발생:', error);
|
||||||
|
alert('파일 처리 중 오류가 발생했습니다.');
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function filterEmptyRows(data: any[]) {
|
function filterEmptyRows(data: any[]) {
|
||||||
return data
|
return data
|
||||||
.filter(row => {
|
.filter(row => {
|
||||||
return Object.entries(row).some(([key, value]) => {
|
return Object.entries(row).some(([key, value]) => {
|
||||||
const match = key.match(/^__EMPTY_(\d+)$/);
|
const match = key.match(/^__EMPTY_(\d+)$/);
|
||||||
if (!match || parseInt(match[1] ?? '', 10) < 2) return false;
|
if (!match || parseInt(match[1] ?? '', 10) < 2) return false;
|
||||||
|
|
||||||
return value !== undefined &&
|
return value !== undefined &&
|
||||||
value !== null &&
|
value !== null &&
|
||||||
String(value).trim() !== '' &&
|
String(value).trim() !== '' &&
|
||||||
String(value).trim() !== '-' &&
|
String(value).trim() !== '-' &&
|
||||||
String(value).trim() !== '';
|
String(value).trim() !== '';
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.map((row) => {
|
.map((row) => {
|
||||||
const processedRow = { ...row };
|
const processedRow = { ...row };
|
||||||
const keys = Object.keys(processedRow);
|
const keys = Object.keys(processedRow);
|
||||||
|
|
||||||
keys.forEach((key, keyIndex) => {
|
keys.forEach((key, keyIndex) => {
|
||||||
// 마지막 속성(사업 근거)이 아닌 경우에만 빈 값을 '-'으로 변경
|
// 마지막 속성(사업 근거)이 아닌 경우에만 빈 값을 '-'으로 변경
|
||||||
if (keyIndex !== keys.length - 1) {
|
if (keyIndex !== keys.length - 1) {
|
||||||
const value = processedRow[key];
|
const value = processedRow[key];
|
||||||
if (value === undefined ||
|
if (value === undefined ||
|
||||||
value === null ||
|
value === null ||
|
||||||
value === '' ||
|
value === '' ||
|
||||||
String(value).trim() === '') {
|
String(value).trim() === '') {
|
||||||
processedRow[key] = '-';
|
processedRow[key] = '-';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return processedRow;
|
return processedRow;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 특정 시트만 선택적으로 JSON으로 변환하는 함수
|
||||||
|
function filePickedSelectedSheets(file: File, headerNum: number = 0, sheetNames: string[]): Promise<Record<string, any[]>> {
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
reader.onload = function (e) {
|
||||||
|
const data = e.target?.result;
|
||||||
|
if (!data) {
|
||||||
|
console.error("Failed to read file: e.target.result is null");
|
||||||
|
reject(new Error("Failed to read file"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Excel 파일 읽기
|
||||||
|
const wb = XLSX.read(data, { type: 'binary', cellDates: true });
|
||||||
|
const result: Record<string, any[]> = {};
|
||||||
|
|
||||||
|
// 지정된 시트 이름만 찾아서 처리
|
||||||
|
sheetNames.forEach(targetSheetName => {
|
||||||
|
// 대소문자 구분 없이 시트 이름 찾기
|
||||||
|
const sheetName = wb.SheetNames.find(name =>
|
||||||
|
name.toLowerCase() === targetSheetName.toLowerCase()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sheetName) {
|
||||||
|
const sheet = wb.Sheets[sheetName];
|
||||||
|
if (sheet) {
|
||||||
|
const jsonData = XLSX.utils.sheet_to_json(sheet, { range: headerNum, raw: false });
|
||||||
|
result[targetSheetName] = jsonData;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn(`Sheet "${targetSheetName}" not found in workbook`);
|
||||||
|
result[targetSheetName] = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.onerror = function () {
|
||||||
|
console.error("Error reading file");
|
||||||
|
reject(new Error("Error reading file"));
|
||||||
|
};
|
||||||
|
|
||||||
|
// 파일 읽기 시작
|
||||||
|
reader.readAsBinaryString(file);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 특정 시트만 선택적으로 JSON으로 변환하는 함수
|
|
||||||
function filePickedSelectedSheets(file: File, headerNum: number = 0, sheetNames: string[]): Promise<Record<string, any[]>> {
|
|
||||||
const reader = new FileReader();
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
reader.onload = function (e) {
|
|
||||||
const data = e.target?.result;
|
|
||||||
if (!data) {
|
|
||||||
console.error("Failed to read file: e.target.result is null");
|
|
||||||
reject(new Error("Failed to read file"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Excel 파일 읽기
|
|
||||||
const wb = XLSX.read(data, { type: 'binary', cellDates: true });
|
|
||||||
const result: Record<string, any[]> = {};
|
|
||||||
|
|
||||||
// 지정된 시트 이름만 찾아서 처리
|
|
||||||
sheetNames.forEach(targetSheetName => {
|
|
||||||
// 대소문자 구분 없이 시트 이름 찾기
|
|
||||||
const sheetName = wb.SheetNames.find(name =>
|
|
||||||
name.toLowerCase() === targetSheetName.toLowerCase()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (sheetName) {
|
|
||||||
const sheet = wb.Sheets[sheetName];
|
|
||||||
if (sheet) {
|
|
||||||
const jsonData = XLSX.utils.sheet_to_json(sheet, { range: headerNum, raw: false });
|
|
||||||
result[targetSheetName] = jsonData;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.warn(`Sheet "${targetSheetName}" not found in workbook`);
|
|
||||||
result[targetSheetName] = [];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
resolve(result);
|
|
||||||
};
|
|
||||||
|
|
||||||
reader.onerror = function () {
|
|
||||||
console.error("Error reading file");
|
|
||||||
reject(new Error("Error reading file"));
|
|
||||||
};
|
|
||||||
|
|
||||||
// 파일 읽기 시작
|
|
||||||
reader.readAsBinaryString(file);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* 탭 영역 */}
|
{/* 탭 영역 */}
|
||||||
<UITab
|
<UITab
|
||||||
defaultValue={activeTab}
|
defaultValue={activeTab}
|
||||||
tabList={TABS.map((tab) => ({
|
tabList={TABS.map((tab) => ({
|
||||||
value: tab.val,
|
value: tab.val,
|
||||||
label: tab.text
|
label: tab.text
|
||||||
}))}
|
}))}
|
||||||
onValueChange={(value: string) => setActiveTab(value)}
|
onValueChange={(value: string) => setActiveTab(value)}
|
||||||
/>
|
/>
|
||||||
{/* row data 탭 */}
|
{/* row data 탭 */}
|
||||||
{activeTab === '1' && (
|
{activeTab === '1' && (
|
||||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
<div className="h-[79vh] rounded-lg border flex flex-col">
|
||||||
<div className="flex-1 px-2 pb-2">
|
<div className="flex-1 min-w-[50vw] max-w-[100vw] overflow-auto">
|
||||||
<LoadingOverlay isLoading={isLoading} />
|
<LoadingOverlay isLoading={isLoading} />
|
||||||
<div className="min-w-[150%]">
|
<div className="min-w-max">
|
||||||
<UiTable
|
<UiTable
|
||||||
headName={'row data'}
|
headName={'raw data'}
|
||||||
tableData={tableData1}
|
tableData={tableData1}
|
||||||
headlist={tableHeader1}
|
headlist={tableHeader1}
|
||||||
pageSize={10}
|
pageSize={10}
|
||||||
total={0}
|
total={0}
|
||||||
cellClick={undefined}
|
cellClick={undefined}
|
||||||
onPageChange={() => { }}
|
onPageChange={() => { }}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
{/* 1.정밀조사 탭 */}
|
||||||
{/* 1.정밀조사 탭 */}
|
{activeTab === '2' && (
|
||||||
{activeTab === '2' && (
|
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
<div className="flex-1 px-2 pb-2">
|
||||||
<div className="flex-1 px-2 pb-2">
|
<LoadingOverlay isLoading={isLoading} />
|
||||||
<LoadingOverlay isLoading={isLoading} />
|
<div className="min-w-[150%]">
|
||||||
<div className="min-w-[150%]">
|
<UiTable
|
||||||
<UiTable
|
headName={'1.정밀조사'}
|
||||||
headName={'1.정밀조사'}
|
tableData={tableData2}
|
||||||
tableData={tableData2}
|
headlist={tableHeader2}
|
||||||
headlist={tableHeader2}
|
pageSize={10}
|
||||||
pageSize={10}
|
total={0}
|
||||||
total={0}
|
className={"overflow-x-auto overflow-y-auto"}
|
||||||
className={"overflow-x-auto overflow-y-auto"}
|
cellClick={undefined}
|
||||||
cellClick={undefined}
|
onPageChange={() => { }}
|
||||||
onPageChange={() => { }}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
{/* 2.정밀조사_정비사업연계 탭 */}
|
||||||
{/* 2.정밀조사_정비사업연계 탭 */}
|
{activeTab === '3' && (
|
||||||
{activeTab === '3' && (
|
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
<div className="flex-1 px-2 pb-2">
|
||||||
<div className="flex-1 px-2 pb-2">
|
<LoadingOverlay isLoading={isLoading} />
|
||||||
<LoadingOverlay isLoading={isLoading} />
|
<div className="min-w-[550%]">
|
||||||
<div className="min-w-[550%]">
|
<UiTable
|
||||||
<UiTable
|
headName={'2.정밀조사_정비사업연계'}
|
||||||
headName={'2.정밀조사_정비사업연계'}
|
tableData={tableData3}
|
||||||
tableData={tableData3}
|
headlist={oldPpTable2HeadList}
|
||||||
headlist={oldPpTable2HeadList}
|
pageSize={10}
|
||||||
pageSize={10}
|
total={0}
|
||||||
total={0}
|
className={"overflow-x-auto overflow-y-auto"}
|
||||||
className={"overflow-x-auto overflow-y-auto"}
|
cellClick={undefined}
|
||||||
cellClick={undefined}
|
onPageChange={() => { }}
|
||||||
onPageChange={() => { }}
|
>
|
||||||
>
|
<HeadMakeColSpan upHeadList={oldPpTable2NodeList} />
|
||||||
<HeadMakeColSpan upHeadList={oldPpTable2NodeList} />
|
</UiTable>
|
||||||
</UiTable>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
{/* 3.정비사업 탭 */}
|
||||||
{/* 3.정비사업 탭 */}
|
{activeTab === '4' && (
|
||||||
{activeTab === '4' && (
|
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
<div className="flex-1 px-2 pb-2">
|
||||||
<div className="flex-1 px-2 pb-2">
|
<LoadingOverlay isLoading={isLoading} />
|
||||||
<LoadingOverlay isLoading={isLoading} />
|
<div className="min-w-[160%]">
|
||||||
<div className="min-w-[160%]">
|
<UiTable
|
||||||
<UiTable
|
headName={'3.정비사업'}
|
||||||
headName={'3.정비사업'}
|
tableData={tableData4}
|
||||||
tableData={tableData4}
|
headlist={tableHeader4}
|
||||||
headlist={tableHeader4}
|
pageSize={10}
|
||||||
pageSize={10}
|
total={0}
|
||||||
total={0}
|
className={"overflow-x-auto overflow-y-auto"}
|
||||||
className={"overflow-x-auto overflow-y-auto"}
|
cellClick={undefined}
|
||||||
cellClick={undefined}
|
onPageChange={() => { }}
|
||||||
onPageChange={() => { }}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
{/* 4.정비사업요약 탭 */}
|
||||||
{/* 4.정비사업요약 탭 */}
|
{activeTab === '5' && (
|
||||||
{activeTab === '5' && (
|
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
<div className="flex-1 px-2 pb-2">
|
||||||
<div className="flex-1 px-2 pb-2">
|
<LoadingOverlay isLoading={isLoading} />
|
||||||
<LoadingOverlay isLoading={isLoading} />
|
<div className="min-w-[130%]">
|
||||||
<div className="min-w-[130%]">
|
<UiTable
|
||||||
<UiTable
|
headName={'4.정비사업요약'}
|
||||||
headName={'4.정비사업요약'}
|
tableData={tableData5}
|
||||||
tableData={tableData5}
|
headlist={tableHeader5}
|
||||||
headlist={tableHeader5}
|
pageSize={10}
|
||||||
pageSize={10}
|
total={0}
|
||||||
total={0}
|
className={"overflow-x-auto overflow-y-auto"}
|
||||||
className={"overflow-x-auto overflow-y-auto"}
|
cellClick={undefined}
|
||||||
cellClick={undefined}
|
onPageChange={() => { }}
|
||||||
onPageChange={() => { }}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
{/* 4.정비사업최종 탭 */}
|
||||||
{/* 4.정비사업최종 탭 */}
|
{activeTab === '6' && (
|
||||||
{activeTab === '6' && (
|
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
<div className="flex-1 px-2 pb-2">
|
||||||
<div className="flex-1 px-2 pb-2">
|
<LoadingOverlay isLoading={isLoading} />
|
||||||
<LoadingOverlay isLoading={isLoading} />
|
<div className="min-w-[200%]">
|
||||||
<div className="min-w-[200%]">
|
<UiTable
|
||||||
<UiTable
|
headName={'4.정비사업최종'}
|
||||||
headName={'4.정비사업최종'}
|
tableData={tableData6}
|
||||||
tableData={tableData6}
|
headlist={oldPpTable6HeadList}
|
||||||
headlist={oldPpTable6HeadList}
|
pageSize={10}
|
||||||
pageSize={10}
|
total={0}
|
||||||
total={0}
|
className={"overflow-x-auto overflow-y-auto"}
|
||||||
className={"overflow-x-auto overflow-y-auto"}
|
cellClick={undefined}
|
||||||
cellClick={undefined}
|
onPageChange={() => { }}
|
||||||
onPageChange={() => { }}
|
>
|
||||||
>
|
<HeadMakeColSpan upHeadList={oldPpTable6NodeList} />
|
||||||
<HeadMakeColSpan upHeadList={oldPpTable6NodeList} />
|
</UiTable>
|
||||||
</UiTable>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
</>
|
||||||
</>
|
)
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TableModal;
|
export default TableModal;
|
||||||
@@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from "next/server";
|
|||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
const hostname = request.nextUrl.hostname;
|
const hostname = request.nextUrl.hostname;
|
||||||
const redirectUrl = process.env.NEXT_PUBLIC_CM_LOGIN_PAGE_URL || "https://queen.hasuon.or.kr";
|
const redirectUrl = process.env.NEXT_PUBLIC_CM_LOGIN_PAGE_URL || "https://portal.hasuon.or.kr";
|
||||||
|
|
||||||
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr") {
|
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr") {
|
||||||
return NextResponse.redirect(new URL("/", request.url)); // 로컬 및 개발 환경
|
return NextResponse.redirect(new URL("/", request.url)); // 로컬 및 개발 환경
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
|
const subDomain =
|
||||||
|
process.env.NEXT_PUBLIC_SUB_DOMAIN || "http://localhost:13000";
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
experimental: {
|
experimental: {
|
||||||
@@ -11,6 +14,17 @@ const nextConfig: NextConfig = {
|
|||||||
eslint: {
|
eslint: {
|
||||||
ignoreDuringBuilds: true,
|
ignoreDuringBuilds: true,
|
||||||
},
|
},
|
||||||
|
async rewrites() {
|
||||||
|
return {
|
||||||
|
afterFiles: [
|
||||||
|
{
|
||||||
|
source: "/cms/:path*",
|
||||||
|
destination: `${subDomain}/cms/:path*`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
fallback: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from "next/server";
|
|||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
const hostname = request.nextUrl.hostname;
|
const hostname = request.nextUrl.hostname;
|
||||||
const redirectUrl = process.env.NEXT_PUBLIC_CM_LOGIN_PAGE_URL || "https://queen.hasuon.or.kr";
|
const redirectUrl = process.env.NEXT_PUBLIC_CM_LOGIN_PAGE_URL || "https://portal.hasuon.or.kr";
|
||||||
|
|
||||||
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr") {
|
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr") {
|
||||||
return NextResponse.redirect(new URL("/", request.url)); // 로컬 및 개발 환경
|
return NextResponse.redirect(new URL("/", request.url)); // 로컬 및 개발 환경
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const BASE_URL = `${PROXY_HOST}/server`;
|
|||||||
export const getImageUrlByAtflCd = async (atflCd: string): Promise<string> => {
|
export const getImageUrlByAtflCd = async (atflCd: string): Promise<string> => {
|
||||||
if (!atflCd) return "";
|
if (!atflCd) return "";
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${BASE_URL}/${ENDPOINT.ATTACH_SERVICE.IMAGES}/atflCd/${atflCd}`,
|
`${BASE_URL}${ENDPOINT.ATTACH_SERVICE.IMAGES}/atflCd/${atflCd}`,
|
||||||
);
|
);
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
return URL.createObjectURL(blob);
|
return URL.createObjectURL(blob);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const client = getApiClient();
|
|||||||
|
|
||||||
export const getBannerList = async (siteId: string) => {
|
export const getBannerList = async (siteId: string) => {
|
||||||
const response = await client.get<Banner[]>(
|
const response = await client.get<Banner[]>(
|
||||||
`${BASE_URL}/${ENDPOINT.CMS_SERVICE.BANNERS}/${siteId}`,
|
`${BASE_URL}${ENDPOINT.CMS_SERVICE.BANNERS}/${siteId}`,
|
||||||
{
|
{
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ const BASE_URL = `${PROXY_HOST}/server`;
|
|||||||
|
|
||||||
export const getSiteInfo = async (siteId: string) => {
|
export const getSiteInfo = async (siteId: string) => {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${BASE_URL}/${ENDPOINT.CMS_SERVICE.SITES}/${siteId}`,
|
`${BASE_URL}${ENDPOINT.CMS_SERVICE.SITES}/${siteId}`,
|
||||||
{
|
{
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -74,7 +74,7 @@ const client = getApiClient();
|
|||||||
|
|
||||||
export const getSiteList = async () => {
|
export const getSiteList = async () => {
|
||||||
const response = await client.get<SiteListResponse>(
|
const response = await client.get<SiteListResponse>(
|
||||||
`${BASE_URL}/${ENDPOINT.CMS_SERVICE.SITE_LIST}`,
|
`${BASE_URL}${ENDPOINT.CMS_SERVICE.SITE_LIST}`,
|
||||||
{
|
{
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
Reference in New Issue
Block a user