['name'], ]; } /** * @return int[] 入参 tag_ids 规范化后的非空字符串数组(实际为 string[]) */ private function normalizeTagIds(): array { $raw = $this->params['tag_ids'] ?? null; if ($raw === null || $raw === '') { return []; } if (is_string($raw)) { $raw = explode(',', $raw); } if (!is_array($raw)) { return []; } $ids = []; foreach ($raw as $v) { $s = trim((string) $v); if ($s !== '') { $ids[] = $s; } } return array_values(array_unique($ids)); } private function baseQuery() { $query = QywxExternalContact::where($this->searchWhere); if (!empty($this->params['follow_user'])) { $kw = addcslashes((string) $this->params['follow_user'], '%_\\'); $query->whereLike('follow_users', '%' . $kw . '%'); } // 标签筛选:JOIN 关系表按 tag_id 过滤;多个标签为 OR(命中任一即返回)。 // 走 zyt_qywx_external_contact_tag.idx_tag 索引,比 LIKE follow_users 快得多 $tagIds = $this->normalizeTagIds(); if ($tagIds !== []) { $matchedExtIds = Db::name('qywx_external_contact_tag') ->whereIn('tag_id', $tagIds) ->group('external_userid') ->column('external_userid'); if ($matchedExtIds === []) { // 没人命中:直接给一个不可能成立的条件,避免下面命中所有客户 $query->whereRaw('1=0'); } else { $query->whereIn('external_userid', $matchedExtIds); } } return $query; } /** * @notes 获取列表 */ public function lists(): array { // 按首次添加时间倒序:库字段 external_first_add_time;未回填(0)时回退 create_time(与列表「添加时间」展示一致) $lists = $this->baseQuery() ->orderRaw( '(COALESCE(NULLIF(external_first_add_time, 0), create_time) = 0) ASC, ' . 'COALESCE(NULLIF(external_first_add_time, 0), create_time) DESC, id DESC' ) ->limit($this->limitOffset, $this->limitLength) ->select() ->toArray(); $wxUserids = []; foreach ($lists as $item) { $raw = json_decode($item['follow_users'] ?? '[]', true); if (!is_array($raw)) { continue; } foreach ($raw as $fu) { if (!is_array($fu)) { continue; } $wx = trim((string) ($fu['userid'] ?? '')); if ($wx !== '') { $wxUserids[$wx] = true; } } } $wxUserids = array_keys($wxUserids); $adminNameByWx = []; if ($wxUserids !== []) { $adminNameByWx = Admin::whereIn('work_wechat_userid', $wxUserids)->column('name', 'work_wechat_userid'); } foreach ($lists as &$item) { $followUsers = json_decode($item['follow_users'] ?? '[]', true); $followUsers = is_array($followUsers) ? $followUsers : []; foreach ($followUsers as &$fu) { if (!is_array($fu)) { continue; } $wx = trim((string) ($fu['userid'] ?? '')); if ($wx !== '' && isset($adminNameByWx[$wx]) && $adminNameByWx[$wx] !== '') { $fu['admin_name'] = $adminNameByWx[$wx]; } } unset($fu); $item['follow_users'] = $followUsers; $followAdminIds = json_decode($item['follow_admin_ids'] ?? '[]', true); $item['follow_admin_ids'] = is_array($followAdminIds) ? $followAdminIds : []; // 解析标签 JSON 数组(值由 CustomerLogic::extractFollowUserTags 写入;按 tag_id 去重) $tags = json_decode((string) ($item['tags'] ?? '[]'), true); $item['tags'] = is_array($tags) ? $tags : []; $fromDb = (int) ($item['external_first_add_time'] ?? 0); $fromJson = CustomerLogic::minFollowCreatetime($followUsers); $item['external_first_add_time'] = $fromDb > 0 ? $fromDb : $fromJson; } unset($item); return $lists; } /** * @notes 获取数量 */ public function count(): int { return $this->baseQuery()->count(); } }