/
Ged52
/
DomainInfo
Обзор
Документация
Войти
/
Ged52
/
DomainInfo
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
templates/summary.html
300 строк
12 KB
Oleg Korshunov
+ страничка с отчетом
13 июл 2026, 14:02
13 июл 2026, 14:02
8c4e826
Код
Авторство
О чём код?
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Domain Info - Сводка</title> <link rel="stylesheet" href="/static/style.css"> <link rel="stylesheet" href="/static/login.css"> </head> <body> {% include "includes/header.html" %} <section id="status" class="status hidden"></section> <section class="results-section"> <div class="results-header"> <h2>Сводка по доменам</h2> </div> <div class="summary-grid"> <div class="summary-card"> <h3>Всего доменов</h3> <p id="total-domains" class="summary-value">0</p> </div> <div class="summary-card"> <h3>Истекшие</h3> <p id="expired-domains" class="summary-value warning">0</p> </div> <div class="summary-card"> <h3>Срок истекает в ближ. 30 дней</h3> <p id="soon-expiring" class="summary-value caution">0</p> </div> <div class="summary-card"> <h3>Срок истекает в ближ. 90 дней</h3> <p id="medium-expiry" class="summary-value caution">0</p> </div> <div class="summary-card"> <h3>Неизвестный срок</h3> <p id="unknown-expiry" class="summary-value">0</p> </div> <div class="summary-card"> <h3>Сервисы</h3> <p id="services-count" class="summary-value">0</p> </div> </div> <div class="summary-section"> <h3>Топ-10 по сроку действия</h3> <div class="table-wrap"> <table id="summary-table"> <thead> <tr> <th>Домен</th> <th>Окончание</th> <th>Осталось</th> <th>Регистратор</th> <th>Группа</th> </tr> </thead> <tbody id="summary-body"> <tr class="empty-row"><td colspan="5">Загрузка...</td></tr> </tbody> </table> </div> </div> <div class="summary-section"> <h3>Статистика по доменам</h3> <div class="table-wrap"> <table id="stats-table"> <thead> <tr> <th>Поле</th> <th>Количество</th> </tr> </thead> <tbody id="stats-body"> <tr class="empty-row"><td colspan="2">Загрузка...</td></tr> </tbody> </table> </div> </div> </section> <script> const logoutBtn = document.getElementById("logout-btn"); const totalDomainsEl = document.getElementById("total-domains"); const expiredDomainsEl = document.getElementById("expired-domains"); const soonExpiringEl = document.getElementById("soon-expiring"); const mediumExpiryEl = document.getElementById("medium-expiry"); const unknownExpiryEl = document.getElementById("unknown-expiry"); const servicesCountEl = document.getElementById("services-count"); const summaryBody = document.getElementById("summary-body"); const statsBody = document.getElementById("stats-body"); const statusEl = document.getElementById("status"); let domains = []; function showStatus(message, type = "info") { statusEl.textContent = message; statusEl.className = `status ${type}`; statusEl.classList.remove("hidden"); } function hideStatus() { statusEl.classList.add("hidden"); } function daysBadge(days) { if (days === null || days === undefined) return '<span class="badge unknown">—</span>'; if (days < 0) return `<span class="badge expired"> истёк ${Math.abs(days)} дн.</span>`; if (days <= 30) return `<span class="badge warning">${days} дн.</span>`; if (days <= 90) return `<span class="badge caution">${days} дн.</span>`; return `<span class="badge ok">${days} дн.</span>`; } function escapeHtml(text) { const div = document.createElement("div"); div.textContent = text ?? ""; return div.innerHTML; } function truncate(text, max = 28) { const value = (text || "").trim(); if (!value) return "—"; if (value.length <= max) return escapeHtml(value); return `<span title="${escapeHtml(value)}">${escapeHtml(value.slice(0, max))}…</span>`; } async function loadSummary() { try { const response = await fetch("/api/domains", { credentials: "include" }); console.log("loadSummary response status:", response.status); if (!response.ok) { const errorText = await response.text(); console.error("loadSummary response error:", response.statusText, errorText); showStatus("Не удалось загрузить домены: " + response.statusText + " " + errorText, "error"); return; } const data = await response.json(); console.log("loadSummary data keys:", Object.keys(data)); console.log("data.count:", data.count); console.log("data.results:", data.results); console.log("data.results length:", data.results ? data.results.length : "null"); domains = data.results || []; console.log("Loaded domains:", domains.length, "domains"); console.log("domains type:", Array.isArray(domains) ? "array" : typeof domains); if (data.count !== domains.length) { console.warn("data.count", data.count, "!= domains.length", domains.length); } if (!Array.isArray(domains)) { console.error("domains is not an array!"); domains = []; } console.log("About to call renderSummary with", domains.length, "domains"); renderSummary(); } catch (e) { console.error("loadSummary error:", e); showStatus("Ошибка при загрузке данных", "error"); } } function renderSummary() { console.log("renderSummary called with", domains.length, "domains"); if (!domains.length) { console.log("No domains, showing empty state"); totalDomainsEl.textContent = "0"; expiredDomainsEl.textContent = "0"; soonExpiringEl.textContent = "0"; mediumExpiryEl.textContent = "0"; unknownExpiryEl.textContent = "0"; servicesCountEl.textContent = "0"; summaryBody.innerHTML = '<tr class="empty-row"><td colspan="5">Список пуст</td></tr>'; renderStats(); return; } console.log("Sample domain:", domains[0]); console.log("days_left types:", domains.map(d => typeof d.days_left)); const total = domains.length; const expired = domains.filter(d => d.days_left !== null && d.days_left < 0).length; const soon = domains.filter(d => d.days_left !== null && d.days_left >= 0 && d.days_left <= 30).length; const medium = domains.filter(d => d.days_left !== null && d.days_left > 30 && d.days_left <= 90).length; const unknown = domains.filter(d => d.days_left === null || d.days_left === undefined).length; const services = new Set(domains.map(d => d.hoster).filter(Boolean)).size; console.log("total:", total, "expired:", expired, "soon:", soon, "medium:", medium, "unknown:", unknown, "services:", services); console.log("group values:", domains.map(d => d.group)); console.log("hoster values:", domains.map(d => d.hoster)); console.log("responsible values:", domains.map(d => d.responsible)); console.log("organization values:", domains.map(d => d.organization)); console.log("login values:", domains.map(d => d.login)); console.log("esia_verified values:", domains.map(d => d.esia_verified)); console.log("expiry values:", domains.map(d => d.expiry)); console.log("dns_provider values:", domains.map(d => d.dns_provider)); console.log("registrar values:", domains.map(d => d.registrar)); console.log("Calling renderStats..."); totalDomainsEl.textContent = total; expiredDomainsEl.textContent = expired; soonExpiringEl.textContent = soon; mediumExpiryEl.textContent = medium; unknownExpiryEl.textContent = unknown; servicesCountEl.textContent = services; const sorted = [...domains].sort((a, b) => { const aDays = a.days_left ?? 9999; const bDays = b.days_left ?? 9999; return aDays - bDays; }).slice(0, 10); console.log("Top 10 sorted domains:", sorted); summaryBody.innerHTML = sorted.map(row => ` <tr> <td class="domain"><a href="https://${escapeHtml(row.domain)}" target="_blank">${escapeHtml(row.domain)}</a></td> <td>${escapeHtml(row.expiry || "—")}</td> <td>${daysBadge(row.days_left)}</td> <td>${truncate(row.registrar || "—")}</td> <td>${truncate(row.group || "—")}</td> </tr> `).join(""); console.log("Calling renderStats..."); renderStats(); } function renderStats() { console.log("renderStats called"); console.log("domains[0]:", domains[0]); console.log("dns_provider values:", domains.map(d => d.dns_provider)); console.log("registrar values:", domains.map(d => d.registrar)); console.log("hoster values:", domains.map(d => d.hoster)); console.log("group values:", domains.map(d => d.group)); console.log("responsible values:", domains.map(d => d.responsible)); console.log("organization values:", domains.map(d => d.organization)); console.log("login values:", domains.map(d => d.login)); console.log("esia_verified values:", domains.map(d => d.esia_verified)); console.log("expiry values:", domains.map(d => d.expiry)); const stats = { "С DNS провайдером": domains.filter(d => d.dns_provider && d.dns_provider !== "—").length, "Без DNS провайдера": domains.filter(d => !d.dns_provider || d.dns_provider === "—").length, "С Registrar": domains.filter(d => d.registrar && d.registrar !== "—").length, "Без Registrar": domains.filter(d => !d.registrar || d.registrar === "—").length, "С ЕСИА": domains.filter(d => d.esia_verified === 1).length, "Без ЕСИА": domains.filter(d => d.esia_verified !== 1).length, "С Группой": domains.filter(d => d.group && d.group !== "—").length, "Без Группы": domains.filter(d => !d.group || d.group === "—").length, "С Ответственным": domains.filter(d => d.responsible && d.responsible !== "—").length, "С Организацией": domains.filter(d => d.organization && d.organization !== "—").length, "С Хостером": domains.filter(d => d.hoster && d.hoster !== "—").length, "С Логином": domains.filter(d => d.login && d.login !== "—").length, }; console.log("Stats:", stats); statsBody.innerHTML = Object.entries(stats).map(([key, value]) => ` <tr> <td>${key}</td> <td>${value}</td> </tr> `).join(""); } async function checkAuth() { console.log("checkAuth called"); const response = await fetch("/api/auth/check", { credentials: "include" }); console.log("checkAuth response status:", response.status); if (response.status === 401) { console.log("checkAuth unauthorized, redirecting to /"); window.location.href = "/"; return; } const data = await response.json(); console.log("checkAuth data:", data); console.log("user:", data.user); document.getElementById("user-info").textContent = data.user.username + " (" + (data.user.role === "admin" ? "Админ" : "Пользователь") + ")"; } loadSummary(); checkAuth(); if (logoutBtn) { logoutBtn.addEventListener("click", async () => { try { const response = await fetch("/api/auth/logout", { method: "POST", credentials: "include" }); if (!response.ok) console.error("Logout failed:", response.statusText); } catch (e) { console.error("Logout failed:", e); } setTimeout(() => { window.location.href = "/"; }, 100); }); } </script> {% include "includes/footer.html" %} </body> </html>