| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- <script setup lang="ts">
- import { useI18n } from 'vue-i18n'
- import SortSvg from '~/assets/icons/sort.svg'
- import SortUpSvg from '~/assets/icons/sort-up.svg'
- import SortDownSvg from '~/assets/icons/sort-down.svg'
- defineProps<{
- onFindPartner: () => void
- }>()
- const emit = defineEmits<{
- (e: 'changeSort', payload: { sortByStar: number, sortByPrice: number }): void
- }>()
- type SortOption = {
- labelKey: string
- value: string
- }
- type SortDirection = 'none' | 'asc' | 'desc'
- const { t } = useI18n()
- // star -> sortByStar, price -> sortByPrice
- const sortOptions: SortOption[] = [
- { labelKey: 'home.sort.star', value: 'star' },
- { labelKey: 'home.sort.price', value: 'price' },
- ]
- const activeSort = ref<SortOption['value']>(sortOptions[0]?.value ?? '')
- const sortDirections = ref<Record<string, SortDirection>>({
- star: 'none',
- price: 'none',
- })
- const directionToBackend = (direction: SortDirection): number => {
- // 后端字段:-1 默认,0 升序,1 降序
- if (direction === 'asc')
- return 0
- if (direction === 'desc')
- return 1
- return -1
- }
- const emitSortChange = () => {
- const starDirection = sortDirections.value.star ?? 'none'
- const priceDirection = sortDirections.value.price ?? 'none'
- emit('changeSort', {
- sortByStar: directionToBackend(starDirection),
- sortByPrice: directionToBackend(priceDirection),
- })
- }
- // Handle sort click
- const handleSort = (sortValue: string) => {
- const currentDirection = sortDirections.value[sortValue] ?? 'none'
- let nextDirection: SortDirection
- // Cycle through: none -> desc -> asc -> none -> ...
- if (currentDirection === 'none')
- nextDirection = 'desc'
- else if (currentDirection === 'desc')
- nextDirection = 'asc'
- else
- nextDirection = 'none'
- // 支持多个排序字段同时生效:仅切换当前字段的排序方向,不重置其他字段
- sortDirections.value[sortValue] = nextDirection
- activeSort.value = sortValue
- emitSortChange()
- }
- // Get sort icon component based on direction
- const getSortIcon = (sortValue: string) => {
- const direction = sortDirections.value[sortValue]
- if (direction === 'asc')
- return SortUpSvg
- if (direction === 'desc')
- return SortDownSvg
- return SortSvg
- }
- </script>
- <template>
- <section class="flex flex-wrap items-center justify-between bg-bg-primary z-50">
- <div class="flex gap-4 text-xs font-normal text-text-secondary">
- <button
- v-for="sortOption in sortOptions"
- :key="sortOption.value"
- class="flex items-center gap-1 py-1"
- :class="sortDirections[sortOption.value] !== 'none' ? 'text-text-primary' : ''"
- @click="handleSort(sortOption.value)"
- >
- {{ t(sortOption.labelKey) }}
- <component :is="getSortIcon(sortOption.value)" />
- </button>
- </div>
- <van-button
- round
- size="small"
- class="find-btn flex items-center justify-center"
- plain
- type="primary"
- @click="onFindPartner"
- >
- <span class="text-xs font-title font-semibold text-text-secondary">{{ t('home.findPartner.title') }}</span>
- <van-icon
- class="ml-1 text-text-secondary"
- name="arrow"
- size="14"
- />
- </van-button>
- </section>
- </template>
- <style lang="scss" scoped>
- .find-btn {
- height: 40px;
- padding: 0 12px;
- border-radius: 20px;
- border: 1px solid #FFF;
- background: linear-gradient(90deg, rgba(183, 238, 255, 0.60) 0.01%, rgba(221, 255, 183, 0.60) 26.99%, rgba(255, 255, 255, 0.60) 75.07%);
- }
- </style>
|