fix(web): 补回缺失的登录页(task-3 重构路由时误删,审计发现致命缺陷)

This commit is contained in:
2026-09-22 13:35:34 +08:00
parent 434cad7e5f
commit 984a53f2ae
+63
View File
@@ -0,0 +1,63 @@
// 登录页:语义对齐 web.archived/src/app/LoginPage.jsx(提交 d97cade)。
// 提交 GET /api/gateways 校验 Basic 凭证,成功后写入 localStorage('creatorhub.auth') 并跳转首页。
// 仅用 antd 默认组件:Card/Form/Input/Button/Alert。
import { history } from '@umijs/max';
import { Alert, Button, Card, Form, Input, Typography } from 'antd';
import { useState } from 'react';
interface FormValues {
username: string;
password: string;
}
export default function Page() {
const [form] = Form.useForm<FormValues>();
const [busy, setBusy] = useState(false);
const [error, setError] = useState('');
async function onFinish({ username, password }: FormValues) {
setBusy(true);
setError('');
const controller = new AbortController();
const timer = window.setTimeout(() => controller.abort(), 15000);
try {
const response = await fetch('/api/gateways', {
headers: { Authorization: `Basic ${btoa(`${username}:${password}`)}` },
signal: controller.signal,
});
if (response.status === 401) throw new Error('用户名或密码不正确');
if (!response.ok) throw new Error(`认证服务不可用(${response.status}`);
localStorage.setItem('creatorhub.auth', `${username}:${password}`);
history.replace('/accounts');
} catch (reason: any) {
setError(
reason.name === 'AbortError' ? '认证请求超时,请检查控制面连接' : reason.message || '登录失败',
);
} finally {
window.clearTimeout(timer);
setBusy(false);
}
}
return (
<div style={{ display: 'flex', minHeight: '100vh', alignItems: 'center', justifyContent: 'center', padding: 16 }}>
<Card style={{ width: 360 }}>
<Typography.Title level={4} style={{ marginBottom: 24, textAlign: 'center' }}>
CreatorHub
</Typography.Title>
{error ? <Alert type="error" showIcon style={{ marginBottom: 16 }} message={error} /> : null}
<Form form={form} layout="vertical" onFinish={onFinish} requiredMark={false}>
<Form.Item name="username" label="用户名" rules={[{ required: true, message: '请输入用户名' }]}>
<Input autoComplete="username" />
</Form.Item>
<Form.Item name="password" label="密码" rules={[{ required: true, message: '请输入密码' }]}>
<Input.Password autoComplete="current-password" />
</Form.Item>
<Button type="primary" htmlType="submit" block loading={busy}>
{busy ? '登录中…' : '登录'}
</Button>
</Form>
</Card>
</div>
);
}