132 lines
4.2 KiB
TypeScript
132 lines
4.2 KiB
TypeScript
import { useEffect, useRef, useState } from "react";
|
||
import { Avatar, Divider, Space, SpinLoading, Toast } from "antd-mobile";
|
||
import { VoiceIcon } from "@workspace/shared";
|
||
import { Message } from "../../../types";
|
||
import "./index.less";
|
||
import { Refresh } from "@icon-park/react";
|
||
|
||
interface DefinedProps {
|
||
data: Message[];
|
||
isRecording: boolean;
|
||
onRefresh: (formData: FormData, messageId: number) => void;
|
||
}
|
||
|
||
function Index(props: DefinedProps) {
|
||
const { data, isRecording } = props;
|
||
const audioRefs = useRef<{ [key: string]: HTMLAudioElement }>({});
|
||
const [isPlaying, setIsPlating] = useState(false);
|
||
const [currentPlayingId, setCurrentPlayingId] = useState<number>();
|
||
|
||
useEffect(() => {
|
||
if (isRecording && currentPlayingId) {
|
||
audioRefs.current[currentPlayingId].pause();
|
||
audioRefs.current[currentPlayingId].currentTime = 0;
|
||
setCurrentPlayingId(undefined);
|
||
}
|
||
}, [isRecording, currentPlayingId]);
|
||
|
||
const playAudio = (id: number, audioUrl: string) => {
|
||
if (isRecording) {
|
||
Toast.show("录音中,无法播放音频");
|
||
return;
|
||
}
|
||
if (currentPlayingId && audioRefs.current[currentPlayingId]) {
|
||
audioRefs.current[currentPlayingId].pause();
|
||
audioRefs.current[currentPlayingId].currentTime = 0;
|
||
}
|
||
if (currentPlayingId !== id) {
|
||
setCurrentPlayingId(id);
|
||
audioRefs.current[id] = new Audio(audioUrl);
|
||
audioRefs.current[id].play();
|
||
audioRefs.current[id].onended = () => {
|
||
setCurrentPlayingId(undefined);
|
||
};
|
||
} else {
|
||
audioRefs.current[id].pause();
|
||
audioRefs.current[id].currentTime = 0;
|
||
setCurrentPlayingId(undefined);
|
||
}
|
||
};
|
||
|
||
const renderAvatar = (item: Message) => {
|
||
return <Avatar src={item.petAvatar || ""} style={{ "--border-radius": "32px" }} />;
|
||
};
|
||
|
||
const refreshMessage = async (messageId: number, e: React.MouseEvent) => {
|
||
e.stopPropagation();
|
||
const formData = new FormData();
|
||
formData.append("msgId", messageId.toString());
|
||
props.onRefresh(formData, messageId);
|
||
};
|
||
|
||
const renderTranslateResult = (item: Message) => {
|
||
if (item.isTranslating) {
|
||
return (
|
||
<div className="translate">
|
||
<SpinLoading color="default" style={{ "--size": "12px" }} />
|
||
<span>翻译中...</span>
|
||
</div>
|
||
);
|
||
} else {
|
||
if (item.transStatus === 1) {
|
||
return item.transResult?.length ? (
|
||
<Space justify={"between"} className="translate" style={{ verticalAlign: "middle" }}>
|
||
<span>{item.transResult}</span>
|
||
</Space>
|
||
) : (
|
||
<Space justify={"between"} className="translate" style={{ verticalAlign: "middle" }}>
|
||
<span>未知语句</span>
|
||
<Refresh onClick={(e) => refreshMessage(item.id, e)} size="12" fill="#333" />
|
||
</Space>
|
||
);
|
||
} else {
|
||
return (
|
||
<Space
|
||
justify={"between"}
|
||
className="translate"
|
||
style={{ verticalAlign: "middle" }}
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
}}
|
||
>
|
||
<span>翻译失败,请重试</span>
|
||
<Refresh onClick={(e) => refreshMessage(item.id, e)} size="12" fill="#333" />
|
||
</Space>
|
||
);
|
||
}
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className="message">
|
||
{data.map((item, index) => (
|
||
<div className="item" key={index}>
|
||
{renderAvatar(item)}
|
||
|
||
<div className="rig">
|
||
<div>
|
||
<span className="name">
|
||
{item.isTranslating && !item.isRefresh ? "" : item.petName ?? "未知宠物"}
|
||
</span>
|
||
<Divider direction="vertical" style={{ margin: "0px 8px" }} />
|
||
<span className="">{item.createTime}</span>
|
||
</div>
|
||
<div className="voice-container" onClick={() => playAudio(item.id, item.contentText)}>
|
||
<VoiceIcon
|
||
// onChange={onVoiceChange}
|
||
isPlaying={currentPlayingId === item.id}
|
||
/>
|
||
<div className="time">{item.contentDuration}''</div>
|
||
</div>
|
||
{renderTranslateResult(item)}
|
||
</div>
|
||
</div>
|
||
))}
|
||
|
||
<div style={{ height: "80px", width: "100%" }}></div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default Index;
|