feat(admin-frontend): 新增节点自动上线托管能力
为节点新增 auto_online 字段与后台同步任务, 仅对开启托管的节点按在线状态自动同步前台显示。 管理端补齐单节点与批量开关、列表标识与统计, 并在自动上线启用时禁用手动显隐切换。 后端新增定时命令、保存校验、批量更新支持、 数据库迁移与单元测试,保证托管逻辑可落地。
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Services\ServerAutoOnlineService;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class SyncServerAutoOnline extends Command
|
||||
{
|
||||
protected $signature = 'sync:server-auto-online';
|
||||
|
||||
protected $description = 'Sync visible status for nodes with auto online enabled';
|
||||
|
||||
public function handle(ServerAutoOnlineService $service): int
|
||||
{
|
||||
$result = $service->sync();
|
||||
|
||||
$this->info(sprintf(
|
||||
'Server auto online synced: total=%d updated=%d shown=%d hidden=%d unchanged=%d',
|
||||
$result['total'],
|
||||
$result['updated'],
|
||||
$result['shown'],
|
||||
$result['hidden'],
|
||||
$result['unchanged']
|
||||
));
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ class Kernel extends ConsoleKernel
|
||||
$schedule->command('horizon:snapshot')->everyFiveMinutes()->onOneServer();
|
||||
// cleanup stale online_count (GC for Redis TTL expiration)
|
||||
$schedule->command('cleanup:online-status')->everyFiveMinutes()->onOneServer();
|
||||
$schedule->command('sync:server-auto-online')->everyFiveMinutes()->onOneServer()->withoutOverlapping(5);
|
||||
// backup Timing
|
||||
// if (env('ENABLE_AUTO_BACKUP_AND_UPDATE', false)) {
|
||||
// $schedule->command('backup:database', ['true'])->daily()->onOneServer();
|
||||
|
||||
@@ -81,6 +81,7 @@ class ManageController extends Controller
|
||||
$params = $request->validate([
|
||||
'id' => 'required|integer',
|
||||
'show' => 'nullable|integer',
|
||||
'auto_online' => 'nullable|boolean',
|
||||
'machine_id' => 'nullable|integer',
|
||||
'enabled' => 'nullable|boolean',
|
||||
]);
|
||||
@@ -93,6 +94,9 @@ class ManageController extends Controller
|
||||
if (array_key_exists('show', $params)) {
|
||||
$server->show = (int) $params['show'];
|
||||
}
|
||||
if (array_key_exists('auto_online', $params)) {
|
||||
$server->auto_online = (bool) $params['auto_online'];
|
||||
}
|
||||
if (array_key_exists('machine_id', $params)) {
|
||||
$server->machine_id = $params['machine_id'] ?: null;
|
||||
}
|
||||
@@ -226,6 +230,7 @@ class ManageController extends Controller
|
||||
'ids' => 'required|array',
|
||||
'ids.*' => 'integer',
|
||||
'show' => 'nullable|integer|in:0,1',
|
||||
'auto_online' => 'nullable|boolean',
|
||||
'enabled' => 'nullable|boolean',
|
||||
'machine_id' => 'nullable|integer',
|
||||
'host' => 'sometimes|required|string',
|
||||
@@ -243,6 +248,9 @@ class ManageController extends Controller
|
||||
if (array_key_exists('show', $params) && $params['show'] !== null) {
|
||||
$update['show'] = (int) $params['show'];
|
||||
}
|
||||
if (array_key_exists('auto_online', $params) && $params['auto_online'] !== null) {
|
||||
$update['auto_online'] = (bool) $params['auto_online'];
|
||||
}
|
||||
if (array_key_exists('enabled', $params) && $params['enabled'] !== null) {
|
||||
$update['enabled'] = (bool) $params['enabled'];
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ class ServerSave extends FormRequest
|
||||
'spectific_key' => 'nullable|string',
|
||||
'code' => 'nullable|string',
|
||||
'show' => '',
|
||||
'auto_online' => 'nullable|boolean',
|
||||
'name' => 'required|string',
|
||||
'group_ids' => 'nullable|array',
|
||||
'route_ids' => 'nullable|array',
|
||||
|
||||
@@ -24,6 +24,7 @@ use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
* @property array|null $route_ids 路由IDs
|
||||
* @property array|null $tags 标签
|
||||
* @property boolean $show 是否显示
|
||||
* @property boolean $auto_online 是否根据在线状态自动同步显示
|
||||
* @property string|null $allow_insecure 是否允许不安全
|
||||
* @property string|null $network 网络类型
|
||||
* @property int|null $parent_id 父节点ID
|
||||
@@ -36,7 +37,7 @@ use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
* @property int $updated_at
|
||||
*
|
||||
* @property-read Server|null $parent 父节点
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, StatServer> $stats 节点统计
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, StatServer> $stats 节点统计
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, ServerGfwCheck> $gfwChecks 墙状态检测记录
|
||||
*
|
||||
* @property-read int|null $last_check_at 最后检查时间(Unix时间戳)
|
||||
@@ -125,6 +126,7 @@ class Server extends Model
|
||||
'last_check_at' => 'integer',
|
||||
'last_push_at' => 'integer',
|
||||
'show' => 'boolean',
|
||||
'auto_online' => 'boolean',
|
||||
'enabled' => 'boolean',
|
||||
'created_at' => 'timestamp',
|
||||
'updated_at' => 'timestamp',
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Server;
|
||||
|
||||
class ServerAutoOnlineService
|
||||
{
|
||||
public function sync(): array
|
||||
{
|
||||
$servers = Server::query()
|
||||
->where('auto_online', true)
|
||||
->get();
|
||||
|
||||
$result = [
|
||||
'total' => $servers->count(),
|
||||
'updated' => 0,
|
||||
'shown' => 0,
|
||||
'hidden' => 0,
|
||||
'unchanged' => 0,
|
||||
];
|
||||
|
||||
foreach ($servers as $server) {
|
||||
$shouldShow = (int) $server->available_status !== Server::STATUS_OFFLINE;
|
||||
|
||||
if ((bool) $server->show === $shouldShow) {
|
||||
$result['unchanged']++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$server->show = $shouldShow;
|
||||
$server->save();
|
||||
|
||||
$result['updated']++;
|
||||
$shouldShow ? $result['shown']++ : $result['hidden']++;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user