↩️ Назад

Категории

Интеграция расписания с 1С через JSON API: система авторизации и антифлуда на чистом PHP

02.06.2026 | коды из категории: 1С

про Интеграция расписания с 1С через JSON API: система авторизации и антифлуда на чистом PHP

Стек: PHP (без фреймворков), MySQL (PDO), HTML, немного JavaScript.

Что умеет система:

Структура базы данных

Скрипт сам создаёт три таблицы:

Как работает антифлуд (Rate Limiting)

Админ-панель

Работа с внешним API

Запросы к API расписания выполняются через cURL с параметрами:

?token=...&DatRasp=YYYYMMDD&telephone=...

SSL-проверка отключена для совместимости с серверами на самоподписных сертификатах.

Пользовательская часть

Особенности безопасности

Минусы и что можно улучшить

Итог

Отличное решение для небольшого корпоративного сервиса или учебного проекта. Всё работает "из коробки": создал БД, накидал таблицы, настроил подключение — и можно пользоваться. Админка позволяет править всё на лету без доступа к коду и FTP.

PHP

<div class="container">
<?php
session_start();

// Подключение к MySQL
$db_host = 'localhost';
$db_name = 'baza';
$db_user = 'nameuser';
$db_pass = 'parol';

try {
    $db = new PDO("mysql:host=$db_host;dbname=$db_name;charset=utf8mb4", $db_user, $db_pass);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    // Создание таблицы для настроек
    $db->exec("CREATE TABLE IF NOT EXISTS settings (
        setting_key VARCHAR(100) PRIMARY KEY,
        setting_value TEXT NOT NULL,
        updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
    
    // Создание таблицы для rate limiting
    $db->exec("CREATE TABLE IF NOT EXISTS rate_limits (
        id INT AUTO_INCREMENT PRIMARY KEY,
        user_id INT NOT NULL,
        request_time DATETIME NOT NULL,
        INDEX idx_user_time (user_id, request_time)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
    
    // Функция получения настроек
    function getSetting($db, $key, $default = '') {
        $stmt = $db->prepare("SELECT setting_value FROM settings WHERE setting_key = ?");
        $stmt->execute([$key]);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        return $result ? $result['setting_value'] : $default;
    }
    
    // Функция обновления настроек
    function updateSetting($db, $key, $value) {
        $stmt = $db->prepare("INSERT INTO settings (setting_key, setting_value) VALUES (?, ?) 
                              ON DUPLICATE KEY UPDATE setting_value = ?");
        return $stmt->execute([$key, $value, $value]);
    }
    
    // Инициализация настроек по умолчанию, если их нет
    if (!getSetting($db, 'api_url')) {
        updateSetting($db, 'api_url', 'https://38.22.15.96:88/logobaza/ru_RU/hs/RaspSite/');
    }
    if (!getSetting($db, 'api_token')) {
        updateSetting($db, 'api_token', '68421395:AAasdfasdfasFdYeFmqLs_s');
    }
    if (!getSetting($db, 'rate_limit_requests')) {
        updateSetting($db, 'rate_limit_requests', '6');
    }
    if (!getSetting($db, 'rate_limit_time')) {
        updateSetting($db, 'rate_limit_time', '60');
    }
    if (!getSetting($db, 'rate_limit_cooldown')) {
        updateSetting($db, 'rate_limit_cooldown', '10');
    }
    
} catch (PDOException $e) {
    die("Ошибка базы данных: " . $e->getMessage());
}

// Получаем текущие настройки
$apiUrlBase = getSetting($db, 'api_url');
$defaultToken = getSetting($db, 'api_token');
$RATE_LIMIT_REQUESTS = (int)getSetting($db, 'rate_limit_requests');
$RATE_LIMIT_TIME = (int)getSetting($db, 'rate_limit_time');
$RATE_LIMIT_COOLDOWN = (int)getSetting($db, 'rate_limit_cooldown');

// Функция проверки rate limit
function checkRateLimit($db, $userId) {
    global $RATE_LIMIT_REQUESTS, $RATE_LIMIT_TIME, $RATE_LIMIT_COOLDOWN;
    
    if (!$userId) return true;
    
    try {
        $now = new DateTime();
        
        // Проверка минимального интервала между запросами
        $stmt = $db->prepare("SELECT request_time FROM rate_limits 
                              WHERE user_id = ? 
                              ORDER BY request_time DESC LIMIT 1");
        $stmt->execute([$userId]);
        $lastRequest = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if ($lastRequest) {
            $lastTime = new DateTime($lastRequest['request_time']);
            $interval = $now->getTimestamp() - $lastTime->getTimestamp();
            if ($interval < $RATE_LIMIT_COOLDOWN) {
                return [
                    'allowed' => false,
                    'message' => "Подождите " . ($RATE_LIMIT_COOLDOWN - $interval) . " секунд перед следующим запросом",
                    'wait' => $RATE_LIMIT_COOLDOWN - $interval
                ];
            }
        }
        
        // Проверка количества запросов за период
        $periodStart = new DateTime();
        $periodStart->modify('-' . $RATE_LIMIT_TIME . ' seconds');
        
        $stmt = $db->prepare("SELECT COUNT(*) as count FROM rate_limits 
                              WHERE user_id = ? AND request_time > ?");
        $stmt->execute([$userId, $periodStart->format('Y-m-d H:i:s')]);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if ($result['count'] >= $RATE_LIMIT_REQUESTS) {
            $oldestRequest = new DateTime();
            $oldestRequest->modify('-' . $RATE_LIMIT_TIME . ' seconds');
            
            $stmt = $db->prepare("SELECT request_time FROM rate_limits 
                                  WHERE user_id = ? AND request_time > ? 
                                  ORDER BY request_time ASC LIMIT 1");
            $stmt->execute([$userId, $oldestRequest->format('Y-m-d H:i:s')]);
            $oldest = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($oldest) {
                $oldTime = new DateTime($oldest['request_time']);
                $waitTime = $RATE_LIMIT_TIME - ($now->getTimestamp() - $oldTime->getTimestamp());
                return [
                    'allowed' => false,
                    'message' => "Лимит запросов: " . $RATE_LIMIT_REQUESTS . " запросов в " . $RATE_LIMIT_TIME . " секунд. Подождите " . ceil($waitTime) . " секунд",
                    'wait' => ceil($waitTime)
                ];
            }
        }
        
        // Записываем запрос
        $stmt = $db->prepare("INSERT INTO rate_limits (user_id, request_time) VALUES (?, ?)");
        $stmt->execute([$userId, $now->format('Y-m-d H:i:s')]);
        
        // Очищаем старые записи
        $cleanupTime = new DateTime();
        $cleanupTime->modify('-1 hour');
        $stmt = $db->prepare("DELETE FROM rate_limits WHERE request_time < ?");
        $stmt->execute([$cleanupTime->format('Y-m-d H:i:s')]);
        
        return ['allowed' => true, 'message' => null];
        
    } catch (PDOException $e) {
        error_log("Rate limit error: " . $e->getMessage());
        return ['allowed' => true, 'message' => null];
    }
}

// Создаем администратора если его нет
$adminPasswordHash = password_hash('qwert12345', PASSWORD_DEFAULT);
$stmt = $db->prepare("SELECT id FROM users WHERE phone = 'admin'");
$stmt->execute();
if (!$stmt->fetch()) {
    $stmt = $db->prepare("INSERT INTO users (phone, password, full_name, is_admin) VALUES (?, ?, ?, 1)");
    $stmt->execute(['admin', $adminPasswordHash, 'Администратор']);
}

// Обработка админских действий
if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] == 1) {
    
    // Обновление настроек API
    if (isset($_POST['update_api_settings'])) {
        $new_api_url = trim($_POST['api_url']);
        $new_api_token = trim($_POST['api_token']);
        $new_rate_requests = (int)$_POST['rate_limit_requests'];
        $new_rate_time = (int)$_POST['rate_limit_time'];
        $new_rate_cooldown = (int)$_POST['rate_limit_cooldown'];
        
        if ($new_api_url && $new_api_token) {
            updateSetting($db, 'api_url', $new_api_url);
            updateSetting($db, 'api_token', $new_api_token);
            updateSetting($db, 'rate_limit_requests', $new_rate_requests);
            updateSetting($db, 'rate_limit_time', $new_rate_time);
            updateSetting($db, 'rate_limit_cooldown', $new_rate_cooldown);
            
            // Обновляем глобальные переменные
            $apiUrlBase = $new_api_url;
            $defaultToken = $new_api_token;
            $RATE_LIMIT_REQUESTS = $new_rate_requests;
            $RATE_LIMIT_TIME = $new_rate_time;
            $RATE_LIMIT_COOLDOWN = $new_rate_cooldown;
            
            $_SESSION['admin_message'] = "Настройки API успешно обновлены!";
        } else {
            $_SESSION['admin_error'] = "Заполните все поля настроек";
        }
        header('Location: ' . $_SERVER['PHP_SELF'] . '?admin_panel=1');
        exit;
    }
    
    // Сброс пароля
    if (isset($_POST['reset_password'])) {
        $user_id = $_POST['user_id'];
        $new_password = 'qwerty';
        $hashed_password = password_hash($new_password, PASSWORD_DEFAULT);
        
        $stmt = $db->prepare("UPDATE users SET password = ? WHERE id = ?");
        if ($stmt->execute([$hashed_password, $user_id])) {
            $_SESSION['admin_message'] = "Пароль успешно сброшен на: qwerty";
        } else {
            $_SESSION['admin_error'] = "Ошибка сброса пароля";
        }
        header('Location: ' . $_SERVER['PHP_SELF'] . '?admin_panel=1');
        exit;
    }
    
    // Удаление пользователя
    if (isset($_POST['delete_user'])) {
        $user_id = $_POST['user_id'];
        
        if ($user_id == $_SESSION['user_id']) {
            $_SESSION['admin_error'] = "Нельзя удалить самого себя!";
        } else {
            $stmt = $db->prepare("DELETE FROM users WHERE id = ?");
            if ($stmt->execute([$user_id])) {
                $_SESSION['admin_message'] = "Пользователь успешно удален";
            } else {
                $_SESSION['admin_error'] = "Ошибка удаления";
            }
        }
        header('Location: ' . $_SERVER['PHP_SELF'] . '?admin_panel=1');
        exit;
    }
    
    // Редактирование пользователя
    if (isset($_POST['edit_user'])) {
        $user_id = $_POST['user_id'];
        $full_name = $_POST['full_name'];
        $phone = preg_replace('/[^0-9]/', '', $_POST['phone']);
        
        $stmt = $db->prepare("UPDATE users SET full_name = ?, phone = ? WHERE id = ?");
        if ($stmt->execute([$full_name, $phone, $user_id])) {
            $_SESSION['admin_message'] = "Данные пользователя обновлены";
        } else {
            $_SESSION['admin_error'] = "Ошибка обновления";
        }
        header('Location: ' . $_SERVER['PHP_SELF'] . '?admin_panel=1');
        exit;
    }
}

// Обработка действий пользователя
$action = isset($_GET['action']) ? $_GET['action'] : 'login';
$error = '';
$success = '';

// Регистрация
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['register'])) {
    $phone = preg_replace('/[^0-9]/', '', $_POST['phone']);
    $password = $_POST['password'];
    $confirm_password = $_POST['confirm_password'];
    $full_name = trim($_POST['full_name'] ?? '');
    
    if (empty($phone) || empty($password)) {
        $error = "Заполните все обязательные поля";
    } elseif (strlen($phone) != 11) {
        $error = "Телефон должен содержать 11 цифр (например, 79262852676)";
    } elseif (strlen($password) < 4) {
        $error = "Пароль должен быть не менее 4 символов";
    } elseif ($password != $confirm_password) {
        $error = "Пароли не совпадают";
    } else {
        $stmt = $db->prepare("SELECT id FROM users WHERE phone = ?");
        $stmt->execute([$phone]);
        if ($stmt->fetch()) {
            $error = "Пользователь с таким номером уже существует";
        } else {
            $hashed_password = password_hash($password, PASSWORD_DEFAULT);
            $stmt = $db->prepare("INSERT INTO users (phone, password, full_name, is_admin) VALUES (?, ?, ?, 0)");
            if ($stmt->execute([$phone, $hashed_password, $full_name, 0])) {
                $success = "Регистрация успешна! Теперь вы можете войти.";
                $action = 'login';
            } else {
                $error = "Ошибка при регистрации";
            }
        }
    }
}

// Авторизация
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['login'])) {
    $phone = preg_replace('/[^0-9]/', '', $_POST['phone']);
    $password = $_POST['password'];
    
    if (empty($phone) || empty($password)) {
        $error = "Введите телефон и пароль";
    } else {
        $stmt = $db->prepare("SELECT id, phone, password, full_name, is_admin FROM users WHERE phone = ?");
        $stmt->execute([$phone]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if ($user && password_verify($password, $user['password'])) {
            $_SESSION['user_id'] = $user['id'];
            $_SESSION['user_phone'] = $user['phone'];
            $_SESSION['user_name'] = $user['full_name'];
            $_SESSION['is_admin'] = isset($user['is_admin']) ? $user['is_admin'] : 0;
            
            $stmt = $db->prepare("UPDATE users SET last_login = NOW() WHERE id = ?");
            $stmt->execute([$user['id']]);
            
            header('Location: ' . $_SERVER['PHP_SELF']);
            exit;
        } else {
            $error = "Неверный телефон или пароль";
        }
    }
}

// Админ-логин
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['admin_login'])) {
    $login = $_POST['admin_login_name'];
    $password = $_POST['admin_password'];
    
    if ($login == 'admin' && password_verify($password, $adminPasswordHash)) {
        $_SESSION['admin_logged_in'] = true;
        $_SESSION['is_admin'] = 1;
        $_SESSION['user_id'] = 1;
        $_SESSION['user_phone'] = 'admin';
        $_SESSION['user_name'] = 'Администратор';
        header('Location: ' . $_SERVER['PHP_SELF'] . '?admin_panel=1');
        exit;
    } else {
        $admin_error = "Неверный логин или пароль";
    }
}

