Quellcode durchsuchen

login & register

wind vor 3 Wochen
Ursprung
Commit
72a715f8d7

+ 1 - 0
package.json

@@ -11,6 +11,7 @@
   "dependencies": {
     "@ant-design/pro-components": "^2.8.2",
     "antd": "^5.22.4",
+    "js-cookie": "^3.0.5",
     "jsdom": "^25.0.1",
     "next": "14.2.20",
     "react": "^18.0.0",

+ 1 - 1
src/app/(home)/components/Services/services.module.scss

@@ -49,7 +49,7 @@
           flex: none;
           flex-grow: 0;
           order: 0;
-          width: 201px;
+          width: 240px;
           height: 57px;
 
           /* text-color */

+ 4 - 1
src/app/layout.tsx

@@ -1,6 +1,7 @@
 import type { Metadata } from "next";
 import type { Viewport } from "next";
 import "./globals.css";
+import { CommonProvider } from "@/context/commonContext";
 
 export const viewport: Viewport = {
   width: "device-width",
@@ -40,7 +41,9 @@ export default function RootLayout({
         <meta httpEquiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
         <meta httpEquiv="X-UA-Compatible" content="IE=8" />
       </head>
-      <body>{children}</body>
+      <body>
+        <CommonProvider>{children}</CommonProvider>
+      </body>
     </html>
   );
 }

+ 11 - 17
src/app/user/login/login.module.css

@@ -3,33 +3,22 @@
   flex-direction: column;
   height: 100vh;
   overflow: auto;
-  background: @layout-body-background;
-}
-
-.lang {
-  width: 100%;
-  height: 40px;
-  line-height: 44px;
-  text-align: right;
-  :global(.ant-dropdown-trigger) {
-    margin-right: 24px;
-  }
 }
 
 .content {
   flex: 1;
+  margin: 100px 0;
   padding: 32px 0;
 }
 
-@media (min-width: @screen-md-min) {
+@media screen and (max-width: 767px) {
   .container {
-    background-image: url("https://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg");
-    background-repeat: no-repeat;
     background-position: center 110px;
     background-size: 100%;
   }
 
   .content {
+    margin: 100px 0;
     padding: 32px 0 24px;
   }
 }
@@ -41,8 +30,13 @@
   vertical-align: middle;
   cursor: pointer;
   transition: color 0.3s;
+}
 
-  &:hover {
-    color: @primary-color;
-  }
+.footer {
+  position: absolute;
+  bottom: 0;
+  width: 100%;
+  background-color: #f8f9fa;
+  text-align: center;
+  padding: 1rem 0;
 }

+ 187 - 187
src/app/user/login/page.tsx

@@ -1,198 +1,198 @@
-// import { LockOutlined, MobileOutlined } from "@ant-design/icons";
-// import { LoginForm, ProForm, ProFormCaptcha, ProFormText } from "@ant-design/pro-components";
-// import { Alert, message, Tabs } from "antd";
-// import React, { useState } from "react";
-// import { history, SelectLang } from "umi";
-// import styles from "./login.module.css";
-// import { login, sendCaptcha } from "@/lib/user";
-// import Cookies from "js-cookie";
+"use client";
+
+import { GoDeviceMobile, GoLock } from "react-icons/go";
+import { LoginForm, ProForm, ProFormCaptcha, ProFormText } from "@ant-design/pro-components";
+import { Alert, message, Tabs } from "antd";
+import React, { useState } from "react";
+import styles from "./login.module.scss";
+import { login, sendCaptcha } from "@/lib/user";
+
+import { useRouter } from "next/navigation";
+import Cookies from "js-cookie";
+import { useCommonContext } from "@/context/commonContext";
 // import { useModel } from "@@/plugin-model/useModel";
 // import { USER_TYPE_ADMIN, USER_TYPE_PLATFORM } from "@/services/constants";
 
-// const LoginMessage: React.FC<{ content: string }> = ({ content }) => (
-//   <Alert
-//     style={{
-//       marginBottom: 24,
-//     }}
-//     message={content}
-//     type="error"
-//     showIcon
-//   />
-// );
+type LoginParams = {
+  type?: number;
+  username?: string;
+  password?: string;
+  captcha?: string;
+  sourceId?: number;
+};
 
-const Login: React.FC = () => {
-  //   const [errorMsg, setErrorMsg] = useState<string>("");
-  //   const [type, setType] = useState<string>("password");
-  //   const [form] = ProForm.useForm();
-  //   const { initialState, setInitialState } = useModel("@@initialState");
+const LoginMessage: React.FC<{ content: string }> = ({ content }) => (
+  <Alert
+    style={{
+      marginBottom: 24,
+    }}
+    message={content}
+    type="error"
+    showIcon
+  />
+);
 
-  //   const fetchUserInfo = async () => {
-  //     const userInfo = await initialState?.fetchUserInfo?.();
-  //     if (userInfo) {
-  //       await setInitialState((s) => ({
-  //         ...s,
-  //         currentUser: userInfo,
-  //       }));
-  //     }
-  //   };
+export default function Login() {
+  const router = useRouter();
+  const [errorMsg, setErrorMsg] = useState<string>("");
+  const [type, setType] = useState<string>("password");
+  const [form] = ProForm.useForm();
+  const { redirectAfterLogin, setUser } = useCommonContext();
 
-  //   const handleSubmit = async (values: API.LoginParams) => {
-  //     try {
-  //       const response = await login({ ...values, type: type == "password" ? 0 : 1 });
-  //       console.log(response);
-  //       if (response.code === 200) {
-  //         if (response.data?.type !== USER_TYPE_ADMIN && response.data?.type !== USER_TYPE_PLATFORM) {
-  //           message.success("登录成功");
-  //           await setInitialState((s) => ({
-  //             ...s,
-  //             currentUser: response.data,
-  //           }));
-  //           Cookies.set("ut", response!.data!.token!);
-  //           await fetchUserInfo();
-  //           if (!history) return;
-  //           const { query } = history.location;
-  //           const { redirect } = query as { redirect: string };
-  //           history.push(redirect || "/welcome");
-  //           return;
-  //         } else {
-  //           setErrorMsg("登录平台错误");
-  //           return;
-  //         }
-  //       }
-  //       // 如果失败去设置用户错误信息
-  //       setErrorMsg(response.message || "");
-  //     } catch (error) {
-  //       message.error("登录失败,请重试!");
-  //     }
-  //   };
+  const handleSubmit = async (values: LoginParams) => {
+    try {
+      const response = await login({ ...values, type: type == "password" ? 0 : 1 });
+      console.log(response);
+      if (response.code === 200) {
+        const data = response.data;
+        Cookies.set("ut", data.token);
 
-  return <div>hi</div>;
-  //     <div className={styles.container}>
-  //       <div className={styles.content}>
-  //         <LoginForm
-  //           form={form}
-  //           title="高潜咨询"
-  //           subTitle={"中国企业人效的未来"}
-  //           initialValues={{}}
-  //           actions={[]}
-  //           onFinish={async (values) => {
-  //             await handleSubmit(values as API.LoginParams);
-  //           }}
-  //         >
-  //           <Tabs activeKey={type} onChange={setType}>
-  //             <Tabs.TabPane key="password" tab={"手机号密码登录"} />
-  //             <Tabs.TabPane key="captcha" tab={"手机号验证码登录"} />
-  //           </Tabs>
+        const user = {
+          id: data.id,
+          name: data.name,
+          phone: data.phone,
+        };
+        setUser(user);
+        router.push(redirectAfterLogin);
+        return;
+      }
+      setErrorMsg(response.message || "");
+    } catch (error) {
+      message.error("登录失败,请重试!");
+    }
+  };
 
-  //           {errorMsg && <LoginMessage content={errorMsg} />}
+  const tabItems = [
+    {
+      key: "password",
+      label: "手机号密码登录",
+    },
+    {
+      key: "captcha",
+      label: "手机号验证码登录",
+    },
+  ];
 
-  //           {type === "password" && (
-  //             <>
-  //               <ProFormText
-  //                 fieldProps={{
-  //                   size: "large",
-  //                   prefix: <MobileOutlined className={styles.prefixIcon} />,
-  //                 }}
-  //                 name="phone"
-  //                 placeholder="手机号"
-  //                 rules={[
-  //                   {
-  //                     required: true,
-  //                     message: "请输入手机号!",
-  //                   },
-  //                   {
-  //                     pattern: /^1\d{10}$/,
-  //                     message: "手机号格式错误!",
-  //                   },
-  //                 ]}
-  //               />
-  //               <ProFormText.Password
-  //                 name="password"
-  //                 fieldProps={{
-  //                   size: "large",
-  //                   prefix: <LockOutlined className={styles.prefixIcon} />,
-  //                 }}
-  //                 placeholder={"密码"}
-  //                 rules={[
-  //                   {
-  //                     required: true,
-  //                     message: "请输入密码",
-  //                   },
-  //                 ]}
-  //               />
-  //             </>
-  //           )}
+  return (
+    <div className={styles.container}>
+      <div className={styles.content}>
+        <LoginForm
+          form={form}
+          title="高潜咨询"
+          subTitle={"中国企业人效的未来"}
+          initialValues={{}}
+          actions={[]}
+          onFinish={async (values) => {
+            await handleSubmit(values as LoginParams);
+          }}
+        >
+          <Tabs activeKey={type} onChange={setType} items={tabItems} />
 
-  //           {type === "captcha" && (
-  //             <>
-  //               <ProFormText
-  //                 fieldProps={{
-  //                   size: "large",
-  //                   prefix: <MobileOutlined className={styles.prefixIcon} />,
-  //                 }}
-  //                 name="phone"
-  //                 placeholder="手机号"
-  //                 rules={[
-  //                   {
-  //                     required: true,
-  //                     message: "请输入手机号!",
-  //                   },
-  //                   {
-  //                     pattern: /^1\d{10}$/,
-  //                     message: "手机号格式错误!",
-  //                   },
-  //                 ]}
-  //               />
-  //               <ProFormCaptcha
-  //                 fieldProps={{
-  //                   size: "large",
-  //                   prefix: <LockOutlined className={styles.prefixIcon} />,
-  //                 }}
-  //                 captchaProps={{
-  //                   size: "large",
-  //                 }}
-  //                 placeholder="请输入验证码"
-  //                 captchaTextRender={(timing, count) => {
-  //                   if (timing) {
-  //                     return `${count} 获取验证码`;
-  //                   }
-  //                   return "获取验证码";
-  //                 }}
-  //                 name="captcha"
-  //                 rules={[
-  //                   {
-  //                     required: true,
-  //                     message: "请输入验证码!",
-  //                   },
-  //                 ]}
-  //                 onGetCaptcha={async () => {
-  //                   const phone = form.getFieldValue("phone");
-  //                   if (!phone) {
-  //                     message.error("请先输入手机号");
-  //                     throw new Error("请先输入手机号");
-  //                   }
-  //                   const result = await sendCaptcha({
-  //                     phone,
-  //                   });
-  //                   console.log(result);
-  //                   if (result === false) {
-  //                     return;
-  //                   }
-  //                   message.success("获取验证码成功");
-  //                 }}
-  //               />
-  //             </>
-  //           )}
-  //           <div
-  //             style={{
-  //               marginBottom: 24,
-  //             }}
-  //           ></div>
-  //         </LoginForm>
-  //       </div>
-  //       <div>@2024 高潜咨询</div>
-  //     </div>
-  //   );
-};
+          {errorMsg && <LoginMessage content={errorMsg} />}
+
+          {type === "password" && (
+            <>
+              <ProFormText
+                fieldProps={{
+                  size: "large",
+                  prefix: <GoDeviceMobile className={styles.prefixIcon} />,
+                }}
+                name="phone"
+                placeholder="手机号"
+                rules={[
+                  {
+                    required: true,
+                    message: "请输入手机号!",
+                  },
+                  {
+                    pattern: /^1\d{10}$/,
+                    message: "手机号格式错误!",
+                  },
+                ]}
+              />
+              <ProFormText.Password
+                name="password"
+                fieldProps={{
+                  size: "large",
+                  prefix: <GoLock className={styles.prefixIcon} />,
+                }}
+                placeholder={"密码"}
+                rules={[
+                  {
+                    required: true,
+                    message: "请输入密码",
+                  },
+                ]}
+              />
+            </>
+          )}
 
-export default Login;
+          {type === "captcha" && (
+            <>
+              <ProFormText
+                fieldProps={{
+                  size: "large",
+                  prefix: <GoDeviceMobile className={styles.prefixIcon} />,
+                }}
+                name="phone"
+                placeholder="手机号"
+                rules={[
+                  {
+                    required: true,
+                    message: "请输入手机号!",
+                  },
+                  {
+                    pattern: /^1\d{10}$/,
+                    message: "手机号格式错误!",
+                  },
+                ]}
+              />
+              <ProFormCaptcha
+                fieldProps={{
+                  size: "large",
+                  prefix: <GoLock className={styles.prefixIcon} />,
+                }}
+                captchaProps={{
+                  size: "large",
+                }}
+                placeholder="请输入验证码"
+                captchaTextRender={(timing, count) => {
+                  if (timing) {
+                    return `${count} 获取验证码`;
+                  }
+                  return "获取验证码";
+                }}
+                name="captcha"
+                rules={[
+                  {
+                    required: true,
+                    message: "请输入验证码!",
+                  },
+                ]}
+                onGetCaptcha={async () => {
+                  const phone = form.getFieldValue("phone");
+                  if (!phone) {
+                    message.error("请先输入手机号");
+                    throw new Error("请先输入手机号");
+                  }
+                  const result = await sendCaptcha(phone);
+                  console.log(result);
+                  if (result === false) {
+                    return;
+                  }
+                  message.success("获取验证码成功");
+                }}
+              />
+            </>
+          )}
+          <div
+            style={{
+              marginBottom: 24,
+            }}
+          ></div>
+        </LoginForm>
+      </div>
+      <div className={styles.footer}>@2024 高潜咨询</div>
+    </div>
+  );
+}

+ 141 - 0
src/app/user/register/page.tsx

@@ -0,0 +1,141 @@
+"use client";
+
+import { GoDeviceMobile, GoLock } from "react-icons/go";
+import { ProForm, ProFormCaptcha, ProFormText } from "@ant-design/pro-components";
+import { message } from "antd";
+import React from "react";
+import { register, sendCaptcha } from "@/lib/user";
+import styles from "./register.module.scss";
+import { useRouter } from "next/navigation";
+
+type RegisterParams = {
+  phone?: string;
+  password?: string;
+  inviteCode?: string;
+  captcha?: string;
+};
+
+const Register: React.FC = () => {
+  const router = useRouter();
+  const [form] = ProForm.useForm();
+
+  const handleSubmit = async (values: RegisterParams) => {
+    register({ ...values }).then((data) => {
+      if (data.code === 200) {
+        message.success("注册成功!");
+        router.push("/user/login");
+        return;
+      } else {
+        message.error(data.message);
+      }
+    });
+  };
+
+  return (
+    <div className={styles.container}>
+      <div className={styles.content}>
+        <div className={styles.top}>
+          <div className={styles.header}>
+            <span className={styles.title}>高潜咨询</span>
+          </div>
+          <div className={styles.desc}>中国企业人效的未来</div>
+          <ProForm
+            form={form}
+            initialValues={{}}
+            submitter={{
+              render: (_, dom) => dom.pop(),
+              submitButtonProps: {
+                size: "large",
+                style: {
+                  width: "100%",
+                },
+              },
+              searchConfig: {
+                submitText: "注册",
+              },
+            }}
+            onFinish={async (values) => {
+              await handleSubmit(values);
+            }}
+          >
+            <>
+              <ProFormText
+                fieldProps={{
+                  size: "large",
+                  prefix: <GoDeviceMobile className={styles.prefixIcon} />,
+                }}
+                required
+                name="phone"
+                placeholder="手机号"
+                rules={[
+                  {
+                    required: true,
+                    message: "请输入手机号!",
+                  },
+                  {
+                    pattern: /^1\d{10}$/,
+                    message: "手机号格式错误!",
+                  },
+                ]}
+              />
+              <ProFormText.Password
+                name="password"
+                fieldProps={{
+                  size: "large",
+                  prefix: <GoLock className={styles.prefixIcon} />,
+                }}
+                required
+                placeholder={"密码"}
+                rules={[
+                  {
+                    required: true,
+                    message: "请输入密码",
+                  },
+                ]}
+              />
+              <ProFormCaptcha
+                fieldProps={{
+                  size: "large",
+                  prefix: <GoLock className={styles.prefixIcon} />,
+                }}
+                captchaProps={{
+                  size: "large",
+                }}
+                placeholder="请输入验证码"
+                captchaTextRender={(timing, count) => {
+                  if (timing) {
+                    return `${count} 获取验证码`;
+                  }
+                  return "获取验证码";
+                }}
+                name="captcha"
+                rules={[
+                  {
+                    required: true,
+                    message: "请输入验证码!",
+                  },
+                ]}
+                onGetCaptcha={async () => {
+                  const phone = form.getFieldValue("phone");
+                  if (!phone) {
+                    message.error("请先输入手机号");
+                    throw new Error("请先输入手机号");
+                  }
+                  const result = await sendCaptcha(phone);
+                  console.log(result);
+                  if (result === false) {
+                    return;
+                  }
+                  message.success("获取验证码成功");
+                }}
+              />
+            </>
+          </ProForm>
+        </div>
+      </div>
+      <div className={styles.footer}>@2024 高潜咨询</div>
+    </div>
+  );
+};
+
+export default Register;

+ 76 - 0
src/app/user/register/register.module.scss

@@ -0,0 +1,76 @@
+.container {
+  display: flex;
+  flex-direction: column;
+  height: 100vh;
+  overflow: auto;
+}
+
+.content {
+  flex: 1;
+  margin: 100px 0;
+  padding: 32px 0;
+  width: 328px;
+  margin: 0 auto;
+}
+
+@media screen and (max-width: 767px) {
+  .container {
+    background-position: center 110px;
+    background-size: 100%;
+  }
+
+  .content {
+    margin: 100px 0;
+    padding: 32px 0 24px;
+  }
+}
+
+.icon {
+  margin-left: 8px;
+  color: rgba(0, 0, 0, 0.2);
+  font-size: 24px;
+  vertical-align: middle;
+  cursor: pointer;
+  transition: color 0.3s;
+}
+
+.top {
+  text-align: center;
+  margin-top: 80px;
+}
+
+.header {
+  height: 44px;
+  line-height: 44px;
+  a {
+    text-decoration: none;
+  }
+}
+
+.logo {
+  height: 44px;
+  margin-right: 16px;
+  vertical-align: top;
+}
+
+.title {
+  position: relative;
+  top: 2px;
+  font-weight: 600;
+  font-size: 33px;
+  font-family: Avenir, "Helvetica Neue", Arial, Helvetica, sans-serif;
+}
+
+.desc {
+  margin-top: 12px;
+  margin-bottom: 40px;
+}
+
+.footer {
+  position: absolute;
+  bottom: 0;
+  width: 100%;
+  background-color: #f8f9fa;
+  text-align: center;
+  padding: 1rem 0;
+}

+ 1 - 1
src/components/Footer/footer.module.scss

@@ -64,7 +64,7 @@
             flex: none;
             flex-grow: 0;
             order: 0;
-            width: 97px;
+            width: 110px;
             height: 32px;
 
             /* light-text-color */

+ 50 - 0
src/components/Header/header.module.scss

@@ -80,6 +80,56 @@
         height: 24px;
       }
 
