박정하 박정하 03-28
240328 박정하 기록물, 언론에서 바라본 구미시 폼 액션 수정
@a46a47a2590c81c1f73a0e2f6b9eebd2f80525da
client/views/component/listLayout/DefaultPagination.vue
--- client/views/component/listLayout/DefaultPagination.vue
+++ client/views/component/listLayout/DefaultPagination.vue
@@ -1,24 +1,30 @@
 <template>
   <div class="pagination flex-center">
-    <button type="button" :disabled="search.currentPage === search.startPage" @click="$emit('onChange', search.startPage)">
+    <!-- 첫 페이지로 이동 -->
+    <button type="button" :disabled="currentPage <= 1" @click="changePage(1)">
       <DoubleLeftOutlined />
     </button>
-    <button type="button" :disabled="!search.existPrevPage" @click="$emit('onChange', (search.currentPage - 1))">
+    <!-- 이전 페이지로 이동 -->
+    <button type="button" :disabled="currentPage <= 1" @click="changePage(currentPage - 1)">
       <LeftOutlined />
     </button>
-    <template v-for="idx in search.totalPageCount" :key="idx">
-      <button type="button" :class="{ 'page-number': true, clicked: search.currentPage === idx }" :disabled="search.currentPage === idx" @click="$emit('onChange', idx)">{{ idx }}</button>
+    <!-- 페이지 번호 버튼 -->
+    <template v-for="pageNum in displayedPageNumbers" :key="pageNum">
+      <button type="button" :class="{ 'page-number': true, clicked: currentPage === pageNum }" :disabled="currentPage === pageNum" @click="changePage(pageNum)"> {{ pageNum }} </button>
     </template>
-    <button type="button" :disabled="!search.existNextPage" @click="$emit('onChange', (search.currentPage + 1))">
+    <!-- 다음 페이지로 이동 -->
+    <button type="button" :disabled="currentPage >= totalPages" @click="changePage(currentPage + 1)">
       <RightOutlined />
     </button>
-    <button type="button" :disabled="search.currentPage === search.endPage" @click="$emit('onChange', search.endPage)">
+    <!-- 마지막 페이지로 이동 -->
+    <button type="button" :disabled="currentPage >= totalPages" @click="changePage(totalPages)">
       <DoubleRightOutlined />
     </button>
   </div>
 </template>
 <script>
 import { DoubleLeftOutlined, LeftOutlined, RightOutlined, DoubleRightOutlined } from '@ant-design/icons-vue';
