Update ConversionLogic.php
This commit is contained in:
@@ -327,100 +327,82 @@ class ConversionLogic
|
||||
int $startTimestamp,
|
||||
int $endTimestamp
|
||||
): void {
|
||||
$wxUserIdToAdminIds = self::loadWorkWechatAdminMap();
|
||||
$rows = Db::name('qywx_external_contact')
|
||||
->whereNull('delete_time')
|
||||
->whereRaw(
|
||||
'((external_first_add_time BETWEEN ? AND ?) OR (external_first_add_time = 0 AND create_time BETWEEN ? AND ?))',
|
||||
[$startTimestamp, $endTimestamp, $startTimestamp, $endTimestamp]
|
||||
)
|
||||
->field('follow_admin_ids, follow_users')
|
||||
->select()
|
||||
->toArray();
|
||||
$timeSql = '((q.external_first_add_time BETWEEN ? AND ?) OR (q.external_first_add_time = 0 AND q.create_time BETWEEN ? AND ?))';
|
||||
$bind = [$startTimestamp, $endTimestamp, $startTimestamp, $endTimestamp];
|
||||
$indexSql = self::buildJsonIndexUnionSql(32);
|
||||
|
||||
$countsByAdmin = [];
|
||||
foreach ($rows as $row) {
|
||||
$adminIds = self::extractFollowAdminIds($row, $wxUserIdToAdminIds);
|
||||
if ($adminIds === []) {
|
||||
// 优先使用 follow_admin_ids(JSON 数组) 做 SQL 聚合,兼容不支持 JSON_TABLE 的 MySQL 版本。
|
||||
$countsByAdmin = Db::query(
|
||||
<<<SQL
|
||||
SELECT
|
||||
CAST(JSON_UNQUOTE(JSON_EXTRACT(q.follow_admin_ids, CONCAT('$[', idx.n, ']'))) AS UNSIGNED) AS admin_id,
|
||||
COUNT(*) AS cnt
|
||||
FROM zyt_qywx_external_contact q
|
||||
JOIN (
|
||||
{$indexSql}
|
||||
) AS idx
|
||||
WHERE q.delete_time IS NULL
|
||||
AND COALESCE(JSON_LENGTH(q.follow_admin_ids), 0) > idx.n
|
||||
AND {$timeSql}
|
||||
GROUP BY admin_id
|
||||
SQL,
|
||||
$bind
|
||||
);
|
||||
|
||||
$mergedCounts = [];
|
||||
foreach ($countsByAdmin as $row) {
|
||||
$adminId = (int) ($row['admin_id'] ?? 0);
|
||||
if ($adminId <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($adminIds as $adminId) {
|
||||
$countsByAdmin[$adminId] = ($countsByAdmin[$adminId] ?? 0) + 1;
|
||||
}
|
||||
$mergedCounts[$adminId] = ($mergedCounts[$adminId] ?? 0) + (int) ($row['cnt'] ?? 0);
|
||||
}
|
||||
|
||||
foreach ($countsByAdmin as $adminId => $count) {
|
||||
// 兼容历史数据:follow_admin_ids 为空时,再从 follow_users(JSON) -> admin.work_wechat_userid 回填。
|
||||
$fallbackRows = Db::query(
|
||||
<<<SQL
|
||||
SELECT
|
||||
a.id AS admin_id,
|
||||
COUNT(*) AS cnt
|
||||
FROM zyt_qywx_external_contact q
|
||||
JOIN (
|
||||
{$indexSql}
|
||||
) AS idx
|
||||
ON COALESCE(JSON_LENGTH(q.follow_users), 0) > idx.n
|
||||
JOIN zyt_admin a
|
||||
ON a.work_wechat_userid = JSON_UNQUOTE(JSON_EXTRACT(q.follow_users, CONCAT('$[', idx.n, '].userid')))
|
||||
AND a.delete_time IS NULL
|
||||
WHERE q.delete_time IS NULL
|
||||
AND COALESCE(JSON_LENGTH(q.follow_admin_ids), 0) = 0
|
||||
AND {$timeSql}
|
||||
GROUP BY a.id
|
||||
SQL,
|
||||
$bind
|
||||
);
|
||||
|
||||
foreach ($fallbackRows as $row) {
|
||||
$adminId = (int) ($row['admin_id'] ?? 0);
|
||||
if ($adminId <= 0) {
|
||||
continue;
|
||||
}
|
||||
$mergedCounts[$adminId] = ($mergedCounts[$adminId] ?? 0) + (int) ($row['cnt'] ?? 0);
|
||||
}
|
||||
|
||||
foreach ($mergedCounts as $adminId => $count) {
|
||||
foreach (self::mapEntityIds($dimension, (int) $adminId, $entityIds, $adminToDeptIds) as $entityId) {
|
||||
$entities[$entityId]['add_fans_count'] += (int) $count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, int[]>
|
||||
*/
|
||||
private static function loadWorkWechatAdminMap(): array
|
||||
private static function buildJsonIndexUnionSql(int $maxIndex): string
|
||||
{
|
||||
$rows = Db::name('admin')
|
||||
->whereNull('delete_time')
|
||||
->where('work_wechat_userid', '<>', '')
|
||||
->field('id, work_wechat_userid')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$map = [];
|
||||
foreach ($rows as $row) {
|
||||
$userId = trim((string)($row['work_wechat_userid'] ?? ''));
|
||||
$adminId = (int)($row['id'] ?? 0);
|
||||
if ($userId === '' || $adminId <= 0) {
|
||||
continue;
|
||||
}
|
||||
$map[$userId] ??= [];
|
||||
$map[$userId][] = $adminId;
|
||||
$parts = [];
|
||||
for ($i = 0; $i < $maxIndex; $i++) {
|
||||
$parts[] = 'SELECT ' . $i . ' AS n';
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $row
|
||||
* @param array<string, int[]> $wxUserIdToAdminIds
|
||||
* @return int[]
|
||||
*/
|
||||
private static function extractFollowAdminIds(array $row, array $wxUserIdToAdminIds): array
|
||||
{
|
||||
$adminIds = json_decode((string)($row['follow_admin_ids'] ?? '[]'), true);
|
||||
if (is_array($adminIds)) {
|
||||
$adminIds = array_values(array_unique(array_filter(array_map('intval', $adminIds), static fn (int $id): bool => $id > 0)));
|
||||
} else {
|
||||
$adminIds = [];
|
||||
}
|
||||
|
||||
if ($adminIds !== []) {
|
||||
return $adminIds;
|
||||
}
|
||||
|
||||
$followUsers = json_decode((string)($row['follow_users'] ?? '[]'), true);
|
||||
if (!is_array($followUsers)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$resolved = [];
|
||||
foreach ($followUsers as $followUser) {
|
||||
if (!is_array($followUser)) {
|
||||
continue;
|
||||
}
|
||||
$userId = trim((string)($followUser['userid'] ?? ''));
|
||||
if ($userId === '' || !isset($wxUserIdToAdminIds[$userId])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($wxUserIdToAdminIds[$userId] as $adminId) {
|
||||
$resolved[$adminId] = $adminId;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($resolved);
|
||||
return implode(' UNION ALL ', $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user