| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726 | <template>	<view class="chose-city">		<view>			<view class="status_bar" :style="{height: iStatusBarHeight + 'px'}" v-if="topshow"></view>			<view class="nav" v-if="topshow">城市选择				<image src="../../static/img/goback.png" mode="" class="foback" @click="closeModal"></image>			</view>		</view>		<!-- 城市搜索 -->		<view class="city-search-wrap">			<view class="search">				<view class="l-search">					<view class="icon-search">						<!-- <view class="cuIcon-search"></view> -->						<image src="../../static/img/icon_search.png" mode="" class="cuIcon-search"></image>					</view>					<input class="input-search" type="text" :value="inputValue" placeholder="请输入城市"						placeholder-style="color:#8E8F97" :focus="searchFocus" @input="searchChange" />					<text class="clear-input iconfont icon-icon-test" v-if="isClearBtn" @click="inputValue = ''"></text>				</view>				<view class="r-cancel" @click="closeModal">取消</view>			</view>			<!-- 搜索列表  -->			<view class="reach-content" v-show="inputValue">				<block v-show="searchData.length">					<view class="li" v-for="item in searchData" :key="item.citycode" @click="selectCity(item)">						{{item.name}}					</view>				</block>				<view class="has-no-data" v-show="hasNoData">没有找到匹配数据~</view>			</view>		</view>		<!-- 城市列表 -->		<scroll-view class="scroll-view" scroll-y scroll-with-animation="true" enable-back-to-top="true"			:scroll-into-view="toIndex" @scroll="scrollHandle" v-if="!inputValue">			<view class="block">				<!-- 您所在的地区 -->				<view class="area list-item" id="area">					<view class="title-wrapp">						<view class="c-title">							<text class="l">定位城市</text>						</view>					</view>					<view class="ul">												<view v-if="citydw.name" @click="selectCity(citydw)" class="dingweiCity">{{citydw.name}}</view>						<view v-else class="dingweiCity" style="color: #999999;">未获取</view>												<view class="dingBg" @click="againDingWei()">							<image src='../../static/img/icon_location.png' class="icon"></image>							<text class="text">重新定位</text>						</view>					</view>				</view>				<!-- 历史记录 -->				<!-- <view class="area list-item" id="record" v-if="recordList.length">					<view class="title-wrapp">						<view class="c-title">							<text class="l">历史记录</text>						</view>					</view>					<view class="ul">						<view class="li font-clamp" v-for="item in recordList" :key="item.citycode" @click="selectCity(item)">							{{ item.name }}						</view>					</view>				</view> -->			</view>			<!-- 城市列表  -->			<view class="city-list">				<view class="list list-item" v-for="(item, key) of cityList" :key="key" :id="item.nameType">					<view class="c-title">{{ item.nameType }}</view>					<view class="item" v-for="innerItem in item.list" :key="innerItem.citycode"						@click="selectCity(innerItem)">						{{ innerItem.name }}					</view>				</view>			</view>		</scroll-view>		<!-- 字母列表 -->		<view class="alphabet" @touchstart="touchStart" @touchend="touchEnd" @touchmove.stop="touchMove">			<view v-for="(item, index) in alphabet" :key="index" @touchstart="getLetter" @touchend="setLetter"				:id="item">				<view class="item" :class="{ active: currentLetter == item }">					{{ item == 'area' ? '当前' : item == 'record' ? '历史' : item }}				</view>			</view>		</view>	</view></template><script>	import cityJson from '@/static/dataJson/city.json'	export default {		props: {			topshow: { //参数名				type: Boolean, //定义传值的类型				default: false //参数默认			}		},		data() {			return {				isIPX: null,				regionId: null, // 区域ID				isToggle: true,				isReach: false,				inputValue: '',				searchData: [], // 搜索的数据				isClearBtn: false,				toIndex: '', // 跳转的索引的字母				tipsLetter: '', // 滑动显示字母				timer: null,				hasNoData: false,				searchFocus: false,				letterDetails: [],				currentLetter: 'area', //默认选择				cityArr: [],				recordList: [],				cityList: [],				hasLocation: false,				myCityObj: {},				alphabet: [],				iStatusBarHeight: '',				lng: '',				lat: '',				cityname: '',				cityCode: '',				citydw: {					name: '',					citycode: '',				}			};		},		mounted() {			this.iStatusBarHeight = uni.getSystemInfoSync().statusBarHeight;			this.cityArr = cityJson.data.list			if (this.cityArr && this.cityArr[0]) {				this.cityArr.map(v => {					v.nameType = v.pinyin.substr(0, 1)				})				this.cityList = this.groupArr(this.cityArr, 'nameType')			}			this.recordList = cityJson.data.recordList			this.alphabet = cityJson.data.alphabet			this.getLocation()		},		watch: {			// 城市搜索输入框			inputValue(newVal) {				this.isClearBtn = newVal ? true : false;				if (this.timer) {					clearTimeout(this.timer);				}				if (!this.inputValue) {					this.searchData = [];					return;				}				this.timer = setTimeout(() => {					const result = [];					this.cityList.map(v => {						v.list.forEach((item) => {							if (/^[a-zA-Z]+$/.test(item.pinyin) && item.pinyin.toLowerCase()								.includes(this.inputValue.toLowerCase()) ||								item.name.includes(this.inputValue)) {								result.push(item);							}						});					})					this.searchData = result;					if (this.searchData.length === 0) {						this.hasNoData = true;					} else {						this.hasNoData = false;					}				}, 500);			},			isReach(val) {				this.searchFocus = val;			},		},		methods: {			againDingWei(){				uni.showModal({					title:'重新获取位置',					success() {											}				})				this.getLocation();			},			getLocation() {								const that = this				/* uni.getLocation({					// #ifdef MP-ALIPAY					type: 'gcj02',					// #endif					success(res) {						console.log('---',res)						res.name = res.city						res.citycode = res.cityAdcode						that.myCityObj = res						that.hasLocation = true						uni.setStorageSync('nowCityObj', res)					},					fail(err) {						that.hasLocation = false						uni.showToast({							icon:'none',							title: '重新定位失败,请稍后重试'						})					},				}) */				console.log("定位")				uni.getLocation({					type: 'gcj02',					success: function(res) {						console.log(res)						that.lng = res.longitude						that.lat = res.latitude						that.getAdress();					},					fail(err) {						console.log(err)						// that.cityname = uni.getStorageSync("location").cityname;						// that.citydw.name = uni.getStorageSync("location").cityname						// that.citydw.citycode = uni.getStorageSync("location").cityCode						uni.showToast({							icon:'none',							title: '重新定位失败,请稍后重试'						})					}				});			},			getAdress() {				var location = this.lng + ',' + this.lat				uni.request({					url: 'https://restapi.amap.com/v3/place/around', //仅为示例,并非真实接口地址。					data: {						key: '064b6a4a8ade55656edcde2f528876de',						location: location,						types: "190000",						extensions: "all",						radius: 100					},					dataType: "json",					success: (res) => {						console.log(res);						this.cityname = res.data.pois[0].cityname;						var cityCode = res.data.pois[0].adcode						cityCode = cityCode.slice(0, -2)						cityCode = cityCode + '00'						this.cityCode = cityCode						this.citydw.name = this.cityname						this.citydw.citycode = this.cityCode					}				});			},			groupArr(list, field) {				var fieldList = [],					att = [];				list.map((e) => {					fieldList.push(e[field])				})				//数组去重				fieldList = fieldList.filter((e, i, self) => {					return self.indexOf(e) == i				})				for (var j = 0; j < fieldList.length; j++) {					//过滤出匹配到的数据					var arr = list.filter((e) => {						return e[field] == fieldList[j];					})					att.push({						nameType: arr[0].nameType,						list: arr					})				}				return att;			},			selectCity(item, type) {				if (type === 'refresh' && !this.hasLocation) {					// 获取定位					return this.getLocation()				}				// console.log('选择的城市:', item);				uni.setStorageSync('myCityObj', item)				this.$emit('selectCity', item)				// 当前项目是需要选择到区域,所以选择城市后回到区县的地方				this.toIndex = 'area';				setTimeout(() => {					this.toIndex = '';				}, 1000);			},			closeModal() {				this.$emit('closeModal')			},			//列表滚动,和右边字母表对应			scrollHandle(e) {				let view = uni.createSelectorQuery().in(this).selectAll('.list-item');				view					.boundingClientRect((d) => {						let top = d[0].top;						d.forEach((item) => {							item.top = item.top - top;							item.bottom = item.bottom - top;							this.letterDetails.push({								id: item.id,								top: item.top,								bottom: item.bottom,							});						});					})					.exec();				const scrollTop = e.detail.scrollTop;				this.letterDetails.some((item) => {					if (scrollTop >= item.top && scrollTop <= item.bottom - 20) {						this.currentLetter = item.id;						//当前固定用的是粘性定位,如果不用粘性定位,在这里设置						return true;					}				});			},			//搜索			searchChange(e) {				let {					value				} = e.detail;				this.inputValue = value;			},			// 触发开始			touchStart(e) {				// console.log(e);			},			//移动时			touchMove(e) {				uni.vibrateShort();				let y = e.touches[0].clientY;				let offsettop = e.currentTarget.offsetTop;				//判断选择区域,只在选择区才会生效				if (y > offsettop) {					let num = parseInt((y - offsettop) / 15); //右边每个字母元素的高度					let letter = this.alphabet[num];					this.tipsLetter = letter;					let curentLetter = this.letterTransform(letter);					uni.showToast({						title: curentLetter,						icon: 'none',					});				}			},			//触发结束			touchEnd() {				this.toIndex = this.tipsLetter;			},			//移动开始获取字母,并放大提示			getLetter(e) {				uni.vibrateShort();				let {					id				} = e.currentTarget;				this.tipsLetter = id;				let curentLetter = this.letterTransform(id);				uni.showToast({					title: curentLetter,					icon: 'none',				});			},			//移动结束设置字母,赋值到toIndex			setLetter() {				this.toIndex = this.tipsLetter;			},			//提示字母转换			letterTransform(letter) {				let str = '';				if (letter == 'area') {					str = '当前';				} else if (letter == 'record') {					str = '历史';				} else {					str = letter;				}				return str;			},		},	}</script><style lang="less" scoped>	.chose-city {		position: fixed;		top: 0;		left: 0;		right: 0;		bottom: 0;		z-index: 999;		background: #fff;	}	.city-search-wrap {		width: 100%;		box-sizing: border-box;		.search {			width: 750rpx;			height: 110rpx;			display: flex;			align-items: center;			font-size: 28rpx;			color: #222;			padding: 14rpx 36rpx;			box-sizing: border-box;			background: #fff;			.l-search {				width: 597rpx;				position: relative;				height: 72rpx;				line-height: 72rpx;				.icon-search {					font-size: 28rpx;					position: absolute;					left: 0rpx;					top: 0;					color: #8e8f97;					font-weight: 700;					height: 72rpx;					line-height: 72rpx;				}				.cuIcon-search {					width: 40rpx;					height: 40rpx;					padding: 20rpx;				}				.input-search {					width: 597rpx;					height: 72rpx;					box-sizing: border-box;					padding: 0 84rpx 0 84rpx;					text-align: left;					background: #f4f5f9;					border-radius: 12rpx;					border: 0;				}				.clear-input {					font-size: 30rpx;					position: absolute;					right: 10rpx;					top: 50%;					transform: translateY(-50%);					padding: 10rpx;					color: #8e8f97;				}			}			.r-cancel {				width: 80rpx;				box-sizing: border-box;				padding-left: 24rpx;				font-size: 28rpx;				height: 72rpx;				line-height: 72rpx;				background: transparent;				border: 0;				color: #519AD2;			}		}	}	.reach-content {		padding-left: 36rpx;		box-sizing: border-box;		.li {			width: 714rpx;			font-size: 28rpx;			height: 100rpx;			line-height: 100rpx;			color: #333;			position: relative;			box-sizing: border-box;			border-bottom: 2rpx solid #F5F5F5;		}	}	.block {		// padding: 0 36rpx;		padding-left: 36rpx;		padding-right: 20rpx;		box-sizing: border-box;	}	.top-search {		line-height: 72rpx;		padding: 14rpx 30rpx 0;		box-sizing: border-box;		margin-bottom: 26rpx;		.item {			background: #F5F5F5;			border-radius: 12rpx;			font-size: 28rpx;			text-align: center;			color: #999999;			/* #ifdef MP-ALIPAY */			height: 72rpx;			line-height: 72rpx;			/* #endif */			text {				padding-left: 20rpx;				color: #c1c2cd;				vertical-align: middle;				position: relative;				top: -4rpx;			}		}	}	.scroll-view {		width: 100%;		height: calc(100vh - 110rpx);		box-sizing: border-box;	}	.area {		margin-bottom: 8rpx;		.title-wrapp {			position: sticky;			top: 0;			left: 0;			background: #fff;		}		.c-title {			width: 100%;			box-sizing: border-box;			font-size: 28rpx;			color: #999999;			margin-bottom: 24rpx;			display: inline-flex;			justify-content: space-between;			align-items: center;			.r {				font-size: 24rpx;				color: #8e8f97;				display: inline-block;				align-items: center;				.iconfont {					font-size: 24rpx;				}			}		}		.dingweiCity {			background-color: #F4F5F7;			border-radius: 49rpx;			width: 140rpx;			height: 64rpx;			text-align: center;			line-height: 64rpx;			font-size: 26rpx;		}		.ul {			display: flex;			flex-wrap: wrap;			justify-content: space-between;			.li {				width: 155rpx;				padding: 0 10rpx;				box-sizing: border-box;				height: 72rpx;				line-height: 68rpx;				text-align: center;				font-size: 32rpx;				color: #333;				border-radius: 8rpx;				margin: 0 18rpx 28rpx 0;				// border: 2rpx solid #E2E2E2;				&:nth-child(4n) {					margin-right: 0;				}				&.now {					width: auto;					padding: 0 32rpx 0 22rpx;					.icon {						width: 33rpx;						height: 33rpx;						background-size: 100%;						vertical-align: middle;						position: relative;						top: -4rpx;					}					.text {						padding-left: 10rpx;						color: #3F90F7;						font-size: 26rpx;					}				}				&.active {					font-weight: 500;					background: #ffde45;				}			}			.hover {				background: #ffde45;			}		}	}	.city-list {		width: 750rpx;		padding-bottom: 50rpx;		.c-title {			height: 60rpx;			line-height: 60rpx;			font-size: 30rpx;			font-weight: 500;			color: #272636;			background: #fff;			box-sizing: border-box;			padding-left: 36rpx;			position: sticky;			top: 0;			left: 0;			z-index: 2;		}		.item {			width: 714rpx;			margin-left: 36rpx;			padding: 0 36rpx 0 0;			height: 100rpx;			line-height: 100rpx;			color: #333;			font-size: 28rpx;			box-sizing: border-box;			border-bottom: 2rpx solid #F5F5F5;		}	}	.alphabet {		position: fixed;		right: 0;		bottom: 12%;		width: calc(750rpx - 680rpx);		text-align: center;		font-size: 20rpx;		font-weight: 700;		color: #8e8f97;		z-index: 99;		.item {			height: 15px;			line-height: 15px;		}		.active {			color: #222;		}	}	.has-no-data {		font-size: 24rpx;		text-align: center;		color: #8e8f97;		margin-top: 50rpx;	}	.nav {		height: 44px;		line-height: 44px;		text-align: center;		font-size: 26rpx;		color: #3C3C3C;		position: relative;	}	.foback {		position: absolute;		width: 15px;		height: 15px;		left: 24rpx;		top: 15px;	}	.dingBg{		display: flex;		align-items: center;		color: #3F90F7;		font-size: 26rpx;			}	.icon{		width: 33rpx;		height: 33rpx;		margin-right: 5rpx;	}</style>
 |