MineAdmin 交流群

官方QQ群: 150105478

Skip to content

請求與攔截器

MineAdmin基於 axios 作為請求庫,同時提供了請求攔截器,方便開發者對請求進行統一處理。

請求

説明

系統內封裝了兩種請求處理:

  • 一種僅對 MineAdmin 後端的請求封裝,只適合 MineAdmin後端
  • 一種是可請求外部網絡或者其他後端接口的封裝。

使用

在前端全局任何位置,且無需顯性加載,即可使用 useHttp(),注意,這個方式僅對 MineAdmin 後端有效

ts
// 獲取請求實例
const http = useHttp()

// get 請求
http.get('/xxxx?id=1')
// post 請求
http.post('/xxxx', { username: 'test' })
// put 請求
http.put('/xxxx/1', { other: 'update' })
// delete 請求
http.delete('/xxxx/2')

以上請求,系統會自動處理 tokenerror 等,開發者無需關心, 如果需要傳入其他配置,例如: headertimeout 等參數,只需要在後面加參數傳入即可。

token刷新

useHttp() 內部已經封裝了自動續期 token 功能,具體原理可查看 後端文檔 這裏不再贅述。

請求外部網絡

以上都是針對 MineAdmin 後端請求的説明,外部網絡請求方式如下:

ts
import request from '@/utils/http'

const { createHttp } = request

// 設置baseurl 和 其他參數
const http = createHttp('https://www.baidu.com', {
  header: {
    'user-agent': 'Windows NT',
  }
})

const requestHome = async () => {
  return await http.get('/')
}

console.log(requestHome())

攔截器

MineAdmin 已經封裝了攔截器,但需要説明只適配 MineAdmin 的後端接口,如果需要調整、修改,打開 src/utils/http.ts 文件 找到下面這段代碼:

ts
http.interceptors.response.use(
  async (response: AxiosResponse): Promise<any> => {
    isLoading.value = false
    const userStore = useUserStore()
    await usePluginStore().callHooks('networkResponse', response)
    const config = response.config
    if ((response.request.responseType === 'blob'
        || response.request.responseType === 'arraybuffer')
      && !/^application\/json/.test(response.headers['content-type'])
      && response.status === ResultCode.SUCCESS
    ) {
      return Promise.resolve(response.data)
    }

    if (response?.data?.code === ResultCode.SUCCESS) {
      return Promise.resolve(response.data)
    }
    else {
      switch (response?.data?.code) {
        case ResultCode.UNAUTHORIZED: {
          const logout = useDebounceFn(
            async () => {
              Message.error('登錄狀態已過期,需要重新登錄', { zIndex: 9999 })
              await useUserStore().logout()
            },
            3000,
            { maxWait: 5000 },
          )
          // 檢查token是否需要刷新
          if (userStore.isLogin && !isRefreshToken.value) {
            isRefreshToken.value = true
            if (!cache.get('refresh_token')) {
              await logout()
              break
            }

            try {
              const refreshTokenResponse = await createHttp(null, {
                headers: {
                  Authorization: `Bearer ${cache.get('refresh_token')}`,
                },
              }).post('/admin/passport/refresh')

              if (refreshTokenResponse.data.code !== 200) {
                await logout()
                break
              }
              else {
                const { data } = refreshTokenResponse.data
                userStore.token = data.access_token
                cache.set('token', data.access_token)
                cache.set('expire', useDayjs().unix() + data.expire_at, { exp: data.expire_at })
                cache.set('refresh_token', data.refresh_token)

                config.headers!.Authorization = `Bearer ${userStore.token}`
                requestList.value.map((cb: any) => cb())
                requestList.value = []
                return http(config)
              }
            }
              // eslint-disable-next-line unused-imports/no-unused-vars
            catch (e: any) {
              requestList.value.map((cb: any) => cb())
              await logout()
              break
            }
            finally {
              requestList.value = []
              isRefreshToken.value = false
            }
          }
          else {
            return new Promise((resolve) => {
              requestList.value.push(() => {
                config.headers!.Authorization = `Bearer ${cache.get('token')}`
                resolve(http(config))
              })
            })
          }
        }
        case ResultCode.NOT_FOUND:
          Message.error('服務器資源不存在', { zIndex: 9999 })
          break
        case ResultCode.FORBIDDEN:
          Message.error('沒有權限訪問此接口', { zIndex: 9999 })
          break
        case ResultCode.METHOD_NOT_ALLOWED:
          Message.error('請求方法不被允許', { zIndex: 9999 })
          break
        case ResultCode.FAIL:
          Message.error('服務器內部錯誤', { zIndex: 9999 })
          break
        default:
          Message.error(response?.data?.message ?? '未知錯誤', { zIndex: 9999 })
          break
      }

      return Promise.reject(response.data ? response.data : null)
    }
  },
  async (error: any) => {
    isLoading.value = false
    const serverError = useDebounceFn(async () => {
      if (error && error.response && error.response.status === 500) {
        Message.error(error.message ?? '服務器內部錯誤', { zIndex: 9999 })
      }
    }, 3000, { maxWait: 5000 })
    await serverError()
    return Promise.reject(error)
  },
)

致力于为品牌和企业创造价值