'use client' import {useState} from 'react' import {Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger} from '@/components/ui/dialog' import {Button} from '@/components/ui/button' import {Form, FormField} from '@/components/ui/form' import {Input} from '@/components/ui/input' import {useForm, useFormContext} from 'react-hook-form' import {zodResolver} from '@hookform/resolvers/zod' import * as z from 'zod' import {toast} from 'sonner' import {useRouter} from 'next/navigation' import {updatePassword} from '@/actions/user' import SendMsg from '@/components/send-msg' // 表单验证规则 const schema = z.object({ phone: z.string().regex(/^1\d{10}$/, `请输入正确的手机号`), captcha: z.string().nonempty('请输入验证码'), code: z.string().regex(/^\d{6}$/, `请输入正确的验证码`), password: z.string().min(6, `密码至少6位`), confirm_password: z.string(), }).refine(data => data.password === data.confirm_password, { message: '两次输入的密码不一致', path: ['confirm_password'], }) type Schema = z.infer interface ChangePasswordDialogProps { triggerClassName?: string open?: boolean defaultOpen?: boolean onOpenChange?: (open: boolean) => void onSuccess?: () => void } export function ChangePasswordDialog({ triggerClassName, open, defaultOpen, onOpenChange, onSuccess, }: ChangePasswordDialogProps) { const [internalOpen, setInternalOpen] = useState(defaultOpen || false) const router = useRouter() const actualOpen = open !== undefined ? open : internalOpen const actualOnOpenChange = onOpenChange || setInternalOpen // 表单初始化 const form = useForm({ resolver: zodResolver( schema.refine( data => /^(?=.*[a-zA-Z])(?=.*\d).{6,}$/.test(data.password), { message: '密码需包含字母和数字,且不少于6位', path: ['password'], }, ), ), defaultValues: { phone: '', captcha: '', code: '', password: '', confirm_password: '', }, }) // 提交处理 const handler = form.handleSubmit(async (value) => { try { const resp = await updatePassword({ phone: value.phone, code: value.code, password: value.password, }) if (!resp.success) { throw new Error(resp.message) } toast.success(`保存成功,请重新登录`) onSuccess?.() actualOnOpenChange(false) router.replace('/login') } catch (e) { console.error(e) toast.error(`保存失败`, { description: e instanceof Error ? e.message : String(e), }) } }) return ( 修改密码
{/* 手机号输入 */} name="phone" label="手机号" className="flex-auto"> {({field}) => ( )} {/* 短信验证码 */}
name="code" label="验证码" className="flex-auto"> {({field}) => ( )}
{/* 新密码 */} name="password" label="新密码" className="flex-auto"> {({field}) => ( )} {/* 确认密码 */} name="confirm_password" label="确认密码" className="flex-auto"> {({field}) => ( )}
) } function SendMsgByPhone() { const form = useFormContext() const phone = form.watch('phone') return }