请求封装
在composables文件夹下新建useHttp.ts
import { ElMessage } from 'element-plus'
import type { FetchResponse, SearchParameters } from 'ofetch'
export interface ResOptions<T> {
data: T
code: number
message: string
success: boolean
}
const handleError = <T>(response: FetchResponse<ResOptions<T>> & FetchResponse<ResponseType>) => {
const err = (text: string) => {
ElMessage.error(response?._data?.message ?? text)
}
if (!response._data) {
err('请求超时,服务器无响应!')
return
}
const userStore = useUserStore()
const handleMap: { [key: number]: () => void } = {
404: () => err('服务器资源不存在'),
500: () => err('服务器内部错误'),
403: () => err('没有权限访问该资源'),
401: () => {
err('登录状态已过期,需要重新登录')
userStore.value.userInfo = null
// TODO 跳转实际登录页
navigateTo('/login')
},
}
handleMap[response.status] ? handleMap[response.status]() : err('未知错误!')
}
// get方法传递数组形式参数
const paramsSerializer = (params?: SearchParameters) => {
if (!params)
return
const query = params
Object.entries(query).forEach(([key, val]) => {
if (typeof val === 'object' && Array.isArray(val) && val !== null) {
query[`${key}[]`] = toRaw(val).map((v: any) => JSON.stringify(v))
delete query[key]
}
})
return query
}
const fetch = $fetch.create({
// 请求拦截器
onRequest({ options }) {
// get方法传递数组形式参数
options.params = paramsSerializer(options.params)
// 添加baseURL,nuxt3环境变量要从useRuntimeConfig里面取
const { public: { apiBase } } = useRuntimeConfig()
options.baseURL = apiBase
// 添加请求头,没登录不携带token
const userStore = useUserStore()
if (!userStore.value.isLogin)
return
options.headers = new Headers(options.headers)
options.headers.set('Authorization', `Bearer ${userStore.value.getToken()}`)
},
// 响应拦截
onResponse({ response }) {
if (response.status === 200){
return response
}else{
handleError(response)
return Promise.reject(response._data)
}
// 成功返回
return response._data
},
// 错误处理
onResponseError({ response }) {
handleError(response)
return Promise.reject(response?._data ?? null)
},
})
// 自动导出
export const useHttp = {
get: <T>(url: string, params?: any) => {
return fetch<T>(url, { method: 'get', params })
},
post: <T>(url: string, body?: any) => {
return fetch<T>(url, { method: 'post', body })
},
put: <T>(url: string, body?: any) => {
return fetch<T>(url, { method: 'put', body })
},
delete: <T>(url: string, body?: any) => {
return fetch<T>(url, { method: 'delete', body })
},
}
用户登录状态管理
import { login } from '~/api/login'
interface user{
/**是否登录 */
isLogin: Boolean,
/**获取保存的token */
getToken: Function,
/**保存token */
setToken: Function,
/**用户信息 */
userInfo: any,
/**用户登录 */
login: Function,
/**获取用户信息 */
getCurrentUser: Function,
/**退出登录 */
logout: Function,
}
export const useUserStore = () => useState<user>('useUserStore',()=>({
isLogin:false,
getToken: ()=>{
return localStorage.getItem('token')
},
setToken: (e: string)=>{
localStorage.setItem('token',e)
},
userInfo: {},
login:(e: Object)=>{
return loginApi(e)
},
getCurrentUser:()=>{
getUserInfo()
},
logout:()=>{
logout()
}
})
)
// 获取用户信息
function getUserInfo(){
useUserStore().value.isLogin = true
useUserStore().value.userInfo = {
name: '张三',
age: 18
}
}
// 退出登录
function logout(){
useUserStore().value.isLogin = false
useUserStore().value.userInfo = {}
localStorage.removeItem('token')
}
// 登录
function loginApi(e: Object) {
return new Promise((resolve, reject) => {
login(e).then((result: any) => {
resolve(result)
}).catch((err: any) => {
reject(err)
});
})
}