Update: 2026-06-29 23:09:43

This commit is contained in:
Hamza-Ayed
2026-06-29 23:09:43 +03:00
parent 65b2e68154
commit 3506b07bc7
42 changed files with 8252 additions and 0 deletions

View File

@@ -0,0 +1,190 @@
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>تتبع السائقين - Tripz</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<style>
body { margin: 0; padding: 0; font-family: 'Segoe UI', Tahoma, sans-serif; overflow: hidden; }
#map { height: 100vh; width: 100%; z-index: 1; }
/* تصميم لوحة التحكم */
.dashboard {
position: absolute; top: 20px; right: 20px; width: 280px;
background: rgba(255, 255, 255, 0.95); padding: 15px;
border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.15);
z-index: 1000; text-align: right; border: 1px solid #ddd;
}
.dashboard h2 { margin: 0 0 10px 0; font-size: 16px; color: #333; border-bottom: 2px solid #3498db; padding-bottom: 8px; }
/* أزرار التبديل */
.mode-switcher { display: flex; gap: 5px; margin-bottom: 15px; }
.mode-btn {
flex: 1; padding: 8px; border: 1px solid #3498db; background: white;
color: #3498db; cursor: pointer; border-radius: 4px; font-size: 12px; transition: 0.2s;
}
.mode-btn.active { background: #3498db; color: white; font-weight: bold; }
/* الإحصائيات */
.info-row { display: flex; justify-content: space-between; margin-bottom: 5px; font-size: 13px; }
.val-active { color: #27ae60; font-weight: bold; }
.update-time { font-size: 11px; color: #7f8c8d; text-align: center; margin-top: 10px; display: block; }
/* زر التحديث */
.refresh-btn {
width: 100%; margin-top: 8px; padding: 8px; background: #2c3e50;
color: white; border: none; border-radius: 4px; cursor: pointer;
}
.refresh-btn:hover { background: #34495e; }
/* أيقونة السيارة */
.car-wrapper { transition: transform 0.5s ease; }
.car-svg { width: 35px; height: 35px; filter: drop-shadow(0px 2px 2px rgba(0,0,0,0.3)); }
/* Popup */
.popup-content { text-align: right; font-size: 12px; }
</style>
</head>
<body>
<div id="map"></div>
<div class="dashboard">
<h2>نظام التتبع المباشر</h2>
<div class="mode-switcher">
<button class="mode-btn active" id="btnLive" onclick="setMode('live')">مباشر (20د)</button>
<button class="mode-btn" id="btnDay" onclick="setMode('day')">اليوم كامل</button>
</div>
<div class="info-row">
<span>الوضع:</span>
<span id="modeLabel" style="font-weight:bold; color:#2980b9;">مباشر</span>
</div>
<div class="info-row">
<span>السائقين:</span>
<span id="countVal" class="val-active">0</span>
</div>
<small id="statusMsg" class="update-time">جاري التحميل...</small>
<button class="refresh-btn" onclick="fetchData()">تحديث البيانات</button>
</div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
// ================= إعدادات النظام =================
const BASE_URL = "https://location.intaleq.xyz/intaleq/ride/";
let currentMode = 'live';
// إعداد الخريطة
const map = L.map('map').setView([33.513, 36.276], 10);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Tripz System'
}).addTo(map);
const markersGroup = L.layerGroup().addTo(map);
// ================= دوال التحكم =================
function setMode(mode) {
currentMode = mode;
// تحديث الأزرار
document.getElementById('btnLive').className = mode === 'live' ? 'mode-btn active' : 'mode-btn';
document.getElementById('btnDay').className = mode === 'day' ? 'mode-btn active' : 'mode-btn';
// تحديث البيانات
fetchData();
}
function fetchData() {
const statusElem = document.getElementById('statusMsg');
statusElem.innerText = "جاري الاتصال بالسيرفر...";
statusElem.style.color = "#7f8c8d";
// تحديد اسم الملف
const fileName = currentMode === 'day' ? 'locations_day.json' : 'locations_live.json';
const finalUrl = BASE_URL + fileName + '?t=' + Date.now(); // Cache busting
fetch(finalUrl)
.then(response => {
// التحقق من أن الملف موجود
if (!response.ok) {
throw new Error("الملف غير موجود (404)");
}
// التحقق من نوع المحتوى (لتجنب Hello World)
const contentType = response.headers.get("content-type");
if (contentType && contentType.indexOf("application/json") === -1) {
throw new Error("البيانات ليست JSON (الرجاء تشغيل ملف PHP أولاً)");
}
return response.json();
})
.then(data => {
renderMap(data);
statusElem.innerText = "آخر تحديث: " + (data.last_updated || "الآن");
})
.catch(err => {
console.error("Error:", err);
statusElem.innerText = "خطأ: " + err.message;
statusElem.style.color = "#e74c3c";
// لا نمسح الخريطة عند الخطأ للحفاظ على آخر عرض
});
}
function renderMap(json) {
markersGroup.clearLayers();
const drivers = json.drivers || [];
document.getElementById('countVal').innerText = json.count || drivers.length;
document.getElementById('modeLabel').innerText = json.title || (currentMode=='day'?'يومي':'مباشر');
let bounds = [];
drivers.forEach(d => {
// البحث الذكي عن الإحداثيات
let lat = parseFloat(d.lat || d.latitude || d.Lat || d.LAT);
let lon = parseFloat(d.lon || d.lng || d.longitude || d.long || d.Lon || d.LNG);
if (!isNaN(lat) && !isNaN(lon) && lat !== 0 && lon !== 0) {
bounds.push([lat, lon]);
const color = currentMode === 'live' ? '#27ae60' : '#2980b9'; // أخضر للمباشر، أزرق لليومي
const heading = d.heading || 0;
const iconHtml = `
<div class="car-wrapper" style="transform: rotate(${heading}deg);">
<svg class="car-svg" viewBox="0 0 24 24" fill="${color}">
<path d="M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z"/>
</svg>
</div>`;
const icon = L.divIcon({ className: '', html: iconHtml, iconSize: [35, 35], iconAnchor: [17.5, 17.5] });
L.marker([lat, lon], {icon: icon})
.bindPopup(`
<div class="popup-content">
<strong>ID:</strong> ${d.driver_id || d.id}<br>
<strong>السرعة:</strong> ${d.speed || 0}<br>
<strong>الوقت:</strong> ${d.updated_at}
</div>
`)
.addTo(markersGroup);
}
});
// توجيه الكاميرا تلقائياً (Auto Zoom)
if (bounds.length > 0) {
map.fitBounds(bounds, { padding: [50, 50] });
}
}
// بدء التشغيل
fetchData();
// تحديث تلقائي كل 15 ثانية
setInterval(fetchData, 15000);
</script>
</body>
</html>