diff --git a/web/src/pages/login/index.tsx b/web/src/pages/login/index.tsx new file mode 100644 index 0000000..c94eff5 --- /dev/null +++ b/web/src/pages/login/index.tsx @@ -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(); + 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 ( +
+ + + CreatorHub + + {error ? : null} +
+ + + + + + + +
+
+
+ ); +}