后台新增「联想词按键」设置:可用 , 和 . 代替 ↑/↓ 选联想词

输入法手感 —— 习惯中文输入法的话,手不用离开主键区就能在联想下拉里选词。

- 设置项 suggest_keys:arrows(默认,等同改造前)/ punct(, 和 .)/ both。
  后台为三选一下拉,保存走白名单回退(非白名单一律 arrows),默认值 = 旧行为。
- app.js 认**物理键**(e.code 的 Comma / Period)而不是字符 —— 中文输入法下按逗号
  打出来的是全角「,」,e.key 会变成「,」,但物理键不变;「跟输入法一样」就该这么认。
- ⚠️ 逗号和句号同时是搜索框的合法输入字符(如「python, pandas」)—— 所以只在
  **联想下拉打开时**才把它们当选词键;没有下拉时放行,照常输入。这条边界写进了
  后台说明(想输入逗号本身先按 Esc 关掉下拉)。
- 「,」= 上一条(同 ↑)、「.」= 下一条(同 ↓),首尾循环、与方向键行为完全一致。
- 前台输出两处同源标记:#search-form 的 data-keys(供断言/排查)与
  window.SIMPLENAV.suggestKeys(JS 实际读它决定用哪组键)。

验证:
- jsdom 交互测试 54/54 —— arrows / punct / both 三种模式各跑一遍;覆盖全角「,」「。」
  (中文输入法场景)、「没有下拉时 ,/. 不被拦截」(关键回归)、
  以及上一轮的核心回归「直接回车用原文」在三种模式下都成立。
- 反向验证两个变体:把回车改回旧行为 → 「直接回车不改动输入框」精确失败(27 项);
  把「没下拉放行」改坏 → 恰好只失败「没有下拉时按 ./, 不被拦截」那两条(2 项),
  其余全过 —— 两条核心断言各自有效、定位精准。
- e2e 128/128(新增联想按键场景:保存 → data-keys / suggestKeys 同步、
  非法值回退 arrows、保存不动其它设置)。
- 线上部署 0 FAIL(77 条静态断言、38 文件哈希逐字节一致);线上几何 25/25;
  直连线上核验 data-keys / suggestKeys / app.js 内容均已就位。
This commit is contained in:
2026-09-28 20:25:33 +08:00
parent 9225113dae
commit 13b12a3d67
5 changed files with 55 additions and 7 deletions
+8 -2
View File
@@ -32,6 +32,12 @@ function open_target(): string
$openTarget = open_target();
$openMode = $openTarget === '_blank' ? 'blank' : 'self';
// 联想词的选中按键(后台「设置 → 联想词按键」):
// arrows = 只认 ↓/↑(默认,等同改造前) / punct = 只认 , 和 . (输入法手感)/ both = 都认
// 白名单回退:任何非法值都回到 arrows,别让手改库/被篡改的表单把交互搞坏。
$suggestKeys = setting('suggest_keys', 'arrows');
if (!in_array($suggestKeys, ['arrows', 'punct', 'both'], true)) { $suggestKeys = 'arrows'; }
// 默认引擎
$defSlug = setting('default_engine', 'bing');
$default = null;
@@ -122,7 +128,7 @@ function site_tile(array $s): void
</div>
<form id="search-form" action="<?= e($default['search_url'] ?? 'https://cn.bing.com/search') ?>" method="get" target="<?= e($openTarget) ?>"<?= $openTarget === '_blank' ? ' rel="noopener"' : '' ?>
data-slug="<?= e($default['slug'] ?? '') ?>">
data-slug="<?= e($default['slug'] ?? '') ?>" data-keys="<?= e($suggestKeys) ?>">
<input type="text" id="search-text" name="<?= e($default['param'] ?? 'q') ?>"
placeholder="<?= e(($default['name'] ?? '搜索') . '搜索') ?>" autocomplete="off">
<button class="submit" type="submit" aria-label="搜索">
@@ -188,7 +194,7 @@ function site_tile(array $s): void
</footer>
</div>
<script>window.SIMPLENAV = { suggest: "<?= e(url('suggest.php')) ?>" };</script>
<script>window.SIMPLENAV = { suggest: "<?= e(url('suggest.php')) ?>", suggestKeys: "<?= e($suggestKeys) ?>" };</script>
<script src="<?= e(asset('assets/js/app.js')) ?>"></script>
</body>
</html>