366 lines
9.5 KiB
Vue
366 lines
9.5 KiB
Vue
<template>
|
||
<view class="container">
|
||
|
||
<!-- 城市列表 -->
|
||
<view v-show="!isReach">
|
||
<!-- 当前城市 -->
|
||
|
||
<!-- <u-gap height="8" bgColor="#F8F8F8"></u-gap> -->
|
||
<scroll-view class="scroll-view" scroll-y scroll-with-animation="true" enable-back-to-top="true"
|
||
:scroll-into-view="toIndex" @scroll="scrollHandle">
|
||
|
||
<!-- 城市列表 -->
|
||
<view class="city-list">
|
||
<view class="list list-item" v-for="(item, key) of resultObject" :key="key" :id="key">
|
||
<view class="title">{{ key }}</view>
|
||
<view class="item borderBottom" hover-class="hover" v-for="innerItem in item"
|
||
:key="innerItem.cityId" @click="selectCity(innerItem)"
|
||
style="width: 90%;display: flex;flex-wrap: nowrap; align-items: center;"
|
||
>
|
||
<view class="imagebox">
|
||
<image src=" https://file.langsi.online/yasiimg/web/static/udWNTRG6GulmTtgPRQ49"></image>
|
||
</view>
|
||
<view style="width: 50%;text-align: left;">{{ innerItem.spell }}</view>
|
||
</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 == "hot" ? "#" :item }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
isReach: false,
|
||
resultObject:{},
|
||
alphabet: [], //字母列表
|
||
toIndex: "", //跳转的索引的字母
|
||
tipsLetter: "", //滑动显示字母
|
||
timer: null,
|
||
hasNoData: false,
|
||
searchFocus: false,
|
||
letterDetails: [],
|
||
currentLetter: "地区" ,//默认选择hot
|
||
adress:"" //当前位置
|
||
};
|
||
},
|
||
watch: {
|
||
|
||
},
|
||
created() {
|
||
//真实数据请求...
|
||
this.generateNames()
|
||
},
|
||
onLoad(option) {
|
||
// this.areaName=option.name
|
||
},
|
||
methods: {
|
||
generateNames() {
|
||
// 生成随机中文名字
|
||
const familyNames = [
|
||
"赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋", "沈", "韩", "杨", "朱", "秦", "尤", "许", "何", "吕", "施", "张", "孔", "曹", "严", "华", "金", "魏", "陶", "姜", "戚", "谢", "邹", "喻", "柏", "水", "窦", "章", "云", "苏", "潘", "葛", "奚", "范", "彭", "郎", "鲁", "韦", "昌", "马", "苗", "凤"
|
||
];
|
||
const givenNames = [
|
||
"乐", "思", "彤", "悦", "欣", "怡", "雨", "晴", "静", "雅", "婷", "舒", "涵", "瑶", "蓉", "梦", "雪", "娜", "琳", "佳", "蕾", "琪", "媛", "璐"
|
||
];
|
||
|
||
const usedFirstLetters = []; // 已使用的首字母
|
||
const studentNames = [];
|
||
|
||
while (studentNames.length < 24) {
|
||
const familyIndex = Math.floor(Math.random() * familyNames.length);
|
||
const givenIndex = Math.floor(Math.random() * givenNames.length);
|
||
const firstName = familyNames[familyIndex];
|
||
const lastName = givenNames[givenIndex];
|
||
|
||
// 检查首字母是否已使用
|
||
const firstLetter = firstName.charAt(0);
|
||
if (!usedFirstLetters.includes(firstLetter)) {
|
||
usedFirstLetters.push(firstLetter);
|
||
const fullName = firstName + lastName;
|
||
studentNames.push(fullName);
|
||
}
|
||
}
|
||
|
||
this.studentNames = studentNames;
|
||
this.generateNameMap()
|
||
console.log('运行了');
|
||
},
|
||
generateNameMap() {
|
||
const nameMap = {};
|
||
const alphabet = [];
|
||
|
||
this.studentNames.forEach(fullName => {
|
||
const firstLetter = this.getEnglishFirstLetter(fullName.charAt(0));
|
||
|
||
if (!nameMap[firstLetter]) {
|
||
nameMap[firstLetter] = [];
|
||
alphabet.push(firstLetter);
|
||
}
|
||
|
||
nameMap[firstLetter].push({
|
||
"spell": fullName,
|
||
});
|
||
});
|
||
|
||
// 删除city和cityId字段
|
||
const sortedAlphabet = alphabet.sort();
|
||
const resultObject = {};
|
||
|
||
sortedAlphabet.forEach(key => {
|
||
resultObject[key] = nameMap[key].map(item => ({ "spell": item.spell }));
|
||
});
|
||
|
||
console.log(resultObject, 'resultObject');
|
||
console.log("alphabet:", sortedAlphabet);
|
||
this.alphabet=sortedAlphabet
|
||
this.resultObject=resultObject
|
||
this.alphabet.unshift('#');
|
||
// return resultArray;
|
||
},
|
||
|
||
getEnglishFirstLetter(chineseCharacter) {
|
||
const pinyin = this.simpleChineseToPinyin(chineseCharacter);
|
||
return pinyin.charAt(0).toUpperCase();
|
||
},
|
||
|
||
simpleChineseToPinyin(chineseCharacter) {
|
||
// 简单的中文转拼音的映射表
|
||
const pinyinMap = {
|
||
"赵": "zhao", "钱": "qian", "孙": "sun", "李": "li", "周": "zhou", "吴": "wu", "郑": "zheng", "王": "wang",
|
||
"冯": "feng", "陈": "chen", "褚": "zhu", "卫": "wei", "蒋": "jiang", "沈": "shen", "韩": "han", "杨": "yang",
|
||
"朱": "zhu", "秦": "qin", "尤": "you", "许": "xu", "何": "he", "吕": "lv", "施": "shi", "张": "zhang",
|
||
"孔": "kong", "曹": "cao", "严": "yan", "华": "hua", "金": "jin", "魏": "wei", "陶": "tao", "姜": "jiang",
|
||
"戚": "qi", "谢": "xie", "邹": "zou", "喻": "yu", "柏": "bai", "水": "shui", "窦": "dou", "章": "zhang",
|
||
"云": "yun", "苏": "su", "潘": "pan", "葛": "ge", "奚": "xi", "范": "fan", "彭": "peng", "郎": "lang",
|
||
"鲁": "lu", "韦": "wei", "昌": "chang", "马": "ma", "苗": "miao", "凤": "feng"
|
||
};
|
||
|
||
return pinyinMap[chineseCharacter] || chineseCharacter;
|
||
},
|
||
|
||
//列表滚动,和右边字母表对应
|
||
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;
|
||
}
|
||
});
|
||
},
|
||
|
||
|
||
|
||
|
||
//区域选择
|
||
selectRegion(item) {
|
||
console.log('选择的区域是:', item)
|
||
},
|
||
|
||
//触发开始
|
||
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",
|
||
duration: 1000
|
||
});
|
||
}
|
||
},
|
||
//触发结束
|
||
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",
|
||
duration: 1000
|
||
});
|
||
},
|
||
//移动结束设置字母,赋值到toIndex
|
||
setLetter() {
|
||
this.toIndex = this.tipsLetter;
|
||
},
|
||
|
||
//提示字母转换
|
||
letterTransform(letter) {
|
||
let str = "";
|
||
if (letter == "hot") {
|
||
str = "地区";
|
||
} else {
|
||
str = letter;
|
||
}
|
||
|
||
return str;
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.borderBottom {}
|
||
|
||
.reach-content {
|
||
padding-top: 60rpx;
|
||
|
||
.li {
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
padding: 20rpx 0;
|
||
position: relative;
|
||
}
|
||
}
|
||
|
||
.block {
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
.scroll-view {
|
||
width: 100%;
|
||
height: 918rpx;
|
||
background: #ffffff;
|
||
box-sizing: border-box;
|
||
border-radius: 20rpx 20rpx 0rpx 0rpx;
|
||
|
||
}
|
||
|
||
|
||
|
||
.city-list {
|
||
margin-top: 32rpx;
|
||
width: 677rpx;
|
||
padding-bottom: 50rpx;
|
||
|
||
|
||
.title {
|
||
// height: 60rpx;
|
||
|
||
font-size: 28rpx;
|
||
font-family: PingFang SC, PingFang SC;
|
||
font-weight: 800;
|
||
color: #2E4975;
|
||
// margin-bottom: 20rpx;
|
||
padding-left: 32rpx;
|
||
background-color: #fff;
|
||
position: sticky;
|
||
top: 0;
|
||
left: 0;
|
||
z-index: 2;
|
||
}
|
||
|
||
.item {
|
||
padding: 22rpx 0 18rpx 32rpx;
|
||
font-size: 24rpx;
|
||
font-family: PingFang SC, PingFang SC;
|
||
font-weight: 500;
|
||
color: #072F5A;
|
||
margin-bottom: 32rpx;
|
||
&::after {
|
||
left: 30rpx;
|
||
width: calc(100% - 30rpx);
|
||
background: #d2d2d2;
|
||
}
|
||
.imagebox{
|
||
margin-right: 20rpx;
|
||
width: 56rpx;
|
||
height: 56rpx;
|
||
}
|
||
}
|
||
|
||
.hover {
|
||
background: #f4f5f9;
|
||
|
||
&::after {
|
||
background: #f4f5f9;
|
||
}
|
||
}
|
||
}
|
||
|
||
.alphabet {
|
||
position: fixed;
|
||
right: 10rpx;
|
||
bottom: 15%;
|
||
width: calc(750rpx - 680rpx);
|
||
text-align: center;
|
||
font-size: 16rpx;
|
||
font-family: PingFang SC, PingFang SC;
|
||
font-weight: 500;
|
||
color: rgba(46,73,117,0.5);
|
||
|
||
|
||
.item {
|
||
height: 30rpx;
|
||
line-height: 30rpx;
|
||
margin: 6rpx 0;
|
||
}
|
||
|
||
.active {
|
||
color: #222;
|
||
}
|
||
}
|
||
|
||
.has-no-data {
|
||
font-size: 24rpx;
|
||
text-align: center;
|
||
color: #8e8f97;
|
||
margin-top: 50rpx;
|
||
}
|
||
</style>
|