Compare commits

...

2 Commits

Author SHA1 Message Date
zhengchen.tao 1655f11514 fix(numpad): 全部按键 @click 换 @pointerdown.left,零延迟
Build Docker Image / build (push) Successful in 23m41s
Build Docker Image / deploy (push) Successful in 1m2s
第一阶段(touch-action: manipulation)只解了浏览器双击缩放延迟,但 F7
内部 tap 合成 + active-state 检测仍让 @click 比 pointerdown 慢一拍。
完全弃用 @click:

- 16 个按键(数字 0-9、运算 ×−+、C 清空、小数点/双零、OK 确认)改 @pointerdown.left
- 触屏 button=0 始终满足 .left 修饰符
- 桌面右键 button=2 不会误触发
- F7 active-state 视觉反馈基于独立 touchstart/touchend 监听,按下效果保留
- 退格键的 pointer 事件方案在上个 commit 已实现,本次不动

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 11:24:16 +08:00
zhengchen.tao 0fb2dfdc63 fix(numpad): 退格键按下零延迟 + 500ms 长按清空
Build Docker Image / build (push) Has been cancelled
Build Docker Image / deploy (push) Has been cancelled
弃用 @click + @taphold 组合(F7 需 ~750ms 判别 tap vs hold,期间抑制 click 导致单点延迟),改用原生 pointerdown/up/cancel/leave + 自管定时器:

- pointerdown 立即调 backspace()
- 同时启动 500ms 定时器,到点 clear()
- 任何抬起/移出/取消事件取消定时器
- sheet 关闭时也清

