From 0693f5de744bf92f66d6ea95cb16080c2ceb82c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E7=BA=A7=E8=80=81=E7=99=BD=E5=85=94?= Date: Wed, 30 Jul 2025 14:42:22 +0800 Subject: [PATCH] =?UTF-8?q?FEAT=20=3D>=20=E6=9C=AC=E6=AC=A1=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E9=A1=B9=E7=9B=AE=E4=B8=BA=EF=BC=9A=20=E5=AD=98?= =?UTF-8?q?=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nkebao/src/App.tsx | 7 +- nkebao/src/components/DeviceGuard/index.tsx | 90 --------------------- nkebao/src/pages/guide/index.tsx | 22 +++-- nkebao/src/pages/login/api.ts | 1 + nkebao/src/pages/login/login.tsx | 86 +++++++++++--------- nkebao/src/router/index.tsx | 5 +- nkebao/src/store/index.ts | 1 - nkebao/src/store/module/device.ts | 30 ------- nkebao/src/store/module/user.ts | 6 +- nkebao/src/utils/device.ts | 30 ------- 10 files changed, 67 insertions(+), 211 deletions(-) delete mode 100644 nkebao/src/components/DeviceGuard/index.tsx delete mode 100644 nkebao/src/store/module/device.ts delete mode 100644 nkebao/src/utils/device.ts diff --git a/nkebao/src/App.tsx b/nkebao/src/App.tsx index fa7a4541..bfee5515 100644 --- a/nkebao/src/App.tsx +++ b/nkebao/src/App.tsx @@ -1,8 +1,11 @@ import React from "react"; import AppRouter from "@/router"; - function App() { - return ; + return ( + <> + + + ); } export default App; diff --git a/nkebao/src/components/DeviceGuard/index.tsx b/nkebao/src/components/DeviceGuard/index.tsx deleted file mode 100644 index 9335ddfe..00000000 --- a/nkebao/src/components/DeviceGuard/index.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React, { useEffect, useState, useMemo } from "react"; -import { useNavigate, useLocation } from "react-router-dom"; -import { useDeviceStore } from "@/store/module/device"; -import { useUserStore } from "@/store/module/user"; -import { updateDeviceCount } from "@/utils/device"; - -interface DeviceGuardProps { - children: React.ReactNode; -} - -const DeviceGuard: React.FC = ({ children }) => { - const navigate = useNavigate(); - const location = useLocation(); - const { isLoggedIn } = useUserStore(); - const { setDeviceCount } = useDeviceStore(); - const [isChecking, setIsChecking] = useState(true); - - // 不需要设备检查的路径 - const EXEMPT_PATHS = useMemo( - () => ["/login", "/guide", "/register", "/forgot-password"], - [], - ); - - useEffect(() => { - const checkDeviceStatus = async () => { - // 如果用户未登录,不需要检查设备状态 - if (!isLoggedIn) { - setIsChecking(false); - return; - } - - // 如果当前路径是豁免路径,不需要检查设备状态 - if (EXEMPT_PATHS.includes(location.pathname)) { - setIsChecking(false); - return; - } - - try { - // 从API获取最新的设备数量并更新到store - const currentDeviceCount = await updateDeviceCount(setDeviceCount); - - // 如果设备数量为0且不在guide页面,跳转到guide页面 - if (currentDeviceCount === 0 && location.pathname !== "/guide") { - navigate("/guide"); - return; - } - - // 如果设备数量大于0且在guide页面,跳转到首页 - if (currentDeviceCount > 0 && location.pathname === "/guide") { - navigate("/"); - return; - } - } catch (error) { - console.error("检查设备状态失败:", error); - // 如果检查失败,默认跳转到guide页面 - if (location.pathname !== "/guide") { - navigate("/guide"); - return; - } - } finally { - setIsChecking(false); - } - }; - - checkDeviceStatus(); - }, [isLoggedIn, location.pathname, navigate, setDeviceCount, EXEMPT_PATHS]); - - // 如果正在检查,显示加载状态 - if (isChecking) { - return ( -
-
- 检查设备状态中... -
-
- ); - } - - return <>{children}; -}; - -export default DeviceGuard; diff --git a/nkebao/src/pages/guide/index.tsx b/nkebao/src/pages/guide/index.tsx index 27c8aed8..8e1e1ea8 100644 --- a/nkebao/src/pages/guide/index.tsx +++ b/nkebao/src/pages/guide/index.tsx @@ -8,15 +8,16 @@ import { QrcodeOutlined, } from "@ant-design/icons"; import Layout from "@/components/Layout/Layout"; -import { fetchDeviceQRCode, addDeviceByImei, fetchDeviceList } from "./api"; -import { useUserStore, useDeviceStore } from "@/store"; +import { getDashboard } from "@/pages/mobile/home/api"; +import { fetchDeviceQRCode, addDeviceByImei } from "./api"; +import { useUserStore } from "@/store/module/user"; import styles from "./index.module.scss"; const Guide: React.FC = () => { const navigate = useNavigate(); const { user } = useUserStore(); - const { deviceCount, setDeviceCount } = useDeviceStore(); const [loading, setLoading] = useState(true); + const [deviceCount, setDeviceCount] = useState(0); // 添加设备弹窗状态 const [addVisible, setAddVisible] = useState(false); @@ -36,10 +37,8 @@ const Guide: React.FC = () => { const checkDeviceStatus = useCallback(async () => { try { setLoading(true); - const dashboardData = await fetchDeviceList({ - accountId: user.s2_accountId, - }); - const deviceNum = dashboardData.added ? 1 : 0; + const dashboardData = await getDashboard(); + const deviceNum = dashboardData?.deviceNum || 0; setDeviceCount(deviceNum); @@ -49,6 +48,7 @@ const Guide: React.FC = () => { return; } } catch (error) { + console.error("检查设备状态失败:", error); Toast.show({ content: "检查设备状态失败,请重试", position: "top", @@ -56,7 +56,7 @@ const Guide: React.FC = () => { } finally { setLoading(false); } - }, [navigate, setDeviceCount]); + }, []); useEffect(() => { checkDeviceStatus(); @@ -71,9 +71,7 @@ const Guide: React.FC = () => { const pollDeviceStatus = async () => { try { - const dashboardData = await fetchDeviceList({ - accountId: user.s2_accountId, - }); + const dashboardData = await getDashboard(); const currentDeviceCount = dashboardData?.deviceNum || 0; // 如果设备数量增加了,说明有新设备添加成功 @@ -97,7 +95,7 @@ const Guide: React.FC = () => { // 每3秒检查一次设备状态 pollingRef.current = setInterval(pollDeviceStatus, 3000); - }, [isPolling, deviceCount, setDeviceCount]); + }, [isPolling, deviceCount]); // 停止轮询 const stopPolling = useCallback(() => { diff --git a/nkebao/src/pages/login/api.ts b/nkebao/src/pages/login/api.ts index 617d0bed..9c1f6e6c 100644 --- a/nkebao/src/pages/login/api.ts +++ b/nkebao/src/pages/login/api.ts @@ -11,6 +11,7 @@ export interface LoginResponse { data: { token: string; token_expired: string; + deviceTotal: number; // 设备总数 member: { id: string; name: string; diff --git a/nkebao/src/pages/login/login.tsx b/nkebao/src/pages/login/login.tsx index 5a91a67c..c1b52807 100644 --- a/nkebao/src/pages/login/login.tsx +++ b/nkebao/src/pages/login/login.tsx @@ -1,14 +1,13 @@ import React, { useState, useEffect } from "react"; import { useNavigate, useSearchParams } from "react-router-dom"; -import { Form, Input, Button, Toast, Tabs, Checkbox } from "antd-mobile"; +import { Form, Input, Button, Toast, Checkbox } from "antd-mobile"; import { EyeInvisibleOutline, EyeOutline, UserOutline, } from "antd-mobile-icons"; -import { useUserStore, useDeviceStore } from "@/store"; +import { useUserStore } from "@/store/module/user"; import { loginWithPassword, loginWithCode, sendVerificationCode } from "./api"; -import { updateDeviceCount } from "@/utils/device"; import style from "./login.module.scss"; const Login: React.FC = () => { @@ -22,7 +21,6 @@ const Login: React.FC = () => { const navigate = useNavigate(); const [searchParams] = useSearchParams(); const { login } = useUserStore(); - const { setDeviceCount } = useDeviceStore(); // 倒计时效果 useEffect(() => { @@ -44,17 +42,33 @@ const Login: React.FC = () => { // 发送验证码 const handleSendVerificationCode = async () => { + const account = form.getFieldValue("account"); + + if (!account) { + Toast.show({ content: "请输入手机号", position: "top" }); + return; + } + + // 手机号格式验证 + const phoneRegex = /^1[3-9]\d{9}$/; + if (!phoneRegex.test(account)) { + Toast.show({ content: "请输入正确的11位手机号", position: "top" }); + return; + } + try { - const phone = form.getFieldValue("phone"); - if (!phone) { - Toast.show({ content: "请输入手机号", position: "top" }); - return; - } - await sendVerificationCode(phone); - setCountdown(60); + setLoading(true); + await sendVerificationCode({ + mobile: account, + type: "login", + }); + Toast.show({ content: "验证码已发送", position: "top" }); - } catch (error: any) { - // 错误已在request中处理 + setCountdown(60); + } catch (error) { + // 错误已在request中处理,这里不需要额外处理 + } finally { + setLoading(false); } }; @@ -81,40 +95,32 @@ const Login: React.FC = () => { } console.log(response, "response"); + // 获取设备总数 + const deviceTotal = response.deviceTotal || 0; + console.log(deviceTotal, "deviceTotal"); + // 更新状态管理(token会自动存储到localStorage,用户信息存储在状态管理中) - login(response.token, response.member); + login(response.token, response.member, deviceTotal); Toast.show({ content: "登录成功", position: "top" }); - // 检查设备绑定状态并更新到store - try { - const deviceNum = await updateDeviceCount(setDeviceCount); - console.log(deviceNum, "deviceNum"); - - // 如果没有绑定设备,跳转到引导页面 - if (deviceNum === 0) { - navigate("/guide"); - return; - } - } catch (error) { - console.error("检查设备状态失败:", error); - // 如果检查失败,设置设备数量为0并跳转到guide页面 - setDeviceCount(0); - navigate("/guide"); - return; - } - - // 跳转到首页或重定向URL - const returnUrl = searchParams.get("returnUrl"); - if (returnUrl) { - const decodedUrl = decodeURIComponent(returnUrl); - if (isLoginPage(decodedUrl)) { - navigate("/"); + // 根据设备数量判断跳转 + if (deviceTotal > 0) { + // 有设备,跳转到首页或重定向URL + const returnUrl = searchParams.get("returnUrl"); + if (returnUrl) { + const decodedUrl = decodeURIComponent(returnUrl); + if (isLoginPage(decodedUrl)) { + navigate("/"); + } else { + window.location.href = decodedUrl; + } } else { - window.location.href = decodedUrl; + navigate("/"); } } else { - navigate("/"); + // 没有设备,跳转到引导页面 + navigate("/guide"); } } catch (error: any) { // 错误已在request中处理,这里不需要额外处理 diff --git a/nkebao/src/router/index.tsx b/nkebao/src/router/index.tsx index 7ff448cc..117681a7 100644 --- a/nkebao/src/router/index.tsx +++ b/nkebao/src/router/index.tsx @@ -1,7 +1,6 @@ import React from "react"; import { BrowserRouter, useRoutes, RouteObject } from "react-router-dom"; import PermissionRoute from "./permissionRoute"; -import DeviceGuard from "@/components/DeviceGuard"; // 动态导入所有 module 下的 ts/tsx 路由模块 const modules = import.meta.glob("./module/*.{ts,tsx}", { eager: true }); @@ -43,9 +42,7 @@ const AppRouter: React.FC = () => ( v7_relativeSplatPath: true, }} > - - - + ); diff --git a/nkebao/src/store/index.ts b/nkebao/src/store/index.ts index c74f8ad2..4eca24e3 100644 --- a/nkebao/src/store/index.ts +++ b/nkebao/src/store/index.ts @@ -1,3 +1,2 @@ export * from "./module/user"; -export * from "./module/device"; // 未来可继续合并其他模块 diff --git a/nkebao/src/store/module/device.ts b/nkebao/src/store/module/device.ts deleted file mode 100644 index 53477263..00000000 --- a/nkebao/src/store/module/device.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { createPersistStore } from "@/store/createPersistStore"; - -export interface DeviceState { - deviceCount: number; - setDeviceCount: (count: number) => void; - updateDeviceCount: () => Promise; - resetDeviceCount: () => void; -} - -export const useDeviceStore = createPersistStore( - (set, get) => ({ - deviceCount: 0, - setDeviceCount: (count: number) => set({ deviceCount: count }), - updateDeviceCount: async () => { - try { - // 这里需要导入getDashboard,但为了避免循环依赖,我们通过参数传入 - // 实际使用时会在组件中调用并传入API函数 - set({ deviceCount: 0 }); // 默认设置为0,实际值由调用方设置 - } catch (error) { - console.error("更新设备数量失败:", error); - set({ deviceCount: 0 }); - } - }, - resetDeviceCount: () => set({ deviceCount: 0 }), - }), - "device-store", - state => ({ - deviceCount: state.deviceCount, - }), -); diff --git a/nkebao/src/store/module/user.ts b/nkebao/src/store/module/user.ts index a26c3e58..bee4f4c6 100644 --- a/nkebao/src/store/module/user.ts +++ b/nkebao/src/store/module/user.ts @@ -15,6 +15,7 @@ export interface User { updateTime: string | null; lastLoginIp: string; lastLoginTime: number; + deviceTotal: number; // 设备总数 } interface UserState { @@ -24,7 +25,7 @@ interface UserState { setUser: (user: User) => void; setToken: (token: string) => void; clearUser: () => void; - login: (token: string, userInfo: User) => void; + login: (token: string, userInfo: User, deviceTotal: number) => void; logout: () => void; } @@ -36,7 +37,7 @@ export const useUserStore = createPersistStore( setUser: user => set({ user, isLoggedIn: true }), setToken: token => set({ token }), clearUser: () => set({ user: null, token: null, isLoggedIn: false }), - login: (token, userInfo) => { + login: (token, userInfo, deviceTotal) => { // 只将token存储到localStorage localStorage.setItem("token", token); @@ -56,6 +57,7 @@ export const useUserStore = createPersistStore( updateTime: userInfo.updateTime, lastLoginIp: userInfo.lastLoginIp, lastLoginTime: userInfo.lastLoginTime, + deviceTotal: deviceTotal, }; set({ user, token, isLoggedIn: true }); }, diff --git a/nkebao/src/utils/device.ts b/nkebao/src/utils/device.ts deleted file mode 100644 index 8b5c5b8c..00000000 --- a/nkebao/src/utils/device.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { getDashboard } from "@/pages/mobile/home/api"; - -/** - * 更新设备数量到store - * @param setDeviceCount store中的setDeviceCount函数 - * @returns 更新后的设备数量 - */ -export const updateDeviceCount = async ( - setDeviceCount: (count: number) => void, -): Promise => { - try { - const dashboardData = await getDashboard(); - const deviceCount = dashboardData?.deviceNum || 0; - setDeviceCount(deviceCount); - return deviceCount; - } catch (error) { - console.error("更新设备数量失败:", error); - setDeviceCount(0); - return 0; - } -}; - -/** - * 检查是否需要设备绑定 - * @param deviceCount 设备数量 - * @returns 是否需要设备绑定 - */ -export const needsDeviceBinding = (deviceCount: number): boolean => { - return deviceCount === 0; -};