Files
xinfra/frontend/src/views/cluster/ClusterList.vue
T

172 lines
5.5 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>统一建设容器池 · RKE2 上建 Wayne 后新服务的标准发布流程 · 数据源:Wayne 原生接口</p>
</div>
<el-button type="primary" :loading="loading" @click="loadClusters">同步</el-button>
</div>
<div class="panel">
<div class="panel-body">
<div v-if="error" class="error-line">{{ error }}</div>
<table v-loading="loading">
<thead>
<tr>
<th>集群</th>
<th>机房 / 区域</th>
<th>状态</th>
<th>节点</th>
<th>CPU 使用</th>
<th>RKE2 版本</th>
<th>Calico</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-if="!businessLineClusters.length">
<td colspan="8" class="text-dim">当前业务线暂无 Wayne 集群数据</td>
</tr>
<tr
v-for="cluster in businessLineClusters"
:key="cluster.name"
:class="['tr-hover', { selected: cluster.name === selectedCluster }]"
@click="selectedCluster = cluster.name"
>
<td class="strong">{{ cluster.name }}</td>
<td><span class="tag" :class="cluster.zoneClass">{{ cluster.zone }}</span></td>
<td :class="['status-text', cluster.statusClass]">● {{ cluster.status }}</td>
<td class="mono">{{ cluster.nodes }}</td>
<td>
<span class="bar-wrap"><span class="bar-fill" :class="cluster.cpuClass" :style="{ width: cluster.cpu + '%' }"></span></span>{{ cluster.cpu }}%
</td>
<td class="mono">{{ cluster.version }}</td>
<td class="mono">{{ cluster.calico }}</td>
<td><el-button text>详情</el-button></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="panel">
<div class="panel-head">
<h3>{{ selectedCluster || businessLineClusters[0]?.name || '未选择集群' }} · 节点列表</h3>
<span class="meta">node-label 多租户隔离</span>
</div>
<div class="panel-body">
<table v-loading="loading">
<thead>
<tr>
<th>节点</th>
<th>IP</th>
<th>业务线标签</th>
<th>污点 Taint</th>
<th>规格</th>
<th>CPU / Mem</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<tr v-if="!businessLineNodes.length">
<td colspan="7" class="text-dim">当前集群暂无 Wayne 节点数据</td>
</tr>
<tr v-for="node in businessLineNodes" :key="node.name" class="tr-hover">
<td class="strong mono">{{ node.name }}</td>
<td class="mono">{{ node.ip }}</td>
<td><span class="tag biz">{{ node.label }}</span></td>
<td class="mono text-xs">{{ node.taint }}</td>
<td class="mono">{{ node.spec }}</td>
<td>
<template v-if="node.cpu > 0">
<span class="bar-wrap"><span class="bar-fill" :class="node.cpuClass" :style="{ width: node.cpu + '%' }"></span></span>{{ node.cpu }}%
</template>
<span v-else class="text-dim">-</span>
</td>
<td :class="['status-text', node.statusClass]">● {{ node.status }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { containerServiceApi, type ContainerCluster, type ContainerNode } from '@/api/containerService'
import { useBusinessLineStore } from '@/stores/businessLine'
const businessLineStore = useBusinessLineStore()
const clusters = ref<ContainerCluster[]>([])
const nodes = ref<ContainerNode[]>([])
const selectedCluster = ref('')
const loading = ref(false)
const error = ref('')
const businessLineClusters = computed(() => clusters.value)
const businessLineNodes = computed(() => {
if (!selectedCluster.value) return []
return nodes.value.filter((node) => node.cluster === selectedCluster.value)
})
async function loadClusters() {
const businessLineId = businessLineStore.current?.id
if (!businessLineId) {
clusters.value = []
nodes.value = []
selectedCluster.value = ''
return
}
loading.value = true
error.value = ''
try {
const data = await containerServiceApi.listClusters(businessLineId)
clusters.value = data.items
nodes.value = data.nodes
if (!clusters.value.some((cluster) => cluster.name === selectedCluster.value)) {
selectedCluster.value = clusters.value[0]?.name || ''
}
if (data.summary.errors?.length) {
error.value = data.summary.errors.join(';')
}
} catch (err) {
error.value = err instanceof Error ? err.message : 'Wayne 集群数据同步失败'
clusters.value = []
nodes.value = []
selectedCluster.value = ''
} finally {
loading.value = false
}
}
watch(
() => businessLineStore.current?.id,
() => {
void loadClusters()
},
)
onMounted(loadClusters)
</script>
<style scoped>
/* 公共样式已在 global.css 中定义 */
.tr-hover.selected {
background: rgba(22, 93, 255, 0.08);
}
.error-line {
margin-bottom: 12px;
color: var(--danger);
font-size: 13px;
}
.tag.biz {
color: var(--text-mid);
}
</style>