# 佳友厚苑 MVP 第一阶段开发文档

---

## 1. 项目目标与范围

### 1.1 项目目标
第一阶段目标是快速搭建“扫码溯源展示能力”，跑通最小业务闭环：

- 用户扫码 → 打开溯源页面
- 页面展示商品、农场、批次、检测报告、合格证
- 支撑运营实际使用（打印标签 + 贴标 + 直播/发货使用）

---

### 1.2 本阶段解决的问题

- 如何让用户“看到可信信息”
- 如何快速上线溯源能力
- 如何支撑运营落地流程

---

### 1.3 本阶段不做内容

- 不做商城交易系统
- 不做登录注册
- 不接农小禹系统
- 不做农事记录
- 不接设备/摄像头数据
- 不做复杂审核流
- 不做统计分析

---

## 2. 业务流程

### 2.1 标准流程

1. 运营创建批次
2. 填写商品信息、农场信息、批次信息
3. 收集农户提供的：
   - 合格证
   - 检测报告
4. 在爱智农后台上传资料
5. 生成批次二维码
6. 生成标签打印文件
7. 打印标签并贴标
8. 用户扫码进入溯源页查看信息

---

### 2.2 关键约束

- 批次创建时必须填写商品与农场信息
- 批次未发布不可扫码
- 所有展示内容均来源于批次

---

## 3. 角色与职责

### 3.1 运营人员
- 创建批次
- 收集合格证与检测报告
- 上传资料
- 生成二维码
- 打印标签
- 校验扫码效果

---

### 3.2 系统（爱智农）
- 提供批次管理能力
- 提供文件上传能力
- 提供二维码生成能力
- 提供标签打印能力

---

### 3.3 用户
- 扫码查看溯源信息

---

## 4. 核心数据模型

### 4.1 核心对象：批次（Batch）

> 第一阶段所有数据围绕“批次”组织

---

### 4.2 批次结构

批次包含以下信息：

#### 商品信息
- 商品名称
- 商品规格
- 商品图片
- 商品简介

#### 农场信息
- 农场名称
- 农场所在地
- 农场简介
- 农场图片

#### 批次信息
- 批次号
- 生产/采收日期
- 包装日期
- 状态（草稿/已发布/已下线）

#### 文件信息
- 检测报告
- 合格证

---

### 4.3 设计原则

- 批次创建时必须填写商品与农场信息
- 批次为唯一展示数据源
- 前端不单独维护数据

---

## 5. 前端页面说明（溯源页）

### 5.1 页面目标

让用户快速理解：
- 买的是什么（商品基础信息清晰可见）
- 来自哪里（农场来源明确）
- 属于哪一批（批次信息明确）
- 是否经过检测（检测报告可查看）
- 是否具备合格证（合格证可查看）
- 页面整体有一定品牌感与可信感

---

### 5.2 页面结构

#### 1. 页面头部
- 品牌名称：佳友厚苑
- 页面标题：商品溯源信息
- 商品/农场背景图
- 品牌文案（如：可追溯 · 更安心）
- 商品主视觉图优先，若无则使用农场图

#### 2. 商品信息区
- 商品名称
- 商品图片
- 商品规格
- 商品简介

#### 3. 农场信息区
- 农场名称
- 农场所在地
- 农场图片
- 农场简介

#### 4. 批次信息区
- 批次号
- 生产/采收时间
- 包装时间
- 批次状态

#### 5. 检测报告区
- 检测状态（合格/待补充）
- 检测日期（可选）
- 报告编号（可选）
- 报告文件预览（PDF/图片）
- 查看原件按钮

#### 6. 合格证区
- 合格证状态
- 开具日期
- 合格证文件预览
- 查看原件按钮
- 合格证编号（可选）

#### 7. 溯源说明区
- 数据来源说明（前端固定文案）
- 溯源说明文案（前端固定文案）

示例文案：

数据来源说明：
本页面信息由佳友厚苑溯源系统提供，相关检测报告及合格证由平台统一收集并上传，确保信息真实可查。

溯源说明文案：
本商品支持溯源查询，您可通过本页面查看该批次的商品来源、生产信息、检测报告及合格证等内容，让消费更安心。

