Islam-Ash/SVU-Forensics-System
0
1<!DOCTYPE html>2<html lang="ar" dir="rtl">3<head>4 <meta charset="UTF-8">5 <meta name="viewport" content="width=device-width, initial-scale=1.0">6 <title>لوحة المراقبة السيادية | SVU Admin</title>7 <link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;700;900&family=Tajawal:wght@400;500;800&display=swap" rel="stylesheet">8 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">9 <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>10 11 <style>12 :root {13 --primary-color: #0f3460;14 --accent-color: #e94560;15 --sidebar-width: 260px;16 --bg-light: #f0f2f5;17 --card-bg: rgba(255, 255, 255, 0.95);18 }19 20 * { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Tajawal', sans-serif; }21 22 body { background: var(--bg-light); min-height: 100vh; display: flex; overflow-x: hidden; }23 24 /* Sidebar Styling */25 .admin-sidebar { 26 width: var(--sidebar-width); 27 background: var(--primary-color); 28 color: white; 29 position: fixed; 30 top: 0; 31 right: 0; 32 height: 100vh; 33 display: flex; 34 flex-direction: column; 35 z-index: 1000; 36 box-shadow: -5px 0 15px rgba(0,0,0,0.1);37 }38 39 .sidebar-header { padding: 30px 20px; text-align: center; border-bottom: 1px solid rgba(255,255,255,0.05); }40 .sidebar-header img { width: 45px; margin-bottom: 10px; filter: brightness(0) invert(1); }41 .sidebar-header h2 { font-family: 'Cairo'; font-size: 1.1rem; }42 43 .nav-list { list-style: none; flex: 1; padding-top: 20px; }44 .nav-item { 45 padding: 15px 25px; 46 display: flex; 47 align-items: center; 48 gap: 12px; 49 cursor: pointer; 50 color: rgba(255,255,255,0.6); 51 transition: 0.3s; 52 font-weight: bold;53 }54 .nav-item:hover, .nav-item.active { 55 background: rgba(255,255,255,0.08); 56 color: white; 57 border-right: 4px solid var(--accent-color); 58 }59 60 /* Main Content Area */61 .dashboard-main { 62 flex: 1; 63 margin-right: var(--sidebar-width); 64 padding: 25px; 65 display: flex; 66 flex-direction: column; 67 gap: 25px; 68 }69 70 /* Header & Stats */71 .top-monitor { 72 background: var(--card-bg); 73 padding: 15px 25px; 74 border-radius: 15px; 75 display: flex; 76 justify-content: space-between; 77 align-items: center; 78 box-shadow: 0 4px 10px rgba(0,0,0,0.05); 79 }80 81 .pulse-dot { width: 10px; height: 10px; background: #27ae60; border-radius: 50%; animation: pulse-ring 1.5s infinite; box-shadow: 0 0 0 0 rgba(39, 174, 96, 0.7); }82 @keyframes pulse-ring { 0% { box-shadow: 0 0 0 0 rgba(39, 174, 96, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(39, 174, 96, 0); } 100% { box-shadow: 0 0 0 0 rgba(39, 174, 96, 0); } }83 84 .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px; }85 .stat-card { background: white; padding: 25px; border-radius: 15px; text-align: center; box-shadow: 0 4px 15px rgba(0,0,0,0.03); border: 1px solid rgba(0,0,0,0.05); transition: 0.3s; }86 .stat-card:hover { transform: translateY(-5px); }87 .stat-card h3 { font-size: 2.2rem; color: var(--primary-color); margin: 10px 0; font-family: 'Cairo'; }88 .stat-card span { font-size: 0.9rem; color: #7f8c8d; font-weight: bold; text-transform: uppercase; letter-spacing: 1px; }89 90 /* Dashboard Content Layout */91 .content-grid { display: grid; grid-template-columns: 2fr 1.2fr; gap: 25px; }92 93 .card { 94 background: white; 95 padding: 25px; 96 border-radius: 20px; 97 box-shadow: 0 5px 20px rgba(0,0,0,0.04); 98 display: flex; 99 flex-direction: column; 100 }101 102 .card-title { 103 font-family: 'Cairo'; 104 font-size: 1.1rem; 105 margin-bottom: 20px; 106 display: flex; 107 align-items: center; 108 gap: 10px; 109 color: var(--primary-color); 110 font-weight: 800;111 border-bottom: 2px solid #f0f0f0;112 padding-bottom: 15px;113 }114 115 /* Terminal & Live Ticker */116 .terminal { 117 background: #1e1e2e; 118 color: #a6e3a1; 119 padding: 15px; 120 border-radius: 10px; 121 font-family: 'Courier New', monospace; 122 font-size: 0.8rem; 123 height: 180px; 124 overflow-y: auto; 125 margin-top: 20px; 126 border: 1px solid #333;127 }128 129 .live-stream-box { 130 background: #0d1b2a; 131 border-radius: 12px; 132 padding: 10px 20px; 133 overflow: hidden; 134 position: relative; 135 border: 1px solid #1b263b; 136 margin-bottom: 25px;137 }138 .stream-track { display: flex; gap: 50px; animation: scrollLeft 30s linear infinite; white-space: nowrap; }139 .stream-node { color: #51e2f5; font-family: monospace; font-size: 0.85rem; font-weight: bold; }140 @keyframes scrollLeft { from { transform: translateX(-100%); } to { transform: translateX(100%); } }141 142 /* Queue Items (Human-in-the-Loop) */143 .queue-container { flex: 1; overflow-y: auto; padding-right: 5px; max-height: 500px; }144 .queue-item { 145 background: #fff; 146 border: 1px solid #eee; 147 border-radius: 12px; 148 padding: 15px; 149 margin-bottom: 15px; 150 position: relative;151 transition: 0.2s;152 }153 .queue-item:hover { border-color: var(--primary-color); }154 155 .queue-header { display: flex; justify-content: space-between; margin-bottom: 10px; font-size: 0.8rem; color: #e67e22; font-weight: bold; }156 .queue-img { width: 100%; height: 160px; object-fit: cover; border-radius: 8px; margin-bottom: 12px; background: #f9f9f9; }157 158 .btn-group { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }159 .btn { padding: 10px; border: none; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 0.9rem; color: white; transition: 0.2s; display: flex; align-items: center; justify-content: center; gap: 5px; }160 .btn:hover { opacity: 0.9; transform: scale(1.02); }161 .btn-approve { background: #27ae60; }162 .btn-reject { background: #e74c3c; }163 .btn:disabled { background: #bdc3c7; cursor: not-allowed; transform: none; }164 165 /* Scrollbar */166 ::-webkit-scrollbar { width: 8px; }167 ::-webkit-scrollbar-track { background: #f1f1f1; }168 ::-webkit-scrollbar-thumb { background: #cbd5e0; border-radius: 4px; }169 ::-webkit-scrollbar-thumb:hover { background: #a0aec0; }170 171 @media (max-width: 1100px) { .content-grid { grid-template-columns: 1fr; } .admin-sidebar { width: 70px; } .dashboard-main { margin-right: 70px; } }172 </style>173</head>174<body>175 176 <!-- Sidebar -->177 <aside class="admin-sidebar">178 <div class="sidebar-header">179 <img src="https://cdn-icons-png.flaticon.com/512/2092/2092663.png" alt="Logo">180 <h2>لوحة الإدارة</h2>181 </div>182 <ul class="nav-list">183 <li class="nav-item active"><i class="fas fa-th-large"></i> <span>الرئيسية</span></li>184 <li class="nav-item" onclick="window.location.href='/'"><i class="fas fa-user-graduate"></i> <span>صفحة الطالب</span></li>185 <li class="nav-item"><i class="fas fa-chart-pie"></i> <span>التقارير والبيانات</span></li>186 <li class="nav-item"><i class="fas fa-cogs"></i> <span>إعدادات النموذج</span></li>187 </ul>188 <div class="nav-item" style="margin-top: auto; border-top: 1px solid rgba(255,255,255,0.1); color: #ff7675;">189 <i class="fas fa-sign-out-alt"></i> <span>تسجيل خروج</span>190 </div>191 </aside>192 193 <!-- Main Content -->194 <main class="dashboard-main">195 196 <!-- Top Header -->197 <header class="top-monitor">198 <div class="status-badge" style="display: flex; align-items: center; gap: 10px; font-size: 0.9rem;">199 <div class="pulse-dot"></div>200 <span>حالة النظام: نشط (Active)</span>201 <span style="color: #95a5a6; margin: 0 10px;">|</span>202 <span>التدخل البشري: مفعّل</span>203 </div>204 <div id="clock" style="font-family: 'Courier New', monospace; font-weight: bold; color: var(--primary-color);">00:00:00</div>205 </header>206 207 <!-- Live Stream Logs -->208 <div class="live-stream-box">209 <div class="stream-track">210 <div class="stream-node" id="log-stream-1">[SYSTEM] Initializing Sovereign V8 Core...</div>211 <div class="stream-node" id="log-stream-2" style="color: #f1c40f;">[MONITOR] Watching for low-confidence inputs...</div>212 <div class="stream-node" id="log-stream-3">[DB] Connected to local storage successfully.</div>213 </div>214 </div>215 216 <!-- Statistics Grid -->217 <section class="stats-grid">218 <div class="stat-card">219 <span>الطلبات الكلية</span>220 <h3 id="stat-total">0</h3>221 </div>222 <div class="stat-card">223 <span style="color: #27ae60;">نسبة الدقة</span>224 <h3 id="stat-accuracy" style="color: #27ae60;">0%</h3>225 </div>226 <div class="stat-card">227 <span>طلبات مقبولة</span>228 <h3 id="stat-accepted" style="color: #3498db;">0</h3>229 </div>230 <div class="stat-card">231 <span style="color: #e94560;">طلبات مشبوهة</span>232 <h3 id="stat-suspicious" style="color: #e94560;">0</h3>233 </div>234 </section>235 236 <!-- Main Dashboard Grid -->237 <section class="content-grid">238 239 <!-- Left: Charts & Logs -->240 <div class="card">241 <div class="card-title">242 <i class="fas fa-chart-line"></i>243 <span>أداء النموذج في الوقت الفعلي</span>244 </div>245 <div style="height: 280px; width: 100%;">246 <canvas id="pulseChart"></canvas>247 </div>248 <div class="terminal" id="terminal">249 <div>> System Ready.</div>250 <div>> Waiting for stream...</div>251 </div>252 </div>253 254 <!-- Right: Human Audit Queue -->255 <div class="card">256 <div class="card-title">257 <i class="fas fa-user-shield"></i>258 <span>قائمة الانتظار للتدقيق البشري</span>259 </div>260 <div style="margin-bottom: 10px; font-size: 0.8rem; color: #7f8c8d;">261 هذه الصور شك فيها النظام وتحتاج تأكيد بشري لتدريب الموديل.262 </div>263 <div class="queue-container" id="queueList">264 <!-- سيتم إضافة العناصر هنا بواسطة JavaScript -->265 <div style="text-align: center; padding: 20px; color: #bdc3c7;">266 <i class="fas fa-check-circle fa-2x"></i>267 <p>لا توجد حالات مشبوهة حالياً</p>268 </div>269 </div>270 </div>271 272 </section>273 274 </main>275 276 <script>277 // Clock278 setInterval(() => {279 document.getElementById('clock').innerText = new Date().toLocaleTimeString('ar-EG');280 }, 1000);281 282 // --- إعداد الرسم البياني (Chart.js) ---283 const ctx = document.getElementById('pulseChart').getContext('2d');284 let pulseChart = new Chart(ctx, {285 type: 'line',286 data: {287 labels: Array(20).fill(''), 288 datasets: [{289 label: 'Efficiency',290 data: Array(20).fill(99),291 borderColor: '#0f3460',292 backgroundColor: 'rgba(15, 52, 96, 0.05)',293 borderWidth: 2,294 tension: 0.4,295 fill: true,296 pointRadius: 0297 }]298 },299 options: {300 responsive: true,301 maintainAspectRatio: false,302 animation: { duration: 0 }, // Disable animation for real-time performance303 plugins: { legend: { display: false } },304 scales: { 305 x: { display: false }, 306 y: { 307 min: 80, max: 100, 308 grid: { color: '#f0f0f0' } 309 } 310 }311 }312 });313 314 // --- الاتصال بالباك إند وجلب البيانات ---315 316 // 1. جلب الإحصائيات (Stats)317 async function fetchLiveStats() {318 try {319 const res = await fetch('/api/stats');320 const data = await res.json();321 322 // تحديث الأرقام323 document.getElementById('stat-total').innerText = data.total_requests;324 document.getElementById('stat-accuracy').innerText = data.accuracy + '%';325 document.getElementById('stat-accepted').innerText = data.accepted_count;326 document.getElementById('stat-suspicious').innerText = data.suspicious_count;327 328 // تحديث الشارت329 pulseChart.data.datasets[0].data.shift();330 pulseChart.data.datasets[0].data.push(data.accuracy);331 pulseChart.update();332 333 // تحديث الـ Terminal334 if(data.logs && data.logs.length > 0) {335 const term = document.getElementById('terminal');336 const lastLog = data.logs[data.logs.length - 1];337 const div = document.createElement('div');338 div.innerText = `> ${lastLog}`;339 div.style.color = '#fff';340 div.style.marginBottom = '2px';341 term.appendChild(div);342 term.scrollTop = term.scrollHeight;343 }344 345 // تحديث شريط الأخبار العلوية346 if(data.logs.length > 0) {347 const lastLog = data.logs[data.logs.length - 1];348 document.getElementById('log-stream-1').innerText = `[LIVE] ${lastLog}`;349 }350 351 } catch (e) { console.log("Connection Pending..."); }352 }353 354 // 2. جلب قائمة المشبوهين (Queue)355 async function fetchQueue() {356 try {357 const res = await fetch('/api/queue');358 const queue = await res.json();359 const container = document.getElementById('queueList');360 361 container.innerHTML = ''; // تفريغ القائمة الحالية362 363 if (queue.length === 0) {364 container.innerHTML = `365 <div style="text-align: center; padding: 20px; color: #27ae60;">366 <i class="fas fa-check-circle fa-2x"></i>367 <p>النظام يعمل بكفاءة، لا توجد حالات مشبوهة</p>368 </div>`;369 return;370 }371 372 // عرض كل عنصر في القائمة373 queue.forEach(item => {374 const div = document.createElement('div');375 div.className = 'queue-item';376 // استخدام صورة عشوائية للتجربة لأن الباك إند محاكاة377 const imgSrc = item.img_data || `https://picsum.photos/seed/${item.id}/300/200.jpg`;378 379 div.innerHTML = `380 <div class="queue-header">381 <span><i class="fas fa-clock"></i> ${item.timestamp}</span>382 <span><i class="fas fa-user"></i> ${item.name}</span>383 </div>384 <img src="${imgSrc}" class="queue-img" alt="Suspicious Document">385 <div class="btn-group">386 <button class="btn btn-approve" onclick="handleAudit(${item.id}, 'approve')">387 <i class="fas fa-check"></i> أصلي388 </button>389 <button class="btn btn-reject" onclick="handleAudit(${item.id}, 'reject')">390 <i class="fas fa-times"></i> مزور391 </button>392 </div>393 `;394 container.appendChild(div);395 });396 397 } catch (e) { console.log("Queue Fetch Error", e); }398 }399 400 // 3. إرسال قرار التدقيق (Audit Action)401 async function handleAudit(id, action) {402 try {403 const res = await fetch('/api/audit/fix', {404 method: 'POST',405 headers: { 'Content-Type': 'application/json' },406 body: JSON.stringify({ action: action, id: id })407 });408 409 // تحديث فوري للواجهة (إزالة العنصر)410 const btn = event.currentTarget;411 btn.parentElement.parentElement.remove();412 413 // إظهار رسالة بسيطة414 alert(`تم تسجيل القرار: ${action === 'approve' ? 'أصلي' : 'مزور'}`);415 416 } catch (e) {417 alert('فشل إرسال القرار');418 }419 }420 421 // تشغيل التحديثات التلقائية422 setInterval(fetchLiveStats, 2000); // كل ثانيتين للإحصائيات423 setInterval(fetchQueue, 3000); // كل 3 ثواني للقائمة424 425 // استدعاء فوري عند التحميل426 fetchLiveStats();427 fetchQueue();428 429 </script>430</body>431</html>