yjryu / UI_Layout star
류윤주 류윤주 01-11
240111류윤주 템플릿 추가 및 수정
@204100959eed3b5d53a1aec070517b09c6869dc5
client/resources/css/common.css
--- client/resources/css/common.css
+++ client/resources/css/common.css
@@ -28,24 +28,96 @@
     display: flex;
     justify-content: flex-end;
     align-items: center;
+
 }
+
+.flex-contentBox {
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-start;
+}
+
+.flex-column {
+    display: flex;
+    flex-direction: column;
+    gap: 30px;
+}
+
+
+
+/* 정렬 배율 */
+
+.flex10 {
+    flex: 0 0 9.2%
+}
+
+
+.flex20 {
+    flex: 0 0 19.2%
+}
+
+
+.flex30 {
+    flex: 0 0 29.2%
+}
+
+
+.flex40 {
+    flex: 0 0 39.2%
+}
+
+.flex50 {
+    flex: 0 0 39.2%
+}
+
+
+.flex60 {
+    flex: 0 0 59.2%
+}
+
+
+.flex70 {
+    flex: 0 0 69.2%
+}
+
+.flex80 {
+    flex: 0 0 79.2%
+}
+
+
+.flex90 {
+    flex: 0 0 89.2%
+}
+
 
 
 /* btn */
 .small-btn {
-    padding: 3px 6px;
+    padding: 5px 10px;
     border-radius: 5px;
 }
 
 .large-btn {
     height: 100%;
-    padding: 5px 10px;
+    padding: 5px 15px;
     border-radius: 5px;
 }
 
 .logout-btn {
     padding: 5px 10px;
     color: #aaa;
+    position: relative;
+}
+
+.logout-btn::before{
+    content: "";
+    width: 1px;
+    height: 10px;
+    position: absolute;
+    top: 50%;
+    left: 0;
+    transform: translateY(-50%);
+    background-color: #aaa;
 }
 
 .blue-btn,
@@ -133,7 +205,11 @@
 .container {
     width: 100%;
     height: 100%;
-    padding: 50px;
+}
+
+.content-box {
+    width: 100%;
+    height: calc(100% - 66px);
 }
 
 .left-content,
@@ -141,42 +217,39 @@
     height: 100%;
 }
 
-.vertical {
-    display: flex;
-    width: 100%;
-}
 
 .top-content,
 .bottom-content,
 .left-content,
 .right-content,
 .content {
-    padding: 30px;
-    background-color: #f8f8f8;
+    padding: 15px;
     border-radius: 10px;
-}
-
-.right-content {
-    margin-left: 30px;
-}
-
-.horizontal .top-content {
-    margin-bottom: 30px;
+    background-color: #fff;
+    position: relative;
 }
 
 /* title 공통 */
+.page-titleZone {
+    margin-bottom: 20px;
+}
+
 .main-title {
+    font-family: 'GmarketSansB';
     font-size: 2rem;
-    font-weight: bold;
+    color: #213f99;
+}
+
+.content-titleZone {
+    margin-bottom: 15px;
 }
 
 .box-title {
     font-size: 1.6rem;
     font-weight: bold;
-    margin-bottom: 30px;
 }
 
-/* 테이블 기본 css로 테이블 템블릿에서 html만 복사해서 넣으면 자동으로 css 적용됨 */
+/* 테이블 공통 */
 .list-table {
     border-bottom: 1px solid #aaa;
 }
@@ -211,6 +284,79 @@
     border-top: 1px solid #aaa;
 }
 
+.option-table th{
+    text-align: left;
+}
+
+
+/* 서치바 공통 */
+/* .table-zone */
+.searchbar-zone{
+    margin-bottom: 10px;
+}
+/* 기본 서치바 */
+.search-square {
+    position: relative;
+    margin-left: 5px;
+}
+
+.square-date,
+.square-select {
+    width: 150px;
+}
+
+.square-input {
+    color: #646464;
+    padding: 6px 10px;
+    border-radius: 5px;
+    width: 300px;
+    transition: all ease-in-out .5s;
+}
+
+.square-input:hover,
+.square-input:focus {
+    box-shadow: 0 0 1em #00000013;
+}
+
+.square-input:focus {
+    outline: none;
+    background-color: #f0eeee;
+}
+
+.square-input::-webkit-input-placeholder {
+    font-weight: 100;
+    color: #ccc;
+}
+
+.square-input:focus {
+    background-color: #f0eeee;
+}
+
+.square-button {
+    border: none;
+    margin-left: 0;
+    position: absolute;
+    right: 5px;
+    top: 50%;
+    transform: translateY(-50%);
+}
+
+.square-button:hover {
+    cursor: pointer;
+}
+
+.square-icon {
+    color: #b4b4b4;
+}
+
+/* 상세 서치바 */
+.option-searchbar{
+    width: 50%;
+    margin: 0 auto;
+    padding: 15px;
+    background-color: #f8f9fe;
+    border-radius: 10px;
+}
 
 
 /* 기타 공통 */
client/resources/css/font.css
--- client/resources/css/font.css
+++ client/resources/css/font.css
@@ -3,4 +3,25 @@
     src: url('../font/PretendardVariable.woff2') format('woff');
     font-weight: 400;
     font-style: normal;
