Update: 2026-06-29 23:09:43
This commit is contained in:
190
loction_server/siro/ride/driversLocation.html
Executable file
190
loction_server/siro/ride/driversLocation.html
Executable 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>
|
||||
Reference in New Issue
Block a user