uniapp-ZHSQ/pages/shopcity/shopcity.vue
2025-06-30 08:37:35 +08:00

305 lines
7.6 KiB
Vue

<template>
<view class="city-select-page">
<view class="white_container padding_bottom40">
<!-- 搜索框 -->
<u-search placeholder="输入城市进行搜索" :value="searchValue" @search="handleSearch" @change="handleSearch"
:showAction=false height="70" searchIconSize="40" shape="round"></u-search>
<view v-if="searchValue" class="search_popup">
<view v-for="(item, index) in searchRes" :key="index"
:class="['list-item', index === searchRes.length - 1 && 'no_border']"
@click="headerSelectMapClick(item)">
{{ item.name }}
</view>
</view>
<view v-if="!searchValue">
<!-- 当前定位城市 -->
<view class="current-city">
<image src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/Index_add.png" mode="widthFix" />
<text>当前定位城市 {{ location.cityName }}</text>
</view>
<!-- 国内热门城市 -->
<view class="hot-cities">
<text class="title">国内热门城市</text>
<view class="city-list">
<view v-for="(item, index) in hotCities" class="city_name" :key="index"
@click="headerSelectMapClick(item)">{{ item }}</view>
</view>
</view>
</view>
</view>
<view v-if="!searchValue" class="container">
<!-- 左侧列表 -->
<scroll-view class="list-scroll" scroll-y :scroll-into-view="activeId" @scroll="handleScroll">
<view v-for="(group, index) in groupedData" :key="index" class="white_container"
:id="'group-' + group.letter">
<!-- 字母标题 -->
<view class="letter-title">{{ group.letter }}</view>
<!-- 列表项 -->
<view v-for="(item, ind) in group.list" :key="item.id"
:class="['list-item', ind === group.list.length - 1 && 'no_border']"
@click="headerSelectMapClick(item)">
{{ item.name }}
</view>
</view>
</scroll-view>
<!-- 右侧索引栏 -->
<view class="index-bar">
<view v-for="(letter, index) in letters" :key="index" class="index-item" @tap="scrollToLetter(letter)">
{{ letter }}
</view>
</view>
</view>
</view>
</template>
<script>
import {
apiArr
} from '../../api/community.js';
import { apiArr as areaApi } from '../../api/area.js';
import {
util,
picUrl,
request,
menuButtonInfo
} from '../../utils/index.js';
import {pinyin} from 'pinyin-pro';
console.log(pinyin('汉语拼音'),'zz');
export default {
data() {
return {
location: {},
searchValue: '',
currentCity: '衡水',
hotCities: ['上海', '北京', '广州', '杭州', '成都', '深圳', '苏州', '南京', '重庆', '西安', '长沙', '天津', '三亚', '厦门', '武汉', '无锡'],
rawData: [{
id: 1,
name: '阿巴嘎旗',
letters: 'A',
lat: '39.908823',
long: '116.39747',
},
{
id: 2,
name: '阿坝',
letters: 'A',
lat: '31.196322',
long: '121.339841'
},
{
id: 3,
name: '阿坝县',
letters: 'A',
},
{
id: 4,
name: '阿城区',
letters: 'A',
},
{
id: 5,
name: '阿尔山市',
letters: 'B',
},
{
id: 6,
name: '阿合奇县',
letters: 'B',
},
{
id: 7,
name: '阿克塞哈萨克族自治县',
letters: 'B',
},
{
id: 8,
name: '阿克苏地区',
letters: 'C',
},
{
id: 9,
name: '阿克苏市',
letters: 'D',
},
{
id: 10,
name: '阿拉尔',
letters: 'E',
},
],
letters: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z'
],
groupedData: [], // 分组后的数据
activeId: '', // 当前高亮的字母区域 ID
activeLetter: '',// 当前高亮的字母
searchRes: [
{
name: '河北,石家庄'
},
{
name: '河北,廊坊'
},
{
name: '河北,保定'
},
{
name: '河北,衡水'
},
{
name: '河北,沧州'
},
{
name: '河北,唐山'
},
],
proviceList: [],
cityList: []
}
},
onLoad(options) {
this.location = uni.getStorageSync('location');
this.getArea()
},
methods: {
headerSelectMapClick(item) {
console.log('地图选点', item);
const lat = Number(item.lat);
const long = Number(item.long);
uni.chooseLocation({
latitude: lat,
longitude: long,
success: (res) => {
console.log('打开地图选择商铺名称', res);
if (!res.name) {
uni.showToast({
title: '请选择具体城市信息',
icon: 'none'
});
return;
}
// 更新页面数据,如标记点等
const selectLocation = {
cityName: res.address.match(/(.*?(?:省|自治区)|^)(.*?)(?:市|地区|盟|州|县|区)?$/)[2].match(/(.*市)/)[1],
district: res.address.match(/市(.*)/)[1],
lat: res.latitude,
lng: res.longitude
};
uni.setStorageSync('location', selectLocation); // 缓存数据信息
// uni.setStorageSync('city', selectLocation.cityName); // 缓存数据信息
console.log('location', selectLocation);
uni.navigateBack({
delta: 1
});
},
fail: (err) => {
console.log('选择位置失败', err);
}
});
},
handleSearch(e) {
// 搜索逻辑,可以在这里根据 searchValue 过滤城市数据
this.searchValue = e;
console.log('搜ee索:', e);
},
groupData() {
const map = {};
this.letters.forEach(letter => {
map[letter] = {
letter,
list: []
};
});
this.rawData.forEach(item => {
if (map[item.letters]) {
map[item.letters].list.push(item);
}
});
console.log('112312313', Object.values(map).filter(group => group.list.length > 0))
// 过滤掉没有数据的字母
this.groupedData = Object.values(map).filter(group => group.list.length > 0);
},
// 点击字母滚动到对应区域
scrollToLetter(letter) {
this.$nextTick(() => {
this.activeId = 'group-' + letter;
this.activeLetter = letter;
});
},
// 滚动时监听当前位置
handleScroll(e) {
const query = uni.createSelectorQuery().in(this);
let activeLetter = '';
// 遍历每个字母区域,检查是否在可视范围内
this.letters.some(letter => {
query.select(`#group-${letter}`).boundingClientRect(rect => {
if (rect && rect.top <= 100 && rect.bottom >= 0) {
activeLetter = letter;
}
}).exec();
return activeLetter; // 找到第一个符合条件的字母后退出循环
});
if (activeLetter && activeLetter !== this.activeLetter) {
this.activeLetter = activeLetter;
}
},
getArea() {
let that = this
request(areaApi.getArea, "POST", {}).then(res => {
this.proviceList = res.rows
this.proviceList.forEach(item => {
that.getCity(item.ad_code)
})
})
},
getCity(e) {
request(areaApi.getArea, "POST", { parent_ad_code: e }).then(res => {
const citiesWithLetters = res.rows.map(city => {
const firstChar = city.ad_name.charAt(0);
// 检查是否是英文字母
if (/^[A-Za-z]$/.test(firstChar)) {
return { ...city, letters: firstChar.toUpperCase() };
}
// 使用 pinyin-pro 获取首个拼音并转为大写
const firstPinyin = pinyin(firstChar, { pattern: 'first', type: 'array',toneType:"none" });
const firstPinyinChar = firstPinyin[0] ? firstPinyin[0].toUpperCase() : '#';
// 验证转换结果是否为有效字母,无效则标记为 '#'
const letter = /^[A-Z]$/.test(firstPinyinChar) ? firstPinyinChar : '#';
if (letter === '#') {
console.log('当前城市', city.short_name);
}
return { ...city, letters: letter };
});
this.cityList = this.cityList.concat(citiesWithLetters);
});
},
},
}
</script>
<style>
@import url("./index.css");
</style>