微信小程序实战:基于原生框架 + 云开发实现 干饭足迹小程序,美食打卡、地图探索与消费报告

最近做了一个微信小程序项目 foodie-footprint,想把"吃过什么、花了多少、值不值得再来"这件事记录下来。项目不算复杂,但在实现过程中把登录鉴权、打卡记录、图片上传、位置选择、地图足迹、收藏体系和消费统计这些典型能力基本都跑通了。
这篇文章就结合当前项目,聊聊这个小程序从 0 到 1 的实现思路,以及几个我觉得比较值得记录下来的技术细节。

01. 这个项目是怎么冒出来的

这个小程序叫 foodie-footprint,我自己给它起的中文名是"干饭足迹"。

一开始想做它,原因不复杂,甚至有点过于普通了。

就是那种很常见的时刻:吃到一家店,觉得"不错,下次再来",过两周名字忘了;或者总觉得自己最近也没怎么花钱,结果一翻账单,奶茶、咖啡、简餐、夜宵全算上,数字相当诚实。

我后来发现,和"吃饭"有关的记忆其实特别容易散。你会记得某一顿当下很开心,但不太会系统地记住:

  • 这家店到底叫什么
  • 我花了多少钱
  • 它在哪
  • 我到底还想不想再去

所以我就想,干脆做个小程序,把这些事情认真记下来。

最开始我以为它会是个很轻的小东西,结果越做越不像"一个表单页",慢慢长成了一个完整项目:

  • 微信登录
  • 打卡记录
  • 图片上传
  • 地点选择
  • 地图足迹
  • 收藏店铺
  • 消费报告
  • 成就勋章

它不是一个多大的系统,但它确实已经有了点"像产品"的样子。

02. 我没用很重的技术栈

这个项目的技术选型挺老实的,没有故意上难度:

  • 微信小程序原生框架
  • tdesign-miniprogram
  • qiun-data-charts
  • 微信云开发
  • 云数据库
  • 云存储

为什么这么选?

因为这种项目最怕一上来就把自己埋进技术栈里,页面还没跑通,架构先讲半天。对我来说,这个项目最重要的是先把"记录吃饭"这件事做顺,再考虑怎么做得更好看、更完整。

原生小程序 + 云开发这套东西,有个很实际的好处:你离运行环境很近,很多事情不需要绕。

尤其是地图、登录、云函数、文件上传这种能力,越贴近平台,越省心。

03. 表面上是 12 个页面,本质上是在做一条顺滑的使用路径

这个项目现在有这些页面:

  • 首页
  • 登录页
  • 打卡页
  • 地图页
  • 收藏页
  • 记录页
  • 详情页
  • 报告页
  • 我的页面
  • 成就页
  • 资料编辑页
  • 反馈页

看起来页面很多,但真正麻烦的其实不是页面数量,而是这些页面之间怎么接。

我做这类项目的时候,最怕一种状态:每个页面单看都还行,但连起来特别拧巴。

比如:

  • 没登录时,是直接拦,还是先让你看看
  • 打完卡以后,首页要不要马上更新
  • 从地图页去补记录,最后应该回哪里
  • 收藏和记录之间,到底该怎么关联

这些问题每个都不大,但只要处理得糙一点,整个项目就会看起来很散。

后来我越来越觉得,一个项目"像不像真的会有人用",往往就看这些地方。

04. 首页最怕做成"几个数字摆在那儿"

很多练手项目的首页都会有一个问题:它不是首页,它只是一个入口板。

放几个统计数字,再放几个按钮,乍一看挺完整,实际上没什么承接能力。

我这个项目里,首页主要做两件事:

  1. 展示累计打卡次数和累计消费金额
  2. 展示最近的打卡时间线

对应的逻辑也很直接:

  • getStats 拉统计
  • getRecords 拉记录列表

但真正让我花心思的,不是"怎么显示",而是"更新之后怎么办"。

因为这不是一个纯展示项目。用户会新增记录、编辑记录、删除记录。如果每次操作完都粗暴地整页重拉,虽然也能用,但体验很硬,像一块没磨过边的板子。

所以我后面补了一层本地同步逻辑。简单讲,就是某些数据先在本地做轻量更新,等页面真的回来了,再决定要不要全量刷新。

这个设计不算多高深,但它很值。因为用户感受到的不是"这里做了同步优化",而是"这个项目反应挺顺"。

05. 打卡页看着像表单,实际上是项目里最啰嗦的一页

如果只从 UI 看,打卡页无非就是填内容、传图片、点提交。

但真正做起来,它其实特别碎。

要处理的东西有:

  • 店名
  • 金额
  • 分类
  • 标签
  • 时间
  • 评分
  • 备注
  • 图片
  • 地点

而且还不只是新增,还得支持编辑。

新增和编辑,我最后没拆成两页

我一开始也想过,新增一页,编辑一页,看起来很清楚。

