|
|
|
@ -1,14 +1,107 @@
|
|
|
|
|
<template>
|
|
|
|
|
<div class="map-container">
|
|
|
|
|
<mars-map :options="options" @onload="onload"></mars-map>
|
|
|
|
|
<navigationBar></navigationBar>
|
|
|
|
|
<mars-map :options="options"></mars-map>
|
|
|
|
|
<!-- 搜索 -->
|
|
|
|
|
<div class="search-container" id="box">
|
|
|
|
|
<div class="search-input flex-container">
|
|
|
|
|
<div class="input-title">点位搜索:</div>
|
|
|
|
|
<div class="input-box">
|
|
|
|
|
<el-input
|
|
|
|
|
v-model="queryParams.name"
|
|
|
|
|
placeholder="请输入点位名称"
|
|
|
|
|
clearable
|
|
|
|
|
/>
|
|
|
|
|
<div class="result-popup" v-show="popupShow">
|
|
|
|
|
<div class="list" v-if="list.length > 0">
|
|
|
|
|
<div
|
|
|
|
|
class="list-item"
|
|
|
|
|
v-for="item in list"
|
|
|
|
|
:key="item.id"
|
|
|
|
|
@click="addMarker(item.id, item.lonLat, item.pointName)"
|
|
|
|
|
>
|
|
|
|
|
<div class="enterprise-name">{{ item.pointName }}</div>
|
|
|
|
|
<div class="loaction-icon"></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="no-data" v-else>暂无搜索结果</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="search-bnt input-title" @click="getList()">搜索</div>
|
|
|
|
|
<div
|
|
|
|
|
class="search-bnt input-title"
|
|
|
|
|
style="margin-left: 10px; padding: 5px 10px"
|
|
|
|
|
@click="handlePointSelect()"
|
|
|
|
|
>
|
|
|
|
|
选择点位
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<button @click="laoding3d">加载</button>
|
|
|
|
|
<!-- 树形结构 -->
|
|
|
|
|
<el-drawer v-model="drawer" title="点位选择">
|
|
|
|
|
<el-tree
|
|
|
|
|
node-key="id"
|
|
|
|
|
:props="props"
|
|
|
|
|
:load="loadNode"
|
|
|
|
|
lazy
|
|
|
|
|
accordion
|
|
|
|
|
@node-click="handleNodeClick"
|
|
|
|
|
/>
|
|
|
|
|
<template #footer>
|
|
|
|
|
<el-button type="primary" @click="finishTree">确定</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-drawer>
|
|
|
|
|
<!-- 地图图层 -->
|
|
|
|
|
<div class="map-layer">
|
|
|
|
|
<div class="model flex-container">
|
|
|
|
|
<div
|
|
|
|
|
class="model-item"
|
|
|
|
|
:class="currentModelIndex == index ? 'activeBtn' : ''"
|
|
|
|
|
v-for="(item, index) in mapModel"
|
|
|
|
|
:key="index"
|
|
|
|
|
>
|
|
|
|
|
{{ item }}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="point flex-container">
|
|
|
|
|
<div
|
|
|
|
|
class="point-item"
|
|
|
|
|
:class="currentIndex == index ? 'activeBtn' : ''"
|
|
|
|
|
v-for="(item, index) in pointLayer"
|
|
|
|
|
:key="index"
|
|
|
|
|
@click="handlePointLayer(index, item.value)"
|
|
|
|
|
>
|
|
|
|
|
{{ item.name }}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<el-dialog
|
|
|
|
|
v-model="dialogVisible"
|
|
|
|
|
title="Tips"
|
|
|
|
|
width="500"
|
|
|
|
|
:before-close="handleClose"
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup name="Map">
|
|
|
|
|
import NavigationBar from "@/components/NavigationBar";
|
|
|
|
|
import marsMap from "@/components/marsMap";
|
|
|
|
|
import { ref, reactive, onMounted } from "vue";
|
|
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
|
|
import {
|
|
|
|
|
getPointListByType,
|
|
|
|
|
getPointList,
|
|
|
|
|
getPointinfo,
|
|
|
|
|
getdicts,
|
|
|
|
|
getbusinessById,
|
|
|
|
|
getEnterpriseTree,
|
|
|
|
|
} from "@/api/mapApi";
|
|
|
|
|
import { ref, reactive, onMounted, onUnmounted } from "vue";
|
|
|
|
|
let options = reactive({
|
|
|
|
|
scene: {
|
|
|
|
|
center: {
|
|
|
|
@ -43,7 +136,6 @@ let options = reactive({
|
|
|
|
|
show: false,
|
|
|
|
|
},
|
|
|
|
|
basemaps: [
|
|
|
|
|
// { name: "天地图", type: "tdt", layer: "img_d", show: true },
|
|
|
|
|
{
|
|
|
|
|
id: 2017,
|
|
|
|
|
pid: 10,
|
|
|
|
@ -63,13 +155,120 @@ let options = reactive({
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
});
|
|
|
|
|
//地图图层
|
|
|
|
|
const mapModel = reactive(["二维地图", "三维地图"]);
|
|
|
|
|
//图标类型图层
|
|
|
|
|
const pointLayer = reactive([
|
|
|
|
|
{ name: "服务点位", value: undefined },
|
|
|
|
|
{ name: "轨道交通警务站", value: "13" },
|
|
|
|
|
{ name: "巡防警务站", value: "04" },
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
//查询条件
|
|
|
|
|
let queryParams = reactive({
|
|
|
|
|
name: "",
|
|
|
|
|
type: 0,
|
|
|
|
|
lonLat: undefined,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let list = reactive([]);
|
|
|
|
|
let popupShow = ref(false);
|
|
|
|
|
let dictList = reactive([]);
|
|
|
|
|
|
|
|
|
|
let map = null
|
|
|
|
|
const dialogVisible = ref(true)
|
|
|
|
|
|
|
|
|
|
let map = null;
|
|
|
|
|
let currentIndex = ref(null);
|
|
|
|
|
let currentModelIndex = ref(0);
|
|
|
|
|
//树形结构配置
|
|
|
|
|
let drawer = ref(false);
|
|
|
|
|
const props = {
|
|
|
|
|
label: "simpleName",
|
|
|
|
|
children: "zones",
|
|
|
|
|
isLeaf: (data, node) => {
|
|
|
|
|
return data.isLeaf == 1 ? false : true;
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
let currentNodeKey = reactive({});
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
|
|
|
|
//字典
|
|
|
|
|
getdictList();
|
|
|
|
|
document.addEventListener("click", handleOutsideClick);
|
|
|
|
|
});
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
document.removeEventListener("click", handleOutsideClick);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 监听搜索结果弹出层
|
|
|
|
|
* @param event
|
|
|
|
|
*/
|
|
|
|
|
const handleOutsideClick = (event) => {
|
|
|
|
|
const box = document.getElementById("box");
|
|
|
|
|
if (popupShow.value && box && !box.contains(event.target)) {
|
|
|
|
|
popupShow.value = false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* 地图渲染完成
|
|
|
|
|
* @param mapInstance
|
|
|
|
|
*/
|
|
|
|
|
const onload = (mapInstance) => {
|
|
|
|
|
map = mapInstance;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 点图层切换
|
|
|
|
|
* @param index
|
|
|
|
|
* @param value
|
|
|
|
|
*/
|
|
|
|
|
const handlePointLayer = (index, value) => {
|
|
|
|
|
if (currentIndex.value != index) {
|
|
|
|
|
currentIndex.value = index;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* 点位选择
|
|
|
|
|
*/
|
|
|
|
|
const handlePointSelect = () => {
|
|
|
|
|
drawer.value = true;
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* 懒加载树形结构
|
|
|
|
|
* @param node
|
|
|
|
|
* @param resolve
|
|
|
|
|
*/
|
|
|
|
|
const loadNode = async (node, resolve) => {
|
|
|
|
|
if (node.level === 0) {
|
|
|
|
|
// 获取第一层数据
|
|
|
|
|
const res = await getEnterpriseTree();
|
|
|
|
|
return resolve(res.data);
|
|
|
|
|
}
|
|
|
|
|
if (node.level > 0 && node.data.isLeaf == 0) return resolve([]);
|
|
|
|
|
//其他层
|
|
|
|
|
const treeItem = await getEnterpriseTree(node.level + 1, {
|
|
|
|
|
parent: node.data.parent,
|
|
|
|
|
child: node.data.child,
|
|
|
|
|
});
|
|
|
|
|
return resolve(treeItem.data);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 树被单击
|
|
|
|
|
* @param data
|
|
|
|
|
*/
|
|
|
|
|
const handleNodeClick = (data) => {
|
|
|
|
|
currentNodeKey = data;
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* 树结构选择完毕
|
|
|
|
|
*/
|
|
|
|
|
const finishTree = () => {
|
|
|
|
|
drawer.value = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const laoding3d = () => {
|
|
|
|
|
const tiles3dLayer = new mars3d.layer.TilesetLayer({
|
|
|
|
|
name: "模型名称",
|
|
|
|
@ -97,16 +296,200 @@ const laoding3d = () => {
|
|
|
|
|
});
|
|
|
|
|
map.addLayer(tiles3dLayer);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 根据关键字搜索
|
|
|
|
|
*/
|
|
|
|
|
const getList = async () => {
|
|
|
|
|
if (!queryParams.name) {
|
|
|
|
|
proxy.$modal.msgError("请先输入点位名称");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let res = await getPointList(queryParams);
|
|
|
|
|
list = res.data;
|
|
|
|
|
popupShow.value = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 字典
|
|
|
|
|
*/
|
|
|
|
|
const getdictList = async () => {
|
|
|
|
|
let res = await getdicts();
|
|
|
|
|
dictList = res.result;
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.map-container {
|
|
|
|
|
position: relative;
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
|
|
|
|
button {
|
|
|
|
|
background: #0059a2;
|
|
|
|
|
.search-container {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 180px;
|
|
|
|
|
left: 50%;
|
|
|
|
|
transform: translateX(-50%);
|
|
|
|
|
width: 900px;
|
|
|
|
|
background: rgba(15, 42, 79, 0.9);
|
|
|
|
|
border: 1px solid #094edb;
|
|
|
|
|
z-index: 100;
|
|
|
|
|
padding: 13px 18px;
|
|
|
|
|
.input-title {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
.search-bnt {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
background: url("@/assets/images/btn_bg.png");
|
|
|
|
|
padding: 5px 16px;
|
|
|
|
|
background-size: 100% 100%;
|
|
|
|
|
}
|
|
|
|
|
.input-box {
|
|
|
|
|
position: relative;
|
|
|
|
|
flex: 1;
|
|
|
|
|
margin: 0 10px;
|
|
|
|
|
|
|
|
|
|
.result-popup {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 55px;
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 500px;
|
|
|
|
|
border: 1px solid 094edb;
|
|
|
|
|
background-color: rgba(15, 42, 79, 0.9);
|
|
|
|
|
border: 1px solid #094edb;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
padding: 6px 10px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
.list {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
}
|
|
|
|
|
.no-data {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
color: #fff;
|
|
|
|
|
letter-spacing: 1px;
|
|
|
|
|
}
|
|
|
|
|
.list-item {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
color: #fff;
|
|
|
|
|
padding: 13px 6px;
|
|
|
|
|
border-bottom: 1px solid rgba(3, 91, 178, 0.5);
|
|
|
|
|
.loaction-icon {
|
|
|
|
|
display: none;
|
|
|
|
|
height: 25px;
|
|
|
|
|
width: 25px;
|
|
|
|
|
background: url("@/assets/images/loaction.png");
|
|
|
|
|
background-size: 100% 100%;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.list-item:hover {
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
background-color: #409eff;
|
|
|
|
|
.loaction-icon {
|
|
|
|
|
display: block;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.map-layer {
|
|
|
|
|
position: absolute;
|
|
|
|
|
right: 30px;
|
|
|
|
|
bottom: 30px;
|
|
|
|
|
.model {
|
|
|
|
|
width: 55%;
|
|
|
|
|
margin-left: auto;
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
}
|
|
|
|
|
& > div {
|
|
|
|
|
background: rgba(15, 42, 79, 0.9);
|
|
|
|
|
border: 1px solid #094edb;
|
|
|
|
|
& > div {
|
|
|
|
|
position: relative;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
padding: 6px 15px;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
& > div:not(:last-child)::after {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 50%;
|
|
|
|
|
right: 0;
|
|
|
|
|
transform: translateY(-50%);
|
|
|
|
|
content: "|";
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #409eff;
|
|
|
|
|
}
|
|
|
|
|
.activeBtn {
|
|
|
|
|
background: #409eff;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.flex-container {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
::v-deep .el-drawer {
|
|
|
|
|
// width: 20% !important;
|
|
|
|
|
background: rgba(15, 42, 79, 1);
|
|
|
|
|
border: 1px solid #094edb;
|
|
|
|
|
.el-drawer__header {
|
|
|
|
|
color: #fff !important;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
font-size: 22px;
|
|
|
|
|
}
|
|
|
|
|
.drawer-btn {
|
|
|
|
|
position: absolute;
|
|
|
|
|
bottom: 10px;
|
|
|
|
|
right: 10px;
|
|
|
|
|
right: 20px;
|
|
|
|
|
bottom: 20px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
::v-deep .el-tree {
|
|
|
|
|
background: transparent;
|
|
|
|
|
color: #fff;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
}
|
|
|
|
|
::v-deep .el-tree-node__content {
|
|
|
|
|
padding-top: 20px !important;
|
|
|
|
|
padding-bottom: 20px !important;
|
|
|
|
|
}
|
|
|
|
|
::v-deep .el-tree-node__content:hover {
|
|
|
|
|
background: #409eff !important;
|
|
|
|
|
}
|
|
|
|
|
::v-deep .el-tree-node:focus > .el-tree-node__content {
|
|
|
|
|
background: #409eff !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 滚动条
|
|
|
|
|
/* 设置滚动条整体样式 */
|
|
|
|
|
::-webkit-scrollbar {
|
|
|
|
|
width: 8px; /* 滚动条宽度 */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 设置滚动条轨道 */
|
|
|
|
|
::-webkit-scrollbar-track {
|
|
|
|
|
background: transparent; /* 轨道背景颜色 */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 设置滚动条滑块 */
|
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
|
|
|
background: #094edb; /* 滑块背景颜色 */
|
|
|
|
|
border-radius: 5px; /* 滑块圆角 */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 鼠标悬停在滑块上时的样式 */
|
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
|
|
|
background: #02a1cb; /* 悬停时滑块背景颜色 */
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|