// Выход
if (isset($_GET['logout'])) {
    session_destroy();
    header('Location: ' . $_SERVER['PHP_SELF']);
    exit;
}

// Проверка авторизации
$isAuthenticated = isset($_SESSION['user_id']);
$userPhone = $isAuthenticated ? $_SESSION['user_phone'] : '';

// Админ-панель
$showAdminPanel = isset($_GET['admin_panel']) && isset($_SESSION['is_admin']) && $_SESSION['is_admin'] == 1;

// Получаем список пользователей для админки
$users = [];
if ($showAdminPanel) {
    $stmt = $db->query("SELECT id, phone, full_name, is_admin, created_at, last_login FROM users ORDER BY id DESC");
    $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
}

// Получаем данные расписания
$schedule = [];
$error_api = null;
$submitted = false;
$date = isset($_GET['date']) ? preg_replace('/[^0-9]/', '', $_GET['date']) : date('Ymd');
$diagnosticCode = isset($_GET['diagnostic']) ? preg_replace('/[^0-9]/', '', $_GET['diagnostic']) : null;
$rateLimitError = null;

if ($isAuthenticated && isset($_GET['show_schedule']) && !$showAdminPanel) {
    // Проверяем rate limit перед запросом
    $rateLimitCheck = checkRateLimit($db, $_SESSION['user_id']);
    
    if (!$rateLimitCheck['allowed']) {
        $error_api = $rateLimitCheck['message'];
    } else {
        $submitted = true;
        $phone = $diagnosticCode ? $diagnosticCode : $userPhone;
        
        $url = $apiUrlBase . "?token=" . urlencode($defaultToken) . "&DatRasp=" . $date . "&telephone=" . urlencode($phone);
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($response === false) {
            $error_api = "Ошибка соединения с сервером";
        } elseif ($httpCode != 200) {
            $error_api = "Ошибка сервера: " . $httpCode;
        } else {
            $bom = pack('H*','EFBBBF');
            $response = preg_replace('/^' . $bom . '/', '', $response);
            $data = json_decode($response, true);
            
            if (json_last_error() === JSON_ERROR_NONE && is_array($data)) {
                $schedule = $data;
            } else {
                $error_api = "Ошибка обработки данных";
            }
        }
    }
}

