src/features/auth/auth-form.tsx
此代码来自构建时的仓库快照。修改源码后重新构建即可更新。
'use client';
import { useState } from 'react';
import { Alert, Button, Card, Form, Input, Tabs } from 'antd';
import { authClient } from '@/lib/auth-client';
export function AuthForm() {
const [mode, setMode] = useState('login');
const [busy, setBusy] = useState(false);
const [error, setError] = useState('');
async function submit(values: {
email: string;
password: string;
name?: string;
}) {
setBusy(true);
setError('');
try {
const result =
mode === 'login'
? await authClient.signIn.email({
email: values.email.trim().toLowerCase(),
password: values.password,
})
: await authClient.signUp.email({
email: values.email.trim().toLowerCase(),
password: values.password,
name: values.name!.trim(),
});
if (result.error) {
setError(
mode === 'login'
? '登录失败,请检查邮箱和密码后重试'
: '注册失败,请检查输入或尝试登录已有账号',
);
return;
}
// 完整刷新销毁上一账号的查询缓存和草稿,避免同一浏览器切换账号时残留数据。
// 登录身份发生变化时刻意完整刷新,销毁上一账号的内存缓存。
// eslint-disable-next-line @next/next/no-location-assign-relative-destination
window.location.assign('/');
} catch {
setError('网络连接失败,请稍后重试');
} finally {
setBusy(false);
}
}
return (
<main className="mx-auto flex min-h-screen max-w-md items-center px-5 py-12">
<Card className="w-full" title="TeamDesk · 团队客服平台">
<p className="mb-5 text-slate-500">
登录后进入你的团队,协作处理每一张工单。
</p>
<Tabs
activeKey={mode}
onChange={(key) => {
setMode(key);
setError('');
}}
items={[
{ key: 'login', label: '登录' },
{ key: 'register', label: '注册' },
]}
/>
{error && (
<Alert className="mb-4" type="error" showIcon title={error} />
)}
<Form key={mode} layout="vertical" onFinish={submit} disabled={busy}>
{mode === 'register' && (
<Form.Item
label="姓名"
name="name"
rules={[
{ required: true, whitespace: true, message: '请输入姓名' },
{ max: 80 },
]}
>
<Input autoComplete="name" />
</Form.Item>
)}
<Form.Item
label="邮箱"
name="email"
rules={[
{ required: true, message: '请输入邮箱' },
{ type: 'email', message: '请输入有效邮箱' },
]}
>
<Input autoComplete="email" />
</Form.Item>
<Form.Item
label="密码"
name="password"
rules={[
{ required: true, message: '请输入密码' },
...(mode === 'register'
? [
{ min: 10, message: '密码至少 10 字符' },
{ max: 128, message: '密码最多 128 字符' },
]
: []),
]}
>
<Input.Password
autoComplete={
mode === 'login' ? 'current-password' : 'new-password'
}
/>
</Form.Item>
<Button htmlType="submit" type="primary" block loading={busy}>
{mode === 'login' ? '登录' : '注册并登录'}
</Button>
</Form>
</Card>
</main>
);
}