관리자 관리 , 권환 관리 빈 페이지 및 Entity, Data 추가
This commit is contained in:
parent
b27fbb4296
commit
86d76b6d38
|
|
@ -21,7 +21,7 @@ dependencies {
|
||||||
|
|
||||||
// thymeleaf
|
// thymeleaf
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
|
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.3.0'
|
||||||
|
|
||||||
// jpa
|
// jpa
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||||
|
|
|
||||||
|
|
@ -13,16 +13,19 @@ public class Administrator extends BaseEntity {
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Column(name = "login_id")
|
@Column(name = "login_id", length = 100, nullable = false)
|
||||||
private String loginId;
|
private String loginId;
|
||||||
|
|
||||||
@Column(name = "password")
|
@Column(name = "password", length = 255, nullable = false)
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@Column(name = "email")
|
@Column(name = "email", length = 100, nullable = false)
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@Column(name = "name")
|
@Column(name = "name", length = 100, nullable = false)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
@OneToOne(mappedBy = "administrator", fetch = FetchType.LAZY)
|
||||||
|
private AdministratorRole administratorRole;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.bpgroup.poc.admin.domain.admin;
|
||||||
|
|
||||||
|
import com.bpgroup.poc.admin.domain.BaseEntity;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Entity
|
||||||
|
@Table(name = "administrator_role")
|
||||||
|
public class AdministratorRole extends BaseEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||||
|
@JoinColumn(name = "administrator_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||||
|
private Administrator administrator;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||||
|
@JoinColumn(name = "role_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||||
|
private Role role;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.bpgroup.poc.admin.domain.admin;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum Menu {
|
||||||
|
ADMINISTRATOR_MANAGEMENT("/admin/management", "관리자 관리"),
|
||||||
|
ROLE_MANAGEMENT("/admin/role", "권한 관리"),
|
||||||
|
MENU_MANAGEMENT("/admin/menu", "메뉴 관리")
|
||||||
|
;
|
||||||
|
|
||||||
|
private final String uri;
|
||||||
|
private final String name;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.bpgroup.poc.admin.domain.admin;
|
||||||
|
|
||||||
|
import com.bpgroup.poc.admin.domain.BaseEntity;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "role")
|
||||||
|
public class Role extends BaseEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "name", length = 100, nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(name = "description")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "role", fetch = FetchType.LAZY)
|
||||||
|
private List<RoleMenu> roleMenus = new ArrayList<>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.bpgroup.poc.admin.domain.admin;
|
||||||
|
|
||||||
|
import com.bpgroup.poc.admin.domain.BaseEntity;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
@Table
|
||||||
|
@Entity(name = "role_menu")
|
||||||
|
public class RoleMenu extends BaseEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||||
|
@JoinColumn(name = "role_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||||
|
private Role role;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(name = "menu", length = 100, nullable = false)
|
||||||
|
private Menu menu;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.bpgroup.poc.admin.domain.admin;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface RoleRepository extends JpaRepository<Role, Long> {
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ package com.bpgroup.poc.admin.security;
|
||||||
|
|
||||||
import com.bpgroup.poc.admin.common.FormatHelper;
|
import com.bpgroup.poc.admin.common.FormatHelper;
|
||||||
import com.bpgroup.poc.admin.security.authentication.AuthenticationFailException;
|
import com.bpgroup.poc.admin.security.authentication.AuthenticationFailException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
|
@ -15,6 +16,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class SecurityConfig {
|
public class SecurityConfig {
|
||||||
|
|
||||||
private static final String LOGIN_PATH = "/login";
|
private static final String LOGIN_PATH = "/login";
|
||||||
|
|
@ -27,19 +29,20 @@ public class SecurityConfig {
|
||||||
CsrfTokenRequestAttributeHandler csrfTokenRequestAttributeHandler = new CsrfTokenRequestAttributeHandler();
|
CsrfTokenRequestAttributeHandler csrfTokenRequestAttributeHandler = new CsrfTokenRequestAttributeHandler();
|
||||||
csrfTokenRequestAttributeHandler.setCsrfRequestAttributeName("_csrf");
|
csrfTokenRequestAttributeHandler.setCsrfRequestAttributeName("_csrf");
|
||||||
|
|
||||||
http.csrf(t -> {
|
http.csrf(c -> {
|
||||||
t.csrfTokenRequestHandler(csrfTokenRequestAttributeHandler)
|
c.csrfTokenRequestHandler(csrfTokenRequestAttributeHandler)
|
||||||
.ignoringRequestMatchers("/common/modal/**")
|
.ignoringRequestMatchers("/common/modal/**")
|
||||||
.ignoringRequestMatchers(LOGIN_PATH, LOGOUT_PATH, ERROR_PATH) // CSRF 무시 URL 설정
|
.ignoringRequestMatchers(LOGIN_PATH, LOGOUT_PATH, ERROR_PATH) // CSRF 무시 URL 설정
|
||||||
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); // CSRF 토큰을 쿠키에 저장 및 사용 가능
|
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); // CSRF 토큰을 쿠키에 저장 및 사용 가능
|
||||||
}).addFilterAfter(new CsrfCookieFilter(), BasicAuthenticationFilter.class); // 로그인이 완료된 후 CSRF Filter 를 실행
|
}).addFilterAfter(new CsrfCookieFilter(), BasicAuthenticationFilter.class); // 로그인이 완료된 후 CSRF Filter 를 실행
|
||||||
|
|
||||||
// 인증 설정
|
// 인증 설정
|
||||||
http.authorizeHttpRequests(c -> c
|
http.authorizeHttpRequests(c -> {
|
||||||
.requestMatchers("/css/**", "/images/**", "/js/**").permitAll()
|
c.requestMatchers("/css/**", "/images/**", "/js/**").permitAll()
|
||||||
.requestMatchers("/common/modal/**").permitAll()
|
.requestMatchers("/common/modal/**").permitAll()
|
||||||
.requestMatchers(LOGIN_PATH, LOGOUT_PATH, ERROR_PATH).permitAll()
|
.requestMatchers(LOGIN_PATH, LOGOUT_PATH, ERROR_PATH).permitAll()
|
||||||
.anyRequest().authenticated());
|
.anyRequest().authenticated();
|
||||||
|
});
|
||||||
|
|
||||||
http.formLogin(c -> c
|
http.formLogin(c -> c
|
||||||
.loginPage(LOGIN_PATH)
|
.loginPage(LOGIN_PATH)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.bpgroup.poc.admin.web.advice;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
|
||||||
|
@ControllerAdvice
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PathInfoControllerAdvice {
|
||||||
|
|
||||||
|
@ModelAttribute("pathInfo")
|
||||||
|
public PathInfo pathInfo(HttpServletRequest request) {
|
||||||
|
return new PathInfo(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public static class PathInfo {
|
||||||
|
|
||||||
|
private final String currentPath;
|
||||||
|
|
||||||
|
public PathInfo(HttpServletRequest request) {
|
||||||
|
this.currentPath = request.getServletPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActive(String path) {
|
||||||
|
return currentPath.startsWith(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String activeClass(String path) {
|
||||||
|
return isActive(path) ? "active" : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.bpgroup.poc.admin.web.main.admin.management;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/admin/management")
|
||||||
|
public class AdministratorManagementController {
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public String administratorManagementPage() {
|
||||||
|
return "main/admin/management/list";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.bpgroup.poc.admin.web.main.admin.role;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/admin/role")
|
||||||
|
public class RoleController {
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public String rolePage() {
|
||||||
|
return "main/admin/role/list";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,2 +1,17 @@
|
||||||
INSERT INTO `administrator` (`login_id`, `password`, `email`, `name`, `create_date`, `update_date`)
|
INSERT INTO `administrator` (`login_id`, `password`, `email`, `name`, `create_date`, `update_date`)
|
||||||
VALUES ('admin', '$2a$10$g6UOrQ/OS8o5r5CJk7C5juVFaItQ62U3EIn8zLPzkFplM3wVLvKZ2', 'admin@admin.com', '홍길동', CURDATE(), CURDATE());
|
VALUES ('admin', '$2a$10$g6UOrQ/OS8o5r5CJk7C5juVFaItQ62U3EIn8zLPzkFplM3wVLvKZ2', 'admin@admin.com', '홍길동', CURDATE(), CURDATE());
|
||||||
|
|
||||||
|
INSERT INTO `role` (`name`, `description`, `create_date`, `update_date`)
|
||||||
|
VALUES ('SUPER_ADMIN', '최고 관리자', CURDATE(), CURDATE()),
|
||||||
|
('ADMIN', '관리자', CURDATE(), CURDATE()),
|
||||||
|
('CLIENT', '고객', CURDATE(), CURDATE());
|
||||||
|
|
||||||
|
INSERT INTO `administrator_role` (`administrator_id`, `role_id`, `create_date`, `update_date`)
|
||||||
|
VALUES ('1', '1', CURDATE(), CURDATE());
|
||||||
|
|
||||||
|
INSERT INTO `role_menu` (`role_id`, `menu`, `create_date`, `update_date`)
|
||||||
|
VALUES ('1', 'ADMINISTRATOR_MANAGEMENT', CURDATE(), CURDATE()),
|
||||||
|
('1', 'ROLE_MANAGEMENT', CURDATE(), CURDATE()),
|
||||||
|
('1', 'MENU_MANAGEMENT', CURDATE(), CURDATE());
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ko" xmlns:th="http://www.thymeleaf.org"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
||||||
|
<title>관리자 시스템</title>
|
||||||
|
<script type="text/javascript" th:src="@{/js/jquery/jquery-3.7.1.min.js}"></script>
|
||||||
|
<link rel="shortcut icon" th:href="@{/images/favicon.ico}">
|
||||||
|
<link rel="stylesheet" th:href="@{/css/style.css}"/>
|
||||||
|
<link rel="stylesheet" th:href="@{/css/sub.css}"/>
|
||||||
|
|
||||||
|
<script type="text/javascript" th:src="@{/js/motion.js}"></script>
|
||||||
|
<script type="text/javascript" th:src="@{/js/pagehelper.js}"></script>
|
||||||
|
<script type="text/javascript" th:src="@{/js/reqhelper.js}"></script>
|
||||||
|
<script type="text/javascript" th:src="@{/js/eventrouter.js}"></script>
|
||||||
|
|
||||||
|
<th:block th:replace="~{fragment/csrf/csrf :: applyCsrf}"></th:block>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<th:block th:replace="~{layout/gnb :: gnb}"></th:block>
|
||||||
|
</header>
|
||||||
|
<div class="wrapper flexbox">
|
||||||
|
<th:block th:replace="~{layout/lnb :: lnb}"></th:block>
|
||||||
|
<div class="container flexitem">
|
||||||
|
<th:block layout:fragment="contents"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<th:block layout:fragment="script">
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ko"
|
||||||
|
xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<body>
|
||||||
|
<th:block th:fragment="lnb">
|
||||||
|
<nav class="menu_wrap flexitem">
|
||||||
|
<h2>메뉴</h2>
|
||||||
|
<button class="closeButton"><img th:src="@{/images/ico_close.svg}"></button>
|
||||||
|
<a class="nav_tit"
|
||||||
|
th:classappend="${pathInfo.activeClass('/admin')}">
|
||||||
|
관리자
|
||||||
|
</a>
|
||||||
|
<ul class="nav_section">
|
||||||
|
<li>
|
||||||
|
<a th:with="path='/admin/management'" th:href="${path}"
|
||||||
|
th:classappend="${pathInfo.activeClass(path)}">관리자 관리</a>
|
||||||
|
<a th:with="path='/admin/role'" th:href="${path}"
|
||||||
|
th:classappend="${pathInfo.activeClass(path)}">권한 관리</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ko" xmlns:th="http://www.thymeleaf.org"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{main/admin/management/root.html}">
|
||||||
|
<body>
|
||||||
|
<th:block layout:fragment="innerContents">
|
||||||
|
</th:block>
|
||||||
|
|
||||||
|
<th:block layout:fragment="innerScript">
|
||||||
|
<script th:inline="javascript">
|
||||||
|
</script>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<!-- 메뉴 공통 영역-->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ko" xmlns:th="http://www.thymeleaf.org"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{layout/common.html}">
|
||||||
|
<body>
|
||||||
|
<th:block layout:fragment="contents">
|
||||||
|
<th:block layout:fragment="innerContents"></th:block>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<th:block layout:fragment="script">
|
||||||
|
<th:block layout:fragment="innerScript"></th:block>
|
||||||
|
</th:block>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ko" xmlns:th="http://www.thymeleaf.org"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{main/admin/role/root.html}">
|
||||||
|
<body>
|
||||||
|
<th:block layout:fragment="innerContents">
|
||||||
|
</th:block>
|
||||||
|
|
||||||
|
<th:block layout:fragment="innerScript">
|
||||||
|
<script th:inline="javascript">
|
||||||
|
</script>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<!-- 메뉴 공통 영역-->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ko" xmlns:th="http://www.thymeleaf.org"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{layout/common.html}">
|
||||||
|
<body>
|
||||||
|
<th:block layout:fragment="contents">
|
||||||
|
<th:block layout:fragment="innerContents"></th:block>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<th:block layout:fragment="script">
|
||||||
|
<th:block layout:fragment="innerScript"></th:block>
|
||||||
|
</th:block>
|
||||||
|
</html>
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="ko"
|
|
||||||
xmlns:th="http://www.thymeleaf.org"
|
|
||||||
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity6">
|
|
||||||
<body>
|
|
||||||
<th:block th:fragment="lnb">
|
|
||||||
<nav class="menu_wrap flexitem">
|
|
||||||
<!--/*@thymesVar id="pathInfo" type="kr.co.bpsoft.settlement_system.backend.admin.web.advice.PathInfoControllerAdvice$PathInfo"*/-->
|
|
||||||
<h2>메뉴</h2>
|
|
||||||
<button class="closeButton"><img th:src="@{/images/ico_close.svg}"></button>
|
|
||||||
<th>
|
|
||||||
<a href="#"
|
|
||||||
class="nav_tit">
|
|
||||||
1 Depth
|
|
||||||
</a>
|
|
||||||
<ul class="nav_section">
|
|
||||||
<li>
|
|
||||||
<a>2 Depth</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</th>
|
|
||||||
</nav>
|
|
||||||
</th:block>
|
|
||||||
</body>
|
|
||||||
|
|
@ -1,37 +1,17 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="ko" xmlns:th="http://www.thymeleaf.org"
|
<html lang="ko" xmlns:th="http://www.thymeleaf.org"
|
||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
<head>
|
layout:decorate="~{layout/common.html}">
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
|
||||||
<title>관리자 시스템</title>
|
|
||||||
<script type="text/javascript" th:src="@{/js/jquery/jquery-3.7.1.min.js}"></script>
|
|
||||||
<link rel="shortcut icon" th:href="@{/images/favicon.ico}">
|
|
||||||
<link rel="stylesheet" th:href="@{/css/style.css}"/>
|
|
||||||
<link rel="stylesheet" th:href="@{/css/sub.css}"/>
|
|
||||||
|
|
||||||
<script type="text/javascript" th:src="@{/js/motion.js}"></script>
|
|
||||||
<script type="text/javascript" th:src="@{/js/pagehelper.js}"></script>
|
|
||||||
<script type="text/javascript" th:src="@{/js/reqhelper.js}"></script>
|
|
||||||
<script type="text/javascript" th:src="@{/js/eventrouter.js}"></script>
|
|
||||||
|
|
||||||
<th:block th:replace="~{fragment/csrf/csrf :: applyCsrf}"></th:block>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<th:block layout:fragment="contents">
|
||||||
<th:block th:replace="~{main/gnb :: gnb}"></th:block>
|
<th:block layout:fragment="innerContents">
|
||||||
</header>
|
|
||||||
<div class="wrapper flexbox">
|
|
||||||
<th:block th:replace="~{main/lnb :: lnb}"></th:block>
|
|
||||||
<div class="container flexitem">
|
|
||||||
<th:block layout:fragment="contents"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<th:block layout:fragment="script">
|
|
||||||
|
|
||||||
</th:block>
|
</th:block>
|
||||||
|
</th:block>
|
||||||
</body>
|
</body>
|
||||||
|
<th:block layout:fragment="script">
|
||||||
|
<script th:inline="javascript">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</th:block>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue