|
@@ -1,7 +1,8 @@
|
|
|
-import { View, Text, ScrollView } from '@tarojs/components'
|
|
|
|
|
|
|
+import { View, Text, ScrollView, Input } from '@tarojs/components'
|
|
|
import { Button } from '@/components/ui/button'
|
|
import { Button } from '@/components/ui/button'
|
|
|
import { useState, useEffect } from 'react'
|
|
import { useState, useEffect } from 'react'
|
|
|
import { goodsClient } from '@/api'
|
|
import { goodsClient } from '@/api'
|
|
|
|
|
+import Taro from '@tarojs/taro'
|
|
|
import './index.css'
|
|
import './index.css'
|
|
|
|
|
|
|
|
interface SpecOption {
|
|
interface SpecOption {
|
|
@@ -149,12 +150,98 @@ export function GoodsSpecSelector({
|
|
|
validatePriceCalculation()
|
|
validatePriceCalculation()
|
|
|
}, [selectedSpec, quantity])
|
|
}, [selectedSpec, quantity])
|
|
|
|
|
|
|
|
- const handleQuantityChange = (change: number) => {
|
|
|
|
|
|
|
+ // 获取最大可购买数量
|
|
|
|
|
+ const getMaxQuantity = () => {
|
|
|
|
|
+ if (!selectedSpec) return 999
|
|
|
|
|
+ return Math.min(selectedSpec.stock, 999)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理减少数量
|
|
|
|
|
+ const handleDecrease = () => {
|
|
|
if (!selectedSpec) return
|
|
if (!selectedSpec) return
|
|
|
|
|
+ const currentQty = quantity === 0 ? 1 : quantity
|
|
|
|
|
+ const newQuantity = Math.max(1, currentQty - 1)
|
|
|
|
|
+ setQuantity(newQuantity)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理增加数量
|
|
|
|
|
+ const handleIncrease = () => {
|
|
|
|
|
+ if (!selectedSpec) return
|
|
|
|
|
+ const currentQty = quantity === 0 ? 1 : quantity
|
|
|
|
|
+ const maxQuantity = getMaxQuantity()
|
|
|
|
|
+ if (currentQty >= maxQuantity) {
|
|
|
|
|
+ if (maxQuantity === selectedSpec.stock) {
|
|
|
|
|
+ Taro.showToast({
|
|
|
|
|
+ title: `库存只有${selectedSpec.stock}件`,
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 1500
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Taro.showToast({
|
|
|
|
|
+ title: '单次最多购买999件',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 1500
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ setQuantity(currentQty + 1)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理数量输入变化
|
|
|
|
|
+ const handleQuantityChange = (value: string) => {
|
|
|
|
|
+ if (!selectedSpec) return
|
|
|
|
|
+
|
|
|
|
|
+ // 清除非数字字符
|
|
|
|
|
+ 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 === selectedSpec.stock) {
|
|
|
|
|
+ Taro.showToast({
|
|
|
|
|
+ title: `库存只有${selectedSpec.stock}件`,
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 1500
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Taro.showToast({
|
|
|
|
|
+ title: '单次最多购买999件',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 1500
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setQuantity(numValue)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- const newQuantity = quantity + change
|
|
|
|
|
- if (newQuantity >= 1 && newQuantity <= selectedSpec.stock) {
|
|
|
|
|
- setQuantity(newQuantity)
|
|
|
|
|
|
|
+ // 处理输入框失去焦点(完成输入)
|
|
|
|
|
+ const handleQuantityBlur = () => {
|
|
|
|
|
+ // 如果数量小于1(表示空输入或负数),设为1
|
|
|
|
|
+ if (quantity < 1) {
|
|
|
|
|
+ setQuantity(1)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -252,18 +339,25 @@ export function GoodsSpecSelector({
|
|
|
size="sm"
|
|
size="sm"
|
|
|
variant="ghost"
|
|
variant="ghost"
|
|
|
className="quantity-btn"
|
|
className="quantity-btn"
|
|
|
- onClick={() => handleQuantityChange(-1)}
|
|
|
|
|
- disabled={quantity <= 1}
|
|
|
|
|
|
|
+ onClick={handleDecrease}
|
|
|
>
|
|
>
|
|
|
-
|
|
-
|
|
|
</Button>
|
|
</Button>
|
|
|
- <Text className="quantity-value">{quantity}</Text>
|
|
|
|
|
|
|
+ <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
|
|
<Button
|
|
|
size="sm"
|
|
size="sm"
|
|
|
variant="ghost"
|
|
variant="ghost"
|
|
|
className="quantity-btn"
|
|
className="quantity-btn"
|
|
|
- onClick={() => handleQuantityChange(1)}
|
|
|
|
|
- disabled={quantity >= selectedSpec.stock}
|
|
|
|
|
|
|
+ onClick={handleIncrease}
|
|
|
>
|
|
>
|
|
|
+
|
|
+
|
|
|
</Button>
|
|
</Button>
|