Merge remote-tracking branch 'origin/master'

This commit is contained in:
JSYOO 2021-09-09 11:27:32 +09:00
commit fb660a7138
12 changed files with 223 additions and 21 deletions

View File

@ -1,5 +1,6 @@
package nlib.cmm; package nlib.cmm;
import java.lang.reflect.Method;
import java.util.Base64; import java.util.Base64;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -22,7 +23,6 @@ import org.springframework.web.servlet.support.RequestContextUtils;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import nlib.bbs.web.BoardController;
import nlib.cmm.exception.ErrorMessage; import nlib.cmm.exception.ErrorMessage;
import nlib.restful.service.DataApiResVO; import nlib.restful.service.DataApiResVO;
import nlib.security.SecUserVO; import nlib.security.SecUserVO;
@ -79,6 +79,83 @@ public class NlibCommonController {
return (NlibLoginVO)authentication.getPrincipal(); return (NlibLoginVO)authentication.getPrincipal();
} }
public NlibLoginVO getNlibLoginVO(HttpServletRequest request) {
Authentication auth = (Authentication)request.getUserPrincipal();
if(auth == null || !auth.isAuthenticated()) return new NlibLoginVO();
NlibLoginVO loginVO = (NlibLoginVO)auth.getPrincipal();
if(loginVO == null || StringUtil.isEmpty(loginVO.getMbInfoId())) return new NlibLoginVO();
return loginVO;
}
/**
* 인증에 저장된 사용자 로그인 정보 VO의 값을 매개변수값으로 대체하여 저장하고 돌려 준다.
*
* @param request
* @param newLoginVO
* @return
*/
public NlibLoginVO replaceNlibLoginVO(HttpServletRequest request, NlibLoginVO newLoginVO) {
if(newLoginVO == null) return null;
Authentication auth = (Authentication)request.getUserPrincipal();
if(auth == null || !auth.isAuthenticated()) return new NlibLoginVO();
NlibLoginVO loginVO = getNlibLoginVO(request);
if(loginVO == null) return null;
if(!loginVO.getMbInfoId().equals(newLoginVO.getMbInfoId())) {
log.error("replaceNlibLoginVO > 서로 다른 사용자 정보이므로 인증 LoginVO 정보를 변경할 수 없습니다.");
return null;
}
// 복사작업
Method[] methods = NlibLoginVO.class.getMethods();
String mName;
HashMap<String, Method> setterNames = new HashMap<String, Method>();
HashMap<String, Method> getterNames = new HashMap<String, Method>();
final String skipSetterList = "|setIp|setAlerted|setAuthKey|setAuthorityList|";
for(Method m : methods) {
mName = m.getName();
if(skipSetterList.contains(mName)) continue;
//log.debug("NlibLoginVO : methods > " + m.getName());
if(mName.toUpperCase().startsWith("SET")) setterNames.put(mName, m);
else if(mName.toUpperCase().startsWith("GET")) getterNames.put(mName, m);
else if(mName.toUpperCase().startsWith("IS")) getterNames.put(mName, m);
}
String getterName;
for(String setterName : setterNames.keySet()) {
getterName = "get" + setterName.substring(3);
Method setter = setterNames.get(setterName);
Method getter = getterNames.get(getterName);
if(setter != null && getter != null) {
try {
String oldValue = (String)getter.invoke(loginVO);
String newValue = (String)getter.invoke(newLoginVO);
setter.invoke(loginVO, getter.invoke(newLoginVO));
//log.debug("replaceNlibLoginVO > Method invoke : " + setterName + " : " + oldValue + " -> " + newValue);
} catch(Exception e) {
log.error("replaceNlibLoginVO > Method invoke error : " + setterName + ", " + getterName);
e.printStackTrace();
}
}
}
return loginVO;
}
/** /**
* 사용자로그인정보 ID를 리턴한다. * 사용자로그인정보 ID를 리턴한다.
* 로그인하지 않은 경우, null을 리턴한다. * 로그인하지 않은 경우, null을 리턴한다.
@ -353,4 +430,18 @@ public class NlibCommonController {
return getCurCouncilInfo(request, INFO_ID_COUNCIL_NM); return getCurCouncilInfo(request, INFO_ID_COUNCIL_NM);
} }
public void setAlerted(HttpServletRequest request, boolean alerted) {
NlibLoginVO nlibLoginVO = getNlibLoginVO(request);
if(nlibLoginVO == null) return;
nlibLoginVO.setAlerted(alerted);
return;
}
public boolean isAlerted(HttpServletRequest request) {
NlibLoginVO nlibLoginVO = getNlibLoginVO(request);
if(nlibLoginVO == null) return false;
return nlibLoginVO.isAlerted();
}
} }

View File

@ -16,6 +16,16 @@ public interface AlertService
public List<AlertVO> listAlerts(AlertVO alertVO) throws Exception; public List<AlertVO> listAlerts(AlertVO alertVO) throws Exception;
/**
* 읽지 않은 알림 건수를 조회한다.
*
* @param mbInfoId
* @return
* @throws Exception
*/
public int countUnreadAlert(String mbInfoId) throws Exception;
// /* // /*
// * 사용자 미확인 신규 알림 건수를 조회한다. // * 사용자 미확인 신규 알림 건수를 조회한다.
// */ // */

