news 2026/9/9 12:53:51

SpringBoot+Vue3汽车维修预约系统全栈开发实战与部署详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot+Vue3汽车维修预约系统全栈开发实战与部署详解

1. 项目整体设计与思路拆解

1.1 这个项目到底解决了什么问题

先说结论:这是一个面向汽车维修门店和车主两端使用的预约服务系统。你如果开过修理厂或者去4S店排过队修车,一定体会过那种“到了门店发现师傅在忙别的车,白等两小时”的尴尬。这个系统的核心价值就是把“到店排队”改成“线上预约、按时到店、状态可追踪”,客户能提前选时间段、选服务项目,门店能提前安排工位和技师,双方的时间都不浪费。

技术选型方面,SpringBoot2 + Vue3 + MyBatis-Plus + MySQL8.0这套组合在2024年依然是中小型管理系统里非常主流、非常稳的搭配。SpringBoot2负责后端接口和业务逻辑,Vue3负责前端页面和交互体验,MyBatis-Plus把数据库操作简化到几乎不用写XML,MySQL8.0作为底层数据存储。整套东西跑起来,前后端分离,接口交互,是典型的Java Web全栈项目形态。

这套源码适合谁来参考?三部分人:一是正在做毕业设计或课程设计的计算机专业学生,这个项目从选题到技术栈到文档都完整;二是准备往全栈方向走的Java开发初学者,能用它完整走一遍“需求分析→数据库设计→后端接口→前端页面→联调部署”的全流程;三是想快速落地一个小型预约系统的业务方或外包开发者,直接在源码基础上改改就能用。

1.2 为什么选这套技术栈而不是别的

很多人一上来就问:SpringBoot都出3.x了,怎么还用2.x?这话对了一半。SpringBoot2虽然官方维护期在缩短,但目前存量项目、企业生产环境里跑得最多的还是2.7.x,网上能搜到的资料和解决方案也最全,遇到问题基本都能抄到答案。对于学习项目和毕业设计来说,SpringBoot2比3.x稳得多——没有JDK17强制要求,没有Jakarta命名空间迁移的坑,用起来更省心。

Vue3这边的理由也很实在:Vue2已经停止维护,组合式API的写法在Vue3里已经非常成熟,而且Element Plus这类组件库全面转向了Vue3生态。现在新开前端项目再用Vue2,等于主动选择一条不归路。拿这个项目练习Vue3的setup语法、响应式API、路由守卫、Pinia状态管理,跟在真实企业项目里用的东西完全对得上。

MyBatis-Plus更不用说了,它在MyBatis基础上封装了通用Mapper和条件构造器,单表CRUD几乎不用手写SQL。对业务系统来说,80%的数据库操作都是单表增删改查,用MyBatis-Plus能省掉大量重复劳动。而MySQL8.0是当前最主流的关系型数据库版本,窗口函数、CTE这些新特性以后做数据分析也用得上。

1.3 系统角色与业务流程梳理

这个系统从业务上划分,主要涉及三类角色:管理员、门店员工(技师/接待)、注册用户(车主)。

车主端的流程是这样:注册登录后,在首页选择维修门店(如果有多个门店),选择维修服务项目(比如小保养、大保养、钣金喷漆、轮胎更换等),然后选择预约日期和可用时间段,填写备注(比如车辆故障描述),提交预约。提交后可以在“我的预约”里查看预约状态,状态是待确认、已确认、已完成或者已取消。门店确认后,车主按时间到店就行。

门店端的流程:员工登录后能看到所有待确认的预约单,确认后系统自动锁定该时间段,避免重复预约。维修过程中可以更新状态为“维修中”,完工后标记“待取车”,车主取车后标记“已完成”。整个状态流转清晰,前后端都要做对应的权限控制。

管理员端的职能更偏向系统运营:管理门店信息、管理服务项目、管理员工账号、查看所有预约记录、处理异常预约,以及一些数据统计(比如每日预约量、门店工单量)。从源码和文档里看,这套系统把这三条线都打通了,登录鉴权用JWT,密码加密用BCrypt,角色权限用拦截器或Spring Security实现。

2. 核心功能模块与数据结构详解

2.1 数据库表设计与关联关系

