308 lines
8.6 KiB
Vue
308 lines
8.6 KiB
Vue
<template>
|
||
<view class="city-select-page" v-if="loading">
|
||
<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-if="searchRes.length === 0" class="list-item">暂无搜索结果</view>
|
||
<view v-else 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://static.hshuishang.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 hotCityList" class="city_name" :key="index"
|
||
@click="headerSelectMapClick(item)">{{ item.name }}</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>
|
||
<!-- 列表项 -->
|
||
<!-- TODO: 小程序编译避坑指南: -->
|
||
<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/area.js";
|
||
import { request, debounce, NavgateTo } from "../../utils/index.js";
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
location: {},
|
||
searchValue: "",
|
||
hotCities: [
|
||
"上海",
|
||
"北京",
|
||
"广州",
|
||
"杭州",
|
||
"成都",
|
||
"深圳",
|
||
"苏州",
|
||
"南京",
|
||
"重庆",
|
||
"西安",
|
||
"长沙",
|
||
"天津",
|
||
"三亚",
|
||
"厦门",
|
||
"武汉",
|
||
"无锡",
|
||
],
|
||
// 右侧字母列表
|
||
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",
|
||
],
|
||
activeId: "", // 当前高亮的字母区域 ID
|
||
activeLetter: "", // 当前高亮的字母
|
||
searchRes: [],
|
||
loading: false,
|
||
hotCityList: [], // 接口请求返回参数信息
|
||
groupedData: [], // 实际展示数据
|
||
|
||
};
|
||
},
|
||
onLoad() {
|
||
this.location = uni.getStorageSync("location");
|
||
this.init();
|
||
},
|
||
methods: {
|
||
headerSelectMapClick(item) {
|
||
console.log('1111 this', this);
|
||
console.log("地图选点", item);
|
||
const lat = Number(item.lat) || 0;
|
||
const long = Number(item.long) || 0;
|
||
uni.chooseLocation({
|
||
latitude: lat,
|
||
longitude: long,
|
||
success: (res) => {
|
||
console.log("打开地图选择商铺名称", res);
|
||
if (!res.name) {
|
||
uni.showToast({
|
||
title: "请选择具体城市信息",
|
||
icon: "none",
|
||
});
|
||
return;
|
||
}
|
||
// 更新页面数据,如标记点等
|
||
// 提取城市名称,添加防御性检查
|
||
let cityName = '';
|
||
let district = '';
|
||
let region = '';
|
||
|
||
// 提取城市名
|
||
const cityMatch = res.address.match(/(.*?(?:省|自治区)|^)(.*?)(?:市|地区|盟|州|县|区)?$/);
|
||
if (cityMatch && cityMatch[2]) {
|
||
const cityMatch2 = cityMatch[2].match(/(.*市)/);
|
||
if (cityMatch2 && cityMatch2[1]) {
|
||
cityName = cityMatch2[1];
|
||
}
|
||
}
|
||
|
||
// 提取区县
|
||
const districtMatch = res.address.match(/市(.*)/);
|
||
if (districtMatch && districtMatch[1]) {
|
||
district = districtMatch[1];
|
||
}
|
||
|
||
// 提取省市区
|
||
const regionMatch = res.address.match(/^(.*?省.*?(?:市|自治州|盟).*?(?:县|区|旗))/);
|
||
if (regionMatch && regionMatch[1]) {
|
||
region = regionMatch[1];
|
||
}
|
||
|
||
const selectLocation = {
|
||
cityName: cityName,
|
||
district: district,
|
||
lat: res.latitude,
|
||
lng: res.longitude,
|
||
region: region,
|
||
};
|
||
uni.setStorageSync("location", selectLocation); // 缓存数据信息
|
||
// uni.setStorageSync('city', selectLocation.cityName); // 缓存数据信息
|
||
console.log("location", selectLocation);
|
||
uni.navigateBack({
|
||
delta: 1,
|
||
});
|
||
},
|
||
fail: (err) => {
|
||
console.log("选择位置失败", err);
|
||
},
|
||
});
|
||
},
|
||
handleSearch: debounce(function (keyword) {
|
||
if (keyword === '') {
|
||
this.searchValue = '';
|
||
this.searchRes = [];
|
||
return;
|
||
}
|
||
|
||
uni.showLoading({
|
||
title: '加载中',
|
||
mask: true
|
||
})
|
||
request(apiArr.getRegionList, 'POST', {
|
||
short_name: keyword,
|
||
ad_level: 2,
|
||
|
||
}, { silent: false }).then((res) => {
|
||
console.log('搜索结果', res);
|
||
this.searchValue = keyword;
|
||
this.searchRes = res.rows || [];
|
||
uni.hideLoading();
|
||
})
|
||
}, 500),
|
||
|
||
groupData(item) {
|
||
console.log('123. item', item);
|
||
const map = {};
|
||
this.letters.forEach((letter) => {
|
||
map[letter] = {
|
||
letter,
|
||
list: [],
|
||
};
|
||
});
|
||
|
||
item.forEach((items) => {
|
||
if (map[items.letters]) {
|
||
map[items.letters].list.push(items);
|
||
}
|
||
});
|
||
console.log('11111111', map)
|
||
|
||
// 过滤掉没有数据的字母
|
||
this.groupedData = Object.values(map).filter(
|
||
(group) => group.list.length > 0
|
||
);
|
||
uni.hideLoading();
|
||
this.loading = true;
|
||
},
|
||
|
||
// 点击字母滚动到对应区域
|
||
scrollToLetter(letter) {
|
||
this.$nextTick(() => {
|
||
this.activeId = "group-" + letter;
|
||
this.activeLetter = letter;
|
||
});
|
||
},
|
||
|
||
|
||
async init() {
|
||
uni.showLoading({
|
||
title: '加载中',
|
||
mask: true
|
||
})
|
||
const params = {
|
||
ad_level: 2
|
||
}
|
||
const res = await request(apiArr.getRegionList, 'POST', params, { silent: false });
|
||
// TODO: 数据量返回过于庞大,只获取所需信息,其他内容舍弃
|
||
const newRes = res.rows.map((item) => {
|
||
return {
|
||
lat: item.lat,
|
||
letters: item.letters,
|
||
long: item.long,
|
||
name: item.name,
|
||
}
|
||
})
|
||
console.log('111', newRes)
|
||
// this.cityList = newRes;
|
||
const hotsList = res.rows.filter((item) => item.hot === 2).map((item) => {
|
||
return {
|
||
lat: item.lat,
|
||
long: item.long,
|
||
name: item.name,
|
||
};
|
||
});
|
||
console.log('热门城市信息', hotsList);
|
||
this.hotCityList = hotsList;
|
||
await this.groupData(newRes);
|
||
},
|
||
|
||
// 滚动时监听当前位置
|
||
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;
|
||
}
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style>
|
||
@import url("./index.css");
|
||
</style>
|