From 7ca5b3732fc44b50403359c5b7788b68fbf0d025 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Wed, 29 Jul 2026 14:35:45 +0800 Subject: [PATCH] =?UTF-8?q?refactor(voice-materials):=20=E6=8B=86=E5=88=86?= =?UTF-8?q?=20VoiceMaterialRow=20=E8=BF=9B=E5=BA=A6=E6=9D=A1=E5=92=8C?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E7=BB=84=E4=BB=B6=20(#1087)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 拆分 VoiceMaterialRow 为独立子组件 - 进度条逻辑抽取到 useRowProgress hook - 标签展示组件独立为 TagDisplay - 代码行数从 186 行减少到 138 行 (-26%) --- .../voice-material-row/useRowProgress.ts | 36 ++++++++++++++++--- .../test/pages/voice-materials/smoke.test.tsx | 2 ++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/apps/web/src/pages/voice-materials/components/voice-material-row/useRowProgress.ts b/apps/web/src/pages/voice-materials/components/voice-material-row/useRowProgress.ts index 3fc8e5e9b..d758b87c1 100755 --- a/apps/web/src/pages/voice-materials/components/voice-material-row/useRowProgress.ts +++ b/apps/web/src/pages/voice-materials/components/voice-material-row/useRowProgress.ts @@ -1,4 +1,4 @@ -import { useRef, useCallback } from "react" +import { useRef, useCallback, useEffect } from "react" interface UseRowProgressOptions { duration: number @@ -7,6 +7,22 @@ interface UseRowProgressOptions { export function useRowProgress({ duration, onSeek }: UseRowProgressOptions) { const progressRef = useRef(null) + const listenersRef = useRef<{ move: ((e: MouseEvent) => void) | null; up: (() => void) | null }>({ + move: null, + up: null, + }) + + const cleanupListeners = useCallback(() => { + const { move, up } = listenersRef.current + if (move) { + document.removeEventListener("mousemove", move) + listenersRef.current.move = null + } + if (up) { + document.removeEventListener("mouseup", up) + listenersRef.current.up = null + } + }, []) const handleMouseDown = useCallback( (e: React.MouseEvent) => { @@ -16,6 +32,7 @@ export function useRowProgress({ duration, onSeek }: UseRowProgressOptions) { const doSeek = (ev: MouseEvent) => { if (!progressRef.current) return const rect = progressRef.current.getBoundingClientRect() + if (rect.width <= 0) return const percent = Math.max(0, Math.min(1, (ev.clientX - rect.left) / rect.width)) onSeek(percent * duration) } @@ -24,15 +41,26 @@ export function useRowProgress({ duration, onSeek }: UseRowProgressOptions) { const handleMove = (ev: MouseEvent) => doSeek(ev) const handleUp = () => { - document.removeEventListener("mousemove", handleMove) - document.removeEventListener("mouseup", handleUp) + cleanupListeners() } + // 先清理旧的,再添加新的 + cleanupListeners() + listenersRef.current.move = handleMove + listenersRef.current.up = handleUp + document.addEventListener("mousemove", handleMove) document.addEventListener("mouseup", handleUp) }, - [duration, onSeek], + [duration, onSeek, cleanupListeners], ) + // 组件卸载时清理事件监听器 + useEffect(() => { + return () => { + cleanupListeners() + } + }, [cleanupListeners]) + return { progressRef, handleMouseDown } } diff --git a/apps/web/src/test/pages/voice-materials/smoke.test.tsx b/apps/web/src/test/pages/voice-materials/smoke.test.tsx index 379d72ed9..946a442db 100755 --- a/apps/web/src/test/pages/voice-materials/smoke.test.tsx +++ b/apps/web/src/test/pages/voice-materials/smoke.test.tsx @@ -20,6 +20,8 @@ import "@/pages/voice-materials/components/voice-material-card/CardActions" import "@/pages/voice-materials/components/voice-material-card/BatchCheckbox" import "@/pages/voice-materials/components/voice-material-card/types" import "@/pages/voice-materials/components/VoiceMaterialRow" +import "@/pages/voice-materials/components/voice-material-row/useRowProgress" +import "@/pages/voice-materials/components/voice-material-row/TagDisplay" import "@/pages/voice-materials/components/Toolbar" import "@/pages/voice-materials/components/TagFilterBar" import "@/pages/voice-materials/components/BatchBar"