增加登录器客户端心跳

This commit is contained in:
2026-06-22 12:03:58 +08:00
parent b0629b1001
commit b103192fac
7 changed files with 382 additions and 3 deletions
@@ -112,6 +112,9 @@ function sourceLabel(source: string) {
<el-descriptions-item label="创建时间">
{{ display(row.createdAt) }}
</el-descriptions-item>
<el-descriptions-item label="最后心跳时间">
{{ display(row.lastHeartbeatAt) }}
</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">
<span class="remark-text">{{ display(row.remark) }}</span>
</el-descriptions-item>
+43 -2
View File
@@ -97,8 +97,11 @@ const summary = computed(() => {
const inactive = tableData.value.filter((item) => item.status === 'inactive').length;
const disabled = tableData.value.filter((item) => item.status === 'disabled').length;
const expired = tableData.value.filter((item) => item.status === 'expired').length;
const online = tableData.value.filter((item) => item.isOnline).length;
const offline = tableData.value.length - online;
return [
{ label: '当前页设备', value: tableData.value.length, type: 'primary' },
{ label: '在线 / 离线', isOnlineOffline: true, online, offline },
{ label: '已激活设备', value: active, type: 'success' },
{ label: '未激活', value: inactive, type: 'info' },
{ label: '禁用/过期', value: disabled + expired, type: 'danger' },
@@ -186,6 +189,8 @@ function normalizeRow(raw: any): EquipmentRow {
lastExtractedAt: formatTime(pick(raw, 'last_extracted_at', 'lastExtractedAt', 'extracted_at')),
expiredAt: formatTime(pick(raw, 'expiredAt', 'expired_at', 'expireTime', 'expire_time')),
createdAt: formatTime(pick(raw, 'create_time', 'created_at', 'createdAt', 'CreatedAt')),
isOnline: !!pick(raw, 'isOnline', 'is_online'),
lastHeartbeatAt: formatTime(pick(raw, 'lastHeartbeatAt', 'last_heartbeat_at')),
lastLoginIp: pick(raw, 'lastLoginIp', 'last_login_ip') || '',
lastLoginIpInfo: raw?.lastLoginIpInfo ?? null,
remark: pick(raw, 'remark', 'Remark'),
@@ -463,7 +468,12 @@ onUnmounted(() => {
<div class="summary-grid">
<div v-for="item in summary" :key="item.label" class="summary-card">
<div class="summary-label">{{ item.label }}</div>
<div class="summary-value" :class="`is-${item.type}`">{{ item.value }}</div>
<div v-if="item.isOnlineOffline" class="summary-value combined-value">
<span class="is-online">{{ item.online }}</span>
<span class="divider">/</span>
<span class="is-offline">{{ item.offline }}</span>
</div>
<div v-else class="summary-value" :class="`is-${item.type}`">{{ item.value }}</div>
</div>
</div>
@@ -500,6 +510,13 @@ onUnmounted(() => {
>
<el-table-column type="selection" width="52" />
<el-table-column prop="id" label="ID" width="80" />
<el-table-column label="在线" width="90" align="center">
<template #default="{ row }">
<el-tag :type="row.isOnline ? 'success' : 'info'" effect="dark">
{{ row.isOnline ? '在线' : '离线' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="设备信息" min-width="220">
<template #default="{ row }">
<div class="device-name">{{ row.name || '-' }}</div>
@@ -633,7 +650,7 @@ onUnmounted(() => {
.summary-grid {
display: grid;
grid-template-columns: repeat(4, minmax(120px, 1fr));
grid-template-columns: repeat(5, minmax(120px, 1fr));
gap: 12px;
margin-bottom: 14px;
}
@@ -660,6 +677,10 @@ onUnmounted(() => {
color: #67c23a;
}
&.is-online {
color: #67c23a;
}
&.is-info {
color: #909399;
}
@@ -667,6 +688,26 @@ onUnmounted(() => {
&.is-danger {
color: #f56c6c;
}
&.combined-value {
display: flex;
align-items: center;
gap: 6px;
.is-online {
color: #67c23a;
}
.divider {
color: #dcdfe6;
font-weight: normal;
font-size: 18px;
}
.is-offline {
color: #909399;
}
}
}
.toolbar {