JewelryMall/miniprogram/pages/index/index.vue
2026-02-21 14:20:00 +08:00

132 lines
2.9 KiB
Vue

<template>
<view class="home-page">
<!-- 分类筛选 -->
<scroll-view class="category-bar" scroll-x>
<view
v-for="cat in categories"
:key="cat.id"
class="category-item"
:class="{ 'category-item--active': activeCategoryId === cat.id }"
@click="selectCategory(cat.id)"
>
{{ cat.name }}
</view>
</scroll-view>
<!-- 商品列表 -->
<view class="product-grid">
<view v-for="product in products" :key="product.id" class="product-grid__item">
<ProductCard :product="product" />
</view>
</view>
<!-- 空状态 -->
<view v-if="!loading && products.length === 0" class="empty-tip">
<text>暂无商品</text>
</view>
<!-- 加载更多 -->
<view v-if="loading" class="loading-tip">
<text>加载中...</text>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import type { Product, Category } from '../../types'
import { getProducts, getCategories } from '../../api/product'
import ProductCard from '../../components/ProductCard.vue'
const products = ref<Product[]>([])
const categories = ref<Category[]>([])
const activeCategoryId = ref<number | undefined>(undefined)
const loading = ref(false)
const page = ref(1)
const pageSize = 20
async function loadCategories() {
try {
const data = await getCategories()
categories.value = [{ id: 0, name: '全部', sort: 0 } as Category, ...data]
} catch {
// 错误已在 request 中统一处理
}
}
async function loadProducts(reset = false) {
if (reset) {
page.value = 1
products.value = []
}
loading.value = true
try {
const params: Record<string, unknown> = { page: page.value, pageSize }
if (activeCategoryId.value && activeCategoryId.value !== 0) {
params.categoryId = activeCategoryId.value
}
const data = await getProducts(params as { categoryId?: number; page?: number; pageSize?: number })
if (reset) {
products.value = data.list
} else {
products.value.push(...data.list)
}
} catch {
// 错误已在 request 中统一处理
} finally {
loading.value = false
}
}
function selectCategory(id: number) {
activeCategoryId.value = id
loadProducts(true)
}
onMounted(() => {
loadCategories()
loadProducts(true)
})
</script>
<style scoped>
.home-page {
min-height: 100vh;
background: #f5f5f5;
}
.category-bar {
white-space: nowrap;
background: #fff;
padding: 20rpx 16rpx;
}
.category-item {
display: inline-block;
padding: 12rpx 28rpx;
margin-right: 16rpx;
font-size: 26rpx;
color: #666;
background: #f5f5f5;
border-radius: 28rpx;
}
.category-item--active {
color: #fff;
background: #e4393c;
}
.product-grid {
display: flex;
flex-wrap: wrap;
padding: 16rpx;
gap: 16rpx;
}
.product-grid__item {
width: calc(50% - 8rpx);
}
.empty-tip,
.loading-tip {
text-align: center;
padding: 60rpx 0;
color: #999;
font-size: 28rpx;
}
</style>