feat: expand vehicle data platform capabilities

This commit is contained in:
lingniu
2026-07-27 16:46:15 +08:00
parent e3a1f80f86
commit 3c4bece72c
650 changed files with 62155 additions and 2552 deletions

View File

@@ -0,0 +1,39 @@
import { FormEvent, useState } from "react";
import { api, type Session, tokenStore } from "./api";
import { Brand, Icon, navigate } from "./ui";
export function LoginPage({ onLogin }: { onLogin: (session: Session) => void }) {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
async function submit(event: FormEvent) {
event.preventDefault();
setError(""); setLoading(true);
try {
const response = await api.login(username.trim(), password);
tokenStore.set(response.accessToken);
onLogin(response.session);
} catch (reason) {
setError(reason instanceof Error ? reason.message : "登录失败");
} finally {
setLoading(false);
}
}
return <main className="login-page">
<button className="login-back" onClick={() => navigate("home")}><Icon name="arrow" size={16} /></button>
<section className="login-panel">
<Brand />
<div className="login-heading"><h1></h1><p>使</p></div>
<form onSubmit={submit}>
<label><input autoFocus autoComplete="username" value={username} onChange={(event) => setUsername(event.target.value)} placeholder="请输入账号" /></label>
<label><input type="password" autoComplete="current-password" value={password} onChange={(event) => setPassword(event.target.value)} placeholder="请输入密码" /></label>
{error && <div className="form-error" role="alert">{error}</div>}
<button className="button primary large full" disabled={loading || !username.trim() || !password}>{loading ? "正在登录…" : "登录控制台"}</button>
</form>
<div className="login-help"><Icon name="shield" size={17} /><p><b></b><span>使使</span></p></div>
</section>
</main>;
}