feat: host display_name в ingest, поиск хостов, UI и docs

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
PTah
2026-05-28 11:49:10 +10:00
parent 108e1756c4
commit d4bf6e536c
8 changed files with 122 additions and 11 deletions
+21 -3
View File
@@ -1,5 +1,12 @@
<template>
<h1>Хосты</h1>
<div class="filters">
<label>
Поиск (hostname / display name)
<input v-model="search" type="search" placeholder="UNMS Kalina" @keyup.enter="loadHosts" />
</label>
<button type="button" class="secondary" @click="loadHosts">Найти</button>
</div>
<p v-if="error" class="error">{{ error }}</p>
<p v-else-if="loading">Загрузка</p>
<template v-else>
@@ -8,6 +15,7 @@
<thead>
<tr>
<th>ID</th>
<th>Имя</th>
<th>Hostname</th>
<th>Product</th>
<th>OS</th>
@@ -22,7 +30,8 @@
<tbody>
<tr v-for="h in data?.items ?? []" :key="h.id">
<td>{{ h.id }}</td>
<td>{{ h.display_name || h.hostname }}</td>
<td>{{ h.display_name || "—" }}</td>
<td>{{ h.hostname }}</td>
<td>{{ h.product }} {{ h.product_version || "" }}</td>
<td>{{ h.os_family }}</td>
<td>{{ h.ipv4 || "—" }}</td>
@@ -52,6 +61,7 @@ import { apiFetch, type HostListResponse } from "../api";
const data = ref<HostListResponse | null>(null);
const loading = ref(false);
const error = ref("");
const search = ref("");
function formatDt(iso: string) {
return new Date(iso).toLocaleString("ru-RU");
@@ -63,14 +73,22 @@ function agentLabel(status: string) {
return "unknown";
}
onMounted(async () => {
async function loadHosts() {
loading.value = true;
error.value = "";
try {
data.value = await apiFetch<HostListResponse>("/api/v1/hosts?page=1&page_size=100");
const q = search.value.trim();
const params = new URLSearchParams({ page: "1", page_size: "100" });
if (q) params.set("hostname", q);
data.value = await apiFetch<HostListResponse>(`/api/v1/hosts?${params}`);
} catch (e) {
error.value = e instanceof Error ? e.message : "Ошибка";
} finally {
loading.value = false;
}
}
onMounted(() => {
loadHosts();
});
</script>