Skip to content

Commit 626dc51

Browse files
committed
博客文档数据设置缓存
1 parent 581c7af commit 626dc51

File tree

2 files changed

+106
-80
lines changed

2 files changed

+106
-80
lines changed

package/website/src/api/blog.js

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,35 @@
1-
// src/store/counter.js
2-
import { defineStore } from 'pinia'
1+
import { defineStore } from 'pinia';
32

43
export const useCounterStore = defineStore('counter', {
54
state: () => ({
6-
visitCount: 219793, // 共享的访问量
7-
visitorCount: 119793 // 共享的访问人数
5+
visit: 0,
6+
visitor: 0,
7+
// 新增缓存状态
8+
timelineCache: null, // 缓存时间线数据
9+
metaCache: null, // 缓存元数据(分类、标签等)
10+
cacheTime: 0 // 缓存时间戳(可选,用于过期控制)
811
}),
9-
// 可选:定义修改数据的方法
1012
actions: {
11-
setVisit(count) {
12-
this.visitCount = count
13+
setVisit(visit) {
14+
this.visit = visit;
1315
},
14-
setVisitor(count) {
15-
this.visitorCount = count
16+
setVisitor(visitor) {
17+
this.visitor = visitor;
18+
},
19+
// 新增:缓存时间线数据
20+
setTimelineCache(data) {
21+
this.timelineCache = data;
22+
this.cacheTime = Date.now();
23+
},
24+
// 新增:缓存元数据
25+
setMetaCache(data) {
26+
this.metaCache = data;
27+
},
28+
// 新增:清除缓存(支持手动刷新)
29+
clearCache() {
30+
this.timelineCache = null;
31+
this.metaCache = null;
32+
this.cacheTime = 0;
1633
}
1734
}
18-
})
35+
});

package/website/src/views/BlogPage.vue

