fresh available

This commit is contained in:
felinae98
2021-12-15 22:29:54 +08:00
parent 56397bc270
commit 866e4cd2fb
15 changed files with 219 additions and 76 deletions
@@ -0,0 +1,35 @@
import {CaseReducer, createAsyncThunk, createSlice, PayloadAction} from "@reduxjs/toolkit";
import {getGlobalConf as getGlobalConfApi} from "src/api/config";
import {GlobalConf} from "src/utils/type";
import {RootState} from ".";
const initialState: GlobalConf = {
platformConf: {},
loaded: false
}
const setGlobalConf: CaseReducer<GlobalConf, PayloadAction<GlobalConf>> = (_, action) => {
return {...action.payload, loaded: true}
}
export const getGlobalConf = createAsyncThunk(
"globalConf/set",
getGlobalConfApi,
{
condition: (_, { getState }) => !(getState() as RootState).globalConf.loaded
}
);
export const globalConfSlice = createSlice({
name: "globalConf",
initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(getGlobalConf.fulfilled, setGlobalConf)
}
})
export const platformConfSelector = (state: RootState) => state.globalConf.platformConf
export default globalConfSlice.reducer
+5
View File
@@ -0,0 +1,5 @@
import {TypedUseSelectorHook, useDispatch, useSelector} from "react-redux";
import {AppDispatch, RootState} from ".";
export const useAppDispacher = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
+15
View File
@@ -0,0 +1,15 @@
import {configureStore} from "@reduxjs/toolkit";
import loginSlice from "./loginSlice";
import globalConfSlice from "./globalConfSlice";
const store = configureStore({
reducer: {
login: loginSlice,
globalConf: globalConfSlice,
}
})
export default store;
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
+99
View File
@@ -0,0 +1,99 @@
import { AnyAction, CaseReducer, createAsyncThunk, createSlice, PayloadAction, ThunkAction } from "@reduxjs/toolkit";
import jwt_decode from 'jwt-decode';
import { LoginStatus, TokenResp } from "src/utils/type";
import { auth } from "src/api/config";
import {RootState} from ".";
const initialState: LoginStatus = {
login: false,
type: '',
name: '',
id: '123',
// groups: [],
token: '',
failed: false
}
interface storedInfo {
type: string
name: string
id: string
}
const loginAction: CaseReducer<LoginStatus, PayloadAction<TokenResp>> = (_, action) => {
return {
login: true,
failed: false,
type: action.payload.type,
name: action.payload.name,
id: action.payload.id,
token: action.payload.token
}
}
export const login = createAsyncThunk(
"auth/login",
async (code: string) => {
let res = await auth(code);
if (res.status !== 200) {
throw Error("Login Error")
} else {
localStorage.setItem('loginInfo', JSON.stringify({
'type': res.type,
'name': res.name,
id: res.id,
}))
localStorage.setItem('token', res.token)
}
return res
},
{
condition: (_: string, { getState }) => {
const { login } = getState() as { login: LoginStatus }
return !login.login;
}
}
)
export const loginSlice = createSlice({
name: 'auth',
initialState,
reducers: {
doLogin: loginAction
},
extraReducers: (builder) => {
builder.addCase(login.fulfilled, loginAction);
builder.addCase(login.rejected, (stat) => {
stat.failed = true
})
}
})
export const { doLogin } = loginSlice.actions
export const loadLoginState = (): ThunkAction<void, RootState, unknown, AnyAction> =>
(dispatch, getState) => {
if (getState().login.login) {
return
}
const infoJson = localStorage.getItem('loginInfo')
const jwtToken = localStorage.getItem('token');
if (infoJson && jwtToken) {
const decodedJwt = jwt_decode(jwtToken) as { exp: number };
if (decodedJwt.exp < Date.now() / 1000) {
return
}
const info = JSON.parse(infoJson) as storedInfo
const payload: TokenResp = {
...info,
status: 200,
token: jwtToken,
}
dispatch(doLogin(payload))
}
}
export const loginSelector = (state: RootState) => state.login
export default loginSlice.reducer