soiz1 commited on
Commit
3436304
·
1 Parent(s): 045586e

Update web-socket.html

Browse files
Files changed (1) hide show
  1. web-socket.html +131 -135
web-socket.html CHANGED
@@ -1,65 +1,70 @@
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
- </tr>
 
 
 
 
57
  </thead>
58
  <tbody id="userTableBody"></tbody>
59
- </table>
60
 
61
- <script>
62
  const socket = io("https://web-socket-server-14ap.onrender.com/");
 
63
  const STORAGE_KEY = "userSessions";
64
 
65
  let previousSessions = JSON.parse(localStorage.getItem(STORAGE_KEY) || "{}");
@@ -69,109 +74,100 @@
69
 
70
  const map = L.map('map').setView([35.681236, 139.767125], 5);
71
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
72
- maxZoom: 18,
73
- attribution: '© OpenStreetMap contributors'
74
  }).addTo(map);
75
 
76
  let markers = {};
77
 
78
  function createCircleMarker(lat, lon, color, popupText) {
79
- return L.circleMarker([lat, lon], {
80
- radius: 10,
81
- fillColor: color,
82
- color: '#000',
83
- weight: 1,
84
- opacity: 1,
85
- fillOpacity: 0.9
86
- }).bindPopup(popupText);
87
  }
88
 
89
  socket.on("updateUserCount", (count) => {
90
- userCountElem.textContent = count;
91
  });
92
 
93
- socket.on("userSessionsUpdate", async (userSessions) => {
94
- console.log("userSessionsUpdate受信", userSessions);
95
-
96
- tbody.innerHTML = "";
97
 
98
- for (let key in markers) {
99
- map.removeLayer(markers[key]);
100
- }
101
- markers = {};
102
 
103
- const positions = {};
104
- for (const [socketId, info] of Object.entries(userSessions)) {
105
- if (info.loc) {
106
- const [lat, lon] = info.loc.split(',').map(parseFloat);
107
- if (!isNaN(lat) && !isNaN(lon)) {
108
- positions[socketId] = { lat, lon };
109
- }
110
  }
111
- }
112
-
113
- for (const [socketId, info] of Object.entries(userSessions)) {
114
- const tr = document.createElement("tr");
115
-
116
- function createTd(text, elementKey) {
117
- const td = document.createElement("td");
118
- td.textContent = text;
119
-
120
- const prevValue = previousSessions[socketId]?.[elementKey];
121
- const currValue = info[elementKey];
122
- const changed = prevValue !== currValue;
123
-
124
- if (changed) {
125
- td.classList.add("highlight");
126
- setTimeout(() => td.classList.remove("highlight"), 1000);
127
- }
128
-
129
- return td;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  }
131
 
132
- tr.appendChild(createTd(socketId, "socketId"));
133
- tr.appendChild(createTd(info.ip || "-", "ip"));
134
- tr.appendChild(createTd(info.connectTime ? new Date(info.connectTime).toLocaleString() : "-", "connectTime"));
135
- tr.appendChild(createTd(info.disconnectTime ? new Date(info.disconnectTime).toLocaleString() : "-", "disconnectTime"));
136
-
137
- tbody.appendChild(tr);
138
-
139
- const pos = positions[socketId];
140
- if (pos) {
141
- const prevPos = previousSessions[socketId]?.geoPosition;
142
- let changedPos = true;
143
- if (prevPos && Math.abs(prevPos.lat - pos.lat) < 0.0001 && Math.abs(prevPos.lon - pos.lon) < 0.0001) {
144
- changedPos = false;
145
- }
146
-
147
- const color = info.disconnectTime
148
- ? "gray"
149
- : changedPos
150
- ? "red"
151
- : "black";
152
-
153
- const marker = createCircleMarker(pos.lat, pos.lon, color, `SocketID: ${socketId}<br>IP: ${info.ip || "-"}`);
154
- marker.addTo(map);
155
- markers[socketId] = marker;
156
  }
157
- }
158
-
159
- const markerPositions = Object.values(markers).map(m => m.getLatLng());
160
- if (markerPositions.length > 0) {
161
- const group = L.featureGroup(Object.values(markers));
162
- map.fitBounds(group.getBounds().pad(0.5));
163
- }
164
-
165
- const sessionsToStore = {};
166
- for (const [socketId, info] of Object.entries(userSessions)) {
167
- sessionsToStore[socketId] = {
168
- ...info,
169
- geoPosition: positions[socketId] || null
170
- };
171
- }
172
- localStorage.setItem(STORAGE_KEY, JSON.stringify(sessionsToStore));
173
- previousSessions = sessionsToStore;
174
  });
