feat(api): 新增节点流量悬浮详情与即时自动上线同步
为 server/manage/getNodes 返回节点级今日、本月与累计流量统计, 并在节点管理页名称悬浮层展示上行、下行和合计流量。 同时为自动上线补齐单节点同步入口,在管理端保存、 批量更新以及 REST/WS 心跳后立即同步 show 状态, 避免复制节点后开启自动上线仍需等待定时任务。 另优化管理端前端 Docker 发布流程,默认仅构建 amd64, 并收敛 BuildKit 缓存导出以缩短发布时间
This commit is contained in:
@@ -7,6 +7,8 @@ use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\ServerSave;
|
||||
use App\Models\Server;
|
||||
use App\Models\ServerGroup;
|
||||
use App\Models\StatServer;
|
||||
use App\Services\ServerAutoOnlineService;
|
||||
use App\Services\ServerGfwCheckService;
|
||||
use App\Services\ServerService;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -17,14 +19,80 @@ class ManageController extends Controller
|
||||
{
|
||||
public function getNodes(Request $request)
|
||||
{
|
||||
$servers = app(ServerGfwCheckService::class)->decorateServers(ServerService::getAllServers())->map(function ($item) {
|
||||
$servers = ServerService::getAllServers();
|
||||
$trafficStats = $this->buildNodeTrafficStats($servers);
|
||||
|
||||
$servers = app(ServerGfwCheckService::class)->decorateServers($servers)->map(function ($item) use ($trafficStats) {
|
||||
$item['groups'] = ServerGroup::whereIn('id', $item['group_ids'] ?? [])->get(['name', 'id']);
|
||||
$item['parent'] = $item->parent;
|
||||
$item['traffic_stats'] = $trafficStats[(int) $item['id']] ?? $this->emptyNodeTrafficStats();
|
||||
return $item;
|
||||
});
|
||||
return $this->success($servers);
|
||||
}
|
||||
|
||||
private function buildNodeTrafficStats($servers): array
|
||||
{
|
||||
$stats = [];
|
||||
foreach ($servers as $server) {
|
||||
$serverId = (int) $server->id;
|
||||
$stats[$serverId] = $this->emptyNodeTrafficStats();
|
||||
$stats[$serverId]['total'] = $this->buildTrafficAmount($server->u ?? 0, $server->d ?? 0);
|
||||
}
|
||||
|
||||
if (empty($stats)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$this->fillTrafficWindow($stats, 'today', strtotime('today'));
|
||||
$this->fillTrafficWindow($stats, 'month', strtotime(date('Y-m-01')));
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
private function fillTrafficWindow(array &$stats, string $key, int $startAt): void
|
||||
{
|
||||
$rows = StatServer::query()
|
||||
->selectRaw('server_id, COALESCE(SUM(u), 0) as upload, COALESCE(SUM(d), 0) as download')
|
||||
->whereIn('server_id', array_keys($stats))
|
||||
->where('record_type', 'd')
|
||||
->where('record_at', '>=', $startAt)
|
||||
->groupBy('server_id')
|
||||
->get();
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$stats[(int) $row->server_id][$key] = $this->buildTrafficAmount($row->upload, $row->download);
|
||||
}
|
||||
}
|
||||
|
||||
private function emptyNodeTrafficStats(): array
|
||||
{
|
||||
return [
|
||||
'today' => $this->buildTrafficAmount(0, 0),
|
||||
'month' => $this->buildTrafficAmount(0, 0),
|
||||
'total' => $this->buildTrafficAmount(0, 0),
|
||||
];
|
||||
}
|
||||
|
||||
private function buildTrafficAmount($upload, $download): array
|
||||
{
|
||||
$upload = max(0, (int) $upload);
|
||||
$download = max(0, (int) $download);
|
||||
|
||||
return [
|
||||
'upload' => $upload,
|
||||
'download' => $download,
|
||||
'total' => $upload + $download,
|
||||
];
|
||||
}
|
||||
|
||||
private function syncAutoOnlineIfEnabled(Server $server): void
|
||||
{
|
||||
if ((bool) $server->auto_online) {
|
||||
app(ServerAutoOnlineService::class)->syncServer($server);
|
||||
}
|
||||
}
|
||||
|
||||
public function sort(Request $request)
|
||||
{
|
||||
ini_set('post_max_size', '1m');
|
||||
@@ -64,6 +132,7 @@ class ManageController extends Controller
|
||||
$params['gfw_auto_action_at'] = null;
|
||||
}
|
||||
$server->update($params);
|
||||
$this->syncAutoOnlineIfEnabled($server);
|
||||
return $this->success(true);
|
||||
} catch (\Exception $e) {
|
||||
Log::error($e);
|
||||
@@ -72,7 +141,8 @@ class ManageController extends Controller
|
||||
}
|
||||
|
||||
try {
|
||||
Server::create($params);
|
||||
$server = Server::create($params);
|
||||
$this->syncAutoOnlineIfEnabled($server);
|
||||
return $this->success(true);
|
||||
} catch (\Exception $e) {
|
||||
Log::error($e);
|
||||
@@ -118,6 +188,8 @@ class ManageController extends Controller
|
||||
return $this->fail([500, '保存失败']);
|
||||
}
|
||||
|
||||
$this->syncAutoOnlineIfEnabled($server);
|
||||
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
@@ -295,6 +367,12 @@ class ManageController extends Controller
|
||||
$server->update($update);
|
||||
}
|
||||
});
|
||||
$servers->each(function (Server $server) {
|
||||
$freshServer = $server->fresh();
|
||||
if ($freshServer) {
|
||||
$this->syncAutoOnlineIfEnabled($freshServer);
|
||||
}
|
||||
});
|
||||
return $this->success(true);
|
||||
} catch (\Exception $e) {
|
||||
Log::error($e);
|
||||
|
||||
Reference in New Issue
Block a user