import { useEffect, useState } from 'react'; import { View, Text, Input, Textarea, Switch } from '@tarojs/components'; import Taro, { useRouter } from '@tarojs/taro'; import PageShell from '../../components/PageShell'; import SubPageHeader from '../../components/SubPageHeader'; import RegionPicker from '../../components/RegionPicker'; import { buildAddressListUrl, readCheckoutContext } from '../../lib/checkout-nav'; import { DEFAULT_REGION, REGION_ALL, formatRegion, type RegionSelection, } from '../../lib/region-data'; import { normalizePhoneInput, validateMobilePhone } from '../../lib/phone'; import { getStoredUserPhone, resolveDefaultUserPhone } from '../../lib/user-phone'; import { resolveUserCity } from '../../lib/user-location'; import { request, toast, type UserProfile } from '../../lib/api'; type AddressForm = { receiverName: string; phone: string; province: string; city: string; district: string; detail: string; isDefault: boolean; }; export default function AddressEditPage() { const router = useRouter(); const id = router.params.id; const isEdit = !!id; const checkoutCtx = readCheckoutContext(router.params); const [pickerOpen, setPickerOpen] = useState(false); const [saving, setSaving] = useState(false); const [locating, setLocating] = useState(false); const [error, setError] = useState(''); const [form, setForm] = useState(() => ({ receiverName: '', phone: id ? '' : getStoredUserPhone(), province: DEFAULT_REGION.province, city: DEFAULT_REGION.city, district: DEFAULT_REGION.district, detail: '', isDefault: true, })); useEffect(() => { if (id) return; request('/auth/me') .then((me) => { const phone = resolveDefaultUserPhone(me); if (!phone) return; setForm((prev) => (prev.phone ? prev : { ...prev, phone })); }) .catch(() => {}); }, [id]); useEffect(() => { if (id) return; let cancelled = false; setLocating(true); void resolveUserCity(true) .then((resolved) => { if (cancelled) return; const district = resolved.region.district && resolved.region.district !== REGION_ALL ? resolved.region.district : resolved.district && resolved.district !== REGION_ALL ? resolved.district : DEFAULT_REGION.district; setForm((prev) => ({ ...prev, province: resolved.region.province || prev.province, city: resolved.region.city || prev.city, district: district || prev.district, })); }) .catch(() => {}) .finally(() => { if (!cancelled) setLocating(false); }); return () => { cancelled = true; }; }, [id]); useEffect(() => { if (!id) return; request>>('/user/addresses').then((list) => { const found = list.find((a) => String(a.id) === id); if (found) { setForm({ receiverName: String(found.receiverName ?? ''), phone: String(found.phone ?? ''), province: String(found.province ?? DEFAULT_REGION.province), city: String(found.city ?? DEFAULT_REGION.city), district: String(found.district ?? DEFAULT_REGION.district), detail: String(found.detail ?? ''), isDefault: found.isDefault === 1 || found.isDefault === true, }); } }).catch(() => {}); }, [id]); const regionText = formatRegion(form.province, form.city, form.district); function validateForm(): string | null { if (!form.receiverName.trim()) return '请输入收货人姓名'; const phoneCheck = validateMobilePhone(form.phone); if (!phoneCheck.ok) return phoneCheck.message ?? '请输入正确的手机号码'; if (!form.province || !form.city || !form.district) return '请选择所在地区'; if (!form.detail.trim()) return '请输入详细地址'; return null; } async function save() { const validationError = validateForm(); if (validationError) { setError(validationError); toast(validationError); return; } setSaving(true); setError(''); try { const payload = { receiverName: form.receiverName.trim(), phone: form.phone.trim(), province: form.province, city: form.city, district: form.district, detail: form.detail.trim(), isDefault: form.isDefault, }; if (isEdit && id) { await request(`/user/addresses/${id}`, { method: 'PUT', data: payload }); toast('地址已更新', 'success'); } else { await request('/user/addresses', { method: 'POST', data: payload }); toast('地址已新增', 'success'); } setTimeout(() => { Taro.redirectTo({ url: buildAddressListUrl(checkoutCtx) }).catch(() => { Taro.navigateBack(); }); }, 400); } catch (e) { const msg = e instanceof Error ? e.message : '保存失败'; setError(msg); toast(msg); } finally { setSaving(false); } } function onRegionConfirm(region: RegionSelection) { setForm((prev) => ({ ...prev, province: region.province, city: region.city, district: region.district, })); } return ( 收货人 setForm((prev) => ({ ...prev, receiverName: e.detail.value }))} /> 手机号 setForm((prev) => ({ ...prev, phone: normalizePhoneInput(e.detail.value) })) } /> 所在地区 setPickerOpen(true)} > {locating && !isEdit ? '定位中…' : regionText || '请选择省市区'} 详细地址 {process.env.TARO_ENV === 'h5' ? (