175 lines
5.9 KiB
PHP
175 lines
5.9 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace app\adminapi\lists\qywx;
|
||
|
||
use app\adminapi\lists\BaseAdminDataLists;
|
||
use app\adminapi\logic\qywx\CustomerLogic;
|
||
use app\common\lists\ListsSearchInterface;
|
||
use app\common\model\auth\Admin;
|
||
use app\common\model\QywxExternalContact;
|
||
use think\facade\Db;
|
||
|
||
/**
|
||
* 企业微信客户列表
|
||
*/
|
||
class CustomerLists extends BaseAdminDataLists implements ListsSearchInterface
|
||
{
|
||
/**
|
||
* @notes 搜索条件
|
||
*/
|
||
public function setSearch(): array
|
||
{
|
||
// 表无 follow_user 列,跟进人在 follow_users(JSON);跟进人筛选在 baseQuery() 中处理
|
||
return [
|
||
'%like%' => ['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);
|
||
}
|
||
}
|
||
|
||
// 添加时间:与 lists 排序口径一致(external_first_add_time 优先,0 则 create_time)
|
||
$addStart = trim((string) ($this->params['add_time_start'] ?? ''));
|
||
$addEnd = trim((string) ($this->params['add_time_end'] ?? ''));
|
||
$effExpr = 'COALESCE(NULLIF(external_first_add_time, 0), create_time)';
|
||
if ($addStart !== '') {
|
||
$t = strtotime($addStart . ' 00:00:00');
|
||
if ($t !== false) {
|
||
$query->whereRaw($effExpr . ' > 0 AND ' . $effExpr . ' >= ?', [$t]);
|
||
}
|
||
}
|
||
if ($addEnd !== '') {
|
||
$t = strtotime($addEnd . ' 23:59:59');
|
||
if ($t !== false) {
|
||
$query->whereRaw($effExpr . ' > 0 AND ' . $effExpr . ' <= ?', [$t]);
|
||
}
|
||
}
|
||
|
||
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();
|
||
}
|
||
}
|