Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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