+
 export default {
   components: {
     DoubleLeftOutlined,
@@ -30,15 +36,58 @@
   props: {
     search: {
       type: Object,
-      default: {},
+      required: true,
+      default: () => ({}),
     }
   },
 
-  methods: {},
+  computed: {
+    // 현재 페이지
+    currentPage() {
+      return this.search.currentPage;
+    },
+
+    // 총 페이지 수
+    totalPages() {
+      return this.search.totalPageCount > 0 ? this.search.totalPageCount : 1;
+    },
+
+    // 표시할 페이지 번호 목록
+    displayedPageNumbers() {
+      const currentPage = this.currentPage;
+      const totalPages = this.totalPages;
+
+      const visiblePages = this.search.pageSize > 0 ? this.search.pageSize : 10;
+
+      // 표시할 페이지 범위 계산
+      let startPageNum = Math.max(1, currentPage - Math.floor(visiblePages / 2));
+      let endPageNum = Math.min(totalPages, startPageNum + visiblePages - 1);
+
+      // endPage가 최대 페이지 수보다 작을 경우, startPage를 조정
+      if (endPageNum - startPageNum + 1 < visiblePages) {
+        startPageNum = Math.max(1, endPageNum - visiblePages + 1);
+      }
+
+      // 페이지 번호 배열 생성
+      const pageNumbers = [];
+      for (let i = startPageNum; i <= endPageNum; i++) {
+        pageNumbers.push(i);
+      }
+
+      return pageNumbers;
+    }
+  },
+
+  methods: {
+    // 페이지 변경 처리
+    changePage(pageNum) {
+      if (pageNum < 1) pageNum = 1;
+      if (pageNum > this.totalPages) pageNum = this.totalPages;
+
+      if (pageNum !== this.currentPage) {
+        this.$emit('onChange', pageNum);
+      }
+    }
+  }
 }
-</script>
-<style scoped>
-button:disabled {
-  cursor: not-allowed;
-}
-</style>
(파일 끝에 줄바꿈 문자 없음)
+</script>
(파일 끝에 줄바꿈 문자 없음)
client/views/pages/bbsDcry/photo/PicHistoryDetail.vue
--- client/views/pages/bbsDcry/photo/PicHistoryDetail.vue
+++ client/views/pages/bbsDcry/photo/PicHistoryDetail.vue
@@ -4,7 +4,8 @@
       <h2>사진 기록물</h2>
       <div class="breadcrumb-list">
         <ul>
-          <li><img :src="homeicon" alt="Home Icon">
+          <li>
+            <img :src="homeicon" alt="Home Icon">
             <p>기록물</p>
           </li>
           <li><img :src="righticon" alt=""></li>
@@ -12,13 +13,13 @@
         </ul>
       </div>
     </div>
-    <div class="gallery-form mb-40">
+    <form class="gallery-form mb-40" @submit.prevent>
       <dl class="mb-20">
         <dd>
-          <p>{{ dcry.sj }}</p>
+          <p>{{ findResult.sj }}</p>
           <div class="date flex align-center">
             <img :src="calendaricon" alt="">
-            <span>{{ $dotFormatDate(dcry.rgsde) }}</span>
+            <span>{{ $dotFormatDate(findResult.rgsde) }}</span>
           </div>
         </dd>
       </dl>
@@ -26,14 +27,14 @@
         <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-slide v-for="(item, idx) of dcry.files" :key="idx">
+              <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-slide v-for="(item, idx) of dcry.files" :key="idx">
+              <swiper-slide v-for="(item, idx) of findResult.files" :key="idx">
                 <input type="checkbox" :id="'photo_' + idx" :value="item.fileId" v-model="selectedFiles" />
                 <img :src="item.filePath" :alt="item.fileNm" />
               </swiper-slide>
@@ -45,41 +46,41 @@
           <button class="all-down" @click="fnDownload('all')">전체 다운로드</button>
         </div>
       </div>
-    </div>
+    </form>
     <h3>내용</h3>
-    <div class="info-form mb-50">
+    <form class="info-form mb-50" @submit.prevent>
       <dl>
         <dd>
-          <ViewerComponent :content="dcry.cn" />
+          <ViewerComponent :content="findResult.cn" />
         </dd>
       </dl>
-    </div>
+    </form>
     <h3>기본정보</h3>
-    <div class="info-form mb-50">
+    <form class="info-form mb-50" @submit.prevent>
       <dl>
         <dd class="mb-20">
           <img :src="addressicon" alt="">
           <span>주소</span>
-          <p>{{ dcry.adres }}</p>
+          <p>{{ findResult.adres }}</p>
         </dd>
         <dd class="mb-20">
           <img :src="yearicon" alt="">
           <span>생산연도</span>
-          <p>{{ $dotFormatDate(dcry.prdctnYear) }}</p>
+          <p>{{ $dotFormatDate(findResult.prdctnYear) }}</p>
         </dd>
         <dd>
           <img :src="categoryicon" alt="">
           <span>카테고리</span>
           <ul class="category">
-            <li v-for="(item, idx) of dcry.ctgrys" :key="idx" class="category">{{ item.ctgryNm }}</li>
+            <li v-for="(item, idx) of findResult.ctgrys" :key="idx" class="category">{{ item.ctgryNm }}</li>
           </ul>
         </dd>
       </dl>
-    </div>
+    </form>
     <div class="btn-group flex-center">
       <button class="red-line " type="button" @click="fnDelete">삭제</button>
-      <button class="blue-line " type="button" @click="fnMoveTo('PicHistoryInsert', pageId)">수정</button>
-      <button class="gray-line-bg " type="button" @click="fnMoveTo('PicHistorySearch')">목록</button>
+      <button class="blue-line " type="button" @click="fnMoveTo('edit', pageId)">수정</button>
+      <button class="gray-line-bg " type="button" @click="fnMoveTo('list')">목록</button>
     </div>
   </div>
 </template>
@@ -136,7 +137,7 @@
       categoryicon: 'client/resources/images/icon/categoryicon.png',
 
       pageId: null,
-      dcry: {},
+      findResult: {},
       selectedFiles: [],
     };
   },
@@ -145,7 +146,7 @@
     this.pageId = this.$route.query.id;
     if (this.pageId === null) {
       alert("게시물 존재하지 않습니다.");
-      this.fnMoveTo('PicHistorySearch');
+      this.fnMoveTo('list');
     }
   },
 
