ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

微信小程序点餐系统项目拆解:从数据库设计到前后端交互实现

微信小程序点餐系统项目拆解:从数据库设计到前后端交互实现 简介包含源码与说明文档的微信小程序点餐系统项目面向小程序开发者与前端初学者提供了从移动端点餐到后台管理的完整实现方案。压缩包共1343个文件大小15.31MB主要涵盖png图片资源、js/wxml/wxss小程序核心代码、vue后台页面、java服务端代码、json配置文件等目录结构完整说明文档对运行环境和部署步骤也有交代。已有1661人学习或下载属于实战型小程序资料。系统覆盖用户界面、商品管理、订单系统、微信支付、消息推送、账户管理和后台管理等功能通过阅读源码可以掌握WXML、WXSS、JavaScript开发以及前后端交互、订单状态流转、库存变动等关键设计还能借鉴vue/java后端部分理解前后端分离架构对课程设计或毕业设计都有参考价值。 最近后台收到好几个开发者私信都在问有没有适合练手的小程序项目要求是“代码能跑、注释清楚、最好贴近真实业务”。正好手上整理了一份点餐系统的微信小程序源码包里面除了完整的前端小程序代码还有配套的接口说明和部署文档。这篇文章我就拿这套点餐系统做一次完整的项目拆解从功能设计、数据表结构、核心代码实现到常见的坑把整个项目的来龙去脉讲清楚。先说这套系统能干什么。用户端是小程序顾客扫码进入后能看到菜品分类、加购物车、提交订单、查看历史订单商家端是一个简单后台可以管理菜品、分类和订单状态。整体是经典的小程序 后端APIJava/PHP均可 MySQL 的架构。适合正在学小程序开发、想了解完整前后端交互流程、或者需要一套可以二次开发的点餐系统模板的同学参考。1. 项目整体设计与思路拆解1.1 为什么选择点餐系统作为小程序项目小程序项目那么多为什么拿点餐系统当模板讲因为它的业务链路足够完整但又没有复杂到劝退新手。一个点餐系统天然包含列表展示、条件筛选、购物车管理本地缓存、订单状态流转、微信登录、支付对接预览几乎覆盖了小程序的全部核心交互场景。更重要的是点餐系统的数据模型特别清晰。菜品、分类、订单、订单明细四张表就够用没有复杂的关联关系。它不像电商系统那样要处理库存、优惠券、多规格SKU也不需要物流跟踪这类外延功能。对于第一次完整做一个小程序项目的开发者来说这个复杂度刚刚好——既能练到东西又不至于被业务绕晕。我做这套项目时给它的定位是“课练级”项目也就是介于课程作业和商用系统之间的一个阶梯。它保留了商用系统的核心骨架砍掉了运营后台那些繁琐的配置项。后续真要商用在这套骨架上加支付回调、打印机对接、桌台管理都是顺理成章的事。1.2 技术选型原生小程序 自建后端技术栈的选择我纠结过一阵子。最开始考虑过用云开发毕竟云开发省去了后端搭建的麻烦一个数据库 云函数就能跑通全部业务。但后来放弃了原因是云开发的调试体验对于“想学完整前后端交互”的开发者来说反而容易形成黑盒——你不太清楚请求是怎么发出、怎么鉴权、怎么查库的。最终这套源码采用的是原生微信小程序 自建后端API的方案。前端用WXML WXSS JS不引入第三方UI框架因为点餐系统的界面复杂度用原生组件完全能搞定。后端我同时提供了Java Spring Boot和PHP ThinkPHP两个版本的接口源码数据库用MySQL。这样做的好处是你只要会其中任意一门后端语言就能把服务跑起来。为什么推荐这个选型有几个实际考量原生小程序在性能和兼容性上永远是最稳的不出幺蛾子自建后端能让你完整看到token鉴权、订单状态这些逻辑是怎么落地成SQL语句的另外这套架构是可以直接平滑升级到生产环境的不像云开发绑定平台后期迁移成本高。1.3 系统整体架构与模块划分整个系统分为三个端C端小程序、商家管理端、后端服务API。小程序端负责用户交互管理端负责商家维护菜品和订单API服务层负责业务逻辑和数据持久化。小程序端的代码结构按业务模块划分pages/index首页包含分类导航和菜品列表pages/cart购物车页同时充当结算入口pages/order订单列表页当前订单 历史订单pages/detail菜品详情页pages/login登录授权页utils/request.js封装wx.request请求统一处理token注入和错误提示store/购物车本地缓存管理模块后端API按资源划分接口auth登录、category分类、dish菜品、order订单。每个模块一套Controller Service Mapper结构干净拿来做二次开发的起点非常合适。2. 核心功能模块与数据表设计2.1 功能清单与业务逻辑梳理动手写代码之前先把功能点一条条列清楚我当时就是靠这一步避免了后面反复改表结构的尴尬用户打开小程序进入首页看到菜品分类横向滚动条和菜品纵向列表点击分类菜品列表滚动到对应分组或者过滤菜品卡片上有“加入购物车”按钮支持增减数量购物车页展示已选商品、总价支持单选/全选提交订单前校验登录状态未登录引导授权订单提交成功生成订单号状态为“待接单”用户可在订单列表查看状态流转待接单 → 制作中 → 已完成/已取消商家端可以手动变更订单状态管理菜品上下架这里有一个当时反复权衡的交互点购物车数据存在哪里。网上很多教程直接把购物车放在全局变量里小程序切后台数据就丢了体验很差。这套系统的做法是每次变更购物车的同时写入本地缓存提交订单时从本地缓存读取一份快照上传给后端后端存到订单明细表。这样一来即使小程序被微信回收重新打开购物车数据也还在。2.2 数据库表设计菜品表、订单表核心字段详解数据表是整个系统的地基表结构设计合理后面写代码会顺手很多。核心表一共四张菜品表dish主键id、分类id、菜品名称、图片URL、价格以分为单位存储INT、月售数量、是否推荐、上下架状态、排序号。价格用分存储是一个经验点浮点数做相加运算在MySQL和Java里都可能出现精度丢失用分存储可以规避这个问题展示的时候再除以100。分类表categoryid、分类名称、排序号。之所以把分类独立成表而不是直接给菜品加一个字符串字段是为了后续做分类管理时不改动菜品表。虽然现阶段是固定分类但商用后商家肯定要增删改分类。订单主表ordersid、订单号唯一索引、用户openid、订单总金额、订单状态、桌台号可选、备注、创建时间、支付时间、完成时间。订单状态我用TINYINT存0待接单、1制作中、2已完成、3已取消避免直接用中文字符串查表效率更高也避免前后端状态值不一致。订单明细表order_detailid、订单号、菜品id、菜品名称冗余、菜品单价、数量、小计。这里冗余了菜品名称和单价是有意的——如果商家改了菜品名或价格历史订单仍然显示下单时的信息。字段设计上有一个小技巧所有表的创建时间和更新时间统一用datetime类型默认值管理后端代码里不手写时间。MyBatis Plus有自动填充功能ThinkPHP用时间戳字段即可这样能保证所有时间的格式统一。2.3 微信登录流程与token鉴权机制登录这块是最容易被新手写崩的。这套系统的登录逻辑是这样设计的小程序端调用wx.login拿到临时code把code传给后端。后端拿code请求微信接口换取openid然后生成一个自定义token可以用UUID也可以用JWT返回给前端。这里注意一点openid是不能直接返回给小程序的它是用户在小程序生态里的唯一身份证属于敏感数据。后端把openid和token的对应关系写入一张用户表之后小程序端所有需要鉴权的接口都在请求头里携带token后端拦截器解析token查出对应的openid再拿openid做数据归属校验。为什么要多包一层token而不是直接把openid当凭证因为openid一旦泄露别人就能伪装你下单。token有过期时间可以控制会话的有效期降低安全风险。3. 实操过程与核心代码实现3.1 搭建本地开发环境的完整步骤先把环境跑起来代码后面再细看。我按Windows环境举例Mac基本一致。第一步安装微信开发者工具微信公众平台官网下载稳定版用你自己的微信扫码登录。创建一个空项目AppID先用测试号游客模式正式发布前再换成小程序后台申请到的AppID。第二步搭建后端环境。Java版需要JDK 1.8和Maven导入项目后修改application.yml里的数据库账号密码。PHP版需要PHP 7和Composer部署到本地Nginx或Apache即可。第三步初始化数据库。在源码包的sql目录下找到init.sql用Navicat或命令行整体导入。创建好数据库名比如ordering然后执行导入。第四步修改小程序端请求地址。在utils/config.js里把baseURL改成你后端服务的地址。本地调试时记得在开发者工具里勾选“不校验合法域名”因为本地IP不在微信白名单里。3.2 小程序端关键页面与交互代码解读挑两个核心页面看代码。先看菜单首页是怎么处理分类和菜品滚动的。实现方案是左右联动——左侧分类栏点击右侧scroll-view滚动到对应位置右侧滚动时左侧联动高亮当前分类。关键代码如下WXML已简化view classcategory-side scroll-view scroll-y view wx:for{{categoryList}} wx:keyid classcategory-item {{currentIndex index ? active : }} bindtapswitchCategory>const CART_KEY cart_data; // 加购 addToCart(dish) { const cart wx.getStorageSync(CART_KEY) || {}; if (cart[dish.id]) { cart[dish.id].count 1; } else { cart[dish.id] { ...dish, count: 1 }; } wx.setStorageSync(CART_KEY, cart); this.setData({ totalCount: this.calcTotalCount(cart) }); }整体设计非常直白——以菜品id为主键存一个对象value是菜品信息和数量。数量为0的时候删除该key防止脏数据积累。这里的calcTotalCount会遍历所有value把count加起来用于首页的角标展示。3.3 订单提交与状态流转实现订单提交是最容易出bug的环节核心问题是“并发”和“幂等”。如果用户手快连点了两次提交按钮会产生两笔一模一样的订单。我的处理方式分两层前端提交后立刻disable按钮并加一个isSubmitting锁后端用订单号做唯一索引兜底同一订单号重复插入会直接报错配合全局异常处理器返回“订单已提交”。订单号生成我用的格式是时间戳 4位随机数 用户id后三位例如20250406153022123456789001。之所以不用数据库自增id是因为自增id在订单列表展示时容易暴露订单量也不方便外部查询。后端下单核心逻辑Java版已简化Transactional public OrderVO createOrder(OrderCreateDTO dto) { // 1. 生成订单号 String orderNo generateOrderNo(dto.getUserId()); // 2. 计算订单金额注意必须以“菜品表当前价格”为准不信任前端传的总价 ListCartItemDTO items dto.getItems(); BigDecimal total BigDecimal.ZERO; ListOrderDetail details new ArrayList(); for (CartItemDTO item : items) { Dish dish dishMapper.selectById(item.getDishId()); BigDecimal subtotal dish.getPrice().multiply(new BigDecimal(item.getCount())); total total.add(subtotal); OrderDetail detail new OrderDetail(); detail.setOrderNo(orderNo); detail.setDishId(dish.getId()); detail.setDishName(dish.getName()); detail.setPrice(dish.getPrice()); detail.setCount(item.getCount()); detail.setSubtotal(subtotal); details.add(detail); } // 3. 写入订单主表和明细表 Orders order new Orders(); order.setOrderNo(orderNo); order.setUserId(dto.getUserId()); order.setTotalAmount(total); order.setStatus(0); orderMapper.insert(order); detailMapper.insertBatch(details); return orderVO; }Transactional 保证订单主表和明细表要么同时写入、要么同时回滚不会出现“主单有了明细没有”的情况。计算总价时又重新查了一次菜品价格没有直接信任前端传来的总价这是必须做的——否则用户改一下请求体里的金额下单直接变“白菜价”。点餐项目可以不做支付但接口安全设计从一开始就要养成习惯。3.4 源码包目录结构与使用说明拿到源码包后第一件事不是双击打开而是先看目录结构。这套包的根目录分三块miniprogram/ 是小程序前端代码server-java/ 是Java后端API代码server-php/ 是PHP后端API代码docs/ 目录下放的是接口文档和部署说明PDF。接口文档是手写的Markdown整理成PDF的包含每个接口的请求方法、路径、参数名、类型、是否必填、响应示例。做这个文档的过程很枯燥但它对二次开发帮助巨大尤其是你想把微信登录换成其他登录方式时直接改对应接口就能定位到前后端所有涉及位置。部署建议顺序先初始化数据库 → 再起后端 → 用Postman测两个接口登录、获取菜品列表 → 最后在开发者工具里打开小程序 → 真机预览。按这个顺序走出了问题你能快速判断是哪一层的锅。4. 常见问题与排查技巧实录4.1 小程序获取登录后的微信用户信息失败很多新手在wx.getUserProfile真机调试时会遇到“获取失败”或直接弹不出授权框。原因大概率是调试基础库版本以及用户已经拒绝过授权。处理方式先检查AppID和调试基础库版本推荐2.30.0以上登录授权推荐wx.login获取code换取openid补充用户资料替代旧的getUserInfo弹窗方式getUserProfile需要在用户点击事件bindtap回调里调用不能在App.onLaunch里调用也不能在异步回调里调用。如果用户之前拒绝过授权去右上角菜单的“设置”里手动打开用户信息权限或者用wx.openSetting引导用户重新授权。4.2 真机预览时网络请求失败net::ERR_CONNECTION_RESET这是一个几乎人人都踩过的坑开发者工具里请求一切正常手机扫码预览就报net::ERR_CONNECTION_RESET。原因基本是手机和开发机不在同一局域网或者域名没有配置到合法域名列表。排查步骤确认手机和电脑连的是同一个WiFi确认后端服务监听地址是0.0.0.0而不是127.0.0.1后者只能本机访问把本地IP地址填到小程序端的baseURL里如果用了HTTPS证书必须是有效且受信任的开发者工具里的“不校验域名”选项只对工具调试有效真机不生效。这套源码包里我在config.js里加了环境判断开发环境用本地IP生产环境用正式域名。你只需要维护一份环境变量即可。4.3 微信支付功能对接要点这套源码没把支付功能做成完整闭环只接了模拟支付因为申请微信支付需要企业资质个人开发者申请不了。如果你自己做项目已经具备商户号对接支付的基本逻辑是先调用统一下单接口拿到prepay_id再用这个prepay_id调起小程序端wx.requestPayment。服务端需要用商户私钥对下单参数做签名微信支付的回调地址必须公网可访问且必须对回调通知验签防止伪造回调。模拟支付阶段我在订单表加了一个is_paid字段真流程时用微信支付回调通知更新这个字段模拟流程时手动置1这样前后端逻辑不冲突。4.4 性能优化与包体积控制最后再说一个实用项。小程序主包体积限制是2MB做点餐系统最容易超的坑是图片——原图随便几张就超过1MB了。我踩过坑后的做法是图片全部压缩到宽度750px宽质量70%这个尺寸在微信上已经足够清晰商家上传的菜品图统一走后端缩放接口不直接存原图图片尽量走CDN不要塞在小程序包里。这套系统全部代码和压缩后的图片主包大约900KB还有富余空间可以加功能。另外建议开启小程序的“按需注入”特性在app.json里配置lazyCodeLoading: requiredComponents能减少启动耗时。对于页面较多的应用还可以用subPackages做分包把购物车和订单列表拆到分包里进一步降低首屏加载时间。5. 这套源码的扩展玩法与二次开发方向源码包拿来跑通只是第一步真正有价值的是拿它练手改造成自己的项目。我列几个扩展方向供参考。桌台点餐扫码带入一个桌台参数下单后把桌台号一起提交。改造成本很低只需要在banner图或海报里拼接参数首次进入小程序时解析scene值存到全局变量下单时带过去即可。多门店支持给菜品表加一个门店字段所有查询带上门店条件入门店过滤。数据模型不用动太大但接口需要统一加门店参数的校验和透传。优化菜品推荐做一个“招牌推荐”的聚合接口将推荐菜品列表放在首页顶部。后端可以加分页前端用swiper组件做横滑轮播交互体验会提升一大截。接入打印机订单提交后通过服务端调用云打印API或本地打印机接口把订单推送到后厨。这个需要后端多写一个定时任务轮询扫描新订单配合WebSocket实现实时推送。数据统计面板在商家端加一个简单的报表页统计每日订单量、客单价等指标。SQL层面用GROUP BY DATE_FORMAT就能搞定前端用echarts的小程序版本渲染柱状图。我个人在实际操作中体会最深的是读书时做项目眼睛总盯着“能用”真正踩过部署、真机调试、接口鉴权的坑之后才明白一个项目从“能跑”到“像样”之间差的都是工程细节。这套点餐系统能把这些细节都覆盖到对正在学小程序开发的朋友来说是一个性价比很高的练手素材。最后再分享一个小技巧拿到任何源码项目都先花半小时把它的接口文档和数据结构梳理清楚再动代码。磨刀不误砍柴工这个习惯能让你少熬夜查bug。本文还有配套的精品资源点击获取
返回列表