Files
Neo-ZQYY/apps/admin-web/src/pages/Login.tsx
Neo 6f8f12314f feat: 累积功能变更 — 聊天集成、租户管理、小程序更新、ETL 增强、迁移脚本
包含多个会话的累积代码变更:
- backend: AI 聊天服务、触发器调度、认证增强、WebSocket、调度器最小间隔
- admin-web: ETL 状态页、任务管理、调度配置、登录优化
- miniprogram: 看板页面、聊天集成、UI 组件、导航更新
- etl: DWS 新任务(finance_area_daily/board_cache)、连接器增强
- tenant-admin: 项目初始化
- db: 19 个迁移脚本(etl_feiqiu 11 + zqyy_app 8)
- packages/shared: 枚举和工具函数更新
- tools: 数据库工具、报表生成、健康检查
- docs: PRD/架构/部署/合约文档更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 00:03:48 +08:00

93 lines
2.5 KiB
TypeScript

/**
* 登录页面 — Ant Design Form + Zustand authStore。
*/
import React, { useState } from "react";
import { Button, Card, Form, Input, message, Typography, Space } from "antd";
import { LockOutlined, UserOutlined } from "@ant-design/icons";
import { useNavigate } from "react-router-dom";
import { useAuthStore } from "../store/authStore";
const { Title, Text } = Typography;
interface LoginFormValues {
username: string;
password: string;
}
const Login: React.FC = () => {
const navigate = useNavigate();
const login = useAuthStore((s) => s.login);
const [loading, setLoading] = useState(false);
const onFinish = async (values: LoginFormValues) => {
setLoading(true);
try {
await login(values.username, values.password);
message.success("登录成功");
navigate("/dashboard", { replace: true });
} catch (err: unknown) {
const detail =
(err as { response?: { data?: { detail?: string } } })?.response?.data
?.detail ?? "登录失败,请检查用户名和密码";
message.error(detail);
} finally {
setLoading(false);
}
};
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
minHeight: "100vh",
background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
}}
>
<Card
style={{
width: 400,
borderRadius: 12,
boxShadow: "0 8px 32px rgba(0,0,0,0.15)",
}}
>
<Space direction="vertical" style={{ width: "100%", textAlign: "center", marginBottom: 24 }}>
<Title level={3} style={{ margin: 0 }}>NeoZQYY</Title>
<Text type="secondary"></Text>
</Space>
<Form<LoginFormValues>
name="login"
onFinish={onFinish}
autoComplete="off"
size="large"
>
<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>
);
};
export default Login;