Compare commits
160
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
738b1f7735 | ||
|
|
b64ba3b343 | ||
|
|
3381e16573 | ||
|
|
b73490ebc1 | ||
|
|
662e44b19a | ||
|
|
d12cae1e65 | ||
|
|
f002c05292 | ||
|
|
e41dd0539a | ||
|
|
bf1c2a3300 | ||
|
|
e6ddcfca57 | ||
|
|
aa4dc99f30 | ||
|
|
a3daa72bc8 | ||
|
|
1a9ec5450c | ||
|
|
1b57670830 | ||
|
|
3fbf9d0850 | ||
|
|
375397de2e | ||
|
|
960227d8dd | ||
|
|
00a8165476 | ||
|
|
8d68fe652a | ||
|
|
7f1f1933b5 | ||
|
|
c6d7564eb9 | ||
|
|
c72fa450bc | ||
|
|
5952760b05 | ||
|
|
6c022cd1ec | ||
|
|
c853163d99 | ||
|
|
1b2da753a1 | ||
|
|
400d6cf732 | ||
|
|
0929fe0674 | ||
|
|
c54381ae71 | ||
|
|
0a2284138c | ||
|
|
536f07a13f | ||
|
|
bf3ced7a00 | ||
|
|
0d9ebcbd55 | ||
|
|
46b1482e01 | ||
|
|
64e5c4c0fb | ||
|
|
29e8223efa | ||
|
|
d12610db98 | ||
|
|
824ad72dfe | ||
|
|
ab0d787615 | ||
|
|
39e2734a49 | ||
|
|
bc016c71ae | ||
|
|
1c24065c6e | ||
|
|
0995e6e43b | ||
|
|
cbc83207df | ||
|
|
4610f671b1 | ||
|
|
884af91733 | ||
|
|
baa7e71ba6 | ||
|
|
b4e72a02e4 | ||
|
|
cee4073cf2 | ||
|
|
ac29217256 | ||
|
|
77b4ba01b4 | ||
|
|
8e8c18c1fc | ||
|
|
6c5cd9d1e0 | ||
|
|
9c36553e77 | ||
|
|
eac09bde2e | ||
|
|
ebd2a9f2c8 | ||
|
|
41b90bd7b5 | ||
|
|
6844db4c29 | ||
|
|
311ce14fc9 | ||
|
|
3c5d37cc6c | ||
|
|
adacc5fe33 | ||
|
|
52b380a088 | ||
|
|
d92d4d3949 | ||
|
|
68ee60e252 | ||
|
|
858a2c0bac | ||
|
|
0bc87e2082 | ||
|
|
5588eddbc5 | ||
|
|
682cc1297c | ||
|
|
e26d800449 | ||
|
|
e6be168d0d | ||
|
|
ad6e4484b7 | ||
|
|
92f12c2104 | ||
|
|
c17da82661 | ||
|
|
75d2d0c827 | ||
|
|
675a1a09fa | ||
|
|
372843a083 | ||
|
|
b93efa5503 | ||
|
|
32939d8b1a | ||
|
|
00b0832acb | ||
|
|
6e109e970e | ||
|
|
8b2efad803 | ||
|
|
00ecc1dc72 | ||
|
|
328787e1b2 | ||
|
|
1862497bf4 | ||
|
|
344e77eafa | ||
|
|
1bf8afd9ac | ||
|
|
f50de19137 | ||
|
|
f9e8748906 | ||
|
|
2f5d76ed38 | ||
|
|
0b8559891a | ||
|
|
6df0f45fa3 | ||
|
|
c916977292 | ||
|
|
d898121764 | ||
|
|
79faffdfee | ||
|
|
500a6b1489 | ||
|
|
28f495f11b | ||
|
|
ffa1781005 | ||
|
|
7fb9454c74 | ||
|
|
c05c7e6f41 | ||
|
|
b47c0dff2b | ||
|
|
7e7335530e | ||
|
|
2d474696e6 | ||
|
|
a89eb98191 | ||
|
|
2b28bae58f | ||
|
|
9fadb172f9 | ||
|
|
99b0580697 | ||
|
|
d9b52ba5ef | ||
|
|
cbc7c4918f | ||
|
|
192cb91517 | ||
|
|
ca45874fe9 | ||
|
|
d051d3fa1d | ||
|
|
d99dbfee36 | ||
|
|
ab6279a449 | ||
|
|
c4c5e68267 | ||
|
|
5ec38f1fb4 | ||
|
|
9707232954 | ||
|
|
d9cd742355 | ||
|
|
a26262d3b2 | ||
|
|
50b5c66a7e | ||
|
|
b92baf8b2a | ||
|
|
236cc9fdd2 | ||
|
|
f923297498 | ||
|
|
83f5d878e7 | ||
|
|
2f00efadfc | ||
|
|
34e88c6b63 | ||
|
|
c85147e989 | ||
|
|
e434e711bf | ||
|
|
03dd39b128 | ||
|
|
cfc4d70d43 | ||
|
|
ebe7d1a86c | ||
|
|
155f345911 | ||
|
|
a2a38f8937 | ||
|
|
1bfc8b6a19 | ||
|
|
1cdbdd00d9 | ||
|
|
eea932f43a | ||
|
|
5357a65b91 | ||
|
|
9d8678e8e5 | ||
|
|
03d5fc330a | ||
|
|
7ddb7dda97 | ||
|
|
2e6679c14f | ||
|
|
14c1846fe1 | ||
|
|
1600927237 | ||
|
|
88893eb0be | ||
|
|
d3fa026e22 | ||
|
|
537c895ebe | ||
|
|
1b22d55b94 | ||
|
|
1fceb181b7 | ||
|
|
aa54f32ba2 | ||
|
|
bc5bce3171 | ||
|
|
af8677d510 | ||
|
|
8013483d17 | ||
|
|
7ca09a60d8 | ||
|
|
f425a303e5 | ||
|
|
fc70b9c4be | ||
|
|
cc4e3ea0cf | ||
|
|
1fa1a880e9 | ||
|
|
035f2fd4c1 | ||
|
|
fda8750f14 | ||
|
|
4e7d291ad9 | ||
|
|
03f87c2042 |
+3
-1
@@ -5,4 +5,6 @@ NEXT_PUBLIC_SITE_ID=CS
|
||||
NEXT_PUBLIC_SUB_DOMAIN=http://localhost:13000
|
||||
NEXT_PUBLIC_SERVER_API_URL=http://dev.onasys.co.kr:8000
|
||||
NEXT_PUBLIC_LINK_BACKEND_API_HOST=http://rsone.iptime.org:10014
|
||||
NEXT_PUBLIC_TINY_API_KEY=t9nc4z6inquvvd5pq1vea8wcp7lb01qmqseh6egms9vpaju2
|
||||
NEXT_PUBLIC_TINY_API_KEY=t9nc4z6inquvvd5pq1vea8wcp7lb01qmqseh6egms9vpaju2
|
||||
|
||||
NEXT_PUBLIC_SERVER_API_URL2=http://con.mind-one.co.kr:11083/
|
||||
@@ -11,6 +11,18 @@ import {
|
||||
const serverApiUrl =
|
||||
process.env.NEXT_PUBLIC_SERVER_API_URL ?? "http://localhost:3000";
|
||||
|
||||
const serverApiUrl2 =
|
||||
process.env.NEXT_PUBLIC_SERVER_API_URL2 ?? serverApiUrl;
|
||||
|
||||
const serverApiUrl3 =
|
||||
process.env.NEXT_PUBLIC_SERVER_API_URL3 ?? serverApiUrl;
|
||||
|
||||
const serverApiUrl4 =
|
||||
process.env.NEXT_PUBLIC_SERVER_API_URL4 ?? serverApiUrl;
|
||||
|
||||
const serverApiUrl5 =
|
||||
process.env.NEXT_PUBLIC_SERVER_API_URL5 ?? serverApiUrl;
|
||||
|
||||
export function middleware(req: NextRequest) {
|
||||
const pathname = req.nextUrl.pathname;
|
||||
const searchParams = req.nextUrl.searchParams;
|
||||
@@ -52,6 +64,97 @@ export function middleware(req: NextRequest) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (pathname.startsWith("/sewerage-service")) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const token = req.cookies.get(CLAIM_NAME)?.value;
|
||||
const userId = req.cookies.get(AUTH_USER_ID)?.value;
|
||||
const newUrl = `${serverApiUrl2}${pathname}`;
|
||||
|
||||
if (token) requestHeaders.set(CLAIM_NAME, token);
|
||||
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
|
||||
|
||||
logMessages.push(` Rewritten URL: ${newUrl}`);
|
||||
logMessages.push("\n--------------------------------\n");
|
||||
console.log(logMessages.join("\n"));
|
||||
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders,
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/reuse-service")) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const token = req.cookies.get(CLAIM_NAME)?.value;
|
||||
const userId = req.cookies.get(AUTH_USER_ID)?.value;
|
||||
const newUrl = `${serverApiUrl3}${pathname}`;
|
||||
|
||||
if (token) requestHeaders.set(CLAIM_NAME, token);
|
||||
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
|
||||
|
||||
logMessages.push(` Rewritten URL: ${newUrl}`);
|
||||
logMessages.push("\n--------------------------------\n");
|
||||
console.log(logMessages.join("\n"));
|
||||
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders,
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/operation-service")) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const token = req.cookies.get(CLAIM_NAME)?.value;
|
||||
const userId = req.cookies.get(AUTH_USER_ID)?.value;
|
||||
const newUrl = `${serverApiUrl4}${pathname}`;
|
||||
|
||||
if (token) requestHeaders.set(CLAIM_NAME, token);
|
||||
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
|
||||
|
||||
logMessages.push(` Rewritten URL: ${newUrl}`);
|
||||
logMessages.push("\n--------------------------------\n");
|
||||
console.log(logMessages.join("\n"));
|
||||
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders,
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/ic-service")) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const token = req.cookies.get(CLAIM_NAME)?.value;
|
||||
const userId = req.cookies.get(AUTH_USER_ID)?.value;
|
||||
const newUrl = `${serverApiUrl5}${pathname}`;
|
||||
|
||||
if (token) requestHeaders.set(CLAIM_NAME, token);
|
||||
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
|
||||
|
||||
logMessages.push(` Rewritten URL: ${newUrl}`);
|
||||
logMessages.push("\n--------------------------------\n");
|
||||
console.log(logMessages.join("\n"));
|
||||
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders,
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/dc-service")) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const token = req.cookies.get(CLAIM_NAME)?.value;
|
||||
const userId = req.cookies.get(AUTH_USER_ID)?.value;
|
||||
const newUrl = `${serverApiUrl5}${pathname}`;
|
||||
|
||||
if (token) requestHeaders.set(CLAIM_NAME, token);
|
||||
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
|
||||
|
||||
logMessages.push(` Rewritten URL: ${newUrl}`);
|
||||
logMessages.push("\n--------------------------------\n");
|
||||
console.log(logMessages.join("\n"));
|
||||
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders,
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/user-service")) {
|
||||
const queryParams = searchParams.toString();
|
||||
const newUrl = `${serverApiUrl}${pathname}${
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 538 755">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #fff;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<!-- Generator: Adobe Illustrator 28.7.9, SVG Export Plug-In . SVG Version: 1.2.0 Build 218) -->
|
||||
<g>
|
||||
<g id="Layer_1">
|
||||
<g id="han" data-label-shift="dx,dy">
|
||||
<path class="cls-1" d="M159.2,197l-5,5.8,5.1,3.7,13.2,9.7-7.3,3.5-8.2-1.2-9.4,1.4,1.4,4.9-3.5,7.3,3.8,2.6-.9,4.7,8.9-2.3,4.2-3.7,5.2,4.2-6.1,2.3.9,12,3,7-.9,3.3-.5,1.6,5.4,6.8,5.2,13.4h-3.6c0-.1,6.4,3.8,6.4,3.8l4.8,6h1.2l3.6-5.4,3.6-.6,13.8,5.9,19.7-1.1,4.6-6.5,3-5.2,8.2-1.7,11.7-17.8,7.1,1.9,4.9,10,13.2,9.6,3.8,13-1.4,12.2-.5,9.5,1.6,1.1-.6,1.3v1.1c.1,0-2.2,2.4-2.2,2.4l-17.5,7.4,7.6,19.2,16.3,1.1,8.4,10.8,12.6.6,4.2-5.2-4.6-7.9-9.2-6.2,12.1-7.1,6.4,5.2,1.3-5.6-6.6-6.5,17.5-5.8,4.8,4.4,4.8-2.1-4.7-6.5,4.5-8.8,6.3-.4,4.7-3,8,3,24.1,4.5,11.5-7.8-2.8-6.4,6.5-11.7,10.5-5.5,7.6-7.9,10.2-2.3,13.4,4.6,4.4-8,12.4,8.2,3.4-3.1.2-15.2.4-11.3,13.4-3.2,4.6-.4-1.9,9.9,9.8,4.6,1.6,12.8,12.2,9.2,9.8-8.4,15-8.9-3.7-19-21.8-40.6-5.7-10.6,1.2-6.8-4.9-6.1-4-4.9,1.2-5.2-26.3-33.1-5.8-12.1-7.1-14.9-11.9-20.9-2.9-9.4-2.1-6.7-1.8-5.2-8.7-25.5-8.6-14.4-.9-11-5.2-11-3-6.3-6,6.5-5.2,22.8-9.8,11-5.5,2.8-7.4,3.7-17.1.5-12.7-1.6-8.2,2.3-5.2-3.4-3.4-2.2-18.8-2.3-21.8,4.5-19-3.7-3.5,4.7-11.2-7.3-5.2,4.2-6.1-.7-11.5,3.5-14.1,10.8-3.7,10.1-12.9,9.8-4,7.3-8.5,6.8-2.3,1.9-9.1,4.5-4,18.3-9.2,11.5-14.3,1.2-2.1,30,5.6,1.4,3.3,9.2-1.4,2.7.9,2.6,2.9-.7,1.8,3.2-4.5,2.2,1.7,8.6,3.8,6.9,8.9,3.4Z"/>
|
||||
</g>
|
||||
<g id="yeongsan" data-label-shift="dx,dy">
|
||||
<path class="cls-1" d="M57.4,578.4s.2,1.4.2,2.3.7,1.6.7,1.9.5,1.4.7,2.3c.2.9,1.2,1.2,1.2,1.2h0s.5,1.4.5,1.4c0,0-.5.7-.9,1.4-.5.7,1.6.9,1.6.9l2.8-.7s1.4-.7,1.4-1.2,0,0-.2-.7c-.2-.7-.5-.7-.9-1.2-.5-.5.5-.2.5-.2l.5.2,2.6-.5s.9-.5,1.4-.7c.5-.2-.2-.5-.2-.9s-.2-1.2-.2-1.2l.2-.9v-1.2c0-.5.7-.7.9-1.2.2-.5.5-.7.9-1.2.5-.5,0-.7,0-1.6s-.5-.5-.5-.9-.5,0-.5,0l-.9.5-.9.7s-.2.9-.5,1.2c-.2.2-1.4.2-1.4.2,0,0-.2-.5-1.2-.9-.9-.5,0,0-.5,0s-1.2-.2-1.2-.2c0,0-1.2-.7-1.6-.9-.5-.2-.5-.9-.5-.9h-1.2s-1.9,1.4-2.8,1.9c-.9.5,0,1.2,0,1.2Z"/>
|
||||
<path class="cls-1" d="M45.2,585.7c.2.2,0,.2.7.9.7.7.5,1.6.9,1.6s.2-.5,1.2,0c.9.5,1.4.5,1.9.7.5.2,1.6.9,1.9.9s1.4.7,1.4.9-.2.2,0,.5c.2.2,0,.5.5,1.4.5.9,1.9,2.6,1.9,2.6,0,0-.7.7.5.5,1.2-.2,1.9-.2,1.9-.9s.2-1.2.2-1.4-.2-.2-.5-1.2c-.2-.9-.7-1.6-.7-1.6,0,0,1.2-.2,0-1.2-1.2-.9-.2-1.2-1.2-.9-.9.2-1.9.2-1.9.2-.2-1.2-.2-1.9-.2-1.9l-.5-.5.7-1.4h0c.5,0,.9-.2,1.2-.2s.9-.7.9-.7c0,0,.2-.2,0-.7-.2-.5-.2-.2-.9-.7s-1.6-.7-1.6-.7l-2.1-1.2-1.4-.9c-.7-.2-2.6.9-2.6.9,0,0,.9-.5,0,.7-.9,1.2-2.3,1.9-2.3,1.9,0,0-.2.5,0,.9.2.5,0,1.2.2,1.4Z"/>
|
||||
<path class="cls-1" d="M28.6,585.5s0,.7,1.2.7h2.1c.5,0,.9.7.9.7v1.9l1.2.7s1.4,0,1.9-.5c.5-.5.5-.7.5-.7l-.5-1.4,2.3-.7s.5-.5.7-1.2c.2-.7-.2-1.2,0-2.3.2-1.2,0-2.8,0-2.8,0,0,.9-1.4.9-2.1s1.9-2.6,1.9-2.8h0v-.7h-1.4c-.2,0-1.7.5-2.1.7-.5.2,0,0-.9,1.2s-.2,1.6-.2,1.6l-1.9.5-1.4.7-.9.2s-1.2-.2-2.1-.2-.5.9-.5.9c0,0-1.2,1.4-1.9,1.6-.7.2-.7.7-.7.7,0,0,.9,2.3.9,2.8v.5Z"/>
|
||||
<path class="cls-1" d="M41.7,591.4c-.5.2-.7-1.2-.5,0,.2,1.2,1.2,2.1,1.2,2.1l1.4.9s.9-.2,1.4,0c.5.2.9,0,.9,0l1.9.7v.2s.7-.2.5-1.6c-.2-1.4,0-1.4,0-1.4l-.7-.9-2.6-1.4h0s-2.8-.7-3-.5c-.2.2-.5-.2-.5.2s.5,1.4,0,1.6Z"/>
|
||||
<path class="cls-1" d="M34.2,597.7s0,0,0,0c0,0,0,0,0,0Z"/>
|
||||
<path class="cls-1" d="M45,598.9l-.7-.7-.5-.9s.2-1.4-.2-1.4-1.9-.5-1.9-.5l-1.4-.7h0s-1.4,0-1.4,0c0,0-.9,0-1.2.7-.2.7-.9.5-.9.9s-2.1,1.2-2.5,1.4c0,0,.2.2.4.5.5.7.5,1.4,1.2,1.4s2.1.2,2.3,0c.2-.2.9-.7,1.2-.5.2.2.5.5.5.9s-.5,1.2-.5,1.6.5,0,0,.5c-.5.5.2,1.4.5,1.6.2.2-.7,2.1-.7,2.1,0,0-.5.5-.5.7s1.4.7,1.6,0c.2-.7.7-1.2.9-1.4.2-.2.9-.5.9-.5,0,0-.5.2.7.2s2.1.2,2.1-.5v-1.9s-.2-1.2,0-1.4c.2-.2,0-2.3,0-2.3Z"/>
|
||||
<path class="cls-1" d="M18.5,619.7c.7,0,1.9-.9,2.3,0,.5.9,1.9,2.6,1.9,2.6,0,0,.2-.2,1.4,0,1.2.2,1.2.5,2.1,0,.9-.5,1.4-1.4,1.4-1.4l1.2-1.2,3.3-1.4s-.2-.7-.7-2.1c-.5-1.4-.7-2.1-.7-2.1,0,0,1.2.2.5-.9-.7-1.2-.9-1.9-.9-1.9l-.5-1.6h0s-.7-.9-.7-.9l-2.1.2s-.2,1.2,0,1.9c.2.7.2.9,0,1.4-.2.5-.7-.5-1.2,0-.5.5-2.3.2-2.3.2h-1.2l-.9,1.4-1.2.9-2.3.9-2.1,1.4s-.5,0,0,.9c.5.9,2.1,1.6,2.8,1.6Z"/>
|
||||
<path class="cls-1" d="M33.1,624h-.9l-1.4-.7-2.1.7s-.9,1.2-.9,1.6.7,1.9,1.4,2.3c.7.5,1.6.7,1.9,1.6.2.9.2,1.9.2,1.9,0,0,1.9.7,2.3-.7.5-1.4.2-2.3.7-2.6.5-.2,1.9-1.6,1.9-1.6,0,0-.5-.5.7-.5s1.6-.5,1.6-.7v-1.9l-.9-.9h.9l.7-.9s.2-.7,0-1.2c-.2-.5-.5-1.9-.5-1.9l-2.6.5h0l-1.4,1.4-.5.9s.2.9,0,1.2c-.2.2-1.2,1.4-1.2,1.4Z"/>
|
||||
<path class="cls-1" d="M65.6,620.2l1.9-.7-2.1-2.6-3.5-1.9h0s-3.3.7-3.3.7l1.6,2.1.9,1.4s-.5.5-.9.9c-.5.5-1.6.7-1.6.7,0,0-.5.5-.5.9s-.9,0-2.1.7c-1.2.7-4.5,1.9-4.5,1.9h-.9c.9,0,1.6,2.6,2.3,2.6h3.1s-.2-.5.9-.7c1.2-.2,2.6-1.2,2.6-1.2,1.4.2,2.3-.7,3,.5.7,1.2,1.4.9,1.6,1.4.2.5,1.2,2.1,1.2,2.1l-.7,2.6s1.2.9,1.6.7c.5-.2,1.9-1.4,1.9-1.4l.9-1.9s-.5-1.4,0-1.9c.5-.5-1.6-1.4-1.6-1.4l-2.8-.7-1.9-2.6v-1.2l2.8-1.2Z"/>
|
||||
<path class="cls-1" d="M64.2,635.5v-1.6s-3.3,1.4-3.3,1.6.9,1.6.9,1.6h1.6l.7-1.6Z"/>
|
||||
<path class="cls-1" d="M59.8,639.2c0,1.2.5,2.8,1.2,3,.7.2,1.6,0,1.6,0v-3l-1.6-.9s-1.2-.2-1.2.9Z"/>
|
||||
<path class="cls-1" d="M38.4,638.3c1.2,0,2.8-4.5,2.8-4.5v-1.4h0s-3.5,0-3.5,0l-2.1,1.4-3.5.7s-.2,1.9,1.4,1.9.7-.1.6-.2c0,0,.3,0,.6.2,1.6.5,3.3.7,3.3,1.2s-.7.7.5.7Z"/>
|
||||
<path class="cls-1" d="M15.4,630.1h0s0,0,0,0h0Z"/>
|
||||
<path class="cls-1" d="M7,642.7c.2-.5,1.2-.7,1.2-1.4s-1.6-2.6-.5-3.1c1.2-.5,2.6-.9,2.8-1.2.2-.2,1.2-.7,1.6-.5s.9.9.9.9l1.4-.5.5-.9s.2-.9.5-1.4c.2-.5.7-1.9.7-1.9v-1.2l-.7-1.6c-.3.2-2.6,2.1-2.8,2.3-.2.2-3,1.2-3.3,1.2s-3.1.2-3.1.2l-3.8.5-2.6,1.9,1.9,2.1s-.2,1.9,0,2.1c.2.2-.5,1.2.5,1.6.9.5,1.6.9,1.6.9,0,0,2.8.2,3-.2Z"/>
|
||||
<path class="cls-1" d="M16.6,649.1c0-.7-1.2-1.6-1.2-1.6l-.7-.7-.9-.9s-.2-1.2-.2-1.4-.7-.9-.7-.9c0,0-2.3.2-2.3.5s-.7.7-.7.7c0,0-.2.7-1.6.7s-2.8-.5-2.6,0c.2.5-.2.9-.2,1.6s-.5,1.9-.5,1.9v1.2s.2,1.2.7,1.4c.5.2,1.2.5,1.4.7.2.2,1.4.9,1.2,1.4-.2.5,2.3.2,2.3.2l.5-.5c.2-.2,1.9-1.2,1.9-1.2,0,0,0-.9.5-.9s3.3-.5,3.3-.5v-1.6Z"/>
|
||||
<polygon class="cls-1" points="12.9 643.4 12.9 643.4 12.9 643.4 12.9 643.4"/>
|
||||
<path class="cls-1" d="M27.7,639.9c.5.5,1.4,1.6,2.1,1.9.7.2,1.2.5,1.4,1.2.2.7.2,1.4.5,2.1.2.7,1.9.7,1.9,1.2s.5-.2,1.4,0c.9.2.2-.2,1.6,1.2,1.4,1.4,2.3,2.1,2.6,2.6.2.5.9,0,.9,0l1.2-.9s-.2-1.6,0-1.6.2-2.1.2-2.3-.5-2.3-.5-2.3c0,0-1.2-1.4-1.4-1.4s-2.1-.7-2.1-.7l-1.2-1.2-.9-1.2-1.4-.5h0l-3.7-.7h-2.1l-1.2,1.6s.2.7.7,1.2Z"/>
|
||||
<path class="cls-1" d="M32.6,663.4c.5.2,2.3.5,2.8.5s1.6-.2,1.9-.5c.2-.2.9-.2,1.6-.2s3.5.2,3.5.2c0,0,.5-.7.2-1.4-.2-.7-.9-1.4-.9-1.4l-.2-.7-.7-.5.7-1.2v-.9s-.7-.5-1.4-.5-1.4.2-1.4-.2-.9-1.9-.9-1.9l-1.4.7h0c-.9.5-1.9.7-2.1.9-.2.2-3.3.2-3.1.7.2.5.7,1.2.9,1.4.2.2.9,1.6.9,1.6,0,0-.5,1.6-.5,1.9s-.5,1.2,0,1.4Z"/>
|
||||
<path class="cls-1" d="M21.3,670.4c0-.2,0-1.4.5-1.6.5-.2.7-.5.7-.7s-.7-1.2-.7-1.4-1.2-1.2-1.2-1.2l-.5-1.2-.2-1.2-.2-1.9h0s-.9-1.9-1.2-1.9-1.4-.2-1.4,0-.5.9-.5.9v.7c0,.2-.2.7,0,1.2.2.5-.2,1.4,0,1.6.2.2.2.7.5,1.4.2.7.7,1.2.7,1.4s-.2,1.2-.2,1.2c0,0-.5-.7-.5.5s-1.9,1.9-.5,2.1c1.4.2,2.8.5,3,.5s1.6-.2,1.6-.5Z"/>
|
||||
<path class="cls-1" d="M27.4,673s-.5-.9,0-1.6c.3-.5.5-.9.7-1.2.2-.5.9-.5.9-.9s.5-2.3,0-2.8c-.5-.5-.9-1.6-1.4-2.3-.5-.7-.2-.9-1.2-1.6-.9-.7-1.9-1.2-1.9-1.2l-1.2.2h0s-.7,2.1-.7,2.3.2,2.3.7,2.6c.5.2,1.6,1.4,1.9,1.9.2.5.2,1.2.2,1.6s-.7,2.1-.9,2.1,0,0-1.2.5c-1.2.5-2.6.2-3,.9-.5.7-1.2,1.4-1.2,1.4v1.4c0,.2-.2.7.5.7s2.3-.2,2.8-.5c.5-.2,1.4-.7,1.4-.7l2.3-2.1,1.2-.7Z"/>
|
||||
<path class="cls-1" d="M63.7,683.1c-.2-.5-1.4-2.1-1.4-2.1l-.5-.9s0-1.6-.9-1.9c-.9-.2-3-.2-3-.2l-1.6-2.3s-1.4-2.6-1.6-2.6-1.4,0-2.1-.2c-.7-.2-2.6-1.2-2.6-1.2l-.9.7c.2.7,1.6,2.8,1.6,2.8l1.2,2.3-.5,1.9s-1.9.5-2.3.5h-3s-.5-.7-.7.7c-.2,1.4-2.6,2.6-2.6,2.6h-3s-.9,1.6-.9,2.1-6.1,3.1-6.1,3.1l-1.9,2.6-1.9.5s-.5.7-.5.9-1.2,1.6-1.2,1.6h-.7s-2.3.5-2.3.9.5,1.6.5,2.1v1.6s0,1.6.2,1.6,1.4.7,1.4.7l.7,1.2s.5.2.5.5.7,1.2.7,1.2l1.2,1.2s-.5,1.6,0,2.1c.5.5.9.5,1.4.7.5.2,4.2.7,4.2.7,0,0,1.9.2,2.1.5.2.2,1.4.5,2.1,0,.7-.5,7-1.6,7-1.6,0,0-.7-.9,0-1.2.7-.2,1.9-.5,3-1.4,1.2-.9,3.7-1.2,3.7-1.2,0,0-.5-1.2.2-1.6.7-.5,2.6-2.1,2.8-2.1s2.1,1.4,2.1,1.4c0,0-.7.7.5.7s1.4-.5,1.9-2.1c.5-1.6,1.9-2.3,1.9-2.3l.5-.7s-.5-.5,0-1.6c.5-1.2.9-2.6.9-2.6v-3.5s-.5,0,.5-.5c.9-.5,2.1-2.3,1.4-3.1-.7-.7-1.6-1.9-1.9-2.3Z"/>
|
||||
<polygon class="cls-1" points="49 672.3 49 672.3 49 672.3 49 672.3"/>
|
||||
<path class="cls-1" d="M93.5,737.5c-2.3-1.2-4.2-2.3-4.2-2.3h-1.9l-1.2,3.5s1.4,0,1.2.9c-.2.9-1.6.5-1.2,1.6.5,1.2-.5.7,1.6,1.6,2.1.9,2.8,1.9,3.7.9.9-.9,1.9-2.6,1.9-2.6h0l.7-1.2s1.6-1.4-.7-2.6Z"/>
|
||||
<path class="cls-1" d="M86.2,745l-2.8-1.9s-2.8,2.6-2.8,3.1-2.1,3.3-1.6,4,1.2,1.6,2.8,1.6,3.3-1.6,5.4-2.6c2.1-.9,2.8-2.3,3.7-1.9.9.5,2.1-.5,2.1-.5h0l-1.9-1.2-4.9-.7Z"/>
|
||||
<path class="cls-1" d="M101.7,742h0l-3.5,1.2s-.9,1.2-.9,1.6.5,2.6.5,2.6c0,0-.5.5-.5,1.6v2.3s1.2,3.1,2.1,3.5c.9.5,2.6-.5,3.1-1.9.5-1.4-.9-5.6-.9-5.6,0,0-2.8-1.2-2.1-1.4.7-.2,2.8-.5,3.1-.5s.9-.7.9-.7l-.7-2.8h-.9Z"/>
|
||||
<path class="cls-1" d="M115.1,720.4l-1.2-1.6-.5-1.6h0v-2.6l-2.1-3.3s-1.6-1.2-1.9-1.6c-.2-.5-3-2.3-3-2.1s-2.3,2.3-2.3,2.6-3.7,2.8-3.7,2.8c0,0,1.2,4,1.2,4.2s-1.9.2-.5,1.9c1.4,1.6,5.9,2.1,5.9,2.1,0,0,.2-1.4.5.5.2,1.9-.5,2.8-.5,3.1s1.2,1.2,2.6,1.2,3.3-.2,3.5,0c.2.2,3.5.5,3.5.5,0,0,.2,0,0-2.1-.2-2.1-1.4-3.8-1.4-3.8Z"/>
|
||||
<path class="cls-1" d="M125.6,711.9c.5,0,1.4-1.9,1.4-1.9,0,0-.5-.7.9-.5,1.4.2.9,0,1.6.5.7.5,1.2.5,1.4.5s1.2-.7.5-1.4c-.7-.7-1.4-.9-1.9-1.6-.5-.7-.5-2.6-.5-2.6,0,0-.5-1.4-.7-1.4h-2.8l-.9.9h0c-.7,0-3.5-.7-3.5-.7l-.5,2.8-2.1,1.4s-.9.5-.5,1.2c.5.7.9,1.2.7,1.6-.2.5-1.6,0-1.4.7.2.7,1.6,1.9,1.6,1.9,0,0-.7,1.2-.7,1.6s.9,1.4,1.4,1.4,1.9-2.1,1.9-2.1c0,0,.5-.9.9-1.2.5-.2,2.1-1.2,2.1-1.2h.9Z"/>
|
||||
<path class="cls-1" d="M141.5,712.4c0-.2-.9-.5-1.2-.7-.2-.2-1.6-.7-1.6-.7l-3-.9h-1.7s-.7,2.1-.7,2.3-.5,1.2,0,1.4c.5.2,2.1.7,2.1.7v1.2c0,.5-.7.7.5,1.2,1.2.5,4.2-.5,4.2-.5h2.6s.9-1.4.5-1.9c-.5-.5-1.6-1.9-1.6-2.1Z"/>
|
||||
<path class="cls-1" d="M128.6,725.1s.2-.2.5,0c.2.2,1.4-.5,1.4-.5,0,0-.2-.5.5-.5s1.9.5,1.9.5c0,0,.7-.2.9-.7.2-.5-.2-.9,0-1.4.2-.5,0-1.6,0-1.6l-.7-1.6s-.9-.2-1.4-.2-1.2-.2-1.2-.2l-.5-.2-.9-.7h0s-2.3-.2-2.6.5c-.2.7-.7,1.6-.9,1.9-.2.2-1.9.9-1.9.9l1.4,1.4s.2.7,1.2,1.2c.9.5,2.3,1.4,2.3,1.4Z"/>
|
||||
<path class="cls-1" d="M121.1,719.9c-.3-.3-.7-.5-1.2-.5h0c-.6,0-1.1.6-1.2,1.2,0,.4.2.8.5,1.2.1.2.3.5.7.7.5.3,1.4.6,1.6.2.2-.2,0-.5-.2-1.6,0-.7,0-.9-.2-1.2Z"/>
|
||||
<path class="cls-1" d="M137.3,747.6c-.9-.5-1.9-.9-1.9-.9l-.5-1.2.9-1.2.2-2.3-4.2-.5-2.1.5h0s-1.2,2.1-1.4,2.6c-.2.5-2.1,1.9-2.1,2.1s0,.7-.2,1.4c-.2.7-.9,1.9,0,2.3.9.5,2.1.7,2.1.7,0,0,2.6-1.4,2.8-.7.2.7.2,1.2,1.2,1.9.9.7,2.1.9,2.3.9s.2-1.2.9-1.4c.7-.2,2.6-1.9,2.6-1.9,0,0,.2-1.9-.7-2.3Z"/>
|
||||
<path class="cls-1" d="M267.1,679.6s.5-.5,0-1.6c-.5-1.2-.7-2.1-.7-2.1l-.7-1.2-.5-1.4s-.5-.5-.2-1.2c.2-.7,0-2.6,0-2.6l-.2-.7.7-.9h0c.2-.2.5-2.1.5-2.1l-3.3-2.3s-1.4.9-1.2,1.9c.2.9.9,2.1.9,2.6s.2,1.6,0,2.1c-.2.5-.9,1.2-.9,1.4s-.7,1.4-.9,1.9c-.2.5-2.8,1.9-2.8,1.9,0,0-1.9,1.9-1.9,2.1s-1.2.2-.7,1.6c.5,1.4.5,3.3.5,3.3,0,0-1.2.9-.5,1.6.7.7,1.4,1.6,2.8,2.1,1.4.5,4.2,1.6,4.2,1.6l3.1.5s2.3-.9,1.9-1.4c-.5-.5-1.6-1.4-1.6-1.4l-.5-1.2s0-1.2.5-1.9,1.6-2.6,1.6-2.6Z"/>
|
||||
<polygon class="cls-1" points="279.4 600.4 279.4 586.1 272 579.9 262.7 571.1 261.3 561.5 254.5 559.9 251.7 557.3 244.7 562.9 243.5 566.9 235.1 563.3 234.4 553 235.1 535.7 240.9 533.6 245.9 532.1 247.1 523.8 256.9 510.3 248.3 507 239.9 515.4 232.7 509.4 238.7 493.8 231.6 486.6 229.2 475.8 217.2 472.2 206.4 484.2 205.2 493.8 195.7 486.6 186.1 495 186.1 502.2 176.5 510.6 159.8 515.4 157.4 523.8 140.6 521.4 127.4 517.8 124.5 512.7 119.4 508.3 115.3 512.5 110.2 512.4 96.4 517.8 89.3 530 84.4 535 85.6 538.3 88.3 540.1 87.2 541.1 82.3 539.9 76.8 551.3 72.3 553.6 67.3 564.8 76.6 566.5 73.6 571.4 75.3 574.4 80.6 583.9 85.4 585.9 85.4 589.7 80 596 78.4 589.4 69.9 588.5 68.8 590 71.3 593.4 75.4 595.9 74.3 598.4 69.7 600 68.7 603.3 63 605.4 61.9 611.5 67.8 615.5 70.4 613.1 73.2 605.9 74.3 613.6 75.3 626.5 69.7 634.5 69.7 639.2 68.1 643.4 67.8 644.3 80.4 650.4 92.7 661.4 89.3 661.9 86.5 659.8 85.6 664 79 654.2 69.4 650 67.8 656.3 70.6 661.9 74.3 663.3 77.1 670.4 72.7 669.9 66.1 661.5 62.9 648.1 58.5 642.1 51.9 654.2 55.1 668.3 59.6 674.6 61.9 673.9 65.8 676.6 67.1 680.5 69.9 680.2 72.7 677.9 79 686.6 77.7 698.2 82.8 699.7 79.7 706.7 76.6 709.9 77.4 712.1 82.5 712.8 82.7 721.2 93.1 719.9 97.3 713.3 97.1 709.8 112.1 701.6 110.7 695.9 117.2 694.3 120.8 688.2 120.2 673.4 122.8 671.1 124.7 675.1 124.5 684.5 122.4 694.3 125.7 699.9 130.4 702.1 134.8 704.2 136.9 700.4 143.5 702.3 145.8 697.6 149.1 698.3 148.3 688.6 152.1 687 152.9 684.2 151.7 682 155 673 162 671.1 167.4 666.2 174.9 662.4 179.6 664 183.8 662.6 187.1 655.8 192.4 654.7 194.6 657.2 202.1 657.2 202.7 663.8 200.6 669.2 196 669.8 194.8 663.8 189.6 664 187.5 671.6 189.1 675.6 185.9 681.9 181.9 681.2 183.1 676 181.4 674.3 176 692.2 189.2 694.5 191.7 701.4 195.5 706.3 203.9 704.4 207.4 697.8 213.3 694.1 214.2 689.9 209.3 687.1 210 684 218 684.7 221 686.6 224.2 683.9 222.7 674.6 209.2 661.4 209.5 657 212.8 653.7 210.5 650.9 215.4 646.2 211.9 643.7 213.5 642.5 216.5 642.5 222 642.5 227.6 640.4 228.1 635.9 230.9 638 231.2 641.7 231.8 647.4 236.2 650.7 238.4 657 234.6 663.8 232.6 672.3 234.9 676.9 238.7 676.9 243.5 679.8 244.5 675.1 243.3 671.1 245.9 662.9 249.9 659.4 255 664.1 261.6 661 262.3 655.8 265.1 651.9 267 645.5 264.6 642 261.1 642.5 257.9 642 248 646 246.3 642 239.9 634.6 244.2 626.8 246.3 631 251.6 632.8 262.5 623.5 278.8 628.6 285.4 617.2 285.4 607.6 279.4 600.4"/>
|
||||
</g>
|
||||
<g id="nakdong" data-label-shift="dx,dy">
|
||||
<path class="cls-1" d="M405.4,649.3l-2.1-.2-1.6,1.2-.9,1.6-1.2.2-.9-.5v-1.2l.2-.9,1.4-.9.9-.7v-.9l.9-.9.7-1.2-.2-1.6-.2-1.4.5-3v-1.9l-1.6-1.6-.9-.9.2-1.9.7-2.8h0c0,0,1.6-.5,1.6-.5,0,0,1.2-.9,1.2-1.2s.2-.7.2-.7l-.2-.9-1.4-.9-1.9-.7-1.6.2-1.2.5-.9,1.2-.7,1.2-.2,1.2.5,1.9v.9l-.5.7-.7.2-1.2.2-.9.5-.5.5-.2,1.2-.2.5h-1.4l-1.4.5s-.9.2-1.2.2-.7.7-.7.7l-1.2.5h-1.4c-.2,0-.7.2-.7.2l-.5.5v.5l.2.7s.7.7.9.7,0,.7,0,.7l.2.9v.7l.2.9.5.5.7.5s.5.5.7.5.2.7.2.7c0,0,.5.7.5.9v2.1h-.2s-.7-.2-.9-.2-.5-.5-.5-.5l-.9-.7h-.9l-.9-.5-.5-.7-.7-1.2-.7-.5-.5-.2-.5.2-.7.7-.7.2h-.9l-1.4-.9-1.4-.9-1.4-.7h-1.2l-.5.2-.7.9-.5.7-1.2.7s-.2,0-.5.2c-.2.2-.7.5-.7.5l-.5.7-.7,1.2-.5,1.2-.9.9v3.3l1.2,1.4s.7,1.4.7,1.6.2,1.4.2,1.4l.7,1.2.7,1.6,1.6.2,1.4-.9.7-1.2.7-.7h2.6l1.4-1.2.9-1.6.7-.9.7-.5.5.5.5.7v2.6s.5.5.7.5,0,.7,0,.7l-.7,1.2-1.2,1.9-.5.7-.2.5-.2.5-.9.5-1.2.2-1.4.2-.7.5-.5.5-.2.7,1.4.5.5.5v.7l.5.5.7.2h1.2l2.1.2.7.5.2.7-.2.5-.7.5s-.9.7-1.2.7-.5.9-.5.9l-.2.7.2.9v.7l.9.2.9.7,1.2.2v.9l-.2.2-.9.5-1.4.5-.7.2-.5.7v.9l.5.7s.5.5.7.5,1.4.2,1.4.2c0,0,1.4.2,1.6.2s.9-.5.9-.5l1.2-.5,1.2-.7.5-.7v-.7l.2-1.2s.5-.9.5-1.2.9-.5.9-.5l1.4-.2.2-.7-.9-.9-.7-1.4.5-1.6v-1.2l.7-.7,1.6-.2,1.6-.2.7-.9.2-1.2v-2.1l.7-.7,1.9.2,1.6-.2.5,2.1,1.2,1.4,2.1.9,1.6-.7.2-1.2-.2-1.2-1.6-1.2-.7-1.4.2-1.2-1.2-.7-.9-.9.5-1.4h1.9c.2,0,.7-.5.7-.5l.7-.9v-1.6h.9c.2,0,.7-.5.7-.5l.2-1.4s.2-.5.7-.7c.5-.2,0-1.4,0-1.4v-1.4Z"/>
|
||||
<path class="cls-1" d="M330.3,650.8v-1.2l-.9-.5h0s-4.2-1.2-4.2-.9-2.8,0-2.8,0l-1.4.9s-.2.7-.2.9.2,1.2.2,1.2l.5.2.9.7,2.8.5h1.9l.9-.7.9-.7.9-.2.5-.2Z"/>
|
||||
<polygon class="cls-1" points="333.8 654.8 332.6 654.1 332.2 652.9 331.7 652.7 331 652.9 329.8 653.9 329.6 654.8 329.1 656 329.1 657.6 329.4 659 329.8 659.7 330.8 659.7 331.9 659.5 332.4 659 333.8 659 335 658.8 335.2 657.8 335.2 656.9 334.7 655.7 333.8 654.8"/>
|
||||
<polygon class="cls-1" points="308 649.2 307.6 648.4 307.6 647.5 308 646.3 308.7 645.2 308.7 644.2 308.3 644 307.3 643.5 306.4 642.8 305.5 641.9 304.7 641.2 303.1 641.4 302.2 642.8 302.2 644.7 301.2 645.2 300.8 644.2 300.5 642.6 301 641.4 301.7 639.8 302.4 638.4 303.6 637.2 303.6 636.5 303.3 635.8 302.6 635.8 301 636 299.8 637 298.4 638.1 298.2 639.5 297.3 640 295.6 640.9 294.7 642.4 293.5 643.5 293.3 644.9 293.3 645.9 293.5 647 294.2 648.2 295.4 648.4 297 649.2 299.4 649.2 301.2 648.7 303.1 649.2 304.1 649.9 306.2 651 307.8 652 308.3 651.7 309.4 651.7 309.7 651 309.2 650.3 308 649.2"/>
|
||||
<path class="cls-1" d="M305.2,653.4l-1.2-.5-.9-.7-.7-.2h-2.1l-1.6-.2-.9-.7h-1.6l-1.2,1.2-1.6,1.2-.9.7v.7l-1.4-.2-.5-1.2-.9-1.4-.2-.7-.5-.9-1.2-.5-1.2-.5-.5-.5s-.2-.5-.2-.7-.2-1.2-.2-1.2v-.5c0-.2-.7-.7-.7-.7l-.2-.7-.5-1.2-.2-1.4.7-.9.2-.9,1.6-.2.7-.5.5-.2.2-.7.2-1.2.5-.5.7-.9v-.7l-.2-1.2-.5-1.4.2-1.4-2.1-1.4h-3.1l-1.9.2-1.4,1.2-.9,1.4-.5,1.2-.5,1.4v.7l-1.6.5-.9.5-.7.9s.2.5,0,.7c-.2.2-1.2.9-1.2.9v1.4l-.5,1.2-.7.5-.9.5-.2.9v1.4l.2,1.2-.2,1.4.5,1.6.5,1.9,1.2,1.9h0v1.6l.2,1.4.7.9.9.7.2.7-.2.7-.9.9-.9.7-.5.7-.2.7,1.2.7.7.5,1.4.7v.7l.2,1.2.5.9.9.5.9-.2h1.9l1.2-.2.9-.5.9-.9v-1.4l-.5-.9-.2-1.4.2-.7.7-.5,1.9-.2,1.2-.9h2.3l.5.9v.7s-.5.7-.5.9-.2,1.2-.2,1.2l-.5,1.4v.5l-.2.9.2.5.2.5.2,1.2v1.2l.5.9,2.1.2,2.3.7,1.6-.2,1.2.2.9-.7s.5.5.7.5.5.9.5.9l1.6.7,1.6.2h.7l.2-1.2-.2-1.4-.7-.7-.2-.9v-1.2l.5-.5.9-.9.7-.2.5-.5v-2.3s-.5-2.1-.5-2.3v-.9l.2-1.2.5-1.4s-.2-.9,0-.9.7-.7.7-.7l.7-.5.2-.9-.2-.9-1.2-.5Z"/>
|
||||
<polygon class="cls-1" points="533.7 451.9 529.9 457.3 516.8 465.7 509.4 457.5 516.6 447.7 513.8 417.3 513.1 408.8 521.3 392.4 522.9 355.1 523.6 353.3 531.1 333.9 526.2 315.4 526.2 282.1 519.8 263.8 504.8 272.7 495 281.2 482.8 272 481.1 259.2 471.4 254.5 473.3 244.6 468.7 245 455.3 248.2 454.9 259.5 454.7 274.8 451.4 277.9 438.9 269.7 434.5 277.6 421.1 273 410.9 275.3 403.3 283.3 392.8 288.8 386.2 300.5 389 306.9 377.6 314.7 353.5 310.3 345.4 307.2 340.7 310.3 334.5 310.7 330 319.5 334.6 326 329.8 328.1 325 323.7 307.5 329.5 314.2 336 312.9 341.5 306.5 336.4 294.4 343.5 303.6 349.6 308.1 357.5 304 362.7 314.1 371.6 316.5 383.6 314.1 388.4 326.1 392 323.3 402.6 325.2 414.4 315.5 413.8 315 423.6 307.5 439.1 298 443 298.5 447.6 301.2 454.4 296.8 462.5 286.2 472.3 276.7 473.4 269.4 480.7 267.1 483.1 264.5 485.8 256.9 505.2 256.9 510.3 247.1 523.8 245.9 532.1 240.9 533.6 235.1 535.7 234.4 553 235.1 563.3 243.5 566.9 244.7 562.9 251.7 557.3 254.5 559.9 261.3 561.5 262.7 571.1 272 579.9 279.4 586.1 279.4 600.4 285.4 607.6 285.4 617.2 278.8 628.6 282.6 628.4 288.8 622.6 289.3 620.3 291.9 621.5 292.3 624.3 296.3 623 298.7 624.3 301.6 622.6 298.9 615.9 301.2 614.9 303.4 615.5 304.7 611.2 309.9 609.7 307.1 614.2 306.9 625.2 305.5 632.3 314.8 637.2 317 641.5 318.3 642.1 322.4 640.3 325.1 641.7 326.8 641.4 329.4 634.9 335.5 635.5 338.5 640.5 342.8 638.4 346.2 633 347.4 636.3 348.6 639.8 343.1 642.3 344.4 645.9 349.4 647.4 351.4 645.9 353.5 647.7 353.3 655.5 347.7 654.1 346.2 655.7 351 659.7 353.7 666.6 356.3 667.8 358.7 665.9 359.9 659.7 358.5 655.6 361.6 654.2 365.6 646.5 363.1 643.5 360.7 647.8 358.5 646.8 361.3 632.3 361.1 630.7 361 629.5 368.3 628 371.4 624.3 365.9 619.1 357.2 620.8 355.4 623.6 351.9 624.1 354.8 618.5 361.5 616.3 367.3 614.4 366.1 610.6 379 609.8 381.7 611.6 383.5 619.4 389.9 616.8 383.5 596.4 387.2 591.5 388.9 592.4 387.7 599.2 390.1 604.4 394.7 605 398 608.8 399.5 604.8 401.5 606.5 400.5 612.2 406.2 614.7 414 613.3 414.9 615.6 420.1 616.2 424.6 617.3 428.8 614.1 432.5 616.6 438.5 610.1 436.6 622.3 438 626.7 441.3 625.8 442.5 620.6 445.7 622.8 453.5 612.9 457 616.4 461.6 616.6 461.7 613.8 459.8 610.5 463.1 606.6 469.9 608.2 480.9 594.4 480.7 591.3 485.5 581.8 491 579.8 494.6 576.1 498.5 573.7 497.1 571.8 499.6 567.6 499.9 561.3 498 558.2 504.1 554 504 546.1 505.5 548.8 506.9 554.5 511.6 551.2 514.6 544.4 514.4 537.4 515.8 532.7 513.9 528 514 525.4 524.7 493.4 527.1 486.2 527.8 477.8 535.1 466.5 538 455.6 533.7 451.9"/>
|
||||
</g>
|
||||
<g id="geum" data-label-shift="dx,dy">
|
||||
<path class="cls-1" d="M298,443l9.5-3.9,7.5-15.6.5-9.8,9.7.6-1.9-11.8,2.8-10.6-12-3.6,2.4-4.8-2.4-12-10.1-8.9-12.6-.6-8.4-10.8-16.3-1.1-7.6-19.2,17.5-7.4,2.3-2.4v-1.1c-.1,0,.4-1.3.4-1.3l-1.6-1.1.5-9.5,1.4-12.2-3.8-13-13.2-9.6-4.9-10-7.1-1.9-11.7,17.8-8.2,1.7-3,5.2-4.6,6.5-19.7,1.1-13.8-5.9-3.6.6-3.6,5.4h-1.2l-4.8-6-6.4-3.9-5-.2-9.1-18.5-5.4,3-2.4-5.7-11.4-2.8-11.7-9.2h-3.9c0,.1-3.4,4.8-3.4,4.8l1,6.2,2.1,5.4-1.2.8-4.4-7.5-6.7-3.2-6.3-.3-5.2,3.3,5.9,3.4-3.6,2.2,5.3,4.4,2.5.8.4,3-6.5,6.1-8.7,11.2-4-1.9,6.4-13.5-1.6-1.9,1.1-7.9-2.1-3-4.7,14.5-3,1.8-3.8-5.7-4.4,2.7.5,8.4-1.5,1.7-3.3-.8-4.2,3.2-5.1,13.8.5,1.5,3.9-.2.2-6.5,5.6,2.5,2.8,5.3-7.4,2.4v3c0,0,5.9,1.2,5.9,1.2l4.3-1.5,2.1-3.3,4-.3-1.4,6,4.1,3.7-2.4,9.4,4.3,6.1,1.1,27,11.6,2.1-6.6-26.7,2.3-4.1-6.3-4.9,1.7-1.9,1-6.9,2-1.5,2.2,9,4.4,3.2,3.1-1.9,3.1-6.1,1.8,1.5-1.9,8.6,2,14.4,1.9,13.7-2.8,6.5,8.2,7.8v2.1l-6.9,2.9,2.9,21.8-1.6,1.9-5.9,6.7,1.3,2.7,3.3-2.7,8.2,2.8,6.2,7.7-1.2,2.8,5.1,13.1,5.6,3.1-19.1.5-1.8,3.3,6.4,3.1-.6,10.7,7.3,2.8,3-3.3,8.9,1.9,9.4-3.4.3,1.4.2.9-3.1,5.4-5.1-.9-9.4,3.5,6.8,6.4,4.3,1.4-.2,5.6-20.6-5.8-6.4,13.7-18.1,10.4-1.9,6.6,5.9,4.7h19.9s3.8,4.2,3.8,4.2l-.5,3.4,3,5.1,13.2,3.6,16.8,2.4,2.4-8.4,16.8-4.8,9.6-8.4v-7.2l9.6-8.4,9.6,7.2,1.2-9.6,10.8-12,12,3.6,2.4,10.8,7.2,7.2-6,15.6,7.2,6,8.4-8.4,8.6,3.3v-5.1s7.6-19.4,7.6-19.4l12.2-12.4,9.6-1.1,10.5-9.8,4.5-8.1-2.7-6.8-.6-4.6Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 219 KiB |
@@ -0,0 +1 @@
|
||||
export { BoardApi } from "../api/board-service";
|
||||
@@ -0,0 +1,60 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import type {
|
||||
Board,
|
||||
BoardFormData,
|
||||
BoardList,
|
||||
BoardParams,
|
||||
BoardPopupList,
|
||||
BoardPopupParams,
|
||||
BoardService,
|
||||
} from "../model/board-interface";
|
||||
|
||||
export class BoardApiService implements BoardService {
|
||||
public async getBoardList(params?: BoardParams): Promise<BoardList> {
|
||||
const response = await client.get<BoardList>(
|
||||
`${ENDPOINT.BOARD_SERVICE.BBS}`,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getBoardPopupList(
|
||||
params: BoardPopupParams,
|
||||
): Promise<BoardPopupList> {
|
||||
const response = await client.get<BoardPopupList>(
|
||||
`${ENDPOINT.BOARD_SERVICE.BBS}`,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getBoardInfo(bbsId: string): Promise<Board> {
|
||||
const response = await client.get<Board>(
|
||||
`${ENDPOINT.BOARD_SERVICE.BBS}/${bbsId}`,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async createBoard(data: BoardFormData): Promise<Board> {
|
||||
const response = await client.post<Board>(
|
||||
`${ENDPOINT.BOARD_SERVICE.BBS}`,
|
||||
data,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async updateBoard(bbsId: string, data: BoardFormData): Promise<Board> {
|
||||
const response = await client.put<Board>(
|
||||
`${ENDPOINT.BOARD_SERVICE.BBS}/${bbsId}`,
|
||||
data,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async deleteBoard(bbsId: string): Promise<void> {
|
||||
await client.delete(`${ENDPOINT.BOARD_SERVICE.BBS}/${bbsId}`);
|
||||
}
|
||||
}
|
||||
|
||||
export const BoardApi = new BoardApiService();
|
||||
@@ -0,0 +1,17 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import type {
|
||||
BoardTemplate,
|
||||
BoardTemplateService,
|
||||
} from "../model/board-template-interface";
|
||||
|
||||
export class BoardTemplateApiService implements BoardTemplateService {
|
||||
public async getBoardTemplate(bbsTypeCd: string): Promise<BoardTemplate> {
|
||||
const response = await client.get<BoardTemplate>(
|
||||
`${ENDPOINT.BOARD_SERVICE.BBS_TEMPLATES}/${bbsTypeCd}`,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
export const BoardTemplateApi = new BoardTemplateApiService();
|
||||
@@ -0,0 +1,11 @@
|
||||
export { BoardApi } from "./api/board-service";
|
||||
export {
|
||||
boardFormSchema,
|
||||
BOARD_POSTING_CODE,
|
||||
type Board,
|
||||
type BoardFormData,
|
||||
type BoardParams,
|
||||
type BoardPopup,
|
||||
type BoardPostingCode,
|
||||
} from "./model/board-interface";
|
||||
export { BoardTemplateApi } from "./api/board-template-service";
|
||||
@@ -0,0 +1,99 @@
|
||||
import { z } from "zod";
|
||||
import type { PageableList, PageableParams } from "@/shared/model";
|
||||
import type { BbsType } from "@/shared/store";
|
||||
|
||||
export const BOARD_POSTING_CODE = {
|
||||
팝업게시: "01",
|
||||
상단게시: "02",
|
||||
기간게시: "03",
|
||||
} as const;
|
||||
|
||||
export type BoardPostingCode =
|
||||
(typeof BOARD_POSTING_CODE)[keyof typeof BOARD_POSTING_CODE];
|
||||
|
||||
export interface BoardParams extends PageableParams {
|
||||
keywordType?: string;
|
||||
keyword?: string;
|
||||
bbsId?: number;
|
||||
bbsTypeCd?: string;
|
||||
bbsNm?: string;
|
||||
bbsExpln?: string;
|
||||
rfrncUseYn?: string;
|
||||
atflUseYn?: string;
|
||||
atflMaxCnt?: number;
|
||||
atflMaxFileSz?: number;
|
||||
ansUseYn?: string;
|
||||
cmntUseYn?: string;
|
||||
dgstfnEvlUseYn?: string;
|
||||
smsUseYn?: string;
|
||||
upndFixUseYn?: string;
|
||||
pstgPrdUseYn?: string;
|
||||
popupUseYn?: string;
|
||||
delYn?: string;
|
||||
}
|
||||
|
||||
export interface BoardPopupParams extends PageableParams {
|
||||
bbsNm?: string;
|
||||
}
|
||||
|
||||
export interface Board {
|
||||
bbsId: number;
|
||||
bbsTypeCd: BbsType;
|
||||
bbsTypeNm: string;
|
||||
bbsNm: string;
|
||||
bbsExpln: string;
|
||||
rfrncUseYn: string;
|
||||
atflUseYn: string;
|
||||
atflMaxCnt: number;
|
||||
atflMaxFileSz: number;
|
||||
ansUseYn: string;
|
||||
ansUseAuthrt: string;
|
||||
cmntUseYn: string;
|
||||
dgstfnEvlUseYn: string;
|
||||
smsUseYn: string;
|
||||
upndFixUseYn: string;
|
||||
pstgPrdUseYn: string;
|
||||
popupUseYn: string;
|
||||
delYn: string;
|
||||
useYn: string;
|
||||
prvcIndctYn: string;
|
||||
mdfcnDt: string;
|
||||
mdfrNm: string;
|
||||
}
|
||||
|
||||
export interface BoardPopup extends Board {
|
||||
pstCnt: number;
|
||||
}
|
||||
|
||||
export const boardFormSchema = z.object({
|
||||
bbsTypeCd: z.string(),
|
||||
bbsNm: z.string(),
|
||||
bbsExpln: z.string(),
|
||||
rfrncUseYn: z.string(),
|
||||
atflUseYn: z.string(),
|
||||
atflMaxCnt: z.number().nullish(),
|
||||
atflMaxFileSz: z.number().nullish(),
|
||||
ansUseYn: z.string(),
|
||||
ansUseAuthrt: z.string().nullish(),
|
||||
cmntUseYn: z.string(),
|
||||
dgstfnEvlUseYn: z.string(),
|
||||
smsUseYn: z.string(),
|
||||
upndFixUseYn: z.string(),
|
||||
pstgPrdUseYn: z.string(),
|
||||
popupUseYn: z.string(),
|
||||
useYn: z.string(),
|
||||
prvcIndctYn: z.string(),
|
||||
});
|
||||
|
||||
export type BoardList = PageableList<Board>;
|
||||
export type BoardPopupList = PageableList<BoardPopup>;
|
||||
export type BoardFormData = z.infer<typeof boardFormSchema>;
|
||||
|
||||
export interface BoardService {
|
||||
getBoardList: (params: BoardParams) => Promise<BoardList>;
|
||||
getBoardPopupList: (params: BoardPopupParams) => Promise<BoardPopupList>;
|
||||
getBoardInfo: (bbsId: string) => Promise<Board>;
|
||||
createBoard: (data: BoardFormData) => Promise<Board>;
|
||||
updateBoard: (bbsId: string, data: BoardFormData) => Promise<Board>;
|
||||
deleteBoard: (bbsId: string) => Promise<void>;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
export interface BoardTemplate {
|
||||
bbsTypeCd: string;
|
||||
rfrncUseYn: string;
|
||||
atflUseYn: string;
|
||||
atflMaxCnt: number;
|
||||
atflMaxFileSz: number;
|
||||
ansUseYn: string;
|
||||
cmntUseYn: string;
|
||||
dgstfnEvlUseYn: string;
|
||||
smsUseYn: string;
|
||||
upndFixUseYn: string;
|
||||
pstgPrdUseYn: string;
|
||||
popupUseYn: string;
|
||||
regDt: string;
|
||||
rgtr: string;
|
||||
mdfcnDt: string;
|
||||
mdfr: string;
|
||||
rgtrNm: string;
|
||||
mdfrNm: string;
|
||||
}
|
||||
|
||||
export interface BoardTemplateService {
|
||||
getBoardTemplate: (bbsTypeCd: string) => Promise<BoardTemplate>;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import {
|
||||
postFormSchema,
|
||||
postUpdateFormSchema,
|
||||
type Post,
|
||||
type MovePost,
|
||||
type DeletePost,
|
||||
type PostInfo,
|
||||
type PostList,
|
||||
type MyPostList,
|
||||
type PostParams,
|
||||
type MyPostParams,
|
||||
type PostFormData,
|
||||
type PostUpdateFormData,
|
||||
type PostService,
|
||||
} from "../model/post-interface";
|
||||
|
||||
export class PostApiService implements PostService {
|
||||
public async getPostList(
|
||||
bbsId: number,
|
||||
params: PostParams,
|
||||
): Promise<PostList> {
|
||||
const response = await client.get<PostList>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}`,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getMyPostList(
|
||||
params?: MyPostParams,
|
||||
): Promise<MyPostList> {
|
||||
const response = await client.get<MyPostList>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS}/mypost`,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getPostInfo(bbsId: number, pstNo: number): Promise<PostInfo> {
|
||||
const response = await client.get<PostInfo>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async createPost(data: PostFormData): Promise<Post> {
|
||||
const validatedData = postFormSchema.parse(data);
|
||||
const response = await client.post<Post>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS}`,
|
||||
validatedData,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async updatePost(
|
||||
bbsId: number,
|
||||
pstNo: number,
|
||||
data: PostUpdateFormData,
|
||||
): Promise<Post> {
|
||||
const validatedData = postUpdateFormSchema.parse(data);
|
||||
const response = await client.put<Post>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`,
|
||||
validatedData,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async deletePost(
|
||||
bbsId: number,
|
||||
pstNo: number,
|
||||
delRsn?: string,
|
||||
): Promise<void> {
|
||||
await client.delete(`${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`, {
|
||||
params: { delRsn },
|
||||
});
|
||||
}
|
||||
|
||||
public async softDeletePost(data: DeletePost[]): Promise<void> {
|
||||
await client.post(`${ENDPOINT.BOARD_SERVICE.POSTS}/softDeleteSels`, data);
|
||||
}
|
||||
|
||||
public async hardDeletePost(data: DeletePost[]): Promise<void> {
|
||||
await client.post(`${ENDPOINT.BOARD_SERVICE.POSTS}/hardDeleteSels`, data);
|
||||
}
|
||||
|
||||
public async movePost(data: MovePost[]): Promise<void> {
|
||||
await client.post(`${ENDPOINT.BOARD_SERVICE.POSTS}/movePstByBbsId`, data);
|
||||
}
|
||||
|
||||
public async restorePost(data: DeletePost[]): Promise<void> {
|
||||
await client.post(`${ENDPOINT.BOARD_SERVICE.POSTS}/restoreSels`, data);
|
||||
}
|
||||
}
|
||||
|
||||
export const PostApi = new PostApiService();
|
||||
@@ -0,0 +1,17 @@
|
||||
export { PostApi } from "./api/post-service";
|
||||
export {
|
||||
postFormSchema,
|
||||
postUpdateFormSchema,
|
||||
type Post,
|
||||
type MyPost,
|
||||
type MovePost,
|
||||
type DeletePost,
|
||||
type PostList,
|
||||
type PostParams,
|
||||
type MyPostParams,
|
||||
type PostFormData,
|
||||
type PostUpdateFormData,
|
||||
type PostService,
|
||||
} from "./model/post-interface";
|
||||
export { deleteReasonMessages } from "./model/delete-reason-messages";
|
||||
export { PostPageGuard } from "./lib/post-page-guard";
|
||||
@@ -0,0 +1,39 @@
|
||||
import { useEffect } from "react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
import { BoardApi } from "@/entities/board/@x/post";
|
||||
import { useAlertStore, useMenuStore } from "@/shared/lib";
|
||||
|
||||
function PostPageGuard({
|
||||
bbsId,
|
||||
children,
|
||||
}: {
|
||||
bbsId: string;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
const setBbsInfo = useMenuStore((state) => state.setBbsInfo);
|
||||
|
||||
const { data: boardInfo, isLoading } = useQuery({
|
||||
queryKey: [bbsId],
|
||||
queryFn: () => BoardApi.getBoardInfo(bbsId),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!boardInfo) return;
|
||||
setBbsInfo(boardInfo);
|
||||
}, [boardInfo]);
|
||||
|
||||
if (!isLoading && pathname && boardInfo) {
|
||||
if (!pathname.includes(boardInfo.bbsTypeCd.toLowerCase())) {
|
||||
alert("잘못된 경로로 접속하였습니다.", router.back);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
export { PostPageGuard };
|
||||
@@ -0,0 +1,11 @@
|
||||
export const deleteReasonMessages = {
|
||||
"저작권 침해":
|
||||
"타인의 저작물을 허락 없이 게시하는 경우 저작권 침해로 간주되어 삭제될 수 있습니다.",
|
||||
명예훼손: "타인의 명예를 훼손하는 내용의 게시물은 삭제될 수 있습니다.",
|
||||
"개인정보 노출": "타인의 개인정보를 노출하는 게시물도 삭제될 수 있습니다.",
|
||||
"불법 정보 유통":
|
||||
"불법적인 상품이나 서비스를 판매하거나 홍보하는 게시물은 삭제될 수 있습니다.",
|
||||
"욕설 및 비방":
|
||||
"심한 욕설이나 비방, 모욕적인 내용이 포함된 게시물은 삭제될 수 있습니다.",
|
||||
"광고성 정보": "지나치게 광고성이 짙은 게시물은 삭제될 수 있습니다.",
|
||||
};
|
||||
@@ -0,0 +1,119 @@
|
||||
import { z } from "zod";
|
||||
import type { PageableList, PageableParams } from "@/shared/model";
|
||||
|
||||
export interface PostParams extends PageableParams {
|
||||
keywordType?: string;
|
||||
keyword?: string;
|
||||
popupYn?: string;
|
||||
upndFixYn?: string;
|
||||
prdPstgYn?: string;
|
||||
siteId?: string;
|
||||
bbsTypeCd?: string;
|
||||
ansUseYn?: string;
|
||||
}
|
||||
|
||||
export interface MyPostParams extends PageableParams {
|
||||
keywordType?: string;
|
||||
keyword?: string;
|
||||
bbsId?: number | null;
|
||||
delYn?: string;
|
||||
frDateYmd?: string;
|
||||
toDateYmd?: string;
|
||||
}
|
||||
|
||||
export interface Post {
|
||||
rowNo: number;
|
||||
bbsId: number;
|
||||
pstNo: number;
|
||||
pstTtl: string;
|
||||
pstCn: string;
|
||||
inqNocs: number;
|
||||
rfrncUrl: string;
|
||||
popupYn: string;
|
||||
upndFixYn: string;
|
||||
prdPstgYn: string;
|
||||
rootPath: string;
|
||||
pstPath: string;
|
||||
ansPstn: number;
|
||||
wrtrNm: string;
|
||||
wrtrCplc: string;
|
||||
atflCd: string;
|
||||
regDt: string;
|
||||
rgtrNm: string;
|
||||
cmntCnt: number;
|
||||
}
|
||||
|
||||
export interface MyPost extends Post {
|
||||
bbsNm: string;
|
||||
bbsTypeCd: string;
|
||||
}
|
||||
|
||||
export interface PostInfo extends Post {
|
||||
pstCn: string;
|
||||
rgtr: string;
|
||||
mdfcnDt: string;
|
||||
mdfr: string;
|
||||
}
|
||||
|
||||
export interface MovePost {
|
||||
fromBbsId: number;
|
||||
toBbsId?: number;
|
||||
pstNo: number;
|
||||
}
|
||||
|
||||
export interface DeletePost {
|
||||
bbsId: number;
|
||||
pstNo: number;
|
||||
delRsn?: string;
|
||||
}
|
||||
|
||||
const postEtcSchema = z.object({
|
||||
bbsPstgTypeCd: z.string(),
|
||||
pstgPrdSeCd: z.string(),
|
||||
pstgBgngDt: z.string().nullish(),
|
||||
pstgEndDt: z.string().nullish(),
|
||||
});
|
||||
|
||||
export const postFormSchema = z.object({
|
||||
bbsId: z.number(),
|
||||
pstTtl: z.string().nonempty(),
|
||||
pstCn: z.string().nullish(),
|
||||
rfrncUrl: z.string().nullish(),
|
||||
popupYn: z.string().nullish(),
|
||||
popupYnEtc: z.array(postEtcSchema).nullish(),
|
||||
upndFixYn: z.string().nullish(),
|
||||
upndFixYnEtc: z.array(postEtcSchema).nullish(),
|
||||
prdPstgYn: z.string().nullish(),
|
||||
prdPstgYnEtc: z.array(postEtcSchema).nullish(),
|
||||
pstPswd: z.string(),
|
||||
wrtrNm: z.string().nullish(),
|
||||
wrtrCplc: z.string().nullish(),
|
||||
atflCd: z.string().nullish(),
|
||||
parentPstNo: z.number().nullish(),
|
||||
});
|
||||
|
||||
export const postUpdateFormSchema = postFormSchema.omit({
|
||||
bbsId: true,
|
||||
parentPstNo: true,
|
||||
});
|
||||
|
||||
export type PostList = PageableList<Post>;
|
||||
export type MyPostList = PageableList<MyPost>;
|
||||
export type PostFormData = z.infer<typeof postFormSchema>;
|
||||
export type PostUpdateFormData = z.infer<typeof postUpdateFormSchema>;
|
||||
|
||||
export interface PostService {
|
||||
getPostList(bbsId: number, params: PostParams): Promise<PostList>;
|
||||
getMyPostList(params: MyPostParams): Promise<MyPostList>;
|
||||
getPostInfo(bbsId: number, pstNo: number): Promise<PostInfo>;
|
||||
createPost(data: PostFormData): Promise<Post>;
|
||||
updatePost(
|
||||
bbsId: number,
|
||||
pstNo: number,
|
||||
data: PostUpdateFormData,
|
||||
): Promise<Post>;
|
||||
deletePost(bbsId: number, pstNo: number, delRsn?: string): Promise<void>;
|
||||
softDeletePost(data: DeletePost[]): Promise<void>;
|
||||
hardDeletePost(data: DeletePost[]): Promise<void>;
|
||||
movePost(data: MovePost[]): Promise<void>;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import type { Dashboard, DashboardService } from "../model/dashboard-interface";
|
||||
|
||||
export class DashboardApiService implements DashboardService {
|
||||
public async getDashboard(): Promise<Dashboard> {
|
||||
const response = await client.get<Dashboard>(
|
||||
ENDPOINT.CMS_SERVICE.DASHBOARD,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
export const DashboardApi = new DashboardApiService();
|
||||
@@ -0,0 +1,212 @@
|
||||
#mapArea {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.stage {
|
||||
--map-inset: 7.5%;
|
||||
aspect-ratio: 0.72/1;
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
position: relative;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.bgLayer {
|
||||
position: absolute;
|
||||
inset: var(--map-inset);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1;
|
||||
width: calc(100% - var(--map-inset) * 2);
|
||||
height: calc(100% - var(--map-inset) * 2);
|
||||
background-image: url("/images/region_map_bg.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-position: center center;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
opacity: 0.7;
|
||||
filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.02));
|
||||
pointer-events: none;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.svgLayer {
|
||||
position: absolute;
|
||||
inset: var(--map-inset);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2;
|
||||
width: calc(100% - var(--map-inset) * 2);
|
||||
height: calc(100% - var(--map-inset) * 2);
|
||||
}
|
||||
|
||||
.svgLayer > svg {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: auto;
|
||||
height: auto;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: crisp-edges;
|
||||
shape-rendering: geometricPrecision;
|
||||
}
|
||||
|
||||
/* SVG 스타일을 위한 컨테이너 */
|
||||
.svgContainer :global(svg) :global(path) {
|
||||
fill: rgba(0, 150, 255, 0.2) !important;
|
||||
stroke: #0066cc;
|
||||
stroke-width: 1;
|
||||
vector-effect: non-scaling-stroke;
|
||||
}
|
||||
|
||||
.svgContainer :global(svg) :global(.cls-1) {
|
||||
fill: rgba(0, 150, 255, 0.2) !important;
|
||||
stroke: #0066cc;
|
||||
stroke-width: 1;
|
||||
vector-effect: non-scaling-stroke;
|
||||
}
|
||||
|
||||
.svgContainer :global(svg) :global(.basin) {
|
||||
opacity: 0;
|
||||
pointer-events: all;
|
||||
transition: opacity 0.15s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.svgContainer :global(svg) :global(.basin.active),
|
||||
.svgContainer :global(svg) :global(.basin:hover) {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.svgContainer :global(svg) :global(.basin) :global(path),
|
||||
.svgContainer :global(svg) :global(.basin) :global(polygon),
|
||||
.svgContainer :global(svg) :global(.basin) :global(polyline) {
|
||||
fill: rgba(0, 209, 209, 0.5);
|
||||
stroke: #399AC3;
|
||||
stroke-width: 1.3;
|
||||
vector-effect: non-scaling-stroke;
|
||||
}
|
||||
|
||||
/* 팝업 + 배지 */
|
||||
.popup {
|
||||
position: absolute;
|
||||
width: 300px;
|
||||
height: 150px;
|
||||
min-width: 220px;
|
||||
background: #fff;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 10px;
|
||||
box-shadow:
|
||||
0 12px 24px rgba(0, 0, 0, 0.18),
|
||||
0 2px 0 rgba(0, 0, 0, 0.05);
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translate(-50%, -8px) scale(0.98);
|
||||
transition:
|
||||
opacity 0.12s,
|
||||
visibility 0.12s,
|
||||
transform 0.12s;
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
}
|
||||
.popup.show {
|
||||
opacity: 1 !important;
|
||||
visibility: visible !important;
|
||||
transform: translate(-50%, -12px) scale(1) !important;
|
||||
}
|
||||
|
||||
.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
.popup .head {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
background: #d1ecfa;
|
||||
border-bottom: 1px solid #c8e4f3;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
}
|
||||
.popup .head > div {
|
||||
padding: 10px 12px;
|
||||
text-align: center;
|
||||
}
|
||||
.popup .body {
|
||||
padding: 6px 10px 8px;
|
||||
}
|
||||
.popup td {
|
||||
padding: 8px 10px;
|
||||
border-bottom: 1px solid #eef2f7;
|
||||
font-size: 14px;
|
||||
}
|
||||
.popup .arrow {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: -8px;
|
||||
transform: translateX(-50%);
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 10px solid transparent;
|
||||
border-right: 10px solid transparent;
|
||||
border-top: 10px solid #fff;
|
||||
filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.1));
|
||||
}
|
||||
.badge {
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
padding: 6px 10px;
|
||||
border-radius: 8px;
|
||||
background: #1e40af;
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
transform: translate(-50%, -50%);
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.22);
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.12s, visibility 0.12s;
|
||||
}
|
||||
.badge.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* 권역 라벨 */
|
||||
.labelsLayer {
|
||||
position: absolute;
|
||||
inset: var(--map-inset);
|
||||
pointer-events: none;
|
||||
z-index: 3;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.basinLabel {
|
||||
position: absolute;
|
||||
transform: translate(-50%, -50%);
|
||||
pointer-events: none;
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
background: #ffffffee;
|
||||
border: 2px solid #d0d0d0;
|
||||
white-space: nowrap;
|
||||
min-width: 60px;
|
||||
text-align: center;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.basinLabel.active {
|
||||
background: #006bf8;
|
||||
color: #fff;
|
||||
border-color: #96c3ff;
|
||||
box-shadow: 0 4px 12px rgba(0, 107, 248, 0.3);
|
||||
}
|
||||
@@ -0,0 +1,425 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import styles from "./KoreaBasinMap.module.css"; // 추가
|
||||
|
||||
const SVG_URL = "/images/region_map.svg"; // public 폴더에 region_map.svg 위치 필요
|
||||
|
||||
const MANUAL_LABEL_POS = {
|
||||
han: { x: 0.52, y: 0.14 },
|
||||
geum: { x: 0.28, y: 0.47 },
|
||||
nakdong: { x: 0.64, y: 0.47 },
|
||||
yeongsan: { x: 0.18, y: 0.77 },
|
||||
};
|
||||
|
||||
const BASIN_DATA = {
|
||||
han: {
|
||||
name: "한강",
|
||||
colTitle: "시설수",
|
||||
rows: [
|
||||
["500m³ 미만", 100000000],
|
||||
["500m³ 이상", 100000000],
|
||||
],
|
||||
},
|
||||
geum: {
|
||||
name: "금강",
|
||||
colTitle: "시설수",
|
||||
rows: [
|
||||
["500m³ 미만", 100000000],
|
||||
["500m³ 이상", 100000000],
|
||||
],
|
||||
},
|
||||
nakdong: {
|
||||
name: "낙동강",
|
||||
colTitle: "시설수",
|
||||
rows: [
|
||||
["500m³ 미만", 100000000],
|
||||
["500m³ 이상", 100000000],
|
||||
],
|
||||
},
|
||||
yeongsan: {
|
||||
name: "영산강",
|
||||
colTitle: "시설수",
|
||||
rows: [
|
||||
["500m³ 미만", 100000000],
|
||||
["500m³ 이상", 100000000],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const BASIN_IDS = [
|
||||
{ key: "han", labels: ["한강", "han"] },
|
||||
{ key: "geum", labels: ["금강", "geum"] },
|
||||
{ key: "nakdong", labels: ["낙동강", "nakdong"] },
|
||||
{ key: "yeongsan", labels: ["영산강", "yeongsan"] },
|
||||
];
|
||||
|
||||
function fmt(n: number) {
|
||||
return new Intl.NumberFormat("ko-KR").format(n);
|
||||
}
|
||||
|
||||
export function KoreaBasinMap() {
|
||||
const stageRef = useRef<HTMLDivElement>(null);
|
||||
const svgLayerRef = useRef<HTMLDivElement>(null);
|
||||
const labelsLayerRef = useRef<HTMLDivElement>(null);
|
||||
const popupRef = useRef<HTMLDivElement>(null);
|
||||
const badgeRef = useRef<HTMLDivElement>(null);
|
||||
const rowsRef = useRef<HTMLTableSectionElement>(null);
|
||||
const colTitleRef = useRef<HTMLTableCellElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let svg: SVGSVGElement | null = null;
|
||||
let gs: SVGGElement[] = [];
|
||||
let labels: HTMLDivElement[] = [];
|
||||
|
||||
console.log("Loading SVG from:", SVG_URL);
|
||||
fetch(SVG_URL)
|
||||
.then((r) => {
|
||||
console.log("SVG fetch response:", r.status, r.statusText);
|
||||
if (!r.ok) throw new Error(`HTTP error! status: ${r.status}`);
|
||||
return r.text();
|
||||
})
|
||||
.then((txt) => {
|
||||
console.log("SVG content loaded, length:", txt.length);
|
||||
if (!svgLayerRef.current) {
|
||||
console.error("svgLayerRef.current is null");
|
||||
return;
|
||||
}
|
||||
svgLayerRef.current.innerHTML = txt;
|
||||
svg = svgLayerRef.current.querySelector("svg");
|
||||
if (!svg) {
|
||||
console.error("SVG element not found in loaded content");
|
||||
return;
|
||||
}
|
||||
console.log("SVG element found:", svg);
|
||||
|
||||
// viewBox/크기 세팅
|
||||
if (!svg.hasAttribute("viewBox")) {
|
||||
const bb = svg.getBBox();
|
||||
svg.setAttribute(
|
||||
"viewBox",
|
||||
[bb.x, bb.y, bb.width, bb.height].join(" "),
|
||||
);
|
||||
}
|
||||
const vb = (svg.getAttribute("viewBox") || "").split(/\s+/).map(Number);
|
||||
if (vb.length === 4 && vb[3]! > 0 && stageRef.current) {
|
||||
stageRef.current!.style.aspectRatio = String(vb[2]! / vb[3]!);
|
||||
}
|
||||
svg!.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
||||
svg.style.width = "100%";
|
||||
svg.style.height = "100%";
|
||||
|
||||
// 1) 지도 그룹 수집
|
||||
gs = [];
|
||||
console.log("Looking for basin groups in SVG...");
|
||||
BASIN_IDS.forEach((item) => {
|
||||
let g: SVGGElement | null = null;
|
||||
for (const id of item.labels) {
|
||||
g = svg!.getElementById(id) as SVGGElement | null;
|
||||
if (g) {
|
||||
console.log(`Found group for ${item.key} with id '${id}':`, g);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!g) {
|
||||
console.warn(`No group found for ${item.key} with labels:`, item.labels);
|
||||
return;
|
||||
}
|
||||
g.classList.add("basin");
|
||||
(g as SVGGElement & { dataset: { key: string; label: string } }).dataset.key = item.key;
|
||||
(g as SVGGElement & { dataset: { key: string; label: string } }).dataset.label = item.labels[0] || '';
|
||||
|
||||
// 패스에 기본 스타일 적용
|
||||
const paths = g.querySelectorAll('path');
|
||||
paths.forEach((path) => {
|
||||
path.style.fill = 'rgba(0, 150, 255, 0.2)';
|
||||
path.style.stroke = '#0066cc';
|
||||
path.style.strokeWidth = '1';
|
||||
path.style.vectorEffect = 'non-scaling-stroke';
|
||||
});
|
||||
|
||||
gs.push(g);
|
||||
});
|
||||
console.log(`Found ${gs.length} basin groups`);
|
||||
|
||||
// 각 유역 그룹의 패스 정보 확인
|
||||
gs.forEach((g, index) => {
|
||||
const paths = g.querySelectorAll('path');
|
||||
console.log(`Group ${index} (${(g as SVGGElement & { dataset: { key: string } }).dataset.key}):`, {
|
||||
element: g,
|
||||
pathCount: paths.length,
|
||||
paths: Array.from(paths).map(p => ({
|
||||
className: p.className.baseVal,
|
||||
d: p.getAttribute('d')?.substring(0, 50) + '...'
|
||||
}))
|
||||
});
|
||||
});
|
||||
|
||||
// 2) 함수들 먼저 정의
|
||||
const clear = () => {
|
||||
gs.forEach((el) => el.classList.remove("active"));
|
||||
if (popupRef.current) {
|
||||
if (styles.show) {
|
||||
popupRef.current.classList.remove(styles.show);
|
||||
}
|
||||
popupRef.current.style.opacity = "0";
|
||||
popupRef.current.style.visibility = "hidden";
|
||||
}
|
||||
if (badgeRef.current) {
|
||||
if (styles.show) {
|
||||
badgeRef.current.classList.remove(styles.show);
|
||||
}
|
||||
badgeRef.current.style.opacity = "0";
|
||||
badgeRef.current.style.visibility = "hidden";
|
||||
}
|
||||
labels.forEach((l) => l.classList.remove("active"));
|
||||
};
|
||||
|
||||
function showFor(g: SVGGElement) {
|
||||
console.log("showFor called for:", g);
|
||||
const key = (g as SVGGElement & { dataset: { key: string; label: string } }).dataset.key;
|
||||
const data = (BASIN_DATA as Record<string, { name: string; colTitle: string; rows: (string | number)[][] }>)[key] || {
|
||||
name: (g as SVGGElement & { dataset: { label: string } }).dataset.label,
|
||||
colTitle: "",
|
||||
rows: [],
|
||||
};
|
||||
console.log("Data for popup:", data);
|
||||
|
||||
if (badgeRef.current) badgeRef.current.textContent = data.name;
|
||||
if (colTitleRef.current)
|
||||
colTitleRef.current.textContent = data.colTitle || "???";
|
||||
if (rowsRef.current)
|
||||
rowsRef.current.innerHTML = data.rows
|
||||
.map(
|
||||
(r: (string | number)[]) =>
|
||||
`<tr><td>${r[0]}</td><td style="text-align:right">${fmt(Number(r[1]) || 0)}</td></tr>`,
|
||||
)
|
||||
.join("");
|
||||
|
||||
if (!stageRef.current) return;
|
||||
const sRect = stageRef.current.getBoundingClientRect(),
|
||||
r = g.getBoundingClientRect();
|
||||
const cx = (r.left + r.right) / 2 - sRect.left;
|
||||
const ty = r.top - sRect.top;
|
||||
|
||||
console.log("Popup position:", { cx, ty });
|
||||
|
||||
if (badgeRef.current) {
|
||||
badgeRef.current.style.left = cx + "px";
|
||||
badgeRef.current.style.top = ty + 24 + "px";
|
||||
}
|
||||
if (popupRef.current) {
|
||||
popupRef.current.style.left = cx + "px";
|
||||
popupRef.current.style.top = ty + 6 + "px";
|
||||
popupRef.current.style.opacity = "1";
|
||||
popupRef.current.style.visibility = "visible";
|
||||
if (styles.show) {
|
||||
popupRef.current.classList.add(styles.show);
|
||||
}
|
||||
console.log("Added show class to popup:", popupRef.current.classList.toString());
|
||||
}
|
||||
if (badgeRef.current && styles.show) {
|
||||
badgeRef.current.classList.add(styles.show);
|
||||
}
|
||||
|
||||
if (popupRef.current) {
|
||||
const pRect = popupRef.current.getBoundingClientRect();
|
||||
const x = Math.max(
|
||||
12 + pRect.width / 2,
|
||||
Math.min(cx, sRect.width - 12 - pRect.width / 2),
|
||||
);
|
||||
popupRef.current.style.left = x + "px";
|
||||
if (badgeRef.current) badgeRef.current.style.left = x + "px";
|
||||
}
|
||||
}
|
||||
|
||||
function showForWithLabel(g: SVGGElement) {
|
||||
console.log("showForWithLabel called for:", g);
|
||||
showFor(g);
|
||||
const idx = gs.indexOf(g);
|
||||
labels.forEach((l) => l.classList.remove("active"));
|
||||
if (idx >= 0) labels[idx]!.classList.add("active");
|
||||
}
|
||||
|
||||
// 3) 라벨 DOM 생성
|
||||
labels = [];
|
||||
if (labelsLayerRef.current) {
|
||||
labelsLayerRef.current.innerHTML = "";
|
||||
gs.forEach((g) => {
|
||||
const el = document.createElement("div");
|
||||
el.className = styles.basinLabel || '';
|
||||
el.textContent = (g as SVGGElement & { dataset: { label: string } }).dataset.label || '';
|
||||
labelsLayerRef.current!.appendChild(el);
|
||||
labels.push(el);
|
||||
});
|
||||
}
|
||||
|
||||
// 3) 라벨 위치
|
||||
function positionLabels() {
|
||||
if (!stageRef.current || !svg) return;
|
||||
const sRect = stageRef.current.getBoundingClientRect();
|
||||
const inset =
|
||||
parseFloat(
|
||||
getComputedStyle(stageRef.current).getPropertyValue(
|
||||
"--map-inset",
|
||||
) || "0",
|
||||
) / 100;
|
||||
const left = sRect.width * inset,
|
||||
top = sRect.height * inset;
|
||||
const w = sRect.width * (1 - inset * 2),
|
||||
h = sRect.height * (1 - inset * 2);
|
||||
const [vx, vy, vw, vh] = (
|
||||
svg!.getAttribute("viewBox") || "0 0 100 100"
|
||||
)
|
||||
.split(/\s+/)
|
||||
.map(Number);
|
||||
|
||||
const svgRect = svg.getBoundingClientRect();
|
||||
const stageRect = stageRef.current.getBoundingClientRect();
|
||||
const offsetX = svgRect.left - stageRect.left - left;
|
||||
const offsetY = svgRect.top - stageRect.top - top;
|
||||
|
||||
gs.forEach((g, i) => {
|
||||
const key = (g as SVGGElement & { dataset: { key: string } }).dataset.key;
|
||||
const manual = (MANUAL_LABEL_POS as Record<string, { x?: number; y?: number; px?: number; py?: number }>)[key];
|
||||
let px, py;
|
||||
if (
|
||||
manual &&
|
||||
(("x" in manual && "y" in manual) ||
|
||||
("px" in manual && "py" in manual))
|
||||
) {
|
||||
if ("px" in manual) {
|
||||
px = left + (manual.px || 0) + offsetX;
|
||||
py = top + (manual.py || 0) + offsetY;
|
||||
} else {
|
||||
px = left + w * (manual.x || 0) + offsetX;
|
||||
py = top + h * (manual.y || 0) + offsetY;
|
||||
}
|
||||
} else {
|
||||
const b = g.getBBox();
|
||||
const cx = b.x + b.width / 2,
|
||||
cy = b.y + b.height / 2;
|
||||
px = ((cx - vx!) / vw!) * w + left + offsetX;
|
||||
py = ((cy - vy!) / vh!) * h + top + offsetY;
|
||||
}
|
||||
labels[i]!.style.left = `${px}px`;
|
||||
labels[i]!.style.top = `${py + 18}px`;
|
||||
});
|
||||
}
|
||||
|
||||
// 4) 상호작용 (함수들은 이미 위에서 정의됨)
|
||||
gs.forEach((g) => {
|
||||
g.addEventListener("mouseenter", () => {
|
||||
clear();
|
||||
g.classList.add("active");
|
||||
showForWithLabel(g);
|
||||
});
|
||||
g.addEventListener("mousemove", () => {
|
||||
if (g.classList.contains("active")) showForWithLabel(g);
|
||||
});
|
||||
g.addEventListener("mouseleave", clear);
|
||||
g.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
clear();
|
||||
g.classList.add("active");
|
||||
showForWithLabel(g);
|
||||
});
|
||||
});
|
||||
if (stageRef.current) {
|
||||
stageRef.current.addEventListener("mouseleave", clear);
|
||||
stageRef.current.addEventListener("click", () => clear());
|
||||
}
|
||||
|
||||
// 5) 실행
|
||||
positionLabels();
|
||||
window.addEventListener("resize", positionLabels);
|
||||
new window.ResizeObserver(positionLabels).observe(stageRef.current!);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error loading SVG:", error);
|
||||
if (svgLayerRef.current)
|
||||
svgLayerRef.current.innerHTML =
|
||||
`<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #666; font-size: 14px;">지도를 불러올 수 없습니다. (${error.message})</div>`;
|
||||
});
|
||||
|
||||
// cleanup
|
||||
return () => {
|
||||
window.removeEventListener("resize", () => {});
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 스타일은 필요에 따라 tailwind, css 등으로 커스터마이즈하세요.
|
||||
return (
|
||||
<div
|
||||
ref={stageRef}
|
||||
id="stage"
|
||||
style={
|
||||
{
|
||||
width: "100%",
|
||||
height: "560px",
|
||||
position: "relative",
|
||||
zIndex: 20,
|
||||
"--map-inset": "0",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
>
|
||||
<div
|
||||
className={styles.bgLayer}
|
||||
id="bgLayer"
|
||||
/>
|
||||
<div
|
||||
ref={svgLayerRef}
|
||||
id="svgLayer"
|
||||
className={`${styles.svgLayer} ${styles.svgContainer}`}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
/>
|
||||
<div
|
||||
ref={labelsLayerRef}
|
||||
id="labelsLayer"
|
||||
className={styles.labelsLayer}
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
ref={badgeRef}
|
||||
id="badge"
|
||||
className={styles.badge}
|
||||
style={{ position: "absolute", zIndex: 10, display: "block" }}
|
||||
/>
|
||||
<div
|
||||
ref={popupRef}
|
||||
id="popup"
|
||||
className={styles.popup}
|
||||
style={{
|
||||
position: "absolute",
|
||||
zIndex: 20,
|
||||
background: "#fff",
|
||||
border: "1px solid #ccc",
|
||||
borderRadius: 8,
|
||||
padding: 12,
|
||||
minWidth: 160,
|
||||
boxShadow: "0 2px 8px #0002",
|
||||
display: "block",
|
||||
opacity: 0,
|
||||
visibility: "hidden",
|
||||
}}
|
||||
>
|
||||
<table style={{ width: "100%" }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>구분</th>
|
||||
<th ref={colTitleRef} id="colTitle">
|
||||
시설수
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody ref={rowsRef} id="rows"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
import { type ChartData, type ChartOptions } from "chart.js";
|
||||
|
||||
const commonData = {
|
||||
labels: ["1", "2", "3", "4", "5", "6", "7"],
|
||||
datasets: [
|
||||
{
|
||||
fill: true,
|
||||
pointRadius: 0,
|
||||
tension: 0.5,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const commonOptions = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
display: false,
|
||||
},
|
||||
y: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const chartData: Record<
|
||||
string,
|
||||
{ data: ChartData<"line" | "bar">; options: ChartOptions<"line" | "bar"> }
|
||||
> = {
|
||||
memberChartData: {
|
||||
data: {
|
||||
...commonData,
|
||||
datasets: [
|
||||
{
|
||||
...commonData.datasets[0],
|
||||
data: [8, 10, 7, 12, 9, 13, 12],
|
||||
borderColor: "rgba(255, 255, 255, 0.6)",
|
||||
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
...commonOptions,
|
||||
scales: {
|
||||
...commonOptions.scales,
|
||||
y: {
|
||||
...commonOptions.scales.y,
|
||||
min: 5,
|
||||
max: 15,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
postChartData: {
|
||||
data: {
|
||||
...commonData,
|
||||
datasets: [
|
||||
{
|
||||
...commonData.datasets[0],
|
||||
data: [5200, 5350, 5450, 5520, 5600, 5650, 5678],
|
||||
borderColor: "rgba(86, 138, 255, 1)",
|
||||
backgroundColor: "rgba(86, 138, 255, 0.1)",
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
...commonOptions,
|
||||
},
|
||||
},
|
||||
visitorChartData: {
|
||||
data: {
|
||||
...commonData,
|
||||
datasets: [
|
||||
{
|
||||
...commonData.datasets[0],
|
||||
data: [1800, 2100, 1950, 2300, 2150, 2250, 2345],
|
||||
borderColor: "rgba(149, 131, 252)",
|
||||
backgroundColor: "rgba(149, 131, 252, 0.1)",
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
...commonOptions,
|
||||
},
|
||||
},
|
||||
apiChartData: {
|
||||
data: {
|
||||
...commonData,
|
||||
datasets: [
|
||||
{
|
||||
...commonData.datasets[0],
|
||||
data: [41000, 42500, 43200, 44100, 44800, 45200, 45678],
|
||||
borderColor: "rgba(220, 103, 206)",
|
||||
backgroundColor: "rgba(220, 103, 206, 0.1)",
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
...commonOptions,
|
||||
},
|
||||
},
|
||||
siteAccessChartData: {
|
||||
data: {
|
||||
labels: Array.from({ length: 24 }, (_, i) =>
|
||||
i.toString().padStart(2, "0"),
|
||||
),
|
||||
datasets: [],
|
||||
},
|
||||
options: {
|
||||
...commonOptions,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: "top",
|
||||
},
|
||||
tooltip: {
|
||||
mode: "index",
|
||||
intersect: false,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
text: "시간대",
|
||||
},
|
||||
},
|
||||
y: {
|
||||
title: {
|
||||
text: "접속자 수",
|
||||
},
|
||||
beginAtZero: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
menuAccessChartData: {
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [],
|
||||
},
|
||||
options: {
|
||||
...commonOptions,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: "top",
|
||||
},
|
||||
tooltip: {
|
||||
mode: "index",
|
||||
intersect: false,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
text: "메뉴명",
|
||||
},
|
||||
},
|
||||
y: {
|
||||
title: {
|
||||
text: "접속 횟수",
|
||||
},
|
||||
beginAtZero: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
export interface SiteStatisticsContent {
|
||||
siteId: string;
|
||||
siteNm: string;
|
||||
accessHour: string;
|
||||
accessCnt: number;
|
||||
}
|
||||
|
||||
export interface MenuStatisticsContent {
|
||||
menuCd: number;
|
||||
menuNm: string;
|
||||
accessCnt: number;
|
||||
}
|
||||
|
||||
export interface Dashboard {
|
||||
memberTotCnt: number;
|
||||
memberTodayCnt: number;
|
||||
pstTotCnt: number;
|
||||
pstTodayCnt: number;
|
||||
accessTodayCnt: number;
|
||||
accessBefDayPer: number;
|
||||
apiTodayCnt: number;
|
||||
waitMemberCnt: number;
|
||||
waitCntnCnt: number;
|
||||
notiList: [];
|
||||
schdlList: [];
|
||||
siteAccessList: SiteStatisticsContent[];
|
||||
menuAccessList: MenuStatisticsContent[];
|
||||
}
|
||||
|
||||
export interface DashboardService {
|
||||
getDashboard(): Promise<Dashboard>;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import dayjs from "dayjs";
|
||||
import type { ColumnDef } from "@tanstack/react-table";
|
||||
import { Badge } from "@common/components";
|
||||
import type { Post, MyPost } from "@/entities/post";
|
||||
|
||||
const noticePostTableColumns: ColumnDef<Post>[] = [
|
||||
{
|
||||
header: "번호",
|
||||
cell: ({ row, table }) => {
|
||||
if (row.original.upndFixYn === "Y") {
|
||||
return (
|
||||
<Badge
|
||||
color="orange"
|
||||
className="flex size-8 items-center justify-center"
|
||||
>
|
||||
<i className="diveicon di-volume-up-fill" />
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
const totalRows = table.getRowCount();
|
||||
const currentPage = table.getState().pagination.pageIndex;
|
||||
const pageSize = table.getState().pagination.pageSize;
|
||||
return totalRows - (currentPage * pageSize + row.index);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "pstTtl",
|
||||
header: "제목",
|
||||
},
|
||||
{
|
||||
accessorKey: "wrtrNm",
|
||||
header: "작성자",
|
||||
},
|
||||
{
|
||||
accessorKey: "regDt",
|
||||
header: "작성일",
|
||||
cell: ({ row }) => dayjs(row.original.regDt).format("YYYY-MM-DD"),
|
||||
},
|
||||
{
|
||||
accessorKey: "inqNocs",
|
||||
header: "조회수",
|
||||
},
|
||||
];
|
||||
|
||||
const myPostTableColumns: ColumnDef<MyPost>[] = [
|
||||
{
|
||||
header: "번호",
|
||||
cell: ({ row, table }) => {
|
||||
const totalRows = table.getRowCount();
|
||||
const currentPage = table.getState().pagination.pageIndex;
|
||||
const pageSize = table.getState().pagination.pageSize;
|
||||
return totalRows - (currentPage * pageSize + row.index);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "pstTtl",
|
||||
header: "제목",
|
||||
},
|
||||
{
|
||||
accessorKey: "wrtrNm",
|
||||
header: "작성자",
|
||||
},
|
||||
{
|
||||
accessorKey: "regDt",
|
||||
header: "작성일",
|
||||
cell: ({ row }) => dayjs(row.original.regDt).format("YYYY-MM-DD"),
|
||||
},
|
||||
{
|
||||
accessorKey: "inqNocs",
|
||||
header: "조회수",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
export { noticePostTableColumns, myPostTableColumns };
|
||||
@@ -1,9 +1,36 @@
|
||||
"use client";
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { tokenManager } from '@/entities/auth/lib/token-manager';
|
||||
import { client } from '@/shared/api';
|
||||
import { ENDPOINT } from '@/shared/config';
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { tokenManager } from "@/entities/auth/lib/token-manager";
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { KoreaBasinMap } from "../lib/KoreaBasinMap";
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
LineElement,
|
||||
BarElement,
|
||||
Filler,
|
||||
Legend,
|
||||
Tooltip,
|
||||
ArcElement,
|
||||
} from "chart.js";
|
||||
import { Doughnut } from "react-chartjs-2";
|
||||
|
||||
// Chart.js 등록
|
||||
ChartJS.register(
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
LineElement,
|
||||
BarElement,
|
||||
Filler,
|
||||
Legend,
|
||||
Tooltip,
|
||||
ArcElement
|
||||
);
|
||||
|
||||
interface UserInfo {
|
||||
email?: string;
|
||||
@@ -14,124 +41,258 @@ interface UserInfo {
|
||||
|
||||
function DashboardPage() {
|
||||
const [userInfo, setUserInfo] = useState<UserInfo | null>(null);
|
||||
const [error, setError] = useState('');
|
||||
const [error, setError] = useState("");
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchUserInfo = async () => {
|
||||
console.log('fetchUserInfo called');
|
||||
|
||||
const fetchUserInfo = async () => {
|
||||
console.log("fetchUserInfo called");
|
||||
|
||||
try {
|
||||
// tokenManager를 통해 토큰 확인
|
||||
const accessToken = tokenManager.getToken('Authorization');
|
||||
const userId = tokenManager.getToken('token-id');
|
||||
|
||||
const accessToken = tokenManager.getToken("Authorization");
|
||||
const userId = tokenManager.getToken("token-id");
|
||||
|
||||
if (!accessToken || !userId) {
|
||||
console.log('No tokens found, redirecting to login');
|
||||
setError('로그인이 필요합니다.');
|
||||
router.push('/auth/login');
|
||||
console.log("No tokens found, redirecting to login");
|
||||
setError("로그인이 필요합니다.");
|
||||
router.push("/auth/login");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Fetching user info with userId:', userId);
|
||||
|
||||
console.log("Fetching user info with userId:", userId);
|
||||
|
||||
// client를 사용하여 API 호출 (자동 토큰 처리)
|
||||
const response = await client.get(`${ENDPOINT.USER_SERVICE.USERS}/${userId}`);
|
||||
|
||||
const response = await client.get(
|
||||
`${ENDPOINT.USER_SERVICE.USERS}/${userId}`,
|
||||
);
|
||||
|
||||
if (response.data) {
|
||||
console.log('User info received:', response.data);
|
||||
console.log("User info received:", response.data);
|
||||
setUserInfo(response.data);
|
||||
} else {
|
||||
setError('사용자 정보를 불러올 수 없습니다.');
|
||||
setError("사용자 정보를 불러올 수 없습니다.");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching user info:', error);
|
||||
if (error instanceof Error && error.message.includes('401')) {
|
||||
setError('인증이 만료되었습니다. 다시 로그인해주세요.');
|
||||
console.error("Error fetching user info:", error);
|
||||
if (error instanceof Error && error.message.includes("401")) {
|
||||
setError("인증이 만료되었습니다. 다시 로그인해주세요.");
|
||||
tokenManager.clearAuthToken();
|
||||
router.push('/auth/login');
|
||||
router.push("/auth/login");
|
||||
} else {
|
||||
setError('네트워크 오류가 발생했습니다.');
|
||||
setError("네트워크 오류가 발생했습니다.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
fetchUserInfo();
|
||||
}, [router]);
|
||||
|
||||
const handleLogout = () => {
|
||||
console.log('Logging out...');
|
||||
console.log("Logging out...");
|
||||
// localStorage 정리
|
||||
localStorage.removeItem('tempToken');
|
||||
localStorage.removeItem("tempToken");
|
||||
// tokenManager를 통해 쿠키 정리
|
||||
tokenManager.clearAuthToken();
|
||||
router.push('/auth/logout');
|
||||
router.push("/auth/logout");
|
||||
};
|
||||
|
||||
const handleChangePassword = () => {
|
||||
router.push('/otp?next=change-password');
|
||||
const handleChangePassword = () => {
|
||||
router.push("/otp?next=change-password");
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-6">
|
||||
<div className="flex flex-col gap-1">
|
||||
{/* 첫번째 라인 */}
|
||||
<div className="grid grid-cols-7 gap-1">
|
||||
{/* 총 회원수 카드 */}
|
||||
<div className="card card-border h-80 !p-0 col-span-2">
|
||||
|
||||
|
||||
<div className="grid grid-cols-8 gap-1">
|
||||
{/* 첫번쨰 열 */}
|
||||
<div className="col-span-2 h-250 !p-0">
|
||||
{/* 전국 하수처리시설 가동률 */}
|
||||
<div className="card card-border">
|
||||
<div className="card-header text-foreground">
|
||||
<h3 className="text-2xl font-medium">전국 하수처리시설 가동률</h3>
|
||||
</div>
|
||||
<div className="h-60 p-4">
|
||||
<Doughnut
|
||||
data={{
|
||||
datasets: [{
|
||||
data: [75, 25], // 75% 가동률
|
||||
backgroundColor: ['#00DFE5', '#f5f5f5'],
|
||||
borderWidth: 0
|
||||
}]
|
||||
}}
|
||||
options={{
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
cutout: '70%',
|
||||
circumference: 180, // 반원
|
||||
rotation: -90, // 왼쪽에서 시작
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
}}
|
||||
plugins={[{
|
||||
id: 'centerText',
|
||||
afterDraw: (chart) => {
|
||||
const ctx = chart.ctx;
|
||||
const centerX = chart.width / 2;
|
||||
const centerY = chart.height / 2;
|
||||
|
||||
// 가동률 텍스트
|
||||
ctx.save();
|
||||
ctx.font = 'bold 24px Arial';
|
||||
ctx.fillStyle = '#00DFE5';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText('75%', centerX, centerY + 10);
|
||||
|
||||
// 라벨 텍스트
|
||||
ctx.font = '12px Arial';
|
||||
ctx.fillStyle = '#666';
|
||||
ctx.fillText('가동률', centerX, centerY + 30);
|
||||
ctx.restore();
|
||||
}
|
||||
}]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 오수관로 및 우수관로 현황 */}
|
||||
<div className="card card-border">
|
||||
<div className="card-header text-foreground">
|
||||
<h3 className="text-2xl font-medium">오수관로 및 우수관로 현황</h3>
|
||||
</div>
|
||||
<div className="h-60 p-4"></div>
|
||||
</div>
|
||||
|
||||
{/* 하수처리수 재이용 */}
|
||||
<div className="card card-border">
|
||||
<div className="card-header text-foreground">
|
||||
<h3 className="text-2xl font-medium">하수처리수 재이용</h3>
|
||||
</div>
|
||||
<div className="h-60 p-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
{/* 전체 게시물 카드 */}
|
||||
<div className="card card-border h-80 !p-0 col-span-2">
|
||||
|
||||
{/* 두번쨰 열 */}
|
||||
<div className="col-span-2 h-250 !p-0">
|
||||
{/* 하수처리시설(개소) */}
|
||||
<div className="card card-border">
|
||||
<div className="card-header text-foreground">
|
||||
<h3 className="text-2xl font-medium">하수처리시설(개소)</h3>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-1 h-60 !p-0">
|
||||
<div className="card card-border">
|
||||
<div className="card-header text-foreground text-center">
|
||||
<h3 className="text-l font-medium" style={{textAlign: "center", width: "100%"}}>500㎥ 미만(개소)</h3>
|
||||
</div>
|
||||
<div style={{fontSize: "38px", textAlign: "center", fontWeight: "600", lineHeight: "1.2", color: "#0ec58a", padding: "2px 0"}}>3,567 <span style={{fontSize: "14px", color: "#000000"}}>개소</span></div>
|
||||
</div>
|
||||
<div className="card card-border">
|
||||
<div className="card-header text-foreground text-center">
|
||||
<h3 className="text-l font-medium" style={{textAlign: "center", width: "100%"}}>500㎥ 이상(개소)</h3>
|
||||
</div>
|
||||
<div style={{fontSize: "38px", textAlign: "center", fontWeight: "600", lineHeight: "1.2", color: "#0ec58a", padding: "2px 0"}}>767 <span style={{fontSize: "14px", color: "#000000"}}>개소</span></div>
|
||||
</div>
|
||||
<div className="col-span-2" style={{width: "100%", textAlign: "right"}}>기준년월 : 2025.09 </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 노후하수관로현황 */}
|
||||
<div className="card card-border">
|
||||
<div className="card-header text-foreground">
|
||||
<h3 className="text-2xl font-medium">노후하수관로현황</h3>
|
||||
</div>
|
||||
<div className="h-70 p-4">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 재이용시설(개소) */}
|
||||
<div className="card card-border">
|
||||
<div className="card-header text-foreground">
|
||||
<h3 className="text-2xl font-medium">재이용시설(개소)</h3>
|
||||
</div>
|
||||
<div className="h-70 p-4">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* 오늘 접속자 수 카드 */}
|
||||
<div className="card card-border h-80 !p-0 col-span-2">
|
||||
|
||||
|
||||
{/* 지도영역 */}
|
||||
<div className="col-span-3 h-200 !p-0 relative z-10">
|
||||
<div className="card card-border">
|
||||
<div className="card-header text-foreground">
|
||||
<h3 className="text-2xl font-medium">유역별 정보</h3>
|
||||
</div>
|
||||
<KoreaBasinMap />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 사용자 정보 카드 */}
|
||||
<div className="card card-border h-80 p-10 col-span-1">
|
||||
<h2 className="text-2xl mb-6">사용자 정보</h2>
|
||||
{error && <div className="text-red-500 mb-4">{error}</div>}
|
||||
{userInfo ? (
|
||||
<div className="mb-4">
|
||||
<div><b>아이디:</b> {userInfo.userId}</div>
|
||||
<div><b>이메일:</b> {userInfo.email || userInfo.userId}</div>
|
||||
<div><b>이름:</b> {userInfo.userName || '-'}</div>
|
||||
<div><b>2FA 활성화:</b> {userInfo.twoFactorEnabled ? '예' : '아니오'}</div>
|
||||
<div className="card card-border col-span-1 h-80 p-10">
|
||||
<h2 className="mb-6 text-2xl">사용자 정보</h2>
|
||||
{error && <div className="mb-4 text-red-500">{error}</div>}
|
||||
{userInfo ? (
|
||||
<div className="mb-4">
|
||||
<div>
|
||||
<b>아이디:</b> {userInfo.userId}
|
||||
</div>
|
||||
) : (
|
||||
!error && <div>사용자 정보를 불러오는 중...</div>
|
||||
)}
|
||||
<button className="btn w-full mb-2" onClick={handleLogout}>로그아웃</button>
|
||||
<button className="btn w-full" onClick={handleChangePassword}>패스워드 변경</button>
|
||||
</div>
|
||||
<div>
|
||||
<b>이메일:</b> {userInfo.email || userInfo.userId}
|
||||
</div>
|
||||
<div>
|
||||
<b>이름:</b> {userInfo.userName || "-"}
|
||||
</div>
|
||||
<div>
|
||||
<b>2FA 활성화:</b>{" "}
|
||||
{userInfo.twoFactorEnabled ? "예" : "아니오"}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
!error && <div>사용자 정보를 불러오는 중...</div>
|
||||
)}
|
||||
<button className="btn mb-2 w-full" onClick={handleLogout}>
|
||||
로그아웃
|
||||
</button>
|
||||
<button className="btn w-full" onClick={handleChangePassword}>
|
||||
패스워드 변경
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 두번째 라인 */}
|
||||
<div className="grid grid-cols-2 gap-1">
|
||||
<div className="card card-border h-80 p-10 col-span-1">
|
||||
<div className="grid grid-cols-4 gap-1">
|
||||
<div className="card card-border"id="grouping-statistics">
|
||||
<div className="card-header text-foreground">
|
||||
<h3 className="text-2xl font-medium">지원현황</h3>
|
||||
</div>
|
||||
<div className="h-70 p-4">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className="card card-border">
|
||||
<div className="card-header text-foreground">
|
||||
<h3 className="text-2xl font-medium">자료관 자료현황</h3>
|
||||
</div>
|
||||
<div className="h-70 p-4">
|
||||
</div>
|
||||
</div>
|
||||
<div className="card card-border">
|
||||
<div className="card-header text-foreground">
|
||||
<h3 className="text-2xl font-medium">공지사항</h3>
|
||||
</div>
|
||||
<div className="h-70 p-4">
|
||||
</div>
|
||||
</div>
|
||||
<div className="card card-border h-80 p-10 col-span-1">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{/* 배너 영역 */}
|
||||
<div className="card card-border">
|
||||
|
||||
{/* 세번째 라인 */}
|
||||
<div className="grid grid-cols-2 gap-1">
|
||||
<div className="card card-border h-80 p-10 col-span-1">
|
||||
</div>
|
||||
<div className="card card-border h-80 p-10 col-span-1">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 네번째 라인 */}
|
||||
<div className="grid grid-cols-2 gap-1">
|
||||
<div className="card card-border h-80 p-10 col-span-1">
|
||||
</div>
|
||||
<div className="card card-border h-80 p-10 col-span-1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -139,4 +300,4 @@ function DashboardPage() {
|
||||
);
|
||||
}
|
||||
|
||||
export { DashboardPage };
|
||||
export { DashboardPage };
|
||||
|
||||
@@ -69,6 +69,17 @@ export const ENDPOINT = {
|
||||
POSTS_COMMENTS: "/board-service/api/v1/posts-cmnts",
|
||||
POST_EVALUATION: "/board-service/api/v1/pstEvl",
|
||||
},
|
||||
SEWERAGE_SERVICE: {
|
||||
PPL_COUNTS: "/sewerage-service/api/v1/ms/pplCounts",
|
||||
OLD_PPL_COUNTS: "/sewerage-service/api/v1/ms/oldPplCounts",
|
||||
},
|
||||
IC_SERVICE: {
|
||||
GROUPING_STATISTICS: "/ic-service/api/v1/nti/grouping-statistics",
|
||||
},
|
||||
DC_SERVICE: {
|
||||
DATA_STATUS: "/dc-service/api/v1/dc/dataStatus",
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export const JWT_EXPIRATION_TIME = 1800000;
|
||||
|
||||
@@ -19,4 +19,4 @@ NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/ap
|
||||
|
||||
|
||||
NEXT_PUBLIC_FINDADRESS_URL=https://business.juso.go.kr/addrlink/addrLinkApi.do
|
||||
NEXT_PUBLIC_WR_ADDRESS_KEY = devU01TX0FVVEgyMDI1MDgyNTEwMzkwNDExNjEwNTM=
|
||||
NEXT_PRIVATE_WR_ADDRESS_KEY = devU01TX0FVVEgyMDI1MDgyNTEwMzkwNDExNjEwNTM=
|
||||
|
||||
+1
-1
@@ -22,4 +22,4 @@ NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/ap
|
||||
|
||||
|
||||
NEXT_PUBLIC_FINDADRESS_URL=https://business.juso.go.kr/addrlink/addrLinkApi.do
|
||||
NEXT_PUBLIC_WR_ADDRESS_KEY = devU01TX0FVVEgyMDI1MDgyNTEwMzkwNDExNjEwNTM=
|
||||
NEXT_PRIVATE_WR_ADDRESS_KEY = devU01TX0FVVEgyMDI1MDgyNTEwMzkwNDExNjEwNTM=
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
NEXT_PUBLIC_SITE_ID = DM
|
||||
NEXT_PUBLIC_PORT = 11035
|
||||
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11035
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000/api/v1
|
||||
NEXT_PUBLIC_FO_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000/operation-service/api/v1
|
||||
NEXT_PUBLIC_CS_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000
|
||||
NEXT_PUBLIC_PROXY_HOST = https://reuse.hasuon.or.kr
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000/api/v1
|
||||
NEXT_PUBLIC_FO_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000/operation-service/api/v1
|
||||
NEXT_PUBLIC_CS_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
|
||||
NEXT_PUBLIC_CS_TUS_UPLOAD = /attach-service/api/v1/tus/upload
|
||||
NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver
|
||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl
|
||||
@@ -11,11 +11,11 @@ NEXT_PUBLIC_CLAIM_NAME = Authorization
|
||||
NEXT_PUBLIC_AUTH_USER_ID = token-id
|
||||
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||
NEXT_PUBLIC_REUSE_API_URL=http://con.mind-one.co.kr:11080/api/v1
|
||||
NEXT_PUBLIC_REUSE_API_URL= http://apigateway.iipbs-was.svc.cluster.local:8000/reuse-service/api/v1
|
||||
NEXT_PUBLIC_NGII_URL = http://10.98.25.94:18080/openapi/Gettile.do?apiKey=BDE2BEF39DAFEC293AB6730150F222AC
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000/sewerage-service/api
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000/sewerage-service/api
|
||||
|
||||
|
||||
|
||||
NEXT_PUBLIC_FINDADRESS_URL=https://business.juso.go.kr/addrlink/addrLinkApi.do
|
||||
NEXT_PUBLIC_WR_ADDRESS_KEY = U01TXOFVVEgyMDI1MDgyODE0MTAxNzExNjEyMjA=
|
||||
NEXT_PRIVATE_WR_ADDRESS_KEY = U01TXOFVVEgyMDI1MDgyODE0MTAxNzExNjEyMjA=
|
||||
|
||||
@@ -58,6 +58,7 @@ export default function MyForm() {
|
||||
dataList={demandCompList}
|
||||
rtnValue={callback}
|
||||
rtnInputData={handleInsertSdmData}
|
||||
openNetwork={true}
|
||||
/>
|
||||
<Toaster position="top-center" />
|
||||
</div>
|
||||
|
||||
@@ -1,237 +1,45 @@
|
||||
'use client';
|
||||
|
||||
import { regionData, regionIdMap } from '@/app/common/comFunction';
|
||||
import { useDmStore } from '@/app/store';
|
||||
import type { DmStatusDataType } from '@/app/store/wrStatus/type';
|
||||
import { CHART_FORM, MainChart, type ChartConfig } from '@common/business_components';
|
||||
import React, { useEffect, useRef, useState, useMemo, useCallback } from 'react';
|
||||
import React, { useEffect, useRef, useState, useCallback } from 'react';
|
||||
|
||||
interface RegionData {
|
||||
name: string;
|
||||
x: number;
|
||||
y: number;
|
||||
values: number[];
|
||||
|
||||
interface WrStatusChartProps {
|
||||
chartForm: string;
|
||||
chartConfig: ChartConfig;
|
||||
chartData: any;
|
||||
chartTitle: string;
|
||||
chartClassName?: string;
|
||||
graphSize?: number;
|
||||
yFieldText? : string | undefined;
|
||||
yFieldText2? : string | undefined;
|
||||
showLegend? : boolean;
|
||||
setXAxisYearTick ?: boolean;
|
||||
}
|
||||
|
||||
interface TableData {
|
||||
region: string;
|
||||
sewage: string;
|
||||
rainwater: string;
|
||||
reclaimed: string;
|
||||
thermal: string;
|
||||
}
|
||||
export default function WrStatusPage() {
|
||||
|
||||
|
||||
const WrStatusPage: React.FC = () => {
|
||||
|
||||
|
||||
const { Common, dmStatus, getDmStatusData,initializeCommonData} = useDmStore((state) => state);
|
||||
const { statusData,facilityTotals ,chartData} = dmStatus;
|
||||
const [selectedRegion, setSelectedRegion] = useState<string | null>(null);
|
||||
const [hoveredRegion, setHoveredRegion] = useState<string | null>(null);
|
||||
const [tooltipPosition, setTooltipPosition] = useState<{ x: number; y: number } | null>(null);
|
||||
const [chartOption, setChartOption] = useState<WrStatusChartProps>({} as WrStatusChartProps)
|
||||
const svgContainerRef = useRef<HTMLDivElement>(null);
|
||||
const [chartData] = useState<any[]>([
|
||||
{
|
||||
label : '서울',
|
||||
하수 : 4,
|
||||
빗물 : 816,
|
||||
중수도 : 371,
|
||||
온배수 : 0
|
||||
},
|
||||
{
|
||||
label : '부산',
|
||||
하수 : 13,
|
||||
빗물 : 68,
|
||||
중수도 : 20,
|
||||
온배수 : 1
|
||||
},
|
||||
{
|
||||
label : '대구',
|
||||
하수 : 9,
|
||||
빗물 : 294,
|
||||
중수도 : 14,
|
||||
온배수 : 2
|
||||
},
|
||||
{
|
||||
label : '인천',
|
||||
하수 : 17,
|
||||
빗물 : 165,
|
||||
중수도 : 35,
|
||||
온배수 : 15
|
||||
},
|
||||
{
|
||||
label : '광주',
|
||||
하수 : 3,
|
||||
빗물 : 74,
|
||||
중수도 : 15,
|
||||
온배수 : 15
|
||||
},
|
||||
{
|
||||
label : '대전',
|
||||
하수 : 2,
|
||||
빗물 : 52,
|
||||
중수도 : 11,
|
||||
온배수 : 20
|
||||
},
|
||||
{
|
||||
label : '울산',
|
||||
하수 : 8,
|
||||
빗물 : 111,
|
||||
중수도 : 19,
|
||||
온배수 : 30
|
||||
},
|
||||
{
|
||||
label : '세종',
|
||||
하수 : 9,
|
||||
빗물 : 65,
|
||||
중수도 : 0,
|
||||
온배수 : 0
|
||||
},
|
||||
{
|
||||
label : '경기',
|
||||
하수 : 176,
|
||||
빗물 : 1009,
|
||||
중수도 : 252,
|
||||
온배수 : 40
|
||||
},
|
||||
{
|
||||
label : '강원',
|
||||
하수 : 69,
|
||||
빗물 : 69,
|
||||
중수도 : 22,
|
||||
온배수 : 0
|
||||
},
|
||||
{
|
||||
label : '충북',
|
||||
하수 : 38,
|
||||
빗물 : 17,
|
||||
중수도 : 91,
|
||||
온배수 : 0
|
||||
},
|
||||
{
|
||||
label : '충남',
|
||||
하수 : 67,
|
||||
빗물 : 54,
|
||||
중수도 : 188,
|
||||
온배수 : 0
|
||||
},
|
||||
{
|
||||
label : '전북',
|
||||
하수 : 55,
|
||||
빗물 : 33,
|
||||
중수도 : 220,
|
||||
온배수 : 0
|
||||
},
|
||||
{
|
||||
label : '전남',
|
||||
하수 : 83,
|
||||
빗물 : 16,
|
||||
중수도 : 75,
|
||||
온배수 : 0
|
||||
},
|
||||
{
|
||||
label : '경북',
|
||||
하수 : 81,
|
||||
빗물 : 37,
|
||||
중수도 : 70,
|
||||
온배수 : 0
|
||||
},
|
||||
{
|
||||
label : '경남',
|
||||
하수 : 75,
|
||||
빗물 : 27,
|
||||
중수도 : 140,
|
||||
온배수 : 0
|
||||
},
|
||||
{
|
||||
label : '제주',
|
||||
하수 : 8,
|
||||
빗물 : 47,
|
||||
중수도 : 64,
|
||||
온배수 : 0
|
||||
}
|
||||
]);
|
||||
|
||||
const chartConfig = chartData.reduce((config, element) => {
|
||||
config[element.label] = {
|
||||
label: element.label,
|
||||
color : "hsl(var(--chart-1))"
|
||||
};
|
||||
return config;
|
||||
}, {} as Record<string, { label: string; color: string; }>) satisfies ChartConfig;
|
||||
|
||||
const chartOption = {
|
||||
chartForm : CHART_FORM.BAR,
|
||||
chartConfig : chartConfig,
|
||||
chartData : chartData,
|
||||
chartTitle : '',
|
||||
chartClassName : "h-[300px] w-full",
|
||||
graphSize : 40,
|
||||
yFieldText : '시설(개소)',
|
||||
showLegend : true
|
||||
}
|
||||
|
||||
const colorLegend = [
|
||||
{ label: '하수', color: '#FF6B6B', key: 'sewage' },
|
||||
{ label: '빗물', color: '#4ECDC4', key: 'rainwater' },
|
||||
{ label: '중수도', color: '#45B7D1', key: 'reclaimed' },
|
||||
{ label: '온배수', color: '#FED16A', key: 'thermal' },
|
||||
];
|
||||
const facilityTotalsColor = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FED16A'];
|
||||
const defaultYear= '2023'
|
||||
|
||||
const regionIdMap: Record<string, string> = {
|
||||
서울: '서울특별시',
|
||||
부산: '부산광역시',
|
||||
대구: '대구광역시',
|
||||
인천: '인천광역시',
|
||||
광주: '광주광역시',
|
||||
대전: '대전광역시',
|
||||
울산: '울산광역시',
|
||||
세종: '세종특별자치시',
|
||||
경기: '경기도',
|
||||
강원: '강원특별자치도',
|
||||
충북: '충청북도',
|
||||
충남: '충청남도',
|
||||
전북: '전라북도',
|
||||
전남: '전라남도',
|
||||
경북: '경상북도',
|
||||
경남: '경상남도',
|
||||
제주: '제주특별자치도'
|
||||
};
|
||||
|
||||
const tableData: TableData[] = [
|
||||
{ region: '전국', sewage: '717(1,137,538)', rainwater: '3544(13,945)', reclaimed: '1018(222,476)', thermal: '123(492)' },
|
||||
{ region: '서울특별시', sewage: '4(114,908)', rainwater: '816(430)', reclaimed: '371(341)', thermal: '0' },
|
||||
{ region: '부산광역시', sewage: '13(146,197)', rainwater: '68(335)', reclaimed: '20(512)', thermal: '1(18)' },
|
||||
{ region: '대구광역시', sewage: '9(102,380)', rainwater: '294(133)', reclaimed: '14(44)', thermal: '2(12)' },
|
||||
{ region: '인천광역시', sewage: '17(57,691)', rainwater: '165(642)', reclaimed: '35(7,859)', thermal: '15(32)' },
|
||||
{ region: '광주광역시', sewage: '3(28,738)', rainwater: '74(23)', reclaimed: '15(450)', thermal: '15(6)' },
|
||||
{ region: '대전광역시', sewage: '2(11,966)', rainwater: '52(2)', reclaimed: '11(492)', thermal: '20(100)' },
|
||||
{ region: '울산광역시', sewage: '8(36,076)', rainwater: '111(39)', reclaimed: '19(28,904)', thermal: '30(130)' },
|
||||
{ region: '세종특별자치시', sewage: '9(2,555)', rainwater: '65(16)', reclaimed: '0(0)', thermal: '0' },
|
||||
{ region: '경기도', sewage: '176(313,298)', rainwater: '1009(4,735)', reclaimed: '252(77,096)', thermal: '40(143)' },
|
||||
{ region: '강원특별자치도', sewage: '69(19,677)', rainwater: '69(4)', reclaimed: '22(447)', thermal: '0' },
|
||||
{ region: '충청북도', sewage: '38(15,607)', rainwater: '17(91)', reclaimed: '91(2,211)', thermal: '0' },
|
||||
{ region: '충청남도', sewage: '67(41,368)', rainwater: '54(77)', reclaimed: '188(50,434)', thermal: '0' },
|
||||
{ region: '전라북도', sewage: '55(42,671)', rainwater: '33(199)', reclaimed: '220(9,453)', thermal: '0' },
|
||||
{ region: '전라남도', sewage: '83(23,560)', rainwater: '16(885)', reclaimed: '75(15,412)', thermal: '0' },
|
||||
{ region: '경상북도', sewage: '81(129,081)', rainwater: '37(341)', reclaimed: '70(27,818)', thermal: '0' },
|
||||
{ region: '경상남도', sewage: '75(50,101)', rainwater: '27(244)', reclaimed: '140(343)', thermal: '0' },
|
||||
{ region: '제주특별자치도', sewage: '8(1,666)', rainwater: '47(5,746)', reclaimed: '64(660)', thermal: '0' },
|
||||
];
|
||||
|
||||
const regionData: RegionData[] = useMemo(() => [
|
||||
{ name: '서울', x: 170, y: 140, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '인천', x: 120, y: 150, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '경기', x: 210, y: 210, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '강원', x: 330, y: 120, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '충북', x: 260, y: 280, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '충남', x: 100, y: 320, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '세종', x: 180, y: 305, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '대전', x: 195, y: 360, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '전북', x: 170, y: 450, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '전남', x: 160, y: 600, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '광주', x: 120, y: 530, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '경북', x: 400, y: 320, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '경남', x: 310, y: 530, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '대구', x: 350, y: 450, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '울산', x: 450, y: 500, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '부산', x: 420, y: 550, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '제주', x: 60, y: 750, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
], []);
|
||||
|
||||
const handleMarkerClick = (regionId: string) => {
|
||||
if (selectedRegion === regionId) {
|
||||
@@ -242,6 +50,10 @@ const WrStatusPage: React.FC = () => {
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
initializeCommonData();
|
||||
}, [initializeCommonData]);
|
||||
|
||||
const createDonutMarker = useCallback((svg: SVGSVGElement, x: number, y: number, name: string, values: number[]) => {
|
||||
const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FED16A'];
|
||||
const radius = 26;
|
||||
@@ -252,7 +64,6 @@ const WrStatusPage: React.FC = () => {
|
||||
console.warn(`Invalid region name: ${name}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||
g.setAttribute('transform', `translate(${x}, ${y})`);
|
||||
g.setAttribute('id', `marker-${name}`);
|
||||
@@ -336,6 +147,14 @@ const WrStatusPage: React.FC = () => {
|
||||
svg.appendChild(g);
|
||||
}, [handleMarkerClick, regionIdMap]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if(Common.selectSidoData&&Common.selectSidoData.length>0)
|
||||
getDmStatusData(Common.selectSidoData);
|
||||
},[Common.selectSidoData])
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const loadSVG = async () => {
|
||||
try {
|
||||
@@ -393,6 +212,31 @@ const WrStatusPage: React.FC = () => {
|
||||
});
|
||||
}
|
||||
}, [selectedRegion]);
|
||||
useEffect(() => {
|
||||
if(chartData.length>0){
|
||||
const chartConfig = chartData.reduce((config, element) => {
|
||||
config[element.label] = {
|
||||
label: element.label,
|
||||
color : "hsl(var(--chart-1))"
|
||||
};
|
||||
return config;
|
||||
}, {} as Record<string, { label: string; color: string; }>) satisfies ChartConfig;
|
||||
|
||||
const Option = {
|
||||
chartForm : CHART_FORM.BAR,
|
||||
chartConfig : chartConfig,
|
||||
chartData : chartData,
|
||||
chartTitle : '',
|
||||
chartClassName : "w-full h-[350px] ",
|
||||
graphSize : 10,
|
||||
yFieldText : '시설(개소)',
|
||||
showLegend : true
|
||||
}
|
||||
setChartOption(Option)
|
||||
}else{
|
||||
setChartOption({} as WrStatusChartProps)
|
||||
}
|
||||
}, [chartData]);
|
||||
|
||||
return (
|
||||
<div className="flex h-screen bg-[#F2F2F2] text-gray-800">
|
||||
@@ -401,7 +245,6 @@ const WrStatusPage: React.FC = () => {
|
||||
{/* 상단 제목 */}
|
||||
<div className="mb-6 flex justify-between items-center">
|
||||
<h2 className="text-2xl font-bold">물재이용 현황</h2>
|
||||
<div className="text-sm text-gray-500">관리자 ▼</div>
|
||||
</div>
|
||||
|
||||
{/* 콘텐츠 본문 */}
|
||||
@@ -410,7 +253,7 @@ const WrStatusPage: React.FC = () => {
|
||||
<div className="bg-white rounded-xl shadow border border-[#DBE2E6] overflow-hidden max-h-[900px]">
|
||||
{/* 타이틀 영역 */}
|
||||
<div className="border-b border-[#DBE2E6] px-4 py-3">
|
||||
<h3 className="text-[12px] font-semibold">재이용시설현황(2023)</h3>
|
||||
<h3 className="text-[12px] font-semibold">{`재이용시설현황(${defaultYear})`}</h3>
|
||||
<p className="text-[12px] text-[#999] font-medium">행정구역별 재이용시설현황(개소)</p>
|
||||
</div>
|
||||
|
||||
@@ -439,11 +282,11 @@ const WrStatusPage: React.FC = () => {
|
||||
<div className="font-semibold mb-1">{hoveredRegion}</div>
|
||||
<div className="space-y-1">
|
||||
{colorLegend.map(({ label, color, key }) => (
|
||||
<div key={key} className="flex items-center space-x-2">
|
||||
<div key={key+'' +color} className="flex items-center space-x-2">
|
||||
<span className="text-[12px] inline-block w-3 h-3 rounded-sm" style={{ backgroundColor: color }}></span>
|
||||
<span className="text-[12px]">
|
||||
{label}:{' '}
|
||||
{tableData.find(d => d.region === hoveredRegion)?.[key as keyof TableData] ?? '-'}
|
||||
{statusData?.find(d => d.region === hoveredRegion)?.[key as keyof DmStatusDataType] || '-'}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
@@ -453,22 +296,12 @@ const WrStatusPage: React.FC = () => {
|
||||
|
||||
{/* 범례 */}
|
||||
<div className="absolute bottom-2 right-2 bg-white rounded-lg shadow-md p-4 text-sm space-y-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="inline-block w-4 h-4 rounded-sm" style={{backgroundColor: '#FF6B6B'}}></span>
|
||||
<span className="text-[12px] text-gray-900">하수재이용시설 (총 717개소)</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="inline-block w-4 h-4 rounded-sm" style={{backgroundColor: '#4ECDC4'}}></span>
|
||||
<span className="text-[12px] text-gray-900">빗물이용시설 (총 3,730개소)</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="inline-block w-4 h-4 rounded-sm" style={{backgroundColor: '#45B7D1'}}></span>
|
||||
<span className="text-[12px] text-gray-900">중수도시설 (총 1,074개소)</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="inline-block w-4 h-4 rounded-sm" style={{backgroundColor: '#FED16A'}}></span>
|
||||
<span className="text-[12px] text-gray-900">온배수시설 (총 201개소)</span>
|
||||
</div>
|
||||
{facilityTotals?.map((item, index) => (
|
||||
<div key ={'fcltTotal' +index}className="flex items-center space-x-2">
|
||||
<span className="inline-block w-4 h-4 rounded-sm" style={{backgroundColor:facilityTotalsColor[index]}}></span>
|
||||
<span className="text-[12px] text-gray-900">{item}</span>
|
||||
</div>
|
||||
)) }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -479,10 +312,10 @@ const WrStatusPage: React.FC = () => {
|
||||
{/* 재이용시설현황 표 */}
|
||||
<div className="bg-white rounded-xl shadow border border-[#DBE2E6] overflow-hidden">
|
||||
{/* 타이틀 + 버튼 영역 */}
|
||||
<div className="flex justify-between items-center border-b border-[#DBE2E6] px-4 py-3">
|
||||
<div className="flex justify-between items-center border-b border-[#436d85] px-4 py-3">
|
||||
<div>
|
||||
<h3 className="text-[12px] font-semibold">재이용시설현황(2023)</h3>
|
||||
<p className="text-[12px] text-[#999] font-medium">행정구역별 재이용시설현황(개소)</p>
|
||||
<h3 className="text-[12px] font-semibold">{`재이용시설현황(${defaultYear})`}</h3>
|
||||
<p className="text-[12px] text-[#999] font-medium">행정구역별 재이용시설현황[개소(천m³/년)]</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -493,14 +326,17 @@ const WrStatusPage: React.FC = () => {
|
||||
<tr>
|
||||
<th className="text-[12px] font-semibold px-4 py-2">번호</th>
|
||||
<th className="text-[12px] font-semibold px-4 py-2">시도</th>
|
||||
<th className="text-[12px] font-semibold px-4 py-2">하수(이용량,천𝓂³/년)</th>
|
||||
<th className="text-[12px] font-semibold px-4 py-2">하수재이용시설</th>
|
||||
<th className="text-[12px] font-semibold px-4 py-2">빗물이용시설</th>
|
||||
<th className="text-[12px] font-semibold px-4 py-2">중수도시설</th>
|
||||
{/* <th className="text-[12px] font-semibold px-4 py-2">하수(이용량,천𝓂³/년)</th>
|
||||
<th className="text-[12px] font-semibold px-4 py-2">빗물(이용량,천𝓂³/년)</th>
|
||||
<th className="text-[12px] font-semibold px-4 py-2">중수도(이용량,천𝓂³/년)</th>
|
||||
<th className="text-[12px] font-semibold px-4 py-2">온배수(이용량,천𝓂³/년)</th>
|
||||
<th className="text-[12px] font-semibold px-4 py-2">온배수(이용량,천𝓂³/년)</th> */}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y">
|
||||
{tableData.map((row, index) => (
|
||||
{statusData?.map((row, index) => (
|
||||
<tr key={index} className="hover:bg-gray-50">
|
||||
<td className="text-[12px] px-4 py-2 text-center">
|
||||
{index+1}
|
||||
@@ -509,7 +345,6 @@ const WrStatusPage: React.FC = () => {
|
||||
<td className="text-[12px]">{row.sewage}</td>
|
||||
<td className="text-[12px]">{row.rainwater}</td>
|
||||
<td className="text-[12px]">{row.reclaimed}</td>
|
||||
<td className="text-[12px]">{row.thermal}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
@@ -521,21 +356,23 @@ const WrStatusPage: React.FC = () => {
|
||||
{/* 재이용통계 차트 */}
|
||||
<div className="bg-white rounded-xl shadow border border-[#DBE2E6] overflow-hidden">
|
||||
<div className="border-b border-[#DBE2E6] px-4 py-3">
|
||||
<h3 className="text-[12px] font-semibold">재이용통계(2023)</h3>
|
||||
<h3 className="text-[12px] font-semibold">{`재이용통계(${defaultYear})`}</h3>
|
||||
<p className="text-[12px] text-[#999] font-medium">행정구역별 재이용시설 현황 개소수 그래프</p>
|
||||
</div>
|
||||
<div className="p-4 bg-[#f9fbfd]">
|
||||
<div className="h-[305px] text-gray-500">
|
||||
<MainChart
|
||||
chartForm={chartOption.chartForm}
|
||||
chartConfig={chartOption.chartConfig}
|
||||
chartData={chartOption.chartData}
|
||||
chartTitle={chartOption.chartTitle}
|
||||
chartClassName={chartOption.chartClassName}
|
||||
graphSize={chartOption.graphSize}
|
||||
yFieldText={chartOption.yFieldText}
|
||||
showLegend={chartOption.showLegend}
|
||||
/>
|
||||
{chartOption?
|
||||
<MainChart
|
||||
chartForm={chartOption.chartForm}
|
||||
chartConfig={chartOption.chartConfig}
|
||||
chartData={chartOption.chartData}
|
||||
chartTitle={chartOption.chartTitle}
|
||||
chartClassName={chartOption.chartClassName}
|
||||
graphSize={chartOption.graphSize}
|
||||
yFieldText={chartOption.yFieldText}
|
||||
showLegend={chartOption.showLegend}
|
||||
/>
|
||||
:<></>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -545,5 +382,3 @@ const WrStatusPage: React.FC = () => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WrStatusPage;
|
||||
@@ -0,0 +1,65 @@
|
||||
import type { RegionData, } from "../store/wrStatus/type";
|
||||
|
||||
|
||||
|
||||
export const regionData:RegionData[] = [
|
||||
{ name: '서울', x: 170, y: 140, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '인천', x: 120, y: 150, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '경기', x: 210, y: 210, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '강원', x: 330, y: 120, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '충북', x: 260, y: 280, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '충남', x: 100, y: 320, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '세종', x: 180, y: 305, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '대전', x: 195, y: 360, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '전북', x: 170, y: 450, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '전남', x: 160, y: 600, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '광주', x: 120, y: 530, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '경북', x: 400, y: 320, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '경남', x: 310, y: 530, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '대구', x: 350, y: 450, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '울산', x: 450, y: 500, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '부산', x: 420, y: 550, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
{ name: '제주', x: 60, y: 750, values: [0.3, 0.3, 0.2, 0.2] },
|
||||
]
|
||||
|
||||
export const regionIdMap: Record<string, string> = {
|
||||
서울: '서울특별시',
|
||||
부산: '부산광역시',
|
||||
대구: '대구광역시',
|
||||
인천: '인천광역시',
|
||||
광주: '광주광역시',
|
||||
대전: '대전광역시',
|
||||
울산: '울산광역시',
|
||||
세종: '세종특별자치시',
|
||||
경기: '경기도',
|
||||
강원: '강원특별자치도',
|
||||
충북: '충청북도',
|
||||
충남: '충청남도',
|
||||
전북: '전라북도',
|
||||
전남: '전라남도',
|
||||
경북: '경상북도',
|
||||
경남: '경상남도',
|
||||
제주: '제주특별자치도'
|
||||
};
|
||||
|
||||
|
||||
export const makeRegion = (region: string) => {
|
||||
if (region === '서울특별시') return '서울'
|
||||
if (region === '부산광역시') return '부산'
|
||||
if (region === '대구광역시') return '대구'
|
||||
if (region === '인천광역시') return '인천'
|
||||
if (region === '광주광역시') return '광주'
|
||||
if (region === '대전광역시') return '대전'
|
||||
if (region === '울산광역시') return '울산'
|
||||
if (region === '세종특별자치시') return '세종'
|
||||
if (region === '경기도') return '경기'
|
||||
if (region === '강원특별자치도') return '강원'
|
||||
if (region === '충청북도') return '충북'
|
||||
if (region === '충청남도') return '충남'
|
||||
if (region === '전북특별자치도') return '전북'
|
||||
if (region === '전라남도') return '전남'
|
||||
if (region === '경상북도') return '경북'
|
||||
if (region === '경상남도') return '경남'
|
||||
if (region === '제주특별자치도') return '제주'
|
||||
return region;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
"use client"
|
||||
"use client";
|
||||
import "./globals.css";
|
||||
|
||||
export default function RootLayout({
|
||||
@@ -6,15 +6,13 @@ export default function RootLayout({
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
|
||||
return (
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<title>물재이용 대민</title>
|
||||
</head>
|
||||
<body>
|
||||
{children}
|
||||
</body>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@ const selectMiddleRegionData: SelectDataType[] = [
|
||||
// 시도 API 호출 함수 추가
|
||||
const fetchSidoData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch(fetchType.COMMON, '/addr/city');
|
||||
const res = await getFetch(fetchType.FO, '/addr/city');
|
||||
const data = res.data;
|
||||
selectSidoData = [
|
||||
{ text: "전체", val: '0'},
|
||||
@@ -233,7 +233,7 @@ const fetchSidoData = async (): Promise<SelectDataType[]> => {
|
||||
// 시군구 API 호출 함수 추가
|
||||
const fetchSigunData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch(fetchType.COMMON, '/addr/sgg');
|
||||
const res = await getFetch(fetchType.FO, '/addr/sgg');
|
||||
const data = res.data;
|
||||
selectSigunData = [
|
||||
{ text: "전체", val: '0' },
|
||||
@@ -253,7 +253,7 @@ const fetchSigunData = async (): Promise<SelectDataType[]> => {
|
||||
// 권역 API 호출 함수 추가
|
||||
const fetchRegionData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch(fetchType.COMMON, '/addr/sarea');
|
||||
const res = await getFetch(fetchType.FO, '/addr/sarea');
|
||||
const data = res.data;
|
||||
return [
|
||||
{ text: "전체", val: '0'},
|
||||
@@ -271,7 +271,7 @@ const fetchRegionData = async (): Promise<SelectDataType[]> => {
|
||||
// 중권역 API 호출 함수 추가
|
||||
const fetchMiddleRegionData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch(fetchType.COMMON, '/addr/midArea');
|
||||
const res = await getFetch(fetchType.FO, '/addr/midArea');
|
||||
const data = res.data;
|
||||
return [
|
||||
{ text: "전체", val: '0' },
|
||||
@@ -290,7 +290,7 @@ const fetchMiddleRegionData = async (): Promise<SelectDataType[]> => {
|
||||
// 단위유역 API 호출 함수 추가
|
||||
const fetchUnitWaterShedData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch(fetchType.COMMON, '/addr/largeArea');
|
||||
const res = await getFetch(fetchType.FO, '/addr/largeArea');
|
||||
const data = res.data;
|
||||
return [
|
||||
{ text: "전체", val: '0' },
|
||||
@@ -309,7 +309,7 @@ const fetchUnitWaterShedData = async (): Promise<SelectDataType[]> => {
|
||||
// 환경청 데이터
|
||||
const fetchEnvPartData = async (): Promise<envPartSelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch(fetchType.COMMON, '/addr/govArea');
|
||||
const res = await getFetch(fetchType.FO, '/addr/govArea');
|
||||
const data = res.data;
|
||||
selectEnvPartData = [
|
||||
{ text: "전체", val: '0', adstDliStrCd: '' },
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { getFetch } from "@/components/ui/api";
|
||||
import { fetchType, getFetch } from "@/components/ui/api";
|
||||
import { DEV_URL_FO } from "@/components/ui/config";
|
||||
import type { FacilityInfo, SubsInfo } from "./type";
|
||||
|
||||
const checkWrRegList = async () => {
|
||||
const wrRegList = await getFetch("wr", `/reuseFc/pubFc`);
|
||||
const wrRegList = await getFetch(fetchType.WR, `/reuseFc/pubFc`);
|
||||
return wrRegList;
|
||||
};
|
||||
|
||||
|
||||
+38
-19
@@ -1,29 +1,48 @@
|
||||
import { createStore } from 'zustand/vanilla';
|
||||
import { CommonReducer, CommonState, type CommonStore, type CommonType } from './common';
|
||||
import { SdmReducer, SdmState, type SdmStore, type SdmType } from './sdmMng';
|
||||
import { dmMapState, type DmMapType, type DmMapStore, DmMapReducer } from './map';
|
||||
import { tokenManager } from '@/src/entities/auth/lib/token-manager';
|
||||
import { createStore } from "zustand/vanilla";
|
||||
import {
|
||||
CommonReducer,
|
||||
CommonState,
|
||||
type CommonStore,
|
||||
type CommonType,
|
||||
} from "./common";
|
||||
import { SdmReducer, SdmState, type SdmStore, type SdmType } from "./sdmMng";
|
||||
import {
|
||||
dmMapState,
|
||||
type DmMapType,
|
||||
type DmMapStore,
|
||||
DmMapReducer,
|
||||
} from "./map";
|
||||
import { tokenManager } from "@/src/entities/auth/lib/token-manager";
|
||||
import {
|
||||
DmStatusReducer,
|
||||
dmStatusState,
|
||||
type DmStatusStore,
|
||||
type DmStatusType,
|
||||
} from "./wrStatus";
|
||||
|
||||
export type DmStore = CommonStore & SdmStore &DmMapStore ;
|
||||
export type DmState = CommonType & SdmType &DmMapType;
|
||||
export type DmStore = CommonStore & SdmStore & DmMapStore & DmStatusStore;
|
||||
export type DmState = CommonType & SdmType & DmMapType & DmStatusType;
|
||||
|
||||
export const StoreZus = (initState: DmState= {
|
||||
...CommonState,
|
||||
...SdmState,
|
||||
...dmMapState,
|
||||
}) => {
|
||||
export const StoreZus = (
|
||||
initState: DmState = {
|
||||
...CommonState,
|
||||
...SdmState,
|
||||
...dmMapState,
|
||||
...dmStatusState,
|
||||
}
|
||||
) => {
|
||||
return createStore<DmStore>()((set) => {
|
||||
if (typeof window !== "undefined") {
|
||||
tokenManager.setToken("site-id-key", 'DM');
|
||||
tokenManager.setToken("site-theme-key", 'green');
|
||||
tokenManager.setToken("site-id-key", "DM");
|
||||
tokenManager.setToken("site-theme-key", "green");
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
...initState,
|
||||
...CommonReducer(set),
|
||||
...SdmReducer(set),
|
||||
...DmMapReducer(set)
|
||||
}
|
||||
})
|
||||
}
|
||||
...DmMapReducer(set),
|
||||
...DmStatusReducer(set),
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
import { fetchType, getFetch } from "@/components/ui/api";
|
||||
import type {
|
||||
DmStatusDataType,
|
||||
DmStatusChartType,
|
||||
DmStatusBoardType,
|
||||
} from "./type";
|
||||
import type { SelectDataType } from "../common";
|
||||
import { makeRegion } from "@/app/common/comFunction";
|
||||
|
||||
export type DmStatusActions = {
|
||||
getDmStatusData(cityCd: SelectDataType[]): void;
|
||||
};
|
||||
|
||||
export type DmStatusType = {
|
||||
dmStatus: {
|
||||
statusData: DmStatusDataType[];
|
||||
facilityTotals: string[];
|
||||
chartData: DmStatusChartType[];
|
||||
};
|
||||
};
|
||||
|
||||
export const dmStatusState: DmStatusType = {
|
||||
dmStatus: {
|
||||
statusData: [],
|
||||
facilityTotals: [],
|
||||
chartData: [],
|
||||
},
|
||||
};
|
||||
export type DmStatusStore = DmStatusType & DmStatusActions;
|
||||
|
||||
export const DmStatusReducer = (set: any): DmStatusActions => {
|
||||
return {
|
||||
getDmStatusData: async (cityCd: SelectDataType[]) => {
|
||||
const data = await getFetch(fetchType.FO, "/dashBoard/daemin");
|
||||
|
||||
const dataSum = data.data.reduce(
|
||||
(acc: DmStatusDataType, item: DmStatusDataType) => {
|
||||
acc.sewage = (
|
||||
parseInt(acc.sewage.replaceAll(",", "")) +
|
||||
parseInt(item.sewage.replaceAll(",", ""))
|
||||
).toLocaleString();
|
||||
acc.rainwater = (
|
||||
parseInt(acc.rainwater.replaceAll(",", "")) +
|
||||
parseInt(item.rainwater.replaceAll(",", ""))
|
||||
).toLocaleString();
|
||||
acc.reclaimed = (
|
||||
parseInt(acc.reclaimed.replaceAll(",", "")) +
|
||||
parseInt(item.reclaimed.replaceAll(",", ""))
|
||||
).toLocaleString();
|
||||
acc.sewageCnt = (
|
||||
parseInt(acc.sewageCnt.replaceAll(",", "")) +
|
||||
parseInt(item.sewageCnt.replaceAll(",", ""))
|
||||
).toLocaleString();
|
||||
acc.rainwaterCnt = (
|
||||
parseInt(acc.rainwaterCnt.replaceAll(",", "")) +
|
||||
parseInt(item.rainwaterCnt.replaceAll(",", ""))
|
||||
).toLocaleString();
|
||||
acc.reclaimedCnt = (
|
||||
parseInt(acc.reclaimedCnt.replaceAll(",", "")) +
|
||||
parseInt(item.reclaimedCnt.replaceAll(",", ""))
|
||||
).toLocaleString();
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
region: "합계",
|
||||
sewage: "0",
|
||||
rainwater: "0",
|
||||
reclaimed: "0",
|
||||
sewageCnt: "0",
|
||||
rainwaterCnt: "0",
|
||||
reclaimedCnt: "0",
|
||||
}
|
||||
);
|
||||
data.data.unshift(dataSum);
|
||||
|
||||
console.log("dataSum ", dataSum);
|
||||
const facilityTotals = [
|
||||
"하수재이용시설" + "(총" + dataSum?.sewageCnt + "개소)",
|
||||
"빗물재이용시설" + "(총" + dataSum?.rainwaterCnt + "개소)",
|
||||
"중수도재이용시설" + "(총" + dataSum?.reclaimedCnt + "개소)",
|
||||
];
|
||||
|
||||
const boardData: DmStatusBoardType[] = data.data.map(
|
||||
(item: DmStatusDataType) => {
|
||||
const regionText = cityCd.find((city) => item.region === city.val);
|
||||
const sewage = item.sewage;
|
||||
const rainwater = item.rainwater;
|
||||
const reclaimed = item.reclaimed;
|
||||
const sewageCnt = item.sewageCnt;
|
||||
const rainwaterCnt = item.rainwaterCnt;
|
||||
const reclaimedCnt = item.reclaimedCnt;
|
||||
|
||||
return {
|
||||
region: regionText ? regionText.text : item.region,
|
||||
sewage: sewageCnt + "(" + sewage + ")",
|
||||
rainwater: rainwaterCnt + "(" + rainwater + ")",
|
||||
reclaimed: reclaimedCnt + "(" + reclaimed + ")",
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const chartData = data.data.map((item) => ({
|
||||
label: makeRegion(
|
||||
cityCd.find((city) => item.region === city.val)?.text ?? ""
|
||||
),
|
||||
하수: item.sewage,
|
||||
빗물: item.rainwater,
|
||||
중수도: item.reclaimed,
|
||||
}));
|
||||
|
||||
set((state: DmStatusType) => ({
|
||||
...state,
|
||||
dmStatus: {
|
||||
...state.dmStatus,
|
||||
statusData: boardData,
|
||||
chartData: chartData,
|
||||
facilityTotals: facilityTotals,
|
||||
},
|
||||
}));
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
export type DmStatusDataType = {
|
||||
region: string;
|
||||
sewage: string;
|
||||
rainwater: string;
|
||||
reclaimed: string;
|
||||
sewageCnt:string
|
||||
rainwaterCnt:string
|
||||
reclaimedCnt:string
|
||||
};
|
||||
|
||||
export type DmStatusBoardType = {
|
||||
region: string;
|
||||
sewage: string;
|
||||
rainwater: string;
|
||||
reclaimed: string;
|
||||
};
|
||||
|
||||
export type DmStatusFcltType = {
|
||||
sewageFclt: string;
|
||||
rainwaterFclt: string;
|
||||
reclaimedFclt: string;
|
||||
thermalFclt: string;
|
||||
};
|
||||
|
||||
|
||||
|
||||
export type DmStatusChartType = {
|
||||
label: string,
|
||||
하수: string,
|
||||
빗물: string,
|
||||
중수도: string,
|
||||
}
|
||||
|
||||
export type RegionData = {
|
||||
name: string;
|
||||
x: number;
|
||||
y: number;
|
||||
values: number[];
|
||||
}
|
||||
@@ -3,7 +3,8 @@ import { DEV_URL_FO, DEV_URL_WR } from "../config";
|
||||
|
||||
export const fetchType = {
|
||||
COMMON: "common",
|
||||
WR: "wr"
|
||||
WR: "wr",
|
||||
FO:'fo'
|
||||
};
|
||||
|
||||
interface RequestParams {
|
||||
@@ -11,7 +12,7 @@ interface RequestParams {
|
||||
}
|
||||
|
||||
export const getFetch = async (type: string, url: string) => {
|
||||
const baseUrl = type === fetchType.COMMON ? DEV_URL_FO : DEV_URL_WR;
|
||||
const baseUrl = type === fetchType.FO ? DEV_URL_FO : DEV_URL_WR;
|
||||
const response = await fetch(baseUrl + url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
|
||||
@@ -637,7 +637,7 @@ export function SdmInfoRegForm({
|
||||
}}
|
||||
/>
|
||||
<div className="col-span-1">
|
||||
<Label className="text-xl">수소이온농도(PH)</Label>
|
||||
<Label className="text-xl">수소이온농도(pH)</Label>
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<Input
|
||||
className="!text-xl w-36"
|
||||
|
||||
@@ -8,7 +8,7 @@ const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || "";
|
||||
const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || "";
|
||||
const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
|
||||
const BUSINESS_JUSO_API_URL = process.env.NEXT_PUBLIC_FINDADRESS_URL || "";
|
||||
const AdressKey = process.env.NEXT_PUBLIC_WR_ADDRESS_KEY || "";
|
||||
const AdressKey = process.env.NEXT_PRIVATE_WR_ADDRESS_KEY || "";
|
||||
|
||||
export function middleware(req: NextRequest) {
|
||||
const pathname = req.nextUrl.pathname;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
[
|
||||
{ "region": "전국", "sewage": "717(1,137,538)", "rainwater": "3544(13,945)", "reclaimed": "1018(222,476)", "thermal": "123(492)" },
|
||||
{ "region": "서울특별시", "sewage": "4(114,908)", "rainwater": "816(430)", "reclaimed": "371(341)", "thermal": "0" },
|
||||
{ "region": "부산광역시", "sewage": "13(146,197)", "rainwater": "68(335)", "reclaimed": "20(512)", "thermal": "1(18)" },
|
||||
{ "region": "대구광역시", "sewage": "9(102,380)", "rainwater": "294(133)", "reclaimed": "14(44)", "thermal": "2(12)" },
|
||||
{ "region": "인천광역시", "sewage": "17(57,691)", "rainwater": "165(642)", "reclaimed": "35(7,859)", "thermal": "15(32)" },
|
||||
{ "region": "광주광역시", "sewage": "3(28,738)", "rainwater": "74(23)", "reclaimed": "15(450)", "thermal": "15(6)" },
|
||||
{ "region": "대전광역시", "sewage": "2(11,966)", "rainwater": "52(2)", "reclaimed": "11(492)", "thermal": "20(100)" },
|
||||
{ "region": "울산광역시", "sewage": "8(36,076)", "rainwater": "111(39)", "reclaimed": "19(28,904)", "thermal": "30(130)" },
|
||||
{ "region": "세종특별자치시", "sewage": "9(2,555)", "rainwater": "65(16)", "reclaimed": "0(0)", "thermal": "0" },
|
||||
{ "region": "경기도", "sewage": "176(313,298)", "rainwater": "1009(4,735)", "reclaimed": "252(77,096)", "thermal": "40(143)" },
|
||||
{ "region": "강원특별자치도", "sewage": "69(19,677)", "rainwater": "69(4)", "reclaimed": "22(447)", "thermal": "0" },
|
||||
{ "region": "충청북도", "sewage": "38(15,607)", "rainwater": "17(91)", "reclaimed": "91(2,211)", "thermal": "0" },
|
||||
{ "region": "충청남도", "sewage": "67(41,368)", "rainwater": "54(77)", "reclaimed": "188(50,434)", "thermal": "0" },
|
||||
{ "region": "전라북도", "sewage": "55(42,671)", "rainwater": "33(199)", "reclaimed": "220(9,453)", "thermal": "0" },
|
||||
{ "region": "전라남도", "sewage": "83(23,560)", "rainwater": "16(885)", "reclaimed": "75(15,412)", "thermal": "0" },
|
||||
{ "region": "경상북도", "sewage": "81(129,081)", "rainwater": "37(341)", "reclaimed": "70(27,818)", "thermal": "0" },
|
||||
{ "region": "경상남도", "sewage": "75(50,101)", "rainwater": "27(244)", "reclaimed": "140(343)", "thermal": "0" },
|
||||
{ "region": "제주특별자치도", "sewage": "8(1,666)", "rainwater": "47(5,746)", "reclaimed": "64(660)", "thermal": "0" }
|
||||
]
|
||||
+19
-18
@@ -1,31 +1,32 @@
|
||||
# NEXT_PUBLIC_SITE_ID = WR
|
||||
# NEXT_PUBLIC_PORT = 11301
|
||||
# NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11301
|
||||
# NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||
# NEXT_PUBLIC_SITE_ID = FO
|
||||
# NEXT_PUBLIC_PORT = 11300
|
||||
# NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300
|
||||
# NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1
|
||||
# #NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||
# NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1
|
||||
# NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||
# NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
|
||||
# NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
|
||||
# NEXT_PUBLIC_CLAIM_NAME = Authorization
|
||||
# NEXT_PUBLIC_AUTH_USER_ID = token-id
|
||||
# NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||
# NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||
|
||||
|
||||
# NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
|
||||
|
||||
NEXT_PUBLIC_SITE_ID = FO
|
||||
NEXT_PUBLIC_PORT = 11300
|
||||
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1
|
||||
#NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||
NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1
|
||||
NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||
#NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/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_PORT = 3000
|
||||
NEXT_PUBLIC_PROXY_HOST = https://larva.hasuon.or.kr
|
||||
# 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/operation-service/api/v1
|
||||
NEXT_PUBLIC_FO_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000/operation-service/api/v1
|
||||
NEXT_PUBLIC_CS_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
|
||||
NEXT_PUBLIC_CS_TUS_UPLOAD = /attach-service/api/v1/tus/upload
|
||||
NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver
|
||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl
|
||||
NEXT_PUBLIC_CLAIM_NAME = Authorization
|
||||
NEXT_PUBLIC_AUTH_USER_ID = token-id
|
||||
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||
NEXT_PUBLIC_NGII_URL = http://10.98.25.94:18080/openapi/Gettile.do?apiKey=BDE2BEF39DAFEC293AB6730150F222AC
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
|
||||
|
||||
NEXT_PUBLIC_WR_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000/reuse-service/api/v1
|
||||
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000/sewerage-service/api
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 강우영향일 계산 로직
|
||||
*
|
||||
* 1.강우영향일 및 강우량을 계산하며 강우량이 3이상이면 강우영향일이며 이후 이틀까지 강우영향일로 포함
|
||||
*
|
||||
* 2.강우영향일이면서 3mm이하의 강우량일 경우에는 강우영향을 준 날의 강우량을 따름
|
||||
* @param data
|
||||
* @param weather (default:ALL), SUNNY, ..etc
|
||||
* @author jsyang
|
||||
*/
|
||||
|
||||
export default function CalcRainEffect(data : any, weather='ALL') {
|
||||
console.log("%c Calculate RainEffect !" , "background:blue;color:white");
|
||||
console.log("%c Data Length :"+data.length+" Weather : "+weather , "background:yellow;color:blue");
|
||||
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
const item = data[idx];
|
||||
if(item){
|
||||
if(item.infoRnDay && Number(item.infoRnDay) >= 3) {
|
||||
item.rainEffectDay = 1;
|
||||
} else {
|
||||
item.rainEffectDay = 0;
|
||||
}
|
||||
|
||||
if(item.infoRnDay == 'x'){
|
||||
item.infoRnDay = '0.0';
|
||||
item.toBeInfoRnDay = '0.0';
|
||||
}else{
|
||||
item.infoRnDay = Number(item.infoRnDay).toFixed(1);
|
||||
item.toBeInfoRnDay = Number(item.infoRnDay).toFixed(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
if(data[idx]) {
|
||||
// 하루 전이 강우영향일(3 이상)인 경우
|
||||
if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) {
|
||||
data[idx]!.rainEffectDay = 1;
|
||||
}
|
||||
// 이틀 전이 강우영향일(3 이상)인 경우
|
||||
if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) {
|
||||
data[idx]!.rainEffectDay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
if(data[idx] && data[idx]?.rainEffectDay === 1) {
|
||||
if(idx > 1){
|
||||
if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
|
||||
data[idx]!.toBeInfoRnDay = data[idx-1]!.infoRnDay;
|
||||
}
|
||||
}
|
||||
if(idx > 2){
|
||||
if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
|
||||
data[idx]!.toBeInfoRnDay = data[idx-2]!.infoRnDay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let rtnData : any = [];
|
||||
if (weather === 'ALL') {
|
||||
rtnData = data;
|
||||
} else if (weather === 'SUNNY') {
|
||||
rtnData = data.filter((item: any) => item.rainEffectDay === 0);
|
||||
} else {
|
||||
rtnData = data.filter((item: any) => item.rainEffectDay === 1);
|
||||
}
|
||||
return rtnData;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export default function CommaToNumber (data: any){
|
||||
const rtnValue = data&&data.toString().trim()!=''&&data!=undefined?Number(data.toString().replaceAll(',','')):'';
|
||||
return rtnValue;
|
||||
}
|
||||
@@ -39,7 +39,7 @@ export default function DataForm({ type, column, item }: DataFormProps) {
|
||||
break;
|
||||
case 'float0':
|
||||
if(value) {
|
||||
item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 1) / 1).split('.').map((part, index) =>
|
||||
item[column] = item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 1) / 1).split('.').map((part, index) =>
|
||||
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
|
||||
).join('.')
|
||||
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
|
||||
@@ -97,26 +97,27 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
const rainEffectDay = (item as T & { rainEffectDay: number }).rainEffectDay;
|
||||
|
||||
if(flowPanel === '2'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 3 && infoRnDay < 10;
|
||||
} else if(flowPanel === '3'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 10 && infoRnDay < 20;
|
||||
} else if(flowPanel === '4'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 20 && infoRnDay < 30;
|
||||
} else if(flowPanel === '5'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 30 && infoRnDay < 40;
|
||||
} else if(flowPanel === '6'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 40 && infoRnDay < 50;
|
||||
} else if(flowPanel === '7'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 50 && infoRnDay < 60;
|
||||
} else if(flowPanel === '8'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 60;
|
||||
} else {
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && (rainEffectDay ===1);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import React from 'react'
|
||||
|
||||
/**
|
||||
* 하단 주석 영역
|
||||
*/
|
||||
|
||||
type CommentType={
|
||||
commentStartPoint? : string,
|
||||
commentArray? : string[],
|
||||
divHeight? : string,
|
||||
}
|
||||
|
||||
function UnderComment({commentStartPoint="☞", commentArray=[], divHeight="14"} :CommentType) {
|
||||
|
||||
if(commentArray && commentArray.length > 0){
|
||||
return (
|
||||
<div className={"mt-"+divHeight}>
|
||||
{commentArray.map((item, index) => (
|
||||
<React.Fragment key={"comment" + index}>
|
||||
<span className="text-2xl font-bold text-gray-500">
|
||||
{commentStartPoint} {item}
|
||||
</span>
|
||||
<br/>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default UnderComment;
|
||||
@@ -0,0 +1,137 @@
|
||||
# 운영실태 인수인계
|
||||
## 이력
|
||||
 written by yjs
|
||||
 2025-
|
||||
## 0. 알아두면 좋아요
|
||||
 - 화면 초기 화면 : 메인 대시보드(표로 보는 대시보드)
|
||||
<br> - API swagger 주소 : http://con.mind-one.co.kr:11082/swagger-ui/index.html#
|
||||
<br> - 단위 : 유량은 정수까지 강우량은 소수점 1자리 반올림한다, 수질은 TN, TP만 소수점 3자리, 나머지는 1자리까지 반올림한다.
|
||||
<br>  ▶︎ roundNumber(value:any, decimal:number) 컴포넌트를 활용해보세요!!
|
||||
<br> - 강우영향일 : 강우량이 3mm이상인 날은 강우영향일에 포함되고 하루전, 이틀전에 강우량이 3mm인 날의 경우도 강우량에 포함된다. 팝업의 강우시, 청천시 탭에서 보여주는 리스트를 만들 때 필요한 정보이니 참고한다.
|
||||
<br>  ▶︎ 예시 : 1월 13일 강우량이 5일 경우 - 강우영향일 포함됨, 1월 14일, 1월 15일 강우량에 상관없이 ___강우영향일 포함됨___, 1월 16일의 경우 14일, 15일이 3mm미만이면 ___강우영향일 미포함됨___
|
||||
<br>  ▶︎ CalcRainEffect(data:any, weather) 컴포넌트에서 측정일, 강우량이 포함된 데이터를 파라미터로 넘기면 강우영향일(rainEffectDay) 컬럼 및 0,1로 여부 value로 데이터에 추가되어 리턴한다.
|
||||
<br> - 운영실태는 대부분 시설의 정보를 추출해주는 화면이 대다수이며 검색은 행정별, 유역별, 환경청별로 시설을 분류하여 조회하고 엑셀, 초기화, 조회 버튼이 우측에 존재한다.
|
||||
<br> - 메인 대시보드의 경우에는 수질, 유량 등 조회하는 화면의 정보들을 압축해서 보여주는 화면이라고 생각하면 좋다. 그렇기 때문에 대시보드에서의 각각의 데이터와 메인 화면의 데이터가 일치하는지 검증하는 작업이 많이 필요하다.
|
||||
<br> - 하루 단위의 데이터를 보여주는 모달에서 연간, 하절기, 동절기, 청천시, 강우시 등의 1년치 데이터를 필터링 하여 보여주는데 탭을 누를 시 api가 재호출 되는 형식이 아니고 1년치 데이터를 필터링 하여 출력해주고 청천시탭의 경우 강우영향일은 미포함, 강우시탭의 경우 강우영향일 포함된 데이터를 보여줘야 한다.
|
||||
## 1. 표로 보기(메인 대시보드)
|
||||
### 1-1) 시설정보 및 운영현황
|
||||
 - 년도, 시설에 해당하는 시설정보 및 유량, 수질, 물사용량 등의 정보를 표로 표출해주는 화면
|
||||
<br> - 시설계획 : 알에스원 DC-SERVICE API에서 받은 데이터를 화면에 출력
|
||||
<br>  ▶︎ 주소 : 'https://apigateway.apps.rsonesoft.com/dc-service/api/v1/nowDmgMtncGnsvy';
|
||||
<br>  ▶︎ 파라미터 : swtrmtFcltCd - 시설코드 / ctpvNm - 시도명 / sggNm - 시군구명 / targetYear - 대상년도
|
||||
<br>  ▶︎ 리턴값(사용되는것 위주)
|
||||
<br>   /**
|
||||
<br>    * 증설계획
|
||||
<br>    */
|
||||
<br>   기승인(당초4단계), 현재, 변경1~4
|
||||
<br>   planSwageQntSumDt4 : number | '',
|
||||
<br>   planSwageQntSum : number | '',
|
||||
<br>   planSwageQntSumDc1 : number | '',
|
||||
<br>   planSwageQntSumDc2 : number | '',
|
||||
<br>   planSwageQntSumDc3 : number | '',
|
||||
<br>   planSwageQntSumDc4 : number | '',
|
||||
<br>   /**
|
||||
<br>    * 처리인구
|
||||
<br>    */
|
||||
<br>   // 기승인(당초4단계), 현재, 변경1~4
|
||||
<br>   swtrmtPpltnCntDt4 : number | '',
|
||||
<br>   swtrmtPpltnCnt : number | '',
|
||||
<br>   swtrmtPpltnCntDc1 : number | '',
|
||||
<br>   swtrmtPpltnCntDc2 : number | '',
|
||||
<br>   swtrmtPpltnCntDc3 : number | '',
|
||||
<br>   swtrmtPpltnCntDc4 : number | '',
|
||||
<br>   /**
|
||||
<br>    * 처리구역면적
|
||||
<br>    */
|
||||
<br>   // 기승인(당초4단계), 현재, 변경1~4
|
||||
<br>   swtrmtZoneAreaDt4 : number | '',
|
||||
<br>   swtrmtZoneArea : number | '',
|
||||
<br>   swtrmtZoneAreaDc1 : number | '',
|
||||
<br>   swtrmtZoneAreaDc2 : number | '',
|
||||
<br>   swtrmtZoneAreaDc3 : number | '',
|
||||
<br>   swtrmtZoneAreaDc4 : number | '',
|
||||
<br>   // 처리구역
|
||||
<br>   trtDstr : string | '',
|
||||
<br>   
|
||||
<br> - 물사용량 : 현재 DB가 없기 때문에 해당 년도의 평균 하수유입량 * 0.65 (65%)
|
||||
<br> - 운영실태 표(우측 표)의 년도는 검색한 년도에 따라 값 설정
|
||||
<br> - 유입유량 : 순수하수유입량 + 연계처리수 + 총인설비반류수
|
||||
|
||||
### 1-2) 메인 그래프
|
||||
 - 1년치 수질항목들의 데이터들을 표출해주는 화면
|
||||
<br> - lineBarChart, lineChart 컴포넌트를 사용하여 차트를 생성함
|
||||
|
||||
### 1-3) 강우일 운영현황
|
||||
 - 1년치 시설의 강우량 데이터를 구간별로 일수와 강우량 정보를 표출해주는 화면
|
||||
<br> - 순수 하루단위의 강우량에 따라서 데이터를 표출하는 것이 아닌 __강우영향일__ 계산된 후 통계를 구한다.
|
||||
<br>  ▶︎ 예시 : 1월 13일 강우량이 5일 경우 - 3~10mm구간 통계포함, 1월 14일 강우량이 0일 경우 - ___3~10mm구간 통계 포함___
|
||||
<br> - 설계유입수질은 처음 설계 당시의 수질 데이터이기 때문에 한개의 데이터만 추출
|
||||
<br> - 시설용량 대비는 유입유량/시설용량 * 100 (비율)
|
||||
<br> - 계의 경우 일수는 합계 그 외에는 평균값을 나타낸다.
|
||||
## 2. 처리시설 현황
|
||||
### 2-1) 처리시설 시설정보
|
||||
 - 처리시설 정보들과 이력들을 조회할 수 있는 화면이다.
|
||||
<br> - 모달 '기본정보' 탭의 시설계획정보는 '이력관리' 탭의 이력 리스트 중 마지막 이력의 수질정보를 표출해준다.
|
||||
<br> - 모달 '이력관리' 탭에서는 이력정보와 해당 차수의 수질정보를 보여준다. (1대1)
|
||||
### 2-2) 처리구역정보
|
||||
 - 처리시설의 계획정보를 조회할 수 있는 화면이다.
|
||||
<br> - 1-1)의 시설계획을 참고하도록 한다. 해당 api로 계획정보를 가져온다.
|
||||
<br> - 요구사항 중 원래는 단계별로 년도를 괄호로 표시해달라는 요청사항이 있었으나 시설들마다 다르기 때문에 메인화면에 단계하단에 년도를 넣는게 불가능하다.
|
||||
<br>  ▶︎ 대시보드의 계획정보 영역의 경우에는 시설코드를 파라미터로 던져 계획정보를 가져오기 때문에 가능하여 대시보드의 계획정보는 괄호로 년도를 추출하도록 한다.
|
||||
## 3. 처리시설 연간 운영 현황
|
||||
### 3-1) 강수현황
|
||||
 - 시설별 강수현황을 조회할 수 있는 화면이다.
|
||||
<br> - 메인화면에서의 시설별 1년치 강우일, 강우일수, 강우량 데이터는 백엔드에서 계산되어 출력되는 형식이 아니라 하루치 데이터의 object(rainyDayObjList)를 store에서 계산하여 출력한다. swagger를 참고한다.
|
||||
<br>  
|
||||
<br>  data": [
|
||||
<br>   {
|
||||
<br>    "bscFctCd": "11000SW001R",
|
||||
<br>    "bscFctNm": "난지",
|
||||
<br>    "sido": "서울특별시",
|
||||
<br>    "gugun": " ",
|
||||
<br>    "addr": "경기도 고양시 덕양구 현천동 692-2",
|
||||
<br>    "fctCpc": 860000,
|
||||
<br>    "stnKo": "강서",
|
||||
<br>    "rvbsn": "한강",
|
||||
<br>    "lgbsn": "한강본류",
|
||||
<br>    "mdmbsn": "한강서울",
|
||||
<br>    "rgnNm": "한강유역환경청",
|
||||
<br>    "totalCount": 0,
|
||||
<br>    "rainyDayObjList": [
|
||||
<br>     {
|
||||
<br>      "bscFctCd": "11000SW001R",
|
||||
<br>      "rainDt": "2024-01-01",
|
||||
<br>      "infoRnDay": 0
|
||||
<br>     },
|
||||
<br>     {
|
||||
<br>      "bscFctCd": "11000SW001R",
|
||||
<br>      "rainDt": "2024-01-02",
|
||||
<br>      "infoRnDay": 0
|
||||
<br>     },
|
||||
<br>     .....
|
||||
<br><br> - 일별 데이터 object(rainyDayObjList)를 강우영향일 구하는 컴포넌트에 던져 강우영향일을 구한 후 메인화면에 출력해야한다.
|
||||
<br> - 모달 화면에서는 일별 데이터를 추출해 보여준다.
|
||||
### 3-2) 유량현황
|
||||
 - 시설별 년도별 유량현황을 조회할 수 있는 화면이다.
|
||||
<br> - 화면의 구성은 강수현황과 같이 메인화면에는 1년치 유량정보, 모달로는 하루 단위의 유량정보를 보여주지만 메인화면에서 데이터는 집계되어 추출된다.
|
||||
### 3-3) 수질현황
|
||||
 - 시설별 년도별 수질현황을 조회할 수 있는 화면이다.
|
||||
<br> - 2021년 이전은 COD, 21년부터는 TOC값을 표출한다. 그것을 구분하기 위해 2021년 이전의 TOC값들은 소괄호로 감싸준다.
|
||||
<br> - 모달에서 '수질 TMS'의 경우에는 운영실태 API가 아닌 물재이용 API에서 데이터를 얻으며 getFetch에서 'wr' 파라미터로 물재이용 데이터를 얻는다.
|
||||
<br>  ▶︎ api 주소 : http://con.mind-one.co.kr:11080/api/v1/il/getTms/{시설번호}
|
||||
## 4. 운영실태
|
||||
### 4-1) 오수발생량 추정
|
||||
 - 물사용량 : 원래는 연간 월별 물사용량을 연계받아서 사용해야하지만 현재 연계를 받지 못하여 하수유입량의 65%를 물사용량으로 잡았다.
|
||||
<br> - 오수전환율 : 90%로 고정
|
||||
<br> - 오수발생량 추정 : 물사용량 * (100/오수전환율)
|
||||
<br> - 연간 하수유입량과 청천시 하수유입량을 구하기 위해서 1년치 하루단위의 데이터를 가져와 계산이 필요(강우영향일 계산필요)
|
||||
<br> - 물 사용량은 월별로 연계를 받기 때문에 모달에서 하수유입량을 월별로 통계를 구해야 한다.
|
||||
<br> - 계산을 해보면 모달에서 월별 사용량의 평균과 1년치 데이터의 평균은 다르다. 직접 계산해보면 다를 수 밖에 없다. 하지만 값을 맞추기 위해서 모달에서의 평균값을 모달의 데이터가 아닌 1년치 데이터의 평균을 넣고 최대, 최소만 월별 데이터를 기반으로 구한다.
|
||||
### 4-2) 지하수유입량 추정
|
||||
 -적정여부 = 연간 지하수유입량/연평균 유입하수량*100
|
||||
<br> -지하수 유입량 = 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)
|
||||
<br> -모달에서의 오수발생량 전체 평균을 구할 때 평균 하수유입량을 기반으로 한 물사용량이 아닌 현재 월 데이터에서의 평균을 구한것을 넣는다.
|
||||
### 4-3) RDII분석
|
||||
 -RDII 추정값 : 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD))
|
||||
<br> - RDII 추정시 일강수량 : 하절기 최저 유입 BOD 날짜의 강우량
|
||||
<br> - 적정여부 : 하절기일 때 최저유입 BOD유입유량 > 시설용량 일 경우 초과유입 아니면 적정
|
||||
@@ -1,4 +1,10 @@
|
||||
"use client"
|
||||
/**
|
||||
* 대시보드 - 표로보기 - 배수설비 정비현황
|
||||
*
|
||||
* - 배수설비 현황을 조회하는 화면. 2차사업 때 예정인 화면으로 현재 사용되지 않음.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
|
||||
import { useFoStore } from '@/app/store';
|
||||
import type { DrainageEquipmentListProps, TableUpperProps } from '@/app/store/dashboard';
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
"use client"
|
||||
/**
|
||||
* 대시보드 - 표로보기 - 시설정보 및 운영현황(모달)
|
||||
*
|
||||
* - 유량, 수질, 총인시설의 연간, 하절기, 동절기 단위로 값을 차트로 시각화하여 보여주는 모달화면
|
||||
* - 막대그래프로 모달을 그려준다.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import type { OperationalStatusListProps } from "@/app/store/dashboard";
|
||||
import { CHART_FORM, MainChart, type ChartConfig } from "@common/business_components";
|
||||
import { Button } from "@common/business_components/ui/table/lib/button";
|
||||
@@ -69,22 +76,12 @@ export default function DashBoardChartModal({item='', period='', title='',modalD
|
||||
useEffect(() => {
|
||||
if(period === 'year'){
|
||||
const filteredData: yearProps[] = modalData.map((item) => {
|
||||
if(waterQlty.trim().includes('T-N') || waterQlty.trim().includes('T-P')){
|
||||
return {
|
||||
label: item.waterQlty,
|
||||
평균: typeof item.yearAvg === 'string' ? Number(item.yearAvg.replace(/,/g, '')).toFixed(3) : (item.yearAvg || 0),
|
||||
최대: typeof item.yearMax === 'string' ? Number(item.yearMax.replace(/,/g, '')).toFixed(3) : (item.yearMax || 0),
|
||||
최소: typeof item.yearMin === 'string' ? Number(item.yearMin.replace(/,/g, '')).toFixed(3) : (item.yearMin || 0),
|
||||
평균: typeof item.yearAvg === 'string' ? Number(item.yearAvg.replace(/,/g, '')) : (item.yearAvg || 0),
|
||||
최대: typeof item.yearMax === 'string' ? Number(item.yearMax.replace(/,/g, '')) : (item.yearMax || 0),
|
||||
최소: typeof item.yearMin === 'string' ? Number(item.yearMin.replace(/,/g, '')) : (item.yearMin || 0),
|
||||
}
|
||||
}
|
||||
else{
|
||||
return {
|
||||
label: item.waterQlty,
|
||||
평균: typeof item.yearAvg === 'string' ? Number(item.yearAvg.replace(/,/g, '')).toFixed(1) : (item.yearAvg || 0),
|
||||
최대: typeof item.yearMax === 'string' ? Number(item.yearMax.replace(/,/g, '')).toFixed(1) : (item.yearMax || 0),
|
||||
최소: typeof item.yearMin === 'string' ? Number(item.yearMin.replace(/,/g, '')).toFixed(1) : (item.yearMin || 0),
|
||||
}
|
||||
}
|
||||
})
|
||||
if (item === 'flowRate') {
|
||||
setChartData(filteredData.slice(0,5));
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
"use client"
|
||||
/**
|
||||
* 대시보드 - 표로보기 - 시설정보 및 운영현황
|
||||
*
|
||||
* - 시설정보 및 운영현황 탭의 메인 페이지
|
||||
* - 중앙상단에는 시설에 대한 요약정보가, 좌측 상단은 시설계획에 대한 정보, 좌측하단에는 물사용량에 대한 정보,
|
||||
* 우측에는 조회년도 및 시설에 해당하는 유량 및 수질정보를 연간,하절기,동절기별 추출하여 데이터를 보여준다.
|
||||
* - 우측 운영실태는 연간, 하절기, 동절기별로 색이 칠해져있는데 어떤항목들끼리 차트로 그려지는지 확인하기 위해서다.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { roundNumber } from "@/app/components/common/DataForm";
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/processFacility";
|
||||
@@ -13,7 +22,12 @@ export type facilityInfoProps = {
|
||||
fcltyList?: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string, efflWqltStndrdNm: string }[];
|
||||
};
|
||||
|
||||
// 시설계획 table header 변경
|
||||
/**
|
||||
* 시설계획 table header 변경
|
||||
* @param upHeadList
|
||||
* @param planYearList
|
||||
* @returns
|
||||
*/
|
||||
const headMakeColSpanPlanFclty = (upHeadList: TableUpperProps[], planYearList: string[]) => {
|
||||
return ( <>
|
||||
<TableRow>{
|
||||
@@ -29,6 +43,12 @@ const headMakeColSpanPlanFclty = (upHeadList: TableUpperProps[], planYearList: s
|
||||
}
|
||||
|
||||
// 시설계획 table header 변경
|
||||
/**
|
||||
*
|
||||
* @param upHeadList
|
||||
* @param searchYear
|
||||
* @returns
|
||||
*/
|
||||
const headMakeColSpanOperationStatus = (upHeadList: TableUpperProps[], searchYear: string) => {
|
||||
return ( <>
|
||||
<TableRow>
|
||||
@@ -182,7 +202,7 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
|
||||
useEffect(() => {
|
||||
operationalStatusList.map((item: { [key: string]: string | number | boolean },index) => {
|
||||
if(index===8 || index===9 || index===10 || index===11 || index===12 || index===13 || index===14 || index===15){
|
||||
item['yearAvg'] = Number(item['yearAvg']).toFixed(3);
|
||||
/* item['yearAvg'] = Number(item['yearAvg']).toFixed(3);
|
||||
item['yearMax'] = item['yearMax']+'%';
|
||||
item['yearMin'] = item['yearMin']+'%';
|
||||
item['summerAll'] = item['summerAll']+'%';
|
||||
@@ -191,7 +211,7 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
|
||||
item['winterAll'] = item['winterAll']+'%';
|
||||
item['winterSunnyAvg'] = item['winterSunnyAvg']+'%';
|
||||
item['winterSunnyMax'] = item['winterSunnyMax']+'%';
|
||||
item['winterSunnyMin'] = item['winterSunnyMin']+'%';
|
||||
item['winterSunnyMin'] = item['winterSunnyMin']+'%'; */
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
"use client"
|
||||
/**
|
||||
* 대시보드 - 표로보기 - 주요그래프
|
||||
*
|
||||
* - 시설의 조회년도에 해당하는 수질정보, 강우량, 유입량 등을 특정 항목별로 묶어서 차트로 시각화해주는 화면
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { lineChartDataProps } from "@/app/store/dashboard";
|
||||
import { CHART_FORM, type ChartConfig, ContentsDiv, MainChart } from "@common/business_components";
|
||||
@@ -22,10 +28,12 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
|
||||
const [chart_tpTp, setChart_tpTp] = useState<{
|
||||
chartData1: lineChartDataProps[];
|
||||
chartData2: lineChartDataProps[];
|
||||
chartData3: lineChartDataProps[];
|
||||
}>();
|
||||
const [chart_tntn, setChart_tntn] = useState<{
|
||||
chartData1: lineChartDataProps[];
|
||||
chartData2: lineChartDataProps[];
|
||||
chartData3: lineChartDataProps[];
|
||||
}>();
|
||||
const [chart_inflBodInflTn, setChart_inflBodInflTn] = useState<{
|
||||
chartData1: lineChartDataProps[];
|
||||
@@ -46,6 +54,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
|
||||
chart_efflTn,
|
||||
chart_inflBod,
|
||||
isLoadingMainGraph,
|
||||
waterQltyStandartd,
|
||||
} = MainGraph;
|
||||
|
||||
/**
|
||||
@@ -60,7 +69,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
|
||||
color: colors[2],
|
||||
},
|
||||
lineVal0: {
|
||||
label: '시설용량',
|
||||
label: '지하수유입량',
|
||||
color: colors[1],
|
||||
},
|
||||
lineVal1: {
|
||||
@@ -90,6 +99,10 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
|
||||
label: '방류T-P',
|
||||
color: colors[1],
|
||||
},
|
||||
chartData3: {
|
||||
label : '법적방류T-P',
|
||||
color : 'blackdash',
|
||||
}
|
||||
} satisfies ChartConfig;
|
||||
|
||||
// 유입T-N-방류T-N
|
||||
@@ -102,6 +115,10 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
|
||||
label: '방류T-N',
|
||||
color: colors[1],
|
||||
},
|
||||
chartData3: {
|
||||
label : '법적방류T-N',
|
||||
color : 'blackdash',
|
||||
}
|
||||
} satisfies ChartConfig;
|
||||
|
||||
// 유입BOD-유입T-N
|
||||
@@ -139,21 +156,37 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
|
||||
|
||||
useEffect(() => {
|
||||
if (!chart_chongInTp || !chart_efflTp) return;
|
||||
const legalTpData: lineChartDataProps[] = [];
|
||||
if (waterQltyStandartd){
|
||||
chart_inflTn.forEach(item =>{
|
||||
legalTpData.push({label : item.label, val:waterQltyStandartd.tp});
|
||||
})
|
||||
}
|
||||
|
||||
const chartTpTpData = {
|
||||
chartData1: chart_chongInTp,
|
||||
chartData2: chart_efflTp
|
||||
chartData2: chart_efflTp,
|
||||
chartData3: legalTpData
|
||||
};
|
||||
setChart_tpTp(chartTpTpData);
|
||||
}, [chart_chongInTp, chart_efflTp]);
|
||||
}, [chart_chongInTp, chart_efflTp, chart_inflTn, waterQltyStandartd]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chart_inflTn || !chart_efflTn) return;
|
||||
const legalTnData: lineChartDataProps[] = [];
|
||||
if (waterQltyStandartd){
|
||||
chart_inflTn.forEach(item =>{
|
||||
legalTnData.push({label : item.label, val:waterQltyStandartd.tn});
|
||||
})
|
||||
}
|
||||
|
||||
const chartTntnData = {
|
||||
chartData1: chart_inflTn,
|
||||
chartData2: chart_efflTn
|
||||
chartData2: chart_efflTn,
|
||||
chartData3: legalTnData,
|
||||
};
|
||||
setChart_tntn(chartTntnData);
|
||||
}, [chart_inflTn, chart_efflTn]);
|
||||
}, [chart_inflTn, chart_efflTn, waterQltyStandartd]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chart_inflBod || !chart_inflTn) return;
|
||||
@@ -185,21 +218,21 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINEBAR} chartConfig={chartConfig_inflowRain} chartData={chart_inflowRain} chartTitle="유입하수량-강수량" yFieldText="유입하수량(m³/일)" yFieldText2="강수량(mm)"></MainChart>
|
||||
<MainChart chartForm={CHART_FORM.LINEBAR} chartConfig={chartConfig_inflowRain} chartData={chart_inflowRain} chartTitle="유입하수량-강수량" yFieldText="유입하수량(m³/일)" yFieldText2="강수량(mm)" setXAxisYearTick={true}></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINEBAR} chartConfig={chartConfig_rainBod} chartData={chart_bodRain} chartTitle="유입BOD-강수량" yFieldText="BOD(mg/L)" yFieldText2="강수량(mm)"></MainChart>
|
||||
<MainChart chartForm={CHART_FORM.LINEBAR} chartConfig={chartConfig_rainBod} chartData={chart_bodRain} chartTitle="유입BOD-강수량" yFieldText="BOD(mg/L)" yFieldText2="강수량(mm)" setXAxisYearTick = {true}></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_tptp} chartData={chart_tpTp} chartTitle="총인유입T-P-방류T-P" yFieldText="T-P(mg/L)"></MainChart>
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_tptp} chartData={chart_tpTp} chartTitle="총인유입T-P-방류T-P" yFieldText="T-P(mg/L)" setXAxisYearTick={true}></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
@@ -207,7 +240,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_tntn} chartData={chart_tntn} chartTitle="유입T-N-방류T-N" yFieldText="T-N(mg/L)"></MainChart>
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_tntn} chartData={chart_tntn} chartTitle="유입T-N-방류T-N" yFieldText="T-N(mg/L)" setXAxisYearTick={true}></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
@@ -215,7 +248,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_inflBodInflTn} chartData={chart_inflBodInflTn} chartTitle="유입BOD-유입T-N" yFieldText="농도(mg/L)"></MainChart>
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_inflBodInflTn} chartData={chart_inflBodInflTn} chartTitle="유입BOD-유입T-N" yFieldText="농도(mg/L)" setXAxisYearTick={true}></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
@@ -223,7 +256,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_inflBodInflTp} chartData={chart_inflBodInflTp} chartTitle="유입BOD-유입T-P" yFieldText="농도(mg/L)"></MainChart>
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_inflBodInflTp} chartData={chart_inflBodInflTp} chartTitle="유입BOD-유입T-P" yFieldText="농도(mg/L)" setXAxisYearTick={true}></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
"use client"
|
||||
/**
|
||||
* 대시보드 - 표로보기(메인)
|
||||
*
|
||||
* - 대시보드 - 표로보기 메인페이지로 상단영역의 제어 및 탭 전환 시 보여주는 페이지를 지정해준다.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { ContentsDiv, downloadExcel, downloadMultipleExcel, filePickedBlobArray, MainDiv, SelectBox, UITab, type SelectDataType } from "@common/business_components";
|
||||
import { Button, TabsContent } from "@common/components/ui";
|
||||
@@ -9,6 +15,7 @@ import ProcessFacilitySearch from "./facilityInfo/page";
|
||||
import DashBoardChart from "./maingraph/page";
|
||||
import RainManageTab from "./rainManage/page";
|
||||
import DrainageEquipment from "./drainageEquipment/page";
|
||||
import { roundNumber } from "@/app/components/common/DataForm";
|
||||
|
||||
const tabList = [
|
||||
{ value: 'facilityInfo', label: '시설정보 및 운영현황' },
|
||||
@@ -17,6 +24,22 @@ const tabList = [
|
||||
//{ value: 'drainageEquipment', label: '배수설비 정비현황' }
|
||||
];
|
||||
|
||||
export const generateYearDates = (searchYear: string) => {
|
||||
const dates: string[] = [];
|
||||
const start = new Date(Number(searchYear), 0, 1); // 1월 1일
|
||||
const end = new Date(Number(searchYear), 11, 31); // 12월 31일
|
||||
|
||||
for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(d.getDate()).padStart(2, "0");
|
||||
|
||||
dates.push(`${year}-${month}-${day}`); // YYYY-MM-DD 형식
|
||||
}
|
||||
|
||||
return dates;
|
||||
}
|
||||
|
||||
export default function DashBoard() {
|
||||
// 입력값 상태 관리
|
||||
const { Common, initializeCommonData,searchMainGraph, searchRainManage, searchOperationStatus, OperationStatus, RainManage, MainGraph, PlanFclty } = useFoStore((state) => state);
|
||||
@@ -60,11 +83,11 @@ export default function DashBoard() {
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || '0');
|
||||
// 시설명
|
||||
const [fcltyList, setFcltyList] = useState<{bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | ''}>({
|
||||
bscFctCd: '26260PB001R',
|
||||
bscFctNm: '수영',
|
||||
fcltyCpc: 452000,
|
||||
trtFrfNm: '표준활성슬러지법, MLE, MBR',
|
||||
efflWqltStndrdNm: '500톤 이상(Ⅳ지역)'
|
||||
bscFctCd: '11000SW001R',
|
||||
bscFctNm: '난지',
|
||||
fcltyCpc: 860000,
|
||||
trtFrfNm: '표준활성슬러지법, MLE, A2O',
|
||||
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
|
||||
});
|
||||
|
||||
const [searchFcltyList, setSearchFcltyList] = useState<{bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | ''}>({
|
||||
@@ -79,11 +102,11 @@ export default function DashBoard() {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
setSearchFcltyList({
|
||||
bscFctCd: '26260PB001R',
|
||||
bscFctNm: '수영',
|
||||
fcltyCpc: 452000,
|
||||
trtFrfNm: '표준활성슬러지법, MLE, MBR',
|
||||
efflWqltStndrdNm: '500톤 이상(Ⅳ지역)'
|
||||
bscFctCd: '11000SW001R',
|
||||
bscFctNm: '난지',
|
||||
fcltyCpc: 860000,
|
||||
trtFrfNm: '표준활성슬러지법, MLE, A2O',
|
||||
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
|
||||
});
|
||||
}
|
||||
}, [isInit, initializeCommonData]);
|
||||
@@ -136,7 +159,7 @@ export default function DashBoard() {
|
||||
const excelData1 = planFcltyList.map((item) => {
|
||||
return [
|
||||
item.item,
|
||||
item.provisionalApproval,
|
||||
Number(item.provisionalApproval.toString().replaceAll(',',''))?Number(item.provisionalApproval.toString().replaceAll(',','')):item.provisionalApproval,
|
||||
item.now,
|
||||
item.stepOne,
|
||||
item.stepTwo,
|
||||
@@ -148,23 +171,24 @@ export default function DashBoard() {
|
||||
// operationalStatusList를 2차원 배열로 변환
|
||||
const excelData2 = operationalStatusList.map((item, index) => {
|
||||
const baseData = [
|
||||
item.yearAvg,
|
||||
item.yearMax,
|
||||
item.yearMin,
|
||||
item.summerAll,
|
||||
item.summerThree,
|
||||
item.summerRain,
|
||||
item.winterAll,
|
||||
item.winterSunnyAvg,
|
||||
item.winterSunnyMax,
|
||||
item.winterSunnyMin,
|
||||
item.groundWaterAvg,
|
||||
item.groundWaterSummer,
|
||||
item.groundWaterWinter
|
||||
Number(item.yearAvg?.replaceAll(',','')),
|
||||
Number(item.yearMax?.replaceAll(',','')),
|
||||
Number(item.yearMin?.replaceAll(',','')),
|
||||
Number(item.summerAll?.replaceAll(',','')),
|
||||
Number(item.summerThree?.replaceAll(',','')),
|
||||
Number(item.summerRain?.replaceAll(',','')),
|
||||
Number(item.winterAll?.replaceAll(',','')),
|
||||
Number(item.winterSunnyAvg?.replaceAll(',','')),
|
||||
Number(item.winterSunnyMax?.replaceAll(',','')),
|
||||
Number(item.winterSunnyMin?.replaceAll(',','')),
|
||||
Number(item.groundWaterAvg?.replaceAll(',','').replaceAll('%','')),
|
||||
Number(item.groundWaterSummer?.replaceAll(',','').replaceAll('%','')),
|
||||
Number(item.groundWaterWinter?.replaceAll(',','').replaceAll('%',''))
|
||||
];
|
||||
|
||||
// index가 0일 때만 rdi와 rdiRain 추가
|
||||
return index === 0 ? [...baseData, item.rdi, item.rdiRain] : baseData;
|
||||
console.log(item.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;
|
||||
});
|
||||
|
||||
const sheetParameter = [
|
||||
@@ -190,62 +214,98 @@ export default function DashBoard() {
|
||||
|
||||
case 'mainGraph':
|
||||
searchMainGraph(searchYear, fcltyList.bscFctCd);
|
||||
const yearData = generateYearDates(searchYear);
|
||||
const yearValueData : any = [];
|
||||
|
||||
for (const i in yearData){
|
||||
const rowArray: string[] = [];
|
||||
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]?.lineVal1?.toString(), 0) || '');
|
||||
//시설용량
|
||||
rowArray.push(roundNumber(chart_inflowRain.filter(item=>{return yearData[i] === item.label})[0]?.lineVal0?.toString(), 0) || '');
|
||||
//유입BOD
|
||||
rowArray.push(roundNumber(chart_bodRain.filter(item=>{return yearData[i] === item.label})[0]?.lineVal0?.toString(), 1) || '');
|
||||
//유입T-P
|
||||
rowArray.push(roundNumber(chart_inflTp.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || '');
|
||||
//총인유입T-P
|
||||
rowArray.push(roundNumber(chart_chongInTp.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || '');
|
||||
//방류T-P
|
||||
rowArray.push(roundNumber(chart_efflTp.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || '');
|
||||
//유입T-N
|
||||
rowArray.push(roundNumber(chart_inflTn.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || '');
|
||||
//방류T-N
|
||||
rowArray.push(roundNumber(chart_efflTn.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || '');
|
||||
|
||||
yearValueData.push(
|
||||
rowArray
|
||||
)
|
||||
}
|
||||
/* const excelData = [['날짜', '강수량', '유입하수량','시설용량', '유입BOD', '유입T-P', '총인유입T-P', '방류T-P'], */
|
||||
|
||||
const sheetParameter = [
|
||||
{
|
||||
data: [['날짜', '강수량'],...chart_inflowRain.map((item) => [item.label, item.barVal0])],
|
||||
data: [['날짜', '강수량', '유입하수량', '지하수유입량', '유입BOD', '유입T-P','총인유입T-P', '방류T-P', '유입T-N', '방류T-N'],...yearValueData],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:J1',
|
||||
sheetName: '주요그래프'
|
||||
}
|
||||
/* {
|
||||
data: [['날짜', '강수량'],...chart_inflowRain.map((item) => [item.label, roundNumber(item.barVal0, 1)])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '강수량'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '유입하수량'],...chart_inflowRain.map((item) => [item.label, item.lineVal1])],
|
||||
data: [['날짜', '유입하수량'],...chart_inflowRain.map((item) => [item.label, roundNumber(item.lineVal1, 0)])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '유입하수량'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '시설용량'],...chart_inflowRain.map((item) => [item.label, item.lineVal0])],
|
||||
data: [['날짜', '시설용량'],...chart_inflowRain.map((item) => [item.label, roundNumber(item.lineVal0, 0)])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '시설용량'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '유입BOD'],...chart_bodRain.map((item) => [item.label, item.lineVal0])],
|
||||
data: [['날짜', '유입BOD'],...chart_bodRain.map((item) => [item.label, roundNumber(item.lineVal0, 1)])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '유입BOD'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '유입T-P'],...chart_inflTp.map((item) => [item.label, item.val])],
|
||||
data: [['날짜', '유입T-P'],...chart_inflTp.map((item) => [item.label, roundNumber(item.val, 3)])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '유입T-P'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '총인유입T-P'],...chart_chongInTp.map((item) => [item.label, item.val])],
|
||||
data: [['날짜', '총인유입T-P'],...chart_chongInTp.map((item) => [item.label, roundNumber(item.val, 3)])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '총인유입T-P'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '방류T-P'],...chart_efflTp.map((item) => [item.label, item.val])],
|
||||
data: [['날짜', '방류T-P'],...chart_efflTp.map((item) => [item.label, roundNumber(item.val, 3)])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '방류T-P'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '유입T-N'],...chart_inflTn.map((item) => [item.label, item.val])],
|
||||
data: [['날짜', '유입T-N'],...chart_inflTn.map((item) => [item.label, roundNumber(item.val, 3)])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '유입T-N'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '방류T-N'],...chart_efflTn.map((item) => [item.label, item.val])],
|
||||
data: [['날짜', '방류T-N'],...chart_efflTn.map((item) => [item.label, roundNumber(item.val, 3)])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '방류T-N'
|
||||
}
|
||||
} */
|
||||
];
|
||||
|
||||
downloadMultipleExcel('주요그래프', sheetParameter);
|
||||
@@ -265,22 +325,22 @@ export default function DashBoard() {
|
||||
|
||||
const initVal = () => {
|
||||
setFcltyList({
|
||||
bscFctCd: '26260PB001R',
|
||||
bscFctNm: '수영',
|
||||
fcltyCpc: 452000,
|
||||
trtFrfNm: '표준활성슬러지법, MLE, MBR',
|
||||
efflWqltStndrdNm: '500톤 이상(Ⅳ지역)'
|
||||
bscFctCd: '11000SW001R',
|
||||
bscFctNm: '난지',
|
||||
fcltyCpc: 860000,
|
||||
trtFrfNm: '표준활성슬러지법, MLE, A2O',
|
||||
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
|
||||
});
|
||||
|
||||
setSearchFcltyList({
|
||||
bscFctCd: '26260PB001R',
|
||||
bscFctNm: '수영',
|
||||
fcltyCpc: 452000,
|
||||
trtFrfNm: '표준활성슬러지법, MLE, MBR',
|
||||
efflWqltStndrdNm: '500톤 이상(Ⅳ지역)'
|
||||
bscFctCd: '11000SW001R',
|
||||
bscFctNm: '난지',
|
||||
fcltyCpc: 860000,
|
||||
trtFrfNm: '표준활성슬러지법, MLE, A2O',
|
||||
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
|
||||
});
|
||||
setSearchYear(selectSearchYear[0]?.val || '0');
|
||||
searchFcltyList.bscFctNm = '수영';
|
||||
searchFcltyList.bscFctNm = '난지';
|
||||
|
||||
setSidoValue('0');
|
||||
setSigunValue('0');
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
"use client"
|
||||
/**
|
||||
* 대시보드 - 표로보기 - 강우일 운영현황
|
||||
*
|
||||
* - 시설의 강우량 구간별(3~10mm미만..10~20mm미만 등) 강우일수 및 수질정보를 표로 보여주는 화면
|
||||
* - 강우영향일 계산후 바뀌는 tobe강우일을 계산해야 한다.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { UiTable } from "@common/business_components/ui/table";
|
||||
import { useEffect, useState } from "react";
|
||||
@@ -46,16 +53,17 @@ export default function RainManageTab({searchYear = '', fcltyList = []}: facilit
|
||||
|
||||
return (
|
||||
<div>
|
||||
<UiTable
|
||||
headName=""
|
||||
tableData={rainManageList}
|
||||
headlist={upHeadListRainManage}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
>
|
||||
</UiTable>
|
||||
<UiTable
|
||||
headName=""
|
||||
tableData={rainManageList}
|
||||
headlist={upHeadListRainManage}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
widthFixed={true}
|
||||
>
|
||||
</UiTable>
|
||||
<span className="text-2xl font-bold text-gray-500">☞ 일수에 강우영향일 포함됨</span>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
"use client"
|
||||
/**
|
||||
* 대시보드 - 표로보기 상단구역 페에지
|
||||
*
|
||||
* - 대시보드 - 표로보기의 3개의 탭 상단에 조회년도, 행정정보, 시설명의 구역을 컴포넌트
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { useEffect, useState } from "react";
|
||||
import SearchInput from "../../../components/common/SearchInput";
|
||||
@@ -12,7 +18,7 @@ export default function DashBoardFclty({ onFacilityChange, sidoSigun, facilityNm
|
||||
} = Common;
|
||||
|
||||
// 시설명
|
||||
const [bscFctNm, setFcltyName] = useState<string>(facilityNm || '수영');
|
||||
const [bscFctNm, setFcltyName] = useState<string>(facilityNm || '난지');
|
||||
const [bscFctCd, setbscFctCd] = useState<string>('11000SW001R');
|
||||
const [fcltyCpc, setFcltyCpc] = useState<number | ''>(860000);
|
||||
const [trtFrfNm, setTrtFrfNm] = useState<string | ''>('표준활성슬러지법, MLE, A2O');
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
"use client"
|
||||
/**
|
||||
* 처리시설 연간 운영현황 - 강수현황(모달)
|
||||
*
|
||||
* - 선택한 시설을 조회한 년도의 하루단위로 강우량 및 강우영향일 정보를 보여주는 화면.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
|
||||
import { roundNumber } from "@/app/components/common/DataForm";
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { PrecipitationPropsDetailProps } from "@/app/store/facilityPrecipitation";
|
||||
import { DatePickerRange, UiTable } from "@common/business_components/ui";
|
||||
import { DatePickerRange, downloadExcel, UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Table, TableCell, TableHead, TableRow } from "@common/components/ui";
|
||||
import { Button, Table, TableCell, TableHead, TableRow } from "@common/components/ui";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
type PrecipitationModalProps = {
|
||||
@@ -19,16 +27,17 @@ type DateRange = {
|
||||
}
|
||||
|
||||
export default function PrecipitationModal(props: PrecipitationModalProps) {
|
||||
const { PrecipitationDetail } = useFoStore((state) => state);
|
||||
const { Common, PrecipitationDetail } = useFoStore((state) => state);
|
||||
const { upHeadListPrecipitationDetail } = PrecipitationDetail;
|
||||
|
||||
const { btnClass } = Common;
|
||||
// Refs
|
||||
const startPickerRef = useRef<HTMLDivElement>(null);
|
||||
const endPickerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// States
|
||||
const [startDate, setStartDate] = useState<Date | null>(null);
|
||||
const [endDate, setEndDate] = useState<Date | null>(null);
|
||||
const [startDate, setStartDate] = useState<Date | undefined>(new Date());
|
||||
const [endDate, setEndDate] = useState<Date | undefined>(new Date());
|
||||
const didInit = useRef(false);
|
||||
const [filteredDetailList, setFilteredDetailList] = useState<PrecipitationPropsDetailProps[]>([]);
|
||||
const [copyDetailList, setCopyDetailList] = useState<PrecipitationPropsDetailProps[]>([]);
|
||||
|
||||
@@ -102,6 +111,8 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
|
||||
|
||||
const getTableData = () => {
|
||||
const totals = calculateTotals();
|
||||
totals.infoRnDay = roundNumber(totals.infoRnDay, 1);
|
||||
|
||||
return [
|
||||
{
|
||||
bscFctCd: "",
|
||||
@@ -113,17 +124,20 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if(didInit.current) return;
|
||||
|
||||
if (props.detailList.length > 0) {
|
||||
const filteredList = props.detailList.filter((item) =>
|
||||
props.facilityCd === item.bscFctCd
|
||||
);
|
||||
|
||||
setFilteredDetailList(filteredList);
|
||||
setCopyDetailList(filteredList);
|
||||
|
||||
if (filteredList.length > 0) {
|
||||
const firstDateStr = filteredList[0]?.rainDt;
|
||||
const lastDateStr = filteredList[filteredList.length - 1]?.rainDt;
|
||||
didInit.current = true;
|
||||
const filteredList = props.detailList
|
||||
.map(i => ({ ...i })) // ← 얕은 복제
|
||||
.filter((item) => props.facilityCd === item.bscFctCd);
|
||||
const calcData = CalcRainEffect(filteredList);
|
||||
|
||||
setFilteredDetailList(calcData);
|
||||
setCopyDetailList(calcData);
|
||||
if (calcData.length > 0) {
|
||||
const firstDateStr = calcData[0]?.rainDt;
|
||||
const lastDateStr = calcData[calcData.length - 1]?.rainDt;
|
||||
|
||||
if (firstDateStr) {
|
||||
const firstDate = new Date(firstDateStr);
|
||||
@@ -131,7 +145,6 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
|
||||
setStartDate(firstDate);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastDateStr) {
|
||||
const lastDate = new Date(lastDateStr);
|
||||
if (!isNaN(lastDate.getTime())) {
|
||||
@@ -142,8 +155,24 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
|
||||
}
|
||||
}, [props.detailList, props.facilityCd]);
|
||||
|
||||
if (!startDate || !endDate) {
|
||||
return <div>로딩 중...</div>;
|
||||
const excelDownload = () => {
|
||||
const totData = getTableData();
|
||||
const excelDownList: any[] = [];
|
||||
if(totData.length > 0){
|
||||
totData.forEach((item) => {
|
||||
excelDownList.push({
|
||||
"날짜": item.rainDt,
|
||||
"강수량(mm/일)": roundNumber(item.infoRnDay, 1),
|
||||
"강우일(일)": roundNumber(item.rainDay, 0),
|
||||
"강우영향일(일)": roundNumber(item.rainEffectDay, 0),
|
||||
});
|
||||
});
|
||||
}
|
||||
if (excelDownList && excelDownList.length > 0) {
|
||||
downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.searchYear+'년 '+props.fcltyName + ' 강수현황', sheetNameArray: ['지하수유입량'], headerRange: 'A1:D1' });
|
||||
} else if (totData.length == 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -187,6 +216,9 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
|
||||
</div>
|
||||
</ListDiv>
|
||||
<ListDiv className="h-[550px] overflow-y-auto">
|
||||
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownload}>
|
||||
{"엑셀다운로드"}
|
||||
</Button>
|
||||
<UiTable
|
||||
headName={"강수현황"}
|
||||
tableData={getTableData()}
|
||||
@@ -196,6 +228,7 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
boldArray={[0]}
|
||||
widthFixed={true}
|
||||
/>
|
||||
</ListDiv>
|
||||
</>
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
"use client"
|
||||
/**
|
||||
* 처리시설 연간 운영현황 - 강수현황(메인)
|
||||
*
|
||||
* - 시설별 강수 현황을 조회조건대로 추출하여 표로 보여주는 화면.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
@@ -6,6 +12,7 @@ import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import PrecipitationModal from "./modal/page";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
import UnderComment from "@/app/components/common/UnderComment";
|
||||
|
||||
export default function FacilityPrecipitation() {
|
||||
const {Common
|
||||
@@ -129,7 +136,7 @@ export default function FacilityPrecipitation() {
|
||||
initializeCommonData();
|
||||
searchFacilityPrecipitationList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchFacilityPrecipitationList]);
|
||||
}, [isInit, initializeCommonData, searchFacilityPrecipitationList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
@@ -153,14 +160,6 @@ export default function FacilityPrecipitation() {
|
||||
*/
|
||||
// 조회
|
||||
const searchFacilityPrecipitation = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
console.log('partValue : ', partValue);
|
||||
console.log('regionValue : ', regionValue);
|
||||
console.log('unitWaterShedValue : ', unitWaterShedValue);
|
||||
console.log('middleRegionValue : ', middleRegionValue);
|
||||
console.log('envPartValue : ', envPartValue);
|
||||
console.log('sidoValue : ', sidoValue);
|
||||
console.log('sigunValue : ', sigunValue);
|
||||
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
@@ -231,9 +230,9 @@ export default function FacilityPrecipitation() {
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 강수현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 강수현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
|
||||
</div>
|
||||
<span className="text-2xl font-bold text-gray-500">☞ 강우일은 3mm 이상만 해당 / 강우영향일은 강우일 및 강우일 후 연속 2일간으로 정의</span>
|
||||
<UnderComment divHeight={"3"} commentArray={["강우일은 3mm 이상만 해당 / 강우영향일은 강우일 및 강우일 후 연속 2일간으로 정의"]} />
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
/**
|
||||
* 처리시설 연간 운영현황 - 수질현황
|
||||
*
|
||||
* - 수질현황의 헤더를 만들어주는 컴포넌트
|
||||
*/
|
||||
|
||||
import { TableHead, TableRow } from "@common/components/ui";
|
||||
|
||||
interface TableUpperProps {
|
||||
|
||||
@@ -1,13 +1,30 @@
|
||||
"use client"
|
||||
/**
|
||||
* 처리시설 연간 운영현황 - 수질현황
|
||||
*
|
||||
* - 메인화면에서 선택한 시설의 수질정보를 하루단위로 보여주는 모달.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import CommaToNumber from "@/app/components/common/CommaToNumber";
|
||||
import { roundNumber } from "@/app/components/common/DataForm";
|
||||
import UnderComment from "@/app/components/common/UnderComment";
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { FacilityWaterQltyProps, modalExcelType } from "@/app/store/facilityWaterQlty";
|
||||
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";
|
||||
import FacilityTermModalHeader from "../../../../components/common/FacilityTermModalHeader";
|
||||
import { HeadMakeColSpan } from "../HeadMakeColSpan";
|
||||
|
||||
const commentArrayChungchun = [
|
||||
"청천시 : 강우량이 3mm미만의 날"
|
||||
];
|
||||
|
||||
const commentArrayRain = [
|
||||
"강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날"
|
||||
];
|
||||
|
||||
type ModalProps ={
|
||||
fcltyName: string;
|
||||
facilityCd : string;
|
||||
@@ -39,9 +56,10 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
searchFacilityWaterQltyListHist,
|
||||
Common
|
||||
} = useFoStore((state) => state);
|
||||
const {btnClass} = Common;
|
||||
const {btnClass, COD_YEAR} = Common;
|
||||
const {
|
||||
upHeadListModalYear,
|
||||
upHeadListModalYearCod,
|
||||
facilityWaterQltyYearList,
|
||||
upHeadListModalTms,
|
||||
tmsList,
|
||||
@@ -64,50 +82,62 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
let maxEfflWqltTn = 0;
|
||||
let maxEfflWqltTp = 0;
|
||||
let maxefflWqltToc = 0;
|
||||
let maxefflWqltCod = 0;
|
||||
let maxEfflWqltSs = 0;
|
||||
|
||||
let maxinflAssctBfrWqltBod = 0;
|
||||
let maxinflAssctBfrWqltTn = 0;
|
||||
let maxInflAssctBfrWqltTp = 0;
|
||||
let maxinflAssctBfrWqltToc = 0;
|
||||
let maxinflAssctBfrWqltCod = 0;
|
||||
let maxinflAssctBfrWqltSs = 0;
|
||||
|
||||
let maxTpInflWqltBod = 0;
|
||||
let maxTpInflWqltTp = 0;
|
||||
let maxNoProcessInflAmnt = 0;
|
||||
let maxInfoRnDay = 0;
|
||||
|
||||
|
||||
// 초기값 설정
|
||||
let minEfflWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltBod) : 0;
|
||||
let minEfflWqltTn = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltTn) : 0;
|
||||
let minEfflWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltTp) : 0;
|
||||
let minefflWqltToc = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltToc) : 0;
|
||||
let minefflWqltCod = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltCod) : 0;
|
||||
let minEfflWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltSs) : 0;
|
||||
|
||||
let mininflAssctBfrWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltBod) : 0;
|
||||
let mininflAssctBfrWqltTn = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltTn) : 0;
|
||||
let minInflAssctBfrWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltTp) : 0;
|
||||
let mininflAssctBfrWqltToc = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltToc) : 0;
|
||||
let mininflAssctBfrWqltCod = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltCod) : 0;
|
||||
let mininflAssctBfrWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltSs) : 0;
|
||||
|
||||
let minTpInflWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.tpInflWqltBod) : 0;
|
||||
let minTpInflWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.tpInflWqltTp) : 0;
|
||||
|
||||
let minTpInflWqltBod = 99999999;
|
||||
let minTpInflWqltTp = 99999999;
|
||||
let minNoProcessInflAmnt = 99999999;
|
||||
let minInfoRnDay = filteredData.length > 0 ? parseNumber(filteredData[0]?.infoRnDay) : 0;
|
||||
|
||||
let avgEfflWqltBod = 0;
|
||||
let avgEfflWqltTn = 0;
|
||||
let avgEfflWqltTp = 0;
|
||||
let avgefflWqltToc = 0;
|
||||
let avgefflWqltCod = 0;
|
||||
let avgEfflWqltSs = 0;
|
||||
|
||||
let avginflAssctBfrWqltBod = 0;
|
||||
let avginflAssctBfrWqltTn = 0;
|
||||
let avgInflAssctBfrWqltTp = 0;
|
||||
let avginflAssctBfrWqltToc = 0;
|
||||
let avginflAssctBfrWqltCod = 0;
|
||||
let avginflAssctBfrWqltSs = 0;
|
||||
|
||||
let avgTpInflWqltBod = 0;
|
||||
let avgTpInflWqltTp = 0;
|
||||
let tpInflWqltBodCnt = 0;
|
||||
let tpInflWqltTpCnt = 0;
|
||||
let avgNoProcessInflAmnt = 0;
|
||||
let noProcessInflAmntCnt = 0;
|
||||
|
||||
let avgInfoRnDay = 0;
|
||||
|
||||
@@ -116,17 +146,23 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
const efflWqltTn = parseNumber(item.efflWqltTn);
|
||||
const efflWqltTp = parseNumber(item.efflWqltTp);
|
||||
const efflWqltToc = parseNumber(item.efflWqltToc);
|
||||
const efflWqltCod = parseNumber(item.efflWqltCod?item.efflWqltCod.replaceAll("(","").replaceAll(")",""):0);
|
||||
const efflWqltSs = parseNumber(item.efflWqltSs);
|
||||
|
||||
const inflAssctBfrWqltBod = parseNumber(item.inflAssctBfrWqltBod);
|
||||
const inflAssctBfrWqltTn = parseNumber(item.inflAssctBfrWqltTn);
|
||||
const inflAssctBfrWqltTp = parseNumber(item.inflAssctBfrWqltTp);
|
||||
const inflAssctBfrWqltToc = parseNumber(item.inflAssctBfrWqltToc);
|
||||
const inflAssctBfrWqltCod = parseNumber(item.inflAssctBfrWqltCod?item.inflAssctBfrWqltCod.replaceAll("(","").replaceAll(")",""):0);
|
||||
const inflAssctBfrWqltSs = parseNumber(item.inflAssctBfrWqltSs);
|
||||
|
||||
|
||||
const tpInflWqltBod = parseNumber(item.tpInflWqltBod);
|
||||
const tpInflWqltTp = parseNumber(item.tpInflWqltTp);
|
||||
if(item.tpInflWqltBod != null && item.tpInflWqltBod.trim() != '' && item.tpInflWqltBod != undefined ){
|
||||
tpInflWqltBodCnt += 1;
|
||||
}
|
||||
if(item.tpInflWqltTp != null && item.tpInflWqltTp.trim() != '' && item.tpInflWqltTp != undefined ){
|
||||
tpInflWqltTpCnt += 1;
|
||||
}
|
||||
|
||||
const infoRnDay = parseNumber(item.infoRnDay);
|
||||
|
||||
@@ -134,12 +170,14 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
maxEfflWqltTn = Math.max(maxEfflWqltTn, efflWqltTn);
|
||||
maxEfflWqltTp = Math.max(maxEfflWqltTp, efflWqltTp);
|
||||
maxefflWqltToc = Math.max(maxefflWqltToc, efflWqltToc);
|
||||
maxefflWqltCod = Math.max(maxefflWqltCod, efflWqltCod);
|
||||
maxEfflWqltSs = Math.max(maxEfflWqltSs, efflWqltSs);
|
||||
|
||||
maxinflAssctBfrWqltBod = Math.max(maxinflAssctBfrWqltBod, inflAssctBfrWqltBod);
|
||||
maxinflAssctBfrWqltTn = Math.max(maxinflAssctBfrWqltTn, inflAssctBfrWqltTn);
|
||||
maxInflAssctBfrWqltTp = Math.max(maxInflAssctBfrWqltTp, inflAssctBfrWqltTp);
|
||||
maxinflAssctBfrWqltToc = Math.max(maxinflAssctBfrWqltToc, inflAssctBfrWqltToc);
|
||||
maxinflAssctBfrWqltCod = Math.max(maxinflAssctBfrWqltCod, inflAssctBfrWqltCod);
|
||||
maxinflAssctBfrWqltSs = Math.max(maxinflAssctBfrWqltSs, inflAssctBfrWqltSs);
|
||||
|
||||
maxTpInflWqltBod = Math.max(maxTpInflWqltBod, tpInflWqltBod);
|
||||
@@ -151,16 +189,24 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
minEfflWqltTn = Math.min(minEfflWqltTn, efflWqltTn);
|
||||
minEfflWqltTp = Math.min(minEfflWqltTp, efflWqltTp);
|
||||
minefflWqltToc = Math.min(minefflWqltToc, efflWqltToc);
|
||||
minefflWqltCod = Math.min(minefflWqltCod, efflWqltCod);
|
||||
minEfflWqltSs = Math.min(minEfflWqltSs, efflWqltSs);
|
||||
|
||||
mininflAssctBfrWqltBod = Math.min(mininflAssctBfrWqltBod, inflAssctBfrWqltBod);
|
||||
mininflAssctBfrWqltTn = Math.min(mininflAssctBfrWqltTn, inflAssctBfrWqltTn);
|
||||
minInflAssctBfrWqltTp = Math.min(minInflAssctBfrWqltTp, inflAssctBfrWqltTp);
|
||||
mininflAssctBfrWqltToc = Math.min(mininflAssctBfrWqltToc, inflAssctBfrWqltToc);
|
||||
mininflAssctBfrWqltCod = Math.min(mininflAssctBfrWqltToc, inflAssctBfrWqltCod);
|
||||
mininflAssctBfrWqltSs = Math.min(mininflAssctBfrWqltSs, inflAssctBfrWqltSs);
|
||||
|
||||
minTpInflWqltBod = Math.min(minTpInflWqltBod, tpInflWqltBod);
|
||||
minTpInflWqltTp = Math.min(minTpInflWqltTp, tpInflWqltTp);
|
||||
if(item.tpInflWqltBod != null && item.tpInflWqltBod.trim() != '' && item.tpInflWqltBod != undefined ){
|
||||
minTpInflWqltBod = Math.min(minTpInflWqltBod, tpInflWqltBod);
|
||||
avgTpInflWqltBod += tpInflWqltBod;
|
||||
}
|
||||
if(item.tpInflWqltTp != null && item.tpInflWqltTp.trim() != '' && item.tpInflWqltTp != undefined ){
|
||||
minTpInflWqltTp = Math.min(minTpInflWqltTp, tpInflWqltTp);
|
||||
avgTpInflWqltTp += tpInflWqltTp;
|
||||
}
|
||||
|
||||
minInfoRnDay = Math.min(minInfoRnDay, infoRnDay);
|
||||
|
||||
@@ -168,16 +214,23 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
avgEfflWqltTn += efflWqltTn;
|
||||
avgEfflWqltTp += efflWqltTp;
|
||||
avgefflWqltToc += efflWqltToc;
|
||||
avgefflWqltCod += efflWqltCod;
|
||||
avgEfflWqltSs += efflWqltSs;
|
||||
|
||||
avginflAssctBfrWqltBod += inflAssctBfrWqltBod;
|
||||
avginflAssctBfrWqltTn += inflAssctBfrWqltTn;
|
||||
avgInflAssctBfrWqltTp += inflAssctBfrWqltTp;
|
||||
avginflAssctBfrWqltToc += inflAssctBfrWqltToc;
|
||||
avginflAssctBfrWqltCod += inflAssctBfrWqltCod;
|
||||
avginflAssctBfrWqltSs += inflAssctBfrWqltSs;
|
||||
|
||||
avgTpInflWqltBod += tpInflWqltBod;
|
||||
avgTpInflWqltTp += tpInflWqltTp;
|
||||
if(item.noProcessInflAmnt && item.noProcessInflAmnt.toString().trim() != '' && item.noProcessInflAmnt != undefined){
|
||||
const noProcessInflAmnt = Number(item.noProcessInflAmnt.toString().replaceAll(',',''));
|
||||
avgNoProcessInflAmnt += noProcessInflAmnt;
|
||||
maxNoProcessInflAmnt = Math.max(maxNoProcessInflAmnt, noProcessInflAmnt);
|
||||
minNoProcessInflAmnt = Math.min(minNoProcessInflAmnt, noProcessInflAmnt);
|
||||
noProcessInflAmntCnt +=1;
|
||||
}
|
||||
|
||||
avgInfoRnDay += infoRnDay;
|
||||
});
|
||||
@@ -185,16 +238,18 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
const newFilteredData = [
|
||||
{
|
||||
msrDt: '평균',
|
||||
efflWqltBod: filteredData.length==0?'0.0':(Math.round(avgEfflWqltBod / filteredData.length * 10) / 10).toFixed(1),
|
||||
efflWqltToc: filteredData.length==0?'0.0':(Math.round(avgefflWqltToc / filteredData.length * 10) / 10).toFixed(1),
|
||||
efflWqltSs: filteredData.length==0?'0.0':(Math.round(avgEfflWqltSs / filteredData.length * 10) / 10).toFixed(1),
|
||||
efflWqltTn: filteredData.length==0?'0.000':(Math.round(avgEfflWqltTn / filteredData.length * 1000) / 1000).toFixed(3),
|
||||
efflWqltTp: filteredData.length==0?'0.000':(Math.round(avgEfflWqltTp / filteredData.length * 1000) / 1000).toFixed(3),
|
||||
inflAssctBfrWqltBod: filteredData.length==0?'0.0':(Math.round(avginflAssctBfrWqltBod / filteredData.length * 10) / 10).toFixed(1),
|
||||
inflAssctBfrWqltTn: filteredData.length==0?'0.000':(Math.round(avginflAssctBfrWqltTn / filteredData.length * 1000) / 1000).toFixed(3),
|
||||
inflAssctBfrWqltTp: filteredData.length==0?'0.000':(Math.round(avgInflAssctBfrWqltTp / filteredData.length * 1000) / 1000).toFixed(3),
|
||||
inflAssctBfrWqltToc: filteredData.length==0?'0.0':(Math.round(avginflAssctBfrWqltToc / filteredData.length * 10) / 10).toFixed(1),
|
||||
inflAssctBfrWqltSs: filteredData.length==0?'0.0':(Math.round(avginflAssctBfrWqltSs / filteredData.length * 10) / 10).toFixed(1),
|
||||
efflWqltBod: filteredData.length==0 || avgEfflWqltBod===0?'0.0':roundNumber((avgEfflWqltBod / filteredData.length), 1),
|
||||
efflWqltToc: filteredData.length==0 || avgefflWqltToc===0?'0.0':roundNumber((avgefflWqltToc / filteredData.length), 1),
|
||||
efflWqltCod: filteredData.length==0 || avgefflWqltCod===0?"(0.0)":"("+roundNumber((avgefflWqltCod / filteredData.length), 1)+")",
|
||||
efflWqltSs: filteredData.length==0 || avgEfflWqltSs===0?'0.0':roundNumber((avgEfflWqltSs / filteredData.length), 1),
|
||||
efflWqltTn: filteredData.length==0 || avgEfflWqltTn ===0?'0.000':roundNumber((avgEfflWqltTn / filteredData.length), 3),
|
||||
efflWqltTp: filteredData.length==0 || avgEfflWqltTp ===0?'0.000':roundNumber((avgEfflWqltTp / filteredData.length), 3),
|
||||
inflAssctBfrWqltBod: filteredData.length==0 || avginflAssctBfrWqltBod===0?'0.0':roundNumber((avginflAssctBfrWqltBod / filteredData.length), 1),
|
||||
inflAssctBfrWqltTn: filteredData.length==0 || avginflAssctBfrWqltTn===0?'0.000':roundNumber((avginflAssctBfrWqltTn / filteredData.length), 3),
|
||||
inflAssctBfrWqltTp: filteredData.length==0 || avgInflAssctBfrWqltTp===0?'0.000':roundNumber((avgInflAssctBfrWqltTp / filteredData.length), 3),
|
||||
inflAssctBfrWqltToc: filteredData.length==0 || avginflAssctBfrWqltToc===0?'0.0':roundNumber((avginflAssctBfrWqltToc / filteredData.length), 1),
|
||||
inflAssctBfrWqltCod: filteredData.length==0 || avginflAssctBfrWqltCod===0?'(0.0)':"("+roundNumber((avginflAssctBfrWqltCod / filteredData.length), 1)+")",
|
||||
inflAssctBfrWqltSs: filteredData.length==0 || avginflAssctBfrWqltSs===0?'0.0':roundNumber((avginflAssctBfrWqltSs / filteredData.length), 1),
|
||||
bscFctCd: "",
|
||||
bscFctNm: "",
|
||||
lclgvrnmntNm: "",
|
||||
@@ -202,22 +257,25 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
sggNm: "",
|
||||
addr: "",
|
||||
fctCpc: 0,
|
||||
infoRnDay: filteredData.length==0?'0.0':(Math.round(avgInfoRnDay / filteredData.length * 10) / 10).toFixed(1),
|
||||
tpInflWqltBod: filteredData.length==0?'0.0':(Math.round(avgTpInflWqltBod / filteredData.length * 10) / 10).toFixed(1),
|
||||
tpInflWqltTp: filteredData.length==0?'0.000':(Math.round(avgTpInflWqltTp / filteredData.length * 1000) / 1000).toFixed(3)
|
||||
noProcessInflAmnt : roundNumber(avgNoProcessInflAmnt / noProcessInflAmntCnt, 0),
|
||||
infoRnDay: filteredData.length==0 || avgInfoRnDay===0?'0.0':roundNumber(avgInfoRnDay / filteredData.length, 1),
|
||||
tpInflWqltBod: filteredData.length==0 || avgTpInflWqltBod ===0 ?'0.0':roundNumber(avgTpInflWqltBod / tpInflWqltBodCnt, 1),
|
||||
tpInflWqltTp: filteredData.length==0 || avgTpInflWqltTp === 0?'0.000':roundNumber(avgTpInflWqltTp / tpInflWqltTpCnt, 3)
|
||||
},
|
||||
{
|
||||
msrDt : '최대',
|
||||
efflWqltBod : Math.round(maxEfflWqltBod * 10) / 10?(Math.round(maxEfflWqltBod * 10) / 10).toFixed(1):'0.0',
|
||||
efflWqltToc : Math.round(maxefflWqltToc * 10) / 10?(Math.round(maxefflWqltToc * 10) / 10).toFixed(1):'0.0',
|
||||
efflWqltSs : Math.round(maxEfflWqltSs * 10) / 10?(Math.round(maxEfflWqltSs * 10) / 10).toFixed(1):'0.0',
|
||||
efflWqltTn : Math.round(maxEfflWqltTn * 1000) / 1000?(Math.round(maxEfflWqltTn * 1000) / 1000).toFixed(3):'0.000',
|
||||
efflWqltTp : Math.round(maxEfflWqltTp * 1000) / 1000?(Math.round(maxEfflWqltTp * 1000) / 1000).toFixed(3):'0.000',
|
||||
inflAssctBfrWqltBod : Math.round(maxinflAssctBfrWqltBod * 10) / 10?(Math.round(maxinflAssctBfrWqltBod * 10) / 10).toFixed(1):'0.0',
|
||||
inflAssctBfrWqltTn : Math.round(maxinflAssctBfrWqltTn * 1000) / 1000?(Math.round(maxinflAssctBfrWqltTn * 1000) / 1000).toFixed(3):'0.000',
|
||||
inflAssctBfrWqltTp : Math.round(maxInflAssctBfrWqltTp * 1000) / 1000?(Math.round(maxInflAssctBfrWqltTp * 1000) / 1000).toFixed(3):'0.000',
|
||||
inflAssctBfrWqltToc : Math.round(maxinflAssctBfrWqltToc * 10) / 10?(Math.round(maxinflAssctBfrWqltToc * 10) / 10).toFixed(1):'0.0',
|
||||
inflAssctBfrWqltSs : Math.round(maxinflAssctBfrWqltSs * 10) / 10?(Math.round(maxinflAssctBfrWqltSs * 10) / 10).toFixed(1):'0.0',
|
||||
efflWqltBod : Math.round(maxEfflWqltBod * 10) / 10?roundNumber(maxEfflWqltBod, 1):'0.0',
|
||||
efflWqltToc : Math.round(maxefflWqltToc * 10) / 10?roundNumber(maxefflWqltToc, 1):'0.0',
|
||||
efflWqltCod : Math.round(maxefflWqltCod * 10) / 10?"("+roundNumber(maxefflWqltCod, 1)+")":'(0.0)',
|
||||
efflWqltSs : Math.round(maxEfflWqltSs * 10) / 10?roundNumber(maxEfflWqltSs, 1):'0.0',
|
||||
efflWqltTn : Math.round(maxEfflWqltTn * 1000) / 1000?roundNumber(maxEfflWqltTn, 3):'0.000',
|
||||
efflWqltTp : Math.round(maxEfflWqltTp * 1000) / 1000?roundNumber(maxEfflWqltTp, 3):'0.000',
|
||||
inflAssctBfrWqltBod : Math.round(maxinflAssctBfrWqltBod * 10) / 10?roundNumber(maxinflAssctBfrWqltBod, 1):'0.0',
|
||||
inflAssctBfrWqltTn : Math.round(maxinflAssctBfrWqltTn * 1000) / 1000?roundNumber(maxinflAssctBfrWqltTn, 3):'0.000',
|
||||
inflAssctBfrWqltTp : Math.round(maxInflAssctBfrWqltTp * 1000) / 1000?roundNumber(maxInflAssctBfrWqltTp, 3):'0.000',
|
||||
inflAssctBfrWqltToc : Math.round(maxinflAssctBfrWqltToc * 10) / 10?roundNumber(maxinflAssctBfrWqltToc, 1):'0.0',
|
||||
inflAssctBfrWqltCod : Math.round(maxinflAssctBfrWqltCod * 10) / 10?"("+roundNumber(maxinflAssctBfrWqltCod, 1)+")":'(0.0)',
|
||||
inflAssctBfrWqltSs : Math.round(maxinflAssctBfrWqltSs * 10) / 10?roundNumber(maxinflAssctBfrWqltSs, 1):'0.0',
|
||||
bscFctCd: "",
|
||||
bscFctNm: "",
|
||||
lclgvrnmntNm: "",
|
||||
@@ -225,22 +283,25 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
sggNm: "",
|
||||
addr: "",
|
||||
fctCpc: 0,
|
||||
infoRnDay: 0,
|
||||
tpInflWqltBod: Math.round(maxTpInflWqltBod * 10) / 10?(Math.round(maxTpInflWqltBod * 10) / 10).toFixed(1):'0.0',
|
||||
tpInflWqltTp: Math.round(maxTpInflWqltTp * 1000) / 1000?(Math.round(maxTpInflWqltTp * 1000) / 1000).toFixed(3):'0.000'
|
||||
noProcessInflAmnt : roundNumber(maxNoProcessInflAmnt, 0),
|
||||
infoRnDay: Math.round(maxInfoRnDay * 10) / 10?roundNumber(maxInfoRnDay, 1):'0.0',
|
||||
tpInflWqltBod: Math.round(maxTpInflWqltBod * 10) / 10?roundNumber(maxTpInflWqltBod, 1):'0.0',
|
||||
tpInflWqltTp: Math.round(maxTpInflWqltTp * 1000) / 1000?roundNumber(maxTpInflWqltTp, 3):'0.000'
|
||||
},
|
||||
{
|
||||
msrDt : '최소',
|
||||
efflWqltBod : Math.round(minEfflWqltBod * 10) / 10?(Math.round(minEfflWqltBod?minEfflWqltBod:0 * 10) / 10).toFixed(1) : '0.0',
|
||||
efflWqltToc : Math.round(minefflWqltToc * 10) / 10?(Math.round(minefflWqltToc?minefflWqltToc:0 * 10) / 10).toFixed(1) : '0.0',
|
||||
efflWqltSs : Math.round(minEfflWqltSs * 10) / 10?(Math.round(minEfflWqltSs * 10) / 10).toFixed(1) : '0.0',
|
||||
efflWqltTn : Math.round(minEfflWqltTn * 1000) / 1000?(Math.round(minEfflWqltTn * 1000) / 1000).toFixed(3) : '0.000',
|
||||
efflWqltTp : Math.round(minEfflWqltTp * 1000) / 1000?(Math.round(minEfflWqltTp * 1000) / 1000).toFixed(3) : '0.000',
|
||||
inflAssctBfrWqltBod : Math.round(mininflAssctBfrWqltBod * 10) / 10?(Math.round(mininflAssctBfrWqltBod * 10) / 10).toFixed(1) : '0.0',
|
||||
inflAssctBfrWqltTn : Math.round(mininflAssctBfrWqltTn * 1000) / 1000?(Math.round(mininflAssctBfrWqltTn * 1000) / 1000).toFixed(3) : '0.000',
|
||||
inflAssctBfrWqltTp : Math.round(minInflAssctBfrWqltTp * 1000) / 1000?(Math.round(minInflAssctBfrWqltTp * 1000) / 1000).toFixed(3) : '0.000',
|
||||
inflAssctBfrWqltToc : Math.round(mininflAssctBfrWqltToc * 10) / 10?(Math.round(mininflAssctBfrWqltToc * 10) / 10).toFixed(1) : '0.0',
|
||||
inflAssctBfrWqltSs : Math.round(mininflAssctBfrWqltSs * 10) / 10?(Math.round(mininflAssctBfrWqltSs * 10) / 10).toFixed(1) : '0.0',
|
||||
efflWqltBod : Math.round(minEfflWqltBod * 10) / 10?roundNumber(minEfflWqltBod, 1) : '0.0',
|
||||
efflWqltToc : Math.round(minefflWqltToc * 10) / 10?roundNumber(minefflWqltToc, 1) : '0.0',
|
||||
efflWqltCod : Math.round(minefflWqltCod * 10) / 10?"("+roundNumber(minefflWqltCod, 1)+")" : '(0.0)',
|
||||
efflWqltSs : Math.round(minEfflWqltSs * 10) / 10?roundNumber(minEfflWqltSs, 1) : '0.0',
|
||||
efflWqltTn : Math.round(minEfflWqltTn * 1000) / 1000?roundNumber(minEfflWqltTn, 3) : '0.000',
|
||||
efflWqltTp : Math.round(minEfflWqltTp * 1000) / 1000?roundNumber(minEfflWqltTp, 3) : '0.000',
|
||||
inflAssctBfrWqltBod : Math.round(mininflAssctBfrWqltBod * 10) / 10?roundNumber(mininflAssctBfrWqltBod, 1) : '0.0',
|
||||
inflAssctBfrWqltTn : Math.round(mininflAssctBfrWqltTn * 1000) / 1000?roundNumber(mininflAssctBfrWqltTn, 3) : '0.000',
|
||||
inflAssctBfrWqltTp : Math.round(minInflAssctBfrWqltTp * 1000) / 1000?roundNumber(minInflAssctBfrWqltTp, 3) : '0.000',
|
||||
inflAssctBfrWqltToc : Math.round(mininflAssctBfrWqltToc * 10) / 10?roundNumber(mininflAssctBfrWqltToc, 1) : '0.0',
|
||||
inflAssctBfrWqltCod : Math.round(mininflAssctBfrWqltCod * 10) / 10?"("+roundNumber(mininflAssctBfrWqltCod, 1)+")" : '(0.0)',
|
||||
inflAssctBfrWqltSs : Math.round(mininflAssctBfrWqltSs * 10) / 10?roundNumber(mininflAssctBfrWqltSs, 1) : '0.0',
|
||||
bscFctCd: "",
|
||||
bscFctNm: "",
|
||||
lclgvrnmntNm: "",
|
||||
@@ -248,12 +309,14 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
sggNm: "",
|
||||
addr: "",
|
||||
fctCpc: 0,
|
||||
infoRnDay: 0,
|
||||
tpInflWqltBod: Math.round(minTpInflWqltBod * 10) / 10?'0.0':(Math.round(minTpInflWqltBod * 10) / 10).toFixed(1),
|
||||
tpInflWqltTp: Math.round(minTpInflWqltTp * 1000) / 1000?'0.000':(Math.round(minTpInflWqltTp * 1000) / 1000).toFixed(3)
|
||||
noProcessInflAmnt : roundNumber(minNoProcessInflAmnt, 0),
|
||||
infoRnDay: Math.round(minInfoRnDay * 10) / 10?'0.0':roundNumber(minInfoRnDay, 1),
|
||||
tpInflWqltBod: Math.round(minTpInflWqltBod * 10) / 10 && minTpInflWqltBod != 99999999?roundNumber(minTpInflWqltBod, 1):'0.0',
|
||||
tpInflWqltTp: Math.round(minTpInflWqltTp * 1000) / 1000 && minTpInflWqltTp != 99999999?roundNumber(minTpInflWqltTp, 3):'0.000'
|
||||
},
|
||||
...filteredData
|
||||
];
|
||||
|
||||
return newFilteredData;
|
||||
}
|
||||
|
||||
@@ -293,22 +356,29 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
copyYearList.forEach((item) => {
|
||||
excelDownList.push({
|
||||
날짜: item.msrDt,
|
||||
"유입BOD(mg/L)": item.inflAssctBfrWqltBod,
|
||||
"유입TOC(COD)(mg/L)": item.inflAssctBfrWqltToc,
|
||||
"유입SS(mg/L)": item.inflAssctBfrWqltSs,
|
||||
"유입TN(mg/L)": item.inflAssctBfrWqltTn,
|
||||
"유입TP(mg/L)": item.inflAssctBfrWqltTp,
|
||||
"유출BOD(mg/L)": item.efflWqltBod,
|
||||
"유출TOC(COD)(mg/L)": item.efflWqltToc,
|
||||
"유출SS(mg/L)": item.efflWqltSs,
|
||||
"유출TN(mg/L)": item.efflWqltTn,
|
||||
"유출TP(mg/L)": item.efflWqltTp,
|
||||
/* "강우량(mm/일)": item.infoRnDay?item.infoRnDay.toString():"0.0", */
|
||||
"유입BOD(mg/L)": CommaToNumber(item.inflAssctBfrWqltBod),
|
||||
"유입TOC(COD)(mg/L)": CommaToNumber(item.inflAssctBfrWqltToc),
|
||||
"유입SS(mg/L)": CommaToNumber(item.inflAssctBfrWqltSs),
|
||||
"유입TN(mg/L)": CommaToNumber(item.inflAssctBfrWqltTn),
|
||||
"유입TP(mg/L)": CommaToNumber(item.inflAssctBfrWqltTp),
|
||||
"유출BOD(mg/L)": CommaToNumber(item.efflWqltBod),
|
||||
"유출TOC(COD)(mg/L)": CommaToNumber(item.efflWqltToc),
|
||||
"유출SS(mg/L)": CommaToNumber(item.efflWqltSs),
|
||||
"유출TN(mg/L)": CommaToNumber(item.efflWqltTn),
|
||||
"유출TP(mg/L)": CommaToNumber(item.efflWqltTp),
|
||||
"강우량(mm/일)": CommaToNumber(item.infoRnDay?item.infoRnDay.toString():"0.0"),
|
||||
});
|
||||
});
|
||||
}
|
||||
if (excelDownList && excelDownList.length > 0) {
|
||||
downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: searchYear+'년 '+fcltyName + ' 수질현황', sheetNameArray: [fcltyName + ' 수질현황'], headerRange: 'A1:K1' });
|
||||
downloadExcelFormat(
|
||||
{ data: JSON.parse(JSON.stringify(excelDownList))
|
||||
, fileName: searchYear+'년 '+fcltyName + ' 수질현황'
|
||||
, sheetNameArray: [fcltyName + ' 수질현황']
|
||||
, headerRange: 'A1:L1'
|
||||
, decimalArray1: [1,2,3,6,7,8,11]
|
||||
, decimalArray3: [4,5,9,10]
|
||||
});
|
||||
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
@@ -338,7 +408,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
headlist={Number(searchYear)<COD_YEAR?upHeadListModalYearCod:upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
@@ -366,7 +436,9 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalTms} layoutNum={4} />
|
||||
</UiTable>
|
||||
{msrmtDate != yesterDayStr?.replaceAll('-','')?<h3 className="text-2xl text-left text-gray-500">※전날 데이터 결측으로 인해 가장 최근 데이터 표출함</h3> : ''}
|
||||
{msrmtDate != yesterDayStr?.replaceAll('-','') ? (
|
||||
<UnderComment commentArray={["전날 데이터 결측으로 인해 가장 최근 데이터 표출함"]} divHeight="0"/>
|
||||
) : null}
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
@@ -380,11 +452,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<div className="overflow-y-auto h-[500px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
headlist={Number(searchYear)<COD_YEAR?upHeadListModalYearCod:upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
@@ -407,11 +479,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<div className="overflow-y-auto h-[500px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
headlist={Number(searchYear)<COD_YEAR?upHeadListModalYearCod:upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
@@ -434,11 +506,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<div className="overflow-y-auto h-[500px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
headlist={Number(searchYear)<COD_YEAR?upHeadListModalYearCod:upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
@@ -449,9 +521,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
|
||||
</UiTable>
|
||||
</div>
|
||||
<div className="mt-14">
|
||||
<span className="text-2xl font-bold text-gray-500">☞ 청천시 : 강우량이 3mm미만의 날</span>
|
||||
</div>
|
||||
<UnderComment commentArray={commentArrayChungchun} divHeight="10"/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_rain">
|
||||
@@ -464,11 +534,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<div className="overflow-y-auto h-[500px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
headlist={Number(searchYear)<COD_YEAR?upHeadListModalYearCod:upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
@@ -479,9 +549,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
|
||||
</UiTable>
|
||||
</div>
|
||||
<div className="mt-14">
|
||||
<span className="text-2xl font-bold text-gray-500">☞ 강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날</span>
|
||||
</div>
|
||||
<UnderComment commentArray={commentArrayRain} divHeight="10"/>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</TabsContent>
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
"use client"
|
||||
/**
|
||||
* 처리시설 연간 운영현황 - 수질현황
|
||||
*
|
||||
* - 시설별 수질 현황을 조회조건대로 추출하여 표로 보여주는 화면.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import type { FacilityWaterQltyProps } from "@/app/store/facilityWaterQlty";
|
||||
import { ContentsDiv, downloadExcelFormat, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import WaterQualityModal from "./modal/page";
|
||||
import type { FacilityWaterQltyProps } from "@/app/store/facilityWaterQlty";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
|
||||
export default function ProcessFacilitySearch() {
|
||||
const { Common
|
||||
@@ -134,16 +140,27 @@ export default function ProcessFacilitySearch() {
|
||||
initializeCommonData();
|
||||
searchFacilityWaterQltyList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchFacilityWaterQltyList]);
|
||||
}, [isInit, initializeCommonData, searchFacilityWaterQltyList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
downloadExcelFormat(
|
||||
{
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '시설별 수질현황',
|
||||
sheetNameArray: ['시설별 수질현황'],
|
||||
headerRange: 'A1:T1',
|
||||
decimalArray1:[10,11,12,15,16,17],
|
||||
decimalArray3:[13,14,18,19]
|
||||
}
|
||||
);
|
||||
|
||||
/* downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '시설별 수질현황',
|
||||
sheetNameArray: ['시설별 수질현황'],
|
||||
headerRange: 'A1:T1'
|
||||
});
|
||||
}); */
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
@@ -163,7 +180,6 @@ export default function ProcessFacilitySearch() {
|
||||
}, [searchFcltyQltyList]);
|
||||
|
||||
const total = facilityWaterQltyCount || 1;
|
||||
console.log('total : ', total);
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="시설별 수질현황" />
|
||||
@@ -191,7 +207,7 @@ export default function ProcessFacilitySearch() {
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 수질현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total<10?facilityWaterQltyList.length:total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 수질현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total<10?facilityWaterQltyList.length:total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
"use client"
|
||||
/**
|
||||
* 처리시설 연간 운영현황 - 유량현황(모달))
|
||||
*
|
||||
* - 선택한 시설의 유량 정보를 하루 단위로 표로 출력해주는 모달
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import FacilityTermModalHeader from "@/app/components/common/FacilityTermModalHeader";
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { FlowRateModalInterface, modalExcelType } from "@/app/store/flowRate";
|
||||
@@ -7,6 +13,9 @@ import { Button, TabsContent } from "@common/components/ui";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import type { ReturnType } from "../../../../components/common/FacilityTermModalHeader";
|
||||
import { roundUp } from "@/app/store/common";
|
||||
import { roundNumber } from "@/app/components/common/DataForm";
|
||||
import UnderComment from "@/app/components/common/UnderComment";
|
||||
import CommaToNumber from "@/app/components/common/CommaToNumber";
|
||||
|
||||
const tabList = [
|
||||
{ value: 'tab_term_year', label: '연간' },
|
||||
@@ -59,6 +68,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
|
||||
let maxreturnAmnt = 0;
|
||||
let maxefflAmnt = 0;
|
||||
let maxinfoRnDay = 0;
|
||||
let maxNoProcessInflAmnt = 0;
|
||||
|
||||
// 초기값 설정
|
||||
let mintotInflAmnt = parseNumber(filteredData[0]?.totInflAmnt);
|
||||
@@ -67,6 +77,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
|
||||
let minreturnAmnt = parseNumber(filteredData[0]?.returnAmnt);
|
||||
let minefflAmnt = parseNumber(filteredData[0]?.efflAmnt);
|
||||
let mininfoRnDay = parseNumber(filteredData[0]?.infoRnDay && filteredData[0]?.infoRnDay.toString().trim() !== 'x' ? filteredData[0]?.infoRnDay.toString().trim() : 0);
|
||||
let minNoProcessInflAmnt = 99999999;
|
||||
|
||||
let avgtotInflAmnt = 0;
|
||||
let avginflAmnt = 0;
|
||||
@@ -74,8 +85,9 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
|
||||
let avgreturnAmnt = 0;
|
||||
let avgefflAmnt = 0;
|
||||
let avginfoRnDay = 0;
|
||||
|
||||
console.log('filteredData', filteredData);
|
||||
let avgNoProcessInflAmnt = 0;
|
||||
let noProcessInflAmntCnt = 0;
|
||||
|
||||
filteredData.forEach((item: FlowRateModalInterface) => {
|
||||
const totInflAmnt = parseNumber(item.totInflAmnt);
|
||||
const inflAmnt = parseNumber(item.inflAmnt);
|
||||
@@ -83,6 +95,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
|
||||
const returnAmnt = parseNumber(item.returnAmnt);
|
||||
const efflAmnt = parseNumber(item.efflAmnt);
|
||||
const infoRnDay = parseNumber(item.infoRnDay && item.infoRnDay.toString().trim() !== 'x' ? item.infoRnDay.toString().trim() : 0);
|
||||
|
||||
maxtotInflAmnt = Math.max(maxtotInflAmnt, totInflAmnt);
|
||||
maxinflAmnt = Math.max(maxinflAmnt, inflAmnt);
|
||||
maxsumFlow = Math.max(maxsumFlow, sumFlow);
|
||||
@@ -103,16 +116,25 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
|
||||
avgreturnAmnt += returnAmnt;
|
||||
avgefflAmnt += efflAmnt;
|
||||
avginfoRnDay += infoRnDay;
|
||||
|
||||
if(item.noProcessInflAmnt && item.noProcessInflAmnt.toString().trim() != '' && item.noProcessInflAmnt != undefined){
|
||||
const noProcessInflAmnt = Number(item.noProcessInflAmnt.toString().replaceAll(',',''));
|
||||
avgNoProcessInflAmnt += noProcessInflAmnt;
|
||||
maxNoProcessInflAmnt = Math.max(maxNoProcessInflAmnt, noProcessInflAmnt);
|
||||
minNoProcessInflAmnt = Math.min(minNoProcessInflAmnt, noProcessInflAmnt);
|
||||
noProcessInflAmntCnt +=1;
|
||||
}
|
||||
});
|
||||
|
||||
const newFilteredData = [
|
||||
{
|
||||
msrDt: '평균',
|
||||
totInflAmnt: roundUp((avgtotInflAmnt / filteredData.length), 0),
|
||||
inflAmnt: roundUp((avginflAmnt / filteredData.length), 0),
|
||||
sumFlow: roundUp((avgsumFlow / filteredData.length), 0),
|
||||
returnAmnt: roundUp((avgreturnAmnt / filteredData.length), 0),
|
||||
efflAmnt: roundUp((avgefflAmnt / filteredData.length), 0),
|
||||
totInflAmnt: avgtotInflAmnt && avgtotInflAmnt!=0 ? roundUp((avgtotInflAmnt / filteredData.length), 0) : 0,
|
||||
inflAmnt: avginflAmnt && avginflAmnt!=0 ? roundUp((avginflAmnt / filteredData.length), 0) : 0,
|
||||
sumFlow: avgsumFlow && avgsumFlow!=0 ? roundUp((avgsumFlow / filteredData.length), 0) : 0,
|
||||
returnAmnt: avgreturnAmnt && avgreturnAmnt!=0 ? roundUp((avgreturnAmnt / filteredData.length), 0) : 0,
|
||||
efflAmnt: avgefflAmnt && avgefflAmnt!=0 ? roundUp((avgefflAmnt / filteredData.length), 0) : 0,
|
||||
noProcessInflAmnt : roundNumber(avgNoProcessInflAmnt / noProcessInflAmntCnt, 0),
|
||||
infoRnDay: avginfoRnDay > 0 ? roundUp((avginfoRnDay / filteredData.length), 1) : '0.0',
|
||||
rainEffectDay: 0,
|
||||
},
|
||||
@@ -123,6 +145,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
|
||||
sumFlow: roundUp(maxsumFlow, 0),
|
||||
returnAmnt: roundUp(maxreturnAmnt, 0),
|
||||
efflAmnt: roundUp(maxefflAmnt, 0),
|
||||
noProcessInflAmnt : roundNumber(maxNoProcessInflAmnt, 0),
|
||||
infoRnDay: maxinfoRnDay > 0 ? roundUp(maxinfoRnDay, 1) : '0.0',
|
||||
rainEffectDay: 0,
|
||||
},
|
||||
@@ -133,6 +156,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
|
||||
sumFlow: roundUp(minsumFlow, 0),
|
||||
returnAmnt: roundUp(minreturnAmnt, 0),
|
||||
efflAmnt: roundUp(minefflAmnt, 0),
|
||||
noProcessInflAmnt : roundNumber(minNoProcessInflAmnt, 0),
|
||||
infoRnDay: mininfoRnDay > 0 ? roundUp(mininfoRnDay, 1) : '0.0',
|
||||
rainEffectDay: 0,
|
||||
},
|
||||
@@ -163,11 +187,11 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
|
||||
copyYearList.forEach((item) => {
|
||||
excelDownList.push({
|
||||
"날짜": item.msrDt,
|
||||
"총유입량(m³/일)": item.totInflAmnt,
|
||||
"하수유입량(m³/일)": item.inflAmnt,
|
||||
"연계처리량(m³/일)": item.sumFlow,
|
||||
"총인반류수량(m³/일)": item.returnAmnt,
|
||||
"방류량(m³/일)": item.efflAmnt,
|
||||
"총유입량(m³/일)": CommaToNumber(item.totInflAmnt),
|
||||
"하수유입량(m³/일)": CommaToNumber(item.inflAmnt),
|
||||
"연계처리량(m³/일)": CommaToNumber(item.sumFlow),
|
||||
"총인반류수량(m³/일)": CommaToNumber(item.returnAmnt),
|
||||
"방류량(m³/일)": CommaToNumber(item.efflAmnt),
|
||||
/* "강우량(mm/일)": item.infoRnDay, */
|
||||
});
|
||||
});
|
||||
@@ -281,9 +305,6 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-14">
|
||||
<span className="text-2xl font-bold text-gray-500">☞ 청천시 : 강우량이 3mm미만의 날</span>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="tab_term_rain">
|
||||
<FacilityTermModalHeader<FlowRateModalInterface>
|
||||
@@ -298,9 +319,7 @@ 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]}/>
|
||||
</div>
|
||||
<div className="mt-14">
|
||||
<span className="text-2xl font-bold text-gray-500">☞ 강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날</span>
|
||||
</div>
|
||||
<UnderComment commentArray={["강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날"]} />
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</>
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
"use client"
|
||||
/**
|
||||
* 처리시설 연간 운영현황 - 유량현황
|
||||
*
|
||||
* - 시설별 유량 현황을 조회조건대로 추출하여 표로 보여주는 화면.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import type { ExcelType } from "@/app/store/flowRate";
|
||||
import { ContentsDiv, downloadExcelFormat, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import FlowRateModal from "./modal/page";
|
||||
import type { ExcelType } from "@/app/store/flowRate";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
|
||||
export default function ProcessFacilitySearch() {
|
||||
const {Common
|
||||
@@ -134,7 +140,7 @@ export default function ProcessFacilitySearch() {
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({ data: JSON.parse(JSON.stringify(excelList)), fileName: '시설별 유량현황', sheetNameArray: ['시설별 유량현황'], headerRange: 'A1:O1' });
|
||||
downloadExcelFormat({ data: JSON.parse(JSON.stringify(excelList)), fileName: '시설별 유량현황', sheetNameArray: ['시설별 유량현황'], headerRange: 'A1:O1', decimalArray0: [9,10,11,12,13,14] });
|
||||
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
@@ -192,7 +198,7 @@ export default function ProcessFacilitySearch() {
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 유량현황"} tableData={flowRateList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 유량현황"} tableData={flowRateList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
"use client"
|
||||
/**
|
||||
* 처리시설 연간 운영현황 - 계획하수량 산정지표 현황
|
||||
*
|
||||
* - 시설별 여유용량, 변동부하율, 분류식화율을 조회조건대로 추출하여 표로 보여주는 화면.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
|
||||
import UnderComment from "@/app/components/common/UnderComment";
|
||||
|
||||
const commentArray = [
|
||||
"여유용량 = 하수처리시설 시설용량 – 건기시 유입유량(평균)",
|
||||
"변동부하율 = 건기시 일최대 유량/일평균유량(기준 최근 3개년)",
|
||||
"분류식화율 = 분류식지역 면적(㎢) / 처리구역 면적합계(㎢) ×100"
|
||||
]
|
||||
|
||||
export default function PlanSewage() {
|
||||
const {Common
|
||||
,PlanSewage
|
||||
@@ -104,10 +117,9 @@ export default function PlanSewage() {
|
||||
initializeCommonData();
|
||||
searchPlanSewageList(1, 10, selectSearchYear[0]?.val || "0", ref.current.partValue);
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchPlanSewageList]);
|
||||
}, [isInit, initializeCommonData, searchPlanSewageList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('excelList' , excelList);
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
@@ -136,12 +148,14 @@ export default function PlanSewage() {
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchPlanSewageList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
// G로 넘기면 데이터가 안떠서 환경청 전체로 넘기면 전체를 추출하기위해서...
|
||||
partValue = partValue==='G'?'A':partValue;
|
||||
searchPlanSewageList(pageNo, pageCnt, searchYear, partValue);
|
||||
}
|
||||
}, [operationValue, fcltyName, searchPlanSewageList, searchYear, fcltCpct]);
|
||||
@@ -192,13 +206,9 @@ export default function PlanSewage() {
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={ undefined } headName={"계획하수량 산정지표 현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
<div className="mt-14">
|
||||
<span className="text-2xl font-bold text-gray-500">☞ 여유용량 = 하수처리시설 시설용량 – 건기시 유입유량(평균)</span><br/>
|
||||
<span className="text-2xl font-bold text-gray-500">☞ 변동부하율 = 건기시 일최대 유량/일평균유량(기준 최근 3개년)</span><br/>
|
||||
<span className="text-2xl font-bold text-gray-500">☞ 분류식화율 = 분류식지역 면적(㎢) / 처리구역 면적합계(㎢) ×100</span><br/>
|
||||
<UiTable cellClick={ undefined } headName={"계획하수량 산정지표 현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
|
||||
</div>
|
||||
<UnderComment divHeight={"5"} commentArray={commentArray} />
|
||||
</div>
|
||||
</ListDiv>
|
||||
</MainDiv>
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
"use client"
|
||||
/**
|
||||
* 처리시설 현황 - 처리구역정보(모달)
|
||||
*
|
||||
* - 선택한 시설의 계획정보를 가져와 표로 출력해주는 모달
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
"use client"
|
||||
/**
|
||||
* 처리시설 현황 - 처리구역정보(메인)
|
||||
*
|
||||
* - 시설계획 정보를 조회조건대로 추출하여 표로 보여주는 화면.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
@@ -157,7 +163,7 @@ export default function ProcessArea() {
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className="w-[180%]">
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"처리구역정보"} tableData={mainList} headlist={upHeadList1} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"처리구역정보"} tableData={mainList} headlist={upHeadList1} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
"use client"
|
||||
/**
|
||||
* 처리시설 현황 - 처리시설 시설정보(모달))
|
||||
*
|
||||
* - 선택한 시설의 정보와 시설이력정보를 보여주는 모달.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/dashboard";
|
||||
import { UITab, UiTable } from "@common/business_components/ui";
|
||||
import { downloadExcelFormat, filePickedBlobArray, UITab, UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import {
|
||||
TabsContent
|
||||
} from "@common/components";
|
||||
import { Table, TableCell, TableHead, TableRow } from "@common/components/ui";
|
||||
import { Button, Table, TableCell, TableHead, TableRow } from "@common/components/ui";
|
||||
|
||||
type ModalType = {
|
||||
fcltyName: string;
|
||||
@@ -82,8 +88,8 @@ const headMakeList = (upHeadList: TableUpperProps[], gridNum:number) => {
|
||||
|
||||
export default function ProcessFacilityInfoModal(props: ModalType) {
|
||||
// 그리드 관련
|
||||
const {ProcessFacilityDetail} = useFoStore((state) => state);
|
||||
|
||||
const {Common, ProcessFacilityDetail} = useFoStore((state) => state);
|
||||
const { btnClass } = Common;
|
||||
const {
|
||||
upHeadListPlanInfo,
|
||||
gridListPlanInfo,
|
||||
@@ -111,10 +117,82 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
|
||||
{ value: 'common_info', label: '기본정보' },
|
||||
{ value: 'history_info', label: '이력정보' },
|
||||
];
|
||||
const fctCpc = props.fctCpc ? props.fctCpc.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : '';
|
||||
const fctCpc = props.fctCpc ? Number(props.fctCpc).toLocaleString() : '';
|
||||
const upHeadListPlanInfoChange = headMakeList(upHeadListPlanInfo, 2);
|
||||
const upHeadListFcltyHistInfoChange = headMakeList(upHeadListFcltyHistInfo, 3);
|
||||
const upHeadListFcltyWaterQltyInfoChange = headMakeList(upHeadListFcltyWaterQltyInfo, 4);
|
||||
|
||||
const excelDownloadPlan = () => {
|
||||
const excelDownList: any[] = [];
|
||||
|
||||
if(gridListFcltyHistInfo.length > 0){
|
||||
gridListFcltyHistInfo.forEach((item) => {
|
||||
excelDownList.push({
|
||||
"차수": item.extnsSeqno,
|
||||
"구분": item.extnsNm,
|
||||
"사업시작일": item.bzStrtYrMnth,
|
||||
"사업종료일": item.bzEdYrMnth,
|
||||
"설치인가일": item.eqpPrmsDt,
|
||||
"준공일": item.cmplDt,
|
||||
"시운전완료일": item.trlrnCmplDt,
|
||||
"가동개시일": item.rnDt,
|
||||
"시설용량(m³/일)": item.fctCpc&&item.fctCpc.toString().trim()!=''?Number(item.fctCpc.toString().replaceAll(',','')):'',
|
||||
});
|
||||
});
|
||||
}
|
||||
if (excelDownList && excelDownList.length > 0) {
|
||||
downloadExcelFormat({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.fcltyName + ' 시설이력관리', sheetNameArray: [props.fcltyName + ' 시설이력관리'], headerRange: 'A1:I1' });
|
||||
} else if (gridListFcltyHistInfo.length == 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
const excelDownloadQlty = () => {
|
||||
fetch(`/dashBoadModalWaterQlty.xlsx`, {}).then(async (response) => {
|
||||
if (!response.ok) {
|
||||
throw Error(response.statusText);
|
||||
}
|
||||
|
||||
// 받은 파일 바인너리 처리
|
||||
const blobRet = await response.arrayBuffer();
|
||||
const excelData = gridListFcltyWaterQltyInfo.map((item) => {
|
||||
return [
|
||||
item.extnsSeqno,
|
||||
item.plInflWqltBod,
|
||||
item.plInflWqltToc,
|
||||
item.plInflWqltCod,
|
||||
item.plInflWqltSs,
|
||||
item.plInflWqltTn,
|
||||
item.plInflWqltTp,
|
||||
item.dsInflWqltBod,
|
||||
item.dsInflWqltToc,
|
||||
item.dsInflWqltCod,
|
||||
item.dsInflWqltSs,
|
||||
item.dsInflWqltTn,
|
||||
item.dsInflWqltTp,
|
||||
item.plEfflWqltBod,
|
||||
item.plEfflWqltToc,
|
||||
item.plEfflWqltCod,
|
||||
item.plEfflWqltSs,
|
||||
item.plEfflWqltTn,
|
||||
item.plEfflWqltTp,
|
||||
];
|
||||
});
|
||||
|
||||
const sheetParameter = [
|
||||
{
|
||||
data: excelData,
|
||||
headerNum: 2,
|
||||
headerRange: 'A1:S2',
|
||||
sheetName: '시설 수질정보',
|
||||
startCol: 'A'
|
||||
},
|
||||
];
|
||||
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
|
||||
await filePickedBlobArray(blobRet, props.fcltyName +' 수질정보', sheetParameter);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListDiv className="!h-[80px]">
|
||||
@@ -132,7 +210,7 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
|
||||
</div>
|
||||
</ListDiv>
|
||||
<div className="overflow-y-auto">
|
||||
<div className="!h-[600px]">
|
||||
<div className="h-[550px]">
|
||||
<ListDiv className="">
|
||||
<UITab tabList={tabList} defaultValue="common_info">
|
||||
<TabsContent value="common_info">
|
||||
@@ -144,9 +222,9 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
|
||||
<thead>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'시설명'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.fcltyName}</TableCell>
|
||||
<TableHead className="w-1/6">{'시설구분'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.bscFctClsNm}</TableCell>
|
||||
<TableCell className="w-1/6" colSpan={3}>{props.fcltyName}</TableCell>
|
||||
{/* <TableHead className="w-1/6">{'시설구분'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.bscFctClsNm}</TableCell> */}
|
||||
<TableHead className="w-1/6">{'시설용량(m³/일)'}</TableHead>
|
||||
<TableCell className="w-1/6">{fctCpc}</TableCell>
|
||||
</TableRow>
|
||||
@@ -184,8 +262,11 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
|
||||
|
||||
<TabsContent value="history_info">
|
||||
<ListDiv>
|
||||
<div className="h-[270px] w-full overflow-y-auto overflow-x-hidden">
|
||||
<div className="h-[130%]">
|
||||
<div className="h-[250px] w-full overflow-y-auto overflow-x-hidden">
|
||||
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownloadPlan}>
|
||||
{"엑셀다운로드"}
|
||||
</Button>
|
||||
<div className="h-[120%]">
|
||||
<UiTable headName={"시설 이력관리"} tableData={gridListFcltyHistInfo} headlist={upHeadListFcltyHistInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
{upHeadListFcltyHistInfoChange}
|
||||
</UiTable>
|
||||
@@ -193,8 +274,11 @@ export default function ProcessFacilityInfoModal(props: ModalType) {
|
||||
</div>
|
||||
</ListDiv>
|
||||
<ListDiv>
|
||||
<div className="h-[270px] w-full overflow-y-auto overflow-x-hidden">
|
||||
<div className="h-[130%]">
|
||||
<div className="h-[250px] w-full overflow-y-auto overflow-x-hidden">
|
||||
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownloadQlty}>
|
||||
{"엑셀다운로드"}
|
||||
</Button>
|
||||
<div className="h-[120%]">
|
||||
<UiTable headName={"시설 수질정보"} tableData={gridListFcltyWaterQltyInfo} headlist={upHeadListFcltyWaterQltyInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
{upHeadListFcltyWaterQltyInfoChange}
|
||||
</UiTable>
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
"use client"
|
||||
import { HeadMakeColSpan } from "@/app/components/common/HeadMakeColSpan";
|
||||
/**
|
||||
* 처리시설 현황 - 처리시설 시설정보(메인)
|
||||
*
|
||||
* - 시설별 정보를 조회조건대로 추출하여 표로 보여주는 화면.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import UnderComment from "@/app/components/common/UnderComment";
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import ProcessFacilityInfoModal from "./modal/page";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
|
||||
export default function ProcessFacilitySearch() {
|
||||
const {Common
|
||||
@@ -204,12 +210,13 @@ export default function ProcessFacilitySearch() {
|
||||
const cellClick = (index: number) => {
|
||||
const facility = processFacilityList[index];
|
||||
if (facility) {
|
||||
const fctCpc = String(facility.fctCpc).replace(/,/g, "").trim();
|
||||
setModalFcltyNm(facility.bscFctNm);
|
||||
setModalFcltyCd(facility.bscFctCd);
|
||||
setModalSido(facility.sido);
|
||||
setModalGugun(facility.gugun);
|
||||
setModalAddr(facility.daddr);
|
||||
setModalFctCpc(Number(facility.fctCpc));
|
||||
setModalFctCpc(Number(fctCpc));
|
||||
setModalTrtFrfNm(facility.trtFrfNm);
|
||||
setModalRnDt(facility.rnDt);
|
||||
setModalCmplDt(facility.cmplDt);
|
||||
@@ -274,13 +281,13 @@ export default function ProcessFacilitySearch() {
|
||||
total={total}
|
||||
resetPageNo={resetPage}
|
||||
onPageChange={changePage}
|
||||
widthFixed={true}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadList} layoutNum={partValue}/>
|
||||
</UiTable>
|
||||
</div>
|
||||
<UnderComment divHeight={"0"} commentArray={["계획유입수질 및 설계유입수질은 해당 BOD를 나타냄"]} />
|
||||
</div>
|
||||
</ListDiv>
|
||||
<span className="text-2xl text-gray-500">※계획유입수질 및 설계유입수질은 해당 BOD를 나타냄</span>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
"use client"
|
||||
/**
|
||||
* 운영실태 - RDII 추정
|
||||
*
|
||||
* - 시설별 유입량과 하절기 최저 유입 BOD 정보를 통해 RDII를 추정치를 보여주는 화면
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
import UnderComment from "@/app/components/common/UnderComment";
|
||||
|
||||
const commentArray = [
|
||||
"강우시 총 추정유입량 = 청천시 유입하수량 + RDII 추정값",
|
||||
"주) 처리장 유입부에서 측정된 유량 및 수질조사 자료를 기준으로 산정된 결과임"
|
||||
]
|
||||
|
||||
export default function Rdi() {
|
||||
const {Common
|
||||
@@ -60,7 +72,7 @@ export default function Rdi() {
|
||||
// 초기화 변수
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
// 표 너비
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[130%]");
|
||||
// 구분별 그리드 헤더
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
// 용량별
|
||||
@@ -107,7 +119,7 @@ export default function Rdi() {
|
||||
initializeCommonData();
|
||||
searchRdiList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchRdiList]);
|
||||
}, [isInit, initializeCommonData, searchRdiList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
@@ -149,7 +161,7 @@ export default function Rdi() {
|
||||
}, [operationValue, fcltyName, searchRdiList, searchYear, fcltCpct]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[130%]":"w-[150%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
@@ -195,9 +207,9 @@ export default function Rdi() {
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={ undefined } headName={"RDII추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
<UiTable cellClick={ undefined } headName={"RDII추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
|
||||
</div>
|
||||
<span className="text-2xl text-gray-500">※주) 처리장 유입부에서 측정된 유량 및 수질조사 자료를 기준으로 산정된 결과임</span>
|
||||
<UnderComment divHeight={"0"} commentArray={commentArray} />
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
"use client"
|
||||
/**
|
||||
* 운영실태 - 오수발생량 추정(모달)
|
||||
*
|
||||
* - 선택한 시설의 물사용량과 오수전환율을 가지고 오수발생량 추정 데이터를 월별로 보여주는 모달.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { roundNumber } from "@/app/components/common/DataForm";
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { modalTableType } from "@/app/store/sewageOccur";
|
||||
import { DateMonthPicker, UiTable } from "@common/business_components/ui";
|
||||
import { DateMonthPicker, downloadExcel, UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Table, TableCell, TableHead, TableRow } from "@common/components/ui";
|
||||
import { Button, Table, TableCell, TableHead, TableRow } from "@common/components/ui";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function SewageOccurModal(props: { fcltyName: string; facilityCd : string; searchYear : string}) {
|
||||
// 그리드 관련
|
||||
const {SewageOccurDetail, searchSewageOccurDetailList} = useFoStore((state) => state);
|
||||
|
||||
const { Common, SewageOccurDetail, searchSewageOccurDetailList} = useFoStore((state) => state);
|
||||
const { btnClass } = Common;
|
||||
|
||||
// searchYear 유효성 검사 및 기본값 설정
|
||||
const validSearchYear = props.searchYear && /^\d{4}$/.test(props.searchYear) ? props.searchYear : new Date().getFullYear().toString();
|
||||
|
||||
@@ -61,6 +69,25 @@ export default function SewageOccurModal(props: { fcltyName: string; facilityCd
|
||||
}
|
||||
}, [endYearMonth, startYearMonth]);
|
||||
|
||||
const excelDownload = () => {
|
||||
const excelDownList: any[] = [];
|
||||
if(detailList.length > 0){
|
||||
detailList.forEach((item) => {
|
||||
excelDownList.push({
|
||||
"날짜": item.msrDt,
|
||||
"물사용량(m³/일)": roundNumber(item.waterUsage, 0),
|
||||
"오수전환율(%)": roundNumber(item.swageChangePercent, 0),
|
||||
"오수발생량 추정(m³/일)": roundNumber(item.estimationSewage, 0),
|
||||
});
|
||||
});
|
||||
}
|
||||
if (excelDownList && excelDownList.length > 0) {
|
||||
downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.searchYear+'년 '+props.fcltyName + ' 오수발생량 추정', sheetNameArray: [props.fcltyName + ' 오수발생량 추정'], headerRange: 'A1:D1' });
|
||||
} else if (detailList.length == 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListDiv className="!h-[80px] !mt-10">
|
||||
@@ -118,7 +145,10 @@ export default function SewageOccurModal(props: { fcltyName: string; facilityCd
|
||||
</ListDiv>
|
||||
<ListDiv className="!h-[570px] overflow-y-auto">
|
||||
<div className="h-[120%]">
|
||||
<UiTable headName={"오수발생량 추정"} tableData={detailList} headlist={upHeadListSewageOccurDetail} pageSize={0} total={0} cellClick={undefined} onPageChange={() => {}} boldArray={[0, 1, 2]}>
|
||||
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownload}>
|
||||
{"엑셀다운로드"}
|
||||
</Button>
|
||||
<UiTable headName={"오수발생량 추정"} tableData={detailList} headlist={upHeadListSewageOccurDetail} pageSize={0} total={0} cellClick={undefined} onPageChange={() => {}} boldArray={[0, 1, 2]} widthFixed={true} >
|
||||
</UiTable>
|
||||
</div>
|
||||
</ListDiv>
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
"use client"
|
||||
/**
|
||||
* 운영실태 - 오수발생량 추정(메인)
|
||||
*
|
||||
* - 조회조건대로 시설별 물 사용량과 오수전환율을 기반으로 오수발생량 추정치를 표로 보여주는 화면
|
||||
* - 현재 물사용량의 경우 연계받는 데이터가 아닌 연 하수유입량의 65%로 가정하고 계산함
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
@@ -222,7 +229,7 @@ export default function PlanSewage() {
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"오수발생량 추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"오수발생량 추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
"use client"
|
||||
/**
|
||||
* 운영실태 - 지하수 유입량 추정(모달)
|
||||
*
|
||||
* - 선택한 시설의 월별 청천시 실제 하수유입량, 오수발생량으로 지하수 유입량을 보여주는 모달
|
||||
* - 청천시 실제 하수유입량 - 오수발생량으로 지하수유입량을 추정한다.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { roundNumber } from "@/app/components/common/DataForm";
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { UnderWaterInputModalProps } from "@/app/store/underWaterInput/types";
|
||||
import { downloadExcel } from "@common/business_components";
|
||||
import { DateMonthPicker, UITab, UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Table, TableCell, TableHead, TableRow, TabsContent } from "@common/components/ui";
|
||||
import { Button, Table, TableCell, TableHead, TableRow, TabsContent } from "@common/components/ui";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
type ModalProps ={
|
||||
@@ -20,8 +29,8 @@ const tabList1 = [
|
||||
|
||||
export default function UnderWaterInputModal({fcltyCd='', fcltyName='',searchYear=new Date().getFullYear().toString()} : ModalProps) {
|
||||
// 그리드 관련
|
||||
const {UnderWaterDetail, unserWaterModal} = useFoStore((state) => state);
|
||||
|
||||
const {Common, UnderWaterDetail, unserWaterModal} = useFoStore((state) => state);
|
||||
const { btnClass } = Common;
|
||||
const [startYmDate, setStartYmDate] = useState<string>(searchYear+'01');
|
||||
const [endYmDate, setEndYmDate] = useState<string>(searchYear+'12');
|
||||
const [tabTerm, setTabTerm] = useState<string>('tab_term_year');
|
||||
@@ -87,9 +96,31 @@ export default function UnderWaterInputModal({fcltyCd='', fcltyName='',searchYea
|
||||
unserWaterModal(fcltyCd, searchYear, prevStartYmDate, prevEndYmDate);
|
||||
} , [fcltyCd, searchYear, unserWaterModal, prevStartYmDate, prevEndYmDate]);
|
||||
|
||||
const excelDownload = () => {
|
||||
const excelDownList: any[] = [];
|
||||
if(copyYearList.length > 0){
|
||||
copyYearList.forEach((item) => {
|
||||
excelDownList.push({
|
||||
"날짜": item.msrDt,
|
||||
"청천시 실제 하수유입량(m³/일)": roundNumber(item.realSewageInput, 0),
|
||||
"오수발생량(m³/일)": roundNumber(item.sewageOccur, 0),
|
||||
"지하수 유입량(m³/일)": roundNumber(item.underWaterInput, 0),
|
||||
});
|
||||
});
|
||||
}
|
||||
if (excelDownList && excelDownList.length > 0) {
|
||||
downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: searchYear+'년 '+fcltyName + ' 지하수유입량', sheetNameArray: [fcltyName + ' 지하수유입량'], headerRange: 'A1:D1' });
|
||||
} else if (copyYearList.length == 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<UITab tabList={tabList1} defaultValue="tab_term_year" onValueChange={(val) => {setTabTerm(val)}}>
|
||||
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownload}>
|
||||
{"엑셀다운로드"}
|
||||
</Button>
|
||||
<TabsContent value="tab_term_year">
|
||||
<ListDiv className="!h-[100px]">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
@@ -142,6 +173,7 @@ export default function UnderWaterInputModal({fcltyCd='', fcltyName='',searchYea
|
||||
onPageChange={() => {}}
|
||||
className="h-[200px]"
|
||||
boldArray={[0,1,2]}
|
||||
widthFixed={true}
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
@@ -209,6 +241,7 @@ export default function UnderWaterInputModal({fcltyCd='', fcltyName='',searchYea
|
||||
onPageChange={() => { } }
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
widthFixed={true}
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
@@ -267,6 +300,7 @@ export default function UnderWaterInputModal({fcltyCd='', fcltyName='',searchYea
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
widthFixed={true}
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
"use client"
|
||||
/**
|
||||
* 운영실태 - 지하수 유입량 추정(메인)
|
||||
*
|
||||
* - 조회조건대로 시설별 연간, 하절기, 동절기 단위로 지하수 유입량 추정을 표로 보여주는 화면
|
||||
* - 청천시 실제 하수유입량 - 오수발생량으로 지하수유입량을 추정한다.
|
||||
* - 연간 지하수 유입량이 하수유입량보다 20% 클 경우 초과유입으로 아닌 경우 적정으로 적정여부를 표시한다.
|
||||
*/
|
||||
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
@@ -220,9 +228,10 @@ export default function UnderWaterInput() {
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"지하수유입량 추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"지하수유입량 추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} widthFixed={true}/>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-2xl text-gray-500">※적정여부 = 연간 지하수유입량/연평균 유입하수량*100 </span><br></br>
|
||||
<span className="text-2xl text-gray-500">※지하수 유입량 = 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)</span>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
|
||||
@@ -201,6 +201,9 @@ const selectMiddleRegionData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
// 오수전환율
|
||||
export const OSU_PERCENT = 0.9;
|
||||
|
||||
/**
|
||||
* 반올림 함수
|
||||
* @param value : 대상 숫자
|
||||
@@ -211,6 +214,19 @@ export const roundUp = (value: number, precision: number = 1): number => {
|
||||
return Math.round(value * (10 ** precision)) / (10 ** precision);
|
||||
}
|
||||
|
||||
/**
|
||||
* 수질 데이터 포맷 변경 함수
|
||||
* @param value : 수질 데이터
|
||||
* @param day : 일수
|
||||
* @param digit : 소수점 자리수
|
||||
*/
|
||||
export const qltyDataSetting = (value: number, day : number, digit: number) => {
|
||||
const toZero = digit === 1 ? '0.0' : digit === 2 ? '0.00' : '0.000';
|
||||
return value > 0 ? roundUp((value/day), digit).toFixed(digit) : toZero;
|
||||
};
|
||||
|
||||
export const COD_YEAR = 2021;
|
||||
|
||||
/**
|
||||
* STORE - API
|
||||
*/
|
||||
@@ -378,6 +394,7 @@ export type CommonType = {
|
||||
selectFlowPanel: SelectDataType[];
|
||||
selectEnvPartData: envPartSelectDataType[];
|
||||
btnClass: string;
|
||||
COD_YEAR : number;
|
||||
};
|
||||
|
||||
auth: {
|
||||
@@ -406,7 +423,8 @@ export const commonState: CommonType = {
|
||||
selectFlowTerm: selectFlowTerm,
|
||||
selectFlowPanel: selectFlowPanel,
|
||||
selectEnvPartData: selectEnvPartData,
|
||||
btnClass: "p-4 m-2 text-white rounded-sm text-lg font-medium",
|
||||
btnClass: "p-4 m-2 !mr-10 text-white rounded-sm text-lg font-medium",
|
||||
COD_YEAR : COD_YEAR,
|
||||
},
|
||||
|
||||
auth: {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
|
||||
import { roundNumber } from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
@@ -49,11 +50,11 @@ export interface ExcelType {
|
||||
시군구: string,
|
||||
시설이름: string,
|
||||
주소: string,
|
||||
시설용량: number,
|
||||
"시설옹량(m³/일)": number,
|
||||
관측소정보 : string,
|
||||
강우일 : number,
|
||||
강우영향일 : number,
|
||||
연간총강수량 : number,
|
||||
"강우일(일)": number,
|
||||
"강우영향일(일)": number,
|
||||
"연간총강수량(mm)": number,
|
||||
}
|
||||
|
||||
/**====================================
|
||||
@@ -68,48 +69,48 @@ const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "A", title: "행정구역", row: 0, colSpan: 2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row: 1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2, row: 1 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "A", title: "행정구역", row: 0, colSpan: 2, widthPercent: 20 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, 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: "addr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2, align:"right"},
|
||||
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2},
|
||||
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2, align:"right"},
|
||||
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2, align:"right"},
|
||||
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2, align:"right"}
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2, align:"right", widthPercent: 10 },
|
||||
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2, widthPercent: 10 },
|
||||
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2, align:"right", widthPercent: 7 },
|
||||
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2, align:"right", widthPercent: 7 },
|
||||
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2, align:"right", widthPercent: 7 }
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3} ,
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row: 1} ,
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row: 1},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row: 1},
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3, widthPercent: 21 } ,
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row: 1, widthPercent: 7 } ,
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row: 1, widthPercent: 7 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row: 1, widthPercent: 7 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 10 },
|
||||
{ id: "addr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2, align:"right"},
|
||||
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2},
|
||||
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2, align:"right"},
|
||||
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2, align:"right"},
|
||||
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2, align:"right"}
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2, align:"right", widthPercent: 10 },
|
||||
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2, widthPercent: 10 },
|
||||
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2, align:"right", widthPercent: 7 },
|
||||
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2, align:"right", widthPercent: 7 },
|
||||
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2, align:"right", widthPercent: 7 }
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3} ,
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row: 1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row: 1},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row: 1},
|
||||
{ id: "rgnNm", title: "환경청", row: 0, rowSpan: 2},
|
||||
{ id: "B", title: "행정구역", upName:"upChangeRe2", row: 0, colSpan: 2},
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, row: 1},
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe2",upSequnce:2, row: 1},
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3, widthPercent: 15 } ,
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row: 1, widthPercent: 5 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row: 1, widthPercent: 5 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row: 1, widthPercent: 5 },
|
||||
{ id: "rgnNm", title: "환경청", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "B", title: "행정구역", upName:"upChangeRe2", row: 0, colSpan: 2, widthPercent: 10 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, 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: "addr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2, align:"right"},
|
||||
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2},
|
||||
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2, align:"right"},
|
||||
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2, align:"right"},
|
||||
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2, align:"right"}
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2, align:"right", widthPercent: 10 },
|
||||
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2, widthPercent: 10 },
|
||||
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2, align:"right", widthPercent: 7 },
|
||||
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2, align:"right", widthPercent: 7 },
|
||||
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2, align:"right", widthPercent: 7 }
|
||||
];
|
||||
|
||||
const facilityPrecipitation:FacilityPrecipitationProps[] = [
|
||||
@@ -135,7 +136,6 @@ const gridListPrecipitationDetail:PrecipitationPropsDetailProps[] = [
|
||||
|
||||
const fetchFacilityPrecipitationList = async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const tailStr = '/'+pageNo + '/' + pageSize + '/' + searchYear + (part?'/' + part:'' ) + (nameCd?'/' + nameCd:'' ) + (fcltCpct?'/' + fcltCpct:'' ) + (operationValue?'/' + operationValue:'' ) + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') ;
|
||||
console.log('tailStr', tailStr);
|
||||
const url = '/fclt/rain' + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
const tmpData:PrecipitationPropsDetailProps[] = [];
|
||||
@@ -146,45 +146,30 @@ const fetchFacilityPrecipitationList = async (pageNo: number, pageSize: number,
|
||||
const rainDt = res.data[idx].rainyDayObjList[idx2].rainDt;
|
||||
const infoRnDay = res.data[idx].rainyDayObjList[idx2].infoRnDay;
|
||||
const rainDay = res.data[idx].rainyDayObjList[idx2].infoRnDay>=3?1:0;
|
||||
let rainEffectDay = 0;
|
||||
if(idx2 < res.data[idx].rainyDayObjList.length-2){
|
||||
if(rainDay==1){
|
||||
rainEffectDay = 1;
|
||||
} else {
|
||||
if(idx2 >= 2){
|
||||
if(res.data[idx].rainyDayObjList[idx2-1].infoRnDay>=3 || res.data[idx].rainyDayObjList[idx2-2].infoRnDay>=3){
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(idx2 < res.data[idx].rainyDayObjList.length-1){
|
||||
if(rainDay==1 || res.data[idx].rainyDayObjList[idx2+1].infoRnDay>=3){
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
} else {
|
||||
rainEffectDay = rainDay;
|
||||
}
|
||||
|
||||
tmpData.push({
|
||||
bscFctCd : bscFctCd,
|
||||
rainDt : rainDt,
|
||||
infoRnDay : infoRnDay,
|
||||
rainDay : rainDay,
|
||||
rainEffectDay : rainEffectDay
|
||||
rainEffectDay : rainDay
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
res.data.map((item: FacilityPrecipitationProps) => {
|
||||
const filteredList = tmpData.filter((gridItem) => {
|
||||
return gridItem.bscFctCd === item.bscFctCd;
|
||||
return gridItem.bscFctCd === item.bscFctCd;
|
||||
});
|
||||
|
||||
item.rainEffectDay = filteredList.reduce((acc, curr) => acc + curr.rainEffectDay, 0);
|
||||
item.totalYearRain = filteredList.reduce((acc, curr) => acc + curr.infoRnDay, 0);
|
||||
const rtnData = CalcRainEffect(filteredList);
|
||||
item.rainEffectDay = rtnData.reduce((acc, curr) => acc + curr.rainEffectDay, 0);
|
||||
item.totalYearRain = rtnData.reduce((acc, curr) => acc + Number(curr.infoRnDay), 0);
|
||||
item.infoRnDay = filteredList.reduce((acc, curr) => acc + curr.rainDay, 0);
|
||||
})
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return { data: res.data, count: res.count, detailData: tmpData };
|
||||
}
|
||||
|
||||
@@ -195,11 +180,6 @@ export type FacilityPrecipitationActions = {
|
||||
searchFacilityPrecipitationList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
|
||||
}
|
||||
|
||||
const dataFormSetting=(item : FacilityPrecipitationProps)=> {
|
||||
DataForm({ type: 'number', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'totalYearRain', item: item as unknown as Record<string, unknown>});
|
||||
};
|
||||
|
||||
export type FacilityPrecipitationType = {
|
||||
FacilityPrecipitationSearch: {
|
||||
isInit: boolean;
|
||||
@@ -263,13 +243,16 @@ export const facilityPrecipitationReducer:(set:(fn: (state: FacilityPrecipitatio
|
||||
|
||||
const res = await fetchFacilityPrecipitationList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const data = res.data;
|
||||
|
||||
data.forEach(item => {
|
||||
item.fctCpc = roundNumber(item.fctCpc, 0);
|
||||
item.totalYearRain = roundNumber(item.totalYearRain, 1);
|
||||
});
|
||||
|
||||
const excelDownList: ExcelType[] = [];
|
||||
|
||||
if(pageSize>5000){
|
||||
data.forEach((item: FacilityPrecipitationProps) => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : 0;
|
||||
item.totalYearRain = item.totalYearRain ? parseFloat(item.totalYearRain.toString().replace(/,/g, '')) : 0;
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
@@ -280,25 +263,19 @@ export const facilityPrecipitationReducer:(set:(fn: (state: FacilityPrecipitatio
|
||||
시군구: item.gugun,
|
||||
시설이름: item.bscFctNm,
|
||||
주소: item.addr,
|
||||
시설용량: item.fctCpc,
|
||||
"시설옹량(m³/일)": item.fctCpc,
|
||||
관측소정보: item.stnKo,
|
||||
강우일: item.infoRnDay,
|
||||
강우영향일: item.rainEffectDay,
|
||||
연간총강수량: item.totalYearRain,
|
||||
"강우일(일)": item.infoRnDay,
|
||||
"강우영향일(일)": item.rainEffectDay,
|
||||
"연간총강수량(mm)": item.totalYearRain,
|
||||
})
|
||||
})
|
||||
}else{
|
||||
data.forEach((item: FacilityPrecipitationProps) => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : 0;
|
||||
item.totalYearRain = item.totalYearRain ? parseFloat(item.totalYearRain.toString().replace(/,/g, '')) : 0;
|
||||
})
|
||||
}
|
||||
set((state:FacilityPrecipitationType) => ({
|
||||
...state,
|
||||
FacilityPrecipitation: pageSize<5000?{
|
||||
...state.FacilityPrecipitation,
|
||||
facilityPrecipitation: res.data,
|
||||
facilityPrecipitation: data,
|
||||
facilityPrecipitationCount: res.count,
|
||||
isLoading : false,
|
||||
}:{
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import DataForm, { roundNumber } from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
|
||||
import { COD_YEAR } from "../common";
|
||||
import CommaToNumber from "@/app/components/common/CommaToNumber";
|
||||
export type { TableUpperProps };
|
||||
|
||||
/**====================================
|
||||
@@ -25,6 +28,8 @@ export interface FacilityWaterQltyProps {
|
||||
inflAssctAftWqltBod: string | '',
|
||||
inflAssctBfrWqltToc: string | '',
|
||||
inflAssctAftWqltToc: string | '',
|
||||
inflAssctBfrWqltCod : string | '',
|
||||
inflAssctAftWqltCod : string | '',
|
||||
inflAssctBfrWqltSs: string | '',
|
||||
inflAssctAftWqltSs: string | '',
|
||||
inflAssctBfrWqltTn: string | '',
|
||||
@@ -33,6 +38,7 @@ export interface FacilityWaterQltyProps {
|
||||
inflAssctAftWqltTp: string | '',
|
||||
efflWqltBod: string | '',
|
||||
efflWqltToc: string | '',
|
||||
efflWqltCod : string | '',
|
||||
efflWqltSs: string | '',
|
||||
efflWqltTn: string | '',
|
||||
efflWqltTp: string | '',
|
||||
@@ -42,7 +48,7 @@ export interface FacilityWaterQltyProps {
|
||||
mdmbsn:string|'',
|
||||
inflAmnt: number | '',
|
||||
lclgvrnmntNm: string,
|
||||
infoRnDay: number | '',
|
||||
infoRnDay: number | string | '',
|
||||
rainEffectDay: number | '',
|
||||
tpInflWqltTmprtr: number | '',
|
||||
tpInflWqltPh: string | '',
|
||||
@@ -53,6 +59,7 @@ export interface FacilityWaterQltyProps {
|
||||
tpInflWqltTp: string | '',
|
||||
tpInflWqltEclgyTox: string | '',
|
||||
tpInflWqltClfgrpcnt: string | '',
|
||||
noProcessInflAmnt : string | number | '',
|
||||
}
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
@@ -64,17 +71,17 @@ export interface ExcelType {
|
||||
시군구: string,
|
||||
시설이름: string,
|
||||
주소: string,
|
||||
용량: number,
|
||||
유입BOD: string | '',
|
||||
유입TOC: string | '',
|
||||
유입SS: string | '',
|
||||
유입TN: string | '',
|
||||
유입TP: string | '',
|
||||
유출BOD: string | '',
|
||||
유출TOC: string | '',
|
||||
유출SS: string | '',
|
||||
유출TN: string | '',
|
||||
유출TP: string | '',
|
||||
"시설용량(m³/일)": number | '',
|
||||
"유입BOD(mg/L)": number | '',
|
||||
"유입TOC(mg/L)": number | '',
|
||||
"유입SS(mg/L)": number | '',
|
||||
"유입TN(mg/L)": number | '',
|
||||
"유입TP(mg/L)": number | '',
|
||||
"유출BOD(mg/L)": number | '',
|
||||
"유출TOC(mg/L)": number | '',
|
||||
"유출SS(mg/L)": number | '',
|
||||
"유출TN(mg/L)": number | '',
|
||||
"유출TP(mg/L)": number | '',
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,17 +105,17 @@ export interface WaterQualityHistoryResponse {
|
||||
|
||||
export type modalExcelType = {
|
||||
날짜: string;
|
||||
"유입BOD(mg/L)": string;
|
||||
"유입TOC(COD)(mg/L)": string;
|
||||
"유입SS(mg/L)": string;
|
||||
"유입TN(mg/L)": string;
|
||||
"유입TP(mg/L)": string;
|
||||
"유출BOD(mg/L)": string;
|
||||
"유출TOC(COD)(mg/L)": string;
|
||||
"유출SS(mg/L)": string;
|
||||
"유출TN(mg/L)": string;
|
||||
"유출TP(mg/L)": string;
|
||||
/* "강우량(mm/일)": string; */
|
||||
"유입BOD(mg/L)": number | '';
|
||||
"유입TOC(COD)(mg/L)": number | '';
|
||||
"유입SS(mg/L)": number | '';
|
||||
"유입TN(mg/L)": number | '';
|
||||
"유입TP(mg/L)": number | '';
|
||||
"유출BOD(mg/L)": number | '';
|
||||
"유출TOC(COD)(mg/L)": number | '';
|
||||
"유출SS(mg/L)": number | '';
|
||||
"유출TN(mg/L)": number | '';
|
||||
"유출TP(mg/L)": number | '';
|
||||
"강우량(mm/일)": number | '';
|
||||
}
|
||||
|
||||
/**====================================
|
||||
@@ -122,74 +129,74 @@ const mainLabelArray: string[] = ['구분', '시도', '시군구', '용량별',
|
||||
|
||||
// 시설수질리스트 헤더(행정별)
|
||||
const upHeadList1: TableUpperProps[] = [
|
||||
{ id: "C", title: "행정명", colSpan: 2, row: 0 },
|
||||
{ id: "sidoNm", title: "시도", row: 1 },
|
||||
{ id: "sggNm", title: "시군구", row: 1 },
|
||||
{ id: "bscFctNm", title: "시설명", rowSpan: 2, row: 0 },
|
||||
{ id: "C", title: "행정명", colSpan: 2, row:0, widthPercent:10 },
|
||||
{ id: "sidoNm", title: "시도", row: 1, widthPercent:5},
|
||||
{ id: "sggNm", 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 },
|
||||
{ id: "A", title: "유입", colSpan: 5, row: 0 },
|
||||
{ id: "B", title: "방류", colSpan: 5, row: 0 },
|
||||
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row: 1 },
|
||||
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1 },
|
||||
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1 },
|
||||
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 4, align: "right", row: 1 },
|
||||
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1 },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row: 1 },
|
||||
{ id: "efflWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row: 1 },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1 },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 4, align: "right", row: 1 },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align: "right", rowSpan: 2, row: 0, widthPercent:10 },
|
||||
{ id: "A", title: "유입", colSpan: 5, row: 0, widthPercent:25 },
|
||||
{ id: "B", title: "방류", colSpan: 5, row: 0, widthPercent:25 },
|
||||
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row: 1, widthPercent:5 },
|
||||
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1, widthPercent:5 },
|
||||
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1, widthPercent:5 },
|
||||
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 4, align: "right", row: 1, widthPercent:5 },
|
||||
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1, widthPercent:5 },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row: 1, widthPercent:5 },
|
||||
{ id: "efflWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row: 1, widthPercent:5 },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1, widthPercent:5 },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 4, align: "right", row: 1, widthPercent:5 },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1, widthPercent:5 },
|
||||
];
|
||||
|
||||
// 시설수질리스트 헤더(권역별)
|
||||
const upHeadList2: TableUpperProps[] = [
|
||||
{ id: "C", title: "유역", colSpan: 3, row: 0 },
|
||||
{ id: "rvbsn", title: "권역", upName: "upChangeRe1", upSequnce: 1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName: "upChangeRe1", upSequnce: 2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName: "upChangeRe1", upSequnce: 3, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "C", title: "유역", colSpan: 3, row: 0, widthPercent:15 },
|
||||
{ id: "rvbsn", title: "권역", upName: "upChangeRe1", upSequnce: 1, row:1, widthPercent:5 },
|
||||
{ id: "lgbsn", title: "단위유역", upName: "upChangeRe1", upSequnce: 2, row:1, widthPercent:5 },
|
||||
{ id: "mdmbsn", title: "중권역", upName: "upChangeRe1", upSequnce: 3, row:1, widthPercent:5 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent:10 },
|
||||
{ id: "addr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/L)", align: "right", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유입", colSpan: 5, row: 0 },
|
||||
{ id: "B", title: "방류", colSpan: 5, row: 0 },
|
||||
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1 },
|
||||
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row:1 },
|
||||
{ id: "efflWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/L)", align: "right", row:0, rowSpan:2, widthPercent:8 },
|
||||
{ id: "A", title: "유입", colSpan: 5, row: 0, widthPercent:25 },
|
||||
{ id: "B", title: "방류", colSpan: 5, row: 0, widthPercent:25 },
|
||||
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1, widthPercent:5 },
|
||||
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1, widthPercent:5 },
|
||||
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1, widthPercent:5 },
|
||||
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1, widthPercent:5 },
|
||||
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1, widthPercent:5 },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row:1, widthPercent:5 },
|
||||
{ id: "efflWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1, widthPercent:5 },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1, widthPercent:5 },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1, widthPercent:5 },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1, widthPercent:5 },
|
||||
];
|
||||
|
||||
// 시설수질리스트 헤더(환경청별)
|
||||
const upHeadList3: TableUpperProps[] = [
|
||||
{ id: "C", title: "유역", colSpan: 3, row: 0 },
|
||||
{ id: "rvbsn", title: "권역", row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "D", title: "행정명", colSpan: 2, row: 0 },
|
||||
{ id: "sidoNm", title: "시도", upName: "upChangeRe2", row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName: "upChangeRe2", row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "C", title: "유역", colSpan: 3, row: 0, widthPercent: 15 },
|
||||
{ id: "rvbsn", title: "권역", row:1, widthPercent: 5 },
|
||||
{ id: "lgbsn", title: "단위유역", row:1, widthPercent: 5 },
|
||||
{ id: "mdmbsn", title: "중권역", row:1, widthPercent: 5 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2, widthPercent: 7 },
|
||||
{ id: "D", title: "행정명", colSpan: 2, row: 0, widthPercent: 10 },
|
||||
{ id: "sidoNm", title: "시도", upName: "upChangeRe2", row:1, widthPercent: 5 },
|
||||
{ id: "sggNm", title: "시군구", upName: "upChangeRe2", row:1, widthPercent: 5 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
|
||||
{ id: "addr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/L)", align: "right", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유입", colSpan: 5, row: 0 },
|
||||
{ id: "B", title: "방류", colSpan: 5, row: 0 },
|
||||
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1 },
|
||||
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row:1 },
|
||||
{ id: "efflWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/L)", align: "right", row:0, rowSpan:2, widthPercent: 5 },
|
||||
{ id: "A", title: "유입", colSpan: 5, row: 0, widthPercent: 20 },
|
||||
{ id: "B", title: "방류", colSpan: 5, row: 0, widthPercent: 20 },
|
||||
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1, widthPercent: 4 },
|
||||
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1, widthPercent: 4 },
|
||||
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1, widthPercent: 4 },
|
||||
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1, widthPercent: 4 },
|
||||
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1, widthPercent: 4 },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row:1, widthPercent: 4 },
|
||||
{ id: "efflWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1, widthPercent: 4 },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1, widthPercent: 4 },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1, widthPercent: 4 },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1, widthPercent: 4 },
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -208,7 +215,23 @@ const upHeadListModalYear: TableUpperProps[] = [
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe2", upSequnce: 3, align: "right" },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe2", upSequnce: 2, align: "right" },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe2", upSequnce: 3, align: "right" },
|
||||
/* { id: "infoRnDay", title: "강우량(mm/일)", align: "right" }, */
|
||||
{ id: "infoRnDay", title: "강우량\n(mm/일)", align: "right" }
|
||||
];
|
||||
|
||||
// 처리시설 수질현황 헤더(모달-연간)
|
||||
const upHeadListModalYearCod: TableUpperProps[] = [
|
||||
{ id: "msrDt", title: "날짜" },
|
||||
{ id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe1", upSequnce: 1, align: "right" },
|
||||
{ id: "inflAssctBfrWqltCod", title: "TOC(COD)\n(mg/L)", upName: "upChangeRe1", upSequnce: 2, align: "right" },
|
||||
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe1", upSequnce: 3, align: "right" },
|
||||
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe1", upSequnce: 2, align: "right" },
|
||||
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe1", upSequnce: 3, align: "right" },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe2", upSequnce: 1, align: "right" },
|
||||
{ id: "efflWqltCod", title: "TOC(COD)\n(mg/L)", upName: "upChangeRe2", upSequnce: 2, align: "right" },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe2", upSequnce: 3, align: "right" },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe2", upSequnce: 2, align: "right" },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe2", upSequnce: 3, align: "right" },
|
||||
{ id: "infoRnDay", title: "강우량\n(mm/일)", align: "right" }
|
||||
];
|
||||
|
||||
// 처리시설 수질현황 헤더(모달-수질TMS)
|
||||
@@ -295,6 +318,7 @@ export type FacilityWaterQltyType = {
|
||||
FacilityWaterQltyModal: {
|
||||
// 처리시설 수질현황
|
||||
upHeadListModalYear: TableUpperProps[];
|
||||
upHeadListModalYearCod : TableUpperProps[];
|
||||
facilityWaterQltyYearList: FacilityWaterQltyProps[];
|
||||
upHeadListModalTms: TableUpperProps[];
|
||||
facilityWaterQltyTmsList: FacilityWaterQltyTmsProps[];
|
||||
@@ -324,6 +348,7 @@ export const facilityWaterQltyInitState: FacilityWaterQltyType = {
|
||||
FacilityWaterQltyModal: {
|
||||
// 처리시설 수질현황
|
||||
upHeadListModalYear: upHeadListModalYear,
|
||||
upHeadListModalYearCod: upHeadListModalYearCod,
|
||||
facilityWaterQltyYearList: facilityWaterQltyYearList,
|
||||
upHeadListModalTms: upHeadListModalTms,
|
||||
facilityWaterQltyTmsList: facilityWaterQltyTmsList,
|
||||
@@ -375,6 +400,7 @@ export type FacilityWaterQltyActions = {
|
||||
*/
|
||||
const dataFormSetting = (item: FacilityWaterQltyProps) => {
|
||||
DataForm({ type: 'date', column: 'msrDt', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'infoRnDay', item: item as unknown as Record<string, unknown> });
|
||||
}
|
||||
|
||||
export type FacilityWaterQltyStore = FacilityWaterQltyType & FacilityWaterQltyActions;
|
||||
@@ -449,8 +475,8 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
item.inflAssctBfrWqltToc = Number(searchYear)<2021? "("+item.inflAssctBfrWqltToc+")" : item.inflAssctBfrWqltToc;
|
||||
item.efflWqltToc = Number(searchYear)<2021? "("+item.efflWqltToc+")" : item.efflWqltToc;
|
||||
item.inflAssctBfrWqltToc = Number(searchYear)<COD_YEAR? "("+item.inflAssctBfrWqltToc+")" : item.inflAssctBfrWqltToc;
|
||||
item.efflWqltToc = Number(searchYear)<COD_YEAR? "("+item.efflWqltToc+")" : item.efflWqltToc;
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
@@ -461,17 +487,17 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
|
||||
시군구: item.sggNm,
|
||||
시설이름: item.bscFctNm,
|
||||
주소: item.addr,
|
||||
용량: item.fctCpc,
|
||||
유입BOD: item.inflAssctBfrWqltBod,
|
||||
유입TOC: item.inflAssctBfrWqltToc,
|
||||
유입SS: item.inflAssctBfrWqltSs,
|
||||
유입TN: item.inflAssctBfrWqltTn,
|
||||
유입TP: item.inflAssctBfrWqltTp,
|
||||
유출BOD: item.efflWqltBod,
|
||||
유출TOC: item.efflWqltToc,
|
||||
유출SS: item.efflWqltSs,
|
||||
유출TN: item.efflWqltTn,
|
||||
유출TP: item.efflWqltTp,
|
||||
"시설용량(m³/일)": CommaToNumber(item.fctCpc),
|
||||
"유입BOD(mg/L)": CommaToNumber(item.inflAssctBfrWqltBod),
|
||||
"유입TOC(mg/L)": CommaToNumber(item.inflAssctBfrWqltToc),
|
||||
"유입SS(mg/L)": CommaToNumber(item.inflAssctBfrWqltSs),
|
||||
"유입TN(mg/L)": CommaToNumber(item.inflAssctBfrWqltTn),
|
||||
"유입TP(mg/L)": CommaToNumber(item.inflAssctBfrWqltTp),
|
||||
"유출BOD(mg/L)": CommaToNumber(item.efflWqltBod),
|
||||
"유출TOC(mg/L)": CommaToNumber(item.efflWqltToc),
|
||||
"유출SS(mg/L)": CommaToNumber(item.efflWqltSs),
|
||||
"유출TN(mg/L)": CommaToNumber(item.efflWqltTn),
|
||||
"유출TP(mg/L)": CommaToNumber(item.efflWqltTp),
|
||||
});
|
||||
});
|
||||
}else{
|
||||
@@ -480,8 +506,8 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
item.inflAssctBfrWqltToc = Number(searchYear)<2021? "("+item.inflAssctBfrWqltToc+")" : item.inflAssctBfrWqltToc;
|
||||
item.efflWqltToc = Number(searchYear)<2021? "("+item.efflWqltToc+")" : item.efflWqltToc;
|
||||
item.inflAssctBfrWqltToc = Number(searchYear)<COD_YEAR? "("+item.inflAssctBfrWqltToc+")" : item.inflAssctBfrWqltToc;
|
||||
item.efflWqltToc = Number(searchYear)<COD_YEAR? "("+item.efflWqltToc+")" : item.efflWqltToc;
|
||||
});
|
||||
}
|
||||
set((state: FacilityWaterQltyType) => ({
|
||||
@@ -573,48 +599,33 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
|
||||
}
|
||||
|
||||
// facilityPrecipitation의 rainEffectDay 계산 로직을 적용
|
||||
|
||||
const data = res.data.wqltObjs;
|
||||
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
const item = data[idx];
|
||||
if(item){
|
||||
if(item.infoRnDay && Number(item.infoRnDay) > 3) {
|
||||
item.rainEffectDay = 1;
|
||||
} else {
|
||||
item.rainEffectDay = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
const data = CalcRainEffect(res.data.wqltObjs);
|
||||
|
||||
// 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
if(data[idx]) {
|
||||
// 하루 전이 강우영향일(3 이상)인 경우
|
||||
if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) {
|
||||
data[idx]!.rainEffectDay = 1;
|
||||
}
|
||||
// 이틀 전이 강우영향일(3 이상)인 경우
|
||||
if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) {
|
||||
data[idx]!.rainEffectDay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* [(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]
|
||||
/강우시 일별유입BOD)
|
||||
*/
|
||||
//let rainInflAmnt = 0;
|
||||
let sunnyInflAmnt = 0;
|
||||
let sunnyBod = 0;
|
||||
//let rainDay = 0;
|
||||
let sunnyDay = 0;
|
||||
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
if(data[idx] && data[idx]?.rainEffectDay === 1) {
|
||||
if(idx > 1){
|
||||
if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay) >= 3) {
|
||||
data[idx]!.infoRnDay = data[idx-1]!.infoRnDay;
|
||||
}
|
||||
}
|
||||
if(idx > 2){
|
||||
if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay) >= 3) {
|
||||
data[idx]!.infoRnDay = data[idx-2]!.infoRnDay;
|
||||
}
|
||||
}
|
||||
data.forEach(item => {
|
||||
if(item.rainEffectDay == 1){
|
||||
//rainDay += 1;
|
||||
//rainInflAmnt += Number(item.inflAmnt);
|
||||
} else {
|
||||
sunnyDay += 1;
|
||||
sunnyInflAmnt += Number(item.inflAmnt);
|
||||
sunnyBod += Number(item.inflAssctBfrWqltBod);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//const yearRainAmnt = rainInflAmnt===0?0:rainInflAmnt / rainDay;
|
||||
const yearSunnyAmnt = sunnyInflAmnt===0?0:sunnyInflAmnt / sunnyDay;
|
||||
const yearSunnyBod = sunnyBod===0?0:sunnyBod / sunnyDay;
|
||||
//
|
||||
|
||||
const rtnData = data.map((item: FacilityWaterQltyProps) => {
|
||||
dataFormSetting(item)
|
||||
@@ -636,6 +647,12 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
|
||||
if(item.efflWqltToc){
|
||||
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctBfrWqltCod){
|
||||
item.inflAssctBfrWqltCod = "("+Number(Math.round(Number(item.inflAssctBfrWqltCod) * 10)/10).toFixed(1)+")";
|
||||
}
|
||||
if(item.efflWqltCod){
|
||||
item.efflWqltCod = "("+Number(Math.round(Number(item.efflWqltCod) * 10)/10).toFixed(1)+")";
|
||||
}
|
||||
if(item.inflAssctBfrWqltBod){
|
||||
item.inflAssctBfrWqltBod = Number(Math.round(Number(item.inflAssctBfrWqltBod) * 10)/10).toFixed(1);
|
||||
}
|
||||
@@ -665,6 +682,11 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
|
||||
}else{
|
||||
item.tpInflWqltTp = '';
|
||||
}
|
||||
|
||||
const dayBod = Number(item.inflAssctBfrWqltBod);
|
||||
const noProcessInflAmnt = roundNumber(((Number(item.inflAmnt) * dayBod) - (yearSunnyAmnt * yearSunnyBod)) / dayBod, 0)
|
||||
item.noProcessInflAmnt = noProcessInflAmnt && Number(noProcessInflAmnt.replaceAll(',','')) > 0 ? noProcessInflAmnt : '';
|
||||
|
||||
return item;
|
||||
})
|
||||
set((state: FacilityWaterQltyType) => ({
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import DataForm, { roundNumber } from "@/app/components/common/DataForm";
|
||||
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
|
||||
import { fetchFacilityWaterQltyListHist } from "../facilityWaterQlty";
|
||||
import CommaToNumber from "@/app/components/common/CommaToNumber";
|
||||
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
@@ -36,17 +39,17 @@ export interface ExcelType {
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설이름: string,
|
||||
주소: string,
|
||||
용량: number,
|
||||
총유입량: number | '',
|
||||
하수유입량: number | '',
|
||||
연계처리량: number | '',
|
||||
총인반류수량: number | '',
|
||||
방류량: number | '',
|
||||
환경청:string|'',
|
||||
"시설용량(m³/일)": number,
|
||||
"총유입량(m³/일)": number | '',
|
||||
"하수유입량(m³/일)": number | '',
|
||||
"연계처리량(m³/일)": number | '',
|
||||
"총인반류수량(m³/일)": number | '',
|
||||
"방류량(m³/일)": number | '',
|
||||
}
|
||||
|
||||
export type modalExcelType = {
|
||||
@@ -70,6 +73,7 @@ export interface FlowRateModalInterface {
|
||||
efflAmnt : number | '',
|
||||
infoRnDay : number | string | '',
|
||||
rainEffectDay : number | string | '' ,
|
||||
noProcessInflAmnt : number | string | ''
|
||||
}
|
||||
export type FlowRateModalProps = {
|
||||
msrDt : string,
|
||||
@@ -80,6 +84,7 @@ export type FlowRateModalProps = {
|
||||
efflAmnt : number,
|
||||
infoRnDay : number | string | '',
|
||||
rainEffectDay : number | string | '',
|
||||
noProcessInflAmnt : number | string | ''
|
||||
}
|
||||
|
||||
/**====================================
|
||||
@@ -91,53 +96,53 @@ export type FlowRateModalProps = {
|
||||
*/
|
||||
// 리스트 (행정별)
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "A", title: "행정명", row: 0 ,colSpan: 2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", row:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe", row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "totInflAmnt", title: "총 유입입량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2}
|
||||
{ id: "A", title: "행정명", row: 0, colSpan: 2, widthPercent: 16 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", row:1, widthPercent: 8 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe", row:1, widthPercent: 8 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 10},
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "totInflAmnt", title: "총 유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 }
|
||||
];
|
||||
|
||||
// 리스트 (권역별)
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3},
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "totInflAmnt", title: "총 유입입량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2}
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3, widthPercent: 24 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", row:1, widthPercent: 8 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", row:1, widthPercent: 8 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", row:1, widthPercent: 8 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 10 },
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 10 },
|
||||
{ id: "totInflAmnt", title: "총 유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 }
|
||||
];
|
||||
|
||||
// 리스트 (환경청별별)
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "행정명", row: 0 ,colSpan: 2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", row:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe2", row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2 },
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3, widthPercent: 15 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", row:1, widthPercent: 5 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", row:1, widthPercent: 5 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", row:1, widthPercent: 5 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2, widthPercent: 7 },
|
||||
{ id: "B", title: "행정명", row: 0 ,colSpan: 2, widthPercent: 10 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", row:1, widthPercent: 5 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe2", row:1, widthPercent: 5 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "totInflAmnt", title: "총 유입입량\n(m³/일)", align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2 }
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "totInflAmnt", title: "총 유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 },
|
||||
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2, widthPercent: 7 }
|
||||
];
|
||||
|
||||
const flowRateList:flowRateListProps[] = [
|
||||
@@ -154,6 +159,7 @@ const upHeadListFlowRateModal:TableUpperProps[] = [
|
||||
{ id: "sumFlow", title: "연계처리량(m³/일)", align:"right"},
|
||||
{ id: "returnAmnt", title: "총인 반류수량(m³/일)", align:"right"},
|
||||
{ id: "efflAmnt", title: "방류량(m³/일)", align:"right"},
|
||||
{ id: "noProcessInflAmnt", title: "미처리하수량(m³/일)", align:"right"},
|
||||
{ id: "infoRnDay", title: "강우량(mm/일)", align:"right"}
|
||||
]
|
||||
|
||||
@@ -165,7 +171,9 @@ const modalFlowRateListYear:FlowRateModalProps[] = [
|
||||
====================================*/
|
||||
const fetchFlowRateList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
try {
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : ''; const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
console.log(url);
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count }
|
||||
} catch (error) {
|
||||
@@ -174,7 +182,7 @@ const fetchFlowRateList = async (pageNo: number, pageSize: number, searchYear: s
|
||||
}
|
||||
}
|
||||
|
||||
const fetchFlowRateModalList = async (bscFctCd: string, searchYear: string) => {
|
||||
export const fetchFlowRateModalList = async (bscFctCd: string, searchYear: string) => {
|
||||
try {
|
||||
const url = '/fclt/flow/' + bscFctCd + '/' + searchYear;
|
||||
const res = await getFetch('fo', url);
|
||||
@@ -292,12 +300,12 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow
|
||||
시군구: item.gugun,
|
||||
시설이름: item.bscFctNm,
|
||||
주소: item.daddr,
|
||||
용량: item.fctCpc,
|
||||
총유입량: item.totInflAmnt,
|
||||
하수유입량: item.inflAmnt,
|
||||
연계처리량: item.sumFlow,
|
||||
총인반류수량: item.returnAmnt,
|
||||
방류량: item.efflAmnt,
|
||||
"시설용량(m³/일)": item.fctCpc,
|
||||
"총유입량(m³/일)": CommaToNumber(item.totInflAmnt),
|
||||
"하수유입량(m³/일)": CommaToNumber(item.inflAmnt),
|
||||
"연계처리량(m³/일)": CommaToNumber(item.sumFlow),
|
||||
"총인반류수량(m³/일)": CommaToNumber(item.returnAmnt),
|
||||
"방류량(m³/일)": CommaToNumber(item.efflAmnt),
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -318,50 +326,43 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow
|
||||
},
|
||||
searchFlowRateModalList: async (bscFctCd: string, searchYear: string) => {
|
||||
const res = await fetchFlowRateModalList(bscFctCd, searchYear);
|
||||
const data = res.data;
|
||||
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
const item = data[idx];
|
||||
if(item){
|
||||
if(item.infoRnDay && Number(item.infoRnDay.toString().trim()) >= 3) {
|
||||
item.rainEffectDay = 1;
|
||||
} else {
|
||||
item.rainEffectDay = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
const inflData = CalcRainEffect(res.data);
|
||||
|
||||
// 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
if(data[idx]) {
|
||||
// 하루 전이 강우영향일(3 이상)인 경우
|
||||
if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
|
||||
data[idx]!.rainEffectDay = 1;
|
||||
}
|
||||
// 이틀 전이 강우영향일(3 이상)인 경우
|
||||
if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
|
||||
data[idx]!.rainEffectDay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
const res2 = await fetchFacilityWaterQltyListHist(searchYear, bscFctCd);
|
||||
const wqltData = CalcRainEffect(res2?.data.wqltObjs);
|
||||
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
if(data[idx] && data[idx]?.rainEffectDay === 1) {
|
||||
if(idx > 1){
|
||||
if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
|
||||
data[idx]!.infoRnDay = data[idx-1]!.infoRnDay;
|
||||
}
|
||||
}
|
||||
if(idx > 2){
|
||||
if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
|
||||
data[idx]!.infoRnDay = data[idx-2]!.infoRnDay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* [(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]
|
||||
/강우시 일별유입BOD)
|
||||
*/
|
||||
//let rainInflAmnt = 0;
|
||||
let sunnyInflAmnt = 0;
|
||||
let sunnyBod = 0;
|
||||
//let rainDay = 0;
|
||||
let sunnyDay = 0;
|
||||
|
||||
const rtnData = data.map((item: FlowRateModalProps) => {
|
||||
item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0)
|
||||
inflData.forEach(item => {
|
||||
if(item.rainEffectDay == 1){
|
||||
//rainDay += 1;
|
||||
//rainInflAmnt += Number(item.inflAmnt);
|
||||
} else {
|
||||
const msrDt = item.msrDt.replaceAll('-','');
|
||||
sunnyDay += 1;
|
||||
sunnyInflAmnt += Number(item.inflAmnt);
|
||||
sunnyBod += Number(wqltData.filter((wqitem)=>wqitem.msrDt === msrDt)[0].inflAssctBfrWqltBod);
|
||||
}
|
||||
});
|
||||
|
||||
//const yearRainAmnt = rainInflAmnt===0?0:rainInflAmnt / rainDay;
|
||||
const yearSunnyAmnt = sunnyInflAmnt===0?0:sunnyInflAmnt / sunnyDay;
|
||||
const yearSunnyBod = sunnyBod===0?0:sunnyBod / sunnyDay;
|
||||
|
||||
const rtnData = inflData.map((item: FlowRateModalProps) => {
|
||||
const dayBod = Number(wqltData.filter(wqitem=>wqitem.msrDt === item.msrDt.replaceAll('-',''))[0].inflAssctBfrWqltBod);
|
||||
const noProcessInflAmnt = roundNumber(((Number(item.inflAmnt) * dayBod) - (yearSunnyAmnt * yearSunnyBod)) / dayBod, 0)
|
||||
|
||||
item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0);
|
||||
item.noProcessInflAmnt = noProcessInflAmnt && Number(noProcessInflAmnt.replaceAll(',','')) > 0 ? noProcessInflAmnt : '';
|
||||
dataFormSetting(item);
|
||||
return item;
|
||||
});
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import { calRainEffectDay, type ApiResponse, type FlowDataItem } from "../underWaterInput";
|
||||
import { type ApiResponse, type FlowDataItem } from "../underWaterInput";
|
||||
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
|
||||
import { roundUp } from "../common";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
@@ -45,44 +47,44 @@ const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "A", title: "행정구역", upSequnce:1, row:0, colSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, 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: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "variableLoadPercent", title: "변동부하율", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' },
|
||||
{ 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: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "A", title: "유역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row:1},
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, 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: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 10 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "variableLoadPercent", title: "변동부하율", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' },
|
||||
{ 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: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "A", title: "유역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1},
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1, widthPercent: 5 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1, widthPercent: 5 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1, widthPercent: 5},
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2, widthPercent: 8 },
|
||||
{ id: "B", title: "행정구역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, 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: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "variableLoadPercent", title: "변동부하율", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' },
|
||||
{ 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: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right', widthPercent: 8 },
|
||||
];
|
||||
|
||||
const planSewageList:PlanSewageProps[] = [
|
||||
@@ -112,10 +114,10 @@ export type ExcelType = {
|
||||
시군구: string;
|
||||
시설이름: string;
|
||||
주소: string;
|
||||
시설용량: number;
|
||||
여유용량: number;
|
||||
변동부하율 : number;
|
||||
분류식화율 : number;
|
||||
"시설용량(m³/일)": number;
|
||||
"여유용량(m³/일)": number;
|
||||
"변동부하율(%)" : number;
|
||||
"분류식화율(%)" : number;
|
||||
}
|
||||
|
||||
const dataFormSetting=(item : PlanSewageProps)=> {
|
||||
@@ -182,22 +184,25 @@ export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageTy
|
||||
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 = calRainEffectDay(res2.data, 'SUNNY');
|
||||
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 = avgInflAmntSunny;
|
||||
if(item.bscFctCd === '11200PB001R'){
|
||||
console.log('avgInflAmntSunny : ',item.avgInflAmntSunny);
|
||||
console.log('calData : ',calData);
|
||||
}
|
||||
item.avgInflAmntSunny = roundUp(avgInflAmntSunny, 0);
|
||||
item.maxInflAmntSunny = roundUp(maxInflAmntSunny, 0);
|
||||
return item;
|
||||
}));
|
||||
|
||||
|
||||
/**
|
||||
* 결과데이터 계산
|
||||
* (1) 여유용량 = 시설용량 - 건기시 평균유량
|
||||
@@ -205,8 +210,6 @@ export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageTy
|
||||
* (3) 분류식화율 = 분류식지역 면적(㎢)/처리구역 면적합계(㎢) ×100
|
||||
*/
|
||||
const resultData = processedData.map((item:PlanSewageProps) => {
|
||||
console.log('item.fctCpc : ',item.fctCpc);
|
||||
console.log('item.avgInflAmntSunny : ',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.classifiedSewerPercent = item.sprtProcZoneAr && item.sprtProcZoneAr!==0 ? Number(item.sprtProcZoneAr) / Number(item.procZoneSm) * 100 : 0;
|
||||
@@ -229,10 +232,10 @@ export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageTy
|
||||
시도: item.sido,
|
||||
시군구: item.gugun,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc,
|
||||
여유용량: item.spareCapacity,
|
||||
변동부하율: item.variableLoadPercent,
|
||||
분류식화율: item.classifiedSewerPercent,
|
||||
"시설용량(m³/일)": item.fctCpc,
|
||||
"여유용량(m³/일)": item.spareCapacity,
|
||||
"변동부하율(%)": item.variableLoadPercent,
|
||||
"분류식화율(%)": item.classifiedSewerPercent,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -63,25 +63,25 @@ export interface ExcelType {
|
||||
시설코드: string,
|
||||
시설명: string,
|
||||
주소: string,
|
||||
시설용량: number | '',
|
||||
증설계획기존: number | '',
|
||||
증설계획현재: number | '',
|
||||
증설계획1단계: number | '',
|
||||
증설계획2단계: number | '',
|
||||
증설계획3단계: number | '',
|
||||
증설계획4단계: number | '',
|
||||
처리인구기존: number | '',
|
||||
처리인구현재: number | '',
|
||||
처리인구1단계: number | '',
|
||||
처리인구2단계: number | '',
|
||||
처리인구3단계: number | '',
|
||||
처리인구4단계: number | '',
|
||||
처리구역기존: number | '',
|
||||
처리구역현재: number | '',
|
||||
처리구역1단계: number | '',
|
||||
처리구역2단계: number | '',
|
||||
처리구역3단계: number | '',
|
||||
처리구역4단계: number | '',
|
||||
"시설옹량(m³/일)": number | '',
|
||||
"증설계획기존(m³/일)": number | '',
|
||||
"증설계획현재(m³/일)": number | '',
|
||||
"증설계획1단계(m³/일)": number | '',
|
||||
"증설계획2단계(m³/일)": number | '',
|
||||
"증설계획3단계(m³/일)": number | '',
|
||||
"증설계획4단계(m³/일)": number | '',
|
||||
"처리인구기존(인)": number | '',
|
||||
"처리인구현재(인)": number | '',
|
||||
"처리인구1단계(인)": number | '',
|
||||
"처리인구2단계(인)": number | '',
|
||||
"처리인구3단계(인)": number | '',
|
||||
"처리인구4단계(인)": number | '',
|
||||
"처리구역기존(km²)": number | '',
|
||||
"처리구역현재(km²)": number | '',
|
||||
"처리구역1단계(km²)": number | '',
|
||||
"처리구역2단계(km²)": number | '',
|
||||
"처리구역3단계(km²)": number | '',
|
||||
"처리구역4단계(km²)": number | '',
|
||||
처리구역: string | ''
|
||||
}
|
||||
|
||||
@@ -128,35 +128,35 @@ const ProcessFacilityLabelArray:string[] = ['구분', '시도', '시군구','용
|
||||
|
||||
// 리스트 헤더(행정별)
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "A", title: "행정구역", colSpan:2, rowSpan:2, row:0},
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", row:2 },
|
||||
{ id: "sigungo", title: "시군구", upName:"upChangeRe", row:2 },
|
||||
{ id: "swtrmtFcltNm", title: "시설명", rowSpan:3, row:0},
|
||||
{ id: "location", title: "주소", rowSpan:3, row:0, },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", rowSpan:3, row:0},
|
||||
{ id: "B", title: "시설계획", colSpan:19, row:0},
|
||||
{ id: "C", title: "증설계획(m³/일)", colSpan:6, row:1},
|
||||
{ id: "planSwageQntSumDt4", title: "기승인\n4단계", row:2, align:"right"},
|
||||
{ id: "planSwageQntSum", title: "현재", row:2, align:"right"},
|
||||
{ id: "planSwageQntSumDc1", title: "1단계", row:2, align:"right"},
|
||||
{ id: "planSwageQntSumDc2", title: "2단계", row:2, align:"right"},
|
||||
{ id: "planSwageQntSumDc3", title: "3단계", row:2, align:"right"},
|
||||
{ id: "planSwageQntSumDc4", title: "4단계", row:2, align:"right"},
|
||||
{ id: "D", title: "처리인구(인)", colSpan:6, row:1},
|
||||
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계", row:2, align:"right"},
|
||||
{ id: "swtrmtPpltnCnt", title: "현재", row:2, align:"right"},
|
||||
{ id: "swtrmtPpltnCntDc1", title: "1단계", row:2, align:"right"},
|
||||
{ id: "swtrmtPpltnCntDc2", title: "2단계", row:2, align:"right"},
|
||||
{ id: "swtrmtPpltnCntDc3", title: "3단계", row:2, align:"right"},
|
||||
{ id: "swtrmtPpltnCntDc4", title: "4단계", row:2, align:"right"},
|
||||
{ id: "E", title: "처리구역(km²)", colSpan:7, row:1},
|
||||
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계", row:2, align:"right"},
|
||||
{ id: "swtrmtZoneArea", title: "현재", row:2, align:"right"},
|
||||
{ id: "swtrmtZoneAreaDc1", title: "1단계", row:2, align:"right"},
|
||||
{ id: "swtrmtZoneAreaDc2", title: "2단계", row:2, align:"right"},
|
||||
{ id: "swtrmtZoneAreaDc3", title: "3단계", row:2, align:"right"},
|
||||
{ id: "swtrmtZoneAreaDc4", title: "4단계", row:2, align:"right"},
|
||||
{ id: "trtDstr", title: "처리구역", row:2}
|
||||
{ id: "A", title: "행정구역", colSpan:2, rowSpan:2, row:0 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", row:2, widthPercent:4 },
|
||||
{ id: "sigungo", title: "시군구", upName:"upChangeRe", row:2, widthPercent:4 },
|
||||
{ id: "swtrmtFcltNm", title: "시설명", rowSpan:3, row:0, widthPercent: 8 },
|
||||
{ id: "location", title: "주소", rowSpan:3, row:0 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", rowSpan:3, row:0, widthPercent: 5 },
|
||||
{ id: "B", title: "시설계획", colSpan:19, row: 0 },
|
||||
{ id: "C", title: "증설계획(m³/일)", colSpan:6, row: 1 },
|
||||
{ id: "planSwageQntSumDt4", title: "기승인\n4단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "planSwageQntSum", title: "현재", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "planSwageQntSumDc1", title: "1단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "planSwageQntSumDc2", title: "2단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "planSwageQntSumDc3", title: "3단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "planSwageQntSumDc4", title: "4단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "D", title: "처리인구(인)", colSpan:6, row:1 },
|
||||
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "swtrmtPpltnCnt", title: "현재", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "swtrmtPpltnCntDc1", title: "1단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "swtrmtPpltnCntDc2", title: "2단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "swtrmtPpltnCntDc3", title: "3단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "swtrmtPpltnCntDc4", title: "4단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "E", title: "처리구역(km²)", colSpan:7, row:1 },
|
||||
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "swtrmtZoneArea", title: "현재", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "swtrmtZoneAreaDc1", title: "1단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "swtrmtZoneAreaDc2", title: "2단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "swtrmtZoneAreaDc3", title: "3단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "swtrmtZoneAreaDc4", title: "4단계", row:2, align:"right", widthPercent: 2.5 },
|
||||
{ id: "trtDstr", title: "처리구역", row:2 }
|
||||
];
|
||||
|
||||
const processAreaList:ProcessAreaProps[] = [
|
||||
@@ -385,25 +385,25 @@ export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set:
|
||||
시설코드: item.swtrmtFcltCd,
|
||||
시설명: item.swtrmtFcltNm,
|
||||
주소: item.location,
|
||||
시설용량: item.fctCpc,
|
||||
증설계획기존: item.planSwageQntSumDt4,
|
||||
증설계획현재: item.planSwageQntSum,
|
||||
증설계획1단계: item.planSwageQntSumDc1,
|
||||
증설계획2단계: item.planSwageQntSumDc2,
|
||||
증설계획3단계: item.planSwageQntSumDc3,
|
||||
증설계획4단계: item.planSwageQntSumDc4,
|
||||
처리인구기존: item.swtrmtPpltnCntDt4,
|
||||
처리인구현재: item.swtrmtPpltnCnt,
|
||||
처리인구1단계: item.swtrmtPpltnCntDc1,
|
||||
처리인구2단계: item.swtrmtPpltnCntDc2,
|
||||
처리인구3단계: item.swtrmtPpltnCntDc3,
|
||||
처리인구4단계: item.swtrmtPpltnCntDc4,
|
||||
처리구역기존: item.swtrmtZoneAreaDt4,
|
||||
처리구역현재: item.swtrmtZoneArea,
|
||||
처리구역1단계: item.swtrmtZoneAreaDc1,
|
||||
처리구역2단계: item.swtrmtZoneAreaDc2,
|
||||
처리구역3단계: item.swtrmtZoneAreaDc3,
|
||||
처리구역4단계: item.swtrmtZoneAreaDc4,
|
||||
"시설옹량(m³/일)": item.fctCpc,
|
||||
"증설계획기존(m³/일)": item.planSwageQntSumDt4,
|
||||
"증설계획현재(m³/일)": item.planSwageQntSum,
|
||||
"증설계획1단계(m³/일)": item.planSwageQntSumDc1,
|
||||
"증설계획2단계(m³/일)": item.planSwageQntSumDc2,
|
||||
"증설계획3단계(m³/일)": item.planSwageQntSumDc3,
|
||||
"증설계획4단계(m³/일)": item.planSwageQntSumDc4,
|
||||
"처리인구기존(인)": item.swtrmtPpltnCntDt4,
|
||||
"처리인구현재(인)": item.swtrmtPpltnCnt,
|
||||
"처리인구1단계(인)": item.swtrmtPpltnCntDc1,
|
||||
"처리인구2단계(인)": item.swtrmtPpltnCntDc2,
|
||||
"처리인구3단계(인)": item.swtrmtPpltnCntDc3,
|
||||
"처리인구4단계(인)": item.swtrmtPpltnCntDc4,
|
||||
"처리구역기존(km²)": item.swtrmtZoneAreaDt4,
|
||||
"처리구역현재(km²)": item.swtrmtZoneArea,
|
||||
"처리구역1단계(km²)": item.swtrmtZoneAreaDc1,
|
||||
"처리구역2단계(km²)": item.swtrmtZoneAreaDc2,
|
||||
"처리구역3단계(km²)": item.swtrmtZoneAreaDc3,
|
||||
"처리구역4단계(km²)": item.swtrmtZoneAreaDc4,
|
||||
처리구역: item.trtDstr
|
||||
});
|
||||
});
|
||||
|
||||
@@ -44,9 +44,9 @@ export interface ExcelType {
|
||||
시군구: string,
|
||||
시설이름: string,
|
||||
주소: string,
|
||||
시설용량: number | '',
|
||||
계획유입수질: number | '',
|
||||
설계유입수질: number | '',
|
||||
"시설용량(m³/일)": number | '',
|
||||
"계획유입수질(mg/L)": number | '',
|
||||
"설계유입수질(mg/L)": number | '',
|
||||
공법: string,
|
||||
가동개시일: string,
|
||||
준공일: string,
|
||||
@@ -118,7 +118,7 @@ export type fcltyHistInfoProps = {
|
||||
sitArea : number,
|
||||
trtDstrArea : number,
|
||||
swrTrtPopl : number,
|
||||
fcltCpc : number | ''
|
||||
fctCpc : number | ''
|
||||
}
|
||||
|
||||
// 시설 수질정보
|
||||
@@ -162,52 +162,56 @@ const ProcessFacilityLabelArray:string[] = ['구분', '시도', '시군구','용
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2 },
|
||||
{ id: "bscFctNm", title: "시설명"},
|
||||
{ id: "daddr", title: "주소"},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align: 'right'},
|
||||
{ id: "plInflWqltBod", title: "계획유입수질\n(mg/L)", align:"right"},
|
||||
{ id: "dsInflWqltBod", title: "설계유입수질\n(mg/L)", align:"right"},
|
||||
{ id: "trtFrfNm", title: '공법'},
|
||||
{ id: "rnDt", title: '가동개시일'},
|
||||
{ id: "cmplDt", title: '준공일' },
|
||||
{ id: "trstOprEtpNm", title: '관리대행업자'}
|
||||
{ id: "A", title: "행정명", colSpan: 2, row: 0, widthPercent: 10 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", row: 1, upSequnce:1, widthPercent: 5 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe", row: 1, upSequnce:2, widthPercent: 5 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", row: 0, align: 'right', rowSpan: 2, widthPercent: 5 },
|
||||
{ id: "plInflWqltBod", title: "계획유입수질\n(mg/L)", row: 0, align:"right", rowSpan: 2, widthPercent: 5 },
|
||||
{ id: "dsInflWqltBod", title: "설계유입수질\n(mg/L)", row: 0, align:"right", rowSpan: 2, widthPercent: 5 },
|
||||
{ id: "trtFrfNm", title: '공법', row: 0, rowSpan: 2 },
|
||||
{ id: "rnDt", title: '가동개시일', row: 0, rowSpan: 2, widthPercent: 5 },
|
||||
{ id: "cmplDt", title: '준공일', row: 0, rowSpan: 2, widthPercent: 5 },
|
||||
{ id: "trstOprEtpNm", title: '관리대행업자', row: 0, rowSpan: 2 , widthPercent: 14}
|
||||
];
|
||||
|
||||
// 처리시설 리스트 (유역)
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3},
|
||||
{ id: "bscFctNm", title: "시설명"},
|
||||
{ id: "daddr", title: "주소"},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align: 'right'},
|
||||
{ id: "plInflWqltBod", title: "계획유입수질\n(mg/L)", align:'right'},
|
||||
{ id: "dsInflWqltBod", title: "설계유입수질\n(mg/L)", align:'right'},
|
||||
{ id: "trtFrfNm", title: '공법'},
|
||||
{ id: "rnDt", title: '가동개시일'},
|
||||
{ id: "cmplDt", title: '준공일' },
|
||||
{ id: "trstOprEtpNm", title: '관리대행업자'}
|
||||
{ id: "A", title: "유역", colSpan: 3, row: 0, widthPercent: 15 },
|
||||
{ id: "rvbsn", title: "권역", row: 1, widthPercent: 5 },
|
||||
{ id: "lgbsn", title: "단위유역", row: 1, widthPercent: 5 },
|
||||
{ id: "mdmbsn", title: "중권역", row: 1, widthPercent: 5 },
|
||||
{ id: "bscFctNm", title: "시설명", rowSpan: 2,row: 0, widthPercent: 8 },
|
||||
{ id: "daddr", title: "주소", rowSpan: 2,row: 0 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", rowSpan: 2,row: 0, widthPercent: 5, align: 'right'},
|
||||
{ id: "plInflWqltBod", title: "계획유입수질\n(mg/L)", rowSpan: 2,row: 0, widthPercent: 6, align:'right'},
|
||||
{ id: "dsInflWqltBod", title: "설계유입수질\n(mg/L)", rowSpan: 2,row: 0, widthPercent: 6, align:'right'},
|
||||
{ id: "trtFrfNm", title: '공법', rowSpan: 2,row: 0 },
|
||||
{ id: "rnDt", title: '가동개시일', rowSpan: 2,row: 0, widthPercent: 5 },
|
||||
{ id: "cmplDt", title: '준공일', rowSpan: 2,row: 0, widthPercent: 5 },
|
||||
{ id: "trstOprEtpNm", title: '관리대행업자', rowSpan: 2,row: 0, widthPercent: 14 }
|
||||
];
|
||||
|
||||
// 처리시설 리스트 (환경청청)
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3},
|
||||
{ id: "rgnNm", title: "환경청"},
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe2",upSequnce:2 },
|
||||
{ id: "bscFctNm", title: "시설명"},
|
||||
{ id: "daddr", title: "주소"},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align: 'right'},
|
||||
{ id: "plInflWqltBod", title: "계획유입수질\n(mg/L)", align:'right'},
|
||||
{ id: "dsInflWqltBod", title: "설계유입수질\n(mg/L)", align:'right'},
|
||||
{ id: "trtFrfNm", title: '공법'},
|
||||
{ id: "rnDt", title: '가동개시일'},
|
||||
{ id: "cmplDt", title: '준공일' },
|
||||
{ id: "trstOprEtpNm", title: '관리대행업자'}
|
||||
{ id: "A", title: "유역", colSpan: 3, row: 0, widthPercent: 12 },
|
||||
{ id: "rvbsn", title: "권역", row: 1, widthPercent: 4 },
|
||||
{ id: "lgbsn", title: "단위유역", row: 1, widthPercent: 4},
|
||||
{ id: "mdmbsn", title: "중권역", row: 1, widthPercent: 4 },
|
||||
{ id: "rgnNm", title: "환경청", row: 0, rowSpan: 2, widthPercent: 6 },
|
||||
{ id: "B", title: "행정명", colSpan: 2, row: 0, widthPercent: 8 },
|
||||
{ id: "sido", title: "시도", row: 1, widthPercent: 4 },
|
||||
{ id: "gugun", title: "시군구", row: 1, widthPercent: 4 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 8 },
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", row: 0, rowSpan: 2, align: 'right', widthPercent: 5 },
|
||||
{ id: "plInflWqltBod", title: "계획유입수질\n(mg/L)", row: 0, rowSpan: 2, align:'right', widthPercent: 5 },
|
||||
{ id: "dsInflWqltBod", title: "설계유입수질\n(mg/L)", row: 0, rowSpan: 2, align:'right', widthPercent: 5 },
|
||||
{ id: "trtFrfNm", title: '공법', row: 0, rowSpan: 2 },
|
||||
{ id: "rnDt", title: '가동개시일', row: 0, rowSpan: 2, widthPercent: 5 },
|
||||
{ id: "cmplDt", title: '준공일', row: 0, rowSpan: 2, widthPercent: 5 },
|
||||
{ id: "trstOprEtpNm", title: '관리대행업자', row: 0, rowSpan: 2, widthPercent: 14 }
|
||||
];
|
||||
|
||||
const processFacilityList:facilityListProps[] = [
|
||||
@@ -345,7 +349,7 @@ const gridListFcltyHistInfo:fcltyHistInfoProps[] = [
|
||||
sitArea : 0,
|
||||
trtDstrArea : 0,
|
||||
swrTrtPopl : 0,
|
||||
fcltCpc : 860000
|
||||
fctCpc : 860000
|
||||
}
|
||||
];
|
||||
|
||||
@@ -456,7 +460,7 @@ const fetchFacilityHistInfo = async (facilityCd:string ): Promise<fcltyHistInfoP
|
||||
};
|
||||
|
||||
// 시설정보 수질정보 데이터 호출
|
||||
const fetchFacilityWaterQltyInfo = async (facilityCd:string ): Promise<fcltyWaterQltyInfoProps[]> => {
|
||||
export const fetchFacilityWaterQltyInfo = async (facilityCd:string ): Promise<fcltyWaterQltyInfoProps[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/prcsFclt/info/history/'+facilityCd);
|
||||
const data = res.data;
|
||||
@@ -623,13 +627,13 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio
|
||||
시군구: item.gugun,
|
||||
시설이름: item.bscFctNm,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc ? Number(item.fctCpc) : '',
|
||||
계획유입수질: item.plInflWqltBod ? Number(item.plInflWqltBod) : '',
|
||||
설계유입수질: item.dsInflWqltBod ? Number(item.dsInflWqltBod) : '',
|
||||
"시설용량(m³/일)": item.fctCpc ? Number(item.fctCpc.toString().replaceAll(',','')) : '',
|
||||
"계획유입수질(mg/L)": item.plInflWqltBod ? Number(item.plInflWqltBod) : '',
|
||||
"설계유입수질(mg/L)": item.dsInflWqltBod ? Number(item.dsInflWqltBod) : '',
|
||||
공법: item.trtFrfNm,
|
||||
가동개시일: item.rnDt,
|
||||
준공일: item.cmplDt,
|
||||
관리대행업자: item.mnstr,
|
||||
관리대행업자: item.trstOprEtpNm,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
+171
-76
@@ -1,8 +1,9 @@
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
|
||||
import DataForm, { roundNumber } from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { fetchFacilityWaterQltyListHist } from "../facilityWaterQlty";
|
||||
import { calRainEffectDay } from "../underWaterInput";
|
||||
import type { FlowResponse } from "../sewageOccur";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
@@ -30,6 +31,9 @@ export type RdiProps = {
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
rainEffectDay : number, // 강우영향일
|
||||
chungchunFlow : string | number | '',
|
||||
rainCalInflAmnt : string | number | '',
|
||||
properYn : string,
|
||||
}
|
||||
|
||||
export interface RdiInterface {
|
||||
@@ -44,11 +48,15 @@ export interface RdiInterface {
|
||||
inflAmnt : number,
|
||||
winterAvgBodLowRainfall : number,
|
||||
rdiiValue : number,
|
||||
infoRnDay : number,
|
||||
infoRnDay : number | string,
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
rainEffectDay : number, // 강우영향일
|
||||
chungchunFlow : string | number | '',
|
||||
rainCalInflAmnt : string | number | '',
|
||||
properYn : string,
|
||||
}
|
||||
|
||||
// 모달
|
||||
@@ -79,67 +87,79 @@ export interface ExcelType {
|
||||
시군구: string,
|
||||
시설명: string,
|
||||
주소: string,
|
||||
시설용량: number,
|
||||
하절기강우일최저유입BOD: number | '',
|
||||
하절기최저유입BOD유입유량: number | string | '',
|
||||
동절기청천시유입BOD: number | '',
|
||||
RDII추정 : number | '',
|
||||
RDII추정시일강수량 : number | '',
|
||||
"시설용량(m³/일)": number,
|
||||
"청천시유입하수량(m³/일)": string | number | '',
|
||||
"하절기강우일최저유입BOD(mg/L)": number | '',
|
||||
"하절기최저유입BOD유입유량(m³/일)": number | string | '',
|
||||
"동절기청천시유입BOD(mg/L)": number | '',
|
||||
"RDII추정" : number | '',
|
||||
"RDII추정시일강수량(mm)": number | '',
|
||||
"강우시총추정유입량(m³/일)" : string | number | '',
|
||||
적정여부 : string,
|
||||
}
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "A", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "sigungo", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "sido", title: "시도", row:1, widthPercent: 6 },
|
||||
{ id: "sigungo", title: "시군구", row:1, widthPercent: 6 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 7 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 7 },
|
||||
{ id: "chungchunFlow", title: "청천시 유입하수량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 7 },
|
||||
{ id: "B", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 },
|
||||
{ id: "summerMinBodValue", title: "3mm 이상 강우일 중 최저 유입BOD\n(mg/L)", align:"right", row:1 },
|
||||
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량\n(m³/일)", row:1, align:"right" },
|
||||
{ id: "summerMinBodValue", title: "3mm 이상 강우일 중\n최저 유입BOD\n(mg/L)", align:"right", row:1, widthPercent: 7 },
|
||||
{ id: "inflAmnt", title: "하절기최저유입\nBOD유입유량\n(m³/일)", row:1, align:"right", widthPercent: 7 },
|
||||
{ id: "C", title: "동절기 운영현황(1~2월)", row:0 },
|
||||
{ id: "winterAvgBodLowRainfall", title: "청천시 유입BOD\n(mg/L)", row:1, align:"right" },
|
||||
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2, align:"right" },
|
||||
{ id: "infoRnDay", title: "RDII추정시일강수량\n(mm)", row:0, rowSpan:2, align:"right" },
|
||||
{ id: "winterAvgBodLowRainfall", title: "청천시 유입BOD\n(mg/L)", row:1, align:"right", widthPercent: 8 },
|
||||
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2, align:"right", widthPercent: 8 },
|
||||
{ id: "infoRnDay", title: "RDII추정시\n일강수량\n(mm)", row:0, rowSpan:2, align:"right", widthPercent: 7 },
|
||||
{ id: "rainCalInflAmnt", title: "강우시\n총 추정유입량\n(m³/일)", row:0, rowSpan:2, align:"right", widthPercent: 6 },
|
||||
{ id: "properYn", title: "적정여부", row:0, rowSpan:2, widthPercent: 6 },
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "rvbsn", title: "권역", row:1, widthPercent: 5 },
|
||||
{ id: "lgbsn", title: "단위유역", row:1, widthPercent: 5 },
|
||||
{ id: "mdmbsn", title: "중권역", row:1, widthPercent: 5 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 7 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 7 },
|
||||
{ id: "chungchunFlow", title: "청천시 유입하수량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 7 },
|
||||
{ id: "B", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 },
|
||||
{ id: "summerMinBodValue", title: "하절기강우일최저유입BOD", align:"right", row:1 },
|
||||
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량", row:1, align:"right" },
|
||||
{ id: "summerMinBodValue", title: "3mm 이상 강우일 중\n최저 유입BOD\n(mg/L)", align:"right", row:1, widthPercent: 7 },
|
||||
{ id: "inflAmnt", title: "하절기최저유입\nBOD유입유량\n(m³/일)", row:1, align:"right", widthPercent: 7 },
|
||||
{ id: "D", title: "동절기 운영현황(1~2월)", row:0 },
|
||||
{ id: "winterAvgBodLowRainfall", title: "동절기청천시유입BOD", row:1, align:"right" },
|
||||
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2, align:"right" },
|
||||
{ id: "infoRnDay", title: "RDII추정시일강수량", row:0, rowSpan:2, align:"right" },
|
||||
{ id: "winterAvgBodLowRainfall", title: "청천시 유입BOD\n(mg/L)", row:1, align:"right", widthPercent: 8 },
|
||||
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2, align:"right", widthPercent: 7 },
|
||||
{ id: "infoRnDay", title: "RDII추정시\n일강수량\n(mm)", row:0, rowSpan:2, align:"right", widthPercent: 7 },
|
||||
{ id: "rainCalInflAmnt", title: "강우시\n총 추정유입량\n(m³/일)", row:0, rowSpan:2, align:"right", widthPercent: 6 },
|
||||
{ id: "properYn", title: "적정여부", row:0, rowSpan:2, widthPercent: 6 },
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "rvbsn", title: "권역", row:1, widthPercent: 4 },
|
||||
{ id: "lgbsn", title: "단위유역", row:1, widthPercent: 4 },
|
||||
{ id: "mdmbsn", title: "중권역", row:1, widthPercent: 4 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2, widthPercent: 6 },
|
||||
{ id: "B", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1 },
|
||||
{ id: "sigungo", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1, widthPercent: 4 },
|
||||
{ id: "sigungo", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1, widthPercent: 4 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 6 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 5 },
|
||||
{ id: "chungchunFlow", title: "청천시 유입하수량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 6 },
|
||||
{ id: "C", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 },
|
||||
{ id: "summerMinBodValue", title: "하절기강우일최저유입BOD", align:"right", row:1 },
|
||||
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량", row:1, align:"right" },
|
||||
{ id: "summerMinBodValue", title: "3mm 이상 강우일 중\n최저 유입BOD\n(mg/L)", align:"right", row:1, widthPercent: 6 },
|
||||
{ id: "inflAmnt", title: "하절기최저유입\nBOD유입유량\n(m³/일)", row:1, align:"right", widthPercent: 6 },
|
||||
{ id: "D", title: "동절기 운영현황(1~2월)", row:0 },
|
||||
{ id: "winterAvgBodLowRainfall", title: "동절기청천시유입BOD", row:1, align:"right" },
|
||||
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2, align:"right" },
|
||||
{ id: "infoRnDay", title: "RDII추정시일강수량", row:0, rowSpan:2, align:"right" },
|
||||
{ id: "winterAvgBodLowRainfall", title: "청천시 유입BOD\n(mg/L)", row:1, align:"right", widthPercent: 8 },
|
||||
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2, align:"right", widthPercent: 6 },
|
||||
{ id: "infoRnDay", title: "RDII추정시\n일강수량\n(mm)", row:0, rowSpan:2, align:"right", widthPercent: 6 },
|
||||
{ id: "rainCalInflAmnt", title: "강우시\n총 추정유입량\n(m³/일)", row:0, rowSpan:2, align:"right", widthPercent: 6 },
|
||||
{ id: "properYn", title: "적정여부", row:0, rowSpan:2, widthPercent: 6 },
|
||||
];
|
||||
|
||||
const rdiList:RdiProps[] = [
|
||||
@@ -153,7 +173,6 @@ const fetchRdiList = async (pageNo: number, pageSize: number, searchYear: string
|
||||
try{
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/rdii/list/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
console.log(url);
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count }
|
||||
}catch(error){
|
||||
@@ -207,11 +226,6 @@ export const rdiInitState: RdiType = {
|
||||
|
||||
const dataFormSetting=(item : RdiProps)=> {
|
||||
DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'summerMinBodValue', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'winterAvgBodLowRainfall', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'rdiiValue', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'infoRnDay', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float0', column: 'inflAmnt', item: item as unknown as Record<string, unknown>});
|
||||
}
|
||||
|
||||
// Add type definitions for state setter function
|
||||
@@ -232,9 +246,31 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio
|
||||
|
||||
const res = await fetchRdiList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const data = res.data;
|
||||
const excelDownList: ExcelType[] = [];
|
||||
const reData = await Promise.all(data.map(async (item: RdiProps) => {
|
||||
const bscFctCd = item.bscFctCd;
|
||||
const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as FlowResponse;
|
||||
const calData = CalcRainEffect(res2.data, 'SUNNY');
|
||||
let avgChungcunSumFlow = 0;
|
||||
let chungcunSumFlow = 0;
|
||||
|
||||
const rtnData = data.map((item: RdiProps) => {
|
||||
calData.forEach((flowItem: any) => {
|
||||
chungcunSumFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
|
||||
/* if(flowItem.msrDt.substring(4,6) ==='06' || flowItem.msrDt.substring(4,6) ==='07' || flowItem.msrDt.substring(4,6) ==='08'){
|
||||
sumSummerChungcunDay += 1;
|
||||
sumSummerChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
|
||||
}else if(flowItem.msrDt.substring(4,6) ==='01' || flowItem.msrDt.substring(4,6) ==='02'){
|
||||
sumWinterChungcunDay += 1;
|
||||
sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
|
||||
} */
|
||||
});
|
||||
avgChungcunSumFlow = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / calData.length : 0;
|
||||
item.chungchunFlow = avgChungcunSumFlow;
|
||||
item.rainCalInflAmnt = Number(avgChungcunSumFlow) + Number(item.rdiiValue);
|
||||
return item;
|
||||
}));
|
||||
|
||||
const excelDownList: ExcelType[] = [];
|
||||
const rtnData = reData.map((item: RdiProps) => {
|
||||
return {
|
||||
...item,
|
||||
sido: item.lclgvrnmntNm.split(' ')[0]?.toString() || '',
|
||||
@@ -242,44 +278,100 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio
|
||||
inflAmnt: item.inflAmnt?Number(item.inflAmnt).toFixed(1): ''
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// 청천히 동절기 유입bod를 새로 구하기 위해서 재 호출
|
||||
for (const item of rtnData) {
|
||||
const fcltyCd = item.bscFctCd;
|
||||
let winterInflBod = 0;
|
||||
|
||||
const res: any = await fetchFacilityWaterQltyListHist(searchYear, fcltyCd);
|
||||
|
||||
let rtnWinterInflBod = 0;
|
||||
let rtnSummerBodInfl = 0;
|
||||
let rtnSummerBod = 0;
|
||||
let rtnRdiValue = 0;
|
||||
let rtnRdiRain = 0;
|
||||
let chungchunFlow = 0;
|
||||
|
||||
if (res?.data) {
|
||||
const clone = (arr: any[]) => arr?.map(v => ({ ...v })) ?? [];
|
||||
const rtnWqltData = res.data.wqltObjs;
|
||||
rtnWqltData.forEach((dataItem: any) => {
|
||||
dataItem.rainEffectDay = 0;
|
||||
});
|
||||
const wqltDataTot = CalcRainEffect(clone(rtnWqltData));
|
||||
const wqltDataSunny = CalcRainEffect(clone(rtnWqltData), 'SUNNY');
|
||||
|
||||
calRainEffectDay(rtnWqltData, 'SUNNY');
|
||||
let chungchunInfl = 0;
|
||||
let chungchunCnt = 0;
|
||||
let minSummerBod = 99999999;
|
||||
let minSummerBodInfl = 99999999;
|
||||
let winterCnt = 0;
|
||||
let winterBodSunny = 0;
|
||||
let rdiRain = 0;
|
||||
|
||||
const summerMonth = ['06', '07', '08'];
|
||||
const winterMonth = ['01', '02'];
|
||||
|
||||
const rtnWqltWinterData = rtnWqltData.filter((dataItem: any) =>
|
||||
(dataItem.msrDt.substring(4, 6) === '01' ||
|
||||
dataItem.msrDt.substring(4, 6) === '02') &&
|
||||
dataItem.rainEffectDay == 0
|
||||
);
|
||||
wqltDataTot.forEach(item2 => {
|
||||
if(item2.rainEffectDay == 0){
|
||||
chungchunCnt ++;
|
||||
chungchunInfl += Number(item2.inflAmnt);
|
||||
}
|
||||
|
||||
rtnWqltWinterData.forEach((dataItem: any) => {
|
||||
winterInflBod += dataItem.inflAssctBfrWqltBod
|
||||
? Number(dataItem.inflAssctBfrWqltBod)
|
||||
: 0;
|
||||
if(summerMonth.includes(item2.msrDt.toString().replaceAll('-','').substring(4,6))){
|
||||
if(Number(item2.infoRnDay)>=3){
|
||||
const inflBod = Number(item2.inflAssctBfrWqltBod);
|
||||
const infl = Number(item2.inflAmnt);
|
||||
const rain = Number(item2.infoRnDay);
|
||||
if(inflBod < minSummerBod){
|
||||
minSummerBodInfl = infl;
|
||||
minSummerBod = inflBod;
|
||||
rdiRain = rain;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (rtnWqltWinterData.length > 0) {
|
||||
winterInflBod = winterInflBod / rtnWqltWinterData.length;
|
||||
}
|
||||
wqltDataSunny.filter(item=>winterMonth.includes(item.msrDt.toString().replaceAll('-','').substring(4,6))).forEach(item2 => {
|
||||
winterBodSunny += Number(item2.inflAssctBfrWqltBod);
|
||||
winterCnt += 1;
|
||||
});
|
||||
|
||||
minSummerBod = minSummerBod === 99999999 ? 0 : minSummerBod;
|
||||
minSummerBodInfl = minSummerBodInfl === 99999999 ? 0 : minSummerBodInfl;
|
||||
|
||||
const roundMinSummerBodInfl = Number(roundNumber(minSummerBodInfl, 0).toString().replaceAll(',',''));
|
||||
const roundMinSummerBod = Number(roundNumber(minSummerBod, 1).toString().replaceAll(',',''));
|
||||
const roundWinterBodSunny = Number(roundNumber(winterBodSunny, 1).toString().replaceAll(',',''));
|
||||
|
||||
console.log('bsccd : ', item.bscFctCd);
|
||||
console.log('roundMinSummerBodInfl : ',roundMinSummerBodInfl);
|
||||
console.log('roundMinSummerBod : ',roundMinSummerBod);
|
||||
console.log('roundWinterBodSunny : ',roundWinterBodSunny);
|
||||
|
||||
const winterBodAvg = Number(roundNumber((roundWinterBodSunny / winterCnt), 1).toString().replaceAll(',',''));
|
||||
// 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD))
|
||||
const winMinusSum = winterBodAvg - roundMinSummerBod;
|
||||
|
||||
const rdiValue = winMinusSum===0 ? 0 : roundMinSummerBodInfl * (winMinusSum / winterBodAvg );
|
||||
|
||||
rtnWinterInflBod = winterBodAvg;
|
||||
rtnSummerBodInfl = minSummerBodInfl;
|
||||
rtnSummerBod = minSummerBod;
|
||||
rtnRdiValue = rdiValue;
|
||||
rtnRdiRain = rdiRain;
|
||||
chungchunFlow = chungchunInfl == 0? 0 : chungchunInfl / chungchunCnt;
|
||||
}
|
||||
|
||||
item.winterAvgBodLowRainfall = winterInflBod;
|
||||
item.summerMinBodValue = roundNumber(rtnSummerBod,1);
|
||||
item.inflAmnt = roundNumber(rtnSummerBodInfl.toString(), 0);
|
||||
item.winterAvgBodLowRainfall = roundNumber(rtnWinterInflBod, 1);
|
||||
item.rdiiValue = roundNumber(rtnRdiValue, 0);
|
||||
item.infoRnDay = roundNumber(rtnRdiRain, 0);
|
||||
item.chungchunFlow = roundNumber(chungchunFlow, 0);
|
||||
item.rainCalInflAmnt = roundNumber(Number(item.chungchunFlow.toString().replaceAll(',','')) + Number(item.rdiiValue.toString().replaceAll(',','')), 0);
|
||||
item.properYn = Number(item.rainCalInflAmnt.toString().replaceAll(',','')) > Number(item.fctCpc.toString().replaceAll(',','')) ? '초과유입' : '적정';
|
||||
|
||||
}
|
||||
|
||||
rtnData.forEach((item: RdiProps) => {
|
||||
dataFormSetting(item)
|
||||
dataFormSetting(item);
|
||||
})
|
||||
|
||||
if(pageSize>5000){
|
||||
@@ -294,12 +386,15 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio
|
||||
시도: item.sido,
|
||||
시군구: item.sigungo,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc,
|
||||
하절기강우일최저유입BOD: item.summerMinBodValue,
|
||||
하절기최저유입BOD유입유량: item.inflAmnt,
|
||||
동절기청천시유입BOD: item.winterAvgBodLowRainfall,
|
||||
RDII추정 : item.rdiiValue,
|
||||
RDII추정시일강수량 : item.infoRnDay,
|
||||
"시설용량(m³/일)": item.fctCpc,
|
||||
"청천시유입하수량(m³/일)": item.chungchunFlow,
|
||||
"하절기강우일최저유입BOD(mg/L)": item.summerMinBodValue,
|
||||
"하절기최저유입BOD유입유량(m³/일)": item.inflAmnt,
|
||||
"동절기청천시유입BOD(mg/L)": item.winterAvgBodLowRainfall,
|
||||
"RDII추정": item.rdiiValue,
|
||||
"RDII추정시일강수량(mm)": item.infoRnDay,
|
||||
"강우시총추정유입량(m³/일)": item.rainCalInflAmnt,
|
||||
적정여부: item.properYn,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
|
||||
import { OSU_PERCENT } from "../common";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
@@ -50,61 +52,61 @@ export interface ExcelType {
|
||||
시군구: string,
|
||||
시설명: string,
|
||||
주소: string,
|
||||
시설용량: number,
|
||||
물사용량: number | '',
|
||||
오수전환율: number | '',
|
||||
오수발생량추정: number | '',
|
||||
연간하수유입량: number | '',
|
||||
청천시하수유입량: number | '',
|
||||
"시설용량(m³/일)": number,
|
||||
"물사용량(m³/일)": number | '',
|
||||
"오수전환율(%)": number | '',
|
||||
"오수발생량추정(m³/일)": number | '',
|
||||
"연간하수유입량(m³/일)": number | '',
|
||||
"청천시하수유입량(m³/일)": number | '',
|
||||
}
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "A", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sidoNm", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "sidoNm", title: "시도", row:1, widthPercent: 8 },
|
||||
{ id: "sggNm", title: "시군구", row:1, widthPercent: 8 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "waterUsage", title: "물사용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "swageChangePercent", title: "오수전환율\n(%)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "estimationSewage", title: "오수발생량 추정\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "sewageInputYear", title: "연간 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ 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: "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: "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 },
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "rvbsn", title: "권역", row:1, widthPercent: 6 },
|
||||
{ id: "lgbsn", title: "단위유역", row:1, widthPercent: 6 },
|
||||
{ id: "mdmbsn", title: "중권역", row:1, widthPercent: 6 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "waterUsage", title: "물사용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "swageChangePercent", title: "오수전환율", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "estimationSewage", title: "오수발생량 추정\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "sewageInputYear", title: "연간 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ 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: "swageChangePercent", title: "오수전환율", 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: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "rvbsn", title: "권역", row:1, widthPercent: 5 },
|
||||
{ id: "lgbsn", title: "단위유역", row:1, widthPercent: 5 },
|
||||
{ id: "mdmbsn", title: "중권역", row:1, widthPercent: 5 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2, widthPercent: 8 },
|
||||
{ id: "B", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sidoNm", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "sidoNm", title: "시도", row:1, widthPercent: 6 },
|
||||
{ id: "sggNm", title: "시군구", row:1, widthPercent: 6 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "waterUsage", title: "물사용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "swageChangePercent", title: "오수전환율", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "estimationSewage", title: "오수발생량 추정\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "sewageInputYear", title: "연간 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ 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: "swageChangePercent", title: "오수전환율", 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: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 6 },
|
||||
];
|
||||
|
||||
const upHeadListSewageOccurDetail:TableUpperProps[] = [
|
||||
@@ -236,47 +238,9 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
||||
let totWaterUsage = 0;
|
||||
|
||||
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
|
||||
for(let idx = 0; idx < res2.data.length; idx++) {
|
||||
const item = res2.data[idx];
|
||||
if(item){
|
||||
if(item.infoRnDay && Number(item.infoRnDay.toString().trim()) >= 3) {
|
||||
item.rainEffectDay = 1;
|
||||
} else {
|
||||
item.rainEffectDay = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정
|
||||
for(let idx = 0; idx < res2.data.length; idx++) {
|
||||
if(res2.data[idx]) {
|
||||
// 하루 전이 강우영향일(3 이상)인 경우
|
||||
if(idx > 0 && res2.data[idx-1]?.infoRnDay && Number(res2.data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
|
||||
res2.data[idx]!.rainEffectDay = 1;
|
||||
}
|
||||
// 이틀 전이 강우영향일(3 이상)인 경우
|
||||
if(idx > 1 && res2.data[idx-2]?.infoRnDay && Number(res2.data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
|
||||
res2.data[idx]!.rainEffectDay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(let idx = 0; idx < res2.data.length; idx++) {
|
||||
if(res2.data[idx] && res2.data[idx]?.rainEffectDay === 1) {
|
||||
if(idx > 1){
|
||||
if(res2.data[idx-1]?.infoRnDay && Number(res2.data[idx]?.infoRnDay) < 3 && Number(res2.data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
|
||||
res2.data[idx]!.infoRnDay = res2.data[idx-1]!.infoRnDay;
|
||||
}
|
||||
}
|
||||
if(idx > 2){
|
||||
if(res2.data[idx-2]?.infoRnDay && Number(res2.data[idx]?.infoRnDay) < 3 && Number(res2.data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
|
||||
res2.data[idx]!.infoRnDay = res2.data[idx-2]!.infoRnDay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const rainEffectData = CalcRainEffect(res2.data);
|
||||
|
||||
res2.data.forEach((item: FlowDataItem) => {
|
||||
rainEffectData.forEach((item: FlowDataItem) => {
|
||||
|
||||
if(Number(item.rainEffectDay) === 0){
|
||||
chungcunSumFlow += Number(item.inflAmnt);
|
||||
@@ -314,12 +278,12 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
||||
시도: item.sidoNm,
|
||||
시군구: item.sggNm,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc,
|
||||
물사용량: item.waterUsage,
|
||||
오수전환율: item.swageChangePercent,
|
||||
오수발생량추정: item.estimationSewage,
|
||||
연간하수유입량 : item.sewageInputYear,
|
||||
청천시하수유입량 : item.sewageInputChungchun,
|
||||
"시설용량(m³/일)": item.fctCpc,
|
||||
"물사용량(m³/일)": item.waterUsage,
|
||||
"오수전환율(%)": item.swageChangePercent,
|
||||
"오수발생량추정(m³/일)": item.estimationSewage,
|
||||
"연간하수유입량(m³/일)": item.sewageInputYear,
|
||||
"청천시하수유입량(m³/일)": item.sewageInputChungchun,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -382,8 +346,8 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
|
||||
tableData.push({
|
||||
msrDt: item.yr+'-'+(index+1>=10?String(index+1):'0'+(index+1)),
|
||||
waterUsage: Math.round(item.usege*1) /1,
|
||||
swageChangePercent: (Math.round((item.usege/item.usege*0.9) * 100) / 100) * 100,
|
||||
estimationSewage: Math.round(item.usege*0.9 * 1) / 1
|
||||
swageChangePercent: (Math.round((item.usege/item.usege*OSU_PERCENT) * 100) / 100) * 100,
|
||||
estimationSewage: Math.round(item.usege*OSU_PERCENT * 1) / 1
|
||||
})
|
||||
if (item.usege > maxWaterUsage) {
|
||||
maxWaterUsage = item.usege;
|
||||
|
||||
@@ -2,6 +2,8 @@ import { getFetch } from "@/app/components/api";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import type { ExcelType, UnderWaterInputModalProps, UnderWaterProps } from "./types";
|
||||
import CalcRainEffect from "@/app/components/common/CalcRainEffect";
|
||||
import { OSU_PERCENT } from "../common";
|
||||
export type { TableUpperProps };
|
||||
|
||||
// SewageOccurDetailProps 타입을 여기에 정의
|
||||
@@ -33,47 +35,53 @@ const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "A", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sidoNm", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "sidoNm", title: "시도", row:1, widthPercent: 8 },
|
||||
{ id: "sggNm", title: "시군구", row:1, widthPercent: 8 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
||||
{ id: "inflAmnt", title: "연평균유입하수량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 10 },
|
||||
{ id: "C", title: "지하수 유입량 추정", align:"right", row:0, colSpan:3 },
|
||||
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1, widthPercent: 8 },
|
||||
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1, widthPercent: 8 },
|
||||
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1, widthPercent: 8 },
|
||||
{ id: "properYn", title: "적정여부", row:0, rowSpan:2, widthPercent: 8 },
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "rvbsn", title: "권역", row:1, widthPercent: 5 },
|
||||
{ id: "lgbsn", title: "단위유역", row:1, widthPercent: 5 },
|
||||
{ id: "mdmbsn", title: "중권역", row:1, widthPercent: 5 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 8 },
|
||||
{ id: "inflAmnt", title: "연평균유입하수량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 10 },
|
||||
{ id: "C", title: "지하수 유입량 추정", align:"right", row:0, colSpan:3 },
|
||||
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1, widthPercent: 8 },
|
||||
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1, widthPercent: 8 },
|
||||
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1, widthPercent: 8 },
|
||||
{ id: "properYn", title: "적정여부", row:0, rowSpan:2, widthPercent: 8 },
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1, widthPercent: 5 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1, widthPercent: 5 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1, widthPercent: 5 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2, widthPercent: 8 },
|
||||
{ id: "B", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sidoNm", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "sidoNm", title: "시도", row:1, widthPercent: 6 },
|
||||
{ id: "sggNm", title: "시군구", row:1, widthPercent: 6 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2, widthPercent: 8 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 6 },
|
||||
{ id: "inflAmnt", title: "연평균유입하수량(m³/일)", align:"right", row:0, rowSpan:2, widthPercent: 10 },
|
||||
{ id: "C", title: "지하수 유입량 추정", align:"right", row:0, colSpan:3 },
|
||||
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1, widthPercent: 6},
|
||||
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1, widthPercent: 6 },
|
||||
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1, widthPercent: 6 },
|
||||
{ id: "properYn", title: "적정여부", row:0, rowSpan:2, widthPercent: 6 },
|
||||
];
|
||||
|
||||
// 모달
|
||||
@@ -251,6 +259,7 @@ export const underWaterInitState: UnderWaterType = {
|
||||
|
||||
const dataFormSetting=(item : UnderWaterProps)=> {
|
||||
DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float0', column: 'inflAmnt', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float0', column: 'underWaterInputYear', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float0', column: 'underWaterInputSummer', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float0', column: 'underWaterInputWinter', item: item as unknown as Record<string, unknown>});
|
||||
@@ -258,65 +267,6 @@ const dataFormSetting=(item : UnderWaterProps)=> {
|
||||
|
||||
export type UnderWaterStore = UnderWaterType & UnderWaterActions;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param data
|
||||
* @param weather ('ALL' | 'SUNNY' | 'RAINY')
|
||||
* @returns
|
||||
*/
|
||||
export const calRainEffectDay = (data: any, weather: string) => {
|
||||
// 강우영향일 계산 (강우량이 3 이상이면 무조건 강우영향일)
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
const item = data[idx];
|
||||
if(item){
|
||||
if(item.infoRnDay && Number(item.infoRnDay.toString().trim()) >= 3) {
|
||||
item.rainEffectDay = 1;
|
||||
} else {
|
||||
item.rainEffectDay = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
if(data[idx]) {
|
||||
// 하루 전이 강우영향일(3 이상)인 경우
|
||||
if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
|
||||
data[idx]!.rainEffectDay = 1;
|
||||
}
|
||||
// 이틀 전이 강우영향일(3 이상)인 경우
|
||||
if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
|
||||
data[idx]!.rainEffectDay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
if(data[idx] && data[idx]?.rainEffectDay === 1) {
|
||||
if(idx > 1){
|
||||
if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
|
||||
data[idx]!.infoRnDay = data[idx-1]!.infoRnDay;
|
||||
}
|
||||
}
|
||||
if(idx > 2){
|
||||
if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
|
||||
data[idx]!.infoRnDay = data[idx-2]!.infoRnDay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let rtnData : FlowDataItem[] = [];
|
||||
if (weather === 'ALL') {
|
||||
rtnData = data;
|
||||
} else if (weather === 'SUNNY') {
|
||||
rtnData = data.filter((item: FlowDataItem) => item.rainEffectDay === 0);
|
||||
} else {
|
||||
rtnData = data.filter((item: FlowDataItem) => item.rainEffectDay === 1);
|
||||
}
|
||||
return rtnData;
|
||||
}
|
||||
|
||||
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) => {
|
||||
@@ -337,7 +287,8 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
|
||||
|
||||
const bscFctCd = item.bscFctCd;
|
||||
const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as ApiResponse;
|
||||
const calData = calRainEffectDay(res2.data, 'SUNNY');
|
||||
const calData = CalcRainEffect(res2.data, 'SUNNY');
|
||||
|
||||
let chungcunSumFlow = 0;
|
||||
|
||||
let sumSummerChungcunDay = 0;
|
||||
@@ -357,20 +308,19 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
|
||||
sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
|
||||
}
|
||||
});
|
||||
|
||||
const usage = chungcunSumFlow / calData.length;
|
||||
const summerUsage = sumSummerChungcunFlow / sumSummerChungcunDay;
|
||||
const winterUsage = sumWinterChungcunFlow / sumWinterChungcunDay;
|
||||
const usage = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / calData.length:0;
|
||||
const summerUsage = sumSummerChungcunFlow?sumSummerChungcunFlow / sumSummerChungcunDay:0;
|
||||
const winterUsage = sumWinterChungcunFlow?sumWinterChungcunFlow / sumWinterChungcunDay:0;
|
||||
|
||||
if(bscFctCd === '11200PB001R') {
|
||||
//bscFctCd === '11200PB001R') 중랑 - 테스트할 때 코드넣고 해야 보기편해요~
|
||||
/* if(bscFctCd === '11200PB001R') {
|
||||
console.log('calData.length : ', calData.length);
|
||||
console.log('usage : ', usage, 'summerUsage : ', summerUsage, 'winterUsage : ', winterUsage);
|
||||
}
|
||||
|
||||
item.underWaterInputYear = Math.round((usage-(usage*0.65*0.9)) * 1) / 1;
|
||||
item.underWaterInputSummer = Math.round((summerUsage-(summerUsage*0.65*0.9)) * 1) / 1;
|
||||
item.underWaterInputWinter = Math.round((winterUsage-(winterUsage*0.65*0.9)) * 1) / 1;
|
||||
|
||||
} */
|
||||
item.underWaterInputYear = Math.round((usage-(usage*0.65*OSU_PERCENT)) * 1) / 1;
|
||||
item.underWaterInputSummer = Math.round((summerUsage-(summerUsage*0.65*OSU_PERCENT)) * 1) / 1;
|
||||
item.underWaterInputWinter = Math.round((winterUsage-(winterUsage*0.65*OSU_PERCENT)) * 1) / 1;
|
||||
item.properYn = Math.round( (Number(usage-(usage*0.65*OSU_PERCENT)) / Number(item.inflAmnt)) * 100 * 1 ) / 1 > 20?'초과유입':'적정';
|
||||
return item;
|
||||
}));
|
||||
|
||||
@@ -391,11 +341,12 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
|
||||
시군구: item.sggNm,
|
||||
시설명: item.bscFctNm,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc,
|
||||
연간지하수유입량: item.underWaterInputYear,
|
||||
하절기지하수유입량: item.underWaterInputSummer,
|
||||
동절기지하수유입량: item.underWaterInputWinter,
|
||||
|
||||
"시설용량(m³/일)": item.fctCpc,
|
||||
"평균유입하수량(m³/일)": item.inflAmnt,
|
||||
"연간지하수유입량(m³/일)": item.underWaterInputYear,
|
||||
"하절기지하수유입량(m³/일)": item.underWaterInputSummer,
|
||||
"동절기지하수유입량(m³/일)": item.underWaterInputWinter,
|
||||
적정여부: item.properYn,
|
||||
});
|
||||
});
|
||||
}else{
|
||||
@@ -425,7 +376,7 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
|
||||
const res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear);
|
||||
const monthData: SewageOccurDetailProps[] = [];
|
||||
|
||||
const calData = calRainEffectDay(res.data, 'SUNNY');
|
||||
const calData = CalcRainEffect(res.data, 'SUNNY');
|
||||
let tot = 0;
|
||||
let cnt = 0;
|
||||
|
||||
@@ -456,8 +407,8 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
|
||||
tableData.push({
|
||||
msrDt: item.yr+'-'+(index+1>=10?String(index+1):'0'+(index+1)),
|
||||
realSewageInput:Math.round(item.usege*1) /1,
|
||||
sewageOccur:Math.round(item.usege*0.65*0.9 * 1) / 1,
|
||||
underWaterInput:Math.round((item.usege-(item.usege*0.65*0.9)) * 1) / 1,
|
||||
sewageOccur:Math.round(item.usege*0.65*OSU_PERCENT * 1) / 1,
|
||||
underWaterInput:Math.round((item.usege-(item.usege*0.65*OSU_PERCENT)) * 1) / 1,
|
||||
})
|
||||
if (item.usege > maxWaterUsage) {
|
||||
maxWaterUsage = item.usege;
|
||||
@@ -468,28 +419,33 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
|
||||
}
|
||||
|
||||
});
|
||||
console.log('tot', tot, 'calData.length', calData.length);
|
||||
|
||||
if(monthData.length == 0){
|
||||
maxWaterUsage = 0;
|
||||
avgWaterUsage = 0;
|
||||
minWaterUsage = 0;
|
||||
}
|
||||
|
||||
avgWaterUsage = tot/cnt;
|
||||
console.log(avgWaterUsage);
|
||||
const newData= [
|
||||
{
|
||||
msrDt: '평균',
|
||||
realSewageInput:Math.round(avgWaterUsage*1) /1,
|
||||
sewageOccur:Math.round(avgWaterUsage*0.65*0.9 * 1) / 1,
|
||||
underWaterInput: Math.round((avgWaterUsage-(avgWaterUsage*0.65*0.9)) * 1) / 1
|
||||
sewageOccur:Math.round(avgWaterUsage*0.65*OSU_PERCENT * 1) / 1,
|
||||
underWaterInput: Math.round((avgWaterUsage-(avgWaterUsage*0.65*OSU_PERCENT)) * 1) / 1
|
||||
//underWaterInput:Math.round((avgWaterUsage-(avgWaterUsage*0.65*0.8)) * 100) / 100,
|
||||
},
|
||||
{
|
||||
msrDt: '최대',
|
||||
realSewageInput: Math.round(maxWaterUsage*1) /1,
|
||||
sewageOccur: Math.round(maxWaterUsage*0.65*0.9 * 1) / 1,
|
||||
underWaterInput: Math.round((maxWaterUsage-(maxWaterUsage*0.65*0.9)) * 1) / 1,
|
||||
sewageOccur: Math.round(maxWaterUsage*0.65*OSU_PERCENT * 1) / 1,
|
||||
underWaterInput: Math.round((maxWaterUsage-(maxWaterUsage*0.65*OSU_PERCENT)) * 1) / 1,
|
||||
},
|
||||
{
|
||||
msrDt: '최소',
|
||||
realSewageInput: Math.round(minWaterUsage*1) /1,
|
||||
sewageOccur: Math.round(minWaterUsage*0.65*0.9 * 1) / 1,
|
||||
underWaterInput: Math.round((minWaterUsage-(minWaterUsage*0.65*0.9)) * 1) / 1,
|
||||
sewageOccur: Math.round(minWaterUsage*0.65*OSU_PERCENT * 1) / 1,
|
||||
underWaterInput: Math.round((minWaterUsage-(minWaterUsage*0.65*OSU_PERCENT)) * 1) / 1,
|
||||
},
|
||||
...tableData
|
||||
]
|
||||
|
||||
@@ -14,6 +14,8 @@ export type UnderWaterProps = {
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
inflAmnt : number | '',
|
||||
properYn : string | '',
|
||||
}
|
||||
export interface UnderWaterInterface {
|
||||
bscFctCd : string,
|
||||
@@ -30,6 +32,8 @@ export interface UnderWaterInterface {
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
inflAmnt : number | '',
|
||||
properYn : string | '',
|
||||
}
|
||||
|
||||
// 모달
|
||||
@@ -51,8 +55,10 @@ export interface ExcelType {
|
||||
시군구: string,
|
||||
시설명: string,
|
||||
주소: string,
|
||||
시설용량: number,
|
||||
연간지하수유입량: number | '',
|
||||
하절기지하수유입량: number | '',
|
||||
동절기지하수유입량: number | '',
|
||||
"시설용량(m³/일)": number,
|
||||
"평균유입하수량(m³/일)": number | '',
|
||||
"연간지하수유입량(m³/일)": number | '',
|
||||
"하절기지하수유입량(m³/일)": number | '',
|
||||
"동절기지하수유입량(m³/일)": number | '',
|
||||
적정여부: string | '',
|
||||
}
|
||||
+43
-6
@@ -6,7 +6,7 @@ const CLAIM_NAME = process.env.NEXT_PUBLIC_CLAIM_NAME || "Authorization";
|
||||
const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || "";
|
||||
const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || "";
|
||||
const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
|
||||
|
||||
const serverApiUrl = SERVER_API_CS_URL;
|
||||
export function middleware(req: NextRequest) {
|
||||
console.log("Middleware 진입:", req.nextUrl.pathname);
|
||||
const pathname = req.nextUrl.pathname;
|
||||
@@ -14,7 +14,7 @@ export function middleware(req: NextRequest) {
|
||||
|
||||
if (pathname.startsWith("/server")) {
|
||||
const queryParams = searchParams.toString();
|
||||
const newUrl = `${SERVER_API_CS_URL}${pathname.replace("/server", "")}${
|
||||
const newUrl = `${serverApiUrl}${pathname.replace("/server", "")}${
|
||||
queryParams ? `?${queryParams}` : ""
|
||||
}`;
|
||||
console.log(`[Middleware] Rewriting from '/server' path to: ${newUrl}`);
|
||||
@@ -76,13 +76,47 @@ export function middleware(req: NextRequest) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const token = req.cookies.get(CLAIM_NAME)?.value;
|
||||
const userId = req.cookies.get(AUTH_USER_ID)?.value;
|
||||
const newUrl = `${SERVER_API_CS_URL}${pathname}`;
|
||||
const newUrl = `${serverApiUrl}${pathname}`;
|
||||
|
||||
if (token) requestHeaders.set(CLAIM_NAME, token);
|
||||
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
|
||||
|
||||
console.log(
|
||||
`[Middleware] Rewriting from '/attach-service' path to: ${newUrl}`,
|
||||
`[Middleware] Rewriting from '/attach-service' path to: ${newUrl}`
|
||||
);
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders,
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/operation-service")) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const token = req.cookies.get(CLAIM_NAME)?.value;
|
||||
const userId = req.cookies.get(AUTH_USER_ID)?.value;
|
||||
const newUrl = `${serverApiUrl}${pathname}`;
|
||||
|
||||
if (token) requestHeaders.set(CLAIM_NAME, token);
|
||||
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
|
||||
|
||||
console.log(
|
||||
`[Middleware] Rewriting from '/operation-service' path to: ${newUrl}`
|
||||
);
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders,
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/reuse-service")) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const token = req.cookies.get(CLAIM_NAME)?.value;
|
||||
const userId = req.cookies.get(AUTH_USER_ID)?.value;
|
||||
const newUrl = `${serverApiUrl}${pathname}`;
|
||||
|
||||
if (token) requestHeaders.set(CLAIM_NAME, token);
|
||||
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
|
||||
|
||||
console.log(
|
||||
`[Middleware] Rewriting from '/reuse-service' path to: ${newUrl}`
|
||||
);
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders,
|
||||
@@ -94,12 +128,13 @@ export function middleware(req: NextRequest) {
|
||||
const newUrl = `${SERVER_API_CS_URL}${pathname}`;
|
||||
|
||||
console.log(
|
||||
`[Middleware] Rewriting from '/user-service' path to: ${newUrl}`,
|
||||
`[Middleware] Rewriting from '/user-service' path to: ${newUrl}`
|
||||
);
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders,
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname === "/") {
|
||||
return NextResponse.redirect(new URL("/pages/dashboard", req.url));
|
||||
}
|
||||
@@ -108,11 +143,13 @@ export function middleware(req: NextRequest) {
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
"/",
|
||||
"/server/:path*",
|
||||
"/geoserver/:path*",
|
||||
"/attach-service/:path*",
|
||||
"/user-service/:path*",
|
||||
"/cms-service/:path*",
|
||||
"/"
|
||||
"/operation-service/:path*",
|
||||
"/reuse-service/:path*",
|
||||
],
|
||||
};
|
||||
|
||||
Binary file not shown.
@@ -8,6 +8,7 @@ NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11302
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||
NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver
|
||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
|
||||
NEXT_PUBLIC_DC_URL = https://apigateway.apps.rsonesoft.com
|
||||
NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api
|
||||
NEXT_PUBLIC_DC_URL = https://apigateway.apps.rsonesoft.com
|
||||
NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://dev.onasys.co.kr:3000/auth/login
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083
|
||||
+9
-7
@@ -4,13 +4,15 @@ NEXT_PUBLIC_AUTH_USER_ID = token-id
|
||||
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||
NEXT_PUBLIC_PORT = 3002
|
||||
NEXT_PUBLIC_PROXY_HOST = http://localhost:3002
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||
# NEXT_PUBLIC_PROXY_HOST = http://localhost:3002
|
||||
NEXT_PUBLIC_PROXY_HOST = http://sn.onasys.co.kr:3002
|
||||
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_DC_URL = https://apigateway.apps.rsonesoft.com
|
||||
NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api
|
||||
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api
|
||||
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.222:8883/sewerage-service/api
|
||||
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883/sewerage-service/api
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083
|
||||
NEXT_PUBLIC_DC_URL = https://apigateway.apps.rsonesoft.com
|
||||
NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://dev.onasys.co.kr:3000/auth/login
|
||||
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883
|
||||
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.222:8883
|
||||
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883
|
||||
@@ -4,10 +4,11 @@ NEXT_PUBLIC_AUTH_USER_ID = token-id
|
||||
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||
NEXT_PUBLIC_PORT = 3000
|
||||
NEXT_PUBLIC_PROXY_HOST = https://sn.hasuon.or.kr
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000
|
||||
NEXT_PUBLIC_PROXY_HOST = https://lion.hasuon.or.kr
|
||||
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_DC_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000
|
||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl
|
||||
NEXT_PUBLIC_NGII_URL = http://10.98.25.94:18080/openapi/Gettile.do?apiKey=BDE2BEF39DAFEC293AB6730150F222AC
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL = https://apigateway.hasuon.or.kr/sewerage-service/api
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
|
||||
NEXT_PUBLIC_DC_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
|
||||
NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://dev.onasys.co.kr:3000/auth/login
|
||||
@@ -0,0 +1,14 @@
|
||||
NEXT_PUBLIC_SITE_ID = SN
|
||||
NEXT_PUBLIC_CLAIM_NAME = Authorization
|
||||
NEXT_PUBLIC_AUTH_USER_ID = token-id
|
||||
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||
NEXT_PUBLIC_PORT = 3000
|
||||
NEXT_PUBLIC_PROXY_HOST = https://sn.hasuon.or.kr
|
||||
NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver
|
||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl
|
||||
NEXT_PUBLIC_NGII_URL = http://10.98.25.94:18080/openapi/Gettile.do?apiKey=BDE2BEF39DAFEC293AB6730150F222AC
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
|
||||
NEXT_PUBLIC_DC_URL = http://apigateway.iipbs-was.svc.cluster.local:8000
|
||||
NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://dev.onasys.co.kr:3000/auth/login
|
||||
@@ -1,3 +1,16 @@
|
||||
/**
|
||||
* ➡️ 경로 : 하수관망도 모든 페이지
|
||||
*
|
||||
* 📄 Map Layout
|
||||
* Next.js App Router (app/) 기반 맵 레이아웃 컴포넌트
|
||||
*
|
||||
* - 메뉴 클릭 이벤트 처리 및 라우팅
|
||||
* - 현재 메뉴 정보 Zustand를 통한 상태 관리
|
||||
* - 시도/시군구/사업 구분/사업 유형 데이터 초기 로드
|
||||
* - NoFooterLayout을 통한 공통 레이아웃 적용
|
||||
* - QueryClient를 통한 데이터 캐싱 및 관리
|
||||
* - 경로 변경 시 메뉴 정보 동기화
|
||||
*/
|
||||
"use client";
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
/**
|
||||
* ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 (하수관로)
|
||||
*
|
||||
* 📄 MsSwagePpl
|
||||
* 하수관로 정보 컴포넌트
|
||||
*
|
||||
* - 하수관로의 자체입력정보 표시 및 편집 기능
|
||||
* - 보수 및 갱신, 청소 및 준설, 점검 및 진단 데이터 조회 및 표시
|
||||
* - VerticalTable을 통한 입력 폼 렌더링
|
||||
* - InputSection을 통한 운영 데이터 관리
|
||||
* - 저장 버튼을 통한 데이터 저장 기능
|
||||
*
|
||||
* 🔗 사용 API
|
||||
* - 시설별 운영 정보 조회: GET /api/v1/bizInfo/bizByFclt (sewerage-service)
|
||||
*/
|
||||
'use client'
|
||||
import { VerticalTable } from '@/components/ui/verticalTable';
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import InputSection from '../InputSection';
|
||||
import { handleInputChange } from '../common';
|
||||
import { getData } from "@/components/lib/api";
|
||||
import useStore from '../../../../store/useStore';
|
||||
import useStore from '@/store/useStore';
|
||||
|
||||
// 하수관로
|
||||
const inputColumn = [
|
||||
@@ -88,9 +103,6 @@ const MsSwagePpl = ({ featureData, onSaveClick }: { featureData: any, onSaveClic
|
||||
setInspectionData(inspectionArr);
|
||||
setCleaningData(cleaningArr);
|
||||
setRepairData(repairArr);
|
||||
console.log('inspectionArr', inspectionArr);
|
||||
console.log('cleaningArr', cleaningArr);
|
||||
console.log('repairArr', repairArr);
|
||||
};
|
||||
fetchAll();
|
||||
}, [featureData]);
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
// 우수토실
|
||||
/**
|
||||
* ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 (우수토실)
|
||||
*
|
||||
* 📄 Ssc
|
||||
* 우수토실 정보 컴포넌트
|
||||
*
|
||||
* - 우수토실의 자체입력정보 표시 및 편집 기능
|
||||
* - 중점우수토실 운영정보 모달 표시 (강우/측정 정보, 수량/수질측정 정보)
|
||||
* - VerticalTable을 통한 입력 폼 렌더링
|
||||
* - 저장 버튼을 통한 데이터 저장 기능
|
||||
*
|
||||
* 🔗 사용 API
|
||||
* - 위경도로 강우시 미처리 하수 목록 조회: GET /api/v1/onsemiro/getSwgRainsByGeomety (sewerage-service)
|
||||
* - 강우시 월류 하수 관리 모니터링 조회: GET /api/v1/onsemiro/swgRain/{adstDstrCd}/{manageNo}/mntrngs (sewerage-service)
|
||||
*/
|
||||
import { UiModal, UiTable } from '@common/business_components/ui';
|
||||
import { Button, TableHead, TableRow } from '@common/components/ui';
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { untrtSwgRainCol3, untrtSwgRainCol4, untrtSwgRainCol5 } from '../common/table';
|
||||
import { VerticalTable } from '@/components/ui/verticalTable';
|
||||
import { getData } from "@/components/lib/api";
|
||||
@@ -34,8 +48,6 @@ const Ssc = ({ featureData, isMainSsc, chmbrXcnts, chmbrYdnts, onSaveClick }: {
|
||||
const [isResetDetailPage, setIsResetDetailPage] = useState<boolean>(true);
|
||||
const [isResetSelection, setIsResetSelection] = useState<boolean>(false);
|
||||
|
||||
console.log('featureData', featureData);
|
||||
|
||||
// 강우, 측정 정보 API 호출 함수
|
||||
const fetchRainMeasureData = async (chmbrXcnts: string, chmbrYdnts: string) => {
|
||||
setIsResetDetailPage(true);
|
||||
@@ -53,13 +65,8 @@ const Ssc = ({ featureData, isMainSsc, chmbrXcnts, chmbrYdnts, onSaveClick }: {
|
||||
size: '3',
|
||||
});
|
||||
|
||||
console.log('queryParams', queryParams.toString());
|
||||
console.log(`추가 데이터 API 호출 시작: v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`);
|
||||
|
||||
const result = await getData(`v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`);
|
||||
|
||||
console.log('추가 데이터 API 호출 성공:', result);
|
||||
|
||||
const processedDataArray: any[] = result.content.map((data: any) => {
|
||||
// 🎯 formatDisplayData로 기본 포맷팅 적용
|
||||
const formattedItem = formatDisplayData(data);
|
||||
@@ -92,12 +99,8 @@ const Ssc = ({ featureData, isMainSsc, chmbrXcnts, chmbrYdnts, onSaveClick }: {
|
||||
size: '3',
|
||||
});
|
||||
|
||||
console.log(`SSC 추가 데이터 API 호출 시작: v1/onsemiro/swgRain/${adstDstrCd}/${manageNo}/mntrngs?${queryParams.toString()}`);
|
||||
|
||||
const result = await getData(`v1/onsemiro/swgRain/${adstDstrCd}/${manageNo}/mntrngs?${queryParams.toString()}`);
|
||||
|
||||
console.log('SSC 추가 데이터 API 호출 성공:', result);
|
||||
|
||||
// 각 아이템 전처리
|
||||
const processedDataArray = result.content.map((data: any) => {
|
||||
// 기본 포맷팅 적용
|
||||
@@ -107,8 +110,6 @@ const Ssc = ({ featureData, isMainSsc, chmbrXcnts, chmbrYdnts, onSaveClick }: {
|
||||
};
|
||||
});
|
||||
|
||||
console.log('processedDataArray', processedDataArray);
|
||||
|
||||
setMntrngsData(processedDataArray);
|
||||
setTotalDetailCount(result?.totalElements || 0);
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 (하수처리시설)
|
||||
*
|
||||
* 📄 SwtrmtFclt
|
||||
* 하수처리시설 정보 컴포넌트
|
||||
*
|
||||
* - 하수처리시설의 디지털 자료관 연계 정보 표시
|
||||
* - VerticalTable을 통한 테이블 렌더링
|
||||
* - 조회 버튼을 통한 모달 표시 및 ReportTab 연동
|
||||
*/
|
||||
'use client'
|
||||
import React, { useState } from 'react'
|
||||
import { VerticalTable } from '@/components/ui/verticalTable';
|
||||
|
||||
@@ -84,7 +84,6 @@ const selectAplcnYms = async(gubun:string) => { // 상수사용월
|
||||
const queryString = '';
|
||||
const result = await getData(`v1/${gubun}/aplcnYm${queryString ? `?${queryString}` : ''}`);
|
||||
if (result && result.length > 0) {
|
||||
console.log("selectAplcnYms", result);
|
||||
return getOptionsAplcnYm(result);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -119,7 +118,6 @@ export const selectInftwtAnls = async(aplcnYm:string) => { // 침입수분석
|
||||
const queryString = aplcnYm ? `aplcnYmFrom=${aplcnYm}&aplcnYmTo=${aplcnYm}` : '';
|
||||
const result = await getData(`v1/inftwtAnls${queryString ? `?${queryString}` : ''}`);
|
||||
if (result && result.numberOfElements > 0) {
|
||||
console.log("selectInftwtAnls", result.content);
|
||||
return result.content;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -141,7 +139,6 @@ export const selectInftwtAnlsRslt = async(inftwtAnlsSn:number, pplMngNo:string)
|
||||
}
|
||||
const result = await getData(`v1/inftwtAnlsRslt/ppl/${inftwtAnlsSn}/${pplMngNo}`);
|
||||
if (result && result.numberOfElements > 0) {
|
||||
console.log("selectInftwtAnlsRslt", result.content);
|
||||
return result.content;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -163,7 +160,6 @@ export const selectOilq = async(inftwtAnlsSn:number, pplMngNo:string) => { //
|
||||
}
|
||||
const result = await getData(`v1/inftwtAnlsRslt/oilqPpl/${inftwtAnlsSn}/${pplMngNo}`);
|
||||
if (result && result.numberOfElements > 0) {
|
||||
console.log("selectOilq", result.content);
|
||||
return result.content;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -178,7 +174,6 @@ export const selectPplInftwtQty = async(inftwtAnlsSn:number, pplMngNo:string) =>
|
||||
}
|
||||
const result = await getData(`v1/inftwtAnlsRslt/pplInftwtQty/${inftwtAnlsSn}/${pplMngNo}`);
|
||||
if (result.length > 0) {
|
||||
console.log("selectPplInftwtQty", result);
|
||||
return result[0].avg_day_flow;
|
||||
} else {
|
||||
return 0; // 데이터가 없을 경우 0 반환
|
||||
@@ -196,7 +191,6 @@ export const selectPplRdiiQty = async(rainInfwtAnlsSn:number, pplMngNo:string) =
|
||||
}
|
||||
const result = await getData(`v1/rdiiAnlsRslt/pplRdiiQty/${rainInfwtAnlsSn}/${pplMngNo}`);
|
||||
if (result?.sustaintime > 0) {
|
||||
console.log("selectPplRdiiQty", result);
|
||||
return result;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -218,7 +212,6 @@ export const selectRdiiAnls = async(aplcnYm:string) => { // 침입수분석
|
||||
const queryString = aplcnYm ? `aplcnYmFrom=${aplcnYm}&aplcnYmTo=${aplcnYm}` : '';
|
||||
const result = await getData(`v1/rdiiAnls${queryString ? `?${queryString}` : ''}`);
|
||||
if (result && result.numberOfElements > 0) {
|
||||
console.log("selectRdiiAnls", result.content);
|
||||
return result.content;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -262,7 +255,6 @@ export const selectRainData = async(rainInfwtAnlsSn:number) => { // 강우데이
|
||||
}
|
||||
const result = await getData(`v1/rdiiAnlsRslt/rainData/${rainInfwtAnlsSn}`);
|
||||
if (result && result.numberOfElements > 0) {
|
||||
console.log("selectRainData", result.content);
|
||||
return result.content;
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -63,7 +63,6 @@ const InfilChart = ({ pplMngNo }: ModalOpenProp) => {
|
||||
// 상수사용월 변경 핸들러
|
||||
const handleAplcnYmChange = async (val: string | number) => {
|
||||
const selectedValue = String(val);
|
||||
console.log("선택된 상수사용월:", selectedValue);
|
||||
|
||||
setSelectedAplcnYm(selectedValue);
|
||||
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/**
|
||||
* ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창
|
||||
*
|
||||
* 📄 FeatureClickEventPopup
|
||||
* 시설물(피처) 클릭시 오른쪽 팝업창 컴포넌트
|
||||
*
|
||||
* - 지도 시설물(피처) 클릭 시 팝업 표시 및 데이터 로딩
|
||||
* - 레이어 유형에 따른 동적 테이블 및 헤드리스트 설정
|
||||
* - 자체입력정보 조회 및 저장 기능 (하수관로, 우수토실, 하수펌프장, 하수맨홀)
|
||||
* - 코드 매핑 및 데이터 포맷팅 처리
|
||||
* - 상류관로 검색, 침입수/RDII 분석 차트 표시
|
||||
* - 모달을 통한 저장 확인 및 API 연동
|
||||
*
|
||||
* 🔗 사용 API
|
||||
* - 하수관로 자체입력정보 조회: GET /api/v1/fcltppl/{fcltMngNo}/{mngInstCd} (sewerage-service)
|
||||
* - 우수토실 자체입력정보 조회: GET /api/v1/fcltstofcbr/{fcltMngNo}/{mngInstCd} (sewerage-service)
|
||||
* - 하수펌프장 자체입력정보 조회: GET /api/v1/fcltpump/{fcltMngNo}/{mngInstCd} (sewerage-service)
|
||||
* - 하수맨홀 자체입력정보 조회: GET /api/v1/fcltmhl/{fcltMngNo}/{mngInstCd} (sewerage-service)
|
||||
* - 하수관로 자체입력정보 저장: POST /api/v1/fcltppl (sewerage-service)
|
||||
* - 우수토실 자체입력정보 저장: POST /api/v1/fcltstofcbr (sewerage-service)
|
||||
* - 하수펌프장 자체입력정보 저장: POST /api/v1/fcltpump (sewerage-service)
|
||||
* - 하수맨홀 자체입력정보 저장: POST /api/v1/fcltmhl (sewerage-service)
|
||||
*/
|
||||
'use client'
|
||||
import { getData, postData } from "@/components/lib/api";
|
||||
import Modal from "@/components/ui/modal";
|
||||
@@ -75,7 +98,6 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
if (featureData['ol_uid']) {
|
||||
// Gis 레이어 클릭 이벤트
|
||||
setIsClicked(true);
|
||||
console.log('gis data', featureData.values_);
|
||||
const lyrTyNm = featureData.id_.split('.')[0];
|
||||
|
||||
switch (lyrTyNm) {
|
||||
@@ -139,7 +161,6 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
else {
|
||||
// SearchModal 클릭 이벤트
|
||||
setIsClicked(false);
|
||||
console.log('SearchModal data', featureData);
|
||||
const lyrTyNm = featureData.lyrTypeNm;
|
||||
|
||||
switch (lyrTyNm) {
|
||||
@@ -158,12 +179,10 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
case 'tb_ms_swage_pmstn': {
|
||||
const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장');
|
||||
if (drtwPumpCode && featureData.usgCd.trim() === drtwPumpCode.val) {
|
||||
console.log('오수펌프장');
|
||||
setIsDrtwSewagePump(false);
|
||||
setHeadlist(ExclnSewagePumpCol2)
|
||||
}
|
||||
else {
|
||||
console.log('빗물펌프장');
|
||||
setIsDrtwSewagePump(true);
|
||||
setHeadlist(DrtwSewagePumpCol2)
|
||||
}
|
||||
@@ -299,9 +318,6 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
const result = await getData(apiEndpoint);
|
||||
|
||||
if (result) {
|
||||
console.log('API 데이터 로드 성공:', result);
|
||||
|
||||
// ✅ codeMapper 사용하여 API 결과도 변환
|
||||
const processedApiData = codeMapper({
|
||||
layerName: selectedLayerName,
|
||||
data: { ...result, ...tableData }
|
||||
@@ -381,12 +397,9 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
bodyData.prrtymngYn = 'N';
|
||||
}
|
||||
}
|
||||
console.log('bodyData', bodyData);
|
||||
console.log('apiEndpoint', apiEndpoint);
|
||||
|
||||
try {
|
||||
result = await postData(apiEndpoint, bodyData);
|
||||
console.log('result', result);
|
||||
|
||||
if (result) {
|
||||
alert('저장되었습니다');
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 (하수펌프장)
|
||||
*
|
||||
* 📄 sewagePump
|
||||
* 하수펌프장 정보 컴포넌트
|
||||
*
|
||||
* - 빗물펌프장 및 오수펌프장 구분에 따른 자체 입력 정보 표시 및 편집 기능
|
||||
* - VerticalTable을 통한 입력 폼 렌더링
|
||||
* - 저장 버튼을 통한 데이터 저장 기능
|
||||
*/
|
||||
import { VerticalTable } from '@/components/ui/verticalTable';
|
||||
import React, { useState, useEffect } from 'react'
|
||||
// 빗물펌프장 자체 입력 정보
|
||||
@@ -12,7 +22,7 @@ const drtwInputColumn = [
|
||||
{ id: "mltvDtdvNm", title: "처리분구", type: "input" },
|
||||
]
|
||||
|
||||
// 하수펌프장
|
||||
|
||||
const sewagePump = ({ featureData, isDrtwSewagePump, onSaveClick }: { featureData: any, isDrtwSewagePump?: boolean, onSaveClick?: () => void }) => {
|
||||
const [formData, setFormData] = useState<any>({});
|
||||
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
// 하수맨홀
|
||||
/**
|
||||
* ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 (하수맨홀)
|
||||
*
|
||||
* 📄 Smh
|
||||
* 하수맨홀 정보 컴포넌트
|
||||
*
|
||||
* - 하수맨홀의 자체입력정보 표시 및 편집 기능
|
||||
* - VerticalTable을 통한 입력 폼 렌더링
|
||||
* - 상류관로 검색 및 지도 포커스 기능
|
||||
* - 저장 버튼을 통한 데이터 저장 기능
|
||||
*
|
||||
* 🔗 사용 API
|
||||
* - 상류관로 조회: GET /api/v1/fcltmhl/upperPpls/{fcltMngNo} (sewerage-service)
|
||||
*/
|
||||
import { VerticalTable } from '@/components/ui/verticalTable';
|
||||
import { useEffect, useState } from 'react';
|
||||
import GisApp from "@common/business_components/ui/map/lib/gis.core";
|
||||
|
||||
// 상류관로 보기 함수 (FeatureClickEventPopup에서 사용)
|
||||
export async function searchUpperPpls(gisMap: any, fcltMngNo: any) {
|
||||
const BASE_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
|
||||
const BASE_URL = "/sewerage-service/api";
|
||||
const res = await fetch(`${BASE_URL}/v1/fcltmhl/upperPpls/${fcltMngNo}`, {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
/**
|
||||
* ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 (빗물펌프)
|
||||
*
|
||||
* 📄 StormWaterPump
|
||||
* 빗물펌프 정보 컴포넌트
|
||||
*
|
||||
* - 빗물펌프의 자체입력정보 표시 및 편집 기능
|
||||
* - VerticalTable을 통한 입력 폼 렌더링
|
||||
*/
|
||||
import { VerticalTable } from '@/components/ui/verticalTable';
|
||||
import React from 'react'
|
||||
const inputColumn = [
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/**
|
||||
* ➡️ 경로 : 하수관망도 메인 페이지
|
||||
*
|
||||
* 📄 Map Page
|
||||
* 지도 페이지 컴포넌트
|
||||
*
|
||||
* - OpenLayers 기반 GIS 지도 렌더링 및 상호작용
|
||||
* - 레이어 트리 데이터 관리 및 동적 레이어 표시/숨김
|
||||
* - 피처 검색 및 선택 기능 (SearchModal, ProcSearchBar)
|
||||
* - 피처 클릭 이벤트 처리 및 상세 정보 팝업 표시
|
||||
* - 수심(WaterDepth) 레이어 애니메이션 재생 기능
|
||||
* - Zustand를 통한 검색 모달 상태 관리
|
||||
*
|
||||
* 🔗 사용 API
|
||||
* - 레이어 설정 조회: GET /api/v1/map/lyrStngs/{lyrGrp} (sewerage-service)
|
||||
*/
|
||||
|
||||
"use client";
|
||||
|
||||
import Gis from "@common/business_components/ui/map/Gis";
|
||||
@@ -8,37 +25,14 @@ import SearchModal from "./searchModal/searchModal";
|
||||
import FeatureClickEventPopup from "./components/popupComponent/featureClickEventPopup";
|
||||
import { WaterDepth, WATER_DEPTH_LAYER_TYPES } from "./waterDepth/waterDepth";
|
||||
import { ProcSearchBar } from "@common/business_components/ui/map/searchBar";
|
||||
|
||||
// 타입 정의 추가
|
||||
export type LyrStngProps = {
|
||||
lyr_sn: string;
|
||||
lyr_nm: string;
|
||||
upper_lyr_sn: string;
|
||||
drawOrdr: string;
|
||||
flterSql: string;
|
||||
gobjTy: string;
|
||||
lyrTpNm: string;
|
||||
useYn: string;
|
||||
minViewSize: string;
|
||||
iconNm: string;
|
||||
lblAtrbNm: string;
|
||||
fontNm: string;
|
||||
fontIntnColor: string;
|
||||
fontExtnColor: string;
|
||||
fontExtnWdth: string;
|
||||
lnWdth: string;
|
||||
lnColor: string;
|
||||
polgnColor: string;
|
||||
initEprssYn: string;
|
||||
clickPsblYn: string;
|
||||
};
|
||||
import useSearchModalStore from "@/store/useSearchModalStore";
|
||||
|
||||
const Map = () => {
|
||||
const { isSearchModalOpen, setIsSearchModalOpen } = useSearchModalStore();
|
||||
|
||||
const [treeData, setTreeData] = useState([]); // 초기값을 객체 또는 null로 설정
|
||||
const [selectedFeature, setSelectedFeature] = useState(null); // 선택된 피처 상태
|
||||
const gisMaps = useRef<any | null>(null);
|
||||
const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태
|
||||
const [isSearchModalOpen, setIsSearchModalOpen] = useState(false); // SearchModal 열림 상태
|
||||
const [featureData, setFeatureData] = useState(null); // 선택된 피쳐 데이터
|
||||
const [showWaterDepth, setShowWaterDepth] = useState(false); // WaterDepth 표시 여부
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
@@ -95,7 +89,6 @@ const Map = () => {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 3. 피처 선택
|
||||
if (foundFeature) {
|
||||
let geometry = foundFeature.getGeometry();
|
||||
@@ -148,12 +141,12 @@ const Map = () => {
|
||||
searchView={SearchModal}
|
||||
detailView={FeatureClickEventPopup}
|
||||
onFeatureSelect={onFeatureSelect}
|
||||
setIsOpen={setIsOpen}
|
||||
setFeatureData={setFeatureData}
|
||||
featureData={featureData}
|
||||
setIsSearchModalOpen={setIsSearchModalOpen}
|
||||
setFeatureData={setFeatureData}
|
||||
isOpen={isOpen}
|
||||
setIsOpen={setIsOpen}
|
||||
isSearchModalOpen={isSearchModalOpen}
|
||||
setIsSearchModalOpen={setIsSearchModalOpen}
|
||||
onCheckedLayersChange={handleCheckedLayersChange}
|
||||
searchBar={<ProcSearchBar gisMaps={gisMaps} facilityTypes={facilityTypes} />}
|
||||
waterDepth={showWaterDepth ? WaterDepth : undefined}
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
/**
|
||||
* ➡️ 경로 : 하수관망도 메인 페이지 (오른쪽 돋보기 모양 클릭) - 검색 모달 창 내 기본정보 탭
|
||||
*
|
||||
* 📄 BasicTab Component
|
||||
* Next.js App Router (app/) 기반 검색 모달의 기본정보 탭 컴포넌트
|
||||
*
|
||||
* - 기본정보 검색을 위한 구분 선택 및 조건 입력 UI 제공
|
||||
* - 하수관로, 하수처리시설, 하수처리구역, 하수맨홀, 하수펌프장, 우수토실 등 다양한 유형별 컴포넌트 렌더링
|
||||
* - useSearchModalStore를 통해 상태 관리 및 사용자 상호작용 처리
|
||||
*/
|
||||
import React from 'react';
|
||||
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
|
||||
import { SelectBox } from '@common/business_components/ui';
|
||||
import { Button, Label } from '@common/components';
|
||||
import { Label } from '@common/components';
|
||||
import SwagePpl from './swagePpl';
|
||||
import SwagePrcsFclt from './swagePrcsFclt';
|
||||
import SwagePrcsZone from './swagePrcsZone';
|
||||
import SwageMhl from './swageMhl';
|
||||
import SwagePmstn from './swagePmstn';
|
||||
import Stofcbr from './stofcbr';
|
||||
import { useSearchModal, type SearchModalProps } from './useSearchModal';
|
||||
import useSearchModalStore from '../../../store/useSearchModalStore';
|
||||
import useSearchModalStore from '@/store/useSearchModalStore';
|
||||
|
||||
|
||||
// 기본정보 '구분' 선택 목록
|
||||
@@ -22,7 +30,7 @@ export const BASIC_TYPES = [
|
||||
{ val: "tb_ms_stofcbr", text: "우수토실" },
|
||||
];
|
||||
|
||||
const BasicTab: React.FC<SearchModalProps> = (props) => {
|
||||
const BasicTab: React.FC = () => {
|
||||
const { basicType, setBasicType } = useSearchModalStore();
|
||||
|
||||
return (
|
||||
@@ -45,12 +53,12 @@ const BasicTab: React.FC<SearchModalProps> = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
{/* 조회 조건 */}
|
||||
{basicType === "tb_ms_swage_ppl" && (<SwagePpl {...props} />)} {/* 하수관로 */}
|
||||
{basicType === "tb_il_swage_prcs_fclt" && (<SwagePrcsFclt {...props} />)} {/* 하수처리시설 */}
|
||||
{basicType === "tb_ms_swage_prcs_zone" && (<SwagePrcsZone {...props} />)} {/* 하수처리구역 */}
|
||||
{basicType === "tb_ms_swage_mhl" && (<SwageMhl {...props} />)} {/* 하수맨홀 */}
|
||||
{basicType === "tb_ms_swage_pmstn" && (<SwagePmstn {...props} />)} {/* 하수펌프장 */}
|
||||
{basicType === "tb_ms_stofcbr" && (<Stofcbr {...props} />)} {/* 우수토실 */}
|
||||
{basicType === "tb_ms_swage_ppl" && (<SwagePpl />)} {/* 하수관로 */}
|
||||
{basicType === "tb_il_swage_prcs_fclt" && (<SwagePrcsFclt />)} {/* 하수처리시설 */}
|
||||
{basicType === "tb_ms_swage_prcs_zone" && (<SwagePrcsZone />)} {/* 하수처리구역 */}
|
||||
{basicType === "tb_ms_swage_mhl" && (<SwageMhl />)} {/* 하수맨홀 */}
|
||||
{basicType === "tb_ms_swage_pmstn" && (<SwagePmstn />)} {/* 하수펌프장 */}
|
||||
{basicType === "tb_ms_stofcbr" && (<Stofcbr />)} {/* 우수토실 */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user