API_REPLACEMENT_GUIDE.md 10 KB

酒谷小程序 API 替换指南

概述

本文档说明如何将前端模拟数据替换为真实后端API接口调用。目前前端使用模拟数据进行开发,后端接口开发完成后,需要按照本指南进行替换。

🔄 替换步骤总览

  1. 更新API服务层 (/api/homepage.js)
  2. 配置请求基础URL和认证
  3. 调整数据结构映射 (如果需要)
  4. 测试接口集成
  5. 移除模拟数据文件

📁 文件结构

├── api/
│   └── homepage.js           # ⚠️ 需要替换
├── mock/
│   └── mockData.js          # 🗑️ 后期可删除
├── pages/
│   └── index/index.vue      # ✅ 无需修改
└── docs/
    └── API_REPLACEMENT_GUIDE.md

🛠️ 详细替换步骤

1. 更新 API 服务层 (/api/homepage.js)

1.1 替换 getHomepageData 方法

当前模拟代码:

import { MOCK_HOMEPAGE_DATA } from '@/mock/mockData.js'

export const getHomepageData = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(MOCK_HOMEPAGE_DATA)
    }, 300)
  })
}

替换为真实API:

export const getHomepageData = () => {
  return uni.request({
    url: `${API_BASE_URL}/api/homepage/data`,
    method: 'GET',
    header: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${getToken()}` // 如果需要认证
    },
    timeout: 10000
  }).then(([error, res]) => {
    if (error) {
      throw error
    }
    return res.data
  })
}

1.2 添加基础配置

在文件顶部添加:

// API基础配置
const API_BASE_URL = 'https://your-api-domain.com' // 替换为实际域名

// 获取认证token
const getToken = () => {
  return uni.getStorageSync('token') || ''
}

1.3 替换其他API方法

按照相同模式替换所有 API 方法:

  • getBannerConfig()
  • getCategories()
  • getCategoryProducts()
  • getProductDetail()
  • getAssetUrl()
  • searchProducts()

2. 后端接口规范

2.1 首页数据接口

请求:

GET /api/homepage/data
Authorization: Bearer {token}

期望响应格式:

{
  "success": true,
  "message": "数据获取成功",
  "data": {
    "banners": [
      {
        "id": "banner_config_001",
        "title": "新春特惠酒水节",
        "subtitle": "全场酒水满299减50",
        "imageUrl": "https://cdn.example.com/banner1.jpg",
        "linkType": "product",
        "linkTarget": "product_jg_001",
        "status": 1,
        "sort": 1
      }
    ],
    "categories": [
      {
        "id": "category_jiugu",
        "name": "酒谷酒",
        "sort": 1,
        "status": 1,
        "products": [
          {
            "id": "product_jg_001",
            "name": "酒谷陈酿",
            "imageUrl": "https://cdn.example.com/product1.jpg",
            "stock": 100,
            "sales": 256
          }
        ]
      }
    ]
  }
}

2.2 轮播图配置接口

请求:

GET /api/config/banners
Authorization: Bearer {token}

期望响应格式:

{
  "success": true,
  "data": {
    "banners": [
      {
        "id": "banner_config_001",
        "title": "新春特惠酒水节",
        "assetId": "banner_001",
        "imageUrl": "https://cdn.example.com/banner1.jpg",
        "linkType": "product",
        "linkTarget": "product_jg_001",
        "status": 1,
        "sort": 1,
        "startTime": "2024-01-01 00:00:00",
        "endTime": "2024-12-31 23:59:59"
      }
    ]
  }
}

2.3 商品分类接口

请求:

GET /api/categories
Authorization: Bearer {token}

期望响应格式:

{
  "success": true,
  "data": {
    "categories": [
      {
        "id": "category_jiugu",
        "name": "酒谷酒",
        "sort": 1,
        "status": 1,
        "description": "自主品牌酒谷系列"
      }
    ]
  }
}

2.4 商品列表接口

请求:

GET /api/products?categoryId={categoryId}&page={page}&limit={limit}
Authorization: Bearer {token}

期望响应格式:

{
  "success": true,
  "data": {
    "products": [
      {
        "id": "product_jg_001",
        "name": "酒谷陈酿",
        "categoryId": "category_jiugu",
        "imageUrl": "https://cdn.example.com/product1.jpg",
        "status": 1,
        "sort": 1,
        "stock": 100,
        "sales": 256
      }
    ],
    "pagination": {
      "page": 1,
      "limit": 10,
      "total": 50
    }
  }
}

3. 错误处理更新

3.1 更新 handleApiError 方法

export const handleApiError = (error) => {
  console.error('API请求错误:', error)
  
  // 根据实际后端错误码进行处理
  const { statusCode, data } = error
  
  switch (statusCode) {
    case 401:
      // 清除本地token
      uni.removeStorageSync('token')
      uni.showToast({ title: '登录已过期,请重新登录', icon: 'none' })
      // 跳转到登录页
      uni.navigateTo({ url: '/pages/auth/login' })
      break
      
    case 403:
      uni.showToast({ title: '权限不足', icon: 'none' })
      break
      
    case 404:
      uni.showToast({ title: '请求的资源不存在', icon: 'none' })
      break
      
    case 422:
      // 参数验证错误
      const message = data?.message || '参数错误'
      uni.showToast({ title: message, icon: 'none' })
      break
      
    case 500:
      uni.showToast({ title: '服务器内部错误', icon: 'none' })
      break
      
    default:
      const errorMessage = data?.message || '网络错误,请稍后重试'
      uni.showToast({ title: errorMessage, icon: 'none' })
  }
}

4. 数据结构映射

如果后端返回的数据结构与前端需要的不完全一致,需要在API层进行映射转换:

export const getHomepageData = async () => {
  const response = await uni.request({
    // ... 请求配置
  })
  
  // 数据结构映射
  const mappedData = {
    success: response.data.success,
    message: response.data.message,
    data: {
      banners: response.data.data.banners.map(banner => ({
        id: banner.id,
        title: banner.title,
        subtitle: banner.subtitle,
        image: banner.imageUrl,  // 映射字段名
        linkType: banner.linkType,
        linkTarget: banner.linkTarget
      })),
      categories: response.data.data.categories.map(category => ({
        id: category.id,
        name: category.name,
        products: category.products.map(product => ({
          id: product.id,
          name: product.name,
          image: product.imageUrl,  // 映射字段名
          stock: product.stock,
          sales: product.sales
        }))
      }))
    }
  }
  
  return mappedData
}

5. 环境配置

5.1 创建环境配置文件

创建 /config/env.js

// 环境配置
const ENV_CONFIG = {
  development: {
    API_BASE_URL: 'http://localhost:8080',
    CDN_BASE_URL: 'http://localhost:8080/uploads'
  },
  production: {
    API_BASE_URL: 'https://api.jiugu.com',
    CDN_BASE_URL: 'https://cdn.jiugu.com'
  }
}

// 根据编译环境自动选择
const env = process.env.NODE_ENV === 'production' ? 'production' : 'development'
export default ENV_CONFIG[env]

5.2 在API中使用环境配置

import ENV_CONFIG from '@/config/env.js'

const API_BASE_URL = ENV_CONFIG.API_BASE_URL

6. 测试验证

6.1 替换后的测试检查清单

  • 首页数据正常加载
  • 轮播图显示正确
  • 商品分类和商品列表正常
  • 图片资源正常显示
  • 点击跳转功能正常
  • 错误处理正常工作
  • 加载状态正确显示
  • 下拉刷新功能正常

6.2 调试技巧

  1. 开启网络请求日志

    // 在 main.js 中添加
    uni.addInterceptor('request', {
    invoke(args) {
    console.log('🚀 API请求:', args)
    },
    success(args) {
    console.log('✅ API成功:', args)
    },
    fail(err) {
    console.log('❌ API失败:', err)
    }
    })
    
  2. 对比模拟数据和真实数据: 确保数据结构一致,特别关注字段名和数据类型

  3. 分阶段替换: 可以先替换一个接口进行测试,确认无误后再替换其他接口

7. 性能优化建议

7.1 请求缓存

// 添加简单的内存缓存
const cache = new Map()
const CACHE_DURATION = 5 * 60 * 1000 // 5分钟

export const getHomepageData = async () => {
  const cacheKey = 'homepage_data'
  const cached = cache.get(cacheKey)
  
  if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
    return cached.data
  }
  
  const data = await fetchHomepageData()
  cache.set(cacheKey, {
    data,
    timestamp: Date.now()
  })
  
  return data
}

7.2 图片懒加载

在组件中添加图片懒加载:

<image 
  :src="product.image" 
  class="product-image" 
  mode="aspectFill"
  lazy-load
></image>

8. 清理工作

接口替换完成并测试通过后:

  1. 删除模拟数据文件

    rm -rf mock/
    
  2. 清理import引用: 检查并移除所有对模拟数据的引用

  3. 更新注释: 移除代码中的 "TODO: API替换" 注释


📋 替换检查清单

准备阶段

  • 确认后端接口开发完成
  • 获取API文档和接口地址
  • 确认认证方式和token获取方法
  • 准备测试数据和测试账号

替换阶段

  • 更新API基础配置(域名、认证)
  • 替换 getHomepageData 接口
  • 替换 getBannerConfig 接口
  • 替换 getCategories 接口
  • 替换 getCategoryProducts 接口
  • 替换 getProductDetail 接口
  • 替换 searchProducts 接口
  • 更新错误处理逻辑
  • 添加数据结构映射(如需要)

测试阶段

  • 首页加载测试
  • 轮播图功能测试
  • 商品列表测试
  • 搜索功能测试
  • 错误场景测试
  • 网络异常测试
  • 性能测试

清理阶段

  • 移除模拟数据文件
  • 清理TODO注释
  • 更新文档
  • 代码review

🔗 相关文档链接


📞 支持联系

如在API替换过程中遇到问题,请联系:

  • 前端开发:[联系方式]
  • 后端开发:[联系方式]
  • 技术负责人:[联系方式]