ARTICLE DETAIL

资讯详情

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

基于Spring Boot+Vue的汽车维修保养管理系统设计与实现

基于Spring Boot+Vue的汽车维修保养管理系统设计与实现 每年到这个时间点总能看到一群计算机专业的大四学生被毕设折磨得焦头烂额。说实话Java方向的毕设选题翻来覆去就那么几类而基于Spring Boot Vue的管理系统绝对是出镜率最高、也最适合用来兜底的一类。我自己带过的学弟学妹里至少十个人做过类似的项目这次要聊的这套“汽车维修保养管理系统”算是在同类型题目里业务逻辑比较完整、又不会复杂到做不完的一个典型代表。先说清楚这个东西能做啥。它本质上就是一个典型的业务管理系统前端用Vue搭页面后端用Spring Boot提供接口数据库存业务数据。围绕“汽车维修保养”这个场景核心要解决的是车主信息、车辆档案、维修工单、保养提醒、配件库存、结算统计这一整条业务链路的管理问题。对毕设来说它的价值在于业务场景贴近真实生活、功能模块边界清晰、容易讲清楚设计思路再加上Spring Boot Vue这套技术栈本身就属于Java方向毕业生的“标配”无论是代码量还是答辩难度都比较可控。这套系统的受众很明确一是正在选题或者已经定题、需要从零搭建一个完整项目的计算机专业学生二是想快速了解Spring Boot Vue前后端分离项目怎么落地、怎么部署、怎么避开常见坑的同学三是那些时间紧、目标就是“能跑、能演示、能答辩”的务实派。下面我按自己实际做过的项目经验把这个系统从设计思路到核心代码再到部署上线一条一条拆开讲。1. 项目拆解这套系统的定位与设计思路1.1 为什么汽车维修保养管理系统适合做毕设选毕设题目有个很现实的逻辑业务不能太简单否则工作量不够但也不能太复杂否则做不完。汽车维修保养管理系统正好卡在了一个比较舒服的位置。从业务角度看它不是说只有一个“增删改查”那么简单而是天然带有一条完整的主线车主把车送来维修或者保养前台登记车辆和故障信息维修技师接单、领配件、填写维修记录完工后生成结算单最后形成收入统计。这个链条上下游清晰每个环节都有独立的数据实体和状态流转设计起来有东西可讲。从技术角度看它又不会难到让你做不出来的程度。车辆管理、工单管理、配件管理这些模块核心都是对数据库表的增删改查再配合一些关联查询和状态更新。唯一稍微有点门槛的是维修工单的状态流转、保养提醒的到期判断、以及统计报表的SQL聚合但也都在常规技术范围内。所以选这个题目的实际收益是业务故事完整、模块划分清楚、答辩时能从容讲出“系统解决了什么问题、为什么要这么设计”。比起那种一眼假的“XX管理系统”空壳它至少能让老师觉得你认真思考过业务。1.2 系统整体架构前后端分离到底怎么分这套系统采用的是目前主流的前后端分离架构。后端单独跑一个Spring Boot服务负责提供RESTful API接口、处理业务逻辑、操作数据库前端单独跑一个Vue工程负责页面展示、表单交互、调用后端接口两者通过JSON格式的数据交互。这种架构在毕设阶段最大的好处是职责边界非常清晰。你可以在同一个电脑上同时启动后端和前端两个服务开发时不用互相干扰。后端接口用Postman就能单独测试前端页面可以用Mock数据先调样式最后联调时再接真实接口。实际的工程结构大概是这样的car-repair-system/ ├── backend/ # Spring Boot 后端工程 │ ├── src/main/java/ │ │ ├── com/example/carrepair/ │ │ │ ├── controller/ # 接口层 │ │ │ ├── service/ # 业务逻辑层 │ │ │ ├── mapper/ # 数据访问层 │ │ │ ├── entity/ # 实体类 │ │ │ ├── config/ # 配置类跨域、拦截器 │ │ │ ├── common/ # 公共返回结果、工具类 │ │ │ └── CarRepairApplication.java │ │── src/main/resources/ │ │ ├── application.yml │ │ └── mapper/ # MyBatis XML文件 │ └── pom.xml └── frontend/ # Vue 前端工程 ├── src/ │ ├── api/ # 接口请求封装 │ ├── views/ # 页面组件 │ ├── router/ # 路由配置 │ ├── store/ # 状态管理 │ ├── utils/ # 工具类request封装 │ ├── App.vue │ └── main.js ├── package.json └── vue.config.js1.3 技术选型版本选择才是第一个坑技术栈看起来简单但选版本的时候如果不注意后面能踩出一连串坑。我建议的这套组合是经历过实践验证的稳定性优先技术组件推荐版本选型理由JDK1.8兼容性最好Spring Boot 2.x完美支持大部分学校的实验环境也是这个Spring Boot2.7.x2.x的最终维护版本稳定且资料最多别一上来就选3.xJDK版本要求高不说很多旧教程直接失效MyBatis-Plus3.5.x省去大量XML编写自带分页插件和条件构造器对赶毕设的学生党极度友好MySQL5.7或8.05.7兼容性最好8.0性能更好两者在JDBC连接配置上略有不同Vue2.xElement UI生态匹配度最高教程资源丰富Vue 3Element Plus上手成本稍高Element UI2.15.x快速搭建后台管理界面的首选Maven3.6依赖管理和项目构建Node.js14.x或16.x对应Vue 2项目比较稳定的版本过高版本可能编译报错这里单独说一下Spring Boot版本的问题。现在很多同学一搜教程就搜到最新的结果Spring Boot 3.x要求JDK 17起步而学校机器上装的是JDK 8一启动就报错来回折腾一天心态直接崩了。做毕设的黄金法则是项目能跑起来比什么都重要。Spring Boot 2.7.x JDK 8这个组合网上资料多、遇到问题能搜到解决方案而且完全不影响功能演示。2. 业务闭环与数据库设计实操2.1 角色权限三种角色怎么设计最合理维修保养系统的用户角色我见过很多人一上来就设计五六个角色结果自己都分不清楚。实际上对毕设这种规模的项目三种角色是最佳平衡点系统管理员拥有全部权限负责用户管理、员工管理、数据统计。登录后能看到所有模块的菜单。前台接待员也可以叫操作员负责登记车主和车辆信息、创建维修/保养工单、录入结算单。相当于业务入口。维修技师查看分配给自己的工单填写维修项目、领取配件、维护维修进度。相当于业务执行角色。权限控制的实现方式有几种对毕设来说没必要引入Spring Security JWT那一套复杂的东西太重了。我自己常用的做法是后端用拦截器 自定义注解简单控制在角色层面前端用路由守卫控制菜单显隐。具体来说后端在每个需要权限的接口上标注允许访问的角色拦截器统一校验当前登录用户的角色前端在路由配置文件里给每个页面标注meta.roles用户登录后菜单只渲染他角色允许的页面路由跳转时做拦截。这套方案代码量少、逻辑清晰答辩时完全能解释得通。2.2 核心数据表设计与字段取舍数据库设计是答辩时老师必问的高频区域。我整理这套系统中最关键的几张表和设计思路你可以直接对照着看用户表sys_user核心字段是用户名、密码MD5加密存储不用明文、真实姓名、手机号、角色ID。额外加一个状态字段启用/禁用比直接删除用户要好业务数据可以保持关联完整。车辆信息表car_info核心字段是车牌号、品牌型号、车主ID、购买日期、当前里程数、发动机号、车架号。当前里程数这个字段很重要保养提醒全靠它来计算。维修工单表repair_order这是整个系统的核心字段包括工单号、车辆ID、车主ID、接待员ID、维修技师ID、故障描述、维修项目、工单状态待派工/维修中/待结算/已完成、创建时间、完成时间。配件表parts_info配件编码、名称、规格、单价、库存数量、预警阈值。库存数量是动态变化的每次出入库都要更新。配件出入库记录表parts_stock_log配件ID、类型入库/出库、数量、关联工单ID、操作人、时间。这张表本质上是一张“流水账”用来追溯每一次库存变动。保养记录表maintain_record车辆ID、保养类型小保养/大保养、保养项目、保养里程、保养时间、下次保养里程、下次保养时间、工单ID。保养提醒就是靠这张表和车辆当前里程做比对。结算表settlement关联工单ID、配件费用、工时费用、总金额、支付状态、创建时间。设计这几张表时要特别注意有金额的字段不要用double用decimal时间字段建议用datetime而不是timestamp避免时区问题凡是多表关联的外键关系逻辑上要理清楚但物理外键可加可不加很多企业开发里反而会刻意不用物理外键把关联控制放在应用层。2.3 数据库设计时的几个关键细节和易错点第一工单号要设计成可读性强的格式比如“BX20240512001”表示保养BX加上年月日加上当天序号。这个用数据库自增ID当主键没问题但展示给用户看的业务编号要单独生成不能直接暴露主键。答辩时说出这个细节老师会觉得你想到了实际问题。第二保养提醒不能只查一次要每次登录后刷新判断。正确的逻辑是以车辆当前里程和最近一次保养记录的下次保养里程做对比当前里程大于等于下次保养里程时系统在首页提醒“该保养了”。这里要注意的一点是下次保养里程的计算方式一般是“本次保养里程 保养周期”不同车型周期不一样所以在保养记录表里要把保养周期也存下来。第三配件库存的并发问题。虽然毕设一般不会遇到高并发但设计时还是要考虑每次出库操作最好用UPDATE parts_info SET stock stock - #{count} WHERE id #{id} AND stock #{count}这种带条件更新的SQL来做避免超卖问题。这行代码放到答辩里讲属于加分项因为在真实项目中这叫乐观锁思维。3. 后端Spring Boot核心实现要点3.1 项目基础配置与pom.xml依赖清单Spring Boot项目的起步配置没什么玄学就是把该引的依赖引全。我的pom.xml里核心依赖是这些dependencies !-- Web 启动器 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MyBatis-Plus 启动器 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3/version /dependency !-- MySQL 驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency !-- Lombok 简化实体类 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependenciesapplication.yml里最需要注意的配置是数据库连接和MyBatis-Plus配置server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/car_repair?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 mybatis-plus: mapper-locations: classpath:mapper/*.xml configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印SQL调试时非常有用 global-config: db-config: id-type: auto注意几个细节MySQL 8.0的驱动必须是com.mysql.cj.jdbc.Driver旧版的com.mysql.jdbc.Driver会告警serverTimezoneAsia/Shanghai要加上否则数据库连接会报时区错误StdOutImpl日志配置在调试阶段务必打开它能让你看到MyBatis底层执行的每一条SQL语句。3.2 统一返回结果与登录鉴权后端的第一层地基我见过很多学生的项目每个接口返回的数据格式都不一致有的直接返回一个Map有的返回实体类前端对接时痛苦不堪。正确的做法是定义一个统一的返回类所有接口都走这个格式Data public class ResultT { private Integer code; private String message; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(操作成功); result.setData(data); return result; } public static T ResultT error(String message) { ResultT result new Result(); result.setCode(500); result.setMessage(message); return result; } }这样一来前端所有请求都是统一结构处理起来非常清爽。登录鉴权我推荐用最务实的方案LoginInterceptor Redis或不用Redis直接用Session。对毕设来说Session其实就够用了不必为了炫技引入Redis。核心逻辑是用户登录成功后把用户ID、用户名、角色存入Session定义拦截器在请求到达Controller前校验Session里有没有用户信息没有就返回401。Component public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); Object user session.getAttribute(user); if (user null) { response.setStatus(401); response.setContentType(application/json;charsetUTF-8); response.getWriter().write({\code\:401,\message\:\未登录或登录已过期\}); return false; } return true; } }然后注册到WebMvcConfig中指定哪些路径需要拦截、哪些路径放行Configuration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor) .addPathPatterns(/api/**) .excludePathPatterns(/api/user/login, /api/user/register); } }3.3 维修工单的状态流转怎么实现维修工单是整个系统的核心实体它的状态是动态变化的。一个工单从创建到完成要经历待派工 → 维修中 → 待结算 → 已完成。如果客户取消那还要走到已取消。这个用一段if-else写在Controller里也可以但我建议你在Service层抽出单独的方法用状态机的思路来做public boolean updateOrderStatus(Long orderId, Integer oldStatus, Integer newStatus) { // 只允许合法流转待派工(0)-维修中(1)-待结算(2)-已完成(3) // 任何状态都可以流转到已取消(4) LambdaUpdateWrapperRepairOrder wrapper new LambdaUpdateWrapper(); wrapper.eq(RepairOrder::getId, orderId) .eq(RepairOrder::getStatus, oldStatus); // 条件里带上旧状态防止并发覆盖 RepairOrder update new RepairOrder(); update.setStatus(newStatus); update.setUpdateTime(new Date()); return repairOrderMapper.update(update, wrapper) 0; }这里的精髓在eq(RepairOrder::getStatus, oldStatus)这一行。它的意思是只有工单当前状态确实等于预期值时才允许更新。这就避免了两个人同时操作一张工单时相互覆盖的问题面试和答辩时都可以拿出来讲。3.4 统计报表用一个SQL讲清楚分组聚合很多毕设的统计报表页面就是前端画个图后端接口随便返回几条假数据。这样虽然能蒙混过关但答辩时一问数据怎么来的就露馅了。正确的做法是后端写一个聚合查询接口。比如按月份统计维修收入GetMapping(/api/report/monthlyIncome) public ResultListMapString, Object monthlyIncome() { String sql SELECT DATE_FORMAT(create_time, %Y-%m) AS month, SUM(total_amount) AS income FROM settlement WHERE pay_status 1 GROUP BY DATE_FORMAT(create_time, %Y-%m) ORDER BY month DESC; ListMapString, Object list settlementMapper.selectMaps(new QueryWrapper()); return Result.success(list); }注意这里用了DATE_FORMAT函数把datetime转成“年-月”格式进行分组SUM求和总金额WHERE pay_status 1过滤掉未支付的记录。配合前端的ECharts折线图就是一个能讲课、能演示的完整功能模块。另外一个值得实现的报表是维修项目频次统计统计哪种故障最多、哪种保养项目最常做。这个需要从维修工单表里的维修项目字段做拆解统计SQL会复杂一点但配合ECharts的饼图展示效果非常好老师基本都会多看一眼。4. 前端Vue页面搭建与接口联调4.1 Vue工程结构和路由设计前端这一侧同样有讲究。Vue工程没必要用特别复杂的状态管理结构Vuex可以很轻量地管一个用户信息就够了。目录结构按模块划分即可src/ ├── api/ │ ├── user.js # 用户模块接口 │ ├── car.js # 车辆模块接口 │ ├── order.js # 工单模块接口 │ ├── parts.js # 配件模块接口 │ ├── report.js # 报表模块接口 ├── views/ │ ├── Login.vue │ ├── layout/Layout.vue │ ├── user/UserList.vue │ ├── car/CarList.vue │ ├── order/OrderList.vue │ ├── order/OrderDetail.vue │ ├── parts/PartStockList.vue │ ├── report/IncomeReport.vue │ ├── dashboard/Home.vue ├── router/index.js ├── store/index.js └── utils/request.js路由配置里基础的登录页和主布局是独立的其余所有业务页面都挂在Layout下面这样左侧菜单栏和顶部导航可以复用{ path: /login, component: () import(/views/Login.vue) }, { path: /, component: () import(/views/layout/Layout.vue), redirect: /dashboard, children: [ { path: dashboard, name: Dashboard, component: () import(/views/dashboard/Home.vue), meta: { title: 首页, icon: el-icon-home } }, { path: order, name: OrderList, component: () import(/views/order/OrderList.vue), meta: { title: 维修工单管理, roles: [admin, operator, tech] } } // 其他模块路由... ] }这里用了Vue Router的懒加载模式() import(...)意思是只有当访问到对应路由时才加载对应的组件文件这样首屏加载速度会好很多。这个细节写进论文或者答辩提一嘴也是个加分点。4.2 Axios封装与跨域前端联调的必修课前端最脏最累的活就是接口对接。我强烈建议把Axios实例封装成一个公共模块统一处理请求头、超时时间、错误提示和401跳转import axios from axios import { Message } from element-ui import router from /router const request axios.create({ baseURL: /api, timeout: 10000 }) // 请求拦截器自动携带Session凭证 request.interceptors.request.use(config { config.withCredentials true return config }) // 响应拦截器统一处理返回结果和异常 request.interceptors.response.use( response { const res response.data if (res.code 200) { return res } else { Message.error(res.message || 请求失败) return Promise.reject(new Error(res.message)) } }, error { if (error.response error.response.status 401) { Message.error(登录已过期请重新登录) router.push(/login) } else { Message.error(网络异常请稍后重试) } return Promise.reject(error) } ) export default request跨域问题的处理有两种常见方式。一种是在后端加CrossOrigin注解或者全局CORS配置另一种是通过前端vue.config.js里的devServer代理转发。我的建议是开发阶段用代理因为这样最省事// vue.config.js module.exports { devServer: { port: 3000, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } }这样前端请求/api/user/login时开发服务器会将它转发到后端的http://localhost:8080/api/user/login浏览器层面不存在跨域问题也就不需要后端额外配置CORS。上线部署时再用Nginx做统一反向代理前后端都同一个域名访问天然没有跨域问题。4.3 核心页面的实现要点表格、表单、时间线页面实现最核心的是工单管理页和首页看板。工单列表页的核心是一个搜索表格顶部是筛选条件工单号、状态、车牌号中间是数据表格底部是分页。Element UI的el-table和el-pagination组合就能搞定。关键是当你修改工单状态后要刷新当前页数据而不是跳回第一页这个小细节很容易被忽略。维修工单的详情页可以用el-steps来做状态时间线展示“待派工 → 维修中 → 待结算 → 已完成”的进度同时把维修项目、配件使用记录、费用明细放在不同Tab页签里。这个页面的展示效果直接决定答辩现场老师的第一印象值得多花时间美化。首页Dashboard看板则是整个系统最直观的“脸面”。我一般做法是放四个统计卡片今日新增工单、今日收入、待处理工单、库存预警数量再放两个图表月度收入折线图、维修项目占比饼图。数据全部从真实接口获取用ECharts绘制。这里要特别注意图表组件在Tab切换时可能出现宽度塌陷问题要在mounted里调用this.$nextTick后再初始化图表。5. 部署全过程实录从源码到一键启动5.1 环境准备清单对照检查很多同学拿到源码后第一反应就是运行报错然后心态爆炸。其实90%的启动失败都是环境问题。我整理一份部署前必须确认的检查清单检查项要求验证方法JDK版本1.864位命令行执行java -versionMaven3.6及以上mvn -vMySQL5.7或8.0mysql --versionNode.js14.x或16.xnode -vnpm/yarn6.x或以上npm -vIDEA2019及以上确认Lombok插件已安装数据库脚本已执行确认car_repair库存在且表完整这里特别强调Lombok插件的问题。很多同学报错java: You arent using a compiler supported by lombok就是因为IDEA里的Lombok插件版本和JDK版本不匹配或者插件没装。解决办法很粗暴IDEA里直接装最新版Lombok插件或者确认pom.xml里Lombok的版本不是那种奇怪的本地自定义版。数据库导入这一步也有讲究。拿到SQL文件后先创建数据库再导入CREATE DATABASE IF NOT EXISTS car_repair DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE car_repair; SOURCE /path/to/car_repair.sql;注意数据库字符集建议用utf8mb4而不是utf8因为utf8在MySQL里最多只能存3字节如果数据里有emoji或者非常规字符会直接报错。5.2 后端启动常见启动报错与解决后端启动的过程是在IDEA中打开backend目录等待Maven下载依赖然后点击启动按钮。这个过程看着简单实际上是个大坑集中地。依赖下载慢的问题最常见。Maven默认从中央仓库下载在国内网络环境下经常卡死。解决办法是在~/.m2/settings.xml里配阿里云镜像mirror idaliyunmaven/id mirrorOf*/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror改完这个配置依赖下载速度能从龟速变成秒开这是后端启动环节性价比最高的一次优化。启动过程中报Failed to configure a DataSource几乎可以肯定是application.yml里的数据库配置不对。重点检查三点数据库名是否存在、用户名密码是否正确、MySQL服务有没有启动。另外注意如果MySQL是8.0版本pom.xml里的mysql-connector-java版本不能太低建议用8.0.x。启动成功标志是日志中出现Started CarRepairApplication in x.xxx seconds同时控制台会打印出Tomcat started on port 8080。这时候你可以在浏览器里访问http://localhost:8080/api/user/login正常应该返回JSON格式的错误信息因为没传参数这就说明后端已经通了。5.3 前端构建与完整启动流程后端启动成功后再动前端。在frontend目录下依次执行# 1. 安装依赖首次执行需要几分钟 npm install # 2. 启动开发服务器 npm run serve看到App running at: Local: http://localhost:3000说明前端起来了。此时浏览器访问http://localhost:3000通过proxy代理访问后端接口就能看到登录页面。这里再强调一次前端和后端两个服务要同时开着因为前端开发服务器是靠代理转发到后端拿数据的。如果你关掉了后端前端页面能打开但登录按钮点了没反应控制台里全是Network Error。如果npm install过程特别慢或者报错大概率是npm源的问题。换成淘宝镜像源能解决npm config set registry https://registry.npmmirror.comNode版本这块也得注意。如果你用的是新版Node比如18以上Vue 2项目编译时可能报error:0308010C:digital envelope routines::unsupported这个经典的OpenSSL错误。解决方案是设置环境变量export NODE_OPTIONS--openssl-legacy-providerWindows用户要用set NODE_OPTIONS--openssl-legacy-provider再执行npm run serve。5.4 演示视频录制与答辩准备的实用建议拿到一套能跑的系统之后录制演示视频也有讲究。不要拿起手机对着屏幕一镜到底乱点一通老师根本看不清你想展示什么。正确姿势是用录屏软件OBS、ScreenToGif都行按这个节奏来先展示登录界面输入不同角色账号登录说明角色权限差异。然后进入首页把统计卡片、图表数据对着系统里的真实数据讲一遍。接着展示核心业务流新建维修工单 → 派工给技师 → 技师填维修记录 → 生成结算单 → 在统计报表里看到收入变化。最后展示配件库存模块演示一次出库操作后库存数量减少、出入库记录新增一条流水。这样录出来才叫“一条龙演示”。答辩时还要能应对高频追问。我总结过老师最常问的几个问题“工单状态是谁在控制流转怎么防止员工乱改状态” —— 答后端校验角色权限状态流转只能由有权限的角色操作且每次更新都带旧状态条件。“数据库里有几条表表之间的关联关系是什么” —— 答画出ER图把客户-车辆-工单-结算这条主链讲清楚。“如果并发下单库存怎么控制” —— 答带条件更新的SQL利用数据库行锁保证原子性。“项目里哪些地方用了面向对象的设计思想” —— 答比如不同角色需要不同操作权限用自定义注解和拦截器做了一个轻量级的权限控制比在每个Controller里写if-else要更符合开闭原则。6. 常见问题排查与学生党避坑实录6.1 前端运行问题速查问题现象可能原因解决办法npm install 卡住/超时npm源太慢切换淘宝镜像源npm run serve 报 OpenSSL错误Node版本过高Vue2不兼容设置NODE_OPTIONS--openssl-legacy-provider页面能开但登录请求404代理配置路径不对检查vue.config.js中proxy的target和路径是否匹配表单提交后列表不刷新组件间通信/刷新逻辑遗漏在提交成功后重新调用列表接口el-table列错位数据加载时序问题给表格设置固定的column宽度这里最值得提醒的一点是排查问题时先看浏览器F12控制台大部分网络错误和JS报错都会在这里显示。不要凭感觉瞎猜前端问题90%都能从控制台找到线索。比如最常见的跨域报错控制台会有明确的CORS字样接口404会有红色的请求记录。6.2 后端运行问题速查问题现象可能原因解决办法启动报端口占用8080端口被其他程序占用修改application.yml里的server.port或者关掉占用程序Failed to configure a DataSource数据库连接配置有误检查数据库名、用户名密码、MySQL服务是否启动查询中文乱码数据库字符集不是utf8mb4建库时指定utf8mb4连接字符串加characterEncodingutf8接口返回401未登录或Session失效检查是否先调用了登录接口前端请求是否携带了凭证SQL语句打印但结果不对MyBatis-Plus条件构造问题打开StdOutImpl日志复制SQL到数据库工具里单跑验证Lombok报错IDEA插件问题或版本不匹配安装Lombok插件检查依赖是否引入端口占用是学生项目里出现频率最高的启动故障。如果报Port 8080 was already in use可以先看端口被谁占用# Windows netstat -ano | findstr 8080 taskkill /PID 进程号 /F # Mac/Linux lsof -i:8080 kill -9 进程号6.3 时间管理与整体开发顺序建议最后说点务实的开发顺序建议。很多学生习惯从后端到前端一路线性推进结果做到中间发现前端页面样式太丑又回头改后端接口结构来回折腾浪费大量时间。我建议按下面这个顺序走第一阶段约1周把数据库所有表建好写好接口文档哪怕只是简单列一下接口路径和参数。这个阶段最重要因为表结构一旦后面改动牵连的代码非常广。第二阶段约2周后端接口全部实现用Postman把每个接口都测试通过。这个时候不需要关心前端页面只保证接口数据正确。第三阶段约1周前端页面全部搭好先对接接口。先做登录和主框架布局再做业务流最后做统计报表和首页看板。第四阶段约3-4天整体联调、优化细节、补数据。给自己导入一批测试数据包括10辆车、30张工单、若干配件的进出库记录这样统计报表才不会空白演示视频才有的讲。第五阶段约2-3天录视频、准备答辩PPT、演练讲解词。这个阶段重点不是写代码而是把整个项目的“故事”捋顺。这样安排的好处是每一步都有一个可验证的阶段性成果卡住了也能精确定位问题范围。很多学生就是前期闷头写代码不做整体规划到最后发现某个模块设计不合理推翻重来时间根本不够用。6.4 答辩前必须做好的三件事第一件把测试数据做得漂亮一点。不要拿一条“测试123”这种数据上去演示要模拟真实业务场景车牌号就写“京A12345”车主姓名就写“张伟”“李娜”这种正常名字维修项目就写“更换机油”“刹车片更换”“空调滤芯清洗”。数据显示真实感强老师看得顺眼你的演示也自然。第二件提前排练一遍完整功能演示。至少完整操作三遍从登录到新建工单到派工到填维修记录到结算到在报表里看到数据变化。多练几遍你才能发现那些只有操作到特定环节才会暴露的Bug比如新建工单时某个下拉框没数据、结算后工单状态没有自动变化等。第三件准备一份“项目说明文档”放在手边。不用多正式就是自己在纸上画清楚系统架构图、数据库ER图、核心接口列表、角色权限表。答辩时老师问到任何一点你都能第一时间接住话头展示出你对这个项目是真的理解而不是照着一篇现成论文念。写在最后折腾过几套毕设项目之后我最大的体会是毕业设计真正考的不是你的代码能力有多强而是你在规定时间内把一个题目从零做到完整交付的能力。汽车维修保养管理系统这个题目胜在业务链路完整、技术栈主流、工作量适中做出来之后从代码到论文再到演示都有内容可讲。做项目的时候多一点耐心把每个模块的细节抠到位把每次报错的原因记录下来这套流程走下来你的收获远比那一份“能跑能演示”的源码多得多。祝各位都能顺利通过答辩。
返回列表