为什么宠物洗护店需要一个预约小程序
做宠物洗护这行的朋友应该都有体会:周末和节假日永远是爆单状态,客人打电话、发微信、到店问,前台一个人根本忙不过来。更麻烦的是,洗护服务时长差异极大——小型犬洗澡吹干可能40分钟,大型犬加做SPA、剪毛、药浴可能要三小时。如果排期靠纸笔或者Excel,超约、撞单几乎是必然。
我去年帮一家连锁宠物店做了个预约小程序,上线三个月后,前台电话量下降了约六成,客户爽约率也从两成降到了8%左右。这篇文章就把整套开发思路和关键实现拆开讲一遍,适合想接类似外包或者自己做产品的独立开发者参考。
核心功能拆解
不要一上来就写代码,先把业务闭环想清楚。宠物洗护预约小程序的最小可用版本(MVP)应该包含这几块:
- 宠物档案:品种、体重、毛量、是否有皮肤病或应激史,这些直接决定服务时长和报价。
- 服务项目与定价:按体型+服务类型组合计价,比如「中型犬+基础洗护」和「中型犬+精致造型」价格不同。
- 技师排期:每个技师每天的可预约时段,需要扣除已有订单和休息时间。
- 预约下单:选宠物、选服务、选时段、支付定金。
- 消息通知:预约成功、到店前2小时提醒、服务完成通知。
技术选型:为什么我推荐微信云开发
这类项目客户预算通常不高,但要求上线快、后期维护省心。我的方案是微信小程序原生 + 云开发(CloudBase)。理由很实在:
- 不用自己买服务器、配域名、搞HTTPS证书,省掉一堆运维成本。
- 云数据库、云函数、云存储开箱即用,订阅消息也能直接在云函数里调。
- 对于中小宠物店,日订单量几百条,云开发的免费额度基本够用,客户续费压力小。
如果客户明确要做多门店SaaS、需要复杂报表,再考虑自建后端。但多数单店场景,云开发真的够。
数据库设计要点
云数据库是文档型的,设计时要注意把「经常一起查」的数据放在一起,减少联表。核心集合我一般这么建:
// pets 宠物档案
{
_id: "pet_001",
_openid: "user_openid",
name: "豆豆",
breed: "柯基",
weight: 12.5,
sizeType: "medium", // small / medium / large
notes: "怕吹风机,需安抚"
}
// services 服务项目
{
_id: "svc_001",
name: "基础洗护",
priceMap: { small: 68, medium: 98, large: 158 },
durationMap: { small: 40, medium: 60, large: 90 } // 分钟
}
// appointments 预约单
{
_id: "apt_001",
_openid: "user_openid",
petId: "pet_001",
serviceId: "svc_001",
staffId: "staff_001",
startTime: 1735689600000,
endTime: 1735693200000,
status: "confirmed", // pending/confirmed/done/cancelled
deposit: 20
}注意 startTime 和 endTime 存时间戳,方便做区间查询和冲突检测。体型用枚举而不是直接存价格,改价时只改服务表,历史订单不受影响。
排期冲突检测:整个系统最关键的一段逻辑
预约系统最怕的就是同一技师同一时段被约两次。我的做法是在云函数里做原子性校验,而不是只靠前端置灰。前端置灰只是体验优化,真正的防线在服务端。
// 云函数 checkAndCreateAppointment
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
const _ = db.command
exports.main = async (event) => {
const { staffId, startTime, endTime, petId, serviceId } = event
// 1. 查询该技师在目标时段是否已有未取消的预约
const conflict = await db.collection('appointments')
.where({
staffId,
status: _.in(['pending', 'confirmed']),
startTime: _.lt(endTime),
endTime: _.gt(startTime)
})
.count()
if (conflict.total > 0) {
return { code: 409, msg: '该时段已被预约,请重新选择' }
}
// 2. 无冲突则创建订单
const res = await db.collection('appointments').add({
data: {
staffId, startTime, endTime, petId, serviceId,
status: 'pending',
createTime: Date.now()
}
})
return { code: 0, data: res._id }
}这里用了经典的区间重叠判断:新开始 < 旧结束 且 新结束 > 旧开始。并发场景下,云函数单实例执行加上数据库查询,已经能挡住绝大多数重复提交。如果客户量级很大,可以考虑用云开发的数据库事务或者加一个「时段锁」集合。
订阅消息与到店提醒
小程序不能主动给用户发消息,必须走订阅消息。用户下单时一次性订阅「预约结果通知」和「服务提醒」,然后在云函数里调用:
await cloud.openapi.subscribeMessage.send({
touser: openid,
templateId: '你的模板ID',
page: 'pages/appointment/detail?id=' + aptId,
data: {
thing1: { value: '豆豆 · 基础洗护' },
time2: { value: '2025-01-01 14:00' },
thing3: { value: '到店前请提前10分钟' }
}
})到店前2小时的提醒,用云函数的定时触发器每10分钟扫一次未来2小时内即将开始的订单,发过提醒的打标记避免重复发送。
几个踩过的坑
- 时区问题:云函数默认UTC时间,做「今天/明天」筛选时一定要手动加8小时偏移,否则凌晨时段会错乱。
- 定金退款:微信支付退款要单独申请商户号并配置,提前和客户确认好爽约规则,最好在页面上写清楚。
- 技师端:别只做用户端,给技师做一个简单的接单/完成页面,用同一个后台,权限用角色字段区分。
小结
宠物洗护预约小程序的技术难度其实不高,难点在于把业务规则(体型定价、时长、排期、爽约)翻译成清晰的数据结构和校验逻辑。建议先用云开发把MVP跑通,上线收反馈,再逐步加会员卡、储值、多门店这些模块。独立开发者接这类项目,两周左右做出可用版本是比较现实的节奏。
评论 (0)
还没有评论,快来抢沙发吧~