fix(ticket): 解决配送范围检查中的地址状态问题

- 添加 deliveryRangeCheckedAddressId 状态防止使用旧地址的配送范围结果
- 在配送范围检查成功时更新已检查地址ID
- 在配送范围检查失败时清除已检查地址ID
- 在地址变更预检查中添加已检查地址验证
- 更新依赖数组包含 deliveryRangeCheckedAddressId
- 修正提交按钮禁用条件确保只在当前地址已检查且超出范围时禁用
- 完善按钮文字显示逻辑确保只在当前地址已检查且超出范围时显示配送范围提示
This commit is contained in:
2026-02-27 15:57:48 +08:00
parent 31d47f0a0b
commit 8b5609255a

View File

@@ -81,6 +81,8 @@ const OrderConfirm = () => {
const [deliveryRangeChecking, setDeliveryRangeChecking] = useState(false)
const deliveryRangeCheckingRef = useRef(false)
const [inDeliveryRange, setInDeliveryRange] = useState<boolean | undefined>(undefined)
// Prevent using stale `inDeliveryRange` from a previous address when user switches addresses.
const [deliveryRangeCheckedAddressId, setDeliveryRangeCheckedAddressId] = useState<number | undefined>(undefined)
const router = Taro.getCurrentInstance().router;
const goodsId = router?.params?.goodsId;
@@ -264,6 +266,7 @@ const OrderConfirm = () => {
const p = await getCheckPoint()
const ok = await isPointInFence(p)
setInDeliveryRange(ok)
setDeliveryRangeCheckedAddressId(address?.id)
if (!ok) {
Taro.showToast({ title: '不在配送范围内,暂不支持下单', icon: 'none' })
}
@@ -271,6 +274,7 @@ const OrderConfirm = () => {
} catch (e: any) {
console.error('配送范围校验失败:', e)
setInDeliveryRange(undefined)
setDeliveryRangeCheckedAddressId(undefined)
// Note: we validate by address coords only; no GPS permission prompt here.
Taro.showToast({ title: e?.message || '配送范围校验失败,请稍后重试', icon: 'none' })
@@ -654,26 +658,33 @@ const OrderConfirm = () => {
;(async () => {
if (!address?.id) {
setInDeliveryRange(undefined)
setDeliveryRangeCheckedAddressId(undefined)
return
}
const p = parseLngLatFromText(`${address?.lng || ''},${address?.lat || ''}`)
if (!p) {
// Cannot validate without address coords -> treat as out of range to block ordering.
setInDeliveryRange(false)
setDeliveryRangeCheckedAddressId(address.id)
return
}
// Avoid keeping stale state from previous address while we validate this one.
setInDeliveryRange(undefined)
setDeliveryRangeCheckedAddressId(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)
if (!cancelled) {
setInDeliveryRange(undefined)
setDeliveryRangeCheckedAddressId(undefined)
}
return
}
if (cancelled) return
setInDeliveryRange(ok)
setDeliveryRangeCheckedAddressId(address.id)
})()
return () => {
cancelled = true
@@ -686,11 +697,12 @@ const OrderConfirm = () => {
useEffect(() => {
const id = address?.id
if (!id) return
if (deliveryRangeCheckedAddressId !== id) return
if (inDeliveryRange !== false) return
if (outOfRangePromptedAddressIdRef.current === id) return
outOfRangePromptedAddressIdRef.current = id
Taro.showToast({ title: addressHasCoords ? '该地址不在配送范围,请更换围栏内地址' : '该地址缺少定位,请在地址里选择地图定位后重试', icon: 'none' })
}, [address?.id, addressHasCoords, inDeliveryRange])
}, [address?.id, addressHasCoords, deliveryRangeCheckedAddressId, inDeliveryRange])
// When tickets/stock change, clamp quantity into [0..maxQuantity].
useEffect(() => {
@@ -1049,7 +1061,7 @@ const OrderConfirm = () => {
deliveryRangeChecking ||
!address?.id ||
!addressHasCoords ||
inDeliveryRange === false ||
(deliveryRangeCheckedAddressId === address?.id && inDeliveryRange === false) ||
availableTicketTotal <= 0 ||
!canStartOrder
}
@@ -1057,7 +1069,16 @@ const OrderConfirm = () => {
>
{deliveryRangeChecking
? '校验配送范围...'
: (!address?.id ? '请选择地址' : (!addressHasCoords ? '地址缺少定位' : (inDeliveryRange === false ? '不在配送范围' : (submitLoading ? '提交中...' : '立即提交'))))
: (!address?.id
? '请选择地址'
: (!addressHasCoords
? '地址缺少定位'
: ((deliveryRangeCheckedAddressId === address?.id && inDeliveryRange === false)
? '不在配送范围'
: (submitLoading ? '提交中...' : '立即提交')
)
)
)
}
</Button>
)}