177 lines
4.5 KiB
Vue
177 lines
4.5 KiB
Vue
<template>
|
|
<div class="news-list-wrap flex flex-col" v-loading.fullscreen.lock="fullscreenLoading">
|
|
<div class="input">
|
|
<SearchInput v-model="searchText" placeholder="Please enter the key words" @search="handleTextSearch" />
|
|
</div>
|
|
<div class="card flex flex-col flex-1">
|
|
<div class="flex-1 pad-10">
|
|
<div class="scroll-box">
|
|
<div class="daily-content" v-for="(it, i) in groupedArticles" :key="i">
|
|
<div class="date-title flex items-center">
|
|
<img src="/about/icon_title_date.png" alt="Daily News" />
|
|
<div class="gradient-color">{{ it.date }}</div>
|
|
</div>
|
|
<div class="flex-col flex gap-40">
|
|
<ArticleTextListItem v-for="item in it.list" :key="item.id" :item="item" />
|
|
</div>
|
|
<div class="diver"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex-middle-left">
|
|
<Pagination :current-page="currentPage" :total-pages="totalPages" @page-change="handlePageChange" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import ArticleTextListItem from "@/pages/DailyNews/components/ArticleTextListItem.vue";
|
|
|
|
export default {
|
|
components: {
|
|
ArticleTextListItem,
|
|
},
|
|
data() {
|
|
return {
|
|
currentPage: 1,
|
|
totalPages: 1,
|
|
pageSize: 10,
|
|
articleList: [],
|
|
searchText: '',
|
|
total: 0,
|
|
fullscreenLoading: false,
|
|
}
|
|
},
|
|
methods: {
|
|
// 模糊搜索
|
|
async handleTextSearch() {
|
|
await this.getArticleListData(this.currentPage, this.pageSize, this.searchText);
|
|
},
|
|
calculateTotalPages() {
|
|
// 否则向上取整计算总页数
|
|
this.totalPages = this.total === 0 ? 1 : Math.ceil(this.total / this.pageSize);
|
|
},
|
|
// 获取文章数据列表
|
|
async getArticleListData(page = 1, limit = 10, searchText) {
|
|
const params = {page, limit, title: searchText, articleType: 'news', sortField: 'publish_time', sortOrder: 'desc'};
|
|
if (!searchText) {
|
|
delete params.title;
|
|
}
|
|
this.fullscreenLoading = true;
|
|
const {data: res} = await this.$api.article.getArticleList(params);
|
|
const {code, data} = res;
|
|
if (code === 0 && data.list) {
|
|
this.total = data.total;
|
|
this.articleList = data.list;
|
|
this.calculateTotalPages();
|
|
}
|
|
this.fullscreenLoading = false;
|
|
},
|
|
handlePageChange(pageNumber) {
|
|
this.currentPage = pageNumber;
|
|
this.getArticleListData(pageNumber, 10);
|
|
},
|
|
// 添加日期格式化方法
|
|
formatDate(date) {
|
|
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
const month = months[date.getMonth()];
|
|
const day = date.getDate().toString().padStart(2, '0');
|
|
const year = date.getFullYear();
|
|
return `${month} ${day} ${year}`;
|
|
},
|
|
},
|
|
computed: {
|
|
// 添加计算属性,将文章列表按日期分组
|
|
groupedArticles() {
|
|
if (!this.articleList || this.articleList.length === 0) {
|
|
return [];
|
|
}
|
|
|
|
// 创建一个对象来存储按日期分组的文章
|
|
const groups = {};
|
|
|
|
// 遍历文章列表,按日期分组
|
|
this.articleList.forEach(article => {
|
|
// 假设 publishTime 是时间戳或可被解析的时间字符串
|
|
const date = new Date(article.publishTime);
|
|
|
|
// 格式化日期为 YYYY-MM-DD 格式作为键
|
|
const dateKey = date.toISOString().split('T')[0];
|
|
|
|
// 如果该日期还没有分组,则初始化
|
|
if (!groups[dateKey]) {
|
|
groups[dateKey] = {
|
|
date: this.formatDate(date), // 格式化为 Sep 04 2025 这样的格式
|
|
list: []
|
|
};
|
|
}
|
|
|
|
// 将文章添加到对应日期的分组中
|
|
groups[dateKey].list.push(article);
|
|
});
|
|
|
|
// 将分组对象转换为数组并按日期降序排列
|
|
return Object.values(groups).sort((a, b) => {
|
|
// 解析日期字符串进行比较
|
|
const dateA = new Date(a.date);
|
|
const dateB = new Date(b.date);
|
|
return dateB - dateA;
|
|
});
|
|
}
|
|
},
|
|
mounted() {
|
|
this.getArticleListData(this.currentPage, this.pageSize);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.pad-10 {
|
|
padding: 10px 0;
|
|
}
|
|
.gap-40 {
|
|
gap: 40px;
|
|
}
|
|
.scroll-box {
|
|
max-height: 1600px;
|
|
overflow-y: auto;
|
|
}
|
|
.card {
|
|
padding: 20px;
|
|
background-color: #FFFFFF;
|
|
border-radius: 12px;
|
|
box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.08);
|
|
}
|
|
.news-list-wrap {
|
|
height: 100%;
|
|
gap: 16px;
|
|
.input {
|
|
display: flex;
|
|
margin-top: 20px;
|
|
}
|
|
.daily-content {
|
|
.date-title {
|
|
gap: 8px;
|
|
font-family: 'Poppins-SemiBold';
|
|
font-size: 24px;
|
|
font-weight: 600;
|
|
margin-bottom: 40px;
|
|
img {
|
|
width: 28px;
|
|
height: 28px;
|
|
}
|
|
}
|
|
}
|
|
.diver {
|
|
width: 100%;
|
|
height: 2px;
|
|
border-top-color: #f3f8fe;
|
|
border-top-style: solid;
|
|
border-top-width: 2px;
|
|
margin: 40px 0;
|
|
}
|
|
}
|
|
</style>
|