diff --git a/apps/web/src/pages/voice-materials/components/VoiceMaterialRow.tsx b/apps/web/src/pages/voice-materials/components/VoiceMaterialRow.tsx old mode 100644 new mode 100755 index 54b6528f2..536bc56b7 --- a/apps/web/src/pages/voice-materials/components/VoiceMaterialRow.tsx +++ b/apps/web/src/pages/voice-materials/components/VoiceMaterialRow.tsx @@ -1,4 +1,4 @@ -import React, { useRef } from "react" +import React from "react" import { PlayCircleOutlined, PauseCircleOutlined, @@ -6,11 +6,8 @@ import { DeleteOutlined, CheckOutlined, } from "@ant-design/icons" -import { Tooltip } from "antd" -import { Tag } from "@/components/ui" import { type TagItem } from "@/api/tags" import { type VoiceMaterial } from "../types" -import { MAX_ROW_TAGS, TAG_VARIANTS } from "../constants" import { genderClass, genderIcon, @@ -18,6 +15,8 @@ import { formatDuration, formatFileSize, } from "../utils/format" +import { useRowProgress } from "./voice-material-row/useRowProgress" +import TagDisplay from "./voice-material-row/TagDisplay" export interface VoiceRowProps { material: VoiceMaterial @@ -48,26 +47,10 @@ const VoiceMaterialRow: React.FC = ({ onDelete, onToggleSelect, }) => { - const progressRef = useRef(null) - - const handleProgressMouseDown = (e: React.MouseEvent) => { - if (!progressRef.current) return - e.preventDefault() - const doSeek = (ev: MouseEvent) => { - if (!progressRef.current) return - const rect = progressRef.current.getBoundingClientRect() - const percent = Math.max(0, Math.min(1, (ev.clientX - rect.left) / rect.width)) - onSeek(percent * material.duration) - } - doSeek(e.nativeEvent) - const handleMove = (ev: MouseEvent) => doSeek(ev) - const handleUp = () => { - document.removeEventListener("mousemove", handleMove) - document.removeEventListener("mouseup", handleUp) - } - document.addEventListener("mousemove", handleMove) - document.addEventListener("mouseup", handleUp) - } + const { progressRef, handleMouseDown } = useRowProgress({ + duration: material.duration, + onSeek, + }) const progress = material.duration > 0 ? (currentTime / material.duration) * 100 : 0 @@ -75,7 +58,6 @@ const VoiceMaterialRow: React.FC = ({
- {/* 批量选择 checkbox */} {(batchMode || isSelected) && (
= ({
)} - {/* 播放按钮 */} - {/* 名称 + 描述 */}

{material.name}

{material.description &&

{material.description}

}
- {/* 性别 */} {genderIcon(material.gender)} {genderLabel(material.gender)} - {/* 标签 */}
- {material.tagIds.length === 0 ? ( - onEdit()}> - 添加标签 - - ) : ( - <> - {material.tagIds.slice(0, MAX_ROW_TAGS).map((tagId, i) => ( - - {tagMap.get(tagId)?.name ?? tagId} - - ))} - {material.tagIds.length > MAX_ROW_TAGS && ( - tagMap.get(id)?.name ?? id) - .join("、")} - > - +{material.tagIds.length - MAX_ROW_TAGS} - - )} - - )} + onEdit()} />
- {/* 进度条(可拖拽) */} -
+
{isPlaying &&
}
- {/* 时长 */} {isPlaying ? formatDuration(currentTime) : formatDuration(material.duration)} - {/* 文件大小 */} {formatFileSize(material.fileSize)} - {/* 操作 */}