ufutx-pc-website/src/views/News/News.vue

527 lines
12 KiB
Vue
Raw Normal View History

<template>
<div class="page-container">
2025-07-04 11:29:23 +08:00
<!-- 已有Banner组件 -->
2025-06-30 09:26:33 +08:00
<BannerCarousel />
<!-- 核心内容区 -->
<div class="news-content">
2025-07-04 11:29:23 +08:00
<!-- 标签切换动态加载 -->
<el-tabs v-model="activeTab" class="news-tabs" @tab-change="resetPage">
<el-tab-pane v-for="item in categories" :key="item.name" :label="item.name" :name="item.name">
<template #label>
<div class="categories-label">{{ item.name }}</div>
</template>
</el-tab-pane>
</el-tabs>
2025-07-04 11:29:23 +08:00
<!-- 新闻列表数据加载后显示 -->
<div v-if="!loading && newsData.length > 0" class="news-list">
<div v-for="(item, idx) in filteredNews" :key="idx" class="news-item">
2025-07-04 11:29:23 +08:00
<img :src="item.pic" alt="image" class="news-cover" />
<div class="news-info">
<h3 class="news-title">{{ item.title }}</h3>
2025-07-04 11:29:23 +08:00
<h3 class="news-label">{{ item.publisher }}</h3>
<div class="news-wrap" @click="openArticleInNewWindow(item.id)">
2025-06-20 18:44:15 +08:00
<div class="view-btn">查看详情</div>
<div class="news-date">
<img
class="icon"
src="https://images.health.ufutx.com/202506/13/c5e3552a870fd254610290bbabce5e30.png"
/>
2025-07-04 11:29:23 +08:00
<p>{{ item.create_time }}</p>
</div>
</div>
</div>
</div>
</div>
2025-07-04 11:29:23 +08:00
<!-- 无数据时显示占位图加载完成且数据为空 -->
<div v-else-if="!loading && newsData.length === 0" class="empty-state">
<img
src="https://images.health.ufutx.com/202507/02/259f20509b57b36199ef7619f8d63733.png"
alt="暂无数据"
class="empty-img"
/>
<p class="empty-text">暂无内容</p>
</div>
<!-- 加载状态 -->
<div v-else class="loading-container">
<!-- <el-spinner size="large"></el-spinner>-->
<p>加载中...</p>
</div>
<!-- 分页 -->
<div class="pagination-wrap">
<el-pagination
:current-page="currentPage"
:page-sizes="[10, 20, 50]"
:page-size="pageSize"
2025-07-04 11:29:23 +08:00
background
layout="total,prev, pager, next"
:total="totalCount"
@size-change="handleSizeChange"
@current-change="handlePageChange"
2025-07-04 11:29:23 +08:00
>
</el-pagination>
</div>
</div>
</div>
</template>
<script setup lang="ts">
2025-07-04 11:29:23 +08:00
import { ref, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
2025-06-30 09:26:33 +08:00
import BannerCarousel from '@/views/News/sections/BannerCarousel.vue'
2025-07-04 11:29:23 +08:00
import request from '@/utils/request' // 假设已有请求工具函数
2025-07-04 11:29:23 +08:00
// 路由相关
// import { useRoute, useRouter } from 'vue-router'
import { openNewWindow } from '@/utils/navigation.ts'
2025-07-04 11:29:23 +08:00
// const route = useRoute()
// const router = useRouter()
2025-07-04 11:29:23 +08:00
// 响应式数据
const activeTab = ref('') // 激活标签
const currentPage = ref(1) // 当前页码
const pageSize = ref(15) // 每页条数
const totalCount = ref(0) // 总数据量
const loading = ref(false) // 加载状态
const categories = ref<Array<any>>([]) // 标签分类
const newsData = ref<Array<any>>([]) // 新闻数据
// 计算当前显示的新闻(带分页)
const filteredNews = computed(() => {
const start = (currentPage.value - 1) * pageSize.value
2025-07-04 11:29:23 +08:00
return newsData.value.slice(start, start + pageSize.value)
})
2025-07-04 11:29:23 +08:00
// 跳转详情页携带文章ID
const openArticleInNewWindow = (id: number) => {
openNewWindow(`/articleDetail/${id}`)
}
// 获取标签分类列表
const fetchCategories = async () => {
loading.value = true
try {
// 从接口获取标签分类(:plat从路由参数获取
const res = await request.get(`/go/api/:plat/v1/article/category/list`)
if (res.data.length > 0) {
categories.value = res.data || []
// 设置默认激活标签(如果有数据)
if (categories.value.length > 0) {
activeTab.value = categories.value[0].name
}
} else {
2025-07-24 18:26:24 +08:00
// ElMessage.error(res.message || '获取分类失败')
2025-07-04 11:29:23 +08:00
}
} catch (error: any) {
console.error('获取分类列表失败', error)
ElMessage.error('网络错误,请稍后重试')
} finally {
loading.value = false
}
}
// 获取新闻列表数据
const fetchNewsList = async (category_id: string, page: number) => {
loading.value = true
try {
// 接口参数type根据标签分类传递
const params = {
category_id: category_id,
page
}
2025-06-20 18:44:15 +08:00
2025-07-04 11:29:23 +08:00
// 调用新闻列表接口
const res = await request.get(`/go/api/:plat/v1/article/list`, params)
if (res.code === 0) {
newsData.value = res.data.data || []
console.log(newsData.value)
totalCount.value = res.data.total_count || 0
} else {
ElMessage.error(res.message || '获取新闻失败')
}
} catch (error: any) {
console.error('获取新闻列表失败', error)
ElMessage.error('网络错误,请稍后重试')
} finally {
loading.value = false
}
2025-06-20 18:44:15 +08:00
}
2025-07-04 11:29:23 +08:00
// 标签切换时重置页码并加载数据
const resetPage = () => {
currentPage.value = 1
if (activeTab.value) {
loadNewsData()
}
}
// 加载新闻数据(整合标签和分页参数)
const loadNewsData = () => {
if (!activeTab.value) return
// 假设标签分类的name对应新闻接口的type参数
console.log(activeTab.value)
const category = categories.value.find(item => item.name === activeTab.value)
if (category) {
fetchNewsList(category.id || '', currentPage.value)
}
}
// 分页事件
const handleSizeChange = (val: number) => {
pageSize.value = val
currentPage.value = 1
2025-07-04 11:29:23 +08:00
loadNewsData()
}
2025-07-04 11:29:23 +08:00
const handlePageChange = (val: number) => {
currentPage.value = val
2025-07-04 11:29:23 +08:00
loadNewsData()
}
2025-07-04 11:29:23 +08:00
// 组件挂载时加载分类和新闻数据
onMounted(async () => {
await fetchCategories()
if (activeTab.value) {
loadNewsData()
}
})
// 监听标签切换,重新加载数据
// watch(activeTab, () => {
// loadNewsData()
// })
</script>
<style scoped lang="less">
@import '@/styles/global.less';
.page-container {
min-height: 100vh;
background-color: @bg-color;
}
.news-content {
max-width: 1920px;
2025-07-04 11:29:23 +08:00
padding: 0 20px;
}
/* 加载状态样式 */
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 300px;
color: @text-color-secondary;
.el-spinner {
margin-bottom: 20px;
}
}
/* 标签切换样式(还原设计的蓝色下划线) */
.news-tabs {
2025-07-04 11:29:23 +08:00
padding-top: 50px;
.categories-label {
font-size: 32px;
}
:deep(.el-tabs__nav-wrap) {
&:after {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 100vw;
2025-06-30 09:26:33 +08:00
height: 0.5px;
background-color: #b5b5b5;
z-index: var(--el-index-normal);
}
}
:deep(.el-tabs__active-bar) {
background-color: @primary-dark; // 下划线颜色
height: 3px;
bottom: -20px !important;
margin-top: 20px;
}
:deep(.el-tabs__header) {
margin: 0;
2025-07-04 11:29:23 +08:00
width: 100%;
.el-tabs__nav {
2025-07-04 11:29:23 +08:00
justify-content: center;
width: 100%;
margin-bottom: 20px;
.el-tabs__item {
font-size: @font-size-xxl;
color: @text-color-secondary;
margin-right: 104px;
&.is-active {
color: @primary-dark; // 激活态文字颜色
}
}
}
}
2025-07-04 11:29:23 +08:00
// 响应式适配
@media (max-width: @tablet-breakpoint) {
2025-07-11 14:51:12 +08:00
.categories-label {
font-size: @font-size-lg;
}
2025-07-04 11:29:23 +08:00
:deep(.el-tabs__item) {
margin-right: @space-md;
font-size: @font-size-lg;
}
:deep(.el-tabs__active-bar) {
bottom: -15px !important;
}
}
@media (max-width: @mobile-breakpoint) {
:deep(.el-tabs__item) {
margin-right: @space-sm;
font-size: @font-size-md;
}
:deep(.el-tabs__active-bar) {
bottom: -10px !important;
}
}
}
2025-07-04 11:29:23 +08:00
/* 新闻列表 */
.news-list {
display: flex;
flex-direction: column;
gap: 50px;
2025-07-04 11:29:23 +08:00
padding: 100px 192px 0;
.news-item {
display: flex;
align-items: center;
border-bottom: 0.3px solid #b5b5b5;
2025-07-04 11:29:23 +08:00
padding-bottom: 50px;
.news-cover {
width: 500px;
height: 260px;
object-fit: cover;
border-radius: @border-radius-md;
2025-07-24 18:26:24 +08:00
flex-shrink: 0; /* 禁止收缩,保证宽度不变 */
margin-right: 30px;
}
2025-07-04 11:29:23 +08:00
.news-info {
width: 100%;
2025-07-04 11:29:23 +08:00
padding-top: 20px;
text-align: left;
2025-07-04 11:29:23 +08:00
.news-title {
font-size: @font-size-lg;
font-weight: @font-weight-medium;
color: @text-color;
margin-bottom: @space-sm;
}
2025-07-04 11:29:23 +08:00
.news-label {
font-size: @font-size-sm;
2025-07-04 11:29:23 +08:00
color: @text-color-secondary;
margin-top: 13px;
margin-bottom: 76px;
}
2025-07-04 11:29:23 +08:00
.news-wrap {
display: flex;
justify-content: space-between;
.view-btn {
padding: 6px 16px;
color: @primary-dark;
border-radius: 4px;
border: 1px solid var(--1060-ff, #1060ff);
cursor: pointer;
}
2025-07-04 11:29:23 +08:00
.news-date {
font-size: @font-size-sm;
color: @text-color-secondary;
display: flex;
align-items: center;
gap: 8px;
.icon {
width: 18px;
height: 18px;
object-fit: contain;
}
}
}
}
}
2025-07-04 11:29:23 +08:00
// 响应式适配
@media (max-width: @tablet-breakpoint) {
padding: @space-xl @space-md 0;
.news-item {
flex-direction: column;
2025-07-04 11:29:23 +08:00
align-items: flex-start;
gap: @space-lg;
.news-cover {
width: 100%;
height: auto;
2025-07-04 11:29:23 +08:00
margin-right: 0;
margin-bottom: @space-lg;
}
2025-07-04 11:29:23 +08:00
.news-info .news-wrap {
flex-direction: column;
gap: @space-sm;
2025-07-04 11:29:23 +08:00
.view-btn {
align-self: flex-start;
}
2025-07-04 11:29:23 +08:00
.news-date {
order: -1;
}
}
}
}
2025-07-04 11:29:23 +08:00
@media (max-width: @mobile-breakpoint) {
padding: @space-lg @space-md 0;
gap: @space-xl;
.news-item {
padding-bottom: @space-lg;
.news-cover {
height: 180px;
}
.news-info .news-title {
font-size: @font-size-md;
}
.news-info .news-label {
2025-07-11 14:51:12 +08:00
font-size: @font-size-sm;
}
.news-info .view-btn {
font-size: @font-size-xs;
}
}
.news-date {
.icon {
width: 40px;
height: 40px;
}
p {
font-size: @font-size-xs;
}
}
}
}
2025-07-04 11:29:23 +08:00
/* 分页样式 */
.pagination-wrap {
margin-top: 50px;
padding-bottom: 170px;
display: flex;
justify-content: center;
:deep(.el-pager li.is-active) {
color: @primary-dark;
}
2025-07-04 11:29:23 +08:00
.el-pagination {
.el-pagination__total {
color: @text-color-light;
}
2025-07-04 11:29:23 +08:00
.el-pager li.active {
background-color: @primary-color;
color: #fff;
}
2025-07-04 11:29:23 +08:00
.el-pagination__sizes {
margin: 0 @space-md;
}
}
2025-07-04 11:29:23 +08:00
// 响应式适配
@media (max-width: @mobile-breakpoint) {
.el-pagination {
.el-pagination__total {
2025-07-04 11:29:23 +08:00
font-size: @font-size-xs;
}
.el-pager li {
width: 28px;
height: 28px;
line-height: 28px;
2025-07-04 11:29:23 +08:00
font-size: @font-size-xs;
}
.el-pagination__sizes {
2025-07-04 11:29:23 +08:00
margin: 0 @space-xs;
.el-input {
2025-07-04 11:29:23 +08:00
font-size: @font-size-xs;
}
}
}
}
}
2025-07-04 11:29:23 +08:00
// 无数据占位图样式
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100px 0; // 与列表区域上下间距保持一致
text-align: center;
.empty-img {
width: 300px; // 调整占位图宽度(根据实际图片比例)
height: auto;
margin-bottom: 20px;
opacity: 0.8; // 轻微降低透明度,避免过于突兀
}
.empty-text {
font-size: 20px;
color: @text-color-secondary;
.mt(10px);
}
// 响应式适配
@media (max-width: @mobile-breakpoint) {
.empty-img {
width: 200px; // 移动端缩小图片
}
.empty-text {
font-size: @font-size-md;
}
}
}
.pagination {
margin-top: 20px;
text-align: right;
}
:deep(.el-pager li.is-active) {
background-color: #1665fc !important;
color: #ffffff !important;
}
</style>