前端极简黑白重设计,并纳入客户端注册、站点设置与后台相关改动

- storefront 全站改为极简黑白配色:直角、细线分隔、卡片 hover 浅底、深色模式(跟随系统+手动切换)
- 抽出 storefront/partials/card 复用卡片
- 一并提交此前暂存的客户端注册 API、站点设置、后台页面与测试

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
浪子
2026-09-22 08:35:49 +08:00
parent 62cffc6f5f
commit 04a2034975
41 changed files with 3447 additions and 658 deletions
@@ -0,0 +1,95 @@
@php
$statusLabel = $filters['status'] === 'online' ? '在线' : ($filters['status'] === 'offline' ? '离线' : '全部');
@endphp
@extends('admin.layout', [
'title' => 'Tstore Admin · 站点接入',
'pageTitle' => '站点接入',
'pageSubtitle' => '查看哪些 Typecho 站点已注册、是否在线,以及最近一次上报状态。',
'pageBadge' => 'Clients',
])
@section('content')
<div class="grid">
<section class="stats">
<div class="stat"><span class="label">已注册站点</span><span class="value">{{ $stats['registered_sites'] }}</span><span class="hint">完成 token 注册</span></div>
<div class="stat"><span class="label">在线站点</span><span class="value">{{ $stats['online_sites'] }}</span><span class="hint">{{ $onlineWindowMinutes }} 分钟内有心跳</span></div>
<div class="stat"><span class="label">离线站点</span><span class="value">{{ max($stats['registered_sites'] - $stats['online_sites'], 0) }}</span><span class="hint">超出在线窗口</span></div>
<div class="stat"><span class="label">追踪用户数</span><span class="value">{{ $stats['tracked_users'] }}</span><span class="hint">所有站点上报总和</span></div>
<div class="stat"><span class="label">当前筛选</span><span class="value">{{ $statusLabel }}</span><span class="hint">站点状态过滤</span></div>
</section>
<section class="panel">
<div class="toolbar">
<div class="section-title" style="margin-bottom:0">
<div>
<h2>站点列表</h2>
<p>插件端注册成功后会出现在这里,之后每次状态同步都会刷新最近心跳和用户数。</p>
</div>
</div>
<form method="get" class="filters">
<div class="field">
<label>状态</label>
<select class="select" name="status">
<option value="">全部</option>
<option value="online" @selected($filters['status'] === 'online')>在线</option>
<option value="offline" @selected($filters['status'] === 'offline')>离线</option>
</select>
</div>
<div class="field" style="flex:1 1 260px">
<label>搜索</label>
<input class="input" type="text" name="keyword" value="{{ $filters['keyword'] }}" placeholder="站点名、URL、Typecho 或 PHP 版本">
</div>
<div class="form-actions">
<button class="btn" type="submit">应用筛选</button>
<a class="btn secondary" href="{{ route('webadmin.clients') }}">重置</a>
</div>
</form>
</div>
<div class="table-wrap">
<table class="table">
<thead>
<tr>
<th>站点</th>
<th>状态</th>
<th>用户数</th>
<th>环境</th>
<th>注册时间</th>
<th>最近同步</th>
<th>Token 尾缀</th>
</tr>
</thead>
<tbody>
@forelse ($clients as $client)
<tr>
<td>
<strong>{{ $client->site_name ?: '未命名站点' }}</strong>
<div class="muted">{{ $client->site_url }}</div>
</td>
<td><span class="chip {{ $client->is_online ? 'ok' : 'muted' }}">{{ $client->is_online ? '在线' : '离线' }}</span></td>
<td>{{ $client->user_count }}</td>
<td>
<div>Typecho {{ $client->typecho_version ?: '-' }}</div>
<div class="muted">PHP {{ $client->php_version ?: '-' }} · 插件 {{ $client->plugin_version ?: '-' }}</div>
</td>
<td>{{ optional($client->registered_at)->format('Y-m-d H:i:s') ?: '-' }}</td>
<td>{{ optional($client->last_seen_at)->format('Y-m-d H:i:s') ?: '尚未同步' }}</td>
<td><code>...{{ $client->token_suffix ?: '--------' }}</code></td>
</tr>
@empty
<tr>
<td colspan="7">
<div class="empty">当前还没有站点完成注册。</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
{{ $clients->links() }}
</section>
</div>
@endsection