Files
xinfra/frontend/src/views/resource/StatusBoard.vue
T
wonder 46419bd57c feat(frontend): 添加资源管理页面骨架
页面:
- views/resource/StatusBoard.vue,资源状态看板(物理机/虚机/基础服务状态汇总)
- views/resource/Management.vue,资源管理(CMDB 物理机/虚机台账)

功能:
- 统计卡片展示
- 状态表格(按机房、业务线筛选)
- 进度条展示(CPU 使用率、健康率)

数据来源:SINA CMDB、阿里云同步、AWS 同步、七牛 LAS 同步
2026-07-14 15:40:04 +08:00

307 lines
7.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div>
<div class="page-head">
<div>
<h1>资源状态看板</h1>
<p>物理机 / 虚机 / 基础服务状态汇总</p>
</div>
<el-button @click="refresh">⟳ 刷新</el-button>
</div>
<div class="stat-row">
<div class="stat-card">
<div class="label">物理机总数</div>
<div class="value">186</div>
<div class="delta">186 / 186 监控覆盖</div>
</div>
<div class="stat-card">
<div class="label">虚机总数(LAS)</div>
<div class="value">512</div>
<div class="delta up">↑ 14 本周新增</div>
</div>
<div class="stat-card">
<div class="label">基础组件实例</div>
<div class="value">214</div>
<div class="delta">MySQL 38 · Redis 92 · 其他 84</div>
</div>
<div class="stat-card">
<div class="label">P0 / Disaster 告警</div>
<div class="value" style="color: var(--err)">1</div>
<div class="delta" style="color: var(--err)">来自 VictoriaMetrics</div>
</div>
<div class="stat-card">
<div class="label">P1 / High 告警</div>
<div class="value" style="color: var(--warn)">5</div>
<div class="delta warn">来自 Zabbix · 4 条 / VM · 1 条</div>
</div>
</div>
<div class="cols-2">
<div class="panel">
<div class="panel-head">
<h3>物理机状态 · 按机房</h3>
<span class="meta">数据源:Zabbix</span>
</div>
<div class="panel-body">
<table>
<tr><th>机房</th><th>总数</th><th>在线</th><th>健康率</th><th>状态</th></tr>
<tr class="tr-hover">
<td class="strong mono">YZH 机房</td>
<td class="mono">78</td>
<td class="mono">78</td>
<td><span class="bar-wrap"><span class="bar-fill" style="width: 98%"></span></span>98%</td>
<td class="status-text ok">● 正常</td>
</tr>
<tr class="tr-hover">
<td class="strong mono">XS 机房</td>
<td class="mono">64</td>
<td class="mono">63</td>
<td><span class="bar-wrap"><span class="bar-fill warn" style="width: 91%"></span></span>91%</td>
<td class="status-text warn">● 1 条告警</td>
</tr>
<tr class="tr-hover">
<td class="strong mono">JF 机房</td>
<td class="mono">22</td>
<td class="mono">22</td>
<td><span class="bar-wrap"><span class="bar-fill" style="width: 100%"></span></span>100%</td>
<td class="status-text ok">● 正常</td>
</tr>
<tr class="tr-hover">
<td class="strong mono">海外 IDC(4)</td>
<td class="mono">22</td>
<td class="mono">21</td>
<td><span class="bar-wrap"><span class="bar-fill err" style="width: 86%"></span></span>86%</td>
<td class="status-text err">● 1 条严重</td>
</tr>
</table>
</div>
</div>
<div class="panel">
<div class="panel-head">
<h3>虚机状态 · LAS 资源池</h3>
<span class="meta">数据源:VictoriaMetrics</span>
</div>
<div class="panel-body">
<table>
<tr><th>业务线</th><th>虚机数</th><th>CPU 均值</th><th>状态</th></tr>
<tr class="tr-hover">
<td class="strong mono">Kodo</td>
<td class="mono">218</td>
<td><span class="bar-wrap"><span class="bar-fill" style="width: 64%"></span></span>64%</td>
<td class="status-text ok">● 正常</td>
</tr>
<tr class="tr-hover">
<td class="strong mono">LAS</td>
<td class="mono">164</td>
<td><span class="bar-wrap"><span class="bar-fill warn" style="width: 82%"></span></span>82%</td>
<td class="status-text warn">● 1 条告警</td>
</tr>
<tr class="tr-hover">
<td class="strong mono">灵矽</td>
<td class="mono">96</td>
<td><span class="bar-wrap"><span class="bar-fill" style="width: 57%"></span></span>57%</td>
<td class="status-text ok">● 正常</td>
</tr>
<tr class="tr-hover">
<td class="strong mono">共享池 / 未分配</td>
<td class="mono">34</td>
<td><span class="bar-wrap"><span class="bar-fill" style="width: 31%"></span></span>31%</td>
<td class="status-text ok">● 正常</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
const refresh = () => {
// 刷新数据
}
</script>
<style scoped>
.page-head {
display: flex;
align-items: flex-end;
justify-content: space-between;
margin-bottom: 18px;
}
.page-head h1 {
font-size: 19px;
margin: 0 0 4px;
font-weight: 700;
letter-spacing: 0.2px;
}
.page-head p {
margin: 0;
color: var(--text-dim);
font-size: 12.5px;
}
.stat-row {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 12px;
margin-bottom: 20px;
}
.stat-card {
background: var(--bg-panel);
border: 1px solid var(--line);
border-radius: 8px;
padding: 14px 16px;
}
.stat-card .label {
font-size: 11px;
color: var(--text-dim);
margin-bottom: 8px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.stat-card .value {
font-family: var(--mono);
font-size: 24px;
font-weight: 600;
}
.stat-card .delta {
font-size: 11px;
color: var(--text-dim);
margin-top: 4px;
}
.stat-card .delta.up {
color: var(--accent);
}
.stat-card .delta.warn {
color: var(--warn);
}
.cols-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 18px;
}
.panel {
background: var(--bg-panel);
border: 1px solid var(--line);
border-radius: 8px;
}
.panel-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 13px 16px;
border-bottom: 1px solid var(--line-soft);
}
.panel-head h3 {
margin: 0;
font-size: 13.5px;
font-weight: 600;
}
.panel-head .meta {
font-size: 11.5px;
color: var(--text-dim);
font-family: var(--mono);
}
.panel-body {
padding: 4px 0;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 12.5px;
}
th {
text-align: left;
color: var(--text-dim);
font-weight: 500;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.4px;
padding: 9px 16px;
border-bottom: 1px solid var(--line-soft);
}
td {
padding: 11px 16px;
border-bottom: 1px solid var(--line-soft);
color: var(--text-mid);
}
tr:last-child td {
border-bottom: none;
}
tr.tr-hover:hover td {
background: var(--bg-panel-2);
}
.strong {
color: var(--text-hi);
font-weight: 500;
}
.mono {
font-family: var(--mono);
}
.bar-wrap {
width: 90px;
height: 5px;
background: #262C38;
border-radius: 3px;
overflow: hidden;
display: inline-block;
vertical-align: middle;
margin-right: 8px;
}
.bar-fill {
height: 100%;
border-radius: 3px;
background: var(--accent);
}
.bar-fill.warn {
background: var(--warn);
}
.bar-fill.err {
background: var(--err);
}
.status-text {
font-size: 12px;
display: flex;
align-items: center;
}
.status-text.ok {
color: var(--accent);
}
.status-text.warn {
color: var(--warn);
}
.status-text.err {
color: var(--err);
}
</style>