news 2026/10/29 18:17:40

基于 Spring Boot + Vue3 的汽车服务管理系统设计与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于 Spring Boot + Vue3 的汽车服务管理系统设计与实现

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系名片!

一、项目背景与意义

随着汽车保有量的持续增长,汽车维修、保养、美容、保险等后市场服务需求快速扩张。传统汽车服务门店多依赖纸质工单、Excel 表格和电话沟通来管理客户、车辆、维修项目与配件库存,普遍存在信息分散、工单流转不透明、库存账实不符、客户复购难以追踪等问题。

本系统基于Spring Boot + Vue3前后端分离架构,构建一套覆盖「客户—车辆—服务工单—配件库存—结算统计」全流程的汽车服务管理系统,帮助门店实现业务数字化,提升服务效率与客户体验。

二、系统目标与核心功能

系统面向汽车维修保养门店,主要服务于管理员、服务顾问、维修技师、仓库管理员四类角色,核心目标如下:

  • 客户与车辆档案统一管理:一个客户可关联多台车辆,记录车牌、车型、里程、保养记录。
  • 服务工单全流程闭环:从预约、接车、派工、维修、质检到结算,状态可追溯。
  • 配件库存精细化管理:入库、出库、领料、盘点与库存预警。
  • 经营数据可视化:营业额、工单量、热门服务项目、客户复购率等统计报表。
  • 权限与安全控制:基于角色的菜单与接口权限控制,操作日志留痕。

三、技术选型

层次技术栈说明
后端框架Spring Boot 3.x快速构建 RESTful 接口,内置 Tomcat
持久层MyBatis-Plus简化 CRUD,支持分页与条件构造器
数据库MySQL 8.0存储业务数据,支持事务与索引优化
缓存Redis缓存登录令牌、字典数据与热点统计
认证授权Spring Security + JWT无状态认证,接口级权限校验
前端框架Vue3 + TypeScript组合式 API,类型安全
构建工具Vite快速冷启动与热更新
UI 组件库Element Plus后台管理常用组件
状态与路由Pinia + Vue Router全局状态管理与动态路由
图表ECharts经营数据可视化

四、系统架构设计

系统采用前后端分离架构,前端通过 Axios 调用后端 RESTful 接口,后端按 Controller、Service、Mapper 三层组织代码,公共能力(认证、日志、异常处理、文件上传)以切面与拦截器方式统一实现。

flowchart TD A[Vue3 前端 Element Plus] -->|HTTP / JSON| B[Nginx 静态资源与反向代理] B --> C[Spring Boot 应用] C --> D[Controller 层] D --> E[Service 层] E --> F[Mapper 层 MyBatis-Plus] F --> G[(MySQL 8.0)] C --> H[(Redis 缓存)] C --> I[文件存储 本地或 OSS] C --> J[Spring Security + JWT 认证]

五、数据库设计

核心表设计围绕客户、车辆、工单、服务项目与配件展开,主要表结构如下:

表名说明关键字段
sys_user系统用户id、username、password、role_id、status
customer客户档案id、name、phone、level、create_time
vehicle车辆档案id、customer_id、plate_no、brand、model、mileage
service_item服务项目id、name、price、duration、category
work_order服务工单id、order_no、vehicle_id、status、total_amount、create_time
order_item工单明细id、order_id、item_type、item_id、quantity、price
part配件库存id、name、spec、stock、warn_stock、unit_price
stock_record出入库记录id、part_id、type、quantity、operator、create_time

工单状态建议使用枚举统一管理:待接车 → 已接车 → 维修中 → 待质检 → 已完成 → 已结算,并通过状态机校验流转合法性,避免越级变更。

六、后端核心实现

6.1 统一响应与全局异常处理

@Data public class Result<T> { private Integer code; private String message; private T data; public static <T> Result<T> success(T data) { Result<T> r = new Result<>(); r.setCode(200); r.setMessage("操作成功"); r.setData(data); return r; } public static <T> Result<T> fail(String message) { Result<T> r = new Result<>(); r.setCode(500); r.setMessage(message); return r; } }

