uniapp请求接口封装

发布于:2025-06-12 ⋅ 阅读:(21) ⋅ 点赞:(0)

前言:

        uniapp请求接口封装

实现效果:

实现代码:

核心:request.js
// 是否为本地环境
const isDev = process.env.NODE_ENV === 'development'

// 默认配置
const defaultOptions = {
  baseURL: isDev ? 'https://xxxxx' : '',
  timeout: 15000, // 请求接口超时时间
  dataType: 'json',
  header: {
    'Content-Type': 'application/json'
  },
  showErrToast: true,
  loading: true
}

// 请求核心方法
const request = async (method, url, data = {}, customOptions = {}) => {
  // 合并配置
  const options = {
    ...defaultOptions,
    method,
    data,
  }
  // 请求接口地址处理,如果传来http/https的直接用传来的地址
  if( url.startsWith('http') ||  url.startsWith('https')){
	  options.url = url
  } else {
	  options.url = `${defaultOptions.baseURL}${url}`
  }

  // 请求拦截
  const token = uni.getStorageSync('token')
  if (token) {
    options.header.Authorization = `Bearer ${token}`
  }

  // 显示 Loading
  if (options.loading) {
    uni.showLoading({ title: '加载中...', mask: true })
  }

  
	// 自定义header
	if(customOptions.header){
		options.header = Object.assign(options.header,customOptions.header)
	}

  return new Promise((resolve, reject) => {
    uni.request({
      ...options,
      success: (res) => {
        try {
          const processedRes = responseInterceptor(res)
          resolve(processedRes.data)
        } catch (error) {
          reject(error)
        }
      },
      fail: (err) => {
        console.error('[Request Fail]', err)
        if (options.showErrToast) {
          uni.showToast({ title: err.errMsg || '请求失败', icon: 'none' })
        }
        reject(err)
      },
      complete: () => {
        options.loading && uni.hideLoading()
      }
    })
  })
}

// 响应拦截器
const responseInterceptor = (res) => {
  console.log(`[Response] ${res.statusCode}`, res)

  // HTTP 状态码错误
  if (res.statusCode < 200 || res.statusCode >= 300) {
    throw new Error(`接口请求失败 Error: ${res.statusCode}`)
  }

  // 业务状态码处理
  if (res.data?.code === 401) {
    handleUnauthorized()
    throw new Error('登录状态已过期')
  }

  return res
}

// 401 处理封装
const handleUnauthorized = () => {
  const pages = getCurrentPages()
  const currentPage = pages[pages.length - 1]
  const redirectUrl = currentPage ? `/${currentPage.route}` : '/'

  uni.removeStorageSync('token')
  uni.removeStorageSync('userInfo')

  uni.showToast({
    title: '登录已过期',
    icon: 'none',
    duration: 800
  })

  setTimeout(() => {
	// 关闭所有界面,回到登录页面
	uni.reLaunch({
	    url: `/pages/login/index?redirect=${encodeURIComponent(redirectUrl)}` 
	})
  }, 800)
}

// 快捷方法
export const get = (url, data, options) => request('GET', url, data, options)
export const post = (url, data, options) => request('POST', url, data, options)
export const put = (url, data, options) => request('PUT', url, data, options)
export const del = (url, data, options) => request('DELETE', url, data, options)

// 文件上传优化
export const uploadFile = (url, filePath, options = {}) => {
  let fullUrl = ''
  // 请求接口地址处理,如果传来http/https的直接用传来的地址
  if( url.startsWith('http') ||  url.startsWith('https')){
  	  fullUrl = url
  } else {
  	  fullUrl = `${defaultOptions.baseURL}${url}`
  }
  
  return new Promise((resolve, reject) => {
    uni.uploadFile({
      url: fullUrl,
      filePath,
      name: 'file', // 参数字段
      header: {
        Authorization: uni.getStorageSync('token') ? `Bearer ${uni.getStorageSync('token')}` : '',
        ...options.header
      },
      success: (res) => {
        if (res.statusCode === 200) {
          try {
            resolve(JSON.parse(res.data))
          } catch (e) {
            resolve(res.data)
          }
        } else {
          reject(new Error(`上传失败:${res.errMsg}`))
        }
      },
      fail: reject
    })
  })
}
 
// 文件下载
export const downloadFile = (url, options = {}) => {
  const fullUrl = url.startsWith('http') ||  url.startsWith('https') ? url : `${API_URL}${url}`
  return uni.downloadFile({
    url: fullUrl,
    ...options
  })
}