说明：
- 第一阶段溯源说明区内容建议由前端写死为固定文案，不依赖后台配置
- 若检测报告或合格证缺失，通过对应模块内“待补充”提示即可，不单独设置“数据完整性说明”区域

#### 8. 底部引导
- 联系客服
- 引导回购买渠道（直播/小店）

---

### 5.3 页面状态设计

#### 正常状态
- 展示全部信息

#### 空数据状态
- 显示：
  - “检测报告待补充”
  - “合格证待补充”
  - “农场信息待补充”

#### 异常状态
- 批次不存在 → 提示“无效二维码”
- 批次未发布 → 提示“暂未开放查询”
- 批次已下线 → 提示“该批次已下线”

---

### 5.4 第一阶段溯源页展示建议（推荐采用卡片式布局）

#### 推荐展示顺序
1. 页面头部（品牌 + 标题 + 主视觉）
2. 商品信息区
3. 农场信息区
4. 批次信息区
5. 检测报告区
6. 合格证区
7. 溯源说明区
8. 底部引导区

#### 推荐展示原则
- 先展示用户最关心的信息：商品、农场、批次
- 再展示证明可信的信息：检测报告、合格证
- 再展示平台与品牌说明，增强页面完整度
- 第一阶段即使数据不全，也建议将展示结构预留完整，未填字段以空状态或待补充提示处理
- 第一阶段展示字段以“实用、易维护、可快速上线”为原则，暂不引入冗余修饰型字段
- 第一阶段仅保留必要展示字段，避免增加运营录入负担与前后端复杂度

---

## 6. 爱智农后台功能说明

### 6.1 批次管理

#### 功能
- 创建批次
- 编辑批次
- 查看批次
- 上传检测报告（操作按钮）
- 上传合格证（操作按钮）
- 生成二维码
- 打印标签
- 发布/下线

#### 关键规则
- 创建时必须填写商品与农场信息
- 草稿状态不可生成二维码

---

### 6.2 检测报告管理

- 通过批次管理操作按钮上传
- 支持 PDF 或多张图片上传
- 支持查看/预览与覆盖上传

---

### 6.3 合格证管理

- 通过批次管理操作按钮上传
- 支持 PDF 或多张图片上传
- 支持查看/预览与覆盖上传

---

### 6.4 二维码生成

- 为批次生成唯一溯源链接
- 生成二维码图片
- 支持下载

---

### 6.5 标签打印管理


#### 功能
- 选择批次
- 生成标签PDF
- 下载打印文件

#### 标签内容
- 二维码（核心，保证清晰可扫码）
- 商品名称（用户可快速识别商品）
- 批次号（用于溯源对应）
- 简要提示文案（如：扫码查看溯源信息）
- 品牌名称（佳友厚苑，可选）
- 打印日期（可选）

#### 标签展示设计建议
- 不建议仅打印二维码，必须搭配文字说明，否则用户无法理解用途
- 推荐结构：二维码在中间或左侧，文字信息在下方或右侧
- 建议至少包含一句引导语：如“扫码查看商品溯源信息”
- 商品名称建议简化显示，避免过长导致排版拥挤
- 批次号可使用较小字体展示
- 整体布局保持简洁，确保二维码识别优先

---

### 6.6 发布管理

批次状态：

- 草稿：不可扫码
- 已发布：可扫码
- 已下线：不可扫码

---

## 7. 字段定义（简要）

### 批次
- batchNo
- productName
- productSpec
- productImage
- productDesc
- farmName
- farmRegion
- farmImage
- farmIntro
- produceDate
- packageDate
- status

---

### 检测报告
- reportStatus（上传状态：uploaded/pending）
- reportFiles（文件列表，支持PDF或多图）
- reportDate（必填）
- reportNo（必填）

---

### 合格证
- certStatus（上传状态：uploaded/pending）
- certFiles（文件列表，支持PDF或多图）
- certIssueDate（必填）
- certNo（必填）

---

## 8. 二维码与标签打印方案

### 8.1 二维码内容
- 二维码本质为一个带 batchId 的溯源访问链接
- 推荐格式：`/trace/{batchId}`（可扩展 source、campaign 参数）
- 若区分入口来源，可扩展参数：
  - source：来源渠道（如 packaging / douyin / wechat / service）
  - campaign：活动标识（可选）

