| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| 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; |
|
|