一个预约系统的数据库设计直接决定了整个项目的复杂度上限。这套源码里表结构划分得很清晰,核心表有:用户表、门店表、服务项目表、预约订单表、评价表,可能还有公告表或操作日志表。

用户表就是最基础的账号体系,包含用户名、密码(BCrypt加密后的密文)、手机号、角色标识(区分车主/员工/管理员)。门店表记录门店名称、地址、联系电话、营业时间、状态。服务项目表记录项目名称、项目分类(保养/维修/美容)、标准工时、价格、门店ID——这里需要注意,如果允许多门店多项目,应该在门店和服务项目之间建中间表,否则就退化成单门店系统了。

预约订单表是整个系统的核心,字段设计上要重点看这几个:订单编号、用户ID、门店ID、服务项目ID、预约日期、预约时间段(几点到几点)、车辆信息(车牌号、品牌型号、里程数)、故障描述、订单状态、创建时间、更新时间。订单状态建议用int存,0待确认、1已确认、2维修中、3待取车、4已完成、5取消,比直接存字符串更省空间,也方便状态机流转。

评价表记录用户对服务的打分和文字评价,关联订单ID,做技术差评展示用。个人建议可以再加一张预约时间排期表,用来标注每个时间段被占用的批次,防止同一时间段被多人预约——源码里可能直接用订单表查时间段是否已有确认订单来实现,数据量小的时候也能跑,但并发高一点就容易出问题。

2.2 后端接口设计要点

后端接口遵循RESTful风格,按模块划分Controller。常见的接口路径会是这样:

  • /api/auth/register/api/auth/login:注册、登录,返回JWT token
  • /api/user/profile:获取当前登录用户信息
  • /api/store/list:门店列表
  • /api/service/list:服务项目列表,可按门店ID筛选
  • /api/appointment/create:创建预约
  • /api/appointment/my:我的预约列表
  • /api/appointment/updateStatus:更新预约状态(员工端)
  • /api/admin/appointment/page:管理员分页查询所有预约
  • /api/admin/statistics:统计仪表盘数据

接口设计上有一个容易踩的坑:创建预约时的时间段冲突判断。这个判断不能只在前端做,后端必须做二次校验。正确做法是:在create接口里先查数据库,看同一个门店、同一个日期、同一个时间段是否存在“待确认”或“已确认”状态的订单,如果存在就拒绝创建。数据库层面可以用联合唯一索引兜底,但预约表一般不会直接建唯一索引,因为同一时间段可以有多个工位同时服务,所以这里还是得靠业务代码逻辑控制。

鉴权这块,源码如果用的是Spring Security + JWT,会在拦截器或过滤器中校验token,然后从token里解析出用户ID和角色。如果用的是简单的拦截器+自定义注解,也够用。区别在于Spring Security比较重但功能全,拦截器方案轻量但需要自己处理登录态过期、角色校验等逻辑。对学习项目来说,拦截器方案更容易理解整个请求流转过程。

2.3 前端页面结构与Vue3组合式API写法

前端部分用Vue3 + Vite + Element Plus搭建,目录结构一般是:src/views放页面组件,src/api放接口请求封装,src/router放路由配置,src/storesrc/stores放状态管理(Pinia)。

页面分成两大块:用户端和后台管理端。

用户端页面包括首页(门店展示、公告)、预约页面(选门店、选项目、选时间)、我的预约页面(列表展示、状态标签、取消按钮)、个人中心页面(修改资料、修改密码、我的评价)。

后台管理端页面包括:数据仪表盘(预约量统计、收入统计的图表)、预约管理页(表格展示所有预约,支持按状态筛选、确认/取消操作)、门店管理页(增删改查门店)、服务项目管理页(增删改查服务项目)、用户管理页(查看注册用户列表、禁用/启用账号)、系统设置页。

Vue3里最常用的几个点:setup语法糖写法、refreactive定义响应式数据、computed计算属性、watch监听、onMounted生命周期调用接口。比如预约时间选择器,可以用Element Plus的el-date-picker配合el-time-select实现日期和时间段的联动选择。前端接口请求统一封装在src/api/request.js里,用axios实例,配置baseURL,请求拦截器里加token,响应拦截器里统一处理错误码和401跳转登录。

路由守卫是必须写的:router.beforeEach里判断本地有没有token,没有就直接跳转到登录页,有token但访问的是登录页就重定向到首页。角色权限如果做得细,可以在路由meta里配置角色标识,然后在守卫里做角色判断。这个项目是典型的多页面权限示例,适合学习。

