1. 驾校管理系统到底要解决什么问题——需求与功能边界
每年到毕业设计开题的时候,我都会遇到一批同学,拿着"基于SpringBoot + Vue的XX管理系统"这种题目来问我:这个题目网上一搜一大把,是不是太水了?实际上,越是这样看起来普通的题目,越要看你到底能做多深。驾校管理系统这个题目,核心不是"管理系统"这三个字,而是你能不能把驾校的真实业务链条梳理清楚。驾校日常运转涉及报名、建档、教练分配、约车、学时统计、考试预约、缴费、车辆维护,这些环节乱成一团的时候,靠Excel和微信群是管不过来的。这就是系统的价值所在。
先想清楚一个前提:你的系统是给谁用的?驾校管理系统通常分成三类角色。
- 管理员:管全局,维护学员档案、教练信息、车辆信息,查看预约和考试数据,处理缴费记录。
- 教练:查看自己的带教任务,确认学员到场,填写训练记录,查看个人日程。
- 学员:注册登录,浏览公告,在线约车,查看自己的学时、考试成绩、缴费状态。
这三类角色的需求叠加在一起,才是完整的业务闭环。如果只做一堆CRUD(增删改查)页面,那是管理后台,不是管理系统。好的毕设系统,一定要把角色、流程、状态变化串起来。
功能模块我建议拆成七个核心块,每个块对应一套表、一组接口、至少一个前端页面。
| 模块 | 核心功能 | 涉及角色 |
|---|---|---|
| 用户认证 | 登录、注册、密码加密、角色区分 | 全部 |
| 学员管理 | 报名建档、资料修改、学时查询 | 管理员、学员 |
| 教练管理 | 教练信息维护、带教学员分配 | 管理员 |
| 车辆管理 | 车辆档案、状态维护、维修记录 | 管理员 |
| 约车管理 | 查看可约时段、在线预约、取消预约 | 学员、教练、管理员 |
| 考试管理 | 科目一至科目四成绩录入、考试预约 | 全部 |
| 缴费与统计 | 缴费记录、费用汇总、简单图表 | 管理员、学员 |
这里要特意提醒一句:不要在功能上贪多。我见过好多人开题的时候列了十几个模块,最后实际做出来的只有四个半,答辩的时候被老师追着问"你文档里的XX功能在哪",场面非常尴尬。倒不如把上面七个模块做扎实,尤其是约车管理的冲突处理,这一个点做好了,就足够说明你的系统不是玩具。
业务流线的核心是"学员从报名到拿证"的完整链路:报名建档之后分配教练,然后在约车模块预约训练时段,教练确认到场并录入训练记录,训练学时达到要求后学员预约考试,考试通过进入下一科目,四科全部通过则结业。这个链路要能闭环,你的系统才叫"管理系统",而不是"信息维护系统"。
2. 技术选型为什么是SpringBoot + Vue,而不是其他组合
这个组合快被毕设用烂了,但用烂了恰恰说明它适合。我拆开说。
2.1 后端:为什么SpringBoot而不是SSH或SSM
很多学校教材还在教SSM(Spring + SpringMVC + MyBatis),但SSM的问题在于配置繁琐——数据源、事务、扫描器、视图解析器,一整套XML配置下来,还没开始写业务代码就已经头晕了。SpringBoot最大的贡献是"约定大于配置",内嵌Tomcat,一个SpringBootApplication就能启动,极大降低了搭建门槛。
对于毕设来说,选型还要考虑答辩老师能不能看懂。SpringBoot继承自Spring,核心的IOC、AOP、MVC理念不变,老师问到底层也能聊得下去。相比用Node.js或者Python写后端,Java在高校的接受度要高得多,这不是技术优劣问题,是沟通成本问题。
2.2 前端:为什么Vue而不是React或者纯JSP
如果你的项目还停留在JSP + JQuery时代,那确实能跑,但答辩的时候技术选型这一关就容易被挑战。Vue的优势是上手曲线平缓,核心概念就那么几个:数据绑定、组件、路由、状态管理。配合Element UI这套组件库,后台管理系统常用的表格、表单、弹窗、分页、日期选择器全都是现成的,你只需要做组合和业务逻辑。
React当然也很好,但React的生态链条对新手不够友好——你光是理解函数式组件、Hooks、状态管理搭配就开始头疼了。Vue则直观得多,template模板写起来有传统HTML的影子,Vuex或Pinia管理状态也足够。
另外想澄清一个误区:很多人觉得前后端分离很高级,其实也就是前端跑一个Vite开发服务器,后端跑一个SpringBoot程序,两边通过HTTP接口通信。但正因为分离,你才需要在论文里单独写"前端设计"和"后端设计"两个章节,内容量自然就上去了。这对凑论文字数来说,是个实打实的优势。
2.3 辅助工具选型清单
我推荐一套我自己带学生常用的配置,兼顾可行性和可解释性:
- 数据库:MySQL 8.x,别用5.7了,但要注意驱动版本对应
- 持久层:MyBatis-Plus。它能减少大量单表CRUD代码,分页插件也方便。但如果你怕老师问"你怎么不用MyBatis",建议在论文里写清楚MyBatis-Plus是MyBatis的增强工具,核心SQL执行机制没变
- 认证方案:JWT + 登录拦截器。轻量,无状态,不需要额外搞Spring Security那套重家伙
- 前端构建:Vite。比Vue CLI快很多,但如果你不熟,用Vue CLI也完全没问题
- UI组件库:Element Plus(对应Vue3)或Element UI(对应Vue2)
- 接口调试:Apifox或Postman,年前后联调阶段离不开
这里我建议,如果你的基础偏弱,直接用Vue2 + Element UI + Vue CLI,因为网上教程最多,踩坑的时候搜索引擎能救你。如果你基础还行,用Vue3 + Element Plus + Vite,技术新一些,答辩观感更好。
3. 数据库设计:一张表一张表理清楚
数据库设计是论文里最容易被老师翻看的部分,也比代码本身更容易得高分。整个系统我规划了九张表,下面逐一说明核心字段和设计意图。
3.1 用户与角色设计:冗余字段还是RBAC
最简单也最常见的做法是建一张user表,加一个role字段区分管理员、教练、学员。这样做跳过了权限系统的复杂度,适合大多数毕设场景。
CREATE TABLE `sys_user` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键', `username` VARCHAR(50) NOT NULL UNIQUE COMMENT '登录账号', `password` VARCHAR(255) NOT NULL COMMENT '密码(BCrypt加密)', `real_name` VARCHAR(50) COMMENT '真实姓名', `phone` VARCHAR(20) COMMENT '手机号', `role` TINYINT NOT NULL COMMENT '角色:1管理员 2教练 3学员', `status` TINYINT DEFAULT 1 COMMENT '状态:1正常 0禁用', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;注意密码不要存明文,用BCrypt加密,Spring Security的密码工具类可以直接调用,这是最基本的安全意识,写进论文里是个加分项。
如果你想让系统显得有深度,可以采用RBAC(基于角色的访问控制)再加两张表:角色表和用户角色关联表。但说句实在话,管理员、教练、学员这三种角色用一张表的role字段就够了,强行上RBAC反而显得为了复杂而复杂。
3.2 核心业务表设计:学员、教练、车辆、预约
业务表的设计我要重点说约车相关的表,因为这是全系统的逻辑难点。
教练表一般包含教练编号、姓名、准教车型、联系电话、当前状态(空闲/带教中)。
车辆表包含车牌号、车型、状态(可用/维修中)、下次保养里程等。
预约表要同时关联学员、教练、车辆、时间段:
CREATE TABLE `appointment` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `student_id` BIGINT NOT NULL COMMENT '学员ID', `coach_id` BIGINT NOT NULL COMMENT '教练ID', `vehicle_id` BIGINT COMMENT '车辆ID', `appointment_date` DATE NOT NULL COMMENT '预约日期', `time_slot` TINYINT NOT NULL COMMENT '时段:1上午 2下午 3晚间', `status` TINYINT NOT NULL COMMENT '状态:1待确认 2已完成 3已取消', `progress_note` VARCHAR(500) COMMENT '训练内容记录', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY `uk_coach_slot` (`coach_id`, `appointment_date`, `time_slot`), UNIQUE KEY `uk_vehicle_slot` (`vehicle_id`, `appointment_date`, `time_slot`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;这里两个唯一索引是精华所在,它们直接在数据库层面保证了同一教练或同一辆车在同一时段只可能有一条有效预约。这是面试和答辩时非常好讲的一个点。
科目成绩表单独设计,把科目一、科目二、科目三、科目四的成绩记录在一条记录里,用字段区分阶段,状态字段标记待考、通过、未通过,比建四张子表更简洁。缴费表记录费用类型、金额、缴费时间,金额用DECIMAL类型,不用FLOAT,避免浮点数精度问题。
3.3 建表的常见坑
第一,时间字段统一用DATETIME,别混用TIMESTAMP,否则时间范围和数据更新行为会让你头疼。第二,所有业务表都要有create_time和update_time;第三,表名和字段名用下划线风格,Java实体类用驼峰,开启MyBatis-Plus的下划线自动映射开关,两者一一对应,不会对不上。第四,逻辑删除加一个deleted字段,毕设系统虽然不涉及多少删除场景,但写了这个字段能在答辩时显得你考虑到了数据安全问题。
4. 后端核心接口设计与实现
后端这部分是所有功能的发动机,下面按模块讲清楚接口设计和实现思路,并且会指出哪些地方容易出问题、为什么那么设计。
4.1 登录认证与权限控制:轻量JWT方案
我用了JWT做登录凭证。学员注册成功后,系统自动创建一个角色为学员的账号。登录成功后后端生成一个token返回给前端,前端存到localStorage,每次请求在请求头里带Authorization字段。
后端使用一个拦截器统一拦截需要认证的接口,解析token,判断角色是否有权限访问该接口。代码核心逻辑如下:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("Authorization"); if (token == null || token.isEmpty()) { throw new BusinessException(401, "未登录"); } // 解析token,校验签名和过期时间 Claims claims = JwtUtil.parseToken(token); // 从token中获取角色信息,判断是否有权限 int role = (int) claims.get("role"); // 如果要访问的接口要求管理员角色,而当前用户不是,则拒绝 if (requiresAdmin(request) && role != 1) { throw new BusinessException(403, "无权限"); } // 将用户信息放入request上下文,方便后续业务取用 request.setAttribute("userId", claims.get("userId")); return true; }这里的关键是把数据库查询次数降到最低——token里直接存userId和role,拦截器不用每次去查库。虽然安全性和实时性比从Redis里再校验一次弱一点,但毕设场景足够用了。答辩时被问到"如果用户被禁用怎么办",你可以答"登录时校验过状态,如果要更实时,可以把token存Redis并在禁用时删除对应key",这就显得你有思考。
4.2 学员管理:用MyBatis-Plus把CRUD做干净
学员管理后端接口基本是一致的套路:分页查询列表、按条件筛选、新增、修改、删除、详情。MyBatis-Plus的IService接口已经把单表操作封装好了,你需要做的是把业务规则写进去。
比如在新增学员的时候,除了插入学员表,还要同步创建登录账号。这个过程要用事务保证原子性。我的习惯是这样的:
@Transactional(rollbackFor = Exception.class) public Long addStudent(StudentDTO dto) { // 1. 生成一个默认登录账号,比如手机号作为用户名 SysUser user = new SysUser(); user.setUsername(dto.getPhone()); user.setPassword(BCrypt.hashpw("123456", BCrypt.gensalt())); user.setRole(3); // 学员角色 sysUserService.save(user); // 2. 创建学员档案,关联用户ID Student student = new Student(); BeanUtils.copyProperties(dto, student); student.setUserId(user.getId()); student.setStatus("在读"); studentService.save(student); return student.getId(); }@Transactional注解必须兜住异常,否则用户创建成功了学员档案插入失败,数据就处于半状态,这种低级错误是答辩扣分项。另一个细节是默认密码,系统生成后一定要在文档里写清楚初始密码是什么,不方便演示的时候这就是你的救命稻草。
4.3 约车业务:并发冲突如果处理
约车是整个系统里最值得深入讲的地方。同一个教练在同一个时段可能被多个学员同时点击预约,如果后端不处理,后插入的数据就会因为上面的唯一索引而报错。后端要明确捕获这个冲突,然后给用户一个友好提示:
try { appointmentService.save(booking); return success("预约成功"); } catch (DuplicateKeyException e) { return error("该教练或车辆在该时段已被预约,请选择其他时段"); }为了给用户更好的体验,前端在展示可选时段时,后端需要提供一个查询接口:传入教练ID或车辆ID、日期,返回哪些时段已被占用,哪些还能约。这个查询接口本质上就是查appointment表里对应日期的记录,然后把结果映射成一个时段数组。就这么一个简单的逻辑,整个系统的核心业务就通了。
再往深走一步,如果需要防止"两个人同时看到空闲时段并同时提交",可以使用乐观锁的思路:预约表加一个version字段,更新时条件加上version=旧值,如果更新影响行数为0,说明期间被其他人改过,返回冲突提示。毕设做到这个程度已经超出九成的人了,这句话不是夸张,是真的想拿优秀论文值得下的功夫。
4.4 统计报表与数据导出
管理员首页需要几个关键数字:学员总数、今日预约数、本月收入、教练数量。这些用聚合查询就能搞定。如果用MyBatis-Plus,Service层的queryWrapper加selectCount就解决,不需要写复杂SQL。只有按月份汇总收入这种复杂一点的,才需要写自定义SQL:
SELECT DATE_FORMAT(pay_time, '%Y-%m') AS month, SUM(amount) AS total FROM payment WHERE pay_time BETWEEN #{startTime} AND #{endTime} GROUP BY month ORDER BY month导出Excel用EasyExcel,网上一搜教程很多。论文里能写"系统支持缴费记录导出,便于驾校财务做线下对账",功能不大,但抬头一下子就不一样了。
5. Vue前端实现:从搭建到跑通
5.1 项目初始化的正确姿势
如果是Vue3 + Vite,命令是:
npm create vite@latest driving-school-frontend -- --template vue cd driving-school-frontend npm install element-plus axios vue-router pinia安装完依赖后,建议第一时间把目录结构理好,不要全部堆在src下面。我的习惯是分成api、router、store、views、components、utils六个目录。api目录下每个模块一个文件,比如student.js、coach.js、appointment.js,统一封装接口请求。这个习惯的重要性在写论文时的系统实现章节就体现出来了——你能按照模块清楚地描述前端结构。
5.2 Router路由与权限控制
前端路由要配合后端角色做控制。最实用的方案是路由守卫:
router.beforeEach((to, from, next) => { const token = localStorage.getItem('token'); if (to.path !== '/login' && !token) { next('/login'); } else { // 根据角色动态过滤可访问菜单 next(); } });菜单根据登录用户角色动态渲染。管理员能看到全部的菜单,教练只能看到我的日程和训练记录,学员只能看到预约和成绩查询。我见过太多人把全部菜单静态写在侧边栏,然后每个页面里再判断权限,这样做出来界面是可以接受的,但答辩时老师问"没有权限的页面学员能不能直接通过URL访问",你答不上来就比较尴尬。所以用动态路由或者路由守卫拦截,都要体现在你的实现里。
5.3 Axios拦截器的两个关键处理
第一,请求时要带上token。第二,响应时统一处理错误码。这两件事在Axios拦截器里做,不用在每一个接口里重复写。实践代码如下:
axios.interceptors.request.use(config => { const token = localStorage.getItem('token'); if (token) { config.headers.Authorization = token; } return config; }); axios.interceptors.response.use( res => { const code = res.data.code; if (code === 401) { localStorage.removeItem('token'); router.push('/login'); } return res.data; }, err => { // 网络错误或者HTTP异常时的统一提示 ElMessage.error(err.message); return Promise.reject(err); } );统一拦截的意义在于,后端返回400、401、403、500这些状态时,前端能够保持一致的用户提示。这个细节的代码量不大,但写在论文里《系统实现》部分非常加分。
5.4 表格、表单、弹窗三件套
后台管理系统在世界里90%是Element Plus的el-table加el-form加el-dialog。做一个学员管理页面,页面上方是筛选表单,中间是数据表格,末尾是分页器,新增和编辑共用一个弹窗表单。
几个实操心得:
- 表格列不要全部展示,字段多的时候用设置列显隐,或者把重要的字段放前面
- 日期时间字段用Format,别让时间戳直接裸奔在表格里
- 状态字段用el-tag展示不同颜色,比如"已预约"蓝色、"已完成"绿色、"已取消"灰色,一屏看完状态分布
- 弹窗的关闭时机要统一:保存成功后自动关闭、重置表单、刷新列表,三个动作要在同一个函数里完成
这些点单独拿出来都不值钱,但组合在一起,系统的完成度会肉眼可见地提升。答辩时老师坐在后面扫一眼页面,感觉和"能跑"之间差好几个档次。
5.5 跨域问题和联调
前端开发服务器默认端口5173,后端SpringBoot默认8080,二者必然要跨域。不要试图在Axios里随便加个proxy就完事,要明白原理。最稳的方案是在SpringBoot里写一个CorsConfiguration或加@CrossOrigin,或者在Vite的vite.config.js里配置proxy:
server: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true, rewrite: path => path.replace(/^\/api/, '') } } }用proxy的好处是前端请求的地址看起来是同源的,不会有浏览器跨域限制。但需要注意,如果你最后部署的时候没有走同一个服务,跨域问题又会冒出来。所以我会建议你在后端的全局跨域配置也写一份,双保险。
联调阶段我最建议的做法是用Apifox先把全部接口自测一遍,确认返回结构正常,再让前端对接。只要接口返回值结构统一,前端会在半小时内接完一个模块;如果边写后端边联调,效率会低很多。这个"先后端自测、再前端联调"的顺序,是能救命的。
6. 数据库设计常见翻车现场与优化点
这部分非常重要,因为很多人的设计是"看起来能跑",但表一多就站不住脚。我在带学生的过程中发现一些高频问题,值得单独提醒。
6.1 用户表与业务表的关系
我见过有人把学员的信息全部塞进user表,phone、idCard、address、emergencyContact、报名时间、考试次数全堆在一起。这样建表只有一个好处:写代码快。坏处是用户表的职责不清晰,而且教练、管理员没有这些字段,表结构会变得非常稀疏。
正确做法是在user表只保存登录所需的最小信息,业务字段放到对应的学员表、教练表。学员表和user表通过user_id关联。这个设计在答辩时是加分项,因为这是规范的"职责单一"思想。
6.2 状态字段设计
很多新手喜欢用字符串状态,比如"待支付"、"已支付"、"已取消"。字符串可读性好,但是数据库字段冗余和耦合度高。如果你后续改了中文显示,比如把"已取消"改成"已关闭",意味着要把历史数据全部UPDATE一遍。
比较好的做法是状态字段用TINYINT存储数字状态,1、2、3,然后在Java代码里用枚举定义各个状态的含义。前端再根据状态值映射显示文字和颜色。数据库里只存真状态,展示逻辑交给代码。这样程序稳定,而且你可以在论文里写一段"系统状态统一使用枚举管理"的话,听起来就很规范。
6.3 索引设计与慢查询
没有索引的查询在数据量小的时候看不出问题,几千条数据随便查都很快。但答辩老师可能会问你"如果数据量到几十万条,这个查询会怎样"。这时候你能回答出"我对经常查询的字段加了索引"就能接住这个问题。常见的需要加索引的字段有:
- 关联字段:student_id、coach_id、user_id
- 查询条件:appointment_date、phone、status
- 需要排序的:create_time
同时要避免在索引列上做函数运算,比如where DATE_FORMAT(create_time, '%Y-%m') = '2024-06'会让索引失效。更好的写法是使用范围查询:where create_time >= '2024-06-01' and create_time < '2024-07-01'。这一个知识点写进论文的数据库优化章节,让整篇文章的深度有了立竿见影的提升。
6.4 逻辑删除的价值
刚开始做项目的时候,我直接使用物理删除——把DELETE语句一发,数据没了。后来发现这样做的隐患很大,比如你误删了一个学员,连带他的报名记录、缴费记录、预约记录全部查不出来,想恢复也没办法。
后来我在所有业务表上都加了deleted字段,MyBatis-Plus的@TableLogic注解可以自动在查询时加条件where deleted = 0,删除操作变成UPDATE。这个改动很简单,但让数据多了一道安全防线。更关键的是,在论文里写"系统采用逻辑删除防止误操作导致的数据不可恢复",是非常标准的安全性描述。
7. 论文写作与答辩演示的准备策略
这个部分看似和技术无关,但每逢毕业季我发现很多人的失败不是代码跑不起来,而是不会把代码讲成论文。
7.1 论文结构怎么安排
一般的毕业论文结构是摘要、绪论、需求分析、系统设计、数据库设计、系统实现、系统测试、总结。其中需求分析和系统设计是占比最高的部分,要尽量写厚、写详实。
需求分析不要笼统地说"系统需要学员管理功能",而是用用例图配合角色说明:某个角色发起某操作,系统反馈什么,异常情况下又该怎样处理。比如预约模块的需求描述:学员选择教练、日期和时段,若时段被占用则提示重新选择;若预约成功,教练端显示该时段待确认信息,这比干巴巴的文字更有说服力。
系统设计部分要画出架构图。我这里说的不是Mermaid,而是你在Word或ProcessOn里自己拉出来的框架图——前端通过HTTP请求访问后端接口,后端依赖业务层、数据层,数据库MySQL存储数据。这种图用一张就够,但它能帮老师十秒钟建立你对整个系统的掌控感。
数据库设计章节直接把建表SQL和字段说明表放进去,注意每个字段要写注释。表多没关系,但一定要有一段文字把表与表之间的关联关系说清楚,最好再画一个ER图。
7.2 答辩高频问题怎么准备
根据我当答辩记录员的经验,老师问的最多的是以下几类:
问"系统分了哪些角色,分别有什么权限?"
参考答案思路:系统分管理员、教练、学员三类角色。管理员在登录后可以访问全部功能模块;教练端只能看自己的日程和训练记录;学员端只能预约和查询自己的数据。权限控制通过后端拦截器加前端路由守卫双重实现。
问"同一个时段被两个人约了怎么办?"
这是一个必考题。答辩准备时要把唯一索引、事务处理、前端置灰这些链路讲清楚。最好能现场演示:用两个浏览器开两个窗口,同时点同一个时段的预约按钮,一个成功一个提示冲突。这个演示一出来,老师基本不再追问。
问"密码存在数据库里安全吗?"
你要提到使用了BCrypt加密,并且说明为什么不能使用MD5——MD5加固定盐依然有被彩虹表破解的风险,而BCrypt加随机的盐,即使两次相同密码加密结果也不一样。虽然答不了太深,但能把这个对比说清楚就已经是加分项了。
问"系统有什么不足?"
不要回答"没有不足"。我见过有人说"我的系统很完美",老师当场笑了。正确姿势是主动指出两三个可扩展的方向:比如可以增加消息通知功能,预约成功后通过邮箱或短信提醒学员;比如可以引入Redis缓存热门的教练时段数据;比如可以增加人脸识别签到功能。这既表明你了解系统的边界,也让老师觉得你有工程思维。
7.3 演示Demo的准备细节
答辩演示翻车往往不是功能不够,而是环境问题。开学答辩的时候老师不会慢慢等你启动项目,所以提前要做好三件准备:
第一,准备一个录屏备胎。将整个操作流程录制成视频,防止现场电脑蓝牙鼠标突然失灵、显示器分辨率不兼容。第二,预设账号提前准备好,管理员、教练、学员各一个,密码写在便利贴上。第三,演示数据要足够多,至少10个学员、5个教练、10辆车、几十条预约记录,让页面看起来是活的。空的页面会放大一切视觉问题。
我见过的另一类翻车是现场改了代码,页面崩了。答辩前一晚尽量不要再动核心功能,要加特性不如录进视频里。记住,答辩演示的目标是"稳定不翻车",不是"当场写新功能"。
8. 我的一些实在建议
如果让我从零把这个题目再做一遍,我会严格按下述顺序推进,保证每个阶段都有可见的产出:
第一周,只画原型图和写数据库建表SQL。不用写任何代码,就能把业务关系理清楚。第二到三周,完成后端全部接口,用Apifox自测通过。第四到五周,完成前端页面和联调。第六周,写论文初稿,把需求分析、系统设计、数据库设计章节写透。最后十天做PPT、整理演示数据和录屏,反复排练答辩话术。
还有一件容易被忽略的事:Git提交记录。从第一天开始就用Git管理代码,每次完成一个小功能就提交一次。论文里可以附上项目Git仓库地址,答辩时也可以展示提交记录,说明你是一步一个脚印完成的。那些最后一天打包一下代码的,很难讲出"开发过程"。
驾校管理系统这个题目真正考验的不是技术难度,而是你有没有完整走完一个"需求分析—设计—实现—测试—文档"的全流程。数据库里的唯一索引设计、后端的事务处理、前端的路由守卫、答辩时的权限问答,这些点戳中任何一道题,整个项目就算立住了。说到底,毕业设计考察的是独立思考能力和工程表达能力,这两样过关了,分数不会低。