300 lines
7.8 KiB
TypeScript
300 lines
7.8 KiB
TypeScript
|
|
import { FC, useState } from 'react';
|
|||
|
|
|
|||
|
|
const CallScreen: FC = () => {
|
|||
|
|
const [callStatus, setCallStatus] = useState<'idle' | 'calling' | 'connected'>('idle');
|
|||
|
|
const [selectedLanguage, setSelectedLanguage] = useState('zh-en');
|
|||
|
|
|
|||
|
|
const handleStartCall = () => {
|
|||
|
|
setCallStatus('calling');
|
|||
|
|
// 模拟连接过程
|
|||
|
|
setTimeout(() => {
|
|||
|
|
setCallStatus('connected');
|
|||
|
|
}, 2000);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleEndCall = () => {
|
|||
|
|
setCallStatus('idle');
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const languageOptions = [
|
|||
|
|
{ value: 'zh-en', label: '中文 ⇄ 英文' },
|
|||
|
|
{ value: 'zh-es', label: '中文 ⇄ 西班牙文' },
|
|||
|
|
{ value: 'zh-fr', label: '中文 ⇄ 法文' },
|
|||
|
|
{ value: 'zh-ja', label: '中文 ⇄ 日文' },
|
|||
|
|
{ value: 'zh-ko', label: '中文 ⇄ 韩文' },
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div style={styles.container}>
|
|||
|
|
<div style={styles.content}>
|
|||
|
|
{/* 语言选择 */}
|
|||
|
|
<div style={styles.section}>
|
|||
|
|
<h3 style={styles.sectionTitle}>选择翻译语言</h3>
|
|||
|
|
<select
|
|||
|
|
value={selectedLanguage}
|
|||
|
|
onChange={(e) => setSelectedLanguage(e.target.value)}
|
|||
|
|
style={styles.languageSelect}
|
|||
|
|
>
|
|||
|
|
{languageOptions.map((option) => (
|
|||
|
|
<option key={option.value} value={option.value}>
|
|||
|
|
{option.label}
|
|||
|
|
</option>
|
|||
|
|
))}
|
|||
|
|
</select>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* 通话状态 */}
|
|||
|
|
<div style={styles.callContainer}>
|
|||
|
|
{callStatus === 'idle' && (
|
|||
|
|
<div style={styles.idleState}>
|
|||
|
|
<div style={styles.callIcon}>📞</div>
|
|||
|
|
<h2 style={styles.statusText}>准备开始通话</h2>
|
|||
|
|
<p style={styles.statusSubtext}>点击下方按钮开始翻译通话</p>
|
|||
|
|
<button style={styles.startButton} onClick={handleStartCall}>
|
|||
|
|
开始通话
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{callStatus === 'calling' && (
|
|||
|
|
<div style={styles.callingState}>
|
|||
|
|
<div style={styles.pulsingIcon}>📞</div>
|
|||
|
|
<h2 style={styles.statusText}>正在连接...</h2>
|
|||
|
|
<p style={styles.statusSubtext}>请稍候,正在为您连接译员</p>
|
|||
|
|
<div style={styles.loadingDots}>
|
|||
|
|
<span>●</span>
|
|||
|
|
<span>●</span>
|
|||
|
|
<span>●</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{callStatus === 'connected' && (
|
|||
|
|
<div style={styles.connectedState}>
|
|||
|
|
<div style={styles.connectedIcon}>✅</div>
|
|||
|
|
<h2 style={styles.statusText}>通话中</h2>
|
|||
|
|
<p style={styles.statusSubtext}>译员已连接,可以开始对话</p>
|
|||
|
|
|
|||
|
|
{/* 通话控制 */}
|
|||
|
|
<div style={styles.callControls}>
|
|||
|
|
<button style={styles.muteButton}>🔇</button>
|
|||
|
|
<button style={styles.endButton} onClick={handleEndCall}>
|
|||
|
|
结束通话
|
|||
|
|
</button>
|
|||
|
|
<button style={styles.speakerButton}>🔊</button>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* 通话信息 */}
|
|||
|
|
<div style={styles.callInfo}>
|
|||
|
|
<div style={styles.infoItem}>
|
|||
|
|
<span style={styles.infoLabel}>通话时长</span>
|
|||
|
|
<span style={styles.infoValue}>00:45</span>
|
|||
|
|
</div>
|
|||
|
|
<div style={styles.infoItem}>
|
|||
|
|
<span style={styles.infoLabel}>译员</span>
|
|||
|
|
<span style={styles.infoValue}>张译员</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* 快速操作 */}
|
|||
|
|
<div style={styles.section}>
|
|||
|
|
<h3 style={styles.sectionTitle}>快速操作</h3>
|
|||
|
|
<div style={styles.quickActions}>
|
|||
|
|
<button style={styles.actionButton}>
|
|||
|
|
<span style={styles.actionIcon}>📝</span>
|
|||
|
|
<span style={styles.actionLabel}>记录笔记</span>
|
|||
|
|
</button>
|
|||
|
|
<button style={styles.actionButton}>
|
|||
|
|
<span style={styles.actionIcon}>📧</span>
|
|||
|
|
<span style={styles.actionLabel}>发送邮件</span>
|
|||
|
|
</button>
|
|||
|
|
<button style={styles.actionButton}>
|
|||
|
|
<span style={styles.actionIcon}>📋</span>
|
|||
|
|
<span style={styles.actionLabel}>复制内容</span>
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const styles = {
|
|||
|
|
container: {
|
|||
|
|
display: 'flex',
|
|||
|
|
flexDirection: 'column' as const,
|
|||
|
|
height: '100%',
|
|||
|
|
backgroundColor: '#f5f5f5',
|
|||
|
|
},
|
|||
|
|
content: {
|
|||
|
|
flex: 1,
|
|||
|
|
padding: '16px',
|
|||
|
|
paddingBottom: '100px',
|
|||
|
|
},
|
|||
|
|
section: {
|
|||
|
|
marginBottom: '24px',
|
|||
|
|
},
|
|||
|
|
sectionTitle: {
|
|||
|
|
fontSize: '18px',
|
|||
|
|
fontWeight: 'bold',
|
|||
|
|
color: '#333',
|
|||
|
|
margin: '0 0 16px 0',
|
|||
|
|
},
|
|||
|
|
languageSelect: {
|
|||
|
|
width: '100%',
|
|||
|
|
padding: '12px',
|
|||
|
|
fontSize: '16px',
|
|||
|
|
border: '1px solid #d9d9d9',
|
|||
|
|
borderRadius: '8px',
|
|||
|
|
backgroundColor: '#fff',
|
|||
|
|
},
|
|||
|
|
callContainer: {
|
|||
|
|
display: 'flex',
|
|||
|
|
flexDirection: 'column' as const,
|
|||
|
|
alignItems: 'center',
|
|||
|
|
justifyContent: 'center',
|
|||
|
|
minHeight: '300px',
|
|||
|
|
backgroundColor: '#fff',
|
|||
|
|
borderRadius: '16px',
|
|||
|
|
padding: '32px',
|
|||
|
|
marginBottom: '24px',
|
|||
|
|
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)',
|
|||
|
|
},
|
|||
|
|
idleState: {
|
|||
|
|
textAlign: 'center' as const,
|
|||
|
|
},
|
|||
|
|
callingState: {
|
|||
|
|
textAlign: 'center' as const,
|
|||
|
|
},
|
|||
|
|
connectedState: {
|
|||
|
|
textAlign: 'center' as const,
|
|||
|
|
width: '100%',
|
|||
|
|
},
|
|||
|
|
callIcon: {
|
|||
|
|
fontSize: '64px',
|
|||
|
|
marginBottom: '16px',
|
|||
|
|
},
|
|||
|
|
pulsingIcon: {
|
|||
|
|
fontSize: '64px',
|
|||
|
|
marginBottom: '16px',
|
|||
|
|
animation: 'pulse 1.5s ease-in-out infinite alternate',
|
|||
|
|
},
|
|||
|
|
connectedIcon: {
|
|||
|
|
fontSize: '64px',
|
|||
|
|
marginBottom: '16px',
|
|||
|
|
},
|
|||
|
|
statusText: {
|
|||
|
|
fontSize: '24px',
|
|||
|
|
fontWeight: 'bold',
|
|||
|
|
color: '#333',
|
|||
|
|
margin: '0 0 8px 0',
|
|||
|
|
},
|
|||
|
|
statusSubtext: {
|
|||
|
|
fontSize: '16px',
|
|||
|
|
color: '#666',
|
|||
|
|
margin: '0 0 24px 0',
|
|||
|
|
},
|
|||
|
|
startButton: {
|
|||
|
|
backgroundColor: '#52c41a',
|
|||
|
|
color: '#fff',
|
|||
|
|
border: 'none',
|
|||
|
|
borderRadius: '50px',
|
|||
|
|
padding: '16px 32px',
|
|||
|
|
fontSize: '18px',
|
|||
|
|
fontWeight: 'bold',
|
|||
|
|
cursor: 'pointer',
|
|||
|
|
transition: 'background-color 0.3s ease',
|
|||
|
|
},
|
|||
|
|
loadingDots: {
|
|||
|
|
display: 'flex',
|
|||
|
|
gap: '8px',
|
|||
|
|
justifyContent: 'center',
|
|||
|
|
},
|
|||
|
|
callControls: {
|
|||
|
|
display: 'flex',
|
|||
|
|
gap: '16px',
|
|||
|
|
justifyContent: 'center',
|
|||
|
|
margin: '24px 0',
|
|||
|
|
},
|
|||
|
|
muteButton: {
|
|||
|
|
backgroundColor: '#1890ff',
|
|||
|
|
color: '#fff',
|
|||
|
|
border: 'none',
|
|||
|
|
borderRadius: '50%',
|
|||
|
|
width: '56px',
|
|||
|
|
height: '56px',
|
|||
|
|
fontSize: '20px',
|
|||
|
|
cursor: 'pointer',
|
|||
|
|
},
|
|||
|
|
endButton: {
|
|||
|
|
backgroundColor: '#ff4d4f',
|
|||
|
|
color: '#fff',
|
|||
|
|
border: 'none',
|
|||
|
|
borderRadius: '50px',
|
|||
|
|
padding: '16px 24px',
|
|||
|
|
fontSize: '16px',
|
|||
|
|
fontWeight: 'bold',
|
|||
|
|
cursor: 'pointer',
|
|||
|
|
},
|
|||
|
|
speakerButton: {
|
|||
|
|
backgroundColor: '#1890ff',
|
|||
|
|
color: '#fff',
|
|||
|
|
border: 'none',
|
|||
|
|
borderRadius: '50%',
|
|||
|
|
width: '56px',
|
|||
|
|
height: '56px',
|
|||
|
|
fontSize: '20px',
|
|||
|
|
cursor: 'pointer',
|
|||
|
|
},
|
|||
|
|
callInfo: {
|
|||
|
|
display: 'flex',
|
|||
|
|
justifyContent: 'space-around',
|
|||
|
|
width: '100%',
|
|||
|
|
marginTop: '24px',
|
|||
|
|
},
|
|||
|
|
infoItem: {
|
|||
|
|
display: 'flex',
|
|||
|
|
flexDirection: 'column' as const,
|
|||
|
|
alignItems: 'center',
|
|||
|
|
},
|
|||
|
|
infoLabel: {
|
|||
|
|
fontSize: '14px',
|
|||
|
|
color: '#666',
|
|||
|
|
marginBottom: '4px',
|
|||
|
|
},
|
|||
|
|
infoValue: {
|
|||
|
|
fontSize: '16px',
|
|||
|
|
fontWeight: 'bold',
|
|||
|
|
color: '#333',
|
|||
|
|
},
|
|||
|
|
quickActions: {
|
|||
|
|
display: 'grid',
|
|||
|
|
gridTemplateColumns: 'repeat(3, 1fr)',
|
|||
|
|
gap: '12px',
|
|||
|
|
},
|
|||
|
|
actionButton: {
|
|||
|
|
display: 'flex',
|
|||
|
|
flexDirection: 'column' as const,
|
|||
|
|
alignItems: 'center',
|
|||
|
|
padding: '16px 8px',
|
|||
|
|
backgroundColor: '#fff',
|
|||
|
|
border: 'none',
|
|||
|
|
borderRadius: '12px',
|
|||
|
|
cursor: 'pointer',
|
|||
|
|
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
|
|||
|
|
},
|
|||
|
|
actionIcon: {
|
|||
|
|
fontSize: '24px',
|
|||
|
|
marginBottom: '8px',
|
|||
|
|
},
|
|||
|
|
actionLabel: {
|
|||
|
|
fontSize: '12px',
|
|||
|
|
color: '#666',
|
|||
|
|
textAlign: 'center' as const,
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export default CallScreen;
|