ARTICLE DETAIL

资讯详情

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

SpringBoot+Vue宿舍维修管理系统毕业设计实战:从架构设计到部署演示

SpringBoot+Vue宿舍维修管理系统毕业设计实战:从架构设计到部署演示 1. 项目概述1.1 核心需求解析这个项目说的是一个典型的Java Web毕业设计题目宿舍维修管理系统技术栈锁定在SpringBoot Vue配套SQL脚本和接口文档。我第一眼看到这个标题的时候脑子里跳出来的是“又是宿舍管理”这几个字因为这类系统在高校毕设里出现频率极高几乎是“选题万金油”。但仔细想一下它其实有一套比较清晰的业务主线和固定的技术套路能做扎实、能跑通、能展示、能答辩就已经是一份相当拿得出手的毕业设计了。宿舍维修管理系统解决的痛点很简单学生宿舍里报修麻烦、维修进度不透明、后勤管理混乱。传统模式下学生要么去宿管办公室填纸质单子要么打电话催维修师傅上门之后也没人记录到底修没修、什么时候修完的。而一个管理系统要做的就是把“学生报修、维修工接单、管理员派单、维修完成、学生确认”这一条业务链路搬到线上让所有环节可跟踪、可追溯、可统计。这种系统为什么用SpringBoot Vue来写因为这两个框架是目前Java Web毕设的主流搭配。SpringBoot负责后端接口和业务逻辑Vue负责前端页面展示和用户交互前后端通过RESTful API通信再配上MySQL存数据、Swagger出接口文档一套标准的“前后端分离”项目就齐了。做这个项目的人要么是计算机科学与技术、软件工程专业的本科生要么是正在职提升的Java开发学习者目标是搭一个能跑、有页面、能演示的完整系统。从标题来看这个项目赠送的附件很明确完整项目源码前端Vue后端SpringBoot、SQL脚本初始化数据库、接口文档给前后端对接或答辩展示用。这三样东西凑在一起意味着它不只停留在“能跑”的基础层面而是尽量往“可交付、可演示、可答辩”的方向靠拢。我拿到这个标题后先把它拆成了几条关键技术线和业务线分别梳理。接下来这篇文章我不打算只讲“怎么下载源码然后跑起来”这种流水账而是把整个系统从头梳理一遍包括业务设计、数据库建模、后端接口设计、前端页面结构以及我在做这类项目时踩过的坑和总结出的加分技巧。准备做宿舍维修管理系统或类似管理类毕设的同学可以直接把这套思路套进去用。2. 系统的技术骨架与业务边界2.1 功能模块先从需求说起动手写代码之前最重要的一步是先把“系统要做什么”理清楚。宿舍维修管理系统的核心用户有三种角色学生、维修工、管理员。不同角色看到的东西、能做的事情完全不同这也是这类系统设计时第一个要明确的点。先说学生端。学生是报修的发起点他需要的功能是最直观的发起报修填宿舍号、问题描述、上传照片、查看自己报修单的进度待派单、维修中、已完成、对完成的维修单进行确认或评分。这里要注意学生的身份信息应该和宿舍房间绑定这样管理员派单时才能快速定位到具体地点。维修工端是接单和执行的角色。维修工登录后能看到分配给自己的报修单可以更新维修状态开始维修、维修完成可以填写维修备注和所用材料。有些系统还会加上工时记录和材料费用登记方便月底统计工作量。这里有一个容易被忽略的需求维修工通常不止一个人派单时需要考虑“谁有空、谁负责哪个区域”所以维修工应该有一个“负责区域”或“所属楼栋”的概念。管理员端是最重的角色。管理员负责整个流程的管理维护宿舍楼栋房间信息、创建维修工账号并分配区域、查看所有报修单、手动派单或自动派单、按时间/楼栋/类型查看统计报表。管理员还要管理一些基础字典数据比如维修类型水、电、木工、网络等、报修优先级普通、紧急、维修状态枚举值。这些看似琐碎的配置实际上决定了系统的灵活度和演示效果。另外还有一个容易被忽视的角色宿管阿姨或值班室。这一步实际项目中经常合并到管理员权限里或者单独给一个只读权限的账号。毕设阶段一般不做这么细但在论文的“功能需求分析”章节里可以提一嘴说明你考虑到了场景多样性这对论文查重降重和答辩加分都有帮助。2.2 核心业务流程串起来看需求理清之后要把业务流程串成闭环。整个系统最核心的一条链路是学生发起报修 → 生成报修单状态待派单 → 管理员审核并派单状态已派单 → 维修工接单并维修状态维修中 → 维修工标记完成状态待确认 → 学生确认完成并评价状态已完成这套流程里最关键的几个设计点在于第一报修单状态机的定义。千万不要把状态做成自由文本而应该用固定的枚举值因为有状态流转才能做统计、筛选和防呆。比如学生提交后状态是“待派单”如果管理员一直没处理应该在前端有提示如果维修工长时间没有接单管理员可以重新派单。状态流转一旦清晰前后端联调时的沟通成本会大幅降低。第二派单逻辑的设计。最简单的方式是管理员在后台看报修列表手动选择维修工。稍微进阶一点的做法是系统根据维修工所属楼栋和当前待处理工单数量自动推荐维修工。做毕设的话手动派单已经完全够用但如果你想把系统做成“亮点”可以在派单页面加一个“推荐维修工”的字段显示各维修工的待处理单量哪怕只是查询出来展示也足以体现你的思考深度。第三整个流程的可追踪性。每一步操作都最好记录时间和操作人这样答辩时老师说“你怎么证明这个人修过单”你可以直接打开报修单详情页展示时间线几点提交、几点派单、几点开始维修、几点完成、几点确认。这一设计逻辑其实是在模拟现实工单系统的审计需求做出来之后整套系统的专业感立刻就上来了。很多同学做这类系统容易掉进一个陷阱把页面做得很花但业务逻辑没打通。比如学生提交了报修就结束了后台看不到状态变化维修工不知道怎么更新进度。这种系统看起来功能很多实际上是个半成品。所以我在搭建整个系统前会花大量时间先把状态流转图画清楚、把每个角色在每个状态下的操作权限写清楚然后再去建表写代码。这条经验无论做宿舍维修系统还是做图书管理、设备管理系统都是通用的。3. 核心技术选型与原因拆解3.1 后端为什么选SpringBootSpringBoot在Java Web毕设里统治级的存在几乎不需要过多解释。但如果你在技术选型答辩时只回答“因为SpringBoot方便、流行”那太单薄了。你需要从几个维度来说明你选它的理由。第一是自动装配机制。SpringBoot通过starter依赖和自动配置大幅减少了Spring传统开发中的XML配置。对比一下老Spring项目要配dataSource、transactionManager、sqlSessionFactory要写一堆XMLSpringBoot把这些都封装好了你把依赖加进去配置文件里写几条连接信息就能跑起来。这对毕设这种“时间紧、任务重”的场景非常友好。第二是生态成熟度。SpringBoot集成了SpringMVC、MyBatis/JPA、Security、Validation等组件做楼宇信息管理、报修工单流转这种典型CRUD 状态机项目需要的所有能力都有现成方案不需要自己造轮子。比如参数校验直接用Validated注解权限控制用拦截器或Spring Security日志记录用Slf4j这些都是简历上能直接写的东西。第三是部署简单。SpringBoot内置Tomcat打包成jar就直接运行不需要单独装Tomcat服务器配置war包。对毕设演示来说一个java -jar命令把后端跑起来相比传统方式省了至少半小时的环境安装时间这对答辩前的紧张准备阶段帮助极大。配套的持久层框架推荐MyBatis-Plus而不是传统MyBatis原因也很实际单表CRUD可以直接用内置的BaseMapper不用手写XML分页查询用分页插件一行搞定条件构造器让动态查询变得非常直观。宿舍维修系统里大量单表查询按楼栋查报修单、按状态查工单、按维修工查任务用MyBatis-Plus能把开发效率提升一个档次。3.2 前端为什么选Vue前端选Vue的理由同样要能说清楚。Vue的核心优势是响应式数据绑定和组件化开发。响应式数据绑定的价值在于页面上的列表数据、状态标签、操作按钮全部由data中的数据驱动。后端返回的报修单状态是“维修中”页面上自动显示对应的黄色标签和“标记完成”按钮状态变成“已完成”按钮自动消失显示评价信息。这一切不需要手动操作DOM只需要更新data对象Vue会响应式地重渲染视图。这在传统jQuery时代是要写大量DOM操作代码的Vue把这部分复杂度抹平了。组件化开发的价值在于头部导航栏、侧边菜单、状态标签、分页组件、图片预览弹窗这些模块可以抽成独立组件在多个页面里复用。比如报修状态标签这个组件在报修列表、报修详情、个人中心三个地方都要用写成组件后传一个status值进去即可在不同页面保持一致的展示效果。Vue的版本选择上我更推荐Vue 3 Element Plus而不是Vue 2 Element UI。原因是Vue 3的Composition API在逻辑组织上更清晰Element Plus组件库从设计上更现代化而且现在市面上的新项目基本都切到Vue 3了。虽然Vue 2的教程资料更多但你现在做毕设用Vue 3等到六个月后找工作面试时你聊的至少是当前主流技术不会给人“还在用旧技术栈”的感觉。3.3 通信与数据层前后端分离项目的通信方式主流方案是RESTful API对接。后端的Controller层暴露HTTP接口前端用Axios发起请求JSON作为数据交互格式。这套模式很成熟但有几个细节值得注意。一个细节是统一接口响应结构。后端每个接口返回的JSON格式应该保持一致比如都包含code、message、data三个字段。为什么因为前端Axios拦截器可以统一处理code为200时正常返回数据code为401时跳转登录页code为500时弹出错误提示。如果不统一每个接口单独写一遍错误处理逻辑前端代码会非常丑陋还容易出现遗漏。另一个细节是跨域问题。前端跑在8080端口后端跑在8081端口浏览器默认会拦截这种跨源请求。后端的解决方案一般是在SpringBoot的WebMvcConfigurer里配置CorsMapping把允许的来源、请求头、请求方法都放行或者加一个CrossOrigin注解到Controller上。要注意的是如果你用了Spring Security还需要确保跨域配置和Security的过滤链顺序不冲突否则会出现前端请求都到不了Controller就报跨域错误的情况。数据库选型方面MySQL依然是首选。宿舍维修管理系统数据量不大MySQL完全够用而且它的DDL、DML语法通用性最强SQL脚本可以随手在Navicat或命令行里执行。有同学问要不要用PostgreSQL我的建议是除非你论文里特意要写“采用PostgreSQL的JSONB字段存储扩展信息”这种差异化设计否则不要折腾MySQL对你的时间更友好。3.4 接口文档从Swagger到Apifox这个项目的标题里特别强调了“接口文档”作为交付物这一点我个人很认可。接口文档不只是给答辩老师看的更是能体现工程化的核心产物。很多同学自己写的接口自己清楚但过两周再看就忘了参数含义前后端联调时全靠猜效率极低。我经常推荐的方案是后端集成SpringDocOpenAPI 3规范或者SpringfoxSwagger 2在Controller和实体类上写注解启动后打开/swagger-ui.html页面就能看到所有接口的定义、参数说明、响应结构甚至可以直接在线调试。SpringBoot 2.6以上版本用Springfox容易遇到路径匹配策略冲突的问题SpringDoc在这方面要稳定得多推荐直接用SpringDoc依赖是springdoc-openapi-ui。如果你觉得Swagger在线调试不够顺手可以再配一个Apifox或Postman。Apifox的优势是可以直接导入Swagger的JSON文档把接口同步到本地然后通过接口调试、Mock数据、自动化测试一整套工具链管理接口。我在写接口文档步骤时会优先做Swagger注解然后导出OpenAPI JSON再导入Apifox生成界面友好的文档。这条路走通了之后前端对接时直接把Apifox链接发过去自己就能测接口不用反复找我询问参数含义。4. 数据库设计与SQL脚本编写要点4.1 核心表结构与关系有了业务流和技术选型下一步就是建表。数据库设计的好坏直接决定整个系统的代码复杂度和扩展性。我用最精简的版本给你拆一遍宿舍维修系统的表结构。第一张表是用户表user存放所有能登录系统的人学生、维修工、管理员。字段上我会设计为id、username、password密文存储、real_name、phone、role枚举STUDENT/WORKER/ADMIN、status。用户表是权限系统的基础role字段决定了登录后进入哪个端。这里不建议为不同角色分别建三张表因为登录逻辑、密码校验完全一样区别只在页面展示和接口权限上。当然如果你做的是更复杂的系统把角色单独拆成角色表、权限表但毕设阶段一个role字段就够用了写论文的时候可以提一句“考虑到角色规模小采用字段标识而非RBAC模型”。第二张表是宿舍楼栋表dormitory字段包括id、name、address、floor_count、remark。这块的粒度取决于管理员的管理方式。常见做法是只建一张楼栋表管理员创建楼栋后再建一张房间表room房间归属于楼栋房间字段包括楼栋id、房号、床位容量、已住人数。为什么要拆二楼因为报修单最终要关联到“哪个楼栋哪个房间”如果只存楼栋和房间号字符串后期做统计时关联查询会比较别扭。第三张表是报修单表repair_order这是整个系统的核心表。字段设计如下id、order_no工单号冗余一个业务编号方便展示和查找、student_id关联用户表、room_id关联房间表、repair_type维修类型、description问题描述、images报修图片存JSON数组或逗号分隔的URL、status状态枚举、priority优先级、assignee_id维修工ID、assign_time派单时间、start_time维修开始时间、finish_time完成时间、student_confirm_time学生确认时间、rating评分、remark备注。这一步有一个常见的争论点把维修工ID直接放在报修单表里还是建立一个单独的“派单表”。如果维修工只能一对一维修直接冗余assignee_id更高效如果一次报修可能涉及多个维修工比如水电两个工种协同那就要建报修单-维修工关联表。宿舍维修系统一般一对多场景较少我建议直接冗余一个assignee_id字段查询时一次join拿到维修工姓名代码简洁明了。至于“一次派多个人”的场景可以在论文的“系统扩展方向”里提表明你考虑到了。第四张表是操作日志表operation_log记录报修单从创建到完成的每一次状态变化操作人、操作类型、操作时间、备注。这张表不参与业务逻辑只作为追踪和审计的数据来源。有了它报修单详情页就可以渲染一条时间线学生在前端看到“提交报修→管理员已派单→维修工张三开始维修→维修完成”等动态记录整个系统的可信度一下子就上去了。除了上面四张核心表还可以根据需求补充通知公告表announcement、维修类型字典表repair_type_dict、评价表rating_record。评价我建议直接冗余到报修单里的rating字段不用单独建表减少联查复杂度。4.2 SQL脚本书写的避坑指南标题里明确提到“SQL脚本”是交付物之一所以创建数据库的SQL脚本要写得足够规范。这里有几个细节值得注意。第一所有表必须有主键建议用AUTO_INCREMENT的自增主键。有同学喜欢用UUID做字符串主键但如果表之间有关联UUID会带来大量的字符串比较索引效率不如bigint。毕设阶段统一用自增主键最简单实用。第二表名和字段名用下划线命名法比如repair_order、assignee_id、create_time别用RepairOrder这类驼峰。原因很简单MySQL在Linux环境下大小写敏感驼峰命名在跨环境部署时容易埋坑。Java代码里通过MyBatis-Plus的map-underscore-to-camel-case配置可以自动把下划线字段映射成驼峰属性两边规范并不会冲突。第三每张表都必须有create_time和update_time字段这是不可省的“审计字段”。是否有update_time答辩老师看一眼表结构就能判断你有没有工程经验。表格设计规范一些给后续统计报表查询留下了时间维度。第四SQL脚本里明确写好建库语句和初始数据。比如CREATE DATABASE IF NOT EXISTS dorm_repair DEFAULT CHARACTER SET utf8mb4;然后USE dorm_repair;再建表。初始化数据要包含一个管理员账号admin/admin123密码存密文、几个测试学生账号、几个维修工账号、几条状态不同的报修单数据。为什么要预先塞数据因为答辩演示时你不可能当场注册一个新学生、提交一个报修再走完整个流程太浪费时间。有预置数据打开系统就能看到列表和统计图表展示效果完全不一样。第五如果你用MyBatis-Plus创建时间字段可以开启自动填充功能在字段上加TableField(fill FieldFill.INSERT)然后在MetaObjectHandler实现类里统一设置这样插入时不用手动写setCreateTime。这个细节看着小但能省下大量重复代码而且让代码看起来更整洁。4.3 状态枚举与字段值设计报修单的status字段我建议用一个varchar类型存英文代码PENDING待派单、ASSIGNED已派单、IN_PROGRESS维修中、PENDING_CONFIRM待确认、COMPLETED已完成。不直接存中文的原因很简单前后端通过JSON交互时英文代码更稳定中文文案可以交给前端根据枚举映射表统一翻译比如“PENDING→待派单”。同样的思路适用于repair_type用PLUMBING水、ELECTRIC电、CARPENTRY木工、NETWORK网络、OTHER其他。这不仅方便前端下拉框渲染也方便做统计报表的group by。很多同学在枚举设计上容易有一个坏习惯用数字0、1、2、3做状态值。这个在接管他人代码时会非常困惑1到底代表已完成还是待派单虽然你自己清楚但答辩老师或接手你代码的人看着就会头疼。所以用有语义的英文代码在代码可读性上是彻底的提升。我在自己项目里后端会写一个枚举类RepairOrderStatusEnum统一提供code和description的映射前端的路由和标签颜色也用同一套枚举定义这样状态流转逻辑前后端保持一致不会出现“前端显示已完成后端统计却是未完成”之类的低级错误。5. 后端接口设计与实现细节5.1 接口层面的规范设计后端Controller的接口设计要遵循RESTful风格但也不要为了形式主义过度设计。宿舍维修系统的核心接口清单大概如下学生端POST /api/student/repair/apply提交报修GET /api/student/repair/list查看自己提交的报修单列表GET /api/student/repair/detail/{id}查看报修单详情POST /api/student/repair/confirm/{id}确认完成管理员端POST /api/admin/user新增用户学生/维修工PUT /api/admin/user/{id}编辑用户DELETE /api/admin/user/{id}删除用户GET /api/admin/repair/list查看全部报修单支持多条件筛选GET /api/admin/repair/detail/{id}查看详情POST /api/admin/repair/assign手动派单GET /api/admin/statistics/overview看板统计接口维修工端GET /api/worker/repair/list查看分配给自己的维修单POST /api/worker/repair/start/{id}开始维修POST /api/worker/repair/finish/{id}完成维修这套接口已经覆盖了系统的核心功能整体数量控制在十个出头毕业论文里完全写得出结构清晰的接口设计表格。接口的统一返回体设计成Result 结构包含code、message、data三个字段。所有接口直接返回Result.success(data)或Result.error(消息)由全局异常处理器统一兜底。这里关键点在于数据库操作抛出的异常Services层尽量不要把原始异常堆栈直接抛给前端而是转成业务流程上可读的错误提示例如“该报修单已被处理请刷新查看”避免用户看到一堆看不懂的MySQL英文报错。另外一个必须做的是参数校验。比如发起报修的接口在DTO类上用NotBlank、Size等注解声明校验规则Controller方法的参数加上Validated注解校验不通过时会抛出MethodArgumentNotValidException由全局异常处理器接收后返回友好提示。这一套写下来代码量和配置量都很小但在答辩“系统健壮性”上是实打实的加分项。5.2 登录鉴权方案怎么选登录鉴权是每个Web系统躲不开的环节。我强烈建议这一部分认真考虑JWT方案而不是简单的session。虽然毕设规模小用session也完全够跑但使用JWT有两个明显的实际收益。第一前后端分离时后端不需要依赖session存储天然契合无状态API风格前端拿到token后放进请求头后端每个请求都可以通过拦截器快速校验。这样你不需要在Spring Boot中额外配置session共享、跨域cookie等一堆麻烦问题。第二简历面试时聊到认证机制时能聊出JWT的结构header.payload.signature、为什么用HS256签名、token过期时间怎么设计、刷新令牌机制等深度内容更容易展示自己的技术理解。实现上我会用jjwt库在拦截器里统一做token校验。策略很简单登录成功时签发token返回给前端前端每次请求在Authorization请求头里带上token后端写一个JwtInterceptor在preHandle里解析token把当前登录用户的ID和角色塞进ThreadLocal或RequestAttribute遇到token缺失或过期则直接返回401由前端统一跳转到登录页。要注意的一个安全细节密码不能用明文存数据库。在用户注册或创建用户的时候用BCrypt加密再存储登录时用BCrypt校验。Spring Security自带BCryptPasswordEncoder但你如果不想引入整个Spring Security做权限控制毕竟拦截器角色判断已经够用可以单独引入spring-security-crypto这个轻量依赖单独使用密码加密功能避免多余的安全框架配置。5.3 核心接口场景的代码思路以“学生提交报修管理员派单”这个组合场景为例我把典型实现逻辑展开来说大家可以直接参考。学生提交报修的Controller接口大概是这样读取当前登录学生ID从token解析出来的用户ID组装RepairOrder对象设置状态为WAITING_ASSIGN设置order_no为时间戳加随机数拼接的唯一编号设置room_id为学生绑定的房间ID从学生基础信息中查出。保存到数据库后返回报修单ID并附带一条提示“报修已提交请等待管理员派单”。这里有几个容易被忽略的细节截图上传。很多同学在报修功能上纠结“图片到底怎么传”最简单的方案是用OSS对象存储但OSS需要开通服务、配置密钥对毕设来说折腾且费时间。我的建议是图片上传接口先做一个本地文件存储的方案后端接收MultipartFile保存到服务器某个目录下如/usr/local/upload生成访问URL比如http://localhost:8081/files/xxxx.jpg返回给前端存储。只要把静态资源映射配置好就行。这一个细节能让你在答辩时展示“图片上传逻辑”的前后打通功能完整度提升很大。管理员派单的逻辑也差不多管理员在报修单列表点击“派单”弹出一个对话框选择维修工下拉选项里显示未离职的维修工然后调用派单接口。后端在派单接口里更新报修单的assignee_id、assign_time、status为ASSIGNED状态同时向operation_log表插入一条派单记录。这里顺便可以做一个小优化页面下拉框旁显示维修工“当前待处理单量”让管理员能合理选择派单人选我前文已经提过这个细节做起来不复杂属于性价比很高的加分项。我在实际开发中还有一个体会这类系统的接口代码其实并不复杂真正容易出问题的地方在于多角色、多状态下“谁可以操作什么、不能操作什么”的权限校验。所以我会把每个操作接口的开头都写清楚一句话校验逻辑“当前用户是否为该单的负责人”“该单当前状态是否允许此操作”哪怕多两行代码系统的安全性也能提升一大档。6. 前端Vue项目的结构与关键页面实现6.1 前端项目的目录组织前端项目如果用的是Vue CLI或Vite构建标准目录结构大概是这样的src/api存放所有接口调用封装按业务模块拆分如repair.js、user.js、statistics.jssrc/router路由配置定义每个页面路径和组件并配置路由守卫控制页面访问权限src/views页面组件按角色分目录如admin、student、worker每个角色目录下放自己的页面src/components公共组件如状态标签组件、图片上传组件、分页组件、时间轴组件src/utils工具函数如请求封装、token读取、时间格式化src/store如果是Vue 3 Pinia可以放全局状态如登录用户信息、菜单展开状态这层目录设计虽然看着很简单但很多新手项目一上来就是把所有代码往App.vue和Home.vue里堆最后页面互相耦合得没法维护。一个结构清晰的前端目录既是给自己省事也是给答辩老师留下“这是一个懂工程化的项目”的印象。6.2 路由与菜单权限控制的位置前端权限控制的核心思路是路由守卫。用户登录成功后后端返回用户的role信息前端根据role来决定可见的菜单和可访问的路由。最简单的做法是在路由配置里给每个需要权限的路由加meta: { roles: [ADMIN] }然后在全局前置守卫里判断没有token就跳登录页有token但当前路由的roles不包含当前用户角色就跳403页。注意不要只做菜单隐藏不做路由拦截。有些项目只在侧边菜单里按角色隐藏了入口但用户直接在地址栏输入其他角色的路由地址照样能访问页面这种漏洞答辩时被问到会很尴尬。路由守卫对每个访问做判断才是完整的权限控制。再往深走一步按钮级别的权限控制。比如说学生页面里有一个“确认完成”按钮只有当前报修单状态为待确认且属于当前学生时才显示管理员的“派单”按钮也是一样状态不对时按钮置灰。这些控制在Vue里可以写成父子组件传值配合状态判断也可以抽取一个权限指令来统一控制。毕设阶段用v-if配合角色判断已经足够清晰不需要额外引入vue-permission插件。6.3 核心页面设计与实现细节宿舍维修管理系统的前端页面不算多核心页面大约六到七个登录页、学生报修页、学生报修列表页含详情弹窗、管理员报修管理页带筛选和派单、管理员用户管理页学生和维修工的增删改查、维修工任务中心页、管理员数据统计页。登录页的设计建议简洁一些背景图加卡片式表单毕竟毕设的核心不是美术设计把界面做干净清爽就ok了。这里最容易踩的坑是表单校验不做用户直接输入空用户名就点击登录。Vue Element Plus的表单自带校验规则配置好required和trigger属性就能轻松搞定。报修列表页是比较核心的页面。前端要支持多条件搜索按楼栋、按状态、按维修类型、按时间范围、按关键词工单号。搜索条件传到后端通过MyBatis-Plus的QueryWrapper动态拼接SQL。前端这块用Element Plus的el-form做了搜索栏el-table做了数据列表。注意操作列不要过于拥挤每行动态展示操作按钮管理员看到“派单”“详情”维修工看到“开始处理”“完成维修”学生看到“确认完成”“评价”“详情”。数据统计页是体现系统价值的页面。这里的统计口径要明确按状态的报修单数柱状图、每周报修趋势折线图、各楼层报修占比饼图、维修工工作量排行横向条形图。ECharts在这块完全足够不要把echarts的饼图柱状图当成很复杂的操作掌握了它统计报表的表现力能上一个台阶。统计接口在后端用group by count做聚合查询返回给前端渲染图表。这个页面做出来后演示时是很有冲击力的部分。6.4 Vue项目打包并整合进SpringBoot标题里的一个核心操作是“把Vue打包放进SpringBoot”这也是很多同学在部署环节卡住的地方。这个需求本质上就是前端构建产物dist目录放到SpringBoot的静态资源目录下让后端一个应用直接把前后端都跑起来。操作步骤如下第一步前端项目根目录下执行npm run build生成dist目录里面是index.html和静态资源文件。第二步把dist目录里的内容复制到SpringBoot项目的src/main/resources/static目录下或者通过Maven的插件配置把构建过程绑定。前者更适合毕设后者更适合工程化项目。第三步启动SpringBoot后浏览器直接访问localhost:8081/如果配置正确SpringBoot会优先查找static目录下的index.html前端页面就出来了。这个方案下有个大坑Vue使用vue-router的history模式时访问页面内部的深层路由如/student/repair刷新页面会出现404。为什么因为是前后端分离的SPA应用刷新时浏览器向服务器请求了这个路径而后端没有对应的Controller来处理它。解决方案有两个最简单的是把路由改用hash模式URL会带#号有点丑但稳另一个是后端写一个转发规则把所有非API的路径转发到index.html这个稍微复杂一些推荐毕设阶段直接采用hash模式把风险降到最低。7. 从零搭建到演示复盘的实操录7.1 开发环境的确定版本进入实操阶段先明确开发环境。毕设项目最怕环境版本不一致复现时一堆莫名其妙的问题。我会推荐一套经过验证的稳定版本组合JDK1.8或11。SpringBoot 2.7系列的兼容性最好JDK 8完全够用。如果你非要上新版本SpringBoot 3.x那必须用JDK 17别匹配错了。MySQL5.7或8.0。8.0的认证插件坑比较多如果用8.0连接url里要加allowPublicKeyRetrievaltrue。Node.js16.x或18.x。Vue 3 Vite构建Node 18最稳。Maven3.8.x。IDE后端IntelliJ IDEA前端VSCode或WebStorm。建议两个都装各写各的。版本统一是构建环境时最容易被忽略的阻力。每年都有同学在群里问“为什么我启动报错明明照着教程做的”十有八九就是版本不一致导致的。建议准备项目时写一个README.md把你验证过的版本组合写清楚这也是一份“可直接交付”的关键工程素养。7.2 阶段一后端骨架第一步用Spring Initializr创建一个SpringBoot项目勾选Spring Web、MyBatis、MySQL Driver、Validation依赖。这里有个小建议groupId用com.example这类默认没问题artifactId建议用dormrepair这种有业务含义的名字后面代码里的包名就会对应cn.edu.dormrepair之类看着专业些。第二步application.yml里配置数据源、MyBatis-Plus、文件上传路径、端口等。端口我建议设置8081而不是默认8080原因是前端Vite开发服务器默认也是8080如果后端占用8080前端启动时会提示端口冲突很烦。第三步搭全局异常处理和统一返回结构。这一步放在写业务代码之前因为后续所有Controller都要依赖它们。全局异常处理器用RestControllerAdvice注解处理三类异常业务异常自己抛的BizException、校验异常参数校验失败、兜底异常记录日志后返回系统繁忙。业务异常的设计这里多说一句我习惯自己定义一个BizException然后一个ErrorCode枚举存错误码和默认错误信息比如报修单不存在、状态已变更等。这样Service里遇到不能继续执行的场景直接throw new BizException(ErrorCode.ORDER_STATUS_ERROR)在调用链路上统一被捕获并返回代码简洁且逻辑可追踪。第四步先写实体类和Mapper把对应表映射出来。用MyBatis-Plus注解TableName指定表名TableId(type IdType.AUTO)指定主键策略。7.3 阶段二后端业务代码后端业务代码按模块来写不推荐一次性写完所有接口。我的习惯是先学生端再管理员端再维修工端最后统计接口。写学生端的“提交报修”时需要同时完成前端需要的接口文档和JSON结构定义。这里养成一个好习惯所有时间字段传递给前端时统一格式化为字符串如yyyy-MM-dd HH:mm:ss不要在JSON里裸放Date对象否则前端拿到的是时间戳或者奇怪的对象展示时又要二次转换。写管理员端时重点维护好分页查询的参数。MyBatis-Plus的分页查询需要先注册PaginationInnerInterceptor到MybatisPlusInterceptor里然后业务代码用Page 类型接收pageNum和pageSize参数。分页查询条件可以封装为QueryParams对象里面有楼栋ID、状态、关键字、时间范围等Service层用LambdaQueryWrapper动态拼接。这个过程建议顺手写一个“条件构造器封装工具类”避免每个Service里重复构造QueryWrapper逻辑。写维修工时要加入“校验状态”逻辑维修工只能操作assignee为自己且状态为ASSIGNED的工单开始维修时设置start_time为当前时间完成时设置finish_time并且要求必须填写维修结果说明才能提交。这些校验写在Service层里不要写在Controller层保持Controller薄而Service厚。统计接口是很多同学最后憋不出来的部分。建议设计三个聚合SQL状态分布统计select status, count(*) from repair_order group by status、近七周工单趋势用create_time按周分组、维修工工作量排行按assignee_id分组统计数量并join用户表取姓名。这三个查询用XML或者Mapper层的Select注解实现都可以注意group by结果要用单独VO接收不要试图塞进有复杂嵌套的实体类。7.4 阶段三前端功能页面前端这里可以按下面的顺序开发先搭项目骨架Vite Vue 3 Element Plus Vue Router Pinia然后封装Axios请求工具再写登录页和登录逻辑之后依次写各角色页面。Axios请求工具封装是前端的核心环节。统一设置baseURL为/api请求拦截器里读取localStorage中的token并加到请求头响应拦截器里统一处理code字段——401跳登录页清除token500提示服务端异常200直接返回data。这样所有业务代码只需要关心接口返回的业务数据不需要每处重复处理异常场景。登录页和路由守卫可以在一天内完成这是整个前端快速迭代的基础。接着写学生端和管理员端的页面。写页面时建议有顺序意识先做“列表页的查询条件数据表格分页器”这个模板一旦成型后面所有列表页都能复制修改写起来会越来越快。提一个前端常见踩坑点Element Plus的el-select组件选项是用数字作value还是字符串作value如果你的后端接收的是String枚举代码就统一用字符串如果字段类型是数字就统一转成Number。前后端类型不一致时表单提交后在校验或比较环节容易莫名其妙报错花的时间比写代码还多。从一开始就约定好前后端字段类型能省掉大量联调时间。7.5 阶段四联调、构建与演示彩排联调是整个项目里最容易拖节奏的环节。我的经验是“先约定后写码”在写界面之前先把所有接口的出入参用Swagger定义好双方按这个定义同步开发。前端遇到不明确的字段先去Swagger页面查看后端接口有调整也一定要同步更新Swagger描述。这样联调时大部分接口第一遍就能通而不是你来我往地调整各种字段名和类型。联调完成后按前面的方法把前端打包进SpringBoot的static目录。跑一次端到端演示从管理员登录创建测试学生和维修工账号学生登录提交报修单并上传一张维修现场图片管理员登录派单维修工登录接单并完成学生确认完成并评价。这套流程完整走下来基本保证演示时不会出错。彩排过程中还经常会遇到一个小问题刷新页面后token过期接口返回401但前端没有跳转登录页。很多情况是在响应拦截器里的跳转逻辑写在了业务代码里导致401没有统一处理。规范做法是在拦截器里捕获401直接清localStorage并跳转/router/login。这个细节看起来事小但演示时如果突然掉链子非常影响观感。8. 常见问题排查与避坑清单8.1 启动阶段的五个高频报错第一类Bean创建失败。这类错误多半是启动时某个依赖注入不成功背后原因通常是Service类忘记加Service注解或者Mapper接口没有加MapperScan扫描。排查思路看启动日志中报错提到的类名去对应目录里检查注解。第二类MySQL连接失败。报错信息一般有Access denied大概率是账号密码错误或host配置不对。解决方法是检查application.yml中的url、username、password注意url中的数据库名不能写错。第三类端口被占用。启动日志提示Port 8081 was already in use在命令行执行netstat -ano | findstr 8081查看占用程序然后释放端口或用其他端口启动。这个情况几乎每个人都会遇到优先级比较高。第四类前端npm依赖安装失败。出现这种问题一定要先检查Node.js版本其次看看有没有严格的代理或镜像源问题。如果用的是npm官方源在国内环境下网络经常不稳定建议换成淘宝镜像源即npm config set registry https://registry.npmmirror.com。第五类MyBatis-Plus分页不生效。用了分页插件后查询结果是全量数据原因通常是PaginationInnerInterceptor没有注册。检查MybatisPlusInterceptor的Bean是否存在并确认分页插件加入的顺序。常见做法是加上Configuration实现一个配置类在里面注册拦截器。8.2 接口开发阶段常见错误接口开发时最常见的是状态流转逻辑遗漏。比如学生提交了报修单但管理员误把单派给某个维修工维修工开始维修后管理员又想改派一个人——此时到底允不允许为了屏蔽这种争议我会在设计文档里明确状态流转矩阵只有待派单状态可以被管理员改为已派单已派单状态只能由维修工改为维修中维修中只能由维修工改为待确认待确认只能由学生改为已完成。任何一个不符合流转规则的接口操作后端一律拦截并返回“当前状态不允许此操作”的错误。另一个常见错误是SQL注入隐患。虽然MyBatis-Plus的QueryWrapper已经做了参数化的防注入处理但如果有人为了追求方便写了“select * from repair_order where order_no 拼接字符串”这种原始SQL就非常危险。正确的做法是始终使用参数占位符#{orderNo}不要随便用${}除非你想把列名或排序字段等非变量内容动态拼进去。还有一个交互层面的“坑”时间格式的不统一。前端展示报修时间数据库返回的可能是2024-05-01T10:30:00这种ISO格式也可能是后端自定义的“2024-05-01 10:30:00”如果没有统一格式前端表格里显示的示数可能对不上。建议后端在实体类的日期字段上加JsonFormat(pattern yyyy-MM-dd HH:mm:ss)注解统一输出格式前端再配合dayjs或moment做一次格式化兜底。8.3 答辩环节的经验附加题你在答辩时如果被问到“你这个系统能改进什么”不要张口就说“不知道”。比较好的回答是从安全性、性能和功能完整度三个方向展开。安全性方面当前JWT token过期时间固定可以考虑引入refresh token机制实现无感续期接口层面没有做细粒度的按钮权限控制可以引入Spring Security的PreAuthorize注解来按角色限制具体接口。性能方面当前的统计报表是每次请求都实时group by如果数据量达到十万级别可以考虑定时任务预处理把统计结果存入报表表前端读取更快。功能方面当前缺少消息通知机制学生提交报修后维修工看不到推送提醒如果引入WebSocket就可以实现“新报修单生成时实时提醒维修工”并附带未读消息数。这几个方向既能展现技术水平也都有成熟的落地路径写进论文“未来展望”里评委印象分会高不少。9. 小结与建议从拿到一个“SpringBootVue宿舍维修管理系统”的毕设标题到完整交付一套可演示、可上传、可答辩的项目我来来回回走过不少弯路也沉淀下不少经验。我的直观体会是这类管理系统的开发难点从来不在某个单一技术上而在于“如何把业务闭环打通并在细节上体现工程素养”。报表是否清晰、状态流转是否严格、错误提示是否有友好语义、接口文档是否团队可读——这些才是区分“能跑”和“做得好”的分界线。如果你准备照着类似项目来练手第一步建议先把业务流程图和表结构设计画出来再动手写代码。买了源码或找到某份开源项目也一样切忌直接导入数据库、运行、截几张图就去答辩。把表结构看懂、把状态流转理顺、把接口文档翻一遍这才叫消化学到了。完全靠惯性“交差”老师问一个“你怎么让维修工只看到自己的工单”你答不上来那才是真的尴尬。最后分享一个更为顺手的小技巧项目里彻底地写一份README文档内容包括环境版本、数据库初始化步骤、后端启动命令、前端启动命令、默认账号密码、以及可能遇到的环境坑。看起来是给自己备忘本质上是在锻炼交付意识。工作以后这个习惯会帮你减掉不少被反复咨询的情景这笔早期投入的性价比很高。
返回列表