1. 先搞清楚需求:农产品交易小程序到底要解决谁的问题
很多人做这种小程序,第一步就跳进写代码里了,结果页面做了一堆,真正上线跑单的时候才发现方向不对。我做完这整个项目后的第一个体会是:特色农产品交易系统的难点不在技术,而在需求建模。农产品不是标准工业品,你没法像卖数码产品那样用一张参数表搞定一个 SKU,所以必须先想明白你这套小程序是给谁用的,要替用户解决什么具体的、重复发生的难处。
1.1 卖家这边的真实痛点
我前期专门找了几位家里做果园、茶厂生意的朋友聊过。他们最折磨的事情是这样的:朋友圈发图卖货,熟人能买一次两次,新客建立信任的成本极高;日常订单靠记在本子上,时不时漏单、发错货;到了丰收季,价格波动快,想搞个限时预购活动,又没有一个能自动收款的工具。这些痛点的共性是很明显的:他们缺一个能承载商品展示、在线下单、收款、发货反馈的轻量工具,而微信小程序恰好符合"不用下载、打开就用、用完即走"的流量习惯,对卖方和买方都是最低门槛的解决方案。
1.2 买家这边的顾虑
买家买特色农产品,最担心的三件事:第一,东西是不是真的产地货,有没有以次充好;第二,规格到底是多少斤、什么等级,买回来发现和自己预期不符;第三,坏了、烂了怎么办,去找谁赔付。这三个问题反映到系统设计上,就是在商品详情里必须有产地信息、规格参数、实物图片、售后承诺这些要素,否则就只是一个普通的卖货页面,没有"信任感"可言。特色农产品和普通电商货品最大的差别,就是用户在付款前会反复确认"这箱水果到底值不值",页面上信息给得越具体,转化率越高。
1.3 项目功能边界:先做闭环,不贪大
功能清单是项目开始前必须锁死的东西。我的做法是分三个优先级:P0 必做、P1 尽量做、P2 下次再做。
| 功能模块 | 优先级 | 说明 |
|---|---|---|
| 商品浏览、搜索、分类 | P0 | 首页/分类页/搜索,商品按产地、品类筛选 |
| 商品详情、规格选择、加购 | P0 | 一个商品多个规格,规格决定价格和库存 |
| 购物车、提交订单、支付 | P0 | 微信支付闭环,订单状态流转 |
| 订单列表、发货、确认收货 | P0 | 用户和商家都能看到订单状态 |
| 地址管理、售后申请 | P1 | 地址簿增删改查,退款退换入口 |
| 优惠券、会员积分 | P1 | 提升复购,放在二期做也可以 |
| 多商家入驻 | P2 | 需要商户结算体系,个人起步阶段不做 |
| 直播带货、视频溯源 | P2 | 涉及推流和内容审核,基础闭环跑通后再加 |
把范围划清楚之后,整个项目的实际工作量立刻变得可控。一个单店自营、商品自采自销、商家发货的闭环,对个人开发者和初创团队来说是半年内能落地的体量。这个判断非常重要,因为它决定了你的数据库、接口、页面数量,也决定了后面上线审核的资质要求。
2. 技术路线怎么选:云开发、自建后端还是低代码
这一节是很多人在立项时纠结最久的地方。我一直觉得,技术选型没有绝对的好坏,只有合不合适。做特色农产品交易小程序,本质上做的是一个需要快速上线、频繁迭代、规模可控的电商闭环,所以选型要围绕开发效率、运维成本、上线资质、后续扩展四个维度来考虑。
2.1 三条路线的对比
我身边做类似项目的朋友,主流方案大概是这三种:
| 方案 | 开发速度 | 运维成本 | 费用 | 适合场景 |
|---|---|---|---|---|
| 原生小程序 + 微信云开发 | 快,前后端一体 | 低,免运维 | 有免费额度,付费包也不贵 | 个人开发者、毕业设计、初创验证 |
| 原生小程序 + 自建后端(Node/Java/PHP) | 慢,要自己写接口、部署服务器 | 高,要考虑带宽、数据库备份 | 服务器费用 | 已有后端团队、业务逻辑复杂 |
| 低代码平台(如微信微搭、第三方商城系统) | 最快 | 平台维护 | 组件和模板按年付费 | 没有开发能力的商家、快速出成品 |
我最终选了原生小程序 + 微信云开发。云开发提供云函数、云数据库、云存储和云调用,登录、支付、订阅消息这些微信生态能力都有封装,省掉了自己买服务器、配 SSL 证书、写鉴权中间件这套繁琐流程。对一个农产品交易项目来说,前期最要紧的是把业务闭环跑通,而不是在处理高并发上炫技。
2.2 选云开发的具体理由
这里多说几句,因为很多人对云开发有误解,觉得它不够"专业"。实际上,微信云开发的底层就是一套托管在腾讯侧的无服务器架构,你写的云函数运行在 Node.js 环境里,云数据库是文档型数据库,云存储可以存取商品图片和一些临时文件。对交易类场景来说,它有几个非常实用的点:
- 免鉴权拿用户身份:在云函数里通过
cloud.getWXContext()直接拿到 OPENID,不用自己维护复杂的 session。 - 微信支付云调用:统一下单、支付回调都可以通过云函数里的云调用完成,比自己拼签名、做证书管理要省事得多。
- 定时触发器:订单超时未支付、预售活动到点自动关闭,这些都可以用云函数定时器实现。
- 控制台直接看数据:商品表、订单表、用户表都在云开发控制台里可视化管理,对后期运营梳理数据帮助很大。
当然,如果你做这个项目是为了应付企业级生产环境,或者团队后端已经很成熟了,那走自建后端完全没问题。但从"设计并实现一个特色农产品交易小程序"这个项目目标出发,云开发是最经济和稳妥的起跑姿势。
2.3 项目目录与工程结构
顺着这个选型,我把整个项目的工程结构定为两层:前端小程序页面+云函数后端。前端按功能划分为四个主 Tab 页面和一些业务页面,云函数按领域拆分,避免一个函数里堆几百行代码。
miniprogram/ pages/ index/ 首页 category/ 分类页 cart/ 购物车 user/ 我的 goods/ 商品列表 detail/ 商品详情 order/ 订单列表 checkout/ 确认订单 address/ 地址管理 order-detail/ 订单详情 aftersale/ 售后申请 components/ sku-popup/ 规格选择弹层 empty-view/ 空状态占位 price/ 价格展示 goods-card/ 商品卡片 utils/ nav.js 导航栏高度适配 format.js 金额、时间格式化 app.js app.json cloudfunctions/ login/ 登录获取 openid goods/ 商品列表、详情、上下架 cart/ 购物车增删改查 order/ 创建订单、支付、状态流转 payCallback/ 支付结果回调 address/ 地址管理 aftersale/ 售后单处理 wxSubscribe/ 订阅消息下发这个目录的好处是:页面和接口对应关系清晰,后面增加功能不会牵一发动全身。云函数按业务域拆,单个函数代码量控制在两三百行以内,排查问题的时候能快速定位。
3. 数据模型设计:把"非标"农产品装进标准化的表结构里
如果说架构是骨架,那数据模型就是血肉。特色农产品系统最容易翻车的地方,就是把商品当成普通电商商品来做一张简单的商品表,结果发现一个"赣南脐橙"有 5斤装、9斤装、箱装三个价格,一个"阳澄湖大闸蟹"有公蟹母蟹、不同规格的套餐,订单里完全对不上号。所以数据模型的设计我花了比写页面更长的时间。
3.1 商品与 SKU 的拆分
我最终用的是经典的"商品 SPU + 规格 SKU"模型。**SPU(标准产品单位)**描述一件商品的公共信息,比如名称、产地、品类、主图、详情;**SKU(库存量单位)**描述具体的售卖规格,比如"5斤中果装""9斤大果装",SKU 级别存价格、库存和编码。
两张表的核心字段大概是这样的:
商品表(product):
| 字段 | 类型 | 说明 |
|---|---|---|
| _id | string | 主键,自动生成 |
| name | string | 商品名称 |
| category | string | 分类,如水果/蔬菜/粮油 |
| origin | string | 产地,如赣州/烟台 |
| cover | string | 封面图 fileID |
| images | array | 详情轮播图 |
| detail | string | 富文本详情(可存图片链) |
| certification | string | 认证信息,如绿色食品 |
| status | number | 0下架/1上架 |
| createdAt | date | 创建时间 |
规格表(product_sku):
| 字段 | 类型 | 说明 |
|---|---|---|
| _id | string | 主键 |
| productId | string | 关联商品 |
| skuName | string | 规格描述,如"5斤装" |
| price | number | 单价,单位分 |
| stock | number | 库存 |
| weight | number | 预估重量,用于运费计算 |
| image | string | 该规格的专属图片 |
农产品有个特殊性:同一棵树上摘下来的果子,个头、甜度都会有差异,所以很多商品并不适合做严格的规格管理。我的经验是,规格粒度不要细到"单个果径",而是要细到"顾客能明确感知的规格差异":重量装、礼盒装、家庭装这种。规格越多,库存同步越容易出错,在上线初期宁可少设规格。
3.2 订单模型和状态机
订单表是交易系统的核心,字段设计要兼顾业务完整性和后期写入的便利性。
订单表(order):
| 字段 | 类型 | 说明 |
|---|---|---|
| orderNo | string | 订单号,可在云函数里生成 |
| openid | string | 下单用户 |
| skuList | array | 包含 productId、skuId、数量、单价快照 |
| totalAmount | number | 商品总额(分) |
| freight | number | 运费(分) |
| payAmount | number | 实付金额 |
| addressSnapshot | object | 下单时候的完整地址快照 |
| status | number | 状态,见下方状态机 |
| createTime / payTime / shipTime / receiveTime | date | 各节点时间 |
| logistics | object | 物流公司、快递单号 |
订单状态机我设计成五个主状态,外加两个异常状态:
- 10 待支付:创建订单后进入,超时未支付由定时任务自动关闭
- 20 已支付待发货:微信支付成功回调后进入,商家在后台发货
- 30 已发货:填写物流单号后进入,用户可见物流信息
- 40 已完成:用户确认收货,或者发货后超过一定时间自动确认
- 50 已取消:用户主动取消或超时关闭
- 60 退款中 / 70 退款完成:售后流程涉及
状态机的关键是买单后动作的闭环。农产品生鲜场景里,"未发货全额退、已发货生鲜不支持无理由退、有质量问题部分退"这些规则要在代码里也落地,不能只写在详情页的文字声明里。
3.3 地址、购物车与售后表的取舍
地址表字段相对固定(收件人、手机号、省市区、详细地址、是否默认),购物车表我会冗余商品名称、规格名称、价格、封面图,这样购物车列表不用每打开一次都联表查商品详情,性能上更稳定。售后表则是关联订单号和 SKU 列表,记录退款原因、图片凭证、退款金额和处理结果。
需要提醒的是,云数据库的查询性能和关系型数据库不一样,表之间没有 join,所以该冗余的地方要冗余,该存快照的地方要存快照,否则页面渲染的时候会出现大量 DDoS 式的循环查询。这也是新手团队最容易踩的坑:照搬 MySQL 的逻辑去设计 MongoDB 风格的数据结构,最后查询慢到崩溃。
4. 核心功能实现:首页加载、商品详情、登录、支付一条龙
数据模型定好之后,开发节奏就顺手了。这一节我挑几个最核心、也是网络上资料最零散的部分来讲:首页的商品分页加载、商品详情的规格选择、登录态的完整链路、微信支付的接入姿势。
4.1 首页的商品列表与"加载更多"
首页这是用户进来的第一屏,直接决定留存。我用了"商品卡片双列网格 + 触底加载更多"的方案,数据请求走云数据库分页查询。代码框架如下:
// miniprogram/pages/index/index.js Page({ data: { productList: [], page: 0, pageSize: 10, finished: false, loading: false }, async onLoad() { this.loadProducts() }, async onPullDownRefresh() { this.setData({ productList: [], page: 0, finished: false }) await this.loadProducts() wx.stopPullDownRefresh() }, async onReachBottom() { // 触底加载更多:防止重复请求 if (this.data.finished || this.data.loading) return await this.loadProducts() }, async loadProducts() { this.setData({ loading: true }) const db = wx.cloud.database() const res = await db.collection('product') .where({ status: 1 }) .orderBy('createdAt', 'desc') .skip(this.data.page * this.data.pageSize) .limit(this.data.pageSize) .field({ name: true, cover: true, price: true, origin: true }) .get() const list = [...this.data.productList, ...res.data] this.setData({ productList: list, page: this.data.page + 1, finished: res.data.length < this.data.pageSize, loading: false }) } })这里有几个细节值得展开。第一,防重复:finished和loading两个开关缺一不可,否则手指快速滑动时,onReachBottom可能连续触发多次,造成重复数据。第二,用field指定返回字段:首页列表只需要名称、封面、价格、产地,没必要把详情和图片数组都拉下来,这对提升加载速度效果显著。第三,云数据库分页有上限:skip在数据量大到一定程度时性能下降,但如果你的商品量在几千条以内,这个方案完全够用,不必过早引入搜索服务。
4.2 商品详情页的规格选择交互
商品详情页是整个项目交互最重的页面,核心是规格选择弹层。用户点击"加入购物车"或"立即购买"时,底部弹出规格选择层,里面展示当前商品的 SKU 列表、价格、库存。
规格选择我建议直接用卡片式单选 + 实时价格联动,而不是用微信自带的radio组件,原因是原生单选框样式和业务场景很难匹配,用户对"点某个卡片选中规格"的反馈会更直观。核心交互逻辑是:
// miniprogram/components/sku-popup/index.js Component({ data: { selectedSkuId: null, quantity: 1 }, methods: { selectSku(e) { const skuId = e.currentTarget.dataset.skuId const sku = this.data.skuList.find(item => item._id === skuId) this.setData({ selectedSkuId: skuId, price: sku.price, stock: sku.stock }) }, addCart() { if (!this.data.selectedSkuId) { wx.showToast({ title: '请先选择规格', icon: 'none' }) return } // 调用云函数 cart.add 写入购物车 } } })农产品场景下,详情页的"信任元素"再强调一遍:产地实拍图(最好是带地理位置的)、采摘/发货时效说明、坏果赔付条款。这些信息不一定都是代码实现的,但作为数据字段一定要预留位置。我在商品详情页底部专门放了一个"产地溯源"区域,展示几张果园/农田实拍图和简单的文字介绍,转化数据比纯参数表高了不少。
4.3 登录态:wx.login 那套链路要理顺
很多新手一上来就在前端wx.login拿 code,然后直接当作登录凭证存本地,这是不对的。code的有效期只有五分钟,而且只能用一次,必须交给后端去换取用户的 openid。
使用云开发时,最简单的方案是彻底绕开 code2Session 的繁琐环节:
// cloudfunctions/login/index.js const cloud = require('wx-server-sdk') cloud.init() exports.main = async () => { const { OPENID } = cloud.getWXContext() const db = cloud.database() const userCollection = db.collection('user') const exist = await userCollection.where({ openid: OPENID }).count() if (exist.total === 0) { await userCollection.add({ data: { openid: OPENID, nickname: '', avatar: '', createdAt: Date.now() } }) } return { openid: OPENID } }前端只需要在启动时调用这个云函数,拿到 openid 后存本地,之后所有下单、加购、查订单操作都把 openid 作为查询条件之一。用户手机号绑定是另一层逻辑,getPhoneNumber按钮拿到动态令牌code之后,需要再调云开发的手机号解析接口。我的经验是:登录闭环不等同于手机号绑定,很多用户只浏览不买,没必要一进来就强制授权手机号,可以在提交订单的时候再引导绑定。
4.4 微信支付:个人开发者绕不过的那道坎
支付是整个系统最敏感也最容易卡壳的部分。这里必须说清楚一个现实:微信支付要求小程序主体是企业或个体工商户,纯个人主体无法申请微信支付商户号。做毕业设计的话,可以用"模拟支付"代替,但在真实上线运营场景中,没有支付闭环就等于没有交易系统。
个人主体的两种务实的替代方案:
- 注册个体工商户:成本低,很多地方可以线上办理,拿到营业执照后即可用个体户主体申请小程序和微信支付,并能使用"商家自营"类目。
- 先跑通模拟支付:项目演示阶段,用云函数模拟创建订单后的支付成功回调,把订单状态流转到"已支付待发货",页面 UI 和数据流都是完整的,后续换掉支付模块的成本很小。
真正接入微信支付时,云开发的cloudPay.unifiedOrder可以省掉大量签名和证书的工作:
// cloudfunctions/order/pay.js const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) exports.main = async (event) => { const { orderNo, body, totalFee } = event const res = await cloud.cloudPay.unifiedOrder({ body, outTradeNo: orderNo, spbillCreateIp: '127.0.0.1', subMchId: '你的商户号', totalFee, // 单位是分 tradeType: 'JSAPI' }) return res }支付回调的验签处理也必须放在服务端云函数里,不能在前端拼接支付结果就改订单状态,否则用户可以伪造回调。所有支付成功逻辑都以云函数收到微信支付回调、且校验通过为准。
5. 上线前必须趟过的一串坑
项目写出来只是第一步,从"能跑"到"能上线"之间,有一堆零碎但致命的问题。这部分我整理成了排查清单,都是我真实踩过的。
5.1 主包体积超限:2MB 只是一道门槛
项目中后期最烦的就是这个报错:source size 2612kb exceed max limit 2mb。我一开始把商品详情富文本图片、几个 UI 库的完整包都塞进了主包里,主包直接冲到 2.6MB,上传审核直接被拒。解决方法是三板斧:
- 图片一律走云存储,本地只放 tab 栏图标和少量必要的启动图,并压缩到几 KB 级别。
- 拆分分包:把售后、订单详情、地址管理等低频页面放到分包里,主包只保留首页、分类、购物车、我的这几个高频页面。
- 按需引入组件:如果引入了第三方 UI 组件库,检查有没有打包很多用不到的组件,改成按需注册。
压缩图片的实操技巧:云存储里的商品图片可以用在线工具把原图从 1MB 压到 100KB 左右,肉眼几乎无差别,但加载速度会快很多。记住,小程序体积限制不只影响审核,也直接决定用户首屏加载速度,这是一个既关系到上线也关系到体验的指标。
5.2 顶部导航栏高度:不同机型对不齐的老问题
如果页面使用了自定义导航栏(为了在顶部放搜索框或自定义标题),那么 iOS 和安卓的刘海屏、灵动岛的高度是不同的。直接写死64rpx这种高度的做法,真机上一定翻车。
正确做法是动态计算,核心代码:
// miniprogram/utils/nav.js function getNavBarInfo() { const menu = wx.getMenuButtonBoundingClientRect() // 胶囊按钮位置 const { statusBarHeight } = wx.getWindowInfo() const navBarHeight = (menu.top - statusBarHeight) * 2 + menu.height return { statusBarHeight, navBarHeight, menuTop: menu.top, menuHeight: menu.height } } module.exports = { getNavBarInfo }拿到这个数据后,在 App 启动时存入全局变量,所有自定义导航栏页面统一使用。底部如果用了自定义 tabBar 或者吸底按钮,还需要处理env(safe-area-inset-bottom),否则 iPhone 底部会被手势条遮挡。这类边界细节代码量不大,但能直接决定上线后在用户手机上的第一观感。
5.3 体验版分发与真机调试:发给别人试用怎么搞
开发完小程序,要收集朋友几天的试用反馈,很多人不知道怎么把开发者工具里的小程序发给别人。这里要分清三个版本:
- 开发版:开发者工具点"预览",生成二维码,只有开发者本人和管理员能扫开。
- 体验版:在小程序管理后台或开发者工具中"上传代码",然后在后台"版本管理"里将某个版本设为体验版,再把体验二维码发给已添加到体验成员列表里的人。
- 正式版:提交审核通过后发布,所有用户可见。
所以收集试用反馈的正确姿势是:上传版本到后台 → 添加体验成员 → 把体验版二维码发给这些人 → 让他们用几天并记录问题。需要注意,体验版本更新后,体验成员需要重新扫码或者在小程序后台刷新版本,否则一直停留在老版本上。
真机调试时如果怀疑请求被干扰、数据没拉到,可以借助抓包工具来看请求链路。对小程序场景,电脑上装抓包工具、手机 Wi-Fi 代理指向电脑 IP,并安装对应证书,就能看到小程序的 HTTPS 请求。不过更省事的做法是直接用微信开发者工具自带的"真机调试"功能,它集成了 Network 面板,不需要额外抓包。只有当你需要验证服务端接口传参或排查第三方接口联调问题时,再上抓包工具。
5.4 审核被拒:类目资质和话术比代码重要
微信审核是上线前玄学感最强的一环。特产交易小程序最容易踩的雷是类目选错。你要卖食品,就必须走"商家自营-食品"类目,这个类目需要提供营业执照、食品经营许可证等资质,个人主体基本没戏。如果是初级农产品(未加工的蔬菜、水果),有的情况下资质要求会宽松一些,但最稳妥的方案还是用个体工商户或企业主体来运营,这也是我前面反复强调小额个体执照的原因。
提交审核时,页面截图和简介要写得直白:这是做什么的、有哪些页面、谁在用。我见过太多因为"页面功能不完整""测试数据无法体验"被拒的案例,所以给审核员留一个能直接体验的账号路径很重要,比如在备注里写清楚"测试账号可正常下单,支持模拟发货"。审核的目的是确认你的产品是真实可用的,不是故意卡你。
还有一个农产品项目特有的点:不要在简介和详情页夸大保健功效,什么"抗癌""降血压"这类词千万别出现,会被判违规。老老实实写"新鲜采摘、产地直发"就够了。
6. 上线之后,交易系统的要害全在交易之外的环节
代码上线只是开始,真正暴露问题的是运营。农产品交易小程序跑一个月下来,我发现最耗精力的不是改 bug,而是处理那些代码没预料到的现实问题。这一节聊聊我从数据反馈里得出的经验,算是给后来人打个预防针。
6.1 物流履约是生死线
农产品和服装鞋帽最大的差别在物流。水果生鲜对时效要求极高,普通快递塑封袋包装两三天就到,但如果是跨省的生鲜水果,箱子的防震缓冲、冰袋数量、发货时效、坏果率这些都需要提前测算。我的建议是上线初期只做本省或邻近省份的订单,运费模板按地区和重量设置好,避免冷链不可控带来大量售后。
预售模式在这里非常有用。农产品是季节性、强时效的,果园还没熟就能挂预售链接,成熟后统一采摘、统一发货,既能提前回笼资金,又避免了库存积压的损耗。代码上,预售商品就是给订单加一个isPreSale标记,发货时间承诺在详情页写清楚即可。
6.2 售后规则要前置,不能等纠纷来了再想
生鲜商品天然有损耗,坏果率不可能为零。售后规则必须在上线前就写好,并且写进商品详情页。我实践下来比较好用的模板是:
收货后 24 小时内,如有腐烂、破损、缺重问题,请拍照并联系客服。坏果按比例赔付,烂果超过一半可补发或全额退款。
技术上,售后表要记录用户的图片凭证和退款原因,订单状态能流转到"退款中",商家确认后执行退款。这里要特别注意一个细节:退款金额不一定是全额退款,按比例赔付时,退款单里要能填一个部分金额。很多新手只做了"全额退款"按钮,结果处理坏果赔付的时候得手动改数据库,非常坑。
6.3 复购与触达:订阅消息是唯一抓手
小程序用完即走,用户买完一次可能就再也找不到了。目前小程序给开发者留下的主动触达渠道并不多,订阅消息是合规且触达率较高的一种。用户可以订阅"订单发货通知""售后处理结果通知",你可以在发货成功、售后处理完成时向用户下发一条服务通知。注意订阅消息的规则:每次点击授权仅能下发一条,所以要在合适的节点引导用户多次订阅,最好在支付成功页做一次性授权,在订单详情页再引导一次,别浪费授权机会。
复购的另一个抓手是优惠券。在支付成功页发放"满 99 减 10"的复购券,用户优惠券到账后再来消费的转化效果比邮件和短信都好。优惠券表的字段设计要注意有效期、使用门槛和使用范围,别搞得太复杂。
6.4 数据看板:从下单率看懂用户行为
云开发控制台可以直接看数据库的读写量,但这些运维指标没法反映业务。我在"我的"页面里埋了几条统计:商品曝光数、商品点击量、加入购物车次数、下单转化率、支付成功率。农产品项目的用户决策周期比普通日用品长,很多人会把商品加购物车里放几天再买,所以不要因为加购后不及时支付就判定用户流失,可以针对"加购未支付"的用户做一次订阅消息或客服消息关怀,询问是否有疑问。这条链路跑下来,支付转化率比光看首页 UV 要真实得多。
最后说几句个人的实在话
这个项目从需求梳理到上线运营,前前后后花了两个多月,最大的感悟是:小程序只是一个载体,真正让我做出判断的,是对"特色农产品交易"这个场景的理解深度。代码写得好可以让系统不崩,但只有把产地信任、规格表达、物流履约、售后规则这些业务细节想明白,这个系统才真正有人愿意用它下单。
如果让我重新做一遍,我会先把商品详情页的信任内容和售后规则文案写好,再动手写购物车和支付。技术在后面可以随时补,但业务逻辑漏了,返工成本会高到你怀疑人生。希望这篇复盘能帮你少踩几个坑,尤其是那些我在审核和物流环节掉进去的坑。