6.2 JWT 认证与权限校验

登录成功后签发 JWT,前端将令牌存入 Pinia 与 localStorage,请求时通过拦截器放入Authorization请求头。后端自定义过滤器解析令牌并写入SecurityContext,结合@PreAuthorize实现接口级权限控制。

@Component public class JwtAuthenticationFilter extends OncePerRequestFilter { @Resource private JwtUtil jwtUtil; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String header = request.getHeader("Authorization"); if (header != null && header.startsWith("Bearer ")) { String token = header.substring(7); if (jwtUtil.validate(token)) { String username = jwtUtil.getUsername(token); List<String> roles = jwtUtil.getRoles(token); UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(username, null, roles.stream().map(SimpleGrantedAuthority::new).toList()); SecurityContextHolder.getContext().setAuthentication(auth); } } chain.doFilter(request, response); } }

6.3 工单创建与库存扣减

工单结算时需要同时更新工单状态、写入明细并扣减配件库存,必须保证事务一致性。这里使用@Transactional配合乐观锁字段version防止并发超卖。

@Service public class WorkOrderService { @Resource private WorkOrderMapper workOrderMapper; @Resource private PartMapper partMapper; @Transactional(rollbackFor = Exception.class) public void settle(Long orderId) { WorkOrder order = workOrderMapper.selectById(orderId); if (order == null || !"已完成".equals(order.getStatus())) { throw new BizException("工单状态不允许结算"); } List<OrderItem> items = order.getItems(); for (OrderItem item : items) { if ("PART".equals(item.getItemType())) { int rows = partMapper.deductStock(item.getItemId(), item.getQuantity()); if (rows == 0) { throw new BizException("配件库存不足:" + item.getItemId()); } } } order.setStatus("已结算"); workOrderMapper.updateById(order); } }

七、前端核心实现

7.1 请求封装与统一拦截

import axios from 'axios' import { ElMessage } from 'element-plus' import { useUserStore } from '@/stores/user' const request = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 10000 }) request.interceptors.request.use(config => { const userStore = useUserStore() if (userStore.token) { config.headers.Authorization = `Bearer ${userStore.token}` } return config }) request.interceptors.response.use( res => { const { code, message, data } = res.data if (code === 200) return data ElMessage.error(message || '请求失败') return Promise.reject(new Error(message)) }, err => { if (err.response?.status === 401) { useUserStore().logout() } ElMessage.error(err.message) return Promise.reject(err) } ) export default request

7.2 工单列表页

<template> <el-table :data="orderList" v-loading="loading"> <el-table-column prop="orderNo" label="工单号" width="180" /> <el-table-column prop="plateNo" label="车牌号" width="120" /> <el-table-column prop="customerName" label="客户" width="120" /> <el-table-column prop="status" label="状态"> <template #default="{ row }"> <el-tag :type="statusType(row.status)">{{ row.status }}</el-tag> </template> </el-table-column> <el-table-column prop="totalAmount" label="金额" /> <el-table-column label="操作" width="160"> <template #default="{ row }"> <el-button link type="primary" @click="handleDetail(row)">详情</el-button> <el-button link type="success" :disabled="row.status !== '已完成'" @click="handleSettle(row)">结算</el-button> </template> </el-table-column> </el-table> </template> <script setup lang="ts"> import { ref, onMounted } from 'vue' import { getOrderPage, settleOrder } from '@/api/order' const orderList = ref([]) const loading = ref(false) const loadData = async () => { loading.value = true try { orderList.value = await getOrderPage({ page: 1, size: 10 }) } finally { loading.value = false } } const handleSettle = async (row: any) => { await settleOrder(row.id) loadData() } onMounted(loadData) </script>

