| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- import { FormEvent, useState } from 'react'
- import { Navigate, useSearchParams } from 'react-router-dom'
- import { ArrowRight, LockKeyhole, Phone } from 'lucide-react'
- import { Brand } from '../components/Brand'
- import { Footer } from '../components/Footer'
- import { useAuth } from '../AuthContext'
- export function AuthPage() {
- const [searchParams] = useSearchParams()
- const { user, authenticate } = useAuth()
- const [mode, setMode] = useState<'login' | 'register'>(() => searchParams.get('mode') === 'register' ? 'register' : 'login')
- const [busy, setBusy] = useState(false)
- const [error, setError] = useState('')
- if (user) {
- return <Navigate to={user.role === 'ADMIN' ? '/admin' : '/'} replace />
- }
- async function submit(e: FormEvent<HTMLFormElement>) {
- e.preventDefault()
- const f = new FormData(e.currentTarget)
- const password = String(f.get('password'))
- if (mode === 'register' && password !== String(f.get('confirmPassword'))) {
- setError('两次输入的密码不一致')
- return
- }
- setBusy(true)
- setError('')
- try {
- await authenticate(mode, String(f.get('phone')), password)
- } catch (x) {
- setError(x instanceof Error ? x.message : '操作失败')
- } finally {
- setBusy(false)
- }
- }
- return (
- <div className="auth-wrapper">
- <div className="auth-page">
- <section className="auth-brand">
- <Brand />
- <div>
- <p className="">智能课程工坊</p>
- <h1>
- 让每一门好课,
- <br />
- <em>留下清晰的星痕。</em>
- </h1>
- <p>归集课程资产与讲师信息,让课程制作更简单。</p>
- </div>
- </section>
- <form className="auth-card" onSubmit={submit}>
- <h2>{mode === 'login' ? '登录星痕' : '创建账号'}</h2>
- <p>{mode === 'login' ? '使用手机号和密码继续' : '注册后即可开始'}</p>
- <label>
- 手机号
- <div className="input-with-icon">
- <Phone />
- <input
- name="phone"
- inputMode="numeric"
- required
- pattern="1[0-9]{10}"
- placeholder="请输入 11 位手机号"
- />
- </div>
- </label>
- <label>
- 密码
- <div className="input-with-icon">
- <LockKeyhole />
- <input
- name="password"
- type="password"
- autoComplete={mode === 'login' ? 'current-password' : 'new-password'}
- required
- minLength={6}
- placeholder="至少 6 位密码"
- />
- </div>
- </label>
- {mode === 'register' && (
- <label>
- 确认密码
- <div className="input-with-icon">
- <LockKeyhole />
- <input
- name="confirmPassword"
- type="password"
- autoComplete="new-password"
- required
- minLength={6}
- placeholder="请再次输入密码"
- />
- </div>
- </label>
- )}
- {error && <div className="notice notice-error">{error}</div>}
- <button className="primary-button full-button" disabled={busy}>
- {busy ? '请稍候…' : mode === 'login' ? '登录' : '注册'}
- <ArrowRight size={17} />
- </button>
- <button
- type="button"
- className="auth-switch"
- onClick={() => {
- setMode(mode === 'login' ? 'register' : 'login')
- setError('')
- }}
- >
- {mode === 'login' ? '还没有账号?立即注册' : '已有账号?返回登录'}
- </button>
- </form>
- </div>
- <Footer />
- </div>
- )
- }
|