forked from gxwebsoft/mp-10550
feat(shop): 添加水票套票活动功能支持
- 移除未使用的 Shop 图标导入和 navTo 工具函数 - 新增水票套票模板查询接口和类型定义 - 实现套票活动状态判断逻辑和最小购买量校验 - 添加购买数量变更时的赠送水票计算功能 - 在商品详情区域显示最低购买量和赠送水票信息 - 为套票活动商品添加注意事项展示 - 禁用不符合最低购买量要求的支付按钮 - 注释掉门店选择相关UI组件以优化界面
This commit is contained in:
@@ -11,7 +11,7 @@ import {
|
||||
InputNumber,
|
||||
ConfigProvider
|
||||
} from '@nutui/nutui-react-taro'
|
||||
import {Location, ArrowRight, Shop} from '@nutui/icons-react-taro'
|
||||
import {Location, ArrowRight} from '@nutui/icons-react-taro'
|
||||
import Taro, {useDidShow} from '@tarojs/taro'
|
||||
import {ShopGoods} from "@/api/shop/shopGoods/model";
|
||||
import {getShopGoods} from "@/api/shop/shopGoods";
|
||||
@@ -27,6 +27,8 @@ import OrderConfirmSkeleton from "@/components/OrderConfirmSkeleton";
|
||||
import CouponList from "@/components/CouponList";
|
||||
import {CouponCardProps} from "@/components/CouponCard";
|
||||
import {getMyAvailableCoupons} from "@/api/shop/shopUserCoupon";
|
||||
import {getGltTicketTemplateByGoodsId} from "@/api/glt/gltTicketTemplate";
|
||||
import type {GltTicketTemplate} from "@/api/glt/gltTicketTemplate/model";
|
||||
import {
|
||||
transformCouponData,
|
||||
calculateCouponDiscount,
|
||||
@@ -36,7 +38,6 @@ import {
|
||||
filterUsableCoupons,
|
||||
filterUnusableCoupons
|
||||
} from "@/utils/couponUtils";
|
||||
import navTo from "@/utils/common";
|
||||
import type {ShopStore} from "@/api/shop/shopStore/model";
|
||||
import {getShopStore, listShopStore} from "@/api/shop/shopStore";
|
||||
import {getSelectedStoreFromStorage, saveSelectedStoreToStorage} from "@/utils/storeSelection";
|
||||
@@ -54,6 +55,9 @@ const OrderConfirm = () => {
|
||||
const [error, setError] = useState<string>('')
|
||||
const [payLoading, setPayLoading] = useState<boolean>(false)
|
||||
|
||||
// 水票套票活动(若存在则按规则限制最小购买量等)
|
||||
const [ticketTemplate, setTicketTemplate] = useState<GltTicketTemplate | null>(null)
|
||||
|
||||
// InputNumber 主题配置
|
||||
const customTheme = {
|
||||
nutuiInputnumberButtonWidth: '28px',
|
||||
@@ -79,6 +83,23 @@ const OrderConfirm = () => {
|
||||
const router = Taro.getCurrentInstance().router;
|
||||
const goodsId = router?.params?.goodsId;
|
||||
|
||||
const isTicketTemplateActive =
|
||||
!!ticketTemplate &&
|
||||
ticketTemplate.enabled !== false &&
|
||||
ticketTemplate.status !== 1 &&
|
||||
ticketTemplate.deleted !== 1
|
||||
|
||||
// 需求:套票活动最低购买量固定为 20 桶
|
||||
const minBuyQty = isTicketTemplateActive ? 20 : 1
|
||||
|
||||
const getGiftTicketQty = (buyQty: number) => {
|
||||
if (!isTicketTemplateActive) return 0
|
||||
const multiplier = Number(ticketTemplate?.giftMultiplier || 0)
|
||||
const startSend = Number(ticketTemplate?.startSendQty || 0)
|
||||
if (multiplier > 0) return Math.max(0, buyQty) * multiplier
|
||||
return Math.max(0, startSend)
|
||||
}
|
||||
|
||||
const loadStores = async () => {
|
||||
if (storeLoading) return
|
||||
try {
|
||||
@@ -94,6 +115,7 @@ const OrderConfirm = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const openStorePopup = async () => {
|
||||
setStorePopupVisible(true)
|
||||
if (!stores.length) {
|
||||
@@ -393,6 +415,15 @@ const OrderConfirm = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 水票套票活动:最小购买量校验
|
||||
if (isTicketTemplateActive && quantity < minBuyQty) {
|
||||
Taro.showToast({
|
||||
title: `最低购买量:${minBuyQty}桶`,
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 库存校验
|
||||
if (goods.stock !== undefined && quantity > goods.stock) {
|
||||
Taro.showToast({
|
||||
@@ -513,7 +544,7 @@ const OrderConfirm = () => {
|
||||
// icon: 'success'
|
||||
// })
|
||||
} catch (error: any) {
|
||||
return navTo('/user/order/order?statusFilter=0', true)
|
||||
// return navTo('/user/order/order?statusFilter=0', true)
|
||||
// console.error('支付失败:', error)
|
||||
|
||||
// 只处理PaymentHandler未处理的错误
|
||||
@@ -565,6 +596,18 @@ const OrderConfirm = () => {
|
||||
setGoods(goodsRes)
|
||||
}
|
||||
|
||||
// 查询当前商品是否存在水票套票活动(失败/无数据时不影响正常下单)
|
||||
if (goodsId) {
|
||||
try {
|
||||
const tpl = await getGltTicketTemplateByGoodsId(Number(goodsId))
|
||||
setTicketTemplate(tpl)
|
||||
} catch (e) {
|
||||
setTicketTemplate(null)
|
||||
}
|
||||
} else {
|
||||
setTicketTemplate(null)
|
||||
}
|
||||
|
||||
// 设置默认收货地址
|
||||
if (addressRes && addressRes.length > 0) {
|
||||
setAddress(addressRes[0])
|
||||
@@ -656,25 +699,25 @@ const OrderConfirm = () => {
|
||||
)}
|
||||
</CellGroup>
|
||||
|
||||
<CellGroup className={'hidden'}>
|
||||
<Cell
|
||||
title={(
|
||||
<View className="flex items-center gap-2">
|
||||
<Shop className={'text-gray-500'}/>
|
||||
<Text>门店</Text>
|
||||
</View>
|
||||
)}
|
||||
extra={(
|
||||
<View className={'flex items-center gap-2'}>
|
||||
<View className={'text-gray-900'}>
|
||||
{selectedStore?.name || '请选择门店'}
|
||||
</View>
|
||||
<ArrowRight className={'text-gray-400'} size={14}/>
|
||||
</View>
|
||||
)}
|
||||
onClick={openStorePopup}
|
||||
/>
|
||||
</CellGroup>
|
||||
{/*<CellGroup>*/}
|
||||
{/* <Cell*/}
|
||||
{/* title={(*/}
|
||||
{/* <View className="flex items-center gap-2">*/}
|
||||
{/* <Shop className={'text-gray-500'}/>*/}
|
||||
{/* <Text>门店</Text>*/}
|
||||
{/* </View>*/}
|
||||
{/* )}*/}
|
||||
{/* extra={(*/}
|
||||
{/* <View className={'flex items-center gap-2'}>*/}
|
||||
{/* <View className={'text-gray-900'}>*/}
|
||||
{/* {selectedStore?.name || '请选择门店'}*/}
|
||||
{/* </View>*/}
|
||||
{/* <ArrowRight className={'text-gray-400'} size={14}/>*/}
|
||||
{/* </View>*/}
|
||||
{/* )}*/}
|
||||
{/* onClick={openStorePopup}*/}
|
||||
{/* />*/}
|
||||
{/*</CellGroup>*/}
|
||||
|
||||
<CellGroup>
|
||||
<Cell key={goods.goodsId}>
|
||||
@@ -705,6 +748,12 @@ const OrderConfirm = () => {
|
||||
库存 {goods.stock} 件
|
||||
</Text>
|
||||
)}
|
||||
{isTicketTemplateActive && (
|
||||
<View className={'text-xs text-gray-500'}>
|
||||
<Text>最低购买量:{minBuyQty}桶</Text>
|
||||
<Text className={'ml-2'}>赠送水票:{getGiftTicketQty(quantity)}张</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@@ -789,12 +838,19 @@ const OrderConfirm = () => {
|
||||
)}/>
|
||||
</CellGroup>
|
||||
|
||||
<div className={'text-gray-400'}>
|
||||
{ticketTemplate && (
|
||||
<CellGroup>
|
||||
<Cell extra={(
|
||||
<div className={'text-red-500 text-sm'}>
|
||||
注意事项:
|
||||
1.最低起送量≥20桶;
|
||||
2.配送范围要在电子围栏内;
|
||||
3.上楼费暂不收取,收费另行通知。
|
||||
</div>
|
||||
)}/>
|
||||
</CellGroup>
|
||||
)}
|
||||
|
||||
|
||||
{/* 支付方式选择 */}
|
||||
<ActionSheet
|
||||
@@ -953,6 +1009,7 @@ const OrderConfirm = () => {
|
||||
type="success"
|
||||
size="large"
|
||||
loading={payLoading}
|
||||
disabled={isTicketTemplateActive && quantity < minBuyQty}
|
||||
onClick={() => onPay(goods)}
|
||||
>
|
||||
{payLoading ? '支付中...' : '立即付款'}
|
||||
|
||||
Reference in New Issue
Block a user