八、系统部署与运行

  1. 准备环境:JDK 17、Node.js 18、MySQL 8.0、Redis 6。
  2. 导入数据库脚本,修改后端application.yml中的数据源与 Redis 配置。
  3. 后端执行mvn clean package,运行java -jar car-service.jar。
  4. 前端执行npm install与npm run build,将dist目录交由 Nginx 托管。
  5. Nginx 配置/api反向代理到后端服务,解决跨域问题。

九、总结与展望

本文围绕 Spring Boot + Vue3 前后端分离架构,完成了汽车服务管理系统从需求分析、技术选型、数据库设计到核心功能实现的整体方案。系统通过工单状态机与事务控制保证了业务一致性,通过 JWT 与角色权限保障了数据安全。

后续可继续扩展的方向包括:接入微信小程序实现客户自助预约、引入消息队列处理库存与通知异步任务、基于历史工单数据做保养提醒与客户流失预警,以及对接第三方支付与电子发票能力。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/29 18:17:39

狼羊菜过河:状态空间搜索与DFS/BFS算法入门实战

简介&#xff1a;经典农夫过河问题是人工智能与算法设计中的经典入门案例&#xff0c;这份文档围绕狼、羊、白菜、农夫渡河场景&#xff0c;面向计算机专业学生与算法初学者&#xff0c;完整梳理状态空间搜索、深度优先/广度优先搜索、动态规划、回溯与约束条件等核心思路。资源…

作者头像 李华
网站建设 2026/10/29 18:15:59

caveman思维:用简单直接的方式破解复杂系统的密码

说到“caveman”&#xff0c;很多人的第一反应是部落时代敲石头、钻木取火&#xff0c;或者某个健身视频里生啃牛排的野性画风。但如果是在开发者圈子、内容创作者圈子和效率追求者圈子里提到这个词&#xff0c;它其实更像一种充满反差的赞美&#xff1a;夸一个人把复杂问题砍到…

作者头像 李华
网站建设 2026/10/29 18:15:26

2026年网络安全毕设选题指南与云安全实践

1. 2026年网安毕设选题的底层逻辑作为带过7届毕业设计的导师&#xff0c;我发现学生们最常犯的错误是选题时盲目追求"高大上"&#xff0c;却忽略了三个核心要素&#xff1a;可操作性、创新空间和实际价值。2026年的网络安全领域&#xff0c;技术迭代速度远超想象&…

作者头像 李华
网站建设 2026/10/29 18:14:26

遥感影像语义分割数据集对比与应用指南

1. 遥感影像语义分割数据集全景解析在计算机视觉与遥感测绘交叉领域&#xff0c;语义分割技术正推动着地物识别从"看得见"向"看得懂"跨越。作为算法训练的基石&#xff0c;高质量标注数据集的价值不言而喻。本文将深度剖析8个主流遥感分割数据集的技术特性…

作者头像 李华
网站建设 2026/10/29 18:14:24

TSL1401线性CCD嵌入式驱动实战:STM32精准采样与三阶校准

简介&#xff1a;本资源是一份面向智能车竞赛光电组选手及嵌入式图像采集初学者的TSL1401线性CCD快速入门指南&#xff0c;聚焦解决线阵CCD原理理解难、曝光时序控制模糊、编程逻辑不清晰等实操痛点。文档以中文精讲替代原厂英文手册&#xff0c;系统梳理TSL1401引脚功能&#…

作者头像 李华
网站建设 2026/10/29 18:13:19

共享状态隔离问题:KV cache串扰实验与推理优化方案

1. 从一场口令实验说起&#xff1a;共享状态到底藏了什么猫腻第一次看到“共享状态&#xff0c;隔离问题”这个说法&#xff0c;是在一个做推理优化的朋友群里。有人丢了一张图&#xff0c;说同一个模型、同一段输入&#xff0c;跑两遍结果居然不一样&#xff0c;但把并发关掉就…

作者头像 李华