Merge branch 'master' of http://118.219.150.34:50501/DBNT/kcscDev into thkim

thkim
thkim 2024-03-05 13:28:44 +09:00
commit 5fc1e01f57
25 changed files with 294 additions and 288 deletions

View File

@ -170,22 +170,16 @@
.userList .result .list_item > div:nth-child(7) {width: 100px;}
/* 사이트관리 > 환경설정 > 메뉴관리 */
.menuList .head > span:nth-child(1) {width: 100px;}
.menuList .head > span:nth-child(2) {width: 150px;}
.menuList .head > span:nth-child(3) {width: 100px;}
.menuList .head > span:nth-child(4) {width: 60px;}
.menuList .head > span:nth-child(5) {width: 60px;}
.menuList .head > span:nth-child(6) {width: 200px;}
.menuList .head > span:nth-child(7) {width: 100px;}
.menuList .head > span:nth-child(8) {width: 100px;}
.menuList .result .list_item > div:nth-child(1) {width: 100px;}
.menuList .result .list_item > div:nth-child(2) {width: 150px;}
.menuList .result .list_item > div:nth-child(3) {width: 100px;}
.menuList .result .list_item > div:nth-child(4) {width: 60px;}
.menuList .result .list_item > div:nth-child(5) {width: 60px;}
.menuList .result .list_item > div:nth-child(6) {width: 200px;}
.menuList .result .list_item > div:nth-child(7) {width: 100px;}
.menuList .result .list_item > div:nth-child(8) {width: 100px;}
.menuList .head > span:nth-child(1) {width: 120px;}
.menuList .head > span:nth-child(2) {width: 100px;}
.menuList .head > span:nth-child(3) {width: 200px;}
.menuList .head > span:nth-child(4) {width: 100px;}
.menuList .head > span:nth-child(5) {width: 100px;}
.menuList .result .list_item > div:nth-child(1) {width: 120px;}
.menuList .result .list_item > div:nth-child(2) {width: 100px;}
.menuList .result .list_item > div:nth-child(3) {width: 200px;}
.menuList .result .list_item > div:nth-child(4) {width: 100px;}
.menuList .result .list_item > div:nth-child(5) {width: 100px;}
/* 사이트관리 > 환경설정 > 메뉴권한관리 */
.roleList .head > span:nth-child(1) {width: 120px;}

View File

