fix(order): 修复订单状态判断逻辑和配送范围验证

- 修复订单状态数值转换逻辑,统一使用 toNum 函数处理状态值
- 移除基于 formId 推断订单完成状态的逻辑,改用 orderStatus 字段
- 更新订单列表中各状态的条件判断,确保标签页与状态文案同步
- 修改配送范围验证逻辑,移除GPS定位回退,仅使用地址坐标验证
- 添加地址坐标缺失的错误提示和表单验证
- 更新配送范围检查的UI状态管理和错误处理流程
- 优化按钮状态控制,增加地址坐标验证检查
```
This commit is contained in:
2026-02-27 15:49:21 +08:00
parent 68d5848d3d
commit 31d47f0a0b
2 changed files with 83 additions and 57 deletions

View File

@@ -249,12 +249,11 @@ const OrderConfirm = () => {
}
const getCheckPoint = async (): Promise<{ lng: number; lat: number }> => {
// Prefer address coords (delivery location). Fallback to current GPS if address doesn't have coords.
// Immediate water delivery must validate by the delivery address coordinates.
// Falling back to current GPS may allow ordering with an out-of-fence address.
const byAddress = parseLngLatFromText(`${address?.lng || ''},${address?.lat || ''}`)
if (byAddress) return byAddress
const loc = await Taro.getLocation({ type: 'gcj02' })
return { lng: loc.longitude, lat: loc.latitude }
throw new Error('该收货地址缺少经纬度,请在地址里选择地图定位后重试')
}
const ensureInDeliveryRange = async (): Promise<boolean> => {
@@ -272,30 +271,7 @@ const OrderConfirm = () => {
} catch (e: any) {
console.error('配送范围校验失败:', e)
setInDeliveryRange(undefined)
const msg = String(e?.errMsg || e?.message || '')
const denied =
msg.includes('auth deny') ||
msg.includes('authorize') ||
msg.includes('permission') ||
msg.includes('denied') ||
msg.includes('scope.userLocation')
if (denied) {
const r = await Taro.showModal({
title: '需要定位权限',
content: '下单前需要校验是否在配送范围内,请在设置中开启定位权限后重试。',
confirmText: '去设置'
})
if (r.confirm) {
try {
await Taro.openSetting()
} catch (_e) {
// ignore
}
}
return false
}
// Note: we validate by address coords only; no GPS permission prompt here.
Taro.showToast({ title: e?.message || '配送范围校验失败,请稍后重试', icon: 'none' })
return false
@@ -504,6 +480,10 @@ const OrderConfirm = () => {
Taro.showToast({ title: '请选择收货地址', icon: 'none' })
return
}
if (!addressHasCoords) {
Taro.showToast({ title: '该收货地址缺少经纬度,请在地址里选择地图定位后重试', icon: 'none' })
return
}
// Ensure ticket list is loaded.
if (ticketLoading) {
@@ -655,6 +635,11 @@ const OrderConfirm = () => {
loadAllData({ silent: hasInitialLoadedRef.current })
})
const addressHasCoords = useMemo(() => {
if (!address?.id) return false
return !!parseLngLatFromText(`${address?.lng || ''},${address?.lat || ''}`)
}, [address?.id, address?.lng, address?.lat])
// Auto-pick nearest store by delivery address (best-effort, won't override manual selection).
useEffect(() => {
if (!address?.id) return
@@ -667,13 +652,24 @@ const OrderConfirm = () => {
useEffect(() => {
let cancelled = false
;(async () => {
if (!address?.id) {
setInDeliveryRange(undefined)
return
}
const p = parseLngLatFromText(`${address?.lng || ''},${address?.lat || ''}`)
if (!p) return
if (!p) {
// Cannot validate without address coords -> treat as out of range to block ordering.
setInDeliveryRange(false)
return
}
// Avoid keeping stale state from previous address while we validate this one.
setInDeliveryRange(undefined)
let ok = true
try {
ok = await isPointInFence(p)
} catch (_e) {
// Pre-check is best-effort; don't block UI here.
if (!cancelled) setInDeliveryRange(undefined)
return
}
if (cancelled) return
@@ -685,6 +681,17 @@ const OrderConfirm = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [address?.id, address?.lng, address?.lat])
// When user changes the delivery address to an out-of-fence one, prompt immediately (once per address).
const outOfRangePromptedAddressIdRef = useRef<number | undefined>(undefined)
useEffect(() => {
const id = address?.id
if (!id) return
if (inDeliveryRange !== false) return
if (outOfRangePromptedAddressIdRef.current === id) return
outOfRangePromptedAddressIdRef.current = id
Taro.showToast({ title: addressHasCoords ? '该地址不在配送范围,请更换围栏内地址' : '该地址缺少定位,请在地址里选择地图定位后重试', icon: 'none' })
}, [address?.id, addressHasCoords, inDeliveryRange])
// When tickets/stock change, clamp quantity into [0..maxQuantity].
useEffect(() => {
setQuantity(prev => {
@@ -761,7 +768,10 @@ const OrderConfirm = () => {
<CellGroup>
{
address && (
<Cell className={'address-bottom-line'}>
<Cell
className={'address-bottom-line'}
onClick={() => Taro.navigateTo({ url: '/user/address/index' })}
>
<Space>
<Location className={'text-gray-500'}/>
<View className={'flex flex-col w-full justify-between items-start'}>
@@ -1037,6 +1047,8 @@ const OrderConfirm = () => {
loading={submitLoading || deliveryRangeChecking}
disabled={
deliveryRangeChecking ||
!address?.id ||
!addressHasCoords ||
inDeliveryRange === false ||
availableTicketTotal <= 0 ||
!canStartOrder
@@ -1045,7 +1057,7 @@ const OrderConfirm = () => {
>
{deliveryRangeChecking
? '校验配送范围...'
: (inDeliveryRange === false ? '不在配送范围' : (submitLoading ? '提交中...' : '立即提交'))
: (!address?.id ? '请选择地址' : (!addressHasCoords ? '地址缺少定位' : (inDeliveryRange === false ? '不在配送范围' : (submitLoading ? '提交中...' : '立即提交'))))
}
</Button>
)}