From 76ee99cda2eb7ebc7d46d05d75b07081a384a0ca Mon Sep 17 00:00:00 2001 From: mtvpls Date: Mon, 22 Dec 2025 22:07:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E7=AB=8B=E5=8D=B3=E6=89=AB?= =?UTF-8?q?=E6=8F=8Fopenlist=E7=AB=AF=E4=B8=8D=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/admin/page.tsx | 11 ++- src/app/api/openlist/list/route.ts | 39 ++++------ src/app/api/openlist/refresh/route.ts | 108 ++------------------------ src/lib/openlist.client.ts | 5 +- 4 files changed, 30 insertions(+), 133 deletions(-) diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 8dff29c..9121e76 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -2569,10 +2569,11 @@ const OpenListConfigComponent = ({ } }, [config]); - const fetchVideos = async () => { + const fetchVideos = async (noCache = false) => { try { setRefreshing(true); - const response = await fetch('/api/openlist/list?page=1&pageSize=100&includeFailed=true'); + const url = `/api/openlist/list?page=1&pageSize=100&includeFailed=true${noCache ? '&noCache=true' : ''}`; + const response = await fetch(url); if (response.ok) { const data = await response.json(); setVideos(data.list || []); @@ -2658,8 +2659,10 @@ const OpenListConfigComponent = ({ `扫描完成!新增 ${task.result.new} 个,已存在 ${task.result.existing} 个,失败 ${task.result.errors} 个`, showAlert ); + // 先强制从数据库读取视频列表(这会更新缓存) + await fetchVideos(true); + // 然后再刷新配置(这会触发 useEffect,但此时缓存已经是新的了) await refreshConfig(); - await fetchVideos(); } else if (task.status === 'failed') { clearInterval(pollInterval); setScanProgress(null); @@ -2703,7 +2706,7 @@ const OpenListConfigComponent = ({ }; const handleCorrectSuccess = () => { - fetchVideos(); + fetchVideos(true); // 强制从数据库重新读取,不使用缓存 }; const formatDate = (timestamp?: number) => { diff --git a/src/app/api/openlist/list/route.ts b/src/app/api/openlist/list/route.ts index 4c18a84..8c67b18 100644 --- a/src/app/api/openlist/list/route.ts +++ b/src/app/api/openlist/list/route.ts @@ -16,7 +16,7 @@ import { getTMDBImageUrl } from '@/lib/tmdb.search'; export const runtime = 'nodejs'; /** - * GET /api/openlist/list?page=1&pageSize=20&includeFailed=false + * GET /api/openlist/list?page=1&pageSize=20&includeFailed=false&noCache=false * 获取私人影库视频列表 */ export async function GET(request: NextRequest) { @@ -30,6 +30,7 @@ export async function GET(request: NextRequest) { const page = parseInt(searchParams.get('page') || '1'); const pageSize = parseInt(searchParams.get('pageSize') || '20'); const includeFailed = searchParams.get('includeFailed') === 'true'; + const noCache = searchParams.get('noCache') === 'true'; const config = await getConfig(); const openListConfig = config.OpenListConfig; @@ -49,30 +50,22 @@ export async function GET(request: NextRequest) { ); // 读取 metainfo (从数据库或缓存) - let metaInfo: MetaInfo | null = getCachedMetaInfo(rootPath); + let metaInfo: MetaInfo | null = null; - console.log('[OpenList List] 缓存检查:', { - rootPath, - hasCachedMetaInfo: !!metaInfo, - }); + // 如果不使用缓存,直接从数据库读取 + if (noCache) { + // noCache 模式:跳过缓存 + } else { + metaInfo = getCachedMetaInfo(rootPath); + } if (!metaInfo) { try { - console.log('[OpenList List] 尝试从数据库读取 metainfo'); - const metainfoJson = await db.getGlobalValue('video.metainfo'); if (metainfoJson) { - console.log('[OpenList List] 从数据库获取到数据,长度:', metainfoJson.length); - try { metaInfo = JSON.parse(metainfoJson); - console.log('[OpenList List] JSON 解析成功'); - console.log('[OpenList List] metaInfo 结构:', { - hasfolders: !!metaInfo?.folders, - foldersType: typeof metaInfo?.folders, - keys: metaInfo?.folders ? Object.keys(metaInfo.folders) : [], - }); // 验证数据结构 if (!metaInfo || typeof metaInfo !== 'object') { @@ -82,8 +75,10 @@ export async function GET(request: NextRequest) { throw new Error('metaInfo.folders 不存在或不是对象'); } - console.log('[OpenList List] 解析成功,视频数量:', Object.keys(metaInfo.folders).length); - setCachedMetaInfo(rootPath, metaInfo); + // 只有在不是 noCache 模式时才更新缓存 + if (!noCache) { + setCachedMetaInfo(rootPath, metaInfo); + } } catch (parseError) { console.error('[OpenList List] JSON 解析或验证失败:', parseError); throw new Error(`JSON 解析失败: ${(parseError as Error).message}`); @@ -106,7 +101,6 @@ export async function GET(request: NextRequest) { } if (!metaInfo) { - console.error('[OpenList List] metaInfo 为 null'); return NextResponse.json( { error: '无数据', list: [], total: 0 }, { status: 200 } @@ -115,19 +109,12 @@ export async function GET(request: NextRequest) { // 验证 metaInfo 结构 if (!metaInfo.folders || typeof metaInfo.folders !== 'object') { - console.error('[OpenList List] metaInfo.folders 无效:', { - hasfolders: !!metaInfo.folders, - foldersType: typeof metaInfo.folders, - metaInfoKeys: Object.keys(metaInfo), - }); return NextResponse.json( { error: 'metainfo.json 结构无效', list: [], total: 0 }, { status: 200 } ); } - console.log('[OpenList List] 开始转换视频列表,视频数:', Object.keys(metaInfo.folders).length); - // 转换为数组并分页 const allVideos = Object.entries(metaInfo.folders) .filter(([, info]) => includeFailed || !info.failed) // 根据参数过滤失败的视频 diff --git a/src/app/api/openlist/refresh/route.ts b/src/app/api/openlist/refresh/route.ts index dccd53b..e728858 100644 --- a/src/app/api/openlist/refresh/route.ts +++ b/src/app/api/openlist/refresh/route.ts @@ -104,59 +104,21 @@ async function performScan( ): Promise { const client = new OpenListClient(url, username!, password!); - console.log('[OpenList Refresh] 开始扫描:', { - taskId, - rootPath, - url, - }); + // 立即清除缓存,确保后续读取的是新数据 + invalidateMetaInfoCache(rootPath); // 立即更新进度,确保任务可被查询 updateScanTaskProgress(taskId, 0, 0); try { - // 1. 读取现有 metainfo (从数据库或缓存) - let existingMetaInfo: MetaInfo | null = getCachedMetaInfo(rootPath); - - if (!existingMetaInfo) { - try { - console.log('[OpenList Refresh] 尝试从数据库读取 metainfo'); - const metainfoJson = await db.getGlobalValue('video.metainfo'); - - if (metainfoJson) { - existingMetaInfo = JSON.parse(metainfoJson); - console.log('[OpenList Refresh] 从数据库读取到现有数据:', { - hasfolders: !!existingMetaInfo?.folders, - foldersType: typeof existingMetaInfo?.folders, - videoCount: Object.keys(existingMetaInfo?.folders || {}).length, - }); - } - } catch (error) { - console.error('[OpenList Refresh] 从数据库读取 metainfo 失败:', error); - console.log('[OpenList Refresh] 将创建新数据'); - } - } else { - console.log('[OpenList Refresh] 使用缓存的 metainfo,视频数:', Object.keys(existingMetaInfo.folders).length); - } - - const metaInfo: MetaInfo = existingMetaInfo || { + // 1. 不读取现有数据,直接创建新的 metainfo + const metaInfo: MetaInfo = { folders: {}, last_refresh: Date.now(), }; - // 确保 folders 对象存在 - if (!metaInfo.folders || typeof metaInfo.folders !== 'object') { - console.warn('[OpenList Refresh] metaInfo.folders 无效,重新初始化'); - metaInfo.folders = {}; - } - - console.log('[OpenList Refresh] metaInfo 初始化完成:', { - hasfolders: !!metaInfo.folders, - foldersType: typeof metaInfo.folders, - videoCount: Object.keys(metaInfo.folders).length, - }); - - // 2. 列出根目录下的所有文件夹 - const listResponse = await client.listDirectory(rootPath); + // 2. 列出根目录下的所有文件夹(强制刷新 OpenList 缓存) + const listResponse = await client.listDirectory(rootPath, 1, 100, true); if (listResponse.code !== 200) { throw new Error('OpenList 列表获取失败'); @@ -164,11 +126,6 @@ async function performScan( const folders = listResponse.data.content.filter((item) => item.is_dir); - console.log('[OpenList Refresh] 找到文件夹:', { - total: folders.length, - names: folders.map(f => f.name), - }); - // 更新任务进度 updateScanTaskProgress(taskId, 0, folders.length); @@ -178,19 +135,11 @@ async function performScan( for (let i = 0; i < folders.length; i++) { const folder = folders[i]; - console.log('[OpenList Refresh] 处理文件夹:', folder.name); // 更新进度 updateScanTaskProgress(taskId, i + 1, folders.length, folder.name); - // 跳过已搜索过的文件夹 - if (metaInfo.folders[folder.name]) { - console.log('[OpenList Refresh] 跳过已存在的文件夹:', folder.name); - continue; - } - try { - console.log('[OpenList Refresh] 搜索 TMDB:', folder.name); // 搜索 TMDB const searchResult = await searchTMDB( tmdbApiKey, @@ -198,12 +147,6 @@ async function performScan( tmdbProxy ); - console.log('[OpenList Refresh] TMDB 搜索结果:', { - folder: folder.name, - code: searchResult.code, - hasResult: !!searchResult.result, - }); - if (searchResult.code === 200 && searchResult.result) { const result = searchResult.result; @@ -219,14 +162,8 @@ async function performScan( failed: false, }; - console.log('[OpenList Refresh] 添加成功:', { - folder: folder.name, - title: metaInfo.folders[folder.name].title, - }); - newCount++; } else { - console.warn(`[OpenList Refresh] TMDB 搜索失败: ${folder.name}`); // 记录失败的文件夹 metaInfo.folders[folder.name] = { tmdb_id: 0, @@ -266,34 +203,11 @@ async function performScan( metaInfo.last_refresh = Date.now(); const metainfoContent = JSON.stringify(metaInfo); - console.log('[OpenList Refresh] 保存 metainfo 到数据库:', { - videoCount: Object.keys(metaInfo.folders).length, - contentLength: metainfoContent.length, - }); - await db.setGlobalValue('video.metainfo', metainfoContent); - console.log('[OpenList Refresh] 保存成功'); - - // 验证保存:立即读取数据库 - try { - console.log('[OpenList Refresh] 验证保存:读取数据库'); - const verifyContent = await db.getGlobalValue('video.metainfo'); - if (verifyContent) { - const verifyParsed = JSON.parse(verifyContent); - console.log('[OpenList Refresh] 验证解析成功:', { - hasfolders: !!verifyParsed.folders, - foldersType: typeof verifyParsed.folders, - videoCount: Object.keys(verifyParsed.folders || {}).length, - }); - } - } catch (verifyError) { - console.error('[OpenList Refresh] 验证失败:', verifyError); - } // 5. 更新缓存 invalidateMetaInfoCache(rootPath); setCachedMetaInfo(rootPath, metaInfo); - console.log('[OpenList Refresh] 缓存已更新'); // 6. 更新配置 const config = await getConfig(); @@ -305,15 +219,7 @@ async function performScan( completeScanTask(taskId, { total: folders.length, new: newCount, - existing: Object.keys(metaInfo.folders).length - newCount, - errors: errorCount, - }); - - console.log('[OpenList Refresh] 扫描完成:', { - taskId, - total: folders.length, - new: newCount, - existing: Object.keys(metaInfo.folders).length - newCount, + existing: 0, errors: errorCount, }); } catch (error) { diff --git a/src/lib/openlist.client.ts b/src/lib/openlist.client.ts index f291f47..790caad 100644 --- a/src/lib/openlist.client.ts +++ b/src/lib/openlist.client.ts @@ -174,7 +174,8 @@ export class OpenListClient { async listDirectory( path: string, page = 1, - perPage = 100 + perPage = 100, + refresh = false ): Promise { const response = await this.fetchWithRetry(`${this.baseURL}/api/fs/list`, { method: 'POST', @@ -182,7 +183,7 @@ export class OpenListClient { body: JSON.stringify({ path, password: '', - refresh: false, + refresh, page, per_page: perPage, }),