1. 项目概述:影院票务管理的数字化升级
去年参与某连锁影院系统改造时,我深刻体会到传统人工售票的痛点:黄金时段排长队、座位冲突频发、财务对账困难。这套基于SpringBoot+Vue的影院购票系统,正是为解决这些行业痛点而设计的全栈解决方案。系统采用前后端分离架构,后端使用SpringBoot提供RESTful API,前端通过Vue实现响应式交互,数据库选用MySQL 8.0存储业务数据。实测在200座影厅的售票场景下,系统能稳定支撑每秒50笔并发交易。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心功能模块解析
2.1 多维度影院管理
采用树形结构存储影院-影厅层级关系,核心数据表设计如下:
sql复制CREATE TABLE `cinema` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8mb4_bin NOT NULL,
`address` varchar(200) COLLATE utf8mb4_bin DEFAULT NULL,
`contact_phone` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
影厅管理特别处理了座位模板功能,通过JSON存储座位矩阵:
java复制// 影厅座位配置示例
{
"rows": 10,
"cols": 15,
"disabledSeats": ["A1","B5"],
"vipSeats": ["C8","D9"]
}
2.2 动态排片与锁座机制
排片系统采用时间重叠校验算法,防止同一影厅排片冲突:
java复制public boolean checkScheduleConflict(LocalDateTime start, LocalDateTime end, Integer hallId) {
return scheduleMapper.countOverlappingSchedules(
start.minusMinutes(10), // 预留10分钟散场时间
end.plusMinutes(5), // 包含5分钟误差缓冲
hallId
) > 0;
}
座位锁定使用Redis分布式锁实现,关键代码:
java复制public boolean lockSeats(Integer scheduleId, List<String> seats) {
String lockKey = "seat_lock:" + scheduleId;
return redisTemplate.opsForValue().setIfAbsent(
lockKey,
seats.toString(),
5, TimeUnit.MINUTES // 5分钟未支付自动释放
);
}
3. 购票业务流程实现
3.1 选座购票流程
- 前端通过WebSocket实时获取座位状态
- 选择座位后发起预占请求
- 生成待支付订单(15分钟有效期)
- 支付成功后更新座位状态
状态机设计:
mermaid复制stateDiagram
[*] --> 待支付
待支付 --> 已取消: 超时未支付
待支付 --> 已支付: 支付成功
已支付 --> 已完成: 观影时间结束
3.2 支付对接方案
系统集成微信支付和支付宝沙箱环境,支付回调处理要点:
java复制@PostMapping("/pay/notify")
public String paymentNotify(@RequestBody String notifyData) {
// 1. 验证签名
if(!paymentService.verifySign(notifyData)) {
return "failure";
}
// 2. 更新订单状态
Order order = parseOrder(notifyData);
if(orderService.updateOrderStatus(order)) {
// 3. 释放座位锁
seatService.unlockSeats(order.getScheduleId());
return "success";
}
return "processing";
}
4. 后台管理功能实现
4.1 票房统计模块
使用ECharts实现多维度数据可视化:
- 日/周/月票房趋势图
- 影片上座率热力图
- 会员消费占比饼图
统计SQL示例:
sql复制SELECT
f.title AS filmName,
COUNT(t.id) AS ticketCount,
SUM(t.actual_price) AS totalAmount
FROM
ticket t
JOIN schedule s ON t.schedule_id = s.id
JOIN film f ON s.film_id = f.id
WHERE
t.create_time BETWEEN :start AND :end
GROUP BY
f.id
ORDER BY
totalAmount DESC
LIMIT 10;
4.2 权限控制系统
基于RBAC模型设计,包含:
- 菜单权限表(menu)
- 角色表(role)
- 用户角色关联表(user_role)
- 角色菜单关联表(role_menu)
权限校验拦截器:
java复制public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
String requestURI = request.getRequestURI();
User user = getCurrentUser();
if(!permissionService.hasPermission(user.getId(), requestURI)) {
response.sendError(403, "无访问权限");
return false;
}
return true;
}
5. 系统部署与优化实践
5.1 性能优化方案
- 二级缓存配置:
yaml复制spring:
cache:
type: redis
redis:
time-to-live: 30m
key-prefix: "cinema:"
cache-null-values: false
- Nginx静态资源配置:
nginx复制server {
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://backend;
proxy_set_header X-Real-IP $remote_addr;
}
}
5.2 常见问题排查
- 座位状态不同步问题:
- 检查WebSocket连接状态
- 验证Redis pub/sub通道配置
- 确认后端事件发布逻辑
- 支付回调失败处理:
java复制@Scheduled(fixedDelay = 300000) // 5分钟轮询一次
public void checkUnconfirmedOrders() {
List<Order> orders = orderService.getUnpaidOrders();
orders.forEach(order -> {
PaymentStatus status = paymentService.queryPayment(order.getPayNo());
if(status == PaymentStatus.SUCCESS) {
orderService.confirmOrder(order.getId());
}
});
}
6. 项目二次开发指南
6.1 基础修改建议
- 修改系统名称:
- 前端:/src/config/settings.js
- 后端:application.yml中的spring.application.name
- 调整票务规则:
java复制// 票价计算策略接口
public interface PriceStrategy {
BigDecimal calculate(Schedule schedule, Seat seat);
}
// 节假日价格策略实现
@Component
@ConditionalOnProperty(name = "pricing.mode", havingValue = "holiday")
public class HolidayPriceStrategy implements PriceStrategy {
@Override
public BigDecimal calculate(Schedule schedule, Seat seat) {
// 实现特定计价逻辑
}
}
6.2 扩展功能方向
- 会员积分系统:
- 消费积分累计
- 积分兑换优惠券
- 会员等级权益
- 智能推荐模块:
- 基于用户历史记录的影片推荐
- 相似用户偏好分析
- 热映影片排行榜
项目源码采用模块化设计,核心包结构:
code复制com.cinema
├── admin -- 管理后台功能
├── gateway -- API网关
├── order -- 订单服务
├── payment -- 支付服务
├── schedule -- 排片服务
└── user -- 用户中心
在开发过程中,特别要注意影院业务的时间敏感性,所有涉及时间比较的操作都必须使用UTC时间戳处理,避免时区问题导致的排片错误。对于座位状态这种高并发场景,建议采用Redisson的分布式锁替代原生Redis命令,提高锁机制的可靠性。
