| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- import React, { useState } from 'react';
- import { useAuth } from '../context/AuthContext';
- import { Sparkles, ArrowRight, Lock, User, Mail, ShieldCheck } from 'lucide-react';
- export const LoginView = () => {
- const { login, register } = useAuth();
- const [isLoginTab, setIsLoginTab] = useState(true);
- const [identifier, setIdentifier] = useState('');
- const [password, setPassword] = useState('');
- const [username, setUsername] = useState('');
- const [loading, setLoading] = useState(false);
- const [errorMsg, setErrorMsg] = useState('');
- const handleSubmit = async (e) => {
- e.preventDefault();
- setErrorMsg('');
- setLoading(true);
- try {
- if (isLoginTab) {
- const res = await login(identifier, password);
- if (!res.success) {
- setErrorMsg(res.message || '登录失败,请检查账号与密码');
- }
- } else {
- if (!username.trim()) {
- setErrorMsg('请输入用户名');
- setLoading(false);
- return;
- }
- const res = await register(username, identifier, password);
- if (!res.success) {
- setErrorMsg(res.message || '注册失败,请稍后重试');
- }
- }
- } catch (err) {
- setErrorMsg('网络请求异常,请稍后重试');
- } finally {
- setLoading(false);
- }
- };
- return (
- <div className="min-h-screen flex items-center justify-center p-4 business-grid-bg">
- <div className="w-full max-w-md bg-white/90 dark:bg-slate-900/90 backdrop-blur-xl border border-black/10 dark:border-white/10 rounded-3xl p-8 shadow-2xl space-y-6 transition-all duration-300">
- {/* Header Branding */}
- <div className="text-center space-y-2">
- <img
- src="/app-icon.png"
- alt="星痕 App Logo"
- className="w-16 h-16 rounded-2xl object-cover border border-black/10 dark:border-white/20 mx-auto shadow-lg transform hover:scale-105 transition-transform"
- />
- <h1 className="text-2xl font-bold tracking-tight text-slate-900 dark:text-white">
- 星痕 CelestiaTrace
- </h1>
- <p className="text-xs text-slate-500 dark:text-slate-400">
- 云端现场记录极简同步平台
- </p>
- </div>
- {/* Tab Switcher */}
- <div className="flex bg-slate-100 dark:bg-slate-800/60 p-1 rounded-xl border border-black/5 dark:border-white/5">
- <button
- type="button"
- onClick={() => { setIsLoginTab(true); setErrorMsg(''); }}
- className={`flex-1 py-2 text-xs font-semibold rounded-lg transition-all ${
- isLoginTab
- ? 'bg-white dark:bg-slate-700 text-slate-900 dark:text-white shadow-sm'
- : 'text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white'
- }`}
- >
- 账号登录
- </button>
- <button
- type="button"
- onClick={() => { setIsLoginTab(false); setErrorMsg(''); }}
- className={`flex-1 py-2 text-xs font-semibold rounded-lg transition-all ${
- !isLoginTab
- ? 'bg-white dark:bg-slate-700 text-slate-900 dark:text-white shadow-sm'
- : 'text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white'
- }`}
- >
- 新用户注册
- </button>
- </div>
- {/* Error Alert */}
- {errorMsg && (
- <div className="p-3 text-xs rounded-xl bg-rose-500/10 border border-rose-500/20 text-rose-600 dark:text-rose-400 text-center font-medium animate-fade-in">
- {errorMsg}
- </div>
- )}
- {/* Form */}
- <form onSubmit={handleSubmit} className="space-y-4">
- {!isLoginTab && (
- <div className="space-y-1">
- <label className="text-xs font-medium text-slate-600 dark:text-slate-300">
- 用户名
- </label>
- <div className="relative">
- <User className="w-4 h-4 text-slate-400 absolute left-3 top-3" />
- <input
- type="text"
- required
- value={username}
- onChange={(e) => setUsername(e.target.value)}
- placeholder="例如: 张工"
- className="w-full pl-9 pr-4 py-2.5 rounded-xl bg-slate-50 dark:bg-slate-800 border border-black/10 dark:border-white/10 text-slate-900 dark:text-white text-xs focus:outline-none focus:border-slate-800 dark:focus:border-slate-200 transition-colors"
- />
- </div>
- </div>
- )}
- <div className="space-y-1">
- <label className="text-xs font-medium text-slate-600 dark:text-slate-300">
- 邮箱或手机号
- </label>
- <div className="relative">
- <Mail className="w-4 h-4 text-slate-400 absolute left-3 top-3" />
- <input
- type="text"
- required
- value={identifier}
- onChange={(e) => setIdentifier(e.target.value)}
- placeholder="user@example.com 或 13800138000"
- className="w-full pl-9 pr-4 py-2.5 rounded-xl bg-slate-50 dark:bg-slate-800 border border-black/10 dark:border-white/10 text-slate-900 dark:text-white text-xs focus:outline-none focus:border-slate-800 dark:focus:border-slate-200 transition-colors"
- />
- </div>
- </div>
- <div className="space-y-1">
- <label className="text-xs font-medium text-slate-600 dark:text-slate-300">
- 密码
- </label>
- <div className="relative">
- <Lock className="w-4 h-4 text-slate-400 absolute left-3 top-3" />
- <input
- type="password"
- required
- value={password}
- onChange={(e) => setPassword(e.target.value)}
- placeholder="输入密码"
- className="w-full pl-9 pr-4 py-2.5 rounded-xl bg-slate-50 dark:bg-slate-800 border border-black/10 dark:border-white/10 text-slate-900 dark:text-white text-xs focus:outline-none focus:border-slate-800 dark:focus:border-slate-200 transition-colors"
- />
- </div>
- </div>
- <button
- type="submit"
- disabled={loading}
- className="w-full mt-2 py-3 rounded-xl bg-slate-900 hover:bg-slate-800 dark:bg-white dark:hover:bg-slate-100 text-white dark:text-slate-900 text-xs font-semibold shadow-md flex items-center justify-center space-x-2 disabled:opacity-50 transition-all cursor-pointer"
- >
- <span>{loading ? '处理中...' : isLoginTab ? '安全登录' : '立即注册'}</span>
- {!loading && <ArrowRight className="w-4 h-4" />}
- </button>
- </form>
- <div className="flex items-center justify-center space-x-1.5 text-[11px] text-slate-400 pt-2">
- <ShieldCheck className="w-3.5 h-3.5" />
- <span>端到端同步加密与身份认证保驾护航</span>
- </div>
- </div>
- </div>
- );
- };
|