842 lines
32 KiB
TypeScript
842 lines
32 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { downloadExcelWithKoreanHeaders } from '@common/business_components/ui';
|
|
import axios from 'axios';
|
|
import {
|
|
MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_USE_CODES, MS_SWAGE_MHL_CODES, MS_SWAGE_MHL_USE_CODES,
|
|
MsSwagePplExcelCol, SwtrmtFcltExcelCol, SwtrmtPrcsZoneExcelCol, MsSwageMhlExcelCol, ExclnSewagePumpExcelCol, stofcbrExcelCol
|
|
} from '../components/common/table';
|
|
import { getData } from "@/components/lib/api";
|
|
import { BASIC_TYPES } from './basicTab';
|
|
import { WORK_TYPES } from './operationTab';
|
|
import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue';
|
|
import useStore from '../../../store/useStore';
|
|
import GisApp from "@common/business_components/ui/map/lib/gis.core";
|
|
import { confirmToast } from '@/components/ui/toast'
|
|
import { toast } from "react-hot-toast";
|
|
import useSearchModalStore from '../../../store/useSearchModalStore';
|
|
import { swagePplCqlFilters } from './swagePpl';
|
|
import { swagePrcsFcltCqlFilters } from './swagePrcsFclt';
|
|
import { swagePrcsZoneCqlFilters } from './swagePrcsZone';
|
|
import { swageMhlCqlFilters } from './swageMhl';
|
|
import { swagePmstnCqlFilters } from './swagePmstn';
|
|
import { stofcbrCqlFilters } from './stofcbr';
|
|
|
|
const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}`;
|
|
export const OPERATION_TABLE_SIZE = 5;
|
|
|
|
export interface SearchModalProps {
|
|
open: boolean;
|
|
onOpenChange: (open: boolean) => void;
|
|
onFeatureSelect: (row: any) => void;
|
|
}
|
|
|
|
export function useSearchModal({ open, onOpenChange, onFeatureSelect }: SearchModalProps) {
|
|
const {
|
|
activeTab, basicType, workType,
|
|
showTable,
|
|
tableData, detailTableData,
|
|
curPage, detailCurPage,
|
|
detailBizId,
|
|
ctpvCd, ctpvName, sggCd, sggName,
|
|
start1, start2, end1, end2,
|
|
var1, var2,
|
|
yearFilter,
|
|
todayYear, todayMonth, todayDate,
|
|
setShowTable,
|
|
setTableData, setDetailTableData,
|
|
setTableCount, setDetailTableCount,
|
|
setCurPage, setDetailCurPage,
|
|
setIsLoading, setIsDetailLoading,
|
|
setIsResetPage, setIsResetDetailPage,
|
|
setIsResetSelection, setIsResetDetailSelection,
|
|
setDetailBizId,
|
|
resetFilters,
|
|
getDateString
|
|
} = useSearchModalStore();
|
|
const { ctpv, sgg, BIZ_TY_CD } = useStore();
|
|
|
|
const TABS = [
|
|
{ val: "basic", text: "기본정보" },
|
|
{ val: "operation", text: "운영정보" },
|
|
{ val: "report", text: "하수도정비기본계획보고서" },
|
|
];
|
|
|
|
|
|
useEffect(() => {
|
|
resetFilters();
|
|
}, [activeTab, basicType, workType]);
|
|
|
|
// 페이지 변경 시마다 데이터 fetch
|
|
useEffect(() => {
|
|
setIsResetPage(false);
|
|
setIsResetDetailPage(true);
|
|
setDetailBizId(0);
|
|
if (showTable) fetchFilteredData();
|
|
}, [curPage]);
|
|
|
|
// 페이지 변경 시마다 데이터 fetch
|
|
useEffect(() => {
|
|
setIsResetDetailSelection(false);
|
|
if (showTable) handleOperationPageNation(Number(detailBizId));
|
|
}, [detailCurPage]);
|
|
|
|
|
|
// 검색 API 호출 함수
|
|
const fetchFilteredData = async () => {
|
|
setIsLoading(true); // 로딩 시작
|
|
setIsResetSelection(true); // 선택 초기화
|
|
setIsResetDetailSelection(true); // 선택 초기화
|
|
|
|
try {
|
|
let cqlFilters: string[] = [];
|
|
if (activeTab === 'basic') {
|
|
const queryParams = new URLSearchParams({
|
|
lyrTypeNm: basicType,
|
|
page: `${curPage - 1}`,
|
|
size: '10',
|
|
sort: 'string',
|
|
});
|
|
|
|
if (basicType === 'tb_ms_swage_prcs_zone') cqlFilters = swagePrcsZoneCqlFilters({
|
|
ctpvCd, sggCd,
|
|
var1, var2
|
|
}); // 하수처리구역
|
|
else if (basicType === 'tb_il_swage_prcs_fclt') cqlFilters = swagePrcsFcltCqlFilters({
|
|
ctpvName, sggName,
|
|
yearFilter,
|
|
start1, end1,
|
|
todayYear, todayMonth, todayDate,
|
|
getDateString
|
|
}); // 하수처리시설
|
|
else if (basicType === 'tb_ms_swage_ppl') cqlFilters = swagePplCqlFilters({
|
|
var1, var2,
|
|
ctpvCd, sggCd,
|
|
yearFilter,
|
|
start1, start2, end1, end2,
|
|
todayYear, todayMonth, todayDate,
|
|
getDateString
|
|
}); // 하수관로
|
|
else if (basicType === 'tb_ms_swage_mhl') cqlFilters = swageMhlCqlFilters({
|
|
ctpvCd, sggCd,
|
|
yearFilter,
|
|
start1, end1,
|
|
var1,
|
|
todayYear, todayMonth, todayDate,
|
|
getDateString
|
|
}); // 하수맨홀
|
|
else if (basicType === 'tb_ms_swage_pmstn') cqlFilters = swagePmstnCqlFilters({
|
|
ctpvCd, sggCd,
|
|
yearFilter,
|
|
start1, start2, end1, end2,
|
|
todayYear, todayMonth, todayDate,
|
|
getDateString
|
|
}); // 하수펌프장
|
|
else if (basicType === 'tb_ms_stofcbr') cqlFilters = stofcbrCqlFilters({
|
|
ctpvCd, sggCd,
|
|
yearFilter,
|
|
todayYear, todayMonth, todayDate,
|
|
getDateString
|
|
}); // 우수토실
|
|
|
|
if (cqlFilters.length > 0) queryParams.append('cqlFiter', cqlFilters.join(' and '));
|
|
|
|
const res = await axios.get(`${API_URL}/v1/fclts?${queryParams.toString()}`);
|
|
|
|
// 🎯 각 아이템을 개별적으로 포맷팅하면서 일련번호 추가
|
|
const dataWithRowNumber = (res.data.data || []).map((item: any, index: number) => {
|
|
// 🎯 먼저 각 아이템을 포맷팅
|
|
const formattedItem = formatDisplayData(item);
|
|
|
|
let ctpvCd = item?.ctpvNm ?? formattedItem?.ctpvNm ?? '';
|
|
let sggCd = item?.sggNm ?? formattedItem?.sggNm ?? '';
|
|
|
|
if (!ctpvCd || !sggCd) {
|
|
const code = String(item?.pbadmsEmdCd ?? formattedItem?.pbadmsEmdCd ?? '')?.trim();
|
|
if (!ctpvCd && code) ctpvCd = code.slice(0, 2);
|
|
if (!sggCd && code) sggCd = code.slice(0, 5);
|
|
}
|
|
|
|
const matchedMhlCode = MS_SWAGE_MHL_CODES.find(code => code.val === item?.mqltCd?.trim());
|
|
const matchedMhlUsgCode = MS_SWAGE_MHL_USE_CODES.find(code => code.val === item?.usgCd);
|
|
const ctpvNm = ctpv.find(code => code.val.trim() === ctpvCd)?.text || item?.ctpvNm;
|
|
const sggNm = sgg.find(code => code.val.trim() === sggCd)?.text || item?.sggNm;
|
|
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim());
|
|
|
|
// 추가 처리 및 일련번호 추가
|
|
return {
|
|
...formattedItem,
|
|
rowNumber: (curPage - 1) * 10 + index + 1, // 1부터 시작하는 일련번호 추가
|
|
scsYn: item.scsYn === null || item.scsYn === undefined ? 'N' : item?.scsYn, // scsYn이 null이면 'N'으로 변경
|
|
mqltCd: matchedMhlCode ? matchedMhlCode.text : item?.mqltCd,
|
|
usgCd: matchedMhlUsgCode ? matchedMhlUsgCode.text : (usgCdObj ? usgCdObj.text : item?.usgCd),
|
|
ctpvNm: ctpvNm ?? '-',
|
|
sggNm : sggNm ?? '-',
|
|
swtrmt_zone_nm: item.swtrmtZoneNm || item.swtrmt_zone_nm || '-',
|
|
};
|
|
});
|
|
|
|
setTableData(dataWithRowNumber);
|
|
setTableCount(res.data.count || []);
|
|
|
|
} else if (activeTab === 'operation') {
|
|
const RequestDTO: Record<string, string> = {
|
|
page: `${curPage - 1}`,
|
|
size: `${OPERATION_TABLE_SIZE}`,
|
|
};
|
|
if (var1) RequestDTO.bizInfoNm = var1;
|
|
if (var2 != '0' && var2) RequestDTO.bizTypeCd = var2;
|
|
// 수행기간 범위
|
|
const startDate = getDateString(
|
|
yearFilter.start,
|
|
'',
|
|
'',
|
|
"19000101",
|
|
);
|
|
const endDate = getDateString(
|
|
yearFilter.end,
|
|
'',
|
|
'',
|
|
`${todayYear}${todayMonth}${todayDate}`,
|
|
);
|
|
RequestDTO.fromflfmtEndYmd = startDate;
|
|
RequestDTO.toflfmtEndYmd = endDate;
|
|
|
|
// JSON.parse 사용으로 문자열 -> 배열 변환
|
|
RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"'));
|
|
|
|
const params = new URLSearchParams(RequestDTO).toString();
|
|
|
|
const res = await getData(`v1/bizInfo?${params}`);
|
|
|
|
const mappedContent = (res.content || []).map((item: any, index: number) => {
|
|
const formattedItem = formatDisplayData(item);
|
|
const matched = BIZ_TY_CD.find(code => code.lwpoCd === item.bizTypeCd);
|
|
return {
|
|
...formattedItem,
|
|
rowNumber: (curPage - 1) * OPERATION_TABLE_SIZE + index + 1, // 1부터 시작하는 일련번호 추가
|
|
bizTypeCd: matched ? matched.lwpoCdNm : item.bizTypeCd,
|
|
};
|
|
});
|
|
|
|
setTableData(mappedContent || []);
|
|
setTableCount(res.totalElements || 0);
|
|
setDetailTableData([]);
|
|
setDetailTableCount(0);
|
|
}
|
|
|
|
setShowTable(true);
|
|
setIsResetSelection(false);
|
|
} catch (err) {
|
|
console.error('API ERROR:', err);
|
|
setTableData([]);
|
|
setIsResetSelection(false);
|
|
} finally {
|
|
setIsLoading(false); // 로딩 종료
|
|
setIsResetSelection(false);
|
|
// setIsResetDetailSelection(false);
|
|
}
|
|
};
|
|
|
|
// 조회 버튼 클릭 시 1페이지로 이동 및 데이터 초기화
|
|
const handleSearch = () => {
|
|
setCurPage(1); // 페이지를 1로 초기화
|
|
fetchFilteredData();
|
|
setIsResetPage(true); // 페이지를 초기화
|
|
setIsResetDetailPage(true); // 디테일 페이지를 초기화
|
|
setIsResetSelection(false); // 선택 초기화
|
|
setIsResetDetailSelection(false); // 선택 초기화
|
|
setShowTable(true);
|
|
};
|
|
|
|
// 기본정보 테이블 cellClick 핸들러
|
|
const handleBasicCellClick = async (index?: number | undefined, headId?: String) => {
|
|
if (typeof index === "number") {
|
|
setIsLoading(true);
|
|
|
|
const row = tableData[index];
|
|
const layerNm = row.lyrTypeNm;
|
|
const fid = row.fid;
|
|
const core = GisApp.Module.layer as any;
|
|
await core.showSearchResultsFromGeoJSON(layerNm, fid);
|
|
setIsLoading(false);
|
|
onOpenChange(false); // SearchModal 닫기
|
|
}
|
|
};
|
|
// 운영정보 테이블 cellClick 핸들러
|
|
const handleOperationCellClick = async (index?: number | undefined, headId?: String) => {
|
|
setIsResetDetailPage(true); // 페이지를 1로 초기화
|
|
setIsResetDetailSelection(true); // 선택 초기화
|
|
setIsResetDetailPage(true); // 디테일 페이지를 초기화
|
|
|
|
if (typeof index === "number") {
|
|
setIsDetailLoading(true);
|
|
setDetailBizId(tableData[index].bizId);
|
|
setDetailCurPage(1); // 상세 페이지 초기화
|
|
try {
|
|
const RequestDTO: Record<string, string> = {
|
|
page: `${detailCurPage - 1}`,
|
|
size: `${OPERATION_TABLE_SIZE}`,
|
|
bizId: tableData[index % OPERATION_TABLE_SIZE].bizId,
|
|
};
|
|
|
|
RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"'));
|
|
|
|
const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`);
|
|
|
|
const mappedData = (res.data || []).map((item: any, detailIndex: number) => {
|
|
const formattedItem = formatDisplayData(item);
|
|
|
|
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim());
|
|
const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item?.mqltCd?.trim());
|
|
return {
|
|
...formattedItem,
|
|
rowNumber: (detailCurPage - 1) * OPERATION_TABLE_SIZE + detailIndex + 1,
|
|
usgCd: usgCdObj ? usgCdObj.text : item.usgCd,
|
|
mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd,
|
|
swtrmt_zone_nm: item.swtrmt_zone_nm ? item.swtrmt_zone_nm : '-',
|
|
};
|
|
});
|
|
|
|
setDetailTableData(mappedData);
|
|
setDetailTableCount(res.count || 0);
|
|
} catch (error) {
|
|
console.error('운영정보 cellClick 에러:', error);
|
|
} finally {
|
|
setIsDetailLoading(false);
|
|
setIsResetDetailPage(false);
|
|
setIsResetDetailSelection(false);
|
|
}
|
|
}
|
|
};
|
|
// 운영정보 디테일 테이블 페이지네이션 핸들러
|
|
const handleOperationPageNation = async (index?: number | undefined) => {
|
|
if (typeof index === "number") {
|
|
setIsDetailLoading(true);
|
|
try {
|
|
const RequestDTO: Record<string, string> = {
|
|
page: `${detailCurPage - 1}`,
|
|
size: `${OPERATION_TABLE_SIZE}`,
|
|
bizId: String(detailBizId),
|
|
};
|
|
const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`);
|
|
|
|
const mappedData = (res.data || []).map((item: any, detailIndex: number) => {
|
|
const formattedItem = formatDisplayData(item);
|
|
|
|
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim());
|
|
const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item?.mqltCd?.trim());
|
|
return {
|
|
...formattedItem,
|
|
rowNumber: (detailCurPage - 1) * OPERATION_TABLE_SIZE + detailIndex + 1,
|
|
usgCd: usgCdObj ? usgCdObj.text : item.usgCd,
|
|
mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd,
|
|
swtrmt_zone_nm: item.swtrmt_zone_nm ? item.swtrmt_zone_nm : '-',
|
|
};
|
|
});
|
|
|
|
setDetailTableData(mappedData);
|
|
setDetailTableCount(res.count || 0);
|
|
} catch (error) {
|
|
console.error('운영정보 페이지네이션 에러:', error);
|
|
} finally {
|
|
setIsDetailLoading(false);
|
|
}
|
|
}
|
|
};
|
|
|
|
const handleOperationResultCellClick = async (index?: number | undefined, headId?: String) => {
|
|
if (typeof index === "number") {
|
|
setIsLoading(true);
|
|
|
|
const row = detailTableData[index];
|
|
const layerNm = row.lyrTypeNm;
|
|
const fid = row.fid;
|
|
const core = GisApp.Module.layer as any;
|
|
await core.showSearchResultsFromGeoJSON(layerNm, fid);
|
|
setIsLoading(false);
|
|
onOpenChange(false); // SearchModal 닫기
|
|
}
|
|
};
|
|
|
|
// 기본정보 Excel 다운로드 핸들러
|
|
const basicExcelDownload = async () => {
|
|
if (tableData.length === 0) {
|
|
alert("다운로드 할 Excel 파일이 없습니다.\n조회 후 다시 시도해주세요.");
|
|
return;
|
|
}
|
|
|
|
toast.dismiss("global-confirm-toast");
|
|
|
|
confirmToast(
|
|
"파일 다운로드에는 2분 내외의 시간이 소요될 수 있습니다.\n파일 다운로드를 진행하시겠습니까?",
|
|
onAnalysis ?? (() => { }),
|
|
"text-xl font-medium text-gray-800"
|
|
);
|
|
|
|
async function onAnalysis() {
|
|
setIsLoading(true);
|
|
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
lyrTypeNm: basicType,
|
|
size: '10000',
|
|
});
|
|
|
|
let cqlFilters: string[] = [];
|
|
let headerMapping: { [key: string]: string } = {};
|
|
let headerRange: string = "A1:F1";
|
|
|
|
switch (basicType) {
|
|
case 'tb_ms_swage_ppl': {
|
|
// 하수관로
|
|
cqlFilters = swagePplCqlFilters({
|
|
var1, var2,
|
|
ctpvCd, sggCd,
|
|
yearFilter,
|
|
start1, start2, end1, end2,
|
|
todayYear, todayMonth, todayDate,
|
|
getDateString
|
|
})
|
|
headerMapping = MsSwagePplExcelCol;
|
|
headerRange = "A1:M1";
|
|
break;
|
|
}
|
|
case 'tb_il_swage_prcs_fclt': {
|
|
// 하수처리시설
|
|
cqlFilters = swagePrcsFcltCqlFilters({
|
|
ctpvName, sggName,
|
|
yearFilter,
|
|
start1, end1,
|
|
todayYear, todayMonth, todayDate,
|
|
getDateString
|
|
});
|
|
headerMapping = SwtrmtFcltExcelCol;
|
|
headerRange = "A1:J1";
|
|
break;
|
|
}
|
|
case 'tb_ms_swage_prcs_zone': {
|
|
// 하수처리구역
|
|
cqlFilters = swagePrcsZoneCqlFilters({
|
|
ctpvCd, sggCd,
|
|
var1, var2
|
|
});
|
|
headerMapping = SwtrmtPrcsZoneExcelCol;
|
|
headerRange = "A1:D1";
|
|
break;
|
|
}
|
|
case 'tb_ms_swage_mhl': {
|
|
// 하수맨홀
|
|
cqlFilters = swageMhlCqlFilters({
|
|
ctpvCd, sggCd,
|
|
yearFilter,
|
|
start1, end1,
|
|
var1,
|
|
todayYear, todayMonth, todayDate,
|
|
getDateString
|
|
});
|
|
headerMapping = MsSwageMhlExcelCol;
|
|
headerRange = "A1:J1";
|
|
break;
|
|
}
|
|
case 'tb_ms_swage_pmstn': {
|
|
// 하수펌프장
|
|
cqlFilters = swagePmstnCqlFilters({
|
|
ctpvCd, sggCd,
|
|
yearFilter,
|
|
start1, start2, end1, end2,
|
|
todayYear, todayMonth, todayDate,
|
|
getDateString
|
|
});
|
|
headerMapping = ExclnSewagePumpExcelCol;
|
|
headerRange = "A1:J1";
|
|
break;
|
|
}
|
|
case 'tb_ms_stofcbr': {
|
|
// 우수토실
|
|
cqlFilters = stofcbrCqlFilters({
|
|
ctpvCd, sggCd,
|
|
yearFilter,
|
|
todayYear, todayMonth, todayDate,
|
|
getDateString
|
|
});
|
|
headerMapping = stofcbrExcelCol;
|
|
headerRange = "A1:H1";
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (cqlFilters.length > 0) queryParams.append('cqlFiter', cqlFilters.join(' and '));
|
|
|
|
const res = await axios.get(`${API_URL}/v1/fclts?${queryParams.toString()}`);
|
|
|
|
|
|
|
|
|
|
// const mhlCdMap = new Map(MS_SWAGE_MHL_CODES.map(code => [code.val?.trim(), code.text]));
|
|
const mhlUsgCdMap = new Map(MS_SWAGE_MHL_USE_CODES.map(code => [code.val?.trim(), code.text]));
|
|
const pplUsgCdMap = new Map(MS_SWAGE_PPL_USE_CODES.map(code => [code.val?.trim(), code.text]));
|
|
const ctpvMap = new Map(ctpv.map(code => [code.val?.trim(), code.text]));
|
|
const sggMap = new Map(sgg.map(code => [code.val?.trim(), code.text]));
|
|
|
|
const mappedContent = (res.data.data || []).map((item: any) => {
|
|
const formattedItem = formatDisplayData(item);
|
|
|
|
let ctpvCd = item?.ctpvCd ?? formattedItem?.ctpvCd ?? '';
|
|
let sggCd = item?.sggCd ?? formattedItem?.sggCd ?? '';
|
|
|
|
if (!ctpvCd || !sggCd) {
|
|
const code = String(item?.pbadmsEmdCd ?? formattedItem?.pbadmsEmdCd ?? '')?.trim();
|
|
if (!ctpvCd && code) ctpvCd = code.slice(0, 2);
|
|
if (!sggCd && code) sggCd = code.slice(0, 5);
|
|
}
|
|
|
|
// trim 한 번만 수행
|
|
const trimmedUsgCd = item?.usgCd?.trim();
|
|
// const trimmedMqltCd = item?.mqltCd?.trim();
|
|
|
|
switch (basicType) {
|
|
case 'tb_ms_swage_ppl': {
|
|
// 하수관로
|
|
return {
|
|
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '-',
|
|
instMngNo: formattedItem.instMngNo ?? item.instMngNo ?? '-',
|
|
ctpvNm: ctpvMap.get(ctpvCd) ?? item.ctpvNm ?? '-',
|
|
sggNm: sggMap.get(sggCd) ?? item.sggNm ?? '-',
|
|
swtrmt_zone_nm: formattedItem.swtrmt_zone_nm ?? item.swtrmt_zone_nm ?? '-',
|
|
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '-',
|
|
usgCd: pplUsgCdMap.get(trimmedUsgCd) || item.usgCd || formattedItem.usgCd || '-',
|
|
pdmtVl: formattedItem.pdmtVl ?? item.pdmtVl ?? '-',
|
|
prlgVl: formattedItem.prlgVl ?? item.prlgVl ?? '-',
|
|
tmptDpth: formattedItem.tmptDpth ?? item.tmptDpth ?? '-',
|
|
tmptMhlMngNo: formattedItem.tmptMhlMngNo ?? item.tmptMhlMngNo ?? '-',
|
|
scendDpth: formattedItem.scendDpth ?? item.scendDpth ?? '-',
|
|
scendMhlMngNo: formattedItem.scendMhlMngNo ?? item.scendMhlMngNo ?? '-',
|
|
};
|
|
}
|
|
case 'tb_il_swage_prcs_fclt': {
|
|
// 하수처리시설
|
|
return {
|
|
swtrmtFcltNm: formattedItem.swtrmtFcltNm ?? item.swtrmtFcltNm ?? '-',
|
|
fcltCpct: formattedItem.fcltCpct ?? item.fcltCpct ?? '-',
|
|
rgnExpln: formattedItem.rgnExpln ?? item.rgnExpln ?? '-',
|
|
oprtngStrtYmd: formattedItem.oprtngStrtYmd ?? item.oprtngStrtYmd ?? '-',
|
|
laeNm: formattedItem.laeNm ?? item.laeNm ?? '-',
|
|
sareaNm: formattedItem.sareaNm ?? item.sareaNm ?? '-',
|
|
rvrNm: formattedItem.rvrNm ?? item.rvrNm ?? '-',
|
|
dschgWtstNm: formattedItem.dschgWtstNm ?? item.dschgWtstNm ?? '-',
|
|
swtrmtPpltnCnt: formattedItem.swtrmtPpltnCnt ?? item.swtrmtPpltnCnt ?? '-',
|
|
rprsMsrcCn: formattedItem.rprsMsrcCn ?? item.rprsMsrcCn ?? '-'
|
|
};
|
|
}
|
|
case 'tb_ms_swage_prcs_zone': {
|
|
// 하수처리구역
|
|
return {
|
|
swtrmtZoneNm: formattedItem.swtrmtZoneNm ?? item.swtrmtZoneNm ?? '-',
|
|
ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? '-',
|
|
sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? '-',
|
|
swtrmtFcltNm: formattedItem.swtrmtFcltNm ?? item.swtrmtFcltNm ?? '-'
|
|
};
|
|
}
|
|
case 'tb_ms_swage_mhl': {
|
|
// 하수맨홀
|
|
return {
|
|
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '-',
|
|
ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? '-',
|
|
sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? '-',
|
|
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '-',
|
|
usgCd: mhlUsgCdMap.get(trimmedUsgCd) || item.usgCd || formattedItem.usgCd || '-',
|
|
swageMhlDiamVl: formattedItem.swageMhlDiamVl ?? item.swageMhlDiamVl ?? '-',
|
|
wdthLen: formattedItem.wdthLen ?? item.wdthLen ?? '-',
|
|
vrtcLen: formattedItem.vrtcLen ?? item.vrtcLen ?? '-',
|
|
altdVl: formattedItem.altdVl ?? item.altdVl ?? '-',
|
|
dpthlVl: formattedItem.dpthlVl ?? item.dpthlVl ?? '-'
|
|
};
|
|
}
|
|
case 'tb_ms_swage_pmstn': {
|
|
// 하수펌프장
|
|
return {
|
|
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '-',
|
|
ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? '-',
|
|
sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? '-',
|
|
swagePmstnNm: formattedItem.swagePmstnNm ?? item.swagePmstnNm ?? '-',
|
|
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '-',
|
|
dailyPrcsCpct: formattedItem.dailyPrcsCpct ?? item.dailyPrcsCpct ?? '-',
|
|
maxImpndCpct: formattedItem.maxImpndCpct ?? item.maxImpndCpct ?? '-',
|
|
altdVl: formattedItem.altdVl ?? item.altdVl ?? '-',
|
|
wtlvVl: formattedItem.wtlvVl ?? item.wtlvVl ?? '-',
|
|
exclnWpmpAbltVl: formattedItem.exclnWpmpAbltVl ?? item.exclnWpmpAbltVl ?? '-'
|
|
};
|
|
}
|
|
case 'tb_ms_stofcbr': {
|
|
// 우수토실
|
|
return {
|
|
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '-',
|
|
mapshtNo: formattedItem.mapshtNo ?? item.mapshtNo ?? '-',
|
|
ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? '-',
|
|
sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? '-',
|
|
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '-',
|
|
worflwWallHgt: formattedItem.worflwWallHgt ?? item.worflwWallHgt ?? '-',
|
|
swageMhlMngNo: formattedItem.swageMhlMngNo ?? item.swageMhlMngNo ?? '-',
|
|
drtnAngl: formattedItem.drtnAngl ?? item.drtnAngl ?? '-'
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
// 선택된 행 데이터를 Excel 다운로드 형식으로 변환
|
|
const excelData = mappedContent; // 배열로 감싸서 전달
|
|
|
|
// 파일명 생성 (분석번호 기반)
|
|
const label = BASIC_TYPES.find((type) => type.val === basicType)?.text
|
|
const fileName = `${label} 조회 결과_${todayYear}${todayMonth}${todayDate}`;
|
|
|
|
await downloadExcelWithKoreanHeaders({
|
|
data: excelData as JSON[],
|
|
fileName: fileName,
|
|
sheetNameArray: [fileName],
|
|
headerRange: headerRange,
|
|
headerMapping: headerMapping
|
|
});
|
|
setIsLoading(false);
|
|
} catch (error) {
|
|
setIsLoading(false);
|
|
console.error("Excel 다운로드 중 오류 발생:", error);
|
|
alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요.");
|
|
}
|
|
}
|
|
};
|
|
|
|
// 운영정보 Excel 다운로드 핸들러 추가
|
|
const operationExcelDownload = async () => {
|
|
if (tableData.length === 0) {
|
|
alert("다운로드 할 Excel 파일이 없습니다.\n조회 후 다시 시도해주세요.");
|
|
return;
|
|
}
|
|
|
|
toast.dismiss("global-confirm-toast");
|
|
|
|
confirmToast(
|
|
"파일 다운로드에는 2분 내외의 시간이 소요될 수 있습니다.\n파일 다운로드를 진행하시겠습니까?",
|
|
onAnalysis ?? (() => { }),
|
|
"text-xl font-medium text-gray-800"
|
|
);
|
|
|
|
async function onAnalysis() {
|
|
setIsLoading(true);
|
|
|
|
try {
|
|
const RequestDTO: Record<string, string> = {
|
|
size: '10000',
|
|
};
|
|
if (var1) RequestDTO.bizInfoNm = var1;
|
|
if (var2 != '0' && var2) RequestDTO.bizTypeCd = var2;
|
|
// 수행기간 범위
|
|
const startDate = getDateString(
|
|
yearFilter.start,
|
|
'',
|
|
'',
|
|
"19000101",
|
|
);
|
|
const endDate = getDateString(
|
|
yearFilter.end,
|
|
'',
|
|
'',
|
|
`${todayYear}${todayMonth}${todayDate}`,
|
|
);
|
|
RequestDTO.fromflfmtEndYmd = startDate;
|
|
RequestDTO.toflfmtEndYmd = endDate;
|
|
|
|
// JSON.parse 사용으로 문자열 -> 배열 변환
|
|
RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"'));
|
|
|
|
const params = new URLSearchParams(RequestDTO).toString();
|
|
const res = await getData(`v1/bizInfo?${params}`);
|
|
|
|
// 헤더 매핑 정의
|
|
const headerMapping: { [key: string]: string } = {
|
|
'bizInfoNm': '사업명',
|
|
'flfmtBgngYmd': '수행시작일자',
|
|
'flfmtEndYmd': '수행종료일자',
|
|
'flfmtYr': '수행년도',
|
|
'bizTypeCd': '사업유형',
|
|
'bizAmt': '사업금액(원)',
|
|
};
|
|
|
|
const bizTyCdMap = new Map(BIZ_TY_CD.map(code => [code.lwpoCd, code.lwpoCdNm]));
|
|
|
|
const mappedContent = (res.content || []).map((item: any) => {
|
|
const formattedItem = formatDisplayData(item);
|
|
|
|
return {
|
|
bizInfoNm: formattedItem.bizInfoNm ?? item.bizInfoNm ?? '',
|
|
flfmtBgngYmd: formattedItem.flfmtBgngYmd ?? item.flfmtBgngYmd ?? '',
|
|
flfmtEndYmd: formattedItem.flfmtEndYmd ?? item.flfmtEndYmd ?? '',
|
|
flfmtYr: formattedItem.flfmtYr ?? item.flfmtYr ?? '',
|
|
bizTypeCd: bizTyCdMap.get(item.bizTypeCd) || item.bizTypeCd || formattedItem.bizTypeCd || '',
|
|
bizAmt: ((v) => (v === 0 || v === '0') ? '0' : (v ?? ''))(formattedItem.bizAmt ?? item.bizAmt),
|
|
};
|
|
});
|
|
|
|
// 선택된 행 데이터를 Excel 다운로드 형식으로 변환
|
|
const excelData = mappedContent; // 배열로 감싸서 전달
|
|
|
|
// 파일명 생성 (분석번호 기반)
|
|
const label = WORK_TYPES.find((type) => type.val === workType)?.text
|
|
const fileName = `${label} 사업 현황_${todayYear}${todayMonth}${todayDate}`;
|
|
|
|
await downloadExcelWithKoreanHeaders({
|
|
data: excelData as JSON[],
|
|
fileName: fileName,
|
|
sheetNameArray: [fileName],
|
|
headerRange: "A1:F1",
|
|
headerMapping: headerMapping
|
|
});
|
|
setIsLoading(false);
|
|
} catch (error) {
|
|
setIsLoading(false);
|
|
console.error("Excel 다운로드 중 오류 발생:", error);
|
|
alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요.");
|
|
}
|
|
}
|
|
};
|
|
|
|
// 운영정보 Excel 다운로드 핸들러 추가
|
|
const operationResultExcelDownload = async () => {
|
|
if (detailTableData.length === 0) {
|
|
alert("다운로드 할 Excel 파일이 없습니다.\n조회 후 다시 시도해주세요.");
|
|
return;
|
|
}
|
|
|
|
toast.dismiss("global-confirm-toast");
|
|
|
|
confirmToast(
|
|
"파일 다운로드에는 2분 내외의 시간이 소요될 수 있습니다.\n파일 다운로드를 진행하시겠습니까?",
|
|
onAnalysis ?? (() => { }),
|
|
"text-xl font-medium text-gray-800"
|
|
);
|
|
|
|
async function onAnalysis() {
|
|
|
|
setIsLoading(true);
|
|
|
|
try {
|
|
const RequestDTO: Record<string, string> = {
|
|
size: '10000',
|
|
bizId: String(detailBizId),
|
|
};
|
|
|
|
const apiStartTime = performance.now();
|
|
const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`);
|
|
const apiEndTime = performance.now();
|
|
|
|
const mappingStartTime = performance.now();
|
|
// 헤더 매핑 정의
|
|
const headerMapping: { [key: string]: string } = {
|
|
'fcltMngNo': '관리번호',
|
|
'swtrmt_zone_nm': '처리구역',
|
|
'usgCd': '용도',
|
|
'mqltCd': '재질',
|
|
'pdmtVl': '관경(mm)',
|
|
'prlgVl': '연장(m)',
|
|
'instlYmd': '설치일자',
|
|
'strc_stts_grd': '구조적 상태등급',
|
|
'oper_stts_grd': '운영적 상태등급',
|
|
};
|
|
|
|
const usgCdMap = new Map(MS_SWAGE_PPL_USE_CODES.map(code => [code.val, code.text]));
|
|
const mqltCdMap = new Map(MS_SWAGE_PPL_CODES.map(code => [code.val, code.text]));
|
|
|
|
// 🎯 단일 반복문으로 최적화 - 각 아이템마다 필요한 필드만 직접 매핑
|
|
const mappedData = (res.data || []).map((item: any) => {
|
|
const formattedItem = formatDisplayData(item);
|
|
|
|
// trim 한 번만 수행
|
|
const trimmedUsgCd = item?.usgCd?.trim();
|
|
const trimmedMqltCd = item?.mqltCd?.trim();
|
|
|
|
// zone 값 한 번만 계산
|
|
const zone = item.swtrmtZoneNm ?? formattedItem.swtrmt_zone_nm ?? item.swtrmt_zone_nm ?? '';
|
|
|
|
// 직접 매핑 - 반복문 없이 한 번에 객체 생성
|
|
return {
|
|
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '',
|
|
swtrmt_zone_nm: (zone === null || zone === '') ? '-' : zone,
|
|
usgCd: usgCdMap.get(trimmedUsgCd) || item.usgCd || formattedItem.usgCd || '',
|
|
mqltCd: mqltCdMap.get(trimmedMqltCd) || item.mqltCd || formattedItem.mqltCd || '',
|
|
pdmtVl: formattedItem.pdmtVl ?? item.pdmtVl ?? '',
|
|
prlgVl: formattedItem.prlgVl ?? item.prlgVl ?? '',
|
|
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '',
|
|
strc_stts_grd: ((v) => (v === 0 || v === '0') ? '0' : (v ?? ''))(formattedItem.strc_stts_grd ?? item.strc_stts_grd),
|
|
oper_stts_grd: ((v) => (v === 0 || v === '0') ? '0' : (v ?? ''))(formattedItem.oper_stts_grd ?? item.oper_stts_grd),
|
|
};
|
|
});
|
|
|
|
// 선택된 행 데이터를 Excel 다운로드 형식으로 변환
|
|
const excelData = mappedData; // 배열로 감싸서 전달
|
|
|
|
// 파일명 생성 (분석번호 기반)
|
|
const label = WORK_TYPES.find((type) => type.val === workType)?.text
|
|
const fileName = `${label} 결과표_${todayYear}${todayMonth}${todayDate}`;
|
|
|
|
await downloadExcelWithKoreanHeaders({
|
|
data: excelData as JSON[],
|
|
fileName: fileName,
|
|
sheetNameArray: [fileName],
|
|
headerRange: "A1:I1",
|
|
headerMapping: headerMapping
|
|
});
|
|
|
|
setIsLoading(false);
|
|
} catch (error) {
|
|
setIsLoading(false);
|
|
console.error("Excel 다운로드 중 오류 발생:", error);
|
|
alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요.");
|
|
}
|
|
}
|
|
};
|
|
|
|
// 여러 시설 보기
|
|
const viewMultipleFeature = async () => {
|
|
if (activeTab === 'basic') {
|
|
if (!(tableData.length === 0)) {
|
|
setIsLoading(true);
|
|
|
|
const row = tableData[0];
|
|
const layerNm = row.lyrTypeNm;
|
|
const fids = tableData.map((item) => item.fid);
|
|
const core = GisApp.Module.layer as any;
|
|
await core.showMultipleSearchResultsFromGeoJSON(layerNm, fids);
|
|
setIsLoading(false);
|
|
onOpenChange(false);
|
|
}
|
|
} else if (activeTab === 'operation') {
|
|
if (!(detailTableData.length === 0)) {
|
|
setIsLoading(true);
|
|
|
|
const row = detailTableData[0];
|
|
const layerNm = row.lyrTypeNm;
|
|
const fids = detailTableData.map((item) => item.fid);
|
|
const core = GisApp.Module.layer as any;
|
|
await core.showMultipleSearchResultsFromGeoJSON(layerNm, fids);
|
|
setIsLoading(false);
|
|
onOpenChange(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
open, onOpenChange, onFeatureSelect,
|
|
TABS,
|
|
getDateString,
|
|
handleSearch,
|
|
handleBasicCellClick,
|
|
handleOperationCellClick,
|
|
handleOperationPageNation,
|
|
handleOperationResultCellClick,
|
|
basicExcelDownload,
|
|
operationExcelDownload,
|
|
operationResultExcelDownload,
|
|
viewMultipleFeature,
|
|
};
|
|
};
|