fix: 搜索过滤收藏、拼音首字母匹配、清除图片、滑动切换、通知已读
1. 搜索时收藏配方也按关键词过滤,不匹配的隐藏
2. 编辑配方添加精油时支持拼音首字母匹配(如xyc→薰衣草)
3. 品牌设置页清除图片立即保存到后端,不需点保存按钮
4. 左右滑动切换tab,轮播区域内滑动切换图片不触发tab切换
5. 通知列表每条未读通知加"已读"按钮,调用POST /api/notifications/{id}/read
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -39,7 +39,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<div class="main">
|
||||
<div class="main" @touchstart="onSwipeStart" @touchend="onSwipeEnd">
|
||||
<router-view />
|
||||
</div>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { ref, computed, onMounted, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useAuthStore } from './stores/auth'
|
||||
import { useOilsStore } from './stores/oils'
|
||||
@@ -106,6 +106,48 @@ function toggleUserMenu() {
|
||||
showUserMenu.value = !showUserMenu.value
|
||||
}
|
||||
|
||||
// Swipe to switch tabs
|
||||
const swipeStartX = ref(0)
|
||||
const swipeStartY = ref(0)
|
||||
|
||||
// Tab order for swipe navigation (only user-accessible tabs)
|
||||
const tabOrder = computed(() => {
|
||||
const tabs = ['search', 'oils']
|
||||
if (auth.isLoggedIn) {
|
||||
tabs.splice(1, 0, 'manage', 'inventory')
|
||||
}
|
||||
if (auth.isBusiness) tabs.push('projects')
|
||||
return tabs
|
||||
})
|
||||
|
||||
function onSwipeStart(e) {
|
||||
const touch = e.touches[0]
|
||||
swipeStartX.value = touch.clientX
|
||||
swipeStartY.value = touch.clientY
|
||||
}
|
||||
|
||||
function onSwipeEnd(e) {
|
||||
const touch = e.changedTouches[0]
|
||||
const dx = touch.clientX - swipeStartX.value
|
||||
const dy = touch.clientY - swipeStartY.value
|
||||
// Only trigger if horizontal swipe is dominant and > 50px
|
||||
if (Math.abs(dx) < 50 || Math.abs(dy) > Math.abs(dx)) return
|
||||
// Check if the swipe originated inside a carousel (data-no-tab-swipe)
|
||||
if (e.target.closest && e.target.closest('[data-no-tab-swipe]')) return
|
||||
|
||||
const tabs = tabOrder.value
|
||||
const currentIdx = tabs.indexOf(ui.currentSection)
|
||||
if (currentIdx < 0) return
|
||||
|
||||
if (dx < -50 && currentIdx < tabs.length - 1) {
|
||||
// Swipe left -> next tab
|
||||
goSection(tabs[currentIdx + 1])
|
||||
} else if (dx > 50 && currentIdx > 0) {
|
||||
// Swipe right -> previous tab
|
||||
goSection(tabs[currentIdx - 1])
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await auth.initToken()
|
||||
await Promise.all([
|
||||
|
||||
Reference in New Issue
Block a user