API 외부데이타 통계 화면 추가

API 호출 건수 통계 추가(일별, 월별, 연도별)
main
유지인 2025-11-12 18:08:08 +09:00
parent fda6f024e3
commit 36a47a44c9
19 changed files with 1786 additions and 295 deletions

View File

@ -15,16 +15,16 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import egovframework.rte.psl.dataaccess.util.EgovMap;
import geoinfo.admins.apiManagement.service.ApiManagementService;
import geoinfo.admins.apiManagement.service.ApiInDataManagementService;
import geoinfo.comm.util.strUtil;
import geoinfo.session.UserInfo;
@Controller
public class ApiManagementController {
@Resource(name = "apiManagementService")
private ApiManagementService apiManagementService;
public class ApiInDataManagementController {
@Resource(name = "apiInDataManagementService")
private ApiInDataManagementService apiInDataManagementService;
/**
* API > API
@ -62,7 +62,7 @@ public class ApiManagementController {
HashMap<String, Object> result = new HashMap<String, Object>();
String CHART_DATE = sUtil.checkNull((String)params.get("chartDate"));
params.put("CHART_DATE", CHART_DATE);
EgovMap chartData = apiManagementService.selectDailyAccessCountByHour(params);
EgovMap chartData = apiInDataManagementService.selectDailyAccessCountByHour(params);
result.put("code", "SUCCESS");
result.put("msg", "일일접속량 데이터 조회를 성공했습니다.");
@ -85,7 +85,7 @@ public class ApiManagementController {
public HashMap<String, Object> getMgmtApiList(@RequestParam HashMap<String, Object> params, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
HashMap<String, Object> result = new HashMap<String, Object>();
List<?> listData = apiManagementService.selectInfo(params);
List<?> listData = apiInDataManagementService.selectInfo(params);
result.put("code", "SUCCESS");
result.put("msg", "관리 API 목록 조회를 성공했습니다.");
@ -117,9 +117,9 @@ public class ApiManagementController {
params.put("idxArr", idxArr);
params.put("activeYn", activeYn);
apiManagementService.updateInfoStatus(params);
apiInDataManagementService.updateInfoStatus(params);
List<?> listData = apiManagementService.selectInfo(params);
List<?> listData = apiInDataManagementService.selectInfo(params);
result.put("code", "SUCCESS");
result.put("msg", "관리 API 목록 조회를 성공했습니다.");
@ -142,7 +142,7 @@ public class ApiManagementController {
public HashMap<String, Object> getMgmtApiLogList(@RequestParam HashMap<String, Object> params, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
HashMap<String, Object> result = new HashMap<String, Object>();
List<?> listData = apiManagementService.selectWebApiLogList(params);
List<?> listData = apiInDataManagementService.selectWebApiLogList(params);
result.put("code", "SUCCESS");
result.put("msg", "API 호출 로그 목록 조회를 성공했습니다.");
@ -150,106 +150,5 @@ public class ApiManagementController {
return result;
}
/**
* API > API
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@RequestMapping(value = "admins/mgmtApi/mgmt-api-key.do")
public String goMgmtApiKey(@RequestParam HashMap<String, Object> params, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
if (!UserInfo.isValidSession(request, response, "admin")) {
return "";
}
model.addAttribute("params", params);
return "admins/mgmtApi/mgmt-api-key";
}
/**
* API > API
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/mgmtApiKey/list.do", method = RequestMethod.POST)
public HashMap<String, Object> getMgmtApiKeyList(@RequestParam HashMap<String, Object> params, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
HashMap<String, Object> result = new HashMap<String, Object>();
List<?> listData = apiManagementService.selectWebApiKeyList(params);
result.put("code", "SUCCESS");
result.put("msg", "API 신청 목록 조회를 성공했습니다.");
result.put("data", listData);
return result;
}
/**
* API > API
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/mgmtApiKey/approve.do", method = RequestMethod.POST)
public HashMap<String, Object> modMgmtApiKeyApprove(@RequestParam(value="apiSeq") int apiSeq, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
HashMap<String, Object> result = new HashMap<String, Object>();
HashMap<String,Object> params = new HashMap<>();
params.put("apiSeq", apiSeq);
params.put("approveYn", "Y");
apiManagementService.updateWebApiKeyApprove(params);
List<?> listData = apiManagementService.selectWebApiKeyList(params);
result.put("code", "SUCCESS");
result.put("msg", " API 신청 목록 조회를 성공했습니다.");
result.put("data", listData);
return result;
}
/**
* API > API .
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/mgmtApiKey/revoke.do", method = RequestMethod.POST)
public HashMap<String, Object> modMgmtApiKeyRevoke(@RequestParam(value="apiSeq") int apiSeq, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
HashMap<String, Object> result = new HashMap<String, Object>();
HashMap<String,Object> params = new HashMap<>();
params.put("apiSeq", apiSeq);
apiManagementService.deleteWebApiKey(params);
List<?> listData = apiManagementService.selectWebApiKeyList(params);
result.put("code", "SUCCESS");
result.put("msg", " API 신청 목록 조회를 성공했습니다.");
result.put("data", listData);
return result;
}
}

View File

@ -0,0 +1,130 @@
package geoinfo.admins.apiManagement;
import java.util.HashMap;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import egovframework.rte.psl.dataaccess.util.EgovMap;
import geoinfo.admins.apiManagement.service.ApiKeyManagementService;
import geoinfo.comm.util.strUtil;
import geoinfo.session.UserInfo;
@Controller
public class ApiKeyManagementController {
@Resource(name = "apiKeyManagementService")
private ApiKeyManagementService apiKeyManagementService;
/**
* API > API
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@RequestMapping(value = "admins/mgmtApi/mgmt-api-key.do")
public String goMgmtApiKey(@RequestParam HashMap<String, Object> params, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
if (!UserInfo.isValidSession(request, response, "admin")) {
return "";
}
model.addAttribute("params", params);
return "admins/mgmtApi/mgmt-api-key";
}
/**
* API > API
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/mgmtApiKey/list.do", method = RequestMethod.POST)
public HashMap<String, Object> getMgmtApiKeyList(@RequestParam HashMap<String, Object> params, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
HashMap<String, Object> result = new HashMap<String, Object>();
List<?> listData = apiKeyManagementService.selectWebApiKeyList(params);
result.put("code", "SUCCESS");
result.put("msg", "API 신청 목록 조회를 성공했습니다.");
result.put("data", listData);
return result;
}
/**
* API > API
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/mgmtApiKey/approve.do", method = RequestMethod.POST)
public HashMap<String, Object> modMgmtApiKeyApprove(@RequestParam(value="apiSeq") int apiSeq, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
HashMap<String, Object> result = new HashMap<String, Object>();
HashMap<String,Object> params = new HashMap<>();
params.put("apiSeq", apiSeq);
params.put("approveYn", "Y");
apiKeyManagementService.updateWebApiKeyApprove(params);
List<?> listData = apiKeyManagementService.selectWebApiKeyList(params);
result.put("code", "SUCCESS");
result.put("msg", " API 신청 목록 조회를 성공했습니다.");
result.put("data", listData);
return result;
}
/**
* API > API .
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/mgmtApiKey/revoke.do", method = RequestMethod.POST)
public HashMap<String, Object> modMgmtApiKeyRevoke(@RequestParam(value="apiSeq") int apiSeq, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
HashMap<String, Object> result = new HashMap<String, Object>();
HashMap<String,Object> params = new HashMap<>();
params.put("apiSeq", apiSeq);
apiKeyManagementService.deleteWebApiKey(params);
List<?> listData = apiKeyManagementService.selectWebApiKeyList(params);
result.put("code", "SUCCESS");
result.put("msg", " API 신청 목록 조회를 성공했습니다.");
result.put("data", listData);
return result;
}
}

View File

@ -0,0 +1,192 @@
package geoinfo.admins.apiManagement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import egovframework.rte.psl.dataaccess.util.EgovMap;
import geoinfo.admins.apiManagement.service.ApiOutDataManagementService;
import geoinfo.comm.util.strUtil;
import geoinfo.session.UserInfo;
@Controller
public class ApiOutDataManagementController {
@Resource(name = "apiOutDataManagementService")
private ApiOutDataManagementService apiOutDataManagementService;
/**
* API > API ( )
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@RequestMapping(value = "admins/mgmtApi/mgmt-api-outdata.do")
public String goMgmtApiOutdata(@RequestParam HashMap<String, Object> params, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
if (!UserInfo.isValidSession(request, response, "admin")) {
return "";
}
model.addAttribute("params", params);
return "admins/mgmtApi/mgmt-api-outdata";
}
/**
* API >
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/mgmtApi/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);
EgovMap chartData = apiOutDataManagementService.selectDailyAccessCountByHour(params);
result.put("code", "SUCCESS");
result.put("msg", "일일접속량 데이터 조회를 성공했습니다.");
result.put("data", chartData);
return result;
}
/**
* API > API
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/mgmtApi/o_counts.do", method = RequestMethod.POST)
public HashMap<String, Object> getMgmtApiOutDataCounts(@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 STAT_TYPE = sUtil.checkNull((String)params.get("statType"));
String COUNT_FROM_DT = sUtil.checkNull((String)params.get("countFromDt"));
String COUNT_TO_DT = sUtil.checkNull((String)params.get("countToDt"));
params.put("COUNT_FROM_DT", COUNT_FROM_DT);
params.put("COUNT_TO_DT", COUNT_TO_DT);
List<?> countList = new ArrayList<>();
if("monthly".equals(STAT_TYPE)) {
countList = apiOutDataManagementService.selectWebApiLogMonthlyCount(params);
} else if("yearly".equals(STAT_TYPE)) {
countList = apiOutDataManagementService.selectWebApiLogYearlyCount(params);
} else { // daily(기본)
countList = apiOutDataManagementService.selectWebApiLogDailyCount(params);
}
result.put("code", "SUCCESS");
result.put("msg", "일일접속량 데이터 조회를 성공했습니다.");
result.put("data", countList);
return result;
}
/**
* API > API
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/mgmtApi/o_list.do", method = RequestMethod.POST)
public HashMap<String, Object> getMgmtApiOutDataList(@RequestParam HashMap<String, Object> params, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
HashMap<String, Object> result = new HashMap<String, Object>();
List<?> listData = apiOutDataManagementService.selectInfo(params);
result.put("code", "SUCCESS");
result.put("msg", "관리 API 목록 조회를 성공했습니다.");
result.put("data", listData);
return result;
}
/**
* API > API
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/mgmtApi/o_toggleSts.do", method = RequestMethod.POST)
public HashMap<String, Object> modMgmtApiOutDataActiveYn(
@RequestParam(value="idxArr") List<Integer> idxArr,
@RequestParam(value="activeYn", required=false) String activeYn, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
HashMap<String, Object> result = new HashMap<String, Object>();
// String sIdxArr[] = params.get("idx").toString().split(",");
System.out.println("idxArr = " + idxArr);
System.out.println("activeYn = " + activeYn);
HashMap<String,Object> params = new HashMap<>();
params.put("idxArr", idxArr);
params.put("activeYn", activeYn);
apiOutDataManagementService.updateInfoStatus(params);
List<?> listData = apiOutDataManagementService.selectInfo(params);
result.put("code", "SUCCESS");
result.put("msg", "관리 API 목록 조회를 성공했습니다.");
result.put("data", listData);
return result;
}
/**
* API > API
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/mgmtApi/o_logList.do", method = RequestMethod.POST)
public HashMap<String, Object> getMgmtApiOutDataLogList(@RequestParam HashMap<String, Object> params, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
HashMap<String, Object> result = new HashMap<String, Object>();
List<?> listData = apiOutDataManagementService.selectWebApiLogList(params);
result.put("code", "SUCCESS");
result.put("msg", "API 호출 로그 목록 조회를 성공했습니다.");
result.put("data", listData);
return result;
}
}

View File

@ -0,0 +1,21 @@
package geoinfo.admins.apiManagement.service;
import java.util.HashMap;
import java.util.List;
import egovframework.rte.psl.dataaccess.mapper.Mapper;
import egovframework.rte.psl.dataaccess.util.EgovMap;
@Mapper("apiInDataManagementMapper")
public interface ApiInDataManagementMapper {
public EgovMap selectDailyAccessCountByHour(HashMap<String, Object> params) throws Exception;
public List<?> selectInfo(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiLogList(HashMap<String, Object> params) throws Exception;
public void saveInfo(HashMap<String, Object> params) throws Exception;
public void updateInfoStatus(HashMap<String, Object> params) throws Exception;
}

View File

@ -0,0 +1,22 @@
package geoinfo.admins.apiManagement.service;
import java.util.HashMap;
import java.util.List;
import egovframework.rte.psl.dataaccess.util.EgovMap;
public interface ApiInDataManagementService {
public EgovMap selectDailyAccessCountByHour(HashMap<String, Object> params) throws Exception;
public List<?> selectInfo(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiLogList(HashMap<String, Object> params) throws Exception;
public void saveInfo(HashMap<String, Object> params) throws Exception;
public void updateInfoStatus(HashMap<String, Object> params) throws Exception;
}

View File

@ -0,0 +1,17 @@
package geoinfo.admins.apiManagement.service;
import java.util.HashMap;
import java.util.List;
import egovframework.rte.psl.dataaccess.mapper.Mapper;
import egovframework.rte.psl.dataaccess.util.EgovMap;
@Mapper("apiKeyManagementMapper")
public interface ApiKeyManagementMapper {
public List<?> selectWebApiKeyList(HashMap<String, Object> params) throws Exception;
public void updateWebApiKeyApprove(HashMap<String, Object> params) throws Exception;
public void deleteWebApiKey(HashMap<String, Object> params) throws Exception;
}

View File

@ -0,0 +1,17 @@
package geoinfo.admins.apiManagement.service;
import java.util.HashMap;
import java.util.List;
import egovframework.rte.psl.dataaccess.util.EgovMap;
public interface ApiKeyManagementService {
public List<?> selectWebApiKeyList(HashMap<String, Object> params) throws Exception;
public void updateWebApiKeyApprove(HashMap<String, Object> params) throws Exception;
public void deleteWebApiKey(HashMap<String, Object> params) throws Exception;
}

View File

@ -6,10 +6,16 @@ import java.util.List;
import egovframework.rte.psl.dataaccess.mapper.Mapper;
import egovframework.rte.psl.dataaccess.util.EgovMap;
@Mapper("ApiManagementMapper")
public interface ApiManagementMapper {
@Mapper("apiOutDataManagementMapper")
public interface ApiOutDataManagementMapper {
public EgovMap selectDailyAccessCountByHour(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiLogDailyCount(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiLogMonthlyCount(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiLogYearlyCount(HashMap<String, Object> params) throws Exception;
public List<?> selectInfo(HashMap<String, Object> params) throws Exception;
@ -17,17 +23,6 @@ public interface ApiManagementMapper {
public void saveInfo(HashMap<String, Object> params) throws Exception;
// public EgovMap selectDetailInfo(HashMap<String, Object> params) throws Exception;
// public void deleteInfo(HashMap<String, Object> params) throws Exception;
// public EgovMap selectModifyInfo(HashMap<String, Object> params) throws Exception;
public void updateInfoStatus(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiKeyList(HashMap<String, Object> params) throws Exception;
public void updateWebApiKeyApprove(HashMap<String, Object> params) throws Exception;
public void deleteWebApiKey(HashMap<String, Object> params) throws Exception;
}

View File

@ -7,27 +7,21 @@ import egovframework.rte.psl.dataaccess.util.EgovMap;
public interface ApiManagementService {
public interface ApiOutDataManagementService {
public EgovMap selectDailyAccessCountByHour(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiLogDailyCount(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiLogMonthlyCount(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiLogYearlyCount(HashMap<String, Object> params) throws Exception;
public List<?> selectInfo(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiLogList(HashMap<String, Object> params) throws Exception;
public void saveInfo(HashMap<String, Object> params) throws Exception;
// public EgovMap selectDetailInfo(HashMap<String, Object> params) throws Exception;
// public void deleteInfo(HashMap<String, Object> params) throws Exception;
// public EgovMap selectModifyInfo(HashMap<String, Object> params) throws Exception;
public void updateInfoStatus(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiKeyList(HashMap<String, Object> params) throws Exception;
public void updateWebApiKeyApprove(HashMap<String, Object> params) throws Exception;
public void deleteWebApiKey(HashMap<String, Object> params) throws Exception;
}

View File

@ -0,0 +1,45 @@
package geoinfo.admins.apiManagement.service.impl;
import java.util.HashMap;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import egovframework.rte.psl.dataaccess.util.EgovMap;
import geoinfo.admins.apiManagement.service.ApiInDataManagementMapper;
import geoinfo.admins.apiManagement.service.ApiInDataManagementService;
@Service("apiInDataManagementService")
public class ApiInDataManagementServiceImpl implements ApiInDataManagementService {
@Resource(name = "apiInDataManagementMapper")
private ApiInDataManagementMapper masterMapper;
@Override
public EgovMap selectDailyAccessCountByHour(HashMap<String, Object> params) throws Exception {
return masterMapper.selectDailyAccessCountByHour(params);
}
@Override
public List<?> selectInfo(HashMap<String, Object> params) throws Exception {
return masterMapper.selectInfo(params);
}
@Override
public List<?> selectWebApiLogList(HashMap<String, Object> params) throws Exception {
return masterMapper.selectWebApiLogList(params);
}
@Override
public void saveInfo(HashMap<String, Object> params) throws Exception {
masterMapper.saveInfo(params);
}
@Override
public void updateInfoStatus(HashMap<String, Object> params) throws Exception {
masterMapper.updateInfoStatus(params);
}
}

View File

@ -0,0 +1,35 @@
package geoinfo.admins.apiManagement.service.impl;
import java.util.HashMap;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import geoinfo.admins.apiManagement.service.ApiKeyManagementMapper;
import geoinfo.admins.apiManagement.service.ApiKeyManagementService;
@Service("apiKeyManagementService")
public class ApiKeyManagementServiceImpl implements ApiKeyManagementService {
@Resource(name = "apiKeyManagementMapper")
private ApiKeyManagementMapper masterMapper;
@Override
public List<?> selectWebApiKeyList(HashMap<String, Object> params) throws Exception {
return masterMapper.selectWebApiKeyList(params);
}
@Override
public void updateWebApiKeyApprove(HashMap<String, Object> params) throws Exception {
masterMapper.updateWebApiKeyApprove(params);
}
@Override
public void deleteWebApiKey(HashMap<String, Object> params) throws Exception {
masterMapper.deleteWebApiKey(params);
}
}

View File

@ -1,76 +0,0 @@
package geoinfo.admins.apiManagement.service.impl;
import java.util.HashMap;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import egovframework.rte.psl.dataaccess.util.EgovMap;
import geoinfo.admins.apiManagement.service.ApiManagementMapper;
import geoinfo.admins.apiManagement.service.ApiManagementService;
@Service("apiManagementService")
public class ApiManagementServiceImpl implements ApiManagementService {
@Resource(name = "ApiManagementMapper")
private ApiManagementMapper masterMapper;
@Override
public EgovMap selectDailyAccessCountByHour(HashMap<String, Object> params) throws Exception {
return masterMapper.selectDailyAccessCountByHour(params);
}
@Override
public List<?> selectInfo(HashMap<String, Object> params) throws Exception {
return masterMapper.selectInfo(params);
}
@Override
public List<?> selectWebApiLogList(HashMap<String, Object> params) throws Exception {
return masterMapper.selectWebApiLogList(params);
}
@Override
public void saveInfo(HashMap<String, Object> params) throws Exception {
masterMapper.saveInfo(params);
}
// @Override
// public EgovMap selectDetailInfo(HashMap<String, Object> params) throws Exception {
// return masterMapper.selectDetailInfo(params);
// }
// @Override
// public void deleteInfo(HashMap<String, Object> params) throws Exception {
// masterMapper.deleteInfo(params);
// }
// @Override
// public EgovMap selectModifyInfo(HashMap<String, Object> params) throws Exception {
// return masterMapper.selectModifyInfo(params);
// }
@Override
public void updateInfoStatus(HashMap<String, Object> params) throws Exception {
masterMapper.updateInfoStatus(params);
}
@Override
public List<?> selectWebApiKeyList(HashMap<String, Object> params) throws Exception {
return masterMapper.selectWebApiKeyList(params);
}
@Override
public void updateWebApiKeyApprove(HashMap<String, Object> params) throws Exception {
masterMapper.updateWebApiKeyApprove(params);
}
@Override
public void deleteWebApiKey(HashMap<String, Object> params) throws Exception {
masterMapper.deleteWebApiKey(params);
}
}

View File

@ -0,0 +1,59 @@
package geoinfo.admins.apiManagement.service.impl;
import java.util.HashMap;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import egovframework.rte.psl.dataaccess.util.EgovMap;
import geoinfo.admins.apiManagement.service.ApiOutDataManagementMapper;
import geoinfo.admins.apiManagement.service.ApiOutDataManagementService;
@Service("apiOutDataManagementService")
public class ApiOutDataManagementServiceImpl implements ApiOutDataManagementService {
@Resource(name = "apiOutDataManagementMapper")
private ApiOutDataManagementMapper masterMapper;
@Override
public EgovMap selectDailyAccessCountByHour(HashMap<String, Object> params) throws Exception {
return masterMapper.selectDailyAccessCountByHour(params);
}
@Override
public List<?> selectWebApiLogDailyCount(HashMap<String, Object> params) throws Exception {
return masterMapper.selectWebApiLogDailyCount(params);
}
@Override
public List<?> selectWebApiLogMonthlyCount(HashMap<String, Object> params) throws Exception {
return masterMapper.selectWebApiLogMonthlyCount(params);
}
@Override
public List<?> selectWebApiLogYearlyCount(HashMap<String, Object> params) throws Exception {
return masterMapper.selectWebApiLogYearlyCount(params);
}
@Override
public List<?> selectInfo(HashMap<String, Object> params) throws Exception {
return masterMapper.selectInfo(params);
}
@Override
public List<?> selectWebApiLogList(HashMap<String, Object> params) throws Exception {
return masterMapper.selectWebApiLogList(params);
}
@Override
public void saveInfo(HashMap<String, Object> params) throws Exception {
masterMapper.saveInfo(params);
}
@Override
public void updateInfoStatus(HashMap<String, Object> params) throws Exception {
masterMapper.updateInfoStatus(params);
}
}

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="geoinfo.admins.apiManagement.service.ApiManagementMapper">
<mapper namespace="geoinfo.admins.apiManagement.service.ApiInDataManagementMapper">
<!-- API 관리 > 일일 접속량 -->
<select id="selectDailyAccessCountByHour" parameterType="map" resultType="egovMap">
@ -80,33 +80,6 @@
WHERE 1=1
) TB
</select>
<!-- <insert id="saveInfo" parameterType="map">
<![CDATA[
INSERT INTO WEB_COMMUNITY
SELECT NVL(MAX(IDX),0) + 1, #{name}, #{password}, #{email}, #{homepage}, #{subject}, #{content}, NVL(MAX(IDX),0) + 1, 0, #{fileName1}, #{saveName1}, SYSDATE, 0, #{topnotice}, #{fileName2}, #{saveName2}, #{fileName3}, #{saveName3}
FROM WEB_COMMUNITY
]]>
</insert> -->
<!-- <select id="selectDetailInfo" parameterType="map" resultType="egovMap">
SELECT IDX, SUBJECT, EMAIL, HOMEPAGE, SAVENAME, FILENAME, SAVENAME2, FILENAME2, SAVENAME3, FILENAME3, CONTENT, NAME, READCOUNT, TO_CHAR(DATETIME,'YYYY-MM-DD') DATETIME, SEQ
FROM WEB_COMMUNITY
WHERE IDX = #{idx}
</select> -->
<!-- <delete id="deleteInfo" parameterType="map">
<![CDATA[
DELETE FROM WEB_COMMUNITY
WHERE IDX = #{idx}
]]>
</delete> -->
<!-- <select id="selectModifyInfo" parameterType="map" resultType="egovMap">
SELECT IDX, SUBJECT, CONTENT, NAME, READCOUNT, TO_CHAR(DATETIME,'YYYY-MM-DD') DATETIME, SEQ, FILENAME, SAVENAME, TOP, FILENAME2, SAVENAME2, FILENAME3, SAVENAME3
FROM WEB_COMMUNITY
WHERE IDX = #{idx}
</select> -->
<!-- API 호출 활성상태 변경 -->
<update id="updateInfoStatus" parameterType="map">
@ -121,46 +94,4 @@
</foreach>
)
</update>
<!-- API 신청 관리 목록 조회 -->
<select id="selectWebApiKeyList" parameterType="map" resultType="egovMap">
SELECT TB.RN
,TB.API_SEQ
,TB.USERID
,TB.USER_TYPE
,TB.API_KEY
,TO_CHAR(TB.START_DT, 'YYYY-MM-DD HH24:MI') AS START_DT
,TO_CHAR(TB.END_DT, 'YYYY-MM-DD HH24:MI') AS END_DT
,TB.APPROVE_YN
FROM (SELECT API_SEQ
,USERID
,USER_TYPE
,API_KEY
,START_DT
,END_DT
,APPROVE_YN
,ROW_NUMBER() OVER(ORDER BY API_SEQ ASC) RN
,TO_CHAR(LAST_VALUE(ROWNUM) OVER (ORDER BY ROWNUM ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)) AS TOTALROWS
FROM WEB_API_KEY
WHERE 1=1) TB
<!-- WHERE RN BETWEEN #{firstIndex} + 1 AND #{firstIndex} + #{recordCountPerPage} -->
</select>
<!-- API 신청 승인상태 변경 -->
<update id="updateWebApiKeyApprove" parameterType="map">
UPDATE WEB_API_KEY
SET
<if test="approveYn != null and approveYn !=''">
APPROVE_YN = #{approveYn}
</if>
WHERE API_SEQ IN (#{apiSeq})
</update>
<!-- 사용자 API 신청 삭제하기 -->
<delete id="deleteWebApiKey" parameterType="map">
DELETE
FROM WEB_API_KEY
WHERE API_SEQ IN (#{apiSeq})
</delete>
</mapper>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="geoinfo.admins.apiManagement.service.ApiKeyManagementMapper">
<!-- API 신청 관리 목록 조회 -->
<select id="selectWebApiKeyList" parameterType="map" resultType="egovMap">
SELECT TB.RN
,TB.API_SEQ
,TB.USERID
,TB.USER_TYPE
,TB.API_KEY
,TO_CHAR(TB.START_DT, 'YYYY-MM-DD HH24:MI') AS START_DT
,TO_CHAR(TB.END_DT, 'YYYY-MM-DD HH24:MI') AS END_DT
,TB.APPROVE_YN
FROM (SELECT API_SEQ
,USERID
,USER_TYPE
,API_KEY
,START_DT
,END_DT
,APPROVE_YN
,ROW_NUMBER() OVER(ORDER BY API_SEQ ASC) RN
,TO_CHAR(LAST_VALUE(ROWNUM) OVER (ORDER BY ROWNUM ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)) AS TOTALROWS
FROM WEB_API_KEY
WHERE 1=1) TB
<!-- WHERE RN BETWEEN #{firstIndex} + 1 AND #{firstIndex} + #{recordCountPerPage} -->
</select>
<!-- API 신청 승인상태 변경 -->
<update id="updateWebApiKeyApprove" parameterType="map">
UPDATE WEB_API_KEY
SET
<if test="approveYn != null and approveYn !=''">
APPROVE_YN = #{approveYn}
</if>
WHERE API_SEQ IN (#{apiSeq})
</update>
<!-- 사용자 API 신청 삭제하기 -->
<delete id="deleteWebApiKey" parameterType="map">
DELETE
FROM WEB_API_KEY
WHERE API_SEQ IN (#{apiSeq})
</delete>
</mapper>

View File

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="geoinfo.admins.apiManagement.service.ApiOutDataManagementMapper">
<!-- API 관리 > 일일 접속량 -->
<select id="selectDailyAccessCountByHour" parameterType="map" resultType="egovMap">
SELECT
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '00' THEN 1 END), 0) AS COUNT_00,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '01' THEN 1 END), 0) AS COUNT_01,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '02' THEN 1 END), 0) AS COUNT_02,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '03' THEN 1 END), 0) AS COUNT_03,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '04' THEN 1 END), 0) AS COUNT_04,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '05' THEN 1 END), 0) AS COUNT_05,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '06' THEN 1 END), 0) AS COUNT_06,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '07' THEN 1 END), 0) AS COUNT_07,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '08' THEN 1 END), 0) AS COUNT_08,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '09' THEN 1 END), 0) AS COUNT_09,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '10' THEN 1 END), 0) AS COUNT_10,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '11' THEN 1 END), 0) AS COUNT_11,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '12' THEN 1 END), 0) AS COUNT_12,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '13' THEN 1 END), 0) AS COUNT_13,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '14' THEN 1 END), 0) AS COUNT_14,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '15' THEN 1 END), 0) AS COUNT_15,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '16' THEN 1 END), 0) AS COUNT_16,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '17' THEN 1 END), 0) AS COUNT_17,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '18' THEN 1 END), 0) AS COUNT_18,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '19' THEN 1 END), 0) AS COUNT_19,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '20' THEN 1 END), 0) AS COUNT_20,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '21' THEN 1 END), 0) AS COUNT_21,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '22' THEN 1 END), 0) AS COUNT_22,
NVL(SUM(CASE WHEN TO_CHAR(ACCESS_DT, 'HH24') = '23' THEN 1 END), 0) AS COUNT_23
FROM GEOINFO.WEB_API_LOG
WHERE ACCESS_DT >= TRUNC(TO_DATE(#{CHART_DATE}, 'YYYY-MM-DD'))
AND ACCESS_DT <![CDATA[<]]> TRUNC(TO_DATE(#{CHART_DATE}, 'YYYY-MM-DD')) + 1
</select>
<!-- API 관리 > 날짜별 통계 -->
<select id="selectWebApiLogDailyCount" parameterType="map" resultType="egovMap">
WITH date_range AS (
SELECT TO_DATE(#{COUNT_FROM_DT}, 'YYYY-MM-DD') + LEVEL - 1 AS dt
FROM dual
CONNECT BY LEVEL <![CDATA[<=]]> TO_DATE(#{COUNT_TO_DT}, 'YYYY-MM-DD') - TO_DATE(#{COUNT_FROM_DT}, 'YYYY-MM-DD') + 1
)
SELECT
TO_CHAR(dr.dt, 'YYYY-MM-DD') AS period,
NVL(COUNT(wal.access_dt), 0) || '건' AS access_count
FROM
date_range dr
LEFT JOIN GEOINFO.WEB_API_LOG wal
ON TRUNC(wal.access_dt) = dr.dt
GROUP BY dr.dt
ORDER BY dr.dt
</select>
<!-- API 관리 > 월별 통계 -->
<select id="selectWebApiLogMonthlyCount" parameterType="map" resultType="egovMap">
WITH month_range AS (
SELECT ADD_MONTHS(TRUNC(TO_DATE(#{COUNT_FROM_DT}, 'YYYY-MM'), 'MM'), LEVEL - 1) AS month_start
FROM dual
CONNECT BY LEVEL <![CDATA[<=]]> MONTHS_BETWEEN(TRUNC(TO_DATE(#{COUNT_TO_DT}, 'YYYY-MM'), 'MM'),
TRUNC(TO_DATE(#{COUNT_FROM_DT}, 'YYYY-MM'), 'MM')) + 1
)
SELECT
TO_CHAR(mr.month_start, 'YYYY-MM') AS period,
NVL(COUNT(wal.access_dt), 0) || '건' AS access_count
FROM
month_range mr
LEFT JOIN GEOINFO.WEB_API_LOG wal
ON TRUNC(wal.access_dt, 'MM') = mr.month_start
GROUP BY mr.month_start
ORDER BY mr.month_start
</select>
<!-- API 관리 > 연도별 통계 -->
<select id="selectWebApiLogYearlyCount" parameterType="map" resultType="egovMap">
WITH year_range AS (
SELECT ADD_MONTHS(TRUNC(TO_DATE(#{COUNT_FROM_DT}, 'YYYY'), 'YYYY'), (LEVEL - 1) * 12) AS year_start
FROM dual
CONNECT BY LEVEL <![CDATA[<=]]> FLOOR(MONTHS_BETWEEN(TRUNC(TO_DATE(#{COUNT_TO_DT}, 'YYYY'), 'YYYY'),
TRUNC(TO_DATE(#{COUNT_FROM_DT}, 'YYYY'), 'YYYY')) / 12) + 1
)
SELECT
TO_CHAR(yr.year_start, 'YYYY') AS period,
NVL(COUNT(wal.access_dt), 0) || '건' AS access_count
FROM
year_range yr
LEFT JOIN GEOINFO.WEB_API_LOG wal
ON TRUNC(wal.access_dt, 'YYYY') = yr.year_start
GROUP BY yr.year_start
ORDER BY yr.year_start
</select>
<select id="selectInfo" parameterType="map" resultType="egovMap">
SELECT TB.RN
,TB.IDX
,TB."NAME"
,TB."DESC"
,TB.ACTIVE_YN
,TO_CHAR(LAST_VALUE(ROWNUM) OVER (ORDER BY ROWNUM ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)) AS TOTALROWS
FROM (SELECT IDX
,"NAME"
,"DESC"
,ACTIVE_YN
,ROW_NUMBER() OVER(ORDER BY IDX ASC) RN
,TO_CHAR(LAST_VALUE(ROWNUM) OVER (ORDER BY ROWNUM ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)) AS TOTALROWS
FROM WEB_API_OUTBOUND
WHERE 1=1
) TB
<!-- WHERE RN BETWEEN #{firstIndex} + 1 AND #{firstIndex} + #{recordCountPerPage} -->
</select>
<!-- API 관리 > API 호출 로그 목록 표시 -->
<select id="selectWebApiLogList" parameterType="map" resultType="egovMap">
SELECT TB.RN
,TB.LOG_SEQ
,SUBSTR(TB.API_KEY, 1, 10) || '...' AS API_KEY_CONCAT
,TB.API_KEY
,TB.ACCESS_ID
,TB.ACCESS_TYPE
,TB.ACCESS_TABLE
,TO_CHAR(TB.ACCESS_DT, 'YYYY-MM-DD HH24:MI') AS ACCESS_DT
,TB.IP_ADDRESS
,TO_CHAR(LAST_VALUE(ROWNUM) OVER (ORDER BY ROWNUM ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)) AS TOTALROWS
FROM (SELECT LOG_SEQ
,API_KEY
,ACCESS_ID
,ACCESS_TYPE
,ACCESS_TABLE
,ACCESS_DT
,IP_ADDRESS
,ROW_NUMBER() OVER(ORDER BY LOG_SEQ DESC) RN
,COUNT(*) OVER () AS TOTALROWS
FROM WEB_API_LOG
WHERE 1=1
) TB
</select>
<!-- API 호출 활성상태 변경 -->
<update id="updateInfoStatus" parameterType="map">
UPDATE WEB_API_INBOUND
SET
<if test="activeYn != null and activeYn !=''">
ACTIVE_YN = #{activeYn}
</if>
WHERE IDX IN (
<foreach item="item" index="index" collection="idxArr" open="" separator=", " close="">
#{item}
</foreach>
)
</update>
</mapper>

View File

@ -3,10 +3,13 @@
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<!-- Bootstrap Datepicker -->
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.min.css"> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/locales/bootstrap-datepicker.ko.min.js"></script> -->
<!-- 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>
@ -14,16 +17,129 @@
<!-- MUI + Chart.js + jQuery -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link href="https://cdn.jsdelivr.net/npm/@mui/material@5.15.14/dist/material.min.css" rel="stylesheet">
<!-- <link href="https://cdn.jsdelivr.net/npm/@mui/material@5.15.14/dist/material.min.css" rel="stylesheet"> -->
<style>
body { font-family: 'Pretendard', 'Roboto', sans-serif; background-color: #f5f6fa; margin: 0; padding: 20px; }
body { font-family: 'Pretendard', 'Roboto', sans-serif; background-color: #f5f6fa; color: #333; margin: 0; padding: 20px; }
.chart-container {
background: #fff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);
padding: 20px; margin-bottom: 20px;
}
.chart-container h3 { margin-bottom: 10px; }
/* 국토지반 API 호출 통계 */
.stats-container {
margin: 20px auto;
background-color: #ffffff;
border: 1px solid #dbe3e0;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
/* overflow: hidden; */
}
/* 헤더 영역 (버튼 배치를 위해 수정) */
.stats-header {
padding: 20px 30px;
border-bottom: 1px solid #eee;
overflow: hidden; /* float을 포함하기 위함 */
}
.stats-header h1 {
margin: 0;
color: #2c3e50;
font-size: 24px;
display: inline-block; /* 버튼과 정렬 */
float: left;
}
/* CSV 내보내기 버튼 스타일 */
.export-btn {
float: right;
background-color: #007bff;
color: white;
border: none;
padding: 8px 14px;
border-radius: 5px;
font-weight: 600;
cursor: pointer;
font-size: 14px;
transition: background-color 0.2s;
}
.export-btn:hover {
background-color: #0056b3;
}
/* (이하 탭, 테이블 스타일 동일) */
.tab-nav {
display: flex;
background-color: #fdfdfd;
border-bottom: 1px solid #eee;
padding: 0 30px;
}
.tab-link {
font-size: 16px;
font-weight: 600;
color: #555;
background-color: transparent;
border: none;
padding: 15px 20px;
cursor: pointer;
border-bottom: 3px solid transparent;
transition: all 0.3s ease;
margin-right: 10px;
}
.tab-link:hover {
color: #007bff;
}
.tab-link.active {
color: #007bff;
border-bottom-color: #007bff;
}
.tab-content-wrapper {
padding: 30px;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
.tab-content h2 {
font-size: 20px;
color: #34495e;
margin-bottom: 20px;
}
.stats-table {
width: 100%;
border-collapse: collapse;
font-size: 14px;
}
.stats-table th,
.stats-table td {
border: 1px solid #e0e0e0;
padding: 12px 15px;
text-align: left;
}
.stats-table thead {
background-color: #f9fafa;
}
.stats-table th {
font-weight: 600;
color: #444;
}
.stats-table tbody tr:nth-child(even) {
background-color: #fcfcfc;
}
.stats-table td:last-child {
text-align: right;
font-weight: 600;
color: #e74c3c;
}
.stats-table .period-cell {
vertical-align: top;
font-weight: 600;
color: #333;
background-color: #fdfdfd;
}
/* 국토지반 API 호출 통계 END ------------------------- */
.dashboard-grid {
display: grid; grid-template-columns: 1fr 1fr; gap: 20px;
}
@ -183,6 +299,17 @@
.pagination button:hover:not(.active) {
background-color: #cbd5e1;
}
.datepicker-wrapper {
}
.datepicker-dropdown {
z-index: 99999 !important;
position: absolute;
left: 0 !important;
background: #fff;
border: 1px solid #e6e6e6;
}
</style>
</head>
<body>
@ -190,10 +317,79 @@
<!-- 일일 접속량 -->
<div class="chart-container">
<h3>📈 일일 접속량</h3>
<input type="text" name="chartDate" id="chartDate" class="input" placeholder="클릭하여 날짜 선택" >
<!-- <div id="chartDateContainer" style="position: relative;"><input type="text" name="chartDate" id="chartDate " class="input" placeholder="클릭하여 날짜 선택" ></div> -->
<div class="datepicker-wrapper" style="position: relative; display: inline-block;">
<input type="text" name="chartDate" id="chartDate" class="input" placeholder="클릭하여 날짜 선택">
</div>
<canvas id="trafficChart" height="100"></canvas>
</div>
<!-- 국토지반 API 호출 건수 통계 -->
<div class="stats-container">
<header class="stats-header">
<h1>국토지반 API 호출 통계</h1>
<button id="export-csv-btn" class="export-btn">CSV 내보내기</button>
</header>
<nav class="tab-nav">
<button class="tab-link active" data-tab="daily">일별 통계</button>
<button class="tab-link" data-tab="monthly">월별 통계</button>
<button class="tab-link" data-tab="yearly">연도별 통계</button>
</nav>
<div class="tab-content-wrapper">
<div class="datepicker-wrapper" style="position: relative; display: inline-block;">
<input type="text" name="count_from_dt" id="count_from_dt" class="input" placeholder="클릭하여 날짜 선택" >~
<input type="text" name="count_to_dt" id="count_to_dt" class="input" placeholder="클릭하여 날짜 선택" >
</div>
<div id="daily" class="tab-content active">
<h2>일별 API 호출 현황</h2>
<table class="stats-table">
<thead>
<tr>
<th>날짜</th>
<th>API 명</th>
<th>호출 건수</th>
</tr>
</thead>
<tbody id="daily-tbody">
<tr><td colspan="3">표시 할 통계데이타가 없습니다.</td></tr>
</tbody>
</table>
</div>
<div id="monthly" class="tab-content">
<h2>월별 API 호출 현황</h2>
<table class="stats-table">
<thead>
<tr>
<th>월</th>
<th>API 명</th>
<th>총 호출 건수</th>
</tr>
</thead>
<tbody id="monthly-tbody">
<tr><td colspan="3">표시 할 통계데이타가 없습니다.</td></tr>
</tbody>
</table>
</div>
<div id="yearly" class="tab-content">
<h2>연도별 API 호출 현황</h2>
<table class="stats-table">
<thead>
<tr>
<th>연도</th>
<th>API 명</th>
<th>총 호출 건수</th>
</tr>
</thead>
<tbody id="yearly-tbody">
<tr><td colspan="3">표시 할 통계데이타가 없습니다.</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="dashboard-grid">
<!-- API 호출 현황 -->
<div class="card">
@ -315,15 +511,103 @@
}
let trafficChart; // 전역 변수
var today = new Date(); // (기준)오늘 날짜
var thisYear = today.getFullYear(); // (기준)올해연도
var thisMonth = today.getMonth+1; // (기준)이번달
var toDate = new Date(today.getFullYear(), today.getMonth(), 1); // (기준)이번달1일
var weekAgo = new Date(); // 7일 전 날짜
weekAgo.setDate(today.getDate() - 7);
var fvMonthAgo = new Date();
fvMonthAgo.setMonth(toDate.getMonth() -5);
$(document).ready(function(){
// ----------------------------------------------------
// 1. 날짜 선택기 초기화
// ----------------------------------------------------
// datepicker
$("#chartDate").datepicker({
format: "yyyy-mm-dd",
$("#chartDate, #count_from_dt, #count_to_dt").datepicker({
format: "yyyy-mm-dd",
language: "ko",
autoclose: true
autoclose: true,
todayHighlight: true,
container: $("#chartDate").closest(".datepicker-wrapper")
}).datepicker("setDate", new Date());
$("#count_from_dt").datepicker("setDate", weekAgo); // 국토지반 API 호출 통계 시작일 셋팅(저번주)
// API 호출 현황
// ----------------------------------------------------
// 2. 탭 전환 처리
// ----------------------------------------------------
$('.tab-link').on('click', function() {
const targetId = $(this).data('tab');
$('.tab-link').removeClass('active');
$(this).addClass('active');
$('.tab-content').removeClass('active');
$('#' + targetId).addClass('active');
$("#count_from_dt, #count_to_dt").datepicker('destroy'); // datepicker 재선언(format 변경)
// 일별 탭 클릭 시
if (targetId === 'daily') {
// 월 단위 datepicker 재초기화
$("#count_from_dt, #count_to_dt").datepicker({
format: "yyyy-mm-dd",
language: "ko",
autoclose: true,
minViewMode: 0, // 월 단위
todayHighlight: true,
container: $("#count_from_dt").closest(".datepicker-wrapper")
});
$("#count_to_dt").datepicker("setDate", today); // 국토지반 API 호출 통계 시작일 셋팅(저번주)
$("#count_from_dt").datepicker("setDate", weekAgo); // 국토지반 API 호출 통계 시작일 셋팅(저번주)
}
// 월별 탭 클릭 시
if (targetId === 'monthly') {
// 월 단위 datepicker 재초기화
$("#count_from_dt, #count_to_dt").datepicker({
format: "yyyy-mm",
language: "ko",
autoclose: true,
minViewMode: 1, // 월 단위
todayHighlight: true,
container: $("#count_from_dt").closest(".datepicker-wrapper")
});
$("#count_from_dt").datepicker("setDate", fvMonthAgo);
$("#count_to_dt").datepicker("setDate", thisMonth);
$("#count_from_dt").val($("#count_from_dt").val().substr(0,7));
$("#count_to_dt").val($("#count_to_dt").val().substr(0,7));
}
// 연도별 탭 클릭 시
if (targetId === 'yearly') {
// 월 단위 datepicker 재초기화
$("#count_from_dt, #count_to_dt").datepicker({
minViewMode: 'years',
format: "yyyy",
language: "ko",
autoclose: true,
// minViewMode: 1, // 월 단위
todayHighlight: true,
container: $("#count_from_dt").closest(".datepicker-wrapper")
});
$("#count_to_dt").datepicker("setDate", new Date(thisYear, 0, 1));
$("#count_from_dt").datepicker("setDate", new Date((thisYear -5), 0, 1));
$("#count_to_dt").val($("#count_to_dt").val().substr(0,4))
$("#count_from_dt").val($("#count_from_dt").val().substr(0,4))
}
});
// ----------------------------------------------------
// 3. API 호출 현황 초기 로드
// ----------------------------------------------------
animateValue("successRate", 0, 100, 1500);
animateValue("failRate", 0, 0, 1500);
animateValue("delayRate", 0, 0, 1500);
@ -332,6 +616,9 @@
// API 호출 통제 목록 조회
getMgmtApiList();
// API 호출 통계 > 일별 통계
getApiStatDaily();
// API 호출로그 목록 조회
getMgmtApiLogList();
@ -342,6 +629,15 @@
$(document).on('change', '#chartDate', function() {
getMgmtApiChart();
});
// API 호출 현황 건수 - 날짜 변경 시 차트 다시 로드
$(document).on('change', '#count_from_dt, #count_to_dt', function() {
// console.log(validDate())
if(!validDate()){
return;
}
getApiStatDaily();
});
});
// API 호출 통제 목록 조회
@ -432,6 +728,74 @@
return html;
}
// API 호출 통계 > 일별 통계
function getApiStatDaily(){
var statType = $('.stats-container > .tab-nav').find('.active').data("tab");
var fromDt = $('#count_from_dt').val();
var toDt = $('#count_to_dt').val();
// 날짜데이터가 올바르게 셋팅되지 않았을때는 요청하지 않는다.
if (statType === "monthly") {
if (fromDt.length < 7 || toDt.length < 7 ) return;
} else if (statType === "yearly") {
if (fromDt.length < 4 || toDt.length < 4 ) return;
} else { // statType === "daily"
if (fromDt.length < 10 || toDt.length < 10 ) return;
}
$.ajax({
type : "POST",
url : "/admins/mgmtApi/o_counts.do" ,
data : {
statType : statType,
countFromDt: $('#count_from_dt').val(),
countToDt: $('#count_to_dt').val()
},
dataType :"json",
success : function(res){ // res.code, res.msg, res.data
if (res.code == "SUCCESS") {
let countList = res.data; //Array List
let $listContainer;
if (statType === "monthly") {
$listContainer = $("#monthly-tbody");
} else if (statType === "yearly") {
$listContainer = $("#yearly-tbody");
} else { // statType === "daily"
$listContainer = $("#daily-tbody");
}
$listContainer.empty(); // 기존 내용 제거
if (!countList.length > 1) {
$listContainer.append('<tr><td colspan="3">표시 할 통계데이타가 없습니다.</td></tr>');
return;
}
// 데이터 반복
$.each(res.data, function(i, item) {
// DOM에 추가
$listContainer.append(drawApiCountList(item));
});
} else {
alert("API 호출 로그 목록 조회중 오류가 발생하였습니다. 다시 시도해주세요.");
}
},
error : function(response){
alert("API 호출 로그 목록 조회중 내부 오류가 발생하였습니다. 다시 시도해주세요.");
}
});
};
function drawApiCountList(item) {
// HTML 문자열 생성
const html = `
<tr>
<td>\${item.period}</td>
<td></td>
<td>\${item.accessCount}</td>
</tr>
`;
return html;
}
// API 호출 로그 목록 조회
function getMgmtApiLogList(){
$.ajax({
@ -479,7 +843,6 @@
// API 호출 로그 목록 조회
function getMgmtApiChart(){
var chartDate = $('#chartDate').val();
console.log($('#chartDate').val())
$.ajax({
type : "POST",
url : "/admins/mgmtApi/charts.do" ,
@ -563,6 +926,19 @@
raw.slice(10, 12)
);
}
/**
* API 호출 통계 날짜 유효검사
*/
function validDate(){
var statType = $('.stats-container > .tab-nav').find('.active').data("tab");
var from_dt_val = $('#count_from_dt').val();
var to_dt_val = $('#count_to_dt').val();
if ("daily" === statType && (from_dt_val.length != 10 || to_dt_val.length != 10)) return false; // YYYY-MM-DD
if ("monthly" === statType && (from_dt_val.length != 7 || to_dt_val.length != 7)) return false; // YYYY-MM
if ("yearly" === statType && (from_dt_val.length != 4 || to_dt_val.length != 4)) return false; // YYYY
return true;
}
// 예시 데이터 (100개 생성)
// const apiLogs = Array.from({ length: 100 }, (_, i) => ({

View File

@ -75,7 +75,14 @@ img { border:0; }
<tr>
<td>
<div class="menu-item active">
<span style="cursor:hand" onClick="javascript:goUrl('mgmt-api-index', '${menuId}')"><img src="${pageContext.request.contextPath}/images/renew/arrow-right.png" /> &nbsp;API 통계</span>
<span style="cursor:hand" onClick="javascript:goUrl('mgmt-api-index', '${menuId}')"><img src="${pageContext.request.contextPath}/images/renew/arrow-right.png" /> &nbsp;API 통계(내부 데이타)</span>
</div>
</td>
</tr>
<tr>
<td>
<div class="menu-item active">
<span style="cursor:hand" onClick="javascript:goUrl('mgmt-api-outdata', '${menuId}')"><img src="${pageContext.request.contextPath}/images/renew/arrow-right.png" /> &nbsp;API 통계(외부 데이타)</span>
</div>
</td>
</tr>

View File

@ -0,0 +1,629 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<!-- 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>
<link href="https://cdn.jsdelivr.net/npm/@mui/material@5.15.14/dist/material.min.css" rel="stylesheet">
<style>
body { font-family: 'Pretendard', 'Roboto', sans-serif; background-color: #f5f6fa; margin: 0; padding: 20px; }
.chart-container {
background: #fff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);
padding: 20px; margin-bottom: 20px;
}
.chart-container h3 { margin-bottom: 10px; }
.dashboard-grid {
display: grid; grid-template-columns: 1fr 1fr; gap: 20px;
}
.card {
background: #fff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); padding: 20px;
}
.card-header {
display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;
}
.dashboard-btn {
background: linear-gradient(135deg, #4285f4, #1a73e8);
color: #fff; border: none; border-radius: 20px; padding: 6px 16px;
cursor: pointer; font-weight: 600; transition: 0.3s;
}
.dashboard-btn:hover { opacity: 0.9; }
.status-item {
display: flex; align-items: center; justify-content: space-between;
background: #fafafa; border-radius: 10px; padding: 10px 15px; margin-bottom: 8px;
}
.status-left { display: flex; align-items: center; gap: 10px; }
.status-icon {
width: 26px; height: 26px; display: flex; justify-content: center; align-items: center; border-radius: 50%;
}
.success { background-color: #e7f9ed; color: #2ecc71; }
.fail { background-color: #fdecea; color: #e74c3c; }
.delay { background-color: #eaf3fd; color: #3498db; }
.error { background-color: #fff7e6; color: #f1c40f; }
/* 통제 카드 */
.switch-container {
max-height: 260px;
overflow-y: auto;
}
.api-switch {
display: flex;
justify-content: space-between;
align-items: center; /* 수직 가운데 정렬 */
background: #f8f8f8;
border-radius: 10px;
padding: 12px 15px;
margin-bottom: 10px;
gap: 12px; /* 텍스트와 스위치 사이 여백 */
}
.api-switch > div {
flex: 1; /* 왼쪽 내용이 남는 공간 차지 */
min-width: 0; /* 긴 텍스트 줄바꿈 정상화 */
}
.switch-title {
font-weight: 600;
font-size: 14px;
color: #222;
margin-bottom: 4px;
}
.switch-desc {
font-size: 12px;
color: #777;
line-height: 1.4;
white-space: pre-line; /* \n이나 <br>을 줄바꿈으로 인식 */
}
/* 스위치 디자인 */
.mui-switch {
position: relative;
flex-shrink: 0; /* 스위치 크기 줄어들지 않게 */
display: inline-block;
width: 48px;
height: 26px;
}
.mui-switch input {
opacity: 0;
width: 0;
height: 0;
}
.mui-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: 0.4s;
border-radius: 34px;
display: flex;
align-items: center;
justify-content: ${''}; /* 가운데 맞춤 */
}
.mui-slider:before {
position: absolute;
content: "OFF";
color: #fff;
font-size: 10px;
height: 20px;
width: 20px;
left: 3px;
bottom: 3px;
background-color: #999;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
transition: 0.4s;
}
input:checked + .mui-slider {
background-color: #4A90E2;
}
input:checked + .mui-slider:before {
transform: translateX(22px);
content: "ON";
background-color: #1A73E8;
}
/* 로그 테이블 */
.table-container {
margin-top: 25px; background: #fff; border-radius: 12px; padding: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
table { width: 100%; border-collapse: collapse; }
thead { background: #f0f3f8; }
th, td { padding: 10px; border-bottom: 1px solid #eee; text-align: left; }
th { color: #555; font-weight: 600; }
.pagination {
display: flex;
justify-content: center;
align-items: center;
gap: 6px;
margin-top: 15px;
}
.pagination button {
border: none;
background-color: #e2e8f0;
color: #334155;
padding: 6px 12px;
border-radius: 8px;
font-size: 13px;
cursor: pointer;
transition: all 0.2s ease;
}
.pagination button.active {
background-color: #3b82f6;
color: white;
}
.pagination button:hover:not(.active) {
background-color: #cbd5e1;
}
</style>
</head>
<body>
<!-- 일일 접속량 -->
<div class="chart-container">
<h3>📈 일일 접속량</h3>
<input type="text" name="chartDate" id="chartDate" class="input" placeholder="클릭하여 날짜 선택" >
<canvas id="trafficChart" height="100"></canvas>
</div>
<div class="dashboard-grid">
<!-- API 호출 현황 -->
<div class="card">
<div class="card-header">
<h3>API 호출 현황</h3>
</div>
<div class="status-item">
<div class="status-left">
<div class="status-icon success">✔</div>
<div>
<div><strong>호출 성공</strong></div>
<small>3초 이내 응답</small>
</div>
</div>
<div><strong id="successRate">0%</strong></div>
</div>
<div class="status-item">
<div class="status-left">
<div class="status-icon fail">❌</div>
<div>
<div><strong>호출 실패</strong></div>
<small>API 실패</small>
</div>
</div>
<div><strong id="failRate">0%</strong></div>
</div>
<div class="status-item">
<div class="status-left">
<div class="status-icon delay">🕓</div>
<div>
<div><strong>호출 지연</strong></div>
<small>3초 초과 지연</small>
</div>
</div>
<div><strong id="delayRate">0%</strong></div>
</div>
<div class="status-item">
<div class="status-left">
<div class="status-icon error">⚠️</div>
<div>
<div><strong>호출 오류</strong></div>
<small>오류 응답</small>
</div>
</div>
<div><strong id="errorRate">0%</strong></div>
</div>
</div>
<!-- API 목록 -->
<div class="card">
<div class="card-header">
<h3>API 목록</h3>
<!-- <label class="mui-switch"> -->
<!-- <input type="checkbox" id="globalSwitch" onchange="toggleStatus(this)" checked> -->
<!-- <span class="mui-slider"></span> -->
<!-- </label> -->
</div>
<div class="switch-container" id="apiSwitchList">
<div class="api-switch">
<div>
<div class="switch-title">표시 할 API 목록이 존재하지 않습니다.</div>
<div class="switch-desc">API를 등록해주세요.</div>
</div>
</div>
</div>
</div>
</div>
<!-- 로그 테이블 -->
<div class="table-container">
<h3>API 호출 로그</h3>
<table>
<colgroup>
<col style="width: 3%">
<col style="width: 7%">
<col style="width: 5%">
<col style="width: 15%">
<col style="width: auto">
<col style="width: 15%">
<col style="width: 5%">
</colgroup>
<thead>
<tr>
<th>No.</th>
<th>API_KEY</th>
<th>ACCESS_ID</th>
<th>ACCESS_TYPE</th>
<th>ACCESS_TABLE</th>
<th>ACCESS_DT</th>
<th>IP_ADDRESS</th>
</tr>
</thead>
<tbody id="apiLogBody">
</tbody>
</table>
<!-- 페이징 영역 -->
<div id="pagination" class="pagination"></div>
</div>
<script>
// 퍼센트 애니메이션
function animateValue(id, start, end, duration) {
const obj = document.getElementById(id);
let startTime = null;
function animation(currentTime) {
if (!startTime) startTime = currentTime;
const progress = Math.min((currentTime - startTime) / duration, 1);
obj.innerText = (progress * (end - start) + start).toFixed(1) + "%";
if (progress < 1) requestAnimationFrame(animation);
}
requestAnimationFrame(animation);
}
let trafficChart; // 전역 변수
$(document).ready(function(){
// datepicker
$("#chartDate").datepicker({
format: "yyyy-mm-dd",
language: "ko",
autoclose: true
}).datepicker("setDate", new Date());
// API 호출 현황
animateValue("successRate", 0, 100, 1500);
animateValue("failRate", 0, 0, 1500);
animateValue("delayRate", 0, 0, 1500);
animateValue("errorRate", 0, 0, 1500);
// API 목록 목록 조회
getMgmtApiList();
// API 호출로그 목록 조회
getMgmtApiLogList();
// 페이지 로드시 차트 먼저 로드
getMgmtApiChart();
// 날짜 변경 시 차트 다시 로드
$(document).on('change', '#chartDate', function() {
getMgmtApiChart();
});
});
// 외부요청 API 목록 조회
function getMgmtApiList(){
$.ajax({
type : "POST",
url : "/admins/mgmtApi/o_list.do" ,
data : {},
dataType :"json",
success : function(res){ // res.code, res.msg, res.data
if (res.code == "SUCCESS") {
let procList = res.data; //Array List
const $listContainer = $("#apiSwitchList");
$listContainer.empty(); // 기존 내용 제거
// 데이터 반복
$.each(res.data, function(i, item) {
// DOM에 추가
$listContainer.append(drawApiControlList(item));
});
} else {
alert("관리 API 목록 조회중 오류가 발생하였습니다. 다시 시도해주세요.");
}
},
error : function(response){
alert("관리 API 목록 조회중 내부 오류가 발생하였습니다. 다시 시도해주세요.");
}
});
}
// 개별 API 활성상태 변경
function toggleStatus(ele) { // ele => 스위치(형제요소 input 값으로 변경할 상태 Y,N 그리고 btnType을 판별한다)
let btnType = $(ele).attr('id'); // 일괄변경 버튼, 각 변경 버튼 여부(globalSwitch면 일괄변경임)
let idxArr = [];
let active = $(ele).is(":checked") ? "Y" : "N"
if (btnType == 'globalSwitch') {
$('#apiSwitchList .api-switch').each(function(i, el) {
const idx = $(el).data('idx');
idxArr.push(idx);
});
} else {
idxArr.push($(ele).parents('.api-switch').data("idx"));
}
$.ajax({
type : "POST",
url : "/admins/mgmtApi/toggleSts.do" ,
data : {idxArr:idxArr, activeYn: active},
traditional: true,
dataType :"json",
success : function(res){ // res.code, res.msg, res.data
if (res.code == "SUCCESS") {
let procList = res.data; //Array List
const $listContainer = $("#apiSwitchList");
$listContainer.empty(); // 기존 내용 제거
// 데이터 반복
$.each(res.data, function(i, item) {
// DOM에 추가
$listContainer.append(drawApiControlList(item));
});
} else {
alert("활성상태 변경 중 오류가 발생했습니다. 다시 시도해주세요");
}
},
error : function(response){
alert("활성상태 변경 중 내부 오류가 발생했습니다. 다시 시도해주세요");
}
});
}
function drawApiControlList(item) {
// activeYn 이 "Y"이면 체크 상태, 아니면 체크 해제
const isChecked = item.activeYn === "Y" ? "checked" : "";
// HTML 문자열 생성
const html = `
<div class="api-switch" data-idx="\${item.idx}">
<div>
<div class="switch-title">\${item.idx} \${item.name}</div>
<div class="switch-desc">\${item.desc.replace(/\\n/g, "<br>")}</div>
</div>
<%-- <label class="mui-switch">
<input type="checkbox" class="api-toggle" data-api="\${item.idx}" onchange="toggleStatus(this)" \${isChecked}>
<span class="mui-slider"></span>
</label>--%>
</div>
`;
return html;
}
// API 호출 로그 목록 조회
function getMgmtApiLogList(){
$.ajax({
type : "POST",
url : "/admins/mgmtApiLog/list.do" ,
data : {},
dataType :"json",
success : function(res){ // res.code, res.msg, res.data
if (res.code == "SUCCESS") {
let procList = res.data; //Array List
const $listContainer = $("#apiLogBody");
$listContainer.empty(); // 기존 내용 제거
// 데이터 반복
$.each(res.data, function(i, item) {
// DOM에 추가
$listContainer.append(drawApiLogList(item));
});
} else {
alert("API 호출 로그 목록 조회중 오류가 발생하였습니다. 다시 시도해주세요.");
}
},
error : function(response){
alert("API 호출 로그 목록 조회중 내부 오류가 발생하였습니다. 다시 시도해주세요.");
}
});
}
function drawApiLogList(item) {
// HTML 문자열 생성
const html = `
<tr data-idx="\${item.logSeq}">
<td>\${item.rn}</td>
<td title="\${item.apiKey}">\${item.apiKeyConcat}</td>
<td>\${item.accessId}</td>
<td>\${item.accessType}</td>
<td>\${item.accessTable}</td>
<td>\${item.accessDt}</td>
<td>\${item.ipAddress}</td>
</tr>
`;
return html;
}
// API 호출 로그 목록 조회
function getMgmtApiChart(){
var chartDate = $('#chartDate').val();
console.log($('#chartDate').val())
$.ajax({
type : "POST",
url : "/admins/mgmtApi/charts.do" ,
data : {chartDate: $('#chartDate').val()},
dataType :"json",
success : function(res){ // res.code, res.msg, res.data
if (res.code == "SUCCESS") {
const d = res.data;
// 시간대별 카운트를 배열로 변환
const chartData = [
d.count00, d.count01, d.count02, d.count03,
d.count04, d.count05, d.count06, d.count07,
d.count08, d.count09, d.count10, d.count11,
d.count12, d.count13, d.count14, d.count15,
d.count16, d.count17, d.count18, d.count19,
d.count20, d.count21, d.count22, d.count23
];
drawTrafficChart(chartData);
} else {
alert("API 호출 로그 목록 조회중 오류가 발생하였습니다. 다시 시도해주세요.");
}
},
error : function(response){
alert("API 호출 로그 목록 조회중 내부 오류가 발생하였습니다. 다시 시도해주세요.");
}
});
}
// Chart.js: 일일 접속량
function drawTrafficChart(dataArr) {
const ctx = document.getElementById('trafficChart').getContext('2d');
const labels = [
'00시','01시','02시','03시','04시','05시','06시','07시','08시','09시','10시','11시',
'12시','13시','14시','15시','16시','17시','18시','19시','20시','21시','22시','23시'
];
// 이미 차트가 있으면 갱신
if (trafficChart) {
trafficChart.data.datasets[0].data = dataArr;
trafficChart.update();
return;
}
// 최초 생성
trafficChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
data: dataArr,
borderColor: '#4285f4',
tension: 0.4,
fill: true,
backgroundColor: 'rgba(66,133,244,0.1)',
pointRadius: 3
}]
},
options: {
plugins: { legend: { display: false } },
scales: {
y: {
beginAtZero: true,
ticks: { stepSize: 1 }
}
}
}
});
}
/**
* 날짜형식 YYYYMMDDHHMI -> YYYY-MM-DD HH:MI
*/
function formatDateTime(raw) {
if (!raw || raw.length !== 12) return "";
return (
raw.slice(0, 4) + "-" +
raw.slice(4, 6) + "-" +
raw.slice(6, 8) + " " +
raw.slice(8, 10) + ":" +
raw.slice(10, 12)
);
}
// 예시 데이터 (100개 생성)
// const apiLogs = Array.from({ length: 100 }, (_, i) => ({
// api: i % 2 === 0 ? "/API_CHA_085/request" : "/API_BH_020/dc332",
// method: ["GET", "POST", "PUT"][Math.floor(Math.random() * 3)],
// params: `subCode=test${i}&prvcCode=x${i}`,
// status: [ "200 OK", "404 NOT FOUND", "500 INTERNAL ERROR" ][Math.floor(Math.random() * 3)],
// time: Math.floor(Math.random() * 500),
// result: ["성공", "지연", "실패"][Math.floor(Math.random() * 3)]
// }));
// const rowsPerPage = 10;
// let currentPage = 1;
// function renderTable(page) {
// const tableBody = document.getElementById("apiLogBody");
// tableBody.innerHTML = "";
// const start = (page - 1) * rowsPerPage;
// const end = start + rowsPerPage;
// const pageData = apiLogs.slice(start, end);
// pageData.forEach(row => {
// const tr = document.createElement("tr");
// tr.innerHTML += '<td>' + row.api + '</td><td>' + row.method + '</td><td>' + row.params + '</td><td>' + row.status + '</td><td>' + row.time + '</td><td>' + getResultIcon(row.result) + ' ' +row.result + '</td>';
// tableBody.appendChild(tr);
// });
// }
// function renderPagination() {
// const totalPages = Math.ceil(apiLogs.length / rowsPerPage);
// const pagination = document.getElementById("pagination");
// pagination.innerHTML = "";
// for (let i = 1; i <= totalPages; i++) {
// const btn = document.createElement("button");
// btn.textContent = i;
// if (i === currentPage) btn.classList.add("active");
// btn.addEventListener("click", () => {
// currentPage = i;
// renderTable(currentPage);
// renderPagination();
// });
// pagination.appendChild(btn);
// }
// }
// function getResultIcon(result) {
// if (result === "성공")
// return `<span style="color:#22c55e;">✔</span>`;
// if (result === "실패")
// return `<span style="color:#ef4444;">⚠</span>`;
// if (result === "지연")
// return `<span style="color:#3b82f6;">⏱</span>`;
// return "";
// }
// 초기 렌더링
// renderTable(currentPage);
// renderPagination();
</script>
</body>
</html>