[관리자]건설현장관리>발주기관 로그인 내역 : 발주기관 별로 접속량 표시 쿼리

main
유지인 2026-02-13 13:24:36 +09:00
parent 61be76c392
commit 15a58a9c3b
7 changed files with 373 additions and 34 deletions

View File

@ -1005,7 +1005,7 @@ public class ConstructionProjectManagementController {
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/constructionProjectManagement/o_charts.do", method = RequestMethod.POST)
@RequestMapping(value = "/admins/constructionProjectManagement/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>();
@ -1020,6 +1020,33 @@ public class ConstructionProjectManagementController {
return result;
}
/**
* API >
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
* selectUserLoginHistoryChartByMasterCompany
*/
@ResponseBody
@RequestMapping(value = "/admins/constMastComLoginHis/charts.do", method = RequestMethod.POST)
public HashMap<String, Object> getMgmtConstMastComLoginHistoryChart(@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.selectUserLoginHistoryChartByMasterCompany(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 {
List<?> selectInfoListExcel = (List<?>) model.get("selectInfoListExcel");

View File

@ -56,6 +56,8 @@ public interface GeneralUserMngMapper {
public List<EgovMap> selectUserLoginHistoryChart(HashMap<String, Object> params) throws Exception;
public List<EgovMap> selectUserLoginHistoryChartByMasterCompany(HashMap<String, Object> params) throws Exception;
String findProjectMasterCompanyNameByUserid(String userId);
List<EgovMap> getUserGDisList(HashMap<String, Object> params) throws Exception;

View File

@ -54,6 +54,8 @@ public interface GeneralUserMngService {
public List<EgovMap> selectUserLoginHistoryChart(HashMap<String, Object> params) throws Exception;
public List<EgovMap> selectUserLoginHistoryChartByMasterCompany(HashMap<String, Object> params) throws Exception;
public List<EgovMap> getUserGDisList(HashMap<String, Object> params) throws Exception;
}

View File

@ -133,6 +133,11 @@ public class GeneralUserMngServiceImpl implements GeneralUserMngService {
return masterMapper.selectUserLoginHistoryChart(params);
}
@Override
public List<EgovMap> selectUserLoginHistoryChartByMasterCompany(HashMap<String, Object> params) throws Exception {
return masterMapper.selectUserLoginHistoryChartByMasterCompany(params);
}
@Override
public List<EgovMap> getUserGDisList(HashMap<String, Object> params) throws Exception {
return masterMapper.getUserGDisList(params);

View File

@ -486,18 +486,6 @@
</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
@ -513,6 +501,51 @@
ORDER BY d.visit_date
</select>
<select id="selectUserLoginHistoryChartByMasterCompany" parameterType="map" resultType="egovMap">
SELECT TO_CHAR(d.visit_date, 'YYYY-MM-DD') AS visit_date
,mc.COM_CODE AS company_code
,mc.COM_NAME AS company_namAe
,COUNT(wrl.USERID) AS visit_count
-- 날짜 생성
FROM (SELECT TRUNC(TO_DATE(#{chartDate}, 'YYYY-MM'), 'MM') + LEVEL - 1 AS visit_date
FROM DUAL
CONNECT BY LEVEL <![CDATA[<=]]> TO_NUMBER(TO_CHAR(LAST_DAY(TO_DATE(#{chartDate}, 'YYYY-MM')), 'DD'))
) d
-- 기관 생성
CROSS JOIN (SELECT DISTINCT PROJECT_MASTER_COMPANY_CODE AS COM_CODE
FROM WEB_MEMBER_IN
WHERE CLS = '2'
--AND PROJECT_MASTER_COMPANY_CODE IN ('630', '722', '610', '723', '588', '025')
<if test="type!= null and type == 'master'">
AND PROJECT_MASTER_COMPANY_CODE IN (SELECT (COM_CODE)
FROM TBL_MASTER_COMPANY
WHERE COM_NAME IN (SELECT GS_DISTRICT_NAME
FROM TBL_GS_DISTRICT
WHERE gl_code = '01' and gm_code = '01' ))
</if>
<if test="type!= null and type == 'sub'">
AND PROJECT_MASTER_COMPANY_CODE IN (SELECT (COM_CODE)
FROM TBL_MASTER_COMPANY
WHERE COM_NAME IN (SELECT GS_DISTRICT_NAME
FROM TBL_GS_DISTRICT
WHERE gl_code = '01' and gm_code = '02' ))
</if>
) c
-- 발주처 매핑
JOIN TBL_MASTER_COMPANY mc ON mc.COM_CODE = c.COM_CODE
-- 회원정보의 발주처코드와 발주처정보 테이블 join
LEFT JOIN WEB_MEMBER_IN wmi ON wmi.PROJECT_MASTER_COMPANY_CODE = mc.COM_CODE
AND wmi.CLS = '2'
-- 접속로그 정보의 userid와 회원테이블 join
LEFT JOIN WEB_REQUEST_LOG wrl ON wrl.USERID = wmi.USERID
AND wrl.DATETIME <![CDATA[>=]]> d.visit_date
AND wrl.DATETIME <![CDATA[<]]> d.visit_date + 1
group BY d.visit_date, mc.COM_CODE, mc.COM_NAME
ORDER BY d.visit_date, mc.COM_CODE
</select>
<select id="findProjectMasterCompanyNameByUserid" parameterType="String" resultType="String">
<![CDATA[
SELECT

View File

@ -100,7 +100,7 @@
// (4) 하단 전체 기관 등록 건수 차트 갱신
// (4)-1 하단 국토부 소속 기관 등록 건수 차트 갱신
var gm01List = data.institutionStats.filter(function(stat) {
return stat.gm === "01";
return stat.gm === "01" && stat.name != "국토교통부 부산지방국토관리청";
});
// (4)-2 하단 국토부 산하 기관 등록 건수 차트 갱신
@ -109,8 +109,8 @@
});
// 각각 차트 생성
updateInstitutionChart('institutionChart_gm01', gm01List, '지방국토관리청 등록 현황');
updateInstitutionChart('institutionChart_gm02', gm02List, '산하기관 등록 현황');
updateInstitutionChart('institutionChart_gm01', gm01List, '');
updateInstitutionChart('institutionChart_gm02', gm02List, '');
}
// [상단] 전체 단계별 차트
@ -293,9 +293,35 @@
legend: { display: false },
title: { display: true, text: title }
}
}
},
plugins: [barValuePlugin] // 👈 이거 추가
});
}
const barValuePlugin = {
id: 'barValuePlugin',
afterDatasetsDraw(chart, args, options) {
const { ctx } = chart;
chart.data.datasets.forEach((dataset, datasetIndex) => {
const meta = chart.getDatasetMeta(datasetIndex);
meta.data.forEach((bar, index) => {
const value = dataset.data[index];
if (value === null || value === undefined) return;
ctx.save();
ctx.fillStyle = '#333';
ctx.font = '12px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.fillText(value, bar.x, bar.y - 5);
ctx.restore();
});
});
}
};
</script>
</head>

View File

@ -53,6 +53,8 @@
<script>
// --------- 일일 접속량 차트 관련 변수 --------------------
let trafficChart; // 전역 변수
let mastComTrafficChart; // 전역 변수
let subComTrafficChart; // 전역 변수
// --------- 일일 접속량 차트 관련 변수 --------------------
document.addEventListener('DOMContentLoaded', function() {
@ -61,7 +63,7 @@ document.addEventListener('DOMContentLoaded', function() {
// ----------------------------------------------------
// datepicker
$("#chartDate, #count_from_dt, #count_to_dt").datepicker({
$("#chartDate").datepicker({
format: "yyyy-mm-dd",
language: "ko",
autoclose: true,
@ -69,16 +71,38 @@ document.addEventListener('DOMContentLoaded', function() {
container: 'body'
}).datepicker("setDate", new Date());
// 페이지 로드시 차트 먼저 로드
getMgmtApiChart();
$("#chartDateGl01, #chartDateGl02").datepicker({
format: "yyyy-mm",
language: "ko",
autoclose: true,
todayHighlight: true,
startView: 1, // ⭐ 월 뷰로 시작
minViewMode: 1, // ⭐ 월 단위 선택
container: 'body'
}).datepicker("setDate", new Date());
// 날짜 변경 시 차트 다시 로드
// 페이지 로드시 차트 먼저 로드
getMgmtConstLoginChart();
getMgmtConstComLoginHistoryChart('master'); // 소속기관
getMgmtConstComLoginHistoryChart('sub'); // 산하기관
// 날짜 변경 시 차트 다시 로드 - 일일접속량
$(document).on('change', '#chartDate', function() {
getMgmtApiChart();
getMgmtConstLoginChart();
});
// 날짜 변경 시 차트 다시 로드 - 국토부 소속기관 일일접속량
$(document).on('change', '#chartDateGl01', function() {
getMgmtConstComLoginHistoryChart('master');
});
// 날짜 변경 시 차트 다시 로드 - 국토부 산하기관 일일접속량
$(document).on('change', '#chartDateGl02', function() {
getMgmtConstComLoginHistoryChart('sub');
});
// <> 버튼으로 날짜 변경
$(document).on('click', '.date-prev, .date-next', function() {
$('.chart-container').on('click', '.date-prev, .date-next', function() {
const $input = $('#chartDate');
// 현재 날짜 가져오기 (yyyy-mm-dd)
@ -100,10 +124,34 @@ document.addEventListener('DOMContentLoaded', function() {
currentDate.setDate(currentDate.getDate() + 10);
}
// datepicker 날짜 변경 (이게 핵심)
$input.datepicker('setDate', currentDate);
});
// <> 버튼으로 날짜 변경
$('.chart-container-gl01, .chart-container-gl02').on('click', '.date-prev, .date-next', function(e) {
// setDate 하면 change 이벤트가 자동으로 발생함
let container = $(e.target).parents('.datepicker-wrapper').parents('div').attr('class'); // 'chart-container-gl01' 또는 'chart-container-gl02'
let $input = $('#chartDateGl01');
if (container.includes('gl02')) $input = $('#chartDateGl02');
// 현재 날짜 가져오기 (yyyy-mm-dd)
let currentVal = $input.val();
if (!currentVal) return;
// 문자열 → Date 객체
let dateParts = currentVal.split('-');
let currentDate = new Date(
dateParts[0],
dateParts[1] - 1,
);
// 이전 / 다음 구분
if ($(this).hasClass('date-prev')) {
currentDate.setMonth(currentDate.getMonth() -1 );
} else {
currentDate.setMonth(currentDate.getMonth() + 1);
}
$input.datepicker('setDate', currentDate);
});
})
var context = "${pageContext.request.contextPath}";
@ -113,12 +161,12 @@ function linkPage(index){
$("#searchForm").attr("action", "${pageContext.request.contextPath}/admins/user/02.do").submit();
}
// API 호출 로그 목록 조회
function getMgmtApiChart(){
// 일일접속량 그래프데이터
function getMgmtConstLoginChart(){
var chartDate = $('#chartDate').val();
$.ajax({
type : "POST",
url : "/admins/constructionProjectManagement/o_charts.do" ,
url : "/admins/constructionProjectManagement/charts.do" ,
data : {chartDate: $('#chartDate').val()},
dataType :"json",
success : function(res){ // res.code, res.msg, res.data
@ -127,17 +175,110 @@ function getMgmtApiChart(){
const data = res.data.map(d => d.visitCount);
drawTrafficChart(labels, data);
} else {
alert("API 호출 로그 목록 조회중 오류가 발생하였습니다. 다시 시도해주세요.");
alert("일일접속량 조회중 오류가 발생하였습니다. 다시 시도해주세요.");
}
},
error : function(response){
alert("API 호출 로그 목록 조회중 내부 오류가 발생하였습니다. 다시 시도해주세요.");
alert("일일접속량 조회중 내부 오류가 발생하였습니다. 다시 시도해주세요.");
}
});
}
// 소속기관 일일접속량 그래프 데이터
function getMgmtConstComLoginHistoryChart(type){
var chartDate = $('#chartDateGl01').val();
if (type == 'sub') {
chartDate = $('#chartDateGl02').val();
}
$.ajax({
type : "POST",
url : "/admins/constMastComLoginHis/charts.do" ,
data : {
chartDate: chartDate,
type: type
},
dataType :"json",
success : function(res){ // res.code, res.msg, res.data
if (res.code !== "SUCCESS") {
alert("소속기관 일일접속량 조회중 오류가 발생하였습니다.");
return;
}
const raw = res.data;
// 1⃣ YYYY-MM-DD 기준 날짜 목록 (중복 제거)
const fullDates = [...new Set(
raw.map(d => d.visitDate)
)].sort();
// 2⃣ 화면 표시용 MM-DD 라벨
const labels = fullDates.map(date =>
date.substring(5)
);
// 3⃣ 기관별 그룹핑
const companyMap = {};
raw.forEach(item => {
if (!companyMap[item.companyCode]) {
companyMap[item.companyCode] = {
label: item.companyNamae,
data: {}
};
}
companyMap[item.companyCode].data[item.visitDate] = item.visitCount;
});
// 4⃣ 색상 배열
const colors = [
'#4285F4',
'#EA4335',
'#FBBC05',
'#34A853',
'#8E24AA',
'#FF6D00'
];
let colorIndex = 0;
// 5⃣ Chart.js datasets 생성
const datasets = Object.values(companyMap).map(company => {
const dataArr = fullDates.map(date =>
company.data[date] ?? 0
);
return {
label: company.label,
data: dataArr,
borderColor: colors[colorIndex++ % colors.length],
backgroundColor: 'transparent',
tension: 0,
pointRadius: 3
};
});
// 전체 표시/해제 처리를 위함
datasets.unshift({
label: '전체',
data: [],
borderColor: 'transparent'
});
// 6⃣ 차트 그리기
drawMultiLineChart(labels, datasets, type);
},
error : function(response){
alert("소속기관 일일접속량 조회중 내부 오류가 발생하였습니다. 다시 시도해주세요.");
}
});
}
// Chart.js: 일일 접속량
function drawTrafficChart(labels, dataArr) {
const ctx = document.getElementById('trafficChart').getContext('2d');
let ctx = document.getElementById('trafficChart').getContext('2d');
// 이미 차트가 있으면 갱신
if (trafficChart) {
@ -175,6 +316,83 @@ function drawTrafficChart(labels, dataArr) {
});
}
function drawMultiLineChart(labels, datasets, type){
let chartInstance;
let ctx;
if (type === "master") {
ctx = document.getElementById('mastComTrafficChart').getContext('2d');
chartInstance = mastComTrafficChart;
} else {
ctx = document.getElementById('subComTrafficChart').getContext('2d');
chartInstance = subComTrafficChart;
}
// ✅ 이미 차트가 있으면 데이터만 업데이트
if (chartInstance) {
chartInstance.data.labels = labels;
chartInstance.data.datasets = datasets;
chartInstance.update();
return;
}
// ✅ 새로 생성
const newChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: datasets
},
options: {
responsive: true,
plugins: {
legend: {
display: true,
position: 'top',
labels: {
usePointStyle: true,
pointStyle: 'line'
},
onClick: function(e, legendItem, legend) {
const chart = legend.chart;
if (legendItem.text === '전체') {
const anyVisible = chart.data.datasets.some((_, i) =>
chart.isDatasetVisible(i)
);
chart.data.datasets.forEach((_, i) => {
chart.setDatasetVisibility(i, !anyVisible);
});
chart.update();
return;
}
Chart.defaults.plugins.legend.onClick(e, legendItem, legend);
}
}
},
scales: {
y: {
beginAtZero: true,
ticks: { stepSize: 1 }
}
}
}
});
// 전역 변수에 다시 저장
if (type === "master") {
mastComTrafficChart = newChart;
} else {
subComTrafficChart = newChart;
}
}
// 엑셀 다운로드
function clickExcelDownload(){
const params = new URLSearchParams();
@ -218,7 +436,33 @@ function clickExcelDownload(){
<div class="date-prev"> &lt;</div>
<div class="date-next"> &gt;</div>
</div>
<canvas id="trafficChart" height="100"></canvas>
<canvas id="trafficChart" height="40"></canvas>
</div>
</td>
</tr>
<tr height=20 colspan=2>
<td>
<div class="chart-container-gl01">
<div class="datepicker-wrapper" style="position: relative;display: flex;align-items: center;">
<h3>📈 소속기관 일별 접속량</h3>
<input type="text" name="chartDateGl01" id="chartDateGl01" class="input" placeholder="클릭하여 날짜 선택">
<div class="date-prev"> &lt;</div>
<div class="date-next"> &gt;</div>
</div>
<canvas id="mastComTrafficChart" height="40"></canvas>
</div>
</td>
</tr>
<tr height=20 colspan=2>
<td>
<div class="chart-container-gl02">
<div class="datepicker-wrapper" style="position: relative;display: flex;align-items: center;">
<h3>📈 산하기관 일별 접속량</h3>
<input type="text" name="chartDateGl02" id="chartDateGl02" class="input" placeholder="클릭하여 날짜 선택">
<div class="date-prev"> &lt;</div>
<div class="date-next"> &gt;</div>
</div>
<canvas id="subComTrafficChart" height="40"></canvas>
</div>
</td>
</tr>