geng
This commit is contained in:
@@ -21,6 +21,8 @@ class MediaChannelService
|
||||
'update_time',
|
||||
];
|
||||
|
||||
public const GROUP_CODE_PREFIX = 'group:';
|
||||
|
||||
/** @var array<int, array<string, mixed>>|null */
|
||||
private static ?array $activeChannelRowsCache = null;
|
||||
|
||||
@@ -199,8 +201,9 @@ SQL;
|
||||
'code' => (string) ($row['channel_code'] ?? ''),
|
||||
'name' => (string) ($row['channel_name'] ?? ''),
|
||||
'tag_id' => (string) ($row['source_tag_id'] ?? ''),
|
||||
'group_name' => (string) ($row['source_group_name'] ?? ''),
|
||||
'group_name' => trim((string) ($row['source_group_name'] ?? '')),
|
||||
'customer_count' => (int) ($row['customer_count'] ?? 0),
|
||||
'kind' => 'channel',
|
||||
], self::getCurrentTagChannelRows());
|
||||
}
|
||||
|
||||
@@ -217,6 +220,11 @@ SQL;
|
||||
return null;
|
||||
}
|
||||
|
||||
$groupName = self::parseGroupName($channelCode);
|
||||
if ($groupName !== '') {
|
||||
return self::buildCurrentTagGroupChannel($groupName);
|
||||
}
|
||||
|
||||
foreach (self::getCurrentTagChannelRows() as $row) {
|
||||
if ((string) ($row['channel_code'] ?? '') === $channelCode) {
|
||||
return $row;
|
||||
@@ -226,6 +234,57 @@ SQL;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function isGroupCode(string $channelCode): bool
|
||||
{
|
||||
return self::parseGroupName($channelCode) !== '';
|
||||
}
|
||||
|
||||
public static function buildGroupCode(string $groupName): string
|
||||
{
|
||||
$groupName = trim($groupName);
|
||||
|
||||
return $groupName === '' ? '' : self::GROUP_CODE_PREFIX . $groupName;
|
||||
}
|
||||
|
||||
public static function parseGroupName(string $channelCode): string
|
||||
{
|
||||
$channelCode = trim($channelCode);
|
||||
if (!str_starts_with($channelCode, self::GROUP_CODE_PREFIX)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return trim(substr($channelCode, strlen(self::GROUP_CODE_PREFIX)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 账户消耗等事实表使用的真实渠道 code;分组筛选会展开为组内全部叶子渠道。
|
||||
*
|
||||
* @param array<string, mixed>|null $channel
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getChannelCodesForStats(?array $channel): array
|
||||
{
|
||||
if ($channel === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$codes = [];
|
||||
if (isset($channel['channel_codes']) && is_array($channel['channel_codes'])) {
|
||||
foreach ($channel['channel_codes'] as $code) {
|
||||
$code = trim((string) $code);
|
||||
if ($code !== '' && !str_starts_with($code, self::GROUP_CODE_PREFIX)) {
|
||||
$codes[$code] = $code;
|
||||
}
|
||||
}
|
||||
}
|
||||
$code = trim((string) ($channel['channel_code'] ?? ''));
|
||||
if ($code !== '' && !str_starts_with($code, self::GROUP_CODE_PREFIX)) {
|
||||
$codes[$code] = $code;
|
||||
}
|
||||
|
||||
return array_values($codes);
|
||||
}
|
||||
|
||||
public static function getDefaultCode(): string
|
||||
{
|
||||
$rows = self::getActiveChannelRows();
|
||||
@@ -303,12 +362,21 @@ SQL;
|
||||
return [];
|
||||
}
|
||||
|
||||
$names = array_values(array_unique(array_filter([
|
||||
$names = [
|
||||
trim((string) ($channel['channel_name'] ?? '')),
|
||||
trim((string) ($channel['source_tag_name'] ?? '')),
|
||||
trim((string) ($channel['legacy_channel_name'] ?? '')),
|
||||
trim((string) ($channel['legacy_source_tag_name'] ?? '')),
|
||||
])));
|
||||
];
|
||||
foreach (['channel_names', 'source_tag_names'] as $listKey) {
|
||||
if (!isset($channel[$listKey]) || !is_array($channel[$listKey])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($channel[$listKey] as $name) {
|
||||
$names[] = trim((string) $name);
|
||||
}
|
||||
}
|
||||
$names = array_values(array_unique(array_filter($names, static fn (string $name): bool => $name !== '')));
|
||||
|
||||
if ($names === []) {
|
||||
return [];
|
||||
@@ -362,18 +430,22 @@ SQL;
|
||||
return;
|
||||
}
|
||||
|
||||
$tagId = trim((string) ($channel['source_tag_id'] ?? ''));
|
||||
if ($tagId !== '') {
|
||||
$tagIds = self::channelTagIds($channel);
|
||||
if ($tagIds !== []) {
|
||||
$tagTable = self::tableWithPrefix('qywx_external_contact_tag');
|
||||
$contactTable = self::tableWithPrefix('qywx_external_contact');
|
||||
$tagPredicate = count($tagIds) === 1
|
||||
? 'channel_tag.tag_id = ?'
|
||||
: 'channel_tag.tag_id IN (' . implode(', ', array_fill(0, count($tagIds), '?')) . ')';
|
||||
// 相关 EXISTS 走 (tag_id, external_userid) 索引,避免先物化整渠客户 ID 再 IN。
|
||||
$query->whereRaw(
|
||||
"{$field} IN ("
|
||||
. "SELECT channel_tag.external_userid FROM {$tagTable} channel_tag "
|
||||
. 'WHERE channel_tag.tag_id = ? '
|
||||
"EXISTS (SELECT 1 FROM {$tagTable} channel_tag "
|
||||
. "WHERE channel_tag.external_userid = {$field} "
|
||||
. "AND {$tagPredicate} "
|
||||
. "AND EXISTS (SELECT 1 FROM {$contactTable} active_channel_contact "
|
||||
. 'WHERE active_channel_contact.external_userid = channel_tag.external_userid '
|
||||
. 'AND active_channel_contact.delete_time IS NULL))',
|
||||
[$tagId]
|
||||
$tagIds
|
||||
);
|
||||
|
||||
return;
|
||||
@@ -768,16 +840,24 @@ SQL;
|
||||
private static function buildLikePatterns(array $channel): array
|
||||
{
|
||||
$patterns = [];
|
||||
$tagId = trim((string) ($channel['source_tag_id'] ?? ''));
|
||||
$tagName = trim((string) ($channel['source_tag_name'] ?? ''));
|
||||
|
||||
if ($tagId !== '') {
|
||||
foreach (self::channelTagIds($channel) as $tagId) {
|
||||
$escapedTagId = addcslashes($tagId, '%_\\');
|
||||
$patterns[] = '%"tag_id":"' . $escapedTagId . '"%';
|
||||
$patterns[] = '%"id":"' . $escapedTagId . '"%';
|
||||
}
|
||||
|
||||
if ($tagName !== '') {
|
||||
$tagNames = [trim((string) ($channel['source_tag_name'] ?? ''))];
|
||||
if (isset($channel['channel_names']) && is_array($channel['channel_names'])) {
|
||||
foreach ($channel['channel_names'] as $name) {
|
||||
$tagNames[] = trim((string) $name);
|
||||
}
|
||||
}
|
||||
if (isset($channel['source_tag_names']) && is_array($channel['source_tag_names'])) {
|
||||
foreach ($channel['source_tag_names'] as $name) {
|
||||
$tagNames[] = trim((string) $name);
|
||||
}
|
||||
}
|
||||
foreach (array_unique(array_filter($tagNames, static fn (string $name): bool => $name !== '')) as $tagName) {
|
||||
$escapedTagName = addcslashes($tagName, '%_\\');
|
||||
$patterns[] = '%"name":"' . $escapedTagName . '"%';
|
||||
$patterns[] = '%"tag_name":"' . $escapedTagName . '"%';
|
||||
@@ -786,6 +866,86 @@ SQL;
|
||||
return array_values(array_unique($patterns));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $channel
|
||||
* @return string[]
|
||||
*/
|
||||
private static function channelTagIds(array $channel): array
|
||||
{
|
||||
$tagIds = [];
|
||||
if (isset($channel['source_tag_ids']) && is_array($channel['source_tag_ids'])) {
|
||||
foreach ($channel['source_tag_ids'] as $tagId) {
|
||||
$tagId = trim((string) $tagId);
|
||||
if ($tagId !== '') {
|
||||
$tagIds[$tagId] = $tagId;
|
||||
}
|
||||
}
|
||||
}
|
||||
$tagId = trim((string) ($channel['source_tag_id'] ?? ''));
|
||||
if ($tagId !== '') {
|
||||
$tagIds[$tagId] = $tagId;
|
||||
}
|
||||
|
||||
return array_values($tagIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
private static function buildCurrentTagGroupChannel(string $groupName): ?array
|
||||
{
|
||||
$groupName = trim($groupName);
|
||||
if ($groupName === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$rows = [];
|
||||
foreach (self::getCurrentTagChannelRows() as $row) {
|
||||
if (trim((string) ($row['source_group_name'] ?? '')) === $groupName) {
|
||||
$rows[] = $row;
|
||||
}
|
||||
}
|
||||
if ($rows === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$tagIds = [];
|
||||
$codes = [];
|
||||
$names = [];
|
||||
$customerCount = 0;
|
||||
foreach ($rows as $row) {
|
||||
$tagId = trim((string) ($row['source_tag_id'] ?? ''));
|
||||
if ($tagId !== '') {
|
||||
$tagIds[$tagId] = $tagId;
|
||||
}
|
||||
$code = trim((string) ($row['channel_code'] ?? ''));
|
||||
if ($code !== '' && !str_starts_with($code, self::GROUP_CODE_PREFIX)) {
|
||||
$codes[$code] = $code;
|
||||
}
|
||||
foreach (['channel_name', 'source_tag_name', 'legacy_channel_name', 'legacy_source_tag_name'] as $nameKey) {
|
||||
$name = trim((string) ($row[$nameKey] ?? ''));
|
||||
if ($name !== '') {
|
||||
$names[$name] = $name;
|
||||
}
|
||||
}
|
||||
$customerCount = max($customerCount, (int) ($row['customer_count'] ?? 0));
|
||||
}
|
||||
|
||||
return [
|
||||
'channel_code' => self::buildGroupCode($groupName),
|
||||
'channel_name' => $groupName,
|
||||
'source_group_name' => $groupName,
|
||||
'source_tag_id' => '',
|
||||
'source_tag_name' => $groupName,
|
||||
'source_tag_ids' => array_values($tagIds),
|
||||
'channel_codes' => array_values($codes),
|
||||
'channel_names' => array_values($names),
|
||||
'customer_count' => $customerCount,
|
||||
'is_group' => true,
|
||||
'status' => 1,
|
||||
];
|
||||
}
|
||||
|
||||
private static function tableWithPrefix(string $table): string
|
||||
{
|
||||
$prefix = (string) (Db::getConfig('connections.mysql.prefix') ?: 'zyt_');
|
||||
|
||||
Reference in New Issue
Block a user