修正立即扫描openlist端不刷新
This commit is contained in:
@@ -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) => {
|
||||
|
||||
@@ -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);
|
||||
// 只有在不是 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) // 根据参数过滤失败的视频
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user