박정하 박정하 04-09
250409 박정하 파일 썸네일 조회 수정
@8f117e305d6fbe352055b12d630d3ccf64db8514
client/resources/api/file.js
--- client/resources/api/file.js
+++ client/resources/api/file.js
@@ -1,8 +1,8 @@
 import { apiClient } from "./index";
 
 // 파일 다운로드
-export const fileDownloadProc = (fileId) => {
-  return apiClient.get(`/file/${fileId}/fileDownload.json`, { responseType: 'blob' });
+export const fileDownloadProc = (files) => {
+  return apiClient.get(`/file/${files.fileId}/${files.fileOrdr}/fileDownload.json`, { responseType: 'blob' });
 }
 
 // 파일 다운로드
client/views/pages/bbsDcry/photo/PicHistoryDetail.vue
--- client/views/pages/bbsDcry/photo/PicHistoryDetail.vue
+++ client/views/pages/bbsDcry/photo/PicHistoryDetail.vue
@@ -26,18 +26,16 @@
       <div>
         <div class="gallery">
           <div class="main-swiper">
-            <swiper :style="{ '--swiper-navigation-color': '#fff', '--swiper-pagination-color': '#fff' }" :loop="true"
-              :spaceBetween="10" :thumbs="{ swiper: thumbsSwiper }" :modules="modules" class="mySwiper2">
+            <swiper :style="{ '--swiper-navigation-color': '#fff', '--swiper-pagination-color': '#fff' }" :loop="true" :spaceBetween="10" :thumbs="{ swiper: thumbsSwiper }" :modules="modules" class="mySwiper2">
               <swiper-slide v-for="(item, idx) of findResult.files" :key="idx">
                 <img :src="item.filePath" :alt="item.fileNm" />
               </swiper-slide>
             </swiper>
           </div>
           <div class="thumbnail">
-            <swiper @swiper="setThumbsSwiper" :spaceBetween="20" :slidesPerView="4" :freeMode="true"
-              :watchSlidesProgress="true" :modules="modules" :navigation="true" class="mySwiper">
+            <swiper @swiper="setThumbsSwiper" :spaceBetween="20" :slidesPerView="4" :freeMode="true" :watchSlidesProgress="true" :modules="modules" :navigation="true" class="mySwiper">
               <swiper-slide v-for="(item, idx) of findResult.files" :key="idx">
-                <input type="checkbox" :id="'photo_' + idx" :value="item.fileId" v-model="selectedFiles" @click.stop />
+                <input type="checkbox" :id="'photo_' + idx" :value="item" v-model="selectedFiles" @click.stop />
                 <img :src="item.filePath" :alt="item.fileNm" />
               </swiper-slide>
             </swiper>
@@ -46,7 +44,7 @@
         <div class="btn-group">
           <button class="select-down" @click="fnDownload('selected')">선택 다운로드</button>
           <button class="all-down" @click="fnDownload('all')">전체 다운로드</button>
-          <div v-if="loading"  class="loading-overlay">
+          <div v-if="loading" class="loading-overlay">
             <div class="loading-spinner"></div>
             <div>
               <p>다운로드 중입니다</p>
@@ -148,7 +146,7 @@
       pageId: null,
       findResult: {},
       selectedFiles: [],
-      loading: false, 
+      loading: false,
     };
   },
 
