'无', self::STATUS_BIDDING_ONGOING => '竞标中', self::STATUS_BIDDING_WIN => '中标', self::STATUS_BIDDING_FAILED => '未中标', ]; // 竞标状态 const STATUS_PROCESS_NO = 0; //未处理 const STATUS_PROCESS_ONGOING = 1; //待确认 const STATUS_PROCESS_CONFIRMED = 2; //已确认 const STATUS_PROCESS_FAILED = 3; //已拒绝 const STATUS_PROCESS_TIMEOUT = 4; //超时弃权 const PROCESS_STATUS_MAP = [ self::STATUS_PROCESS_NO => '未处理', self::STATUS_PROCESS_ONGOING => '待确认', self::STATUS_PROCESS_CONFIRMED => '已确认', self::STATUS_PROCESS_FAILED => '已拒绝', self::STATUS_PROCESS_TIMEOUT => '超时弃权', ]; /** * 保存客户群列表(只补充未入库的群,可重复执行) * @return int 新增数量 * @throws GuzzleException */ public static function syncList(): int { $scene = 2; $state = ''; $group_chat_list = WorkWeChatService::groupChatList(); $dataList = []; foreach ($group_chat_list as $chat) { $chat_id = $chat['chat_id'] ?? ''; if (!$chat_id) { continue; } $groupChatInfo = WorkWeChatService::groupChatInfo($chat_id); $dataList[] = [ 'demand_id' => 0, 'chat_id' => $chat_id, 'name' => $groupChatInfo['name'] ?? '', 'config_id' => '', 'qr_code' => '', 'scene' => $scene, 'state' => $state, ]; } //群名为空时不再排序,避免空列表导致报错 if (!$dataList) { Log::warning(__METHOD__ . ' 企业微信未返回任何客户群,请检查群主配置与接口权限'); return 0; } usort($dataList, function ($a, $b) { return (int)filter_var($a['name'], FILTER_SANITIZE_NUMBER_INT) <=> (int)filter_var($b['name'], FILTER_SANITIZE_NUMBER_INT); }); $chatIdList = self::where('chat_id', '<>', '')->column('chat_id'); $dataList = array_filter($dataList, function ($value) use ($chatIdList) { return !in_array($value['chat_id'], $chatIdList); }); if (!$dataList) { return 0; } (new self::$Model)->saveAll($dataList); return count($dataList); } /** * 分配一个空闲群给需求,并生成(或刷新)二维码 * @param $demand_id * @param bool $refresh * @return mixed * @throws */ public static function updateQrCode($demand_id, bool $refresh = false) { //分配一个未使用的群 $info = self::getOne(['demand_id' => 0], [], ['id']); if (!$info) { Log::error(__METHOD__ . ' 群池已空,无法为需求分配沟通群,demand_id:' . $demand_id); return false; } $info->demand_id = $demand_id; self::refreshQrCode($info, $refresh); return $info->save(); } /** * 重新生成群的入群二维码 * 失败只记录日志并返回 false,不抛异常,避免影响确认接单等主流程 * @param Chat|\think\Model $info * @param bool $refresh 已有二维码时是否强制刷新 * @return bool * @throws GuzzleException */ public static function refreshQrCode($info, bool $refresh = false): bool { if ($info->qr_code && !$refresh) { return true; } //更新config_id,防止设置群聊邀请确认后不生效 $config_id = WorkWeChatService::groupChatAddJoinWay([$info['chat_id']]); if (!$config_id) { Log::error(__METHOD__ . ' 生成入群方式失败,chat_id:' . $info['chat_id']); return false; } $join_way = WorkWeChatService::groupChatGetJoinWay($config_id); if (empty($join_way['qr_code'])) { Log::error(__METHOD__ . ' 获取群二维码失败,config_id:' . $config_id); return false; } $info->config_id = $config_id; $info->qr_code = $join_way['qr_code']; return true; } /** * 刷新所有已分配群的二维码 * @return array * @throws GuzzleException */ public static function refreshAll(): array { $list = self::where('demand_id', '>', 0)->select(); $result = ['total' => 0, 'success' => 0, 'fail' => 0, 'failDemandIds' => []]; foreach ($list as $item) { $result['total']++; if (self::refreshQrCode($item, true) && $item->save()) { $result['success']++; } else { $result['fail']++; $result['failDemandIds'][] = $item->demand_id; } } return $result; } /** * 刷新指定需求群的二维码 * @param $demand_id * @return bool * @throws GuzzleException */ public static function refreshByDemand($demand_id) { $info = self::getOne(['demand_id' => $demand_id]); if (!$info) { Log::error(__METHOD__ . ' 该需求没有已分配的沟通群,demand_id:' . $demand_id); return false; } if (!self::refreshQrCode($info, true)) { return false; } return (bool)$info->save(); } /** * 回收需求占用的群,归还群池 * @param $demand_id * @return bool */ public static function recycle($demand_id) { $info = self::getOne(['demand_id' => $demand_id]); if (!$info) { return false; } $info->demand_id = 0; $info->config_id = ''; //旧二维码随需求作废,下次分配时重新生成 $info->qr_code = ''; return (bool)$info->save(); } /** * 群池状态 * @return array */ public static function stat(): array { return [ 'total' => self::$Model::count(), 'free' => self::where('demand_id', 0)->count(), 'used' => self::where('demand_id', '>', 0)->count(), 'no_qrcode' => self::where('qr_code', '')->count(), ]; } }