update tag title

This commit is contained in:
cxc
2023-01-17 10:34:21 +08:00
parent 2772f5ade1
commit a09eab0d40
8 changed files with 523 additions and 187 deletions

View File

@ -1,4 +1,5 @@
import AMapLoader from "@amap/amap-jsapi-loader"; import AMapLoader from "@amap/amap-jsapi-loader";
import markBsPng from "@/assets/images/mark_bs.png";
// 初始化地图 // 初始化地图
export const loadAMap = async (plugins) => { export const loadAMap = async (plugins) => {
@ -27,3 +28,44 @@ export const loadAMap = async (plugins) => {
throw new Error("地图创建失败"); throw new Error("地图创建失败");
} }
}; };
export const searchPlace = ({ AMap, map, searchPlugin, keyword, events }) => {
if (events.beforeSearch) {
events.beforeSearch();
}
searchPlugin.search(keyword, (status, result) => {
if (status === "complete") {
const searchResultMarkers = result.poiList.pois.map((el, index) => {
const marker = new AMap.Marker({
map,
position: el.location,
anchor: "bottom-center",
extData: el,
content: `
<div
style="
background-image: url(${markBsPng});
width: 19px;
height: 31px;
background-size: cover;
color: #fff;
text-align: center;
font-size: 12px;
padding-top: 3px;
"
>
${index + 1}
</div>
`,
});
// marker.on("mouseover", handleResultHover);
// marker.on("click", handleResultClick);
// marker.on("mouseout", (ev) => {
// resultInfoWindow.value.close();
// });
return marker;
});
map.setFitView(searchResultMarkers);
}
});
};

View File