2.4 MyBatis-Plus在项目中怎么用最省事

MyBatis-Plus的核心用法在项目里体现得很明显:实体类继承Model或加@TableName注解,Mapper接口继承BaseMapper<T>,Service层继承IService<T>ServiceImpl<M, T>。这一套下来,单表的CRUD方法全都有了,基本不用写SQL。

举几个实际使用场景:

分页查预约列表,直接用Page<Appointment>LambdaQueryWrapper组合。比如按状态筛选加按时间倒序排:

Page<Appointment> page = new Page<>(current, size); LambdaQueryWrapper<Appointment> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Appointment::getStoreId, storeId) .eq(status != null, Appointment::getStatus, status) .orderByDesc(Appointment::getCreateTime); appointmentMapper.selectPage(page, wrapper);

条件构造器里eq(condition, column, value)这种写法很常见,condition为true时才拼接条件,避免了写一堆if判断的丑代码。这是MyBatis-Plus相比原生MyBatis最大的体验提升。

时间段的冲突校验也可以用QueryWrapper来实现:

LambdaQueryWrapper<Appointment> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Appointment::getStoreId, storeId) .eq(Appointment::getAppointmentDate, date) .eq(Appointment::getTimeSlot, timeSlot) .in(Appointment::getStatus, Arrays.asList(0, 1)); Long count = appointmentMapper.selectCount(wrapper); if (count > 0) { throw new BizException("该时间段已被预约"); }

写这种代码的时候注意in的用法,待确认和已确认两种状态的订单都要查,否则可能出现重复预约。MyBatis-Plus 3.5.x版本里selectCount返回的是Long而不是Integer,这个细节容易踩坑,类型不对导致编译报错或者NPE的案例太多了。

另外在实体类里,自动填充字段用@TableField(fill = FieldFill.INSERT)@TableField(fill = FieldFill.INSERT_UPDATE),配合MetaObjectHandler实现创建时间和更新时间的自动填充。这样每次insert或update都不用手动set时间,省事不少。源码的文档里应该有说明这一点,如果没有,建议自己加上。

3. 从零跑通项目的完整实操记录

3.1 本地环境准备清单

在开始跑项目之前,建议把环境统一一下,版本不一致会省很多事但也可能出很多事。我在本地测试用的组合是:

软件版本说明
JDK1.8 或 11SpringBoot2.7.x 兼容
Maven3.6+构建后端项目
Node.js16.x 或 18.x前端构建工具链需要
npm8.x+随Node自带
MySQL8.0.x数据库
Navicat / DBeaver任意数据库可视化工具
IDEA2022+后端开发IDE
VSCode最新前端开发建议用

MySQL8.0安装的时候有一个细节:认证插件默认是caching_sha2_password,旧版驱动和旧版工具会连不上。如果遇到连接报错或者密码明明对却登录失败,可以在MySQL里执行:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码'; FLUSH PRIVILEGES;

不过新版的mysql-connector-java 8.0.x已经支持caching_sha2_password了,所以这一步通常不需要。但如果你用的是5.x版本的驱动,那必须转成mysql_native_password

JDK版本上多说一句:别用JDK17跑SpringBoot2.x的项目。虽然也能编译,但Lombok的兼容性、反射访问的模块限制都可能出问题,不如老老实实用JDK8或者JDK11,稳得一批。

3.2 后端启动三步走

第一步,导入数据库。用Navicat或命令行执行项目里自带的sql文件,通常文件名类似schema.sqlinit.sql。执行成功后检查一下表是否都建好了,最好核对一下初始数据(管理员账号、测试用户、服务项目)是否导入完整。

第二步,改配置文件。数据库连接配置在application.ymlapplication-dev.yml里,核心就是改三项:URL、用户名、密码。特别注意URL里要带上useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai,否则中文乱码和时区问题会一起来。

spring: datasource: url: jdbc:mysql://localhost:3306/car_repair?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver

第三步,启动。IDEA里打开项目,等Maven依赖下载完,找到主启动类(类名一般是ApplicationXxxApplication),右键Run。看到类似Started Application in 5.32 seconds的日志就说明启动成功。默认端口如果是8080,访问http://localhost:8080/api/health/swagger-ui.html(如果有集成Swagger)验证一下后端是否正常。

