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.

517 lines
12 KiB

2 weeks ago
<template>
<view class="index-page">
6 days ago
<map :latitude="defaultMapCenter.latitude" :longitude="defaultMapCenter.longitude"
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>
6 days ago
<!-- <view class="rec-swiper">
<recruitment></recruitment>
6 days ago
</view> -->
<!-- 弹出层示例 -->
<popup-drawer :visible="showPopup" @update:visible="showPopup = $event" @close="onPopupClose">
<view class="popup-content">
6 days ago
<!-- <view class="popup-title">弹出层标题</view> -->
<view class="popup-body">
6 days ago
<template v-for="item in jobFromFactoryList">
<recruitment :dataSource="item"></recruitment>
<view class="driver"></view>
</template>
</view>
</view>
</popup-drawer>
2 weeks ago
</view>
</template>
<script setup>
import {
ref,
computed
} from 'vue';
import {
onLoad
} from '@dcloudio/uni-app'
import {
6 days ago
factoryMapGetJobById,
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);
6 days ago
const defaultMapCenter = ref({
latitude: null,
longitude: null
})
// 距离范围选择相关数据
const showDistancePicker = ref(false);
const selectedDistance = ref(1); // 默认1km
const distanceValue = ref(0);
6 days ago
// 弹出层相关数据
const showPopup = ref(false);
6 days ago
const jobFromFactoryList = ref([])
// 距离范围数据
const distanceData = ref([{
label: '1',
value: 1
},
{
label: '5',
value: 5
},
{
label: '10',
value: 10
},
{
label: '50',
value: 50
},
{
label: '100',
value: 100
2 weeks ago
},
{
label: '500',
value: 500
}
]);
// 省份数据
const regionData = ref([{
label: '江苏省',
value: '江苏省'
},
{
label: '浙江省',
value: '浙江省'
}
]);
// 从本地存储读取省份信息
const getStoredRegionInfo = () => {
try {
const storedRegion = uni.getStorageSync('selectedRegionInfo');
if (storedRegion) {
6 days ago
return storedRegion;
}
} catch (e) {
console.error('读取本地存储的地区信息失败', e);
}
return null;
};
// 保存省份信息到本地存储
6 days ago
const setStoredRegionInfo = (value) => {
try {
6 days ago
uni.setStorageSync('selectedRegionInfo', value);
} 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;
// 保存地区信息到本地存储
6 days ago
setStoredRegionInfo(province.value);
// 更新地图数据
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
}
6 days ago
const markers = ref([/* {
id: 1,
latitude: 31.230416,
longitude: 121.473701,
title: '默认点位1',
iconPath: '/static/position-icon.png',
width: 30,
height: 30,
label: {
content: '默认点位1',
textAlign: 'center',
fontSize: 18,
}
2 weeks ago
},
{
6 days ago
id: 2,
latitude: 31.230416,
longitude: 121.473701,
title: '默认点位2',
iconPath: '/static/position-icon.png',
width: 30,
height: 30,
label: {
content: '默认点位2',
textAlign: 'center',
fontSize: 18,
}
6 days ago
} */
])
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'
})
2 weeks ago
}
} finally {
uni.hideLoading()
2 weeks ago
}
}
// 弹出层关闭处理
const onPopupClose = () => {
showPopup.value = false;
}
6 days ago
const onPopupOpen = () => {
showPopup.value = true
}
const onMarkerTap = async (e) => {
const markerId = e.markerId;
6 days ago
console.log(e)
onPopupOpen()
if (!(userLatLng.lat && userLatLng.lng)) {
userLatLng = await getLatLng()
}
const params = {
...(userLatLng.lat && userLatLng.lng ? userLatLng : {}),
}
try {
const res = await factoryMapGetJobById(markerId)
console.log(res)
jobFromFactoryList.value = res.data
} catch (err) {
console.log(err)
}
}
const handleMapLoad = async () => {
// 确保获取到用户位置
if (!(userLatLng.lat && userLatLng.lng)) {
userLatLng = await getLatLng();
}
// 如果成功获取到位置,设置地图中心点为用户位置
if (userLatLng.lat && userLatLng.lng) {
// 获取地图上下文
// const mapContext = uni.createMapContext('myMap');
defaultMapCenter.value = {
latitude: userLatLng.lat,
longitude: userLatLng.lng
}
// 设置地图中心点为用户位置
/* mapContext.includePoints({
points: [{latitude: userLatLng.lat, longitude: userLatLng.lng}],
padding: [100, 100, 100, 100] // 边距,防止点位贴边
}); */
console.log('地图视角已设置为用户当前位置');
} else {
console.log('无法获取用户位置,使用默认视角');
}
}
6 days ago
onLoad(() => {
// 从本地存储读取地区信息
const storedRegion = getStoredRegionInfo();
if (storedRegion) {
// 使用存储的地区信息
6 days ago
selectedRegion.value = storedRegion;
handleGetFactoryList(storedRegion);
} else {
// 使用默认地区信息
handleGetFactoryList();
}
})
2 weeks ago
</script>
<style lang="scss">
.index-page {
height: 100vh;
overflow: hidden;
position: relative;
6 days ago
.driver {
width: 100%;
height: 1px;
background-color: #eee;
}
.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;
}
2 weeks ago
.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);
}
6 days ago
.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;
}
6 days ago
.popup-content {
6 days ago
// padding: 20rpx;
}
6 days ago
.popup-title {
font-size: 36rpx;
font-weight: bold;
text-align: center;
margin-bottom: 30rpx;
}
6 days ago
.popup-body {
font-size: 28rpx;
line-height: 1.6;
6 days ago
box-sizing: border-box;
// padding: 15rpx;
}
2 weeks ago
}
</style>