@@ -204,19 +202,18 @@
       let link = null;
 
       try {
-        // 파일 ID 수집
         let fileList;
         if (type === 'selected') {
           fileList = this.selectedFiles;
         } else if (type === 'all') {
-          fileList = this.findResult.files.map(file => file.fileId);
+          fileList = this.findResult.files;
         }
 
         let isMultiple = fileList.length > 1;
-        let fileIds = isMultiple ? fileList : fileList[0];
+        let files = isMultiple ? fileList : fileList[0];
 
         // Call the API to get the file data
-        const response = isMultiple ? await multiFileDownloadProc(fileIds) : await fileDownloadProc(fileIds);
+        const response = isMultiple ? await multiFileDownloadProc(files) : await fileDownloadProc(files);
 
         // 파일명 추출 부분 수정
         let filename = isMultiple ? 'downloadFile.zip' : 'downloadFile.bin';
client/views/pages/bbsDcry/photo/PicHistoryInsert.vue
--- client/views/pages/bbsDcry/photo/PicHistoryInsert.vue
+++ client/views/pages/bbsDcry/photo/PicHistoryInsert.vue
@@ -66,21 +66,33 @@
               <p class="mb-10">파일목록</p>
               <div id="fileNames" class="file-names">
                 <div v-if="requestDTO.files.length === 0 && multipartFiles.length === 0">선택된 파일이 없습니다.</div>
-                <!-- 새로 추가된 파일 목록 -->
-                <div v-for="(file, idx) of multipartFiles" :key="idx" class="flex-sp-bw mb-5 file-wrap">
-                  <div class="file-name">
-                    <img src="/client/resources/images/icon/imgicon.png" alt="fileicon">
-                    <p>{{ file.name }}</p>
-                  </div>
-                  <button type="button" class="cancel" @click="fnDelFile('new', idx)"><b>✕</b></button>
-                </div>
                 <!-- 기존 등록된 파일 목록 -->
-                <div v-for="(file, idx) of requestDTO.files" :key="idx" class="flex-sp-bw mb-5 file-wrap">
-                  <div class="file-name">
-                    <img src="/client/resources/images/icon/imgicon.png" alt="fileicon">
-                    <p>{{ file.fileNm }}</p>
-                  </div>
-                  <button type="button" class="cancel" @click="fnDelFile('old', file.fileId)"><b>✕</b></button>
+                <div v-for="(file, idx) of requestDTO.files" :key="idx" class="mb-5">
+                  <input type="radio" name="thumbAt" :id="'oldFile_' + file.fileOrdr" v-model="selectedThumb" :value="file.fileNm">
+                  <label :for="'oldFile_' + file.fileOrdr">
+                    <p>썸네일여부</p>
+                    <div class="flex-sp-bw file-wrap">
+                      <div class="file-name">
+                        <img src="/client/resources/images/icon/imgicon.png" alt="fileicon">
+                        <p>{{ file.fileNm }}</p>
+                      </div>
+                      <button type="button" class="cancel" @click="fnDelFile('old', file.fileOrdr)"><b>✕</b></button>
+                    </div>
+                  </label>
+                </div>
+                <!-- 새로 추가된 파일 목록 -->
+                <div v-for="(file, idx) of multipartFiles" :key="idx" class="mb-5">
+                  <input type="radio" name="thumbAt" :id="'newFile_' + idx" v-model="selectedThumb" :value="file.name">
+                  <label :for="'newFile_' + idx">
+                    <p>썸네일여부</p>
+                    <div class="flex-sp-bw file-wrap">
+                      <div class="file-name">
+                        <img src="/client/resources/images/icon/imgicon.png" alt="fileicon">
+                        <p>{{ file.name }}</p>
+                      </div>
+                      <button type="button" class="cancel" @click="fnDelFile('new', idx)"><b>✕</b></button>
+                    </div>
+                  </label>
                 </div>
               </div>
             </li>
@@ -147,6 +159,8 @@
 
       multipartFiles: [],
       selectedCtgries: [], // 카테고리 목록
+
+      selectedThumb: null,
     };
   },
 
@@ -192,6 +206,12 @@
 
       this.multipartFiles = [];
       this.selectedCtgries = dcry.ctgrys.length > 0 ? dcry.ctgrys : [];
+
+      // 썸네일
+      const thumbFile = this.requestDTO.files.find(f => f.thumbAt === 'Y');
+      if (thumbFile) {
+        this.selectedThumb = thumbFile.fileNm;
+      }
 
       console.log(this.requestDTO);
     },
@@ -276,9 +296,13 @@
           continue;
         }
 
-        // 파일명+확장자 조합이 중복되지 않으면 추가
         this.multipartFiles.push(file);
         existingFilesMap.set(fileNameLower, file.name);
+
+        // 최초 등록 시 썸네일로 설정
+        if (this.requestDTO.files.length < 1 && this.multipartFiles.length > 0) {
+          this.selectedThumb = this.multipartFiles[0].name;
+        }
       }
     },
 
@@ -287,7 +311,12 @@
       if (type === 'new') {
         this.multipartFiles.splice(separator, 1);
       } else if (type === 'old') {
-        this.requestDTO.files = this.requestDTO.files.filter(item => item.fileId !== separator);
+        this.requestDTO.files = this.requestDTO.files.filter(item => item.fileOrdr !== separator);
+      }
+
+      // 썸네일 변경
+      if (this.requestDTO.files.length < 1 && this.multipartFiles.length > 0) {
+        this.selectedThumb = this.multipartFiles[0].name;
       }
     },
 
@@ -313,14 +342,23 @@
 
         // 텍스트 데이터 추가
         formData.append('sj', this.requestDTO.sj);
-        formData.append('cn', this.requestDTO.cn);
-        formData.append('adres', this.requestDTO.adres);
-        formData.append('prdctnYear', this.requestDTO.prdctnYear);
         formData.append('ty', this.requestDTO.ty);
 
         // 게시물 아이디
         if (!this.$isEmpty(this.pageId)) {
           formData.append('dcryId', this.pageId);
+        }
+
+        if (!this.$isEmpty(this.requestDTO.prdctnYear)) {
+          formData.append('prdctnYear', this.requestDTO.prdctnYear);
+        }
+
+        if (!this.$isEmpty(this.requestDTO.adres)) {
+          formData.append('adres', this.requestDTO.adres);
+        }
+
+        if (!this.$isEmpty(this.requestDTO.cn)) {
+          formData.append('cn', this.requestDTO.cn);
         }
 
         // 파일 아이디