#### 第一阶段二维码承载的信息原则
- 二维码本身只承载访问入口，不直接写入完整业务数据
- 实际展示内容通过 batchId 在后台查询获取
- 所有前端展示内容均通过批次数据统一返回

#### 二维码关联的前端展示内容
扫码后进入溯源页，页面展示内容包括：
- 商品信息
- 农场信息
- 批次信息
- 检测报告
- 合格证
- 溯源说明

#### 二维码生成规则
- 每个批次生成唯一二维码
- 未发布批次不可生成正式可用二维码
- 批次下线后，扫码应提示“该批次已下线”或“暂不可查询”

---

### 8.2 打印方案

- 打印机：热敏标签打印机
- 标签尺寸：40×30mm（推荐）
- 文件格式：PDF
- 打印方式：人工触发
- 标签打印内容建议与溯源页保持一致性（至少包含商品名与批次号）
- 标签需包含用户可读信息（如商品名称 + 溯源提示语），避免仅二维码导致用户无法理解用途
- 二维码尺寸需保证可扫码识别
- 生成的PDF需固定尺寸，避免打印缩放导致二维码失效
- 首期采用“后台生成PDF + 人工触发打印”的轻方案

---

## 9. 接口清单（第一阶段）

本章节仅作为接口总览，详细接口定义及返回结构详见第 14 章。

前端核心接口：
- 获取溯源详情接口（/api/trace/{batchId}）

后台接口分类：
- 批次管理
- 检测报告管理
- 合格证管理
- 二维码生成
- 标签打印

---

## 10. 验收标准

- 能创建批次
- 能上传检测报告
- 能上传合格证
- 能生成二维码
- 扫码可打开溯源页
- 页面显示真实数据
- 页面展示结构完整（商品 / 农场 / 批次 / 检测报告 / 合格证）
- 报告与合格证支持预览或查看原件
- 页面空状态与异常状态展示正常
- 标签可打印
- 打印二维码可扫码

---

## 11. 开发排期建议

### 第1-2天
- 确认字段
- 确认页面结构
- 确认打印方案

---

### 第3-5天
- 前端溯源页开发
- 批次后台开发
- 文件上传功能

---

### 第6-7天
- 二维码生成
- 标签打印功能
- 联调

---

### 第8-10天
- 测试
- 修复问题
- 优化细节

---

## 12. 总体原则

- 批次为核心数据模型
- 前端只展示，不维护数据
- 优先保证“能用”
- 不追求复杂功能
- 先跑通，再优化

---

## 13. 数据库设计（第一阶段）

### 13.1 批次表（batch）
字段：
- id（主键）
- batch_no（批次号，唯一）
- product_name（商品名称）
- product_spec（商品规格）
- product_image（商品图片URL）
- product_desc（商品简介，可选）
- farm_name（农场名称）
- farm_region（农场所在地）
- farm_image（农场图片URL）
- farm_intro（农场简介，可选）
- produce_date（生产/采收日期）
- package_date（包装日期）
- status（状态：draft/published/offline）
- created_at
- updated_at

约束：
- batch_no 唯一
- status 仅允许：draft/published/offline

---

### 13.2 检测报告表（report）
字段：
- id（主键）
- batch_id（关联批次）
- report_status（状态：uploaded/pending）
- report_files（JSON数组，文件URL列表）
- report_no（报告编号，必填）
- report_date（检测日期，必填）
- created_at

约束：
- batch_id 唯一（第一阶段每批次仅一条报告）

---

### 13.3 合格证表（certificate）
字段：
- id（主键）
- batch_id（关联批次）
- cert_status（状态：uploaded/pending）
- cert_files（JSON数组，文件URL列表）
- cert_no（合格证编号，必填）
- cert_issue_date（开具日期，必填）
- created_at

约束：
- batch_id 唯一（第一阶段每批次仅一张合格证）

---

## 14. 接口设计（第一阶段）

### 14.1 前端溯源接口（核心）

GET /api/trace/{batchId}

