|
|
@@ -30,7 +30,7 @@ import { QRCodeSVG } from 'qrcode.react';
|
|
|
|
|
|
const { Text, Paragraph } = Typography;
|
|
|
|
|
|
-const TwoFASetting = () => {
|
|
|
+const TwoFASetting = ({ t }) => {
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
const [status, setStatus] = useState({
|
|
|
enabled: false,
|
|
|
@@ -59,7 +59,7 @@ const TwoFASetting = () => {
|
|
|
setStatus(res.data.data);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- showError('获取2FA状态失败');
|
|
|
+ showError(t('获取2FA状态失败'));
|
|
|
}
|
|
|
};
|
|
|
|
|
|
@@ -80,7 +80,7 @@ const TwoFASetting = () => {
|
|
|
showError(res.data.message);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- showError('设置2FA失败');
|
|
|
+ showError(t('设置2FA失败'));
|
|
|
} finally {
|
|
|
setLoading(false);
|
|
|
}
|
|
|
@@ -89,7 +89,7 @@ const TwoFASetting = () => {
|
|
|
// 启用2FA
|
|
|
const handleEnable2FA = async () => {
|
|
|
if (!verificationCode) {
|
|
|
- showWarning('请输入验证码');
|
|
|
+ showWarning(t('请输入验证码'));
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -99,7 +99,7 @@ const TwoFASetting = () => {
|
|
|
code: verificationCode
|
|
|
});
|
|
|
if (res.data.success) {
|
|
|
- showSuccess('两步验证启用成功!');
|
|
|
+ showSuccess(t('两步验证启用成功!'));
|
|
|
setEnableModalVisible(false);
|
|
|
setSetupModalVisible(false);
|
|
|
setVerificationCode('');
|
|
|
@@ -109,7 +109,7 @@ const TwoFASetting = () => {
|
|
|
showError(res.data.message);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- showError('启用2FA失败');
|
|
|
+ showError(t('启用2FA失败'));
|
|
|
} finally {
|
|
|
setLoading(false);
|
|
|
}
|
|
|
@@ -118,12 +118,12 @@ const TwoFASetting = () => {
|
|
|
// 禁用2FA
|
|
|
const handleDisable2FA = async () => {
|
|
|
if (!verificationCode) {
|
|
|
- showWarning('请输入验证码或备用码');
|
|
|
+ showWarning(t('请输入验证码或备用码'));
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (!confirmDisable) {
|
|
|
- showWarning('请确认您已了解禁用两步验证的后果');
|
|
|
+ showWarning(t('请确认您已了解禁用两步验证的后果'));
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -133,7 +133,7 @@ const TwoFASetting = () => {
|
|
|
code: verificationCode
|
|
|
});
|
|
|
if (res.data.success) {
|
|
|
- showSuccess('两步验证已禁用');
|
|
|
+ showSuccess(t('两步验证已禁用'));
|
|
|
setDisableModalVisible(false);
|
|
|
setVerificationCode('');
|
|
|
setConfirmDisable(false);
|
|
|
@@ -142,7 +142,7 @@ const TwoFASetting = () => {
|
|
|
showError(res.data.message);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- showError('禁用2FA失败');
|
|
|
+ showError(t('禁用2FA失败'));
|
|
|
} finally {
|
|
|
setLoading(false);
|
|
|
}
|
|
|
@@ -151,7 +151,7 @@ const TwoFASetting = () => {
|
|
|
// 重新生成备用码
|
|
|
const handleRegenerateBackupCodes = async () => {
|
|
|
if (!verificationCode) {
|
|
|
- showWarning('请输入验证码');
|
|
|
+ showWarning(t('请输入验证码'));
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -162,31 +162,31 @@ const TwoFASetting = () => {
|
|
|
});
|
|
|
if (res.data.success) {
|
|
|
setBackupCodes(res.data.data.backup_codes);
|
|
|
- showSuccess('备用码重新生成成功');
|
|
|
+ showSuccess(t('备用码重新生成成功'));
|
|
|
setVerificationCode('');
|
|
|
fetchStatus();
|
|
|
} else {
|
|
|
showError(res.data.message);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- showError('重新生成备用码失败');
|
|
|
+ showError(t('重新生成备用码失败'));
|
|
|
} finally {
|
|
|
setLoading(false);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 通用复制函数
|
|
|
- const copyTextToClipboard = (text, successMessage = '已复制到剪贴板') => {
|
|
|
+ const copyTextToClipboard = (text, successMessage = t('已复制到剪贴板')) => {
|
|
|
navigator.clipboard.writeText(text).then(() => {
|
|
|
showSuccess(successMessage);
|
|
|
}).catch(() => {
|
|
|
- showError('复制失败,请手动复制');
|
|
|
+ showError(t('复制失败,请手动复制'));
|
|
|
});
|
|
|
};
|
|
|
|
|
|
const copyBackupCodes = () => {
|
|
|
const codesText = backupCodes.join('\n');
|
|
|
- copyTextToClipboard(codesText, '备用码已复制到剪贴板');
|
|
|
+ copyTextToClipboard(codesText, t('备用码已复制到剪贴板'));
|
|
|
};
|
|
|
|
|
|
// 备用码展示组件
|
|
|
@@ -229,7 +229,7 @@ const TwoFASetting = () => {
|
|
|
onClick={onCopy}
|
|
|
className="!rounded-lg !bg-slate-600 hover:!bg-slate-700 w-full"
|
|
|
>
|
|
|
- 复制所有代码
|
|
|
+ {t('复制所有代码')}
|
|
|
</Button>
|
|
|
</div>
|
|
|
</Card>
|
|
|
@@ -245,7 +245,7 @@ const TwoFASetting = () => {
|
|
|
onClick={() => setCurrentStep(currentStep - 1)}
|
|
|
className="!rounded-lg"
|
|
|
>
|
|
|
- 上一步
|
|
|
+ {t('上一步')}
|
|
|
</Button>
|
|
|
)}
|
|
|
{currentStep < 2 ? (
|
|
|
@@ -255,7 +255,7 @@ const TwoFASetting = () => {
|
|
|
onClick={() => setCurrentStep(currentStep + 1)}
|
|
|
className="!rounded-lg !bg-slate-600 hover:!bg-slate-700"
|
|
|
>
|
|
|
- 下一步
|
|
|
+ {t('下一步')}
|
|
|
</Button>
|
|
|
) : (
|
|
|
<Button
|
|
|
@@ -264,14 +264,14 @@ const TwoFASetting = () => {
|
|
|
loading={loading}
|
|
|
onClick={() => {
|
|
|
if (!verificationCode) {
|
|
|
- showWarning('请输入验证码');
|
|
|
+ showWarning(t('请输入验证码'));
|
|
|
return;
|
|
|
}
|
|
|
handleEnable2FA();
|
|
|
}}
|
|
|
className="!rounded-lg !bg-slate-600 hover:!bg-slate-700"
|
|
|
>
|
|
|
- 完成设置并启用两步验证
|
|
|
+ {t('完成设置并启用两步验证')}
|
|
|
</Button>
|
|
|
)}
|
|
|
</>
|
|
|
@@ -290,7 +290,7 @@ const TwoFASetting = () => {
|
|
|
}}
|
|
|
className="!rounded-lg"
|
|
|
>
|
|
|
- 取消
|
|
|
+ {t('取消')}
|
|
|
</Button>
|
|
|
<Button
|
|
|
type="danger"
|
|
|
@@ -300,7 +300,7 @@ const TwoFASetting = () => {
|
|
|
onClick={handleDisable2FA}
|
|
|
className="!rounded-lg !bg-slate-500 hover:!bg-slate-600"
|
|
|
>
|
|
|
- 确认禁用
|
|
|
+ {t('确认禁用')}
|
|
|
</Button>
|
|
|
</>
|
|
|
);
|
|
|
@@ -320,7 +320,7 @@ const TwoFASetting = () => {
|
|
|
}}
|
|
|
className="!rounded-lg !bg-slate-600 hover:!bg-slate-700"
|
|
|
>
|
|
|
- 完成
|
|
|
+ {t('完成')}
|
|
|
</Button>
|
|
|
);
|
|
|
}
|
|
|
@@ -335,7 +335,7 @@ const TwoFASetting = () => {
|
|
|
}}
|
|
|
className="!rounded-lg"
|
|
|
>
|
|
|
- 取消
|
|
|
+ {t('取消')}
|
|
|
</Button>
|
|
|
<Button
|
|
|
type="primary"
|
|
|
@@ -345,7 +345,7 @@ const TwoFASetting = () => {
|
|
|
onClick={handleRegenerateBackupCodes}
|
|
|
className="!rounded-lg !bg-slate-600 hover:!bg-slate-700"
|
|
|
>
|
|
|
- 生成新的备用码
|
|
|
+ {t('生成新的备用码')}
|
|
|
</Button>
|
|
|
</>
|
|
|
);
|
|
|
@@ -366,23 +366,23 @@ const TwoFASetting = () => {
|
|
|
<div className="flex-1">
|
|
|
<div className="flex items-center gap-2 mb-1">
|
|
|
<Typography.Title heading={6} className="mb-0">
|
|
|
- 两步验证设置
|
|
|
+ {t('两步验证设置')}
|
|
|
</Typography.Title>
|
|
|
{status.enabled ? (
|
|
|
- <Tag color="green" shape="circle" size="small">已启用</Tag>
|
|
|
+ <Tag color="green" shape="circle" size="small">{t('已启用')}</Tag>
|
|
|
) : (
|
|
|
- <Tag color="red" shape="circle" size="small">未启用</Tag>
|
|
|
+ <Tag color="red" shape="circle" size="small">{t('未启用')}</Tag>
|
|
|
)}
|
|
|
{status.locked && (
|
|
|
- <Tag color="orange" shape="circle" size="small">账户已锁定</Tag>
|
|
|
+ <Tag color="orange" shape="circle" size="small">{t('账户已锁定')}</Tag>
|
|
|
)}
|
|
|
</div>
|
|
|
<Typography.Text type="tertiary" className="text-sm">
|
|
|
- 两步验证(2FA)为您的账户提供额外的安全保护。启用后,登录时需要输入密码和验证器应用生成的验证码。
|
|
|
+ {t('两步验证(2FA)为您的账户提供额外的安全保护。启用后,登录时需要输入密码和验证器应用生成的验证码。')}
|
|
|
</Typography.Text>
|
|
|
{status.enabled && (
|
|
|
<div className="mt-2">
|
|
|
- <Text size="small" type="secondary">剩余备用码:{status.backup_codes_remaining || 0} 个</Text>
|
|
|
+ <Text size="small" type="secondary">{t('剩余备用码:')}{status.backup_codes_remaining || 0}{t('个')}</Text>
|
|
|
</div>
|
|
|
)}
|
|
|
</div>
|
|
|
@@ -398,7 +398,7 @@ const TwoFASetting = () => {
|
|
|
className="!rounded-lg !bg-slate-600 hover:!bg-slate-700"
|
|
|
icon={<IconShield />}
|
|
|
>
|
|
|
- 启用验证
|
|
|
+ {t('启用验证')}
|
|
|
</Button>
|
|
|
) : (
|
|
|
<div className="flex flex-col space-y-2">
|
|
|
@@ -410,7 +410,7 @@ const TwoFASetting = () => {
|
|
|
className="!rounded-lg !bg-slate-500 hover:!bg-slate-600"
|
|
|
icon={<IconAlertTriangle />}
|
|
|
>
|
|
|
- 禁用两步验证
|
|
|
+ {t('禁用两步验证')}
|
|
|
</Button>
|
|
|
<Button
|
|
|
type="primary"
|
|
|
@@ -420,7 +420,7 @@ const TwoFASetting = () => {
|
|
|
className="!rounded-lg"
|
|
|
icon={<IconRefresh />}
|
|
|
>
|
|
|
- 重新生成备用码
|
|
|
+ {t('重新生成备用码')}
|
|
|
</Button>
|
|
|
</div>
|
|
|
)}
|
|
|
@@ -433,7 +433,7 @@ const TwoFASetting = () => {
|
|
|
title={
|
|
|
<div className="flex items-center">
|
|
|
<IconShield className="mr-2 text-slate-600" />
|
|
|
- 设置两步验证
|
|
|
+ {t('设置两步验证')}
|
|
|
</div>
|
|
|
}
|
|
|
visible={setupModalVisible}
|
|
|
@@ -451,9 +451,9 @@ const TwoFASetting = () => {
|
|
|
<div className="space-y-6">
|
|
|
{/* 步骤进度 */}
|
|
|
<Steps type="basic" size="small" current={currentStep}>
|
|
|
- <Steps.Step title="扫描二维码" description="使用认证器应用扫描二维码" />
|
|
|
- <Steps.Step title="保存备用码" description="保存备用码以备不时之需" />
|
|
|
- <Steps.Step title="验证设置" description="输入验证码完成设置" />
|
|
|
+ <Steps.Step title={t('扫描二维码')} description={t('使用认证器应用扫描二维码')} />
|
|
|
+ <Steps.Step title={t('保存备用码')} description={t('保存备用码以备不时之需')} />
|
|
|
+ <Steps.Step title={t('验证设置')} description={t('输入验证码完成设置')} />
|
|
|
</Steps>
|
|
|
|
|
|
{/* 步骤内容 */}
|
|
|
@@ -461,7 +461,7 @@ const TwoFASetting = () => {
|
|
|
{currentStep === 0 && (
|
|
|
<div>
|
|
|
<Paragraph className="text-gray-600 dark:text-gray-300 mb-4">
|
|
|
- 使用认证器应用(如 Google Authenticator、Microsoft Authenticator)扫描下方二维码:
|
|
|
+ {t('使用认证器应用(如 Google Authenticator、Microsoft Authenticator)扫描下方二维码:')}
|
|
|
</Paragraph>
|
|
|
<div className="flex justify-center mb-4">
|
|
|
<div className="bg-white p-4 rounded-lg shadow-sm">
|
|
|
@@ -470,7 +470,7 @@ const TwoFASetting = () => {
|
|
|
</div>
|
|
|
<div className="bg-blue-50 dark:bg-blue-900 rounded-lg p-3">
|
|
|
<Text className="text-blue-800 dark:text-blue-200 text-sm">
|
|
|
- 或手动输入密钥:<Text code copyable className="ml-2">{setupData.secret}</Text>
|
|
|
+ {t('或手动输入密钥:')}<Text code copyable className="ml-2">{setupData.secret}</Text>
|
|
|
</Text>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -481,10 +481,10 @@ const TwoFASetting = () => {
|
|
|
{/* 备用码展示 */}
|
|
|
<BackupCodesDisplay
|
|
|
codes={setupData.backup_codes}
|
|
|
- title="备用恢复代码"
|
|
|
+ title={t('备用恢复代码')}
|
|
|
onCopy={() => {
|
|
|
const codesText = setupData.backup_codes.join('\n');
|
|
|
- copyTextToClipboard(codesText, '备用码已复制到剪贴板');
|
|
|
+ copyTextToClipboard(codesText, t('备用码已复制到剪贴板'));
|
|
|
}}
|
|
|
/>
|
|
|
</div>
|
|
|
@@ -492,7 +492,7 @@ const TwoFASetting = () => {
|
|
|
|
|
|
{currentStep === 2 && (
|
|
|
<Input
|
|
|
- placeholder="输入认证器应用显示的6位数字验证码"
|
|
|
+ placeholder={t('输入认证器应用显示的6位数字验证码')}
|
|
|
value={verificationCode}
|
|
|
onChange={setVerificationCode}
|
|
|
size="large"
|
|
|
@@ -510,7 +510,7 @@ const TwoFASetting = () => {
|
|
|
title={
|
|
|
<div className="flex items-center">
|
|
|
<IconAlertTriangle className="mr-2 text-red-500" />
|
|
|
- 禁用两步验证
|
|
|
+ {t('禁用两步验证')}
|
|
|
</div>
|
|
|
}
|
|
|
visible={disableModalVisible}
|
|
|
@@ -528,7 +528,7 @@ const TwoFASetting = () => {
|
|
|
<div className="rounded-xl">
|
|
|
<Banner
|
|
|
type="warning"
|
|
|
- description="警告:禁用两步验证将永久删除您的验证设置和所有备用码,此操作不可撤销!"
|
|
|
+ description={t('警告:禁用两步验证将永久删除您的验证设置和所有备用码,此操作不可撤销!')}
|
|
|
className="!rounded-lg"
|
|
|
/>
|
|
|
</div>
|
|
|
@@ -537,24 +537,24 @@ const TwoFASetting = () => {
|
|
|
<div className="space-y-4">
|
|
|
<div>
|
|
|
<Text strong className="block mb-2 text-slate-700 dark:text-slate-200">
|
|
|
- 禁用后的影响:
|
|
|
+ {t('禁用后的影响:')}
|
|
|
</Text>
|
|
|
<ul className="space-y-2 text-sm text-slate-600 dark:text-slate-300">
|
|
|
<li className="flex items-start gap-2">
|
|
|
<Badge dot type='warning' />
|
|
|
- 降低您账户的安全性
|
|
|
+ {t('降低您账户的安全性')}
|
|
|
</li>
|
|
|
<li className="flex items-start gap-2">
|
|
|
<Badge dot type='warning' />
|
|
|
- 需要重新完整设置才能再次启用
|
|
|
+ {t('需要重新完整设置才能再次启用')}
|
|
|
</li>
|
|
|
<li className="flex items-start gap-2">
|
|
|
<Badge dot type='danger' />
|
|
|
- 永久删除您的两步验证设置
|
|
|
+ {t('永久删除您的两步验证设置')}
|
|
|
</li>
|
|
|
<li className="flex items-start gap-2">
|
|
|
<Badge dot type='danger' />
|
|
|
- 永久删除所有备用码(包括未使用的)
|
|
|
+ {t('永久删除所有备用码(包括未使用的)')}
|
|
|
</li>
|
|
|
</ul>
|
|
|
</div>
|
|
|
@@ -564,10 +564,10 @@ const TwoFASetting = () => {
|
|
|
<div className="space-y-4">
|
|
|
<div>
|
|
|
<Text strong className="block mb-2 text-slate-700 dark:text-slate-200">
|
|
|
- 验证身份
|
|
|
+ {t('验证身份')}
|
|
|
</Text>
|
|
|
<Input
|
|
|
- placeholder="请输入认证器验证码或备用码"
|
|
|
+ placeholder={t('请输入认证器验证码或备用码')}
|
|
|
value={verificationCode}
|
|
|
onChange={setVerificationCode}
|
|
|
size="large"
|
|
|
@@ -581,7 +581,7 @@ const TwoFASetting = () => {
|
|
|
onChange={(e) => setConfirmDisable(e.target.checked)}
|
|
|
className="text-sm"
|
|
|
>
|
|
|
- 我已了解禁用两步验证将永久删除所有相关设置和备用码,此操作不可撤销
|
|
|
+ {t('我已了解禁用两步验证将永久删除所有相关设置和备用码,此操作不可撤销')}
|
|
|
</Checkbox>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -594,7 +594,7 @@ const TwoFASetting = () => {
|
|
|
title={
|
|
|
<div className="flex items-center">
|
|
|
<IconRefresh className="mr-2 text-slate-600" />
|
|
|
- 重新生成备用码
|
|
|
+ {t('重新生成备用码')}
|
|
|
</div>
|
|
|
}
|
|
|
visible={backupModalVisible}
|
|
|
@@ -614,7 +614,7 @@ const TwoFASetting = () => {
|
|
|
<div className="rounded-xl">
|
|
|
<Banner
|
|
|
type="warning"
|
|
|
- description="重新生成备用码将使现有的备用码失效,请确保您已保存了当前的备用码。"
|
|
|
+ description={t('重新生成备用码将使现有的备用码失效,请确保您已保存了当前的备用码。')}
|
|
|
className="!rounded-lg"
|
|
|
/>
|
|
|
</div>
|
|
|
@@ -623,10 +623,10 @@ const TwoFASetting = () => {
|
|
|
<div className="space-y-4">
|
|
|
<div>
|
|
|
<Text strong className="block mb-2 text-slate-700 dark:text-slate-200">
|
|
|
- 验证身份
|
|
|
+ {t('验证身份')}
|
|
|
</Text>
|
|
|
<Input
|
|
|
- placeholder="请输入认证器验证码"
|
|
|
+ placeholder={t('请输入认证器验证码')}
|
|
|
value={verificationCode}
|
|
|
onChange={setVerificationCode}
|
|
|
size="large"
|
|
|
@@ -642,17 +642,17 @@ const TwoFASetting = () => {
|
|
|
<div className="flex items-center justify-center gap-2">
|
|
|
<Badge dot type='success' />
|
|
|
<Text strong className="text-lg text-slate-700 dark:text-slate-200">
|
|
|
- 新的备用码已生成
|
|
|
+ {t('新的备用码已生成')}
|
|
|
</Text>
|
|
|
</div>
|
|
|
<Text className="text-slate-500 dark:text-slate-400 text-sm">
|
|
|
- 旧的备用码已失效,请保存新的备用码
|
|
|
+ {t('旧的备用码已失效,请保存新的备用码')}
|
|
|
</Text>
|
|
|
|
|
|
{/* 备用码展示 */}
|
|
|
<BackupCodesDisplay
|
|
|
codes={backupCodes}
|
|
|
- title="新的备用恢复代码"
|
|
|
+ title={t('新的备用恢复代码')}
|
|
|
onCopy={copyBackupCodes}
|
|
|
/>
|
|
|
</Space>
|