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.

428 lines
10 KiB

2 months ago
<template>
<div class="safe-operation">
<div id="reservoir-map-container"></div>
<!-- 按钮浮窗 -->
<!-- <el-input
class="search-input"
placeholder="请输入内容"
style="width: 240px"
size="small"
>
<el-button
type="default"
slot="append"
icon="el-icon-search"
size="small"
></el-button>
</el-input> -->
<div class="tool-btn">
<div class="btn cursor-pointer" @click="showTreeBox = !showTreeBox">
<img class="icon" src="@/assets/icons/layer.png" alt="" />
图层管理
</div>
<div class="line"></div>
<div class="btn cursor-pointer" @click="handleChangeMode">
<img class="icon" src="@/assets/icons/change23D.png" alt="" />
{{ mapSceneType === 3 ? "三" : "二" }}维地图
</div>
</div>
<!-- 树结构浮窗 -->
<Transition name="fade">
<div class="tree-box" v-if="showTreeBox">
<el-tree
@check-change="handleCheckTree"
:data="treeData"
default-expand-all
node-key="id"
ref="tree"
show-checkbox
highlight-current
:props="defaultProps"
>
<template #default="{ node, data }">
<div class="flex items-center">
<img
v-if="node.level > 1"
src="@/assets/common/icon-layer.png"
alt=""
/>
<img v-else src="@/assets/common/icon-folder.png" alt="" />
<span style="margin-left: 4px">{{
data.nameCn || data.text
}}</span>
</div>
</template>
</el-tree>
</div>
</Transition>
<div class="legend-icon">
<div class="row">
<img class="icon" src="@/assets/image/reservoir_big.png" alt="" />
<span>大型</span>
</div>
<div class="row">
<img class="icon" src="@/assets/image/reservoir_normal.png" alt="" />
<span>中型</span>
</div>
<div class="row">
<img class="icon" src="@/assets/image/reservoir_small.png" alt="" />
<span>小型</span>
</div>
</div>
<!-- 弹窗 -->
<el-dialog
:title="`${(resInfoData && resInfoData.resName) || '未知'}(${
(resInfoData && resInfoData.resCode) || '??'
})`"
:visible.sync="showDialog"
:destroy-on-close="true"
width="1080px"
>
<ProjectDetail
ref="detailRef"
:resCode="commonResCode"
@getResInfo="handleGetResInfo"
></ProjectDetail>
</el-dialog>
</div>
</template>
<script>
import mitt from "mitt";
import ProjectDetail from "./components/ProjectDetail.vue";
import { getSceneListData, getLayerData } from "@/api/mapCommon";
import {
addLayer,
removeLayer,
zoomToLayer,
} from "@/views/aiSupervision/waterSetting/runScene/layerTree/index";
import { queryLayersByPos, getSelectedLayersLegend } from "@/utils/mapUtils";
import { throttle } from "lodash-es";
import { devRun } from "@/utils";
const emitter = mitt();
let viewer, htmlLayer;
// let graphicsList = [];
window.panelClickFunc = function (e) {
console.log("panelClickFunc >>>>> ", e);
emitter.emit("openDialog", e);
};
export default {
components: { ProjectDetail },
data() {
return {
showDialog: false,
// 水库信息
resInfoData: null,
// 当前水库code
commonResCode: null,
mapSceneType: 2, // 2: 2D, 3: 3D
showTreeBox: false,
defaultProps: {
children: "layers",
label: "nameCn",
},
layerList: [],
checkList: [],
treeData: [],
};
},
methods: {
initData() {
getSceneListData({
name: "水库安全运行",
}).then((res) => {
let id = res.records?.[0]?.id;
getLayerData(id).then((res) => {
this.treeData = res.data.children;
});
});
},
handleChangeMode() {
this.mapSceneType = this.mapSceneType === 3 ? 2 : 3;
viewer?.changeSceneMode(this.mapSceneType);
let position = new sycim.Position(113.27, 23.13, 600000, 0, -90, 0);
viewer?.flyToPosition(
position,
() => {
console.log("移动结束 >>>>> ");
},
1
);
},
handleGetResInfo(data) {
console.log("handleGetResInfo >>>>> ", data);
this.resInfoData = data;
},
initMap() {
viewer = new sycim.Viewer("reservoir-map-container");
window.viewer = viewer;
let baseLayer = sycim.ImageryLayerFactory.createImageryLayer(
sycim.ImageryType.ARCGIS,
{
url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
}
);
viewer.addBaseLayer(baseLayer);
let layer = new sycim.EntityLayer("layer");
viewer.addLayer(layer);
// plot = new sycim.Plot(viewer);
htmlLayer = new sycim.HtmlLayer("layer");
viewer.addLayer(htmlLayer);
viewer.setOptions({
globe: {
depthTestAgainstTerrain: true,
},
});
// 三维模型才需要
// viewer.on(
// sycim.SceneEventType.CAMERA_CHANGED,
// () => {
// viewer.setOptions({
// globe: {
// depthTestAgainstTerrain: viewer.cameraPosition.alt > 10000 ? false : true
// }
// });
// },
// viewer
// );
setTimeout(() => {
viewer.scene.camera.setView({
destination: new Cesium.Cartesian3.fromDegrees(113.27, 23.13, 600000),
// orientation: {
// heading: 0,
// pitch: -90,
// roll: 0,
// },
duration: 2,
});
this.viewerAddEventListener();
}, 300);
},
handleAddHtmlLayer(position, data) {
console.log("添加DivIcon >>>>> ", position, data);
htmlLayer?.clear();
let divIcon = new sycim.DivIcon(
`${position.lng}, ${position.lat}`,
`
<div class="sycim-panel" onclick="panelClickFunc('${
data.attributes?.showCode
}')">
<div class="panel-text">${data.attributes?.showName || "未知"}
</div>
</div>
`
);
divIcon.setStyle({
// 设置可视距离
distanceDisplayCondition: {
near: 0, //最近距离
far: 8000000, //最远距离
},
//设置视距缩放
scaleByDistance: {
near: 0, //最近距离
nearValue: 1.5, //最近距离值
far: 50000, //最远距离值
farValue: 1, //最远距离值
},
horizontalOrigin: sycim.Cesium.HorizontalOrigin.CENTER,
verticalOrigin: sycim.Cesium.VerticalOrigin.BOTTOM,
});
htmlLayer.addGraphic(divIcon);
},
// 监听鼠标移动事件
viewerAddEventListener() {
window.viewer.on(
sycim.MouseEventType.MOUSE_MOVE,
throttle((e) => {
if (!e.wgs84SurfacePosition) {
return;
}
queryLayersByPos(e.wgs84SurfacePosition, this.layerList, (res) => {
console.log("res >>>>> ", res);
if (res) {
this.handleAddHtmlLayer(e.wgs84SurfacePosition, res);
} else {
htmlLayer?.clear();
}
});
}, 100),
window.viewer
);
},
openDialog(e) {
console.log("打开弹窗获取resCode >>>>> ", e);
let code = e;
// devRun(() => {
// code = "440111000008";
// });
this.commonResCode = code;
this.showDialog = true;
},
// 点击
handleClickTree(data, node) {
if (node.isLeaf && !data.children) {
let resId = this.checkList.find((v) => v === data.id);
if (resId) {
this.checkList = this.checkList.filter((v) => v != resId);
this.layerList = this.layerList.filter((v) => v.id != resId);
removeLayer(data);
} else {
this.checkList = [...this.checkList, data.id];
addLayer(data);
this.layerList.push(data);
}
}
},
handleCheckTree(data, checked) {
console.log("data, checked >>>>> ", data, checked);
if (data.pid === "root" || data.layers) return;
if (checked) {
this.checkList = [...this.checkList, data.id];
addLayer(data);
this.layerList.push(data);
} else {
this.checkList = this.checkList.filter((v) => v != data.id);
this.layerList = this.layerList.filter((v) => v.id != data.id);
removeLayer(data);
}
},
},
created() {
this.initData();
emitter.on("openDialog", this.openDialog);
},
mounted() {
setTimeout(() => {
this.initMap();
}, 50);
},
beforeDestroy() {
window.viewer = null;
htmlLayer = null;
},
};
</script>
<style scoped lang="scss">
.safe-operation {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
#reservoir-map-container {
width: 100%;
height: 100%;
}
.search-input {
position: absolute;
font-size: 14px;
z-index: 9;
right: 148px;
top: 20px;
}
.tool-btn {
border-radius: 4px;
font-size: 14px;
padding: 12px;
background: #fff;
position: absolute;
z-index: 9;
right: 12px;
top: 12px;
display: flex;
align-items: center;
.btn {
user-select: none;
display: flex;
align-items: center;
font-size: 14px;
.icon {
width: 18px;
height: 18px;
}
}
.line {
width: 2px;
background: #e7e7e7;
height: 12px;
margin: 0 8px;
}
}
.tree-box {
position: absolute;
z-index: 9;
right: 12px;
top: 66px;
border-radius: 4px;
padding: 2px;
background: #fff;
width: 280px;
min-height: 300px;
max-height: 600px;
padding: 12px 0;
overflow: auto;
}
.legend-icon {
border-radius: 4px;
padding: 8px 10px;
background: #fff;
width: 80px;
position: absolute;
z-index: 9;
right: 20px;
bottom: 20px;
.row {
display: flex;
align-items: center;
font-size: 14px;
margin-bottom: 4px;
.icon {
width: 16px;
height: 16px;
margin-right: 4px;
}
&:last-child {
margin-bottom: 0;
}
}
}
.my-icon {
width: 16px;
height: 16px;
}
}
</style>
<style lang="scss">
.sycim-panel {
padding: 10px;
background: #fff;
border-radius: 2px;
cursor: pointer;
.panel-text {
color: #000;
font-size: 14px;
}
}
</style>