资讯动态

汽修管理系统源码实战:接车派工配件结算业务闭环与二次开发

发布时间:2026/10/27 20:18:37 来源:尧图企业网站定制
简介这是一套面向汽车修理厂日常运营场景的汽修管理系统源码适合计算机专业学生做课程设计、毕业设计参考也适合中小型修理厂二次开发或学习业务管理逻辑。系统围绕客户档案、预约登记、维修订单、配件库存、财务收支、员工任务与统计报表等模块展开覆盖从接车到结算的完整流程并配有数据库脚本与权限控制思路。压缩包共53个文件、约2.66MB以C源码.h与.cpp为主体辅以MFC资源文件、工程配置.dsp/.dsw、Access数据库.mdb及可执行程序结构完整、便于编译调试。目前已有678人学习下载读者可从中获得一套可直接运行的桌面端管理系统骨架理解界面与数据库交互方式并借鉴其模块划分与业务建模思路用于改造或扩展自己的项目。1. 汽修管理系统从接车到结算一套跑在修理厂里的业务闭环上个月去一个开修理厂的朋友那儿串门正赶上他手忙脚乱一辆车刚做完保养前台在纸质单上找工时费库房那边说机油只剩半桶财务又在翻上个月的结算记录对账。三张纸、两个本子、一个微信群就是他们全部的“管理系统”。这种场景在中小修理厂太常见了接车靠喊、配件靠记、结算靠算车一多就乱套。这套汽修管理系统要解决的正是这个痛点——把接车登记、维修派工、配件领用、工时结算串成一条线让前台、车间、库房看到的是同一份数据。它适合谁适合想给自己厂子搭一套轻量业务系统的开发者也适合拿它当管理系统类项目练手、学完整业务闭环怎么落地的人。下面我按“能干什么、怎么跑、怎么改”的顺序把这份源码拆开讲。2. 技术栈与目录结构一套典型的前后端分离管理系统骨架拿到源码先别急着跑先看它用什么搭的、文件怎么摆。这套系统是标准的前后端分离结构后端管业务和数据前端管界面和交互中间靠 HTTP 接口通信。这种结构在管理系统类项目里几乎是默认选择好处是前后端可以分开开发、分开部署改界面不用动后端逻辑。2.1 后端技术选型与分层后端我一般会按“控制层—服务层—数据访问层”三层来组织这套项目也是这个路子。控制层负责接收请求、校验参数、返回结果服务层放业务逻辑比如“接车时自动生成工单号”“结算时汇总工时和配件金额”数据访问层只管和数据库打交道。分层的好处是业务改动集中在服务层不会牵一发动全身。常见做法是用 Spring Boot 做后端框架搭配 MyBatis 或 MyBatis-Plus 做数据访问MySQL 存业务数据。依赖管理用 Maven启动类一个main方法就能把整个服务拉起来。数据库连接、端口这些配置放在application.yml里改环境不用动代码。# application.yml 关键配置示例 server: port: 8080 # 后端服务端口前端代理要指向这里 spring: datasource: url: jdbc:mysql://localhost:3306/repair_db?useUnicodetruecharacterEncodingutf8 username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: configuration: map-underscore-to-camel-case: true # 数据库下划线字段自动映射成驼峰属性这段配置里最容易被忽略的是map-underscore-to-camel-case数据库里叫customer_name实体类里叫customerName开了这个映射就不用每个字段写TableField。端口8080要和前端代理配置对上不然前端请求会 404。2.2 前端结构与页面组织前端一般是 Vue 加 Element UI 这类组件库页面按业务模块分目录接车登记一个页面、维修派工一个页面、配件管理一个页面、结算一个页面。路由配置里每个模块对应一个路径菜单栏根据路由生成。请求统一走一个封装好的request.js里面配了后端地址和拦截器登录态、错误提示都在拦截器里处理。// request.js 请求封装核心逻辑 import axios from axios const service axios.create({ baseURL: /api, // 开发环境由 devServer 代理到后端 8080 timeout: 10000 }) service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) config.headers[Authorization] token // 登录后每个请求带 token return config }) export default servicebaseURL写成/api是为了开发时走代理、上线时走 Nginx 转发前端代码不用改地址。拦截器里统一加 token避免每个接口手动传。这套封装是管理系统前端的标配看懂这一个文件其他页面的请求逻辑就都通了。2.3 目录结构速览把源码解压后大致是这么摆的repair-system/ ├── backend/ # 后端工程 │ ├── src/main/java/com/repair/ │ │ ├── controller/ # 接口层接车、派工、配件、结算 │ │ ├── service/ # 业务逻辑层 │ │ ├── mapper/ # 数据访问层 │ │ ├── entity/ # 实体类对应数据库表 │ │ └── config/ # 跨域、拦截器等配置 │ └── src/main/resources/ │ ├── application.yml # 配置文件 │ └── mapper/ # MyBatis XML如果用了 ├── frontend/ # 前端工程 │ ├── src/ │ │ ├── views/ # 各业务页面 │ │ ├── api/ # 接口定义 │ │ ├── router/ # 路由 │ │ └── utils/request.js # 请求封装 │ └── package.json └── sql/ # 建库建表脚本看到sql/目录就说明作者把建表脚本一起给了这是跑起来的关键——先建库导表再启动后端顺序反了会报“表不存在”。3. 跑起来从建库到登录的完整启动链路这一章是给想直接跑通的人看的。我按实际操作的顺序写先准备环境再建库导数据然后起后端、起前端最后登录验证。每一步都写清楚失败时看哪里照着走基本不会卡住。3.1 环境准备与版本对齐先确认本机装了什么。后端要 JDK 8 或以上、Maven前端要 Node.js 和 npm数据库要 MySQL 5.7 或 8.0。版本这块有个血泪经验MySQL 8 的驱动类名是com.mysql.cj.jdbc.DriverMySQL 5 是com.mysql.jdbc.Driver配置里写错启动就报驱动加载失败。Node 版本也别太新老项目用太新的 Node 跑npm install容易卡在依赖编译上我一般用 Node 16 左右。# 检查环境版本 java -version # 期望 1.8 及以上 mvn -v # 期望 3.6 及以上 node -v # 建议 16.x mysql --version # 5.7 或 8.0版本对不上不用硬扛装个对应版本或者用版本管理工具切一下比后面排查依赖冲突省事得多。3.2 建库导表与配置修改打开sql/目录下的脚本里面一般是建库语句加建表语句可能还带几条初始数据比如默认管理员账号。用命令行或者数据库客户端执行都行。# 命令行导入示例 mysql -u root -p -e CREATE DATABASE repair_db DEFAULT CHARACTER SET utf8mb4; mysql -u root -p repair_db sql/repair_db.sql导完表去改application.yml里的数据库地址、用户名、密码改成你本机的。字符集用utf8mb4不然客户姓名里带生僻字或者特殊符号会存成乱码。这一步翻车的典型现象是后端启动没报错但一查列表就是空或者插入报字段超长——多半是字符集或字段长度的问题。3.3 启动后端与前端后端在backend/目录下用 Maven 起cd backend mvn spring-boot:run # 或者先打包再运行 mvn clean package -DskipTests java -jar target/repair-system.jar看到控制台打出Started ... Application就说明起来了默认监听 8080。如果报端口占用改application.yml里的server.port或者把占用 8080 的进程关掉。前端在frontend/目录下cd frontend npm install # 第一次跑必须装依赖网络慢可以换镜像源 npm run dev # 开发模式启动一般监听 8081 或 3000npm install卡住是常见问题多半是网络原因换个国内镜像源再试。启动后控制台会打印本地访问地址浏览器打开就能看到登录页。3.4 登录验证与接口连通性检查用初始账号登录账号密码一般在 SQL 脚本的初始数据里或者项目说明里。登录成功后重点看两件事一是菜单能不能正常加载二是列表页有没有数据。如果登录报“用户名或密码错误”先去数据库user表里确认账号存在、密码字段是不是加密过的——有些项目密码存的是明文有些是 MD5对不上就登不进去。如果页面能打开但接口全报 404 或跨域错误检查前端request.js的baseURL和后端端口是否一致以及后端有没有配跨域。开发阶段前端一般配了代理代理目标要指向后端实际端口。提示第一次跑通后先把数据库备份一份。后面改代码、改表结构有备份就有后悔药改坏了直接还原。4. 核心模块拆解接车、派工、配件、结算怎么串起来跑通之后就该看代码了。这套系统的价值不在界面多漂亮而在业务链路是否闭环。我挑四个核心模块讲接车登记是入口派工是流转配件领用是成本结算是出口。四个模块的数据是串起来的看懂它们之间的关联二次开发就有底了。4.1 接车登记工单的起点接车登记做的事是把客户、车辆、故障描述录进系统生成一张工单。工单号一般按日期加流水生成保证唯一。核心逻辑在服务层控制层只做参数接收。// RepairOrderService.java 接车登记核心逻辑 public String createOrder(RepairOrderDTO dto) { // 1. 校验车辆是否已存在不存在则先建档 Vehicle vehicle vehicleMapper.selectByPlate(dto.getPlateNo()); if (vehicle null) { vehicle new Vehicle(); vehicle.setPlateNo(dto.getPlateNo()); vehicle.setOwnerName(dto.getOwnerName()); vehicleMapper.insert(vehicle); } // 2. 生成工单号日期 4 位流水 String orderNo RO LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE) String.format(%04d, orderMapper.countToday() 1); // 3. 落工单状态置为“待派工” RepairOrder order new RepairOrder(); order.setOrderNo(orderNo); order.setVehicleId(vehicle.getId()); order.setFaultDesc(dto.getFaultDesc()); order.setStatus(PENDING); // 状态机起点 orderMapper.insert(order); return orderNo; }这段代码有三个关键点。第一车辆按车牌查重避免同一辆车重复建档这是数据干净的前提。第二工单号用“日期流水”流水按当天已有单量加一简单够用并发高的话要加锁或改用序列小修理厂一天几十单这样写没问题。第三status字段是整个流程的状态机从PENDING待派工往后流转后面派工、完工、结算都靠改这个字段推进。4.2 维修派工状态流转与人员分配派工是把工单分配给具体的维修师傅同时记录预计工时。这一步的核心是状态校验——只有“待派工”的单才能派已经派过的不能再派否则会出现两个师傅干同一辆车。// DispatchService.java 派工逻辑 public void dispatch(Long orderId, Long technicianId, BigDecimal estimatedHours) { RepairOrder order orderMapper.selectById(orderId); // 状态校验只有待派工状态可以派工 if (!PENDING.equals(order.getStatus())) { throw new BizException(当前工单状态不允许派工); } DispatchRecord record new DispatchRecord(); record.setOrderId(orderId); record.setTechnicianId(technicianId); record.setEstimatedHours(estimatedHours); dispatchMapper.insert(record); // 更新工单状态为“维修中” order.setStatus(REPAIRING); orderMapper.updateById(order); }状态校验这段是血泪经验换来的。早期没加校验前台手快点两次派工按钮同一张单生成两条派工记录结算时工时翻倍客户当场就急了。加了这个判断之后重复提交直接被拦。estimatedHours是预计工时实际工时在完工时录入两者对比能看出师傅的估时准不准这也是后面结算的依据之一。4.3 配件领用库存扣减与成本归集配件领用是修理厂成本的大头也是最容易出猫腻的地方。领用时要扣库存同时把配件成本挂到工单上结算时一起算。库存扣减必须防超卖两个人同时领最后一个配件不能都成功。// PartUsageService.java 配件领用 Transactional public void usePart(Long orderId, Long partId, Integer quantity) { // 1. 带条件扣库存库存不足时影响行数为 0 int affected partMapper.deductStock(partId, quantity); if (affected 0) { throw new BizException(配件库存不足); } // 2. 记录领用明细挂到工单 PartUsage usage new PartUsage(); usage.setOrderId(orderId); usage.setPartId(partId); usage.setQuantity(quantity); usage.setUnitPrice(partMapper.selectById(partId).getSalePrice()); partUsageMapper.insert(usage); }关键是deductStock这条 SQL用UPDATE part SET stock stock - #{qty} WHERE id #{id} AND stock #{qty}把库存判断放进 SQL 的WHERE里靠数据库行锁保证并发安全比先查再改靠谱得多。方法上加Transactional扣库存和记明细要么都成功要么都回滚不会出现扣了库存没记账的情况。4.4 结算工时费与配件费的汇总结算是把工单上的工时和配件汇总成一张账单。工时费按实际工时乘工时单价配件费按领用明细汇总可能还有折扣。结算完成后工单状态置为“已结算”这张单就闭环了。// SettlementService.java 结算汇总 public SettlementVO settle(Long orderId) { RepairOrder order orderMapper.selectById(orderId); if (!FINISHED.equals(order.getStatus())) { throw new BizException(工单未完工不能结算); } // 工时费实际工时 × 工时单价 BigDecimal laborFee order.getActualHours() .multiply(laborPriceConfig.getHourlyRate()); // 配件费领用明细汇总 BigDecimal partFee partUsageMapper.sumAmountByOrder(orderId); BigDecimal total laborFee.add(partFee); // 落结算单更新工单状态 Settlement s new Settlement(); s.setOrderId(orderId); s.setLaborFee(laborFee); s.setPartFee(partFee); s.setTotalAmount(total); settlementMapper.insert(s); order.setStatus(SETTLED); orderMapper.updateById(order); return buildVO(s); }结算前必须校验工单已完工不然会出现没修完就收钱的荒唐账。工时单价从配置里读不写死在代码里调价时改配置就行。配件费从领用明细汇总保证结算金额和实际用料一致这也是前面领用要记明细的原因——账能对上客户才信服。5. 避坑与排查跑这套系统最容易翻车的五个地方这套系统结构不复杂但真跑起来坑都藏在细节里。下面五条是我实际踩过或者见别人踩过的每条按“现象—原因—解决”写遇到问题对着查。5.1 启动报“表不存在”或“Unknown database”现象后端启动直接抛异常提示某张表不存在或者数据库连不上。原因SQL 脚本没导或者导到了别的库或者application.yml里的库名和脚本建的不一致。解决先确认库建了、表导了用SHOW TABLES;看一眼再核对配置里的库名拼写。顺序永远是先建库导表再启动后端。5.2 前端请求全部 404 或跨域被拦现象页面能打开但登录、列表接口全红控制台报 404 或 CORS 错误。原因前端代理没配或配错端口或者后端没开跨域。解决检查前端vue.config.js或vite.config.js里代理的target是否指向后端实际端口后端加跨域配置开发阶段允许本地来源。两边端口对不上是最常见的。5.3 中文乱码现象客户姓名、故障描述存进去变成问号或乱码。原因数据库或表字符集不是utf8mb4或者连接串没指定编码。解决建库时指定DEFAULT CHARACTER SET utf8mb4连接串加characterEncodingutf8已有表用ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4转一下。5.4 配件库存扣成负数现象库存明明只有 1 个两个人同时领都成功了库存变成 -1。原因先查库存再更新两步之间没有锁并发下都查到有库存。解决把库存判断写进UPDATE的WHERE条件里靠数据库行锁保证原子性影响行数为 0 就抛库存不足。这是并发场景的必修课。5.5 结算金额和预期对不上现象结算出来的总价比手工算的少或多。原因工时单价读的配置不对或者配件领用明细里有单价为空的记录或者实际工时没录。解决先查结算单的工时费、配件费两个分项定位是哪一项偏了再查领用明细的unit_price是否有空值工时字段是否为空。分项拆开看问题一目了然。注意改表结构前先备份尤其是给已有数据的表加字段、改类型改错了数据恢复很麻烦。6. 二次开发从单店到多店改造思路与验证方法这套系统默认是单店模型数据表里没有门店维度。如果要做成多店版本改造的核心是给业务表加门店标识并在查询层统一过滤。我一般按这个顺序改先加字段再改查询最后改权限。第一步给工单、配件、结算这些业务表加store_id字段默认值设成 1保证老数据不丢。第二步在服务层的查询方法里统一带上store_id条件这一步最容易漏漏一个查询就会串店。第三步登录时把用户所属门店写进 token后端从 token 里取门店过滤前端不用传。-- 给工单表加门店维度 ALTER TABLE repair_order ADD COLUMN store_id BIGINT NOT NULL DEFAULT 1; CREATE INDEX idx_store_status ON repair_order(store_id, status);加索引是因为多店之后按门店加状态查列表是高频操作不建索引数据一多就慢。改完怎么验证我的办法是造两家店的数据用不同门店的账号登录互相看不到对方的单再交叉查一次配件库存确认隔离干净。这个验证方法比看代码可靠数据不会骗人。还有一个改造点是工单状态机。现在状态是硬编码的字符串要加“挂起”“退单”这类状态建议抽成枚举或者状态配置表流转规则集中管理别散落在各个if里。我吃过这个亏状态判断散在五六个方法里加一个新状态改了四处漏了一处线上出了张状态错乱的单查了半天。从那以后我每次动状态机都先把所有流转点列出来改完用一条完整流程走一遍——接车、派工、领料、完工、结算每个状态都过一遍确认没有断点。希望这套拆解能帮到你少走我走过的弯路。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