diff --git a/src/components/NodesStatus.vue b/src/components/NodesStatus.vue index d4d37be..a5e4839 100644 --- a/src/components/NodesStatus.vue +++ b/src/components/NodesStatus.vue @@ -32,12 +32,13 @@
{{ host.name }} - + import { ref, computed, onMounted } from 'vue' import { Wifi, RefreshCw } from '@lucide/vue' -import { getAllCountries } from '@tw-labs/countries' const hosts = ref([]) const loading = ref(true) const error = ref(null) -const countriesList = getAllCountries() - -// Ручной маппинг для проблемных стран -const countryOverrides = { - 'United States': 'us', - 'USA': 'us', - 'U.S.A.': 'us', - 'America': 'us', - 'United Arab Emirates': 'ae', - 'UAE': 'ae', -} - -const findCountryByFirstWord = (name) => { - if (!name) return null - - // 1. Проверяем ручные override - const override = countryOverrides[name] - if (override) { - return { code: override.toUpperCase() } - } - - // 2. Ищем по первому слову - const firstWord = name.split(' ')[0] - if (!firstWord) return null - - // Точное совпадение - const exact = countriesList.find(c => - c.label.toLowerCase() === firstWord.toLowerCase() - ) - if (exact) return exact - - // Частичное совпадение - const partial = countriesList.find(c => - firstWord.toLowerCase().includes(c.label.toLowerCase()) || - c.label.toLowerCase().includes(firstWord.toLowerCase()) - ) - if (partial) return partial - - // 3. Пробуем найти по полному имени - const fullMatch = countriesList.find(c => - name.toLowerCase().includes(c.label.toLowerCase()) || - c.label.toLowerCase().includes(name.toLowerCase()) - ) - return fullMatch || null -} - const sortedHosts = computed(() => { return [...hosts.value].sort((a, b) => { if (a.ping === null && b.ping === null) return 0 @@ -157,17 +111,14 @@ const fetchHosts = async () => { if (!res.ok) throw new Error() const data = await res.json() - hosts.value = data.map((h) => { - const country = findCountryByFirstWord(h.name) - return { - ...h, - countryCode: country?.code?.toLowerCase() || null, - isOnline: true, - ping: null, - } - }) + hosts.value = data.map((h) => ({ + ...h, + countryCode: h.country_code ? h.country_code.toLowerCase() : null, + isOnline: true, + ping: null, + })) } catch { - error.value = 'Ошибка загрузки' + error.value = 'Ошибка загрузки данных' } finally { loading.value = false } @@ -182,32 +133,28 @@ const refreshData = async () => { if (!res.ok) throw new Error() const data = await res.json() - hosts.value = data.map((h) => { - const country = findCountryByFirstWord(h.name) - return { - ...h, - countryCode: country?.code?.toLowerCase() || null, - isOnline: true, - ping: null, - } - }) + hosts.value = data.map((h) => ({ + ...h, + countryCode: h.country_code ? h.country_code.toLowerCase() : null, + isOnline: true, + ping: null, + })) + // Пингуем все хосты параллельно const pings = await Promise.all(hosts.value.map(h => pingHost(h))) hosts.value.forEach((h, i) => { - if (h.isOnline) h.ping = pings[i] + h.ping = pings[i] }) } catch { - error.value = 'Ошибка обновления' + error.value = 'Ошибка обновления данных' } finally { loading.value = false } } -// При первом открытии — загружаем и пингуем onMounted(async () => { await fetchHosts() - // Автоматический пинг только при первом открытии await refreshData() }) \ No newline at end of file