input('page', 1); // $perPage = $request->input('per_page', 10); $perPage = $params['size'] ?? 10; $page = $params['current'] ?? 1; $keyword = $params['keyword'] ?? ''; $recycle = $params['recycle'] ?? ''; $follow = $params['follow'] ?? ''; $follow_last = $params['follow_last'] ?? ''; $tagId = $params['tag_id'] ?? []; $sort = $params['sort'] ?? null; $sortId = $params['sort_id'] ?? null; $countryId = $params['country_id'] ?? ''; $channelId = $params['channel_id'] ?? ''; $where = []; $user_id =$params['user_id']; $seas = $params['seas'] ?? ''; if($seas == 'seas'){ $where[] = ['user_id', 0]; // }elseif($recycle == 'recycle'){ // $where[] = ['user_id', $user_id]; }else{ $where[] = ['user_id', $user_id]; } $where[] = ['status', 1]; if (!empty($countryId)){ $where[] = ['country_id', $countryId]; } if (!empty($channelId)){ $where[] = ['channel_id', $channelId]; } $grade = []; if (!Util::isEmpty($follow) && $follow == 0) { $where[] = ['grade', '<=', 2]; } elseif (!Util::isEmpty($follow) && $follow == 1) { $grade = [3, 4]; } elseif (!Util::isEmpty($follow) && $follow == 2) { $where[] = ['grade', '=', 5]; } if (!Util::isEmpty($follow_last) && $follow_last == 0) { $where[] = ['follow_last', '>', strtotime('-1 day')]; } elseif (!Util::isEmpty($follow_last) && $follow_last == 1) { $where[] = ['follow_last', '>', strtotime('-3 day')]; } elseif (!Util::isEmpty($follow_last) && $follow_last == 2) { $where[] = ['follow_last', '>', strtotime('-7 day')]; } $query = Customer::select('crm_customer.*')->where($where); if(!empty($tagId)){ //查询有$tagId 里任意一个标签的客户 //$query->whereHas('tags', function($query) use ($tagId){ // $query->whereIn ('tag.id', $tagId); //}); //查询有$tagId 里所有标签的客户 foreach ($tagId as $id) { $query->whereHas('tags', function($query) use ($id){ $query->where('tag_id', $id); }); } } if (!Util::isEmpty($keyword)) { $query->where(function ($query) use ($keyword) { $query->where('contacts', 'like', "%{$keyword}%") ->orWhere('phone', 'like', "%{$keyword}%") ->orWhere('email', 'like', "%{$keyword}%") ->orWhere('WhatsApp', 'like', "%{$keyword}%") ->orWhere('code', 'like', "%{$keyword}%"); }); } if (!Util::isEmpty($grade)) { $query->whereIn('grade', $grade); } if ($recycle == 'recycle') { $query->onlyTrashed(); } if ($seas == 'seas') { $corp = Corp::where('abbr', $params['corp_abbr'])->first(); $corpId = $corp?$corp->id:0; if($corpId == 1){ $query->whereIn('channel_id', [1,2,3,4,5,6,7,8]); } elseif($corpId == 3) { $query->whereIn('channel_id', [9,10,11,16,17]); } else{ $query->whereIn('channel_id', [0]); } $query->withTrashed(); } if ($sort == 'tag_group') { // 排序:按关联的 crm_tag.sort 最小值升序,其次按客户ID倒序 $minSortSub = Tag::selectRaw('MIN(crm_tag.sort) AS min_sort, crm_customer_tag.customer_id') ->join('crm_customer_tag', 'crm_customer_tag.tag_id', '=', 'crm_tag.id') ->whereNull('crm_tag.deleted_at') ->when(!empty($sortId), function ($q) use ($sortId) { $q->where('crm_tag.group_id', $sortId); }) ->groupBy('crm_customer_tag.customer_id'); $query->leftJoinSub($minSortSub, 'tag_min', function ($join) { $join->on('crm_customer.id', '=', 'tag_min.customer_id'); }); $query = $query->orderByRaw('tag_min.min_sort IS NULL') ->orderBy('tag_min.min_sort', 'asc') ->orderBy('crm_customer.id', 'desc'); }elseif ($sort == 'follow_last') { $query = $query->orderBy('crm_customer.follow_last', 'desc'); }elseif ($sort == 'follow_next') { $query = $query->orderByRaw('crm_customer.follow_next IS NULL, crm_customer.follow_next ASC'); }elseif ($sort == 'id' || empty($sort)) { $query = $query->orderBy('crm_customer.id', 'desc'); } $customer = $query->paginate($perPage, ['*'], 'page', $page); foreach ($customer as &$item) { $item = $this->getCustomer($item); if($seas == 'seas'){ $item['phone'] = Util::mask($item['phone']); $item['email'] = Util::mask($item['email']); $item['WhatsApp'] = Util::mask($item['WhatsApp']); $item['seas_time'] = time()-(empty($item['deleted_at'])?strtotime($item['updated_at']):strtotime($item['deleted_at'])); } } unset($item); return $customer; } public function preset($params) { $keyword = $params['keyword'] ?? ''; $where = []; $user_id =$params['user_id']; $where[] = ['status', 1]; $where[] = ['user_id', $user_id]; if (!empty($countryId)){ $where[] = ['country_id', $countryId]; } $query = Customer::select('id','code','sn','corp_id','email','phone','WhatsApp','contacts','company')->where($where); if (!Util::isEmpty($keyword)) { $query->where(function ($query) use ($keyword) { $query->where('contacts', 'like', "%{$keyword}%") ->orWhere('phone', 'like', "%{$keyword}%") ->orWhere('email', 'like', "%{$keyword}%") ->orWhere('WhatsApp', 'like', "%{$keyword}%") ->orWhere('code', 'like', "%{$keyword}%"); }); } $customer = $query->orderBy('follow_last','desc')->get(); foreach ($customer as &$item) { } unset($item); return $customer; } /** 分页列表 */ public function serviceList(Request $request) { if (method_exists($this, 'complexQuery')) { $result = $this->complexQuery($request->get()); } else { $config = $this->buildQueryConfig($request, 'index'); $limit = (int)$request->get('size', 15); $page = (int)$request->get('current', 1); $result = $this->logicList($config, $limit, $page); } return $this->postProcess('List', $result); } /** * 构造 CrudUtil 查询配置 */ protected function buildQueryConfig(Request $request, string $scene = 'default'): array { $p = $request->all(); $config = []; $config['model'] = $this->modelClass; switch ($scene) { case 'index': $config['where']['status'] = 1; // 关键字 if (isset($p['user_id']) && $p['user_id']) { $config['where']['user_id'] = $p['user_id']; } // 关键字 if (isset($p['keyword']) && $p['keyword']) { $k = '%' . $p['keyword'] . '%'; $config['orWhere'][] = ['contacts','like', $k]; $config['orWhere'][] = ['phone','like', $k]; $config['orWhere'][] = ['email','like', $k]; $config['orWhere'][] = ['WhatsApp','like', $k]; $config['orWhere'][] = ['code','like', $k]; } $config['order']['id'] = 'desc'; $config['dataLimit']['type'] = 'relation'; $config['dataLimit']['userId'] = $request->user->uid; $config['dataLimit']['userField'] = 'user_id'; break; } return $config; } /** * 无用线索举报 * @param $params * @return false */ public function report($params) { $id = $params['id']; $userId = $params['user_id']; $where = [ 'id' => $id, 'user_id' => $userId, ]; $customer = Customer::where($where)->withTrashed()->first(); if(empty($customer)){ return false; } CustomerAudit::create([ 'customer_id' => $id, 'report_user_id' => $userId, 'remark' => $params['remark'], 'status' => 1, 'img' => implode(',', $params['img']), ]); CustomerHis::create([ 'customer_id' => $id, 'user_his' => $userId, 'user_id' => 0, ]); $customer->user_id = 0; $customer->status = 2; $res = $customer->save(); self::inquiryUpdate($customer); //软删除 $customer->delete(); return $res; } /** * 询单修改 */ public static function inquiryUpdate($customer,$userId = null) { if(empty($customer->sn) || $customer->type!=1){ return false; } $inquiryLog = InquiryLog::where('order_no', $customer->sn)->first(); if(empty($inquiryLog)){ return false; } $userId = $userId??$customer->user_id; if ($userId == 0){ $inquiryLog->recipient = 0; $inquiryLog->t_time = time(); $inquiryLog->status = 1; $inquiryLog->r_time = time(); $inquiryLog->save(); }else { $inquiryLog->recipient = $customer->user_id; $inquiryLog->t_time = time(); $inquiryLog->save(); } return true; } /** * @param $customer * @param $request * @param $tag 是否返回客户标签 * @return mixed */ public static function getCustomer($customer, $language = 'zh_CN', $tag = false) { $customer['grade_txt'] = Util::language($language, Constants::GRADE_EN[$customer['grade']], Constants::GRADE_ZH[$customer['grade']], Constants::GRADE_RU[$customer['grade']]); $customer['magnitude'] = ($customer['magnitude']==0)?1:$customer['magnitude']; $customer['magnitude_txt'] = Util::language($language, Constants::MAGNITUDE_EN[$customer['magnitude']], Constants::MAGNITUDE[$customer['magnitude']], Constants::MAGNITUDE_RU[$customer['magnitude']]); $customer['sex_txt'] = Util::language($language, Constants::SEX_EN[$customer['sex']], Constants::SEX[$customer['sex']], Constants::SEX_RU[$customer['sex']]); if ($customer['grade']<=2) { $customer['follow'] = 0; $customer['follow_txt'] = Util::language($language,'Following','跟进中','Продолжение'); }elseif ($customer['grade']<5) { $customer['follow'] = 1; $customer['follow_txt'] = Util::language($language,'transacted','已成交','Транзакция завершена'); }else{ $customer['follow'] = 2; $customer['follow_txt'] = Util::language($language,'lost','已流失','Потерянный'); } $where = [ 'customer_id' => $customer['id'] ]; $begin_follow = Follow::select('id','created_at','updated_at') ->where($where) ->min('created_at'); $customer['begin_follow'] = Util::timeTotDate($begin_follow); // $customer['created_at'] = Util::timeTotDate($customer['created_at']); // $customer['updated_at'] = Util::timeTotDate($customer['updated_at']); $customer = Util::formatDate($customer,['follow_next','follow_last']); $nameLang = $language=='en'?'name_en':($language=='ru'?'name_ru':'name'); $countryLang = $language=='en'?'en_addr':'cn_addr'; // $customer['car_type_name'] = empty($customer['car_type_id'])?'':CarType::where(['id'=>$customer['car_type_id']])->value($nameLang); $customer['country_name'] = empty($customer['country_id'])?'':Country::where(['id'=>$customer['country_id']])->value($countryLang); $customer['channel_name'] = empty($customer['channel_id'])?'':Channel::where(['id'=>$customer['channel_id']])->value($nameLang); // $customer['last_follow'] = $last_follow; $customer['enter_user_name'] = empty($customer['enter_user_id']) ? '' : User::where('id',$customer['enter_user_id'])->value('name'); $customer['user_name'] = empty($customer['user_id']) ? '公海' : User::where('id',$customer['user_id'])->value('name'); if ($tag) { foreach ($customer['tags'] as &$tag) { $tag['names'] = unserialize($tag['names']); $tag['name'] = $tag['names'][$language]; } } // WhatsApp导入截图:desc_collect 里的 OSS 对象键 -> 带签名 (前端 v-html 渲染) $customer['desc_collect'] = self::signScreenshotImages((string)($customer['desc_collect'] ?? '')); return $customer; } /** * 将 desc_collect 中 crm_whatsapp 截图的 OSS 对象键替换为带签名的 标签。 * 键按原文匹配签名(历史记录为双斜杠键,对象即存于该键,不可归一)。 */ private static function signScreenshotImages(string $desc): string { if ($desc === '' || strpos($desc, 'crm_whatsapp/') === false) { return $desc; } return preg_replace_callback( '/([A-Za-z0-9_\-]+(?:\/[A-Za-z0-9_\-]+)*\/+crm_whatsapp\/[A-Za-z0-9_\-\.]+\.(?:png|jpe?g|webp))/', function ($m) { try { $url = (new OssService())->generatePrivateUrl($m[1], 7 * 86400); return ''; } catch (\Throwable $e) { return $m[0]; } }, $desc ); } public function detail($params) { $id =$params['id']; $customer = Customer::with('tags')->select('id', 'user_id', 'grade', 'channel_id', 'car_type_id', 'country_id', 'magnitude', 'email', 'phone', 'WhatsApp', 'contacts', 'describe', 'address', 'lat', 'lng', 'follow_next', 'follow_remark', 'sex', 'company') ->where('id', $id) ->first(); return $customer; } /** * 查询客户关系是否重复 */ public function distinct($params,$corpId){ // 9.1 add 报重修正 if (!$params['email'] && !$params['phone'] && !$params['whatsApp']) { return false; } $customer = Customer::where('corp_id',$corpId) ->where((function (Builder $query) use ($params) { if(!empty($params['email'])) $query->Orwhere('email', '=', $params['email']); if(!empty($params['phone'])) $query->Orwhere('phone', '=', $params['phone']); if(!empty($params['whatsApp'])) $query->Orwhere('whatsApp', '=', $params['whatsApp']); // $query->where('email', '=', $params['email']) // ->Orwhere('phone', '=', $params['phone']) // ->Orwhere('whatsApp', '=', $params['whatsApp']); return $query; })) ->first(); if (!empty($customer)) { //客户重复,消息通知 // if($corpId != $customer->corp_id){ // return false; // } return $customer; } return false; } /** * 客户重复通知 * @param $params * @param $corpId * @return Customer|false|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object */ public function distinctNotice($customer_id){ $customer = Customer::where('id', $customer_id) ->first(); if (!empty($customer)) { $contacts = $customer->contacts??$customer['phone']; $contacts = $contacts??$customer['whatsApp']; $contacts = $contacts??$customer['email']; $data = [ 'sender_id' => 0, //发送人ID 0默认系统 'sender_type' => 'system', //发送者类型 user admin system 'title' => '客户跟进提醒 - ' . $contacts, //标题 'content' => $contacts . ' 产生了新的询单,请及时跟进', //内容 'scene' => 1, //场景 0系统公共 1系统通知 'recipient' => [$customer->user_id], //接收人 空为全部 'push_method' => 0 //推送方式0系统推送1手动推送 ]; // 异步推送 \Webman\RedisQueue\Redis::send('notice', $data); return $customer; } return false; } }