Files
AIProd/pages/Launches/index.vue

388 lines
11 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 id="normal-container" class="launches-content" v-loading.fullscreen.lock="fullscreenLoading">
<IntegratedLayout>
<div class="content">
<div class="bread-menu">
<span class="gradient-color crumbs">AI Launches</span>
</div>
<div class="launches-header">
<h1 class="launches-title-text">
AI Launches
</h1>
<p class="launches-subtitle-text">A daily curated selection of the newest AI applications and products. Explore the most talked-about innovations, trending technologies, and hot new releases shaping the AI landscape. Stay ahead by discovering whats capturing attention in the AI community.</p>
</div>
<div class="flex justify-center">
<SwitchDate v-model="currentMode" />
</div>
<div class="list-header flex-between-center">
<SwitchSort v-model="sortType" />
<div class="flex items-center gap-40">
<SwitchMonth v-show="currentMode === 'Daily'" v-model="currentMonth" />
<SwitchYear v-model="currentYear" />
</div>
</div>
<div class="card list-container">
<OptionDates :year="currentYear" :mode="currentMode" :month="currentMonth" @select="handleDateSelect" @month-change="handleMonthChange" />
<div class="diver"></div>
<div class="list">
<ListItem v-for="(it, i) in articleList" :key="it.id" :config="it" :sort-index="i + 1" />
</div>
</div>
<div class="flex-bottom-right">
<Pagination :current-page="currentPage" :total-pages="totalPages" @page-change="handlePageChange" />
</div>
</div>
</IntegratedLayout>
</div>
</template>
<script>
import SwitchDate from "@/pages/Launches/components/SwitchDate.vue";
import SwitchSort from "@/pages/Launches/components/SwitchSort.vue";
import SwitchYear from "@/pages/Launches/components/SwitchYear.vue";
import SwitchMonth from "@/pages/Launches/components/SwitchMonth.vue";
import ListItem from "@/pages/Launches/components/ListItem.vue";
import OptionDates from "@/pages/Launches/components/OptionDates.vue";
const SEARCH_CACHE_KEY = 'launches_search_cache';
export default {
components: {
SwitchDate,
SwitchSort,
SwitchYear,
ListItem,
OptionDates,
SwitchMonth,
},
data() {
return {
lastSelectedValue: null,
currentPage: 1,
totalPages: 1,
pageSize: 10,
total: 0,
currentYear: new Date().getFullYear(),
currentMode: 'Daily',
currentMonth: new Date().getMonth() + 1,
articleList: [],
sortType: 'popular',
fullscreenLoading: false,
}
},
watch: {
total() {
this.calculateTotalPages();
},
pageSize() {
this.calculateTotalPages();
},
sortType(newVal, oldVal) {
if (oldVal !== null) { // 避免初始化时触发
let startTime = '';
let endTime = '';
if (this.lastSelectedValue) {
try {
const selectedValue = JSON.parse(this.lastSelectedValue);
if (selectedValue instanceof Array) {
startTime = selectedValue[0] + ' 00:00:00';
endTime = selectedValue[1] + ' 23:59:59';
} else {
startTime = selectedValue + ' 00:00:00';
endTime = selectedValue + ' 23:59:59';
}
} catch (e) {
console.error('解析时间参数失败', e);
}
}
this.saveSearchCache();
// 重新获取文章列表,传入新的排序类型
this.getArticleListData(this.currentPage, this.pageSize, startTime, endTime, newVal);
}
},
// 监听其他搜索条件变化
currentPage() {
this.saveSearchCache();
},
currentYear() {
this.saveSearchCache();
},
currentMode() {
this.saveSearchCache();
},
currentMonth() {
this.saveSearchCache();
},
lastSelectedValue() {
this.saveSearchCache();
}
},
methods: {
handleMonthChange(month) {
this.currentMonth = month;
// 无论当前模式是什么都更新lastSelectedValue
const [start, end] = this.getMonthRange(this.currentYear, month);
this.lastSelectedValue = JSON.stringify([start, end]);
},
getMonthRange(year, month) {
const start = new Date(year, month - 1, 1);
const end = new Date(year, month, 0);
// 格式化为 yyyy-mm-dd HH:MM:SS
const formatDate = (date, isStart = true) => {
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, '0');
const d = String(date.getDate()).padStart(2, '0');
const time = isStart ? '00:00:00' : '23:59:59';
return `${y}-${m}-${d} ${time}`;
};
return [formatDate(start), formatDate(end)];
},
// 保存搜索条件到sessionStorage
saveSearchCache() {
const cacheData = {
currentPage: this.currentPage,
currentYear: this.currentYear,
currentMode: this.currentMode,
currentMonth: this.currentMonth,
sortType: this.sortType,
lastSelectedValue: this.lastSelectedValue
};
try {
sessionStorage.setItem(SEARCH_CACHE_KEY, JSON.stringify(cacheData));
} catch (e) {
console.error('保存搜索缓存失败', e);
}
},
// 从sessionStorage加载搜索条件
loadSearchCache() {
try {
const cachedData = sessionStorage.getItem(SEARCH_CACHE_KEY);
if (cachedData) {
const parsedData = JSON.parse(cachedData);
// 恢复各个搜索条件
if (parsedData.currentPage !== undefined) {
this.currentPage = parsedData.currentPage;
}
if (parsedData.currentYear !== undefined) {
this.currentYear = parsedData.currentYear;
}
if (parsedData.currentMode !== undefined) {
this.currentMode = parsedData.currentMode;
}
if (parsedData.currentMonth !== undefined) {
this.currentMonth = parsedData.currentMonth;
}
if (parsedData.sortType !== undefined) {
this.sortType = parsedData.sortType;
}
if (parsedData.lastSelectedValue !== undefined) {
this.lastSelectedValue = parsedData.lastSelectedValue;
}
// 确保数据同步在月模式下如果currentMonth和lastSelectedValue不一致以currentMonth为准
this.$nextTick(() => {
if (this.currentMode === 'Monthly' && this.currentMonth) {
// 解析lastSelectedValue获取其中的月份
let cachedMonth = null;
try {
if (this.lastSelectedValue) {
const selectedValue = JSON.parse(this.lastSelectedValue);
if (Array.isArray(selectedValue) && selectedValue.length > 0) {
// 从日期字符串中提取月份
const dateParts = selectedValue[0].split('-');
if (dateParts.length >= 2) {
cachedMonth = parseInt(dateParts[1], 10);
}
}
}
} catch (e) {
console.error('解析lastSelectedValue失败', e);
}
// 如果lastSelectedValue中的月份与currentMonth不一致更新lastSelectedValue
if (cachedMonth !== this.currentMonth) {
this.handleMonthChange(this.currentMonth);
}
}
// 从lastSelectedValue中提取时间参数并重新请求数据
let startTime = '';
let endTime = '';
if (this.lastSelectedValue) {
try {
const selectedValue = JSON.parse(this.lastSelectedValue);
if (selectedValue instanceof Array) {
startTime = selectedValue[0];
endTime = selectedValue[1];
} else {
startTime = selectedValue;
endTime = selectedValue;
}
} catch (e) {
console.error('解析时间参数失败', e);
}
}
// 调用数据加载方法
this.getArticleListData(this.currentPage, this.pageSize, startTime, endTime, this.sortType);
});
}
} catch (e) {
console.error('加载搜索缓存失败', e);
}
},
calculateTotalPages() {
// 当 total 为 0 时 totalPages 为 1
// 否则向上取整计算总页数
this.totalPages = this.total === 0 ? 1 : Math.ceil(this.total / this.pageSize);
},
handleDateSelect(selectedValue) {
// 确保selectedValue已经包含时分秒
let valueToSave = selectedValue;
// 处理日期字符串或日期范围数组,添加时分秒
if (typeof selectedValue === 'string' && !selectedValue.includes(' ')) {
// 单个日期,添加时间
valueToSave = selectedValue + ' 00:00:00';
} else if (Array.isArray(selectedValue) && selectedValue.length === 2) {
// 日期范围数组,确保每个日期都有时间
const start = selectedValue[0].includes(' ') ? selectedValue[0] : selectedValue[0] + ' 00:00:00';
const end = selectedValue[1].includes(' ') ? selectedValue[1] : selectedValue[1] + ' 23:59:59';
valueToSave = [start, end];
}
const stringValue = JSON.stringify(valueToSave);
if (this.lastSelectedValue === stringValue) {
return;
}
this.lastSelectedValue = stringValue;
// 获取开始和结束时间
let startTime = '';
let endTime = '';
if (valueToSave instanceof Array) {
startTime = valueToSave[0];
endTime = valueToSave[1];
} else {
startTime = valueToSave;
endTime = valueToSave;
}
this.getArticleListData(this.currentPage, this.pageSize, startTime, endTime, this.sortType);
},
// 获取文章列表
async getArticleListData(page = 1, limit = 10, startTime, endTime, sortType = 'popular') {
const params = {page, limit, startTime, endTime, articleType: 'launches'};
if (sortType === 'popular') {
params.isHot = 1;
} else {
params.sortField = 'publish_time';
params.sortOrder = 'desc';
}
this.fullscreenLoading = true;
const {data: res} = await this.$api.article.getArticleList(params);
const {code, data} = res;
if (code === 0 && data.list) {
this.articleList = data.list;
this.total = data.total;
this.calculateTotalPages();
} else {
this.articleList = [];
this.total = 0;
this.calculateTotalPages();
}
this.fullscreenLoading = false;
},
handlePageChange(pageNumber) {
this.currentPage = pageNumber;
// 从 lastSelectedValue 中提取时间参数
let startTime = '';
let endTime = '';
if (this.lastSelectedValue) {
try {
const selectedValue = JSON.parse(this.lastSelectedValue);
if (selectedValue instanceof Array) {
startTime = selectedValue[0] + ' 00:00:00';
endTime = selectedValue[1] + ' 23:59:59';
} else {
startTime = selectedValue + ' 00:00:00';
endTime = selectedValue + ' 23:59:59';
}
} catch (e) {
console.error('解析时间参数失败', e);
}
}
this.getArticleListData(pageNumber, this.pageSize, startTime, endTime, this.sortType);
},
},
mounted() {
this.loadSearchCache();
}
}
</script>
<style scoped lang="scss">
.gap-40 {
gap: 40px;
}
.card {
padding: 20px 30px;
background-color: #FFFFFF;
border-radius: 12px;
box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.08);
}
.launches-content {
flex: 1;
overflow-y: auto;
position: relative;
.content {
padding-top: 25px;
padding-bottom: 100px;
.bread-menu {
font-size: 18px;
font-family: 'Poppins-Medium';
margin-bottom: 25px;
.crumbs {
font-family: 'Poppins-SemiBold';
font-weight: 600;
}
}
.launches-header {
margin-bottom: 25px;
.launches-title-text {
margin: 0;
font-size: 40px;
font-weight: bold;
font-family: 'Poppins-Bold';
}
.launches-subtitle-text {
font-family: 'Poppins-Medium';
color: #64748B;
margin-top: 10px;
}
}
.list-header {
margin-top: 25px;
}
.list-container {
margin-top: 30px;
margin-bottom: 40px;
.diver {
height: 1px;
border-top-color: #E2E8F0;
border-top-style: solid;
border-top-width: 2px;
margin-top: 15px;
margin-bottom: 15px;
}
.list {
gap: 30px;
display: flex;
flex-direction: column;
}
}
}
}
</style>