弹幕缓存显示元信息
This commit is contained in:
+48
-12
@@ -606,9 +606,21 @@ function PlayPageClient() {
|
|||||||
|
|
||||||
// 先尝试从 IndexedDB 缓存加载
|
// 先尝试从 IndexedDB 缓存加载
|
||||||
try {
|
try {
|
||||||
const cachedComments = await getDanmakuFromCache(title, episodeIndex);
|
const cachedData = await getDanmakuFromCache(title, episodeIndex);
|
||||||
if (cachedComments && cachedComments.length > 0) {
|
if (cachedData && cachedData.comments.length > 0) {
|
||||||
console.log(`[弹幕] 使用缓存: title="${title}", episodeIndex=${episodeIndex}, 数量=${cachedComments.length}`);
|
console.log(`[弹幕] 使用缓存: title="${title}", episodeIndex=${episodeIndex}, 数量=${cachedData.comments.length}`);
|
||||||
|
|
||||||
|
// 如果缓存中有元信息,更新当前选择状态
|
||||||
|
if (cachedData.metadata) {
|
||||||
|
setCurrentDanmakuSelection({
|
||||||
|
animeId: cachedData.metadata.animeId || 0,
|
||||||
|
episodeId: cachedData.metadata.episodeId || 0,
|
||||||
|
animeTitle: cachedData.metadata.animeTitle || '',
|
||||||
|
episodeTitle: cachedData.metadata.episodeTitle || '',
|
||||||
|
searchKeyword: cachedData.metadata.searchKeyword,
|
||||||
|
danmakuCount: cachedData.metadata.danmakuCount || cachedData.comments.length,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 如果弹幕插件还未初始化,等待初始化
|
// 如果弹幕插件还未初始化,等待初始化
|
||||||
if (!danmakuPluginRef.current) {
|
if (!danmakuPluginRef.current) {
|
||||||
@@ -620,7 +632,7 @@ function PlayPageClient() {
|
|||||||
setDanmakuLoading(true);
|
setDanmakuLoading(true);
|
||||||
|
|
||||||
// 转换弹幕格式
|
// 转换弹幕格式
|
||||||
let danmakuData = convertDanmakuFormat(cachedComments);
|
let danmakuData = convertDanmakuFormat(cachedData.comments);
|
||||||
|
|
||||||
// 手动应用过滤规则
|
// 手动应用过滤规则
|
||||||
const filterConfig = danmakuFilterConfigRef.current;
|
const filterConfig = danmakuFilterConfigRef.current;
|
||||||
@@ -3007,7 +3019,13 @@ function PlayPageClient() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 加载弹幕到播放器
|
// 加载弹幕到播放器
|
||||||
const loadDanmaku = async (episodeId: number) => {
|
const loadDanmaku = async (episodeId: number, metadata?: {
|
||||||
|
animeId?: number;
|
||||||
|
animeTitle?: string;
|
||||||
|
episodeTitle?: string;
|
||||||
|
searchKeyword?: string;
|
||||||
|
danmakuCount?: number;
|
||||||
|
}) => {
|
||||||
if (!danmakuPluginRef.current) {
|
if (!danmakuPluginRef.current) {
|
||||||
console.warn('弹幕插件未初始化');
|
console.warn('弹幕插件未初始化');
|
||||||
return;
|
return;
|
||||||
@@ -3036,7 +3054,7 @@ function PlayPageClient() {
|
|||||||
|
|
||||||
console.log(`[弹幕加载] episodeId=${episodeId}, title="${title}", episodeIndex=${episodeIndex}`);
|
console.log(`[弹幕加载] episodeId=${episodeId}, title="${title}", episodeIndex=${episodeIndex}`);
|
||||||
|
|
||||||
const comments = await getDanmakuById(episodeId, title, episodeIndex);
|
const comments = await getDanmakuById(episodeId, title, episodeIndex, metadata);
|
||||||
|
|
||||||
if (comments.length === 0) {
|
if (comments.length === 0) {
|
||||||
console.warn('未获取到弹幕数据');
|
console.warn('未获取到弹幕数据');
|
||||||
@@ -3214,8 +3232,14 @@ function PlayPageClient() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载弹幕
|
// 加载弹幕,传递元信息
|
||||||
await loadDanmaku(selection.episodeId);
|
await loadDanmaku(selection.episodeId, {
|
||||||
|
animeId: selection.animeId,
|
||||||
|
animeTitle: selection.animeTitle,
|
||||||
|
episodeTitle: selection.episodeTitle,
|
||||||
|
searchKeyword: selection.searchKeyword,
|
||||||
|
danmakuCount: selection.danmakuCount,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理用户选择弹幕源
|
// 处理用户选择弹幕源
|
||||||
@@ -3330,9 +3354,21 @@ function PlayPageClient() {
|
|||||||
|
|
||||||
// 先尝试从 IndexedDB 缓存加载
|
// 先尝试从 IndexedDB 缓存加载
|
||||||
try {
|
try {
|
||||||
const cachedComments = await getDanmakuFromCache(title, currentEpisodeIndex);
|
const cachedData = await getDanmakuFromCache(title, currentEpisodeIndex);
|
||||||
if (cachedComments && cachedComments.length > 0) {
|
if (cachedData && cachedData.comments.length > 0) {
|
||||||
console.log(`[弹幕] 使用缓存: title="${title}", episodeIndex=${currentEpisodeIndex}, 数量=${cachedComments.length}`);
|
console.log(`[弹幕] 使用缓存: title="${title}", episodeIndex=${currentEpisodeIndex}, 数量=${cachedData.comments.length}`);
|
||||||
|
|
||||||
|
// 如果缓存中有元信息,更新当前选择状态
|
||||||
|
if (cachedData.metadata) {
|
||||||
|
setCurrentDanmakuSelection({
|
||||||
|
animeId: cachedData.metadata.animeId || 0,
|
||||||
|
episodeId: cachedData.metadata.episodeId || 0,
|
||||||
|
animeTitle: cachedData.metadata.animeTitle || '',
|
||||||
|
episodeTitle: cachedData.metadata.episodeTitle || '',
|
||||||
|
searchKeyword: cachedData.metadata.searchKeyword,
|
||||||
|
danmakuCount: cachedData.metadata.danmakuCount || cachedData.comments.length,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 直接加载缓存的弹幕,不需要调用 API
|
// 直接加载缓存的弹幕,不需要调用 API
|
||||||
if (!danmakuPluginRef.current) {
|
if (!danmakuPluginRef.current) {
|
||||||
@@ -3343,7 +3379,7 @@ function PlayPageClient() {
|
|||||||
setDanmakuLoading(true);
|
setDanmakuLoading(true);
|
||||||
|
|
||||||
// 转换弹幕格式
|
// 转换弹幕格式
|
||||||
let danmakuData = convertDanmakuFormat(cachedComments);
|
let danmakuData = convertDanmakuFormat(cachedData.comments);
|
||||||
|
|
||||||
// 手动应用过滤规则
|
// 手动应用过滤规则
|
||||||
const filterConfig = danmakuFilterConfigRef.current;
|
const filterConfig = danmakuFilterConfigRef.current;
|
||||||
|
|||||||
@@ -238,6 +238,11 @@ export default function DanmakuPanel({
|
|||||||
<p className='text-xs text-gray-600 dark:text-gray-400'>
|
<p className='text-xs text-gray-600 dark:text-gray-400'>
|
||||||
{currentSelection.episodeTitle}
|
{currentSelection.episodeTitle}
|
||||||
</p>
|
</p>
|
||||||
|
{currentSelection.danmakuCount !== undefined && (
|
||||||
|
<p className='mt-1 text-xs text-gray-500 dark:text-gray-500'>
|
||||||
|
弹幕数量: {currentSelection.danmakuCount}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
+20
-6
@@ -143,15 +143,22 @@ export async function getEpisodes(
|
|||||||
export async function getDanmakuById(
|
export async function getDanmakuById(
|
||||||
episodeId: number,
|
episodeId: number,
|
||||||
title?: string,
|
title?: string,
|
||||||
episodeIndex?: number
|
episodeIndex?: number,
|
||||||
|
metadata?: {
|
||||||
|
animeId?: number;
|
||||||
|
animeTitle?: string;
|
||||||
|
episodeTitle?: string;
|
||||||
|
searchKeyword?: string;
|
||||||
|
danmakuCount?: number;
|
||||||
|
}
|
||||||
): Promise<DanmakuComment[]> {
|
): Promise<DanmakuComment[]> {
|
||||||
try {
|
try {
|
||||||
// 1. 如果提供了 title 和 episodeIndex,先尝试从缓存读取
|
// 1. 如果提供了 title 和 episodeIndex,先尝试从缓存读取
|
||||||
if (title && episodeIndex !== undefined) {
|
if (title && episodeIndex !== undefined) {
|
||||||
const cachedComments = await getDanmakuFromCache(title, episodeIndex);
|
const cachedData = await getDanmakuFromCache(title, episodeIndex);
|
||||||
if (cachedComments) {
|
if (cachedData) {
|
||||||
console.log(`[弹幕缓存] 使用缓存: title=${title}, episodeIndex=${episodeIndex}, 数量=${cachedComments.length}`);
|
console.log(`[弹幕缓存] 使用缓存: title=${title}, episodeIndex=${episodeIndex}, 数量=${cachedData.comments.length}`);
|
||||||
return cachedComments;
|
return cachedData.comments;
|
||||||
}
|
}
|
||||||
console.log(`[弹幕缓存] 缓存未命中,从 API 获取: title=${title}, episodeIndex=${episodeIndex}`);
|
console.log(`[弹幕缓存] 缓存未命中,从 API 获取: title=${title}, episodeIndex=${episodeIndex}`);
|
||||||
} else {
|
} else {
|
||||||
@@ -173,7 +180,14 @@ export async function getDanmakuById(
|
|||||||
if (comments.length > 0 && title && title.trim() !== '' && episodeIndex !== undefined && episodeIndex >= 0) {
|
if (comments.length > 0 && title && title.trim() !== '' && episodeIndex !== undefined && episodeIndex >= 0) {
|
||||||
try {
|
try {
|
||||||
console.log(`[弹幕缓存] 尝试保存缓存: title="${title}", episodeIndex=${episodeIndex}, 数量=${comments.length}`);
|
console.log(`[弹幕缓存] 尝试保存缓存: title="${title}", episodeIndex=${episodeIndex}, 数量=${comments.length}`);
|
||||||
await saveDanmakuToCache(title, episodeIndex, comments);
|
await saveDanmakuToCache(title, episodeIndex, comments, {
|
||||||
|
animeId: metadata?.animeId,
|
||||||
|
episodeId: episodeId,
|
||||||
|
animeTitle: metadata?.animeTitle,
|
||||||
|
episodeTitle: metadata?.episodeTitle,
|
||||||
|
searchKeyword: metadata?.searchKeyword,
|
||||||
|
danmakuCount: metadata?.danmakuCount ?? comments.length,
|
||||||
|
});
|
||||||
console.log(`[弹幕缓存] 已缓存: title=${title}, episodeIndex=${episodeIndex}, 数量=${comments.length}`);
|
console.log(`[弹幕缓存] 已缓存: title=${title}, episodeIndex=${episodeIndex}, 数量=${comments.length}`);
|
||||||
} catch (cacheError) {
|
} catch (cacheError) {
|
||||||
console.error('[弹幕缓存] 保存缓存失败:', cacheError);
|
console.error('[弹幕缓存] 保存缓存失败:', cacheError);
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ export interface DanmakuCacheData {
|
|||||||
timestamp: number; // 缓存时间戳
|
timestamp: number; // 缓存时间戳
|
||||||
title?: string; // 可选:视频标题
|
title?: string; // 可选:视频标题
|
||||||
episodeIndex?: number; // 可选:集数索引
|
episodeIndex?: number; // 可选:集数索引
|
||||||
|
// 弹幕元信息
|
||||||
|
animeId?: number; // 动漫ID
|
||||||
|
episodeId?: number; // 剧集ID
|
||||||
|
animeTitle?: string; // 动漫标题
|
||||||
|
episodeTitle?: string; // 剧集标题
|
||||||
|
searchKeyword?: string; // 搜索关键词
|
||||||
|
danmakuCount?: number; // 弹幕数量
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成缓存键(title + episodeIndex)
|
// 生成缓存键(title + episodeIndex)
|
||||||
@@ -73,7 +80,15 @@ async function openDB(): Promise<IDBDatabase> {
|
|||||||
export async function saveDanmakuToCache(
|
export async function saveDanmakuToCache(
|
||||||
title: string,
|
title: string,
|
||||||
episodeIndex: number,
|
episodeIndex: number,
|
||||||
comments: DanmakuComment[]
|
comments: DanmakuComment[],
|
||||||
|
metadata?: {
|
||||||
|
animeId?: number;
|
||||||
|
episodeId?: number;
|
||||||
|
animeTitle?: string;
|
||||||
|
episodeTitle?: string;
|
||||||
|
searchKeyword?: string;
|
||||||
|
danmakuCount?: number;
|
||||||
|
}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// 验证参数
|
// 验证参数
|
||||||
if (!title || title.trim() === '') {
|
if (!title || title.trim() === '') {
|
||||||
@@ -104,6 +119,13 @@ export async function saveDanmakuToCache(
|
|||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
title,
|
title,
|
||||||
episodeIndex,
|
episodeIndex,
|
||||||
|
// 保存弹幕元信息
|
||||||
|
animeId: metadata?.animeId,
|
||||||
|
episodeId: metadata?.episodeId,
|
||||||
|
animeTitle: metadata?.animeTitle,
|
||||||
|
episodeTitle: metadata?.episodeTitle,
|
||||||
|
searchKeyword: metadata?.searchKeyword,
|
||||||
|
danmakuCount: metadata?.danmakuCount ?? comments.length, // 使用提供的数量或comments长度
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加调试日志
|
// 添加调试日志
|
||||||
@@ -141,7 +163,17 @@ export async function saveDanmakuToCache(
|
|||||||
export async function getDanmakuFromCache(
|
export async function getDanmakuFromCache(
|
||||||
title: string,
|
title: string,
|
||||||
episodeIndex: number
|
episodeIndex: number
|
||||||
): Promise<DanmakuComment[] | null> {
|
): Promise<{
|
||||||
|
comments: DanmakuComment[];
|
||||||
|
metadata?: {
|
||||||
|
animeId?: number;
|
||||||
|
episodeId?: number;
|
||||||
|
animeTitle?: string;
|
||||||
|
episodeTitle?: string;
|
||||||
|
searchKeyword?: string;
|
||||||
|
danmakuCount?: number;
|
||||||
|
};
|
||||||
|
} | null> {
|
||||||
// 如果缓存时间设置为 0,不使用缓存
|
// 如果缓存时间设置为 0,不使用缓存
|
||||||
const expireTime = getDanmakuCacheExpireTime();
|
const expireTime = getDanmakuCacheExpireTime();
|
||||||
if (expireTime === 0) {
|
if (expireTime === 0) {
|
||||||
@@ -186,7 +218,17 @@ export async function getDanmakuFromCache(
|
|||||||
console.log(
|
console.log(
|
||||||
`从缓存获取弹幕: title=${title}, episodeIndex=${episodeIndex}, 数量=${result.comments.length}, 年龄=${ageMinutes}分钟`
|
`从缓存获取弹幕: title=${title}, episodeIndex=${episodeIndex}, 数量=${result.comments.length}, 年龄=${ageMinutes}分钟`
|
||||||
);
|
);
|
||||||
resolve(result.comments);
|
resolve({
|
||||||
|
comments: result.comments,
|
||||||
|
metadata: {
|
||||||
|
animeId: result.animeId,
|
||||||
|
episodeId: result.episodeId,
|
||||||
|
animeTitle: result.animeTitle,
|
||||||
|
episodeTitle: result.episodeTitle,
|
||||||
|
searchKeyword: result.searchKeyword,
|
||||||
|
danmakuCount: result.danmakuCount ?? result.comments.length,
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
request.onerror = () => {
|
request.onerror = () => {
|
||||||
|
|||||||
@@ -114,4 +114,5 @@ export interface DanmakuSelection {
|
|||||||
animeTitle: string;
|
animeTitle: string;
|
||||||
episodeTitle: string;
|
episodeTitle: string;
|
||||||
searchKeyword?: string; // 用户搜索时使用的关键词
|
searchKeyword?: string; // 用户搜索时使用的关键词
|
||||||
|
danmakuCount?: number; // 弹幕数量
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user