
1. 毕设选型为什么最后锁定了 SpringBoot Vue 组合每年到了毕设季也就是现在这个时间点很多同学开始在技术选型上反复横跳。天天刷论坛、看热搜一会儿觉得 PHP 简单一会儿觉得 Flask 轻量结果折腾两周发现连个像样的后台管理界面都没拼出来。作为经历过一次完整 Java Web 毕设的人我特别想说一句如果你的题目是在线学习平台这类的管理系统SpringBoot Vue 前后端分离就是最稳的答案没有之一。先别急着反驳我帮你把逻辑理一遍。SpringBoot 的生态成熟度摆在那里网上随便一搜就是大量现成的模板项目、依赖配置、问题解决方案遇到报错你几乎不可能找不到对应的博客或帖子。Vue 这边更是夸张中文文档写得清楚组件化开发思路对新手友好得不像话就算你之前没碰过前端工程化照着官方教程把 vue-cli 或者 vite 的项目跑起来也就是一个下午的事。这两个东西配合在一起做在线互动学习网站正好覆盖了用户管理、课程展示、视频播放、互动评论这类需求的所有技术点而且每一块都有大量的现成轮子可以用。我要强调的是毕设项目的核心评判标准从来不是用了多少新技术而是功能是否完整、逻辑是否自洽、代码是否规整。用 SpringBoot 管后端接口和数据库用 Vue 管前端页面渲染和交互中间走 RESTful API 通信这一套流程本身就是行业里最常见的开发范式你做完一个项目相当于提前演练了一遍真实的开发工作流答辩的时候也能理直气壮地讲清楚每个环节的设计理由。另外一个现实因素是资源好找。完整的项目源码、SQL 脚本、接口文档这些东西SpringBootVue 的组合存量最大。你不需要从零开始摸索怎么建表、怎么分页、怎么做权限校验别人踩过的坑都有文字记录。把精力省下来放在理解业务逻辑、跑通整个流程、准备答辩追问上这才是性价比最高的做法。2. 数据库设计在线学习平台的表结构拆解与 SQL 脚本要点拿到一个毕设题目第一件要做的事不是写代码而是把数据库表结构理清楚。在线互动学习网站说白了就是用户 课程 互动三个核心模块大部分表都是围绕这三个词展开的。这一节我把表结构拆开讲你照着这个思路去调整自己的脚本基本不会出大问题。2.1 用户角色设计为什么必须要有 player 和 admin 两个端我在最初的版本里只建了一张 user 表把所有注册用户塞在一起管理员也是在里面加个标识字段。后来做到后台管理功能时发现权限逻辑混在一起会导致接口校验特别啰嗦每个请求都要判断当前用户是不是 admin代码写得很痛苦。改成用户表 角色字段的方案之后后台接口直接通过 SpringBoot 拦截器统一校验省了很多事。用户表建议保留这些字段id、username、password记得加密存储、nickname、avatar、email、phone、role可取值 player/admin、status启用/禁用、create_time、update_time。密码加密用 BCryptSpring Security 自带的 BCryptPasswordEncoder 就行不要用 MD5答辩时被问密码怎么存储的如果你说 MD5老师很容易追着问彩虹表攻击的问题给自己挖坑。课程相关的表是整个系统的核心。course 表放课程基础信息字段包括 id、title、subtitle、cover、teacher_name、category_id、price0 表示免费、level初级/中级/高级、intro课程简介、status上架/下架、create_time。注意要单独建一个 category 分类表而不是把分类名直接塞在 course 表里因为分类是做筛选功能的基础冗余字段在后续的搜索和分组统计里会非常麻烦。互动模块是这个项目的亮点也是体现在线互动这四个字的关键。我在表结构上设计了三块comment 评论表、collect 收藏表、learn_record 学习进度记录表。comment 表要支持层级评论所以除了 id、course_id、user_id、content、create_time 之外还要有 parent_id 字段指向父评论root_id 字段指向根评论这样前端做楼中楼才能方便地递归渲染。collect 表很简单就是 course_id user_id 的唯一索引用于判断当前用户是否收藏过。learn_record 表用来记录每个用户学到课程的哪个章节字段包含 id、user_id、course_id、section_id、watch_duration、is_finished这个表在我的学习进度页面会用到。课程的视频内容不建议直接存文件路径到数据库里而是把视频上传到对象存储或者直接用 FastDFS/MinIO 这类服务管理数据库里只存视频的 URL 或者 key。我在项目中用了 MinIO 来存视频文件SQL 脚本里只需要一个 video_url 字段记住地址就好。理由很简单数据库不适合存大文件而且你在毕设演示时视频文件是本地资源系统换一台机器跑文件路径如果写死视频就会全部失效用 MinIO 或者相对路径方案会灵活很多。整套 SQL 脚本的编写要注意几点第一所有表都加 create_time 字段这是通用设计答辩时解释便于追溯数据很有说服力第二主键用自增整数就可以不要刻意去搞雪花 ID毕设查重和答辩不会因为 ID 生成策略给你加分反而可能因为分布式 ID 引入不必要的追问第三外键约束尽量少用逻辑外键就足够这样删除数据时灵活也少踩删不掉的坑第四统一用 InnoDB 引擎和 utf8mb4 字符集否则中文评论内容容易出现乱码。2.2 SQL 脚本的分步执行策略与初始数据填充很多同学拿到 SQL 脚本直接往 Navicat 里一扔执行报错就开始慌。实际上在线学习平台这类项目SQL 脚本的正确打开方式是分步骤执行而不是全量运行。我的建议是拆成三个文件schema.sql建库建表、init_data.sql初始管理员账号和分类数据、demo_data.sql示例课程和用户数据。schema.sql 里面第一步创建数据库本身指定字符集然后再切到对应的库去建表。这里有个容易踩的坑如果你的脚本里用了 DROP TABLE IF EXISTS而数据库里已经有正在跑的数据一执行就全没了。所以我一般不在初始化脚本里放删除语句除非明确写清楚这是一个重置脚本。对于毕设项目我建议你在脚本注释中标注清楚每张表的用途这样老师打开脚本就能快速理解你的设计意图印象分直接上一个档次。init_data.sql 至少要提供一条管理员账号和一条测试玩家账号管理员用户名建议用 admin、密码用 123456 配合 BCrypt 加密后的字符串。这里容易犯糊涂的是你直接在 SQL 里写 INSERT 一条明文密码然后登录时发现永远验证不通过。因为你的后端代码用的是 BCrypt 校验而 BCrypt 只能验证加密后的结果你必须在初始化脚本里放的是 BCrypt 加密后的密文而不是明文。我在第一次写这个脚本时就在这里栽了跟头后来专门写了个临时接口把明文转密文输出才把初始化数据补齐。demo_data.sql 是用来填充演示环境的假数据。课程分类至少要有前端开发、后端开发、数据库、运维、人工智能这几类方便演示分类筛选。示例课程每个分类放 3 到 4 门课程封面图可以用占位图服务尽量让页面看起来有内容。用户数据放 5 到 8 个密码一样是加密后的 123456。评论数据要模拟出至少两条楼中楼比如一条根评论下面有两条回复这样的前端展示效果比全部平铺的列表强得多。3. 后端 SpringBoot 核心实现从分层思想到接口设计的完整链路SpringBoot 后端这部分我不想一句一句带你写 controller因为网上那些教学文章多得很。我更想跟你讲清楚的是一个在线学习平台项目里哪些模块是必不可少的以及每个模块背后的设计逻辑。你把骨架搭对了代码是水到渠成的事。3.1 分层架构与统一响应封装我在这个项目里用的是经典的四层结构controller、service、mapper、entity。Controller 层只做参数接收和调用 Service不在里面写任何业务逻辑。Service 层处理核心业务比如用户注册时校验用户名是否重复、课程列表查询时拼接过滤条件、提交评论时验证用户有没有购买课程。Mapper 层用 MyBatis-Plus 写简单的 CRUD 和分页查询复杂一点的 SQL 通过注解或者 XML 实现。Entity 类对应数据库表的字段用 Lombok 的 Data 注解减少 getter/setter 的样板代码。接口返回结构要统一。我定义了一个通用的 Result 类包含 code、message、data 三个字段code 为 200 表示成功400 表示参数错误401 表示未登录500 表示服务器异常。这个类在前后端联调时至关重要因为前端 Axios 拦截器可以统一判断 code 并弹出对应的提示不必每个接口单独处理错误状态。如果你不统一返回结构前端就要在每个接口的 response 里去猜字段联调过程会变成大型翻车现场。异常处理一定要用全局异常处理器。我在项目里用 RestControllerAdvice 加 ExceptionHandler 分别拦截业务异常、参数校验异常和运行时异常让所有异常都能落到统一的 Result 格式里返回给前端。这里有个小细节不能把堆栈信息直接返回给前端而是要在日志里记录堆栈返回给用户的只有友好提示。这样既方便你排查问题也不会暴露系统内部信息。3.2 登录鉴权JWT 的接入流程和权限控制思路在线学习平台里有些接口是公开的比如课程列表、课程详情有些是必须登录才能访问的比如收藏课程、提交评论、记录学习进度还有些是管理员才能操作的比如课程上下架、修改用户状态。所以我用 JWT 做登录态管理配合 SpringBoot 拦截器做权限控制整体流程是用户登录成功后后端生成一个 token 返回给前端前端把 token 存在本地存储里之后每发一个请求都在 header 里带上 token后端解析 token 拿到用户信息再判断是否有权限执行当前操作。JWT 的生成用 jjwt 库就行pom.xml 里引入依赖写一个 JwtUtil 工具类封装生成和解析的方法。token 里只放 userId 和 role 两个核心信息过期时间设置为 24 小时。要注意的是JWT 是存在客户端的后端在响应请求时如果需要拿到当前用户信息不能直接在拦截器里去查数据库每请求查一次库太重了而是在生成 token 时把 userId 放进去拦截器解析 token 后直接放到 request 的 attribute 里Controller 再取出来用。权限控制这块我在代码里用了一个比较轻量的方案定义一个 RequireRole(admin) 注解然后写一个拦截器读取注解值结合 token 里的 role 字段判断是否放行。这个方法虽然简陋但足够应付毕设场景。如果你想更简洁也可以直接在 Controller 方法里通过工具类拿到当前用户的角色自行判断。说实话在毕设里上 Spring Security 做全套 OAuth2 有点杀鸡用牛刀理解成本和配置成本都偏高而且答辩老师大概率会问你讲讲 Spring Security 的过滤器链这个坑一旦踩进去很容易被追问到细节卡壳。3.3 课程与互动的关键接口设计逻辑课程模块的接口相对简单课程列表接口支持分页、按分类过滤、按关键字搜索、按价格筛选课程详情接口返回课程基本信息、教师信息、章节列表视频地址同时要根据当前登录用户判断是否已收藏、是否已购买。这里的一个技巧是接口参数用一个查询对象承接而不是在接口签名里写一大堆 RequestParam否则传参和扩展都会很痛苦。互动模块的接口是这个项目的重头戏。提交评论接口要先校验用户是否登录再校验 parent_id 对应的评论是否存在最后写入评论表。评论列表接口要做成分页 树形结构返回。我在 Service 层先把这条课程的所有评论查出来冲内存里用 root_id 分组拼装成树再返回给前端。这个过程虽然听起来有点复杂但其实代码量并不多大概四五十行就能搞定。收藏接口就更简单了判断是否存在记录有就删除没有就插入对收藏状态做反操作即可。学习进度记录接口是扩展功能用户播放视频时前端定时调用这个接口上报进度后端把观看时长累加到 learn_record 表。后面查我的学习记录时把该用户的所有记录 join 课程表查出来展示成最近学习列表。这里要注意一个细节不要把用户每看 10 秒就上报一次的做法写进数据库一定要在 Service 层做一个时间差判断比如距离上次上报超过 30 秒才落库否则会产生大量无效写入。3.4 技术选型细节拦截器、MyBatis-Plus 分页、视频文件处理MyBatis-Plus 的分页插件的配置比较固定在配置类里加 MapperScan、注入 PaginationInnerInterceptor 即可。用的时候记住一个核心规则分页插件只对 Mapper 层的方法生效你只要在 Service 层把 Page 对象传进去插件会自动 LIMIT不要自己手写 LIMIT否则就会出现分页失效却查出了全表数据的诡异表现。视频播放这部分我是用 MinIO 做对象存储启动一个本地 MinIO 服务上传视频后拿到预签名 URL 或者公网 URL再把这个 URL 存储到数据库的 video_url 字段。前端用 H5 的 video 标签播放时直接指向这个 URL 就行不需要后端做转码、切片这些高难度操作。MinIO 的界面里可以手动上传视频也可以通过后端接口上传。这一点建议在毕设文档里写清楚因为媒体资源管理这个点本身就属于一个独立的子系统能体现你对文件处理的思考。4. Vue 前端实现页面拆分、组件复用的核心方法论前端部分我用的 Vue 2 加 Element UI如果你是新手这个组合的资料量最丰富遇到问题基本都能搜到答案。项目结构上views 目录放页面级组件components 目录放可复用的业务组件router 统一管理路由store 用 Vuex 管理全局状态。下面挑几个最有代表性的场景拆开讲。4.1 前端项目结构与路由设计我用 vue-cli 创建项目然后把前后端联调的配置收敛到一个文件里。具体做法是在根目录下建一个 .env.development 文件里面写 VUE_APP_BASE_URL http://localhost:8080然后在 axios 封装里统一引用这个变量。因为在线学习平台的接口都部署在本地 SpringBoot 上端口容易冲突时我会把前端代理也配起来通过 devServer 的 proxy 把 /api 开头的请求代理到 8080 端口这样跨域问题在开发期就解决了不需要在后端写一堆 CORS 配置。路由设计要分普通用户和管理员两套。普通用户的页面包括首页、课程列表页、课程详情页、个人中心页、登录注册页。管理员的页面包括课程管理、用户管理、评论管理、数据看板。我用嵌套路由实现后台管理布局统一一个侧边栏加顶栏的框架组件部分用 Element UI 的 Layout 布局组件整体开发速度会快很多。这里要特别说一下权限路由我用 Vuex 保存当前用户的 role然后在全局路由守卫里判断目标路由的 meta 是否要求 admin 权限不满足就强制跳转回首页。这个思路简单直接也和后端接口的权限校验形成双层保障。4.2 视频播放页的交互细节课程详情与播放器集成课程详情页是整个前端最核心的页面它要展示课程描述、教师信息、章节列表、评论区、收藏按钮、播放区域功能点非常密集。我在布局上分成左右两列左边是播放器加课程详情描述右边是章节列表加购买入口评论区放在最下方。这个布局逻辑符合学习网站的使用直觉用户在观看视频的同时可以在右侧快速切换章节。播放器我这里用了一个折中的方案直接用 HTML5 的 video 标签把后端返回的 video_url 赋值给 src。原因很简单如果是 MP4 格式的视频video 标签原生就能播放不需要额外引入 video.js 或者 plyr。但如果你用了 m3u8 这种流媒体格式那就需要引入 hls.js 库去把 m3u8 拉流播放。这里有一个很容易踩的坑很多学校机房或者老师提供的 demo 视频是 m3u8 格式的而你在本地测试时用的 mp4 能放换到学校演示机器上就黑屏了。所以我建议从项目开始就直接统一视频源格式要么全用 mp4要么全用 m3u8不要混着来。互动区域的设计上评论区我封装成了一个 CommentList 组件和 CommentForm 组件CommentList 负责渲染树形评论CommentForm 负责提交新评论和回复。注意前端渲染树形评论时如果层级太深会导致 DOM 嵌套过深页面卡顿所以在递归组件里要加一个最大层级限制比如最多支持两层楼中楼超过的评论就平铺显示。这个细节在真实项目里很常见也是答辩时你可以拿出来讲的亮点。4.3 Vuex 状态管理与 Axios 封装技巧Vuex 里我管理三个全局状态token、userInfo、isCollapse侧边栏折叠状态。token 和 userInfo 在用户登录成功后写入 store同时持久化到 localStorage页面刷新时再从 localStorage 里恢复相当于手动实现了一个简单的持久化。这里有个 Vuex 常见坑刷新页面会导致 Vuex 状态丢失如果你没有在 main.js 里先读 localStorage 再初始化 store就会出现登录成功一刷新就变成未登录的诡异问题。Axios 封装是整个前端工程最值得花时间的一部分。我在 request.js 里创建了一个 axios 实例设置 baseURL、超时时间然后加两个拦截器。请求拦截器负责从 store 里取 token放进 header 的 Authorization 字段。响应拦截器负责统一处理错误如果 code 是 401 就说明 token 失效清掉本地存储并跳转登录页如果 code 是 400 就弹提示框提醒用户检查输入如果网络出错则弹网络异常请稍后重试。把这些逻辑集中在一个文件里比你每个页面都写 try-catch 再根据状态码判断要优雅十倍。4.4 远程接口联调时最容易被忽略的细节前后端联调阶段最常见的问题是接口文档里写的是驼峰命名前端开发时却误写成下划线或者反过来。我在项目里约定后端返回的 JSON 字段一律用驼峰命名和 Java 的属性名保持一致前端也直接用这个字段名中间不做任何转换处理。这个约定能省掉大量无意义的联调时间。第二个常见问题是跨域。如果你用了 vue-cli 的 proxy 代理注意在 axios 里请求的 URL 必须不带完整域名直接写 /api/xxx 相对路径proxy 才会把请求转发到后端。如果你在 request.js 里把 baseURL 设置成了 http://localhost:8080/api那 proxy 反而不会生效因为 axios 直接把请求发到了后端绕过了前端代理服务器这个时候就不得不依赖后端的 CORS 配置。这个逻辑我在项目里绕了半天才彻底搞清楚写出来供大家参考。第三个问题是上传视频时的请求体类型。如果你用 FormData 上传文件不要手动设置 Content-Type 为 multipart/form-datalet 浏览器自动带上 boundary 参数否则后端解析不到文件内容直接报空指针。类似这种细节网上教程很少提到但实际开发中特别容易遇到。5. 接口文档编写与联调经验给前后端协同工作减少摩擦很多同学把接口文档当成项目做完之后补交的作业这是一个很大的误区。真正有开发经验的团队接口文档是写在后端开发之前或者开发同时的因为前端需要拿接口地址去 mock 数据、去写页面逻辑没有接口文档的前后端开发就是各写各的最后联调时面对一堆对不上的字段互相扯皮。5.1 接口文档应该包含的最小信息集我给这个项目写的接口文档每个接口都包含五个要素接口地址、请求方式、请求参数、返回结构、示例。请求参数要写明字段名、类型、是否必填、字段含义。返回结构要写清楚 Result 最外层字段的取值含义再列出 data 字段里面的结构。示例最好用真实的 JSON而不是占位符方便前端直接粘贴到代码里模拟测试。接口地址的前缀我统一用 /api比如 /api/course/list、/api/user/login、/api/comment/list。方法类型遵循 RESTful 风格查询用 GET新增用 POST修改用 PUT删除用 DELETE。这个约定不算严格标准但胜在清晰统一前端可以根据方法类型判断请求方式和语义程序员之间也能快速对齐。5.2 用 Swagger 自动生成还是手写 Markdown这个问题我犹豫过很久。Swagger 的优点是可以自动扫描 Controller 生成在线文档省事而且能在线调试。缺点是需要引入一堆依赖代码里要加大量注解而且生成的页面风格偏技术化。对于毕设项目来说我最后选择了手写 Markdown 文档原因有三点第一手写文档可以自己控制详略把容易出错的请求参数和返回结构讲清楚第二答辩时可以打印出来给老师看排版可控第三手写一遍接口文档相当于自己重新梳理了一遍接口设计很多问题就是在梳理过程中发现的。手写接口文档看起来费时间但实际上你的核心接口也就二三十个每个写一两页一周之内肯定完成。我在接口文档的最后加了一个全局错误码说明的章节把 200、400、401、403、500 分别代表什么含义列清楚这样前端在接到 401 时能明确知道是登录过期而不是瞎找后端要日志。5.3 联调前必做的三项检查清单开始联调之前我建议你先做一个自测清单在 Postman 里把所有接口按顺序跑一遍。第一项登录接口要能正常拿到 token携带 token 访问需要登录的接口能成功不带 token 或错 token 的状态码正确。第二项分页接口要确认页码从 1 开始返回体里的 total 字段是否和数据库中记录条数一致排序字段是否符合预期。第三项评论树形结构能不能正常拼装parent_id 是否存在逻辑错误导致死循环。这三项是我每次项目联调前必查的因为这三大类问题一旦联调时才发现前后端互相推诿的时间成本足以让你失眠。还有一个小技巧在前端控制台里打印每一次请求的完整请求头和响应体联调时信息量越大越高效。我在调试时习惯把 axios 拦截器写死一个 console.log把所有请求的 method、url、params、data 打出来响应回来后打状态、data。这样定位问题基本是秒级的不用在浏览器开发者工具的 Network 面板里翻来翻去。6. 部署演示与答辩准备从本地跑到老师面前只差这几步毕设项目做到能跑只是第一步。真正拉开差距的是能不能在老师面前稳定流畅地演示以及能不能把自己做的东西讲清楚。这部分的经验我觉得比写代码本身更值得分享。6.1 部署环境准备与启动顺序在线学习平台是前后端分离项目部署时要分别启动后端和前端。后端的 SpringBoot 项目用 mvn spring-boot:run 或者打 jar 包运行注意配置文件里的数据库地址、Redis 地址如果用的话、MinIO 地址都要改成部署机对应的环境。前端的 Vue 项目要看你要不要打生产包。如果只是本地演示npm run serve 就够了如果要部署到服务器就 npm run build 再扔到 Nginx 里。如果演示环境是一台全新的电脑检查三样东西JDK 版本是否匹配我用的 JDK 8、MySQL 是否启动并且导入过 SQL 脚本、Node 环境是否存在。在答辩机房里经常遇到机器上没有 Node 或者 JDK 版本不对导致项目起不来所以稳妥的做法是提前把后端打成 jar 包前端用 build 出来的 dist 目录配合 Nginx 静态服务这台机器上只需要装 JDK 和启动 MySQL这样演示时的环境依赖最少。启动顺序也有讲究。先启动 MySQL再把数据导入接着启动 MinIO如果视频是存在 MinIO再启动 SpringBoot 后端最后启动前端。后端启动时如果数据库没起来数据源初始化失败会直接起一个异常进程你看着是启动失败了其实只是依赖顺序问题。演示前我习惯把 MySQL、后端、前端全部手动起一遍再开浏览器从头到尾走流程确保不会临场翻车。6.2 答辩现场最容易拿分的知识点和追问应对答辩时老师最喜欢问的几个方向基本是固定的项目架构是什么你是怎么做权限控制的数据库为什么这么设计某个功能具体怎么实现的你在回答时要学会引导老师问你会的问题。比如你讲我用拦截器做了一套基于 JWT 的权限校验老师顺着问 JWT 的原理你如果能答出header.payload.signature 的结构签名是加密的payload 里有有效期这就很稳了如果你没准备老师往深了问很容易露怯。第二个高频追问是你遇到了哪些难点怎么解决的。这个问题每年都有人答不好开口就说都挺顺利的这是最差的回答。你应该准备两三个真实的坑比如我在项目里踩的评论树形拼接、BCrypt 加密后初始化数据、前端刷新 Token 丢失这三个。讲的时候要突出你从发现问题、定位问题到解决问题的完整链路老师想听的是你的排错思路而不是你用了多牛的技术。第三个高频追问是这个项目还有什么改进空间。老师不是真的让你现场改代码而是看你对项目有没有完整的认知。你可以从性能优化、功能扩展、安全加固三个角度各说一两点比如课程列表加缓存减少数据库压力、评论区加敏感词过滤、后台加数据统计图表。提前准备这些能展示出你的思考广度。6.3 演示流程的编排和技巧演示流程建议固定为一条主线注册新用户 → 浏览课程分类 → 查看课程详情 → 观看视频 → 留言互动 → 收藏课程 → 查看个人中心记录 → 退出登录 → 换管理员登录 → 进入后台管理 → 对课程/用户/评论进行管理操作。这条链路完整覆盖了系统所有核心功能而且剧情上也是自然的先以普通用户身份体验再以管理员身份验证管理能力。演示时一个很实用的技巧是提前准备好测试账号和固定的演示数据。不要现场注册新用户因为涉及密码校验、验证码等步骤一旦网络卡顿或者代码有边界问题会浪费大量时间。管理员账号 admin/123456、普通用户账号 player/123456 提前登录好演示时直接切换即可。视频文件确保播放流畅最好准备多个格式的视频源避免单一点播失败导致演示中断。7. 从毕设走向实战的扩展思路项目交上去、答辩通过这并不意味着代码只能封存。在线学习平台是一个可塑性很强的模板系统我在做完之后陆陆续续扩展过几个方向这里给大家提供一些参考。第一个方向是改造成知识付费或培训机构的官网。在现有课程管理基础上增加学习路线推荐、课程套餐、优惠券、订单支付的功能。订单表涉及的逻辑比较多但只要你把 course 表里的价格字段用好配合一个 order 表和 pay_log 表就能支撑起一个完整的付费流程。第二个方向是补上数据统计和大屏展示。后端通过定时任务把每日新增用户数、课程点击数、评论数聚合到一张统计表中前端用 ECharts 做图表看板这个功能很受老师欢迎因为能看到数据可视化的能力。第三个方向是往微信小程序端迁移。小程序端的核心页面跟 Vue 前端是类似的接口可以完全复用。用一个原生小程序项目或者 uni-app 项目把课程列表、课程详情、视频播放、评论互动重新实现一遍工作量可控但产出会显得相当丰富。我做这个项目最大的体会是毕设不是技术炫技场而是你对自己大学四年开发能力的一次综合检阅。选择一个稳妥的、生态完善的技术栈把核心功能的代码逻辑想清楚把数据库设计得规整把前后端协作的文档整理好就已经远超平均水平了。至于那些花里胡哨的分布式、微服务、容器编排在毕设这个场景里往往是双刃剑讲不清楚反而扣分。最后分享一个在实操中小技巧不管你最终选择了什么技术方案拿到任何源码项目第一步永远是先读 README第二步是跑起来第三步是照着接口文档把所有接口在 Postman 里通一遍之后再去看代码。顺序不能乱因为先理解系统的输入输出再深入内部实现你的认知效率会高很多。这套方法论也可以沿用到你以后的工作里任何陌生代码库到手都是这个流程。