9 changed files with 478 additions and 50 deletions
@ -0,0 +1,60 @@ |
|||
import React from 'react'; |
|||
import { Badge } from "@nutui/nutui-react-taro"; |
|||
import { Cart } from "@nutui/icons-react-taro"; |
|||
import Taro from '@tarojs/taro'; |
|||
import { useCart } from "@/hooks/useCart"; |
|||
|
|||
interface CartIconProps { |
|||
style?: React.CSSProperties; |
|||
className?: string; |
|||
size?: number; |
|||
showBadge?: boolean; |
|||
onClick?: () => void; |
|||
} |
|||
|
|||
const CartIcon: React.FC<CartIconProps> = ({ |
|||
style, |
|||
className = '', |
|||
size = 16, |
|||
showBadge = true, |
|||
onClick |
|||
}) => { |
|||
const { cartCount } = useCart(); |
|||
|
|||
const handleClick = () => { |
|||
if (onClick) { |
|||
onClick(); |
|||
} else { |
|||
// 默认跳转到购物车页面
|
|||
Taro.switchTab({ url: '/pages/cart/cart' }); |
|||
} |
|||
}; |
|||
|
|||
if (showBadge) { |
|||
return ( |
|||
<div |
|||
className={className} |
|||
style={style} |
|||
onClick={handleClick} |
|||
> |
|||
<Badge value={cartCount} top="-2" right="2"> |
|||
<div style={{ display: 'flex', alignItems: 'center' }}> |
|||
<Cart size={size} /> |
|||
</div> |
|||
</Badge> |
|||
</div> |
|||
); |
|||
} |
|||
|
|||
return ( |
|||
<div |
|||
className={className} |
|||
style={style} |
|||
onClick={handleClick} |
|||
> |
|||
<Cart size={size} /> |
|||
</div> |
|||
); |
|||
}; |
|||
|
|||
export default CartIcon; |
@ -0,0 +1,151 @@ |
|||
import { useState, useEffect } from 'react'; |
|||
import Taro from '@tarojs/taro'; |
|||
|
|||
// 购物车商品接口
|
|||
export interface CartItem { |
|||
goodsId: number; |
|||
name: string; |
|||
price: string; |
|||
image: string; |
|||
quantity: number; |
|||
addTime: number; |
|||
} |
|||
|
|||
// 购物车Hook
|
|||
export const useCart = () => { |
|||
const [cartItems, setCartItems] = useState<CartItem[]>([]); |
|||
const [cartCount, setCartCount] = useState(0); |
|||
|
|||
// 从本地存储加载购物车数据
|
|||
const loadCartFromStorage = () => { |
|||
try { |
|||
const cartData = Taro.getStorageSync('cart_items'); |
|||
if (cartData) { |
|||
const items = JSON.parse(cartData) as CartItem[]; |
|||
setCartItems(items); |
|||
updateCartCount(items); |
|||
} |
|||
} catch (error) { |
|||
console.error('加载购物车数据失败:', error); |
|||
} |
|||
}; |
|||
|
|||
// 保存购物车数据到本地存储
|
|||
const saveCartToStorage = (items: CartItem[]) => { |
|||
try { |
|||
Taro.setStorageSync('cart_items', JSON.stringify(items)); |
|||
} catch (error) { |
|||
console.error('保存购物车数据失败:', error); |
|||
} |
|||
}; |
|||
|
|||
// 更新购物车数量
|
|||
const updateCartCount = (items: CartItem[]) => { |
|||
const count = items.reduce((total, item) => total + item.quantity, 0); |
|||
setCartCount(count); |
|||
}; |
|||
|
|||
// 添加商品到购物车
|
|||
const addToCart = (goods: { |
|||
goodsId: number; |
|||
name: string; |
|||
price: string; |
|||
image: string; |
|||
}, quantity: number = 1) => { |
|||
const newItems = [...cartItems]; |
|||
const existingItemIndex = newItems.findIndex(item => item.goodsId === goods.goodsId); |
|||
|
|||
if (existingItemIndex >= 0) { |
|||
// 如果商品已存在,增加数量
|
|||
newItems[existingItemIndex].quantity += quantity; |
|||
} else { |
|||
// 如果商品不存在,添加新商品
|
|||
const newItem: CartItem = { |
|||
goodsId: goods.goodsId, |
|||
name: goods.name, |
|||
price: goods.price, |
|||
image: goods.image, |
|||
quantity, |
|||
addTime: Date.now() |
|||
}; |
|||
newItems.push(newItem); |
|||
} |
|||
|
|||
setCartItems(newItems); |
|||
updateCartCount(newItems); |
|||
saveCartToStorage(newItems); |
|||
|
|||
// 显示成功提示
|
|||
Taro.showToast({ |
|||
title: '加入购物车成功', |
|||
icon: 'success', |
|||
duration: 1500 |
|||
}); |
|||
}; |
|||
|
|||
// 从购物车移除商品
|
|||
const removeFromCart = (goodsId: number) => { |
|||
const newItems = cartItems.filter(item => item.goodsId !== goodsId); |
|||
setCartItems(newItems); |
|||
updateCartCount(newItems); |
|||
saveCartToStorage(newItems); |
|||
}; |
|||
|
|||
// 更新商品数量
|
|||
const updateQuantity = (goodsId: number, quantity: number) => { |
|||
if (quantity <= 0) { |
|||
removeFromCart(goodsId); |
|||
return; |
|||
} |
|||
|
|||
const newItems = cartItems.map(item => |
|||
item.goodsId === goodsId ? { ...item, quantity } : item |
|||
); |
|||
setCartItems(newItems); |
|||
updateCartCount(newItems); |
|||
saveCartToStorage(newItems); |
|||
}; |
|||
|
|||
// 清空购物车
|
|||
const clearCart = () => { |
|||
setCartItems([]); |
|||
setCartCount(0); |
|||
Taro.removeStorageSync('cart_items'); |
|||
}; |
|||
|
|||
// 获取购物车总价
|
|||
const getTotalPrice = () => { |
|||
return cartItems.reduce((total, item) => { |
|||
return total + (parseFloat(item.price) * item.quantity); |
|||
}, 0).toFixed(2); |
|||
}; |
|||
|
|||
// 检查商品是否在购物车中
|
|||
const isInCart = (goodsId: number) => { |
|||
return cartItems.some(item => item.goodsId === goodsId); |
|||
}; |
|||
|
|||
// 获取商品在购物车中的数量
|
|||
const getItemQuantity = (goodsId: number) => { |
|||
const item = cartItems.find(item => item.goodsId === goodsId); |
|||
return item ? item.quantity : 0; |
|||
}; |
|||
|
|||
// 初始化时加载购物车数据
|
|||
useEffect(() => { |
|||
loadCartFromStorage(); |
|||
}, []); |
|||
|
|||
return { |
|||
cartItems, |
|||
cartCount, |
|||
addToCart, |
|||
removeFromCart, |
|||
updateQuantity, |
|||
clearCart, |
|||
getTotalPrice, |
|||
isInCart, |
|||
getItemQuantity, |
|||
loadCartFromStorage |
|||
}; |
|||
}; |
@ -1,5 +1,4 @@ |
|||
export default definePageConfig({ |
|||
navigationBarTitleText: '购物车', |
|||
navigationBarTextStyle: 'black', |
|||
navigationStyle: 'custom' |
|||
}) |
|||
|
Loading…
Reference in new issue