fix: useRowProgress 除零保护 + 组件卸载清理 + 补充smoke测试引用
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 15s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m14s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m0s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 18s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 45s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m30s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 58s
AI Code Review / AI Code Review (pull_request) Successful in 3m12s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 42s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m33s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 35s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m33s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 7m12s
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 1176h46m53s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 1176h46m54s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 1176h46m55s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 1176h46m55s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 1176h46m54s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 1176h46m56s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 1176h50m39s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 1176h50m41s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 1176h51m7s
CI/CD Pipeline / PR Build API Image (pull_request) Failing after 1176h51m24s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 1176h51m54s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 1176h53m52s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 1176h53m54s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 1177h19m55s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 1177h23m40s
CI/CD Pipeline / PR Build Worker Image (pull_request) Failing after 1177h24m9s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 1177h26m50s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 15s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m14s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m0s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 18s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 45s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m30s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 58s
AI Code Review / AI Code Review (pull_request) Successful in 3m12s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 42s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m33s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 35s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m33s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 7m12s
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 1176h46m53s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 1176h46m54s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 1176h46m55s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 1176h46m55s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 1176h46m54s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 1176h46m56s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 1176h50m39s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 1176h50m41s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 1176h51m7s
CI/CD Pipeline / PR Build API Image (pull_request) Failing after 1176h51m24s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 1176h51m54s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 1176h53m52s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 1176h53m54s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 1177h19m55s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 1177h23m40s
CI/CD Pipeline / PR Build Worker Image (pull_request) Failing after 1177h24m9s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 1177h26m50s
This commit is contained in:
@@ -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<HTMLDivElement>(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<HTMLDivElement>) => {
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user