+}
+
+@font-face {
+    font-family: "GmarketSansM";
+    src: url("/client/resources/font/GmarketSansMedium.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: "GmarketSansL";
+    src: url("/client/resources/font/GmarketSansLight.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: "GmarketSansB";
+    src: url("/client/resources/font/GmarketSansBold.woff") format("woff");
+    font-weight: bold;
+    font-style: normal;
 }
(파일 끝에 줄바꿈 문자 없음)
client/resources/css/layout.css
--- client/resources/css/layout.css
+++ client/resources/css/layout.css
@@ -2,7 +2,7 @@
 
 .dashboard-wrap {
     width: 100%;
-    height: 100vh;
+    height: 100%;
     display: grid;
     grid-template-columns: 270px minmax(auto, 1fr);
     grid-template-rows: auto 1fr;
@@ -12,7 +12,13 @@
         "nav  main  "
 }
 
+.layout-wrap{
+    width: 100%;
+    height: 100%;
+}
+
 header {
+    background-color: #fff;
     padding: 15px 30px;
     grid-area: header;
     position: relative;
@@ -99,7 +105,7 @@
 
 nav.side-menu>ul.main-menu>li>div>a,
 nav>ul>li {
-    padding: 10px;
+    padding: 10px 0;
     font-size: 1.4rem;
     font-weight: bold;
 }
@@ -112,8 +118,12 @@
     justify-content: center;
 }
 
+.depth1{
+    cursor: default;
+}
+
 .top-menu>ul>li {
-    min-width: 165px;
+    min-width: 161px;
     text-align: center;
     position: relative;
 }
@@ -122,7 +132,7 @@
     position: absolute;
     width: 100%;
     background-color: #fff;
-    z-index: 1000;
+    z-index: 10000;
     bottom: 0;
     left: 0;
     transform: translateY(100%);
@@ -142,6 +152,7 @@
     left: 0;
     transform: translateY(100%);
     width: 100%;
+    z-index: 9999;
 }
 
 .top-menu ul.sub-menu.hide,
@@ -159,7 +170,8 @@
 
 /* 메인 */
 .main {
-    padding: 30px;
+    padding: 20px;
+    height: calc(100% - 105px);
     grid-area: main;
 }
 
client/resources/css/reset.css
--- client/resources/css/reset.css
+++ client/resources/css/reset.css
@@ -18,6 +18,7 @@
 
 body {
     min-width: 1356px;
+    background-color: #f7f6fb;
 }
 
 a {
@@ -45,7 +46,7 @@
 
 table th,
 table td {
-    padding: 5px;
+    padding: 8px;
     font-size: 1.3rem;
 }
 
@@ -65,14 +66,14 @@
 input {
     min-width: 100px;
     width: 100%;
-    padding: px 10px;
+    padding: 5px 10px;
     border: 1px solid #eee;
     border-radius: 5px;
     margin-left: 5px;
 }
 
-input{
-    min-width: 300px; 
+input[type="text"] {
+    min-width: 300px;
 }
 
 input:focus {
@@ -107,10 +108,12 @@
     width: 8px;
     height: 8px;
 }
+
 ::-webkit-scrollbar-thumb {
     background-color: #ededed;
     border-radius: 10px;
 }
+
 ::-webkit-scrollbar-track {
     background-color: #fff;
     border-radius: 10px;
client/resources/css/style.css
--- client/resources/css/style.css
+++ client/resources/css/style.css
@@ -1,1 +1,3 @@
-@charset "utf-8";
(파일 끝에 줄바꿈 문자 없음)
+@charset "utf-8";
+
+/*  */
(파일 끝에 줄바꿈 문자 없음)
 
client/resources/font/GmarketSansBold.woff (Binary) (added)
+++ client/resources/font/GmarketSansBold.woff
Binary file is not shown
 
client/resources/font/GmarketSansLight.woff (Binary) (added)
+++ client/resources/font/GmarketSansLight.woff
Binary file is not shown
 
client/resources/font/GmarketSansMedium.woff (Binary) (added)
+++ client/resources/font/GmarketSansMedium.woff
Binary file is not shown
 
client/views/component/FileTree.vue (added)
+++ client/views/component/FileTree.vue
@@ -0,0 +1,100 @@
+<template>
+    <v-jstree :data="fileTree" show-checkbox multiple allow-batch whole-row @item-click="itemClick"></v-jstree>
+</template>
+
+<script>
+import VJstree from 'vue-jstree'
+export default {
+    data() {
+        return {
+            fileTree: [
+                {
+                    "text": "Same but with checkboxes",
+                    "children": [
+                        {
+                            "text": "initially selected",
+                            "selected": true
+                        },
+                        {
+                            "text": "custom icon",
+                            "icon": "fa fa-warning icon-state-danger"
+                        },
+                        {
+                            "text": "initially open",
+                            "icon": "fa fa-folder icon-state-default",
+                            "opened": true,
+                            "children": [
+                                {
+                                    "text": "Another node"
+                                }
+                            ]
+                        },
+                        {
+                            "text": "custom icon",
+                            "icon": "fa fa-warning icon-state-warning"
+                        },
+                        {
+                            "text": "disabled node",
+                            "icon": "fa fa-check icon-state-success",
+                            "disabled": true
+                        }
+                    ]
+                },
+                {
+                    "text": "Same but with checkboxes",
+                    "opened": true,
+                    "children": [
+                        {
+                            "text": "initially selected",
+                            "selected": true
+                        },
+                        {
+                            "text": "custom icon",
+                            "icon": "fa fa-warning icon-state-danger"
+                        },
+                        {
+                            "text": "initially open",
+                            "icon": "fa fa-folder icon-state-default",
+                            "opened": true,
+                            "children": [
+                                {
+                                    "text": "Another node"
+                                }
+                            ]
+                        },
+                        {
+                            "text": "custom icon",
+                            "icon": "fa fa-warning icon-state-warning"
+                        },
+                        {
+                            "text": "disabled node",
+                            "icon": "fa fa-check icon-state-success",
+                            "disabled": true
+                        }
+                    ]
+                },
+                {
+                    "text": "And wholerow selection"
+                }
+            ]
+        }
+    },
+    methods: {
+        itemClick: function (node) {
+            console.log(node.model.text + ' clicked !')
+        }
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+        'VJstree': VJstree
+    },
+    mounted() {
+
+    }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
client/views/component/PageNavigation.vue
--- client/views/component/PageNavigation.vue
+++ client/views/component/PageNavigation.vue
@@ -47,9 +47,7 @@
 
 <style scoped>
 .navigate_bar {
-    width: 100%;
-    padding: 10px 30px;
+    padding: 10px 0px;
     font-size: 1.3rem;
-    text-align: right;
 }
 </style>
 
client/views/component/PaginationButton.vue (added)
+++ client/views/component/PaginationButton.vue
@@ -0,0 +1,174 @@
+<template lang="html">
+	<div class="component-pagination" id="pagination">
+		<div class="pagination-button-type">
+			<a class="first-page" @click="excute(1)" title="첫 번 째 페이지로 이동"></a>
+			<a class="prev" @click="excute(currentPage - 1)" title="이전 페이지로 이동"></a>
+			<a @click="excute(i)" v-for="i in createRange" :class="{ 'active': currentPage == i }">{{ i }}</a>
+			<a class="next" @click="excute(currentPage + 1)" title="다음 페이지로 이동"></a>
+			<a class="end-page" @click="excute(maxEndPage)" title="마지막 페이지로 이동"></a>
+		</div>
+	</div>
+</template>
+
+<script>
+export default {
+	props: {
+		currentPage: {
+			type: Number,
+			default: 0
+		},
+		perPage: {
+			type: Number,
+			default: 10
+		},
+		totalCount: {
+			type: Number,
+			default: 0
+		},
+		maxRange: {
+			type: Number,
+			default: 5
+		},
+		click: Function
+	},
+	emits: ['update:currentPage'],
+	data: function () {
+		return {
+			//data
+		}
+	},
+	methods: {
+		excute: function (i) {
+			if (i >= 1 && i <= this.maxEndPage) {
+				if (i != this.currentPage) {
+					this.$emit('update:currentPage', i);//부모 currentPage에 선택한 page번호 할당
+					this.click(i);//부모 function 실행
+				} else {
+					return;
+				}
+			} else {
+				alert('이동할 페이지가 없습니다.');
+			}
+		}
+	},
+	computed: {
+		startPage: function () {
+			return Math.floor((this.currentPage - 1) / this.maxRange) * this.maxRange + 1;
+		},
+		endPage: function () {
+			if (this.maxEndPage < this.currentEndPage) {
+				return this.maxEndPage;
+			} else {
+				return this.currentEndPage;
+			}
+		},
+		currentEndPage: function () {
+			return this.maxRange * Math.ceil((this.currentPage / this.maxRange));
+		},
+		maxEndPage: function () {
+			return Math.ceil(this.totalCount / this.perPage);
+		},
+		createRange: function () {
+			var range = [];
+			for (var i = this.startPage; i <= this.endPage; i++) {
+				range.push(i);
+			}
+			if (range.length == 0) {
+					range.push(1);
+			}
+			return range;
+		}
+	},
+	watch: {
+
+	},
+	//beforeCreate: function () {},
+	//created: function () {},
+	//beforeUpdate: function () {},
+	//updated: function () {},
+	mounted: function () {
+	}
+}
+</script>
+
+<style scoped>
+/*PAGINATION NEW START*/
+.component-pagination {
+	padding: 15px 0;
+	position: absolute;
+	bottom: 0;
+	left: 50%;
+	transform: translateX(-50%);
+}
+
+.pagination-button-type {
+	display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.pagination-button-type a {
+	display: inline-block;
+	width: 30px;
+	height: 30px;
+	padding: 5px;
+	text-align: center;
+	line-height: 20px;
+	cursor: pointer;
+}
+
+/* 정우추가 */
+.pagination-button-type a.prev:after {
+	content: "\003C";
+	font-family: 'KoPub_Dotum';
+	font-weight: 900;
+}
+
+.pagination-button-type a.next:after {
+	content: "\003E";
+	font-family: 'KoPub_Dotum';
+	font-weight: 900;
+}
+
+.pagination-button-type a.first-page:after {
+	content: "\003C\003C";
+	font-family: 'KoPub_Dotum';
+	font-weight: 900;
+}
+
+.pagination-button-type a.end-page:after {
+	content: "\003E\003E";
+	font-family: 'KoPub_Dotum';
+	font-weight: 900;
+}
+
+.pagination-button-type a.active {
+	background-color: #213f99;
+	color: #fff;
+	cursor: default !important;
+	border-radius: 50px;
+}
+
+.pagination-button-type a:hover:not(.active) {
+	background-color: #213f99;
+	color: #fff;
+	border-radius: 50px;
+}
+
+.pagination-button-type a:first-child {
+	border-top-left-radius: 0px;
+	border-bottom-left-radius: 0px;
+}
+
+.pagination-button-type a:last-child {
+	border-top-right-radius: 0px;
+	border-bottom-right-radius: 0px;
+}
+
+/*PAGINATION NEW END*/
+
+@media screen and (max-width:479px) {
+	.pagination-button-type a {
+		margin: 3px;
+	}
+}</style>(파일 끝에 줄바꿈 문자 없음)
client/views/layout/Header.vue
--- client/views/layout/Header.vue
+++ client/views/layout/Header.vue
@@ -16,14 +16,13 @@
                     </div>
                     <span class="user-name">000님</span>
                 </div>
-                <Button :className="'logout-btn'" :btnName="'로그아웃'" />
+                <button class="logout-btn">로그아웃</button>
             </div>
         </div>
     </header>
 </template>
 
 <script>
-import Button from '../component/Button.vue';
 import SvgIcon from '@jamescoyle/vue-icon'
 import { mdiEmail, mdiAccountCircle } from '@mdi/js'
 export default {
@@ -57,7 +56,6 @@
         }
     },
     components: {
-        'Button': Button,
         'SvgIcon': SvgIcon
     },
     mounted() {
client/views/layout/TopMenu.vue
--- client/views/layout/TopMenu.vue
+++ client/views/layout/TopMenu.vue
@@ -2,7 +2,7 @@
     <nav class="top-menu">
         <ul class="main-menu">
             <li v-for="(mainMenu, idx) in menuList" :key="idx" @mouseover="showAllSubMenus" @mouseout="hideAllSubMenus">
-                <p :class="{ active: isMainMenuActive(mainMenu) }">{{ mainMenu.pathName }}</p>
+                <p class="depth1" :class="{ active: isMainMenuActive(mainMenu) }">{{ mainMenu.pathName }}</p>
                 <ul v-if="mainMenu.subMenu" class="sub-menu" v-show="showSubmenu"
                     :class="{ show: showSubmenu, hide: !showSubmenu }">
                     <li v-for="(subMenu, idx) in mainMenu.subMenu" :key="idx" :class="{ active: isSubMenuActive(subMenu) }">
@@ -79,13 +79,20 @@
                     ],
                 },
                 {
-                    path: "/searchbar.page", pathName: "템플릿",
+                    pathName: "템플릿",
                     subMenu: [
                         { path: "/searchbar.page", pathName: "서치바" },
                         { path: "/table.page", pathName: "테이블" },
                         { path: "/btnPosition.page", pathName: "버튼별 위치" },
                     ],
                 },
+                {
+                    pathName: "레이아웃 템플릿",
+                    subMenu: [
+                        { path: "/vertical.page", pathName: "수직 레이아웃" },
+                        { path: "/horizontal.page", pathName: "수평 레이아웃" },
+                    ],
+                },
             ],
             currentRoute: null,
             showSubmenu: false
client/views/pages/App.vue
--- client/views/pages/App.vue
+++ client/views/pages/App.vue
@@ -15,12 +15,11 @@
 import SideMenu from '../layout/SideMenu.vue';
 import TopMenu from '../layout/TopMenu.vue';
 import PageNavigation from '../component/PageNavigation.vue';
-
 const App = {
    data: () => {
       return {
          // side혹은 top 둘중 한개 타입
-         layoutType: "top"
+         layoutType: "top",
       }
    },
    methods: {
client/views/pages/AppRouter.js
--- client/views/pages/AppRouter.js
+++ client/views/pages/AppRouter.js
@@ -10,6 +10,8 @@
 import Searchbar from "../pages/template/Searchbar.vue";
 import Table from "../pages/template/Table.vue";
 import BtnPosition from "../pages/template/BtnPosition.vue";
+import Horizontal from "../pages/layoutTemplate/Horizontal.vue";
+import Vertical from "../pages/layoutTemplate/Vertical.vue";
 
 const routes = [
   /* 메인화면 */
@@ -24,6 +26,8 @@
   {path: "/searchbar.page",name: "Searchbar",component: Searchbar,},
   {path: "/table.page",name: "Table",component: Table,},
   {path: "/btnPosition.page",name: "BtnPosition",component: BtnPosition,},
+  {path: "/horizontal.page",name: "Horizontal",component: Horizontal,},
+  {path: "/vertical.page",name: "Vertical",component: Vertical,},
 ];
 
 const AppRouter = createRouter({
 
client/views/pages/layoutTemplate/Horizontal.vue (added)
+++ client/views/pages/layoutTemplate/Horizontal.vue
@@ -0,0 +1,40 @@
+<template>
+    <div class="container">
+        <div class="page-titleZone flex-between">
+            <p class="main-title">페이지 제목을 적어주세요</p>
+            <PageNavigation />
+        </div>
+        <div class="content-box flex-column">
+            <div class="top-content"></div>
+        <div class="bottom-content"></div>
+        </div>
+    </div>
+</template>
+
+<script>
+import PageNavigation from '../../component/PageNavigation.vue';
+import PaginationButton from '../../component/PaginationButton.vue';
+
+export default {
+    data () {
+        return {
+        }
+    },
+    methods: {
+
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+        'PageNavigation': PageNavigation,
+        'PaginationButton': PaginationButton
+    },
+    mounted() {
+        console.log('main mounted');
+    }
+}
+</script>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/layoutTemplate/Vertical.vue (added)
+++ client/views/pages/layoutTemplate/Vertical.vue
@@ -0,0 +1,109 @@
+<template>
+    <div class="container">
+        <div class="page-titleZone flex-between">
+            <p class="main-title">페이지 제목을 적어주세요</p>
+            <PageNavigation />
+        </div>
+        <div class="content-box flex-contentBox">
+            <div class="left-content flex20">
+                <div class="content-titleZone flex-between">
+                    <p class="box-title">폴더 리스트</p>
+                    <button class="darkg-border-btn small-btn">폴더추가</button>
+                </div>
+                <div class="content-zone">
+
+                </div>
+            </div>
+            <div class="right-content flex80">
+                <div class="searchbar-zone">
+                    <div class="flex-end">
+                        <input type="date" name="" id="" class="square-date">
+                        <span class="coupler">~</span>
+                        <input type="date" name="" id="" class="square-date">
+                        <select name="" id="" class="square-select">
+                            <option value="all">전체</option>
+                        </select>
+                        <div class="search-square">
+                            <input type="text" class="square-input" placeholder="Search">
+                            <button class="square-button">
+                                <svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon>
+                            </button>
+                        </div>
+                    </div>
+                </div>
+                <div class="table-zone">
+                    <table class="list-table">
+                        <colgroup>
+                            <col style="width: ;">
+                            <col style="width: ;">
+                            <col style="width: ;">
+                            <col style="width: ;">
+                        </colgroup>
+                        <thead>
+                            <tr>
+                                <th>No</th>
+                                <th>user ID</th>
+                                <th>이름</th>
+                                <th>생년월일</th>
+                                <th>성별</th>
+                            </tr>
+                        </thead>
+                        <tbody>
+                            <tr>
+                                <td>1</td>
+                                <td>test123</td>
+                                <td>홍길동</td>
+                                <td>1999.01.01</td>
+                                <td>여</td>
+                            </tr>
+
+                        </tbody>
+                    </table>
+                </div>
+                <PaginationButton />
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import PageNavigation from '../../component/PageNavigation.vue';
+import PaginationButton from '../../component/PaginationButton.vue';
+import FileTree from '../../component/FileTree.vue';
+import SvgIcon from '@jamescoyle/vue-icon';
+import { mdiMagnify } from '@mdi/js';
+export default {
+    data() {
+        return {
+            searchPath: mdiMagnify
+        }
+    },
+    methods: {
+
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+        'PageNavigation': PageNavigation,
+        'FileTree': FileTree,
+        'SvgIcon': SvgIcon,
+        'PaginationButton': PaginationButton
+    },
+    mounted() {
+        console.log('main mounted');
+    }
+}
+</script>
+
+<style lang="css" scoped>
+.content-zone {
+    border: 1px solid #eee;
+    padding: 10px;
+    height: calc(100% - 44px);
+    overflow: auto;
+}
+</style>(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/template/DefaultSearchBar.vue (added)
+++ client/views/pages/template/DefaultSearchBar.vue
@@ -0,0 +1,45 @@
+<template>
+    <div class="search-bar">
+        <div class="flex-end">
+            <input type="date" name="" id="" class="square-date">
+            <span class="coupler">~</span>
+            <input type="date" name="" id="" class="square-date">
+            <select name="" id="" class="square-select">
+                <option value="all">전체</option>
+            </select>
+            <div class="search-square">
+                <input type="text" class="square-input" placeholder="Search">
+                <button class="square-button">
+                    <svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon>
+                </button>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import SvgIcon from '@jamescoyle/vue-icon';
+import { mdiMagnify } from '@mdi/js';
+export default {
+    data() {
+        return {
+            searchPath: mdiMagnify
+        }
+    },
+    methods: {
+
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+        'SvgIcon': SvgIcon
+    },
+    mounted() {
+        console.log('main mounted');
+    }
+}
+</script>
 
client/views/pages/template/DetailSearchBar.vue (added)
+++ client/views/pages/template/DetailSearchBar.vue
@@ -0,0 +1,173 @@
+<template>
+    <div class="search-bar">
+        <div class="option-searchbar">
+            <div class="search-top">
+                <div class="flex">
+                    <input type="date" name="" id="" class="square-date">
+                    <span class="coupler">~</span>
+                    <input type="date" name="" id="" class="square-date">
+                    <select name="" id="" class="square-select">
+                        <option value="all">전체</option>
+                    </select>
+                    <div class="search-square">
+                        <input type="text" class="square-input" placeholder="Search">
+                        <button class="square-button">
+                            <svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon>
+                        </button>
+                    </div>
+                </div>
+            </div>
+            <div class="search-bottom">
+                <table class="option-table">
+                    <colgroup>
+                        <col style="width: 10%;" />
+                    </colgroup>
+                    <tbody>
+                        <tr>
+                            <th>단일조건</th>
+                            <td>
+                                <div class="input-container flex">
+                                    <label class="radio-label">
+                                        <input type="radio" name="radio" checked="" class="custom-radiobox ">
+                                        <span>HTML</span>
+                                    </label>
+                                    <label class="radio-label">
+                                        <input type="radio" name="radio" class="custom-radiobox ">
+                                        <span>CSS</span>
+                                    </label>
+                                    <label class="radio-label">
+                                        <input type="radio" name="radio" class="custom-radiobox ">
+                                        <span>Javascript</span>
+                                    </label>
+                                </div>
+                            </td>
+                        </tr>
+                        <tr>
+                            <th>다중조건</th>
+                            <td>
+                                <div class="input-container flex">
+                                    <label class="check-label">
+                                        <input type="checkbox" name="check" checked="" class="custom-checkbox ">
+                                        <span>HTML</span>
+                                    </label>
+                                    <label class="check-label">
+                                        <input type="checkbox" name="check" class="custom-checkbox ">
+                                        <span>CSS</span>
+                                    </label>
+                                    <label class="check-label">
+                                        <input type="checkbox" name="check" class="custom-checkbox ">
+                                        <span>Javascript</span>
+                                    </label>
+                                </div>
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import SvgIcon from '@jamescoyle/vue-icon';
+import { mdiMagnify } from '@mdi/js';
+export default {
+    data() {
+        return {
+            searchPath: mdiMagnify
+        }
+    },
+    methods: {
+
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+        'SvgIcon': SvgIcon
+    },
+    mounted() {
+        console.log('main mounted');
+    }
+}
+</script>
+
+<style>
+.search-top {
+    padding: 15px 0;
+    border-bottom: 1px solid #aaa;
+}
+
+/* radio css */
+.input-container label {
+    display: flex;
+    cursor: pointer;
+    font-weight: 500;
+    position: relative;
+    overflow: hidden;
+    margin-bottom: 3px;
+}
+
+.input-container label input.custom-radiobox,
+.input-container label input.custom-checkbox {
+    position: absolute;
+    left: -9999px;
+}
+
+.input-container label input.custom-radiobox:checked+span {
+    background-color: #5b72b8;
+    color: #fff;
+}
+
+.input-container label input.custom-checkbox:checked+span {
+    background-color: #f8bb59;
+    color: #fff;
+}
+
+.input-container label input.custom-radiobox:checked+span:before {
+    box-shadow: inset 0 0 0 4px #213f99;
+}
+
+.input-container label input.custom-checkbox:checked+span:before {
+    box-shadow: inset 0 0 0 4px #ff9d00;
+}
+
+.input-container label span {
+    display: flex;
+    align-items: center;
+    padding: 3px 7px;
+    border-radius: 10px;
+    transition: 0.25s ease;
+    color: #333;
+}
+
+
+.input-container label.radio-label span:hover {
+    background-color: #d6d6e5;
+}
+
+.input-container label.check-label span:hover {
+    background-color: #f4e3c2;
+}
+
+.input-container label.radio-label span:before,
+.input-container label.check-label span:before {
+    display: flex;
+    flex-shrink: 0;
+    content: "";
+    background-color: #fff;
+    width: 15px;
+    height: 15px;
+    border-radius: 50%;
+    margin-right: 3px;
+    transition: 0.25s ease;
+    box-shadow: inset 0 0 0 1px #333;
+}
+
+.input-container label.check-label span:before {
+    border-radius: 0%;
+}
+</style>(파일 끝에 줄바꿈 문자 없음)
client/views/pages/template/FormModal.vue (Renamed from client/views/component/Button.vue)
--- client/views/component/Button.vue
+++ client/views/pages/template/FormModal.vue
@@ -1,15 +1,11 @@
 <template>
-    <button :class="className">{{ btnName }}</button>
+    <div>Main.vue</div>
 </template>
 
 <script>
 
 export default {
-    props: {
-        className: String,
-        btnName: String
-    },
-    data() {
+    data () {
         return {
         }
     },
@@ -28,4 +24,4 @@
         console.log('main mounted');
     }
 }
-</script>
+</script>
(파일 끝에 줄바꿈 문자 없음)
 
client/views/pages/template/FormTable.vue (added)
+++ client/views/pages/template/FormTable.vue
@@ -0,0 +1,57 @@
+<template>
+    <table class="form-table">
+        <colgroup>
+            <col style="width: ;">
+            <col style="width: ;">
+            <col style="width: ;">
+            <col style="width: ;">
+        </colgroup>
+        <tbody>
+            <tr>
+                <th>user ID</th>
+                <td><input type="text" name="" id=""></td>
+                <th>이름</th>
+                <td><input type="text" name="" id=""></td>
+            </tr>
+            <tr>
+                <th>생년월일</th>
+                <td>
+                    <div class="flex">
+                        <select name="" id=""></select>
+                        <select name="" id=""></select>
+                        <select name="" id=""></select>
+                    </div>
+                </td>
+                <th>성별</th>
+                <td>
+                    <select name="" id=""></select>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</template>
+
+<script>
+
+export default {
+    data() {
+        return {
+        }
+    },
+    methods: {
+
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+    },
+    mounted() {
+        console.log('main mounted');
+    }
+}
+</script>
+
 
client/views/pages/template/ListTable.vue (added)
+++ client/views/pages/template/ListTable.vue
@@ -0,0 +1,61 @@
+<template>
+    <div class="table-zone">
+        <table class="list-table">
+            <colgroup>
+                <col style="width: ;">
+                <col style="width: ;">
+                <col style="width: ;">
+                <col style="width: ;">
+            </colgroup>
+            <thead>
+                <tr>
+                    <th>No</th>
+                    <th>user ID</th>
+                    <th>이름</th>
+                    <th>생년월일</th>
+                    <th>성별</th>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td>1</td>
+                    <td>test123</td>
+                    <td>홍길동</td>
+                    <td>1999.01.01</td>
+                    <td>여</td>
+                </tr>
+                <tr>
+                    <td>1</td>
+                    <td>test123</td>
+                    <td>홍길동</td>
+                    <td>1999.01.01</td>
+                    <td>여</td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+</template>
+
+<script>
+
+export default {
+    data() {
+        return {
+        }
+    },
+    methods: {
+
+    },
+    watch: {
+
+    },
+    computed: {
+
+    },
+    components: {
+    },
+    mounted() {
+        console.log('main mounted');
+    }
+}
+</script>
client/views/pages/template/Searchbar.vue
--- client/views/pages/template/Searchbar.vue
+++ client/views/pages/template/Searchbar.vue
@@ -2,71 +2,24 @@
     <div class="box">
         <p style="font-size:2rem; font-weight:800; margin-bottom:10px">기본 Search Bar</p>
         <div style="padding:30px 0">
-            <div class="flex-between">
-                <!-- 여기서부터 -->
-                <div class="flex">
-                    <select name="" id="" class="circle-select">
-                        <option value="all">전체</option>
-                    </select>
-                    <div class="search">
-                        <input type="text" class="search-input" placeholder="Search">
-                        <button class="search-button">
-                            <svg-icon type="mdi" :path="searchPath" class="search-icon"></svg-icon>
-                        </button>
-                    </div>
-                </div>
-                <!-- 여기서까지 복사 -->
-                <!-- 여기서부터 -->
-                <div class="flex">
-                    <select name="" id="" class="square-select">
-                        <option value="all">전체</option>
-                    </select>
-                    <div class="search-square">
-                        <input type="text" class="square-input" placeholder="Search">
-                        <button class="square-button">
-                            <svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon>
-                        </button>
-                    </div>
-                </div>
-                <!-- 여기서까지 복사 -->
-            </div>
+            <DefaultSearchBar />
         </div>
-        <div style="padding:30px 0">
-            <div class="flex-between">
-                <!-- 여기서부터 -->
-                <div class="flex">
-                    <select name="" id="" class="circle-select2">
-                        <option value="all">전체</option>
-                    </select>
-                    <div class="search2">
-                        <input placeholder="Search" type="text" class="search-zone">
-                        <button type="submit" class="search-btn">검색</button>
-                    </div>
-                </div>
-                <!-- 여기서까지 복사 -->
-                <!-- 여기서부터 -->
-                <div class="flex">
-                    <select name="" id="" class="square-select2">
-                        <option value="all">전체</option>
-                    </select>
-                    <div class="search2-square">
-                        <input placeholder="Search" type="text" class="square-zone">
-                        <button type="submit" class="square-btn">검색</button>
-                    </div>
-                </div>
-                <!-- 여기서까지 복사 -->
-            </div>
+    </div>
+    <div class="box">
+        <p style="font-size:2rem; font-weight:800; margin-bottom:10px">상세 Search Bar</p>
+        <div>
+            <DetailSearchBar />
         </div>
     </div>
 </template>
 
 <script>
-import SvgIcon from '@jamescoyle/vue-icon';
-import { mdiMagnify } from '@mdi/js';
+import DefaultSearchBar from './DefaultSearchBar.vue';
+import DetailSearchBar from './DetailSearchBar.vue';
 export default {
     data() {
         return {
-            searchPath: mdiMagnify
+
         }
     },
     methods: {
@@ -79,11 +32,11 @@
 
     },
     components: {
-        'SvgIcon': SvgIcon
+        'DefaultSearchBar':DefaultSearchBar,
+        'DetailSearchBar':DetailSearchBar
     },
     mounted() {
-        console.log('main mounted');
-    }
+ }
 }
 </script>
 
@@ -93,193 +46,7 @@
     padding: 50px;
     border: 1px solid #eee;
     margin-bottom: 30px;
+    background-color: #fff;
 }
 
-/* 1번 디자인 */
-.search {
-    position: relative;
-    margin-left: 5px;
-}
-
-.circle-select {
-    border-radius: 30px;
-}
-
-.search-input {
-    color: #646464;
-    padding: 5px 10px;
-    border-radius: 30px;
-    width: 300px;
-    transition: all ease-in-out .5s;
-}
-
-.search-input:hover,
-.search-input:focus {
-    box-shadow: 0 0 1em #00000013;
-}
-
-.search-input:focus {
-    outline: none;
-    background-color: #f0eeee;
-}
-
-.search-input::-webkit-input-placeholder {
-    font-weight: 100;
-    color: #ccc;
-}
-
-.search-input:focus {
-    background-color: #f0eeee;
-}
-
-.search-button {
-    border: none;
-    margin-left: 0;
-    position: absolute;
-    right: 5px;
-    top: 50%;
-    transform: translateY(-50%);
-}
-
-.search-button:hover {
-    cursor: pointer;
-}
-
-.search-icon {
-    color: #b4b4b4;
-}
-
-/* 1-2 */
-.search-square {
-    position: relative;
-}
-
-.square-input {
-    color: #646464;
-    padding: 5px 10px;
-    border-radius: 5px;
-    width: 300px;
-    transition: all ease-in-out .5s;
-    margin-left: 5px;
-}
-
-.square-input:hover,
-.square-input:focus {
-    box-shadow: 0 0 1em #00000013;
-}
-
-.square-input:focus {
-    outline: none;
-    background-color: #f0eeee;
-}
-
-.square-input::-webkit-input-placeholder {
-    font-weight: 100;
-    color: #ccc;
-}
-
-.square-input:focus {
-    background-color: #f0eeee;
-}
-
-.square-button {
-    border: none;
-    margin-left: 0;
-    position: absolute;
-    right: 5px;
-    top: 50%;
-    transform: translateY(-50%);
-}
-
-.square-button:hover {
-    cursor: pointer;
-}
-
-.square-icon {
-    color: #b4b4b4;
-}
-
-
-/* 2번 디자인 */
-.search2 {
-    display: inline-block;
-    position: relative;
-}
-
-.circle-select2 {
-    border: none;
-    border-radius: 30px;
-    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
-}
-
-.search2 .search-zone {
-    width: 200px;
-    padding: 5px 10px;
-    border: none;
-    border-radius: 20px;
-    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
-    margin-left: 5px;
-}
-
-.search2 .search-btn {
-    background-color: #4e99e9;
-    border: none;
-    color: #fff;
-    cursor: pointer;
-    padding: 5px 10px;
-    border-radius: 20px;
-    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
-    position: absolute;
-    top: 0;
-    right: 0;
-    transition: .9s ease;
-}
-
-.search2 .search-btn:hover {
-    transform: scale(1.05);
-    color: rgb(255, 255, 255);
-    background-color: #213f99;
-}
-
-/* 2-1 */
-.search2-square {
-    display: inline-block;
-    position: relative;
-}
-
-.square-select2{
-    border: none;
-    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
-}
-
-.search2-square .square-zone {
-    width: 200px;
-    padding: 5px 10px;
-    border: none;
-    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
-    margin-left: 5px;
-}
-
-.search2-square .square-btn {
-    background-color: #4e99e9;
-    border: none;
-    color: #fff;
-    cursor: pointer;
-    padding: 5px 10px;
-    border-radius: 3px;
-    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
-    position: absolute;
-    top: 0;
-    right: 0;
-    transition: .9s ease;
-}
-
-.search2-square .square-btn:hover {
-    transform: scale(1.05);
-    color: rgb(255, 255, 255);
-    background-color: #213f99;
-}
-
-
-/* select + search */
 </style>
(파일 끝에 줄바꿈 문자 없음)
client/views/pages/template/Table.vue
--- client/views/pages/template/Table.vue
+++ client/views/pages/template/Table.vue
@@ -1,79 +1,17 @@
 <template>
     <div class="box">
         <p style="font-size:2rem; font-weight:800; margin-bottom:10px">기본 List Table</p>
-        <!-- 여기서부터 복사 -->
-        <table class="list-table">
-            <colgroup>
-                <col style="width: ;">
-                <col style="width: ;">
-                <col style="width: ;">
-                <col style="width: ;">
-            </colgroup>
-            <thead>
-                <tr>
-                    <th>No</th>
-                    <th>user ID</th>
-                    <th>이름</th>
-                    <th>생년월일</th>
-                    <th>성별</th>
-                </tr>
-            </thead>
-            <tbody>
-                <tr>
-                    <td>1</td>
-                    <td>test123</td>
-                    <td>홍길동</td>
-                    <td>1999.01.01</td>
-                    <td>여</td>
-                </tr>
-                <tr>
-                    <td>1</td>
-                    <td>test123</td>
-                    <td>홍길동</td>
-                    <td>1999.01.01</td>
-                    <td>여</td>
-                </tr>
-            </tbody>
-        </table>
+        <ListTable />
     </div>
     <div class="box">
         <p style="font-size:2rem; font-weight:800; margin-bottom:10px">기본 form Table</p>
-        <!-- 여기서부터 복사 -->
-        <table class="form-table">
-            <colgroup>
-                <col style="width: ;">
-                <col style="width: ;">
-                <col style="width: ;">
-                <col style="width: ;">
-            </colgroup>
-            <tbody>
-                <tr>
-                    <th>user ID</th>
-                    <td><input type="text" name="" id=""></td>
-                    <th>이름</th>
-                    <td><input type="text" name="" id=""></td>
-                </tr>
-                <tr>
-                    <th>생년월일</th>
-                    <td>
-                        <div class="flex">
-                            <select name="" id=""></select>
-                            <select name="" id=""></select>
-                            <select name="" id=""></select>
-                        </div>
-                    </td>
-                    <th>성별</th>
-                    <td>
-                        <select name="" id=""></select>
-                    </td>
-                </tr>
-            </tbody>
-        </table>
+        <FormTable />
     </div>
 </template>
 
 <script>
-
+import ListTable from './ListTable.vue';
+import FormTable from './FormTable.vue';
 export default {
     data() {
         return {
@@ -89,9 +27,11 @@
 
     },
     components: {
+        'ListTable': ListTable,
+        'FormTable': FormTable
     },
     mounted() {
-        console.log('main mounted');
+
     }
 }
 </script>
@@ -102,5 +42,4 @@
     border: 1px solid #eee;
     margin-bottom: 30px;
 }
-
 </style>
(파일 끝에 줄바꿈 문자 없음)
node_modules/.package-lock.json
--- node_modules/.package-lock.json
+++ node_modules/.package-lock.json
@@ -1,5 +1,5 @@
 {
-  "name": "Taken_BI_Manager",
+  "name": "UI_Layout",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
@@ -4930,6 +4930,11 @@
         "@vue/shared": "3.2.40"
       }
     },
+    "node_modules/vue-jstree": {
+      "version": "2.1.6",
+      "resolved": "https://registry.npmjs.org/vue-jstree/-/vue-jstree-2.1.6.tgz",
+      "integrity": "sha512-vtUmhLbfE2JvcnYNRXauJPkNJSRO/f9BTsbxV+ESXP/mMQPVUIYI4EkSHKSEOxVDHTU7SfLp/AxplmaAl6ctcg=="
+    },
     "node_modules/vue-loader": {
       "version": "17.0.0",
       "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.0.tgz",
package-lock.json
--- package-lock.json
+++ package-lock.json
@@ -1,5 +1,5 @@
 {
-  "name": "Taken_BI_Manager",
+  "name": "UI_Layout",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
@@ -23,6 +23,7 @@
         "pg": "8.8.0",
         "url-loader": "4.1.1",
         "vue": "3.2.40",
+        "vue-jstree": "^2.1.6",
         "vue-loader": "^17.0.0",
         "vue-router": "4.1.5",
         "vue-style-loader": "4.1.3",
@@ -4972,6 +4973,11 @@
         "@vue/shared": "3.2.40"
       }
     },
+    "node_modules/vue-jstree": {
+      "version": "2.1.6",
+      "resolved": "https://registry.npmjs.org/vue-jstree/-/vue-jstree-2.1.6.tgz",
+      "integrity": "sha512-vtUmhLbfE2JvcnYNRXauJPkNJSRO/f9BTsbxV+ESXP/mMQPVUIYI4EkSHKSEOxVDHTU7SfLp/AxplmaAl6ctcg=="
+    },
     "node_modules/vue-loader": {
       "version": "17.0.0",
       "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.0.tgz",
@@ -9126,6 +9132,11 @@
         "@vue/shared": "3.2.40"
       }
     },
+    "vue-jstree": {
+      "version": "2.1.6",
+      "resolved": "https://registry.npmjs.org/vue-jstree/-/vue-jstree-2.1.6.tgz",
+      "integrity": "sha512-vtUmhLbfE2JvcnYNRXauJPkNJSRO/f9BTsbxV+ESXP/mMQPVUIYI4EkSHKSEOxVDHTU7SfLp/AxplmaAl6ctcg=="
+    },
     "vue-loader": {
       "version": "17.0.0",
       "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.0.tgz",
package.json
--- package.json
+++ package.json
@@ -1,5 +1,6 @@
 {
   "dependencies": {
+    "@amcharts/amcharts5": "^5.5.7",
     "@babel/cli": "7.19.3",
     "@babel/core": "7.19.3",
     "@jamescoyle/vue-icon": "^0.1.2",
@@ -10,21 +11,21 @@
     "express": "4.18.1",
     "express-http-proxy": "^2.0.0",
     "file-loader": "6.2.0",
+    "file-saver": "^2.0.5",
     "fs": "0.0.1-security",
+    "lodash": "^4.17.21",
     "new-line": "^1.1.1",
     "pg": "8.8.0",
     "url-loader": "4.1.1",
     "vue": "3.2.40",
+    "vue-jstree": "^2.1.6",
     "vue-loader": "^17.0.0",
     "vue-router": "4.1.5",
     "vue-style-loader": "4.1.3",
     "vue3-sfc-loader": "^0.8.4",
+    "vuex": "^4.1.0",
     "webpack": "5.74.0",
-    "webpack-cli": "4.10.0",
-    "@amcharts/amcharts5": "^5.5.7",
-    "file-saver": "^2.0.5",
-    "lodash": "^4.17.21",
-    "vuex": "^4.1.0"
+    "webpack-cli": "4.10.0"
   },
   "scripts": {
     "prod": "set NODE_ENV=production&&node ./server/modules/web/server.js",
Add a comment
List