// Получаем сообщения из сессии
$admin_message = isset($_SESSION['admin_message']) ? $_SESSION['admin_message'] : null;
$admin_error = isset($_SESSION['admin_error']) ? $_SESSION['admin_error'] : null;
unset($_SESSION['admin_message'], $_SESSION['admin_error']);
?>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
    <style>
		.page-title {padding: 0px !important;
		}

       
        .auth-card, .schedule-card, .admin-card { background: white; border-radius: 24px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); overflow: hidden; }
        .auth-header, .schedule-header, .admin-header { padding: 32px; text-align: center; color: white; }
        .auth-header, .schedule-header { background:#612f8c; }
        .admin-header { background: linear-gradient(135deg, #e53e3e 0%, #c53030 100%); }
        .auth-header h1, .schedule-header h1, .admin-header h1 { font-size: 1.8rem; margin-bottom: 8px; }
        .auth-body, .schedule-body, .admin-body { padding: 32px; background: #d7cce1}
        .form-group { margin-bottom: 20px; }
        .form-group label { display: block; font-size: 0.85rem; font-weight: 600; color: #4a5568; margin-bottom: 8px; }
        .form-group input, .form-group textarea { width: 100%; padding: 12px 16px; border: 2px solid #e2e8f0; border-radius: 12px; font-size: 1rem; font-family: monospace; }
        .form-group textarea { font-family: monospace; resize: vertical; }
		.btn {background: #FFFFFF}
        .btn-danger { background: linear-gradient(135deg, #e53e3e 0%, #c53030 100%); }
        .btn-warning { background: linear-gradient(135deg, #ed8936 0%, #dd6b20 100%); }
        .btn-sm { padding: 8px 16px; font-size: 0.85rem; width: auto; }
        .btn-success { background: linear-gradient(135deg, #48bb78 0%, #38a169 100%); }
        .link { text-align: center; margin-top: 20px; color: #718096; }
        .link a { color: #667eea; text-decoration: none; font-weight: 600; }
        .alert { padding: 12px 16px; border-radius: 12px; margin-bottom: 20px; }
        .alert-error { background: #fed7d7; color: #c53030; }
        .alert-success { background: #c6f6d5; color: #22543d; }
        .alert-info { background: #edf2f7; text-align: center; }
        .user-info { background: #edf2f7; padding: 16px; border-radius: 12px; margin-bottom: 24px; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px; align-items: center; }
        .users-table, .schedule-table { width: 100%; border-collapse: collapse; overflow-x: auto; display: block; }
        .users-table th, .users-table td, .schedule-table th, .schedule-table td { padding: 12px; text-align: left; border-bottom: 1px solid #e2e8f0; }
        .users-table th, .schedule-table th { background: #f7fafc; font-weight: 600; }
        .badge-admin { background: #e53e3e; color: white; padding: 2px 8px; border-radius: 12px; font-size: 0.7rem; display: inline-block; }
        .badge-user { background: #48bb78; color: white; padding: 2px 8px; border-radius: 12px; font-size: 0.7rem; display: inline-block; }
        .action-buttons { display: flex; gap: 8px; flex-wrap: wrap; }
        .diagnostic-link { display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 4px 12px; border-radius: 20px; font-size: 0.8rem; text-decoration: none; }
        .break-row { background: #fff5f0; }
        .settings-section { background: #f7fafc; border-radius: 16px; padding: 20px; margin-bottom: 30px; border: 2px solid #e2e8f0; }
        .settings-section h3 { margin-bottom: 15px; color: #2d3748; }
        .settings-section .form-group { margin-bottom: 15px; }
        hr { margin: 20px 0; border-color: #e2e8f0; }
        @media (max-width: 768px) { .container { padding: 20px; } .action-buttons { flex-direction: column; } }
    </style>

    <?php if ($showAdminPanel): ?>
        <div class="admin-card">
            <div class="admin-header"><h1>🔧 Админ-панель</h1><p>Управление пользователями и настройками системы</p></div>
            <div class="admin-body">
                <?php if ($admin_message): ?><div class="alert alert-success">✅ <?php echo htmlspecialchars($admin_message); ?></div><?php endif; ?>
                <?php if ($admin_error): ?><div class="alert alert-error">⚠️ <?php echo htmlspecialchars($admin_error); ?></div><?php endif; ?>
                
                <div style="display: flex; gap: 12px; margin-bottom: 24px; flex-wrap: wrap;">
                    <a href="<?php echo $_SERVER['PHP_SELF']; ?>" style="padding: 10px 20px; background: #edf2f7; color: #4a5568; text-decoration: none; border-radius: 40px;">📅 Основная страница</a>
                    <a href="?logout" style="padding: 10px 20px; background: #e53e3e; color: white; text-decoration: none; border-radius: 40px;">🚪 Выйти</a>
                </div>
                
                <!-- Настройки API -->
                <div class="settings-section">
                    <h3>⚙️ Настройки API расписания</h3>
                    <form method="POST">
                        <div class="form-group">
                            <label>🔗 URL API:</label>
                            <input type="text" name="api_url" value="<?php echo htmlspecialchars(getSetting($db, 'api_url')); ?>" required>
                        </div>
                        <div class="form-group">
                            <label>🔑 Токен доступа:</label>
                            <textarea name="api_token" rows="2" required><?php echo htmlspecialchars(getSetting($db, 'api_token')); ?></textarea>
                        </div>
                        
                        <h4 style="margin: 20px 0 15px 0;">🚦 Настройки ограничения запросов</h4>
                        <div class="form-group">
                            <label>📊 Максимум запросов:</label>
                            <input type="number" name="rate_limit_requests" value="<?php echo htmlspecialchars(getSetting($db, 'rate_limit_requests')); ?>" min="1" max="60" required>
                            <small style="color:#718096;">Количество запросов за период</small>
                        </div>
                        <div class="form-group">
                            <label>⏱️ Период (секунд):</label>
                            <input type="number" name="rate_limit_time" value="<?php echo htmlspecialchars(getSetting($db, 'rate_limit_time')); ?>" min="10" max="3600" required>
                            <small style="color:#718096;">За сколько секунд считаются запросы</small>
                        </div>
                        <div class="form-group">
                            <label>🕐 Минимальный интервал (секунд):</label>
                            <input type="number" name="rate_limit_cooldown" value="<?php echo htmlspecialchars(getSetting($db, 'rate_limit_cooldown')); ?>" min="1" max="60" required>
                            <small style="color:#718096;">Минимальное время между запросами</small>
                        </div>
                        
                        <button type="submit" name="update_api_settings" class="btn btn-success">💾 Сохранить настройки</button>
                    </form>
                </div>
                
                <hr>
                
                <h3>👥 Список пользователей</h3>
                <div style="overflow-x: auto; margin-top: 20px;">
                    <table class="users-table">
                        <thead>
                            <tr><th>ID</th><th>Телефон</th><th>Имя</th><th>Роль</th><th>Действия</th>
                        </thead>
                        <tbody>
                        <?php foreach ($users as $user): ?>
                            <tr>
                                <td><?php echo $user['id']; ?></td>
                                <td><?php echo htmlspecialchars($user['phone']); ?></td>
                                <td><?php echo htmlspecialchars($user['full_name'] ?: '—'); ?></td>
                                <td><?php echo ($user['is_admin'] == 1) ? '<span class="badge-admin">👑 Админ</span>' : '<span class="badge-user">👤 Пользователь</span>'; ?></td>
                                <td class="action-buttons">
                                    <button onclick='editUser(<?php echo $user['id']; ?>, "<?php echo htmlspecialchars($user['phone']); ?>", "<?php echo htmlspecialchars($user['full_name']); ?>")' class="btn btn-sm" style="background:#4299e1;">✏️ Ред.</button>
                                    <button onclick='resetPassword(<?php echo $user['id']; ?>)' class="btn btn-sm btn-warning">🔑 Сброс</button>
                                    <?php if ($user['id'] != $_SESSION['user_id']): ?>
                                        <button onclick='deleteUser(<?php echo $user['id']; ?>)' class="btn btn-sm btn-danger">🗑️ Удалить</button>
                                    <?php endif; ?>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
                
                <div id="editModal" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); align-items:center; justify-content:center;">
                    <div style="background:white; padding:30px; border-radius:24px; max-width:500px;">
                        <h3>Редактировать пользователя</h3>
                        <form method="POST">
                            <input type="hidden" name="user_id" id="edit_user_id">
                            <div class="form-group"><label>Телефон</label><input type="tel" name="phone" id="edit_phone" required></div>
                            <div class="form-group"><label>Имя</label><input type="text" name="full_name" id="edit_full_name"></div>
                            <div style="display:flex; gap:10px;">
                                <button type="submit" name="edit_user" class="btn">Сохранить</button>
                                <button type="button" onclick="closeModal()" class="btn" style="background:#a0aec0;">Отмена</button>
                            </div>
                        </form>
                    </div>
                </div>
                <form method="POST" id="resetForm" style="display:none;"><input type="hidden" name="user_id" id="reset_user_id"><input type="hidden" name="reset_password" value="1"></form>
                <form method="POST" id="deleteForm" style="display:none;"><input type="hidden" name="user_id" id="delete_user_id"><input type="hidden" name="delete_user" value="1"></form>
            </div>
        </div>
        <script>
            function editUser(id,phone,name){ 
                document.getElementById('edit_user_id').value=id; 
                document.getElementById('edit_phone').value=phone; 
                document.getElementById('edit_full_name').value=name; 
                document.getElementById('editModal').style.display='flex'; 
            }
            function closeModal(){ 
                document.getElementById('editModal').style.display='none'; 
            }
            function resetPassword(id){ 
                if(confirm('Сбросить пароль на qwerty?')){ 
                    document.getElementById('reset_user_id').value=id; 
                    document.getElementById('resetForm').submit(); 
                } 
            }
            function deleteUser(id){ 
                if(confirm('Удалить пользователя?')){ 
                    document.getElementById('delete_user_id').value=id; 
                    document.getElementById('deleteForm').submit(); 
                } 
            }
        </script>
    <?php elseif (!$isAuthenticated): ?>
        <div class="auth-card"><div class="auth-header"><p>Вход в систему</p></div>
        <div class="auth-body">
            <?php if ($error): ?><div class="alert alert-error"><?php echo htmlspecialchars($error); ?></div><?php endif; ?>
            <?php if ($success): ?><div class="alert alert-success"><?php echo htmlspecialchars($success); ?></div><?php endif; ?>
            <?php if ($action == 'login'): ?>
                <form method="POST"><div class="form-group"><label>📞 Телефон</label><input type="tel" name="phone"  required></div>
                <div class="form-group"><label>🔒 Пароль</label><input type="password" name="password" required></div>
                <button type="submit" name="login" class="btn">Войти</button><div class="link">Нет аккаунта? <a href="?action=register">Регистрация</a></div></form>
            <?php else: ?>
                <form method="POST"><div class="form-group"><label>📞 Телефон</label><input type="tel" name="phone"  required></div>
                <div class="form-group"><label>👤 Имя</label><input type="text" name="full_name" placeholder="Иван Иванов"></div>
                <div class="form-group"><label>🔒 Пароль</label><input type="password" name="password" required></div>
                <div class="form-group"><label>🔒 Подтверждение</label><input type="password" name="confirm_password" required></div>
                <button type="submit" name="register" class="btn">Зарегистрироваться</button><div class="link">Уже есть аккаунт? <a href="?action=login">Войти</a></div></form>
            <?php endif; ?>
            <hr style="margin:20px 0"><details><summary style="color:#718096;cursor:pointer;">🔐 Вход для администратора</summary>
            <form method="POST" style="margin-top:15px;"><div class="form-group"><label>Логин</label><input type="text" name="admin_login_name" ></div>
            <div class="form-group"><label>Пароль</label><input type="password" name="admin_password"></div>
            <button type="submit" name="admin_login" class="btn">Войти как админ</button></form></details>
        </div></div>
    <?php else: ?>
        <div class="schedule-card"><div class="schedule-header"><h1>📅 Моё расписание</h1><p>Добро пожаловать, <?php echo htmlspecialchars($_SESSION['user_name'] ?: $_SESSION['user_phone']); ?>!</p></div>
        <div class="schedule-body"><div class="user-info"><span>📞 Телефон: <?php echo htmlspecialchars($userPhone); ?></span>
        <div style="display:flex; gap:12px;"><?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] == 1): ?><a href="?admin_panel=1" style="background:#e53e3e; color:white; padding:8px 20px; border-radius:40px; text-decoration:none;">🔧 Админ-панель</a><?php endif; ?>
        <a href="?logout" style="background:#718096; color:white; padding:8px 20px; border-radius:40px; text-decoration:none;">Выйти</a></div></div>
        <form method="GET"><div class="form-group"><label>📅 Выберите дату:</label><input type="date" name="date" value="<?php echo date('Y-m-d', strtotime($date)); ?>" required></div>
        <button type="submit" name="show_schedule" class="btn">Показать расписание</button></form>
        <?php if ($submitted && !$error_api && empty($schedule)): ?><div class="alert alert-info" style="margin-top:20px;">📭 Нет записей</div>
        <?php elseif ($error_api): ?><div class="alert alert-error" style="margin-top:20px;">⚠️ <?php echo htmlspecialchars($error_api); ?></div>
        <?php elseif (!empty($schedule)): ?>
            <div style="background:#edf2f7; padding:12px; border-radius:12px; margin:20px 0;">📋 Найдено: <?php echo count($schedule); ?> на <?php echo date('d.m.Y', strtotime($date)); ?></div>
            <div style="overflow-x:auto;"><table class="schedule-table"><thead><tr><th>Время</th><th>Пациент</th><th>Услуга</th><th>Диагноз</th></tr></thead>
            <tbody><?php foreach ($schedule as $item): $isBreak = ($item['Услуга']??'')=='Перерыв'; $dCode = $item['Диагностика']??null; ?>
                <tr class="<?php echo $isBreak?'break-row':''; ?>"><td><?php if(!empty($item['НачалоПриема'])) echo date('H:i',strtotime($item['НачалоПриема'])).'-'.date('H:i',strtotime($item['ОкончаниеПриема'])); else echo '—'; ?></td>
                <td><strong><?php echo htmlspecialchars($item['Пациент']??'—'); ?></strong></td>
                <td><?php echo htmlspecialchars($item['Услуга']??'—'); ?></td>
                <td><?php if($dCode): ?><a href="?show_schedule=1&date=<?php echo $date; ?>&diagnostic=<?php echo $dCode; ?>" class="diagnostic-link">🧪 Диагностика: <?php echo $dCode; ?></a><?php else: echo htmlspecialchars($item['Нарушение']??'—'); endif; ?></td></tr>
            <?php endforeach; ?></tbody></table></div>
        <?php elseif (!$submitted): ?><div class="alert alert-info" style="margin-top:20px;">🗓️ Выберите дату</div><?php endif; ?>
        </div></div>
    <?php endif; ?>
<script>document.querySelectorAll('input[type="tel"]').forEach(i=>i.addEventListener('input',function(e){this.value=this.value.replace(/[^0-9]/g,'').slice(0,11);}));</script>

</div>
<br/><br/><br/><br/>



Категории:

Категории

Комментарии

Пока нет комментариев. Будьте первым!

Оставить комментарий

← Назад к списку

Посетителей сегодня: 0
о блоге | карта блога | 📡 Подписаться на RSS

© Digital Specialist | Не являемся сотрудниками Google, Яндекса и NASA