$chatInfo) { $chatId = $chatInfo['chat_id'] ?? null; if(!$chatId) unset($params['chat_id_list'][$index]); $status = $chatInfo['status'] ?? 1; $isUsed = 1; if($params['join_type'] == 1 && $index >0) { // 顺序进群仅排序最靠前的群会被配置到活码中 $isUsed = 0; } # 提交的chatId是否被创建 // if(!in_array($chatId, $chatIdsOfQrcode) && $status == 1) { // $chatInfo['enable'] = 0; // } # 数据入库 QrcodeChatGroupDetail::updateOrCreate([ 'chat_id' => $chatId, 'rule_id' => $ruleId, 'corpid' => $params['corpid'], ], [ 'user_limit' => $chatInfo['user_limit'], 'status' => $status, 'enable' => $chatInfo['enable'] ?? 1, 'is_used' => $isUsed, 'sort' => $index ]); } DB::commit(); } catch (\Exception $e) { EmailQueue::rPush('创建群活码流程发生异常', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '创建群活码流程发生异常'); Log::logError('创建群活码流程发生异常', [ 'line' => $e->getLine(), 'msg' => $e->getMessage(), 'param' => $params ], 'GroupChatJoinWayCreate'); DB::rollBack(); return 4804; } return 0; } /** * 编辑群活码 * */ public static function editRule($params, $ruleId, $configId) { try{ # 校验configId是否合法 $ruleInfo = QrcodeChatGroup::checkConfigId($params['corpid'], $ruleId, $configId); if(empty($ruleInfo)) return 4807; $params['config_id'] = $configId; $state = $ruleInfo->state; $params['state'] = $state; $params['qrcode'] = $ruleInfo->qrcode; # 校验已配置的群信息与本次提交的群信息是否一致 $chatIdList = QrcodeChatGroupDetail::select(['chat_id'])->where('rule_id', $ruleId) ->where('enable', 1)->where('status', 1)->orderBy('sort')->pluck('chat_id')->toArray(); DB::beginTransaction(); $errCode = QrcodeChatGroup::editRule($params, $ruleId); if($errCode) { DB::rollBack(); return $errCode; } $updateQrcode = false; $chatIds = []; foreach ($params['chat_id_list'] as $index=>$chatInfo) { $chatId = $chatInfo['chat_id'] ?? null; $enable = $chatInfo['enable'] ?? 1; $status = $chatInfo['status'] ?? 1; $isUsed = 1; if(!$chatId) { unset($params['chat_id_list'][$index]); continue; } # 与群活码中设置的群不一致 if($params['join_type'] == 1) { if($index) { $isUsed = 0; } else { # 获取当前配置的chat_id与本次的chat_id是否一致 $result = GroupChatJoinWayService::getChatGroupJoinWay($params['corpid'], $params['config_id']); $chatIdsOfQrcode = $result['chat_id_list']; if(!in_array($chatId, $chatIdsOfQrcode)) { $updateQrcode = true; } } } else { if(( !in_array($chatId, $chatIdList) && $enable==1 && $status==1) || (in_array($chatId, $chatIdList) && ($enable==0 || $status==0))) { $updateQrcode = true; } } if($enable && $status) { array_push($chatIds, $chatId); } # 数据入库 QrcodeChatGroupDetail::updateOrCreate([ 'corpid' => $params['corpid'], 'chat_id' => $chatId, 'rule_id' => $ruleId ], [ 'user_limit' => $chatInfo['user_limit'], 'enable' => $enable, 'status' => $status, 'is_used' => $isUsed, 'sort' => $index ]); } if(empty($chatIds)) { DB::rollBack(); return 4809; } # 若群活码发生变更则执行群活码更新 if($updateQrcode) { if($params['join_type'] == 1) { $chatIds = array_splice($chatIds, 0, 1); } $qrcodeInfo = ['corpid' => $params['corpid'], 'config_id' => $configId, 'chat_id' =>$chatIds, 'state' => $state]; RedisModel::lPush(QrcodeChatGroup::UPDATE_QRCODE_CHAT_ID_RDS, json_encode($qrcodeInfo, 256)); } DB::commit(); } catch (\Exception $e) { EmailQueue::rPush('编辑群活码流程发生异常', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '编辑群活码流程发生异常'); Log::logError('编辑群活码流程发生异常', [ 'line' => $e->getLine(), 'msg' => $e->getMessage(), 'param' => $params, 'rule_id' => $ruleId ], 'GroupChatJoinWayUpdate'); DB::rollBack(); return 4808; } return 0; } /** * 群活码列表 * */ public static function ruleList($corpid, $groupId, $name, $page, $pageSize) { list($list, $count) = QrcodeChatGroup::getGroupQrcodeList($corpid, $groupId, $name, $page, $pageSize); # 获取创建人信息 $adminIds = $list->pluck('admin_id'); $adminData = Users::select(['id','name'])->whereIn('id', $adminIds)->get(); # 获取分组信息 $groupIds = $list->pluck('group_id'); $groupData = SourceQrcodeGroups::select(['id', 'name'])->whereIn('id', $groupIds)->where('type', 2)->get(); # 获取扫码数据 $ruleIds = $list->pluck('id'); $scanData = QrcodeChatGroupDailyReport::select(['rule_id', 'scan_num'])->whereIn('rule_id', $ruleIds) ->groupBy(['rule_id'])->get(); foreach ($list as $datum) { # 创建人信息 $adminInfo = $adminData->where('id', $datum->admin_id)->first(); $datum->creator = $adminInfo->name ?? ''; # 分组信息 $groupInfo = $groupData->where('id', $datum->group_id)->first(); $datum->group_name = $groupInfo->name ?? ''; # 扫码人数 $scanInfo = $scanData->where('rule_id', $datum->id)->first(); $datum->scan = $scanInfo->scan_num ?? 0; } return [$list, $count]; } /** * 群活码详情 * */ public static function ruleDetail($corpid, $ruleId, &$errno) { try { $detail = QrcodeChatGroup::getGroupQrcodeDetail($corpid, $ruleId); if(empty($detail)) { $errno = 4811; return []; } # 获取群活码对应的群组信息配置 $chatGroupConfig = QrcodeChatGroupDetail::select(['chat_id', 'sort', 'user_limit', 'enable', 'status']) ->where('corpid', $corpid)->where('rule_id', $ruleId)->where('enable', 1)->orderBy('sort') ->get(); $detail->chat_id_list = $chatGroupConfig; } catch (\Exception $e) { Log::logError('群活码详情获取过程发生异常', [ 'line' => $e->getLine(), 'msg' => $e->getMessage(), 'rule_id' => $ruleId, 'corpid' => $corpid ], 'QrcodeChatGroupRuleDetail'); $errno = 4810; return []; } return $detail; } public static function qrcodeDetail($corpid, $ruleId, &$errno) { try { $detail = QrcodeChatGroup::getGroupQrcodeDetail($corpid, $ruleId); if(empty($detail)) { $errno = 4811; return ''; } } catch (\Exception $e) { Log::logError('群活码详情获取过程发生异常', [ 'line' => $e->getLine(), 'msg' => $e->getMessage(), 'rule_id' => $ruleId, 'corpid' => $corpid ], 'QrcodeChatGroupRuleDetail'); $errno = 4810; return ''; } return $detail->qrcode; } /** * 禁用群活码 * */ public static function delQrcode($corpid, $ruleId) { try { DB::beginTransaction(); # 校验群活码是否存在 $qrcodeInfo = QrcodeChatGroup::where('enable', 1)->where('status', 1)->where('id', $ruleId) ->where('corpid', $corpid) ->first(); if(empty($qrcodeInfo)) { DB::rollBack(); return 4811; } $qrcodeInfo->del_time = date('Y-m-d H:i:s'); $qrcodeInfo->status = 0; $result = $qrcodeInfo->save(); if(!$result) { DB::rollBack(); return 4813; } # 调用企微api执行删除群活码 $configId = $qrcodeInfo->config_id; $responseData = QyCommon::delGroupJoinWay($corpid, $configId); if(!isset($responseData['errcode']) || $responseData['errcode']) { EmailQueue::rPush('删除客户群进群方式配置', json_encode($responseData['errmsg'], 256), ['xiaohua.hou@kuxuan-inc.com'], '删除客户群进群方式配置'); return 4813; } # 修改群活码配置状态 QrcodeChatGroupDetail::where('rule_id', $ruleId)->update(['enable' => 0]); DB::commit(); } catch (\Exception $e) { DB::rollBack(); Log::logError('删除群活码过程发生异常', [ 'line' => $e->getLine(), 'msg' => $e->getMessage(), 'corpid' => $corpid, 'rule_id' => $ruleId ], 'ChatGroupQrcodeDel'); return 4812; } return 0; } /** * 获取群活码总概数据 * */ public static function getCondition($corpid, $ruleId) { # 统计群活码累计数据 $data = QrcodeChatGroupDailyReport::selectRaw("scan_num as scan_total, sum(join_num) as join_total, " . "sum(loss_num) as loss_total, sum(keep_num) as keep_total") ->where('corpid', $corpid)->where('rule_id', $ruleId) ->first(); # 统计群活码当日数据 $today = QrcodeChatGroupDailyReport::selectRaw("scan_num as scan_today, sum(join_num) as join_today, " . "sum(loss_num) as loss_today")->where('ref_date', date('Y-m-d'))->where('corpid', $corpid)->where('rule_id', $ruleId) ->first(); # 累计进群人数 $joinTotal = $data->join_total ?? 0; # 累计退群人数 $lossTotal = $data->loss_total ?? 0; # 累计留存人数 $keepTotal = $data->keep_total ?? 0; return [ 'scan_total' => $data->scan_total ?? 0, 'scan_today' => $today->scan_today ?? 0, 'join_total' => $joinTotal, 'join_today' => $today->join_today ?? 0, 'loss_total' => $lossTotal, 'loss_today' => $today->loss_today ?? 0, 'loss_rate' => $joinTotal ? round($lossTotal / $joinTotal, 4) * 100 . '%' : '0%', 'keep_rate' => $joinTotal ? round($keepTotal / $joinTotal, 4) * 100 . '%' : '0%', ]; } /** * 群活码每日数据分析 * */ public static function getDailyReport($corpid, $ruleId, $startDate, $endDate) { $list = self::getTrendFormatData($startDate, $endDate); $data = QrcodeChatGroupDailyReport::selectRaw("ref_date, corpid, rule_id, scan_num as scan_total, sum(keep_num) as keep_total") ->where('corpid', $corpid)->where('rule_id', $ruleId) ->where('ref_date', '>=', $startDate) ->where('ref_date', '<=', $endDate) ->groupBy(['corpid','ref_date', 'rule_id']) ->get(); if(!empty($data)) { foreach ($data as $datum) { $list[$datum->ref_date]['scan_total'] = intval($datum->scan_total); $list[$datum->ref_date]['keep_total'] = intval($datum->keep_total); } } return array_values($list); } /** * 群活码扫码进群客户列表 * */ public static function getMemberList($corpid, $ruleId, $keyword, $page, $pageSize) { # 获取客户群ID集合及state $state = QrcodeChatGroup::where('id', $ruleId)->where('corpid', $corpid)->where('enable', 1)->value('state'); if(empty($state)) return [[], 0]; $chatIds = QrcodeChatGroupDetail::where('rule_id', $ruleId)->pluck('chat_id')->toArray(); list($list, $count) = ChatGroupMember::getMemberListOfQrcode($corpid, $chatIds, $state, $keyword, $page, $pageSize); return [$list, $count]; } /** * 群活码配置群的数据分析 * */ public static function chatGroupAnalysis($corpid, $ruleId) { $data = QrcodeChatGroupDailyReport::selectRaw("sum(join_num) as join_total, sum(loss_num) as loss_total, sum(keep_num) as keep_total, chat_id") ->where('corpid', $corpid)->where('rule_id', $ruleId)->groupBy(['chat_id']) ->get(); # 获取群名称 $chatIds = $data->pluck('chat_id'); $chatGroupList = ChatGroup::select(['chat_id', 'name'])->where('corpid', $corpid)->whereIn('chat_id', $chatIds)->get(); foreach ($data as $datum) { # 群名称 $chatGroupInfo = $chatGroupList->where('chat_id', $datum->chat_id)->first(); $datum->chat_group_name = $chatGroupInfo->name ?? ''; # 留存率 $joinTotal = $datum->join_total ?? 0; $keepTotal = $datum->keep_total ?? 0; $datum->keep_rate = $joinTotal ? round($keepTotal / $joinTotal, 4) * 100 . '%' : '0%'; } return $data; } /** * 扫码数据上报 * */ public static function scanNumIncr($corpid, $ruleId) { try { $result = QrcodeChatGroupDailyReport::where('corpid', $corpid)->where('rule_id', $ruleId)->increment('scan_num'); if(!$result) { Log::logError('扫码数据上报失败', [ 'corpid' => $corpid, 'rule_id' => $ruleId ], 'scanNumIncr'); return 4814; } } catch (\Exception $e) { Log::logError('扫码数据上报发生异常', [ 'corpid' => $corpid, 'rule_id' => $ruleId, 'line' => $e->getLine(), 'msg' => $e->getMessage() ], 'scanNumIncr'); } return 0; } /** * 创建临时渠道码 * */ public static function createTempContactQrcode($corpid, $ruleId, &$errno) { # 获取群活码配置的客服信息 $configInfo = QrcodeChatGroup::select(['user_list', 'leading_words', 'state']) ->where('id', $ruleId)->where('corpid', $corpid) ->where('enable', 1)->first(); $userListStr = $configInfo->user_list ?? ''; if(empty($userListStr)) { $errno = 4815; return []; } # 随机取出一个客服 $userList = explode(',', $userListStr); $userId = $userList[rand(0, count($userList) -1)]; # 查询客服对应的二维码 $userInfo = DjUser::where('corpid', $corpid)->where('user_id', $userId)->first(); $qrcode = $userInfo->qr_code ?? ''; if(empty($qrcode)) { # 生成临时渠道码 $params = [ "type" => 2, //联系方式类型,1-单人, 2-多人 "scene" => 2, //场景,1-在小程序中联系,2-通过二维码联系 "remark" => "临时渠道码活码", //联系方式的备注信息 "skip_verify" => true, //外部客户添加时是否无需验证,默认为true "state" => $configInfo->state, //企业自定义的state参数,用于区分不同的添加渠道,不超过30字符 "user" => [$userId], //客服列表 ]; $responseData = QyCommon::momentCommon('add_contact_way', $corpid, $params); if(!$responseData) { $errno = 4815; return []; } # 更新渠道活码信息到客服信息 $qrcode = $responseData['qr_code']; $userInfo->qr_code = $qrcode; $userInfo->save(); } $errno = 0; return [ 'qrcode' => $qrcode, 'leading_words' => $configInfo->leading_words ]; } /** * 获取群组下的群活码规则数 * */ public static function chatGroupCountOfGroup($corpid, $groupId) { return QrcodeChatGroup::where('enable', 1)->where('corpid', $corpid) ->where('group_id', $groupId)->count(); } /** * 数据结构组装 * */ protected static function getTrendFormatData($stDate, $enDate) { $dayArr = []; $stDateStr = strtotime($stDate); $enDateStr = strtotime($enDate); while ($stDateStr <= $enDateStr) { $date = date('Y-m-d', $stDateStr); $dayArr[$date] = [ 'ref_date' => $date, 'scan_total' => 0, 'keep_total' => 0 ]; $stDateStr += 86400; } return $dayArr; } /** * 创建群活码信息 * */ public static function createChatGroupJoinWay( $corpid, $scene, $chatIds, $state, $autoCreateRoom=1, $roomBaseName='', $roomBaseId=1, $remark=null ) { $responseData = QyCommon::addGroupJoinWay($corpid, $scene, $chatIds, $state, $autoCreateRoom, $roomBaseName, $roomBaseId, $remark); if(!isset($responseData['errcode']) || $responseData['errcode']) { Log::logError('创建群活码失败', [ 'corpid' => $corpid, 'scene' => $scene, 'chatIds' => $chatIds, 'state' => $state, 'autoCreateRoom' => $autoCreateRoom, 'roomBaseName' => $roomBaseName, 'roomBaseId' => $roomBaseId, 'remark' => $remark, 'response' => $responseData ], 'CreateChatGroupJoinWay'); if($responseData['errcode'] != 701170) { EmailQueue::rPush('创建群活码失败', json_encode($responseData['errmsg'], 256), ['xiaohua.hou@kuxuan-inc.com'], '创建群活码失败'); } return 4801; } return $responseData['config_id']; } /** * 获取群活码信息 * */ public static function getChatGroupJoinWay($corpid, $configId) { $responseData = QyCommon::getGroupJoinWay($corpid, $configId); if(!isset($responseData['errcode']) || $responseData['errcode']) { EmailQueue::rPush('获取群活码信息失败', json_encode($responseData['errmsg'], 256), ['xiaohua.hou@kuxuan-inc.com'], '获取群活码信息失败'); return 4802; } $chatIdList = $responseData['join_way']['chat_id_list'] ?? null; $qrcode = $responseData['join_way']['qr_code'] ?? null; if(!$chatIdList || !$qrcode) return 4803; return ['chat_id_list' => $chatIdList, 'qrcode' => $qrcode]; } }