codernew-api-frontend/src/pages/login/form.tsx
gaoziman 6d96c5b947 feat(登录页): 重新设计登录页面
- 采用居中卡片布局设计
- 左侧展示品牌区域和认证动画
- 右侧提供登录表单
- 使用灰白色背景提升视觉体验
- 添加响应式设计支持移动端
- 优化表单交互和动画效果
2025-11-06 00:42:53 +08:00

134 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
Form,
Input,
Checkbox,
Link,
Button,
Space,
Message,
} from '@arco-design/web-react';
import { FormInstance } from '@arco-design/web-react/es/Form';
import { IconLock, IconUser } from '@arco-design/web-react/icon';
import React, { useEffect, useRef, useState } from 'react';
import axios from 'axios';
import useStorage from '@/utils/useStorage';
import useLocale from '@/utils/useLocale';
import locale from './locale';
import styles from './style/index.module.less';
export default function LoginForm() {
const formRef = useRef<FormInstance>();
const [errorMessage, setErrorMessage] = useState('');
const [loading, setLoading] = useState(false);
const [loginParams, setLoginParams, removeLoginParams] =
useStorage('loginParams');
const t = useLocale(locale);
const [rememberPassword, setRememberPassword] = useState(!!loginParams);
function afterLoginSuccess(params) {
// 记住密码
if (rememberPassword) {
setLoginParams(JSON.stringify(params));
} else {
removeLoginParams();
}
// 记录登录状态
localStorage.setItem('userStatus', 'login');
// 跳转首页
window.location.href = '/';
}
function login(params) {
setErrorMessage('');
setLoading(true);
axios
.post('/api/user/login', params)
.then((res) => {
const { status, msg } = res.data;
if (status === 'ok') {
afterLoginSuccess(params);
} else {
setErrorMessage(msg || t['login.form.login.errMsg']);
}
})
.finally(() => {
setLoading(false);
});
}
function onSubmitClick() {
formRef.current.validate().then((values) => {
login(values);
});
}
// 读取 localStorage设置初始值
useEffect(() => {
const rememberPassword = !!loginParams;
setRememberPassword(rememberPassword);
if (formRef.current && rememberPassword) {
const parseParams = JSON.parse(loginParams);
formRef.current.setFieldsValue(parseParams);
}
}, [loginParams]);
return (
<div className={styles['login-form-wrapper']}>
<div className={styles['login-form-title']}></div>
{errorMessage && (
<div className={styles['login-form-error-msg']}>{errorMessage}</div>
)}
<Form
className={styles['login-form']}
layout="vertical"
ref={formRef}
initialValues={{ userName: 'admin', password: 'admin' }}
>
<Form.Item
field="userName"
rules={[{ required: true, message: t['login.form.userName.errMsg'] }]}
>
<Input
placeholder={t['login.form.userName.placeholder']}
onPressEnter={onSubmitClick}
size="large"
/>
</Form.Item>
<Form.Item
field="password"
rules={[{ required: true, message: t['login.form.password.errMsg'] }]}
>
<Input.Password
placeholder={t['login.form.password.placeholder']}
onPressEnter={onSubmitClick}
size="large"
/>
</Form.Item>
<div className={styles['login-form-actions']}>
<Checkbox checked={rememberPassword} onChange={setRememberPassword}>
{t['login.form.rememberPassword']}
</Checkbox>
<Link>{t['login.form.forgetPassword']}</Link>
</div>
<Button
type="primary"
long
size="large"
onClick={onSubmitClick}
loading={loading}
className={styles['login-btn']}
>
{t['login.form.login']}
</Button>
</Form>
</div>
);
}