后来想明白了,没必要。

这两种场景的主体逻辑几乎是同一套:图片上传、金额输入、分类标签、时间选择、地点选择,全都一样。硬拆成两页,除了让自己后面维护更烦,没什么实际收益。

所以最后就是一个 add 页,两种模式切换。

这种取舍我后来越来越常做:如果两个页面八成一样,那就别为了"形式上分开"硬拆。

图片上传这件事,最怕"功能有了,体验没了"

图片上传很容易写成"能传就行",但真上手一试就知道不够。

原图一大,问题就来了:

  • 上传慢
  • 等待感重
  • 网络差的时候很容易卡住

所以我在前端加了一层压缩判断。图片大于阈值,就先压一下,再传云存储。

这个动作本身不稀奇,但很必要。因为记录、详情、收藏这些页面最后都会吃到图片。如果源头不收一下,后面全都要跟着受罪。

位置选择不是调个 API 就结束

一开始我真以为 chooseLocation 调起来就完了。

结果一写才发现,前面还有一串现实问题:

  • 用户有没有授权位置权限
  • 拒绝过以后怎么处理
  • 已经有位置时,要不要拿它做默认点
  • 用户取消选点,要不要提示

这些逻辑都不难,但很容易偷懒。如果偷懒,项目不会立刻坏,只是会给人一种不太稳的感觉。

我现在做项目越来越信一个判断:很多"产品感差一点"的地方,本质上就是这些小事没处理。

06. 地图页是我做着做着开始上头的一块

我本来对地图页的预期很简单:把吃过的店标到地图上,看看自己都在哪吃过饭。

后来做到一半,我突然觉得,如果它只是"展示足迹",那有点浪费。

既然已经有位置数据了,不如干脆把它做成一个能继续帮我找店的页面。

于是我往里面继续加:

  • 分类筛选
  • 关键词搜索
  • 距离最近排序
  • 只看收藏
  • marker 和底部卡片联动

加完以后,地图页的味道就变了。它不再只是一个"看一眼"的页面,而是变成了一个你真有可能反复打开的页面。

有时候不知道吃什么,翻翻它,反而挺有用。

不是所有记录都应该直接上地图

真实数据不会那么听话。总会有一些记录的位置不完整,或者根本不适合渲染到地图上。

所以我这里不是查出来就直接丢 marker,而是先做一轮标准化和过滤。只保留那些位置信息真的成立的记录。

这一步做完,页面的稳定感会好很多。

地图和卡片不联动的话,地图页就会很木

我很不喜欢那种地图归地图、列表归列表的页面。

所以这里做成了:

  • 点地图上的点,下面卡片跟着切
  • 滑下面卡片,地图中心和高亮 marker 跟着动

其实写法不复杂,但效果特别明显。用户不会说"你这个联动真优雅",他只会觉得"嗯,这页面挺顺手"。

而这就够了。

07. 登录这件事,最烦的从来不是"点一下登录"

很多小程序项目的登录都写得很快:有按钮,点了能进,就算完成。

但只要项目稍微像样一点,登录真正麻烦的地方就会冒出来:

  • 登录态怎么存
  • token 什么时候过期
  • 过期以后怎么处理
  • 每个页面是不是都要自己判断一遍

我这里是用 login_handler 云函数做登录,逻辑不花哨,就是:

  • 通过微信上下文拿 OPENID
  • users
  • 生成 authToken
  • 带上过期时间返回给前端

前端再统一做:

  • 本地缓存登录信息
  • 请求自动带 token
  • token 失效自动清理
  • 需要登录的页面统一拦截

做完之后最大的感受是,页面会清爽很多。

因为每个页面都不用再写一遍"如果没登录怎么办"的碎逻辑,很多事收口到公共工具里,后面迭代会轻松不少。

08. 收藏我单独做了一套,没有塞进记录表里凑合

这个地方我一开始也想过,是不是直接在记录上挂个 isFavorite 就完了。

后来想想,还是不对。

因为"收藏"不是"这条记录被标了一下",它更像是"我对这家店有持续兴趣"。

所以我单独做了 favorites 集合。

这么一拆,整个东西就活了很多:

  • 收藏可以有自己的列表页
  • 可以记录收藏来源
  • 可以和地图、详情、记录产生更自然的关系

比如来源我就做了几种:

  • 朋友推荐
  • 小红书看到
  • 偶然路过

这种信息很轻,但它会让一条收藏不只是"点了一下星",而是带着一点场景感。

09. 报告页我果断扔给云函数了

报告页这种东西,我的态度一直很明确:能在服务端聚合,就别让前端硬算。

因为它本质上不是展示页,而是统计页。

这里面要做的事包括:

  • 累计消费
  • 累计打卡
  • 平均消费
  • 最近 7 天 / 4 周趋势
  • 分类占比
  • 趣味数据

如果这些都让前端自己拉全量记录来算,短期能跑,后面一定越来越沉。

