支持在线时间跨天并优化发布与筛选体验

允许在线时段 end 早于 start 表示跨天,统一展示「次日」文案;修复移动端价格区间清空后被 sessionStorage 回写;优化 PC/移动端在线时间控件密度与通栏展示。
This commit is contained in:
yml2213
2026-07-19 17:28:57 +08:00
parent 6450b31129
commit ae79550d78
12 changed files with 410 additions and 136 deletions
@@ -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 })