blob: 289ce1656507389d732207b1d247620726d9317f [file] [log] [blame]
// src/feature/auth/authSlice.ts
import { createAsyncThunk, createSlice, type PayloadAction } from "@reduxjs/toolkit";
import type { AuthState } from "./types";
import type { LoginRequest } from "../../api/Auth/type";
import AuthAPI from "../../api/Auth/AuthApi";
// 获取本地存储的 token
const storedToken = localStorage.getItem('token');
const initialState: AuthState = {
token: storedToken || '',
loading: false,
isAuth: !!storedToken, // 如果有token就设为true
error: '',
};
export const loginUser = createAsyncThunk<
{token: string},
LoginRequest,
{ rejectValue: string }
>(
'auth/login',
async (loginRequest: LoginRequest, { rejectWithValue }) => {
try {
const response = await AuthAPI.login(loginRequest);
if(response.data.code == 0) {
return {token: response.data.data};
}
else
return rejectWithValue(response.data.message);
} catch {
return rejectWithValue('登录失败');
}
}
);
// 新增:从localStorage恢复登录状态
export const loginFromLocalStorage = createAsyncThunk<
{token: string} | {empty: true},
void,
{ rejectValue: string }
>(
'auth/loginFromLocalStorage',
async (_, { rejectWithValue, dispatch }) => {
try {
const token = localStorage.getItem('token');
if (!token) {
// 返回空状态而不是错误
return { empty: true };
}
// 直接使用refreshToken来验证token有效性
const result = await dispatch(refreshToken(token));
if (refreshToken.fulfilled.match(result)) {
// refresh成功,返回新的token
return { token: result.payload.token };
} else {
// refresh失败,token无效
localStorage.removeItem('token');
return rejectWithValue('token已失效,需要重新登录');
}
} catch {
localStorage.removeItem('token');
return rejectWithValue('恢复登录状态失败');
}
}
);
export const refreshToken = createAsyncThunk<
{token: string},
string,
{ rejectValue: string }
>(
'auth/refresh',
async (oldToken: string, { rejectWithValue }) => {
try {
const response = await AuthAPI.refreshToken(oldToken);
if(response.data.code == 0)
return {token: response.data.data};
else
return rejectWithValue(response.data.message);
} catch {
return rejectWithValue('刷新失败');
}
}
);
const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
logout: (state) => {
state.token = '';
state.isAuth = false;
localStorage.clear();
},
// 清除错误信息
clearError: (state) => {
state.error = '';
},
},
extraReducers: (builder) => {
// 处理普通登录的异步操作
builder
.addCase(loginUser.pending, (state) => {
state.loading = true;
state.error = '';
})
.addCase(loginUser.fulfilled, (state, action: PayloadAction<{token: string}>) => {
state.loading = false;
state.token = action.payload.token;
state.isAuth = true;
localStorage.setItem('token', state.token);
})
.addCase(loginUser.rejected, (state, action) => {
state.loading = false;
state.error = action.payload ? action.payload : '';
});
// 处理从localStorage恢复登录状态
builder
.addCase(loginFromLocalStorage.pending, (state) => {
state.loading = true;
state.error = '';
})
.addCase(loginFromLocalStorage.fulfilled, (state, action) => {
state.loading = false;
if ('token' in action.payload) {
// 有token的情况
state.token = action.payload.token;
state.isAuth = true;
} else {
// 空token的情况
state.token = '';
state.isAuth = false;
}
})
.addCase(loginFromLocalStorage.rejected, (state, action) => {
state.loading = false;
state.token = '';
state.isAuth = false;
state.error = action.payload ? action.payload : '';
localStorage.removeItem('token');
});
// 处理刷新 token 的异步操作
builder
.addCase(refreshToken.pending, (state) => {
state.loading = true;
state.error = '';
})
.addCase(refreshToken.fulfilled, (state, action) => {
state.loading = false;
state.token = action.payload.token;
state.isAuth = true;
localStorage.setItem('token', state.token);
})
.addCase(refreshToken.rejected, (state, action) => {
state.loading = false;
state.error = action.payload ? action.payload : '';
state.isAuth = false;
});
},
});
export const { logout, clearError } = authSlice.actions;
export default authSlice.reducer;