行为:单击立即删一位;按住不放先删一位、约 500ms 后清空全部。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 11:14:11 +08:00
2 changed files with 65 additions and 27 deletions
+17 -9
View File
@@ -84,7 +84,8 @@
1 2 3 + 1 2 3 +
C 0 . OK C 0 . OK
``` ```
- ⌫ 单击退格,长按清除;C 清除全部 - ⌫ 单击退格;按住不放先删一位、约 500ms 后清空全部(长按响应细节见 #11 第二阶段)
- C 一键清除全部
- 涉及文件:`src/components/mobile/NumberPadSheet.vue` - 涉及文件:`src/components/mobile/NumberPadSheet.vue`
--- ---
@@ -136,17 +137,24 @@
- Tab 切换动画保持原样(设置中已有开关可控制) - Tab 切换动画保持原样(设置中已有开关可控制)
- 涉及文件:`src/styles/mobile/global.scss` - 涉及文件:`src/styles/mobile/global.scss`
### 11. 🟢 小键盘点击卡顿(修正:范围非全局 ### 11. 🟢 小键盘点击卡顿(三次修正)
**描述:** 移动端点击按钮有延迟感。 **描述:** 移动端小键盘点击有延迟感。
**真因2026-05-02 定位):** **不是**全局点击/接口响应问题。诊断后确认仅小键盘有卡顿,其他按钮正常。根因是上游在 `.numpad-button` 上设了 `touch-action: none`commit `e178a079` "code refactor" by MaysWind),与 F7 内部 tap 处理叠加后让 click 事件合成慢一拍。backspace(个人新增 `.numpad-backspace-button` 类)不受影响,刚好佐证范围 **第一阶段2026-05-02`touch-action: none` 引发的 300ms 双击延迟:** 上游在 `.numpad-button` 上设了 `touch-action: none`commit `e178a079` "code refactor" by MaysWind),与浏览器双击缩放检测叠加后保留了老式 300ms 点击延迟
- 修复:`.numpad-button``touch-action: none` 改为 `touch-action: manipulation`W3C 标准"快速点击"值,禁双击缩放)
**已完成:** **第二阶段(2026-05-08)退格键 `@taphold` 等待 750ms** backspace 单点仍可感知延迟。根因是 `@click` + `@taphold` 让 F7 必须等 ~750ms 判别 tap vs hold,期间 click 被抑制。
- `.numpad-button``touch-action: none` 改为 `touch-action: manipulation` - 修复:弃用 `@click="backspace" @taphold="clear()"`,改为原生 `pointerdown`/`pointerup`/`pointercancel`/`pointerleave` + 自管定时器
- `manipulation` 是 W3C 标准的"快速点击"值:禁双击缩放(消除老 300ms 延迟)但保留 click 事件正常合成 - 行为:单击立即删一位;按住不放先删一位、约 500ms 后清空全部
- 涉及文件:`src/components/mobile/NumberPadSheet.vue`
**附带认知:**#11 假设是"全局点击响应慢"或"接口慢",与 #12 离线缓存挂钩调研。实际诊断后跟那两条都无关,纯 CSS `touch-action` 与框架 tap 处理叠加导致。该认知值得记录避免后续误诊路径 **第三阶段(2026-05-08)所有数字/运算键也延迟:** 第一阶段修完后用户反馈数字键仍有"等一拍"感。怀疑 F7 整套 tap 处理(含 active-state 检测、`fastClicks` 兼容代码、tap-hold 全局监听)即便不显式声明 `@taphold` 也会给 `@click` 加上判别期
- 修复:把所有按键(数字 0-9、运算 ×−+、C 清空、小数点/双零、OK 确认)的 `@click` 全部换成 `@pointerdown.left`
- 原理:`pointerdown` 在按下瞬间触发,绕开 F7 的 tap 合成路径。`.left` 修饰符限制只响应主键(触屏 button=0 始终满足,桌面右键不会误触发)
- F7 的 `.active-state` 视觉反馈基于独立的 touchstart/touchend 监听,不依赖 `@click`,按下视觉效果保留
涉及文件:`src/components/mobile/NumberPadSheet.vue`
**附带认知:**#11 假设是"全局点击响应慢"或"接口慢",与 #12 离线缓存挂钩调研。实际诊断后跟那两条都无关——纯 F7 框架 tap 合成 + 双击缩放 + taphold 检测三者叠加。最终通过完全弃用 `@click` 改 pointer 事件解决。该认知值得记录避免后续误诊路径。
--- ---
+48 -18
View File
@@ -8,7 +8,11 @@
</div> </div>
<div class="numpad-values"> <div class="numpad-values">
<span id="numpad-value" class="numpad-value" :class="currentDisplayNumClass" @click="onDisplayValueClick">{{ currentDisplay }}</span> <span id="numpad-value" class="numpad-value" :class="currentDisplayNumClass" @click="onDisplayValueClick">{{ currentDisplay }}</span>
<f7-button class="numpad-backspace-button" @click="backspace" @taphold="clear()"> <f7-button class="numpad-backspace-button"
@pointerdown="onBackspacePointerDown"
@pointerup="onBackspacePointerEnd"
@pointercancel="onBackspacePointerEnd"
@pointerleave="onBackspacePointerEnd">
<f7-icon class="icon-with-direction" f7="delete_left"></f7-icon> <f7-icon class="icon-with-direction" f7="delete_left"></f7-icon>
</f7-button> </f7-button>
</div> </div>
@@ -21,55 +25,55 @@
</f7-popover> </f7-popover>
<div class="numpad-buttons"> <div class="numpad-buttons">
<f7-button class="numpad-button numpad-button-num" @click="inputNum(7)"> <f7-button class="numpad-button numpad-button-num" @pointerdown.left="inputNum(7)">
<span class="numpad-button-text numpad-button-text-normal">{{ digits[7] }}</span> <span class="numpad-button-text numpad-button-text-normal">{{ digits[7] }}</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-num" @click="inputNum(8)"> <f7-button class="numpad-button numpad-button-num" @pointerdown.left="inputNum(8)">
<span class="numpad-button-text numpad-button-text-normal">{{ digits[8] }}</span> <span class="numpad-button-text numpad-button-text-normal">{{ digits[8] }}</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-num" @click="inputNum(9)"> <f7-button class="numpad-button numpad-button-num" @pointerdown.left="inputNum(9)">
<span class="numpad-button-text numpad-button-text-normal">{{ digits[9] }}</span> <span class="numpad-button-text numpad-button-text-normal">{{ digits[9] }}</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-function no-right-border" @click="setSymbol('×')"> <f7-button class="numpad-button numpad-button-function no-right-border" @pointerdown.left="setSymbol('×')">
<span class="numpad-button-text numpad-button-text-normal">&times;</span> <span class="numpad-button-text numpad-button-text-normal">&times;</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-num" @click="inputNum(4)"> <f7-button class="numpad-button numpad-button-num" @pointerdown.left="inputNum(4)">
<span class="numpad-button-text numpad-button-text-normal">{{ digits[4] }}</span> <span class="numpad-button-text numpad-button-text-normal">{{ digits[4] }}</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-num" @click="inputNum(5)"> <f7-button class="numpad-button numpad-button-num" @pointerdown.left="inputNum(5)">
<span class="numpad-button-text numpad-button-text-normal">{{ digits[5] }}</span> <span class="numpad-button-text numpad-button-text-normal">{{ digits[5] }}</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-num" @click="inputNum(6)"> <f7-button class="numpad-button numpad-button-num" @pointerdown.left="inputNum(6)">
<span class="numpad-button-text numpad-button-text-normal">{{ digits[6] }}</span> <span class="numpad-button-text numpad-button-text-normal">{{ digits[6] }}</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-function no-right-border" @click="setSymbol('')"> <f7-button class="numpad-button numpad-button-function no-right-border" @pointerdown.left="setSymbol('')">
<span class="numpad-button-text numpad-button-text-normal">&minus;</span> <span class="numpad-button-text numpad-button-text-normal">&minus;</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-num" @click="inputNum(1)"> <f7-button class="numpad-button numpad-button-num" @pointerdown.left="inputNum(1)">
<span class="numpad-button-text numpad-button-text-normal">{{ digits[1] }}</span> <span class="numpad-button-text numpad-button-text-normal">{{ digits[1] }}</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-num" @click="inputNum(2)"> <f7-button class="numpad-button numpad-button-num" @pointerdown.left="inputNum(2)">
<span class="numpad-button-text numpad-button-text-normal">{{ digits[2] }}</span> <span class="numpad-button-text numpad-button-text-normal">{{ digits[2] }}</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-num" @click="inputNum(3)"> <f7-button class="numpad-button numpad-button-num" @pointerdown.left="inputNum(3)">
<span class="numpad-button-text numpad-button-text-normal">{{ digits[3] }}</span> <span class="numpad-button-text numpad-button-text-normal">{{ digits[3] }}</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-function no-right-border" @click="setSymbol('+')"> <f7-button class="numpad-button numpad-button-function no-right-border" @pointerdown.left="setSymbol('+')">
<span class="numpad-button-text numpad-button-text-normal">&plus;</span> <span class="numpad-button-text numpad-button-text-normal">&plus;</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-num" @click="clear()"> <f7-button class="numpad-button numpad-button-num" @pointerdown.left="clear()">
<span class="numpad-button-text numpad-button-text-normal">C</span> <span class="numpad-button-text numpad-button-text-normal">C</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-num" @click="inputNum(0)"> <f7-button class="numpad-button numpad-button-num" @pointerdown.left="inputNum(0)">
<span class="numpad-button-text numpad-button-text-normal">{{ digits[0] }}</span> <span class="numpad-button-text numpad-button-text-normal">{{ digits[0] }}</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-num" v-if="supportDecimalSeparator" @click="inputDecimalSeparator()"> <f7-button class="numpad-button numpad-button-num" v-if="supportDecimalSeparator" @pointerdown.left="inputDecimalSeparator()">
<span class="numpad-button-text numpad-button-text-normal">{{ decimalSeparator }}</span> <span class="numpad-button-text numpad-button-text-normal">{{ decimalSeparator }}</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-num" v-if="!supportDecimalSeparator" @click="inputDoubleNum(0)"> <f7-button class="numpad-button numpad-button-num" v-if="!supportDecimalSeparator" @pointerdown.left="inputDoubleNum(0)">
<span class="numpad-button-text numpad-button-text-normal">{{ `${digits[0]}${digits[0]}` }}</span> <span class="numpad-button-text numpad-button-text-normal">{{ `${digits[0]}${digits[0]}` }}</span>
</f7-button> </f7-button>
<f7-button class="numpad-button numpad-button-confirm no-right-border no-bottom-border" fill @click="confirm()"> <f7-button class="numpad-button numpad-button-confirm no-right-border no-bottom-border" fill @pointerdown.left="confirm()">
<span :class="{ 'numpad-button-text': true, 'numpad-button-text-confirm': !currentSymbol }">{{ confirmText }}</span> <span :class="{ 'numpad-button-text': true, 'numpad-button-text-confirm': !currentSymbol }">{{ confirmText }}</span>
</f7-button> </f7-button>
</div> </div>
@@ -326,6 +330,31 @@ function clear(): void {
currentSymbol.value = ''; currentSymbol.value = '';
} }
const BACKSPACE_HOLD_TO_CLEAR_MS = 500;
let backspaceClearTimer: ReturnType<typeof setTimeout> | null = null;
function onBackspacePointerDown(event: PointerEvent): void {
// 按下立刻删一位(消除 F7 taphold 判别期带来的点击延迟)
if (event.button !== undefined && event.button !== 0) {
return;
}
backspace();
if (backspaceClearTimer !== null) {
clearTimeout(backspaceClearTimer);
}
backspaceClearTimer = setTimeout(() => {
clear();
backspaceClearTimer = null;
}, BACKSPACE_HOLD_TO_CLEAR_MS);
}
function onBackspacePointerEnd(): void {
if (backspaceClearTimer !== null) {
clearTimeout(backspaceClearTimer);
backspaceClearTimer = null;
}
}
function paste(): void { function paste(): void {
showPastePopover.value = false; showPastePopover.value = false;
@@ -442,6 +471,7 @@ function onSheetOpen(): void {
} }
function onSheetClosed(): void { function onSheetClosed(): void {
onBackspacePointerEnd();
close(); close();
} }