feat: 初始提交

This commit is contained in:
siujamo
2025-12-25 16:12:01 +08:00
commit faff32475f
77 changed files with 6123 additions and 0 deletions
View File
+29
View File
@@ -0,0 +1,29 @@
import type { IPublicClientApplication } from "@azure/msal-browser"
import * as AuthApi from "@/api/auth"
import type { AppDispatch } from "@/store"
import { loginSuccess } from "@/store/auth-slice"
/**
* Login with Microsoft Entra ID.
*
* @param instance Microsoft Entra ID application instance
* @param dispatch app dispatcher
* @param onSuccess callback when login succeeded
*/
export async function doMsalLogin(
instance: IPublicClientApplication,
dispatch: AppDispatch,
onSuccess?: () => void
) {
try {
const response = await instance.loginPopup({
scopes: ["openid", "profile", "email"],
})
const { accessToken, user } = await AuthApi.msalLogin(response.idToken)
dispatch(loginSuccess({ user, token: accessToken }))
if (onSuccess) onSuccess()
} catch (err) {
console.error("MSAL login failed", err)
}
}
+38
View File
@@ -0,0 +1,38 @@
import axios, { type AxiosError } from "axios"
import dayjs from "dayjs"
import store from "@/store"
import type { GeneralErrorResponse } from "@/types"
import { HttpStatus } from "@/constant"
import { logout } from "@/store/auth-slice"
const webClient = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: dayjs.duration({ seconds: 10 }).asMilliseconds(),
})
webClient.interceptors.request.use(
(config) => {
const state = store.getState()
if (state.auth.isAuthenticated) {
config.headers["Authorization"] = `Bearer ${state.auth.token!}`
}
return config
},
(error: unknown) => {
console.log(error)
return Promise.reject(new Error("请求错误,请稍后再试"))
}
)
webClient.interceptors.response.use((response) => {
return response
}, (error: unknown) => {
const err = error as AxiosError<GeneralErrorResponse>
if (err.response?.status == HttpStatus.UNAUTHORIZED) {
store.dispatch(logout())
}
return Promise.reject(error as AxiosError)
})
export default webClient