Files
martial-admin-mini/index.html
DevOps 5349b80cf8 Fix: iOS Safari 双击缩放问题 - UniApp H5 专用解决方案
问题描述:
- 用户在 iOS Safari 上快速点击加分/减分按钮时触发页面缩放
- 影响用户体验,导致操作困难

解决方案:
1. 全局事件拦截(index.html)
   - 拦截 touchstart/touchend 事件,检测快速连续触摸(<350ms)
   - 完全禁用 dblclick 和 gesture 事件
   - 使用 MutationObserver 动态监听 DOM 变化
   - 添加 CSS 强制禁用缩放

2. 组件级优化(modify-score.vue)
   - 使用 touchstart/touchend 替代 click 事件
   - 添加 300ms 防抖机制,忽略快速连续触摸
   - 实现长按连续加减分功能(500ms 后每 100ms 触发一次)
   - H5 平台条件编译,添加原生事件监听器
   - 清理定时器,防止内存泄漏

3. UniApp 特性应用
   - 使用条件编译 #ifdef H5 针对 H5 平台特殊处理
   - 利用 $nextTick 确保 DOM 渲染完成后添加事件监听
   - 保持跨平台兼容性(小程序、App 不受影响)

技术要点:
- touch-action: none 禁用触摸动作
- event.preventDefault() 阻止默认行为
- capture: true 在捕获阶段拦截事件
- passive: false 允许调用 preventDefault()

测试建议:
- 在 iOS Safari 上快速点击按钮,验证不再缩放
- 测试长按功能是否正常工作
- 验证其他平台(微信小程序、Android)不受影响

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 01:24:36 +08:00

239 lines
8.4 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 关键:使用最严格的 viewport 设置 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, viewport-fit=cover">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<title>武术评分系统</title>
<link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />
<style>
* {
/* 允许垂直滚动,但禁用其他触摸动作 */
touch-action: pan-y !important;
-webkit-touch-callout: none !important;
-webkit-tap-highlight-color: transparent !important;
-webkit-user-select: none !important;
user-select: none !important;
}
/* 针对按钮元素完全禁用所有触摸动作 */
button,
.control-btn,
[class*="btn"],
[class*="control"],
.decrease,
.increase {
touch-action: none !important;
-webkit-user-select: none !important;
user-select: none !important;
-webkit-touch-callout: none !important;
pointer-events: auto !important;
}
/* 允许输入框正常交互 */
input, textarea {
touch-action: manipulation !important;
-webkit-user-select: text !important;
user-select: text !important;
}
/* 防止页面整体缩放 */
html, body {
touch-action: pan-y !important;
-ms-touch-action: pan-y !important;
}
</style>
<script>
// UniApp H5 专用iOS Safari 双击缩放终极解决方案
(function() {
'use strict';
var lastTouchEnd = 0;
var touchStartTime = 0;
var touchCount = 0;
var resetTimer = null;
var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
console.log('iOS 检测:', isIOS);
console.log('User Agent:', navigator.userAgent);
// 方案1: 全局拦截 touchstart - 最高优先级
document.addEventListener('touchstart', function(event) {
var now = Date.now();
touchStartTime = now;
// 清除重置计时器
if (resetTimer) {
clearTimeout(resetTimer);
}
// 检查是否是快速连续触摸
var timeSinceLastTouch = now - lastTouchEnd;
if (timeSinceLastTouch < 350) {
touchCount++;
// 如果是第二次或更多次快速触摸,立即阻止
if (touchCount >= 1) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
console.log('阻止快速连续触摸', touchCount, timeSinceLastTouch);
return false;
}
} else {
touchCount = 0;
}
// 600ms 后重置计数器
resetTimer = setTimeout(function() {
touchCount = 0;
}, 600);
}, { passive: false, capture: true });
// 方案2: 全局拦截 touchend
document.addEventListener('touchend', function(event) {
var now = Date.now();
var touchDuration = now - touchStartTime;
var timeSinceLastTouch = now - lastTouchEnd;
// 如果触摸时间很短(<150ms)且距离上次触摸很近(<350ms),很可能是双击
if (touchDuration < 150 && timeSinceLastTouch < 350 && timeSinceLastTouch > 0) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
console.log('阻止疑似双击', touchDuration, timeSinceLastTouch);
return false;
}
lastTouchEnd = now;
}, { passive: false, capture: true });
// 方案3: 完全禁用 dblclick 事件
document.addEventListener('dblclick', function(event) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
console.log('阻止 dblclick 事件');
return false;
}, { passive: false, capture: true });
// 方案4: 禁用手势缩放
document.addEventListener('gesturestart', function(event) {
event.preventDefault();
event.stopPropagation();
console.log('阻止 gesturestart');
}, { passive: false, capture: true });
document.addEventListener('gesturechange', function(event) {
event.preventDefault();
event.stopPropagation();
}, { passive: false, capture: true });
document.addEventListener('gestureend', function(event) {
event.preventDefault();
event.stopPropagation();
}, { passive: false, capture: true });
// 方案5: 监听 click 事件,过滤快速连续点击
var lastClickTime = 0;
document.addEventListener('click', function(event) {
var now = Date.now();
var timeSinceLastClick = now - lastClickTime;
// 如果距离上次点击小于350ms阻止
if (timeSinceLastClick < 350 && timeSinceLastClick > 0) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
console.log('阻止快速连续点击', timeSinceLastClick);
return false;
}
lastClickTime = now;
}, { passive: false, capture: true });
// 方案6: 针对按钮元素的特殊处理
function addButtonProtection() {
var selectors = [
'.control-btn',
'.control-btn.decrease',
'.control-btn.increase',
'button',
'[class*="btn"]'
];
selectors.forEach(function(selector) {
var elements = document.querySelectorAll(selector);
elements.forEach(function(element) {
// 移除所有现有的事件监听器(通过克隆节点)
var newElement = element.cloneNode(true);
element.parentNode.replaceChild(newElement, element);
// 添加新的保护性事件监听器
['touchstart', 'touchend', 'touchmove', 'click', 'dblclick'].forEach(function(eventType) {
newElement.addEventListener(eventType, function(e) {
if (eventType === 'dblclick') {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
return false;
}
}, { passive: false, capture: true });
});
});
});
}
// DOM 加载完成后添加按钮保护
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
setTimeout(addButtonProtection, 100);
// 使用 MutationObserver 监听 DOM 变化
var observer = new MutationObserver(function(mutations) {
addButtonProtection();
});
observer.observe(document.body, {
childList: true,
subtree: true
});
});
} else {
setTimeout(addButtonProtection, 100);
}
// 方案7: 使用 CSS 强制禁用缩放
var style = document.createElement('style');
style.innerHTML = `
* {
touch-action: pan-y !important;
}
.control-btn,
.control-btn *,
button,
button * {
touch-action: none !important;
-webkit-user-select: none !important;
user-select: none !important;
-webkit-touch-callout: none !important;
}
`;
document.head.appendChild(style);
console.log('iOS Safari 双击缩放防护已启用 - UniApp H5 专用版本');
})();
</script>
</head>
<body>
<noscript>
<strong>请开启JavaScript运行本应用</strong>
</noscript>
<div id="app"></div>
</body>
</html>