Forráskód Böngészése

省市区弹窗组件重做

@dongkboy 1 hónapja
szülő
commit
853f00575c
1 módosított fájl, 171 hozzáadás és 5 törlés
  1. 171 5
      components/uni-areaCascadePicker/uni-areaCascadePicker.vue

+ 171 - 5
components/uni-areaCascadePicker/uni-areaCascadePicker.vue

@@ -1,8 +1,41 @@
 <template>
 	<view class="addressPicker">
-		<u-picker :show="shows" ref="uPicker" :defaultIndex="defaultIndex" :columns="columns" keyName="name"
+		<u-popup :show="modelshow" @close="close" round="20rpx" bgColor="#fff" mode="bottom"
+			:closeOnClickOverlay="true">
+			<view class="">
+				<view class="header header-padding dis a-c j-c borderBottom">
+					<text>选择地区</text>
+				</view>
+				<view class="content">
+					<view class="quickOptions">
+						<picker-view :indicator-style="indicatorStyle" :value="value" @change="monthbindChange"
+							class="picker-view">
+							<picker-view-column>
+								<view class="item dis a-c j-c " v-for="(item,index) in columns[0]" :key="index">
+									{{item.name}}
+								</view>
+							</picker-view-column>
+							<picker-view-column>
+								<view class="item dis a-c j-c " v-for="(item,index) in columns[1]" :key="index">
+									{{item.name}}
+								</view>
+							</picker-view-column>
+							<picker-view-column>
+								<view class="item dis a-c j-c " v-for="(item,index) in columns[2]" :key="index">
+									{{item.name}}
+								</view>
+							</picker-view-column>
+						</picker-view>
+						<view class="custom-footer 	dis j-s a-c ">
+							<view class="dis a-c j-c" @tap="statusConfirm">确定</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</u-popup>
+		<!-- <u-picker :show="shows" ref="uPicker" :defaultIndex="defaultIndex" :columns="columns" keyName="name"
 			@change="changeHandler" @cancel="cancel" @confirm="confirm" @close="close"
-			:closeOnClickOverlay="true"></u-picker>
+			:closeOnClickOverlay="true"></u-picker> -->
 	</view>
 </template>
 
@@ -25,18 +58,21 @@
 		},
 		data() {
 			return {
-				shows: this.show,
+				modelshow: this.show,
 				columns: [
 					[],
 					[],
 					[]
 				], // 省/市/区三级数据
-				fullData: [] // 包含完整结构的缓存数据
+				fullData: [], // 包含完整结构的缓存数据
+				value: [0, 0, 0],
+				lastValue: [0, 0, 0], // 保存上一次的选中值
+				indicatorStyle: `height: 41px;`
 			}
 		},
 		watch: {
 			show(val) {
-				this.shows = val
+				this.modelshow = val
 				if (val) this.initByCodes(this.defaultCodes)
 			},
 			defaultCodes: {
@@ -48,8 +84,65 @@
 		},
 		async created() {
 			await this.initData()
+			console.log(this.fullData);
 		},
 		methods: {
+			//月份滚动事件
+			monthbindChange: function(e) {
+				const val = e.detail.value; // 当前选中下标数组 [省索引, 市索引, 区索引]
+				const lastVal = this.lastValue;
+
+				let provinceIndex = val[0];
+				let cityIndex = val[1];
+				let areaIndex = val[2] || 0;
+
+				// 判断是否是省份变化
+				if (provinceIndex !== lastVal[0]) {
+					if (this.fullData[provinceIndex]) {
+						const cities = this.fullData[provinceIndex].children || [];
+						this.columns[1] = cities.map(c => ({
+							name: c.name,
+							code: c.code
+						}));
+
+						// 重置城市索引到第一个
+						cityIndex = 0;
+
+						// 更新区级数据
+						if (cities[0]) {
+							const areas = cities[0].children || [];
+							this.columns[2] = areas.map(a => ({
+								name: a.name,
+								code: a.code
+							}));
+							areaIndex = 0;
+						} else {
+							this.columns[2] = [];
+						}
+					}
+				}
+				// 判断是否是城市变化
+				else if (cityIndex !== lastVal[1]) {
+					if (this.fullData[provinceIndex]?.children?.[cityIndex]) {
+						const areas = this.fullData[provinceIndex].children[cityIndex].children || [];
+						this.columns[2] = areas.map(a => ({
+							name: a.name,
+							code: a.code
+						}));
+						areaIndex = 0;
+					} else {
+						this.columns[2] = [];
+					}
+				}
+
+				// 保存当前值
+				this.lastValue = [provinceIndex, cityIndex, areaIndex];
+
+				// 使用nextTick延迟更新value,避免阻塞用户滑动
+				this.$nextTick(() => {
+					this.value = [provinceIndex, cityIndex, areaIndex];
+				});
+			},
 			// 初始化数据结构(含6位码处理)
 			initData() {
 				this.fullData = address.map(province => ({
@@ -168,6 +261,23 @@
 					this.$refs.uPicker.setColumnValues(2, this.columns[2])
 				}
 			},
+			statusConfirm() {
+				const provinceIndex = this.value[0] || 0;
+				const cityIndex = this.value[1] || 0;
+				const areaIndex = this.value[2] || 0;
+
+				const province = this.columns[0][provinceIndex];
+				const city = this.columns[1][cityIndex];
+				const area = this.columns[2][areaIndex];
+
+				this.$emit('confirm', {
+					names: [province?.name, city?.name, area?.name].filter(Boolean),
+					codes: [province?.code, city?.code, area?.code].filter(Boolean),
+					fullAddress: [province?.name, city?.name, area?.name].filter(Boolean).join('-')
+				});
+
+				this.close();
+			},
 			cancel() {
 				this.$emit('cancel')
 			},
@@ -188,5 +298,61 @@
 
 
 <style lang="scss" scoped>
+	.header {
+		color: #333;
+		font-size: 32rpx;
+		font-weight: bold;
+	}
+
+	.header-padding {
+		padding: 27rpx 30rpx;
+	}
 
+	.borderBottom {
+		border-bottom: 1px solid #EEEEEE;
+	}
+
+	.quickOptions {
+		padding: 32rpx;
+		box-sizing: border-box;
+		margin-bottom: 20rpx;
+
+
+
+	}
+
+	.custom-footer {
+		padding: 40rpx 0 0;
+		box-sizing: border-box;
+
+		view {
+			font-size: 30rpx;
+			padding: 20rpx;
+			flex: 1;
+		}
+
+		view:first-child {
+			color: #333;
+			background: transparent;
+			border-radius: 50rpx;
+			border: 1rpx solid #FDE935;
+			margin-right: 28rpx;
+		}
+
+		view:last-child {
+			background: #FDE935;
+			border-radius: 50rpx;
+			color: #1F1F1F;
+		}
+	}
+
+	.picker-view {
+		width: 100%;
+		height: 400rpx;
+
+		.item {
+			font-size: 30rpx;
+			color: #333;
+		}
+	}
 </style>