高校毕业与学位资格审核系统:SpringBoot+Vue+MySQL实战解析 先说实话这种“高校毕业与学位资格审核系统”在每年的毕设季几乎扎堆出现。你随便一搜就能看到各种版本但真正能改明白、跑起来、答辩时讲清楚逻辑的并不多。这套源码我在本地完整跑过一遍后端用的是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 MySQL2.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、passwordBCrypt加密后存储、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 环境准备版本对上号才能少踩坑这套源码跑起来的完整前置环境我列一份清单每项都标了版本建议因为版本不匹配是最容易出问题的工具建议版本说明JDK1.88u201以上SpringBoot 2.xJDK8是最稳组合别用JDK17很多老依赖会翻车Maven3.6.33.8以上需要额外配置仓库源新手容易卡在下载依赖MySQL5.7或8.0两端都比5.7更严格字符集统一utf8mb4Node.js14.x/16.xVue 2项目用这两个版本18.x容易出现OpenSSL问题npm6.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-setutf8mb4进入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?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 你自己的密码 driver-class-name: com.mysql.cj.jdbc.Driver注意serverTimezoneAsia/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里的实际值为准账号密码角色admin123456系统管理员counselor01123456辅导员registrar01123456教务秘书student01123456学生建议按“学生 → 辅导员 → 教务秘书 → 管理员”这个顺序依次登录体验一遍完整流程先用学生账号提交毕业申请再用辅导员账号审核再用教务秘书复核最后用管理员查看统计面板。这个完整的操作序跑通说明角色权限配置、状态机流转、数据表联查都没有问题。也是答辩演示时最流畅的演示脚本。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末尾加?serverTimezoneAsia/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换掉用sassDart Sasssass-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串起来画出请求的流转图第二遍再改代码把你觉得不合理的点比如刷新后路由白屏、密码明文初始值、没有批量导入自己修掉哪怕很小一处。改出成果来比交一个原封不动的能跑项目更有说服力。个人体会最深的一件事是毕业资格审核系统的核心算法不算复杂——它本质上就是一堆条件判断的组合难点全在工程化上条件配置要动态化、不同角色关注的数据维度不同、状态变更必须留痕、数据导入要支持大批量。这套SpringBootVueMySQL的组合确实很适合作为理解企业级管理系统的起点因为它把典型的“权限状态机报表统计”三者都覆盖了。最后分享一个我实际调试时用到的小技巧前端登录成功后F12里看一眼localStorage里存的userInfo确认后端返回的role_id和你预设的一致。很多时候界面上按钮消失、菜单显示不全不是后端没返回权限是前端拿role_id去匹配路由表时英文角色名和数据库里的ID没对上。这个小坑排查起来很快但看一眼就少走半小时弯路。这套代码底子扎实前后端分离、角色权限、状态机设计都在正规思路上跑通只是第一步。把它改成带有自己思考的作品才是这个项目真正的加分项。