fo: 강우시 강우일의 강우량에 음영

This commit is contained in:
2026-01-30 16:22:51 +09:00
parent 39fb1d974a
commit 164fc1388e
5 changed files with 104 additions and 70 deletions
@@ -30,18 +30,18 @@ export default function CalcRainEffect(data: any, weather = 'ALL') {
rtnDataSunny.push(item);
} else if (rainEffectStd >= 0) { // 강우일 + 강우영향일
item.rainEffectDay = 1;
if (idx > 1) {
// 전날 비가 왔고 오늘 강우량 3미만인 경우 전날 강우량이 3이상이면 오늘 toBeInfoRnDay을 전날 강우량으로 설정
if (data[idx - 1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx - 1]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.toBeInfoRnDay = data[idx - 1]!.infoRnDay;
}
}
if (idx > 2) {
// 전전날 비가 왔고 오늘 강우량 3미만인 경우 전전날 강우량이 3이상이면 오늘 toBeInfoRnDay을 전전날 강우량으로 설정
if (data[idx - 2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx - 2]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.toBeInfoRnDay = data[idx - 2]!.infoRnDay;
}
}
if (idx > 1) {
// 전날 비가 왔고 오늘 강우량 3미만인 경우 전날 강우량이 3이상이면 오늘 toBeInfoRnDay을 전날 강우량으로 설정
if (data[idx - 1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx - 1]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.toBeInfoRnDay = data[idx - 1]!.infoRnDay;
}
}
rtnDataRain.push(item);
}
@@ -34,6 +34,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
const { btnClass } = Common;
const [copyYearList, setCopyYearList] = useState<FlowRateModalInterface[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [activeTab, setActiveTab] = useState<string>("tab_term_year");
const prevExcelListRef = useRef<modalExcelType[] | null>(null);
const { modalFlowRateListYear, upHeadListFlowRateModalYear, } = FlowRateModal;
@@ -183,10 +184,6 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
fetchData();
}, [props.facilityCd, props.searchYear, searchFlowRateModalList]);
if (isLoading) {
return <div>로딩 중...</div>;
}
const excelDownload = () => {
const excelDownList: modalExcelType[] = [];
if (copyYearList.length > 0) {
@@ -206,14 +203,32 @@ 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' });
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
alert('다운받을 데이터가 없습니다.');
alert('조회된 결과가 없습니다.');
}
prevExcelListRef.current = excelDownList;
}
const rainCellClassName = useCallback(
(row: FlowRateModalInterface, headId: string, rowIndex: number) => {
if (activeTab !== "tab_term_rain") return "";
if (headId !== "infoRnDay") return "";
if (rowIndex < 3) return "";
const raw = row.infoRnDay;
const value = typeof raw === "string" ? Number(raw.replace(/,/g, "").trim()) : Number(raw);
if (!Number.isFinite(value)) return "";
return value > 3 ? "bg-red-50 font-semibold" : "";
},
[activeTab],
);
if (isLoading) {
return <div>로딩 중...</div>;
}
return (
<>
<UITab tabList={tabList} defaultValue="tab_term_year">
<UITab tabList={tabList} defaultValue="tab_term_year" onValueChange={setActiveTab}>
<Button className={btnClass} style={{ float: 'right' }} color="green" onClick={excelDownload}>
{"엑셀다운로드"}
</Button>
@@ -337,7 +352,8 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
/>
<div className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable headName="유량현황" tableData={copyYearList} headlist={upHeadListFlowRateModalYear} pageSize={0} total={0}
cellClick={undefined} onPageChange={() => { }} className="h-[370px]" boldArray={[0, 1, 2]} />
cellClick={undefined} onPageChange={() => { }} className="h-[370px]" boldArray={[0, 1, 2]}
cellClassName={rainCellClassName} />
</div>
<div className="mt-20">
<UnderComment commentArray={["미처리하수 추정량 산식 =[(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]/강우시 일별유입BOD)", "강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날"]} />
@@ -346,4 +362,4 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
</UITab>
</>
);
}
}
+15 -13
View File
@@ -28,9 +28,11 @@ export interface FacilityRdiiDetailProps {
export interface FacilityWaterQltyProps {
bscFctCd: string,
bscFctNm: string,
msrDt: string
sidoNm: string,
sggNm: string,
msrDt: string,
sido: string,
gugun: string,
// sidoNm: string,
// sggNm: string,
addr: string,
fctCpc: number,
inflAssctBfrWqltBod: string | '',
@@ -147,8 +149,8 @@ const mainLabelArray: string[] = ['구분', '시도', '시군구', '용량별',
// 시설수질리스트 헤더(행정별)
const upHeadList1: TableUpperProps[] = [
{ id: "C", title: "행정명", colSpan: 2, row: 0, widthPercent: 10 },
{ id: "sidoNm", title: "시도", row: 1, widthPercent: 5 },
{ id: "sggNm", title: "시군구", row: 1, widthPercent: 5 },
{ id: "sido", title: "시도", row: 1, widthPercent: 5 },
{ id: "gugun", title: "시군구", row: 1, widthPercent: 5 },
{ id: "bscFctNm", title: "시설명", rowSpan: 2, row: 0, widthPercent: 10 },
{ id: "addr", title: "주소", rowSpan: 2, row: 0 },
{ id: "fctCpc", title: "시설용량(m³/일)", align: "right", rowSpan: 2, row: 0, widthPercent: 10 },
@@ -197,8 +199,8 @@ const upHeadList3: TableUpperProps[] = [
{ id: "mdmbsn", title: "중권역", row: 1, widthPercent: 5 },
{ id: "rgnNm", title: "환경청", row: 0, rowSpan: 2, widthPercent: 7 },
{ id: "D", title: "행정명", colSpan: 2, row: 0, widthPercent: 10 },
{ id: "sidoNm", title: "시도", upName: "upChangeRe2", row: 1, widthPercent: 5 },
{ id: "sggNm", title: "시군구", upName: "upChangeRe2", row: 1, widthPercent: 5 },
{ id: "sido", title: "시도", upName: "upChangeRe2", row: 1, widthPercent: 5 },
{ id: "gugun", title: "시군구", upName: "upChangeRe2", row: 1, widthPercent: 5 },
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 8 },
{ id: "addr", title: "주소", row: 0, rowSpan: 2 },
{ id: "fctCpc", title: "시설용량(m³/L)", align: "right", row: 0, rowSpan: 2, widthPercent: 5 },
@@ -533,8 +535,8 @@ export const facilityWaterQltyReducer = (set: SetFunc): FacilityWaterQltyActions
waterQltyList.forEach(item => {
dataFormSetting(item)
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
// item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
// item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
item.inflAssctBfrWqltToc = Number(searchYear) < COD_YEAR ? "(" + item.inflAssctBfrWqltToc + ")" : item.inflAssctBfrWqltToc;
item.efflWqltToc = Number(searchYear) < COD_YEAR ? "(" + item.efflWqltToc + ")" : item.efflWqltToc;
excelDownList.push({
@@ -543,8 +545,8 @@ export const facilityWaterQltyReducer = (set: SetFunc): FacilityWaterQltyActions
단위유역: item.lgbsn,
중권역: item.mdmbsn,
환경청: item.rgnNm,
시도: item.sidoNm,
시군구: item.sggNm,
시도: item.sido,
시군구: item.gugun,
시설이름: item.bscFctNm,
주소: item.addr,
"시설용량(m³/일)": CommaToNumber(item.fctCpc),
@@ -565,8 +567,8 @@ export const facilityWaterQltyReducer = (set: SetFunc): FacilityWaterQltyActions
waterQltyList.forEach((item: FacilityWaterQltyProps) => {
dataFormSetting(item)
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
// item.sidoNm = item.;
// item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
item.inflAssctBfrWqltToc = Number(searchYear) < COD_YEAR ? "(" + item.inflAssctBfrWqltToc + ")" : item.inflAssctBfrWqltToc;
item.efflWqltToc = Number(searchYear) < COD_YEAR ? "(" + item.efflWqltToc + ")" : item.efflWqltToc;
});
+9 -1
View File
@@ -317,6 +317,14 @@ export type UnderWaterStore = UnderWaterType & UnderWaterActions;
export const underWaterReducer: (set: (fn: (state: UnderWaterType) => UnderWaterType) => void) => UnderWaterActions = (set: (fn: (state: UnderWaterType) => UnderWaterType) => void) => {
return {
searchUnderWaterList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
set((state: UnderWaterType) => ({
...state,
UnderWater: {
...state.UnderWater,
isLoading: true,
},
}));
const facilityInitData = await fetchFacilityListInit(pageNo, pageSize, part, nameCd, fcltCpct, operationValue, fcltyNm);
if (pageSize < 5000) {
@@ -724,4 +732,4 @@ export const underWaterReducer: (set: (fn: (state: UnderWaterType) => UnderWater
}))
}
}
}
}
@@ -16,14 +16,15 @@ export type ChkClass = {
chk: boolean;
readonly: boolean;
};
type UiTableProps = {
type UiTableProps<T extends object> = {
headName: React.ReactNode | undefined;
tableData: { [key: string]: any }[];
tableData: T[];
headlist: UiHeadProps[];
pageSize: number;
total: number;
cellClick: ((index: number | undefined, headId: string) => void) | undefined;
onPageChange: (page: number) => void;
cellClassName?: (row: T, headId: string, rowIndex: number) => string;
className?: string;
resetPageNo?: boolean;
children?: React.ReactNode | undefined;
@@ -46,7 +47,7 @@ type UiHeadProps = {
colSpan?: number;
};
export function UiTable({
export function UiTable<T extends object = Record<string, unknown>>({
tableData,
headlist,
pageSize,
@@ -55,6 +56,7 @@ export function UiTable({
children,
cellClick,
onPageChange,
cellClassName,
className = "",
resetPageNo = false,
boldArray = [],
@@ -63,7 +65,7 @@ export function UiTable({
curPage = 1,
headButton = undefined,
widthFixed = false
}: UiTableProps) {
}: UiTableProps<T>) {
const [cur, setCur] = useState<number>(curPage);
const [idx, setIdx] = useState<number>(index);
const [headerHeight, setHeaderHeight] = useState<number>(0);
@@ -148,7 +150,7 @@ export function UiTable({
</TableHeader>
<TableBody className="text-center">
{tableData.length > 0 ? (
tableData?.map((el: Record<string, unknown>, index) => (
tableData?.map((el: T, index) => (
<TableRow key={`row-${index}`}>
{headlist
.filter((item) => item.visible != false)
@@ -163,29 +165,32 @@ export function UiTable({
: cellClick
? "cursor-pointer"
: ""
} sticky top-20 z-40 bg-secondary !font-bold whitespace-pre-line`}
} ${cellClassName ? cellClassName(el, head.id, index) : ""} sticky top-20 z-40 bg-secondary !font-bold whitespace-pre-line`}
style={{ top: `${headerHeight + index * 32 - 4}px` }}
onClick={() => handleCellClick(index, head.id)}
key={`cell-${head.id}-${index}`}
>
{typeof el[head.id] !== "number"
? String(el[head.id] ?? "")
: String(el[head.id]).includes(".")
? String(el[head.id])
.split(".")
.map((part, index) =>
index === 0
? part.replace(
/\B(?=(\d{3})+(?!\d))/g,
",",
)
: part,
)
.join(".")
: String(el[head.id] ?? "").replace(
/\B(?=(\d{3})+(?!\d))/g,
",",
)}
{(() => {
const cellValue = (el as Record<string, unknown>)[head.id];
return typeof cellValue !== "number"
? String(cellValue ?? "")
: String(cellValue).includes(".")
? String(cellValue)
.split(".")
.map((part, index) =>
index === 0
? part.replace(
/\B(?=(\d{3})+(?!\d))/g,
",",
)
: part,
)
.join(".")
: String(cellValue ?? "").replace(
/\B(?=(\d{3})+(?!\d))/g,
",",
);
})()}
</TableCell>
) : (
<TableCell
@@ -194,47 +199,49 @@ export function UiTable({
: cellClick
? "cursor-pointer"
: ""
} mt-[${boldArray.length * 40}px] whitespace-pre-line`}
} ${cellClassName ? cellClassName(el, head.id, index) : ""} mt-[${boldArray.length * 40}px] whitespace-pre-line`}
onClick={() => handleCellClick(index, head.id)}
key={`cell-${head.id}-${index}`}
>
{
//체크박스 유형애서 readOnly가 필요한 경우를 위해서 ChkClass 를 사용해서 readOnly 처리함.
typeof el[head.id] === "object" &&
el[head.id] !== null &&
"chk" in (el[head.id] as object) &&
"readonly" in (el[head.id] as object) ? (
(() => {
const cellValue = (el as Record<string, unknown>)[head.id];
return typeof cellValue === "object" &&
cellValue !== null &&
"chk" in (cellValue as object) &&
"readonly" in (cellValue as object) ? (
<Checkbox
checked={
(el[head.id] as ChkClass)?.chk === true
(cellValue as ChkClass)?.chk === true
}
onCheckedChange={(checked) => {
{
console.log(el[head.id]);
console.log(cellValue);
}
if (
(el[head.id] as ChkClass).readonly == true
(cellValue as ChkClass).readonly == true
)
return;
(el[head.id] as ChkClass).chk =
(cellValue as ChkClass).chk =
Boolean(checked);
}}
>
<Check className="h-6 w-6 text-primary" />
</Checkbox>
) : typeof el[head.id] === "boolean" ? (
) : typeof cellValue === "boolean" ? (
<Checkbox
checked={el[head.id] === true}
checked={cellValue === true}
onCheckedChange={(checked) => {
el[head.id] = checked;
(el as Record<string, unknown>)[head.id] = checked;
}}
>
<Check className="h-6 w-6 text-primary" />
</Checkbox>
) : typeof el[head.id] !== "number" ? (
String(el[head.id] ?? "")
) : String(el[head.id]).includes(".") ? (
String(el[head.id])
) : typeof cellValue !== "number" ? (
String(cellValue ?? "")
) : String(cellValue).includes(".") ? (
String(cellValue)
.split(".")
.map((part, index) =>
index === 0
@@ -246,11 +253,12 @@ export function UiTable({
)
.join(".")
) : (
String(el[head.id] ?? "").replace(
String(cellValue ?? "").replace(
/\B(?=(\d{3})+(?!\d))/g,
",",
)
)
);
})()
}
</TableCell>
)),