| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- <template>
- <main>
- <TopVisual :className="className" :title="title" :navigation="navigation" />
- <section class="news--section">
- <div class="sub--container type2">
- <div class="title--wrap">
- <h2 class="title">
- 친환경 플라스틱과 관련한 <br />
- <strong>새로운 소식들을 전해드립니다.</strong>
- </h2>
- </div>
- <div class="news--wrap">
- <div class="news--list">
- <a
- v-for="news in paginatedNews"
- :key="news.id"
- :href="news.link"
- target="_blank"
- rel="noopener noreferrer"
- class="news"
- >
- <div class="news--title--wrap">
- <h4>{{ news.title }}</h4>
- <span>{{ news.date }}</span>
- </div>
- <div class="news--thumb--wrap">
- <img :src="news.image" alt="" />
- </div>
- </a>
- </div>
- <div class="pagination--wrap">
- <UButton
- @click="prevPage"
- class="prev--btn"
- :disabled="currentPage === 1"
- ></UButton>
- <div class="numbs">
- <UButton
- v-for="page in totalPages"
- :key="page"
- @click="goToPage(page)"
- :class="{ active: currentPage === page }"
- >
- {{ page }}
- </UButton>
- </div>
- <UButton
- @click="nextPage"
- class="next--btn"
- :disabled="currentPage === totalPages"
- ></UButton>
- </div>
- </div>
- </div>
- </section>
- </main>
- </template>
- <script setup>
- import { ref, computed, onMounted } from "vue";
- import TopVisual from "~/components/topVisual.vue";
- const className = ref("media");
- const title = ref("Media");
- const navigation = ref([
- {
- name: "Media",
- link: "/media/news",
- gnbList: [
- { name: "Company", link: "/company/intro" },
- { name: "Product", link: "/products/materials" },
- { name: "Technology", link: "/technology/facilities" },
- { name: "Media", link: "/media/news" },
- { name: "Contact", link: "/contact/notice" },
- ],
- },
- {
- name: "환경뉴스",
- link: "/media/news",
- gnbList: [
- { name: "환경뉴스", link: "/media/news" },
- { name: "보도자료", link: "/media/press" },
- ],
- },
- ]);
- const loading = ref(true);
- const allNewsData = ref([]); // 전체 데이터를 누적하여 저장
- const newsData = ref([]);
- const totalCount = ref(0);
- const loadedPages = ref(new Set()); // 이미 로드한 백엔드 페이지 추적
- // API에서 뉴스 데이터 가져오기
- const fetchNewsList = async (page = 1, reset = false) => {
- try {
- // 이미 로드한 페이지는 스킵
- if (!reset && loadedPages.value.has(page)) {
- console.log(`페이지 ${page}는 이미 로드됨`);
- return;
- }
- loading.value = true;
- // 공지사항과 동일한 방식으로 호출
- const response = await $postForm(`/board_list/media`, {
- boardId: 'news',
- page: page,
- searchKind: "",
- searchKeyword: "",
- });
- // 백엔드가 JSON으로 응답하는지 확인
- if (response && typeof response === "object") {
- // JSON 응답인 경우
- if (response.success && response.list) {
- // 전체 개수와 현재 페이지를 기준으로 번호 계산
- totalCount.value = response.totalCount || 0;
- const currentPageNum = page || 1;
- const pageSize = 20; // 백엔드의 페이지 사이즈와 동일
- console.log("뉴스 API 응답:", {
- totalCount: totalCount.value,
- listCount: response.list.length,
- currentPage: currentPageNum,
- pageSize,
- backendPage: page,
- });
- const newData = response.list.map((item, index) => {
- // 번호 = 전체개수 - ((현재페이지-1) * 페이지크기 + 인덱스)
- const displayNumber = totalCount.value - ((currentPageNum - 1) * pageSize + index);
- return {
- id: displayNumber, // 순차적인 번호로 표시
- title: item.title,
- date: item.regdate,
- image: item.main_file1
- ? `http://green.interscope.co.kr/backend${item.main_file1}`
- : "/img/img--cycle--center.png", // 기본 이미지
- link: item.etc1 || "#", // etc1 필드에 외부 링크 저장
- };
- });
- if (reset) {
- // 리셋 모드: 전체 데이터 초기화
- allNewsData.value = newData;
- loadedPages.value = new Set([page]);
- } else {
- // 누적 모드: 새 데이터를 적절한 위치에 삽입
- const startIndex = (page - 1) * pageSize;
- allNewsData.value.splice(startIndex, pageSize, ...newData);
- loadedPages.value.add(page);
- }
- // newsData를 allNewsData로 업데이트
- newsData.value = [...allNewsData.value];
- } else {
- console.error("JSON 응답 형식이 올바르지 않습니다:", response);
- // 에러시 기본 더미 데이터 사용
- }
- } else if (typeof response === "string") {
- // HTML 응답인 경우 (백엔드에서 AJAX 감지 실패시)
- console.warn("HTML 응답을 받았습니다. AJAX 감지가 실패했을 수 있습니다.");
- console.log("HTML 내용:", response.substring(0, 200) + "...");
- // 기본 더미 데이터 사용
- } else {
- console.error("예상하지 못한 응답 형식:", typeof response, response);
- // 기본 더미 데이터 사용
- }
- } catch (error) {
- console.error("뉴스 데이터 로드 실패:", error);
- // 에러시 기본 더미 데이터 사용
- } finally {
- loading.value = false;
- }
- };
- // 페이지네이션 로직
- const currentPage = ref(1);
- const itemsPerPage = 10; // 프론트엔드에서 10개씩 표시
- const backendPageSize = 20; // 백엔드는 20개씩 가져옴
- const totalPages = computed(() => Math.ceil(totalCount.value / itemsPerPage));
- const paginatedNews = computed(() => {
- const start = (currentPage.value - 1) * itemsPerPage;
- const end = start + itemsPerPage;
- return newsData.value.slice(start, end);
- });
- // 백엔드에서 필요한 데이터가 있는지 확인하고 필요시 API 호출
- const needToFetchData = (targetPage) => {
- const startIndex = (targetPage - 1) * itemsPerPage;
- const endIndex = targetPage * itemsPerPage;
-
- // 필요한 데이터의 백엔드 페이지들 계산
- const startBackendPage = Math.floor(startIndex / backendPageSize) + 1;
- const endBackendPage = Math.ceil(endIndex / backendPageSize);
-
- // 아직 로드되지 않은 페이지가 있는지 확인
- for (let i = startBackendPage; i <= endBackendPage; i++) {
- if (!loadedPages.value.has(i)) {
- return i; // 로드가 필요한 백엔드 페이지 번호 반환
- }
- }
- return null; // 모든 필요한 데이터가 이미 로드됨
- };
- const goToPage = async (page) => {
- if (page >= 1 && page <= totalPages.value) {
- currentPage.value = page;
- const backendPageToLoad = needToFetchData(page);
- if (backendPageToLoad !== null) {
- console.log(`프론트엔드 페이지 ${page}를 위해 백엔드 페이지 ${backendPageToLoad} 로드`);
- await fetchNewsList(backendPageToLoad);
- }
- }
- };
- const nextPage = async () => {
- if (currentPage.value < totalPages.value) {
- await goToPage(currentPage.value + 1);
- }
- };
- const prevPage = async () => {
- if (currentPage.value > 1) {
- await goToPage(currentPage.value - 1);
- }
- };
- // 컴포넌트 마운트 시 데이터 로드
- onMounted(() => {
- fetchNewsList(1, true); // reset=true로 초기 로드
- });
- </script>
|