<template> <view class=""> <view class="card"> <up-form labelPosition="left" :model="formData" :rules="rules" ref="uForm" labelWidth="100"> <up-form-item label="联系人" prop="real_name" borderBottom> <up-input v-model="formData.real_name" disabledColor="#ffffff" border="none" placeholder="请填写联系人姓名"></up-input> </up-form-item> <up-form-item label="联系电话" prop="phone" borderBottom> <up-input v-model="formData.phone" disabledColor="#ffffff" type="number" placeholder="请填写联系电话" border="none"></up-input> </up-form-item> <up-form-item label="所在位置" prop="address" borderBottom> <view @click="showPop = true" style="width: 100%;"> <up-input style="pointer-events: none" v-model="formData.address" border="none" prefixIcon="map" readonly placeholder="点击选择地址" :customStyle="{ background: '#F3F3F3', padding: '20rpx', 'border-radius': '30rpx' }" :placeholderStyle="{ color: '#444444' }" :prefixIconStyle="{ 'margin-right': '40rpx' }" suffixIcon='arrow-down'></up-input> </view> </up-form-item> <!-- <up-form-item label="详细地址" prop="detail" borderBottom> <up-input v-model="formData.detail" disabledColor="#ffffff" placeholder="请填写详细地址" border="none"></up-input> </up-form-item> --> </up-form> </view> <!-- <view class="card"> <view class="is-default"> <view>设置为默认地址</view> <up-switch v-model="formData.is_default" :activeValue="1" :inactiveValue="0" activeColor="#20B128"></up-switch> </view> </view> --> <view class="bottom-fixed"> <up-button color="#20B128" shape="circle" @click="submit">保存</up-button> </view> <!-- 地址选择器 --> <up-popup :show="showPop" @close="showPop = false" @open="showPop = true" :round="10"> <view style="padding: 20rpx;"> <up-tabs :list="tabsList" @change='addressTbasChange' :current='currentAddressIndex' lineColor='#20B128' :activeStyle="{ color: '#20B128' }"></up-tabs> <up-line style="margin-top:20rpx "></up-line> <view class="address-content" v-if='currentAddressIndex == 0'> <view class="address-li" :class='{ act: item.city_code == formData.city }' v-for="item in addressList.city" :key="item.city_code" @click="addressLiClick(0, item)"> <text>{{ item.city_name }}</text> <up-icon name="arrow-right" :color="item.city_code == formData.city ? '#20B128' : '#777777'" /> </view> </view> <view class="address-content" v-else-if='currentAddressIndex == 1'> <view class="address-li" v-for="item in addressList.area" @click="addressLiClick(1, item)" :key="item.area_code" :class='{ act: item.area_code == formData.area }'> <text>{{ item.area_name }}</text> <up-icon name="arrow-right" :color="item.area_code == formData.area ? '#20B128' : '#777777'" /> </view> </view> <view class="address-content" v-else-if='currentAddressIndex == 2'> <view class="address-li" v-for="item in addressList.street" @click="addressLiClick(2, item)" :key="item.street_code" :class='{ act: item.street_code == formData.street }'> <text>{{ item.street_name }}</text> <up-icon name="arrow-right" :color="item.street_code == formData.street ? '#20B128' : '#777777'" /> </view> </view> <view class="address-content" v-else-if='currentAddressIndex == 3'> <view class="address-li" v-for="item in addressList.village" @click="addressLiClick(3, item)" :key="item.village_code" :class='{ act: item.village_code == formData.village }'> <text>{{ item.village_name }}</text> <up-icon name="arrow-right" :color="item.village_code == formData.village ? '#20B128' : '#777777'" /> </view> </view> <view class="address-content" v-else-if='currentAddressIndex == 4'> <view class="address-li" :class='{ act: item.id == formData.brigade }' v-for="item in addressList.brigade" :key="item.id" @click="addressLiClick(4, item)"> <text>{{ item.brigade_name }}</text> <up-icon name="arrow-right" :color="item.id == formData.brigade ? '#20B128' : '#777777'" /> </view> </view> </view> </up-popup> </view> </template> <script setup> import { onLoad } from "@dcloudio/uni-app" import { reactive, ref } from "vue" import { addressCreateApi, addressEditApi, addressDetailApi } from "@/api/user.js" import { provinceListApi, cityListApi, areaListApi, streetListApi, villageListApi, brigadeListApi } from "@/api/address.js" import useUserStore from "@/store/user"; const mode = ref('add'); const type = ref(''); const showAddressPop = ref(false) const formData = ref({ real_name: '', phone: '', detail: '', is_default: 1, province: 510000, city: '', area: "", street: "", village: "", brigade: "", address: "" }) const userInfo = useUserStore().userInfo; if (userInfo) { formData.value.phone = userInfo.mobile formData.value.real_name = userInfo.real_name } const rules = ref({ real_name: [{ required: true, message: '请输入姓名', trigger: ['blur'] }], phone: [{ required: true, message: '请输入手机号', trigger: ['blur'] }, { validator: (rule, value, callback) => { return uni.$u.test.mobile(value); }, message: '手机号码不正确', trigger: ['change', 'blur'], }], detail: [{ required: true, message: '请输入地址', trigger: ['blur'] }] }) const uForm = ref(null); const submit = () => { uForm.value.validate().then(() => { if (mode.value == 'add') { addressCreateApi(formData.value).then(res => { uni.$u.toast(res.msg); uni.$u.sleep(800).then(res => { if (type.value == 'settle') { uni.redirectTo({ url: '/pagesOrder/settle/settle' }); } else { uni.navigateBack(); } }) }) } else { addressEditApi(formData.value).then(res => { uni.$u.toast(res.msg); uni.$u.sleep(800).then(res => { if (type.value == 'settle') { uni.redirectTo({ url: '/pagesOrder/settle/settle' }); } else { uni.navigateBack(); } }) }) } }).catch(() => { console.log('验证失败'); }) } const getAddressDetil = (address_id) => { addressDetailApi({ address_id }).then(res => { formData.value = res.data; }) } // 地址选择 const showPop = ref(false) const currentAddressIndex = ref(0) const currentAddressList = () => { if (!formData.city) return [0, 'city']; else if (formData.area) return [1, 'area']; else if (formData.street) return [2, 'street']; else if (formData.village) return [3, 'village']; else if (formData.brigade) return [4, 'brigade']; } const addressTbasChange = (e) => { currentAddressIndex.value = e.index } const addressList = reactive({ city: [], area: [], street: [], village: [], brigade: [] }) const addressLiClick = async (i, item) => { if (i == 0) { formData.value.city = item.city_code tabsList[0].name = item.city_name let res = await areaListApi({ city_code: formData.value.city }) addressList.area = res.data } if (i == 1) { formData.value.area = item.area_code tabsList[1].name = item.area_name let res = await streetListApi({ area_code: formData.value.area }) addressList.street = res.data } if (i == 2) { formData.value.street = item.street_code tabsList[2].name = item.street_name let res = await villageListApi({ street_code: formData.value.street }) addressList.village = res.data } if (i == 3) { formData.value.village = item.village_code tabsList[3].name = item.village_name let res = await brigadeListApi({ village_code: formData.value.village }) addressList.brigade = res.data } if (i == 4) { formData.value.brigade = item.id tabsList[4].name = item.brigade_name formData.value.address = tabsList[0].name + tabsList[1].name + tabsList[2].name + tabsList[3].name + tabsList[4].name return showPop.value = false } formData.value.address = tabsList[0].name + tabsList[1].name + tabsList[2].name + tabsList[3].name + tabsList[4] .name return currentAddressIndex.value++ } const getCityList = async () => { let res = await cityListApi({ province_code: formData.value.province }) addressList.city = res.data } const tabsList = reactive( [{ name: "请选择" }, { name: '请选择', disabled: false }, { name: '请选择', disabled: false }, { name: '请选择', disabled: false }, { name: '请选择', disabled: false }, ]); onLoad((options) => { if (options.type) { type.value = options.type } if (options.mode == 'edit' && options.address_id) { mode.value = 'edit'; uni.setNavigationBarTitle({ title: '编辑地址' }) getAddressDetil(options.address_id) } else uni.setNavigationBarTitle({ title: '新增地址' }) getCityList() }) </script> <style lang="scss"> .card { margin: 20rpx; background-color: #fff; border-radius: 14rpx; padding: 0 30rpx; .is-default { display: flex; align-items: center; justify-content: space-between; padding: 20rpx 0; } } .bottom-fixed { position: fixed; bottom: 0; left: 0; height: 120rpx; height: calc(constant(safe-area-inset-bottom) + 120rpx); /* 适用于iOS设备 */ height: calc(env(safe-area-inset-bottom) + 120rpx); /* 适用于Android设备 */ width: 100%; box-sizing: border-box; background-color: #fff; padding: 20rpx; padding-bottom: calc(constant(safe-area-inset-bottom) + 20rpx); /* 适用于iOS设备 */ padding-bottom: calc(env(safe-area-inset-bottom) + 20rpx); /* 适用于Android设备 */ } .address-content { padding: 20rpx; height: 60vh; overflow-y: auto; .address-li { display: flex; justify-content: space-between; align-items: center; font-size: 32rpx; color: #777777; margin: 30rpx 0; } .act { color: #20B128; } } </style>