<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('运行了',this.studentNames); }, 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>