
+++ client/resources/api/cmmnCode.js
... | ... | @@ -0,0 +1,6 @@ |
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/index.js
+++ client/resources/api/index.js
... | ... | @@ -54,7 +54,7 @@ |
54 | 54 |
window.history.back(); |
55 | 55 |
return Promise.reject(error); |
56 | 56 |
} |
57 |
- |
|
57 |
+ |
|
58 | 58 |
// 리프레시 토큰 요청 |
59 | 59 |
if (originalReq.url.includes('/refresh/tknReissue.json')) { |
60 | 60 |
return Promise.reject(error); |
+++ client/resources/api/sanctns.js
... | ... | @@ -0,0 +1,6 @@ |
1 | +import apiClient from "./index"; | |
2 | + | |
3 | +// 조회 - 목록 | |
4 | +export const findSanctnsProc = data => { | |
5 | + return apiClient.get('/sanctn/findSanctns.json', data); | |
6 | +}(파일 끝에 줄바꿈 문자 없음) |
+++ client/resources/api/user.js
... | ... | @@ -0,0 +1,6 @@ |
1 | +import apiClient from "./index"; | |
2 | + | |
3 | +// 조회 - 목록 | |
4 | +export const findUsersProc = data => { | |
5 | + return apiClient.get('/user/users.json', { params: data }); | |
6 | +}(파일 끝에 줄바꿈 문자 없음) |
+++ client/resources/api/vcatn.js
... | ... | @@ -0,0 +1,36 @@ |
1 | +import apiClient from "./index"; | |
2 | + | |
3 | +// 등록 | |
4 | +export const saveVcatnProc = data => { | |
5 | + return apiClient.post('/vcatn/saveVcatn.json', data); | |
6 | +} | |
7 | + | |
8 | +// 조회 - 현황 | |
9 | +export const findVcatnsSummary = () => { | |
10 | + return apiClient.get('/vcatn/findVcatnsSummary.json'); | |
11 | +} | |
12 | + | |
13 | +// 조회 - 목록 | |
14 | +export const findMyVcatnsProc = data => { | |
15 | + return apiClient.get('/vcatn/findMyVcatns.json', { params: data }); | |
16 | +} | |
17 | + | |
18 | +// 조회 - 상세 | |
19 | +export const findVcatnProc = data => { | |
20 | + return apiClient.get(`/vcatn/${data}/findVcatn.json`); | |
21 | +} | |
22 | + | |
23 | +// 조회 - 이전 승인자 | |
24 | +export const findLastVcatnProc = () => { | |
25 | + return apiClient.get('/vcatn/findLastVcatn.json'); | |
26 | +} | |
27 | + | |
28 | +// 삭제 | |
29 | +export const deleteVcatnProc = data => { | |
30 | + return apiClient.delete(`/vcatn/${data}/deleteVcatn.json`); | |
31 | +} | |
32 | + | |
33 | +// 수정 | |
34 | +export const updateVcatnProc = data => { | |
35 | + return apiClient.post('/vcatn/updateVcatn.json', data); | |
36 | +}(파일 끝에 줄바꿈 문자 없음) |
--- client/resources/js/cmmnPlugin.js
+++ client/resources/js/cmmnPlugin.js
... | ... | @@ -1,3 +1,6 @@ |
1 |
+import store from '../../views/pages/AppStore' |
|
2 |
+import { findCodeListProc } from '../api/cmmnCode' |
|
3 |
+ |
|
1 | 4 |
export default { |
2 | 5 |
install(Vue) { |
3 | 6 |
// 빈값체크 |
... | ... | @@ -12,5 +15,108 @@ |
12 | 15 |
return false; |
13 | 16 |
} |
14 | 17 |
} |
18 |
+ |
|
19 |
+ // 게시물 권한 체크 |
|
20 |
+ Vue.config.globalProperties.$registerChk = (register) => { |
|
21 |
+ // 사용자 권한 확인 |
|
22 |
+ const roles = store.state.roles; |
|
23 |
+ if (roles != null && roles.length > 0) { |
|
24 |
+ for (let role of roles) { |
|
25 |
+ if (role.authority === 'ROLE_ADMIN') { |
|
26 |
+ return true; // 관리자인 경우 true 반환 |
|
27 |
+ } |
|
28 |
+ } |
|
29 |
+ } |
|
30 |
+ |
|
31 |
+ // 관리자가 아닌 경우 작성자 확인 |
|
32 |
+ const userId = store.state.userId; |
|
33 |
+ if (register === userId) { |
|
34 |
+ return true; // 작성자인 경우 true 반환 |
|
35 |
+ } else { |
|
36 |
+ return false; // 작성자가 아닌 경우 false 반환 |
|
37 |
+ } |
|
38 |
+ } |
|
39 |
+ |
|
40 |
+ // 공통코드 조회 |
|
41 |
+ Vue.config.globalProperties.$findCodeList = async function (serachRequest) { |
|
42 |
+ try { |
|
43 |
+ const response = await findCodeListProc(serachRequest); |
|
44 |
+ const result = response.data.data; |
|
45 |
+ return result.codeList; |
|
46 |
+ } catch (error) { |
|
47 |
+ if (error.response) { |
|
48 |
+ alert(error.response.data.message); |
|
49 |
+ } else { |
|
50 |
+ alert("에러가 발생했습니다."); |
|
51 |
+ } |
|
52 |
+ console.error(error.message); |
|
53 |
+ throw error; |
|
54 |
+ } |
|
55 |
+ } |
|
56 |
+ |
|
57 |
+ // 날짜 형식 변경 |
|
58 |
+ Vue.config.globalProperties.$formattedDate = (day, hour, min) => { |
|
59 |
+ let beginHour = hour ? hour.toString().padStart(2, '0') : '00'; |
|
60 |
+ let beginMnt = min ? min.toString().padStart(2, '0') : '00'; |
|
61 |
+ |
|
62 |
+ return day.split(' ')[0] + " " + beginHour + ":" + beginMnt |
|
63 |
+ } |
|
64 |
+ |
|
65 |
+ // 공통코드 조회 (부모 코드로 자식 코드 조회) |
|
66 |
+ Vue.config.globalProperties.$findChildCodes = async (upperCode) => { |
|
67 |
+ try { |
|
68 |
+ const searchRequest = { |
|
69 |
+ searchType: 'upperCd', |
|
70 |
+ searchText: upperCode, |
|
71 |
+ }; |
|
72 |
+ |
|
73 |
+ const codes = await Vue.config.globalProperties.$findCodeList(searchRequest); |
|
74 |
+ return Array.isArray(codes) ? codes : []; |
|
75 |
+ } catch (error) { |
|
76 |
+ console.error(`코드 조회 실패 (${upperCode}):`, error); |
|
77 |
+ return []; |
|
78 |
+ } |
|
79 |
+ }; |
|
80 |
+ |
|
81 |
+ // 기본 코드 목록 초기화 |
|
82 |
+ Vue.config.globalProperties.$defaultCodes = async () => { |
|
83 |
+ const codeGroups = { |
|
84 |
+ vcatnKndCodeList: [], // 휴가 종류 (연차/반차) |
|
85 |
+ bsrpCodeList: [], // 출장 종류 (해외/국내) |
|
86 |
+ sanctnCodeList: [], // 결재 구분 (결재/대결/전결) |
|
87 |
+ confmCodeList: [], // 상태 코드 (대기/결재대기/승인/반려) |
|
88 |
+ clsfCodeList: [], // 직급 코드 (사원/주임/대리) |
|
89 |
+ rspofcCodeList: [], // 직책 코드 (사원/주임/대리) |
|
90 |
+ }; |
|
91 |
+ |
|
92 |
+ // 휴가 종류 - depth 2 조회 |
|
93 |
+ const vcatnKndCodes = await Vue.config.globalProperties.$findChildCodes('sanctn_mby_vcatn'); |
|
94 |
+ for (const code of vcatnKndCodes) { |
|
95 |
+ const childCodes = await Vue.config.globalProperties.$findChildCodes(code.code); |
|
96 |
+ codeGroups.vcatnKndCodeList.push(...childCodes); |
|
97 |
+ } |
|
98 |
+ |
|
99 |
+ // 출장 종류 - depth 1 조회 |
|
100 |
+ const bsrpCodes = await Vue.config.globalProperties.$findChildCodes('sanctn_mby_bsrp'); |
|
101 |
+ codeGroups.bsrpCodeList.push(...bsrpCodes); |
|
102 |
+ |
|
103 |
+ // 결재 구분 - depth 1 조회 |
|
104 |
+ const sanctnCodes = await Vue.config.globalProperties.$findChildCodes('sanctn_code'); |
|
105 |
+ codeGroups.sanctnCodeList.push(...sanctnCodes); |
|
106 |
+ |
|
107 |
+ // 상태 코드 - depth 1 조회 |
|
108 |
+ const confmCodes = await Vue.config.globalProperties.$findChildCodes('confm_code'); |
|
109 |
+ codeGroups.confmCodeList.push(...confmCodes); |
|
110 |
+ |
|
111 |
+ // 직급 코드 - depth 1 조회 |
|
112 |
+ const clsfCodes = await Vue.config.globalProperties.$findChildCodes('clsf_code'); |
|
113 |
+ codeGroups.clsfCodeList.push(...clsfCodes); |
|
114 |
+ |
|
115 |
+ // 직책 코드 - depth 1 조회 |
|
116 |
+ const rspofcCodes = await Vue.config.globalProperties.$findChildCodes('rspofc_code'); |
|
117 |
+ codeGroups.rspofcCodeList.push(...rspofcCodes); |
|
118 |
+ |
|
119 |
+ return codeGroups; |
|
120 |
+ }; |
|
15 | 121 |
}, |
16 | 122 |
}(파일 끝에 줄바꿈 문자 없음) |
--- client/views/component/Popup/HrPopup.vue
+++ client/views/component/Popup/HrPopup.vue
... | ... | @@ -1,121 +1,157 @@ |
1 | 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 |
- <div class="sch-input"> |
|
10 |
- <input type="text" class="form-control" placeholder="직원명"> |
|
11 |
- <button class="ico-sch"><SearchOutlined /></button> |
|
12 |
- </div> |
|
13 |
- </div> |
|
14 |
- </div> |
|
15 |
- |
|
16 |
- <!-- Table --> |
|
17 |
- <div class="tbl-wrap"> |
|
18 |
- <table id="myTable" class="tbl data"> |
|
19 |
- <!-- 동적으로 <th> 생성 --> |
|
20 |
- <thead> |
|
21 |
- <tr> |
|
22 |
- <th>직책 </th> |
|
23 |
- <th>직무</th> |
|
24 |
- <th>부서</th> |
|
25 |
- <th>이름</th> |
|
26 |
- <th>아이디</th> |
|
27 |
- <th>선택</th> |
|
28 |
- </tr> |
|
29 |
- </thead> |
|
30 |
- <!-- 동적으로 <td> 생성 --> |
|
31 |
- <tbody> |
|
32 |
- <tr v-for="(item, index) in popuplistData" :key="index"> |
|
33 |
- <td>{{ item.position }}</td> |
|
34 |
- <td>{{ item.role }}</td> |
|
35 |
- <td>{{ item.department }}</td> |
|
36 |
- <td>{{ item.name }}</td> |
|
37 |
- <td>{{ item.id }}</td> |
|
38 |
- <td> |
|
39 |
- <button |
|
40 |
- type="button" |
|
41 |
- class="btn sm secondary" |
|
42 |
- @click="selectPerson(item)" |
|
43 |
- > |
|
44 |
- 선택 |
|
45 |
- </button> |
|
46 |
- </td> |
|
47 |
- </tr> |
|
48 |
- </tbody> |
|
49 |
- </table> |
|
50 |
- |
|
51 |
- </div> |
|
52 |
- <div class="pagination"> |
|
53 |
- <ul> |
|
54 |
- <!-- 왼쪽 화살표 (이전 페이지) --> |
|
55 |
- <li class="arrow" :class="{ disabled: currentPage === 1 }" |
|
56 |
- @click="changePage(currentPage - 1)"> |
|
57 |
- < |
|
58 |
- </li> |
|
59 |
- |
|
60 |
- <!-- 페이지 번호 --> |
|
61 |
- <li v-for="page in totalPages" :key="page" :class="{ active: currentPage === page }" |
|
62 |
- @click="changePage(page)"> |
|
63 |
- {{ page }} |
|
64 |
- </li> |
|
65 |
- |
|
66 |
- <!-- 오른쪽 화살표 (다음 페이지) --> |
|
67 |
- <li class="arrow" :class="{ disabled: currentPage === totalPages }" |
|
68 |
- @click="changePage(currentPage + 1)"> |
|
69 |
- > |
|
70 |
- </li> |
|
71 |
- </ul> |
|
72 |
- </div> |
|
73 |
- <!-- End Table --> |
|
74 |
- </div> |
|
75 |
- </div> |
|
76 |
- <button @click="$emit('close')" class="close-btn"> |
|
77 |
- <CloseCircleFilled /> |
|
78 |
- </button> |
|
79 |
- </div> |
|
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 |
+ <div class="sch-input"> |
|
10 |
+ <input type="text" class="form-control" placeholder="직원명" v-model="request.searchText" @keyup.enter="findDatas"> |
|
11 |
+ <button type="button" class="ico-sch" @click="findDatas"> |
|
12 |
+ <SearchOutlined /> |
|
13 |
+ </button> |
|
80 | 14 |
</div> |
15 |
+ </div> |
|
16 |
+ </div> |
|
17 |
+ <div class="tbl-wrap"> |
|
18 |
+ <table id="myTable" class="tbl data"> |
|
19 |
+ <thead> |
|
20 |
+ <tr> |
|
21 |
+ <th>직급</th> |
|
22 |
+ <th>직책</th> |
|
23 |
+ <th>부서</th> |
|
24 |
+ <th>이름</th> |
|
25 |
+ <th>선택</th> |
|
26 |
+ </tr> |
|
27 |
+ </thead> |
|
28 |
+ <tbody> |
|
29 |
+ <tr v-for="(item, idx) in users" :key="idx"> |
|
30 |
+ <td>{{ getCodeName(item.clsf, 'clsfCodeList') }}</td> |
|
31 |
+ <td>{{ getCodeName(item.rspofc, 'rspofcCodeList') }}</td> |
|
32 |
+ <td>{{ item.userDeptInfo.deptVO.deptNm }}</td> |
|
33 |
+ <td>{{ item.userNm }}</td> |
|
34 |
+ <td> |
|
35 |
+ <button type="button" class="btn sm secondary" @click="selectPerson(item)" :disabled="isUserSelected(item.userId)">선택</button> |
|
36 |
+ </td> |
|
37 |
+ </tr> |
|
38 |
+ </tbody> |
|
39 |
+ </table> |
|
40 |
+ </div> |
|
41 |
+ <Pagenation :search="request" @onChange="fnChangeCurrentPage" /> |
|
42 |
+ </div> |
|
43 |
+ </div> |
|
44 |
+ <button @click="$emit('close')" class="close-btn"> |
|
45 |
+ <CloseCircleFilled /> |
|
46 |
+ </button> |
|
47 |
+ </div> |
|
48 |
+ </div> |
|
81 | 49 |
</template> |
82 | 50 |
<script> |
83 | 51 |
import { SearchOutlined, CloseCircleFilled } from '@ant-design/icons-vue'; |
52 |
+import Pagenation from '../Pagenation.vue'; |
|
53 |
+// API |
|
54 |
+import { findUsersProc } from '../../../resources/api/user'; |
|
84 | 55 |
|
85 | 56 |
export default { |
86 |
- data() { |
|
87 |
- return { |
|
88 |
- popuplistData: [ |
|
89 |
- { |
|
90 |
- position: '과장', |
|
91 |
- role: '인사관리', |
|
92 |
- department: '총무부', |
|
93 |
- name: '김철수', |
|
94 |
- id: 'admin', |
|
95 |
- }, |
|
96 |
- { |
|
97 |
- position: '대리', |
|
98 |
- role: '회계', |
|
99 |
- department: '재무부', |
|
100 |
- name: '이영희', |
|
101 |
- id: 'admin1', |
|
102 |
- }, |
|
103 |
- ], |
|
104 |
- } |
|
105 |
- }, |
|
106 |
- components: { |
|
107 |
- SearchOutlined, CloseCircleFilled |
|
57 |
+ components: { |
|
58 |
+ SearchOutlined, CloseCircleFilled, |
|
59 |
+ Pagenation |
|
108 | 60 |
}, |
61 |
+ |
|
62 |
+ props: { |
|
63 |
+ sanctns: { |
|
64 |
+ type: Array, |
|
65 |
+ default: () => [], |
|
66 |
+ } |
|
67 |
+ }, |
|
68 |
+ |
|
69 |
+ data() { |
|
70 |
+ return { |
|
71 |
+ users: [], |
|
72 |
+ |
|
73 |
+ request: { |
|
74 |
+ searchType: 'nm', // 검색조건 사용자 이름 고정 |
|
75 |
+ searchText: null, // 검색어 |
|
76 |
+ searchSttus: 1, // 회원상태 승인 고정 |
|
77 |
+ searchUseAt: 'Y', // 사용여부 사용 고정 |
|
78 |
+ }, |
|
79 |
+ |
|
80 |
+ cmmnCodes: {}, |
|
81 |
+ } |
|
82 |
+ }, |
|
83 |
+ |
|
84 |
+ computed: { |
|
85 |
+ selectedUserIds() { |
|
86 |
+ return new Set(this.sanctns.map(sanctn => sanctn.confmerId)); |
|
87 |
+ } |
|
88 |
+ }, |
|
89 |
+ |
|
90 |
+ async created() { |
|
91 |
+ this.cmmnCodes = await this.$defaultCodes(); |
|
92 |
+ }, |
|
93 |
+ |
|
94 |
+ mounted() { |
|
95 |
+ this.findDatas(); // 목록 조회 |
|
96 |
+ }, |
|
97 |
+ |
|
109 | 98 |
methods: { |
99 |
+ // 목록 조회 |
|
100 |
+ async findDatas() { |
|
101 |
+ try { |
|
102 |
+ const response = await findUsersProc(this.request); |
|
103 |
+ const result = response.data.data; |
|
104 |
+ |
|
105 |
+ this.users = result.users; |
|
106 |
+ this.request = result.search; |
|
107 |
+ } catch (error) { |
|
108 |
+ if (error.response) { |
|
109 |
+ alert(error.response.data.message); |
|
110 |
+ } else { |
|
111 |
+ alert("에러가 발생했습니다."); |
|
112 |
+ } |
|
113 |
+ console.error(error.message); |
|
114 |
+ } |
|
115 |
+ }, |
|
116 |
+ |
|
117 |
+ // 공통코드명 조회 |
|
118 |
+ getCodeName(code, codeListName) { |
|
119 |
+ if (!code || !this.cmmnCodes[codeListName]) return ''; |
|
120 |
+ const codeItem = this.cmmnCodes[codeListName].find(item => item.code === code); |
|
121 |
+ return codeItem ? codeItem.codeNm : null; |
|
122 |
+ }, |
|
123 |
+ |
|
124 |
+ // 사용자 검증 |
|
125 |
+ isUserSelected(userId) { |
|
126 |
+ return this.selectedUserIds.has(userId); |
|
127 |
+ }, |
|
128 |
+ |
|
129 |
+ // 승인자 선택 |
|
110 | 130 |
selectPerson(item) { |
111 |
- this.$emit('select', item); // 부모에게 데이터 전달 |
|
112 |
- }, |
|
113 |
- |
|
131 |
+ const data = { |
|
132 |
+ confmerId: item.userId, |
|
133 |
+ clsf: item.clsf, |
|
134 |
+ sanctnOrdr: this.sanctns.length + 1, |
|
135 |
+ sanctnSe: this.cmmnCodes.sanctnCodeList[0].code, |
|
136 |
+ |
|
137 |
+ clsfNm: this.getCodeName(item.clsf, 'clsfCodeList'), |
|
138 |
+ userNm: item.userNm, |
|
139 |
+ }; |
|
140 |
+ this.$emit('onSelected', data); |
|
141 |
+ }, |
|
142 |
+ |
|
143 |
+ // 페이지 이동 |
|
144 |
+ fnChangeCurrentPage(currentPage) { |
|
145 |
+ this.request.currentPage = Number(currentPage); |
|
146 |
+ this.$nextTick(() => { |
|
147 |
+ this.findDatas(); |
|
148 |
+ }); |
|
149 |
+ }, |
|
114 | 150 |
} |
115 | 151 |
} |
116 | 152 |
</script> |
117 | 153 |
<style scoped> |
118 | 154 |
.popup-content { |
119 |
- width: 50%; |
|
155 |
+ width: 50%; |
|
120 | 156 |
} |
121 | 157 |
</style>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/component/Sanctn/SanctnList.vue
... | ... | @@ -0,0 +1,193 @@ |
1 | +<template> | |
2 | + <div> | |
3 | + <div v-for="(sanctns, idx) of sanctns" :key="sanctns.sanctnId || idx" class="draggable-item-wrapper"> | |
4 | + <div class="drop-zone" @dragover.prevent="handleDragEnter($event, idx)" @dragenter.prevent="handleDragEnter($event, idx)" @dragleave="handleDragLeave($event, idx)" @drop.prevent="handleDrop($event, idx)" :class="{ | |
5 | + 'drop-active': dropTarget === idx, | |
6 | + 'drop-visible': draggedIndex !== null && shouldShowDropZone(idx), | |
7 | + 'drop-hidden': draggedIndex !== null && !shouldShowDropZone(idx) | |
8 | + }"> | |
9 | + <div class="drop-indicator">여기에 놓기</div> | |
10 | + </div> | |
11 | + <div class="d-flex addapproval draggable-item" draggable="true" @dragstart="handleDragStart(idx, $event)" @dragend="handleDragEnd" :class="{ 'being-dragged': draggedIndex === idx }"> | |
12 | + <select class="form-select" v-model="sanctns.sanctnSe" style="width: 110px;" @mousedown.stop> | |
13 | + <option v-for="(item, idx) of cmmnCodes.sanctnCodeList" :key="idx" :value="item.code"> {{ item.codeNm }} </option> | |
14 | + </select> | |
15 | + <div class="d-flex align-items-center border-x"> | |
16 | + <p>{{ sanctns.userNm }} {{ formatClsf(sanctns.clsfNm) }} ({{ sanctns.sanctnOrdr }})</p> | |
17 | + <button type="button" @click="$emit('delSanctn', idx)" @mousedown.stop> | |
18 | + <CloseOutlined /> | |
19 | + </button> | |
20 | + </div> | |
21 | + </div> | |
22 | + </div> | |
23 | + <div class="drop-zone" @dragover.prevent="handleDragEnter($event, sanctns.length)" @dragenter.prevent="handleDragEnter($event, sanctns.length)" @dragleave="handleDragLeave($event, sanctns.length)" @drop.prevent="handleDrop($event, sanctns.length)" :class="{ | |
24 | + 'drop-active': dropTarget === sanctns.length, | |
25 | + 'drop-visible': draggedIndex !== null && shouldShowLastDropZone(), | |
26 | + 'drop-hidden': draggedIndex !== null && !shouldShowLastDropZone() | |
27 | + }"> | |
28 | + <div class="drop-indicator">여기에 놓기</div> | |
29 | + </div> | |
30 | + </div> | |
31 | +</template> | |
32 | +<script> | |
33 | +import { CloseOutlined } from '@ant-design/icons-vue'; | |
34 | + | |
35 | +export default { | |
36 | + name: 'SanctnList', | |
37 | + | |
38 | + components: { CloseOutlined }, | |
39 | + | |
40 | + props: { | |
41 | + sanctns: { | |
42 | + type: Array, | |
43 | + default: () => [], | |
44 | + } | |
45 | + }, | |
46 | + | |
47 | + data() { | |
48 | + return { | |
49 | + cmmnCodes: {}, // 결재 코드 목록 | |
50 | + draggedIndex: null, | |
51 | + dropTarget: null, | |
52 | + } | |
53 | + }, | |
54 | + | |
55 | + async created() { | |
56 | + this.cmmnCodes = await this.$defaultCodes(); // 코드 목록 초기화 | |
57 | + }, | |
58 | + | |
59 | + methods: { | |
60 | + formatClsf(code) { | |
61 | + const clsfCode = this.cmmnCodes?.clsfCodeList?.find(item => item.code === code); | |
62 | + return clsfCode?.codeNm || code; | |
63 | + }, | |
64 | + | |
65 | + shouldShowDropZone(index) { | |
66 | + if (this.draggedIndex === null) return true; | |
67 | + if (index === this.draggedIndex || index === this.draggedIndex + 1) return false; | |
68 | + return true; | |
69 | + }, | |
70 | + | |
71 | + shouldShowLastDropZone() { | |
72 | + if (this.draggedIndex === null) return true; | |
73 | + return this.draggedIndex !== this.sanctns.length - 1; | |
74 | + }, | |
75 | + | |
76 | + handleDragStart(index, event) { | |
77 | + this.draggedIndex = index; | |
78 | + event.dataTransfer.effectAllowed = 'move'; | |
79 | + event.dataTransfer.setData('text/plain', index.toString()); | |
80 | + }, | |
81 | + | |
82 | + handleDragEnter(event, dropIndex) { | |
83 | + if (this.draggedIndex !== null) { | |
84 | + this.dropTarget = dropIndex; | |
85 | + } | |
86 | + }, | |
87 | + | |
88 | + handleDragLeave(event, dropIndex) { | |
89 | + const rect = event.currentTarget.getBoundingClientRect(); | |
90 | + const x = event.clientX; | |
91 | + const y = event.clientY; | |
92 | + | |
93 | + if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom) { | |
94 | + if (this.dropTarget === dropIndex) { | |
95 | + this.dropTarget = null; | |
96 | + } | |
97 | + } | |
98 | + }, | |
99 | + | |
100 | + handleDrop(event, dropIndex) { | |
101 | + if (this.draggedIndex !== null && this.draggedIndex !== dropIndex) { | |
102 | + let finalDropIndex = dropIndex; | |
103 | + | |
104 | + if (this.draggedIndex < dropIndex) { | |
105 | + finalDropIndex = dropIndex - 1; | |
106 | + } | |
107 | + | |
108 | + const newSanctns = [...this.sanctns]; | |
109 | + const draggedItem = newSanctns.splice(this.draggedIndex, 1)[0]; | |
110 | + newSanctns.splice(finalDropIndex, 0, draggedItem); | |
111 | + | |
112 | + newSanctns.forEach((item, index) => { | |
113 | + item.sanctnOrdr = index + 1; | |
114 | + }); | |
115 | + | |
116 | + this.$emit('update:sanctns', newSanctns); | |
117 | + } | |
118 | + | |
119 | + this.dropTarget = null; | |
120 | + }, | |
121 | + | |
122 | + handleDragEnd() { | |
123 | + this.draggedIndex = null; | |
124 | + this.dropTarget = null; | |
125 | + } | |
126 | + } | |
127 | +}; | |
128 | +</script> | |
129 | +<style scoped> | |
130 | +.draggable-item-wrapper { | |
131 | + position: relative; | |
132 | +} | |
133 | + | |
134 | +.draggable-item { | |
135 | + transition: all 0.3s ease; | |
136 | + border: 2px solid transparent; | |
137 | + background: white; | |
138 | + border-radius: 8px; | |
139 | + padding: 8px; | |
140 | +} | |
141 | + | |
142 | +.being-dragged { | |
143 | + opacity: 0.5; | |
144 | + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); | |
145 | +} | |
146 | + | |
147 | +.drop-zone { | |
148 | + height: 0; | |
149 | + margin: 0; | |
150 | + padding: 0; | |
151 | + border: 2px dashed transparent; | |
152 | + border-radius: 8px; | |
153 | + display: flex; | |
154 | + align-items: center; | |
155 | + justify-content: center; | |
156 | + transition: all 0.2s ease; | |
157 | + opacity: 0; | |
158 | + overflow: hidden; | |
159 | + line-height: 0; | |
160 | + font-size: 0; | |
161 | +} | |
162 | + | |
163 | +.drop-zone.drop-visible { | |
164 | + height: 40px; | |
165 | + margin: 8px 0; | |
166 | + opacity: 1; | |
167 | + border-color: #ddd; | |
168 | + font-size: 14px; | |
169 | + line-height: normal; | |
170 | +} | |
171 | + | |
172 | +.drop-zone.drop-hidden { | |
173 | + height: 0; | |
174 | + margin: 0; | |
175 | + padding: 0; | |
176 | + opacity: 0; | |
177 | + pointer-events: none; | |
178 | + line-height: 0; | |
179 | + font-size: 0; | |
180 | +} | |
181 | + | |
182 | +.drop-zone.drop-active { | |
183 | + border-color: #007bff !important; | |
184 | + background-color: #e3f2fd; | |
185 | +} | |
186 | + | |
187 | +.drop-indicator { | |
188 | + color: #007bff; | |
189 | + font-weight: bold; | |
190 | + font-size: inherit; | |
191 | + pointer-events: none; | |
192 | +} | |
193 | +</style>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/component/editor/EditorComponent.vue
... | ... | @@ -0,0 +1,160 @@ |
1 | +<template> | |
2 | + <ckeditor v-if="editor && config" :model-value="editorContent" :editor="editor" :config="config" @ready="onReady" @update:model-value="updateContents" /> | |
3 | +</template> | |
4 | +<script> | |
5 | +/** | |
6 | + * This configuration was generated using the CKEditor 5 Builder. You can modify it anytime using this link: | |
7 | + * https://ckeditor.com/ckeditor-5/builder/#installation/NoNgNARATAdAzPCkCMAGKIAcmCsrdwghzICcUqqyyALESDnKXFKW6djTdkhANYB7JKjDBkYEZIlhkAXUggAZmxwBjVRFlA== | |
8 | + */ | |
9 | +import { Ckeditor } from '@ckeditor/ckeditor5-vue'; | |
10 | +import { | |
11 | + ClassicEditor, | |
12 | + Alignment, | |
13 | + AutoLink, | |
14 | + BlockQuote, | |
15 | + Bold, | |
16 | + Essentials, | |
17 | + FontBackgroundColor, | |
18 | + FontColor, | |
19 | + FontFamily, | |
20 | + FontSize, | |
21 | + HorizontalLine, | |
22 | + Indent, | |
23 | + IndentBlock, | |
24 | + Italic, | |
25 | + Link, | |
26 | + Paragraph, | |
27 | + RemoveFormat, | |
28 | + Strikethrough, | |
29 | + Subscript, | |
30 | + Superscript, | |
31 | + Table, | |
32 | + TableCaption, | |
33 | + TableCellProperties, | |
34 | + TableColumnResize, | |
35 | + TableProperties, | |
36 | + TableToolbar, | |
37 | + TextPartLanguage, | |
38 | + Underline, | |
39 | +} from 'ckeditor5'; | |
40 | +import translations from 'ckeditor5/translations/ko.js'; | |
41 | +import 'ckeditor5/ckeditor5.css'; | |
42 | +const LICENSE_KEY = 'GPL'; | |
43 | +export default { | |
44 | + name: 'EditorComponent', | |
45 | + components: { | |
46 | + Ckeditor | |
47 | + }, | |
48 | + props: { | |
49 | + contents: { | |
50 | + type: String, | |
51 | + default: '' | |
52 | + } | |
53 | + }, | |
54 | + emits: ['update:contents'], | |
55 | + data() { | |
56 | + return { | |
57 | + isLayoutReady: false, | |
58 | + editor: ClassicEditor, | |
59 | + editorInstance: null, | |
60 | + }; | |
61 | + }, | |
62 | + computed: { | |
63 | + editorContent() { | |
64 | + return this.contents || ''; | |
65 | + }, | |
66 | + config() { | |
67 | + if (!this.isLayoutReady) { | |
68 | + return null; | |
69 | + } | |
70 | + return { | |
71 | + toolbar: { | |
72 | + items: [ | |
73 | + 'fontSize', | |
74 | + 'fontFamily', | |
75 | + 'fontColor', | |
76 | + 'fontBackgroundColor', | |
77 | + '|', | |
78 | + 'bold', | |
79 | + 'italic', | |
80 | + 'underline', | |
81 | + 'strikethrough', | |
82 | + 'subscript', | |
83 | + 'superscript', | |
84 | + 'removeFormat', | |
85 | + '|', | |
86 | + 'horizontalLine', | |
87 | + 'link', | |
88 | + 'insertTable', | |
89 | + 'blockQuote', | |
90 | + '|', | |
91 | + 'alignment', | |
92 | + '|', | |
93 | + 'outdent', | |
94 | + 'indent' | |
95 | + ], | |
96 | + shouldNotGroupWhenFull: true | |
97 | + }, | |
98 | + plugins: [ | |
99 | + Alignment, | |
100 | + AutoLink, | |
101 | + BlockQuote, | |
102 | + Bold, | |
103 | + Essentials, | |
104 | + FontBackgroundColor, | |
105 | + FontColor, | |
106 | + FontFamily, | |
107 | + FontSize, | |
108 | + HorizontalLine, | |
109 | + Indent, | |
110 | + IndentBlock, | |
111 | + Italic, | |
112 | + Link, | |
113 | + Paragraph, | |
114 | + RemoveFormat, | |
115 | + Strikethrough, | |
116 | + Subscript, | |
117 | + Superscript, | |
118 | + Table, | |
119 | + TableCaption, | |
120 | + TableCellProperties, | |
121 | + TableColumnResize, | |
122 | + TableProperties, | |
123 | + TableToolbar, | |
124 | + TextPartLanguage, | |
125 | + Underline, | |
126 | + ], | |
127 | + fontFamily: { | |
128 | + supportAllValues: true | |
129 | + }, | |
130 | + fontSize: { | |
131 | + options: [10, 12, 14, 'default', 18, 20, 22], | |
132 | + supportAllValues: true | |
133 | + }, | |
134 | + language: 'ko', | |
135 | + licenseKey: LICENSE_KEY, | |
136 | + link: { | |
137 | + addTargetToExternalLinks: true, | |
138 | + defaultProtocol: 'https://', | |
139 | + }, | |
140 | + placeholder: '내용을 입력하세요.', | |
141 | + table: { | |
142 | + contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties'] | |
143 | + }, | |
144 | + translations: [translations], | |
145 | + }; | |
146 | + } | |
147 | + }, | |
148 | + mounted() { | |
149 | + this.isLayoutReady = true; | |
150 | + }, | |
151 | + methods: { | |
152 | + onReady(editor) { | |
153 | + this.editorInstance = editor; | |
154 | + }, | |
155 | + updateContents(data) { | |
156 | + this.$emit('update:contents', data); | |
157 | + } | |
158 | + } | |
159 | +}; | |
160 | +</script>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/component/editor/ViewerComponent.vue
... | ... | @@ -0,0 +1,15 @@ |
1 | +<template> | |
2 | + <div class="ck-content" v-html="content"></div> | |
3 | +</template> | |
4 | +<script> | |
5 | +import 'ckeditor5/ckeditor5.css'; | |
6 | +export default { | |
7 | + name: 'ViewerComponent', | |
8 | + props: { | |
9 | + content: { | |
10 | + type: String, | |
11 | + default: '' | |
12 | + } | |
13 | + } | |
14 | +}; | |
15 | +</script>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/layout/Menu.vue
+++ client/views/layout/Menu.vue
... | ... | @@ -35,10 +35,10 @@ |
35 | 35 |
<router-link to="/system-management.page" class="nav-link " active-class="active"> |
36 | 36 |
<span>시스템관리</span></router-link> |
37 | 37 |
</li> |
38 |
- |
|
38 |
+ |
|
39 | 39 |
|
40 | 40 |
</ul><!-- End Profile Dropdown Items --> |
41 |
- |
|
41 |
+ |
|
42 | 42 |
</template> |
43 | 43 |
|
44 | 44 |
<script> |
... | ... | @@ -48,7 +48,7 @@ |
48 | 48 |
return { |
49 | 49 |
isLoggedIn: false, |
50 | 50 |
userName: '', |
51 |
- logo: "/client/resources/img/logo.png", |
|
51 |
+ logo: "/client/resources/img/logo.png", |
|
52 | 52 |
}; |
53 | 53 |
}, |
54 | 54 |
methods: { |
--- client/views/pages/Manager/approval/approvalList.vue
+++ client/views/pages/Manager/approval/approvalList.vue
... | ... | @@ -9,16 +9,16 @@ |
9 | 9 |
<select name="" id="" class="form-select"> |
10 | 10 |
<option :value="currentYear">{{ currentYear }}년</option> |
11 | 11 |
<option value="all">전체</option> |
12 |
- <option v-for="year in remainingYears" :key="year" :value="year" v-if="year !== currentYear"> |
|
13 |
- {{ year }}년 |
|
14 |
- </option> |
|
12 |
+ <template v-for="year in remainingYears" :key="year"> |
|
13 |
+ <option :value="year" v-if="year !== currentYear"> {{ year }}년</option> |
|
14 |
+ </template> |
|
15 | 15 |
</select> |
16 | 16 |
<select name="" id="" class="form-select"> |
17 | 17 |
<option :value="currentMonth">{{ currentMonth }}월</option> |
18 | 18 |
<option value="all">전체</option> |
19 |
- <option v-for="month in remainingMonths" :key="month" :value="month" v-if="month !== currentMonth"> |
|
20 |
- {{ month }}월 |
|
21 |
- </option> |
|
19 |
+ <template v-for="month in remainingMonths" :key="month"> |
|
20 |
+ <option :value="month" v-if="month !== currentMonth"> {{ month }}월</option> |
|
21 |
+ </template> |
|
22 | 22 |
</select> |
23 | 23 |
<div class="sch-input"> |
24 | 24 |
<input type="text" class="form-control" placeholder="신청자명"> |
... | ... | @@ -28,68 +28,52 @@ |
28 | 28 |
</div> |
29 | 29 |
</div> |
30 | 30 |
</div> |
31 |
- |
|
32 |
- <!-- Table --> |
|
33 | 31 |
<div class="tbl-wrap"> |
34 | 32 |
<table id="myTable" class="tbl data"> |
35 |
- <!-- 동적으로 <th> 생성 --> |
|
33 |
+ <colgroup> |
|
34 |
+ <col style="width: 13%;"> |
|
35 |
+ <col style="width: 13%;"> |
|
36 |
+ <col style="width: 13%;"> |
|
37 |
+ <col style="width: 48%;"> |
|
38 |
+ <col style="width: 13%;"> |
|
39 |
+ </colgroup> |
|
36 | 40 |
<thead> |
37 | 41 |
<tr> |
38 |
- <th>구분 </th> |
|
42 |
+ <th>구분</th> |
|
39 | 43 |
<th>결재구분</th> |
40 | 44 |
<th>신청자</th> |
41 | 45 |
<th>기간</th> |
42 | 46 |
<th>신청일</th> |
43 | 47 |
</tr> |
44 | 48 |
</thead> |
45 |
- <!-- 동적으로 <td> 생성 --> |
|
46 | 49 |
<tbody> |
47 |
- <tr v-for="(item, index) in listData" :key="index" :class="{ 'expired': isPastPeriod(item.period) }" @click="goToPage(item)"> |
|
48 |
- <td>{{ item.type }}</td> |
|
49 |
- <td>{{ item.approvalType }}</td> |
|
50 |
- <td>{{ item.applicant }}</td> |
|
51 |
- <td>{{ item.period }}</td> |
|
52 |
- <td>{{ item.requestDate }}</td> |
|
50 |
+ <tr v-for="(item, idx) in waitListData" :key="idx" :class="{ 'expired': true }"> |
|
51 |
+ <td>{{ getCodeName('type', item.iemInfo.vcatnKnd) }}</td> |
|
52 |
+ <td>{{ getCodeName('cate', item.sanctnSe) }}</td> |
|
53 |
+ <td>{{ item.registerInfo.userNm }}</td> |
|
54 |
+ <td>{{ $formattedDate(item.iemInfo.bgnde, item.iemInfo.beginHour, item.iemInfo.beginMnt) }} ~ {{ $formattedDate(item.iemInfo.bgnde, item.iemInfo.beginHour, item.iemInfo.beginMnt) }}</td> |
|
55 |
+ <td>{{ item.registerInfo.userNm }}</td> |
|
53 | 56 |
</tr> |
54 | 57 |
</tbody> |
55 | 58 |
</table> |
56 |
- |
|
57 | 59 |
</div> |
58 |
- <div class="pagination"> |
|
59 |
- <ul> |
|
60 |
- <!-- 왼쪽 화살표 (이전 페이지) --> |
|
61 |
- <li class="arrow" :class="{ disabled: currentPage === 1 }" @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 }" @click="changePage(currentPage + 1)"> |
|
73 |
- > |
|
74 |
- </li> |
|
75 |
- </ul> |
|
76 |
- </div> |
|
60 |
+ <Pagenation :search="waitRequest" @onChange="(currentPage) => fnChangeCurrentPage(currentPage, 'wait')" /> |
|
77 | 61 |
<div class="sch-form-wrap title-wrap"> |
78 | 62 |
<h3><img :src="h3icon" alt="">승인 이력</h3> |
79 | 63 |
<div class="input-group"> |
80 | 64 |
<select name="" id="" class="form-select"> |
81 | 65 |
<option :value="currentYear">{{ currentYear }}년</option> |
82 | 66 |
<option value="all">전체</option> |
83 |
- <option v-for="year in remainingYears" :key="year" :value="year" v-if="year !== currentYear"> |
|
84 |
- {{ year }}년 |
|
85 |
- </option> |
|
67 |
+ <template v-for="year in remainingYears" :key="year"> |
|
68 |
+ <option :value="year" v-if="year !== currentYear"> {{ year }}년 </option> |
|
69 |
+ </template> |
|
86 | 70 |
</select> |
87 | 71 |
<select name="" id="" class="form-select"> |
88 | 72 |
<option :value="currentMonth">{{ currentMonth }}월</option> |
89 | 73 |
<option value="all">전체</option> |
90 |
- <option v-for="month in remainingMonths" :key="month" :value="month" v-if="month !== currentMonth"> |
|
91 |
- {{ month }}월 |
|
92 |
- </option> |
|
74 |
+ <template v-for="month in remainingMonths" :key="month"> |
|
75 |
+ <option :value="month" v-if="month !== currentMonth"> {{ month }}월 </option> |
|
76 |
+ </template> |
|
93 | 77 |
</select> |
94 | 78 |
<select name="" id="" class="form-select"> |
95 | 79 |
<option value="all">상태</option> |
... | ... | @@ -104,14 +88,19 @@ |
104 | 88 |
</div> |
105 | 89 |
</div> |
106 | 90 |
</div> |
107 |
- |
|
108 |
- <!-- Table --> |
|
109 | 91 |
<div class="tbl-wrap"> |
110 | 92 |
<table id="myTable" class="tbl data"> |
111 |
- <!-- 동적으로 <th> 생성 --> |
|
93 |
+ <colgroup> |
|
94 |
+ <col style="width: 13%;"> |
|
95 |
+ <col style="width: 13%;"> |
|
96 |
+ <col style="width: 13%;"> |
|
97 |
+ <col style="width: 35%;"> |
|
98 |
+ <col style="width: 13%;"> |
|
99 |
+ <col style="width: 13%;"> |
|
100 |
+ </colgroup> |
|
112 | 101 |
<thead> |
113 | 102 |
<tr> |
114 |
- <th>구분 </th> |
|
103 |
+ <th>구분</th> |
|
115 | 104 |
<th>결재구분</th> |
116 | 105 |
<th>신청자</th> |
117 | 106 |
<th>기간</th> |
... | ... | @@ -119,53 +108,57 @@ |
119 | 108 |
<th>상태</th> |
120 | 109 |
</tr> |
121 | 110 |
</thead> |
122 |
- <!-- 동적으로 <td> 생성 --> |
|
123 | 111 |
<tbody> |
124 |
- <tr v-for="(item, index) in filteredList" :key="index" :class="{ 'expired': isPastPeriod(item.period) }"> |
|
125 |
- <td>{{ item.type }}</td> |
|
126 |
- <td>{{ item.approvalType }}</td> |
|
127 |
- <td>{{ item.applicant }}</td> |
|
128 |
- <td>{{ item.period }}</td> |
|
129 |
- <td>{{ item.requestDate }}</td> |
|
130 |
- <td :class="getStatusClass(item.status)">{{ item.status }}</td> |
|
112 |
+ <tr v-for="(item, index) in confmListData" :key="index" :class="{ 'expired': true }"> |
|
113 |
+ <td>{{ getCodeName('type', item.iemInfo.vcatnKnd) }}</td> |
|
114 |
+ <td>{{ getCodeName('cate', item.sanctnSe) }}</td> |
|
115 |
+ <td>{{ item.registerInfo.userNm }}</td> |
|
116 |
+ <td>{{ $formattedDate(item.iemInfo.bgnde, item.iemInfo.beginHour, item.iemInfo.beginMnt) }} ~ {{ $formattedDate(item.iemInfo.bgnde, item.iemInfo.beginHour, item.iemInfo.beginMnt) }}</td> |
|
117 |
+ <td>{{ item.registerInfo.userNm }}</td> |
|
118 |
+ <td :class="getStatusClass(item.status)">{{ getCodeName('confm', item.confmAt) }}</td> |
|
131 | 119 |
</tr> |
132 | 120 |
</tbody> |
133 | 121 |
</table> |
134 |
- |
|
135 | 122 |
</div> |
136 |
- <div class="pagination"> |
|
137 |
- <ul> |
|
138 |
- <!-- 왼쪽 화살표 (이전 페이지) --> |
|
139 |
- <li class="arrow" :class="{ disabled: currentPage === 1 }" @click="changePage(currentPage - 1)"> |
|
140 |
- < |
|
141 |
- </li> |
|
142 |
- |
|
143 |
- <!-- 페이지 번호 --> |
|
144 |
- <li v-for="page in totalPages" :key="page" :class="{ active: currentPage === page }" |
|
145 |
- @click="changePage(page)"> |
|
146 |
- {{ page }} |
|
147 |
- </li> |
|
148 |
- |
|
149 |
- <!-- 오른쪽 화살표 (다음 페이지) --> |
|
150 |
- <li class="arrow" :class="{ disabled: currentPage === totalPages }" @click="changePage(currentPage + 1)"> |
|
151 |
- > |
|
152 |
- </li> |
|
153 |
- </ul> |
|
154 |
- </div> |
|
123 |
+ <Pagenation :search="confmRequest" @onChange="(currentPage) => fnChangeCurrentPage(currentPage, 'wait')" /> |
|
155 | 124 |
</div> |
156 | 125 |
</div> |
157 | 126 |
</div> |
158 | 127 |
</template> |
159 |
- |
|
160 | 128 |
<script> |
161 |
-import { ref } from 'vue'; |
|
162 | 129 |
import { SearchOutlined } from '@ant-design/icons-vue'; |
130 |
+import Pagenation from '../../../component/Pagenation.vue'; |
|
131 |
+// API |
|
132 |
+import { findSanctnsProc } from '../../../../resources/api/sanctns'; |
|
133 |
+ |
|
163 | 134 |
const currentYear = new Date().getFullYear(); |
164 | 135 |
const currentMonth = new Date().getMonth() + 1; |
136 |
+ |
|
165 | 137 |
export default { |
138 |
+ components: { |
|
139 |
+ SearchOutlined, |
|
140 |
+ Pagenation, |
|
141 |
+ }, |
|
142 |
+ |
|
166 | 143 |
data() { |
167 | 144 |
return { |
168 |
- selectedStatus: 'all', |
|
145 |
+ photoicon: "/client/resources/img/photo_icon.png", |
|
146 |
+ h3icon: "/client/resources/img/h3icon.png", |
|
147 |
+ |
|
148 |
+ // 목록 조회용 |
|
149 |
+ waitListData: [], |
|
150 |
+ waitRequest: { |
|
151 |
+ sanctnDe: null, // 결재일 |
|
152 |
+ sanctnIem: null, // 결재항목 : 출장 구분 or 휴가 종류 (휴가/출장 구분 코드) |
|
153 |
+ sanctnMbyId: null, // 결재 주체 아이디 : 휴가/출장 아이디 |
|
154 |
+ }, |
|
155 |
+ confmListData: [], |
|
156 |
+ confmRequest: { |
|
157 |
+ sanctnDe: null, // 결재일 |
|
158 |
+ sanctnIem: null, // 결재항목 : 출장 구분 or 휴가 종류 (휴가/출장 구분 코드) |
|
159 |
+ sanctnMbyId: null, // 결재 주체 아이디 : 휴가/출장 아이디 |
|
160 |
+ }, |
|
161 |
+ |
|
169 | 162 |
currentMonth, |
170 | 163 |
selectedMonth: currentMonth, |
171 | 164 |
remainingMonths: Array.from({ length: 12 }, (_, i) => i + 1), |
... | ... | @@ -174,82 +167,157 @@ |
174 | 167 |
remainingYears: Array.from({ length: 10 }, (_, i) => currentYear - i), |
175 | 168 |
currentPage: 1, |
176 | 169 |
totalPages: 3, |
177 |
- photoicon: "/client/resources/img/photo_icon.png", |
|
178 |
- h3icon: "/client/resources/img/h3icon.png", |
|
179 | 170 |
// 데이터 초기화 |
180 | 171 |
years: [2023, 2024, 2025], // 연도 목록 |
181 | 172 |
months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], // 월 목록 |
182 | 173 |
selectedYear: '', |
183 | 174 |
selectedMonth: '', |
184 |
- listData: [ |
|
185 |
- { |
|
186 |
- type: '연차', |
|
187 |
- approvalType: '결재', |
|
188 |
- applicant: '홍길동', |
|
189 |
- period: '2025-05-10 ~ 2025-15-03', |
|
190 |
- requestDate: '2025-04-25', |
|
191 |
- }, { |
|
192 |
- type: '출장-복명', |
|
193 |
- approvalType: '전결', |
|
194 |
- applicant: '홍길동', |
|
195 |
- period: '2025-05-01 ~ 2025-05-03', |
|
196 |
- requestDate: '2025-04-25', |
|
197 |
- }, { |
|
198 |
- type: '출장-품의', |
|
199 |
- approvalType: '전결', |
|
200 |
- applicant: '홍길동', |
|
201 |
- period: '2025-05-01 ~ 2025-05-03', |
|
202 |
- requestDate: '2025-04-25', |
|
203 |
- } |
|
204 |
- ], |
|
205 |
- listData2: [ |
|
206 |
- { |
|
207 |
- type: '연차', |
|
208 |
- approvalType: '결재', |
|
209 |
- applicant: '홍길동', |
|
210 |
- period: '2025-05-10 ~ 2025-15-03', |
|
211 |
- requestDate: '2025-04-25', |
|
212 |
- status: '대기' |
|
213 |
- }, { |
|
214 |
- type: '반차', |
|
215 |
- approvalType: '전결', |
|
216 |
- applicant: '홍길동', |
|
217 |
- period: '2025-05-01 ~ 2025-05-03', |
|
218 |
- requestDate: '2025-04-25', |
|
219 |
- status: '승인' |
|
220 |
- }], |
|
221 |
- filteredData: [], |
|
175 |
+ |
|
176 |
+ // 공통코드 목록 |
|
177 |
+ sanctnCodes: [], // 결재 종류 코드 목록 |
|
178 |
+ sanctnMbyCodes: [], // 결재 항목 코드 목록 |
|
179 |
+ sanctnConfmCodes: [], // 결재 상태 코드 목록 |
|
222 | 180 |
}; |
223 | 181 |
}, |
224 |
- computed: { |
|
225 |
- filteredList() { |
|
226 |
- if (this.selectedStatus === 'all') { |
|
227 |
- return this.listData2; |
|
228 |
- } |
|
229 |
- return this.listData2.filter((item) => item.status === this.selectedStatus); |
|
230 |
- }, |
|
182 |
+ |
|
183 |
+ computed: {}, |
|
184 |
+ |
|
185 |
+ created() { |
|
186 |
+ this.initializeSanctnCodes(); |
|
187 |
+ |
|
188 |
+ console.log("sanctnCodes: ", this.sanctnCodes); |
|
189 |
+ console.log("sanctnMbyCodes: ", this.sanctnMbyCodes); |
|
231 | 190 |
}, |
232 |
- components: { |
|
233 |
- SearchOutlined |
|
191 |
+ |
|
192 |
+ mounted() { |
|
193 |
+ this.findList('wait'); // 목록 조회 |
|
194 |
+ this.findList('confm'); // 목록 조회 |
|
234 | 195 |
}, |
196 |
+ |
|
235 | 197 |
methods: { |
236 |
- goToPage(item) { |
|
237 |
- const type = item.type; |
|
238 |
- if (type === '연차' || type === '반차') { |
|
239 |
- this.$router.push({name: 'Hyuga'}); |
|
240 |
- } else if (type === '출장-품의') { |
|
241 |
- this.$router.push({name: 'ChuljangPumui'}); |
|
242 |
- } else if (type === '출장-복명') { |
|
243 |
- this.$router.push({name: 'ChuljangBokmyeong'}); |
|
244 |
- } else { |
|
245 |
- alert('이동할 수 없는 항목입니다.'); |
|
246 |
- } |
|
247 |
- }, |
|
248 |
- changePage(page) { |
|
249 |
- if (page < 1 || page > this.totalPages) return; |
|
250 |
- this.currentPage = page; |
|
251 |
- this.$emit('page-changed', page); // 필요 시 부모에 알림 |
|
198 |
+ // 결재 관련 코드 초기화 |
|
199 |
+ async initializeSanctnCodes() { |
|
200 |
+ try { |
|
201 |
+ this.sanctnCodes = []; |
|
202 |
+ this.sanctnMbyCodes = []; |
|
203 |
+ |
|
204 |
+ // 순차적으로 코드 조회 및 추가 |
|
205 |
+ const vcatnCodes = await this.findCodeByDepth2('sanctn_mby_vcatn'); // 휴가 종류 |
|
206 |
+ this.sanctnCodes.push(...vcatnCodes); |
|
207 |
+ |
|
208 |
+ const bsrpCodes = await this.findCodeByDepth1('sanctn_mby_bsrp'); // 출장 종류 |
|
209 |
+ this.sanctnCodes.push(...bsrpCodes); |
|
210 |
+ |
|
211 |
+ const sanctnCodes = await this.findCodeByDepth1('sanctn_code'); // 결재 구분 |
|
212 |
+ this.sanctnMbyCodes.push(...sanctnCodes); |
|
213 |
+ |
|
214 |
+ const confmCodes = await this.findCodeByDepth1('confm_code'); // 상태 코드 |
|
215 |
+ this.sanctnConfmCodes.push(...confmCodes); |
|
216 |
+ } catch (error) { |
|
217 |
+ console.error('코드 조회 중 오류 발생:', error); |
|
218 |
+ } |
|
252 | 219 |
}, |
220 |
+ |
|
221 |
+ // 코드 목록 조회 (depth 1) |
|
222 |
+ async findCodeByDepth1(upperCode) { |
|
223 |
+ try { |
|
224 |
+ const searchRequest = { |
|
225 |
+ searchType: 'upperCd', |
|
226 |
+ searchText: upperCode, |
|
227 |
+ }; |
|
228 |
+ |
|
229 |
+ const codes = await this.$findCodeList(searchRequest); |
|
230 |
+ return Array.isArray(codes) ? codes : []; |
|
231 |
+ |
|
232 |
+ } catch (error) { |
|
233 |
+ console.error(`코드 조회 실패 (${upperCode}):`, error); |
|
234 |
+ return []; |
|
235 |
+ } |
|
236 |
+ }, |
|
237 |
+ |
|
238 |
+ // 코드 목록 조회 (depth 2) |
|
239 |
+ async findCodeByDepth2(upperCode) { |
|
240 |
+ try { |
|
241 |
+ const parentCodes = await this.findCodeByDepth1(upperCode); |
|
242 |
+ const childCodes = []; |
|
243 |
+ |
|
244 |
+ for (const code of parentCodes) { |
|
245 |
+ const result = await this.findCodeByDepth1(code.code); |
|
246 |
+ childCodes.push(...result); |
|
247 |
+ } |
|
248 |
+ |
|
249 |
+ return childCodes; |
|
250 |
+ |
|
251 |
+ } catch (error) { |
|
252 |
+ console.error(`하위 코드 조회 실패 (${upperCode}):`, error); |
|
253 |
+ return []; |
|
254 |
+ } |
|
255 |
+ }, |
|
256 |
+ |
|
257 |
+ // 코드 매핑 |
|
258 |
+ getCodeName(type, code) { |
|
259 |
+ let codeList; |
|
260 |
+ |
|
261 |
+ if (type === 'type') { |
|
262 |
+ codeList = this.sanctnCodes; |
|
263 |
+ } else if (type === 'cate') { |
|
264 |
+ codeList = this.sanctnMbyCodes; |
|
265 |
+ } else if (type === 'confm') { |
|
266 |
+ const foundCode = this.sanctnConfmCodes?.find(item => item.codeValue === code); |
|
267 |
+ return foundCode ? foundCode.codeNm : code; |
|
268 |
+ } else { |
|
269 |
+ return code; // 알 수 없는 타입이면 원본 반환 |
|
270 |
+ } |
|
271 |
+ |
|
272 |
+ const foundCode = codeList?.find(item => item.code === code); |
|
273 |
+ return foundCode ? foundCode.codeNm : code; |
|
274 |
+ }, |
|
275 |
+ |
|
276 |
+ // 목록 조회 |
|
277 |
+ async findList(type) { |
|
278 |
+ const vm = this; |
|
279 |
+ |
|
280 |
+ try { |
|
281 |
+ let request = {}; |
|
282 |
+ if (type === 'wait') { |
|
283 |
+ request = vm.waitRequest; |
|
284 |
+ } else if (type == 'confm') { |
|
285 |
+ request = vm.confmRequest; |
|
286 |
+ } |
|
287 |
+ |
|
288 |
+ const response = await findSanctnsProc(request); |
|
289 |
+ const result = response.data.data; |
|
290 |
+ |
|
291 |
+ if (type === 'wait') { |
|
292 |
+ vm.waitListData = result.lists; |
|
293 |
+ vm.waitRequest = result.search; |
|
294 |
+ } else if (type == 'confm') { |
|
295 |
+ vm.confmListData = result.lists; |
|
296 |
+ vm.confmRequest = result.search; |
|
297 |
+ } |
|
298 |
+ } catch (error) { |
|
299 |
+ if (error.response) { |
|
300 |
+ alert(error.response.data.message); |
|
301 |
+ } else { |
|
302 |
+ alert("에러가 발생했습니다."); |
|
303 |
+ } |
|
304 |
+ console.error(error.message); |
|
305 |
+ }; |
|
306 |
+ }, |
|
307 |
+ |
|
308 |
+ // 페이지 이동 |
|
309 |
+ fnChangeCurrentPage(currentPage, type) { |
|
310 |
+ if (type === 'wait') { |
|
311 |
+ this.waitRequest.currentPage = Number(currentPage); |
|
312 |
+ } else if (type === 'confm') { |
|
313 |
+ this.confmRequest.currentPage = Number(currentPage); |
|
314 |
+ } |
|
315 |
+ |
|
316 |
+ this.$nextTick(() => { |
|
317 |
+ this.findList(type); |
|
318 |
+ }); |
|
319 |
+ }, |
|
320 |
+ |
|
253 | 321 |
async onClickSubmit() { |
254 | 322 |
// `useMutation` 훅을 사용하여 mutation 함수 가져오기 |
255 | 323 |
const { mutate, onDone, onError } = useMutation(mygql); |
... | ... | @@ -277,27 +345,11 @@ |
277 | 345 |
if (status === '대기') return 'status-pending'; |
278 | 346 |
return ''; |
279 | 347 |
}, |
280 |
- isPastPeriod(period) { |
|
281 |
- // 예: '2025-05-01 ~ 2025-05-03' → 종료일 추출 |
|
282 |
- const endDateStr = period.split('~')[1]?.trim(); |
|
283 |
- if (!endDateStr) return false; |
|
284 |
- |
|
285 |
- const endDate = new Date(endDateStr); |
|
286 |
- const today = new Date(); |
|
287 |
- |
|
288 |
- // 현재 날짜보다 과거면 true |
|
289 |
- return endDate < today; |
|
290 |
- } |
|
291 |
- }, |
|
292 |
- created() { |
|
293 |
- }, |
|
294 |
- mounted() { |
|
295 |
- |
|
296 |
- |
|
297 | 348 |
}, |
298 | 349 |
}; |
299 | 350 |
</script> |
300 |
- |
|
301 | 351 |
<style scoped> |
302 |
-tr{cursor: pointer;} |
|
352 |
+tr { |
|
353 |
+ cursor: pointer; |
|
354 |
+} |
|
303 | 355 |
</style>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/Manager/attendance/HyugaDetail.vue
+++ client/views/pages/Manager/attendance/HyugaDetail.vue
... | ... | @@ -1,153 +1,266 @@ |
1 | 1 |
<template> |
2 |
-<div class="card "> |
|
3 |
- <div class="card-body"> |
|
4 |
- <h2 class="card-title">휴가 현황</h2> |
|
5 |
- |
|
2 |
+ <div class="card"> |
|
3 |
+ <div class="card-body"> |
|
4 |
+ <h2 class="card-title">휴가 현황</h2> |
|
6 | 5 |
<div class="form-card"> |
7 | 6 |
<h1>휴가신청서</h1> |
8 |
- <div class="approval-box tbl-wrap tbl2"> |
|
9 |
- <table class="tbl data"> |
|
10 |
- <tbody> |
|
11 |
- <tr class="thead"> |
|
12 |
- <td rowspan="2" class="th">승인자</td> |
|
13 |
- <td>과장</td> |
|
14 |
- <td>소장</td> |
|
15 |
- </tr> |
|
16 |
- <tr> |
|
17 |
- <td><p class="name">홍길동</p><p class="date">2025/05/09</p></td> |
|
18 |
- <td><p class="name">홍길동</p><p class="date">2025/05/09</p></td> |
|
19 |
- </tr> |
|
20 |
- </tbody> |
|
21 |
- |
|
22 |
- </table> |
|
7 |
+ <div v-if="detailData.sanctnList && detailData.sanctnList.length > 0" class="approval-box tbl-wrap tbl2"> |
|
8 |
+ <table class="tbl data"> |
|
9 |
+ <tbody> |
|
10 |
+ <tr class="thead"> |
|
11 |
+ <td rowspan="2" class="th">승인자</td> |
|
12 |
+ <template v-for="(item, idx) of detailData.sanctnList" :key="idx"> |
|
13 |
+ <td>{{ fnFindNm(item.clsf) }}</td> |
|
14 |
+ </template> |
|
15 |
+ </tr> |
|
16 |
+ <tr> |
|
17 |
+ <td v-for="(item, idx) of detailData.sanctnList" :key="idx"> |
|
18 |
+ <template v-if="item.confmAt === 'A'"> |
|
19 |
+ <p v-if="item.sanctnSe === 'sanctn_agncy'">(대결)</p> |
|
20 |
+ <p class="name">{{ item.confmerInfo?.userNm || '' }}</p> |
|
21 |
+ <small class="date">{{ new Date(item.sanctnDe).toISOString().split('T')[0] }}</small> |
|
22 |
+ </template> |
|
23 |
+ <template v-else-if="item.confmAt === 'R'"> |
|
24 |
+ <p class="name">반려</p> |
|
25 |
+ </template> |
|
26 |
+ </td> |
|
27 |
+ </tr> |
|
28 |
+ </tbody> |
|
29 |
+ </table> |
|
23 | 30 |
</div> |
24 |
- <form class="row g-3 needs-validation detail" :class="{ 'was-validated': formSubmitted }" @submit.prevent="handleRegister" novalidate> |
|
25 |
- <div class="col-12 "> |
|
26 |
- <div class="col-12 border-x"> |
|
27 |
- <label for="youremail" class="form-label ">유형<p class="require"><img :src="require" alt=""></p></label> |
|
28 |
- <input v-model="email" type="text" name="username" class="form-control" readonly > |
|
29 |
- </div> |
|
30 |
- |
|
31 |
- <div class="col-12 border-x"> |
|
32 |
- <label for="yourPassword" class="form-label">신청자</label> |
|
33 |
- <input v-model="password" type="password" name="password" class="form-control" readonly placeholder="주식회사 테이큰 소프트"> |
|
34 |
- </div> |
|
35 |
- </div> |
|
36 |
- <div class="col-12"> |
|
37 |
- <div class="col-12 border-x"> |
|
38 |
- <label for="youremail" class="form-label">부서</label> |
|
39 |
- <input v-model="email" type="text" name="username" class="form-control" readonly placeholder="과장"> |
|
40 |
- </div> |
|
41 |
- |
|
42 |
- <div class="col-12 border-x"> |
|
43 |
- <label for="yourPassword" class="form-label">직급</label> |
|
44 |
- <input v-model="password" type="password" name="password" class="form-control" readonly placeholder="팀장"> |
|
45 |
- </div> |
|
46 |
- </div> |
|
47 |
- <div class="col-12"> |
|
48 |
- <label for="yourName" class="form-label">기간</label> |
|
49 |
- <input v-model="name" type="text" name="name" class="form-control" readonly> |
|
31 |
+ <form class="row g-3 needs-validation detail" novalidate> |
|
32 |
+ <div class="col-12"> |
|
33 |
+ <div class="col-12 border-x"> |
|
34 |
+ <label for="vcatnType" class="form-label">유형</label> |
|
35 |
+ <p>{{ formattedVcatnKnd }}</p> |
|
50 | 36 |
</div> |
51 |
- <div class="col-12 hyuga"> |
|
52 |
- <label for="yourName" class="form-label">세부사항</label> |
|
53 |
- <input v-model="name" type="text" name="name" class="form-control textarea" readonly> |
|
37 |
+ <div class="col-12 border-x"> |
|
38 |
+ <label for="applicant" class="form-label">신청자</label> |
|
39 |
+ <p>{{ detailData.registerInfo?.userNm || '' }}</p> |
|
54 | 40 |
</div> |
55 |
- <div class="col-12 "> |
|
56 |
- <label for="yourName" class="form-label">신청일</label> |
|
57 |
- <input v-model="name" type="text" name="name" class="form-control " readonly> |
|
41 |
+ </div> |
|
42 |
+ <div class="col-12"> |
|
43 |
+ <div class="col-12 border-x"> |
|
44 |
+ <label for="department" class="form-label">부서</label> |
|
45 |
+ <p>{{ detailData.registerInfo?.userDeptInfo?.deptVO?.deptNm || '' }}</p> |
|
58 | 46 |
</div> |
59 |
- <div class="col-12 border-x return" > |
|
60 |
- <label for="yourName" class="form-label ">반려사유</label> |
|
61 |
- <input v-model="name" type="text" name="name" class="form-control" readonly > |
|
47 |
+ <div class="col-12 border-x"> |
|
48 |
+ <label for="position" class="form-label">직급</label> |
|
49 |
+ <p>{{ formattedClsf }}</p> |
|
62 | 50 |
</div> |
63 |
- |
|
64 |
- |
|
65 |
- </form> |
|
51 |
+ </div> |
|
52 |
+ <div class="col-12"> |
|
53 |
+ <label for="period" class="form-label">기간</label> |
|
54 |
+ <p>{{ formattedPeriod }}</p> |
|
55 |
+ </div> |
|
56 |
+ <div class="col-12 hyuga"> |
|
57 |
+ <label for="details" class="form-label">세부사항</label> |
|
58 |
+ <ViewerComponent :content="detailData.detailCn || ''" /> |
|
59 |
+ </div> |
|
60 |
+ <div class="col-12"> |
|
61 |
+ <label for="requestDate" class="form-label">신청일</label> |
|
62 |
+ <p>{{ detailData.rgsde || '' }}</p> |
|
63 |
+ </div> |
|
64 |
+ <div class="col-12"> |
|
65 |
+ <label for="status" class="form-label">상태</label> |
|
66 |
+ <p>{{ formattedStatus }}</p> |
|
67 |
+ </div> |
|
68 |
+ <div v-if="detailData.confmAt === 'R'" class="col-12 border-x return"> |
|
69 |
+ <label for="rejectReason" class="form-label">반려사유</label> |
|
70 |
+ <template v-for="(item, idx) of detailData.sanctnList" :key="idx"> |
|
71 |
+ <p v-if="item.confmAt === 'R'">{{ item.returnResn || '' }}</p> |
|
72 |
+ </template> |
|
73 |
+ </div> |
|
74 |
+ </form> |
|
66 | 75 |
</div> |
67 |
- <div class="buttons"> |
|
68 |
- <button class="btn btn-red" type="button">신청취소</button> |
|
69 |
- <button class="btn secondary" type="button">재신청</button> |
|
70 |
- <button class="btn secondary" type="button">수정</button> |
|
71 |
- <button class="btn tertiary " type="button">목록</button> |
|
72 |
- </div> |
|
73 |
- <ReturnPopup v-if="showPopup" @close="showPopup = false"/> |
|
76 |
+ <div class="buttons"> |
|
77 |
+ <button v-if="detailData.confmAt === 'W' || detailData.confmAt === 'R'" class="btn btn-red" type="button" @click="deleteData">신청취소</button> |
|
78 |
+ <button v-if="detailData.confmAt === 'W'" class="btn secondary" type="button" @click="fnMoveTo('edit', pageId)">수정</button> |
|
79 |
+ <button v-if="detailData.confmAt === 'R'" class="btn secondary" type="button" @click="reSave">재신청</button> |
|
80 |
+ <button class="btn tertiary" type="button" @click="fnMoveTo('list')">목록</button> |
|
74 | 81 |
</div> |
82 |
+ <ReturnPopup v-if="showPopup" @close="showPopup = false" /> |
|
75 | 83 |
</div> |
84 |
+ </div> |
|
76 | 85 |
</template> |
77 |
- |
|
78 | 86 |
<script> |
79 | 87 |
import ReturnPopup from '../../../component/Popup/ReturnPopup.vue'; |
88 |
+import ViewerComponent from '../../../component/editor/ViewerComponent.vue'; |
|
89 |
+// API |
|
90 |
+import { findVcatnProc, deleteVcatnProc } from '../../../../resources/api/vcatn'; |
|
91 |
+ |
|
80 | 92 |
export default { |
93 |
+ components: { ReturnPopup, ViewerComponent }, |
|
94 |
+ |
|
81 | 95 |
data() { |
82 |
- const today = new Date().toISOString().split('T')[0]; |
|
83 | 96 |
return { |
97 |
+ require: "/client/resources/img/require.png", |
|
98 |
+ |
|
99 |
+ pageId: null, |
|
100 |
+ isRegister: false, |
|
84 | 101 |
showPopup: false, |
85 |
- startDate: today, |
|
86 |
- startTime: "09:00", // 기본 시작 시간 09:00 |
|
87 |
- endDate: today, |
|
88 |
- endTime: "18:00", // 기본 종료 시간 18:00 |
|
89 |
- category: "", |
|
90 |
- dayCount: 1, |
|
91 |
- reason: "", // 사유 |
|
92 |
- listData: [ |
|
93 |
- { |
|
94 |
- type: '연차', |
|
95 |
- approvalType: '결재', |
|
96 |
- applicant: '홍길동', |
|
97 |
- period: '2025-05-10 ~ 2025-15-03', |
|
98 |
- requestDate: '2025-04-25', |
|
99 |
- status: '대기' |
|
100 |
- }, { |
|
101 |
- type: '반차', |
|
102 |
- approvalType: '전결', |
|
103 |
- applicant: '홍길동', |
|
104 |
- period: '2025-05-01 ~ 2025-05-03', |
|
105 |
- requestDate: '2025-04-25', |
|
106 |
- status: '승인' |
|
107 |
- }], |
|
102 |
+ |
|
103 |
+ // 휴가 신청서 정보 |
|
104 |
+ detailData: { |
|
105 |
+ registerInfo: {}, |
|
106 |
+ sanctnList: [], |
|
107 |
+ confmAt: '', |
|
108 |
+ vcatnKnd: '', |
|
109 |
+ clsf: '', |
|
110 |
+ bgnde: '', |
|
111 |
+ endde: '', |
|
112 |
+ detailCn: '', |
|
113 |
+ rgsde: '' |
|
114 |
+ }, |
|
115 |
+ |
|
116 |
+ cmmnCodes: { |
|
117 |
+ vcatnKndCodeList: [], |
|
118 |
+ clsfCodeList: [], |
|
119 |
+ confmCodeList: [] |
|
120 |
+ } |
|
108 | 121 |
}; |
109 | 122 |
}, |
110 |
- components: { |
|
111 |
- ReturnPopup |
|
112 |
- }, |
|
123 |
+ |
|
113 | 124 |
computed: { |
114 |
- |
|
125 |
+ formattedVcatnKnd() { |
|
126 |
+ if (!this.cmmnCodes.vcatnKndCodeList || this.cmmnCodes.vcatnKndCodeList.length === 0) return this.detailData.vcatnKnd; |
|
127 |
+ const vcatnKnd = this.cmmnCodes.vcatnKndCodeList.find(v => v.code === this.detailData.vcatnKnd); |
|
128 |
+ return vcatnKnd ? vcatnKnd.codeNm : this.detailData.vcatnKnd; |
|
129 |
+ }, |
|
130 |
+ |
|
131 |
+ formattedClsf() { |
|
132 |
+ if (!this.cmmnCodes.clsfCodeList || this.cmmnCodes.clsfCodeList.length === 0) return this.detailData.clsf; |
|
133 |
+ const clsf = this.cmmnCodes.clsfCodeList.find(v => v.code === this.detailData.clsf); |
|
134 |
+ return clsf ? clsf.codeNm : this.detailData.clsf; |
|
135 |
+ }, |
|
136 |
+ |
|
137 |
+ formattedStatus() { |
|
138 |
+ if (!this.cmmnCodes.confmCodeList || this.cmmnCodes.confmCodeList.length === 0) return this.detailData.confmAt; |
|
139 |
+ const confmAt = this.cmmnCodes.confmCodeList.find(v => v.codeValue === this.detailData.confmAt); |
|
140 |
+ return confmAt ? confmAt.codeNm : this.detailData.confmAt; |
|
141 |
+ }, |
|
142 |
+ |
|
143 |
+ formattedPeriod() { |
|
144 |
+ if (!this.detailData.bgnde || !this.detailData.endde) return ''; |
|
145 |
+ |
|
146 |
+ const formattedBgnde = this.detailData.bgnde.split(' ')[0]; |
|
147 |
+ const formattedBeginHour = this.detailData.beginHour?.toString().padStart(2, '0') || '00'; |
|
148 |
+ const formattedBeginMnt = this.detailData.beginMnt?.toString().padStart(2, '0') || '00'; |
|
149 |
+ const startDay = `${formattedBgnde} ${formattedBeginHour}:${formattedBeginMnt}`; |
|
150 |
+ |
|
151 |
+ const formattedEndde = this.detailData.endde.split(' ')[0]; |
|
152 |
+ const formattedEndHour = this.detailData.endHour?.toString().padStart(2, '0') || '00'; |
|
153 |
+ const formattedEndMnt = this.detailData.endMnt?.toString().padStart(2, '0') || '00'; |
|
154 |
+ const endDay = `${formattedEndde} ${formattedEndHour}:${formattedEndMnt}`; |
|
155 |
+ |
|
156 |
+ const dayCount = this.calculateDayCount(); |
|
157 |
+ return `${startDay} ~ ${endDay} (${dayCount}일)`; |
|
158 |
+ }, |
|
115 | 159 |
}, |
116 |
- methods: { |
|
117 |
- |
|
118 |
- calculateDayCount() { |
|
119 |
- const start = new Date(`${this.startDate}T${this.startTime}:00`); |
|
120 |
- const end = new Date(`${this.endDate}T${this.endTime}:00`); |
|
121 |
- |
|
122 |
- let totalHours = (end - start) / (1000 * 60 * 60); // 밀리초를 시간 단위로 변환 |
|
123 |
- |
|
124 |
- if (this.startDate !== this.endDate) { |
|
125 |
- // 시작일과 종료일이 다른경우 |
|
126 |
- const startDateObj = new Date(this.startDate); |
|
127 |
- const endDateObj = new Date(this.endDate); |
|
128 |
- const daysDifference = (endDateObj - startDateObj) / (1000 * 60 * 60 * 24); // 두 날짜 사이의 차이를 일수로 계산 |
|
129 |
- if (this.startTime !== "09:00" || this.endTime !== "18:00") { |
|
130 |
- this.dayCount = daysDifference + 0.5; // 시간 조건이 기준에서 벗어날 경우 |
|
131 |
- } else { |
|
132 |
- this.dayCount = Math.ceil(daysDifference + 1); // 시간 조건이 기준에 맞을 경우 |
|
133 |
- } |
|
134 |
- } else { |
|
135 |
- // 시작일과 종료일이 같은 경우 |
|
136 |
- if (this.startTime !== "09:00" || this.endTime !== "18:00") { |
|
137 |
- this.dayCount = 0.5; // 시작 시간 또는 종료 시간이 기준과 다를 경우 0.5 |
|
138 |
- } else { |
|
139 |
- this.dayCount = 1; // 기준 시간(09:00~18:00)이 맞으면 1일로 간주 |
|
140 |
- } |
|
160 |
+ |
|
161 |
+ async created() { |
|
162 |
+ this.pageId = this.$route.query.id; |
|
163 |
+ if (this.$isEmpty(this.pageId)) { |
|
164 |
+ alert("게시물이 존재하지 않습니다."); |
|
165 |
+ this.fnMoveTo('list'); |
|
141 | 166 |
} |
142 | 167 |
|
143 |
- this.validateForm(); // dayCount 변경 후 폼 재검증 |
|
168 |
+ // 코드 목록 초기화 |
|
169 |
+ this.cmmnCodes = await this.$defaultCodes(); |
|
144 | 170 |
}, |
145 |
- |
|
146 |
- |
|
147 |
- |
|
148 |
- }, |
|
171 |
+ |
|
149 | 172 |
mounted() { |
173 |
+ this.findData(); // 상세 조회 |
|
150 | 174 |
}, |
151 |
- |
|
175 |
+ |
|
176 |
+ methods: { |
|
177 |
+ // 상세 조회 |
|
178 |
+ async findData() { |
|
179 |
+ try { |
|
180 |
+ const response = await findVcatnProc(this.pageId); |
|
181 |
+ const result = response.data.data; |
|
182 |
+ |
|
183 |
+ this.detailData = result.vo; |
|
184 |
+ this.isRegister = this.$registerChk(result.vo.register); |
|
185 |
+ } catch (error) { |
|
186 |
+ if (error.response) { |
|
187 |
+ alert(error.response.data.message); |
|
188 |
+ } else { |
|
189 |
+ alert("에러가 발생했습니다."); |
|
190 |
+ } |
|
191 |
+ console.error(error.message); |
|
192 |
+ this.fnMoveTo('list'); |
|
193 |
+ } |
|
194 |
+ }, |
|
195 |
+ |
|
196 |
+ fnFindNm(code) { |
|
197 |
+ if (this.$isEmpty(code)) { |
|
198 |
+ return code; |
|
199 |
+ } |
|
200 |
+ |
|
201 |
+ const clsf = this.cmmnCodes.clsfCodeList.find(v => v.code === code); |
|
202 |
+ return clsf ? clsf.codeNm : code; |
|
203 |
+ }, |
|
204 |
+ |
|
205 |
+ // 일수 계산 |
|
206 |
+ calculateDayCount() { |
|
207 |
+ if (!this.detailData.bgnde || !this.detailData.endde) return 0; |
|
208 |
+ |
|
209 |
+ let dayCnt = 1; // 기본값 |
|
210 |
+ |
|
211 |
+ // 반차인 경우 |
|
212 |
+ if (this.detailData.vcatnKnd === 'MORNING_HALF' || this.detailData.vcatnKnd === 'AFTERNOON_HALF') { |
|
213 |
+ dayCnt = 0.5; |
|
214 |
+ } |
|
215 |
+ |
|
216 |
+ const startDate = new Date(this.detailData.bgnde); |
|
217 |
+ const endDate = new Date(this.detailData.endde); |
|
218 |
+ const timeDiff = endDate.getTime() - startDate.getTime(); |
|
219 |
+ const dayDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24)) + 1; |
|
220 |
+ |
|
221 |
+ return dayCnt * Math.max(0, dayDiff); |
|
222 |
+ }, |
|
223 |
+ |
|
224 |
+ // 삭제 |
|
225 |
+ async deleteData() { |
|
226 |
+ try { |
|
227 |
+ const response = await deleteVcatnProc(this.pageId); |
|
228 |
+ |
|
229 |
+ this.fnMoveTo('list'); |
|
230 |
+ } catch (error) { |
|
231 |
+ if (error.response) { |
|
232 |
+ alert(error.response.data.message); |
|
233 |
+ } else { |
|
234 |
+ alert("에러가 발생했습니다."); |
|
235 |
+ } |
|
236 |
+ console.error(error.message); |
|
237 |
+ this.fnMoveTo('list'); |
|
238 |
+ } |
|
239 |
+ }, |
|
240 |
+ |
|
241 |
+ // 재신청 |
|
242 |
+ reSave() { |
|
243 |
+ this.$router.push({ name: 'hyugaInsert', query: { id: this.pageId } }); |
|
244 |
+ }, |
|
245 |
+ |
|
246 |
+ // 페이지 이동 |
|
247 |
+ fnMoveTo(type, id) { |
|
248 |
+ const routes = { |
|
249 |
+ 'list': { name: 'hyugaStatue' }, |
|
250 |
+ 'view': { name: 'HyugaDetail', query: { id } }, |
|
251 |
+ 'edit': { name: 'hyugaInsert', query: this.$isEmpty(id) ? {} : { id } }, |
|
252 |
+ }; |
|
253 |
+ |
|
254 |
+ if (routes[type]) { |
|
255 |
+ if (!this.$isEmpty(this.pageId) && type === 'list') { |
|
256 |
+ this.$router.push({ name: 'HyugaDetail', query: { id: this.pageId } }); |
|
257 |
+ } |
|
258 |
+ this.$router.push(routes[type]); |
|
259 |
+ } else { |
|
260 |
+ alert("올바르지 않은 경로를 요청하여 목록으로 이동합니다."); |
|
261 |
+ this.$router.push(routes['list']); |
|
262 |
+ } |
|
263 |
+ }, |
|
264 |
+ } |
|
152 | 265 |
}; |
153 |
-</script> |
|
266 |
+</script>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/Manager/attendance/HyugaInsert.vue
+++ client/views/pages/Manager/attendance/HyugaInsert.vue
... | ... | @@ -1,227 +1,466 @@ |
1 | 1 |
<template> |
2 | 2 |
<div class="card"> |
3 |
- |
|
4 | 3 |
<div class="card-body"> |
5 | 4 |
<h2 class="card-title">휴가 신청</h2> |
6 | 5 |
<p class="require"><img :src="require" alt=""> 필수입력</p> |
7 |
- <!-- Multi Columns Form --> |
|
8 |
- <form class="row g-3 needs-validation" @submit.prevent="handleSubmit"> |
|
6 |
+ <div class="row g-3 needs-validation"> |
|
9 | 7 |
<div class="col-12"> |
10 | 8 |
<label for="inputName5" class="form-label"> |
11 |
- <p>유형 |
|
12 |
- <p class="require"><img :src="require" alt=""></p> |
|
13 |
- </p> |
|
9 |
+ <p>유형<span class="require"><img :src="require" alt=""></span></p> |
|
14 | 10 |
</label> |
15 |
- <select id="category" class="form-select" style="max-width: 200px;"> |
|
16 |
- <option value="연차">연차</option> |
|
17 |
- <option value="반차">반차</option> |
|
18 |
- <option value="병가">병가</option> |
|
19 |
- <option value="경조">경조</option> |
|
20 |
- <option value="무급">무급</option> |
|
21 |
- <option value="공가">공가</option> |
|
11 |
+ <select class="form-select" style="max-width: 200px;" v-model="editData.vcatnKnd" @change="fnOnchangeVcatnKnd"> |
|
12 |
+ <option value="" disabled hidden>유형 선택</option> |
|
13 |
+ <option v-for="(item, idx) of cmmnCodes.vcatnKndCodeList" :key="idx" :value="item.code">{{ item.codeNm }}</option> |
|
22 | 14 |
</select> |
15 |
+ <template v-if="showSubTypeSelect"> |
|
16 |
+ <select class="form-select mt-2" style="max-width: 200px;" v-model="editData.vcatnSubKnd" @change="fnOnchangeVcatnSubKnd"> |
|
17 |
+ <option value="" disabled hidden>세부 유형 선택</option> |
|
18 |
+ <option v-for="(item, idx) of subTypes" :key="idx" :value="item.code">{{ item.codeNm }}</option> |
|
19 |
+ </select> |
|
20 |
+ </template> |
|
23 | 21 |
</div> |
24 |
- |
|
25 | 22 |
<div class="col-12"> |
26 |
- <label for="startDate" class="form-label"> |
|
27 |
- <p>시작일 |
|
28 |
- <p class="require"><img :src="require" alt=""></p> |
|
29 |
- </p> |
|
23 |
+ <label for="bgnde" class="form-label"> |
|
24 |
+ <p>시작일<span class="require"><img :src="require" alt=""></span></p> |
|
30 | 25 |
</label> |
31 | 26 |
<div class="d-flex gap-1"> |
32 |
- <input type="date" class="form-control" id="startDate" v-model="startDate" /> |
|
33 |
- <!-- 시간 선택을 위한 select 사용 --> |
|
34 |
- <select class="form-control" id="startTime" v-model="startTime"> |
|
35 |
- <option value="09:00">09:00</option> |
|
36 |
- <option value="10:00">10:00</option> |
|
37 |
- <option value="11:00">11:00</option> |
|
38 |
- <option value="12:00">12:00</option> |
|
39 |
- <option value="13:00">13:00</option> |
|
40 |
- <option value="14:00">14:00</option> |
|
41 |
- <option value="15:00">15:00</option> |
|
42 |
- <option value="16:00">16:00</option> |
|
43 |
- <option value="17:00">17:00</option> |
|
44 |
- <option value="18:00">18:00</option> |
|
45 |
- </select> |
|
27 |
+ <input type="date" class="form-control" id="bgnde" v-model="editData.bgnde" @keydown="preventKeyboard" /> |
|
28 |
+ <input type="text" class="form-control" placeholder="시" v-model="editData.beginHour" readonly /> |
|
29 |
+ <input type="text" class="form-control" placeholder="분" v-model="editData.beginMnt" readonly /> |
|
46 | 30 |
</div> |
47 | 31 |
</div> |
48 |
- |
|
49 | 32 |
<div class="col-12"> |
50 |
- <label for="endDate" class="form-label"> |
|
51 |
- <p>종료일 |
|
52 |
- <p class="require"><img :src="require" alt=""></p> |
|
53 |
- </p> |
|
33 |
+ <label for="endde" class="form-label"> |
|
34 |
+ <p>종료일<span class="require"><img :src="require" alt=""></span></p> |
|
54 | 35 |
</label> |
55 | 36 |
<div class="d-flex gap-1"> |
56 |
- <input type="date" class="form-control" id="endDate" v-model="endDate" /> |
|
57 |
- <!-- 종료 시간을 위한 select 사용 --> |
|
58 |
- <select class="form-control" id="endTime" v-model="endTime"> |
|
59 |
- <option value="09:00">09:00</option> |
|
60 |
- <option value="10:00">10:00</option> |
|
61 |
- <option value="11:00">11:00</option> |
|
62 |
- <option value="12:00">12:00</option> |
|
63 |
- <option value="13:00">13:00</option> |
|
64 |
- <option value="14:00">14:00</option> |
|
65 |
- <option value="15:00">15:00</option> |
|
66 |
- <option value="16:00">16:00</option> |
|
67 |
- <option value="17:00">17:00</option> |
|
68 |
- <option value="18:00">18:00</option> |
|
69 |
- </select> |
|
37 |
+ <input type="date" class="form-control" id="endde" v-model="editData.endde" :readonly="dayCnt === 0.5" @keydown="preventKeyboard" /> |
|
38 |
+ <input type="text" class="form-control" placeholder="시" v-model="editData.endHour" readonly /> |
|
39 |
+ <input type="text" class="form-control" placeholder="분" v-model="editData.endMnt" readonly /> |
|
70 | 40 |
</div> |
71 | 41 |
</div> |
72 |
- |
|
73 | 42 |
<div class="col-12"> |
74 |
- <label for="dayCount" class="form-label">사용 휴가일</label> |
|
75 |
- <input type="text" class="form-control" id="dayCount" v-model="dayCount" readonly /> |
|
43 |
+ <label for="totalDays" class="form-label">사용 휴가일</label> |
|
44 |
+ <input type="text" class="form-control" id="totalDays" v-model="totalDays" readonly /> |
|
76 | 45 |
</div> |
77 |
- |
|
78 | 46 |
<div class="col-12"> |
79 | 47 |
<label for="member" class="form-label"> |
80 |
- 승인자 |
|
81 |
- <button type="button" title="추가" @click="showPopup = true"> |
|
48 |
+ <span>승인자<span class="require"><img :src="require" alt=""></span></span> |
|
49 |
+ <button type="button" title="추가" @click="isOpenModal = true"> |
|
82 | 50 |
<PlusCircleFilled /> |
83 | 51 |
</button> |
84 | 52 |
</label> |
85 |
- <HrPopup v-if="showPopup" @close="showPopup = false" @select="addApproval" /> |
|
86 |
- <!-- 반복 렌더링되는 addapproval 항목 --> |
|
53 |
+ <HrPopup v-if="isOpenModal" :sanctns="editData.sanctnList" @onSelected="fnAddSanctn" @close="isOpenModal = false" /> |
|
87 | 54 |
<div class="approval-container"> |
88 |
- <div v-for="(approval, index) in approvals" :key="index" class="d-flex gap-2 addapproval mb-2"> |
|
89 |
- <select class="form-select" v-model="approval.category" style="width: 110px;"> |
|
90 |
- <option value="결재">결재</option> |
|
91 |
- <option value="전결">전결</option> |
|
92 |
- <option value="대결">대결</option> |
|
93 |
- </select> |
|
94 |
- |
|
95 |
- <form class="d-flex align-items-center border-x"> |
|
96 |
- <input type="text" class="form-control" v-model="approval.name" style="max-width: 150px;" /> |
|
97 |
- <button type="button" @click="removeApproval(index)" class="delete-button"> |
|
98 |
- <CloseOutlined /> |
|
99 |
- </button> |
|
100 |
- </form> |
|
101 |
- </div> |
|
55 |
+ <SanctnList v-model:sanctns="editData.sanctnList" @delSanctn="fnDelSanctn" /> |
|
102 | 56 |
</div> |
103 | 57 |
</div> |
104 | 58 |
<div class="col-12 border-x hyuga"> |
105 | 59 |
<label for="prvonsh" class="form-label">세부사항</label> |
106 |
- <input type="text" class="form-control textarea" id="reason" v-model="reason" /> |
|
60 |
+ <div> |
|
61 |
+ <EditorComponent v-model:contents="editData.detailCn" /> |
|
62 |
+ </div> |
|
107 | 63 |
</div> |
108 |
- |
|
109 |
- |
|
110 |
- </form><!-- End Multi Columns Form --> |
|
64 |
+ </div> |
|
111 | 65 |
<div class="buttons"> |
112 |
- <button type="submit" class="btn btn-red">이전 승인자 불러오기</button> |
|
113 |
- <button type="submit" class="btn primary">신청</button> |
|
114 |
- <button type="reset" class="btn tertiary">취소</button> |
|
66 |
+ <button type="button" class="btn btn-red" @click="fnRecord">이전 승인자 불러오기</button> |
|
67 |
+ <button type="button" class="btn primary" @click="fnSave">신청</button> |
|
68 |
+ <button type="reset" class="btn tertiary" @click="fnMoveTo('list')">취소</button> |
|
115 | 69 |
</div> |
116 | 70 |
</div> |
117 | 71 |
</div> |
118 | 72 |
</template> |
119 |
- |
|
120 | 73 |
<script> |
121 | 74 |
import { PlusCircleFilled, CloseOutlined } from '@ant-design/icons-vue'; |
122 | 75 |
import HrPopup from '../../../component/Popup/HrPopup.vue'; |
76 |
+import SanctnList from '../../../component/Sanctn/SanctnList.vue'; |
|
77 |
+import EditorComponent from '../../../component/editor/EditorComponent.vue'; |
|
78 |
+// API |
|
79 |
+import { findVcatnProc, saveVcatnProc, findLastVcatnProc, updateVcatnProc } from '../../../../resources/api/vcatn'; |
|
80 |
+ |
|
123 | 81 |
export default { |
82 |
+ components: { |
|
83 |
+ PlusCircleFilled, |
|
84 |
+ CloseOutlined, |
|
85 |
+ HrPopup, |
|
86 |
+ SanctnList, |
|
87 |
+ EditorComponent, |
|
88 |
+ }, |
|
89 |
+ |
|
124 | 90 |
data() { |
125 |
- const today = new Date().toISOString().split('T')[0]; |
|
126 | 91 |
return { |
127 |
- showPopup: false, |
|
128 |
- approvals: [], |
|
129 | 92 |
require: "/client/resources/img/require.png", |
130 |
- startDate: today, |
|
131 |
- startTime: "09:00", // 기본 시작 시간 09:00 |
|
132 |
- endDate: today, |
|
133 |
- endTime: "18:00", // 기본 종료 시간 18:00 |
|
134 |
- category: "", |
|
135 |
- dayCount: 1, |
|
136 |
- reason: "", // 사유 |
|
93 |
+ pageId: null, |
|
94 |
+ isOpenModal: false, |
|
95 |
+ editData: { |
|
96 |
+ vcatnId: null, |
|
97 |
+ userId: null, |
|
98 |
+ vcatnKnd: '', |
|
99 |
+ vcatnSubKnd: '', // 세부 유형 추가 |
|
100 |
+ deptId: null, |
|
101 |
+ clsf: null, |
|
102 |
+ bgnde: null, |
|
103 |
+ beginHour: null, |
|
104 |
+ beginMnt: null, |
|
105 |
+ endde: null, |
|
106 |
+ endHour: null, |
|
107 |
+ endMnt: null, |
|
108 |
+ detailCn: null, |
|
109 |
+ confmAt: null, |
|
110 |
+ sanctnList: [], |
|
111 |
+ }, |
|
112 |
+ dayCnt: 0, |
|
113 |
+ totalDays: 0, |
|
114 |
+ cmmnCodes: {}, |
|
115 |
+ workConfig: { |
|
116 |
+ startHour: 9, // 근무 시작 시간 |
|
117 |
+ endHour: 18, // 근무 종료 시간 |
|
118 |
+ lunchStart: 12, // 점심 시작 시간 |
|
119 |
+ lunchEnd: 13, // 점심 종료 시간 |
|
120 |
+ }, |
|
121 |
+ subTypes: [], |
|
137 | 122 |
}; |
138 | 123 |
}, |
139 |
- components: { |
|
140 |
- PlusCircleFilled, CloseOutlined, HrPopup |
|
141 |
- }, |
|
124 |
+ |
|
142 | 125 |
computed: { |
143 |
- // Pinia Store의 상태를 가져옵니다. |
|
144 |
- loginUser() { |
|
145 |
- const authStore = useAuthStore(); |
|
146 |
- return authStore.getLoginUser; |
|
147 |
- }, |
|
126 |
+ // 세부 유형 선택박스를 보여줄지 여부 |
|
127 |
+ showSubTypeSelect() { |
|
128 |
+ return this.dayCnt === 0.5 && this.subTypes.length > 0; |
|
129 |
+ } |
|
148 | 130 |
}, |
149 |
- methods: { |
|
150 |
- addApproval(selectedUser) { |
|
151 |
- this.approvals.push({ |
|
152 |
- category: '결재', |
|
153 |
- name: selectedUser.name, // or other fields if needed |
|
154 |
- }); |
|
155 |
- this.showPopup = false; // 팝업 닫기 |
|
156 |
- }, |
|
157 |
- // 승인자 삭제 |
|
158 |
- removeApproval(index) { |
|
159 |
- this.approvals.splice(index, 1); |
|
160 |
- }, |
|
161 |
- validateForm() { |
|
162 |
- // 필수 입력 필드 체크 |
|
163 |
- if ( |
|
164 |
- this.category && |
|
165 |
- this.startDate && |
|
166 |
- this.startTime && |
|
167 |
- this.endDate && |
|
168 |
- this.endTime && |
|
169 |
- this.dayCount > 0 && |
|
170 |
- this.reason.trim() !== "" |
|
171 |
- ) { |
|
172 |
- this.isFormValid = true; |
|
173 |
- } else { |
|
174 |
- this.isFormValid = false; |
|
131 |
+ |
|
132 |
+ async created() { |
|
133 |
+ this.pageId = this.$route.query.id; |
|
134 |
+ this.cmmnCodes = await this.$defaultCodes(); |
|
135 |
+ for (const vcatnType of this.cmmnCodes.vcatnKndCodeList) { |
|
136 |
+ if (parseFloat(vcatnType.codeValue) === 0.5) { |
|
137 |
+ this.subTypes = await this.$findChildCodes(vcatnType.code); |
|
138 |
+ break; |
|
175 | 139 |
} |
176 |
- }, |
|
177 |
- calculateDayCount() { |
|
178 |
- const start = new Date(`${this.startDate}T${this.startTime}:00`); |
|
179 |
- const end = new Date(`${this.endDate}T${this.endTime}:00`); |
|
180 |
- |
|
181 |
- let totalHours = (end - start) / (1000 * 60 * 60); // 밀리초를 시간 단위로 변환 |
|
182 |
- |
|
183 |
- if (this.startDate !== this.endDate) { |
|
184 |
- // 시작일과 종료일이 다른경우 |
|
185 |
- const startDateObj = new Date(this.startDate); |
|
186 |
- const endDateObj = new Date(this.endDate); |
|
187 |
- const daysDifference = (endDateObj - startDateObj) / (1000 * 60 * 60 * 24); // 두 날짜 사이의 차이를 일수로 계산 |
|
188 |
- if (this.startTime !== "09:00" || this.endTime !== "18:00") { |
|
189 |
- this.dayCount = daysDifference + 0.5; // 시간 조건이 기준에서 벗어날 경우 |
|
190 |
- } else { |
|
191 |
- this.dayCount = Math.ceil(daysDifference + 1); // 시간 조건이 기준에 맞을 경우 |
|
192 |
- } |
|
193 |
- } else { |
|
194 |
- // 시작일과 종료일이 같은 경우 |
|
195 |
- if (this.startTime !== "09:00" || this.endTime !== "18:00") { |
|
196 |
- this.dayCount = 0.5; // 시작 시간 또는 종료 시간이 기준과 다를 경우 0.5 |
|
197 |
- } else { |
|
198 |
- this.dayCount = 1; // 기준 시간(09:00~18:00)이 맞으면 1일로 간주 |
|
199 |
- } |
|
200 |
- } |
|
201 |
- |
|
202 |
- this.validateForm(); // dayCount 변경 후 폼 재검증 |
|
203 |
- }, |
|
204 |
- handleSubmit() { |
|
205 |
- this.validateForm(); // 제출 시 유효성 확인 |
|
206 |
- if (this.isFormValid) { |
|
207 |
- localStorage.setItem('HyugaFormData', JSON.stringify(this.$data)); |
|
208 |
- alert("승인 요청이 완료되었습니다."); |
|
209 |
- // 추가 처리 로직 (API 요청 등) |
|
210 |
- } else { |
|
211 |
- alert("모든 필드를 올바르게 작성해주세요."); |
|
212 |
- } |
|
213 |
- }, |
|
214 |
- |
|
140 |
+ } |
|
215 | 141 |
}, |
142 |
+ |
|
216 | 143 |
mounted() { |
144 |
+ if (!this.$isEmpty(this.pageId)) { |
|
145 |
+ this.findData(); |
|
146 |
+ } |
|
217 | 147 |
}, |
148 |
+ |
|
218 | 149 |
watch: { |
219 |
- startDate: 'calculateDayCount', |
|
220 |
- startTime: 'calculateDayCount', |
|
221 |
- endDate: 'calculateDayCount', |
|
222 |
- endTime: 'calculateDayCount', |
|
223 |
- reason: "validateForm", |
|
224 |
- category: 'category', |
|
150 |
+ 'editData.bgnde'(newVal, oldVal) { |
|
151 |
+ if (newVal !== oldVal) { |
|
152 |
+ this.changeBgnde(); |
|
153 |
+ } |
|
154 |
+ }, |
|
155 |
+ 'editData.endde'(newVal, oldVal) { |
|
156 |
+ if (newVal !== oldVal) { |
|
157 |
+ this.validateAndCalculateDays(); // calculateTotalDays 대신 validateAndCalculateDays 호출 |
|
158 |
+ } |
|
159 |
+ }, |
|
160 |
+ }, |
|
161 |
+ |
|
162 |
+ methods: { |
|
163 |
+ async findData() { |
|
164 |
+ try { |
|
165 |
+ const response = await findVcatnProc(this.pageId); |
|
166 |
+ const result = response.data.data; |
|
167 |
+ |
|
168 |
+ this.editData = result.vo; |
|
169 |
+ this.editData.bgnde = this.editData.bgnde.split(' ')[0]; |
|
170 |
+ this.editData.endde = this.editData.endde.split(' ')[0]; |
|
171 |
+ |
|
172 |
+ let sanctns = []; |
|
173 |
+ for (let sanctn of this.editData.sanctnList) { |
|
174 |
+ console.log("sanctn: ", sanctn); |
|
175 |
+ let data = { |
|
176 |
+ confmerId: sanctn.confmerId, |
|
177 |
+ clsf: sanctn.clsf, |
|
178 |
+ sanctnOrdr: sanctn.sanctnOrdr, |
|
179 |
+ sanctnSe: sanctn.sanctnSe, |
|
180 |
+ clsfNm: sanctn.confmerInfo?.clsf, |
|
181 |
+ userNm: sanctn.confmerInfo?.userNm |
|
182 |
+ } |
|
183 |
+ sanctns.push(data); |
|
184 |
+ } |
|
185 |
+ this.editData.sanctnList = sanctns; |
|
186 |
+ |
|
187 |
+ // cmmnCodes가 초기화되었는지 확인 후 호출 |
|
188 |
+ if (this.cmmnCodes && this.cmmnCodes.vcatnKndCodeList) { |
|
189 |
+ await this.fnOnchangeVcatnKnd(); |
|
190 |
+ } else { |
|
191 |
+ console.warn('cmmnCodes가 아직 초기화되지 않았습니다.'); |
|
192 |
+ } |
|
193 |
+ } catch (error) { |
|
194 |
+ console.error('데이터 조회 실패:', error); |
|
195 |
+ const message = error.response?.data?.message || "데이터를 불러오는데 실패했습니다."; |
|
196 |
+ alert(message); |
|
197 |
+ this.fnMoveTo('list'); |
|
198 |
+ } |
|
199 |
+ }, |
|
200 |
+ |
|
201 |
+ // 유형 변경 |
|
202 |
+ async fnOnchangeVcatnKnd() { |
|
203 |
+ // 안전성 검사 추가 |
|
204 |
+ if (!this.cmmnCodes || !this.cmmnCodes.vcatnKndCodeList || !Array.isArray(this.cmmnCodes.vcatnKndCodeList)) { |
|
205 |
+ console.warn('cmmnCodes.vcatnKndCodeList가 초기화되지 않았거나 배열이 아닙니다.'); |
|
206 |
+ return; |
|
207 |
+ } |
|
208 |
+ |
|
209 |
+ const selectedVcatn = this.cmmnCodes.vcatnKndCodeList.find(item => item.code === this.editData.vcatnKnd); |
|
210 |
+ if (!selectedVcatn) { |
|
211 |
+ console.warn('선택된 휴가 유형을 찾을 수 없습니다.'); |
|
212 |
+ return; |
|
213 |
+ } |
|
214 |
+ |
|
215 |
+ this.dayCnt = parseFloat(selectedVcatn.codeValue); |
|
216 |
+ |
|
217 |
+ if (this.dayCnt === 0.5) { |
|
218 |
+ this.changeBgnde(); // 반차일 경우 종료일을 시작일과 동일하게 설정 |
|
219 |
+ } else { |
|
220 |
+ // 반차가 아닌 경우 |
|
221 |
+ this.editData.vcatnSubKnd = ''; // 세부 유형 선택 초기화 |
|
222 |
+ |
|
223 |
+ // 전체 근무시간으로 설정 |
|
224 |
+ this.editData.beginHour = this.workConfig.startHour.toString().padStart(2, '0'); |
|
225 |
+ this.editData.beginMnt = '00'; |
|
226 |
+ this.editData.endHour = this.workConfig.endHour.toString().padStart(2, '0'); |
|
227 |
+ this.editData.endMnt = '00'; |
|
228 |
+ this.calculateTotalDays(); |
|
229 |
+ } |
|
230 |
+ }, |
|
231 |
+ |
|
232 |
+ // 세부 유형 변경 |
|
233 |
+ fnOnchangeVcatnSubKnd() { |
|
234 |
+ if (this.dayCnt === 0.5) { |
|
235 |
+ const selectedSubType = this.subTypes.find(item => item.code === this.editData.vcatnSubKnd); |
|
236 |
+ if (selectedSubType) { |
|
237 |
+ this.setHalfDayTime(selectedSubType); |
|
238 |
+ } |
|
239 |
+ } |
|
240 |
+ this.calculateTotalDays(); |
|
241 |
+ }, |
|
242 |
+ |
|
243 |
+ // 반차 시간 설정 메서드 |
|
244 |
+ setHalfDayTime(selectedSubType) { |
|
245 |
+ const codeValue = selectedSubType.codeValue; |
|
246 |
+ |
|
247 |
+ // 전체 실제 근무시간 계산 (점심시간 제외) |
|
248 |
+ const totalHours = this.workConfig.endHour - this.workConfig.startHour; // 전체 시간 |
|
249 |
+ const lunchHours = this.workConfig.lunchEnd - this.workConfig.lunchStart; // 점심시간 |
|
250 |
+ const actualWorkHours = totalHours - lunchHours; // 실제 근무시간 |
|
251 |
+ const halfWorkHours = actualWorkHours / 2; // 반차 시간 |
|
252 |
+ |
|
253 |
+ this.editData.beginMnt = '00'; |
|
254 |
+ this.editData.endMnt = '00'; |
|
255 |
+ |
|
256 |
+ if (codeValue === 'AM') { |
|
257 |
+ this.editData.beginHour = this.workConfig.startHour.toString().padStart(2, '0'); |
|
258 |
+ this.editData.endHour = this.calculateTimeWithLunch(this.workConfig.startHour, halfWorkHours, 1).toString().padStart(2, '0'); |
|
259 |
+ } else if (codeValue === 'PM') { |
|
260 |
+ this.editData.beginHour = this.calculateTimeWithLunch(this.workConfig.endHour, halfWorkHours, -1).toString().padStart(2, '0'); |
|
261 |
+ this.editData.endHour = this.workConfig.endHour.toString().padStart(2, '0'); |
|
262 |
+ } |
|
263 |
+ }, |
|
264 |
+ |
|
265 |
+ // 점심시간을 고려하여 시간 계산 (방향: 1=앞으로, -1=뒤로) |
|
266 |
+ calculateTimeWithLunch(startTime, workHours, direction = 1) { |
|
267 |
+ let currentHour = startTime; |
|
268 |
+ let remainingHours = workHours; |
|
269 |
+ |
|
270 |
+ while (remainingHours > 0) { |
|
271 |
+ if (direction === 1) { |
|
272 |
+ // 앞으로 계산 (종료시간 구하기) |
|
273 |
+ if (currentHour >= this.workConfig.lunchStart && currentHour < this.workConfig.lunchEnd) { |
|
274 |
+ currentHour++; |
|
275 |
+ } else { |
|
276 |
+ currentHour++; |
|
277 |
+ remainingHours--; |
|
278 |
+ } |
|
279 |
+ } else { |
|
280 |
+ // 뒤로 계산 (시작시간 구하기) |
|
281 |
+ currentHour--; |
|
282 |
+ if (!(currentHour >= this.workConfig.lunchStart && currentHour < this.workConfig.lunchEnd)) { |
|
283 |
+ remainingHours--; |
|
284 |
+ } |
|
285 |
+ } |
|
286 |
+ } |
|
287 |
+ |
|
288 |
+ return currentHour; |
|
289 |
+ }, |
|
290 |
+ |
|
291 |
+ // 시작일과 종료일 통일 |
|
292 |
+ changeBgnde() { |
|
293 |
+ if (!this.editData.bgnde) { |
|
294 |
+ return; |
|
295 |
+ } |
|
296 |
+ |
|
297 |
+ // 반차인 경우 종료일을 시작일과 동일하게 설정 |
|
298 |
+ if (this.dayCnt === 0.5) { |
|
299 |
+ this.editData.endde = this.editData.bgnde; |
|
300 |
+ } |
|
301 |
+ |
|
302 |
+ this.validateAndCalculateDays(); // 사용 휴가일 계산 |
|
303 |
+ }, |
|
304 |
+ |
|
305 |
+ // 사용 휴가일 계산 |
|
306 |
+ validateAndCalculateDays() { |
|
307 |
+ if (!this.editData.bgnde || !this.editData.endde) { |
|
308 |
+ this.totalDays = 0; |
|
309 |
+ return; |
|
310 |
+ } |
|
311 |
+ |
|
312 |
+ const startDate = new Date(this.editData.bgnde); |
|
313 |
+ const endDate = new Date(this.editData.endde); |
|
314 |
+ |
|
315 |
+ // 날짜 유효성 검사 |
|
316 |
+ if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) { |
|
317 |
+ console.warn('유효하지 않은 날짜입니다.'); |
|
318 |
+ this.totalDays = 0; |
|
319 |
+ return; |
|
320 |
+ } |
|
321 |
+ |
|
322 |
+ // 종료일이 시작일보다 이전인지 확인 (반차가 아닌 경우) |
|
323 |
+ if (this.dayCnt !== 0.5 && endDate < startDate) { |
|
324 |
+ alert('종료일은 시작일보다 이전일 수 없습니다.'); |
|
325 |
+ this.editData.endde = this.editData.bgnde; |
|
326 |
+ return; |
|
327 |
+ } |
|
328 |
+ |
|
329 |
+ this.calculateTotalDays(); |
|
330 |
+ }, |
|
331 |
+ |
|
332 |
+ calculateTotalDays() { |
|
333 |
+ if (!this.editData.bgnde || !this.editData.endde) { |
|
334 |
+ this.totalDays = 0; |
|
335 |
+ return; |
|
336 |
+ } |
|
337 |
+ |
|
338 |
+ const startDate = new Date(this.editData.bgnde); |
|
339 |
+ const endDate = new Date(this.editData.endde); |
|
340 |
+ |
|
341 |
+ if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) { |
|
342 |
+ this.totalDays = 0; |
|
343 |
+ return; |
|
344 |
+ } |
|
345 |
+ |
|
346 |
+ const timeDiff = endDate.getTime() - startDate.getTime(); |
|
347 |
+ const dayDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24)) + 1; |
|
348 |
+ |
|
349 |
+ // 반차의 경우 0.5일, 그 외의 경우 실제 일수 계산 |
|
350 |
+ if (this.dayCnt === 0.5) { |
|
351 |
+ this.totalDays = 0.5; |
|
352 |
+ } else { |
|
353 |
+ this.totalDays = Math.max(0, dayDiff); |
|
354 |
+ } |
|
355 |
+ }, |
|
356 |
+ |
|
357 |
+ preventKeyboard(event) { |
|
358 |
+ if (event.key !== 'Tab') { |
|
359 |
+ event.preventDefault(); |
|
360 |
+ } |
|
361 |
+ }, |
|
362 |
+ |
|
363 |
+ fnAddSanctn(data) { |
|
364 |
+ this.editData.sanctnList.push(data); |
|
365 |
+ this.isOpenModal = false; |
|
366 |
+ }, |
|
367 |
+ |
|
368 |
+ fnDelSanctn(idx) { |
|
369 |
+ this.editData.sanctnList.splice(idx, 1); |
|
370 |
+ this.editData.sanctnList.forEach((item, index) => { |
|
371 |
+ item.sanctnOrdr = index + 1; |
|
372 |
+ }); |
|
373 |
+ }, |
|
374 |
+ |
|
375 |
+ async fnRecord() { |
|
376 |
+ try { |
|
377 |
+ const response = await findLastVcatnProc(); |
|
378 |
+ const result = response.data.data; |
|
379 |
+ |
|
380 |
+ if (this.$isEmpty(result.lists)) { |
|
381 |
+ alert("휴가 기록이 존재하지 않아, 이전 승인자를 불러올 수 없습니다."); |
|
382 |
+ return; |
|
383 |
+ } |
|
384 |
+ |
|
385 |
+ this.editData.sanctnList = result.lists; |
|
386 |
+ } catch (error) { |
|
387 |
+ console.error('이전 승인자 조회 실패:', error); |
|
388 |
+ const message = error.response?.data?.message || "이전 승인자를 불러오는데 실패했습니다."; |
|
389 |
+ alert(message); |
|
390 |
+ } |
|
391 |
+ }, |
|
392 |
+ |
|
393 |
+ validateForm() { |
|
394 |
+ if (this.$isEmpty(this.editData.vcatnKnd)) { |
|
395 |
+ alert("유형을 선택해 주세요."); |
|
396 |
+ return false; |
|
397 |
+ } |
|
398 |
+ |
|
399 |
+ if (this.$isEmpty(this.editData.bgnde)) { |
|
400 |
+ alert("시작일을 선택해 주세요."); |
|
401 |
+ return false; |
|
402 |
+ } |
|
403 |
+ |
|
404 |
+ if (this.$isEmpty(this.editData.endde)) { |
|
405 |
+ alert("종료일을 선택해 주세요."); |
|
406 |
+ return false; |
|
407 |
+ } |
|
408 |
+ |
|
409 |
+ if (this.$isEmpty(this.editData.sanctnList)) { |
|
410 |
+ alert("승인자를 선택해 주세요."); |
|
411 |
+ return false; |
|
412 |
+ } |
|
413 |
+ |
|
414 |
+ if (this.dayCnt === 0.5) { |
|
415 |
+ if (this.$isEmpty(this.editData.vcatnSubKnd)) { |
|
416 |
+ alert("세부 유형을 선택해 주세요."); |
|
417 |
+ return false; |
|
418 |
+ } |
|
419 |
+ } |
|
420 |
+ |
|
421 |
+ return true; |
|
422 |
+ }, |
|
423 |
+ |
|
424 |
+ async fnSave() { |
|
425 |
+ try { |
|
426 |
+ if (!this.validateForm()) { |
|
427 |
+ return; |
|
428 |
+ } |
|
429 |
+ |
|
430 |
+ if (!this.$isEmpty(this.pageId)) { |
|
431 |
+ this.editData.confm_at = 'W'; |
|
432 |
+ } |
|
433 |
+ |
|
434 |
+ const response = this.$isEmpty(this.pageId) ? await saveVcatnProc(this.editData) : await updateVcatnProc(this.editData); |
|
435 |
+ const message = this.$isEmpty(this.pageId) ? "등록되었습니다." : "수정되었습니다."; |
|
436 |
+ alert(message); |
|
437 |
+ |
|
438 |
+ this.fnMoveTo('view', response.data.data.pageId); |
|
439 |
+ } catch (error) { |
|
440 |
+ console.error('저장 실패:', error); |
|
441 |
+ const message = error.response?.data?.message || "저장에 실패했습니다."; |
|
442 |
+ alert(message); |
|
443 |
+ } |
|
444 |
+ }, |
|
445 |
+ |
|
446 |
+ fnMoveTo(type, id) { |
|
447 |
+ const routes = { |
|
448 |
+ 'list': { name: 'hyugaStatue' }, |
|
449 |
+ 'view': { name: 'HyugaDetail', query: { id } }, |
|
450 |
+ 'edit': { name: 'hyugaInsert', query: this.$isEmpty(id) ? {} : { id } }, |
|
451 |
+ }; |
|
452 |
+ |
|
453 |
+ if (routes[type]) { |
|
454 |
+ if (!this.$isEmpty(this.pageId) && type === 'list') { |
|
455 |
+ this.$router.push({ name: 'HyugaDetail', query: { id: this.pageId } }); |
|
456 |
+ return; |
|
457 |
+ } |
|
458 |
+ this.$router.push(routes[type]); |
|
459 |
+ } else { |
|
460 |
+ alert("올바르지 않은 경로를 요청하여 목록으로 이동합니다."); |
|
461 |
+ this.$router.push(routes['list']); |
|
462 |
+ } |
|
463 |
+ }, |
|
225 | 464 |
}, |
226 | 465 |
}; |
227 |
-</script> |
|
466 |
+</script>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/Manager/attendance/hyugaStatue.vue
+++ client/views/pages/Manager/attendance/hyugaStatue.vue
... | ... | @@ -1,221 +1,347 @@ |
1 | 1 |
<template> |
2 |
-<div class="col-lg-12"> |
|
3 |
- <div class="card"> |
|
4 |
- <div class="card-body"> |
|
5 |
- <h2 class="card-title">휴가 현황</h2> |
|
6 |
- <!-- 폼그룹 --> |
|
7 |
-<div class="form-group"> |
|
8 |
- <div class="form-conts"> |
|
9 |
- <div class="form-conts datepicker-conts"> |
|
10 |
- <div class="datepicker-input"> |
|
11 |
- <input |
|
12 |
- type="date" |
|
13 |
- class="form-control datepicker cal" |
|
14 |
- :value="startDate" |
|
15 |
- style="max-width: 200px;" |
|
16 |
- /> |
|
17 |
- <mark>~</mark> |
|
18 |
- <input |
|
19 |
- type="date" |
|
20 |
- class="form-control datepicker cal" |
|
21 |
- :value="endDate" |
|
22 |
- style="max-width: 200px;" |
|
23 |
- /> |
|
2 |
+ <div class="col-lg-12"> |
|
3 |
+ <div class="card"> |
|
4 |
+ <div class="card-body"> |
|
5 |
+ <h2 class="card-title">휴가 현황</h2> |
|
6 |
+ <div class="form-group"> |
|
7 |
+ <div class="form-conts"> |
|
8 |
+ <div class="form-conts datepicker-conts"> |
|
9 |
+ <div class="datepicker-input"> |
|
10 |
+ <input type="date" class="form-control datepicker cal" v-model="request.bgnde" style="max-width: 200px;" @change="changeDate" /> |
|
11 |
+ <mark>~</mark> |
|
12 |
+ <input type="date" class="form-control datepicker cal" v-model="request.endde" style="max-width: 200px;" @change="changeDate" /> |
|
13 |
+ </div> |
|
24 | 14 |
</div> |
15 |
+ </div> |
|
25 | 16 |
</div> |
26 |
- </div> |
|
27 |
-</div> |
|
28 |
-<!-- //폼그룹 --> |
|
29 |
- <div class="boxs"> |
|
30 |
- <div class="color-boxs"> |
|
31 |
- <div class="box "> |
|
32 |
- <h3>지각</h3> |
|
33 |
- 3 |
|
34 |
- </div> |
|
35 |
- <div class="box blue"> |
|
36 |
- <h3>조기퇴근</h3> |
|
37 |
- 3 |
|
38 |
- </div> |
|
39 |
- <div class="box red"> |
|
40 |
- <h3>결근</h3> |
|
41 |
- 3 |
|
42 |
- </div> |
|
43 |
- <div class="box green"> |
|
44 |
- <h3>결근</h3> |
|
45 |
- 3 |
|
46 |
- </div> |
|
47 |
- <div class="box purple"> |
|
48 |
- <h3>결근</h3> |
|
49 |
- 3 |
|
50 |
- </div> |
|
51 |
- <div class="box orange"> |
|
52 |
- <h3>결근</h3> |
|
53 |
- 3 |
|
54 |
- </div> |
|
17 |
+ <div class="boxs"> |
|
18 |
+ <div class="color-boxs"> |
|
19 |
+ <div v-for="(item, idx) of useSummary" :key="idx" :class="getBoxClass(idx)" @click="fnFindUseList(item)"> |
|
20 |
+ <h3>{{ item.name }}</h3> {{ item.value }} |
|
55 | 21 |
</div> |
22 |
+ <div v-for="(item, idx) of notUseSummary" :key="idx" :class="getBoxClass(useSummary.length + idx)" @click="fnFindNotUseList(item.code)"> |
|
23 |
+ <h3>{{ item.codeNm }}</h3> {{ item.value }} |
|
24 |
+ </div> |
|
25 |
+ </div> |
|
56 | 26 |
</div> |
57 |
- <!-- Table --> |
|
58 |
- <div class="tbl-wrap"> |
|
27 |
+ <div class="tbl-wrap"> |
|
59 | 28 |
<table id="myTable" class="tbl data"> |
60 |
- <!-- 동적으로 <th> 생성 --> |
|
29 |
+ <colgroup> |
|
30 |
+ <col style="width: 15%;"> |
|
31 |
+ <col style="width: 40%;"> |
|
32 |
+ <col style="width: 30%;"> |
|
33 |
+ <col style="width: 15%;"> |
|
34 |
+ </colgroup> |
|
61 | 35 |
<thead> |
62 | 36 |
<tr> |
63 |
- <th>구분 </th> |
|
37 |
+ <th>구분</th> |
|
64 | 38 |
<th>기간</th> |
65 |
- <th>승인자</th> |
|
66 | 39 |
<th>신청일</th> |
67 | 40 |
<th>상태</th> |
68 | 41 |
</tr> |
69 | 42 |
</thead> |
70 |
- <!-- 동적으로 <td> 생성 --> |
|
71 | 43 |
<tbody> |
72 |
- <tr v-for="(item, index) in listData" :key="index" @click="goToDetailPage(item)"> |
|
73 |
- <td>{{ item.type }}</td> |
|
74 |
- <td>{{ item.period }}</td> |
|
75 |
- <td>{{ item.approval }}</td> |
|
76 |
- <td>{{ item.requestDate }}</td> |
|
77 |
- <td :class="getStatusClass(item.status)">{{ item.status }}</td> |
|
44 |
+ <template v-if="formattedListData.length > 0"> |
|
45 |
+ <tr v-for="(item, idx) in formattedListData" :key="idx" @click="fnMoveTo('view', item.vcatnId)"> |
|
46 |
+ <td :class="getTypeColorClass(item.formattedVcatnKnd)">{{ item.formattedVcatnKnd }}</td> |
|
47 |
+ <td>{{ item.formattedBgnde }} {{ item.formattedBeginHour }}:{{ item.formattedBeginMnt }} ~ {{ item.formattedEndde }} {{ item.formattedEndHour }}:{{ item.formattedEndMnt }}</td> |
|
48 |
+ <td>{{ item.rgsde }}</td> |
|
49 |
+ <td :class="getStatusClass(item.formattedStatus)">{{ item.formattedStatus }}</td> |
|
50 |
+ </tr> |
|
51 |
+ </template> |
|
52 |
+ <tr v-else> |
|
53 |
+ <td colspan="4">해당 기간 내 등록된 휴가가 없습니다.</td> |
|
78 | 54 |
</tr> |
79 | 55 |
</tbody> |
80 | 56 |
</table> |
81 |
- |
|
82 | 57 |
</div> |
83 |
- <div class="pagination"> |
|
84 |
- <ul> |
|
85 |
- <!-- 왼쪽 화살표 (이전 페이지) --> |
|
86 |
- <li |
|
87 |
- class="arrow" |
|
88 |
- :class="{ disabled: currentPage === 1 }" |
|
89 |
- @click="changePage(currentPage - 1)" |
|
90 |
- > |
|
91 |
- < |
|
92 |
- </li> |
|
93 |
- |
|
94 |
- <!-- 페이지 번호 --> |
|
95 |
- <li |
|
96 |
- v-for="page in totalPages" |
|
97 |
- :key="page" |
|
98 |
- :class="{ active: currentPage === page }" |
|
99 |
- @click="changePage(page)" |
|
100 |
- > |
|
101 |
- {{ page }} |
|
102 |
- </li> |
|
103 |
- |
|
104 |
- <!-- 오른쪽 화살표 (다음 페이지) --> |
|
105 |
- <li |
|
106 |
- class="arrow" |
|
107 |
- :class="{ disabled: currentPage === totalPages }" |
|
108 |
- @click="changePage(currentPage + 1)" |
|
109 |
- > |
|
110 |
- > |
|
111 |
- </li> |
|
112 |
- </ul> |
|
113 |
- </div> |
|
114 |
- |
|
58 |
+ <Pagenation :search="request" @onChange="fnChangeCurrentPage" /> |
|
59 |
+ </div> |
|
115 | 60 |
</div> |
116 | 61 |
</div> |
117 |
-</div> |
|
118 | 62 |
</template> |
119 |
- |
|
120 | 63 |
<script> |
121 |
-import { ref } from 'vue'; |
|
122 | 64 |
import { SearchOutlined } from '@ant-design/icons-vue'; |
65 |
+import Pagenation from '../../../component/Pagenation.vue'; |
|
66 |
+// API |
|
67 |
+import { findVcatnsSummary, findMyVcatnsProc } from '../../../../resources/api/vcatn'; |
|
68 |
+ |
|
123 | 69 |
export default { |
70 |
+ components: { |
|
71 |
+ SearchOutlined, |
|
72 |
+ Pagenation |
|
73 |
+ }, |
|
74 |
+ |
|
124 | 75 |
data() { |
125 |
- const today = new Date(); |
|
126 |
- const formattedToday = today.toISOString().split('T')[0]; // 'YYYY-MM-DD' |
|
127 | 76 |
return { |
128 |
- startDate: '2025-01-01', |
|
129 |
- endDate: formattedToday, |
|
130 |
- showOptions: false, |
|
131 |
- currentPage: 1, |
|
132 |
- totalPages: 3, |
|
133 | 77 |
photoicon: "/client/resources/img/photo_icon.png", |
134 |
- // 데이터 초기화 |
|
135 |
- years: [2023, 2024, 2025], // 연도 목록 |
|
136 |
- months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], // 월 목록 |
|
137 |
- selectedYear: '', |
|
138 |
- selectedMonth: '', |
|
139 |
- listData: [ |
|
140 |
- { |
|
141 |
- type: '연차', |
|
142 |
- period: '2025-05-10 ~ 2025-15-03', |
|
143 |
- approval: '홍길동', |
|
144 |
- requestDate: '2025-04-25', |
|
145 |
- status: '대기' |
|
146 |
- }, { |
|
147 |
- type: '반차', |
|
148 |
- period: '2025-05-01 ~ 2025-05-03', |
|
149 |
- approval: '홍길동', |
|
150 |
- requestDate: '2025-04-25', |
|
151 |
- status: '승인' |
|
152 |
- }], |
|
153 |
- filteredData: [], |
|
78 |
+ |
|
79 |
+ color: ['blue', 'red', 'green', 'purple', 'orange'], |
|
80 |
+ colorMap: [], |
|
81 |
+ |
|
82 |
+ useSummary: [], // 연차 소모성 휴가 |
|
83 |
+ notUseSummary: [], // 연차 비 소모성 휴가 |
|
84 |
+ |
|
85 |
+ // 휴가 현황 목록 조회용 |
|
86 |
+ listData: [], |
|
87 |
+ request: { |
|
88 |
+ vcatnKnds: null, // 휴가 종류 |
|
89 |
+ bgnde: null, // 시작일 |
|
90 |
+ endde: null, // 종료일 |
|
91 |
+ }, |
|
92 |
+ |
|
93 |
+ // 공통코드(구분, 상태) 목록 조회용 |
|
94 |
+ vcatnKnds: [], |
|
95 |
+ confmTypes: [], |
|
96 |
+ serachRequest: { |
|
97 |
+ searchType: "upperCd", |
|
98 |
+ searchText: null, |
|
99 |
+ }, |
|
154 | 100 |
}; |
155 | 101 |
}, |
156 |
- components:{ |
|
157 |
- SearchOutlined |
|
158 |
- }, |
|
102 |
+ |
|
159 | 103 |
computed: { |
104 |
+ formattedListData() { |
|
105 |
+ if (!this.listData || !Array.isArray(this.listData)) { |
|
106 |
+ return []; |
|
107 |
+ } |
|
108 |
+ |
|
109 |
+ return this.listData.map(item => { |
|
110 |
+ const vcatnKnd = this.vcatnKnds.find(v => v.code === item.vcatnKnd); |
|
111 |
+ const confmAt = this.confmTypes.find(v => v.codeValue === item.confmAt); |
|
112 |
+ return { |
|
113 |
+ ...item, |
|
114 |
+ formattedVcatnKnd: vcatnKnd ? vcatnKnd.codeNm : item.vcatnKnd, |
|
115 |
+ formattedBgnde: item.bgnde ? item.bgnde.split(' ')[0] : '', |
|
116 |
+ formattedEndde: item.endde ? item.endde.split(' ')[0] : '', |
|
117 |
+ formattedBeginHour: item.beginHour ? item.beginHour.toString().padStart(2, '0') : '00', |
|
118 |
+ formattedEndHour: item.endHour ? item.endHour.toString().padStart(2, '0') : '00', |
|
119 |
+ formattedBeginMnt: item.beginMnt ? item.beginMnt.toString().padStart(2, '0') : '00', |
|
120 |
+ formattedEndMnt: item.endMnt ? item.endMnt.toString().padStart(2, '0') : '00', |
|
121 |
+ formattedStatus: confmAt ? confmAt.codeNm : item.confmAt, |
|
122 |
+ }; |
|
123 |
+ }); |
|
124 |
+ } |
|
160 | 125 |
}, |
126 |
+ |
|
127 |
+ created() { |
|
128 |
+ this.vcatnCodes(); // 휴가 종류 코드 조회 |
|
129 |
+ this.confmTypeCodes(); // 상태 코드 조회 |
|
130 |
+ }, |
|
131 |
+ |
|
132 |
+ mounted() { |
|
133 |
+ this.findSummary(); // 현황 조회 |
|
134 |
+ this.findList(); // 목록 조회 |
|
135 |
+ }, |
|
136 |
+ |
|
161 | 137 |
methods: { |
138 |
+ // 휴가 종류 코드 조회 |
|
139 |
+ async confmTypeCodes() { |
|
140 |
+ this.vcatnKnds = []; // 초기화 |
|
141 |
+ this.serachRequest.searchText = "sanctn_mby_vcatn"; |
|
162 | 142 |
|
163 |
- goToAttendancePage(item) { |
|
164 |
- this.$router.push({ name: 'AttendanceDetail', query: { id: item.id } }); |
|
165 |
- }, |
|
166 |
- changePage(page) { |
|
167 |
- if (page < 1 || page > this.totalPages) return; |
|
168 |
- this.currentPage = page; |
|
169 |
- this.$emit('page-changed', page); // 필요 시 부모에 알림 |
|
170 |
- }, |
|
171 |
- async onClickSubmit() { |
|
172 |
- // `useMutation` 훅을 사용하여 mutation 함수 가져오기 |
|
173 |
- const { mutate, onDone, onError } = useMutation(mygql); |
|
143 |
+ const codes = await this.$findCodeList(this.serachRequest); |
|
144 |
+ if (codes && Array.isArray(codes)) { |
|
145 |
+ for (const code of codes) { |
|
146 |
+ this.serachRequest.searchText = code.code; |
|
174 | 147 |
|
175 |
- try { |
|
176 |
- const result = await mutate(); |
|
177 |
- console.log(result); |
|
178 |
- } catch (error) { |
|
179 |
- console.error('Mutation error:', error); |
|
148 |
+ const result = await this.$findCodeList(this.serachRequest); |
|
149 |
+ if (result && Array.isArray(result)) { |
|
150 |
+ this.vcatnKnds.push(...result); |
|
151 |
+ } |
|
152 |
+ } |
|
180 | 153 |
} |
181 | 154 |
}, |
182 |
- goToDetailPage(item) { |
|
183 |
- this.$router.push({ |
|
184 |
- name: 'HyugaDetail', |
|
185 |
- query: { id: item.id } |
|
186 |
- }); |
|
187 |
-}, |
|
188 | 155 |
|
189 |
- // 상태에 따른 클래스 반환 메소드 |
|
190 |
- getStatusClass(status) { |
|
191 |
- return status === 'active' ? 'status-active' : 'status-inactive'; |
|
192 |
- }, |
|
156 |
+ // 상태 코드 조회 |
|
157 |
+ async vcatnCodes() { |
|
158 |
+ this.confmTypes = []; // 초기화 |
|
159 |
+ this.serachRequest.searchText = "confm_code"; |
|
160 |
+ |
|
161 |
+ const codes = await this.$findCodeList(this.serachRequest); |
|
162 |
+ if (codes && Array.isArray(codes)) { |
|
163 |
+ this.confmTypes = codes; |
|
164 |
+ } |
|
165 |
+ }, |
|
166 |
+ |
|
167 |
+ // 현황 조회 |
|
168 |
+ async findSummary() { |
|
169 |
+ const vm = this; |
|
170 |
+ try { |
|
171 |
+ const response = await findVcatnsSummary(vm.request); |
|
172 |
+ const result = response.data.data; |
|
173 |
+ |
|
174 |
+ this.request.bgnde = new Date(result.data.bgnde).toISOString().split('T')[0]; |
|
175 |
+ this.request.endde = new Date(result.data.endde).toISOString().split('T')[0]; |
|
176 |
+ if (result.data.yryc < 1) { |
|
177 |
+ this.request.endde = new Date().toISOString().split('T')[0]; |
|
178 |
+ } |
|
179 |
+ |
|
180 |
+ let yrycCyfdCo = result.data.yrycCyfdCo; |
|
181 |
+ let totalCo = result.data.yrycCo + yrycCyfdCo; |
|
182 |
+ let useCo = result.useSummary.useCo; |
|
183 |
+ let notUseCo = totalCo - useCo; |
|
184 |
+ |
|
185 |
+ this.useSummary = []; // 초기화 |
|
186 |
+ this.useSummary.push({ key: 'totalCo', name: '전체', value: totalCo + '(' + yrycCyfdCo + ')' }); |
|
187 |
+ this.useSummary.push({ key: 'useCo', name: '사용', value: useCo, codeList: result.useSummary.codeList }); |
|
188 |
+ this.useSummary.push({ key: 'notUseCo', name: '미사용', value: notUseCo }); |
|
189 |
+ |
|
190 |
+ this.notUseSummary = []; // 초기화 |
|
191 |
+ this.notUseSummary = result.notUseSummary; |
|
192 |
+ |
|
193 |
+ this.colorMap = []; // 초기화 |
|
194 |
+ const keys = Object.keys(this.notUseSummary); |
|
195 |
+ for (let i = 0; i < Object.keys(this.notUseSummary).length; i++) { |
|
196 |
+ this.colorMap.push({ |
|
197 |
+ code: keys[i].code, |
|
198 |
+ class: this.color[this.useSummary.length + i], |
|
199 |
+ }) |
|
200 |
+ } |
|
201 |
+ } catch (error) { |
|
202 |
+ if (error.response) { |
|
203 |
+ alert(error.response.data.message); |
|
204 |
+ } else { |
|
205 |
+ alert("에러가 발생했습니다."); |
|
206 |
+ } |
|
207 |
+ console.error(error.message); |
|
208 |
+ }; |
|
209 |
+ }, |
|
210 |
+ |
|
211 |
+ // 현황에 클래스 부여 |
|
212 |
+ getBoxClass(idx) { |
|
213 |
+ if (idx === 0) return 'box'; |
|
214 |
+ return `box ${this.color[(idx - 1) % this.color.length]}`; |
|
215 |
+ }, |
|
216 |
+ |
|
217 |
+ // 날짜 선택 |
|
218 |
+ changeDate() { |
|
219 |
+ if (!this.request.bgnde || !this.request.endde) { |
|
220 |
+ return; |
|
221 |
+ } |
|
222 |
+ |
|
223 |
+ const startDate = new Date(this.request.bgnde); |
|
224 |
+ const endDate = new Date(this.request.endde); |
|
225 |
+ if (endDate < startDate) { |
|
226 |
+ alert('종료일은 시작일보다 이전일 수 없습니다.'); |
|
227 |
+ this.request.endde = this.request.bgnde; |
|
228 |
+ return; |
|
229 |
+ } |
|
230 |
+ |
|
231 |
+ this.findList(); // 목록 조회 |
|
232 |
+ }, |
|
233 |
+ |
|
234 |
+ // 목록 조회 |
|
235 |
+ async findList() { |
|
236 |
+ const vm = this; |
|
237 |
+ try { |
|
238 |
+ delete vm.request.vcatnKndList; |
|
239 |
+ |
|
240 |
+ const response = await findMyVcatnsProc(vm.request); |
|
241 |
+ const result = response.data.data; |
|
242 |
+ |
|
243 |
+ vm.listData = result.lists; |
|
244 |
+ vm.request = result.search; |
|
245 |
+ } catch (error) { |
|
246 |
+ if (error.response) { |
|
247 |
+ alert(error.response.data.message); |
|
248 |
+ } else { |
|
249 |
+ alert("에러가 발생했습니다."); |
|
250 |
+ } |
|
251 |
+ console.error(error.message); |
|
252 |
+ }; |
|
253 |
+ }, |
|
254 |
+ |
|
255 |
+ // 목록 필터 조회 |
|
256 |
+ fnFindUseList(item) { |
|
257 |
+ if (item.key === 'totalCo') { |
|
258 |
+ this.request.vcatnKnds = null; |
|
259 |
+ } else if (item.key === 'useCo') { |
|
260 |
+ this.request.vcatnKnds = item.codeList.map(code => code.code).join(", "); |
|
261 |
+ } else { |
|
262 |
+ return; |
|
263 |
+ } |
|
264 |
+ |
|
265 |
+ this.findList(); // 목록 조회 |
|
266 |
+ }, |
|
267 |
+ fnFindNotUseList(vcatnKnd) { |
|
268 |
+ this.request.vcatnKnds = vcatnKnd; |
|
269 |
+ |
|
270 |
+ this.findList(); // 목록 조회 |
|
271 |
+ }, |
|
272 |
+ |
|
273 |
+ // 구분에 클래스 부여 |
|
274 |
+ getTypeColorClass(code) { |
|
275 |
+ for (let color of this.colorMap) { |
|
276 |
+ if (color.code === code) { |
|
277 |
+ return 'vcatnKnd ' + color.class; |
|
278 |
+ } |
|
279 |
+ } |
|
280 |
+ return 'vcatnKnd blue'; |
|
281 |
+ }, |
|
282 |
+ |
|
283 |
+ // 상태에 따른 클래스 반환 메소드 |
|
193 | 284 |
getStatusClass(status) { |
194 | 285 |
if (status === '승인') return 'status-approved'; |
195 | 286 |
if (status === '대기') return 'status-pending'; |
196 | 287 |
return ''; |
197 | 288 |
}, |
198 |
- isPastPeriod(period) { |
|
199 |
- // 예: '2025-05-01 ~ 2025-05-03' → 종료일 추출 |
|
200 |
- const endDateStr = period.split('~')[1]?.trim(); |
|
201 |
- if (!endDateStr) return false; |
|
202 | 289 |
|
203 |
- const endDate = new Date(endDateStr); |
|
204 |
- const today = new Date(); |
|
290 |
+ // 페이지 이동 |
|
291 |
+ fnChangeCurrentPage(currentPage) { |
|
292 |
+ this.request.currentPage = Number(currentPage); |
|
293 |
+ this.$nextTick(() => { |
|
294 |
+ this.findList(); |
|
295 |
+ }); |
|
296 |
+ }, |
|
205 | 297 |
|
206 |
- // 현재 날짜보다 과거면 true |
|
207 |
- return endDate < today; |
|
208 |
- } |
|
209 |
- }, |
|
210 |
- created() { |
|
211 |
- }, |
|
212 |
- mounted() { |
|
298 |
+ // 페이지 이동 |
|
299 |
+ fnMoveTo(type, id) { |
|
300 |
+ const routes = { |
|
301 |
+ 'list': { name: 'hyugaStatue' }, |
|
302 |
+ 'view': { name: 'HyugaDetail', query: { id } }, |
|
303 |
+ 'edit': { name: 'hyugaInsert', query: this.$isEmpty(id) ? {} : { id } }, |
|
304 |
+ }; |
|
213 | 305 |
|
214 |
- |
|
306 |
+ if (routes[type]) { |
|
307 |
+ if (!this.$isEmpty(this.pageId) && type === 'list') { |
|
308 |
+ this.$router.push({ name: 'HyugaDetail', query: { id: this.pageId } }); |
|
309 |
+ } |
|
310 |
+ this.$router.push(routes[type]); |
|
311 |
+ } else { |
|
312 |
+ alert("올바르지 않은 경로를 요청하여 목록으로 이동합니다."); |
|
313 |
+ this.$router.push(routes['list']); |
|
314 |
+ } |
|
315 |
+ }, |
|
215 | 316 |
}, |
216 | 317 |
}; |
217 | 318 |
</script> |
218 |
- |
|
219 | 319 |
<style scoped> |
220 |
-tr{cursor: pointer;} |
|
221 |
-</style> |
|
320 |
+tr { |
|
321 |
+ cursor: pointer; |
|
322 |
+} |
|
323 |
+ |
|
324 |
+.box { |
|
325 |
+ cursor: pointer; |
|
326 |
+} |
|
327 |
+ |
|
328 |
+.vcatnKnd.red { |
|
329 |
+ color: #E92727 !important; |
|
330 |
+} |
|
331 |
+ |
|
332 |
+.vcatnKnd.green { |
|
333 |
+ color: #3C97AB !important; |
|
334 |
+} |
|
335 |
+ |
|
336 |
+.vcatnKnd.blue { |
|
337 |
+ color: #1D75E1 !important; |
|
338 |
+} |
|
339 |
+ |
|
340 |
+.vcatnKnd.purple { |
|
341 |
+ color: #A36CD4 !important; |
|
342 |
+} |
|
343 |
+ |
|
344 |
+.vcatnKnd.orange { |
|
345 |
+ color: #F7941C !important; |
|
346 |
+} |
|
347 |
+</style>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/Manager/hr/hr.vue
+++ client/views/pages/Manager/hr/hr.vue
... | ... | @@ -32,8 +32,8 @@ |
32 | 32 |
</div> |
33 | 33 |
</router-link> |
34 | 34 |
</li> |
35 |
- |
|
36 |
- |
|
35 |
+ |
|
36 |
+ |
|
37 | 37 |
</ul> |
38 | 38 |
</details> |
39 | 39 |
<details class="menu-box"> |
... | ... | @@ -45,8 +45,8 @@ |
45 | 45 |
<img :src="menuicon" alt=""> |
46 | 46 |
</div> |
47 | 47 |
</router-link></li> |
48 |
- |
|
49 |
- |
|
48 |
+ |
|
49 |
+ |
|
50 | 50 |
</ul> |
51 | 51 |
</details> |
52 | 52 |
</div> |
--- package-lock.json
+++ package-lock.json
... | ... | @@ -9,11 +9,13 @@ |
9 | 9 |
"@ant-design/icons-vue": "^7.0.1", |
10 | 10 |
"@babel/cli": "7.19.3", |
11 | 11 |
"@babel/core": "7.19.3", |
12 |
+ "@ckeditor/ckeditor5-vue": "^7.3.0", |
|
12 | 13 |
"@fullcalendar/core": "^6.1.15", |
13 | 14 |
"@fullcalendar/daygrid": "^6.1.15", |
14 | 15 |
"@fullcalendar/vue3": "^6.1.15", |
15 | 16 |
"axios": "^1.10.0", |
16 | 17 |
"babel-loader": "8.2.5", |
18 |
+ "ckeditor5": "^45.2.1", |
|
17 | 19 |
"css-loader": "6.7.1", |
18 | 20 |
"express": "4.18.1", |
19 | 21 |
"express-http-proxy": "^2.1.1", |
... | ... | @@ -380,6 +382,828 @@ |
380 | 382 |
"node": ">=6.9.0" |
381 | 383 |
} |
382 | 384 |
}, |
385 |
+ "node_modules/@ckeditor/ckeditor5-adapter-ckfinder": { |
|
386 |
+ "version": "45.2.1", |
|
387 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-45.2.1.tgz", |
|
388 |
+ "integrity": "sha512-lvXu5hc1wP0U2tTGm9wi8QoWrxnoPfR04A5br8u5cYzIbmyYDFcHgBWhWXjrDrjxVGDMSLgmrMtsw5gLhzE2yw==", |
|
389 |
+ "dependencies": { |
|
390 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
391 |
+ "@ckeditor/ckeditor5-upload": "45.2.1", |
|
392 |
+ "ckeditor5": "45.2.1" |
|
393 |
+ } |
|
394 |
+ }, |
|
395 |
+ "node_modules/@ckeditor/ckeditor5-alignment": { |
|
396 |
+ "version": "45.2.1", |
|
397 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-45.2.1.tgz", |
|
398 |
+ "integrity": "sha512-aYCxhuvur2vtgzhl8yw4OWqhjsNvqUBW5Lyk4SVcs+fVyaOxIYhjNw+9oVkAjryPT/wLVhXBHnQEBoG6hUuE8g==", |
|
399 |
+ "dependencies": { |
|
400 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
401 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
402 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
403 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
404 |
+ "ckeditor5": "45.2.1" |
|
405 |
+ } |
|
406 |
+ }, |
|
407 |
+ "node_modules/@ckeditor/ckeditor5-autoformat": { |
|
408 |
+ "version": "45.2.1", |
|
409 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-45.2.1.tgz", |
|
410 |
+ "integrity": "sha512-0QsRJ+Oh3+3oAwG+KeuyPBnFArF4mzFk8RX277iqQInbIit63lds0pgejJGvXMrDcpUxo6RzmXKZPJEeps818Q==", |
|
411 |
+ "dependencies": { |
|
412 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
413 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
414 |
+ "@ckeditor/ckeditor5-heading": "45.2.1", |
|
415 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
416 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
417 |
+ "ckeditor5": "45.2.1" |
|
418 |
+ } |
|
419 |
+ }, |
|
420 |
+ "node_modules/@ckeditor/ckeditor5-autosave": { |
|
421 |
+ "version": "45.2.1", |
|
422 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autosave/-/ckeditor5-autosave-45.2.1.tgz", |
|
423 |
+ "integrity": "sha512-XnK5Ktec5nQ12ianvf++zrxNpS9sjA2C/e9TTBcY3h99oMcdO7cbm0Yv9zzQNODQifdrHq/KXwAoWSYYNTjtiw==", |
|
424 |
+ "dependencies": { |
|
425 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
426 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
427 |
+ "ckeditor5": "45.2.1", |
|
428 |
+ "es-toolkit": "1.32.0" |
|
429 |
+ } |
|
430 |
+ }, |
|
431 |
+ "node_modules/@ckeditor/ckeditor5-basic-styles": { |
|
432 |
+ "version": "45.2.1", |
|
433 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-45.2.1.tgz", |
|
434 |
+ "integrity": "sha512-PXnnddU8boF2PFziaodXrPYtLgEmWSjH9YaZMSFrcsf11RmqLJ3YjaJHfL94TFFQuK+Ey3pAIiT7d7EOjARBVw==", |
|
435 |
+ "dependencies": { |
|
436 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
437 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
438 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
439 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
440 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
441 |
+ "ckeditor5": "45.2.1" |
|
442 |
+ } |
|
443 |
+ }, |
|
444 |
+ "node_modules/@ckeditor/ckeditor5-block-quote": { |
|
445 |
+ "version": "45.2.1", |
|
446 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-45.2.1.tgz", |
|
447 |
+ "integrity": "sha512-H7x7EYwfK6M2v4n6VIp1PJ5YyZBnR6/vyqEiH7CQB5cN6IvgjxArXimD6BnIVYXgiwVGk89P4Lv0UZOe4zICYQ==", |
|
448 |
+ "dependencies": { |
|
449 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
450 |
+ "@ckeditor/ckeditor5-enter": "45.2.1", |
|
451 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
452 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
453 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
454 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
455 |
+ "ckeditor5": "45.2.1" |
|
456 |
+ } |
|
457 |
+ }, |
|
458 |
+ "node_modules/@ckeditor/ckeditor5-bookmark": { |
|
459 |
+ "version": "45.2.1", |
|
460 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-bookmark/-/ckeditor5-bookmark-45.2.1.tgz", |
|
461 |
+ "integrity": "sha512-qJxadIb5d0dJWSA3pLC9Udo22tViqgg60LqvkjA7HPoP/NNx0YPaS5fmnb7nW03KaZo/58C8nc9DdvuO7LlWWw==", |
|
462 |
+ "dependencies": { |
|
463 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
464 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
465 |
+ "@ckeditor/ckeditor5-link": "45.2.1", |
|
466 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
467 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
468 |
+ "@ckeditor/ckeditor5-widget": "45.2.1", |
|
469 |
+ "ckeditor5": "45.2.1" |
|
470 |
+ } |
|
471 |
+ }, |
|
472 |
+ "node_modules/@ckeditor/ckeditor5-ckbox": { |
|
473 |
+ "version": "45.2.1", |
|
474 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckbox/-/ckeditor5-ckbox-45.2.1.tgz", |
|
475 |
+ "integrity": "sha512-v+2I5scbc6y4lnz9cbH/6FQRxpqJ1vymlSACFe6R9mH8aqIROHArIhofG6Bwd9LK6ksAMITO+He20fFWe0HJRA==", |
|
476 |
+ "dependencies": { |
|
477 |
+ "@ckeditor/ckeditor5-cloud-services": "45.2.1", |
|
478 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
479 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
480 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
481 |
+ "@ckeditor/ckeditor5-image": "45.2.1", |
|
482 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
483 |
+ "@ckeditor/ckeditor5-upload": "45.2.1", |
|
484 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
485 |
+ "blurhash": "2.0.5", |
|
486 |
+ "ckeditor5": "45.2.1", |
|
487 |
+ "es-toolkit": "1.32.0" |
|
488 |
+ } |
|
489 |
+ }, |
|
490 |
+ "node_modules/@ckeditor/ckeditor5-ckfinder": { |
|
491 |
+ "version": "45.2.1", |
|
492 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckfinder/-/ckeditor5-ckfinder-45.2.1.tgz", |
|
493 |
+ "integrity": "sha512-LEgK9IM+ZX+WcE60kqyr1aMQQfH6HgUUIomly2b7InmIfwUBzIc37ef21WlFd/w+YSjwBjwRLG0W+oYVmx3SZg==", |
|
494 |
+ "dependencies": { |
|
495 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
496 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
497 |
+ "@ckeditor/ckeditor5-image": "45.2.1", |
|
498 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
499 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
500 |
+ "ckeditor5": "45.2.1" |
|
501 |
+ } |
|
502 |
+ }, |
|
503 |
+ "node_modules/@ckeditor/ckeditor5-clipboard": { |
|
504 |
+ "version": "45.2.1", |
|
505 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-45.2.1.tgz", |
|
506 |
+ "integrity": "sha512-VEzCNHEzJO4B5Co4Q3YO06g7GThkSmgOWAFgQwa/BDKqT40/u36ccB7uYKsWzBMBRu3KsOWFk6sPSueQiMfmew==", |
|
507 |
+ "dependencies": { |
|
508 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
509 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
510 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
511 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
512 |
+ "@ckeditor/ckeditor5-widget": "45.2.1", |
|
513 |
+ "es-toolkit": "1.32.0" |
|
514 |
+ } |
|
515 |
+ }, |
|
516 |
+ "node_modules/@ckeditor/ckeditor5-cloud-services": { |
|
517 |
+ "version": "45.2.1", |
|
518 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-cloud-services/-/ckeditor5-cloud-services-45.2.1.tgz", |
|
519 |
+ "integrity": "sha512-LQDjKxScFAkgXiFB9fypqf3pj2ou63SgsTmt3aMuH/e5NGxGCbG9EodHWgFCg5cvGEXV+jC7JCrOquflti/yBg==", |
|
520 |
+ "dependencies": { |
|
521 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
522 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
523 |
+ "ckeditor5": "45.2.1" |
|
524 |
+ } |
|
525 |
+ }, |
|
526 |
+ "node_modules/@ckeditor/ckeditor5-code-block": { |
|
527 |
+ "version": "45.2.1", |
|
528 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-code-block/-/ckeditor5-code-block-45.2.1.tgz", |
|
529 |
+ "integrity": "sha512-/XmKP8lol6WHDK/wbxFJu3npH8WnbZC9Gt7kND8bnpfQTSVihZmtjOnSfmyo6jKTsXWB1eDUI4+JdKCdrgfd2A==", |
|
530 |
+ "dependencies": { |
|
531 |
+ "@ckeditor/ckeditor5-clipboard": "45.2.1", |
|
532 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
533 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
534 |
+ "@ckeditor/ckeditor5-enter": "45.2.1", |
|
535 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
536 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
537 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
538 |
+ "ckeditor5": "45.2.1" |
|
539 |
+ } |
|
540 |
+ }, |
|
541 |
+ "node_modules/@ckeditor/ckeditor5-core": { |
|
542 |
+ "version": "45.2.1", |
|
543 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-45.2.1.tgz", |
|
544 |
+ "integrity": "sha512-h32tw/50ampWiouysBEQLXbPSAV1QV4iUEFNQzJVSy9q9fnGy6hsLZNlTqA+bORHwhn8SL96+OcAcGUNOiWfEg==", |
|
545 |
+ "dependencies": { |
|
546 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
547 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
548 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
549 |
+ "@ckeditor/ckeditor5-watchdog": "45.2.1", |
|
550 |
+ "es-toolkit": "1.32.0" |
|
551 |
+ } |
|
552 |
+ }, |
|
553 |
+ "node_modules/@ckeditor/ckeditor5-easy-image": { |
|
554 |
+ "version": "45.2.1", |
|
555 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-45.2.1.tgz", |
|
556 |
+ "integrity": "sha512-jPydqTv1pRWo+uYQQn+er/WH3z6R77Jn3w2hQGKy77Ku9j0gEp/YwODSTW/IeZDDHE7Bmrw1S5ULHoveX7k4lg==", |
|
557 |
+ "dependencies": { |
|
558 |
+ "@ckeditor/ckeditor5-cloud-services": "45.2.1", |
|
559 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
560 |
+ "@ckeditor/ckeditor5-upload": "45.2.1", |
|
561 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
562 |
+ "ckeditor5": "45.2.1" |
|
563 |
+ } |
|
564 |
+ }, |
|
565 |
+ "node_modules/@ckeditor/ckeditor5-editor-balloon": { |
|
566 |
+ "version": "45.2.1", |
|
567 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-balloon/-/ckeditor5-editor-balloon-45.2.1.tgz", |
|
568 |
+ "integrity": "sha512-K/nNGeaBuD5MvaxamoZzv97LPzyb7n9t8FiScmXIpgkmy/mRt1jkbhmMtGuHdTuUL2v4z3hCthb1EDsxJM8HwQ==", |
|
569 |
+ "dependencies": { |
|
570 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
571 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
572 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
573 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
574 |
+ "ckeditor5": "45.2.1", |
|
575 |
+ "es-toolkit": "1.32.0" |
|
576 |
+ } |
|
577 |
+ }, |
|
578 |
+ "node_modules/@ckeditor/ckeditor5-editor-classic": { |
|
579 |
+ "version": "45.2.1", |
|
580 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-45.2.1.tgz", |
|
581 |
+ "integrity": "sha512-cIyNNu4jano8WHl94ljNxXVpxGQadx4esDbV1rmj3e5gCh0XCXPOcyHYW9QPCT1Jf2M7YX32t5FFT/ixV4269A==", |
|
582 |
+ "dependencies": { |
|
583 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
584 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
585 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
586 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
587 |
+ "ckeditor5": "45.2.1", |
|
588 |
+ "es-toolkit": "1.32.0" |
|
589 |
+ } |
|
590 |
+ }, |
|
591 |
+ "node_modules/@ckeditor/ckeditor5-editor-decoupled": { |
|
592 |
+ "version": "45.2.1", |
|
593 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-decoupled/-/ckeditor5-editor-decoupled-45.2.1.tgz", |
|
594 |
+ "integrity": "sha512-LNXe8CTIYL7PxwMHe2i1Ta7BlqmEO9ke/xrQxW+FHJ1obEsjZS56uz7YgBWISGXjWh/0bBRpz+7jL0FhflK9Dw==", |
|
595 |
+ "dependencies": { |
|
596 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
597 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
598 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
599 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
600 |
+ "ckeditor5": "45.2.1", |
|
601 |
+ "es-toolkit": "1.32.0" |
|
602 |
+ } |
|
603 |
+ }, |
|
604 |
+ "node_modules/@ckeditor/ckeditor5-editor-inline": { |
|
605 |
+ "version": "45.2.1", |
|
606 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-45.2.1.tgz", |
|
607 |
+ "integrity": "sha512-/z/7U43QdVn0PUgIq+a/HRbgAut2eeLCzWVL4henbfSRxYJ9DBHH3ckIhX//QTfyTodeJ/5igrSmZH7oGVPwww==", |
|
608 |
+ "dependencies": { |
|
609 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
610 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
611 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
612 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
613 |
+ "ckeditor5": "45.2.1", |
|
614 |
+ "es-toolkit": "1.32.0" |
|
615 |
+ } |
|
616 |
+ }, |
|
617 |
+ "node_modules/@ckeditor/ckeditor5-editor-multi-root": { |
|
618 |
+ "version": "45.2.1", |
|
619 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-multi-root/-/ckeditor5-editor-multi-root-45.2.1.tgz", |
|
620 |
+ "integrity": "sha512-o3AIx3fKCbQPKrbcgflgUVLEfP+zL2/oX22agIA0iugghpLF2Q7y0hlVRuYjWa0fOY1mxt7EKC6BWwgrSF3X3Q==", |
|
621 |
+ "dependencies": { |
|
622 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
623 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
624 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
625 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
626 |
+ "ckeditor5": "45.2.1", |
|
627 |
+ "es-toolkit": "1.32.0" |
|
628 |
+ } |
|
629 |
+ }, |
|
630 |
+ "node_modules/@ckeditor/ckeditor5-emoji": { |
|
631 |
+ "version": "45.2.1", |
|
632 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-emoji/-/ckeditor5-emoji-45.2.1.tgz", |
|
633 |
+ "integrity": "sha512-g5jtferdBRC7VI34AiLoVQZ4MYYr3PgEM0yZ1rNJSt0UfxQgZcHTu0SrZV/qxxweDcyQikHeBMrkQy0i77zabQ==", |
|
634 |
+ "dependencies": { |
|
635 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
636 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
637 |
+ "@ckeditor/ckeditor5-mention": "45.2.1", |
|
638 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
639 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
640 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
641 |
+ "ckeditor5": "45.2.1", |
|
642 |
+ "es-toolkit": "1.32.0", |
|
643 |
+ "fuzzysort": "3.1.0" |
|
644 |
+ } |
|
645 |
+ }, |
|
646 |
+ "node_modules/@ckeditor/ckeditor5-engine": { |
|
647 |
+ "version": "45.2.1", |
|
648 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-45.2.1.tgz", |
|
649 |
+ "integrity": "sha512-kX6myPFscybc7ujM/iFTCKi5353+uRg0h1UKXVvh0NuqcnzJkMmpke3iFyzUckkfmtw/GvLvtRTli3190QgBaw==", |
|
650 |
+ "dependencies": { |
|
651 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
652 |
+ "es-toolkit": "1.32.0" |
|
653 |
+ } |
|
654 |
+ }, |
|
655 |
+ "node_modules/@ckeditor/ckeditor5-enter": { |
|
656 |
+ "version": "45.2.1", |
|
657 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-45.2.1.tgz", |
|
658 |
+ "integrity": "sha512-y5wsQmB6+rERieqkPi/DvrrY2v8t8bUVZtVtx7vdiujF3Iab7s6GvPcLCZJDhDPRNSVxJb2wR0jREIqGv+CAgw==", |
|
659 |
+ "dependencies": { |
|
660 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
661 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
662 |
+ "@ckeditor/ckeditor5-utils": "45.2.1" |
|
663 |
+ } |
|
664 |
+ }, |
|
665 |
+ "node_modules/@ckeditor/ckeditor5-essentials": { |
|
666 |
+ "version": "45.2.1", |
|
667 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-45.2.1.tgz", |
|
668 |
+ "integrity": "sha512-kMHqD/m5Y55CqgjAa4Ui5p+yg28c1Itm6V97Sn30z3lMXauSRU9Bg9JnSlV+b1zqZuiUGBedEtc8ou5rm1px+A==", |
|
669 |
+ "dependencies": { |
|
670 |
+ "@ckeditor/ckeditor5-clipboard": "45.2.1", |
|
671 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
672 |
+ "@ckeditor/ckeditor5-enter": "45.2.1", |
|
673 |
+ "@ckeditor/ckeditor5-select-all": "45.2.1", |
|
674 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
675 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
676 |
+ "@ckeditor/ckeditor5-undo": "45.2.1", |
|
677 |
+ "ckeditor5": "45.2.1" |
|
678 |
+ } |
|
679 |
+ }, |
|
680 |
+ "node_modules/@ckeditor/ckeditor5-find-and-replace": { |
|
681 |
+ "version": "45.2.1", |
|
682 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-find-and-replace/-/ckeditor5-find-and-replace-45.2.1.tgz", |
|
683 |
+ "integrity": "sha512-mfdWr5Sy+HHLKZXXq3qkuMYgIUR+est/snEQyUeySUYMMh0LxvlO5nUG6X5RQXmWy9eTmpNDvObLxm48/tcsvg==", |
|
684 |
+ "dependencies": { |
|
685 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
686 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
687 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
688 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
689 |
+ "ckeditor5": "45.2.1", |
|
690 |
+ "es-toolkit": "1.32.0" |
|
691 |
+ } |
|
692 |
+ }, |
|
693 |
+ "node_modules/@ckeditor/ckeditor5-font": { |
|
694 |
+ "version": "45.2.1", |
|
695 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-45.2.1.tgz", |
|
696 |
+ "integrity": "sha512-ZrvK0XcR/SXYbGyAczJRd4Y/U2fJcqEKSpxNHZLxTpVDArS9E1PQGQ/F27w4Z2wfmAKKjqf2SPlWb2JBZ/RY/w==", |
|
697 |
+ "dependencies": { |
|
698 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
699 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
700 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
701 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
702 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
703 |
+ "ckeditor5": "45.2.1" |
|
704 |
+ } |
|
705 |
+ }, |
|
706 |
+ "node_modules/@ckeditor/ckeditor5-fullscreen": { |
|
707 |
+ "version": "45.2.1", |
|
708 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-fullscreen/-/ckeditor5-fullscreen-45.2.1.tgz", |
|
709 |
+ "integrity": "sha512-quSvp00VLA03aXTStgICRIglKN19Dn2elyJ+w20i1ZitvWZNf9bNayDeeCZGR2+qU/2kAEAsn5Q2bdHlC2tUnA==", |
|
710 |
+ "dependencies": { |
|
711 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
712 |
+ "@ckeditor/ckeditor5-editor-classic": "45.2.1", |
|
713 |
+ "@ckeditor/ckeditor5-editor-decoupled": "45.2.1", |
|
714 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
715 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
716 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
717 |
+ "ckeditor5": "45.2.1" |
|
718 |
+ } |
|
719 |
+ }, |
|
720 |
+ "node_modules/@ckeditor/ckeditor5-heading": { |
|
721 |
+ "version": "45.2.1", |
|
722 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-45.2.1.tgz", |
|
723 |
+ "integrity": "sha512-J9ICygU3x0c0gY7FJJ0Ba3EFVlspbQinungipnIyMF2/4SXTOepKxHYG3x7j9xcjpUGosokeSvKfdQ0ACKtoKg==", |
|
724 |
+ "dependencies": { |
|
725 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
726 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
727 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
728 |
+ "@ckeditor/ckeditor5-paragraph": "45.2.1", |
|
729 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
730 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
731 |
+ "ckeditor5": "45.2.1" |
|
732 |
+ } |
|
733 |
+ }, |
|
734 |
+ "node_modules/@ckeditor/ckeditor5-highlight": { |
|
735 |
+ "version": "45.2.1", |
|
736 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-highlight/-/ckeditor5-highlight-45.2.1.tgz", |
|
737 |
+ "integrity": "sha512-Z8mIWO0TpvAyfQslJn3FertL8Brl2L7xIgad/s8JMfUWPcB7Tg2qm5GUqe1yfBmROz2g86JX+v6iMVvb5MkBHg==", |
|
738 |
+ "dependencies": { |
|
739 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
740 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
741 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
742 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
743 |
+ "ckeditor5": "45.2.1" |
|
744 |
+ } |
|
745 |
+ }, |
|
746 |
+ "node_modules/@ckeditor/ckeditor5-horizontal-line": { |
|
747 |
+ "version": "45.2.1", |
|
748 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-horizontal-line/-/ckeditor5-horizontal-line-45.2.1.tgz", |
|
749 |
+ "integrity": "sha512-YMI7XQuMUTbhG33jrAGlmkkIxVnusF/e057oUAJ+Er6ug1RRAd3Y1I2MLmmk4/4mGmjXZPOXH8ueWHHFCMOvog==", |
|
750 |
+ "dependencies": { |
|
751 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
752 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
753 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
754 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
755 |
+ "@ckeditor/ckeditor5-widget": "45.2.1", |
|
756 |
+ "ckeditor5": "45.2.1" |
|
757 |
+ } |
|
758 |
+ }, |
|
759 |
+ "node_modules/@ckeditor/ckeditor5-html-embed": { |
|
760 |
+ "version": "45.2.1", |
|
761 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-embed/-/ckeditor5-html-embed-45.2.1.tgz", |
|
762 |
+ "integrity": "sha512-UMr3GPcoavAHHFv4DWk/9dvgHmHEft1VzUYEAYK9S2lC8ADkSzo6rrWOwYapFZps1tJEwQjLQF+XZ9fw41t0lw==", |
|
763 |
+ "dependencies": { |
|
764 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
765 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
766 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
767 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
768 |
+ "@ckeditor/ckeditor5-widget": "45.2.1", |
|
769 |
+ "ckeditor5": "45.2.1" |
|
770 |
+ } |
|
771 |
+ }, |
|
772 |
+ "node_modules/@ckeditor/ckeditor5-html-support": { |
|
773 |
+ "version": "45.2.1", |
|
774 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-support/-/ckeditor5-html-support-45.2.1.tgz", |
|
775 |
+ "integrity": "sha512-ZxT3vxO4++iN7BU1fApTIDGkjAkWemUyNkUxWt/TRg3tgOUbnlyhyS9HHOh/UITfNuLgx9IKm04uh611okIIAA==", |
|
776 |
+ "dependencies": { |
|
777 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
778 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
779 |
+ "@ckeditor/ckeditor5-enter": "45.2.1", |
|
780 |
+ "@ckeditor/ckeditor5-heading": "45.2.1", |
|
781 |
+ "@ckeditor/ckeditor5-image": "45.2.1", |
|
782 |
+ "@ckeditor/ckeditor5-list": "45.2.1", |
|
783 |
+ "@ckeditor/ckeditor5-table": "45.2.1", |
|
784 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
785 |
+ "@ckeditor/ckeditor5-widget": "45.2.1", |
|
786 |
+ "ckeditor5": "45.2.1", |
|
787 |
+ "es-toolkit": "1.32.0" |
|
788 |
+ } |
|
789 |
+ }, |
|
790 |
+ "node_modules/@ckeditor/ckeditor5-icons": { |
|
791 |
+ "version": "45.2.1", |
|
792 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-icons/-/ckeditor5-icons-45.2.1.tgz", |
|
793 |
+ "integrity": "sha512-vDCbPu8zKMFgiUQTFuie0h9PNHifXuAeiNHvk/W/6OutTNJwuBp7oLBpYvvkkJ5/iTFPL7En5nOc/czScNmqQw==" |
|
794 |
+ }, |
|
795 |
+ "node_modules/@ckeditor/ckeditor5-image": { |
|
796 |
+ "version": "45.2.1", |
|
797 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-45.2.1.tgz", |
|
798 |
+ "integrity": "sha512-dBd9jKh0Pn6pXJEOc3HX0aONJjTOVTh758K43Ncm/AN73G/mcoaN92mkoMSm1yxzea5W21hFBbr8ttseOyaIYw==", |
|
799 |
+ "dependencies": { |
|
800 |
+ "@ckeditor/ckeditor5-clipboard": "45.2.1", |
|
801 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
802 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
803 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
804 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
805 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
806 |
+ "@ckeditor/ckeditor5-undo": "45.2.1", |
|
807 |
+ "@ckeditor/ckeditor5-upload": "45.2.1", |
|
808 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
809 |
+ "@ckeditor/ckeditor5-widget": "45.2.1", |
|
810 |
+ "ckeditor5": "45.2.1", |
|
811 |
+ "es-toolkit": "1.32.0" |
|
812 |
+ } |
|
813 |
+ }, |
|
814 |
+ "node_modules/@ckeditor/ckeditor5-indent": { |
|
815 |
+ "version": "45.2.1", |
|
816 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-45.2.1.tgz", |
|
817 |
+ "integrity": "sha512-aQlXGtsydQ2l3wffKFE/Hs9RAmlJPLn6vMzi44NLnKxQ33bPPhqAr3JlCEMlyI5ihVlUE45KtEWt+F7wNljFrg==", |
|
818 |
+ "dependencies": { |
|
819 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
820 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
821 |
+ "@ckeditor/ckeditor5-heading": "45.2.1", |
|
822 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
823 |
+ "@ckeditor/ckeditor5-list": "45.2.1", |
|
824 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
825 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
826 |
+ "ckeditor5": "45.2.1" |
|
827 |
+ } |
|
828 |
+ }, |
|
829 |
+ "node_modules/@ckeditor/ckeditor5-integrations-common": { |
|
830 |
+ "version": "2.2.3", |
|
831 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-integrations-common/-/ckeditor5-integrations-common-2.2.3.tgz", |
|
832 |
+ "integrity": "sha512-92kQWQj1wiABF7bY1+J79Ze+WHr7pwVBufn1eeJLWcTXbPQq4sAolfKv8Y8Ka9g69mdyE9+GPWmGFYDeQJVPDg==", |
|
833 |
+ "engines": { |
|
834 |
+ "node": ">=18.0.0" |
|
835 |
+ }, |
|
836 |
+ "peerDependencies": { |
|
837 |
+ "ckeditor5": ">=42.0.0 || ^0.0.0-nightly" |
|
838 |
+ } |
|
839 |
+ }, |
|
840 |
+ "node_modules/@ckeditor/ckeditor5-language": { |
|
841 |
+ "version": "45.2.1", |
|
842 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-language/-/ckeditor5-language-45.2.1.tgz", |
|
843 |
+ "integrity": "sha512-pCN1tr+g4Cj7wqRLiaLcbDRJze+pxp8bfHr0T1z1wZRIs5c2lyZtSX00EqyxkXWFYWfu0wPujqKxQzetPbr98w==", |
|
844 |
+ "dependencies": { |
|
845 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
846 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
847 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
848 |
+ "ckeditor5": "45.2.1" |
|
849 |
+ } |
|
850 |
+ }, |
|
851 |
+ "node_modules/@ckeditor/ckeditor5-link": { |
|
852 |
+ "version": "45.2.1", |
|
853 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-45.2.1.tgz", |
|
854 |
+ "integrity": "sha512-TjqPAfbjQEpmJK7YQ3ounjnEVSbseGwyws9AeyhVKHINbppE1LSA9Q8pDELEUalEOBvaEZgB5x0OtuCQE7exdg==", |
|
855 |
+ "dependencies": { |
|
856 |
+ "@ckeditor/ckeditor5-clipboard": "45.2.1", |
|
857 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
858 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
859 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
860 |
+ "@ckeditor/ckeditor5-image": "45.2.1", |
|
861 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
862 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
863 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
864 |
+ "@ckeditor/ckeditor5-widget": "45.2.1", |
|
865 |
+ "ckeditor5": "45.2.1", |
|
866 |
+ "es-toolkit": "1.32.0" |
|
867 |
+ } |
|
868 |
+ }, |
|
869 |
+ "node_modules/@ckeditor/ckeditor5-list": { |
|
870 |
+ "version": "45.2.1", |
|
871 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-45.2.1.tgz", |
|
872 |
+ "integrity": "sha512-liUKNg4XVoj4dx2JtxS6F+zSlnAYLUCv8y9odEAOQ/ar9m2cCvtxfBAbO6GQnJu1aBOxM5/P1J3HuQmFCr48EQ==", |
|
873 |
+ "dependencies": { |
|
874 |
+ "@ckeditor/ckeditor5-clipboard": "45.2.1", |
|
875 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
876 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
877 |
+ "@ckeditor/ckeditor5-enter": "45.2.1", |
|
878 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
879 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
880 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
881 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
882 |
+ "ckeditor5": "45.2.1" |
|
883 |
+ } |
|
884 |
+ }, |
|
885 |
+ "node_modules/@ckeditor/ckeditor5-markdown-gfm": { |
|
886 |
+ "version": "45.2.1", |
|
887 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-markdown-gfm/-/ckeditor5-markdown-gfm-45.2.1.tgz", |
|
888 |
+ "integrity": "sha512-SGLY//kbcZy/MzZDSy/af/80gmh5vkMoQhAqR4FBTgWTosKbZblhgXaLM10Ld0bcjQMJL2BLeTNKHDcy7S2MFQ==", |
|
889 |
+ "dependencies": { |
|
890 |
+ "@ckeditor/ckeditor5-clipboard": "45.2.1", |
|
891 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
892 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
893 |
+ "@types/marked": "4.3.2", |
|
894 |
+ "@types/turndown": "5.0.5", |
|
895 |
+ "ckeditor5": "45.2.1", |
|
896 |
+ "marked": "4.0.12", |
|
897 |
+ "turndown": "7.2.0", |
|
898 |
+ "turndown-plugin-gfm": "1.0.2" |
|
899 |
+ } |
|
900 |
+ }, |
|
901 |
+ "node_modules/@ckeditor/ckeditor5-media-embed": { |
|
902 |
+ "version": "45.2.1", |
|
903 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-45.2.1.tgz", |
|
904 |
+ "integrity": "sha512-0NED9h+BIAns/DNaUotCD5Uhm6MNzGI4QsJ4obCrtl0lolBerXhzcRtlRVaF3R8omlMvS6r80fWsWSCttcpGjw==", |
|
905 |
+ "dependencies": { |
|
906 |
+ "@ckeditor/ckeditor5-clipboard": "45.2.1", |
|
907 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
908 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
909 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
910 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
911 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
912 |
+ "@ckeditor/ckeditor5-undo": "45.2.1", |
|
913 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
914 |
+ "@ckeditor/ckeditor5-widget": "45.2.1", |
|
915 |
+ "ckeditor5": "45.2.1" |
|
916 |
+ } |
|
917 |
+ }, |
|
918 |
+ "node_modules/@ckeditor/ckeditor5-mention": { |
|
919 |
+ "version": "45.2.1", |
|
920 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-mention/-/ckeditor5-mention-45.2.1.tgz", |
|
921 |
+ "integrity": "sha512-q77TXcjzQ1dZkvxPKu3TC3OAJiwLXeCNYglGvt5iqxQ1PmY86TI0EyO/qWApKiydacowev7ppCbDkHvA0oCMRA==", |
|
922 |
+ "dependencies": { |
|
923 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
924 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
925 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
926 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
927 |
+ "ckeditor5": "45.2.1", |
|
928 |
+ "es-toolkit": "1.32.0" |
|
929 |
+ } |
|
930 |
+ }, |
|
931 |
+ "node_modules/@ckeditor/ckeditor5-minimap": { |
|
932 |
+ "version": "45.2.1", |
|
933 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-minimap/-/ckeditor5-minimap-45.2.1.tgz", |
|
934 |
+ "integrity": "sha512-bKYcvZ7wIolttXfXR9BzyVEI+6FmflO0EhvOw+Ic9VClDy81Y4EYyCMB0XsXK0JO0KTnTKUOmLrPTfOnU/c68w==", |
|
935 |
+ "dependencies": { |
|
936 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
937 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
938 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
939 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
940 |
+ "ckeditor5": "45.2.1" |
|
941 |
+ } |
|
942 |
+ }, |
|
943 |
+ "node_modules/@ckeditor/ckeditor5-page-break": { |
|
944 |
+ "version": "45.2.1", |
|
945 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-page-break/-/ckeditor5-page-break-45.2.1.tgz", |
|
946 |
+ "integrity": "sha512-KiHGordLRIzebAeyyY43WHR1bpjXab9cD+S8BWeivGBYytFRN4S+MT288HiweYk53Pla2pumrgoBZ/qKLkn98Q==", |
|
947 |
+ "dependencies": { |
|
948 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
949 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
950 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
951 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
952 |
+ "@ckeditor/ckeditor5-widget": "45.2.1", |
|
953 |
+ "ckeditor5": "45.2.1" |
|
954 |
+ } |
|
955 |
+ }, |
|
956 |
+ "node_modules/@ckeditor/ckeditor5-paragraph": { |
|
957 |
+ "version": "45.2.1", |
|
958 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-45.2.1.tgz", |
|
959 |
+ "integrity": "sha512-bDZUEHXruWG7P7PDIwNKKuUjgIvLbbY+m0GEXOI4+eB7cnJBOLbs62t8m+tLFJ/PRWUsJ/kA1RJQgouiy60+0Q==", |
|
960 |
+ "dependencies": { |
|
961 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
962 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
963 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
964 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
965 |
+ "@ckeditor/ckeditor5-utils": "45.2.1" |
|
966 |
+ } |
|
967 |
+ }, |
|
968 |
+ "node_modules/@ckeditor/ckeditor5-paste-from-office": { |
|
969 |
+ "version": "45.2.1", |
|
970 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-45.2.1.tgz", |
|
971 |
+ "integrity": "sha512-G5duZPSLmdGxghjBeHU2i1WJoKn8YdKI2lZu8GxqRQ1/FTaoWqnCpEAnxztLLTtwyI9HuFh6IuxrdnyPQOWtxw==", |
|
972 |
+ "dependencies": { |
|
973 |
+ "@ckeditor/ckeditor5-clipboard": "45.2.1", |
|
974 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
975 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
976 |
+ "ckeditor5": "45.2.1" |
|
977 |
+ } |
|
978 |
+ }, |
|
979 |
+ "node_modules/@ckeditor/ckeditor5-remove-format": { |
|
980 |
+ "version": "45.2.1", |
|
981 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-remove-format/-/ckeditor5-remove-format-45.2.1.tgz", |
|
982 |
+ "integrity": "sha512-JKZdCqdrCOjP84ynUhE8F10q0LTiOTadhCsMYtfFUaMXlv+Ey6BMwh28I9WstGmhBiDmF4evivI8Jovncc0pyg==", |
|
983 |
+ "dependencies": { |
|
984 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
985 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
986 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
987 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
988 |
+ "ckeditor5": "45.2.1" |
|
989 |
+ } |
|
990 |
+ }, |
|
991 |
+ "node_modules/@ckeditor/ckeditor5-restricted-editing": { |
|
992 |
+ "version": "45.2.1", |
|
993 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-restricted-editing/-/ckeditor5-restricted-editing-45.2.1.tgz", |
|
994 |
+ "integrity": "sha512-rapILyX18HIw8xCuXozfQorz6Y/0Jd48/zr9ChXDbDkbDr4qaWdqAZ2bMuz8qP8k53dmkvxl4DfVfqM200txXQ==", |
|
995 |
+ "dependencies": { |
|
996 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
997 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
998 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
999 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
1000 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
1001 |
+ "ckeditor5": "45.2.1" |
|
1002 |
+ } |
|
1003 |
+ }, |
|
1004 |
+ "node_modules/@ckeditor/ckeditor5-select-all": { |
|
1005 |
+ "version": "45.2.1", |
|
1006 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-45.2.1.tgz", |
|
1007 |
+ "integrity": "sha512-WRXtKECu+yrZGfNeriRQT+q41NDmW3K72cQL7Sben9CsJ4ixAFdc4APaDC5GvIvE00hjjLhZAVBtV8fiBTys/g==", |
|
1008 |
+ "dependencies": { |
|
1009 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1010 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
1011 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
1012 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
1013 |
+ "@ckeditor/ckeditor5-utils": "45.2.1" |
|
1014 |
+ } |
|
1015 |
+ }, |
|
1016 |
+ "node_modules/@ckeditor/ckeditor5-show-blocks": { |
|
1017 |
+ "version": "45.2.1", |
|
1018 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-show-blocks/-/ckeditor5-show-blocks-45.2.1.tgz", |
|
1019 |
+ "integrity": "sha512-VX6v9mkDkh5xaK/KANxjDRiRMowcUODHBg1z+MJZyVqeFxfDabHSQuS2OLYzsSJfeTlCzs/11IRHCGQq4ifyIQ==", |
|
1020 |
+ "dependencies": { |
|
1021 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1022 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
1023 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
1024 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
1025 |
+ "ckeditor5": "45.2.1" |
|
1026 |
+ } |
|
1027 |
+ }, |
|
1028 |
+ "node_modules/@ckeditor/ckeditor5-source-editing": { |
|
1029 |
+ "version": "45.2.1", |
|
1030 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-source-editing/-/ckeditor5-source-editing-45.2.1.tgz", |
|
1031 |
+ "integrity": "sha512-HFaUovnh6v/9oIUWpxmxNxQIHArONuqzKMyipLHS7XWzb9nnMda+P5wnoYEiysoiNSDyBhM+yLCsgqs28XsmJg==", |
|
1032 |
+ "dependencies": { |
|
1033 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1034 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
1035 |
+ "@ckeditor/ckeditor5-theme-lark": "45.2.1", |
|
1036 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
1037 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
1038 |
+ "ckeditor5": "45.2.1" |
|
1039 |
+ } |
|
1040 |
+ }, |
|
1041 |
+ "node_modules/@ckeditor/ckeditor5-special-characters": { |
|
1042 |
+ "version": "45.2.1", |
|
1043 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-special-characters/-/ckeditor5-special-characters-45.2.1.tgz", |
|
1044 |
+ "integrity": "sha512-VECZXNiE1dA/TTJJUdz9kbWXDTXTIWsXyuBrvwQX/SgsPjIKYlpGW+oTu6iZdC4I/q0dsFvJvDJ6ngx89cxpLg==", |
|
1045 |
+ "dependencies": { |
|
1046 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1047 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
1048 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
1049 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
1050 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
1051 |
+ "ckeditor5": "45.2.1" |
|
1052 |
+ } |
|
1053 |
+ }, |
|
1054 |
+ "node_modules/@ckeditor/ckeditor5-style": { |
|
1055 |
+ "version": "45.2.1", |
|
1056 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-style/-/ckeditor5-style-45.2.1.tgz", |
|
1057 |
+ "integrity": "sha512-Rdf3FeNRFBngYBUrdfjLBYQkvcFHc4g7D48+nkBiYmPeYDIcviRxq0Ss50UHHgwl/aB6w6UvVdI2j+2HhYE+xQ==", |
|
1058 |
+ "dependencies": { |
|
1059 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1060 |
+ "@ckeditor/ckeditor5-html-support": "45.2.1", |
|
1061 |
+ "@ckeditor/ckeditor5-list": "45.2.1", |
|
1062 |
+ "@ckeditor/ckeditor5-table": "45.2.1", |
|
1063 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
1064 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
1065 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
1066 |
+ "ckeditor5": "45.2.1", |
|
1067 |
+ "es-toolkit": "1.32.0" |
|
1068 |
+ } |
|
1069 |
+ }, |
|
1070 |
+ "node_modules/@ckeditor/ckeditor5-table": { |
|
1071 |
+ "version": "45.2.1", |
|
1072 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-45.2.1.tgz", |
|
1073 |
+ "integrity": "sha512-Twu2vztW0s5BVwn+AYcvH8Akx0SS1tSZ1P7MbVvYnm3+o0hOsHjO+bFi9anN+U53l5ciukNFtwLbvQw8YcKXvg==", |
|
1074 |
+ "dependencies": { |
|
1075 |
+ "@ckeditor/ckeditor5-clipboard": "45.2.1", |
|
1076 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1077 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
1078 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
1079 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
1080 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
1081 |
+ "@ckeditor/ckeditor5-widget": "45.2.1", |
|
1082 |
+ "ckeditor5": "45.2.1", |
|
1083 |
+ "es-toolkit": "1.32.0" |
|
1084 |
+ } |
|
1085 |
+ }, |
|
1086 |
+ "node_modules/@ckeditor/ckeditor5-theme-lark": { |
|
1087 |
+ "version": "45.2.1", |
|
1088 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-45.2.1.tgz", |
|
1089 |
+ "integrity": "sha512-+JYkfdbCW7bYK+dYmxDSL49s4tZTzabrymvSt+fgFATDmbosP9zRRENPSYpfq0J7v0wJSOJrkK6aPiuEJr8VrQ==", |
|
1090 |
+ "dependencies": { |
|
1091 |
+ "@ckeditor/ckeditor5-ui": "45.2.1" |
|
1092 |
+ } |
|
1093 |
+ }, |
|
1094 |
+ "node_modules/@ckeditor/ckeditor5-typing": { |
|
1095 |
+ "version": "45.2.1", |
|
1096 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-45.2.1.tgz", |
|
1097 |
+ "integrity": "sha512-zsIDw2UZjEgH1OBFTE/e+ACFWgpQgwLGmfOA1R99SpSyuBzGgEeTQm/rLniZbnAQ3TJMHDm89dz0MneMhn9cgg==", |
|
1098 |
+ "dependencies": { |
|
1099 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1100 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
1101 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
1102 |
+ "es-toolkit": "1.32.0" |
|
1103 |
+ } |
|
1104 |
+ }, |
|
1105 |
+ "node_modules/@ckeditor/ckeditor5-ui": { |
|
1106 |
+ "version": "45.2.1", |
|
1107 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-45.2.1.tgz", |
|
1108 |
+ "integrity": "sha512-ZBl6xJliYhdQr8/9gCi9Pytz88YDD3VV+zyDq+5pBl1mI8feBjxp5XfPZxxAfV0dowqppqP/17UnPLtc+7YA0g==", |
|
1109 |
+ "dependencies": { |
|
1110 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1111 |
+ "@ckeditor/ckeditor5-editor-multi-root": "45.2.1", |
|
1112 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
1113 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
1114 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
1115 |
+ "@types/color-convert": "2.0.4", |
|
1116 |
+ "color-convert": "2.0.1", |
|
1117 |
+ "color-parse": "1.4.2", |
|
1118 |
+ "es-toolkit": "1.32.0", |
|
1119 |
+ "vanilla-colorful": "0.7.2" |
|
1120 |
+ } |
|
1121 |
+ }, |
|
1122 |
+ "node_modules/@ckeditor/ckeditor5-undo": { |
|
1123 |
+ "version": "45.2.1", |
|
1124 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-45.2.1.tgz", |
|
1125 |
+ "integrity": "sha512-c3xJqk6iZLgHrCpJHektg/I1+ApcaTDEDfIS0pps8oxL1Ys6CWNE0QrlF5AuRoUopv//ik1iZg/qoA98JsQ1Ng==", |
|
1126 |
+ "dependencies": { |
|
1127 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1128 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
1129 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
1130 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
1131 |
+ "@ckeditor/ckeditor5-utils": "45.2.1" |
|
1132 |
+ } |
|
1133 |
+ }, |
|
1134 |
+ "node_modules/@ckeditor/ckeditor5-upload": { |
|
1135 |
+ "version": "45.2.1", |
|
1136 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-45.2.1.tgz", |
|
1137 |
+ "integrity": "sha512-lg54V7wXouKy4q9Umt47ubUidelMsujgwxJCJg3egcNLKPiskYHnWlhYfA8hyVV21XCpfbm73c8Y1UWvkTglXA==", |
|
1138 |
+ "dependencies": { |
|
1139 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1140 |
+ "@ckeditor/ckeditor5-utils": "45.2.1" |
|
1141 |
+ } |
|
1142 |
+ }, |
|
1143 |
+ "node_modules/@ckeditor/ckeditor5-utils": { |
|
1144 |
+ "version": "45.2.1", |
|
1145 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-45.2.1.tgz", |
|
1146 |
+ "integrity": "sha512-qjSsnUaw/VwklJZsRTVT6zDSBjMnmYIIGu3mHSk7Ybtao8W3fz1yzqdX3X6i937XGbw37+2MUfhJhrpubMnA8A==", |
|
1147 |
+ "dependencies": { |
|
1148 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
1149 |
+ "es-toolkit": "1.32.0" |
|
1150 |
+ } |
|
1151 |
+ }, |
|
1152 |
+ "node_modules/@ckeditor/ckeditor5-vue": { |
|
1153 |
+ "version": "7.3.0", |
|
1154 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-vue/-/ckeditor5-vue-7.3.0.tgz", |
|
1155 |
+ "integrity": "sha512-OM8VW2bf5cXWKKaSr2eS1BhjzPmvkC2Jp/rWFdjU8wi4hhcKVJ5QqMepDguDcC+PHThaLec45WIrQTeLCb2AaA==", |
|
1156 |
+ "dependencies": { |
|
1157 |
+ "@ckeditor/ckeditor5-integrations-common": "^2.2.2", |
|
1158 |
+ "lodash-es": "^4.17.21" |
|
1159 |
+ }, |
|
1160 |
+ "engines": { |
|
1161 |
+ "node": ">=18.0.0" |
|
1162 |
+ }, |
|
1163 |
+ "peerDependencies": { |
|
1164 |
+ "ckeditor5": ">=42.0.0 || ^0.0.0-nightly", |
|
1165 |
+ "vue": "^3.4.0" |
|
1166 |
+ } |
|
1167 |
+ }, |
|
1168 |
+ "node_modules/@ckeditor/ckeditor5-watchdog": { |
|
1169 |
+ "version": "45.2.1", |
|
1170 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-45.2.1.tgz", |
|
1171 |
+ "integrity": "sha512-FthIfLtl4qCv7iNEul9ZvUulFZVYNeMwS+Ww22HstZlJP3Ahh/JF4CGTkzfbP/oGFUsZCEochQ7H2/f4MN7pbg==", |
|
1172 |
+ "dependencies": { |
|
1173 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1174 |
+ "@ckeditor/ckeditor5-editor-multi-root": "45.2.1", |
|
1175 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
1176 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
1177 |
+ "es-toolkit": "1.32.0" |
|
1178 |
+ } |
|
1179 |
+ }, |
|
1180 |
+ "node_modules/@ckeditor/ckeditor5-widget": { |
|
1181 |
+ "version": "45.2.1", |
|
1182 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-45.2.1.tgz", |
|
1183 |
+ "integrity": "sha512-4HOfHewBE0cF+7zKnQBWRJHLdq4K48YDW/uC5J0vDhLrtetBwWPE9kbnOUUoAGNYqGkiYRd7btt1M6pPhXrz9Q==", |
|
1184 |
+ "dependencies": { |
|
1185 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1186 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
1187 |
+ "@ckeditor/ckeditor5-enter": "45.2.1", |
|
1188 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
1189 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
1190 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
1191 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
1192 |
+ "es-toolkit": "1.32.0" |
|
1193 |
+ } |
|
1194 |
+ }, |
|
1195 |
+ "node_modules/@ckeditor/ckeditor5-word-count": { |
|
1196 |
+ "version": "45.2.1", |
|
1197 |
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-word-count/-/ckeditor5-word-count-45.2.1.tgz", |
|
1198 |
+ "integrity": "sha512-H4JmccFnFM+IaiT0zUTnx/7ebpAvelaJMEHWmntRlr1IFLf8AtwgOGBSeurglDVebyGXyqarbUxV4HpDxtzBxA==", |
|
1199 |
+ "dependencies": { |
|
1200 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
1201 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
1202 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
1203 |
+ "ckeditor5": "45.2.1", |
|
1204 |
+ "es-toolkit": "1.32.0" |
|
1205 |
+ } |
|
1206 |
+ }, |
|
383 | 1207 |
"node_modules/@ctrl/tinycolor": { |
384 | 1208 |
"version": "3.6.1", |
385 | 1209 |
"resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", |
... | ... | @@ -533,6 +1357,11 @@ |
533 | 1357 |
"@jridgewell/sourcemap-codec": "^1.4.14" |
534 | 1358 |
} |
535 | 1359 |
}, |
1360 |
+ "node_modules/@mixmark-io/domino": { |
|
1361 |
+ "version": "2.2.0", |
|
1362 |
+ "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz", |
|
1363 |
+ "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==" |
|
1364 |
+ }, |
|
536 | 1365 |
"node_modules/@nicolo-ribaudo/chokidar-2": { |
537 | 1366 |
"version": "2.1.8-no-fsevents.3", |
538 | 1367 |
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", |
... | ... | @@ -592,6 +1421,19 @@ |
592 | 1421 |
"node": ">= 10" |
593 | 1422 |
} |
594 | 1423 |
}, |
1424 |
+ "node_modules/@types/color-convert": { |
|
1425 |
+ "version": "2.0.4", |
|
1426 |
+ "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.4.tgz", |
|
1427 |
+ "integrity": "sha512-Ub1MmDdyZ7mX//g25uBAoH/mWGd9swVbt8BseymnaE18SU4po/PjmCrHxqIIRjBo3hV/vh1KGr0eMxUhp+t+dQ==", |
|
1428 |
+ "dependencies": { |
|
1429 |
+ "@types/color-name": "^1.1.0" |
|
1430 |
+ } |
|
1431 |
+ }, |
|
1432 |
+ "node_modules/@types/color-name": { |
|
1433 |
+ "version": "1.1.5", |
|
1434 |
+ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.5.tgz", |
|
1435 |
+ "integrity": "sha512-j2K5UJqGTxeesj6oQuGpMgifpT5k9HprgQd8D1Y0lOFqKHl3PJu5GMeS4Y5EgjS55AE6OQxf8mPED9uaGbf4Cg==" |
|
1436 |
+ }, |
|
595 | 1437 |
"node_modules/@types/eslint": { |
596 | 1438 |
"version": "9.6.1", |
597 | 1439 |
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", |
... | ... | @@ -624,6 +1466,11 @@ |
624 | 1466 |
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", |
625 | 1467 |
"license": "MIT" |
626 | 1468 |
}, |
1469 |
+ "node_modules/@types/marked": { |
|
1470 |
+ "version": "4.3.2", |
|
1471 |
+ "resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.3.2.tgz", |
|
1472 |
+ "integrity": "sha512-a79Yc3TOk6dGdituy8hmTTJXjOkZ7zsFYV10L337ttq/rec8lRMDBpV7fL3uLx6TgbFCa5DU/h8FmIBQPSbU0w==" |
|
1473 |
+ }, |
|
627 | 1474 |
"node_modules/@types/minimist": { |
628 | 1475 |
"version": "1.2.5", |
629 | 1476 |
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", |
... | ... | @@ -646,6 +1493,11 @@ |
646 | 1493 |
"integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", |
647 | 1494 |
"dev": true, |
648 | 1495 |
"license": "MIT" |
1496 |
+ }, |
|
1497 |
+ "node_modules/@types/turndown": { |
|
1498 |
+ "version": "5.0.5", |
|
1499 |
+ "resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.5.tgz", |
|
1500 |
+ "integrity": "sha512-TL2IgGgc7B5j78rIccBtlYAnkuv8nUQqhQc+DSYV5j9Be9XOcm/SKOVRuA47xAVI3680Tk9B1d8flK2GWT2+4w==" |
|
649 | 1501 |
}, |
650 | 1502 |
"node_modules/@vue/compiler-core": { |
651 | 1503 |
"version": "3.5.13", |
... | ... | @@ -1294,6 +2146,11 @@ |
1294 | 2146 |
"url": "https://github.com/sponsors/sindresorhus" |
1295 | 2147 |
} |
1296 | 2148 |
}, |
2149 |
+ "node_modules/blurhash": { |
|
2150 |
+ "version": "2.0.5", |
|
2151 |
+ "resolved": "https://registry.npmjs.org/blurhash/-/blurhash-2.0.5.tgz", |
|
2152 |
+ "integrity": "sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==" |
|
2153 |
+ }, |
|
1297 | 2154 |
"node_modules/body-parser": { |
1298 | 2155 |
"version": "1.20.0", |
1299 | 2156 |
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", |
... | ... | @@ -1633,6 +2490,74 @@ |
1633 | 2490 |
"node": ">=6.0" |
1634 | 2491 |
} |
1635 | 2492 |
}, |
2493 |
+ "node_modules/ckeditor5": { |
|
2494 |
+ "version": "45.2.1", |
|
2495 |
+ "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-45.2.1.tgz", |
|
2496 |
+ "integrity": "sha512-fPFysHo71yQ2TUYsD+VpnjH9kjboHSKGCIPf4AhJQ+eQwopzsnFkNgdvYcGPfAP11bHTRLG5Ol0wWISFa1mwCQ==", |
|
2497 |
+ "dependencies": { |
|
2498 |
+ "@ckeditor/ckeditor5-adapter-ckfinder": "45.2.1", |
|
2499 |
+ "@ckeditor/ckeditor5-alignment": "45.2.1", |
|
2500 |
+ "@ckeditor/ckeditor5-autoformat": "45.2.1", |
|
2501 |
+ "@ckeditor/ckeditor5-autosave": "45.2.1", |
|
2502 |
+ "@ckeditor/ckeditor5-basic-styles": "45.2.1", |
|
2503 |
+ "@ckeditor/ckeditor5-block-quote": "45.2.1", |
|
2504 |
+ "@ckeditor/ckeditor5-bookmark": "45.2.1", |
|
2505 |
+ "@ckeditor/ckeditor5-ckbox": "45.2.1", |
|
2506 |
+ "@ckeditor/ckeditor5-ckfinder": "45.2.1", |
|
2507 |
+ "@ckeditor/ckeditor5-clipboard": "45.2.1", |
|
2508 |
+ "@ckeditor/ckeditor5-cloud-services": "45.2.1", |
|
2509 |
+ "@ckeditor/ckeditor5-code-block": "45.2.1", |
|
2510 |
+ "@ckeditor/ckeditor5-core": "45.2.1", |
|
2511 |
+ "@ckeditor/ckeditor5-easy-image": "45.2.1", |
|
2512 |
+ "@ckeditor/ckeditor5-editor-balloon": "45.2.1", |
|
2513 |
+ "@ckeditor/ckeditor5-editor-classic": "45.2.1", |
|
2514 |
+ "@ckeditor/ckeditor5-editor-decoupled": "45.2.1", |
|
2515 |
+ "@ckeditor/ckeditor5-editor-inline": "45.2.1", |
|
2516 |
+ "@ckeditor/ckeditor5-editor-multi-root": "45.2.1", |
|
2517 |
+ "@ckeditor/ckeditor5-emoji": "45.2.1", |
|
2518 |
+ "@ckeditor/ckeditor5-engine": "45.2.1", |
|
2519 |
+ "@ckeditor/ckeditor5-enter": "45.2.1", |
|
2520 |
+ "@ckeditor/ckeditor5-essentials": "45.2.1", |
|
2521 |
+ "@ckeditor/ckeditor5-find-and-replace": "45.2.1", |
|
2522 |
+ "@ckeditor/ckeditor5-font": "45.2.1", |
|
2523 |
+ "@ckeditor/ckeditor5-fullscreen": "45.2.1", |
|
2524 |
+ "@ckeditor/ckeditor5-heading": "45.2.1", |
|
2525 |
+ "@ckeditor/ckeditor5-highlight": "45.2.1", |
|
2526 |
+ "@ckeditor/ckeditor5-horizontal-line": "45.2.1", |
|
2527 |
+ "@ckeditor/ckeditor5-html-embed": "45.2.1", |
|
2528 |
+ "@ckeditor/ckeditor5-html-support": "45.2.1", |
|
2529 |
+ "@ckeditor/ckeditor5-icons": "45.2.1", |
|
2530 |
+ "@ckeditor/ckeditor5-image": "45.2.1", |
|
2531 |
+ "@ckeditor/ckeditor5-indent": "45.2.1", |
|
2532 |
+ "@ckeditor/ckeditor5-language": "45.2.1", |
|
2533 |
+ "@ckeditor/ckeditor5-link": "45.2.1", |
|
2534 |
+ "@ckeditor/ckeditor5-list": "45.2.1", |
|
2535 |
+ "@ckeditor/ckeditor5-markdown-gfm": "45.2.1", |
|
2536 |
+ "@ckeditor/ckeditor5-media-embed": "45.2.1", |
|
2537 |
+ "@ckeditor/ckeditor5-mention": "45.2.1", |
|
2538 |
+ "@ckeditor/ckeditor5-minimap": "45.2.1", |
|
2539 |
+ "@ckeditor/ckeditor5-page-break": "45.2.1", |
|
2540 |
+ "@ckeditor/ckeditor5-paragraph": "45.2.1", |
|
2541 |
+ "@ckeditor/ckeditor5-paste-from-office": "45.2.1", |
|
2542 |
+ "@ckeditor/ckeditor5-remove-format": "45.2.1", |
|
2543 |
+ "@ckeditor/ckeditor5-restricted-editing": "45.2.1", |
|
2544 |
+ "@ckeditor/ckeditor5-select-all": "45.2.1", |
|
2545 |
+ "@ckeditor/ckeditor5-show-blocks": "45.2.1", |
|
2546 |
+ "@ckeditor/ckeditor5-source-editing": "45.2.1", |
|
2547 |
+ "@ckeditor/ckeditor5-special-characters": "45.2.1", |
|
2548 |
+ "@ckeditor/ckeditor5-style": "45.2.1", |
|
2549 |
+ "@ckeditor/ckeditor5-table": "45.2.1", |
|
2550 |
+ "@ckeditor/ckeditor5-theme-lark": "45.2.1", |
|
2551 |
+ "@ckeditor/ckeditor5-typing": "45.2.1", |
|
2552 |
+ "@ckeditor/ckeditor5-ui": "45.2.1", |
|
2553 |
+ "@ckeditor/ckeditor5-undo": "45.2.1", |
|
2554 |
+ "@ckeditor/ckeditor5-upload": "45.2.1", |
|
2555 |
+ "@ckeditor/ckeditor5-utils": "45.2.1", |
|
2556 |
+ "@ckeditor/ckeditor5-watchdog": "45.2.1", |
|
2557 |
+ "@ckeditor/ckeditor5-widget": "45.2.1", |
|
2558 |
+ "@ckeditor/ckeditor5-word-count": "45.2.1" |
|
2559 |
+ } |
|
2560 |
+ }, |
|
1636 | 2561 |
"node_modules/classnames": { |
1637 | 2562 |
"version": "2.5.1", |
1638 | 2563 |
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", |
... | ... | @@ -1695,6 +2620,14 @@ |
1695 | 2620 |
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", |
1696 | 2621 |
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", |
1697 | 2622 |
"license": "MIT" |
2623 |
+ }, |
|
2624 |
+ "node_modules/color-parse": { |
|
2625 |
+ "version": "1.4.2", |
|
2626 |
+ "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.4.2.tgz", |
|
2627 |
+ "integrity": "sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA==", |
|
2628 |
+ "dependencies": { |
|
2629 |
+ "color-name": "^1.0.0" |
|
2630 |
+ } |
|
1698 | 2631 |
}, |
1699 | 2632 |
"node_modules/color-support": { |
1700 | 2633 |
"version": "1.1.3", |
... | ... | @@ -2167,6 +3100,11 @@ |
2167 | 3100 |
"engines": { |
2168 | 3101 |
"node": ">= 0.4" |
2169 | 3102 |
} |
3103 |
+ }, |
|
3104 |
+ "node_modules/es-toolkit": { |
|
3105 |
+ "version": "1.32.0", |
|
3106 |
+ "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.32.0.tgz", |
|
3107 |
+ "integrity": "sha512-ZfSfHP1l6ubgW/B/FRtqb9bYdMvI6jizbOSfbwwJNcOQ1QE6TFsC3jpQkZ900uUPSR3t3SU5Ds7UWKnYz+uP8Q==" |
|
2170 | 3108 |
}, |
2171 | 3109 |
"node_modules/es6-promise": { |
2172 | 3110 |
"version": "4.2.8", |
... | ... | @@ -2644,6 +3582,11 @@ |
2644 | 3582 |
"funding": { |
2645 | 3583 |
"url": "https://github.com/sponsors/ljharb" |
2646 | 3584 |
} |
3585 |
+ }, |
|
3586 |
+ "node_modules/fuzzysort": { |
|
3587 |
+ "version": "3.1.0", |
|
3588 |
+ "resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-3.1.0.tgz", |
|
3589 |
+ "integrity": "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==" |
|
2647 | 3590 |
}, |
2648 | 3591 |
"node_modules/gauge": { |
2649 | 3592 |
"version": "4.0.4", |
... | ... | @@ -3418,6 +4361,11 @@ |
3418 | 4361 |
"dev": true, |
3419 | 4362 |
"license": "MIT" |
3420 | 4363 |
}, |
4364 |
+ "node_modules/lodash-es": { |
|
4365 |
+ "version": "4.17.21", |
|
4366 |
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", |
|
4367 |
+ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" |
|
4368 |
+ }, |
|
3421 | 4369 |
"node_modules/lru-cache": { |
3422 | 4370 |
"version": "5.1.1", |
3423 | 4371 |
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", |
... | ... | @@ -3507,6 +4455,17 @@ |
3507 | 4455 |
}, |
3508 | 4456 |
"funding": { |
3509 | 4457 |
"url": "https://github.com/sponsors/sindresorhus" |
4458 |
+ } |
|
4459 |
+ }, |
|
4460 |
+ "node_modules/marked": { |
|
4461 |
+ "version": "4.0.12", |
|
4462 |
+ "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", |
|
4463 |
+ "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", |
|
4464 |
+ "bin": { |
|
4465 |
+ "marked": "bin/marked.js" |
|
4466 |
+ }, |
|
4467 |
+ "engines": { |
|
4468 |
+ "node": ">= 12" |
|
3510 | 4469 |
} |
3511 | 4470 |
}, |
3512 | 4471 |
"node_modules/math-intrinsics": { |
... | ... | @@ -5890,6 +6849,19 @@ |
5890 | 6849 |
"dev": true, |
5891 | 6850 |
"license": "Apache-2.0" |
5892 | 6851 |
}, |
6852 |
+ "node_modules/turndown": { |
|
6853 |
+ "version": "7.2.0", |
|
6854 |
+ "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz", |
|
6855 |
+ "integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==", |
|
6856 |
+ "dependencies": { |
|
6857 |
+ "@mixmark-io/domino": "^2.2.0" |
|
6858 |
+ } |
|
6859 |
+ }, |
|
6860 |
+ "node_modules/turndown-plugin-gfm": { |
|
6861 |
+ "version": "1.0.2", |
|
6862 |
+ "resolved": "https://registry.npmjs.org/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz", |
|
6863 |
+ "integrity": "sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==" |
|
6864 |
+ }, |
|
5893 | 6865 |
"node_modules/type-fest": { |
5894 | 6866 |
"version": "0.18.1", |
5895 | 6867 |
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", |
... | ... | @@ -6067,6 +7039,11 @@ |
6067 | 7039 |
"spdx-expression-parse": "^3.0.0" |
6068 | 7040 |
} |
6069 | 7041 |
}, |
7042 |
+ "node_modules/vanilla-colorful": { |
|
7043 |
+ "version": "0.7.2", |
|
7044 |
+ "resolved": "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz", |
|
7045 |
+ "integrity": "sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg==" |
|
7046 |
+ }, |
|
6070 | 7047 |
"node_modules/vary": { |
6071 | 7048 |
"version": "1.1.2", |
6072 | 7049 |
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", |
--- package.json
+++ package.json
... | ... | @@ -4,11 +4,13 @@ |
4 | 4 |
"@ant-design/icons-vue": "^7.0.1", |
5 | 5 |
"@babel/cli": "7.19.3", |
6 | 6 |
"@babel/core": "7.19.3", |
7 |
+ "@ckeditor/ckeditor5-vue": "^7.3.0", |
|
7 | 8 |
"@fullcalendar/core": "^6.1.15", |
8 | 9 |
"@fullcalendar/daygrid": "^6.1.15", |
9 | 10 |
"@fullcalendar/vue3": "^6.1.15", |
10 | 11 |
"axios": "^1.10.0", |
11 | 12 |
"babel-loader": "8.2.5", |
13 |
+ "ckeditor5": "^45.2.1", |
|
12 | 14 |
"css-loader": "6.7.1", |
13 | 15 |
"express": "4.18.1", |
14 | 16 |
"express-http-proxy": "^2.1.1", |
+++ vetur.config.js
... | ... | @@ -0,0 +1,5 @@ |
1 | +module.exports = { | |
2 | + settings: { | |
3 | + "vetur.ignoreProjectWarning": true, | |
4 | + }, | |
5 | +}; |
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?