| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | import React from 'react';
|
| | import { useTranslation } from 'react-i18next';
|
| | import { Modal, Button, Input, Typography } from '@douyinfe/semi-ui';
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | const TwoFactorAuthModal = ({
|
| | visible,
|
| | code,
|
| | loading,
|
| | onCodeChange,
|
| | onVerify,
|
| | onCancel,
|
| | title,
|
| | description,
|
| | placeholder,
|
| | }) => {
|
| | const { t } = useTranslation();
|
| |
|
| | const handleKeyDown = (e) => {
|
| | if (e.key === 'Enter' && code && !loading) {
|
| | onVerify();
|
| | }
|
| | };
|
| |
|
| | return (
|
| | <Modal
|
| | title={
|
| | <div className='flex items-center'>
|
| | <div className='w-8 h-8 rounded-full bg-blue-100 dark:bg-blue-900 flex items-center justify-center mr-3'>
|
| | <svg
|
| | className='w-4 h-4 text-blue-600 dark:text-blue-400'
|
| | fill='currentColor'
|
| | viewBox='0 0 20 20'
|
| | >
|
| | <path
|
| | fillRule='evenodd'
|
| | d='M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z'
|
| | clipRule='evenodd'
|
| | />
|
| | </svg>
|
| | </div>
|
| | {title || t('安全验证')}
|
| | </div>
|
| | }
|
| | visible={visible}
|
| | onCancel={onCancel}
|
| | footer={
|
| | <>
|
| | <Button onClick={onCancel}>{t('取消')}</Button>
|
| | <Button
|
| | type='primary'
|
| | loading={loading}
|
| | disabled={!code || loading}
|
| | onClick={onVerify}
|
| | >
|
| | {t('验证')}
|
| | </Button>
|
| | </>
|
| | }
|
| | width={500}
|
| | style={{ maxWidth: '90vw' }}
|
| | >
|
| | <div className='space-y-6'>
|
| | {/* 安全提示 */}
|
| | <div className='bg-blue-50 dark:bg-blue-900 rounded-lg p-4'>
|
| | <div className='flex items-start'>
|
| | <svg
|
| | className='w-5 h-5 text-blue-600 dark:text-blue-400 mt-0.5 mr-3 flex-shrink-0'
|
| | fill='currentColor'
|
| | viewBox='0 0 20 20'
|
| | >
|
| | <path
|
| | fillRule='evenodd'
|
| | d='M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z'
|
| | clipRule='evenodd'
|
| | />
|
| | </svg>
|
| | <div>
|
| | <Typography.Text
|
| | strong
|
| | className='text-blue-800 dark:text-blue-200'
|
| | >
|
| | {t('安全验证')}
|
| | </Typography.Text>
|
| | <Typography.Text className='block text-blue-700 dark:text-blue-300 text-sm mt-1'>
|
| | {description || t('为了保护账户安全,请验证您的两步验证码。')}
|
| | </Typography.Text>
|
| | </div>
|
| | </div>
|
| | </div>
|
| |
|
| | {/* 验证码输入 */}
|
| | <div>
|
| | <Typography.Text strong className='block mb-2'>
|
| | {t('验证身份')}
|
| | </Typography.Text>
|
| | <Input
|
| | placeholder={placeholder || t('请输入认证器验证码或备用码')}
|
| | value={code}
|
| | onChange={onCodeChange}
|
| | size='large'
|
| | maxLength={8}
|
| | onKeyDown={handleKeyDown}
|
| | autoFocus
|
| | />
|
| | <Typography.Text type='tertiary' size='small' className='mt-2 block'>
|
| | {t(
|
| | '支持6位TOTP验证码或8位备用码,可到`个人设置-安全设置-两步验证设置`配置或查看。',
|
| | )}
|
| | </Typography.Text>
|
| | </div>
|
| | </div>
|
| | </Modal>
|
| | );
|
| | };
|
| |
|
| | export default TwoFactorAuthModal;
|
| |
|