feat: 初次提交我的项目代码

This commit is contained in:
2026-01-22 17:07:39 +08:00
parent 75fad97d5d
commit 73498128dd
39 changed files with 21439 additions and 835 deletions

View File

@@ -0,0 +1,361 @@
<!-- 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>