添加跳过片头片尾功能,更新相关组件和文档,支持用户自定义设置

This commit is contained in:
katelya
2025-09-02 14:18:44 +08:00
parent 5bbea4f3d5
commit a6bcb72987
5 changed files with 375 additions and 32 deletions
+13 -3
View File
@@ -23,7 +23,7 @@ import { getVideoResolutionFromM3u8, processImageUrl } from '@/lib/utils';
import EpisodeSelector from '@/components/EpisodeSelector';
import PageLayout from '@/components/PageLayout';
import SkipController from '@/components/SkipController';
import SkipController, { SkipSettingsButton } from '@/components/SkipController';
// 扩展 HTMLVideoElement 类型以支持 hls 属性
declare global {
@@ -168,6 +168,9 @@ function PlayPageClient() {
const [currentPlayTime, setCurrentPlayTime] = useState<number>(0);
const [videoDuration, setVideoDuration] = useState<number>(0);
// 跳过设置状态
const [isSkipSettingMode, setIsSkipSettingMode] = useState<boolean>(false);
const artPlayerRef = useRef<any>(null);
const artRef = useRef<HTMLDivElement | null>(null);
@@ -1478,8 +1481,8 @@ function PlayPageClient() {
return (
<PageLayout activePath='/play'>
<div className='flex flex-col gap-3 py-4 px-5 lg:px-[3rem] 2xl:px-20'>
{/* 第一行:影片标题 */}
<div className='py-1'>
{/* 第一行:影片标题和操作按钮 */}
<div className='py-1 flex items-center justify-between'>
<h1 className='text-xl font-semibold text-gray-900 dark:text-gray-100'>
{videoTitle || '影片标题'}
{totalEpisodes > 1 && (
@@ -1488,6 +1491,11 @@ function PlayPageClient() {
</span>
)}
</h1>
{/* 跳过设置按钮 */}
{currentSource && currentId && (
<SkipSettingsButton onClick={() => setIsSkipSettingMode(true)} />
)}
</div>
{/* 第二行:播放器和选集 */}
<div className='space-y-2'>
@@ -1560,6 +1568,8 @@ function PlayPageClient() {
artPlayerRef={artPlayerRef}
currentTime={currentPlayTime}
_duration={videoDuration}
isSettingMode={isSkipSettingMode}
onSettingModeChange={setIsSkipSettingMode}
/>
)}
+7 -4
View File
@@ -18,6 +18,8 @@ interface SkipControllerProps {
artPlayerRef: React.MutableRefObject<any>;
currentTime?: number;
_duration?: number; // 使用下划线前缀标识未使用的参数
isSettingMode?: boolean;
onSettingModeChange?: (isOpen: boolean) => void;
}
export default function SkipController({
@@ -27,11 +29,12 @@ export default function SkipController({
artPlayerRef,
currentTime = 0,
_duration = 0,
isSettingMode = false,
onSettingModeChange,
}: SkipControllerProps) {
const [skipConfig, setSkipConfig] = useState<EpisodeSkipConfig | null>(null);
const [showSkipButton, setShowSkipButton] = useState(false);
const [currentSkipSegment, setCurrentSkipSegment] = useState<SkipSegment | null>(null);
const [isSettingMode, setIsSettingMode] = useState(false);
const [newSegment, setNewSegment] = useState<Partial<SkipSegment>>({});
const lastSkipTimeRef = useRef<number>(0);
@@ -131,7 +134,7 @@ export default function SkipController({
await saveSkipConfig(source, id, updatedConfig);
setSkipConfig(updatedConfig);
setIsSettingMode(false);
onSettingModeChange?.(false);
setNewSegment({});
alert('跳过片段已保存');
@@ -139,7 +142,7 @@ export default function SkipController({
console.error('保存跳过片段失败:', err);
alert('保存失败,请重试');
}
}, [newSegment, skipConfig, source, id, title]);
}, [newSegment, skipConfig, source, id, title, onSettingModeChange]);
// 删除跳过片段
const handleDeleteSegment = useCallback(
@@ -297,7 +300,7 @@ export default function SkipController({
</button>
<button
onClick={() => {
setIsSettingMode(false);
onSettingModeChange?.(false);
setNewSegment({});
}}
className="flex-1 px-4 py-2 bg-gray-500 hover:bg-gray-600 text-white rounded font-medium transition-colors"