diff --git a/src/user/ticket/index.tsx b/src/user/ticket/index.tsx index 4e6a374..024811c 100644 --- a/src/user/ticket/index.tsx +++ b/src/user/ticket/index.tsx @@ -748,37 +748,6 @@ const UserTicketList = () => { 下单时间:{formatDateTime(item.createTime)} - {item.id ? ( - - - - - ) : null} {/*{item.storeName ? (*/} {/* */} {/* 门店:{item.storeName}*/} @@ -815,6 +784,38 @@ const UserTicketList = () => { ) : null} + + {item.id ? ( + + + + + ) : null} ))} diff --git a/src/user/ticket/use.tsx b/src/user/ticket/use.tsx index 70ddd5b..3e84fd0 100644 --- a/src/user/ticket/use.tsx +++ b/src/user/ticket/use.tsx @@ -28,7 +28,6 @@ import type { GltUserTicket } from '@/api/glt/gltUserTicket/model' import { getGltUserTicket, listGltUserTicket } from '@/api/glt/gltUserTicket' import { getGltTicketTemplate, getGltTicketTemplateByGoodsId } from '@/api/glt/gltTicketTemplate' import { addGltTicketOrder, getGltTicketOrder, updateGltTicketOrder } from '@/api/glt/gltTicketOrder' -import { pageGltTicketOrder } from '@/api/glt/gltTicketOrder' import type { GltTicketOrder } from '@/api/glt/gltTicketOrder/model' import type { ShopStoreRider } from '@/api/shop/shopStoreRider/model' import { listShopStoreRider } from '@/api/shop/shopStoreRider' @@ -37,7 +36,6 @@ import { listShopStoreFence } from '@/api/shop/shopStoreFence' import { parseFencePoints, parseLngLatFromText, pointInAnyPolygon, pointInPolygon } from '@/utils/geofence' const DEFAULT_MIN_START_QTY = 10 -const ADDRESS_CHANGE_COOLDOWN_DAYS = 30 const OrderConfirm = () => { const [goods, setGoods] = useState(null); @@ -112,18 +110,6 @@ const OrderConfirm = () => { return Number.isFinite(id) && id > 0 ? id : undefined }, []) - type TicketAddressModifyLimit = { - loaded: boolean - canModify: boolean - nextAllowedText?: string - lockedAddressId?: number - } - const [ticketAddressModifyLimit, setTicketAddressModifyLimit] = useState({ - loaded: false, - canModify: true, - }) - const ticketAddressModifyLimitPromiseRef = useRef | null>(null) - const parseTime = (raw?: unknown) => { if (raw === undefined || raw === null || raw === '') return null // Compatible with seconds/milliseconds timestamps. @@ -142,111 +128,16 @@ const OrderConfirm = () => { return d.isBefore(today, 'day') ? today : d.startOf('day') } - const getOrderTime = (o?: Partial | null) => { - return parseTime(o?.createTime) || parseTime(o?.updateTime) - } - - const getOrderAddressKey = (o?: Partial | null) => { - const id = Number(o?.addressId) - if (Number.isFinite(id) && id > 0) return `id:${id}` - const txt = String(o?.address || '').trim() - if (txt) return `txt:${txt}` - return '' - } - - const loadTicketAddressModifyLimit = async (): Promise => { - if (ticketAddressModifyLimitPromiseRef.current) return ticketAddressModifyLimitPromiseRef.current - - ticketAddressModifyLimitPromiseRef.current = (async () => { - if (!userId) return { loaded: true, canModify: true } - - const now = dayjs() - const pageSize = 20 - let page = 1 - const all: GltTicketOrder[] = [] - - let latestKey = '' - let latestAddressId: number | undefined = undefined - - while (true) { - const res = await pageGltTicketOrder({ page, limit: pageSize, userId }) - const list = Array.isArray(res?.list) ? res.list : [] - if (page === 1) { - const first = list[0] - latestKey = getOrderAddressKey(first) - const id = Number(first?.addressId) - latestAddressId = Number.isFinite(id) && id > 0 ? id : undefined - } - - if (!list.length) break - all.push(...list) - - // Find the oldest order in the newest contiguous block of the latest address key. - // That order's time represents the last time user "set/changed" the ticket delivery address. - const currentKey = latestKey - if (!currentKey) { - return { loaded: true, canModify: true } - } - - let lastSameIndex = 0 - let foundDifferent = false - for (let i = 1; i < all.length; i++) { - const k = getOrderAddressKey(all[i]) - if (!k) continue - if (k === currentKey) { - lastSameIndex = i - continue - } - foundDifferent = true - break - } - - if (foundDifferent) { - const lastSetAt = getOrderTime(all[lastSameIndex]) - if (!lastSetAt) return { loaded: true, canModify: true, lockedAddressId: latestAddressId } - const nextAllowed = lastSetAt.add(ADDRESS_CHANGE_COOLDOWN_DAYS, 'day') - const canModify = now.isAfter(nextAllowed) - return { - loaded: true, - canModify, - nextAllowedText: nextAllowed.format('YYYY-MM-DD'), - lockedAddressId: latestAddressId, - } - } - - const oldest = getOrderTime(all[all.length - 1]) - if (oldest && now.diff(oldest, 'day') >= ADDRESS_CHANGE_COOLDOWN_DAYS) { - // We have enough history beyond the cooldown window, and still no different address found. - return { loaded: true, canModify: true, lockedAddressId: latestAddressId } - } - - const totalCount = typeof (res as any)?.count === 'number' ? Number((res as any).count) : undefined - if (totalCount !== undefined && all.length >= totalCount) break - if (list.length < pageSize) break - - page += 1 - if (page > 10) break // safety: avoid excessive paging - } - - if (!all.length) return { loaded: true, canModify: true } - - // If we can't prove the last-set time is older than the cooldown window, be conservative and lock. - const lastSetAt = getOrderTime(all[all.length - 1]) - if (!lastSetAt) return { loaded: true, canModify: true, lockedAddressId: latestAddressId } - const nextAllowed = lastSetAt.add(ADDRESS_CHANGE_COOLDOWN_DAYS, 'day') - const canModify = now.isAfter(nextAllowed) - return { - loaded: true, - canModify, - nextAllowedText: nextAllowed.format('YYYY-MM-DD'), - lockedAddressId: latestAddressId, - } - })() - .finally(() => { - ticketAddressModifyLimitPromiseRef.current = null - }) - - return ticketAddressModifyLimitPromiseRef.current + const isPendingDeliveryOrder = (o?: Partial | null) => { + if (!o) return false + const ds = (o as any)?.deliveryStatus + const hasProgress = !!o.sendStartTime || !!o.sendEndTime || !!o.receiveConfirmTime + return ( + Number((o as any)?.deleted) !== 1 && + Number(o.status) !== 1 && + !hasProgress && + (ds === 10 || (typeof ds !== 'number' && !!o.riderId)) + ) } const getTicketAvailableQty = (t?: Partial | null) => { @@ -363,17 +254,15 @@ const OrderConfirm = () => { } const openAddressPage = async () => { - const limit = ticketAddressModifyLimit.loaded - ? ticketAddressModifyLimit - : await loadTicketAddressModifyLimit().catch(() => ({ loaded: true, canModify: true } as TicketAddressModifyLimit)) - if (!ticketAddressModifyLimit.loaded) setTicketAddressModifyLimit(limit) - - if (!limit.canModify) { - Taro.showToast({ - title: `送水地址每${ADDRESS_CHANGE_COOLDOWN_DAYS}天可修改一次${limit.nextAllowedText ? ',' + limit.nextAllowedText + ' 后可修改' : ''}`, - icon: 'none', - }) - return + if (isEditMode) { + if (!editingOrder?.id) { + Taro.showToast({ title: '订单信息加载中,请稍后重试', icon: 'none' }) + return + } + if (!isPendingDeliveryOrder(editingOrder)) { + Taro.showToast({ title: '该订单当前不可修改', icon: 'none' }) + return + } } Taro.navigateTo({ url: '/user/address/index' }) } @@ -662,27 +551,12 @@ const OrderConfirm = () => { Taro.showToast({ title: '订单信息加载中,请稍后重试', icon: 'none' }) return } - if (!address?.id) { - Taro.showToast({ title: '请选择收货地址', icon: 'none' }) + if (isEditMode && !isPendingDeliveryOrder(editingOrder)) { + Taro.showToast({ title: '该订单当前不可修改', icon: 'none' }) return } - - // Ticket delivery address is based on order snapshot. Enforce "once per 30 days" by latest ticket-order history. - const limit = ticketAddressModifyLimit.loaded - ? ticketAddressModifyLimit - : await loadTicketAddressModifyLimit().catch(() => ({ loaded: true, canModify: true } as TicketAddressModifyLimit)) - if (!ticketAddressModifyLimit.loaded) setTicketAddressModifyLimit(limit) - if (!limit.canModify && limit.lockedAddressId && address.id !== limit.lockedAddressId) { - Taro.showToast({ - title: `送水地址每${ADDRESS_CHANGE_COOLDOWN_DAYS}天可修改一次,请使用上次下单地址${limit.nextAllowedText ? '(' + limit.nextAllowedText + ' 后可修改)' : ''}`, - icon: 'none', - }) - try { - const locked = await getShopUserAddress(limit.lockedAddressId) - if (locked?.id) setAddress(locked) - } catch (_e) { - // ignore: keep current address, but still block submission - } + if (!address?.id) { + Taro.showToast({ title: '请选择收货地址', icon: 'none' }) return } if (!addressHasCoords) { @@ -861,13 +735,7 @@ const OrderConfirm = () => { setEditingOrder(editingOrderRes) Taro.setNavigationBarTitle({ title: '订单确认' }) - const ds = editingOrderRes.deliveryStatus - const hasProgress = !!editingOrderRes.sendStartTime || !!editingOrderRes.sendEndTime || !!editingOrderRes.receiveConfirmTime - const isPending = - Number((editingOrderRes as any)?.deleted) !== 1 && - Number(editingOrderRes.status) !== 1 && - !hasProgress && - (ds === 10 || (typeof ds !== 'number' && !!editingOrderRes.riderId)) + const isPending = isPendingDeliveryOrder(editingOrderRes) if (!isPending) { Taro.showToast({ title: '该订单当前不可修改', icon: 'none' }) setTimeout(() => { @@ -898,20 +766,6 @@ const OrderConfirm = () => { } } } - - // Load ticket-order history to enforce "address can be modified once per 30 days". - // If currently locked, force using last ticket-order address (snapshot) to avoid getting stuck with a new default address. - try { - const limit = await loadTicketAddressModifyLimit() - setTicketAddressModifyLimit(limit) - if (!limit.canModify && limit.lockedAddressId) { - const locked = await getShopUserAddress(limit.lockedAddressId) - if (locked?.id) setAddress(locked) - } - } catch (e) { - console.error('加载送水地址修改限制失败:', e) - setTicketAddressModifyLimit({ loaded: true, canModify: true }) - } // Tickets are non-blocking for first paint; load in background. loadUserTickets() } catch (err) { @@ -989,10 +843,6 @@ const OrderConfirm = () => { // When user changes the delivery address to an out-of-fence one, prompt immediately (once per address). const outOfRangePromptedAddressIdRef = useRef(undefined) useEffect(() => { - // Only prompt when user is allowed to change the ticket delivery address. - // Otherwise this toast is noisy (they can't fix it within the cooldown window). - if (!ticketAddressModifyLimit.loaded) return - if (!ticketAddressModifyLimit.canModify) return const id = address?.id if (!id) return if (deliveryRangeCheckedAddressId !== id) return @@ -1004,9 +854,7 @@ const OrderConfirm = () => { address?.id, addressHasCoords, deliveryRangeCheckedAddressId, - inDeliveryRange, - ticketAddressModifyLimit.loaded, - ticketAddressModifyLimit.canModify + inDeliveryRange ]) // When tickets/stock change, clamp quantity into [0..maxQuantity]. @@ -1145,12 +993,6 @@ const OrderConfirm = () => { {address.name} {address.phone} - {ticketAddressModifyLimit.loaded && !ticketAddressModifyLimit.canModify && ( - - 送水地址每{ADDRESS_CHANGE_COOLDOWN_DAYS}天可修改一次 - {ticketAddressModifyLimit.nextAllowedText ? `,${ticketAddressModifyLimit.nextAllowedText} 后可修改` : ''} - - )} @@ -1342,7 +1184,7 @@ const OrderConfirm = () => { @@ -1426,7 +1268,7 @@ const OrderConfirm = () => {
{noUsableTickets ? ( ) : (