¶Ô±ÈÐÂÎļþ |
| | |
| | | <script setup lang="ts"> |
| | | import { ref, reactive, onMounted } from 'vue'; |
| | | import tab from '@/plugins/tab'; |
| | | import citySelect from '@/components/u-city-select/u-city-select.vue'; |
| | | import { useAddressEditPage } from './index'; |
| | | |
| | | // 使ç¨ç¼è¾é¡µé¢Hook |
| | | const { |
| | | isEdit, |
| | | form, |
| | | defaultAddress, |
| | | selectedTag, |
| | | addressTags, |
| | | initEditPage, |
| | | saveAddress, |
| | | deleteAddress |
| | | } = useAddressEditPage(); |
| | | |
| | | // å°åºéæ©å¨æ¾ç¤ºç¶æ |
| | | const showRegionPicker = ref(false); |
| | | |
| | | // 表åéè¯¯ç¶æ - ç§»å°Vueç»ä»¶ä¸ |
| | | const formErrors = reactive({ |
| | | name: false, |
| | | phone: false, |
| | | region: false, |
| | | address: false |
| | | }); |
| | | |
| | | // é置表åé误 |
| | | function resetFormErrors() { |
| | | formErrors.name = false; |
| | | formErrors.phone = false; |
| | | formErrors.region = false; |
| | | formErrors.address = false; |
| | | } |
| | | |
| | | // åå§å页颿°æ® |
| | | onMounted(() => { |
| | | const pages = getCurrentPages(); |
| | | const currentPage: any = pages[pages.length - 1]; |
| | | const options = currentPage.$page?.options; |
| | | |
| | | // è°ç¨hookçåå§åæ¹æ³ |
| | | initEditPage(options?.id); |
| | | // é置表åéè¯¯ç¶æ |
| | | resetFormErrors(); |
| | | }); |
| | | |
| | | // 设置é»è®¤å°å |
| | | function handleSetDefault(e: any) { |
| | | defaultAddress.value = e.detail.value; |
| | | } |
| | | |
| | | // æ¾ç¤ºå°åºéæ©å¨ |
| | | function handleShowRegionPicker() { |
| | | showRegionPicker.value = true; |
| | | } |
| | | |
| | | // ç¡®è®¤éæ©å°åº |
| | | function handleCityChange(e: any) { |
| | | form.region = e.province.label + e.city.label + e.area.label; |
| | | formErrors.region = false; |
| | | } |
| | | |
| | | // éæ©æ ç¾ |
| | | function handleSelectTag(tag: string) { |
| | | selectedTag.value = tag; |
| | | } |
| | | |
| | | // 表åéªè¯ |
| | | function validateForm(): boolean { |
| | | // éªè¯å§å |
| | | formErrors.name = !form.name.trim(); |
| | | |
| | | // éªè¯ææºå· |
| | | const phoneReg = /^1[3-9]\d{9}$/; |
| | | formErrors.phone = !phoneReg.test(form.phone); |
| | | |
| | | // éªè¯å°åº |
| | | formErrors.region = !form.region; |
| | | |
| | | // éªè¯è¯¦ç»å°å |
| | | formErrors.address = !form.address.trim(); |
| | | |
| | | // 妿æä»»ä½é误ï¼è¿åfalse |
| | | return !(formErrors.name || formErrors.phone || formErrors.region || formErrors.address); |
| | | } |
| | | |
| | | // ä¿åå°å |
| | | function handleSaveAddress() { |
| | | // ä½¿ç¨æ¬å°éªè¯æ¹æ³ |
| | | if (!validateForm()) { |
| | | uni.showToast({ |
| | | title: '请填å宿´ä¿¡æ¯', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | const success = saveAddress(); |
| | | |
| | | if (success) { |
| | | uni.showToast({ |
| | | title: isEdit.value ? 'ä¿®æ¹æå' : 'æ·»å æå', |
| | | icon: 'success' |
| | | }); |
| | | |
| | | // å»¶è¿è¿åï¼è®©ç¨æ·çå°æç¤º |
| | | setTimeout(() => { |
| | | tab.navigateBack(); |
| | | }, 1000); |
| | | } else { |
| | | uni.showToast({ |
| | | title: 'ä¿å失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | } catch (e) { |
| | | console.error('ä¿åå°å失败', e); |
| | | uni.showToast({ |
| | | title: 'ä¿å失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // å é¤å°å |
| | | function handleDeleteAddress() { |
| | | if (!isEdit.value) return; |
| | | |
| | | uni.showModal({ |
| | | title: 'æç¤º', |
| | | content: 'ç¡®å®è¦å 餿¤å°ååï¼', |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | try { |
| | | const success = deleteAddress(); |
| | | |
| | | if (success) { |
| | | uni.showToast({ |
| | | title: 'å 餿å', |
| | | icon: 'success' |
| | | }); |
| | | |
| | | setTimeout(() => { |
| | | tab.navigateBack(); |
| | | }, 1000); |
| | | } else { |
| | | uni.showToast({ |
| | | title: 'å é¤å¤±è´¥', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | } catch (e) { |
| | | console.error('å é¤å°å失败', e); |
| | | uni.showToast({ |
| | | title: 'å é¤å¤±è´¥', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <view class="wrap"> |
| | | <view class="container"> |
| | | <view class="top"> |
| | | <view class="item"> |
| | | <view class="left"> |
| | | <text class="required">*</text>æ¶è´§äºº |
| | | </view> |
| | | <input type="text" v-model="form.name" placeholder-class="line" placeholder="è¯·å¡«åæ¶è´§äººå§å" |
| | | :class="{ 'error-input': formErrors.name }" /> |
| | | <u-icon name="account" size="36rpx" color="#999"></u-icon> |
| | | </view> |
| | | <view class="error-msg" v-if="formErrors.name">请è¾å
¥æ¶è´§äººå§å</view> |
| | | |
| | | <view class="item"> |
| | | <view class="left"> |
| | | <text class="required">*</text>ææºå·ç |
| | | </view> |
| | | <input type="number" v-model="form.phone" placeholder-class="line" placeholder="è¯·å¡«åæ¶è´§äººææºå·" maxlength="11" |
| | | :class="{ 'error-input': formErrors.phone }" /> |
| | | <u-icon name="phone" size="36rpx" color="#999"></u-icon> |
| | | </view> |
| | | <view class="error-msg" v-if="formErrors.phone">请è¾å
¥æ£ç¡®çææºå·ç </view> |
| | | |
| | | <view class="item" @tap="handleShowRegionPicker"> |
| | | <view class="left"> |
| | | <text class="required">*</text>æå¨å°åº |
| | | </view> |
| | | <input disabled v-model="form.region" type="text" placeholder-class="line" placeholder="çå¸åºå¿ã乡éç" |
| | | :class="{ 'error-input': formErrors.region }" /> |
| | | <u-icon name="arrow-right" size="36rpx" color="#999"></u-icon> |
| | | </view> |
| | | <view class="error-msg" v-if="formErrors.region">è¯·éæ©æå¨å°åº</view> |
| | | |
| | | <view class="item address"> |
| | | <view class="left"> |
| | | <text class="required">*</text>详ç»å°å |
| | | </view> |
| | | <textarea v-model="form.address" type="text" placeholder-class="line" placeholder="è¡éãæ¥¼çç" |
| | | :class="{ 'error-textarea': formErrors.address }" /> |
| | | </view> |
| | | <view class="error-msg" v-if="formErrors.address">请è¾å
¥è¯¦ç»å°å</view> |
| | | </view> |
| | | |
| | | <view class="bottom"> |
| | | <view class="tag"> |
| | | <view class="left">æ ç¾</view> |
| | | <view class="right"> |
| | | <text v-for="tag in addressTags" :key="tag" class="tags" :class="{ 'active': selectedTag === tag }" |
| | | @tap="handleSelectTag(tag)"> |
| | | {{ tag }} |
| | | </text> |
| | | <view class="tags plus"><u-icon size="22" name="plus" color="#999"></u-icon></view> |
| | | </view> |
| | | </view> |
| | | <view class="default"> |
| | | <view class="left"> |
| | | <view class="set">设置é»è®¤å°å</view> |
| | | <view class="tips">æéï¼æ¯æ¬¡ä¸åä¼é»è®¤æ¨è该å°å</view> |
| | | </view> |
| | | <view class="right"> |
| | | <switch color="#fa3534" :checked="defaultAddress" @change="handleSetDefault" /> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="button-group"> |
| | | <view class="save-btn" @tap="handleSaveAddress"> |
| | | {{ isEdit ? 'ä¿åä¿®æ¹' : 'ä¿åå°å' }} |
| | | </view> |
| | | <view v-if="isEdit" class="delete-btn" @tap="handleDeleteAddress"> |
| | | å é¤å°å |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <city-select v-model="showRegionPicker" @city-change="handleCityChange"></city-select> |
| | | </view> |
| | | </template> |
| | | |
| | | <style lang="scss" scoped> |
| | | :v-deep(.line) { |
| | | color: $u-light-color; |
| | | font-size: 28rpx; |
| | | } |
| | | |
| | | .wrap { |
| | | background-color: #f5f5f5; |
| | | min-height: 100vh; |
| | | padding: 20rpx; |
| | | box-sizing: border-box; |
| | | |
| | | .container { |
| | | border-radius: 16rpx; |
| | | overflow: hidden; |
| | | box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .top { |
| | | background-color: #ffffff; |
| | | padding: 30rpx; |
| | | |
| | | .item { |
| | | display: flex; |
| | | font-size: 32rpx; |
| | | line-height: 100rpx; |
| | | align-items: center; |
| | | border-bottom: solid 1rpx #eeeeee; |
| | | position: relative; |
| | | |
| | | .left { |
| | | width: 180rpx; |
| | | font-weight: 500; |
| | | color: #333; |
| | | |
| | | .required { |
| | | color: #fa3534; |
| | | margin-right: 4rpx; |
| | | } |
| | | } |
| | | |
| | | input { |
| | | text-align: left; |
| | | flex: 1; |
| | | height: 100rpx; |
| | | font-size: 30rpx; |
| | | |
| | | &.error-input { |
| | | border-bottom: 1px solid #fa3534; |
| | | } |
| | | } |
| | | |
| | | u-icon { |
| | | margin-left: 10rpx; |
| | | } |
| | | } |
| | | |
| | | .error-msg { |
| | | color: #fa3534; |
| | | font-size: 24rpx; |
| | | padding-left: 180rpx; |
| | | margin-top: -10rpx; |
| | | margin-bottom: 10rpx; |
| | | } |
| | | |
| | | .address { |
| | | padding: 20rpx 0; |
| | | align-items: flex-start; |
| | | |
| | | .left { |
| | | padding-top: 20rpx; |
| | | } |
| | | |
| | | textarea { |
| | | flex: 1; |
| | | height: 180rpx; |
| | | background-color: #f9f9f9; |
| | | line-height: 60rpx; |
| | | margin: 20rpx 0; |
| | | padding: 20rpx; |
| | | border-radius: 12rpx; |
| | | font-size: 30rpx; |
| | | |
| | | &.error-textarea { |
| | | border: 1px solid #fa3534; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .bottom { |
| | | margin-top: 20rpx; |
| | | padding: 30rpx; |
| | | background-color: #ffffff; |
| | | font-size: 28rpx; |
| | | border-radius: 16rpx; |
| | | |
| | | .tag { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .left { |
| | | width: 160rpx; |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | |
| | | .right { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | flex: 1; |
| | | |
| | | .tags { |
| | | width: 150rpx; |
| | | padding: 20rpx 10rpx; |
| | | border: solid 2rpx #eeeeee; |
| | | text-align: center; |
| | | border-radius: 100rpx; |
| | | margin: 0 20rpx 20rpx 0; |
| | | display: flex; |
| | | font-size: 28rpx; |
| | | align-items: center; |
| | | justify-content: center; |
| | | color: #333; |
| | | line-height: 1; |
| | | transition: all 0.3s; |
| | | |
| | | &.active { |
| | | background-color: #ffebec; |
| | | color: #fa3534; |
| | | border-color: #fa3534; |
| | | } |
| | | } |
| | | |
| | | .plus { |
| | | background-color: #f5f5f5; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .default { |
| | | margin-top: 30rpx; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding-bottom: 20rpx; |
| | | |
| | | .left { |
| | | .set { |
| | | font-weight: 500; |
| | | color: #333; |
| | | font-size: 30rpx; |
| | | } |
| | | |
| | | .tips { |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | margin-top: 10rpx; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .button-group { |
| | | display: flex; |
| | | flex-direction: column; |
| | | margin-top: 60rpx; |
| | | |
| | | .save-btn { |
| | | background: linear-gradient(90deg, #ff4034, #fa3534); |
| | | color: #fff; |
| | | height: 90rpx; |
| | | line-height: 90rpx; |
| | | text-align: center; |
| | | font-size: 32rpx; |
| | | border-radius: 45rpx; |
| | | font-weight: bold; |
| | | box-shadow: 0 10rpx 20rpx rgba(250, 53, 52, 0.2); |
| | | letter-spacing: 2rpx; |
| | | } |
| | | |
| | | .delete-btn { |
| | | margin-top: 30rpx; |
| | | background: #ffffff; |
| | | color: #fa3534; |
| | | border: 1px solid #fa3534; |
| | | height: 90rpx; |
| | | line-height: 90rpx; |
| | | text-align: center; |
| | | font-size: 32rpx; |
| | | border-radius: 45rpx; |
| | | letter-spacing: 2rpx; |
| | | } |
| | | } |
| | | } |
| | | </style> |