| <!DOCTYPE html>
|
| <html lang="fa" dir="rtl">
|
| <head>
|
| <meta charset="UTF-8">
|
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| <title>تست اتصال WebSocket</title>
|
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
| <link rel="stylesheet" href="/static/css/connection-status.css">
|
| <style>
|
| body {
|
| padding-top: 50px;
|
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| min-height: 100vh;
|
| }
|
|
|
| .main-container {
|
| max-width: 1200px;
|
| margin: 0 auto;
|
| padding: 20px;
|
| }
|
|
|
| .stats-card {
|
| background: white;
|
| border-radius: 15px;
|
| padding: 30px;
|
| box-shadow: 0 10px 40px rgba(0,0,0,0.15);
|
| margin-bottom: 20px;
|
| }
|
|
|
| .big-stat {
|
| text-align: center;
|
| padding: 30px;
|
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| border-radius: 15px;
|
| color: white;
|
| margin-bottom: 20px;
|
| }
|
|
|
| .big-stat-value {
|
| font-size: 72px;
|
| font-weight: bold;
|
| margin: 0;
|
| animation: scaleIn 0.5s ease;
|
| }
|
|
|
| .big-stat-label {
|
| font-size: 20px;
|
| opacity: 0.9;
|
| margin-top: 10px;
|
| }
|
|
|
| @keyframes scaleIn {
|
| from { transform: scale(0.5); opacity: 0; }
|
| to { transform: scale(1); opacity: 1; }
|
| }
|
|
|
| .message-log {
|
| background: #f8f9fa;
|
| border-radius: 10px;
|
| padding: 20px;
|
| max-height: 400px;
|
| overflow-y: auto;
|
| font-family: 'Courier New', monospace;
|
| font-size: 13px;
|
| }
|
|
|
| .message-item {
|
| padding: 8px;
|
| margin-bottom: 5px;
|
| border-radius: 5px;
|
| animation: fadeIn 0.3s ease;
|
| }
|
|
|
| .message-sent {
|
| background: #e3f2fd;
|
| border-left: 3px solid #2196f3;
|
| }
|
|
|
| .message-received {
|
| background: #e8f5e9;
|
| border-left: 3px solid #4caf50;
|
| }
|
|
|
| @keyframes fadeIn {
|
| from { opacity: 0; transform: translateY(-10px); }
|
| to { opacity: 1; transform: translateY(0); }
|
| }
|
|
|
| .control-panel {
|
| display: grid;
|
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
| gap: 10px;
|
| margin-top: 20px;
|
| }
|
|
|
| .btn-action {
|
| padding: 12px 20px;
|
| font-weight: 600;
|
| border-radius: 8px;
|
| transition: all 0.3s ease;
|
| }
|
|
|
| .btn-action:hover {
|
| transform: translateY(-2px);
|
| box-shadow: 0 5px 15px rgba(0,0,0,0.2);
|
| }
|
| </style>
|
| </head>
|
| <body>
|
|
|
| <div class="connection-status-bar" id="ws-connection-status">
|
| <div class="ws-connection-info">
|
| <span class="status-dot status-dot-offline" id="ws-status-dot"></span>
|
| <span class="ws-status-text" id="ws-status-text">در حال اتصال...</span>
|
| <span class="connection-spinner"></span>
|
| </div>
|
|
|
| <div class="online-users-widget">
|
| <div class="online-users-count">
|
| <span class="users-icon">👥</span>
|
| <span class="count-number" id="active-users-count">0</span>
|
| <span class="count-label">کاربر آنلاین</span>
|
| </div>
|
| <div class="online-users-count">
|
| <span class="users-icon">📊</span>
|
| <span class="count-number" id="total-sessions-count">0</span>
|
| <span class="count-label">جلسات کل</span>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div class="alerts-container" id="alerts-container"></div>
|
|
|
|
|
| <div class="main-container">
|
| <div class="big-stat">
|
| <div class="big-stat-value" id="active-users-big">0</div>
|
| <div class="big-stat-label">کاربر در حال حاضر آنلاین هستند</div>
|
| </div>
|
|
|
| <div class="row">
|
| <div class="col-md-6">
|
| <div class="stats-card">
|
| <h3>📊 آمار اتصالات</h3>
|
| <hr>
|
| <table class="table">
|
| <tr>
|
| <td>اتصالات فعال:</td>
|
| <td><strong id="stat-active">0</strong></td>
|
| </tr>
|
| <tr>
|
| <td>جلسات کل:</td>
|
| <td><strong id="stat-total">0</strong></td>
|
| </tr>
|
| <tr>
|
| <td>پیامهای ارسالی:</td>
|
| <td><strong id="stat-sent">0</strong></td>
|
| </tr>
|
| <tr>
|
| <td>پیامهای دریافتی:</td>
|
| <td><strong id="stat-received">0</strong></td>
|
| </tr>
|
| <tr>
|
| <td>Session ID:</td>
|
| <td><code id="session-id">-</code></td>
|
| </tr>
|
| </table>
|
|
|
| <h5>انواع کلاینتها:</h5>
|
| <div id="client-types-list"></div>
|
| </div>
|
| </div>
|
|
|
| <div class="col-md-6">
|
| <div class="stats-card">
|
| <h3>🎮 کنترلها</h3>
|
| <hr>
|
| <div class="control-panel">
|
| <button class="btn btn-primary btn-action" onclick="requestStats()">
|
| 📊 درخواست آمار
|
| </button>
|
| <button class="btn btn-success btn-action" onclick="subscribeToMarket()">
|
| ✅ Subscribe به Market
|
| </button>
|
| <button class="btn btn-warning btn-action" onclick="unsubscribeFromMarket()">
|
| ❌ Unsubscribe از Market
|
| </button>
|
| <button class="btn btn-info btn-action" onclick="sendPing()">
|
| 🏓 ارسال Ping
|
| </button>
|
| <button class="btn btn-danger btn-action" onclick="disconnect()">
|
| 🔌 قطع اتصال
|
| </button>
|
| <button class="btn btn-secondary btn-action" onclick="reconnect()">
|
| 🔄 اتصال مجدد
|
| </button>
|
| </div>
|
| </div>
|
|
|
| <div class="stats-card">
|
| <h3>📝 لاگ پیامها</h3>
|
| <hr>
|
| <div class="message-log" id="message-log"></div>
|
| <button class="btn btn-sm btn-outline-secondary mt-2" onclick="clearLog()">
|
| 🗑️ پاک کردن لاگ
|
| </button>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
| <script src="/static/js/websocket-client.js"></script>
|
|
|
| <script>
|
|
|
| if (window.wsClient) {
|
| window.wsClient.on('welcome', (message) => {
|
| document.getElementById('session-id').textContent = message.session_id;
|
| logMessage('دریافت', message);
|
| });
|
|
|
| window.wsClient.on('stats_update', (message) => {
|
| updateStatsDisplay(message.data);
|
| logMessage('دریافت', message);
|
| });
|
|
|
| window.wsClient.on('subscribed', (message) => {
|
| logMessage('دریافت', message);
|
| });
|
|
|
| window.wsClient.on('pong', (message) => {
|
| logMessage('دریافت', message);
|
| });
|
| }
|
|
|
|
|
| function requestStats() {
|
| if (window.wsClient) {
|
| window.wsClient.requestStats();
|
| logMessage('ارسال', { type: 'get_stats' });
|
| }
|
| }
|
|
|
| function subscribeToMarket() {
|
| if (window.wsClient) {
|
| window.wsClient.subscribe('market');
|
| logMessage('ارسال', { type: 'subscribe', group: 'market' });
|
| }
|
| }
|
|
|
| function unsubscribeFromMarket() {
|
| if (window.wsClient) {
|
| window.wsClient.unsubscribe('market');
|
| logMessage('ارسال', { type: 'unsubscribe', group: 'market' });
|
| }
|
| }
|
|
|
| function sendPing() {
|
| if (window.wsClient) {
|
| window.wsClient.send({ type: 'ping' });
|
| logMessage('ارسال', { type: 'ping' });
|
| }
|
| }
|
|
|
| function disconnect() {
|
| if (window.wsClient) {
|
| window.wsClient.close();
|
| logMessage('سیستم', 'قطع اتصال توسط کاربر');
|
| }
|
| }
|
|
|
| function reconnect() {
|
| if (window.wsClient) {
|
| window.wsClient.reconnectAttempts = 0;
|
| window.wsClient.connect();
|
| logMessage('سیستم', 'تلاش برای اتصال مجدد');
|
| }
|
| }
|
|
|
| function updateStatsDisplay(data) {
|
| document.getElementById('stat-active').textContent = data.active_connections || 0;
|
| document.getElementById('stat-total').textContent = data.total_sessions || 0;
|
| document.getElementById('stat-sent').textContent = data.messages_sent || 0;
|
| document.getElementById('stat-received').textContent = data.messages_received || 0;
|
|
|
|
|
| const bigValue = document.getElementById('active-users-big');
|
| bigValue.textContent = data.active_connections || 0;
|
| bigValue.style.animation = 'none';
|
| setTimeout(() => bigValue.style.animation = 'scaleIn 0.5s ease', 10);
|
| }
|
|
|
| function logMessage(direction, message) {
|
| const log = document.getElementById('message-log');
|
| const item = document.createElement('div');
|
| item.className = `message-item ${direction === 'ارسال' ? 'message-sent' : 'message-received'}`;
|
|
|
| const time = new Date().toLocaleTimeString('fa-IR');
|
| const content = typeof message === 'string' ? message : JSON.stringify(message, null, 2);
|
|
|
| item.innerHTML = `
|
| <strong>[${time}] ${direction}:</strong><br>
|
| <pre style="margin:5px 0 0 0">${content}</pre>
|
| `;
|
|
|
| log.appendChild(item);
|
| log.scrollTop = log.scrollHeight;
|
| }
|
|
|
| function clearLog() {
|
| document.getElementById('message-log').innerHTML = '';
|
| }
|
|
|
|
|
| setInterval(() => {
|
| if (window.wsClient && window.wsClient.isConnected) {
|
| requestStats();
|
| }
|
| }, 5000);
|
| </script>
|
| </body>
|
| </html>
|
|
|
|
|