175
- </script>
 
176
  </body>
177
- </html>
 
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
+
68
  const STORAGE_KEY = "userSessions";
69
 
70
  let previousSessions = JSON.parse(localStorage.getItem(STORAGE_KEY) || "{}");
 
74
 
75
  const map = L.map('map').setView([35.681236, 139.767125], 5);
76
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
77
+ maxZoom: 18,
78
+ attribution: '© OpenStreetMap contributors'
79
  }).addTo(map);
80
 
81
  let markers = {};
82
 
83
  function createCircleMarker(lat, lon, color, popupText) {
84
+ return L.circleMarker([lat, lon], {
85
+ radius: 10,
86
+ fillColor: color,
87
+ color: '#000',
88
+ weight: 1,
89
+ opacity: 1,
90
+ fillOpacity: 0.9
91
+ }).bindPopup(popupText);
92
  }
93
 
94
  socket.on("updateUserCount", (count) => {
95
+ userCountElem.textContent = count;
96
  });
97
 
98
+ socket.on("userSessionsUpdate", (userSessions) => {
99
+ console.log("userSessionsUpdate受信", userSessions);
 
 
100
 
101
+ tbody.innerHTML = "";
 
 
 
102
 
103
+ for (let key in markers) {
104
+ map.removeLayer(markers[key]);
 
 
 
 
 
105
  }
106
+ markers = {};
107
+
108
+ for (const [socketId, info] of Object.entries(userSessions)) {
109
+ const tr = document.createElement("tr");
110
+
111
+ function createTd(text, elementKey) {
112
+ const td = document.createElement("td");
113
+ td.textContent = text;
114
+
115
+ const prevValue = previousSessions[socketId] ? previousSessions[socketId][elementKey] : undefined;
116
+ const currValue = info[elementKey];
117
+
118
+ const changed = prevValue !== currValue;
119
+
120
+ if (changed) {
121
+ td.classList.add("highlight");
122
+ setTimeout(() => td.classList.remove("highlight"), 1000);
123
+ }
124
+
125
+ return td;
126
+ }
127
+
128
+ tr.appendChild(createTd(socketId, "socketId"));
129
+ tr.appendChild(createTd(info.ip || "-", "ip"));
130
+ tr.appendChild(createTd(info.connectTime ? new Date(info.connectTime).toLocaleString() : "-", "connectTime"));
131
+ tr.appendChild(createTd(info.disconnectTime ? new Date(info.disconnectTime).toLocaleString() : "-", "disconnectTime"));
132
+ tr.appendChild(createTd(info.loc || "-", "loc"));
133
+ tr.appendChild(createTd(info.city || "-", "city"));
134
+ tr.appendChild(createTd(info.region || "-", "region"));
135
+ tr.appendChild(createTd(info.country || "-", "country"));
136
+
137
+ tbody.appendChild(tr);
138
+
139
+ // 位置情報がある場合、地図にマーカーを追加
140
+ if (info.loc) {
141
+ const [lat, lon] = info.loc.split(',').map(Number);
142
+ const prevLoc = previousSessions[socketId]?.loc;
143
+ const changedPos = prevLoc !== info.loc;
144
+ const color = changedPos ? 'red' : 'blue';
145
+
146
+ const locationText = [
147
+ `SocketID: ${socketId}`,
148
+ `IP: ${info.ip || "-"}`,
149
+ `都市: ${info.city || "-"}`,
150
+ `地域: ${info.region || "-"}`,
151
+ `国: ${info.country || "-"}`
152
+ ].join('<br>');
153
+
154
+ const marker = createCircleMarker(lat, lon, color, locationText);
155
+ marker.addTo(map);
156
+ markers[socketId] = marker;
157
+ }
158
  }
159
 
160
+ // マーカーがある場合、地図を適切な範囲に調整
161
+ if (Object.keys(markers).length > 0) {
162
+ const group = L.featureGroup(Object.values(markers));
163
+ map.fitBounds(group.getBounds().pad(0.5));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  }
165
+
166
+ // セッション情報をローカルストレージに保存
167
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(userSessions));
168
+ previousSessions = userSessions;
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  });
170
+
171
+ </script>
172
  </body>
173
+ </html>