From 309898045c14691720066a1cea8f64778d93e91b Mon Sep 17 00:00:00 2001 From: yu <1919727607@qq.com> Date: Thu, 5 Nov 2026 11:11:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=83=E7=B4=A0=E6=8B=BE=E5=8F=96=E6=82=AC?= =?UTF-8?q?=E5=81=9C0.3=E7=A7=92=E8=87=AA=E5=8A=A8=E9=92=BB=E5=85=A5?= =?UTF-8?q?=E5=AD=90=E5=85=83=E7=B4=A0,=20=E6=97=A0=E9=9C=80=E5=85=88?= =?UTF-8?q?=E9=94=81=E5=AE=9A=E5=86=8D=E8=B0=83=E5=B1=82=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 进入新交互区域先吸附交互元素, 悬停300ms后自动钻入光标最深处 - 钻入后跟随光标在卡片内部移动; PageUp/PageDown 保留为手动上下调层(未锁定时直接锁定) --- src/main/browser/session.ts | 53 ++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/src/main/browser/session.ts b/src/main/browser/session.ts index bbbf71f..962fe1d 100644 --- a/src/main/browser/session.ts +++ b/src/main/browser/session.ts @@ -1256,6 +1256,9 @@ const PICKER_BOOTSTRAP_SOURCE = `(() => { let badge = null; let target = null; let deepTarget = null; + let lastSnap = null; + let drilled = false; + let hoverTimer = 0; let locked = false; let chain = []; let chainIndex = 0; @@ -1341,7 +1344,7 @@ const PICKER_BOOTSTRAP_SOURCE = `(() => { if (locked) { badge.textContent = '已锁定 ' + (chainIndex + 1) + '/' + chain.length + ' · ' + tag + (name ? ' · ' + name.slice(0, 42) : '') + ' · [PageUp]升 [PageDown]钻入子元素 [空格]确认 [Esc]取消'; } else { - badge.textContent = '拾取 · ' + tag + (name ? ' · ' + name.slice(0, 42) : '') + ' · [空格]锁定 [Esc]取消 · 可直接翻页后继续拾取'; + badge.textContent = '拾取 · ' + tag + (name ? ' · ' + name.slice(0, 42) : '') + ' · 悬停0.3秒自动钻入 · [PageUp/PageDown]手动调层 [空格]确认 [Esc]取消 · 可直接翻页后继续拾取'; } badge.style.left = Math.max(0, rect.left) + 'px'; badge.style.top = Math.max(0, rect.top - 34) + 'px'; @@ -1387,25 +1390,26 @@ const PICKER_BOOTSTRAP_SOURCE = `(() => { } return result; }; - const lock = () => { - if (locked || !target) return; + const lockAt = (base) => { + if (locked || !base) return; locked = true; - chain = buildChain(target); + chain = buildChain(base); chainIndex = Math.max(0, chain.length - 1); - // 把光标下最深处元素到锁定元素之间的子级路径并入链,PageDown 可钻入卡片内部的标题/价格等子元素 - if (deepTarget && target !== deepTarget && target.contains(deepTarget)) { + // 把光标下最深处元素到锁定元素之间的子级路径并入链,PageDown/PageUp 可在卡片与其内部子元素间切换 + if (deepTarget && base !== deepTarget && base.contains(deepTarget)) { const below = []; let current = deepTarget; - while (current && current !== target && target.contains(current)) { + while (current && current !== base && base.contains(current)) { below.unshift(current); const root = current.getRootNode(); current = root instanceof ShadowRoot ? root.host : current.parentElement; } chain = chain.concat(below); } - selected = chain[chainIndex] || target; + selected = chain[chainIndex] || base; updateBox(); }; + const lock = () => lockAt(target); const adjustLevel = (delta) => { if (!locked || !chain.length) return; const next = Math.min(chain.length - 1, Math.max(0, chainIndex + delta)); @@ -1421,7 +1425,27 @@ const PICKER_BOOTSTRAP_SOURCE = `(() => { const move = (event) => { if (finished || locked) return; deepTarget = deepestOf(event); - target = firstElement(event); + const snapped = firstElement(event); + if (snapped !== lastSnap) { + // 进入新的交互区域:先吸附交互元素,悬停 0.3 秒后自动钻入光标最深处 + lastSnap = snapped; + drilled = false; + target = snapped; + clearTimeout(hoverTimer); + if (deepTarget && deepTarget !== snapped) { + hoverTimer = setTimeout(() => { + if (finished || locked) return; + drilled = true; + target = deepTarget; + updateBox(); + }, 300); + } + updateBox(); + return; + } + if (drilled && deepTarget && snapped.contains(deepTarget)) { + target = deepTarget; // 已钻入:跟随光标在卡片内部移动 + } updateBox(); }; const click = (event) => { @@ -1444,21 +1468,24 @@ const PICKER_BOOTSTRAP_SOURCE = `(() => { else lock(); return; } - if (locked && event.key === 'PageUp' && !event.repeat) { + if (event.key === 'PageDown' && !event.repeat) { event.preventDefault(); event.stopPropagation(); - adjustLevel(-1); + if (locked) adjustLevel(1); + else lockAt(deepTarget || target); // 未锁定时直接锁定光标最深处(如卡片内的标题) return; } - if (locked && event.key === 'PageDown' && !event.repeat) { + if (event.key === 'PageUp' && !event.repeat) { event.preventDefault(); event.stopPropagation(); - adjustLevel(1); + if (locked) adjustLevel(-1); + else if (target) lockAt(target); // 未锁定时锁定吸附到的交互元素(如整张卡片) } }; const cleanup = () => { if (finished) return; finished = true; + clearTimeout(hoverTimer); window.removeEventListener('mousemove', move, true); window.removeEventListener('mousedown', click, true); window.removeEventListener('click', click, true);