알람기능 작업 완료.

강석 최 2022-11-24 18:00:50 +09:00
parent 698616fb80
commit 16b7570b56
17 changed files with 293 additions and 5 deletions

View File

@ -24,7 +24,6 @@ public class BaseController {
private final CodeMgtService codeMgtService;
private final OrganConfigService organConfigService;
private final MenuMgtService menuMgtService;
private final UserInfoService userInfoService;
@GetMapping("/")
public ModelAndView loginCheck(@AuthenticationPrincipal UserInfo loginUser) {

View File

@ -37,6 +37,8 @@ public class BaseModel {
private String endDate;
@Transient
private Boolean dashboardFlag = false;
@Transient
private Integer refDocKey;
public void setQueryInfo(){
setFirstIndex((getPageIndex()-1)*getRowCnt());

View File

@ -32,6 +32,7 @@ public class FaispInterceptor implements HandlerInterceptor {
param.setViewYn("N");
param.setQueryInfo();
mav.addObject("alarmList", userAlarmService.selectAlarmList(param));
mav.addObject("alarmListCnt", userAlarmService.selectAlarmListCnt(param));
}
}
}

View File

@ -167,4 +167,9 @@ public class MenuMgtService {
});
return firstMenuList;
}
public String selectMenuUrl(Integer menuKey) {
MenuMgt menuMgt = menuMgtRepository.findById(menuKey).orElse(new MenuMgt());
return menuMgt.getMenuUrl();
}
}

View File

@ -2,8 +2,11 @@ package com.dbnt.faisp.main.userInfo;
import com.dbnt.faisp.kwms.service.KwmsService;
import com.dbnt.faisp.main.codeMgt.service.CodeMgtService;
import com.dbnt.faisp.main.menuMgt.service.MenuMgtService;
import com.dbnt.faisp.main.userInfo.model.DashboardConfig;
import com.dbnt.faisp.main.userInfo.model.UserAlarm;
import com.dbnt.faisp.main.userInfo.model.UserInfo;
import com.dbnt.faisp.main.userInfo.service.UserAlarmService;
import com.dbnt.faisp.main.userInfo.service.UserInfoService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
@ -19,6 +22,8 @@ public class MyInfoController {
private final UserInfoService userInfoService;
private final CodeMgtService codeMgtService;
private final UserAlarmService userAlarmService;
private final MenuMgtService menuMgtService;
private final KwmsService kwmsService;
@GetMapping("/myInfoPage")
@ -70,4 +75,27 @@ public class MyInfoController {
userInfoService.updateUserInfo(loginUser,kwmsInfo);
}
}
@GetMapping("/moveAlarmBoard")
public ModelAndView moveAlarmBoard(UserAlarm alarm){
alarm = userAlarmService.selectAlarm(alarm);
String url = menuMgtService.selectMenuUrl(alarm.getMenuKey());
if(url.contains("?")){
url+="&refDocKey="+alarm.getRefDocKey();
}else{
url+="?refDocKey="+alarm.getRefDocKey();
}
return new ModelAndView("redirect:"+url);
}
@GetMapping("/myAlarm")
public ModelAndView myAlarm(@AuthenticationPrincipal UserInfo loginUser, UserAlarm alarm){
ModelAndView mav = new ModelAndView("user/myAlarm");
alarm.setQueryInfo();
alarm.setUserSeq(loginUser.getUserSeq());
mav.addObject("pageAlarmList", userAlarmService.selectAlarmList(alarm));
alarm.setContentCnt(userAlarmService.selectAlarmListCnt(alarm));
alarm.setPaginationInfo();
mav.addObject("searchParams", alarm);
return mav;
}
}

View File