+      .navbar-user {
+        position: absolute;
+        top: 0px;
+        left: 255px;
+        width: 100px;
+        height: 24px;
+        text-align: center;
+
+        .link {
+          color: #ffffff;
+          font-weight: 600;
+          font-size: 14px;
+          font-family: "Montserrat";
+          font-style: normal;
+          line-height: 24px;
+          letter-spacing: 0.2px;
+          transition: box-shadow 0.3s ease, color 0.3s ease;
+        }
+
+        .hide-drop {
+          position: absolute;
+          display: none;
+          top: 100%;
+          left: 0;
+          text-align: center;
+          padding-top: 20px;
+          padding-bottom: 5px;
+          background-color: rgba(0, 0, 0, 0.2);
+          min-width: 100px;
+          z-index: 1000;
+        }
+
+        .show-drop {
+          position: absolute;
+          display: block;
+          top: 100%;
+          left: 0;
+          text-align: center;
+          padding-top: 20px;
+          padding-bottom: 5px;
+          background-color: rgba(0, 0, 0, 0.2);
+          min-width: 100px;
+          z-index: 1000;
+        }
+      }
+      .navbar-user:hover {
+        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+        background-color: rgba(0, 0, 0, 0.2); /* 可选:微弱的背景颜色 */
+      }
+
       .link {
         /* light-text-color */
 

+ 46 - 7
src/components/Header/headerMobile.tsx

@@ -1,9 +1,11 @@
 "use client";
 
-import React, { useState } from "react";
+import React, { useState, useEffect } from "react";
 import Link from "next/link";
 import Image from "next/image";
 import styles from "./header.module.scss";
+import { useCommonContext } from "@/context/commonContext";
+import Cookies from "js-cookie";
 
 const HeaderMobile: React.FC = () => {
   const [showMenu, setShowMenu] = useState("");
@@ -12,6 +14,22 @@ const HeaderMobile: React.FC = () => {
     setShowMenu("hide");
   };
 
+  const [isLogin, setIsLogin] = useState(false);
+  const { user, setUser } = useCommonContext();
+
+  useEffect(() => {
+    if (user) {
+      setIsLogin(true);
+    } else {
+      setIsLogin(false);
+    }
+  }, [user]);
+
+  const logout = () => {
+    setUser(null);
+    Cookies.remove("ut");
+  };
+
   return (
     <>
       <div className={styles["nav-fixed"]}>
@@ -48,12 +66,33 @@ const HeaderMobile: React.FC = () => {
             <Link className={styles.item} href="/contactUs">
               联系我们
             </Link>
-            <Link className={styles.item} href={"https://hi-po.com.cn/user/login"}>
-              登录
-            </Link>
-            <Link className={styles.item} href={"https://hi-po.com.cn/user/register"}>
-              注册
-            </Link>
+            {isLogin && (
+              <>
+                <Link className={styles.item} href="#" onClick={() => hideMenu()}>
+                  {user?.phone}
+                </Link>
+                <Link
+                  className={styles.item}
+                  href="#"
+                  onClick={() => {
+                    logout();
+                    hideMenu();
+                  }}
+                >
+                  退出
+                </Link>
+              </>
+            )}
+            {!isLogin && (
+              <>
+                <Link className={styles.item} href={"/user/login"}>
+                  登录
+                </Link>
+                <Link className={styles.item} href={"/user/register"}>
+                  注册
+                </Link>
+              </>
+            )}
           </div>
         </div>
       </div>

+ 68 - 11
src/components/Header/headerPC.tsx

@@ -1,11 +1,46 @@
 "use client";
 
-import React from "react";
+import React, { useState, useEffect } from "react";
 import Link from "next/link";
 import Image from "next/image";
 import styles from "./header.module.scss";
+import { useCommonContext } from "@/context/commonContext";
+import Cookies from "js-cookie";
 
 const HeaderPC: React.FC = () => {
+  const [showDropdown, setDropdown] = useState(false);
+
+  const toggleDropdown = () => {
+    if (showDropdown) {
+      setDropdown(false);
+    } else {
+      setDropdown(true);
+    }
+  };
+  const handleMouseEnter = () => {
+    setDropdown(true);
+  };
+
+  const handleMouseLeave = () => {
+    setDropdown(false);
+  };
+
+  const [isLogin, setIsLogin] = useState(false);
+  const { user, setUser } = useCommonContext();
+
+  useEffect(() => {
+    if (user) {
+      setIsLogin(true);
+    } else {
+      setIsLogin(false);
+    }
+  }, [user]);
+
+  const logout = () => {
+    setUser(null);
+    Cookies.remove("ut");
+  };
+
   return (
     <div className={styles.nav}>
       <div className={styles["nav-bar"]}>
@@ -33,16 +68,38 @@ const HeaderPC: React.FC = () => {
               联系我们
             </Link>
           </div>
-          <div className={styles["navbar-login"]}>
-            <Link className={styles.link} href={"https://hi-po.com.cn/user/login"}>
-              登录
-            </Link>
-          </div>
-          <div className={styles["navbar-register"]}>
-            <Link className={styles.link} href={"https://hi-po.com.cn/user/register"}>
-              注册
-            </Link>
-          </div>
+          {isLogin && (
+            <>
+              <div className={styles["navbar-user"]}>
+                <Link className={styles.link} href="#" onClick={() => toggleDropdown()}>
+                  {user?.phone}
+                </Link>
+                <div
+                  className={showDropdown ? styles["show-drop"] : styles["hide-drop"]}
+                  onMouseEnter={handleMouseEnter}
+                  onMouseLeave={handleMouseLeave}
+                >
+                  <Link className={styles.link} href="#" onClick={() => logout()}>
+                    退出
+                  </Link>
+                </div>
+              </div>
+            </>
+          )}
+          {!isLogin && (
+            <>
+              <div className={styles["navbar-login"]}>
+                <Link className={styles.link} href={"/user/login"}>
+                  登录
+                </Link>
+              </div>
+              <div className={styles["navbar-register"]}>
+                <Link className={styles.link} href={"/user/register"}>
+                  注册
+                </Link>
+              </div>
+            </>
+          )}
         </div>
       </div>
       <div className={styles["nav-container"]}>

+ 2 - 2
src/components/Nav/navMobile.tsx

@@ -49,10 +49,10 @@ const NavMobile: React.FC = () => {
             <Link className={styles.item} href="/contactUs">
               联系我们
             </Link>
-            <Link className={styles.item} href={"https://hi-po.com.cn/user/login"}>
+            <Link className={styles.item} href={"/user/login"}>
               登录
             </Link>
-            <Link className={styles.item} href={"https://hi-po.com.cn/user/register"}>
+            <Link className={styles.item} href={"/user/register"}>
               注册
             </Link>
           </div>

+ 2 - 2
src/components/Nav/navPC.tsx

@@ -40,10 +40,10 @@ const NavPC: React.FC<NavPCProps> = ({ title }) => {
             <Link className={isCurrent("联系我们") ? styles.linkChecked : styles.link} href="/contactUs">
               联系我们
             </Link>
-            <Link className={styles.link} href={"https://hi-po.com.cn/user/login"}>
+            <Link className={styles.link} href={"/user/login"}>
               登录
             </Link>
-            <Link className={styles.link} href={"https://hi-po.com.cn/user/register"}>
+            <Link className={styles.link} href={"/user/register"}>
               注册
             </Link>
           </div>

+ 46 - 0
src/context/commonContext.tsx

@@ -0,0 +1,46 @@
+"use client";
+
+import React, { createContext, useContext, useState, useEffect } from "react";
+import Cookies from "js-cookie";
+import { userInfo } from "@/lib/user";
+
+export interface UserType {
+  id: string;
+  name: string;
+  phone: string;
+}
+
+interface CommonContextType {
+  user: UserType | null;
+  setUser: (user: UserType | null) => void;
+  redirectAfterLogin: string;
+  setRedirectAfterLogin: (path: string) => void;
+}
+
+const CommonContext = createContext<CommonContextType | undefined>(undefined);
+
+export function CommonProvider({ children }: { children: React.ReactNode }) {
+  const [user, setUser] = useState<UserType | null>(null);
+  const [redirectAfterLogin, setRedirectAfterLogin] = useState<string>("/");
+
+  useEffect(() => {
+    const ut = Cookies.get("ut");
+    userInfo(ut).then(({ code: data }) => {
+      console.log(data);
+    });
+  }, []);
+
+  return (
+    <CommonContext.Provider value={{ user, setUser, redirectAfterLogin, setRedirectAfterLogin }}>
+      {children}
+    </CommonContext.Provider>
+  );
+}
+
+export const useCommonContext = (): CommonContextType => {
+  const context = useContext(CommonContext);
+  if (context === undefined) {
+    throw new Error("useCommon must be used within a CommonProvider");
+  }
+  return context;
+};

+ 1 - 0
src/lib/cms.ts

@@ -34,6 +34,7 @@ export async function fetchArticleList(type: number, page: number, size: number)
   const result = await fetch(`${host}/api/v1/cms/listArticle`, {
     method: "POST",
     body: formData,
+    cache: "no-store",
   });
   const json = await result.json();
   return json;

+ 9 - 0
src/lib/user.ts

@@ -56,3 +56,12 @@ export async function register(params: RegisterParams) {
   const json = await result.json();
   return json;
 }
+
+export async function userInfo(token: string) {
+  const options = {
+    method: "POST",
+  };
+  const response = await fetch(`${host}/api/v1/user/userInfo`, options);
+  const json = await response.json();
+  return json;
+}