@@ -159,15 +160,14 @@
       try {
         const response = await findDcryProc(this.pageId);
 
-        if (response.data.data.dcry.ty !== 'P') {
+        this.findResult = response.data.data.dcry;
+        if (this.findResult.ty !== 'P') {
           alert('올바른 접근이 아닙니다.');
-          this.fnMoveTo('PicHistorySearch'); // 목록으로 이동
+          this.fnMoveTo('list'); // 목록으로 이동
         }
-
-        this.dcry = response.data.data.dcry;
       } catch (error) {
         alert('조회중 오류가 발생했습니다.');
-        this.fnMoveTo('PicHistorySearch');
+        this.fnMoveTo('list');
 
         if (error.response) {
           alert(error.response.data.message);
@@ -190,8 +190,8 @@
       try {
         // 파일 ID 수집
         let fileIds = this.selectedFiles[0];
-        if (type === 'all' && this.dcry.files.length > 1) {
-          fileIds = this.dcry.files.map(file => file.fileId).join(',');
+        if (type === 'all' && this.findResult.files.length > 1) {
+          fileIds = this.findResult.files.map(file => file.fileId).join(',');
         }
 
         let isMultiple = fileIds.length > 1;
@@ -238,7 +238,7 @@
         const response = await deleteDcryProc(this.pageId);
         alert('해당 페이지를 삭제했습니다.');
 
-        this.fnMoveTo('PicHistorySearch');
+        this.fnMoveTo('list');
       } catch (error) {
         if (error.response) {
           alert(error.response.data.message);
@@ -248,11 +248,18 @@
     },
 
     // 페이지 이동
-    fnMoveTo(page, id) {
-      if (this.$isEmpty(id)) {
-        this.$router.push({ name: page });
+    fnMoveTo(type, id) {
+      const routes = {
+        'list': { name: 'PicHistorySearch' },
+        'view': { name: 'PicHistoryDetail', query: { id } },
+        'edit': { name: 'PicHistoryInsert', query: this.$isEmpty(id) ? {} : { id } },
+      };
+
+      if (routes[type]) {
+        this.$router.push(routes[type]);
       } else {
-        this.$router.push({ name: page, query: { id: id } });
+        alert("올바르지 않은 경로를 요청하여 목록으로 이동합니다.");
+        this.$router.push(routes['list']);
       }
     },
   },
client/views/pages/bbsDcry/photo/PicHistoryInsert.vue
--- client/views/pages/bbsDcry/photo/PicHistoryInsert.vue
+++ client/views/pages/bbsDcry/photo/PicHistoryInsert.vue
@@ -4,7 +4,8 @@
       <h2>사진 기록물</h2>
       <div class="breadcrumb-list">
         <ul>
-          <li><img :src="homeicon" alt="Home Icon">
+          <li>
+            <img :src="homeicon" alt="Home Icon">
             <p>기록물</p>
           </li>
           <li><img :src="righticon" alt=""></li>
@@ -12,7 +13,7 @@
         </ul>
       </div>
     </div>
-    <form class="insert-form mb-50">
+    <form class="insert-form mb-50" @submit.prevent>
       <dl>
         <dd>
           <label for="sj" class="require">제목</label>
client/views/pages/bbsDcry/photo/PicHistorySearch.vue
--- client/views/pages/bbsDcry/photo/PicHistorySearch.vue
+++ client/views/pages/bbsDcry/photo/PicHistorySearch.vue
@@ -38,7 +38,7 @@
         </dd>
         <dd class="mb-15">
           <p>검색어</p>
-          <div class="wfull"><input type="text" v-model="searchReqDTO.searchText" v-on:keyup.enter="fnSearch()"></div>
+          <div class="wfull"><input type="text" v-model="searchReqDTO.searchText" v-on:keyup.enter="fnChnageReqDTO"></div>
         </dd>
         <dd class="mb-15">
           <p>생산연도</p>
@@ -69,7 +69,7 @@
             <img :src="reseticon" alt="">
             <p>초기화</p>
           </button>
-          <button type="button" class="search" @click="fnSearch">
+          <button type="button" class="search" @click="fnChnageReqDTO">
             <img :src="searchicon" alt="">
             <p>검색</p>
           </button>
@@ -91,7 +91,7 @@
               </li>
             </ul>
             <div class="select-box">
-              <select v-model="searchReqDTO.recordSize" @change="fnSearch">
+              <select v-model="searchReqDTO.recordSize" @change="fnChnageReqDTO">
                 <option :value="24">24개</option>
                 <option :value="36">36개</option>
                 <option :value="100">100개</option>
@@ -197,20 +197,16 @@
     this.fnFindCategorys(); // 카테고리 목록 조회 (검색조건 없음)
   },
 
-  mounted() {
-    let searchText = this.$route.query.searchText;
-    if (searchText !== null) {
-      this.searchReqDTO.searchText = searchText;
-    }
-
-    this.fnSearch(); // 통합검색
-  },
-
   methods: {
     // 초기화
     init() {
       if (this.isInitialLoad) {
         this.isInitialLoad = false;
+
+        let searchText = this.$route.query.searchText;
+        if (searchText !== null) {
+          this.searchReqDTO.searchText = searchText;
+        }
       } else {
         if (!confirm('검색 조건을 초기화하시겠습니까?')) {
           return;
@@ -244,7 +240,15 @@
     fnChangeCurrentPage(currentPage) {
       this.searchReqDTO.currentPage = Number(currentPage);
       this.$nextTick(() => {
-        this.fnFindCategorys();
+        this.fnSearch();
+      });
+    },
+
+    // 검색 조건이 변경된 경우
+    fnChnageReqDTO() {
+      this.searchReqDTO.currentPage = 1;
+      this.$nextTick(() => {
+        this.fnSearch();
       });
     },
 
client/views/pages/bbsDcry/video/VideoHistoryDetail.vue
--- client/views/pages/bbsDcry/video/VideoHistoryDetail.vue
+++ client/views/pages/bbsDcry/video/VideoHistoryDetail.vue
@@ -12,13 +12,13 @@
         </ul>
       </div>
     </div>
-    <form action="" class="gallery-form mb-40">
+    <form class="gallery-form mb-40" @submit.prevent>
       <dl class="mb-20">
         <dd>
-          <p>{{ dcry.sj }}</p>
+          <p>{{ findResult.sj }}</p>
           <div class="date flex align-center">
             <img :src="calendaricon" alt="">
-            <span>{{ $dotFormatDate(dcry.rgsde) }}</span>
+            <span>{{ $dotFormatDate(findResult.rgsde) }}</span>
           </div>
         </dd>
       </dl>
@@ -27,88 +27,58 @@
       </div>
     </form>
     <h3>내용</h3>
-    <form action="" class=" info-form mb-50">
+    <form class=" info-form mb-50" @submit.prevent>
       <dl>
         <dd>
-          <p> 대한민국 최대의 내륙 산업단지를 보유하고, 서울로부터 277km, 부산으로부터 167km 거리에 있으며, 면적은 615㎢로 경상북도 전체 면적의 3.2%에 달합니다. 인구는 41만 명이고, 선산읍, 고아읍, 산동읍을 비롯한 3읍, 5면, 17개 동으로 구성되어 있습니다.</p>
+          <ViewerComponent :content="findResult.cn" />
         </dd>
       </dl>
     </form>
     <h3>기본정보</h3>
-    <form action="" class="info-form mb-50">
+    <form class="info-form mb-50" @submit.prevent>
       <dl>
         <dd class="mb-20">
           <img :src="addressicon" alt="">
           <span>주소</span>
-          <p>경상북도 구미시 송정대로 55</p>
+          <p>{{ findResult.adres }}</p>
         </dd>
         <dd class="mb-20">
           <img :src="yearicon" alt="">
           <span>생산연도</span>
-          <p>2017</p>
+          <p>{{ $dotFormatDate(findResult.prdctnYear) }}</p>
         </dd>
         <dd>
           <img :src="categoryicon" alt="">
           <span>카테고리</span>
           <ul class="category">
-            <li v-if="resultitem.category1" class="category1">카테고리1</li>
-            <li v-if="resultitem.category2" class="category2">카테고리2</li>
+            <li v-for="(item, idx) of findResult.ctgrys" :key="idx" class="category">{{ item.ctgryNm }}</li>
           </ul>
         </dd>
       </dl>
     </form>
     <div class="btn-group flex-center">
-      <button class="red-line " type="button" @click="fnDeleteUser">삭제</button>
-      <button class="blue-line " type="button" @click="fnUpdateUser">수정</button>
-      <button class="gray-line-bg " type="button" @click="fnUpdateUser">목록</button>
-      <button class="gradient ">다운로드</button>
+      <button type="button" class="red-line" @click="fnDelete">삭제</button>
+      <button type="button" class="blue-line" @click="fnMoveTo('edit', pageId)">수정</button>
+      <button type="button" class="gray-line-bg" @click="fnMoveTo('list')">목록</button>
+      <button type="button" class="gradient" @click="fnDownload">다운로드</button>
     </div>
   </div>
 </template>
 <script>
-import axios from "axios";
-import { ref } from 'vue';
-import { updateUsers, logOutProc, updatePassword } from "../../../../resources/api/user"
-// Import Swiper Vue components
-import { CaretRightOutlined, PauseOutlined } from '@ant-design/icons-vue';
-import { Swiper, SwiperSlide } from 'swiper/vue';
-
-// Import Swiper styles
-import 'swiper/css';
-
-import 'swiper/css/free-mode';
-import 'swiper/css/navigation';
-import 'swiper/css/thumbs';
-
-// import required modules
-import { FreeMode, Navigation, Thumbs } from 'swiper/modules';
+// COMPONENT
+import ViewerComponent from '../../../component/editor/ViewerComponent.vue';
+// API
+import { findDcryProc, deleteDcryProc } from '@/resources/api/dcry';
+import { fileDownloadProc, multiFileDownloadProc } from '@/resources/api/file';
 
 export default {
   components: {
-    PauseOutlined,
-    CaretRightOutlined,
-    Swiper,
-    SwiperSlide,
+    ViewerComponent,
   },
-  setup() {
-    const thumbsSwiper = ref(null);
 
-    const setThumbsSwiper = (swiper) => {
-      thumbsSwiper.value = swiper;
-    };
-
-    return {
-      thumbsSwiper,
-      setThumbsSwiper,
-      modules: [FreeMode, Navigation, Thumbs],
-    };
-  },
   data() {
     return {
-      resultitem: {
-        category1: true,
-        category2: true,
-      },
+      // ICON
       calendaricon: 'client/resources/images/icon/calendaricon.png',
       homeicon: 'client/resources/images/icon/home.png',
       erroricon: 'client/resources/images/icon/error.png',
@@ -116,24 +86,122 @@
       addressicon: 'client/resources/images/icon/addressicon.png',
       yearicon: 'client/resources/images/icon/yearicon.png',
       categoryicon: 'client/resources/images/icon/categoryicon.png',
-      eximg: 'client/resources/images/img8.png',
-      slides: [
-        { img: 'client/resources/images/visual.png', alt: 'Slide 1' },
-        { img: 'client/resources/images/visual.png', alt: 'Slide 2' },
-        { img: 'client/resources/images/visual.png', alt: 'Slide 3' },
-        { img: 'client/resources/images/visual.png', alt: 'Slide 3' },
-        { img: 'client/resources/images/visual.png', alt: 'Slide 3' },
-        { img: 'client/resources/images/visual.png', alt: 'Slide 3' },
-        // Add more slides as needed
-      ],
 
+      pageId: null,
+      findResult: {},
+      selectedFiles: [],
     };
   },
+
+  created() {
+    this.pageId = this.$route.query.id;
+    if (this.pageId === null) {
+      alert("게시물 존재하지 않습니다.");
+      this.fnMoveTo('list');
+    }
+  },
+
+  mounted() {
+    this.fnFindDcry(); // 상세 조회
+  },
+
   methods: {
+    // 상세 조회
+    async fnFindDcry() {
+      try {
+        const response = await findDcryProc(this.pageId);
+
+        this.findResult = response.data.data.dcry;
+        if (this.findResult.ty !== 'V') {
+          alert('올바른 접근이 아닙니다.');
+          this.fnMoveTo('list'); // 목록으로 이동
+        }
+      } catch (error) {
+        alert('조회중 오류가 발생했습니다.');
+        this.fnMoveTo('list');
+
+        if (error.response) {
+          alert(error.response.data.message);
+        }
+        console.error(error.message);
+      }
+    },
+
+    // 파일 다운로드
+    async fnDownload() {
+      let url = null;
+      let link = null;
+
+      try {
+        // 파일 ID 수집
+        let fileId = this.findResult.files[0].fileId;
+        const response = await fileDownloadProc(fileId);
+
+        // 파일명 조회
+        let filename = 'downloadFile.bin';
+        const filenameRegex = /file[Nn]ame[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
+        const matches = filenameRegex.exec(response.headers['content-disposition']);
+        if (matches != null && matches[1]) {
+          filename = matches[1].replace(/['"]/g, '');
+        }
+
+        // 파일 다운로드 생성
+        url = window.URL.createObjectURL(new Blob([response.data]));
+        link = document.createElement('a');
+        link.href = url;
+        link.setAttribute('download', filename);
+        document.body.appendChild(link);
+        link.click();
+      } catch (error) {
+        alert('파일 다운로드 중 오류가 발생했습니다.');
+      } finally {
+        // 리소스 정리
+        setTimeout(() => {
+          if (url) {
+            window.URL.revokeObjectURL(url);
+          }
+          if (link && link.parentNode) {
+            document.body.removeChild(link);
+          }
+        }, 100);
+      }
+    },
+
+    // 삭제
+    async fnDelete() {
+      let isCheck = confirm("해당 페이지를 삭제하시겠습니까?");
+      if (!isCheck) {
+        return;
+      }
+
+      try {
+        const response = await deleteDcryProc(this.pageId);
+        alert('해당 페이지를 삭제했습니다.');
+
+        this.fnMoveTo('list');
+      } catch (error) {
+        if (error.response) {
+          alert(error.response.data.message);
+        }
+        console.error(error.message);
+      }
+    },
+
+    // 페이지 이동
+    fnMoveTo(type, id) {
+      const routes = {
+        'list': { name: 'VideoHistorySearch' },
+        'view': { name: 'VideoHistoryDetail', query: { id } },
+        'edit': { name: 'VideoHistoryInsert', query: this.$isEmpty(id) ? {} : { id } },
+      };
+
+      if (routes[type]) {
+        this.$router.push(routes[type]);
+      } else {
+        alert("올바르지 않은 경로를 요청하여 목록으로 이동합니다.");
+        this.$router.push(routes['list']);
+      }
+    },
   },
-  watch: {},
-  computed: {
-  },
-  mounted() { },
 };
 </script>
(파일 끝에 줄바꿈 문자 없음)
client/views/pages/bbsDcry/video/VideoHistoryInsert.vue
--- client/views/pages/bbsDcry/video/VideoHistoryInsert.vue
+++ client/views/pages/bbsDcry/video/VideoHistoryInsert.vue
@@ -12,7 +12,7 @@
         </ul>
       </div>
     </div>
-    <form class="insert-form mb-50">
+    <form class="insert-form mb-50" @submit.prevent>
       <dl>
         <dd>
           <label for="sj" class="require">제목</label>
client/views/pages/bbsDcry/video/VideoHistorySearch.vue
--- client/views/pages/bbsDcry/video/VideoHistorySearch.vue
+++ client/views/pages/bbsDcry/video/VideoHistorySearch.vue
@@ -38,7 +38,7 @@
         </dd>
         <dd class="mb-15">
           <p>검색어</p>
-          <div class="wfull"><input type="text" v-model="searchReqDTO.searchText" v-on:keyup.enter="fnSearch()"></div>
+          <div class="wfull"><input type="text" v-model="searchReqDTO.searchText" v-on:keyup.enter="fnChnageReqDTO"></div>
         </dd>
         <dd class="mb-15">
           <p>생산연도</p>
@@ -69,7 +69,7 @@
             <img :src="reseticon" alt="">
             <p>초기화</p>
           </button>
-          <button type="button" class="search" @click="fnSearch">
+          <button type="button" class="search" @click="fnChnageReqDTO">
             <img :src="searchicon" alt="">
             <p>검색</p>
           </button>
@@ -91,7 +91,7 @@
               </li>
             </ul>
             <div class="select-box">
-              <select v-model="searchReqDTO.recordSize" @change="fnSearch">
+              <select v-model="searchReqDTO.recordSize" @change="fnChnageReqDTO">
                 <option :value="24">24개</option>
                 <option :value="36">36개</option>
                 <option :value="100">100개</option>
@@ -197,20 +197,16 @@
     this.fnFindCategorys(); // 카테고리 목록 조회 (검색조건 없음)
   },
 
-  mounted() {
-    let searchText = this.$route.query.searchText;
-    if (searchText !== null) {
-      this.searchReqDTO.searchText = searchText;
-    }
-
-    this.fnSearch(); // 통합검색
-  },
-
   methods: {
     // 초기화
     init() {
       if (this.isInitialLoad) {
         this.isInitialLoad = false;
+
+        let searchText = this.$route.query.searchText;
+        if (searchText !== null) {
+          this.searchReqDTO.searchText = searchText;
+        }
       } else {
         if (!confirm('검색 조건을 초기화하시겠습니까?')) {
           return;
@@ -222,7 +218,7 @@
 
       this.selectedTabId = this.tabs[0].id;
 
-      this.fnSearch(); // 통합검색
+      this.fnChnageReqDTO(); // 통합검색
     },
 
     // 카테고리 목록 조회
@@ -248,6 +244,14 @@
       });
     },
 
+    // 검색 조건이 변경된 경우
+    fnChnageReqDTO() {
+      this.searchReqDTO.currentPage = 1;
+      this.$nextTick(() => {
+        this.fnSearch();
+      });
+    },
+
     // 통합검색
     async fnSearch() {
       try {
client/views/pages/bbsMediaVido/MediaVideoDetail.vue
--- client/views/pages/bbsMediaVido/MediaVideoDetail.vue
+++ client/views/pages/bbsMediaVido/MediaVideoDetail.vue
@@ -12,54 +12,54 @@
         </ul>
       </div>
     </div>
-    <div class="gallery-form mb-40">
+    <form class="gallery-form mb-40" @submit.prevent>
       <dl class="mb-20">
         <dd>
-          <p>{{ mediaVido.sj }} </p>
+          <p>{{ findResult.sj }} </p>
           <div class="date flex align-center">
             <img :src="calendaricon" alt="">
-            <span>{{ $dotFormatDate(mediaVido.rgsde) }}</span>
+            <span>{{ $dotFormatDate(findResult.rgsde) }}</span>
           </div>
         </dd>
       </dl>
       <div class="gallery video">
-        <Youtube-component :link="mediaVido.link" />
+        <Youtube-component :link="findResult.link" />
       </div>
-    </div>
+    </form>
     <h3>내용</h3>
-    <div class="info-form mb-50">
+    <form class="info-form mb-50" @submit.prevent>
       <dl>
         <dd>
-          <Viewer-component :content="mediaVido.cn" />
+          <Viewer-component :content="findResult.cn" />
         </dd>
       </dl>
-    </div>
+    </form>
     <h3>기본정보</h3>
-    <div class="info-form mb-50">
+    <form class="info-form mb-50" @submit.prevent>
       <dl>
         <dd class="mb-20">
           <img :src="addressicon" alt="">
           <span>원본주소</span>
-          <p>{{ mediaVido.link }}</p>
+          <p>{{ findResult.link }}</p>
         </dd>
         <dd class="mb-20">
           <img :src="yearicon" alt="">
           <span>생산연도</span>
-          <p>{{ $dotFormatDate(mediaVido.prdctnYear) }}</p>
+          <p>{{ $dotFormatDate(findResult.prdctnYear) }}</p>
         </dd>
         <dd>
           <img :src="categoryicon" alt="">
           <span>카테고리</span>
           <ul class="category">
-            <li v-for="(item, idx) of mediaVido.ctgrys" :key="idx" class="category">{{ item.ctgryNm }}</li>
+            <li v-for="(item, idx) of findResult.ctgrys" :key="idx" class="category">{{ item.ctgryNm }}</li>
           </ul>
         </dd>
       </dl>
-    </div>
+    </form>
     <div class="btn-group flex-center">
       <button class="red-line " type="button" @click="fnDelete">삭제</button>
-      <button class="blue-line " type="button" @click="fnMoveTo('MediaVideoInsert', pageId)">수정</button>
-      <button class="gray-line-bg " type="button" @click="fnMoveTo('MediaVideoSearch')">목록</button>
+      <button class="blue-line " type="button" @click="fnMoveTo('edit', pageId)">수정</button>
+      <button class="gray-line-bg " type="button" @click="fnMoveTo('list')">목록</button>
     </div>
   </div>
 </template>
@@ -89,7 +89,7 @@
       categoryicon: 'client/resources/images/icon/categoryicon.png',
 
       pageId: null,
-      mediaVido: {},
+      findResult: {},
       selectedFiles: [],
     };
   },
@@ -98,7 +98,7 @@
     this.pageId = this.$route.query.id;
     if (this.pageId === null) {
       alert("게시물 존재하지 않습니다.");
-      this.fnMoveTo('MediaVideoSearch');
+      this.fnMoveTo('list');
     }
   },
 
@@ -111,10 +111,10 @@
     async fnFindDcry() {
       try {
         const response = await findMediaVidoProc(this.pageId);
-        this.mediaVido = response.data.data.mediaVido;
+        this.findResult = response.data.data.mediaVido;
       } catch (error) {
         alert('조회중 오류가 발생했습니다.');
-        this.fnMoveTo('MediaVideoSearch');
+        this.fnMoveTo('list');
 
         if (error.response) {
           alert(error.response.data.message);
@@ -179,7 +179,7 @@
         const response = await deleteMediaVidoProc(this.pageId);
         alert('해당 페이지를 삭제했습니다.');
 
-        this.fnMoveTo('MediaVideoSearch');
+        this.fnMoveTo('list');
       } catch (error) {
         if (error.response) {
           alert(error.response.data.message);
@@ -189,11 +189,18 @@
     },
 
     // 페이지 이동
-    fnMoveTo(page, id) {
-      if (this.$isEmpty(id)) {
-        this.$router.push({ name: page });
+    fnMoveTo(type, id) {
+      const routes = {
+        'list': { name: 'MediaVideoSearch' },
+        'view': { name: 'MediaVideoDetail', query: { id } },
+        'edit': { name: 'MediaVideoInsert', query: this.$isEmpty(id) ? {} : { id } },
+      };
+
+      if (routes[type]) {
+        this.$router.push(routes[type]);
       } else {
-        this.$router.push({ name: page, query: { id: id } });
+        alert("올바르지 않은 경로를 요청하여 목록으로 이동합니다.");
+        this.$router.push(routes['list']);
       }
     },
   },
client/views/pages/bbsMediaVido/MediaVideoInsert.vue
--- client/views/pages/bbsMediaVido/MediaVideoInsert.vue
+++ client/views/pages/bbsMediaVido/MediaVideoInsert.vue
@@ -12,7 +12,7 @@
         </ul>
       </div>
     </div>
-    <form class="insert-form mb-50">
+    <form class="insert-form mb-50" @submit.prevent>
       <dl>
         <dd>
           <label for="sj" class="require">제목</label>
client/views/pages/bbsMediaVido/MediaVideoSearch.vue
--- client/views/pages/bbsMediaVido/MediaVideoSearch.vue
+++ client/views/pages/bbsMediaVido/MediaVideoSearch.vue
@@ -33,7 +33,7 @@
         </dd>
         <dd class="mb-15">
           <p>검색어</p>
-          <div class="wfull"><input type="text" v-model="searchReqDTO.searchText" v-on:keyup.enter="fnSearch()"></div>
+          <div class="wfull"><input type="text" v-model="searchReqDTO.searchText" v-on:keyup.enter="fnChnageReqDTO"></div>
         </dd>
         <dd class="mb-15">
           <p>생산연도</p>
@@ -64,7 +64,7 @@
             <img :src="reseticon" alt="">
             <p>초기화</p>
           </button>
-          <button type="button" class="search" @click="fnSearch">
+          <button type="button" class="search" @click="fnChnageReqDTO">
             <img :src="searchicon" alt="">
             <p>검색</p>
           </button>
@@ -86,7 +86,7 @@
               </li>
             </ul>
             <div class="select-box">
-              <select v-model="searchReqDTO.recordSize" @change="fnSearch">
+              <select v-model="searchReqDTO.recordSize" @change="fnChnageReqDTO">
                 <option :value="24">24개</option>
                 <option :value="36">36개</option>
                 <option :value="100">100개</option>
@@ -190,20 +190,16 @@
     this.fnFindCategorys(); // 카테고리 목록 조회 (검색조건 없음)
   },
 
-  mounted() {
-    let searchText = this.$route.query.searchText;
-    if (searchText !== null) {
-      this.searchReqDTO.searchText = searchText;
-    }
-
-    this.fnSearch(); // 통합검색
-  },
-
   methods: {
     // 초기화
     init() {
       if (this.isInitialLoad) {
         this.isInitialLoad = false;
+
+        let searchText = this.$route.query.searchText;
+        if (searchText !== null) {
+          this.searchReqDTO.searchText = searchText;
+        }
       } else {
         if (!confirm('검색 조건을 초기화하시겠습니까?')) {
           return;
@@ -215,7 +211,7 @@
 
       this.selectedTabId = this.tabs[0].id;
 
-      this.fnSearch(); // 통합검색
+      this.fnChnageReqDTO(); // 통합검색
     },
 
     // 카테고리 목록 조회
@@ -236,7 +232,17 @@
     // 페이지 이동
     fnChangeCurrentPage(currentPage) {
       this.searchReqDTO.currentPage = Number(currentPage);
-      this.fnFindCategorys();
+      this.$nextTick(() => {
+        this.fnSearch();
+      });
+    },
+
+    // 검색 조건이 변경된 경우
+    fnChnageReqDTO() {
+      this.searchReqDTO.currentPage = 1;
+      this.$nextTick(() => {
+        this.fnSearch();
+      });
     },
 
     // 통합검색
client/views/pages/bbsNesDta/NewsReleaseSearch.vue
--- client/views/pages/bbsNesDta/NewsReleaseSearch.vue
+++ client/views/pages/bbsNesDta/NewsReleaseSearch.vue
@@ -34,7 +34,7 @@
         </dd>
         <dd class="mb-15">
           <p>검색어</p>
-          <div class="wfull"><input type="text" v-model="searchReqDTO.searchText" v-on:keyup.enter="fnSearch()"></div>
+          <div class="wfull"><input type="text" v-model="searchReqDTO.searchText" v-on:keyup.enter="fnChnageReqDTO"></div>
         </dd>
         <dd class="mb-15">
           <p>생산연도</p>
@@ -65,7 +65,7 @@
             <img :src="reseticon" alt="">
             <p>초기화</p>
           </button>
-          <button type="button" class="search" @click="fnSearch">
+          <button type="button" class="search" @click="fnChnageReqDTO">
             <img :src="searchicon" alt="">
             <p>검색</p>
           </button>
@@ -87,7 +87,7 @@
               </li>
             </ul>
             <div class="select-box">
-              <select v-model="searchReqDTO.recordSize" @change="fnSearch">
+              <select v-model="searchReqDTO.recordSize" @change="fnChnageReqDTO">
                 <option :value="24">24개</option>
                 <option :value="36">36개</option>
                 <option :value="100">100개</option>
@@ -191,20 +191,16 @@
     this.fnFindCategorys(); // 카테고리 목록 조회 (검색조건 없음)
   },
 
-  mounted() {
-    let searchText = this.$route.query.searchText;
-    if (searchText !== null) {
-      this.searchReqDTO.searchText = searchText;
-    }
-
-    this.fnSearch(); // 통합검색
-  },
-
   methods: {
     // 초기화
     init() {
       if (this.isInitialLoad) {
         this.isInitialLoad = false;
+
+        let searchText = this.$route.query.searchText;
+        if (searchText !== null) {
+          this.searchReqDTO.searchText = searchText;
+        }
       } else {
         if (!confirm('검색 조건을 초기화하시겠습니까?')) {
           return;
@@ -216,7 +212,7 @@
 
       this.selectedTabId = this.tabs[0].id;
 
-      this.fnSearch(); // 통합검색
+      this.fnChnageReqDTO(); // 통합검색
     },
 
     // 카테고리 목록 조회
@@ -237,7 +233,17 @@
     // 페이지 이동
     fnChangeCurrentPage(currentPage) {
       this.searchReqDTO.currentPage = Number(currentPage);
-      this.fnFindCategorys();
+      this.$nextTick(() => {
+        this.fnSearch();
+      });
+    },
+
+    // 검색 조건이 변경된 경우
+    fnChnageReqDTO() {
+      this.searchReqDTO.currentPage = 1;
+      this.$nextTick(() => {
+        this.fnSearch();
+      });
     },
 
     // 통합검색
Add a comment
List