Merge branch 'iipbs/sn/dev'

This commit is contained in:
dongsilove
2026-02-10 23:08:10 +09:00
7 changed files with 174 additions and 36 deletions
@@ -7,7 +7,7 @@
"use client"
import { useFoStore } from "@/app/store";
import {
ContentsDiv, downloadExcel, downloadMultipleExcel, filePickedBlobArray, MainDiv
ContentsDiv, downloadExcelFormat, downloadMultipleExcel, filePickedBlobArrayFormat, MainDiv
, SelectBox, UITab, type SelectDataType
} from "@common/business_components";
import { Button, TabsContent } from "@common/components/ui";
@@ -142,13 +142,11 @@ export default function DashBoard() {
}
}
const excelDownload = () => {
const excelDownload = async () => {
if (!fcltyList.bscFctCd) return;
switch (activeTab) {
case 'facilityInfo': // 시설정보 및 운영현황
searchOperationStatus(false, searchYear, fcltyList.bscFctCd).then(() => { setTimeout(() => { makeExcelData(); }, 200); });
const makeExcelData = async () => {
fetch(`/mainDashBoard.xlsx`, {}).then(async (response) => {
if (!response.ok) {
@@ -198,20 +196,27 @@ export default function DashBoard() {
headerNum: 3,
headerRange: 'A1:G2',
sheetName: '운영실태',
startCol: 'A'
startCol: 'A',
decimalRange0: 'B3:G2,B9:B11',
decimalRange1: 'B5:G5',
},
{
data: excelData2,
headerNum: 4,
headerRange: 'A1:Q3',
sheetName: '운영실태',
startCol: 'C'
startCol: 'C',
decimalRange0: 'C4:O8',
decimalRange1: 'C9:L10,M11:O11',
decimalRange3: 'C11:L16',
}
];
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
await filePickedBlobArray(blobRet, '시설정보및운영현황', sheetParameter);
await filePickedBlobArrayFormat(blobRet, '시설정보및운영현황', sheetParameter);
});
};
await searchOperationStatus(false, searchYear, fcltyList.bscFctCd);
await makeExcelData();
break;
case 'mainGraph': // 주요그래프
@@ -262,7 +267,15 @@ export default function DashBoard() {
case 'rainManage': // 강우일 운영현황
searchRainManage(searchYear, fcltyList.bscFctCd, true);
if (excelList && excelList.length > 0) {
downloadExcel({ data: excelList as unknown as JSON[], fileName: '강우일 운영현황', sheetNameArray: ['강우일 운영현황'], headerRange: 'A1:T1' });
downloadExcelFormat({
data: excelList as unknown as JSON[],
fileName: '강우일 운영현황',
sheetNameArray: ['강우일 운영현황'],
headerRange: 'A1:T1',
decimalArray0: [2,3],
decimalArray1: [1,4,5,6,7,10,11,12,15,16,17],
decimalArray3: [8,9,13,14,18,19],
});
}
break;
// Add other cases for different tabs as needed
@@ -394,7 +394,7 @@ export default function WaterQualityModal({ fcltyName = '', facilityCd = '', sea
"유입BOD(mg/L)": CommaToNumber(item.tpInflWqltBod),
"유입TP(mg/L)": CommaToNumber(item.tpInflWqltTp),
"유출BOD(mg/L)": CommaToNumber(item.efflWqltBod),
"유출TP(mg/L)": CommaToNumber(item.efflWqltTn),
"유출TP(mg/L)": CommaToNumber(item.efflWqltTp),
});
});
}
@@ -9,7 +9,7 @@ import FacilityTermModalHeader from "@/app/components/common/FacilityTermModalHe
import { useFoStore } from "@/app/store";
import type { FlowRateModalInterface, modalExcelType } from "@/app/store/flowRate";
import { dataFormSetting } from "@/app/store/flowRate";
import { downloadExcel, UITab, UiTable } from "@common/business_components/ui";
import { downloadExcelFormat, UITab, UiTable } from "@common/business_components/ui";
import { Button, TabsContent } from "@common/components/ui";
import { useCallback, useEffect, useRef, useState } from "react";
import type { ReturnType } from "../../../../components/common/FacilityTermModalHeader";
@@ -201,7 +201,14 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
});
}
if (excelDownList && excelDownList.length > 0) {
downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.searchYear + '년 ' + props.fcltyName + ' 유량현황', sheetNameArray: [props.fcltyName + ' 유량현황'], headerRange: 'A1:H1' });
downloadExcelFormat({
data: JSON.parse(JSON.stringify(excelDownList)),
fileName: props.searchYear + '년 ' + props.fcltyName + ' 유량현황',
sheetNameArray: [props.fcltyName + ' 유량현황'],
headerRange: 'A1:H1',
decimalArray0: [1, 2, 3, 4, 5, 6],
decimalArray1: [0],
});
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
alert('조회된 결과가 없습니다.');
}
@@ -160,11 +160,8 @@ export default function ProcessArea() {
fileName: '처리구역정보',
sheetNameArray: ['처리구역정보'],
headerRange: 'A1:W1',
decimalArray0: [
3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15,
17, 18, 19, 20, 21
]
decimalArray0: [3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15],
decimalArray2: [16, 17, 18, 19, 20, 21],
});
} else {
alert('조회된 결과가 없습니다.');
@@ -206,7 +206,7 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
const sheetParameter = [
{
data: excelData,
headerNum: 2,
headerNum: 3,
headerRange: 'A1:S2',
sheetName: '시설 수질정보',
startCol: 'A'
+8 -12
View File
@@ -190,12 +190,10 @@ export const chRowspanTable = (
value={formatCommaNumber(value) || ""}
disabled={!selectedIds.includes(row.chkgdnSn)}
maxLength={numSize}
onInput={(e: React.ChangeEvent<HTMLInputElement>) => {
if (
head.type === "number" &&
e.target.value.length > numSize
) {
e.target.value = e.target.value.slice(0, numSize);
onInput={(e: React.FormEvent<HTMLInputElement>) => {
const el = e.currentTarget;
if (head.type === "number" && el.value.length > numSize) {
el.value = el.value.slice(0, numSize);
}
}}
/>
@@ -225,12 +223,10 @@ export const chRowspanTable = (
value={value || ""}
disabled={!selectedIds.includes(row.chkgdnSn)}
maxLength={numSize}
onInput={(e: React.ChangeEvent<HTMLInputElement>) => {
if (
head.type === "number" &&
e.target.value.length > numSize
) {
e.target.value = e.target.value.slice(0, numSize);
onInput={(e: React.FormEvent<HTMLInputElement>) => {
const el = e.currentTarget;
if (head.type === "number" && el.value.length > numSize) {
el.value = el.value.slice(0, numSize);
}
}}
/>
@@ -11,6 +11,10 @@ type ExcelDownloadProps = {
decimalArray1? : number[];
decimalArray2? : number[];
decimalArray3? : number[];
decimalRange0?: string;
decimalRange1?: string;
decimalRange2?: string;
decimalRange3?: string;
}
export const downloadExcel = ({ data, fileName = new Date().getTime().toString() + '.xlsx', sheetNameArray = ["Sheet1"], headerRange='A1:V3'}: ExcelDownloadProps) => {
@@ -29,7 +33,20 @@ export const downloadExcelHeaders = ({ data, fileName = new Date().getTime().toS
excelStyle(XLSX.write(workbook, { bookType: "xlsx", type: "buffer" }), headerRange, fileName);
};
export const downloadExcelFormat = ({ data, fileName = new Date().getTime().toString() + '.xlsx', sheetNameArray = ["Sheet1"], headerRange='A1:V3', decimalArray0=[], decimalArray1=[], decimalArray2=[], decimalArray3=[]}: ExcelDownloadProps) => {
export const downloadExcelFormat = ({
data,
fileName = new Date().getTime().toString() + '.xlsx',
sheetNameArray = ["Sheet1"],
headerRange = 'A1:V3',
decimalArray0 = [],
decimalArray1 = [],
decimalArray2 = [],
decimalArray3 = [],
decimalRange0,
decimalRange1,
decimalRange2,
decimalRange3,
}: ExcelDownloadProps) => {
const worksheet = XLSX.utils.json_to_sheet(Array.isArray(data) ? data : [data]);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, sheetNameArray[0]);
@@ -61,10 +78,35 @@ export const downloadExcelFormat = ({ data, fileName = new Date().getTime().toSt
}
}
};
const applyRangeFormat = (rangeStr: string | undefined, decimal: number) => {
if (!rangeStr) return;
const rangeInfo = XLSX.utils.decode_range(rangeStr);
for (let row = rangeInfo.s.r; row <= rangeInfo.e.r; row++) {
for (let col = rangeInfo.s.c; col <= rangeInfo.e.c; col++) {
const cellAddr = XLSX.utils.encode_cell({ r: row, c: col });
const cell = worksheet[cellAddr];
if (cell && typeof cell.v === "number") {
if (decimal === 1) {
cell.z = "#,##0.0";
} else if (decimal === 2) {
cell.z = "#,##0.00";
} else if (decimal === 3) {
cell.z = "#,##0.000";
} else {
cell.z = "#,##0";
}
}
}
}
};
chaneValue(decimalArray0, 0);
chaneValue(decimalArray1, 1);
chaneValue(decimalArray2, 2);
chaneValue(decimalArray3, 3);
applyRangeFormat(decimalRange0, 0);
applyRangeFormat(decimalRange1, 1);
applyRangeFormat(decimalRange2, 2);
applyRangeFormat(decimalRange3, 3);
excelStyle(XLSX.write(workbook, { bookType: "xlsx", type: "buffer" }), headerRange, fileName);
};
@@ -74,6 +116,10 @@ export type SheetParameter = {
headerRange: string;
sheetName: string;
startCol?: string;
decimalRange0?: string;
decimalRange1?: string;
decimalRange2?: string;
decimalRange3?: string;
};
export const downloadMultipleExcel = (fileName = new Date().getTime().toString() + '.xlsx', sheetArray: SheetParameter[]): Promise<JSON | undefined> => {
@@ -201,9 +247,29 @@ export const filePickedBlob=(oFile: ArrayBuffer, data:[][],fileNm:string, header
});
}
export const filePickedBlobArray = (oFile: ArrayBuffer, fileNm: string, sheetArray: SheetParameter[]): Promise<JSON | undefined> => {
return new Promise<JSON | undefined>(async () => {
const wb = XLSX.read(oFile, { type: 'binary' });
// export const filePickedBlobArray = (oFile: ArrayBuffer, fileNm: string, sheetArray: SheetParameter[]): Promise<JSON | undefined> => {
// return new Promise<JSON | undefined>(async () => {
// const wb = XLSX.read(oFile, { type: 'binary' });
// wb.SheetNames.forEach(function (sheetName, index) {
// if (sheetArray[index]) {
// const sheet = wb.Sheets[sheetName];
// if (sheet) {
// const startCol = sheetArray[index].startCol ? sheetArray[index].startCol : 'A';
// XLSX.utils.sheet_add_aoa(sheet, sheetArray[index].data, { origin: startCol + sheetArray[index].headerNum });
// } else {
// console.error(`Sheet "${sheetName}" is undefined.`);
// }
// }
// });
// await excelArrayStyle(XLSX.write(wb, { bookType: "xlsx", type: "buffer" }), sheetArray, fileNm)
// });
// }
export const filePickedBlobArray = async (
oFile: ArrayBuffer,
fileNm: string,
sheetArray: SheetParameter[]
): Promise<JSON | undefined> => {
const wb = XLSX.read(oFile, { type: 'binary' });
wb.SheetNames.forEach(function (sheetName, index) {
if (sheetArray[index]) {
const sheet = wb.Sheets[sheetName];
@@ -215,9 +281,68 @@ export const filePickedBlobArray = (oFile: ArrayBuffer, fileNm: string, sheetArr
}
}
});
await excelArrayStyle(XLSX.write(wb, { bookType: "xlsx", type: "buffer" }), sheetArray, fileNm)
await excelArrayStyle(XLSX.write(wb, { bookType: "xlsx", type: "buffer" }), sheetArray, fileNm);
return undefined;
};
export const filePickedBlobArrayFormat = async (
oFile: ArrayBuffer,
fileNm: string,
sheetArray: SheetParameter[]
): Promise<JSON | undefined> => {
const wb = XLSX.read(oFile, { type: "binary" });
wb.SheetNames.forEach((sheetName, index) => {
if (sheetArray[index]) {
const sheet = wb.Sheets[sheetName];
if (sheet) {
const startCol = sheetArray[index].startCol ?? "A";
XLSX.utils.sheet_add_aoa(sheet, sheetArray[index].data, {
origin: startCol + sheetArray[index].headerNum,
});
const applyRangeFormat = (rangeStr: string | undefined, decimal: number) => {
if (!rangeStr) return;
const parts = rangeStr.split(",").map((part) => part.trim()).filter(Boolean);
for (const part of parts) {
const rangeInfo = XLSX.utils.decode_range(part);
for (let row = rangeInfo.s.r; row <= rangeInfo.e.r; row++) {
for (let col = rangeInfo.s.c; col <= rangeInfo.e.c; col++) {
const cellAddr = XLSX.utils.encode_cell({ r: row, c: col });
const cell = sheet[cellAddr];
if (cell && typeof cell.v === "number") {
if (decimal === 1) {
cell.z = "#,##0.0";
} else if (decimal === 2) {
cell.z = "#,##0.00";
} else if (decimal === 3) {
cell.z = "#,##0.000";
} else {
cell.z = "#,##0";
}
}
}
}
}
};
applyRangeFormat(sheetArray[index].decimalRange0, 0);
applyRangeFormat(sheetArray[index].decimalRange1, 1);
applyRangeFormat(sheetArray[index].decimalRange2, 2);
applyRangeFormat(sheetArray[index].decimalRange3, 3);
} else {
console.error(`Sheet "${sheetName}" is undefined.`);
}
}
});
}
await excelArrayStyle(
XLSX.write(wb, { bookType: "xlsx", type: "buffer" }),
sheetArray,
fileNm
);
return undefined;
};
type ExcelDownloadWithHeaderProps = {
data: JSON | JSON[];
@@ -251,4 +376,4 @@ export const downloadExcelWithKoreanHeaders = async ({
// 3. 헤더만 한글로 교체하는 커스텀 스타일 함수 호출
await excelStyleWithKoreanHeaders(buffer, headerRange, fileName, headerMapping, dataArray[0]);
};
};