건설현장 관리 > 발주기관 로그인 내역 - 일별 접속량 차트 추가
parent
dbb58e393c
commit
61be76c392
|
|
@ -995,6 +995,31 @@ public class ConstructionProjectManagementController {
|
||||||
return "admins/constructionProjectManagement/construction-user-login-history";
|
return "admins/constructionProjectManagement/construction-user-login-history";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API 관리 > 일일접속량 차트
|
||||||
|
* @param params
|
||||||
|
* @param model
|
||||||
|
* @param response
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@ResponseBody
|
||||||
|
@RequestMapping(value = "/admins/constructionProjectManagement/o_charts.do", method = RequestMethod.POST)
|
||||||
|
public HashMap<String, Object> getMgmtApiOutDataAccessChart(@RequestParam HashMap<String, Object> params, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
|
||||||
|
strUtil sUtil = new strUtil();
|
||||||
|
HashMap<String, Object> result = new HashMap<String, Object>();
|
||||||
|
String CHART_DATE = sUtil.checkNull((String)params.get("chartDate"));
|
||||||
|
params.put("CHART_DATE", CHART_DATE);
|
||||||
|
List<EgovMap> listData = masterService.selectUserLoginHistoryChart(params);
|
||||||
|
|
||||||
|
result.put("code", "SUCCESS");
|
||||||
|
result.put("msg", "일별 접속량 데이터 조회를 성공했습니다.");
|
||||||
|
result.put("data", listData);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public void buildExcelDocument(Map<String, Object> model, HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
public void buildExcelDocument(Map<String, Object> model, HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||||
|
|
||||||
List<?> selectInfoListExcel = (List<?>) model.get("selectInfoListExcel");
|
List<?> selectInfoListExcel = (List<?>) model.get("selectInfoListExcel");
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,8 @@ public interface GeneralUserMngMapper {
|
||||||
|
|
||||||
public List<EgovMap> selectUserLoginHistory(HashMap<String, Object> params) throws Exception;
|
public List<EgovMap> selectUserLoginHistory(HashMap<String, Object> params) throws Exception;
|
||||||
|
|
||||||
|
public List<EgovMap> selectUserLoginHistoryChart(HashMap<String, Object> params) throws Exception;
|
||||||
|
|
||||||
String findProjectMasterCompanyNameByUserid(String userId);
|
String findProjectMasterCompanyNameByUserid(String userId);
|
||||||
|
|
||||||
List<EgovMap> getUserGDisList(HashMap<String, Object> params) throws Exception;
|
List<EgovMap> getUserGDisList(HashMap<String, Object> params) throws Exception;
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ public interface GeneralUserMngService {
|
||||||
|
|
||||||
public List<EgovMap> selectUserLoginHistory(HashMap<String, Object> params) throws Exception;
|
public List<EgovMap> selectUserLoginHistory(HashMap<String, Object> params) throws Exception;
|
||||||
|
|
||||||
|
public List<EgovMap> selectUserLoginHistoryChart(HashMap<String, Object> params) throws Exception;
|
||||||
|
|
||||||
public List<EgovMap> getUserGDisList(HashMap<String, Object> params) throws Exception;
|
public List<EgovMap> getUserGDisList(HashMap<String, Object> params) throws Exception;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,11 @@ public class GeneralUserMngServiceImpl implements GeneralUserMngService {
|
||||||
return masterMapper.selectUserLoginHistory(params);
|
return masterMapper.selectUserLoginHistory(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<EgovMap> selectUserLoginHistoryChart(HashMap<String, Object> params) throws Exception {
|
||||||
|
return masterMapper.selectUserLoginHistoryChart(params);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<EgovMap> getUserGDisList(HashMap<String, Object> params) throws Exception {
|
public List<EgovMap> getUserGDisList(HashMap<String, Object> params) throws Exception {
|
||||||
return masterMapper.getUserGDisList(params);
|
return masterMapper.getUserGDisList(params);
|
||||||
|
|
|
||||||
|
|
@ -485,6 +485,34 @@
|
||||||
]]> -->
|
]]> -->
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectUserLoginHistoryChart" parameterType="map" resultType="egovMap">
|
||||||
|
<!-- SELECT TO_CHAR(d.visit_date, 'YYYY-MM-DD') AS visit_date
|
||||||
|
,COUNT(wmi.USERID) AS visit_count
|
||||||
|
FROM (SELECT TRUNC(TO_DATE(#{chartDate})) - LEVEL + 1 AS visit_date
|
||||||
|
FROM DUAL
|
||||||
|
CONNECT BY LEVEL <![CDATA[<=]]> 10) d
|
||||||
|
LEFT JOIN WEB_REQUEST_LOG wrl ON wrl.DATETIME <![CDATA[>=]]> d.visit_date
|
||||||
|
AND wrl.DATETIME <![CDATA[<]]> d.visit_date + 1
|
||||||
|
INNER JOIN WEB_MEMBER_IN wmi ON wrl.USERID = wmi.USERID
|
||||||
|
AND wmi.CLS = 2
|
||||||
|
GROUP BY d.visit_date
|
||||||
|
ORDER BY d.visit_date -->
|
||||||
|
|
||||||
|
SELECT TO_CHAR(d.visit_date, 'YYYY-MM-DD') AS visit_date
|
||||||
|
,NVL(COUNT(wrl.DATETIME), 0) AS visit_count
|
||||||
|
FROM (SELECT TRUNC(TO_DATE(#{chartDate})) - LEVEL + 1 AS visit_date
|
||||||
|
FROM DUAL
|
||||||
|
CONNECT BY LEVEL <![CDATA[<=]]> 10) d
|
||||||
|
LEFT JOIN WEB_REQUEST_LOG wrl ON wrl.DATETIME <![CDATA[>=]]> d.visit_date
|
||||||
|
AND wrl.DATETIME <![CDATA[<]]> d.visit_date + 1
|
||||||
|
AND EXISTS (SELECT 1
|
||||||
|
FROM WEB_MEMBER_IN WMI
|
||||||
|
WHERE WMI.USERID = wrl.USERID
|
||||||
|
AND WMI.CLS = 2)
|
||||||
|
GROUP BY d.visit_date
|
||||||
|
ORDER BY d.visit_date
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="findProjectMasterCompanyNameByUserid" parameterType="String" resultType="String">
|
<select id="findProjectMasterCompanyNameByUserid" parameterType="String" resultType="String">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
SELECT
|
SELECT
|
||||||
|
|
|
||||||
|
|
@ -7,75 +7,105 @@
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
<script src="${pageContext.request.contextPath}/js/jquery/jquery-1.10.2.min.js"></script>
|
<script src="${pageContext.request.contextPath}/js/jquery/jquery-1.10.2.min.js"></script>
|
||||||
|
<!-- Bootstrap Datepicker -->
|
||||||
|
<link rel="stylesheet" href="${pageContext.request.contextPath}/js/bootstrap-datepicker-1.9.0-dist/css/bootstrap-datepicker.min.css">
|
||||||
|
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap-datepicker-1.9.0-dist/js/bootstrap-datepicker.min.js"></script>
|
||||||
|
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap-datepicker-1.9.0-dist/locales/bootstrap-datepicker.ko.min.js"></script>
|
||||||
|
|
||||||
|
<!-- MUI + Chart.js + jQuery -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
<script src="${pageContext.request.contextPath}/js/admins/common.js"></script>
|
<script src="${pageContext.request.contextPath}/js/admins/common.js"></script>
|
||||||
<link rel="stylesheet" HREF="${pageContext.request.contextPath}/css/admins/style.css" type="text/css">
|
<link rel="stylesheet" HREF="${pageContext.request.contextPath}/css/admins/style.css" type="text/css">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.datepicker-wrapper > * {
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
.datepicker-wrapper .date-next,
|
||||||
|
.datepicker-wrapper .date-prev {
|
||||||
|
border: 1px solid #4285f4;
|
||||||
|
height: 18px;
|
||||||
|
line-height: 18px;
|
||||||
|
padding: 0 2px;
|
||||||
|
margin-right: 1px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: #ecf3fe;
|
||||||
|
color: #337bed;
|
||||||
|
transition: .3s;
|
||||||
|
}
|
||||||
|
.date-prev:hover, .date-next:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background: #337bed;
|
||||||
|
color: #ecf3fe;
|
||||||
|
}
|
||||||
|
.title-container, .chart-container {
|
||||||
|
background: #fff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
||||||
|
padding: 20px; margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown {
|
||||||
|
z-index: 99999 !important;
|
||||||
|
position: absolute;
|
||||||
|
left: 0 !important;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #e6e6e6;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<script>
|
<script>
|
||||||
|
// --------- 일일 접속량 차트 관련 변수 --------------------
|
||||||
|
let trafficChart; // 전역 변수
|
||||||
|
// --------- 일일 접속량 차트 관련 변수 --------------------
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
var searchTitle = document.getElementById('searchTitle');
|
// ----------------------------------------------------
|
||||||
var searchValue = document.getElementById('searchValue');
|
// 1. 날짜 선택기 초기화
|
||||||
var searchContainer = searchValue.parentNode;
|
// ----------------------------------------------------
|
||||||
var tildeText = document.createElement('span');
|
|
||||||
tildeText.innerHTML = '~';
|
|
||||||
var searchBgndt = document.createElement('input');
|
|
||||||
var searchEnddt = document.createElement('input');
|
|
||||||
|
|
||||||
function createInput(input, id) {
|
// datepicker
|
||||||
input.type = 'text';
|
$("#chartDate, #count_from_dt, #count_to_dt").datepicker({
|
||||||
input.id = id;
|
format: "yyyy-mm-dd",
|
||||||
input.name = id;
|
language: "ko",
|
||||||
input.className = 'search';
|
autoclose: true,
|
||||||
input.style.display = 'inline-block';
|
todayHighlight: true,
|
||||||
input.style.width = '12ch';
|
container: 'body'
|
||||||
input.placeholder = 'YYYYMMDD';
|
}).datepicker("setDate", new Date());
|
||||||
input.style.color = '#000'; // Text color
|
|
||||||
input.maxLength = 8; // Limit input length
|
|
||||||
input.onfocus = function() {
|
|
||||||
this.placeholder = '';
|
|
||||||
this.style.color = '#000'; // Text color
|
|
||||||
};
|
|
||||||
input.onblur = function() {
|
|
||||||
if (this.value === '') {
|
|
||||||
this.placeholder = 'YYYYMMDD';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
createInput(searchBgndt, 'searchBgndt');
|
// 페이지 로드시 차트 먼저 로드
|
||||||
createInput(searchEnddt, 'searchEnddt');
|
getMgmtApiChart();
|
||||||
searchBgndt.style.marginRight = '2px';
|
|
||||||
searchEnddt.style.marginLeft = '2px';
|
|
||||||
searchBgndt.value = "${params.searchBgndt}";
|
|
||||||
searchEnddt.value = "${params.searchEnddt}";
|
|
||||||
|
|
||||||
function addInputs() {
|
// 날짜 변경 시 차트 다시 로드
|
||||||
searchValue.style.display = 'none';
|
$(document).on('change', '#chartDate', function() {
|
||||||
searchContainer.insertBefore(searchBgndt, searchValue);
|
getMgmtApiChart();
|
||||||
searchContainer.insertBefore(tildeText, searchValue);
|
|
||||||
searchContainer.insertBefore(searchEnddt, searchValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeInputs() {
|
|
||||||
if (document.getElementById('searchBgndt')) {
|
|
||||||
searchBgndt.remove();
|
|
||||||
tildeText.remove();
|
|
||||||
searchEnddt.remove();
|
|
||||||
}
|
|
||||||
searchValue.style.display = 'inline-block';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchTitle.value == '7') {
|
|
||||||
addInputs();
|
|
||||||
}
|
|
||||||
|
|
||||||
searchTitle.addEventListener('change', function() {
|
|
||||||
if (this.value == '7') {
|
|
||||||
addInputs();
|
|
||||||
} else {
|
|
||||||
removeInputs();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
|
// <> 버튼으로 날짜 변경
|
||||||
|
$(document).on('click', '.date-prev, .date-next', function() {
|
||||||
|
const $input = $('#chartDate');
|
||||||
|
|
||||||
|
// 현재 날짜 가져오기 (yyyy-mm-dd)
|
||||||
|
const currentVal = $input.val();
|
||||||
|
if (!currentVal) return;
|
||||||
|
|
||||||
|
// 문자열 → Date 객체
|
||||||
|
const dateParts = currentVal.split('-');
|
||||||
|
const currentDate = new Date(
|
||||||
|
dateParts[0],
|
||||||
|
dateParts[1] - 1,
|
||||||
|
dateParts[2]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 이전 / 다음 구분
|
||||||
|
if ($(this).hasClass('date-prev')) {
|
||||||
|
currentDate.setDate(currentDate.getDate() - 10);
|
||||||
|
} else {
|
||||||
|
currentDate.setDate(currentDate.getDate() + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// datepicker 날짜 변경 (이게 핵심)
|
||||||
|
$input.datepicker('setDate', currentDate);
|
||||||
|
|
||||||
|
// setDate 하면 change 이벤트가 자동으로 발생함
|
||||||
|
});
|
||||||
|
})
|
||||||
var context = "${pageContext.request.contextPath}";
|
var context = "${pageContext.request.contextPath}";
|
||||||
|
|
||||||
function linkPage(index){
|
function linkPage(index){
|
||||||
|
|
@ -83,21 +113,70 @@ function linkPage(index){
|
||||||
$("#searchForm").attr("action", "${pageContext.request.contextPath}/admins/user/02.do").submit();
|
$("#searchForm").attr("action", "${pageContext.request.contextPath}/admins/user/02.do").submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* function excelDownload(){
|
// API 호출 로그 목록 조회
|
||||||
$("#searchForm").attr("action", "${pageContext.request.contextPath}/admins/user/02_excel.do").submit();
|
function getMgmtApiChart(){
|
||||||
$("#searchForm").attr("action", "${pageContext.request.contextPath}/admins/user/02.do");
|
var chartDate = $('#chartDate').val();
|
||||||
|
$.ajax({
|
||||||
|
type : "POST",
|
||||||
|
url : "/admins/constructionProjectManagement/o_charts.do" ,
|
||||||
|
data : {chartDate: $('#chartDate').val()},
|
||||||
|
dataType :"json",
|
||||||
|
success : function(res){ // res.code, res.msg, res.data
|
||||||
|
if (res.code == "SUCCESS") {
|
||||||
|
const labels = res.data.map(d => d.visitDate.substring(5));
|
||||||
|
const data = res.data.map(d => d.visitCount);
|
||||||
|
drawTrafficChart(labels, data);
|
||||||
|
} else {
|
||||||
|
alert("API 호출 로그 목록 조회중 오류가 발생하였습니다. 다시 시도해주세요.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error : function(response){
|
||||||
|
alert("API 호출 로그 목록 조회중 내부 오류가 발생하였습니다. 다시 시도해주세요.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Chart.js: 일일 접속량
|
||||||
|
function drawTrafficChart(labels, dataArr) {
|
||||||
|
const ctx = document.getElementById('trafficChart').getContext('2d');
|
||||||
|
|
||||||
|
// 이미 차트가 있으면 갱신
|
||||||
|
if (trafficChart) {
|
||||||
|
trafficChart.data.labels = labels;
|
||||||
|
trafficChart.data.datasets[0].data = dataArr;
|
||||||
|
trafficChart.update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 최초 생성
|
||||||
|
trafficChart = new Chart(ctx, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [{
|
||||||
|
data: dataArr,
|
||||||
|
borderColor: '#4285f4',
|
||||||
|
backgroundColor: 'rgba(66,133,244,0.1)',
|
||||||
|
tension: 0.4,
|
||||||
|
fill: true,
|
||||||
|
pointRadius: 3
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
plugins: {
|
||||||
|
legend: { display: false }
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
beginAtZero: true,
|
||||||
|
ticks: { stepSize: 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
$(function(){
|
|
||||||
var searchTitle = "${params.searchTitle}";
|
|
||||||
searchTitle = searchTitle == "" ? "0" : searchTitle;
|
|
||||||
$("#searchTitle").val(searchTitle);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// 엑셀 다운로드
|
||||||
|
function clickExcelDownload(){
|
||||||
// 엑셀 다운로드
|
|
||||||
function clickExcelDownload(){
|
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
params.append("constTag", "");
|
params.append("constTag", "");
|
||||||
|
|
@ -119,7 +198,7 @@ $(function(){
|
||||||
// AJAX가 아닌 직접 다운로드 요청
|
// AJAX가 아닌 직접 다운로드 요청
|
||||||
window.location.href = "/admins/constructionProjectManagement/excel.do?" + params.toString();
|
window.location.href = "/admins/constructionProjectManagement/excel.do?" + params.toString();
|
||||||
$('#excelDownload').val("");
|
$('#excelDownload').val("");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -128,10 +207,21 @@ $(function(){
|
||||||
<input type="hidden" id="cls" name="cls" value="2" />
|
<input type="hidden" id="cls" name="cls" value="2" />
|
||||||
<table id="Table_Main" width="100%" border="0" cellpadding="0" cellspacing="0">
|
<table id="Table_Main" width="100%" border="0" cellpadding="0" cellspacing="0">
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan=2><div style="background: #fff; border-radius: 12px; padding: 5px 10px;
|
<td colspan=2><div class="title-container" style="padding: 5px 10px;"><h3>발주기관 로그인 내역</h3></div></td>
|
||||||
box-shadow: 0 2px 8px rgba(0,0,0,0.05);"><h3>발주기관 로그인 내역</h3></div></td>
|
</tr>
|
||||||
|
<tr height=20 colspan=2>
|
||||||
|
<td>
|
||||||
|
<div class="chart-container">
|
||||||
|
<div class="datepicker-wrapper" style="position: relative;display: flex;align-items: center;">
|
||||||
|
<h3>📈 일별 접속량</h3>
|
||||||
|
<input type="text" name="chartDate" id="chartDate" class="input" placeholder="클릭하여 날짜 선택">
|
||||||
|
<div class="date-prev"> <</div>
|
||||||
|
<div class="date-next"> ></div>
|
||||||
|
</div>
|
||||||
|
<canvas id="trafficChart" height="100"></canvas>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr height=20 colspan=2><td> </td></tr>
|
|
||||||
<%-- <tr height=25>
|
<%-- <tr height=25>
|
||||||
<!-- START : 엑셀 다운로드 ------------------------------------------------------------------------->
|
<!-- START : 엑셀 다운로드 ------------------------------------------------------------------------->
|
||||||
<td>
|
<td>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue