筛选增加多选功能
This commit is contained in:
@@ -8,6 +8,8 @@ import {
|
||||
isSameQuery,
|
||||
mergeHomeQuery,
|
||||
readStoredHomeQuery,
|
||||
joinQueryCSV,
|
||||
readQueryCSV,
|
||||
readQueryNumber,
|
||||
readQueryString,
|
||||
storeHomeQuery,
|
||||
@@ -26,6 +28,14 @@ describe('useHomeFilterQuery', () => {
|
||||
expect(readQueryNumber(query, 'max_coin')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('应该读写 CSV 多选筛选参数', () => {
|
||||
expect(readQueryCSV({ insurance: '3*3,2*2,3*3' }, 'insurance')).toEqual(['3*3', '2*2'])
|
||||
expect(readQueryCSV({ insurance: '3*3' }, 'insurance')).toEqual(['3*3'])
|
||||
expect(readQueryCSV({}, 'insurance')).toEqual([])
|
||||
expect(joinQueryCSV(['3*3', '2*2', '3*3'])).toBe('3*3,2*2')
|
||||
expect(joinQueryCSV([])).toBeUndefined()
|
||||
})
|
||||
|
||||
it('应该合并新筛选并移除旧的托管参数', () => {
|
||||
const query = mergeHomeQuery(
|
||||
{ keyword: '旧关键词', page: '2', region: '上海' },
|
||||
|
||||
@@ -11,6 +11,8 @@ describe('useHomeFilters', () => {
|
||||
const { filters } = useHomeFilters(publishOptions, listings)
|
||||
|
||||
expect(filters.keyword).toBe('')
|
||||
expect(filters.region).toEqual([])
|
||||
expect(filters.insurance).toEqual([])
|
||||
expect(filters.minCoin).toBeUndefined()
|
||||
expect(filters.maxCoin).toBeUndefined()
|
||||
})
|
||||
@@ -23,24 +25,42 @@ describe('useHomeFilters', () => {
|
||||
|
||||
filters.keyword = '测试'
|
||||
filters.minCoin = 100
|
||||
filters.region = '北京'
|
||||
filters.region = ['北京', '上海']
|
||||
filters.insurance = ['3*3', '2*2']
|
||||
|
||||
resetFilters()
|
||||
|
||||
expect(filters.keyword).toBe('')
|
||||
expect(filters.minCoin).toBeUndefined()
|
||||
expect(filters.region).toBe('')
|
||||
expect(filters.region).toEqual([])
|
||||
expect(filters.insurance).toEqual([])
|
||||
})
|
||||
|
||||
it('应该正确设置字符串筛选器', () => {
|
||||
it('应该正确设置字符串多选筛选器', () => {
|
||||
const publishOptions = ref(emptyListingPublishOptions)
|
||||
const listings = ref([])
|
||||
|
||||
const { filters, setStringFilter } = useHomeFilters(publishOptions, listings)
|
||||
|
||||
setStringFilter('region', '上海')
|
||||
expect(filters.region).toEqual(['上海'])
|
||||
|
||||
expect(filters.region).toBe('上海')
|
||||
setStringFilter('region', ['北京', '上海', '上海'])
|
||||
expect(filters.region).toEqual(['北京', '上海'])
|
||||
})
|
||||
|
||||
it('应该支持切换字符串筛选项', () => {
|
||||
const publishOptions = ref(emptyListingPublishOptions)
|
||||
const listings = ref([])
|
||||
|
||||
const { filters, toggleStringFilter } = useHomeFilters(publishOptions, listings)
|
||||
|
||||
toggleStringFilter('insurance', '3*3')
|
||||
toggleStringFilter('insurance', '2*2')
|
||||
expect(filters.insurance).toEqual(['3*3', '2*2'])
|
||||
|
||||
toggleStringFilter('insurance', '3*3')
|
||||
expect(filters.insurance).toEqual(['2*2'])
|
||||
})
|
||||
|
||||
it('应该正确设置范围筛选器', () => {
|
||||
|
||||
@@ -48,6 +48,20 @@ export function readQueryNumber(query: LocationQuery | LocationQueryRaw, key: st
|
||||
return Number.isFinite(number) ? number : undefined
|
||||
}
|
||||
|
||||
/** 读取 CSV 多选筛选参数,兼容旧版单值与逗号分隔多值。 */
|
||||
export function readQueryCSV(query: LocationQuery | LocationQueryRaw, key: string): string[] {
|
||||
const raw = readQueryString(query, key)
|
||||
if (!raw) return []
|
||||
return [...new Set(raw.split(',').map(item => item.trim()).filter(Boolean))]
|
||||
}
|
||||
|
||||
/** 将多选数组序列化为 CSV;空数组返回 undefined 以便从 query 中省略。 */
|
||||
export function joinQueryCSV(values: string[] | undefined | null): string | undefined {
|
||||
if (!values?.length) return undefined
|
||||
const joined = [...new Set(values.map(item => item.trim()).filter(Boolean))].join(',')
|
||||
return joined || undefined
|
||||
}
|
||||
|
||||
export function mergeHomeQuery(
|
||||
currentQuery: LocationQuery,
|
||||
managedKeys: readonly string[],
|
||||
|
||||
@@ -23,12 +23,12 @@ export type StringFilterKey = 'insurance' | 'stamina' | 'load' | 'region' | 'ran
|
||||
export interface HomeFilters {
|
||||
keyword: string
|
||||
server: string
|
||||
region: string
|
||||
loginMethod: string
|
||||
rank: string
|
||||
insurance: string
|
||||
stamina: string
|
||||
load: string
|
||||
region: string[]
|
||||
loginMethod: string[]
|
||||
rank: string[]
|
||||
insurance: string[]
|
||||
stamina: string[]
|
||||
load: string[]
|
||||
skinGroup: string
|
||||
skinName: string
|
||||
minCoin: number | undefined
|
||||
@@ -52,12 +52,12 @@ export function useHomeFilters(
|
||||
const filters = reactive<HomeFilters>({
|
||||
keyword: '',
|
||||
server: '',
|
||||
region: '',
|
||||
loginMethod: '',
|
||||
rank: '',
|
||||
insurance: '',
|
||||
stamina: '',
|
||||
load: '',
|
||||
region: [],
|
||||
loginMethod: [],
|
||||
rank: [],
|
||||
insurance: [],
|
||||
stamina: [],
|
||||
load: [],
|
||||
skinGroup: '',
|
||||
skinName: '',
|
||||
minCoin: undefined,
|
||||
@@ -111,12 +111,12 @@ export function useHomeFilters(
|
||||
function resetFilters() {
|
||||
filters.keyword = ''
|
||||
filters.server = ''
|
||||
filters.region = ''
|
||||
filters.loginMethod = ''
|
||||
filters.rank = ''
|
||||
filters.insurance = ''
|
||||
filters.stamina = ''
|
||||
filters.load = ''
|
||||
filters.region = []
|
||||
filters.loginMethod = []
|
||||
filters.rank = []
|
||||
filters.insurance = []
|
||||
filters.stamina = []
|
||||
filters.load = []
|
||||
filters.skinGroup = ''
|
||||
filters.skinName = ''
|
||||
filters.minCoin = undefined
|
||||
@@ -133,11 +133,23 @@ export function useHomeFilters(
|
||||
filters.maxFireLevel = undefined
|
||||
}
|
||||
|
||||
function setStringFilter(key: StringFilterKey, value: string) {
|
||||
filters[key] = value
|
||||
function setStringFilter(key: StringFilterKey, value: string | string[]) {
|
||||
filters[key] = Array.isArray(value)
|
||||
? uniqueOptions(value)
|
||||
: value.trim()
|
||||
? [value.trim()]
|
||||
: []
|
||||
closeFilterPopover()
|
||||
}
|
||||
|
||||
function toggleStringFilter(key: StringFilterKey, value: string) {
|
||||
const current = filters[key]
|
||||
const next = current.includes(value)
|
||||
? current.filter(item => item !== value)
|
||||
: uniqueOptions([...current, value])
|
||||
filters[key] = next
|
||||
}
|
||||
|
||||
function setCoinRange(min: number | undefined, max: number | undefined) {
|
||||
filters.minCoin = min
|
||||
filters.maxCoin = max
|
||||
@@ -194,6 +206,7 @@ export function useHomeFilters(
|
||||
skinChipLabel,
|
||||
resetFilters,
|
||||
setStringFilter,
|
||||
toggleStringFilter,
|
||||
setCoinRange,
|
||||
setPriceRange,
|
||||
setDepositRange,
|
||||
|
||||
@@ -18,6 +18,10 @@ 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 {
|
||||
page,
|
||||
@@ -26,12 +30,12 @@ export function useListingQuery(
|
||||
sort: sortBy.value,
|
||||
zone: activeZone.value,
|
||||
server: filters.server,
|
||||
region: filters.region,
|
||||
login_method: filters.loginMethod,
|
||||
rank: filters.rank,
|
||||
insurance: filters.insurance,
|
||||
stamina: filters.stamina,
|
||||
load: filters.load,
|
||||
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: filters.skinGroup,
|
||||
skin_name: filters.skinName,
|
||||
min_coin: filters.minCoin,
|
||||
|
||||
Reference in New Issue
Block a user