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

Update web-socket.html

Browse files
Files changed (1) hide show
  1. web-socket.html +135 -131
web-socket.html CHANGED
@@ -1,70 +1,65 @@
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,100 +69,109 @@
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>
 
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
 
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>