本文目录导读:

在PHP项目中配置循环排班周期规则,可以采用以下几种常见的实现方案:
基础数据库设计
轮班规则表 (shift_rules)
CREATE TABLE shift_rules (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) COMMENT '规则名称',
cycle_type ENUM('daily', 'weekly', 'monthly', 'custom') COMMENT '周期类型',
cycle_days INT COMMENT '循环天数',
start_date DATE COMMENT '生效日期',
end_date DATE COMMENT '失效日期',
status TINYINT DEFAULT 1 COMMENT '状态 1:启用 0:禁用',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
轮班明细表 (shift_details)
CREATE TABLE shift_details (
id INT PRIMARY KEY AUTO_INCREMENT,
rule_id INT,
day_number INT COMMENT '第几天(从1开始)',
shift_type ENUM('morning', 'afternoon', 'night', 'rest') COMMENT '班次类型',
start_time TIME,
end_time TIME,
sort_order INT DEFAULT 0,
FOREIGN KEY (rule_id) REFERENCES shift_rules(id)
);
PHP核心实现类
<?php
namespace App\Services;
class CycleShiftService
{
private $db;
public function __construct($db)
{
$this->db = $db;
}
/**
* 获取指定日期范围内的排班
*/
public function getShiftSchedule($ruleId, $startDate, $endDate)
{
$rule = $this->getRule($ruleId);
if (!$rule) {
throw new \Exception('规则不存在');
}
// 获取轮班模式
$pattern = $this->getShiftPattern($ruleId);
// 计算排班
$schedule = [];
$currentDate = new \DateTime($startDate);
$endDateTime = new \DateTime($endDate);
while ($currentDate <= $endDateTime) {
$dayNumber = $this->calculateCycleDayNumber($currentDate, $rule);
$shift = $this->getShiftForDay($pattern, $dayNumber);
$schedule[] = [
'date' => $currentDate->format('Y-m-d'),
'day_of_week' => $currentDate->format('w'),
'shift' => $shift
];
$currentDate->modify('+1 day');
}
return $schedule;
}
/**
* 计算循环天数
*/
private function calculateCycleDayNumber(\DateTime $date, $rule)
{
$startDate = new \DateTime($rule['start_date']);
$interval = $startDate->diff($date);
$totalDays = $interval->days;
if ($rule['cycle_type'] === 'weekly') {
// 每周循环
return ($date->format('w') + 1) % 7 + 1;
} elseif ($rule['cycle_type'] === 'daily') {
// 日循环
return 1;
} else {
// 自定义天数循环
return ($totalDays % $rule['cycle_days']) + 1;
}
}
/**
* 获取某天的班次
*/
private function getShiftForDay($pattern, $dayNumber)
{
foreach ($pattern as $shift) {
if ($shift['day_number'] === $dayNumber) {
return $shift;
}
}
return null;
}
/**
* 获取轮班模式
*/
private function getShiftPattern($ruleId)
{
$stmt = $this->db->prepare(
"SELECT * FROM shift_details WHERE rule_id = ? ORDER BY day_number, sort_order"
);
$stmt->execute([$ruleId]);
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
/**
* 获取规则
*/
private function getRule($ruleId)
{
$stmt = $this->db->prepare(
"SELECT * FROM shift_rules WHERE id = ? AND status = 1"
);
$stmt->execute([$ruleId]);
return $stmt->fetch(\PDO::FETCH_ASSOC);
}
}
常见轮班模式配置示例
<?php
class ShiftPatternConfig
{
/**
* 三班倒(早中晚)
* 模式:早-中-晚-休
*/
public static function getThreeShiftPattern()
{
return [
['day_number' => 1, 'shift' => 'morning', 'start_time' => '08:00', 'end_time' => '16:00'],
['day_number' => 2, 'shift' => 'afternoon', 'start_time' => '16:00', 'end_time' => '00:00'],
['day_number' => 3, 'shift' => 'night', 'start_time' => '00:00', 'end_time' => '08:00'],
['day_number' => 4, 'shift' => 'rest', 'start_time' => null, 'end_time' => null],
];
}
/**
* 两班倒(白班-夜班-休)
*/
public static function getTwoShiftPattern()
{
return [
['day_number' => 1, 'shift' => 'day', 'start_time' => '08:00', 'end_time' => '20:00'],
['day_number' => 2, 'shift' => 'night', 'start_time' => '20:00', 'end_time' => '08:00'],
['day_number' => 3, 'shift' => 'rest', 'start_time' => null, 'end_time' => null],
];
}
}
高级功能实现
节假日跳过功能
public function skipHolidays($schedule, $holidays)
{
return array_map(function($item) use ($holidays) {
if (isset($holidays[$item['date']])) {
$item['shift'] = 'rest';
$item['is_holiday'] = true;
}
return $item;
}, $schedule);
}
人员轮换分配
public function assignStaffToShift($schedule, $staffList, $shiftRule)
{
$assignments = [];
$currentStaffIndex = 0;
foreach ($schedule as $day) {
if ($day['shift'] === 'rest') {
continue;
}
$staff = $staffList[$currentStaffIndex % count($staffList)];
$assignments[] = [
'date' => $day['date'],
'shift' => $day['shift'],
'staff_id' => $staff['id'],
'staff_name' => $staff['name']
];
$currentStaffIndex++;
}
return $assignments;
}
数据验证规则
public function validateShiftRule($data)
{
$rules = [
'name' => 'required|string|max:100',
'cycle_type' => 'required|in:daily,weekly,monthly,custom',
'cycle_days' => 'required_if:cycle_type,custom|integer|min:1|max:365',
'start_date' => 'required|date',
'pattern' => 'required|array|min:1'
];
// 验证调换模式完整性
$validator = Validator::make($data, $rules);
if ($validator->fails()) {
return ['error' => $validator->errors()];
}
return ['success' => true];
}
使用示例
// 初始化服务
$shiftService = new CycleShiftService($db);
// 创建轮班规则
$ruleId = 1;
$startDate = '2024-01-01';
$endDate = '2024-01-31';
// 获取排班表
$schedule = $shiftService->getShiftSchedule($ruleId, $startDate, $endDate);
// 跳过节假日
$holidays = ['2024-01-01' => '元旦', '2024-02-10' => '春节'];
$schedule = $shiftService->skipHolidays($schedule, $holidays);
// 打印排班表
foreach ($schedule as $day) {
echo "{$day['date']} - {$day['shift']}\n";
}
这个方案提供了灵活的循环排班配置,支持多种循环周期(日/周/月/自定义),并包含节假日处理、人员分配等扩展功能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播