286 lines
7.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="wrap">
<view class="form-item">
<text class="label">姓名</text>
<input class="input" v-model="name" placeholder="请输入姓名" />
</view>
<view class="form-item">
<text class="label">手机号</text>
<input class="input" v-model="mobile" placeholder="请输入手机号" />
</view>
<view class="form-item region-picker" @click="openRegionPicker">
<text class="label">省市区</text>
<picker
mode="region"
:value="regionValue"
@change="onRegionChange"
@cancel="onRegionCancel"
>
<view class="picker-value" :class="{ placeholder: !hasRegion }">
{{ hasRegion ? `${province} ${city} ${district}` : '请选择省市区' }}
<text class="arrow-icon"></text>
</view>
</picker>
</view>
<view class="form-item">
<text class="label">详细地址</text>
<input class="input" v-model="detail" placeholder="请输入详细地址" />
</view>
<view class="form-item">
<text class="label">设为默认</text>
<switch :checked="isDefault" @change="e => isDefault = e.detail.value" />
</view>
<button class="submit" :disabled="loading" @click="onSubmit">保存</button>
<view v-if="error" class="error">{{ error }}</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { addAddress, updateAddress, listAddresses, setDefaultAddress } from '../../api/appUser'
const id = ref('')
const name = ref('')
const mobile = ref('')
const province = ref('')
const city = ref('')
const district = ref('')
const detail = ref('')
let isDefault = false
const loading = ref(false)
const error = ref('')
// 省市区选择器
const regionValue = computed(() => [province.value, city.value, district.value])
const hasRegion = computed(() => province.value && city.value && district.value)
function onRegionChange(e) {
const values = e.detail.value
province.value = values[0] || ''
city.value = values[1] || ''
district.value = values[2] || ''
}
function onRegionCancel() {
// picker 取消时不做处理
}
function openRegionPicker() {
// 点击整行时触发 picker
}
function fill(data) {
name.value = data.name || data.realname || ''
mobile.value = data.mobile || data.phone || ''
province.value = data.province || ''
city.value = data.city || ''
district.value = data.district || ''
detail.value = data.address || data.detail || ''
isDefault = !!data.is_default
}
async function init(idParam) {
if (!idParam) {
const data = uni.getStorageSync('edit_address') || {}
if (data && data.id) fill(data)
return
}
const user_id = uni.getStorageSync('user_id')
try {
const list = await listAddresses(user_id)
const arr = Array.isArray(list) ? list : (list && (list.list || list.items)) || []
const found = arr.find(a => String(a.id) === String(idParam))
if (found) fill(found)
} catch (e) {}
}
async function onSubmit() {
const user_id = uni.getStorageSync('user_id')
if (!name.value || !mobile.value || !province.value || !city.value || !district.value || !detail.value) {
uni.showToast({ title: '请完善必填信息', icon: 'none' })
return
}
loading.value = true
error.value = ''
const payload = {
name: name.value,
mobile: mobile.value,
province: province.value,
city: city.value,
district: district.value,
address: detail.value,
is_default: isDefault
}
try {
let savedId = id.value
if (id.value) {
await updateAddress(user_id, id.value, payload)
savedId = id.value
} else {
try {
const res = await addAddress(user_id, payload)
savedId = (res && (res.id || res.address_id)) || ''
} catch (eAdd) {
const sc = eAdd && eAdd.statusCode
const bc = (eAdd && eAdd.data && (eAdd.data.code || eAdd.code)) || undefined
const msg = eAdd && (eAdd.message || eAdd.errMsg || '')
const isUniqueErr = sc === 400 && (bc === 10011 || (msg && msg.toLowerCase().includes('unique')))
if (isUniqueErr) {
try {
const list = await listAddresses(user_id)
const arr = Array.isArray(list) ? list : (list && (list.list || list.items)) || []
const found = arr.find(a => (a.mobile === mobile.value || a.phone === mobile.value) && (a.address === detail.value || a.detail === detail.value) && (a.city === city.value) && (a.district === district.value) && (a.province === province.value))
if (found) {
savedId = found.id
await updateAddress(user_id, savedId, payload)
}
} catch (_) {}
} else {
throw eAdd
}
}
}
if (isDefault) {
if (!savedId) {
try {
const list = await listAddresses(user_id)
const arr = Array.isArray(list) ? list : (list && (list.list || list.items)) || []
const found = arr.find(a => (a.mobile === mobile.value || a.phone === mobile.value) && (a.address === detail.value || a.detail === detail.value))
if (found) savedId = found.id
} catch (_) {}
}
if (savedId) {
await setDefaultAddress(user_id, savedId)
}
}
uni.showToast({ title: '保存成功', icon: 'success' })
uni.navigateBack()
} catch (e) {
error.value = e && (e.message || e.errMsg) || '保存失败'
} finally {
loading.value = false
}
}
onLoad((opts) => {
id.value = (opts && opts.id) || ''
init(id.value)
})
</script>
<style lang="scss" scoped>
/* ============================================
柯大鸭潮玩 - 地址编辑页面
采用暖橙色调的表单设计
============================================ */
.wrap {
padding: $spacing-lg;
min-height: 100vh;
background: $bg-page;
}
/* 表单项 */
.form-item {
display: flex;
align-items: center;
background: #FFFFFF;
border-radius: $radius-lg;
padding: $spacing-lg $spacing-xl;
margin-bottom: $spacing-md;
box-shadow: $shadow-sm;
transition: all 0.2s;
&:focus-within {
box-shadow: $shadow-md;
transform: translateY(-2rpx);
}
}
.label {
width: 160rpx;
font-size: $font-md;
font-weight: 600;
color: $text-main;
flex-shrink: 0;
}
.input {
flex: 1;
font-size: $font-md;
color: $text-main;
background: transparent;
height: 48rpx;
}
/* 省市区选择器 */
.region-picker {
cursor: pointer;
picker {
flex: 1;
}
}
.picker-value {
display: flex;
align-items: center;
justify-content: space-between;
font-size: $font-md;
color: $text-main;
height: 48rpx;
line-height: 48rpx;
&.placeholder {
color: $text-tertiary;
}
}
.arrow-icon {
font-size: 36rpx;
color: $text-tertiary;
margin-left: 12rpx;
transform: rotate(0deg);
transition: transform 0.2s;
}
/* 提交按钮 */
.submit {
width: 100%;
height: 96rpx;
line-height: 96rpx;
margin-top: 60rpx;
background: $gradient-brand !important;
color: #FFFFFF !important;
border-radius: $radius-round;
font-size: $font-lg;
font-weight: 800;
border: none;
box-shadow: $shadow-warm;
transition: all 0.2s ease;
&:active {
transform: scale(0.96);
box-shadow: none;
}
&[disabled] {
opacity: 0.6;
box-shadow: none;
background: $text-disabled !important;
}
}
/* 错误提示 */
.error {
color: $color-error;
font-size: $font-sm;
margin-top: $spacing-lg;
padding: $spacing-md;
background: rgba($color-error, 0.1);
border-radius: $radius-md;
text-align: center;
font-weight: 500;
}
</style>