修复emby分类加载旧数据

This commit is contained in:
mtvpls
2026-01-08 12:50:41 +08:00
parent 9e8e3a4cc5
commit 7783a47a5c
+56 -40
View File
@@ -75,6 +75,7 @@ export default function PrivateLibraryPage() {
const pageSize = 20; const pageSize = 20;
const observerTarget = useRef<HTMLDivElement>(null); const observerTarget = useRef<HTMLDivElement>(null);
const isFetchingRef = useRef(false); const isFetchingRef = useRef(false);
const abortControllerRef = useRef<AbortController | null>(null);
const scrollContainerRef = useRef<HTMLDivElement>(null); const scrollContainerRef = useRef<HTMLDivElement>(null);
const embyScrollContainerRef = useRef<HTMLDivElement>(null); const embyScrollContainerRef = useRef<HTMLDivElement>(null);
const isDraggingRef = useRef(false); const isDraggingRef = useRef(false);
@@ -160,6 +161,8 @@ export default function PrivateLibraryPage() {
setHasMore(true); setHasMore(true);
setError(''); setError('');
setSelectedView('all'); setSelectedView('all');
setLoading(false);
setLoadingMore(false);
isFetchingRef.current = false; isFetchingRef.current = false;
}, [sourceType, embyKey]); }, [sourceType, embyKey]);
@@ -171,6 +174,8 @@ export default function PrivateLibraryPage() {
setVideos([]); setVideos([]);
setHasMore(true); setHasMore(true);
setError(''); setError('');
setLoading(false);
setLoadingMore(false);
isFetchingRef.current = false; isFetchingRef.current = false;
}, [selectedView]); }, [selectedView]);
@@ -191,13 +196,15 @@ export default function PrivateLibraryPage() {
} else { } else {
setEmbyViews(data.views || []); setEmbyViews(data.views || []);
// 分类加载完成后,检查URL中是否有view参数 // 分类加载完成后,检查URL中是否有view参数(仅在初始化时)
const urlView = searchParams.get('view'); if (!isInitializedRef.current) {
if (urlView && data.views && data.views.length > 0) { const urlView = searchParams.get('view');
// 检查该view是否存在于分类列表中 if (urlView && data.views && data.views.length > 0) {
const viewExists = data.views.some((v: EmbyView) => v.id === urlView); // 检查该view是否存在于分类列表中
if (viewExists) { const viewExists = data.views.some((v: EmbyView) => v.id === urlView);
setSelectedView(urlView); if (viewExists) {
setSelectedView(urlView);
}
} }
} }
} }
@@ -210,7 +217,7 @@ export default function PrivateLibraryPage() {
}; };
fetchEmbyViews(); fetchEmbyViews();
}, [sourceType, embyKey, searchParams]); }, [sourceType, embyKey]);
// 鼠标拖动滚动 // 鼠标拖动滚动
const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => { const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
@@ -249,9 +256,9 @@ export default function PrivateLibraryPage() {
const fetchVideos = async () => { const fetchVideos = async () => {
const isInitial = page === 1; const isInitial = page === 1;
// 防止重复请求 // 取消之前的请求
if (isFetchingRef.current) { if (abortControllerRef.current) {
return; abortControllerRef.current.abort();
} }
// 如果选择了 openlist 但未配置,不发起请求 // 如果选择了 openlist 但未配置,不发起请求
@@ -266,6 +273,9 @@ export default function PrivateLibraryPage() {
return; return;
} }
// 创建新的 AbortController
const abortController = new AbortController();
abortControllerRef.current = abortController;
isFetchingRef.current = true; isFetchingRef.current = true;
try { try {
@@ -280,7 +290,7 @@ export default function PrivateLibraryPage() {
? `/api/openlist/list?page=${page}&pageSize=${pageSize}` ? `/api/openlist/list?page=${page}&pageSize=${pageSize}`
: `/api/emby/list?page=${page}&pageSize=${pageSize}${selectedView !== 'all' ? `&parentId=${selectedView}` : ''}&embyKey=${embyKey}`; : `/api/emby/list?page=${page}&pageSize=${pageSize}${selectedView !== 'all' ? `&parentId=${selectedView}` : ''}&embyKey=${embyKey}`;
const response = await fetch(endpoint); const response = await fetch(endpoint, { signal: abortController.signal });
if (!response.ok) { if (!response.ok) {
throw new Error('获取视频列表失败'); throw new Error('获取视频列表失败');
@@ -308,23 +318,37 @@ export default function PrivateLibraryPage() {
const hasMoreData = currentPage < totalPages; const hasMoreData = currentPage < totalPages;
setHasMore(hasMoreData); setHasMore(hasMoreData);
} }
} catch (err) { } catch (err: any) {
// 忽略取消请求的错误
if (err.name === 'AbortError') {
return;
}
console.error('获取视频列表失败:', err); console.error('获取视频列表失败:', err);
setError('获取视频列表失败'); setError('获取视频列表失败');
if (isInitial) { if (isInitial) {
setVideos([]); setVideos([]);
} }
} finally { } finally {
if (isInitial) { // 只有当这个请求没有被取消时才更新状态
setLoading(false); if (!abortController.signal.aborted) {
} else { if (isInitial) {
setLoadingMore(false); setLoading(false);
} else {
setLoadingMore(false);
}
isFetchingRef.current = false;
} }
isFetchingRef.current = false;
} }
}; };
fetchVideos(); fetchVideos();
// 清理函数:组件卸载时取消请求
return () => {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
};
}, [sourceType, embyKey, page, selectedView, runtimeConfig]); }, [sourceType, embyKey, page, selectedView, runtimeConfig]);
const handleVideoClick = (video: Video) => { const handleVideoClick = (video: Video) => {
@@ -380,33 +404,22 @@ export default function PrivateLibraryPage() {
{/* 第一级:源类型选择(OpenList / Emby */} {/* 第一级:源类型选择(OpenList / Emby */}
<div className='mb-6 flex justify-center'> <div className='mb-6 flex justify-center'>
<div className='inline-flex gap-2 bg-gray-100 dark:bg-gray-800 rounded-lg p-1'> <CapsuleSwitch
<button options={[
onClick={() => setSourceType('openlist')} { label: 'OpenList', value: 'openlist' },
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${ { label: 'Emby', value: 'emby' },
sourceType === 'openlist' ]}
? 'bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow' active={sourceType}
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white' onChange={(value) => setSourceType(value as LibrarySourceType)}
}`} />
>
OpenList
</button>
<button
onClick={() => setSourceType('emby')}
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
sourceType === 'emby'
? 'bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white'
}`}
>
Emby
</button>
</div>
</div> </div>
{/* 第二级:Emby源选择(仅当选择Emby且有多个源时显示) */} {/* 第二级:Emby源选择(仅当选择Emby且有多个源时显示) */}
{sourceType === 'emby' && embySourceOptions.length > 1 && ( {sourceType === 'emby' && embySourceOptions.length > 1 && (
<div className='mb-6'> <div className='mb-6'>
<div className='text-xs text-gray-500 dark:text-gray-400 mb-2 px-4'>
</div>
<div className='relative'> <div className='relative'>
<div <div
ref={embyScrollContainerRef} ref={embyScrollContainerRef}
@@ -462,6 +475,9 @@ export default function PrivateLibraryPage() {
{/* 第三级:Emby 媒体库分类选择器 */} {/* 第三级:Emby 媒体库分类选择器 */}
{sourceType === 'emby' && ( {sourceType === 'emby' && (
<div className='mb-6'> <div className='mb-6'>
<div className='text-xs text-gray-500 dark:text-gray-400 mb-2 px-4'>
</div>
{loadingViews ? ( {loadingViews ? (
<div className='flex justify-center'> <div className='flex justify-center'>
<div className='w-5 h-5 border-2 border-blue-600 border-t-transparent rounded-full animate-spin' /> <div className='w-5 h-5 border-2 border-blue-600 border-t-transparent rounded-full animate-spin' />