/* Copyright (C) 2025 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import React, { useState, useRef, useEffect } from 'react'; import { Modal, Typography, Tag, Button } from '@douyinfe/semi-ui'; import { IconExternalOpen, IconCopy } from '@douyinfe/semi-icons'; import { useTranslation } from 'react-i18next'; const { Text, Title } = Typography; const formatDuration = (seconds) => { if (!seconds || seconds <= 0) return '--:--'; const m = Math.floor(seconds / 60); const s = Math.floor(seconds % 60); return `${m}:${s.toString().padStart(2, '0')}`; }; const AudioClipCard = ({ clip }) => { const { t } = useTranslation(); const [hasError, setHasError] = useState(false); const audioRef = useRef(null); useEffect(() => { setHasError(false); }, [clip.audio_url]); const title = clip.title || t('未命名'); const tags = clip.tags || clip.metadata?.tags || ''; const duration = clip.duration || clip.metadata?.duration; const imageUrl = clip.image_url || clip.image_large_url; const audioUrl = clip.audio_url; return (
{imageUrl && ( {title} { e.target.style.display = 'none'; }} /> )}
{title} {duration > 0 && ( {formatDuration(duration)} )}
{tags && (
{tags}
)} {hasError ? (
{t('音频无法播放')}
) : (
); }; const AudioPreviewModal = ({ isModalOpen, setIsModalOpen, audioClips }) => { const { t } = useTranslation(); const clips = Array.isArray(audioClips) ? audioClips : []; return ( setIsModalOpen(false)} onCancel={() => setIsModalOpen(false)} closable={null} footer={null} bodyStyle={{ maxHeight: '70vh', overflow: 'auto', padding: '16px', }} width={560} > {clips.length === 0 ? ( {t('无')} ) : (
{clips.map((clip, idx) => ( ))}
)}
); }; export default AudioPreviewModal;