- 后端: FastAPI + SQLAlchemy + SQLite, JWT认证, 代理支持的AirwallexClient - 前端: React 18 + Vite + Ant Design 5, 中文界面 - 功能: 卡片管理, 持卡人管理, 交易记录, API令牌, 系统设置, 审计日志 - 第三方API: X-API-Key认证, 权限控制 - Docker部署: docker-compose编排前后端
52 lines
1.9 KiB
TypeScript
52 lines
1.9 KiB
TypeScript
import { useState } from 'react'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import { Card, Form, Input, Button, message } from 'antd'
|
|
import { UserOutlined, LockOutlined, CreditCardOutlined } from '@ant-design/icons'
|
|
import { useAuthStore } from '@/stores/auth'
|
|
|
|
export default function Login() {
|
|
const [loading, setLoading] = useState(false)
|
|
const login = useAuthStore((s) => s.login)
|
|
const navigate = useNavigate()
|
|
|
|
const onFinish = async (values: { username: string; password: string }) => {
|
|
setLoading(true)
|
|
try {
|
|
await login(values.username, values.password)
|
|
message.success('登录成功')
|
|
navigate('/')
|
|
} catch (err: unknown) {
|
|
const error = err as { response?: { data?: { detail?: string } } }
|
|
message.error(error.response?.data?.detail || '登录失败,请检查用户名和密码')
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="login-container">
|
|
<Card className="login-card">
|
|
<div style={{ textAlign: 'center', marginBottom: 32 }}>
|
|
<CreditCardOutlined style={{ fontSize: 48, color: '#667eea' }} />
|
|
<h2 className="login-title" style={{ marginTop: 12 }}>
|
|
Airwallex 发卡管理系统
|
|
</h2>
|
|
</div>
|
|
<Form name="login" onFinish={onFinish} size="large" autoComplete="off">
|
|
<Form.Item name="username" rules={[{ required: true, message: '请输入用户名' }]}>
|
|
<Input prefix={<UserOutlined />} placeholder="用户名" />
|
|
</Form.Item>
|
|
<Form.Item name="password" rules={[{ required: true, message: '请输入密码' }]}>
|
|
<Input.Password prefix={<LockOutlined />} placeholder="密码" />
|
|
</Form.Item>
|
|
<Form.Item>
|
|
<Button type="primary" htmlType="submit" loading={loading} block>
|
|
登录
|
|
</Button>
|
|
</Form.Item>
|
|
</Form>
|
|
</Card>
|
|
</div>
|
|
)
|
|
}
|