先说实话,这种“高校毕业与学位资格审核系统”在每年的毕设季几乎扎堆出现。你随便一搜就能看到各种版本,但真正能改明白、跑起来、答辩时讲清楚逻辑的,并不多。这套源码我在本地完整跑过一遍,后端用的是SpringBoot,前端是Vue,数据库用的MySQL。你拿到手之后第一件事不是急着解压,而是先把系统的核心逻辑拆清楚——毕业资格审核和学位资格审核到底审的是什么,状态是怎么流转的,角色权限是怎么控制操作的。这些东西理清了,后面的部署、改bug、二次开发,甚至答辩演示,都会顺很多。
这篇文章我按“先看懂设计 → 再折腾技术 → 最后排查问题”的顺序来写。前面几节偏原理和建模,中间是实打实的运行步骤,后面是我跑这套源码时踩过的坑和解决办法。不管你是拿去做毕设、课程设计,还是单纯想学一下前后端分离的系统怎么搭,这篇都能帮你少走不少弯路。
1. 项目整体设计与核心逻辑拆解
1.1 这套系统到底解决了什么问题
高校里每年最头疼的行政工作之一,就是毕业资格和学位资格的审核。学生能不能毕业、能不能拿学位证,不是看单一门课过了没有,而是要综合查考勤、学分、必修课、选修课、毕业论文、处分记录等多维数据。以前很多学校靠人工核对Excel,一个几百人的专业,教务员要对着十几个表格来回比对,漏一个学分、错一个学分绩点,都会直接影响学生的毕业。这套系统的核心价值,就是把“人肉比对”变成“系统自动核对+分角色审批”的线上流程。
它不是简单的增删改查信息管理,而是一个带业务规则的审核流系统。学生提交毕业申请后,系统会自动依据预设的毕业条件(比如必修课是否全过、总学分是否达标、毕业论文是否通过)做第一轮校验,校验结果再推给辅导员、教务秘书、院系负责人逐级审核。每级审核有退回、通过、驳回三种操作,操作记录全部留痕,谁在什么时候审的、改了什么,都能追溯。
这里有个很关键的设计点:初审(资格校验)是系统做的,终审(人工判断)是人做的。系统先把明显不符合条件的学生筛掉,剩下边缘情况的交给人工,比如某学生差0.5个选修学分但论文很优秀,这种情况适合人工介入。这种“机器预审+人工终审”的混合流程,比纯自动或纯人工都合理。
1.2 毕业资格与学位资格的关系和区别
很多初次接触这个项目的人会把“毕业审核”和“学位审核”混为一谈,其实在高校教学管理里,这是两套并行但既关联又独立的流程。毕业资格解决的是“你能不能完成本科学业”,核心看培养方案里的学分要求、必修课成绩、毕业论文(设计)、毕业实习是否完成。学位资格解决的是“你能不能获得学士学位”,除了毕业资格里的基础条件,还看平均学分绩点是否达到学校定的线(一般2.0左右)、有没有受过记过以上处分且未解除、毕业论文查重和答辩成绩是否达标。
在实际业务里,学生可能“能毕业但不能拿学位”,比如绩点不够、违纪记录未消。也可能“能拿学位但不能毕业”,这个少见但存在,比如论文答辩没过但课程都修完。这套系统在表设计和代码实现中,是把毕业审核表、学位审核表分开建的,两条流程独立跑、独立审批,但底层共用学生基础信息和课程成绩数据。这个设计我当时第一眼看觉得啰嗦,后来想明白是刻意为之:因为两条流程的审核时间、审核人、审批逻辑都不完全一样,硬合在一张表里,状态机根本没法写。
1.3 角色权限模型
系统内置了五种角色:学生、辅导员、教务秘书、院系负责人、系统管理员(校级教务)。这和真实高校的审核链条是咬合的:
| 角色 | 核心操作 | 可见数据范围 |
|---|---|---|
| 学生 | 提交申请、查看进度、撤回申请、查看结果 | 仅自己的数据 |
| 辅导员 | 初审确认、退回补材料、导出所带班级名单 | 本班级/本年级学生 |
| 教务秘书 | 资格复核、成绩核对、条件修改、批量导入成绩 | 本院系学生 |
| 院系负责人 | 终审签字、抽查审核记录 | 本院系全量 |
| 系统管理员 | 用户管理、院系专业配置、毕业条件参数设置、日志查看 | 全量 |
这个角色权限模型本质上是在拷“最小权限原则”:每个角色能操作的数据范围被严格限制。代码里用的是Spring Security做了认证(登录、Token签发),再配合自定义权限注解做接口级授权。比如/audit/confirm这个接口只允许ROLE_COUNSELOR访问,学生账号哪怕手动构造请求,也会被拦截器拦下来。这套权限控制的思路,在答辩时是一个很拿得出手的技术亮点。
2. 技术选型解析:为什么是SpringBoot + Vue + MySQL
2.1 后端框架:SpringBoot的技术红利
这个项目选SpringBoot,是典型的“带着镣铐跳舞但跳得舒服”的选择。SpringBoot最大的价值不是新,而是把Spring生态的配置复杂度藏起来了。内置Tomcat、自动装配、无需手写一堆XML配置,这对课程设计和毕设来说非常友好。但注意,SpringBoot本身不提供业务能力,真正的发力点在于它的生态插件:MyBatis-Plus操作数据库,Spring Security做认证授权,Lombok消除样板代码,这些才是让开发效率起飞的东西。
我实测跑这套源码的时候,发现它在配置文件里预置了一套很实用的设置:分页插件、逻辑删除字段(deleted标志位代替物理删除)、统一异常处理(@RestControllerAdvice)。这三个配置看着不起眼,但在实际开发中能躲掉很多坑。逻辑删除尤其重要,学位审核数据被删了还能查回来,这对教务系统这种要留痕的场景是刚需。
2.2 前端框架:Vue + Element UI的组合打法
前端选Vue,而且用的是Vue 2 + Element UI,这是当前毕设项目最成熟的组合(Vue 3 + Element Plus虽然新款,但很多老项目的组件和教学资源还是Vue 2的)。Element UI提供了一套开箱即用的后台管理界面组件,表格、表单、弹窗、分页、步骤条都有,做后台管理系统几乎不用改样式,直接拼装就能用。
我看这套前端的源码,整体是标准的前后端分离结构:api目录下按模块拆分的接口请求方法,router里配置了根据角色动态生成的路由表,store里用Vuex管理用户登录态和权限信息。页面组件主要围绕审核流展开,学生端有申请页、进度页,管理端有审核列表、审核详情、批次审批。这里有个值得学习的点:前端通过路由守卫(beforeEach)拦截未登录用户,再通过动态路由渲染不同角色能看到的菜单,不是把菜单写死。这样加一个新的审核角色,前端只需在路由表里加一段配置,不用改所有页面。
2.3 数据库选型:MySQL为什么够用
选MySQL而不是Oracle或PostgreSQL,核心考量是“匹配场景”。这套系统的数据量级,撑死几千个学生、几万条成绩记录,MySQL单库单表跑这种负载绰绰有余。更重要的是,MySQL上手成本极低,文档多、问题答案多,毕设和课程设计选它不会卡在环境上。
但“够用”不等于“乱建表”。这套系统的表设计是有讲究的,核心表包括:学生基本信息表、用户表(登录账号)、专业表、院系表、培养方案表、课程表、学生成绩表、毕业审核主表、学位审核主表、审核记录表、毕业条件参数表。表与表之间的关系,典型的是student_id字段一串到底,用逻辑外键关联而不是物理外键(物理外键在管理类系统里维护成本高,迁移数据容易出问题),这一点在后端代码中体现得很明显,查询全靠手动join或MyBatis-Plus的Wrapper拼接。
2.4 前后端分离的联调思路
前后端分离的项目,最常见的“桥”就是RESTful接口。这套系统的接口设计遵循了REST风格,资源用名词,操作用HTTP方法。比如获取学生列表是GET /api/student,提交毕业申请是POST /api/graduate/apply,审核操作是PUT /api/graduate/audit。状态码也有含义:200成功、401未登录、403无权限、500服务端异常。我建议你在跑这套系统之前,先用浏览器F12或者Postman把接口请求流程走一遍,理解前端哪一步调了哪个接口、传了什么参数、后端返回什么数据。这一步打通了,后面看代码会清晰很多。
前后端的另一个联调难点是跨域(CORS)。前端跑在http://localhost:8081,后端跑在http://localhost:8080,两边端口不同,浏览器默认拦截跨域请求。这套源码在后端写了一个全局CORS配置类,放行了前端的来源地址。这里有个实战小提醒:allowedOrigins尽量写具体域名,别图省事写*,不然安全性会打折扣。
3. 核心设计详解:审核状态机与数据库建模
3.1 审核状态流转:整张系统的“心脏”
你要想把这套系统讲明白,必须先吃透审核状态的流转逻辑。它不像普通的CRUD(增删改查),而是一条有方向、有约束的状态链。我把这套系统的毕业审核状态整理成了一条链路:
草稿(draft) → 已提交(submitted) → 辅导员初审(counselor_checked) → 教务秘书复核(registrar_checked) → 院系终审(dept_approved) → 通过(passed) ↘ 退回(returned) → 学生修改 → 重新提交 ↘ 驳回(rejected) → 结束(不可再提交)这套状态机的设计核心,是“每一步审核必须有上一步的状态作为前提”,不能跳级。比如教务秘书复核时,如果学生状态还是draft,后端会直接抛异常。这个约束是在代码里用枚举+状态判断实现的,不是靠前端按钮隐藏就行(前端隐藏按钮只是UI层面,后端必须能做同样的校验)。每个状态变更都会写一条审核记录到audit_record表,包括操作人、操作时间、操作结果、备注内容。这种“状态机+全链路审计日志”的设计,是这套系统最有含金量的地方。
我一开始跑的时候就注意到它把“退回”和“驳回”分成了两个操作。退回是可以修改后重新提交的,驳回是最终判定不合格的。这个区别在真实业务里很关键:成绩单没盖错章可以退回去改,但是学位资格差0.5绩点而且处分未消,直接驳回。很多毕设项目会把这两个操作合并成一个,数据上虽然省事,但业务表达上就糊了。
3.2 数据库表设计:几张核心表逐一拆解
我直接把几张核心表的结构和设计意图说清楚,这里也是答辩时的重点。
学生表student:核心字段是student_no(学号,唯一索引)、name、gender、college_id(所属院系)、major_id(专业)、grade(入学年份)、status(在读/休学/毕业)。这里有个细节:学号一定设唯一索引,不能只设普通索引,因为学号是业务上识别一个学生的唯一凭证。
用户表user:与student(以及教职工)是一对一关联。字段包括username、password(BCrypt加密后存储)、role_id、is_active。密码密文存储是底线要求,如果这套源码里密码是明文存的,你接手后第一件事就是改掉它。
课程成绩表course_score:字段包括student_id、course_id、score、credit、semester、is_pass。is_pass可以冗余存储,由score >= 60计算得出,也可以由管理员手动调整(比如某些缓考、缺考的特殊情况)。
毕业审核主表graduate_audit:字段包括student_id、application_date、total_credits(系统算出来的总学分)、course_pass_status(必修课是否全过)、thesis_status(论文是否通过)、status(状态机里的状态码)、current_auditor(当前待审核人ID)、remark。
学位审核主表degree_audit:在毕业审核基础上增加了gpa_status(绩点是否达标)、score_threshold(学位课平均分是否过学校线)、punishment_status(处分是否解除)。有些学校还有“外语水平”和“计算机水平”要求,这套源码里没做死,条件参数表可以配置,这一点设计得很聪明。
审核记录表audit_record:字段包括audit_id、audit_type(毕业/学位)、operator_id、operation(确认/退回/驳回)、from_status、to_status、remark、create_time。这张表是“审计日志”,只能插入,不能修改和删除,这是表的底线约束。
这几张表的关联关系,我用一句话概括:student是根节点,course_score、graduate_audit、degree_audit都是围绕student的一对多或多对一关系。查询学生是否具备毕业资格,本质上是一个以学生ID为输入条件,跨多张表做聚合判断的过程。
3.3 毕业条件参数化:一套代码适配多种培养方案
这套系统让我比较欣赏的一个设计,是“毕业条件参数表”graduate_condition。这张表把毕业资格审核规则抽了出来,比如“总学分>=培养方案要求学分”“必修课全部通过”“毕业论文通过”“无未清除处分”。每一条规则是一个配置项,有field_name(判断用的字段)、operator(大于等于/等于/包含)、threshold(阈值)。系统运行时,先动态读取条件配置,再逐条对学生的数据做匹配,所有条件都满足才进入“系统预审通过”。
这样做的好处是,毕业条件因专业而异、因年级而异。比如2020级某专业要求选修课修满10学分,2021级要求12学分,如果条件写死在代码里,改一次规则就要改一次代码。参数化之后,管理员可以在界面上直接修改阈值,不用动一行Java代码。从答辩角度讲,这个设计可以往“低耦合”“规则引擎雏形”这些方向讲,很加分。
4. 实操运行指南:从零把项目跑起来
4.1 环境准备:版本对上号,才能少踩坑
这套源码跑起来的完整前置环境,我列一份清单,每项都标了版本建议,因为版本不匹配是最容易出问题的:
| 工具 | 建议版本 | 说明 |
|---|---|---|
| JDK | 1.8(8u201以上) | SpringBoot 2.x+JDK8是最稳组合,别用JDK17,很多老依赖会翻车 |
| Maven | 3.6.3 | 3.8以上需要额外配置仓库源,新手容易卡在下载依赖 |
| MySQL | 5.7或8.0 | 两端都比5.7更严格,字符集统一utf8mb4 |
| Node.js | 14.x/16.x | Vue 2项目用这两个版本,18.x容易出现OpenSSL问题 |
| npm | 6.x/8.x | 跟随Node版本即可,注意锁文件的兼容性 |
在正式解压源码之前,先把上面这些装好。我用的是MySQL 8.0,连接时遇到时区问题(serverTimezone),后面章节会写具体解决办法。你如果手头有MySQL 5.7,直接跑会更顺,因为5.7对驱动要求的参数少。
4.2 数据库初始化:导入脚本别忽略字符集
源码包一般带两个数据库脚本,一个叫init.sql,建库建表,另一个叫data.sql,插入初始数据和测试账号。导入时有一个超关键的细节:必须在导入前设置字符集。直接在cmd里执行source或者用Navicat运行脚本时,如果系统默认字符集不是utf8mb4,中文数据会变乱码。我用Navicat实验过一次,不指定字符集导入,字段值全是问号,后续登录都失败。
推荐用命令行导入,并显式指定字符集:
mysql -uroot -p --default-character-set=utf8mb4进入MySQL后:
CREATE DATABASE graduate_system DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE graduate_system; SOURCE init.sql; SOURCE data.sql;导入完成后,先验证一下表数量和关键数据:
USE graduate_system; SHOW TABLES; SELECT * FROM user;你应该能看到一张初始化好的user表,里面有管理员账号、教师账号、学生账号的记录。如果user表里的密码字段是一串类似$2a$10$xxxx的BCrypt加密串,说明密码处理是对的;如果看到明文123456,建议你立刻手动改成加密后字段(可以参考后端代码里自带的BCrypt工具类生成)。
数据库编码有没有问题,最直接的验证方法,是查看学生姓名和院系名称有没有乱码。
SELECT * FROM student LIMIT 5;如果看到“张�”“信息??学院”这类字符,还没启动后端,你已经进了第一个坑——这大概率是导入时字符集不对,请按上面命令重导一遍,不要往下走。
4.3 后端启动:改配置、跑起来、验证接口
导入数据库后,打开后端项目的application.yml,把数据源改成本机的:
spring: datasource: url: jdbc:mysql://localhost:3306/graduate_system?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: 你自己的密码 driver-class-name: com.mysql.cj.jdbc.Driver注意serverTimezone=Asia/Shanghai这一步。MySQL 8.0的JDBC驱动如果不指定时区,启动就会报The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized。这个是老经典问题了,我在MySQL 8.0上必踩。
然后还需要确认application.yml里的服务端口(默认8080)和上下文路径(有些项目会加server.servlet.context-path: /api)。如果加了上下文路径,前端的接口请求地址也要对应加上,否则404。
修改完成后,在后端项目根目录执行:
mvn spring-boot:run或者先打包再跑:
mvn clean package -DskipTests java -jar target/xxx-0.0.1-SNAPSHOT.jar启动成功的标志,是日志里出现Tomcat started on port(s): 8080,并且没有抛出BeanCreationException之类的异常。启动后不要急着看前端,先用浏览器访问http://localhost:8080/api/auth/login看看是否返回404还是400,如果返回404可以改成访问http://localhost:8080空白但不断连。更标准的是用Postman直接调登录接口,发一个JSON体:
{ "username": "admin", "password": "123456" }如果返回token字符串和角色信息,后端已经活了。
4.4 前端启动:依赖、代理、跨域
前端项目有独立的package.json,你需要先安装依赖。这里有一个高频翻车点:直接执行npm install时,如果项目里有node-sass依赖,会尝试从远程下载二进制文件,网络稍差就失败。解决办法是先设置镜像源再装:
npm config set registry https://registry.npmmirror.com npm install装完后,重点检查一下前端的vue.config.js或.env.development里的代理配置。如果是用代理方式解决跨域,应该在devServer.proxy里配置:
devServer: { port: 8081, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } }这种代理方式,前端代码里请求地址写/api/xxx,浏览器上不需要处理跨域,代理服务在服务器端转发。如果你改的是CORS全局放行方式,那代理可以不走,二选一即可,不要同时开,避免出现奇怪的重复转发问题。
前端启动命令:
npm run serve看到Compiled successfully的提示就可以打开http://localhost:8081,登录界面出来了,说明前后端已经连通。
4.5 初始账号与角色实测
这套源码自带的初始账号一般是这样几类(以data.sql里的实际值为准):
| 账号 | 密码 | 角色 |
|---|---|---|
| admin | 123456 | 系统管理员 |
| counselor01 | 123456 | 辅导员 |
| registrar01 | 123456 | 教务秘书 |
| student01 | 123456 | 学生 |
建议按“学生 → 辅导员 → 教务秘书 → 管理员”这个顺序依次登录,体验一遍完整流程:先用学生账号提交毕业申请,再用辅导员账号审核,再用教务秘书复核,最后用管理员查看统计面板。这个完整的操作序跑通,说明角色权限配置、状态机流转、数据表联查都没有问题。也是答辩演示时最流畅的演示脚本。
5. 常见问题与排查技巧实录
5.1 后端启动报错速查表
我前后在这套源码上跑了三轮,整理了下面这些必见问题。如果我跑的时候没遇到,多半也是早晚的事,建议你先存个档。
问题现象:APPLICATION FAILED TO START,提示Failed to configure a DataSource
原因:基本不是代码问题,是application.yml里的数据库连接参数没匹配。比如密码不对、主机没写对、数据库名写错一个字母。也可能是那个经典小坑,driver-class-name在MySQL 5.7与8.0之间版本不同,如果导入了不兼容的驱动类会直接卡在这里。
解决办法:依次核对url、username、password、driver-class-name四项。如果使用MySQL 8.0,驱动类名应为com.mysql.cj.jdbc.Driver;如果是5.7,可以用com.mysql.jdbc.Driver(但建议统一用8.0驱动连5.7,兼容性更好)。
问题现象:数据库连接时提示The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized
原因:MySQL 8.0默认时区配置和JDBC驱动不匹配,它把系统本地时区识别成乱码。这不是代码问题,是连接串缺了参数。
解决办法,在url末尾加:
?serverTimezone=Asia/Shanghai如果是在装的MySQL 8.0里也可以顺手改掉系统时区:
SET GLOBAL time_zone = '+8:00';问题现象:启动成功,但/api/xxx路径访问总是404
原因:两种常见可能。一是后端设置了server.servlet.context-path=/api,但你在前端没加前缀;二是你直接在后端浏览器里访问了/api开头的接口地址,但没有完全匹配后端@RequestMapping声明的路径。
解决办法:先看application.yml里有没有context-path,有的话前端请求统一加前缀;后端直接测试接口时,用Swagger或Postman,避免浏览器缓存干扰。
问题现象:启动时端口8080被占用
原因:常有旧进程没关干净。在Windows上,netstat -ano | findstr 8080找到PID,然后taskkill /pid 进程号 /f,重启后端进程。
5.2 前端启动报错速查表
问题现象:npm run serve之后,页面能打开,但接口全部超时
原因:大概率是vue.config.js的代理配置没生效,或者代理目标和后端context-path没对齐。
解决办法:打开浏览器F12,看请求地址,如果是http://localhost:8080/api/xxx,说明代理被绕过,应该检查环境变量VUE_APP_BASE_URL或请求封装里的baseURL;如果请求地址是http://localhost:8081/api/xxx,说明代理拦截了但目标没匹配上,检查target是否写了http://localhost:8080。
问题现象:npm install一直卡在sill idealTree buildDeps,或者报node-gyp相关错误
原因:node-sass编译需要Python和C++编译环境,Windows上最好先装好VS Build Tools;或者干脆用npm config set sass_binary_site https://npmmirror.com/mirrors/node-sass/,把二进制下载源切到国内镜像。
解决办法:如果你只是跑这个系统,不追求改样式,可以保留node-sass,但先把镜像源和sass_binary_site都设置好;如果你打算重写前端页面,建议把node-sass换掉,用sass(Dart Sass)+sass-loader的较新版本,安装干净利落。
问题现象:页面能登录,但切换路由后白屏
原因:动态路由的问题很常见,特别是每次刷新都白屏。大概率是刷新后store里的权限路由被清空了,但路由守卫只做了一次全局前置验证,没重新拉取动态路由。
解决办法:登录态在localStorage里存好,刷新时重新向后端调一次/auth/info获取角色和权限,再动态添加路由。这套源码如果刷新后直接白屏,大概率就是这块没处理好,有心情可以自己改一版。
5.3 业务逻辑层面的坑
问题现象:学生提交申请后,辅导员端看不到申请记录
原因:不是权限问题,就是院系关联没对上。student表里college_id和辅导员的college_id不是同一个值,或者学生在基础表里根本没维护college_id。
解决办法:用管理端账号进“学生信息管理”,核对学生的院系字段是否已维护。这个坑我在测试时踩过,因为data.sql里部分测试学生的院系ID是0,没关联到真实院系,导致辅导员列表查不出来。
问题现象:系统预审时学分统计结果和实际不符
原因:course_score表里可能维护了重复的课程记录,或者有补考、重修记录没做标识,导致统计算双倍学分。系统按course_id分组统计总学分时很容易错。
解决办法:看后端的scoreService实现,确认学分统计是依据“每门课只取最高成绩/最近一次成绩”这个规则,而不是直接把所有行累加。如果有重修逻辑,表设计里一定要有course_type或retake_flag来区分首修和重修。
6. 二次开发方向与个人扩展体会
6.1 高价值增强点:批量导入与导出
当前系统的学生和成绩数据基本靠管理员逐条录入,这在真实使用中不现实,因为几百号人的成绩单一次性Excel导入才符合行政场景。如果你想做二次开发,我建议优先加一个“批量导入成绩”功能。
具体思路:前端用Element UI的Upload组件上传Excel,后端用EasyExcel或POI解析,先解析成内存对象,再逐行校验(学号是否存在、分数范围0-100、日期格式),校验通过的行批量插入course_score表,校验失败的行生成错误信息文件返回给前端下载。这个功能的MVP版本,一天多时间就能做出来,但答辩展示效果好,因为“一键导入”可以直接对比“手工录入”的效率差。
6.2 高价值增强点:消息通知与待办提醒
审核系统天然需要“通知接收方”的能力。当前源码里没有消息中心,审核人不知道有新的申请待审,学生也不知道审核被退回。加一个通知表notification,在状态机变更时,向下一环节角色所属用户插入一条待处理通知,可以在前端顶部放一个铃铛图标,展示未读数量。
技术实现上,最轻量的方案是前端轮询接口(每30秒查一次未读数),后端在auditRecordService的每次状态变更时,同步插入通知记录,在事务里保证原子性。如果需要实时性更强,可以升级为WebSocket,但管理系统的实时性要求没那么高,轮询足够用。
6.3 安全与性能:生产环境必须补的短板
这套源码跑通没问题,但如果要部署到真实环境,还有几个短板必须补上。
密码策略:初始账号密码都是123456,上线前必须强制首次登录修改密码,最好增加密码复杂度校验(8位以上,含大小写字母数字)。
接口限流:管理系统面临最多的是撞库风险,登录接口应该加验证码+尝试次数限制。听说这套源码里登录接口没有验证码,建议自己用kaptcha集成一个滑块或图片验证码,再把失败5次后的账号锁定30分钟。
HTTPS:前后端分离部署,生产环境建议Nginx反向代理后端并配置HTTPS证书。如果学校环境有统一身份认证系统对接的,还可以调研一下CAS或OAuth2登录的集成方案。
数据备份:审核数据是重要数据,定时备份不能省。MySQL层面每天mysqldump一次,保留最近30天副本。这个看似不起眼,但在真实教务系统里是底线,别等数据丢失了再想办法。
6.4 从毕设到实战,心态上的一点建议
我在帮别人调试这套系统的过程中,最大的感触是:很多同学拿到源码,第一反应是“能不能直接交”,而不是“能不能讲明白”。但实际上,答辩时老师问得最深入的就是技术决策的“为什么”——为什么用SpringBoot不用SSH,为什么状态用枚举不用字符串,为什么学位审核和毕业审核分开建表。如果这些“为什么”你自己没想清楚,就算代码跑得再顺,答不上来也是白搭。
我的建议是,拿到这套源码后,按两遍走:第一遍只读不写,把每个模块的Controller、Service、Mapper串起来,画出请求的流转图;第二遍再改代码,把你觉得不合理的点(比如刷新后路由白屏、密码明文初始值、没有批量导入)自己修掉哪怕很小一处。改出成果来,比交一个原封不动的能跑项目,更有说服力。
个人体会最深的一件事是:毕业资格审核系统的核心算法不算复杂——它本质上就是一堆条件判断的组合,难点全在工程化上:条件配置要动态化、不同角色关注的数据维度不同、状态变更必须留痕、数据导入要支持大批量。这套SpringBoot+Vue+MySQL的组合,确实很适合作为理解企业级管理系统的起点,因为它把典型的“权限+状态机+报表统计”三者都覆盖了。
最后分享一个我实际调试时用到的小技巧:前端登录成功后,F12里看一眼localStorage里存的userInfo,确认后端返回的role_id和你预设的一致。很多时候界面上按钮消失、菜单显示不全,不是后端没返回权限,是前端拿role_id去匹配路由表时,英文角色名和数据库里的ID没对上。这个小坑排查起来很快,但看一眼就少走半小时弯路。
这套代码底子扎实,前后端分离、角色权限、状态机设计都在正规思路上,跑通只是第一步。把它改成带有自己思考的作品,才是这个项目真正的加分项。