# 佳友厚苑 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 ---