@ -37,6 +37,13 @@ public class UserAlarm extends BaseModel {
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime wrtDt;
@Transient
private String cat1Cd;
@Transient
private String cat2Cd;
@Transient
private String cat3Cd;
@Embeddable
@Data
@NoArgsConstructor

View File

@ -63,4 +63,16 @@ public class UserAlarmService {
alarmList.add(alarm);
saveAlarmList(alarmList);
}
public UserAlarm selectAlarm(UserAlarm alarm) {
alarm = userAlarmRepository.findById(new UserAlarm.UserAlarmId(alarm.getAlarmKey(), alarm.getUserSeq())).orElse(null);
alarm.setViewYn("Y");
updateAlarm(alarm);
return alarm;
}
@Transactional
public void updateAlarm(UserAlarm alarm) {
userAlarmRepository.save(alarm);
}
}

View File

@ -393,19 +393,24 @@
<if test='userSeq != null and userSeq != 0'>
and a.user_seq = #{userSeq}
</if>
<if test='viewYn != null and viewYn != ""'>
and a.view_yn = #{viewYn}
</if>
</where>
</sql>
<select id="selectAlarmList" resultType="UserAlarm" parameterType="UserAlarm">
select a.alarm_key ,
a.user_seq ,
a.menu_key ,
b.menu_url ,
a.ref_doc_key ,
b.cat1_cd,
b.cat2_cd,
b.cat3_cd,
a.alarm_msg ,
a.view_yn ,
a.wrt_dt
from user_alarm a
inner join menu_mgt b on a.menu_key = b.menu_key
inner join menu_mgt b on a.menu_key = b.menu_key
<include refid="selectAlarmListWhere"></include>
order by wrt_dt desc
limit #{rowCnt} offset #{firstIndex}
@ -413,7 +418,7 @@
<select id="selectAlarmListCnt" resultType="int" parameterType="UserAlarm">
select count(*)
from user_alarm a
inner join menu_mgt b on a.menu_key = b.menu_key
inner join menu_mgt b on a.menu_key = b.menu_key
<include refid="selectAlarmListWhere"></include>
</select>
</mapper>

View File

@ -1,3 +1,4 @@
#fadeDiv{
width: 100%;
height: 100%;
@ -34,6 +35,19 @@
background-color: #ffffff;
}
#alarmCntDiv{
width: 16px;
height: 16px;
left: 12px;
top: -4px;
}
#alarmListDiv{
width: 500px;
left: -300px;
top: 30px;
z-index: 5000;
}
.activeTr{
--bs-bg-opacity: 0.25;
background-color: rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important;

View File

@ -16,6 +16,20 @@ function searchFade(action){
}
}
$(document).on('click', '#bellIcon', function (){
const alarmListDiv = $("#alarmListDiv")[0];
if(alarmListDiv.className.includes('d-none')){
alarmListDiv.className = "position-absolute bg-white card";
}else{
alarmListDiv.className = "position-absolute bg-white card d-none";
}
})
$(document).on('click', '.alarmTr', function (){
location.href = "/myInfo/moveAlarmBoard?" +
"alarmKey="+$(this).find(".alarmKey").val()+
"&userSeq="+$(this).find(".userSeq").val();
})
$(document).on('click', '.allChk', function (){
$(this).parents('table').find('[type="checkbox"]').prop("checked", this.checked);
})

View File

