= $end) { throw new \InvalidArgumentException('结束时间须晚于开始时间'); } } else { if ($start === '' || $end === '') { throw new \InvalidArgumentException('请填写时段开始与结束时间'); } if ($start >= $end) { throw new \InvalidArgumentException('结束时间须晚于开始时间'); } } $shiftType = $params['shift_type'] ?? ''; if ($shiftType !== '' && !in_array($shiftType, ['day', 'night'], true)) { $shiftType = ''; } $quota = (int) ($params['quota'] ?? 0); if ($status !== 1) { $quota = 0; } return [ 'doctor_id' => (int) $params['doctor_id'], 'date' => $params['date'], 'period' => $period, 'start_time' => $start, 'end_time' => $end, 'shift_type' => $shiftType !== '' ? $shiftType : null, 'slot_minutes' => $slotMinutes, 'status' => $status, 'quota' => $quota, 'max_patients' => $status === 1 ? (int) ($params['max_patients'] ?? 0) : 0, 'remark' => (string) ($params['remark'] ?? ''), ]; } /** * 是否存在相同医生、日期、起止时间的记录(排除指定 id) */ protected static function duplicateExists(int $doctorId, string $date, string $start, string $end, ?int $excludeId = null): bool { $q = Roster::where([ ['doctor_id', '=', $doctorId], ['date', '=', $date], ['start_time', '=', $start], ['end_time', '=', $end], ]); if ($excludeId) { $q->where('id', '<>', $excludeId); } return (bool) $q->find(); } /** * @notes 保存排班 * @param array $params * @return array|bool */ public static function save(array $params) { try { $data = self::buildRowData($params); if (self::duplicateExists($data['doctor_id'], $data['date'], $data['start_time'], $data['end_time'], !empty($params['id']) ? (int) $params['id'] : null)) { self::setError('该医生在同一天已存在相同的接诊时段'); return false; } if (!empty($params['id'])) { $data['update_time'] = time(); Roster::where('id', (int) $params['id'])->update($data); return ['id' => (int) $params['id']]; } $data['create_time'] = time(); $data['update_time'] = time(); $roster = Roster::create($data); return ['id' => $roster->id]; } catch (\InvalidArgumentException $e) { self::setError($e->getMessage()); return false; } catch (\Exception $e) { self::setError($e->getMessage()); return false; } } /** * @notes 删除排班 * @param array $params * @return bool */ public static function delete(array $params) { try { Roster::destroy($params['id']); return true; } catch (\Exception $e) { self::setError($e->getMessage()); return false; } } /** * @notes 排班详情 * @param array $params * @return array */ public static function detail(array $params) { return Roster::findOrEmpty($params['id'])->toArray(); } /** * @notes 批量保存排班 * @param array $params * @return array|bool */ public static function batchSave(array $params) { try { Db::startTrans(); $successCount = 0; $updateCount = 0; $createCount = 0; foreach ($params['rosters'] as $roster) { $data = self::buildRowData($roster); $exists = Roster::where([ ['doctor_id', '=', $data['doctor_id']], ['date', '=', $data['date']], ['start_time', '=', $data['start_time']], ['end_time', '=', $data['end_time']], ])->find(); if ($exists) { $data['update_time'] = time(); $exists->save($data); ++$updateCount; } else { $data['create_time'] = time(); $data['update_time'] = time(); Roster::create($data); ++$createCount; } ++$successCount; } Db::commit(); return [ 'success_count' => $successCount, 'create_count' => $createCount, 'update_count' => $updateCount, ]; } catch (\InvalidArgumentException $e) { Db::rollback(); self::setError($e->getMessage()); return false; } catch (\Exception $e) { Db::rollback(); self::setError($e->getMessage()); return false; } } /** * @notes 复制排班 * @param array $params * @return bool */ public static function copy(array $params) { try { Db::startTrans(); $where = [ ['date', 'between', [$params['source_start_date'], $params['source_end_date']]], ]; if (isset($params['doctor_id']) && $params['doctor_id']) { $where[] = ['doctor_id', '=', $params['doctor_id']]; } $sourceRosters = Roster::where($where)->select(); $targetDays = (strtotime($params['target_start_date']) - strtotime($params['source_start_date'])) / 86400; foreach ($sourceRosters as $roster) { $newDate = date('Y-m-d', strtotime($roster->date) + ($targetDays * 86400)); $data = [ 'doctor_id' => $roster->doctor_id, 'date' => $newDate, 'period' => $roster->period, 'start_time' => $roster->start_time, 'end_time' => $roster->end_time, 'shift_type' => $roster->shift_type, 'slot_minutes' => $roster->slot_minutes ?: 15, 'status' => $roster->status, 'quota' => $roster->quota, 'max_patients' => $roster->max_patients, 'remark' => $roster->remark, 'create_time' => time(), 'update_time' => time(), ]; if (empty($data['start_time']) || empty($data['end_time'])) { continue; } $dup = Roster::where([ ['doctor_id', '=', $data['doctor_id']], ['date', '=', $data['date']], ['start_time', '=', $data['start_time']], ['end_time', '=', $data['end_time']], ])->find(); if (!$dup) { Roster::create($data); } } Db::commit(); return true; } catch (\Exception $e) { Db::rollback(); self::setError($e->getMessage()); return false; } } }