soiz1 commited on
Commit
f30da11
·
1 Parent(s): b8cd5cf

Update web-socket.html

Browse files
Files changed (1) hide show
  1. web-socket.html +73 -159
web-socket.html CHANGED
@@ -1,181 +1,95 @@
1
  <!DOCTYPE html>
2
  <html lang="ja">
3
  <head>
4
- <script src="https://soiz1-eruda3.hf.space/eruda.js"></script>
5
- <script>eruda.init();</script>
6
- <meta charset="UTF-8" />
7
- <title>管理ページ(IP・接続時間表示 + 地図表示)</title>
8
- <script src="https://cdn.socket.io/4.0.1/socket.io.min.js"></script>
9
- <link
10
- rel="stylesheet"
11
- href="https://unpkg.com/[email protected]/dist/leaflet.css"
12
- crossorigin=""
13
- />
14
- <script
15
- src="https://unpkg.com/[email protected]/dist/leaflet.js"
16
- crossorigin=""
17
- ></script>
18
- <style>
19
- #map {
20
- height: 400px;
21
- width: 100%;
22
- border: 1px solid #ccc;
23
- margin-bottom: 20px;
24
- }
25
- table {
26
- border-collapse: collapse;
27
- width: 100%;
28
- margin-bottom: 20px;
29
- }
30
- th, td {
31
- border: 1px solid #ccc;
32
- padding: 8px;
33
- text-align: left;
34
- }
35
- th {
36
- background-color: #eee;
37
- }
38
- .highlight {
39
- background-color: #f99;
40
- transition: background-color 1s ease;
41
- }
42
- </style>
43
  </head>
44
  <body>
45
- <div id="map"></div>
46
-
47
- <h1>現在の接続ユーザー数: <span id="userCount">0</span></h1>
48
- <div>更新はページ再読み込みで行います。</div>
49
- <table>
50
  <thead>
51
- <tr>
52
  <th>Socket ID</th>
53
  <th>IPアドレス</th>
54
  <th>接続時間</th>
55
- <th>切断時間</th>
56
  <th>位置情報</th>
57
  <th>都市</th>
58
  <th>地域</th>
59
  <th>国</th>
60
- </tr>
61
  </thead>
62
- <tbody id="userTableBody"></tbody>
63
- </table>
64
-
65
- <script>
66
- const socket = io("https://web-socket-server-14ap.onrender.com/", {
67
- query: {
68
- isAdmin: true // 管理画面からの接続であることを示す
 
 
 
 
 
 
 
 
69
  }
70
- });
71
-
72
- const STORAGE_KEY = "userSessions";
73
-
74
- // 過去・現在含む全セッション情報を管理
75
- let allSessions = JSON.parse(localStorage.getItem(STORAGE_KEY) || "{}");
76
-
77
- const userCountElem = document.getElementById("userCount");
78
- const tbody = document.getElementById("userTableBody");
79
-
80
- const map = L.map('map').setView([35.681236, 139.767125], 5);
81
- L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
82
- maxZoom: 18,
83
- attribution: '© OpenStreetMap contributors'
84
- }).addTo(map);
85
 
86
- let markers = {};
87
-
88
- function createCircleMarker(lat, lon, color, popupText) {
89
- return L.circleMarker([lat, lon], {
90
- radius: 10,
91
- fillColor: color,
92
- color: '#000',
93
- weight: 1,
94
- opacity: 1,
95
- fillOpacity: 0.9
96
- }).bindPopup(popupText);
97
- }
98
-
99
- // ユーザー数更新
100
- socket.on("updateUserCount", (count) => {
101
- userCountElem.textContent = count;
102
- });
103
-
104
- // 現在接続中のセッション更新(リアルタイム)
105
- socket.on("userSessionsUpdate", (userSessions) => {
106
- // 現在のセッションをallSessionsにマージ(上書き)
107
- for (const [socketId, info] of Object.entries(userSessions)) {
108
- allSessions[socketId] = info;
109
  }
110
- renderTable(allSessions);
111
- });
112
 