@ -1,5 +1,14 @@
let selectedList = [];
$(function(){
if(location.search.includes("refDocKey")){
const params = location.search.split('&');
$.each(params, function (idx, param){
if(param.includes("refDocKey")){
const faRptKey = param.slice(param.indexOf("=")+1, param.length);
getFaRptViewModal(faRptKey);
}
})
}
$("#dateSelectorDiv").datepicker({
format: "yyyy-mm-dd",
language: "ko",

View File

@ -1,5 +1,14 @@
$(function(){
if(location.search.includes("refDocKey")){
const params = location.search.split('&');
$.each(params, function (idx, param){
if(param.includes("refDocKey")){
const key = param.slice(param.indexOf("=")+1, param.length);
getAffairViewModal(key);
}
})
}
$("#dateSelectorDiv").datepicker({
format: "yyyy-mm-dd",
language: "ko",

View File

@ -1,5 +1,14 @@
$(function(){
if(location.search.includes("refDocKey")){
const params = location.search.split('&');
$.each(params, function (idx, param){
if(param.includes("refDocKey")){
const key = param.slice(param.indexOf("=")+1, param.length);
getPlanViewModal(key);
}
})
}
$("#dateSelectorDiv").datepicker({
format: "yyyy-mm-dd",
language: "ko",

View File

@ -1,5 +1,14 @@
$(function(){
if(location.search.includes("refDocKey")){
const params = location.search.split('&');
$.each(params, function (idx, param){
if(param.includes("refDocKey")){
const key = param.slice(param.indexOf("=")+1, param.length);
getResultViewModal(key);
}
})
}
$("#dateSelectorDiv").datepicker({
format: "yyyy-mm-dd",
language: "ko",

View File

@ -1,5 +1,17 @@
let selectedList = [];
$(function() {
if (location.search.includes("refDocKey")) {
const params = location.search.split('&');
$.each(params, function (idx, param) {
if (param.includes("refDocKey")) {
const key = param.slice(param.indexOf("=") + 1, param.length);
getSriViewModal(key);
}
})
}
})
$(document).on('click', '#addSriBtn', function (){
getSriEditModal({faSriKey: null})
})

View File

@ -50,7 +50,43 @@
</div>
<div class="col-auto my-auto">
<ul class="nav nav-pills" sec:authorize="isAuthenticated()">
<li class="nav-item"><a href="#" class="nav-link" th:classappend="${#lists.isEmpty(alarmList)?'link-dark':'link-danger'}"><i class="bi bi-bell-fill"></i></a></li>
<li class="nav-item">
<a href="#" class="nav-link" th:classappend="${#lists.isEmpty(alarmList)?'link-dark':'link-danger'}">
<th:block th:if="${!#lists.isEmpty(alarmList)}">
<div class="position-relative">
<div id="alarmCntDiv" class="position-absolute text-center rounded-circle bg-danger text-white fs-11" th:text="${alarmListCnt}"></div>
<div id="alarmListDiv" class="position-absolute bg-white card d-none">
<div class="card-body">
<table class="table table-bordered table-hover">
<thead>
<tr class="table-secondary">
<th>메시지</th>
<th>발생일</th>
</tr>
</thead>
<tbody class="table-group-divider">
<tr class="alarmTr" th:each="alarm:${alarmList}">
<input type="hidden" class="alarmKey" th:value="${alarm.alarmKey}">
<input type="hidden" class="userSeq" th:value="${alarm.userSeq}">
<td th:text="${alarm.alarmMsg}"></td>
<td th:text="${#temporals.format(alarm.wrtDt, 'yyyy-MM-dd HH:mm:ss')}"></td>
</tr>
</tbody>
<tfoot th:if="${alarmListCnt>10}">
<tr>
<td colspan="2">더보기</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</th:block>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bell-fill" viewBox="0 0 16 16" th:id="${#lists.isEmpty(alarmList)?'':'bellIcon'}">
<path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zm.995-14.901a1 1 0 1 0-1.99 0A5.002 5.002 0 0 0 3 6c0 1.098-.5 6-2 7h14c-1.5-1-2-5.902-2-7 0-2.42-1.72-4.44-4.005-4.901z"/>
</svg>
</a>
</li>
<li class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle text-black" data-bs-toggle="dropdown" aria-expanded="false">
<th:block th:each="commonCode:${session.commonCode.get('JT')}">
@ -62,6 +98,7 @@
</a>
<ul class="dropdown-menu">
<li><a href="/myInfo/myInfoPage" class="dropdown-item">마이페이지</a></li>
<li><a href="/myInfo/myAlarm" class="dropdown-item">수신알람</a></li>
<li><a href="/logout" class="dropdown-item">로그아웃</a></li>
</ul>
</li>

View File

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout}">
<div layout:fragment="content">
<main class="pt-3">
<h4>수신 알람 목록</h4>
<div class="row mx-0">
<div class="col-12 card">
<div class="card-body">
<form method="get" th:action="@{/myInfo/noticePage}">
<input type="hidden" name="pageIndex" id="pageIndex" th:value="${searchParams.pageIndex}">
<div class="row justify-content-between pe-3 py-1">
<div class="col-auto">
<select class="form-select form-select-sm" name="rowCnt" id="rowCnt">
<th:block th:each="num : ${#numbers.sequence(1,5)}">
<option th:value="${num*10}" th:text="${num*10}" th:selected="${searchParams.rowCnt eq num*10}"></option>
</th:block>
</select>
</div>
<div class="col-auto">
<div class="row justify-content-end">
<div class="col-4">
<div class="input-group w-auto input-daterange" id="dateSelectorDiv">
<input type="text" class="form-control form-control-sm" id="startDate" name="startDate" placeholder="시작일" autocomplete="off" readonly th:value="${searchParams.startDate}">
<input type="text" class="form-control form-control-sm" id="endDate" name="endDate" placeholder="종료일" autocomplete="off" readonly th:value="${searchParams.endDate}">
</div>
</div>
<input type="submit" class="btn btn-sm btn-primary col-auto" id="searchBtn" value="검색">
</div>
</div>
</div>
</form>
<div class="row justify-content-start">
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="row">
<table class="table table-hover table-bordered">
<thead>
<tr class="table-secondary">
<th>대분류</th>
<th>중분류</th>
<th>소분류</th>
<th>메시지</th>
<th>열람여부</th>
<th>등록일시</th>
</tr>
</thead>
<tbody class="table-group-divider">
<tr class="alarmTr" th:each="alarm:${pageAlarmList}">
<input type="hidden" class="alarmKey" th:value="${alarm.alarmKey}">
<input type="hidden" class="userSeq" th:value="${alarm.userSeq}">
<td>
<th:block th:each="code:${session.commonCode.get('CAT1')}">
<th:block th:if="${code.itemCd eq alarm.cat1Cd}" th:text="${code.itemValue}"></th:block>
</th:block>
</td>
<td>
<th:block th:each="code:${session.commonCode.get('CAT2')}">
<th:block th:if="${code.itemCd eq alarm.cat2Cd}" th:text="${code.itemValue}"></th:block>
</th:block>
</td>
<td>
<th:block th:each="code:${session.commonCode.get('CAT3')}">
<th:block th:if="${code.itemCd eq alarm.cat3Cd}" th:text="${code.itemValue}"></th:block>
</th:block>
</td>
<td th:text="${alarm.alarmMsg}"></td>
<td th:text="${alarm.viewYn eq 'Y'?'O':'X'}"></td>
<td th:text="${#temporals.format(alarm.wrtDt, 'yyyy-MM-dd HH:mm:ss')}"></td>
</tr>
</tbody>
</table>
</div>
<div class="row justify-content-between">
<div class="col-auto"></div>
<div class="col-auto">
<nav aria-label="Page navigation">
<ul class="pagination">
<th:block th:if="${searchParams.pageIndex>3}">
<li class="page-item" th:data-pageindex="${(searchParams.pageIndex)-3}">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
</th:block>
<th:block th:each="num : ${#numbers.sequence(searchParams.startNum, searchParams.endNum)}">
<li class="page-item" th:data-pageindex="${num}" th:classappend="${searchParams.pageIndex eq num?'active':''}">
<a class="page-link" href="#" th:text="${num}"></a>
</li>
</th:block>
<th:block th:if="${searchParams.maxNum>searchParams.endNum+2}">
<li class="page-item" th:data-pageindex="${(searchParams.pageIndex)+3}">
<a class="page-link" href="#" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
</th:block>
</ul>
</nav>
</div>
<div class="col-auto">
<input type="button" class="btn btn-success" value="등록" id="addNoticeBtn" sec:authorize="hasRole('ROLE_SUB_ADMIN')">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</html>