Files
portal/src/views/news/index.vue
yiqiuyang e5569b37a1 1
2025-10-16 15:48:14 +08:00

182 lines
3.9 KiB
Vue

<script setup>
defineOptions({name: 'New'})
import {ref, onMounted, nextTick, onActivated, onDeactivated} from 'vue'
import Banner from '@/components/Banner/index.vue'
import Swiper from '@/components/Swiper/index.vue'
import {useRouter} from 'vue-router'
import {onBeforeRouteLeave} from 'vue-router'
import {getNews} from '@/api/index'
const currentPage = ref(1)
const showLoad = ref(true)
const containerWidth = ref(1700)
const containerHeight = ref(1400)
onMounted(() => {
getNewList()
})
let router = useRouter()
let scrollTop = 0
const newList = ref([])
const page = ref({
pageNum: 1,
pageSize: 10,
totalPages: 0,
})
async function getNewList() {
let query = {
status: 'published',
page: page.value.pageNum,
page_size: page.value.pageSize,
}
let {code, data, pagination} = await getNews(query)
if (code === 0) {
newList.value = data
page.value.totalPages = pagination.total_pages
showLoad.value = false
} else {
showLoad.value = false
}
}
const toDetail = (item) => {
router.push({
path: '/news/detail',
query: {
id: item.id,
slug: item.slug,
},
})
}
onActivated(async () => {
await nextTick()
// 再强制等一帧布局
requestAnimationFrame(() => {
window.scrollTo({top: scrollTop, behavior: 'instant'})
})
})
onDeactivated(() => {
scrollTop = document.documentElement.scrollTop || document.body.scrollTop
})
onBeforeRouteLeave((to) => {
if (to.name === 'Detail') return
// 去别的顶级菜单 → 销毁
const parent = to.matched[0]
if (parent?.name !== 'News') {
// 通过修改路由 meta 让 keep-alive 排除当前组件
// 需要把 keep-alive 写成 :include="cachedNames" 并在 pinia 里维护数组
}
})
</script>
<template>
<div class="page" v-loading="showLoad">
<Banner class="banner" img="banner/news.png" />
<Swiper
id="one"
title="新闻中心"
v-model="currentPage"
:source-width="containerWidth"
:source-height="containerHeight"
:show-pagination="false"
:auto-play="false"
:showHover="false"
>
<template #default="{item, index, isActive}">
<div class="my-card">
<div
class="news flex j-s"
:class="{active: isActive}"
v-for="item in newList"
:key="item.id"
@click="toDetail(item)"
>
<div class="img">
<img :src="item.cover_image" />
</div>
<div class="content">
<div class="label">{{ item.title }}</div>
<div class="time">{{ item?.time }}</div>
<div class="sub-label">{{ item?.subLabel }}</div>
<div class="text">{{ item.snapshot }}</div>
</div>
</div>
</div>
</template>
</Swiper>
</div>
</template>
<style lang="scss" scoped>
.my-card {
width: 100%;
height: 100%;
.news {
width: calc(100% - 100px);
margin: 20px 50px;
padding: 10px;
overflow-y: hidden;
transition: all 0.3s;
cursor: pointer;
background: rgba(255, 255, 255, 0.01);
box-shadow: 0px 2px 16px rgba(0, 0, 0, 0.04);
&:not(:last-of-type) {
margin-bottom: 40px;
}
&:hover {
scale: (1.05);
}
}
.img {
width: 428px;
height: 278px;
background-color: #d9d9d9;
border-radius: 5px;
img {
width: 100%;
height: 100%;
}
}
.content {
flex: 1;
text-align: left;
margin-left: 58px;
margin-top: 30px;
padding-right: 20px;
.label {
font-family: 'PingFang SC';
font-weight: 500;
font-size: 20px;
color: $black;
}
.time {
font-family: 'PingFang SC';
font-weight: 400;
font-size: 18px;
margin-top: 16px;
}
.sub-label {
margin-top: 16px;
}
.sub-label,
.text {
font-family: 'PingFang SC';
font-weight: 400;
font-size: 16px;
color: #999999;
}
}
}
</style>