Lines changed: 79 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ const tag_num = ref(2)
4747
const word_num = ref(197220)
4848
// 声明默认展开状态常量
4949
const DEFAULT_EXPANDED = true;
50+
// 缓存配置:5分钟过期(单位:毫秒)
51+
const CACHE_EXPIRE_TIME = 5 * 60 * 1000; // 300000ms = 5分钟
5052
// 获取Store实例
5153
const counterStore = useCounterStore()
5254
const years = ref([
@@ -98,84 +100,91 @@ const toggleExpand = (yearGroup) => {
98100
yearGroup.isExpanded = !yearGroup.isExpanded;
99101
};
100102
101-
// 发起请求的函数
102-
const fetchData = async () => {
103-
// years.value = null
104-
if (loading.value) return // 防止重复请求
105-
error.value = null
106-
loading.value = true
103+
// 核心请求逻辑(支持强制刷新、缓存过期判断)
104+
const fetchData = async (forceRefresh = false) => {
105+
if (loading.value) return; // 防止重复请求
106+
error.value = null;
107+
loading.value = true;
107108
108109
try {
109-
// 发起GET请求(使用之前配置的代理路径)
110-
const response = await axios.get('/api/blog/public/timeline')
111-
const status = response.data.statusCode
112-
if (status !== 200) {
113-
throw new Error(response.data.message || '请求失败,请稍后再试')
110+
// ============== 1. 时间线数据处理(含缓存过期判断)==============
111+
const isTimelineExpired = !counterStore.cacheTime || (Date.now() - counterStore.cacheTime) > CACHE_EXPIRE_TIME;
112+
if (!forceRefresh && counterStore.timelineCache && !isTimelineExpired) {
113+
// 缓存有效:直接使用缓存
114+
years.value = counterStore.timelineCache;
115+
} else {
116+
// 缓存过期/无缓存/强制刷新:重新请求
117+
const timelineRes = await axios.get('/api/blog/public/timeline');
118+
if (timelineRes.data.statusCode !== 200) throw new Error(timelineRes.data.message || '时间线请求失败');
119+
const newYears = handleTimelineData(timelineRes.data.data);
120+
years.value = newYears;
121+
counterStore.setTimelineCache(newYears); // 更新缓存(自动刷新cacheTime)
114122
}
115-
// 将结果存入响应式变量
116-
const data = response.data.data
117-
console.log(data)
118-
// 步骤1:提取对象的所有年份键(得到 ["2023", "2024", "2025"])
119-
const yearKeys = Object.keys(data);
120-
// 步骤2:将年份键转为数字,并按倒序排序(得到 [2025, 2024, 2023])
121-
const sortedYears = yearKeys
122-
.map(year => Number(year)) // 字符串转数字(避免 "202" 比 "2023" 大的字符串排序坑)
123-
.sort((a, b) => b - a); // 倒序排序(b - a 是倒序,a - b 是正序)
124-
// 步骤3:遍历排序后的年份,再遍历对应文章
125-
const new_years = []
126-
sortedYears.forEach(year => {
127-
const yearStr = String(year); // 转回字符串,匹配原始对象的键
128-
const articles = data[yearStr]; // 当前年份的所有文章
129-
new_years.push({
130-
year: yearStr,
131-
isExpanded: DEFAULT_EXPANDED, // 每年分组的展开状态,默认展开
132-
articles: articles
133-
})
134-
// 遍历当前年份的每篇文章
135-
articles.forEach((article, index) => {
136-
// 2025-10-24T16:31:03.078Z,转成时区时间 MM-DD 格式
137-
const utcDate = new Date(article.createdAt);
138-
article.date = `${String(utcDate.getMonth() + 1).padStart(2, '0')}-${String(utcDate.getDate()).padStart(2, '0')}`;
139-
});
140-
});
141-
years.value = new_years
142-
} catch (err) {
143-
// 处理错误
144-
error.value = err.message || '请求失败,请稍后再试'
145-
console.error('请求错误:', err)
146-
} finally {
147-
// 结束加载状态
148-
loading.value = false
149-
}
150-
try {
151-
// 发起GET请求(使用之前配置的代理路径)
152-
const response = await axios.get('/api/blog/public/meta')
153-
const status = response.data.statusCode
154-
if (status !== 200) {
155-
throw new Error(response.data.message || '请求失败,请稍后再试')
123+
124+
// ============== 2. 元数据处理(和时间线共用缓存过期状态)==============
125+
if (!forceRefresh && counterStore.metaCache && !isTimelineExpired) {
126+
// 缓存有效:直接使用缓存
127+
const metaCache = counterStore.metaCache;
128+
tag_num.value = metaCache.tagNum;
129+
category_num.value = metaCache.categoryNum;
130+
article_num.value = metaCache.articleNum;
131+
word_num.value = metaCache.wordNum;
132+
counterStore.setVisit(metaCache.visit);
133+
counterStore.setVisitor(metaCache.visitor);
134+
} else {
135+
// 缓存过期/无缓存/强制刷新:重新请求
136+
const metaRes = await axios.get('/api/blog/public/meta');
137+
if (metaRes.data.statusCode !== 200) throw new Error(metaRes.data.message || '元数据请求失败');
138+
const metaData = metaRes.data.data;
139+
// 处理元数据并缓存
140+
const metaCache = {
141+
tagNum: metaData.tags.length,
142+
categoryNum: metaData.meta.categories.length,
143+
articleNum: metaData.totalArticles,
144+
wordNum: metaData.totalWordCount,
145+
visit: metaData.meta.viewer,
146+
visitor: metaData.meta.visited
147+
};
148+
// 更新组件状态
149+
tag_num.value = metaCache.tagNum;
150+
category_num.value = metaCache.categoryNum;
151+
article_num.value = metaCache.articleNum;
152+
word_num.value = metaCache.wordNum;
153+
counterStore.setVisit(metaCache.visit);
154+
counterStore.setVisitor(metaCache.visitor);
155+
counterStore.setMetaCache(metaCache); // 缓存元数据
156156
}
157-
// 将结果存入响应式变量
158-
const data = response.data.data
159-
const tags = data.tags
160-
tag_num.value = tags.length
161-
const categories = data.meta.categories
162-
category_num.value = categories.length
163-
article_num.value = data.totalArticles
164-
word_num.value = data.totalWordCount
165-
counterStore.setVisit(data.meta.viewer)
166-
counterStore.setVisitor(data.meta.visited)
167157
} catch (err) {
168-
// 处理错误
169-
error.value = err.message || '请求失败,请稍后再试'
170-
console.error('请求错误:', err)
158+
error.value = err.message || '请求失败,请稍后再试';
159+
console.error('请求错误:', err);
171160
} finally {
172-
// 结束加载状态
173-
loading.value = false
161+
loading.value = false;
174162
}
175-
}
163+
};
164+
165+
// 提取原日期处理逻辑为独立函数(复用)
166+
const handleTimelineData = (data) => {
167+
const yearKeys = Object.keys(data);
168+
const sortedYears = yearKeys.map(Number).sort((a, b) => b - a);
169+
return sortedYears.map(year => {
170+
const yearStr = String(year);
171+
const articles = data[yearStr].map(article => {
172+
const utcDate = new Date(article.createdAt);
173+
return {
174+
...article,
175+
date: `${String(utcDate.getMonth() + 1).padStart(2, '0')}-${String(utcDate.getDate()).padStart(2, '0')}`
176+
};
177+
});
178+
return {
179+
year: yearStr,
180+
isExpanded: DEFAULT_EXPANDED,
181+
articles
182+
};
183+
});
184+
};
176185
177-
// 可选:组件挂载时自动请求
178-
onMounted(fetchData)
186+
// 组件挂载时请求(优先用缓存)
187+
onMounted(() => fetchData());
179188
180189
</script>
181190

0 commit comments

Comments
 (0)