527 lines
12 KiB
Vue
527 lines
12 KiB
Vue
<template>
|
||
<div class="page-container">
|
||
<!-- 已有Banner组件 -->
|
||
<BannerCarousel />
|
||
|
||
<!-- 核心内容区 -->
|
||
<div class="news-content">
|
||
<!-- 标签切换(动态加载) -->
|
||
<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>
|
||
|
||
<!-- 新闻列表(数据加载后显示) -->
|
||
<div v-if="!loading && newsData.length > 0" class="news-list">
|
||
<div v-for="(item, idx) in filteredNews" :key="idx" class="news-item">
|
||
<img :src="item.pic" alt="image" class="news-cover" />
|
||
<div class="news-info">
|
||
<h3 class="news-title">{{ item.title }}</h3>
|
||
<h3 class="news-label">{{ item.publisher }}</h3>
|
||
<div class="news-wrap" @click="openArticleInNewWindow(item.id)">
|
||
<div class="view-btn">查看详情</div>
|
||
<div class="news-date">
|
||
<img
|
||
class="icon"
|
||
src="https://images.health.ufutx.com/202506/13/c5e3552a870fd254610290bbabce5e30.png"
|
||
/>
|
||
<p>{{ item.create_time }}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- 无数据时显示占位图(加载完成且数据为空) -->
|
||
<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"
|
||
background
|
||
layout="total,prev, pager, next"
|
||
:total="totalCount"
|
||
@size-change="handleSizeChange"
|
||
@current-change="handlePageChange"
|
||
>
|
||
</el-pagination>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, computed, onMounted } from 'vue'
|
||
import { ElMessage } from 'element-plus'
|
||
import BannerCarousel from '@/views/News/sections/BannerCarousel.vue'
|
||
import request from '@/utils/request' // 假设已有请求工具函数
|
||
|
||
// 路由相关
|
||
// import { useRoute, useRouter } from 'vue-router'
|
||
import { openNewWindow } from '@/utils/navigation.ts'
|
||
|
||
// const route = useRoute()
|
||
// const router = useRouter()
|
||
|
||
// 响应式数据
|
||
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
|
||
return newsData.value.slice(start, start + pageSize.value)
|
||
})
|
||
|
||
// 跳转详情页(携带文章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 {
|
||
// ElMessage.error(res.message || '获取分类失败')
|
||
}
|
||
} 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
|
||
}
|
||
|
||
// 调用新闻列表接口
|
||
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
|
||
}
|
||
}
|
||
|
||
// 标签切换时重置页码并加载数据
|
||
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
|
||
loadNewsData()
|
||
}
|
||
|
||
const handlePageChange = (val: number) => {
|
||
currentPage.value = val
|
||
loadNewsData()
|
||
}
|
||
|
||
// 组件挂载时加载分类和新闻数据
|
||
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;
|
||
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 {
|
||
padding-top: 50px;
|
||
.categories-label {
|
||
font-size: 32px;
|
||
}
|
||
:deep(.el-tabs__nav-wrap) {
|
||
&:after {
|
||
content: '';
|
||
position: absolute;
|
||
left: 0;
|
||
bottom: 0;
|
||
width: 100vw;
|
||
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;
|
||
width: 100%;
|
||
|
||
.el-tabs__nav {
|
||
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; // 激活态文字颜色
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 响应式适配
|
||
@media (max-width: @tablet-breakpoint) {
|
||
.categories-label {
|
||
font-size: @font-size-lg;
|
||
}
|
||
: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;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 新闻列表 */
|
||
.news-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 50px;
|
||
padding: 100px 192px 0;
|
||
|
||
.news-item {
|
||
display: flex;
|
||
align-items: center;
|
||
border-bottom: 0.3px solid #b5b5b5;
|
||
padding-bottom: 50px;
|
||
|
||
.news-cover {
|
||
width: 500px;
|
||
height: 260px;
|
||
object-fit: cover;
|
||
border-radius: @border-radius-md;
|
||
flex-shrink: 0; /* 禁止收缩,保证宽度不变 */
|
||
margin-right: 30px;
|
||
}
|
||
|
||
.news-info {
|
||
width: 100%;
|
||
padding-top: 20px;
|
||
text-align: left;
|
||
|
||
.news-title {
|
||
font-size: @font-size-lg;
|
||
font-weight: @font-weight-medium;
|
||
color: @text-color;
|
||
margin-bottom: @space-sm;
|
||
}
|
||
|
||
.news-label {
|
||
font-size: @font-size-sm;
|
||
color: @text-color-secondary;
|
||
margin-top: 13px;
|
||
margin-bottom: 76px;
|
||
}
|
||
|
||
.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;
|
||
}
|
||
|
||
.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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 响应式适配
|
||
@media (max-width: @tablet-breakpoint) {
|
||
padding: @space-xl @space-md 0;
|
||
|
||
.news-item {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
gap: @space-lg;
|
||
|
||
.news-cover {
|
||
width: 100%;
|
||
height: auto;
|
||
margin-right: 0;
|
||
margin-bottom: @space-lg;
|
||
}
|
||
|
||
.news-info .news-wrap {
|
||
flex-direction: column;
|
||
gap: @space-sm;
|
||
|
||
.view-btn {
|
||
align-self: flex-start;
|
||
}
|
||
|
||
.news-date {
|
||
order: -1;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
@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 {
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 分页样式 */
|
||
.pagination-wrap {
|
||
margin-top: 50px;
|
||
padding-bottom: 170px;
|
||
display: flex;
|
||
justify-content: center;
|
||
|
||
:deep(.el-pager li.is-active) {
|
||
color: @primary-dark;
|
||
}
|
||
|
||
.el-pagination {
|
||
.el-pagination__total {
|
||
color: @text-color-light;
|
||
}
|
||
|
||
.el-pager li.active {
|
||
background-color: @primary-color;
|
||
color: #fff;
|
||
}
|
||
|
||
.el-pagination__sizes {
|
||
margin: 0 @space-md;
|
||
}
|
||
}
|
||
|
||
// 响应式适配
|
||
@media (max-width: @mobile-breakpoint) {
|
||
.el-pagination {
|
||
.el-pagination__total {
|
||
font-size: @font-size-xs;
|
||
}
|
||
|
||
.el-pager li {
|
||
width: 28px;
|
||
height: 28px;
|
||
line-height: 28px;
|
||
font-size: @font-size-xs;
|
||
}
|
||
|
||
.el-pagination__sizes {
|
||
margin: 0 @space-xs;
|
||
|
||
.el-input {
|
||
font-size: @font-size-xs;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// 无数据占位图样式
|
||
.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>
|