包含多个会话的累积代码变更: - 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>
93 lines
2.5 KiB
TypeScript
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;
|