diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index 0a7e668..b766d69 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -38,7 +38,7 @@
-
+
@@ -167,23 +167,36 @@ function toggleUserMenu() {
}
// ── 左右滑动切换 tab ──
-// 滑动顺序 = visibleTabs 的顺序(根据用户角色动态决定)
-// 轮播区域(data-no-tab-swipe)内的滑动不触发 tab 切换
+// touch-action: pan-y on .main tells the browser to only handle vertical scroll natively,
+// leaving horizontal swipe gestures to our JS handler.
const swipeStartX = ref(0)
const swipeStartY = ref(0)
+const swipeEndX = ref(0)
+const swipeEndY = ref(0)
+const swipeStartTarget = ref(null)
function onSwipeStart(e) {
swipeStartX.value = e.touches[0].clientX
swipeStartY.value = e.touches[0].clientY
+ swipeEndX.value = e.touches[0].clientX
+ swipeEndY.value = e.touches[0].clientY
+ swipeStartTarget.value = e.target
}
-function onSwipeEnd(e) {
- const dx = e.changedTouches[0].clientX - swipeStartX.value
- const dy = e.changedTouches[0].clientY - swipeStartY.value
- // 必须是水平滑动 > 50px,且水平距离大于垂直距离
- if (Math.abs(dx) < 50 || Math.abs(dy) > Math.abs(dx)) return
- // 轮播区域内不触发 tab 切换
- if (e.target.closest && e.target.closest('[data-no-tab-swipe]')) return
+function onSwipeMove(e) {
+ swipeEndX.value = e.touches[0].clientX
+ swipeEndY.value = e.touches[0].clientY
+}
+
+function onSwipeEnd() {
+ const dx = swipeEndX.value - swipeStartX.value
+ const dy = swipeEndY.value - swipeStartY.value
+ // Must be primarily horizontal (>60px) and more horizontal than vertical
+ if (Math.abs(dx) < 60 || Math.abs(dy) > Math.abs(dx)) return
+ // Carousel area excluded
+ if (swipeStartTarget.value?.closest?.('[data-no-tab-swipe]')) return
+ // Skip when modal/overlay is open
+ if (document.querySelector('.modal-overlay, .detail-overlay, .dialog-overlay')) return
const tabs = visibleTabs.value.map(t => t.key)
const currentIdx = tabs.indexOf(ui.currentSection)
@@ -193,8 +206,7 @@ function onSwipeEnd(e) {
if (dx < 0 && currentIdx < tabs.length - 1) nextIdx = currentIdx + 1
else if (dx > 0 && currentIdx > 0) nextIdx = currentIdx - 1
if (nextIdx >= 0) {
- const tab = visibleTabs.value[nextIdx]
- handleTabClick(tab)
+ handleTabClick(visibleTabs.value[nextIdx])
}
}