This commit is contained in:
liu
2026-08-21 12:41:15 +08:00
parent 8a7bdca6b1
commit 4bbe92d8e8
6 changed files with 50 additions and 13 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
"miniprogramRoot": "./", "miniprogramRoot": "./",
"projectname": "pure-project-vantui", "projectname": "pure-project-vantui",
"description": "", "description": "",
"appid": "wx7ed74d60503b5ee3", "appid": "wx8f48874e3bf1dccd",
"setting": { "setting": {
"urlCheck": false, "urlCheck": false,
"es6": true, "es6": true,
+9
View File
@@ -24,6 +24,15 @@
.cart-empty { .cart-empty {
padding-top: 160rpx; padding-top: 160rpx;
&__btn {
margin-top: 24rpx;
padding: 14rpx 60rpx;
background: #ee0a24;
color: #fff;
font-size: 28rpx;
border-radius: 999rpx;
}
} }
.cart-loading { .cart-loading {
+18 -4
View File
@@ -2,6 +2,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'
import Taro, { useDidShow } from '@tarojs/taro' import Taro, { useDidShow } from '@tarojs/taro'
import { View, Text, Image, Textarea, ScrollView } from '@tarojs/components' import { View, Text, Image, Textarea, ScrollView } from '@tarojs/components'
import { Button, Empty, Icon, Popup, Stepper } from '@antmjs/vantui' import { Button, Empty, Icon, Popup, Stepper } from '@antmjs/vantui'
import useAuthStore from '@/stores/auth/useAuthStore'
import useCartStore from '@/stores/cart/useCartStore' import useCartStore from '@/stores/cart/useCartStore'
import { createOrderApi } from '@/services/order' import { createOrderApi } from '@/services/order'
import { getStoreInfoApi } from '@/services/store' import { getStoreInfoApi } from '@/services/store'
@@ -12,6 +13,7 @@ import type { StoreDetail } from '@/types/store'
import './index.less' import './index.less'
export default function CartPage() { export default function CartPage() {
const token = useAuthStore(s => s.token)
const items = useCartStore(s => s.items) const items = useCartStore(s => s.items)
const totalQuantity = useCartStore(s => s.totalQuantity) const totalQuantity = useCartStore(s => s.totalQuantity)
const totalAmount = useCartStore(s => s.totalAmount) const totalAmount = useCartStore(s => s.totalAmount)
@@ -39,6 +41,12 @@ export default function CartPage() {
const purchasable = items.filter(item => item.status === 1) const purchasable = items.filter(item => item.status === 1)
const hasInvalid = items.length > 0 && purchasable.length < items.length const hasInvalid = items.length > 0 && purchasable.length < items.length
const loggedIn = !!token
const goLogin = useCallback(() => {
Taro.navigateTo({ url: '/pages/login/index' })
}, [])
/** 拉取门店配送信息 */ /** 拉取门店配送信息 */
const fetchStoreInfo = useCallback(() => { const fetchStoreInfo = useCallback(() => {
setStoreLoading(true) setStoreLoading(true)
@@ -49,6 +57,8 @@ export default function CartPage() {
}, []) }, [])
useDidShow(() => { useDidShow(() => {
// 未登录不请求接口,直接展示去登录空态(参考消息页)
if (!loggedIn) return
fetchCart().catch(() => {}) fetchCart().catch(() => {})
// 从门店信息编辑页返回且弹层仍打开时 → 刷新配送信息 // 从门店信息编辑页返回且弹层仍打开时 → 刷新配送信息
if (showOrder) fetchStoreInfo() if (showOrder) fetchStoreInfo()
@@ -177,13 +187,17 @@ export default function CartPage() {
{/* ========== 头部 ========== */} {/* ========== 头部 ========== */}
<View className='cart-header'> <View className='cart-header'>
<Text className='cart-header__title'></Text> <Text className='cart-header__title'></Text>
{items.length > 0 && ( {loggedIn && items.length > 0 && (
<Text className='cart-header__clear' onClick={handleClear}></Text> <Text className='cart-header__clear' onClick={handleClear}></Text>
)} )}
</View> </View>
{/* ========== 列表 ========== */} {/* ========== 列表 ========== */}
{items.length === 0 ? ( {!loggedIn ? (
<Empty description='登录后查看购物车' className='cart-empty'>
<View className='cart-empty__btn' onClick={goLogin}></View>
</Empty>
) : items.length === 0 ? (
loading ? ( loading ? (
<View className='cart-loading'><Text>...</Text></View> <View className='cart-loading'><Text>...</Text></View>
) : ( ) : (
@@ -238,14 +252,14 @@ export default function CartPage() {
)) ))
)} )}
{hasInvalid && ( {loggedIn && hasInvalid && (
<View className='cart-invalid-hint'> <View className='cart-invalid-hint'>
<Text></Text> <Text></Text>
</View> </View>
)} )}
{/* ========== 底部结算栏 ========== */} {/* ========== 底部结算栏 ========== */}
{items.length > 0 && ( {loggedIn && items.length > 0 && (
<View className='cart-footer'> <View className='cart-footer'>
<View className='cart-footer__total'> <View className='cart-footer__total'>
<Text className='cart-footer__label'>{totalQuantity}</Text> <Text className='cart-footer__label'>{totalQuantity}</Text>
+6 -1
View File
@@ -102,6 +102,11 @@ export default function IndexPage() {
Taro.switchTab({ url: '/pages/product/index' }) Taro.switchTab({ url: '/pages/product/index' })
}, []) }, [])
/** 跳转商品详情 */
const goDetail = useCallback((id: number) => {
Taro.navigateTo({ url: `/pages/product-detail/index?id=${id}` })
}, [])
/** 搜索框聚焦/提交 → 商品页搜索 */ /** 搜索框聚焦/提交 → 商品页搜索 */
const handleSearchFocus = useCallback(() => { const handleSearchFocus = useCallback(() => {
goProduct(keyword.trim()) goProduct(keyword.trim())
@@ -240,7 +245,7 @@ export default function IndexPage() {
) : ( ) : (
<View className='product-grid'> <View className='product-grid'>
{products.map(product => ( {products.map(product => (
<View key={product.id} className='product-card' onClick={() => goProduct()}> <View key={product.id} className='product-card' onClick={() => goDetail(product.id)}>
<Image <Image
className='product-card__image' className='product-card__image'
src={getProductCover(product) || 'https://img.yzcdn.cn/vant/cat.jpeg'} src={getProductCover(product) || 'https://img.yzcdn.cn/vant/cat.jpeg'}
+4 -1
View File
@@ -3,6 +3,9 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background: #f7f8fa; background: #f7f8fa;
// 底部预留给自定义 tabBar(110rpx + 安全区),避免列表被遮挡
padding-bottom: calc(110rpx + env(safe-area-inset-bottom));
box-sizing: border-box;
.product-search { .product-search {
flex-shrink: 0; flex-shrink: 0;
@@ -92,8 +95,8 @@
.product-main { .product-main {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
height: 100%;
padding: 20rpx 20rpx 40rpx; padding: 20rpx 20rpx 40rpx;
overflow-y: auto;
box-sizing: border-box; box-sizing: border-box;
} }
+12 -6
View File
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import Taro, { useDidShow, useReachBottom } from '@tarojs/taro' import Taro, { useDidShow } from '@tarojs/taro'
import { View, Text, Image, ScrollView } from '@tarojs/components' import { View, Text, Image, ScrollView } from '@tarojs/components'
import { Button, Empty, Popup, Search, Stepper } from '@antmjs/vantui' import { Button, Empty, Popup, Search, Stepper } from '@antmjs/vantui'
import useCartStore from '@/stores/cart/useCartStore' import useCartStore from '@/stores/cart/useCartStore'
@@ -149,11 +149,12 @@ export default function ProductPage() {
fetchList(1, true, pendingKeyword ?? undefined) fetchList(1, true, pendingKeyword ?? undefined)
}) })
useReachBottom(() => { /** 右侧列表触底加载(页面为固定布局不滚动,由 ScrollView 触发) */
const handleLoadMore = useCallback(() => {
if (!finished) { if (!finished) {
fetchList(page + 1, false) fetchList(page + 1, false)
} }
}) }, [finished, page, fetchList])
/** 点击一级分类:有子分类仅展开/收起(不可选中),无子分类则选中 */ /** 点击一级分类:有子分类仅展开/收起(不可选中),无子分类则选中 */
const handleTopTap = useCallback((cat: Category) => { const handleTopTap = useCallback((cat: Category) => {
@@ -274,8 +275,13 @@ export default function ProductPage() {
})} })}
</ScrollView> </ScrollView>
{/* ========== 右侧商品列表 ========== */} {/* ========== 右侧商品列表ScrollView 滚动 + 触底加载) ========== */}
<View className='product-main'> <ScrollView
scrollY
className='product-main'
lowerThreshold={80}
onScrollToLower={handleLoadMore}
>
{/* 商品列表 */} {/* 商品列表 */}
{products.length === 0 && !loading ? ( {products.length === 0 && !loading ? (
<Empty description='暂无商品' className='product-empty' /> <Empty description='暂无商品' className='product-empty' />
@@ -317,7 +323,7 @@ export default function ProductPage() {
{finished && products.length > 0 && ( {finished && products.length > 0 && (
<View className='product-loading'><Text></Text></View> <View className='product-loading'><Text></Text></View>
)} )}
</View> </ScrollView>
</View> </View>
{/* ========== 加购弹层 ========== */} {/* ========== 加购弹层 ========== */}