feat(api): 新增节点月流量限额强制下线

新增节点级月流量限额配置、重置调度和运行状态持久化
下发 traffic_limit 给 mi-node,并在超额后停止内核、到期后恢复
管理端支持编辑限额参数并展示额度进度、状态和下次重置
手动与定时重置会同步清理限额状态并通知节点刷新配置
This commit is contained in:
yinjianm
2026-04-29 00:46:12 +08:00
parent 52529d1f58
commit 922e86070d
26 changed files with 1127 additions and 11 deletions
@@ -0,0 +1,54 @@
<?php
namespace Tests\Unit;
use App\Models\Server;
use App\Services\ServerTrafficLimitService;
use Carbon\Carbon;
use Tests\TestCase;
class ServerTrafficLimitServiceTest extends TestCase
{
public function test_calculate_next_reset_at_clamps_day_to_short_month(): void
{
$server = new Server([
'traffic_limit_enabled' => true,
'transfer_enable' => 100,
'traffic_limit_reset_day' => 31,
'traffic_limit_reset_time' => '03:30',
'traffic_limit_timezone' => 'UTC',
]);
$nextReset = app(ServerTrafficLimitService::class)->calculateNextResetAt(
$server,
Carbon::create(2026, 2, 1, 0, 0, 0, 'UTC')
);
$this->assertSame('2026-02-28 03:30:00', $nextReset?->format('Y-m-d H:i:s'));
}
public function test_build_node_config_uses_transfer_enable_and_panel_usage(): void
{
$server = new Server([
'traffic_limit_enabled' => true,
'transfer_enable' => 1024,
'traffic_limit_reset_day' => 1,
'traffic_limit_reset_time' => '04:00',
'traffic_limit_timezone' => 'Asia/Shanghai',
'traffic_limit_next_reset_at' => 1774977600,
'u' => 400,
'd' => 600,
]);
$config = app(ServerTrafficLimitService::class)->buildNodeConfig($server);
$this->assertTrue($config['enabled']);
$this->assertSame(1024, $config['limit']);
$this->assertSame(1000, $config['current_used']);
$this->assertSame(1, $config['reset_day']);
$this->assertSame('04:00', $config['reset_time']);
$this->assertSame('Asia/Shanghai', $config['timezone']);
$this->assertSame(1774977600, $config['next_reset_at']);
$this->assertSame(Server::TRAFFIC_LIMIT_STATUS_NORMAL, $config['status']);
}
}