✅ Проведено полное тестирование функционала: - Меню жильца (11 кнопок) - Меню админа (17 кнопок) - База данных (проверка записей) - Уникальность callback_data - Сообщения в личку (без спама) 📝 Созданные файлы: - tests/run_tests.py — автотесты - tests/TEST_REPORT.md — отчёт о тестировании - tests/COMPREHENSIVE_TEST_PLAN.md — план тестов - send_test_report.py — отправка отчёта 📊 Результаты: - Все кнопки работают - Участковский работает через БД (2 записи) - Сообщения только в личку - Веб-админка работает со всеми разделами 🎯 ВСЁ РАБОТАЕТ! Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
89 lines
5.4 KiB
HTML
89 lines
5.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Рассылки - Домовой Бот</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
|
|
<style>
|
|
.sidebar { min-height: 100vh; background: linear-gradient(180deg, #2c3e50 0%, #1a252f 100%); }
|
|
.sidebar .nav-link { color: rgba(255,255,255,0.8); padding: 1rem; }
|
|
.sidebar .nav-link:hover, .sidebar .nav-link.active { color: white; background-color: rgba(255,255,255,0.1); }
|
|
.content { padding: 2rem; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container-fluid">
|
|
<div class="row">
|
|
<div class="col-md-2 sidebar p-0">
|
|
<div class="p-3 text-white text-center"><h4><i class="bi bi-house-door"></i> Домовой Бот</h4></div>
|
|
<nav class="nav flex-column">
|
|
<a class="nav-link" href="/"><i class="bi bi-speedometer2"></i> Дашборд</a>
|
|
<a class="nav-link" href="/users"><i class="bi bi-people"></i> Пользователи</a>
|
|
<a class="nav-link" href="/verification"><i class="bi bi-shield-check"></i> Верификация</a>
|
|
<a class="nav-link" href="/phones"><i class="bi bi-telephone"></i> Телефоны</a>
|
|
<a class="nav-link" href="/ads"><i class="bi bi-megaphone"></i> Объявления</a>
|
|
<a class="nav-link active" href="/broadcast"><i class="bi bi-broadcast"></i> Рассылки</a>
|
|
<a class="nav-link" href="/polls"><i class="bi bi-bar-chart"></i> Опросы</a>
|
|
<a class="nav-link" href="/events"><i class="bi bi-calendar-event"></i> События</a>
|
|
<a class="nav-link" href="/schedules"><i class="bi bi-clock"></i> Расписания</a>
|
|
<a class="nav-link" href="/export"><i class="bi bi-download"></i> Экспорт</a>
|
|
<a class="nav-link" href="/settings"><i class="bi bi-gear"></i> Настройки</a>
|
|
</nav>
|
|
</div>
|
|
<div class="col-md-10 content">
|
|
<h2 class="mb-4"><i class="bi bi-broadcast"></i> Рассылки сообщений</h2>
|
|
|
|
<div class="card">
|
|
<div class="card-header bg-primary text-white">
|
|
<h5 class="mb-0"><i class="bi bi-send"></i> Отправить рассылку</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<label class="form-label">Кому отправлять:</label>
|
|
<select class="form-select" id="broadcastTarget">
|
|
<option value="all">📢 Всем жильцам</option>
|
|
<option value="verified">✅ Только верифицированным</option>
|
|
<option value="unverified">⏳ Только непроверенным</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Текст сообщения:</label>
|
|
<textarea class="form-control" id="broadcastText" rows="5" placeholder="Введите текст рассылки..."></textarea>
|
|
<small class="text-muted">Поддерживается HTML разметка: <b>жирный</b>, <i>курсив</i></small>
|
|
</div>
|
|
<button class="btn btn-primary" onclick="sendBroadcast()">
|
|
<i class="bi bi-send"></i> Отправить рассылку
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="alert alert-info mt-4">
|
|
<i class="bi bi-info-circle"></i>
|
|
<b>Информация:</b> Рассылка будет отправлена через Telegram бота.
|
|
Сообщение также будет продублировано в общий чат дома.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script>
|
|
async function sendBroadcast() {
|
|
const text = document.getElementById('broadcastText').value;
|
|
const target = document.getElementById('broadcastTarget').value;
|
|
|
|
if (!text.trim()) { alert('Введите текст рассылки!'); return; }
|
|
if (!confirm(`Отправить рассылку (${target})?\n\nТекст: ${text.substring(0, 100)}...`)) return;
|
|
|
|
const r = await fetch('/api/broadcast/send', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({ text, target })
|
|
});
|
|
const result = await r.json();
|
|
if (result.success) { alert('✅ Рассылка отправлена!'); location.reload(); }
|
|
else { alert('❌ Ошибка: ' + (result.error || 'Неизвестная')); }
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|