|
<!DOCTYPE html> |
|
<html lang="ja"> |
|
<head> |
|
<meta charset="UTF-8" /> |
|
<title>IPアクセス履歴管理</title> |
|
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" crossorigin="" /> |
|
<script src="https://soiz1-eruda3.hf.space/eruda.js"></script> |
|
<script>eruda.init();</script> |
|
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" crossorigin=""></script> |
|
<style> |
|
#map { height: 400px; width: 100%; margin-bottom: 20px; } |
|
table { border-collapse: collapse; width: 100%; } |
|
th, td { border: 1px solid #ccc; padding: 8px; text-align: left; } |
|
th { background-color: #f0f0f0; } |
|
</style> |
|
</head> |
|
<body> |
|
<h1>アクセスログ一覧</h1> |
|
<div id="map"></div> |
|
<table> |
|
<thead> |
|
<tr> |
|
<th>Socket ID</th> |
|
<th>IPアドレス</th> |
|
<th>接続時間</th> |
|
<th>位置情報</th> |
|
<th>都市</th> |
|
<th>地域</th> |
|
<th>国</th> |
|
</tr> |
|
</thead> |
|
<tbody id="table-body"></tbody> |
|
</table> |
|
|
|
<script> |
|
const map = L.map('map').setView([35.681236, 139.767125], 4); |
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { |
|
maxZoom: 18, |
|
attribution: '© OpenStreetMap contributors' |
|
}).addTo(map); |
|
|
|
async function loadSessions() { |
|
const res = await fetch('https://soiz1-websocket.hf.space/api/sessions'); |
|
const data = await res.json(); |
|
renderTable(data); |
|
renderMap(data); |
|
} |
|
|
|
function renderTable(sessions) { |
|
const tbody = document.getElementById('table-body'); |
|
tbody.innerHTML = ''; |
|
|
|
sessions.forEach(session => { |
|
const tr = document.createElement('tr'); |
|
tr.innerHTML = ` |
|
<td>${session.socketId}</td> |
|
<td>${session.ip}</td> |
|
<td>${new Date(session.connectTime).toLocaleString()}</td> |
|
<td>${session.loc || '-'}</td> |
|
<td>${session.city || '-'}</td> |
|
<td>${session.region || '-'}</td> |
|
<td>${session.country || '-'}</td> |
|
`; |
|
tbody.appendChild(tr); |
|
}); |
|
} |
|
|
|
function renderMap(sessions) { |
|
const markers = sessions |
|
.filter(s => s.loc) |
|
.map(s => { |
|
const [lat, lon] = s.loc.split(',').map(Number); |
|
return L.circleMarker([lat, lon], { |
|
radius: 8, |
|
fillColor: 'blue', |
|
color: '#000', |
|
weight: 1, |
|
opacity: 1, |
|
fillOpacity: 0.8 |
|
}).bindPopup(` |
|
IP: ${s.ip}<br> |
|
都市: ${s.city}<br> |
|
地域: ${s.region}<br> |
|
国: ${s.country} |
|
`).addTo(map); |
|
}); |
|
|
|
if (markers.length > 0) { |
|
const group = L.featureGroup(markers); |
|
map.fitBounds(group.getBounds().pad(0.5)); |
|
} |
|
} |
|
|
|
loadSessions(); |
|
</script> |
|
</body> |
|
</html> |
|
|