@@ -336,17 +374,24 @@
         }
 
         // 파일 추가
-        for (let file of this.multipartFiles) {
-          formData.append("multipartFiles", file);
+        if (this.multipartFiles.length > 0) {
+          for (let file of this.multipartFiles) {
+            formData.append("multipartFiles", file);
+          }
         }
 
         // 기존파일 수정
         if (!this.$isEmpty(this.pageId) && this.requestDTO.files.length > 0) {
           for (let file of this.requestDTO.files) {
-            formData.append("files", file.fileId);
+            formData.append("files", file.fileOrdr);
           }
         }
 
+        // 썸네일 정보 추가
+        if (this.selectedThumb !== null) {
+          formData.append('selectedThumb', this.selectedThumb);
+        }
+
         // API 통신
         const response = this.$isEmpty(this.pageId) ? await saveDcry(formData) : await updateDcry(formData);
         let id = response.data.data.dcryId;
client/views/pages/bbsDcry/video/VideoHistoryDetail.vue
--- client/views/pages/bbsDcry/video/VideoHistoryDetail.vue
+++ client/views/pages/bbsDcry/video/VideoHistoryDetail.vue
@@ -63,9 +63,9 @@
       <button type="button" class="gray-line-bg" @click="fnMoveTo('list')">목록</button>
       <button type="button" class="gradient" @click="fnDownload">다운로드</button>
       <div v-if="loading" class="loading-overlay">
-      <div class="loading-spinner"></div>
-      <p>파일을 다운로드 중입니다...</p>
-    </div>
+        <div class="loading-spinner"></div>
+        <p>파일을 다운로드 중입니다...</p>
+      </div>
     </div>
   </div>
 </template>
@@ -97,7 +97,7 @@
       pageId: null,
       findResult: {},
       selectedFiles: [],
-      loading: false, 
+      loading: false,
     };
   },
 
@@ -143,8 +143,8 @@
 
       try {
         // 파일 ID 수집
-        let fileId = this.findResult.files[0].fileId;
-        const response = await fileDownloadProc(fileId);
+        let file = this.findResult.files[0];
+        const response = await fileDownloadProc(file);
 
         // 파일명 조회
         let filename = 'downloadFile.bin';
client/views/pages/bbsDcry/video/VideoHistoryInsert.vue
--- client/views/pages/bbsDcry/video/VideoHistoryInsert.vue
+++ client/views/pages/bbsDcry/video/VideoHistoryInsert.vue
@@ -64,21 +64,20 @@
               <p class="mb-10">파일목록</p>
               <div id="fileNames" class="file-names">
                 <div v-if="requestDTO.files.length === 0 && multipartFiles.length === 0">선택된 파일이 없습니다.</div>
-                <!-- 새로 추가된 파일 목록 -->
-                <div v-for="(file, idx) of multipartFiles" :key="idx" class="flex-sp-bw mb-5 file-wrap">
-                  <div class="file-name">
-                    <img src="/client/resources/images/icon/imgicon.png" alt="fileicon">
-                    <p>{{ file.name }}</p>
-                  </div>
-                  <button type="button" class="cancel" @click="fnDelFile('new', idx)"><b>✕</b></button>
-                </div>
                 <!-- 기존 등록된 파일 목록 -->
                 <div v-for="(file, idx) of requestDTO.files" :key="idx" class="flex-sp-bw mb-5 file-wrap">
                   <div class="file-name">
                     <img src="/client/resources/images/icon/imgicon.png" alt="fileicon">
                     <p>{{ file.fileNm }}</p>
                   </div>
-                  <button type="button" class="cancel" @click="fnDelFile('old', file.fileId)"><b>✕</b></button>
+                  <button type="button" class="cancel" @click="fnDelFile('old', file.fileOrdr)"><b>✕</b></button>
+                </div><!-- 새로 추가된 파일 목록 -->
+                <div v-for="(file, idx) of multipartFiles" :key="idx" class="flex-sp-bw mb-5 file-wrap">
+                  <div class="file-name">
+                    <img src="/client/resources/images/icon/imgicon.png" alt="fileicon">
+                    <p>{{ file.name }}</p>
+                  </div>
+                  <button type="button" class="cancel" @click="fnDelFile('new', idx)"><b>✕</b></button>
                 </div>
               </div>
             </li>
@@ -268,7 +267,7 @@
       if (type === 'new') {
         this.multipartFiles.splice(separator, 1);
       } else if (type === 'old') {
-        this.requestDTO.files = this.requestDTO.files.filter(item => item.fileId !== separator);
+        this.requestDTO.files = this.requestDTO.files.filter(item => item.fileOrdr !== separator);
       }
     },
 
