简介:本资源是微信小程序毕业设计“移动学习平台”的完整项目包,面向计算机相关专业做毕业设计或课程设计的学生,可作为可运行原型与文档参考。项目采用微信小程序开发工具+Java后端+MySQL+B/S架构,实现管理员、教师、学生三类角色的核心流程:管理员管理教师、课程分类、班级、课程与作业审核;教师维护课程资源和作业审核;学生可提交作业、查看审核状态、收藏评论资源并浏览班级课程。包内共1312个文件,含241个图片素材、194个js、162个svg、151个vue、127个java、108个json以及98个wxml和95个wxss等,覆盖前后端主要代码与界面资源;另有sql和mp4演示视频便于直接导入和学习。压缩包大小约33.81MB,包含源码、演示视频、说明文档和数据库文件,目录结构清晰,适合快速跑通并二次开发。目前已有129人学习下载。
1. 微信小程序移动学习平台毕设资源:能跑通、能改、能答辩的完整骨架
做微信小程序毕业设计,最怕的不是页面写不出来,而是后端接口、数据库、角色权限这些“黑匣子”一碰就翻车。这份移动学习平台毕设资源,前端是微信小程序能直接导入的工程,后端是 Java + MySQL 的 B/S 结构,附带演示视频、说明文档和数据库脚本,覆盖了管理员、教师、学生三种角色的完整业务闭环。管理员管教师和课程分类,教师审核作业和管理课程资源,学生提交作业、收藏评论课程资源。不管是做毕业设计还是课程设计,拿它当骨架做二开,能省掉从零搭环境、造数据的大量时间。下面按我实际拆包的顺序,把技术栈、启动步骤、核心逻辑和踩过的坑一次说清。
2. 技术栈与角色权限:先看懂请求链路再动手改
2.1 从小程序到 Java 后端的请求链路
这个项目是典型的 B/S 结构:微信小程序承担前端页面和交互,Java 后端处理业务逻辑,MySQL 做数据持久化。小程序里凡是要动态数据的地方,都通过 wx.request 发起 HTTP 请求,打到后端 REST 接口上。后端常见组合是 Spring Boot + MyBatis-Plus,Controller 接收请求,Service 写业务,Mapper 操作数据库,最后把结果序列化成 JSON 返回给小程序。
以登录为例,完整链路是这样:小程序调 /api/login,后端按用户名密码查 user 表,比对成功后用 JWT 生成 token 返回;小程序把 token 存到本地 storage,之后每个请求的 header 都带 Authorization 字段;后端拦截器解析 token,失败就返回 401。这条链路里有一个容易忽略的环节——拦截器怎么判断哪些接口不需要登录。常见做法是给登录、注册这类开放接口加白名单,其余接口全部走鉴权。
我拆这份源码时,会先找 utils/request.js 或 common/request.js 这类公共请求封装。只要把 baseUrl 指到本机后端地址,登录、列表、提交作业这些页面基本就能通。所以动手改功能前,先画一遍这条请求链路,再改代码,比盲改前端页面靠谱得多。
2.2 三种角色各自能看到什么
管理员、教师、学生在界面上看到的内容完全不一样。管理员端是系统级维护:管理教师账号、维护课程分类、创建班级、维护课程、审核学生作业、上下架课程资源,这类数据变化会直接影响教师端和学生端的数据范围。教师端只看到与自己关联的课程、班级和学生,能对学生作业做“通过/退回”审核,能往课程里上传资源。学生端聚焦个人学习:查看所在班级和可选课程,提交作业,查看审核结果,收藏评论课程资源。
权限落地时,后端在登录成功时把角色 code 写进 JWT 的 payload,拦截器从 token 里取出角色,用字符串比对决定放行还是拒绝:
// 从 token 中取出角色标识 String role = JwtUtil.getRoleFromToken(token); // 仅 admin 和 teacher 角色可访问管理接口 if (!"admin".equals(role) && !"teacher".equals(role)) { return Result.error(403, "无权限访问"); }这段逻辑不复杂,毕设场景完全够用。答辩时老师问“你怎么做权限控制”,你直接说“用 JWT 携带角色标识,在拦截器里做接口级校验”,比一句“用了框架”更有说服力。
2.3 数据库核心表:看清业务模型
数据库脚本是整个资源里信息密度最高的部分。我拆包会先看表名和注释,基本能还原作者的整个业务设计。这个项目涉及的核心表大致如下:
| 表名 | 关键字段 | 说明 |
|---|---|---|
| user | username, password, role | 登录账号统一表 |
| student | student_no, name, class_id | 学生信息,归属班级 |
| teacher | teacher_no, name, title | 教师信息 |
| class | class_name, teacher_id | 班级,绑定负责教师 |
| course_category | cate_name, sort | 课程分类 |
| course | course_name, category_id, teacher_id | 课程,挂分类和教师 |
| course_resource | course_id, file_path, type | 课程资源,文件路径是关键 |
| resource_comment | resource_id, user_id, content | 资源评论 |
| resource_collect | resource_id, student_id | 资源收藏 |
| homework | student_id, course_id, file_path, status | 作业,status 控制审核流程 |
班级表通过 teacher_id 关联负责教师,课程表通过 teacher_id 关联授课教师,作业表通过 student_id 和 course_id 把学生与课程串起来。最核心的字段是 homework.status:0 表示待审核,1 表示通过,2 表示退回。教师审核作业,本质上是一次针对 status 的状态更新,不是复杂业务流。
还要注意课程资源表和作业表都有 file_path 字段。这说明文件很可能存放在服务器本地磁盘,数据库只存路径。如果你把项目部署到别的机器,一定要同步迁移文件目录,不然图片和附件会全部 404。
2.4 表间关系与外键处理
表之间的关系不算密集,但有几处要留意。student 与 class 是多对一,course 与 course_category 是多对一,homework 与 student 是多对一。资源评论和收藏都挂在 course_resource 的 ID 上,属于一对多。
常见做法是删除资源前先处理子表,后再删主表:
-- 删除资源前先清空关联的评论和收藏 DELETE FROM resource_comment WHERE resource_id = 1001; DELETE FROM resource_collect WHERE resource_id = 1001; DELETE FROM course_resource WHERE id = 1001;如果脚本里外键约束写得很严,建议改成逻辑删除。给 course_resource 加 is_deleted 字段,删除时置 1,查询时自动过滤,既不会外键爆炸,也保留恢复数据的余地。
2.5 为什么这份资源适合做毕设骨架
三个角色把“信息管理、业务流程、用户自服务”都覆盖到了,这是毕业设计评分里常见的几个得分点。你答辩时讲清楚这三条线的请求链路和状态流转,评审老师基本挑不出大毛病。改的时候也沿三条线分别加自己的想法,比如管理员加导出报表、学生加学习进度、教师加成绩分析,都比从零造系统省力。
3. 环境搭建与数据初始化:把项目从压缩包跑成线上效果
3.1 工具链准备与版本对应
这个项目的技术栈涉及到微信小程序开发工具、Java、MySQL,环境准备需要四样东西:JDK(8 或 11 都行)、MySQL(5.7 或 8.0)、微信开发者工具、一个数据库管理工具(Navicat 或直接用命令行)。
安装顺序我建议先装 MySQL,因为后端启动第一步就是连接数据库。JDK 装完在终端输入 java -version 确认;MySQL 装完用 mysql -u root -p 登录确认;微信开发者工具装完用测试号扫一下登录。如果本机之前装过别的版本,注意环境变量有没有指向对。
后端连接数据库的配置一般在 src/main/resources/application.yml 里,常见默认账号密码是 root/root 或 root/123456。如果你本机密码不同,启动后端必报 Access denied。先把密码改成你自己的,省得后面排查一小时。
3.2 导入数据库脚本与验证
资源里自带 .sql 文件,可能是完整建库脚本,也可能只是建表和初始数据。我习惯用命令行导入,可控性强:
# 创建数据库,并指定 utf8mb4 字符集,避免中文乱码 mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS mobile_learning DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" # 把 sql 脚本导入到刚创建的库中 mysql -u root -p mobile_learning < database.sql如果 sql 文件路径里含空格或中文,记得给路径加引号。导入完成后,验证 user 表里有没有初始账号:
-- 检查登录账号表是否已有初始数据 SELECT id, username, role FROM user;如果 user 表是空的,说明脚本里只建表没插数据。你需要手动补一条管理员记录。密码字段如果是 MD5 或 BCrypt,要去后端代码里找到加密工具类,生成对应密文再 INSERT,避免前端登录时密码比对不上。
3.3 三个批处理脚本:先读内容再执行
压缩包里带 1-install.bat、2-run.bat、3-build.bat,光看名字就知道它是按顺序走的。建议用文本编辑器打开,确认脚本里的路径与当前目录一致再执行。
1-install.bat 做依赖安装,后端执行 Maven 依赖下载,前端执行 npm install:
@echo off cd /d %~dp0 echo 安装后端依赖... call mvn install -DskipTests echo 安装前端依赖... cd frontend call npm install echo 安装完成 pause2-run.bat 做后端启动。如果后端是源码工程,脚本大概率是 mvn spring-boot:run;如果已经打成 jar,则是 java -jar target/xxxx.jar。启动后看到 Tomcat started on port 8080 基本就稳了。
3-build.bat 做前端构建。如果前端是 uni-app 工程,命令是 npm run build:mp-weixin,产物输出到 dist/build/mp-weixin 目录,再用微信开发者工具导入;如果是 HBuilderX 工程,也可能直接在 HBuilderX 里运行到微信开发者工具。
这里有个常见翻车点:压缩包解压后目录结构一变,脚本里的相对路径就失效。执行前先确认脚本里的 cd 路径和实际目录是同一层。
3.4 微信开发者工具导入与联调配置
导入小程序前端工程时,注意区分两种工程:如果目录里有 manifest.json 和 pages.json,它是 uni-app 工程;如果只有 app.json、app.js,是原生微信小程序工程。uni-app 工程需要先 build 或在 HBuilderX 里运行,原生小程序直接在开发者工具里打开工程目录。
导入后必改两处:appid 换成你自己的测试号;baseUrl 改为后端地址。
# 本地联调 http://localhost:8080 # 真机预览 http://192.168.x.x:8080同时在微信开发者工具右上角“详情-本地设置”里,勾选“不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书”,否则本地联调发 http 请求会被域名校验直接拦截。
3.5 后端启动后的联调自测清单
后端起来后,先用浏览器或 Postman 请求一个登录接口验证连通性。我一般会按这个顺序自测:
- 浏览器访问 http://localhost:8080/api/login,确认接口没挂。
- 小程序端执行一次登录,看是否成功拿到 token。
- 看后端控制台是否打印 SQL。如果能看到 SELECT * FROM user WHERE username=... 这样的日志,说明链路已经打通。
- 如果控制台没有 SQL,优先检查数据库账号密码、连接池配置,再看拦截器是否把请求误拦。
这套自测清单我每次搭完环境都会跑一遍,五分钟内能定位八成问题。
提示:数据库连接、端口占用、baseUrl 指向的问题占了环境搭建阶段九成以上的报错,先按这三项排查,不要急着改业务代码。
4. 核心功能拆解:从登录鉴权到作业审核的代码逻辑
这章把三条业务线拆开讲:登录鉴权是怎么做的、学生提交作业到教师审核的整条链路、课程资源的管理。看完你就知道改代码该从哪个文件下手。
4.1 登录接口与 JWT 鉴权
登录接口是整条业务线的入口,代码结构一般是这样的:
@PostMapping("/api/login") public Result login(@RequestBody LoginRequest req) { // 按用户名和加密后的密码查用户表 User user = userMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getUsername, req.getUsername()) .eq(User::getPassword, MD5Util.encrypt(req.getPassword()))); if (user == null) { return Result.error("账号或密码错误"); } // 生成 JWT token,payload 中携带用户 ID 和角色 String token = JwtUtil.generateToken(user.getId(), user.getRole(), user.getNickName()); return Result.success(token); }逻辑不复杂:用户名密码查到人,生成 JWT 返回;查不到就报错。要注意密码比对必须和数据库存储的加密方式一致。如果数据库里是 MD5 密文,代码里就要用同一种 MD5 工具类;如果数据库是明文,那后端大概率没做加密,你改代码时要多留个心眼。
我拆包时会特意看 JwtUtil 的过期时间设置,常见是 2 小时或 12 小时。如果毕设演示时间较长,token 中途失效会突然跳回登录页,观感很差。把过期时间临时调成 48 小时,或者在前端拦截 401 后自动重新登录,都能避免这种尴尬。
4.2 小程序请求封装与登录态管理
前端请求封装是所有页面发请求的必经之路。找到一个封装好的 request.js,它的作用就是统一拼 baseUrl、统一带 token、统一处理错误码:
const request = (url, method, data) => { return new Promise((resolve, reject) => { wx.request({ url: baseUrl + url, method: method || 'GET', data: data || {}, header: { // 从本地 storage 取出登录后保存的 token 'Authorization': wx.getStorageSync('token'), 'Content-Type': 'application/json' }, success: (res) => { // 后端返回 401 时说明登录态失效,跳回登录页 if (res.data.code === 401) { wx.navigateTo({ url: '/pages/login/login' }); return; } resolve(res.data); }, fail: reject }); }); };header 里的 Authorization 字段必须和后端拦截器取的名字一致,否则后端拿不到 token,请求全部 401。我见过前端写 token、后端取 Authorization,联调一上午全是 401,最后才发现字段名不一致。建议拆包后第一时间把前后端两个字段名对齐。
4.3 学生端提交作业:文件上传与表单提交
学生提交作业是业务闭环里的关键操作,涉及图片或文件上传。小程序端基本是 wx.chooseImage 选文件,再用 wx.uploadFile 把文件和表单数据一起打过去:
wx.chooseImage({ count: 1, success: function (res) { const tempFile = res.tempFilePaths[0]; wx.uploadFile({ url: baseUrl + '/api/homework/submit', filePath: tempFile, name: 'file', formData: { courseId: this.data.courseId, title: this.data.title, content: this.data.content }, success: (res) => { const data = JSON.parse(res.data); if (data.code === 200) { wx.showToast({ title: '提交成功' }); } } }); } });注意这里没有传 studentId,因为更安全的做法是从后端 token 里解析用户 ID,而不是信任前端传来的参数。后端 upload 接口要做两件事:把文件保存到本地磁盘或云存储,再把 file_path 和表单字段写入 homework 表。评审如果追问越权问题,你答“用户 ID 从 token 解析,不从前端取”,就是加分项。
4.4 教师端审核作业:状态流转与列表查询
教师审核作业的入口是审核列表,后端按教师 ID 关联课程,课程关联作业,把待审核记录拉回来:
@GetMapping("/api/homework/auditList") public Result auditList(@RequestParam Long teacherId) { // 只查询该教师名下课程关联的作业 List<HomeworkVO> list = homeworkMapper.selectAuditList(teacherId); return Result.success(list); }列表里每条记录的 status 都是 0(待审核)。审核动作是更新状态:通过置 1,退回置 2,同时把审核意见存到 audit_comment:
-- 审核通过,写入审核意见和审核时间 UPDATE homework SET status = 1, audit_comment = '内容完整,通过', audit_time = NOW() WHERE id = 88;这里用一个 tinyint 状态字段表达业务流程,简单直接,也容易在答辩里讲清楚。你不用设计一张审核流程表,毕设范围内状态字段完全够用。
4.5 课程资源管理与文件访问映射
课程资源的管理核心是文件上传和预览。文件存在服务器本地,数据库存 URL 相对路径。前端根据文件后缀决定渲染方式:图片用 image 标签,PDF 用 web-view,视频用 video 标签。
实际写的时候,我一般会在后端加一个静态资源映射,把 /files/** 指向磁盘里的真实目录:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 把 /files/** 的请求映射到服务器本地磁盘目录 registry.addResourceHandler("/files/**") .addResourceLocations("file:" + uploadPath + "/"); } }如果这段配置缺失,上传成功但小程序端无法加载文件,会误以为是前端代码有问题,实际是后端没有把静态文件暴露出来。
资源的收藏、评论功能相对简单,就是对两张子表做增删查。需要注意删除资源时同步删除相关收藏和评论,否则外键约束会让你删不下去。
5. 避坑记录:五个高频问题的现象、原因与解决
5.1 数据库连接报 Access denied
现象:后端启动时控制台持续刷 Access denied for user 'root'@'localhost'(using password: YES),应用根本起不来。
原因:application.yml 里配置的数据库账号密码和本机 MySQL 实际不一致,或数据库名写错、端口不是默认 3306。
解决:打开 backend/src/main/resources/application.yml,核对 spring.datasource 下的 url、username、password:
spring: datasource: url: jdbc:mysql://localhost:3306/mobile_learning?useUnicode=true&characterEncoding=utf8 username: root password: 123456把 password 改成你本机的真实密码,url 里的数据库名也要和脚本建库名一致。改完重启,如果还报错,用命令行登录 MySQL 确认账号密码确实可用,不要凭记忆写。
5.2 解压后出现 .baiduyun.downloading.cfg 残留文件
现象:解压后看到 tki-qrcode.vue.baiduyun.downloading.cfg、uni-load-more.vue.baiduyun.downloading.cfg 这类文件,或某些页面功能缺失报错。
原因:这是网盘客户端未下载完成留下的残留标记,原文件没下全,并不是资源本身缺少功能。tki-qrcode.vue 是二维码组件,uni-load-more.vue 是列表加载更多组件,缺失后对应页面会直接报错。
解决:把 .baiduyun.downloading.cfg 对应的原文件在网盘客户端重新下载完整,不要手动改后缀名去伪装。安全做法是解压前先检查压缩包里是否有残留标记文件,有的话单独补齐再解压。
5.3 真机预览白屏或接口全部失败
现象:微信开发者工具里一切正常,扫码真机预览后页面白屏或接口全部 fail。
原因:手机端访问 localhost 指向的是手机自己,访问不到电脑上的后端;同时真机上“不校验合法域名”设置不生效。
解决:把 baseUrl 改成电脑的局域网 IP,比如 http://192.168.x.x:8080,确保手机和电脑在同一网络。Windows 下执行 ipconfig 查 IPv4 地址,Mac 下执行 ipconfig getifaddr en0。后端 Spring Boot 的 server.address 如果配置了 127.0.0.1,也要改成 0.0.0.0 或直接注释,否则局域网请求进不来。改完记得重新编译运行。
5.4 上传成功但图片加载 404
现象:学生提交作业时提示上传成功,后端文件目录里也有文件,但前端按返回的 file_path 访问却 404。
原因:前端拿到的 file_path 是相对路径,比如 /files/xxx.jpg,而后端没有配置对应的静态资源映射,这个 URL 根本不存在。另一种可能是拼接路径时多了一层斜杠,比如 baseUrl 结尾带 /,file_path 开头也带 /,拼出来变成 //files。
解决:在后端加上 /files/** 的静态资源映射,把请求指到服务器实际存储文件的目录。拼接 URL 时统一处理,baseUrl 结尾不要带 /,或 file_path 开头不要带 /,二选一。Windows 下路径分隔符用 \,Linux 和 Mac 用 /,代码里建议统一写 /,避免部署到不同系统时路径错误。
5.5 .bak 备份文件被当成主文件改
现象:前端工程里有 main.css.bak、IndexAsideStatic.vue.bak、BreadCrumbs.vue.bak,同学改样式或组件后页面没任何变化。
原因:.bak 是备份文件,不参与编译。源码运行时真正加载的是 main.css、IndexAsideStatic.vue 这些正式文件。你一直在改 .bak,等于改了个寂寞。
解决:先分清哪些文件参与编译。.vue、.js、.css、.json 这些才是运行文件;.bak 可以直接忽略或删掉。想彻底清理,在项目根目录执行 find . -name "*.bak" -delete,注意先备份一份再删。血的教训:我当年第一次拿到这类工程,把 IndexHeader.vue.bak 当成主文件改了十分钟,页面纹丝不动,才发现从一开始就开错了文件。
6. 把毕设改成自己的:换皮、加表与答辩演示的落地技巧
6.1 换主题色与首页文案
小程序前端一般有一个全局样式文件,像 main.css 或 App.vue 里定义的主题变量。找到 primary-color 这类变量,整体换色;再替换首页的轮播图、课程标语,外观上立刻不像从资源模板复制来的。改成你自己的课程名称和专业方向,比只改配色更有辨识度。
6.2 给作业表加评分字段
在 homework 表加 score、comment 两个字段,教师审核时多填评分。改动涉及后端实体类、Mapper XML、前端审核表单和结果展示页四个地方。加字段之前先梳理数据流,不然容易出现数据库导入了,但接口返回 JSON 里没有新字段的情况。操作顺序建议是:先改 SQL 加字段,再改后端实体和 Mapper,最后改前端页面,每一步完成后用接口测试工具验证一次。
6.3 答辩演示脚本:三分钟过完三条业务线
先不看代码,把项目的演示顺序稳定下来。我一般这样走:
- 管理员账号登录,展示教师列表、课程分类和班级管理;
- 切教师账号,进入作业审核列表,把一条待审核作业通过;
- 切学生账号,提交一份新作业,再切回教师端看审核状态更新。
这个顺序能在三分钟内让评审看到三个角色和完整闭环。如果时间充裕,再展示一下课程资源的收藏和评论交互。技术提问环节把登录鉴权、状态流转、文件上传映射这三个点讲透,基本就能站住脚。
6.4 数据备份与恢复练习
答辩前可以演练一次“数据库误删恢复”:用 Navicat 备份一份数据库,然后模拟删一条班级记录,再用备份恢复。这个动作能帮你熟悉数据库脚本,万一答辩现场演示时数据被弄乱,你有后悔药。备份文件放在项目外,不要和源码混在一起。
从那以后,我每次拿到这种带 .bak 和残留下载配置的项目包,都会先列一遍文件清单,确认哪些参与编译、哪些是备份、哪些是未下全的残留,再进 IDE 动手改。这套习惯帮我躲掉了不少低级错误,也希望帮到你。
本文还有配套的精品资源,点击获取