naweigete-web/pages/index_product_s.vue

355 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="bg-white">
<!-- Banner section with background image -->
<div class="aboutimgBg">
<div class="pl-4 md:pl-[200px]">
<div class="newsTit">
<h2 class="animated fadeInLeft text-2xl md:text-[40px] font-bold">{{ $t('list_p1') }}</h2>
<h3 class="animated fadeInLeft text-lg md:text-[25px] font-medium mt-3 md:mt-[30px] text-[#606060]">{{ $t('list_p2') }}</h3>
</div>
</div>
</div>
<!-- Featured news section -->
<div class="newsBox1 container mx-auto px-4 py-8 flex flex-col md:flex-row flex-wrap" v-if="newsList.length > 0">
<div class="newsBox1lider w-full md:w-[38%] mb-6 md:mb-0">
<img id="featuredImage" :src="topImg" class="h-[200px] md:h-[300px] w-full object-cover rounded-[5px]" />
</div>
<div class="newsTit1 w-full md:w-[62%] relative pl-0 md:pl-4 mt-6 md:mt-0">
<div id="swipen_next" class="absolute left-0 md:left-4 top-[70%] -translate-y-1/2 cursor-pointer z-10" @click="prevSlide">
<img src="/images/group10.png" class="w-[40px] md:w-[50px]" alt="Previous" />
</div>
<div id="swipen_prev" class="absolute right-0 md:right-4 top-[70%] -translate-y-1/2 cursor-pointer z-10" @click="nextSlide">
<img src="/images/group9-1.png" class="w-[40px] md:w-[50px]" alt="Next" />
</div>
<div class="flex justify-end items-center mb-4">
<div class="relative pr-3 md:pr-5">
<h2 class="t7 m-0">
<span id="time1" class="newsSpan1 text-2xl md:text-[40px]">{{ formatYear(currentNews.inputtime || currentNews.add_time) }}/</span>
<span id="time2" class="newsSpan2 text-xl md:text-[28px]">{{ formatDate(currentNews.inputtime || currentNews.add_time) }}</span>
</h2>
</div>
<div class="text-right">
<span class="t6 text-lg md:text-[25px] font-semibold">{{ $t('list_p1') }}</span>
</div>
</div>
<div class="newsdi w-full h-[1px] bg-gray-300 my-3 md:my-4"></div>
<div class="listSwiper overflow-hidden w-full md:w-[90%] h-[115px] md:h-[200px]">
<div class="swiper-wrapper w-full">
<span v-if="!isMobile" class="newsbs2 hidden md:inline-block"></span>
<div v-for="(news, index) in newsList" :key="index"
:class="['swiper-slide pl-[50px] pr-[40px] md:pl-[118px] pt-3 md:pt-[20px]', {'hidden': currentIndex !== index}]">
<h2 class="text-xl md:text-3xl font-bold mb-3 md:mb-4 line-clamp-1">
<NuxtLink :to="'/info/' + news.id" target="_blank" class="text-[#0c1923] hover:text-blue-600">
{{ getCurrentLanguage() === 'zh' ? news.title : news.en_title || news.title }}
</NuxtLink>
</h2>
<h3 class="line-clamp-2 text-gray-600 text-base md:text-lg mb-4 md:mb-6">
{{ getCurrentLanguage() === 'zh' ? news.synopsis : news.en_synopsis || news.synopsis }}
</h3>
<h4 v-if="!isMobile" class="mt-6 md:mt-10">
<NuxtLink :to="'/info/' + news.id" target="_blank"
class="text-[#0c1923] px-4 py-1 md:px-5 md:py-2.5 text-sm md:text-base rounded-[10px] border border-solid border-[#0c1923] hover:bg-gray-100">
{{ $t('list_b3') }}
</NuxtLink>
</h4>
</div>
</div>
</div>
</div>
</div>
<!-- News list section -->
<div class="container mx-auto px-4 py-8 md:py-12">
<div v-for="(news, index) in allNewsList" :key="'all-'+index" class="newsBox2 min-h-[200px] md:min-h-[300px] h-auto md:h-[300px] flex flex-col md:flex-row flex-wrap items-start md:items-center p-4 md:p-[20px] mb-8 md:mb-12 border-b border-gray-200">
<NuxtLink :to="'/info/' + news.id" target="_blank" class="text-[#0c1923] hover:text-blue-600 md:h-[300px] flex md:p-[20px]">
<div class="newsTit2 w-full md:w-2/3 pr-0 md:pr-6 mb-4 md:mb-0">
<h2>
<span class="newsSpan1 text-2xl md:text-[40px]">{{ formatYear(news.add_time) }}/</span>
<span class="newsSpan2 text-xl md:text-[28px]">{{ formatDate(news.add_time) }}</span>
</h2>
<div class="newsBox2di w-full md:w-[473px]"></div>
<h3 class="text-xl md:text-2xl font-bold mb-2 md:mb-4 pt-3 md:pt-[20px] line-clamp-1">
{{ getCurrentLanguage() == 'zh' ? news.title : (news.en_title || news.title) }}
</h3>
<h4 class="text-gray-600 text-base md:text-lg line-clamp-2">
{{ getCurrentLanguage() == 'zh' ? news.synopsis : (news.en_synopsis || news.synopsis) }}
</h4>
</div>
<img :src="news.image_input[0]" class="news2g10 w-full md:w-1/3 h-[200px] md:h-full object-cover rounded-lg" alt="News thumbnail" />
</NuxtLink>
</div>
<!-- Pagination -->
<div id="pages" class="text-center mt-6 md:mt-8">
<button
v-for="page in totalPages"
:key="page"
@click="changePage(page)"
:class="['mx-1 px-3 py-1 md:px-4 md:py-2 text-sm md:text-base rounded', currentPage === page ? 'bg-blue-500 text-white' : 'bg-gray-200 hover:bg-gray-300']">
{{ page }}
</button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import $api from '@/service/webRequest'
// 分页相关变量
const currentPage = ref(1)
const itemsPerPage = 5
const totalItems = ref(0)
// 新闻数据
const mockNewsData = ref([])
const allNewsList = ref([])
const isMobile = ref(false)
onMounted(() => {
isMobile.value = window.innerWidth < 768
getNewsList()
getFeaturedNews()
})
const topImg = ref('')
// 获取轮播展示的新闻前5条
const getFeaturedNews = () => {
$api.get("/api/article/list/8", { params: { page: 1, limit: 5 } })
.then((res: any) => {
mockNewsData.value = res.data.data.list
topImg.value = res.data.data.list[0].image_input[0]
})
.catch((err) => {
console.error("获取轮播新闻失败:", err)
})
}
// 获取分页新闻列表
const getNewsList = () => {
$api.get("/api/article/list/8", { params: { page: currentPage.value, limit: itemsPerPage } })
.then((res: any) => {
allNewsList.value = res.data.data.list
// 获取总条数用于分页
totalItems.value = res.data.data.count
})
.catch((err) => {
console.error("获取新闻列表失败:", err)
})
}
const { locale } = useI18n()
const currentIndex = ref(0)
// 轮播新闻列表
const newsList = computed(() => mockNewsData.value)
// 计算总页数
const totalPages = computed(() => Math.ceil(totalItems.value / itemsPerPage))
// 当前轮播的新闻
const currentNews = computed(() => {
return newsList.value[currentIndex.value] || {
id: 0,
title: '',
description: '',
inputtime: ''
}
})
// 轮播控制方法
const prevSlide = () => {
topImg.value = mockNewsData.value[currentIndex.value - 1].image_input[0]
currentIndex.value = (currentIndex.value - 1 + newsList.value.length) % newsList.value.length
}
const nextSlide = () => {
topImg.value = mockNewsData.value[currentIndex.value + 1].image_input[0]
currentIndex.value = (currentIndex.value + 1) % newsList.value.length
}
// 分页方法
const changePage = (page: number) => {
currentPage.value = page
getNewsList() // 切换页码时重新获取数据
}
// 格式化年份 - 处理字符串格式的日期 "2023-02-15 16:50"
const formatYear = (dateStr: string) => {
if (!dateStr) return ''
// 从日期字符串中提取年份
const year = dateStr.split(' ')[0].split('-')[0]
return year
}
// 格式化日期 - 处理字符串格式的日期 "2023-02-15 16:50"
const formatDate = (dateStr: string) => {
if (!dateStr) return ''
// 从日期字符串中提取月和日
const dateParts = dateStr.split(' ')[0].split('-')
if (dateParts.length < 3) return ''
const month = dateParts[1]
const day = dateParts[2]
return `${month}/${day}`
}
const getCurrentLanguage = () => {
return locale.value
}
</script>
<style lang="scss" scoped>
@import "@/assets/animate/animate.min.css";
.container {
width: 100%;
@media (min-width: 768px) {
max-width: 1310px;
}
}
.aboutimgBg {
background-image: url(/images/newsgroup3.png);
background-size: cover;
height: 300px;
display: flex;
align-items: center;
justify-content: start;
@media (min-width: 768px) {
height: 600px;
}
}
.newsTit h2::after {
content: '';
width: 120px;
height: 20px;
@media (min-width: 768px) {
width: 100%;
height: 28px;
margin: 0 auto;
margin-top: -15px;
}
background: #A8CBFF;
display: block;
margin-top: -20px;
}
.ellipsis-3 {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.newsBox1 {
margin-top: 20px;
@media (min-width: 768px) {
margin-top: 50px;
}
}
.newsBox2 {
transition: all 0.3s ease;
}
.newsBox2:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.05);
}
.newsSpan1 {
color: #333;
}
.newsSpan2 {
color: #1C1C1C;
letter-spacing: 2px;
@media (min-width: 768px) {
letter-spacing: 5px;
padding-left: 10px;
}
padding-left: 5px;
}
.newsbs2 {
position: absolute;
margin-left: 81px;
border-right: 2px solid #1C1C1C;
display: inline-block;
height: 300px;
@media (min-width: 768px) {
height: 344px;
margin-top: 10px;
}
}
.t6::after {
content: '';
width: 100px;
height: 15px;
@media (min-width: 768px) {
width: 175px;
height: 20px;
margin-top: -18px;
}
background: #A3C8FF;
display: block;
margin-top: -14px;
}
.t7::after {
content: '';
width: 2px;
height: 16px;
@media (min-width: 768px) {
width: 3px;
height: 21px;
top: 20px;
}
background: #000000;
display: block;
position: absolute;
right: 0;
top: 15px;
}
.newsTit2 h2::after {
content: '';
margin-top: -20px;
width: 120px;
height: 20px;
@media (min-width: 768px) {
margin-top: -29px;
width: 200px;
height: 31px;
margin-left: 2px;
}
background: #A8CBFF;
display: block;
margin-left: 0;
}
.newsBox2di {
width: 100%;
border-top: 1px solid #1C1C1C;
@media (min-width: 768px) {
width: 473px;
border-top: 2px solid #1C1C1C;
margin-left: 0px;
margin-top: 0px;
}
}
</style>