Merge remote-tracking branch 'origin/main' into auth-login
This commit is contained in:
@@ -12,7 +12,7 @@ export interface Subsystem {
|
||||
url: string
|
||||
domain: string
|
||||
category: string
|
||||
status: 'integrated' | 'integrating'
|
||||
status: 'active' | 'integrated' | 'integrating'
|
||||
sso_enabled: boolean
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ const mockSubsystems: Subsystem[] = [
|
||||
url: 'https://wayne.qiniu.com',
|
||||
domain: 'wayne.xinfra.internal',
|
||||
category: '容器管理',
|
||||
status: 'integrated',
|
||||
status: 'active',
|
||||
sso_enabled: true,
|
||||
},
|
||||
{
|
||||
@@ -43,7 +43,7 @@ const mockSubsystems: Subsystem[] = [
|
||||
url: 'https://clouddm.qiniu.com',
|
||||
domain: 'clouddm.xinfra.internal',
|
||||
category: '数据库',
|
||||
status: 'integrated',
|
||||
status: 'active',
|
||||
sso_enabled: true,
|
||||
},
|
||||
{
|
||||
@@ -79,7 +79,7 @@ const mockSubsystems: Subsystem[] = [
|
||||
url: 'https://qpass.xinfra.internal',
|
||||
domain: 'qpass.xinfra.internal',
|
||||
category: '内部系统',
|
||||
status: 'integrated',
|
||||
status: 'integrating',
|
||||
sso_enabled: true,
|
||||
},
|
||||
{
|
||||
@@ -91,7 +91,19 @@ const mockSubsystems: Subsystem[] = [
|
||||
url: 'https://grafana.xinfra.internal',
|
||||
domain: 'grafana.xinfra.internal',
|
||||
category: '可观测性',
|
||||
status: 'integrated',
|
||||
status: 'integrating',
|
||||
sso_enabled: true,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: 'Superset',
|
||||
label: '日志数据可视化',
|
||||
description: '日志数据探索与可视化分析平台,支持多数据源接入和丰富的图表展示。',
|
||||
icon: 'SS',
|
||||
url: 'https://superset.xinfra.internal',
|
||||
domain: 'superset.xinfra.internal',
|
||||
category: '可观测性',
|
||||
status: 'integrating',
|
||||
sso_enabled: true,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -11,29 +11,29 @@
|
||||
<router-link to="/service/catalog" class="nav-item" active-class="active">
|
||||
<span class="ic">▤</span>基础服务
|
||||
</router-link>
|
||||
<router-link to="/tasks" class="nav-item" active-class="active">
|
||||
<router-link to="/task/log" class="nav-item" active-class="active">
|
||||
<span class="ic">▧</span>任务日志<span class="badge">2</span>
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="nav-group">
|
||||
<div class="nav-label">资源纳管</div>
|
||||
<router-link to="/resource/mgmt" class="nav-item" active-class="active">
|
||||
<router-link to="/resource/management" class="nav-item" active-class="active">
|
||||
<span class="ic">▥</span>资源管理<span class="badge">CMDB</span>
|
||||
</router-link>
|
||||
<router-link to="/cluster" class="nav-item" active-class="active">
|
||||
<router-link to="/infrastructure/cluster" class="nav-item" active-class="active">
|
||||
<span class="ic">◆</span>集群与容器<span class="badge">3</span>
|
||||
</router-link>
|
||||
<router-link to="/tenants" class="nav-item" active-class="active">
|
||||
<router-link to="/business/quota" class="nav-item" active-class="active">
|
||||
<span class="ic">▦</span>业务配额
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="nav-group">
|
||||
<div class="nav-label">可观测性</div>
|
||||
<router-link to="/monitor" class="nav-item" active-class="active">
|
||||
<span class="ic">◎</span>监控
|
||||
<router-link to="/observable/monitoring" class="nav-item" active-class="active">
|
||||
<span class="ic">◎</span>监控看板
|
||||
</router-link>
|
||||
<router-link to="/alert" class="nav-item" active-class="active">
|
||||
<span class="ic">⚡</span>告警
|
||||
<router-link to="/observable/alert" class="nav-item" active-class="active">
|
||||
<span class="ic">⚡</span>告警信息
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="nav-group">
|
||||
@@ -60,7 +60,7 @@
|
||||
<span class="ic" style="font-size:12px;">▦</span>全部总览
|
||||
</router-link>
|
||||
</div>
|
||||
<router-link to="/subsystem/authz" class="nav-item" active-class="active">
|
||||
<router-link to="/subsystem/authorization" class="nav-item" active-class="active">
|
||||
<span class="ic">▦</span>子系统赋权
|
||||
</router-link>
|
||||
<router-link v-if="isPlatformAdmin" to="/business-line/manage" class="nav-item" active-class="active">
|
||||
@@ -75,7 +75,7 @@
|
||||
<router-link to="/audit/login" class="nav-item" active-class="active">
|
||||
<span class="ic">📋</span>登录审计
|
||||
</router-link>
|
||||
<router-link to="/audit/ops" class="nav-item" active-class="active">
|
||||
<router-link to="/audit/operation" class="nav-item" active-class="active">
|
||||
<span class="ic">📝</span>运维操作审计
|
||||
</router-link>
|
||||
</div>
|
||||
@@ -104,6 +104,7 @@ const subsystems = [
|
||||
{ name: 'Apollo', label: '配置中心', icon: 'AP' },
|
||||
{ name: 'qpass', label: '七牛统一运维平台', icon: 'QP' },
|
||||
{ name: 'Grafana', label: '指标可视化平台', icon: 'GF' },
|
||||
{ name: 'Superset', label: '日志数据可视化', icon: 'SS' },
|
||||
]
|
||||
|
||||
const isPortalActive = computed(() => {
|
||||
@@ -118,6 +119,7 @@ function dotColor(icon: string): string {
|
||||
AP: 'var(--tag-blue-text)',
|
||||
QP: 'var(--tag-amber-text)',
|
||||
GF: 'var(--warn)',
|
||||
SS: 'var(--tag-cyan-text)',
|
||||
}
|
||||
return colors[icon] || 'var(--text-dim)'
|
||||
}
|
||||
|
||||
@@ -11,20 +11,23 @@
|
||||
</div>
|
||||
<p>{{ system.description }}</p>
|
||||
<div class="sso-row">
|
||||
<span class="sso-dot" :class="{ warn: system.status === 'integrating' }"></span>
|
||||
{{ system.status === 'integrated' ? 'LDAP 原生配置接入 · 零代码' : 'LDAP 接入改造中' }}
|
||||
<span class="sso-dot" :class="{ warn: system.status !== 'active' }"></span>
|
||||
{{ system.status === 'active' ? 'LDAP 原生配置接入 · 在线' : 'LDAP 接入改造中' }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { subsystemApi, type Subsystem } from '@/api/subsystem'
|
||||
import { useRouter } from 'vue-router'
|
||||
import type { Subsystem } from '@/api/subsystem'
|
||||
|
||||
const props = defineProps<{
|
||||
system: Subsystem
|
||||
}>()
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const bgColor = computed(() => {
|
||||
const colors: Record<string, string> = {
|
||||
W: 'var(--logo-w-bg)',
|
||||
@@ -33,6 +36,7 @@ const bgColor = computed(() => {
|
||||
AP: 'var(--logo-ap-bg)',
|
||||
QP: 'var(--logo-qp-bg)',
|
||||
GF: 'var(--logo-gf-bg)',
|
||||
SS: 'var(--logo-ss-bg)',
|
||||
}
|
||||
return colors[props.system.icon] || 'var(--bg-panel-2)'
|
||||
})
|
||||
@@ -45,17 +49,13 @@ const iconColor = computed(() => {
|
||||
AP: 'var(--tag-blue-text)',
|
||||
QP: 'var(--tag-amber-text)',
|
||||
GF: 'var(--warn)',
|
||||
SS: 'var(--tag-cyan-text)',
|
||||
}
|
||||
return colors[props.system.icon] || 'var(--text-mid)'
|
||||
})
|
||||
|
||||
const handleClick = async () => {
|
||||
if (props.system.sso_enabled) {
|
||||
const { data } = await subsystemApi.getSSOUrl(props.system.id)
|
||||
window.location.assign(data.sso_url)
|
||||
} else {
|
||||
window.open(props.system.url, '_blank')
|
||||
}
|
||||
const handleClick = () => {
|
||||
router.push(`/subsystem/detail/${props.system.name.toLowerCase()}`)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -42,8 +42,8 @@ const router = createRouter({
|
||||
meta: { title: '子系统详情' },
|
||||
},
|
||||
{
|
||||
path: 'subsystem/authz',
|
||||
name: 'SubsystemAuthz',
|
||||
path: 'subsystem/authorization',
|
||||
name: 'SubsystemAuthorization',
|
||||
component: () => import('@/views/subsystem/Authorization.vue'),
|
||||
meta: { title: '子系统赋权' },
|
||||
},
|
||||
@@ -70,8 +70,8 @@ const router = createRouter({
|
||||
meta: { title: '登录审计' },
|
||||
},
|
||||
{
|
||||
path: 'audit/ops',
|
||||
name: 'OpsAudit',
|
||||
path: 'audit/operation',
|
||||
name: 'OperationAudit',
|
||||
component: () => import('@/views/audit/OpsAudit.vue'),
|
||||
meta: { title: '运维操作审计' },
|
||||
},
|
||||
@@ -82,20 +82,20 @@ const router = createRouter({
|
||||
meta: { title: '资源状态看板' },
|
||||
},
|
||||
{
|
||||
path: 'resource/mgmt',
|
||||
name: 'ResourceMgmt',
|
||||
path: 'resource/management',
|
||||
name: 'ResourceManagement',
|
||||
component: () => import('@/views/resource/Management.vue'),
|
||||
meta: { title: '资源管理' },
|
||||
},
|
||||
{
|
||||
path: 'cluster',
|
||||
name: 'Cluster',
|
||||
path: 'infrastructure/cluster',
|
||||
name: 'InfrastructureCluster',
|
||||
component: () => import('@/views/cluster/ClusterList.vue'),
|
||||
meta: { title: '集群与容器' },
|
||||
},
|
||||
{
|
||||
path: 'tenants',
|
||||
name: 'Tenants',
|
||||
path: 'business/quota',
|
||||
name: 'BusinessQuota',
|
||||
component: () => import('@/views/resource/Tenants.vue'),
|
||||
meta: { title: '业务配额' },
|
||||
},
|
||||
@@ -103,19 +103,19 @@ const router = createRouter({
|
||||
path: 'service/catalog',
|
||||
name: 'ServiceCatalog',
|
||||
component: () => import('@/views/service/Catalog.vue'),
|
||||
meta: { title: '基础服务目录' },
|
||||
meta: { title: '基础服务' },
|
||||
},
|
||||
{
|
||||
path: 'service/mgmt',
|
||||
name: 'ServiceMgmt',
|
||||
path: 'service/management',
|
||||
name: 'ServiceManagement',
|
||||
component: () => import('@/views/service/Management.vue'),
|
||||
meta: { title: '服务管理' },
|
||||
},
|
||||
{
|
||||
path: 'tasks',
|
||||
name: 'Tasks',
|
||||
path: 'task/log',
|
||||
name: 'TaskLog',
|
||||
component: () => import('@/views/task/TaskCenter.vue'),
|
||||
meta: { title: '任务中心' },
|
||||
meta: { title: '任务日志' },
|
||||
},
|
||||
{
|
||||
path: 'config',
|
||||
@@ -124,16 +124,16 @@ const router = createRouter({
|
||||
meta: { title: '配置中心管理' },
|
||||
},
|
||||
{
|
||||
path: 'monitor',
|
||||
name: 'Monitor',
|
||||
path: 'observable/monitoring',
|
||||
name: 'MonitoringDashboard',
|
||||
component: () => import('@/views/monitor/Monitor.vue'),
|
||||
meta: { title: '监控' },
|
||||
meta: { title: '监控看板' },
|
||||
},
|
||||
{
|
||||
path: 'alert',
|
||||
name: 'Alert',
|
||||
path: 'observable/alert',
|
||||
name: 'AlertInformation',
|
||||
component: () => import('@/views/monitor/Alert.vue'),
|
||||
meta: { title: '告警' },
|
||||
meta: { title: '告警信息' },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -89,29 +89,6 @@ button {
|
||||
background: var(--text-dim);
|
||||
}
|
||||
|
||||
/* 状态文本 */
|
||||
.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);
|
||||
}
|
||||
|
||||
.status-text.idle {
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
/* 标签 */
|
||||
.tag {
|
||||
display: inline-flex;
|
||||
@@ -387,8 +364,7 @@ tr.tr-hover.active td {
|
||||
/* ========== 状态文本 ========== */
|
||||
.status-text {
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.status-text.ok {
|
||||
|
||||
@@ -61,6 +61,11 @@
|
||||
--tag-green-bg: #E8FFEA;
|
||||
--tag-green-border: #9FD9A8;
|
||||
|
||||
/* 标签/徽章颜色 - 青色系 */
|
||||
--tag-cyan-text: #0FC6C2;
|
||||
--tag-cyan-bg: #E8FFFB;
|
||||
--tag-cyan-border: #87E8DE;
|
||||
|
||||
/* 节点单元格颜色 */
|
||||
--node-empty-bg: #F0F2F5;
|
||||
--node-a-bg: #E8FFEA;
|
||||
@@ -90,6 +95,7 @@
|
||||
--logo-ap-bg: #E8F3FF;
|
||||
--logo-qp-bg: #FFF7E6;
|
||||
--logo-gf-bg: #F5F7FA;
|
||||
--logo-ss-bg: #E8FFFB;
|
||||
|
||||
/* 发光/阴影效果 */
|
||||
--accent-glow: rgba(0, 180, 42, 0.3);
|
||||
@@ -158,6 +164,11 @@
|
||||
--tag-green-bg: #0F261D;
|
||||
--tag-green-border: var(--accent-dim);
|
||||
|
||||
/* 标签/徽章颜色 - 青色系 */
|
||||
--tag-cyan-text: #5CFFFF;
|
||||
--tag-cyan-bg: #0A2626;
|
||||
--tag-cyan-border: #1A5C5C;
|
||||
|
||||
/* 节点单元格颜色 */
|
||||
--node-empty-bg: #1E2532;
|
||||
--node-a-bg: #13261F;
|
||||
@@ -187,6 +198,7 @@
|
||||
--logo-ap-bg: #1C2A3A;
|
||||
--logo-qp-bg: #241B0A;
|
||||
--logo-gf-bg: #1B202B;
|
||||
--logo-ss-bg: #0A2626;
|
||||
|
||||
/* 发光/阴影效果 */
|
||||
--accent-glow: rgba(63, 224, 165, 0.3);
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
<div class="panel">
|
||||
<div class="panel-head">
|
||||
<h3>最近任务</h3>
|
||||
<router-link to="/tasks" class="meta">查看全部 →</router-link>
|
||||
<router-link to="/task/log" class="meta">查看全部 →</router-link>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table>
|
||||
|
||||
@@ -2,63 +2,129 @@
|
||||
<div>
|
||||
<div class="page-head">
|
||||
<div>
|
||||
<h1>告警</h1>
|
||||
<p>夜莺(Nightingale)统一告警引擎 · qpass 推送</p>
|
||||
<h1>告警信息</h1>
|
||||
<p>夜莺(Nightingale)统一告警引擎对接 Zabbix + VictoriaMetrics · qpass 推送</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cols-2-equal">
|
||||
<div class="panel">
|
||||
<div class="panel-head">
|
||||
<h3>当前告警</h3>
|
||||
<span class="meta">实时</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr class="tr-hover">
|
||||
<td>硬件告警</td>
|
||||
<td class="status-text warn">● 2 条</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td>业务告警</td>
|
||||
<td class="status-text ok">● 0 条</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td>今日已推送</td>
|
||||
<td class="mono strong">5</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<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 class="stat-card">
|
||||
<div class="label">今日已推送</div>
|
||||
<div class="value">5</div>
|
||||
<div class="delta">qpass 统一告警通道</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-head">
|
||||
<h3>告警通道</h3>
|
||||
<span class="meta">qpass</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr class="tr-hover">
|
||||
<td>推送状态</td>
|
||||
<td class="status-text ok">● 正常</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td>通道类型</td>
|
||||
<td>企业微信 · 钉钉 · 短信</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="panel">
|
||||
<div class="panel-head">
|
||||
<h3>告警来源接入 · 夜莺统一告警</h3>
|
||||
<span class="meta">Nightingale ← Zabbix / VictoriaMetrics</span>
|
||||
</div>
|
||||
<div class="panel-body" style="padding: 14px 16px">
|
||||
<div class="dc-row dc-row-3" style="margin-bottom: 0">
|
||||
<div class="dc-card dc-card-flat">
|
||||
<div class="dc-name">Zabbix <span class="dc-role">物理机 / 硬件层</span></div>
|
||||
<div class="dc-item">IPMI · 温度 · 电源 · 风扇</div>
|
||||
<div class="dc-item">网络设备 · 存储健康度</div>
|
||||
<div class="dc-item">事件级别:disaster / high / average</div>
|
||||
</div>
|
||||
<div class="dc-card dc-card-flat">
|
||||
<div class="dc-name">VictoriaMetrics <span class="dc-role">虚机 / 容器 / 业务层</span></div>
|
||||
<div class="dc-item">K8s / 容器 / 主机指标</div>
|
||||
<div class="dc-item">基础服务可用性探活</div>
|
||||
<div class="dc-item">告警级别:P0 / P1 / P2</div>
|
||||
</div>
|
||||
<div class="dc-card dc-card-flat">
|
||||
<div class="dc-name">夜莺 Nightingale <span class="dc-role">统一告警引擎</span></div>
|
||||
<div class="dc-item">按 P0/P1 或 disaster/high/average 过滤聚合</div>
|
||||
<div class="dc-item">去重 · 收敛 · 分级推送</div>
|
||||
<div class="dc-item">下游:qpass 统一告警通道</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-head">
|
||||
<h3>告警记录</h3>
|
||||
<span class="meta">近 24h</span>
|
||||
<h3>当前告警 · P0/P1(disaster / high / average)</h3>
|
||||
<span class="meta">夜莺聚合 · 已去重</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table>
|
||||
<tr>
|
||||
<th>级别</th>
|
||||
<th>来源</th>
|
||||
<th>原始级别</th>
|
||||
<th>对象</th>
|
||||
<th>告警内容</th>
|
||||
<th>时间</th>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td><span class="tag sev-p0">P0</span></td>
|
||||
<td class="mono">VictoriaMetrics</td>
|
||||
<td class="mono">disaster</td>
|
||||
<td class="strong mono">sg-las-overseas-007</td>
|
||||
<td>磁盘只读 / IO 错误,节点不可写</td>
|
||||
<td class="mono">07:38:55</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td><span class="tag sev-p1">P1</span></td>
|
||||
<td class="mono">Zabbix</td>
|
||||
<td class="mono">high</td>
|
||||
<td class="strong mono">yzh-las-014</td>
|
||||
<td>风扇转速低于阈值(FAN_6: 1920 RPM)</td>
|
||||
<td class="mono">07:35:12</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td><span class="tag sev-p1">P1</span></td>
|
||||
<td class="mono">Zabbix</td>
|
||||
<td class="mono">high</td>
|
||||
<td class="strong mono">xs-bm-291</td>
|
||||
<td>电源冗余丢失(PSU2 离线)</td>
|
||||
<td class="mono">07:21:40</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td><span class="tag sev-p1">P1</span></td>
|
||||
<td class="mono">VictoriaMetrics</td>
|
||||
<td class="mono">high</td>
|
||||
<td class="strong mono">redis-ads-feature-cluster-02</td>
|
||||
<td>慢查询比例超阈值(>5%,持续5分钟)</td>
|
||||
<td class="mono">07:18:03</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td><span class="tag sev-avg">average</span></td>
|
||||
<td class="mono">Zabbix</td>
|
||||
<td class="mono">average</td>
|
||||
<td class="strong mono">overseas-dallas-idc</td>
|
||||
<td>专线延迟抖动超基线(WireGuard ↔ AWS US)</td>
|
||||
<td class="mono">07:10:22</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td><span class="tag sev-avg">average</span></td>
|
||||
<td class="mono">Zabbix</td>
|
||||
<td class="mono">average</td>
|
||||
<td class="strong mono">jf-bm-118</td>
|
||||
<td>CPU 温度接近阈值(76℃ / 80℃)</td>
|
||||
<td class="mono">06:58:47</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-head">
|
||||
<h3>告警推送记录</h3>
|
||||
<span class="meta">近 24h · qpass</span>
|
||||
</div>
|
||||
<div class="panel-body log-stream">
|
||||
<div v-for="(alert, index) in alerts" :key="index" :class="['task-log-line', alert.class]">
|
||||
@@ -73,13 +139,72 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
const alerts = ref([
|
||||
{ time: '07:38:55', message: '[Zabbix] yzh-las-014 风扇转速低于阈值(FAN_6: 1920 RPM)', class: '' },
|
||||
{ time: '07:38:55', message: '[Zabbix] yzh-las-014 风扇转速低于阈值(FAN_5: 1880 RPM)', class: '' },
|
||||
{ time: '07:30:00', message: '[qpass] 告警已合并推送:1 条硬件告警 + 0 条业务告警', class: '' },
|
||||
{ time: '07:38:55', message: '[qpass] P0 告警推送:sg-las-overseas-007 磁盘只读 / IO 错误', class: 'err' },
|
||||
{ time: '07:35:12', message: '[qpass] P1 告警推送:yzh-las-014 风扇转速低于阈值(FAN_6: 1920 RPM)', class: '' },
|
||||
{ time: '07:21:40', message: '[qpass] P1 告警推送:xs-bm-291 电源冗余丢失(PSU2 离线)', class: '' },
|
||||
{ time: '07:18:03', message: '[qpass] P1 告警推送:redis-ads-feature-cluster-02 慢查询比例超阈值', class: '' },
|
||||
{ time: '07:10:22', message: '[qpass] average 告警推送:overseas-dallas-idc 专线延迟抖动超基线', class: '' },
|
||||
{ time: '06:58:47', message: '[qpass] average 告警推送:jf-bm-118 CPU 温度接近阈值(76℃ / 80℃)', class: '' },
|
||||
{ time: '06:15:22', message: '[Nightingale] sg-las-007 CPU 使用率恢复(当前 42%)', class: 'ok' },
|
||||
{ time: '05:48:10', message: '[Nightingale] sg-las-007 CPU 使用率超过 90% 持续 5 分钟', class: '' },
|
||||
])
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dc-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.dc-row-3 {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.dc-card {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
padding: 16px;
|
||||
background: var(--card-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.dc-card-flat {
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
.dc-name {
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.dc-role {
|
||||
font-size: 12px;
|
||||
color: var(--text-dim);
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.dc-item {
|
||||
font-size: 13px;
|
||||
color: var(--text-dim);
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.sev-p0 {
|
||||
background: var(--err) !important;
|
||||
color: #fff !important;
|
||||
border-color: var(--err) !important;
|
||||
}
|
||||
|
||||
.sev-p1 {
|
||||
background: var(--warn) !important;
|
||||
color: #000 !important;
|
||||
border-color: var(--warn) !important;
|
||||
}
|
||||
|
||||
.sev-avg {
|
||||
background: var(--card-bg) !important;
|
||||
color: var(--warn) !important;
|
||||
border-color: var(--warn) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,71 +2,196 @@
|
||||
<div>
|
||||
<div class="page-head">
|
||||
<div>
|
||||
<h1>监控</h1>
|
||||
<p>VictoriaMetrics 指标 · Zabbix 硬件状态</p>
|
||||
<h1>监控看板</h1>
|
||||
<p>物理机 / 虚机 / 基础服务状态汇总 · 夜莺(Nightingale)统一告警引擎对接 Zabbix + VictoriaMetrics · 最近更新于 18 秒前</p>
|
||||
</div>
|
||||
<button class="btn btn-ghost">⟳ 刷新</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>
|
||||
|
||||
<div class="cols-2-equal">
|
||||
<div class="cols-2">
|
||||
<div class="panel">
|
||||
<div class="panel-head">
|
||||
<h3>VictoriaMetrics · 指标概览</h3>
|
||||
<span class="meta">K8s / 容器 / 业务指标</span>
|
||||
<h3>物理机状态 · 按机房</h3>
|
||||
<span class="meta">数据源:Zabbix</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr class="tr-hover">
|
||||
<td>七机房采集节点数</td>
|
||||
<td class="mono strong">128</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td>活跃时序数量</td>
|
||||
<td class="mono strong">42.6M</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td>Prometheus 接口接入</td>
|
||||
<td class="status-text ok">● 正常</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td>Grafana 仪表盘数</td>
|
||||
<td class="mono strong">37</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<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>Zabbix · 硬件健康</h3>
|
||||
<span class="meta">IPMI / 温度 / 电源 / 风扇</span>
|
||||
<h3>虚机状态 · LAS 资源池</h3>
|
||||
<span class="meta">数据源:VictoriaMetrics</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr class="tr-hover">
|
||||
<td>物理机监控覆盖</td>
|
||||
<td class="mono strong">186 / 186</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td>当前告警</td>
|
||||
<td class="status-text warn">● 2 条(风扇转速异常)</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td>网络设备健康</td>
|
||||
<td class="status-text ok">● 正常</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td>存储健康度</td>
|
||||
<td class="status-text ok">● 正常</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<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 class="panel">
|
||||
<div class="panel-head">
|
||||
<h3>基础服务状态汇总</h3>
|
||||
<span class="meta">MySQL / Redis / 中间件 · 探活数据源:VictoriaMetrics</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">MySQL</td>
|
||||
<td class="mono">38</td>
|
||||
<td class="mono">0</td>
|
||||
<td class="mono">100%</td>
|
||||
<td class="status-text ok">● 正常</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td class="strong">Redis(CacheCloud)</td>
|
||||
<td class="mono">92</td>
|
||||
<td class="mono">1</td>
|
||||
<td class="mono">98.9%</td>
|
||||
<td class="status-text warn">● 1 条告警</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td class="strong">PostgreSQL</td>
|
||||
<td class="mono">12</td>
|
||||
<td class="mono">0</td>
|
||||
<td class="mono">100%</td>
|
||||
<td class="status-text ok">● 正常</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td class="strong">openresty 网关</td>
|
||||
<td class="mono">26</td>
|
||||
<td class="mono">0</td>
|
||||
<td class="mono">100%</td>
|
||||
<td class="status-text ok">● 正常</td>
|
||||
</tr>
|
||||
<tr class="tr-hover">
|
||||
<td class="strong">其他中间件</td>
|
||||
<td class="mono">46</td>
|
||||
<td class="mono">0</td>
|
||||
<td class="mono">100%</td>
|
||||
<td class="status-text ok">● 正常</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -74,5 +199,5 @@
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* .page-head, .cols-2-equal, .panel, table, .status-text 已在 global.css 中定义 */
|
||||
/* .page-head, .stat-row, .panel, .cols-2, .bar-wrap, .status-text, .tag 已在 global.css 中定义 */
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 基础服务目录 -->
|
||||
<div class="page-head">
|
||||
<div>
|
||||
<h1>基础服务目录</h1>
|
||||
@@ -9,7 +10,7 @@
|
||||
|
||||
<div class="svc-grid">
|
||||
<div
|
||||
v-for="service in services"
|
||||
v-for="service in basicServices"
|
||||
:key="service.name"
|
||||
class="svc-card"
|
||||
:class="{ disabled: service.disabled }"
|
||||
@@ -30,61 +31,38 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 弹窗:发布服务 · 跳 Wayne -->
|
||||
<Teleport to="body">
|
||||
<div v-if="showWayneModal" class="overlay" @click.self="showWayneModal = false">
|
||||
<div class="modal">
|
||||
<div class="modal-head">
|
||||
<h3>发布服务 · 跳 Wayne</h3>
|
||||
<button class="close" @click="showWayneModal = false">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="field-row">
|
||||
<div class="field">
|
||||
<label>业务线</label>
|
||||
<select v-model="wayneForm.bl">
|
||||
<option value="las">las(当前)</option>
|
||||
<option value="kodo">kodo</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>命名空间</label>
|
||||
<select v-model="wayneForm.namespace">
|
||||
<option value="ns-las-prod">ns-las-prod</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-row">
|
||||
<div class="field">
|
||||
<label>目标集群</label>
|
||||
<select v-model="wayneForm.cluster">
|
||||
<option value="rke2-sh-prod-01">rke2-sh-prod-01(华东)</option>
|
||||
<option value="rke2-bj-prod-01">rke2-bj-prod-01(华北)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>规格</label>
|
||||
<select v-model="wayneForm.spec">
|
||||
<option value="2C4G">2C 4G × 3 副本</option>
|
||||
<option value="4C8G">4C 8G × 3 副本</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>服务名称</label>
|
||||
<input v-model="wayneForm.serviceName" placeholder="las-search-api" />
|
||||
</div>
|
||||
<div class="tooltip-note">
|
||||
凭 SSO 身份免登进入 <b>Wayne</b>,在 ns-las-prod 下部署服务;权限随业务线 / 角色自动具备,仅可操作被授权 namespace。
|
||||
<!-- 容器服务部署 -->
|
||||
<div class="page-head" style="margin-top: 24px;">
|
||||
<div>
|
||||
<h1>容器服务部署</h1>
|
||||
<p>容器化服务统一管理与发布</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-head">
|
||||
<h3>统一入口</h3>
|
||||
<span class="meta">Wayne · LDAP 单点登录</span>
|
||||
</div>
|
||||
<div class="panel-body" style="padding: 16px;">
|
||||
<div class="ext-card" style="max-width: 560px;">
|
||||
<div class="ext-top">
|
||||
<div class="ext-logo" style="background: var(--logo-w-bg); color: var(--tag-blue-text);">W</div>
|
||||
<div>
|
||||
<h4>Wayne</h4>
|
||||
<div class="ext-sub">wayne.xinfra.internal</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-foot">
|
||||
<button class="btn btn-ghost" @click="showWayneModal = false">取消</button>
|
||||
<button class="btn btn-primary" @click="handleWayneSubmit">跳 Wayne 发布 ↗</button>
|
||||
<p>业务容器发布、命名空间与配额管理,复用 Wayne 原生多租户能力。所有集群的容器发布均可通过此入口统一操作。</p>
|
||||
<div class="sso-row">
|
||||
<span class="sso-dot"></span> LDAP 原生配置接入 · 在线
|
||||
</div>
|
||||
<button class="btn btn-primary" style="margin-top: 8px; align-self: flex-start;" @click="openWayne">
|
||||
打开 Wayne ↗
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
</div>
|
||||
|
||||
<!-- 弹窗:数据库标准化交付 · MySQL -->
|
||||
<Teleport to="body">
|
||||
@@ -153,6 +131,7 @@
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { subsystemApi } from '@/api/subsystem'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -170,17 +149,7 @@ interface Service {
|
||||
modal?: string
|
||||
}
|
||||
|
||||
const services = ref<Service[]>([
|
||||
{
|
||||
name: '容器服务(Wayne)',
|
||||
icon: 'Wy',
|
||||
bgColor: '#1C2A3A',
|
||||
iconColor: '#7FB8FF',
|
||||
description: '在 RKE2 容器池标准发布业务服务,跳 Wayne 免登管理多集群与命名空间。',
|
||||
playbook: 'wayne · ns-las-prod',
|
||||
version: '',
|
||||
modal: 'wayne',
|
||||
},
|
||||
const basicServices = ref<Service[]>([
|
||||
{
|
||||
name: 'MySQL',
|
||||
icon: 'My',
|
||||
@@ -238,17 +207,8 @@ const services = ref<Service[]>([
|
||||
])
|
||||
|
||||
// 弹窗状态
|
||||
const showWayneModal = ref(false)
|
||||
const showMysqlModal = ref(false)
|
||||
|
||||
const wayneForm = reactive({
|
||||
bl: 'las',
|
||||
namespace: 'ns-las-prod',
|
||||
cluster: 'rke2-sh-prod-01',
|
||||
spec: '2C4G',
|
||||
serviceName: 'las-search-api',
|
||||
})
|
||||
|
||||
const mysqlForm = reactive({
|
||||
bl: 'las',
|
||||
topology: '1m2r',
|
||||
@@ -264,7 +224,7 @@ const handleCardClick = (service: Service) => {
|
||||
return
|
||||
}
|
||||
if (service.modal === 'wayne') {
|
||||
showWayneModal.value = true
|
||||
openWayne()
|
||||
} else if (service.modal === 'mysql') {
|
||||
showMysqlModal.value = true
|
||||
} else if (service.modal === 'openresty') {
|
||||
@@ -272,16 +232,24 @@ const handleCardClick = (service: Service) => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleWayneSubmit = () => {
|
||||
showWayneModal.value = false
|
||||
ElMessage.success('已跳转 Wayne 并提交发布任务')
|
||||
router.push({ name: 'Tasks' })
|
||||
const openWayne = async () => {
|
||||
try {
|
||||
const wayne = subsystemApi.getSubsystemByName('wayne')
|
||||
if (!wayne) {
|
||||
ElMessage.error('Wayne 子系统未找到')
|
||||
return
|
||||
}
|
||||
const { data } = await subsystemApi.getSSOUrl(wayne.id)
|
||||
window.location.assign(data.sso_url)
|
||||
} catch {
|
||||
// 错误已由 request 拦截器统一处理
|
||||
}
|
||||
}
|
||||
|
||||
const handleMysqlSubmit = () => {
|
||||
showMysqlModal.value = false
|
||||
ElMessage.success('MySQL 标准化交付已提交,完成后自动注册 CloudDM')
|
||||
router.push({ name: 'Tasks' })
|
||||
router.push({ name: 'TaskLog' })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
<h1>{{ system.name }}</h1>
|
||||
<p>{{ system.description }} · {{ system.domain }}</p>
|
||||
</div>
|
||||
<span class="env-pill" :class="system.status === 'integrated' ? '' : 'warn'">
|
||||
{{ system.status === 'integrated' ? '● 已接入' : '● 接入中' }}
|
||||
<span class="env-pill" :class="system.status === 'active' ? '' : 'warn'">
|
||||
{{ system.status === 'active' ? '● 在线' : '● 接入中' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="stat-row">
|
||||
<div class="stat-card">
|
||||
<div class="label">接入状态</div>
|
||||
<div class="value" :class="system.status === 'integrated' ? 'accent' : 'warn'">
|
||||
{{ system.status === 'integrated' ? '已接入' : '接入中' }}
|
||||
<div class="value" :class="system.status === 'active' ? 'accent' : 'warn'">
|
||||
{{ system.status === 'active' ? '在线' : '接入中' }}
|
||||
</div>
|
||||
<div class="delta">{{ system.category }}</div>
|
||||
</div>
|
||||
@@ -50,11 +50,17 @@
|
||||
</div>
|
||||
<p>{{ detailDesc }}</p>
|
||||
<div class="sso-row">
|
||||
<span class="sso-dot" :class="{ warn: system.status === 'integrating' }"></span>
|
||||
{{ system.status === 'integrated' ? 'LDAP 原生配置接入 · 已上线' : 'LDAP 接入改造中' }}
|
||||
<span class="sso-dot" :class="{ warn: system.status !== 'active' }"></span>
|
||||
{{ system.status === 'active' ? 'LDAP 原生配置接入 · 在线' : 'LDAP 接入改造中' }}
|
||||
</div>
|
||||
<button class="btn btn-primary" style="margin-top:8px;align-self:flex-start;" @click="openPortal">
|
||||
打开 {{ system.name }} ↗
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
:class="{ 'btn-disabled': system.status !== 'active' }"
|
||||
:disabled="system.status !== 'active'"
|
||||
style="margin-top:8px;align-self:flex-start;"
|
||||
@click="openPortal"
|
||||
>
|
||||
{{ system.status !== 'active' ? '暂未开放' : '打开 ' + system.name + ' ↗' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -86,6 +92,7 @@ const bgColor = computed(() => {
|
||||
AP: 'var(--logo-ap-bg)',
|
||||
QP: 'var(--logo-qp-bg)',
|
||||
GF: 'var(--logo-gf-bg)',
|
||||
SS: 'var(--logo-ss-bg)',
|
||||
}
|
||||
return colors[system.value.icon] || 'var(--bg-panel-2)'
|
||||
})
|
||||
@@ -99,6 +106,7 @@ const iconColor = computed(() => {
|
||||
AP: 'var(--tag-blue-text)',
|
||||
QP: 'var(--tag-amber-text)',
|
||||
GF: 'var(--warn)',
|
||||
SS: 'var(--tag-cyan-text)',
|
||||
}
|
||||
return colors[system.value.icon] || 'var(--text-mid)'
|
||||
})
|
||||
@@ -112,6 +120,7 @@ const detailDesc = computed(() => {
|
||||
Apollo: '统一管理多机房 Config Service Cluster 的配置发布、灰度、回滚与变更审计,所有机房配置项均可在此单一入口检索与编辑。',
|
||||
qpass: '七牛云内部系统。',
|
||||
Grafana: '对接 VictoriaMetrics 数据源,K8s / 容器 / 业务指标统一仪表盘展示。预置核心看板,支持自定义。',
|
||||
Superset: '日志数据探索与可视化分析平台,支持多数据源接入和丰富的图表展示。用于日志数据分析和可视化报表。',
|
||||
}
|
||||
return descs[system.value.name] || system.value.description
|
||||
})
|
||||
@@ -167,4 +176,14 @@ const openPortal = async () => {
|
||||
.btn-primary:hover {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.btn-disabled {
|
||||
background: var(--text-dim);
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.btn-disabled:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user