0) { $diagnosisId = (int) Db::name('tcm_prescription_order')->where('id', $orderId)->value('diagnosis_id'); } if ($diagnosisId <= 0) { return; } RevisitDueService::refreshDiagnoses([$diagnosisId], [ 'reason' => self::reasonTag('order', $reason), 'operator_id' => self::currentAdminId(), ]); } catch (\Throwable $e) { Log::warning(sprintf('复诊到期钩子 onOrderChanged 失败 diagnosis_id=%d order_id=%d: %s', $diagnosisId, $orderId, $e->getMessage())); } } /** * 挂号变化(创建 / 取消 / 完成 / 后台编辑)。diagnosisId 为 0 时按 appointmentId 反查(patient_id 存诊单 id)。 */ public static function onAppointmentChanged(int $diagnosisId, int $appointmentId = 0, string $reason = ''): void { try { if ($diagnosisId <= 0 && $appointmentId > 0) { $diagnosisId = (int) Db::name('doctor_appointment')->where('id', $appointmentId)->value('patient_id'); } if ($diagnosisId <= 0) { return; } RevisitDueService::refreshDiagnoses([$diagnosisId], [ 'reason' => self::reasonTag('appointment', $reason), 'operator_id' => self::currentAdminId(), ]); } catch (\Throwable $e) { Log::warning(sprintf('复诊到期钩子 onAppointmentChanged 失败 diagnosis_id=%d appointment_id=%d: %s', $diagnosisId, $appointmentId, $e->getMessage())); } } /** * 医助变更(指派 / 继承 / 释放 to=0 / 自动分配 / 回退)。toAssistantId 仅用于流水 payload,实际以库内 tcm_diagnosis.assistant_id 为准。 */ public static function onAssistantChanged(int $diagnosisId, int $toAssistantId, string $reason = ''): void { try { if ($diagnosisId <= 0) { return; } $tag = self::reasonTag('assign', $reason); if ($toAssistantId >= 0) { $tag .= ':to=' . $toAssistantId; } RevisitDueService::refreshDiagnoses([$diagnosisId], [ 'reason' => $tag, 'operator_id' => self::currentAdminId(), ]); } catch (\Throwable $e) { Log::warning(sprintf('复诊到期钩子 onAssistantChanged 失败 diagnosis_id=%d to=%d: %s', $diagnosisId, $toAssistantId, $e->getMessage())); } } /** * 诊单其它字段变更(如 revisit_slot_start_offset、status 禁用/启用、软删)。 */ public static function onDiagnosisChanged(int $diagnosisId, string $reason = ''): void { try { if ($diagnosisId <= 0) { return; } RevisitDueService::refreshDiagnoses([$diagnosisId], [ 'reason' => self::reasonTag('diagnosis', $reason), 'operator_id' => self::currentAdminId(), ]); } catch (\Throwable $e) { Log::warning(sprintf('复诊到期钩子 onDiagnosisChanged 失败 diagnosis_id=%d: %s', $diagnosisId, $e->getMessage())); } } /** * 过号 cron(update_appointment_status)执行之后:重评 closed_state=2 / appointment_state=1 的行,使当天过号即进标红/弹窗。 */ public static function onAppointmentStatusCronDone(): void { try { RevisitDueService::reevaluateBookedRows(); } catch (\Throwable $e) { Log::warning('复诊到期钩子 onAppointmentStatusCronDone 失败: ' . $e->getMessage()); } } /** 流水 payload 的 reason 标签:<来源>[:<说明>],限 64 字符 */ private static function reasonTag(string $source, string $reason): string { $reason = trim($reason); return mb_substr($reason !== '' ? $source . ':' . $reason : $source, 0, 64); } /** 当前登录管理员 id(CLI / 回调无登录态时为 0),任何异常均视为 0 */ private static function currentAdminId(): int { try { $req = request(); $admin = $req->adminInfo ?? null; if (is_array($admin)) { return (int) ($admin['admin_id'] ?? 0); } } catch (\Throwable $e) { // CLI 场景无请求上下文,忽略 } return 0; } }