$v > 0 )); if (empty($userIds)) { throw new BusinessException('SALES_USER_IDS 业务员列表不能为空,请先在命令中配置.'); } // 取出“待分配”的询盘(你可以根据自己系统调整条件) // 当前策略:status = 0 且 recipient = 0 的视为未分配 $inquiries = Db::table('inquiry_log') ->where('enter_user_id', 186) ->where('channel', 10) ->where('status', 0) ->where('recipient', 0) ->where('id', '>', 34426) ->orderBy('id') ->limit(static::BATCH_LIMIT) ->get(); if ($inquiries->isEmpty()) { $output->writeln('没有需要分配的询盘(status=0 且 recipient=0)'); return self::SUCCESS; } $now = time(); $count = 0; foreach ($inquiries as $row) { $inquiryId = (int)$row->id; sleep(1); // 轮询取出一个业务员 ID $recipientUserId = $this->nextRecipientId($userIds, static::ROUND_ROBIN_GROUP_KEY); // 对每一条记录单独事务,避免单条异常拖垮全部 Db::transaction(function () use ($inquiryId, $recipientUserId, $now, $output, &$count) { // 1)更新 inquiry_log $affected = Db::table('inquiry_log') ->where('id', $inquiryId) ->update([ 'recipient' => $recipientUserId, 'status' => 2, 'r_time' => $now, 't_time' => $now, 'updated_at' => $now, ]); if ($affected === 0) { // 被其他进程抢先更新也有可能,这里只打印提示不中断整个批次 $output->writeln("询盘 {$inquiryId} 未更新(可能已被处理)"); return; } // 2)构造队列 payload(后续 CRM 消费时至少知道 ID) $res = [ 'id' => $inquiryId, 'recipient' => $recipientUserId, 'dispatched_at' => $now, 'source' => 'fb_leads_inquiry', ]; // 3)推送到 CRM 队列 RedisQueueRedis::send('inquiry-to-crm-new', $res); $count++; $output->writeln("已分配询盘 {$inquiryId} 给业务员 {$recipientUserId},并推送到队列"); }); } $output->writeln("本次共分配成功 {$count} 条询盘"); return self::SUCCESS; } /** * 轮询获取“下一位业务员 ID” * * @param int[] $userIds * @param string $groupKey * @return int * @throws BusinessException */ protected function nextRecipientId(array $userIds, string $groupKey = 'default'): int { $userIds = array_values(array_filter(array_map('intval', $userIds), fn($v) => $v > 0)); if (empty($userIds)) { throw new BusinessException('轮询分配失败:业务员列表为空'); } $count = count($userIds); $key = 'inquiry:assign:round_robin:' . $groupKey; // Redis INCR 是原子操作,适合并发下使用 $val = Redis::incr($key); // 第一次会从 0 变成 1 // 换算为从 0 开始的下标 $index = ($val - 1) % $count; return $userIds[$index]; } }