@@ -0,0 +1,120 @@
|
||||
<%@ page language="java" contentType="text/html; charset=utf-8"%>
|
||||
<%@ page import="java.util.List"%>
|
||||
<%@ page import="com.eactive.eai.rms.common.acl.sitemap.ui.SitemapNode"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%!
|
||||
private void printNodeLabel(javax.servlet.jsp.JspWriter out, SitemapNode node) throws java.io.IOException {
|
||||
String url = node.getMenuUrl();
|
||||
boolean hasLink = url != null && !url.trim().isEmpty() && !"NAN".equalsIgnoreCase(url.trim());
|
||||
if (hasLink) {
|
||||
out.print("<a href=\"javascript:void(0);\" class=\"sitemap-name\" onclick=\"goPage('"
|
||||
+ escapeJs(url) + "','" + escapeJs(node.getMenuId()) + "');return false;\">"
|
||||
+ escapeHtml(node.getMenuName()) + "</a>");
|
||||
} else {
|
||||
out.print("<span class=\"sitemap-name\">" + escapeHtml(node.getMenuName()) + "</span>");
|
||||
}
|
||||
}
|
||||
|
||||
private void printSitemapNode(javax.servlet.jsp.JspWriter out, SitemapNode node) throws java.io.IOException {
|
||||
out.print("<li>");
|
||||
printNodeLabel(out, node);
|
||||
|
||||
List<SitemapNode> children = node.getChildren();
|
||||
if (children != null && !children.isEmpty()) {
|
||||
out.print("<ul>");
|
||||
for (SitemapNode child : children) {
|
||||
printSitemapNode(out, child);
|
||||
}
|
||||
out.print("</ul>");
|
||||
}
|
||||
out.print("</li>");
|
||||
}
|
||||
|
||||
private String escapeHtml(String value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
return value.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """);
|
||||
}
|
||||
|
||||
private String escapeJs(String value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
return value.replace("\\", "\\\\").replace("'", "\\'");
|
||||
}
|
||||
%>
|
||||
<%
|
||||
response.setHeader("Pragma", "No-cache");
|
||||
response.setHeader("Cache-Control", "no-cache");
|
||||
response.setHeader("Expires", "0");
|
||||
|
||||
List<SitemapNode> sitemapTree = (List<SitemapNode>) request.getAttribute("sitemapTree");
|
||||
%>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<jsp:include page="/jsp/common/include/css.jsp"/>
|
||||
<jsp:include page="/jsp/common/include/script.jsp"/>
|
||||
<style>
|
||||
.sitemap-columns { display: flex; flex-wrap: wrap; gap: 40px; }
|
||||
.sitemap-column { min-width: 180px; }
|
||||
.sitemap-category { font-size: 1.1em; font-weight: bold; padding-bottom: 6px; margin-bottom: 8px; border-bottom: 2px solid #ccc; }
|
||||
.sitemap-tree, .sitemap-tree ul { list-style-type: disc; margin: 0; padding-left: 18px; }
|
||||
.sitemap-tree { padding-left: 0; list-style-type: none; }
|
||||
.sitemap-tree li { line-height: 1.8; }
|
||||
a.sitemap-name { text-decoration: none; cursor: pointer; }
|
||||
a.sitemap-name:hover { text-decoration: underline; }
|
||||
</style>
|
||||
<script language="javascript">
|
||||
function goPage(url, menuId) {
|
||||
var serviceType = sessionStorage["serviceType"];
|
||||
|
||||
var pageUrl = url;
|
||||
pageUrl += (pageUrl.indexOf("?") > -1 ? "&" : "?") + "menuId=" + menuId;
|
||||
pageUrl += "&serviceType=" + serviceType;
|
||||
|
||||
parent.leftFrame.location.href = '<c:url value="/leftMenu.do"/>?menuId=' + menuId + '&serviceType=' + serviceType;
|
||||
location.href = pageUrl;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="right_box">
|
||||
<div class="content_top">
|
||||
<ul class="path">
|
||||
<li><a href="#">${rmsMenuPath}</a></li>
|
||||
</ul>
|
||||
</div><!-- end content_top -->
|
||||
<div class="content_middle">
|
||||
<div class="title">사이트맵</div>
|
||||
<div class="sitemap-columns">
|
||||
<%
|
||||
for (SitemapNode category : sitemapTree) {
|
||||
%>
|
||||
<div class="sitemap-column">
|
||||
<div class="sitemap-category">
|
||||
<%
|
||||
printNodeLabel(out, category);
|
||||
%>
|
||||
</div>
|
||||
<ul class="sitemap-tree">
|
||||
<%
|
||||
List<SitemapNode> children = category.getChildren();
|
||||
if (children != null) {
|
||||
for (SitemapNode child : children) {
|
||||
printSitemapNode(out, child);
|
||||
}
|
||||
}
|
||||
%>
|
||||
</ul>
|
||||
</div>
|
||||
<%
|
||||
}
|
||||
%>
|
||||
</div>
|
||||
</div><!-- end content_middle -->
|
||||
</div><!-- end right_box -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -9,6 +9,8 @@
|
||||
<%@page import="com.eactive.eai.rms.common.util.StringUtils" %>
|
||||
<%@page import="com.eactive.eai.rms.common.datasource.DataSourceType" %>
|
||||
<%@page import="com.eactive.eai.rms.common.datasource.DataSourceTypeManager" %>
|
||||
<%@page import="com.eactive.eai.common.util.ApplicationContextProvider" %>
|
||||
<%@page import="com.eactive.eai.rms.data.entity.man.role.RoleMenuAuthService" %>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
|
||||
<%@ include file="/jsp/common/include/localemessage.jsp" %>
|
||||
@@ -16,6 +18,12 @@
|
||||
<%
|
||||
String serviceKey = SessionManager.getServiceTypeKey(request);
|
||||
String serviceText = DataSourceTypeManager.getDataSourceType(serviceKey).getText();
|
||||
|
||||
final String SITEMAP_MENU_ID = "0510013";
|
||||
RoleMenuAuthService roleMenuAuthService = ApplicationContextProvider.getContext().getBean(RoleMenuAuthService.class);
|
||||
String sitemapMenuAuth = roleMenuAuthService.getRoleList(SessionManager.getUserId(request), SITEMAP_MENU_ID, serviceKey);
|
||||
boolean showSitemapLink = "R".equals(sitemapMenuAuth) || "W".equals(sitemapMenuAuth);
|
||||
|
||||
String roleScreenId = (String) request.getAttribute("roleScreenId");
|
||||
String mainPage = (String) request.getAttribute("mainPage");
|
||||
String menuId = (String) request.getAttribute("menuId");
|
||||
@@ -240,6 +248,12 @@
|
||||
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="<c:url value="/css/web_ui.css"/>"/>
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="<c:url value="/css/theme_${themeColor}.css"/>"/>
|
||||
<style>
|
||||
.gnb .sitemap-link { display: inline-block; height: 80px; line-height: 80px; padding: 0 15px; font-size: 14px; color: #000; opacity: 0.7; vertical-align: top; }
|
||||
.gnb .sitemap-link:hover { opacity: 1; }
|
||||
.gnb.sitemap-hover { height: 80px !important; overflow-y: hidden !important; }
|
||||
.gnb.sitemap-hover + .gnb_bg { display: none !important; }
|
||||
</style>
|
||||
<script language="javascript" src="<c:url value="/js/jquery-1.12.1.min.js"/>"></script>
|
||||
<script language="javascript" src="<c:url value="/js/prefixfree.min.js"/>"></script>
|
||||
<script language="javascript" src="<c:url value="/js/jquery.cookie.js"/>"></script>
|
||||
@@ -529,6 +543,12 @@
|
||||
console.log("selectLocaleValue : " + selectLocaleValue);
|
||||
parent.changeLocale($(this).val());
|
||||
});
|
||||
|
||||
$('.sitemap-link').on('mouseenter', function () {
|
||||
$(this).closest('.gnb').addClass('sitemap-hover');
|
||||
}).on('mouseleave', function () {
|
||||
$(this).closest('.gnb').removeClass('sitemap-hover');
|
||||
});
|
||||
});
|
||||
|
||||
$(function() {
|
||||
@@ -610,6 +630,9 @@
|
||||
<%=subLayer.toString()%>
|
||||
</ul>
|
||||
</nav>
|
||||
<% if (showSitemapLink) { %>
|
||||
<a href="<c:url value="/common/acl/sitemap/sitemapMan.view"><c:param name="menuId" value="<%=SITEMAP_MENU_ID%>"/><c:param name="serviceType" value="<%=serviceKey%>"/></c:url>" target="mainFrame" class="sitemap-link">사이트맵</a>
|
||||
<% } %>
|
||||
</div><!-- end gnb -->
|
||||
<div class="gnb_bg"></div>
|
||||
</div><!-- end gnb_wrap -->
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.eactive.eai.rms.common.acl.sitemap;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import com.eactive.eai.rms.common.base.BaseAnnotationController;
|
||||
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
public class SitemapController extends BaseAnnotationController {
|
||||
|
||||
private final SitemapService sitemapService;
|
||||
|
||||
@GetMapping(value = "/common/acl/sitemap/sitemapMan.view")
|
||||
public String view(@RequestParam(value = "serviceType", required = false) String serviceType, Model model) {
|
||||
model.addAttribute("sitemapTree", sitemapService.getSitemapTree(serviceType));
|
||||
return "/common/acl/sitemap/sitemapMan";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.eactive.eai.rms.common.acl.sitemap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.eactive.eai.rms.common.acl.sitemap.ui.SitemapNode;
|
||||
|
||||
public interface SitemapService {
|
||||
|
||||
public List<SitemapNode> getSitemapTree(String serviceType);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.eactive.eai.rms.common.acl.sitemap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.eactive.eai.rms.common.acl.sitemap.ui.SitemapNode;
|
||||
import com.eactive.eai.rms.common.base.BaseService;
|
||||
import com.eactive.eai.rms.data.entity.man.menu.Menu;
|
||||
import com.eactive.eai.rms.data.entity.man.menu.MenuService;
|
||||
import com.eactive.eai.rms.data.entity.man.role.RoleMenuAuthService;
|
||||
|
||||
@Service("sitemapService")
|
||||
@Transactional(transactionManager = "transactionManagerForEMS")
|
||||
public class SitemapServiceImpl extends BaseService implements SitemapService {
|
||||
|
||||
@Autowired
|
||||
private MenuService menuService;
|
||||
|
||||
@Autowired
|
||||
private RoleMenuAuthService roleMenuAuthService;
|
||||
|
||||
public List<SitemapNode> getSitemapTree(String serviceType) {
|
||||
Menu root = menuService.getById("ROOT_DEV");
|
||||
Menu langRoot = findLangRoot(root);
|
||||
List<SitemapNode> tree = new ArrayList<>();
|
||||
if (langRoot == null) {
|
||||
return tree;
|
||||
}
|
||||
|
||||
Set<String> serviceTypeMenuIds = StringUtils.isBlank(serviceType)
|
||||
? null
|
||||
: new HashSet<>(roleMenuAuthService.findMenuIdsByServiceType(serviceType));
|
||||
|
||||
for (Menu menu : sortedChildren(langRoot)) {
|
||||
if (isVisible(menu) && matchesServiceType(menu, serviceTypeMenuIds)) {
|
||||
tree.add(buildNode(menu, serviceTypeMenuIds));
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
// 엔티티의 childMenus는 menuId 기준으로 정렬되어 있어, 실제 메뉴(운영화면 GNB)와 동일하게 sortOrder 기준으로 재정렬한다.
|
||||
private List<Menu> sortedChildren(Menu menu) {
|
||||
List<Menu> children = new ArrayList<>(menu.getChildMenus());
|
||||
children.sort(Comparator.comparing(Menu::getSortOrder, Comparator.nullsLast(Comparator.naturalOrder())));
|
||||
return children;
|
||||
}
|
||||
|
||||
// MenuService.getMenuList()의 GNB 렌더링과 동일하게 "ROOT"(한글)/"ROOT_EN"(영문) 이름의 언어별 루트를 찾는다.
|
||||
private Menu findLangRoot(Menu root) {
|
||||
String lang = LocaleContextHolder.getLocale().getLanguage();
|
||||
String langRootName = (StringUtils.isBlank(lang) || "ko".equalsIgnoreCase(lang))
|
||||
? "ROOT"
|
||||
: "ROOT_" + lang.toUpperCase();
|
||||
|
||||
return root.getChildMenus().stream()
|
||||
.filter(m -> langRootName.equalsIgnoreCase(m.getMenuName()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private SitemapNode buildNode(Menu menu, Set<String> serviceTypeMenuIds) {
|
||||
SitemapNode node = new SitemapNode(menu);
|
||||
for (Menu child : sortedChildren(menu)) {
|
||||
if (isVisible(child) && matchesServiceType(child, serviceTypeMenuIds)) {
|
||||
node.getChildren().add(buildNode(child, serviceTypeMenuIds));
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
private boolean isVisible(Menu menu) {
|
||||
return "Y".equalsIgnoreCase(menu.getDisplayYn()) && "Y".equalsIgnoreCase(menu.getUseYn());
|
||||
}
|
||||
|
||||
// serviceType 필터가 없으면 통과. 있으면 자신이나 하위메뉴 중 하나라도 해당 serviceType 권한이 있어야 통과(상위메뉴 누락 방지).
|
||||
private boolean matchesServiceType(Menu menu, Set<String> serviceTypeMenuIds) {
|
||||
if (serviceTypeMenuIds == null) {
|
||||
return true;
|
||||
}
|
||||
if (serviceTypeMenuIds.contains(menu.getMenuId())) {
|
||||
return true;
|
||||
}
|
||||
return menu.getChildMenus().stream().anyMatch(child -> matchesServiceType(child, serviceTypeMenuIds));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.eactive.eai.rms.common.acl.sitemap.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.eactive.eai.rms.data.entity.man.menu.Menu;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SitemapNode {
|
||||
|
||||
private String menuId;
|
||||
|
||||
private String menuName;
|
||||
|
||||
private String menuUrl;
|
||||
|
||||
private List<SitemapNode> children = new ArrayList<>();
|
||||
|
||||
public SitemapNode(Menu menu) {
|
||||
this.menuId = menu.getMenuId();
|
||||
this.menuName = menu.getMenuName();
|
||||
this.menuUrl = menu.getMenuUrl();
|
||||
}
|
||||
|
||||
public SitemapNode() {
|
||||
}
|
||||
}
|
||||
@@ -51,4 +51,17 @@ public class RoleMenuAuthService extends AbstractEMSDataSerivce<RoleMenuAuth, Ro
|
||||
.fetch();
|
||||
}
|
||||
|
||||
public List<String> findMenuIdsByServiceType(String serviceType) {
|
||||
|
||||
QRoleMenuAuth qRoleMenuAuth = QRoleMenuAuth.roleMenuAuth;
|
||||
|
||||
return getJPAQueryFactory()
|
||||
.select(qRoleMenuAuth.id.menuId)
|
||||
.distinct()
|
||||
.from(qRoleMenuAuth)
|
||||
.where(qRoleMenuAuth.id.serviceType.eq(serviceType))
|
||||
.setHint(QueryHints.CACHEABLE, true)
|
||||
.fetch();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user