1. 项目背景与需求分析
最近给本地一家体育中心做了套场地预约系统,客户是琪华体育中心,主要解决他们足球场地预约管理混乱的问题。之前他们全靠人工登记,经常出现重复预约、时间冲突的情况,特别是周末高峰期,前台电话都快被打爆了。
这个系统需要实现三个核心功能:
- 用户端:在线查看场地档期、预约支付、取消预约
- 管理端:场地信息维护、预约订单审核、营收统计
- 硬件对接:门禁系统核销(后期扩展)
选择SpringBoot+Vue这个技术栈主要考虑:
- 体育中心现有IT基础设施一般,需要轻量级方案
- 运维人员Java基础较好,后期维护成本低
- Vue前端学习曲线平缓,方便行政人员操作
2. 技术架构设计
2.1 后端架构
采用经典三层架构:
code复制└── com.qihua.sports
├── config # 安全配置
├── controller # 对外接口
├── service # 业务逻辑
│ ├── impl # 实现类
├── dao # 数据访问
├── entity # 实体类
└── util # 工具包
关键依赖:
xml复制<!-- 核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
<!-- 特色功能 -->
<dependency> <!-- 微信支付 -->
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.7</version>
</dependency>
<dependency> <!-- 场地冲突检测 -->
<groupId>org.joda</groupId>
<artifactId>joda-time</artifactId>
<version>2.12.5</version>
</dependency>
2.2 数据库设计
核心表结构:
| 表名 | 字段示例 | 说明 |
|---|---|---|
| t_field | id,name,type,status | 场地基本信息 |
| t_schedule | id,field_id,date,time_slot | 场地档期 |
| t_order | order_no,user_id,field_id,status | 预约订单 |
| t_user | openid,nickname,mobile | 微信用户 |
特别注意:
- 时间字段统一用UTC时间戳存储
- 订单号采用
FD+年月日+6位随机数的规则生成 - 场地状态用枚举值(0-空闲 1-已预约 2-维护中)
2.3 前端框架选型
使用Vue3组合式API开发,主要考虑:
- Element Plus组件库成熟度高
- Vite构建速度快,适合频繁调试
- Pinia状态管理简单直接
典型页面结构:
bash复制src/
├── api/ # 接口封装
├── assets/ # 静态资源
├── components/ # 公共组件
│ ├── FieldCard.vue # 场地卡片
│ └── TimePicker.vue # 时间选择器
├── router/ # 路由配置
├── stores/ # 状态管理
└── views/
├── user/ # 用户端
└── admin/ # 管理端
3. 核心功能实现
3.1 预约冲突检测
关键算法逻辑:
java复制public boolean checkConflict(Long fieldId, LocalDateTime start, LocalDateTime end) {
return orderMapper.selectList(new QueryWrapper<Order>()
.eq("field_id", fieldId)
.eq("status", 1) // 已支付订单
.apply("(start_time < {0} AND end_time > {1})", end, start)
).isEmpty();
}
实际开发中踩过的坑:
- 时区问题:前端传北京时间,后端存UTC,需要统一转换
- 缓冲时间:需预留30分钟场地整理时间,在SQL条件中额外加减
- 并发控制:使用@Transactional + SELECT FOR UPDATE防止超卖
3.2 微信支付集成
支付流程:
- 前端调起JSAPI支付
- 后端生成预支付订单(关键代码):
java复制WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withMerchant(merchantId, merchantSerialNo, privateKey)
.withValidator(new WechatPay2Validator(verifier));
CloseableHttpClient httpClient = builder.build();
HttpPost post = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
post.addHeader("Accept", "application/json");
post.addHeader("Content-type", "application/json; charset=utf-8");
post.setEntity(new StringEntity(payRequest.toJsonString()));
- 支付成功后微信回调通知
- 更新订单状态并发送短信提醒
3.3 可视化排期表
使用FullCalendar组件实现:
vue复制<template>
<FullCalendar :options="calendarOptions" />
</template>
<script setup>
import FullCalendar from '@fullcalendar/vue3'
import dayGridPlugin from '@fullcalendar/daygrid'
import timeGridPlugin from '@fullcalendar/timegrid'
const calendarOptions = {
plugins: [dayGridPlugin, timeGridPlugin],
initialView: 'timeGridWeek',
slotMinTime: '08:00:00',
slotMaxTime: '22:00:00',
events: loadScheduleData // 从API加载数据
}
</script>
4. 性能优化实践
4.1 缓存策略
采用多级缓存方案:
- Redis缓存热点数据(场地信息、价格策略)
- 本地Caffeine缓存用户基本信息
- HTTP缓存静态资源
配置示例:
yaml复制spring:
cache:
type: redis
redis:
time-to-live: 1h
redis:
host: 127.0.0.1
port: 6379
4.2 SQL优化技巧
- 为高频查询字段添加复合索引:
sql复制CREATE INDEX idx_field_schedule ON t_schedule (field_id, date, time_slot);
- 使用EXPLAIN分析慢查询
- 批量操作代替循环单条插入
4.3 前端性能提升
- 路由懒加载
js复制const FieldList = () => import('./views/FieldList.vue')
- 图片使用WebP格式
- API请求防抖处理
5. 安全防护措施
5.1 接口安全
- JWT认证流程:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthFilter(authenticationManager()));
}
}
- 敏感数据脱敏处理
- 接口限流(Guava RateLimiter)
5.2 数据安全
- 密码加密存储(BCrypt)
- 日志脱敏处理
- 定期备份策略
5.3 支付安全
- 签名验证
- 金额二次确认
- 对账机制
6. 部署与运维
6.1 服务器配置
推荐配置:
- 2核4G云服务器(用户量<1000)
- CentOS 7.6
- OpenJDK 11
- Nginx 1.18
6.2 部署脚本示例
bash复制#!/bin/bash
# 后端部署
mvn clean package
scp target/sports-center.jar user@server:/opt/app
# 前端部署
npm run build
rsync -avz dist/ user@server:/var/www/html
6.3 监控方案
- Spring Boot Actuator健康检查
- Prometheus + Grafana监控
- 关键业务日志ELK收集
7. 典型问题排查
7.1 支付回调失败
排查步骤:
- 检查微信商户平台配置
- 验证签名算法
- 查看Nginx访问日志
7.2 档期显示异常
常见原因:
- 时区配置不一致
- 缓存未及时更新
- 数据库连接池耗尽
7.3 并发预约冲突
解决方案:
- 添加数据库乐观锁
- 引入分布式锁(Redisson)
- 前端增加loading状态防止重复提交
8. 扩展功能规划
- 会员积分系统
- 赛事活动模块
- 智能推荐时段
- 天气影响预警
这个项目从需求分析到上线用了3个月时间,最大的体会是体育场馆的线下业务流程一定要摸透,我们前期花了2周时间蹲点观察他们的实际运营流程,这比任何需求文档都有价值。现在系统日均处理300+预约订单,客户最满意的是自动冲突检测功能,再也没出现过"一场多卖"的情况。