返回示例：
{
  "batch": {
    "batchNo": "B20250101",
    "productName": "有机鸡蛋",
    "productSpec": "30枚",
    "productImage": "https://example.com/product.jpg",
    "productDesc": "新鲜鸡蛋，适合家庭日常食用。",
    "farmName": "阳光农场",
    "farmRegion": "陕西西安",
    "farmImage": "https://example.com/farm.jpg",
    "farmIntro": "阳光农场位于西安周边，采用规范化种养管理。",
    "produceDate": "2025-01-01",
    "packageDate": "2025-01-02",
    "status": "published"
  },
  "report": {
    "reportStatus": "uploaded",
    "reportFiles": ["https://example.com/report1.jpg"],
    "reportDate": "2025-01-02",
    "reportNo": "R20250102001"
  },
  "certificate": {
    "certStatus": "uploaded",
    "certFiles": ["https://example.com/cert1.jpg"],
    "certIssueDate": "2025-01-02",
    "certNo": "C20250102001"
  }
}

说明：
- 前端所有展示数据统一通过该接口返回
- productDesc、farmIntro 为可选字段
- reportStatus、certStatus 表示“文件上传状态”，不是检测结果
- 前端需将 uploaded/pending 映射为“已上传/待补充”进行展示

---

### 14.2 后台接口

批次：
- POST /api/batch（创建）
- GET /api/batch/list（列表）
- GET /api/batch/{id}（详情）
- PUT /api/batch/{id}（编辑）
- POST /api/batch/{id}/publish（发布）
- POST /api/batch/{id}/offline（下线）

检测报告：
- POST /api/report/upload
- GET /api/report/{batchId}

合格证：
- POST /api/certificate/upload
- GET /api/certificate/{batchId}

二维码：
- GET /api/qrcode/{batchId}

打印：
- GET /api/print/{batchId}

---

## 15. 业务规则说明

### 15.1 批次规则
- 批次必须绑定商品与农场信息
- 批次创建后默认状态为 draft
- draft 状态不可生成二维码
- 只有 published 状态可扫码访问
- offline 状态扫码提示不可用

---

### 15.2 文件规则
- 每个批次多检测报告（支持多文件）
- 每个批次多个合格证（支持多文件）
- 支持 PDF 或多张图片上传
- 报告编号、检测日期为必填
- 合格证编号、开具日期为必填
- 支持覆盖上传（新文件覆盖旧文件）

---

### 15.3 二维码规则
- 每个批次生成唯一二维码
- 二维码内容为带 batchId 的溯源访问链接
- 可扩展 source / campaign 参数用于渠道区分

---

### 15.4 打印规则
- 标签必须包含二维码 + 商品名称 + 批次号
- 打印文件为固定尺寸 PDF
- 不允许缩放打印

---

### 15.5 页面展示规则
- 页面数据统一来源于批次接口
- 数据缺失需展示“待补充”
- 商品简介、农场简介为可选字段
- 报告/合格证状态由后端返回，前端根据状态展示
- reportStatus、certStatus 仅表示文件是否上传，不表示检测是否合格

---


---

## 16. HTTP 请求工具模块

### 16.1 模块概述

项目已集成企业级 HTTP 请求工具模块，提供统一的网络请求能力，支持 Web 和 uni-app 多端运行。

#### 核心特性
- 基于 axios 封装，支持 uni-app 适配
- 统一的请求/响应拦截器
- 自动 Token 管理
- 统一错误处理
- 文件上传/下载支持
- 请求重试机制
- 防重复请求
- 多环境配置

---

### 16.2 目录结构

```
utils/
├── request.js          # 核心请求模块（基于 axios）
├── uniRequest.js       # uni-app 原生请求适配器（备选）
├── upload.js           # 文件上传模块
├── download.js         # 文件下载模块
├── retry.js            # 请求重试模块
├── storage.js          # 本地存储模块
├── ui.js               # UI 交互模块
├── platform.js         # 平台检测模块
├── env.js              # 环境配置模块
├── index.js            # 统一导出
├── README.md           # 使用文档
└── ARCHITECTURE.md     # 架构设计文档

api/
├── user.js             # 用户相关 API
├── order.js            # 订单相关 API
├── product.js          # 产品相关 API
└── index.js            # API 统一导出
```

---

### 16.3 快速使用

