
--- client/resources/scss/admin/content.scss
+++ client/resources/scss/admin/content.scss
... | ... | @@ -15,12 +15,9 @@ |
15 | 15 |
.scroll { |
16 | 16 |
height: 100%; |
17 | 17 |
overflow-y: auto; |
18 |
- |
|
19 |
- |
|
20 | 18 |
} |
21 | 19 |
|
22 | 20 |
} |
23 |
- |
|
24 | 21 |
&.full-page { |
25 | 22 |
height: 100%; |
26 | 23 |
} |
... | ... | @@ -39,7 +36,6 @@ |
39 | 36 |
.page-title { |
40 | 37 |
font-size: var(--tk-fz-title-xlg); |
41 | 38 |
font-weight: 700; |
42 |
- margin-bottom: 1rem; |
|
43 | 39 |
} |
44 | 40 |
|
45 | 41 |
.box-title, |
... | ... | @@ -48,8 +44,6 @@ |
48 | 44 |
font-weight: 700; |
49 | 45 |
margin-bottom: 1rem; |
50 | 46 |
} |
51 |
- |
|
52 |
- |
|
53 | 47 |
|
54 | 48 |
.search-bar { |
55 | 49 |
@include flex-layout(flex, center, end); |
... | ... | @@ -96,9 +90,9 @@ |
96 | 90 |
padding: 1rem; |
97 | 91 |
border-bottom: 1px solid var(--tk-gray-10); |
98 | 92 |
|
99 |
- &:last-child { |
|
100 |
- align-items: flex-start; |
|
101 |
- } |
|
93 |
+ // &:last-child { |
|
94 |
+ // align-items: flex-start; |
|
95 |
+ // } |
|
102 | 96 |
|
103 | 97 |
.form-title { |
104 | 98 |
width: 180px; |
... | ... | @@ -180,12 +174,6 @@ |
180 | 174 |
} |
181 | 175 |
|
182 | 176 |
} |
183 |
- |
|
184 |
- .check-area { |
|
185 |
- @include flex-layout(flex, center); |
|
186 |
- gap: 3rem; |
|
187 |
- } |
|
188 |
- |
|
189 | 177 |
|
190 | 178 |
} |
191 | 179 |
|
... | ... | @@ -399,4 +387,9 @@ |
399 | 387 |
.dp__action_button{ |
400 | 388 |
font-size: 1.5rem; |
401 | 389 |
} |
390 |
+} |
|
391 |
+ |
|
392 |
+.check-area { |
|
393 |
+ @include flex-layout(flex, center); |
|
394 |
+ gap: 3rem; |
|
402 | 395 |
}(파일 끝에 줄바꿈 문자 없음) |
--- client/resources/scss/admin/layout.scss
+++ client/resources/scss/admin/layout.scss
... | ... | @@ -2,7 +2,7 @@ |
2 | 2 |
background-color: #eaeff4; |
3 | 3 |
display: grid; |
4 | 4 |
grid-template-columns: clamp(240px, 10vw, 450px) minmax(1020px, 1fr); |
5 |
- grid-template-rows: auto minmax(864px, auto); |
|
5 |
+ grid-template-rows: auto minmax(864px, 1226px); |
|
6 | 6 |
grid-template-areas: |
7 | 7 |
"sidebar header " |
8 | 8 |
"sidebar main "; |
... | ... | @@ -12,26 +12,30 @@ |
12 | 12 |
|
13 | 13 |
.admin-header { |
14 | 14 |
grid-area: header; |
15 |
+ @include flex-layout(flex, center, space-between); |
|
16 |
+ padding: 1rem 3rem; |
|
15 | 17 |
border-bottom: 1px solid var(--tk-gray-30); |
16 | 18 |
|
17 |
- .top-menu ul { |
|
18 |
- @include flex-layout(flex, center, space-between); |
|
19 |
- |
|
20 |
- li { |
|
21 |
- cursor: pointer; |
|
22 |
- padding: 1rem 2rem; |
|
23 |
- } |
|
24 |
- |
|
25 |
- li.main-active { |
|
26 |
- border-bottom: 3px solid var(--tk-gray-70);; |
|
27 |
- // @include radius(25); |
|
28 |
- font-weight: 700; |
|
19 |
+ .info-wrap { |
|
20 |
+ .info { |
|
21 |
+ @include flex-layout(flex, center, flex-end); |
|
22 |
+ .info-name{ |
|
23 |
+ padding: .8rem |
|
24 |
+ } |
|
25 |
+ ul.info-btn{ |
|
26 |
+ @include flex-layout(flex, center); |
|
27 |
+ li{ |
|
28 |
+ @include flex-layout(flex, center, center); |
|
29 |
+ padding: 1rem; |
|
30 |
+ } |
|
31 |
+ } |
|
29 | 32 |
} |
30 | 33 |
} |
31 | 34 |
|
32 | 35 |
} |
33 | 36 |
|
34 |
- .sub-menu { |
|
37 |
+ .side-bar{ |
|
38 |
+ // .sub-menu { |
|
35 | 39 |
grid-area: sidebar; |
36 | 40 |
height: 100%; |
37 | 41 |
background-color: #f7f9fb; |
... | ... | @@ -45,25 +49,7 @@ |
45 | 49 |
text-align: center; |
46 | 50 |
} |
47 | 51 |
|
48 |
- .info-wrap { |
|
49 |
- background-color: var(--tk-gray-10); |
|
50 |
- |
|
51 |
- .info { |
|
52 |
- @include flex-layout(flex, center, space-between); |
|
53 |
- .info-name{ |
|
54 |
- padding: .8rem |
|
55 |
- } |
|
56 |
- ul.info-btn{ |
|
57 |
- @include flex-layout(flex, center); |
|
58 |
- li{ |
|
59 |
- @include flex-layout(flex, center, center); |
|
60 |
- background-color: var(--tk-gray-20); |
|
61 |
- padding: 1rem; |
|
62 |
- border-left: 1px solid var(--tk-gray-30); |
|
63 |
- } |
|
64 |
- } |
|
65 |
- } |
|
66 |
- } |
|
52 |
+ |
|
67 | 53 |
.menu-zone{ |
68 | 54 |
p{ |
69 | 55 |
font-size: var(--tk-fz-title-sm); |
--- client/views/component/userInfo/UserAuthorList.vue
+++ client/views/component/userInfo/UserAuthorList.vue
... | ... | @@ -1,43 +1,29 @@ |
1 | 1 |
<template> |
2 |
- <div class="gd-12 pl0 pr0"> |
|
3 |
- <div class="flex justify-between align-center mb10"> |
|
4 |
- <label for="" class="point-font2 mb10">사용자 권한</label> |
|
5 |
- <div v-show="editMode != 'view'" class="gd-1 pr0"> |
|
6 |
- <button |
|
2 |
+ |
|
3 |
+ <label class="form-title">사용자 권한</label> |
|
4 |
+ <div class="form-group"> |
|
5 |
+ <button v-show="editMode != 'view'" class="btn sm ico-plus" @click="fnAuthAddModalOpen">권한 추가</button> |
|
6 |
+ <template v-if="mbrVO.authorList != null && mbrVO.authorList != []"> |
|
7 |
+ <div v-for="(auth, index) of mbrVO.authorList" :key="index" |
|
7 | 8 |
:class="{ |
8 |
- 'large-btn': true, |
|
9 |
- 'blue-border-btn': pageRole == 'adm', |
|
10 |
- 'green-border-btn': pageRole == 'portal', |
|
9 |
+ 'flex align-center border radius pd10 inline-block': true, |
|
10 |
+ ml10: index != 0, |
|
11 | 11 |
}" |
12 |
- @click="fnAuthAddModalOpen" |
|
13 | 12 |
> |
14 |
- 권한 추가 |
|
15 |
- </button> |
|
16 |
- </div> |
|
17 |
- </div> |
|
18 |
- </div> |
|
19 |
- <template v-if="mbrVO.authorList != null && mbrVO.authorList != []"> |
|
20 |
- <template v-for="(auth, index) of mbrVO.authorList" :key="index"> |
|
21 |
- <div |
|
22 |
- :class="{ |
|
23 |
- 'flex align-center border radius pd10 inline-block': true, |
|
24 |
- ml10: index != 0, |
|
25 |
- }" |
|
26 |
- > |
|
27 |
- <span>{{ auth.authrtNm }}</span> |
|
28 |
- <button |
|
29 |
- v-show="editMode != 'view'" |
|
30 |
- class="icon-btn" |
|
31 |
- @click="fnAuthDelete(index)" |
|
32 |
- > |
|
33 |
- <svg-icon type="mdi" :width="15" :height="15" :path="path"></svg-icon> |
|
34 |
- </button> |
|
35 |
- </div> |
|
13 |
+ <span>{{ auth.authrtNm }}</span> |
|
14 |
+ <button |
|
15 |
+ v-show="editMode != 'view'" |
|
16 |
+ class="icon-btn" |
|
17 |
+ @click="fnAuthDelete(index)" |
|
18 |
+ > |
|
19 |
+ <svg-icon type="mdi" :width="15" :height="15" :path="path"></svg-icon> |
|
20 |
+ </button> |
|
21 |
+ </div> |
|
36 | 22 |
</template> |
37 |
- </template> |
|
38 |
- <template> |
|
39 |
- <p class="data-none">등록된 정보가 존재하지 않습니다.</p> |
|
40 |
- </template> |
|
23 |
+ <template v-else> |
|
24 |
+ <p class="data-none">등록된 정보가 존재하지 않습니다.</p> |
|
25 |
+ </template> |
|
26 |
+ </div> |
|
41 | 27 |
|
42 | 28 |
<Modal :showModal="editMode != 'view' && isOpen"> |
43 | 29 |
<template v-slot:header> |
--- client/views/component/userInfo/UserInfoView.vue
+++ client/views/component/userInfo/UserInfoView.vue
... | ... | @@ -46,7 +46,7 @@ |
46 | 46 |
disabled |
47 | 47 |
/> --> |
48 | 48 |
</div> |
49 |
- <div v-if="showOpt.isTelNo"> |
|
49 |
+ <div v-if="showOpt.isTelNo" class="border-bottom"> |
|
50 | 50 |
<p class="form-title">전화번호</p> |
51 | 51 |
<p>{{ mbrVO.telno }}</p> |
52 | 52 |
<!-- <input |
--- client/views/index.html
+++ client/views/index.html
... | ... | @@ -11,13 +11,8 @@ |
11 | 11 |
<!-- 공통css --> |
12 | 12 |
<link rel="stylesheet" href="/client/resources/lib/swiper/swiper-bundle.min.css"> |
13 | 13 |
<link rel="stylesheet" href="/client/build/assets/css/app.css"> |
14 |
- |
|
15 |
- |
|
16 |
- |
|
17 |
- <!-- 테마 v2 css --> |
|
18 |
- <!-- <link rel="stylesheet" href="/client/theme/tema_v2/css/component.css"> |
|
19 |
- <link rel="stylesheet" href="/client/theme/tema_v2/css/style.css"> --> |
|
20 | 14 |
|
15 |
+ <!-- 스크립트 --> |
|
21 | 16 |
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script> |
22 | 17 |
<script src="/client/resources/lib/swiper/swiper-element-bundle.min.js"></script> |
23 | 18 |
<script type="text/javascript" charset="utf-8" src="../client/ckeditor/build/ckeditor.js"></script> |
+++ client/views/layout/AdminHeader copy.vue
... | ... | @@ -0,0 +1,85 @@ |
1 | +<template> | |
2 | + <header class="admin-header"> | |
3 | + <div class="header-wrap"> | |
4 | + <nav class="top-menu"> | |
5 | + <ul class="main-menu"> | |
6 | + <li v-for="(menu, idx) in menuList" :key="idx" @click="subMenuShow(menu)" | |
7 | + :class="{ 'main-active': checkMenu == menu.menuId }"> | |
8 | + {{ menu.menuNm }} | |
9 | + </li> | |
10 | + </ul> | |
11 | + </nav> | |
12 | + </div> | |
13 | + </header> | |
14 | +</template> | |
15 | + | |
16 | +<script> | |
17 | +import store from "../../views/pages/AppStore"; | |
18 | +import queryParams from '../../resources/js/queryParams'; | |
19 | +import { defaultSearchParams } from '../../resources/js/defaultSearchParams'; | |
20 | +import { findBySysMenu } from '../../resources/api/menu'; | |
21 | + | |
22 | +export default { | |
23 | + mixins: [queryParams], | |
24 | + components: { | |
25 | + | |
26 | + }, | |
27 | + data() { | |
28 | + return { | |
29 | + checkMenu: null, | |
30 | + resetSearch: { ...defaultSearchParams }, | |
31 | + menuList: [], | |
32 | + } | |
33 | + }, | |
34 | + created() { | |
35 | + this.findAll(); | |
36 | + this.menuCheck(); | |
37 | + }, | |
38 | + methods: { | |
39 | + menuCheck() { | |
40 | + const menu = store.state.menu; | |
41 | + if(menu != null && menu != '' && menu != undefined) { | |
42 | + this.checkMenu = menu.menuId; | |
43 | + } | |
44 | + }, | |
45 | + // 목록 조회 | |
46 | + async findAll() { | |
47 | + try { | |
48 | + const params = { | |
49 | + roles : store.state.roles.map(auth => auth.authority), | |
50 | + menuType : store.state.userType | |
51 | + }; | |
52 | + const res = await findBySysMenu(params); | |
53 | + if(res.status == 200) { | |
54 | + this.menuList = res.data.data.menuList; | |
55 | + // 전체 메뉴 트리 store에 저장 | |
56 | + this.$store.commit('setMenuList', this.menuList); | |
57 | + } | |
58 | + } catch(error) { | |
59 | + alert('에러가 발생했습니다.\n관리자에게 문의하세요.'); | |
60 | + } | |
61 | + }, | |
62 | + async subMenuShow(menu) { | |
63 | + this.saveQueryParams('queryParams', this.resetSearch); // 검색조건 초기화 | |
64 | + this.$store.commit('setMenu', menu); | |
65 | + }, | |
66 | + | |
67 | + }, | |
68 | + watch: { | |
69 | + '$store.state.menu': function (newValue, oldValue) { | |
70 | + if(newValue == null || newValue == '' || newValue == undefined) { | |
71 | + this.checkMenu = null; | |
72 | + } else { | |
73 | + this.checkMenu = newValue.menuId; | |
74 | + } | |
75 | + }, | |
76 | + | |
77 | + }, | |
78 | + computed: { | |
79 | + | |
80 | + }, | |
81 | + mounted() { | |
82 | + | |
83 | + } | |
84 | +} | |
85 | +</script>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/layout/AdminHeader.vue
+++ client/views/layout/AdminHeader.vue
... | ... | @@ -1,14 +1,17 @@ |
1 | 1 |
<template> |
2 | 2 |
<header class="admin-header"> |
3 |
- <div class="header-wrap"> |
|
4 |
- <nav class="top-menu"> |
|
5 |
- <ul class="main-menu"> |
|
6 |
- <li v-for="(menu, idx) in menuList" :key="idx" @click="subMenuShow(menu)" |
|
7 |
- :class="{ 'main-active': checkMenu == menu.menuId }"> |
|
8 |
- {{ menu.menuNm }} |
|
9 |
- </li> |
|
3 |
+ <div class="page-title"> |
|
4 |
+ {{ pgNm }} |
|
5 |
+ </div> |
|
6 |
+ <div class="info-wrap"> |
|
7 |
+ <div class="info"> |
|
8 |
+ <p class="info-name">{{ mbrNm }} 님</p> |
|
9 |
+ <ul class="info-btn"> |
|
10 |
+ <li><button class="btn-ico xsm ico-logout" @click="fnlogOut" title="로그아웃"></button></li> |
|
11 |
+ <li><button class="btn-ico xsm ico-go" @click="fnSiteMove" title="사이트이동"></button></li> |
|
12 |
+ <li><button class="btn-ico xsm ico-reset" @click="cacheClean()" title="변경사항 적용"></button></li> |
|
10 | 13 |
</ul> |
11 |
- </nav> |
|
14 |
+ </div> |
|
12 | 15 |
</div> |
13 | 16 |
</header> |
14 | 17 |
</template> |
... | ... | @@ -16,8 +19,8 @@ |
16 | 19 |
<script> |
17 | 20 |
import store from "../../views/pages/AppStore"; |
18 | 21 |
import queryParams from '../../resources/js/queryParams'; |
19 |
-import { defaultSearchParams } from '../../resources/js/defaultSearchParams'; |
|
20 |
-import { findBySysMenu } from '../../resources/api/menu'; |
|
22 |
+import { mapActions } from "vuex"; |
|
23 |
+import { cacheReSet } from "../../resources/api/cacheReSet"; |
|
21 | 24 |
|
22 | 25 |
export default { |
23 | 26 |
mixins: [queryParams], |
... | ... | @@ -26,52 +29,38 @@ |
26 | 29 |
}, |
27 | 30 |
data() { |
28 | 31 |
return { |
29 |
- checkMenu: null, |
|
30 |
- resetSearch: { ...defaultSearchParams }, |
|
31 |
- menuList: [], |
|
32 |
+ mbrNm: store.state.mbrNm, |
|
33 |
+ pgNm: store.state.menu.menuNm, |
|
32 | 34 |
} |
33 | 35 |
}, |
34 | 36 |
created() { |
35 |
- this.findAll(); |
|
36 |
- this.menuCheck(); |
|
37 | 37 |
}, |
38 | 38 |
methods: { |
39 |
- menuCheck() { |
|
40 |
- const menu = store.state.menu; |
|
41 |
- if(menu != null && menu != '' && menu != undefined) { |
|
42 |
- this.checkMenu = menu.menuId; |
|
43 |
- } |
|
39 |
+ // 사이트 이동 |
|
40 |
+ fnSiteMove() { |
|
41 |
+ this.$router.push({ |
|
42 |
+ path: "/", |
|
43 |
+ }); |
|
44 | 44 |
}, |
45 |
- // 목록 조회 |
|
46 |
- async findAll() { |
|
47 |
- try { |
|
48 |
- const params = { |
|
49 |
- roles : store.state.roles.map(auth => auth.authority), |
|
50 |
- menuType : store.state.userType |
|
51 |
- }; |
|
52 |
- const res = await findBySysMenu(params); |
|
53 |
- if(res.status == 200) { |
|
54 |
- this.menuList = res.data.data.menuList; |
|
55 |
- // 전체 메뉴 트리 store에 저장 |
|
56 |
- this.$store.commit('setMenuList', this.menuList); |
|
57 |
- } |
|
58 |
- } catch(error) { |
|
59 |
- alert('에러가 발생했습니다.\n관리자에게 문의하세요.'); |
|
60 |
- } |
|
45 |
+ ...mapActions(["logout"]), |
|
46 |
+ // 로그 아웃 |
|
47 |
+ async fnlogOut() { |
|
48 |
+ await this.logout(); |
|
49 |
+ this.$router.push({ |
|
50 |
+ path: "/login.page", |
|
51 |
+ }); |
|
61 | 52 |
}, |
62 |
- async subMenuShow(menu) { |
|
63 |
- this.saveQueryParams('queryParams', this.resetSearch); // 검색조건 초기화 |
|
64 |
- this.$store.commit('setMenu', menu); |
|
53 |
+ // 캐시 초기화 |
|
54 |
+ async cacheClean() { |
|
55 |
+ if (!confirm("변경사항을 적용하시겠습니까?")) return; |
|
56 |
+ const res = await cacheReSet(); |
|
57 |
+ alert(res.data.message); |
|
65 | 58 |
}, |
66 | 59 |
|
67 | 60 |
}, |
68 | 61 |
watch: { |
69 |
- '$store.state.menu': function (newValue, oldValue) { |
|
70 |
- if(newValue == null || newValue == '' || newValue == undefined) { |
|
71 |
- this.checkMenu = null; |
|
72 |
- } else { |
|
73 |
- this.checkMenu = newValue.menuId; |
|
74 |
- } |
|
62 |
+ '$store.state.menu'(newValue) { |
|
63 |
+ this.pgNm = newValue.menuNm |
|
75 | 64 |
}, |
76 | 65 |
|
77 | 66 |
}, |
+++ client/views/layout/AdminMenu copy.vue
... | ... | @@ -0,0 +1,144 @@ |
1 | +<template> | |
2 | + <nav class="sub-menu"> | |
3 | + <div class="logo"> | |
4 | + <router-link :to="{path : '/adm/main.page'}">ADMINISTRATOR</router-link> | |
5 | + </div> | |
6 | + <div class="info-wrap"> | |
7 | + <div class="info"> | |
8 | + <p class="info-name">{{ mbrNm }}</p> | |
9 | + <ul class="info-btn"> | |
10 | + <li><button class="btn-ico xsm ico-logout" @click="fnlogOut" title="로그아웃"></button></li> | |
11 | + <li><button class="btn-ico xsm ico-go" @click="fnSiteMove" title="사이트이동"></button></li> | |
12 | + <li><button class="btn-ico xsm ico-reset" @click="cacheClean()" title="변경사항 적용"></button></li> | |
13 | + </ul> | |
14 | + </div> | |
15 | + </div> | |
16 | + <div class="menu-zone"> | |
17 | + <p>MENU</p> | |
18 | + <ul class="side-menu"> | |
19 | + <template v-if="menuList.length > 0"> | |
20 | + <li v-for="(sub, subidx) in menuList" :key="subidx" :class="{ 'sub-active': isActive(sub.routerUrl) }"> | |
21 | + <div @click=" | |
22 | + menuClick( | |
23 | + sub.routerUrl != '' && sub.routerUrl != null | |
24 | + ? sub | |
25 | + : sub.childList[0] | |
26 | + ) | |
27 | + "> | |
28 | + <span>{{ sub.menuNm }}</span> | |
29 | + </div> | |
30 | + <ul v-show="sub.childList.length > 0"> | |
31 | + <li v-for="(third, thirdIdx) in sub.childList" :key="thirdIdx" :class="{ | |
32 | + 'sub-active': isActive(third.routerUrl), | |
33 | + }" @click="menuClick(third)"> | |
34 | + <span>{{ third.menuNm }}</span> | |
35 | + </li> | |
36 | + </ul> | |
37 | + </li> | |
38 | + </template> | |
39 | + </ul> | |
40 | + </div> | |
41 | + </nav> | |
42 | +</template> | |
43 | +<script> | |
44 | +import store from "../pages/AppStore"; | |
45 | +import queryParams from "../../resources/js/queryParams"; | |
46 | +import { defaultSearchParams } from "../../resources/js/defaultSearchParams"; | |
47 | +import { mapActions } from "vuex"; | |
48 | +import cntnStatsSave from "../../resources/js/cntnStatsSave"; | |
49 | +import { cacheReSet } from "../../resources/api/cacheReSet"; | |
50 | + | |
51 | +export default { | |
52 | + mixins: [queryParams, cntnStatsSave], | |
53 | + components: {}, | |
54 | + props: {}, | |
55 | + data() { | |
56 | + return { | |
57 | + mbrNm: store.state.mbrNm, | |
58 | + currentPath: this.$route.path, | |
59 | + resetSearch: { ...defaultSearchParams }, | |
60 | + menuList: [], | |
61 | + }; | |
62 | + }, | |
63 | + created() { | |
64 | + this.menuCheck(); | |
65 | + }, | |
66 | + methods: { | |
67 | + menuCheck() { | |
68 | + const menu = store.state.menu; | |
69 | + if (menu != null && menu != "" && menu != undefined) { | |
70 | + this.menuList = menu.childList; | |
71 | + } | |
72 | + }, | |
73 | + async menuClick(menu) { | |
74 | + this.saveQueryParams("queryParams", this.resetSearch); // 검색조건 초기화 | |
75 | + await this.cntnStatsSave(menu.menuId); | |
76 | + if (menu.linkType === "0") { | |
77 | + // 현재창 | |
78 | + this.$router.push({ | |
79 | + path: menu.routerUrl, | |
80 | + }); | |
81 | + } else if (menu.linkType === "1") { | |
82 | + // 새창 | |
83 | + window.open(menu.routerUrl, "_blank"); | |
84 | + } | |
85 | + }, | |
86 | + isActive(subPath) { | |
87 | + const checkUrl = this.currentPath.substring( | |
88 | + 0, | |
89 | + this.currentPath.lastIndexOf("/") + 1 | |
90 | + ); | |
91 | + return subPath.startsWith(checkUrl); | |
92 | + }, | |
93 | + // 사이트 이동 | |
94 | + fnSiteMove() { | |
95 | + this.$router.push({ | |
96 | + path: "/", | |
97 | + }); | |
98 | + }, | |
99 | + ...mapActions(["logout"]), | |
100 | + // 로그 아웃 | |
101 | + async fnlogOut() { | |
102 | + await this.logout(); | |
103 | + this.$router.push({ | |
104 | + path: "/login.page", | |
105 | + }); | |
106 | + }, | |
107 | + // 캐시 초기화 | |
108 | + async cacheClean() { | |
109 | + if (!confirm("변경사항을 적용하시겠습니까?")) return; | |
110 | + const res = await cacheReSet(); | |
111 | + alert(res.data.message); | |
112 | + }, | |
113 | + }, | |
114 | + watch: { | |
115 | + // 나중에 네비게이션 가드에서 form 받을 수 있으면 form adm/main으로 갈때 sotre.state값0로 바꿔주기 | |
116 | + $route(to) { | |
117 | + this.currentPath = to.path; | |
118 | + }, | |
119 | + async "$store.state.menu"(newVal) { | |
120 | + if (newVal == null || newVal == "" || newVal == undefined) { | |
121 | + this.menuList = []; | |
122 | + } else { | |
123 | + this.menuList = newVal.childList; | |
124 | + if (newVal && this.menuList.length > 0) { | |
125 | + await this.cntnStatsSave(this.menuList[0].menuId); | |
126 | + if ( | |
127 | + newVal.menuId == "MENU_000000000000010" && | |
128 | + this.$store.state.path.includes("BBS_MNG_") | |
129 | + ) { | |
130 | + return; | |
131 | + } else { | |
132 | + this.$router.push(this.menuList[0].routerUrl); | |
133 | + } | |
134 | + } | |
135 | + } | |
136 | + }, | |
137 | + "$store.state.mbrNm"(newVal) { | |
138 | + this.mbrNm = newVal; | |
139 | + }, | |
140 | + }, | |
141 | + computed: {}, | |
142 | + mounted() { }, | |
143 | +}; | |
144 | +</script> |
--- client/views/layout/AdminMenu.vue
+++ client/views/layout/AdminMenu.vue
... | ... | @@ -1,144 +1,177 @@ |
1 | 1 |
<template> |
2 |
- <nav class="sub-menu"> |
|
3 |
- <div class="logo"> |
|
4 |
- <router-link :to="{path : '/adm/main.page'}">ADMINISTRATOR</router-link> |
|
5 |
- </div> |
|
6 |
- <div class="info-wrap"> |
|
7 |
- <div class="info"> |
|
8 |
- <p class="info-name">{{ mbrNm }}</p> |
|
9 |
- <ul class="info-btn"> |
|
10 |
- <li><button class="btn-ico xsm ico-logout" @click="fnlogOut" title="로그아웃"></button></li> |
|
11 |
- <li><button class="btn-ico xsm ico-go" @click="fnSiteMove" title="사이트이동"></button></li> |
|
12 |
- <li><button class="btn-ico xsm ico-reset" @click="cacheClean()" title="변경사항 적용"></button></li> |
|
13 |
- </ul> |
|
14 |
- </div> |
|
15 |
- </div> |
|
16 |
- <div class="menu-zone"> |
|
17 |
- <p>MENU</p> |
|
18 |
- <ul class="side-menu"> |
|
19 |
- <template v-if="menuList.length > 0"> |
|
20 |
- <li v-for="(sub, subidx) in menuList" :key="subidx" :class="{ 'sub-active': isActive(sub.routerUrl) }"> |
|
21 |
- <div @click=" |
|
22 |
- menuClick( |
|
23 |
- sub.routerUrl != '' && sub.routerUrl != null |
|
24 |
- ? sub |
|
25 |
- : sub.childList[0] |
|
26 |
- ) |
|
27 |
- "> |
|
28 |
- <span>{{ sub.menuNm }}</span> |
|
29 |
- </div> |
|
30 |
- <ul v-show="sub.childList.length > 0"> |
|
31 |
- <li v-for="(third, thirdIdx) in sub.childList" :key="thirdIdx" :class="{ |
|
32 |
- 'sub-active': isActive(third.routerUrl), |
|
33 |
- }" @click="menuClick(third)"> |
|
34 |
- <span>{{ third.menuNm }}</span> |
|
35 |
- </li> |
|
2 |
+ <div class="side-bar"> |
|
3 |
+ <div class="logo"> |
|
4 |
+ <router-link :to="{path : '/adm/main.page'}">ADMINISTRATOR</router-link> |
|
5 |
+ </div> |
|
6 |
+ <nav> |
|
7 |
+ <ul class="main-menu"> |
|
8 |
+ <li v-for="(menu, idx) in menuList" :key="idx" class="menu-item" |
|
9 |
+ @click.stop="toggleSubMenu(menu)"> |
|
10 |
+ <span :class="{ 'main-active': checkMenu == menu.menuId }"> |
|
11 |
+ {{ menu.menuNm }} |
|
12 |
+ </span> |
|
13 |
+ <!-- 드롭다운 메뉴 --> |
|
14 |
+ <ul v-if="menu.isOpen" class="sub-menu"> |
|
15 |
+ <li v-for="(subMenu, subIdx) in menu.childList" :key="subIdx" :class="{ 'sub-active': isActive(subMenu.routerUrl) }" |
|
16 |
+ @click.stop="menuClick( subMenu.routerUrl != '' && subMenu.routerUrl != null ? subMenu : subMenu.childList[0])"> |
|
17 |
+ {{ subMenu.menuNm }} |
|
18 |
+ <ul v-show="subMenu.childList.length > 0"> |
|
19 |
+ <li v-for="(third, thirdIdx) in subMenu.childList" :key="thirdIdx" :class="{ |
|
20 |
+ 'ss-active': isActive(third.routerUrl), |
|
21 |
+ }" @click.stop="menuClick(third)"> |
|
22 |
+ <span>{{ third.menuNm }}</span> |
|
23 |
+ </li> |
|
24 |
+ </ul> |
|
25 |
+ </li> |
|
26 |
+ </ul> |
|
27 |
+ </li> |
|
36 | 28 |
</ul> |
37 |
- </li> |
|
38 |
- </template> |
|
39 |
- </ul> |
|
29 |
+ </nav> |
|
40 | 30 |
</div> |
41 |
- </nav> |
|
42 | 31 |
</template> |
32 |
+ |
|
43 | 33 |
<script> |
44 |
-import store from "../../views/pages/AppStore"; |
|
45 |
-import queryParams from "../../resources/js/queryParams"; |
|
46 |
-import { defaultSearchParams } from "../../resources/js/defaultSearchParams"; |
|
47 |
-import { mapActions } from "vuex"; |
|
34 |
+import store from "../pages/AppStore"; |
|
35 |
+import queryParams from '../../resources/js/queryParams'; |
|
36 |
+import { defaultSearchParams } from '../../resources/js/defaultSearchParams'; |
|
48 | 37 |
import cntnStatsSave from "../../resources/js/cntnStatsSave"; |
49 |
-import { cacheReSet } from "../../resources/api/cacheReSet"; |
|
38 |
+import { findBySysMenu } from '../../resources/api/menu'; |
|
50 | 39 |
|
51 | 40 |
export default { |
52 |
- mixins: [queryParams, cntnStatsSave], |
|
53 |
- components: {}, |
|
54 |
- props: {}, |
|
55 |
- data() { |
|
56 |
- return { |
|
57 |
- mbrNm: store.state.mbrNm, |
|
58 |
- currentPath: this.$route.path, |
|
59 |
- resetSearch: { ...defaultSearchParams }, |
|
60 |
- menuList: [], |
|
61 |
- }; |
|
62 |
- }, |
|
63 |
- created() { |
|
64 |
- this.menuCheck(); |
|
65 |
- }, |
|
66 |
- methods: { |
|
67 |
- menuCheck() { |
|
68 |
- const menu = store.state.menu; |
|
69 |
- if (menu != null && menu != "" && menu != undefined) { |
|
70 |
- this.menuList = menu.childList; |
|
71 |
- } |
|
41 |
+ mixins: [queryParams, cntnStatsSave], |
|
42 |
+ data() { |
|
43 |
+ return { |
|
44 |
+ checkMenu: null, |
|
45 |
+ currentPath: this.$route.path, |
|
46 |
+ resetSearch: { ...defaultSearchParams }, |
|
47 |
+ menuList: [], |
|
48 |
+ }; |
|
72 | 49 |
}, |
73 |
- async menuClick(menu) { |
|
74 |
- this.saveQueryParams("queryParams", this.resetSearch); // 검색조건 초기화 |
|
75 |
- await this.cntnStatsSave(menu.menuId); |
|
76 |
- if (menu.linkType === "0") { |
|
77 |
- // 현재창 |
|
78 |
- this.$router.push({ |
|
79 |
- path: menu.routerUrl, |
|
80 |
- }); |
|
81 |
- } else if (menu.linkType === "1") { |
|
82 |
- // 새창 |
|
83 |
- window.open(menu.routerUrl, "_blank"); |
|
84 |
- } |
|
50 |
+ created() { |
|
51 |
+ this.findAll(); |
|
52 |
+ this.menuCheck(); |
|
85 | 53 |
}, |
86 |
- isActive(subPath) { |
|
87 |
- const checkUrl = this.currentPath.substring( |
|
88 |
- 0, |
|
89 |
- this.currentPath.lastIndexOf("/") + 1 |
|
90 |
- ); |
|
91 |
- return subPath.startsWith(checkUrl); |
|
54 |
+ methods: { |
|
55 |
+ menuCheck() { |
|
56 |
+ const menu = store.state.menu; |
|
57 |
+ if (menu) { |
|
58 |
+ this.checkMenu = menu.menuId; |
|
59 |
+ } |
|
60 |
+ }, |
|
61 |
+ async findAll() { |
|
62 |
+ try { |
|
63 |
+ const params = { |
|
64 |
+ roles: store.state.roles.map(auth => auth.authority), |
|
65 |
+ menuType: store.state.userType |
|
66 |
+ }; |
|
67 |
+ const res = await findBySysMenu(params); |
|
68 |
+ if (res.status === 200) { |
|
69 |
+ // `isOpen` 속성을 추가하여 초기 상태 설정 |
|
70 |
+ this.menuList = res.data.data.menuList.map(menu => ({ |
|
71 |
+ ...menu, |
|
72 |
+ isOpen: false, |
|
73 |
+ })); |
|
74 |
+ // 전체 메뉴 트리 store에 저장 |
|
75 |
+ this.$store.commit('setMenuList', this.menuList); |
|
76 |
+ } |
|
77 |
+ } catch (error) { |
|
78 |
+ alert('에러가 발생했습니다.\n관리자에게 문의하세요.'); |
|
79 |
+ } |
|
80 |
+ }, |
|
81 |
+ async menuClick(menu) { |
|
82 |
+ this.saveQueryParams("queryParams", this.resetSearch); // 검색조건 초기화 |
|
83 |
+ this.$store.commit('setMenu', menu); |
|
84 |
+ await this.cntnStatsSave(menu.menuId); |
|
85 |
+ if (menu.linkType === "0") { |
|
86 |
+ // 현재창 |
|
87 |
+ this.$router.push({ |
|
88 |
+ path: menu.routerUrl, |
|
89 |
+ }); |
|
90 |
+ } else if (menu.linkType === "1") { |
|
91 |
+ // 새창 |
|
92 |
+ window.open(menu.routerUrl, "_blank"); |
|
93 |
+ } |
|
94 |
+ }, |
|
95 |
+ toggleSubMenu(menu) { |
|
96 |
+ menu.isOpen = !menu.isOpen; |
|
97 |
+ this.checkMenu = menu.menuId; |
|
98 |
+ // this.saveQueryParams('queryParams', this.resetSearch); // 검색조건 초기화 |
|
99 |
+ }, |
|
100 |
+ |
|
101 |
+ isActive(subPath) { |
|
102 |
+ const checkUrl = this.currentPath.substring( |
|
103 |
+ 0, |
|
104 |
+ this.currentPath.lastIndexOf("/") + 1 |
|
105 |
+ ); |
|
106 |
+ return subPath.startsWith(checkUrl); |
|
107 |
+ }, |
|
92 | 108 |
}, |
93 |
- // 사이트 이동 |
|
94 |
- fnSiteMove() { |
|
95 |
- this.$router.push({ |
|
96 |
- path: "/", |
|
97 |
- }); |
|
98 |
- }, |
|
99 |
- ...mapActions(["logout"]), |
|
100 |
- // 로그 아웃 |
|
101 |
- async fnlogOut() { |
|
102 |
- await this.logout(); |
|
103 |
- this.$router.push({ |
|
104 |
- path: "/login.page", |
|
105 |
- }); |
|
106 |
- }, |
|
107 |
- // 캐시 초기화 |
|
108 |
- async cacheClean() { |
|
109 |
- if (!confirm("변경사항을 적용하시겠습니까?")) return; |
|
110 |
- const res = await cacheReSet(); |
|
111 |
- alert(res.data.message); |
|
112 |
- }, |
|
113 |
- }, |
|
114 |
- watch: { |
|
115 |
- // 나중에 네비게이션 가드에서 form 받을 수 있으면 form adm/main으로 갈때 sotre.state값0로 바꿔주기 |
|
116 |
- $route(to) { |
|
117 |
- this.currentPath = to.path; |
|
118 |
- }, |
|
119 |
- async "$store.state.menu"(newVal) { |
|
120 |
- if (newVal == null || newVal == "" || newVal == undefined) { |
|
121 |
- this.menuList = []; |
|
122 |
- } else { |
|
123 |
- this.menuList = newVal.childList; |
|
124 |
- if (newVal && this.menuList.length > 0) { |
|
125 |
- await this.cntnStatsSave(this.menuList[0].menuId); |
|
126 |
- if ( |
|
127 |
- newVal.menuId == "MENU_000000000000010" && |
|
128 |
- this.$store.state.path.includes("BBS_MNG_") |
|
129 |
- ) { |
|
130 |
- return; |
|
131 |
- } else { |
|
132 |
- this.$router.push(this.menuList[0].routerUrl); |
|
133 |
- } |
|
134 |
- } |
|
135 |
- } |
|
136 |
- }, |
|
137 |
- "$store.state.mbrNm"(newVal) { |
|
138 |
- this.mbrNm = newVal; |
|
139 |
- }, |
|
140 |
- }, |
|
141 |
- computed: {}, |
|
142 |
- mounted() { }, |
|
109 |
+ watch: { |
|
110 |
+ // '$store.state.menu'(newValue) { |
|
111 |
+ // this.checkMenu = newValue ? newValue.menuId : null; |
|
112 |
+ // }, |
|
113 |
+ // 나중에 네비게이션 가드에서 form 받을 수 있으면 form adm/main으로 갈때 sotre.state값0로 바꿔주기 |
|
114 |
+ $route(to) { |
|
115 |
+ this.currentPath = to.path; |
|
116 |
+ }, |
|
117 |
+ // async "$store.state.menu"(newVal) { |
|
118 |
+ // console.log(newVal) |
|
119 |
+ // if (newVal == null || newVal == "" || newVal == undefined) { |
|
120 |
+ // this.menuList = []; |
|
121 |
+ // } else { |
|
122 |
+ // this.menuList = newVal.childList; |
|
123 |
+ // if (newVal && this.menuList.length > 0) { |
|
124 |
+ // await this.cntnStatsSave(this.menuList[0].menuId); |
|
125 |
+ // if ( |
|
126 |
+ // newVal.menuId == "MENU_000000000000010" && |
|
127 |
+ // this.$store.state.path.includes("BBS_MNG_") |
|
128 |
+ // ) { |
|
129 |
+ // return; |
|
130 |
+ // } else { |
|
131 |
+ // this.$router.push(this.menuList[0].routerUrl); |
|
132 |
+ // } |
|
133 |
+ // } |
|
134 |
+ // } |
|
135 |
+ // }, |
|
136 |
+ "$store.state.mbrNm"(newVal) { |
|
137 |
+ this.mbrNm = newVal; |
|
138 |
+ }, |
|
139 |
+ } |
|
143 | 140 |
}; |
144 | 141 |
</script> |
142 |
+ |
|
143 |
+<style scoped> |
|
144 |
+/* 메뉴 스타일 */ |
|
145 |
+.main-menu { |
|
146 |
+ list-style: none; |
|
147 |
+ padding: 0; |
|
148 |
+ margin: 0; |
|
149 |
+} |
|
150 |
+ |
|
151 |
+.menu-item { |
|
152 |
+ position: relative; |
|
153 |
+ cursor: pointer; |
|
154 |
+ padding: 10px; |
|
155 |
+ border-bottom: 1px solid #ccc; |
|
156 |
+} |
|
157 |
+ |
|
158 |
+/* 서브메뉴 스타일 */ |
|
159 |
+.sub-menu { |
|
160 |
+ list-style: none; |
|
161 |
+ padding: 5px 0; |
|
162 |
+ margin: 0; |
|
163 |
+ background: white; |
|
164 |
+ border: 1px solid #ccc; |
|
165 |
+ display: block; |
|
166 |
+ width: 100%; |
|
167 |
+} |
|
168 |
+ |
|
169 |
+.sub-menu li { |
|
170 |
+ padding: 8px 15px; |
|
171 |
+ cursor: pointer; |
|
172 |
+} |
|
173 |
+ |
|
174 |
+.sub-menu li:hover { |
|
175 |
+ background-color: #f0f0f0; |
|
176 |
+} |
|
177 |
+</style> |
+++ client/views/pages/adm/boardManagement/template/commonTemplate/CommonInsert copy.vue
... | ... | @@ -0,0 +1,657 @@ |
1 | +<template> | |
2 | + <div | |
3 | + :class="{ | |
4 | + content: true, | |
5 | + 'admin-style overflow-y': pageRole === 'adm', | |
6 | + 'w1400 pt50 pb50': pageRole === 'portal', | |
7 | + }" | |
8 | + > | |
9 | + <div | |
10 | + :class="{ | |
11 | + 'admin-page-title point-font2 mb30': pageRole == 'adm', | |
12 | + 'page-title point-font mb30': | |
13 | + pageRole == 'portal', | |
14 | + }" | |
15 | + > | |
16 | + <p>{{ bbsMng.bbsNm }}</p> | |
17 | + </div> | |
18 | + <table class="form-table mb30"> | |
19 | + <colgroup> | |
20 | + <col width="10%" /> | |
21 | + <col width="90%" /> | |
22 | + </colgroup> | |
23 | + <tbody> | |
24 | + <tr> | |
25 | + <th | |
26 | + :class="{ | |
27 | + 'text-lf': true, | |
28 | + 'point-font2': pageRole == 'adm', | |
29 | + 'point-font': pageRole == 'portal', | |
30 | + }" | |
31 | + > | |
32 | + <span>제목</span> | |
33 | + </th> | |
34 | + <td> | |
35 | + <input | |
36 | + type="text" | |
37 | + class="full-input" | |
38 | + v-model="bbsCn.bbsNm" | |
39 | + placeholder="제목을 입력하세요." | |
40 | + /> | |
41 | + </td> | |
42 | + </tr> | |
43 | + <tr class="border-top"> | |
44 | + <th | |
45 | + colspan="4" | |
46 | + :class="{ | |
47 | + 'text-lf': true, | |
48 | + 'point-font2': pageRole == 'adm', | |
49 | + 'point-font': pageRole == 'portal', | |
50 | + }" | |
51 | + > | |
52 | + <span>내용</span> | |
53 | + </th> | |
54 | + </tr> | |
55 | + <tr style="max-height: 600px"> | |
56 | + <td colspan="4" style="height: 100%"> | |
57 | + <!-- <textarea name="smart" id="smart" style="width:100%"></textarea> --> | |
58 | + <!-- <textarea name="editor4" id="editor4" style="width:100%"></textarea> --> | |
59 | + <ckeditorComponent | |
60 | + ref="ckeditor5" | |
61 | + :bbsCn.sync="bbsCn" | |
62 | + ></ckeditorComponent> | |
63 | + </td> | |
64 | + </tr> | |
65 | + <tr v-if="bbsMng.atchFileUseYn === 'Y'" class="border-top"> | |
66 | + <th | |
67 | + :class="{ | |
68 | + 'text-lf': true, | |
69 | + 'point-font2': pageRole == 'adm', | |
70 | + 'point-font': pageRole == 'portal', | |
71 | + }" | |
72 | + > | |
73 | + 첨부파일 | |
74 | + </th> | |
75 | + <td colspan="2"> | |
76 | + <div class="gd-12 pr0"> | |
77 | + <div class="gd-2 pl0 pr0"> | |
78 | + <label | |
79 | + for="file" | |
80 | + :class="{ | |
81 | + 'large-btn text-ct': true, | |
82 | + 'blue-border-btn': pageRole == 'adm', | |
83 | + 'green-border-btn': | |
84 | + pageRole == 'portal', | |
85 | + }" | |
86 | + >파일찾기</label | |
87 | + > | |
88 | + <input | |
89 | + type="file" | |
90 | + id="file" | |
91 | + ref="file" | |
92 | + @change="fnFileInsert" | |
93 | + multiple | |
94 | + /> | |
95 | + </div> | |
96 | + <div class="gd-12 pl0 pr0" v-if="fileList.length > 0"> | |
97 | + <ul> | |
98 | + <li | |
99 | + v-for="(file, idx) in fileList" | |
100 | + :key="idx" | |
101 | + class="pd10 mt10 border radius" | |
102 | + > | |
103 | + <div | |
104 | + v-if="file['fileId'] != null" | |
105 | + class="flex align-center justify-between file-wrap" | |
106 | + > | |
107 | + <p>{{ file["fileNm"] }}.{{ file["extnNm"] }}</p> | |
108 | + <button class="del-btn" @click="fnFileDelete(file, idx)"> | |
109 | + X | |
110 | + </button> | |
111 | + </div> | |
112 | + <div | |
113 | + v-else | |
114 | + class="flex align-center justify-between file-wrap" | |
115 | + > | |
116 | + <p>{{ file.name }}</p> | |
117 | + <button class="del-btn" @click="fnFileDelete(file, idx)"> | |
118 | + X | |
119 | + </button> | |
120 | + </div> | |
121 | + </li> | |
122 | + </ul> | |
123 | + </div> | |
124 | + </div> | |
125 | + </td> | |
126 | + </tr> | |
127 | + <tr v-if="bbsMng.ntcUseYn === 'Y'" class="border-top"> | |
128 | + <th | |
129 | + :class="{ | |
130 | + 'text-lf': true, | |
131 | + 'point-font2': pageRole == 'adm', | |
132 | + 'point-font': pageRole == 'portal', | |
133 | + }" | |
134 | + > | |
135 | + 공지글 | |
136 | + </th> | |
137 | + <td colspan="3"> | |
138 | + <div class="flex align-center no-gutters"> | |
139 | + <div class="gd-4"> | |
140 | + <input | |
141 | + type="radio" | |
142 | + name="notice" | |
143 | + id="notice-y" | |
144 | + class="mr5" | |
145 | + value="Y" | |
146 | + v-model="bbsCn.ntcPstYn" | |
147 | + /> | |
148 | + <label for="notice-y">사용</label> | |
149 | + </div> | |
150 | + <div class="gd-4"> | |
151 | + <input | |
152 | + type="radio" | |
153 | + name="notice" | |
154 | + id="notice-n" | |
155 | + class="mr5" | |
156 | + value="N" | |
157 | + v-model="bbsCn.ntcPstYn" | |
158 | + /> | |
159 | + <label for="notice-n">미사용</label> | |
160 | + </div> | |
161 | + </div> | |
162 | + </td> | |
163 | + </tr> | |
164 | + <tr v-if="bbsCn.ntcPstYn === 'Y'" class="border-top"> | |
165 | + <th | |
166 | + :class="{ | |
167 | + 'text-lf': true, | |
168 | + 'point-font2': pageRole == 'adm', | |
169 | + 'point-font': pageRole == 'portal', | |
170 | + }" | |
171 | + > | |
172 | + 공지글 게시기간 | |
173 | + </th> | |
174 | + <td colspan="3"> | |
175 | + <div class="flex align-center no-gutters"> | |
176 | + <div class="gd-4"> | |
177 | + <input | |
178 | + type="datetime-local" | |
179 | + class="full-input ml0" | |
180 | + v-model="bbsCn.ntcBgngDt" | |
181 | + @change="checkDateValidity('ntcBgngDt', $event)" | |
182 | + /> | |
183 | + </div> | |
184 | + <div class="pd10">-</div> | |
185 | + <div class="gd-4"> | |
186 | + <input | |
187 | + type="datetime-local" | |
188 | + class="full-input ml0" | |
189 | + v-model="bbsCn.ntcEndDt" | |
190 | + @change="checkDateValidity('ntcEndDt', $event)" | |
191 | + /> | |
192 | + </div> | |
193 | + </div> | |
194 | + </td> | |
195 | + </tr> | |
196 | + <tr v-if="bbsMng.prvtPstUseYn === 'Y'" class="border-top"> | |
197 | + <th | |
198 | + :class="{ | |
199 | + 'text-lf': true, | |
200 | + 'point-font2': pageRole == 'adm', | |
201 | + 'point-font': pageRole == 'portal', | |
202 | + }" | |
203 | + > | |
204 | + 비밀글 | |
205 | + </th> | |
206 | + <td colspan="3"> | |
207 | + <div class="flex align-center no-gutters"> | |
208 | + <div class="gd-4"> | |
209 | + <input | |
210 | + type="radio" | |
211 | + name="private" | |
212 | + id="private-y" | |
213 | + class="mr5" | |
214 | + value="Y" | |
215 | + v-model="bbsCn.prvtPstYn" | |
216 | + /> | |
217 | + <label for="private-y">사용</label> | |
218 | + </div> | |
219 | + <div class="gd-4"> | |
220 | + <input | |
221 | + type="radio" | |
222 | + name="private" | |
223 | + id="private-n" | |
224 | + class="mr5" | |
225 | + value="N" | |
226 | + v-model="bbsCn.prvtPstYn" | |
227 | + /> | |
228 | + <label for="private-n">미사용</label> | |
229 | + </div> | |
230 | + </div> | |
231 | + </td> | |
232 | + </tr> | |
233 | + </tbody> | |
234 | + </table> | |
235 | + <div class="flex justify-end align-center no-gutters"> | |
236 | + <div class="gd-1 mr10"> | |
237 | + <button | |
238 | + :class="{ | |
239 | + 'large-btn': true, | |
240 | + 'blue-btn': pageRole == 'adm', | |
241 | + 'green-btn': pageRole == 'portal', | |
242 | + }" | |
243 | + @click="fnInsert" | |
244 | + > | |
245 | + {{ bbsCn.bbsId == null ? "등록" : "수정" }} | |
246 | + </button> | |
247 | + </div> | |
248 | + <div class="gd-1"> | |
249 | + <button class="large-btn gray-btn" @click="fnCancel">취소</button> | |
250 | + </div> | |
251 | + </div> | |
252 | + </div> | |
253 | +</template> | |
254 | + | |
255 | +<script> | |
256 | +import { mdiClose } from "@mdi/js"; | |
257 | +import { findByBbsCn } from "../../../../../../resources/api/bbsCn.js"; | |
258 | +import queryParams from "../../../../../../resources/js/queryParams"; | |
259 | +import defaultAxios from "../../../../../../resources/js/defaultAxios"; | |
260 | +// ckditor5 | |
261 | +import ckeditorComponent from "../../../../../component/ckeditor5/ckeditorComponent.vue"; | |
262 | + | |
263 | +export default { | |
264 | + mixins: [queryParams], | |
265 | + data() { | |
266 | + return { | |
267 | + file: null, | |
268 | + iconPath: mdiClose, | |
269 | + pageRole: this.$store.state.userType, | |
270 | + path: this.$store.state.path, | |
271 | + pageAuth: this.$store.state.pageAuth, | |
272 | + bbsMngId: null, | |
273 | + bbsCn: {}, | |
274 | + bbsMng: {}, | |
275 | + | |
276 | + // 파일 업로드 | |
277 | + files: null, | |
278 | + fileList: [], | |
279 | + deleteFileList: [], | |
280 | + | |
281 | + //이미지 업로드 | |
282 | + imgFiles: null, | |
283 | + imgFileList: [], | |
284 | + deleteImgFileList: [], | |
285 | + | |
286 | + //스마트 에디터 | |
287 | + editor: null, | |
288 | + }; | |
289 | + }, | |
290 | + created() { | |
291 | + this.fnBbsIdExtraction(); | |
292 | + this.fnSelectOne(); | |
293 | + }, | |
294 | + methods: { | |
295 | + test() { | |
296 | + this.Validation(); | |
297 | + }, | |
298 | + | |
299 | + // 취소 버튼 동작 | |
300 | + fnCancel() { | |
301 | + if (!confirm("등록을 취소하시겠습니까?")) { | |
302 | + return; | |
303 | + } | |
304 | + if (this.bbsCn.bbsId == null || this.bbsCn.bbsId == 0) { | |
305 | + this.$router.push({ | |
306 | + path: this.path + "/list.page", | |
307 | + }); | |
308 | + } else { | |
309 | + this.$router.push({ | |
310 | + path: this.path + "/view.page", | |
311 | + query: { | |
312 | + pageId: this.bbsCn.bbsId, | |
313 | + }, | |
314 | + }); | |
315 | + } | |
316 | + }, | |
317 | + // 상세조회 | |
318 | + async fnSelectOne() { | |
319 | + try { | |
320 | + const params = { | |
321 | + bbsId: this.$route.query.pageId, | |
322 | + bbsMngId: this.bbsMngId, | |
323 | + }; | |
324 | + const res = await findByBbsCn(params); | |
325 | + if (res.status == 200) { | |
326 | + this.bbsCn = res.data.data.bbsCn; | |
327 | + this.bbsMng = res.data.data.bbsMng; | |
328 | + this.bbsMng.byteLmt = res.data.data.bbsMng.fileSzLmt * 1024 * 1024; | |
329 | + this.fileList = res.data.data.fileList; | |
330 | + | |
331 | + this.$refs.ckeditor5.createEditor(); | |
332 | + } | |
333 | + } catch (error) { | |
334 | + alert("에러가 발생했습니다.\n시스템관리자에게 문의하세요."); | |
335 | + } | |
336 | + }, | |
337 | + // 첨부파일 등록 | |
338 | + fnFileInsert() { | |
339 | + // files 개수 만큼 반복해서 type, size 체크 | |
340 | + this.files = this.$refs.file.files; | |
341 | + for (let i = 0; i < this.files.length; i++) { | |
342 | + const file = this.files[i]; | |
343 | + const extnNm = file.name.split(".").pop(); | |
344 | + if (this.bbsMng.fileExtnNmList.length >= 1) { | |
345 | + if (!this.bbsMng.fileExtnNmList.includes(extnNm)) { | |
346 | + alert( | |
347 | + "첨부파일 확장자를 확인해주세요.\n등록가능 확장자: " + | |
348 | + this.bbsMng.fileExtnNmList | |
349 | + ); | |
350 | + return; | |
351 | + } | |
352 | + } | |
353 | + if (this.bbsMng.byteLmt != 0 && this.bbsMng.byteLmt != null) { | |
354 | + if (file.size > this.bbsMng.byteLmt) { | |
355 | + alert(this.bbsMng.fileSzLmt + "MB 이하의 파일만 등록 가능합니다."); | |
356 | + return; | |
357 | + } | |
358 | + } | |
359 | + } | |
360 | + this.fileList = [...this.fileList, ...Array.from(this.files)]; | |
361 | + }, | |
362 | + // 첨부파일 삭제 | |
363 | + fnFileDelete(file, index) { | |
364 | + if (file["fileId"] != null) { | |
365 | + this.deleteFileList.push(file); | |
366 | + } | |
367 | + this.fileList.splice(index, 1); | |
368 | + }, | |
369 | + fnInsert() { | |
370 | + if (this.bbsCn.bbsId == null || this.bbsCn.bbsId == 0) { | |
371 | + this.fnSave(); | |
372 | + } else { | |
373 | + this.fnUpdate(); | |
374 | + } | |
375 | + }, | |
376 | + // 등록 | |
377 | + async fnSave() { | |
378 | + if (!this.Validation()) { | |
379 | + return; | |
380 | + } | |
381 | + // 폼데이터 생성 | |
382 | + this.bbsCn.bbsMngId = this.bbsMngId; | |
383 | + var formData = new FormData(); | |
384 | + const paramsToBlob = new Blob([JSON.stringify(this.bbsCn)], { | |
385 | + type: "application/json; charset=UTF-8", | |
386 | + }); | |
387 | + formData.append("bbsCn", paramsToBlob); | |
388 | + for (const file of this.fileList) { | |
389 | + formData.append("multipartFileList", file); | |
390 | + } | |
391 | + for (const imgFile of this.imgFileList) { | |
392 | + formData.append("multipartImgList", imgFile); | |
393 | + } | |
394 | + // axios 호출 | |
395 | + await defaultAxios({ | |
396 | + url: "/sys/bbsCn/saveBbsCn.file", | |
397 | + method: "post", | |
398 | + headers: { | |
399 | + "Content-Type": "multipart/form-data; charset=UTF-8", | |
400 | + Authorization: this.$store.state.authorization, | |
401 | + }, | |
402 | + data: formData, | |
403 | + }) | |
404 | + .then((response) => { | |
405 | + const bbsId = response.data.data.bbsId; | |
406 | + alert("게시글이 등록되었습니다."); | |
407 | + this.$router.push({ | |
408 | + // name: 'BoardManagementSelectListOne', | |
409 | + path: this.path + "/view.page", | |
410 | + query: { | |
411 | + pageId: bbsId, | |
412 | + }, | |
413 | + }); | |
414 | + }) | |
415 | + .catch((error) => { | |
416 | + const message = error.response.data.message; | |
417 | + alert(message); | |
418 | + }); | |
419 | + }, | |
420 | + // 수정 | |
421 | + async fnUpdate() { | |
422 | + if (!this.Validation()) { | |
423 | + return; | |
424 | + } | |
425 | + // 폼데이터 생성 | |
426 | + this.bbsCn.bbsMngId = this.bbsMngId; | |
427 | + var formData = new FormData(); | |
428 | + const paramsToBlob = new Blob([JSON.stringify(this.bbsCn)], { | |
429 | + type: "application/json; charset=UTF-8", | |
430 | + }); | |
431 | + formData.append("params", paramsToBlob); | |
432 | + const deleteFileListToBlob = new Blob( | |
433 | + [JSON.stringify(this.deleteFileList)], | |
434 | + { | |
435 | + type: "application/json; charset=UTF-8", | |
436 | + } | |
437 | + ); | |
438 | + formData.append("deleteFileList", deleteFileListToBlob); | |
439 | + // 추가 첨부파일 | |
440 | + for (const file of this.fileList) { | |
441 | + if (file["fileId"] == null) { | |
442 | + formData.append("multipartFileList", file); | |
443 | + } | |
444 | + } | |
445 | + // 이미지 파일 | |
446 | + const deleteImgFileListToBlob = new Blob( | |
447 | + [JSON.stringify(this.deleteImgFileList)], | |
448 | + { | |
449 | + type: "application/json; charset=UTF-8", | |
450 | + } | |
451 | + ); | |
452 | + formData.append("deleteImgFileList", deleteImgFileListToBlob); | |
453 | + for (const imgFile of this.imgFileList) { | |
454 | + formData.append("multipartImgList", imgFile); | |
455 | + } | |
456 | + // axios 호출 | |
457 | + defaultAxios({ | |
458 | + url: "/sys/bbsCn/updateBbsCn.file", | |
459 | + method: "post", | |
460 | + headers: { | |
461 | + "Content-Type": "multipart/form-data; charset=UTF-8", | |
462 | + Authorization: this.$store.state.authorization, | |
463 | + }, | |
464 | + data: formData, | |
465 | + }) | |
466 | + .then((response) => { | |
467 | + const bbsId = response.data.data; | |
468 | + this.$router.push({ | |
469 | + // name: 'BoardManagementSelectListOne', | |
470 | + path: this.path + "/view.page", | |
471 | + query: { | |
472 | + pageId: bbsId, | |
473 | + }, | |
474 | + }); | |
475 | + }) | |
476 | + .catch((error) => { | |
477 | + const message = error.response.data.message; | |
478 | + alert(message); | |
479 | + }); | |
480 | + }, | |
481 | + // 유효성 검사 | |
482 | + Validation() { | |
483 | + if (this.bbsCn.bbsNm == null || this.bbsCn.bbsNm.trim() == "") { | |
484 | + alert("게시판 제목을 입력해주세요."); | |
485 | + return false; | |
486 | + } | |
487 | + | |
488 | + // const oEditors = this.oEditors; | |
489 | + // oEditors.getById["smart"].exec("UPDATE_CONTENTS_FIELD", []); | |
490 | + // // 스마트에디터의 iframe에 있는 내용을 textarea로. | |
491 | + // this.bbsCn.bbsCn = document.getElementById("smart").value; | |
492 | + | |
493 | + // 내용 null검사 | |
494 | + // if (!this.tagChecked() && (this.isEmpty(this.bbsCn.bbsCn) || this.removeHtmlAndSpace(this.bbsCn.bbsCn) === '')) { | |
495 | + // alert("내용을 입력하세요."); | |
496 | + // document.getElementById("smart").focus(); | |
497 | + // return false; | |
498 | + // } | |
499 | + | |
500 | + if ( | |
501 | + !this.tagChecked() && | |
502 | + (this.isEmpty(this.bbsCn.bbsCn) || | |
503 | + this.removeHtmlAndSpace(this.bbsCn.bbsCn) === "") | |
504 | + ) { | |
505 | + alert("게시판 내용을 입력해주세요."); | |
506 | + return false; | |
507 | + } | |
508 | + if ( | |
509 | + this.bbsCn.ntcPstYn === "Y" && | |
510 | + (this.bbsCn.ntcBgngDt === null || this.bbsCn.ntcEndDt === null) | |
511 | + ) { | |
512 | + alert("공지기간을 올바르게 설정해주세요."); | |
513 | + return false; | |
514 | + } | |
515 | + | |
516 | + return true; | |
517 | + }, | |
518 | + | |
519 | + // 태그 체크 | |
520 | + tagChecked() { | |
521 | + const tag = this.bbsCn.bbsCn; | |
522 | + if (tag.indexOf("<img") != -1) { | |
523 | + return true; | |
524 | + } else { | |
525 | + return false; | |
526 | + } | |
527 | + }, | |
528 | + | |
529 | + /** | |
530 | + * 빈 객체 여부 | |
531 | + */ | |
532 | + isEmpty: function (data) { | |
533 | + if ( | |
534 | + data === undefined || | |
535 | + data === null || | |
536 | + data === "" || | |
537 | + data.length === 0 || | |
538 | + (data.constructor == Object && Object.keys(data).length === 0) | |
539 | + ) { | |
540 | + return true; | |
541 | + } else { | |
542 | + return false; | |
543 | + } | |
544 | + }, | |
545 | + | |
546 | + removeHtmlAndSpace: function (str) { | |
547 | + return str | |
548 | + .replace(/<[^>]*>/g, "") // HTML 태그 제거 | |
549 | + .replace(/ /gi, " ") // 를 공백으로 변환 | |
550 | + .replace(/\s/g, ""); // 모든 공백 제거 | |
551 | + }, | |
552 | + // 공지기간 유효성 체크 | |
553 | + checkDateValidity(changeDate, event) { | |
554 | + const val = event.target.value; // 변경된 날짜 값 | |
555 | + // 시작일 변경 시 | |
556 | + if (changeDate === "ntcBgngDt") { | |
557 | + if (this.bbsCn.ntcEndDt !== null && this.bbsCn.ntcEndDt < val) { | |
558 | + alert("시작일은 종료일보다 클 수 없습니다."); | |
559 | + this.bbsCn.ntcBgngDt = null; // 유효하지 않은 경우, 시작일을 초기화 | |
560 | + } else { | |
561 | + this.bbsCn.ntcBgngDt = val; | |
562 | + } | |
563 | + } | |
564 | + // 종료일 변경 시 | |
565 | + else if (changeDate === "ntcEndDt") { | |
566 | + if (this.bbsCn.ntcBgngDt !== null && this.bbsCn.ntcBgngDt > val) { | |
567 | + alert("종료일은 시작일보다 작을 수 없습니다."); | |
568 | + this.bbsCn.ntcEndDt = null; // 유효하지 않은 경우, 종료일을 초기화 | |
569 | + } else { | |
570 | + this.bbsCn.ntcEndDt = val; | |
571 | + } | |
572 | + } | |
573 | + }, | |
574 | + | |
575 | + // // 에디터 생성 | |
576 | + // createEditor: function () { | |
577 | + // // ck에디터 적용 | |
578 | + // ClassicEditor | |
579 | + // .create(document.querySelector('#editor4'), { | |
580 | + // extraPlugins: [this.MyCustomUploadAdapterPlugin], | |
581 | + // removePlugins: ['MediaEmbedToolbar'], | |
582 | + // image: { | |
583 | + // toolbar: ['imageTextAlternative', '|', 'imageStyle:alignLeft', 'imageStyle:alignCenter', 'imageStyle:alignRight','|','resizeImage:50','resizeImage:75', 'resizeImage:original','resizeImage:custom',], | |
584 | + // resizeOptions: [ | |
585 | + // { | |
586 | + // name: 'resizeImage:original', | |
587 | + // value: null, | |
588 | + // icon: 'original' | |
589 | + // }, | |
590 | + // { | |
591 | + // name: 'resizeImage:custom', | |
592 | + // value: 'custom', | |
593 | + // icon: 'custom' | |
594 | + // }, | |
595 | + // { | |
596 | + // name: 'resizeImage:50', | |
597 | + // value: '50', | |
598 | + // icon: 'medium' | |
599 | + // }, | |
600 | + // { | |
601 | + // name: 'resizeImage:75', | |
602 | + // value: '75', | |
603 | + // icon: 'large' | |
604 | + // } | |
605 | + // ], | |
606 | + // }, | |
607 | + | |
608 | + // }) | |
609 | + // .then(editor => { | |
610 | + // this.editor = editor; | |
611 | + // editor.setData(this.bbsCn.bbsCn); | |
612 | + // editor.model.document.on('change', () => { | |
613 | + // this.bbsCn.bbsCn = editor.getData(); | |
614 | + // }); | |
615 | + // }) | |
616 | + // .catch(error => { | |
617 | + // console.error('There was a problem initializing the editor.', error); | |
618 | + // }); | |
619 | + // }, | |
620 | + | |
621 | + // beforeDestroy: function() { | |
622 | + // if (this.editor) { | |
623 | + // this.editor.destroy() | |
624 | + // .then(() => { | |
625 | + // this.editor = null; | |
626 | + // }); | |
627 | + // } | |
628 | + // }, | |
629 | + | |
630 | + // MyCustomUploadAdapterPlugin: function(editor) { | |
631 | + // editor.plugins.get('FileRepository').createUploadAdapter = (loader) => { | |
632 | + // console.log('loader', loader); | |
633 | + // return new UploadAdapter(loader); | |
634 | + // } | |
635 | + // } | |
636 | + }, | |
637 | + watch: { | |
638 | + "bbsCn.ntcPstYn": function (val) { | |
639 | + if (val === "Y") { | |
640 | + const offset = new Date().getTimezoneOffset() * 60000; | |
641 | + const now = new Date(Date.now() - offset).toISOString().slice(0, 16); | |
642 | + this.bbsCn.ntcBgngDt = | |
643 | + this.bbsCn.ntcBgngDt == null ? now : this.bbsCn.ntcBgngDt; | |
644 | + this.bbsCn.ntcEndDt = | |
645 | + this.bbsCn.ntcEndDt == null ? now : this.bbsCn.ntcEndDt; | |
646 | + } | |
647 | + }, | |
648 | + }, | |
649 | + computed: {}, | |
650 | + components: { | |
651 | + ckeditorComponent, | |
652 | + }, | |
653 | + mounted() {}, | |
654 | +}; | |
655 | +</script> | |
656 | +<style scoped> | |
657 | +</style> |
--- client/views/pages/adm/boardManagement/template/commonTemplate/CommonInsert.vue
+++ client/views/pages/adm/boardManagement/template/commonTemplate/CommonInsert.vue
... | ... | @@ -1,255 +1,219 @@ |
1 | 1 |
<template> |
2 |
- <div |
|
3 |
- :class="{ |
|
4 |
- content: true, |
|
5 |
- 'admin-style overflow-y': pageRole === 'adm', |
|
6 |
- 'w1400 pt50 pb50': pageRole === 'portal', |
|
7 |
- }" |
|
8 |
- > |
|
9 |
- <div |
|
10 |
- :class="{ |
|
11 |
- 'admin-page-title point-font2 mb30': pageRole == 'adm', |
|
12 |
- 'page-title point-font mb30': |
|
13 |
- pageRole == 'portal', |
|
14 |
- }" |
|
15 |
- > |
|
16 |
- <p>{{ bbsMng.bbsNm }}</p> |
|
17 |
- </div> |
|
18 |
- <table class="form-table mb30"> |
|
19 |
- <colgroup> |
|
20 |
- <col width="10%" /> |
|
21 |
- <col width="90%" /> |
|
22 |
- </colgroup> |
|
23 |
- <tbody> |
|
24 |
- <tr> |
|
25 |
- <th |
|
26 |
- :class="{ |
|
27 |
- 'text-lf': true, |
|
28 |
- 'point-font2': pageRole == 'adm', |
|
29 |
- 'point-font': pageRole == 'portal', |
|
30 |
- }" |
|
31 |
- > |
|
32 |
- <span>제목</span> |
|
33 |
- </th> |
|
34 |
- <td> |
|
35 |
- <input |
|
36 |
- type="text" |
|
37 |
- class="full-input" |
|
38 |
- v-model="bbsCn.bbsNm" |
|
39 |
- placeholder="제목을 입력하세요." |
|
40 |
- /> |
|
41 |
- </td> |
|
42 |
- </tr> |
|
43 |
- <tr class="border-top"> |
|
44 |
- <th |
|
45 |
- colspan="4" |
|
46 |
- :class="{ |
|
47 |
- 'text-lf': true, |
|
48 |
- 'point-font2': pageRole == 'adm', |
|
49 |
- 'point-font': pageRole == 'portal', |
|
50 |
- }" |
|
51 |
- > |
|
52 |
- <span>내용</span> |
|
53 |
- </th> |
|
54 |
- </tr> |
|
55 |
- <tr style="max-height: 600px"> |
|
56 |
- <td colspan="4" style="height: 100%"> |
|
57 |
- <!-- <textarea name="smart" id="smart" style="width:100%"></textarea> --> |
|
58 |
- <!-- <textarea name="editor4" id="editor4" style="width:100%"></textarea> --> |
|
59 |
- <ckeditorComponent |
|
60 |
- ref="ckeditor5" |
|
61 |
- :bbsCn.sync="bbsCn" |
|
62 |
- ></ckeditorComponent> |
|
63 |
- </td> |
|
64 |
- </tr> |
|
65 |
- <tr v-if="bbsMng.atchFileUseYn === 'Y'" class="border-top"> |
|
66 |
- <th |
|
67 |
- :class="{ |
|
68 |
- 'text-lf': true, |
|
69 |
- 'point-font2': pageRole == 'adm', |
|
70 |
- 'point-font': pageRole == 'portal', |
|
71 |
- }" |
|
72 |
- > |
|
73 |
- 첨부파일 |
|
74 |
- </th> |
|
75 |
- <td colspan="2"> |
|
76 |
- <div class="gd-12 pr0"> |
|
77 |
- <div class="gd-2 pl0 pr0"> |
|
78 |
- <label |
|
79 |
- for="file" |
|
80 |
- :class="{ |
|
81 |
- 'large-btn text-ct': true, |
|
82 |
- 'blue-border-btn': pageRole == 'adm', |
|
83 |
- 'green-border-btn': |
|
84 |
- pageRole == 'portal', |
|
85 |
- }" |
|
86 |
- >파일찾기</label |
|
87 |
- > |
|
88 |
- <input |
|
89 |
- type="file" |
|
90 |
- id="file" |
|
91 |
- ref="file" |
|
92 |
- @change="fnFileInsert" |
|
93 |
- multiple |
|
94 |
- /> |
|
95 |
- </div> |
|
96 |
- <div class="gd-12 pl0 pr0" v-if="fileList.length > 0"> |
|
97 |
- <ul> |
|
98 |
- <li |
|
99 |
- v-for="(file, idx) in fileList" |
|
100 |
- :key="idx" |
|
101 |
- class="pd10 mt10 border radius" |
|
102 |
- > |
|
103 |
- <div |
|
104 |
- v-if="file['fileId'] != null" |
|
105 |
- class="flex align-center justify-between file-wrap" |
|
106 |
- > |
|
107 |
- <p>{{ file["fileNm"] }}.{{ file["extnNm"] }}</p> |
|
108 |
- <button class="del-btn" @click="fnFileDelete(file, idx)"> |
|
109 |
- X |
|
110 |
- </button> |
|
111 |
- </div> |
|
112 |
- <div |
|
113 |
- v-else |
|
114 |
- class="flex align-center justify-between file-wrap" |
|
115 |
- > |
|
116 |
- <p>{{ file.name }}</p> |
|
117 |
- <button class="del-btn" @click="fnFileDelete(file, idx)"> |
|
118 |
- X |
|
119 |
- </button> |
|
120 |
- </div> |
|
121 |
- </li> |
|
122 |
- </ul> |
|
123 |
- </div> |
|
124 |
- </div> |
|
125 |
- </td> |
|
126 |
- </tr> |
|
127 |
- <tr v-if="bbsMng.ntcUseYn === 'Y'" class="border-top"> |
|
128 |
- <th |
|
129 |
- :class="{ |
|
130 |
- 'text-lf': true, |
|
131 |
- 'point-font2': pageRole == 'adm', |
|
132 |
- 'point-font': pageRole == 'portal', |
|
133 |
- }" |
|
134 |
- > |
|
135 |
- 공지글 |
|
136 |
- </th> |
|
137 |
- <td colspan="3"> |
|
138 |
- <div class="flex align-center no-gutters"> |
|
139 |
- <div class="gd-4"> |
|
140 |
- <input |
|
141 |
- type="radio" |
|
142 |
- name="notice" |
|
143 |
- id="notice-y" |
|
144 |
- class="mr5" |
|
145 |
- value="Y" |
|
146 |
- v-model="bbsCn.ntcPstYn" |
|
147 |
- /> |
|
148 |
- <label for="notice-y">사용</label> |
|
149 |
- </div> |
|
150 |
- <div class="gd-4"> |
|
151 |
- <input |
|
152 |
- type="radio" |
|
153 |
- name="notice" |
|
154 |
- id="notice-n" |
|
155 |
- class="mr5" |
|
156 |
- value="N" |
|
157 |
- v-model="bbsCn.ntcPstYn" |
|
158 |
- /> |
|
159 |
- <label for="notice-n">미사용</label> |
|
160 |
- </div> |
|
161 |
- </div> |
|
162 |
- </td> |
|
163 |
- </tr> |
|
164 |
- <tr v-if="bbsCn.ntcPstYn === 'Y'" class="border-top"> |
|
165 |
- <th |
|
166 |
- :class="{ |
|
167 |
- 'text-lf': true, |
|
168 |
- 'point-font2': pageRole == 'adm', |
|
169 |
- 'point-font': pageRole == 'portal', |
|
170 |
- }" |
|
171 |
- > |
|
172 |
- 공지글 게시기간 |
|
173 |
- </th> |
|
174 |
- <td colspan="3"> |
|
175 |
- <div class="flex align-center no-gutters"> |
|
176 |
- <div class="gd-4"> |
|
177 |
- <input |
|
178 |
- type="datetime-local" |
|
179 |
- class="full-input ml0" |
|
180 |
- v-model="bbsCn.ntcBgngDt" |
|
181 |
- @change="checkDateValidity('ntcBgngDt', $event)" |
|
182 |
- /> |
|
183 |
- </div> |
|
184 |
- <div class="pd10">-</div> |
|
185 |
- <div class="gd-4"> |
|
186 |
- <input |
|
187 |
- type="datetime-local" |
|
188 |
- class="full-input ml0" |
|
189 |
- v-model="bbsCn.ntcEndDt" |
|
190 |
- @change="checkDateValidity('ntcEndDt', $event)" |
|
191 |
- /> |
|
192 |
- </div> |
|
193 |
- </div> |
|
194 |
- </td> |
|
195 |
- </tr> |
|
196 |
- <tr v-if="bbsMng.prvtPstUseYn === 'Y'" class="border-top"> |
|
197 |
- <th |
|
198 |
- :class="{ |
|
199 |
- 'text-lf': true, |
|
200 |
- 'point-font2': pageRole == 'adm', |
|
201 |
- 'point-font': pageRole == 'portal', |
|
202 |
- }" |
|
203 |
- > |
|
204 |
- 비밀글 |
|
205 |
- </th> |
|
206 |
- <td colspan="3"> |
|
207 |
- <div class="flex align-center no-gutters"> |
|
208 |
- <div class="gd-4"> |
|
209 |
- <input |
|
210 |
- type="radio" |
|
211 |
- name="private" |
|
212 |
- id="private-y" |
|
213 |
- class="mr5" |
|
214 |
- value="Y" |
|
215 |
- v-model="bbsCn.prvtPstYn" |
|
216 |
- /> |
|
217 |
- <label for="private-y">사용</label> |
|
218 |
- </div> |
|
219 |
- <div class="gd-4"> |
|
220 |
- <input |
|
221 |
- type="radio" |
|
222 |
- name="private" |
|
223 |
- id="private-n" |
|
224 |
- class="mr5" |
|
225 |
- value="N" |
|
226 |
- v-model="bbsCn.prvtPstYn" |
|
227 |
- /> |
|
228 |
- <label for="private-n">미사용</label> |
|
229 |
- </div> |
|
230 |
- </div> |
|
231 |
- </td> |
|
232 |
- </tr> |
|
233 |
- </tbody> |
|
234 |
- </table> |
|
235 |
- <div class="flex justify-end align-center no-gutters"> |
|
236 |
- <div class="gd-1 mr10"> |
|
237 |
- <button |
|
238 |
- :class="{ |
|
239 |
- 'large-btn': true, |
|
240 |
- 'blue-btn': pageRole == 'adm', |
|
241 |
- 'green-btn': pageRole == 'portal', |
|
242 |
- }" |
|
243 |
- @click="fnInsert" |
|
244 |
- > |
|
245 |
- {{ bbsCn.bbsId == null ? "등록" : "수정" }} |
|
246 |
- </button> |
|
2 |
+ |
|
3 |
+ <!-- 사용자 --> |
|
4 |
+ <template v-if="pageRole === 'portal'" > |
|
5 |
+ <div class="content w1400 pt50 pb50"> |
|
6 |
+ <div class="page-title point-font mb30"> |
|
7 |
+ <p>{{ bbsMng.bbsNm }}</p> |
|
8 |
+ </div> |
|
9 |
+ <table class="form-table mb30"> |
|
10 |
+ <colgroup> |
|
11 |
+ <col width="10%" /> |
|
12 |
+ <col width="90%" /> |
|
13 |
+ </colgroup> |
|
14 |
+ <tbody> |
|
15 |
+ <tr> |
|
16 |
+ <th class="text-lf point-font"> |
|
17 |
+ <span>제목</span> |
|
18 |
+ </th> |
|
19 |
+ <td> |
|
20 |
+ <input type="text" class="full-input" v-model="bbsCn.bbsNm" placeholder="제목을 입력하세요." /> |
|
21 |
+ </td> |
|
22 |
+ </tr> |
|
23 |
+ <tr class="border-top"> |
|
24 |
+ <th colspan="4" class="text-lf point-font"> |
|
25 |
+ <span>내용</span> |
|
26 |
+ </th> |
|
27 |
+ </tr> |
|
28 |
+ <tr style="max-height: 600px"> |
|
29 |
+ <td colspan="4" style="height: 100%"> |
|
30 |
+ <ckeditorComponent ref="ckeditor5" :bbsCn.sync="bbsCn"></ckeditorComponent> |
|
31 |
+ </td> |
|
32 |
+ </tr> |
|
33 |
+ </tbody> |
|
34 |
+ </table> |
|
247 | 35 |
</div> |
248 |
- <div class="gd-1"> |
|
249 |
- <button class="large-btn gray-btn" @click="fnCancel">취소</button> |
|
36 |
+ </template> |
|
37 |
+ |
|
38 |
+ <!-- 관리자 --> |
|
39 |
+ <template v-else> |
|
40 |
+ <div class="content-zone"> |
|
41 |
+ <div class="content"> |
|
42 |
+ <div class="scroll"> |
|
43 |
+ <div class="title-zone"> |
|
44 |
+ <div class="page-title"> |
|
45 |
+ <p>{{ bbsMng.bbsNm }}</p> |
|
46 |
+ </div> |
|
47 |
+ </div> |
|
48 |
+ <div class="tbl-wrap"> |
|
49 |
+ <table class="tbl data"> |
|
50 |
+ <colgroup> |
|
51 |
+ <col width="10%" /> |
|
52 |
+ <col width="90%" /> |
|
53 |
+ </colgroup> |
|
54 |
+ <tbody> |
|
55 |
+ <tr> |
|
56 |
+ <th class="text-lf"> |
|
57 |
+ <span>제목</span> |
|
58 |
+ </th> |
|
59 |
+ <td> |
|
60 |
+ <input type="text" class="form-control sm" v-model="bbsCn.bbsNm" placeholder="제목을 입력하세요." /> |
|
61 |
+ </td> |
|
62 |
+ </tr> |
|
63 |
+ <tr> |
|
64 |
+ <th class="text-lf" style="vertical-align: top;"> |
|
65 |
+ <span>내용</span> |
|
66 |
+ </th> |
|
67 |
+ <td> |
|
68 |
+ <ckeditorComponent ref="ckeditor5" :bbsCn.sync="bbsCn"></ckeditorComponent> |
|
69 |
+ </td> |
|
70 |
+ </tr> |
|
71 |
+ <tr v-if="bbsMng.atchFileUseYn === 'Y'"> |
|
72 |
+ <th>첨부파일</th> |
|
73 |
+ <td> |
|
74 |
+ <label for="file" >파일찾기</label> |
|
75 |
+ <input |
|
76 |
+ type="file" |
|
77 |
+ id="file" |
|
78 |
+ ref="file" |
|
79 |
+ @change="fnFileInsert" |
|
80 |
+ multiple |
|
81 |
+ /> |
|
82 |
+ <div v-if="fileList.length > 0"> |
|
83 |
+ <ul> |
|
84 |
+ <li v-for="(file, idx) in fileList" :key="idx"> |
|
85 |
+ <div v-if="file['fileId'] != null" class="file-wrap"> |
|
86 |
+ <p>{{ file["fileNm"] }}.{{ file["extnNm"] }}</p> |
|
87 |
+ <button class="del-btn" @click="fnFileDelete(file, idx)">X</button> |
|
88 |
+ </div> |
|
89 |
+ <div v-else class="file-wrap"> |
|
90 |
+ <p>{{ file.name }}</p> |
|
91 |
+ <button class="del-btn" @click="fnFileDelete(file, idx)">X</button> |
|
92 |
+ </div> |
|
93 |
+ </li> |
|
94 |
+ </ul> |
|
95 |
+ </div> |
|
96 |
+ </td> |
|
97 |
+ </tr> |
|
98 |
+ <tr v-if="bbsMng.ntcUseYn === 'Y'" class="border-top"> |
|
99 |
+ <th>공지글</th> |
|
100 |
+ <td> |
|
101 |
+ <div class="check-area"> |
|
102 |
+ <div class="form-check"> |
|
103 |
+ <input |
|
104 |
+ type="radio" |
|
105 |
+ name="notice" |
|
106 |
+ id="notice-y" |
|
107 |
+ class="mr5" |
|
108 |
+ value="Y" |
|
109 |
+ v-model="bbsCn.ntcPstYn" |
|
110 |
+ /> |
|
111 |
+ <label for="notice-y">사용</label> |
|
112 |
+ </div> |
|
113 |
+ <div class="form-check"> |
|
114 |
+ <input |
|
115 |
+ type="radio" |
|
116 |
+ name="notice" |
|
117 |
+ id="notice-n" |
|
118 |
+ class="mr5" |
|
119 |
+ value="N" |
|
120 |
+ v-model="bbsCn.ntcPstYn" |
|
121 |
+ /> |
|
122 |
+ <label for="notice-n">미사용</label> |
|
123 |
+ </div> |
|
124 |
+ </div> |
|
125 |
+ </td> |
|
126 |
+ </tr> |
|
127 |
+ <tr v-if="bbsCn.ntcPstYn === 'Y'" class="border-top"> |
|
128 |
+ <th>공지글 게시기간</th> |
|
129 |
+ <td> |
|
130 |
+ <div class="input-form"> |
|
131 |
+ <div class="form-control sm cal"> |
|
132 |
+ <VueDatePicker |
|
133 |
+ InlineOptions |
|
134 |
+ placeholder="시작일" |
|
135 |
+ locale="ko" |
|
136 |
+ :enable-time-picker="false" |
|
137 |
+ :format="formatDate" |
|
138 |
+ v-model="bbsCn.ntcBgngDt" |
|
139 |
+ @update:model-value="checkDateValidity('ntcBgngDt',$event)" |
|
140 |
+ /> |
|
141 |
+ <!-- <input |
|
142 |
+ type="datetime-local" |
|
143 |
+ class="full-input ml0" |
|
144 |
+ v-model="bbsCn.ntcBgngDt" |
|
145 |
+ @change="checkDateValidity('ntcBgngDt', $event)" |
|
146 |
+ /> --> |
|
147 |
+ </div> |
|
148 |
+ <div class="mark">-</div> |
|
149 |
+ <div class="form-control sm cal"> |
|
150 |
+ <VueDatePicker |
|
151 |
+ InlineOptions |
|
152 |
+ placeholder="종료일" |
|
153 |
+ locale="ko" |
|
154 |
+ :enable-time-picker="false" |
|
155 |
+ :format="formatDate" |
|
156 |
+ v-model="bbsCn.ntcEndDt" |
|
157 |
+ @update:model-value="checkDateValidity('ntcEndDt',$event)" |
|
158 |
+ /> |
|
159 |
+ <!-- <input |
|
160 |
+ type="datetime-local" |
|
161 |
+ class="full-input ml0" |
|
162 |
+ v-model="bbsCn.ntcEndDt" |
|
163 |
+ @change="checkDateValidity('ntcEndDt', $event)" |
|
164 |
+ /> --> |
|
165 |
+ </div> |
|
166 |
+ </div> |
|
167 |
+ </td> |
|
168 |
+ </tr> |
|
169 |
+ <tr v-if="bbsMng.prvtPstUseYn === 'Y'" class="border-top"> |
|
170 |
+ <th |
|
171 |
+ :class="{ |
|
172 |
+ 'text-lf': true, |
|
173 |
+ 'point-font2': pageRole == 'adm', |
|
174 |
+ 'point-font': pageRole == 'portal', |
|
175 |
+ }" |
|
176 |
+ > |
|
177 |
+ 비밀글 |
|
178 |
+ </th> |
|
179 |
+ <td colspan="3"> |
|
180 |
+ <div class="flex align-center no-gutters"> |
|
181 |
+ <div class="gd-4"> |
|
182 |
+ <input |
|
183 |
+ type="radio" |
|
184 |
+ name="private" |
|
185 |
+ id="private-y" |
|
186 |
+ class="mr5" |
|
187 |
+ value="Y" |
|
188 |
+ v-model="bbsCn.prvtPstYn" |
|
189 |
+ /> |
|
190 |
+ <label for="private-y">사용</label> |
|
191 |
+ </div> |
|
192 |
+ <div class="gd-4"> |
|
193 |
+ <input |
|
194 |
+ type="radio" |
|
195 |
+ name="private" |
|
196 |
+ id="private-n" |
|
197 |
+ class="mr5" |
|
198 |
+ value="N" |
|
199 |
+ v-model="bbsCn.prvtPstYn" |
|
200 |
+ /> |
|
201 |
+ <label for="private-n">미사용</label> |
|
202 |
+ </div> |
|
203 |
+ </div> |
|
204 |
+ </td> |
|
205 |
+ </tr> |
|
206 |
+ </tbody> |
|
207 |
+ </table> |
|
208 |
+ </div> |
|
209 |
+ </div> |
|
210 |
+ </div> |
|
250 | 211 |
</div> |
251 |
- </div> |
|
252 |
- </div> |
|
212 |
+ <div class="btn-wrap"> |
|
213 |
+ <button class="btn sm primary" @click="fnInsert">{{ bbsCn.bbsId == null ? "등록" : "수정" }}</button> |
|
214 |
+ <button class="btn sm tertiary" @click="fnCancel">취소</button> |
|
215 |
+ </div> |
|
216 |
+ </template> |
|
253 | 217 |
</template> |
254 | 218 |
|
255 | 219 |
<script> |
... | ... | @@ -551,7 +515,26 @@ |
551 | 515 |
}, |
552 | 516 |
// 공지기간 유효성 체크 |
553 | 517 |
checkDateValidity(changeDate, event) { |
554 |
- const val = event.target.value; // 변경된 날짜 값 |
|
518 |
+ // const val = event.target.value; // 변경된 날짜 값 |
|
519 |
+ let val; |
|
520 |
+ |
|
521 |
+ // 값이 Date 객체인지 확인 |
|
522 |
+ if (event instanceof Date) { |
|
523 |
+ const year = event.getFullYear(); |
|
524 |
+ const month = ('00' + (event.getMonth() + 1)).slice(-2); |
|
525 |
+ const day = ('00' + event.getDate()).slice(-2); |
|
526 |
+ |
|
527 |
+ val = `${year}-${month}-${day}`; |
|
528 |
+ } |
|
529 |
+ // 값이 Event 객체인지 확인 |
|
530 |
+ else if (event instanceof Event) { |
|
531 |
+ val = event.target.value; // input에서 직접 입력된 값 |
|
532 |
+ } |
|
533 |
+ // 그 외의 경우 처리 불필요 (예외 처리) |
|
534 |
+ else { |
|
535 |
+ console.error("Invalid date input:", event); |
|
536 |
+ return; |
|
537 |
+ } |
|
555 | 538 |
// 시작일 변경 시 |
556 | 539 |
if (changeDate === "ntcBgngDt") { |
557 | 540 |
if (this.bbsCn.ntcEndDt !== null && this.bbsCn.ntcEndDt < val) { |
--- client/views/pages/adm/boardManagement/template/commonTemplate/CommonSelectList.vue
+++ client/views/pages/adm/boardManagement/template/commonTemplate/CommonSelectList.vue
... | ... | @@ -1,104 +1,137 @@ |
1 | 1 |
<template> |
2 |
- <div |
|
3 |
- :class="{ |
|
4 |
- content: true, |
|
5 |
- '': pageRole === 'adm', |
|
6 |
- 'w1400 pt50 pb50': pageRole === 'portal', |
|
7 |
- }" |
|
8 |
- > |
|
9 |
- <div |
|
10 |
- :class="{ |
|
11 |
- 'admin-page-title point-font2 mb30': pageRole == 'adm', |
|
12 |
- 'page-title point-font mb30': |
|
13 |
- pageRole == 'portal', |
|
14 |
- }" |
|
15 |
- > |
|
16 |
- <p>{{ bbsMng.bbsNm }}</p> |
|
2 |
+ <!-- 사용자 --> |
|
3 |
+ <template v-if="pageRole === 'portal'"> |
|
4 |
+ <div class="content w1400 pt50 pb50"> |
|
5 |
+ <div class="page-title point-font mb30"> |
|
6 |
+ <p>{{ bbsMng.bbsNm }}</p> |
|
7 |
+ </div> |
|
8 |
+ <div class="search-bar mb15"> |
|
9 |
+ <div class="flex justify-end align-center no-gutters"> |
|
10 |
+ <div class="gd-4"> |
|
11 |
+ <div class="border"> |
|
12 |
+ <select |
|
13 |
+ class="border-none gd-3" |
|
14 |
+ v-model="search.searchType" |
|
15 |
+ > |
|
16 |
+ <option value="">전체</option> |
|
17 |
+ <option v-for="(item, idx) in codeList" :key="idx" :value="item.cd"> |
|
18 |
+ {{ item.cdNm }} |
|
19 |
+ </option> |
|
20 |
+ </select> |
|
21 |
+ <input |
|
22 |
+ type="text" |
|
23 |
+ class="full-input border-none gd-9 condition-input" |
|
24 |
+ placeholder="검색어를 입력하세요." |
|
25 |
+ v-model="search.searchText" |
|
26 |
+ @keyup.enter="findAll" |
|
27 |
+ /> |
|
28 |
+ </div> |
|
29 |
+ </div> |
|
30 |
+ <div class="flex gd-3"> |
|
31 |
+ <div class="gd-6 pr0"> |
|
32 |
+ <button class="large-btn green-border-btn" @click="findAll"> |
|
33 |
+ 검색 |
|
34 |
+ </button> |
|
35 |
+ </div> |
|
36 |
+ <div class="gd-6 pr0"> |
|
37 |
+ <button class="large-btn darkg-border-btn" @click="fnSearchReset"> |
|
38 |
+ <svg-icon type="mdi" :path="refreshPath"></svg-icon> 초기화 |
|
39 |
+ </button> |
|
40 |
+ </div> |
|
41 |
+ </div> |
|
42 |
+ </div> |
|
43 |
+ </div> |
|
44 |
+ <ListTable |
|
45 |
+ class="cmmn-table" |
|
46 |
+ :colgroup="colgroup" |
|
47 |
+ :thead="thead" |
|
48 |
+ :tbody="tbody" |
|
49 |
+ @listClick="fnView" |
|
50 |
+ :lockList="lockList" |
|
51 |
+ :ntcList="ntcList" |
|
52 |
+ /> |
|
53 |
+ <div class="flex justify-between align-center no-gutters"> |
|
54 |
+ <div class="gd-1"></div> |
|
55 |
+ <div class="gd-10"> |
|
56 |
+ <PaginationButton |
|
57 |
+ class="cmmn-table" |
|
58 |
+ v-model:currentPage="search.currentPage" |
|
59 |
+ :pagination="search" |
|
60 |
+ :click="findAll" |
|
61 |
+ /> |
|
62 |
+ </div> |
|
63 |
+ <div v-if="pageAuth.regAuthrt == 'Y'" class="gd-1"> |
|
64 |
+ <button class="large-btn green-btn" @click="fnAdd"> |
|
65 |
+ 등록 |
|
66 |
+ </button> |
|
67 |
+ </div> |
|
68 |
+ </div> |
|
17 | 69 |
</div> |
18 |
- <div class="search-bar mb15"> |
|
19 |
- <div class="flex justify-end align-center no-gutters"> |
|
20 |
- <div class="gd-4"> |
|
21 |
- <div class="border"> |
|
70 |
+ </template> |
|
71 |
+ |
|
72 |
+ <!-- 관리자 --> |
|
73 |
+ <template v-else> |
|
74 |
+ <div class="content-zone"> |
|
75 |
+ <div class="content"> |
|
76 |
+ <div class="scroll"> |
|
77 |
+ <div class="title-zone"> |
|
78 |
+ <div class="page-title"> |
|
79 |
+ <p>{{ bbsMng.bbsNm }}</p> |
|
80 |
+ </div> |
|
81 |
+ </div> |
|
82 |
+ <div class="search-bar"> |
|
22 | 83 |
<select |
23 |
- name="" |
|
24 |
- id="" |
|
25 |
- class="border-none gd-3" |
|
84 |
+ class="form-select sm" |
|
26 | 85 |
v-model="search.searchType" |
27 | 86 |
> |
28 | 87 |
<option value="">전체</option> |
29 |
- <option |
|
30 |
- v-for="(item, idx) in codeList" |
|
31 |
- :key="idx" |
|
32 |
- :value="item.cd" |
|
33 |
- > |
|
88 |
+ <option v-for="(item, idx) in codeList" :key="idx" :value="item.cd"> |
|
34 | 89 |
{{ item.cdNm }} |
35 | 90 |
</option> |
36 | 91 |
</select> |
37 | 92 |
<input |
38 | 93 |
type="text" |
39 |
- class="full-input border-none gd-9 condition-input" |
|
94 |
+ class="form-control sm" |
|
40 | 95 |
placeholder="검색어를 입력하세요." |
41 | 96 |
v-model="search.searchText" |
42 | 97 |
@keyup.enter="findAll" |
43 | 98 |
/> |
44 |
- </div> |
|
45 |
- </div> |
|
46 |
- <div class="flex gd-3"> |
|
47 |
- <div class="gd-6 pr0"> |
|
48 |
- <button |
|
49 |
- :class="{ |
|
50 |
- 'large-btn': true, |
|
51 |
- 'blue-border-btn': pageRole == 'adm', |
|
52 |
- 'green-border-btn': |
|
53 |
- pageRole == 'portal', |
|
54 |
- }" |
|
55 |
- @click="findAll" |
|
56 |
- > |
|
99 |
+ <button class="btn sm ico-before ico-sch" @click="findAll"> |
|
57 | 100 |
검색 |
58 | 101 |
</button> |
102 |
+ <button class="btn-ico md ico-refresh" @click="fnSearchReset"></button> |
|
59 | 103 |
</div> |
60 |
- <div class="gd-6 pr0"> |
|
61 |
- <button class="large-btn darkg-border-btn" @click="fnSearchReset"> |
|
62 |
- <svg-icon type="mdi" :path="refreshPath" ></svg-icon> 초기화 |
|
63 |
- </button> |
|
104 |
+ <div class="tbl-wrap"> |
|
105 |
+ <ListTable |
|
106 |
+ class="data cursor" |
|
107 |
+ :colgroup="colgroup" |
|
108 |
+ :thead="thead" |
|
109 |
+ :tbody="tbody" |
|
110 |
+ @listClick="fnView" |
|
111 |
+ :lockList="lockList" |
|
112 |
+ :ntcList="ntcList" |
|
113 |
+ /> |
|
64 | 114 |
</div> |
65 | 115 |
</div> |
66 | 116 |
</div> |
67 | 117 |
</div> |
68 |
- <ListTable |
|
69 |
- :className="`cmmn-table ${pageRole == 'adm' ? 'admin-list' : ''}`" |
|
70 |
- :colgroup="colgroup" |
|
71 |
- :thead="thead" |
|
72 |
- :tbody="tbody" |
|
73 |
- @listClick="fnView" |
|
74 |
- :lockList="lockList" |
|
75 |
- :ntcList="ntcList" |
|
76 |
- > |
|
77 |
- </ListTable> |
|
78 |
- <div class="flex justify-between align-center no-gutters"> |
|
79 |
- <div class="gd-1"></div> |
|
80 |
- <div class="gd-10"> |
|
81 |
- <PaginationButton |
|
82 |
- :className="pageRole === 'adm' ? 'admin-pagination' : 'cmmn-table'" |
|
83 |
- v-model:currentPage="search.currentPage" |
|
84 |
- :pagination="search" |
|
85 |
- :click="findAll" |
|
86 |
- /> |
|
87 |
- </div> |
|
88 |
- <div v-if="pageAuth.regAuthrt == 'Y'" class="gd-1"> |
|
89 |
- <button |
|
90 |
- :class="{ |
|
91 |
- 'large-btn': true, |
|
92 |
- 'blue-border-btn': pageRole == 'adm', |
|
93 |
- 'green-btn': pageRole == 'portal', |
|
94 |
- }" |
|
95 |
- @click="fnAdd" |
|
96 |
- > |
|
118 |
+ <div class="btn-wrap list"> |
|
119 |
+ <div></div> |
|
120 |
+ <PaginationButton |
|
121 |
+ class="admin-pagination" |
|
122 |
+ v-model:currentPage="search.currentPage" |
|
123 |
+ :pagination="search" |
|
124 |
+ :click="findAll" |
|
125 |
+ /> |
|
126 |
+ <template v-if="pageAuth.regAuthrt == 'Y'"> |
|
127 |
+ <button class="btn sm primary" @click="fnAdd"> |
|
97 | 128 |
등록 |
98 | 129 |
</button> |
99 |
- </div> |
|
130 |
+ </template> |
|
100 | 131 |
</div> |
101 |
- </div> |
|
132 |
+ </template> |
|
133 |
+ |
|
134 |
+ |
|
102 | 135 |
</template> |
103 | 136 |
|
104 | 137 |
<script> |
--- client/views/pages/adm/boardManagement/template/commonTemplate/CommonSelectListOne.vue
+++ client/views/pages/adm/boardManagement/template/commonTemplate/CommonSelectListOne.vue
... | ... | @@ -1,192 +1,289 @@ |
1 | 1 |
<template> |
2 |
- <div |
|
3 |
- :class="{ |
|
4 |
- content: true, |
|
5 |
- 'admin-style overflow-y': pageRole === 'adm', |
|
6 |
- 'w1400 pt50 pb50': pageRole === 'portal', |
|
7 |
- }" |
|
8 |
- > |
|
9 |
- <div |
|
10 |
- :class="{ |
|
11 |
- 'admin-page-title point-font2 mb30': pageRole == 'adm', |
|
12 |
- 'page-title point-font mb30': pageRole == 'portal', |
|
13 |
- }" |
|
14 |
- > |
|
15 |
- <p>{{ bbsMng.bbsNm }}</p> |
|
16 |
- </div> |
|
17 |
- <div> |
|
18 |
- <table |
|
19 |
- class="detail-table mb30" |
|
20 |
- :class="{ 'admin-detail': pageRole === 'adm' }" |
|
21 |
- > |
|
22 |
- <colgroup> |
|
23 |
- <col width="10%" /> |
|
24 |
- <col width="90%" /> |
|
25 |
- </colgroup> |
|
26 |
- <tbody> |
|
27 |
- <tr class="detail-title"> |
|
28 |
- <td colspan="2"> |
|
29 |
- <p |
|
30 |
- :class="{ |
|
31 |
- 'detail-table-title point-font2 mb10': pageRole == 'adm', |
|
32 |
- 'detail-table-title point-font mb10': |
|
33 |
- pageRole == 'portal', |
|
34 |
- }" |
|
35 |
- > |
|
36 |
- {{ bbsCn.bbsNm }} |
|
37 |
- </p> |
|
38 |
- <p> |
|
39 |
- <span>등록일시 | {{ bbsCn.regDt }}</span> |
|
40 |
- </p> |
|
41 |
- </td> |
|
42 |
- </tr> |
|
43 |
- <tr> |
|
44 |
- <td colspan="2" class="pd15"> |
|
45 |
- <div |
|
46 |
- class="editor5" |
|
47 |
- style="width: 100%; min-height: 35rem" |
|
48 |
- v-html="sanitizedContent" |
|
49 |
- ></div> |
|
50 |
- </td> |
|
51 |
- </tr> |
|
52 |
- <tr class="border-top"> |
|
53 |
- <td |
|
54 |
- :class="{ |
|
55 |
- 'pd15 point-font2': pageRole == 'adm', |
|
56 |
- 'pd15 point-font': pageRole == 'portal', |
|
57 |
- }" |
|
58 |
- > |
|
59 |
- 첨부파일 |
|
60 |
- </td> |
|
61 |
- <td> |
|
62 |
- <div v-if="fileList.length == 0"> |
|
63 |
- <label>첨부된 파일이 없습니다.</label> |
|
64 |
- </div> |
|
65 |
- |
|
66 |
- <ul v-else class="pd10"> |
|
67 |
- <li |
|
68 |
- v-for="(item, idx) in fileList" |
|
69 |
- :key="idx" |
|
70 |
- @click="downloadFile(item)" |
|
71 |
- class="cursor pd5 border radius mb5 flex justify-between align-center" |
|
72 |
- > |
|
73 |
- <p>{{ item.fileNm + "." + item.extnNm }}</p> |
|
74 |
- <svg-icon type="mdi" :path="downloadFilePath"></svg-icon> |
|
75 |
- </li> |
|
76 |
- </ul> |
|
77 |
- </td> |
|
78 |
- </tr> |
|
79 |
- </tbody> |
|
80 |
- </table> |
|
81 |
- <div class="flex justify-end align-center mb30"> |
|
82 |
- <div class="gd-1 pr0"> |
|
83 |
- <button class="large-btn gray-border-btn" @click="fnList"> |
|
84 |
- 목록 |
|
85 |
- </button> |
|
86 |
- </div> |
|
87 |
- <div |
|
88 |
- v-if="pageAuth.mdfcnAuthrt == 'Y' || mbrId == bbsCn.rgtr" |
|
89 |
- class="gd-1 pr0" |
|
90 |
- > |
|
91 |
- <button |
|
92 |
- :class="{ |
|
93 |
- 'large-btn': true, |
|
94 |
- 'blue-border-btn': pageRole == 'adm', |
|
95 |
- 'green-border-btn': |
|
96 |
- pageRole == 'portal', |
|
97 |
- }" |
|
98 |
- @click="fnUpdate" |
|
99 |
- > |
|
100 |
- 수정 |
|
101 |
- </button> |
|
102 |
- </div> |
|
103 |
- <div |
|
104 |
- v-if="pageAuth.delAuthrt == 'Y' || mbrId == bbsCn.rgtr" |
|
105 |
- class="gd-1 pr0" |
|
106 |
- > |
|
107 |
- <button class="large-btn red-border-btn" @click="fnDelete"> |
|
108 |
- 삭제 |
|
109 |
- </button> |
|
110 |
- </div> |
|
2 |
+ <!-- 사용자 --> |
|
3 |
+ <template v-if="pageRole === 'portal'"> |
|
4 |
+ <div class="content w1400 pt50 pb50"> |
|
5 |
+ <div class="page-title point-font mb30"> |
|
6 |
+ <p>{{ bbsMng.bbsNm }}</p> |
|
111 | 7 |
</div> |
112 |
- <table v-if="bbsMng.bfrAftrPstUseYn == 'Y'" class="content-navigate mb30"> |
|
113 |
- <colgroup> |
|
114 |
- <col width="10%" /> |
|
115 |
- <col width="90%" /> |
|
116 |
- </colgroup> |
|
117 |
- <tbody> |
|
118 |
- <tr> |
|
119 |
- <td class="pd10 text-ct">이전글</td> |
|
120 |
- <td |
|
121 |
- v-if="prevBbsCn != null" |
|
122 |
- class="pd10 cursor" |
|
123 |
- @click="fnMoveBbsCn(prevBbsCn.bbsId)" |
|
124 |
- > |
|
125 |
- {{ prevBbsCn.bbsNm }} |
|
126 |
- </td> |
|
127 |
- <td v-else class="pd10">이전글이 없습니다</td> |
|
128 |
- </tr> |
|
129 |
- <tr> |
|
130 |
- <td class="pd10 text-ct">다음글</td> |
|
131 |
- <td |
|
132 |
- v-if="nextBbsCn != null" |
|
133 |
- class="pd10 cursor" |
|
134 |
- @click="fnMoveBbsCn(nextBbsCn.bbsId)" |
|
135 |
- > |
|
136 |
- {{ nextBbsCn.bbsNm }} |
|
137 |
- </td> |
|
138 |
- <td v-else class="pd10">다음글이 없습니다</td> |
|
139 |
- </tr> |
|
140 |
- </tbody> |
|
141 |
- </table> |
|
142 |
- <div |
|
143 |
- v-if="bbsMng.cmntUseYn == 'Y'" |
|
144 |
- :class="{ |
|
145 |
- pd30: true, |
|
146 |
- 'comment-zone': pageRole == 'adm', |
|
147 |
- 'comment-zone2': pageRole == 'portal', |
|
148 |
- }" |
|
149 |
- > |
|
150 |
- <div class="flex justify-start align-start mb30"> |
|
151 |
- <div class="gd-10 pl0"> |
|
152 |
- <textarea |
|
153 |
- name="InputCmnt" |
|
154 |
- id="InputCmnt" |
|
155 |
- style="width: 100%; min-height: 4rem" |
|
156 |
- v-model="InputCmnt" |
|
157 |
- ></textarea> |
|
158 |
- </div> |
|
159 |
- <div class="gd-2 pr0"> |
|
160 |
- <button |
|
161 |
- :class="{ |
|
162 |
- 'large-btn comment-btn radius': true, |
|
163 |
- 'blue-btn': pageRole == 'adm', |
|
164 |
- 'green-btn': pageRole == 'portal', |
|
165 |
- }" |
|
166 |
- @click="fnInsertCmnt" |
|
167 |
- > |
|
168 |
- 등록 |
|
8 |
+ <div> |
|
9 |
+ <div class="tbl-wrap"> |
|
10 |
+ <table class="tbl data"> |
|
11 |
+ <colgroup> |
|
12 |
+ <col width="10%" /> |
|
13 |
+ <col width="90%" /> |
|
14 |
+ </colgroup> |
|
15 |
+ <tbody> |
|
16 |
+ <tr class="detail-title"> |
|
17 |
+ <td colspan="2"> |
|
18 |
+ <p class="detail-table-title point-font mb10"> |
|
19 |
+ {{ bbsCn.bbsNm }} |
|
20 |
+ </p> |
|
21 |
+ <p> |
|
22 |
+ <span>등록일시 | {{ bbsCn.regDt }}</span> |
|
23 |
+ </p> |
|
24 |
+ </td> |
|
25 |
+ </tr> |
|
26 |
+ <tr> |
|
27 |
+ <td colspan="2"> |
|
28 |
+ <div |
|
29 |
+ class="editor5" |
|
30 |
+ style="width: 100%; min-height: 35rem" |
|
31 |
+ v-html="sanitizedContent" |
|
32 |
+ ></div> |
|
33 |
+ </td> |
|
34 |
+ </tr> |
|
35 |
+ <tr> |
|
36 |
+ <td>첨부파일</td> |
|
37 |
+ <td> |
|
38 |
+ <div v-if="fileList.length == 0"> |
|
39 |
+ <label>첨부된 파일이 없습니다.</label> |
|
40 |
+ </div> |
|
41 |
+ |
|
42 |
+ <ul v-else> |
|
43 |
+ <li |
|
44 |
+ v-for="(item, idx) in fileList" |
|
45 |
+ :key="idx" |
|
46 |
+ @click="downloadFile(item)" |
|
47 |
+ class="cursor pd5 border radius mb5 flex justify-between align-center" |
|
48 |
+ > |
|
49 |
+ <p>{{ item.fileNm + "." + item.extnNm }}</p> |
|
50 |
+ <svg-icon type="mdi" :path="downloadFilePath"></svg-icon> |
|
51 |
+ </li> |
|
52 |
+ </ul> |
|
53 |
+ </td> |
|
54 |
+ </tr> |
|
55 |
+ </tbody> |
|
56 |
+ </table> |
|
57 |
+ </div> |
|
58 |
+ <div class="flex justify-end align-center mb30"> |
|
59 |
+ <div class="gd-1 pr0"> |
|
60 |
+ <button class="large-btn gray-border-btn" @click="fnList"> |
|
61 |
+ 목록 |
|
169 | 62 |
</button> |
170 | 63 |
</div> |
171 | 64 |
</div> |
172 |
- <div class="comment-wrap"> |
|
173 |
- <template v-if="cmntList.length > 0"> |
|
174 |
- <CommentItem |
|
175 |
- :comments="cmntList" |
|
176 |
- :pageAuth="pageAuth" |
|
177 |
- :pageId="pageId" |
|
178 |
- @isReply="isReply" |
|
179 |
- /> |
|
180 |
- </template> |
|
181 |
- <template v-else> |
|
182 |
- <p class="comment-text text-ct data-none"> |
|
183 |
- 등록된 댓글이 없습니다. |
|
184 |
- </p> |
|
185 |
- </template> |
|
65 |
+ <table v-if="bbsMng.bfrAftrPstUseYn == 'Y'" class="content-navigate mb30"> |
|
66 |
+ <colgroup> |
|
67 |
+ <col width="10%" /> |
|
68 |
+ <col width="90%" /> |
|
69 |
+ </colgroup> |
|
70 |
+ <tbody> |
|
71 |
+ <tr> |
|
72 |
+ <td class="pd10 text-ct">이전글</td> |
|
73 |
+ <td |
|
74 |
+ v-if="prevBbsCn != null" |
|
75 |
+ class="pd10 cursor" |
|
76 |
+ @click="fnMoveBbsCn(prevBbsCn.bbsId)" |
|
77 |
+ > |
|
78 |
+ {{ prevBbsCn.bbsNm }} |
|
79 |
+ </td> |
|
80 |
+ <td v-else class="pd10">이전글이 없습니다</td> |
|
81 |
+ </tr> |
|
82 |
+ <tr> |
|
83 |
+ <td class="pd10 text-ct">다음글</td> |
|
84 |
+ <td |
|
85 |
+ v-if="nextBbsCn != null" |
|
86 |
+ class="pd10 cursor" |
|
87 |
+ @click="fnMoveBbsCn(nextBbsCn.bbsId)" |
|
88 |
+ > |
|
89 |
+ {{ nextBbsCn.bbsNm }} |
|
90 |
+ </td> |
|
91 |
+ <td v-else class="pd10">다음글이 없습니다</td> |
|
92 |
+ </tr> |
|
93 |
+ </tbody> |
|
94 |
+ </table> |
|
95 |
+ <div |
|
96 |
+ v-if="bbsMng.cmntUseYn == 'Y'" |
|
97 |
+ :class="{ |
|
98 |
+ pd30: true, |
|
99 |
+ 'comment-zone': pageRole == 'adm', |
|
100 |
+ 'comment-zone2': pageRole == 'portal', |
|
101 |
+ }" |
|
102 |
+ > |
|
103 |
+ <div class="flex justify-start align-start mb30"> |
|
104 |
+ <div class="gd-10 pl0"> |
|
105 |
+ <textarea |
|
106 |
+ name="InputCmnt" |
|
107 |
+ id="InputCmnt" |
|
108 |
+ style="width: 100%; min-height: 4rem" |
|
109 |
+ v-model="InputCmnt" |
|
110 |
+ ></textarea> |
|
111 |
+ </div> |
|
112 |
+ <div class="gd-2 pr0"> |
|
113 |
+ <button |
|
114 |
+ :class="{ |
|
115 |
+ 'large-btn comment-btn radius': true, |
|
116 |
+ 'blue-btn': pageRole == 'adm', |
|
117 |
+ 'green-btn': pageRole == 'portal', |
|
118 |
+ }" |
|
119 |
+ @click="fnInsertCmnt" |
|
120 |
+ > |
|
121 |
+ 등록 |
|
122 |
+ </button> |
|
123 |
+ </div> |
|
124 |
+ </div> |
|
125 |
+ <div class="comment-wrap"> |
|
126 |
+ <template v-if="cmntList.length > 0"> |
|
127 |
+ <CommentItem |
|
128 |
+ :comments="cmntList" |
|
129 |
+ :pageAuth="pageAuth" |
|
130 |
+ :pageId="pageId" |
|
131 |
+ @isReply="isReply" |
|
132 |
+ /> |
|
133 |
+ </template> |
|
134 |
+ <template v-else> |
|
135 |
+ <p class="comment-text text-ct data-none"> |
|
136 |
+ 등록된 댓글이 없습니다. |
|
137 |
+ </p> |
|
138 |
+ </template> |
|
139 |
+ </div> |
|
186 | 140 |
</div> |
187 | 141 |
</div> |
188 | 142 |
</div> |
189 |
- </div> |
|
143 |
+ </template> |
|
144 |
+ <!-- 관리자 --> |
|
145 |
+ <template v-else> |
|
146 |
+ <div class="content-zone"> |
|
147 |
+ <div class="content"> |
|
148 |
+ <div class="scroll"> |
|
149 |
+ <div class="title-zone"> |
|
150 |
+ <div class="page-title"> |
|
151 |
+ <p>{{ bbsMng.bbsNm }}</p> |
|
152 |
+ </div> |
|
153 |
+ </div> |
|
154 |
+ <div class="tbl-wrap"> |
|
155 |
+ <table class="tbl data"> |
|
156 |
+ <colgroup> |
|
157 |
+ <col width="10%" /> |
|
158 |
+ <col width="90%" /> |
|
159 |
+ </colgroup> |
|
160 |
+ <tbody> |
|
161 |
+ <tr class="detail-title"> |
|
162 |
+ <td colspan="2"> |
|
163 |
+ <p>{{ bbsCn.bbsNm }}</p> |
|
164 |
+ <p><span>등록일시 | {{ bbsCn.regDt }}</span></p> |
|
165 |
+ </td> |
|
166 |
+ </tr> |
|
167 |
+ <tr> |
|
168 |
+ <td colspan="2"> |
|
169 |
+ <div |
|
170 |
+ class="editor5" |
|
171 |
+ style="width: 100%; min-height: 35rem" |
|
172 |
+ v-html="sanitizedContent" |
|
173 |
+ ></div> |
|
174 |
+ </td> |
|
175 |
+ </tr> |
|
176 |
+ <tr> |
|
177 |
+ <td colspan="2"> |
|
178 |
+ <div v-if="fileList.length == 0"> |
|
179 |
+ <label>첨부된 파일이 없습니다.</label> |
|
180 |
+ </div> |
|
181 |
+ |
|
182 |
+ <ul v-else class="pd10"> |
|
183 |
+ <li |
|
184 |
+ v-for="(item, idx) in fileList" |
|
185 |
+ :key="idx" |
|
186 |
+ @click="downloadFile(item)"> |
|
187 |
+ <p>{{ item.fileNm + "." + item.extnNm }}</p> |
|
188 |
+ <svg-icon type="mdi" :path="downloadFilePath"></svg-icon> |
|
189 |
+ </li> |
|
190 |
+ </ul> |
|
191 |
+ </td> |
|
192 |
+ </tr> |
|
193 |
+ </tbody> |
|
194 |
+ </table> |
|
195 |
+ <table v-if="bbsMng.bfrAftrPstUseYn == 'Y'" class="content-navigate"> |
|
196 |
+ <colgroup> |
|
197 |
+ <col width="10%" /> |
|
198 |
+ <col width="90%" /> |
|
199 |
+ </colgroup> |
|
200 |
+ <tbody> |
|
201 |
+ <tr> |
|
202 |
+ <td class="pd10 text-ct">이전글</td> |
|
203 |
+ <td |
|
204 |
+ v-if="prevBbsCn != null" |
|
205 |
+ class="pd10 cursor" |
|
206 |
+ @click="fnMoveBbsCn(prevBbsCn.bbsId)" |
|
207 |
+ > |
|
208 |
+ {{ prevBbsCn.bbsNm }} |
|
209 |
+ </td> |
|
210 |
+ <td v-else class="pd10">이전글이 없습니다</td> |
|
211 |
+ </tr> |
|
212 |
+ <tr> |
|
213 |
+ <td class="pd10 text-ct">다음글</td> |
|
214 |
+ <td |
|
215 |
+ v-if="nextBbsCn != null" |
|
216 |
+ class="pd10 cursor" |
|
217 |
+ @click="fnMoveBbsCn(nextBbsCn.bbsId)" |
|
218 |
+ > |
|
219 |
+ {{ nextBbsCn.bbsNm }} |
|
220 |
+ </td> |
|
221 |
+ <td v-else class="pd10">다음글이 없습니다</td> |
|
222 |
+ </tr> |
|
223 |
+ </tbody> |
|
224 |
+ </table> |
|
225 |
+ <div |
|
226 |
+ v-if="bbsMng.cmntUseYn == 'Y'" |
|
227 |
+ :class="{ |
|
228 |
+ pd30: true, |
|
229 |
+ 'comment-zone': pageRole == 'adm', |
|
230 |
+ 'comment-zone2': pageRole == 'portal', |
|
231 |
+ }" |
|
232 |
+ > |
|
233 |
+ <div class="flex justify-start align-start mb30"> |
|
234 |
+ <div class="gd-10 pl0"> |
|
235 |
+ <textarea |
|
236 |
+ name="InputCmnt" |
|
237 |
+ id="InputCmnt" |
|
238 |
+ style="width: 100%; min-height: 4rem" |
|
239 |
+ v-model="InputCmnt" |
|
240 |
+ ></textarea> |
|
241 |
+ </div> |
|
242 |
+ <div class="gd-2 pr0"> |
|
243 |
+ <button |
|
244 |
+ :class="{ |
|
245 |
+ 'large-btn comment-btn radius': true, |
|
246 |
+ 'blue-btn': pageRole == 'adm', |
|
247 |
+ 'green-btn': pageRole == 'portal', |
|
248 |
+ }" |
|
249 |
+ @click="fnInsertCmnt" |
|
250 |
+ > |
|
251 |
+ 등록 |
|
252 |
+ </button> |
|
253 |
+ </div> |
|
254 |
+ </div> |
|
255 |
+ <div class="comment-wrap"> |
|
256 |
+ <template v-if="cmntList.length > 0"> |
|
257 |
+ <CommentItem |
|
258 |
+ :comments="cmntList" |
|
259 |
+ :pageAuth="pageAuth" |
|
260 |
+ :pageId="pageId" |
|
261 |
+ @isReply="isReply" |
|
262 |
+ /> |
|
263 |
+ </template> |
|
264 |
+ <template v-else> |
|
265 |
+ <p class="comment-text text-ct data-none"> |
|
266 |
+ 등록된 댓글이 없습니다. |
|
267 |
+ </p> |
|
268 |
+ </template> |
|
269 |
+ </div> |
|
270 |
+ </div> |
|
271 |
+ </div> |
|
272 |
+ </div> |
|
273 |
+ </div> |
|
274 |
+ </div> |
|
275 |
+ <div class="btn-wrap"> |
|
276 |
+ <button class="btn sm tertiary" @click="fnList"> |
|
277 |
+ 목록 |
|
278 |
+ </button> |
|
279 |
+ <template v-if="pageAuth.mdfcnAuthrt == 'Y' || mbrId == bbsCn.rgtr"> |
|
280 |
+ <button class="btn sm primary" @click="fnUpdate">수정</button> |
|
281 |
+ </template> |
|
282 |
+ <template v-if="pageAuth.delAuthrt == 'Y' || mbrId == bbsCn.rgtr"> |
|
283 |
+ <button class="btn sm red" @click="fnDelete">삭제</button> |
|
284 |
+ </template> |
|
285 |
+ </div> |
|
286 |
+ </template> |
|
190 | 287 |
</template> |
191 | 288 |
|
192 | 289 |
<script> |
--- client/views/pages/adm/boardManagement/template/galleryTemplate/GallerySelectList.vue
+++ client/views/pages/adm/boardManagement/template/galleryTemplate/GallerySelectList.vue
... | ... | @@ -1,82 +1,115 @@ |
1 | 1 |
<template> |
2 |
- <div :class="{ |
|
3 |
- 'content gall-template': true, |
|
4 |
- '': pageRole === 'adm', |
|
5 |
- 'w1400 pt50 pb50': pageRole === 'portal' |
|
6 |
- }"> |
|
7 |
- <div :class="{ |
|
8 |
- 'admin-page-title point-font2 mb30': pageRole == 'adm', |
|
9 |
- 'page-title point-font mb30': pageRole == 'portal', |
|
10 |
- }"> |
|
11 |
- <p>{{ bbsMng.bbsNm }}</p> |
|
12 |
- </div> |
|
13 |
- <div class="search-bar mb15"> |
|
14 |
- <div class="flex justify-end align-center no-gutters"> |
|
15 |
- <div class="gd-4"> |
|
16 |
- <div class="border"> |
|
17 |
- <select name="" id="" class="border-none gd-3" v-model="search.searchType"> |
|
18 |
- <option value="">전체</option> |
|
19 |
- <option v-for="(item, idx) in codeList" :key="idx" :value="item.cd">{{ item.cdNm }}</option> |
|
20 |
- </select> |
|
21 |
- <input type="text" class="full-input border-none gd-9 condition-input" |
|
22 |
- placeholder="검색어를 입력하세요." v-model="search.searchText" @keyup.enter="findAll"> |
|
23 |
- </div> |
|
24 |
- </div> |
|
25 |
- <div class="flex gd-3"> |
|
26 |
- <div class="gd-6 pr0"> |
|
27 |
- <button :class="{ |
|
28 |
- 'large-btn': true, |
|
29 |
- 'blue-border-btn': pageRole == 'adm', |
|
30 |
- 'green-border-btn': pageRole == 'portal', |
|
31 |
- }" @click="findAll">검색</button> |
|
32 |
- </div> |
|
33 |
- <div class="gd-6 pr0"> |
|
34 |
- <button class="large-btn darkg-border-btn" @click="fnSearchReset"><svg-icon type="mdi" :path="refreshPath"></svg-icon> 초기화</button> |
|
35 |
- </div> |
|
36 |
- </div> |
|
2 |
+ <!-- 사용자 --> |
|
3 |
+ <template v-if="pageRole === 'portal'"> |
|
4 |
+ <div> |
|
5 |
+ <div> |
|
6 |
+ <p>{{ bbsMng.bbsNm }}</p> |
|
37 | 7 |
</div> |
38 |
- </div> |
|
39 |
- <div class="gall-content flex justify-start align-center"> |
|
40 |
- <div v-for="(item, idx) in list" :key="idx" @click="fnView(idx)" class="gd-3 pt10 pb10 cursor gall-item"> |
|
41 |
- <div class="gall-img mb20"> |
|
42 |
- <img :src="item.absltPath" class="inline-block" /> |
|
43 |
- </div> |
|
44 |
- <div class="gall-title mb10"> |
|
45 |
- <p class="detail-bold"> |
|
46 |
- <svg-icon type="mdi" :path="pinPath" :width="20" :height="20" v-if="item.nowNtcYn == 'Y'"></svg-icon> |
|
47 |
- <svg-icon type="mdi" :path="lockPath" :width="20" :height="20" |
|
48 |
- v-else-if="item.prvtPstYn == 'Y'"></svg-icon> |
|
49 |
- <template v-if="item.prvtPstYn == 'Y'"> |
|
50 |
- {{ item.rgtr == mbrId || roles == 'ROLE_ADMIN' ? item.bbsNm : '비밀글입니다' }} |
|
51 |
- </template> |
|
52 |
- <template v-else> |
|
53 |
- {{ item.bbsNm }} |
|
54 |
- </template> |
|
55 |
- </p> |
|
56 |
- </div> |
|
57 |
- <div class="gall-info"> |
|
58 |
- <div class="flex justify-end align-center"> |
|
8 |
+ <div class="search-bar"> |
|
9 |
+ <select name="" id="" class="border-none gd-3" v-model="search.searchType"> |
|
10 |
+ <option value="">전체</option> |
|
11 |
+ <option v-for="(item, idx) in codeList" :key="idx" :value="item.cd">{{ item.cdNm }}</option> |
|
12 |
+ </select> |
|
13 |
+ <input type="text" class="full-input border-none gd-9 condition-input" |
|
14 |
+ placeholder="검색어를 입력하세요." v-model="search.searchText" @keyup.enter="findAll"> |
|
15 |
+ |
|
16 |
+ |
|
17 |
+ <button @click="findAll">검색</button> |
|
18 |
+ |
|
19 |
+ <!-- <button class="large-btn darkg-border-btn" @click="fnSearchReset"><svg-icon type="mdi" :path="refreshPath"></svg-icon> 초기화</button> --> |
|
20 |
+ </div> |
|
21 |
+ <div class="gall-content"> |
|
22 |
+ <div v-for="(item, idx) in list" :key="idx" @click="fnView(idx)" class="gall-item"> |
|
23 |
+ <div class="gall-img"> |
|
24 |
+ <img :src="item.absltPath" /> |
|
25 |
+ </div> |
|
26 |
+ <div class="gall-title"> |
|
27 |
+ <p class="detail-bold"> |
|
28 |
+ <svg-icon type="mdi" :path="pinPath" :width="20" :height="20" v-if="item.nowNtcYn == 'Y'"></svg-icon> |
|
29 |
+ <svg-icon type="mdi" :path="lockPath" :width="20" :height="20" |
|
30 |
+ v-else-if="item.prvtPstYn == 'Y'"></svg-icon> |
|
31 |
+ <template v-if="item.prvtPstYn == 'Y'"> |
|
32 |
+ {{ item.rgtr == mbrId || roles == 'ROLE_ADMIN' ? item.bbsNm : '비밀글입니다' }} |
|
33 |
+ </template> |
|
34 |
+ <template v-else> |
|
35 |
+ {{ item.bbsNm }} |
|
36 |
+ </template> |
|
37 |
+ </p> |
|
38 |
+ </div> |
|
39 |
+ <div class="gall-info"> |
|
59 | 40 |
<p class="pl5 pr5 border-r date-text">{{ item.rgtrNm }}</p> |
60 | 41 |
<p class="pl5 date-text">{{ item.regDt }}</p> |
61 | 42 |
</div> |
62 | 43 |
</div> |
63 | 44 |
</div> |
45 |
+ <!-- <div class="btn-wrap list"> |
|
46 |
+ <div class="gd-1"></div> |
|
47 |
+ <PaginationButton :className="'pagination'" v-model:currentPage="search.currentPage" |
|
48 |
+ :pagination='search' :click="findAll" /> |
|
49 |
+ <template v-if="pageAuth.regAuthrt == 'Y'" > |
|
50 |
+ <button class="btn sm primary" @click="fnAdd">등록</button> |
|
51 |
+ </template> |
|
52 |
+ </div> --> |
|
64 | 53 |
</div> |
65 |
- <div class="flex justify-between align-center no-gutters"> |
|
54 |
+ </template> |
|
55 |
+ <template v-else> |
|
56 |
+ <div class="content-zone"> |
|
57 |
+ <div class="content"> |
|
58 |
+ <div class="scroll"> |
|
59 |
+ <div class="title-zone"> |
|
60 |
+ <div class="page-title"> |
|
61 |
+ <p>{{ bbsMng.bbsNm }}</p> |
|
62 |
+ </div> |
|
63 |
+ </div> |
|
64 |
+ <div class="search-bar"> |
|
65 |
+ <select name="" id="" class="form-select sm" v-model="search.searchType"> |
|
66 |
+ <option value="">전체</option> |
|
67 |
+ <option v-for="(item, idx) in codeList" :key="idx" :value="item.cd">{{ item.cdNm }}</option> |
|
68 |
+ </select> |
|
69 |
+ <input type="text" class="form-control sm" |
|
70 |
+ placeholder="검색어를 입력하세요." v-model="search.searchText" @keyup.enter="findAll"> |
|
71 |
+ |
|
72 |
+ |
|
73 |
+ <button @click="findAll">검색</button> |
|
74 |
+ |
|
75 |
+ <!-- <button class="large-btn darkg-border-btn" @click="fnSearchReset"><svg-icon type="mdi" :path="refreshPath"></svg-icon> 초기화</button> --> |
|
76 |
+ </div> |
|
77 |
+ <div class="gall-content"> |
|
78 |
+ <div v-for="(item, idx) in list" :key="idx" @click="fnView(idx)" class="gall-item"> |
|
79 |
+ <div class="gall-img"> |
|
80 |
+ <img :src="item.absltPath" /> |
|
81 |
+ </div> |
|
82 |
+ <div class="gall-title"> |
|
83 |
+ <p class="detail-bold"> |
|
84 |
+ <svg-icon type="mdi" :path="pinPath" :width="20" :height="20" v-if="item.nowNtcYn == 'Y'"></svg-icon> |
|
85 |
+ <svg-icon type="mdi" :path="lockPath" :width="20" :height="20" |
|
86 |
+ v-else-if="item.prvtPstYn == 'Y'"></svg-icon> |
|
87 |
+ <template v-if="item.prvtPstYn == 'Y'"> |
|
88 |
+ {{ item.rgtr == mbrId || roles == 'ROLE_ADMIN' ? item.bbsNm : '비밀글입니다' }} |
|
89 |
+ </template> |
|
90 |
+ <template v-else> |
|
91 |
+ {{ item.bbsNm }} |
|
92 |
+ </template> |
|
93 |
+ </p> |
|
94 |
+ </div> |
|
95 |
+ <div class="gall-info"> |
|
96 |
+ <p class="pl5 pr5 border-r date-text">{{ item.rgtrNm }}</p> |
|
97 |
+ <p class="pl5 date-text">{{ item.regDt }}</p> |
|
98 |
+ </div> |
|
99 |
+ </div> |
|
100 |
+ </div> |
|
101 |
+ </div> |
|
102 |
+ </div> |
|
103 |
+ </div> |
|
104 |
+ <div class="btn-wrap list"> |
|
66 | 105 |
<div class="gd-1"></div> |
67 |
- <div class="gd-10"> |
|
68 |
- <PaginationButton :className="pageRole === 'adm' ? 'admin-pagination':''" v-model:currentPage="search.currentPage" |
|
106 |
+ <PaginationButton :className="'pagination'" v-model:currentPage="search.currentPage" |
|
69 | 107 |
:pagination='search' :click="findAll" /> |
70 |
- </div> |
|
71 |
- <div v-if="pageAuth.regAuthrt == 'Y'" class="gd-1"> |
|
72 |
- <button :class="{ |
|
73 |
- 'large-btn': true, |
|
74 |
- 'blue-border-btn': pageRole == 'adm', |
|
75 |
- 'green-btn': pageRole == 'portal' , |
|
76 |
- }" @click="fnAdd">등록</button> |
|
77 |
- </div> |
|
108 |
+ <template v-if="pageAuth.regAuthrt == 'Y'" > |
|
109 |
+ <button class="btn sm primary" @click="fnAdd">등록</button> |
|
110 |
+ </template> |
|
78 | 111 |
</div> |
79 |
- </div> |
|
112 |
+ </template> |
|
80 | 113 |
</template> |
81 | 114 |
|
82 | 115 |
<script> |
--- client/views/pages/adm/preferences/commonCodeManagement/CommonCodeManagement.vue
+++ client/views/pages/adm/preferences/commonCodeManagement/CommonCodeManagement.vue
... | ... | @@ -59,7 +59,7 @@ |
59 | 59 |
<label for="" class="form-title">코드값</label> |
60 | 60 |
<input type="text" class="form-control sm" :disabled="isFormDisabled" v-model="viewCode.cdVl" /> |
61 | 61 |
</div> |
62 |
- <div> |
|
62 |
+ <div class="border-bottom"> |
|
63 | 63 |
<label for="" class="form-title">사용여부</label> |
64 | 64 |
<div class="check-area"> |
65 | 65 |
<div class="form-check"> |
... | ... | @@ -74,7 +74,7 @@ |
74 | 74 |
</div> |
75 | 75 |
</div> |
76 | 76 |
</div> |
77 |
- <div> |
|
77 |
+ <div class="grid-column"> |
|
78 | 78 |
<label for="textarea" class="form-title">코드설명</label> |
79 | 79 |
<textarea class="form-control" id="textarea" :disabled="isFormDisabled" v-model="viewCode.cdExpln"></textarea> |
80 | 80 |
</div> |
--- client/views/pages/adm/statistics/BbsStatistics.vue
+++ client/views/pages/adm/statistics/BbsStatistics.vue
... | ... | @@ -6,7 +6,6 @@ |
6 | 6 |
<div class="page-title"> |
7 | 7 |
<p>게시판 접속 통계</p> |
8 | 8 |
</div> |
9 |
- |
|
10 | 9 |
</div> |
11 | 10 |
<div class="search-bar mb30"> |
12 | 11 |
<div class="form-control sm cal"> |
--- client/views/pages/adm/system/networkAccessControl/NetworkAccessControlInsert.vue
+++ client/views/pages/adm/system/networkAccessControl/NetworkAccessControlInsert.vue
... | ... | @@ -23,7 +23,7 @@ |
23 | 23 |
</option> |
24 | 24 |
</select> |
25 | 25 |
</div> |
26 |
- <div> |
|
26 |
+ <div class="border-bottom"> |
|
27 | 27 |
<label for="" class="form-title"><span>*</span> 제어 IP</label> |
28 | 28 |
<div class="form-group"> |
29 | 29 |
<input type="text" class="form-control sm" v-model="accesCtrl.cntrlIp" placeholder="1~255 범위의 숫자로 구성하여 형식에 맞게 작성해주세요." /> |
--- client/views/pages/adm/system/networkAccessControl/NetworkAccessControlSelectListOne.vue
+++ client/views/pages/adm/system/networkAccessControl/NetworkAccessControlSelectListOne.vue
... | ... | @@ -17,7 +17,7 @@ |
17 | 17 |
<p class="form-title">제어유형</p> |
18 | 18 |
<p>{{ accesCtrl.cntrlTypeNm }}</p> |
19 | 19 |
</div> |
20 |
- <div> |
|
20 |
+ <div class="border-bottom"> |
|
21 | 21 |
<p class="form-title">제어 IP</p> |
22 | 22 |
<p>{{ accesCtrl.cntrlIp }}</p> |
23 | 23 |
</div> |
--- client/theme/tema_v1/css/component.css
+++ client/views/theme/tema_v1/css/component.css
No changes |
--- client/theme/tema_v1/css/main.css
+++ client/views/theme/tema_v1/css/main.css
No changes |
--- client/theme/tema_v1/css/style.css
+++ client/views/theme/tema_v1/css/style.css
No changes |
--- client/theme/tema_v1/img/A00.svg
+++ client/views/theme/tema_v1/img/A00.svg
No changes |
--- client/theme/tema_v1/img/next.svg
+++ client/views/theme/tema_v1/img/next.svg
No changes |
--- client/theme/tema_v1/img/play.svg
+++ client/views/theme/tema_v1/img/play.svg
No changes |
--- client/theme/tema_v1/img/prev.svg
+++ client/views/theme/tema_v1/img/prev.svg
No changes |
--- client/theme/tema_v1/img/stop.svg
+++ client/views/theme/tema_v1/img/stop.svg
No changes |
--- client/theme/tema_v2/css/component.css
+++ client/views/theme/tema_v2/css/component.css
No changes |
--- client/theme/tema_v2/css/main.css
+++ client/views/theme/tema_v2/css/main.css
No changes |
--- client/theme/tema_v2/css/style.css
+++ client/views/theme/tema_v2/css/style.css
No changes |
--- client/theme/tema_v2/img/A00.svg
+++ client/views/theme/tema_v2/img/A00.svg
No changes |
--- client/theme/tema_v2/img/btn_bullet_white.png
+++ client/views/theme/tema_v2/img/btn_bullet_white.png
Binary file is not shown |
--- client/theme/tema_v2/img/btn_list_bullet.png
+++ client/views/theme/tema_v2/img/btn_list_bullet.png
Binary file is not shown |
--- client/theme/tema_v2/img/circle_arrow.png
+++ client/views/theme/tema_v2/img/circle_arrow.png
Binary file is not shown |
--- client/theme/tema_v2/img/img1.png
+++ client/views/theme/tema_v2/img/img1.png
Binary file is not shown |
--- client/theme/tema_v2/img/img_service_05.png
+++ client/views/theme/tema_v2/img/img_service_05.png
Binary file is not shown |
--- client/theme/tema_v2/img/next.svg
+++ client/views/theme/tema_v2/img/next.svg
No changes |
--- client/theme/tema_v2/img/play.svg
+++ client/views/theme/tema_v2/img/play.svg
No changes |
--- client/theme/tema_v2/img/prev.svg
+++ client/views/theme/tema_v2/img/prev.svg
No changes |
--- client/theme/tema_v2/img/stop.svg
+++ client/views/theme/tema_v2/img/stop.svg
No changes |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?