From 2054e3122f56ed05e0dc5c6b92fc6cea1b0cf28b Mon Sep 17 00:00:00 2001 From: mtvpls Date: Sat, 3 Jan 2026 14:54:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E7=A9=BA=E5=A2=9E=E5=8A=A0=E7=A1=AE?= =?UTF-8?q?=E8=AE=A4=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ContinueWatching.tsx | 90 +++++++++++++++++++++++------ src/components/FavoritesPanel.tsx | 54 ++++++++++++++++- src/lib/admin.types.ts | 1 + src/lib/types.ts | 1 + 4 files changed, 127 insertions(+), 19 deletions(-) diff --git a/src/components/ContinueWatching.tsx b/src/components/ContinueWatching.tsx index e451d80..ddb01cd 100644 --- a/src/components/ContinueWatching.tsx +++ b/src/components/ContinueWatching.tsx @@ -2,6 +2,8 @@ 'use client'; import { useEffect, useState } from 'react'; +import { createPortal } from 'react-dom'; +import { AlertTriangle } from 'lucide-react'; import type { PlayRecord } from '@/lib/db.client'; import { @@ -22,6 +24,7 @@ export default function ContinueWatching({ className }: ContinueWatchingProps) { (PlayRecord & { key: string })[] >([]); const [loading, setLoading] = useState(true); + const [showConfirmDialog, setShowConfirmDialog] = useState(false); // 处理播放记录数据更新的函数 const updatePlayRecords = (allRecords: Record) => { @@ -85,24 +88,29 @@ export default function ContinueWatching({ className }: ContinueWatchingProps) { return { source, id }; }; + // 处理清空确认 + const handleClearConfirm = async () => { + await clearAllPlayRecords(); + setPlayRecords([]); + setShowConfirmDialog(false); + }; + return ( -
-
-

- 继续观看 -

- {!loading && playRecords.length > 0 && ( - - )} -
+ <> +
+
+

+ 继续观看 +

+ {!loading && playRecords.length > 0 && ( + + )} +
{loading ? ( // 加载状态显示灰色占位数据(使用原始 ScrollableRow)
@@ -158,5 +166,53 @@ export default function ContinueWatching({ className }: ContinueWatchingProps) { )}
+ + {/* 确认对话框 */} + {showConfirmDialog && createPortal( +
setShowConfirmDialog(false)} + > +
e.stopPropagation()} + > +
+ {/* 图标和标题 */} +
+
+ +
+
+

+ 清空播放记录 +

+

+ 确定要清空所有播放记录吗?此操作不可恢复。 +

+
+
+ + {/* 按钮组 */} +
+ + +
+
+
+
, + document.body + )} + ); } diff --git a/src/components/FavoritesPanel.tsx b/src/components/FavoritesPanel.tsx index 318fda8..7276523 100644 --- a/src/components/FavoritesPanel.tsx +++ b/src/components/FavoritesPanel.tsx @@ -2,8 +2,9 @@ 'use client'; -import { Star, X } from 'lucide-react'; +import { Star, X, AlertTriangle } from 'lucide-react'; import { useEffect, useState } from 'react'; +import { createPortal } from 'react-dom'; import { clearAllFavorites, @@ -37,6 +38,7 @@ export const FavoritesPanel: React.FC = ({ }) => { const [favoriteItems, setFavoriteItems] = useState([]); const [loading, setLoading] = useState(false); + const [showConfirmDialog, setShowConfirmDialog] = useState(false); // 加载收藏数据 const loadFavorites = async () => { @@ -83,6 +85,7 @@ export const FavoritesPanel: React.FC = ({ try { await clearAllFavorites(); setFavoriteItems([]); + setShowConfirmDialog(false); } catch (error) { console.error('清空收藏失败:', error); } @@ -143,7 +146,7 @@ export const FavoritesPanel: React.FC = ({
{favoriteItems.length > 0 && (
+ + {/* 确认对话框 */} + {showConfirmDialog && createPortal( +
setShowConfirmDialog(false)} + > +
e.stopPropagation()} + > +
+ {/* 图标和标题 */} +
+
+ +
+
+

+ 清空收藏 +

+

+ 确定要清空所有收藏吗?此操作不可恢复。 +

+
+
+ + {/* 按钮组 */} +
+ + +
+
+
+
, + document.body + )} ); }; diff --git a/src/lib/admin.types.ts b/src/lib/admin.types.ts index dbf9903..e29a17e 100644 --- a/src/lib/admin.types.ts +++ b/src/lib/admin.types.ts @@ -162,6 +162,7 @@ export interface AdminConfig { Username?: string; // 用户名(或使用API Key) Password?: string; // 密码 UserId?: string; // 用户ID(登录后获取) + AuthToken?: string; // 认证令牌(用户名密码登录后获取) Libraries?: string[]; // 要显示的媒体库ID(可选,默认全部) LastSyncTime?: number; // 最后同步时间戳 ItemCount?: number; // 媒体项数量 diff --git a/src/lib/types.ts b/src/lib/types.ts index 175a217..19a4508 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -136,6 +136,7 @@ export interface SearchResult { vod_remarks?: string; // 视频备注信息(如"全80集"、"更新至25集"等) vod_total?: number; // 总集数 proxyMode?: boolean; // 代理模式:启用后由服务器代理m3u8和ts分片 + subtitles?: Array>; // 字幕列表(按集数索引) } // 豆瓣数据结构