mirror of
https://github.com/lkddi/Xboard.git
synced 2026-04-24 12:07:28 +08:00
feat: improve traffic reset precision and admin features
- Increase traffic reset granularity to seconds - Add next reset time display in admin pane
This commit is contained in:
@@ -82,7 +82,8 @@ class TrafficResetService
|
||||
if (
|
||||
!$user->plan
|
||||
|| $user->plan->reset_traffic_method === Plan::RESET_TRAFFIC_NEVER
|
||||
|| ($user->plan->reset_traffic_method === Plan::RESET_TRAFFIC_FOLLOW_SYSTEM && (int) admin_setting('reset_traffic_method', Plan::RESET_TRAFFIC_MONTHLY) === Plan::RESET_TRAFFIC_NEVER)
|
||||
|| ($user->plan->reset_traffic_method === Plan::RESET_TRAFFIC_FOLLOW_SYSTEM
|
||||
&& (int) admin_setting('reset_traffic_method', Plan::RESET_TRAFFIC_MONTHLY) === Plan::RESET_TRAFFIC_NEVER)
|
||||
|| $user->expired_at === NULL
|
||||
) {
|
||||
return null;
|
||||
@@ -94,7 +95,7 @@ class TrafficResetService
|
||||
$resetMethod = (int) admin_setting('reset_traffic_method', Plan::RESET_TRAFFIC_MONTHLY);
|
||||
}
|
||||
|
||||
$now = Carbon::now();
|
||||
$now = Carbon::now(config('app.timezone'));
|
||||
|
||||
return match ($resetMethod) {
|
||||
Plan::RESET_TRAFFIC_FIRST_DAY_MONTH => $this->getNextMonthFirstDay($now),
|
||||
@@ -124,38 +125,20 @@ class TrafficResetService
|
||||
*/
|
||||
private function getNextMonthlyReset(User $user, Carbon $from): Carbon
|
||||
{
|
||||
$expiredAt = Carbon::createFromTimestamp($user->expired_at);
|
||||
$expiredAt = Carbon::createFromTimestamp($user->expired_at, config('app.timezone'));
|
||||
$resetDay = $expiredAt->day;
|
||||
|
||||
return $this->getNextResetByDay($from, $resetDay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next reset time based on a specific day of the month.
|
||||
*/
|
||||
private function getNextResetByDay(Carbon $from, int $targetDay): Carbon
|
||||
{
|
||||
$currentMonthTarget = $this->getValidDayInMonth($from->copy(), $targetDay);
|
||||
$resetTime = [$expiredAt->hour, $expiredAt->minute, $expiredAt->second];
|
||||
// 当前月目标时间
|
||||
$currentMonthTarget = $from->copy()->day($resetDay)
|
||||
->setTime(...$resetTime);
|
||||
if ($currentMonthTarget->timestamp > $from->timestamp) {
|
||||
return $currentMonthTarget;
|
||||
}
|
||||
|
||||
// 下月目标时间
|
||||
$nextMonth = $from->copy()->addMonth();
|
||||
return $this->getValidDayInMonth($nextMonth, $targetDay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a valid day in a given month, handling non-existent dates.
|
||||
*/
|
||||
private function getValidDayInMonth(Carbon $month, int $targetDay): Carbon
|
||||
{
|
||||
$lastDayOfMonth = $month->copy()->endOfMonth()->day;
|
||||
|
||||
if ($targetDay > $lastDayOfMonth) {
|
||||
return $month->endOfMonth()->startOfDay();
|
||||
}
|
||||
|
||||
return $month->day($targetDay)->startOfDay();
|
||||
$lastDayOfNextMonth = $nextMonth->copy()->endOfMonth()->day;
|
||||
$targetDay = min($resetDay, $lastDayOfNextMonth);
|
||||
return $nextMonth->copy()->day($targetDay)->setTime(...$resetTime);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,30 +160,21 @@ class TrafficResetService
|
||||
*/
|
||||
private function getNextYearlyReset(User $user, Carbon $from): Carbon
|
||||
{
|
||||
$expiredAt = Carbon::createFromTimestamp($user->expired_at);
|
||||
|
||||
$currentYearTarget = $this->getValidYearDate($from->copy(), $expiredAt);
|
||||
$expiredAt = Carbon::createFromTimestamp($user->expired_at, config('app.timezone'));
|
||||
$resetMonth = $expiredAt->month;
|
||||
$resetDay = $expiredAt->day;
|
||||
$resetTime = [$expiredAt->hour, $expiredAt->minute, $expiredAt->second];
|
||||
|
||||
$currentYearTarget = $from->copy()->month($resetMonth)->day($resetDay)->setTime(...$resetTime);
|
||||
if ($currentYearTarget->timestamp > $from->timestamp) {
|
||||
return $currentYearTarget;
|
||||
}
|
||||
|
||||
return $this->getValidYearDate($from->copy()->addYear(), $expiredAt);
|
||||
$nextYear = $from->copy()->addYear();
|
||||
$lastDayOfMonth = $nextYear->copy()->month($resetMonth)->endOfMonth()->day;
|
||||
$targetDay = min($resetDay, $lastDayOfMonth);
|
||||
return $nextYear->copy()->month($resetMonth)->day($targetDay)->setTime(...$resetTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a valid date in a given year, handling leap year cases for Feb 29th.
|
||||
*/
|
||||
private function getValidYearDate(Carbon $year, Carbon $expiredAt): Carbon
|
||||
{
|
||||
$target = $year->month($expiredAt->month)->day($expiredAt->day)->startOfDay();
|
||||
|
||||
if ($expiredAt->month === 2 && $expiredAt->day === 29 && !$target->isLeapYear()) {
|
||||
$target->day(28);
|
||||
}
|
||||
|
||||
return $target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the traffic reset log.
|
||||
|
||||
Reference in New Issue
Block a user