| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'
- import Taro from '@tarojs/taro'
- import { talentAuthClient } from '../api'
- import type { InferResponseType } from 'hono'
- export interface TalentUserInfo {
- userId: number
- username: string
- userType: 'talent'
- personId?: number
- phone?: string | null
- nickname?: string | null
- name?: string | null
- // 从 disabled_person 表获取的人才详情
- personInfo?: {
- personId: number
- name: string
- disabilityType: string
- idCard: string
- disabilityId: string
- phone: string
- province: string
- city: string
- district?: string | null
- detailedAddress?: string | null
- jobStatus: number
- }
- }
- export interface AuthContextType {
- isLoggedIn: boolean
- user: TalentUserInfo | null
- token: string | null
- login: (identifier: string, password: string) => Promise<void>
- logout: () => Promise<void>
- refreshUser: () => Promise<void>
- loading: boolean
- }
- const AuthContext = createContext<AuthContextType | undefined>(undefined)
- const TOKEN_KEY = 'talent_token'
- const USER_KEY = 'talent_user'
- export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
- const [isLoggedIn, setIsLoggedIn] = useState(false)
- const [user, setUser] = useState<TalentUserInfo | null>(null)
- const [token, setToken] = useState<string | null>(null)
- const [loading, setLoading] = useState(true)
- // 初始化:从本地存储恢复登录状态
- useEffect(() => {
- const initAuth = async () => {
- try {
- const storedToken = Taro.getStorageSync(TOKEN_KEY)
- const storedUser = Taro.getStorageSync(USER_KEY)
- if (storedToken && storedUser) {
- setToken(storedToken)
- setUser(storedUser)
- setIsLoggedIn(true)
- }
- } catch (error) {
- console.debug('恢复登录状态失败:', error)
- } finally {
- setLoading(false)
- }
- }
- initAuth()
- }, [])
- // 类型定义:登录响应
- type LoginResponse = InferResponseType<typeof talentAuthClient.login.$post, 200>
- const login = async (identifier: string, password: string): Promise<void> => {
- setLoading(true)
- try {
- // 调用登录API
- const response = await talentAuthClient.login.$post({
- body: {
- identifier: identifier.trim(),
- password: password.trim()
- }
- })
- // 转换API响应为UserInfo格式
- const userInfo: TalentUserInfo = {
- userId: response.user.id,
- username: response.user.username,
- userType: 'talent',
- personId: response.user.personId || undefined,
- phone: response.user.phone,
- nickname: response.user.nickname,
- name: response.user.name,
- personInfo: response.user.personInfo ? {
- personId: response.user.personInfo.id,
- name: response.user.personInfo.name,
- disabilityType: response.user.personInfo.disabilityType,
- idCard: response.user.personInfo.idCard,
- disabilityId: response.user.personInfo.disabilityId,
- phone: response.user.personInfo.phone,
- province: response.user.personInfo.province,
- city: response.user.personInfo.city,
- district: response.user.personInfo.district,
- detailedAddress: response.user.personInfo.detailedAddress,
- jobStatus: response.user.personInfo.jobStatus,
- } : undefined
- }
- // 保存到本地存储
- Taro.setStorageSync(TOKEN_KEY, response.token)
- Taro.setStorageSync(USER_KEY, userInfo)
- setToken(response.token)
- setUser(userInfo)
- setIsLoggedIn(true)
- } catch (error: any) {
- console.error('登录失败:', error)
- // 提取错误消息
- const errorMessage = error?.message || '登录失败,请稍后重试'
- throw new Error(errorMessage)
- } finally {
- setLoading(false)
- }
- }
- const logout = async (): Promise<void> => {
- try {
- // TODO: 调用退出API
- // await talentAuthClient.logout.$post()
- // 清除本地存储
- Taro.removeStorageSync(TOKEN_KEY)
- Taro.removeStorageSync(USER_KEY)
- setToken(null)
- setUser(null)
- setIsLoggedIn(false)
- // 跳转到登录页
- Taro.reLaunch({ url: '/pages/login/index' })
- } catch (error) {
- console.error('退出失败:', error)
- throw error
- }
- }
- const refreshUser = async (): Promise<void> => {
- if (!token) return
- try {
- // 调用获取用户信息API
- const response = await talentAuthClient.me.$get()
- // 转换API响应为UserInfo格式
- const userInfo: TalentUserInfo = {
- userId: response.id,
- username: response.username,
- userType: 'talent',
- personId: response.personId || undefined,
- phone: response.phone,
- nickname: response.nickname,
- name: response.name,
- personInfo: response.personInfo ? {
- personId: response.personInfo.id,
- name: response.personInfo.name,
- disabilityType: response.personInfo.disabilityType,
- idCard: response.personInfo.idCard,
- disabilityId: response.personInfo.disabilityId,
- phone: response.personInfo.phone,
- province: response.personInfo.province,
- city: response.personInfo.city,
- district: response.personInfo.district,
- detailedAddress: response.personInfo.detailedAddress,
- jobStatus: response.personInfo.jobStatus,
- } : undefined
- }
- // 更新本地存储
- Taro.setStorageSync(USER_KEY, userInfo)
- setUser(userInfo)
- } catch (error) {
- console.error('刷新用户信息失败:', error)
- throw error
- }
- }
- return (
- <AuthContext.Provider
- value={{
- isLoggedIn,
- user,
- token,
- login,
- logout,
- refreshUser,
- loading,
- }}
- >
- {children}
- </AuthContext.Provider>
- )
- }
- export const useAuth = (): AuthContextType => {
- const context = useContext(AuthContext)
- if (context === undefined) {
- throw new Error('useAuth must be used within an AuthProvider')
- }
- return context
- }
- export default AuthContext
|