ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SpringBoot+Vue+MySQL课表管理系统:设计与部署实战全解析

SpringBoot+Vue+MySQL课表管理系统:设计与部署实战全解析 每年毕设季后台问我要课表管理系统的人特别多。课表管理系统这个东西听起来是个老掉牙的CRUD但真正动手做的时候你就会发现排课逻辑、时间冲突、教室资源分配、前后端联调每一个环节都能把人折腾到怀疑人生。这次分享一套可直接运行的完整源码SpringBoot做后端、Vue做前端、MySQL存数据以西安工商学院的课表管理场景为原型功能上覆盖了课程管理、班级管理、教师管理、教室管理、课表查询和冲突检测这几个核心模块。不管你是准备交毕设的学生还是想快速上手全栈项目的开发者这篇文章都能让你少走不少弯路。我先说结论这套项目的代码风格偏工程化不是那种为了应付检查堆出来的玩具代码。后端用的是SpringBoot MyBatis Plus前端用的是Vue 2 Element UI数据库脚本和初始化数据都给你备好了理论上clone下来改改数据库密码就能跑。但“能跑”和“跑得顺”是两回事下文我会把项目的设计思路、每个模块的实现细节、启动步骤和常见坑全部拆开讲包括我在实际运行中踩过的那些文档里根本不会写的坑。1. 项目整体设计与技术选型拆解1.1 课表管理系统到底在解决什么问题先说业务。高校的课表管理远比想象中复杂。一个学期的课表涉及专业、年级、班级、课程、教师、教室、时间槽七要素的交叉匹配。同一时间同一个教室不能排两门课同一个老师同一时间不能出现在两个教室一个班也不能同时上两门课。人工排课靠Excel和记忆力在课程数量少的时候勉强能撑住一旦到了两百门课、几十个班级的规模冲突几乎是必然的。这套系统的核心价值就是把排课和查询这件事从“Excel手工维护”变成“系统化数据管理”。管理员在系统里录入课程、维护教师和班级信息然后通过课表管理模块把课程分配到具体的时间槽位上系统自动检测时间冲突和教室冲突学生和教师登录之后只能查看跟自己相关的课表。这个模型不算复杂但它是绝大多数高校教务系统的基础单元做好这一个其他管理系统的套路你也就摸清了。1.2 为什么是SpringBoot Vue MySQL这套组合很多同学会纠结技术选型问为什么不选SSH、不选Flask、不选微服务。我的观点很直接毕设和中小型项目SpringBoot Vue MySQL就是性价比最高的组合没有之一。SpringBoot的优势在于零XML配置和自动装配。传统SSH项目光写配置文件就能花掉一天时间SpringBoot通过starter机制把常用场景的依赖打包好引入即用。对于课表管理系统这种典型的CRUD 业务校验项目SpringBoot的开发效率是最高的。同时SpringBoot的生态太成熟了集成MyBatis、Redis、JWT、Swagger都有现成的starter社区资料多到查不完。Vue选择前后端分离架构主要考虑到两个场景课表的周视图和列表视图需要前端做灵活的交互切换而管理端的表单校验、弹窗提示用Vue Element UI写起来非常顺手。前后端分离之后后端只需要提供RESTful API前端通过axios调用开发时用Node代理解决跨域部署时后端打包成Jar包、前端构建成静态文件放在一起整个流程清晰且可控。MySQL就不多说了课表数据是典型的结构化关系数据课程、班级、教师、教室、时间槽之间存在明确的外键关联用关系型数据库表达最自然。MySQL 5.7以上版本对JSON类型的支持也很好如果后续想扩展课表的自定义属性也有空间。选这套组合还有一个现实原因市面上关于这仨的资料和解决方案覆盖非常全你遇到任何问题基本都能在网上找到对应的答案。做项目最怕的不是技术难而是踩了坑没人告诉你坑在哪。1.3 拿到源码之后先从哪个文件开始看我必须给第一次接触全栈项目的同学一条阅读路线。不要一上来就打开application.yml开始改配置也不要直接npm run dev那样你只会收获一堆报错。建议按照这个顺序阅读先打开数据库脚本看表结构搞明白课表数据是怎么组织的这是整个系统最核心的部分。然后打开后端项目从实体类看起对照数据库表结构理解字段映射关系。接着看Controller层了解系统对外暴露了哪些接口。再接着看Service层理解排课冲突检测这类核心业务逻辑是怎么实现的。最后再打开前端从router看起搞清楚页面路由和接口的对应关系。按这条路线走一遍你基本就能看懂整个项目了。2. 功能模块与数据库设计的核心逻辑2.1 三种角色各取所需系统的用户角色分为管理员、教师、学生三类对应的是三种完全不同的使用场景。管理员负责基础数据维护和排课管理。教师基础信息的管理、班级的增删改查、课程的创建、教室资源的维护这些基础数据全部由管理员录入。排课管理是管理端的核心操作管理员选择学期、选择班级、选择课程、指定教师、指定教室、选择时间槽系统在保存前自动做冲突检测。教师端的功能相对简单登录后可以查看自己的代课课表按周次浏览每天的上课时间和地点。部分学校有调课申请的需求这套系统的教师端也预留了申请调课的入口后端有对应的接口前端页面可以直接对接。学生端就是纯粹的课表查询选完班级后系统按周展示这个班的全部课程安排。这里要注意一个业务细节一个学生属于哪个班级决定了学生端看到什么课表一个课程安排绑定的是班级而不是单个学生所以学生端不需要维护个人的课程订阅关系逻辑上简单很多。2.2 核心功能模块一览从功能清单上看这套系统的模块划分是标准的MVC思路。课程管理模块负责课程信息的增删改查字段包括课程名称、课程编号、学分、课时、课程类型。课程是课表系统的基础实体课程信息一旦发生变化已经排好的课表可能全部要跟着调整所以在设计上课程表的数据要保证稳定性修改课程编号这种操作应该禁掉。班级管理模块维护专业、年级、班级名称等信息。班级在整个课表体系里是一个关键的“聚合单位”课表本质上就是班级 × 周次 × 星期 × 节次 的矩阵。教师管理和教室管理比较好理解教师表主要存姓名、工号、职称、所属学院教室表存教室编号、容纳人数、所在校区、教室类型普通教室/机房/多媒体教室。课表管理模块是整个系统的核心。管理员选择班级后系统按周展示这个班的课表空白槽位可以点击添加课程安排。保存时后端做逻辑校验检查教师在同一时间是否有其他课程安排检查教室在同一时间是否被其他班级占用。校验通过才允许写入数据库。查询模块提供多维度检索能力。学生登录查自己的班级课表教师登录查自己的代课课表管理员可以按班级、按教师、按教室三个维度查看课表占用情况。2.3 数据库表设计的关键细节很多初学者在做表设计的时候容易犯一个错误把所有信息塞在一张巨大的表里。这套系统用了细分表的方式核心表总共有八张用户表、教师表、学生表、班级表、课程表、教室表、学期表、课表记录表。课表记录表schedule是整张数据关系网的枢纽我单独说一下。schedule表的核心字段包括id、class_id关联班级、course_id关联课程、teacher_id关联教师、classroom_id关联教室、semester_id关联学期、week_day星期几1-7、start_section开始节次、end_section结束节次、week_start开始周次、week_end结束周次、week_interval周间隔默认1表示每周都有。这个设计的精妙之处在于用week_start和week_end描述课程的“周次范围”。比如一门课从第1周到第16周每周四上午3-4节上课那么week_start1week_end16week_interval1。如果一门课隔周上把week_interval改成2就可以了。这种设计比直接用“周次字符串”或者逐周拆成多条记录要灵活得多排课查询的时候通过时间范围判断就能快速过滤。还有一个设计细节值得提week_day、start_section、end_section 这三列尽量用int类型不要用varchar。一方面是为了查询效率更重要的是后端做冲突检测的时候可以直接用数值比较避免字符串解析的麻烦。数据库字符集一定要用utf8mb4不要用utf8。utf8mb4是utf8的超集能存储emoji和生僻字MySQL 8.0默认就是这个。如果你用的MySQL 5.7建库的时候手动指定一下DEFAULT CHARACTER SET utf8mb4。这一步看似无所谓真到了课程名称里出现生僻字导致页面乱码的时候你就知道什么叫欲哭无泪了。另外所有表都要加上create_time和update_time字段MyBatis Plus的自动填充功能可以直接用后续排查数据问题的时候这两个字段能帮你定位很多麻烦。3. 从零到一运行项目环境配置与实操细节3.1 版本选型别让环境坑了你这个项目能“直接运行”是有前提的就是版本别搞错。我把经过验证的版本组合放在下面这张表里照着配基本不会出问题。组件推荐版本注意事项JDK1.8 或 11SpringBoot 2.x 不建议用JDK 17会有兼容性问题Maven3.6.3配置阿里云镜像否则依赖下载慢到怀疑人生SpringBoot2.3.x - 2.7.x不要用3.x依赖和用法有较大变化MySQL5.7 或 8.08.0要注意驱动版本和时区配置Node.js14.x - 16.xVue CLI 4.x 在Node 18上会有OpenSSL报错Vue CLI4.x不要用5.x4.x生态最稳定特别注意两个点。第一SpringBoot 2.7.x搭配MyBatis Plus 3.5.x是我测试过最稳的组合你如果非要追求最新版SpringBoot 3.x会发现很多starter的坐标都变了网上查到的资料大多不适用。第二前端用的Vue CLI 4.x在Node 16环境下跑得很顺畅但如果你电脑装的是Node 18或20启动开发服务器的时候大概率会报ERR_OSSL_EVP_UNSUPPORTED。解决办法是在package.json的scripts里加上dev: NODE_OPTIONS--openssl-legacy-provider vue-cli-service serve不过这个变量只在Node 17才有意义。3.2 数据库初始化的三个步骤第一步创建数据库。打开MySQL命令行或者Navicat执行数据库脚本。这套源码里带了两个SQL文件一个建表、一个初始化数据。建议先执行建表脚本再执行初始数据脚本顺序不要搞反。这里有个容易忽略的操作如果MySQL是8.0版本建完库之后记得检查一下默认字符集。有时候客户端连接设置的字符集和数据库实际字符集不一致中文字段写入数据库会变成乱码。稳妥的做法是在连接参数里加上characterEncodingutf8mb4JDBC连接串里用serverTimezoneAsia/Shanghai指定时区这个参数不写连8.0的数据库会直接报时区相关的异常。初始化数据脚本里预置了一个admin账号密码是加密存储的。很多同学拿到手发现数据库里存的是一串密文不知道怎么登录。这里说明一下这套源码的密码加密用的是BCrypt你可以直接拿源码里PasswordEncoder生成的新密文替换也可以保留初始密文对应的明文密码在项目文档里一般会注明。如果文档里没写最省事的方法是在后端启动时加一段临时代码用PasswordEncoder生成一条新密文再写进数据库搞完再删掉这段代码。3.3 后端启动改三个地方就能跑后端项目的配置集中在src/main/resources/application.yml这个文件里。你需要修改的无非三处。第一处是数据源配置。把url改成你的数据库地址用户名和密码改成你自己的。url格式是jdbc:mysql://localhost:3306/课表数据库名?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai。注意mysql驱动版本如果用的是8.xdriverClassName要写成com.mysql.cj.jdbc.Driver写成com.mysql.jdbc.Driver会直接报ClassNotFoundException。第二处是MyBatis Plus的配置。主要检查mapper-locations路径默认是classpath*:mapper/*.xml如果你的SQL文件放在resources目录下的mapper文件夹里就不用改。如果改了路径记得把XML文件放到对应位置。第三处是端口配置。server.port默认是8080如果本机端口被占用改成一个不冲突的端口就行。前端代码里如果写死了后端地址这一步的改动会导致接口调用失败要注意联动修改。改完这三处运行SpringBoot主类控制台出现Spring的Banner和“Started xxxApplication in x.xxx seconds”就说明后端起来了。启动过程中如果看到“Failed to configure a DataSource”的报错不用慌99%是数据源配置有问题去检查数据库密码和URL。3.4 前端启动npm install是第一个拦路虎前端项目启动的正确姿势分两步。第一步安装依赖。npm install这个命令对网络环境极其敏感国内环境建议先配置npm镜像源。在终端执行npm config set registry https://registry.npmmirror.com再执行npm install速度会快很多。安装过程中如果报permissions相关的错误不要用sudo硬怼大概率是node_modules目录权限问题删掉node_modules重新安装一次往往就好了。第二步启动开发服务器。运行npm run serve默认端口是8080如果和后端冲突Vue CLI会提示你换端口。这里有个前后端联调的经典问题前端开发服务器跑在8080后端跑在8080端口冲突了怎么处理最优雅的方案不是硬改后端端口而是让前端跑另一个端口比如8081然后通过vue.config.js里的devServer.proxy配置把前端对/api的请求转发到后端的真实地址。这样前端代码里所有请求都写成相对路径联调的时候不用改代码部署的时候也不用改代码。3.5 前端配置代理的完整写法在vue.config.js里这样配置module.exports { devServer: { port: 8081, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/api: } } } } }这段配置的意思是浏览器发起的所有以/api开头的请求都会被开发服务器转发到http://localhost:8080并且把URL里的/api前缀去掉。比如前端请求/api/course/list后端实际收到的请求是/course/list。如果你的后端Controller类上没加/api前缀这种写法正好匹配。这里有个细节要提醒后端接口的路径设计要么统一带/api前缀要么统一不带不要混着来。混着来会导致代理配置和路径重写永远对不上排查起来非常痛苦。前端项目用的是Vue Router路由模式建议保留hash模式默认就是不要轻易改成history模式。改history模式不仅需要后端做路径重定向配置部署到Linux服务器上的时候还要处理Nginx的try_files参数不是不行是麻烦。课表管理系统没有那么严格的URL美观需求hash模式完全够用。4. 前端实现的关键环节从路由到组件4.1 路由设计思路前端路由一共分三层登录页、管理端主布局、功能页面。第一层是/login未登录用户访问任何页面都会被路由守卫拦截并重定向到登录页。登录成功之后会从后端拿到token前端把token存到localStorage写进axios的请求拦截器。这个逻辑是用Vue生态混得久的人都懂的标准套路。第二层是管理端主布局也就是layout。主布局是一个左侧菜单栏加右侧内容区的结构菜单项按管理员、教师、学生三种角色动态渲染。这里就涉及动态路由的概念不同角色登录之后能看到的菜单不同路由表也是登录之后根据角色信息动态添加的。这套源码用了一个简单高效的办法——在router.beforeEach守卫里判断用户角色根据角色去router.addRoutes动态挂载不同权限的路由表。第三层是具体业务页面。课程管理、班级管理、教师管理、教室管理、课表管理、课表查询每个页面都是一个独立组件。页面之间的切换用的是Vue Router的懒加载import语句用函数返回组件代码分包加载首屏不会慢。4.2 课表周视图的表格渲染套路课表管理页面是整套系统前端部分最“有技术含量”的页面。它的核心结构是行表示星期一到星期日列表示节次每个单元格是一个可点击的槽位。前端实现上用Element UI的el-table或者手写一层grid布局都可以。这套源码用的是el-table把表格的行数据定义成一个二维数组一维是节次二维是星期。每个单元格的数据结构是{ courseName: 高等数学, teacherName: 张老师, classroomName: A101, weekRange: 1-16周, color: #409EFF }如果这个时间槽已经排了课单元格里就显示课程信息卡片如果没排课显示加号按钮点击弹出排课表单。这里的要点是处理单元格的合并和跨行展示一门课占了第3-4节视觉上要合并两个单元格。el-table的span-method属性提供了单元格合并的回调返回值是个数组[rowspan, colspan]按这个逻辑计算即可。课程颜色是另一个容易忽略的细节。不同课程给不同颜色前端做一个映射表根据课程ID取模映射颜色这样同一个课程在不同周次、不同班级显示的颜色是一致的视觉上找起来非常方便。纯前端计算颜色的好处是不用后端加字段逻辑上也不复杂。4.3 Vue的组件通信方式和插槽使用项目里组件通信用得很常规父组件往子组件传数据用props子组件往父组件发消息用$emit。排课弹窗组件数据的输入输出就是这么一个闭环课表页面是父组件点某个空槽位把当前班级ID、星期、节次传给弹窗子组件子组件里选完课程、教师、教室后把新排好的课表数据emit回去父组件更新页面数据再调用后端接口做保存。这个交互流程里的插槽用得比较浅主要是布局层面的插槽。Element UI的表格列、弹窗的footer区域都是默认支持的插槽用法。如果你要扩展功能比如在课程卡片上加一个“调课”按钮直接在课表单元格组件里加一个具名插槽外部通过template填充按钮内容就行。Vue的插槽机制本质上就是“占位 内容分发”课表卡片这种高频变化的区域最适合用插槽做扩展。4.4 axios封装和登录状态管理axios的封装决定了整个前端代码的规范程度。源码里把axios实例单独抽了一个文件配置了baseURL、请求超时时间、请求拦截器、响应拦截器。请求拦截器做一件事从localStorage拿token加上Authorization头。响应拦截器做两件事如果状态码是401说明token失效清除本地登录状态跳转登录页如果状态码是200且业务码非0弹出Element UI的Message提示错误信息。登录状态管理没有用Vuex做持久化而是直接存在localStorage刷新页面后通过router.beforeEach检查本地有没有token。这个方案对于课表管理系统这种对权限要求不极端的场景完全够用也简化了状态管理的复杂度。如果你以后要扩展更多动态权限再把Vuex或者Pinia引入也不迟。5. 联调、打包与部署从开发环境到生产环境5.1 前后端联调的标准流程项目开发完前后端联调是必经之路。联调不是一个动作而是一套流程。先确认后端接口文档。源码里如果集成了Swagger启动后访问/swagger-ui.html就能看到所有接口的说明和参数。没有Swagger的话直接打开后端的Controller源码看方法上的RequestMapping注解。建议联调之前先用Postman把每个接口测一遍确认数据返回格式正常再去前端页面里点按钮调接口这样能把问题定位在前端还是后端不用两头Debug。然后是数据格式的对接。后端统一返回结果是{code: 200, message: success, data: {...}}这种格式。如果后端返回的data结构是List前端就不要按Object去取如果后端日期字段是时间戳前端展示层要转换格式。这类问题在联调阶段出现频率最高解决办法就是前后端约定统一的JSON结构而这套源码已经在公共返回类里把这些都封装好了直接用即可。最后处理跨域问题。开发环境通过webpack的proxy解决跨域已经说过了生产环境前后端部署在同一域名下就不存在跨域了。如果生产环境仍然需要前后端分离部署在不同域名后端要额外配置CorsFilter否则浏览器会拦截非同源的响应。5.2 前端打包产物怎么放进SpringBoot这是很多同学都不太清楚的一个环节同时也是部署的关键一步。前端npm run build完成之后dist目录里会生成index.html和一堆js/css静态资源。SpringBoot的静态资源目录默认包含src/main/resources/static。把dist目录里的所有内容拷贝到static目录下然后启动SpringBoot的Jar包直接访问http://IP:端口/就能看到页面。这个方案相当于用SpringBoot托管前端静态资源一个Jar包搞定前后端所有内容。部署到服务器上只需要装一个JDK和MySQL连Nginx都不用装。这里有个路由相关的坑必须提醒如果你在开发环境用的是history模式做上面的合并操作后直接访问根路径没问题但刷新一个深层路径比如访问/course管理页刷新后端没有对应的路由映射会返回404。解决办法有三条一是改回hash模式二是在后端写一个route转发Controller把所有非API的请求转发到index.html三是用Nginx配置try_files。最省事的是第一种所以我前面反复强调hash模式。5.3 Linux服务器部署实操记录把项目部署到Linux服务器核心步骤就五步安装JDK、安装MySQL、导入SQL脚本、上传Jar包、启动。JDK安装用yum或者apt就行版本一定和本地开发保持一致。MySQL安装之后记得把root密码确认好用Navicat远程连接前要开3306端口还得给root账号授权远程访问。生产环境要用root远程连接一般是为了图方便但你最好建一个专用账号只授权本项目库的权限安全性能好一些。启动命令稍微讲讲。常规做法是nohup java -jar xxx.jar logs.log 21 这样关闭终端后服务依然在运行。查看日志用tail -f logs.log动态观察启动过程。如果启动失败翻日志看异常信息是最快的排查手段。数据库连不上就去查网络和密码端口被占就杀掉占用的进程。内存方面SpringBoot默认的JVM堆内存是物理内存的1/4一台2G内存的小服务器跑一个课表系统绰绰有余不需要额外调优。如果你发现启动特别慢可以在启动命令里加-Xms512m -Xmx512m强制指定初始和最大堆内存减少动态扩容的次数。6. 排课冲突检测的算法思路和业务实现6.1 冲突检测的本质是维度交叉判断排课功能是本系统的核心业务点但我发现很多拿到源码的同学并没有真正读懂冲突检测这段代码。我从实现层面拆开讲一下。冲突检测的本质是在课程安排保存之前检查拟新增的时间槽是否和已有安排发生重叠。三个关键维度时间维度学期、周次、星期、节次、资源维度教室、人员维度教师、班级。时间维度的重叠要同时满足四个条件才叫重叠同一学期、周次范围有交集、星期相同、节次范围有交集。听起来很绕实际判断代码核心就是区间重叠判断。两个区间[a, b]和[c, d]有交集的充要条件是a d 且 c b。比如已有课程占第1到16周新课程拟排第8到10周条件a d1 10且c b8 16成立时间上就重叠了。同理节次区间[1, 2]和[2, 2]也有交集因为2 2且2 2。教室维度的冲突就更好理解了同一时间同一教室不能分配两个班级。查数据库时按教室ID 时间条件去比对查到了就说明冲突。人员维度的冲突逻辑同理。6.2 一个完整的保存校验流程后端Service层的保存方法执行的校验步骤是这样的第一步查班级时间冲突。以class_id semester_id为条件查出这个班级已有的全部课程安排逐个比对时间和节次是否有交集有交集直接返回“该班级在所选时间段已有课程”。第二步查教师时间冲突。同样逻辑换成teacher_id去查有交集返回“该教师在所选时间段已有教学安排”。第三步查教室时间冲突。以classroom_id 时间段为条件查询有交集返回“该教室在所选时间段已被占用”。这里还要注意一个细节修改课程安排编辑排课记录的时候校验要排除自身。因为编辑的时候当前这条记录本身就存在数据库里如果不排除自己系统会把这次修改误判成和自身冲突。很多同学第一次写这个逻辑都会漏掉源码里用了一个id ! currentId的条件把这个问题处理掉了。排课业务还有周次间隔的判定。week_interval是2表示隔周上课判断某周是否有课时用weekNumber % week_interval等于0来判定。注意周次的起始点从week_start算起不要从第1周全量算不然隔周课的对错完全反过来。6.3 前端周次选择器的联动处理前端排课表单里选择周次范围是一个联动逻辑。点开周次选择器显示1到20周多选。比如选了第1周、第3周、第5周后端要怎么理解前端先把选择的周数组排序判断是否为连续区间把连续的部分合并成一个区间比如[1,3,5]变成[1,1]、[3,3]、[5,5]存在week_start和week_end里week_interval设为1。这种情况课程每周都有课周间隔性不存在。如果用户选了1,3,5,7,9间隔是2把它合并成start1、end9、interval2一条数据量少而且查询效率高。这个合并逻辑放在前端做还是后端做都行。源码放在前端处理因为Element UI的表单组件直接操作的是数组处理成区间之后再传给后端后端落库的字段结构非常规范。7. 常见问题与排查技巧实录7.1 后端启动失败的典型场景我把实际运行这套源码时最容易翻车的场景罗列一下你可以直接对照排查。报错信息原因解决方案Failed to configure a DataSource数据源配置错误或数据库没启动检查application.yml的url、用户名、密码Access denied for user rootlocalhost数据库账号密码不对用Navicat确认本地MySQL密码Unknown database xxx数据库名写错或没创建库执行CREATE DATABASE语句Port 8080 was already in use端口被占用换端口或者杀掉占用进程ClassNotFoundException: com.mysql.cj.jdbc.DriverMySQL驱动版本和连接串不匹配更新驱动依赖版本并修改driverClassNameAllowPublicKeyRetrievaltrue neededMySQL 8.0 的caching_sha2_password认证问题在连接串加allowPublicKeyRetrievaltrue这里我多说一个很多人都会踩的坑MySQL 8.0默认的认证插件是caching_sha2_password老版本的JDBC驱动不识别这种认证方式会报Public Key Retrieval is not allowed。解决方案是在JDBC连接串末尾加上allowPublicKeyRetrievaltrueuseSSLfalse同时把mysql-connector-java的版本更新到8.0.33以上这个版本对8.0数据库的兼容性最好。7.2 前端run dev之后白屏或报错前端启动过程中遇到的坑比后端多我这里挑典型的说。npm install慢或者卡住不动解决办法前面说了换镜像源但还有个小技巧如果换源之后还是慢检查一下npm config get registry生效没有。有时候你在项目的.npmrc文件里写了一个registry和全局配置冲突实际走的还是旧地址。另一个高频问题是BrowserRouter导致的刷新404我前面已经给过解决方案改hash模式。还有一类问题比较隐蔽Vue打包之后接口请求404。开发环境走代理一切正常打包部署之后页面能打开但接口全部404。原因很可能是后端接口的context-path配置不对或者前端请求的baseURL写的是开发环境的代理地址打包后依然请求localhost。排查思路很简单打开浏览器的Network面板看看实际请求的URL是什么跟后端的接口路径对比就知道是哪一层出了问题。7.3 业务数据异常的处理经验数据这一层的问题往往比环境问题更让人头疼。课表显示错位是最常见的数据问题。比如某门课显示在星期三但数据库里存的week_day是3页面上却跑到星期四去了。这种问题十有八九是前后端对“星期几”的约定不一致。后端约定周一对应1但前端用Date对象的getDay()获取周几得到的值是0到60表示周日。两个体系对不上数据就错位了。解决办法是以数据库字段的int值作为唯一标准前端展示前统一做一次转换。另一个问题是班级和课程调换导致的历史数据残留。比如一门课程被删除了但课表记录表里还有它的外键指向查询的时候如果直接做JOIN会出现查不到课程名的情况。处理办法是课表记录表的外键字段不要加物理外键约束逻辑外键即可删除课程时先清掉对应的课表记录或者在查询时做null判断兜底。还有一个数据库性能方面的问题。课表记录表的数据量不会特别大但在做冲突检测时会频繁按班级、教师、教室维度查询建议在schedule表上建三组联合索引(semester_id, class_id)、(semester_id, teacher_id)、(semester_id, classroom_id, week_day)。索引不是越多越好针对查询频率最高的三个维度建索引性能就完全够用了。8. 这套源码的扩展方向和使用建议8.1 代码层面的优化点如果你打算在这个项目基础上继续做我建议先做三件事。第一件事是把后端返回的日期格式统一。现在的实现是LocalDateTime直接序列化前端拿到的格式是带T的ISO格式建议在application.yml里配置spring.jackson.date-format输出成年月日 时分秒的格式前端展示会友好很多。第二件事是把接口返回类做成泛型统一ResponseResult 避免每个Controller都返回Map。第三件事是在Swagger配置里把API文档完善一下这个工作在一个项目初期做收益最高中期补文档的效率远低于边写边注释。8.2 功能层面的扩展思路课表管理系统后续做功能扩展的空间很大。比较实用的方向有这么几个第一个是学生和教师的导出功能。把课表导出成PDF或者Excel图片是老师和学生都高频使用的功能。后端用POI或者EasyExcel生成Excel文件前端放一个导出按钮需求明确技术也不难。第二个是公告消息模块管理员发布调课通知前端页面提示。第三个是智能排课算法这个方向比较进阶把排课问题建模成约束满足问题用遗传算法去搜索合法的排课方案作为毕设的亮点来写非常加分。第四个是登录增加验证码和操作日志完善一下系统审计能力。8.3 给拿着源码做毕设的同学几点提醒最后以我的个人经验说几句掏心窝的话。这年头拿到一套可以直接运行的源码并不难难的是你能不能把它讲清楚、改明白。答辩的时候老师最常问的三个问题你为什么选择这个技术栈课表冲突是怎么检测的你在这个项目里独立完成了哪些部分如果你只是把项目跑起来连课表冲突检测的代码在哪个文件里都说不出来那答辩基本就是灾难。建议你拿到源码之后至少把课表冲突检测的Server实现类完整读一遍把MyBatis Plus的查询逻辑搞明白能自己画一个系统的架构图。在此基础上哪怕你只是加了一个Excel导出功能或者完善了调课申请模块答辩的时候你都多了一个可以主动展示的亮点。不要做“只跑通不改一行代码”的人那样对不起你这几个月的付出。这套项目后续怎么用还是看你的目标。想快点交差就按部署流程跑通改数据库里的学校名和初始化数据想认真学全栈就按我给的阅读路线一行行过代码把每个Controller、Service、Mapper的角色弄清楚。我自己的习惯是拿到任何一套新代码第一时间不是急着运行而是先把数据库表结构和接口文档通读一遍脑子里有了地图后面不管改代码还是排错都会顺很多。希望这套课表管理系统能成为你全栈路上的第一块完整的台阶。
返回列表