Ver código fonte

Merge remote-tracking branch 'upstream/mini-multi-tenant-mall' into mini-multi-tenant-mall

yourname 1 mês atrás
pai
commit
620c667bb2
2 arquivos alterados com 86 adições e 86 exclusões
  1. 5 2
      mini/src/app.tsx
  2. 81 84
      mini/src/utils/auth.tsx

+ 5 - 2
mini/src/app.tsx

@@ -2,11 +2,14 @@ import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only';
 import '@/utils/headers-polyfill.js'
 import { PropsWithChildren } from 'react'
 import { useLaunch } from '@tarojs/taro'
-import { QueryClientProvider } from '@tanstack/react-query'
-import { AuthProvider, queryClient } from './utils/auth'
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
+import { AuthProvider } from './utils/auth'
 
 import './app.css'
 
+// 创建新的 QueryClient 实例
+const queryClient = new QueryClient()
+
 function App({ children }: PropsWithChildren<any>) {
   useLaunch(() => {
     console.log('App launched.')

+ 81 - 84
mini/src/utils/auth.tsx

@@ -1,8 +1,9 @@
-import { createContext, useContext, PropsWithChildren } from 'react'
+import { createContext, useContext, PropsWithChildren, useState } from 'react'
 import Taro, { useLaunch } from '@tarojs/taro'
 import { authClient } from '../api'
 import { InferResponseType, InferRequestType } from 'hono'
-import { QueryClient, useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
+import { useMutation } from '@tanstack/react-query'
+import { isWeapp, isH5 } from './platform'
 
 // 用户类型定义
 export type User = InferResponseType<typeof authClient.me.$get, 200>
@@ -22,73 +23,92 @@ interface AuthContextType {
 
 const AuthContext = createContext<AuthContextType | undefined>(undefined)
 
-const queryClient = new QueryClient()
-
 export const AuthProvider: React.FC<PropsWithChildren> = ({ children }) => {
-  const queryClient = useQueryClient()
 
-  const { data: user, isLoading } = useQuery<User | null, Error>({
-    queryKey: ['currentUser'],
-    queryFn: async () => {
-      const token = Taro.getStorageSync('mini_token')
-      if (!token) {
-        return null
-      }
+  // 用户状态
+  const [user, setUser] = useState<User | null>(() => {
+    // 从本地存储初始化用户信息
+    const userInfoStr = Taro.getStorageSync('userInfo')
+    if (userInfoStr) {
       try {
-        const response = await authClient.me.$get({})
-        if (response.status !== 200) {
-          throw new Error('获取用户信息失败')
-        }
-        const user = await response.json()
-        Taro.setStorageSync('userInfo', JSON.stringify(user))
-        return user
-      } catch (error) {
-        Taro.removeStorageSync('mini_token')
-        Taro.removeStorageSync('userInfo')
+        return JSON.parse(userInfoStr)
+      } catch {
         return null
       }
-    },
-    staleTime: Infinity, // 用户信息不常变动,设为无限期
-    refetchOnWindowFocus: false, // 失去焦点不重新获取
-    refetchOnReconnect: false, // 网络重连不重新获取
+    }
+    return null
   })
 
-  // 静默登录mutation - 应用启动时自动尝试登录
-  const silentLoginMutation = useMutation<MiniLoginUser | null, Error, void>({
-    mutationFn: async () => {
-      try {
-        // 尝试静默登录
-        const loginRes = await Taro.login()
-        if (!loginRes.code) {
-          return null // 静默登录失败,但不抛出错误
-        }
-
-        // 使用小程序code进行静默登录
-        const response = await authClient['mini-login'].$post({
-          json: {
-            code: loginRes.code,
-            // 静默登录不请求用户信息
-            tenantId: Number(process.env.TARO_APP_TENANT_ID) || 1
+  // 获取用户信息的通用函数
+  const fetchUserInfo = async (): Promise<User | null> => {
+    // const token = Taro.getStorageSync('mini_token')
+    // if (!token) {
+    //   return null
+    // }
+    try {
+      const response = await authClient.me.$get({})
+      if (response.status !== 200) {
+        throw new Error('获取用户信息失败')
+      }
+      const user = await response.json()
+      Taro.setStorageSync('userInfo', JSON.stringify(user))
+      return user
+    } catch (error) {
+      // Token失效时的处理逻辑
+      console.debug('Token失效,开始处理重新登录逻辑')
+
+      if (isWeapp()) {
+        // 小程序环境:使用静默登录重新获取token
+        console.debug('小程序环境,尝试静默登录')
+        try {
+          const loginRes = await Taro.login()
+          if (loginRes.code) {
+            const response = await authClient['mini-login'].$post({
+              json: {
+                code: loginRes.code,
+                tenantId: Number(process.env.TARO_APP_TENANT_ID) || 1
+              }
+            })
+
+            if (response.status === 200) {
+              const { token: newToken } = await response.json()
+              Taro.setStorageSync('mini_token', newToken)
+
+              // 重新获取完整的用户信息
+              const meResponse = await authClient.me.$get({})
+              if (meResponse.status === 200) {
+                const user = await meResponse.json()
+                Taro.setStorageSync('userInfo', JSON.stringify(user))
+                console.debug('静默登录成功,返回新用户信息')
+                return user
+              }
+            }
           }
-        })
-
-        if (response.status === 200) {
-          const { token, user } = await response.json()
-          Taro.setStorageSync('mini_token', token)
-          Taro.setStorageSync('userInfo', JSON.stringify(user))
-          return user
+        } catch (silentLoginError) {
+          console.debug('静默登录失败:', silentLoginError)
         }
-
-        return null // 静默登录失败
-      } catch (error) {
-        // 静默登录失败不抛出错误,不影响用户体验
-        console.debug('静默登录失败:', error)
-        return null
+      } else if (isH5()) {
+        // H5环境:跳转到登录页
+        console.debug('H5环境,跳转到登录页')
+        Taro.redirectTo({ url: '/pages/login/index' })
       }
+
+      // 如果重新登录失败或不是小程序环境,清除token并返回null
+      Taro.removeStorageSync('mini_token')
+      Taro.removeStorageSync('userInfo')
+      return null
+    }
+  }
+
+  // 静默登录mutation - 应用启动时自动尝试登录
+  const silentLoginMutation = useMutation<User | null, Error, void>({
+    mutationFn: async () => {
+      // 使用统一的用户信息获取函数
+      return await fetchUserInfo()
     },
     onSuccess: (user) => {
       if (user) {
-        queryClient.setQueryData(['currentUser'], user)
+        setUser(user)
       }
     }
   })
@@ -113,7 +133,7 @@ export const AuthProvider: React.FC<PropsWithChildren> = ({ children }) => {
       return user
     },
     onSuccess: (newUser) => {
-      queryClient.setQueryData(['currentUser'], newUser)
+      setUser(newUser)
     },
     onError: (error) => {
       Taro.showToast({
@@ -136,7 +156,7 @@ export const AuthProvider: React.FC<PropsWithChildren> = ({ children }) => {
       return user
     },
     onSuccess: (newUser) => {
-      queryClient.setQueryData(['currentUser'], newUser)
+      setUser(newUser)
     },
     onError: (error) => {
       Taro.showToast({
@@ -162,7 +182,7 @@ export const AuthProvider: React.FC<PropsWithChildren> = ({ children }) => {
       }
     },
     onSuccess: () => {
-      queryClient.setQueryData(['currentUser'], null)
+      setUser(null)
       Taro.redirectTo({ url: '/pages/login/index' })
     },
     onError: (error) => {
@@ -185,7 +205,7 @@ export const AuthProvider: React.FC<PropsWithChildren> = ({ children }) => {
       return updatedUser
     },
     onSuccess: (updatedUser) => {
-      queryClient.setQueryData(['currentUser'], updatedUser)
+      setUser(updatedUser)
       Taro.showToast({
         title: '更新成功',
         icon: 'success',
@@ -203,27 +223,6 @@ export const AuthProvider: React.FC<PropsWithChildren> = ({ children }) => {
 
   const updateUser = updateUserMutation.mutateAsync
 
-  // // 使用React Query获取用户信息
-  // const { data: user } = useQuery<User | null>({
-  //   queryKey: ['currentUser'],
-  //   queryFn: async () => {
-  //     // 直接从本地存储获取用户信息
-  //     const userInfoStr = Taro.getStorageSync('userInfo')
-  //     if (userInfoStr) {
-  //       try {
-  //         return JSON.parse(userInfoStr)
-  //       } catch {
-  //         return null
-  //       }
-  //     }
-  //     return null
-  //   },
-  //   staleTime: Infinity, // 用户信息不常变动,设为无限期
-  //   refetchOnWindowFocus: false, // 失去焦点不重新获取
-  //   refetchOnReconnect: false, // 网络重连不重新获取
-  //   enabled: false, // 不自动执行,由静默登录和登录mutation更新
-  // })
-
   const value = {
     user: user || null,
     login: loginMutation.mutateAsync,
@@ -243,6 +242,4 @@ export const useAuth = () => {
     throw new Error('useAuth must be used within an AuthProvider')
   }
   return context
-}
-
-export { queryClient }
+}