98 lines
3.3 KiB
PHP
98 lines
3.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace app\common\service\qywx;
|
|
|
|
/** 计算应交给企业微信官方多人路由的成员范围。 */
|
|
class QywxPromotionMemberRange
|
|
{
|
|
/**
|
|
* @param list<array<string,mixed>> $members
|
|
* @return array{userids:list<string>,members:list<array<string,mixed>>,eligible_count:int}
|
|
*/
|
|
public static function evaluate(array $members, string $today, int $now, array $config = []): array
|
|
{
|
|
$userIds = [];
|
|
$backups = array_fill_keys((array) ($config['backup_userids'] ?? []), true);
|
|
$backupIds = [];
|
|
$scheduled = ($config['reception_mode'] ?? 'always') === 'scheduled';
|
|
$scheduledUsers = [];
|
|
if ($scheduled) {
|
|
foreach ((array) ($config['reception_schedule'] ?? []) as $slot) {
|
|
if (QywxPromotionConfig::matches($slot, $now)) {
|
|
foreach ((array) ($slot['member_userids'] ?? []) as $userId) {
|
|
$scheduledUsers[$userId] = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
foreach ($members as &$member) {
|
|
if ((string) ($member['today_date'] ?? '') !== $today) {
|
|
$member['today_date'] = $today;
|
|
$member['today_count'] = 0;
|
|
}
|
|
$member['current_weight'] = 0;
|
|
if (!self::eligible($member, $now)) {
|
|
continue;
|
|
}
|
|
$userId = trim((string) ($member['userid'] ?? ''));
|
|
if ($userId !== '') {
|
|
if (isset($backups[$userId])) {
|
|
$backupIds[$userId] = true;
|
|
} elseif (!$scheduled || isset($scheduledUsers[$userId])) {
|
|
$userIds[$userId] = true;
|
|
}
|
|
}
|
|
}
|
|
unset($member);
|
|
|
|
$usingBackup = $userIds === [] && $backupIds !== [];
|
|
if ($usingBackup) {
|
|
$userIds = $backupIds;
|
|
}
|
|
return [
|
|
'userids' => array_keys($userIds),
|
|
'members' => array_values($members),
|
|
'eligible_count' => count($userIds),
|
|
'using_backup' => $usingBackup,
|
|
];
|
|
}
|
|
|
|
/** @param array<string,mixed> $member */
|
|
public static function eligible(array $member, int $now): bool
|
|
{
|
|
if ((int) ($member['enabled'] ?? 0) !== 1) {
|
|
return false;
|
|
}
|
|
$start = max(0, (int) ($member['active_start'] ?? 0));
|
|
$end = max(0, (int) ($member['active_end'] ?? 0));
|
|
if (($start > 0 && $start > $now) || ($end > 0 && $end < $now)) {
|
|
return false;
|
|
}
|
|
$limit = max(0, (int) ($member['daily_limit'] ?? 0));
|
|
|
|
return $limit === 0 || (int) ($member['today_count'] ?? 0) < $limit;
|
|
}
|
|
|
|
/** @param list<string> $left @param list<string> $right */
|
|
public static function same(array $left, array $right): bool
|
|
{
|
|
$normalise = static function (array $values): array {
|
|
$result = [];
|
|
foreach ($values as $value) {
|
|
$userId = trim((string) $value);
|
|
if ($userId !== '') {
|
|
$result[$userId] = true;
|
|
}
|
|
}
|
|
$result = array_keys($result);
|
|
sort($result, SORT_STRING);
|
|
|
|
return $result;
|
|
};
|
|
|
|
return $normalise($left) === $normalise($right);
|
|
}
|
|
}
|