113
- // 過去セッション履歴受信時
114
- socket.on("userSessionHistory", (sessionHistory) => {
115
- // 履歴の各セッションをallSessionsに追加(既存のsocketIdを上書きしない)
116
- for (const session of sessionHistory) {
117
- if (!allSessions[session.socketId]) {
118
- allSessions[session.socketId] = session;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  }
120
  }
121
- renderTable(allSessions);
122
- });
123
-
124
- function renderTable(sessions) {
125
- tbody.innerHTML = "";
126
-
127
- // 既存マーカー削除
128
- for (let key in markers) {
129
- map.removeLayer(markers[key]);
130
- }
131
- markers = {};
132
-
133
- for (const [socketId, info] of Object.entries(sessions)) {
134
- const tr = document.createElement("tr");
135
-
136
- function createTd(text) {
137
- const td = document.createElement("td");
138
- td.textContent = text;
139
- return td;
140
- }
141
-
142
- tr.appendChild(createTd(socketId));
143
- tr.appendChild(createTd(info.ip || "-"));
144
- tr.appendChild(createTd(info.connectTime ? new Date(info.connectTime).toLocaleString() : "-"));
145
- tr.appendChild(createTd(info.disconnectTime ? new Date(info.disconnectTime).toLocaleString() : "-"));
146
- tr.appendChild(createTd(info.loc || "-"));
147
- tr.appendChild(createTd(info.city || "-"));
148
- tr.appendChild(createTd(info.region || "-"));
149
- tr.appendChild(createTd(info.country || "-"));
150
-
151
- tbody.appendChild(tr);
152
-
153
- // 位置情報がある場合は地図にマーカーを追加
154
- if (info.loc) {
155
- const [lat, lon] = info.loc.split(',').map(Number);
156
- const locationText = [
157
- `SocketID: ${socketId}`,
158
- `IP: ${info.ip || "-"}`,
159
- `都市: ${info.city || "-"}`,
160
- `地域: ${info.region || "-"}`,
161
- `国: ${info.country || "-"}`
162
- ].join('<br>');
163
-
164
- const marker = createCircleMarker(lat, lon, 'blue', locationText);
165
- marker.addTo(map);
166
- markers[socketId] = marker;
167
- }
168
- }
169
-
170
- // マーカーがあれば地図を調整
171
- if (Object.keys(markers).length > 0) {
172
- const group = L.featureGroup(Object.values(markers));
173
- map.fitBounds(group.getBounds().pad(0.5));
174
- }
175
 
176
- // ローカルストレージに保存
177
- localStorage.setItem(STORAGE_KEY, JSON.stringify(sessions));
178
- }
179
- </script>
180
  </body>
181
- </html>
 
1
  <!DOCTYPE html>
2
  <html lang="ja">
3
  <head>
4
+ <meta charset="UTF-8" />
5
+ <title>IPアクセス履歴管理</title>
6
+ <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" crossorigin="" />
7
+ <script src="https://unpkg.com/[email protected]/dist/leaflet.js" crossorigin=""></script>
8
+ <style>
9
+ #map { height: 400px; width: 100%; margin-bottom: 20px; }
10
+ table { border-collapse: collapse; width: 100%; }
11
+ th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
12
+ th { background-color: #f0f0f0; }
13
+ </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  </head>
15
  <body>
16
+ <h1>アクセスログ一覧</h1>
17
+ <div id="map"></div>
18
+ <table>
 
 
19
  <thead>
20
+ <tr>
21
  <th>Socket ID</th>
22
  <th>IPアドレス</th>
23
  <th>接続時間</th>
 
24
  <th>位置情報</th>
25
  <th>都市</th>
26
  <th>地域</th>
27
  <th>国</th>
28
+ </tr>
29
  </thead>
30
+ <tbody id="table-body"></tbody>
31
+ </table>
32
+
33
+ <script>
34
+ const map = L.map('map').setView([35.681236, 139.767125], 4);
35
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
36
+ maxZoom: 18,
37
+ attribution: '© OpenStreetMap contributors'
38
+ }).addTo(map);
39
+
40
+ async function loadSessions() {
41
+ const res = await fetch('/api/sessions');
42
+ const data = await res.json();
43
+ renderTable(data);
44
+ renderMap(data);
45
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
+ function renderTable(sessions) {
48
+ const tbody = document.getElementById('table-body');
49
+ tbody.innerHTML = '';
50
+
51
+ sessions.forEach(session => {
52
+ const tr = document.createElement('tr');
53
+ tr.innerHTML = `
54
+ <td>${session.socketId}</td>
55
+ <td>${session.ip}</td>
56
+ <td>${new Date(session.connectTime).toLocaleString()}</td>
57
+ <td>${session.loc || '-'}</td>
58
+ <td>${session.city || '-'}</td>
59
+ <td>${session.region || '-'}</td>
60
+ <td>${session.country || '-'}</td>
61
+ `;
62
+ tbody.appendChild(tr);
63
+ });
 
 
 
 
 
 
64
  }
 
 
65
 
66
+ function renderMap(sessions) {
67
+ const markers = sessions
68
+ .filter(s => s.loc)
69
+ .map(s => {
70
+ const [lat, lon] = s.loc.split(',').map(Number);
71
+ return L.circleMarker([lat, lon], {
72
+ radius: 8,
73
+ fillColor: 'blue',
74
+ color: '#000',
75
+ weight: 1,
76
+ opacity: 1,
77
+ fillOpacity: 0.8
78
+ }).bindPopup(`
79
+ IP: ${s.ip}<br>
80
+ 都市: ${s.city}<br>
81
+ 地域: ${s.region}<br>
82
+ 国: ${s.country}
83
+ `).addTo(map);
84
+ });
85
+
86
+ if (markers.length > 0) {
87
+ const group = L.featureGroup(markers);
88
+ map.fitBounds(group.getBounds().pad(0.5));
89
  }
90
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
+ loadSessions();
93
+ </script>
 
 
94
  </body>
95
+ </html>