
--- client/views/component/DepartmentTree.vue
+++ client/views/component/DepartmentTree.vue
... | ... | @@ -1,64 +1,38 @@ |
1 | 1 |
<template> |
2 |
- <li class="cursor"> |
|
3 |
- <div |
|
4 |
- :class="{ |
|
2 |
+ <ul class="tree-wrap"> |
|
3 |
+ <li class="cursor" v-for="(item, idx) of treeList" :key="idx"> |
|
4 |
+ <div :class="{ |
|
5 | 5 |
'tree-container flex align-center': true, |
6 |
- selected: node.dept_code === selectedId, |
|
7 |
- }" |
|
8 |
- @click="handleClick" |
|
9 |
- > |
|
10 |
- <p> |
|
11 |
- <svg-icon |
|
12 |
- type="mdi" |
|
13 |
- :width="18" |
|
14 |
- :height="18" |
|
15 |
- :path="arrowPath" |
|
16 |
- ></svg-icon> |
|
17 |
- </p> |
|
18 |
- <p> |
|
19 |
- <svg-icon |
|
20 |
- type="mdi" |
|
21 |
- :width="18" |
|
22 |
- :height="18" |
|
23 |
- :path="notePath" |
|
24 |
- :color="'#fbbe28'" |
|
25 |
- ></svg-icon> |
|
26 |
- </p> |
|
27 |
- <p class="node-text">{{ node.dept_nm }}</p> |
|
28 |
- </div> |
|
29 |
- <ul |
|
30 |
- v-if="node.children && node.children.length > 0" |
|
31 |
- class="children-node" |
|
32 |
- :style="{ height: toggleSelect === node.dept_code ? 'auto' : '0' }" |
|
33 |
- > |
|
34 |
- <DepartmentTree |
|
35 |
- v-for="(child, index) in node.children" |
|
36 |
- :node="child" |
|
37 |
- :key="index" |
|
38 |
- @selectedNode="parentSelectedNode" |
|
39 |
- /> |
|
40 |
- </ul> |
|
41 |
- </li> |
|
6 |
+ selected: node.id === selectedId, |
|
7 |
+ }" @click="handleClick"> |
|
8 |
+ <p> |
|
9 |
+ <svg-icon type="mdi" :width="18" :height="18" :path="arrowPath"></svg-icon> |
|
10 |
+ </p> |
|
11 |
+ <p> |
|
12 |
+ <svg-icon type="mdi" :width="18" :height="18" :path="notePath" :color="'#fbbe28'"></svg-icon> |
|
13 |
+ </p> |
|
14 |
+ <p class="node-text">{{ node.nm }}</p> |
|
15 |
+ </div> |
|
16 |
+ <ul v-if="node.childList && node.childList.length > 0" class="children-node" :style="{ height: toggleSelect === node.id ? 'auto' : '0' }"> |
|
17 |
+ <DepartmentTree v-for="(item, idx) in node.childList" :node="item" :key="idx" @selectedNode="parentSelectedNode" /> |
|
18 |
+ </ul> |
|
19 |
+ </li> |
|
20 |
+ </ul> |
|
42 | 21 |
</template> |
43 |
- |
|
44 | 22 |
<script> |
45 |
-import axios from "axios"; |
|
46 | 23 |
import SvgIcon from "@jamescoyle/vue-icon"; |
47 |
-import { |
|
48 |
- mdiNote, |
|
49 |
- mdiChevronRight, |
|
50 |
- mdiChevronDown, |
|
51 |
- mdiNoteOutline, |
|
52 |
-} from "@mdi/js"; |
|
24 |
+import { mdiNote, mdiChevronRight, mdiChevronDown, mdiNoteOutline } from "@mdi/js"; |
|
53 | 25 |
|
54 | 26 |
export default { |
55 | 27 |
name: "DepartmentTree", |
28 |
+ |
|
56 | 29 |
props: { |
57 |
- node: { |
|
58 |
- type: Object, |
|
59 |
- default: () => ({}), |
|
30 |
+ treeList: { |
|
31 |
+ type: Array, |
|
32 |
+ default: [], |
|
60 | 33 |
}, |
61 | 34 |
}, |
35 |
+ |
|
62 | 36 |
data() { |
63 | 37 |
return { |
64 | 38 |
toggleSelect: null, |
... | ... | @@ -67,6 +41,7 @@ |
67 | 41 |
selectedId: null, |
68 | 42 |
}; |
69 | 43 |
}, |
44 |
+ |
|
70 | 45 |
methods: { |
71 | 46 |
handleClick: function () { |
72 | 47 |
const vm = this; |
... | ... | @@ -78,8 +53,7 @@ |
78 | 53 |
}); |
79 | 54 |
|
80 | 55 |
// 노드 선택 시 하위 노드 표시 및 가리기 |
81 |
- vm.$emit("selectedNode", vm.node); |
|
82 |
- if (vm.toggleSelect === vm.node.dept_code) { |
|
56 |
+ if (vm.toggleSelect === vm.node.id) { |
|
83 | 57 |
vm.toggleSelect = null; |
84 | 58 |
vm.selectedId = null; |
85 | 59 |
vm.arrowPath = mdiChevronRight; |
... | ... | @@ -88,45 +62,35 @@ |
88 | 62 |
if (!vm.node.children || vm.node.children.length === 0) { |
89 | 63 |
vm.getChildDepartment(); |
90 | 64 |
} |
91 |
- vm.toggleSelect = vm.node.dept_code; |
|
92 |
- vm.selectedId = vm.node.dept_code; |
|
65 |
+ vm.toggleSelect = vm.node.id; |
|
66 |
+ vm.selectedId = vm.node.id; |
|
93 | 67 |
vm.arrowPath = mdiChevronDown; |
94 | 68 |
vm.notePath = mdiNoteOutline; |
95 | 69 |
} |
70 |
+ |
|
71 |
+ vm.$emit("selectedNode", vm.node.id); |
|
96 | 72 |
}, |
97 | 73 |
parentSelectedNode(node) { |
98 | 74 |
this.$emit("selectedNode", node); |
99 | 75 |
}, |
100 |
- // 깊이 2 이상일 때 자식 노드 불러오기 |
|
101 |
- getChildDepartment: function () { |
|
102 |
- axios |
|
103 |
- .get(`/department/tree/${this.node.dept_code}`) |
|
104 |
- .then((response) => { |
|
105 |
- this.node.children.push(...response.data.resultData.childDepartments); |
|
106 |
- }) |
|
107 |
- .catch((error) => { |
|
108 |
- this.$showAlert( |
|
109 |
- "오류", |
|
110 |
- "목록 불러오기 오류, 관리자에게 문의바랍니다." |
|
111 |
- ); |
|
112 |
- }); |
|
113 |
- }, |
|
114 | 76 |
}, |
77 |
+ |
|
115 | 78 |
components: { |
116 | 79 |
SvgIcon: SvgIcon, |
117 | 80 |
}, |
118 | 81 |
}; |
119 | 82 |
</script> |
120 |
- |
|
121 | 83 |
<style scoped> |
122 | 84 |
.tree-container { |
123 | 85 |
padding: 5px 10px; |
124 | 86 |
} |
87 |
+ |
|
125 | 88 |
.children-node { |
126 | 89 |
padding: 0 0 0 10px; |
127 | 90 |
overflow: hidden; |
128 | 91 |
transition: max-height 0.5s ease-in-out; |
129 | 92 |
} |
93 |
+ |
|
130 | 94 |
.node-text { |
131 | 95 |
font-size: 1.4rem; |
132 | 96 |
margin-left: 5px; |
+++ client/views/component/modal/Modal.vue
... | ... | @@ -0,0 +1,89 @@ |
1 | +<template> | |
2 | + <div v-show="isModalOpen" class="modal-wrapper"> | |
3 | + <div class="modal-container"> | |
4 | + <!-- 모달 HEAD (제목) --> | |
5 | + <div class="modal-title flex justify-between align-center"> | |
6 | + <h2>{{ title }}</h2> | |
7 | + <button class="close-btn" @click="closeModal"> | |
8 | + <svg-icon type="mdi" :width="20" :height="20" :path="closePath"></svg-icon> | |
9 | + </button> | |
10 | + </div> | |
11 | + <!-- 모달 BODY (본문) --> | |
12 | + <div class="modal-content-monthly"> | |
13 | + <!-- 검색창 --> | |
14 | + <div class="search-bar flex justify-center mb10"> | |
15 | + <div class="flex justify-between align-center"> | |
16 | + <div class="flex25 pl0"> | |
17 | + <select class="square-select full-select" v-model="searchData.key"> | |
18 | + <option :value="null">선택</option> | |
19 | + <option value="user_nm">이름</option> | |
20 | + <option value="user_id">아이디</option> | |
21 | + </select> | |
22 | + </div> | |
23 | + <div class="pr0 flex75 flex align-center no-gutter"> | |
24 | + <input type="text" class="square-input flex90" v-model="searchData.value" placeholder="검색어를 입력해주세요." @keyup.enter="searchList" /> | |
25 | + <button class="square-button blue-btn flex10" @click="searchList"> | |
26 | + <svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon> | |
27 | + </button> | |
28 | + </div> | |
29 | + </div> | |
30 | + </div> | |
31 | + <!-- 목록: 본문 --> | |
32 | + <div class="overflow-y" style="max-height: 500px"> | |
33 | + <table class="sticky-table list-table2"> | |
34 | + <colgroup> | |
35 | + <col style="width: 10%" /> | |
36 | + <col style="width: 10%" /> | |
37 | + <col style="width: 40%" /> | |
38 | + <col style="width: 40%" /> | |
39 | + </colgroup> | |
40 | + <thead> | |
41 | + <tr> | |
42 | + <th><input type="checkbox" /></th> | |
43 | + <th>No</th> | |
44 | + <th>이름</th> | |
45 | + <th>아이디</th> | |
46 | + </tr> | |
47 | + </thead> | |
48 | + <tbody> | |
49 | + <tr> | |
50 | + <td></td> | |
51 | + <td></td> | |
52 | + <td></td> | |
53 | + <td></td> | |
54 | + </tr> | |
55 | + </tbody> | |
56 | + </table> | |
57 | + </div> | |
58 | + <!-- 목록: 페이지네이션 --> | |
59 | + <PaginationButton v-model:currentPage="search.currentPage" :perPage="search.perPage" :totalCount="search.totalRows" :click="selectUsers" /> | |
60 | + </div> | |
61 | + <!-- 모달 FOOT (버튼) --> | |
62 | + <div class="modal-end flex justify-end"> | |
63 | + <button class="blue-btn small-btn" @click="confirmSelection">등록</button> | |
64 | + </div> | |
65 | + </div> | |
66 | + </div> | |
67 | +</template> | |
68 | +<script> | |
69 | +// icon용 svg import | |
70 | +import SvgIcon from "@jamescoyle/vue-icon"; | |
71 | +import { mdiMagnify, mdiClose } from "@mdi/js"; | |
72 | + | |
73 | +export default { | |
74 | + components: { SvgIcon }, | |
75 | + | |
76 | + data() { | |
77 | + return { | |
78 | + // icon용 svg path | |
79 | + searchPath: mdiMagnify, | |
80 | + closePath: mdiClose, | |
81 | + | |
82 | + isModalOpen: true, | |
83 | + | |
84 | + search: Object.assign({}, this.$getDefaultSerchVO()), | |
85 | + searchData: this.$getDefaultSerchItem(null, "string"), | |
86 | + } | |
87 | + } | |
88 | +} | |
89 | +</script>(No newline at end of file) |
+++ client/views/component/modal/UserSelectModal.vue
... | ... | @@ -0,0 +1,174 @@ |
1 | +<template> | |
2 | + <div v-show="isModalOpen" class="modal-wrapper"> | |
3 | + <div class="modal-container"> | |
4 | + <!-- 모달 HEAD --> | |
5 | + <div class="modal-title flex justify-between align-center"> | |
6 | + <h2>멤버 추가</h2> | |
7 | + <button class="close-btn" @click="$emit('fnCloseModal')"> | |
8 | + <svg-icon type="mdi" :width="20" :height="20" :path="closePath"></svg-icon> | |
9 | + </button> | |
10 | + </div> | |
11 | + <!-- 모달 BODY --> | |
12 | + <div class="modal-content-monthly"> | |
13 | + <!-- 검색 --> | |
14 | + <div class="search-bar flex justify-between align-center mb10"> | |
15 | + <div class="flex25 pl0"> | |
16 | + <select class="square-select full-select" v-model="searchData.key"> | |
17 | + <option :value="null">전체</option> | |
18 | + <option value="ui.user_nm">이름</option> | |
19 | + <option value="ui.user_id">아이디</option> | |
20 | + </select> | |
21 | + </div> | |
22 | + <div class="flex75 flex align-center no-gutter pr0"> | |
23 | + <input type="text" class="square-input flex90" placeholder="검색어를 입력해주세요." v-model="searchData.value" @keyup.enter="fnSelectUserList" /> | |
24 | + <button class="square-button blue-btn flex10" @click="fnSelectUserList"> | |
25 | + <svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon> | |
26 | + </button> | |
27 | + </div> | |
28 | + </div> | |
29 | + <!-- 목록 --> | |
30 | + <div> | |
31 | + <!-- 목록-본문 --> | |
32 | + <table class="list-table2"> | |
33 | + <colgroup> | |
34 | + <col style="width: 10%" /> | |
35 | + <col style="width: 35%" /> | |
36 | + <col style="width: 35%" /> | |
37 | + <col style="width: 20%" /> | |
38 | + </colgroup> | |
39 | + <thead> | |
40 | + <tr> | |
41 | + <th>No</th> | |
42 | + <th>이름</th> | |
43 | + <th>아이디</th> | |
44 | + <th>선택</th> | |
45 | + </tr> | |
46 | + </thead> | |
47 | + <tbody class="overflow-y" style="max-height: 500px"> | |
48 | + <template v-if="userList.length > 0"> | |
49 | + <tr v-for="(item, idx) in userList" :key="idx"> | |
50 | + <td>{{ search.totalRows - idx - (search.currentPage - 1) * search.perPage }}</td> | |
51 | + <td>{{ item.userNm }}</td> | |
52 | + <td>{{ item.userId }}</td> | |
53 | + <td><button type="button" class="blue-border-btn set-btn" @click="fnAddUser(item.userId)">선택</button></td> | |
54 | + </tr> | |
55 | + </template> | |
56 | + <tr v-else> | |
57 | + <td colspan="4">등록된 데이터가 없습니다.</td> | |
58 | + </tr> | |
59 | + </tbody> | |
60 | + </table> | |
61 | + <!-- 목록-페이지네이션 --> | |
62 | + <PaginationButton v-model:currentPage="search.currentPage" :perPage="search.perPage" :totalCount="search.totalRows" :click="fnSelectUserList" /> | |
63 | + </div> | |
64 | + </div> | |
65 | + </div> | |
66 | + </div> | |
67 | +</template> | |
68 | +<script> | |
69 | +import axios from "axios"; | |
70 | +// icon용 svg import | |
71 | +import SvgIcon from "@jamescoyle/vue-icon"; | |
72 | +import { mdiMagnify, mdiClose } from "@mdi/js"; | |
73 | +// 컴포넌트 import | |
74 | +import PageNavigation from "../../component/PageNavigation.vue"; | |
75 | +import PaginationButton from "../../component/PaginationButton.vue"; | |
76 | + | |
77 | +export default { | |
78 | + components: { SvgIcon, PageNavigation, PaginationButton }, | |
79 | + | |
80 | + props: { | |
81 | + deptCode: { | |
82 | + type: String, | |
83 | + default: null, | |
84 | + }, | |
85 | + isModalOpen: { | |
86 | + type: Boolean, | |
87 | + default: false, | |
88 | + }, | |
89 | + }, | |
90 | + | |
91 | + data() { | |
92 | + return { | |
93 | + // icon용 svg path | |
94 | + searchPath: mdiMagnify, | |
95 | + closePath: mdiClose, | |
96 | + | |
97 | + // 검색용 | |
98 | + search: Object.assign({}, this.$getDefaultSerchVO()), | |
99 | + searchData: Object.assign({}, this.$getDefaultSerchItem(null, "string")), | |
100 | + | |
101 | + // 목록용 | |
102 | + userList: [], | |
103 | + } | |
104 | + }, | |
105 | + | |
106 | + watch: { | |
107 | + isModalOpen(v) { | |
108 | + if (v) { | |
109 | + this.fnSelectUserList(); | |
110 | + } else { | |
111 | + // 초기화 | |
112 | + this.search = Object.assign({}, this.$getDefaultSerchVO()); | |
113 | + this.searchData = Object.assign({}, this.$getDefaultSerchItem(null, "string")); | |
114 | + this.userList = []; // 사용자 목록 | |
115 | + } | |
116 | + }, | |
117 | + }, | |
118 | + | |
119 | + methods: { | |
120 | + // 사용자 목록 조회 | |
121 | + fnSelectUserList() { | |
122 | + const vm = this; | |
123 | + | |
124 | + // 데이터 세팅 | |
125 | + let deptInfo = Object.assign({}, this.$getDefaultSerchItem(null, "string")); | |
126 | + deptInfo.key = 'deptCode'; | |
127 | + deptInfo.value = null; | |
128 | + | |
129 | + vm.search.searchObjectList = []; // 초기화 | |
130 | + vm.search.searchObjectList.push(vm.searchData); | |
131 | + vm.search.searchObjectList.push(deptInfo); | |
132 | + | |
133 | + // 실행 | |
134 | + axios({ | |
135 | + url: "/member/list", | |
136 | + method: "post", | |
137 | + headers: { "Content-Type": "application/json; charset=UTF-8" }, | |
138 | + data: vm.search, | |
139 | + }) | |
140 | + .then(response => { | |
141 | + vm.search = response.data.resultData.searchVO; | |
142 | + vm.userList = response.data.resultData.members; | |
143 | + }) | |
144 | + .catch(error => { | |
145 | + vm.$showAlert("사용자 관리", "목록 불러오기 오류, 관리자에게 문의바랍니다."); | |
146 | + }); | |
147 | + }, | |
148 | + | |
149 | + // 사용자 추가 (선택 버튼 동작) | |
150 | + fnAddUser(userId) { | |
151 | + const vm = this; | |
152 | + // 데이터 세팅 | |
153 | + let orgnztMember = { | |
154 | + userId: userId, | |
155 | + deptCode: this.deptCode | |
156 | + } | |
157 | + // 실행 | |
158 | + axios({ | |
159 | + url: "/orgnztMember", | |
160 | + method: "post", | |
161 | + headers: { "Content-Type": "application/json" }, | |
162 | + data: orgnztMember, | |
163 | + }) | |
164 | + .then(response => { | |
165 | + vm.$showAlert("사용자 추가", "사용자를 추가했습니다."); | |
166 | + vm.$emit('fnCloseModal'); // 모달 닫기 | |
167 | + }) | |
168 | + .catch(error => { | |
169 | + vm.$showAlert("오류", "부서 내 사용자 추가 오류, 관리자에게 문의바랍니다."); | |
170 | + }); | |
171 | + }, | |
172 | + } | |
173 | +} | |
174 | +</script>(No newline at end of file) |
+++ client/views/component/treeMenu/TreeMenu.vue
... | ... | @@ -0,0 +1,102 @@ |
1 | +<template> | |
2 | + <li> | |
3 | + <div :class="{ | |
4 | + 'tree-container flex align-center cursor': true, | |
5 | + selected: currentDeptCode.id === node.id, | |
6 | + }" @click="toggleNode(node)"> | |
7 | + <div> | |
8 | + <svg-icon type="mdi" :width="18" :height="18" :path="arrowPath"></svg-icon> | |
9 | + </div> | |
10 | + <div> | |
11 | + <svg-icon type="mdi" :width="18" :height="18" :path="notePath" :color="'#fbbe28'"></svg-icon> | |
12 | + </div> | |
13 | + <p class="node-text">{{ node.nm }}</p> | |
14 | + </div> | |
15 | + <template v-if="node.childList.length > 0"> | |
16 | + <ul v-if="isOpen" class="children-node"> | |
17 | + <li v-for="(item, idx) of node.childList" :key="idx"> | |
18 | + <TreeMenu :node="item" :currentDeptCode="currentDeptCode" @changeCurrent="changeCurrentNode" /> | |
19 | + </li> | |
20 | + </ul> | |
21 | + </template> | |
22 | + </li> | |
23 | +</template> | |
24 | +<script> | |
25 | +import SvgIcon from "@jamescoyle/vue-icon"; | |
26 | +import { mdiNote, mdiChevronRight, mdiChevronDown, mdiNoteOutline } from "@mdi/js"; | |
27 | + | |
28 | +export default { | |
29 | + name: "TreeMenu", | |
30 | + | |
31 | + components: { | |
32 | + SvgIcon: SvgIcon, | |
33 | + }, | |
34 | + | |
35 | + props: { | |
36 | + node: { | |
37 | + type: Object, | |
38 | + required: true, | |
39 | + }, | |
40 | + currentDeptCode: { | |
41 | + type: Object, | |
42 | + }, | |
43 | + }, | |
44 | + | |
45 | + data() { | |
46 | + return { | |
47 | + isOpen: false, | |
48 | + | |
49 | + notePath: mdiNote, | |
50 | + arrowPath: mdiChevronRight, | |
51 | + }; | |
52 | + }, | |
53 | + | |
54 | + watch: { | |
55 | + currentDeptCode: { | |
56 | + deep: true, | |
57 | + handler(v) { | |
58 | + if (this.$isEmpty(v)) { | |
59 | + this.isOpen = false; | |
60 | + this.notePath = mdiNote; | |
61 | + this.arrowPath = mdiChevronRight; | |
62 | + } | |
63 | + }, | |
64 | + } | |
65 | + }, | |
66 | + | |
67 | + methods: { | |
68 | + toggleNode(node) { | |
69 | + this.isOpen = !this.isOpen; | |
70 | + | |
71 | + if (this.isOpen) { | |
72 | + this.notePath = mdiNote; | |
73 | + this.arrowPath = mdiChevronRight; | |
74 | + } else { | |
75 | + this.notePath = mdiNoteOutline; | |
76 | + this.arrowPath = mdiChevronDown; | |
77 | + } | |
78 | + | |
79 | + this.changeCurrentNode(node); | |
80 | + }, | |
81 | + changeCurrentNode(node) { | |
82 | + this.$emit("changeCurrent", node); | |
83 | + } | |
84 | + }, | |
85 | +}; | |
86 | +</script> | |
87 | +<style scoped> | |
88 | +.tree-container { | |
89 | + padding: 5px 10px; | |
90 | +} | |
91 | + | |
92 | +.children-node { | |
93 | + padding: 0 0 0 10px; | |
94 | + overflow: hidden; | |
95 | + transition: max-height 0.5s ease-in-out; | |
96 | +} | |
97 | + | |
98 | +.node-text { | |
99 | + font-size: 1.4rem; | |
100 | + margin-left: 5px; | |
101 | +} | |
102 | +</style>(No newline at end of file) |
--- client/views/pages/integrated/DepartmentManagement.vue
+++ client/views/pages/integrated/DepartmentManagement.vue
... | ... | @@ -10,177 +10,172 @@ |
10 | 10 |
<div class="left-content flex100 content-box"> |
11 | 11 |
<div class="content-box"> |
12 | 12 |
<div class="content-titleZone"> |
13 |
- <p class="box-title">부서리스트</p> |
|
13 |
+ <p class="box-title">부서 목록</p> |
|
14 | 14 |
</div> |
15 | 15 |
<div class="content-zone overflow-y"> |
16 |
- <ul class="tree-wrap"> |
|
17 |
- <DepartmentTree v-for="(node, index) in departmentTreeList" :node="node" :key="index" @selectedNode="loadDepartmentData" @click="deptHostUncheckAll" /> |
|
16 |
+ <ul class="tree-wrap" v-if="deptTreeList.length > 0"> |
|
17 |
+ <TreeMenu v-for="(item, idx) in deptTreeList" :key="idx" :node="item" :currentDeptCode="selectedDept" @changeCurrent="fnSelectDept" /> |
|
18 | 18 |
</ul> |
19 | 19 |
</div> |
20 | 20 |
</div> |
21 | 21 |
</div> |
22 | 22 |
</div> |
23 |
- <div class="flex80 content-box"> |
|
24 |
- <div class="right-content flex100"> |
|
25 |
- <div class="content-titleZone"> |
|
26 |
- <p v-if="departmentData.dept_nm" class="box-title"> {{ departmentData.dept_nm }} </p> |
|
27 |
- <p v-else class="box-title">부서 추가</p> |
|
23 |
+ <div class="right-content flex80"> |
|
24 |
+ <!-- 부서 정보 --> |
|
25 |
+ <div class="content-titleZone"> |
|
26 |
+ <p class="box-title">부서 정보</p> |
|
27 |
+ </div> |
|
28 |
+ <div class="table-zone"> |
|
29 |
+ <div class="form-box"> |
|
30 |
+ <table class="form-table2"> |
|
31 |
+ <colgroup> |
|
32 |
+ <col style="width: 10%" /> |
|
33 |
+ <col style="width: 40%" /> |
|
34 |
+ <col style="width: 10%" /> |
|
35 |
+ <col style="width: 40%" /> |
|
36 |
+ </colgroup> |
|
37 |
+ <tbody> |
|
38 |
+ <tr> |
|
39 |
+ <th>부서코드</th> |
|
40 |
+ <td style="display: flex"> |
|
41 |
+ <input type="text" class="full-input" v-model="currentDept.dept_code" :disabled="editMode == 'update'" /> |
|
42 |
+ <button style="flex-grow: 1" class="small-btn blue-border-btn" v-if="editMode == 'create'" @click="fnDeptCodeDupChk">중복확인</button> |
|
43 |
+ </td> |
|
44 |
+ <th>부서명</th> |
|
45 |
+ <td> |
|
46 |
+ <input type="text" class="full-input" v-model="currentDept.dept_nm" /> |
|
47 |
+ </td> |
|
48 |
+ </tr> |
|
49 |
+ <tr> |
|
50 |
+ <th>부서설명</th> |
|
51 |
+ <td> |
|
52 |
+ <input type="text" class="full-input" v-model="currentDept.dept_dc" /> |
|
53 |
+ </td> |
|
54 |
+ <th>상위부서</th> |
|
55 |
+ <td style="display: flex"> |
|
56 |
+ <input type="text" class="full-input" v-model="currentDept.upper_dept_nm" readonly /> |
|
57 |
+ <button style="flex-grow: 1" class="small-btn blue-border-btn" @click="fnOpenModalByDeptList">부서찾기</button> |
|
58 |
+ </td> |
|
59 |
+ </tr> |
|
60 |
+ </tbody> |
|
61 |
+ </table> |
|
28 | 62 |
</div> |
29 |
- <div class="content-zone overflow-y"> |
|
30 |
- <div style="max-height: 35%"> |
|
31 |
- <div class="table-zone"> |
|
32 |
- <div class="form-box"> |
|
33 |
- <table class="form-table2"> |
|
34 |
- <colgroup> |
|
35 |
- <col style="width: 10%" /> |
|
36 |
- <col style="width: 40%" /> |
|
37 |
- <col style="width: 10%" /> |
|
38 |
- <col style="width: 40%" /> |
|
39 |
- </colgroup> |
|
40 |
- <tbody> |
|
41 |
- <tr> |
|
42 |
- <th>부서코드</th> |
|
43 |
- <td style="display: flex"> |
|
44 |
- <input type="text" v-model="departmentData.dept_code" id="dept_code" class="full-input" :disabled="dataLoaded" /> |
|
45 |
- <button v-if="!dataLoaded" @click="deptCodeDuplicateCheck()" style="flex-grow: 1" class="small-btn blue-border-btn" id="deptCodeDuplicateCheck">중복확인</button> |
|
46 |
- </td> |
|
47 |
- <th>부서명</th> |
|
48 |
- <td> |
|
49 |
- <input type="text" v-model="departmentData.dept_nm" id="dept_nm" class="full-input" /> |
|
50 |
- </td> |
|
51 |
- </tr> |
|
52 |
- <tr> |
|
53 |
- <th>부서설명</th> |
|
54 |
- <td> |
|
55 |
- <input type="text" v-model="departmentData.dept_dc" id="dept_dc" class="full-input" /> |
|
56 |
- </td> |
|
57 |
- <th>상위부서</th> |
|
58 |
- <td style="display: flex"> |
|
59 |
- <input type="text" v-model="departmentData.upper_dept_nm" id="upper_dept_nm" class="full-input" readonly :disabled="departmentData.dept_code == '1000' && departmentData.upper_dept == null" /> |
|
60 |
- <button v-if="!dataLoaded || (departmentData.dept_code == '1000' && departmentData.upper_dept != null)" @click="openDeptSearchModal()" style="flex-grow: 1" class="small-btn blue-border-btn">부서찾기</button> |
|
61 |
- </td> |
|
62 |
- </tr> |
|
63 |
- <tr v-if="departmentData.author == 'ROLE_ADMIN'"> |
|
64 |
- <th>권한</th> |
|
65 |
- <td> |
|
66 |
- <select name="" id="author" class="full-select" v-model="departmentData.author" :disabled="dataLoaded"> |
|
67 |
- <option :value="null" disabled> 권한을 선택해주세요. </option> |
|
68 |
- <option v-for="(author, idx) in authorList" :key="idx" :value="author.author">{{ author.author_dc }}</option> |
|
69 |
- </select> |
|
70 |
- </td> |
|
71 |
- </tr> |
|
72 |
- </tbody> |
|
73 |
- </table> |
|
74 |
- </div> |
|
75 |
- </div> |
|
76 |
- <div class="flex justify-end"> |
|
77 |
- <template v-if="!dataLoaded"> |
|
78 |
- <button class="blue-btn small-btn" @click="departmentInsert">등록</button> |
|
79 |
- </template> |
|
80 |
- <template v-else> |
|
81 |
- <button class="blue-btn small-btn" @click="updateDepartment()">수정</button> |
|
82 |
- <button v-if="departmentData.upper_dept != null" class="red-border-btn small-btn" @click="deleteDepartments()">삭제</button> |
|
83 |
- <button class="blue-border-btn small-btn" @click="insertForm()">취소</button> |
|
84 |
- </template> |
|
85 |
- </div> |
|
63 |
+ </div> |
|
64 |
+ <div class="flex justify-end"> |
|
65 |
+ <button class="blue-btn small-btn" v-if="editMode == 'create'" @click="fnInsertDept">등록</button> |
|
66 |
+ <button class="blue-btn small-btn" v-else @click="fnUpdateDept">수정</button> |
|
67 |
+ <button class="red-border-btn small-btn" v-if="editMode == 'update'" @click="fnDeleteDept">삭제</button> |
|
68 |
+ <button class="blue-border-btn small-btn" @click="fnCancelDept"><span v-if="editMode == 'create'">초기화</span><span v-else>취소</span></button> |
|
69 |
+ </div> |
|
70 |
+ <!-- 부서 내 사용자 목록 --> |
|
71 |
+ <div class="content-titleZone"> |
|
72 |
+ <p class="box-title">사용자 목록</p> |
|
73 |
+ </div> |
|
74 |
+ <div class="table-zone"> |
|
75 |
+ <div class="list-info flex justify-between align-center"> |
|
76 |
+ <div class="count-zone"> |
|
77 |
+ <p> 총 <span>{{ userList.length }}</span>건 중 <span>{{ userSelectList.length }}</span>건 선택 </p> |
|
86 | 78 |
</div> |
87 |
- <div style="min-height: 32.5%"> |
|
88 |
- <div class="table-zone"> |
|
89 |
- <div class="list-info flex justify-between align-center"> |
|
90 |
- <div class="count-zone"> |
|
91 |
- <p> 총 <span>{{ inDeptMemberList.length }}</span>건 중 <span>{{ selectedMembers.length }}</span>건 선택 </p> |
|
92 |
- </div> |
|
93 |
- <div class="cunt-selectZone"> |
|
94 |
- <select name="" id=""> |
|
95 |
- <option value="">10개 보기</option> |
|
96 |
- <option value="">20개 보기</option> |
|
97 |
- </select> |
|
98 |
- </div> |
|
99 |
- </div> |
|
100 |
- <table class="list-table"> |
|
101 |
- <colgroup> |
|
102 |
- <col style="width: 5%" /> |
|
103 |
- <col style="width: 10%" /> |
|
104 |
- <col style="width: 42.5%" /> |
|
105 |
- <col style="width: 42.5%" /> |
|
106 |
- </colgroup> |
|
107 |
- <thead> |
|
108 |
- <tr> |
|
109 |
- <th> |
|
110 |
- <input type="checkbox" @change="memberCheckAll" /> |
|
111 |
- </th> |
|
112 |
- <th>No</th> |
|
113 |
- <th>이름</th> |
|
114 |
- <th>로그인아이디</th> |
|
115 |
- </tr> |
|
116 |
- </thead> |
|
117 |
- <tbody> |
|
118 |
- <tr v-for="(inDeptMember, idx) in inDeptMemberList" :key="idx"> |
|
119 |
- <td> |
|
120 |
- <input type="checkbox" v-model="inDeptMember.selected" name="memberList" /> |
|
121 |
- </td> |
|
122 |
- <td>{{ memberIdx - idx }}</td> |
|
123 |
- <td>{{ inDeptMember.userNm }}</td> |
|
124 |
- <td>{{ inDeptMember.userId }}</td> |
|
125 |
- </tr> |
|
126 |
- </tbody> |
|
127 |
- </table> |
|
128 |
- </div> |
|
129 |
- <div class="flex justify-end"> |
|
130 |
- <button class="blue-btn small-btn" @click="openMemberModal">멤버추가</button> |
|
131 |
- <button class="red-border-btn small-btn" @click="deleteSelection">멤버삭제</button> |
|
132 |
- </div> |
|
133 |
- <PaginationButton v-model:currentPage="memberSearch.currentPage" :perPage="memberSearch.perPage" :totalCount="memberSearch.totalRows" :maxRange="5" :click="selectMemberList" /> |
|
79 |
+ <div class="cunt-selectZone"> |
|
80 |
+ <select v-model="searchByUser.perPage" @change="fnSelectUserList"> |
|
81 |
+ <option value="10">10개 보기</option> |
|
82 |
+ <option value="20">20개 보기</option> |
|
83 |
+ </select> |
|
134 | 84 |
</div> |
135 |
- <!-- <div style="min-height: 32.5%"> |
|
136 |
- <div class="table-zone"> |
|
137 |
- <div class="list-info flex justify-between align-center"> |
|
138 |
- <div class="count-zone"> |
|
139 |
- <p> 총 <span>{{ deptHostData.length }}</span>건 중 <span>{{ selectedDepts.length }}</span>건 선택 </p> |
|
140 |
- </div> |
|
141 |
- <div class="cunt-selectZone"> |
|
142 |
- <select name="" id=""> |
|
143 |
- <option value="">10개 보기</option> |
|
144 |
- <option value="">20개 보기</option> |
|
145 |
- </select> |
|
146 |
- </div> |
|
147 |
- </div> |
|
148 |
- <table class="list-table"> |
|
149 |
- <colgroup> |
|
150 |
- <col style="width: 5%" /> |
|
151 |
- <col style="width: 10%" /> |
|
152 |
- <col style="width: 42.5%" /> |
|
153 |
- <col style="width: 42.5%" /> |
|
154 |
- </colgroup> |
|
155 |
- <thead> |
|
156 |
- <tr> |
|
157 |
- <th> |
|
158 |
- <input type="checkbox" @click="deptHostCheckAll" v-model="deptCheckAll" /> |
|
159 |
- </th> |
|
160 |
- <th>No</th> |
|
161 |
- <th>호스트명</th> |
|
162 |
- <th>메인폴더</th> |
|
163 |
- </tr> |
|
164 |
- </thead> |
|
165 |
- <tbody> |
|
166 |
- <tr v-for="(data, index) in deptHostData" :key="index" @click="chooseDeptHost(data, 'update')"> |
|
167 |
- <td> |
|
168 |
- <input type="checkbox" v-model="selectedDepts" :value="data.host_code" @click.stop /> |
|
169 |
- </td> |
|
170 |
- <td>{{ index + 1 }}</td> |
|
171 |
- <td>{{ data.host_nm }}</td> |
|
172 |
- <td>{{ data.main_folder_path }}</td> |
|
173 |
- </tr> |
|
174 |
- </tbody> |
|
175 |
- </table> |
|
176 |
- <PaginationButton v-model:currentPage="deptSearch.currentPage" :perPage="deptSearch.perPage" :totalCount="deptSearch.totalRows" :maxRange="5" :click="selectDeptHost" /> |
|
177 |
- </div> |
|
178 |
- <div class="flex justify-end"> |
|
179 |
- <button class="orange-border-btn small-btn" @click="openHostModal"> 호스트추가 </button> |
|
180 |
- <button class="blue-border-btn small-btn" @click="deleteSelectedDeptHosts"> 호스트삭제 </button> |
|
181 |
- </div> |
|
182 |
- </div> --> |
|
183 | 85 |
</div> |
86 |
+ <table class="list-table"> |
|
87 |
+ <colgroup> |
|
88 |
+ <col style="width: 5%" /> |
|
89 |
+ <col style="width: 10%" /> |
|
90 |
+ <col style="width: 42.5%" /> |
|
91 |
+ <col style="width: 42.5%" /> |
|
92 |
+ </colgroup> |
|
93 |
+ <thead> |
|
94 |
+ <tr> |
|
95 |
+ <th> |
|
96 |
+ <input type="checkbox" v-model="isChkUserAll" @change="fnChkAll()" /> |
|
97 |
+ </th> |
|
98 |
+ <th>No</th> |
|
99 |
+ <th>이름</th> |
|
100 |
+ <th>아이디</th> |
|
101 |
+ </tr> |
|
102 |
+ </thead> |
|
103 |
+ <tbody> |
|
104 |
+ <template v-if="userList.length > 0"> |
|
105 |
+ <tr v-for="(item, idx) of userList" :key="idx"> |
|
106 |
+ <td> |
|
107 |
+ <input type="checkbox" :value="item" v-model="userSelectList" @click.stop="" @change="fnChangeChk" /> |
|
108 |
+ </td> |
|
109 |
+ <td>{{ searchByUser.totalRows - idx - (searchByUser.currentPage - 1) * searchByUser.perPage }}</td> |
|
110 |
+ <td>{{ item.userNm }}</td> |
|
111 |
+ <td>{{ item.userId }}</td> |
|
112 |
+ </tr> |
|
113 |
+ </template> |
|
114 |
+ <tr v-else> |
|
115 |
+ <td colspan="4">등록된 데이터가 없습니다.</td> |
|
116 |
+ </tr> |
|
117 |
+ </tbody> |
|
118 |
+ </table> |
|
119 |
+ </div> |
|
120 |
+ <div class="flex justify-end"> |
|
121 |
+ <button class="blue-btn small-btn" @click="fnOpenModalByUserList">사용자추가</button> |
|
122 |
+ <button class="red-border-btn small-btn" @click="fnDeleteUser">사용자삭제</button> |
|
123 |
+ </div> |
|
124 |
+ <PaginationButton v-model:currentPage="searchByUser.currentPage" :perPage="searchByUser.perPage" :totalCount="searchByUser.totalRows" :maxRange="5" :click="selectMemberList" /> |
|
125 |
+ <!-- 부서 내 호스트 목록 --> |
|
126 |
+ <div class="content-titleZone"> |
|
127 |
+ <p class="box-title">호스트 목록</p> |
|
128 |
+ </div> |
|
129 |
+ <DeptHostList :deptCode="selectedDept.id" /> |
|
130 |
+ <!-- 부서 내 디렉터리 목록 --> |
|
131 |
+ <div class="content-titleZone"> |
|
132 |
+ <p class="box-title">디렉터리 목록</p> |
|
133 |
+ </div> |
|
134 |
+ <div class="table-zone"> |
|
135 |
+ <div class="list-info flex justify-between align-center"> |
|
136 |
+ <div class="count-zone"> |
|
137 |
+ <p> 총 <span></span>건 중 <span></span>건 선택 </p> |
|
138 |
+ </div> |
|
139 |
+ <div class="cunt-selectZone"> |
|
140 |
+ <select name="" id=""> |
|
141 |
+ <option value="10">10개 보기</option> |
|
142 |
+ <option value="20">20개 보기</option> |
|
143 |
+ </select> |
|
144 |
+ </div> |
|
145 |
+ </div> |
|
146 |
+ <table class="list-table"> |
|
147 |
+ <colgroup> |
|
148 |
+ <col style="width: 5%" /> |
|
149 |
+ <col style="width: 10%" /> |
|
150 |
+ <col style="width: 42.5%" /> |
|
151 |
+ <col style="width: 42.5%" /> |
|
152 |
+ </colgroup> |
|
153 |
+ <thead> |
|
154 |
+ <tr> |
|
155 |
+ <th> |
|
156 |
+ <input type="checkbox" /> |
|
157 |
+ </th> |
|
158 |
+ <th>No</th> |
|
159 |
+ <th>호스트명</th> |
|
160 |
+ <th>메인폴더</th> |
|
161 |
+ </tr> |
|
162 |
+ </thead> |
|
163 |
+ <tbody> |
|
164 |
+ <tr> |
|
165 |
+ <td> |
|
166 |
+ <input type="checkbox" name="memberList" /> |
|
167 |
+ </td> |
|
168 |
+ <td></td> |
|
169 |
+ <td></td> |
|
170 |
+ <td></td> |
|
171 |
+ </tr> |
|
172 |
+ </tbody> |
|
173 |
+ </table> |
|
174 |
+ <PaginationButton v-model:currentPage="searchByDirectory.currentPage" :perPage="searchByDirectory.perPage" :totalCount="searchByDirectory.totalRows" :maxRange="5" :click="selectDeptHost" /> |
|
175 |
+ </div> |
|
176 |
+ <div class="flex justify-end"> |
|
177 |
+ <button class="blue-btn small-btn" @click="openHostModal">호스트추가</button> |
|
178 |
+ <button class="blue-border-btn small-btn" @click="deleteSelectedDeptHosts">호스트삭제</button> |
|
184 | 179 |
</div> |
185 | 180 |
</div> |
186 | 181 |
</div> |
... | ... | @@ -191,7 +186,7 @@ |
191 | 186 |
<div class="modal-container"> |
192 | 187 |
<div class="modal-title flex justify-between align-center"> |
193 | 188 |
<h2>부서 찾기</h2> |
194 |
- <button class="close-btn" @click="closeModal"> |
|
189 |
+ <button class="close-btn" @click="fnCloseModalByDeptList"> |
|
195 | 190 |
<svg-icon type="mdi" :width="20" :height="20" :path="closePath"></svg-icon> |
196 | 191 |
</button> |
197 | 192 |
</div> |
... | ... | @@ -200,15 +195,15 @@ |
200 | 195 |
<div class="search-bar w100"> |
201 | 196 |
<div class="flex justify-between align-center"> |
202 | 197 |
<div class="flex25 pl0"> |
203 |
- <select class="square-select full-select" v-model="dept_search_data.key"> |
|
198 |
+ <select class="square-select full-select" v-model="searchDataByDept.key"> |
|
204 | 199 |
<option :value="null">전체</option> |
205 | 200 |
<option value="dept_code">부서코드</option> |
206 | 201 |
<option value="dept_nm">부서명</option> |
207 | 202 |
</select> |
208 | 203 |
</div> |
209 | 204 |
<div class="flex75 flex align-center no-gutter pr0"> |
210 |
- <input type="text" class="square-input flex90" placeholder="부서를 검색해주세요" v-model="dept_search_data.value" @keyup.enter="selectDepartmentList" /> |
|
211 |
- <button class="square-button blue-btn flex10" @click="selectDepartmentList"> |
|
205 |
+ <input type="text" class="square-input flex90" placeholder="부서를 검색해주세요" v-model="searchDataByDept.value" @keyup.enter="fnSelectUpperDeptList" /> |
|
206 |
+ <button class="square-button blue-btn flex10" @click="fnSelectUpperDeptList"> |
|
212 | 207 |
<svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon> |
213 | 208 |
</button> |
214 | 209 |
</div> |
... | ... | @@ -218,94 +213,37 @@ |
218 | 213 |
<div class="overflow-y" style="height: 500px"> |
219 | 214 |
<table class="sticky-table list-table2"> |
220 | 215 |
<colgroup> |
221 |
- <col style="width: 50%" /> |
|
222 |
- <col style="width: 50%" /> |
|
216 |
+ <col style="width: 35%" /> |
|
217 |
+ <col style="width: 35%" /> |
|
218 |
+ <col style="width: 30%" /> |
|
223 | 219 |
</colgroup> |
224 | 220 |
<thead> |
225 | 221 |
<tr> |
226 | 222 |
<th>부서코드</th> |
227 | 223 |
<th>부서명</th> |
224 |
+ <th>비고</th> |
|
228 | 225 |
</tr> |
229 | 226 |
</thead> |
230 | 227 |
<tbody> |
231 |
- <template v-if="departmentList.length > 0"> |
|
232 |
- <tr v-for="(department, idx) in departmentList" :key="idx" @click="intoUpperDept(department)"> |
|
233 |
- <td>{{ department.dept_code }}</td> |
|
234 |
- <td>{{ department.dept_nm }}</td> |
|
228 |
+ <template v-if="selectDeptList.length > 0"> |
|
229 |
+ <tr v-for="(item, idx) in selectDeptList" :key="idx" :class="{ red: item.isUsed == false }"> |
|
230 |
+ <td>{{ item.dept_code }}</td> |
|
231 |
+ <td>{{ item.dept_nm }}</td> |
|
232 |
+ <td><button type="button" class="small-btn blue-border-btn" @click="fnSelectedUpperDept(item)">선택</button></td> |
|
235 | 233 |
</tr> |
236 | 234 |
</template> |
237 | 235 |
<tr v-else> |
238 |
- <td colspan="2">데이터가 존재하지 않습니다.</td> |
|
236 |
+ <td colspan="3">데이터가 존재하지 않습니다.</td> |
|
239 | 237 |
</tr> |
240 | 238 |
</tbody> |
241 | 239 |
</table> |
242 | 240 |
</div> |
243 | 241 |
</div> |
244 |
- <div class="modal-end flex justify-end"> |
|
245 |
- <button class="gray-btn large-btn pd5" @click="closeModal()">취소</button> |
|
246 |
- </div> |
|
247 | 242 |
</div> |
248 | 243 |
</div> |
249 |
- <div v-show="isHostModalOpen" class="modal-wrapper"> |
|
250 |
- <div class="modal-container"> |
|
251 |
- <div class="modal-title"> |
|
252 |
- <div class="flex justify-between align-center"> |
|
253 |
- <h2>호스트 목록</h2> |
|
254 |
- <button class="close-btn" @click="closeHostModal"> |
|
255 |
- <svg-icon type="mdi" :width="20" :height="20" :path="closePath"></svg-icon> |
|
256 |
- </button> |
|
257 |
- </div> |
|
258 |
- </div> |
|
259 |
- <div class="searchbar-zone modal-content-monthly"> |
|
260 |
- <div class="flex justify-end align-center"> |
|
261 |
- <select name="" id="" class="square-select" v-model="host_search_data.key"> |
|
262 |
- <option :value="null" disabled>선택</option> |
|
263 |
- <option value="host_nm">호스트명</option> |
|
264 |
- <option value="host_ip">호스트(IP)</option> |
|
265 |
- <option value="rgtr_id">등록자</option> |
|
266 |
- </select> |
|
267 |
- <div class="search-square"> |
|
268 |
- <input type="text" class="square-input" v-model="host_search_data.value" placeholder="검색어를 입력해주세요." @keyup.enter="selectHosts" /> |
|
269 |
- <button class="square-button" @click="selectHosts"> |
|
270 |
- <svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon> |
|
271 |
- </button> |
|
272 |
- </div> |
|
273 |
- </div> |
|
274 |
- <div class="table-zone"> |
|
275 |
- <table class="form-table" style="text-align: center"> |
|
276 |
- <colgroup> |
|
277 |
- <col style="width: 10%" /> |
|
278 |
- <col style="width: 30%" /> |
|
279 |
- <col style="width: 30%" /> |
|
280 |
- <col style="width: 20%" /> |
|
281 |
- <col style="width: 10%" /> |
|
282 |
- </colgroup> |
|
283 |
- <thead> |
|
284 |
- <tr> |
|
285 |
- <th>No</th> |
|
286 |
- <th>호스트명</th> |
|
287 |
- <th>호스트(IP)</th> |
|
288 |
- <th>사용자명</th> |
|
289 |
- <th>포트</th> |
|
290 |
- </tr> |
|
291 |
- </thead> |
|
292 |
- <tbody v-if="hosts.length > 0"> |
|
293 |
- <tr v-for="(host, index) in hosts" :key="index" @click="axiosDeptHost(host)"> |
|
294 |
- <td>{{ hostIdx - index }}</td> |
|
295 |
- <td>{{ host.host_nm }}</td> |
|
296 |
- <td>{{ host.host_ip }}</td> |
|
297 |
- <td>{{ host.host_id }}</td> |
|
298 |
- <td>{{ host.host_port }}</td> |
|
299 |
- </tr> |
|
300 |
- </tbody> |
|
301 |
- </table> |
|
302 |
- </div> |
|
303 |
- </div> |
|
304 |
- <PaginationButton v-model:currentPage="hostSearch.currentPage" :perPage="hostSearch.perPage" :totalCount="hostSearch.totalRows" :maxRange="5" :click="selectHosts" /> |
|
305 |
- </div> |
|
306 |
- </div> |
|
244 |
+ <UserSelectModal :deptCode="selectedDept.id" :isModalOpen="isUserModalOpen" @fnCloseModal="fnCloseModalByUserList" /> |
|
307 | 245 |
<!-- 사용자 목록 모달 --> |
308 |
- <div v-show="isMemberModalOpen" class="modal-wrapper"> |
|
246 |
+ <!-- <div v-show="isMemberModalOpen" class="modal-wrapper"> |
|
309 | 247 |
<div class="modal-container"> |
310 | 248 |
<div class="modal-title flex justify-between align-center"> |
311 | 249 |
<h2>멤버 추가</h2> |
... | ... | @@ -365,824 +303,410 @@ |
365 | 303 |
<button class="blue-btn small-btn" @click="confirmSelection">등록</button> |
366 | 304 |
</div> |
367 | 305 |
</div> |
368 |
- </div> |
|
369 |
- <!-- // 사용자 목록 모달 --> |
|
370 |
- <TreeModal :modalOpen="treeModalOpen" :modalConnection="connection" :modalNodes="nodes" :selectType="selectModalType" @modalSelectFolder="selectFolder" @closeTreeModal="closeTreeModal" @modalSubmit="axiosDeptHost" /> |
|
306 |
+ </div> --> |
|
307 |
+ <!-- <TreeModal :modalOpen="treeModalOpen" :modalConnection="connection" :modalNodes="nodes" :selectType="selectModalType" @modalSelectFolder="selectFolder" @closeTreeModal="closeTreeModal" @modalSubmit="axiosDeptHost" /> --> |
|
371 | 308 |
</template> |
372 | 309 |
<script> |
373 |
-import PageNavigation from "../../component/PageNavigation.vue"; |
|
374 |
-import PaginationButton from "../../component/PaginationButton.vue"; |
|
310 |
+import axios from "axios"; |
|
311 |
+// icon용 svg import |
|
375 | 312 |
import SvgIcon from "@jamescoyle/vue-icon"; |
376 | 313 |
import { mdiMagnify, mdiClose } from "@mdi/js"; |
377 |
-import axios from "axios"; |
|
314 |
+// 컴포넌트 import |
|
315 |
+import PageNavigation from "../../component/PageNavigation.vue"; |
|
316 |
+import PaginationButton from "../../component/PaginationButton.vue"; |
|
378 | 317 |
import DepartmentTree from "../../component/DepartmentTree.vue"; |
379 | 318 |
import TreeModal from "../../component/FileTreeModal.vue"; |
319 |
+import TreeMenu from "../../component/treeMenu/TreeMenu.vue"; |
|
320 |
+import DeptHostList from "./department/DeptHostList.vue"; |
|
321 |
+ |
|
322 |
+import UserSelectModal from "../../component/modal/UserSelectModal.vue"; |
|
380 | 323 |
|
381 | 324 |
export default { |
325 |
+ components: { SvgIcon, PageNavigation, PaginationButton, DepartmentTree, TreeModal, TreeMenu, DeptHostList, UserSelectModal }, |
|
326 |
+ |
|
382 | 327 |
data() { |
383 | 328 |
return { |
329 |
+ // icon용 svg path |
|
384 | 330 |
searchPath: mdiMagnify, |
385 |
- startDate: true, |
|
386 |
- endDate: true, |
|
387 |
- |
|
388 |
- departmentData: { |
|
389 |
- dept_code: null, |
|
390 |
- dept_nm: null, |
|
391 |
- dept_dc: null, |
|
392 |
- upper_dept: null, |
|
393 |
- upper_dept_nm: null, |
|
394 |
- dept_addr: null, |
|
395 |
- author: 'ROLE_USER', // 사용자 권한 |
|
396 |
- dept_dp: null, |
|
397 |
- }, |
|
398 |
- |
|
399 |
- departmentList: [], |
|
400 |
- departmentTreeList: [], |
|
401 |
- //부서코드 중복확인 여부 |
|
402 |
- isDuplicateChecked: false, |
|
403 |
- authorList: [], |
|
404 |
- |
|
405 |
- // 부서 호스트 연결용 변수 |
|
406 |
- modalType: "tab-modal", |
|
407 | 331 |
closePath: mdiClose, |
408 |
- isHostModalOpen: false, |
|
409 |
- hostSearch: this.$getDefaultSerchVO(), |
|
410 |
- host_search_data: this.$getDefaultSerchItem(null, "String"), |
|
411 |
- hosts: [], |
|
412 |
- hostIdx: 0, |
|
413 |
- selectedHost: null, |
|
414 |
- connection: { |
|
415 |
- host_code: null, |
|
416 |
- path: null, |
|
417 |
- depth: null, |
|
418 |
- type: null, |
|
419 |
- }, |
|
420 |
- nodes: [], |
|
421 |
- treeModalOpen: false, |
|
422 |
- selectModalType: 0, |
|
423 |
- dept_search_data: this.$getDefaultSerchItem(null, "String"), |
|
424 |
- deptSearch: this.$getDefaultSerchVO(), |
|
425 |
- deptHostData: [], |
|
426 |
- deptIdx: 0, |
|
427 |
- deptCheckAll: false, |
|
428 |
- selectedDepts: [], |
|
429 |
- depthDepth: 0, |
|
430 | 332 |
|
431 |
- //사용자 추가 |
|
432 |
- isMemberModalOpen: false, |
|
433 |
- addusers: [], // 선택된 사용자 정보를 저장할 배열 |
|
434 |
- users: [], |
|
435 |
- usersIdx: 0, |
|
436 |
- usersSearch: this.$getDefaultSerchVO(), |
|
437 |
- search_data1: this.$getDefaultSerchItem(null, "string"), |
|
438 |
- search_data2: this.$getDefaultSerchItem(null, "string"), |
|
439 |
- selectedUsers: null, |
|
333 |
+ // 검색 |
|
334 |
+ // 부서 |
|
335 |
+ searchByDept: Object.assign({}, this.$getDefaultSerchVO()), |
|
336 |
+ searchDataByDept: this.$getDefaultSerchItem(null, "string"), |
|
337 |
+ // 호스트 |
|
338 |
+ searchByHost: Object.assign({}, this.$getDefaultSerchVO()), |
|
339 |
+ searchByDirectory: Object.assign({}, this.$getDefaultSerchVO()), |
|
440 | 340 |
|
441 |
- //세현 추가 |
|
341 |
+ // default |
|
342 |
+ editMode: 'create', |
|
343 |
+ |
|
344 |
+ deptTreeList: [], |
|
345 |
+ |
|
346 |
+ deptVO: {}, |
|
347 |
+ originDept: {}, |
|
348 |
+ currentDept: {}, |
|
349 |
+ selectedDept: { |
|
350 |
+ "upId": null, |
|
351 |
+ "id": null, |
|
352 |
+ "nm": null, |
|
353 |
+ "dp": null, |
|
354 |
+ "ordr": null, |
|
355 |
+ "childList": [], |
|
356 |
+ }, // 부서 목록에서 선택한 부서 |
|
357 |
+ |
|
358 |
+ |
|
359 |
+ // 부서 정보 |
|
360 |
+ isDeptCodeDupChk: false, // 부서코드 중복확인 여부 |
|
361 |
+ |
|
362 |
+ // 부서 찾기 모달 관련 |
|
442 | 363 |
isDeptModalOpen: false, |
443 |
- memberSearch: this.$getDefaultSerchVO(), |
|
444 |
- member_search_data: this.$getDefaultSerchItem(null, "String"), |
|
445 |
- noDeptMemberList: [], |
|
446 |
- inDeptMemberList: [], |
|
447 |
- memberIdx: 0, |
|
448 |
- selectedMembers: [], |
|
449 |
- checkAll: false, |
|
364 |
+ selectDeptList: [], |
|
365 |
+ |
|
366 |
+ // 사용자 목록 관련 |
|
367 |
+ isChkUserAll: false, |
|
368 |
+ userList: [], |
|
369 |
+ userSelectList: [], |
|
370 |
+ searchByUser: Object.assign({}, this.$getDefaultSerchVO()), |
|
371 |
+ searchDataByUser: this.$getDefaultSerchItem(null, "string"), |
|
372 |
+ |
|
373 |
+ // 사용자 추가 모달 관련 |
|
374 |
+ isUserModalOpen: false, |
|
375 |
+ selectUserList: [], |
|
376 |
+ |
|
450 | 377 |
}; |
451 | 378 |
}, |
452 | 379 |
|
380 |
+ mounted() { |
|
381 |
+ this.fnSelectDeptListForTree(); |
|
382 |
+ }, |
|
383 |
+ |
|
384 |
+ watch: { |
|
385 |
+ // 부서코드 변경 시 중복확인 여부 false로 변경 |
|
386 |
+ "currentDept.dept_code"() { |
|
387 |
+ this.isDeptCodeDupChk = false; |
|
388 |
+ }, |
|
389 |
+ }, |
|
390 |
+ |
|
453 | 391 |
methods: { |
454 |
- deptSearchInit: function () { |
|
455 |
- this.deptSearch.searchObjectList.push(this.dept_search_data); |
|
456 |
- }, |
|
457 |
- |
|
458 |
- handleDateChange: function () { |
|
459 |
- if (this.startDate) { |
|
460 |
- this.startDate = false; |
|
461 |
- } else if (this.endDate) { |
|
462 |
- this.endDate = false; |
|
463 |
- } |
|
464 |
- }, |
|
465 |
- |
|
466 |
- insertForm: function () { |
|
467 |
- this.dataLoaded = false; |
|
468 |
- this.resetForm(); |
|
469 |
- }, |
|
470 |
- |
|
471 |
- //부서 목록에서 선택 시 |
|
472 |
- intoUpperDept: function (department) { |
|
473 |
- this.closeModal(); |
|
474 |
- this.departmentData.upper_dept = department.dept_code; |
|
475 |
- this.departmentData.upper_dept_nm = department.dept_nm; |
|
476 |
- }, |
|
477 |
- |
|
478 |
- //부서코드 중복검사 |
|
479 |
- deptCodeDuplicateCheck: function () { |
|
392 |
+ // 부서 목록 조회 (트리형 목록 용도) |
|
393 |
+ fnSelectDeptListForTree() { |
|
480 | 394 |
const vm = this; |
481 |
- |
|
482 |
- // 1. 부서코드 null 검사 |
|
483 |
- if (vm.$isEmpty(vm.departmentData.dept_code)) { |
|
484 |
- vm.$showAlert("부서 등록", "부서코드를 입력해주세요."); |
|
485 |
- document.getElementById("dept_code").focus(); |
|
486 |
- return; |
|
487 |
- } |
|
488 |
- |
|
489 |
- // 2. 부서코드 숫자만 검사 |
|
490 |
- if (!/^\d+$/.test(vm.departmentData.dept_code)) { |
|
491 |
- vm.$showAlert("부서 등록", "부서코드는 숫자만 입력할 수 있습니다."); |
|
492 |
- document.getElementById("dept_code").focus(); |
|
493 |
- return; |
|
494 |
- } |
|
495 |
- |
|
496 | 395 |
axios({ |
497 |
- url: "/department/" + vm.departmentData.dept_code, |
|
396 |
+ url: "/department", |
|
498 | 397 |
method: "get", |
499 |
- headers: { |
|
500 |
- "Content-Type": "application/json;", |
|
501 |
- }, |
|
398 |
+ headers: { "Content-Type": "application/json; charset=UTF-8" }, |
|
502 | 399 |
}) |
503 |
- .then((response) => { |
|
504 |
- if (response.data.resultData.checkDuplicateOrgCode) { |
|
505 |
- vm.$showAlert("부서코드 중복확인", "사용중인 부서코드입니다."); |
|
506 |
- vm.isDuplicateChecked = false; // 중복 확인이 실패하였으므로 중복 확인 상태를 false로 설정합니다. |
|
507 |
- } else { |
|
508 |
- vm.$showAlert( |
|
509 |
- "부서코드 중복확인", |
|
510 |
- "사용할 수 있는 부서코드입니다." |
|
511 |
- ); |
|
512 |
- vm.isDuplicateChecked = true; // 중복 확인이 성공하였으므로 중복 확인 상태를 true로 설정합니다. |
|
513 |
- } |
|
400 |
+ .then(response => { |
|
401 |
+ vm.deptVO = response.data.resultData.departmentVO; |
|
402 |
+ vm.deptTreeList = response.data.resultData.hierachyList; |
|
514 | 403 |
}) |
515 |
- .catch((error) => { |
|
516 |
- this.$showAlert( |
|
517 |
- "에러 발생", |
|
518 |
- "에러가 발생했습니다. 관리자에게 문의해 주세요." |
|
519 |
- ); |
|
404 |
+ .catch(error => { |
|
405 |
+ this.$showAlert("에러 발생", "에러가 발생했습니다. 관리자에게 문의해 주세요."); |
|
520 | 406 |
}); |
521 | 407 |
}, |
522 | 408 |
|
523 |
- // 부서등록 유효성 검사 |
|
524 |
- insertDepartmentValidation() { |
|
409 |
+ // 부서코드 중복확인 |
|
410 |
+ fnDeptCodeDupChk() { |
|
525 | 411 |
const vm = this; |
526 |
- // 1. 부서코드 중복 검사 여부 확인 |
|
527 |
- if (!vm.isDuplicateChecked) { |
|
528 |
- vm.$showAlert("부서 등록", "부서코드 중복확인 후 등록해주세요."); |
|
529 |
- document.getElementById("deptCodeDuplicateCheck").focus(); |
|
412 |
+ |
|
413 |
+ // 유효성 검사 |
|
414 |
+ if (!vm.validationDeptCode()) { |
|
415 |
+ return; |
|
416 |
+ }; |
|
417 |
+ |
|
418 |
+ axios({ |
|
419 |
+ url: "/department/" + vm.currentDept.dept_code, |
|
420 |
+ method: "get", |
|
421 |
+ headers: { "Content-Type": "application/json; charset=UTF-8" }, |
|
422 |
+ }) |
|
423 |
+ .then(response => { |
|
424 |
+ if (response.data.resultData.checkDuplicateOrgCode) { |
|
425 |
+ vm.$showAlert("부서코드 중복확인", "사용중인 부서코드입니다."); |
|
426 |
+ vm.currentDept.dept_code = null; |
|
427 |
+ } else { |
|
428 |
+ vm.$showAlert("부서코드 중복확인", "사용할 수 있는 부서코드입니다."); |
|
429 |
+ vm.isDeptCodeDupChk = true; |
|
430 |
+ } |
|
431 |
+ }) |
|
432 |
+ .catch(error => { |
|
433 |
+ this.$showAlert("에러 발생", "에러가 발생했습니다. 관리자에게 문의해 주세요."); |
|
434 |
+ }); |
|
435 |
+ }, |
|
436 |
+ |
|
437 |
+ // #부서찾기모달 |
|
438 |
+ // 부서찾기 모달 열기 |
|
439 |
+ fnOpenModalByDeptList() { |
|
440 |
+ this.fnSelectUpperDeptList(); // 부서 목록 조회(자신 제외) |
|
441 |
+ this.isDeptModalOpen = true; |
|
442 |
+ }, |
|
443 |
+ // 부서찾기 모달 닫기 |
|
444 |
+ fnCloseModalByDeptList() { |
|
445 |
+ this.isDeptModalOpen = false; |
|
446 |
+ }, |
|
447 |
+ // 부서 목록 조회(자신 제외) |
|
448 |
+ fnSelectUpperDeptList() { |
|
449 |
+ const vm = this; |
|
450 |
+ // 데이터 세팅 |
|
451 |
+ vm.searchByDept.searchObjectList = []; |
|
452 |
+ vm.searchByDept.searchObjectList.push(vm.searchDataByDept); |
|
453 |
+ // 실행 |
|
454 |
+ axios({ |
|
455 |
+ url: "/department/departments/" + vm.currentDept.dept_code, |
|
456 |
+ method: "post", |
|
457 |
+ headers: { "Content-Type": "application/json; charset=UTF-8" }, |
|
458 |
+ data: vm.searchByDept, |
|
459 |
+ }) |
|
460 |
+ .then(response => { |
|
461 |
+ if (response.data != null) { |
|
462 |
+ vm.selectDeptList = response.data.resultData.selectDeptList; |
|
463 |
+ vm.searchByDept = response.data.resultData.searchVO; |
|
464 |
+ |
|
465 |
+ // 하위 부서 선택을 제외하기 위한 옵션 추가 |
|
466 |
+ let selectChildDeptList = response.data.resultData.selectChildDeptList; // 하위 부서 목록 |
|
467 |
+ if (vm.selectDeptList.length > 0 && selectChildDeptList.length > 0) { |
|
468 |
+ for (let dept of vm.selectDeptList) { |
|
469 |
+ dept.isUsed = true; |
|
470 |
+ for (let deptCode of selectChildDeptList) { |
|
471 |
+ if (dept.dept_code == deptCode) { |
|
472 |
+ dept.isUsed = false; |
|
473 |
+ break; |
|
474 |
+ } |
|
475 |
+ } |
|
476 |
+ } |
|
477 |
+ } |
|
478 |
+ } else { |
|
479 |
+ this.$showAlert("사용자 관리", "에러가 발생했습니다. 관리자에게 문의해 주세요."); |
|
480 |
+ } |
|
481 |
+ }) |
|
482 |
+ .catch(error => { |
|
483 |
+ vm.$showAlert("사용자 관리", "목록 불러오기 오류, 관리자에게 문의바랍니다."); |
|
484 |
+ }); |
|
485 |
+ }, |
|
486 |
+ // 부서찾기 모달 내 부서 선택 |
|
487 |
+ fnSelectedUpperDept(dept) { |
|
488 |
+ if (!dept.isUsed) { |
|
489 |
+ this.$showAlert("부서 찾기", "자신의 하위 부서는 선택할 수 없습니다."); |
|
490 |
+ return; |
|
491 |
+ } |
|
492 |
+ this.currentDept.upper_dept = dept.dept_code; |
|
493 |
+ this.currentDept.upper_dept_nm = dept.dept_nm; |
|
494 |
+ |
|
495 |
+ this.fnCloseModalByDeptList(); // 부서찾기 모달 닫기 |
|
496 |
+ }, |
|
497 |
+ |
|
498 |
+ // 부서 등록 |
|
499 |
+ fnInsertDept() { |
|
500 |
+ const vm = this; |
|
501 |
+ // 유효성 검사 |
|
502 |
+ if (!vm.insertDeptValidation()) { |
|
503 |
+ return |
|
504 |
+ }; |
|
505 |
+ // 실행 |
|
506 |
+ axios({ |
|
507 |
+ url: "/department", |
|
508 |
+ method: "post", |
|
509 |
+ headers: { "Content-Type": "application/json; charset=UTF-8" }, |
|
510 |
+ data: vm.currentDept, |
|
511 |
+ }) |
|
512 |
+ .then(response => { |
|
513 |
+ vm.$showAlert("부서 등록", "부서 등록이 완료되었습니다."); |
|
514 |
+ |
|
515 |
+ // 초기화 |
|
516 |
+ vm.fnCancelDept(); |
|
517 |
+ vm.fnSelectDeptListForTree() // 부서 목록 조회 (트리형 목록 용도) |
|
518 |
+ }) |
|
519 |
+ .catch(error => { |
|
520 |
+ this.$showAlert("에러 발생", "에러가 발생했습니다. 관리자에게 문의해 주세요."); |
|
521 |
+ }); |
|
522 |
+ }, |
|
523 |
+ |
|
524 |
+ // 부서 수정 |
|
525 |
+ fnUpdateDept() { |
|
526 |
+ const vm = this; |
|
527 |
+ // 실행 |
|
528 |
+ axios({ |
|
529 |
+ url: "/department", |
|
530 |
+ method: "put", |
|
531 |
+ headers: { "Content-Type": "application/json; charset=UTF-8" }, |
|
532 |
+ data: vm.currentDept, |
|
533 |
+ }) |
|
534 |
+ .then(response => { |
|
535 |
+ vm.$showAlert("부서 수정", "부서 정보가 수정되었습니다."); |
|
536 |
+ |
|
537 |
+ // 초기화 |
|
538 |
+ vm.fnCancelDept(); |
|
539 |
+ vm.fnSelectDeptListForTree(); // 부서 목록 조회 (트리형 목록 용도) |
|
540 |
+ }) |
|
541 |
+ .catch(error => { |
|
542 |
+ this.$showAlert("에러 발생", "에러가 발생했습니다. 관리자에게 문의해 주세요."); |
|
543 |
+ }); |
|
544 |
+ }, |
|
545 |
+ |
|
546 |
+ // 부서 삭제 |
|
547 |
+ async fnDeleteDept() { |
|
548 |
+ const vm = this; |
|
549 |
+ |
|
550 |
+ let isConfirmChk = await this.$showConfirm("경고", "선택한 부서를 삭제하시겠습니까?"); |
|
551 |
+ if (!isConfirmChk) { |
|
552 |
+ return; |
|
553 |
+ } |
|
554 |
+ |
|
555 |
+ // 실행 |
|
556 |
+ axios({ |
|
557 |
+ url: `/department`, |
|
558 |
+ method: "delete", |
|
559 |
+ headers: { "Content-Type": "application/json; charset=UTF-8" }, |
|
560 |
+ data: vm.currentDept, |
|
561 |
+ }) |
|
562 |
+ .then(response => { |
|
563 |
+ vm.$showAlert("부서 삭제", "부서 삭제에 성공했습니다."); |
|
564 |
+ |
|
565 |
+ // 초기화 |
|
566 |
+ vm.fnCancelDept(); |
|
567 |
+ vm.fnSelectDeptListForTree(); // 부서 목록 조회 (트리형 목록 용도) |
|
568 |
+ }) |
|
569 |
+ .catch(error => { |
|
570 |
+ vm.$showAlert("부서 삭제", "삭제오류, 관리자에게 문의바랍니다."); |
|
571 |
+ }); |
|
572 |
+ }, |
|
573 |
+ |
|
574 |
+ // 부서 취소 |
|
575 |
+ fnCancelDept() { |
|
576 |
+ this.editMode = 'create'; |
|
577 |
+ this.currentDept = this.deptVO; |
|
578 |
+ this.selectedDept = {}; |
|
579 |
+ this.isDeptCodeDupChk = false; // 부서코드 중복확인 여부 |
|
580 |
+ |
|
581 |
+ // 사용자 목록 |
|
582 |
+ this.userList = []; |
|
583 |
+ this.userSelectList = []; |
|
584 |
+ this.searchByUser = Object.assign({}, this.$getDefaultSerchVO()); |
|
585 |
+ this.searchDataByUser = this.$getDefaultSerchItem(null, "string"); |
|
586 |
+ }, |
|
587 |
+ |
|
588 |
+ // 부서 상세 조회 |
|
589 |
+ fnSelectDept(currentDept) { |
|
590 |
+ const vm = this; |
|
591 |
+ // 데이터 세팅 |
|
592 |
+ vm.selectedDept = currentDept; |
|
593 |
+ // 실행 |
|
594 |
+ axios({ |
|
595 |
+ url: "/department/selectDept/" + currentDept.id, |
|
596 |
+ method: "get", |
|
597 |
+ headers: { "Content-Type": "application/json; charset=UTF-8" }, |
|
598 |
+ }) |
|
599 |
+ .then(response => { |
|
600 |
+ vm.editMode = 'update'; |
|
601 |
+ vm.originDept = response.data.resultData.departmentVO; |
|
602 |
+ vm.currentDept = Object.assign({}, response.data.resultData.departmentVO); |
|
603 |
+ // 부서 내부 목록 조회 |
|
604 |
+ vm.fnSelectUserList(); |
|
605 |
+ }) |
|
606 |
+ .catch(error => { |
|
607 |
+ vm.$showAlert("사용자 관리", "불러오기 오류, 관리자에게 문의바랍니다."); |
|
608 |
+ }); |
|
609 |
+ }, |
|
610 |
+ |
|
611 |
+ // 부서 내 사용자 목록 조회 |
|
612 |
+ fnSelectUserList() { |
|
613 |
+ const vm = this; |
|
614 |
+ // 데이터 세팅 |
|
615 |
+ vm.searchDataByUser.key = "deptCode"; |
|
616 |
+ vm.searchDataByUser.value = vm.selectedDept.id; |
|
617 |
+ vm.searchByUser.searchObjectList = []; |
|
618 |
+ vm.searchByUser.searchObjectList.push(vm.searchDataByUser); |
|
619 |
+ // 실행 |
|
620 |
+ axios({ |
|
621 |
+ url: "/orgnztMember/selectOrgnztMemberList", |
|
622 |
+ method: "post", |
|
623 |
+ headers: { "Content-Type": "application/json; charset=UTF-8" }, |
|
624 |
+ data: vm.searchByUser, |
|
625 |
+ }) |
|
626 |
+ .then(response => { |
|
627 |
+ vm.userList = response.data.resultData.list; |
|
628 |
+ vm.searchByUser = response.data.resultData.searchVO; |
|
629 |
+ }) |
|
630 |
+ .catch(error => { |
|
631 |
+ vm.$showAlert("회원 목록", "목록 불러오기 오류, 관리자에게 문의바랍니다."); |
|
632 |
+ }); |
|
633 |
+ }, |
|
634 |
+ // 사용자 목록 전체 선택 |
|
635 |
+ fnChkAll() { |
|
636 |
+ if (this.isChkUserAll) { |
|
637 |
+ this.userSelectList = this.userList; |
|
638 |
+ } else { |
|
639 |
+ this.userSelectList = []; |
|
640 |
+ } |
|
641 |
+ }, |
|
642 |
+ // 사용자 목록 상세 선택 |
|
643 |
+ fnChangeChk() { |
|
644 |
+ if (this.userSelectList.length == this.userList.length) { |
|
645 |
+ this.isChkUserAll = true; |
|
646 |
+ } else { |
|
647 |
+ this.isChkUserAll = false; |
|
648 |
+ } |
|
649 |
+ }, |
|
650 |
+ // 사용자 추가 모달 열기 |
|
651 |
+ fnOpenModalByUserList() { |
|
652 |
+ this.isUserModalOpen = true; |
|
653 |
+ }, |
|
654 |
+ // 사용자 추가 모달 닫기 |
|
655 |
+ fnCloseModalByUserList() { |
|
656 |
+ this.isUserModalOpen = false; |
|
657 |
+ this.fnSelectUserList(); // 사용자 목록 조회 |
|
658 |
+ }, |
|
659 |
+ // 사용자 삭제 |
|
660 |
+ fnDeleteUser() { |
|
661 |
+ const vm = this; |
|
662 |
+ // 실행 |
|
663 |
+ axios({ |
|
664 |
+ url: "/orgnztMember", |
|
665 |
+ method: "delete", |
|
666 |
+ headers: { "Content-Type": "application/json; charset=UTF-8" }, |
|
667 |
+ data: vm.userSelectList, |
|
668 |
+ }) |
|
669 |
+ .then(function (response) { |
|
670 |
+ vm.$showAlert("작업 성공", "사용자 삭제에 성공했습니다."); |
|
671 |
+ vm.fnSelectUserList(); // 사용자 목록 조회 |
|
672 |
+ }) |
|
673 |
+ .catch(function (error) { |
|
674 |
+ vm.$showAlert("작업 실패", "사용자 삭제에 실패했습니다.\n관리자에게 문의바랍니다."); |
|
675 |
+ }); |
|
676 |
+ }, |
|
677 |
+ |
|
678 |
+ // #유효성 검사 |
|
679 |
+ // 부서 등록용 유효성 검사 |
|
680 |
+ insertDeptValidation() { |
|
681 |
+ // 부서코드 중복 검사 여부 확인 |
|
682 |
+ if (!this.isDeptCodeDupChk) { |
|
683 |
+ this.$showAlert("부서 등록", "부서코드 중복확인 후 등록해주세요."); |
|
530 | 684 |
return false; |
531 | 685 |
} |
532 | 686 |
|
533 |
- // 2. 부서명 null 검사 |
|
534 |
- if (vm.$isEmpty(vm.departmentData.dept_nm)) { |
|
535 |
- vm.$showAlert("부서 등록", "부서명을 입력해주세요."); |
|
536 |
- document.getElementById("dept_nm").focus(); |
|
537 |
- return false; |
|
538 |
- } |
|
539 |
- |
|
540 |
- // // 3. 상위 부서 검사 null 검사 |
|
541 |
- // if (vm.$isEmpty(vm.departmentData.upper_dept) || vm.$isEmpty(vm.departmentData.upper_dept_nm)) { |
|
542 |
- // vm.$showAlert("부서 등록", "상위 부서를 선택해주세요."); |
|
543 |
- // return false; |
|
544 |
- // } |
|
545 |
- |
|
546 |
- // 4. 권한 null 검사 |
|
547 |
- if (vm.$isEmpty(vm.departmentData.author)) { |
|
548 |
- vm.$showAlert("부서 등록", "권한을 선택해주세요."); |
|
549 |
- document.getElementById("author").focus(); |
|
687 |
+ // 부서코드 유효성 검사 |
|
688 |
+ if (!this.validationDeptCode()) { |
|
550 | 689 |
return false; |
551 | 690 |
} |
552 | 691 |
|
553 | 692 |
return true; |
554 | 693 |
}, |
555 |
- |
|
556 |
- //부서 등록 |
|
557 |
- departmentInsert() { |
|
558 |
- const vm = this; |
|
559 |
- if (!vm.insertDepartmentValidation()) return; |
|
560 |
- |
|
561 |
- axios({ |
|
562 |
- url: "/department", |
|
563 |
- method: "post", |
|
564 |
- headers: { |
|
565 |
- "Content-Type": "application/json;", |
|
566 |
- }, |
|
567 |
- data: vm.departmentData, |
|
568 |
- }) |
|
569 |
- .then(function (response) { |
|
570 |
- vm.$showAlert("부서 등록", "부서 등록이 완료되었습니다."); |
|
571 |
- vm.resetForm(); |
|
572 |
- |
|
573 |
- vm.selectDepartments(); // 부서 리스트 재조회 |
|
574 |
- }) |
|
575 |
- .catch(function (error) { |
|
576 |
- this.$showAlert( |
|
577 |
- "에러 발생", |
|
578 |
- "에러가 발생했습니다. 관리자에게 문의해 주세요." |
|
579 |
- ); |
|
580 |
- }); |
|
581 |
- }, |
|
582 |
- |
|
583 |
- // 부서 찾기 모달 열기 |
|
584 |
- openDeptSearchModal() { |
|
585 |
- this.selectDepartmentList(); // 부서 목록 조회(전체) |
|
586 |
- this.isDeptModalOpen = true; |
|
587 |
- }, |
|
588 |
- // 부서 찾기 모달 닫기 |
|
589 |
- closeModal() { |
|
590 |
- this.departmentList = []; // 초기화 |
|
591 |
- this.isDeptModalOpen = false; |
|
592 |
- }, |
|
593 |
- // 부서 찾기 - 부서 목록 조회 |
|
594 |
- selectDepartmentList() { |
|
595 |
- const vm = this; |
|
596 |
- axios({ |
|
597 |
- url: "/department/departments", |
|
598 |
- method: "post", |
|
599 |
- data: vm.deptSearch, |
|
600 |
- }) |
|
601 |
- .then(function (response) { |
|
602 |
- vm.departmentList = response.data.resultData.selectDeptList; |
|
603 |
- }) |
|
604 |
- .catch(function (error) { |
|
605 |
- vm.$showAlert( |
|
606 |
- "부서 조회", |
|
607 |
- "목록 불러오기 오류, 관리자에게 문의바랍니다." |
|
608 |
- ); |
|
609 |
- }); |
|
610 |
- }, |
|
611 |
- |
|
612 |
- // 부서 리스트 조회 |
|
613 |
- selectDepartments() { |
|
614 |
- const vm = this; |
|
615 |
- axios({ |
|
616 |
- url: "/department", |
|
617 |
- method: "get", |
|
618 |
- params: { |
|
619 |
- user_id: vm.$store.state.loginUser.user_id, |
|
620 |
- }, |
|
621 |
- }) |
|
622 |
- .then(function (response) { |
|
623 |
- vm.departmentTreeList = |
|
624 |
- response.data.resultData.selectTreeDepartments; |
|
625 |
- }) |
|
626 |
- .catch(function (error) { |
|
627 |
- this.$showAlert( |
|
628 |
- "에러 발생", |
|
629 |
- "에러가 발생했습니다. 관리자에게 문의해 주세요." |
|
630 |
- ); |
|
631 |
- }); |
|
632 |
- }, |
|
633 |
- |
|
634 |
- resetForm() { |
|
635 |
- this.departmentData = { |
|
636 |
- org_code: null, |
|
637 |
- dept_nm: null, |
|
638 |
- dept_dc: null, |
|
639 |
- upper_dept: null, |
|
640 |
- author: 'ROLE_USER', // 사용자 권한 |
|
641 |
- }; |
|
642 |
- }, |
|
643 |
- |
|
644 |
- // 권한 목록 조회 |
|
645 |
- getAuthorList() { |
|
646 |
- const vm = this; |
|
647 |
- axios({ |
|
648 |
- url: "/department/getAuthorInfo", |
|
649 |
- method: "get", |
|
650 |
- }) |
|
651 |
- .then(function (response) { |
|
652 |
- vm.authorList = response.data.resultData.getAuthorInfo; |
|
653 |
- }) |
|
654 |
- .catch(function (error) { |
|
655 |
- this.$showAlert( |
|
656 |
- "에러 발생", |
|
657 |
- "에러가 발생했습니다. 관리자에게 문의해 주세요." |
|
658 |
- ); |
|
659 |
- }); |
|
660 |
- }, |
|
661 |
- |
|
662 |
- loadDepartmentData(department) { |
|
663 |
- this.departmentData = Object.assign({}, department); // 클릭한 호스트의 데이터를 복사하여 저장합니다. |
|
664 |
- this.originaldepartmentData = Object.assign({}, department); |
|
665 |
- this.dataLoaded = true; // 데이터가 로드되었음을 표시합니다. |
|
666 |
- this.selectedDeptCode = department.dept_code; |
|
667 |
- this.selectMemberList(); |
|
668 |
- }, |
|
669 |
- |
|
670 |
- //부서별 사용자 목록 조회 |
|
671 |
- selectMemberList: function () { |
|
672 |
- const vm = this; |
|
673 |
- vm.member_search_data.key = "orgnzt_info.dept_code"; |
|
674 |
- vm.member_search_data.value = vm.departmentData.dept_code; |
|
675 |
- vm.memberSearch.searchObjectList.push(vm.member_search_data); |
|
676 |
- |
|
677 |
- axios({ |
|
678 |
- url: "/member/list", |
|
679 |
- method: "post", |
|
680 |
- data: vm.memberSearch, |
|
681 |
- }) |
|
682 |
- .then(function (response) { |
|
683 |
- if (response.data) { |
|
684 |
- vm.inDeptMemberList = response.data.resultData.selectMemberList; |
|
685 |
- vm.memberSearch.totalRows = response.data.resultData.totalRow; |
|
686 |
- vm.memberIdx = |
|
687 |
- vm.memberSearch.totalRows - |
|
688 |
- (vm.memberSearch.currentPage - 1) * vm.memberSearch.perPage; |
|
689 |
- } else { |
|
690 |
- this.$showAlert( |
|
691 |
- "에러 발생", |
|
692 |
- "에러가 발생했습니다. 관리자에게 문의해 주세요." |
|
693 |
- ); |
|
694 |
- } |
|
695 |
- }) |
|
696 |
- .catch(function (error) { |
|
697 |
- vm.$showAlert( |
|
698 |
- "회원 목록", |
|
699 |
- "목록 불러오기 오류, 관리자에게 문의바랍니다." |
|
700 |
- ); |
|
701 |
- }); |
|
702 |
- }, |
|
703 |
- |
|
704 |
- //사용자 선택 삭제용 선택 기능 |
|
705 |
- check: function (member) { |
|
706 |
- this.selectedMembers.push(member.userId); |
|
707 |
- }, |
|
708 |
- |
|
709 |
- //사용자 선택 삭제용 전체 선택 기능 |
|
710 |
- memberCheckAll(event) { |
|
711 |
- const isChecked = event.target.checked; |
|
712 |
- this.inDeptMemberList.forEach((inDeptMember) => { |
|
713 |
- inDeptMember.selected = isChecked; // 전체 선택/해제 기능 |
|
714 |
- }); |
|
715 |
- }, |
|
716 |
- |
|
717 |
- // 부서 수정 |
|
718 |
- async updateDepartment() { |
|
719 |
- const vm = this; |
|
720 |
- if ( |
|
721 |
- JSON.stringify(vm.departmentData) === |
|
722 |
- JSON.stringify(vm.originaldepartmentData) |
|
723 |
- ) { |
|
724 |
- vm.$showAlert("부서 수정", "수정된 정보가 없습니다."); |
|
725 |
- return; |
|
726 |
- } |
|
727 |
- axios |
|
728 |
- .put("/department", vm.departmentData) |
|
729 |
- .then((response) => { |
|
730 |
- vm.$showAlert("부서 수정", "부서 정보가 수정되었습니다."); |
|
731 |
- vm.resetForm(); |
|
732 |
- |
|
733 |
- vm.selectDepartments(); // 부서 리스트 재조회 |
|
734 |
- }) |
|
735 |
- .catch((error) => { |
|
736 |
- vm.$showAlert( |
|
737 |
- "에러 발생", |
|
738 |
- "에러가 발생했습니다. 관리자에게 문의해 주세요."); |
|
739 |
- }); |
|
740 |
- }, |
|
741 |
- |
|
742 |
- async deleteDepartments() { |
|
743 |
- const vm = this; |
|
744 |
- |
|
745 |
- axios({ |
|
746 |
- url: `/department`, |
|
747 |
- method: "delete", |
|
748 |
- headers: { |
|
749 |
- "Content-Type": "application/json", |
|
750 |
- }, |
|
751 |
- data: vm.departmentData, |
|
752 |
- }) |
|
753 |
- .then(function (response) { |
|
754 |
- // 삭제가 성공하면 화면에서도 호스트를 제거합니다. |
|
755 |
- if (response.data.resultData.deleteDepartment > 0) { |
|
756 |
- vm.$showAlert("부서 삭제", "선택한 부서가 삭제되었습니다."); |
|
757 |
- vm.selectDepartments(); |
|
758 |
- } else { |
|
759 |
- vm.$showAlert( |
|
760 |
- "부서 삭제", |
|
761 |
- "선택한 부서 삭제에 실패하였습니다. 다시 시도해주세요." |
|
762 |
- ); |
|
763 |
- } |
|
764 |
- }) |
|
765 |
- .catch(function (error) { |
|
766 |
- vm.$showAlert("부서 삭제", "삭제오류, 관리자에게 문의바랍니다."); |
|
767 |
- }); |
|
768 |
- }, |
|
769 |
- |
|
770 |
- // 호스트-부서 연결을 위한 메서드들 |
|
771 |
- // 호스트 연결 모달창 |
|
772 |
- openHostModal: function () { |
|
773 |
- // if (!this.departmentData.dept_code) { |
|
774 |
- // this.$showAlert("호스트 연결", "선택된 부서가 없습니다."); |
|
775 |
- // return; |
|
776 |
- // } |
|
777 |
- |
|
778 |
- this.isHostModalOpen = true; |
|
779 |
- this.hostSearch.searchObjectList.push(this.host_search_data); |
|
780 |
- this.selectHosts(); |
|
781 |
- }, |
|
782 |
- closeHostModal: function () { |
|
783 |
- this.isHostModalOpen = false; |
|
784 |
- this.hosts = []; |
|
785 |
- this.hostIdx = 0; |
|
786 |
- this.hostSearch = this.$getDefaultSerchVO(); |
|
787 |
- this.host_search_data = this.$getDefaultSerchItem(null, "String"); |
|
788 |
- this.selectedHost = null; |
|
789 |
- }, |
|
790 |
- // 호스트 목록 불러오기 |
|
791 |
- selectHosts() { |
|
792 |
- const vm = this; |
|
793 |
- axios({ |
|
794 |
- url: "/host/list", |
|
795 |
- method: "post", |
|
796 |
- headers: {}, |
|
797 |
- data: vm.hostSearch, |
|
798 |
- }) |
|
799 |
- .then(function (response) { |
|
800 |
- vm.hosts = response.data.resultData.hostList; |
|
801 |
- vm.hostSearch.totalRows = response.data.resultData.totalRow; |
|
802 |
- vm.hostIdx = |
|
803 |
- vm.hostSearch.totalRows - |
|
804 |
- (vm.hostSearch.currentPage - 1) * vm.hostSearch.perPage; |
|
805 |
- // 이미 부서에 등록된 호스트는 빠지게 |
|
806 |
- if (vm.depthDepth === 0) { |
|
807 |
- vm.hosts = vm.hosts.filter( |
|
808 |
- (host) => |
|
809 |
- !vm.deptHostData.some( |
|
810 |
- (deptHost) => deptHost.host_code === host.host_code |
|
811 |
- ) |
|
812 |
- ); |
|
813 |
- } |
|
814 |
- }) |
|
815 |
- .catch(function (error) { |
|
816 |
- vm.$showAlert( |
|
817 |
- "호스트 목록", |
|
818 |
- "목록 불러오기 오류, 관리자에게 문의바랍니다." |
|
819 |
- ); |
|
820 |
- }); |
|
821 |
- }, |
|
822 |
- |
|
823 |
- // 사용자 연결 모달창 |
|
824 |
- openMemberModal: function () { |
|
825 |
- if (!this.departmentData.dept_code) { |
|
826 |
- this.$showAlert("호스트 연결", "선택된 부서가 없습니다."); |
|
827 |
- return; |
|
694 |
+ // 부서코드 유효성 검사 |
|
695 |
+ validationDeptCode() { |
|
696 |
+ // 부서코드 null 검사 |
|
697 |
+ if (this.$isEmpty(this.currentDept.dept_code)) { |
|
698 |
+ this.$showAlert("부서 등록", "부서코드를 입력해주세요."); |
|
699 |
+ return false; |
|
828 | 700 |
} |
829 | 701 |
|
830 |
- this.isMemberModalOpen = true; |
|
831 |
- this.usersSearch.searchObjectList.push(this.search_data1); |
|
832 |
- this.usersSearch.searchObjectList.push(this.search_data2); |
|
833 |
- this.selectUsers(); |
|
834 |
- }, |
|
835 |
- closeMemberModal: function () { |
|
836 |
- this.isMemberModalOpen = false; |
|
837 |
- this.users = []; |
|
838 |
- this.usersIdx = 0; |
|
839 |
- this.usersSearch = this.$getDefaultSerchVO(); |
|
840 |
- this.search_data1 = this.$getDefaultSerchItem(null, "String"); |
|
841 |
- this.search_data2 = this.$getDefaultSerchItem(null, "String"); |
|
842 |
- this.selectedUsers = null; |
|
843 |
- }, |
|
844 |
- |
|
845 |
- // 사용자 목록 불러오기 |
|
846 |
- selectUsers() { |
|
847 |
- const vm = this; |
|
848 |
- vm.usersSearch.searchObjectList = []; |
|
849 |
- if ( |
|
850 |
- vm.departmentData.dept_code != null && |
|
851 |
- vm.departmentData.dept_code != "" |
|
852 |
- ) { |
|
853 |
- vm.search_data1.key = "dept_code"; |
|
854 |
- vm.search_data1.value = vm.departmentData.dept_code; |
|
855 |
- vm.usersSearch.searchObjectList.push(vm.search_data1); |
|
856 |
- } |
|
857 |
- if (vm.search_data2.value != null && vm.search_data2.value != "") { |
|
858 |
- vm.usersSearch.searchObjectList.push(vm.search_data2); |
|
859 |
- vm.usersSearch.currentPage = 1; // 첫 페이지로 초기화 |
|
702 |
+ // 부서코드 숫자만 검사 |
|
703 |
+ if (!/^\d+$/.test(this.currentDept.dept_code)) { |
|
704 |
+ this.$showAlert("부서 등록", "부서코드는 숫자만 입력할 수 있습니다."); |
|
705 |
+ return false; |
|
860 | 706 |
} |
861 | 707 |
|
862 |
- axios({ |
|
863 |
- url: "/member/users", |
|
864 |
- method: "post", |
|
865 |
- headers: {}, |
|
866 |
- data: vm.usersSearch, |
|
867 |
- }) |
|
868 |
- .then(function (response) { |
|
869 |
- vm.users = response.data.resultData.selectMemberList; |
|
870 |
- vm.usersSearch.totalRows = response.data.resultData.totalRow; |
|
871 |
- vm.usersIdx = |
|
872 |
- vm.usersSearch.totalRows - |
|
873 |
- (vm.usersSearch.currentPage - 1) * vm.usersSearch.perPage; |
|
874 |
- }) |
|
875 |
- .catch(function (error) { |
|
876 |
- vm.$showAlert( |
|
877 |
- "사용자 목록", |
|
878 |
- "목록 불러오기 오류, 관리자에게 문의바랍니다." |
|
879 |
- ); |
|
880 |
- }); |
|
708 |
+ return true; |
|
881 | 709 |
}, |
882 |
- addSelectUsers() { |
|
883 |
- const vm = this; |
|
884 |
- axios({ |
|
885 |
- url: "/member/users/add", |
|
886 |
- method: "post", |
|
887 |
- headers: { "Content-Type": "application/json" }, |
|
888 |
- data: JSON.stringify({ users: vm.addusers }), |
|
889 |
- }) |
|
890 |
- .then(function (response) { |
|
891 |
- vm.closeMemberModal(); |
|
892 |
- vm.selectMemberList(); |
|
893 |
- }) |
|
894 |
- .catch(function (error) { |
|
895 |
- vm.$showAlert( |
|
896 |
- "멤버추가 오류", |
|
897 |
- "멤버추가 오류, 관리자에게 문의바랍니다." |
|
898 |
- ); |
|
899 |
- }); |
|
900 |
- }, |
|
901 |
- delSelectUsers() { |
|
902 |
- const vm = this; |
|
903 |
- axios({ |
|
904 |
- url: "/member/users/del", |
|
905 |
- method: "post", |
|
906 |
- headers: { "Content-Type": "application/json" }, |
|
907 |
- data: JSON.stringify({ users: vm.addusers }), |
|
908 |
- }) |
|
909 |
- .then(function (response) { |
|
910 |
- vm.closeMemberModal(); |
|
911 |
- vm.selectMemberList(); |
|
912 |
- }) |
|
913 |
- .catch(function (error) { |
|
914 |
- vm.$showAlert( |
|
915 |
- "멤버추가 오류", |
|
916 |
- "멤버추가 오류, 관리자에게 문의바랍니다." |
|
917 |
- ); |
|
918 |
- }); |
|
919 |
- }, |
|
920 |
- toggleSelectAll(event) { |
|
921 |
- const isChecked = event.target.checked; |
|
922 |
- this.users.forEach((user) => { |
|
923 |
- user.selected = isChecked; // 전체 선택/해제 기능 |
|
924 |
- }); |
|
925 |
- }, |
|
926 |
- async confirmSelection() { |
|
927 |
- this.addusers = this.users |
|
928 |
- .filter((user) => user.selected) // 선택된 사용자 필터링 |
|
929 |
- .map((user) => ({ |
|
930 |
- userId: user.userId, |
|
931 |
- dept_code: this.departmentData.dept_code, |
|
932 |
- })); // 필요한 데이터 추출 |
|
933 |
- const confirmed = await this.$showConfirm( |
|
934 |
- "멤버추가", |
|
935 |
- "선택하신 멤버를 추가하시겠습니까?" |
|
936 |
- ); |
|
937 |
- |
|
938 |
- console.log("!! 1") |
|
939 |
- // 사용자가 확인했을 경우에만 추가 함수 실행 |
|
940 |
- if (confirmed) { |
|
941 |
- console.log("!! 2") |
|
942 |
- this.addSelectUsers(); |
|
943 |
- } |
|
944 |
- }, |
|
945 |
- async deleteSelection() { |
|
946 |
- this.addusers = this.inDeptMemberList |
|
947 |
- .filter((inDeptMember) => inDeptMember.selected) // 선택된 사용자 필터링 |
|
948 |
- .map((inDeptMember) => ({ |
|
949 |
- userId: inDeptMember.userId, |
|
950 |
- dept_code: this.departmentData.dept_code, |
|
951 |
- })); // 필요한 데이터 추출 |
|
952 |
- const deleteSele = await this.$showConfirm( |
|
953 |
- "멤버삭제", |
|
954 |
- "선택하신 멤버를 삭제하시겠습니까?" |
|
955 |
- ); |
|
956 |
- |
|
957 |
- // 사용자가 확인했을 경우에만 추가 함수 실행 |
|
958 |
- if (deleteSele) { |
|
959 |
- this.delSelectUsers(); |
|
960 |
- } |
|
961 |
- }, |
|
962 |
- // 폴더 모달창 열기 |
|
963 |
- selectAndConnect(hostCode) { |
|
964 |
- this.selectedHost = hostCode; |
|
965 |
- this.connectionConfirm("choose"); |
|
966 |
- }, |
|
967 |
- connectionConfirm(type) { |
|
968 |
- const vm = this; |
|
969 |
- vm.connection.host_code = vm.selectedHost || vm.connection.host_code; |
|
970 |
- |
|
971 |
- axios |
|
972 |
- .get("/files/connection", { |
|
973 |
- params: { host_code: vm.connection.host_code }, |
|
974 |
- }) |
|
975 |
- .then((response) => { |
|
976 |
- vm.$showAlert("파일시스템 연결", response.data.message); |
|
977 |
- if (response.data.status === 200) { |
|
978 |
- this.fileTreeList(type); |
|
979 |
- } |
|
980 |
- }) |
|
981 |
- .catch((error) => { |
|
982 |
- vm.$showAlert( |
|
983 |
- "파일시스템 연결", |
|
984 |
- "파일시스템 연결 오류, 관리자에게 문의하세요." |
|
985 |
- ); |
|
986 |
- vm.$router.go(-1); // 오류 시 이전 페이지로 이동 |
|
987 |
- }); |
|
988 |
- }, |
|
989 |
- // 폴더 가져오기 |
|
990 |
- fileTreeList(type) { |
|
991 |
- const vm = this; |
|
992 |
- vm.nodes = []; |
|
993 |
- vm.connection.path = "#"; |
|
994 |
- vm.connection.depth = 0; |
|
995 |
- vm.connection.type = "folder"; |
|
996 |
- |
|
997 |
- axios |
|
998 |
- .get("/files/tree", { params: vm.connection }) |
|
999 |
- .then((response) => { |
|
1000 |
- vm.nodes = response.data.resultData.fileTree; |
|
1001 |
- vm.connection.path = null; |
|
1002 |
- vm.selectedHost = null; |
|
1003 |
- vm.openTreeModal(); |
|
1004 |
- vm.selectModalType = type; |
|
1005 |
- }) |
|
1006 |
- .catch((error) => { |
|
1007 |
- vm.$showAlert( |
|
1008 |
- "파일리스트 조회", |
|
1009 |
- "파일리스트 조회 오류, 관리자에게 문의하세요." |
|
1010 |
- ); |
|
1011 |
- vm.connection.path = null; |
|
1012 |
- vm.selectedHost = null; |
|
1013 |
- vm.closeHostModal(); |
|
1014 |
- }); |
|
1015 |
- }, |
|
1016 |
- openTreeModal() { |
|
1017 |
- this.treeModalOpen = true; |
|
1018 |
- }, |
|
1019 |
- closeTreeModal() { |
|
1020 |
- this.treeModalOpen = false; |
|
1021 |
- this.modalSeletedNode = null; |
|
1022 |
- }, |
|
1023 |
- selectFolder(path) { |
|
1024 |
- this.connection.path = path; |
|
1025 |
- }, |
|
1026 |
- // 폴더 모달창에서 선택한 것으로 삽입 혹은 수정 |
|
1027 |
- async axiosDeptHost(host) { |
|
1028 |
- const vm = this; |
|
1029 |
- if ( |
|
1030 |
- !(await this.$showConfirm("호스트 추가", "호스트 추가하시겠습니까?")) |
|
1031 |
- ) { |
|
1032 |
- return; |
|
1033 |
- } |
|
1034 |
- // if (type === "선택") { |
|
1035 |
- axios({ |
|
1036 |
- url: "/DeptHost", |
|
1037 |
- method: "post", |
|
1038 |
- headers: { |
|
1039 |
- "Content-Type": "application/json", |
|
1040 |
- }, |
|
1041 |
- data: { |
|
1042 |
- dept_code: vm.departmentData.dept_code, |
|
1043 |
- host_code: host.host_code, |
|
1044 |
- main_folder_path: host.path, |
|
1045 |
- }, |
|
1046 |
- }) |
|
1047 |
- .then(function (response) { |
|
1048 |
- if (response.data.resultData.insertDeptHost > 0) { |
|
1049 |
- vm.$showAlert("호스트 추가", "선택한 호스트가 추가되었습니다."); |
|
1050 |
- vm.selectDeptHost(); |
|
1051 |
- } else { |
|
1052 |
- vm.$showAlert( |
|
1053 |
- "호스트 추가", |
|
1054 |
- "선택한 호스트 추가에 실패하였습니다. 다시 시도해주세요." |
|
1055 |
- ); |
|
1056 |
- } |
|
1057 |
- vm.connection.path = null; |
|
1058 |
- vm.closeTreeModal(); |
|
1059 |
- vm.closeHostModal(); |
|
1060 |
- }) |
|
1061 |
- .catch(function (error) { |
|
1062 |
- vm.$showAlert("호스트 추가", "추가오류, 관리자에게 문의바랍니다."); |
|
1063 |
- vm.connection.path = null; |
|
1064 |
- vm.closeTreeModal(); |
|
1065 |
- vm.closeHostModal(); |
|
1066 |
- }); |
|
1067 |
- }, |
|
1068 |
- // 호스트-부서 연결된 데이터 가져오기 |
|
1069 |
- selectDeptHost() { |
|
1070 |
- const vm = this; |
|
1071 |
- vm.dept_search_data.key = "dept_code"; |
|
1072 |
- vm.dept_search_data.value = vm.departmentData.dept_code; |
|
1073 |
- vm.dept_search_data.type = "eq"; |
|
1074 |
- vm.deptSearch.searchObjectList.push(vm.dept_search_data); |
|
1075 |
- |
|
1076 |
- axios({ |
|
1077 |
- url: "/DeptHost/list", |
|
1078 |
- method: "post", |
|
1079 |
- headers: {}, |
|
1080 |
- data: vm.deptSearch, |
|
1081 |
- }) |
|
1082 |
- .then(function (response) { |
|
1083 |
- vm.deptHostData = response.data.resultData.selectDeptHost; |
|
1084 |
- // 상위부서에서 가져온 데이터인지 아닌지 구분 |
|
1085 |
- vm.depthDepth = response.data.resultData.selectDeptHost[0].depth; |
|
1086 |
- }) |
|
1087 |
- .catch(function (error) { }); |
|
1088 |
- }, |
|
1089 |
- // 호스트-부서 연결된 데이터 수정하기 |
|
1090 |
- chooseDeptHost(data, type) { |
|
1091 |
- const vm = this; |
|
1092 |
- if (vm.depthDepth !== 0) { |
|
1093 |
- vm.$showAlert("호스트 수정", "수정할 권한이 없습니다."); |
|
1094 |
- return; |
|
1095 |
- } |
|
1096 |
- vm.connection.host_code = data.host_code; |
|
1097 |
- vm.connectionConfirm(type); |
|
1098 |
- }, |
|
1099 |
- // 호스트-부서 체크박스 일괄 체크 |
|
1100 |
- deptHostCheckAll() { |
|
1101 |
- const vm = this; |
|
1102 |
- vm.deptCheckAll = !vm.deptCheckAll; |
|
1103 |
- vm.selectedDepts = []; |
|
1104 |
- |
|
1105 |
- if (vm.deptCheckAll) { |
|
1106 |
- vm.deptHostData.forEach((data) => { |
|
1107 |
- vm.selectedDepts.push(data.host_code); |
|
1108 |
- }); |
|
1109 |
- } |
|
1110 |
- }, |
|
1111 |
- // 부서 변경 시 체크 해제 |
|
1112 |
- deptHostUncheckAll() { |
|
1113 |
- this.deptCheckAll = null; |
|
1114 |
- this.selectedDepts = []; |
|
1115 |
- }, |
|
1116 |
- // 호스트-부서 삭제 |
|
1117 |
- async deleteSelectedDeptHosts() { |
|
1118 |
- const vm = this; |
|
1119 |
- if (vm.selectedDepts.length === 0) { |
|
1120 |
- vm.$showAlert("호스트 삭제", "선택한 호스트가 없습니다."); |
|
1121 |
- return; |
|
1122 |
- } |
|
1123 |
- if (vm.depthDepth !== 0) { |
|
1124 |
- vm.$showAlert("호스트 삭제", "삭제할 권한이 없습니다."); |
|
1125 |
- return; |
|
1126 |
- } |
|
1127 |
- if ( |
|
1128 |
- !(await vm.$showConfirm( |
|
1129 |
- "호스트삭제", |
|
1130 |
- "선택한 호스트를 삭제하시겠습니까?" |
|
1131 |
- )) |
|
1132 |
- ) { |
|
1133 |
- return; |
|
1134 |
- } |
|
1135 |
- const deptHostsToDelete = vm.selectedDepts.map((host_code) => ({ |
|
1136 |
- dept_code: vm.departmentData.dept_code, |
|
1137 |
- host_code: host_code, |
|
1138 |
- })); |
|
1139 |
- |
|
1140 |
- axios({ |
|
1141 |
- url: "/DeptHost", |
|
1142 |
- method: "delete", |
|
1143 |
- headers: { |
|
1144 |
- "Content-Type": "application/json", |
|
1145 |
- }, |
|
1146 |
- data: deptHostsToDelete, |
|
1147 |
- }) |
|
1148 |
- .then(function (response) { |
|
1149 |
- if (response.data.resultData.deleteResult > 0) { |
|
1150 |
- vm.$showAlert("호스트 삭제", "선택한 호스트가 삭제되었습니다."); |
|
1151 |
- vm.deptCheckAll = false; |
|
1152 |
- vm.selectedDepts = []; |
|
1153 |
- vm.selectDeptHost(); |
|
1154 |
- } else { |
|
1155 |
- vm.$showAlert( |
|
1156 |
- "호스트 삭제", |
|
1157 |
- "선택한 호스트 삭제에 실패하였습니다. 다시 시도해주세요." |
|
1158 |
- ); |
|
1159 |
- } |
|
1160 |
- }) |
|
1161 |
- .catch(function (error) { |
|
1162 |
- vm.$showAlert("호스트 삭제", "삭제오류, 관리자에게 문의바랍니다."); |
|
1163 |
- }); |
|
1164 |
- }, |
|
1165 |
- }, |
|
1166 |
- watch: { |
|
1167 |
- departmentData: { |
|
1168 |
- handler: "selectDeptHost", |
|
1169 |
- }, |
|
1170 |
- //부서코드 값 변경 시 중복체크여부 false로 변경 |
|
1171 |
- "departmentData.dept_code": function (newVal, oldVal) { |
|
1172 |
- this.isDuplicateChecked = false; |
|
1173 |
- }, |
|
1174 |
- }, |
|
1175 |
- components: { |
|
1176 |
- PageNavigation: PageNavigation, |
|
1177 |
- SvgIcon: SvgIcon, |
|
1178 |
- PaginationButton: PaginationButton, |
|
1179 |
- DepartmentTree: DepartmentTree, |
|
1180 |
- TreeModal: TreeModal, |
|
1181 |
- }, |
|
1182 |
- mounted() { |
|
1183 |
- this.getAuthorList(); |
|
1184 |
- this.selectDepartments(); |
|
1185 |
- this.deptSearchInit(); |
|
1186 | 710 |
}, |
1187 | 711 |
}; |
1188 | 712 |
</script>(No newline at end of file) |
+++ client/views/pages/integrated/department/DeptHostList.vue
... | ... | @@ -0,0 +1,298 @@ |
1 | +<template> | |
2 | + <div class="table-zone"> | |
3 | + <div class="list-info flex justify-between align-center"> | |
4 | + <div class="count-zone"> | |
5 | + <p> 총 <span>{{ list.length }}</span>건 중 <span>{{ selectedList.length }}</span>건 선택 </p> | |
6 | + </div> | |
7 | + <div class="cunt-selectZone"> | |
8 | + <select v-model="search.perPage" @change="fnSelectList"> | |
9 | + <option value="10">10개 보기</option> | |
10 | + <option value="20">20개 보기</option> | |
11 | + </select> | |
12 | + </div> | |
13 | + </div> | |
14 | + <table class="list-table"> | |
15 | + <colgroup> | |
16 | + <col style="width: 5%" /> | |
17 | + <col style="width: 10%" /> | |
18 | + <col style="width: 42.5%" /> | |
19 | + <col style="width: 42.5%" /> | |
20 | + </colgroup> | |
21 | + <thead> | |
22 | + <tr> | |
23 | + <th> | |
24 | + <input type="checkbox" v-model="isChkUserAll" @change="fnChkAll()" /> | |
25 | + </th> | |
26 | + <th>No</th> | |
27 | + <th>호스트명</th> | |
28 | + <th>메인폴더</th> | |
29 | + </tr> | |
30 | + </thead> | |
31 | + <tbody> | |
32 | + <template v-if="list.length > 0"> | |
33 | + <tr v-for="(item, idx) of list" :key="idx"> | |
34 | + <td> | |
35 | + <input type="checkbox" :value="item" v-model="selectedList" @click.stop="" @change="fnChangeChk" /> | |
36 | + </td> | |
37 | + <td>{{ search.totalRows - idx - (search.currentPage - 1) * search.perPage }}</td> | |
38 | + <td>{{ item.hostNm }}</td> | |
39 | + <td>{{ item.mainFolderPath }}</td> | |
40 | + </tr> | |
41 | + </template> | |
42 | + <tr v-else> | |
43 | + <td colspan="4">등록된 데이터가 없습니다.</td> | |
44 | + </tr> | |
45 | + </tbody> | |
46 | + </table> | |
47 | + <PaginationButton v-model:currentPage="search.currentPage" :perPage="search.perPage" :totalCount="search.totalRows" :maxRange="5" :click="selectDeptHost" /> | |
48 | + </div> | |
49 | + <div class="flex justify-end"> | |
50 | + <button class="blue-btn small-btn" @click="fnOpenModal">호스트추가</button> | |
51 | + <button class="red-border-btn small-btn" @click="fnDelete">호스트삭제</button> | |
52 | + </div> | |
53 | + <!-- 호스트 추가 모달 --> | |
54 | + <div v-show="isModalOpen" class="modal-wrapper"> | |
55 | + <div class="modal-container"> | |
56 | + <div class="modal-title flex justify-between align-center"> | |
57 | + <h2>호스트 추가</h2> | |
58 | + <button class="close-btn" @click="fnCloseModal"> | |
59 | + <svg-icon type="mdi" :width="20" :height="20" :path="closePath"></svg-icon> | |
60 | + </button> | |
61 | + </div> | |
62 | + <div class="modal-content-monthly"> | |
63 | + <div class="search-bar flex justify-between align-center mb10"> | |
64 | + <div class="flex25 pl0"> | |
65 | + <select class="square-select full-select" v-model="modalSearchData.key"> | |
66 | + <option :value="null">전체</option> | |
67 | + <option value="host_nm">호스트명</option> | |
68 | + <option value="host_ip">호스트(IP)</option> | |
69 | + <option value="rgtr_id">등록자</option> | |
70 | + </select> | |
71 | + </div> | |
72 | + <div class="flex75 flex align-center no-gutter pr0"> | |
73 | + <input type="text" class="square-input flex90" placeholder="검색어를 입력해주세요." v-model="modalSearchData.value" @keyup.enter="fnSelectUserList" /> | |
74 | + <button class="square-button blue-btn flex10" @click="fnSelectUserList"> | |
75 | + <svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon> | |
76 | + </button> | |
77 | + </div> | |
78 | + </div> | |
79 | + <div> | |
80 | + <table class="list-table2"> | |
81 | + <colgroup> | |
82 | + <col style="width: 10%" /> | |
83 | + <col style="width: 20%" /> | |
84 | + <col style="width: 20%" /> | |
85 | + <col style="width: 20%" /> | |
86 | + <col style="width: 20%" /> | |
87 | + <col style="width: 10%" /> | |
88 | + </colgroup> | |
89 | + <thead> | |
90 | + <tr> | |
91 | + <th>No</th> | |
92 | + <th>호스트명</th> | |
93 | + <th>호스트(IP)</th> | |
94 | + <th>사용자명</th> | |
95 | + <th>포트</th> | |
96 | + <th>선택</th> | |
97 | + </tr> | |
98 | + </thead> | |
99 | + <tbody class="overflow-y" style="max-height: 500px"> | |
100 | + <template v-if="modalList.length > 0"> | |
101 | + <tr v-for="(item, idx) in modalList" :key="idx"> | |
102 | + <td>{{ modalSearch.totalRows - idx - (modalSearch.currentPage - 1) * modalSearch.perPage }}</td> | |
103 | + <td>{{ item.host_nm }}</td> | |
104 | + <td>{{ item.host_ip }}</td> | |
105 | + <td>{{ item.host_id }}</td> | |
106 | + <td>{{ item.host_port }}</td> | |
107 | + <td><button type="button" class="blue-border-btn set-btn" @click="fnAddUser(item.hostCode)">선택</button></td> | |
108 | + </tr> | |
109 | + </template> | |
110 | + <tr v-else> | |
111 | + <td colspan="6">등록된 데이터가 없습니다.</td> | |
112 | + </tr> | |
113 | + </tbody> | |
114 | + </table> | |
115 | + <PaginationButton v-model:currentPage="modalSearch.currentPage" :perPage="modalSearch.perPage" :totalCount="modalSearch.totalRows" :click="fnSelectUserList" /> | |
116 | + </div> | |
117 | + </div> | |
118 | + </div> | |
119 | + </div> | |
120 | +</template> | |
121 | +<script> | |
122 | +import axios from "axios"; | |
123 | +// icon용 svg import | |
124 | +import SvgIcon from "@jamescoyle/vue-icon"; | |
125 | +import { mdiMagnify, mdiClose } from "@mdi/js"; | |
126 | +// 컴포넌트 import | |
127 | +import PageNavigation from "../../../component/PageNavigation.vue"; | |
128 | +import PaginationButton from "../../../component/PaginationButton.vue"; | |
129 | + | |
130 | +export default { | |
131 | + components: { SvgIcon, PageNavigation, PaginationButton }, | |
132 | + | |
133 | + props: { | |
134 | + deptCode: { | |
135 | + type: String, | |
136 | + default: null, | |
137 | + }, | |
138 | + }, | |
139 | + | |
140 | + data() { | |
141 | + return { | |
142 | + // icon용 svg path | |
143 | + searchPath: mdiMagnify, | |
144 | + closePath: mdiClose, | |
145 | + | |
146 | + // 목록 | |
147 | + list: [], | |
148 | + isChkUserAll: false, // 전체 선택 여부 | |
149 | + selectedList: [], // 선택 항목 목록 | |
150 | + search: Object.assign({}, this.$getDefaultSerchVO()), | |
151 | + searchData: Object.assign({}, this.$getDefaultSerchItem(null, "string")), | |
152 | + | |
153 | + // 추가 모달 | |
154 | + isModalOpen: false, | |
155 | + selectHostList: [], | |
156 | + | |
157 | + // 검색용 | |
158 | + modalSearch: Object.assign({}, this.$getDefaultSerchVO()), | |
159 | + modalSearchData: Object.assign({}, this.$getDefaultSerchItem(null, "string")), | |
160 | + | |
161 | + // 목록용 | |
162 | + modalList: [], | |
163 | + } | |
164 | + }, | |
165 | + | |
166 | + watch: { | |
167 | + deptCode(v) { | |
168 | + this.fnSelectList(); | |
169 | + }, | |
170 | + }, | |
171 | + | |
172 | + methods: { | |
173 | + // 목록 조회 | |
174 | + fnSelectList() { | |
175 | + const vm = this; | |
176 | + // 데이터 세팅 | |
177 | + vm.search.searchObjectList = []; | |
178 | + vm.search.searchObjectList.push(vm.searchData); | |
179 | + // 실행 | |
180 | + axios({ | |
181 | + url: "/deptHost/list/" + vm.deptCode, | |
182 | + method: "post", | |
183 | + headers: { "Content-Type": "application/json; charset=UTF-8" }, | |
184 | + data: vm.search, | |
185 | + }) | |
186 | + .then(response => { | |
187 | + vm.list = response.data.resultData.list; | |
188 | + vm.search = response.data.resultData.searchVO; | |
189 | + }) | |
190 | + .catch(error => { | |
191 | + vm.$showAlert("호스트 목록", "목록 불러오기 오류, 관리자에게 문의바랍니다."); | |
192 | + }); | |
193 | + }, | |
194 | + | |
195 | + // 목록 전체 선택 | |
196 | + fnChkAll() { | |
197 | + if (this.isChkUserAll) { | |
198 | + this.selectedList = this.list; | |
199 | + } else { | |
200 | + this.selectedList = []; | |
201 | + } | |
202 | + }, | |
203 | + | |
204 | + // 목록 상세 선택 | |
205 | + fnChangeChk() { | |
206 | + if (this.selectedList.length == this.list.length) { | |
207 | + this.isChkUserAll = true; | |
208 | + } else { | |
209 | + this.isChkUserAll = false; | |
210 | + } | |
211 | + }, | |
212 | + | |
213 | + // 호스트 삭제 | |
214 | + fnDelete() { | |
215 | + const vm = this; | |
216 | + // 실행 | |
217 | + axios({ | |
218 | + url: "/deptHost", | |
219 | + method: "delete", | |
220 | + headers: { "Content-Type": "application/json; charset=UTF-8" }, | |
221 | + data: vm.selectedList, | |
222 | + }) | |
223 | + .then(response => { | |
224 | + vm.$showAlert("작업 성공", "삭제에 성공했습니다."); | |
225 | + vm.fnSelectList(); // 목록 조회 | |
226 | + }) | |
227 | + .catch(error => { | |
228 | + vm.$showAlert("작업 실패", "삭제에 실패했습니다.\n관리자에게 문의바랍니다."); | |
229 | + }); | |
230 | + }, | |
231 | + | |
232 | + | |
233 | + // **** 추가용 모달 | |
234 | + // 추가용 모달 열기 | |
235 | + fnOpenModal() { | |
236 | + this.fnSelectUserList(); | |
237 | + // 모달 열기 | |
238 | + this.isModalOpen = true; | |
239 | + }, | |
240 | + // 추가용 모달 닫기 | |
241 | + fnCloseModal() { | |
242 | + // 초기화 | |
243 | + this.search = Object.assign({}, this.$getDefaultSerchVO()); | |
244 | + this.modalSearchData = Object.assign({}, this.$getDefaultSerchItem(null, "string")); | |
245 | + this.modalList = []; // 목록 | |
246 | + // 모달 닫기 | |
247 | + this.isModalOpen = false; | |
248 | + }, | |
249 | + | |
250 | + // 모달 목록 조회 | |
251 | + fnSelectUserList() { | |
252 | + const vm = this; | |
253 | + | |
254 | + // 데이터 세팅 | |
255 | + vm.modalSearch.searchObjectList = []; // 초기화 | |
256 | + vm.modalSearch.searchObjectList.push(vm.modalSearchData); | |
257 | + | |
258 | + // 실행 | |
259 | + axios({ | |
260 | + url: "/host/list/" + vm.deptCode, | |
261 | + method: "post", | |
262 | + headers: { "Content-Type": "application/json; charset=UTF-8" }, | |
263 | + data: vm.modalSearch, | |
264 | + }) | |
265 | + .then(response => { | |
266 | + vm.modalSearch = response.data.resultData.searchVO; | |
267 | + vm.modalList = response.data.resultData.list; | |
268 | + }) | |
269 | + .catch(error => { | |
270 | + vm.$showAlert("관리", "목록 불러오기 오류, 관리자에게 문의바랍니다."); | |
271 | + }); | |
272 | + }, | |
273 | + | |
274 | + // 모달용 호스트 추가 (선택 버튼 동작) | |
275 | + fnAddUser(hostCode) { | |
276 | + const vm = this; | |
277 | + // 데이터 세팅 | |
278 | + let deptHost = { | |
279 | + hostCode: hostCode, | |
280 | + deptCode: this.deptCode | |
281 | + } | |
282 | + // 실행 | |
283 | + axios({ | |
284 | + url: "/deptHost", | |
285 | + method: "post", | |
286 | + headers: { "Content-Type": "application/json" }, | |
287 | + data: deptHost, | |
288 | + }) | |
289 | + .then(response => { | |
290 | + vm.$showAlert("추가", "사용자를 추가했습니다."); | |
291 | + }) | |
292 | + .catch(error => { | |
293 | + vm.$showAlert("오류", "부서 내 추가 오류, 관리자에게 문의바랍니다."); | |
294 | + }); | |
295 | + }, | |
296 | + } | |
297 | +} | |
298 | +</script>(No newline at end of file) |
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?