76 lines
2.4 KiB
TypeScript
76 lines
2.4 KiB
TypeScript
import { useState } from "react";
|
|
import { api, setToken } from "../api";
|
|
import { Package } from "lucide-react";
|
|
|
|
export default function Login({
|
|
onLoggedIn,
|
|
}: {
|
|
onLoggedIn: (username: string) => void;
|
|
}) {
|
|
const [username, setUsername] = useState("");
|
|
const [password, setPassword] = useState("");
|
|
const [error, setError] = useState("");
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
async function submit(e: React.FormEvent) {
|
|
e.preventDefault();
|
|
setError("");
|
|
setLoading(true);
|
|
try {
|
|
const r = await api.login(username, password);
|
|
setToken(r.token);
|
|
onLoggedIn(r.username);
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : "登录失败");
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="flex h-full items-center justify-center">
|
|
<form
|
|
onSubmit={submit}
|
|
className="w-80 rounded-xl bg-white p-8 shadow-md"
|
|
>
|
|
<div className="mb-6 flex flex-col items-center gap-2">
|
|
<Package className="h-8 w-8 text-emerald-600" />
|
|
<h1 className="text-lg font-semibold text-gray-800">
|
|
OpenGoods 管理后台
|
|
</h1>
|
|
</div>
|
|
{error && (
|
|
<div className="mb-4 rounded bg-red-50 px-3 py-2 text-sm text-red-600">
|
|
{error}
|
|
</div>
|
|
)}
|
|
<label className="mb-3 block">
|
|
<span className="mb-1 block text-sm text-gray-600">用户名</span>
|
|
<input
|
|
value={username}
|
|
onChange={(e) => setUsername(e.target.value)}
|
|
className="w-full rounded border border-gray-300 px-3 py-2 text-sm focus:border-emerald-500 focus:outline-none"
|
|
autoFocus
|
|
/>
|
|
</label>
|
|
<label className="mb-5 block">
|
|
<span className="mb-1 block text-sm text-gray-600">密码</span>
|
|
<input
|
|
type="password"
|
|
value={password}
|
|
onChange={(e) => setPassword(e.target.value)}
|
|
className="w-full rounded border border-gray-300 px-3 py-2 text-sm focus:border-emerald-500 focus:outline-none"
|
|
/>
|
|
</label>
|
|
<button
|
|
type="submit"
|
|
disabled={loading}
|
|
className="w-full rounded bg-emerald-600 py-2 text-sm font-medium text-white hover:bg-emerald-700 disabled:opacity-60"
|
|
>
|
|
{loading ? "登录中…" : "登录"}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
);
|
|
}
|