Files
shaguabijia-admin-web/src/app/login/page.tsx
T
ouzhou a393b5c0e3 feat(config): 配置页 bool 开关控件 + 全站 antd App.useApp 迁移 (#12)
- 系统配置页支持 bool 类型(Switch 控件),供「提现自动对账」「比价期广告」等运营开关使用
- message / Modal.confirm 静态调用迁移到 App.useApp() 的 message / modal,消除 React 19
  "Static function can not consume context" 告警;providers 用 <App> 容器包裹全站

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: OuYingJun1024 <1034284404@qq.com>
Reviewed-on: #12
Co-authored-by: ouzhou <ouzhou@wonderable.ai>
Co-committed-by: ouzhou <ouzhou@wonderable.ai>
2026-06-17 10:38:40 +08:00

55 lines
1.7 KiB
TypeScript

'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { App, Button, Card, Form, Input } from 'antd';
import { api, errMsg } from '@/lib/api';
import { setAuth } from '@/lib/auth';
import type { LoginResponse } from '@/lib/types';
export default function LoginPage() {
const router = useRouter();
const { message } = App.useApp();
const [loading, setLoading] = useState(false);
const onFinish = async (values: { username: string; password: string }) => {
setLoading(true);
try {
const { data } = await api.post<LoginResponse>('/admin/api/auth/login', values);
setAuth(data.access_token, data.admin);
message.success('登录成功');
router.replace('/dashboard');
} catch (e) {
message.error(errMsg(e, '登录失败'));
} finally {
setLoading(false);
}
};
return (
<div
style={{
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#f0f2f5',
}}
>
<Card title="傻瓜比价 · 运营后台" style={{ width: 360 }}>
<Form onFinish={onFinish} layout="vertical">
<Form.Item name="username" label="用户名" rules={[{ required: true, message: '请输入用户名' }]}>
<Input autoFocus 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" loading={loading} block>
</Button>
</Form>
</Card>
</div>
);
}