| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- import { useState, useEffect } from "react";
- import {
- Box,
- Flex,
- TextInput,
- Button,
- FormControl,
- Note,
- IconButton,
- } from "@contentful/f36-components";
- import { EyeIcon, EyeClosedIcon } from "@contentful/f36-icons";
- import { useNavigate } from "react-router-dom";
- import { authApi } from "@/services/modules/system";
- import { useAuth } from "@/contexts/AuthContext";
- import { useLoginAuth } from "./hooks/useAuth";
- import { debounce } from "@/utils/lodash";
- import styles from "./index.module.css";
- export default function LoginPage() {
- const [account, setAccount] = useState("内容中心管理员");
- const [password, setPassword] = useState("zyh931015$");
- const [captcha, setCaptcha] = useState("");
- const [captchaKey, setCaptchaKey] = useState("");
- const [captchaImage, setCaptchaImage] = useState("");
- const [errorMessage, setErrorMessage] = useState("");
- const [showPassword, setShowPassword] = useState(false);
-
- const navigate = useNavigate();
- const { refreshAuth } = useAuth();
- const { login, loading } = useLoginAuth();
- // 获取验证码
- const fetchCaptcha = async () => {
- const checkKey =
- new Date().getTime() + Math.random().toString(36).slice(-4); // 1629428467008;
- setCaptchaKey(checkKey);
- try {
- const result = await authApi.getCaptcha(checkKey);
- setCaptchaImage(result);
- setCaptcha(""); // 清空验证码输入
- } catch (error) {
- console.error("获取验证码失败:", error);
- }
- };
- // 页面加载时获取验证码
- useEffect(() => {
- fetchCaptcha();
- }, []);
- const handleLogin = async (e: React.FormEvent) => {
- e.preventDefault();
- // 清空之前的错误
- setErrorMessage("");
- // 验证表单 - 只检查必填
- if (!account.trim() || !password.trim() || !captcha.trim()) {
- setErrorMessage("账号、密码或验证码不能为空");
- return;
- }
- try {
- // 调用登录(使用 hook 统一处理)
- await login({
- username: account,
- password,
- captcha,
- checkKey: captchaKey,
- });
- console.log("登录成功");
- // 刷新权限数据(加载菜单)
- await refreshAuth();
- // 跳转到首页
- navigate("/content-model");
- } catch (error: any) {
- console.error("登录失败:", error);
- setErrorMessage(error.message || "登录失败,请稍后重试");
- // 刷新验证码
- fetchCaptcha();
- }
- };
- return (
- <Flex
- justifyContent="center"
- alignItems="center"
- className={styles.container}
- >
- <Box className={styles.loginBox}>
- {/* 标题 */}
- <Box className={styles.header}>
- <h1 className={styles.title}>欢迎回来</h1>
- <h2 className={styles.subtitle}>登录你的账号</h2>
- </Box>
- {/* 登录表单 */}
- <Box className={styles.formContainer}>
- <form onSubmit={handleLogin}>
- <Flex flexDirection="column" gap="spacingS">
- {/* 错误提示 */}
- {errorMessage && <Note variant="warning">{errorMessage}</Note>}
- {/* account */}
- <FormControl className={styles.form_control}>
- <FormControl.Label>账号</FormControl.Label>
- <TextInput
- // type="account"
- value={account}
- onChange={(e) => {
- setAccount(e.target.value);
- // 清除错误提示
- if (errorMessage) {
- setErrorMessage("");
- }
- }}
- placeholder="请输入你的账号"
- />
- </FormControl>
- {/* Password */}
- <FormControl className={styles.form_control}>
- <FormControl.Label>密码</FormControl.Label>
- <Box className={styles.passwordInputWrapper}>
- <TextInput
- type={showPassword ? "text" : "password"}
- value={password}
- onChange={(e) => {
- setPassword(e.target.value);
- // 清除错误提示
- if (errorMessage) {
- setErrorMessage("");
- }
- }}
- placeholder="请输入你的密码"
- />
- <IconButton
- aria-label={showPassword ? "隐藏密码" : "显示密码"}
- icon={showPassword ? <EyeClosedIcon/> : <EyeIcon />}
- variant="transparent"
- size="small"
- onClick={() => setShowPassword(!showPassword)}
- className={styles.passwordToggle}
- style={{
- opacity: showPassword ? 0.5 : 1,
- transform: showPassword ? 'scale(0.9)' : 'scale(1)'
- }}
- />
- </Box>
- </FormControl>
- {/* Captcha */}
- <FormControl className={styles.form_control}>
- <FormControl.Label>验证码</FormControl.Label>
- <Flex gap="spacingS" alignItems="center">
- <Box className={styles.captchaInputWrapper}>
- <TextInput
- value={captcha}
- onChange={(e) => {
- setCaptcha(e.target.value);
- // 清除错误提示
- if (errorMessage) {
- setErrorMessage("");
- }
- }}
- placeholder="请输入验证码"
- />
- </Box>
- <Box
- onClick={debounce(fetchCaptcha, 500)}
- className={styles.captchaImage}
- >
- {captchaImage ? (
- <img
- src={captchaImage}
- alt="验证码"
- />
- ) : (
- <span className={styles.captchaPlaceholder}>
- 点击刷新
- </span>
- )}
- </Box>
- </Flex>
- </FormControl>
- {/* Remember me */}
- {/* <Checkbox
- isChecked={rememberMe}
- onChange={() => setRememberMe(!rememberMe)}
- >
- Remember me
- </Checkbox> */}
- {/* Login Button */}
- <Button
- variant="primary"
- size="large"
- type="submit"
- isFullWidth
- isLoading={loading}
- >
- Log in
- </Button>
- </Flex>
- </form>
- </Box>
- {/* Footer Links */}
- {/* <Flex
- justifyContent="center"
- gap="spacingS"
- marginTop="spacingL"
- className={styles.footer}
- >
- <Button variant="transparent" size="small">
- Log in via SSO
- </Button>
- <Text>|</Text>
- <Button variant="transparent" size="small">
- Reset password
- </Button>
- <Text>|</Text>
- <Button variant="transparent" size="small">
- Resend confirmation
- </Button>
- <Text>|</Text>
- <Button variant="transparent" size="small">
- Unlock account
- </Button>
- </Flex> */}
- </Box>
- </Flex>
- );
- }
|