Files
OpenFlare/frontend/components/common/general/password-dialog.tsx
T
2026-07-13 15:10:28 +08:00

117 lines
3.1 KiB
TypeScript

'use client';
import * as React from 'react';
import { useState } from 'react';
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import {
InputOTP,
InputOTPGroup,
InputOTPSlot,
} from '@/components/ui/input-otp';
import { Button } from '@/components/ui/button';
import { Spinner } from '@/components/ui/spinner';
interface PasswordDialogProps {
isOpen: boolean;
onOpenChange: (open: boolean) => void;
onConfirm: (password: string) => void;
loading?: boolean;
title?: string;
description?: string;
}
/**
* 密码输入对话框
*
* 用于敏感操作前的二次确认
*/
export function PasswordDialog({
isOpen,
onOpenChange,
onConfirm,
loading = false,
title = '请输入密码',
description = '为了您的账户安全,请输入6位认证密码进行验证',
}: PasswordDialogProps) {
const [password, setPassword] = useState('');
const handleConfirm = () => {
if (password.length === 6) {
onConfirm(password);
}
};
/* 当对话框关闭时重置密码*/
React.useEffect(() => {
if (!isOpen) {
setPassword('');
}
}, [isOpen]);
return (
<Dialog open={isOpen} onOpenChange={onOpenChange}>
<DialogContent className='w-xs sm:w-md'>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>{description}</DialogDescription>
</DialogHeader>
<div className='py-2 flex justify-center'>
<InputOTP
maxLength={6}
value={password}
onChange={setPassword}
disabled={loading}
onKeyDown={(e) => {
if (e.key === 'Enter' && password.length === 6 && !loading) {
handleConfirm();
}
}}
>
<InputOTPGroup className='gap-2'>
<InputOTPSlot index={0} className='w-10 h-10 text-base' />
<InputOTPSlot index={1} className='w-10 h-10 text-base' />
<InputOTPSlot index={2} className='w-10 h-10 text-base' />
<InputOTPSlot index={3} className='w-10 h-10 text-base' />
<InputOTPSlot index={4} className='w-10 h-10 text-base' />
<InputOTPSlot index={5} className='w-10 h-10 text-base' />
</InputOTPGroup>
</InputOTP>
</div>
<div className='flex justify-end gap-2 pt-2'>
<Button
variant='ghost'
onClick={() => onOpenChange(false)}
disabled={loading}
className='h-8 text-xs'
>
取消
</Button>
<Button
type='button'
className='bg-primary hover:bg-primary/90 h-8 text-xs'
onClick={handleConfirm}
disabled={password.length !== 6 || loading}
>
{loading ? (
<>
<Spinner className='mr-2 h-4 w-4' />
验证中...
</>
) : (
'确认'
)}
</Button>
</div>
</DialogContent>
</Dialog>
);
}