@ -257,6 +257,8 @@ function submitForm() {
onMounted(async () => { onMounted(async () => {
reset(); reset();
if (route.query.carId && route.query.uuid) { if (route.query.carId && route.query.uuid) {
const routerObj = Object.assign({}, route, { title: "车辆修改" });
tab.updatePage(routerObj);
const resp = await getInfo(route.query.carId, route.query.uuid); const resp = await getInfo(route.query.carId, route.query.uuid);
form.value = { form.value = {
...resp.data, ...resp.data,

View File

@ -212,6 +212,8 @@ function back() {
onMounted(async () => { onMounted(async () => {
reset(); reset();
if (route.query.driverId && route.query.uuid) { if (route.query.driverId && route.query.uuid) {
const routerObj = Object.assign({}, route, { title: "司机修改" });
tab.updatePage(routerObj);
const { data } = await getInfo(route.query.driverId, route.query.uuid); const { data } = await getInfo(route.query.driverId, route.query.uuid);
form.value = data; form.value = data;
} }

View File

@ -31,7 +31,13 @@
>搜索</el-button >搜索</el-button
> >
<!-- </el-col> --> <!-- </el-col> -->
<el-button type="primary" plain size="small">卫星模式</el-button> <el-button
type="primary"
plain
size="small"
@click="switchMapLayer"
>{{ isSatelliteMode ? "标准模式" : "卫星模式" }}</el-button
>
</el-row> </el-row>
</div> </div>
<div id="map-container"></div> <div id="map-container"></div>
@ -125,11 +131,10 @@
import tab from "@/plugins/tab"; import tab from "@/plugins/tab";
import { onMounted } from "vue"; import { onMounted } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
// import AMapLoader from "@amap/amap-jsapi-loader"; import { loadAMap } from "@/utils/map";
import { addFence, updateFence, getFence } from "@/api/fence";
import markBsPng from "@/assets/images/mark_bs.png"; import markBsPng from "@/assets/images/mark_bs.png";
import mapPinPng from "@/assets/images/map-pin.png"; import mapPinPng from "@/assets/images/map-pin.png";
import { loadAMap } from "@/utils/map"; import { addFence, updateFence, getFence } from "@/api/fence";
const route = useRoute(); const route = useRoute();
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
@ -137,9 +142,12 @@ const AMap = shallowRef(null);
const map = shallowRef(null); const map = shallowRef(null);
const placeSearch = shallowRef(null); const placeSearch = shallowRef(null);
const searchResultMarkers = shallowRef([]); // 搜索结果表笔列表 const searchResultMarkers = shallowRef([]); // 搜索结果表笔列表
const satelliteLayer = shallowRef(null);
const isSatelliteMode = ref(false);
const turningPointMarker = shallowRef([]); const turningPointMarker = shallowRef([]);
const resultInfoWindow = shallowRef(null); const resultInfoWindow = shallowRef(null);
const fencePolygon = shallowRef(null); const fencePolygon = shallowRef(null);
const searchKeyword = ref(""); const searchKeyword = ref("");
const data = reactive({ const data = reactive({
form: {}, form: {},
@ -163,17 +171,15 @@ const data = reactive({
const { form, rules } = toRefs(data); const { form, rules } = toRefs(data);
const handleMapClick = (ev) => { const addFencePath = (lnglat) => {
if (map.value.getAllOverlays("polygon").length === 0) { if (map.value.getAllOverlays("polygon").length === 0) {
map.value.add(fencePolygon.value); map.value.add(fencePolygon.value);
} }
form.value.fencePath.push(lnglat);
form.value.fencePath.push(ev.lnglat);
turningPointMarker.value.push( turningPointMarker.value.push(
new AMap.value.Marker({ new AMap.value.Marker({
map: map.value, map: map.value,
position: ev.lnglat, position: lnglat,
content: ` content: `
<div <div
style=" style="
@ -201,14 +207,24 @@ const handleMapClick = (ev) => {
el.show(); el.show();
}); });
} }
fencePolygon.value.setPath( fencePolygon.value.setPath(form.value.fencePath);
// AMap.value.GeometryUtil.makesureClockwise(
// form.value.fencePath.map((el) => new AMap.value.LngLat(el.lng, el.lat))
form.value.fencePath
// )
);
}; };
const handleResultClick = (ev) => { const handleMapClick = (ev) => {
addFencePath(ev.lnglat);
};
const switchMapLayer = () => {
if (isSatelliteMode.value) {
map.value.remove(satelliteLayer.value);
isSatelliteMode.value = false;
} else {
map.value.add([satelliteLayer.value]);
isSatelliteMode.value = true;
}
};
// 鼠标悬停搜索结果标记
const handleResultHover = (ev) => {
resultInfoWindow.value.setContent(` resultInfoWindow.value.setContent(`
<div> <div>
${ev.target.getExtData().name}</div> ${ev.target.getExtData().name}</div>
@ -221,13 +237,13 @@ const searchPoint = (val /** 搜索建议选项 */, type) => {
form.value.fencePath = []; form.value.fencePath = [];
placeSearch.value.search(searchKeyword.value, (status, result) => { placeSearch.value.search(searchKeyword.value, (status, result) => {
console.log(status, result);
// TODO: 添加搜索结果标记 // TODO: 添加搜索结果标记
if (status === "complete") { if (status === "complete") {
searchResultMarkers.value = result.poiList.pois.map((el, index) => { searchResultMarkers.value = result.poiList.pois.map((el, index) => {
const marker = new AMap.value.Marker({ const marker = new AMap.value.Marker({
map: map.value, map: map.value,
position: new AMap.value.LngLat(el.location.lng, el.location.lat), position: el.location,
anchor: "bottom-center",
extData: el, extData: el,
content: ` content: `
<div <div
@ -246,8 +262,8 @@ const searchPoint = (val /** 搜索建议选项 */, type) => {
</div> </div>
`, `,
}); });
marker.on("mouseover", handleResultClick); marker.on("mouseover", handleResultHover);
marker.on("click", handleMapClick); marker.on("click", handleResultClick);
marker.on("mouseout", (ev) => { marker.on("mouseout", (ev) => {
resultInfoWindow.value.close(); resultInfoWindow.value.close();
}); });
@ -257,6 +273,16 @@ const searchPoint = (val /** 搜索建议选项 */, type) => {
} }
}); });
}; };
// 搜索结果点击
const handleResultClick = async (ev) => {
map.value.clearMap();
searchResultMarkers.value = [];
const lnglat = ev.target.getExtData()?.location;
if (!lnglat) return ElMessage.error("获取经纬度失败");
addFencePath(lnglat);
};
/** 提交按钮 */ /** 提交按钮 */
function submitForm() { function submitForm() {
proxy.$refs["fenceRef"].validate((valid) => { proxy.$refs["fenceRef"].validate((valid) => {
@ -281,6 +307,7 @@ function submitForm() {
} }
}); });
} }
// 表单重置 // 表单重置
function reset() { function reset() {
form.value = { form.value = {
@ -310,9 +337,11 @@ onMounted(() => {
map.value = new AMap.value.Map("map-container", { map.value = new AMap.value.Map("map-container", {
zoom: 16, // 缩放级别 zoom: 16, // 缩放级别
center: [117.290345, 31.797813], // 中心点 center: [117.290345, 31.797813], // 中心点
city: "合肥", // city: "合肥",
}); });
map.value.on("click", handleMapClick); map.value.on("click", handleMapClick);
satelliteLayer.value = new AMap.value.TileLayer.Satellite();
// 地点搜索插件 // 地点搜索插件
placeSearch.value = new AMap.value.PlaceSearch({ placeSearch.value = new AMap.value.PlaceSearch({
// map: map.value, // map: map.value,
@ -320,11 +349,14 @@ onMounted(() => {
}); });
resultInfoWindow.value = new AMap.value.InfoWindow({ resultInfoWindow.value = new AMap.value.InfoWindow({
anchor: "bottom-center", anchor: "bottom-center",
offset: new AMap.value.Pixel(0, -31),
}); });
fencePolygon.value = new AMap.value.Polygon({}); fencePolygon.value = new AMap.value.Polygon({});
map.value.add(fencePolygon.value); map.value.add(fencePolygon.value);
map.value.addControl(new AMap.value.Scale()); map.value.addControl(new AMap.value.Scale());
if (route.query.fenceId && route.query.uuid) { if (route.query.fenceId && route.query.uuid) {
const routerObj = Object.assign({}, route, { title: "修改电子围栏" });
tab.updatePage(routerObj);
getFence(route.query.fenceId, route.query.uuid).then((resp) => { getFence(route.query.fenceId, route.query.uuid).then((resp) => {
form.value = { form.value = {
...resp.data, ...resp.data,
@ -359,3 +391,8 @@ onMounted(() => {
} }
} }
</style> </style>
<style>
.amap-info {
pointer-events: none !important;
}
</style>

View File

@ -144,6 +144,7 @@ const handleRouteClick = (data, index) => {
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0;
} }
.icon { .icon {
flex-shrink: 0;
margin-right: 8px; margin-right: 8px;
width: 20px; width: 20px;
height: 20px; height: 20px;

View File

@ -1,6 +1,14 @@
<template> <template>
<div class="wrap"> <div class="wrap">
<div class="form-drawer" v-show="drawerOpen"> <el-button
id="drawer-switch"
type="primary"
plain
circle
:icon="drawerOpen ? 'ArrowLeftBold' : 'ArrowRightBold'"
@click="switchDrawer"
></el-button>
<div id="form-drawer">
<el-scrollbar class="form-container"> <el-scrollbar class="form-container">
<div <div
:style="{ :style="{
@ -13,6 +21,7 @@
id="route-form" id="route-form"
:model="formData" :model="formData"
:rules="rules" :rules="rules"
size="small"
> >
<el-row justify="center"> <el-row justify="center">
<el-form-item prop="carType"> <el-form-item prop="carType">
@ -36,86 +45,32 @@
</el-col> </el-col>
<el-col :span="20"> <el-col :span="20">
<el-form-item prop="startAddress"> <el-form-item prop="startAddress">
<el-popover <el-input
:width="300" v-model="formData.startAddress"
:visible="showStartSuggestion && !!formData.startAddress" size="small"
title="搜索建议" @keydown.enter="searchPoint(formData.startAddress, 'start')"
@focus="nowSearch = 'start'"
@blur="nowSearch = ''"
:suffix-icon="
formData?.startLngLat ? `circle-check-filled` : null
"
> >
<div <template #prepend>起</template>
v-for="item in searchTips" </el-input>
:key="item.id"
class="suggestion-item"
@click="searchPoint(item.name, 'start')"
>
{{ item.name }}
</div>
<template #reference>
<!-- TODO: @input="handleInput('start', $event)" -->
<el-input
v-model="formData.startAddress"
size="small"
@keydown.enter="
searchPoint(formData.startAddress, 'start')
"
@focus="
nowSearch = 'start';
showStartSuggestion = true;
"
@blur="
showStartSuggestion = false;
nowSearch = '';
"
:suffix-icon="
formData?.startLngLat?.length
? `circle-check-filled`
: null
"
>
<template #prepend>起</template>
</el-input>
</template>
</el-popover>
</el-form-item> </el-form-item>
<el-form-item prop="endAddress"> <el-form-item prop="endAddress">
<el-popover <el-input
:width="300" v-model="formData.endAddress"
:visible="showEndSuggestion && !!formData.endAddress" size="small"
title="搜索建议" @keydown.enter="searchPoint(formData.endAddress, 'end')"
@focus="nowSearch = 'end'"
@blur="nowSearch = ''"
:suffix-icon="
formData?.endLngLat ? `circle-check-filled` : null
"
> >
<div <template #prepend>终</template>
v-for="item in searchTips" </el-input>
:key="item.id"
class="suggestion-item"
@click="searchPoint(item.name, 'end')"
>
{{ item.name }}
</div>
<template #reference>
<!--TODO: @input="getAutoComplete" -->
<el-input
v-model="formData.endAddress"
size="small"
@keydown.enter="searchPoint(formData.endAddress, 'end')"
@focus="
nowSearch = 'end';
// map.clearMap();
showEndSuggestion = true;
"
@blur="
showEndSuggestion = false;
nowSearch = '';
// searchTips = [];
"
:suffix-icon="
formData?.endLngLat?.length
? `circle-check-filled`
: null
"
>
<template #prepend>终</template>
</el-input>
</template>
</el-popover>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2"> <el-col :span="2">
@ -130,6 +85,64 @@
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<el-row v-if="formData.carType === '1'" justify="center">
<el-col :span="20">
<div class="divider"></div>
<el-form-item>
<el-select class="select-car-size">
<template #prefix>车型大小</template>
</el-select>
</el-form-item>
<el-row>
<el-col :span="15">
<el-form-item>
<el-input class="input-width">
<template #prepend>宽/高(米)</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="9">
<el-form-item>
<el-input class="input-height"> </el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="17">
<el-form-item>
<el-input class="input-width">
<template #prepend>车重/载重(吨)</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item>
<el-input class="input-height"> </el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="17">
<el-form-item>
<el-input class="input-width">
<template #prepend>车轴(数)/类型</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item>
<el-input class="input-height"> </el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item>
<el-input placeholder="车牌号码(可判断限行)">
<template #prepend>车牌号码</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row <el-row
justify="space-between" justify="space-between"
:style="{ :style="{
@ -150,30 +163,48 @@
type="border-card" type="border-card"
v-if="showStepPane" v-if="showStepPane"
v-model="formData.lineType" v-model="formData.lineType"
@tab-change="handleTabChange" @tab-change="searchRoute"
> >
<el-tab-pane name="0" label="费用最低"> <el-tab-pane name="0" label="费用最低">
<route-step-list <route-step-list
:route-data="formData.lineJson" :route-data="formData.lineJson"
@step-click="handleRouteClick" @step-click="handleRouteClick"
@start-click="map.setFitView([startMarker])" @start-click="
@end-click="map.setFitView([endMarker])" map.setFitView([startMarker]);
stepPolylineActiveIndex = -1;
"
@end-click="
map.setFitView([endMarker]);
stepPolylineActiveIndex = -1;
"
/> />
</el-tab-pane> </el-tab-pane>
<el-tab-pane name="1" label="时间最短"> <el-tab-pane name="1" label="时间最短">
<route-step-list <route-step-list
:route-data="formData.lineJson" :route-data="formData.lineJson"
@step-click="handleRouteClick" @step-click="handleRouteClick"
@start-click="map.setFitView([startMarker])" @start-click="
@end-click="map.setFitView([endMarker])" map.setFitView([startMarker]);
stepPolylineActiveIndex = -1;
"
@end-click="
map.setFitView([endMarker]);
stepPolylineActiveIndex = -1;
"
/> />
</el-tab-pane> </el-tab-pane>
<el-tab-pane name="2" label="距离最短"> <el-tab-pane name="2" label="距离最短">
<route-step-list <route-step-list
:route-data="formData.lineJson" :route-data="formData.lineJson"
@step-click="handleRouteClick" @step-click="handleRouteClick"
@start-click="map.setFitView([startMarker])" @start-click="
@end-click="map.setFitView([endMarker])" map.setFitView([startMarker]);
stepPolylineActiveIndex = -1;
"
@end-click="
map.setFitView([endMarker]);
stepPolylineActiveIndex = -1;
"
/> />
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
@ -215,26 +246,20 @@
</div> </div>
</el-scrollbar> </el-scrollbar>
</div> </div>
<el-button
id="drawer-switch"
type="primary"
plain
circle
:icon="drawerOpen ? 'ArrowLeftBold' : 'ArrowRightBold'"
@click="switchDrawer"
></el-button>
<div id="map-container"></div> <div id="map-container"></div>
</div> </div>
</template> </template>
<script setup name="AddLine"> <script setup name="AddLine">
import tab from "@/plugins/tab"; import tab from "@/plugins/tab";
import { onMounted } from "vue"; import { onMounted, watch } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { loadAMap } from "@/utils/map"; import { loadAMap } from "@/utils/map";
import { ElMessage } from "element-plus"; import { ElMessage, ElMessageBox, ElOption, ElSelect } from "element-plus";
import endPng from "@/assets/images/end.png"; import endPng from "@/assets/images/end.png";
import RouteStepList from "./RouteStepList.vue"; import RouteStepList from "./RouteStepList.vue";
import startPng from "@/assets/images/start.png"; import startPng from "@/assets/images/start.png";
import markBsPng from "@/assets/images/mark_bs.png";
import { addLine, getLine, updateLine } from "@/api/line/line"; import { addLine, getLine, updateLine } from "@/api/line/line";
const route = useRoute(); const route = useRoute();
@ -250,7 +275,7 @@ const endMarker = shallowRef(null); // 终点标记
const resultInfoWindow = shallowRef(null); const resultInfoWindow = shallowRef(null);
const searchResultMarkers = ref([]); // 搜索结果表笔列表 const searchResultMarkers = ref([]); // 搜索结果表笔列表
const stepsPolylines = ref([]); // 路线步骤标记列表 const stepsPolylines = ref([]); // 路线步骤标记列表
const stepsList = ref([]); const stepPolylineActiveIndex = ref(-1);
const drawerOpen = ref(true); const drawerOpen = ref(true);
const routeFormRef = ref(null); const routeFormRef = ref(null);
const searchTips = ref([]); const searchTips = ref([]);
@ -261,8 +286,8 @@ const activeTabName = ref("LEAST_FEE");
const showStepPane = computed( const showStepPane = computed(
() => () =>
formData.value?.startLngLat?.length === 2 && formData.value?.startLngLat &&
formData.value?.endLngLat?.length === 2 && formData.value?.endLngLat &&
formData.value.lineJson formData.value.lineJson
); );
@ -302,34 +327,34 @@ const data = reactive({
}, },
}); });
const { formData, rules } = toRefs(data); const { formData, rules } = toRefs(data);
// 切换左侧面板显示隐藏 // 切换左侧面板显示隐藏
const switchDrawer = () => { const switchDrawer = () => {
drawerOpen.value = !drawerOpen.value; drawerOpen.value = !drawerOpen.value;
if (drawerOpen.value) { if (drawerOpen.value) {
document.querySelector("#drawer-switch").style.left = "25%"; document.getElementById("form-drawer").style.left = "0";
document.querySelector("#drawer-switch").style.transform = document.getElementById("drawer-switch").style.left = "25%";
document.getElementById("drawer-switch").style.transform =
"translate(-50%, -50%)"; "translate(-50%, -50%)";
} else { } else {
document.querySelector("#drawer-switch").style.left = "0"; document.getElementById("form-drawer").style.left = "-100%";
document.querySelector("#drawer-switch").style.transform = document.getElementById("drawer-switch").style.left = "0";
document.getElementById("drawer-switch").style.transform =
"translate(0, -50%)"; "translate(0, -50%)";
} }
}; };
// 地图点击 // 地图点击
const handleMapClick = (ev) => { const handleMapClick = (ev) => {
// ev.preventDefault();
// 起点输入框 focus 时 // 起点输入框 focus 时
if (nowSearch.value === "start") { if (nowSearch.value === "start") {
map.value.clearMap(); map.value.clearMap();
if (formData.value?.endLngLat?.length === 2) { if (formData.value?.endLngLat) {
map.value.add(endMarker.value); map.value.add(endMarker.value);
} }
startMarker.value.setPosition( startMarker.value.setPosition(ev.lnglat);
new AMap.value.LngLat(ev.lnglat.lng, ev.lnglat.lat)
);
map.value.add(startMarker.value); map.value.add(startMarker.value);
regeoCode([ev.lnglat.lng, ev.lnglat.lat]) regeoCode(ev.lnglat)
.then((address) => { .then((address) => {
formData.value.startAddress = address; formData.value.startAddress = address;
}) })
@ -342,12 +367,10 @@ const handleMapClick = (ev) => {
// 终点输入框 focus 时 // 终点输入框 focus 时
else if (nowSearch.value === "end") { else if (nowSearch.value === "end") {
map.value.clearMap(); map.value.clearMap();
if (formData.value?.startLngLat?.length === 2) { if (formData.value?.startLngLat) {
map.value.add(startMarker.value); map.value.add(startMarker.value);
} }
endMarker.value.setPosition( endMarker.value.setPosition(ev.lnglat);
new AMap.value.LngLat(ev.lnglat.lng, ev.lnglat.lat)
);
map.value.add(endMarker.value); map.value.add(endMarker.value);
regeoCode([ev.lnglat.lng, ev.lnglat.lat]) regeoCode([ev.lnglat.lng, ev.lnglat.lat])
.then((address) => { .then((address) => {
@ -375,6 +398,121 @@ const regeoCode = (lnglat /** [lng, lat] */) => {
}); });
}; };
// 根据名称搜索地图标点
const searchPoint = (val, type) => {
if (!val) return;
map.value.clearMap();
if (type === "start" && formData.value.endLngLat) {
map.value.add(endMarker.value);
} else if (type === "end" && formData.value.startLngLat) {
map.value.add(startMarker.value);
}
placeSearch.value.search(val, (status, result) => {
// 添加搜索结果标记
if (status === "complete") {
if (result.info === "OK") {
searchResultMarkers.value = result.poiList.pois.map((el, index) => {
const marker = new AMap.value.Marker({
map: map.value,
position: el.location,
extData: el,
anchor: "bottom-center",
content: `
<div
style="
background-image: url(${markBsPng});
width: 19px;
height: 31px;
background-size: cover;
color: #fff;
text-align: center;
font-size: 12px;
padding-top: 3px;
pointer-events: none;
"
>
${index + 1}
</div>
`,
});
marker.on("click", handleResultClick);
marker.on("mouseover", (ev) => {
resultInfoWindow.value.setContent(`
<div>
${ev.target.getExtData().name}</div>
`);
resultInfoWindow.value.open(map.value, [
ev.lnglat.lng,
ev.lnglat.lat,
]);
});
marker.on("mouseout", (ev) => {
resultInfoWindow.value.close();
});
return marker;
});
map.value.setFitView(searchResultMarkers.value);
} else if (result.info === "TIP_CITIES") {
// 多个城市有此地名时,选择城市
ElMessageBox({
title: "请选择城市",
showCancelButton: true,
message: () =>
h(
ElSelect,
{
onChange: (val) => {
console.log(val);
},
},
() => result.cityList.map((el) => h(ElOption, { value: el.name }))
),
})
.then(() => {})
.catch(() => {});
} else {
throw new Error(result.info);
}
} else {
console.log(status);
}
});
};
// 搜索结果点击
const handleResultClick = async (ev) => {
const lnglat = ev.target.getExtData()?.location;
if (!lnglat) return ElMessage.error("获取经纬度失败");
let address;
try {
address = ev.target.getExtData()?.name ?? (await regeoCode(lnglat));
} catch (error) {
address = `${lnglat.lng},${lnglat.lat}`;
}
if (nowSearch.value === "start") {
map.value.clearMap();
if (formData.value?.endLngLat) {
map.value.add(endMarker.value);
}
startMarker.value.setPosition(lnglat);
formData.value.startAddress = address;
formData.value.startLngLat = lnglat;
startMarker.value.setPosition(lnglat);
map.value.add(startMarker.value);
} else if (nowSearch.value === "end") {
map.value.clearMap();
if (formData.value?.startLngLat) {
map.value.add(startMarker.value);
}
formData.value.endAddress = address;
formData.value.endLngLat = lnglat;
endMarker.value.setPosition(lnglat);
map.value.add(endMarker.value);
}
};
// 搜索路线 // 搜索路线
const searchRoute = () => { const searchRoute = () => {
if (!driving.value) return; if (!driving.value) return;
@ -386,15 +524,12 @@ const searchRoute = () => {
} else { } else {
return; return;
} }
console.log("123");
const startLngLat = formData.value.startLngLat; const startLngLat = formData.value.startLngLat;
const endLngLat = formData.value.endLngLat; const endLngLat = formData.value.endLngLat;
driving.value.search(startLngLat, endLngLat, (status, result) => { driving.value.search(startLngLat, endLngLat, (status, result) => {
// 未出错时result即是对应的路线规划方案 // 未出错时result即是对应的路线规划方案
if (status === "complete") { if (status === "complete") {
console.log(result);
formData.value.lineJson = result; formData.value.lineJson = result;
stepsList.value = result.routes[0].steps;
drawRoute(result); drawRoute(result);
resolve(result); resolve(result);
} else { } else {
@ -423,11 +558,11 @@ const drawRoute = (result) => {
strokeOpacity: 1, strokeOpacity: 1,
strokeColor: "#808080", strokeColor: "#808080",
strokeStyle: "dashed", strokeStyle: "dashed",
path: [ lineJoin: "round",
new AMap.value.LngLat(...startLngLat), lineCap: "round",
result.routes[0].steps[0].start_location, path: [startLngLat, result.routes[0].steps[0].start_location],
],
}); });
// 结束驾驶地点到终点距离以虚直线表示 // 结束驾驶地点到终点距离以虚直线表示
new AMap.value.Polyline({ new AMap.value.Polyline({
map: map.value, map: map.value,
@ -435,11 +570,14 @@ const drawRoute = (result) => {
strokeOpacity: 1, strokeOpacity: 1,
strokeColor: "#808080", strokeColor: "#808080",
strokeStyle: "dashed", strokeStyle: "dashed",
lineJoin: "round",
lineCap: "round",
path: [ path: [
result.routes[0].steps[result.routes[0].steps.length - 1].end_location, result.routes[0].steps[result.routes[0].steps.length - 1].end_location,
new AMap.value.LngLat(...endLngLat), endLngLat,
], ],
}); });
// 在地图上绘制路线标记,并添加到数组中 // 在地图上绘制路线标记,并添加到数组中
stepsPolylines.value = result.routes[0].steps.map((el) => { stepsPolylines.value = result.routes[0].steps.map((el) => {
return new AMap.value.Polyline({ return new AMap.value.Polyline({
@ -447,19 +585,53 @@ const drawRoute = (result) => {
strokeWeight: 8, strokeWeight: 8,
strokeOpacity: 1, strokeOpacity: 1,
strokeColor: "#1bac2e", strokeColor: "#1bac2e",
lineJoin: "round",
lineCap: "round",
showDir: true, showDir: true,
path: el.path, path: el.path,
}); });
}); });
// 绘制step之间的连接线
result.routes[0].steps.forEach((el, index, arr) => {
if (index >= arr.length - 1) return;
const cur = el.end_location;
const next = arr[index + 1].start_location;
console.log(cur.lng === next.lng && cur.lat === next.lat);
// if (cur.lng === next.lng && cur.lat === next.lat) return;
new AMap.value.Polyline({
map: map.value,
strokeWeight: 8,
strokeOpacity: 1,
strokeColor: "#1bac2e",
showDir: true,
lineJoin: "round",
lineCap: "round",
path: [cur, next],
});
});
map.value.setFitView(stepsPolylines.value); map.value.setFitView(stepsPolylines.value);
}; };
// 点击步骤列表
const handleRouteClick = (data, index) => { const handleRouteClick = (data, index) => {
console.log(data, index);
map.value.setFitView([stepsPolylines.value[index]]); map.value.setFitView([stepsPolylines.value[index]]);
stepPolylineActiveIndex.value = index;
}; };
// 监听激活的路线index改变其颜色恢复上一次点击的颜色
watch(stepPolylineActiveIndex, (val, oldVal) => {
val != -1 &&
stepsPolylines.value[val].setOptions({
strokeColor: "#d12209",
});
oldVal != -1 &&
stepsPolylines.value[oldVal].setOptions({
strokeColor: "#1bac2e",
});
});
// 清除路线reset form // 清除路线reset form
const clearRoute = () => { const clearRoute = () => {
formData.value.lineJson = null; formData.value.lineJson = null;
@ -467,38 +639,41 @@ const clearRoute = () => {
formData.value.endAddress = ""; formData.value.endAddress = "";
formData.value.startLngLat = null; formData.value.startLngLat = null;
formData.value.endLngLat = null; formData.value.endLngLat = null;
stepsList.value = [];
map.value.clearMap(); map.value.clearMap();
}; };
// tab点击事件 // tab点击事件
const handleTabChange = (tab) => { // const handleTabChange = (tab) => {
if (formData.value.startLngLat.length && formData.value.endLngLat.length) { // if (formData.value.startLngLat && formData.value.endLngLat) {
searchRoute(); // searchRoute();
} else { // } else {
// ElMessage.error("err"); // // ElMessage.error("err");
} // }
}; // };
/** 提交按钮 */ /** 提交按钮 */
function submitForm() { function submitForm() {
routeFormRef.value.validate((valid) => { routeFormRef.value.validate((valid) => {
if (valid) { if (valid) {
const lineJson = formData.value.lineJson
? JSON.stringify(formData.value.lineJson)
: null;
if (!lineJson) return ElMessage.error("未选择路线");
if (formData.value.lineId != null) { if (formData.value.lineId != null) {
updateLine({ updateLine({
...formData.value, ...formData.value,
lineJson: JSON.stringify(formData.value.lineJson), lineJson,
reportType: formData.value.reportType.join(","), reportType: formData.value.reportType.join(","),
}).then((response) => { }).then(() => {
ElMessage.success("修改成功"); ElMessage.success("修改成功");
back(); back();
}); });
} else { } else {
addLine({ addLine({
...formData.value, ...formData.value,
lineJson: JSON.stringify(formData.value.lineJson), lineJson,
reportType: formData.value.reportType.join(","), reportType: formData.value.reportType.join(","),
}).then((response) => { }).then(() => {
ElMessage.success("新增成功"); ElMessage.success("新增成功");
back(); back();
}); });
@ -507,9 +682,9 @@ function submitForm() {
}); });
} }
// 重置表单
const reset = () => { const reset = () => {
formData.value = { formData.value = {
// lineId: null,
lineName: null, lineName: null,
carType: "0", carType: "0",
lineType: "0", lineType: "0",
@ -517,16 +692,14 @@ const reset = () => {
endAddress: null, endAddress: null,
reportType: [], reportType: [],
lineJson: null, lineJson: null,
// linePath: null,
// createBy: null,
// createTime: null,
// uuid: null,
// tenantId: null,
}; };
routeFormRef.value && routeFormRef.value.resetFields(); routeFormRef.value && routeFormRef.value.resetFields();
}; };
const getFormData = async () => { const getFormData = async () => {
if (route.query.lineId && route.query.uuid) { if (route.query.lineId && route.query.uuid) {
const routerObj = Object.assign({}, route, { title: "修改路径" });
tab.updatePage(routerObj);
getLine(route.query.lineId, route.query.uuid).then((resp) => { getLine(route.query.lineId, route.query.uuid).then((resp) => {
let lineJson; let lineJson;
try { try {
@ -574,9 +747,9 @@ onMounted(async () => {
map.value = new AMap.value.Map("map-container", { map.value = new AMap.value.Map("map-container", {
zoom: 16, // 缩放级别 zoom: 16, // 缩放级别
center: [117.290345, 31.797813], // 中心点 center: [117.290345, 31.797813], // 中心点
city: "合肥", // city: "合肥",
}); });
window.mapinstance = map.value;
/** 加载插件 */ /** 加载插件 */
// 驾车路线规划插件 // 驾车路线规划插件
driving.value = new AMap.value.Driving(); driving.value = new AMap.value.Driving();
@ -586,7 +759,7 @@ onMounted(async () => {
// 地点搜索插件 // 地点搜索插件
placeSearch.value = new AMap.value.PlaceSearch({ placeSearch.value = new AMap.value.PlaceSearch({
// map: map.value, // map: map.value,
city: "0551", city: "全国",
}); });
geocoder.value = new AMap.value.Geocoder(); geocoder.value = new AMap.value.Geocoder();
// 搜索建议插件 // 搜索建议插件
@ -600,6 +773,10 @@ onMounted(async () => {
icon: endPng, icon: endPng,
anchor: "bottom-center", anchor: "bottom-center",
}); });
resultInfoWindow.value = new AMap.value.InfoWindow({
anchor: "bottom-center",
offset: new AMap.value.Pixel(0, -31),
});
map.value.on("click", handleMapClick); map.value.on("click", handleMapClick);
// 当修改时,从返回数据中读取路线数据绘制 // 当修改时,从返回数据中读取路线数据绘制
@ -616,14 +793,14 @@ onMounted(async () => {
width: 100%; width: 100%;
height: calc(100vh - 84px); height: calc(100vh - 84px);
} }
.form-drawer { #form-drawer {
padding: 20px; padding: 20px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
z-index: 99; z-index: 999;
background-color: #fff; background-color: #fff;
box-sizing: border-box; box-sizing: border-box;
overflow: hidden; overflow: hidden;
@ -648,19 +825,70 @@ onMounted(async () => {
padding-left: 3px; padding-left: 3px;
} }
} }
:deep(.el-input-group__prepend) {
padding: 0 8px;
}
:deep(.select-car-size) {
.el-input__wrapper {
padding-left: 0;
// overflow: hidden;
.el-input__prefix {
// box-shadow: rgb(220, 223, 230) 1px 0px 0px 0px inset,
// rgb(220, 223, 230) 0px 1px 0px 0px inset,
// rgb(220, 223, 230) 0px -1px 0px 0px inset;
.el-input__prefix-inner {
& > div {
box-sizing: border-box;
border-radius: 20px 0 0 20px;
background-color: #f5f7fa;
padding: 0 8px;
margin-right: 0;
border-right: 1px solid #c0c4cc;
}
}
}
.el-input__inner {
padding-left: 7px;
}
}
}
:deep(.input-width) {
.el-input__wrapper {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
}
:deep(.input-height) {
.el-input__wrapper {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
:deep(.submit-bar) { :deep(.submit-bar) {
width: 100%; width: 100%;
.el-button { .el-button {
width: 100%; width: 100%;
} }
} }
.divider {
display: block;
height: 1px;
width: 100%;
margin: 6px 0;
border-top: 1px solid #dcdfe6;
}
} }
:deep(#drawer-switch) { :deep(#drawer-switch) {
position: absolute; position: absolute;
left: 25%; left: 25%;
top: 50%; top: 50%;
z-index: 100; z-index: 1000;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
} }
</style> </style>
<style>
.amap-info {
pointer-events: none !important;
}
</style>

View File

@ -3,6 +3,7 @@
<el-row class="search-bar" :gutter="10"> <el-row class="search-bar" :gutter="10">
<el-col :span="18"> <el-col :span="18">
<el-input <el-input
v-model="searchKeyword"
size="small" size="small"
placeholder="请输入地名或点击地图选点" placeholder="请输入地名或点击地图选点"
@keypress.enter="searchPoint" @keypress.enter="searchPoint"
@ -90,13 +91,15 @@ import { useRoute } from "vue-router";
import { loadAMap } from "@/utils/map"; import { loadAMap } from "@/utils/map";
import { listSiteGroup } from "@/api/site/group"; import { listSiteGroup } from "@/api/site/group";
import CitySelect from "@/components/CitySelect"; import CitySelect from "@/components/CitySelect";
import markBsPng from "@/assets/images/mark_bs.png";
import { addSite, getSite, updateSite } from "@/api/site/site"; import { addSite, getSite, updateSite } from "@/api/site/site";
const route = useRoute(); const route = useRoute();
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const geocoder = shallowRef(null); // 经纬度转地址插件 const geocoder = shallowRef(null); // 经纬度转地址插件
const placeSearch = shallowRef(null); const placeSearch = shallowRef(null);
const searchResultMarkers = shallowRef([]); // 搜索结果表笔列表 const searchResultMarkers = shallowRef([]); // 搜索结果表笔列表
const resultInfoWindow = shallowRef(null);
const siteMarker = shallowRef(null);
const searchKeyword = ref(""); const searchKeyword = ref("");
const AMap = shallowRef(null); const AMap = shallowRef(null);
const map = shallowRef(null); const map = shallowRef(null);
@ -157,7 +160,6 @@ const searchPoint = (val /** 搜索建议选项 */, type) => {
form.value.fencePath = []; form.value.fencePath = [];
placeSearch.value.search(searchKeyword.value, (status, result) => { placeSearch.value.search(searchKeyword.value, (status, result) => {
console.log(status, result);
// TODO: 添加搜索结果标记 // TODO: 添加搜索结果标记
if (status === "complete") { if (status === "complete") {
searchResultMarkers.value = result.poiList.pois.map((el, index) => { searchResultMarkers.value = result.poiList.pois.map((el, index) => {
@ -165,6 +167,7 @@ const searchPoint = (val /** 搜索建议选项 */, type) => {
map: map.value, map: map.value,
position: new AMap.value.LngLat(el.location.lng, el.location.lat), position: new AMap.value.LngLat(el.location.lng, el.location.lat),
extData: el, extData: el,
anchor: "bottom-center",
content: ` content: `
<div <div
style=" style="
@ -182,7 +185,7 @@ const searchPoint = (val /** 搜索建议选项 */, type) => {
</div> </div>
`, `,
}); });
marker.on("mouseover", handleResultClick); marker.on("mouseover", () => {});
marker.on("click", handleMapClick); marker.on("click", handleMapClick);
marker.on("mouseout", (ev) => { marker.on("mouseout", (ev) => {
resultInfoWindow.value.close(); resultInfoWindow.value.close();
@ -218,7 +221,27 @@ function reset() {
proxy.resetForm("siteRef"); proxy.resetForm("siteRef");
} }
onMounted(async () => {});
listSiteGroup().then((resp) => {
siteGroupList.value = resp.rows;
});
reset();
onMounted(async () => { onMounted(async () => {
// load form
if (route.query.siteId && route.query.uuid) {
const routerObj = Object.assign({}, route, { title: "站点修改" });
tab.updatePage(routerObj);
const resp = await getSite(route.query.siteId, route.query.uuid);
form.value = resp.data;
open.value = true;
title.value = "修改站点";
} else {
open.value = true;
title.value = "添加站点";
}
// 加载地图
const _AMap = await loadAMap([ const _AMap = await loadAMap([
"AMap.Scale", "AMap.Scale",
"AMap.Geocoder", "AMap.Geocoder",
@ -229,32 +252,28 @@ onMounted(async () => {
zoom: 16, // 缩放级别 zoom: 16, // 缩放级别
center: [117.290345, 31.797813], // 中心点 center: [117.290345, 31.797813], // 中心点
}); });
resultInfoWindow.value = new AMap.value.InfoWindow({
anchor: "bottom-center",
offset: new AMap.value.Pixel(0, -31),
});
siteMarker.value = new AMap.value.Marker();
// 地点搜索插件 // 地点搜索插件
placeSearch.value = new AMap.value.PlaceSearch({ placeSearch.value = new AMap.value.PlaceSearch({
// map: map.value,
city: "0551", city: "0551",
}); });
geocoder.value = new AMap.value.Geocoder(); geocoder.value = new AMap.value.Geocoder();
map.value.on("click", handleMapClick); map.value.on("click", handleMapClick);
map.value.addControl(new AMap.value.Scale()); map.value.addControl(new AMap.value.Scale());
// TODO:
if (form.value.coordinate) {
siteMarker.value.setPosition(
new AMap.value.LngLat(...form.value.coordinate.split(","))
);
map.value.add(siteMarker.value);
map.value.setFitView([siteMarker.value]);
}
}); });
listSiteGroup().then((resp) => {
siteGroupList.value = resp.rows;
});
reset();
if (route.query.siteId && route.query.uuid) {
getSite(route.query.siteId, route.query.uuid).then((resp) => {
form.value = resp.data;
open.value = true;
title.value = "修改站点";
});
} else {
open.value = true;
title.value = "添加站点";
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -96,7 +96,12 @@
<el-table-column label="省" align="center" prop="province" /> <el-table-column label="省" align="center" prop="province" />
<el-table-column label="市" align="center" prop="city" /> <el-table-column label="市" align="center" prop="city" />
<el-table-column label="区" align="center" prop="area" /> --> <el-table-column label="区" align="center" prop="area" /> -->
<el-table-column label="详细地址" align="center" prop="address" /> <el-table-column
label="详细地址"
align="center"
prop="address"
:show-overflow-tooltip="true"
/>
<el-table-column <el-table-column
label="经纬度" label="经纬度"
align="center" align="center"