fix(address): 修复地址管理中的经纬度验证和导航逻辑

- 添加 parseLngLatFromText 工具函数用于解析经纬度坐标
- 实现 hasValidLngLat 函数验证地址是否包含有效经纬度信息
- 在新增地址时检查默认地址是否缺少经纬度并引导用户完善定位
- 使用 hasValidLngLat 替换原有的经纬度验证逻辑
- 添加安全返回功能避免地址列表页导航异常
- 设置默认地址后自动返回上一页提升用户体验
```
This commit is contained in:
2026-02-22 11:36:18 +08:00
parent 00d3ffaeee
commit 694b5e1e7a
2 changed files with 55 additions and 5 deletions

View File

@@ -9,6 +9,7 @@ import {ShopUserAddress} from "@/api/shop/shopUserAddress/model";
import {getShopUserAddress, listShopUserAddress, updateShopUserAddress, addShopUserAddress} from "@/api/shop/shopUserAddress"; import {getShopUserAddress, listShopUserAddress, updateShopUserAddress, addShopUserAddress} from "@/api/shop/shopUserAddress";
import RegionData from '@/api/json/regions-data.json'; import RegionData from '@/api/json/regions-data.json';
import FixedButton from "@/components/FixedButton"; import FixedButton from "@/components/FixedButton";
import { parseLngLatFromText } from "@/utils/geofence";
type SelectedLocation = { lng: string; lat: string; name?: string; address?: string } type SelectedLocation = { lng: string; lat: string; name?: string; address?: string }
@@ -28,6 +29,15 @@ const isUserCancel = (e: any) => {
return msg.includes('cancel') return msg.includes('cancel')
} }
const hasValidLngLat = (addr?: Partial<ShopUserAddress> | null) => {
if (!addr) return false
const p = parseLngLatFromText(`${(addr as any)?.lng ?? ''},${(addr as any)?.lat ?? ''}`)
if (!p) return false
// Treat "0,0" as missing in this app (typically used as placeholder by backends).
if (p.lng === 0 && p.lat === 0) return false
return true
}
const AddUserAddress = () => { const AddUserAddress = () => {
const {params} = useRouter(); const {params} = useRouter();
const [loading, setLoading] = useState<boolean>(true) const [loading, setLoading] = useState<boolean>(true)
@@ -47,6 +57,31 @@ const AddUserAddress = () => {
// 整理地区数据 // 整理地区数据
setRegionData() setRegionData()
// 新增模式:若存在“默认地址”但缺少经纬度,则强制引导到编辑页完善定位
// 目的:确保业务依赖默认地址坐标(选店/配送范围)时不会因为缺失坐标而失败
if (!isEditMode) {
try {
const defaultList = await listShopUserAddress({ isDefault: true })
const defaultAddr = defaultList?.[0]
if (defaultAddr && !hasValidLngLat(defaultAddr)) {
await Taro.showModal({
title: '需要完善定位',
content: '默认收货地址缺少定位信息,请先进入编辑页面选择定位并保存后再继续。',
confirmText: '去完善',
showCancel: false
})
if (defaultAddr.id) {
Taro.navigateTo({ url: `/user/address/add?id=${defaultAddr.id}` })
} else {
Taro.navigateTo({ url: '/user/address/index' })
}
return
}
} catch (_e) {
// ignore: 新增页不阻塞渲染
}
}
// 如果是编辑模式,加载地址数据 // 如果是编辑模式,加载地址数据
if (isEditMode && addressId) { if (isEditMode && addressId) {
try { try {
@@ -55,9 +90,7 @@ const AddUserAddress = () => {
// 设置所在地区 // 设置所在地区
setText(`${address.province} ${address.city} ${address.region}`) setText(`${address.province} ${address.city} ${address.region}`)
// 回显已保存的经纬度(编辑模式) // 回显已保存的经纬度(编辑模式)
if (address?.lng && address?.lat) { if (hasValidLngLat(address)) setSelectedLocation({ lng: String(address.lng), lat: String(address.lat) })
setSelectedLocation({ lng: String(address.lng), lat: String(address.lat) })
}
} catch (error) { } catch (error) {
console.error('加载地址失败:', error) console.error('加载地址失败:', error)
Taro.showToast({ Taro.showToast({
@@ -348,7 +381,7 @@ const AddUserAddress = () => {
const submitSucceed = async (values: any) => { const submitSucceed = async (values: any) => {
const loc = const loc =
selectedLocation || selectedLocation ||
(FormData?.lng && FormData?.lat ? { lng: String(FormData.lng), lat: String(FormData.lat) } : null) (hasValidLngLat(FormData) ? { lng: String(FormData.lng), lat: String(FormData.lat) } : null)
if (!loc) { if (!loc) {
Taro.showToast({ title: '请选择定位', icon: 'none' }) Taro.showToast({ title: '请选择定位', icon: 'none' })
return return

View File

@@ -13,6 +13,19 @@ const Address = () => {
const [list, setList] = useState<ShopUserAddress[]>([]) const [list, setList] = useState<ShopUserAddress[]>([])
const [address, setAddress] = useState<ShopUserAddress>() const [address, setAddress] = useState<ShopUserAddress>()
const safeNavigateBack = async () => {
try {
const pages = (Taro as any).getCurrentPages?.() || []
if (Array.isArray(pages) && pages.length > 1) {
await Taro.navigateBack()
return true
}
} catch (_e) {
// ignore
}
return false
}
const parseTime = (raw?: unknown) => { const parseTime = (raw?: unknown) => {
if (raw === undefined || raw === null || raw === '') return null; if (raw === undefined || raw === null || raw === '') return null;
// 兼容秒/毫秒时间戳 // 兼容秒/毫秒时间戳
@@ -78,7 +91,11 @@ const Address = () => {
title: '设置成功', title: '设置成功',
icon: 'success' icon: 'success'
}); });
reload(); // 设置默认地址通常是“选择地址”的动作:成功后返回上一页,体验更顺滑
setTimeout(async () => {
const backed = await safeNavigateBack()
if (!backed) reload()
}, 400)
} }
const onDel = async (id?: number) => { const onDel = async (id?: number) => {