
--- client/resources/api/file.js
+++ client/resources/api/file.js
... | ... | @@ -1,8 +1,8 @@ |
1 | 1 |
import { apiClient } from "./index"; |
2 | 2 |
|
3 | 3 |
// 파일 다운로드 |
4 |
-export const fileDownloadProc = (fileId) => { |
|
5 |
- return apiClient.get(`/file/${fileId}/fileDownload.json`, { responseType: 'blob' }); |
|
4 |
+export const fileDownloadProc = (files) => { |
|
5 |
+ return apiClient.get(`/file/${files.fileId}/${files.fileOrdr}/fileDownload.json`, { responseType: 'blob' }); |
|
6 | 6 |
} |
7 | 7 |
|
8 | 8 |
// 파일 다운로드 |
--- client/views/pages/bbsDcry/photo/PicHistoryDetail.vue
+++ client/views/pages/bbsDcry/photo/PicHistoryDetail.vue
... | ... | @@ -26,18 +26,16 @@ |
26 | 26 |
<div> |
27 | 27 |
<div class="gallery"> |
28 | 28 |
<div class="main-swiper"> |
29 |
- <swiper :style="{ '--swiper-navigation-color': '#fff', '--swiper-pagination-color': '#fff' }" :loop="true" |
|
30 |
- :spaceBetween="10" :thumbs="{ swiper: thumbsSwiper }" :modules="modules" class="mySwiper2"> |
|
29 |
+ <swiper :style="{ '--swiper-navigation-color': '#fff', '--swiper-pagination-color': '#fff' }" :loop="true" :spaceBetween="10" :thumbs="{ swiper: thumbsSwiper }" :modules="modules" class="mySwiper2"> |
|
31 | 30 |
<swiper-slide v-for="(item, idx) of findResult.files" :key="idx"> |
32 | 31 |
<img :src="item.filePath" :alt="item.fileNm" /> |
33 | 32 |
</swiper-slide> |
34 | 33 |
</swiper> |
35 | 34 |
</div> |
36 | 35 |
<div class="thumbnail"> |
37 |
- <swiper @swiper="setThumbsSwiper" :spaceBetween="20" :slidesPerView="4" :freeMode="true" |
|
38 |
- :watchSlidesProgress="true" :modules="modules" :navigation="true" class="mySwiper"> |
|
36 |
+ <swiper @swiper="setThumbsSwiper" :spaceBetween="20" :slidesPerView="4" :freeMode="true" :watchSlidesProgress="true" :modules="modules" :navigation="true" class="mySwiper"> |
|
39 | 37 |
<swiper-slide v-for="(item, idx) of findResult.files" :key="idx"> |
40 |
- <input type="checkbox" :id="'photo_' + idx" :value="item.fileId" v-model="selectedFiles" @click.stop /> |
|
38 |
+ <input type="checkbox" :id="'photo_' + idx" :value="item" v-model="selectedFiles" @click.stop /> |
|
41 | 39 |
<img :src="item.filePath" :alt="item.fileNm" /> |
42 | 40 |
</swiper-slide> |
43 | 41 |
</swiper> |
... | ... | @@ -46,7 +44,7 @@ |
46 | 44 |
<div class="btn-group"> |
47 | 45 |
<button class="select-down" @click="fnDownload('selected')">선택 다운로드</button> |
48 | 46 |
<button class="all-down" @click="fnDownload('all')">전체 다운로드</button> |
49 |
- <div v-if="loading" class="loading-overlay"> |
|
47 |
+ <div v-if="loading" class="loading-overlay"> |
|
50 | 48 |
<div class="loading-spinner"></div> |
51 | 49 |
<div> |
52 | 50 |
<p>다운로드 중입니다</p> |
... | ... | @@ -148,7 +146,7 @@ |
148 | 146 |
pageId: null, |
149 | 147 |
findResult: {}, |
150 | 148 |
selectedFiles: [], |
151 |
- loading: false, |
|
149 |
+ loading: false, |
|
152 | 150 |
}; |
153 | 151 |
}, |
154 | 152 |
|
... | ... | @@ -204,19 +202,18 @@ |
204 | 202 |
let link = null; |
205 | 203 |
|
206 | 204 |
try { |
207 |
- // 파일 ID 수집 |
|
208 | 205 |
let fileList; |
209 | 206 |
if (type === 'selected') { |
210 | 207 |
fileList = this.selectedFiles; |
211 | 208 |
} else if (type === 'all') { |
212 |
- fileList = this.findResult.files.map(file => file.fileId); |
|
209 |
+ fileList = this.findResult.files; |
|
213 | 210 |
} |
214 | 211 |
|
215 | 212 |
let isMultiple = fileList.length > 1; |
216 |
- let fileIds = isMultiple ? fileList : fileList[0]; |
|
213 |
+ let files = isMultiple ? fileList : fileList[0]; |
|
217 | 214 |
|
218 | 215 |
// Call the API to get the file data |
219 |
- const response = isMultiple ? await multiFileDownloadProc(fileIds) : await fileDownloadProc(fileIds); |
|
216 |
+ const response = isMultiple ? await multiFileDownloadProc(files) : await fileDownloadProc(files); |
|
220 | 217 |
|
221 | 218 |
// 파일명 추출 부분 수정 |
222 | 219 |
let filename = isMultiple ? 'downloadFile.zip' : 'downloadFile.bin'; |
--- client/views/pages/bbsDcry/photo/PicHistoryInsert.vue
+++ client/views/pages/bbsDcry/photo/PicHistoryInsert.vue
... | ... | @@ -66,21 +66,33 @@ |
66 | 66 |
<p class="mb-10">파일목록</p> |
67 | 67 |
<div id="fileNames" class="file-names"> |
68 | 68 |
<div v-if="requestDTO.files.length === 0 && multipartFiles.length === 0">선택된 파일이 없습니다.</div> |
69 |
- <!-- 새로 추가된 파일 목록 --> |
|
70 |
- <div v-for="(file, idx) of multipartFiles" :key="idx" class="flex-sp-bw mb-5 file-wrap"> |
|
71 |
- <div class="file-name"> |
|
72 |
- <img src="/client/resources/images/icon/imgicon.png" alt="fileicon"> |
|
73 |
- <p>{{ file.name }}</p> |
|
74 |
- </div> |
|
75 |
- <button type="button" class="cancel" @click="fnDelFile('new', idx)"><b>✕</b></button> |
|
76 |
- </div> |
|
77 | 69 |
<!-- 기존 등록된 파일 목록 --> |
78 |
- <div v-for="(file, idx) of requestDTO.files" :key="idx" class="flex-sp-bw mb-5 file-wrap"> |
|
79 |
- <div class="file-name"> |
|
80 |
- <img src="/client/resources/images/icon/imgicon.png" alt="fileicon"> |
|
81 |
- <p>{{ file.fileNm }}</p> |
|
82 |
- </div> |
|
83 |
- <button type="button" class="cancel" @click="fnDelFile('old', file.fileId)"><b>✕</b></button> |
|
70 |
+ <div v-for="(file, idx) of requestDTO.files" :key="idx" class="mb-5"> |
|
71 |
+ <input type="radio" name="thumbAt" :id="'oldFile_' + file.fileOrdr" v-model="selectedThumb" :value="file.fileNm"> |
|
72 |
+ <label :for="'oldFile_' + file.fileOrdr"> |
|
73 |
+ <p>썸네일여부</p> |
|
74 |
+ <div class="flex-sp-bw file-wrap"> |
|
75 |
+ <div class="file-name"> |
|
76 |
+ <img src="/client/resources/images/icon/imgicon.png" alt="fileicon"> |
|
77 |
+ <p>{{ file.fileNm }}</p> |
|
78 |
+ </div> |
|
79 |
+ <button type="button" class="cancel" @click="fnDelFile('old', file.fileOrdr)"><b>✕</b></button> |
|
80 |
+ </div> |
|
81 |
+ </label> |
|
82 |
+ </div> |
|
83 |
+ <!-- 새로 추가된 파일 목록 --> |
|
84 |
+ <div v-for="(file, idx) of multipartFiles" :key="idx" class="mb-5"> |
|
85 |
+ <input type="radio" name="thumbAt" :id="'newFile_' + idx" v-model="selectedThumb" :value="file.name"> |
|
86 |
+ <label :for="'newFile_' + idx"> |
|
87 |
+ <p>썸네일여부</p> |
|
88 |
+ <div class="flex-sp-bw file-wrap"> |
|
89 |
+ <div class="file-name"> |
|
90 |
+ <img src="/client/resources/images/icon/imgicon.png" alt="fileicon"> |
|
91 |
+ <p>{{ file.name }}</p> |
|
92 |
+ </div> |
|
93 |
+ <button type="button" class="cancel" @click="fnDelFile('new', idx)"><b>✕</b></button> |
|
94 |
+ </div> |
|
95 |
+ </label> |
|
84 | 96 |
</div> |
85 | 97 |
</div> |
86 | 98 |
</li> |
... | ... | @@ -147,6 +159,8 @@ |
147 | 159 |
|
148 | 160 |
multipartFiles: [], |
149 | 161 |
selectedCtgries: [], // 카테고리 목록 |
162 |
+ |
|
163 |
+ selectedThumb: null, |
|
150 | 164 |
}; |
151 | 165 |
}, |
152 | 166 |
|
... | ... | @@ -192,6 +206,12 @@ |
192 | 206 |
|
193 | 207 |
this.multipartFiles = []; |
194 | 208 |
this.selectedCtgries = dcry.ctgrys.length > 0 ? dcry.ctgrys : []; |
209 |
+ |
|
210 |
+ // 썸네일 |
|
211 |
+ const thumbFile = this.requestDTO.files.find(f => f.thumbAt === 'Y'); |
|
212 |
+ if (thumbFile) { |
|
213 |
+ this.selectedThumb = thumbFile.fileNm; |
|
214 |
+ } |
|
195 | 215 |
|
196 | 216 |
console.log(this.requestDTO); |
197 | 217 |
}, |
... | ... | @@ -276,9 +296,13 @@ |
276 | 296 |
continue; |
277 | 297 |
} |
278 | 298 |
|
279 |
- // 파일명+확장자 조합이 중복되지 않으면 추가 |
|
280 | 299 |
this.multipartFiles.push(file); |
281 | 300 |
existingFilesMap.set(fileNameLower, file.name); |
301 |
+ |
|
302 |
+ // 최초 등록 시 썸네일로 설정 |
|
303 |
+ if (this.requestDTO.files.length < 1 && this.multipartFiles.length > 0) { |
|
304 |
+ this.selectedThumb = this.multipartFiles[0].name; |
|
305 |
+ } |
|
282 | 306 |
} |
283 | 307 |
}, |
284 | 308 |
|
... | ... | @@ -287,7 +311,12 @@ |
287 | 311 |
if (type === 'new') { |
288 | 312 |
this.multipartFiles.splice(separator, 1); |
289 | 313 |
} else if (type === 'old') { |
290 |
- this.requestDTO.files = this.requestDTO.files.filter(item => item.fileId !== separator); |
|
314 |
+ this.requestDTO.files = this.requestDTO.files.filter(item => item.fileOrdr !== separator); |
|
315 |
+ } |
|
316 |
+ |
|
317 |
+ // 썸네일 변경 |
|
318 |
+ if (this.requestDTO.files.length < 1 && this.multipartFiles.length > 0) { |
|
319 |
+ this.selectedThumb = this.multipartFiles[0].name; |
|
291 | 320 |
} |
292 | 321 |
}, |
293 | 322 |
|
... | ... | @@ -313,14 +342,23 @@ |
313 | 342 |
|
314 | 343 |
// 텍스트 데이터 추가 |
315 | 344 |
formData.append('sj', this.requestDTO.sj); |
316 |
- formData.append('cn', this.requestDTO.cn); |
|
317 |
- formData.append('adres', this.requestDTO.adres); |
|
318 |
- formData.append('prdctnYear', this.requestDTO.prdctnYear); |
|
319 | 345 |
formData.append('ty', this.requestDTO.ty); |
320 | 346 |
|
321 | 347 |
// 게시물 아이디 |
322 | 348 |
if (!this.$isEmpty(this.pageId)) { |
323 | 349 |
formData.append('dcryId', this.pageId); |
350 |
+ } |
|
351 |
+ |
|
352 |
+ if (!this.$isEmpty(this.requestDTO.prdctnYear)) { |
|
353 |
+ formData.append('prdctnYear', this.requestDTO.prdctnYear); |
|
354 |
+ } |
|
355 |
+ |
|
356 |
+ if (!this.$isEmpty(this.requestDTO.adres)) { |
|
357 |
+ formData.append('adres', this.requestDTO.adres); |
|
358 |
+ } |
|
359 |
+ |
|
360 |
+ if (!this.$isEmpty(this.requestDTO.cn)) { |
|
361 |
+ formData.append('cn', this.requestDTO.cn); |
|
324 | 362 |
} |
325 | 363 |
|
326 | 364 |
// 파일 아이디 |
... | ... | @@ -336,17 +374,24 @@ |
336 | 374 |
} |
337 | 375 |
|
338 | 376 |
// 파일 추가 |
339 |
- for (let file of this.multipartFiles) { |
|
340 |
- formData.append("multipartFiles", file); |
|
377 |
+ if (this.multipartFiles.length > 0) { |
|
378 |
+ for (let file of this.multipartFiles) { |
|
379 |
+ formData.append("multipartFiles", file); |
|
380 |
+ } |
|
341 | 381 |
} |
342 | 382 |
|
343 | 383 |
// 기존파일 수정 |
344 | 384 |
if (!this.$isEmpty(this.pageId) && this.requestDTO.files.length > 0) { |
345 | 385 |
for (let file of this.requestDTO.files) { |
346 |
- formData.append("files", file.fileId); |
|
386 |
+ formData.append("files", file.fileOrdr); |
|
347 | 387 |
} |
348 | 388 |
} |
349 | 389 |
|
390 |
+ // 썸네일 정보 추가 |
|
391 |
+ if (this.selectedThumb !== null) { |
|
392 |
+ formData.append('selectedThumb', this.selectedThumb); |
|
393 |
+ } |
|
394 |
+ |
|
350 | 395 |
// API 통신 |
351 | 396 |
const response = this.$isEmpty(this.pageId) ? await saveDcry(formData) : await updateDcry(formData); |
352 | 397 |
let id = response.data.data.dcryId; |
--- client/views/pages/bbsDcry/video/VideoHistoryDetail.vue
+++ client/views/pages/bbsDcry/video/VideoHistoryDetail.vue
... | ... | @@ -63,9 +63,9 @@ |
63 | 63 |
<button type="button" class="gray-line-bg" @click="fnMoveTo('list')">목록</button> |
64 | 64 |
<button type="button" class="gradient" @click="fnDownload">다운로드</button> |
65 | 65 |
<div v-if="loading" class="loading-overlay"> |
66 |
- <div class="loading-spinner"></div> |
|
67 |
- <p>파일을 다운로드 중입니다...</p> |
|
68 |
- </div> |
|
66 |
+ <div class="loading-spinner"></div> |
|
67 |
+ <p>파일을 다운로드 중입니다...</p> |
|
68 |
+ </div> |
|
69 | 69 |
</div> |
70 | 70 |
</div> |
71 | 71 |
</template> |
... | ... | @@ -97,7 +97,7 @@ |
97 | 97 |
pageId: null, |
98 | 98 |
findResult: {}, |
99 | 99 |
selectedFiles: [], |
100 |
- loading: false, |
|
100 |
+ loading: false, |
|
101 | 101 |
}; |
102 | 102 |
}, |
103 | 103 |
|
... | ... | @@ -143,8 +143,8 @@ |
143 | 143 |
|
144 | 144 |
try { |
145 | 145 |
// 파일 ID 수집 |
146 |
- let fileId = this.findResult.files[0].fileId; |
|
147 |
- const response = await fileDownloadProc(fileId); |
|
146 |
+ let file = this.findResult.files[0]; |
|
147 |
+ const response = await fileDownloadProc(file); |
|
148 | 148 |
|
149 | 149 |
// 파일명 조회 |
150 | 150 |
let filename = 'downloadFile.bin'; |
--- client/views/pages/bbsDcry/video/VideoHistoryInsert.vue
+++ client/views/pages/bbsDcry/video/VideoHistoryInsert.vue
... | ... | @@ -64,21 +64,20 @@ |
64 | 64 |
<p class="mb-10">파일목록</p> |
65 | 65 |
<div id="fileNames" class="file-names"> |
66 | 66 |
<div v-if="requestDTO.files.length === 0 && multipartFiles.length === 0">선택된 파일이 없습니다.</div> |
67 |
- <!-- 새로 추가된 파일 목록 --> |
|
68 |
- <div v-for="(file, idx) of multipartFiles" :key="idx" class="flex-sp-bw mb-5 file-wrap"> |
|
69 |
- <div class="file-name"> |
|
70 |
- <img src="/client/resources/images/icon/imgicon.png" alt="fileicon"> |
|
71 |
- <p>{{ file.name }}</p> |
|
72 |
- </div> |
|
73 |
- <button type="button" class="cancel" @click="fnDelFile('new', idx)"><b>✕</b></button> |
|
74 |
- </div> |
|
75 | 67 |
<!-- 기존 등록된 파일 목록 --> |
76 | 68 |
<div v-for="(file, idx) of requestDTO.files" :key="idx" class="flex-sp-bw mb-5 file-wrap"> |
77 | 69 |
<div class="file-name"> |
78 | 70 |
<img src="/client/resources/images/icon/imgicon.png" alt="fileicon"> |
79 | 71 |
<p>{{ file.fileNm }}</p> |
80 | 72 |
</div> |
81 |
- <button type="button" class="cancel" @click="fnDelFile('old', file.fileId)"><b>✕</b></button> |
|
73 |
+ <button type="button" class="cancel" @click="fnDelFile('old', file.fileOrdr)"><b>✕</b></button> |
|
74 |
+ </div><!-- 새로 추가된 파일 목록 --> |
|
75 |
+ <div v-for="(file, idx) of multipartFiles" :key="idx" class="flex-sp-bw mb-5 file-wrap"> |
|
76 |
+ <div class="file-name"> |
|
77 |
+ <img src="/client/resources/images/icon/imgicon.png" alt="fileicon"> |
|
78 |
+ <p>{{ file.name }}</p> |
|
79 |
+ </div> |
|
80 |
+ <button type="button" class="cancel" @click="fnDelFile('new', idx)"><b>✕</b></button> |
|
82 | 81 |
</div> |
83 | 82 |
</div> |
84 | 83 |
</li> |
... | ... | @@ -268,7 +267,7 @@ |
268 | 267 |
if (type === 'new') { |
269 | 268 |
this.multipartFiles.splice(separator, 1); |
270 | 269 |
} else if (type === 'old') { |
271 |
- this.requestDTO.files = this.requestDTO.files.filter(item => item.fileId !== separator); |
|
270 |
+ this.requestDTO.files = this.requestDTO.files.filter(item => item.fileOrdr !== separator); |
|
272 | 271 |
} |
273 | 272 |
}, |
274 | 273 |
|
... | ... | @@ -294,14 +293,23 @@ |
294 | 293 |
|
295 | 294 |
// 텍스트 데이터 추가 |
296 | 295 |
formData.append('sj', this.requestDTO.sj); |
297 |
- formData.append('cn', this.requestDTO.cn); |
|
298 |
- formData.append('adres', this.requestDTO.adres); |
|
299 |
- formData.append('prdctnYear', this.requestDTO.prdctnYear); |
|
300 | 296 |
formData.append('ty', this.requestDTO.ty); |
301 | 297 |
|
302 | 298 |
// 게시물 아이디 |
303 | 299 |
if (!this.$isEmpty(this.pageId)) { |
304 | 300 |
formData.append('dcryId', this.pageId); |
301 |
+ } |
|
302 |
+ |
|
303 |
+ if (!this.$isEmpty(this.requestDTO.prdctnYear)) { |
|
304 |
+ formData.append('prdctnYear', this.requestDTO.prdctnYear); |
|
305 |
+ } |
|
306 |
+ |
|
307 |
+ if (!this.$isEmpty(this.requestDTO.adres)) { |
|
308 |
+ formData.append('adres', this.requestDTO.adres); |
|
309 |
+ } |
|
310 |
+ |
|
311 |
+ if (!this.$isEmpty(this.requestDTO.cn)) { |
|
312 |
+ formData.append('cn', this.requestDTO.cn); |
|
305 | 313 |
} |
306 | 314 |
|
307 | 315 |
// 파일 아이디 |
... | ... | @@ -317,14 +325,16 @@ |
317 | 325 |
} |
318 | 326 |
|
319 | 327 |
// 파일 추가 |
320 |
- for (let file of this.multipartFiles) { |
|
321 |
- formData.append("multipartFiles", file); |
|
328 |
+ if (this.multipartFiles.length > 0) { |
|
329 |
+ for (let file of this.multipartFiles) { |
|
330 |
+ formData.append("multipartFiles", file); |
|
331 |
+ } |
|
322 | 332 |
} |
323 | 333 |
|
324 | 334 |
// 기존파일 수정 |
325 | 335 |
if (!this.$isEmpty(this.pageId) && this.requestDTO.files.length > 0) { |
326 | 336 |
for (let file of this.requestDTO.files) { |
327 |
- formData.append("files", file.fileId); |
|
337 |
+ formData.append("files", file.fileOrdr); |
|
328 | 338 |
} |
329 | 339 |
} |
330 | 340 |
|
--- client/views/pages/bbsNesDta/NewsReleaseInsert.vue
+++ client/views/pages/bbsNesDta/NewsReleaseInsert.vue
... | ... | @@ -282,14 +282,21 @@ |
282 | 282 |
|
283 | 283 |
// 텍스트 데이터 추가 |
284 | 284 |
formData.append('sj', this.requestDTO.sj); |
285 |
- formData.append('cn', this.requestDTO.cn); |
|
286 |
- formData.append('link', this.requestDTO.link); |
|
287 |
- formData.append('prdctnYear', this.requestDTO.prdctnYear); |
|
288 |
- formData.append('ty', this.requestDTO.ty); |
|
289 | 285 |
|
290 |
- // 게시물 아이디 |
|
291 | 286 |
if (!this.$isEmpty(this.pageId)) { |
292 | 287 |
formData.append('nesDtaId', this.pageId); |
288 |
+ } |
|
289 |
+ |
|
290 |
+ if (!this.$isEmpty(this.requestDTO.prdctnYear)) { |
|
291 |
+ formData.append('prdctnYear', this.requestDTO.prdctnYear); |
|
292 |
+ } |
|
293 |
+ |
|
294 |
+ if (!this.$isEmpty(this.requestDTO.link)) { |
|
295 |
+ formData.append('link', this.requestDTO.link); |
|
296 |
+ } |
|
297 |
+ |
|
298 |
+ if (!this.$isEmpty(this.requestDTO.cn)) { |
|
299 |
+ formData.append('cn', this.requestDTO.cn); |
|
293 | 300 |
} |
294 | 301 |
|
295 | 302 |
// 파일 아이디 |
... | ... | @@ -312,10 +319,15 @@ |
312 | 319 |
// 기존파일 수정 |
313 | 320 |
if (!this.$isEmpty(this.pageId) && this.requestDTO.files.length > 0) { |
314 | 321 |
for (let file of this.requestDTO.files) { |
315 |
- formData.append("files", file.fileId); |
|
322 |
+ formData.append("files", file.fileOrdr); |
|
316 | 323 |
} |
317 | 324 |
} |
318 | 325 |
|
326 |
+ // 썸네일 정보 추가 |
|
327 |
+ if (this.selectedThumb !== null) { |
|
328 |
+ formData.append('selectedThumb', this.multipartFiles[0].name); |
|
329 |
+ } |
|
330 |
+ |
|
319 | 331 |
// API 통신 |
320 | 332 |
const response = this.$isEmpty(this.pageId) ? await saveNesDtaProc(formData) : await updateNesDtaProc(formData); |
321 | 333 |
alert(this.$isEmpty(this.pageId) ? "등록되었습니다." : "수정되었습니다."); |
--- client/views/pages/bbsNesDta/NewsReleaseSearch.vue
+++ client/views/pages/bbsNesDta/NewsReleaseSearch.vue
... | ... | @@ -103,9 +103,7 @@ |
103 | 103 |
<div v-else class="no-results"> |
104 | 104 |
<img :src="nosearch" alt=""> |
105 | 105 |
<p>검색 결과가 없습니다.</p> |
106 |
- <p>단어의 철자가 정확한지 확인해 주시기 바랍니다.<br> |
|
107 |
-검색어의 단어 수를 줄이거나, 다른 검색어(유사어)로 검색해 보시기 바랍니다.<br> |
|
108 |
-일반적으로 많이 사용하는 검색어로 다시 검색해 주시기 바랍니다.</p> |
|
106 |
+ <p>단어의 철자가 정확한지 확인해 주시기 바랍니다.<br>검색어의 단어 수를 줄이거나, 다른 검색어(유사어)로 검색해 보시기 바랍니다.<br>일반적으로 많이 사용하는 검색어로 다시 검색해 주시기 바랍니다.</p> |
|
109 | 107 |
</div> |
110 | 108 |
</div> |
111 | 109 |
</div> |
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?