做微信小程序商城这个题目,说实话在毕业设计和课设里属于“经典永流传”的存在。但正因为太常见,市面上的源码和教程鱼龙混杂,很多人拿到手发现跑不起来,或者跑起来了但论文没法写,最后两头抓瞎。这篇东西我不会给你贴整段代码,而是把这类项目从立项到交付拆开揉碎,讲清楚里面的技术选型、业务逻辑、结构设计,还有那些老师不会明说、但评审答辩时一定会被问到的坑。无论你是准备拿这套东西交作业,还是真想做个能上线的小程序,这篇都应该能帮你省下不少瞎折腾的时间。
1. 商城类小程序整体设计与需求拆解
1.1 双向体系定位:用户端与管理端缺一不可
一个完整的电子商城,绝不是小程序里能下单就算完事。很多同学最初理解有偏差,以为把商品列表和购物车做出来就大功告成,实际上商城类系统的核心在于“管理”。为什么?因为商城本质上是一个持续运营的业态,你需要有人去维护商品信息、处理每一笔订单的状态流转、管理用户数据。如果这些操作全堆在手机端,体验会非常糟糕,而且小程序本身对复杂表格操作的支持并不友好。
所以,这类项目在设计阶段就要定下“前后台分离思想”:
- 前台(小程序端):面向消费者,承担商品浏览、加购、下单、支付模拟、订单查询、个人信息管理等高频操作。界面要简洁,路径要短,因为手机屏幕小,用户耐心有限。
- 后台(管理端):面向运营者,大多以Web管理页面形式存在,负责商品上架下架、库存调整、订单发货、数据统计。这部分不一定要非常精美,但功能必须完整,逻辑必须清晰。
这种双向体系的价值在于,评审老师一眼就能看出你对“管理系统”四个字的理解是否到位。如果你只交付一个小程序,那叫“商城展示页”,不叫“商城管理系统”。反过来,后台做得再花哨,小程序端体验稀烂,那也白搭。所以这套项目里,小程序端和Web管理端是两根柱子,缺一根都撑不起整个项目。
1.2 核心技术选型:为什么用原生而非框架
微信小程序开发绕不开一个选择:用原生开发还是用uni-app或Taro这类跨端框架?很多同学想省事,直接上框架,我劝你不要在毕业设计里这么做。
先说框架的好处,确实是编写一套代码可以多端复用(微信、支付宝、H5),语法接近Vue或React,上手快。但这恰恰是问题所在。框架封装了一层语法糖,很多东西出了问题你根本不知道底层发生了什么。比如uni-app在微信小程序端的兼容性问题,经常是编译过了、模拟器正常、一上真机就白屏,你排查起来非常痛苦,因为错误信息经过了一层转译,根本看不懂。
原生小程序开发虽然代码重复度高一些,需要分别维护WXML、WXSS、JS、JSON四个文件,但好处是显性的:
- 运行链路短,出问题可以直接定位到具体逻辑;
- API调用更直接,比如登录、支付、订阅消息这些微信能力,原生支持最完整,没有中间层拦截;
- 包体积容易控制,框架光运行时就要占几十KB,原生的话你能一眼看出每个文件的体积。
我做的这套项目,选的就是原生开发框架。技术上没有秘密,就是一个“稳”字。使用微信开发者工具直接创建项目,不需要繁琐的脚手架配置,对新手还原度最高。总有人觉得原生开发显得“不高级”,但真正一动起手来,你会发现原生才是最省心的。
1.3 后台服务的选型:Java还是Node?
后台服务的实现方案,是这个项目的另一个分岔路口。简单来说就三个选择:Java(Spring Boot)、PHP(ThinkPHP/Laravel)、Node.js(Express/Koa)。技术栈本身没有绝对好坏,要看你的场景和熟络程度。
如果让我排优先级,我会建议用Java Spring Boot。理由很简单:
- 资料最丰富。国内高校的课程设计、毕业设计,Java Web占据半壁江山,你遇到任何问题都能在CSDN、博客园找到对应的解决方案。
- 生态完整。Spring Boot + MyBatis-Plus + MySQL这套组合,做商城类管理系统简直是流水线操作,代码生成器一跑,基础的增删改查全出来了。
- 论文好写。如果后期要写“技术选型”章节,Java的技术栈描述和架构图素材多到用不完。
但这并不意味着Java没有门槛。它的环境配置(JDK、Maven、Tomcat内嵌)对纯前端选手来说,前期可能要花一两天来适应。如果你平时对前后端分离完全没有概念,也可以退而求其次选择Node.js,因为它更轻量,JavaScript语法对你来说可能更友好。
后台服务在项目中的作用,本质上是一个JSON数据的加工与分发中心。小程序端调用wx.request发起HTTP请求,服务端处理业务逻辑、访问数据库、返回JSON数据。管理端Web页面也走同样的链路。所以不管你选哪种后端语言,核心都是:设计好接口协议,把数据模型定清楚。我这边用的是Spring Boot,接下来所有代码示例都以这套体系为准。
1.4 数据库设计:过得了评审的关键
这一块是论文的重头戏,也是评审老师必然细看的部分。商城系统的数据库设计主要围绕五张核心表展开:用户表(user)、商品表(goods)、购物车表(cart)、订单表(orders)、订单详情表(order_item)。如果还有轮播图、公告、分类、地址管理,就可以再扩展表。
不要小看这些表的关联关系设计。我见过太多同学chatgpt生成的数据表,id全是字符串uuid,主外键关系混乱,后边写业务代码时各种连表查询直接崩溃。设计时要注意几点:
- 主键统一用自增int。别整花活,int自增效率高、实现简单,对中小项目完全够用。
- 金额字段类型用decimal(10,2)。不要用float/double,存钱涉及精度,float的二进制浮点误差会让你金额对不上账。
- 时间字段用datetime,统一存储格式,前端展示再自行转化。
- 所有表都加上create_time和update_time字段。这不仅是规范问题,后台列表按时间排序、统计新增数据量都依赖它们。
- 外键约束能不用就不用。不是说外键不好,而是在实际开发中,外键约束会让删除用户、改商品ID这些操作变得异常麻烦。逻辑上保证关联,物理上不建外键约束,是很多生产环境的标准做法。
商品表需要提前考虑SKU(库存量单位)问题,也就是同一个商品可能有多规格属性(颜色、尺寸)。如果你做的是基础版本,可以直接把不同规格拆成不同商品条数,用“商品名+规格”命名即可。这样设计简单,管理端操作也直观。只有当你需要做“同一个商品详情页选择多种规格”时才需要引入规格表和SKU表,但那会极大增加开发量,非必要不碰。
2. 小程序端核心功能与页面结构
2.1 首页、分类与商品模块:从体验到数据
首页是一个小程序的脸面。很多人的首页设计思路是:放一个轮播图、一个公告栏、下面堆一排商品。说实话,这样的首页没有问题,但如果你能多做一点分组逻辑,体验就能上一个台阶。
我当时实现的首页逻辑主要包含这几块:
- 搜索框:固定顶部,支持商品名称模糊搜索。这个功能在原生端要特别注意防抖处理,不然用户每敲一个字母就发一次请求,服务器压力大不说,前端还会出现数据错乱(旧请求晚于新请求返回)。
- 轮播图:数据来自后台banner表,用
swiper组件实现。注意swiper的autoplay要在wx.showToast或弹窗时暂停,否则有遮挡时轮播切换会有视觉卡顿。 - 分类入口:八个彩色icon导航,用
grid布局。每个分类对应入口跳转到分类列表页。 - 热门商品:默认拉取数据库里点击量最高的4个商品,以两列瀑布流展示。
商品列表页要好好设计。两个关键点:分页加载和筛选排序。
分页加载这块经典做法有两种。一种是用onReachBottom触底加载,另一种是用scroll-view配合scrolltolower事件。我个人推荐前者,原因是onReachBottom是页面级别的,稳定性最好,不会因为页面里嵌套了scroll-view导致事件冲突。分页参数前端传pageNum和pageSize,后端返回总条数total和当前页列表,前端根据total判断是否还有下一页,如果没有就显示“没有更多了”。
筛选排序一般提供综合、销量、价格升序、价格降序四个tab,本质上就是后端SQL的order by条件切换。注意价格升序降序切换时,最好加个过渡动画,否则体验上会有一种生硬的“跳变感”。
商品详情页是有隐藏工作量的。除了商品图、价格、简介这些基本信息,还要把库存判断、购买数量限制、是否已收藏做进去。库存判断不是只在前端限流,每次后端接受下单请求时必须重新校验库存,否则高并发下会出现超卖。
2.2 登录与身份体系:openid为核心
购物车、下单、订单查询这些功能,都必须依赖用户身份体系。小程序端的用户体系与网页端完全不同,它不走传统的用户名密码登录,而是基于微信的openid。
具体流程是这样的:
- 用户进入小程序,前端调用
wx.login()获取一个临时code; - 前端把code传给后端接口
/user/login; - 后端拿这个code,加上小程序的AppID和AppSecret,去调用微信的
jscode2session接口,换回openid和session_key; - 后端把openid作为用户唯一标识存库,并生成一个自定义登录态token返回给前端;
- 前端把token存到
wx.setStorageSync里,后续所有需要身份的请求都在header里带上token。
这套链条讲起来不难,但细节上要注意几点。第一,wx.login的code有效期只有五分钟,且每次调用都会刷新,所以不能把code写死。第二,openid换回来后不要直接传给前端,因为它涉及用户隐私,而且如果别人拿到你的openid就能伪造你的身份。最稳妥的办法是后端自己维护openid和token映射,token是随机的UUID串。第三,如果项目要求获取用户手机号,那需要在特定按钮上使用open-type="getPhoneNumber",通过获取到的code去后端调用getPhoneNumber接口换取明文手机号,这个流程和登录是分开的。
如果你只是做模拟登录,这个环节也能手动跳过,比如在小程序端写死一个虚拟用户ID。但真实评审时,老师很可能问“你的用户系统怎么设计的”,拿手写假用户来糊弄会相当尴尬。所以这个登录逻辑,建议认真实现一遍。
2.3 购物车逻辑:本地缓存与服务端同步
购物车是所有电商类小程序中,最容易写乱的一个模块。很多初学者的思路是:把所有加购的商品放在本地缓存(Storage)里,下单时直接拿缓存数据提交。这个思路在小规模场景下能跑通,但有一个致命问题:换设备后购物车数据全丢,而且管理端无法看到用户购物车数据做营销。
正确做法应该是在数据库设计cart表的基础上,小程序端以“本地缓存为壳、服务端数据为核”来实现双写:
- 加购操作:前端把商品信息渲染到本地缓存中(为了体验流畅),同时异步请求后端
/cart/add接口,把数据同步到cart表。 - 购物车列表:进入页面时调后端接口,拉取当前用户的购物车数据,覆盖本地缓存。
- 选中状态管理:商品勾选/全选状态,需要前后端同步。简单做法是前端把选中项的商品ID集合传给后端,后端根据ID集合计算总价;复杂做法是数据库加一个
selected字段。
双写的价值在于,当用户换个设备登录时,购物车数据还在。这个细节在答辩时可以加分,因为说明你考虑了真实场景,而不只是做一个demo。
购物车还要实现数量增减功能。加号减号的逻辑很直观,要注意的是当数量变为0时删除该条商品,并且实时刷新总价。还有一点,加入购物车时前端要做一个“重复添加校验”:如果该商品已经在购物车中,就累加数量,而不是新建一条记录。这个校验建议在后端也做一遍,防止用户快速点击两次加购导致重复数据。
2.4 订单流程:状态机驱动
订单模块是业务逻辑最密集的地方。从用户下单到确认收货,整个流程涉及多个状态转换。我不会顺序贴代码,但会把核心流程和状态设计讲清楚。
一张订单的生命周期大致如下:
- 用户提交订单(待付款):用户从购物车勾选商品,提交生成订单。此时订单状态为0,库存要预占但不扣减。
- 用户模拟支付(待发货):点击“立即支付”,调用后端接口模拟支付成功,状态变1。如果是真实支付,则需要调用微信支付
wx.requestPayment,但毕设项目一般不需要真实接入。 - 管理员后台发货(待收货):管理端看到待发货订单,点击“发货”,状态变2。发货时要能填写物流单号,虽然不接真实物流查询,但字段要先留着。
- 用户确认收货(已完成):用户收到货后点确认,状态变3。
- 可扩展流程:取消订单(状态变-1)、申请退款(状态变4)、退款完成(状态变5)。这些流程可以根据项目需求增加,但对毕设来说,实现前两个主流程已经足够打底。
订单表设计时要注意两个字段:“订单编号”和“支付流水号”。订单编号是唯一的业务单号,通常用时间戳+随机数生成,格式类似202501011530001234。支付流水号记录的是模拟支付的标识符,方便对账。订单金额要在生成订单那一刻就固定下来,这就是“快照”的概念。商品后续再怎么改价,已下订单不受影响。
还有一点,订单创建涉及事务处理。简单场景下,需要保证“创建订单主表”和“插入订单明细表”这两步原子操作,要么全成功要么全失败,否则就会出现有订单号但没商品明细的脏数据。用Spring Boot的话直接在Service层加@Transactional注解即可。这个点在论文的“技术难点”部分写上,会显得你确实懂业务。
3. 后台管理端界面与核心实现
3.1 管理端的界面布局:菜鸟也能直接上手
后台管理端是面向运营人员的,所以设计核心就一个词:效率。所有常用功能必须能在1-2次点击内到达,信息展示必须一目了然。
我使用的布局风格是经典的左侧菜单+右侧内容区。左侧菜单从这些维度展开:
- 数据看板(Dashboard):定制化展示一些核心指标,比如今日订单数、今日销售额、新增用户数、总商品数。
- 商品管理:商品列表、添加商品、分类管理。
- 订单管理:订单列表(可按订单状态筛选)、发货操作。
- 用户管理:用户列表、用户详情。
- 轮播图管理:维护首页轮播图。
- 公告管理:维护公告信息。
- 系统设置:展示不到万不得已别放这里,因为没人喜欢点好几层才能找到功能。
数据看板可以做四个统计卡片排列在第一行,下面接一个“近7日订单量”柱状图。图表不是你核心的加分项,但对于管理系统来说,有一张图会瞬间提升整体的专业度。如果技术栈是Vue,可以使用ECharts;如果后端模板引擎渲染,也可以直接用后端返回的数据生成简单的CSS柱状图,避免引入太多依赖。
3.2 权限与身份校验:管理端和小程序端的区分
后台管理端最大的安全隐患在于接口没有登录校验。很多毕设项目的前后端分离做得不彻底,导致管理端接口可以直接被未授权用户访问,这是个很严重的漏洞。同学写好代码后自己测试时,因为本地环境一切正常,所以很难意识到这个问题。但如果评审老师拿一个HTTP工具直接请求你的后台接口,那场面就很尴尬了。
解决办法是加一个非常简单的Token拦截器:
- 管理员登录后,后端生成一个uuid作为token,存在服务端内存或Redis中,响应给前端;
- 前端存放在localStorage,所有请求header中带上
Authorization: token; - 后端写一个拦截器(Spring Boot的HandlerInterceptor),对所有
/api/admin/**路径做校验,token不存在或过期则返回401。
这个拦截逻辑本质上和用户端是一样的,但表要单独建。管理员身份是独立的,和普通用户表不能混在一起。一张admin表就够,字段包含用户名、密码(MD5加盐或BCrypt加密)、创建时间、上次登录时间。
你可能会问,为什么管理端直接用传统账号密码而不是微信扫码登录?因为管理端的使用场景主要是PC端浏览器,维护一套账号密码体系就足够,而且能在论文里体现“角色权限分离”的设计思想,评审老师会很吃这一套。
3.3 商品发布与订单处理:管理端的每日操作
商品发布这个功能的核心难点,不只在于表单的增删改查,还在于图片上传。小程序端展示的商品图片需要一个可访问的URL,那么管理端就必须提供一个图片上传功能,把图片保存到服务器并返回可访问地址。
图片上传有两个选择:一种是传到本地服务器指定目录,另一种是接到云存储(阿里云OSS、腾讯云COS或七牛云)。毕设项目为了省事和经济,推荐传到本地服务器目录。但要注意,本地存储的图片URL不能写死localhost或127.0.0.1,因为小程序真机永远访问不到你电脑的localhost。要么使用局域网IP,要么使用小程序开发者工具中的“不校验合法域名”选项,后者仅限开发调试阶段使用。真机预览的话,后端必须部署到一台服务器上,或者至少用内网穿透工具把本地服务暴露出去。
订单处理这个功能要设计的是列表页的可操作性。一个订单列表页,至少需要支持:按状态筛选(全部/待付款/待发货/待收货/已完成)、查看订单详情、执行发货操作、备注订单。发货操作点开后是一个弹出框,里面填写物流公司和物流单号,确认后订单状态变更。这些操作都对应后端接口,逻辑不复杂,但界面交互细节要注意,比如发货按钮只在待发货状态显示,已完成订单按钮置灰,不然运营人员容易误操作。
3.4 数据统计与可视化:给老师看的那张图
数据统计是拉开项目档次的关键模块。如果管理端只有简单的列表,那它跟Excel表格没什么两样。加上可视化,整个项目的“信息化管理”属性立刻就立起来了。
不需要做得很复杂,两个核心图表足够:
- 近7日订单量折线图:后端返回最近7天每天的订单数量,前端用ECharts绘制折线。数据字段是date和count,SQL语句用
GROUP BY DATE(create_time)聚合,注意补全没有订单的日期,否则折线会断掉。 - 商品分类占比饼图:后端查商品表中每个分类的商品数量,用饼图展示。这个数据展示的是商品结构,对运营决策有一定参考意义。
实现图表时要注意一个细节:ECharts体积不小,管理端用的是Web,体积不是问题,但如果在小程序端做图表就需要用echarts-for-wx这类定制包,而且小程序对canvas的支持有限,是实现成本有点高的。所以我的建议是,统计图表只放在管理端,小程序端不放图表,省事且不损专业性。
4. 实操过程:从0到1搭建这套系统
4.1 环境准备与工具安装
在正式开始写代码之前,先把开发环境搭好,这一步能让你后续少很多头疼的夜晚。你需要准备的工具大致如下表:
| 工具 | 说明 | 备注 |
|---|---|---|
| 微信开发者工具 | 小程序端开发调试 | 需使用稳定版,注意更新频率高 |
| JDK 1.8+ | 后端Java运行环境 | 建议使用JDK 8,兼容性好 |
| IntelliJ IDEA | 后端集成开发环境 | 社区版即可,不需要付费版 |
| MySQL 5.7+ | 数据库 | 5.7和8.0都可以,注意密码认证方式 |
| Navicat | 数据库可视化工具 | 也可以直接用命令行 |
如果你是完全零基础,我建议先用一天时间把每个工具装好,然后分别跑通一个最小示例:小程序端能输出“Hello World”并能在模拟器中运行,后端能启动并访问一个最简单的接口返回JSON字符串。不要急着一步到位,分阶段验证比什么都在最后一起看结果要稳妥得多。
考虑到很多同学会遇到域名校验问题,调试阶段的便捷做法是:在微信开发者工具的“详情-本地设置”中勾选“不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书”。这样可以在本地开发时直接用http://localhost:8080请求后端。
4.2 后端骨架搭建:从无到有跑通接口
后端项目的创建,我推荐从Spring Initializr(start.spring.io)生成一个基础Spring Boot项目,需要引入的依赖包括:Spring Web、MyBatis、MySQL Driver、Lombok。
项目结构按常见的分层架构搭建:
com.example.mall ├── controller (接收前端请求,返回JSON) ├── service (业务逻辑层) ├── mapper (MyBatis接口,数据访问层) ├── entity (数据库表对应的实体类) ├── dto (前后端交互的数据传输对象) ├── config (配置类,如跨域、拦截器) ├── common (通用工具类,如统一返回结果类) └── interceptor (登录校验拦截器)分层的好处是职责清晰、易于维护。如果是直接在小项目里把SQL写在Controller方法里,前期节奏确实快,但后期加个判断逻辑或者调整数据结构会非常痛苦。
为了省时间,可以用MyBatis-Plus这个增强工具。它内置了单表CRUD的方法,你不需要为每一张表去写一个基础的Mapper接口。节省的时间可以用来做业务逻辑和界面。
首个接口建议做一个GET /api/user/list,返回用户表全部数据。如果能在浏览器中看到JSON数据,说明后端已经完全通了。这一步建立起正向反馈后,再往里面加功能会顺利得多。
4.3 小程序端骨架搭建:目录规划与页面设计
用微信开发者工具创建小程序项目时,一个重要选择是不使用云开发。云开发确实省事,但它绑定的是腾讯的云环境,和传统的Java后端很难协同。咱们要的是一个正经的“管理系统”,所以选择不使用云服务,纯前端发起HTTP请求和Web后端交互。
小程序端的目录结构规划如下:
pages/ ├── index/ (首页) ├── category/ (分类页) ├── cart/ (购物车页) ├── user/ (个人中心) ├── goodsList/ (商品列表页) ├── goodsDetail/ (商品详情页) ├── confirmOrder/ (确认订单页) ├── orderList/ (订单列表页) ├── orderDetail/ (订单详情页) └── address/ (收货地址页)另外,在项目的utils目录下建议放一个request.js,把wx.request封装成统一的请求函数。这样你可以在一个文件里处理BASE_URL、请求头token注入、401统一跳转、错误提示弹窗。这个封装如果做好了,后续每个页面的网络请求代码都会干净很多。
页面跳转方面,首页到商品列表要带分类ID参数,商品列表到详情要带商品ID参数,购物车到确认订单要带上购物车选中项的商品列表。把这些参数约定写清楚,开发过程中才不会乱。
4.4 关键接口设计与前后端联调
前后端联调绝对是最磨人的一步,这里分享一些关于接口设计的经验。设计接口时最忌讳的是没有统一的返回格式,各写各的,前端解析起来是灾难。我使用的统一返回结构如下:
{ "code": 200, "message": "操作成功", "data": { "list": [], "total": 100, "pageNum": 1 } }写一个BaseResponse类来统一包裹返回值,同时写一个异常处理器,把业务异常和系统异常统一转成这个格式返回。前端封装好的request.js里就可以只关注data字段,code不为200时统一弹toast。
联调阶段的主要任务是测通几条主干链路:
- 首页加载接口,确认轮播图和热门商品能正常展示;
- 商品列表分页接口,测试上拉加载更多时不会重复请求;
- 用户登录接口,跑通code换token;
- 购物车加购接口,确认重复加购和库存校验正确;
- 提交订单接口,确认订单生成后购物车能清空。
联调时建议用微信开发者工具的Network面板辅助排查。还可以考虑下一个Charles做抓包,但如果没有也问题不大,开发者工具自带的网络请求展示已经足够定位80%的问题。
5. 常见问题与排查技巧实录(附速查表)
5.1 登录态失效与401循环重定向
这是小程序开发中非常典型的连环坑。假设token过期,用户表现在点击购物车,后端返回401,前端拿到401后要跳转登录。但登录本身需要用户点击按钮触发,如果你在请求拦截器里自动跳转,页面一直在重定向中打转,用户体验就会非常糟糕。
我的建议是,401处理逻辑做成这样:前端收到401后,弹一个Modal提示“登录已过期,请重新登录”,用户点击确定后才调用wx.reLaunch跳转登录页。不要做成自动跳转,模块间的解耦能让你日后排查问题容易得多。
还有一个小坑:wx.login()拿到的code只能使用一次。如果你在页面onLoad里调用了登录接口,又在确定订单页再次调用,第二次必然失败。正确做法是第一次把openid对应的token存下来并复用它,而不是每次调接口都重新登录。
5.2 真机预览失败与域名白名单
本地开发者工具上一切正常,扫码真机预览后白屏或网络请求全部失败,这是新手最常见的问题。原因99%是域名不合规。微信小程序要求所有请求域名必须是HTTPS且完成备案,而且要在小程序后台配置到request合法域名列表中。
毕设阶段的最省事方案如下:
- 在开发者工具中继续勾选“不校验合法域名”用于本地调试;
- 要真机测试时,可以将后端服务打包部署到云服务器上,为后端配置HTTPS域名,然后在小程序管理后台把该域名添加到“request合法域名”列表;
- 如果没有服务器,也别急着买,可以使用内网穿透工具(如ngrok或cpolar)将本地端口映射成一个临时HTTPS地址,再把这个临时域名加到合法域名列表。但注意这类免费域名经常变动,只适合临时测试。
有同学会问,为什么模拟器上不校验域名能行,真机就不行?因为模拟器的“不校验”选项只在开发者工具中生效,手机上运行的正式版小程序是完全受微信服务器端配置约束的。
5.3 购物车数据不一致与库存超卖问题
购物车数据不一致的根源在于双写逻辑没用对。我见过一个同学的做法是:本地缓存存一份、服务端存一份,但用户修改数量时只改了本地缓存,服务端没同步,最后提交订单时对不上账。正确逻辑应该是:所有改动购物车内部状态的操作(加数量、减数量、删除、勾选)都要同步调后端接口。本地缓存只能作为“临时操作日志”,不能让用户感知到明显的卡顿。
再聊聊库存超卖。订单提交时校验库存,但同一件商品被多个人同时下单,一个事务里既要查库存又要扣库存,如果不用行锁,就可能出现两个订单都扣库存成功但实际库存只有一件的情况。解决方案很简单:更新库存时加上条件判断,让数据库自己来把关:
UPDATE goods SET stock = stock - #{num} WHERE id = #{goodsId} AND stock >= #{num}如果受影响行数为0,说明库存不足,事务回滚,订单创建失败。这是最简单的库存防超卖方案,不做分布式锁和队列,但已经足够应付商城的正常并发量。
5.4 小程序setData性能优化问题
如果一个商品列表页一次性渲染50条商品,每条商品三张轮播图片,你会发现页面滚动卡顿严重。原因是小程序的setData是把整个data对象序列化后从逻辑层传到渲染层,数据量一大就必然慢。
几个实用优化手段:
- 分页加载,每页只渲染10-15条数据,用
onReachBottom加载下一页; - 使用
wx:if和wx:elif控制图片懒加载,可以利用图片懒加载属性lazy-load; - 图片用CDN或缩略图,商品图片需要在存储时生成多尺寸,列表页只用小尺寸图,详情页再加载大图;
- 不要在
onPageScroll里频繁做setData,会直接把页面卡死。节流至少100ms起步。
5.5 一些问题速查表
| 现象 | 原因分析 | 排查步骤 |
|---|---|---|
| 小程序请求后端返回404 | 后端接口路径与前端请求不一致 | 打开Network面板比对实际请求URL与后端Controller的RequestMapping |
| 请求接口返回500 | 后端代码抛异常 | 查看后端控制台完整堆栈日志 |
| 数据库中文乱码 | 连接串或表字符集不是utf8 | 检查JDBC URL是否带characterEncoding=utf8,检查表与字段的collation |
| 本地图片能看真机看不了 | 图片URL是localhost | 使用局域网IP或部署后访问公网域名 |
| 下拉刷新失效 | 当前页面JSON未启用enablePullDownRefresh | 在页面的json配置中添加enablePullDownRefresh:true |
| 支付失败 | 未开通微信支付商户号 | 毕设使用模拟支付,在本地标记支付成功即可 |
| 管理端登录重定向死循环 | 拦截器把登录接口也给拦截了 | 确保登录接口在拦截器的excludePathPatterns中配置排除 |
这些坑每个都是我实操时反复踩过的,不是从文档里抄出来的。测试阶段多想想“如果用户手够贱会怎么操作”,这样反向推演,覆盖面会广很多。
6. 论文撰写视角的核心要点
6.1 如何写出一篇能过查重的系统设计论文
论文是这个项目交付的另外一半,很多技术能力不差的同学最后挂在论文上,挺可惜的。围绕这个商城系统,论文提纲可以参考下面这个框架:
- 第一章 绪论:介绍电子商城的发展背景,以及为什么选择微信小程序作为载体,国内外研究现状可以浅谈。
- 第二章 相关技术介绍:将涉及的技术栈逐一介绍,包括微信小程序、Spring Boot、MyBatis、MySQL。注意不要只写概念,要写在这个项目中分别承担什么角色。
- 第三章 需求分析:从用户角色角度出发,拆分为用户端功能和运营端功能,辅以用例图。
- 第四章 系统设计:画系统架构图、功能模块图、数据库ER图,详细说明核心表结构设计。
- 第五章 系统实现:按模块拍摄界面截图并配合文字说明,小程序端重点截首页、商品列表、购物车、订单。管理端重点截商品管理、订单管理、数据统计。
- 第六章 系统测试:编写测试用例表,记录测试步骤、预期结果、实际结果,附上功能测试、性能测试的截图。
- 第七章 总结:项目总结和不足,不要写展望能上天的空话。
写论文时要避免流水账,核心思路是:每一章都要说明“为什么这么做”和“怎么做”。比如数据库设计,不能只贴建表语句,要解释表与表之间的关联关系,字段类型为什么这么选。系统实现部分不要贴完整代码,只留核心代码片段和逻辑分析,否则查重率直接爆表。
6.2 答辩时的常见提问与应对策略
答辩环节老师问的问题是有规律的,围绕这套系统常见的有这几个:
- 为什么用微信小程序而不是H5?可以回答:小程序获客成本低、无需下载安装、体验近似原生App,同时具备微信生态的传播优势。
- 你的系统有哪些安全性考虑?从Token校验、统一响应码、密码加密、前端DOM元素注入防护(规范输入与输出)、SQL注入防护(使用参数化查询)几个层面来回答。
- 订单超卖问题怎么解决?使用数据库行锁条件更新,如
UPDATE ... WHERE stock >= num,再配合事务回滚。 - 如果用户量增加服务器压力大怎么办?可以从多级缓存(Redis缓存热门商品)、静态资源CDN加速、数据库读写分离三个层面提供扩展思路。
- 为什么不用uni-app?可以回答:此项目核心诉求是深度集成微信生态能力,原生框架对微信API的兼容性更好,且不需要考虑跨端复用问题。
每种问题的回答都不要只停留在概念层面上,最好能结合你项目里的具体代码、具体接口说明是怎么做的。老师通常并不指望你有多么高深的理解,而是想看你能不能把理论落地到代码里。
6.3 项目源码交付的注意事项
在最终交付源码时,有几个细节能让你的整体印象分瞬间提上来:
- 数据库初始化脚本要单独放一个文件,并且在README中写明如何导入、如何修改数据库连接配置。
- 接口文档不需要多精美,但要把每个接口的路径、请求参数、返回结果列清楚。用Markdown写一个API.md放在项目根目录即可。
- 演示视频最好录一段,大概3-5分钟,从管理端添加商品开始,到小程序端浏览下单,再到管理端发货,最后小程序端确认收货,完整走一遍业务流程。这个视频虽然不一定是硬性要求,但很多老师会觉得很用心。
- 不要提交配置文件中的敏感信息,比如数据库密码、AppSecret。如果源码要发给同学或公开到Github,一定要把AppSecret从代码中抽离出来,放到config文件并加入.gitignore。
交付源码不要临时压缩一坨了事,花半小时写一个清晰的README,把环境要求、启动步骤、注意问题都写明白,这能帮你省掉大量售后答疑的时间。其实大部分人的项目都是“能用但不好跑”,而一个好的README恰恰可以让你的项目变成“拿来就能跑”。
7. 项目后续扩展方向
7.1 接入微信支付与订阅消息
如果这个项目需要往真实运营方向推进,第一步就是接入微信支付。实现路径没有想象中那么神秘:后端先调用微信支付统一下单接口获取预支付交易会话标识prepay_id,然后返回给小程序端,小程序端调用wx.requestPayment拉起支付面板。但真实接入需要商户号,个体户或企业才能申请,个人开发者无法直接开通。所以毕设阶段用模拟支付是合规且足够的选择。
订阅消息是另一个高价值的扩展。比如用户下单后,通过订阅消息给用户推送“订单支付成功”或“商家已发货”的模板消息。这个功能的好处是:在毕设里能体现你对微信生态的理解深度;同时它实现起来也不难,只需要用户在小程序内点击授权订阅,后端调用subscribeMessage.send接口。注意订阅消息的授权是一次性的,一个模板ID只对应一次推送,用户在下次需要接收通知时需再次授权。
7.2 打造营销功能模块
商城类系统往往需要留住用户,而运营手段基本都是围绕营销模块展开的。比较值得练手的功能包括:
- 优惠券:后台创建优惠券,设置满减门槛,用户在小程序端领取,下单时选择使用并校验是否满足条件。
- 秒杀:设置指定商品在某个时间段以低价限量售卖。这个功能的实现复杂度比正常购买高不少,因为它需要考虑超高并发场景下的库存扣减。秒杀是面试时会被高频问到的高并发场景问题。
- 积分系统:用户下单获得积分,积分可以抵扣金额或兑换礼品。
这几个功能任意做上一个,项目的工作量和含金量就会上一个台阶。但注意别在毕设阶段贪多,如果你连主链路都没有打磨顺畅,营销模块加进去只会分散你的注意力。
7.3 部署上线:买服务器还是用云端?
很多同学纠结要不要把项目真正部署上线,好通过微信审核发布。有两点现实情况先摆出来:第一,微信小程序的个人主体不支持电商类目,必须有企业主体或个体工商户资质;第二,即使你完成了备案、配置了HTTPS域名、通过了微信审核,发布线上后还需要持续的运营维护成本。
所以我的建议是:
- 毕设阶段:把项目打包好,做到能在本地环境顺畅运行,配合演示视频即可。重点是把代码质量和业务完整性做扎实。
- 如有企业资质:可以考虑部署到一台便宜的云服务器(比如2核4G配置足够),使用宝塔面板搭建环境,部署效率极高。
- 想低成本尝试验证:用内网穿透工具临时暴露本地服务,配合开发者工具进行真机演示。这种方式只适合临时验收,不适合稳定运行。
7.4 这套项目的简历包装与面试话术
最后说说这套项目在你的求职简历上能怎么转化。一个商城项目是最典型的全栈练手项目,但从“做过”变成“能讲清楚”之间还有一大段距离。面试官大概率会围绕以下几个维度去提问:
- 为什么做成小程序而不是App?触达用户成本低、开发效率高、有微信生态背书。
- 订单系统的核心难点?状态机的合理设计、防止超卖、用户取消/超时未支付的兜底策略。
- 管理系统涉及多大的数据量?如果数据量上去了,哪些表需要分表或加索引。
- 如果重新做一次,哪些地方会优化?可以把分布式会话、Redis缓存热点数据、消息队列异步处理订单状态这三个方向提出来。
能把这几个问题接住并给出有说服力的回答,比简历花里胡哨写满一行行技术名词有用得多。说到底,商场系统只是表象,你真正要向面试官证明的是:你有完整的业务分析能力,有从数据库到接口再到前端页面的全链路交付能力,以及遇到问题时能独立排查和解决的能力。这套东西做透了,其中收获远超“交一份作业”本身。
我自己在带学生做类似题目的过程中,最常见的状态变化是:第一周觉得不就是个商城嘛,第二周开始被订单状态搞得头晕,第三周被前后端联调磨得没脾气。但只要扛过了集成阶段,这套项目给你带来的信息量,包括对微信生态的理解、对数据库模型设计的直觉、对业务状态流的敬畏,都会在以后的开发工作里反复复用。做项目确实没有捷径,唯一的捷径就是把每个环节都想清楚为什么,然后再动手。