Skip to content
← 返回项目

案例研究 · 家里的小生意

订餐会员管理系统

我给妈妈的订餐工作室做的会员、餐卡、订餐和财务系统,手机和网页用的是同一个应用。

这个应用和代码都不公开,因为里面存的是真实的顾客数据,所以没有在线演示,也没有公开仓库。本页只讲系统怎么运作,不涉及谁在使用。

状态

已上线使用

开始

2026 年 4 月 22 日

平台

网页 · iOS/Android 测试版

角色

独立开发

TypeScriptExpoReact NativeHonoTurso (libSQL)Drizzle ORMZodargon2id + JWTVitestTurborepoVercelGitHub ActionsLinear

起点

我妈妈经营一家小小的订餐工作室。顾客先买预付餐卡,再在群里接龙,报第二天的午餐和晚餐。有这个系统之前,每天晚上的接龙要靠人工统计,再发消息转给下一个人;当天的订单、餐卡余额、收入和支出,最后都要录进一个 Excel 表。

我的目标不是改变工作室的做法,而是让每一步在发生的时候,由做这件事的人记一次。这样晚上的数字就不用再转一遍、再录一遍。

它做什么

员工可以建会员档案,给会员开卡、续卡、升级餐卡。订单可以一条条录,也可以批量录第二天的;每一份餐都从会员的餐卡里扣。手机上的出餐送餐视图,把每一份午餐和晚餐从待出餐推到已出餐,再到已送达。

卖卡和送达的餐会自动记进财务账,支出则手动录入。除此之外还有零售、餐盒标签打印、员工账号,以及记录改动的审计日志。

让数字对得上的几个决定

同一位会员当天的午餐和晚餐是两条独立的订单,各自走一个简单的状态流转:待出餐、已出餐、已送达。已送达和已取消都是终态,完成的订单不能事后被悄悄改掉。

取消订单时,把餐退回餐卡、冲销相关的财务记录、写一条审计日志,这几件事在同一个数据库事务里完成,所以餐卡余额和账本不会对不上。系统也默认人会出错:误点了送达,管理员可以纠正;送餐失败时,餐数也会在同一个事务里退回会员的餐卡。

下单前由服务器检查餐卡余额。请求发出后、返回之前,下单表单会锁住;单条下单的请求还会带一个幂等键,同一个键再提交一次,拿到的是第一次的结果,不会多出一条订单。

权限与安全

密码用 argon2id 做哈希。登录后发放短期有效的签名令牌(HS256 JWT,默认一天),在原生应用里存进 SecureStore。每个请求都会核对账号是否启用以及令牌版本,账号一停用就立刻失去访问权限;登录接口也做了限流。

账号分三级:超级管理员、管理员和员工。会员、餐卡、订单和财务的写操作可以只开放给白名单里的账号,这样只负责核对数字的管理员可以设为只读,不会误改数据。

怎么做出来的

项目是一个 pnpm 加 Turborepo 的 monorepo,分三部分:Expo 应用、部署在 Vercel 上的 Hono API,以及一个共享包,里面放 zod 校验规则、餐卡目录和格式化工具,让应用和 API 遵守同一套规则。每次部署都会自动跑 Drizzle 迁移;主分支上的每次改动,都由 GitHub Actions 跑类型检查和 Vitest 测试。

我把工作分阶段推进,前几个阶段都作为 Linear issue 来跟踪,每次提交都会注明对应的 issue。项目从 2026 年 4 月 22 日开始,第 0 到第 4 阶段(从登录,到会员、餐卡和订餐,再到出餐视图、记录编辑和审计日志)到 4 月 25 日都已上线。之后一直到 2026 年 7 月,又陆续加了零售、标签打印、整套界面重新设计、从 Expo SDK 51 升级到 54,以及列表虚拟化、减少数据库往返等性能优化。

接下来

还在计划里的有:次日接龙汇总、当日收工报表、Excel 导出,以及自动异地备份。

收获

给家里人做系统,也是在给用户做系统。工作室的一天本来就有自己的节奏,从晚上的接龙到最后一单送达。我要做的是贴合这个节奏,让每一步都留下记录,而不是让大家去迁就软件。

为妈妈的工作室而做。应用和代码不公开。

返回项目