所以我这里直接让 getReportStats 云函数来聚合,前端只负责拿结果和渲染图表。

这样后面你想加一个统计维度,脑子也不会炸。

10. 成就系统不是刚需,但它真的很适合这类项目

说实话,成就系统不是这个项目"必须有"的功能。

但我就是觉得,这种偏生活记录的小程序,如果只有"记"和"看",会有一点平。

所以我加了一套勋章,比如:

  • 首次打卡
  • 深夜食堂
  • 高分猎手
  • 标签达人
  • 连续打卡王

它不是为了把项目做得像游戏,而是想给"我又记了一条"这件事一点点反馈。

我一直挺在意这种轻微的情绪价值。功能当然重要,但很多项目做完以后之所以显得干,就是因为它只有功能,没有回声。

11. 这个项目里,我最满意的不是哪个页面,而是几个小处理

真要说我最满意的地方,其实不是地图页,也不是报告页,而是一些很小的处理。

第一,页面之间不是靠暴力刷新交流

新增、编辑、删除之后,不同页面会受影响,但我没有让它们每次都全量重来,而是做了轻量同步和 dirty 标记。

这很像收拾桌子:不是每掉一粒灰就把整间屋子掀一遍。

第二,登录成功的反馈会被带回目标页

这个细节我自己挺喜欢的。

如果你是从首页被引导去登录,那回来以后,首页会接住你,而不是让登录页自己喊一句"成功了"就结束。

页面之间有没有这种"交接感",真的差很多。

第三,我把重复而机械的事交给了脚本

项目里云函数不算少,所以我加了批量部署脚本,也加了鉴权片段同步脚本。

我越来越觉得,脚本最大的意义不是炫技,而是把那些"明明不难但特别烦"的重复劳动拿掉。

12. 如果继续往下做,我会优先补什么

这个项目现在已经能完整跑通流程了,但如果继续认真做,我下一步大概会优先补这几块:

  • 数据库索引
  • 分环境配置
  • 云函数接口和字段文档
  • 页面截图和演示数据

尤其是文档这件事,很多人都会拖。可一旦项目开始变复杂,你很快就会发现,代码不是唯一会过期的东西,脑子里的约定也会。

13. 最后想说的

我做完这个项目以后,一个感受特别深:

一个小程序最难的,往往不是某个 API 会不会调,也不是某个页面能不能画出来,而是你能不能把很多不起眼的小地方接顺。

比如:

  • 登录过期后怎么处理
  • 打卡完别的页面怎么跟上
  • 地图页是不是只是个装饰
  • 收藏是不是一个独立对象
  • 报告页该在前端算还是后端算

这些问题单独看都不吓人,但项目到底像不像样,常常就看它们。

所以如果你也在做微信小程序,我会很建议你别满足于"能增删改查就行"。再多想一步:用户做完这一步,接下来会发生什么?

很多时候,项目质感就是从这一步里长出来的。

14.总结

这个项目做到这里,核心流程已经基本跑通了,包括登录鉴权、打卡记录、图片上传、位置选择、地图足迹、收藏体系和消费统计等几个主要模块。

回过头看,这个项目里真正花时间的,往往不是某个页面本身,而是页面之间怎么衔接、登录态怎么统一处理、数据更新后其他页面怎么跟上、统计逻辑应该放前端还是放云函数。

如果后面继续迭代,我会优先补这几块:

  • 数据库索引优化
  • 分环境配置
  • 云函数接口和字段文档
  • 页面截图与更细的模块拆解文章

如果你也在做微信小程序项目,希望这次复盘能给你一些实现上的参考。

相关推荐
空中海16 小时前
微信小程序 - 03 工程实践层与综合 Demo
微信小程序·小程序·notepad++
小徐_233317 小时前
Wot UI v1 升级 v2?这份迁移指南帮你少踩坑!
前端·微信小程序·uni-app
优睿远行18 小时前
微信小程序云开发环境搭建与REST API混合架构实战
微信小程序·小程序
Greg_Zhong19 小时前
解决绘制的雷达图在页面有滚动时,雷达图出现`轻微上下偏移`的问题
微信小程序·canvans绘制雷达图
空中海19 小时前
微信小程序 - 02 基础概念层与核心能力层
微信小程序·小程序
無名路人21 小时前
小程序点餐页吸顶滚动
前端·微信小程序·ai编程
Greg_Zhong1 天前
微信小程序中使用canvas实现雷达图及标签对角显示(实现雷达图标签的标准做法)
微信小程序·小程序canvas实现雷达图·标签不通过canvas绘制
棋宣1 天前
uni-app编译到微信小程序中,父传子props首次传递数据不接收的bug
微信小程序·uni-app·bug
kyh10033811201 天前
微信小程序摇骰子功能实现|含源码
微信小程序·小程序·摇骰子小游戏·摇色子源码