@@ -294,14 +293,23 @@
 
         // 텍스트 데이터 추가
         formData.append('sj', this.requestDTO.sj);
-        formData.append('cn', this.requestDTO.cn);
-        formData.append('adres', this.requestDTO.adres);
-        formData.append('prdctnYear', this.requestDTO.prdctnYear);
         formData.append('ty', this.requestDTO.ty);
 
         // 게시물 아이디
         if (!this.$isEmpty(this.pageId)) {
           formData.append('dcryId', this.pageId);
+        }
+
+        if (!this.$isEmpty(this.requestDTO.prdctnYear)) {
+          formData.append('prdctnYear', this.requestDTO.prdctnYear);
+        }
+
+        if (!this.$isEmpty(this.requestDTO.adres)) {
+          formData.append('adres', this.requestDTO.adres);
+        }
+
+        if (!this.$isEmpty(this.requestDTO.cn)) {
+          formData.append('cn', this.requestDTO.cn);
         }
 
         // 파일 아이디
@@ -317,14 +325,16 @@
         }
 
         // 파일 추가
-        for (let file of this.multipartFiles) {
-          formData.append("multipartFiles", file);
+        if (this.multipartFiles.length > 0) {
+          for (let file of this.multipartFiles) {
+            formData.append("multipartFiles", file);
+          }
         }
 
         // 기존파일 수정
         if (!this.$isEmpty(this.pageId) && this.requestDTO.files.length > 0) {
           for (let file of this.requestDTO.files) {
-            formData.append("files", file.fileId);
+            formData.append("files", file.fileOrdr);
           }
         }
 
client/views/pages/bbsNesDta/NewsReleaseInsert.vue
--- client/views/pages/bbsNesDta/NewsReleaseInsert.vue
+++ client/views/pages/bbsNesDta/NewsReleaseInsert.vue
@@ -282,14 +282,21 @@
 
         // 텍스트 데이터 추가
         formData.append('sj', this.requestDTO.sj);
-        formData.append('cn', this.requestDTO.cn);
-        formData.append('link', this.requestDTO.link);
-        formData.append('prdctnYear', this.requestDTO.prdctnYear);
-        formData.append('ty', this.requestDTO.ty);
 
-        // 게시물 아이디
         if (!this.$isEmpty(this.pageId)) {
           formData.append('nesDtaId', this.pageId);
+        }
+
+        if (!this.$isEmpty(this.requestDTO.prdctnYear)) {
+          formData.append('prdctnYear', this.requestDTO.prdctnYear);
+        }
+
+        if (!this.$isEmpty(this.requestDTO.link)) {
+          formData.append('link', this.requestDTO.link);
+        }
+
+        if (!this.$isEmpty(this.requestDTO.cn)) {
+          formData.append('cn', this.requestDTO.cn);
         }
 
         // 파일 아이디
@@ -312,10 +319,15 @@
         // 기존파일 수정
         if (!this.$isEmpty(this.pageId) && this.requestDTO.files.length > 0) {
           for (let file of this.requestDTO.files) {
-            formData.append("files", file.fileId);
+            formData.append("files", file.fileOrdr);
           }
         }
 
+        // 썸네일 정보 추가
+        if (this.selectedThumb !== null) {
+          formData.append('selectedThumb', this.multipartFiles[0].name);
+        }
+
         // API 통신
         const response = this.$isEmpty(this.pageId) ? await saveNesDtaProc(formData) : await updateNesDtaProc(formData);
         alert(this.$isEmpty(this.pageId) ? "등록되었습니다." : "수정되었습니다.");
client/views/pages/bbsNesDta/NewsReleaseSearch.vue
--- client/views/pages/bbsNesDta/NewsReleaseSearch.vue
+++ client/views/pages/bbsNesDta/NewsReleaseSearch.vue
@@ -103,9 +103,7 @@
           <div v-else class="no-results">
             <img :src="nosearch" alt="">
             <p>검색 결과가 없습니다.</p>
-            <p>단어의 철자가 정확한지 확인해 주시기 바랍니다.<br>
-검색어의 단어 수를 줄이거나, 다른 검색어(유사어)로 검색해 보시기 바랍니다.<br>
-일반적으로 많이 사용하는 검색어로 다시 검색해 주시기 바랍니다.</p>
+            <p>단어의 철자가 정확한지 확인해 주시기 바랍니다.<br>검색어의 단어 수를 줄이거나, 다른 검색어(유사어)로 검색해 보시기 바랍니다.<br>일반적으로 많이 사용하는 검색어로 다시 검색해 주시기 바랍니다.</p>
           </div>
         </div>
       </div>
Add a comment
List