This commit is contained in:
2026-06-19 19:08:44 +08:00
parent 01b0ad1999
commit 3fbc52c6c1
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { getAdminMqttStatus, getAdminRuntimeSettings, updateAdminRuntimeSettings } from '../api'
import type { AdminMqttStatus, AdminRuntimeSettings } from '../types'
import type { AdminMqttClient, AdminMqttStatus, AdminRuntimeSettings } from '../types'
const status = ref<AdminMqttStatus | null>(null)
const runtimeSettings = ref<AdminRuntimeSettings | null>(null)
@@ -12,6 +12,41 @@ const settingsError = ref('')
const settingsMessage = ref('')
let timer: number | undefined
type ClientSortKey = 'client_id' | 'username' | 'listener' | 'remote_addr' | 'packets_in' | 'packets_out'
type SortDir = 'asc' | 'desc'
const clientSortKey = ref<ClientSortKey>('client_id')
const clientSortDir = ref<SortDir>('asc')
function toggleClientSort(key: ClientSortKey) {
if (clientSortKey.value === key) {
clientSortDir.value = clientSortDir.value === 'asc' ? 'desc' : 'asc'
} else {
clientSortKey.value = key
clientSortDir.value = 'asc'
}
}
const sortedClients = computed<AdminMqttClient[]>(() => {
const list = status.value?.clients ? [...status.value.clients] : []
const key = clientSortKey.value
const dir = clientSortDir.value === 'asc' ? 1 : -1
list.sort((a, b) => {
const av = a[key]
const bv = b[key]
if (typeof av === 'number' && typeof bv === 'number') {
return (av - bv) * dir
}
return String(av ?? '').localeCompare(String(bv ?? '')) * dir
})
return list
})
function sortIndicator(key: ClientSortKey): string {
if (clientSortKey.value !== key) return ''
return clientSortDir.value === 'asc' ? '▲' : '▼'
}
function formatUptime(seconds: number): string {
const hours = Math.floor(seconds / 3600)
const minutes = Math.floor((seconds % 3600) / 60)
@@ -158,16 +193,16 @@ onBeforeUnmount(() => {
<table class="node-table">
<thead>
<tr>
<th>Client ID</th>
<th>Username</th>
<th>Listener</th>
<th>Remote Addr</th>
<th>客户端服务器</th>
<th>服务器客户端</th>
<th class="sortable" @click="toggleClientSort('client_id')">Client ID <span class="sort-indicator">{{ sortIndicator('client_id') }}</span></th>
<th class="sortable" @click="toggleClientSort('username')">Username <span class="sort-indicator">{{ sortIndicator('username') }}</span></th>
<th class="sortable" @click="toggleClientSort('listener')">Listener <span class="sort-indicator">{{ sortIndicator('listener') }}</span></th>
<th class="sortable" @click="toggleClientSort('remote_addr')">Remote Addr <span class="sort-indicator">{{ sortIndicator('remote_addr') }}</span></th>
<th class="sortable" @click="toggleClientSort('packets_in')">客户端服务器 <span class="sort-indicator">{{ sortIndicator('packets_in') }}</span></th>
<th class="sortable" @click="toggleClientSort('packets_out')">服务器客户端 <span class="sort-indicator">{{ sortIndicator('packets_out') }}</span></th>
</tr>
</thead>
<tbody>
<tr v-for="client in status?.clients || []" :key="client.client_id">
<tr v-for="client in sortedClients" :key="client.client_id">
<td>{{ client.client_id || '-' }}</td>
<td>{{ client.username || '-' }}</td>
<td>{{ client.listener || '-' }}</td>
@@ -352,4 +387,20 @@ onBeforeUnmount(() => {
gap: 0.75rem;
}
}
.node-table th.sortable {
cursor: pointer;
user-select: none;
}
.node-table th.sortable:hover {
color: var(--color-primary);
}
.node-table th.sortable .sort-indicator {
display: inline-block;
margin-left: 4px;
font-size: 11px;
color: var(--color-primary);
}
</style>