联想词键盘选词彻底修复:上下键 / 逗号句号 / 输入法组合上屏四条路径全通
背景:用户反馈「上下键和逗号句号都无法选择候选词,只能用鼠标」。逐条查下去
发现是**三个各自独立的原因**叠在一起,任何一个没修都会让人觉得「还是坏的」。
① 单组按键模式让另一组键静默失效
线上 settings.suggest_keys 停在 'punct'(只认 , 和 .)—— 是该模式的正确
行为,但用户不知道那是设置项在起作用,只当坏了。
改法:默认值改为 'both'(↓/↑ 与 , . 都认)。'both' 是 'arrows' 与 'punct'
各自行为的**严格超集**,升级不会让任何人的习惯失效,只是多了一组。
老库用**一次性迁移**(哨兵键 mig_suggest_keys_both 把关)把已知单组值并成
'both'。⚠️ 迁移必须只跑一次:db_init() 每次请求都执行,无条件 UPDATE 会把
用户在后台特意选回的 'arrows' 于下一个请求改回去 —— 设置项直接失效。
同时同步三处默认值:index.php / admin/index.php / admin/actions.php。
② 【元凶】beforeinput 只认 insertText,漏了 insertCompositionText
输入法把标点当**组合内容**提交时,beforeinput 的 inputType 是
insertCompositionText,旧代码直接 return → 这条路径完全失效。
修法:两种 inputType 都认。
③ 【真机实测的硬限制】insertCompositionText 的 beforeinput cancelable = false
Chromium 里这条事件**不允许** preventDefault(CDP 实测记录:
beforeinput it:insertCompositionText comp:true data:"," pd:false cc:false),
所以「命中就拦」对这条路根本无效 —— 标点会被真的插进搜索框。
修法:加「事后收口」——beforeinput 记下快照与该移到的目标下标,
等这一帧事件洪峰过去(setTimeout 0)再把标点从输入框里撤掉、并补上选词移动。
目标下标必须**当场算好**:收口跑在宏任务里,那时 input 的 `active = -1`
已经把选中清掉了,再从 active 起算会每次都回到第一条(不累加)。
顺带把标点判定抽成共用函数 punctDir/keyPunctDir(e.key 与 e.code 互为兜底),
并修掉「方向键也无差别置去重闸门」——方向键不产生 beforeinput,置了纯属副作用,
反而会误挡紧随其后的真实标点。
测试与验证(全部实跑,非推断):
- jsdom 交互测试 89 项全过,新增「真实浏览器形态」场景(cancelable=false +
组合上屏),并**纠正了旧版一条在断言 bug 本身的断言**(原写「组合上屏不该被拦」)。
- 反向验证 6 变体全部精确挂掉对应断言(含新增的「只认 insertText」与
「方向键置闸门」两个变体);旧变体引用的 isComma/isPeriod 已随重构更新。
- **真实浏览器**(Playwright + msedge + CDP IME)21/21:上下键 / 半角 / 全角
insertText / IME 组合上屏四条路径全部能选词。
- 真实浏览器反向验证:基准全绿,删掉「事后收口」或改回只认 insertText 都精确报红。
- 迁移语义测试 16 项全过(真实 db_init,含「用户改回 arrows 后不再被覆盖」)。
- 静态断言空跑 155 条全过;线上部署 0 FAIL,诊断页 57 条断言全过。
- 线上真机直连 n.yangyq.net 21/21。
This commit is contained in:
+3
-3
@@ -268,9 +268,9 @@ try {
|
||||
// 打开方式:'0' = 当前页面;其余(含字段缺失、被篡改成怪值)一律回到 '1'(新标签页)
|
||||
// ——默认必须等于改造前的旧行为,这样老库里已有的值上线后不会突然变样。
|
||||
$open = (string)($_POST['open_blank'] ?? '1') === '0' ? '0' : '1';
|
||||
// 联想词按键:arrows(↓/↑)/ punct(, 和 .)/ both;非白名单一律回到 arrows
|
||||
$keys = (string)($_POST['suggest_keys'] ?? 'arrows');
|
||||
if (!in_array($keys, ['arrows', 'punct', 'both'], true)) { $keys = 'arrows'; }
|
||||
// 联想词按键:both(都认,默认)/ arrows(↓/↑)/ punct(, 和 .);非白名单一律回到 both
|
||||
$keys = (string)($_POST['suggest_keys'] ?? 'both');
|
||||
if (!in_array($keys, ['arrows', 'punct', 'both'], true)) { $keys = 'both'; }
|
||||
$map = [
|
||||
'site_name' => trim((string)($_POST['site_name'] ?? '')),
|
||||
'subtitle' => trim((string)($_POST['subtitle'] ?? '')),
|
||||
|
||||
+9
-8
@@ -325,18 +325,19 @@ else: // settings ?>
|
||||
各用各的(没恢复好的引擎会自动回退到百度的建议)。
|
||||
</p>
|
||||
<label>联想词按键
|
||||
<?php $sk = setting('suggest_keys', 'arrows'); ?>
|
||||
<?php $sk = setting('suggest_keys', 'both'); ?>
|
||||
<select name="suggest_keys">
|
||||
<option value="arrows" <?= $sk === 'arrows' ? 'selected' : '' ?>>↑ / ↓ 方向键(默认)</option>
|
||||
<option value="punct" <?= $sk === 'punct' ? 'selected' : '' ?>>, 和 .(输入法手感)</option>
|
||||
<option value="both" <?= $sk === 'both' ? 'selected' : '' ?>>两者都可以</option>
|
||||
<option value="both" <?= $sk === 'both' ? 'selected' : '' ?>>两者都可以(默认,推荐)</option>
|
||||
<option value="arrows" <?= $sk === 'arrows' ? 'selected' : '' ?>>只用 ↑ / ↓ 方向键</option>
|
||||
<option value="punct" <?= $sk === 'punct' ? 'selected' : '' ?>>只用 , 和 .(输入法手感)</option>
|
||||
</select>
|
||||
</label>
|
||||
<p class="hint span2">
|
||||
决定用哪组键在联想下拉里<b>选词</b>:选中某条后回车才按该词搜索;不选就直接回车 = 用你输入的原文。
|
||||
「, 和 .」跟输入法一样,手不用离开主键区,习惯中文输入法的话更顺手。
|
||||
⚠️ 选它之后,<b>联想下拉打开时</b>逗号与句号会当作选词键,不再直接输入 ——
|
||||
想搜「python, pandas」这类带逗号的词,先按 <b>Esc</b> 关掉下拉再输。
|
||||
决定用哪组键在联想下拉里<b>选词</b>:选中某条后回车才按该词搜索;不选就直接回车 = 用你输入的原文。<br>
|
||||
<b>推荐「两者都可以」</b>——手不用离开主键区,习惯中文输入法的话按 , . 更顺手,同时也保留方向键。
|
||||
⚠️ 只要联想下拉<b>打开着</b>,逗号与句号就会当作选词键、不再直接输入 ——
|
||||
想搜「python, pandas」这类带逗号的词,先按 <b>Esc</b> 关掉下拉再输。<br>
|
||||
若只留一组键,<b>另一组会完全没反应</b>(不是坏了,是这里的选择),所以除非你明确只想用一组,建议保持默认。
|
||||
</p>
|
||||
<label>合集显示方式
|
||||
<?php $cl = setting('collections_layout', 'tabs'); ?>
|
||||
|
||||
Reference in New Issue
Block a user