文章目錄

目錄

系列文章

文章目錄

前言

參數定義

請求修改

調試與測試


前言

        本文介紹了微信小程序中參數統一管理的實現方案。核心內容包括:

        1)通過src/config/index.ts文件實現多環境配置管理,自動區分開發/測試/生產環境;

        2)實例request.ts中應用

參數定義

建立src/config/index.ts文件

// src/config/index.ts
type EnvFile = 'dev' | 'test' | 'prod'

function getEnv(): EnvFile { 
	// #ifdef H5
	  const m = import.meta.env.MODE   // vite 環境變量
	  if (m === 'production') return 'prod'
	  if (m === 'test' || m === 'gray') return 'test'
	  return 'dev'
	  // #endif
	
	  // #ifndef H5
	  const v = uni.getAccountInfoSync().miniProgram.envVersion
	  if (v === 'release') return 'prod'
	  if (v === 'trial') return 'test'
	  return 'dev'          // develop / experience
	  // #endif
}

/* 1. 與環境無關的常量 */
const COMMON = {
  TIMEOUT: 15000,
  PAGE_SIZE: 20,
  MAX_RETRY: 3,
  // 任意其他固定值
} as const

/* 2. 與環境有關的差異配置 */
const ENV_CONFIG = {
  dev: {
    API_BASE_URL: 'http://127.0.0.1:8080',
    API_KEY: 'ae139f8f6a8efc2a74a1e852c5cdaa43',
    TRACK_URL: 'http://127.0.0.1:8080',
    ENABLE_VCONSOLE: true,
  },
  test: {
    API_BASE_URL: 'https://test-api.xxx.com',
    API_KEY: 'test-key-123456',
    TRACK_URL: 'https://test-track.xxx.com',
    ENABLE_VCONSOLE: true,
  },
  prod: {
    API_BASE_URL: 'https://api.xxx.com',
    API_KEY: 'prod-key-abcdef',
    TRACK_URL: 'https://track.xxx.com',
    ENABLE_VCONSOLE: false,
  },
} as const

/* 3. 合併後一次性導出 */
export default {
  ...COMMON,
  ...ENV_CONFIG[getEnv()],
} as const

作 用:

        根據運行平台與構建環境自動選取對應的後端地址、密鑰及功能開關,並統一導出只讀常量供全局使用。

核心思路 

1. 先判斷平台
        H5:讀取 Vite 注入的  import.meta.env.MODE 
        小程序:讀取微信/支付寶等宿主提供的  uni.getAccountInfoSync().miniProgram.envVersion 
2. 再映射到 3 套環境
          dev | test | prod 
3. 最後把「與環境無關的常量」+「當前環境變量」合併成單例導出
 

請求修改

修改src\utils\request.ts文件

import config from '@/src/config/index'
/* 配置 ------------------------------------------------------------------ */
const BASE_URL: string = config.API_BASE_URL //'http://8.130.11.167:8080'// 替換你的後端域名
const API_KEY: string = config.API_KEY
const TIMEOUT = config.TIMEOUT // ms

配置導入説明 
1. 配置來源
         代碼中所有  BASE_URL / API_KEY / TIMEOUT  等常量均統一從  @/src/config/index  自動讀取。
         該文件會根據運行平台(H5 / 小程序)與構建環境(dev / test / prod)動態返回對應的域名、密鑰及功能開關,業務層無需再寫  if/else  判斷環境。

        若後台域名或密鑰發生變更,只需修改  src/config/index.ts ,無需逐文件替換。

完整代碼如下:

// 頂部引入
import { toastError } from './toast'
import config from '@/src/config/index'
/* 配置 ------------------------------------------------------------------ */
const BASE_URL: string = config.API_BASE_URL //'http://8.130.11.167:8080'// 替換你的後端域名
const API_KEY: string = config.API_KEY
const TIMEOUT = config.TIMEOUT // ms

/* 類型定義 --------------------------------------------------------------- */
export type Method = 'GET' | 'POST' | 'PUT' | 'DELETE'

export interface RequestOptions<T = any> {
  url: string
  method?: Method
  data?: T
  headers?: Record<string, string>
  noToken?: boolean // 跳過 token
  noBaseURL?: boolean // 跳過 baseURL
  timeout?: number
}