后端启动遇到最多的问题就是端口冲突,8080被占了启动直接失败。解决办法:换端口,在application.yml里改server.port,或者找出占用进程干掉。Windows下用netstat -ano | findstr 8080查看PID,然后taskkill /F /PID 进程号

3.3 前端启动注意事项

前端项目用Vite构建,启动命令很简单:

npm install npm run dev

npm install这一关常常要折腾一会儿。如果项目用的是npm源,下载Electron相关依赖(虽然这个项目不一定有)会非常慢。建议先把npm源切到国内镜像:

npm config set registry https://registry.npmmirror.com

然后再npm install,速度会快很多。装完后如果npm run dev把Vite服务跑起来了,默认会在http://localhost:5173。这里有个关键问题:前端请求后端接口要解决跨域。

Vite开发服务器的跨域配置在vite.config.js里:

server: { port: 5173, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } }

配好之后,前端请求/api/xxx就会自动转发到后端的8080端口,绕过跨域限制。生产环境部署时可以用Nginx来做反向代理,配置类似:

location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }

前端页面如果白屏或控制台报错,优先检查网络请求是不是404或500,然后对照后端日志排查。交互层面比较常见的报错是:用户登录成功后刷新页面又变回未登录状态。这个问题100%是token没有存到localStoragesessionStorage里,或者刷新时没有从本地读取token再重新写入请求头。

3.4 核心业务代码实现示例:预约下单

预约下单是整个系统最核心的一个接口,我拆开讲讲它的实现思路。前端页面提交预约时,向后端发送的数据结构大致是:

{ "storeId": 1, "serviceItemId": 3, "appointmentDate": "2025-05-20", "timeSlot": "09:00-10:00", "carNumber": "京A12345", "carBrand": "大众", "description": "发动机故障灯亮,需要检查" }

后端接收后的处理逻辑是:

