applyNumberRules($ticket); $this->applyTicketStatusRules($ticket, $completeCount); $this->cascadeTicketClosedToNumbers($ticket); } /** * 同步流程:工单因时间/完成量等原因关闭时,联动关闭非手动号码 */ public function cascadeTicketClosedToNumbers(Ticket $ticket): void { if ((string) ($ticket['status'] ?? 'hidden') !== 'hidden') { return; } Number::where('admin_id', (int) $ticket['admin_id']) ->where('split_link_id', (int) $ticket['split_link_id']) ->where('ticket_name', (string) $ticket['ticket_name']) ->where('manual_manage', 0) ->update([ 'status' => 'hidden', 'updatetime' => time(), ]); } /** * 手动切换工单状态时,联动非手动管理的号码(开→全开,关→全关) */ public function syncNumbersWithTicketStatus(Ticket $ticket): void { $ticketStatus = (string) ($ticket['status'] ?? 'hidden'); Number::where('admin_id', (int) $ticket['admin_id']) ->where('split_link_id', (int) $ticket['split_link_id']) ->where('ticket_name', (string) $ticket['ticket_name']) ->where('manual_manage', 0) ->update([ 'status' => $ticketStatus, 'updatetime' => time(), ]); } /** * 单号上限、下号比率 */ public function applyNumberRules(Ticket $ticket): void { $orderLimit = (int) ($ticket['order_limit'] ?? 0); $assignRatio = (int) ($ticket['assign_ratio'] ?? 0); $numbers = Number::where('admin_id', (int) $ticket['admin_id']) ->where('split_link_id', (int) $ticket['split_link_id']) ->where('ticket_name', (string) $ticket['ticket_name']) ->where('manual_manage', 0) ->select(); foreach ($numbers as $number) { $visitCount = (int) $number['visit_count']; $inboundCount = (int) $number['inbound_count']; $lastVisit = (int) ($number['last_sync_visit_count'] ?? 0); $lastInbound = (int) ($number['last_sync_inbound_count'] ?? 0); $streak = (int) ($number['no_inbound_click_streak'] ?? 0); if ($visitCount > $lastVisit && $inboundCount <= $lastInbound) { $streak += ($visitCount - $lastVisit); } elseif ($inboundCount > $lastInbound) { $streak = 0; } $status = (string) $number['status']; if ($orderLimit > 0 && $inboundCount > $orderLimit) { $status = 'hidden'; } if ($assignRatio > 0 && $streak >= $assignRatio) { $status = 'hidden'; } Number::where('id', (int) $number['id'])->update([ 'no_inbound_click_streak' => $streak, 'last_sync_visit_count' => $visitCount, 'last_sync_inbound_count' => $inboundCount, 'status' => $status, 'updatetime' => time(), ]); } } /** * 完成量、时间窗口决定工单开关 */ public function applyTicketStatusRules(Ticket $ticket, int $completeCount): void { $status = $this->resolveTicketStatus($ticket, $completeCount); if ($status !== (string) $ticket['status']) { Ticket::where('id', (int) $ticket['id'])->update([ 'status' => $status, 'updatetime' => time(), ]); $ticket['status'] = $status; } } /** * 是否处于允许同步/开启的时间窗口 */ public function isWithinTimeWindow(Ticket $ticket, ?int $now = null): bool { $now = $now ?? time(); $start = $ticket['start_time'] ?? null; $end = $ticket['end_time'] ?? null; if ($start !== null && $start !== '' && (int) $start > 0 && $now < (int) $start) { return false; } if ($end !== null && $end !== '' && (int) $end > 0 && $now > (int) $end) { return false; } return true; } private function resolveTicketStatus(Ticket $ticket, int $completeCount): string { if (!$this->isWithinTimeWindow($ticket)) { return 'hidden'; } $ticketTotal = (int) ($ticket['ticket_total'] ?? 0); if ($ticketTotal > 0) { return $completeCount >= $ticketTotal ? 'hidden' : 'normal'; } return 'normal'; } }