Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions web/src/components/auth/LoginForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,11 @@ const LoginForm = () => {
}}
>
<div className='flex flex-col items-center'>
<img src={status.wechat_qrcode} alt='微信二维码' className='mb-4' />
<img
src={status.wechat_qrcode}
alt={t('微信二维码')}
className='mb-4'
/>
</div>

<div className='text-center mb-4'>
Expand Down Expand Up @@ -793,7 +797,7 @@ const LoginForm = () => {
/>
</svg>
</div>
两步验证
{t('两步验证')}
</div>
}
visible={showTwoFA}
Expand Down
6 changes: 5 additions & 1 deletion web/src/components/auth/RegisterForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,11 @@ const RegisterForm = () => {
}}
>
<div className='flex flex-col items-center'>
<img src={status.wechat_qrcode} alt='微信二维码' className='mb-4' />
<img
src={status.wechat_qrcode}
alt={t('微信二维码')}
className='mb-4'
/>
</div>

<div className='text-center mb-4'>
Expand Down
62 changes: 35 additions & 27 deletions web/src/components/auth/TwoFAVerification.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,27 @@ import {
Typography,
} from '@douyinfe/semi-ui';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';

const { Title, Text, Paragraph } = Typography;

const TwoFAVerification = ({ onSuccess, onBack, isModal = false }) => {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [useBackupCode, setUseBackupCode] = useState(false);
const [verificationCode, setVerificationCode] = useState('');

const handleSubmit = async () => {
if (!verificationCode) {
showError('请输入验证码');
showError(t('请输入验证码'));
return;
}
// Validate code format
if (useBackupCode && verificationCode.length !== 8) {
showError('备用码必须是8位');
showError(t('备用码必须是8位'));
return;
} else if (!useBackupCode && !/^\d{6}$/.test(verificationCode)) {
showError('验证码必须是6位数字');
showError(t('验证码必须是6位数字'));
return;
}

Expand All @@ -55,7 +57,7 @@ const TwoFAVerification = ({ onSuccess, onBack, isModal = false }) => {
});

if (res.data.success) {
showSuccess('登录成功');
showSuccess(t('登录成功'));
// 保存用户信息到本地存储
localStorage.setItem('user', JSON.stringify(res.data.data));
if (onSuccess) {
Expand All @@ -65,7 +67,7 @@ const TwoFAVerification = ({ onSuccess, onBack, isModal = false }) => {
showError(res.data.message);
}
} catch (error) {
showError('验证失败,请重试');
showError(t('验证失败,请重试'));
} finally {
setLoading(false);
}
Expand All @@ -80,15 +82,17 @@ const TwoFAVerification = ({ onSuccess, onBack, isModal = false }) => {
if (isModal) {
return (
<div className='space-y-4'>
<Paragraph className='text-gray-600 dark:text-gray-300'>
请输入认证器应用显示的验证码完成登录
<Paragraph className='text-gray-600 dark:text-gray-300'>
{t('请输入认证器应用显示的验证码完成登录')}
</Paragraph>

<Form onSubmit={handleSubmit}>
<Form.Input
field='code'
label={useBackupCode ? '备用码' : '验证码'}
placeholder={useBackupCode ? '请输入8位备用码' : '请输入6位验证码'}
label={useBackupCode ? t('备用码') : t('验证码')}
placeholder={
useBackupCode ? t('请输入8位备用码') : t('请输入6位验证码')
}
value={verificationCode}
onChange={setVerificationCode}
onKeyPress={handleKeyPress}
Expand All @@ -105,7 +109,7 @@ const TwoFAVerification = ({ onSuccess, onBack, isModal = false }) => {
size='large'
style={{ marginBottom: 16 }}
>
验证并登录
{t('验证并登录')}
</Button>
</Form>

Expand All @@ -121,7 +125,7 @@ const TwoFAVerification = ({ onSuccess, onBack, isModal = false }) => {
}}
style={{ marginRight: 16, color: '#1890ff', padding: 0 }}
>
{useBackupCode ? '使用认证器验证码' : '使用备用码'}
{useBackupCode ? t('使用认证器验证码') : t('使用备用码')}
</Button>

{onBack && (
Expand All @@ -131,19 +135,20 @@ const TwoFAVerification = ({ onSuccess, onBack, isModal = false }) => {
onClick={onBack}
style={{ color: '#1890ff', padding: 0 }}
>
返回登录
{t('返回登录')}
</Button>
)}
</div>

<div className='bg-gray-50 dark:bg-gray-800 rounded-lg p-3'>
<Text size='small' type='secondary'>
<strong>提示:</strong>
<strong>{t('提示:')}</strong>
<br />
• 验证码每30秒更新一次
{t('• 验证码每30秒更新一次')}
<br />
• 如果无法获取验证码,请使用备用码
<br />• 每个备用码只能使用一次
{t('• 如果无法获取验证码,请使用备用码')}
<br />
{t('• 每个备用码只能使用一次')}
</Text>
</div>
</div>
Expand All @@ -161,17 +166,19 @@ const TwoFAVerification = ({ onSuccess, onBack, isModal = false }) => {
>
<Card style={{ width: 400, padding: 24 }}>
<div style={{ textAlign: 'center', marginBottom: 24 }}>
<Title heading={3}>两步验证</Title>
<Title heading={3}>{t('两步验证')}</Title>
<Paragraph type='secondary'>
请输入认证器应用显示的验证码完成登录
{t('请输入认证器应用显示的验证码完成登录')}
</Paragraph>
</div>

<Form onSubmit={handleSubmit}>
<Form.Input
field='code'
label={useBackupCode ? '备用码' : '验证码'}
placeholder={useBackupCode ? '请输入8位备用码' : '请输入6位验证码'}
label={useBackupCode ? t('备用码') : t('验证码')}
placeholder={
useBackupCode ? t('请输入8位备用码') : t('请输入6位验证码')
}
value={verificationCode}
onChange={setVerificationCode}
onKeyPress={handleKeyPress}
Expand All @@ -188,7 +195,7 @@ const TwoFAVerification = ({ onSuccess, onBack, isModal = false }) => {
size='large'
style={{ marginBottom: 16 }}
>
验证并登录
{t('验证并登录')}
</Button>
</Form>

Expand All @@ -204,7 +211,7 @@ const TwoFAVerification = ({ onSuccess, onBack, isModal = false }) => {
}}
style={{ marginRight: 16, color: '#1890ff', padding: 0 }}
>
{useBackupCode ? '使用认证器验证码' : '使用备用码'}
{useBackupCode ? t('使用认证器验证码') : t('使用备用码')}
</Button>

{onBack && (
Expand All @@ -214,7 +221,7 @@ const TwoFAVerification = ({ onSuccess, onBack, isModal = false }) => {
onClick={onBack}
style={{ color: '#1890ff', padding: 0 }}
>
返回登录
{t('返回登录')}
</Button>
)}
</div>
Expand All @@ -228,12 +235,13 @@ const TwoFAVerification = ({ onSuccess, onBack, isModal = false }) => {
}}
>
<Text size='small' type='secondary'>
<strong>提示:</strong>
<strong>{t('提示:')}</strong>
<br />
{t('• 验证码每30秒更新一次')}
<br />
• 验证码每30秒更新一次
{t('• 如果无法获取验证码,请使用备用码')}
<br />
• 如果无法获取验证码,请使用备用码
<br />• 每个备用码只能使用一次
{t('• 每个备用码只能使用一次')}
</Text>
</div>
</Card>
Expand Down
22 changes: 12 additions & 10 deletions web/src/components/playground/CustomRequestEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,14 @@ const CustomRequestEditor = ({
<div className='flex items-center gap-2'>
<Code size={16} className='text-gray-500' />
<Typography.Text strong className='text-sm'>
自定义请求体模式
{t('自定义请求体模式')}
</Typography.Text>
</div>
<Switch
checked={customRequestMode}
onChange={handleModeToggle}
checkedText='开'
uncheckedText='关'
checkedText={t('开')}
uncheckedText={t('关')}
size='small'
/>
</div>
Expand All @@ -140,7 +140,9 @@ const CustomRequestEditor = ({
{/* 提示信息 */}
<Banner
type='warning'
description='启用此模式后,将使用您自定义的请求体发送API请求,模型配置面板的参数设置将被忽略。'
description={t(
'启用此模式后,将使用您自定义的请求体发送API请求,模型配置面板的参数设置将被忽略。',
)}
icon={<AlertTriangle size={16} />}
className='!rounded-lg'
closeIcon={null}
Expand All @@ -150,21 +152,21 @@ const CustomRequestEditor = ({
<div>
<div className='flex items-center justify-between mb-2'>
<Typography.Text strong className='text-sm'>
请求体 JSON
{t('请求体 JSON')}
</Typography.Text>
<div className='flex items-center gap-2'>
{isValid ? (
<div className='flex items-center gap-1 text-green-600'>
<Check size={14} />
<Typography.Text className='text-xs'>
格式正确
{t('格式正确')}
</Typography.Text>
</div>
) : (
<div className='flex items-center gap-1 text-red-600'>
<X size={14} />
<Typography.Text className='text-xs'>
格式错误
{t('格式错误')}
</Typography.Text>
</div>
)}
Expand All @@ -177,15 +179,15 @@ const CustomRequestEditor = ({
disabled={!isValid}
className='!rounded-lg'
>
格式化
{t('格式化')}
</Button>
</div>
</div>

<TextArea
value={localValue}
onChange={handleValueChange}
placeholder='{"model": "gpt-4o", "messages": [...], ...}'
placeholder={t('{"model": "gpt-4o", "messages": [...], ...}')}
autosize={{ minRows: 8, maxRows: 20 }}
className={`custom-request-textarea !rounded-lg font-mono text-sm ${!isValid ? '!border-red-500' : ''}`}
style={{
Expand All @@ -201,7 +203,7 @@ const CustomRequestEditor = ({
)}

<Typography.Text className='text-xs text-gray-500 mt-2 block'>
请输入有效的JSON格式的请求体。您可以参考预览面板中的默认请求体格式。
{t('请输入有效的JSON格式的请求体。您可以参考预览面板中的默认请求体格式。')}
</Typography.Text>
</div>
</>
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/playground/DebugPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ const DebugPanel = ({
{t('预览请求体')}
{customRequestMode && (
<span className='px-1.5 py-0.5 text-xs bg-orange-100 text-orange-600 rounded-full'>
自定义
{t('自定义')}
</span>
)}
</div>
Expand Down
22 changes: 12 additions & 10 deletions web/src/components/playground/ImageUrlInput.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import React from 'react';
import { Input, Typography, Button, Switch } from '@douyinfe/semi-ui';
import { IconFile } from '@douyinfe/semi-icons';
import { FileText, Plus, X, Image } from 'lucide-react';
import { useTranslation } from 'react-i18next';

const ImageUrlInput = ({
imageUrls,
Expand All @@ -29,6 +30,7 @@ const ImageUrlInput = ({
onImageEnabledChange,
disabled = false,
}) => {
const { t } = useTranslation();
const handleAddImageUrl = () => {
const newUrls = [...imageUrls, ''];
onImageUrlsChange(newUrls);
Expand Down Expand Up @@ -56,20 +58,20 @@ const ImageUrlInput = ({
}
/>
<Typography.Text strong className='text-sm'>
图片地址
{t('图片地址')}
</Typography.Text>
{disabled && (
<Typography.Text className='text-xs text-orange-600'>
(已在自定义模式中忽略)
{t('(已在自定义模式中忽略)')}
</Typography.Text>
)}
</div>
<div className='flex items-center gap-2'>
<Switch
checked={imageEnabled}
onChange={onImageEnabledChange}
checkedText='启用'
uncheckedText='停用'
checkedText={t('启用')}
uncheckedText={t('停用')}
size='small'
className='flex-shrink-0'
disabled={disabled}
Expand All @@ -89,19 +91,19 @@ const ImageUrlInput = ({
{!imageEnabled ? (
<Typography.Text className='text-xs text-gray-500 mb-2 block'>
{disabled
? '图片功能在自定义请求体模式下不可用'
: '启用后可添加图片URL进行多模态对话'}
? t('图片功能在自定义请求体模式下不可用')
: t('启用后可添加图片URL进行多模态对话')}
</Typography.Text>
) : imageUrls.length === 0 ? (
<Typography.Text className='text-xs text-gray-500 mb-2 block'>
{disabled
? '图片功能在自定义请求体模式下不可用'
: '点击 + 按钮添加图片URL进行多模态对话'}
? t('图片功能在自定义请求体模式下不可用')
: t('点击 + 按钮添加图片URL进行多模态对话')}
</Typography.Text>
) : (
<Typography.Text className='text-xs text-gray-500 mb-2 block'>
已添加 {imageUrls.length} 张图片
{disabled ? ' (自定义模式下不可用)' : ''}
{t('已添加 {{count}} 张图片', { count: imageUrls.length })}
{disabled ? ` ${t('(自定义模式下不可用)')}` : ''}
</Typography.Text>
)}

Expand Down
2 changes: 1 addition & 1 deletion web/src/components/playground/MessageContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ const MessageContent = ({
className='text-red-500 text-sm p-2 bg-red-50 rounded-lg border border-red-200'
style={{ display: 'none' }}
>
图片加载失败: {imgItem.image_url.url}
{t('图片加载失败:')} {imgItem.image_url.url}
</div>
</div>
))}
Expand Down
Loading