View File

@ -48,4 +48,11 @@ public class AlertDAO extends EgovComAbstractDAO {
return selectList("AlertDAO.listAlerts", searchAlertVO); return selectList("AlertDAO.listAlerts", searchAlertVO);
} }
/*
* 사용자가 확인하지 않은 알림 건수를 조회한다.
*/
public int countUnreadAlert(String mbInfoId) throws Exception {
return selectOne("AlertDAO.countUnreadAlert", mbInfoId);
}
} }

View File

@ -24,7 +24,7 @@ public class AlertServiceImpl implements AlertService
@Resource(name="alertDAO") @Resource(name="alertDAO")
private AlertDAO alertDAO; private AlertDAO alertDAO;
/* /**
* 사용자 알림 목록을 조회한다. * 사용자 알림 목록을 조회한다.
*/ */
public List<AlertVO> listAlerts(AlertVO alertVO) throws Exception { public List<AlertVO> listAlerts(AlertVO alertVO) throws Exception {
@ -32,6 +32,19 @@ public class AlertServiceImpl implements AlertService
return alertDAO.listAlerts(alertVO); return alertDAO.listAlerts(alertVO);
} }
/**
* 읽지 않은 알림 건수를 조회한다.
*
* @param mbInfoId
* @return
* @throws Exception
*/
public int countUnreadAlert(String mbInfoId) throws Exception {
return alertDAO.countUnreadAlert(mbInfoId);
}
// //
// /* // /*
// * 사용자 미확인 신규 알림 건수를 조회한다. // * 사용자 미확인 신규 알림 건수를 조회한다.

View File

@ -26,7 +26,7 @@ public class CodeController extends NlibCommonController {
private CodeService codeService; private CodeService codeService;
@RequestMapping( {"/code/listCodes.do"} ) @RequestMapping( {"/code/listCodes.do"} )
public String setContent(HttpServletRequest req, @RequestParam Map<String, String> paramMap, ModelMap model) throws Exception { public String listCodes(HttpServletRequest req, @RequestParam Map<String, String> paramMap, ModelMap model) throws Exception {
String lCodeId = paramMap.get("lCodeId"); String lCodeId = paramMap.get("lCodeId");
@ -37,4 +37,16 @@ public class CodeController extends NlibCommonController {
return "nlib/code/listCodes"; return "nlib/code/listCodes";
} }
@RequestMapping( {"/code/listCodesPopup.do"} )
public String listCodesPopup(HttpServletRequest req, @RequestParam Map<String, String> paramMap, ModelMap model) throws Exception {
String lCodeId = paramMap.get("lCodeId");
List<HashMap<String, String>> resultList = codeService.listCodes(lCodeId);
model.addAttribute("resultList", resultList);
model.addAttribute("lCodeId", lCodeId);
return "nlib/code/listCodesPopup";
}
} }

