GameServicePlatform/pages/category/list.vue

191 lines
4.1 KiB
Vue

<template>
<view class="category-list-page page-container">
<!-- 筛选栏 -->
<view class="filter-bar">
<scroll-view class="filter-scroll" scroll-x show-scrollbar="false">
<view class="filter-tags">
<view
v-for="(item, index) in filters"
:key="index"
class="filter-tag"
:class="{ active: currentFilter === index }"
@click="changeFilter(index)"
>
{{ item }}
</view>
</view>
</scroll-view>
<view class="sort-btn" @click="toggleSort">
<text class="sort-icon">⚡</text>
<text class="sort-text">{{ sortText }}</text>
</view>
</view>
<!-- 服务列表 -->
<view class="services-list">
<service-card
v-for="service in filteredServices"
:key="service.id"
:service="service"
@click="goServiceDetail"
/>
</view>
<!-- 空状态 -->
<view v-if="filteredServices.length === 0" class="empty-state">
<text class="empty-icon">📦</text>
<text class="empty-text">暂无服务</text>
</view>
</view>
</template>
<script setup>
import { ref, computed, onLoad } from '@dcloudio/uni-app'
import { services, getServicesByCategory } from '../../mock'
const categoryId = ref(0)
const categoryName = ref('')
const currentFilter = ref(0)
const currentSort = ref(0)
const filters = ['全部', '代练', '陪玩', '教学']
const sortOptions = ['默认', '价格', '销量', '评分']
const sortText = computed(() => sortOptions[currentSort.value])
const allServices = ref([])
const filteredServices = computed(() => {
let result = allServices.value
// 筛选
if (currentFilter.value > 0) {
const filterMap = { 1: '代练', 2: '陪玩', 3: '教学' }
const keyword = filterMap[currentFilter.value]
result = result.filter(s => s.name.includes(keyword))
}
// 排序
if (currentSort.value === 1) {
result = [...result].sort((a, b) => a.price - b.price)
} else if (currentSort.value === 2) {
result = [...result].sort((a, b) => b.salesCount - a.salesCount)
} else if (currentSort.value === 3) {
result = [...result].sort((a, b) => b.rating - a.rating)
}
return result
})
onLoad((options) => {
if (options.categoryId) {
categoryId.value = parseInt(options.categoryId)
categoryName.value = options.categoryName || ''
allServices.value = getServicesByCategory(categoryId.value)
} else {
allServices.value = services
}
uni.setNavigationBarTitle({
title: categoryName.value || '服务列表'
})
})
const changeFilter = (index) => {
currentFilter.value = index
}
const toggleSort = () => {
currentSort.value = (currentSort.value + 1) % sortOptions.length
}
const goServiceDetail = (service) => {
uni.navigateTo({
url: `/pages/service/detail?id=${service.id}`
})
}
</script>
<style lang="scss" scoped>
.category-list-page {
padding: 24rpx;
}
.filter-bar {
display: flex;
gap: 20rpx;
margin-bottom: 28rpx;
}
.filter-scroll {
flex: 1;
white-space: nowrap;
}
.filter-tags {
display: inline-flex;
gap: 16rpx;
}
.filter-tag {
display: inline-block;
padding: 12rpx 32rpx;
background: rgba(20, 25, 50, 0.9);
border: 1px solid rgba(0, 255, 255, 0.2);
border-radius: 50rpx;
font-size: 26rpx;
color: #a0a4c4;
transition: all 0.3s ease;
&.active {
background: linear-gradient(135deg, #00ffff 0%, #0099ff 100%);
color: #0a0e27;
border-color: transparent;
font-weight: bold;
}
}
.sort-btn {
display: flex;
align-items: center;
gap: 8rpx;
padding: 12rpx 24rpx;
background: rgba(20, 25, 50, 0.9);
border: 1px solid rgba(0, 255, 255, 0.2);
border-radius: 50rpx;
font-size: 26rpx;
color: #00ffff;
&:active {
transform: scale(0.95);
}
}
.sort-icon {
font-size: 28rpx;
}
.services-list {
display: flex;
flex-direction: column;
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
}
.empty-icon {
font-size: 120rpx;
margin-bottom: 24rpx;
opacity: 0.5;
}
.empty-text {
font-size: 28rpx;
color: #7a7e9d;
}
</style>