request.js 4.74 KB
/*
 * @Date: 2022-09-19 14:11:06
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2026-01-08 16:27:50
 * @FilePath: /xyxBooking-weapp/src/utils/request.js
 * @Description: 简单axios封装,后续按实际处理
 */
// import axios from 'axios'
import axios from 'axios-miniprogram';
import Taro from '@tarojs/taro'
// import qs from 'qs'
// import { strExist } from './tools'
import { refreshSession, saveCurrentPagePath, navigateToAuth } from './authRedirect'

// import { ProgressStart, ProgressEnd } from '@/components/axios-progress/progress';
// import store from '@/store'
// import { getToken } from '@/utils/auth'
import BASE_URL, { REQUEST_DEFAULT_PARAMS } from './config';

/**
 * 获取sessionid的工具函数
 * @returns {string|null} sessionid或null
 */
const getSessionId = () => {
  try {
    return Taro.getStorageSync("sessionid") || null;
  } catch (error) {
    console.error('获取sessionid失败:', error);
    return null;
  }
};

// const isPlainObject = (value) => {
//   if (value === null || typeof value !== 'object') return false
//   return Object.prototype.toString.call(value) === '[object Object]'
// }

// create an axios instance
const service = axios.create({
  baseURL: BASE_URL, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 5000, // request timeout
})

service.defaults.params = {
  ...REQUEST_DEFAULT_PARAMS,
};

// request interceptor
service.interceptors.request.use(
  config => {
    // console.warn(config)
    // console.warn(store)

    /**
     * 动态获取sessionid并设置到请求头
     * 确保每个请求都带上最新的sessionid
     */
    const sessionid = getSessionId();
    if (sessionid) {
      config.headers.cookie = sessionid;
    }

    // 增加时间戳
    if (config.method === 'get') {
        config.params = { ...config.params, timestamp: (new Date()).valueOf() }
    }

    // if ((config.method || '').toLowerCase() === 'post') {
    //   const url = config.url || ''
    //   const headers = config.headers || {}
    //   const contentType = headers['content-type'] || headers['Content-Type']
    //   const shouldUrlEncode =
    //     !contentType || String(contentType).includes('application/x-www-form-urlencoded')

    //   if (shouldUrlEncode && !strExist(['upload.qiniup.com'], url) && isPlainObject(config.data)) {
    //     config.headers = {
    //       ...headers,
    //       'content-type': 'application/x-www-form-urlencoded'
    //     }
    //     config.data = qs.stringify(config.data)
    //   }
    // }

    return config
  },
  error => {
    // do something with request error
    console.error(error, 'err') // for debug
    return Promise.reject(error)
  }
)

// response interceptor
service.interceptors.response.use(
  /**
   * 响应拦截器说明
   * - 这里统一处理后端自定义 code(例如 401 未授权)
   * - 如需拿到 headers/status 等原始信息,直接返回 response 即可
   */
  async response => {
    const res = response.data

    // 401 未授权处理
    if (res.code === 401) {
        const config = response?.config || {}
        /**
         * 避免死循环/重复授权:
         * - __is_auth_request:本次请求就是“换取会话”的授权请求,不应再次触发刷新
         * - __is_retry:本次请求是 401 后的重试请求,如果仍 401,不再继续重试
         */
        if (config.__is_auth_request || config.__is_retry) {
          return response
        }

        /**
         * 记录来源页:用于授权成功后回跳
         * - 避免死循环:如果已经在 auth 页则不重复记录/跳转
         */
        const pages = Taro.getCurrentPages();
        const currentPage = pages[pages.length - 1];
        if (currentPage && currentPage.route !== 'pages/auth/index') {
            saveCurrentPagePath()
        }

        try {
          // 优先走静默续期:成功后重放原请求
          await refreshSession()
          const retry_config = { ...config, __is_retry: true }
          return await service(retry_config)
        } catch (error) {
          // 静默续期失败:降级跳转到授权页(由授权页完成授权并回跳)
          const pages_retry = Taro.getCurrentPages();
          const current_page_retry = pages_retry[pages_retry.length - 1];
          if (current_page_retry && current_page_retry.route !== 'pages/auth/index') {
            navigateToAuth()
          }
          return response
        }
    }

    if (['预约ID不存在'].includes(res.msg)) {
      res.show = false;
    }

    return response
  },
  error => {
    // Taro.showToast({
    //   title: error.message,
    //   icon: 'none',
    //   duration: 2000
    // })
    return Promise.reject(error)
  }
)

export default service