修正立即扫描openlist端不刷新

This commit is contained in:
mtvpls
2025-12-22 22:07:09 +08:00
parent 2104abb84b
commit 76ee99cda2
4 changed files with 30 additions and 133 deletions

View File

@@ -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) => {

View File

@@ -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) // 根据参数过滤失败的视频

View File

@@ -104,59 +104,21 @@ async function performScan(
): Promise<void> {
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) {

View File

@@ -174,7 +174,8 @@ export class OpenListClient {
async listDirectory(
path: string,
page = 1,
perPage = 100
perPage = 100,
refresh = false
): Promise<OpenListListResponse> {
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,
}),