feat(user): 使用微信原生 Picker 替换所在地选择弹层
- 删除 NutUI Address 相关导入、状态及地区数据转换逻辑 - 新增派生 regionValue 用于绑定微信原生 Picker 的 value - 将 handleRegionChange 调整为处理微信 Picker 的事件 - 将所在地选择 UI 修改为微信原生 Picker 包裹的视图结构 - 地图定位失败使用弹窗提示,引导用户手动选择或重试 - 移除手动打开地区选择器的函数及 NutUI 组件 - 保留 RegionData 用于文本智能识别解析 - 编译通过,提升在无地图或无权限环境下的地区选择稳定性
This commit is contained in:
@@ -24,3 +24,19 @@
|
||||
- chooseGeoLocation 兜底:去掉 regionLocked 分支,地图失败「手动选择」始终打开地区选择器。
|
||||
编译验证:`taro build --type weapp` 通过。
|
||||
(未做:手动改地区时不自动清除旧经纬度,避免误删数据;如需坐标随地区失效可再加。)
|
||||
|
||||
## 所在地区选择器:NutUI Address → 微信原生 Picker mode='region'
|
||||
|
||||
参考 weiyu-taro 项目(同为 Taro 商城,`src/pages/user/address-edit.tsx` 用原生 `<Picker mode='region'>` 选省市区),将 xinlong 的所在地区从 NutUI `<Address>` 弹层改为微信原生 Picker,与 weiyu-taro 对齐。
|
||||
|
||||
改动 `src/pages/user/address-edit.tsx`:
|
||||
- 删除 `import {Address} from '@nutui/nutui-react-taro'`、状态 `regionPickerVisible`/`regionOptions`、以及把 regions-data.json 转 NutUI options 的 useEffect。
|
||||
- 新增派生 `regionValue = [province, city, region].map(v=>String(v||''))`(3 元素数组,供原生 Picker value 绑定)。
|
||||
- `handleRegionChange` 由 NutUI `(value:string[])` 改为原生 `(e:any)` 读 `e.detail.value`,手动改后 `setRegionLocked(false)`。
|
||||
- 「所在地区」行用 `<Picker mode='region' value={regionValue} onChange={handleRegionChange}>` 包裹。
|
||||
- 删除底部 `<Address>` 组件与 `openRegionPicker` 函数。
|
||||
- 地图失败兜底:原生 Picker 无法用代码调起,改为弹 modal 引导「重试」(chooseLocation({})) / 「手动填写」(toast 提示去下方手动选);未获定位权限时 toast 引导手动选。
|
||||
|
||||
优势:零依赖、零数据准备、系统级选择器永远可用(不联网/不依赖权限/不依赖组件库),是地图不可用最稳的兜底。
|
||||
编译验证:`taro build --type weapp` 通过。
|
||||
注:RegionData 仍被 parseRegion/parseAddressText(文本智能识别)使用,import 保留。
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, {useState, useEffect, useRef} from 'react'
|
||||
import {View, Text, Input, Textarea, ScrollView} from '@tarojs/components'
|
||||
import {View, Text, Input, Textarea, ScrollView, Picker} from '@tarojs/components'
|
||||
import Taro, {useRouter} from '@tarojs/taro'
|
||||
import {Address} from '@nutui/nutui-react-taro'
|
||||
import {getShopUserAddress, addShopUserAddress, updateShopUserAddress} from '@/api/shop/shopUserAddress'
|
||||
import type {ShopUserAddress} from '@/api/shop/shopUserAddress/model'
|
||||
import {parseLngLatFromText} from '@/utils/geofence'
|
||||
@@ -109,31 +108,15 @@ const AddressEditPage: React.FC = () => {
|
||||
isDefault: false,
|
||||
})
|
||||
const [regionText, setRegionText] = useState('')
|
||||
|
||||
/** 所在地区微信原生 Picker 的 value(由 formData 派生) */
|
||||
const regionValue = [formData.province, formData.city, formData.region].map(v => String(v || ''))
|
||||
const [inputText, setInputText] = useState('')
|
||||
const [selectedLocation, setSelectedLocation] = useState<SelectedLocation | null>(null)
|
||||
const [regionLocked, setRegionLocked] = useState(false)
|
||||
const [regionPickerVisible, setRegionPickerVisible] = useState(false)
|
||||
const [regionOptions, setRegionOptions] = useState<any[]>([])
|
||||
const wxDraftRef = useRef<Partial<ShopUserAddress> | null>(null)
|
||||
const wxDraftPatchedRef = useRef(false)
|
||||
|
||||
/** 初始化省市区选择器数据 */
|
||||
useEffect(() => {
|
||||
const options = (RegionData as any[]).map((province) => ({
|
||||
value: province.label,
|
||||
text: province.label,
|
||||
children: province.children?.map((city: any) => ({
|
||||
value: city.label,
|
||||
text: city.label,
|
||||
children: city.children?.map((region: any) => ({
|
||||
value: region.label,
|
||||
text: region.label,
|
||||
})) || [],
|
||||
})) || [],
|
||||
}))
|
||||
setRegionOptions(options)
|
||||
}, [])
|
||||
|
||||
/** 解析省市区 */
|
||||
const parseRegion = (text: string) => {
|
||||
for (const province of RegionData as any[]) {
|
||||
@@ -302,8 +285,7 @@ const AddressEditPage: React.FC = () => {
|
||||
// 2. 定位权限预检 / 申请
|
||||
const granted = await ensureLocationPermission()
|
||||
if (!granted) {
|
||||
Taro.showToast({title: '未获得定位权限,可手动选择地区', icon: 'none'})
|
||||
if (!regionLocked) setRegionPickerVisible(true)
|
||||
Taro.showToast({title: '未获得定位权限,请在下方手动选择所在地区', icon: 'none'})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -320,34 +302,36 @@ const AddressEditPage: React.FC = () => {
|
||||
applyChosenLocation(res)
|
||||
} catch (e: any) {
|
||||
if (isUserCancel(e)) return
|
||||
// 4. 地图失败兜底:引导手动选择地区或重试,避免用户被卡死
|
||||
// 4. 地图失败兜底:原生 Picker 无法用代码调起,提示用户去下方手动选择所在地区;
|
||||
// 同时提供"重试"可再次尝试地图定位
|
||||
Taro.showModal({
|
||||
title: '地图打开失败',
|
||||
content: '无法调起地图定位,您可以手动选择所在地区并填写详细地址,或稍后重试。',
|
||||
confirmText: '手动选择',
|
||||
cancelText: '再试一次',
|
||||
content: '无法调起地图定位,您可以在下方手动选择所在地区并填写详细地址,或稍后重试。',
|
||||
confirmText: '重试',
|
||||
cancelText: '手动填写',
|
||||
}).then((modal) => {
|
||||
if (modal.confirm) {
|
||||
setRegionPickerVisible(true)
|
||||
} else {
|
||||
Taro.chooseLocation({})
|
||||
.then((res: any) => applyChosenLocation(res))
|
||||
.catch(() => setRegionPickerVisible(true))
|
||||
.catch(() => {
|
||||
Taro.showToast({title: '仍无法打开地图,请手动选择所在地区', icon: 'none'})
|
||||
})
|
||||
} else {
|
||||
Taro.showToast({title: '请在下方手动选择所在地区', icon: 'none'})
|
||||
}
|
||||
}).catch(() => setRegionPickerVisible(true))
|
||||
}).catch(() => {
|
||||
Taro.showToast({title: '请在下方手动选择所在地区', icon: 'none'})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/** 打开地区选择器 */
|
||||
const openRegionPicker = () => {
|
||||
setRegionPickerVisible(true)
|
||||
}
|
||||
|
||||
/** 地区选择器确认 */
|
||||
const handleRegionChange = (value: string[]) => {
|
||||
const [province, city, region] = value
|
||||
/** 地区选择器确认(微信原生 Picker mode=region) */
|
||||
const handleRegionChange = (e: any) => {
|
||||
const val = e?.detail?.value as string[]
|
||||
if (!val || val.length < 3) return
|
||||
const [province, city, region] = val
|
||||
setFormData(prev => ({...prev, province, city, region}))
|
||||
setRegionText(value.join(' '))
|
||||
setRegionText(`${province} ${city} ${region}`)
|
||||
// 用户手动修改了所在地区,解除"由地图定位锁定"状态,后续可继续手动调整
|
||||
setRegionLocked(false)
|
||||
}
|
||||
@@ -532,8 +516,9 @@ const AddressEditPage: React.FC = () => {
|
||||
{/* 表单区 */}
|
||||
<View className="bg-white px-4 py-2">
|
||||
|
||||
{/* 所在地区 */}
|
||||
<View className="flex items-center py-3 border-b border-gray-50" onClick={openRegionPicker}>
|
||||
{/* 所在地区(微信原生地区选择器,地图不可用时也可手动选择) */}
|
||||
<Picker mode='region' value={regionValue} onChange={handleRegionChange}>
|
||||
<View className="flex items-center py-3 border-b border-gray-50">
|
||||
<Text className="text-sm text-gray-700" style={{minWidth: '60px'}}>所在地区</Text>
|
||||
<View className="flex-1 flex items-center justify-between">
|
||||
<Text className={`text-sm ${regionText ? 'text-gray-800' : 'text-gray-400'}`}>
|
||||
@@ -542,6 +527,7 @@ const AddressEditPage: React.FC = () => {
|
||||
<Text className="text-gray-300 text-xs">▶</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Picker>
|
||||
|
||||
{/* 详细地址 */}
|
||||
<View className="flex items-center py-3 border-b border-gray-50">
|
||||
@@ -613,15 +599,6 @@ const AddressEditPage: React.FC = () => {
|
||||
<Text className="text-white font-medium text-sm">{isEditMode ? '更新地址' : '保存并使用'}</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 省市区选择器 */}
|
||||
<Address
|
||||
visible={regionPickerVisible}
|
||||
options={regionOptions}
|
||||
title="选择所在地区"
|
||||
onChange={(value) => handleRegionChange(value as string[])}
|
||||
onClose={() => setRegionPickerVisible(false)}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user