From eceda78657c28332b65c0b69b010ed4ef9b1b97a Mon Sep 17 00:00:00 2001 From: laoriy <1161612005@qq.com> Date: Mon, 29 Apr 2024 23:27:01 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9Alogin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/core/Nav.tsx | 37 +++++++++++---- .../src/components/core/SignIn.tsx | 45 +++++++++++++++++-- .../ecommerce-front/src/helpers/auth.ts | 7 +++ .../ecommerce-front/src/store/auth.ts | 8 +++- .../ecommerce-front/src/types/auth.ts | 10 +++++ 5 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 5.react/8.ecommerce/ecommerce-front/src/helpers/auth.ts create mode 100644 5.react/8.ecommerce/ecommerce-front/src/types/auth.ts diff --git a/5.react/8.ecommerce/ecommerce-front/src/components/core/Nav.tsx b/5.react/8.ecommerce/ecommerce-front/src/components/core/Nav.tsx index 2a5e326..24a66f5 100644 --- a/5.react/8.ecommerce/ecommerce-front/src/components/core/Nav.tsx +++ b/5.react/8.ecommerce/ecommerce-front/src/components/core/Nav.tsx @@ -2,6 +2,8 @@ import React, { useState } from "react"; import { Menu, MenuProps } from "antd"; import { useNavigate } from "react-router-dom"; import useRoute from "../../hooks/useRoute"; +import { isAuth } from "../../helpers/auth"; +import { Jwt } from "../../types/auth"; const items: MenuProps["items"] = [ { @@ -12,20 +14,37 @@ const items: MenuProps["items"] = [ label: "购物车", key: "/shop", }, - { - label: "登录", - key: "/signin", - }, - { - label: "注册", - key: "/signup", - }, ]; function Nav() { const { location: { pathname }, } = useRoute(); + const auth = isAuth(); + const menus = [...items!]; + + if (auth) { + const { + user: { role }, + } = auth as Jwt; + menus.push( + role === 0 + ? { label: "dashboard", key: "/user/dashboard" } + : { label: "dashboard", key: "/user/dashboard" } + ); + } else { + menus.push( + { + label: "登录", + key: "/signin", + }, + { + label: "注册", + key: "/signup", + } + ); + } + const navigate = useNavigate(); const [current, setCurrent] = useState(pathname); const onClick: MenuProps["onClick"] = (e) => { @@ -37,7 +56,7 @@ function Nav() { mode="horizontal" onClick={onClick} selectedKeys={[current]} - items={items} + items={menus} > ); } diff --git a/5.react/8.ecommerce/ecommerce-front/src/components/core/SignIn.tsx b/5.react/8.ecommerce/ecommerce-front/src/components/core/SignIn.tsx index 9d41dd9..c13c29c 100644 --- a/5.react/8.ecommerce/ecommerce-front/src/components/core/SignIn.tsx +++ b/5.react/8.ecommerce/ecommerce-front/src/components/core/SignIn.tsx @@ -1,10 +1,46 @@ -import React from "react"; +import React, { useEffect } from "react"; import Layout from "./Layout"; -import { Button, Form, Input } from "antd"; +import { Button, Form, Input, Result } from "antd"; +import { SigninPayload, useSigninStore } from "../../store/auth"; +import { isAuth } from "../../helpers/auth"; +import { Jwt } from "../../types/auth"; +import { redirect, useNavigate } from "react-router-dom"; const SignIn = () => { - const onFinish = () => { + const signinState = useSigninStore(); + const navigate = useNavigate(); + const auth = isAuth(); + // 2. 登录失败 显示错误信息 + const showError = () => { + if (signinState.loaded && !signinState.success) { + return ( + + ); + } + }; + + useEffect(() => { + // 3. 登录成功 根据角色跳转到对应的管理页面 + if (auth) { + const { + user: { role }, + } = auth as Jwt; + if (role === 0) { + // 注册用户 + navigate("/user/dashboard"); + } else { + // 管理员 + navigate("/admin/dashboard"); + } + } + }); + const onFinish = async (value: SigninPayload) => { // 发送登录请求 + await signinState.signin(value); }; const signinForm = () => (
@@ -22,8 +58,9 @@ const SignIn = () => {
); - return ( + return auth ? null : ( + {showError()} {signinForm()} ); diff --git a/5.react/8.ecommerce/ecommerce-front/src/helpers/auth.ts b/5.react/8.ecommerce/ecommerce-front/src/helpers/auth.ts new file mode 100644 index 0000000..0185a0b --- /dev/null +++ b/5.react/8.ecommerce/ecommerce-front/src/helpers/auth.ts @@ -0,0 +1,7 @@ +import { Jwt } from "../types/auth"; + +export function isAuth(): boolean | Jwt { + const jwt = localStorage.getItem("jwt"); + if (jwt) return JSON.parse(jwt); + return false; +} diff --git a/5.react/8.ecommerce/ecommerce-front/src/store/auth.ts b/5.react/8.ecommerce/ecommerce-front/src/store/auth.ts index 5d2f6d3..3fc4aea 100644 --- a/5.react/8.ecommerce/ecommerce-front/src/store/auth.ts +++ b/5.react/8.ecommerce/ecommerce-front/src/store/auth.ts @@ -21,7 +21,7 @@ export interface SignupPayload { } interface SignupState extends AuthState { - signup: (payload: SigninPayload) => Promise; + signup: (payload: SignupPayload) => Promise; signupSuccess: () => void; signupFail: (message: string) => void; resetSignup: () => void; @@ -41,7 +41,7 @@ export interface SigninPayload { } interface SigninState extends AuthState { - signin: (payload: SigninPayload) => void; + signin: (payload: SigninPayload) => Promise; signinSuccess: () => void; signinFail: (message: string) => void; } @@ -76,6 +76,7 @@ const useSigninStore = create((set, get) => ({ signin: async (payload) => { set({ loaded: false, success: false, message: "" }); + let isSuccess = false; // 请求接口 console.log(payload); @@ -83,9 +84,12 @@ const useSigninStore = create((set, get) => ({ let response = await axios.post(`${API}/signin`, payload); localStorage.setItem("jwt", JSON.stringify(response.data)); get().signinSuccess(); + isSuccess = true; } catch (error: any) { get().signinFail(error?.response.data.error); + isSuccess = false; } + return isSuccess; }, signinSuccess: () => set({ loaded: true, success: true, message: "" }), signinFail: (message) => set({ loaded: true, success: false, message }), diff --git a/5.react/8.ecommerce/ecommerce-front/src/types/auth.ts b/5.react/8.ecommerce/ecommerce-front/src/types/auth.ts new file mode 100644 index 0000000..229e0c1 --- /dev/null +++ b/5.react/8.ecommerce/ecommerce-front/src/types/auth.ts @@ -0,0 +1,10 @@ +export interface User { + _id: string; + name: string; + email: string; + role: number; +} +export interface Jwt { + token: string; + user: User; +}