play页面缓存引入主动清理机制
This commit is contained in:
@@ -2,18 +2,16 @@
|
||||
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { initDanmakuModule } from '@/lib/danmaku/api';
|
||||
import { initStartupCacheCleanup } from '@/lib/startup/cacheCleanup';
|
||||
|
||||
/**
|
||||
* 弹幕缓存清理组件
|
||||
* 在应用启动时执行一次过期缓存清理
|
||||
* 启动缓存清理组件
|
||||
* 在应用启动时异步执行一次缓存清理
|
||||
*/
|
||||
export function DanmakuCacheCleanup() {
|
||||
export function StartupCacheCleanup() {
|
||||
useEffect(() => {
|
||||
// 只在客户端执行一次
|
||||
initDanmakuModule();
|
||||
initStartupCacheCleanup();
|
||||
}, []);
|
||||
|
||||
// 这个组件不渲染任何内容
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,12 @@ import { useEnableComments } from '@/hooks/useEnableComments';
|
||||
import ScrollableRow from '@/components/ScrollableRow';
|
||||
import VideoCard from '@/components/VideoCard';
|
||||
|
||||
import {
|
||||
getRecommendationCache,
|
||||
recommendationCacheKeys,
|
||||
setRecommendationCache,
|
||||
} from '@/lib/recommendations/cache';
|
||||
|
||||
interface DoubanRecommendation {
|
||||
doubanId: string;
|
||||
title: string;
|
||||
@@ -31,25 +37,14 @@ export default function DoubanRecommendations({ doubanId }: DoubanRecommendation
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
// 检查localStorage缓存
|
||||
const cacheKey = `douban_recommendations_${doubanId}`;
|
||||
const cached = localStorage.getItem(cacheKey);
|
||||
const cacheKey = recommendationCacheKeys.doubanRecommendations(doubanId);
|
||||
const cached = getRecommendationCache<DoubanRecommendation[]>(cacheKey);
|
||||
|
||||
if (cached) {
|
||||
try {
|
||||
const { data, timestamp } = JSON.parse(cached);
|
||||
const cacheAge = Date.now() - timestamp;
|
||||
const cacheMaxAge = 7 * 24 * 60 * 60 * 1000; // 7天
|
||||
|
||||
if (cacheAge < cacheMaxAge) {
|
||||
console.log('使用缓存的推荐数据');
|
||||
setRecommendations(data);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('解析缓存失败:', e);
|
||||
}
|
||||
console.log('使用缓存的推荐数据');
|
||||
setRecommendations(cached);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
@@ -66,15 +61,7 @@ export default function DoubanRecommendations({ doubanId }: DoubanRecommendation
|
||||
const recommendationsData = result.recommendations || [];
|
||||
setRecommendations(recommendationsData);
|
||||
|
||||
// 保存到localStorage
|
||||
try {
|
||||
localStorage.setItem(cacheKey, JSON.stringify({
|
||||
data: recommendationsData,
|
||||
timestamp: Date.now()
|
||||
}));
|
||||
} catch (e) {
|
||||
console.error('保存缓存失败:', e);
|
||||
}
|
||||
setRecommendationCache(cacheKey, recommendationsData);
|
||||
} catch (err) {
|
||||
console.error('获取推荐失败:', err);
|
||||
setError(err instanceof Error ? err.message : '获取推荐失败');
|
||||
|
||||
@@ -8,6 +8,12 @@ import { useRecommendationDataSource } from '@/hooks/useRecommendationDataSource
|
||||
import ScrollableRow from '@/components/ScrollableRow';
|
||||
import VideoCard from '@/components/VideoCard';
|
||||
|
||||
import {
|
||||
getRecommendationCache,
|
||||
recommendationCacheKeys,
|
||||
setRecommendationCache,
|
||||
} from '@/lib/recommendations/cache';
|
||||
|
||||
interface Recommendation {
|
||||
doubanId?: string;
|
||||
tmdbId?: number;
|
||||
@@ -63,25 +69,14 @@ export default function SmartRecommendations({
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
// 检查localStorage缓存
|
||||
const cacheKey = `douban_recommendations_${doubanId}`;
|
||||
const cached = localStorage.getItem(cacheKey);
|
||||
const cacheKey = recommendationCacheKeys.doubanRecommendations(doubanId);
|
||||
const cached = getRecommendationCache<Recommendation[]>(cacheKey);
|
||||
|
||||
if (cached) {
|
||||
try {
|
||||
const { data, timestamp } = JSON.parse(cached);
|
||||
const cacheAge = Date.now() - timestamp;
|
||||
const cacheMaxAge = 7 * 24 * 60 * 60 * 1000; // 7天
|
||||
|
||||
if (cacheAge < cacheMaxAge) {
|
||||
console.log('使用缓存的豆瓣推荐数据');
|
||||
setRecommendations(data);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('解析缓存失败:', e);
|
||||
}
|
||||
console.log('使用缓存的豆瓣推荐数据');
|
||||
setRecommendations(cached);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await fetch(`/api/douban-recommendations?id=${doubanId}`);
|
||||
@@ -94,18 +89,7 @@ export default function SmartRecommendations({
|
||||
const recommendationsData = result.recommendations || [];
|
||||
setRecommendations(recommendationsData);
|
||||
|
||||
// 保存到localStorage
|
||||
try {
|
||||
localStorage.setItem(
|
||||
cacheKey,
|
||||
JSON.stringify({
|
||||
data: recommendationsData,
|
||||
timestamp: Date.now(),
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.error('保存缓存失败:', e);
|
||||
}
|
||||
setRecommendationCache(cacheKey, recommendationsData);
|
||||
} catch (err) {
|
||||
console.error('获取豆瓣推荐失败:', err);
|
||||
setError(err instanceof Error ? err.message : '获取推荐失败');
|
||||
@@ -122,44 +106,20 @@ export default function SmartRecommendations({
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
// 检查title到tmdbId的映射缓存(1个月)
|
||||
const mappingCacheKey = `tmdb_title_mapping_${videoTitle}`;
|
||||
const mappingCache = localStorage.getItem(mappingCacheKey);
|
||||
let cachedId: string | null = null;
|
||||
const mappingCacheKey = recommendationCacheKeys.tmdbTitleMapping(videoTitle);
|
||||
const cachedId = getRecommendationCache<string>(mappingCacheKey);
|
||||
|
||||
if (mappingCache) {
|
||||
try {
|
||||
const { tmdbId, timestamp } = JSON.parse(mappingCache);
|
||||
const cacheAge = Date.now() - timestamp;
|
||||
const cacheMaxAge = 30 * 24 * 60 * 60 * 1000; // 1个月
|
||||
if (cachedId) {
|
||||
console.log('使用缓存的TMDB ID映射');
|
||||
|
||||
if (cacheAge < cacheMaxAge && tmdbId) {
|
||||
console.log('使用缓存的TMDB ID映射');
|
||||
cachedId = tmdbId;
|
||||
const recommendationsCacheKey = recommendationCacheKeys.tmdbRecommendations(cachedId);
|
||||
const recommendationsCache = getRecommendationCache<Recommendation[]>(recommendationsCacheKey);
|
||||
|
||||
// 检查TMDB推荐数据缓存(1天)
|
||||
const recommendationsCacheKey = `tmdb_recommendations_${tmdbId}`;
|
||||
const recommendationsCache = localStorage.getItem(recommendationsCacheKey);
|
||||
|
||||
if (recommendationsCache) {
|
||||
try {
|
||||
const { data, timestamp: recTimestamp } = JSON.parse(recommendationsCache);
|
||||
const recCacheAge = Date.now() - recTimestamp;
|
||||
const recCacheMaxAge = 24 * 60 * 60 * 1000; // 1天
|
||||
|
||||
if (recCacheAge < recCacheMaxAge && data) {
|
||||
console.log('使用缓存的TMDB推荐数据');
|
||||
setRecommendations(data);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('解析推荐缓存失败:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('解析映射缓存失败:', e);
|
||||
if (recommendationsCache) {
|
||||
console.log('使用缓存的TMDB推荐数据');
|
||||
setRecommendations(recommendationsCache);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,23 +141,10 @@ export default function SmartRecommendations({
|
||||
// 保存title到tmdbId的映射到localStorage(1个月)
|
||||
if (result.tmdbId) {
|
||||
try {
|
||||
localStorage.setItem(
|
||||
mappingCacheKey,
|
||||
JSON.stringify({
|
||||
tmdbId: result.tmdbId,
|
||||
timestamp: Date.now(),
|
||||
})
|
||||
);
|
||||
setRecommendationCache(mappingCacheKey, String(result.tmdbId));
|
||||
|
||||
// 保存TMDB推荐数据到localStorage(1天)
|
||||
const recommendationsCacheKey = `tmdb_recommendations_${result.tmdbId}`;
|
||||
localStorage.setItem(
|
||||
recommendationsCacheKey,
|
||||
JSON.stringify({
|
||||
data: recommendationsData,
|
||||
timestamp: Date.now(),
|
||||
})
|
||||
);
|
||||
const recommendationsCacheKey = recommendationCacheKeys.tmdbRecommendations(result.tmdbId);
|
||||
setRecommendationCache(recommendationsCacheKey, recommendationsData);
|
||||
} catch (e) {
|
||||
console.error('保存缓存失败:', e);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user