Files
WFL/templates/admin_db_index.html

370 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>База</title>
<style>
:root {
--bg: #0f1115;
--panel: #171a21;
--panel-2: #1d222b;
--border: #2b3240;
--text: #e8ecf3;
--muted: #9aa4b2;
--accent: #00c773;
--accent-hover: #00a861;
--success-bg: rgba(46, 204, 113, 0.12);
--success-border: rgba(46, 204, 113, 0.35);
--danger-bg: rgba(255, 99, 99, 0.12);
--danger-border: rgba(255, 99, 99, 0.35);
--shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
--radius: 16px;
}
* { box-sizing: border-box; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
font-family: Arial, sans-serif;
}
.page {
max-width: 1200px;
margin: 0 auto;
padding: 24px;
}
.panel {
background: var(--panel);
border: 1px solid var(--border);
border-radius: var(--radius);
box-shadow: var(--shadow);
padding: 20px;
}
.title {
font-size: 24px;
font-weight: 700;
margin-bottom: 18px;
}
.tabs,
.parser-actions {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.parser-actions {
margin-top: 18px;
padding-top: 18px;
border-top: 1px solid var(--border);
}
.tab-link,
.action-btn {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 42px;
padding: 0 16px;
border-radius: 999px;
background: var(--panel-2);
border: 1px solid var(--border);
color: var(--text);
text-decoration: none;
font-weight: 600;
cursor: pointer;
font-size: 14px;
}
.tab-link:hover,
.action-btn:hover {
background: var(--accent);
border-color: var(--accent);
color: white;
}
.action-form {
margin: 0;
}
.log-block {
margin-top: 20px;
border: 1px solid var(--border);
border-radius: 14px;
padding: 16px;
background: var(--panel-2);
}
.log-block.success {
background: var(--success-bg);
border-color: var(--success-border);
}
.log-block.error {
background: var(--danger-bg);
border-color: var(--danger-border);
}
.log-title {
font-size: 18px;
font-weight: 700;
margin-bottom: 10px;
}
.log-status {
color: var(--muted);
margin-bottom: 10px;
}
.log-output {
margin: 0;
white-space: pre-wrap;
word-break: break-word;
font-family: Consolas, Monaco, monospace;
font-size: 13px;
line-height: 1.5;
}
.action-form.is-loading .action-btn {
opacity: 0.75;
pointer-events: none;
}
.matrix-loader {
position: fixed;
inset: 0;
display: none;
align-items: center;
justify-content: center;
background: rgba(3, 8, 15, 0.94);
z-index: 9999;
overflow: hidden;
}
.matrix-loader.active {
display: flex;
}
.matrix-canvas {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.matrix-content {
position: relative;
z-index: 1;
width: min(90vw, 560px);
padding: 28px 24px;
border-radius: 18px;
border: 1px solid rgba(0, 255, 136, 0.30);
background: rgba(12, 17, 26, 0.88);
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
text-align: center;
backdrop-filter: blur(6px);
}
.matrix-title {
font-size: 28px;
font-weight: 700;
color: #dfffee;
margin-bottom: 12px;
}
.matrix-status {
font-size: 16px;
color: #9ff5c8;
line-height: 1.6;
}
</style>
</head>
<body>
<div class="page">
<div class="panel">
<div class="title">Редактирование базы</div>
<div class="tabs">
<a class="tab-link" href="/admin/db/players">Игроки</a>
<a class="tab-link" href="/admin/db/referees">Судьи</a>
<a class="tab-link" href="/admin/db/teams">Команды</a>
<a class="tab-link" href="/admin/db/coaches">Тренеры</a>
<a class="tab-link" href="/admin/db/stadiums">Стадионы</a>
<a class="tab-link" href="/admin/matches">Назад к матчам</a>
</div>
<div class="parser-actions">
<form method="post" action="/admin/db/run-parser" class="action-form" data-parser-title="Игроки" data-parser-status="Сбор и сохранение базы игроков...">
<input type="hidden" name="parser_name" value="players">
<button type="submit" class="action-btn">🗄️ Заграбить игроков</button>
</form>
<form method="post" action="/admin/db/run-parser" class="action-form" data-parser-title="Расписание" data-parser-status="Загрузка расписания матчей с сайта...">
<input type="hidden" name="parser_name" value="schedule">
<button type="submit" class="action-btn">🗄️ Заграбить расписание</button>
</form>
<form method="post" action="/admin/db/run-parser" class="action-form" data-parser-title="Турнирка" data-parser-status="Обновление турнирной таблицы...">
<input type="hidden" name="parser_name" value="standings">
<button type="submit" class="action-btn">🗄️ Заграбить турнирку</button>
</form>
</div>
<div class="section-card">
<div class="section-title">Создать аккаунт</div>
<form method="post" action="/admin/db/create-account" autocomplete="off">
<div class="account-form-grid">
<div>
<label class="field-label" for="username">Логин</label>
<input class="field-input" id="username" name="username" type="text" placeholder="Введите логин" required>
</div>
<div>
<label class="field-label" for="password">Пароль</label>
<input class="field-input" id="password" name="password" type="password" placeholder="Введите пароль" required>
</div>
<div>
<label class="field-label" for="role">Роль</label>
<select class="field-select" id="role" name="role">
<option value="operator">operator</option>
<option value="admin">admin</option>
</select>
</div>
</div>
<div class="account-actions">
<button type="submit" class="action-btn"> Создать аккаунт</button>
</div>
</form>
</div>
{% if parser_output %}
<div class="log-block {% if parser_success %}success{% else %}error{% endif %}">
<div class="log-title">Итог парсинга{% if parser_name %}: {{ parser_name }}{% endif %}</div>
<div class="log-status">
Статус:
{% if parser_success %}
успешно
{% else %}
ошибка
{% endif %}
</div>
<pre class="log-output">{{ parser_output }}</pre>
</div>
{% endif %}
{% if account_output %}
<div class="log-block {% if account_success %}success{% else %}error{% endif %}">
<div class="log-title">Создание аккаунта</div>
<div class="log-status">
Статус:
{% if account_success %}
успешно
{% else %}
ошибка
{% endif %}
</div>
<pre class="log-output">{{ account_output }}</pre>
</div>
{% endif %}
</div>
</div>
<div id="matrixLoader" class="matrix-loader" aria-hidden="true">
<canvas id="matrixCanvas" class="matrix-canvas"></canvas>
<div class="matrix-content">
<div class="matrix-title" id="matrixTitle">Запуск парсера</div>
<div class="matrix-status" id="matrixStatusText">Подготовка...</div>
</div>
</div>
<script>
const loader = document.getElementById("matrixLoader");
const titleEl = document.getElementById("matrixTitle");
const statusText = document.getElementById("matrixStatusText");
const canvas = document.getElementById("matrixCanvas");
const ctx = canvas ? canvas.getContext("2d") : null;
const parserForms = document.querySelectorAll(".action-form");
let drops = [];
let speeds = [];
let fontSize = 18;
let columns = 0;
let matrixAnimationId = null;
let lastFrameAt = 0;
const frameDelay = 75;
const chars = "01アイウエオカキクケコサシスセソタチツテトABCDEFGHIJKLMNOPQRSTUVWXYZ";
function resizeCanvas() {
if (!canvas || !ctx) return;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
columns = Math.max(1, Math.floor(canvas.width / fontSize));
drops = Array.from({ length: columns }, () => Math.random() * canvas.height / fontSize);
speeds = Array.from({ length: columns }, () => 0.45 + Math.random() * 0.35);
}
function drawMatrixFrame() {
if (!canvas || !ctx) return;
ctx.fillStyle = "rgba(3, 8, 15, 0.08)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#00ff88";
ctx.font = `${fontSize}px monospace`;
for (let i = 0; i < drops.length; i++) {
const text = chars[Math.floor(Math.random() * chars.length)];
const x = i * fontSize;
const y = drops[i] * fontSize;
ctx.fillText(text, x, y);
if (y > canvas.height && Math.random() > 0.985) {
drops[i] = 0;
speeds[i] = 0.45 + Math.random() * 0.35;
}
drops[i] += speeds[i];
}
}
function animateMatrix(timestamp = 0) {
if (!matrixAnimationId) return;
if (!lastFrameAt || timestamp - lastFrameAt >= frameDelay) {
drawMatrixFrame();
lastFrameAt = timestamp;
}
matrixAnimationId = requestAnimationFrame(animateMatrix);
}
function startLoader(title, message) {
if (!loader) return;
titleEl.textContent = title;
statusText.textContent = message;
loader.classList.add("active");
loader.setAttribute("aria-hidden", "false");
if (!matrixAnimationId) {
resizeCanvas();
lastFrameAt = 0;
matrixAnimationId = requestAnimationFrame(animateMatrix);
}
}
parserForms.forEach((form) => {
form.addEventListener("submit", () => {
const parserTitle = form.dataset.parserTitle || "Запуск парсера";
const parserStatus = form.dataset.parserStatus || "Обработка данных...";
document.querySelectorAll(".action-btn").forEach((btn) => {
btn.disabled = true;
});
form.classList.add("is-loading");
startLoader(`Парсинг: ${parserTitle}`, parserStatus);
});
});
resizeCanvas();
window.addEventListener("resize", resizeCanvas);
</script>
</body>
</html>