更新后端服务UI

客户端重构部分界面UI
This commit is contained in:
QWQLwToo
2026-06-30 11:45:52 +08:00
parent 7745e7a2d4
commit 1d0e862299
13 changed files with 942 additions and 121 deletions
@@ -16,7 +16,7 @@ use([CanvasRenderer, LineChart, PieChart, BarChart, GaugeChart, GridComponent, T
<div class="metric-grid">
<article class="metric"><span>反馈总数</span><strong>{{ ctx.kpis.feedbackTotal || 0 }}</strong><small>今日新增 {{ ctx.kpis.feedbackToday || 0 }}</small></article>
<article class="metric"><span>可见接口</span><strong>{{ ctx.kpis.sourceVisible || 0 }}</strong><small>接口总数 {{ ctx.kpis.sourceTotal || 0 }}</small></article>
<article class="metric"><span>版本日志</span><strong>{{ ctx.kpis.releaseNotices || 0 }}</strong><small>{{ ctx.latestNotice?.version || "暂无最新版本" }}</small></article>
<article class="metric"><span>版本日志</span><strong>{{ ctx.kpis.releaseNotices || 0 }}</strong><small>{{ ctx.latestNotice && ctx.latestNotice.version ? ctx.latestNotice.version : "暂无最新版本" }}</small></article>
<article class="metric"><span>邮件失败</span><strong>{{ ctx.kpis.mailFailed || 0 }}</strong><small>旧反馈兼容记录</small></article>
</div>
@@ -26,7 +26,8 @@ use([CanvasRenderer, LineChart, PieChart, BarChart, GaugeChart, GridComponent, T
<component :is="ctx.autoRefreshPaused ? PlayCircle : PauseCircle" :size="16" />
{{ ctx.autoRefreshPaused ? "恢复自动刷新" : "暂停自动刷新" }}
</button>
<span class="muted"> 15 秒自动刷新仪表盘数据</span>
<span class="muted"> 15 秒自动刷新</span>
<span v-if="ctx.lastRefreshedAt" class="muted">上次刷新{{ ctx.lastRefreshedAt }}</span>
</div>
<section v-if="ctx.sourceCheckJobs.length" class="panel">
@@ -37,10 +38,10 @@ use([CanvasRenderer, LineChart, PieChart, BarChart, GaugeChart, GridComponent, T
<tr v-for="job in ctx.sourceCheckJobs.slice(0, 5)" :key="job.id">
<td class="mono">{{ job.id }}</td>
<td>{{ job.checked || 0 }} / {{ job.total || 0 }}</td>
<td>{{ job.stats?.ok || 0 }}</td>
<td>{{ job.stats?.redirected || 0 }}</td>
<td>{{ job.stats?.degraded || 0 }}</td>
<td>{{ job.stats?.error || 0 }}</td>
<td>{{ (job.stats && job.stats.ok) || 0 }}</td>
<td>{{ (job.stats && job.stats.redirected) || 0 }}</td>
<td>{{ (job.stats && job.stats.degraded) || 0 }}</td>
<td>{{ (job.stats && job.stats.error) || 0 }}</td>
<td>{{ job.startedAt || "-" }}</td>
</tr>
</tbody>
@@ -53,7 +54,7 @@ use([CanvasRenderer, LineChart, PieChart, BarChart, GaugeChart, GridComponent, T
<VChart class="chart" :option="ctx.heartbeatOption" autoresize />
<div v-if="ctx.isHeartbeatChartEmpty" class="chart-empty">
<strong>暂无服务端检测记录</strong>
<span>点击立即服务端检测后会生成延迟曲线</span>
<span>点击立即服务端检测后会生成延迟曲线</span>
</div>
</section>
<section class="panel chart-panel"><h2>接口健康分布</h2><VChart class="chart" :option="ctx.healthOption" autoresize /></section>
@@ -68,12 +69,12 @@ use([CanvasRenderer, LineChart, PieChart, BarChart, GaugeChart, GridComponent, T
<tbody>
<tr v-for="item in ctx.heartbeats.slice(0, 10)" :key="item.id">
<td>{{ item.name || item.sourceId }}</td>
<td><span :class="['badge', ctx.statusTone(item.status)]">{{ ctx.labelStatus(item.status) }}</span></td>
<td><span :class='["badge", ctx.statusTone(item.status)]'>{{ ctx.labelStatus(item.status) }}</span></td>
<td>{{ item.latencyMs || 0 }}ms</td>
<td class="hash">{{ ctx.formatHealthOutput(item) }}</td>
<td>{{ item.checkedAt || "-" }}</td>
</tr>
<tr v-if="ctx.heartbeats.length === 0"><td colspan="5">暂无检测记录点击立即服务端检测后会刷新</td></tr>
<tr v-if="ctx.heartbeats.length === 0"><td colspan="5">暂无检测记录点击立即服务端检测后会刷新</td></tr>
</tbody>
</table>
</section>
@@ -85,7 +86,7 @@ use([CanvasRenderer, LineChart, PieChart, BarChart, GaugeChart, GridComponent, T
<tbody>
<tr v-for="item in ctx.clientCalls.slice(0, 8)" :key="item.id">
<td>{{ item.sourceId }}</td>
<td><span :class="['badge', ctx.statusTone(item.status)]">{{ ctx.labelStatus(item.status) }}</span></td>
<td><span :class='["badge", ctx.statusTone(item.status)]'>{{ ctx.labelStatus(item.status) }}</span></td>
<td>{{ item.latencyMs || 0 }}ms</td>
<td class="hash">{{ item.client || "-" }}</td>
<td>{{ item.createdAt || "-" }}</td>
@@ -94,5 +95,37 @@ use([CanvasRenderer, LineChart, PieChart, BarChart, GaugeChart, GridComponent, T
</tbody>
</table>
</section>
<section class="panel">
<div class="section-head">
<h2>系统日志</h2>
<div style="display:flex;gap:8px;align-items:center">
<select v-model="ctx.systemLogPage.category" style="width:100px" @change="ctx.loadSystemLogs">
<option value="">全部分类</option>
<option value="feedback">反馈</option>
<option value="release">发布</option>
<option value="auth">认证</option>
<option value="legacy">兼容</option>
<option value="source">接口</option>
<option value="database">数据库</option>
<option value="risk">风险</option>
</select>
<button class="btn ghost" style="padding:3px 10px;font-size:12px" @click="ctx.loadSystemLogs">刷新</button>
</div>
</div>
<table>
<thead><tr><th>分类</th><th>类型</th><th>状态</th><th>消息</th><th>时间</th></tr></thead>
<tbody>
<tr v-for="item in (ctx.systemLogPage.items || []).slice(0, 20)" :key="item.id">
<td><span class="badge neutral">{{ item.category || "-" }}</span></td>
<td class="mono">{{ item.type || "-" }}</td>
<td><span :class='["badge", ctx.statusTone(item.status)]'>{{ ctx.labelStatus(item.status) }}</span></td>
<td>{{ item.message || "-" }}</td>
<td>{{ item.createdAt || "-" }}</td>
</tr>
<tr v-if="!(ctx.systemLogPage.items || []).length"><td colspan="5">暂无系统日志</td></tr>
</tbody>
</table>
</section>
</section>
</template>