koishi-plugin-ets2-tools-tmp 3.4.6 → 3.5.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.
- package/lib/command/ets-app/changePoint/changePointV1.js +28 -7
- package/lib/command/ets-app/pointRanking/pointRanking.js +12 -5
- package/lib/command/ets-app/queryPoint/queryPoint.js +15 -1
- package/lib/command/ets-app/queryPoint/queryPointV1.js +21 -5
- package/lib/command/ets-app/resetPassword/resetPasswordV1.js +32 -3
- package/lib/command/tmpBind.js +41 -4
- package/lib/command/tmpDlcMap.js +1 -1
- package/lib/command/tmpFootprint.js +3 -2
- package/lib/command/tmpMileageRanking.js +74 -23
- package/lib/command/tmpPosition.js +3 -2
- package/lib/command/tmpQuery/tmpQuery.js +70 -1
- package/lib/command/tmpQuery/tmpQueryImg.js +4 -3
- package/lib/command/tmpQuery/tmpQueryText.js +4 -3
- package/lib/command/tmpServer/tmpServer.js +47 -3
- package/lib/command/tmpServer/tmpServerImg.js +1 -1
- package/lib/command/tmpTraffic/tmpTraffic.js +64 -3
- package/lib/command/tmpTraffic/tmpTrafficMap.js +2 -2
- package/lib/command/tmpVersion.js +81 -9
- package/lib/command/tmpVtcMileageRanking.js +75 -22
- package/lib/command/tmpVtcOnline/tmpVtcOnlineImg.js +1 -1
- package/lib/database/guildBind.js +150 -1
- package/lib/database/model.js +12 -0
- package/lib/index.js +139 -15
- package/lib/resource/command-suggest.html +222 -0
- package/lib/resource/tmp-version.html +292 -0
- package/lib/util/commandSuggest.js +140 -0
- package/lib/util/commandSuggestMiddleware.js +210 -0
- package/lib/util/localImageHost.js +219 -0
- package/lib/util/messageRender.js +234 -0
- package/lib/util/qqMarkdown.js +171 -0
- package/lib/util/qqMediaUpload.js +165 -0
- package/lib/util/qqOfficial.js +233 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -10,6 +10,9 @@ const { ServerType } = require('./util/constant');
|
|
|
10
10
|
const { MileageRankingType } = require('./util/constant');
|
|
11
11
|
const { LeadRoleCallMessage, LeadRoleCallTime } = require('./util/constant');
|
|
12
12
|
const tmpIdPicker = require('./util/tmpIdPicker');
|
|
13
|
+
const qqOfficial = require('./util/qqOfficial');
|
|
14
|
+
const commandSuggestMiddleware = require('./util/commandSuggestMiddleware');
|
|
15
|
+
const localImageHost = require('./util/localImageHost');
|
|
13
16
|
|
|
14
17
|
const commands = {
|
|
15
18
|
tmpQuery: require('./command/tmpQuery/tmpQuery'),
|
|
@@ -114,6 +117,18 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
114
117
|
koishi_1.Schema.const(2).description('热力图')
|
|
115
118
|
]).default(1).description('路况信息展示方式'),
|
|
116
119
|
}).description('路况查询配置'),
|
|
120
|
+
tmpMileageRanking: koishi_1.Schema.object({
|
|
121
|
+
type: koishi_1.Schema.union([
|
|
122
|
+
koishi_1.Schema.const(1).description('文字'),
|
|
123
|
+
koishi_1.Schema.const(2).description('图片')
|
|
124
|
+
]).default(2).description('里程排行榜展示方式')
|
|
125
|
+
}).description('里程排行榜配置'),
|
|
126
|
+
tmpVtcMileageRanking: koishi_1.Schema.object({
|
|
127
|
+
type: koishi_1.Schema.union([
|
|
128
|
+
koishi_1.Schema.const(1).description('文字'),
|
|
129
|
+
koishi_1.Schema.const(2).description('图片')
|
|
130
|
+
]).default(2).description('VTC里程排行榜展示方式')
|
|
131
|
+
}).description('VTC里程排行榜配置'),
|
|
117
132
|
tmpServer: koishi_1.Schema.object({
|
|
118
133
|
type: koishi_1.Schema.union([
|
|
119
134
|
koishi_1.Schema.const(1).description('文字'),
|
|
@@ -126,6 +141,12 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
126
141
|
koishi_1.Schema.const(2).description('图片')
|
|
127
142
|
]).default(1).description('车队在线成员展示方式')
|
|
128
143
|
}).description('车队在线成员查询'),
|
|
144
|
+
tmpVersion: koishi_1.Schema.object({
|
|
145
|
+
type: koishi_1.Schema.union([
|
|
146
|
+
koishi_1.Schema.const(1).description('文字'),
|
|
147
|
+
koishi_1.Schema.const(2).description('图片')
|
|
148
|
+
]).default(2).description('tmp版本展示方式')
|
|
149
|
+
}).description('tmp版本查询配置'),
|
|
129
150
|
|
|
130
151
|
tmpVersionCheck: koishi_1.Schema.object({
|
|
131
152
|
checkInterval: koishi_1.Schema.number().description("版本检查间隔(分钟)").default(30),
|
|
@@ -215,10 +236,105 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
215
236
|
logMessageSending: koishi_1.Schema.boolean().description("记录消息发送详情").default(false)
|
|
216
237
|
}).description("开发者选项")
|
|
217
238
|
}).description("活动查询配置")
|
|
218
|
-
}).description('功能配置')
|
|
239
|
+
}).description('功能配置'),
|
|
240
|
+
koishi_1.Schema.object({
|
|
241
|
+
commandSuggest: koishi_1.Schema.object({
|
|
242
|
+
enable: koishi_1.Schema.boolean().description("启用「猜你想问」指令纠错提示(打错指令时给出相近指令建议)").default(true),
|
|
243
|
+
type: koishi_1.Schema.union([
|
|
244
|
+
koishi_1.Schema.const(1).description('文字'),
|
|
245
|
+
koishi_1.Schema.const(2).description('图片')
|
|
246
|
+
]).default(1).description('「猜你想问」提示的展示方式(图片模式下官方机器人会发图片并在下方附带按钮)'),
|
|
247
|
+
maxDistance: koishi_1.Schema.number().description("最大编辑距离:用户输入与指令名的字符差异上限,越大越宽松(默认按长度自适应,此项留空即自适应)")
|
|
248
|
+
}).description("指令纠错配置"),
|
|
249
|
+
qqOfficial: koishi_1.Schema.object({
|
|
250
|
+
enable: koishi_1.Schema.boolean().description("启用 QQ 官方机器人增强:文本用 markdown 发送、附带交互按钮(仅对 qq/qqguild 适配器生效,onebot 不受影响)").default(true),
|
|
251
|
+
showQueryButtons: koishi_1.Schema.boolean().description("在查询类结果下方附加常用查询按钮(仅官方机器人)").default(true),
|
|
252
|
+
publicBaseUrl: koishi_1.Schema.string()
|
|
253
|
+
.role('link')
|
|
254
|
+
.description("Koishi 对外公网地址(如 https://bd.114512.xyz:5155)。填写后图片会存为本地文件并以公网 URL 发送,不受 QQ 官方 100 张图片限制,且手机端可正常显示;留空则使用 QQ 官方素材上传")
|
|
255
|
+
.default('')
|
|
256
|
+
}).description("QQ 官方机器人配置")
|
|
257
|
+
}).description("通用与适配器配置")
|
|
219
258
|
]);
|
|
220
259
|
|
|
221
260
|
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* 收集本插件注册的指令名,供「猜你想问」使用。
|
|
264
|
+
* 只取指令定义里第一个空格前的部分(去掉参数说明)。
|
|
265
|
+
*/
|
|
266
|
+
function collectCommandNames(cfg) {
|
|
267
|
+
const flags = cfg.commands || {};
|
|
268
|
+
const list = [];
|
|
269
|
+
const add = (enabled, defs) => {
|
|
270
|
+
if (!enabled) return;
|
|
271
|
+
for (const def of defs) list.push(String(def).split(' ')[0]);
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
add(flags.tmpQuery, ['查询']);
|
|
275
|
+
add(flags.tmpServer, ['美卡服务器', '欧卡服务器']);
|
|
276
|
+
add(flags.tmpBind, ['绑定', '我的绑定', '设为默认', '解绑']);
|
|
277
|
+
add(flags.tmpTraffic, ['路况']);
|
|
278
|
+
add(flags.tmpPosition, ['定位']);
|
|
279
|
+
add(flags.tmpVersion, ['tmp版本']);
|
|
280
|
+
add(flags.tmpDlcMap, ['地图dlc价格']);
|
|
281
|
+
add(flags.tmpMileageRanking, ['里程排行榜', '今日里程排行榜']);
|
|
282
|
+
add(flags.tmpVtcMileageRanking, ['vtc里程排行榜', 'vtc今日里程排行榜']);
|
|
283
|
+
add(flags.pointRanking, ['积分排行']);
|
|
284
|
+
add(flags.tmpVtc, ['vtc查询']);
|
|
285
|
+
add(flags.tmpVtcOnline, ['车队在线成员']);
|
|
286
|
+
add(flags.tmpFootprint, [
|
|
287
|
+
'近一年足迹', '近一年足迹p', '近一年足迹美',
|
|
288
|
+
'近一个月足迹美', '近七日足迹美', '昨日足迹美', '今日足迹美',
|
|
289
|
+
'近一个月足迹', '近一个月足迹p', '近七日足迹', '近七日足迹p',
|
|
290
|
+
'昨日足迹', '昨日足迹p', '今日足迹', '今日足迹p',
|
|
291
|
+
]);
|
|
292
|
+
add(flags.resetPassword, ['重置密码']);
|
|
293
|
+
add(flags.mainSettings, ['查询积分']);
|
|
294
|
+
add(flags.changePoint, ['积分修改']);
|
|
295
|
+
|
|
296
|
+
// 无开关、始终注册的指令
|
|
297
|
+
list.push('规则查询');
|
|
298
|
+
|
|
299
|
+
return list;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* 注册「猜你想问」中间件。
|
|
304
|
+
*/
|
|
305
|
+
/**
|
|
306
|
+
* 注册本地图片托管路由(仅配置了公网地址时启用)。
|
|
307
|
+
*/
|
|
308
|
+
function setupLocalImageHost(ctx, cfg) {
|
|
309
|
+
try {
|
|
310
|
+
const baseUrl = localImageHost.getPublicBaseUrl(cfg);
|
|
311
|
+
if (!baseUrl) {
|
|
312
|
+
if (cfg.debugMode) ctx.logger.debug('[本地图片] 未配置 qqOfficial.publicBaseUrl,图片将由 QQ 官方素材接口上传');
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
const dir = localImageHost.registerStaticRoute(ctx, cfg);
|
|
316
|
+
if (dir) {
|
|
317
|
+
ctx.logger.info(`[本地图片] 已启用,访问地址: ${baseUrl}${localImageHost.ROUTE_PREFIX}/,存储目录: ${dir}`);
|
|
318
|
+
} else {
|
|
319
|
+
ctx.logger.warn('[本地图片] 未找到 server 服务,图片将回退为 QQ 官方素材上传');
|
|
320
|
+
}
|
|
321
|
+
} catch (error) {
|
|
322
|
+
ctx.logger.error('[本地图片] 初始化失败:', error.message);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function registerCommandSuggest(ctx, cfg) {
|
|
327
|
+
try {
|
|
328
|
+
const names = collectCommandNames(cfg);
|
|
329
|
+
commandSuggestMiddleware.register(ctx, cfg, names);
|
|
330
|
+
if (cfg.debugMode) {
|
|
331
|
+
ctx.logger.debug(`[猜你想问] 已启用,候选指令 ${names.length} 个`);
|
|
332
|
+
}
|
|
333
|
+
} catch (error) {
|
|
334
|
+
ctx.logger.error("[猜你想问] 初始化失败:", error.message);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
222
338
|
function logDisabledCommands(ctx, cfg) {
|
|
223
339
|
const commandFlags = cfg.commands || {};
|
|
224
340
|
const enabled = [];
|
|
@@ -259,11 +375,11 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
259
375
|
if (cfg.commands?.tmpServer) {
|
|
260
376
|
ctx.command('美卡服务器')
|
|
261
377
|
.usage("查询美国卡车模拟器TMP服务器信息")
|
|
262
|
-
.action(async () => await commands.tmpServer(ctx, cfg, 'ATS'));
|
|
378
|
+
.action(async ({ session }) => await commands.tmpServer(ctx, cfg, session, 'ATS'));
|
|
263
379
|
|
|
264
380
|
ctx.command('欧卡服务器')
|
|
265
381
|
.usage("查询欧洲卡车模拟2TMP服务器信息")
|
|
266
|
-
.action(async () => await commands.tmpServer(ctx, cfg, 'ETS2'));
|
|
382
|
+
.action(async ({ session }) => await commands.tmpServer(ctx, cfg, session, 'ETS2'));
|
|
267
383
|
}
|
|
268
384
|
|
|
269
385
|
if (cfg.commands?.tmpQuery) {
|
|
@@ -274,7 +390,7 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
274
390
|
ctx.command('我的绑定')
|
|
275
391
|
.usage("查看已绑定的全部TMP编号(★ 为默认绑定)")
|
|
276
392
|
.action(async ({ session }) => {
|
|
277
|
-
const bindings = await guildBind.
|
|
393
|
+
const bindings = await guildBind.listWithUnion(ctx.database, session.platform, session.userId, qqOfficial.buildIdentity(session));
|
|
278
394
|
if (bindings.length === 0) {
|
|
279
395
|
return '还没有绑定编号,使用「绑定 tmpId」添加';
|
|
280
396
|
}
|
|
@@ -297,9 +413,10 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
297
413
|
if (!index || !index.trim()) {
|
|
298
414
|
return '请输入要设为默认的序号(序号见「我的绑定」)';
|
|
299
415
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
416
|
+
const bindings = await guildBind.listWithUnion(ctx.database, session.platform, session.userId, qqOfficial.buildIdentity(session));
|
|
417
|
+
await guildBind.refreshNames(ctx, bindings);
|
|
418
|
+
const { row, changed, total } = await guildBind.setDefaultByIndexFromRows(
|
|
419
|
+
ctx.database, bindings, index.trim()
|
|
303
420
|
);
|
|
304
421
|
if (!row) {
|
|
305
422
|
if (!total) {
|
|
@@ -316,7 +433,7 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
316
433
|
.example("解绑 2")
|
|
317
434
|
.example("解绑 all")
|
|
318
435
|
.action(async ({ session }, index) => {
|
|
319
|
-
const bindings = await guildBind.
|
|
436
|
+
const bindings = await guildBind.listWithUnion(ctx.database, session.platform, session.userId, qqOfficial.buildIdentity(session));
|
|
320
437
|
if (bindings.length === 0) {
|
|
321
438
|
return '还没有绑定编号';
|
|
322
439
|
}
|
|
@@ -324,8 +441,9 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
324
441
|
return '请输入要解绑的序号或 all(序号见「我的绑定」)';
|
|
325
442
|
}
|
|
326
443
|
if (/^all$/i.test(index.trim())) {
|
|
327
|
-
|
|
328
|
-
|
|
444
|
+
// 用「已查到的行」删除:跨群时 user_id 是对方群的 openid,不能再按 (platform,user_id) 反查
|
|
445
|
+
const removed = await guildBind.removeAllFromRows(ctx.database, bindings);
|
|
446
|
+
return `已删除全部 ${removed} 个绑定`;
|
|
329
447
|
}
|
|
330
448
|
const idx = parseInt(index, 10);
|
|
331
449
|
if (isNaN(idx) || idx < 1 || idx > bindings.length) {
|
|
@@ -334,7 +452,7 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
334
452
|
// 到这一步才需要显示名字(成功文案 / 顶替提示)→ 此时刷新
|
|
335
453
|
await guildBind.refreshNames(ctx, bindings);
|
|
336
454
|
const row = bindings[idx - 1];
|
|
337
|
-
const { promoted } = await guildBind.
|
|
455
|
+
const { promoted } = await guildBind.removeFromRows(ctx.database, bindings, row.id);
|
|
338
456
|
let msg = `已解绑 ${idx}. ${row.tmp_name || '未知'} (${row.tmp_id})`;
|
|
339
457
|
if (promoted) {
|
|
340
458
|
msg += `\n默认绑定已自动切换到 ${promoted.tmp_name || '未知'} (${promoted.tmp_id})`;
|
|
@@ -347,7 +465,7 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
347
465
|
ctx.command('路况 <serverName>')
|
|
348
466
|
.usage("查询欧洲卡车模拟2服务器路况")
|
|
349
467
|
.example("路况 - s1")
|
|
350
|
-
.action(async ({ session }, serverName) => await commands.tmpTraffic(ctx, cfg, serverName));
|
|
468
|
+
.action(async ({ session }, serverName) => await commands.tmpTraffic(ctx, cfg, session, serverName));
|
|
351
469
|
}
|
|
352
470
|
|
|
353
471
|
if (cfg.commands?.tmpPosition) {
|
|
@@ -359,7 +477,7 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
359
477
|
if (cfg.commands?.tmpVersion) {
|
|
360
478
|
ctx.command('tmp版本')
|
|
361
479
|
.usage("查询TruckersMP支持的游戏版本")
|
|
362
|
-
.action(async () => await commands.tmpVersion(ctx));
|
|
480
|
+
.action(async ({ session }) => await commands.tmpVersion(ctx, cfg, session));
|
|
363
481
|
}
|
|
364
482
|
|
|
365
483
|
if (cfg.commands?.tmpDlcMap) {
|
|
@@ -371,11 +489,11 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
371
489
|
if (cfg.commands?.tmpMileageRanking) {
|
|
372
490
|
ctx.command('里程排行榜 [target]')
|
|
373
491
|
.usage("查询欧洲卡车模拟2里程排行榜(可 @某人 查看对方的排名)")
|
|
374
|
-
.action(async ({ session }, target) => await commands.tmpMileageRanking(ctx, session, MileageRankingType.total, target));
|
|
492
|
+
.action(async ({ session }, target) => await commands.tmpMileageRanking(ctx, cfg, session, MileageRankingType.total, target));
|
|
375
493
|
|
|
376
494
|
ctx.command('今日里程排行榜 [target]')
|
|
377
495
|
.usage("查询欧洲卡车模拟2今日里程排行榜(可 @某人 查看对方的排名)")
|
|
378
|
-
.action(async ({ session }, target) => await commands.tmpMileageRanking(ctx, session, MileageRankingType.today, target));
|
|
496
|
+
.action(async ({ session }, target) => await commands.tmpMileageRanking(ctx, cfg, session, MileageRankingType.today, target));
|
|
379
497
|
}
|
|
380
498
|
|
|
381
499
|
if (cfg.commands?.tmpVtcMileageRanking) {
|
|
@@ -533,6 +651,12 @@ function apply(ctx, cfg) {
|
|
|
533
651
|
// 多绑定选择器中间件(捕获用户回复的序号,完成"列出绑定→序号选择"交互)
|
|
534
652
|
tmpIdPicker.register(ctx);
|
|
535
653
|
|
|
654
|
+
// 「猜你想问」中间件:指令打错时给出提示(只提示不执行)
|
|
655
|
+
registerCommandSuggest(ctx, cfg);
|
|
656
|
+
|
|
657
|
+
// 本地图片托管:配置了公网地址时,图片以本地文件 + 公网 URL 提供
|
|
658
|
+
setupLocalImageHost(ctx, cfg);
|
|
659
|
+
|
|
536
660
|
try {
|
|
537
661
|
model(ctx);
|
|
538
662
|
if (cfg.debugMode) {
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>猜你想问</title>
|
|
6
|
+
<style>
|
|
7
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
8
|
+
|
|
9
|
+
body {
|
|
10
|
+
font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
|
|
11
|
+
background: #06060b;
|
|
12
|
+
-webkit-font-smoothing: antialiased;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
#container {
|
|
16
|
+
width: 560px;
|
|
17
|
+
background: #0a0a12;
|
|
18
|
+
position: relative;
|
|
19
|
+
overflow: hidden;
|
|
20
|
+
padding: 22px 24px 24px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.grid-bg {
|
|
24
|
+
position: absolute;
|
|
25
|
+
inset: 0;
|
|
26
|
+
background-image:
|
|
27
|
+
linear-gradient(rgba(0, 200, 255, 0.03) 1px, transparent 1px),
|
|
28
|
+
linear-gradient(90deg, rgba(0, 200, 255, 0.03) 1px, transparent 1px);
|
|
29
|
+
background-size: 26px 26px;
|
|
30
|
+
pointer-events: none;
|
|
31
|
+
z-index: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.glow-top {
|
|
35
|
+
position: absolute;
|
|
36
|
+
top: -180px;
|
|
37
|
+
left: 50%;
|
|
38
|
+
transform: translateX(-50%);
|
|
39
|
+
width: 620px;
|
|
40
|
+
height: 360px;
|
|
41
|
+
background: radial-gradient(ellipse at center, rgba(0, 200, 255, 0.16) 0%, rgba(0, 200, 255, 0.04) 45%, transparent 70%);
|
|
42
|
+
pointer-events: none;
|
|
43
|
+
z-index: 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.header {
|
|
47
|
+
position: relative;
|
|
48
|
+
z-index: 2;
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
gap: 13px;
|
|
52
|
+
padding-bottom: 16px;
|
|
53
|
+
border-bottom: 1px solid rgba(0, 200, 255, 0.1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.header-badge {
|
|
57
|
+
width: 44px;
|
|
58
|
+
height: 44px;
|
|
59
|
+
flex-shrink: 0;
|
|
60
|
+
border-radius: 13px;
|
|
61
|
+
display: flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
justify-content: center;
|
|
64
|
+
font-size: 22px;
|
|
65
|
+
background: linear-gradient(145deg, rgba(0, 200, 255, 0.22), rgba(0, 200, 255, 0.06));
|
|
66
|
+
border: 1px solid rgba(0, 200, 255, 0.32);
|
|
67
|
+
box-shadow: 0 0 18px rgba(0, 200, 255, 0.22);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.header-title {
|
|
71
|
+
font-size: 19px;
|
|
72
|
+
font-weight: 800;
|
|
73
|
+
color: #eaf6ff;
|
|
74
|
+
letter-spacing: 1.2px;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.header-title em {
|
|
78
|
+
font-style: normal;
|
|
79
|
+
color: #00c8ff;
|
|
80
|
+
text-shadow: 0 0 14px rgba(0, 200, 255, 0.55);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.header-sub {
|
|
84
|
+
margin-top: 3px;
|
|
85
|
+
font-size: 10px;
|
|
86
|
+
letter-spacing: 3px;
|
|
87
|
+
color: #3d5570;
|
|
88
|
+
text-transform: uppercase;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.hint {
|
|
92
|
+
position: relative;
|
|
93
|
+
z-index: 2;
|
|
94
|
+
margin-top: 16px;
|
|
95
|
+
font-size: 12.5px;
|
|
96
|
+
color: #7d8b9c;
|
|
97
|
+
letter-spacing: 0.4px;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.list {
|
|
101
|
+
position: relative;
|
|
102
|
+
z-index: 2;
|
|
103
|
+
margin-top: 11px;
|
|
104
|
+
display: flex;
|
|
105
|
+
flex-direction: column;
|
|
106
|
+
gap: 9px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.item {
|
|
110
|
+
position: relative;
|
|
111
|
+
display: flex;
|
|
112
|
+
align-items: center;
|
|
113
|
+
gap: 12px;
|
|
114
|
+
padding: 13px 15px;
|
|
115
|
+
border-radius: 12px;
|
|
116
|
+
background: rgba(0, 255, 157, 0.05);
|
|
117
|
+
border: 1px solid rgba(0, 255, 157, 0.26);
|
|
118
|
+
box-shadow: inset 0 0 20px rgba(0, 255, 157, 0.06);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.item::before {
|
|
122
|
+
content: '';
|
|
123
|
+
position: absolute;
|
|
124
|
+
left: 0;
|
|
125
|
+
top: 7px;
|
|
126
|
+
bottom: 7px;
|
|
127
|
+
width: 3px;
|
|
128
|
+
border-radius: 0 3px 3px 0;
|
|
129
|
+
background: linear-gradient(180deg, #00ff88, #00c8ff);
|
|
130
|
+
box-shadow: 0 0 10px rgba(0, 255, 136, 0.6);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.item-idx {
|
|
134
|
+
flex-shrink: 0;
|
|
135
|
+
width: 22px;
|
|
136
|
+
height: 22px;
|
|
137
|
+
border-radius: 7px;
|
|
138
|
+
display: flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
justify-content: center;
|
|
141
|
+
font-size: 11px;
|
|
142
|
+
font-weight: 800;
|
|
143
|
+
color: #04121a;
|
|
144
|
+
background: linear-gradient(135deg, #00ff88, #00c8ff);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.item-name {
|
|
148
|
+
font-size: 15.5px;
|
|
149
|
+
font-weight: 700;
|
|
150
|
+
color: #eaf6ff;
|
|
151
|
+
letter-spacing: 0.4px;
|
|
152
|
+
word-break: break-all;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.footer {
|
|
156
|
+
position: relative;
|
|
157
|
+
z-index: 2;
|
|
158
|
+
margin-top: 18px;
|
|
159
|
+
padding-top: 12px;
|
|
160
|
+
border-top: 1px solid rgba(0, 200, 255, 0.08);
|
|
161
|
+
font-size: 10px;
|
|
162
|
+
color: #3d5570;
|
|
163
|
+
letter-spacing: 2.4px;
|
|
164
|
+
text-align: center;
|
|
165
|
+
text-transform: uppercase;
|
|
166
|
+
}
|
|
167
|
+
</style>
|
|
168
|
+
</head>
|
|
169
|
+
<body>
|
|
170
|
+
<div id="container">
|
|
171
|
+
<div class="grid-bg"></div>
|
|
172
|
+
<div class="glow-top"></div>
|
|
173
|
+
|
|
174
|
+
<div class="header">
|
|
175
|
+
<div class="header-badge">💡</div>
|
|
176
|
+
<div>
|
|
177
|
+
<div class="header-title">猜你<em>想问</em></div>
|
|
178
|
+
<div class="header-sub">Did You Mean</div>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
<div class="hint" id="hint">没有找到这条指令,你是不是想用:</div>
|
|
183
|
+
<div class="list" id="list"></div>
|
|
184
|
+
|
|
185
|
+
<div class="footer">TMP-BOT · Command Suggest</div>
|
|
186
|
+
</div>
|
|
187
|
+
|
|
188
|
+
<script>
|
|
189
|
+
function esc(s) {
|
|
190
|
+
return String(s == null ? '' : s)
|
|
191
|
+
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
192
|
+
.replace(/"/g, '"').replace(/'/g, ''');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @param {{ names?: string[], input?: string }} data
|
|
197
|
+
*/
|
|
198
|
+
function setData(data) {
|
|
199
|
+
data = data || {};
|
|
200
|
+
var names = Array.isArray(data.names) ? data.names : [];
|
|
201
|
+
var hintEl = document.getElementById('hint');
|
|
202
|
+
var listEl = document.getElementById('list');
|
|
203
|
+
|
|
204
|
+
if (data.input) {
|
|
205
|
+
hintEl.textContent = '没有找到「' + data.input + '」,你是不是想用:';
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (names.length === 0) {
|
|
209
|
+
listEl.innerHTML = '<div class="item"><div class="item-name">-</div></div>';
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
listEl.innerHTML = names.map(function (name, i) {
|
|
214
|
+
return '<div class="item">' +
|
|
215
|
+
'<div class="item-idx">' + (i + 1) + '</div>' +
|
|
216
|
+
'<div class="item-name">' + esc(name) + '</div>' +
|
|
217
|
+
'</div>';
|
|
218
|
+
}).join('');
|
|
219
|
+
}
|
|
220
|
+
</script>
|
|
221
|
+
</body>
|
|
222
|
+
</html>
|