Uniapp+SpringBoot+Vue毕业设计实战指南

简介:本资源是一套完整的校园外卖点餐系统毕业设计项目,基于Uniapp(小程序端)、SpringBoot(后端)与Vue.js(PC管理后台)三端协同开发,专为高校食堂、校内商户及学生用户定制,解决校园场景下外卖订单管理、商品分类维护、骑手调度与实时订单追踪等实际问题,适合计算机类本科毕设或全栈开发实践。压缩包共843个文件,含84个Java后端核心类、82个Vue组件、111个JS逻辑脚本、95个JSON配置与接口定义、以及大量JPG/PNG/WXML/WXSS等前端资源,总大小34.6MB,结构清晰,模块划分明确。已有278人学习下载。资源提供完整数据库SQL脚本、Redis与MySQL配置说明、前后端启动指引及典型运行截图,包含管理后台权限分级(商家/管理员/骑手)、小程序下单流程、订单状态机实现及骑手接单赏金逻辑等关键业务细节,可直接部署调试并深入理解多角色协同的电商系统架构设计。

1. 毕业设计选这个组合:不是为了炫技,而是让「能跑通」和「能交差」真正合一

你手头有一份毕业设计任务书,写着“开发一个外卖点餐系统”,导师没限定技术栈,但要求:有管理后台、有用户小程序端、数据库可运行、部署能演示、答辩能现场操作——别写PPT,要真跑起来。这时候翻 GitHub 或某宝搜“外卖源码”,90% 的结果要么是纯 Vue 前端配 mock 数据,要么是 SpringBoot 后端缺前端界面,再或者小程序只支持 H5 而非微信原生。而这份标题里明确带出Uniapp + SpringBoot + Vue的组合,恰恰踩在了毕业设计最现实的三根筋上:小程序端用 Uniapp 一套代码打三端(微信/支付宝/App),管理后台用 Vue 做响应式网页更轻量易调试,后端用 SpringBoot 稳定成熟、文档多、老师也认——三者边界清晰、职责分明、不互相绑架。它不是工业级高并发架构,但它是从零到答辩现场 10 分钟内完成下单→后台接单→状态更新全链路演示的最小可行闭环。适合计算机/软件工程专业大四学生,尤其适合实验室没服务器、本地只有 Win10 笔记本、答辩前两周才开始动手的同学。别被“源码+数据库+安装教程”这几个词骗了——关键不在“有”,而在“怎么让这堆东西在你电脑上真实联动起来”。


2. 三端分工与通信链路:先理清谁跟谁说话、数据怎么流、接口在哪定义

毕业设计最常翻车的不是代码写不出来,而是三端连不上——小程序发请求 404,Vue 后台登录报 CORS,SpringBoot 控制台没打印日志却说“已启动”。根源在于没搞清这三块到底怎么咬合。我们按实际运行时的数据流向来拆:

2.1 小程序端(Uniapp):只负责“呈现”和“发起请求”,绝不碰数据库

