简介
本文件面向“预约时段管理”的数据模型与实现,聚焦于预约时段表 book_schedule(在文档中常以 dou_book_schedule 指代)的字段设计、自动切分机制、启用禁用与排序规则、冲突检测与并发控制策略,以及与项目、规则的关联关系。内容同时覆盖后台配置流程与前端展示逻辑,帮助时段配置管理员与系统开发者快速理解并正确使用该模块。
项目结构
围绕预约时段的核心代码分布在以下位置:
- 数据访问层:后台 BookSchedule 模型定义表名、主键、可写字段与类型转换
- 业务服务层:后台 ScheduleService 提供列表、新增、编辑、删除等能力;核心 BookService 负责日期/时段生成、容量与价格计算、冲突校验
- 控制器层:后台 ScheduleController 暴露增删改查页面入口
- 视图层:book_schedule.htm 提供时段表单(容量、加价、排序、状态等)
- 关联模型:BookItem 表示预约项目,book_schedule.item_id 与其关联
- API 路由:api/route/book.php 声明预约相关接口(含 schedule/date/time 等)
graph TB
A["后台控制器<br/>ScheduleController"] --> B["后台服务<br/>ScheduleService"]
B --> C["数据模型<br/>BookSchedule"]
B --> D["数据库查询<br/>book_schedule / book_item"]
E["核心服务<br/>BookService"] --> F["时段生成与校验<br/>日期/时段/容量/价格"]
A --> G["视图模板<br/>book_schedule.htm"]
H["API路由<br/>book.php"] --> E
核心组件
- 数据模型:BookSchedule 定义 book_schedule 表的映射、主键 id、可写入字段集合(包含 item_id、weekday、start_time、end_time、duration、capacity、price_extra、sort、status、created_at)以及类型转换
- 后台服务:ScheduleService 提供列表构建、新增、编辑、删除等能力,并对时间字段进行格式化输出
- 核心服务:BookService 负责根据项目与规则生成可用日期与时段,计算剩余容量、价格、用户已约状态,并执行冲突与容量限制检查
- 控制器:ScheduleController 将请求转发至服务层,渲染后台页面
- 视图:book_schedule.htm 提供时段配置表单(容量、加价、排序、状态)
架构总览
预约时段管理的整体流程如下:
- 后台管理员通过 ScheduleController 进入时段管理页面,使用 ScheduleService 获取列表或提交新增/更新
- 列表页按 item_id、weekday、start_time 排序展示,支持分页
- 新增/编辑时,表单字段包括 weekday、start_time、end_time、duration、capacity、price_extra、sort、status
- 核心服务 BookService 在展示与预约时,基于项目与规则生成实际可用的时段,结合容量、价格、用户已约状态进行过滤与提示
- API 端提供 schedule/date/time 等接口供小程序/前端调用
sequenceDiagram
participant Admin as "后台管理员"
participant Ctrl as "ScheduleController"
participant Svc as "ScheduleService"
participant Model as "BookSchedule"
participant Core as "BookService"
participant DB as "数据库"
Admin->>Ctrl : 打开时段列表/新增/编辑
Ctrl->>Svc : 构建列表/新增/更新
Svc->>DB : 查询 book_schedule + book_item
DB-->>Svc : 返回记录
Svc-->>Ctrl : 组装视图数据
Ctrl-->>Admin : 渲染页面
Admin->>Core : 选择日期/时段预约
Core->>DB : 查询项目/规则/时段/占用
Core-->>Admin : 返回可用时段与状态
详细组件分析
数据模型:book_schedule 字段设计
- id:主键,唯一标识一个时段
- item_id:关联预约项目(book_item.id),用于限定该时段属于哪个项目
- weekday:星期配置(1-7),决定该时段适用于周几
- start_time:时段开始时间(HH:MM:SS)
- end_time:时段结束时间(HH:MM:SS)
- duration:时长设置(分钟)。当为 0 时表示按项目默认时长自动切分时段
- capacity:容量控制,表示该时段最多可预约人数
- price_extra:价格调整,表示在该时段相对于基础价格的额外加价
- sort:排序管理,用于同一项目下时段的前后顺序
- status:状态控制,1 启用、0 禁用,影响是否参与排班与展示
- created_at:创建时间
说明
- 列表与编辑界面均会显示上述字段,其中 start_time/end_time 在后台通常以 HH:MM 形式输入与展示
- 新增/更新时对 capacity 做最小值保护(至少为 1),对 price_extra 做浮点处理,对 sort 做整数处理
自动切分机制:duration 为 0 时的行为
- 当 duration 为 0 时,系统不会将该条记录视为固定时间段,而是作为“模板”,由核心服务根据项目的默认时长自动切分为多个具体时段
- 自动切分发生在核心服务生成可用时段的过程中,会将模板展开为多个连续的时间片,每个时间片具备独立的容量与价格信息
- 这种机制便于统一维护“工作日+时间段范围+默认时长”的规则,减少重复录入
flowchart TD
Start(["开始"]) --> CheckDur{"duration == 0 ?"}
CheckDur -- 否 --> UseFixed["使用固定 start_time~end_time"]
CheckDur -- 是 --> Expand["按项目默认时长自动切分时段"]
Expand --> BuildMap["生成时段映射含容量/价格"]
UseFixed --> BuildMap
BuildMap --> End(["结束"])
启用禁用状态管理与排序规则
- status:1 启用、0 禁用。启用的时段才会参与排班与展示;禁用的时段不参与
- sort:同项目内时段排序依据,越小越靠前;列表按 item_id、weekday、start_time 排序展示
- 后台列表与编辑界面均支持修改 status 与 sort,保存后即时生效
时段冲突检测算法
冲突检测主要发生在用户预约阶段,核心服务会执行以下检查:
- 关闭检查:若项目当天被标记为关闭,则不可预约
- 时段存在性检查:确认所选时段在 schedule 中存在且启用(支持 duration=0 的自动切分结果)
- 容量检查:统计该时段已被预约数量,若达到 capacity(可能受规则覆盖)则拒绝预约
- 用户维度检查:如用户已在该时段预约过,则给出相应提示
flowchart TD
S(["预约请求"]) --> Closed{"当天关闭?"}
Closed -- 是 --> Deny1["拒绝:时段关闭"]
Closed -- 否 --> Exists{"时段存在且启用?"}
Exists -- 否 --> Deny2["拒绝:无可用时段"]
Exists -- 是 --> Cap{"容量是否足够?"}
Cap -- 否 --> Deny3["拒绝:约满"]
Cap -- 是 --> UserCheck{"用户是否已约?"}
UserCheck -- 是 --> Deny4["提示:已预约"]
UserCheck -- 否 --> Allow["允许预约"]
并发控制策略
- 当前实现未显式使用分布式锁或行级锁;容量检查基于数据库计数与条件判断
- 在高并发场景下,建议在预约落库前增加事务与唯一约束(例如 user_id + item_id + date + start_time 的唯一索引),或在关键路径加锁,避免超卖
- 建议将容量扣减与订单创建放在同一事务中,确保一致性
时段与项目、规则的关联关系
- 与项目:book_schedule.item_id 指向 book_item.id,用于限定该时段属于哪个预约项目;删除项目时会级联删除其时段
- 与规则:核心服务在生成时段时会合并规则(如 add/replace 模式),规则可覆盖容量与价格,并支持 duration 拆分
- 项目默认时长:当 duration=0 时,按项目默认时长自动切分,体现项目层配置对时段生成的影响
后台管理流程(控制器与服务)
- 列表:按 item_id、weekday、start_time 排序,分页展示
- 新增:填充默认值(如 duration=60、capacity=1、price_extra=0、sort=50、status=1)
- 编辑:读取现有记录并格式化时间字段
- 删除:二次确认后删除,并记录操作日志
sequenceDiagram
participant U as "管理员"
participant C as "ScheduleController"
participant S as "ScheduleService"
participant M as "BookSchedule"
U->>C : 打开列表/新增/编辑
C->>S : buildScheduleListData / insert / update
S->>M : create / fill/save
M-->>S : 持久化结果
S-->>C : 返回成功/错误
C-->>U : 跳转并提示
前端展示与 API
- 小程序/前端通过 API 路由 book.php 提供的接口获取 schedule/date/time 等信息
- 前端会根据返回的 time_list 展示可用时段,并根据 remaining/full/user_booked/closed 等字段进行状态提示
依赖关系分析
- 控制器依赖服务:ScheduleController 依赖 ScheduleService
- 服务依赖模型与数据库:ScheduleService 通过 BookSchedule 模型与 DB 查询 book_schedule 与 book_item
- 核心服务依赖项目与规则:BookService 根据项目配置与规则生成时段,并计算容量与价格
- 视图依赖服务数据:book_schedule.htm 接收服务层构造的表单数据
graph LR
Ctrl["ScheduleController"] --> Svc["ScheduleService"]
Svc --> Model["BookSchedule"]
Svc --> DB["book_schedule / book_item"]
Core["BookService"] --> Rule["规则/项目配置"]
View["book_schedule.htm"] --> Svc
性能考虑
- 列表查询已按 item_id、weekday、start_time 排序并分页,适合常规规模
- 时段生成与冲突检测涉及多次数据库查询,建议在高频访问场景引入缓存(如 Redis)缓存项目可用日期与时段
- 高并发预约需考虑事务与唯一约束,避免超卖与重复预约
故障排查指南
- 无法显示时段:检查 status 是否为 1,weekday 是否与目标日期匹配,start_time/end_time 是否正确
- 时段不可预约:查看 remaining 是否为 0,或用户是否已预约;检查项目是否关闭
- 删除失败:确认 id 有效,并遵循二次确认流程
- 排序异常:检查 sort 值与列表排序规则(item_id、weekday、start_time)
结论
book_schedule 表是预约时段管理的核心,通过 item_id、weekday、start_time、end_time、duration、capacity、price_extra、sort、status 等字段实现对时段的精细化配置。当 duration=0 时,系统按项目默认时长自动切分时段,提升配置效率。核心服务在展示与预约阶段进行冲突检测与容量控制,确保资源合理分配。建议在高并发场景补充事务与唯一约束,以提升一致性与稳定性。
附录
- 字段含义速查
- id:时段唯一标识
- item_id:所属项目
- weekday:适用星期
- start_time/end_time:时段起止
- duration:时长(0 表示按项目默认时长自动切分)
- capacity:容量
- price_extra:加价
- sort:排序
- status:启用/禁用
- created_at:创建时间