feat: 分类开发

This commit is contained in:
zc 2025-09-25 22:38:47 +08:00
parent 6bcdb0cdcc
commit b21f024822
8 changed files with 457 additions and 51 deletions

View File

@ -14,6 +14,7 @@
},
"requiredPrivateInfos": ["getFuzzyLocation"],
"pages": [
"pages/category/index",
"pages/home/index",
"pages/login/index",
"pages/H5/index",
@ -28,7 +29,7 @@
"text": "首页"
},
{
"pagePath": "pages/H5/index",
"pagePath": "pages/category/index",
"text": "分类"
},
{

View File

@ -1,47 +0,0 @@
// components/custom-tabbar/index.js
Component({
properties: {
cartCount: {
type: Number,
value: 0,
},
},
data: {
list: [
{
pagePath: "/pages/home/home",
iconPath: "/images/tab/home.png",
selectedIconPath: "/images/tab/home-active.png",
text: "首页",
},
{
pagePath: "/pages/category/category",
iconPath: "/images/tab/category.png",
selectedIconPath: "/images/tab/category-active.png",
text: "分类",
},
{
pagePath: "/pages/cart/cart",
iconPath: "/images/tab/cart.png",
selectedIconPath: "/images/tab/cart-active.png",
text: "购物车",
},
{
pagePath: "/pages/user/user",
iconPath: "/images/tab/user.png",
selectedIconPath: "/images/tab/user-active.png",
text: "我的",
},
],
active: 0,
},
methods: {
switchTab(e) {
const { path, index } = e.currentTarget.dataset;
this.setData({ active: index });
wx.switchTab({ url: path });
},
},
});

View File

@ -17,7 +17,7 @@ Component<TabBarData, TabBarProperties, TabBarMethods>({
text: "首页",
},
{
pagePath: "/pages/category/category",
pagePath: "/pages/category/index",
// iconPath: "/images/tab/category.png",
// selectedIconPath: "/images/tab/category-active.png",
text: "分类",

View File

@ -0,0 +1,8 @@
{
"usingComponents": {
"van-button": "@vant/weapp/button/index",
"van-icon": "@vant/weapp/icon/index",
"custom-tabbar": "/components/custom-tabbar/index"
},
"navigationStyle": "custom"
}

View File

@ -0,0 +1,175 @@
$theme-color: #02ce26;
// pages/index/index.scss
.category-page {
display: flex;
flex-direction: column;
height: calc(100vh - 100rpx);
overflow: hidden;
// 包名
.category-header {
padding-top: 100rpx;
background: #fbeccb;
.appName {
padding-left: 40rpx;
font-size: 28rpx;
font-weight: 600;
}
// 搜索区域
.category-search {
margin: 16rpx 16rpx 0;
.search-bar {
display: flex;
align-items: center;
background: #fff;
border-radius: 50rpx;
padding: 10rpx 6rpx 10rpx 24rpx;
.search-button {
padding-right: 20rpx;
font-size: 26rpx;
color: $theme-color;
}
input {
flex: 1;
padding-right: 40rpx;
margin-left: 15rpx;
font-size: 28rpx;
}
.placeholder {
color: #ccc;
}
}
}
// 分类导航
.category-scroll {
.category-list {
display: flex;
padding: 16rpx 30rpx;
gap: 40rpx;
.category-item {
display: flex;
flex-direction: column;
align-items: center;
flex-shrink: 0;
.category-icon {
font-size: 48rpx;
margin-bottom: 10rpx;
}
.category-name {
font-size: 24rpx;
color: #333;
}
}
}
}
}
// 主内容区
.main-content {
flex: 1;
height: calc(100vh - 100rpx - 360rpx);
display: flex;
.left-categories {
max-width: 200rpx;
background: #f8f8f8;
.left-category-item {
padding: 30rpx 16rpx;
font-size: 24rpx;
color: #666;
text-align: center;
border-left: 6rpx solid transparent;
&.active {
background: white;
color: $theme-color;
border-left-color: $theme-color;
font-weight: bold;
}
}
}
.right-products {
flex: 1;
background: white;
// 推荐标签
.tag-list {
display: flex;
justify-content: space-around;
align-items: center;
border-bottom: 1rpx solid #f0f0f0;
.tag-item {
padding: 24rpx;
font-size: 24rpx;
color: #666;
&.active {
color: $theme-color;
}
}
}
.products-grid {
.product-card {
padding: 20rpx;
display: flex;
.product-image {
flex-shrink: 0;
flex-grow: 0;
width: 200rpx;
height: 200rpx;
border-radius: 24rpx;
background: #ddd;
}
.product-info {
margin-left: 20rpx;
border-bottom: 2rpx solid #eee;
.product-name {
font-size: 28rpx;
color: #333;
font-weight: bold;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
overflow: hidden;
}
.product-desc {
font-size: 24rpx;
color: #666;
}
.product-tags {
margin-top: 4rpx;
display: flex;
align-items: flex-start;
gap: 10rpx;
.tag {
background: #fff2f0;
color: #ff4d4f;
padding: 4rpx 8rpx;
border-radius: 6rpx;
font-size: 20rpx;
}
}
.price-section {
display: flex;
justify-content: space-between;
align-items: center;
.price-left {
display: flex;
align-items: center;
.current-price {
font-size: 32rpx;
color: #ff3b30;
font-weight: bold;
margin-right: 10rpx;
}
.original-price {
font-size: 24rpx;
color: #999;
text-decoration: line-through;
}
}
.add-cart-btn {
color: $theme-color;
}
}
}
}
}
}
}
}

View File

@ -0,0 +1,184 @@
// pages/index/index.ts
Page({
data: {
appName: "",
statusBarHeight: 0,
navBarHeight: 44,
searchValue: "",
categories: [
{ id: 1, name: "水果鲜花", icon: "🍎" },
{ id: 2, name: "蔬菜豆制品", icon: "🥬" },
{ id: 3, name: "肉禽蛋", icon: "🥩" },
{ id: 4, name: "海鲜水产", icon: "🐟" },
{ id: 5, name: "乳品烘焙", icon: "🥛" },
{ id: 6, name: "熟食快", icon: "🍱" },
],
recommendTags: ["销量", "折扣", "价格"],
activeTag: "荐 时令推荐",
leftCategories: [
{ id: 1, name: "鲜花/绿植", active: true },
{ id: 2, name: "西梅/桃李枣", active: false },
{ id: 3, name: "橘/柚/橙/柑", active: false },
{ id: 4, name: "苹果/新梨/蕉", active: false },
{ id: 5, name: "石榴/龙眼", active: false },
{ id: 6, name: "西瓜/蜜瓜", active: false },
{ id: 7, name: "严选", active: false },
{ id: 8, name: "果切/小番茄", active: false },
{ id: 9, name: "榴莲/热带果", active: false },
{ id: 7, name: "严选", active: false },
{ id: 8, name: "果切/小番茄", active: false },
{ id: 9, name: "榴莲/热带果", active: false },
],
products: [
{
id: 1,
name: "【五彩心语】洋桔梗混色5枝",
desc: "绚烂多姿 | 无刺玫瑰",
tags: ["近90天最低价"],
currentPrice: 7.96,
originalPrice: 19.9,
image: "/images/product1.jpg",
badge: "出清价",
},
{
id: 2,
name: "【节节高升】剑兰粉色 5枝",
desc: "淡粉色颜值高 | 温柔浪漫",
tags: ["近90天最低价"],
currentPrice: 7.96,
originalPrice: 19.9,
image: "/images/product2.jpg",
badge: "出清价",
},
{
id: 3,
name: "时令【小玲珑】雏菊混搭花束",
desc: "文艺装扮 | 玲珑可爱",
tags: ["近30天最低价"],
currentPrice: 3.95,
originalPrice: 7.9,
image: "/images/product3.jpg",
badge: "出清价",
},
{
id: 4,
name: "【清香宜人】茉莉花30枝",
desc: "百个花头 | 芳香怡人",
tags: ["近90天最低价"],
currentPrice: 10.68,
originalPrice: 17.8,
image: "/images/product4.jpg",
badge: "出清价",
},
{
id: 5,
name: "时令【粉韵流光】粉色吸色牡丹菊 3枝",
desc: "8cm大花头 | 菊花吸色工艺",
tags: ["限时特价"],
currentPrice: 15.8,
originalPrice: 25.8,
image: "/images/product5.jpg",
badge: "秒杀",
countdown: "01:18:44",
},
],
},
onLoad() {
const app = getApp();
this.setData({ appName: app.globalData.appName });
this.getSystemInfo();
},
getSystemInfo() {
const systemInfo = wx.getSystemInfoSync();
this.setData({
statusBarHeight: systemInfo.statusBarHeight,
});
},
onSearchInput(e: WechatMiniprogram.InputInput) {
this.setData({
searchValue: e.detail.value,
});
},
onSearch() {
if (this.data.searchValue.trim()) {
wx.showToast({
title: `搜索: ${this.data.searchValue}`,
icon: "none",
});
}
},
onCategoryTap(e: WechatMiniprogram.TouchEvent) {
const { index } = e.currentTarget.dataset;
const categories = this.data.leftCategories.map((item, i) => ({
...item,
active: i === index,
}));
this.setData({ leftCategories: categories });
},
onTagTap(e: WechatMiniprogram.TouchEvent) {
const { tag } = e.currentTarget.dataset;
this.setData({ activeTag: tag });
},
onProductTap(e: WechatMiniprogram.TouchEvent) {
const { id } = e.currentTarget.dataset;
wx.navigateTo({
url: `/pages/product/detail?id=${id}`,
});
},
onAddToCart(e: WechatMiniprogram.TouchEvent) {
const { id } = e.currentTarget.dataset;
wx.showToast({
title: "已加入购物车",
icon: "success",
});
},
});
interface PageData {
statusBarHeight: number;
navBarHeight: number;
searchValue: string;
categories: Category[];
recommendTags: string[];
activeTag: string;
leftCategories: LeftCategory[];
products: Product[];
}
interface Category {
id: number;
name: string;
icon: string;
}
interface LeftCategory {
id: number;
name: string;
active: boolean;
}
interface Product {
id: number;
name: string;
desc: string;
tags: string[];
currentPrice: number;
originalPrice: number;
image: string;
badge: string;
countdown?: string;
}
interface Coupon {
title: string;
status: string;
expireTime: string;
}

View File

@ -0,0 +1,86 @@
<!-- pages/index/index.wxml -->
<view class="category-page">
<!-- 头部 -->
<view class="category-header">
<text class="appName">{{ appName }}</text>
<!-- 搜索框 -->
<view class="category-search">
<view class="search-bar">
<icon type="search" size="14" color="#999" />
<input placeholder="搜索" placeholder-class="placeholder" bindinput="onSearchInput"
bindconfirm="onSearch" />
<text class="search-button">搜索</text>
</view>
</view>
<!-- 分类导航 -->
<scroll-view class="category-scroll" scroll-x>
<view class="category-list">
<view class="category-item" wx:for="{{categories}}" wx:key="id">
<text class="category-icon">{{item.icon}}</text>
<text class="category-name">{{item.name}}</text>
</view>
</view>
</scroll-view>
</view>
<!-- 主内容区 -->
<view class="main-content">
<!-- 左侧分类 -->
<scroll-view class="left-categories" scroll-y>
<view
class="left-category-item {{item.active ? 'active' : ''}}"
wx:for="{{leftCategories}}"
wx:key="id"
bindtap="onCategoryTap"
data-index="{{index}}"
>
<text>{{item.name}}</text>
</view>
</scroll-view>
<!-- 右侧商品列表 -->
<scroll-view class="right-products" scroll-y>
<!-- 推荐标签 -->
<view class="tag-list">
<view
class="tag-item {{activeTag === item ? 'active' : ''}}"
wx:for="{{recommendTags}}"
wx:key="*this"
bindtap="onTagTap"
data-tag="{{item}}"
>
<text>{{item}}</text>
</view>
</view>
<!-- 商品网格 -->
<view class="products-grid">
<view
class="product-card"
wx:for="{{products}}"
wx:key="id"
bindtap="onProductTap"
data-id="{{item.id}}"
>
<image class="product-image" src="{{item.image}}" mode="aspectFill" />
<view class="product-info">
<text class="product-name">{{item.name}}</text>
<text class="product-desc">{{item.desc}}</text>
<view class="product-tags">
<text class="tag" wx:for="{{item.tags}}" wx:key="*this">{{item}}</text>
</view>
<view class="price-section">
<view class="price-left">
<view class="current-price">¥{{item.currentPrice}}</view>
<view class="original-price" wx:if="{{item.originalPrice}}">
¥{{item.originalPrice}}
</view>
</view>
<van-icon class="add-cart-btn" name="add" bindtap="onAddToCart" data-id="{{item.id}}" size="48rpx" />
</view>
</view>
</view>
</view>
</scroll-view>
</view>
<!-- 自定义底部 TabBar -->
<custom-tabbar />
</view>

View File

@ -1,7 +1,5 @@
// pages/index/index.ts
const app = getApp();
Page({
data: {
appName: "",
@ -86,6 +84,7 @@ Page({
},
onLoad() {
const app = getApp();
// 页面加载时逻辑
this.setData({ appName: app.globalData.appName });
},