# 酒谷小程序 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 方法

**当前模拟代码：**
```javascript
import { MOCK_HOMEPAGE_DATA } from '@/mock/mockData.js'

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

**替换为真实API：**
```javascript
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 添加基础配置

在文件顶部添加：
```javascript
// 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}
```

**期望响应格式：**
```json
{
  "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}
```

**期望响应格式：**
```json
{
  "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}
```

**期望响应格式：**
```json
{
  "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}
```

**期望响应格式：**
```json
{
  "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 方法

```javascript
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层进行映射转换：

```javascript
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`：
```javascript
// 环境配置
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中使用环境配置

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

const API_BASE_URL = ENV_CONFIG.API_BASE_URL
```

### 6. 测试验证

#### 6.1 替换后的测试检查清单

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

#### 6.2 调试技巧

1. **开启网络请求日志**：
```javascript
// 在 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 请求缓存

```javascript
// 添加简单的内存缓存
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 图片懒加载

在组件中添加图片懒加载：
```vue
<image 
  :src="product.image" 
  class="product-image" 
  mode="aspectFill"
  lazy-load
></image>
```

### 8. 清理工作

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

1. **删除模拟数据文件**：
   ```bash
   rm -rf mock/
   ```

2. **清理import引用**：
   检查并移除所有对模拟数据的引用

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

---

## 📋 替换检查清单

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

### 替换阶段
- [ ] 更新API基础配置（域名、认证）
- [ ] 替换 `getHomepageData` 接口
- [ ] 替换 `getBannerConfig` 接口  
- [ ] 替换 `getCategories` 接口
- [ ] 替换 `getCategoryProducts` 接口
- [ ] 替换 `getProductDetail` 接口
- [ ] 替换 `searchProducts` 接口
- [ ] 更新错误处理逻辑
- [ ] 添加数据结构映射（如需要）

### 测试阶段
- [ ] 首页加载测试
- [ ] 轮播图功能测试
- [ ] 商品列表测试
- [ ] 搜索功能测试
- [ ] 错误场景测试
- [ ] 网络异常测试
- [ ] 性能测试

### 清理阶段
- [ ] 移除模拟数据文件
- [ ] 清理TODO注释
- [ ] 更新文档
- [ ] 代码review

---

## 🔗 相关文档链接

- [uni-app网络请求文档](https://uniapp.dcloud.io/api/request/request)
- [小程序网络请求规范](https://developers.weixin.qq.com/miniprogram/dev/framework/ability/network.html)
- [后端API接口文档](#) <!-- 替换为实际文档链接 -->

---

## 📞 支持联系

如在API替换过程中遇到问题，请联系：
- 前端开发：[联系方式]
- 后端开发：[联系方式]
- 技术负责人：[联系方式]
