简介
本文件面向业务运营人员与系统开发者,系统化说明 DouPHP 预约系统的“规则引擎”数据模型,重点围绕预约规则主表 dou_book_rule 与其子表 dou_book_rule_slot 的字段设计、约束与索引、以及规则在时段维度上的容量与价格调整策略。文档同时给出优先级计算、时段合并算法、容量叠加逻辑的设计建议与实现要点,并提供多类复杂业务场景的配置参考,帮助快速落地可维护的规则体系。
项目结构
- 数据库定义位于开发手册 SQL 与模块备份 SQL 中,明确了两张核心表的字段、类型、默认值与注释。
- 后台模型层提供对两张表的 ORM 访问封装,包含字段映射、填充白名单等。
- 后台服务层负责规则与规则时段的增删改查、列表构建、排序与分页等业务流程。
graph TB
A["数据库<br/>dou_book_rule / dou_book_rule_slot"] --> B["后台模型<br/>BookRule / BookRuleSlot"]
B --> C["后台服务<br/>RuleService / RuleSlotService"]
C --> D["管理界面<br/>规则列表/时段列表"]
核心组件
- 预约规则主表(dou_book_rule):描述一条规则的元信息,包括名称、关联项目、规则类型、优先级、日期类型、生效起止日期、星期集合、状态与时间戳。
- 规则时段明细表(dou_book_rule_slot):描述某条规则在一天内多个时间段的具体配置,包括开始/结束时间、时长、容量与容量模式、价格调整与价格模式、排序等。
- 后台模型:对两张表进行 ORM 封装,提供字段类型转换与批量赋值白名单。
- 后台服务:提供规则与规则时段的列表、新增、编辑、删除等完整业务操作。
架构总览
规则引擎的数据流从“规则主表 + 时段明细表”出发,经后台服务组装为前端展示或用于后续预约计算。规则通过优先级与日期/星期匹配筛选,再按规则类型与排序对基础时段进行覆盖、追加或修改,最终得到目标日期的可用时段、容量与价格。
sequenceDiagram
participant Admin as "管理员"
participant RSvc as "RuleService"
participant RModel as "BookRule"
participant SModel as "BookRuleSlot"
Admin->>RSvc : 创建/更新规则
RSvc->>RModel : 写入规则主表
Admin->>RSvc : 添加/更新规则时段
RSvc->>SModel : 写入规则时段明细
RSvc-->>Admin : 返回成功并记录审计日志
详细组件分析
数据模型:预约规则主表(dou_book_rule)
- 关键字段
- id:规则主键
- name:规则名称
- item_id:关联项目ID,0表示全局规则
- rule_type:规则类型,枚举 closed/replace/add/override
- priority:优先级,数值越小优先级越高
- date_type:日期类型,枚举 single/range/weekly/monthly
- start_date/end_date:生效起止日期
- weekdays:生效星期集合(1-7),空或NULL表示所有
- status:启用/禁用
- add_time/update_time:时间戳(不同版本SQL可能使用 created_at/updated_at)
- 索引与查询
- 常见索引:item_id、start_date+end_date、status
- 列表排序:priority ASC, start_date DESC, id DESC
erDiagram
DOU_BOOK_RULE {
int id PK
varchar name
int item_id
enum rule_type
tinyint priority
enum date_type
date start_date
date end_date
set weekdays
tinyint status
datetime created_at
datetime updated_at
}
数据模型:规则时段明细表(dou_book_rule_slot)
- 关键字段
- id:时段主键
- rule_id:关联规则ID
- start_time/end_time:时间段起止
- duration:时长(分钟)
- capacity:容量值(绝对值或调整值)
- capacity_mode:容量模式,枚举 set/inc/dec
- price_extra:价格调整值(金额或百分比)
- price_mode:价格模式,枚举 set/inc/dec/percent_inc/percent_dec
- sort:排序
- add_time/created_at:时间戳
- 索引与查询
- 常见索引:rule_id
- 列表排序:sort ASC, start_time ASC
erDiagram
DOU_BOOK_RULE_SLOT {
int id PK
int rule_id FK
time start_time
time end_time
smallint duration
smallint capacity
enum capacity_mode
decimal price_extra
enum price_mode
smallint sort
datetime created_at
}
后台模型与服务
- 模型
- BookRule:声明表名、主键、字段类型转换与可填充字段
- BookRuleSlot:同上,针对时段明细
- 服务
- RuleService:规则列表、新增、编辑、删除;构建规则类型与星期选项;处理日期类型与星期集合
- RuleSlotService:规则时段的列表、新增、编辑、删除;校验规则存在性;记录审计日志
classDiagram
class BookRule {
+string table
+string primary
+array casts
+array fillable
}
class BookRuleSlot {
+string table
+string primary
+array casts
+array fillable
}
class RuleService {
+buildRuleListData()
+insert()
+update()
+deleteByIdOrConfirm()
}
class RuleSlotService {
+buildRuleSlotListData()
+insert()
+update()
+deleteSlot()
}
RuleService --> BookRule : "读写"
RuleService --> BookRuleSlot : "统计/级联删除"
RuleSlotService --> BookRule : "校验"
RuleSlotService --> BookRuleSlot : "读写"
依赖关系分析
- 表间关系
- dou_book_rule_slot.rule_id → dou_book_rule.id(一对多)
- 服务依赖
- RuleService 依赖 BookRule、BookRuleSlot(列表统计、删除级联)
- RuleSlotService 依赖 BookRule(存在性校验)、BookRuleSlot(CRUD)
- 索引依赖
- 规则列表按 item_id、status、start_date+end_date 过滤与排序
- 时段列表按 rule_id 过滤,按 sort、start_time 排序
graph LR
R["dou_book_rule"] -- "1:N" --> S["dou_book_rule_slot"]
RSvc["RuleService"] --> R
RSvc --> S
RSSvc["RuleSlotService"] --> R
RSSvc --> S
性能考量
- 查询优化
- 规则列表:优先使用 item_id、status、start_date+end_date 复合条件;排序遵循 priority ASC, start_date DESC, id DESC
- 时段列表:使用 rule_id 精确过滤;按 sort、start_time 排序
- 索引建议
- 规则表:(item_id)、(start_date, end_date)、(status)
- 时段表:(rule_id)
- 写入优化
- 批量插入时段明细时,尽量合并事务提交
- 更新规则时避免频繁全量刷新缓存(如适用)
故障排查指南
- 规则不存在/非法
- 更新或删除规则前会校验规则是否存在,若不存在抛出领域异常并跳转回规则列表
- 时段不存在/非法
- 更新或删除时段前会校验所属规则与时段是否存在,若不存在抛出领域异常并跳转回时段列表
- 审计日志
- 所有增删改操作均记录管理员操作日志,便于追溯
结论
- dou_book_rule 与 dou_book_rule_slot 构成规则引擎的核心数据模型,前者定义“何时、对谁、如何影响”,后者定义“具体时段内的容量与价格策略”。
- 通过优先级、日期/星期匹配与规则类型,可实现灵活的时段覆盖、追加与关闭能力。
- 建议在应用层实现统一的优先级计算、时段合并与容量叠加逻辑,确保规则冲突时的确定性结果。
附录:复杂业务场景配置示例
以下为基于现有数据模型的推荐配置思路(不直接粘贴代码,仅给出字段取值与组合方式):
- 场景一:节假日临时关闭
- 规则主表
- rule_type: closed
- date_type: range
- start_date/end_date: 节假日区间
- priority: 较低(高优先级覆盖)
- 规则时段:无需配置(closed 直接关闭该日)
- 规则主表
- 场景二:周末加价且缩短时长
- 规则主表
- rule_type: override
- date_type: weekly
- weekdays: 6,7
- priority: 中等
- 规则时段
- start_time/end_time: 营业时段
- duration: 缩短至目标时长
- price_extra/price_mode: 加价(金额或百分比)
- 规则主表
- 场景三:工作日高峰限流
- 规则主表
- rule_type: replace
- date_type: weekly
- weekdays: 1-5
- priority: 较高
- 规则时段
- 仅保留高峰时段
- capacity/capacity_mode: 限制容量(设定或减少)
- 规则主表
- 场景四:会员专属时段追加
- 规则主表
- rule_type: add
- date_type: single 或 range
- priority: 低(不影响基础时段)
- 规则时段
- 新增额外时段
- capacity: 独立容量
- 规则主表
- 场景五:全局默认规则 + 项目级覆盖
- 规则主表
- 全局规则:item_id=0,priority 较低
- 项目规则:item_id=具体项目,priority 较高
- 规则时段:分别配置各自时段策略
- 规则主表
注意
- 当多条规则在同一日期/星期命中时,按 priority 升序决定生效顺序;同优先级时结合 start_date 与 id 排序确定稳定性。
- 时段合并建议采用“先按规则优先级排序,再按 start_time 顺序合并”,对重叠时段执行覆盖/追加/关闭策略,并对容量按 set/inc/dec 累加或覆盖。