diff --git a/apps/web/src/pages/products/components/VideoPlayer.tsx b/apps/web/src/pages/products/components/VideoPlayer.tsx index 5e5ac79d3..db8a3b503 100644 --- a/apps/web/src/pages/products/components/VideoPlayer.tsx +++ b/apps/web/src/pages/products/components/VideoPlayer.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useState, useEffect, useCallback } from "react" +import React, { useEffect } from "react" import { VideoCameraOutlined, PlayCircleOutlined, @@ -11,6 +11,7 @@ import { import { Button } from "@/components/ui" import type { ProductItem } from "../types" import { formatTime, formatSize } from "../utils" +import { useVideoPlayer } from "../hooks/useVideoPlayer" interface VideoPlayerProps { product: ProductItem @@ -27,52 +28,19 @@ export const VideoPlayer: React.FC = ({ onShare, onViewDetail, }) => { - const videoRef = useRef(null) - const progressRef = useRef(null) - const [isPlaying, setIsPlaying] = useState(false) - const [currentTime, setCurrentTime] = useState(0) - const [duration, setDuration] = useState(product.duration) + const { + videoRef, + progressRef, + isPlaying, + currentTime, + duration, + progress, + togglePlay, + handleSeek, + } = useVideoPlayer() const hasVideo = !!product.videoUrl - - /** 播放/暂停 */ - const handlePlayPause = useCallback(() => { - const video = videoRef.current - if (!video) return - if (isPlaying) { - video.pause() - } else { - video.play().catch(() => {}) - } - setIsPlaying(!isPlaying) - }, [isPlaying]) - - /** 视频事件监听 */ - useEffect(() => { - const video = videoRef.current - if (!video) return - const onTime = () => setCurrentTime(video.currentTime) - const onDur = () => setDuration(video.duration || product.duration) - const onEnd = () => setIsPlaying(false) - video.addEventListener("timeupdate", onTime) - video.addEventListener("loadedmetadata", onDur) - video.addEventListener("ended", onEnd) - return () => { - video.removeEventListener("timeupdate", onTime) - video.removeEventListener("loadedmetadata", onDur) - video.removeEventListener("ended", onEnd) - } - }, [product.duration]) - - /** 进度条点击 */ - const handleProgressClick = (e: React.MouseEvent) => { - if (!progressRef.current) return - const rect = progressRef.current.getBoundingClientRect() - const percent = (e.clientX - rect.left) / rect.width - const newTime = percent * duration - setCurrentTime(newTime) - if (videoRef.current) videoRef.current.currentTime = newTime - } + const displayDuration = duration || product.duration /** ESC 关闭 */ useEffect(() => { @@ -83,8 +51,6 @@ export const VideoPlayer: React.FC = ({ return () => window.removeEventListener("keydown", handleKey) }, [onClose]) - const progress = duration > 0 ? (currentTime / duration) * 100 : 0 - return (
e.stopPropagation()}> @@ -114,7 +80,7 @@ export const VideoPlayer: React.FC = ({ )} {/* 播放/暂停按钮 */} - @@ -125,12 +91,12 @@ export const VideoPlayer: React.FC = ({ {/* 进度条 */}
-
+
{formatTime(currentTime)} - {formatTime(duration)} + {formatTime(displayDuration)}
diff --git a/apps/web/src/test/pages/products/smoke.test.tsx b/apps/web/src/test/pages/products/smoke.test.tsx index fbe1b7dbc..3c2f117eb 100644 --- a/apps/web/src/test/pages/products/smoke.test.tsx +++ b/apps/web/src/test/pages/products/smoke.test.tsx @@ -22,6 +22,7 @@ import "@/pages/products/components/VideoPlayer" // Hooks import "@/pages/products/hooks/useProductList" import "@/pages/products/hooks/useProductActions" +import "@/pages/products/hooks/useVideoPlayer" describe("ProductLibrary module smoke test", () => { it("should load all product modules", () => {