AdminLTE3

This commit is contained in:
2025-10-26 22:14:47 +09:00
parent 291fc63a4c
commit 9974811a3e
226 changed files with 88284 additions and 3406 deletions

View File

@@ -0,0 +1,360 @@
<!-- Content Header (Page header) -->
<section class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1><i class="fab fa-telegram mr-2 text-info"></i>Telegram Bot</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="/admin">Админ</a></li>
<li class="breadcrumb-item active">Telegram Bot</li>
</ol>
</div>
</div>
</div>
</section>
<!-- Main content -->
<section class="content">
<div class="container-fluid">
<!-- Bot Status Card -->
<div class="card">
<div class="card-header">
<h3 class="card-title">Статус бота</h3>
<div class="card-tools">
<button id="refresh-status" class="btn btn-sm btn-default">
<i class="fas fa-sync-alt"></i>
</button>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div class="info-box">
<span class="info-box-icon" id="status-icon">
<i class="fas fa-question"></i>
</span>
<div class="info-box-content">
<span class="info-box-text">Статус подключения</span>
<span class="info-box-number" id="status-text">Проверка...</span>
</div>
</div>
</div>
<div class="col-md-6">
<div class="info-box">
<span class="info-box-icon bg-info">
<i class="fab fa-telegram"></i>
</span>
<div class="info-box-content">
<span class="info-box-text">Имя бота</span>
<span class="info-box-number" id="bot-name">Загрузка...</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Configuration Card -->
<div class="card">
<div class="card-header">
<h3 class="card-title">Конфигурация</h3>
</div>
<form id="config-form">
<div class="card-body">
<div class="form-group">
<label for="bot-token">Токен бота</label>
<div class="input-group">
<input type="password" class="form-control" id="bot-token" name="botToken" placeholder="Введите токен бота">
<div class="input-group-append">
<button type="button" class="btn btn-outline-secondary" onclick="toggleTokenVisibility()">
<i class="fas fa-eye" id="token-eye"></i>
</button>
</div>
</div>
<small class="form-text text-muted">
Получите токен у <a href="https://t.me/BotFather" target="_blank">@BotFather</a>
</small>
</div>
<div class="form-group">
<label for="admin-chat-id">ID чата администратора</label>
<input type="text" class="form-control" id="admin-chat-id" name="adminChatId" placeholder="Введите ID чата">
<small class="form-text text-muted">
Узнайте ваш ID чата у <a href="https://t.me/userinfobot" target="_blank">@userinfobot</a>
</small>
</div>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="notifications-enabled" name="notificationsEnabled">
<label class="custom-control-label" for="notifications-enabled">Включить уведомления</label>
</div>
</div>
<div class="form-group">
<label>Типы уведомлений</label>
<div class="row">
<div class="col-md-6">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="notify-contacts" name="notifyContacts">
<label class="custom-control-label" for="notify-contacts">Новые контакты</label>
</div>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="notify-orders" name="notifyOrders">
<label class="custom-control-label" for="notify-orders">Новые заказы</label>
</div>
</div>
<div class="col-md-6">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="notify-errors" name="notifyErrors">
<label class="custom-control-label" for="notify-errors">Системные ошибки</label>
</div>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="notify-updates" name="notifyUpdates">
<label class="custom-control-label" for="notify-updates">Обновления системы</label>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-primary">
<i class="fas fa-save mr-1"></i>Сохранить
</button>
<button type="button" class="btn btn-secondary ml-2" onclick="testConnection()">
<i class="fas fa-bolt mr-1"></i>Проверить подключение
</button>
</div>
</form>
</div>
<!-- Test Message Card -->
<div class="card">
<div class="card-header">
<h3 class="card-title">Тестовое сообщение</h3>
</div>
<div class="card-body">
<div class="form-group">
<label for="test-message">Сообщение</label>
<textarea class="form-control" id="test-message" rows="3" placeholder="Введите тестовое сообщение...">Тестовое сообщение от SmartSolTech Admin Panel</textarea>
</div>
<button type="button" class="btn btn-info" onclick="sendTestMessage()">
<i class="fas fa-paper-plane mr-1"></i>Отправить тест
</button>
</div>
</div>
<!-- Activity Log Card -->
<div class="card">
<div class="card-header">
<h3 class="card-title">Журнал активности</h3>
<div class="card-tools">
<button class="btn btn-sm btn-default" onclick="clearLog()">
<i class="fas fa-trash"></i> Очистить
</button>
</div>
</div>
<div class="card-body">
<div id="activity-log" style="max-height: 300px; overflow-y: auto;">
<!-- Log entries will be added here -->
</div>
</div>
</div>
</div>
</section>
<script>
let activityLog = [];
document.addEventListener('DOMContentLoaded', function() {
loadConfig();
checkBotStatus();
initializeLog();
document.getElementById('config-form').addEventListener('submit', saveConfig);
});
function addLog(message, type = 'info') {
const timestamp = new Date().toLocaleString('ru-RU');
const logEntry = { timestamp, message, type };
activityLog.unshift(logEntry);
if (activityLog.length > 100) {
activityLog = activityLog.slice(0, 100);
}
updateLogDisplay();
}
function updateLogDisplay() {
const logContainer = document.getElementById('activity-log');
const typeColors = {
info: 'text-info',
success: 'text-success',
error: 'text-danger',
warning: 'text-warning'
};
logContainer.innerHTML = activityLog.map(entry => `
<div class="mb-2">
<small class="text-muted">[${entry.timestamp}]</small>
<span class="${typeColors[entry.type] || 'text-info'}">${entry.message}</span>
</div>
`).join('');
}
function initializeLog() {
addLog('Telegram Bot панель загружена');
}
function clearLog() {
if (confirm('Очистить журнал активности?')) {
activityLog = [];
updateLogDisplay();
addLog('Журнал активности очищен');
}
}
async function loadConfig() {
try {
const response = await fetch('/api/admin/telegram/config');
const data = await response.json();
if (data.success) {
const config = data.config;
document.getElementById('bot-token').value = config.botToken || '';
document.getElementById('admin-chat-id').value = config.adminChatId || '';
document.getElementById('notifications-enabled').checked = config.notificationsEnabled || false;
document.getElementById('notify-contacts').checked = config.notifyContacts || false;
document.getElementById('notify-orders').checked = config.notifyOrders || false;
document.getElementById('notify-errors').checked = config.notifyErrors || false;
document.getElementById('notify-updates').checked = config.notifyUpdates || false;
addLog('Конфигурация загружена');
}
} catch (error) {
console.error('Error loading config:', error);
addLog('Ошибка загрузки конфигурации: ' + error.message, 'error');
}
}
async function saveConfig(event) {
event.preventDefault();
const formData = new FormData(event.target);
const config = {
botToken: formData.get('botToken'),
adminChatId: formData.get('adminChatId'),
notificationsEnabled: formData.has('notificationsEnabled'),
notifyContacts: formData.has('notifyContacts'),
notifyOrders: formData.has('notifyOrders'),
notifyErrors: formData.has('notifyErrors'),
notifyUpdates: formData.has('notifyUpdates')
};
try {
const response = await fetch('/api/admin/telegram/config', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(config)
});
const data = await response.json();
if (data.success) {
addLog('Конфигурация сохранена', 'success');
setTimeout(checkBotStatus, 1000);
} else {
throw new Error(data.message);
}
} catch (error) {
console.error('Error saving config:', error);
addLog('Ошибка сохранения конфигурации: ' + error.message, 'error');
}
}
async function checkBotStatus() {
try {
const response = await fetch('/api/admin/telegram/status');
const data = await response.json();
const statusIcon = document.getElementById('status-icon');
const statusText = document.getElementById('status-text');
const botName = document.getElementById('bot-name');
if (data.success && data.status.connected) {
statusIcon.className = 'info-box-icon bg-success';
statusIcon.innerHTML = '<i class="fas fa-check"></i>';
statusText.textContent = 'Подключен';
botName.textContent = data.status.botInfo.first_name;
addLog('Бот подключен: ' + data.status.botInfo.first_name, 'success');
} else {
statusIcon.className = 'info-box-icon bg-danger';
statusIcon.innerHTML = '<i class="fas fa-times"></i>';
statusText.textContent = 'Не подключен';
botName.textContent = 'Не подключен';
addLog('Бот не подключен: ' + (data.message || 'Неизвестная ошибка'), 'error');
}
} catch (error) {
console.error('Error checking bot status:', error);
const statusIcon = document.getElementById('status-icon');
const statusText = document.getElementById('status-text');
const botName = document.getElementById('bot-name');
statusIcon.className = 'info-box-icon bg-warning';
statusIcon.innerHTML = '<i class="fas fa-exclamation"></i>';
statusText.textContent = 'Ошибка проверки';
botName.textContent = 'Ошибка';
addLog('Ошибка проверки статуса: ' + error.message, 'error');
}
}
async function testConnection() {
addLog('Проверка подключения...');
await checkBotStatus();
}
async function sendTestMessage() {
const message = document.getElementById('test-message').value;
if (!message.trim()) {
alert('Введите сообщение для отправки');
return;
}
try {
addLog('Отправка тестового сообщения...');
const response = await fetch('/api/admin/telegram/test', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message })
});
const data = await response.json();
if (data.success) {
addLog('Тестовое сообщение отправлено', 'success');
} else {
throw new Error(data.message);
}
} catch (error) {
console.error('Error sending test message:', error);
addLog('Ошибка отправки сообщения: ' + error.message, 'error');
}
}
function toggleTokenVisibility() {
const tokenInput = document.getElementById('bot-token');
const tokenEye = document.getElementById('token-eye');
if (tokenInput.type === 'password') {
tokenInput.type = 'text';
tokenEye.className = 'fas fa-eye-slash';
} else {
tokenInput.type = 'password';
tokenEye.className = 'fas fa-eye';
}
}
</script>