ebike-ui/ebike-maintenance/pages/map/map-location.vue
2025-08-08 09:22:47 +08:00

353 lines
7.6 KiB
Vue

<template>
<view :style="{ width: '100%', height: height }">
<!-- 基础工具 -->
<view class="tool-location icon-style" @click="getLocation">
<uni-icons type="location" :size="toolIconSize"></uni-icons>
</view>
<!-- <view class="tool-refresh icon-style">
<uni-icons type="loop" :size="toolIconSize" @click="ajs"></uni-icons>
</view> -->
<view class="tool-top" v-show="isShowTab">
<view class="tab-wrapper">
<view
v-for="item in tabOption"
:key="item.value"
class="tab-item"
:style="{
borderColor: select.includes(item) ? '#3b80f8' : '#dcdcdc',
}"
@click="handleClickTab(item)"
>
<text :style="{ color: select.includes(item) ? '#3b80f8' : '' }">{{
item.label
}}</text>
<view class="tab-active-wrapper">
<uni-icons
v-show="select.includes(item)"
type="checkbox-filled"
size="16"
color="#3b80f8"
></uni-icons>
</view>
</view>
</view>
<view class="coordinateType-wrapper">
<view
v-for="it of coordinateTypeOption"
:key="it.value"
:style="{
color: coordinateTypeSelect.includes(it) ? '#3b80f8' : '',
}"
@click="handleCoordinateType(it)"
>
{{ it.label }}
</view>
</view>
</view>
<!-- 地图 -->
<map
id="mapRef"
ref="mapRef"
show-location
:style="{ width: '100%', height: height }"
:scale="scale"
:longitude="mapcenter.longitude"
:latitude="mapcenter.latitude"
:markers="markers"
:polygons="polygons"
:polyline="polylines"
@tap="ontap"
/>
</view>
</template>
<script setup>
import { ref, onMounted, getCurrentInstance } from "vue";
import { findIndex } from "lodash";
import AMapWX from "@/utils/amap-wx.130.js";
import * as map from "@/utils/map.js";
let tab_list = [
{
label: "定位",
value: "location",
},
{
label: "扫码点",
value: "scan",
},
{
label: "还车点",
value: "return",
},
{
label: "轨迹",
value: "track",
},
{
label: "基站定位",
value: "base",
},
];
var amapsdk = new AMapWX({
key: map.sdkKey,
});
const { height, lng, lat, iconPath, toolIconSize, isShowTab, tabList } =
defineProps({
/*容器高度*/
height: {
type: String,
default: "100vh",
},
/*经度*/
lng: {
type: Number,
default: 116.397128,
},
/*纬度*/
lat: {
type: Number,
default: 39.916527,
},
/*工具图标大小*/
toolIconSize: {
type: [String, Number],
default: "28",
},
/*是否显示地图tab*/
isShowTab: {
type: Boolean,
default: false, // 是否显示地图tab
},
/*地图tab列表 TODO:未开发自定义tab选择后的事件*/
tabList: {
type: Array,
default: () => [],
},
});
const emit = defineEmits(["change"]);
let mapContext = null;
const mapRef = ref("mapRef");
const mapcenter = ref({
longitude: null,
latitude: null,
});
const scale = ref(17);
const markers = ref([]);
const polylines = ref([]);
const polygons = ref([
// {
// points: [
// { longitude: 104.074085, latitude: 30.666171 },
// { longitude: 104.073085, latitude: 30.667171 },
// { longitude: 104.071085, latitude: 30.666171 },
// { longitude: 104.070085, latitude: 30.664171 },
// { longitude: 104.071085, latitude: 30.663171 },
// { longitude: 104.073085, latitude: 30.663171 },
// { longitude: 104.074085, latitude: 30.666171 },
// ],
// strokeWidth: 2,
// strokeColor: "#1791fc",
// fillColor: "#1791fc66",
// zIndex: 5,
// },
]);
const tabOption = tabList.length <= 0 ? ref(tab_list) : ref(tabList);
const coordinateTypeOption = ref([
{
label: "用户坐标",
value: "user",
},
{
label: "车辆坐标",
value: "vehicle",
},
]);
const select = ref([]);
const coordinateTypeSelect = ref([]);
const handleCoordinateType = (it) => {
const index = findIndex(coordinateTypeSelect.value, { value: it.value });
if (index === -1) {
coordinateTypeSelect.value.push(it);
} else {
coordinateTypeSelect.value.splice(index, 1);
}
};
const handleClickTab = (it) => {
const index = findIndex(select.value, { value: it.value });
if (index === -1) {
select.value.push(it);
} else {
select.value.splice(index, 1);
}
};
const getLocation = () => {
map.getLoalcation(mapContext, (res) => {
const { latitude, longitude } = res;
mapcenter.value = {
longitude: longitude,
latitude: latitude,
};
});
};
const ajs = () => {};
// 添加地图点位
const addMarker = (
marker,
options = {
isEmpty: true,
focus: true,
}
) => {
if (options.isEmpty) {
markers.value = [];
}
markers.value.push(
map.addMarker(
marker.id,
marker.longitude,
marker.latitude,
"bike-choose.png"
)
);
// 是否聚焦到新添加的点
if (options.focus) {
mapDirection(marker);
}
};
function mapDirection(marker) {
if (!marker || !marker.longitude || !marker.latitude) {
console.error("Invalid marker data");
return;
}
map.getLoalcation(mapContext, (res) => {
const { latitude: slat, longitude: slng } = res;
const options = {
mapsdk: amapsdk,
slng,
slat,
elng: marker.longitude,
elat: marker.latitude,
success: (res) => {
let { arrPoint, distance } = res;
mapContext.includePoints({
points: arrPoint,
padding: [50, 50, 50, 50], // 视野边缘与点的间距
success: () => {
polylines.value = [map.addLine("#1082FF", arrPoint)];
},
});
},
fail: (res) => {
console.log("fail", res);
},
};
map.direction(options);
});
}
onMounted(() => {
mapContext = uni.createMapContext("mapRef", getCurrentInstance());
// 初始化地图
if (mapContext) {
getLocation();
}
console.log("地图组件已加载", mapContext);
});
defineExpose({
addMarker,
});
</script>
<style lang="scss" scoped>
.icon-style {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
z-index: 100;
width: 60rpx;
height: 60rpx;
background-color: white;
border-radius: 50%;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
}
.tool-location {
left: 5%;
bottom: 15%;
}
.tool-refresh {
right: 5%;
bottom: 15%;
}
.tool-top {
position: absolute;
top: 20rpx;
left: 30rpx;
right: 30rpx;
padding: 20rpx;
background-color: white;
z-index: 100;
border-radius: 10rpx;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
.tab-wrapper {
width: 100%;
overflow-x: auto;
display: flex;
align-items: center;
gap: 12rpx;
.tab-item {
position: relative;
flex-shrink: 0;
padding: 10rpx 35rpx;
border: 1px solid #dcdcdc;
border-radius: 10rpx;
font-size: 26rpx;
color: #333;
white-space: nowrap;
.tab-active-wrapper {
position: absolute;
right: 8rpx;
bottom: 8rpx;
width: 20rpx;
height: 20rpx;
border-radius: 50%;
border: 1px solid #dcdcdc;
display: flex;
justify-content: center;
align-items: center;
}
}
}
.coordinateType-wrapper {
width: 100%;
overflow-x: auto;
display: flex;
align-items: center;
gap: 30rpx;
font-size: 26rpx;
margin-top: 25rpx;
}
}
</style>