koishi-plugin-ets2-tools-tmp 2.5.91 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/lib/command/ets-app/addMember/addMemberV2.js +93 -0
  2. package/lib/command/ets-app/changePoint/changePoint.js +14 -0
  3. package/lib/command/ets-app/changePoint/changePointV1.js +3 -0
  4. package/lib/command/ets-app/changePoint/changePointV2.js +91 -0
  5. package/lib/command/ets-app/queryPoint/queryPoint.js +38 -0
  6. package/lib/command/ets-app/queryPoint/queryPointV1.js +51 -0
  7. package/lib/command/ets-app/queryPoint/queryPointV2.js +51 -0
  8. package/lib/command/ets-app/resetPassword/resetPassword.js +20 -0
  9. package/lib/command/ets-app/resetPassword/resetPasswordV1.js +115 -0
  10. package/lib/command/ets-app/resetPassword/resetPasswordV2.js +71 -0
  11. package/lib/command/tmpActivityService/tmpActivityServiceV1.js +71 -0
  12. package/lib/command/tmpActivityService/tmpActivityServiceV2.js +85 -0
  13. package/lib/command/tmpActivityService.js +13 -120
  14. package/lib/command/tmpDlcMap.js +1 -1
  15. package/lib/command/tmpFootprint.js +1 -1
  16. package/lib/command/tmpMileageRanking.js +1 -1
  17. package/lib/command/tmpPosition.js +1 -1
  18. package/lib/command/tmpServer/tmpServer.d.ts +2 -0
  19. package/lib/command/tmpServer/tmpServer.js +15 -0
  20. package/lib/command/tmpServer/tmpServerImg.d.ts +3 -0
  21. package/lib/command/tmpServer/tmpServerImg.js +35 -0
  22. package/lib/command/tmpServer/tmpServerText.d.ts +2 -0
  23. package/lib/command/tmpServer/tmpServerText.js +33 -0
  24. package/lib/command/tmpTraffic/tmpTrafficMap.js +1 -1
  25. package/lib/index.js +50 -15
  26. package/lib/resource/dlc.html +1 -1
  27. package/lib/resource/footprint.html +2 -2
  28. package/lib/resource/position.html +1 -1
  29. package/lib/resource/server-list.html +298 -0
  30. package/lib/resource/traffic.html +1 -1
  31. package/package.json +1 -1