View File

@ -1,5 +1,6 @@
package nlib.cmm.web; package nlib.cmm.web;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -8,11 +9,15 @@ import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache; import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache; import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import nlib.cmm.NlibCommonController;
import nlib.cmm.service.AlertService;
import nlib.user.service.NlibLoginVO;
import nlib.util.StringUtil;
/** /**
* <pre> * <pre>
* @Class Name : MainController.java * @Class Name : MainController.java
@ -36,22 +41,36 @@ import org.springframework.web.bind.annotation.RequestMapping;
* *
*/ */
@Controller @Controller
public class MainController { public class MainController extends NlibCommonController {
private static final Logger log = LoggerFactory.getLogger(MainController.class); private static final Logger log = LoggerFactory.getLogger(MainController.class);
@Resource(name="alertService")
private AlertService alertService;
@RequestMapping( {"/index.do"} ) @RequestMapping( {"/index.do"} )
public String setContent( public String setContent(
HttpServletRequest req, HttpServletRequest req,
HttpServletResponse res, HttpServletResponse res,
Authentication authentication, Authentication authentication,
ModelMap model) { ModelMap model) throws Exception {
// 캐쉬된 Reqeust 히스토리 삭제 // 캐쉬된 Reqeust 히스토리 삭제
RequestCache cache = new HttpSessionRequestCache(); RequestCache cache = new HttpSessionRequestCache();
cache.removeRequest(req, res); cache.removeRequest(req, res);
log.debug((authentication == null ? "손님 메인 접속" : authentication.getName() + " 메인 접속")); log.debug((authentication == null ? "손님 메인 접속" : authentication.getName() + " 메인 접속"));
// 알림 확인
String mbInfoId = getMbInfoId(req);
int unreadAlertCnt = 0;
if(!isAlerted(req) && StringUtil.isNotEmpty(mbInfoId)) {
unreadAlertCnt = alertService.countUnreadAlert(mbInfoId);
setAlerted(req, true);
}
model.addAttribute("unreadAlertCnt", unreadAlertCnt);
return "nlib/cmm/home"; return "nlib/cmm/home";
} }

View File

@ -23,4 +23,13 @@
]]> ]]>
</select> </select>
<select id="countUnreadAlert" parameterType="String" resultType="Integer">
<![CDATA[
SELECT COUNT(NLIB_ALERT_ID) AS UNREAD_CNT
FROM TMP_NLIB_ALERT A
WHERE A.MB_INFO_ID = #{mbInfoId}
AND A.READ_DD IS NULL
]]>
</select>
</mapper> </mapper>

View File

@ -16,3 +16,10 @@
회원가입 후, 이용하여 주시기 바랍니다. 회원가입 후, 이용하여 주시기 바랍니다.
</sec:authorize> </sec:authorize>
<script type="text/javascript">
window.onload = function() {
fn_myAlert(${unreadAlertCnt});
};
</script>

View File

@ -1,4 +1,4 @@
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<a href="javascript:void(0);" onclick="window.close();" class="floatRight">닫기</a> <a href="javascript:void(0);" onclick="$('#myPop').html('');$('#myPop').hide();" class="floatRight">닫기</a>

View File

