refactor(listings): 统一移动端与PC端筛选逻辑并支持日消耗与绝密KD

- 统一预设体系:在 useFilterOptions.ts 集中导出 defaultRangePresets,两端共享档位定义,消除移动端私有硬编码档位
- 统一参数模型:在 useHomeFilters.ts 增加 mobileFiltersToHomeFilters,将移动端字典结构标准化转换为领域层 HomeFilters 模型
- 统一查询构建:在 useListingQuery.ts 抽象纯函数 buildListingQueryFromFilters,双端共用同一个后端发包构建器
- 功能对齐:移动端首页完整补充「日消耗」区间筛选;PC端高级抽屉对齐补充「绝密KD」筛选
- 验证通过:补充双端测试用例,全站门禁 ./scripts/check.sh(SQL/Go/MySQL/Vitest/Vite构建)全部绿灯
This commit is contained in:
yml2213
2026-10-10 16:48:16 +08:00
parent 95435faf46
commit 03d20223c8
7 changed files with 403 additions and 146 deletions
@@ -11,6 +11,7 @@ import {
totalRangeOptions,
fireLevelRangeOptions,
dailyLossRangeOptions,
secretKdRangeOptions,
isRangeSelected,
} from '@/features/listings/composables/useFilterOptions'
import type { ListingPublishOptions } from '@/features/listings/api/listingOptions'
@@ -72,6 +73,7 @@ function toggleRange(
| 'minTotal'
| 'minFireLevel'
| 'minDailyLoss'
| 'minSecretKd'
| 'minAwmAmmo',
maxKey:
| 'maxCoin'
@@ -81,6 +83,7 @@ function toggleRange(
| 'maxTotal'
| 'maxFireLevel'
| 'maxDailyLoss'
| 'maxSecretKd'
| 'maxAwmAmmo',
option: RangeOption
) {
@@ -102,6 +105,7 @@ function isRangeActive(
| 'minTotal'
| 'minFireLevel'
| 'minDailyLoss'
| 'minSecretKd'
| 'minAwmAmmo',
maxKey:
| 'maxCoin'
@@ -111,6 +115,7 @@ function isRangeActive(
| 'maxTotal'
| 'maxFireLevel'
| 'maxDailyLoss'
| 'maxSecretKd'
| 'maxAwmAmmo',
option: RangeOption
) {
@@ -375,6 +380,22 @@ const redSkinGroup = computed(() =>
</div>
</div>
<div class="filter-field">
<label>绝密KD</label>
<div class="pill-row">
<button
v-for="item in secretKdRangeOptions.filter(o => o.label !== '全部')"
:key="`kd-${item.label}`"
type="button"
class="pill-chip"
:class="{ active: isRangeActive('minSecretKd', 'maxSecretKd', item) }"
@click="toggleRange('minSecretKd', 'maxSecretKd', item)"
>
{{ item.label }}
</button>
</div>
</div>
<div class="filter-field">
<label>段位</label>
<div class="pill-row">
@@ -2,10 +2,12 @@ import { describe, it, expect } from 'vitest'
import {
awmRangeOptions,
depositRangeOptions,
defaultRangePresets,
isRangeSelected,
moneyRangeOptions,
rangeLabel,
ratioRangeOptions,
secretKdRangeOptions,
} from '@/features/listings/composables/useFilterOptions'
describe('useFilterOptions', () => {
@@ -65,4 +67,32 @@ describe('useFilterOptions', () => {
max: undefined,
})
})
it('应该包含绝密KD预设选项', () => {
expect(secretKdRangeOptions.map(option => option.label)).toEqual([
'全部',
'1-2',
'2-3',
'3-5',
'5以上',
])
})
it('defaultRangePresets 应该为移动端提供统一的日消耗与绝密KD档位', () => {
expect(defaultRangePresets.dailyLoss).toEqual([
{ label: '≤10', min: '', max: '10' },
{ label: '10-20', min: '10', max: '20' },
{ label: '20-30', min: '20', max: '30' },
{ label: '30-40', min: '30', max: '40' },
{ label: '40以上', min: '40', max: '' },
])
expect(defaultRangePresets.secretKd).toEqual([
{ label: '1-2', min: '1', max: '2' },
{ label: '2-3', min: '2', max: '3' },
{ label: '3-5', min: '3', max: '5' },
{ label: '5以上', min: '5', max: '' },
])
expect(defaultRangePresets.price.length).toBeGreaterThan(0)
expect(defaultRangePresets.coin.length).toBeGreaterThan(0)
})
})
@@ -1,5 +1,9 @@
import { describe, it, expect } from 'vitest'
import { useHomeFilters } from '@/features/listings/composables/useHomeFilters'
import {
useHomeFilters,
mobileFiltersToHomeFilters,
} from '@/features/listings/composables/useHomeFilters'
import { buildListingQueryFromFilters } from '@/features/listings/composables/useListingQuery'
import { ref } from 'vue'
import { emptyListingPublishOptions } from '@/features/listings/api/listingOptions'
@@ -90,4 +94,110 @@ describe('useHomeFilters', () => {
expect(filters.minCoin).toBe(100)
expect(filters.maxCoin).toBe(500)
})
it('应该支持绝密KD与日消耗并正确统计高级筛选数量', () => {
const publishOptions = ref(emptyListingPublishOptions)
const listings = ref([])
const { filters, advancedActiveCount, setDailyLossRange, setSecretKdRange, resetFilters } =
useHomeFilters(publishOptions, listings)
expect(advancedActiveCount.value).toBe(0)
setDailyLossRange(10, 20)
expect(filters.minDailyLoss).toBe(10)
expect(filters.maxDailyLoss).toBe(20)
expect(advancedActiveCount.value).toBe(1)
setSecretKdRange(2, 3)
expect(filters.minSecretKd).toBe(2)
expect(filters.maxSecretKd).toBe(3)
expect(advancedActiveCount.value).toBe(2)
resetFilters()
expect(filters.minDailyLoss).toBeUndefined()
expect(filters.maxDailyLoss).toBeUndefined()
expect(filters.minSecretKd).toBeUndefined()
expect(filters.maxSecretKd).toBeUndefined()
expect(advancedActiveCount.value).toBe(0)
})
describe('mobileFiltersToHomeFilters & buildListingQueryFromFilters', () => {
it('应该正确转换移动端结构为统一 HomeFilters 并生成对齐的查询参数', () => {
const selectedFilters = {
server: ['微信区'],
region: ['北京', '上海'],
login: ['账密'],
rank: ['大师'],
insurance: ['3*3'],
melee: ['小刀'],
}
const rangeFilters = {
price: { min: '50', max: '100' },
coin: { min: '100', max: '300' },
dailyLoss: { min: '10', max: '20' },
secretKd: { min: '2', max: '3' },
resource_awmAmmo: { min: '50', max: '100' },
resource_testItem: { min: '1', max: '5' },
}
const homeFilters = mobileFiltersToHomeFilters(selectedFilters, rangeFilters, '搜索关键字', [
'melee',
])
expect(homeFilters.keyword).toBe('搜索关键字')
expect(homeFilters.server).toBe('微信区')
expect(homeFilters.region).toEqual(['北京', '上海'])
expect(homeFilters.loginMethod).toEqual(['账密'])
expect(homeFilters.rank).toEqual(['大师'])
expect(homeFilters.insurance).toEqual(['3*3'])
expect(homeFilters.skinGroups).toEqual(['melee'])
expect(homeFilters.skinNames).toEqual(['小刀'])
expect(homeFilters.minPrice).toBe(50)
expect(homeFilters.maxPrice).toBe(100)
expect(homeFilters.minCoin).toBe(100)
expect(homeFilters.maxCoin).toBe(300)
expect(homeFilters.minDailyLoss).toBe(10)
expect(homeFilters.maxDailyLoss).toBe(20)
expect(homeFilters.minSecretKd).toBe(2)
expect(homeFilters.maxSecretKd).toBe(3)
expect(homeFilters.minAwmAmmo).toBe(50)
expect(homeFilters.maxAwmAmmo).toBe(100)
expect(homeFilters.resources).toEqual({ testItem: { min: 1, max: 5 } })
const query = buildListingQueryFromFilters(homeFilters, {
page: 1,
pageSize: 10,
sort: 'recommended',
zone: 'all',
})
expect(query).toMatchObject({
page: 1,
page_size: 10,
keyword: '搜索关键字',
sort: 'recommended',
zone: 'all',
server: '微信区',
region: '北京,上海',
login_method: '账密',
rank: '大师',
insurance: '3*3',
skin_group: 'melee',
skin_name: '小刀',
min_price: 50,
max_price: 100,
min_coin: 100,
max_coin: 300,
min_daily_loss: 10,
max_daily_loss: 20,
min_secret_kd: 2,
max_secret_kd: 3,
resource_awmAmmo_min: 50,
resource_awmAmmo_max: 100,
resource_testItem_min: 1,
resource_testItem_max: 5,
})
})
})
})
@@ -71,6 +71,44 @@ export const dailyLossRangeOptions = [
{ label: '40以上', min: 40, max: undefined },
]
export const secretKdRangeOptions = [
{ label: '全部', min: undefined, max: undefined },
{ label: '1-2', min: 1, max: 2 },
{ label: '2-3', min: 2, max: 3 },
{ label: '3-5', min: 3, max: 5 },
{ label: '5以上', min: 5, max: undefined },
]
export interface RangePresetOption {
label: string
min: string
max: string
}
export function toRangePresets(
options: Array<{ label: string; min?: number; max?: number }>
): RangePresetOption[] {
return options
.filter(option => option.label !== '全部')
.map(option => ({
label: option.label,
min: option.min === undefined ? '' : String(option.min),
max: option.max === undefined ? '' : String(option.max),
}))
}
export const defaultRangePresets: Record<string, RangePresetOption[]> = {
price: toRangePresets(moneyRangeOptions),
coin: toRangePresets(coinRangeOptions),
ratio: toRangePresets(ratioRangeOptions),
deposit: toRangePresets(depositRangeOptions),
total: toRangePresets(totalRangeOptions),
fireLevel: toRangePresets(fireLevelRangeOptions),
dailyLoss: toRangePresets(dailyLossRangeOptions),
secretKd: toRangePresets(secretKdRangeOptions),
resource_awmAmmo: toRangePresets(awmRangeOptions),
}
export function rangeLabel(min: number | undefined, max: number | undefined, fallback: string) {
if (min !== undefined && max !== undefined) return `${min}-${max}`
if (min !== undefined) return `${min}+`
@@ -55,6 +55,13 @@ export interface HomeFilters {
/** 日消耗(M/天)区间 */
minDailyLoss: number | undefined
maxDailyLoss: number | undefined
/** 绝密KD区间 */
minSecretKd?: number | undefined
maxSecretKd?: number | undefined
/** 皮肤分类列表 */
skinGroups?: string[] | undefined
/** 动态资源区间 */
resources?: Record<string, { min?: number; max?: number }> | undefined
/** AWM 子弹数量区间 */
minAwmAmmo: number | undefined
maxAwmAmmo: number | undefined
@@ -66,6 +73,107 @@ export interface SkinFilterGroup {
options: string[]
}
function parseOptionalNumber(value: string | undefined): number | undefined {
if (!value || value.trim() === '') return undefined
const num = Number(value.trim())
return Number.isFinite(num) ? num : undefined
}
/** 将移动端筛选抽屉的 (selectedFilters, rangeFilters) 映射为统一的 HomeFilters 模型 */
export function mobileFiltersToHomeFilters(
selectedFilters: Record<string, string[]>,
rangeFilters: Record<string, { min: string; max: string }>,
keyword = '',
knownSkinGroupKeys: string[] = []
): HomeFilters {
const isSkinGroup = (key: string) =>
knownSkinGroupKeys.includes(key) || key === 'melee' || key === 'operatorRed' || key === 'weapon'
const skinGroups: string[] = []
const skinNames: string[] = []
let server = ''
const region: string[] = []
const loginMethod: string[] = []
const rank: string[] = []
const insurance: string[] = []
const stamina: string[] = []
const load: string[] = []
for (const [key, values] of Object.entries(selectedFilters)) {
const validValues = values.map(v => v.trim()).filter(Boolean)
if (!validValues.length) continue
if (key === 'server') {
server = validValues.join(',')
} else if (key === 'region') {
region.push(...validValues)
} else if (key === 'login') {
loginMethod.push(...validValues)
} else if (key === 'rank') {
rank.push(...validValues)
} else if (key === 'insurance') {
insurance.push(...validValues)
} else if (key === 'stamina') {
stamina.push(...validValues)
} else if (key === 'load') {
load.push(...validValues)
} else if (isSkinGroup(key)) {
skinGroups.push(key)
skinNames.push(...validValues)
}
}
const resources: Record<string, { min?: number; max?: number }> = {}
let minAwmAmmo: number | undefined
let maxAwmAmmo: number | undefined
for (const [key, range] of Object.entries(rangeFilters)) {
if (key.startsWith('resource_')) {
const resKey = key.replace('resource_', '')
const min = parseOptionalNumber(range.min)
const max = parseOptionalNumber(range.max)
if (resKey === 'awmAmmo') {
minAwmAmmo = min
maxAwmAmmo = max
} else if (min !== undefined || max !== undefined) {
resources[resKey] = { min, max }
}
}
}
return {
keyword,
server,
region,
loginMethod,
rank,
insurance,
stamina,
load,
skinNames,
skinGroups: skinGroups.length ? skinGroups : undefined,
resources: Object.keys(resources).length ? resources : undefined,
minCoin: parseOptionalNumber(rangeFilters.coin?.min),
maxCoin: parseOptionalNumber(rangeFilters.coin?.max),
minRatio: parseOptionalNumber(rangeFilters.ratio?.min),
maxRatio: parseOptionalNumber(rangeFilters.ratio?.max),
minPrice: parseOptionalNumber(rangeFilters.price?.min),
maxPrice: parseOptionalNumber(rangeFilters.price?.max),
minDeposit: parseOptionalNumber(rangeFilters.deposit?.min),
maxDeposit: parseOptionalNumber(rangeFilters.deposit?.max),
minTotal: parseOptionalNumber(rangeFilters.total?.min),
maxTotal: parseOptionalNumber(rangeFilters.total?.max),
minFireLevel: parseOptionalNumber(rangeFilters.fireLevel?.min),
maxFireLevel: parseOptionalNumber(rangeFilters.fireLevel?.max),
minDailyLoss: parseOptionalNumber(rangeFilters.dailyLoss?.min),
maxDailyLoss: parseOptionalNumber(rangeFilters.dailyLoss?.max),
minSecretKd: parseOptionalNumber(rangeFilters.secretKd?.min),
maxSecretKd: parseOptionalNumber(rangeFilters.secretKd?.max),
minAwmAmmo,
maxAwmAmmo,
}
}
export function useHomeFilters(
publishOptions: Ref<ListingPublishOptions>,
listings: Ref<PublicListingItem[]>
@@ -94,6 +202,8 @@ export function useHomeFilters(
maxFireLevel: undefined,
minDailyLoss: undefined,
maxDailyLoss: undefined,
minSecretKd: undefined,
maxSecretKd: undefined,
minAwmAmmo: undefined,
maxAwmAmmo: undefined,
})
@@ -159,6 +269,7 @@ export function useHomeFilters(
if (filters.minTotal !== undefined || filters.maxTotal !== undefined) count += 1
if (filters.minFireLevel !== undefined || filters.maxFireLevel !== undefined) count += 1
if (filters.minDailyLoss !== undefined || filters.maxDailyLoss !== undefined) count += 1
if (filters.minSecretKd !== undefined || filters.maxSecretKd !== undefined) count += 1
return count
})
@@ -190,6 +301,8 @@ export function useHomeFilters(
filters.maxFireLevel = undefined
filters.minDailyLoss = undefined
filters.maxDailyLoss = undefined
filters.minSecretKd = undefined
filters.maxSecretKd = undefined
filters.minAwmAmmo = undefined
filters.maxAwmAmmo = undefined
}
@@ -249,6 +362,11 @@ export function useHomeFilters(
filters.maxDailyLoss = max
}
function setSecretKdRange(min: number | undefined, max: number | undefined) {
filters.minSecretKd = min
filters.maxSecretKd = max
}
function setAwmAmmoRange(min: number | undefined, max: number | undefined) {
filters.minAwmAmmo = min
filters.maxAwmAmmo = max
@@ -302,6 +420,7 @@ export function useHomeFilters(
setTotalRange,
setFireLevelRange,
setDailyLossRange,
setSecretKdRange,
setAwmAmmoRange,
toggleRange,
setFilterPopover,
@@ -4,6 +4,65 @@ import type { HomeFilters } from './useHomeFilters'
const homePageSize = 12
function joinCSV(values: string[] | undefined) {
if (!values?.length) return undefined
return values.filter(Boolean).join(',') || undefined
}
export function buildListingQueryFromFilters(
filters: HomeFilters,
options: {
page: number
pageSize: number
sort?: string
zone?: string
}
): PublicListingQuery {
const query: PublicListingQuery = {
page: options.page,
page_size: options.pageSize,
keyword: filters.keyword?.trim() || undefined,
sort: options.sort,
zone: options.zone,
server: filters.server || undefined,
region: joinCSV(filters.region),
login_method: joinCSV(filters.loginMethod),
rank: joinCSV(filters.rank),
insurance: joinCSV(filters.insurance),
stamina: joinCSV(filters.stamina),
load: joinCSV(filters.load),
skin_group: joinCSV(filters.skinGroups),
skin_name: joinCSV(filters.skinNames),
min_coin: filters.minCoin,
max_coin: filters.maxCoin,
min_ratio: filters.minRatio,
max_ratio: filters.maxRatio,
min_price: filters.minPrice,
max_price: filters.maxPrice,
min_deposit: filters.minDeposit,
max_deposit: filters.maxDeposit,
min_total: filters.minTotal,
max_total: filters.maxTotal,
min_fire_level: filters.minFireLevel,
max_fire_level: filters.maxFireLevel,
min_daily_loss: filters.minDailyLoss,
max_daily_loss: filters.maxDailyLoss,
min_secret_kd: filters.minSecretKd,
max_secret_kd: filters.maxSecretKd,
resource_awmAmmo_min: filters.minAwmAmmo,
resource_awmAmmo_max: filters.maxAwmAmmo,
}
if (filters.resources) {
for (const [key, range] of Object.entries(filters.resources)) {
if (range.min !== undefined) query[`resource_${key}_min`] = range.min
if (range.max !== undefined) query[`resource_${key}_max`] = range.max
}
}
return query
}
export function useListingQuery(
filters: HomeFilters,
sortBy: Ref<string>,
@@ -18,43 +77,13 @@ export function useListingQuery(
const hasMoreListings = ref(true)
let listingRequestSeq = 0
function joinCSV(values: string[]) {
return values.filter(Boolean).join(',') || undefined
}
function buildListingQuery(page: number): PublicListingQuery {
return {
return buildListingQueryFromFilters(filters, {
page,
page_size: homePageSize,
keyword: filters.keyword.trim(),
pageSize: homePageSize,
sort: sortBy.value,
zone: activeZone.value,
server: filters.server,
region: joinCSV(filters.region),
login_method: joinCSV(filters.loginMethod),
rank: joinCSV(filters.rank),
insurance: joinCSV(filters.insurance),
stamina: joinCSV(filters.stamina),
load: joinCSV(filters.load),
// 多选皮肤名;后端 skin_name CSV 为 AND 匹配(账号需包含所有选中皮肤)
skin_name: joinCSV(filters.skinNames),
min_coin: filters.minCoin,
max_coin: filters.maxCoin,
min_ratio: filters.minRatio,
max_ratio: filters.maxRatio,
min_price: filters.minPrice,
max_price: filters.maxPrice,
min_deposit: filters.minDeposit,
max_deposit: filters.maxDeposit,
min_total: filters.minTotal,
max_total: filters.maxTotal,
min_fire_level: filters.minFireLevel,
max_fire_level: filters.maxFireLevel,
min_daily_loss: filters.minDailyLoss,
max_daily_loss: filters.maxDailyLoss,
resource_awmAmmo_min: filters.minAwmAmmo,
resource_awmAmmo_max: filters.maxAwmAmmo,
}
})
}
function listingQuerySignature() {
@@ -40,7 +40,9 @@ import {
storeHomeQuery,
type HomeQueryValue,
} from '@/features/listings/composables/useHomeFilterQuery'
import { depositRangeOptions } from '@/features/listings/composables/useFilterOptions'
import { defaultRangePresets } from '@/features/listings/composables/useFilterOptions'
import { mobileFiltersToHomeFilters } from '@/features/listings/composables/useHomeFilters'
import { buildListingQueryFromFilters } from '@/features/listings/composables/useListingQuery'
import {
getListingChips,
getListingDisplayPrice,
@@ -139,51 +141,8 @@ const zoneOptions = [
{ key: 'highCoin', label: '高币', hint: '100M以上' },
]
/** 押金档位直接复用首页高级筛选项,保证移动端与桌面端完全一致 */
const depositPresets = depositRangeOptions
.filter(option => option.label !== '全部')
.map(option => ({
label: option.label,
min: option.min === undefined ? '' : String(option.min),
max: option.max === undefined ? '' : String(option.max),
}))
const rangePresets: Record<string, Array<{ label: string; min: string; max: string }>> = {
price: [
{ label: '50-100', min: '50', max: '100' },
{ label: '100-200', min: '100', max: '200' },
{ label: '200以上', min: '200', max: '' },
],
coin: [
{ label: '0-100', min: '0', max: '100' },
{ label: '100-300', min: '100', max: '300' },
{ label: '300-500', min: '300', max: '500' },
{ label: '500以上', min: '500', max: '' },
],
ratio: [
{ label: '30-40', min: '30', max: '40' },
{ label: '40以上', min: '40', max: '' },
],
deposit: depositPresets,
total: [
{ label: '0-500', min: '0', max: '500' },
{ label: '500-1000', min: '500', max: '1000' },
{ label: '1000-2000', min: '1000', max: '2000' },
{ label: '2000-5000', min: '2000', max: '5000' },
],
fireLevel: [
{ label: '38-50', min: '38', max: '50' },
{ label: '50-60', min: '50', max: '60' },
{ label: '60-70', min: '60', max: '70' },
{ label: '70以上', min: '70', max: '' },
],
resource_awmAmmo: [
{ label: '20-50', min: '20', max: '50' },
{ label: '50-100', min: '50', max: '100' },
{ label: '100-200', min: '100', max: '200' },
{ label: '200以上', min: '200', max: '' },
],
}
/** 统一使用领域层导出的预设区间,保证与桌面端完全一致 */
const rangePresets = defaultRangePresets
const activeSortLabel = computed(
() => sortOptions.find(option => option.key === activeSort.value)?.label || '综合排序'
@@ -279,6 +238,14 @@ const filterSections = computed<FilterSection[]>(() => [
minPlaceholder: '最低',
maxPlaceholder: '最高',
},
{
key: 'dailyLoss',
title: '日消耗',
type: 'range',
unit: 'M/天',
minPlaceholder: '最低',
maxPlaceholder: '最高',
},
{
key: 'fireLevel',
title: '等级',
@@ -602,65 +569,18 @@ function clearFilters() {
}
function buildListingQuery(page: number): PublicListingQuery {
const query: PublicListingQuery = {
const homeFilters = mobileFiltersToHomeFilters(
selectedFilters.value,
rangeFilters.value,
searchValue.value,
publishOptions.value.skin_groups.map(group => group.key)
)
return buildListingQueryFromFilters(homeFilters, {
page,
page_size: mobilePageSize,
keyword: searchValue.value.trim(),
pageSize: mobilePageSize,
sort: activeSort.value,
zone: activeZone.value,
}
const skinGroups: string[] = []
const skinNames: string[] = []
for (const [key, values] of Object.entries(selectedFilters.value)) {
const value = values.filter(Boolean).join(',')
if (!value) continue
if (key === 'server') query.server = value
else if (key === 'region') query.region = value
else if (key === 'login') query.login_method = value
else if (key === 'insurance') query.insurance = value
else if (key === 'stamina') query.stamina = value
else if (key === 'load') query.load = value
else if (key === 'rank') query.rank = value
else if (isSkinGroupKey(key)) {
skinGroups.push(key)
skinNames.push(...values)
}
}
if (skinGroups.length) query.skin_group = skinGroups.join(',')
if (skinNames.length) query.skin_name = skinNames.join(',')
for (const [key, range] of Object.entries(rangeFilters.value)) {
if (!range.min && !range.max) continue
const min = parseOptionalNumber(range.min)
const max = parseOptionalNumber(range.max)
if (key === 'price') {
query.min_price = min
query.max_price = max
} else if (key === 'coin') {
query.min_coin = min
query.max_coin = max
} else if (key === 'ratio') {
query.min_ratio = min
query.max_ratio = max
} else if (key === 'secretKd') {
query.min_secret_kd = min
query.max_secret_kd = max
} else if (key === 'deposit') {
query.min_deposit = min
query.max_deposit = max
} else if (key === 'total') {
query.min_total = min
query.max_total = max
} else if (key === 'fireLevel') {
query.min_fire_level = min
query.max_fire_level = max
} else if (key.startsWith('resource_')) {
const resourceKey = key.replace('resource_', '')
query[`resource_${resourceKey}_min`] = min
query[`resource_${resourceKey}_max`] = max
}
}
return query
})
}
function filterQuerySignature() {
@@ -672,12 +592,6 @@ function filterQuerySignature() {
})
}
function parseOptionalNumber(value: string) {
if (value === '') return undefined
const number = Number(value)
return Number.isFinite(number) ? number : undefined
}
function applyRouteQueryToMobileState() {
const storedQuery = readStoredHomeQuery(mobileHomeFilterStorageKey)
const query = hasHomeQueryValues(route.query, mobileHomeFilterQueryKeys)
@@ -776,10 +690,6 @@ function scrollToTop() {
homeCache.saveScrollTop(0)
}
function isSkinGroupKey(key: string) {
return publishOptions.value.skin_groups.some(group => group.key === key)
}
function parseQuantityUnit(price: string) {
const unit = price.split('/')[1]?.trim()
return unit || undefined