支持在线时间跨天并优化发布与筛选体验
允许在线时段 end 早于 start 表示跨天,统一展示「次日」文案;修复移动端价格区间清空后被 sessionStorage 回写;优化 PC/移动端在线时间控件密度与通栏展示。
This commit is contained in:
@@ -85,11 +85,19 @@ function toggleChip(sectionKey: string, value: string) {
|
||||
emit('update:selectedFilters', { ...props.selectedFilters, [sectionKey]: next })
|
||||
}
|
||||
|
||||
/** 仅保留数字与一个小数点,避免 type=number 受控输入删不干净 */
|
||||
function sanitizeRangeInput(value: string) {
|
||||
const cleaned = value.replace(/[^\d.]/g, '')
|
||||
const dot = cleaned.indexOf('.')
|
||||
if (dot === -1) return cleaned
|
||||
return cleaned.slice(0, dot + 1) + cleaned.slice(dot + 1).replace(/\./g, '')
|
||||
}
|
||||
|
||||
function updateRange(sectionKey: string, side: 'min' | 'max', value: string) {
|
||||
const current = props.rangeFilters[sectionKey] || { min: '', max: '' }
|
||||
emit('update:rangeFilters', {
|
||||
...props.rangeFilters,
|
||||
[sectionKey]: { ...current, [side]: value },
|
||||
[sectionKey]: { ...current, [side]: sanitizeRangeInput(value) },
|
||||
})
|
||||
}
|
||||
|
||||
@@ -214,17 +222,21 @@ function sectionTopInBody(section: HTMLElement, body: HTMLElement) {
|
||||
<template v-if="section.type === 'range'">
|
||||
<div class="range-row">
|
||||
<input
|
||||
:value="rangeFilters[section.key]?.min || ''"
|
||||
type="number"
|
||||
:value="rangeFilters[section.key]?.min ?? ''"
|
||||
type="text"
|
||||
inputmode="decimal"
|
||||
pattern="[0-9.]*"
|
||||
autocomplete="off"
|
||||
:placeholder="section.minPlaceholder || '最低'"
|
||||
@input="updateRange(section.key, 'min', ($event.target as HTMLInputElement).value)"
|
||||
/>
|
||||
<span></span>
|
||||
<input
|
||||
:value="rangeFilters[section.key]?.max || ''"
|
||||
type="number"
|
||||
:value="rangeFilters[section.key]?.max ?? ''"
|
||||
type="text"
|
||||
inputmode="decimal"
|
||||
pattern="[0-9.]*"
|
||||
autocomplete="off"
|
||||
:placeholder="section.maxPlaceholder || '最高'"
|
||||
@input="updateRange(section.key, 'max', ($event.target as HTMLInputElement).value)"
|
||||
/>
|
||||
|
||||
@@ -382,13 +382,19 @@ onBeforeUnmount(() => {
|
||||
watch(
|
||||
() => filterQuerySignature(),
|
||||
() => {
|
||||
syncMobileHomeQuery()
|
||||
// 筛选变化时清空旧列表缓存,避免返回时命中过期数据
|
||||
homeCache.clearList()
|
||||
loadListings(true)
|
||||
// 筛选弹层打开时只改本地 state,避免每个按键写 URL/storage 后被旧缓存回写
|
||||
if (filterOpen.value) return
|
||||
applyFilterStateAndReload()
|
||||
}
|
||||
)
|
||||
|
||||
watch(filterOpen, (open, wasOpen) => {
|
||||
// 关闭弹层时再统一同步 URL 并刷新列表
|
||||
if (wasOpen && !open) {
|
||||
applyFilterStateAndReload()
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => route.query,
|
||||
() => {
|
||||
@@ -623,10 +629,20 @@ function applyRouteQueryToMobileState() {
|
||||
rangeFilters.value = nextRanges
|
||||
}
|
||||
|
||||
function applyFilterStateAndReload() {
|
||||
syncMobileHomeQuery()
|
||||
// 筛选变化时清空旧列表缓存,避免返回时命中过期数据
|
||||
homeCache.clearList()
|
||||
loadListings(true)
|
||||
}
|
||||
|
||||
function syncMobileHomeQuery() {
|
||||
const query = mergeHomeQuery(route.query, mobileHomeFilterQueryKeys, buildMobileHomeQueryValues())
|
||||
if (hasHomeQueryValues(query, mobileHomeFilterQueryKeys)) {
|
||||
storeHomeQuery(mobileHomeFilterStorageKey, query)
|
||||
} else {
|
||||
// 筛选被清空时必须清掉 storage,否则 URL 变空会回退读出旧区间(最后一位删不掉)
|
||||
clearStoredHomeQuery(mobileHomeFilterStorageKey)
|
||||
}
|
||||
if (isSameQuery(route.query, query)) return
|
||||
router.replace({ path: route.path, query })
|
||||
|
||||
Reference in New Issue
Block a user