
--- client/resources/api/cmmnCode.js
... | ... | @@ -1,6 +0,0 @@ |
1 | -import apiClient from "./index"; | |
2 | - | |
3 | -// 조회 - 목록 | |
4 | -export const findCodeListProc = data => { | |
5 | - return apiClient.post('/system/cmmnCode/findCodeList.json', data); | |
6 | -}(파일 끝에 줄바꿈 문자 없음) |
+++ client/resources/api/code.js
... | ... | @@ -0,0 +1,21 @@ |
1 | +import apiClient from "./index"; | |
2 | + | |
3 | +// 등록 | |
4 | +export const saveCodeProc = data => { | |
5 | + return apiClient.post('/code/saveCode.json', data); | |
6 | +} | |
7 | + | |
8 | +// 목록 조회 | |
9 | +export const findCodesProc = data => { | |
10 | + return apiClient.get('/code/findCodes.json', { params: data }); | |
11 | +} | |
12 | + | |
13 | +// 상세 조회 | |
14 | +export const findCodeProc = data => { | |
15 | + return apiClient.get(`/code/${data}/findCode.json`); | |
16 | +} | |
17 | + | |
18 | +// 수정 | |
19 | +export const updateCodeProc = (id, data) => { | |
20 | + return apiClient.put(`/code/${id}/updateCode.json`, data); | |
21 | +}(파일 끝에 줄바꿈 문자 없음) |
--- client/resources/api/sanctns.js
+++ client/resources/api/sanctns.js
... | ... | @@ -1,5 +1,10 @@ |
1 | 1 |
import apiClient from "./index"; |
2 | 2 |
|
3 |
+// 결재 요청 목록 조회 |
|
4 |
+export const findMyRequestsProc = data => { |
|
5 |
+ return apiClient.get('/sanctn/findMyRequests.json', { params: data }); |
|
6 |
+} |
|
7 |
+ |
|
3 | 8 |
// 조회 - 목록 |
4 | 9 |
export const findSanctnsProc = data => { |
5 | 10 |
return apiClient.get('/sanctn/findSanctns.json', { params: data }); |
--- client/resources/js/cmmnPlugin.js
+++ client/resources/js/cmmnPlugin.js
... | ... | @@ -1,5 +1,5 @@ |
1 | 1 |
import store from '../../views/pages/AppStore' |
2 |
-import { findCodeListProc } from '../api/cmmnCode' |
|
2 |
+import { findCodeListProc } from '../api/code' |
|
3 | 3 |
|
4 | 4 |
export default { |
5 | 5 |
install(Vue) { |
--- client/views/component/Pagenation.vue
+++ client/views/component/Pagination.vue
No changes |
--- client/views/component/Popup/CodePopup.vue
... | ... | @@ -1,118 +0,0 @@ |
1 | -<template> | |
2 | - <div class="popup-overlay" @click.self="$emit('close')"> | |
3 | - <div class="popup-content"> | |
4 | - <div class="card"> | |
5 | - <div class="card-body"> | |
6 | - <h2 class="card-title">코드 목록</h2> | |
7 | - <div class="sch-form-wrap"> | |
8 | - <div class="input-group"> | |
9 | - <select name="" id="" class="form-select"> | |
10 | - <option value="">전체</option> | |
11 | - <option value="">상위코드</option> | |
12 | - <option value="">상위코드명</option> | |
13 | - <option value="">코드</option> | |
14 | - <option value="">코드명</option> | |
15 | - </select> | |
16 | - <div class="sch-input"> | |
17 | - <input type="text" class="form-control"> | |
18 | - <button class="ico-sch"><SearchOutlined /></button> | |
19 | - </div> | |
20 | - </div> | |
21 | - </div> | |
22 | - | |
23 | - <!-- Table --> | |
24 | - <div class="tbl-wrap"> | |
25 | - <table id="myTable" class="tbl data"> | |
26 | - <!-- 동적으로 <th> 생성 --> | |
27 | - <thead> | |
28 | - <tr> | |
29 | - <th>상위코드 </th> | |
30 | - <th>상위코드명</th> | |
31 | - <th>코드</th> | |
32 | - <th>코드명</th> | |
33 | - <th>선택</th> | |
34 | - </tr> | |
35 | - </thead> | |
36 | - <!-- 동적으로 <td> 생성 --> | |
37 | - <tbody> | |
38 | - <tr v-for="(item, index) in popuplistData" :key="index"> | |
39 | - <td>{{ item.parentCode }}</td> | |
40 | - <td>{{ item.parentCodeName }}</td> | |
41 | - <td>{{ item.code }}</td> | |
42 | - <td>{{ item.codeName }}</td> | |
43 | - <td> | |
44 | - <button | |
45 | - type="button" | |
46 | - class="btn sm sm secondary" | |
47 | - @click="selectPerson(item)" | |
48 | - > | |
49 | - 선택 | |
50 | - </button> | |
51 | - </td> | |
52 | - </tr> | |
53 | - </tbody> | |
54 | - </table> | |
55 | - | |
56 | - </div> | |
57 | - <div class="pagination"> | |
58 | - <ul> | |
59 | - <!-- 왼쪽 화살표 (이전 페이지) --> | |
60 | - <li class="arrow" :class="{ disabled: currentPage === 1 }" | |
61 | - @click="changePage(currentPage - 1)"> | |
62 | - < | |
63 | - </li> | |
64 | - | |
65 | - <!-- 페이지 번호 --> | |
66 | - <li v-for="page in totalPages" :key="page" :class="{ active: currentPage === page }" | |
67 | - @click="changePage(page)"> | |
68 | - {{ page }} | |
69 | - </li> | |
70 | - | |
71 | - <!-- 오른쪽 화살표 (다음 페이지) --> | |
72 | - <li class="arrow" :class="{ disabled: currentPage === totalPages }" | |
73 | - @click="changePage(currentPage + 1)"> | |
74 | - > | |
75 | - </li> | |
76 | - </ul> | |
77 | - </div> | |
78 | - <!-- End Table --> | |
79 | - </div> | |
80 | - </div> | |
81 | - <button @click="$emit('close')" class="close-btn"> | |
82 | - <CloseCircleFilled /> | |
83 | - </button> | |
84 | - </div> | |
85 | - </div> | |
86 | -</template> | |
87 | -<script> | |
88 | -import { SearchOutlined, CloseCircleFilled } from '@ant-design/icons-vue'; | |
89 | - | |
90 | -export default { | |
91 | - data() { | |
92 | - return { | |
93 | - popuplistData: [ | |
94 | - { | |
95 | - parentCode: '상위코드1', | |
96 | - parentCodeName: '상위코드명1', | |
97 | - code: '코드1', | |
98 | - codeName: '코드명1' | |
99 | - }, | |
100 | - ], | |
101 | - } | |
102 | - }, | |
103 | - components: { | |
104 | - SearchOutlined, CloseCircleFilled | |
105 | - }, | |
106 | - methods: { | |
107 | - selectPerson(item) { | |
108 | - this.$emit('select', item); // 부모에게 데이터 전달 | |
109 | - }, | |
110 | - | |
111 | - } | |
112 | -} | |
113 | -</script> | |
114 | -<style scoped> | |
115 | -.popup-content { | |
116 | - width: 50%; | |
117 | -} | |
118 | -</style>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/component/Popup/CodeSelectorModal.vue
... | ... | @@ -0,0 +1,167 @@ |
1 | +<template> | |
2 | + <div class="popup-overlay"> | |
3 | + <div class="popup-content"> | |
4 | + <div class="card"> | |
5 | + <div class="card-body"> | |
6 | + <h2 class="card-title">공통코드 목록</h2> | |
7 | + <div class="sch-form-wrap"> | |
8 | + <div class="input-group"> | |
9 | + <select name="searchType" id="searchType" class="form-select" v-model="searchParams.searchType"> | |
10 | + <option value="">전체</option> | |
11 | + <option v-for="(item, index) of searchOptions" :key="index" :value="item.key"> {{ item.label }} </option> | |
12 | + </select> | |
13 | + <div class="sch-input"> | |
14 | + <input type="text" class="form-control" v-model="searchParams.searchText" @keyup.enter="handleSearch" placeholder="검색어를 입력하세요"> | |
15 | + <button class="ico-sch" @click="handleSearch" type="button"> | |
16 | + <SearchOutlined /> | |
17 | + </button> | |
18 | + </div> | |
19 | + </div> | |
20 | + </div> | |
21 | + <div class="tbl-wrap"> | |
22 | + <table class="tbl data"> | |
23 | + <colgroup> | |
24 | + <col style="width: 23%;"> | |
25 | + <col style="width: 23%;"> | |
26 | + <col style="width: 23%;"> | |
27 | + <col style="width: 23%;"> | |
28 | + <col style="width: 8%;"> | |
29 | + </colgroup> | |
30 | + <thead> | |
31 | + <tr> | |
32 | + <th>상위코드</th> | |
33 | + <th>상위코드명</th> | |
34 | + <th>코드</th> | |
35 | + <th>코드명</th> | |
36 | + <th>선택</th> | |
37 | + </tr> | |
38 | + </thead> | |
39 | + <tbody> | |
40 | + <template v-if="codeList.length > 0"> | |
41 | + <tr v-for="(item, index) in codeList" :key="index"> | |
42 | + <td>{{ item.upperCode || '-' }}</td> | |
43 | + <td>{{ item.upperCodeNm || '-' }}</td> | |
44 | + <td>{{ item.code }}</td> | |
45 | + <td>{{ item.codeNm }}</td> | |
46 | + <td> | |
47 | + <button type="button" class="btn sm secondary" @click="handleCodeSelect(item)"> 선택 </button> | |
48 | + </td> | |
49 | + </tr> | |
50 | + </template> | |
51 | + <tr v-else> | |
52 | + <td colspan="5" class="text-center">검색 결과가 없습니다.</td> | |
53 | + </tr> | |
54 | + </tbody> | |
55 | + </table> | |
56 | + </div> | |
57 | + <Pagination :search="searchParams" @onChange="handlePageChange" /> | |
58 | + </div> | |
59 | + </div> | |
60 | + <button @click="handleModalClose" class="close-btn" type="button"> | |
61 | + <CloseCircleFilled /> | |
62 | + </button> | |
63 | + </div> | |
64 | + </div> | |
65 | +</template> | |
66 | +<script> | |
67 | +import { SearchOutlined, CloseCircleFilled } from '@ant-design/icons-vue'; | |
68 | +import Pagination from "../Pagination.vue"; | |
69 | +// API | |
70 | +import { findCodesProc } from "../../../resources/api/code"; | |
71 | + | |
72 | +export default { | |
73 | + name: 'CodeSelectorModal', | |
74 | + | |
75 | + components: { | |
76 | + SearchOutlined, | |
77 | + CloseCircleFilled, | |
78 | + Pagination, | |
79 | + }, | |
80 | + | |
81 | + props: { | |
82 | + currentCodeId: { | |
83 | + type: String, | |
84 | + default: null | |
85 | + }, | |
86 | + }, | |
87 | + | |
88 | + emits: ['select', 'close'], | |
89 | + | |
90 | + data() { | |
91 | + return { | |
92 | + codeList: [], | |
93 | + | |
94 | + searchOptions: [ | |
95 | + { key: "UPPER_CODE", label: "상위코드" }, | |
96 | + { key: "UPPERCODE_NAME", label: "상위코드 이름" }, | |
97 | + { key: "CODE", label: "코드" }, | |
98 | + { key: "CODE_NAME", label: "코드 이름" }, | |
99 | + ], | |
100 | + | |
101 | + searchParams: { | |
102 | + searchType: '', | |
103 | + searchText: '', | |
104 | + recordSize: 5, | |
105 | + pageSize: 5, | |
106 | + currentPage: 1, | |
107 | + currentCodeId: this.currentCodeId, // 백엔드에서 제외할 코드ID | |
108 | + } | |
109 | + } | |
110 | + }, | |
111 | + | |
112 | + mounted() { | |
113 | + this.fetchCodeList(); | |
114 | + }, | |
115 | + | |
116 | + methods: { | |
117 | + // 코드 목록 조회 | |
118 | + async fetchCodeList() { | |
119 | + try { | |
120 | + const response = await findCodesProc(this.searchParams); | |
121 | + const result = response.data.data; | |
122 | + | |
123 | + this.codeList = result.codes; | |
124 | + this.searchParams = result.search; | |
125 | + } catch (error) { | |
126 | + this.handleError(error); | |
127 | + } | |
128 | + }, | |
129 | + | |
130 | + // 검색 실행 | |
131 | + handleSearch() { | |
132 | + this.searchParams.currentPage = 1; | |
133 | + this.fetchCodeList(); | |
134 | + }, | |
135 | + | |
136 | + // 페이지 변경 | |
137 | + handlePageChange(currentPage) { | |
138 | + this.searchParams.currentPage = Number(currentPage); | |
139 | + this.$nextTick(() => { | |
140 | + this.fetchCodeList(); | |
141 | + }); | |
142 | + }, | |
143 | + | |
144 | + // 코드 선택 | |
145 | + handleCodeSelect(selectedCode) { | |
146 | + this.$emit('select', selectedCode); | |
147 | + }, | |
148 | + | |
149 | + // 모달 닫기 | |
150 | + handleModalClose() { | |
151 | + this.$emit('close'); | |
152 | + }, | |
153 | + | |
154 | + // 에러 처리 | |
155 | + handleError(error) { | |
156 | + const message = error.response?.data?.message || "에러가 발생했습니다."; | |
157 | + alert(message); | |
158 | + console.error(error.message); | |
159 | + }, | |
160 | + }, | |
161 | +} | |
162 | +</script> | |
163 | +<style scoped> | |
164 | +.popup-content { | |
165 | + width: 50%; | |
166 | +} | |
167 | +</style>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/component/Popup/CorpCarPopup.vue
+++ client/views/component/Popup/CorpCarPopup.vue
... | ... | @@ -34,7 +34,7 @@ |
34 | 34 |
</tbody> |
35 | 35 |
</table> |
36 | 36 |
</div> |
37 |
- <Pagenation :search="request" @onChange="fnChangeCurrentPage" /> |
|
37 |
+ <Pagination :search="request" @onChange="fnChangeCurrentPage" /> |
|
38 | 38 |
</div> |
39 | 39 |
</div> |
40 | 40 |
<button @click="$emit('close')" class="close-btn"> |
... | ... | @@ -45,14 +45,14 @@ |
45 | 45 |
</template> |
46 | 46 |
<script> |
47 | 47 |
import { SearchOutlined, CloseCircleFilled } from '@ant-design/icons-vue'; |
48 |
-import Pagenation from '../Pagenation.vue'; |
|
48 |
+import Pagination from '../Pagination.vue'; |
|
49 | 49 |
// API |
50 | 50 |
import { findAllAsSetVhcle } from '../../../resources/api/asset' |
51 | 51 |
|
52 | 52 |
export default { |
53 | 53 |
components: { |
54 | 54 |
SearchOutlined, CloseCircleFilled, |
55 |
- Pagenation |
|
55 |
+ Pagination |
|
56 | 56 |
}, |
57 | 57 |
|
58 | 58 |
props: { |
--- client/views/component/Popup/CorpCardPopup.vue
+++ client/views/component/Popup/CorpCardPopup.vue
... | ... | @@ -32,7 +32,7 @@ |
32 | 32 |
</tbody> |
33 | 33 |
</table> |
34 | 34 |
</div> |
35 |
- <Pagenation :search="request" @onChange="fnChangeCurrentPage" /> |
|
35 |
+ <Pagination :search="request" @onChange="fnChangeCurrentPage" /> |
|
36 | 36 |
</div> |
37 | 37 |
</div> |
38 | 38 |
<button @click="$emit('close')" class="close-btn"> |
... | ... | @@ -43,14 +43,14 @@ |
43 | 43 |
</template> |
44 | 44 |
<script> |
45 | 45 |
import { SearchOutlined, CloseCircleFilled } from '@ant-design/icons-vue'; |
46 |
-import Pagenation from '../Pagenation.vue'; |
|
46 |
+import Pagination from '../Pagination.vue'; |
|
47 | 47 |
// API |
48 | 48 |
import { findAllAsSetCard } from '../../../resources/api/asset' |
49 | 49 |
|
50 | 50 |
export default { |
51 | 51 |
components: { |
52 | 52 |
SearchOutlined, CloseCircleFilled, |
53 |
- Pagenation, |
|
53 |
+ Pagination, |
|
54 | 54 |
}, |
55 | 55 |
|
56 | 56 |
props: { |
--- client/views/component/Popup/HrPopup.vue
+++ client/views/component/Popup/HrPopup.vue
... | ... | @@ -38,7 +38,7 @@ |
38 | 38 |
</tbody> |
39 | 39 |
</table> |
40 | 40 |
</div> |
41 |
- <Pagenation :search="request" @onChange="fnChangeCurrentPage" /> |
|
41 |
+ <Pagination :search="request" @onChange="fnChangeCurrentPage" /> |
|
42 | 42 |
</div> |
43 | 43 |
</div> |
44 | 44 |
<button @click="$emit('close')" class="close-btn"> |
... | ... | @@ -49,14 +49,14 @@ |
49 | 49 |
</template> |
50 | 50 |
<script> |
51 | 51 |
import { SearchOutlined, CloseCircleFilled } from '@ant-design/icons-vue'; |
52 |
-import Pagenation from '../Pagenation.vue'; |
|
52 |
+import Pagination from '../Pagination.vue'; |
|
53 | 53 |
// API |
54 | 54 |
import { findUsersProc } from '../../../resources/api/user'; |
55 | 55 |
|
56 | 56 |
export default { |
57 | 57 |
components: { |
58 | 58 |
SearchOutlined, CloseCircleFilled, |
59 |
- Pagenation |
|
59 |
+ Pagination |
|
60 | 60 |
}, |
61 | 61 |
|
62 | 62 |
props: { |
--- client/views/pages/AppRouter.js
+++ client/views/pages/AppRouter.js
... | ... | @@ -63,9 +63,9 @@ |
63 | 63 |
//시스템관리 |
64 | 64 |
import AuthorManagementComp from '../pages/Manager/system/AuthorManagement.vue'; |
65 | 65 |
import MenuAuthorManagementComp from './Manager/system/MenuAuthorManagement.vue'; |
66 |
-import commonCodeManagement from '../pages/Manager/system/commonCodeManagement.vue'; |
|
67 |
-import commonCodeInsert from '../pages/Manager/system/commonCodeInsert.vue'; |
|
68 |
-import commonCodeDetail from '../pages/Manager/system/commonCodeDetail.vue'; |
|
66 |
+import CodeManagementListComp from '../pages/Manager/system/CodeManagementList.vue'; |
|
67 |
+import CodeManagementInsertComp from '../pages/Manager/system/CodeManagementInsert.vue'; |
|
68 |
+import CodeManagementViewComp from '../pages/Manager/system/CodeManagementView.vue'; |
|
69 | 69 |
|
70 | 70 |
const routes = [ |
71 | 71 |
{ path: '/', name: '/', component: Main }, |
... | ... | @@ -153,9 +153,9 @@ |
153 | 153 |
children: [ |
154 | 154 |
{ path: 'AuthorManagement.page', name: 'AuthorManagementPage', component: AuthorManagementComp}, |
155 | 155 |
{ path: 'MenuAuthorManagement.page', name: 'MenuAuthorManagementPage', component: MenuAuthorManagementComp }, |
156 |
- { path: 'commonCodeManagement.page', name: 'commonCodeManagement', component: commonCodeManagement }, |
|
157 |
- { path: 'commonCodeInsert.page', name: 'commonCodeInsert', component: commonCodeInsert }, |
|
158 |
- { path: 'commonCodeDetail.page', name: 'commonCodeDetail', component: commonCodeDetail }, |
|
156 |
+ { path: 'CodeManagementList.page', name: 'CodeManagementListPage', component: CodeManagementListComp }, |
|
157 |
+ { path: 'CodeManagementInsert.page', name: 'CodeManagementInsertPage', component: CodeManagementInsertComp }, |
|
158 |
+ { path: 'CodeManagementView.page', name: 'CodeManagementViewPage', component: CodeManagementViewComp }, |
|
159 | 159 |
] |
160 | 160 |
}, |
161 | 161 |
]; |
--- client/views/pages/Manager/approval/approval.vue
... | ... | @@ -1,141 +0,0 @@ |
1 | -<template> | |
2 | - <div class="sidemenu"> | |
3 | - <div class="myinfo simple"> | |
4 | - <div class="name-box"> | |
5 | - <div class="img-area"> | |
6 | - <div><img :src="photoicon" alt=""> | |
7 | - <p class="name">OOO과장</p> | |
8 | - </div> | |
9 | - <div class="info"> | |
10 | - <p>솔루션 개발팀</p> | |
11 | - <i class="fa-bars"></i> | |
12 | - <p>팀장</p> | |
13 | - </div> | |
14 | - </div> | |
15 | - </div> | |
16 | - <details class="menu-box" open> | |
17 | - <summary> | |
18 | - <p>결재</p> | |
19 | - <div class="icon"><img :src="topmenuicon" alt=""></div> | |
20 | - </summary> | |
21 | - <ul> | |
22 | - <li> <router-link :to="{ name: 'approvalRequest' }" exact-active-class="active-link" v-slot="{ isExactActive }"> | |
23 | - <p>결재 요청</p> | |
24 | - <div class="icon" v-if="isExactActive"> | |
25 | - <img :src="menuicon" alt=""> | |
26 | - </div> | |
27 | - </router-link></li> | |
28 | - <li> | |
29 | - <router-link :to="{ name: 'approvalList' }" exact-active-class="active-link" v-slot="{ isExactActive }"> | |
30 | - <p>승인 대기 목록</p> | |
31 | - <div class="icon" v-if="isExactActive"> | |
32 | - <img :src="menuicon" alt=""> | |
33 | - </div> | |
34 | - </router-link> | |
35 | - </li> | |
36 | - </ul> | |
37 | - </details> | |
38 | - </div> | |
39 | - </div> | |
40 | - <!-- End Page Title --> | |
41 | - <div class="content"> | |
42 | - <router-view></router-view> | |
43 | - </div> | |
44 | -</template> | |
45 | -<script> | |
46 | -import { ref } from 'vue'; | |
47 | - | |
48 | -export default { | |
49 | - data() { | |
50 | - return { | |
51 | - photoicon: "/client/resources/img/photo_icon.png", | |
52 | - menuicon: "/client/resources/img/menuicon.png", | |
53 | - topmenuicon: "/client/resources/img/topmenuicon.png", | |
54 | - // 데이터 초기화 | |
55 | - years: [2023, 2024, 2025], // 연도 목록 | |
56 | - months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], // 월 목록 | |
57 | - selectedYear: '', | |
58 | - selectedMonth: '', | |
59 | - DeptData: [ | |
60 | - { member: '', deptNM: '', acceptTerms: false }, | |
61 | - // 더 많은 데이터 추가... | |
62 | - ], | |
63 | - filteredData: [], | |
64 | - }; | |
65 | - }, | |
66 | - computed: { | |
67 | - }, | |
68 | - methods: { | |
69 | - async onClickSubmit() { | |
70 | - // `useMutation` 훅을 사용하여 mutation 함수 가져오기 | |
71 | - const { mutate, onDone, onError } = useMutation(mygql); | |
72 | - | |
73 | - try { | |
74 | - const result = await mutate(); | |
75 | - console.log(result); | |
76 | - } catch (error) { | |
77 | - console.error('Mutation error:', error); | |
78 | - } | |
79 | - }, | |
80 | - registerLeave() { | |
81 | - console.log("등록 버튼 클릭됨"); | |
82 | - | |
83 | - // Vue의 반응성 문제를 피하기 위해, 새로운 객체를 추가합니다. | |
84 | - this.DeptData = [ | |
85 | - ...this.DeptData, | |
86 | - { member: '', deptNM: '', acceptTerms: false } | |
87 | - ]; | |
88 | - | |
89 | - console.log(this.DeptData); // 배열 상태 출력 | |
90 | - }, | |
91 | - saveChanges() { | |
92 | - // 로컬스토리지에 DeptData 저장 | |
93 | - localStorage.setItem('DeptData', JSON.stringify(this.DeptData)); | |
94 | - console.log('데이터가 로컬스토리지에 저장되었습니다.'); | |
95 | - }, | |
96 | - deletePending() { | |
97 | - // 선택된 항목만 필터링하여 삭제 | |
98 | - const selectedItems = this.DeptData.filter(item => item.acceptTerms); | |
99 | - | |
100 | - // 승인된 항목이 없으면 삭제 진행 | |
101 | - if (selectedItems.length > 0) { | |
102 | - this.DeptData = this.DeptData.filter(item => !item.acceptTerms); | |
103 | - alert(`${selectedItems.length}개의 항목이 삭제되었습니다.`); | |
104 | - } else { | |
105 | - alert("선택된 항목이 없습니다."); | |
106 | - } | |
107 | - }, | |
108 | - // 날짜 필터 적용 | |
109 | - filterData() { | |
110 | - this.filteredData = this.DeptData.filter(item => { | |
111 | - const itemYear = new Date(item.startDate).getFullYear(); | |
112 | - const itemMonth = new Date(item.startDate).getMonth() + 1; // 월은 0부터 시작하므로 1을 더해줍니다. | |
113 | - | |
114 | - return ( | |
115 | - (!this.selectedYear || itemYear === parseInt(this.selectedYear)) && | |
116 | - (!this.selectedMonth || itemMonth === parseInt(this.selectedMonth)) | |
117 | - ); | |
118 | - }); | |
119 | - }, | |
120 | - | |
121 | - // 페이지 변경 | |
122 | - changePage(page) { | |
123 | - this.currentPage = page; | |
124 | - }, | |
125 | - }, | |
126 | - created() { | |
127 | - // 로컬스토리지에서 기존 데이터가 있으면 불러오기 | |
128 | - const storedData = localStorage.getItem('DeptData'); | |
129 | - if (storedData) { | |
130 | - this.DeptData = JSON.parse(storedData); | |
131 | - } | |
132 | - }, | |
133 | - mounted() { | |
134 | - | |
135 | - // 처음에는 모든 데이터를 표시 | |
136 | - this.filteredData = this.DeptData; | |
137 | - | |
138 | - }, | |
139 | -}; | |
140 | -</script> | |
141 | -<style scoped></style> |
--- client/views/pages/Manager/asset/CardInfoManagement.vue
+++ client/views/pages/Manager/asset/CardInfoManagement.vue
... | ... | @@ -119,7 +119,7 @@ |
119 | 119 |
</table> |
120 | 120 |
|
121 | 121 |
</div> |
122 |
- <Pagenation :search="searchReqHisDTO" @onChange="fnChangeCurrentPage" /> |
|
122 |
+ <Pagination :search="searchReqHisDTO" @onChange="fnChangeCurrentPage" /> |
|
123 | 123 |
</div> |
124 | 124 |
</div> |
125 | 125 |
</div> |
... | ... | @@ -133,7 +133,7 @@ |
133 | 133 |
import HrPopup from "../../../component/Popup/HrPopup.vue"; |
134 | 134 |
import { SearchOutlined, CloseCircleFilled } from '@ant-design/icons-vue'; |
135 | 135 |
import { saveAsSetCard, findAllAsSetCard, updateAsSetCard, findAllAsSetCardHis } from "../../../../resources/api/asset"; //카드 정보 API |
136 |
-import Pagenation from "../../../component/Pagenation.vue"; |
|
136 |
+import Pagination from "../../../component/Pagination.vue"; |
|
137 | 137 |
|
138 | 138 |
export default { |
139 | 139 |
data() { |
... | ... | @@ -149,7 +149,7 @@ |
149 | 149 |
startbtn: "/client/resources/img/start.png", |
150 | 150 |
stopbtn: "/client/resources/img/stop.png", |
151 | 151 |
moreicon: "/client/resources/img/more.png", |
152 |
- |
|
152 |
+ |
|
153 | 153 |
checkCard: false, |
154 | 154 |
cardId: null, |
155 | 155 |
selectedCards: [], |
... | ... | @@ -188,7 +188,7 @@ |
188 | 188 |
} |
189 | 189 |
}, |
190 | 190 |
components: { |
191 |
- SearchOutlined, CloseCircleFilled, HrPopup, Pagenation |
|
191 |
+ SearchOutlined, CloseCircleFilled, HrPopup, Pagination |
|
192 | 192 |
}, |
193 | 193 |
methods: { |
194 | 194 |
// 페이지 이동 |
--- client/views/pages/Manager/asset/CardList.vue
+++ client/views/pages/Manager/asset/CardList.vue
... | ... | @@ -51,7 +51,7 @@ |
51 | 51 |
</table> |
52 | 52 |
|
53 | 53 |
</div> |
54 |
- <Pagenation :search="searchReqHisResDTO" @onChange="fnChangeCurrentPageRes" /> |
|
54 |
+ <Pagination :search="searchReqHisResDTO" @onChange="fnChangeCurrentPageRes" /> |
|
55 | 55 |
<div class="sch-form-wrap title-wrap"> |
56 | 56 |
<h3><img :src="h3icon" alt="">사용이력</h3> |
57 | 57 |
<div class="input-group"> |
... | ... | @@ -100,7 +100,7 @@ |
100 | 100 |
</table> |
101 | 101 |
|
102 | 102 |
</div> |
103 |
- <Pagenation :search="searchReqHisRtnDTO" @onChange="fnChangeCurrentPageRtn" /> |
|
103 |
+ <Pagination :search="searchReqHisRtnDTO" @onChange="fnChangeCurrentPageRtn" /> |
|
104 | 104 |
</div> |
105 | 105 |
</div> |
106 | 106 |
</div> |
... | ... | @@ -109,7 +109,7 @@ |
109 | 109 |
<script> |
110 | 110 |
import { ref } from 'vue'; |
111 | 111 |
import { SearchOutlined } from '@ant-design/icons-vue'; |
112 |
-import Pagenation from "../../../component/Pagenation.vue"; |
|
112 |
+import Pagination from "../../../component/Pagination.vue"; |
|
113 | 113 |
import { findAllAsSetCardHis } from "../../../../resources/api/asset"; //카드 정보 API |
114 | 114 |
export default { |
115 | 115 |
data() { |
... | ... | @@ -160,7 +160,7 @@ |
160 | 160 |
computed: { |
161 | 161 |
}, |
162 | 162 |
components: { |
163 |
- SearchOutlined, Pagenation |
|
163 |
+ SearchOutlined, Pagination |
|
164 | 164 |
}, |
165 | 165 |
methods: { |
166 | 166 |
// 페이지 이동 예약현황황 |
... | ... | @@ -182,7 +182,7 @@ |
182 | 182 |
console.error("검색 중 오류 발생:", error); |
183 | 183 |
} |
184 | 184 |
}, |
185 |
- // 페이지 이동 사용현황 |
|
185 |
+ // 페이지 이동 사용현황 |
|
186 | 186 |
fnChangeCurrentPageRtn(currentPage) { |
187 | 187 |
this.searchReqHisRtnDTO.currentPage = Number(currentPage); |
188 | 188 |
this.$nextTick(() => { |
--- client/views/pages/Manager/asset/VhcleInfoManagement.vue
+++ client/views/pages/Manager/asset/VhcleInfoManagement.vue
... | ... | @@ -152,7 +152,7 @@ |
152 | 152 |
</table> |
153 | 153 |
|
154 | 154 |
</div> |
155 |
- <Pagenation :search="searchReqHisDTO" @onChange="fnChangeCurrentPage" /> |
|
155 |
+ <Pagination :search="searchReqHisDTO" @onChange="fnChangeCurrentPage" /> |
|
156 | 156 |
</div> |
157 | 157 |
</div> |
158 | 158 |
</div> |
... | ... | @@ -166,7 +166,7 @@ |
166 | 166 |
import { SearchOutlined } from '@ant-design/icons-vue'; |
167 | 167 |
import HrPopup from "../../../component/Popup/HrPopup.vue"; |
168 | 168 |
import { saveAsSetVhcle, findAllAsSetVhcle, updateAsSetVhcle, findAllAsSetVhcleHis } from "../../../../resources/api/asset"; //카드 정보 API |
169 |
-import Pagenation from "../../../component/Pagenation.vue"; |
|
169 |
+import Pagination from "../../../component/Pagination.vue"; |
|
170 | 170 |
|
171 | 171 |
export default { |
172 | 172 |
data() { |
... | ... | @@ -183,7 +183,7 @@ |
183 | 183 |
startbtn: "/client/resources/img/start.png", |
184 | 184 |
stopbtn: "/client/resources/img/stop.png", |
185 | 185 |
moreicon: "/client/resources/img/more.png", |
186 |
- |
|
186 |
+ |
|
187 | 187 |
checkVhcle: false, |
188 | 188 |
vhcleId: null, |
189 | 189 |
selectedVhcles: [], |
... | ... | @@ -226,7 +226,7 @@ |
226 | 226 |
} |
227 | 227 |
}, |
228 | 228 |
components: { |
229 |
- SearchOutlined, HrPopup, Pagenation |
|
229 |
+ SearchOutlined, HrPopup, Pagination |
|
230 | 230 |
}, |
231 | 231 |
methods: { |
232 | 232 |
// 페이지 이동 |
--- client/views/pages/Manager/asset/VhcleList.vue
+++ client/views/pages/Manager/asset/VhcleList.vue
... | ... | @@ -56,7 +56,7 @@ |
56 | 56 |
</table> |
57 | 57 |
|
58 | 58 |
</div> |
59 |
- <Pagenation :search="searchReqHisResDTO" @onChange="fnChangeCurrentPageRes" /> |
|
59 |
+ <Pagination :search="searchReqHisResDTO" @onChange="fnChangeCurrentPageRes" /> |
|
60 | 60 |
<div class="sch-form-wrap title-wrap"> |
61 | 61 |
<h3><img :src="h3icon" alt="">사용이력</h3> |
62 | 62 |
<div class="input-group"> |
... | ... | @@ -110,7 +110,7 @@ |
110 | 110 |
</table> |
111 | 111 |
|
112 | 112 |
</div> |
113 |
- <Pagenation :search="searchReqHisRtnDTO" @onChange="fnChangeCurrentPageRtn" /> |
|
113 |
+ <Pagination :search="searchReqHisRtnDTO" @onChange="fnChangeCurrentPageRtn" /> |
|
114 | 114 |
</div> |
115 | 115 |
</div> |
116 | 116 |
</div> |
... | ... | @@ -119,14 +119,14 @@ |
119 | 119 |
<script> |
120 | 120 |
import { ref } from 'vue'; |
121 | 121 |
import { SearchOutlined } from '@ant-design/icons-vue'; |
122 |
-import Pagenation from "../../../component/Pagenation.vue"; |
|
122 |
+import Pagination from "../../../component/Pagination.vue"; |
|
123 | 123 |
import { findAllAsSetVhcleHis } from "../../../../resources/api/asset"; //차량 정보 API |
124 | 124 |
export default { |
125 | 125 |
data() { |
126 | 126 |
return { |
127 | 127 |
photoicon: "/client/resources/img/photo_icon.png", |
128 | 128 |
h3icon: "/client/resources/img/h3icon.png", |
129 |
- |
|
129 |
+ |
|
130 | 130 |
searchReqHisResDTO: { |
131 | 131 |
searchType: "all", |
132 | 132 |
searchText: null, |
... | ... | @@ -170,7 +170,7 @@ |
170 | 170 |
computed: { |
171 | 171 |
}, |
172 | 172 |
components: { |
173 |
- SearchOutlined, Pagenation |
|
173 |
+ SearchOutlined, Pagination |
|
174 | 174 |
}, |
175 | 175 |
methods: { |
176 | 176 |
// 페이지 이동 예약현황황 |
... | ... | @@ -192,7 +192,7 @@ |
192 | 192 |
console.error("검색 중 오류 발생:", error); |
193 | 193 |
} |
194 | 194 |
}, |
195 |
- // 페이지 이동 사용현황 |
|
195 |
+ // 페이지 이동 사용현황 |
|
196 | 196 |
fnChangeCurrentPageRtn(currentPage) { |
197 | 197 |
this.searchReqHisRtnDTO.currentPage = Number(currentPage); |
198 | 198 |
this.$nextTick(() => { |
--- client/views/pages/Manager/attendance/ChuljangStatue.vue
+++ client/views/pages/Manager/attendance/ChuljangStatue.vue
... | ... | @@ -41,7 +41,7 @@ |
41 | 41 |
</tbody> |
42 | 42 |
</table> |
43 | 43 |
</div> |
44 |
- <Pagenation :search="request" @onChange="fnChangeCurrentPage" /> |
|
44 |
+ <Pagination :search="request" @onChange="fnChangeCurrentPage" /> |
|
45 | 45 |
</div> |
46 | 46 |
</div> |
47 | 47 |
</div> |
--- client/views/pages/Manager/attendance/hyugaStatue.vue
+++ client/views/pages/Manager/attendance/hyugaStatue.vue
... | ... | @@ -55,21 +55,21 @@ |
55 | 55 |
</tbody> |
56 | 56 |
</table> |
57 | 57 |
</div> |
58 |
- <Pagenation :search="request" @onChange="fnChangeCurrentPage" /> |
|
58 |
+ <Pagination :search="request" @onChange="fnChangeCurrentPage" /> |
|
59 | 59 |
</div> |
60 | 60 |
</div> |
61 | 61 |
</div> |
62 | 62 |
</template> |
63 | 63 |
<script> |
64 | 64 |
import { SearchOutlined } from '@ant-design/icons-vue'; |
65 |
-import Pagenation from '../../../component/Pagenation.vue'; |
|
65 |
+import Pagination from '../../../component/Pagination.vue'; |
|
66 | 66 |
// API |
67 | 67 |
import { findVcatnsSummary, findVcatnsProc } from '../../../../resources/api/vcatn'; |
68 | 68 |
|
69 | 69 |
export default { |
70 | 70 |
components: { |
71 | 71 |
SearchOutlined, |
72 |
- Pagenation |
|
72 |
+ Pagination |
|
73 | 73 |
}, |
74 | 74 |
|
75 | 75 |
data() { |
+++ client/views/pages/Manager/system/CodeManagementInsert.vue
... | ... | @@ -0,0 +1,242 @@ |
1 | +<template> | |
2 | + <div class="card"> | |
3 | + <div class="card-body"> | |
4 | + <h2 class="card-title">공통코드 {{ isEditMode ? '수정' : '등록' }}</h2> | |
5 | + <p class="require">* 필수입력</p> | |
6 | + <div class="tbl-wrap needs-validation detail"> | |
7 | + <table class="tbl data radius-table"> | |
8 | + <colgroup> | |
9 | + <col style="width: 25%;"> | |
10 | + <col style="width: 75%;"> | |
11 | + </colgroup> | |
12 | + <tbody> | |
13 | + <tr> | |
14 | + <th>상위코드</th> | |
15 | + <td> | |
16 | + <input type="text" id="parentCode" v-model="formData.upperCode" readonly /> | |
17 | + <button type="button" class="btn sm primary" @click="handleModalOpen"> 검색 </button> | |
18 | + </td> | |
19 | + </tr> | |
20 | + <tr> | |
21 | + <th>상위코드 명</th> | |
22 | + <td> | |
23 | + <input type="text" id="parentCodeName" v-model="formData.upperCodeNm" readonly /> | |
24 | + </td> | |
25 | + </tr> | |
26 | + <tr> | |
27 | + <th>코드 *</th> | |
28 | + <td> | |
29 | + <input type="text" id="code" v-model="formData.code" :disabled="isEditMode" /> | |
30 | + </td> | |
31 | + </tr> | |
32 | + <tr> | |
33 | + <th>코드명 *</th> | |
34 | + <td> | |
35 | + <input type="text" id="codeName" v-model="formData.codeNm" /> | |
36 | + </td> | |
37 | + </tr> | |
38 | + <tr> | |
39 | + <th>코드 설정값</th> | |
40 | + <td> | |
41 | + <input type="text" id="codeValue" v-model="formData.codeValue" /> | |
42 | + </td> | |
43 | + </tr> | |
44 | + <tr> | |
45 | + <th>설명</th> | |
46 | + <td> | |
47 | + <textarea name="description" id="description" v-model="formData.dc"></textarea> | |
48 | + </td> | |
49 | + </tr> | |
50 | + <tr> | |
51 | + <th>사용여부 *</th> | |
52 | + <td> | |
53 | + <div class="chk-area"> | |
54 | + <div class="form-check"> | |
55 | + <input type="radio" name="isActive" id="activeTrue" value="Y" v-model="formData.useAt" disabled> | |
56 | + <label for="activeTrue">사용</label> | |
57 | + </div> | |
58 | + <div class="form-check"> | |
59 | + <input type="radio" name="isActive" id="activeFalse" value="N" v-model="formData.useAt" disabled> | |
60 | + <label for="activeFalse">미사용</label> | |
61 | + </div> | |
62 | + </div> | |
63 | + </td> | |
64 | + </tr> | |
65 | + </tbody> | |
66 | + </table> | |
67 | + </div> | |
68 | + <div class="buttons"> | |
69 | + <template v-if="!isEditMode"> | |
70 | + <button type="button" class="btn sm primary" @click="handleCreate">등록</button> | |
71 | + <button type="button" class="btn sm tertiary" @click="handleNavigation('list')">취소</button> | |
72 | + </template> | |
73 | + <template v-else> | |
74 | + <button type="button" class="btn sm primary" @click="handleUpdate">수정</button> | |
75 | + <button type="button" class="btn sm tertiary" @click="handleNavigation('view', codeId)">취소</button> | |
76 | + </template> | |
77 | + </div> | |
78 | + </div> | |
79 | + </div> | |
80 | + <CodeSelectorModal v-if="isModalVisible" :current-code-id="codeId" @select="handleCodeSelect" @close="handleModalClose" /> | |
81 | +</template> | |
82 | +<script> | |
83 | +import CodeSelectorModal from "../../../component/Popup/CodeSelectorModal.vue"; | |
84 | +import { saveCodeProc, findCodeProc, updateCodeProc } from "../../../../resources/api/code"; | |
85 | + | |
86 | +export default { | |
87 | + name: 'CodeFormPage', | |
88 | + | |
89 | + components: { | |
90 | + CodeSelectorModal | |
91 | + }, | |
92 | + | |
93 | + data() { | |
94 | + return { | |
95 | + codeId: null, | |
96 | + isModalVisible: false, | |
97 | + | |
98 | + formData: { | |
99 | + code: null, | |
100 | + codeNm: null, | |
101 | + upperCode: null, | |
102 | + upperCodeNm: null, | |
103 | + dc: null, | |
104 | + useAt: 'Y', | |
105 | + codeValue: null, | |
106 | + } | |
107 | + } | |
108 | + }, | |
109 | + | |
110 | + computed: { | |
111 | + isEditMode() { | |
112 | + return !this.$isEmpty(this.codeId); | |
113 | + } | |
114 | + }, | |
115 | + | |
116 | + created() { | |
117 | + this.codeId = this.$route.query.id; | |
118 | + }, | |
119 | + | |
120 | + mounted() { | |
121 | + if (this.isEditMode) { | |
122 | + this.fetchCodeDetail(); | |
123 | + } | |
124 | + }, | |
125 | + | |
126 | + methods: { | |
127 | + // 상세 정보 조회 | |
128 | + async fetchCodeDetail() { | |
129 | + try { | |
130 | + const response = await findCodeProc(this.codeId); | |
131 | + const result = response.data.data; | |
132 | + | |
133 | + this.formData = result.code; | |
134 | + } catch (error) { | |
135 | + this.handleError(error); | |
136 | + } | |
137 | + }, | |
138 | + | |
139 | + // 신규 등록 | |
140 | + async handleCreate() { | |
141 | + try { | |
142 | + if (!this.validateForm()) return; | |
143 | + | |
144 | + const requestData = { | |
145 | + code: this.formData.code, | |
146 | + codeNm: this.formData.codeNm, | |
147 | + upperCode: this.formData.upperCode, | |
148 | + dc: this.formData.dc, | |
149 | + codeValue: this.formData.codeValue, | |
150 | + }; | |
151 | + | |
152 | + await saveCodeProc(requestData); | |
153 | + alert('등록되었습니다.'); | |
154 | + this.handleNavigation('list'); | |
155 | + } catch (error) { | |
156 | + this.handleError(error); | |
157 | + } | |
158 | + }, | |
159 | + | |
160 | + // 수정 | |
161 | + async handleUpdate() { | |
162 | + try { | |
163 | + if (!this.validateForm()) return; | |
164 | + | |
165 | + const requestData = { | |
166 | + codeNm: this.formData.codeNm, | |
167 | + upperCode: this.formData.upperCode, | |
168 | + dc: this.formData.dc, | |
169 | + useAt: this.formData.useAt, | |
170 | + codeValue: this.formData.codeValue, | |
171 | + }; | |
172 | + | |
173 | + await updateCodeProc(this.codeId, requestData); | |
174 | + alert('수정되었습니다.'); | |
175 | + this.handleNavigation('view', this.codeId); | |
176 | + } catch (error) { | |
177 | + this.handleError(error); | |
178 | + } | |
179 | + }, | |
180 | + | |
181 | + // 폼 유효성 검사 | |
182 | + validateForm() { | |
183 | + if (!this.formData.code?.trim()) { | |
184 | + alert('코드를 입력해주세요.'); | |
185 | + return false; | |
186 | + } | |
187 | + if (!this.formData.codeNm?.trim()) { | |
188 | + alert('코드명을 입력해주세요.'); | |
189 | + return false; | |
190 | + } | |
191 | + return true; | |
192 | + }, | |
193 | + | |
194 | + // 모달 열기 | |
195 | + handleModalOpen() { | |
196 | + this.isModalVisible = true; | |
197 | + }, | |
198 | + | |
199 | + // 모달 닫기 | |
200 | + handleModalClose() { | |
201 | + this.isModalVisible = false; | |
202 | + }, | |
203 | + | |
204 | + // 상위 코드 선택 | |
205 | + handleCodeSelect(selectedCode) { | |
206 | + this.formData.upperCode = selectedCode.code; | |
207 | + this.formData.upperCodeNm = selectedCode.codeNm; | |
208 | + this.handleModalClose(); | |
209 | + }, | |
210 | + | |
211 | + // 페이지 이동 | |
212 | + handleNavigation(type, id) { | |
213 | + const routeMap = { | |
214 | + 'list': { name: 'CodeManagementListPage' }, | |
215 | + 'view': { name: 'CodeManagementViewPage', query: { id } }, | |
216 | + 'edit': { name: 'CodeManagementInsertPage', query: this.$isEmpty(id) ? {} : { id } }, | |
217 | + }; | |
218 | + | |
219 | + const route = routeMap[type]; | |
220 | + if (route) { | |
221 | + this.$router.push(route); | |
222 | + } else { | |
223 | + this.handleNavigationError(type); | |
224 | + } | |
225 | + }, | |
226 | + | |
227 | + // 네비게이션 에러 처리 | |
228 | + handleNavigationError(type) { | |
229 | + console.warn(`유효하지 않은 라우트 타입: ${type}`); | |
230 | + alert("올바르지 않은 경로를 요청하여 목록으로 이동합니다."); | |
231 | + this.$router.push({ name: 'CodeManagementListPage' }); | |
232 | + }, | |
233 | + | |
234 | + // 에러 처리 | |
235 | + handleError(error) { | |
236 | + const message = error.response?.data?.message || "에러가 발생했습니다."; | |
237 | + alert(message); | |
238 | + console.error(error.message); | |
239 | + } | |
240 | + } | |
241 | +} | |
242 | +</script>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/Manager/system/CodeManagementList.vue
... | ... | @@ -0,0 +1,176 @@ |
1 | +<template> | |
2 | + <div class="col-lg-12"> | |
3 | + <div class="card"> | |
4 | + <div class="card-body"> | |
5 | + <h2 class="card-title">공통코드 관리</h2> | |
6 | + <div class="sch-form-wrap"> | |
7 | + <div class="input-group"> | |
8 | + <select name="searchType" id="searchType" class="form-select" v-model="searchParams.searchType"> | |
9 | + <option value="">전체</option> | |
10 | + <option v-for="(item, index) of searchOptions" :key="index" :value="item.key"> {{ item.label }} </option> | |
11 | + </select> | |
12 | + <div class="sch-input"> | |
13 | + <input type="text" class="form-control" v-model="searchParams.searchText" @keyup.enter="handleSearch" placeholder="검색어를 입력하세요"> | |
14 | + <button class="ico-sch" @click="handleSearch" type="button"> | |
15 | + <SearchOutlined /> | |
16 | + </button> | |
17 | + </div> | |
18 | + </div> | |
19 | + </div> | |
20 | + <div class="tbl-wrap"> | |
21 | + <table id="codeTable" class="tbl data"> | |
22 | + <colgroup> | |
23 | + <col style="width: 18%;"> | |
24 | + <col style="width: 18%;"> | |
25 | + <col style="width: 18%;"> | |
26 | + <col style="width: 18%;"> | |
27 | + <col style="width: 18%;"> | |
28 | + <col style="width: 10%;"> | |
29 | + </colgroup> | |
30 | + <thead> | |
31 | + <tr> | |
32 | + <th>상위코드</th> | |
33 | + <th>상위코드명</th> | |
34 | + <th>코드</th> | |
35 | + <th>코드명</th> | |
36 | + <th>등록일</th> | |
37 | + <th>사용여부</th> | |
38 | + </tr> | |
39 | + </thead> | |
40 | + <tbody> | |
41 | + <template v-if="codeList.length > 0"> | |
42 | + <tr v-for="(code, index) in codeList" :key="index" :class="{ expired: code.useAt === 'N' }" @click="handleNavigation('view', code.code)"> | |
43 | + <td>{{ code.upperCode }}</td> | |
44 | + <td>{{ code.upperCodeNm }}</td> | |
45 | + <td>{{ code.code }}</td> | |
46 | + <td>{{ code.codeNm }}</td> | |
47 | + <td>{{ formatDate(code.rgsde) }}</td> | |
48 | + <td>{{ getActiveStatusText(code.useAt) }}</td> | |
49 | + </tr> | |
50 | + </template> | |
51 | + <tr v-else> | |
52 | + <td colspan="6" class="text-center">등록된 코드가 없습니다.</td> | |
53 | + </tr> | |
54 | + </tbody> | |
55 | + </table> | |
56 | + </div> | |
57 | + <Pagination :search="searchParams" @onChange="handlePageChange" /> | |
58 | + <div class="buttons"> | |
59 | + <button type="button" class="btn sm primary" @click="handleNavigation('edit')">등록</button> | |
60 | + </div> | |
61 | + </div> | |
62 | + </div> | |
63 | + </div> | |
64 | +</template> | |
65 | +<script> | |
66 | +import { SearchOutlined } from '@ant-design/icons-vue'; | |
67 | +import Pagination from "../../../component/Pagination.vue"; | |
68 | +// API | |
69 | +import { findCodesProc } from "../../../../resources/api/code"; | |
70 | + | |
71 | +export default { | |
72 | + name: 'CodeListPage', | |
73 | + | |
74 | + components: { | |
75 | + SearchOutlined, | |
76 | + Pagination, | |
77 | + }, | |
78 | + | |
79 | + data() { | |
80 | + return { | |
81 | + codeList: [], // 코드 목록 | |
82 | + | |
83 | + searchOptions: [ | |
84 | + { key: "UPPER_CODE", label: "상위코드" }, | |
85 | + { key: "UPPERCODE_NAME", label: "상위코드 이름" }, | |
86 | + { key: "CODE", label: "코드" }, | |
87 | + { key: "CODE_NAME", label: "코드 이름" }, | |
88 | + ], | |
89 | + | |
90 | + searchParams: { | |
91 | + searchType: '', | |
92 | + searchText: '', | |
93 | + currentPage: 1, | |
94 | + } | |
95 | + } | |
96 | + }, | |
97 | + | |
98 | + mounted() { | |
99 | + this.fetchCodeList(); | |
100 | + }, | |
101 | + | |
102 | + methods: { | |
103 | + // 코드 목록 조회 | |
104 | + async fetchCodeList() { | |
105 | + try { | |
106 | + const response = await findCodesProc(this.searchParams); | |
107 | + const result = response.data.data; | |
108 | + | |
109 | + this.codeList = result.codes; | |
110 | + this.searchParams = result.search; | |
111 | + } catch (error) { | |
112 | + this.handleError(error); | |
113 | + } | |
114 | + }, | |
115 | + | |
116 | + // 날짜 포맷팅 | |
117 | + formatDate(dateString) { | |
118 | + return dateString ? dateString.split(' ')[0] : '-'; | |
119 | + }, | |
120 | + | |
121 | + // 사용여부 텍스트 반환 | |
122 | + getActiveStatusText(useAt) { | |
123 | + return useAt === 'Y' ? '사용중' : useAt === 'N' ? '미사용' : ''; | |
124 | + }, | |
125 | + | |
126 | + // 검색 실행 | |
127 | + handleSearch() { | |
128 | + this.searchParams.currentPage = 1; | |
129 | + this.fetchCodeList(); | |
130 | + }, | |
131 | + | |
132 | + // 페이지 변경 | |
133 | + handlePageChange(currentPage) { | |
134 | + this.searchParams.currentPage = Number(currentPage); | |
135 | + this.$nextTick(() => { | |
136 | + this.fetchCodeList(); | |
137 | + }); | |
138 | + }, | |
139 | + | |
140 | + // 페이지 이동 | |
141 | + handleNavigation(type, id) { | |
142 | + const routeMap = { | |
143 | + 'list': { name: 'CodeManagementListPage' }, | |
144 | + 'view': { name: 'CodeManagementViewPage', query: { id } }, | |
145 | + 'edit': { name: 'CodeManagementInsertPage', query: this.$isEmpty(id) ? {} : { id } }, | |
146 | + }; | |
147 | + | |
148 | + const route = routeMap[type]; | |
149 | + if (route) { | |
150 | + this.$router.push(route); | |
151 | + } else { | |
152 | + this.handleNavigationError(type); | |
153 | + } | |
154 | + }, | |
155 | + | |
156 | + // 네비게이션 에러 처리 | |
157 | + handleNavigationError(type) { | |
158 | + console.warn(`유효하지 않은 라우트 타입: ${type}`); | |
159 | + alert("올바르지 않은 경로를 요청하여 목록으로 이동합니다."); | |
160 | + this.$router.push({ name: 'CodeManagementListPage' }); | |
161 | + }, | |
162 | + | |
163 | + // 에러 처리 | |
164 | + handleError(error) { | |
165 | + const message = error.response?.data?.message || "에러가 발생했습니다."; | |
166 | + alert(message); | |
167 | + console.error(error.message); | |
168 | + }, | |
169 | + }, | |
170 | +}; | |
171 | +</script> | |
172 | +<style scoped> | |
173 | +tr { | |
174 | + cursor: pointer; | |
175 | +} | |
176 | +</style>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/Manager/system/CodeManagementView.vue
... | ... | @@ -0,0 +1,163 @@ |
1 | +<template> | |
2 | + <div class="card"> | |
3 | + <div class="card-body"> | |
4 | + <h2 class="card-title">공통코드 상세</h2> | |
5 | + <p class="require">* 필수입력</p> | |
6 | + <div class="tbl-wrap"> | |
7 | + <table class="tbl data radius-table"> | |
8 | + <colgroup> | |
9 | + <col style="width: 25%;"> | |
10 | + <col style="width: 25%;"> | |
11 | + <col style="width: 25%;"> | |
12 | + <col style="width: 25%;"> | |
13 | + </colgroup> | |
14 | + <tbody> | |
15 | + <tr> | |
16 | + <th>상위코드</th> | |
17 | + <td>{{ codeDetail.upperCode }}</td> | |
18 | + <th>상위코드 명</th> | |
19 | + <td>{{ codeDetail.upperCodeNm }}</td> | |
20 | + </tr> | |
21 | + <tr> | |
22 | + <th>코드</th> | |
23 | + <td>{{ codeDetail.code }}</td> | |
24 | + <th>코드명</th> | |
25 | + <td>{{ codeDetail.codeNm }}</td> | |
26 | + </tr> | |
27 | + <tr> | |
28 | + <th>코드 설정값</th> | |
29 | + <td colspan="3">{{ codeDetail.codeValue }}</td> | |
30 | + </tr> | |
31 | + <tr> | |
32 | + <th>설명</th> | |
33 | + <td colspan="3"> | |
34 | + <p>{{ codeDetail.dc }}</p> | |
35 | + </td> | |
36 | + </tr> | |
37 | + <tr> | |
38 | + <th>사용여부</th> | |
39 | + <td colspan="3">{{ getActiveStatusText(codeDetail.useAt) }}</td> | |
40 | + </tr> | |
41 | + </tbody> | |
42 | + </table> | |
43 | + </div> | |
44 | + <div class="buttons"> | |
45 | + <button type="button" class="btn sm secondary" v-if="codeDetail.useAt === 'Y'" @click="handleStatusUpdate('N')"> 삭제 </button> | |
46 | + <button type="button" class="btn sm secondary" v-if="codeDetail.useAt === 'N'" @click="handleStatusUpdate('Y')"> 복구 </button> | |
47 | + <button type="button" class="btn sm primary" @click="handleNavigation('edit', pageId)"> 수정 </button> | |
48 | + <button type="button" class="btn sm tertiary" @click="handleNavigation('list')"> 목록 </button> | |
49 | + </div> | |
50 | + </div> | |
51 | + </div> | |
52 | +</template> | |
53 | +<script> | |
54 | +// API | |
55 | +import { findCodeProc, updateCodeProc } from "../../../../resources/api/code"; | |
56 | + | |
57 | +export default { | |
58 | + name: 'CodeDetailPage', | |
59 | + | |
60 | + data() { | |
61 | + return { | |
62 | + pageId: null, | |
63 | + | |
64 | + codeDetail: { | |
65 | + code: null, | |
66 | + codeNm: null, | |
67 | + upperCode: null, | |
68 | + upperCodeNm: null, | |
69 | + dc: null, | |
70 | + useAt: 'Y', | |
71 | + codeValue: null, | |
72 | + } | |
73 | + } | |
74 | + }, | |
75 | + | |
76 | + created() { | |
77 | + this.pageId = this.$route.query.id; | |
78 | + if (this.$isEmpty(this.pageId)) { | |
79 | + alert("게시물이 존재하지 않습니다."); | |
80 | + this.handleNavigation('list'); | |
81 | + } | |
82 | + }, | |
83 | + | |
84 | + mounted() { | |
85 | + this.fetchCodeDetail(); | |
86 | + }, | |
87 | + | |
88 | + methods: { | |
89 | + // 상세 정보 조회 | |
90 | + async fetchCodeDetail() { | |
91 | + try { | |
92 | + const response = await findCodeProc(this.pageId); | |
93 | + const result = response.data.data; | |
94 | + | |
95 | + this.codeDetail = result.code; | |
96 | + } catch (error) { | |
97 | + this.handleError(error); | |
98 | + } | |
99 | + }, | |
100 | + | |
101 | + // 사용상태 업데이트 (삭제/복구) | |
102 | + async handleStatusUpdate(status) { | |
103 | + try { | |
104 | + if (status === "N") { | |
105 | + const isConfirmed = confirm("삭제하시겠습니까?"); | |
106 | + if (!isConfirmed) return; | |
107 | + } | |
108 | + | |
109 | + const updateData = { | |
110 | + codeNm: this.codeDetail.codeNm, | |
111 | + useAt: status, | |
112 | + }; | |
113 | + | |
114 | + const response = await updateCodeProc(this.pageId, updateData); | |
115 | + const result = response.data.data; | |
116 | + | |
117 | + this.codeDetail = result.code; | |
118 | + const message = status === "Y" ? "복구에 성공했습니다." : "삭제에 성공했습니다."; | |
119 | + alert(message); | |
120 | + | |
121 | + this.fetchCodeDetail(); | |
122 | + } catch (error) { | |
123 | + this.handleError(error); | |
124 | + } | |
125 | + }, | |
126 | + | |
127 | + // 사용여부 텍스트 반환 | |
128 | + getActiveStatusText(useAt) { | |
129 | + return useAt === 'Y' ? "사용중" : "미사용"; | |
130 | + }, | |
131 | + | |
132 | + // 페이지 이동 | |
133 | + handleNavigation(type, id) { | |
134 | + const routeMap = { | |
135 | + 'list': { name: 'CodeManagementListPage' }, | |
136 | + 'view': { name: 'CodeManagementViewPage', query: { id } }, | |
137 | + 'edit': { name: 'CodeManagementInsertPage', query: this.$isEmpty(id) ? {} : { id } }, | |
138 | + }; | |
139 | + | |
140 | + const route = routeMap[type]; | |
141 | + if (route) { | |
142 | + this.$router.push(route); | |
143 | + } else { | |
144 | + this.handleNavigationError(type); | |
145 | + } | |
146 | + }, | |
147 | + | |
148 | + // 네비게이션 에러 처리 | |
149 | + handleNavigationError(type) { | |
150 | + console.warn(`유효하지 않은 라우트 타입: ${type}`); | |
151 | + alert("올바르지 않은 경로를 요청하여 목록으로 이동합니다."); | |
152 | + this.$router.push({ name: 'CodeManagementListPage' }); | |
153 | + }, | |
154 | + | |
155 | + // 에러 처리 | |
156 | + handleError(error) { | |
157 | + const message = error.response?.data?.message || "에러가 발생했습니다."; | |
158 | + alert(message); | |
159 | + console.error(error.message); | |
160 | + } | |
161 | + } | |
162 | +} | |
163 | +</script>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/Manager/system/commonCodeDetail.vue
... | ... | @@ -1,144 +0,0 @@ |
1 | -<template> | |
2 | - <div class="card "> | |
3 | - <div class="card-body "> | |
4 | - <h2 class="card-title">사용자권한관리</h2> | |
5 | - <p class="require"><img :src="require" alt=""> 필수입력</p> | |
6 | - <form class="row g-3 pt-3 needs-validation detail" @submit.prevent="handleSubmit" | |
7 | - style="margin-bottom: 3rem;"> | |
8 | - <div class="col-12"> | |
9 | - <div class="col-12 border-x"> | |
10 | - <label for="where" class="form-label">상위코드</label> | |
11 | - <input type="text" class="form-control" id="where" v-model="where" readonly /> | |
12 | - </div> | |
13 | - <div class="col-12 border-x"> | |
14 | - <label for="where" class="form-label">상위코드 명</label> | |
15 | - <input type="text" class="form-control" id="where" v-model="where" readonly/> | |
16 | - </div> | |
17 | - | |
18 | - </div> | |
19 | - <div class="col-12"> | |
20 | - <div class="col-12 border-x"> | |
21 | - <label for="where" class="form-label">코드</label> | |
22 | - <input type="text" class="form-control" id="where" v-model="where"readonly /> | |
23 | - </div> | |
24 | - <div class="col-12 border-x"> | |
25 | - <label for="where" class="form-label">코드명</label> | |
26 | - <input type="text" class="form-control" id="where" v-model="where" readonly/> | |
27 | - </div> | |
28 | - | |
29 | - </div> | |
30 | - | |
31 | - <div class="col-12 chuljang "> | |
32 | - <label for="prvonsh" class="form-label">설명</label> | |
33 | - <input type="text" class="form-control textarea" id="reason" v-model="reason" readonly/> | |
34 | - </div> | |
35 | - <div class="col-12 border-x input-radio"> | |
36 | - <label for="prvonsh" class="form-label">사용여부</label> | |
37 | - <input type="text" class="form-control" id="where" v-model="where" readonly/> | |
38 | - </div> | |
39 | - | |
40 | - | |
41 | - </form> | |
42 | - <div class="buttons"> | |
43 | - <button type="submit" class="btn sm btn-red">삭제</button> | |
44 | - <button type="submit" class="btn sm secondary">수정</button> | |
45 | - <button type="reset" class="btn sm tertiary">목록</button> | |
46 | - </div> | |
47 | - </div> | |
48 | - | |
49 | - </div> | |
50 | - | |
51 | -</template> | |
52 | - | |
53 | -<script> | |
54 | -import GoogleCalendar from "../../../component/GoogleCalendar.vue" | |
55 | -import { SearchOutlined } from '@ant-design/icons-vue'; | |
56 | -export default { | |
57 | - data() { | |
58 | - return { | |
59 | - require: "/client/resources/img/require.png", | |
60 | - h3icon: "/client/resources/img/h3icon.png", | |
61 | - photoicon: "/client/resources/img/photo_icon.png", | |
62 | - img1: "/client/resources/img/img.png", | |
63 | - icon1: "/client/resources/img/icon.png", | |
64 | - dateicon: "/client/resources/img/date.png", | |
65 | - startbtn: "/client/resources/img/start.png", | |
66 | - stopbtn: "/client/resources/img/stop.png", | |
67 | - moreicon: "/client/resources/img/more.png", | |
68 | - today: new Date().toLocaleDateString('ko-KR', { | |
69 | - year: 'numeric', | |
70 | - month: '2-digit', | |
71 | - day: '2-digit', | |
72 | - weekday: 'short', | |
73 | - }), | |
74 | - time: this.getCurrentTime(), | |
75 | - listData: Array.from({ length: 20 }, (_, i) => ({ | |
76 | - department: `부서 ${i + 1}`, | |
77 | - name: `이름 ${i + 1}`, | |
78 | - position: `직급 ${i + 1}` | |
79 | - })) | |
80 | - } | |
81 | - }, | |
82 | - components: { | |
83 | - SearchOutlined | |
84 | - }, | |
85 | - methods: { | |
86 | - formatBudget(amount) { | |
87 | - return new Intl.NumberFormat().format(amount) + ' 원'; | |
88 | - }, | |
89 | - isPastPeriod(period) { | |
90 | - // 예: '2025-05-01 ~ 2025-05-03' → 종료일 추출 | |
91 | - const endDateStr = period.split('~')[1]?.trim(); | |
92 | - if (!endDateStr) return false; | |
93 | - | |
94 | - const endDate = new Date(endDateStr); | |
95 | - const today = new Date(); | |
96 | - | |
97 | - // 현재 날짜보다 과거면 true | |
98 | - return endDate < today; | |
99 | - }, | |
100 | - getStatusClass(status) { | |
101 | - return status === 'active' ? 'status-active' : 'status-inactive'; | |
102 | - }, | |
103 | - getStatusClass(status) { | |
104 | - if (status === '미진행') return 'status-pending'; | |
105 | - if (status === '진행중') return 'status-approved'; | |
106 | - | |
107 | - // Default empty string | |
108 | - return ''; | |
109 | - }, | |
110 | - getCurrentTime() { | |
111 | - const now = new Date(); | |
112 | - const hours = String(now.getHours()).padStart(2, '0'); | |
113 | - const minutes = String(now.getMinutes()).padStart(2, '0'); | |
114 | - const seconds = String(now.getSeconds()).padStart(2, '0'); | |
115 | - return `${hours}:${minutes}:${seconds}`; | |
116 | - }, | |
117 | - getCategoryClass(category) { | |
118 | - switch (category) { | |
119 | - case '용역': return 'category-service'; | |
120 | - case '내부': return 'category-internal'; | |
121 | - case '국가과제': return 'category-government'; | |
122 | - default: return ''; | |
123 | - } | |
124 | - }, | |
125 | - }, | |
126 | - watch: { | |
127 | - | |
128 | - }, | |
129 | - computed: { | |
130 | - | |
131 | - }, | |
132 | - mounted() { | |
133 | - console.log('main mounted'); | |
134 | - setInterval(() => { | |
135 | - this.time = this.getCurrentTime(); | |
136 | - }, 1000); | |
137 | - } | |
138 | -} | |
139 | -</script> | |
140 | -<style scoped> | |
141 | -tr { | |
142 | - cursor: pointer; | |
143 | -} | |
144 | -</style>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/Manager/system/commonCodeInsert.vue
... | ... | @@ -1,168 +0,0 @@ |
1 | -<template> | |
2 | - <div class="card "> | |
3 | - <div class="card-body "> | |
4 | - <h2 class="card-title">사용자권한관리</h2> | |
5 | - <p class="require"><img :src="require" alt=""> 필수입력</p> | |
6 | - <form class=" needs-validation detail" @submit.prevent="handleSubmit" | |
7 | - style="margin-bottom: 3rem;"> | |
8 | - <div class="col-12"> | |
9 | - <div class="col-12 border-x"> | |
10 | - <label for="where" class="form-label">상위코드</label> | |
11 | - <input type="text" class="form-control" id="where" v-model="selectedparentCode" /> | |
12 | - <input type="button" class="form-control " value="검색" @click="showPopup = true" /> | |
13 | - <CodePopup v-if="showPopup" @close="showPopup = false" @select="addCode" /> | |
14 | - </div> | |
15 | - <div class="col-12 border-x"> | |
16 | - <label for="where" class="form-label">상위코드 명</label> | |
17 | - <input type="text" class="form-control" id="where" v-model="where" /> | |
18 | - </div> | |
19 | - | |
20 | - </div> | |
21 | - <div class="col-12"> | |
22 | - <div class="col-12 border-x"> | |
23 | - <label for="where" class="form-label"><p>코드<p class="require"><img :src="require" alt=""></p></p></label> | |
24 | - <input type="text" class="form-control" id="where" v-model="where" /> | |
25 | - </div> | |
26 | - <div class="col-12 border-x"> | |
27 | - <label for="where" class="form-label"><p>코드명<p class="require"><img :src="require" alt=""></p></p></label> | |
28 | - <input type="text" class="form-control" id="where" v-model="where" /> | |
29 | - </div> | |
30 | - | |
31 | - </div> | |
32 | - | |
33 | - <div class="col-12 chuljang "> | |
34 | - <label for="prvonsh" class="form-label">설명</label> | |
35 | - <input type="text" class="form-control textarea" id="reason" v-model="reason" /> | |
36 | - </div> | |
37 | - <div class="col-12 border-x input-radio"> | |
38 | - <label for="prvonsh" class="form-label"> <p>사용여부 | |
39 | - <p class="require"><img :src="require" alt=""></p> | |
40 | - </p></label> | |
41 | - <div class="chk-area"> | |
42 | - <div class="form-check"> | |
43 | - <input type="radio" name="rdo_1" id="rdo_1"> | |
44 | - <label for="rdo_1">사용</label> | |
45 | - </div> | |
46 | - <div class="form-check"> | |
47 | - <input type="radio" name="rdo_1" id="rdo_2" checked> | |
48 | - <label for="rdo_2">미사용</label> | |
49 | - </div> | |
50 | - </div> | |
51 | - </div> | |
52 | - | |
53 | - | |
54 | - </form> | |
55 | - <div class="buttons"> | |
56 | - <button type="submit" class="btn sm primary">등록</button> | |
57 | - <button type="reset" class="btn sm tertiary">취소</button> | |
58 | - </div> | |
59 | - </div> | |
60 | - | |
61 | - </div> | |
62 | - | |
63 | -</template> | |
64 | - | |
65 | -<script> | |
66 | -import GoogleCalendar from "../../../component/GoogleCalendar.vue" | |
67 | -import { SearchOutlined } from '@ant-design/icons-vue'; | |
68 | -import CodePopup from "../../../component/Popup/CodePopup.vue"; | |
69 | -export default { | |
70 | - data() { | |
71 | - return { | |
72 | - showPopup: true, | |
73 | - codes: [], | |
74 | - selectedparentCode: '', | |
75 | - require: "/client/resources/img/require.png", | |
76 | - h3icon: "/client/resources/img/h3icon.png", | |
77 | - photoicon: "/client/resources/img/photo_icon.png", | |
78 | - img1: "/client/resources/img/img.png", | |
79 | - icon1: "/client/resources/img/icon.png", | |
80 | - dateicon: "/client/resources/img/date.png", | |
81 | - startbtn: "/client/resources/img/start.png", | |
82 | - stopbtn: "/client/resources/img/stop.png", | |
83 | - moreicon: "/client/resources/img/more.png", | |
84 | - today: new Date().toLocaleDateString('ko-KR', { | |
85 | - year: 'numeric', | |
86 | - month: '2-digit', | |
87 | - day: '2-digit', | |
88 | - weekday: 'short', | |
89 | - }), | |
90 | - time: this.getCurrentTime(), | |
91 | - listData: Array.from({ length: 20 }, (_, i) => ({ | |
92 | - department: `부서 ${i + 1}`, | |
93 | - name: `이름 ${i + 1}`, | |
94 | - position: `직급 ${i + 1}` | |
95 | - })) | |
96 | - } | |
97 | - }, | |
98 | - components: { | |
99 | - SearchOutlined, CodePopup | |
100 | - }, | |
101 | - methods: { | |
102 | - addCode(selectedUser) { | |
103 | - this.codes.push({ | |
104 | - parentCode: selectedUser.parentCode, | |
105 | - }); | |
106 | - | |
107 | - this.selectedparentCode = selectedUser.parentCode; // 입력창에 표시 | |
108 | - this.showPopup = false; | |
109 | - }, | |
110 | - formatBudget(amount) { | |
111 | - return new Intl.NumberFormat().format(amount) + ' 원'; | |
112 | - }, | |
113 | - isPastPeriod(period) { | |
114 | - // 예: '2025-05-01 ~ 2025-05-03' → 종료일 추출 | |
115 | - const endDateStr = period.split('~')[1]?.trim(); | |
116 | - if (!endDateStr) return false; | |
117 | - | |
118 | - const endDate = new Date(endDateStr); | |
119 | - const today = new Date(); | |
120 | - | |
121 | - // 현재 날짜보다 과거면 true | |
122 | - return endDate < today; | |
123 | - }, | |
124 | - getStatusClass(status) { | |
125 | - return status === 'active' ? 'status-active' : 'status-inactive'; | |
126 | - }, | |
127 | - getStatusClass(status) { | |
128 | - if (status === '미진행') return 'status-pending'; | |
129 | - if (status === '진행중') return 'status-approved'; | |
130 | - | |
131 | - // Default empty string | |
132 | - return ''; | |
133 | - }, | |
134 | - getCurrentTime() { | |
135 | - const now = new Date(); | |
136 | - const hours = String(now.getHours()).padStart(2, '0'); | |
137 | - const minutes = String(now.getMinutes()).padStart(2, '0'); | |
138 | - const seconds = String(now.getSeconds()).padStart(2, '0'); | |
139 | - return `${hours}:${minutes}:${seconds}`; | |
140 | - }, | |
141 | - getCategoryClass(category) { | |
142 | - switch (category) { | |
143 | - case '용역': return 'category-service'; | |
144 | - case '내부': return 'category-internal'; | |
145 | - case '국가과제': return 'category-government'; | |
146 | - default: return ''; | |
147 | - } | |
148 | - }, | |
149 | - }, | |
150 | - watch: { | |
151 | - | |
152 | - }, | |
153 | - computed: { | |
154 | - | |
155 | - }, | |
156 | - mounted() { | |
157 | - console.log('main mounted'); | |
158 | - setInterval(() => { | |
159 | - this.time = this.getCurrentTime(); | |
160 | - }, 1000); | |
161 | - } | |
162 | -} | |
163 | -</script> | |
164 | -<style scoped> | |
165 | -tr { | |
166 | - cursor: pointer; | |
167 | -} | |
168 | -</style>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/Manager/system/commonCodeManagement.vue
... | ... | @@ -1,189 +0,0 @@ |
1 | -<template> | |
2 | -<div class="col-lg-12"> | |
3 | - <div class="card"> | |
4 | - <div class="card-body"> | |
5 | - <h2 class="card-title">공통코드관리</h2> | |
6 | - <div class="sch-form-wrap"> | |
7 | - <div class="input-group"> | |
8 | - <select name="" id="" class="form-select"> | |
9 | - <option value="">전체</option> | |
10 | - <option value="">상위코드</option> | |
11 | - <option value="">상위코드명</option> | |
12 | - <option value="">코드</option> | |
13 | - <option value="">코드명</option> | |
14 | - </select> | |
15 | - <div class="sch-input"> | |
16 | - <input type="text" class="form-control"> | |
17 | - <button class="ico-sch"> | |
18 | - <SearchOutlined /> | |
19 | - </button> | |
20 | - </div> | |
21 | - </div> | |
22 | - </div> | |
23 | - | |
24 | - <!-- Table --> | |
25 | - <div class="tbl-wrap"> | |
26 | - <table id="myTable" class="tbl data"> | |
27 | - <!-- 동적으로 <th> 생성 --> | |
28 | - <thead> | |
29 | - <tr> | |
30 | - <th>상위코드 </th> | |
31 | - <th>상위코드명</th> | |
32 | - <th>코드</th> | |
33 | - <th>코드명</th> | |
34 | - <th>등록일</th> | |
35 | - <th>사용여부</th> | |
36 | - </tr> | |
37 | - </thead> | |
38 | - <!-- 동적으로 <td> 생성 --> | |
39 | - <tbody> | |
40 | - <tr v-for="(item, index) in listData" :key="index" :class="{ expired: !isUsed(item.used) }" @click="goToDetailPage(item)"> | |
41 | - <td>{{ item.parentCode }}</td> | |
42 | - <td>{{ item.parentName }}</td> | |
43 | - <td>{{ item.code }}</td> | |
44 | - <td>{{ item.name }}</td> | |
45 | - <td>{{ item.createdAt }}</td> | |
46 | - <td :class="getStatusClass(item.used)">{{ item.used }}</td> | |
47 | - </tr> | |
48 | - </tbody> | |
49 | - </table> | |
50 | - | |
51 | - </div> | |
52 | - <div class="pagination"> | |
53 | - <ul> | |
54 | - <!-- 왼쪽 화살표 (이전 페이지) --> | |
55 | - <li | |
56 | - class="arrow" | |
57 | - :class="{ disabled: currentPage === 1 }" | |
58 | - @click="changePage(currentPage - 1)" | |
59 | - > | |
60 | - < | |
61 | - </li> | |
62 | - | |
63 | - <!-- 페이지 번호 --> | |
64 | - <li | |
65 | - v-for="page in totalPages" | |
66 | - :key="page" | |
67 | - :class="{ active: currentPage === page }" | |
68 | - @click="changePage(page)" | |
69 | - > | |
70 | - {{ page }} | |
71 | - </li> | |
72 | - | |
73 | - <!-- 오른쪽 화살표 (다음 페이지) --> | |
74 | - <li | |
75 | - class="arrow" | |
76 | - :class="{ disabled: currentPage === totalPages }" | |
77 | - @click="changePage(currentPage + 1)" | |
78 | - > | |
79 | - > | |
80 | - </li> | |
81 | - </ul> | |
82 | - </div> | |
83 | - <!-- End Table --> | |
84 | - <div class="buttons"> | |
85 | - <button type="button" class="btn sm sm primary" @click="goToPage('등록') "> | |
86 | - 등록 | |
87 | - </button> | |
88 | - | |
89 | - <!-- 신청 종류 선택 모달 --> | |
90 | - <div v-if="showOptions" class="modal-overlay"> | |
91 | - <div class="modal-box"> | |
92 | - <p>신청 종류를 선택하세요</p> | |
93 | - <button @click="goToPage('휴가')">휴가신청</button> | |
94 | - <button @click="goToPage('출장')">출장신청</button> | |
95 | - <button class="cancel" @click="showOptions = false">취소</button> | |
96 | - </div> | |
97 | - </div> | |
98 | - </div> | |
99 | - </div> | |
100 | - </div> | |
101 | -</div> | |
102 | -</template> | |
103 | - | |
104 | -<script> | |
105 | -import { ref } from 'vue'; | |
106 | -import { SearchOutlined } from '@ant-design/icons-vue'; | |
107 | -export default { | |
108 | - data() { | |
109 | - return { | |
110 | - showOptions: false, | |
111 | - currentPage: 1, | |
112 | - totalPages: 3, | |
113 | - photoicon: "/client/resources/img/photo_icon.png", | |
114 | - // 데이터 초기화 | |
115 | - years: [2023, 2024, 2025], // 연도 목록 | |
116 | - months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], // 월 목록 | |
117 | - selectedYear: '', | |
118 | - selectedMonth: '', | |
119 | - listData: [ | |
120 | - { | |
121 | - parentCode: 'A01', | |
122 | - parentName: '부서코드', | |
123 | - code: 'A0101', | |
124 | - name: '총무부', | |
125 | - createdAt: '2024-01-10', | |
126 | - used: 'Y', | |
127 | - }, | |
128 | - { | |
129 | - parentCode: 'A01', | |
130 | - parentName: '부서코드', | |
131 | - code: 'A0102', | |
132 | - name: '인사부', | |
133 | - createdAt: '2024-03-21', | |
134 | - used: 'N', | |
135 | - },], | |
136 | - filteredData: [], | |
137 | - }; | |
138 | - }, | |
139 | - computed: { | |
140 | - }, | |
141 | - components: { | |
142 | - SearchOutlined | |
143 | - }, | |
144 | - methods: { | |
145 | - goToDetailPage(item) { | |
146 | - // item.id 또는 다른 식별자를 사용하여 URL을 구성할 수 있습니다. | |
147 | - this.$router.push({ name: 'commonCodeDetail', query: { id: item.id } }); | |
148 | - }, | |
149 | - changePage(page) { | |
150 | - if (page < 1 || page > this.totalPages) return; | |
151 | - this.currentPage = page; | |
152 | - this.$emit('page-changed', page); // 필요 시 부모에 알림 | |
153 | - }, | |
154 | - async onClickSubmit() { | |
155 | - // `useMutation` 훅을 사용하여 mutation 함수 가져오기 | |
156 | - const { mutate, onDone, onError } = useMutation(mygql); | |
157 | - | |
158 | - try { | |
159 | - const result = await mutate(); | |
160 | - console.log(result); | |
161 | - } catch (error) { | |
162 | - console.error('Mutation error:', error); | |
163 | - } | |
164 | - }, | |
165 | - goToPage(type) { | |
166 | - if (type === '등록') { | |
167 | - this.$router.push({ name: 'commonCodeInsert' }); | |
168 | - } | |
169 | -}, | |
170 | -getStatusClass(used) { | |
171 | - return used === 'Y' ? 'status-approved' : 'status-pending'; | |
172 | - }, | |
173 | - | |
174 | - isUsed(used) { | |
175 | - return used === 'Y'; | |
176 | - }, | |
177 | - }, | |
178 | - created() { | |
179 | - }, | |
180 | - mounted() { | |
181 | - | |
182 | - | |
183 | - }, | |
184 | -}; | |
185 | -</script> | |
186 | - | |
187 | -<style scoped> | |
188 | -tr{cursor: pointer;} | |
189 | -</style> |
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?