forked from gxwebsoft/mp-10550
fix(order): 修复配送时间截单逻辑并移除微信地址功能
- 添加当日21点截单时间控制,超过时间下单最早配送日顺延到次日 - 在订单确认页面实现截单时间校验和自动调整配送时间 - 移除用户地址管理中的获取微信地址功能相关代码 - 修复地址表单中CellGroup组件嵌套结构问题 - 更新配送时间选择器的起始日期计算逻辑
This commit is contained in:
@@ -58,7 +58,16 @@ const OrderConfirm = () => {
|
|||||||
const [error, setError] = useState<string>('')
|
const [error, setError] = useState<string>('')
|
||||||
const [payLoading, setPayLoading] = useState<boolean>(false)
|
const [payLoading, setPayLoading] = useState<boolean>(false)
|
||||||
// 配送时间(仅水票套票商品需要)
|
// 配送时间(仅水票套票商品需要)
|
||||||
const [sendTime, setSendTime] = useState<Date>(() => dayjs().startOf('day').toDate())
|
// 当日截单时间:超过该时间下单,最早配送日顺延到次日(避免 21:00 下单仍显示“当天配送”)
|
||||||
|
const DELIVERY_CUTOFF_HOUR = 21
|
||||||
|
const getMinSendDate = () => {
|
||||||
|
const now = dayjs()
|
||||||
|
const cutoff = now.hour(DELIVERY_CUTOFF_HOUR).minute(0).second(0).millisecond(0)
|
||||||
|
const startOfToday = now.startOf('day')
|
||||||
|
// >= 截单时间则最早只能选次日
|
||||||
|
return now.isSame(cutoff) || now.isAfter(cutoff) ? startOfToday.add(1, 'day') : startOfToday
|
||||||
|
}
|
||||||
|
const [sendTime, setSendTime] = useState<Date>(() => getMinSendDate().toDate())
|
||||||
const [sendTimePickerVisible, setSendTimePickerVisible] = useState(false)
|
const [sendTimePickerVisible, setSendTimePickerVisible] = useState(false)
|
||||||
|
|
||||||
// 水票套票活动(若存在则按规则限制最小购买量等)
|
// 水票套票活动(若存在则按规则限制最小购买量等)
|
||||||
@@ -446,6 +455,17 @@ const OrderConfirm = () => {
|
|||||||
Taro.showToast({ title: '请选择配送时间', icon: 'none' })
|
Taro.showToast({ title: '请选择配送时间', icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (hasTicketTemplate) {
|
||||||
|
const min = getMinSendDate()
|
||||||
|
if (dayjs(sendTime).isBefore(min, 'day')) {
|
||||||
|
setSendTime(min.toDate())
|
||||||
|
Taro.showToast({
|
||||||
|
title: `已过当日${DELIVERY_CUTOFF_HOUR}点截单,最早配送:${min.format('YYYY-MM-DD')}`,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 水票套票活动:最小购买量校验
|
// 水票套票活动:最小购买量校验
|
||||||
if (isTicketTemplateActive && quantity < minBuyQty) {
|
if (isTicketTemplateActive && quantity < minBuyQty) {
|
||||||
@@ -716,7 +736,7 @@ const OrderConfirm = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 切换商品时重置配送时间,避免沿用上一次选择
|
// 切换商品时重置配送时间,避免沿用上一次选择
|
||||||
if (!isLoggedIn()) return
|
if (!isLoggedIn()) return
|
||||||
setSendTime(dayjs().startOf('day').toDate())
|
setSendTime(getMinSendDate().toDate())
|
||||||
setSendTimePickerVisible(false)
|
setSendTimePickerVisible(false)
|
||||||
loadAllData()
|
loadAllData()
|
||||||
}, [goodsId]);
|
}, [goodsId]);
|
||||||
@@ -786,7 +806,14 @@ const OrderConfirm = () => {
|
|||||||
<ArrowRight className={'text-gray-400'} size={14}/>
|
<ArrowRight className={'text-gray-400'} size={14}/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
onClick={() => setSendTimePickerVisible(true)}
|
onClick={() => {
|
||||||
|
// 若页面停留跨过截单时间,打开选择器前再校正一次最早可选日期
|
||||||
|
const min = getMinSendDate()
|
||||||
|
if (dayjs(sendTime).isBefore(min, 'day')) {
|
||||||
|
setSendTime(min.toDate())
|
||||||
|
}
|
||||||
|
setSendTimePickerVisible(true)
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</CellGroup>
|
</CellGroup>
|
||||||
)}
|
)}
|
||||||
@@ -1087,7 +1114,7 @@ const OrderConfirm = () => {
|
|||||||
visible={sendTimePickerVisible}
|
visible={sendTimePickerVisible}
|
||||||
title="选择配送时间"
|
title="选择配送时间"
|
||||||
type="date"
|
type="date"
|
||||||
startDate={dayjs().startOf('day').toDate()}
|
startDate={getMinSendDate().toDate()}
|
||||||
endDate={dayjs().add(30, 'day').toDate()}
|
endDate={dayjs().add(30, 'day').toDate()}
|
||||||
value={sendTime}
|
value={sendTime}
|
||||||
onClose={() => setSendTimePickerVisible(false)}
|
onClose={() => setSendTimePickerVisible(false)}
|
||||||
|
|||||||
@@ -589,11 +589,13 @@ const AddUserAddress = () => {
|
|||||||
<Form.Item name="address" label="收货地址" initialValue={FormData.address} required>
|
<Form.Item name="address" label="收货地址" initialValue={FormData.address} required>
|
||||||
<TextArea maxLength={50} placeholder="请输入详细收货地址"/>
|
<TextArea maxLength={50} placeholder="请输入详细收货地址"/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
</CellGroup>
|
||||||
|
<CellGroup>
|
||||||
<Cell
|
<Cell
|
||||||
title="选择定位"
|
title="选择定位"
|
||||||
description={
|
description={
|
||||||
selectedLocation?.address ||
|
selectedLocation?.address ||
|
||||||
(selectedLocation ? `经纬度:${selectedLocation.lng}, ${selectedLocation.lat}` : '')
|
(selectedLocation ? `经纬度:${selectedLocation.lng}, ${selectedLocation.lat}` : '用于计算是否超出配送范围')
|
||||||
}
|
}
|
||||||
extra={(
|
extra={(
|
||||||
<div className={'flex items-center gap-2'}>
|
<div className={'flex items-center gap-2'}>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {useState} from "react";
|
import {useState} from "react";
|
||||||
import Taro, {useDidShow} from '@tarojs/taro'
|
import Taro, {useDidShow} from '@tarojs/taro'
|
||||||
import {Button, Cell, CellGroup, Space, Empty, ConfigProvider, Divider} from '@nutui/nutui-react-taro'
|
import {Button, Cell, Space, Empty, ConfigProvider, Divider} from '@nutui/nutui-react-taro'
|
||||||
import {Dongdong, ArrowRight, CheckNormal, Checked} from '@nutui/icons-react-taro'
|
import {CheckNormal, Checked} from '@nutui/icons-react-taro'
|
||||||
import {View} from '@tarojs/components'
|
import {View} from '@tarojs/components'
|
||||||
import {ShopUserAddress} from "@/api/shop/shopUserAddress/model";
|
import {ShopUserAddress} from "@/api/shop/shopUserAddress/model";
|
||||||
import {listShopUserAddress, removeShopUserAddress, updateShopUserAddress} from "@/api/shop/shopUserAddress";
|
import {listShopUserAddress, removeShopUserAddress, updateShopUserAddress} from "@/api/shop/shopUserAddress";
|
||||||
@@ -144,8 +144,8 @@ const Address = () => {
|
|||||||
/>
|
/>
|
||||||
<Space>
|
<Space>
|
||||||
<Button onClick={() => Taro.navigateTo({url: '/user/address/add'})}>新增地址</Button>
|
<Button onClick={() => Taro.navigateTo({url: '/user/address/add'})}>新增地址</Button>
|
||||||
<Button type="success" fill="dashed"
|
{/*<Button type="success" fill="dashed"*/}
|
||||||
onClick={() => Taro.navigateTo({url: '/user/address/wxAddress'})}>获取微信地址</Button>
|
{/* onClick={() => Taro.navigateTo({url: '/user/address/wxAddress'})}>获取微信地址</Button>*/}
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
@@ -154,19 +154,19 @@ const Address = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CellGroup>
|
{/*<CellGroup>*/}
|
||||||
<Cell
|
{/* <Cell*/}
|
||||||
onClick={() => Taro.navigateTo({url: '/user/address/wxAddress'})}
|
{/* onClick={() => Taro.navigateTo({url: '/user/address/wxAddress'})}*/}
|
||||||
>
|
{/* >*/}
|
||||||
<div className={'flex justify-between items-center w-full'}>
|
{/* <div className={'flex justify-between items-center w-full'}>*/}
|
||||||
<div className={'flex items-center gap-3'}>
|
{/* <div className={'flex items-center gap-3'}>*/}
|
||||||
<Dongdong className={'text-green-600'}/>
|
{/* <Dongdong className={'text-green-600'}/>*/}
|
||||||
<div>获取微信地址</div>
|
{/* <div>获取微信地址</div>*/}
|
||||||
</div>
|
{/* </div>*/}
|
||||||
<ArrowRight className={'text-gray-400'}/>
|
{/* <ArrowRight className={'text-gray-400'}/>*/}
|
||||||
</div>
|
{/* </div>*/}
|
||||||
</Cell>
|
{/* </Cell>*/}
|
||||||
</CellGroup>
|
{/*</CellGroup>*/}
|
||||||
{list.map((item, _) => (
|
{list.map((item, _) => (
|
||||||
<Cell.Group>
|
<Cell.Group>
|
||||||
<Cell className={'flex flex-col gap-1'} onClick={() => selectAddress(item)}>
|
<Cell className={'flex flex-col gap-1'} onClick={() => selectAddress(item)}>
|
||||||
|
|||||||
Reference in New Issue
Block a user