@@ -0,0 +1,298 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Server List</title>
6
+ <style>
7
+ * {
8
+ margin: 0;
9
+ padding: 0;
10
+ box-sizing: border-box;
11
+ }
12
+ body {
13
+ font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
14
+ background-color: #0b1120;
15
+ }
16
+ #container {
17
+ width: 380px;
18
+ background: linear-gradient(180deg, #0f1a2e 0%, #0b1120 100%);
19
+ padding: 0 0 6px 0;
20
+ }
21
+
22
+ /* Header */
23
+ .header {
24
+ height: 42px;
25
+ background-color: rgba(0, 0, 0, 0.3);
26
+ display: flex;
27
+ align-items: center;
28
+ justify-content: center;
29
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4);
30
+ }
31
+ .header .title {
32
+ color: #8bafff;
33
+ font-size: 14px;
34
+ font-weight: 600;
35
+ letter-spacing: 1px;
36
+ }
37
+
38
+ /* Server list */
39
+ .server-list {
40
+ padding: 6px 10px 0 10px;
41
+ display: flex;
42
+ flex-direction: column;
43
+ gap: 5px;
44
+ }
45
+
46
+ /* Server card */
47
+ .server-card {
48
+ background: rgba(22, 33, 55, 0.8);
49
+ border-radius: 6px;
50
+ border: 1px solid rgba(139, 175, 255, 0.08);
51
+ overflow: hidden;
52
+ }
53
+
54
+ /* Card info */
55
+ .server-info {
56
+ padding: 7px 12px 5px 12px;
57
+ }
58
+ .server-row {
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: space-between;
62
+ }
63
+ .server-left {
64
+ display: flex;
65
+ align-items: center;
66
+ gap: 6px;
67
+ flex: 1;
68
+ min-width: 0;
69
+ }
70
+ .status-indicator {
71
+ width: 6px;
72
+ height: 6px;
73
+ border-radius: 50%;
74
+ flex-shrink: 0;
75
+ }
76
+ .status-indicator.online {
77
+ background-color: #34d058;
78
+ box-shadow: 0 0 5px rgba(52, 208, 88, 0.5);
79
+ }
80
+ .status-indicator.offline {
81
+ background-color: #484f58;
82
+ }
83
+ .server-name {
84
+ color: #e6edf3;
85
+ font-size: 13px;
86
+ font-weight: 600;
87
+ white-space: nowrap;
88
+ overflow: hidden;
89
+ text-overflow: ellipsis;
90
+ max-width: 200px;
91
+ }
92
+ .player-count {
93
+ color: #6e7a8a;
94
+ font-size: 11px;
95
+ white-space: nowrap;
96
+ flex-shrink: 0;
97
+ margin-left: 6px;
98
+ }
99
+ .player-count .num {
100
+ color: #c9d1d9;
101
+ font-weight: 700;
102
+ font-size: 12px;
103
+ }
104
+
105
+ /* Features row */
106
+ .features {
107
+ display: flex;
108
+ align-items: center;
109
+ gap: 8px;
110
+ margin-top: 3px;
111
+ }
112
+ .feature {
113
+ font-size: 10px;
114
+ color: #5a6572;
115
+ white-space: nowrap;
116
+ }
117
+
118
+ /* Queue badge */
119
+ .queue-badge {
120
+ color: #f0883e;
121
+ font-size: 10px;
122
+ margin-left: 6px;
123
+ }
124
+
125
+ /* Chart area */
126
+ .chart-area {
127
+ position: relative;
128
+ height: 38px;
129
+ }
130
+ .chart-area svg {
131
+ display: block;
132
+ width: 100%;
133
+ height: 100%;
134
+ }
135
+
136
+ </style>
137
+ </head>
138
+ <body>
139
+ <div id="container">
140
+ <div class="header">
141
+ <div class="title">TruckersMP 服务器状态</div>
142
+ </div>
143
+
144
+ <div class="server-list" id="server-list"></div>
145
+
146
+ </div>
147
+
148
+ <script>
149
+ /**
150
+ * 构建 SVG 面积折线图
151
+ * maxPlayer 的 50% 作为余量,上限不超过 maxPlayer
152
+ */
153
+ function buildChartSVG(data, width, height, maxPlayer) {
154
+ const padTop = 2;
155
+ const padBottom = 0;
156
+ const chartW = width;
157
+ const chartH = height - padTop - padBottom;
158
+
159
+ const dataMax = Math.max(...data, 1);
160
+ const max = Math.min(maxPlayer, maxPlayer * 0.12 + dataMax);
161
+ const step = chartW / (data.length - 1);
162
+
163
+ const points = data.map((v, i) => {
164
+ const x = i * step;
165
+ const y = padTop + chartH - (v / max) * chartH;
166
+ return [x, y];
167
+ });
168
+
169
+ const lineD = points.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' ');
170
+ const areaD = lineD
171
+ + ` L${points[points.length - 1][0]},${padTop + chartH}`
172
+ + ` L${points[0][0]},${padTop + chartH} Z`;
173
+
174
+ const gid = 'g' + Math.random().toString(36).slice(2, 8);
175
+
176
+ return `
177
+ <svg viewBox="0 0 ${width} ${height}" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
178
+ <defs>
179
+ <linearGradient id="${gid}" x1="0" y1="0" x2="0" y2="1">
180
+ <stop offset="0%" stop-color="rgba(79,139,255,0.4)"/>
181
+ <stop offset="100%" stop-color="rgba(79,139,255,0.02)"/>
182
+ </linearGradient>
183
+ </defs>
184
+ <path d="${areaD}" fill="url(#${gid})"/>
185
+ <path d="${lineD}" fill="none" stroke="#4f8bff" stroke-width="1.5" stroke-linejoin="round"/>
186
+ </svg>`;
187
+ }
188
+
189
+ /**
190
+ * 将 playerHistory 标准化为 288 个点(24h,每5分钟一个点)
191
+ * 缺失的时间段填充为 0
192
+ * @param {Array<{updateTime: string, playerCount: number}>} playerHistory
193
+ */
194
+ function normalizeHistory(playerHistory) {
195
+ const SLOT_COUNT = 288;
196
+ const SLOT_MS = 300000;
197
+
198
+ if (!playerHistory || playerHistory.length === 0) return [];
199
+
200
+ // API 返回的是北京时间(UTC+8),用 Date.UTC 生成时间戳再减去8小时偏移
201
+ function parseTime(str) {
202
+ const [datePart, timePart] = str.trim().replace('T', ' ').split(' ');
203
+ const [y, m, d] = datePart.split('-').map(Number);
204
+ const parts = timePart.split(':').map(Number);
205
+ const h = parts[0] || 0, min = parts[1] || 0;
206
+ return Date.UTC(y, m - 1, d, h, min, 0) - 8 * 3600000;
207
+ }
208
+
209
+ const now = Date.now();
210
+ const currentSlot = Math.floor(now / SLOT_MS) * SLOT_MS;
211
+
212
+ const dataMap = {};
213
+ for (const item of playerHistory) {
214
+ const ts = parseTime(item.updateTime);
215
+ if (isNaN(ts)) continue;
216
+ const slot = Math.floor(ts / SLOT_MS) * SLOT_MS;
217
+ dataMap[slot] = item.playerCount;
218
+ }
219
+
220
+ const result = [];
221
+ for (let i = 0; i < SLOT_COUNT; i++) {
222
+ const slotTime = currentSlot - (SLOT_COUNT - 1 - i) * SLOT_MS;
223
+ result.push(dataMap[slotTime] !== undefined ? dataMap[slotTime] : 0);
224
+ }
225
+
226
+ return result;
227
+ }
228
+
229
+ /**
230
+ * 渲染一个服务器卡片
231
+ */
232
+ function createServerCard(server) {
233
+ const card = document.createElement('div');
234
+ card.className = 'server-card';
235
+
236
+ // 只展示存在的特性
237
+ let featuresHTML = '';
238
+ if (server.collisionsEnable === 1) {
239
+ featuresHTML += '<span class="feature">💥 碰撞</span>';
240
+ }
241
+ if (server.afkEnable === 0) {
242
+ featuresHTML += '<span class="feature">💤 挂机</span>';
243
+ }
244
+ if (server.policeCarEnable === 1) {
245
+ featuresHTML += '<span class="feature">🚓 警车</span>';
246
+ }
247
+ if (server.speedLimiterEnable === 1) {
248
+ featuresHTML += '<span class="feature">🐢 限速</span>';
249
+ }
250
+
251
+ // 队列
252
+ let queueText = '';
253
+ if (server.queueCount > 0) {
254
+ queueText = `<span class="queue-badge">队列 ${server.queueCount}</span>`;
255
+ }
256
+
257
+ card.innerHTML = `
258
+ <div class="server-info">
259
+ <div class="server-row">
260
+ <div class="server-left">
261
+ <span class="status-indicator ${server.isOnline === 1 ? 'online' : 'offline'}"></span>
262
+ <span class="server-name">${server.serverName}</span>
263
+ </div>
264
+ <span class="player-count"><span class="num">${server.playerCount}</span> / ${server.maxPlayer}${queueText}</span>
265
+ </div>
266
+ ${featuresHTML ? '<div class="features">' + featuresHTML + '</div>' : ''}
267
+ </div>
268
+ <div class="chart-area">
269
+ ${server.isOnline === 1 && server.playerHistory && server.playerHistory.length > 0
270
+ ? (() => {
271
+ const normalized = normalizeHistory(server.playerHistory);
272
+ return normalized.length > 0 ? buildChartSVG(normalized, 380, 38, server.maxPlayer) : '';
273
+ })()
274
+ : ''}
275
+ </div>`;
276
+
277
+ return card;
278
+ }
279
+
280
+ /**
281
+ * 主渲染函数
282
+ */
283
+ function setData(apiData) {
284
+ if (!apiData || !apiData.data) return;
285
+
286
+ const servers = apiData.data;
287
+ const listEl = document.getElementById('server-list');
288
+
289
+ listEl.innerHTML = '';
290
+
291
+ servers.forEach(server => {
292
+ listEl.appendChild(createServerCard(server));
293
+ });
294
+ }
295
+
296
+ </script>
297
+ </body>
298
+ </html>
@@ -204,4 +204,4 @@
204
204
  }
205
205
  </script>
206
206
  </body>
207
- </html>
207
+ </html>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-ets2-tools-tmp",
3
3
  "description": "欧卡2 TruckersMP信息查询、车队平台查询及活动提醒",
4
- "version": "2.5.91",
4
+ "version": "3.0.0",
5
5
  "contributors": [
6
6
  "opwop <slhp1013@qq.com>",
7
7
  "bot_actions <168329908@qq.com>"