
--- client/views/pages/data/FileManagement.vue
+++ client/views/pages/data/FileManagement.vue
... | ... | @@ -13,1650 +13,24 @@ |
13 | 13 |
<PageNavigation /> |
14 | 14 |
</div> |
15 | 15 |
<div class="content-wrap"> |
16 |
- <div class="content-box flex justify-between"> |
|
17 |
- <div class="flex20 content-box"> |
|
18 |
- <div class="left-content flex100 content-box"> |
|
19 |
- <div class="content-box"> |
|
20 |
- <div class="flex align-end justify-between no-gutter"> |
|
21 |
- <div class="mb10 flex70"> |
|
22 |
- <div class="content"> |
|
23 |
- <p class="box-title">호스트 선택</p> |
|
24 |
- </div> |
|
25 |
- <div> |
|
26 |
- <select class="only full-select" v-model="selectedHostCodeData"> |
|
27 |
- <option :value="null" disabled>선택</option> |
|
28 |
- <option v-for="(host, idx) in hostList" :key="idx" :value="idx"> |
|
29 |
- {{ host.host_nm + " - (" + host.host_ip + ")" }} |
|
30 |
- </option> |
|
31 |
- </select> |
|
32 |
- </div> |
|
33 |
- </div> |
|
34 |
- <div class="mb10 flex70" v-if="userauth !== 'ROLE_ADMIN'"> |
|
35 |
- <div class="content"> |
|
36 |
- <p class="box-title">디렉토리 선택</p> |
|
37 |
- </div> |
|
38 |
- <div> |
|
39 |
- <select class="only full-select" v-model="selectedDirectory"> |
|
40 |
- <option :value="null" disabled>선택</option> |
|
41 |
- <option v-for="(host, idx) in hostList" :key="idx" :value="idx"> |
|
42 |
- {{ host.dept_drctry_nm }} |
|
43 |
- </option> |
|
44 |
- </select> |
|
45 |
- </div> |
|
46 |
- </div> |
|
47 |
- <div class="mb10 flex25"> |
|
48 |
- <button class="blue-btn large-btn" @click="uniquePaths()"> |
|
49 |
- 연결 |
|
50 |
- </button> |
|
51 |
- </div> |
|
52 |
- </div> |
|
53 |
- <div class="file-tree-zone" :style="{ height: userauth !== 'ROLE_ADMIN' ? 'calc(100% - 156px)' : 'calc(100% - 79px)' }"> |
|
54 |
- <div class="content-titleZone flex justify-between align-center"> |
|
55 |
- <p class="box-title">폴더 리스트</p> |
|
56 |
- <button class="blue-border-btn small-btn" @click="openMkdirModal()"> |
|
57 |
- 폴더추가 |
|
58 |
- </button> |
|
59 |
- </div> |
|
60 |
- <div class="file-zone overflow-y"> |
|
61 |
- <ul class="tree-wrap"> |
|
62 |
- <TreeItem ref="treeItem" :connection="connection" :selectedNode="selectedNode" |
|
63 |
- v-for="(item, idx) in nodes" :item="item" :idx="item.id" :selectItem="selectItem" :key="idx" |
|
64 |
- @selectFolder="selectFolder" @isLoading="handleIsLoading" @selectItem="handleSelectItem" /> |
|
65 |
- |
|
66 |
- </ul> |
|
67 |
- </div> |
|
68 |
- </div> |
|
69 |
- </div> |
|
70 |
- </div> |
|
71 |
- </div> |
|
72 |
- <div class="flex80 content-box"> |
|
73 |
- <div class="right-content flex100"> |
|
74 |
- <div class="flex-column justify-between"> |
|
75 |
- <div class="flex justify-between align-center no-gutter"> |
|
76 |
- <div class="flex40"> |
|
77 |
- <button class="blue-border-btn small-btn" @click="openTreeModal('copy')"> |
|
78 |
- 선택복사 |
|
79 |
- </button> |
|
80 |
- <button class="blue-border-btn small-btn" @click="openTreeModal('move')"> |
|
81 |
- 선택이동 |
|
82 |
- </button> |
|
83 |
- <button class="red-border-btn small-btn" @click="remove()"> |
|
84 |
- 선택삭제 |
|
85 |
- </button> |
|
86 |
- </div> |
|
87 |
- <div class="flex justify-end flex60"> |
|
88 |
- <div class="search-bar"> |
|
89 |
- <div class="flex justify-end align-center"> |
|
90 |
- <select name="" id="" class="square-select" v-model="searchType"> |
|
91 |
- <option value="all">전체</option> |
|
92 |
- <option value="folder">현재폴더</option> |
|
93 |
- </select> |
|
94 |
- <div class="search-square"> |
|
95 |
- <div class="flex justify-end align-center no-gutter"> |
|
96 |
- <input type="text" class="square-input flex90" placeholder="Search File" v-model="searchText" |
|
97 |
- @keyup.enter="searchFiles()" /> |
|
98 |
- <button class="square-button blue-btn flex10"> |
|
99 |
- <svg-icon type="mdi" :path="searchPath" class="square-icon" |
|
100 |
- @click="searchFiles()"></svg-icon> |
|
101 |
- </button> |
|
102 |
- </div> |
|
103 |
- </div> |
|
104 |
- </div> |
|
105 |
- </div> |
|
106 |
- </div> |
|
107 |
- </div> |
|
108 |
- <div class="content-zone" style="overflow-y: auto"> |
|
109 |
- <div class="table-zone file-table"> |
|
110 |
- <div class="list-info flex justify-between align-center"> |
|
111 |
- <div class="count-zone"> |
|
112 |
- <p> |
|
113 |
- 총 |
|
114 |
- <span v-if="search.totalRows != 0">{{ |
|
115 |
- search.totalRows |
|
116 |
- }}</span> |
|
117 |
- <span v-else>0</span>건 중 |
|
118 |
- <span>{{ selectedFiles.length }}</span>건 선택 |
|
119 |
- </p> |
|
120 |
- <p> |
|
121 |
- 현재경로 : <span>{{ connection.path }}</span> |
|
122 |
- </p> |
|
123 |
- </div> |
|
124 |
- </div> |
|
125 |
- <table class="list-table"> |
|
126 |
- <!-- col 꼭 너비 기재해야함! 그래야 100%로 차지함 --> |
|
127 |
- <colgroup> |
|
128 |
- <col style="width: 5%" /> |
|
129 |
- <col style="width: 45%" /> |
|
130 |
- <col style="width: 10%" /> |
|
131 |
- <col style="width: 15%" /> |
|
132 |
- <col style="width: 10%" /> |
|
133 |
- <col style="width: 15%" /> |
|
134 |
- </colgroup> |
|
135 |
- <thead> |
|
136 |
- <tr> |
|
137 |
- <th> |
|
138 |
- <input type="checkbox" @click="filesCheckAll" v-model="checkAll" /> |
|
139 |
- </th> |
|
140 |
- <th>이름</th> |
|
141 |
- <th>타입</th> |
|
142 |
- <th>마지막 수정</th> |
|
143 |
- <th>크기</th> |
|
144 |
- <th>관리</th> |
|
145 |
- </tr> |
|
146 |
- </thead> |
|
147 |
- <tbody> |
|
148 |
- <tr v-for="(file, index) in fileList" :key="index" @click="selectFileList(file)"> |
|
149 |
- <td v-if="file.text != '상위폴더로 이동'" @click.stop=""> |
|
150 |
- <input type="checkbox" @click.stop="" v-model="selectedFiles" :value="{ |
|
151 |
- folder: file.folder, |
|
152 |
- path: file.path, |
|
153 |
- fileName: file.text, |
|
154 |
- extension: file.extension, |
|
155 |
- }" name="files" /> |
|
156 |
- </td> |
|
157 |
- <td v-else @click.stop=""></td> |
|
158 |
- <td> |
|
159 |
- <div class="text-lf"> |
|
160 |
- <span v-if="file.extension === 'txt'"><img src="../../../resources/img/icon/txt.png" ref="" |
|
161 |
- alt="" /></span> |
|
162 |
- <span v-else-if="file.extension === 'pdf'"><img src="../../../resources/img/icon/pdf.png" |
|
163 |
- alt="" /></span> |
|
164 |
- <span v-else-if=" |
|
165 |
- file.extension === 'pptx' || |
|
166 |
- file.extension === 'ppt' |
|
167 |
- "><img src="../../../resources/img/icon/ppt.png" alt="" /></span> |
|
168 |
- <span v-else-if="file.extension === 'hwp'"><img src="../../../resources/img/icon/hwp.png" |
|
169 |
- alt="" /></span> |
|
170 |
- <span v-else-if=" |
|
171 |
- file.extension === 'xls' || |
|
172 |
- file.extension === 'xlsx' || |
|
173 |
- file.extension === 'csv' |
|
174 |
- "><img src="../../../resources/img/icon/xls.png" alt="" /></span> |
|
175 |
- <span v-else-if="file.extension === 'jpg'"><img src="../../../resources/img/icon/img.png" |
|
176 |
- alt="" /></span> |
|
177 |
- <span v-else-if="file.extension === 'png'"><img src="../../../resources/img/icon/img.png" |
|
178 |
- ref="" alt="" /></span> |
|
179 |
- <span>{{ " " + file.text }}</span> |
|
180 |
- </div> |
|
181 |
- </td> |
|
182 |
- <td>{{ file.extension }}</td> |
|
183 |
- <td>{{ file.lastUpdate }}</td> |
|
184 |
- <td v-if="file.size != 0"> |
|
185 |
- {{ $filters.bytesToSize(file.size) }} |
|
186 |
- </td> |
|
187 |
- <td v-else></td> |
|
188 |
- <td> |
|
189 |
- <div v-if="!file.folder"> |
|
190 |
- <button class="icon-btn orange-btn" title="미리보기" @click.stop="preview(file)"> |
|
191 |
- <svg-icon type="mdi" :width="18" :height="18" :path="fileFindPath"></svg-icon> |
|
192 |
- </button> |
|
193 |
- <button class="icon-btn green-btn ml5" title="파일명 변경" @click.stop="openReNameModal(file)"> |
|
194 |
- <svg-icon type="mdi" :width="18" :height="18" :path="fileNamePath"></svg-icon> |
|
195 |
- </button> |
|
196 |
- <button class="icon-btn blue-btn ml5" title="다운로드" @click.stop="download(file)"> |
|
197 |
- <svg-icon type="mdi" :width="18" :height="18" :path="filedownPath"></svg-icon> |
|
198 |
- </button> |
|
199 |
- </div> |
|
200 |
- <div v-else-if=" |
|
201 |
- file.folder && file.text != '상위폴더로 이동' |
|
202 |
- "> |
|
203 |
- <button class="icon-btn green-btn ml5" title="폴더명 변경" @click.stop="openReNameModal(file)"> |
|
204 |
- <svg-icon type="mdi" :width="18" :height="18" :path="fileNamePath"></svg-icon> |
|
205 |
- </button> |
|
206 |
- </div> |
|
207 |
- </td> |
|
208 |
- </tr> |
|
209 |
- </tbody> |
|
210 |
- </table> |
|
211 |
- </div> |
|
212 |
- </div> |
|
213 |
- <div class="flex justify-end"> |
|
214 |
- <button class="blue-btn small-btn" @click="setModal('typeSelected', 'small')"> |
|
215 |
- 업로드 |
|
216 |
- </button> |
|
217 |
- </div> |
|
218 |
- </div> |
|
219 |
- </div> |
|
220 |
- </div> |
|
221 |
- </div> |
|
222 |
- </div> |
|
223 |
- </div> |
|
224 |
- <!-- 폴더 목록 모달 --> |
|
225 |
- <TreeModal :modalOpen="treeModalOpen" :modalConnection="modalConnection" :modalNodes="modalNodes" |
|
226 |
- :selectType="selectModalType" @modalSelectFolder="modalSelectFolder" @closeTreeModal="closeTreeModal" |
|
227 |
- @modalSubmit="fileConfirm" /> |
|
228 |
- <!-- 데이터셋 미리보기 모달 --> |
|
229 |
- <div v-show="previewModalOpen" class="modal-wrapper" :style="isLoading ? { cursor: 'wait' } : {}"> |
|
230 |
- <div v-if="isLoading" class="loading-overlay"> |
|
231 |
- <div class="loading-div"> |
|
232 |
- <span>LOADING </span> |
|
233 |
- <span class="anima">.</span> |
|
234 |
- <span class="anima">.</span> |
|
235 |
- <span class="anima">.</span> |
|
236 |
- </div> |
|
237 |
- </div> |
|
238 |
- <div class="modal-container list-modal"> |
|
239 |
- <div class="modal-title"> |
|
240 |
- <div class="flex justify-between align-center"> |
|
241 |
- <h2>데이터 미리보기</h2> |
|
242 |
- <button class="close-btn" @click="previewModalClose()">X</button> |
|
243 |
- </div> |
|
244 |
- </div> |
|
245 |
- <div class="modal-content-monthly"> |
|
246 |
- <FileDataRead v-if="previewModalOpen" v-model:isLoading="isLoading" :dataTable="dataTable" :preview="true"> |
|
247 |
- </FileDataRead> |
|
248 |
- </div> |
|
249 |
- <div class="modal-end flex justify-end"> |
|
250 |
- <button class="blue-btn small-btn" @click="previewModalClose()"> |
|
251 |
- 확인 |
|
252 |
- </button> |
|
253 |
- </div> |
|
254 |
- </div> |
|
255 |
- </div> |
|
256 |
- <!-- 폴더, 파일 이름변경 모달 --> |
|
257 |
- <div v-show="reNameModalOpen" class="modal-wrapper"> |
|
258 |
- <div class="modal-container small-modal"> |
|
259 |
- <div class="modal-title text-ct"> |
|
260 |
- <h2>폴더(파일)명 변경</h2> |
|
261 |
- </div> |
|
262 |
- <div class="modal-content-monthly"> |
|
263 |
- <div class="table-zone"> |
|
264 |
- <table class="form-table2"> |
|
265 |
- <!-- col 꼭 너비 기재해야함! 그래야 100%로 차지함 --> |
|
266 |
- <colgroup> |
|
267 |
- <col style="width: 25%" /> |
|
268 |
- <col style="width: 75%" /> |
|
269 |
- </colgroup> |
|
270 |
- <tbody> |
|
271 |
- <tr> |
|
272 |
- <th>현재 이름</th> |
|
273 |
- <td>{{ reNameObject.currentName }}</td> |
|
274 |
- </tr> |
|
275 |
- <tr> |
|
276 |
- <th>변경 이름</th> |
|
277 |
- <td> |
|
278 |
- <input type="text" class="full-input" v-model="reNameObject.changeName" @keyup.enter="rename()" /> |
|
279 |
- </td> |
|
280 |
- </tr> |
|
281 |
- </tbody> |
|
282 |
- </table> |
|
283 |
- </div> |
|
284 |
- </div> |
|
285 |
- <div class="modal-end flex justify-between" style="flex-wrap: nowrap"> |
|
286 |
- <button class="gray-btn large-btn" @click="closeReNameModal()"> |
|
287 |
- 취소 |
|
288 |
- </button> |
|
289 |
- <button class="blue-btn large-btn" @click="rename()">확인</button> |
|
290 |
- </div> |
|
291 |
- </div> |
|
292 |
- </div> |
|
293 |
- <!-- 폴더추가 모달 --> |
|
294 |
- <div v-show="mkdirModalOpen" class="modal-wrapper"> |
|
295 |
- <div class="modal-container small-modal"> |
|
296 |
- <div class="modal-title text-ct"> |
|
297 |
- <h2>폴더 추가</h2> |
|
298 |
- </div> |
|
299 |
- <div class="modal-content-monthly"> |
|
300 |
- <div class="table-zone"> |
|
301 |
- <table class="form-table2"> |
|
302 |
- <!-- col 꼭 너비 기재해야함! 그래야 100%로 차지함 --> |
|
303 |
- <colgroup> |
|
304 |
- <col style="width: 25%" /> |
|
305 |
- <col style="width: 75%" /> |
|
306 |
- </colgroup> |
|
307 |
- <tbody> |
|
308 |
- <tr> |
|
309 |
- <th>현재경로</th> |
|
310 |
- <td>{{ connection.path }}</td> |
|
311 |
- </tr> |
|
312 |
- <tr> |
|
313 |
- <th>폴더명</th> |
|
314 |
- <td> |
|
315 |
- <input type="text" class="full-input" v-model="folderName" @keyup.enter="mkdir()" /> |
|
316 |
- </td> |
|
317 |
- </tr> |
|
318 |
- </tbody> |
|
319 |
- </table> |
|
320 |
- </div> |
|
321 |
- </div> |
|
322 |
- <div class="modal-end flex justify-between" style="flex-wrap: nowrap"> |
|
323 |
- <button class="blue-btn large-btn" @click="mkdir()">확인</button> |
|
324 |
- <button class="gray-btn large-btn" @click="closeMkdirModal()"> |
|
325 |
- 취소 |
|
326 |
- </button> |
|
327 |
- </div> |
|
328 |
- </div> |
|
329 |
- </div> |
|
330 |
- <!-- 엑셀 타입 지정 --> |
|
331 |
- <div v-if="isOpenExcel" class="modal-wrapper"> |
|
332 |
- <div class="modal-container small-modal"> |
|
333 |
- <div class="modal-title text-ct"> |
|
334 |
- <div class="flex justify-between align-center"> |
|
335 |
- <h2>ExcelEncoding</h2> |
|
336 |
- <button class="close-btn" @click="closeExcel"> |
|
337 |
- <svg-icon type="mdi" :width="20" :height="20" :path="closePath"></svg-icon> |
|
338 |
- </button> |
|
339 |
- </div> |
|
340 |
- </div> |
|
341 |
- <!-- ExcelEncoding 선택--> |
|
342 |
- <div class="modal-content-monthly"> |
|
343 |
- <div class="flex justify-center align-center mb10"> |
|
344 |
- <div class="flex50 pl0"> |
|
345 |
- <button class="blue-border-btn large-btn" @click="selectEncoding('utf-8')"> |
|
346 |
- UTF-8 |
|
347 |
- </button> |
|
348 |
- </div> |
|
349 |
- <div class="flex50 pr0"> |
|
350 |
- <button class="blue-border-btn large-btn" @click="selectEncoding('euc-kr')"> |
|
351 |
- EUC-KR |
|
352 |
- </button> |
|
353 |
- </div> |
|
354 |
- </div> |
|
355 |
- </div> |
|
356 |
- </div> |
|
357 |
- </div> |
|
358 |
- <!-- 모달 --> |
|
359 |
- <div v-show="isModalOpen" class="modal-wrapper"> |
|
360 |
- <div :class="{ |
|
361 |
- 'modal-container': true, |
|
362 |
- 'small-modal': modalSize === 'small', |
|
363 |
- 'large-modal': modalSize === 'large', |
|
364 |
- }"> |
|
365 |
- <div class="modal-title text-ct" v-show="modalType === 'typeSelected'"> |
|
366 |
- <div class="flex justify-between align-center"> |
|
367 |
- <h2>업로드</h2> |
|
368 |
- <button class="close-btn" @click="closeModal"> |
|
369 |
- <svg-icon type="mdi" :width="20" :height="20" :path="closePath"></svg-icon> |
|
370 |
- </button> |
|
371 |
- </div> |
|
372 |
- </div> |
|
373 |
- <!-- 업로드 타입 선택 --> |
|
374 |
- <div class="modal-content-monthly" v-show="modalType === 'typeSelected'"> |
|
375 |
- <div class="flex justify-center align-center mb10"> |
|
376 |
- <div class="flex50 pl0"> |
|
377 |
- <button class="blue-border-btn large-btn" @click="setModal('file-modal', 'small')"> |
|
378 |
- 파일 |
|
379 |
- </button> |
|
380 |
- </div> |
|
381 |
- <div class="flex50 pr0"> |
|
382 |
- <button class="blue-border-btn large-btn" @click="setModal('db-modal', 'middle')"> |
|
383 |
- DB |
|
384 |
- </button> |
|
385 |
- </div> |
|
386 |
- </div> |
|
387 |
- <div class="flex justify-center align-center"> |
|
388 |
- <div class="flex50 pl0"> |
|
389 |
- <button class="blue-border-btn large-btn" @click="setModal('api-modal', 'middle')"> |
|
390 |
- API |
|
391 |
- </button> |
|
392 |
- </div> |
|
393 |
- <div class="flex50 pr0"> |
|
394 |
- <button class="blue-border-btn large-btn" @click="setModal('ehojo-modal', 'middle')"> |
|
395 |
- 차세대 API |
|
396 |
- </button> |
|
397 |
- </div> |
|
398 |
- </div> |
|
399 |
- </div> |
|
400 |
- <!-- 파일 (file-modal) --> |
|
401 |
- <template v-if="modalType == 'file-modal'"> |
|
402 |
- <div class="modal-title"> |
|
403 |
- <div class="flex justify-between align-center"> |
|
404 |
- <h2>파일 등록</h2> |
|
405 |
- <button class="close-btn" @click="closeModal">X</button> |
|
406 |
- </div> |
|
407 |
- </div> |
|
408 |
- <div class="modal-content-monthly"> |
|
409 |
- <div class="table-zone"> |
|
410 |
- <table class="form-table"> |
|
411 |
- <colgroup> |
|
412 |
- <col style="width: 15%" /> |
|
413 |
- <col style="width: 85%" /> |
|
414 |
- </colgroup> |
|
415 |
- <tbody> |
|
416 |
- <tr> |
|
417 |
- <th>현재경로</th> |
|
418 |
- <td>{{ connection.path }}</td> |
|
419 |
- </tr> |
|
420 |
- <tr> |
|
421 |
- <th>파일명</th> |
|
422 |
- <td> |
|
423 |
- <input type="file" name="file" id="file" ref="fileInput" @change="fileInput()" /> |
|
424 |
- </td> |
|
425 |
- </tr> |
|
426 |
- </tbody> |
|
427 |
- </table> |
|
428 |
- <div class="modal-end flex justify-between" style="flex-wrap: nowrap"> |
|
429 |
- <button class="blue-btn large-btn" @click="upload()">확인</button> |
|
430 |
- <button class="gray-btn large-btn" @click="closeModal()"> |
|
431 |
- 취소 |
|
432 |
- </button> |
|
433 |
- </div> |
|
434 |
- </div> |
|
435 |
- </div> |
|
436 |
- </template> |
|
437 |
- <!-- DB (db-modal) --> |
|
438 |
- <DatabaseConnection v-if="modalType == 'db-modal'" openPopup="true" :jobItem="selectNode" @closePopup="closeModal" |
|
439 |
- @saveNodeData="fnUpdateSetup" /> |
|
440 |
- <!-- API (api-modal) --> |
|
441 |
- <apiConnection v-if="modalType == 'api-modal'" openPopup="true" :jobItem="selectNode" @fnCloseModal="closeModal" |
|
442 |
- @fnSaveSetup="fnUpdateSetup" /> |
|
443 |
- <!-- 차세대 API (ehojo-modal) --> |
|
444 |
- <EhojoConnection v-if="modalType == 'ehojo-modal'" openPopup="true" :jobItem="selectNode" |
|
445 |
- @fnCloseModal="closeModal" @fnSaveSetup="fnUpdateSetup" /> |
|
446 |
- <div class="modal-end flex justify-end" v-show="modalType == 'test-modal'" style="flex-wrap: nowrap"> |
|
447 |
- <button class="gray-border-btn small-btn" @click="closeModal"> |
|
448 |
- 이전 |
|
449 |
- </button> |
|
450 |
- <button class="blue-border-btn small-btn" @click="closeModal"> |
|
451 |
- 확인 |
|
452 |
- </button> |
|
453 |
- <button class="darkg-border-btn small-btn" @click="closeModal"> |
|
454 |
- 닫기 |
|
455 |
- </button> |
|
456 |
- </div> |
|
16 |
+ <FileManagementMain /> |
|
457 | 17 |
</div> |
458 | 18 |
</div> |
459 | 19 |
</template> |
460 | 20 |
<script> |
461 |
-import axios from "axios"; |
|
462 | 21 |
import PageNavigation from "../../component/PageNavigation.vue"; |
463 |
-import PaginationButton from "../../component/PaginationButton.vue"; |
|
464 |
-import TreeItem from "../../component/FileTree.vue"; |
|
465 |
-import TreeModal from "../../component/FileTreeModal.vue"; |
|
466 |
-import SvgIcon from "@jamescoyle/vue-icon"; |
|
467 |
-import DatabaseConnection from "../../component/connection/itm/databaseConnection.vue"; |
|
468 |
-import apiConnection from "../../component/connection/itm/apiConnection.vue"; |
|
469 |
-import EhojoConnection from "../../component/connection/EhojoConnection.vue"; |
|
470 |
-import { |
|
471 |
- mdiMagnify, |
|
472 |
- mdiClose, |
|
473 |
- mdiFileCog, |
|
474 |
- mdiDownload, |
|
475 |
- mdiFileFind, |
|
476 |
- mdiClockPlusOutline, |
|
477 |
-} from "@mdi/js"; |
|
478 |
-import store from "../AppStore"; |
|
479 |
-import FileDataRead from "../../component/connection/itm/fileDataRead.vue"; |
|
480 |
-import * as XLSX from "xlsx"; |
|
22 |
+import FileManagementMain from "../../pages/data/filemanger/FileManagementMain.vue"; |
|
481 | 23 |
|
482 | 24 |
export default { |
483 | 25 |
data() { |
484 | 26 |
return { |
485 |
- //엑셀 등록시 타입지정 |
|
486 |
- isOpenExcel: false, |
|
487 |
- encodingType: null, |
|
488 |
- // 검색 객체 |
|
489 |
- search: this.$getDefaultSerchVO(), |
|
490 |
- search_data: this.$getDefaultSerchItem(null, "String"), |
|
491 |
- |
|
492 |
- userauth: null, |
|
493 |
- searchPath: mdiMagnify, |
|
494 |
- closePath: mdiClose, |
|
495 |
- fileNamePath: mdiFileCog, |
|
496 |
- filedownPath: mdiDownload, |
|
497 |
- fileFindPath: mdiFileFind, |
|
498 |
- isModalOpen: false, |
|
499 |
- activeTab: "tab1", |
|
500 |
- modalType: "", |
|
501 |
- modalSize: "small", |
|
502 |
- mkdirModalOpen: false, |
|
503 |
- reNameModalOpen: false, |
|
504 |
- treeModalOpen: false, |
|
505 |
- |
|
506 |
- selectedHost: {}, |
|
507 |
- selectedHostCode: null, |
|
508 |
- // 호스트 목록 |
|
509 |
- hostList: [], |
|
510 |
- // 부서-호스트 목록 |
|
511 |
- //01.17 deptHostList: [], |
|
512 |
- connection: { |
|
513 |
- host_code: null, |
|
514 |
- path: null, |
|
515 |
- depth: null, |
|
516 |
- type: null, |
|
517 |
- }, |
|
518 |
- |
|
519 |
- selectedTab: '', // 현재 선택된 탭 |
|
520 |
- |
|
521 |
- uploadObject: { |
|
522 |
- host_code: null, |
|
523 |
- path: null, |
|
524 |
- uploadFile: null, |
|
525 |
- confirm: false, |
|
526 |
- }, |
|
527 |
- nodes: [], |
|
528 |
- fileList: [], |
|
529 |
- selectedNode: null, |
|
530 |
- folderName: null, |
|
531 |
- uploadFile: null, |
|
532 |
- |
|
533 |
- reNameObject: { |
|
534 |
- currentPath: null, |
|
535 |
- parentPath: null, |
|
536 |
- currentName: null, |
|
537 |
- extension: null, |
|
538 |
- changeName: null, |
|
539 |
- }, |
|
540 |
- checkAll: false, |
|
541 |
- selectedFiles: [], |
|
542 |
- modalNodes: [], |
|
543 |
- modalConnection: { |
|
544 |
- host_code: null, |
|
545 |
- path: null, |
|
546 |
- depth: null, |
|
547 |
- type: null, |
|
548 |
- }, |
|
549 |
- modalSeletedNode: null, |
|
550 |
- selectModalType: 0, |
|
551 |
- |
|
552 |
- searchType: "all", |
|
553 |
- searchText: null, |
|
554 |
- |
|
555 |
- selectItem: { |
|
556 |
- id: null, |
|
557 |
- }, |
|
558 |
- |
|
559 |
- // 데이터 미리보기 |
|
560 |
- isLoading: false, |
|
561 |
- previewModalOpen: false, |
|
562 |
- dataTable: {}, |
|
563 |
- |
|
564 |
- selectNode: {}, // 선택된 노드 |
|
565 |
- |
|
566 |
- selectedHostCodeData: null, |
|
567 |
- selectedDirectory: null, |
|
568 |
- selectedHostData: null, |
|
569 |
- isUpdating: false // 무한 루프 방지를 위한 플래그 |
|
570 | 27 |
}; |
571 | 28 |
}, |
572 | 29 |
methods: { |
573 |
- // 검색 객체 초기화 |
|
574 |
- searchInit: function () { |
|
575 |
- this.search.searchObjectList.push(this.search_data); |
|
576 |
- }, |
|
577 |
- |
|
578 |
- searchFiles() { |
|
579 |
- const vm = this; |
|
580 |
- |
|
581 |
- if (vm.searchText === null || vm.searchText === "") { |
|
582 |
- vm.$showAlert("파일 검색", "검색어를 입력해 주세요."); |
|
583 |
- return; |
|
584 |
- } |
|
585 |
- |
|
586 |
- let path = vm.connection.path; |
|
587 |
- |
|
588 |
- if (vm.searchType === "all") { |
|
589 |
- path = "#"; |
|
590 |
- } else { |
|
591 |
- if (!path) { |
|
592 |
- vm.$showAlert("파일 검색", "폴더를 선택해 주세요."); |
|
593 |
- return; |
|
594 |
- } |
|
595 |
- } |
|
596 |
- |
|
597 |
- vm.isLoading = true; // 로딩 시작 |
|
598 |
- |
|
599 |
- axios({ |
|
600 |
- url: "/files/search/" + vm.connection.host_code, |
|
601 |
- method: "post", |
|
602 |
- headers: {}, |
|
603 |
- data: { |
|
604 |
- searchType: vm.searchType, |
|
605 |
- searchText: vm.searchText, |
|
606 |
- path: path, |
|
607 |
- }, |
|
608 |
- }) |
|
609 |
- .then(function (response) { |
|
610 |
- vm.isLoading = false; // 로딩 해제 |
|
611 |
- vm.fileList = response.data.resultData.fileList; |
|
612 |
- if (vm.fileList.length == 0) { |
|
613 |
- vm.$showAlert("파일 검색", "검색 결과가 없습니다."); |
|
614 |
- } |
|
615 |
- }) |
|
616 |
- .catch(function (error) { |
|
617 |
- vm.isLoading = false; // 로딩 해제 |
|
618 |
- vm.$showAlert( |
|
619 |
- "파일 검색", |
|
620 |
- "파일 검색 오류, 관리자에게 문의바랍니다." |
|
621 |
- ); |
|
622 |
- }); |
|
623 |
- }, |
|
624 |
- |
|
625 |
- // 로딩 상태 변경 |
|
626 |
- handleIsLoading(isLoadingValue) { |
|
627 |
- this.isLoading = isLoadingValue; // 부모 컴포넌트의 데이터 업데이트 |
|
628 |
- }, |
|
629 |
- |
|
630 |
- // 탭 변경 |
|
631 |
- showTab: function (tabName) { |
|
632 |
- this.activeTab = tabName; |
|
633 |
- }, |
|
634 |
- openModal: function () { |
|
635 |
- this.isModalOpen = true; |
|
636 |
- }, |
|
637 |
- closeModal: function () { |
|
638 |
- // this.selectNode = {}; // 초기화 |
|
639 |
- this.modalType = null; |
|
640 |
- this.isModalOpen = false; |
|
641 |
- }, |
|
642 |
- setModal: function (type, size) { |
|
643 |
- if (type == "typeSelected") { |
|
644 |
- if ( |
|
645 |
- this.connection.path == null || |
|
646 |
- this.connection.path == "" || |
|
647 |
- this.connection.path === undefined |
|
648 |
- ) { |
|
649 |
- this.$showAlert("폴더 추가", "폴더를 선택해 주세요."); |
|
650 |
- return; |
|
651 |
- } |
|
652 |
- } else if (type == "db-modal") { |
|
653 |
- this.fnCreateNode("DB_READ"); |
|
654 |
- } else if (type == "api-modal") { |
|
655 |
- this.fnCreateNode("API_READ"); |
|
656 |
- } else if (type == "ehojo-modal") { |
|
657 |
- this.fnCreateNode("EHOJO_READ"); |
|
658 |
- } |
|
659 |
- this.modalType = type; |
|
660 |
- this.modalSize = size; |
|
661 |
- }, |
|
662 |
- |
|
663 |
- openMkdirModal() { |
|
664 |
- if ( |
|
665 |
- this.connection.path == null || |
|
666 |
- this.connection.path == "" || |
|
667 |
- this.connection.path === undefined |
|
668 |
- ) { |
|
669 |
- this.$showAlert("폴더 추가", "폴더를 선택해 주세요."); |
|
670 |
- return; |
|
671 |
- } |
|
672 |
- this.mkdirModalOpen = true; |
|
673 |
- }, |
|
674 |
- |
|
675 |
- closeMkdirModal() { |
|
676 |
- this.mkdirModalOpen = false; |
|
677 |
- }, |
|
678 |
- |
|
679 |
- openTreeModal(type) { |
|
680 |
- if (this.selectedFiles.length === 0) { |
|
681 |
- if (type === "move") { |
|
682 |
- this.$showAlert("파일 이동", "선택한 파일이 없습니다."); |
|
683 |
- } else if (type === "copy") { |
|
684 |
- this.$showAlert("파일 복사", "선택한 파일이 없습니다."); |
|
685 |
- } |
|
686 |
- return; |
|
687 |
- } |
|
688 |
- |
|
689 |
- this.treeModalOpen = true; |
|
690 |
- this.selectModalType = type; |
|
691 |
- }, |
|
692 |
- |
|
693 |
- closeTreeModal() { |
|
694 |
- // this.modalNodes = []; |
|
695 |
- this.treeModalOpen = false; |
|
696 |
- this.modalSeletedNode = null; |
|
697 |
- }, |
|
698 |
- |
|
699 |
- openReNameModal(file) { |
|
700 |
- this.reNameObject.currentPath = file.path; |
|
701 |
- this.reNameObject.parentPath = file.parent; |
|
702 |
- this.reNameObject.currentName = file.text; |
|
703 |
- this.reNameObject.extension = file.extension; |
|
704 |
- this.reNameModalOpen = true; |
|
705 |
- }, |
|
706 |
- |
|
707 |
- closeReNameModal() { |
|
708 |
- this.reNameObject.changeName = null; |
|
709 |
- this.reNameModalOpen = false; |
|
710 |
- }, |
|
711 |
- |
|
712 |
- filesCheckAll() { |
|
713 |
- this.checkAll = !this.checkAll; |
|
714 |
- |
|
715 |
- if (this.checkAll) { |
|
716 |
- this.fileList.forEach((file) => { |
|
717 |
- if (file.text != "상위폴더로 이동") { |
|
718 |
- this.selectedFiles.push({ |
|
719 |
- folder: file.folder, |
|
720 |
- path: file.path, |
|
721 |
- fileName: file.text, |
|
722 |
- extension: file.extension, |
|
723 |
- }); |
|
724 |
- } |
|
725 |
- }); |
|
726 |
- } else { |
|
727 |
- this.selectedFiles = []; |
|
728 |
- } |
|
729 |
- }, |
|
730 |
- |
|
731 |
- // 선택한 호스트 연결 |
|
732 |
- async connectionConfirm() { |
|
733 |
- const vm = this; |
|
734 |
- if (vm.selectedHostCode === null || vm.selectedHostCode === undefined) { |
|
735 |
- vm.$showAlert("파일시스템 연결", "호스트를 선택해 주세요."); |
|
736 |
- return; |
|
737 |
- } |
|
738 |
- |
|
739 |
- // 이전에 선택한 호스트 코드가 있으면 저장 |
|
740 |
- let tempHostCode = null; |
|
741 |
- let tempModalHostCode = null; |
|
742 |
- if (vm.connection.host_code) { |
|
743 |
- tempHostCode = _.cloneDeep(vm.connection.host_code); |
|
744 |
- tempModalHostCode = _.cloneDeep(vm.modalConnection.host_code); |
|
745 |
- } |
|
746 |
- |
|
747 |
- vm.connection.host_code = vm.selectedHost.host_code; |
|
748 |
- vm.modalConnection.host_code = vm.selectedHost.host_code; |
|
749 |
- |
|
750 |
- vm.isLoading = true; // 로딩 시작 |
|
751 |
- |
|
752 |
- try { |
|
753 |
- const response = await axios.get("/files/connection", { |
|
754 |
- params: { host_code: vm.connection.host_code }, |
|
755 |
- }); |
|
756 |
- |
|
757 |
- vm.isLoading = false; // 로딩 해제 |
|
758 |
- if (response.data.status === 200) { |
|
759 |
- await this.fileTreeList(); |
|
760 |
- } else { |
|
761 |
- // 이전에 선택한 호스트 코드로 변경 |
|
762 |
- if (tempHostCode) { |
|
763 |
- vm.connection.host_code = tempHostCode; |
|
764 |
- vm.selectedHost.host_code = tempHostCode; |
|
765 |
- vm.selectedHostCode = tempHostCode; |
|
766 |
- } |
|
767 |
- } |
|
768 |
- this.selectedFiles = []; |
|
769 |
- this.checkAll = false; |
|
770 |
- vm.$showAlert("파일시스템 연결", response.data.message); |
|
771 |
- } catch (error) { |
|
772 |
- vm.isLoading = false; // 로딩 해제 |
|
773 |
- vm.$showAlert( |
|
774 |
- "파일시스템 연결", |
|
775 |
- "파일시스템 연결 오류, 관리자에게 문의하세요." |
|
776 |
- ); |
|
777 |
- this.selectedFiles = []; |
|
778 |
- this.checkAll = false; |
|
779 |
- // 이전에 선택한 호스트 코드로 변경 |
|
780 |
- if (tempHostCode) { |
|
781 |
- vm.connection.host_code = tempHostCode; |
|
782 |
- vm.selectedHost.host_code = tempHostCode; |
|
783 |
- vm.selectedHostCode = tempHostCode; |
|
784 |
- } |
|
785 |
- } |
|
786 |
- }, |
|
787 |
- uniquePaths() { |
|
788 |
- // this.selectedHost = null; |
|
789 |
- this.selectedHost = this.selectedHostData; |
|
790 |
- this.selectedHostCode = this.selectedHostData.host_code; |
|
791 |
- this.connectionConfirm(); |
|
792 |
- }, |
|
793 |
- // 호스트 목록 조회 |
|
794 |
- selectHosts() { |
|
795 |
- const vm = this; |
|
796 |
- vm.isLoading = true; // 로딩 시작 |
|
797 |
- axios({ |
|
798 |
- url: "/files/hosts", |
|
799 |
- method: "post", |
|
800 |
- headers: { |
|
801 |
- "Content-Type": "application/json; charset=UTF-8", |
|
802 |
- }, |
|
803 |
- data: { |
|
804 |
- userId: store.state.loginUser.user_id, |
|
805 |
- //01.17 authList: store.state.loginUser.user_auth, |
|
806 |
- author: store.state.loginUser.user_auth[0], |
|
807 |
- dept_code: store.state.loginUser.dept_code, |
|
808 |
- }, |
|
809 |
- }) |
|
810 |
- .then((response) => { |
|
811 |
- vm.hostList = response.data.resultData.hostList; |
|
812 |
- console.log("@@", vm.hostList); |
|
813 |
- //01.17 vm.deptHostList = response.data.resultData.deptHostList; |
|
814 |
- // this.connection.host_code = this.hostList[this.hostList.length - 1].host_code |
|
815 |
- if (this.hostList.length > 0) { |
|
816 |
- vm.selectedHost = vm.hostList[0]; |
|
817 |
- vm.selectedHostCode = vm.hostList[0].host_code; |
|
818 |
- vm.selectedHostCodeData = 0; |
|
819 |
- vm.selectedDirectory = 0; |
|
820 |
- vm.selectedHostData = vm.hostList[0]; |
|
821 |
- // 01.17for (let i = 0; i < vm.hostList.length; i++) { |
|
822 |
- // for (let j = 0; j < vm.deptHostList.length; j++) { |
|
823 |
- // if (vm.hostList[i].host_code === vm.deptHostList[j].host_code) { |
|
824 |
- // vm.hostList[i].main_folder_path = |
|
825 |
- // vm.deptHostList[j].main_folder_path; |
|
826 |
- // } |
|
827 |
- // } |
|
828 |
- // } |
|
829 |
- vm.connectionConfirm(); |
|
830 |
- } else { |
|
831 |
- vm.isLoading = false; // 로딩 해제 |
|
832 |
- vm.selectedHost = {}; |
|
833 |
- } |
|
834 |
- }) |
|
835 |
- .catch((error) => { |
|
836 |
- vm.isLoading = false; // 로딩 해제 |
|
837 |
- vm.$showAlert( |
|
838 |
- "호스트 조회", |
|
839 |
- "호스트 조회 오류, 관리자에게 문의하세요." |
|
840 |
- ); |
|
841 |
- }); |
|
842 |
- }, |
|
843 |
- |
|
844 |
- // 폴더 리스트 조회 |
|
845 |
- async fileTreeList() { |
|
846 |
- const vm = this; |
|
847 |
- vm.nodes = []; |
|
848 |
- vm.connection.path = vm.selectedHost.dept_drctry_path; |
|
849 |
- vm.connection.depth = 0; |
|
850 |
- vm.connection.type = "folder"; |
|
851 |
- vm.modalNodes = []; |
|
852 |
- vm.modalConnection.path = vm.selectedHost.dept_drctry_path; |
|
853 |
- vm.modalConnection.depth = 0; |
|
854 |
- vm.modalConnection.type = "folder"; |
|
855 |
- vm.modalConnection.host_code = vm.connection.host_code; |
|
856 |
- |
|
857 |
- vm.isLoading = true; // 로딩 시작 |
|
858 |
- |
|
859 |
- try { |
|
860 |
- const response = await axios.get("/files/tree", { |
|
861 |
- params: vm.connection, |
|
862 |
- }); |
|
863 |
- |
|
864 |
- vm.nodes = response.data.resultData.fileTree; |
|
865 |
- vm.modalNodes = response.data.resultData.fileTree; |
|
866 |
- vm.connection.path = null; |
|
867 |
- vm.fileList = []; |
|
868 |
- this.checkAll = false; |
|
869 |
- vm.isLoading = false; // 로딩 해제 |
|
870 |
- } catch (error) { |
|
871 |
- vm.connection.path = null; |
|
872 |
- vm.fileList = []; |
|
873 |
- this.checkAll = false; |
|
874 |
- vm.isLoading = false; // 로딩 해제 |
|
875 |
- vm.$showAlert( |
|
876 |
- "파일리스트 조회", |
|
877 |
- "파일리스트 조회 오류, 관리자에게 문의하세요." |
|
878 |
- ); |
|
879 |
- } |
|
880 |
- }, |
|
881 |
- |
|
882 |
- modalFileTreeList() { |
|
883 |
- const vm = this; |
|
884 |
- |
|
885 |
- vm.modalNodes = []; |
|
886 |
- |
|
887 |
- vm.modalConnection.host_code = vm.connection.host_code; |
|
888 |
- vm.modalConnection.path = "#"; |
|
889 |
- vm.modalConnection.depth = 0; |
|
890 |
- vm.modalConnection.type = "folder"; |
|
891 |
- |
|
892 |
- axios |
|
893 |
- .get("/files/tree", { params: vm.modalConnection }) |
|
894 |
- .then((response) => { |
|
895 |
- vm.modalNodes = response.data.resultData.fileTree; |
|
896 |
- }) |
|
897 |
- .catch((error) => { |
|
898 |
- vm.$showAlert( |
|
899 |
- "파일리스트 조회", |
|
900 |
- "파일리스트 조회 오류, 관리자에게 문의하세요." |
|
901 |
- ); |
|
902 |
- }); |
|
903 |
- }, |
|
904 |
- |
|
905 |
- selectFolder(path) { |
|
906 |
- if (path === null || path === undefined) { |
|
907 |
- this.isLoading = false; |
|
908 |
- } |
|
909 |
- this.connection.path = path; |
|
910 |
- this.fileSelectList(); |
|
911 |
- }, |
|
912 |
- |
|
913 |
- handleSelectItem(item) { |
|
914 |
- this.selectItem = item; |
|
915 |
- }, |
|
916 |
- |
|
917 |
- modalSelectFolder(path) { |
|
918 |
- this.modalSeletedNode = path; |
|
919 |
- }, |
|
920 |
- |
|
921 |
- selectFileList(item) { |
|
922 |
- // 폴더가 선택된 경우, 선택된 노드와 경로를 업데이트하고 파일 리스트 조회 |
|
923 |
- if (item.extension === "폴더" || item.extension === "") { |
|
924 |
- this.selectedNode = item.id; |
|
925 |
- this.connection.path = item.id; |
|
926 |
- this.fileSelectList(); |
|
927 |
- } else { |
|
928 |
- } |
|
929 |
- }, |
|
930 |
- |
|
931 |
- // 파일 리스트 조회 |
|
932 |
- async fileSelectList() { |
|
933 |
- const vm = this; |
|
934 |
- |
|
935 |
- if (vm.connection.path === null || vm.connection.path === "") { |
|
936 |
- vm.fileList = null; |
|
937 |
- return; |
|
938 |
- } |
|
939 |
- |
|
940 |
- vm.connection.type = "all"; |
|
941 |
- vm.connection.depth = 1; |
|
942 |
- |
|
943 |
- vm.isLoading = true; // 로딩 시작 |
|
944 |
- try { |
|
945 |
- const response = await axios.get("/files/list", { |
|
946 |
- params: vm.connection, |
|
947 |
- }); |
|
948 |
- vm.fileList = response.data.resultData.fileList; |
|
949 |
- vm.search.totalRows = response.data.resultData.totalRow; |
|
950 |
- vm.selectedFiles = []; |
|
951 |
- vm.checkAll = false; |
|
952 |
- vm.isLoading = false; // 로딩 해제 |
|
953 |
- } catch (error) { |
|
954 |
- vm.isLoading = false; // 로딩 해제 |
|
955 |
- vm.$showAlert( |
|
956 |
- "파일리스트 조회", |
|
957 |
- "파일리스트 조회 오류, 관리자에게 문의하세요." |
|
958 |
- ); |
|
959 |
- vm.selectedFiles = []; |
|
960 |
- vm.checkAll = false; |
|
961 |
- } |
|
962 |
- }, |
|
963 |
- |
|
964 |
- // 폴더 추가 |
|
965 |
- async mkdir() { |
|
966 |
- const vm = this; |
|
967 |
- if (vm.connection.path === null || vm.connection.path === "") { |
|
968 |
- vm.$showAlert( |
|
969 |
- "폴더 추가", |
|
970 |
- "선택된 경로가 없습니다.\n 경로 선택 후 다시 시도해주세요." |
|
971 |
- ); |
|
972 |
- vm.closeMkdirModal(); |
|
973 |
- vm.folderName = null; |
|
974 |
- return; |
|
975 |
- } |
|
976 |
- |
|
977 |
- const mkdirVO = {}; |
|
978 |
- mkdirVO.host_code = vm.connection.host_code; |
|
979 |
- mkdirVO.path = vm.connection.path; |
|
980 |
- mkdirVO.folderName = vm.folderName; |
|
981 |
- |
|
982 |
- vm.isLoading = true; // 로딩 시작 |
|
983 |
- |
|
984 |
- try { |
|
985 |
- const response = await axios.post("/files/mkdir", mkdirVO); |
|
986 |
- |
|
987 |
- vm.isLoading = false; // 로딩 해제 |
|
988 |
- vm.getChildren(vm.selectItem.id, vm.selectItem.children); // 자식 폴더 리스트 업데이트 |
|
989 |
- await vm.fileSelectList(); |
|
990 |
- vm.$showAlert("폴더 추가", response.data.message); |
|
991 |
- vm.closeMkdirModal(); |
|
992 |
- vm.folderName = null; |
|
993 |
- } catch (error) { |
|
994 |
- vm.isLoading = false; // 로딩 해제 |
|
995 |
- vm.$showAlert("폴더 추가", "폴더 추가 오류, 관리자에게 문의하세요."); |
|
996 |
- vm.folderName = null; |
|
997 |
- } |
|
998 |
- }, |
|
999 |
- |
|
1000 |
- // 자식 파일 정보 조회 |
|
1001 |
- getChildren(path, children) { |
|
1002 |
- const vm = this; |
|
1003 |
- vm.connection.path = path; |
|
1004 |
- vm.connection.type = "folder"; |
|
1005 |
- vm.connection.depth = 1; |
|
1006 |
- |
|
1007 |
- axios |
|
1008 |
- .get("/files/list", { params: vm.connection }) |
|
1009 |
- .then((response) => { |
|
1010 |
- let childrenList = response.data.resultData.fileList; |
|
1011 |
- |
|
1012 |
- // 기존 배열 초기화 |
|
1013 |
- children.length = 0; |
|
1014 |
- |
|
1015 |
- // 새로운 배열의 요소들을 기존 배열에 추가 |
|
1016 |
- Array.prototype.push.apply(children, childrenList); |
|
1017 |
- }) |
|
1018 |
- .catch((error) => { }); |
|
1019 |
- }, |
|
1020 |
- |
|
1021 |
- //파일업로드 |
|
1022 |
- fileInput() { |
|
1023 |
- this.uploadFile = this.$refs.fileInput.files[0]; |
|
1024 |
- }, |
|
1025 |
- |
|
1026 |
- async upload() { |
|
1027 |
- const vm = this; |
|
1028 |
- vm.uploadObject.path = vm.connection.path; |
|
1029 |
- vm.uploadObject.host_code = vm.connection.host_code; |
|
1030 |
- vm.uploadObject.uploadFile = vm.uploadFile; |
|
1031 |
- vm.isLoading = true; |
|
1032 |
- |
|
1033 |
- // 파일 타입 및 인코딩 확인 |
|
1034 |
- if (vm.uploadFile) { |
|
1035 |
- const fileName = vm.uploadFile.name.toLowerCase(); |
|
1036 |
- const isExcel = fileName.endsWith(".xlsx") || fileName.endsWith(".xls"); |
|
1037 |
- const isCsv = fileName.endsWith(".csv"); |
|
1038 |
- |
|
1039 |
- if (isExcel || isCsv) { |
|
1040 |
- try { |
|
1041 |
- const fileReader = new FileReader(); |
|
1042 |
- |
|
1043 |
- fileReader.onload = function (e) { |
|
1044 |
- const content = new Uint8Array(e.target.result); |
|
1045 |
- let encoding = "Unknown"; |
|
1046 |
- |
|
1047 |
- // BOM 확인으로 UTF-8 검사 |
|
1048 |
- if ( |
|
1049 |
- content.length >= 3 && |
|
1050 |
- content[0] === 0xef && |
|
1051 |
- content[1] === 0xbb && |
|
1052 |
- content[2] === 0xbf |
|
1053 |
- ) { |
|
1054 |
- encoding = "UTF-8 with BOM"; |
|
1055 |
- } else if ( |
|
1056 |
- content.length >= 2 && |
|
1057 |
- content[0] === 0xff && |
|
1058 |
- content[1] === 0xfe |
|
1059 |
- ) { |
|
1060 |
- encoding = "UTF-16 LE"; |
|
1061 |
- } else { |
|
1062 |
- // 텍스트 분석으로 인코딩 추정 |
|
1063 |
- try { |
|
1064 |
- const text = new TextDecoder("UTF-8").decode(content); |
|
1065 |
- const hasInvalidChars = text.includes("�"); |
|
1066 |
- encoding = hasInvalidChars ? "Possibly EUC-KR" : "UTF-8"; |
|
1067 |
- } catch (err) { |
|
1068 |
- encoding = "Possibly EUC-KR"; |
|
1069 |
- } |
|
1070 |
- } |
|
1071 |
- |
|
1072 |
- console.log(`파일 타입: ${isExcel ? "Excel" : "CSV"}`); |
|
1073 |
- console.log(`인코딩 타입: ${encoding}`); |
|
1074 |
- }; |
|
1075 |
- |
|
1076 |
- // 파일의 처음 1KB만 읽어서 분석 |
|
1077 |
- fileReader.readAsArrayBuffer(vm.uploadFile.slice(0, 1024)); |
|
1078 |
- } catch (error) { |
|
1079 |
- console.error("인코딩 확인 중 오류:", error); |
|
1080 |
- } |
|
1081 |
- } |
|
1082 |
- } |
|
1083 |
- |
|
1084 |
- try { |
|
1085 |
- const response = await axios.post("/files/upload", vm.uploadObject, { |
|
1086 |
- headers: { |
|
1087 |
- "Content-Type": "multipart/form-data", |
|
1088 |
- }, |
|
1089 |
- }); |
|
1090 |
- |
|
1091 |
- vm.isLoading = false; |
|
1092 |
- |
|
1093 |
- if (response.data.status === 200) { |
|
1094 |
- document.getElementById("file").value = ""; |
|
1095 |
- await vm.fileSelectList(); |
|
1096 |
- vm.$showAlert("파일 업로드", response.data.message); |
|
1097 |
- } else if (response.data.status === 100) { |
|
1098 |
- if (!(await vm.$showConfirm("파일 업로드", response.data.message))) { |
|
1099 |
- document.getElementById("file").value = ""; |
|
1100 |
- return; |
|
1101 |
- } else { |
|
1102 |
- vm.uploadObject.confirm = true; |
|
1103 |
- await vm.reUpload(); |
|
1104 |
- } |
|
1105 |
- } |
|
1106 |
- |
|
1107 |
- vm.closeModal(); |
|
1108 |
- } catch (error) { |
|
1109 |
- vm.isLoading = false; |
|
1110 |
- vm.$showAlert( |
|
1111 |
- "파일 업로드", |
|
1112 |
- "파일 업로드 오류, 관리자에게 문의하세요." |
|
1113 |
- ); |
|
1114 |
- vm.uploadObject.confirm = false; |
|
1115 |
- document.getElementById("file").value = ""; |
|
1116 |
- } |
|
1117 |
- }, |
|
1118 |
- |
|
1119 |
- async reUpload() { |
|
1120 |
- const vm = this; |
|
1121 |
- vm.isLoading = true; // 로딩 시작 |
|
1122 |
- |
|
1123 |
- try { |
|
1124 |
- const response = await axios.post("/files/upload", vm.uploadObject, { |
|
1125 |
- headers: { |
|
1126 |
- "Content-Type": "multipart/form-data", |
|
1127 |
- }, |
|
1128 |
- }); |
|
1129 |
- |
|
1130 |
- vm.isLoading = false; // 로딩 종료 |
|
1131 |
- await vm.fileSelectList(); |
|
1132 |
- vm.$showAlert("파일 업로드", response.data.message); |
|
1133 |
- vm.uploadObject.confirm = false; |
|
1134 |
- document.getElementById("file").value = ""; |
|
1135 |
- } catch (error) { |
|
1136 |
- vm.isLoading = false; // 로딩 종료 |
|
1137 |
- vm.$showAlert( |
|
1138 |
- "파일 업로드", |
|
1139 |
- "파일 업로드 오류, 관리자에게 문의하세요." |
|
1140 |
- ); |
|
1141 |
- vm.uploadObject.confirm = false; |
|
1142 |
- document.getElementById("file").value = ""; |
|
1143 |
- } |
|
1144 |
- }, |
|
1145 |
- |
|
1146 |
- download(file) { |
|
1147 |
- const vm = this; |
|
1148 |
- |
|
1149 |
- vm.isLoading = true; // 로딩 시작 |
|
1150 |
- |
|
1151 |
- axios |
|
1152 |
- .post("/files/download", { |
|
1153 |
- host_code: vm.connection.host_code, |
|
1154 |
- path: file.parent, |
|
1155 |
- fileName: file.text, |
|
1156 |
- }) |
|
1157 |
- .then((response) => { |
|
1158 |
- vm.isLoading = false; // 로딩 해제 |
|
1159 |
- vm.$showAlert("파일 다운로드", response.data.message); |
|
1160 |
- }) |
|
1161 |
- .catch((error) => { |
|
1162 |
- vm.isLoading = false; // 로딩 해제 |
|
1163 |
- vm.$showAlert( |
|
1164 |
- "파일 다운로드", |
|
1165 |
- "파일 다운로드 오류, 관리자에게 문의하세요." |
|
1166 |
- ); |
|
1167 |
- }); |
|
1168 |
- }, |
|
1169 |
- |
|
1170 |
- async rename() { |
|
1171 |
- const vm = this; |
|
1172 |
- |
|
1173 |
- if (vm.reNameObject.changeName === null) { |
|
1174 |
- vm.$showAlert("이름 바꾸기", "변경할 이름을 입력해주세요."); |
|
1175 |
- return; |
|
1176 |
- } |
|
1177 |
- |
|
1178 |
- let fullName = |
|
1179 |
- vm.reNameObject.changeName + "." + vm.reNameObject.extension; |
|
1180 |
- |
|
1181 |
- if (vm.reNameObject.extension === "폴더") { |
|
1182 |
- fullName = vm.reNameObject.changeName; |
|
1183 |
- } |
|
1184 |
- |
|
1185 |
- vm.isLoading = true; // 로딩 시작 |
|
1186 |
- |
|
1187 |
- try { |
|
1188 |
- const response = await axios.put("/files/rename", { |
|
1189 |
- host_code: vm.connection.host_code, |
|
1190 |
- currentPath: vm.reNameObject.currentPath, |
|
1191 |
- changePath: vm.reNameObject.parentPath + "/" + fullName, |
|
1192 |
- }); |
|
1193 |
- |
|
1194 |
- vm.isLoading = false; // 로딩 해제 |
|
1195 |
- vm.reNameObject.changeName = null; |
|
1196 |
- await vm.fileSelectList(); |
|
1197 |
- vm.$showAlert("이름 바꾸기", response.data.message); |
|
1198 |
- vm.closeReNameModal(); |
|
1199 |
- } catch (error) { |
|
1200 |
- vm.isLoading = false; // 로딩 해제 |
|
1201 |
- vm.$showAlert( |
|
1202 |
- "이름 바꾸기", |
|
1203 |
- "이름 바꾸기 오류, 관리자에게 문의하세요." |
|
1204 |
- ); |
|
1205 |
- vm.closeReNameModal(); |
|
1206 |
- vm.reNameObject.changeName = null; |
|
1207 |
- } |
|
1208 |
- }, |
|
1209 |
- |
|
1210 |
- async remove() { |
|
1211 |
- const vm = this; |
|
1212 |
- |
|
1213 |
- if (vm.selectedFiles.length === 0) { |
|
1214 |
- vm.$showAlert("파일 삭제", "선택한 파일이 없습니다."); |
|
1215 |
- return; |
|
1216 |
- } |
|
1217 |
- |
|
1218 |
- if ( |
|
1219 |
- !(await vm.$showConfirm("파일 삭제", "선택한 파일을 삭제하시겠습니까?")) |
|
1220 |
- ) { |
|
1221 |
- return; |
|
1222 |
- } |
|
1223 |
- |
|
1224 |
- vm.selectedFiles.forEach((file) => { |
|
1225 |
- delete file.fileName; |
|
1226 |
- delete file.extension; |
|
1227 |
- }); |
|
1228 |
- vm.isLoading = true; // 로딩 시작 |
|
1229 |
- try { |
|
1230 |
- const response = await axios.delete( |
|
1231 |
- `/files/${vm.connection.host_code}`, |
|
1232 |
- { data: vm.selectedFiles } |
|
1233 |
- ); |
|
1234 |
- |
|
1235 |
- vm.isLoading = false; |
|
1236 |
- vm.getChildren(vm.selectItem.id, vm.selectItem.children); // 자식 폴더 리스트 업데이트 |
|
1237 |
- await vm.fileSelectList(); |
|
1238 |
- vm.$showAlert("파일 삭제", response.data.message); |
|
1239 |
- vm.checkAll = false; |
|
1240 |
- vm.selectedFiles = []; |
|
1241 |
- } catch (error) { |
|
1242 |
- vm.isLoading = false; |
|
1243 |
- vm.$showAlert("파일 삭제", "파일 삭제 오류, 관리자에게 문의하세요."); |
|
1244 |
- vm.checkAll = false; |
|
1245 |
- vm.selectedFiles = []; |
|
1246 |
- } |
|
1247 |
- }, |
|
1248 |
- |
|
1249 |
- async fileConfirm(type) { |
|
1250 |
- const vm = this; |
|
1251 |
- |
|
1252 |
- if ( |
|
1253 |
- !(await vm.$showConfirm( |
|
1254 |
- "파일 " + type, |
|
1255 |
- "선택한 파일을 " + type + " 하시겠습니까?" |
|
1256 |
- )) |
|
1257 |
- ) { |
|
1258 |
- return; |
|
1259 |
- } |
|
1260 |
- |
|
1261 |
- let file = vm.selectedFiles[0]; |
|
1262 |
- let index = file.path.lastIndexOf("/"); |
|
1263 |
- |
|
1264 |
- if (file.path.substring(0, index) === file.movePath) { |
|
1265 |
- vm.$showAlert( |
|
1266 |
- "파일 " + type, |
|
1267 |
- "현재 파일 경로와 동일합니다. 다른 경로를 선택해주세요." |
|
1268 |
- ); |
|
1269 |
- return; |
|
1270 |
- } |
|
1271 |
- |
|
1272 |
- if (type === "복사") { |
|
1273 |
- vm.copy(vm.selectedFiles, "confirm", false); |
|
1274 |
- } else { |
|
1275 |
- vm.move(vm.selectedFiles, [], "confirm", false); |
|
1276 |
- } |
|
1277 |
- }, |
|
1278 |
- async move(fileList, removeFolderList, type, check) { |
|
1279 |
- const vm = this; |
|
1280 |
- |
|
1281 |
- fileList.forEach((file) => { |
|
1282 |
- if (!file.movePath) { |
|
1283 |
- file.movePath = vm.modalSeletedNode; |
|
1284 |
- } |
|
1285 |
- }); |
|
1286 |
- |
|
1287 |
- vm.isLoading = true; // 로딩 시작 |
|
1288 |
- try { |
|
1289 |
- const response = await axios.put( |
|
1290 |
- "/files/move/" + vm.connection.host_code, |
|
1291 |
- { |
|
1292 |
- fileList: fileList, |
|
1293 |
- removeFolder: removeFolderList, |
|
1294 |
- type: type, |
|
1295 |
- check: check, |
|
1296 |
- } |
|
1297 |
- ); |
|
1298 |
- |
|
1299 |
- vm.isLoading = false; // 로딩 해제 |
|
1300 |
- if (response.data.checkMessage.status === 100) { |
|
1301 |
- let returnFileList = response.data.resultData.fileList; |
|
1302 |
- let folderList = response.data.resultData.removeFolderList; |
|
1303 |
- const moveOrCopy = await vm.$showRadioConfirm( |
|
1304 |
- "파일 이동", |
|
1305 |
- response.data.checkMessage.message |
|
1306 |
- ); |
|
1307 |
- vm.move( |
|
1308 |
- returnFileList, |
|
1309 |
- folderList, |
|
1310 |
- moveOrCopy.type, |
|
1311 |
- moveOrCopy.checkBox |
|
1312 |
- ); |
|
1313 |
- } else { |
|
1314 |
- let folderList = response.data.resultData.removeFolderList; |
|
1315 |
- vm.checkAll = false; |
|
1316 |
- vm.selectedFiles = []; |
|
1317 |
- |
|
1318 |
- if (folderList.length != 0) { |
|
1319 |
- vm.removeFolder(folderList); |
|
1320 |
- } else { |
|
1321 |
- await vm.fileSelectList(); |
|
1322 |
- } |
|
1323 |
- vm.$showAlert("파일 이동", response.data.checkMessage.message); |
|
1324 |
- vm.closeTreeModal(); |
|
1325 |
- } |
|
1326 |
- } catch (error) { |
|
1327 |
- vm.isLoading = false; // 로딩 해제 |
|
1328 |
- vm.$showAlert("파일 이동", "파일 이동 오류, 관리자에게 문의하세요."); |
|
1329 |
- vm.checkAll = false; |
|
1330 |
- vm.selectedFiles = []; |
|
1331 |
- vm.closeTreeModal(); |
|
1332 |
- } |
|
1333 |
- }, |
|
1334 |
- |
|
1335 |
- async copy(fileList, type, check) { |
|
1336 |
- const vm = this; |
|
1337 |
- |
|
1338 |
- fileList.forEach((file) => { |
|
1339 |
- if (!file.movePath) { |
|
1340 |
- file.movePath = vm.modalSeletedNode; |
|
1341 |
- } |
|
1342 |
- }); |
|
1343 |
- |
|
1344 |
- vm.isLoading = true; // 로딩 시작 |
|
1345 |
- try { |
|
1346 |
- const response = await axios.put( |
|
1347 |
- "/files/copy/" + vm.connection.host_code, |
|
1348 |
- { fileList: fileList, type: type, check: check } |
|
1349 |
- ); |
|
1350 |
- |
|
1351 |
- vm.isLoading = false; // 로딩 해제 |
|
1352 |
- if (response.data.checkMessage.status === 100) { |
|
1353 |
- let returnFileList = response.data.resultData.fileList; |
|
1354 |
- const moveOrCopy = await vm.$showRadioConfirm( |
|
1355 |
- "파일 복사", |
|
1356 |
- response.data.checkMessage.message |
|
1357 |
- ); |
|
1358 |
- vm.copy(returnFileList, moveOrCopy.type, moveOrCopy.checkBox); |
|
1359 |
- } else { |
|
1360 |
- vm.$showAlert("파일 복사", response.data.checkMessage.message); |
|
1361 |
- vm.checkAll = false; |
|
1362 |
- vm.selectedFiles = []; |
|
1363 |
- vm.closeTreeModal(); |
|
1364 |
- } |
|
1365 |
- } catch (error) { |
|
1366 |
- vm.isLoading = false; // 로딩 해제 |
|
1367 |
- vm.$showAlert("파일 복사", "파일 이동 오류, 관리자에게 문의하세요."); |
|
1368 |
- vm.checkAll = false; |
|
1369 |
- vm.selectedFiles = []; |
|
1370 |
- vm.closeTreeModal(); |
|
1371 |
- } |
|
1372 |
- }, |
|
1373 |
- |
|
1374 |
- async removeFolder(folderList) { |
|
1375 |
- const vm = this; |
|
1376 |
- |
|
1377 |
- vm.isLoading = false; // 로딩 해제 |
|
1378 |
- |
|
1379 |
- try { |
|
1380 |
- const response = await axios.delete( |
|
1381 |
- "/files/folder/" + vm.connection.host_code, |
|
1382 |
- { data: folderList } |
|
1383 |
- ); |
|
1384 |
- |
|
1385 |
- vm.isLoading = false; // 로딩 해제 |
|
1386 |
- vm.getChildren(vm.selectItem.id, vm.selectItem.children); // 자식 폴더 리스트 업데이트 |
|
1387 |
- await vm.fileSelectList(); |
|
1388 |
- if (response.data.status === 500) { |
|
1389 |
- vm.$showAlert("파일 이동", response.data.message); |
|
1390 |
- } |
|
1391 |
- } catch (error) { |
|
1392 |
- vm.isLoading = false; // 로딩 해제 |
|
1393 |
- vm.$showAlert( |
|
1394 |
- "파일 이동", |
|
1395 |
- "원본 폴더 삭제 오류, 관리자에게 문의하세요." |
|
1396 |
- ); |
|
1397 |
- } |
|
1398 |
- }, |
|
1399 |
- |
|
1400 |
- // 미리보기 모달 닫기 |
|
1401 |
- previewModalClose() { |
|
1402 |
- this.previewModalOpen = false; |
|
1403 |
- this.dataTable = {}; |
|
1404 |
- }, |
|
1405 |
- |
|
1406 |
- // 파일 미리보기 |
|
1407 |
- preview(file) { |
|
1408 |
- // 허용된 파일 확장자 검사 |
|
1409 |
- const allowedExtensions = ["xlsx", "xls", "csv", "json"]; |
|
1410 |
- |
|
1411 |
- if (!allowedExtensions.includes(file.extension.toLowerCase())) { |
|
1412 |
- this.$showAlert( |
|
1413 |
- "파일 미리보기", |
|
1414 |
- "엑셀, CSV, JSON 파일만 읽을 수 있습니다." |
|
1415 |
- ); |
|
1416 |
- return; |
|
1417 |
- } |
|
1418 |
- |
|
1419 |
- this.previewModalOpen = true; |
|
1420 |
- this.fileRead(file); |
|
1421 |
- }, |
|
1422 |
- |
|
1423 |
- // 파일 미리보기 - 읽기 |
|
1424 |
- async fileRead(file) { |
|
1425 |
- const vm = this; |
|
1426 |
- vm.isLoading = true; |
|
1427 |
- axios |
|
1428 |
- .post("/files/read/" + vm.connection.host_code, { |
|
1429 |
- path: file.path, |
|
1430 |
- fileName: file.text, |
|
1431 |
- extension: file.extension, |
|
1432 |
- type: "file", |
|
1433 |
- datasetId: "", |
|
1434 |
- viewMode: true, |
|
1435 |
- }) |
|
1436 |
- .then((response) => { |
|
1437 |
- vm.dataTable = response.data.resultData.dataTableMap; |
|
1438 |
- }) |
|
1439 |
- .catch(() => { |
|
1440 |
- vm.isLoading = false; |
|
1441 |
- }); |
|
1442 |
- }, |
|
1443 |
- selectEncoding(encoding) { |
|
1444 |
- // 선택한 인코딩에 대한 처리 |
|
1445 |
- this.encodingType = encoding; |
|
1446 |
- console.log(`${encoding} 인코딩이 선택되었습니다.`); |
|
1447 |
- this.closeExcel(); // 선택 후 모달 닫기 |
|
1448 |
- }, |
|
1449 |
- closeExcel() { |
|
1450 |
- this.isOpenExcel = false; // 모달 상태를 false로 설정+ |
|
1451 |
- this.exportToCSV(); |
|
1452 |
- }, |
|
1453 |
- // 노드 설정 저장 후 닫기 |
|
1454 |
- fnUpdateSetup(jobItem) { |
|
1455 |
- console.log("값을 보자 ", jobItem); |
|
1456 |
- if ( |
|
1457 |
- !jobItem.dataTable.rowData || |
|
1458 |
- jobItem.dataTable.rowData.length === 0 |
|
1459 |
- ) { |
|
1460 |
- // rowData가 null이거나 빈 리스트일 때 실행할 코드 |
|
1461 |
- this.$showAlert("엑셀 생성 실패", "저장된 데이터가 없습니다."); |
|
1462 |
- } else { |
|
1463 |
- this.closeModal(); // 괄호 추가 |
|
1464 |
- this.isOpenExcel = true; |
|
1465 |
- this.selectNode = jobItem; |
|
1466 |
- } |
|
1467 |
- }, |
|
1468 |
- async exportToCSV() { |
|
1469 |
- const vm = this; |
|
1470 |
- |
|
1471 |
- try { |
|
1472 |
- // 컬럼 헤더 생성 |
|
1473 |
- console.log() |
|
1474 |
- const header = this.selectNode.dataTable.columnDatas.map( |
|
1475 |
- (col) => col.displyColumnNm |
|
1476 |
- ); |
|
1477 |
- |
|
1478 |
- // 데이터 준비 (rowData를 객체로 변환) |
|
1479 |
- const data = this.selectNode.dataTable.rowData.map((row) => { |
|
1480 |
- const rowObject = {}; |
|
1481 |
- this.selectNode.dataTable.columnDatas.forEach((col, index) => { |
|
1482 |
- rowObject[col.displyColumnNm] = row[index]; |
|
1483 |
- }); |
|
1484 |
- return rowObject; |
|
1485 |
- }); |
|
1486 |
- |
|
1487 |
- // CSV 데이터 생성 |
|
1488 |
- const csvContent = [ |
|
1489 |
- header.join(","), |
|
1490 |
- ...data.map((row) => |
|
1491 |
- header |
|
1492 |
- .map((col) => { |
|
1493 |
- // null, undefined 처리 및 쉼표가 포함된 데이터 처리 |
|
1494 |
- const cellData = row[col] ?? ""; |
|
1495 |
- return typeof cellData === "string" && cellData.includes(",") |
|
1496 |
- ? `"${cellData}"` |
|
1497 |
- : cellData; |
|
1498 |
- }) |
|
1499 |
- .join(",") |
|
1500 |
- ), |
|
1501 |
- ].join("\n"); |
|
1502 |
- |
|
1503 |
- let blob; |
|
1504 |
- // encodingType이 설정되지 않은 경우 기본값으로 utf-8 사용 |
|
1505 |
- const encoding = this.encodingType || "utf-8"; |
|
1506 |
- console.log("@@@", encoding); |
|
1507 |
- if (encoding === "utf-8") { |
|
1508 |
- // UTF-8 BOM 추가 |
|
1509 |
- blob = new Blob([new Uint8Array([0xef, 0xbb, 0xbf]), csvContent], { |
|
1510 |
- type: "text/csv;charset=utf-8", |
|
1511 |
- }); |
|
1512 |
- } else if (encoding === "euc-kr") { |
|
1513 |
- // EUC-KR 인코딩 |
|
1514 |
- const encoder = new TextEncoder(); |
|
1515 |
- const encodedData = encoder.encode(csvContent); |
|
1516 |
- blob = new Blob([encodedData], { |
|
1517 |
- type: "text/csv;charset=euc-kr", |
|
1518 |
- }); |
|
1519 |
- } else { |
|
1520 |
- console.log("지원되지 않는 인코딩 타입입니다: " + encoding); |
|
1521 |
- } |
|
1522 |
- |
|
1523 |
- if (!blob) { |
|
1524 |
- console.log("Blob 생성 실패"); |
|
1525 |
- } |
|
1526 |
- |
|
1527 |
- // 파일 이름 설정 |
|
1528 |
- const fileName = `${vm.selectNode.node_type}_${vm.$getFullFileTime( |
|
1529 |
- new Date() |
|
1530 |
- )}.csv`; |
|
1531 |
- |
|
1532 |
- // 서버에 업로드 |
|
1533 |
- const formData = new FormData(); |
|
1534 |
- formData.append("uploadFile", blob, fileName); |
|
1535 |
- formData.append("path", this.connection.path); |
|
1536 |
- formData.append("host_code", this.connection.host_code); |
|
1537 |
- |
|
1538 |
- const response = await axios.post("/files/formDataUpload", formData, { |
|
1539 |
- headers: { |
|
1540 |
- "Content-Type": "multipart/form-data", |
|
1541 |
- }, |
|
1542 |
- }); |
|
1543 |
- |
|
1544 |
- vm.$showAlert("업로드", response.data.message); |
|
1545 |
- vm.fileSelectList(); |
|
1546 |
- } catch (error) { |
|
1547 |
- console.error("CSV 내보내기 중 오류 발생:", error); |
|
1548 |
- vm.$showAlert("업로드", "업로드 오류, 관리자에게 문의하세요."); |
|
1549 |
- } |
|
1550 |
- }, |
|
1551 |
- // 노드 생성 |
|
1552 |
- fnCreateNode(type) { |
|
1553 |
- let node = Object.assign({}, this.$getDefaultJobGroup().node); |
|
1554 |
- node.id = Math.floor(Math.random() * 1000) + 1; |
|
1555 |
- node.node_id = node.id; |
|
1556 |
- node.label = type; |
|
1557 |
- node.node_name = type; |
|
1558 |
- node.node_type = type; |
|
1559 |
- node.position = { |
|
1560 |
- x: Math.floor(Math.random() * 500) + 1, |
|
1561 |
- y: Math.floor(Math.random() * 500) + 1, |
|
1562 |
- }; |
|
1563 |
- let tempData = JSON.parse(JSON.stringify(node)); |
|
1564 |
- tempData.data = null; |
|
1565 |
- node.data = tempData; |
|
1566 |
- switch (type) { |
|
1567 |
- case "DB_READ": |
|
1568 |
- node.itm = Object.assign({}, this.$getDefaultJobGroup().connectionDb); |
|
1569 |
- node.itm.type = "dbConnection"; |
|
1570 |
- break; |
|
1571 |
- case "API_READ": |
|
1572 |
- node.itm = Object.assign( |
|
1573 |
- {}, |
|
1574 |
- this.$getDefaultJobGroup().connectionApi |
|
1575 |
- ); |
|
1576 |
- break; |
|
1577 |
- case "EHOJO_READ": |
|
1578 |
- node.itm = Object.assign( |
|
1579 |
- {}, |
|
1580 |
- this.$getDefaultJobGroup().connectionEhojo |
|
1581 |
- ); |
|
1582 |
- break; |
|
1583 |
- } |
|
1584 |
- this.selectNode = node; |
|
1585 |
- }, |
|
1586 |
- }, |
|
1587 |
- |
|
1588 |
- watch: { |
|
1589 |
- // 모달타입에 맞는 모달창 화면 보여주기 |
|
1590 |
- modalType: function (newValue, oldValue) { |
|
1591 |
- if (this.modalType != null) { |
|
1592 |
- this.openModal(newValue); |
|
1593 |
- } |
|
1594 |
- }, |
|
1595 |
- selectedHostCodeData(newVal) { |
|
1596 |
- if (newVal !== null && !this.isUpdating) { |
|
1597 |
- this.isUpdating = true; // 업데이트 시작 |
|
1598 |
- |
|
1599 |
- // newVal이 이제 인덱스입니다 |
|
1600 |
- this.selectedDirectory = newVal; |
|
1601 |
- this.selectedHostData = this.hostList[newVal]; |
|
1602 |
- |
|
1603 |
- this.$nextTick(() => { |
|
1604 |
- this.isUpdating = false; // 업데이트 완료 |
|
1605 |
- }); |
|
1606 |
- } |
|
1607 |
- }, |
|
1608 |
- |
|
1609 |
- selectedDirectory(newVal) { |
|
1610 |
- if (newVal !== null && !this.isUpdating) { |
|
1611 |
- this.isUpdating = true; // 업데이트 시작 |
|
1612 |
- |
|
1613 |
- // newVal이 이제 인덱스입니다 |
|
1614 |
- this.selectedHostCodeData = newVal; |
|
1615 |
- this.selectedHostData = this.hostList[newVal]; |
|
1616 |
- |
|
1617 |
- this.$nextTick(() => { |
|
1618 |
- this.isUpdating = false; // 업데이트 완료 |
|
1619 |
- }); |
|
1620 |
- } |
|
1621 |
- } |
|
1622 | 30 |
}, |
1623 | 31 |
components: { |
1624 |
- PageNavigation: PageNavigation, |
|
1625 |
- SvgIcon: SvgIcon, |
|
1626 |
- PaginationButton: PaginationButton, |
|
1627 |
- TreeItem: TreeItem, |
|
1628 |
- TreeModal: TreeModal, |
|
1629 |
- FileDataRead: FileDataRead, |
|
1630 |
- DatabaseConnection: DatabaseConnection, |
|
1631 |
- apiConnection: apiConnection, |
|
1632 |
- XLSX: XLSX, |
|
1633 |
- EhojoConnection: EhojoConnection, |
|
1634 |
- }, |
|
1635 |
- mounted() { |
|
1636 |
- this.userauth = this.$authorChk(); |
|
1637 |
- this.selectHosts(); |
|
1638 |
- this.searchInit(); |
|
32 |
+ FileManagementMain: FileManagementMain, |
|
33 |
+ PageNavigation: PageNavigation |
|
1639 | 34 |
}, |
1640 | 35 |
}; |
1641 |
-</script> |
|
1642 |
-<style> |
|
1643 |
-.tabs-container { |
|
1644 |
- margin-top: 1rem; |
|
1645 |
-} |
|
1646 |
- |
|
1647 |
-.tab-btn { |
|
1648 |
- padding: 0.5rem 1rem; |
|
1649 |
- margin-right: 0.5rem; |
|
1650 |
- border: 1px solid #ddd; |
|
1651 |
- border-bottom: none; |
|
1652 |
- border-radius: 4px 4px 0 0; |
|
1653 |
- cursor: pointer; |
|
1654 |
- background: #f5f5f5; |
|
1655 |
-} |
|
1656 |
- |
|
1657 |
-.tab-btn.active { |
|
1658 |
- background: #fff; |
|
1659 |
- border-bottom: 2px solid #007bff; |
|
1660 |
- color: #007bff; |
|
1661 |
-} |
|
1662 |
-</style>(파일 끝에 줄바꿈 문자 없음) |
|
36 |
+</script>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/data/datapost/DataPostManagerMain.vue
+++ client/views/pages/data/datapost/DataPostManagerMain.vue
... | ... | @@ -1,116 +1,114 @@ |
1 | 1 |
<template> |
2 |
- <div class="content-box flex justify-between"> |
|
3 |
- <div class="flex20 content-box"> |
|
4 |
- <div class="left-content flex100 content-box"> |
|
5 |
- <div class="content-box"> |
|
6 |
- <div class="content-titleZone"> |
|
7 |
- <p class="box-title">카테고리 리스트</p> |
|
8 |
- </div> |
|
9 |
- <div class="content-zone"> |
|
10 |
- <CodeList :groupCode="'DATA_CTGRY'" @selectCode="selectCode" /> |
|
11 |
- </div> |
|
12 |
- </div> |
|
13 |
- </div> |
|
2 |
+ <div class="content-box flex justify-between"> |
|
3 |
+ <div class="flex20 content-box"> |
|
4 |
+ <div class="left-content flex100 content-box"> |
|
5 |
+ <div class="content-box"> |
|
6 |
+ <div class="content-titleZone"> |
|
7 |
+ <p class="box-title">카테고리 리스트</p> |
|
8 |
+ </div> |
|
9 |
+ <div class="content-zone"> |
|
10 |
+ <CodeList :groupCode="'DATA_CTGRY'" @selectCode="selectCode" /> |
|
11 |
+ </div> |
|
14 | 12 |
</div> |
15 |
- <div class="flex80 content-box"> |
|
16 |
- <div class="right-content flex100"> |
|
17 |
- <div class="flex-column justify-between"> |
|
18 |
- <div class="flex justify-end"> |
|
19 |
- <div class="search-bar"> |
|
20 |
- <div class="flex justify-end align-center" style="gap: 5px"> |
|
21 |
- <input type="date" name="start-date" id="start-date" class="square-date" |
|
22 |
- :class="{ 'date-placeholder': false }" data-placeholder="날짜 선택" |
|
23 |
- v-model="search_date.value" /> |
|
24 |
- <span>~</span> |
|
25 |
- <input type="date" name="end-date" id="end-date" class="square-date" |
|
26 |
- :class="{ 'date-placeholder': false }" data-placeholder="날짜 선택" |
|
27 |
- v-model="search_date.value2" /> |
|
28 |
- <select class="square-select" v-model="search_data1.value"> |
|
29 |
- <option :value="null">공개여부</option> |
|
30 |
- <option :value="true">공개</option> |
|
31 |
- <option :value="false">비공개</option> |
|
32 |
- </select> |
|
33 |
- <select class="square-select" v-model="search_data2.value"> |
|
34 |
- <option :value="null">카테고리</option> |
|
35 |
- <option v-for="(item, indx) in categoryList" :key="indx" :value="item.cmmnCode">{{ |
|
36 |
- item.codeNm }}</option> |
|
37 |
- </select> |
|
38 |
- <select name="" id="searchItm1" class="square-select" v-model="search_data3.key"> |
|
39 |
- <option :value="null">검색조건</option> |
|
40 |
- <option value="post_sj">제목</option> |
|
41 |
- <option value="post_dc">내용</option> |
|
42 |
- </select> |
|
43 |
- <div class="flex justify-end align-center no-gutter"> |
|
44 |
- <input type="text" class="square-input flex90" placeholder="Search" |
|
45 |
- v-model="search_data3.value" v-on:keyup.enter="searchData()" /> |
|
46 |
- <button class="square-button blue-btn flex10" @click="searchData()"> |
|
47 |
- <svg-icon type="mdi" :path="this.$getIconPath()" class="square-icon"></svg-icon> |
|
48 |
- </button> |
|
49 |
- </div> |
|
50 |
- </div> |
|
51 |
- </div> |
|
52 |
- </div> |
|
53 |
- <div class="content-zone" style="overflow: auto;"> |
|
54 |
- <div class="table-zone"> |
|
55 |
- <div class="list-info flex justify-between align-center"> |
|
56 |
- <div class="count-zone"> |
|
57 |
- <p>총<span>{{ search.totalRows }}</span>건</p> |
|
58 |
- </div> |
|
59 |
- <div class="cunt-selectZone"> |
|
60 |
- <select name="" id=""> |
|
61 |
- <option value="">10개 보기</option> |
|
62 |
- <option value="">20개 보기</option> |
|
63 |
- </select> |
|
64 |
- </div> |
|
65 |
- </div> |
|
66 |
- <table class="list-table"> |
|
67 |
- <!-- col 꼭 너비 기재해야함! 그래야 100%로 차지함 --> |
|
68 |
- <colgroup> |
|
69 |
- <col style="width: 10%" /> |
|
70 |
- <col style="width: 40%" /> |
|
71 |
- <col style="width: 10%" /> |
|
72 |
- <col style="width: 10%" /> |
|
73 |
- <col style="width: 10%" /> |
|
74 |
- <col style="width: 30%" /> |
|
75 |
- </colgroup> |
|
76 |
- <thead> |
|
77 |
- <tr> |
|
78 |
- <th>No</th> |
|
79 |
- <th>제목</th> |
|
80 |
- <th>생성자</th> |
|
81 |
- <th>부서</th> |
|
82 |
- <th>카테고리</th> |
|
83 |
- <th>등록일시</th> |
|
84 |
- </tr> |
|
85 |
- </thead> |
|
86 |
- <tbody> |
|
87 |
- <template v-if="dataPostList.length > 0"> |
|
88 |
- <tr v-for="(item, indx) in dataPostList" :key="indx" @click="selectPost(item)"> |
|
89 |
- <td>{{ search.totalRows - indx - (search.currentPage - 1) * search.perPage |
|
90 |
- }}</td> |
|
91 |
- <td>{{ item.post_sj }}</td> |
|
92 |
- <td>{{ item.user_nm }}</td> |
|
93 |
- <td>{{ item.dept_nm }}</td> |
|
94 |
- <td>{{ item.ctgry_id }}</td> |
|
95 |
- <td>{{ $getFullTime(item.creat_dt) }}</td> |
|
96 |
- </tr> |
|
97 |
- </template> |
|
98 |
- <tr v-else> |
|
99 |
- <td colspan="6">등록된 데이터가 없습니다.</td> |
|
100 |
- </tr> |
|
101 |
- </tbody> |
|
102 |
- </table> |
|
103 |
- <PaginationButton v-model:currentPage="search.currentPage" :perPage="search.perPage" |
|
104 |
- :totalCount="search.totalRows" :maxRange="5" :click="searchData" /> |
|
105 |
- </div> |
|
106 |
- </div> |
|
107 |
- <div class="flex justify-end"> |
|
108 |
- <button class="blue-btn small-btn" @click="createDataPost">데이터 등록</button> |
|
109 |
- </div> |
|
110 |
- </div> |
|
111 |
- </div> |
|
112 |
- </div> |
|
13 |
+ </div> |
|
113 | 14 |
</div> |
15 |
+ <div class="flex80 content-box"> |
|
16 |
+ <div class="right-content flex100"> |
|
17 |
+ <div class="flex-column justify-between"> |
|
18 |
+ <div class="flex justify-end"> |
|
19 |
+ <div class="search-bar"> |
|
20 |
+ <div class="flex justify-end align-center" style="gap: 5px"> |
|
21 |
+ <input type="date" name="start-date" id="start-date" class="square-date" |
|
22 |
+ :class="{ 'date-placeholder': false }" data-placeholder="날짜 선택" v-model="search_date.value" /> |
|
23 |
+ <span>~</span> |
|
24 |
+ <input type="date" name="end-date" id="end-date" class="square-date" |
|
25 |
+ :class="{ 'date-placeholder': false }" data-placeholder="날짜 선택" v-model="search_date.value2" /> |
|
26 |
+ <select class="square-select" v-model="search_data1.value"> |
|
27 |
+ <option :value="null">공개여부</option> |
|
28 |
+ <option :value="true">공개</option> |
|
29 |
+ <option :value="false">비공개</option> |
|
30 |
+ </select> |
|
31 |
+ <select class="square-select" v-model="search_data2.value"> |
|
32 |
+ <option :value="null">카테고리</option> |
|
33 |
+ <option v-for="(item, indx) in categoryList" :key="indx" :value="item.cmmnCode">{{ |
|
34 |
+ item.codeNm }}</option> |
|
35 |
+ </select> |
|
36 |
+ <select name="" id="searchItm1" class="square-select" v-model="search_data3.key"> |
|
37 |
+ <option :value="null">검색조건</option> |
|
38 |
+ <option value="post_sj">제목</option> |
|
39 |
+ <option value="post_dc">내용</option> |
|
40 |
+ </select> |
|
41 |
+ <div class="flex justify-end align-center no-gutter"> |
|
42 |
+ <input type="text" class="square-input flex90" placeholder="Search" v-model="search_data3.value" |
|
43 |
+ v-on:keyup.enter="searchData()" /> |
|
44 |
+ <button class="square-button blue-btn flex10" @click="searchData()"> |
|
45 |
+ <svg-icon type="mdi" :path="this.$getIconPath()" class="square-icon"></svg-icon> |
|
46 |
+ </button> |
|
47 |
+ </div> |
|
48 |
+ </div> |
|
49 |
+ </div> |
|
50 |
+ </div> |
|
51 |
+ <div class="content-zone" style="overflow: auto;"> |
|
52 |
+ <div class="table-zone"> |
|
53 |
+ <div class="list-info flex justify-between align-center"> |
|
54 |
+ <div class="count-zone"> |
|
55 |
+ <p>총<span>{{ search.totalRows }}</span>건</p> |
|
56 |
+ </div> |
|
57 |
+ <div class="cunt-selectZone"> |
|
58 |
+ <select name="" id=""> |
|
59 |
+ <option value="">10개 보기</option> |
|
60 |
+ <option value="">20개 보기</option> |
|
61 |
+ </select> |
|
62 |
+ </div> |
|
63 |
+ </div> |
|
64 |
+ <table class="list-table"> |
|
65 |
+ <!-- col 꼭 너비 기재해야함! 그래야 100%로 차지함 --> |
|
66 |
+ <colgroup> |
|
67 |
+ <col style="width: 10%" /> |
|
68 |
+ <col style="width: 40%" /> |
|
69 |
+ <col style="width: 10%" /> |
|
70 |
+ <col style="width: 10%" /> |
|
71 |
+ <col style="width: 10%" /> |
|
72 |
+ <col style="width: 30%" /> |
|
73 |
+ </colgroup> |
|
74 |
+ <thead> |
|
75 |
+ <tr> |
|
76 |
+ <th>No</th> |
|
77 |
+ <th>제목</th> |
|
78 |
+ <th>생성자</th> |
|
79 |
+ <th>부서</th> |
|
80 |
+ <th>카테고리</th> |
|
81 |
+ <th>등록일시</th> |
|
82 |
+ </tr> |
|
83 |
+ </thead> |
|
84 |
+ <tbody> |
|
85 |
+ <template v-if="dataPostList.length > 0"> |
|
86 |
+ <tr v-for="(item, indx) in dataPostList" :key="indx" @click="selectPost(item)"> |
|
87 |
+ <td>{{ search.totalRows - indx - (search.currentPage - 1) * search.perPage |
|
88 |
+ }}</td> |
|
89 |
+ <td>{{ item.post_sj }}</td> |
|
90 |
+ <td>{{ item.user_nm }}</td> |
|
91 |
+ <td>{{ item.dept_nm }}</td> |
|
92 |
+ <td>{{ item.ctgry_id }}</td> |
|
93 |
+ <td>{{ $getFullTime(item.creat_dt) }}</td> |
|
94 |
+ </tr> |
|
95 |
+ </template> |
|
96 |
+ <tr v-else> |
|
97 |
+ <td colspan="6">등록된 데이터가 없습니다.</td> |
|
98 |
+ </tr> |
|
99 |
+ </tbody> |
|
100 |
+ </table> |
|
101 |
+ <PaginationButton v-model:currentPage="search.currentPage" :perPage="search.perPage" |
|
102 |
+ :totalCount="search.totalRows" :maxRange="5" :click="searchData" /> |
|
103 |
+ </div> |
|
104 |
+ </div> |
|
105 |
+ <div class="flex justify-end"> |
|
106 |
+ <button class="blue-btn small-btn" @click="createDataPost">데이터 등록</button> |
|
107 |
+ </div> |
|
108 |
+ </div> |
|
109 |
+ </div> |
|
110 |
+ </div> |
|
111 |
+ </div> |
|
114 | 112 |
</template> |
115 | 113 |
<script> |
116 | 114 |
import CodeList from "../../../component/common/Component_CodeList.vue"; |
... | ... | @@ -118,6 +116,7 @@ |
118 | 116 |
import PageNavigation from "../../../component/PageNavigation.vue"; |
119 | 117 |
import SvgIcon from "@jamescoyle/vue-icon"; |
120 | 118 |
import PaginationButton from "../../../component/PaginationButton.vue"; |
119 |
+import moment from 'moment'; |
|
121 | 120 |
|
122 | 121 |
export default { |
123 | 122 |
data() { |
... | ... | @@ -131,7 +130,14 @@ |
131 | 130 |
// 선택 |
132 | 131 |
search_data3: this.$getDefaultSerchItem("post_sj", "string"), |
133 | 132 |
// 날짜 |
134 |
- search_date: this.$getDefaultSerchItem("creat_dt", "dates"), |
|
133 |
+ search_date: { |
|
134 |
+ key: "creat_dt", |
|
135 |
+ value: null, |
|
136 |
+ key2: "creat_dt", |
|
137 |
+ value2: null, |
|
138 |
+ type: "dates", |
|
139 |
+ }, |
|
140 |
+ // search_date: this.$getDefaultSerchItem("creat_dt", "dates"), |
|
135 | 141 |
categoryList: [], |
136 | 142 |
}; |
137 | 143 |
}, |
... | ... | @@ -152,7 +158,7 @@ |
152 | 158 |
}); |
153 | 159 |
}, |
154 | 160 |
searchData: function () { |
155 |
- console.log("@@검색값",this.search); |
|
161 |
+ console.log("@@검색값", this.search); |
|
156 | 162 |
const vm = this; |
157 | 163 |
|
158 | 164 |
let check = false; |
... | ... | @@ -183,17 +189,26 @@ |
183 | 189 |
}) |
184 | 190 |
.then(function (response) { |
185 | 191 |
if (response.data.checkMessage.success) { |
192 |
+ vm.setDateRange(response.data.resultData.dataPostList); |
|
186 | 193 |
vm.dataPostList = response.data.resultData.dataPostList; |
187 | 194 |
vm.search.totalRows = response.data.resultData.totalRow; |
188 | 195 |
} |
189 | 196 |
}) |
190 | 197 |
.catch(function (error) { |
191 |
- this.$showAlert( |
|
198 |
+ vm.$showAlert( |
|
192 | 199 |
"에러 발생", |
193 | 200 |
"에러가 발생했습니다. 관리자에게 문의해 주세요." |
194 | 201 |
); |
195 | 202 |
}); |
196 | 203 |
}, |
204 |
+ setDateRange(dataList) { |
|
205 |
+ const dates = dataList.map(item => item.creat_dt).sort(); |
|
206 |
+ |
|
207 |
+ if (dates.length > 0) { |
|
208 |
+ this.search_date.value = moment(dates[0]).format('YYYY-MM-DD'); |
|
209 |
+ this.search_date.value2 = moment(dates[dates.length - 1]).format('YYYY-MM-DD'); |
|
210 |
+ } |
|
211 |
+ }, |
|
197 | 212 |
// 초기화 |
198 | 213 |
init: async function () { |
199 | 214 |
this.search.searchObjectList.push(this.search_date); |
+++ client/views/pages/data/filemanger/FileManagementMain.vue
... | ... | @@ -0,0 +1,1646 @@ |
1 | +<template> | |
2 | + <div class="content-box flex justify-between"> | |
3 | + <div class="flex20 content-box"> | |
4 | + <div class="left-content flex100 content-box"> | |
5 | + <div class="content-box"> | |
6 | + <div class="flex align-end justify-between no-gutter"> | |
7 | + <div class="mb10 flex70"> | |
8 | + <div class="content"> | |
9 | + <p class="box-title">호스트 선택</p> | |
10 | + </div> | |
11 | + <div> | |
12 | + <select class="only full-select" v-model="selectedHostCodeData"> | |
13 | + <option :value="null" disabled>선택</option> | |
14 | + <option v-for="(host, idx) in hostList" :key="idx" :value="idx"> | |
15 | + {{ host.host_nm + " - (" + host.host_ip + ")" }} | |
16 | + </option> | |
17 | + </select> | |
18 | + </div> | |
19 | + </div> | |
20 | + <div class="mb10 flex70" v-if="userauth !== 'ROLE_ADMIN'"> | |
21 | + <div class="content"> | |
22 | + <p class="box-title">디렉토리 선택</p> | |
23 | + </div> | |
24 | + <div> | |
25 | + <select class="only full-select" v-model="selectedDirectory"> | |
26 | + <option :value="null" disabled>선택</option> | |
27 | + <option v-for="(host, idx) in hostList" :key="idx" :value="idx"> | |
28 | + {{ host.dept_drctry_nm }} | |
29 | + </option> | |
30 | + </select> | |
31 | + </div> | |
32 | + </div> | |
33 | + <div class="mb10 flex25"> | |
34 | + <button class="blue-btn large-btn" @click="uniquePaths()"> | |
35 | + 연결 | |
36 | + </button> | |
37 | + </div> | |
38 | + </div> | |
39 | + <div class="file-tree-zone" | |
40 | + :style="{ height: userauth !== 'ROLE_ADMIN' ? 'calc(100% - 156px)' : 'calc(100% - 79px)' }"> | |
41 | + <div class="content-titleZone flex justify-between align-center"> | |
42 | + <p class="box-title">폴더 리스트</p> | |
43 | + <button class="blue-border-btn small-btn" @click="openMkdirModal()"> | |
44 | + 폴더추가 | |
45 | + </button> | |
46 | + </div> | |
47 | + <div class="file-zone overflow-y"> | |
48 | + <ul class="tree-wrap"> | |
49 | + <TreeItem ref="treeItem" :connection="connection" :selectedNode="selectedNode" | |
50 | + v-for="(item, idx) in nodes" :item="item" :idx="item.id" :selectItem="selectItem" | |
51 | + :key="idx" @selectFolder="selectFolder" @isLoading="handleIsLoading" | |
52 | + @selectItem="handleSelectItem" /> | |
53 | + | |
54 | + </ul> | |
55 | + </div> | |
56 | + </div> | |
57 | + </div> | |
58 | + </div> | |
59 | + </div> | |
60 | + <div class="flex80 content-box"> | |
61 | + <div class="right-content flex100"> | |
62 | + <div class="flex-column justify-between"> | |
63 | + <div class="flex justify-between align-center no-gutter"> | |
64 | + <div class="flex40"> | |
65 | + <button class="blue-border-btn small-btn" @click="openTreeModal('copy')"> | |
66 | + 선택복사 | |
67 | + </button> | |
68 | + <button class="blue-border-btn small-btn" @click="openTreeModal('move')"> | |
69 | + 선택이동 | |
70 | + </button> | |
71 | + <button class="red-border-btn small-btn" @click="remove()"> | |
72 | + 선택삭제 | |
73 | + </button> | |
74 | + </div> | |
75 | + <div class="flex justify-end flex60"> | |
76 | + <div class="search-bar"> | |
77 | + <div class="flex justify-end align-center"> | |
78 | + <select name="" id="" class="square-select" v-model="searchType"> | |
79 | + <option value="all">전체</option> | |
80 | + <option value="folder">현재폴더</option> | |
81 | + </select> | |
82 | + <div class="search-square"> | |
83 | + <div class="flex justify-end align-center no-gutter"> | |
84 | + <input type="text" class="square-input flex90" placeholder="Search File" | |
85 | + v-model="searchText" @keyup.enter="searchFiles()" /> | |
86 | + <button class="square-button blue-btn flex10"> | |
87 | + <svg-icon type="mdi" :path="searchPath" class="square-icon" | |
88 | + @click="searchFiles()"></svg-icon> | |
89 | + </button> | |
90 | + </div> | |
91 | + </div> | |
92 | + </div> | |
93 | + </div> | |
94 | + </div> | |
95 | + </div> | |
96 | + <div class="content-zone" style="overflow-y: auto"> | |
97 | + <div class="table-zone file-table"> | |
98 | + <div class="list-info flex justify-between align-center"> | |
99 | + <div class="count-zone"> | |
100 | + <p> | |
101 | + 총 | |
102 | + <span v-if="search.totalRows != 0">{{ | |
103 | + search.totalRows | |
104 | + }}</span> | |
105 | + <span v-else>0</span>건 중 | |
106 | + <span>{{ selectedFiles.length }}</span>건 선택 | |
107 | + </p> | |
108 | + <p> | |
109 | + 현재경로 : <span>{{ connection.path }}</span> | |
110 | + </p> | |
111 | + </div> | |
112 | + </div> | |
113 | + <table class="list-table"> | |
114 | + <!-- col 꼭 너비 기재해야함! 그래야 100%로 차지함 --> | |
115 | + <colgroup> | |
116 | + <col style="width: 5%" /> | |
117 | + <col style="width: 45%" /> | |
118 | + <col style="width: 10%" /> | |
119 | + <col style="width: 15%" /> | |
120 | + <col style="width: 10%" /> | |
121 | + <col style="width: 15%" /> | |
122 | + </colgroup> | |
123 | + <thead> | |
124 | + <tr> | |
125 | + <th> | |
126 | + <input type="checkbox" @click="filesCheckAll" v-model="checkAll" /> | |
127 | + </th> | |
128 | + <th>이름</th> | |
129 | + <th>타입</th> | |
130 | + <th>마지막 수정</th> | |
131 | + <th>크기</th> | |
132 | + <th>관리</th> | |
133 | + </tr> | |
134 | + </thead> | |
135 | + <tbody> | |
136 | + <tr v-for="(file, index) in fileList" :key="index" @click="selectFileList(file)"> | |
137 | + <td v-if="file.text != '상위폴더로 이동'" @click.stop=""> | |
138 | + <input type="checkbox" @click.stop="" v-model="selectedFiles" :value="{ | |
139 | + folder: file.folder, | |
140 | + path: file.path, | |
141 | + fileName: file.text, | |
142 | + extension: file.extension, | |
143 | + }" name="files" /> | |
144 | + </td> | |
145 | + <td v-else @click.stop=""></td> | |
146 | + <td> | |
147 | + <div class="text-lf"> | |
148 | + <span v-if="file.extension === 'txt'"><img | |
149 | + src="../../../../resources/img/icon/txt.png" ref="" | |
150 | + alt="" /></span> | |
151 | + <span v-else-if="file.extension === 'pdf'"><img | |
152 | + src="../../../../resources/img/icon/pdf.png" alt="" /></span> | |
153 | + <span v-else-if=" | |
154 | + file.extension === 'pptx' || | |
155 | + file.extension === 'ppt' | |
156 | + "><img src="../../../../resources/img/icon/ppt.png" alt="" /></span> | |
157 | + <span v-else-if="file.extension === 'hwp'"><img | |
158 | + src="../../../../resources/img/icon/hwp.png" alt="" /></span> | |
159 | + <span v-else-if=" | |
160 | + file.extension === 'xls' || | |
161 | + file.extension === 'xlsx' || | |
162 | + file.extension === 'csv' | |
163 | + "><img src="../../../../resources/img/icon/xls.png" alt="" /></span> | |
164 | + <span v-else-if="file.extension === 'jpg'"><img | |
165 | + src="../../../../resources/img/icon/img.png" alt="" /></span> | |
166 | + <span v-else-if="file.extension === 'png'"><img | |
167 | + src="../../../../resources/img/icon/img.png" ref="" | |
168 | + alt="" /></span> | |
169 | + <span>{{ " " + file.text }}</span> | |
170 | + </div> | |
171 | + </td> | |
172 | + <td>{{ file.extension }}</td> | |
173 | + <td>{{ file.lastUpdate }}</td> | |
174 | + <td v-if="file.size != 0"> | |
175 | + {{ $filters.bytesToSize(file.size) }} | |
176 | + </td> | |
177 | + <td v-else></td> | |
178 | + <td> | |
179 | + <div v-if="!file.folder"> | |
180 | + <button class="icon-btn orange-btn" title="미리보기" | |
181 | + @click.stop="preview(file)"> | |
182 | + <svg-icon type="mdi" :width="18" :height="18" | |
183 | + :path="fileFindPath"></svg-icon> | |
184 | + </button> | |
185 | + <button class="icon-btn green-btn ml5" title="파일명 변경" | |
186 | + @click.stop="openReNameModal(file)"> | |
187 | + <svg-icon type="mdi" :width="18" :height="18" | |
188 | + :path="fileNamePath"></svg-icon> | |
189 | + </button> | |
190 | + <button class="icon-btn blue-btn ml5" title="다운로드" | |
191 | + @click.stop="download(file)"> | |
192 | + <svg-icon type="mdi" :width="18" :height="18" | |
193 | + :path="filedownPath"></svg-icon> | |
194 | + </button> | |
195 | + </div> | |
196 | + <div v-else-if=" | |
197 | + file.folder && file.text != '상위폴더로 이동' | |
198 | + "> | |
199 | + <button class="icon-btn green-btn ml5" title="폴더명 변경" | |
200 | + @click.stop="openReNameModal(file)"> | |
201 | + <svg-icon type="mdi" :width="18" :height="18" | |
202 | + :path="fileNamePath"></svg-icon> | |
203 | + </button> | |
204 | + </div> | |
205 | + </td> | |
206 | + </tr> | |
207 | + </tbody> | |
208 | + </table> | |
209 | + </div> | |
210 | + </div> | |
211 | + <div class="flex justify-end"> | |
212 | + <button class="blue-btn small-btn" @click="setModal('typeSelected', 'small')"> | |
213 | + 업로드 | |
214 | + </button> | |
215 | + </div> | |
216 | + </div> | |
217 | + </div> | |
218 | + </div> | |
219 | + </div> | |
220 | + <!-- 폴더 목록 모달 --> | |
221 | + <TreeModal :modalOpen="treeModalOpen" :modalConnection="modalConnection" :modalNodes="modalNodes" | |
222 | + :selectType="selectModalType" @modalSelectFolder="modalSelectFolder" @closeTreeModal="closeTreeModal" | |
223 | + @modalSubmit="fileConfirm" /> | |
224 | + <!-- 데이터셋 미리보기 모달 --> | |
225 | + <div v-show="previewModalOpen" class="modal-wrapper" :style="isLoading ? { cursor: 'wait' } : {}"> | |
226 | + <div v-if="isLoading" class="loading-overlay"> | |
227 | + <div class="loading-div"> | |
228 | + <span>LOADING </span> | |
229 | + <span class="anima">.</span> | |
230 | + <span class="anima">.</span> | |
231 | + <span class="anima">.</span> | |
232 | + </div> | |
233 | + </div> | |
234 | + <div class="modal-container list-modal"> | |
235 | + <div class="modal-title"> | |
236 | + <div class="flex justify-between align-center"> | |
237 | + <h2>데이터 미리보기</h2> | |
238 | + <button class="close-btn" @click="previewModalClose()">X</button> | |
239 | + </div> | |
240 | + </div> | |
241 | + <div class="modal-content-monthly"> | |
242 | + <FileDataRead v-if="previewModalOpen" v-model:isLoading="isLoading" :dataTable="dataTable" | |
243 | + :preview="true"> | |
244 | + </FileDataRead> | |
245 | + </div> | |
246 | + <div class="modal-end flex justify-end"> | |
247 | + <button class="blue-btn small-btn" @click="previewModalClose()"> | |
248 | + 확인 | |
249 | + </button> | |
250 | + </div> | |
251 | + </div> | |
252 | + </div> | |
253 | + <!-- 폴더, 파일 이름변경 모달 --> | |
254 | + <div v-show="reNameModalOpen" class="modal-wrapper"> | |
255 | + <div class="modal-container small-modal"> | |
256 | + <div class="modal-title text-ct"> | |
257 | + <h2>폴더(파일)명 변경</h2> | |
258 | + </div> | |
259 | + <div class="modal-content-monthly"> | |
260 | + <div class="table-zone"> | |
261 | + <table class="form-table2"> | |
262 | + <!-- col 꼭 너비 기재해야함! 그래야 100%로 차지함 --> | |
263 | + <colgroup> | |
264 | + <col style="width: 25%" /> | |
265 | + <col style="width: 75%" /> | |
266 | + </colgroup> | |
267 | + <tbody> | |
268 | + <tr> | |
269 | + <th>현재 이름</th> | |
270 | + <td>{{ reNameObject.currentName }}</td> | |
271 | + </tr> | |
272 | + <tr> | |
273 | + <th>변경 이름</th> | |
274 | + <td> | |
275 | + <input type="text" class="full-input" v-model="reNameObject.changeName" | |
276 | + @keyup.enter="rename()" /> | |
277 | + </td> | |
278 | + </tr> | |
279 | + </tbody> | |
280 | + </table> | |
281 | + </div> | |
282 | + </div> | |
283 | + <div class="modal-end flex justify-between" style="flex-wrap: nowrap"> | |
284 | + <button class="gray-btn large-btn" @click="closeReNameModal()"> | |
285 | + 취소 | |
286 | + </button> | |
287 | + <button class="blue-btn large-btn" @click="rename()">확인</button> | |
288 | + </div> | |
289 | + </div> | |
290 | + </div> | |
291 | + <!-- 폴더추가 모달 --> | |
292 | + <div v-show="mkdirModalOpen" class="modal-wrapper"> | |
293 | + <div class="modal-container small-modal"> | |
294 | + <div class="modal-title text-ct"> | |
295 | + <h2>폴더 추가</h2> | |
296 | + </div> | |
297 | + <div class="modal-content-monthly"> | |
298 | + <div class="table-zone"> | |
299 | + <table class="form-table2"> | |
300 | + <!-- col 꼭 너비 기재해야함! 그래야 100%로 차지함 --> | |
301 | + <colgroup> | |
302 | + <col style="width: 25%" /> | |
303 | + <col style="width: 75%" /> | |
304 | + </colgroup> | |
305 | + <tbody> | |
306 | + <tr> | |
307 | + <th>현재경로</th> | |
308 | + <td>{{ connection.path }}</td> | |
309 | + </tr> | |
310 | + <tr> | |
311 | + <th>폴더명</th> | |
312 | + <td> | |
313 | + <input type="text" class="full-input" v-model="folderName" @keyup.enter="mkdir()" /> | |
314 | + </td> | |
315 | + </tr> | |
316 | + </tbody> | |
317 | + </table> | |
318 | + </div> | |
319 | + </div> | |
320 | + <div class="modal-end flex justify-between" style="flex-wrap: nowrap"> | |
321 | + <button class="blue-btn large-btn" @click="mkdir()">확인</button> | |
322 | + <button class="gray-btn large-btn" @click="closeMkdirModal()"> | |
323 | + 취소 | |
324 | + </button> | |
325 | + </div> | |
326 | + </div> | |
327 | + </div> | |
328 | + <!-- 엑셀 타입 지정 --> | |
329 | + <div v-if="isOpenExcel" class="modal-wrapper"> | |
330 | + <div class="modal-container small-modal"> | |
331 | + <div class="modal-title text-ct"> | |
332 | + <div class="flex justify-between align-center"> | |
333 | + <h2>ExcelEncoding</h2> | |
334 | + <button class="close-btn" @click="closeExcel"> | |
335 | + <svg-icon type="mdi" :width="20" :height="20" :path="closePath"></svg-icon> | |
336 | + </button> | |
337 | + </div> | |
338 | + </div> | |
339 | + <!-- ExcelEncoding 선택--> | |
340 | + <div class="modal-content-monthly"> | |
341 | + <div class="flex justify-center align-center mb10"> | |
342 | + <div class="flex50 pl0"> | |
343 | + <button class="blue-border-btn large-btn" @click="selectEncoding('utf-8')"> | |
344 | + UTF-8 | |
345 | + </button> | |
346 | + </div> | |
347 | + <div class="flex50 pr0"> | |
348 | + <button class="blue-border-btn large-btn" @click="selectEncoding('euc-kr')"> | |
349 | + EUC-KR | |
350 | + </button> | |
351 | + </div> | |
352 | + </div> | |
353 | + </div> | |
354 | + </div> | |
355 | + </div> | |
356 | + <!-- 모달 --> | |
357 | + <div v-show="isModalOpen" class="modal-wrapper"> | |
358 | + <div :class="{ | |
359 | + 'modal-container': true, | |
360 | + 'small-modal': modalSize === 'small', | |
361 | + 'large-modal': modalSize === 'large', | |
362 | + }"> | |
363 | + <div class="modal-title text-ct" v-show="modalType === 'typeSelected'"> | |
364 | + <div class="flex justify-between align-center"> | |
365 | + <h2>업로드</h2> | |
366 | + <button class="close-btn" @click="closeModal"> | |
367 | + <svg-icon type="mdi" :width="20" :height="20" :path="closePath"></svg-icon> | |
368 | + </button> | |
369 | + </div> | |
370 | + </div> | |
371 | + <!-- 업로드 타입 선택 --> | |
372 | + <div class="modal-content-monthly" v-show="modalType === 'typeSelected'"> | |
373 | + <div class="flex justify-center align-center mb10"> | |
374 | + <div class="flex50 pl0"> | |
375 | + <button class="blue-border-btn large-btn" @click="setModal('file-modal', 'small')"> | |
376 | + 파일 | |
377 | + </button> | |
378 | + </div> | |
379 | + <div class="flex50 pr0"> | |
380 | + <button class="blue-border-btn large-btn" @click="setModal('db-modal', 'middle')"> | |
381 | + DB | |
382 | + </button> | |
383 | + </div> | |
384 | + </div> | |
385 | + <div class="flex justify-center align-center"> | |
386 | + <div class="flex50 pl0"> | |
387 | + <button class="blue-border-btn large-btn" @click="setModal('api-modal', 'middle')"> | |
388 | + API | |
389 | + </button> | |
390 | + </div> | |
391 | + <div class="flex50 pr0"> | |
392 | + <button class="blue-border-btn large-btn" @click="setModal('ehojo-modal', 'middle')"> | |
393 | + 차세대 API | |
394 | + </button> | |
395 | + </div> | |
396 | + </div> | |
397 | + </div> | |
398 | + <!-- 파일 (file-modal) --> | |
399 | + <template v-if="modalType == 'file-modal'"> | |
400 | + <div class="modal-title"> | |
401 | + <div class="flex justify-between align-center"> | |
402 | + <h2>파일 등록</h2> | |
403 | + <button class="close-btn" @click="closeModal">X</button> | |
404 | + </div> | |
405 | + </div> | |
406 | + <div class="modal-content-monthly"> | |
407 | + <div class="table-zone"> | |
408 | + <table class="form-table"> | |
409 | + <colgroup> | |
410 | + <col style="width: 15%" /> | |
411 | + <col style="width: 85%" /> | |
412 | + </colgroup> | |
413 | + <tbody> | |
414 | + <tr> | |
415 | + <th>현재경로</th> | |
416 | + <td>{{ connection.path }}</td> | |
417 | + </tr> | |
418 | + <tr> | |
419 | + <th>파일명</th> | |
420 | + <td> | |
421 | + <input type="file" name="file" id="file" ref="fileInput" | |
422 | + @change="fileInput()" /> | |
423 | + </td> | |
424 | + </tr> | |
425 | + </tbody> | |
426 | + </table> | |
427 | + <div class="modal-end flex justify-between" style="flex-wrap: nowrap"> | |
428 | + <button class="blue-btn large-btn" @click="upload()">확인</button> | |
429 | + <button class="gray-btn large-btn" @click="closeModal()"> | |
430 | + 취소 | |
431 | + </button> | |
432 | + </div> | |
433 | + </div> | |
434 | + </div> | |
435 | + </template> | |
436 | + <!-- DB (db-modal) --> | |
437 | + <DatabaseConnection v-if="modalType == 'db-modal'" openPopup="true" :jobItem="selectNode" | |
438 | + @closePopup="closeModal" @saveNodeData="fnUpdateSetup" /> | |
439 | + <!-- API (api-modal) --> | |
440 | + <apiConnection v-if="modalType == 'api-modal'" openPopup="true" :jobItem="selectNode" | |
441 | + @fnCloseModal="closeModal" @fnSaveSetup="fnUpdateSetup" /> | |
442 | + <!-- 차세대 API (ehojo-modal) --> | |
443 | + <EhojoConnection v-if="modalType == 'ehojo-modal'" openPopup="true" :jobItem="selectNode" | |
444 | + @fnCloseModal="closeModal" @fnSaveSetup="fnUpdateSetup" /> | |
445 | + <div class="modal-end flex justify-end" v-show="modalType == 'test-modal'" style="flex-wrap: nowrap"> | |
446 | + <button class="gray-border-btn small-btn" @click="closeModal"> | |
447 | + 이전 | |
448 | + </button> | |
449 | + <button class="blue-border-btn small-btn" @click="closeModal"> | |
450 | + 확인 | |
451 | + </button> | |
452 | + <button class="darkg-border-btn small-btn" @click="closeModal"> | |
453 | + 닫기 | |
454 | + </button> | |
455 | + </div> | |
456 | + </div> | |
457 | + </div> | |
458 | +</template> | |
459 | +<script> | |
460 | +import axios from "axios"; | |
461 | +import TreeItem from "../../../component/FileTree.vue"; | |
462 | +import TreeModal from "../../../component/FileTreeModal.vue"; | |
463 | +import SvgIcon from "@jamescoyle/vue-icon"; | |
464 | +import DatabaseConnection from "../../../component/connection/itm/databaseConnection.vue"; | |
465 | +import apiConnection from "../../../component/connection/itm/apiConnection.vue"; | |
466 | +import EhojoConnection from "../../../component/connection/EhojoConnection.vue"; | |
467 | +import { | |
468 | + mdiMagnify, | |
469 | + mdiClose, | |
470 | + mdiFileCog, | |
471 | + mdiDownload, | |
472 | + mdiFileFind, | |
473 | + mdiClockPlusOutline, | |
474 | +} from "@mdi/js"; | |
475 | +import store from "../../AppStore"; | |
476 | +import FileDataRead from "../../../component/connection/itm/fileDataRead.vue"; | |
477 | +import * as XLSX from "xlsx"; | |
478 | + | |
479 | +export default { | |
480 | + data() { | |
481 | + return { | |
482 | + //엑셀 등록시 타입지정 | |
483 | + isOpenExcel: false, | |
484 | + encodingType: null, | |
485 | + // 검색 객체 | |
486 | + search: this.$getDefaultSerchVO(), | |
487 | + search_data: this.$getDefaultSerchItem(null, "String"), | |
488 | + | |
489 | + userauth: null, | |
490 | + searchPath: mdiMagnify, | |
491 | + closePath: mdiClose, | |
492 | + fileNamePath: mdiFileCog, | |
493 | + filedownPath: mdiDownload, | |
494 | + fileFindPath: mdiFileFind, | |
495 | + isModalOpen: false, | |
496 | + activeTab: "tab1", | |
497 | + modalType: "", | |
498 | + modalSize: "small", | |
499 | + mkdirModalOpen: false, | |
500 | + reNameModalOpen: false, | |
501 | + treeModalOpen: false, | |
502 | + | |
503 | + selectedHost: {}, | |
504 | + selectedHostCode: null, | |
505 | + // 호스트 목록 | |
506 | + hostList: [], | |
507 | + // 부서-호스트 목록 | |
508 | + //01.17 deptHostList: [], | |
509 | + connection: { | |
510 | + host_code: null, | |
511 | + path: null, | |
512 | + depth: null, | |
513 | + type: null, | |
514 | + }, | |
515 | + | |
516 | + selectedTab: '', // 현재 선택된 탭 | |
517 | + | |
518 | + uploadObject: { | |
519 | + host_code: null, | |
520 | + path: null, | |
521 | + uploadFile: null, | |
522 | + confirm: false, | |
523 | + }, | |
524 | + nodes: [], | |
525 | + fileList: [], | |
526 | + selectedNode: null, | |
527 | + folderName: null, | |
528 | + uploadFile: null, | |
529 | + | |
530 | + reNameObject: { | |
531 | + currentPath: null, | |
532 | + parentPath: null, | |
533 | + currentName: null, | |
534 | + extension: null, | |
535 | + changeName: null, | |
536 | + }, | |
537 | + checkAll: false, | |
538 | + selectedFiles: [], | |
539 | + modalNodes: [], | |
540 | + modalConnection: { | |
541 | + host_code: null, | |
542 | + path: null, | |
543 | + depth: null, | |
544 | + type: null, | |
545 | + }, | |
546 | + modalSeletedNode: null, | |
547 | + selectModalType: 0, | |
548 | + | |
549 | + searchType: "all", | |
550 | + searchText: null, | |
551 | + | |
552 | + selectItem: { | |
553 | + id: null, | |
554 | + }, | |
555 | + | |
556 | + // 데이터 미리보기 | |
557 | + isLoading: false, | |
558 | + previewModalOpen: false, | |
559 | + dataTable: {}, | |
560 | + | |
561 | + selectNode: {}, // 선택된 노드 | |
562 | + | |
563 | + selectedHostCodeData: null, | |
564 | + selectedDirectory: null, | |
565 | + selectedHostData: null, | |
566 | + isUpdating: false // 무한 루프 방지를 위한 플래그 | |
567 | + }; | |
568 | + }, | |
569 | + methods: { | |
570 | + // 검색 객체 초기화 | |
571 | + searchInit: function () { | |
572 | + this.search.searchObjectList.push(this.search_data); | |
573 | + }, | |
574 | + | |
575 | + searchFiles() { | |
576 | + const vm = this; | |
577 | + | |
578 | + if (vm.searchText === null || vm.searchText === "") { | |
579 | + vm.$showAlert("파일 검색", "검색어를 입력해 주세요."); | |
580 | + return; | |
581 | + } | |
582 | + | |
583 | + let path = vm.connection.path; | |
584 | + | |
585 | + if (vm.searchType === "all") { | |
586 | + path = "#"; | |
587 | + } else { | |
588 | + if (!path) { | |
589 | + vm.$showAlert("파일 검색", "폴더를 선택해 주세요."); | |
590 | + return; | |
591 | + } | |
592 | + } | |
593 | + | |
594 | + vm.isLoading = true; // 로딩 시작 | |
595 | + | |
596 | + axios({ | |
597 | + url: "/files/search/" + vm.connection.host_code, | |
598 | + method: "post", | |
599 | + headers: {}, | |
600 | + data: { | |
601 | + searchType: vm.searchType, | |
602 | + searchText: vm.searchText, | |
603 | + path: path, | |
604 | + }, | |
605 | + }) | |
606 | + .then(function (response) { | |
607 | + vm.isLoading = false; // 로딩 해제 | |
608 | + vm.fileList = response.data.resultData.fileList; | |
609 | + if (vm.fileList.length == 0) { | |
610 | + vm.$showAlert("파일 검색", "검색 결과가 없습니다."); | |
611 | + } | |
612 | + }) | |
613 | + .catch(function (error) { | |
614 | + vm.isLoading = false; // 로딩 해제 | |
615 | + vm.$showAlert( | |
616 | + "파일 검색", | |
617 | + "파일 검색 오류, 관리자에게 문의바랍니다." | |
618 | + ); | |
619 | + }); | |
620 | + }, | |
621 | + | |
622 | + // 로딩 상태 변경 | |
623 | + handleIsLoading(isLoadingValue) { | |
624 | + this.isLoading = isLoadingValue; // 부모 컴포넌트의 데이터 업데이트 | |
625 | + }, | |
626 | + | |
627 | + // 탭 변경 | |
628 | + showTab: function (tabName) { | |
629 | + this.activeTab = tabName; | |
630 | + }, | |
631 | + openModal: function () { | |
632 | + this.isModalOpen = true; | |
633 | + }, | |
634 | + closeModal: function () { | |
635 | + // this.selectNode = {}; // 초기화 | |
636 | + this.modalType = null; | |
637 | + this.isModalOpen = false; | |
638 | + }, | |
639 | + setModal: function (type, size) { | |
640 | + if (type == "typeSelected") { | |
641 | + if ( | |
642 | + this.connection.path == null || | |
643 | + this.connection.path == "" || | |
644 | + this.connection.path === undefined | |
645 | + ) { | |
646 | + this.$showAlert("폴더 추가", "폴더를 선택해 주세요."); | |
647 | + return; | |
648 | + } | |
649 | + } else if (type == "db-modal") { | |
650 | + this.fnCreateNode("DB_READ"); | |
651 | + } else if (type == "api-modal") { | |
652 | + this.fnCreateNode("API_READ"); | |
653 | + } else if (type == "ehojo-modal") { | |
654 | + this.fnCreateNode("EHOJO_READ"); | |
655 | + } | |
656 | + this.modalType = type; | |
657 | + this.modalSize = size; | |
658 | + }, | |
659 | + | |
660 | + openMkdirModal() { | |
661 | + if ( | |
662 | + this.connection.path == null || | |
663 | + this.connection.path == "" || | |
664 | + this.connection.path === undefined | |
665 | + ) { | |
666 | + this.$showAlert("폴더 추가", "폴더를 선택해 주세요."); | |
667 | + return; | |
668 | + } | |
669 | + this.mkdirModalOpen = true; | |
670 | + }, | |
671 | + | |
672 | + closeMkdirModal() { | |
673 | + this.mkdirModalOpen = false; | |
674 | + }, | |
675 | + | |
676 | + openTreeModal(type) { | |
677 | + if (this.selectedFiles.length === 0) { | |
678 | + if (type === "move") { | |
679 | + this.$showAlert("파일 이동", "선택한 파일이 없습니다."); | |
680 | + } else if (type === "copy") { | |
681 | + this.$showAlert("파일 복사", "선택한 파일이 없습니다."); | |
682 | + } | |
683 | + return; | |
684 | + } | |
685 | + | |
686 | + this.treeModalOpen = true; | |
687 | + this.selectModalType = type; | |
688 | + }, | |
689 | + | |
690 | + closeTreeModal() { | |
691 | + // this.modalNodes = []; | |
692 | + this.treeModalOpen = false; | |
693 | + this.modalSeletedNode = null; | |
694 | + }, | |
695 | + | |
696 | + openReNameModal(file) { | |
697 | + this.reNameObject.currentPath = file.path; | |
698 | + this.reNameObject.parentPath = file.parent; | |
699 | + this.reNameObject.currentName = file.text; | |
700 | + this.reNameObject.extension = file.extension; | |
701 | + this.reNameModalOpen = true; | |
702 | + }, | |
703 | + | |
704 | + closeReNameModal() { | |
705 | + this.reNameObject.changeName = null; | |
706 | + this.reNameModalOpen = false; | |
707 | + }, | |
708 | + | |
709 | + filesCheckAll() { | |
710 | + this.checkAll = !this.checkAll; | |
711 | + | |
712 | + if (this.checkAll) { | |
713 | + this.fileList.forEach((file) => { | |
714 | + if (file.text != "상위폴더로 이동") { | |
715 | + this.selectedFiles.push({ | |
716 | + folder: file.folder, | |
717 | + path: file.path, | |
718 | + fileName: file.text, | |
719 | + extension: file.extension, | |
720 | + }); | |
721 | + } | |
722 | + }); | |
723 | + } else { | |
724 | + this.selectedFiles = []; | |
725 | + } | |
726 | + }, | |
727 | + | |
728 | + // 선택한 호스트 연결 | |
729 | + async connectionConfirm() { | |
730 | + const vm = this; | |
731 | + if (vm.selectedHostCode === null || vm.selectedHostCode === undefined) { | |
732 | + vm.$showAlert("파일시스템 연결", "호스트를 선택해 주세요."); | |
733 | + return; | |
734 | + } | |
735 | + | |
736 | + // 이전에 선택한 호스트 코드가 있으면 저장 | |
737 | + let tempHostCode = null; | |
738 | + let tempModalHostCode = null; | |
739 | + if (vm.connection.host_code) { | |
740 | + tempHostCode = _.cloneDeep(vm.connection.host_code); | |
741 | + tempModalHostCode = _.cloneDeep(vm.modalConnection.host_code); | |
742 | + } | |
743 | + | |
744 | + vm.connection.host_code = vm.selectedHost.host_code; | |
745 | + vm.modalConnection.host_code = vm.selectedHost.host_code; | |
746 | + | |
747 | + vm.isLoading = true; // 로딩 시작 | |
748 | + | |
749 | + try { | |
750 | + const response = await axios.get("/files/connection", { | |
751 | + params: { host_code: vm.connection.host_code }, | |
752 | + }); | |
753 | + | |
754 | + vm.isLoading = false; // 로딩 해제 | |
755 | + if (response.data.status === 200) { | |
756 | + await this.fileTreeList(); | |
757 | + } else { | |
758 | + // 이전에 선택한 호스트 코드로 변경 | |
759 | + if (tempHostCode) { | |
760 | + vm.connection.host_code = tempHostCode; | |
761 | + vm.selectedHost.host_code = tempHostCode; | |
762 | + vm.selectedHostCode = tempHostCode; | |
763 | + } | |
764 | + } | |
765 | + this.selectedFiles = []; | |
766 | + this.checkAll = false; | |
767 | + vm.$showAlert("파일시스템 연결", response.data.message); | |
768 | + } catch (error) { | |
769 | + vm.isLoading = false; // 로딩 해제 | |
770 | + vm.$showAlert( | |
771 | + "파일시스템 연결", | |
772 | + "파일시스템 연결 오류, 관리자에게 문의하세요." | |
773 | + ); | |
774 | + this.selectedFiles = []; | |
775 | + this.checkAll = false; | |
776 | + // 이전에 선택한 호스트 코드로 변경 | |
777 | + if (tempHostCode) { | |
778 | + vm.connection.host_code = tempHostCode; | |
779 | + vm.selectedHost.host_code = tempHostCode; | |
780 | + vm.selectedHostCode = tempHostCode; | |
781 | + } | |
782 | + } | |
783 | + }, | |
784 | + uniquePaths() { | |
785 | + // this.selectedHost = null; | |
786 | + this.selectedHost = this.selectedHostData; | |
787 | + this.selectedHostCode = this.selectedHostData.host_code; | |
788 | + this.connectionConfirm(); | |
789 | + }, | |
790 | + // 호스트 목록 조회 | |
791 | + selectHosts() { | |
792 | + const vm = this; | |
793 | + vm.isLoading = true; // 로딩 시작 | |
794 | + axios({ | |
795 | + url: "/files/hosts", | |
796 | + method: "post", | |
797 | + headers: { | |
798 | + "Content-Type": "application/json; charset=UTF-8", | |
799 | + }, | |
800 | + data: { | |
801 | + userId: store.state.loginUser.user_id, | |
802 | + author: store.state.loginUser.user_auth[0], | |
803 | + dept_code: store.state.loginUser.dept_code, | |
804 | + }, | |
805 | + }) | |
806 | + .then((response) => { | |
807 | + vm.hostList = response.data.resultData.hostList; | |
808 | + console.log("@@", vm.hostList); | |
809 | + if (this.hostList.length > 0) { | |
810 | + vm.selectedHost = vm.hostList[0]; | |
811 | + vm.selectedHostCode = vm.hostList[0].host_code; | |
812 | + vm.selectedHostCodeData = 0; | |
813 | + vm.selectedDirectory = 0; | |
814 | + vm.selectedHostData = vm.hostList[0]; | |
815 | + vm.connectionConfirm(); | |
816 | + } else { | |
817 | + vm.isLoading = false; // 로딩 해제 | |
818 | + vm.selectedHost = {}; | |
819 | + } | |
820 | + }) | |
821 | + .catch((error) => { | |
822 | + vm.isLoading = false; // 로딩 해제 | |
823 | + vm.$showAlert( | |
824 | + "호스트 조회", | |
825 | + "호스트 조회 오류, 관리자에게 문의하세요." | |
826 | + ); | |
827 | + }); | |
828 | + }, | |
829 | + | |
830 | + // 폴더 리스트 조회 | |
831 | + async fileTreeList() { | |
832 | + const vm = this; | |
833 | + vm.nodes = []; | |
834 | + vm.connection.path = vm.selectedHost.dept_drctry_path; | |
835 | + vm.connection.depth = 0; | |
836 | + vm.connection.type = "folder"; | |
837 | + vm.modalNodes = []; | |
838 | + vm.modalConnection.path = vm.selectedHost.dept_drctry_path; | |
839 | + vm.modalConnection.depth = 0; | |
840 | + vm.modalConnection.type = "folder"; | |
841 | + vm.modalConnection.host_code = vm.connection.host_code; | |
842 | + | |
843 | + vm.isLoading = true; // 로딩 시작 | |
844 | + | |
845 | + try { | |
846 | + const response = await axios.get("/files/tree", { | |
847 | + params: vm.connection, | |
848 | + }); | |
849 | + | |
850 | + vm.nodes = response.data.resultData.fileTree; | |
851 | + vm.modalNodes = response.data.resultData.fileTree; | |
852 | + vm.connection.path = null; | |
853 | + vm.fileList = []; | |
854 | + this.checkAll = false; | |
855 | + vm.isLoading = false; // 로딩 해제 | |
856 | + } catch (error) { | |
857 | + vm.connection.path = null; | |
858 | + vm.fileList = []; | |
859 | + this.checkAll = false; | |
860 | + vm.isLoading = false; // 로딩 해제 | |
861 | + vm.$showAlert( | |
862 | + "파일리스트 조회", | |
863 | + "파일리스트 조회 오류, 관리자에게 문의하세요." | |
864 | + ); | |
865 | + } | |
866 | + }, | |
867 | + | |
868 | + modalFileTreeList() { | |
869 | + const vm = this; | |
870 | + | |
871 | + vm.modalNodes = []; | |
872 | + | |
873 | + vm.modalConnection.host_code = vm.connection.host_code; | |
874 | + vm.modalConnection.path = "#"; | |
875 | + vm.modalConnection.depth = 0; | |
876 | + vm.modalConnection.type = "folder"; | |
877 | + | |
878 | + axios | |
879 | + .get("/files/tree", { params: vm.modalConnection }) | |
880 | + .then((response) => { | |
881 | + vm.modalNodes = response.data.resultData.fileTree; | |
882 | + }) | |
883 | + .catch((error) => { | |
884 | + vm.$showAlert( | |
885 | + "파일리스트 조회", | |
886 | + "파일리스트 조회 오류, 관리자에게 문의하세요." | |
887 | + ); | |
888 | + }); | |
889 | + }, | |
890 | + | |
891 | + selectFolder(path) { | |
892 | + if (path === null || path === undefined) { | |
893 | + this.isLoading = false; | |
894 | + } | |
895 | + this.connection.path = path; | |
896 | + this.fileSelectList(); | |
897 | + }, | |
898 | + | |
899 | + handleSelectItem(item) { | |
900 | + this.selectItem = item; | |
901 | + }, | |
902 | + | |
903 | + modalSelectFolder(path) { | |
904 | + this.modalSeletedNode = path; | |
905 | + }, | |
906 | + | |
907 | + selectFileList(item) { | |
908 | + // 폴더가 선택된 경우, 선택된 노드와 경로를 업데이트하고 파일 리스트 조회 | |
909 | + if (item.extension === "폴더" || item.extension === "") { | |
910 | + this.selectedNode = item.id; | |
911 | + this.connection.path = item.id; | |
912 | + this.fileSelectList(); | |
913 | + } else { | |
914 | + } | |
915 | + }, | |
916 | + | |
917 | + // 파일 리스트 조회 | |
918 | + async fileSelectList() { | |
919 | + const vm = this; | |
920 | + | |
921 | + if (vm.connection.path === null || vm.connection.path === "") { | |
922 | + vm.fileList = null; | |
923 | + return; | |
924 | + } | |
925 | + | |
926 | + vm.connection.type = "all"; | |
927 | + vm.connection.depth = 1; | |
928 | + | |
929 | + vm.isLoading = true; // 로딩 시작 | |
930 | + try { | |
931 | + const response = await axios.get("/files/list", { | |
932 | + params: vm.connection, | |
933 | + }); | |
934 | + vm.fileList = response.data.resultData.fileList; | |
935 | + vm.search.totalRows = response.data.resultData.totalRow; | |
936 | + vm.selectedFiles = []; | |
937 | + vm.checkAll = false; | |
938 | + vm.isLoading = false; // 로딩 해제 | |
939 | + } catch (error) { | |
940 | + vm.isLoading = false; // 로딩 해제 | |
941 | + vm.$showAlert( | |
942 | + "파일리스트 조회", | |
943 | + "파일리스트 조회 오류, 관리자에게 문의하세요." | |
944 | + ); | |
945 | + vm.selectedFiles = []; | |
946 | + vm.checkAll = false; | |
947 | + } | |
948 | + }, | |
949 | + | |
950 | + // 폴더 추가 | |
951 | + async mkdir() { | |
952 | + const vm = this; | |
953 | + if (vm.connection.path === null || vm.connection.path === "") { | |
954 | + vm.$showAlert( | |
955 | + "폴더 추가", | |
956 | + "선택된 경로가 없습니다.\n 경로 선택 후 다시 시도해주세요." | |
957 | + ); | |
958 | + vm.closeMkdirModal(); | |
959 | + vm.folderName = null; | |
960 | + return; | |
961 | + } | |
962 | + | |
963 | + const mkdirVO = {}; | |
964 | + mkdirVO.host_code = vm.connection.host_code; | |
965 | + mkdirVO.path = vm.connection.path; | |
966 | + mkdirVO.folderName = vm.folderName; | |
967 | + | |
968 | + vm.isLoading = true; // 로딩 시작 | |
969 | + | |
970 | + try { | |
971 | + const response = await axios.post("/files/mkdir", mkdirVO); | |
972 | + | |
973 | + vm.isLoading = false; // 로딩 해제 | |
974 | + vm.getChildren(vm.selectItem.id, vm.selectItem.children); // 자식 폴더 리스트 업데이트 | |
975 | + await vm.fileSelectList(); | |
976 | + vm.$showAlert("폴더 추가", response.data.message); | |
977 | + vm.closeMkdirModal(); | |
978 | + vm.folderName = null; | |
979 | + } catch (error) { | |
980 | + vm.isLoading = false; // 로딩 해제 | |
981 | + vm.$showAlert("폴더 추가", "폴더 추가 오류, 관리자에게 문의하세요."); | |
982 | + vm.folderName = null; | |
983 | + } | |
984 | + }, | |
985 | + | |
986 | + // 자식 파일 정보 조회 | |
987 | + getChildren(path, children) { | |
988 | + const vm = this; | |
989 | + vm.connection.path = path; | |
990 | + vm.connection.type = "folder"; | |
991 | + vm.connection.depth = 1; | |
992 | + | |
993 | + axios | |
994 | + .get("/files/list", { params: vm.connection }) | |
995 | + .then((response) => { | |
996 | + let childrenList = response.data.resultData.fileList; | |
997 | + | |
998 | + // 기존 배열 초기화 | |
999 | + children.length = 0; | |
1000 | + | |
1001 | + // 새로운 배열의 요소들을 기존 배열에 추가 | |
1002 | + Array.prototype.push.apply(children, childrenList); | |
1003 | + }) | |
1004 | + .catch((error) => { }); | |
1005 | + }, | |
1006 | + | |
1007 | + //파일업로드 | |
1008 | + fileInput() { | |
1009 | + this.uploadFile = this.$refs.fileInput.files[0]; | |
1010 | + }, | |
1011 | + | |
1012 | + async upload() { | |
1013 | + const vm = this; | |
1014 | + vm.uploadObject.path = vm.connection.path; | |
1015 | + vm.uploadObject.host_code = vm.connection.host_code; | |
1016 | + vm.uploadObject.uploadFile = vm.uploadFile; | |
1017 | + vm.isLoading = true; | |
1018 | + | |
1019 | + // 파일 타입 및 인코딩 확인 | |
1020 | + if (vm.uploadFile) { | |
1021 | + const fileName = vm.uploadFile.name.toLowerCase(); | |
1022 | + const isExcel = fileName.endsWith(".xlsx") || fileName.endsWith(".xls"); | |
1023 | + const isCsv = fileName.endsWith(".csv"); | |
1024 | + | |
1025 | + if (isExcel || isCsv) { | |
1026 | + try { | |
1027 | + const fileReader = new FileReader(); | |
1028 | + | |
1029 | + fileReader.onload = function (e) { | |
1030 | + const content = new Uint8Array(e.target.result); | |
1031 | + let encoding = "Unknown"; | |
1032 | + | |
1033 | + // BOM 확인으로 UTF-8 검사 | |
1034 | + if ( | |
1035 | + content.length >= 3 && | |
1036 | + content[0] === 0xef && | |
1037 | + content[1] === 0xbb && | |
1038 | + content[2] === 0xbf | |
1039 | + ) { | |
1040 | + encoding = "UTF-8 with BOM"; | |
1041 | + } else if ( | |
1042 | + content.length >= 2 && | |
1043 | + content[0] === 0xff && | |
1044 | + content[1] === 0xfe | |
1045 | + ) { | |
1046 | + encoding = "UTF-16 LE"; | |
1047 | + } else { | |
1048 | + // 텍스트 분석으로 인코딩 추정 | |
1049 | + try { | |
1050 | + const text = new TextDecoder("UTF-8").decode(content); | |
1051 | + const hasInvalidChars = text.includes("�"); | |
1052 | + encoding = hasInvalidChars ? "Possibly EUC-KR" : "UTF-8"; | |
1053 | + } catch (err) { | |
1054 | + encoding = "Possibly EUC-KR"; | |
1055 | + } | |
1056 | + } | |
1057 | + | |
1058 | + console.log(`파일 타입: ${isExcel ? "Excel" : "CSV"}`); | |
1059 | + console.log(`인코딩 타입: ${encoding}`); | |
1060 | + }; | |
1061 | + | |
1062 | + // 파일의 처음 1KB만 읽어서 분석 | |
1063 | + fileReader.readAsArrayBuffer(vm.uploadFile.slice(0, 1024)); | |
1064 | + } catch (error) { | |
1065 | + console.error("인코딩 확인 중 오류:", error); | |
1066 | + } | |
1067 | + } | |
1068 | + } | |
1069 | + | |
1070 | + try { | |
1071 | + const response = await axios.post("/files/upload", vm.uploadObject, { | |
1072 | + headers: { | |
1073 | + "Content-Type": "multipart/form-data", | |
1074 | + }, | |
1075 | + }); | |
1076 | + | |
1077 | + vm.isLoading = false; | |
1078 | + | |
1079 | + if (response.data.status === 200) { | |
1080 | + document.getElementById("file").value = ""; | |
1081 | + await vm.fileSelectList(); | |
1082 | + vm.$showAlert("파일 업로드", response.data.message); | |
1083 | + } else if (response.data.status === 100) { | |
1084 | + if (!(await vm.$showConfirm("파일 업로드", response.data.message))) { | |
1085 | + document.getElementById("file").value = ""; | |
1086 | + return; | |
1087 | + } else { | |
1088 | + vm.uploadObject.confirm = true; | |
1089 | + await vm.reUpload(); | |
1090 | + } | |
1091 | + } | |
1092 | + | |
1093 | + vm.closeModal(); | |
1094 | + } catch (error) { | |
1095 | + vm.isLoading = false; | |
1096 | + vm.$showAlert( | |
1097 | + "파일 업로드", | |
1098 | + "파일 업로드 오류, 관리자에게 문의하세요." | |
1099 | + ); | |
1100 | + vm.uploadObject.confirm = false; | |
1101 | + document.getElementById("file").value = ""; | |
1102 | + } | |
1103 | + }, | |
1104 | + | |
1105 | + async reUpload() { | |
1106 | + const vm = this; | |
1107 | + vm.isLoading = true; // 로딩 시작 | |
1108 | + | |
1109 | + try { | |
1110 | + const response = await axios.post("/files/upload", vm.uploadObject, { | |
1111 | + headers: { | |
1112 | + "Content-Type": "multipart/form-data", | |
1113 | + }, | |
1114 | + }); | |
1115 | + | |
1116 | + vm.isLoading = false; // 로딩 종료 | |
1117 | + await vm.fileSelectList(); | |
1118 | + vm.$showAlert("파일 업로드", response.data.message); | |
1119 | + vm.uploadObject.confirm = false; | |
1120 | + document.getElementById("file").value = ""; | |
1121 | + } catch (error) { | |
1122 | + vm.isLoading = false; // 로딩 종료 | |
1123 | + vm.$showAlert( | |
1124 | + "파일 업로드", | |
1125 | + "파일 업로드 오류, 관리자에게 문의하세요." | |
1126 | + ); | |
1127 | + vm.uploadObject.confirm = false; | |
1128 | + document.getElementById("file").value = ""; | |
1129 | + } | |
1130 | + }, | |
1131 | + | |
1132 | + download(file) { | |
1133 | + const vm = this; | |
1134 | + | |
1135 | + vm.isLoading = true; // 로딩 시작 | |
1136 | + | |
1137 | + axios | |
1138 | + .post("/files/download", { | |
1139 | + host_code: vm.connection.host_code, | |
1140 | + path: file.parent, | |
1141 | + fileName: file.text, | |
1142 | + }) | |
1143 | + .then((response) => { | |
1144 | + vm.isLoading = false; // 로딩 해제 | |
1145 | + vm.$showAlert("파일 다운로드", response.data.message); | |
1146 | + }) | |
1147 | + .catch((error) => { | |
1148 | + vm.isLoading = false; // 로딩 해제 | |
1149 | + vm.$showAlert( | |
1150 | + "파일 다운로드", | |
1151 | + "파일 다운로드 오류, 관리자에게 문의하세요." | |
1152 | + ); | |
1153 | + }); | |
1154 | + }, | |
1155 | + | |
1156 | + async rename() { | |
1157 | + const vm = this; | |
1158 | + | |
1159 | + if (vm.reNameObject.changeName === null) { | |
1160 | + vm.$showAlert("이름 바꾸기", "변경할 이름을 입력해주세요."); | |
1161 | + return; | |
1162 | + } | |
1163 | + | |
1164 | + let fullName = | |
1165 | + vm.reNameObject.changeName + "." + vm.reNameObject.extension; | |
1166 | + | |
1167 | + if (vm.reNameObject.extension === "폴더") { | |
1168 | + fullName = vm.reNameObject.changeName; | |
1169 | + } | |
1170 | + | |
1171 | + vm.isLoading = true; // 로딩 시작 | |
1172 | + | |
1173 | + try { | |
1174 | + const response = await axios.put("/files/rename", { | |
1175 | + host_code: vm.connection.host_code, | |
1176 | + currentPath: vm.reNameObject.currentPath, | |
1177 | + changePath: vm.reNameObject.parentPath + "/" + fullName, | |
1178 | + }); | |
1179 | + | |
1180 | + vm.isLoading = false; // 로딩 해제 | |
1181 | + vm.reNameObject.changeName = null; | |
1182 | + await vm.fileSelectList(); | |
1183 | + vm.$showAlert("이름 바꾸기", response.data.message); | |
1184 | + vm.closeReNameModal(); | |
1185 | + } catch (error) { | |
1186 | + vm.isLoading = false; // 로딩 해제 | |
1187 | + vm.$showAlert( | |
1188 | + "이름 바꾸기", | |
1189 | + "이름 바꾸기 오류, 관리자에게 문의하세요." | |
1190 | + ); | |
1191 | + vm.closeReNameModal(); | |
1192 | + vm.reNameObject.changeName = null; | |
1193 | + } | |
1194 | + }, | |
1195 | + | |
1196 | + async remove() { | |
1197 | + const vm = this; | |
1198 | + | |
1199 | + if (vm.selectedFiles.length === 0) { | |
1200 | + vm.$showAlert("파일 삭제", "선택한 파일이 없습니다."); | |
1201 | + return; | |
1202 | + } | |
1203 | + | |
1204 | + if ( | |
1205 | + !(await vm.$showConfirm("파일 삭제", "선택한 파일을 삭제하시겠습니까?")) | |
1206 | + ) { | |
1207 | + return; | |
1208 | + } | |
1209 | + | |
1210 | + vm.selectedFiles.forEach((file) => { | |
1211 | + delete file.fileName; | |
1212 | + delete file.extension; | |
1213 | + }); | |
1214 | + vm.isLoading = true; // 로딩 시작 | |
1215 | + try { | |
1216 | + const response = await axios.delete( | |
1217 | + `/files/${vm.connection.host_code}`, | |
1218 | + { data: vm.selectedFiles } | |
1219 | + ); | |
1220 | + | |
1221 | + vm.isLoading = false; | |
1222 | + vm.getChildren(vm.selectItem.id, vm.selectItem.children); // 자식 폴더 리스트 업데이트 | |
1223 | + await vm.fileSelectList(); | |
1224 | + vm.$showAlert("파일 삭제", response.data.message); | |
1225 | + vm.checkAll = false; | |
1226 | + vm.selectedFiles = []; | |
1227 | + } catch (error) { | |
1228 | + vm.isLoading = false; | |
1229 | + vm.$showAlert("파일 삭제", "파일 삭제 오류, 관리자에게 문의하세요."); | |
1230 | + vm.checkAll = false; | |
1231 | + vm.selectedFiles = []; | |
1232 | + } | |
1233 | + }, | |
1234 | + | |
1235 | + async fileConfirm(type) { | |
1236 | + const vm = this; | |
1237 | + | |
1238 | + if ( | |
1239 | + !(await vm.$showConfirm( | |
1240 | + "파일 " + type, | |
1241 | + "선택한 파일을 " + type + " 하시겠습니까?" | |
1242 | + )) | |
1243 | + ) { | |
1244 | + return; | |
1245 | + } | |
1246 | + | |
1247 | + let file = vm.selectedFiles[0]; | |
1248 | + let index = file.path.lastIndexOf("/"); | |
1249 | + | |
1250 | + if (file.path.substring(0, index) === file.movePath) { | |
1251 | + vm.$showAlert( | |
1252 | + "파일 " + type, | |
1253 | + "현재 파일 경로와 동일합니다. 다른 경로를 선택해주세요." | |
1254 | + ); | |
1255 | + return; | |
1256 | + } | |
1257 | + | |
1258 | + if (type === "복사") { | |
1259 | + vm.copy(vm.selectedFiles, "confirm", false); | |
1260 | + } else { | |
1261 | + vm.move(vm.selectedFiles, [], "confirm", false); | |
1262 | + } | |
1263 | + }, | |
1264 | + async move(fileList, removeFolderList, type, check) { | |
1265 | + const vm = this; | |
1266 | + | |
1267 | + fileList.forEach((file) => { | |
1268 | + if (!file.movePath) { | |
1269 | + file.movePath = vm.modalSeletedNode; | |
1270 | + } | |
1271 | + }); | |
1272 | + | |
1273 | + vm.isLoading = true; // 로딩 시작 | |
1274 | + try { | |
1275 | + const response = await axios.put( | |
1276 | + "/files/move/" + vm.connection.host_code, | |
1277 | + { | |
1278 | + fileList: fileList, | |
1279 | + removeFolder: removeFolderList, | |
1280 | + type: type, | |
1281 | + check: check, | |
1282 | + } | |
1283 | + ); | |
1284 | + | |
1285 | + vm.isLoading = false; // 로딩 해제 | |
1286 | + if (response.data.checkMessage.status === 100) { | |
1287 | + let returnFileList = response.data.resultData.fileList; | |
1288 | + let folderList = response.data.resultData.removeFolderList; | |
1289 | + const moveOrCopy = await vm.$showRadioConfirm( | |
1290 | + "파일 이동", | |
1291 | + response.data.checkMessage.message | |
1292 | + ); | |
1293 | + vm.move( | |
1294 | + returnFileList, | |
1295 | + folderList, | |
1296 | + moveOrCopy.type, | |
1297 | + moveOrCopy.checkBox | |
1298 | + ); | |
1299 | + } else { | |
1300 | + let folderList = response.data.resultData.removeFolderList; | |
1301 | + vm.checkAll = false; | |
1302 | + vm.selectedFiles = []; | |
1303 | + | |
1304 | + if (folderList.length != 0) { | |
1305 | + vm.removeFolder(folderList); | |
1306 | + } else { | |
1307 | + await vm.fileSelectList(); | |
1308 | + } | |
1309 | + vm.$showAlert("파일 이동", response.data.checkMessage.message); | |
1310 | + vm.closeTreeModal(); | |
1311 | + } | |
1312 | + } catch (error) { | |
1313 | + vm.isLoading = false; // 로딩 해제 | |
1314 | + vm.$showAlert("파일 이동", "파일 이동 오류, 관리자에게 문의하세요."); | |
1315 | + vm.checkAll = false; | |
1316 | + vm.selectedFiles = []; | |
1317 | + vm.closeTreeModal(); | |
1318 | + } | |
1319 | + }, | |
1320 | + | |
1321 | + async copy(fileList, type, check) { | |
1322 | + const vm = this; | |
1323 | + | |
1324 | + fileList.forEach((file) => { | |
1325 | + if (!file.movePath) { | |
1326 | + file.movePath = vm.modalSeletedNode; | |
1327 | + } | |
1328 | + }); | |
1329 | + | |
1330 | + vm.isLoading = true; // 로딩 시작 | |
1331 | + try { | |
1332 | + const response = await axios.put( | |
1333 | + "/files/copy/" + vm.connection.host_code, | |
1334 | + { fileList: fileList, type: type, check: check } | |
1335 | + ); | |
1336 | + | |
1337 | + vm.isLoading = false; // 로딩 해제 | |
1338 | + if (response.data.checkMessage.status === 100) { | |
1339 | + let returnFileList = response.data.resultData.fileList; | |
1340 | + const moveOrCopy = await vm.$showRadioConfirm( | |
1341 | + "파일 복사", | |
1342 | + response.data.checkMessage.message | |
1343 | + ); | |
1344 | + vm.copy(returnFileList, moveOrCopy.type, moveOrCopy.checkBox); | |
1345 | + } else { | |
1346 | + vm.$showAlert("파일 복사", response.data.checkMessage.message); | |
1347 | + vm.checkAll = false; | |
1348 | + vm.selectedFiles = []; | |
1349 | + vm.closeTreeModal(); | |
1350 | + } | |
1351 | + } catch (error) { | |
1352 | + vm.isLoading = false; // 로딩 해제 | |
1353 | + vm.$showAlert("파일 복사", "파일 이동 오류, 관리자에게 문의하세요."); | |
1354 | + vm.checkAll = false; | |
1355 | + vm.selectedFiles = []; | |
1356 | + vm.closeTreeModal(); | |
1357 | + } | |
1358 | + }, | |
1359 | + | |
1360 | + async removeFolder(folderList) { | |
1361 | + const vm = this; | |
1362 | + | |
1363 | + vm.isLoading = false; // 로딩 해제 | |
1364 | + | |
1365 | + try { | |
1366 | + const response = await axios.delete( | |
1367 | + "/files/folder/" + vm.connection.host_code, | |
1368 | + { data: folderList } | |
1369 | + ); | |
1370 | + | |
1371 | + vm.isLoading = false; // 로딩 해제 | |
1372 | + vm.getChildren(vm.selectItem.id, vm.selectItem.children); // 자식 폴더 리스트 업데이트 | |
1373 | + await vm.fileSelectList(); | |
1374 | + if (response.data.status === 500) { | |
1375 | + vm.$showAlert("파일 이동", response.data.message); | |
1376 | + } | |
1377 | + } catch (error) { | |
1378 | + vm.isLoading = false; // 로딩 해제 | |
1379 | + vm.$showAlert( | |
1380 | + "파일 이동", | |
1381 | + "원본 폴더 삭제 오류, 관리자에게 문의하세요." | |
1382 | + ); | |
1383 | + } | |
1384 | + }, | |
1385 | + | |
1386 | + // 미리보기 모달 닫기 | |
1387 | + previewModalClose() { | |
1388 | + this.previewModalOpen = false; | |
1389 | + this.dataTable = {}; | |
1390 | + }, | |
1391 | + | |
1392 | + // 파일 미리보기 | |
1393 | + preview(file) { | |
1394 | + // 허용된 파일 확장자 검사 | |
1395 | + const allowedExtensions = ["xlsx", "xls", "csv", "json"]; | |
1396 | + | |
1397 | + if (!allowedExtensions.includes(file.extension.toLowerCase())) { | |
1398 | + this.$showAlert( | |
1399 | + "파일 미리보기", | |
1400 | + "엑셀, CSV, JSON 파일만 읽을 수 있습니다." | |
1401 | + ); | |
1402 | + return; | |
1403 | + } | |
1404 | + | |
1405 | + this.previewModalOpen = true; | |
1406 | + this.fileRead(file); | |
1407 | + }, | |
1408 | + | |
1409 | + // 파일 미리보기 - 읽기 | |
1410 | + async fileRead(file) { | |
1411 | + const vm = this; | |
1412 | + vm.isLoading = true; | |
1413 | + axios | |
1414 | + .post("/files/read/" + vm.connection.host_code, { | |
1415 | + path: file.path, | |
1416 | + fileName: file.text, | |
1417 | + extension: file.extension, | |
1418 | + type: "file", | |
1419 | + datasetId: "", | |
1420 | + viewMode: true, | |
1421 | + }) | |
1422 | + .then((response) => { | |
1423 | + vm.dataTable = response.data.resultData.dataTableMap; | |
1424 | + }) | |
1425 | + .catch(() => { | |
1426 | + vm.isLoading = false; | |
1427 | + }); | |
1428 | + }, | |
1429 | + selectEncoding(encoding) { | |
1430 | + // 선택한 인코딩에 대한 처리 | |
1431 | + this.encodingType = encoding; | |
1432 | + console.log(`${encoding} 인코딩이 선택되었습니다.`); | |
1433 | + this.closeExcel(); // 선택 후 모달 닫기 | |
1434 | + }, | |
1435 | + closeExcel() { | |
1436 | + this.isOpenExcel = false; // 모달 상태를 false로 설정+ | |
1437 | + this.exportToCSV(); | |
1438 | + }, | |
1439 | + // 노드 설정 저장 후 닫기 | |
1440 | + fnUpdateSetup(jobItem) { | |
1441 | + console.log("값을 보자 ", jobItem); | |
1442 | + if ( | |
1443 | + !jobItem.dataTable.rowData || | |
1444 | + jobItem.dataTable.rowData.length === 0 | |
1445 | + ) { | |
1446 | + // rowData가 null이거나 빈 리스트일 때 실행할 코드 | |
1447 | + this.$showAlert("엑셀 생성 실패", "저장된 데이터가 없습니다."); | |
1448 | + } else { | |
1449 | + this.closeModal(); // 괄호 추가 | |
1450 | + this.isOpenExcel = true; | |
1451 | + this.selectNode = jobItem; | |
1452 | + } | |
1453 | + }, | |
1454 | + async exportToCSV() { | |
1455 | + const vm = this; | |
1456 | + | |
1457 | + try { | |
1458 | + // 컬럼 헤더 생성 | |
1459 | + console.log() | |
1460 | + const header = this.selectNode.dataTable.columnDatas.map( | |
1461 | + (col) => col.displyColumnNm | |
1462 | + ); | |
1463 | + | |
1464 | + // 데이터 준비 (rowData를 객체로 변환) | |
1465 | + const data = this.selectNode.dataTable.rowData.map((row) => { | |
1466 | + const rowObject = {}; | |
1467 | + this.selectNode.dataTable.columnDatas.forEach((col, index) => { | |
1468 | + rowObject[col.displyColumnNm] = row[index]; | |
1469 | + }); | |
1470 | + return rowObject; | |
1471 | + }); | |
1472 | + | |
1473 | + // CSV 데이터 생성 | |
1474 | + const csvContent = [ | |
1475 | + header.join(","), | |
1476 | + ...data.map((row) => | |
1477 | + header | |
1478 | + .map((col) => { | |
1479 | + // null, undefined 처리 및 쉼표가 포함된 데이터 처리 | |
1480 | + const cellData = row[col] ?? ""; | |
1481 | + return typeof cellData === "string" && cellData.includes(",") | |
1482 | + ? `"${cellData}"` | |
1483 | + : cellData; | |
1484 | + }) | |
1485 | + .join(",") | |
1486 | + ), | |
1487 | + ].join("\n"); | |
1488 | + | |
1489 | + let blob; | |
1490 | + // encodingType이 설정되지 않은 경우 기본값으로 utf-8 사용 | |
1491 | + const encoding = this.encodingType || "utf-8"; | |
1492 | + console.log("@@@", encoding); | |
1493 | + if (encoding === "utf-8") { | |
1494 | + // UTF-8 BOM 추가 | |
1495 | + blob = new Blob([new Uint8Array([0xef, 0xbb, 0xbf]), csvContent], { | |
1496 | + type: "text/csv;charset=utf-8", | |
1497 | + }); | |
1498 | + } else if (encoding === "euc-kr") { | |
1499 | + // EUC-KR 인코딩 | |
1500 | + const encoder = new TextEncoder(); | |
1501 | + const encodedData = encoder.encode(csvContent); | |
1502 | + blob = new Blob([encodedData], { | |
1503 | + type: "text/csv;charset=euc-kr", | |
1504 | + }); | |
1505 | + } else { | |
1506 | + console.log("지원되지 않는 인코딩 타입입니다: " + encoding); | |
1507 | + } | |
1508 | + | |
1509 | + if (!blob) { | |
1510 | + console.log("Blob 생성 실패"); | |
1511 | + } | |
1512 | + | |
1513 | + // 파일 이름 설정 | |
1514 | + const fileName = `${vm.selectNode.node_type}_${vm.$getFullFileTime( | |
1515 | + new Date() | |
1516 | + )}.csv`; | |
1517 | + | |
1518 | + // 서버에 업로드 | |
1519 | + const formData = new FormData(); | |
1520 | + formData.append("uploadFile", blob, fileName); | |
1521 | + formData.append("path", this.connection.path); | |
1522 | + formData.append("host_code", this.connection.host_code); | |
1523 | + | |
1524 | + const response = await axios.post("/files/formDataUpload", formData, { | |
1525 | + headers: { | |
1526 | + "Content-Type": "multipart/form-data", | |
1527 | + }, | |
1528 | + }); | |
1529 | + | |
1530 | + vm.$showAlert("업로드", response.data.message); | |
1531 | + vm.fileSelectList(); | |
1532 | + } catch (error) { | |
1533 | + console.error("CSV 내보내기 중 오류 발생:", error); | |
1534 | + vm.$showAlert("업로드", "업로드 오류, 관리자에게 문의하세요."); | |
1535 | + } | |
1536 | + }, | |
1537 | + // 노드 생성 | |
1538 | + fnCreateNode(type) { | |
1539 | + let node = Object.assign({}, this.$getDefaultJobGroup().node); | |
1540 | + node.id = Math.floor(Math.random() * 1000) + 1; | |
1541 | + node.node_id = node.id; | |
1542 | + node.label = type; | |
1543 | + node.node_name = type; | |
1544 | + node.node_type = type; | |
1545 | + node.position = { | |
1546 | + x: Math.floor(Math.random() * 500) + 1, | |
1547 | + y: Math.floor(Math.random() * 500) + 1, | |
1548 | + }; | |
1549 | + let tempData = JSON.parse(JSON.stringify(node)); | |
1550 | + tempData.data = null; | |
1551 | + node.data = tempData; | |
1552 | + switch (type) { | |
1553 | + case "DB_READ": | |
1554 | + node.itm = Object.assign({}, this.$getDefaultJobGroup().connectionDb); | |
1555 | + node.itm.type = "dbConnection"; | |
1556 | + break; | |
1557 | + case "API_READ": | |
1558 | + node.itm = Object.assign( | |
1559 | + {}, | |
1560 | + this.$getDefaultJobGroup().connectionApi | |
1561 | + ); | |
1562 | + break; | |
1563 | + case "EHOJO_READ": | |
1564 | + node.itm = Object.assign( | |
1565 | + {}, | |
1566 | + this.$getDefaultJobGroup().connectionEhojo | |
1567 | + ); | |
1568 | + break; | |
1569 | + } | |
1570 | + this.selectNode = node; | |
1571 | + }, | |
1572 | + }, | |
1573 | + | |
1574 | + watch: { | |
1575 | + // 모달타입에 맞는 모달창 화면 보여주기 | |
1576 | + modalType: function (newValue, oldValue) { | |
1577 | + if (this.modalType != null) { | |
1578 | + this.openModal(newValue); | |
1579 | + } | |
1580 | + }, | |
1581 | + selectedHostCodeData(newVal) { | |
1582 | + if (newVal !== null && !this.isUpdating) { | |
1583 | + this.isUpdating = true; // 업데이트 시작 | |
1584 | + | |
1585 | + // newVal이 이제 인덱스입니다 | |
1586 | + this.selectedDirectory = newVal; | |
1587 | + this.selectedHostData = this.hostList[newVal]; | |
1588 | + | |
1589 | + this.$nextTick(() => { | |
1590 | + this.isUpdating = false; // 업데이트 완료 | |
1591 | + }); | |
1592 | + } | |
1593 | + }, | |
1594 | + | |
1595 | + selectedDirectory(newVal) { | |
1596 | + if (newVal !== null && !this.isUpdating) { | |
1597 | + this.isUpdating = true; // 업데이트 시작 | |
1598 | + | |
1599 | + // newVal이 이제 인덱스입니다 | |
1600 | + this.selectedHostCodeData = newVal; | |
1601 | + this.selectedHostData = this.hostList[newVal]; | |
1602 | + | |
1603 | + this.$nextTick(() => { | |
1604 | + this.isUpdating = false; // 업데이트 완료 | |
1605 | + }); | |
1606 | + } | |
1607 | + } | |
1608 | + }, | |
1609 | + components: { | |
1610 | + SvgIcon: SvgIcon, | |
1611 | + TreeItem: TreeItem, | |
1612 | + TreeModal: TreeModal, | |
1613 | + FileDataRead: FileDataRead, | |
1614 | + DatabaseConnection: DatabaseConnection, | |
1615 | + apiConnection: apiConnection, | |
1616 | + XLSX: XLSX, | |
1617 | + EhojoConnection: EhojoConnection, | |
1618 | + }, | |
1619 | + mounted() { | |
1620 | + this.userauth = this.$authorChk(); | |
1621 | + this.selectHosts(); | |
1622 | + this.searchInit(); | |
1623 | + }, | |
1624 | +}; | |
1625 | +</script> | |
1626 | +<style> | |
1627 | +.tabs-container { | |
1628 | + margin-top: 1rem; | |
1629 | +} | |
1630 | + | |
1631 | +.tab-btn { | |
1632 | + padding: 0.5rem 1rem; | |
1633 | + margin-right: 0.5rem; | |
1634 | + border: 1px solid #ddd; | |
1635 | + border-bottom: none; | |
1636 | + border-radius: 4px 4px 0 0; | |
1637 | + cursor: pointer; | |
1638 | + background: #f5f5f5; | |
1639 | +} | |
1640 | + | |
1641 | +.tab-btn.active { | |
1642 | + background: #fff; | |
1643 | + border-bottom: 2px solid #007bff; | |
1644 | + color: #007bff; | |
1645 | +} | |
1646 | +</style>(파일 끝에 줄바꿈 문자 없음) |
--- package-lock.json
+++ package-lock.json
... | ... | @@ -26,6 +26,7 @@ |
26 | 26 |
"html2canvas": "^1.4.1", |
27 | 27 |
"https": "^1.0.0", |
28 | 28 |
"lodash": "^4.17.21", |
29 |
+ "moment": "^2.30.1", |
|
29 | 30 |
"new-line": "^1.1.1", |
30 | 31 |
"pg": "8.8.0", |
31 | 32 |
"primeicons": "^6.0.1", |
... | ... | @@ -7388,6 +7389,7 @@ |
7388 | 7389 |
"version": "2.30.1", |
7389 | 7390 |
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", |
7390 | 7391 |
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", |
7392 |
+ "license": "MIT", |
|
7391 | 7393 |
"engines": { |
7392 | 7394 |
"node": "*" |
7393 | 7395 |
} |
--- package.json
+++ package.json
... | ... | @@ -21,6 +21,7 @@ |
21 | 21 |
"html2canvas": "^1.4.1", |
22 | 22 |
"https": "^1.0.0", |
23 | 23 |
"lodash": "^4.17.21", |
24 |
+ "moment": "^2.30.1", |
|
24 | 25 |
"new-line": "^1.1.1", |
25 | 26 |
"pg": "8.8.0", |
26 | 27 |
"primeicons": "^6.0.1", |
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?