You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

472 lines
10 KiB

<template>
<view class="index-page">
<map style="height: 100vh; width: 100vw;" id="myMap" :markers="markers" show-location show-compass
@updated="handleMapLoad" @markertap="onMarkerTap"></map>
<view class="selectors-group">
<view class="distance-selector" @click="openDistancePicker">
<text class="distance-text">{{ selectedDistance }}km </text>
</view>
<view class="region-selector" @click="openRegionPicker">
<text class="region-text">{{ selectedRegion }} </text>
</view>
</view>
<!-- 省份选择器 -->
<view class="region-picker-modal" v-if="showRegionPicker">
<view class="picker-header">
<text class="cancel-btn" @click="showRegionPicker = false">取消</text>
<text class="confirm-btn" @click="confirmRegion">确定</text>
</view>
<picker-view class="region-picker" :value="regionValue" immediate-change @change="onRegionChange">
<picker-view-column>
<view class="picker-item" v-for="(province, index) in regionData" :key="index">
{{ province.label }}
</view>
</picker-view-column>
</picker-view>
</view>
<!-- 距离范围选择器 -->
<view class="distance-picker-modal" v-if="showDistancePicker">
<view class="picker-header">
<text class="cancel-btn" @click="showDistancePicker = false">取消</text>
<text class="confirm-btn" @click="confirmDistance">确定</text>
</view>
<picker-view class="distance-picker" :value="distanceValue" immediate-change @change="onDistanceChange">
<picker-view-column>
<view class="picker-item" v-for="(distance, index) in distanceData" :key="index">
{{ distance.label }}km
</view>
</picker-view-column>
</picker-view>
</view>
<view class="rec-swiper">
<recruitment></recruitment>
</view>
<!-- 弹出层示例 -->
<popup-drawer :visible="showPopup" @update:visible="showPopup = $event" @close="onPopupClose">
<view class="popup-content">
<view class="popup-title">弹出层标题</view>
<view class="popup-body">
<p>这是弹出层的内容区域</p>
<p>你可以在这里放置任何内容</p>
<p>按住顶部拖拽区域可以上拉至全屏</p>
<p>向下拉动可以关闭弹出层</p>
</view>
</view>
</popup-drawer>
<!-- 触发按钮 -->
<view class="trigger-button" @click="showPopup = true">
打开弹出层
</view>
</view>
</template>
<script setup>
import {
ref,
computed
} from 'vue';
import {
onLoad
} from '@dcloudio/uni-app'
import {
factoryMapGetListPage
} from '../../api';
import {
delay,
getLatLng
} from '../../utils';
import PopupDrawer from '../../components/popup-drawer/popup-drawer.vue';
// 省份选择相关数据
const showRegionPicker = ref(false);
const selectedRegion = ref('江苏省');
const regionValue = ref(0);
// 距离范围选择相关数据
const showDistancePicker = ref(false);
const selectedDistance = ref(1); // 默认1km
const distanceValue = ref(0);
// 弹出层相关数据
const showPopup = ref(false);
// 距离范围数据
const distanceData = ref([{
label: '1',
value: 1
},
{
label: '5',
value: 5
},
{
label: '10',
value: 10
},
{
label: '50',
value: 50
},
{
label: '100',
value: 100
},
{
label: '500',
value: 500
}
]);
// 省份数据
const regionData = ref([{
label: '江苏省',
value: '江苏省'
},
{
label: '浙江省',
value: '浙江省'
}
]);
// 从本地存储读取省份信息
const getStoredRegionInfo = () => {
try {
const storedRegion = uni.getStorageSync('selectedRegionInfo');
if (storedRegion) {
return JSON.parse(storedRegion);
}
} catch (e) {
console.error('读取本地存储的地区信息失败', e);
}
return null;
};
// 保存省份信息到本地存储
const setStoredRegionInfo = (province, label) => {
try {
const regionInfo = {
province,
label
};
uni.setStorageSync('selectedRegionInfo', JSON.stringify(regionInfo));
} catch (e) {
console.error('保存地区信息到本地存储失败', e);
}
};
const openRegionPicker = () => {
showRegionPicker.value = true;
};
const openDistancePicker = () => {
showDistancePicker.value = true;
};
// 省份选择器变化事件
const onRegionChange = (e) => {
const values = e.detail.value;
console.log(values)
regionValue.value = values;
};
// 距离范围选择器变化事件
const onDistanceChange = (e) => {
const values = e.detail.value;
distanceValue.value = values;
};
// 确认选择省份
const confirmRegion = () => {
const provinceIndex = regionValue.value[0];
const province = regionData.value[provinceIndex];
selectedRegion.value = province.label;
console.log(selectedRegion.value)
console.log(selectedRegion.value)
showRegionPicker.value = false;
// 保存地区信息到本地存储
setStoredRegionInfo(province.label);
// 更新地图数据
handleGetFactoryList(province.label);
};
// 确认选择距离范围
const confirmDistance = () => {
const distanceIndex = distanceValue.value[0];
const distance = distanceData.value[distanceIndex];
selectedDistance.value = distance.value;
showDistancePicker.value = false;
// 重新加载数据
handleGetFactoryList(selectedRegion.value);
};
let userLatLng = {
lat: null,
lng: null
}
const markers = ref([
{
id: 'default1',
latitude: 31.230416,
longitude: 121.473701,
title: '默认点位1',
iconPath: '/static/position-icon.png',
width: 30,
height: 30,
label: {
content: '默认点位1',
textAlign: 'center',
fontSize: 18,
}
},
{
id: 'default2',
latitude: 31.230416,
longitude: 121.473701,
title: '默认点位2',
iconPath: '/static/position-icon.png',
width: 30,
height: 30,
label: {
content: '默认点位2',
textAlign: 'center',
fontSize: 18,
}
}
])
const handleGetFactoryList = async (province = '江苏省') => {
uni.showLoading({
title: '加载中'
});
if (!(userLatLng.lat && userLatLng.lng)) {
userLatLng = await getLatLng()
}
try {
const params = {
...(userLatLng.lat && userLatLng.lng ? userLatLng : {}),
province: province,
maxDistance: selectedDistance.value * 1000 // 转换为米
}
await delay(500)
const {
data
} = await factoryMapGetListPage(params)
// 清空之前的markers,但保留前两个默认的模拟点位
markers.value = markers.value.slice(0, 2);
data.records.map(item => markers.value.push({
id: item.id,
latitude: item.lat,
longitude: item.lng,
title: item.factoryName,
iconPath: '/static/position-icon.png',
width: 30,
height: 30,
label: {
content: item.factoryName,
textAlign: 'center',
fontSize: 18,
}
}))
console.log(await markers.value)
} catch (err) {
if (!(userLatLng.lat && userLatLng.lng)) {
uni.showToast({
title: '经纬度获取失败',
icon: 'none'
})
} else {
uni.showToast({
title: '位置获取失败',
icon: 'none'
})
}
} finally {
uni.hideLoading()
}
}
// 弹出层关闭处理
const onPopupClose = () => {
showPopup.value = false;
}
const onMarkerTap = (e) => {
const markerId = e.markerId;
console.log(markerId)
}
onLoad(() => {
// 从本地存储读取地区信息
const storedRegion = getStoredRegionInfo();
if (storedRegion) {
// 使用存储的地区信息
selectedRegion.value = storedRegion.label;
handleGetFactoryList(storedRegion.province);
} else {
// 使用默认地区信息
handleGetFactoryList();
}
})
</script>
<style lang="scss">
.index-page {
height: 100vh;
overflow: hidden;
position: relative;
.selectors-group {
position: absolute;
top: 25rpx;
right: 20rpx;
display: flex;
flex-direction: row-reverse;
gap: 6rpx;
z-index: 999;
}
.region-selector {
background-color: rgba(255, 255, 255, 0.9);
padding: 15rpx 25rpx;
border-radius: 15rpx;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
.region-text {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
}
.distance-selector {
background-color: rgba(255, 255, 255, 0.9);
padding: 15rpx 25rpx;
border-radius: 15rpx;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
.distance-text {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
}
/* 省市区选择器样式 */
.region-picker-modal {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 500rpx;
background-color: #fff;
z-index: 1000;
}
/* 距离范围选择器样式 */
.distance-picker-modal {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 500rpx;
background-color: #fff;
z-index: 1000;
}
.picker-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 30rpx;
border-bottom: 1rpx solid #eee;
}
.cancel-btn,
.confirm-btn {
font-size: 32rpx;
padding: 10rpx 20rpx;
}
.cancel-btn {
color: #999;
}
.confirm-btn {
color: #007AFF;
}
.region-picker,
.distance-picker {
height: 400rpx;
width: 100%;
}
.picker-item {
display: flex;
align-items: center;
justify-content: center;
height: 80rpx;
line-height: 80rpx;
text-align: center;
font-size: 30rpx;
}
.rec-swiper {
width: calc(100% - 16px);
// height: 200px;
// background-color: red;
background-color: #FFF;
margin: 0 8px;
position: absolute;
left: 0px;
bottom: 8px;
border-radius: 16px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.trigger-button {
position: fixed;
bottom: 120rpx;
left: 50%;
transform: translateX(-50%);
background-color: #007AFF;
color: white;
padding: 20rpx 40rpx;
border-radius: 50rpx;
font-size: 28rpx;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
z-index: 998;
}
.popup-content {
padding: 20rpx;
}
.popup-title {
font-size: 36rpx;
font-weight: bold;
text-align: center;
margin-bottom: 30rpx;
}
.popup-body {
font-size: 28rpx;
line-height: 1.6;
}
.popup-body p {
margin-bottom: 20rpx;
}
}
</style>