Selaa lähdekoodia

feat:地址选择 四级

DaMowang 2 vuotta sitten
vanhempi
sitoutus
4805db5eaa

+ 592 - 0
src/components/lcw-select-address/lcw-select-address.vue

@@ -0,0 +1,592 @@
+<template>
+	<uni-popup type="bottom" ref="selectAddressRef">
+		<view class="select-address-box">
+			<view class="header-box">
+				<view></view>
+				<view class="title-box">选择所在地区</view>
+				<view class="close-icon" @tap="close">
+					<view class="iconfont icon-a-Shutdown-01">x</view>
+				</view>
+			</view>
+			<view class="main-box">
+				<view class="address-info">
+					<view class="address-item" @tap="setSelectStatus(0)">
+						<view class="strip-item">
+							<view
+								:class="{
+									'show-line': address.province,
+									active: address.province
+								}"
+							></view>
+						</view>
+						<view
+							class="name-box"
+							:class="{
+								active: selectStatus == 0
+							}"
+						>
+							<text v-if="address.province">
+								{{ address.province }}
+							</text>
+							<text v-else>请选择所在省份</text>
+						</view>
+						<view class="icon-box">
+							<view class="iconfont icon-xiangyou">
+								{{ '>' }}
+							</view>
+						</view>
+					</view>
+					<view v-if="address.province" class="address-item" @tap="setSelectStatus(1)">
+						<view class="strip-item">
+							<view
+								:class="{
+									'show-line': address.city,
+									active: address.city
+								}"
+							></view>
+						</view>
+						<view
+							class="name-box"
+							:class="{
+								active: selectStatus == 1
+							}"
+						>
+							<text v-if="address.city">{{ address.city }}</text>
+							<text v-else>请选择所在城市</text>
+						</view>
+						<view class="icon-box">
+							<view class="iconfont icon-xiangyou">
+								{{ '>' }}
+							</view>
+						</view>
+					</view>
+					<view v-if="address.city" class="address-item" @tap="setSelectStatus(2)">
+						<view class="strip-item last-strip-item">
+							<view
+								:class="{
+									'show-line': showStreet,
+									active: address.area
+								}"
+							></view>
+						</view>
+						<view
+							class="name-box"
+							:class="{
+								active: selectStatus == 2
+							}"
+						>
+							<text v-if="address.area">{{ address.area }}</text>
+							<text v-else>请选择所在区/县</text>
+						</view>
+						<view class="icon-box">
+							<view class="iconfont icon-xiangyou">
+								{{ '>' }}
+							</view>
+						</view>
+					</view>
+					<view v-if="showStreet" class="address-item" @tap="setSelectStatus(3)">
+						<view class="strip-item last-strip-item">
+							<view
+								:class="{
+									active: address.street
+								}"
+							></view>
+						</view>
+						<view
+							class="name-box"
+							:class="{
+								active: selectStatus == 3
+							}"
+						>
+							<text v-if="address.street">
+								{{ address.street }}
+							</text>
+							<text v-else>请选择所在乡/镇</text>
+						</view>
+						<view class="icon-box">
+							<view class="iconfont icon-xiangyou">
+								{{ '>' }}
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="address-select-box">
+					<scroll-view
+						class="content-box"
+						:style="{ height: scrollHeight }"
+						scroll-y="true"
+					>
+						<view v-if="selectStatus === 0">
+							<view class="select-tip">请选择省份</view>
+							<view
+								class="select-item"
+								:class="{
+									active: activeProvinvial.name === i.name
+								}"
+								v-for="i in provinvial"
+								:key="i.code"
+								@tap="changeProvinvial(i)"
+							>
+								{{ i.name }}
+							</view>
+						</view>
+						<view v-else-if="selectStatus === 1">
+							<view class="select-tip">请选择城市</view>
+							<view
+								class="select-item"
+								:class="{
+									active: activeCity.name === i.name
+								}"
+								v-for="i in citys"
+								:key="i.code"
+								@tap="changeCity(i)"
+							>
+								{{ i.name }}
+							</view>
+						</view>
+						<view v-else-if="selectStatus === 2">
+							<view class="select-tip">请选择区/县</view>
+							<view
+								class="select-item"
+								:class="{
+									active: activeArea.name === i.name
+								}"
+								v-for="i in areas"
+								:key="i.code"
+								@tap="changeArea(i)"
+							>
+								{{ i.name }}
+							</view>
+						</view>
+						<view v-else>
+							<view class="select-tip">请选择乡/镇</view>
+							<view
+								class="select-item"
+								:class="{
+									active: activeStreet.name === i.name
+								}"
+								v-for="i in streets"
+								:key="i.code"
+								@tap="changeStreet(i)"
+							>
+								{{ i.name }}
+							</view>
+						</view>
+					</scroll-view>
+				</view>
+			</view>
+		</view>
+	</uni-popup>
+</template>
+
+<script>
+import { post } from "@/request/api.js"
+export default {
+	emits: ['change'],
+	props: {
+		address: {
+			type: Object,
+			require: true,
+			default: () => ({
+				province: '',
+				city: '',
+				area: '',
+				street: ''
+			})
+		}
+	},
+	data() {
+		return {
+			//全部数据
+			provinvial: [], // 省
+			cityData: [],
+			areaData: [],
+			streetsData: [],
+			// 筛选后的数据
+			citys: [], // 城市
+			areas: [], // 区/县
+			streets: [], // 镇
+			// 选择的省、市、区具体名称
+			activeProvinvial: { name: '' }, // 选择中的省份
+			activeCity: {
+				name: ''
+			}, // 选中的城市
+			activeArea: { name: '' }, // 选中的区县
+			activeStreet: { name: '' }, // 选中的乡镇
+			//  0 1 2 3 当前正在选择 省 市 区 镇
+			selectStatus: 0
+		};
+	},
+	computed: {
+		// 高度计算
+		scrollHeight() {
+			let height = 920;
+
+			if (this.address.province) {
+				height -= 80;
+			}
+			if (this.address.city) {
+				height -= 80;
+			}
+			if (this.address.area && 'street' in this.address) {
+				height -= 80;
+			}
+			return height + 'rpx';
+		},
+		// 是否展示4级
+		showStreet() {
+			return Boolean(
+				this.selectStatus === 3 ||
+					(this.activeArea.name && 'street' in this.address)
+			);
+		}
+	},
+	watch: {
+		address: {
+			handler(newHandler) {
+				if (newHandler.province && !this.activeProvinvial.code) {
+					this.setActiveProvinvial();
+				}
+				if (newHandler.city && !this.activeCity.code) {
+					this.setActiveCity();
+				}
+				if (newHandler.area && !this.activeArea.code) {
+					this.setActiveArea();
+				}
+				if (newHandler.street && !this.activeStreet.code) {
+					this.setActiveStreet();
+				}
+			},
+			deep: true
+		}
+	},
+	mounted() {
+		this.getProvinvial();
+	},
+	methods: {
+		// 更新正在选择内容的标记
+		setSelectStatus(newSelectStatus) {
+			this.selectStatus = newSelectStatus;
+		},
+		// 关闭 popup
+		close() {
+			this.$refs.selectAddressRef.close();
+		},
+		// 打开  popup
+		open() {
+			this.$refs.selectAddressRef.open();
+		},
+		// 选择省
+		changeProvinvial(i) {
+			if (i.name !== this.address.province) {
+				this.activeProvinvial = i;
+				this.activeCity = {};
+				this.activeArea = {};
+				this.activeStreet = {};
+				const newAddress = {
+					province: i.name,
+					city: '',
+					area: ''
+				};
+				if ('street' in this.address) {
+					newAddress.street = '';
+				}
+				this.$emit('change', newAddress);
+			}
+			this.citys = this.cityData.filter(
+				item => item.provinceCode === i.code
+			);
+			this.selectStatus = 1;
+		},
+		// 选择市
+		changeCity(i) {
+			if (i.name !== this.address.city) {
+				this.activeCity = i;
+				this.activeArea = {};
+				this.activeStreet = {};
+				const newAddress = {
+					province: this.address.province,
+					city: i.name,
+					area: ''
+				};
+				if ('street' in this.address) {
+					newAddress.street = '';
+				}
+				this.$emit('change', newAddress);
+			}
+			this.areas = this.areaData.filter(item => item.cityCode === i.code);
+			this.selectStatus = 2;
+		},
+		// 选择区县
+		changeArea(i) {
+			if (i.name !== this.address.area) {
+				this.activeArea = i;
+				this.activeStreet = {};
+				const newAddress = {
+					province: this.address.province,
+					city: this.address.city,
+					area: i.name
+				};
+				if ('street' in this.address) {
+					newAddress.street = '';
+				}
+				this.$emit('change', newAddress);
+			}
+
+			if ('street' in this.address) {
+				this.selectStatus = 3;
+				this.streets = this.streetsData.filter(
+					item => item.areaCode === i.code
+				);
+			} else {
+				this.close();
+			}
+		},
+		// 选择乡镇
+		changeStreet(i) {
+			if (i.name !== this.address.street) {
+				this.activeStreet = i;
+				this.$emit('change', {
+					...this.address,
+					street: i.name
+				});
+			}
+			this.close();
+		},
+		// 省份数据获取
+		getProvinvial() {
+			post('user/areaConfig',{type:'provinces'}).then(res=>{
+				if(res.code == 0){
+					let da = JSON.parse(res.data.data)
+					this.provinvial = da;
+					this.setActiveProvinvial();
+					this.getCity();
+				}
+			})
+		},
+		setActiveProvinvial() {
+			if (this.address.province && !this.activeProvinvial.code) {
+				const provinceIndex = this.provinvial.findIndex(
+					i => i.name == this.address.province
+				);
+				if (provinceIndex !== -1) {
+					this.activeProvinvial = this.provinvial[provinceIndex];
+				}
+			}
+		},
+		// 城市数据获取
+		getCity() {
+			post('user/areaConfig',{type:'cities'}).then(res=>{
+				if(res.code == 0){
+					let da = JSON.parse(res.data.data)
+					this.cityData = da;
+					this.setActiveCity();
+					this.getArea();
+				}
+			})
+		},
+		setActiveCity() {
+			if (this.cityData && this.cityData.length === 0) {
+				return;
+			}
+
+			this.citys = this.cityData.filter(
+				item => item.provinceCode === this.activeProvinvial.code
+			);
+
+			if (this.address.city && !this.activeCity.code) {
+				const cityIndex = this.cityData.findIndex(
+					i =>
+						i.name == this.address.city &&
+						this.activeProvinvial.code == i.provinceCode
+				);
+				if (cityIndex !== -1) {
+					this.activeCity = this.cityData[cityIndex];
+				}
+			}
+		},
+		// 区县数据
+		getArea() {
+			post('user/areaConfig',{type:'areas'}).then(res=>{
+				if(res.code == 0){
+					let da = JSON.parse(res.data.data)
+					this.areaData = da;
+					this.setActiveArea();
+					if ('street' in this.address) {
+						this.getStreets();
+					}
+				}
+			})
+		},
+		setActiveArea() {
+			if (this.areaData.length === 0) {
+				return;
+			}
+			this.areas = this.areaData.filter(
+				item => item.cityCode === this.activeCity.code
+			);
+			if (this.address.area && !this.activeArea.code) {
+				const areaIndex = this.areaData.findIndex(
+					i =>
+						i.name == this.address.area &&
+						i.cityCode == this.activeCity.code
+				);
+				if (areaIndex !== -1) {
+					this.activeArea = this.areaData[areaIndex];
+				}
+			}
+		},
+		// 镇 社区
+		getStreets() {
+			post('user/areaConfig',{type:'streets'}).then(res=>{
+				if(res.code == 0){
+					let da = JSON.parse(res.data.data)
+					this.streetsData = da;
+					this.setActiveStreet();
+				}
+			})
+		},
+		setActiveStreet() {
+			if (this.streetsData.length === 0) {
+				return;
+			}
+			this.streets = this.streetsData.filter(
+				item => item.areaCode === this.activeArea.code
+			);
+			if (this.address.street && !this.activeStreet.code) {
+				const streetIndex = this.streetsData.findIndex(
+					i => i.name == this.address.street
+				);
+				if (streetIndex !== -1) {
+					this.activeStreet = this.streetsData[streetIndex];
+				}
+			}
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+.select-address-box {
+	height: 1100rpx;
+	border-top-left-radius: 20rpx;
+	border-top-right-radius: 20rpx;
+	background-color: #fff;
+	padding: 30rpx 0;
+
+	.header-box {
+		display: flex;
+		justify-content: space-between;
+		font-size: 32rpx;
+		font-weight: bold;
+		color: #333;
+		margin-bottom: 40rpx;
+		padding: 0 20rpx;
+
+		> .title-box {
+			font-size: 36rpx;
+		}
+
+		.iconfont {
+			color: #72899b;
+		}
+	}
+
+	.main-box {
+		.address-info {
+			padding: 0 20rpx;
+
+			> .address-item {
+				display: flex;
+				align-items: center;
+				height: 80rpx;
+
+				.strip-item {
+					color: #333;
+					margin-right: 48rpx;
+					position: relative;
+
+					> view {
+						width: 12rpx;
+						height: 12rpx;
+						border-radius: 50%;
+						border: 2rpx solid #086df7;
+						transition: all 0.25s;
+						box-sizing: border-box;
+					}
+
+					.show-line {
+						&::after {
+							content: '';
+							position: absolute;
+							top: 100%;
+							left: 50%;
+							width: 2rpx;
+							height: 69rpx;
+							background-color: #086df7;
+						}
+
+						/* #ifndef H5*/
+						&::after {
+							transform: translateX(-50%);
+						}
+						/* #endif */
+
+						/* #ifdef VUE2 */
+						&::after {
+							transform: translateX(-50%);
+						}
+						/* #endif */
+					}
+
+					.active {
+						background: #086df7;
+					}
+				}
+
+				.name-box {
+					font-size: 28rpx;
+					flex: 1;
+				}
+
+				.active {
+					color: #086df7;
+				}
+
+				.icon-box {
+					.iconfont {
+						font-size: 24rpx;
+						color: #72899b;
+					}
+				}
+			}
+		}
+
+		.address-select-box {
+			padding: 20rpx 20rpx;
+			border-top: 2rpx solid #d4d4d4;
+
+			.content-box {
+				height: 600rpx;
+
+				.select-tip {
+					font-size: 32rpx;
+					color: #333;
+					font-weight: bold;
+					padding-bottom: 20rpx;
+				}
+
+				.select-item {
+					padding: 20rpx 20rpx;
+					font-size: 28rpx;
+					color: #333;
+				}
+
+				.active {
+					color: #086df7;
+				}
+			}
+		}
+	}
+}
+</style>

+ 2 - 1
src/pages/sign/index.vue

@@ -159,7 +159,8 @@ export default {
         }
         post("user/doSign", data).then((res) => {
           if (res.code === 0) {
-            this.nextSign = res.data.next_sign
+            // this.nextSign = res.data.next_sign
+            this.$set(this, "nextSign", res.data.next_sign)
             this.loadData();
           } else {
             appEv.errTips(res.msg);

+ 54 - 54
src/pages/xghc-addrress/userAddress.vue

@@ -1,27 +1,28 @@
 <template>
     <uni-popup ref="popup" type="bottom">
         <view class="Address_container">
-            <div class="tit clearfix">
+            <div class="tit flex_r flex_jb">
                 <text class="cancel" v-if="isadd" @click="isadd = false">取消</text>
+                <text v-else></text>
                 <text class="close" @click="close">关闭</text>
             </div>
             <div class="s_con">
                 <form @submit="formSubmit" v-if="isadd">
                     <view class='addAddress'>
-                        <view class="pad30">
+                        <!-- <view class="pad30">
                             <view class='default acea-row borderRadius15'>
                                 <textarea v-model="addressValue" placeholder="粘贴地址信息,自动拆分姓名、电话和地址" @blur="identify()" class="inputa-text" />
                             </view>
-                        </view>
+                        </view> -->
                         <view class="pad30 mt-22">
                             <view class='list borderRadius15'>
                                 <view class='item acea-row row-between-wrapper'>
                                     <view class='name'>姓名</view>
-                                    <input type='text' placeholder='请输入姓名' v-model="userAddress.real_name" class="inputa" />
+                                    <input type='text' placeholder='请输入姓名' v-model="userAddress.name" class="inputa" />
                                 </view>
                                 <view class='item acea-row row-between-wrapper'>
                                     <view class='name'>联系电话</view>
-                                    <input type='number' placeholder='请输入联系电话' v-model='userAddress.phone' class="inputa" />
+                                    <input type='number' placeholder='请输入联系电话' v-model='userAddress.mobile' class="inputa" />
                                 </view>
                                 <view class='item acea-row row-between-wrapper'>
                                     <view class='name'>所在地区</view>
@@ -29,7 +30,7 @@
                                 </view>
                                 <view class='item acea-row row-between-wrapper'>
                                     <view class='name'>详细地址</view>
-                                    <input type='text' placeholder='请填写具体地址' v-model='userAddress.detail' class="inputa" />
+                                    <input type='text' placeholder='请填写具体地址' v-model='userAddress.address' class="inputa" />
                                 </view>
                                 <view class='item acea-row'>
                                     <view class='name'>默认地址</view>
@@ -72,24 +73,24 @@
                 </div>
             </div>
         </view>
-        <select-address  ref='selectAddress' @selectAddress="successSelectAddress"/>
+        <select-address :address.sync="address" ref='selectAddress' @change="changeAddress"/>
     </uni-popup>
 </template>
 <script>
 import { post } from "@/request/api.js";
-import AddressParse from './zh-address-parse.min.js'
-import selectAddress from "@/components/selectAddress/selectAddress.vue"
+// import AddressParse from './zh-address-parse.min.js'
+// import smart from 'address-smart-parse'
+// import selectAddress from "@/components/selectAddress/selectAddress.vue"
+import selectAddress from "@/components/lcw-select-address/lcw-select-address.vue"
 let app = getApp();
 var appEv = app.$vm.$options;
 export default {
+    components: {
+        selectAddress
+    },
     data() {
         return {
-            userAddress: {
-                real_name: "",
-                phone: "",
-                region: "",
-                detail: "",
-            }, //地址详情
+            userAddress: {}, //地址详情
             addressValue: "",
             is_default: 0, //是否设为默认地址
             range: [{ "value": 0, "text": "否" }, { "value": 1, "text": "是" }],
@@ -97,45 +98,51 @@ export default {
             isadd: false,
             addressList: [],
             presentId: "", //当前选择地址的id
+
+            address: {
+                province: '',
+                city: '',
+                area: '',
+                street: ''
+            }
         }
     },
-    components: {
-        selectAddress
-    },
     created() {
         this.loadAddress();
     },
     methods: {
         btnClick() {
-            this.$refs.selectAddress.show()
-        },
-        successSelectAddress(address){ //选择成功回调
-            console.log(address)
-            this.userAddress.region = address
+            this.$refs.selectAddress.open()
         },
-        identify() {
-            const options = {
-                type: 0, // 哪种方式解析,0:正则,1:树查找
-                textFilter: [], // 预清洗的字段
-                nameMaxLength: 4, // 查找最大的中文名字长度
-            }
-            // type参数0表示使用正则解析,1表示采用树查找, textFilter地址预清洗过滤字段。
-            if (!!this.addressValue) {
-                const parseResult = AddressParse(this.addressValue, options)
-                this.userAddress.real_name = parseResult.name;
-                this.userAddress.phone = parseResult.phone;
-                this.userAddress.detail = parseResult.detail;
-                if(parseResult.province && parseResult.city && parseResult.area){
-                    this.userAddress.region = parseResult.province + '/' + parseResult.city + '/' + parseResult.area;
-                }
+        changeAddress(address){ //选择成功回调
+            this.address = address;
+            this.userAddress.region = ""
+            for (const i in address) {
+                this.userAddress.region += address[i] + " "
             }
         },
+
+        // identify() {
+        //     if (this.addressValue) {
+        //         const da = smart(this.addressValue)
+        //         let {province,city,county,street} = da
+        //         street = street || ''
+        //         let obj = {
+        //             name: da.name,
+        //             mobile: da.phone,
+        //             address: da.address,
+        //             region: province + ' ' + city + ' ' + county + ' ' + street
+        //         }
+        //         this.address = { province,city,area: county,street }
+        //         this.$set(this,"userAddress",obj)
+        //     }
+        // },
         formSubmit() {
             let url;
+            let { address, mobile, name } = this.userAddress
             let data = {
-                address: this.userAddress.region + this.userAddress.detail,
-                mobile: this.userAddress.phone,
-                name: this.userAddress.real_name,
+                ...this.address,
+                address, mobile, name,
                 is_default: this.is_default
             }
             if (this.userAddress.id) {
@@ -168,17 +175,11 @@ export default {
             this.userAddress = {};
         },
         onedit(da) {
-            let options = {
-                type: 0, // 哪种方式解析,0:正则,1:树查找
-                textFilter: [], // 预清洗的字段
-                nameMaxLength: 4, // 查找最大的中文名字长度
-            }
-            let parseResult = AddressParse(da.address, options)
-            this.userAddress.id = da.id;
-            this.userAddress.real_name = da.name;
-            this.userAddress.phone = da.mobile;
-            this.userAddress.detail = parseResult.detail;
-            this.userAddress.region = parseResult.province + '/' + parseResult.city + '/' + parseResult.area;
+            let {id,name,mobile,address,province,city,area,street,status} = da
+            this.userAddress = { id,name,mobile,address };
+            this.address = { province,city,area,street };
+            this.userAddress.region = province + ' ' + city + ' ' + area + ' ' + street;
+            this.is_default = status
             this.isadd = true
         },
         delAddress(id) {
@@ -189,7 +190,6 @@ export default {
                 }
             })
         },
-
         open(da) {
             this.$refs.popup.open('bottom')
             if (da == "add") this.isadd = true
@@ -232,7 +232,7 @@ export default {
     }
 
     .close {
-        float: right;
+        // float: right;
         padding: 0 30rpx;
     }
 }