318 lines
9.2 KiB
Vue
318 lines
9.2 KiB
Vue
<template>
|
|
<div>
|
|
<el-row class="search-bar" :gutter="10">
|
|
<el-col :span="18">
|
|
<el-input
|
|
v-model="searchKeyword"
|
|
size="small"
|
|
placeholder="请输入地名或点击地图选点"
|
|
@keypress.enter="searchPoint"
|
|
></el-input>
|
|
</el-col>
|
|
<el-col :span="1.5">
|
|
<el-button type="primary" size="small" icon="search">搜索</el-button>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<div id="map-container"></div>
|
|
<!-- 添加或修改站点对话框 -->
|
|
<el-dialog
|
|
:title="title"
|
|
v-model="open"
|
|
width="500px"
|
|
append-to-body
|
|
:close-on-click-modal="false"
|
|
:close-on-press-escape="false"
|
|
:show-close="false"
|
|
>
|
|
<el-form ref="siteRef" :model="form" :rules="rules" label-width="80px">
|
|
<el-form-item label="站点名称" prop="siteName">
|
|
<el-input v-model="form.siteName" placeholder="请输入站点名称" />
|
|
</el-form-item>
|
|
<el-form-item label="分组" prop="groupId">
|
|
<!-- <el-input v-model="form.groupId" placeholder="请输入分组ID" /> -->
|
|
<el-select v-model="form.groupId" placeholder="请选择站点分组">
|
|
<el-option
|
|
v-for="item in siteGroupList"
|
|
:key="item.groupId"
|
|
:label="item.groupName"
|
|
:value="item.groupId"
|
|
/>
|
|
</el-select>
|
|
</el-form-item>
|
|
<city-select v-model="form" :label-width="80"></city-select>
|
|
<!-- <el-form-item label="省" prop="province">
|
|
<el-input v-model="form.province" placeholder="请输入省" />
|
|
</el-form-item>
|
|
<el-form-item label="市" prop="city">
|
|
<el-input v-model="form.city" placeholder="请输入市" />
|
|
</el-form-item>
|
|
<el-form-item label="区" prop="area">
|
|
<el-input v-model="form.area" placeholder="请输入区" />
|
|
</el-form-item> -->
|
|
<el-form-item label="详细地址" prop="address">
|
|
<el-input v-model="form.address" placeholder="请输入详细地址" />
|
|
</el-form-item>
|
|
<el-form-item label="经纬度" prop="coordinate">
|
|
<el-input
|
|
class="map-select"
|
|
readonly
|
|
v-model="form.coordinate"
|
|
placeholder="请点击右侧按钮在地图上选点"
|
|
>
|
|
<template #append>
|
|
<!-- <el-icon @click="open = false"><Pointer />
|
|
</el-icon
|
|
> -->
|
|
<el-button @click="open = false" icon="pointer"></el-button>
|
|
</template>
|
|
</el-input>
|
|
</el-form-item>
|
|
<el-form-item label="备注" prop="remark">
|
|
<el-input v-model="form.remark" placeholder="请输入备注" />
|
|
</el-form-item>
|
|
<!-- <el-form-item label="站点" prop="tenantId">
|
|
<el-input v-model="form.tenantId" placeholder="请输入站点ID" />
|
|
</el-form-item> -->
|
|
</el-form>
|
|
<template #footer>
|
|
<div class="dialog-footer">
|
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
|
<el-button @click="back">取 消</el-button>
|
|
</div>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import tab from "@/plugins/tab";
|
|
import { useRoute } from "vue-router";
|
|
import { loadAMap } from "@/utils/map";
|
|
import { listSiteGroup } from "@/api/site/group";
|
|
import CitySelect from "@/components/CitySelect";
|
|
import markBsPng from "@/assets/images/mark_bs.png";
|
|
import { addSite, getSite, updateSite } from "@/api/site/site";
|
|
const route = useRoute();
|
|
const { proxy } = getCurrentInstance();
|
|
const geocoder = shallowRef(null); // 经纬度转地址插件
|
|
const placeSearch = shallowRef(null);
|
|
const searchResultMarkers = shallowRef([]); // 搜索结果表笔列表
|
|
const resultInfoWindow = shallowRef(null);
|
|
const siteMarker = shallowRef(null);
|
|
const searchKeyword = ref("");
|
|
const AMap = shallowRef(null);
|
|
const map = shallowRef(null);
|
|
const siteGroupList = ref([]);
|
|
const open = ref(false);
|
|
const title = ref("");
|
|
const data = reactive({
|
|
form: {},
|
|
rules: {},
|
|
});
|
|
|
|
const { form, rules } = toRefs(data);
|
|
|
|
// 根据经纬度获取地址
|
|
const regeoCode = (lnglat /** [lng, lat] */) => {
|
|
return new Promise((resolve, reject) => {
|
|
geocoder.value.getAddress(lnglat, (status, result) => {
|
|
if (status === "complete" && result.regeocode) {
|
|
const address = result.regeocode.formattedAddress;
|
|
resolve(address);
|
|
} else {
|
|
reject("根据经纬度查询地址失败");
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
const handleMapClick = async (ev) => {
|
|
open.value = true;
|
|
form.value.coordinate = `${ev.lnglat.lng},${ev.lnglat.lat}`;
|
|
form.value.address = await regeoCode([ev.lnglat.lng, ev.lnglat.lat]);
|
|
};
|
|
|
|
/** 提交按钮 */
|
|
function submitForm() {
|
|
proxy.$refs["siteRef"].validate((valid) => {
|
|
if (valid) {
|
|
if (form.value.siteId != null) {
|
|
updateSite(form.value).then((response) => {
|
|
proxy.$modal.msgSuccess("修改成功");
|
|
open.value = false;
|
|
back();
|
|
});
|
|
} else {
|
|
addSite(form.value).then((response) => {
|
|
proxy.$modal.msgSuccess("新增成功");
|
|
open.value = false;
|
|
back();
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// 根据名称搜索地图标点
|
|
const searchPoint = (val /** 搜索建议选项 */, type) => {
|
|
map.value.clearMap();
|
|
form.value.fencePath = [];
|
|
|
|
placeSearch.value.search(searchKeyword.value, (status, result) => {
|
|
// TODO: 添加搜索结果标记
|
|
if (status === "complete") {
|
|
searchResultMarkers.value = result.poiList.pois.map((el, index) => {
|
|
const marker = new AMap.value.Marker({
|
|
map: map.value,
|
|
position: new AMap.value.LngLat(el.location.lng, el.location.lat),
|
|
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;
|
|
"
|
|
>
|
|
${index + 1}
|
|
</div>
|
|
`,
|
|
});
|
|
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("click", handleResultClick);
|
|
marker.on("mouseout", (ev) => {
|
|
resultInfoWindow.value.close();
|
|
});
|
|
return marker;
|
|
});
|
|
map.value.setFitView(searchResultMarkers.value);
|
|
}
|
|
});
|
|
};
|
|
|
|
// 搜索结果点击
|
|
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}`;
|
|
}
|
|
open.value = true;
|
|
form.value.coordinate = `${lnglat.lng},${lnglat.lat}`;
|
|
form.value.address = address;
|
|
};
|
|
|
|
function back() {
|
|
reset();
|
|
tab.closeOpenPage({ path: "/basic/site" });
|
|
}
|
|
// 表单重置
|
|
function reset() {
|
|
form.value = {
|
|
siteId: null,
|
|
siteName: null,
|
|
groupId: null,
|
|
province: null,
|
|
city: null,
|
|
area: null,
|
|
address: null,
|
|
coordinate: null,
|
|
remark: null,
|
|
createBy: null,
|
|
createTime: null,
|
|
uuid: null,
|
|
tenantId: null,
|
|
};
|
|
proxy.resetForm("siteRef");
|
|
}
|
|
|
|
onMounted(async () => {});
|
|
|
|
listSiteGroup().then((resp) => {
|
|
siteGroupList.value = resp.rows;
|
|
});
|
|
|
|
reset();
|
|
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([
|
|
"AMap.Scale",
|
|
"AMap.Geocoder",
|
|
"AMap.PlaceSearch",
|
|
]);
|
|
AMap.value = _AMap;
|
|
map.value = new AMap.value.Map("map-container", {
|
|
zoom: 16, // 缩放级别
|
|
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({
|
|
city: "0551",
|
|
});
|
|
geocoder.value = new AMap.value.Geocoder();
|
|
map.value.on("click", handleMapClick);
|
|
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]);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
#map-container {
|
|
width: 100%;
|
|
height: calc(100vh - 84px);
|
|
}
|
|
.search-bar {
|
|
z-index: 99;
|
|
width: 300px;
|
|
position: absolute;
|
|
left: 20px;
|
|
top: 20px;
|
|
}
|
|
// :deep(.map-select) {
|
|
// }
|
|
</style>
|