@ -53,5 +53,7 @@ $( document ).ready(function() {
</div> </div>
</div> </div>
<div id="NLIB_LAYER_POPUP" style="z-index:100; display:none; margin-left:20px !important; position:fixed; top:100px;left:20%; width:500px; height:auto; min-height:200px; max-height:500px; border:3px solid black !important; overflow:scroll; background-color:#eeeeaa; "></div>
</body> </body>
</html> </html>

View File

@ -40,7 +40,8 @@ html, body { height: 100%; }
position: relative; position: relative;
display: block; display: block;
padding: 20px; padding: 20px;
top:120px; /*top:120px;*/
min-height:300px;
padding-bottom: 100px; padding-bottom: 100px;
} }
@ -79,7 +80,7 @@ html, body { height: 100%; }
width: 100%; width: 100%;
height: 60px; height: 60px;
font-weight:bolder; font-weight:bolder;
position: fixed; /*position: fixed;*/
background: #fff; background: #fff;
padding: 20px; padding: 20px;
color: #000; color: #000;
@ -91,7 +92,7 @@ html, body { height: 100%; }
#menu { #menu {
width: 100%; width: 100%;
height: 60px; /* Footer height */ height: 60px; /* Footer height */
position: fixed; /*position: fixed;*/
top:60px; top:60px;
font-weight:bold; font-weight:bold;
background: #2781C1; background: #2781C1;
@ -105,7 +106,7 @@ html, body { height: 100%; }
padding: 1rem; padding: 1rem;
color: #AAAAAA; color: #AAAAAA;
background-color: #333333; background-color: #333333;
position: fixed; /*position: fixed;*/
width: 100%; width: 100%;
display: block; display: block;
text-align: center; text-align: center;
@ -174,7 +175,7 @@ button {
#menu-popup { #menu-popup {
width: 100%; width: 100%;
height: 60px; /* Footer height */ height: 60px; /* Footer height */
position: fixed; /*position: fixed;*/
top:0px; top:0px;
font-weight:bold; font-weight:bold;
background: #278100; background: #278100;
@ -186,17 +187,15 @@ button {
#content-wrap-popup { #content-wrap-popup {
position: relative; position: relative;
display: block; display: block;
padding: 20px; padding: 0px;
top:60px; top:60px;
padding-bottom: 100px; padding-bottom: 100px;
} }
#content-wrap-popup h1 { #content-wrap-popup h1 {
position: fixed; position: relative;
top:5px; color: black;
z-index: 10001;
color: white;
} }
#footer-popup { #footer-popup {

View File

@ -6,6 +6,7 @@
* *
*/ */
var CONTEXT_PATH = "/nlib";
// 팝업으로 비밀번호를 입력받아서 콜백함수에 전달한다. // 팝업으로 비밀번호를 입력받아서 콜백함수에 전달한다.
function fn_promptPassword(msg, placeholder, callbackFucName) { function fn_promptPassword(msg, placeholder, callbackFucName) {
@ -67,3 +68,35 @@ function validEmail(email) {
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(String(email).toLowerCase()); return re.test(String(email).toLowerCase());
} }
function fn_openLayerPopup(title, content, linkName, linkUrl) {
var layerPopupHtml =
"<h2>" + title + "</h2><br/>" +
"<div>" + content + "</div><br/>" +
"<br/>&nbsp;" +
"<div style='text-align:center;'><a href='#' onclick='fn_closeLayerPopup()'>[확인]</a>";
if(linkUrl != null) {
layerPopupHtml += "&nbsp;&nbsp;&nbsp;&nbsp;<a href='" + linkUrl + "'>[" + linkName + "]</a>";
}
layerPopupHtml += "</div>";
$(layerPopupHtml).appendTo("#NLIB_LAYER_POPUP");
$("#NLIB_LAYER_POPUP").show();
console.log(layerPopupHtml);
}
function fn_closeLayerPopup() {
$("#NLB_LAYER_POPUP").html("");
$("#NLIB_LAYER_POPUP").hide();
}
function fn_myAlert(newAlertNum) {
if(newAlertNum == "undefined" || newAlertNum == null || newAlertNum < 1) {
return;
}
fn_openLayerPopup("알림", "아직 확인하지 않은 새로운 알림이 " + newAlertNum + "건 있습니다", "알림 목록으로", CONTEXT_PATH + "/cmm/listAlerts.do");
}