mirror of
https://github.com/lkddi/Xboard.git
synced 2026-04-28 06:47:24 +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 (
|
if (
|
||||||
!$user->plan
|
!$user->plan
|
||||||
|| $user->plan->reset_traffic_method === Plan::RESET_TRAFFIC_NEVER
|
|| $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
|
|| $user->expired_at === NULL
|
||||||
) {
|
) {
|
||||||
return null;
|
return null;
|
||||||
@@ -94,7 +95,7 @@ class TrafficResetService
|
|||||||
$resetMethod = (int) admin_setting('reset_traffic_method', Plan::RESET_TRAFFIC_MONTHLY);
|
$resetMethod = (int) admin_setting('reset_traffic_method', Plan::RESET_TRAFFIC_MONTHLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
$now = Carbon::now();
|
$now = Carbon::now(config('app.timezone'));
|
||||||
|
|
||||||
return match ($resetMethod) {
|
return match ($resetMethod) {
|
||||||
Plan::RESET_TRAFFIC_FIRST_DAY_MONTH => $this->getNextMonthFirstDay($now),
|
Plan::RESET_TRAFFIC_FIRST_DAY_MONTH => $this->getNextMonthFirstDay($now),
|
||||||
@@ -124,38 +125,20 @@ class TrafficResetService
|
|||||||
*/
|
*/
|
||||||
private function getNextMonthlyReset(User $user, Carbon $from): Carbon
|
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;
|
$resetDay = $expiredAt->day;
|
||||||
|
$resetTime = [$expiredAt->hour, $expiredAt->minute, $expiredAt->second];
|
||||||
return $this->getNextResetByDay($from, $resetDay);
|
// 当前月目标时间
|
||||||
}
|
$currentMonthTarget = $from->copy()->day($resetDay)
|
||||||
|
->setTime(...$resetTime);
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
if ($currentMonthTarget->timestamp > $from->timestamp) {
|
if ($currentMonthTarget->timestamp > $from->timestamp) {
|
||||||
return $currentMonthTarget;
|
return $currentMonthTarget;
|
||||||
}
|
}
|
||||||
|
// 下月目标时间
|
||||||
$nextMonth = $from->copy()->addMonth();
|
$nextMonth = $from->copy()->addMonth();
|
||||||
return $this->getValidDayInMonth($nextMonth, $targetDay);
|
$lastDayOfNextMonth = $nextMonth->copy()->endOfMonth()->day;
|
||||||
}
|
$targetDay = min($resetDay, $lastDayOfNextMonth);
|
||||||
|
return $nextMonth->copy()->day($targetDay)->setTime(...$resetTime);
|
||||||
/**
|
|
||||||
* 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -177,30 +160,21 @@ class TrafficResetService
|
|||||||
*/
|
*/
|
||||||
private function getNextYearlyReset(User $user, Carbon $from): Carbon
|
private function getNextYearlyReset(User $user, Carbon $from): Carbon
|
||||||
{
|
{
|
||||||
$expiredAt = Carbon::createFromTimestamp($user->expired_at);
|
$expiredAt = Carbon::createFromTimestamp($user->expired_at, config('app.timezone'));
|
||||||
|
$resetMonth = $expiredAt->month;
|
||||||
$currentYearTarget = $this->getValidYearDate($from->copy(), $expiredAt);
|
$resetDay = $expiredAt->day;
|
||||||
|
$resetTime = [$expiredAt->hour, $expiredAt->minute, $expiredAt->second];
|
||||||
|
|
||||||
|
$currentYearTarget = $from->copy()->month($resetMonth)->day($resetDay)->setTime(...$resetTime);
|
||||||
if ($currentYearTarget->timestamp > $from->timestamp) {
|
if ($currentYearTarget->timestamp > $from->timestamp) {
|
||||||
return $currentYearTarget;
|
return $currentYearTarget;
|
||||||
}
|
}
|
||||||
|
$nextYear = $from->copy()->addYear();
|
||||||
return $this->getValidYearDate($from->copy()->addYear(), $expiredAt);
|
$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.
|
* Record the traffic reset log.
|
||||||
|
|||||||
Vendored
+6
-6
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -2310,6 +2310,7 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
|
|||||||
"commission": "Commission",
|
"commission": "Commission",
|
||||||
"register_time": "Register Time",
|
"register_time": "Register Time",
|
||||||
"actions": "Actions",
|
"actions": "Actions",
|
||||||
|
"next_reset_at": "Next Reset At",
|
||||||
"device_limit": {
|
"device_limit": {
|
||||||
"unlimited": "No device limit",
|
"unlimited": "No device limit",
|
||||||
"limited": "Maximum {{count}} devices allowed"
|
"limited": "Maximum {{count}} devices allowed"
|
||||||
|
|||||||
Vendored
+1
@@ -2383,6 +2383,7 @@ window.XBOARD_TRANSLATIONS['zh-CN'] = {
|
|||||||
"commission": "佣金",
|
"commission": "佣金",
|
||||||
"register_time": "注册时间",
|
"register_time": "注册时间",
|
||||||
"actions": "操作",
|
"actions": "操作",
|
||||||
|
"next_reset_at": "下次重置时间",
|
||||||
"device_limit": {
|
"device_limit": {
|
||||||
"unlimited": "无设备数限制",
|
"unlimited": "无设备数限制",
|
||||||
"limited": "最多可同时在线 {{count}} 台设备"
|
"limited": "最多可同时在线 {{count}} 台设备"
|
||||||
|
|||||||
Reference in New Issue
Block a user