import { useState, useEffect } from "react" import { Form, message } from "antd" import { sendVerificationCode, bindContact, type BindContactResponse } from "@/api/auth" import { useCountdown } from "./useCountdown" type ContactType = "email" | "phone" interface UseBindContactFormOptions { open: boolean onSuccess?: (user: BindContactResponse["user"]) => void onCancel?: () => void } /** * 绑定联系方式表单 Hook * 封装表单状态、验证码发送、提交绑定等业务逻辑 */ export const useBindContactForm = ({ open, onSuccess }: UseBindContactFormOptions) => { const [activeTab, setActiveTab] = useState("email") const [form] = Form.useForm() const [loading, setLoading] = useState(false) const [codeLoading, setCodeLoading] = useState(false) const { countdown, isRunning, start: startCountdown, reset: resetCountdown } = useCountdown(60) /* ── 打开时重置表单 ── */ useEffect(() => { if (open) { form.resetFields() resetCountdown() } }, [open, form, resetCountdown]) /* ── 发送验证码 ── */ const handleSendCode = async () => { try { const fieldName = activeTab === "email" ? "email" : "phone" const value = form.getFieldValue(fieldName) if (!value) { message.warning(activeTab === "email" ? "请输入邮箱" : "请输入手机号") return } setCodeLoading(true) await sendVerificationCode({ target: activeTab, value, purpose: "bind", }) message.success("验证码已发送") startCountdown() } catch { // error handled by interceptor } finally { setCodeLoading(false) } } /* ── 提交绑定 ── */ const handleSubmit = async () => { // 1. 表单验证(失败时 Ant Design Form 会自动展示错误信息) let values try { values = await form.validateFields() } catch { return } // 2. 调用绑定接口 setLoading(true) try { const payload = activeTab === "email" ? { email: values.email, email_code: values.email_code } : { phone: values.phone, phone_code: values.phone_code } const result = await bindContact(payload) message.success("绑定成功") onSuccess?.(result.user) } catch { // API 错误由全局拦截器统一处理提示 } finally { setLoading(false) } } return { activeTab, setActiveTab, form, loading, codeLoading, countdown, codeDisabled: isRunning, handleSendCode, handleSubmit, } }