这两年帮不少餐饮老板做过小程序,其中奶茶店是最典型的场景:SKU 不多、下单频繁、高峰期排队严重、复购靠会员。今天把一套已经上线运营的奶茶店小程序方案拆开讲,包含点单、规格选择、购物车、订单与会员四大模块,代码基于微信小程序原生开发,可直接迁移到其他点单类项目。
一、先想清楚:奶茶店小程序的核心链路
不要一上来就写页面,先把业务链路画出来。奶茶店小程序的主链路其实只有一条:
- 扫码进入小程序(桌贴码/杯贴码/朋友圈广告)
- 浏览菜单,选择商品与规格(杯型、糖度、冰量、加料)
- 加入购物车,确认订单,选择自取或外送
- 支付,生成取餐号,等待叫号
- 支付成功后引导注册会员、发券、沉淀复购
围绕这条链路,数据模型要提前设计好。我一般用三张核心表:category(分类)、product(商品)、sku(规格组合)。其中规格不要写死在商品表里,而是用「规格组 + 选项」的方式存储,方便后台灵活配置。
二、菜单与规格选择的数据结构
规格是奶茶店最容易被写乱的地方。推荐把规格抽象成规格组,每个组有必选/多选、单选上限等属性:
{
"id": 1001,
"name": "招牌珍珠奶茶",
"basePrice": 1200,
"specGroups": [
{ "key": "cup", "name": "杯型", "required": true, "multiple": false,
"options": [
{ "id": "cup_m", "name": "中杯", "priceDelta": 0 },
{ "id": "cup_l", "name": "大杯", "priceDelta": 300 }
]
},
{ "key": "sugar", "name": "糖度", "required": true, "multiple": false,
"options": [
{ "id": "s0", "name": "无糖", "priceDelta": 0 },
{ "id": "s5", "name": "五分糖", "priceDelta": 0 },
{ "id": "s7", "name": "七分糖", "priceDelta": 0 }
]
},
{ "key": "topping", "name": "加料", "required": false, "multiple": true,
"options": [
{ "id": "t_pearl", "name": "珍珠", "priceDelta": 200 },
{ "id": "t_pudding", "name": "布丁", "priceDelta": 300 }
]
}
]
}价格计算统一走一个函数,避免各处重复写逻辑:
function calcPrice(product, selected) {
let price = product.basePrice;
product.specGroups.forEach(g => {
const picked = selected[g.key] || [];
g.options.forEach(opt => {
if (picked.includes(opt.id)) price += opt.priceDelta;
});
});
return price;
}这样后台改价格、加规格,前端完全不用动代码。
三、购物车与本地缓存
奶茶店下单节奏快,购物车必须做到「秒开」。我用 wx.setStorageSync 把购物车持久化到本地,key 用 cart_{shopId},避免多门店数据串味。购物车条目用 productId + 规格签名 作为唯一键:
function makeCartKey(productId, selected) {
const parts = Object.keys(selected).sort()
.map(k => k + ':' + selected[k].slice().sort().join('|'));
return productId + '#' + parts.join('&');
}这样「中杯无糖加珍珠」和「大杯无糖加珍珠」会被识别为两条不同记录,不会互相覆盖。加购时如果 key 已存在,只做数量 +1,用户体验最顺。
四、订单与取餐号
支付成功后不要直接返回首页,而是跳到「取餐码」页面。取餐号建议由后端生成,格式如 A012,每天从 A001 重新计数。前端通过 wx.requestPayment 的回调拿到支付结果,再轮询订单状态:
async function pollOrder(orderId) {
for (let i = 0; i < 20; i++) {
const res = await request('/order/status', { orderId });
if (res.status !== 'PENDING') return res;
await sleep(2000);
}
return null;
}注意支付回调必须以后端异步通知为准,前端回调只用于跳转,否则容易被伪造。
五、会员与复购,才是利润点
很多开发者只做到点单就结束了,但奶茶店真正赚钱的是复购。建议在支付成功页做三件事:
- 引导一键注册会员,手机号授权即可,不做复杂表单
- 自动发一张「满 15 减 3」的券,有效期 7 天,制造回访理由
- 展示积分余额,并提示「再消费 X 元可兑换一杯」
会员体系不用一上来就做得很重,先做「积分 + 优惠券」两层即可。积分规则可以按实付金额 1:1 累计,兑换比例放在后台配置,方便运营随时调整。
六、几个容易踩的坑
- 并发下单导致取餐号重复:取餐号必须用数据库自增或 Redis 原子操作生成,不要用时间戳。
- 规格价格前端算、后端不算:后端一定要用同样的规则重新计算一次,防止篡改。
- 图片体积过大:奶茶店菜单图多,建议统一压缩到 200KB 以内,并开启 CDN 缓存。
- 忽略门店营业时间:非营业时间下单要拦截,否则第二天早上全是异常订单。
结语
奶茶店小程序的技术难度并不高,难的是把规格、购物车、订单、会员这几块串成一条顺滑的链路。先把数据模型设计对,前端代码会省下一半。如果你也在做点单类小程序,欢迎在评论区交流你遇到的坑。
评论 (0)
还没有评论,快来抢沙发吧~