@ -33,11 +33,8 @@ function MenuMgt({}) {
resp.result.menuList.forEach(function (item, index) {
mutListTag.push(
<div className={"list_item"} key={"userListDiv_"+index}>
<div>{item.menuId}</div>
<div>{item.menuGroup?'└ ':''}{item.menuId}</div>
<div>{item.menuTitle}</div>
<div>{item.menuGroup}</div>
<div>{item.menuLevel}</div>
<div>{item.menuSort}</div>
<div>{item.menuUrl}</div>
<div>{item.menuTypeValue}</div>
<div>
@ -90,10 +87,7 @@ function MenuMgt({}) {
<div className="head">
<span>메뉴 코드</span>
<span>메뉴 이름</span>
<span>부모 메뉴</span>
<span>레벨</span>
<span>정렬</span>
<span>URI</span>
<span>경로</span>
<span>타입</span>
<span>
<button className={"btn btn_blue_h31 px-1"} onClick={()=>{editMenu(undefined)}}>추가</button>

View File

@ -38,7 +38,7 @@ function MenuModal({savedInfo, reloadFunction}){
}else if(Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)){
console.log("토큰 갱신중.")
}else{
alert(resp.result.resultMessage)
alert(resp.resultMessage)
}
}
)
@ -78,6 +78,14 @@ function MenuModal({savedInfo, reloadFunction}){
</Modal.Header>
<Modal.Body>
<Form onSubmit={(e) =>{editMenu(e)}} noValidate>
<Form.Group as={Row} className="mb-3">
<Form.Label column sm={3}>
그룹 코드
</Form.Label>
<Col sm={9}>
<Form.Control type="email" name="menuGroup" placeholder="그룹" required defaultValue={savedInfo?.menuGroup} />
</Col>
</Form.Group>
<Form.Group as={Row} className="mb-3">
<Form.Label column sm={3}>
메뉴 코드
@ -94,15 +102,7 @@ function MenuModal({savedInfo, reloadFunction}){
<Form.Control type="text" name="menuTitle" placeholder="이름" required defaultValue={savedInfo?.menuTitle} />
</Col>
</Form.Group>
<Form.Group as={Row} className="mb-3">
<Form.Label column sm={3}>
부모 메뉴
</Form.Label>
<Col sm={9}>
<Form.Control type="email" name="menuGroup" placeholder="그룹" required defaultValue={savedInfo?.menuGroup} />
</Col>
</Form.Group>
<Form.Group as={Row} className="mb-3">
<Form.Group as={Row} className="mb-3 d-none">
<Form.Label column sm={3}>
레벨
</Form.Label>
@ -110,7 +110,7 @@ function MenuModal({savedInfo, reloadFunction}){
<Form.Control type="number" min={"0"} name="menuLevel" placeholder="레벨" required defaultValue={savedInfo!==undefined?savedInfo.menuLevel:0} />
</Col>
</Form.Group>
<Form.Group as={Row} className="mb-3">
<Form.Group as={Row} className="mb-3 d-none">
<Form.Label column sm={3}>
정렬
</Form.Label>
@ -120,7 +120,7 @@ function MenuModal({savedInfo, reloadFunction}){
</Form.Group>
<Form.Group as={Row} className="mb-3">
<Form.Label column sm={3}>
URI
경로
</Form.Label>
<Col sm={9}>
<Form.Control type="text" name="menuUrl" placeholder="URI" required defaultValue={savedInfo?.menuUrl} />

View File

@ -8,6 +8,7 @@ import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
import EgovPaging from 'components/EgovPaging';
import { itemIdxByPage } from 'utils/calc';
import {format} from "date-fns";
function PrivacyConnections(props) {
// console.group("EgovAdminPrivacyList");
@ -66,7 +67,7 @@ function PrivacyConnections(props) {
<div>{item.targetUserId}</div>
<div>{item.accessType === "PRV_LIST" ? "사용자현황 조회" : item.accessType === "PRV_VIEW" ? "User 상세조회" : "User 수정"}</div>
<div>{item.ipAddress}</div>
<div>{item.accessDt}</div>
<div>{item.accessDt ? format(item.accessDt, "yyyy-MM-dd HH:mm") : ""}</div>
</div>
);
}
@ -122,7 +123,7 @@ function PrivacyConnections(props) {
<span>수정 ID</span>
<span>타입</span>
<span>접속IP</span>
<span>변경일자</span>
<span>일자</span>
</div>
<div className="result">
{listTag}

View File

@ -1,24 +1,18 @@
import PropTypes from 'prop-types';
import { useState } from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import { Link as RouterLink } from 'react-router-dom';
// material-ui
import { Box, Link, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from '@mui/material';
import * as EgovNet from 'api/egovFetch';
import {itemIdxByPage} from "../../../utils/calc";
import {format} from "date-fns";
function createData(trackingNo, title, dt, name) {
return { trackingNo, title, dt, name };
}
const rows = [
createData(1, '흙막이 가시설 띠장 전단 설계시 플래지 ...', '2024-02-04 13:22', '홍길동'),
createData(2, '콘크리트 벽체 설계기준 적용 유무 확인 ...', '2024-02-04 13:22', '홍길동'),
createData(3, '한중콘크리트 초기양생 관련', '2024-02-04 13:22', '홍길동'),
createData(4, 'KDS 21 30 00 : 2022가설흙...', '2024-02-04 13:22', '홍길동'),
createData(5, '인테리어필름 시방서 관련', '2024-02-04 13:22', '홍길동'),
createData(6, '고온고압증기양생기포콘크리트(ALC) 구조', '2024-02-04 13:22', '홍길동'),
createData(7, '지반을 최저등급으로 가정한 경우란', '2024-02-04 13:22', '홍길동')
];
function descendingComparator(a, b, orderBy) {
if (b[orderBy] < a[orderBy]) {
return -1;
@ -110,6 +104,68 @@ export default function OrderTable() {
const [orderBy] = useState('trackingNo');
const [selected] = useState([]);
const [listTag, setListTag] = useState([]);
const retrieveList = useCallback(() => {
// console.groupCollapsed("EgovAdminUsageList.retrieveList()");
const retrieveListURL = '/admin/dashboard/question';
const requestOptions = {
method: "POST",
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify()
}
EgovNet.requestFetch(retrieveListURL,
requestOptions,
(resp) => {
let mutListTag = [];
const resultCnt = parseInt(resp.result.QuestionList.length);
// const currentPageNo = 1; // resp.result.paginationInfo.currentPageNo;
// const pageSize = resultCnt; // resp.result.paginationInfo.pageSize;
//
if (resultCnt === 0) {
mutListTag.push(createData('', '데이터가 없습니다.', '', ''));
} else {
resp.result.QuestionList.forEach(function (item, index) {
if (index === 0) mutListTag = []; //
// const listIdx = itemIdxByPage(resultCnt, currentPageNo, pageSize, index);
mutListTag.push(
createData(index+1, item[0], item[1], item[2]),
);
});
}
setListTag(mutListTag);
},
function (resp) {
console.log("err response : ", resp);
}
);
// console.groupEnd("EgovAdminPrivacyList.retrieveList()");
// eslint-disable-next-line react-hooks/exhaustive-deps
},[listTag]);
useEffect(() => {
retrieveList();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// const rows = [listTag
// createData(1, ' ...', '2024-02-04 13:22', ''),
// createData(2, ' ...', '2024-02-04 13:22', ''),
// createData(3, ' ', '2024-02-04 13:22', ''),
// createData(4, 'KDS 21 30 00 : 2022...', '2024-02-04 13:22', ''),
// createData(5, ' ', '2024-02-04 13:22', ''),
// createData(6, '(ALC) ', '2024-02-04 13:22', ''),
// createData(7, ' ', '2024-02-04 13:22', '')
// ];
const isSelected = (trackingNo) => selected.indexOf(trackingNo) !== -1;
return (
@ -137,7 +193,7 @@ export default function OrderTable() {
>
<OrderTableHead order={order} orderBy={orderBy} />
<TableBody>
{stableSort(rows, getComparator(order, orderBy)).map((row, index) => {
{stableSort(listTag, getComparator(order, orderBy)).map((row, index) => {
const isItemSelected = isSelected(row.trackingNo);
const labelId = `enhanced-table-checkbox-${index}`;
@ -153,7 +209,7 @@ export default function OrderTable() {
>
<TableCell width="10%" align="left" component="th" id={labelId} scope="row">{row.trackingNo}</TableCell>
<TableCell width="50%" align="left"><Link color="secondary" component={RouterLink} to="" sx={{ overflow: 'hidden', textOverflow: 'ellipsis', display: 'block'}}>{row.title}</Link></TableCell>
<TableCell width="25%" align="center">{row.dt}</TableCell>
<TableCell width="25%" align="center">{row.dt? format(row.dt, "yyyy-MM-dd HH:mm") : ""}</TableCell>
<TableCell width="15%" align="center">{row.name}</TableCell>
</TableRow>
);

View File

@ -1,11 +1,8 @@
import React, {useState, useEffect, useCallback} from 'react'; // PureComponent
import {Link} from 'react-router-dom'; //useLocation
// import {BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from 'recharts';
import * as EgovNet from 'api/egovFetch';
import URL from 'constants/url';
// import CODE from 'constants/code';
// material-ui
import { Box, Button, Grid, Stack, Typography } from '@mui/material';
@ -27,34 +24,12 @@ function EgovAdminDashboard(props) {
// console.log("EgovAdminScheduleList [location] : ", location);
const DATE = new Date();
// const TODAY = new Date(DATE.getFullYear(), DATE.getMonth(), DATE.getDate());
//
// const [searchCondition, setSearchCondition] = useState(location.state?.searchCondition || {schdulSe: '', year: TODAY.getFullYear(), month: TODAY.getMonth(), date: TODAY.getDate()});
// const [calendarTag, setCalendarTag] = useState([]);
// const innerConsole = (...args) => {
// console.log(...args);
// }
// const changeDate = (target, amount) => {
// let changedDate;
//
// if (target === CODE.DATE_YEAR) {
// changedDate = new Date(searchCondition.year + amount, searchCondition.month, searchCondition.date);
// }
//
// if (target === CODE.DATE_MONTH) {
// changedDate = new Date(searchCondition.year, searchCondition.month + amount, searchCondition.date);
// }
// setSearchCondition({...searchCondition, year: changedDate.getFullYear(), month: changedDate.getMonth(), date: changedDate.getDate()});
// }
// const [countTag, setCountTag] = useState([]);
const [dashboardCnt, setDashboardCnt] = useState({
ConnMonthlyCount: [[0, 0.0, 0]],
DocuMonthlyCount: [[0, 0.0, 0]]
ErrorMonthlyCount: [[0, 0.0, 0]],
DocuMonthlyCount: [[0, 0.0, 0]],
CompMonthlyCount: [[0, 0.0, 0]]
});
// const [item0, setItem0] = useState([]);
const retrieveList = useCallback(() => {
const retrieveListURL = '/admin/dashboard/dash-count';
@ -69,21 +44,8 @@ function EgovAdminDashboard(props) {
EgovNet.requestFetch(retrieveListURL,
requestOptions,
(resp) => {
// let mutCountTag = [];
setDashboardCnt(resp.result);
console.log(resp.result.ConnMonthlyCount);
// mutCountTag.push(
// <div key={listIdx} className="list_item">
// <div>{listIdx}</div>
// <div>{item.userId}</div>
// <div>{item.targetUserId}</div>
// <div>{item.accessType === "PRV_LIST" ? " " : item.accessType === "PRV_VIEW" ? "User " : "User "}</div>
// <div>{item.ipAddress}</div>
// <div>{item.accessDt}</div>
// </div>
// );
// setCountTag(mutCountTag);
// console.log(resp.result.CompMonthlyCount);
},
function (resp) {
console.log("err response : ", resp);
@ -92,123 +54,10 @@ function EgovAdminDashboard(props) {
// eslint-disable-next-lie react-hooks/exhaustive-deps
}, []);
// const Location = React.memo(function Location() {
// return (
// <div className="location">
// <ul>
// <li><Link to={URL.MAIN} className="home">Home</Link></li>
// <li><Link to={URL.ADMIN}></Link></li>
// <li>Dashboard</li>
// </ul>
// </div>
// )
// });
useEffect(() => {
retrieveList();
}, [retrieveList]);
// const [dailyUserLogList, setDailyUserLogList] = useState([]);
// const [isDailyChart, setIsDailyChart] = useState(true);
//
// const getDailyUserLogList = useCallback(() => {
// // console.groupCollapsed("EgovAdminScheduleList.getDailyUserLogList()");
// //
// // console.log("@@@ isDailyChart : " + isDailyChart);
//
// const dailyUserLogListURL = isDailyChart ? '/admin/dashboard/daily-user-log-list' : '/admin/dashboard/monthly-user-log-list';
//
// const requestOptions = {
// method: "GET",
// headers: {
// 'Content-type': 'application/json',
// }
// }
//
// EgovNet.requestFetch(dailyUserLogListURL,
// requestOptions,
// (resp) => {
// setDailyUserLogList(resp.result.dailyUserLogList);
// // console.log("@@@ : " + dailyUserLogList);
// },
// function (resp) {
// // console.log("err response : ", resp);
// }
// );
// // console.groupEnd("EgovAdminScheduleList.getDailyUserLogList()");
// // eslint-disable-next-line react-hooks/exhaustive-deps
// }, [isDailyChart]);
//
// useEffect(() => {
// getDailyUserLogList();
// // eslint-disable-next-line react-hooks/exhaustive-deps
// }, [isDailyChart]);
//
// const handleChartToggle = () => {
// setIsDailyChart(!isDailyChart);
// };
//
// const ChartToggle = ({onToggle}) => {
//
// const handleToggle = () => {
// onToggle(!isDailyChart);
// };
//
// return (
// <button onClick={handleToggle}>
// {isDailyChart ? '' : ''}
// </button>
// )
// }
//
// const data = dailyUserLogList.map(item => ({
// logDt: item.logDt,
// uv: item.mobileCnt,
// " ": item.logCnt,
// amt: item.pcCnt,
// }));
//
// const CustomTooltip = ({active, payload, label}) => {
// if (active && payload && payload.length) {
// return (
// <div className="custom-tooltip">
// <p className="desc"> </p>
// <p className="label">{`${label} : ${payload[0].value}`}</p>
// </div>
// );
// }
//
// return null;
// };
// class UserLogChart extends PureComponent {
// render() {
// return (
// <ResponsiveContainer width="100%" height="100%">
// <BarChart
// width={500}
// height={300}
// data={data}
// margin={{
// top: 5,
// right: 30,
// left: 20,
// bottom: 5,
// }}
// >
// <CartesianGrid strokeDasharray="3 3"/>
// <XAxis dataKey="logDt"/>
// <YAxis/>
// <Tooltip content={<CustomTooltip/>}/>
// <Legend/>
// <Bar dataKey=" " barSize={20} fill="#87CEFA"/>
// </BarChart>
// </ResponsiveContainer>
// );
// }
// }
// console.log("------------------------------EgovAdminScheduleList [End]");
// console.groupEnd("EgovAdminScheduleList");
@ -255,13 +104,13 @@ function EgovAdminDashboard(props) {
<AnalyticEcommerce title={`총접속자수 (${DATE.getMonth() + 1}월)`} count={dashboardCnt.ConnMonthlyCount[0]?.[0]?.toLocaleString() || '0'} percentage={parseFloat(dashboardCnt.ConnMonthlyCount[0]?.[1]) || 0} extra={dashboardCnt.ConnMonthlyCount[0]?.[2]?.toLocaleString() || '0'} isLoss={dashboardCnt.ConnMonthlyCount[0]?.[1] < 0} color={dashboardCnt.ConnMonthlyCount[0]?.[1] < 0 ? "warning" : "primary"} />
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
<AnalyticEcommerce title={`건설기준 오류건수 (${DATE.getMonth() + 1}월)`} count="78,250" percentage={70.5} extra="8,900" />
<AnalyticEcommerce title={`건설기준 오류건수 (${DATE.getMonth() + 1}월)`} count={dashboardCnt.ErrorMonthlyCount[0]?.[0]?.toLocaleString() || '0'} percentage={parseFloat(dashboardCnt.ErrorMonthlyCount[0]?.[1]) || 0} extra={dashboardCnt.ErrorMonthlyCount[0]?.[2]?.toLocaleString() || '0'} isLoss={dashboardCnt.ErrorMonthlyCount[0]?.[1] < 0} color={dashboardCnt.ErrorMonthlyCount[0]?.[1] < 0 ? "warning" : "primary"} />
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
<AnalyticEcommerce title={`기준코드 등록건수 (${DATE.getMonth() + 1}월)`} count={dashboardCnt.DocuMonthlyCount[0]?.[0]?.toLocaleString() || '0'} percentage={parseFloat(dashboardCnt.DocuMonthlyCount[0]?.[1]) || 0} extra={dashboardCnt.DocuMonthlyCount[0]?.[2]?.toLocaleString() || '0'} isLoss={dashboardCnt.DocuMonthlyCount[0]?.[1] < 0} color={dashboardCnt.DocuMonthlyCount[0]?.[1] < 0 ? "warning" : "primary"} />
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
<AnalyticEcommerce title={`민원건수 (${DATE.getMonth() + 1}월)`} count="5" percentage={80} extra="1" isLoss color="warning" />
<AnalyticEcommerce title={`민원건수 (${DATE.getMonth() + 1}월)`} count={dashboardCnt.CompMonthlyCount[0]?.[0]?.toLocaleString() || '0'} percentage={parseFloat(dashboardCnt.CompMonthlyCount[0]?.[1]) || 0} extra={dashboardCnt.CompMonthlyCount[0]?.[2]?.toLocaleString() || '0'} isLoss={dashboardCnt.CompMonthlyCount[0]?.[1] < 0} color={dashboardCnt.CompMonthlyCount[0]?.[1] < 0 ? "warning" : "primary"} />
</Grid>
<Grid item md={8} sx={{ display: { sm: 'none', md: 'block', lg: 'none' } }} />

View File

@ -64,10 +64,6 @@ function List({}) {
);
},[]);
useEffect(() => {
retrieveList(searchCondition);
}, []);
useEffect(() => {
retrieveList(searchCondition);
}, [searchCondition.pageIndex]);

View File

@ -1,13 +1,9 @@
import React from "react";
import { SERVER_URL } from 'config';
import * as File from "utils/file"
import {Button, Modal, Nav} from "react-bootstrap";
function HistoryModal({closeFn, standardCode}){
function fileDownload(fileSeq){
window.open(encodeURI(SERVER_URL+'/file/download?fileSeq='+fileSeq));
}
return(
<>
<Modal.Header closeButton>
@ -30,11 +26,11 @@ function HistoryModal({closeFn, standardCode}){
<div className="mainCategory">{history.rvsnYmd.split('T')[0]}</div>
<div className="middleCategory">
{history.docFileGrpId}
{history.docFileGrpId?<Button size={"sm"} variant={"outline-secondary"} onClick={()=>fileDownload(history.docFileGrpId)}>다운로드 </Button>:''}
{history.docFileGrpId?<Button size={"sm"} variant={"outline-secondary"} onClick={()=>File.standardCode(history.docFileGrpId)}>다운로드 </Button>:''}
</div>
<div className="kcscCd">
{history.rvsnFileGrpId}
{history.rvsnFileGrpId?<Button size={"sm"} variant={"outline-secondary"} onClick={()=>fileDownload(history.rvsnFileGrpId)}>다운로드 </Button>:''}
{history.rvsnFileGrpId?<Button size={"sm"} variant={"outline-secondary"} onClick={()=>File.download(history.rvsnFileGrpId)}>다운로드 </Button>:''}
</div>
</div>
)

View File

@ -1,9 +1,7 @@
import React, { useState, useEffect, useCallback } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import SbItem from './SbItem'
import Loading from 'components/Loading'
import BookmarkModal from './BookmarkModal';
import {SbContainer} from './Sb.style'
import {VwDiv, VwPtag} from './Vw.style'
import Form from 'react-bootstrap/Form'
import Row from 'react-bootstrap/Row';
@ -16,6 +14,7 @@ import {parseJwt} from "utils/parseJwt";
import Button from "react-bootstrap/Button";
import {InputGroup} from "react-bootstrap";
import ViewerTree from "./ViewerTree";
import * as File from "utils/file";
function CodeViewer(props) {
const [treeLoading, setTreeLoading] = useState(true);
@ -73,6 +72,8 @@ function CodeViewer(props) {
let optionTag = [];
let activeIndex = 0;
let docTitle = "";
let docFileGrpId = "";
let rvsnFileGrpId = "";
if(ymd===undefined){
activeIndex = docInfo.length-1
docTitle = docInfo[docInfo.length-1].doc_nm
@ -95,7 +96,10 @@ function CodeViewer(props) {
if(index === activeIndex){
buttonClass += "docInfoActive"
pClass += "yearInfoActive"
docFileGrpId = item.doc_file_grp_id;
rvsnFileGrpId = item.rvsn_file_grp_id;
}
optionTag.push(
<Col>
<input type="button"
@ -109,7 +113,22 @@ function CodeViewer(props) {
<p className={pClass}>{item.doc_yr}</p>
</Col>)
})
headTag.push(<Row className="docInfoRow"><Col className="docInfoTitle">{docCode} {docTitle}</Col>{optionTag}</Row>)
headTag.push(
<>
<Col xs={"auto"}>
<Row className="docInfoRow">
<Col className="docInfoTitle">{docCode} {docTitle}</Col>
{optionTag}
</Row>
</Col>
<Col>
<input type="button" className="btn btn-sm btn-primary optionBtn" value="연혁"/>
<input type="button" className="btn btn-sm btn-primary optionBtn" value="2단비교"/>
{rvsnFileGrpId?<input type="button" className="btn btn-sm btn-primary optionBtn" value="신구조문" onClick={()=>{File.download(rvsnFileGrpId)}}/>:''}
{docFileGrpId?<input type="button" className="btn btn-sm btn-primary optionBtn" value="첨부파일" onClick={()=>{File.standardCode(docFileGrpId)}}/>:''}
</Col>
</>
)
}else{
headTag.push(<div>검색된 결과가 없습니다.</div>); //
}
@ -409,13 +428,7 @@ function CodeViewer(props) {
<Row className="justify-content-between">
<Col xs={"auto"}>
<Row>
<Col xs={"auto"}>{docInfo}</Col>
<Col>
<input type="button" className="btn btn-sm btn-primary optionBtn" value="연혁"/>
<input type="button" className="btn btn-sm btn-primary optionBtn" value="2단비교"/>
<input type="button" className="btn btn-sm btn-primary optionBtn" value="신구조문"/>
<input type="button" className="btn btn-sm btn-primary optionBtn" value="첨부파일"/>
</Col>
{docInfo}
</Row>
</Col>
<Col xs={"auto"}>

View File

@ -0,0 +1,11 @@
import {SERVER_URL} from "../config";
import {parseJwt} from "./parseJwt";
import {getLocalItem} from "./storage";
export function download(fileSeq){
window.open(encodeURI(SERVER_URL+'/file/download?fileSeq='+fileSeq));
}
export function standardCode(fileSeq){
const sessionUser = parseJwt(getLocalItem('accessToken'));
window.open(encodeURI(SERVER_URL+'/file/standardCode-download?userId='+sessionUser?.id+'&fileSeq='+fileSeq));
}

View File

@ -35,7 +35,7 @@ public class TcMenu {
@Column(name = "menu_sort")
private Integer menuSort;
@Column(name = "menu_url")
@NotBlank(message = "메뉴URI를 입력해주세요.")
@NotBlank(message = "경로를 입력해주세요.")
private String menuUrl;
@Column(name = "menu_type_cd")
@NotBlank(message = "타입을 선택해주세요.")

View File

@ -44,9 +44,9 @@ public class AdminDashboardController extends BaseController {
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("ConnMonthlyCount", adminDashboardService.selectConnMonthly());
resultMap.put("DocuMonthlyCount", adminDashboardService.selectDocuMonthly());
// resultMap.put("loginMonthlyList", adminDashboardService.selectLoginMonthly());
// resultMap.put("loginDailyList", adminDashboardService.selectLoginDaily());
resultMap.put("ErrorMonthlyCount", adminDashboardService.selectErrorMonthly());
resultMap.put("DocuMonthlyCount", adminDashboardService.selectDocumentMonthly());
resultMap.put("CompMonthlyCount", adminDashboardService.selectComplaintMonthly());
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
@ -108,6 +108,31 @@ public class AdminDashboardController extends BaseController {
}
@Operation(
summary = "미답변 문의사항 조회",
description = "미답변 문의사항 조회",
tags = {"AdminDashboardController"}
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "조회 성공"),
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
})
@RequestMapping(method = RequestMethod.POST, value = "/question", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResultVO getBbs(@AuthenticationPrincipal LoginVO user)
throws Exception {
ResultVO resultVO = new ResultVO();
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("QuestionList", adminDashboardService.selectQuestion());
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
resultVO.setResult(resultMap);
return resultVO;
}
@Operation(
summary = "해당월 접속방법 조회",
description = "해당월 PC/MOBILE 조회",

View File

@ -32,6 +32,33 @@ public interface DashboardRepository extends JpaRepository<TnDailyMenuLog, Long>
"FROM this_month_logs, last_month_logs", nativeQuery = true)
List<Object[]> ConnMonthlyCount();
@Query(value = "WITH this_month_logs AS ( " +
" SELECT count(*) AS this_month_cnt " +
" FROM tn_document_content " +
" WHERE use_yn = 'Y' AND COALESCE(error_cd, '') <> '' " +
" AND frst_crt_dt >= DATE_TRUNC('month', CURRENT_DATE - INTERVAL '1 month') " +
" AND frst_crt_dt < DATE_TRUNC('month', CURRENT_DATE) " +
"), " +
"last_month_logs AS ( " +
" SELECT count(*) AS last_month_cnt " +
" FROM tn_document_content " +
" WHERE use_yn = 'Y' AND COALESCE(error_cd, '') <> '' " +
" AND frst_crt_dt >= DATE_TRUNC('month', CURRENT_DATE - INTERVAL '1 month') " +
" AND frst_crt_dt < DATE_TRUNC('month', CURRENT_DATE) " +
") " +
"SELECT " +
" this_month_cnt, " +
" CASE " +
" WHEN last_month_cnt = 0 AND this_month_cnt = 0 THEN 0" +
" WHEN last_month_cnt = 0 THEN 100" +
" ELSE ROUND(((CAST(this_month_cnt AS NUMERIC) - last_month_cnt) / last_month_cnt * 100), 1)" +
" END AS ratio, " +
" last_month_cnt " +
"FROM this_month_logs, last_month_logs", nativeQuery = true)
List<Object[]> ErrorMonthlyCount();
@Query(value = "WITH this_month_logs AS ( " +
" SELECT count(*) AS this_month_cnt " +
" FROM tn_document_info " +
@ -57,6 +84,33 @@ public interface DashboardRepository extends JpaRepository<TnDailyMenuLog, Long>
"FROM this_month_logs, last_month_logs", nativeQuery = true)
List<Object[]> DocuMonthlyCount();
@Query(value = "WITH this_month_logs AS ( " +
" SELECT count(*) AS this_month_cnt " +
" FROM tn_bbs_contents " +
" WHERE bbs_id = 'KCSC-QA' AND use_yn = 'Y' " +
" AND frst_crt_dt >= DATE_TRUNC('month', CURRENT_DATE) " +
" AND frst_crt_dt < DATE_TRUNC('month', CURRENT_DATE) + INTERVAL '1 month' " +
"), " +
"last_month_logs AS ( " +
" SELECT count(*) AS last_month_cnt " +
" FROM tn_bbs_contents " +
" WHERE bbs_id = 'KCSC-QA'AND use_yn = 'Y' " +
" AND frst_crt_dt >= DATE_TRUNC('month', CURRENT_DATE - INTERVAL '1 month') " +
" AND frst_crt_dt < DATE_TRUNC('month', CURRENT_DATE) " +
") " +
"SELECT " +
" this_month_cnt, " +
" CASE " +
" WHEN last_month_cnt = 0 AND this_month_cnt = 0 THEN 0" +
" WHEN last_month_cnt = 0 THEN 100" +
" ELSE ROUND(((CAST(this_month_cnt AS NUMERIC) - last_month_cnt) / last_month_cnt * 100), 1) " +
" END AS ratio, " +
" last_month_cnt " +
"FROM this_month_logs, last_month_logs", nativeQuery = true)
List<Object[]> CompMonthlyCount();
@Query(value = "WITH all_months AS (" +
" SELECT generate_series(DATE_TRUNC('year', CURRENT_DATE), DATE_TRUNC('year', CURRENT_DATE) + INTERVAL '11 month', INTERVAL '1 month') AS month_start" +
")" +
@ -97,7 +151,6 @@ public interface DashboardRepository extends JpaRepository<TnDailyMenuLog, Long>
List<Long> LoginMonthlyList();
@Query(value = "WITH all_days AS (" +
" SELECT generate_series(" +
" DATE_TRUNC('year', CURRENT_DATE)," +
@ -113,7 +166,6 @@ public interface DashboardRepository extends JpaRepository<TnDailyMenuLog, Long>
List<Long> LoginDailyList();
@Query(value = "WITH all_days AS (" +
" SELECT generate_series(" +
" DATE_TRUNC('year', CURRENT_DATE)," +
@ -130,6 +182,13 @@ public interface DashboardRepository extends JpaRepository<TnDailyMenuLog, Long>
List<Long> FileDailyList();
@Query(value = "SELECT bbs_cont_title, frst_crt_dt, frst_crt_id " +
"FROM tn_bbs_contents a " +
"WHERE bbs_id = 'KCSC-QA' AND use_yn = 'Y' " +
"AND (SELECT bbs_cont_seq b FROM public.tn_bbs_contents b WHERE bbs_id = 'KCSC-QA' AND use_yn = 'Y' AND b.bbs_cont_seq_group=a.bbs_cont_seq) IS NULL " +
"ORDER BY frst_crt_dt desc", nativeQuery = true)
List<Object[]> QuestionList();
@Query(value = "SELECT sum(pc_cnt) AS p_cnt, sum(mobile_cnt) AS m_cnt " +
"FROM tn_daily_user_log " +

View File

@ -1,25 +1,25 @@
package com.dbnt.kcscbackend.admin.dashboard.service;
//import com.dbnt.kcscbackend.admin.logs.entity.TnDailyUserLog;
//import com.dbnt.kcscbackend.admin.dashboard.repository.TnDailyUserLogRepository;
//import com.dbnt.kcscbackend.admin.boards.entity.TnBbsContents;
import com.dbnt.kcscbackend.admin.dashboard.repository.DashboardRepository;
import com.dbnt.kcscbackend.admin.logs.entity.TnDailyUserLog;
import lombok.RequiredArgsConstructor;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
//import java.time.LocalDate;
import java.util.List;
@Service
@RequiredArgsConstructor
public class AdminDashboardService extends EgovAbstractServiceImpl {
// private final TnDailyUserLogRepository tnDailyUserLogRepository;
private final DashboardRepository dashboardRepository;
public List<Object[]> selectConnMonthly() { return dashboardRepository.ConnMonthlyCount(); }
public List<Object[]> selectDocuMonthly() { return dashboardRepository.DocuMonthlyCount(); }
public List<Object[]> selectErrorMonthly() { return dashboardRepository.ErrorMonthlyCount(); }
public List<Object[]> selectDocumentMonthly() { return dashboardRepository.DocuMonthlyCount(); }
public List<Object[]> selectComplaintMonthly() { return dashboardRepository.CompMonthlyCount(); }
public List<Long> selectMenuMonthly() { return dashboardRepository.MenuMonthlyList(); }
@ -31,13 +31,9 @@ public class AdminDashboardService extends EgovAbstractServiceImpl {
public List<Long> selectFileDaily() { return dashboardRepository.FileDailyList(); }
public List<Object[]> selectQuestion() { return dashboardRepository.QuestionList(); }
public List<Object[]> selectConnectMonthly() { return dashboardRepository.findConnMonthly(); }
// public List<TnDailyUserLog> selectDailyUserLogList(LocalDate startDate, LocalDate endDate) {
// return tnDailyUserLogRepository.findByLogDtBetweenOrderByLogDt(startDate, endDate);
// }
//
// public List<Object[]> selectMonthlyUserLogList(LocalDate startDate, LocalDate endDate) {
// return tnDailyUserLogRepository.selectMonthlyUserLogStatistics(startDate, endDate);
// }
}

View File

@ -9,8 +9,6 @@ import org.hibernate.annotations.DynamicUpdate;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import java.time.LocalDate;
import java.awt.*;
import java.time.LocalDateTime;
@Getter

View File

@ -3,17 +3,14 @@ package com.dbnt.kcscbackend.admin.logs.entity;
import java.io.Serializable;
import com.dbnt.kcscbackend.config.common.BoardParams;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Getter
@ -45,8 +42,7 @@ public class ThPrivacyLog extends BoardParams implements Serializable {
private String ipAddress;
@Column(name = "access_dt")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate accessDt;
private LocalDateTime accessDt;
@Column(name = "session_id")
private String sessionId;

View File

@ -28,7 +28,8 @@ public interface FileLogsRepository extends JpaRepository<ThAttachFileLog, Long>
+ " COUNT(CASE WHEN group_cur_cd = 'O4' THEN 1 ELSE NULL END) AS CodeO4Cnt,"
+ " COUNT(CASE WHEN group_cur_cd IN ('O5', 'O6', 'O7') THEN 1 ELSE NULL END) AS CodeO5Cnt "
+ "FROM th_attach_file_log "
+ "WHERE access_dt BETWEEN TO_DATE(:startDate, 'YYYY-MM-DD') AND TO_DATE(:endDate, 'YYYY-MM-DD') "
+ "WHERE access_dt >= TO_DATE(:startDate, 'YYYY-MM-DD') "
+ "AND access_dt < TO_DATE(:endDate, 'YYYY-MM-DD') + INTERVAL '1 day' "
+ "GROUP BY TO_CHAR(access_dt, 'YYYY-MM-DD') "
+ "ORDER BY log_dt asc", nativeQuery = true)
List<Object[]> selectCountFile(@Param("startDate") String startDate, @Param("endDate") String endDate);

View File

@ -1,11 +1,16 @@
package com.dbnt.kcscbackend.admin.logs.service;
import com.dbnt.kcscbackend.admin.logs.entity.ThAttachFileLog;
import com.dbnt.kcscbackend.admin.logs.entity.ThLoginLog;
import com.dbnt.kcscbackend.admin.logs.entity.ThPrivacyLog;
import com.dbnt.kcscbackend.admin.logs.entity.TnDailyUserLog;
import com.dbnt.kcscbackend.admin.logs.repository.FileLogsRepository;
import com.dbnt.kcscbackend.admin.logs.repository.PrivacyLogsRepository;
import com.dbnt.kcscbackend.admin.logs.repository.ThLoginLogRepository;
import com.dbnt.kcscbackend.admin.logs.repository.UserLogsRepository;
import com.dbnt.kcscbackend.file.entity.TnAttachFile;
import com.dbnt.kcscbackend.standardCode.entity.TnDocumentInfo;
import com.dbnt.kcscbackend.standardCode.repository.TnDocumentInfoRepository;
import lombok.RequiredArgsConstructor;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
@ -24,6 +29,8 @@ public class AdminLogsService extends EgovAbstractServiceImpl {
private final PrivacyLogsRepository privacyLogsRepository;
private final ThLoginLogRepository loginLogRepository;
private final UserLogsRepository userLogsRepository;
private final FileLogsRepository fileLogsRepository;
private final TnDocumentInfoRepository documentInfoRepository;
public Map<String, Object> selectPrivacyList() {
Map<String, Object> resultMap = new HashMap<>();
@ -47,7 +54,7 @@ public class AdminLogsService extends EgovAbstractServiceImpl {
public void insertPrivacyLog(String userId, String ipAddress, String accessType, String targetUserId){
ThPrivacyLog log = new ThPrivacyLog();
log.setUserId(userId);
log.setAccessDt(LocalDate.now());
log.setAccessDt(LocalDateTime.now());
log.setIpAddress(ipAddress);
log.setAccessType(accessType);
log.setTargetUserId(targetUserId);
@ -93,4 +100,26 @@ public class AdminLogsService extends EgovAbstractServiceImpl {
}
}
@Transactional
public void insertFileLog(TnAttachFile tnAttachFile, String accessId, String ipAddress){
TnDocumentInfo documentInfo = documentInfoRepository.findByDocFileGrpId(tnAttachFile.getFileSeq().toString()).orElse(null);
ThAttachFileLog fileLog = new ThAttachFileLog();
fileLog.setFileSeq((long)tnAttachFile.getFileSeq());
fileLog.setAccessType("FILE_DOWN");
fileLog.setAccessId(accessId);
fileLog.setAccessDt(LocalDateTime.now());
fileLog.setIpAddress(ipAddress);
switch (documentInfo.getKcscCd().split(" ")[0]){
case "KDS": fileLog.setGroupCurCd("10"); break;
case "KCS": fileLog.setGroupCurCd("20"); break;
case "SMCS": fileLog.setGroupCurCd("40"); break;
case "EXCS": fileLog.setGroupCurCd("50"); break;
case "KRCCS": fileLog.setGroupCurCd("60"); break;
case "KRACS": fileLog.setGroupCurCd("70"); break;
case "LHCS": fileLog.setGroupCurCd("80"); break;
case "KWCS": fileLog.setGroupCurCd("90"); break;
}
fileLogsRepository.save(fileLog);
}
}

View File

@ -72,6 +72,7 @@ public class SecurityConfig {
"/cmm/main/**.do", // 메인페이지
"/cmm/fms/FileDown.do", //파일 다운로드
"/file/download", //파일 다운로드
"/file/standardCode-download", //파일 다운로드
"/cmm/fms/getImage.do", //갤러리 이미지보기
"/cop/bbs/selectUserBBSMasterInfAPI.do", //게시판 마스터 상세 조회

View File

@ -1,10 +1,13 @@
package com.dbnt.kcscbackend.file;
import com.dbnt.kcscbackend.admin.logs.service.AdminLogsService;
import com.dbnt.kcscbackend.auth.entity.LoginVO;
import com.dbnt.kcscbackend.config.util.ClientUtils;
import com.dbnt.kcscbackend.file.entity.TnAttachFile;
import com.dbnt.kcscbackend.file.service.FileService;
import com.dbnt.kcscbackend.standardCode.service.StandardCodeService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@ -20,37 +23,22 @@ import java.io.*;
public class FileController {
private final FileService fileService;
private final StandardCodeService standardCodeService;
private final AdminLogsService adminLogsService;
@RequestMapping(method = RequestMethod.GET, value = "/download")
public void download(HttpServletRequest request, HttpServletResponse response, TnAttachFile tnAttachFile) throws Exception{
tnAttachFile = fileService.selectTnAttachFile(tnAttachFile);
if(tnAttachFile != null){
BufferedInputStream in;
BufferedOutputStream out;
try {
File file = new File(tnAttachFile.getFilePath());
ClientUtils.setDisposition(tnAttachFile.getFileOldName(), request, response);
in = new BufferedInputStream(new FileInputStream(file));
out = new BufferedOutputStream(response.getOutputStream());
FileCopyUtils.copy(in, out);
out.flush();
if(out!=null) out.close();
if(in!=null )in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
fileDownload(request, response, tnAttachFile);
}
@RequestMapping(method = RequestMethod.GET, value = "/standardCode/download")
public void standardCodeDownload(HttpServletRequest request, HttpServletResponse response, TnAttachFile tnAttachFile) throws Exception{
@RequestMapping(method = RequestMethod.GET, value = "/standardCode-download")
public void standardCodeDownload(HttpServletRequest request, HttpServletResponse response, TnAttachFile tnAttachFile, String userId) throws Exception{
tnAttachFile = fileService.selectTnAttachFile(tnAttachFile);
adminLogsService.insertFileLog(tnAttachFile, userId, ClientUtils.getRemoteIP(request));
fileDownload(request, response, tnAttachFile);
}
private void fileDownload(HttpServletRequest request, HttpServletResponse response, TnAttachFile tnAttachFile){
if(tnAttachFile != null){
BufferedInputStream in;
BufferedOutputStream out;

View File

@ -1,7 +1,6 @@
package com.dbnt.kcscbackend.standardCode.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -22,9 +21,9 @@ public class TnDocumentInfo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "doc_info_seq")
private int docInfoSeq;
private Integer docInfoSeq;
@Column(name = "group_seq", nullable = false)
private int groupSeq;
private Integer groupSeq;
@Column(name = "kcsc_cd")
private String kcscCd;
@Column(name = "old_kcsc_cd")
@ -34,7 +33,7 @@ public class TnDocumentInfo {
@Column(name = "doc_yr", nullable = false)
private String docYr;
@Column(name = "doc_cycl", nullable = false)
private int docCycl;
private Integer docCycl;
@Column(name = "doc_er", nullable = false)
private String docEr;
@Column(name = "estb_ymd")
@ -44,7 +43,7 @@ public class TnDocumentInfo {
@Temporal(TemporalType.DATE)
private Date rvsnYmd;
@Column(name = "doc_rev_hist_seq")
private int docRevHistSeq;
private Integer docRevHistSeq;
@Column(name = "doc_brief", length = 1000)
private String docBrief;
@Column(name = "doc_rvsn_remark", length = 1000)
@ -66,7 +65,7 @@ public class TnDocumentInfo {
@Temporal(TemporalType.DATE)
private Date aplcnEndYmd;
@Column(name = "doc_order", nullable = false)
private int docOrder;
private Integer docOrder;
@Column(name = "last_yn", nullable = false)
private char lastYn;
@Column(name = "doc_file_grp_id")

View File

@ -6,8 +6,11 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
import java.util.Optional;
public interface TnDocumentInfoRepository extends JpaRepository<TnDocumentInfo, Integer> {
@Query(value = "select * from sp_get_tn_document_info_by_group_cd(null, :docCode)", nativeQuery = true)
List<TnDocumentInfoInterface> spGetTnDocumentInfoByGroupCd(String docCode);
Optional<TnDocumentInfo> findByDocFileGrpId(String fileSeq);
}

View File

@ -17,7 +17,7 @@
inner join tc_code_item b on a.user_se = b.item_cd
inner join tc_code_item c on a.status = c.item_cd
<include refid="selectUserListWhere"></include>
order by user_seq asc
order by user_seq desc
limit #{rowCnt} offset #{firstIndex}
</select>

View File

@ -78,6 +78,7 @@
</if>
and b.group_type = 'D'
</where>
order by doc_yr asc
</select>
<select id="selectStandardCodeGroupSeq" parameterType="String" resultType="Integer">

View File

@ -21,7 +21,7 @@
from tc_menu a
inner join tc_code_item b on a.menu_type_cd = b.item_cd
where a.use_yn = 'Y'
order by menu_id asc
order by menu_type_cd desc, menu_id asc
</select>
<select id="selectMenuAuthList" resultType="TcMenu">