fix(style): playground image incomplete

This commit is contained in:
jialin
2024-11-28 17:13:51 +08:00
parent af789ee886
commit bd418b23dc
23 changed files with 704 additions and 255 deletions
+6
View File
@@ -49,5 +49,11 @@
.speaker {
margin-left: 10px;
position: relative;
.volume-slider {
position: absolute;
bottom: 30px;
}
}
}
+57 -5
View File
@@ -1,12 +1,14 @@
import { formatTime } from '@/utils/index';
import { PauseCircleFilled, PlayCircleFilled } from '@ant-design/icons';
import { Button, Slider } from 'antd';
import { Button, Slider, Tooltip } from 'antd';
import { round } from 'lodash';
import React, {
forwardRef,
useCallback,
useEffect,
useImperativeHandle
} from 'react';
import CheckButtons from '../check-buttons';
import IconFont from '../icon-font';
import './index.less';
@@ -21,6 +23,13 @@ interface AudioPlayerProps {
duration?: number;
}
const speedOptions = [
{ label: '1x', value: 1 },
{ label: '2x', value: 2 },
{ label: '3x', value: 3 },
{ label: '4x', value: 4 }
];
const AudioPlayer: React.FC<AudioPlayerProps> = forwardRef((props, ref) => {
const { autoplay = false, speed: defaultSpeed = 1 } = props;
const audioRef = React.useRef<HTMLAudioElement>(null);
@@ -45,6 +54,14 @@ const AudioPlayer: React.FC<AudioPlayerProps> = forwardRef((props, ref) => {
audioRef.current?.pause();
}
}));
const handleShowVolume = useCallback(() => {
setSpeakerOn(!speakerOn);
}, [speakerOn]);
const handleSeepdChange = useCallback((value: number | string) => {
setSpeed(value as number);
audioRef.current!.playbackRate = value as number;
}, []);
const handleAudioOnPlay = useCallback(() => {
timer.current = setInterval(() => {
@@ -78,16 +95,22 @@ const AudioPlayer: React.FC<AudioPlayerProps> = forwardRef((props, ref) => {
setPlayOn(!playOn);
}, [playOn]);
const handleFormatVolume = (val: number) => {
return `${round(val * 100)}%`;
};
const handleVolumeChange = useCallback((value: number) => {
audioRef.current!.volume = round(value, 2);
setVolume(round(value, 2));
}, []);
const initPlayerConfig = useCallback(() => {
// set volume
audioRef.current!.volume = volume;
// set playback rate
audioRef.current!.playbackRate = speed;
}, []);
const handleLoadedMetadata = useCallback(
(data: any) => {
console.log('loadmetadata++++++++');
const duration = Math.ceil(audioRef.current?.duration || 0);
setAudioState({
currentTime: 0,
@@ -158,7 +181,23 @@ const AudioPlayer: React.FC<AudioPlayerProps> = forwardRef((props, ref) => {
onChange={handleCurrentChange}
/>
</div>
<span>{props.speed ? `${props.speed}x` : '1x'}</span>
<Tooltip
overlayInnerStyle={{
backgroundColor: 'var(--color-white-1)'
}}
arrow={false}
title={
<CheckButtons
options={speedOptions}
onChange={handleSeepdChange}
size="small"
></CheckButtons>
}
>
<span style={{ cursor: 'pointer' }}>
{speed ? `${speed}x` : '1x'}
</span>
</Tooltip>
</div>
<span className="time">{formatTime(audioState.duration)}</span>
</div>
@@ -173,6 +212,19 @@ const AudioPlayer: React.FC<AudioPlayerProps> = forwardRef((props, ref) => {
></IconFont>
}
></Button>
{speakerOn && (
<Slider
tooltip={{ formatter: handleFormatVolume }}
style={{ height: '100px' }}
className="volume-slider"
min={0}
max={1}
step={0.01}
value={volume}
vertical
onChange={handleVolumeChange}
/>
)}
</span>
</div>
<audio
+43
View File
@@ -0,0 +1,43 @@
import { Button } from 'antd';
import React from 'react';
interface CheckButtonsProps {
options: Global.BaseOption<string | number>[];
onChange: (value: string | number) => void;
cancelable?: boolean;
size?: 'small' | 'middle' | 'large';
type?: 'text' | 'primary' | 'default' | 'dashed' | 'link' | undefined;
}
const CheckButtons: React.FC<CheckButtonsProps> = (props) => {
const [type, setType] = React.useState(props.type || 'text');
const [active, setActive] = React.useState<string | number | null>(null);
const handleChange = (value: string | number) => {
props.onChange(value);
if (props.cancelable && active === value) {
setActive(null);
} else {
setActive(value);
}
};
return (
<div className="flex-center gap-6">
{props.options?.map?.((option, index) => {
return (
<Button
size={props.size}
key={option.value}
onClick={() => handleChange(option.value)}
variant="filled"
color={active === option.value ? 'default' : undefined}
type={type}
>
{option.label}
</Button>
);
})}
</div>
);
};
export default React.memo(CheckButtons);
-1
View File
@@ -7,7 +7,6 @@ interface SpeechContentProps {
}
const SpeechContent: React.FC<SpeechContentProps> = (props) => {
console.log('SpeechContent', props);
return (
<>
{props.dataList.map((item) => (
+42 -21
View File
@@ -1,11 +1,29 @@
import IconFont from '@/components/icon-font';
import { DownloadOutlined, PlayCircleOutlined } from '@ant-design/icons';
import {
DownloadOutlined,
PauseCircleOutlined,
PlayCircleOutlined
} from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Tooltip } from 'antd';
import dayjs from 'dayjs';
import React, { useRef, useState } from 'react';
import AudioPlayer from './audio-player';
import './styles/index.less';
// const audioUrl = require('./ih.mp4');
const audioFormat = {
'audio/mpeg': 'mp3',
'audio/wav': 'wav',
'audio/ogg': 'ogg',
'audio/webm': 'webm',
'audio/aac': 'aac',
'audio/x-flac': 'flac',
'audio/pcm': 'pcm',
'audio/flac': 'flac',
'audio/x-wav': 'wav',
'audio/L16': 'pcm',
'audio/opus': 'opus'
};
interface SpeechContentProps {
prompt: string;
@@ -16,12 +34,19 @@ interface SpeechContentProps {
audioUrl: string;
}
const SpeechItem: React.FC<SpeechContentProps> = (props) => {
console.log('porps=======', props);
const intl = useIntl();
const [collapsed, setCollapsed] = useState(false);
const [isPlay, setIsPlay] = useState(false);
const ref = useRef<HTMLAudioElement>(null);
const handlePlay = () => {
if (isPlay) {
ref.current?.pause();
setIsPlay(false);
return;
}
ref.current?.play();
setIsPlay(true);
};
const handleCollapse = () => {
@@ -30,7 +55,7 @@ const SpeechItem: React.FC<SpeechContentProps> = (props) => {
const onDownload = () => {
const url = props.audioUrl || '';
const filename = Date.now() + '';
const filename = `audio-${dayjs().format('YYYYMMDDHHmmss')}.${props.format}`;
const link = document.createElement('a');
link.href = url;
@@ -45,7 +70,6 @@ const SpeechItem: React.FC<SpeechContentProps> = (props) => {
<div className="speech-item">
<div className="voice">
<IconFont type="icon-user_voice" className="font-size-16" />
{/* <span className="text">{props.voice}</span> */}
</div>
<div className="wrapper">
<AudioPlayer
@@ -62,15 +86,25 @@ const SpeechItem: React.FC<SpeechContentProps> = (props) => {
<span className="item">{props.speed}x</span>
</span>
<div className="actions">
<Tooltip title="Play">
<Tooltip
title={
isPlay
? intl.formatMessage({ id: 'playground.audio.button.stop' })
: intl.formatMessage({ id: 'playground.audio.button.play' })
}
>
<Button
onClick={handlePlay}
icon={<PlayCircleOutlined />}
icon={isPlay ? <PauseCircleOutlined /> : <PlayCircleOutlined />}
type="text"
size="small"
></Button>
</Tooltip>
<Tooltip title="Download">
<Tooltip
title={intl.formatMessage({
id: 'playground.audio.button.download'
})}
>
<Button
onClick={onDownload}
icon={<DownloadOutlined />}
@@ -78,21 +112,8 @@ const SpeechItem: React.FC<SpeechContentProps> = (props) => {
size="small"
></Button>
</Tooltip>
{/* <Tooltip title="Show Prompt">
<Button
icon={<FileTextOutlined />}
type="text"
size="small"
onClick={handleCollapse}
></Button>
</Tooltip> */}
</div>
</div>
{/* {collapsed && (
<div className="prompt-box">
<div className="prompt">{props.prompt}</div>
</div>
)} */}
</div>
);
};
+1 -2
View File
@@ -13,12 +13,11 @@ interface UploadAudioProps {
const UploadAudio: React.FC<UploadAudioProps> = (props) => {
const intl = useIntl();
const beforeUpload = (file: any) => {
return true;
return false;
};
const handleOnChange = React.useCallback(
(data: { file: any; fileList: any }) => {
console.log('handleOnChange', data);
props.onChange?.(data);
},
[]