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