uniapp-ZHSQ/pages/shopcity/shopcity.vue

313 lines
7.9 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://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 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>
<!-- 列表项 -->
<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 } 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("地图选点", 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: debounce(function(keyword) {
if(keyword === '') {
this.searchValue = '';
this.searchRes = [];
return;
}
uni.showLoading({
title: '加载中',
mask: true
})
request(apiArr.getRegionList, 'POST', {
short_name: keyword
}, { silent: false }).then((res) => {
console.log('搜索结果', res);
this.searchValue = keyword;
this.searchRes = res.rows || [];
uni.hideLoading();
})
}, 500),
groupData(item) {
const map = {};
this.letters.forEach((letter) => {
map[letter] = {
letter,
list: [],
};
});
item.forEach((items) => {
if (map[items.letters]) {
map[items.letters].list.push(items);
}
});
// 过滤掉没有数据的字母
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 res = await request(apiArr.getRegionList, 'POST', {}, { 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>