// 後端統一返回格式(按你的實際改)
export interface HttpResponse<T = any> {
  status_code: number
  status:string
  message: string
  data: T
}

/* 核心請求 --------------------------------------------------------------- */
export function request<R = any>(options: RequestOptions): Promise<HttpResponse<R>> {
  console.log(BASE_URL)
  console.log(API_KEY)
  return new Promise((resolve, reject) => {
    const token = uni.getStorageSync('token')
    const header: AnyObject = {
      'Content-Type': 'application/json; charset=utf-8',
      'x-api-key': API_KEY ,//'ae139f8f6a8efc2a74a1e852c5cdaa43',
      ...options.headers,
    }

    if (!options.noToken && token) header.Authorization = `Bearer ${token}`

    uni.request({
      url: options.noBaseURL ? options.url : `${BASE_URL}${options.url}`,
      method: options.method || 'GET',
      data: options.data || {},
      header,
      timeout: options.timeout || TIMEOUT,
      success: (res) => handleSuccess<R>(res, resolve, reject),
      fail: (err) => handleFail(err, reject),
    })
  })
}

/* 成功處理 --------------------------------------------------------------- */
function handleSuccess<R>(
  res: UniApp.RequestSuccessCallbackResult,
  resolve: (value: HttpResponse<R>) => void,
  reject: (reason?: any) => void,
) {
  const { statusCode, data } = res
  // 成功區間
  if (statusCode >= 200 && statusCode < 300) {
    const resp = data as HttpResponse<R>
    if (resp.status_code === 200) resolve(resp)
    else {
      toastError(resp.message)
      reject(resp)
    }
    return
  }
  // 401 登錄態失效
  if (statusCode === 401) {
    const detail = (data as any)?.detail || '登錄已過期'
    toastError(detail)
    uni.clearStorageSync()
    uni.reLaunch({ url: '/pages/login/index' })
    reject(new Error(detail))
    return
  }
  // 其他 4xx/5xx
  if (statusCode >= 300) {
    const detail = (data as any)?.detail || `請求失敗(${statusCode})`
    toastError(detail)
    reject(new Error(detail))
    return
  }
}

/* 失敗處理 --------------------------------------------------------------- */
function handleFail(err: any, reject: (reason?: any) => void) {
  toastError('網絡異常')
  reject(err)
}

/* 上傳文件 --------------------------------------------------------------- */
export function upload<R = any>(
  url: string,
  filePath: string,
  formData?: Record<string, any>,
  timeout = 30_000,
): Promise<R> {
  const token = uni.getStorageSync('token')
  return new Promise((resolve, reject) => {
    uni.uploadFile({
      url: `${BASE_URL}${url}`,
      filePath,
      name: 'file',
      formData,
      header: { Authorization: `Bearer ${token}` },
      timeout,
      success: (res) => {
        const data: HttpResponse<R> = JSON.parse(res.data)
        if (data.status_code === 0) resolve(data.data)
        else {
          uni.showToast({ title: data.message || '上傳失敗', icon: 'none' })
          reject(data)
        }
      },
      fail: reject,
    })
  })
}

/* 導出別名(可選)-------------------------------------------------------- */
export const http = {
  get<R>(url: string, params?: any, returnData = true) {
    return request<R>({ url, data: params }).then(res =>
      returnData ? res.data : res
    )
  },
  post<R>(url: string, data?: any, returnData = true) {
    return request<R>({ url, method: 'POST', data }).then(res =>
      returnData ? res.data : res
    )
  },
  put<R>(url: string, data?: any, returnData = true) {
    return request<R>({ url, method: 'PUT', data }).then(res =>
      returnData ? res.data : res
    )
  },
  delete<R>(url: string, returnData = true) {
    return request<R>({ url, method: 'DELETE' }).then(res =>
      returnData ? res.data : res
    )
  }
}

調試與測試

1.HBuilderX :運行 → 運行至瀏覽器→Chrome

2.啓動後按 F12 打開開發者工具

3.輸入任意不存在的用户名及密碼,觀察登錄接口返回

微信小程序的知識點_#小程序

4.輸入正確的賬號與密碼

微信小程序的知識點_API_02