@PostMapping("/appointment/create") public Result createAppointment(@RequestBody @Valid AppointmentDTO dto) { // 1. 获取当前登录用户 Long userId = SecurityUtils.getUserId(); // 2. 校验时间段是否可预约 checkTimeSlotAvailable(dto.getStoreId(), dto.getAppointmentDate(), dto.getTimeSlot()); // 3. 创建预约记录 Appointment appointment = new Appointment(); BeanUtils.copyProperties(dto, appointment); appointment.setUserId(userId); appointment.setOrderNo(generateOrderNo()); appointment.setStatus(AppointmentStatus.PENDING); appointmentService.save(appointment); // 4. 返回创建成功 return Result.success(appointment.getId()); }

checkTimeSlotAvailable这块前面已经讲过了,用LambdaQueryWrapper去查有没有状态为0或1的同时间段订单。这里有一个质疑点:如果系统支持同一个时间段多个工位预约,那这种校验就太严格了。实际业务里,应该在服务项目表里维护一个“并发容量”字段,校验时统计的是当前时间段已预约数量是否达到容量上限。源码如果没做这个,建议自己加上,这样系统才有真实落地价值。

订单号生成方式也值得一提。不要用自增ID直接展示给用户,安全性不好,也容易被爬数据。一般用时间戳加随机数,比如:20250520103012345加4位随机数,或者用yyyyMMddHHmmss + userId + random组合。下单时如果遇到重复订单号,重试一次就行,概率极低。

3.5 Docker方式部署MySQL8.0

如果你的开发机不想直接装MySQL,用Docker拉一个MySQL8.0容器会更干净。这里贴一下我在项目中常用的启动命令:

docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=123456 \ -e MYSQL_DATABASE=car_repair \ -v /data/mysql:/var/lib/mysql \ mysql:8.0

注意几个参数:MYSQL_DATABASE会在容器首次启动时自动创建同名数据库,省得手动建库。-v挂载数据目录,这样容器删了数据还在,不会一夜回到解放前。

启动后进入容器执行SQL脚本:

docker exec -i mysql8 mysql -uroot -p123456 car_repair < schema.sql

这里有一个Docker专属的坑:容器里MySQL的时区默认是UTC,你在Java端用serverTimezone=Asia/Shanghai连上后,查出来的时间可能比实际时间少8小时。解决办法是在Docker启动命令里加上时区环境变量:

-e TZ=Asia/Shanghai

或者在MySQL容器里执行:

SET GLOBAL time_zone = '+8:00'; SET SESSION time_zone = '+8:00';

建议两种情况都做,彻底根治时区漂移问题。

4. 常见问题与排查技巧实录

4.1 登录接口报401或token失效

这个问题出现频率最高。先明确一个规则:前端请求除了登录和注册,其他接口都要在请求头里带Authorization: Bearer <token>。如果你用Postman测试后端的/api/appointment/my接口,没有带token,返回401是正常的,那不是代码bug,是你们请求姿势不对。

但有一种情况是bug:token明明带了,后端解析还是失败。排查思路:

  1. 确认token生成和解析的密钥是否一致。JWT的secret如果写死在代码里,启动多实例或重启后失效的情况不存在,但要检查是不是前端存token的key和后端要求的不一致。
  2. 确认Spring Security或拦截器的放行路径配置是否正确。白名单里应该包含/api/auth/**、Swagger相关的路径,其他都需要鉴权。
  3. 检查token过期时间。如果设置的是30分钟,你调完接口吃完饭回来再测,过期了也是正常现象。把过期时间改长一点,或者用刷新token机制。

4.2 前端请求接口报CORS跨域错误

CORS分两种搞法:一种是前端Vite配代理,另一种是后端配跨域过滤器。如果两个都配了,可能会出问题。我建议是:开发环境用Vite代理,生产环境用Nginx代理,后端不要开启全局CORS。因为后端一旦开了CrossOrigin("*"),等于把所有域名都放进来,安全性上不太好控制。

如果你坚持在后端加跨域配置,用这样的过滤器:

@Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOriginPattern("*"); config.addAllowedMethod("*"); config.addAllowedHeader("*"); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } }

注意addAllowedOriginPattern是SpringBoot2.4以后的新方法,旧版本是用addAllowedOrigin。如果通配符写错了,联调时照样给你报CORS。

4.3 MyBatis-Plus自动填充失效或字段为null

自动填充是学习阶段最容易踩的坑:配置了MetaObjectHandler,但是插入数据时createTime还是null。原因是@TableField(fill = FieldFill.INSERT)注解漏写了,或者MetaObjectHandler的包路径配错了。另外一个隐蔽原因是:你在Service层通过save方法走MyBatis-Plus会自动填充,但如果你直接在ServiceImpl里用自定义SQL插入,自动填充不会触发。

还有字段映射问题:数据库字段是create_time,实体类属性是createTime,如果开启了驼峰命名映射(默认开启没问题),但如果你在配置文件里关了map-underscore-to-camel-case,那查询出来的对象里就会有一堆null。遇到字段为null,先去检查这个配置项。

4.4 Vue3页面组件之间传参不生效

Vue3里父子组件通信,最容易犯的错误是:父组件给子组件传的props是异步数据,子组件一渲染就读取,那时候数据还没到。解决办法有两个:一是用v-if控制子组件在数据到达后再渲染;二是在子组件里用watch监听props的变化。

非父子组件通信用Pinia或者EventBus。Pinia的写法比较简洁,适合全局存用户信息:

// store/user.js import { defineStore } from 'pinia' export const useUserStore = defineStore('user', { state: () => ({ token: '', userInfo: {} }), actions: { setToken(token) { this.token = token }, setUserInfo(info) { this.userInfo = info } } })

页面里调用useUserStore()拿到的store是响应式的,修改之后所有组件都会同步更新。这个项目如果用的Vuex,逻辑也类似,只是写法上Pinia更简单,建议新项目直接上Pinia。

4.5 Maven依赖冲突或下载缓慢

后端项目在mvn spring-boot:run或IDEA刷新依赖时,经常卡在下载这步。Maven默认中央仓库在国外,速度感人。改一下settings.xml里的mirror配置:

<mirror> <id>aliyun</id> <mirrorOf>central</mirrorOf> <name>Aliyun Maven Mirror</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>

改完后重新reimport,基本几分钟就能把依赖拉完。

依赖冲突的表现是:启动时NoSuchMethodError、ClassNotFoundException或者Bean创建异常。排查方法是mvn dependency:tree看依赖树,找重复或版本不一致的包,然后在pom里用<exclusion>排除掉旧版。这个项目用到SpringBoot2.7.x,整体依赖兼容性不错,但还是有可能因为lombok版本过旧跟JDK版本冲突,建议把lombok升级到1.18.30以上。

4.6 数据库连接报Public Key Retrieval is not allowed

这个报错比较典型,MySQL8.0使用caching_sha2_password加密插件时,JDBC驱动默认不允许在非SSL连接下检索公钥。解决办法在连接URL上加一个参数:

jdbc:mysql://localhost:3306/car_repair?allowPublicKeyRetrieval=true&useSSL=false

如果不加上这个,第一次连接大概率会报Public Key Retrieval is not allowed。加上后问题就消失了。如果还报错,检查一下useSSL=false是否也加上了,这两个通常要成对出现。

5. 针对网表异常的一些说明

这里针对几个典型异常场景做个汇总速查,我在本地搭环境时把这些坑都踩了一遍,如果你也遇到了,可以对号入座。

现象可能原因解决办法
MySQL连不上服务没启动/端口被占检查任务管理器、`netstat -ano
SpringBoot启动即报错数据库配置错误核对账号密码、URL、驱动
Mapper接口显示红色未加@Mapper@MapperScan在启动类加@MapperScan("com.xxx.mapper")
前端页面空白路由配置错误 / 组件导入路径不对看控制台报错,逐行排查
预约时间可重复提交后端冲突判断没生效检查状态筛选条件是否覆盖所有有效状态
时间显示少8小时时区配置不一致数据库、JDBC URL、JVM时区统一为Asia/Shanghai
上传的头像不显示静态资源映射路径配置错误检查WebMvcConfigaddResourceHandlers

最后再讲一个很多人没注意到的点:这个项目的文档(如果有)会包含数据库设计说明、接口文档、项目部署手册,建议一定要读。很多同学拿到源码直接跑代码,遇到问题了才翻文档,效率很低。正确姿势是先读文档里“项目介绍”和“数据库设计”两章,对整个系统的表结构有个全局认知,再动手跑代码,这样排查问题会快很多。我在实际跑这个项目的时候,因为先花了半小时过数据库表结构,后面遇到问题时基本不用翻源码就能定位到具体是哪张表、哪个接口、哪个字段出了问题。这个习惯,建议所有做Java Web项目的人都养成。

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

从0到1实战:用MCP服务器打通Figma与AI编程的上下文断层

最近在设计稿转前端的过程中&#xff0c;团队遇到一个反复出现的尴尬局面&#xff1a;AI 编程工具能写代码&#xff0c;但它看不懂设计稿的图层结构&#xff0c;只能依赖开发者手动截图、标注、测量间距和颜色。整个流程一旦涉及多页面、多组件&#xff0c;效率损耗非常明显。后…

作者头像 李华
网站建设 2026/9/9 12:49:25

QStackLayout实现无边框悬浮窗:拖拽、事件穿透与桌面浮层实战

简介&#xff1a;一份Qt界面开发学习资源&#xff0c;演示如何利用QStackLayout实现窗口部件重叠&#xff0c;并深度整合事件穿透、位置拖动与无边框窗口&#xff08;Qt::FramelessWindowHint&#xff09;下的尺寸拖拽。项目面向具备基础Qt知识、想实现非规则或分层界面的开发者…

作者头像 李华
网站建设 2026/9/9 12:46:17

Spring Boot汽车保险管理系统:数据库设计与核心功能实现

Spring Boot汽车保险管理系统&#xff0c;这个选题在计算机毕业设计里算是出现频率相当高的一个。一方面是因为车险业务本身流程清晰、表结构好设计&#xff0c;另一方面是它覆盖了用户管理、车辆信息、保单录入、保费计算、理赔登记、统计报表这些典型业务场景&#xff0c;用来…

作者头像 李华
网站建设 2026/9/9 12:40:13

hermes-agent:多Agent消息路由、任务编排与链路追踪的异步框架

做多Agent项目最折磨人的地方&#xff0c;往往不是模型效果不行&#xff0c;而是Agent之间“怎么说话”。我之前用LangChain把三个大模型串起来跑一个自动化调研流程&#xff0c;代码写到一半就乱了&#xff1a;前一个Agent的输出要给下一个用&#xff0c;中间还要接两个外部AP…

作者头像 李华