1. 项目背景与需求分析
剧本杀作为一种新兴的线下社交娱乐方式,近年来在国内迅速流行。然而传统的剧本杀门店管理仍停留在人工登记、电话预约等低效方式上,存在诸多痛点:
-
预约效率低下:玩家需要通过电话或到店咨询场次信息,门店工作人员需要反复确认时间、人数等信息,沟通成本高。
-
资源调配困难:热门剧本的场次安排、DM(主持人)分配等全靠人工记忆和经验判断,容易出现冲突或资源浪费。
-
数据统计缺失:无法实时掌握各剧本的上座率、玩家偏好等经营数据,难以做出科学的运营决策。
-
用户体验不佳:玩家无法自主查看可选场次、剧本详情,预约过程繁琐,缺乏线上互动渠道。
基于这些实际问题,我们决定开发一套专业的剧本杀门店管理系统,核心目标包括:
- 实现7×24小时在线预约,打破时间和空间限制
- 建立完善的剧本、场次、DM管理体系
- 提供多维度的经营数据分析功能
- 打造用户友好的交互界面和流畅的预约流程
2. 技术选型与架构设计
2.1 技术栈选择
经过对项目需求和团队技术储备的综合评估,我们最终确定了以下技术方案:
后端框架:Spring Boot 2.7.x
- 优势:约定优于配置,快速构建生产级应用;丰富的starter依赖;内嵌Tomcat简化部署
- 选型理由:团队熟悉Java生态,Spring Boot的开发效率高,社区支持完善
数据库:MySQL 8.0
- 采用InnoDB存储引擎,支持事务
- 设计合理的索引提升查询性能
- 使用Flyway管理数据库迁移
前端技术:Vue.js + Element UI
- 前后端分离架构,通过RESTful API交互
- Element UI提供丰富的组件,加速开发
- Axios处理HTTP请求,Vuex管理状态
其他关键技术:
- Redis:缓存热点数据,如剧本详情、场次余量
- JWT:实现无状态认证
- Swagger:API文档自动生成
- Lombok:简化Java Bean编写
2.2 系统架构设计
系统采用标准的B/S三层架构,具体分层如下:
表现层(Presentation Layer)
- 职责:处理HTTP请求,返回响应
- 实现:Spring MVC
- 关键组件:
- Controller:接收请求,调用Service
- DTO:数据传输对象
- 异常处理器:统一处理业务异常
- 拦截器:权限校验、日志记录
业务层(Business Layer)
- 职责:实现核心业务逻辑
- 实现:Spring Service
- 关键设计:
- 事务管理:@Transactional注解
- 业务异常:自定义异常体系
- 日志记录:AOP实现操作日志
持久层(Persistence Layer)
- 职责:数据访问和持久化
- 实现:MyBatis-Plus
- 关键特性:
- 代码生成器:自动生成Mapper
- 条件构造器:简化复杂查询
- 分页插件:自动处理分页逻辑
提示:分层架构的关键是明确各层职责边界,避免层间耦合。例如Controller不应包含业务逻辑,Service不应处理HTTP细节。
3. 核心功能模块实现
3.1 用户权限系统
3.1.1 角色设计
系统定义了三类角色,通过RBAC模型管理权限:
-
普通用户:
- 注册/登录
- 查看剧本、场次
- 预约/取消预约
- 个人信息管理
-
DM(主持人):
- 继承普通用户所有权限
- 查看分配场次
- 提交场次反馈
-
管理员:
- 用户管理
- 剧本CRUD
- 场次安排
- 数据统计
3.1.2 权限控制实现
java复制// 使用Spring Security配置权限
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/dm/**").hasAnyRole("DM", "ADMIN")
.antMatchers("/user/**").authenticated()
.anyRequest().permitAll()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()));
}
}
3.1.3 用户注册流程
- 前端提交注册表单(用户名、密码、手机号)
- 后端校验数据合法性
- 密码加盐哈希存储
- 生成默认用户角色
- 发送欢迎短信(异步)
注意事项:密码必须加密存储,推荐使用BCryptPasswordEncoder;手机号需验证真实性,可通过短信验证码实现。
3.2 剧本管理模块
3.2.1 数据结构设计
sql复制CREATE TABLE `script` (
`id` bigint NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL COMMENT '剧本名称',
`type_id` int NOT NULL COMMENT '剧本类型',
`difficulty` tinyint DEFAULT '3' COMMENT '难度(1-5)',
`duration` int NOT NULL COMMENT '预计时长(分钟)',
`player_min` int NOT NULL COMMENT '最少人数',
`player_max` int NOT NULL COMMENT '最多人数',
`price` decimal(10,2) NOT NULL COMMENT '单价',
`cover_url` varchar(255) DEFAULT NULL COMMENT '封面图URL',
`description` text COMMENT '剧本描述',
`status` tinyint DEFAULT '1' COMMENT '状态(0下架/1上架)',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_type` (`type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2.2 关键业务逻辑
剧本上架流程:
- 管理员填写剧本信息
- 上传封面图(OSS存储)
- 设置初始库存
- 审核通过后上架
剧本搜索实现:
- 基础搜索:基于标题、类型的模糊查询
- 高级筛选:难度、时长、人数范围
- 性能优化:为常用查询条件建立组合索引
3.3 预约系统设计
3.3.1 场次模型
java复制public class Session {
private Long id;
private Long scriptId;
private Long dmId;
private LocalDateTime startTime;
private LocalDateTime endTime;
private Integer maxPlayers;
private Integer bookedPlayers;
private Integer status; // 0-未开始 1-进行中 2-已完成 3-已取消
}
3.3.2 预约流程
- 用户查询可用场次
- 选择场次并确认人数
- 系统校验:
- 场次状态是否可预约
- 剩余名额是否充足
- 创建预约订单
- 更新场次已预约人数
- 发送预约确认通知
3.3.3 并发控制
使用乐观锁防止超卖:
sql复制UPDATE session SET booked_players = booked_players + ?
WHERE id = ? AND booked_players + ? <= max_players
4. 系统优化与问题解决
4.1 性能优化实践
缓存策略:
- Redis缓存热点剧本信息(TTL 1小时)
- 场次余量使用Redis原子计数器
- 本地缓存(Caffeine)存储不常变的配置
SQL优化:
- 为所有查询条件添加合适索引
- 避免SELECT *,只查询必要字段
- 复杂查询拆分为多个简单查询
4.2 典型问题排查
问题1:预约高峰期系统响应变慢
- 排查:发现MySQL连接池耗尽
- 解决:调整连接池参数,增加从库分担读压力
问题2:重复预约
- 现象:同一用户多次点击导致创建多个预约
- 解决:前端防重提交+后端幂等设计
问题3:场次状态不同步
- 原因:定时任务更新不及时
- 解决:引入状态机模式,明确状态转换规则
4.3 安全防护措施
- 输入校验:所有API参数进行合法性校验
- XSS防护:前端转义+后端过滤
- CSRF防护:Spring Security默认启用
- SQL注入:MyBatis参数绑定
- 敏感数据:手机号等隐私信息脱敏
5. 部署与监控
5.1 生产环境部署
服务器配置:
- 应用服务器:2核4G × 2(负载均衡)
- 数据库:4核8G(主从架构)
- Redis:2G内存独立实例
部署流程:
- Jenkins自动化构建
- Docker镜像打包
- Kubernetes滚动更新
- 健康检查+服务注册
5.2 监控方案
基础监控:
- Prometheus:采集服务器指标
- Grafana:可视化监控面板
业务监控:
- 关键业务指标(预约量、转化率)
- 异常报警(短信+邮件)
- 日志集中分析(ELK)
在实际运行中,我们发现两个特别值得注意的经验:一是场次安排应该预留至少15分钟的缓冲时间,避免前后场次衔接出现问题;二是用户预约后的提醒消息应该包含详细的准备事项,这能显著降低用户迟到率。