#### 基础请求
```javascript
import { getUserInfo, getOrderList } from '@/api'

export default {
  async onLoad() {
    // 获取用户信息
    const userInfo = await getUserInfo()
    
    // 获取订单列表
    const orders = await getOrderList({ page: 1, size: 10 })
  }
}
```

#### 文件上传
```javascript
import { chooseAndUploadImage } from '@/utils/upload'

const handleUpload = async () => {
  const result = await chooseAndUploadImage({
    count: 1,
    onProgress: (progress) => {
      console.log('上传进度:', progress + '%')
    }
  })
  console.log('上传成功', result)
}
```

#### 文件下载
```javascript
import { downloadFile } from '@/utils/download'

const handleDownload = async () => {
  await downloadFile('/file/download', '文件名.pdf')
}
```

---

### 16.4 配置说明

#### 环境配置
修改 `utils/env.js` 配置不同环境的 API 地址：

```javascript
const envConfig = {
  development: {
    baseURL: 'http://localhost:3000/api',
    timeout: 10000
  },
  production: {
    baseURL: 'https://api.example.com/api',
    timeout: 20000
  }
}
```

#### Token 配置
Token 会自动注入到请求头，格式为：
```javascript
config.headers['Authorization'] = `Bearer ${token}`
```

如需修改格式，编辑 `utils/request.js` 中的请求拦截器。

#### 白名单配置
不需要 Token 的接口添加到白名单：
```javascript
const WHITE_LIST = [
  '/auth/login',
  '/auth/register',
  '/auth/captcha'
]
```

---

### 16.5 API 层设计

#### 按业务模块组织
```javascript
// api/user.js
export const login = (data) => post('/auth/login', data)
export const getUserInfo = () => get('/user/info')

// api/order.js
export const getOrderList = (params) => get('/order/list', params)
export const createOrder = (data) => post('/order/create', data)
```

#### 统一导出
```javascript
// api/index.js
export * from './user'
export * from './order'
export * from './product'
```

---

### 16.6 错误处理

#### 全局错误处理
已在 `utils/request.js` 中实现：
- HTTP 状态码错误（401、403、500 等）
- 业务错误码处理
- Token 过期自动跳转登录
- 网络错误处理

#### 局部错误处理
```javascript
try {
  const data = await getUserInfo()
} catch (error) {
  console.error('获取用户信息失败', error)
}
```

#### 隐藏错误提示
```javascript
const data = await getUserInfo({}, {
  hideError: true  // 不显示错误提示
})
```

---

### 16.7 高级功能

#### 请求重试
```javascript
import { createRetryRequest } from '@/utils/retry'

const getDataWithRetry = createRetryRequest(
  () => get('/api/data'),
  3 // 最大重试 3 次
)
```

#### 并发请求
```javascript
const [userInfo, orders, products] = await Promise.all([
  getUserInfo(),
  getOrderList({ page: 1 }),
  getProductList({ page: 1 })
])
```

#### 请求取消
```javascript
import axios from 'axios'

const source = axios.CancelToken.source()

get('/api/data', {}, {
  cancelToken: source.token
})

// 取消请求
source.cancel('请求被用户取消')
```

---

### 16.8 配置项说明

所有请求方法都支持以下配置：

```javascript
{
  showLoading: true,           // 是否显示 loading
  loadingText: '加载中...',    // loading 文字
  hideError: false,            // 是否隐藏错误提示
  preventDuplicate: false,     // 是否防止重复请求
  noCache: false,              // 是否添加时间戳防缓存
  timeout: 10000,              // 超时时间
  headers: {}                  // 自定义请求头
}
```

---

### 16.9 详细文档

更多详细信息请参考：
- `utils/README.md` - 完整使用文档
- `utils/ARCHITECTURE.md` - 架构设计文档
- `utils/examples/INSTALL.md` - 安装配置指南
- `utils/examples/` - 示例代码

---

### 16.10 注意事项

1. 首次使用前需配置 `utils/env.js` 中的 baseURL
2. 根据后端返回格式调整 `utils/request.js` 中的业务状态码
3. 根据后端 Token 格式调整请求拦截器中的 Token 注入方式
4. 小程序环境需在管理后台配置服务器域名白名单
5. 所有 API 接口建议统一在 `api/` 目录下管理，不要在组件中直接调用 request

---
