fix(order): 修复配送时间截单逻辑并移除微信地址功能

- 添加当日21点截单时间控制,超过时间下单最早配送日顺延到次日
- 在订单确认页面实现截单时间校验和自动调整配送时间
- 移除用户地址管理中的获取微信地址功能相关代码
- 修复地址表单中CellGroup组件嵌套结构问题
- 更新配送时间选择器的起始日期计算逻辑
This commit is contained in:
2026-02-26 01:25:35 +08:00
parent d86cdad470
commit f9dcaa9ce9
3 changed files with 51 additions and 22 deletions

View File

@@ -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)}

View File

@@ -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'}>

View File

@@ -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)}>