diff --git a/egovframe-template-simple-react-contribution/src/pages/admin/schedule/BbsTable.jsx b/egovframe-template-simple-react-contribution/src/pages/admin/schedule/BbsTable.jsx index ce00415..b358800 100644 --- a/egovframe-template-simple-react-contribution/src/pages/admin/schedule/BbsTable.jsx +++ b/egovframe-template-simple-react-contribution/src/pages/admin/schedule/BbsTable.jsx @@ -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() { > - {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() { > {row.trackingNo} {row.title} - {row.dt} + {row.dt? format(row.dt, "yyyy-MM-dd HH:mm") : ""} {row.name} ); diff --git a/egovframe-template-simple-react-contribution/src/pages/admin/schedule/EgovAdminScheduleList.jsx b/egovframe-template-simple-react-contribution/src/pages/admin/schedule/EgovAdminScheduleList.jsx index 7879d2e..c46bcc2 100644 --- a/egovframe-template-simple-react-contribution/src/pages/admin/schedule/EgovAdminScheduleList.jsx +++ b/egovframe-template-simple-react-contribution/src/pages/admin/schedule/EgovAdminScheduleList.jsx @@ -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( - //
- //
{listIdx}
- //
{item.userId}
- //
{item.targetUserId}
- //
{item.accessType === "PRV_LIST" ? "사용자현황 조회" : item.accessType === "PRV_VIEW" ? "User 상세조회" : "User 수정"}
- //
{item.ipAddress}
- //
{item.accessDt}
- //
- // ); - // 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 ( - //
- //
    - //
  • Home
  • - //
  • 사이트관리
  • - //
  • Dashboard
  • - //
- //
- // ) - // }); - 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 ( - // - // ) - // } - // - // 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 ( - //
- //

사용자 접속 현황

- //

{`${label} : ${payload[0].value}`}

- //
- // ); - // } - // - // return null; - // }; - - // class UserLogChart extends PureComponent { - // render() { - // return ( - // - // - // - // - // - // }/> - // - // - // - // - // ); - // } - // } - // console.log("------------------------------EgovAdminScheduleList [End]"); // console.groupEnd("EgovAdminScheduleList"); @@ -255,13 +104,13 @@ function EgovAdminDashboard(props) { - + - + diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/dashboard/AdminDashboardController.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/dashboard/AdminDashboardController.java index 4f29c2f..315ff44 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/dashboard/AdminDashboardController.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/dashboard/AdminDashboardController.java @@ -44,9 +44,9 @@ public class AdminDashboardController extends BaseController { Map 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 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 조회", diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/dashboard/repository/DashboardRepository.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/dashboard/repository/DashboardRepository.java index afa8cc6..d969f86 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/dashboard/repository/DashboardRepository.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/dashboard/repository/DashboardRepository.java @@ -32,6 +32,33 @@ public interface DashboardRepository extends JpaRepository "FROM this_month_logs, last_month_logs", nativeQuery = true) List 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 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 "FROM this_month_logs, last_month_logs", nativeQuery = true) List 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 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 List LoginMonthlyList(); - @Query(value = "WITH all_days AS (" + " SELECT generate_series(" + " DATE_TRUNC('year', CURRENT_DATE)," + @@ -113,7 +166,6 @@ public interface DashboardRepository extends JpaRepository List LoginDailyList(); - @Query(value = "WITH all_days AS (" + " SELECT generate_series(" + " DATE_TRUNC('year', CURRENT_DATE)," + @@ -130,6 +182,13 @@ public interface DashboardRepository extends JpaRepository List 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 QuestionList(); + @Query(value = "SELECT sum(pc_cnt) AS p_cnt, sum(mobile_cnt) AS m_cnt " + "FROM tn_daily_user_log " + diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/dashboard/service/AdminDashboardService.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/dashboard/service/AdminDashboardService.java index bee8ac1..1061a04 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/dashboard/service/AdminDashboardService.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/dashboard/service/AdminDashboardService.java @@ -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 selectConnMonthly() { return dashboardRepository.ConnMonthlyCount(); } - public List selectDocuMonthly() { return dashboardRepository.DocuMonthlyCount(); } + public List selectErrorMonthly() { return dashboardRepository.ErrorMonthlyCount(); } + + public List selectDocumentMonthly() { return dashboardRepository.DocuMonthlyCount(); } + + public List selectComplaintMonthly() { return dashboardRepository.CompMonthlyCount(); } public List selectMenuMonthly() { return dashboardRepository.MenuMonthlyList(); } @@ -31,13 +31,9 @@ public class AdminDashboardService extends EgovAbstractServiceImpl { public List selectFileDaily() { return dashboardRepository.FileDailyList(); } + public List selectQuestion() { return dashboardRepository.QuestionList(); } + public List selectConnectMonthly() { return dashboardRepository.findConnMonthly(); } -// public List selectDailyUserLogList(LocalDate startDate, LocalDate endDate) { -// return tnDailyUserLogRepository.findByLogDtBetweenOrderByLogDt(startDate, endDate); -// } -// -// public List selectMonthlyUserLogList(LocalDate startDate, LocalDate endDate) { -// return tnDailyUserLogRepository.selectMonthlyUserLogStatistics(startDate, endDate); -// } + }