优化积分流水筛选与用户管理样式
This commit is contained in:
@@ -16,7 +16,9 @@ namespace App\Services;
|
||||
use App\Enums\CurrencySource;
|
||||
use App\Models\User;
|
||||
use App\Models\UserCurrencyLog;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
@@ -165,15 +167,75 @@ class UserCurrencyService
|
||||
*/
|
||||
public function activityStats(?string $date = null): Collection
|
||||
{
|
||||
$date = $date ?? today()->toDateString();
|
||||
[$date, $rangeStart, $rangeEnd] = $this->statsDateBounds($date);
|
||||
|
||||
return UserCurrencyLog::query()
|
||||
->whereDate('created_at', $date)
|
||||
->selectRaw('source, currency, SUM(amount) as total_amount, COUNT(DISTINCT user_id) as participant_count')
|
||||
->groupBy('source', 'currency')
|
||||
->orderBy('currency')
|
||||
->orderByRaw('ABS(SUM(amount)) DESC')
|
||||
->get();
|
||||
return Cache::remember("currency_stats:activity:{$date}", 300, function () use ($rangeStart, $rangeEnd) {
|
||||
return UserCurrencyLog::query()
|
||||
->where('created_at', '>=', $rangeStart)
|
||||
->where('created_at', '<', $rangeEnd)
|
||||
->selectRaw('source, currency, SUM(amount) as total_amount, COUNT(DISTINCT user_id) as participant_count')
|
||||
->groupBy('source', 'currency')
|
||||
->orderBy('currency')
|
||||
->orderByRaw('ABS(SUM(amount)) DESC')
|
||||
->get();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询某日三种货币的净流通量(流入、流出、净增)。
|
||||
*
|
||||
* @param string|null $date 日期字符串如 '2026-02-28',默认今日
|
||||
* @return array<string, array{in:int, out:int, net:int}>
|
||||
*/
|
||||
public function netFlowStats(?string $date = null): array
|
||||
{
|
||||
[$date, $rangeStart, $rangeEnd] = $this->statsDateBounds($date);
|
||||
|
||||
$rows = Cache::remember("currency_stats:net_flow:{$date}", 300, function () use ($rangeStart, $rangeEnd) {
|
||||
return UserCurrencyLog::query()
|
||||
->where('created_at', '>=', $rangeStart)
|
||||
->where('created_at', '<', $rangeEnd)
|
||||
->selectRaw('
|
||||
currency,
|
||||
SUM(CASE WHEN amount > 0 THEN amount ELSE 0 END) as total_in,
|
||||
ABS(SUM(CASE WHEN amount < 0 THEN amount ELSE 0 END)) as total_out,
|
||||
SUM(amount) as net_total
|
||||
')
|
||||
->groupBy('currency')
|
||||
->get()
|
||||
->keyBy('currency');
|
||||
});
|
||||
|
||||
$netFlow = [];
|
||||
|
||||
foreach (['exp', 'gold', 'charm'] as $currency) {
|
||||
$row = $rows->get($currency);
|
||||
|
||||
$netFlow[$currency] = [
|
||||
'in' => (int) ($row->total_in ?? 0),
|
||||
'out' => (int) ($row->total_out ?? 0),
|
||||
'net' => (int) ($row->net_total ?? 0),
|
||||
];
|
||||
}
|
||||
|
||||
return $netFlow;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析统计查询的日期边界,统一复用缓存 key 与时间范围。
|
||||
*
|
||||
* @param string|null $date 日期字符串如 '2026-02-28'
|
||||
* @return array{0:string, 1:CarbonImmutable, 2:CarbonImmutable}
|
||||
*/
|
||||
private function statsDateBounds(?string $date = null): array
|
||||
{
|
||||
$statsDate = CarbonImmutable::parse($date ?? today()->toDateString())->startOfDay();
|
||||
|
||||
return [
|
||||
$statsDate->toDateString(),
|
||||
$statsDate,
|
||||
$statsDate->addDay(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,12 +282,17 @@ class UserCurrencyService
|
||||
* @param int $userId 用户 ID
|
||||
* @param string|null $currency 为 null 时返回所有货币类型
|
||||
* @param int $days 查询最近多少天
|
||||
* @param string|null $direction income=收入 / expense=支出 / null=全部
|
||||
* @param array<int, string> $sources 来源 source 值列表,为空时不过滤
|
||||
*/
|
||||
public function userLogs(int $userId, ?string $currency = null, int $days = 7): Collection
|
||||
public function userLogs(int $userId, ?string $currency = null, int $days = 7, ?string $direction = null, array $sources = []): Collection
|
||||
{
|
||||
return UserCurrencyLog::query()
|
||||
->where('user_id', $userId)
|
||||
->when($currency, fn ($q) => $q->where('currency', $currency))
|
||||
->when($direction === 'income', fn ($q) => $q->where('amount', '>', 0))
|
||||
->when($direction === 'expense', fn ($q) => $q->where('amount', '<', 0))
|
||||
->when($sources !== [], fn ($q) => $q->whereIn('source', $sources))
|
||||
->where('created_at', '>=', now()->subDays($days))
|
||||
->orderByDesc('created_at')
|
||||
->limit(200)
|
||||
|
||||
Reference in New Issue
Block a user