361 lines
9.5 KiB
Plaintext
361 lines
9.5 KiB
Plaintext
<!-- pages/mall/consumer/category.uvue -->
|
|
<template>
|
|
<view class="category-page">
|
|
<!-- 顶部搜索栏 -->
|
|
<view class="search-bar">
|
|
<view class="search-box" @click="navigateToSearch">
|
|
<text class="search-icon">🔍</text>
|
|
<text class="search-placeholder">搜索商品</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 分类内容区 -->
|
|
<view class="category-content">
|
|
<!-- 左侧一级分类 -->
|
|
<scroll-view scroll-y class="primary-category">
|
|
<view
|
|
v-for="item in primaryCategories"
|
|
:key="item.id"
|
|
:class="['primary-item', { active: activePrimary === item.id }]"
|
|
@click="selectPrimaryCategory(item.id)"
|
|
>
|
|
<text class="primary-name">{{ item.name }}</text>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<!-- 右侧二级分类和商品 -->
|
|
<scroll-view scroll-y class="secondary-content">
|
|
<!-- 二级分类 -->
|
|
<view v-if="secondaryCategories.length > 0" class="secondary-category">
|
|
<view
|
|
v-for="sub in secondaryCategories"
|
|
:key="sub.id"
|
|
class="secondary-item"
|
|
@click="selectSecondaryCategory(sub.id)"
|
|
>
|
|
<image
|
|
class="sub-category-image"
|
|
:src="sub.image"
|
|
mode="aspectFill"
|
|
/>
|
|
<text class="sub-category-name">{{ sub.name }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 商品列表 -->
|
|
<view v-if="productList.length > 0" class="product-list">
|
|
<view
|
|
v-for="product in productList"
|
|
:key="product.id"
|
|
class="product-item"
|
|
@click="navigateToProduct(product)"
|
|
>
|
|
<view class="product-image-wrapper">
|
|
<image
|
|
class="product-image"
|
|
:src="product.image"
|
|
mode="aspectFill"
|
|
/>
|
|
</view>
|
|
<text class="product-name">{{ product.name }}</text>
|
|
<text class="product-price">¥{{ product.price }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 空状态 -->
|
|
<view v-if="!loading && productList.length === 0 && secondaryCategories.length === 0" class="empty-state">
|
|
<text class="empty-icon">📁</text>
|
|
<text class="empty-text">暂无商品</text>
|
|
<button class="reload-btn" @click="loadData">刷新</button>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="uts">
|
|
import { ref, onMounted } from 'vue'
|
|
|
|
// 响应式数据
|
|
const primaryCategories = ref<any[]>([])
|
|
const secondaryCategories = ref<any[]>([])
|
|
const productList = ref<any[]>([])
|
|
const activePrimary = ref<string>('1')
|
|
const loading = ref<boolean>(false)
|
|
|
|
// Mock 数据
|
|
const mockCategories = {
|
|
primary: [
|
|
{ id: '1', name: '推荐' },
|
|
{ id: '2', name: '女装' },
|
|
{ id: '3', name: '男装' },
|
|
{ id: '4', name: '鞋靴' },
|
|
{ id: '5', name: '箱包' },
|
|
{ id: '6', name: '美妆' },
|
|
{ id: '7', name: '数码' },
|
|
{ id: '8', name: '家电' },
|
|
{ id: '9', name: '家居' },
|
|
{ id: '10', name: '母婴' },
|
|
{ id: '11', name: '食品' },
|
|
{ id: '12', name: '运动' },
|
|
{ id: '13', name: '汽车' },
|
|
{ id: '14', name: '百货' }
|
|
],
|
|
|
|
secondary: {
|
|
'1': [
|
|
{ id: '101', name: '热销推荐', image: 'https://picsum.photos/100/100?random=1' },
|
|
{ id: '102', name: '新品上市', image: 'https://picsum.photos/100/100?random=2' },
|
|
{ id: '103', name: '限时特惠', image: 'https://picsum.photos/100/100?random=3' },
|
|
{ id: '104', name: '精选好物', image: 'https://picsum.photos/100/100?random=4' }
|
|
],
|
|
'2': [
|
|
{ id: '201', name: '连衣裙', image: 'https://picsum.photos/100/100?random=5' },
|
|
{ id: '202', name: 'T恤', image: 'https://picsum.photos/100/100?random=6' },
|
|
{ id: '203', name: '裤子', image: 'https://picsum.photos/100/100?random=7' },
|
|
{ id: '204', name: '外套', image: 'https://picsum.photos/100/100?random=8' },
|
|
{ id: '205', name: '内衣', image: 'https://picsum.photos/100/100?random=9' }
|
|
]
|
|
},
|
|
|
|
products: {
|
|
'101': [
|
|
{ id: '1001', name: '热销商品1', price: 99.9, image: 'https://picsum.photos/150/150?random=10' },
|
|
{ id: '1002', name: '热销商品2', price: 199, image: 'https://picsum.photos/150/150?random=11' },
|
|
{ id: '1003', name: '热销商品3', price: 299, image: 'https://picsum.photos/150/150?random=12' }
|
|
],
|
|
'201': [
|
|
{ id: '2001', name: '连衣裙1', price: 199, image: 'https://picsum.photos/150/150?random=13' },
|
|
{ id: '2002', name: '连衣裙2', price: 299, image: 'https://picsum.photos/150/150?random=14' }
|
|
]
|
|
}
|
|
}
|
|
|
|
// 生命周期
|
|
onMounted(() => {
|
|
loadData()
|
|
})
|
|
|
|
// 加载数据
|
|
const loadData = () => {
|
|
loading.value = true
|
|
|
|
// 使用模拟数据
|
|
setTimeout(() => {
|
|
primaryCategories.value = mockCategories.primary
|
|
secondaryCategories.value = mockCategories.secondary[activePrimary.value] || []
|
|
productList.value = mockCategories.products['101'] || []
|
|
loading.value = false
|
|
}, 500)
|
|
}
|
|
|
|
// 选择一级分类
|
|
const selectPrimaryCategory = (categoryId: string) => {
|
|
activePrimary.value = categoryId
|
|
secondaryCategories.value = mockCategories.secondary[categoryId] || []
|
|
productList.value = mockCategories.products[categoryId + '01'] || []
|
|
}
|
|
|
|
// 选择二级分类
|
|
const selectSecondaryCategory = (subCategoryId: string) => {
|
|
productList.value = mockCategories.products[subCategoryId] || []
|
|
}
|
|
|
|
// 导航函数
|
|
const navigateToSearch = () => {
|
|
uni.navigateTo({ url: '/pages/mall/consumer/search' })
|
|
}
|
|
|
|
const navigateToProduct = (product: any) => {
|
|
uni.navigateTo({ url: `/pages/mall/consumer/product-detail?id=${product.id}` })
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.category-page {
|
|
width: 100%;
|
|
height: 100vh;
|
|
background-color: #f5f5f5;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
/* 搜索栏 */
|
|
.search-bar {
|
|
padding: 10px 15px;
|
|
background-color: white;
|
|
border-bottom: 1px solid #eee;
|
|
}
|
|
|
|
.search-box {
|
|
background-color: #f5f5f5;
|
|
border-radius: 20px;
|
|
padding: 10px 15px;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.search-icon {
|
|
color: #999;
|
|
margin-right: 10px;
|
|
}
|
|
|
|
.search-placeholder {
|
|
color: #999;
|
|
font-size: 14px;
|
|
}
|
|
|
|
/* 分类内容区 */
|
|
.category-content {
|
|
flex: 1;
|
|
display: flex;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* 左侧一级分类 */
|
|
.primary-category {
|
|
width: 100px;
|
|
background-color: white;
|
|
border-right: 1px solid #eee;
|
|
}
|
|
|
|
.primary-item {
|
|
padding: 15px 10px;
|
|
text-align: center;
|
|
border-bottom: 1px solid #f5f5f5;
|
|
}
|
|
|
|
.primary-item.active {
|
|
background-color: #fff0e8;
|
|
color: #ff5000;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.primary-item.active::after {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 3px;
|
|
background-color: #ff5000;
|
|
}
|
|
|
|
.primary-name {
|
|
font-size: 14px;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
/* 右侧内容区 */
|
|
.secondary-content {
|
|
flex: 1;
|
|
padding: 15px;
|
|
background-color: #f5f5f5;
|
|
}
|
|
|
|
/* 二级分类 */
|
|
.secondary-category {
|
|
background-color: white;
|
|
border-radius: 10px;
|
|
padding: 15px;
|
|
margin-bottom: 15px;
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 15px;
|
|
}
|
|
|
|
.secondary-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
|
|
.sub-category-image {
|
|
width: 60px;
|
|
height: 60px;
|
|
border-radius: 30px;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.sub-category-name {
|
|
font-size: 12px;
|
|
color: #333;
|
|
text-align: center;
|
|
}
|
|
|
|
/* 商品列表 */
|
|
.product-list {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 10px;
|
|
}
|
|
|
|
.product-item {
|
|
background-color: white;
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
padding: 10px;
|
|
}
|
|
|
|
.product-image-wrapper {
|
|
width: 100%;
|
|
height: 150px;
|
|
overflow: hidden;
|
|
border-radius: 6px;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.product-image {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.product-name {
|
|
font-size: 13px;
|
|
color: #333;
|
|
line-height: 1.4;
|
|
height: 36px;
|
|
overflow: hidden;
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
-webkit-box-orient: vertical;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.product-price {
|
|
font-size: 16px;
|
|
color: #ff5000;
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* 空状态 */
|
|
.empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 50px 20px;
|
|
text-align: center;
|
|
}
|
|
|
|
.empty-icon {
|
|
font-size: 60px;
|
|
color: #ccc;
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.empty-text {
|
|
font-size: 16px;
|
|
color: #999;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.reload-btn {
|
|
background-color: #ff5000;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 20px;
|
|
padding: 8px 25px;
|
|
font-size: 14px;
|
|
}
|
|
</style> |