优化筛选, 增加记住筛选功能

This commit is contained in:
yml2213
2026-06-13 15:46:47 +08:00
parent 9b41b9dc84
commit 55326b7d06
4 changed files with 317 additions and 15 deletions
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { RouterLink, useRouter } from 'vue-router'
import { RouterLink, useRoute, useRouter } from 'vue-router'
import { showToast } from 'vant'
import MobileBottomNav from '@/components/MobileBottomNav.vue'
@@ -22,6 +22,15 @@ import {
type HomeBannerSlide,
} from '@/features/listings/api/homeConfig'
import MobileHomeFilterSheet, { type FilterSection } from './MobileHomeFilterSheet.vue'
import {
decodeHomeQueryJson,
encodeHomeQueryJson,
isSameQuery,
mergeHomeQuery,
mobileHomeFilterQueryKeys,
readQueryString,
type HomeQueryValue,
} from '@/features/listings/composables/useHomeFilterQuery'
import {
getListingChips,
getListingDisplayPrice,
@@ -38,6 +47,7 @@ import {
import { useSessionStore } from '@/stores/session'
const router = useRouter()
const route = useRoute()
const session = useSessionStore()
const loading = ref(false)
const loadingMore = ref(false)
@@ -255,6 +265,8 @@ const visibleZoneOptions = computed(() =>
}))
)
applyRouteQueryToMobileState()
onMounted(() => {
loadListings()
loadHomeConfig()
@@ -269,11 +281,20 @@ onBeforeUnmount(() => {
watch(
() => filterQuerySignature(),
() => {
syncMobileHomeQuery()
loadListings(true)
}
)
watch(
() => route.query,
() => {
applyRouteQueryToMobileState()
}
)
watch(searchValue, () => {
syncMobileHomeQuery()
if (searchDebounceTimer) clearTimeout(searchDebounceTimer)
searchDebounceTimer = setTimeout(() => {
loadListings(true)
@@ -367,6 +388,7 @@ function clearFilters() {
rangeFilters.value = {}
searchValue.value = ''
activeZone.value = 'all'
syncMobileHomeQuery()
}
function buildListingQuery(page: number): PublicListingQuery {
@@ -443,6 +465,57 @@ function parseOptionalNumber(value: string) {
return Number.isFinite(number) ? number : undefined
}
function applyRouteQueryToMobileState() {
const query = route.query
searchValue.value = readQueryString(query, 'keyword')
activeSort.value = readQueryString(query, 'sort') || 'recommended'
activeZone.value = readQueryString(query, 'zone') || 'all'
selectedFilters.value = normalizeSelectedFilters(
decodeHomeQueryJson<Record<string, unknown>>(query, 'filters', {})
)
rangeFilters.value = normalizeRangeFilters(
decodeHomeQueryJson<Record<string, unknown>>(query, 'ranges', {})
)
}
function syncMobileHomeQuery() {
const query = mergeHomeQuery(route.query, mobileHomeFilterQueryKeys, buildMobileHomeQueryValues())
if (isSameQuery(route.query, query)) return
router.replace({ path: route.path, query })
}
function buildMobileHomeQueryValues(): Record<string, HomeQueryValue> {
return {
keyword: searchValue.value.trim() || undefined,
sort: activeSort.value === 'recommended' ? undefined : activeSort.value,
zone: activeZone.value === 'all' ? undefined : activeZone.value,
filters: encodeHomeQueryJson(normalizeSelectedFilters(selectedFilters.value)),
ranges: encodeHomeQueryJson(normalizeRangeFilters(rangeFilters.value)),
}
}
function normalizeSelectedFilters(value: Record<string, unknown>) {
const normalized: Record<string, string[]> = {}
for (const [key, items] of Object.entries(value)) {
if (!Array.isArray(items)) continue
const filters = items.map(item => String(item).trim()).filter(Boolean)
if (filters.length) normalized[key] = filters
}
return normalized
}
function normalizeRangeFilters(value: Record<string, unknown>) {
const normalized: Record<string, { min: string; max: string }> = {}
for (const [key, range] of Object.entries(value)) {
if (!range || typeof range !== 'object' || Array.isArray(range)) continue
const record = range as Record<string, unknown>
const min = record.min === undefined ? '' : String(record.min).trim()
const max = record.max === undefined ? '' : String(record.max).trim()
if (min || max) normalized[key] = { min, max }
}
return normalized
}
function handleWindowScroll() {
showBackTop.value = window.scrollY > 520
if (window.innerHeight + window.scrollY < document.documentElement.scrollHeight - 360) return