1. 项目概述
在快节奏的现代生活中,家政服务需求日益增长,但传统家政行业存在信息不透明、预约流程繁琐、服务质量难以追溯等问题。作为一名计算机专业的学生,我选择开发一个基于SpringBoot的家政服务管理系统作为毕业设计项目,旨在通过技术手段解决这些痛点。
这个系统采用B/S架构,前端使用Vue.js,后端采用SpringBoot框架,数据库选用MySQL,实现了从用户注册、服务预约到订单管理、服务评价的全流程线上化管理。系统最大的特色是将传统家政服务数字化,通过线上平台实现服务信息的透明化、预约流程的便捷化以及服务质量的追溯机制。
2. 系统架构设计
2.1 技术选型分析
在项目初期,我对比了多种技术方案,最终确定了以下技术栈:
-
前端技术:Vue.js + Element UI
- 选择理由:Vue.js轻量易学,组件化开发模式适合快速构建用户界面;Element UI提供了丰富的UI组件,能够满足系统各种交互需求
- 版本:Vue 2.6.x + Element UI 2.15.x
-
后端技术:SpringBoot 2.5.x + MyBatis
- 选择理由:SpringBoot简化了Spring应用的初始搭建和开发过程,内置Tomcat服务器,减少了配置工作;MyBatis作为ORM框架,提供了灵活的SQL编写方式
-
数据库:MySQL 8.0
- 选择理由:MySQL是成熟的关系型数据库,社区支持完善,性能稳定,且与SpringBoot集成简单
-
开发工具:IntelliJ IDEA + Navicat
- 选择理由:IDEA对Java和SpringBoot支持良好,智能提示和代码补全功能强大;Navicat是优秀的数据库管理工具
2.2 系统架构设计
系统采用经典的三层架构设计:
-
表现层(Presentation Layer):
- 负责用户界面展示和交互
- 使用Vue.js实现前端页面,通过RESTful API与后端通信
- 包含组件:用户登录/注册、服务展示、预约表单、个人中心等
-
业务逻辑层(Business Logic Layer):
- 处理核心业务逻辑
- 使用SpringBoot实现,包含Controller、Service等组件
- 主要功能模块:用户管理、家政人员管理、订单处理、评价系统等
-
数据访问层(Data Access Layer):
- 负责数据持久化
- 使用MyBatis实现数据库操作
- 主要实体:用户、家政人员、服务类型、订单、评价等
提示:在设计架构时,特别注意了各层之间的松耦合,便于后期维护和扩展。例如,业务逻辑层不直接依赖具体的数据访问实现,而是通过接口抽象。
3. 数据库设计
3.1 核心数据表设计
系统数据库包含以下主要表结构:
-
用户表(user):
sql复制CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL COMMENT '用户名', `password` varchar(100) NOT NULL COMMENT '密码', `real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名', `phone` varchar(20) NOT NULL COMMENT '手机号', `email` varchar(100) DEFAULT NULL COMMENT '邮箱', `avatar` varchar(255) DEFAULT NULL COMMENT '头像URL', `balance` decimal(10,2) DEFAULT '0.00' COMMENT '账户余额', `status` tinyint(1) DEFAULT '1' COMMENT '状态(0-禁用,1-正常)', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `idx_username` (`username`), UNIQUE KEY `idx_phone` (`phone`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; -
家政人员表(housekeeper):
sql复制CREATE TABLE `housekeeper` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL COMMENT '关联用户ID', `real_name` varchar(50) NOT NULL COMMENT '真实姓名', `id_card` varchar(18) NOT NULL COMMENT '身份证号', `gender` tinyint(1) DEFAULT '1' COMMENT '性别(0-女,1-男)', `age` int(3) DEFAULT NULL COMMENT '年龄', `work_years` int(2) DEFAULT NULL COMMENT '工作年限', `service_type` varchar(100) DEFAULT NULL COMMENT '服务类型(多选)', `region_code` varchar(20) DEFAULT NULL COMMENT '服务地区编码', `introduction` text COMMENT '个人介绍', `certificates` varchar(255) DEFAULT NULL COMMENT '证书(逗号分隔)', `star_level` decimal(2,1) DEFAULT '5.0' COMMENT '星级评分', `status` tinyint(1) DEFAULT '1' COMMENT '状态(0-下线,1-在线)', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `idx_user_id` (`user_id`), KEY `idx_region` (`region_code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='家政人员表'; -
服务订单表(service_order):
sql复制CREATE TABLE `service_order` ( `id` int(11) NOT NULL AUTO_INCREMENT, `order_no` varchar(32) NOT NULL COMMENT '订单编号', `user_id` int(11) NOT NULL COMMENT '用户ID', `housekeeper_id` int(11) NOT NULL COMMENT '家政人员ID', `service_id` int(11) NOT NULL COMMENT '服务项目ID', `service_time` datetime NOT NULL COMMENT '服务时间', `address` varchar(255) NOT NULL COMMENT '服务地址', `contact_name` varchar(50) NOT NULL COMMENT '联系人', `contact_phone` varchar(20) NOT NULL COMMENT '联系电话', `total_amount` decimal(10,2) NOT NULL COMMENT '订单总金额', `discount_amount` decimal(10,2) DEFAULT '0.00' COMMENT '优惠金额', `actual_amount` decimal(10,2) NOT NULL COMMENT '实付金额', `status` tinyint(1) DEFAULT '0' COMMENT '状态(0-待支付,1-已支付待服务,2-服务中,3-已完成,4-已取消,5-已退款)', `pay_time` datetime DEFAULT NULL COMMENT '支付时间', `complete_time` datetime DEFAULT NULL COMMENT '完成时间', `cancel_reason` varchar(255) DEFAULT NULL COMMENT '取消原因', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `idx_order_no` (`order_no`), KEY `idx_user_id` (`user_id`), KEY `idx_housekeeper_id` (`housekeeper_id`), KEY `idx_service_time` (`service_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务订单表';
3.2 数据库关系设计
系统采用实体-关系模型设计,主要实体关系如下:
- 用户与家政人员:一对一关系(一个用户账号只能对应一个家政人员身份)
- 用户与订单:一对多关系(一个用户可以创建多个订单)
- 家政人员与订单:一对多关系(一个家政人员可以接多个订单)
- 服务类型与订单:多对多关系(通过中间表关联)
注意事项:在设计数据库时,特别注意了索引的合理设置。例如,订单表的user_id、housekeeper_id和service_time字段都建立了索引,以提高查询效率。同时,对于频繁更新的字段如订单状态,避免建立过多索引,以免影响写入性能。
4. 核心功能实现
4.1 用户认证模块
用户认证采用JWT(JSON Web Token)实现,主要流程如下:
-
登录流程:
java复制@PostMapping("/login") public Result login(@RequestBody LoginDTO loginDTO) { // 1. 验证用户名密码 User user = userService.getByUsername(loginDTO.getUsername()); if (user == null || !passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) { return Result.error("用户名或密码错误"); } // 2. 生成JWT token String token = JwtUtil.generateToken(user.getId(), user.getUsername()); // 3. 返回用户信息和token Map<String, Object> data = new HashMap<>(); data.put("token", token); data.put("user", convertToVO(user)); return Result.success(data); } -
权限控制:
使用Spring Security实现基于角色的访问控制(RBAC),主要角色包括:- ROLE_USER:普通用户
- ROLE_HOUSEKEEPER:家政人员
- ROLE_ADMIN:管理员
java复制@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/auth/**").permitAll() .antMatchers("/api/user/**").hasAnyRole("USER", "HOUSEKEEPER", "ADMIN") .antMatchers("/api/housekeeper/**").hasRole("HOUSEKEEPER") .antMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager())) .addFilter(new JwtAuthorizationFilter(authenticationManager())); } }
4.2 服务预约模块
服务预约是系统的核心功能,主要实现以下业务逻辑:
-
服务查询:
- 支持按服务类型、地区、评分等多维度筛选
- 实现分页查询和排序功能
java复制@GetMapping("/services") public Result listServices( @RequestParam(required = false) Integer typeId, @RequestParam(required = false) String regionCode, @RequestParam(required = false, defaultValue = "1") Integer page, @RequestParam(required = false, defaultValue = "10") Integer size, @RequestParam(required = false, defaultValue = "star_level DESC") String sort) { Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.fromString( sort.split(" ")[1]), sort.split(" ")[0])); ServiceQuery query = new ServiceQuery(); query.setTypeId(typeId); query.setRegionCode(regionCode); Page<ServiceVO> result = serviceService.queryServices(query, pageable); return Result.success(result); } -
预约下单:
- 检查服务时间是否冲突
- 计算服务费用(基础费用+附加费用)
- 生成订单并锁定服务时间
java复制@PostMapping("/orders") public Result createOrder(@RequestBody OrderCreateDTO dto, @RequestHeader("Authorization") String token) { // 1. 验证用户身份 Integer userId = JwtUtil.getUserIdFromToken(token); // 2. 检查服务时间是否可用 if (!serviceTimeService.isTimeAvailable(dto.getHousekeeperId(), dto.getServiceTime())) { return Result.error("该时间段已被预约,请选择其他时间"); } // 3. 计算订单金额 Service service = serviceService.getById(dto.getServiceId()); BigDecimal totalAmount = calculateOrderAmount(service, dto.getDuration()); // 4. 创建订单 ServiceOrder order = new ServiceOrder(); order.setUserId(userId); order.setHousekeeperId(dto.getHousekeeperId()); order.setServiceId(dto.getServiceId()); order.setServiceTime(dto.getServiceTime()); order.setAddress(dto.getAddress()); order.setContactName(dto.getContactName()); order.setContactPhone(dto.getContactPhone()); order.setTotalAmount(totalAmount); order.setActualAmount(totalAmount); // 暂不考虑优惠 order.setStatus(OrderStatus.UNPAID.getCode()); orderService.createOrder(order); return Result.success("订单创建成功", order.getId()); }
4.3 评价系统模块
评价系统设计考虑了以下要点:
-
评价维度:
- 服务态度(1-5星)
- 专业技能(1-5星)
- 守时情况(1-5星)
- 文字评价(可选)
- 图片上传(可选)
-
评价流程:
- 只有已完成的服务可以评价
- 每个订单只能评价一次
- 评价后更新家政人员的综合评分
java复制@PostMapping("/reviews") public Result createReview(@RequestBody ReviewCreateDTO dto, @RequestHeader("Authorization") String token) { // 1. 验证用户身份 Integer userId = JwtUtil.getUserIdFromToken(token); // 2. 检查订单状态 ServiceOrder order = orderService.getById(dto.getOrderId()); if (order == null || !order.getUserId().equals(userId)) { return Result.error("订单不存在或无权评价"); } if (order.getStatus() != OrderStatus.COMPLETED.getCode()) { return Result.error("只有已完成的服务可以评价"); } // 3. 检查是否已评价 if (reviewService.existsByOrderId(dto.getOrderId())) { return Result.error("该订单已评价"); } // 4. 创建评价 ServiceReview review = new ServiceReview(); review.setOrderId(dto.getOrderId()); review.setUserId(userId); review.setHousekeeperId(order.getHousekeeperId()); review.setServiceId(order.getServiceId()); review.setAttitudeScore(dto.getAttitudeScore()); review.setSkillScore(dto.getSkillScore()); review.setPunctualityScore(dto.getPunctualityScore()); review.setContent(dto.getContent()); review.setImages(StringUtils.join(dto.getImages(), ",")); reviewService.createReview(review); // 5. 更新家政人员评分 housekeeperService.updateStarLevel(order.getHousekeeperId()); return Result.success("评价成功"); }
5. 系统测试与优化
5.1 功能测试
系统测试采用以下策略:
-
单元测试:使用JUnit + Mockito对核心业务逻辑进行测试
java复制@Test public void testCreateOrder_Success() { // 准备测试数据 OrderCreateDTO dto = new OrderCreateDTO(); dto.setHousekeeperId(1); dto.setServiceId(1); dto.setServiceTime(LocalDateTime.now().plusDays(1)); dto.setDuration(2); dto.setAddress("测试地址"); dto.setContactName("测试联系人"); dto.setContactPhone("13800138000"); // Mock服务 when(serviceTimeService.isTimeAvailable(anyInt(), any())).thenReturn(true); when(serviceService.getById(anyInt())).thenReturn(new Service()); when(orderService.createOrder(any())).thenReturn(1); // 执行测试 Result result = orderController.createOrder(dto, "mock_token"); // 验证结果 assertEquals(Result.SUCCESS_CODE, result.getCode()); assertNotNull(result.getData()); } -
集成测试:使用TestRestTemplate测试API接口
-
前端测试:使用Jest进行组件测试
5.2 性能优化
针对系统性能瓶颈,实施了以下优化措施:
-
数据库优化:
- 添加合适的索引
- 对大表进行分表(如订单表按月份分表)
- 使用连接池(HikariCP)
-
缓存策略:
- 使用Redis缓存热门服务数据
- 实现二级缓存(Caffeine + Redis)
java复制@Configuration @EnableCaching public class CacheConfig { @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { return RedisCacheManager.builder(factory) .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(30)) .disableCachingNullValues()) .withInitialCacheConfigurations(getCacheConfigurations()) .build(); } private Map<String, RedisCacheConfiguration> getCacheConfigurations() { Map<String, RedisCacheConfiguration> configMap = new HashMap<>(); // 服务数据缓存1小时 configMap.put("services", RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1))); return configMap; } } -
接口优化:
- 对列表接口实现分页
- 使用DTO减少不必要的数据传输
- 对复杂查询使用@Transactional(readOnly = true)
6. 项目总结与经验分享
在开发这个家政服务管理系统的过程中,我积累了一些宝贵的经验:
-
需求分析要彻底:在项目初期,我花了大量时间与潜在用户交流,了解他们的真实需求。这帮助我避免了后期频繁的需求变更。
-
技术选型要务实:作为毕业设计项目,我选择了相对成熟且文档丰富的主流技术,而不是盲目追求新技术。这大大降低了开发难度和学习成本。
-
代码规范很重要:从一开始就坚持良好的编码习惯,包括合理的包结构、一致的命名规范、适当的注释等。这在后期维护和功能扩展时节省了大量时间。
-
测试驱动开发:虽然项目规模不大,但我仍然坚持编写单元测试和集成测试。这帮助我及早发现并修复了许多潜在问题。
-
性能考虑要前置:在数据库设计和接口实现阶段就考虑性能问题,比后期优化要高效得多。例如,合理设计索引、避免N+1查询等问题。
对于想要开发类似系统的同学,我有以下几点建议:
- 先从核心功能入手,如用户认证和服务预约,再逐步扩展其他功能
- 使用版本控制工具(如Git)管理代码,定期提交并写好提交信息
- 文档要及时更新,包括API文档、数据库设计文档等
- 部署可以使用Docker简化环境配置
- 重视用户体验,多进行可用性测试
这个项目让我对SpringBoot全栈开发有了更深入的理解,也让我认识到一个完整的系统需要考虑的方方面面。虽然还有很多可以改进的地方,但作为毕业设计,它已经达到了我预期的目标。