- 支付页面新增线下付款选项,支持微信转账付款方式 - 订单流程新增线下付款待确认(offline_pending)阶段 - 订单详情与订单卡片显示线下付款状态及提示信息 - 支付接口和模型增加线下付款支付方式(payType=9)支持 - 订单列表页区分线下付款待确认与待收款状态 - 地址编辑页修复智能识别按钮无法点击问题,调整布局避免被Textarea遮挡
608 lines
25 KiB
TypeScript
608 lines
25 KiB
TypeScript
import React, {useState, useEffect, useRef} from 'react'
|
||
import {View, Text, Input, Textarea, ScrollView, Picker} from '@tarojs/components'
|
||
import Taro, {useRouter} from '@tarojs/taro'
|
||
import {getShopUserAddress, addShopUserAddress, updateShopUserAddress} from '@/api/shop/shopUserAddress'
|
||
import type {ShopUserAddress} from '@/api/shop/shopUserAddress/model'
|
||
import {parseLngLatFromText} from '@/utils/geofence'
|
||
import RegionData from '@/api/json/regions-data.json'
|
||
|
||
definePageConfig({
|
||
navigationBarTitleText: '新增收货地址',
|
||
})
|
||
|
||
type SelectedLocation = { lng: string; lat: string; name?: string; address?: string }
|
||
|
||
const isUserCancel = (e: any) => {
|
||
const msg = String(e?.errMsg || e?.message || e || '')
|
||
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
|
||
if (p.lng === 0 && p.lat === 0) return false
|
||
return true
|
||
}
|
||
|
||
/** 确保已通过微信隐私授权(定位类接口前置要求);旧基础库无该接口时直接放行 */
|
||
const ensurePrivacyAuthorized = (): Promise<void> => {
|
||
return new Promise((resolve) => {
|
||
const wxAny: any = Taro
|
||
if (typeof wxAny.requirePrivacyAuthorize !== 'function') {
|
||
resolve()
|
||
return
|
||
}
|
||
if (typeof wxAny.getPrivacySetting === 'function') {
|
||
wxAny.getPrivacySetting({
|
||
success: (res: any) => {
|
||
if (res && res.needAuthorization) {
|
||
wxAny.requirePrivacyAuthorize({success: () => resolve(), fail: () => resolve()})
|
||
} else {
|
||
resolve()
|
||
}
|
||
},
|
||
fail: () => resolve(),
|
||
})
|
||
} else {
|
||
wxAny.requirePrivacyAuthorize({success: () => resolve(), fail: () => resolve()})
|
||
}
|
||
})
|
||
}
|
||
|
||
/** 预检并申请定位权限;已拒绝则引导去设置,返回最终是否拥有权限 */
|
||
const ensureLocationPermission = async (): Promise<boolean> => {
|
||
try {
|
||
const setting: any = await Taro.getSetting()
|
||
const auth = setting?.authSetting?.['scope.userLocation']
|
||
if (auth === true) return true
|
||
if (auth === false) {
|
||
const modal = await Taro.showModal({
|
||
title: '需要定位权限',
|
||
content: '选择定位需要开启定位权限,请在设置中开启后重试。',
|
||
confirmText: '去设置',
|
||
})
|
||
if (modal.confirm) {
|
||
await Taro.openSetting()
|
||
const setting2: any = await Taro.getSetting()
|
||
return setting2?.authSetting?.['scope.userLocation'] === true
|
||
}
|
||
return false
|
||
}
|
||
try {
|
||
await Taro.authorize({scope: 'scope.userLocation'})
|
||
return true
|
||
} catch {
|
||
const modal = await Taro.showModal({
|
||
title: '需要定位权限',
|
||
content: '选择定位需要开启定位权限,请在设置中开启后重试。',
|
||
confirmText: '去设置',
|
||
})
|
||
if (modal.confirm) {
|
||
await Taro.openSetting()
|
||
const setting2: any = await Taro.getSetting()
|
||
return setting2?.authSetting?.['scope.userLocation'] === true
|
||
}
|
||
return false
|
||
}
|
||
} catch {
|
||
return false
|
||
}
|
||
}
|
||
|
||
const AddressEditPage: React.FC = () => {
|
||
const {id, fromWx} = useRouter().params
|
||
const isEditMode = !!id
|
||
const addressId = id ? Number(id) : undefined
|
||
const fromWxMode = fromWx === '1' || fromWx === 'true'
|
||
|
||
const [loading, setLoading] = useState(true)
|
||
const [formData, setFormData] = useState<Partial<ShopUserAddress>>({
|
||
name: '',
|
||
phone: '',
|
||
province: '',
|
||
city: '',
|
||
region: '',
|
||
address: '',
|
||
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 wxDraftRef = useRef<Partial<ShopUserAddress> | null>(null)
|
||
const wxDraftPatchedRef = useRef(false)
|
||
|
||
/** 解析省市区 */
|
||
const parseRegion = (text: string) => {
|
||
for (const province of RegionData as any[]) {
|
||
if (text.includes(province.label)) {
|
||
const result: any = {province: province.label}
|
||
if (province.children) {
|
||
for (const city of province.children) {
|
||
if (text.includes(city.label)) {
|
||
result.city = city.label
|
||
if (city.children) {
|
||
for (const region of city.children) {
|
||
if (text.includes(region.label)) {
|
||
result.region = region.label
|
||
return result
|
||
}
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
}
|
||
return null
|
||
}
|
||
|
||
/** 解析地址文本(智能识别) */
|
||
const parseAddressText = (text: string) => {
|
||
const result: any = {}
|
||
|
||
// 手机号正则
|
||
const phoneRegex = /1[3-9]\d{9}/
|
||
const phoneMatch = text.match(phoneRegex)
|
||
if (phoneMatch) result.phone = phoneMatch[0]
|
||
|
||
// 姓名正则(2-4个中文字符,通常在开头)
|
||
const nameRegex = /^[\u4e00-\u9fa5]{2,4}/
|
||
const nameMatch = text.match(nameRegex)
|
||
if (nameMatch) result.name = nameMatch[0]
|
||
|
||
// 省市区识别
|
||
const regionResult = parseRegion(text)
|
||
if (regionResult) {
|
||
result.province = regionResult.province
|
||
result.city = regionResult.city
|
||
result.region = regionResult.region
|
||
}
|
||
|
||
// 详细地址提取
|
||
let addressText = text
|
||
if (result.name) addressText = addressText.replace(result.name, '')
|
||
if (result.phone) addressText = addressText.replace(result.phone, '')
|
||
if (result.province) addressText = addressText.replace(result.province, '')
|
||
if (result.city) addressText = addressText.replace(result.city, '')
|
||
if (result.region) addressText = addressText.replace(result.region, '')
|
||
result.address = addressText.replace(/[,,。\s]+/g, '').trim()
|
||
|
||
return result
|
||
}
|
||
|
||
/** 地址智能识别 */
|
||
const recognizeAddress = () => {
|
||
if (!inputText.trim()) {
|
||
Taro.showToast({title: '请输入要识别的文本', icon: 'none'})
|
||
return
|
||
}
|
||
|
||
try {
|
||
const result = parseAddressText(inputText)
|
||
const newFormData: any = {
|
||
...formData,
|
||
name: result.name || formData.name,
|
||
phone: result.phone || formData.phone,
|
||
address: result.address || formData.address,
|
||
}
|
||
|
||
if (!regionLocked) {
|
||
newFormData.province = result.province || formData.province
|
||
newFormData.city = result.city || formData.city
|
||
newFormData.region = result.region || formData.region
|
||
}
|
||
|
||
setFormData(newFormData)
|
||
|
||
if (!regionLocked && result.province && result.city && result.region) {
|
||
setRegionText(`${result.province} ${result.city} ${result.region}`)
|
||
}
|
||
|
||
Taro.showToast({title: regionLocked ? '识别成功(所在地区以定位为准)' : '识别成功', icon: 'success'})
|
||
setInputText('')
|
||
} catch {
|
||
Taro.showToast({title: '识别失败,请检查文本格式', icon: 'none'})
|
||
}
|
||
}
|
||
|
||
/** 将地图选点结果应用到表单 */
|
||
const applyChosenLocation = (res: any) => {
|
||
if (!res) return
|
||
if (res.latitude === undefined || res.longitude === undefined) {
|
||
Taro.showToast({title: '定位信息获取失败', icon: 'none'})
|
||
return
|
||
}
|
||
|
||
const next: SelectedLocation = {
|
||
lng: String(res.longitude),
|
||
lat: String(res.latitude),
|
||
name: res.name,
|
||
address: res.address,
|
||
}
|
||
|
||
// 尝试从地图返回的地址文本解析省市区
|
||
const regionResult = res?.provinceName || res?.cityName || res?.adName
|
||
? {
|
||
province: String(res.provinceName || ''),
|
||
city: String(res.cityName || ''),
|
||
region: String(res.adName || '')
|
||
}
|
||
: parseRegion(String(res.address || ''))
|
||
|
||
const province = String(regionResult?.province || '').trim()
|
||
const city = String(regionResult?.city || '').trim()
|
||
const region = String(regionResult?.region || '').trim()
|
||
if (!province || !city || !region) {
|
||
Taro.showToast({title: '定位未识别到所在地区,请重新选择定位', icon: 'none'})
|
||
return
|
||
}
|
||
|
||
setSelectedLocation(next)
|
||
setRegionLocked(true)
|
||
|
||
// 将地图选点的地址同步到"收货地址"(剥离省市区,避免重复)
|
||
const rawAddr = String(res.address || '').trim()
|
||
const name = String(res.name || '').trim()
|
||
let detail = rawAddr
|
||
for (const part of [province, city, region]) {
|
||
if (part) detail = detail.replace(part, '')
|
||
}
|
||
detail = detail.replace(/[,,]+/g, ' ').replace(/\s+/g, ' ').trim()
|
||
const base = detail || rawAddr
|
||
const nextDetailAddress = (() => {
|
||
if (!base && !name) return ''
|
||
if (!base) return name
|
||
if (!name) return base
|
||
return base.includes(name) ? base : `${base} ${name}`
|
||
})()
|
||
|
||
setFormData(prev => ({
|
||
...prev,
|
||
lng: next.lng,
|
||
lat: next.lat,
|
||
address: nextDetailAddress || prev.address,
|
||
province,
|
||
city,
|
||
region,
|
||
}))
|
||
setRegionText(`${province} ${city} ${region}`)
|
||
}
|
||
|
||
/** 选择定位 */
|
||
const chooseGeoLocation = async () => {
|
||
try {
|
||
// 1. 微信隐私授权(新版基础库强制,未同意会直接拒绝定位接口)
|
||
await ensurePrivacyAuthorized()
|
||
|
||
// 2. 定位权限预检 / 申请
|
||
const granted = await ensureLocationPermission()
|
||
if (!granted) {
|
||
Taro.showToast({title: '未获得定位权限,请在下方手动选择所在地区', icon: 'none'})
|
||
return
|
||
}
|
||
|
||
// 3. 仅在有有效经纬度时传入初始化参数,避免 undefined 触发部分机型失败
|
||
const initLat = selectedLocation?.lat ? Number(selectedLocation.lat) : undefined
|
||
const initLng = selectedLocation?.lng ? Number(selectedLocation.lng) : undefined
|
||
const latitude = typeof initLat === 'number' && Number.isFinite(initLat) ? initLat : undefined
|
||
const longitude = typeof initLng === 'number' && Number.isFinite(initLng) ? initLng : undefined
|
||
const params: any = {}
|
||
if (typeof latitude === 'number') params.latitude = latitude
|
||
if (typeof longitude === 'number') params.longitude = longitude
|
||
|
||
const res = await Taro.chooseLocation(params)
|
||
applyChosenLocation(res)
|
||
} catch (e: any) {
|
||
if (isUserCancel(e)) return
|
||
// 4. 地图失败兜底:原生 Picker 无法用代码调起,提示用户去下方手动选择所在地区;
|
||
// 同时提供"重试"可再次尝试地图定位
|
||
Taro.showModal({
|
||
title: '地图打开失败',
|
||
content: '无法调起地图定位,您可以在下方手动选择所在地区并填写详细地址,或稍后重试。',
|
||
confirmText: '重试',
|
||
cancelText: '手动填写',
|
||
}).then((modal) => {
|
||
if (modal.confirm) {
|
||
Taro.chooseLocation({})
|
||
.then((res: any) => applyChosenLocation(res))
|
||
.catch(() => {
|
||
Taro.showToast({title: '仍无法打开地图,请手动选择所在地区', icon: 'none'})
|
||
})
|
||
} else {
|
||
Taro.showToast({title: '请在下方手动选择所在地区', icon: 'none'})
|
||
}
|
||
}).catch(() => {
|
||
Taro.showToast({title: '请在下方手动选择所在地区', icon: 'none'})
|
||
})
|
||
}
|
||
}
|
||
|
||
/** 地区选择器确认(微信原生 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(`${province} ${city} ${region}`)
|
||
// 用户手动修改了所在地区,解除"由地图定位锁定"状态,后续可继续手动调整
|
||
setRegionLocked(false)
|
||
}
|
||
|
||
/** 保存地址 */
|
||
const handleSave = async () => {
|
||
// 表单校验
|
||
if (!formData.name?.trim()) {
|
||
Taro.showToast({title: '请输入收货人姓名', icon: 'none'})
|
||
return
|
||
}
|
||
if (!formData.phone?.trim()) {
|
||
Taro.showToast({title: '请输入手机号', icon: 'none'})
|
||
return
|
||
}
|
||
if (!/^1[3-9]\d{9}$/.test(formData.phone)) {
|
||
Taro.showToast({title: '手机号格式不正确', icon: 'none'})
|
||
return
|
||
}
|
||
if (!formData.province || !formData.city || !formData.region) {
|
||
Taro.showToast({title: '请选择所在地区', icon: 'none'})
|
||
return
|
||
}
|
||
if (!formData.address?.trim()) {
|
||
Taro.showToast({title: '请输入详细地址', icon: 'none'})
|
||
return
|
||
}
|
||
|
||
// 经纬度检查(可选,不阻断保存流程)
|
||
const loc = selectedLocation || (hasValidLngLat(formData) ? {
|
||
lng: String(formData.lng),
|
||
lat: String(formData.lat)
|
||
} : null)
|
||
|
||
try {
|
||
const submitData: any = {
|
||
name: formData.name,
|
||
phone: formData.phone,
|
||
country: formData.country || '中国',
|
||
province: formData.province,
|
||
city: formData.city,
|
||
region: formData.region,
|
||
address: formData.address,
|
||
isDefault: formData.isDefault ?? true,
|
||
...(loc ? {lng: loc.lng, lat: loc.lat} : {}),
|
||
}
|
||
|
||
if (isEditMode && addressId) {
|
||
submitData.id = addressId
|
||
}
|
||
|
||
// 执行新增或更新
|
||
if (isEditMode) {
|
||
await updateShopUserAddress(submitData)
|
||
} else {
|
||
await addShopUserAddress(submitData)
|
||
}
|
||
|
||
Taro.showToast({title: `${isEditMode ? '更新' : '保存'}成功`, icon: 'success'})
|
||
setTimeout(() => Taro.navigateBack(), 1000)
|
||
} catch (error) {
|
||
console.error('保存失败:', error)
|
||
Taro.showToast({title: `${isEditMode ? '更新' : '保存'}失败`, icon: 'none'})
|
||
}
|
||
}
|
||
|
||
const updateField = (field: string, value: any) => {
|
||
setFormData(prev => ({...prev, [field]: value}))
|
||
}
|
||
|
||
/** 初始化加载 */
|
||
useEffect(() => {
|
||
const init = async () => {
|
||
// 动态设置页面标题
|
||
Taro.setNavigationBarTitle({
|
||
title: isEditMode ? '编辑收货地址' : (fromWxMode ? '完善收货地址' : '新增收货地址'),
|
||
})
|
||
|
||
// 微信地址导入
|
||
if (!isEditMode && fromWxMode && !wxDraftPatchedRef.current) {
|
||
try {
|
||
const draft = Taro.getStorageSync('WxAddressDraft')
|
||
if (draft) {
|
||
wxDraftPatchedRef.current = true
|
||
wxDraftRef.current = draft as any
|
||
Taro.removeStorageSync('WxAddressDraft')
|
||
setFormData(prev => ({...prev, ...(draft as any)}))
|
||
const p = String((draft as any)?.province || '').trim()
|
||
const c = String((draft as any)?.city || '').trim()
|
||
const r = String((draft as any)?.region || '').trim()
|
||
const rText = [p, c, r].filter(Boolean).join(' ')
|
||
if (rText) setRegionText(rText)
|
||
}
|
||
} catch (_e) { /* ignore */
|
||
}
|
||
}
|
||
|
||
// 编辑模式:加载已有地址数据
|
||
if (isEditMode && addressId) {
|
||
try {
|
||
const addr = await getShopUserAddress(addressId)
|
||
setFormData(addr)
|
||
setRegionText(`${addr.province || ''} ${addr.city || ''} ${addr.region || ''}`)
|
||
if (hasValidLngLat(addr)) {
|
||
setSelectedLocation({lng: String(addr.lng), lat: String(addr.lat)})
|
||
setRegionLocked(true)
|
||
}
|
||
} catch (error) {
|
||
console.error('加载地址失败:', error)
|
||
Taro.showToast({title: '加载地址失败', icon: 'none'})
|
||
}
|
||
}
|
||
|
||
setLoading(false)
|
||
}
|
||
|
||
init()
|
||
}, [])
|
||
|
||
if (loading) {
|
||
return (
|
||
<View className="flex items-center justify-center min-h-screen">
|
||
<Text className="text-gray-400 text-sm">加载中...</Text>
|
||
</View>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<View className="min-h-screen bg-gray-50 flex flex-col">
|
||
<ScrollView scrollY className="flex-1">
|
||
{/* 地址智能识别区 */}
|
||
<View className="bg-white px-3 pt-3 pb-2">
|
||
<View
|
||
className="rounded-lg p-2"
|
||
style={{border: '1px dashed #0e932e'}}
|
||
>
|
||
<Textarea
|
||
style={{height: '80px', width: '100%', fontSize: '13px'}}
|
||
value={inputText}
|
||
onInput={e => setInputText(e.detail.value)}
|
||
placeholder="粘贴文本,点击「识别」自动识别收货人、地址、电话"
|
||
maxlength={200}
|
||
/>
|
||
<View className="flex justify-end mt-2">
|
||
<View
|
||
style={{
|
||
backgroundColor: '#0e932e',
|
||
borderRadius: '12px',
|
||
paddingLeft: '12px',
|
||
paddingRight: '12px',
|
||
paddingTop: '4px',
|
||
paddingBottom: '4px'
|
||
}}
|
||
onClick={recognizeAddress}
|
||
>
|
||
<Text className="text-white text-xs">识别</Text>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
|
||
<View className="bg-gray-100" style={{height: '8px'}}/>
|
||
|
||
{/* 选择定位 */}
|
||
<View className="bg-white px-4 mb-2">
|
||
<View className="flex items-center py-3" onClick={chooseGeoLocation}>
|
||
<View className="flex-1">
|
||
<View className="flex items-center gap-1 mb-1">
|
||
<Text className="text-sm text-gray-700">选择定位</Text>
|
||
<Text className="text-gray-300" style={{fontSize: '10px'}}>(推荐)</Text>
|
||
</View>
|
||
<Text className="text-xs text-gray-400">
|
||
{selectedLocation?.address || (selectedLocation ? `经度:${selectedLocation.lng}, 纬度:${selectedLocation.lat}` : '用于判断是否超出配送范围')}
|
||
</Text>
|
||
{selectedLocation?.name && (
|
||
<Text className="text-xs text-green-600 mt-1">{selectedLocation.name}</Text>
|
||
)}
|
||
</View>
|
||
<Text className="text-gray-300 text-xs">▶</Text>
|
||
</View>
|
||
</View>
|
||
|
||
{/* 表单区 */}
|
||
<View className="bg-white px-4 py-2">
|
||
|
||
{/* 所在地区(微信原生地区选择器,地图不可用时也可手动选择) */}
|
||
<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'}`}>
|
||
{regionText || '请选择省市区'}
|
||
</Text>
|
||
<Text className="text-gray-300 text-xs">▶</Text>
|
||
</View>
|
||
</View>
|
||
</Picker>
|
||
|
||
{/* 详细地址 */}
|
||
<View className="flex items-center py-3 border-b border-gray-50">
|
||
<Text className="text-sm text-gray-700" style={{minWidth: '60px'}}>详细地址</Text>
|
||
<Input
|
||
className="flex-1 text-sm"
|
||
placeholder="请输入详细收货地址"
|
||
maxLength={50}
|
||
value={formData.address || ''}
|
||
onInput={e => updateField('address', e.detail.value)}
|
||
/>
|
||
</View>
|
||
|
||
{/* 收货人 */}
|
||
<View className="flex items-center py-3 border-b border-gray-50">
|
||
<Text className="text-sm text-gray-700" style={{minWidth: '60px'}}>收货人</Text>
|
||
<Input
|
||
className="flex-1 text-sm"
|
||
placeholder="请输入收货人姓名"
|
||
maxLength={10}
|
||
value={formData.name || ''}
|
||
onInput={e => updateField('name', e.detail.value)}
|
||
/>
|
||
</View>
|
||
|
||
{/* 手机号 */}
|
||
<View className="flex items-center py-3 border-b border-gray-50">
|
||
<Text className="text-sm text-gray-700" style={{minWidth: '60px'}}>手机号</Text>
|
||
<Input
|
||
className="flex-1 text-sm"
|
||
placeholder="请输入手机号"
|
||
type="number"
|
||
maxlength={11}
|
||
value={formData.phone || ''}
|
||
onInput={e => updateField('phone', e.detail.value)}
|
||
/>
|
||
</View>
|
||
|
||
</View>
|
||
|
||
{/* 默认地址开关 */}
|
||
<View className="bg-white px-4 mt-2">
|
||
<View className="flex items-center justify-between py-3">
|
||
<Text className="text-sm text-gray-700">设为默认地址</Text>
|
||
<View
|
||
className={`rounded-full relative ${formData.isDefault ? 'bg-green-500' : 'bg-gray-300'}`}
|
||
style={{width: '40px', height: '22px'}}
|
||
onClick={() => updateField('isDefault', !formData.isDefault)}
|
||
>
|
||
<View
|
||
className={`absolute top-1 rounded-full bg-white ${formData.isDefault ? 'right-1' : 'left-1'}`}
|
||
style={{width: '16px', height: '16px'}}
|
||
/>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
|
||
{/* 底部占位 */}
|
||
<View style={{height: '100px'}}/>
|
||
</ScrollView>
|
||
|
||
{/* 底部保存按钮 - 使用 flex 布局而非 fixed */}
|
||
<View className="bg-white border-t border-gray-200 px-4 py-3" style={{paddingBottom: '20px'}}>
|
||
<View
|
||
className="py-3 rounded-full text-center"
|
||
style={{backgroundColor: '#0e932e'}}
|
||
onClick={handleSave}
|
||
>
|
||
<Text className="text-white font-medium text-sm">{isEditMode ? '更新地址' : '保存并使用'}</Text>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
)
|
||
}
|
||
|
||
export default AddressEditPage
|