From 55ebfd4645a68f6f0ae137ff21b5bd02c2132fbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=EC=A7=80=EC=9D=B8?= Date: Tue, 4 Nov 2025 15:56:55 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=EC=97=90=EC=84=9C=20=EA=B0=81=20API=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=EC=9D=B4=20=EB=B3=B4=EC=9D=B4=EA=B3=A0=20API=EB=A5=BC?= =?UTF-8?q?=20=ED=99=9C=EC=84=B1/=EB=B9=84=ED=99=9C=EC=84=B1=ED=99=94?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ApiManagementController.java | 94 ++-- .../service/ApiManagementMapper.java | 24 ++ .../service/ApiManagementService.java | 24 ++ .../impl/ApiManagementServiceImpl.java | 49 +++ .../mappers/admins/mgmt/Mgmt_Api_SQL.xml | 66 +++ .../mgmtApi/api-request-statistics-index.jsp | 404 ++++++++---------- 6 files changed, 409 insertions(+), 252 deletions(-) create mode 100644 src/main/java/geoinfo/admins/apiManagement/service/ApiManagementMapper.java create mode 100644 src/main/java/geoinfo/admins/apiManagement/service/ApiManagementService.java create mode 100644 src/main/java/geoinfo/admins/apiManagement/service/impl/ApiManagementServiceImpl.java create mode 100644 src/main/resources/geoinfo/sqlmap/mappers/admins/mgmt/Mgmt_Api_SQL.xml diff --git a/src/main/java/geoinfo/admins/apiManagement/ApiManagementController.java b/src/main/java/geoinfo/admins/apiManagement/ApiManagementController.java index 9905f84..79ee1d2 100644 --- a/src/main/java/geoinfo/admins/apiManagement/ApiManagementController.java +++ b/src/main/java/geoinfo/admins/apiManagement/ApiManagementController.java @@ -1,59 +1,28 @@ package geoinfo.admins.apiManagement; -import java.net.URLEncoder; -import java.security.SecureRandom; -import java.sql.SQLException; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.HashMap; import java.util.List; -import java.util.Locale; -import java.util.Map; import javax.annotation.Resource; -import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import org.apache.log4j.Logger; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.Sheet; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.RequestBody; 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 org.springframework.web.servlet.ModelAndView; -import egovframework.com.cmm.service.EgovProperties; -import egovframework.rte.psl.dataaccess.util.EgovMap; -import egovframework.rte.ptl.mvc.tags.ui.pagination.PaginationInfo; -import geoinfo.admins.board.RefrncRoomController; -import geoinfo.admins.user.service.GeneralUserMngService; -import geoinfo.admins.user.service.HomeTrainingService; -import geoinfo.com.EgovExcel; -import geoinfo.com.GeoinfoCommon; -import geoinfo.comm.util.ScriptUtil; +import geoinfo.admins.apiManagement.service.ApiManagementService; import geoinfo.session.UserInfo; -import geoinfo.util.MyUtil; -import whois.whoisSMS; @Controller public class ApiManagementController { - @Resource(name = "generalUserMngService") - private GeneralUserMngService masterService; - - @Resource(name = "homeTrainingService") - private HomeTrainingService homeTrainingService; + @Resource(name = "apiManagementService") + private ApiManagementService apiManagementService; /** * API 관리 > API 통계 화면 @@ -74,4 +43,61 @@ public class ApiManagementController { model.addAttribute("params", params); return "admins/mgmtApi/api-request-statistics-index"; } + + /** + * API 관리 > 관리 API 목록 + * @param params + * @param model + * @param response + * @param request + * @return + * @throws Exception + */ + @ResponseBody + @RequestMapping(value = "/admins/mgmtApi/list.do", method = RequestMethod.POST) + public HashMap getMgmtApiList(@RequestParam HashMap params, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception { + HashMap result = new HashMap(); + + List listData = apiManagementService.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/toggleSts.do", method = RequestMethod.POST) + public HashMap modMgmtApiActiveYn( + @RequestParam(value="idxArr") List idxArr, + @RequestParam(value="activeYn", required=false) String activeYn, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception { + HashMap result = new HashMap(); +// String sIdxArr[] = params.get("idx").toString().split(","); + System.out.println("idxArr = " + idxArr); + System.out.println("activeYn = " + activeYn); + + HashMap params = new HashMap<>(); + params.put("idxArr", idxArr); + params.put("activeYn", activeYn); + + apiManagementService.updateInfoStatus(params); + + List listData = apiManagementService.selectInfo(params); + + result.put("code", "SUCCESS"); + result.put("msg", "관리 API 목록 조회를 성공했습니다."); + result.put("data", listData); + + return result; + } } diff --git a/src/main/java/geoinfo/admins/apiManagement/service/ApiManagementMapper.java b/src/main/java/geoinfo/admins/apiManagement/service/ApiManagementMapper.java new file mode 100644 index 0000000..4256e86 --- /dev/null +++ b/src/main/java/geoinfo/admins/apiManagement/service/ApiManagementMapper.java @@ -0,0 +1,24 @@ +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("ApiManagementMapper") +public interface ApiManagementMapper { + + public List selectInfo(HashMap params) throws Exception; + + public void saveInfo(HashMap params) throws Exception; + +// public EgovMap selectDetailInfo(HashMap params) throws Exception; + +// public void deleteInfo(HashMap params) throws Exception; + +// public EgovMap selectModifyInfo(HashMap params) throws Exception; + + public void updateInfoStatus(HashMap params) throws Exception; + +} diff --git a/src/main/java/geoinfo/admins/apiManagement/service/ApiManagementService.java b/src/main/java/geoinfo/admins/apiManagement/service/ApiManagementService.java new file mode 100644 index 0000000..b9f547a --- /dev/null +++ b/src/main/java/geoinfo/admins/apiManagement/service/ApiManagementService.java @@ -0,0 +1,24 @@ +package geoinfo.admins.apiManagement.service; + +import java.util.HashMap; +import java.util.List; + +import egovframework.rte.psl.dataaccess.util.EgovMap; + + + +public interface ApiManagementService { + + public List selectInfo(HashMap params) throws Exception; + + public void saveInfo(HashMap params) throws Exception; + +// public EgovMap selectDetailInfo(HashMap params) throws Exception; + +// public void deleteInfo(HashMap params) throws Exception; + +// public EgovMap selectModifyInfo(HashMap params) throws Exception; + + public void updateInfoStatus(HashMap params) throws Exception; + +} diff --git a/src/main/java/geoinfo/admins/apiManagement/service/impl/ApiManagementServiceImpl.java b/src/main/java/geoinfo/admins/apiManagement/service/impl/ApiManagementServiceImpl.java new file mode 100644 index 0000000..90bfbce --- /dev/null +++ b/src/main/java/geoinfo/admins/apiManagement/service/impl/ApiManagementServiceImpl.java @@ -0,0 +1,49 @@ +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.ApiManagementMapper; +import geoinfo.admins.apiManagement.service.ApiManagementService; + +@Service("apiManagementService") +public class ApiManagementServiceImpl implements ApiManagementService { + + @Resource(name = "ApiManagementMapper") + private ApiManagementMapper masterMapper; + + @Override + public List selectInfo(HashMap params) throws Exception { + return masterMapper.selectInfo(params); + } + + @Override + public void saveInfo(HashMap params) throws Exception { + masterMapper.saveInfo(params); + } + +// @Override +// public EgovMap selectDetailInfo(HashMap params) throws Exception { +// return masterMapper.selectDetailInfo(params); +// } + +// @Override +// public void deleteInfo(HashMap params) throws Exception { +// masterMapper.deleteInfo(params); +// } + +// @Override +// public EgovMap selectModifyInfo(HashMap params) throws Exception { +// return masterMapper.selectModifyInfo(params); +// } + + @Override + public void updateInfoStatus(HashMap params) throws Exception { + masterMapper.updateInfoStatus(params); + } + +} diff --git a/src/main/resources/geoinfo/sqlmap/mappers/admins/mgmt/Mgmt_Api_SQL.xml b/src/main/resources/geoinfo/sqlmap/mappers/admins/mgmt/Mgmt_Api_SQL.xml new file mode 100644 index 0000000..01a213d --- /dev/null +++ b/src/main/resources/geoinfo/sqlmap/mappers/admins/mgmt/Mgmt_Api_SQL.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + UPDATE WEB_API_INBOUND + SET + + ACTIVE_YN = #{activeYn} + + WHERE IDX IN ( + + #{item} + + ) + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/admins/mgmtApi/api-request-statistics-index.jsp b/src/main/webapp/WEB-INF/views/admins/mgmtApi/api-request-statistics-index.jsp index 3599477..99f0287 100644 --- a/src/main/webapp/WEB-INF/views/admins/mgmtApi/api-request-statistics-index.jsp +++ b/src/main/webapp/WEB-INF/views/admins/mgmtApi/api-request-statistics-index.jsp @@ -52,38 +52,97 @@ .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; - } - .switch-title { font-weight: 600; } - .switch-desc { font-size: 12px; color: #777; } - - .mui-switch { - position: relative; 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; - } - .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; - } + .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이나
을 줄바꿈으로 인식 */ + } + + /* 스위치 디자인 */ + .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 { @@ -187,7 +246,7 @@

API 호출 통제

@@ -195,172 +254,10 @@
-
프로젝트 목록 조회
-
TBL_PROJECT_INFO 테이블에서 검색 조건에 해당하는 레코드를 모두 검색
-
- +
표시 할 API 목록이 존재하지 않습니다.
+
API를 등록해주세요.
+
- -
-
-
프로젝트 개수 조회
-
TBL_PROJECT_INFO 테이블에서 검색 조건에 해당하는 레코드의 개수를 조회
-
- -
- -
-
-
프로젝트 관련 하위 정보 개수 조회
-
특정 프로젝트에 속한 각 테이블(물리탐사, 시추조사, 각종 시험 등)의 데이터 개수를 조회
-
- -
- - - -
-
-
프로젝트 관련 하위 시추공 정보 개수 조회
-
특정 프로젝트에 속한 전체 시추공의 시험정보 개수를 조회
-
- -
- -
-
-
지형 및 지질 정보 조회
-
TBL_TOPO_GEOLOGY 테이블에서 특정 프로젝트의 지형 및 지질 정보를 조회
-
- -
- -
-
-
전기비저항탐사시험
-
TBL_RESISTIVITY_SURVEY 테이블에서 특정 프로젝트의 전기 비저항 탐사 정보를 조회
-
- -
- -
-
-
굴절법탄성파
-
TBL_REFRACTION_SURVEY 테이블에서 특정 프로젝트의 굴절법 탐사 정보를 조회
-
- -
- -
-
-
시추정보
-
사용자 작업용 API
-
- -
- -
-
-
지층정보
-
사용자 작업용 API
-
- -
- -
-
-
표준관입시험
-
사용자 작업용 API
-
- -
- -
-
-
절리정보
-
사용자 작업용 API
-
- -
- -
-
-
TCR RQD 시험정보
-
사용자 작업용 API
-
- -
- -
-
-
DSF 시험정보
-
사용자 작업용 API
-
- -
- -
-
-
RMR정보
-
사용자 작업용 API
-
- -
- -
-
-
Q시험정보
-
사용자 작업용 API
-
- -
- - @@ -471,8 +368,99 @@ animateValue("failRate", 0, 0, 1500); animateValue("delayRate", 0, 0.5, 1500); animateValue("errorRate", 0, 0, 1500); + + // API 호출 통제 목록 조회 + getMgmtApiList(); }); + + // API 호출 통제 목록 조회 + function getMgmtApiList(){ + $.ajax({ + type : "POST", + url : "/admins/mgmtApi/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 = ` +
+
+
\${item.idx} \${item.name}
+
\${item.desc.replace(/\\n/g, "
")}
+
+ +
+ `; + return html; + } + // Chart.js: 일일 접속량 const ctx = document.getElementById('trafficChart'); new Chart(ctx, { @@ -490,26 +478,6 @@ options: { plugins: { legend: { display: false } } } }); - // 일괄 On/Off - $("#globalSwitch").on("change", function() { - const enabled = $(this).is(":checked"); - $(".api-toggle").prop("checked", enabled).trigger("change"); - }); - - // 개별 토글 - $(".api-toggle").on("change", function() { - const apiName = $(this).data("api"); - const enabled = $(this).is(":checked"); - - $.ajax({ - url: "/api/control", - method: "POST", - data: { api: apiName, status: enabled }, - success: () => console.log(`API ${apiName} → ${enabled ? '활성' : '비활성'}`), -// error: () => return false; /*alert("API 상태 변경 실패")*/ - }); - }); - function refreshDashboard() { location.reload(); }