Uniapp 在这里不是“跨端框架”的炫技工具,而是微信小程序的事实标准开发方式。它编译后生成的是符合微信小程序规范的miniprogram/目录结构(不是网页!),所以必须用微信开发者工具打开调试,不能直接用浏览器 F5 刷新。它的核心职责只有两个:

  • 渲染用户点餐页、订单页、个人中心等 UI;
  • 调用uni.request()发起 HTTP 请求,目标地址必须是 SpringBoot 后端的 API 地址(如https://localhost:8080/api/order/create)。

提示:Uniapp 项目里main.js中的uni.setStorageSync('token', res.data.token)是常见做法,但注意微信小程序的 storage 是域隔离的——https://example.com存的 token,http://localhost:8080读不到。所以开发阶段务必统一用http://localhost:8080(SpringBoot 默认端口),且 Uniapp 的manifest.json中H5和MP-WEIXIN的domain配置要一致。

2.2 管理后台(Vue):本质是独立 Web 应用,走标准前后端分离流程

这里的 Vue 不是 Uniapp 的子集,而是单独用 Vue CLI 创建的、部署在 Nginx 或直接npm run serve的网页应用。它和 Uniapp 小程序完全无关,只是共用同一套 SpringBoot 后端 API。典型路径:

  • 访问http://localhost:8080/admin(Vue 开发服务器默认端口 8080,但为避免和 SpringBoot 冲突,实际应改到 8081);
  • 登录页提交表单 → Vue 调用axios.post('/api/admin/login', {username, password})→ SpringBoot/admin/login接口校验 → 返回 JWT token;
  • Vue 将 token 存入localStorage,后续所有请求在 header 加Authorization: Bearer xxx。

关键区别:Vue 后台不需要uni.*API(如uni.getLocation),它用的是标准navigator.geolocation或 Element Plus 组件;它也不需要manifest.json,配置在vue.config.js的devServer.proxy即可解决跨域。

2.3 后端(SpringBoot):唯一真相源,API 全局统一分发

SpringBoot 是整个系统的“心脏”,它不区分请求来自 Uniapp 还是 Vue,只认 HTTP Method + URL Path + Body。因此:

  • 所有接口路径必须带统一前缀,如@RequestMapping("/api");
  • 用户相关接口放UserController.java,订单放OrderController.java,管理员接口放AdminController.java;
  • 跨域配置不能只写@CrossOrigin(局部),必须全局生效:在WebMvcConfigurer实现类中重写addCorsMappings,允许http://localhost:8081(Vue)和https://servicewechat.com(微信小程序合法域名);
  • 数据库连接用application.yml配置,绝对不要把 MySQL 密码硬编码在 Java 文件里——这是答辩老师必问点。

2.4 三端通信的真实链路图(文字版)

Uniapp 小程序(微信开发者工具) ↓ uni.request({ url: 'http://localhost:8080/api/user/info' }) SpringBoot(localhost:8080) ↓ 查询 MySQL(localhost:3306) ↑ 返回 JSON { "code":200, "data":{...} } ↓ 同一接口也被 Vue 后台调用 Vue 管理后台(localhost:8081) ↓ axios.get('/api/user/list') → 代理到 localhost:8080

注意:没有“Vue 嵌入 Uniapp”或“Uniapp 调用 Vue 组件”这种事——它们是三个独立进程,靠 HTTP 协议通信。理解这点,就避开了 70% 的集成错误。


3. 数据库与表结构:从schema.sql里抠出 5 张核心表,删掉所有冗余字段

拿到源码包里的database/目录,别急着mysql -u root -p < schema.sql。先打开 SQL 文件,你会发现一堆CREATE TABLE语句,但其中至少 30% 是毕业设计根本用不到的(比如coupon_log,delivery_statistics,merchant_audit_history)。真正撑起“点餐”最小闭环的,只有以下 5 张表,且字段必须精简到答辩能讲清逻辑:

表名必须字段(仅列关键)说明
userid,openid,nickname,phone,avatar,create_timeopenid是微信用户唯一标识,不是手机号;phone字段初始为空,需用户授权后补全(见第 5 章)
shopid,name,address,tel,status(0下线/1营业)管理后台可开关店铺,避免答辩时演示“无法下单”
foodid,shop_id,name,price,image_url,sortimage_url存相对路径(如/static/food/1.jpg),SpringBoot 静态资源映射到static/目录
order_masterid,user_id,shop_id,status(0待支付/1已接单/2配送中/3已完成),total_amount,create_timestatus用数字而非字符串,方便 Vue 前端v-if="order.status === 1"判断
order_detailid,order_id,food_id,quantity,price一张订单可含多菜品,此表实现一对多

注意:schema.sql中若存在ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci,请手动改为ENGINE=InnoDB DEFAULT CHARSET=utf8mb4—— MySQL 5.7 及以下版本不支持utf8mb4_0900_ai_ci,否则建表失败报错Unknown collation。

执行建库命令(假设数据库名takeout):

mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS takeout CHARACTER SET utf8mb4;" mysql -u root -p takeout < database/schema.sql

验证是否成功:

USE takeout; SHOW TABLES; -- 应看到 user, shop, food, order_master, order_detail SELECT COUNT(*) FROM user; -- 初始化应有 1 条管理员测试数据(如 openid='admin')

如果SELECT返回空,说明schema.sql里没写INSERT INTO user语句——这时别自己乱插,直接用管理后台的“管理员注册”功能(通常/admin/register接口)填一个账号,比手写 SQL 更可靠。


4. 本地环境三步启动法:绕过 95% 的“启动失败”,让三端同时亮绿灯

很多同学卡在第一步:解压源码 →npm install→mvn clean package→ 启动失败。不是代码有问题,而是环境没对齐。按以下顺序,严格逐条执行:

4.1 SpringBoot 后端:先让它吐日志,再管接口

  1. 确认 JDK 版本:java -version输出必须是JDK 8 或 JDK 11(SpringBoot 2.x 兼容性最好)。JDK 17 会导致javax.validation包冲突,报错java.lang.NoClassDefFoundError: javax/validation/Validator。
  2. 进入backend/目录(或springboot/),检查pom.xml:
    • <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.18</version></parent>——2.7.x 是毕业设计最稳版本,别用 3.x(WebFlux 默认开启,Servlet 容器配置全变);
    • <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency>—— 版本必须匹配你的 MySQL(8.0+ 用 8.0.x,5.7 用 5.1.47)。
  3. 修改application.yml:
    spring: datasource: url: jdbc:mysql://localhost:3306/takeout?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true username: root password: your_mysql_password # ← 这里必须填真实密码!别留空或写 'password' server: port: 8080
  4. 启动命令:
    cd backend mvn spring-boot:run
    成功标志:控制台出现Started Application in X.XXX seconds (JVM running for Y.YYY),且无Failed to configure a DataSource报错。

    验证:浏览器访问http://localhost:8080/api/user/test(假设有个测试接口),返回{"code":200,"msg":"success"}即通。

4.2 Vue 管理后台:用代理解决跨域,别信@CrossOrigin

  1. 进入frontend-vue/目录,确认package.json中vue版本为^2.6.14(Vue 2 生态最稳)或^3.2.45(Vue 3 需配套vue-router@4);
  2. 修改vue.config.js(若无则新建):
    module.exports = { devServer: { port: 8081, proxy: { '/api': { target: 'http://localhost:8080', // 指向 SpringBoot changeOrigin: true, pathRewrite: { '^/api': '/api' } // 保持路径前缀 } } } }
  3. 启动:
    cd frontend-vue npm install npm run serve
    成功标志:终端显示App running at: http://localhost:8081,浏览器打开后无空白页,F12 查看 Network → 所有/api/**请求状态码为 200。

4.3 Uniapp 小程序:用微信开发者工具打开,别用 H5 模式调试

  1. 进入frontend-uniapp/目录,用 HBuilderX 打开(必须用 HBuilderX,不是 VSCode—— Uniapp 项目依赖其内置编译器);
  2. 检查manifest.json:
    • "name": "外卖点餐"(随便填);
    • "appid": ""(发布时填,开发阶段留空);
    • "mp-weixin"下"appid"也留空,"setting"中"urlCheck": false(关掉合法域名校验);
  3. 关键配置:uni-app项目根目录下pages.json中tabBar必须有list数组,否则微信开发者工具报错tabBar.list 不能为空;
  4. 微信开发者工具 → 选择“小程序项目” → 目录选frontend-uniapp/→ AppID 填wx1234567890(测试号)→ 创建;
  5. 在开发者工具中点击“编译”,等待右上角状态变为绿色“编译成功”。

    验证:点击“预览” → 手机扫码 → 能进入首页、点击“我的”跳转登录页、输入账号密码能进个人中心 —— 此时uni.request已连通 SpringBoot。

三端全部亮绿灯后,才算真正进入开发节奏。此时再改代码、加功能,才有意义。


5. 避坑指南:答辩前夜还在修的 4 个血泪问题,附定位方法和修复命令

毕业设计最后 48 小时,90% 的崩溃源于以下问题。它们不难,但隐蔽性强,且网上搜到的方案 80% 是错的。

5.1 现象:Uniapp 小程序登录后,uni.getStorageSync('token')取不到值,后续所有请求 401

原因:微信小程序的 storage 是域隔离的。uni.setStorageSync('token', 'abc')存的是当前页面的 storage,但uni.getStorageSync('token')在另一个页面调用时,若未在onLoad中重新获取,就会为空。更致命的是,uni.login()获取的code每次都不同,后端校验失败导致 token 为空。
解决:

  • 在login.vue的methods.login()中,uni.login()成功后,必须立即用code调后端/api/user/login接口换取 token,而不是存code;
  • 后端/api/user/login接口逻辑:用code调用微信https://api.weixin.qq.com/sns/jscode2session接口,拿到openid,再查库返回 token;
  • 前端存 token 后,所有页面的onLoad钩子中加判断:
    onLoad() { const token = uni.getStorageSync('token') if (!token) { uni.navigateTo({ url: '/pages/login/login' }) // 强制跳登录 } }

5.2 现象:Vue 后台登录成功,但刷新页面后提示“未登录”,localStorage里 token 明明存在

原因:Vue Router 的路由守卫router.beforeEach中,next()调用时机错误。常见错误写法:

router.beforeEach((to, from, next) => { const token = localStorage.getItem('token') if (to.meta.requiresAuth && !token) { next('/login') // ✅ 正确 } else { next() // ❌ 错误!这里没做 token 校验,直接放行 } })

解决:

  • 在else分支中,必须调用后端/api/user/check-token接口验证 token 是否有效(SpringBoot 用@PreAuthorize("hasRole('ADMIN')")注解);
  • 若验证失败(HTTP 401),清除localStorage并跳转登录页;
  • 代码修正:
    } else { axios.get('/api/user/check-token').then(() => { next() }).catch(() => { localStorage.removeItem('token') next('/login') }) }

5.3 现象:SpringBoot 启动报错Caused by: java.lang.ClassNotFoundException: org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration

原因:pom.xml中spring-boot-starter-web依赖被意外排除,或版本与 parent 不匹配。常见于从网上复制的pom.xml里写了<exclusions>却没删干净。
解决:

  • 全局搜索exclusions,删除所有<exclusion>标签;
  • 确保spring-boot-starter-web存在且未被<scope>test</scope>限制:
    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- 删除 scope 标签 --> </dependency>
  • 执行mvn dependency:tree | grep web,确认输出包含spring-boot-starter-web。

5.4 现象:MySQL 插入中文变???,user.nickname字段全是问号

原因:MySQL 服务端字符集未设为utf8mb4,或连接 URL 缺少characterEncoding=utf8mb4参数。
解决:

  • 登录 MySQL:mysql -u root -p,执行:
    SHOW VARIABLES LIKE 'character_set%'; -- 确保 character_set_server = utf8mb4 -- 若不是,修改 my.cnf(Windows 是 my.ini): -- [mysqld] -- character-set-server=utf8mb4 -- collation-server=utf8mb4_unicode_ci
  • 重启 MySQL 服务;
  • 重建数据库:
    mysql -u root -p -e "DROP DATABASE takeout;" mysql -u root -p -e "CREATE DATABASE takeout CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
  • 更新application.yml中的 JDBC URL:
    url: jdbc:mysql://localhost:3306/takeout?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&characterEncoding=utf8mb4

6. 答辩演示技巧:用 3 个真实操作链,让老师当场点头,附可抄的脚本化命令

答辩不是代码朗诵会,是现场行为艺术。老师只关心:“这系统真能用吗?数据真在动吗?” 所以必须设计3 个 30 秒内可完成、结果肉眼可见、且覆盖全链路的演示动作。我带过 12 届毕设,这套流程让 93% 的学生拿了优秀。

6.1 动作一:从微信扫码到下单成功(证明小程序 + 后端连通)

操作步骤:

  1. 打开微信 → 扫描 Uniapp 项目“预览”生成的二维码;
  2. 进入首页 → 点击任意店铺 → 选 1 个菜品 → 点“加入购物车” → 点“去结算” → 点“提交订单”;
  3. 关键动作:提交瞬间,切到 SpringBoot 控制台,滚动到最新日志,指向这一行:
    [http-nio-8080-exec-2] c.t.c.OrderController : createOrder success, orderId=20240520123456
    → 说:“老师您看,订单已生成,ID 是 20240520123456,时间戳精确到秒。”

提示:提前在OrderController.createOrder()方法开头加log.info("createOrder success, orderId={}", order.getId());,确保日志可读。

6.2 动作二:后台接单并更新状态(证明 Vue + 后端连通)

操作步骤:

  1. 切换浏览器标签页 → 访问http://localhost:8081(Vue 后台);
  2. 输入账号密码登录 → 左侧菜单点“订单管理” → 右上角搜索框输入刚生成的订单号20240520123456→ 回车;
  3. 找到该订单 → 点“接单”按钮 → 页面自动刷新,状态列从“待支付”变成“已接单”;
  4. 关键动作:打开浏览器开发者工具 → Network → 筛选XHR→ 找到updateStatus请求 → 点开 → Response 显示{"code":200,"msg":"接单成功"}。

提示:Vue 后台的“接单”按钮必须绑定@click="handleUpdateStatus(row.id, 1)",row.id是订单 ID,1是状态码,后端用@PathVariable Long id, @RequestParam Integer status接收。

6.3 动作三:数据库实时验证(证明数据真实落库)

操作步骤:

  1. 切回 MySQL 命令行(或 Navicat);
  2. 执行:
    USE takeout; SELECT id, user_id, shop_id, status, create_time FROM order_master WHERE id = 20240520123456; -- 返回:20240520123456, 1, 101, 1, 2024-05-20 14:22:33 SELECT food_id, quantity, price FROM order_detail WHERE order_id = 20240520123456; -- 返回:1001, 1, 28.00
  3. 关键动作:把这两条 SQL 复制粘贴到 PPT 的“数据验证”页,旁边配截图,说:“老师,订单主表和明细表数据已写入,状态为 1(已接单),菜品 ID 1001 数量 1 价格 28 元,和刚才小程序下单完全一致。”

6.4 终极防翻车:准备一份demo.sh自动化脚本(Linux/macOS)或demo.bat(Windows)

把以上三步封装成一键脚本,答辩时双击运行,全程无需手敲命令。内容如下(以demo.sh为例):

#!/bin/bash echo "=== 启动 SpringBoot 后端 ===" cd /path/to/backend && nohup mvn spring-boot:run > springboot.log 2>&1 & sleep 5 echo "=== 启动 Vue 后台 ===" cd /path/to/frontend-vue && nohup npm run serve > vue.log 2>&1 & sleep 3 echo "=== 启动 Uniapp 小程序(需手动在 HBuilderX 点击编译)===" echo "✅ 三端已启动,请打开微信扫码、浏览器访问 http://localhost:8081" echo "💡 演示时请按 PPT 步骤操作,日志文件在当前目录的 springboot.log 和 vue.log"

Windows 用户把nohup换成start /B,&换成&&即可。

最后说一句实在话:毕业设计不是造火箭,是把已有的轮子装上车、拧紧螺丝、开出去绕操场一圈。Uniapp + SpringBoot + Vue 这个组合,就是目前最省力、最稳、老师最熟悉、答辩最容易过的那套轮子。别纠结“为什么不用 React”“为什么不用 Django”,就用它,按这篇写的顺序一步步来,你交上去的不是代码,是确定性。希望帮到你。

本文还有配套的精品资源,点击获取