feat: 初始化智能电量监控系统项目
该提交完成了完整的电费监控系统项目初始化,包含: 1. 后端Node.js+Express服务,支持定时采集、登录认证、数据API 2. React前端界面,包含登录页和数据仪表盘 3. Docker容器化配置和docker-compose部署文件 4. 环境变量示例和gitignore、dockerignore配置 5. 完整的项目文档README
This commit is contained in:
106
client/src/pages/Login.jsx
Normal file
106
client/src/pages/Login.jsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import { useState } from 'react';
|
||||
import { Card, Form, Input, Button, message } from 'antd';
|
||||
import { UserOutlined, LockOutlined } from '@ant-design/icons';
|
||||
import { Lightning } from '@icon-park/react';
|
||||
import { login } from '../api';
|
||||
|
||||
export default function Login({ onLogin }) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleSubmit = async (values) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await login(values.username, values.password);
|
||||
if (data.success) {
|
||||
onLogin();
|
||||
} else {
|
||||
message.error(data.message || '用户名或密码错误');
|
||||
}
|
||||
} catch {
|
||||
message.error('网络错误,请重试');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
minHeight: '100vh',
|
||||
background: '#f5f7fa',
|
||||
padding: 0,
|
||||
}}>
|
||||
<Card
|
||||
style={{
|
||||
width: '100%',
|
||||
maxWidth: 400,
|
||||
borderRadius: 12,
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.08)',
|
||||
}}
|
||||
styles={{ body: { padding: '48px 40px', textAlign: 'center' } }}
|
||||
>
|
||||
<div style={{ marginBottom: 32 }}>
|
||||
<Lightning theme="filled" size="40" fill="#4a90e2" style={{ display: 'flex', justifyContent: 'center', marginBottom: 8 }} />
|
||||
<h2 style={{
|
||||
margin: 0,
|
||||
fontSize: 24,
|
||||
fontWeight: 600,
|
||||
color: '#1a1a1a',
|
||||
}}>
|
||||
智能电量监控
|
||||
</h2>
|
||||
<p style={{ color: '#999', fontSize: 14, marginTop: 8, marginBottom: 0 }}>
|
||||
请登录后查看用电数据
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Form
|
||||
layout="vertical"
|
||||
onFinish={handleSubmit}
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item
|
||||
name="username"
|
||||
rules={[{ required: true, message: '请输入用户名' }]}
|
||||
>
|
||||
<Input
|
||||
prefix={<UserOutlined style={{ color: '#999' }} />}
|
||||
placeholder="用户名"
|
||||
size="large"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="password"
|
||||
rules={[{ required: true, message: '请输入密码' }]}
|
||||
>
|
||||
<Input.Password
|
||||
prefix={<LockOutlined style={{ color: '#999' }} />}
|
||||
placeholder="密码"
|
||||
size="large"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item style={{ marginTop: 32, marginBottom: 0 }}>
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
loading={loading}
|
||||
block
|
||||
size="large"
|
||||
style={{
|
||||
height: 44,
|
||||
fontWeight: 600,
|
||||
fontSize: 16,
|
||||
}}
|
||||
>
|
||||
登 录
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user