|
|
|
|
<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>
|