|
@@ -1,4 +1,4 @@
|
|
|
-import { View, ScrollView, Text, RichText } from '@tarojs/components'
|
|
|
|
|
|
|
+import { View, ScrollView, Text, RichText, Input } from '@tarojs/components'
|
|
|
import { useQuery } from '@tanstack/react-query'
|
|
import { useQuery } from '@tanstack/react-query'
|
|
|
import { useState, useEffect } from 'react'
|
|
import { useState, useEffect } from 'react'
|
|
|
import Taro, { useRouter, useShareAppMessage } from '@tarojs/taro'
|
|
import Taro, { useRouter, useShareAppMessage } from '@tarojs/taro'
|
|
@@ -140,6 +140,96 @@ export default function GoodsDetailPage() {
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
|
|
+ // 获取最大可购买数量
|
|
|
|
|
+ const getMaxQuantity = () => {
|
|
|
|
|
+ return Math.min(goods?.stock || 999, 999)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理减少数量
|
|
|
|
|
+ const handleDecrease = () => {
|
|
|
|
|
+ const currentQty = quantity === 0 ? 1 : quantity
|
|
|
|
|
+ const newQuantity = Math.max(1, currentQty - 1)
|
|
|
|
|
+ setQuantity(newQuantity)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理增加数量
|
|
|
|
|
+ const handleIncrease = () => {
|
|
|
|
|
+ const currentQty = quantity === 0 ? 1 : quantity
|
|
|
|
|
+ const maxQuantity = getMaxQuantity()
|
|
|
|
|
+ if (currentQty >= maxQuantity) {
|
|
|
|
|
+ if (maxQuantity === goods?.stock) {
|
|
|
|
|
+ Taro.showToast({
|
|
|
|
|
+ title: `库存只有${goods?.stock}件`,
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 1500
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Taro.showToast({
|
|
|
|
|
+ title: '单次最多购买999件',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 1500
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ setQuantity(currentQty + 1)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理数量输入变化
|
|
|
|
|
+ const handleQuantityChange = (value: string) => {
|
|
|
|
|
+ // 清除非数字字符
|
|
|
|
|
+ const cleanedValue = value.replace(/[^\d]/g, '')
|
|
|
|
|
+
|
|
|
|
|
+ // 如果输入为空,设为空字符串(允许用户删除)
|
|
|
|
|
+ if (cleanedValue === '') {
|
|
|
|
|
+ setQuantity(0) // 设为0表示空输入
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const numValue = parseInt(cleanedValue)
|
|
|
|
|
+
|
|
|
|
|
+ // 验证最小值
|
|
|
|
|
+ if (numValue < 1) {
|
|
|
|
|
+ setQuantity(1)
|
|
|
|
|
+ Taro.showToast({
|
|
|
|
|
+ title: '数量不能小于1',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 1500
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 验证最大值
|
|
|
|
|
+ const maxQuantity = getMaxQuantity()
|
|
|
|
|
+ if (numValue > maxQuantity) {
|
|
|
|
|
+ setQuantity(maxQuantity)
|
|
|
|
|
+ if (maxQuantity === goods?.stock) {
|
|
|
|
|
+ Taro.showToast({
|
|
|
|
|
+ title: `库存只有${goods?.stock}件`,
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 1500
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Taro.showToast({
|
|
|
|
|
+ title: '单次最多购买999件',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 1500
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setQuantity(numValue)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理输入框失去焦点(完成输入)
|
|
|
|
|
+ const handleQuantityBlur = () => {
|
|
|
|
|
+ // 如果数量为0(表示空输入),设为1
|
|
|
|
|
+ if (quantity === 0) {
|
|
|
|
|
+ setQuantity(1)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 添加到购物车
|
|
// 添加到购物车
|
|
|
const handleAddToCart = () => {
|
|
const handleAddToCart = () => {
|
|
|
if (!goods) return
|
|
if (!goods) return
|
|
@@ -147,7 +237,9 @@ export default function GoodsDetailPage() {
|
|
|
const currentPrice = goods.price
|
|
const currentPrice = goods.price
|
|
|
const currentStock = goods.stock
|
|
const currentStock = goods.stock
|
|
|
|
|
|
|
|
- if (quantity > currentStock) {
|
|
|
|
|
|
|
+ const finalQuantity = quantity === 0 ? 1 : quantity
|
|
|
|
|
+
|
|
|
|
|
+ if (finalQuantity > currentStock) {
|
|
|
Taro.showToast({
|
|
Taro.showToast({
|
|
|
title: '库存不足',
|
|
title: '库存不足',
|
|
|
icon: 'none'
|
|
icon: 'none'
|
|
@@ -161,7 +253,7 @@ export default function GoodsDetailPage() {
|
|
|
price: currentPrice,
|
|
price: currentPrice,
|
|
|
image: goods.imageFile?.fullUrl || '',
|
|
image: goods.imageFile?.fullUrl || '',
|
|
|
stock: currentStock,
|
|
stock: currentStock,
|
|
|
- quantity,
|
|
|
|
|
|
|
+ quantity: finalQuantity,
|
|
|
spec: ''
|
|
spec: ''
|
|
|
})
|
|
})
|
|
|
|
|
|
|
@@ -177,8 +269,9 @@ export default function GoodsDetailPage() {
|
|
|
|
|
|
|
|
const currentPrice = goods.price
|
|
const currentPrice = goods.price
|
|
|
const currentStock = goods.stock
|
|
const currentStock = goods.stock
|
|
|
|
|
+ const finalQuantity = quantity === 0 ? 1 : quantity
|
|
|
|
|
|
|
|
- if (quantity > currentStock) {
|
|
|
|
|
|
|
+ if (finalQuantity > currentStock) {
|
|
|
Taro.showToast({
|
|
Taro.showToast({
|
|
|
title: '库存不足',
|
|
title: '库存不足',
|
|
|
icon: 'none'
|
|
icon: 'none'
|
|
@@ -188,7 +281,7 @@ export default function GoodsDetailPage() {
|
|
|
|
|
|
|
|
Taro.removeStorageSync('buyNow')
|
|
Taro.removeStorageSync('buyNow')
|
|
|
Taro.removeStorageSync('checkoutItems')
|
|
Taro.removeStorageSync('checkoutItems')
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 将商品信息存入临时存储,跳转到订单确认页
|
|
// 将商品信息存入临时存储,跳转到订单确认页
|
|
|
Taro.setStorageSync('buyNow', {
|
|
Taro.setStorageSync('buyNow', {
|
|
|
goods: {
|
|
goods: {
|
|
@@ -196,10 +289,10 @@ export default function GoodsDetailPage() {
|
|
|
name: goods.name,
|
|
name: goods.name,
|
|
|
price: currentPrice,
|
|
price: currentPrice,
|
|
|
image: goods.imageFile?.fullUrl || '',
|
|
image: goods.imageFile?.fullUrl || '',
|
|
|
- quantity,
|
|
|
|
|
|
|
+ quantity: finalQuantity,
|
|
|
spec: ''
|
|
spec: ''
|
|
|
},
|
|
},
|
|
|
- totalAmount: currentPrice * quantity
|
|
|
|
|
|
|
+ totalAmount: currentPrice * finalQuantity
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
// const buyNowData = Taro.getStorageSync('buyNow')
|
|
// const buyNowData = Taro.getStorageSync('buyNow')
|
|
@@ -309,32 +402,39 @@ export default function GoodsDetailPage() {
|
|
|
|
|
|
|
|
{/* 底部操作栏 */}
|
|
{/* 底部操作栏 */}
|
|
|
<View className="bottom-action-bar">
|
|
<View className="bottom-action-bar">
|
|
|
- <View className="action-left">
|
|
|
|
|
- <View className="quantity-selector">
|
|
|
|
|
- <Text className="quantity-label">数量:</Text>
|
|
|
|
|
- <View className="quantity-controls">
|
|
|
|
|
- <Button
|
|
|
|
|
- size="sm"
|
|
|
|
|
- variant="ghost"
|
|
|
|
|
- className="quantity-btn"
|
|
|
|
|
- onClick={() => setQuantity(Math.max(1, quantity - 1))}
|
|
|
|
|
- >
|
|
|
|
|
- -
|
|
|
|
|
- </Button>
|
|
|
|
|
- <Text className="quantity-value">{quantity}</Text>
|
|
|
|
|
- <Button
|
|
|
|
|
- size="sm"
|
|
|
|
|
- variant="ghost"
|
|
|
|
|
- className="quantity-btn"
|
|
|
|
|
- onClick={() => setQuantity(Math.min(goods.stock, quantity + 1))}
|
|
|
|
|
- >
|
|
|
|
|
- +
|
|
|
|
|
- </Button>
|
|
|
|
|
- </View>
|
|
|
|
|
|
|
+ <View className="quantity-section">
|
|
|
|
|
+ <Text className="quantity-label">数量</Text>
|
|
|
|
|
+ <View className="quantity-controls">
|
|
|
|
|
+ <Button
|
|
|
|
|
+ size="sm"
|
|
|
|
|
+ variant="ghost"
|
|
|
|
|
+ className="quantity-btn"
|
|
|
|
|
+ onClick={handleDecrease}
|
|
|
|
|
+ >
|
|
|
|
|
+ -
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Input
|
|
|
|
|
+ className="quantity-input"
|
|
|
|
|
+ type="number"
|
|
|
|
|
+ value={quantity === 0 ? '' : quantity.toString()}
|
|
|
|
|
+ onInput={(e) => handleQuantityChange(e.detail.value)}
|
|
|
|
|
+ onBlur={handleQuantityBlur}
|
|
|
|
|
+ placeholder="1"
|
|
|
|
|
+ maxlength={3}
|
|
|
|
|
+ confirmType="done"
|
|
|
|
|
+ />
|
|
|
|
|
+ <Button
|
|
|
|
|
+ size="sm"
|
|
|
|
|
+ variant="ghost"
|
|
|
|
|
+ className="quantity-btn"
|
|
|
|
|
+ onClick={handleIncrease}
|
|
|
|
|
+ >
|
|
|
|
|
+ +
|
|
|
|
|
+ </Button>
|
|
|
</View>
|
|
</View>
|
|
|
</View>
|
|
</View>
|
|
|
|
|
|
|
|
- <View className="action-right">
|
|
|
|
|
|
|
+ <View className="button-section">
|
|
|
<Button
|
|
<Button
|
|
|
className="add-cart-btn"
|
|
className="add-cart-btn"
|
|
|
onClick={handleAddToCart}
|
|
onClick={handleAddToCart}
|