瀏覽代碼

no message

DESKTOP-CRQ4N2U\jintian 1 年之前
父節點
當前提交
50a58d8e5e
共有 36 個文件被更改,包括 8665 次插入205 次删除
  1. 3 3
      index.html
  2. 1 0
      package-lock.json
  3. 2 0
      package.json
  4. 8 0
      src/main.js
  5. 60 1
      src/store/index.ts
  6. 192 0
      src/views/Map3d-自测/Map3DMain.vue
  7. 237 0
      src/views/Map3d-自测/components/TrackRoam.vue
  8. 220 0
      src/views/Map3d-自测/components/analysis-data.vue
  9. 517 0
      src/views/Map3d-自测/components/analysis-space.vue
  10. 342 0
      src/views/Map3d-自测/components/analysis-terrain.vue
  11. 386 0
      src/views/Map3d-自测/components/coordsTool.vue
  12. 462 0
      src/views/Map3d-自测/components/drawEdit.vue
  13. 387 0
      src/views/Map3d-自测/components/location-region.vue
  14. 279 0
      src/views/Map3d-自测/components/manage-basemap.vue
  15. 347 0
      src/views/Map3d-自测/components/manage-layer.vue
  16. 453 0
      src/views/Map3d-自测/components/map-compare.vue
  17. 314 0
      src/views/Map3d-自测/components/map-split.vue
  18. 101 0
      src/views/Map3d-自测/components/map.vue
  19. 242 0
      src/views/Map3d-自测/components/measure.vue
  20. 278 0
      src/views/Map3d-自测/components/navigation.vue
  21. 318 0
      src/views/Map3d-自测/components/printmap.vue
  22. 465 0
      src/views/Map3d-自测/components/query-graphics.vue
  23. 365 0
      src/views/Map3d-自测/components/query-keyword.vue
  24. 300 0
      src/views/Map3d-自测/components/queryResult.vue
  25. 401 0
      src/views/Map3d-自测/components/special-effects.vue
  26. 240 0
      src/views/Map3d-自测/components/toolbars.vue
  27. 316 0
      src/views/Map3d-自测/components/viewerlabel.vue
  28. 79 0
      src/views/Map3d-自测/index.js
  29. 1136 0
      src/views/Map3d-自测/map.js
  30. 42 0
      src/views/Map3d-自测/widget.vue
  31. 6 0
      src/views/Map3d/Map3DMain.vue
  32. 44 35
      src/views/Map3d/components/manage-layer.vue
  33. 14 42
      src/views/Map3d/components/map-compare.vue
  34. 6 30
      src/views/Map3d/components/map-split.vue
  35. 50 20
      src/views/Map3d/components/toolbars.vue
  36. 52 74
      src/views/Map3d/map.js

+ 3 - 3
index.html

@@ -11,10 +11,10 @@
 			}
 		</style>
 		<!-- 引入Cesium -->
-		<link rel="stylesheet" type="text/css" href="./public/ThirdParty/Cesium-1.93/Widgets/widgets.css" />
-		<script src="./ThirdParty/Cesium-1.93/Cesium.js"></script>
+		<!-- <link rel="stylesheet" type="text/css" href="./public/ThirdParty/Cesium-1.93/Widgets/widgets.css" />
+		<script src="./ThirdParty/Cesium-1.93/Cesium.js"></script> -->
 		<!-- 引入生成热力图 -->
-		<script src="./ThirdParty/CesiumHeatmap.js"></script>
+		<!-- <script src="./ThirdParty/CesiumHeatmap.js"></script> -->
 		<script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
 		<script src="src/assets/js/plus.js"></script>
 		<script src="src/assets/js/mui.min.js"></script>

+ 1 - 0
package-lock.json

@@ -9,6 +9,7 @@
       "version": "0.0.0",
       "dependencies": {
         "@element-plus/icons-vue": "^2.0.10",
+        "@jintian/cesium": "^1.95.2",
         "@jintian/Map3dSDK": "^0.0.6",
         "axios": "^1.1.3",
         "cesium-navigation-es6": "^3.0.8",

+ 2 - 0
package.json

@@ -8,6 +8,7 @@
   },
   "dependencies": {
     "@element-plus/icons-vue": "^2.0.10",
+    "@jintian/cesium": "^1.95.2",
     "@jintian/Map3dSDK": "^0.0.6",
     "axios": "^1.1.3",
     "cesium-navigation-es6": "^3.0.8",
@@ -48,6 +49,7 @@
       "include": [
         "@element-plus/icons-vue",
         "@jintian/Map3dSDK",
+        "@jintian/cesium/Build/Cesium/Cesium.js",
         "axios",
         "cesium-navigation-es6",
         "echarts",

+ 8 - 0
src/main.js

@@ -30,6 +30,10 @@ import jtpopupif from './components/jt-popup/jt-popup-if.vue'
 import jtdrawer from './components/jt-drawer/drawer.vue'
 import jtcharts from './components/jt-charts/charts.vue'
 
+//npm失效
+// import "@jintian/cesium/Build/Cesium/Widgets/widgets.css"
+// import "@jintian/cesium/Build/Cesium/Cesium.js"
+
 // 引入jt3dSDK
 // import '/public/jt3dSDK/index.css';
 // import * as jt3dSDK from '/public/jt3dSDK/jt3d.es.js';
@@ -73,4 +77,8 @@ import { injectState, key } from "@/common/store/widget"
 import storeWidget from "./widget-store"
 app.use(injectState(storeWidget), key)
 
+//全局异步引入组件
+// import comJs from '@/views/map3d/index.js'
+// app.use(comJs);
+
 app.mount('#app');

+ 60 - 1
src/store/index.ts

@@ -43,7 +43,66 @@ export const Store = defineStore({
 			mark: {
 				isMark: false, //是否显示标注
 				markData: {}, //地形数据
-			}
+			},
+			
+			toolDatas: [
+				{
+					name: "关键字查询",
+					icon: "iconfont icon-winfo-icon-tucengkongzhi",
+					router: "query-keyword"
+				},
+				{
+					name: "绕点自旋",
+					icon: "iconfont icon-chaxunzuobiaozhi",
+					router: "rotateCamera"
+				},
+				{
+					name: "全图",
+					icon: "iconfont icon-chaxunzuobiaozhi",
+					router: "fullMap"
+				},
+				{
+					name: "底图",
+					icon: "iconfont icon-dituzuobiao",
+					router: "manage-basemap"
+				},
+				{
+					name: "图层",
+					icon: "iconfont icon-winfo-icon-tucengkongzhi",
+					router: "manage-layer"
+				},
+				{
+					name: "工具",
+					icon: "iconfont icon-xitong1",
+					router: "toolbars",
+					children: [{
+							name: "卷帘对比",
+							icon: "iconfont maxsize icon-juanlian",
+							router: "map-split"
+						},
+						{
+							name: "分屏对比",
+							icon: "iconfont minsize icon-fenping",
+							router: "map-compare"
+						},
+						{
+							name: "地区导航",
+							icon: "iconfont icon-zhijiantou",
+							router: "location-region"
+						},
+						{
+							name: "视角标签",
+							icon: "iconfont icon-fushi",
+							router: "viewerlabel"
+						},
+					]
+				},
+				{
+					name: "清除",
+					icon: "iconfont icon-shanchu",
+					router: "clearAll"
+				},
+			]
 		}
 	},
 	getters:{

+ 192 - 0
src/views/Map3d-自测/Map3DMain.vue

@@ -0,0 +1,192 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage
+	} from 'element-plus';
+
+	import {
+		defineAsyncComponent,
+		markRaw,
+		computed,
+		provide,
+		ref
+	} from 'vue';
+	
+	import {
+		Store
+	} from '@/store/index'
+	store = Store()
+
+	import map3d from './components/map.vue';
+
+	let jtMap3dInstance = null;
+	let isJTMap3DOnload = ref(false);
+	const jtMap3DOnload = (map) => {
+		console.log("map构造完成", map)
+		jtMap3dInstance = map;
+		isJTMap3DOnload.value = true
+	}
+	provide("getMapInstance", () => {
+		return jtMap3dInstance;
+	});
+</script>
+
+<template>
+	<div class="jt-map3dMain">
+
+		<!-- 地图组件 -->
+		<map3d @onload="jtMap3DOnload" ref="refMap3d" />
+
+		<!-- 地图加载完成后,在加载其他组件 -->
+		<template v-if="isJTMap3DOnload">
+
+			<template v-for="comp in toolDatas" >
+				<component :is="comp.router" />
+			</template>
+
+		</template>
+	</div>
+</template>
+
+<script>
+	import useLifecycle from "@/common/uses/use-lifecycle"
+	import * as mapWork from "./map"
+	let store = undefined
+
+	// 启用map.ts生命周期
+	useLifecycle(mapWork)
+
+	export default {
+		name: "JtMap3DMain",
+
+		/**
+		 *  数据 
+		 */
+		data() {
+			return {
+				toolDatas: store.toolDatas
+			}
+		},
+
+		/**
+		 *  方法 
+		 */
+		methods: {
+			init() {
+
+				//默认加载图层控制
+				mapWork.getLayers().then(layers => {
+					layers.map((item) => {
+						if (item.isinit === '1') {
+
+							//图层ID
+							let serviceId = "service_" + item.layercode + item.layerorder;
+							item.serviceId = serviceId;
+
+							//透明度
+							let opacity = 1;
+							if (item.opacity == null) {
+								opacity = 1;
+							} else {
+								opacity = Number(item.opacity);
+							}
+							item.opacity = opacity;
+
+							//默认加载
+							mapWork.setLayersControl(window.viewer, item, true).then(res => {
+								if (res === true) {
+
+								} else {
+									ElMessage(res)
+								}
+							});
+						}
+
+						//默认展开
+						if (item.isexpand === '1') {
+							store.expandedKeys.push(item.id);
+						}
+
+						// 复选框默认选中
+						if (item.isinit === '1') {
+							store.checkedkeys.push(item.id);
+						}
+					})
+				});
+
+				// 默认加载底图切换
+				mapWork.getBaseMaps().then(baseMaps => {
+					baseMaps.map((item) => {
+						//图层ID
+						let serviceId = "service_" + item.layercode + item.layerorder;
+						item.serviceId = serviceId;
+
+						//透明度
+						let opacity = 1;
+						if (item.opacity == null) {
+							opacity = 1;
+						} else {
+							opacity = Number(item.opacity);
+						}
+						item.opacity = opacity;
+
+						if (item.layertype === '地形') {
+							store.terrain.terrainData = item;
+
+							if (item.isinit === '1') {
+								store.terrain.isTerrain = true;
+
+								//默认加载的地形
+								mapWork.setLayersControl(window.viewer, item, true).then(res => {
+									if (res === true) {
+
+									} else {
+										ElMessage(res)
+									}
+								});
+							}
+						} else if (item.layertype === '标注') {
+							store.mark.markData = item;
+
+							if (item.isinit === '1') {
+								store.mark.isMark = true;
+
+								//默认加载的标注
+								mapWork.setLayersControl(window.viewer, item, true).then(res => {
+									if (res === true) {
+
+									} else {
+										ElMessage(res)
+									}
+								});
+							}
+						} else {
+							if (item.isinit === '1') {
+								store.basemap.selectBaseMap = item;
+								store.basemap.selectImg = item.layerorder;
+
+								//默认加载的底图
+								mapWork.setLayersControl(window.viewer, item, true).then(res => {
+									if (res === true) {
+
+									} else {
+										ElMessage(res)
+									}
+								});
+							}
+						}
+					})
+				});
+			}
+		},
+
+		mounted() {
+			this.init();
+		}
+	};
+</script>
+<style lang="scss" scoped>
+
+</style>

+ 237 - 0
src/views/Map3d-自测/components/TrackRoam.vue

@@ -0,0 +1,237 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage
+	} from 'element-plus';
+
+	import {
+		inject
+	} from "vue";
+
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	<div class="jt-TrackRoam">
+
+		<el-row style="margin-bottom: 5px;">
+			<el-button type="danger" v-if="isNew" @click="drawLine()">
+				<el-icon>
+					<Plus />
+				</el-icon>新增漫游
+			</el-button>
+			<el-button type="danger" v-if="!isNew" @click="flightRoaming('remove')">
+				<el-icon>
+					<Delete />
+				</el-icon>
+				退出漫游
+			</el-button>
+		</el-row>
+
+		<el-row style="margin-bottom: 5px;" v-if="!isNew">
+
+			<el-button type="danger" v-if="isBackward" @click="flightRoaming('playReverse')">
+				<el-icon>
+					<Back />
+				</el-icon>向后飞行
+			</el-button>
+			<el-button type="danger" v-if="!isBackward" @click="flightRoaming('playForward')">
+				<el-icon>
+					<Right />
+				</el-icon>向前飞行
+			</el-button>
+
+			<el-button type="danger" v-if="isPause" @click="flightRoaming('pause')">
+				<el-icon>
+					<VideoPause />
+				</el-icon>暂停漫游
+			</el-button>
+			<el-button type="danger" v-if="!isPause" @click="flightRoaming('pause')">
+				<el-icon>
+					<VideoPlay />
+				</el-icon>继续漫游
+			</el-button>
+		</el-row>
+
+		<el-row style="margin-bottom: 5px;" v-if="!isNew">
+			<el-button type="danger" @click="flightRoaming(0)">
+				自由漫游
+			</el-button>
+			<el-button type="danger" @click="flightRoaming(1)">
+				相机跟随
+			</el-button>
+		</el-row>
+		<el-row style="margin-bottom: 5px;" v-if="!isNew">
+			<el-button type="danger" @click="flightRoaming(2)">
+				第一视角
+			</el-button>
+			<el-button type="danger" @click="flightRoaming(3)">
+				上帝视角
+			</el-button>
+		</el-row>
+
+		<el-form label-width="130rem">
+			<el-form-item label="飞行速度:" v-if="!isNew">
+				<el-slider v-model="roam.speed" @input="handleSpeedChange" :max="100" :min="1" :step="1" />
+			</el-form-item>
+			<el-form-item label="距离运动点的距离(后方):" v-if="roam.role===2">
+				<el-slider v-model="roam.followedX" @input="handleFollowedXChange" :max="10000" :min="1" :step="1" />
+			</el-form-item>
+			<el-form-item label="距离运动点的距离(上方):" v-if="roam.role===2">
+				<el-slider v-model="roam.followedZ" @input="handleFollowedZChange" :max="10000" :min="1" :step="1" />
+			</el-form-item>
+		</el-form>
+	</div>
+</template>
+
+<script>
+	let jt3d = undefined;
+
+	export default {
+		data() {
+			return {
+				isNew: true,
+				isPause: true,
+				isBackward: true,
+				Roaming: undefined,
+
+				roam: {
+					role: 0,
+					speed: 10,
+					followedX: 50,
+					followedZ: 10
+				}
+			}
+		},
+
+		/* 方法 */
+		methods: {
+
+			handleFollowedXChange(followedX) {
+				this.Roaming.followedX = followedX;
+			},
+			handleFollowedZChange(followedZ) {
+				this.Roaming.followedZ = followedZ;
+			},
+
+			handleSpeedChange(speed) {
+				this.Roaming.ChangeRoamingSpeed(speed);
+			},
+
+			/**
+			 * 绘制飞行路线
+			 */
+			drawLine() {
+				let _self = this;
+
+				jt3d.DrawTools.draw('polyline', {
+					isEdit: false,
+					onComplete(cartesian3d, points) {
+						//清除绘制
+						jt3d.DrawTools.Clear();
+
+						_self.Roaming = new jt3dSDK.Roaming(jt3d._viewer, cartesian3d, {
+							time: 360,
+							role: 2,
+							label: {
+								text: "lineName",
+							}
+						});
+						_self.isPause = true;
+						_self.isNew = false;
+						_self.roam.role = 2;
+						_self.Roaming.PauseOrContinue(_self.isPause);
+					}
+				});
+
+			},
+
+			/**
+			 * 飞行漫游
+			 * @param {Object} type
+			 */
+			flightRoaming(type) {
+
+				let _self = this;
+
+				switch (type) {
+					case "pause": //暂停飞行
+						this.isPause = !this.isPause;
+						this.Roaming.PauseOrContinue(this.isPause);
+						break;
+					case "playForward": //向前飞行
+						this.isPause = true;
+						this.isBackward = !this.isBackward;
+						this.Roaming.forwardFly();
+						break;
+					case "playReverse": //向后飞行
+						this.isPause = true;
+						this.isBackward = !this.isBackward;
+						this.Roaming.backwardsFly();
+						break;
+					case "remove": //向后飞行
+						this.isNew = true;
+						this.roam.role = Number(type);
+						this.Roaming.EndRoaming();
+						// //获取被clock监听的全部事件数量
+						// let len = jt3d._viewer.clock.onTick.numberOfListeners;
+						// for (let i = 0; i < len; i++) {
+						// 	//将被监听的方法移除来停止方法
+						// 	jt3d._viewer.clock.onTick.removeEventListener(jt3d._viewer.clock.onTick._listeners[i]);
+						// }
+						break;
+					case 0:
+						this.roam.role = Number(type);
+						this.Roaming.initRole(0);
+						break;
+					case 1:
+						this.roam.role = Number(type);
+						this.Roaming.initRole(1);
+						break;
+					case 2:
+						this.roam.role = Number(type);
+						this.Roaming.initRole(2);
+						break;
+					case 3:
+						this.roam.role = Number(type);
+						this.Roaming.initRole(3);
+						break;
+				}
+			},
+		},
+
+		mounted() {
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	::v-deep .el-table .cell {
+		line-height: 23rem !important;
+		padding: 0 12rem !important;
+		font-size: 14rem;
+	}
+
+	//整体样式
+	.jt-TrackRoam {
+		width: 90%;
+		margin-top: 16rem;
+		margin-left: 5%;
+		text-align: left;
+
+		--el-bg-color: rgb(0 44 126 / 60%);
+		--el-fill-color-blank: rgb(0 44 126 / 60%);
+		--el-text-color-secondary: rgb(216 240 255); //title
+		--el-text-color-regular: rgb(216 240 255); //内容
+		--el-fill-color-light: rgb(30 130 255);
+
+		.el-icon {
+			margin-right: 5rem;
+			color: #fff;
+		}
+	}
+</style>

+ 220 - 0
src/views/Map3d-自测/components/analysis-data.vue

@@ -0,0 +1,220 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage
+	} from 'element-plus';
+
+	import {
+		inject
+	} from "vue";
+
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	<div class="jt-analysisData">
+		<el-collapse v-model="activeName" accordion>
+			<el-upload drag :auto-upload=false action="" accept="shp" :on-preview="handlePreview" :on-remove="handleRemove" :on-change="bind">
+				<i class="el-icon-upload"></i>
+				<div class="el-upload__text">将shp文件拖到此处,或<em>点击上传</em></div>
+
+				<!-- <div class="el-upload__tip" slot="tip">必须是shp文件</div> -->
+				<span>
+					<el-icon>
+						<WarnTriangleFilled />
+					</el-icon>必须是shp文件
+				</span>
+			</el-upload>
+			<!-- <el-button style="margin-left: 10rem;" size="small" type="success" @click="config">生成GeoJson数据</el-button> -->
+		</el-collapse>
+	</div>
+</template>
+
+<script>
+	import {
+		open
+	} from 'shapefile'
+
+	let jt3d = undefined;
+
+	export default {
+		props: {},
+		watch: {
+
+		},
+		name: "Config",
+		data() {
+			return {
+				file: {},
+				filelist: [],
+			}
+		},
+
+		/* 方法 */
+		methods: {
+			/* shp文件解析生成图形 */
+			config() {
+				let _this = this
+				const name = this.file.name
+				const extension = name.split('.')[1]
+				console.log(extension)
+				if ('shp' !== extension) {
+					this.$alert('文件不是shp文件!请重新选择文件', {
+						confirmButtonText: '确定'
+					})
+				} else {
+					const reader = new FileReader()
+					const fileData = this.file.raw
+					reader.readAsArrayBuffer(fileData)
+					reader.onload = function(e) {
+						open(this.result).then(source => source.read().then(function log(result) {
+							if (result.done) return;
+							console.log(result)
+							console.log(result.value);
+
+							let promise = Cesium.GeoJsonDataSource.load(result.value, {
+								clampToGround: true
+							});
+							promise.then((dataSource) => {
+
+								window["viewer"].dataSources.add(dataSource); // 加载这个geojson资源
+								dataSource.name = name.split('.')[0];
+								console.log(dataSource)
+								const entities = dataSource.entities.values;
+								for (let index = 0; index < entities.length; index++) {
+									const entity = entities[index];
+									entity.polygon.material = Cesium.Color.fromBytes(50, 160, 255, 77)
+									entity.polygon.outlineWidth = 3;
+									entity.polygon.outline = false;
+									entity.polygon.outlineColor = Cesium.Color.RED;
+									entity.polyline = {
+										positions: entity.polygon.hierarchy._value.positions,
+										width: entity.polygon.outlineWidth,
+										material: Cesium.Color.fromBytes(0, 255, 180, 255),
+										clampToGround: true
+									}
+								}
+
+								let options = {};
+								// 初始化参数默认值
+								options.duration = Cesium.defaultValue(options.duration, 2);
+								options.heading = Cesium.defaultValue(options.heading, 0);
+								options.pitch = Cesium.defaultValue(options.pitch, -60);
+								options.range = Cesium.defaultValue(options.range, 0.0);
+								let flyPromise = window["viewer"].flyTo(entities, {
+									duration: options.duration,
+									offset: {
+										heading: Cesium.Math.toRadians(options.heading),
+										pitch: Cesium.Math.toRadians(options.pitch),
+										range: options.range
+									}
+								});
+
+							});
+
+							return source.read().then(log);
+
+						})).catch(error => console.error(error.stack));
+					}
+				}
+
+			},
+			remove() {
+
+			},
+
+			//移除
+			handleRemove(file, fileList) {
+
+				/* 清除图形 */
+				console.log(file, fileList);
+				let list = window["viewer"].dataSources.getByName(file.name.split('.')[0])
+				// for(let i=0;i<list.length;i++){
+				// 	console.log(list.length)
+				// 	window["viewer"].dataSources.remove(list[i])
+				// }
+				list.forEach(res => {
+					console.log(res)
+					window["viewer"].dataSources.remove(res)
+				})
+
+				// window["viewer"].dataSources.remove(window["viewer"].dataSources.getByName(file.name.split('.')[0]))
+
+			},
+
+			//定位
+			handlePreview(file) {
+				console.log(file)
+				this.file = file;
+				// this.config();
+
+				let list = window["viewer"].dataSources.getByName(file.name.split('.')[0])
+				list.forEach(res => {
+					const entities = res.entities.values;
+					
+					let options = {};
+					// 初始化参数默认值
+					options.duration = Cesium.defaultValue(options.duration, 2);
+					options.heading = Cesium.defaultValue(options.heading, 0);
+					options.pitch = Cesium.defaultValue(options.pitch, -60);
+					options.range = Cesium.defaultValue(options.range, 0.0);
+					let flyPromise = window["viewer"].flyTo(entities, {
+						duration: options.duration,
+						offset: {
+							heading: Cesium.Math.toRadians(options.heading),
+							pitch: Cesium.Math.toRadians(options.pitch),
+							range: options.range
+						}
+					});
+				})
+
+			},
+			bind(files, fileList) {
+				//绑定文件
+				this.file = fileList[fileList.length - 1]
+				//console.log(this.file)
+				this.config();
+			}
+		},
+
+		mounted() {
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.el-upload-dragger .el-upload__text{
+		font-size: 16rem;
+	}
+	
+	.upload_demo {
+		text-align: center;
+		margin-top: 50rem;
+	}
+
+	.el-button {
+		margin-top: 10rem;
+	}
+
+	::v-deep .el-upload-dragger {
+		padding: 0rem;
+		margin-top: 10rem;
+		color: #606266;
+		font-size: 12rem;
+
+	}
+
+	::v-deep .el-upload-list__item-name {
+		color: #fff;
+		margin-left: -21rem;
+	}
+
+	::v-deep .el-icon svg {
+		color: #409eff;
+		font-size: smaller;
+	}
+</style>

+ 517 - 0
src/views/Map3d-自测/components/analysis-space.vue

@@ -0,0 +1,517 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage
+	} from 'element-plus';
+
+	import {
+		inject
+	} from "vue";
+
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	<div class="jt-analysisSpace">
+		<el-collapse v-model="activeName" accordion>
+			<el-collapse-item name="光照分析">
+				<template #title>
+					<i class='iconfont icon-svgguangzhaofenxi' />光照分析
+				</template>
+				<div class="el-collapse-item__content">
+					<el-button color="rgb(20 136 255)" @click="SunShine('start')">开启光照分析</el-button>
+					<el-button color="rgb(255 100 100)" @click="SunShine('remove')"><span style="color: #fff;">移除光照分析</span></el-button>
+				</div>
+			</el-collapse-item>
+			<el-collapse-item name="方量分析">
+				<template #title>
+					<i class='iconfont icon-svgfangliangfenxi' />方量分析
+				</template>
+				<div class="el-collapse-item__content">
+					<el-form label-width="100rem">
+						<el-form-item label="挖方填方高度:">
+							<el-input v-model="cutFill.height" />
+						</el-form-item>
+						<el-form-item label="挖方填方精度:">
+							<el-input v-model="cutFill.precision" />
+						</el-form-item>
+					</el-form>
+					<div class="jt-btn" style="margin: 10rem;">
+						<el-button color="rgb(255 100 100)" @click="CutFill('draw')"><span style="color: #fff;">绘制挖方填方区域</span></el-button>
+						<el-button color="rgb(255 100 100)" @click="CutFill('remove')"><span style="color: #fff;">清除分析结果</span></el-button>
+					</div>
+					<el-form label-width="120rem">
+						<el-form-item label="总分析面积(㎡):">
+							<el-input v-model="cutFill.result.allArea" />
+						</el-form-item>
+						<el-form-item label="填方面积(㎡):">
+							<el-input v-model="cutFill.result.fillArea" />
+						</el-form-item>
+						<el-form-item label="填方体积(m³):">
+							<el-input v-model="cutFill.result.fillVolume" />
+						</el-form-item>
+						<el-form-item label="挖方面积(㎡):">
+							<el-input v-model="cutFill.result.cutArea" />
+						</el-form-item>
+						<el-form-item label="挖方体积(m³):">
+							<el-input v-model="cutFill.result.cutVolume" />
+						</el-form-item>
+					</el-form>
+				</div>
+			</el-collapse-item>
+			<el-collapse-item name="剖面分析">
+				<template #title>
+					<i class='iconfont icon-svgpoumianfenxi' />剖面分析
+				</template>
+				<div class="el-collapse-item__content">
+					<div style="line-height: 2em; table-layout: fixed; word-wrap: break-word; word-break: normal; text-align:justify; text-justify: inter-ideograph;color: #ffffff99;">
+						提示:单击【剖面分析】按钮触发,然后在实景三维或地形上左键单击开始,左键双击结束
+					</div>
+					<el-button color="rgb(20 136 255)" @click="SectionAnalysis">剖面分析</el-button>
+				</div>
+			</el-collapse-item>
+			<el-collapse-item name="通视分析">
+				<template #title>
+					<i class='iconfont icon-svgtongshifenxi' />通视分析
+				</template>
+				<div class="el-collapse-item__content">
+					<div style="line-height: 2em; table-layout: fixed; word-wrap: break-word; word-break: normal; text-align:justify; text-justify: inter-ideograph;color: #ffffff99;">
+						提示:红色代表不可视,绿色代表可视;
+					</div>
+					<el-button color="rgb(20 136 255)" @click="SightLine('activate')">添加通视分析</el-button>
+					<el-button color="rgb(255 100 100)" @click="SightLine('deactivate')"><span style="color: #fff;">清除通视分析</span></el-button>
+				</div>
+			</el-collapse-item>
+			<el-collapse-item name="视域分析">
+				<template #title>
+					<i class='iconfont icon-svgshiyufenxi' />视域分析
+				</template>
+				<div class="el-collapse-item__content">
+					<div style="line-height: 2em; table-layout: fixed; word-wrap: break-word; word-break: normal; text-align:justify; text-justify: inter-ideograph;color: #ffffff99;">
+						提示:点击“添加视域”按钮后在场景中点击两个点添加视域,红色代表不可视,绿色代表可视;
+					</div>
+					<el-button color="rgb(20 136 255)" @click="ViewShed('activate')">添加视域</el-button>
+					<el-button color="rgb(255 100 100)" @click="ViewShed('deactivate')"><span style="color: #fff;">清除视域</span></el-button>
+				</div>
+			</el-collapse-item>
+			<el-collapse-item name="限高分析">
+				<template #title>
+					<i class='iconfont icon-svgxiangaofenxi' />限高分析
+				</template>
+				<div class="el-collapse-item__content">
+					<el-form ref="form" label-width="100rem" label-position="right" size="mini">
+						<el-form-item label="地表海拔:">
+							<span>{{heightLimit.baseHeight}}</span>米&nbsp;&nbsp;<el-button color="rgb(20 136 255)" @click="HeightLimit('pickUp')">图上选点</el-button>
+						</el-form-item>
+						<el-form-item label="限制高度:">
+							<el-slider v-model="heightLimit.height" :min="0" :max="300" :step="1" @input="changeHeight"></el-slider>
+						</el-form-item>
+						<el-form-item label="当前高度:">
+							{{heightLimit.height}}米
+						</el-form-item>
+					</el-form>
+					<div class="jt-btn" style="margin-bottom: 10rem;">
+						<el-button color="rgb(20 136 255)" @click="HeightLimit('activate')">绘制限高区域</el-button>
+						<el-button color="rgb(255 100 100)" @click="HeightLimit('deactivate')"><span style="color: #fff;">清除限高分析</span></el-button>
+					</div>
+				</div>
+			</el-collapse-item>
+			<el-collapse-item name="剖切展示">
+				<template #title>
+					<i class='iconfont icon-svgpouqiezhanshi' />剖切展示
+				</template>
+				<div class="el-collapse-item__content">
+					<div style="line-height: 2em; table-layout: fixed; word-wrap: break-word; word-break: normal; text-align:justify; text-justify: inter-ideograph;color: #ffffff60;">
+						目前仅支持凸多边形,如果绘制的是凹多边形,可能裁剪结果不正确
+					</div>
+					<el-button color="rgb(20 136 255)" @click="Cutting('activate')">添加剖切多边形</el-button>
+				</div>
+			</el-collapse-item>
+			<!-- <el-collapse-item name="视频融合">
+				<template #title>
+					<i class='iconfont icon-svgshipinronghe' />视频融合
+				</template>
+				<div class="el-collapse-item__content">
+					<div style="line-height: 2em; table-layout: fixed; word-wrap: break-word; word-break: normal; text-align:justify; text-justify: inter-ideograph;color: #ffffff60;">
+						请先打开【牟平中心城实景三维】
+					</div>
+					<el-button color="rgb(20 136 255)" @click="PolygonHierarchy">视频融合</el-button>
+				</div>
+			</el-collapse-item> -->
+		</el-collapse>
+	</div>
+</template>
+
+<script>
+	let jt3d = undefined;
+
+	export default {
+		props: {},
+		watch: {},
+
+		/* 数据 */
+		data() {
+			return {
+				activeName: "光照分析",
+
+				// 限高分析
+				heightLimit: {
+					height: 20,
+					baseHeight: 0,
+				},
+
+				//方量分析	
+				cutFill: {
+					height: 10, //挖方填方高度
+					precision: 1256, //挖方填方精度
+					result: { //挖方填方结果
+						allArea: "",
+						cutArea: "",
+						cutVolume: "",
+						fillArea: "",
+						fillVolume: "",
+					},
+				},
+			}
+		},
+
+		/* 方法 */
+		methods: {
+			/**
+			 * 光照分析
+			 */
+			SunShine(type) {
+				let _self = this;
+				switch (type) {
+					case "start":
+						jt3d.statusBar.show = false;
+						jt3d.SpatialAnalysis.SunshineShadow.start();
+
+						break;
+					case "remove":
+						jt3d.statusBar.show = true;
+						jt3d.SpatialAnalysis.SunshineShadow.remove();
+						break;
+				}
+			},
+
+			/**
+			 * 方量分析
+			 */
+			CutFill(type) {
+				let _self = this;
+
+				//功能初始化
+				_self.init();
+
+				switch (type) {
+					case "draw":
+						jt3d.DrawTools.draw('polygon', {
+							isEdit: false,
+							onComplete(cartesian3d, points) {
+								//清除绘制
+								jt3d.DrawTools.Clear();
+
+								let pointsArray = [];
+								points.forEach((coordinate, index) => {
+									pointsArray.push([
+										coordinate.lng,
+										coordinate.lat,
+										coordinate.height
+									]);
+								});
+
+								jt3d.SpatialAnalysis.CutFill.createPolygonGeo(pointsArray, {
+									height: _self.height,
+									precision: _self.precision,
+								}).then(res => {
+									_self.cutFill.result = res;
+								});
+
+							}
+						});
+
+						break;
+					case "remove":
+						jt3d.SpatialAnalysis.CutFill.remove();
+						this.cutFill.result = {
+							allArea: "",
+							cutArea: "",
+							cutVolume: "",
+							fillArea: "",
+							fillVolume: "",
+						}
+
+						//还原左键单击事件
+						this.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+						break;
+				}
+			},
+
+			/**
+			 * 视频融合
+			 */
+			PolygonHierarchy() {
+				let videoElement = document.getElementById('trailer');
+				var videopolygon = jt3d._viewer.entities.add({
+					polygon: {
+						height: 0.1,
+						hierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArrayHeights([121.600444, 37.398272, 37.95, 121.600443, 37.398272, 33, 121.600443, 37.398341, 33, 121.600444, 37.398341, 37.95])),
+						material: videoElement,
+						perPositionHeight: true,
+					}
+				});
+
+				let flyToEntity = jt3d.LocateUtil.flyToEntity(videopolygon, {
+					heading: 90, //方向
+					pitch: -32, //倾斜角度
+					range: 72
+				});
+				flyToEntity.then(function(vehicleEntity) {
+					jt3d._viewer.trackedEntity = vehicleEntity; //获取或设置摄像机当前正在跟踪的Entity实例。
+					vehicleEntity.viewFrom = new Cesium.Cartesian3(0, 1, 0.3);
+				});
+			},
+
+			/**
+			 * 剖切分析
+			 */
+			Cutting(type) {
+				let _self = this;
+				//功能初始化
+				_self.init();
+
+				switch (type) {
+					case "activate":
+						if (window["my3dtiles"]) {
+							jt3d.DrawTools.draw('polygon', {
+								isEdit: false,
+								onComplete(cartesian3d, points) {
+									//清除绘制
+									jt3d.DrawTools.Clear();
+							
+									let pointsArray = [];
+									points.forEach((coordinate, index) => {
+										pointsArray.push([
+											coordinate.lng,
+											coordinate.lat,
+											coordinate.height
+										]);
+									});
+							
+									jt3d.SpatialAnalysis.Cutting.addTiles(window["my3dtiles"], pointsArray);
+							
+								}
+							});
+						} else {
+							ElMessage.error("请先勾选3D模型");
+						}
+						break;
+					case "deactivate":
+						//还原左键单击事件
+						this.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+						break;
+				}
+			},
+
+			/**
+			 * 限高分析
+			 */
+			HeightLimit(type) {
+				let _self = this;
+				//功能初始化
+				_self.init();
+
+				switch (type) {
+					case "pickUp": //图上选点,获取地表高度
+						jt3d.CommonTools._sketchViewModel.sketchTools('point', {
+							onComplete(cPoint, gPoint) {
+								_self.heightLimit.baseHeight = Number(gPoint.height.toFixed(2));
+							},
+							onError(message) {
+								
+							}
+						});
+						break;
+					case "activate":
+						jt3d.DrawTools.draw('polygon', {
+							isEdit: false,
+							onComplete(cartesian3d, points) {
+								//清除绘制
+								// jt3d.DrawTools._entities.remove(jt3d.DrawTools._drawEntity.polygon);
+								jt3d.DrawTools.Clear();
+
+								let pointsArray = [];
+								points.forEach((coordinate, index) => {
+									pointsArray.push([
+										coordinate.lng,
+										coordinate.lat,
+										coordinate.height
+									]);
+								});
+
+								jt3d.SpatialAnalysis.HeightLimit.addPrimitive(pointsArray, {
+									height: _self.heightLimit.height,
+									baseHeight: _self.heightLimit.baseHeight,
+								});
+							}
+						});
+						break;
+					case "deactivate":
+						jt3d.SpatialAnalysis.HeightLimit.removePrimitive();
+						jt3d.CommonTools._sketchViewModel.sketchClear();
+						//还原左键单击事件
+						this.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+						break;
+				}
+			},
+			changeHeight(val) {
+				jt3d.SpatialAnalysis.HeightLimit.changeHeight(val);
+			},
+
+			/**
+			 * 通视分析
+			 * @param {Object} type
+			 */
+			SightLine(type) {
+				let _self = this;
+				//功能初始化
+				_self.init();
+
+				switch (type) {
+					case "activate":
+						jt3d.SpatialAnalysis.SightLine.startSightLine();
+						break;
+					case "deactivate":
+						jt3d.SpatialAnalysis.SightLine.clearAll();
+						//还原左键单击事件
+						this.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+						break;
+				}
+			},
+
+			/**
+			 * 视域分析
+			 */
+			ViewShed(type) {
+				let _self = this;
+				//功能初始化
+				_self.init();
+
+				switch (type) {
+					case "activate":
+						jt3d.SpatialAnalysis.ViewShed.createViewshed(10);
+						break;
+					case "deactivate":
+						jt3d.SpatialAnalysis.ViewShed.clearAll();
+						//还原左键单击事件
+						this.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+						break;
+				}
+			},
+
+			/**
+			 * 剖面分析
+			 */
+			SectionAnalysis() {
+				let _self = this;
+				//功能初始化
+				_self.init();
+
+				jt3d.DrawTools.draw('polyline', {
+					isEdit: false,
+					onComplete(cartesian3d, points) {
+						let pointsArray = [];
+						points.forEach((coordinate, index) => {
+							pointsArray.push([
+								coordinate.lng,
+								coordinate.lat,
+								coordinate.height
+							]);
+						});
+
+						let ProfileAnalysis = jt3d.SpatialAnalysis.Profile.startProfileAnalysis(pointsArray, jt3d.DrawTools._drawEntity.polyline);
+						ProfileAnalysis.then(function(result) {
+							_self.$parent.$parent.$refs.refDrawerSectionAnalysis.drawerVisible = true;
+							_self.$parent.$parent.initEchartsData(result);
+						});
+
+					}
+				});
+			},
+
+			/**
+			 * 功能初始化
+			 */
+			init() {
+				//移除左键单击事件
+				if (jt3d.handlerLeftClick) {
+					jt3d.handlerLeftClick.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); //移除事件
+				}
+
+				jt3d.DrawTools.Clear();
+				jt3d.CommonTools._sketchViewModel.sketchClear();
+
+				jt3d.SpatialAnalysis.CutFill.remove(); //清除方量分析
+				jt3d.SpatialAnalysis.Profile.removeProfileAnalysis(); //移除剖面分析
+				jt3d.SpatialAnalysis.SightLine.clearAll(); //清除通视分析
+				jt3d.SpatialAnalysis.ViewShed.clearAll(); //清除视域分析
+				jt3d.SpatialAnalysis.HeightLimit.removePrimitive(); //清除限高分析		
+			}
+		},
+
+		mounted() {
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.jt-analysisSpace {
+		position: relative;
+
+		.iconfont {
+			padding: 0 10rem;
+		}
+
+		.el-collapse {
+			--el-collapse-border-color: rgb(0 44 126 / 0%);
+
+			--el-collapse-header-text-color: #ffffff;
+			--el-collapse-header-font-size: 13rem;
+			--el-collapse-content-bg-color: rgb(0 44 126 / 0%);
+			--el-collapse-content-font-size: 13rem;
+			--el-collapse-content-text-color: rgb(216 240 255);
+
+			--el-collapse-header-height: 40rem;
+			--el-collapse-header-bg-color: rgb(30 130 255);
+
+			--el-fill-color-blank: rgb(0 44 126 / 68%);
+			--el-text-color-regular: rgb(216 240 255);
+			--el-border-color: rgb(35 135 255);
+
+			.el-collapse-item__content {
+				padding: 10rem;
+				// padding-bottom: 0rem;
+			}
+		}
+	}
+
+	::v-deep .el-collapse-item__content {
+		padding: 10rem;
+		// padding-bottom: 0rem;
+		overflow-y: hidden;
+	}
+
+	::v-deep .el-collapse-item__header {
+		background: url(@/assets/images/bg_collapse_title.png) no-repeat;
+		background-size: 350rem 40rem;
+		// background-color: rgb(22 90 190);
+		// background-color: rgb(5 45 100 /60%);
+		background-color: rgb(30 130 255);
+		border-bottom: 0;
+	}
+</style>

+ 342 - 0
src/views/Map3d-自测/components/analysis-terrain.vue

@@ -0,0 +1,342 @@
+<script setup>
+	import {
+		inject
+	} from "vue";
+
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	<div class="jt-analysisTerrain">
+		<el-collapse v-model="activeName" accordion>
+			<el-collapse-item name="地下模式">
+				<template #title>
+					<i class='iconfont icon-svgdixiamoshi' />地下模式
+				</template>
+				<div class="el-collapse-item__content">
+					<div style="line-height: 2em; table-layout: fixed; word-wrap: break-word; word-break: normal; text-align:justify; text-justify: inter-ideograph;color: #ffffff60;">
+						提示:可以透明地表,进入地下模式,可以看地下管网数据。
+					</div>
+					<el-form label-width="130rem">
+						<el-form-item label="地下模式开启状态:">
+							<el-switch v-model="underground.boolUnderground" active-text="已开启" inactive-text="已关闭" @change="handleUndergroundChange">
+							</el-switch>
+						</el-form-item>
+						<el-form-item label="地表透明度:">
+							<el-slider v-model="underground.alpha" :min="0" :max="1" :step="0.1" :disabled="!underground.boolUnderground" @input="handleAlphaChange">
+							</el-slider>
+						</el-form-item>
+					</el-form>
+				</div>
+			</el-collapse-item>
+			<el-collapse-item name="地形开挖">
+				<template #title>
+					<i class='iconfont icon-svgdixingkaiwa' />地形开挖
+				</template>
+				<div class="el-collapse-item__content">
+					<el-form ref="form" label-width="100rem" label-position="right" size="mini">
+						<el-form-item label="开挖深度:">
+							<el-input v-model="terrainExcavation.excavateDepth" />
+						</el-form-item>
+					</el-form>
+					<div class="jt-btn" style="margin-bottom: 10rem;">
+						<el-button color="rgb(20 136 255)" @click="terrainExcavate('add')">绘制开挖区域</el-button>
+						<el-button color="rgb(255 100 100)" @click="terrainExcavate('remove')"><span style="color: #fff;">清除开挖分析</span></el-button>
+					</div>
+				</div>
+			</el-collapse-item>
+			<el-collapse-item name="坡度分析">
+				<template #title>
+					<i class='iconfont icon-svgpodufenxi' />坡度分析
+				</template>
+				<div class="el-collapse-item__content">
+					<div class="jt-btn" style="margin-top: 10rem;">
+						<el-button color="rgb(20 136 255)" @click="SlopeAspect('Num')">坡度等分</el-button>
+						<el-button color="rgb(20 136 255)" @click="SlopeAspect('Distance')">坡度等距</el-button>
+						<el-button color="rgb(255 100 100)" @click="removeSlopeAspect"><span style="color: #fff;">移除</span></el-button>
+					</div>
+				</div>
+			</el-collapse-item>
+			<!-- <el-collapse-item name="深度检测">
+					<template #title>
+						<i class='iconfont icon-tianqizitiku43' />深度检测
+					</template>
+					<div class="el-collapse-item__content">
+						深度检测
+					</div>
+				</el-collapse-item>
+				<el-collapse-item name="等高线">
+					<template #title>
+						<i class='iconfont icon-tianqizitiku43' />等高线
+					</template>
+					<div class="el-collapse-item__content">
+						等高线
+					</div>
+				</el-collapse-item> -->
+		</el-collapse>
+	</div>
+</template>
+
+<script>
+	let jt3d = undefined;
+
+	export default {
+		props: {
+
+		},
+		watch: {
+		},
+
+		/* 数据 */
+		data() {
+			return {
+				activeName: "地下模式",
+				
+				//地下模式
+				underground: {
+					alpha: 0.5,
+					boolUnderground: false,
+				},
+				
+				//地形开挖
+				terrainExcavation:{
+					excavateDepth: 10, //开挖深度
+				}
+				
+			}
+		},
+
+		/* 方法 */
+		methods: {
+			/**
+			 * 是否开启地下模式
+			 * @param {Object} bool
+			 */
+			handleUndergroundChange(bool) {
+				window["viewer"].scene.screenSpaceCameraController.enableCollisionDetection = !bool; //相机与地形的碰撞检测
+				window["viewer"].scene.globe.translucency.frontFaceAlphaByDistance = new Cesium.NearFarScalar(1.5e2, 0.5, 8.0e6, 1.0);
+				window["viewer"].scene.globe.translucency.enabled = bool; //是否开启透明
+				this.handleAlphaChange(this.underground.alpha);
+			},
+			/**
+			 * el-slider 值改变时触发
+			 * 设置地表透明度
+			 * @param {Object} alpha
+			 */
+			handleAlphaChange(alpha) {
+				const frontFaceAlphaByDistance = window["viewer"].scene.globe.translucency.frontFaceAlphaByDistance;
+				frontFaceAlphaByDistance.nearValue = alpha;
+				frontFaceAlphaByDistance.farValue = alpha;
+			},
+
+			/**
+			 * 移除坡度分析
+			 */
+			removeSlopeAspect() {
+				jt3d.TerrainAnalysis.SlopeAspect.clearAll();
+				//还原左键单击事件
+				this.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+			},
+			/**
+			 * 坡度坡向分析
+			 * @param {Object} type
+			 */
+			SlopeAspect(type) {
+				let _self = this;
+				//功能初始化
+				_self.init();
+
+				switch (type) {
+					case "Num":
+						jt3d.DrawTools.draw('polygon', {
+							isEdit: false,
+							onComplete(cartesian3d, points) {
+
+								let pointsArray = [];
+								points.forEach((coordinate, index) => {
+									pointsArray.push([
+										coordinate.lng,
+										coordinate.lat,
+										coordinate.height
+									]);
+								});
+
+								jt3d.TerrainAnalysis.SlopeAspect.createNew4Num(pointsArray, jt3d.DrawTools._drawEntity.polygon, {
+									num: 10
+								});
+
+								//清除绘制
+								// jt3d.DrawTools._entities.remove(jt3d.DrawTools._drawEntity.polygon);
+								jt3d.DrawTools.Clear();
+							}
+						});
+
+						break;
+					case "Distance":
+						jt3d.DrawTools.draw('polygon', {
+							isEdit: false,
+							onComplete(cartesian3d, points) {
+
+								let pointsArray = [];
+								points.forEach((coordinate, index) => {
+									pointsArray.push([
+										coordinate.lng,
+										coordinate.lat,
+										coordinate.height
+									]);
+								});
+
+								jt3d.TerrainAnalysis.SlopeAspect.createNew4Distance(pointsArray, jt3d.DrawTools._drawEntity.polygon, {
+									distance: 0.05
+								});
+
+								//清除绘制
+								// jt3d.DrawTools._entities.remove(jt3d.DrawTools._drawEntity.polygon);
+								jt3d.DrawTools.Clear();
+							}
+						});
+						break;
+				}
+			},
+
+			/**
+			 * 移除地形开挖
+			 */
+			removeTerrainExcavate() {
+				jt3d.TerrainAnalysis.TerrainExcavation.clear();
+				//还原左键单击事件
+				this.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+			},
+			/**
+			 * 地形开挖
+			 */
+			terrainExcavate(type) {
+				let _self = this;
+				//功能初始化
+				_self.init();
+				
+				if (type === "add") {
+					jt3d.DrawTools.draw('polygon', {
+						onComplete(aa, points) {
+							jt3d.DrawTools.Clear();
+							let pointsArray = [];
+							points.forEach((coordinate, index) => {
+								pointsArray.push([
+									coordinate.lng,
+									coordinate.lat,
+									coordinate.height
+								]);
+							});
+							jt3d.TerrainAnalysis.TerrainExcavation.add(pointsArray, {
+								excavateDepth: _self.terrainExcavation.excavateDepth
+							});
+
+						}
+					});
+				} else if (type === "remove") {
+					_self.removeTerrainExcavate();
+				}
+			},
+
+			/**
+			 * 功能初始化
+			 */
+			init() {
+				//移除左键单击事件
+				if (jt3d.handlerLeftClick) {
+					jt3d.handlerLeftClick.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); //移除事件
+				}
+
+				jt3d.DrawTools.Clear();
+
+				jt3d.TerrainAnalysis.TerrainExcavation.clear();; //清除地形开挖
+				jt3d.TerrainAnalysis.SlopeAspect.clearAll(); //移除坡度坡向分析	
+			}
+		},
+
+		mounted() {
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.el-switch{
+		font-size: 14rem !important;
+		line-height: 20rem !important;
+		align-items: self-start !important;
+	}
+	::v-deep .is-checked .el-switch__core .el-switch__action{
+		margin-left: calc(-1rem - 14rem);
+	}
+	
+	::v-deep .el-switch__core .el-switch__action{
+		top:1rem;
+	}
+	
+	::v-deep .el-switch__core .el-switch__action{
+		width: 14rem;
+		height: 14rem;
+	}
+	
+	::v-deep .el-switch__core{
+		width: 40rem !important;
+		height: 20rem !important;
+	}
+	::v-deep .el-switch__label{
+		height: 20rem !important;
+		font-size: 14rem !important;
+	}
+	::v-deep .el-switch__label *{
+		font-size: 14rem !important;
+	}
+	
+	::v-deep .el-switch__label--left{
+		margin-right: 10rem;
+	}
+	
+	.jt-analysisTerrain {
+		position: relative;
+		.iconfont {
+			padding: 0 10rem;
+		}
+
+		.el-collapse {
+			--el-collapse-border-color: rgb(0 44 126 / 0%);
+
+			--el-collapse-header-text-color: #ffffff;
+			--el-collapse-header-font-size: 13rem;
+			--el-collapse-content-bg-color: rgb(0 44 126 / 0%);
+			--el-collapse-content-font-size: 13rem;
+			--el-collapse-content-text-color: rgb(216 240 255);
+
+			--el-collapse-header-height: 40rem;
+			--el-collapse-header-bg-color: rgb(30 130 255);
+
+			--el-fill-color-blank: rgb(0 44 126 / 68%);
+			--el-text-color-regular: rgb(216 240 255);
+			--el-border-color: rgb(35 135 255);
+
+			.el-collapse-item__content {
+				padding: 10rem;
+				// padding-bottom: 0rem;
+			}
+		}
+	}
+
+	::v-deep .el-collapse-item__content {
+		padding: 10rem;
+		// padding-bottom: 0rem;
+		overflow-y: hidden;
+	}
+
+	::v-deep .el-collapse-item__header {
+		background: url(@/assets/images/bg_collapse_title.png) no-repeat;
+		background-size: 350rem 40rem;
+		// background-color: rgb(22 90 190);
+		// background-color: rgb(5 45 100 /60%);
+		background-color: rgb(30 130 255);
+		border-bottom: 0;
+	}
+</style>

+ 386 - 0
src/views/Map3d-自测/components/coordsTool.vue

@@ -0,0 +1,386 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage
+	} from 'element-plus';
+
+	import {
+		inject
+	} from "vue";
+
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+<template>
+	<div class="jt-coordsTool">
+		<el-collapse v-model="activeName" accordion>
+			<el-collapse-item name="坐标定位">
+				<template #title>
+					<i class='iconfont icon-dituzuobiao' />坐标定位
+				</template>
+				<div class="el-collapse-item__content">
+					<div style="line-height: 2em; table-layout: fixed; word-wrap: break-word; word-break: normal; text-align:justify; text-justify: inter-ideograph;color: #ffffff60;">
+						提示: 填写格式:x1,y1,z1;x2,y2,z2;x3,y3,z3;......;标点符号必须采用英文半角。
+					</div>
+					<el-form label-width="80rem">
+						<el-form-item label="定位类型:">
+							<el-radio-group v-model="position.locationType">
+								<el-radio label="point">点</el-radio>
+								<el-radio label="polyline">线</el-radio>
+								<el-radio label="polygon">多边形</el-radio>
+							</el-radio-group>
+						</el-form-item>
+					</el-form>
+					<el-input v-model="position.locationCoords" type="textarea" :autosize="{ minRows: 6, maxRows: 6 }" />
+					<div class="jt-btn" style="margin-top: 10rem;">
+						<el-button color="rgb(20 136 255)" @click="Position">坐标定位</el-button>
+						<el-button color="rgb(255 100 100)" @click="emptyLoc"><span style="color: #fff;">清除定位</span></el-button>
+					</div>
+				</div>
+			</el-collapse-item>
+			<el-collapse-item name="坐标拾取">
+				<template #title>
+					<i class='iconfont icon-chaxunzuobiaozhi' />坐标拾取
+				</template>
+				<div class="el-collapse-item__content">
+					<div style="line-height: 2em; table-layout: fixed; word-wrap: break-word; word-break: normal; text-align:justify; text-justify: inter-ideograph;color: #ffffff60;">
+						提示:点击【坐标拾取】按钮,在地图上点击获取坐标。
+					</div>
+					<el-input v-model="pickCoords" type="textarea" :autosize="{ minRows: 6, maxRows: 6 }" />
+					<div class="jt-btn" style="margin-top: 10rem;">
+						<el-button color="rgb(20 136 255)" @click="pickUp">坐标拾取</el-button>
+						<el-button color="rgb(20 136 255)" @click="undo">撤销</el-button>
+						<el-button color="rgb(255 100 100)" @click="emptyPic"><span style="color: #fff;">清空</span></el-button>
+					</div>
+				</div>
+			</el-collapse-item>
+		</el-collapse>
+	</div>
+</template>
+<script>
+	let jt3d = undefined;
+
+	export default {
+		props: {
+
+		},
+		watch: {
+			pickCoordsLable: function(val) {
+				this.setPickCoordsLable(val);
+			},
+
+		},
+
+		/* 数据 */
+		data() {
+			return {
+				activeName: "坐标定位",
+
+				position: {
+					locationType: "point", //定位类型
+					locationCoords: "", //定位坐标
+				},
+
+				pickCoords: "", //坐标拾取
+				pickCoordsArray: [],
+				pickCoordsLable: 1,
+
+				pointEntities: []
+			}
+		},
+
+		/* 方法 */
+		methods: {
+			/**
+			 * 设置点的lable
+			 */
+			setPickCoordsLable(val) {
+				jt3d.CommonTools._sketchViewModel._lineLabel = val.toString();
+			},
+
+			/**
+			 * 坐标拾取
+			 */
+			pickUp() {
+				let _self = this;
+
+				//移除左键单击事件
+				if (jt3d.handlerLeftClick) {
+					jt3d.handlerLeftClick.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
+				}
+
+				jt3d.CommonTools._sketchViewModel._lineLabel = _self.pickCoordsLable.toString();
+				jt3d.CommonTools._sketchViewModel.sketchTools('point', {
+					onComplete(cPoint, gPoint) {
+						_self.pickCoordsArray.push(gPoint.lng.toFixed(6) + ',' + gPoint.lat.toFixed(6) + ',' + gPoint.height.toFixed(2)) + ";";
+						_self.pickCoords = _self.pickCoordsArray.join(";\n");
+						_self.pickCoordsLable++;
+
+						//还原左键单击事件
+						_self.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+					},
+					onError(message) {
+						
+					}
+				});
+			},
+
+			/**
+			 * 坐标拾取 - 撤销
+			 */
+			undo() {
+				this.pickCoordsArray.pop();
+				this.pickCoords = this.pickCoordsArray.join(";\n");
+				this.pickCoordsLable--;
+
+				//移除最后一个元素
+				let lastPointEntity = jt3d.CommonTools._sketchViewModel._pointEntitys[jt3d.CommonTools._sketchViewModel._pointEntitys.length - 1];
+				jt3d._entities.remove(lastPointEntity);
+				jt3d.CommonTools._sketchViewModel._pointEntitys.pop();
+			},
+
+			/**
+			 * 坐标拾取 - 清空
+			 */
+			empty() {
+				this.pickCoords = "";
+				this.pickCoordsArray = [];
+				this.pickCoordsLable = 1;
+				jt3d.CommonTools._sketchViewModel.sketchClear();
+				jt3d.CommonTools._sketchViewModel._clearEvent();
+				jt3d.CommonTools._sketchViewModel._clearEvent(jt3d.CommonTools._sketchViewModel._sketchEventHandler);
+
+				this.position.locationCoords = "";
+				jt3d._viewer.entities.remove(jt3d.LocateUtil._locationEntity);
+
+				for (let i = 0; i < this.pointEntities.length; i++) {
+					jt3d._viewer.entities.remove(this.pointEntities[i]);
+				}
+				this.pointEntities = []; //脏数据,存储entities
+			},
+			
+			/**
+			 * 坐标拾取 - 清空
+			 */
+			emptyPic() {
+				this.pickCoords = "";
+				this.pickCoordsArray = [];
+				this.pickCoordsLable = 1;
+				jt3d.CommonTools._sketchViewModel.sketchClear();
+				jt3d.CommonTools._sketchViewModel._clearEvent();
+				jt3d.CommonTools._sketchViewModel._clearEvent(jt3d.CommonTools._sketchViewModel._sketchEventHandler);
+			
+				jt3d._viewer.entities.remove(jt3d.LocateUtil._locationEntity);
+			
+				for (let i = 0; i < this.pointEntities.length; i++) {
+					jt3d._viewer.entities.remove(this.pointEntities[i]);
+				}
+				this.pointEntities = []; //脏数据,存储entities
+			},
+			
+			/**
+			 * 坐标定位 - 清空
+			 */
+			emptyLoc() {
+				this.pickCoordsArray = [];
+				this.pickCoordsLable = 1;
+				jt3d.CommonTools._sketchViewModel.sketchClear();
+				jt3d.CommonTools._sketchViewModel._clearEvent();
+				jt3d.CommonTools._sketchViewModel._clearEvent(jt3d.CommonTools._sketchViewModel._sketchEventHandler);
+			
+				this.position.locationCoords = "";
+				jt3d._viewer.entities.remove(jt3d.LocateUtil._locationEntity);
+			
+				for (let i = 0; i < this.pointEntities.length; i++) {
+					jt3d._viewer.entities.remove(this.pointEntities[i]);
+				}
+				this.pointEntities = []; //脏数据,存储entities
+			},
+
+			/**
+			 * 坐标定位
+			 */
+			Position() {
+				let _self = this;
+
+				let endstring = _self.position.locationCoords.substring(_self.position.locationCoords.length - 1);
+				if (endstring != ";") {
+					ElMessage("最后一位请用;结束!");
+					return false;
+				}
+
+				let coords = _self.position.locationCoords.substr(0, _self.position.locationCoords.length - 1);
+				let coordArray = coords.split(';');
+				let pointArray = [];
+				coordArray.forEach((coordinate, index) => {
+					let xyArray = coordinate.split(',');
+					if (xyArray.length != 2 && xyArray.length != 3) {
+						ElMessage("坐标不是成对出现,请检查!");
+						throw Error(); //forEach()本身无法跳出循环,所以,这里使用了抛异常的方法来终止它。
+					} else {
+						let longitude = xyArray[0];
+						let latitude = xyArray[1];
+
+						if (xyArray[2]) {
+							let height = xyArray[2];
+							let point = [Number(longitude), Number(latitude), Number(height)];
+
+							pointArray.push(point);
+							//点标记
+							jt3d.CommonTools._sketchViewModel._lineLabel = (index + 1).toString();
+							jt3d.CommonTools._sketchViewModel.sketchDrawFeacture(point, 'drawPoint');
+
+							if (index === (coordArray.length - 1)) {
+								loc();
+							}
+						} else {
+
+							let terrainAltitude = jt3dSDK.common.getHeigthByPointsMostDetailed(jt3d._viewer, [
+								[Number(longitude), Number(latitude)]
+							]);
+							terrainAltitude.then(function(updatedPositions) {
+								let point = [Number(longitude), Number(latitude), Number(updatedPositions[0].height)];
+								pointArray.push(point);
+								//点标记
+								jt3d.CommonTools._sketchViewModel._lineLabel = (index + 1).toString();
+								jt3d.CommonTools._sketchViewModel.sketchDrawFeacture(point, 'drawPoint');
+
+								if (index === (coordArray.length - 1)) {
+									loc();
+								}
+							});
+						}
+					}
+				});
+
+				function loc() {
+					switch (_self.position.locationType) {
+						case "point":
+							if (coordArray.length === 1) {
+
+								let point = jt3d.PointObject.generatePoint(
+									pointArray[0]
+								);
+								point.then(function(entity) {
+									_self.flyToEntity(entity);
+								});
+							} else {
+								let line = jt3d.PolylineObject.drawSpecifyColorLine(pointArray, {
+									color: [255, 0, 0, 0]
+								});
+								line.then(function(entity) {
+									_self.flyToEntity(entity);
+								});
+							}
+							break;
+						case "polyline":
+							let line = jt3d.PolylineObject.drawSpecifyColorLine(pointArray, {
+								color: [255, 255, 0, 0.8]
+							});
+							line.then(function(entity) {
+								_self.flyToEntity(entity);
+							});
+
+							break;
+						case "polygon":
+							let polygon = jt3d.PolygonObject.generatePolygonByPoints(pointArray, {
+								color: [255, 255, 0, 0.8]
+							});
+							polygon.then(function(entity) {
+								_self.flyToEntity(entity);
+							});
+							break;
+					}
+
+				}
+
+			},
+
+			flyToEntity(entity) {
+				let flyToEntity = jt3d.LocateUtil.flyToEntity(entity, {
+					duration: 3,
+					heading: -45,
+					pitch: -20,
+					range: 6000
+				});
+				flyToEntity.then(function(entity) {
+					if (entity.point) {
+						jt3d._viewer.entities.remove(entity);
+					}
+				});
+			},
+		},
+
+		mounted() {
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.el-radio-group {
+		height: 32rem;
+		line-height: 32rem;
+		flex-wrap: nowrap;
+	}
+
+	::v-deep .el-radio__label {
+		font-size: 14rem !important;
+		padding-left: 8rem !important;
+	}
+
+	.jt-coordsTool {
+		position: relative;
+
+		.iconfont {
+			padding: 0 10rem;
+		}
+
+		.el-collapse {
+			--el-collapse-border-color: rgb(0 44 126 / 0%);
+
+			--el-collapse-header-text-color: #ffffff;
+			--el-collapse-header-font-size: 13rem;
+			--el-collapse-content-bg-color: rgb(0 44 126 / 0%);
+			--el-collapse-content-font-size: 13rem;
+			--el-collapse-content-text-color: rgb(216 240 255);
+
+			--el-collapse-header-height: 40rem;
+			--el-collapse-header-bg-color: rgb(30 130 255);
+
+			--el-fill-color-blank: rgb(0 44 126 / 68%);
+			--el-text-color-regular: rgb(216 240 255);
+			--el-border-color: rgb(35 135 255);
+
+			.el-collapse-item__content {
+				padding: 10rem;
+				// padding-bottom: 0rem;
+			}
+		}
+	}
+
+	::v-deep .el-collapse-item__content {
+		padding: 10rem;
+		// padding-bottom: 0rem;
+		overflow-y: hidden;
+	}
+
+	::v-deep .el-collapse-item__header {
+		background: url(@/assets/images/bg_collapse_title.png) no-repeat;
+		background-size: 350rem 40rem;
+		// background-color: rgb(22 90 190);
+		// background-color: rgb(5 45 100 /60%);
+		background-color: rgb(30 130 255);
+		border-bottom: 0;
+	}
+
+	::v-deep .el-form-item {
+		margin-bottom: 10rem;
+	}
+
+	::v-deep .el-radio {
+		margin-right: 10rem;
+	}
+</style>

+ 462 - 0
src/views/Map3d-自测/components/drawEdit.vue

@@ -0,0 +1,462 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage
+	} from 'element-plus';
+	import {
+		inject
+	} from "vue";
+	import {
+		ArrowLeft,
+		ArrowRight,
+		Delete,
+		Edit,
+		Share
+	} from '@element-plus/icons-vue';
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	<div class="jt-drawTool">
+		<div style="margin-bottom: 0rem;">
+			<el-select class="selectInfo" v-model="value" @change="handleClick" placeholder="请选择" style="width: 65%; margin-bottom: 10rem;margin-right: 10rem;">
+				<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
+			</el-select>
+			<el-button type="danger" :icon="Delete" style="margin-top: 8rem;width: 30%;" @click="removeAll()">清除</el-button>
+		</div>
+		<div v-show="value=='二维平面类'">
+			<el-row :gutter="20" style="margin-left: 0rem; margin-right: 0rem">
+				<el-col v-for="(item,index) in towDimension" :span="8" @click="createGraphics(item.drawType,index)">
+					<el-avatar shape="circle" :size="70" :class="currentIndex===index?'selectStyle':'defaultStyle'">
+						<i :class="[item.icon,currentIndex===index?'selectFontStyle':'']" />
+					</el-avatar>
+					<div style="margin-top: 5rem; font-size: 14rem;" :class="currentIndex===index?'selectFontStyle':''">{{item.label}}</div>
+				</el-col>
+			</el-row>
+		</div>
+		<div v-show="value=='三维立体类'">
+			<el-row :gutter="20" style="margin-left: 0rem; margin-right: 0rem">
+				<el-col v-for="(item,index) in threeDimension" :span="8" @click="createGraphics(item.drawType,index)">
+					<el-avatar shape="circle" :size="70" :class="currentIndex===index?'selectStyle':'defaultStyle'">
+						<i :class="[item.icon,currentIndex===index?'selectFontStyle':'']" />
+					</el-avatar>
+					<div style="margin-top: 5rem; font-size: 14rem;" :class="currentIndex===index?'selectFontStyle':''">{{item.label}}</div>
+				</el-col>
+			</el-row>
+		</div>
+		<div v-show="value=='军事标绘类'">
+			<el-row :gutter="20" style="margin-left: 0rem; margin-right: 0rem">
+				<el-col v-for="(item,index) in militaryPlotting" :span="8" @click="createMilitaryPlot(item.drawType,index)">
+					<el-avatar shape="circle" :size="70" :class="currentIndex===index?'selectStyle':'defaultStyle'">
+						<i :class="[item.icon,currentIndex===index?'selectFontStyle':'']" />
+					</el-avatar>
+					<div style="margin-top: 5rem; font-size: 14rem;" :class="currentIndex===index?'selectFontStyle':''">{{item.label}}</div>
+				</el-col>
+			</el-row>
+		</div>
+		<div v-show="value=='点标绘类'">
+			<el-row :gutter="20" style="margin-left: 0rem; margin-right: 0rem">
+				<el-col v-for="(item,index) in point" :span="8" @click="createDrawPoint(item.drawType,index)">
+					<el-avatar shape="circle" :size="70" :class="currentIndex===index?'selectStyle':'defaultStyle'">
+						<i :class="[item.icon,currentIndex===index?'selectFontStyle':'']" />
+					</el-avatar>
+					<div style="margin-top: 5rem; font-size: 14rem;" :class="currentIndex===index?'selectFontStyle':''">{{item.label}}</div>
+				</el-col>
+			</el-row>
+		</div>
+	</div>
+</template>
+
+<script>
+	let jt3d = undefined;
+	let tipEntity = undefined;
+	export default {
+		props: {},
+		watch: {},
+		/* 数据 */
+		data() {
+			return {
+				currentIndex: -1,
+				value: "二维平面类",
+				options: [{
+						value: '点标绘类',
+						label: '点标绘类',
+					}, {
+						value: '二维平面类',
+						label: '二维平面类',
+					},
+					{
+						value: '三维立体类',
+						label: '三维立体类',
+					},
+					{
+						value: '军事标绘类',
+						label: '军事标绘类',
+					},
+				],
+				towDimension: [{
+						label: '贴地线',
+						drawType: 'polyline',
+						number: 0,
+						icon: 'iconfont icon-svgtiedixian'
+					},
+					{
+						label: '箭头线',
+						drawType: 'arrowPolyline',
+						number: 1,
+						icon: 'iconfont icon-svgjiantouxian'
+					},
+					{
+						label: '贴地面',
+						drawType: 'polygon', //polygon
+						number: 2,
+						icon: 'iconfont icon-svgtiedimian'
+					},
+					{
+						label: '动态线',
+						drawType: 'dynamicPolyline',
+						number: 3,
+						icon: 'iconfont icon-svgliudongxian'
+					},
+					{
+						label: '发光线',
+						drawType: '发光线',
+						number: 4,
+						icon: 'iconfont icon-svgfaguangxian'
+					},
+					{
+						label: '描边线',
+						drawType: 'outlinePolyline',
+						number: 5,
+						icon: 'iconfont icon-svgmiaobianxian'
+					},
+					{
+						label: '动态圆',
+						drawType: 'dynamicCircle',
+						number: 6,
+						icon: 'iconfont icon-svgdongtaiyuan'
+					},
+					{
+						label: '普通圆',
+						drawType: 'circle',
+						number: 7,
+						icon: 'iconfont icon-svgputongyuan'
+					},
+					{
+						label: '矩形',
+						drawType: 'rectangle',
+						number: 8,
+						icon: 'iconfont icon-svgjuxing'
+					},
+
+				],
+				threeDimension: [{
+						label: '空间线',
+						drawType: 'spatialLine',
+						number: 0,
+						icon: 'iconfont icon-svgkongjianxian'
+					},
+					{
+						label: '动态墙',
+						drawType: 'dynamicWall',
+						number: 1,
+						icon: 'iconfont icon-svgdongtaiqiang'
+					},
+					{
+						label: '房屋',
+						drawType: 'house',
+						number: 2,
+						icon: 'iconfont icon-svgfangwu'
+					},
+					{
+						label: '文字',
+						drawType: 'text',
+						number: 3,
+						icon: 'iconfont icon-svgzi'
+					},
+					{
+						label: '视频墙',
+						drawType: 'videoWall',
+						number: 4,
+						icon: 'iconfont icon-svgshipinqiang'
+					},
+					{
+						label: '普通墙',
+						drawType: 'normalWall',
+						number: 5,
+						icon: 'iconfont icon-svgputongqiang'
+					},
+				],
+				militaryPlotting: [{
+						label: '直线箭头',
+						drawType: 'straightArrow',
+						number: 1,
+						icon: 'iconfont icon-zhijiantou'
+					},
+					{
+						label: '攻击箭头',
+						drawType: 'attackArrow',
+						number: 2,
+						icon: 'iconfont icon-tujifangxiang'
+					},
+					{
+						label: '钳击箭头',
+						drawType: 'pincerArrow',
+						number: 3,
+						icon: 'iconfont icon-qianji'
+					}
+				],
+				point: [{
+						label: '小模型',
+						drawType: 'model',
+						number: 1,
+						icon: 'iconfont icon-jihedi'
+					}, {
+						label: '文字',
+						drawType: 'label',
+						number: 2,
+						icon: 'iconfont icon-jihedi'
+					},
+					{
+						label: '点',
+						drawType: 'point',
+						number: 3,
+						icon: 'iconfont icon-jihedi'
+					},
+					{
+						label: '点及文字',
+						drawType: 'point2Label',
+						number: 4,
+						icon: 'iconfont icon-jihedi'
+					},
+					{
+						label: '广告牌',
+						drawType: 'billboard',
+						number: 5,
+						icon: 'iconfont icon-jihedi'
+					},
+					{
+						label: '广告牌及文字',
+						drawType: 'billboard2Label',
+						number: 6,
+						icon: 'iconfont icon-jihedi'
+					}
+				],
+			}
+		},
+
+		/* 方法 */
+		methods: {
+			//清除全部
+			removeAll() {
+				jt3d.DrawToolsEdit.Clear();
+				jt3d.DrawMilitaryPlot.clearAll();
+				jt3d.DrawPointEdit.clearAll();
+
+				this.currentIndex = -1;
+
+				//还原左键单击事件
+				this.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+			},
+
+			//选择绘制类型
+			//头部标题点击事件
+			handleClick(val) {
+				console.log(val)
+				this.currentIndex = -1;
+				this.value = val
+			},
+
+			//创建军事标会
+			createMilitaryPlot(type, index) {
+				let _self = this;
+				this.currentIndex = index;
+
+				//移除左键单击事件
+				if (jt3d.handlerLeftClick) {
+					jt3d.handlerLeftClick.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
+				}
+
+				/* 创建监听 */
+				jt3d.DrawMilitaryPlot.onEditProperty = {};
+				// 开始绘制
+				jt3d.DrawMilitaryPlot.draw(type, {
+					onComplete(cPoint, gPoint) {
+						// _self.$parent.$parent.param = param;
+						// _self.$parent.$parent.showDialog = true;
+					}
+				});
+			},
+
+			//创建二维标会和三维标会
+			createGraphics(type, index) {
+				let _self = this;
+				this.currentIndex = index;
+
+				//移除左键单击事件
+				if (jt3d.handlerLeftClick) {
+					jt3d.handlerLeftClick.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
+				}
+
+				/* 创建监听 */
+				jt3d.DrawToolsEdit.onEditProperty = {};
+				// 开始绘制
+				jt3d.DrawToolsEdit.draw(type, {
+					isEdit: true,
+					onComplete(cPoint, gPoint) {
+
+					},
+					onError(message) {
+						console.log('错误原因', message)
+					}
+				});
+			},
+
+			//创建点类标绘
+			createDrawPoint(type, index) {
+				let _self = this;
+				this.currentIndex = index;
+
+				//移除左键单击事件
+				if (jt3d.handlerLeftClick) {
+					jt3d.handlerLeftClick.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
+				}
+
+				/* 创建监听 */
+				jt3d.DrawPointEdit.onEditProperty = {};
+				// 开始绘制
+				jt3d.DrawPointEdit.draw(type, {
+					isEdit: true,
+					onComplete(cPoint, gPoint) {
+
+					},
+					onError(message) {
+						console.log('错误原因', message)
+					}
+				});
+			}
+
+		},
+		mounted() {
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.el-avatar {
+		width: 70rem !important;
+		height: 70rem !important;
+		font-size: 14px !important;
+		cursor: pointer;
+	}
+
+	// .el-popper{
+	// 	padding: 5rem 11rem;
+	// 	font-size: 12rem;
+	// 	line-height: 20rem;
+	// 	min-height: 10rem;
+	// 	width: 322rem;
+	// 	height: 311rem;
+	// 	left: 15rem !important;
+	// 	top: 175rem !important;
+	// }
+
+	::v-deep .el-scrollbar {
+		background-color: gainsboro !important;
+	}
+
+	.el-select-dropdown__item {
+		color: #409eff !important;
+		padding: 0 32rem 0 20rem;
+		height: 34rem;
+		line-height: 34rem;
+		font-size: 14rem;
+	}
+
+	.jt-drawTool {
+		--el-avatar-size: 70rem !important;
+
+
+		.el-col {
+			padding: 10rem;
+			// color: rgba(90, 172, 255, 1.0);
+			color: #fff;
+		}
+
+		i {
+			display: inline-block;
+			width: 100%;
+			height: 36rem;
+			line-height: 36rem;
+			text-align: center;
+			border-radius: 5rem;
+			font-size: 40rem;
+			// color: rgba(90, 172, 255, 1.0);
+			color: #fff;
+			transition: all .3s;
+			-webkit-transition: all .3s
+		}
+
+		.selectStyle {
+			// background: rgba(135, 182, 254, 0.5);
+			background: rgb(0 44 126);
+			--el-avatar-size: 70rem !important;
+		}
+
+		.defaultStyle {
+			background: #ffffff00;
+			--el-avatar-size: 70rem !important;
+		}
+
+		.selectFontStyle {
+			color: #fff;
+		}
+
+		.el-button.is-text {
+			background-color: rgba(255, 255, 255, 0.5);
+		}
+
+		el-option {
+			margin-top: -15rem !important;
+		}
+
+		.iconactive {
+			box-shadow: 0 0 3rem 3rem rgba(12, 123, 200, .6);
+		}
+
+		.active {
+			color: #409eff
+		}
+
+		::v-deep .el-input__wrapper {
+			background-color: rgba(255, 255, 255, 0);
+			color: #fff;
+		}
+
+		::v-deep .el-input__inner {
+			color: #fff;
+		}
+
+		.selectInfo {
+			top: 10rem !important;
+		}
+
+		.el-select-dropdown__wrap {
+			margin-top: 10rem;
+		}
+
+		.el-select-dropdown__item {
+			background-color: rgba(255, 255, 255, 1) !important;
+
+		}
+
+		.el-select-dropdown__item:hover {
+			background-color: rgba(255, 255, 235, 1) !important;
+		}
+
+	}
+</style>

+ 387 - 0
src/views/Map3d-自测/components/location-region.vue

@@ -0,0 +1,387 @@
+<script setup>
+	import {
+		ref
+	} from 'vue';
+	import {
+		inject
+	} from "vue";
+	import selshi from '@/assets/images/selshi.png';
+	import selcun from '@/assets/images/selcun.png';
+	import cun from '@/assets/images/cun.png';
+	import shi from '@/assets/images/shi.png';
+	import xian from '@/assets/images/xian.png';
+	import selxian from '@/assets/images/selxian.png';
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	<jt-popup title="空间分析" ref="refAnalysisSpace" >
+		<div class="tabs">
+			<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+				<i v-for="(item,index) in cityList">
+					<el-tab-pane :name="item.number">
+						<template #label>
+							<span class="custom-tabs-label">
+								<img v-if="index==0" :src="isindex==0?selshi:shi">
+								<img v-if="index==1" :src="isindex==1?selxian:xian">
+								<img v-if="index==2" :src="isindex==2?selcun:cun">
+								<span>{{item.label}}</span>
+							</span>
+						</template>
+						<template #default>
+							<div class="content">
+								<div :class="dj == 1?'item':'item2'" v-for="(res,num) in ALLlist" @click="selectCity(res.label,index+1,res.regioncode,res.dj)">
+									<div :class="addcolor(num)" @click="currentidx(num)">
+										<span>{{res.label}}</span>
+									</div>
+								</div>
+							</div>
+						</template>
+					</el-tab-pane>
+				</i>
+			</el-tabs>
+		</div>
+		<div class="Ficons">
+			<!-- <span>遮罩</span> -->
+			<!-- <el-icon color="#ffffff" class="icons" @click="hide" :size="20">
+			<View v-show="!hideicon" />
+			<Hide v-show="hideicon" />
+		</el-icon> -->
+		</div>
+	</jt-popup>
+</template>
+
+<script>
+	let jt3d = undefined;
+	let entities = undefined;
+	export default {
+		data() {
+			return {
+				currentIndex: -1,
+				isindex: 0, //判断选中第几个标题
+				cityList: [{ //tab数组展示列表
+					label: '牟平',
+					number: 0,
+					dj: 1
+				}],
+				activeName: 0, //选中的下标牵引
+				ALLlist: [], //所有子集城市
+				downlist: [], //村集
+				dj: 1, //控制列表样式
+				entities: undefined,
+				hideicon: false, //控制遮罩层显示
+				acolor: true, //是否展示颜色
+			}
+		},
+		watch: {
+			//改变高度值
+			activeName() {
+				this.acolor = false
+			}
+		},
+		methods: {
+			currentidx(index) {
+				this.currentIndex = index
+				this.acolor = true
+			},
+
+			//添加颜色样式
+			addcolor(index) {
+				if (this.currentIndex == index) {
+					return {
+						active: this.acolor
+					}
+				}
+			},
+
+			/**
+			 *控制遮罩层
+			 */
+			hide() {
+				this.hideicon = !this.hideicon
+				if (this.hideicon) {
+					entities[0].polygon.material = Cesium.Color.fromBytes(50, 160, 255, 1)
+				} else {
+					entities[0].polygon.material = Cesium.Color.fromBytes(50, 160, 255, 77)
+				}
+			},
+			/**
+			 * 移除定位样式
+			 */
+			remove() {
+				if (window["viewer"].dataSources.getByName('标绘区')) {
+					window["viewer"].dataSources.remove(window["viewer"].dataSources.getByName('标绘区')[0])
+				}
+			},
+
+			//头部标题点击事件
+			handleClick(data) {
+				let index = Number(data.index)
+				//判断点击的是否是第一个标题
+				if (index == 0) {
+					this.getcityList()
+					this.cityList = this.cityList.slice(0, index + 1)
+					this.isindex = index
+					this.activeName = index
+
+					this.remove();
+					//全图事件
+					this.$parent.$parent.$refs.refMap3d.fullMap(jt3d);
+				}
+			},
+
+			/* 
+			 *** label  城镇村庄名字
+			 * * index  选中下标
+			 * * regioncode  编号
+			 * * dj  村镇等级
+			 */
+			selectCity(label, index, regioncode, dj) {
+
+				let _this = this
+
+				if (!regioncode) {
+					return
+				}
+
+				//如果等级为1,代表点击的乡镇,需要重新设置ALLlist为村庄列表,并在头部添加乡镇名称
+				if (dj == 1) {
+					this.cityList.push({
+						label: label,
+						number: index,
+						dj: 2
+					})
+
+					var id = regioncode.slice(0, 9)
+
+					this.isindex = index
+					this.activeName = index
+					this.$http.get('/getTableList', {
+						tableName: 'map_region', //
+						sqlWhere: "dj = 2 and regioncode like '" + id + "%'",
+						orderByField: ''
+					}).then(res => {
+						if (res.data.length == 0) return
+						this.dj = 2
+						this.ALLlist = []
+						res.data.forEach(
+							item => {
+								this.ALLlist.push({
+									label: item.regionname,
+									regioncode: item.regioncode,
+									dj: 2
+								})
+							}
+						)
+					})
+				}
+
+				//根据等级与id获取乡镇或者村庄的面坐标
+				this.$http.get('/getGeoJson', {
+					tableName: 'map_region', //
+					sqlWhere: "dj = " + dj + " and regioncode like '" + regioncode + "%'",
+					orderByField: ''
+				}).then(res => {
+
+					if (window["viewer"].dataSources.getByName('标绘区')) {
+						window["viewer"].dataSources.remove(window["viewer"].dataSources.getByName('标绘区')[0])
+					}
+					let promise = Cesium.GeoJsonDataSource.load(res.data, {
+						clampToGround: true
+					});
+					promise.then((dataSource) => {
+						window["viewer"].dataSources.add(dataSource); // 加载这个geojson资源 
+						dataSource.name = '标绘区'
+						entities = dataSource.entities.values;
+						const entity = entities[0];
+						entity.polygon.material = Cesium.Color.fromBytes(50, 160, 255, 77)
+						entity.polygon.outlineWidth = 3;
+						entity.polygon.outline = false;
+						entity.polygon.outlineColor = Cesium.Color.RED;
+						entity.polyline = {
+							positions: entity.polygon.hierarchy._value.positions,
+							width: entity.polygon.outlineWidth,
+							material: Cesium.Color.fromBytes(0, 255, 180, 255),
+							clampToGround: true
+						}
+
+						_this.hideicon = false;
+
+						let options = {};
+						// 初始化参数默认值
+						options.duration = Cesium.defaultValue(options.duration, 2);
+						options.heading = Cesium.defaultValue(options.heading, 0);
+						options.pitch = Cesium.defaultValue(options.pitch, -60);
+						options.range = Cesium.defaultValue(options.range, 0.0);
+
+						let colorList = [
+							[90, 120, 255, 153],
+							[150, 255, 90, 153],
+							[255, 150, 50, 153],
+							[50, 160, 255, 77]
+						]
+
+						let flyPromise = window["viewer"].flyTo(entity, {
+							duration: options.duration,
+							offset: {
+								heading: Cesium.Math.toRadians(options.heading),
+								pitch: Cesium.Math.toRadians(options.pitch),
+								range: options.range
+							}
+						});
+						flyPromise.then(res => {
+							//面首次加载颜色
+							const entity = entities[0];
+							entity.polygon.material = Cesium.Color.fromBytes(colorList[0][0],
+								colorList[0][1], colorList[0][2], colorList[0][3])
+
+							let idx = 1
+							let timer = setInterval(res => {
+								const entity = entities[0];
+								entity.polygon.material = Cesium.Color.fromBytes(colorList[idx][0], colorList[idx][1], colorList[idx][2], colorList[idx][3]);
+								idx++
+							}, 500)
+							setTimeout(res => {
+								clearInterval(timer)
+
+								_this.hide();
+							}, 2100)
+						})
+					});
+				})
+			},
+
+			//获取一级街道
+			getcityList() {
+
+				this.dj = 1
+				this.ALLlist = []
+				this.$http.get("/getTableList", {
+					tableName: "map_region",
+					sqlWhere: "dj = 1",
+					orderByField: ''
+				}).then(res => {
+					if (res.data.length > 0) {
+						res.data.forEach(
+							item => {
+								console.log('街道信息', item)
+								this.ALLlist.push({
+									label: item.regionname,
+									regioncode: item.regioncode,
+									dj: 1
+								})
+							}
+						)
+					}
+				})
+
+			}
+		},
+		mounted() {
+			this.getcityList()
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.Ficons {
+		position: absolute;
+		top: 10rem;
+		left: 20rem;
+	}
+
+	.active {
+		color: #409eff;
+	}
+
+	//整体样式
+	.tabs {
+		width: 90%;
+		margin-left: 5%;
+		text-align: left;
+
+		--el-font-size-base: 16rem;
+
+		.item {
+			// width: 135rem;
+			width: 80rem;
+			display: inline-block;
+			height: 42rem;
+			margin-right: 15rem;
+			color: #ffffff;
+			font-size: 16rem;
+			cursor: pointer;
+			white-space: nowrap;
+			/*显示的行数;如果要设置2行加...则设置为2*/
+			overflow: hidden;
+			/*超出的文本隐藏*/
+			text-overflow: ellipsis;
+			/* 溢出用省略号*/
+
+			font-style: normal;
+		}
+
+		.item2 {
+			width: 65rem;
+			display: inline-block;
+			height: 35rem;
+			margin-right: 10rem;
+			color: #ffffff;
+			font-size: 16rem;
+			cursor: pointer;
+			white-space: nowrap;
+			/*显示的行数;如果要设置2行加...则设置为2*/
+			overflow: hidden;
+			/*超出的文本隐藏*/
+			text-overflow: ellipsis;
+			/* 溢出用省略号*/
+
+			font-style: normal;
+		}
+
+		.content {
+			width: 100%;
+			margin: 10rem 0;
+			overflow-y: auto;
+		}
+
+		img {
+			width: 18rem;
+			height: 18rem;
+			vertical-align: -10%;
+			margin-right: 2rem;
+		}
+	}
+
+
+
+	.demo-tabs>.el-tabs__content {
+		padding: 32rem;
+		color: #6b778c;
+		font-size: 32rem;
+		font-weight: 600;
+	}
+
+	//未选择tabs标题样式
+	::v-deep .el-tabs__item {
+		color: #ffffff !important;
+	}
+
+	//选中tabs标签样式
+	::v-deep .el-tabs__item.is-active {
+		color: var(--el-color-primary) !important;
+	}
+
+	//选中下划线样式
+	::v-deep .el-tabs__active-bar {
+		bottom: -1rem !important;
+		height: 4rem !important;
+	}
+
+	//下横线样式
+	::v-deep .el-tabs__nav-wrap::after {
+		height: 1rem !important;
+		background-color: darkgrey;
+	}
+</style>

+ 279 - 0
src/views/Map3d-自测/components/manage-basemap.vue

@@ -0,0 +1,279 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage
+	} from 'element-plus';
+
+	import {
+		Store
+	} from '@/store/index'
+	store = Store();
+
+	import no_img from '@/assets/images/no_img.png';
+</script>
+
+<template>
+	<jt-popup title="底图切换">
+		<div class="jt-basemap">
+			<div class="top">
+				<div class="onceLayer" v-for="(item,index) in baseMaps" :key="index" @click="changeBasicLayer(item)">
+					<img v-if="item.imageurl" :src="item.imageurl" :class="item.layerorder===selectImg?'selectImg':''" />
+				</div>
+			</div>
+			<div class="bottom">
+				<el-switch v-model="terrain.isTerrain" @change="changeTerrain" />
+				<span>显示地形</span>
+				<span> </span>
+				<el-switch v-model="mark.isMark" @change="changeMark" />
+				<span>显示标注</span>
+			</div>
+		</div>
+	</jt-popup>
+
+</template>
+
+<script>
+	let store = undefined
+
+	import * as mapWork from "../map"
+
+	export default {
+		data() {
+			return {
+				//底图数据
+				baseMaps: [], //底图
+				selectImg: store.basemap.selectImg, //选中的底图图片
+				selectBaseMap: store.basemap.selectBaseMap, //选中的底图数据
+
+				//地形数据
+				terrain: {
+					isTerrain: store.terrain.isTerrain, //是否切换地形
+					terrainData: store.terrain.terrainData, //地形数据
+				},
+
+				//标注数据
+				mark: {
+					isMark: store.mark.isMark, //是否显示标注
+					markData: store.mark.markData, //地形数据
+				}
+
+			}
+		},
+		methods: {
+
+			/**
+			 * 切换地形事件
+			 */
+			changeTerrain() {
+				mapWork.setLayersControl(window.viewer, this.terrain.terrainData, this.terrain.isTerrain);
+			},
+
+			/**
+			 * 切换标注
+			 */
+			changeMark() {
+				//图层ID
+				let serviceId = "service_" + this.mark.markData.layercode + this.mark.markData.layerorder;
+				this.mark.markData.serviceId = serviceId;
+
+				//透明度
+				let opacity = 1;
+				if (this.mark.markData.opacity == null) {
+					opacity = 1;
+				} else {
+					opacity = Number(this.mark.markData.opacity);
+				}
+				this.mark.markData.opacity = opacity;
+
+				mapWork.setLayersControl(window.viewer, this.mark.markData, this.mark.isMark).then(res => {
+					if (res === true) {
+
+					} else {
+						ElMessage(res)
+					}
+				});
+			},
+
+			/**
+			 * 切换底图事件
+			 * @param {Object} item
+			 */
+			changeBasicLayer(item) {
+
+				this.selectImg = item.layerorder;
+				store.basemap.selectImg = item.layerorder;
+
+
+				//删除底图后再添加
+				mapWork.setLayersControl(window.viewer, this.selectBaseMap, false).then(res => {
+
+					//图层ID
+					let serviceId = "service_" + item.layercode + item.layerorder;
+					item.serviceId = serviceId;
+
+					//透明度
+					let opacity = 1;
+					if (item.opacity == null) {
+						opacity = 1;
+					} else {
+						opacity = Number(item.opacity);
+					}
+					item.opacity = opacity;
+
+					store.basemap.selectBaseMap = item;
+					this.selectBaseMap = item;
+
+					mapWork.setLayersControl(window.viewer, item, true).then(res => {
+						if (res === true) {
+
+						} else {
+							ElMessage(res)
+						}
+					});
+
+				});
+			},
+
+			/**
+			 * 添加底图图集
+			 */
+			initBaseMap() {
+				let _self = this;
+
+				mapWork.getBaseMaps().then(basemaps => {
+					basemaps.forEach(item => {
+						let parameterset = item.parameterset;
+						if (item.parameterset instanceof Object) {
+							parameterset = item.parameterset;
+						} else if (item.parameterset != "" && item.parameterset != null && item.parameterset != undefined) {
+							parameterset = JSON.parse(item.parameterset);
+						}
+
+						if (item.datasource && item.datasource != '#' && item.layertype != '地形' && item.layertype != '标注') {
+							if (parameterset) {
+								if (parameterset.imgurl) {
+									item.imageurl = parameterset.imgurl;
+								} else {
+									item.imageurl = no_img;
+									ElMessage("请检查底图图层表parameterset字段是否设置imgurl");
+								}
+								_self.baseMaps.push(item);
+							}
+						}
+					});
+
+					//底图组件高度不变
+					if (_self.baseMaps.length % 3 == 1) {
+						_self.baseMaps.push({}, {})
+					} else if (_self.baseMaps.length % 3 == 2) {
+						_self.baseMaps.push({})
+					} else if (_self.baseMaps.length % 3 == 0) {
+						_self.baseMaps.push({}, {}, {})
+					}
+				});
+			}
+		},
+		mounted() {
+			this.initBaseMap();
+		}
+	}
+</script>
+
+<style scoped lang="scss">
+	@charset "UTF-8";
+
+	@font-face {
+		font-family: "TTTGB-Medium";
+		src: url("@/assets/fonts/fonts/TTTGB-Medium.ttf") format("truetype"),
+			url("@/assets/fonts/fonts/TTTGB-Medium.eot") format("embedded-opentype"),
+			url("@/assets/fonts/fonts/TTTGB-Medium.svg") format("svg");
+		font-weight: normal;
+		font-style: normal;
+	}
+
+	::v-deep .is-checked .el-switch__core .el-switch__action {
+		margin-left: calc(-1rem - 14rem);
+	}
+
+	::v-deep .el-switch__core .el-switch__action {
+		top: 1rem;
+	}
+
+	::v-deep .el-switch__core .el-switch__action {
+		width: 14rem;
+		height: 14rem;
+	}
+
+	::v-deep .el-switch__core {
+		width: 40rem !important;
+		height: 20rem !important;
+	}
+
+	.jt-basemap {
+		position: absolute;
+		width: 350rem;
+		height: calc(100% - 105rem);
+
+		.top {
+			height: calc(100% - 50rem);
+			padding: 10rem;
+			flex-wrap: wrap;
+			justify-content: space-around;
+			overflow-y: scroll; // 设置y轴方向的滚动条
+			overflow: hidden; // 超出部分隐藏
+
+			.onceLayer {
+				display: inline-block;
+				padding: 5rem;
+				width: 100rem;
+				height: 120rem;
+
+				img {
+					height: 100%;
+					width: 100%;
+					border-radius: 5rem;
+				}
+
+				img:hover {
+					cursor: pointer;
+					height: calc(100% - 0rem);
+					width: calc(100% - 0rem);
+					border: 0rem solid rgba(255, 255, 255, .8);
+					box-shadow: 0 0 2rem 2rem rgba(255, 255, 255, .5);
+					transition: all .2s;
+				}
+
+				//选中图片样式
+				.selectImg {
+					border: 0rem solid rgba(255, 255, 255, .8);
+					box-shadow: 0 0 3rem 3rem rgba(255, 255, 255, .5);
+				}
+
+				span {
+					font-size: 14rem;
+					display: inline-block;
+				}
+			}
+		}
+
+		.bottom {
+			width: 100%;
+			height: 40rem;
+			line-height: 40rem;
+			text-align: left;
+			padding-left: 10rem;
+			border: 0px solid red;
+
+			el-switch {
+				margin: 3rem 0rem;
+				width: 36rem !important;
+			}
+
+			span {
+				margin: 4rem 4rem;
+			}
+		}
+	}
+</style>

+ 347 - 0
src/views/Map3d-自测/components/manage-layer.vue

@@ -0,0 +1,347 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage
+	} from 'element-plus';
+
+	import {
+		Store
+	} from '@/store/index'
+	store = Store();
+
+	import {
+		deepTree
+	} from "@/utils/deepTree.js";
+
+	import {
+		useWidget
+	} from "@/common/store/widget"
+
+	// const {
+	// 	activate,
+	// 	disable,
+	// 	currentWidget
+	// } = useWidget()
+	// currentWidget.onUpdate(() => {
+	// 	treeData = []
+	// 	expandedKeys = []
+	// 	checkedKey = []
+	// 	initTree()
+	// })
+</script>
+
+<template>
+	<jt-popup title="图层控制">
+		<div class="jt-layer">
+			<!-- :default-checked-keys="checkedkeys"  默认勾选的节点的 key 的数组-->
+			<!-- :default-expanded-keys="expandedKeys" 默认展开的节点的 key 的数组-->
+			<!-- @node-click 节点单击事件 -->
+			<el-tree :data="treeData" :default-expanded-keys="expandedKeys" :default-checked-keys="checkedkeys" node-key="id" class="tree-line" ref="treeRef">
+				<template #default="{ node, data }">
+					<!-- 复选框 -->
+					<el-checkbox v-if="data.ischeck == '1' && store.userport == 'PC'" v-model="node.checked" :indeterminate="node.indeterminate" :disabled="!!node.disabled" @change="handleCheckBoxChange($event, data, node)">
+					</el-checkbox>
+					<el-switch v-else-if="data.ischeck == 1 && store.userport == 'APP'" width="30rem" size="small" v-model="node.checked" @change="handleCheckBoxChange($event, data, node)" />
+					<span class="custom-tree-node" @click="handleClick(data)" style="width: 150rem;text-align: left;">
+						<!-- 字体、图标 -->
+						<!-- <span>
+						<img src="@/assets/images/logo16x16.ico" />
+					</span> -->
+						<span class="overflowtext">
+							{{ data.layername }}
+						</span>
+
+					</span>
+
+					<!-- 透明度 -->
+					<template v-if="node.checked && data.opacity >0">
+						<div style="width: 80rem; padding: 0 20rem; position: absolute; right: 0">
+							<el-slider v-model="data.opacity" @input="handleSliderChange($event, data)" :max="1" :min="0.1" :step="0.1" />
+						</div>
+					</template>
+				</template>
+			</el-tree>
+		</div>
+	</jt-popup>
+</template>
+
+<script>
+	let store = undefined
+
+	import * as mapWork from "../map"
+
+	export default {
+
+		/* 数据 */
+		data() {
+			return {
+				treeData: [], //树结构
+				// expandedKeys: [], //对应要展开的节点id
+				// checkedkeys: [], //默认打开节点的id
+
+				expandedKeys: store.expandedKeys, //对应要展开的节点id
+				checkedkeys: store.checkedkeys, //默认打开节点的id
+			}
+		},
+
+		/* 方法 */
+		methods: {
+			/**
+			 * 单击图层名称触发服务定位
+			 * @param {Object} data 传递给 data 属性的数组中该节点所对应的对象
+			 */
+			handleClick(data) {
+				let serviceId =  "service_" + data.layercode + data.layerorder;
+				mapWork.setLayersLocation(window.viewer, {
+					serviceId: _serviceId,
+					parameterset: data.parameterset,
+					isinit: '1',
+					loadtype: data.loadtype
+				}).then(res => {
+					if (res === true) {
+
+					} else {
+						ElMessage(res)
+					}
+				});
+			},
+
+			/**
+			 * el-slider 值改变时触发
+			 * 地图服务的透明度调整
+			 */
+			handleSliderChange($event, data) {
+				let serviceId = "service_" + data.layercode + data.layerorder;
+				mapWork.setLayersAlpha(window.viewer, {
+					loadtype: data.loadtype,
+					serviceId: serviceId,
+					alpha: $event
+				});
+			},
+
+			/**
+			 * el-checkbox 当绑定值变化时触发的事件
+			 * @param {Object} checked 复选框状态
+			 * @param {Object} data 对应于节点点击的节点对象
+			 * @param {Object} node TreeNode 的 node 属性
+			 */
+			handleCheckBoxChange(checked, data, node) {
+				let _node = this.$refs.treeRef.getNode(data);
+				if (_node.isLeaf) {
+
+					//图层ID
+					let serviceId = "service_" + data.layercode + data.layerorder;
+					data.serviceId = serviceId;
+
+					//透明度
+					let opacity = 1;
+					if (data.opacity == null) {
+						opacity = 1;
+					} else {
+						opacity = Number(data.opacity);
+					}
+					data.opacity = opacity;
+
+					mapWork.setLayersControl(window.viewer, data, checked).then(res => {
+						if (res === true) {
+
+						} else {
+							ElMessage(res)
+						}
+					});
+
+					this.$refs.treeRef.setChecked(_node, checked); //是否设置子节点,默认为false,利用tree组件渲染后带有的isLeaf(是否为叶子节点)属性,如果为叶子节点就选中。利用tree的API就实现了正确的回显效果	
+
+				} else {
+					//控制子节点
+					this.childNodesChange(node, checked);
+				}
+			},
+
+			/**
+			 * 控制子节点
+			 * @param {Object} node
+			 * @param {Object} checked
+			 */
+			childNodesChange(node, checked) {
+				let _self = this;
+				node.childNodes.forEach(item => {
+
+					//图层ID
+					let serviceId = "service_" + item.data.layercode + item.data.layerorder;
+					item.data.serviceId = serviceId;
+
+					//透明度
+					let opacity = 1;
+					if (item.data.opacity == null) {
+						opacity = 1;
+					} else {
+						opacity = Number(item.data.opacity);
+					}
+					item.data.opacity = opacity;
+
+					mapWork.setLayersControl(window.viewer, item.data, checked).then(res => {
+						if (res === true) {
+
+						} else {
+							ElMessage(res)
+						}
+					});
+
+					_self.$refs.treeRef.setChecked(item, checked);
+					_self.childNodesChange(item, checked);
+				});
+			},
+
+
+			/**
+			 * 初始化图层控制树
+			 */
+			initLayerTree() {
+				let _self = this;
+
+				mapWork.getLayers().then(layers => {
+
+					layers.map((item) => {
+						let num = Number(item.layerorder)
+						if (num < 10) {
+							item.layerorder = '0' + item.layerorder
+						}
+
+						//透明度
+						item.opacity = Number(item.opacity);
+
+						// //默认展开
+						// if (item.isexpand === '1') {
+						// 	_self.expandedKeys.push(item.id);
+						// }
+
+						// // 复选框默认选中
+						// if (item.isinit === '1') {
+						// 	_self.checkedkeys.push(item.id);
+						// }
+					})
+
+					_self.treeData = deepTree(layers)
+				});
+			}
+		},
+
+		mounted() {
+			this.initLayerTree();
+		},
+	};
+</script>
+
+<style lang="scss">
+	.el-switch--small .el-switch__core .el-switch__action {
+		width: 12rem;
+		height: 12rem;
+	}
+
+	.el-switch--small.is-checked .el-switch__core .el-switch__action {
+		margin-left: calc(-1rem - 12rem);
+	}
+
+	.el-switch__core .el-switch__action {
+		top: 0;
+	}
+
+	.el-slider__button {
+		width: 20rem;
+		height: 20rem;
+	}
+
+	.el-tree-node__content {
+		height: 26rem;
+	}
+
+	.el-switch--small .el-switch__core {
+		height: 16rem;
+	}
+
+	.el-switch--small {
+		padding: 0 5rem;
+	}
+
+	.jt-layer {
+		padding-left: 10rem;
+
+		.el-tree {
+			background: none;
+			color: #fff;
+			--el-tree-node-hover-bg-color: #2a67c3;
+
+			.overflowtext {
+				width: auto !important;
+				padding: 0;
+			}
+		}
+
+		.tree-line {
+			.el-tree-node {
+				position: relative;
+				// padding-left: 16rem; // 缩进量
+			}
+
+			.el-tree-node__children {
+				padding-left: 16rem !important; // 缩进量
+
+				.el-tree-node__content {
+					padding-left: 18rem !important;
+				}
+			}
+
+			// 竖线
+			.el-tree-node::before {
+				content: "";
+				height: 100%;
+				width: 1rem;
+				position: absolute;
+				left: -3rem;
+				top: -26rem;
+				border-width: 1rem;
+				border-left: 1rem dashed rgba(255, 255, 255, .8);
+			}
+
+			// 当前层最后一个节点的竖线高度固定
+			.el-tree-node:last-child::before {
+				height: 38rem; // 可以自己调节到合适数值
+			}
+
+			// 横线
+			.el-tree-node::after {
+				content: "";
+				width: 24rem;
+				height: 20rem;
+				position: absolute;
+				left: -3rem;
+				top: 12rem;
+				border-width: 1rem;
+				border-top: 1rem dashed rgba(255, 255, 255, .8);
+			}
+
+			// 去掉最顶层的虚线,放最下面样式才不会被上面的覆盖了
+			&>.el-tree-node::after {
+				border-top: none;
+			}
+
+			&>.el-tree-node::before {
+				border-left: none;
+			}
+
+			// 展开关闭的icon
+			.el-tree-node__expand-icon {
+				font-size: 16rem;
+
+				// 叶子节点(无子节点)
+				&.is-leaf {
+					color: transparent;
+					display: none; // 也可以去掉
+				}
+			}
+		}
+	}
+</style>

+ 453 - 0
src/views/Map3d-自测/components/map-compare.vue

@@ -0,0 +1,453 @@
+<script setup>
+	import {
+		inject
+	} from "vue";
+	const getMapInstance = inject("getMapInstance");
+	jt3dRight = getMapInstance();
+
+	import {
+		Store
+	} from '@/store/index'
+	store = Store();
+
+	import {
+		deepTree
+	} from "@/utils/deepTree.js";
+</script>
+
+<template>
+	<jt-popup title="分屏对比" animationClass="fadein-left" :isEmit="true" @closeJTPopup="closeJTPopup">
+		<div class="jt-map-compare">
+			<el-tree :data="treeData" :default-expanded-keys="expandedKeys" :default-checked-keys="checkedkeys" node-key="id" class="tree-line" ref="treeRef">
+				<template #default="{ node, data }">
+					<!-- 复选框 -->
+					<el-checkbox v-if="data.ischeck === '1' && store.userport == 'PC'" v-model="node.checked" :indeterminate="node.indeterminate" :disabled="!!node.disabled" @change="handleCheckBoxChange($event, data, node)">
+					</el-checkbox>
+					<el-switch v-else-if="data.ischeck == 1 && store.userport == 'APP'" width="30rem" size="small" v-model="node.checked" @change="handleCheckBoxChange($event, data, node)" />
+					<span class="custom-tree-node" @click="handleClick(data)" style="width: 150rem;text-align: left;">
+						<!-- 字体、图标 -->
+						<!-- <span>
+						<img src="@/assets/images/logo16x16.ico" />
+					</span> -->
+						<span class="overflowtext">
+							{{ data.layername }}
+						</span>
+					</span>
+
+					<!-- 透明度 -->
+					<template v-if="node.checked && data.opacity >0">
+						<div style="width: 80rem; padding: 0 20rem; position: absolute; right: 0">
+							<el-slider v-model="data.opacity" @input="handleSliderChange($event, data)" :max="1" :min="0.1" :step="0.1" />
+						</div>
+					</template>
+				</template>
+			</el-tree>
+		</div>
+	</jt-popup>
+</template>
+
+<script>
+	let store = undefined;
+	let jt3dRight = undefined;
+	let jt3dLeft = undefined;
+
+	import * as mapWork from "../map"
+
+	export default {
+
+		/* 数据 */
+		data() {
+			return {
+				treeData: [],
+				expandedKeys: [], //对应要展开的节点id
+				checkedkeys: [] //默认打开节点的id
+			}
+		},
+
+		/* 方法 */
+		methods: {
+			/**
+			 * 单击图层名称触发服务定位
+			 * @param {Object} data 传递给 data 属性的数组中该节点所对应的对象
+			 */
+			handleClick(data) {
+				let serviceId = "serviceLeft_" + data.layercode + data.layerorder;
+				mapWork.setLayersLocation(window.viewerLeft, {
+					serviceId: serviceId,
+					parameterset: data.parameterset,
+					isinit: '1',
+					loadtype: data.loadtype
+				}).then(res => {
+					if (res === true) {
+
+					} else {
+						ElMessage(res)
+					}
+				});
+			},
+
+			/**
+			 * el-slider 值改变时触发
+			 * 地图服务的透明度调整
+			 */
+			handleSliderChange($event, data) {
+				let serviceId = "serviceLeft_" + data.layercode + data.layerorder;
+				mapWork.setLayersAlpha(window.viewerLeft, {
+					loadtype: data.loadtype,
+					serviceId: serviceId,
+					alpha: $event
+				})
+			},
+
+			/**
+			 * el-checkbox 当绑定值变化时触发的事件
+			 * @param {Object} checked 复选框状态
+			 * @param {Object} data 对应于节点点击的节点对象
+			 * @param {Object} node TreeNode 的 node 属性
+			 */
+			handleCheckBoxChange(checked, data, node) {
+				let _node = this.$refs.treeRef.getNode(data);
+				if (_node.isLeaf) {
+
+					//图层ID
+					let serviceId = "serviceLeft_" + data.layercode + data.layerorder;
+					data.serviceId = serviceId;
+
+					//透明度
+					let opacity = 1;
+					if (data.opacity == null) {
+						opacity = 1;
+					} else {
+						opacity = Number(data.opacity);
+					}
+					data.opacity = opacity;
+
+					mapWork.setLayersControl(window.viewerLeft, data, checked).then(res => {
+						if (res === true) {
+
+						} else {
+							ElMessage(res)
+						}
+					});
+					//是否设置子节点,默认为false,利用tree组件渲染后带有的isLeaf(是否为叶子节点)属性,如果为叶子节点就选中。利用tree的API就实现了正确的回显效果	
+					this.$refs.treeRef.setChecked(_node, checked);
+				}
+
+				//控制子节点
+				this.childNodesChange(node, checked);
+			},
+			/**
+			 * 控制子节点
+			 * @param {Object} node
+			 * @param {Object} checked
+			 */
+			childNodesChange(node, checked) {
+				let _self = this;
+				node.childNodes.forEach(item => {
+					//图层ID
+					let serviceId = "serviceLeft_" + item.data.layercode + item.data.layerorder;
+					item.data.serviceId = serviceId;
+
+					//透明度
+					let opacity = 1;
+					if (item.data.opacity == null) {
+						opacity = 1;
+					} else {
+						opacity = Number(item.data.opacity);
+					}
+					item.data.opacity = opacity;
+
+					mapWork.setLayersControl(window.viewerLeft, item.data, checked).then(res => {
+						if (res === true) {
+
+						} else {
+							ElMessage(res)
+						}
+					});
+
+					_self.$refs.treeRef.setChecked(item, checked);
+					_self.childNodesChange(item, checked);
+				});
+			},
+
+			/**
+			 * 分屏对比初始化
+			 */
+			initSplitScreen() {
+				let mapView1 = document.getElementById("cesiumContainer");
+				let mapView2 = document.getElementById("cesiumContainer2");
+				mapView1.className = "ViewerSplitScreen";
+				mapView2.style.display = "block";
+
+				//加载分屏左侧大球
+				this.initMap3d();
+				//同步相机状态
+				this.syncViewer();
+				//绑定图层控制
+				this.initLayerTree();
+			},
+
+			/**
+			 * 加载分屏左侧大球
+			 */
+			initMap3d() {
+				jt3dLeft = new jt3dSDK.jtMap3d({
+					container: "cesiumContainer2",
+				});
+
+				//底部工具
+				jt3dLeft.statusBar.show = true;
+				//图层
+				jt3dLeft.layer = new jt3dSDK.layer(jt3dLeft._viewer);
+
+				window["viewerLeft"] = jt3dLeft._viewer;
+				window["viewerLeft"].scene.terrainExaggeration = 100;
+
+				//显示帧率
+				window["viewerLeft"].scene.debugShowFramesPerSecond = true;
+
+			},
+
+			/**
+			 * 同步相机状态
+			 */
+			syncViewer() {
+				let _self = this;
+
+				let viewerL = jt3dLeft._viewer;
+				let viewerR = jt3dRight._viewer;
+
+				var sceneL = viewerL.scene;
+				var sceneR = viewerR.scene;
+
+				var handlerL = new Cesium.ScreenSpaceEventHandler(sceneL.canvas);
+				var ellipsoidL = sceneL.globe.ellipsoid;
+				var handlerR = new Cesium.ScreenSpaceEventHandler(sceneR.canvas);
+				var ellipsoidR = sceneR.globe.ellipsoid;
+
+				handlerL.setInputAction((movement) => {
+					this.isLeftTrigger = true;
+					this.isRightTrigger = false;
+				}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
+
+				handlerR.setInputAction((movement) => {
+					this.isLeftTrigger = false;
+					this.isRightTrigger = true;
+				}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
+
+				var syncViewerL = function() {
+					if (_self.isLeftTrigger) {
+						viewerR.camera.flyTo({
+							destination: viewerL.camera.position,
+							orientation: {
+								heading: viewerL.camera.heading,
+								pitch: viewerL.camera.pitch,
+								roll: viewerL.camera.roll
+							},
+							duration: 0.0
+						});
+					}
+				}
+				viewerR.camera.changed.addEventListener(syncViewerL);
+				viewerR.scene.preRender.addEventListener(syncViewerL);
+
+				var syncViewerR = function() {
+					if (_self.isRightTrigger) {
+						viewerL.camera.flyTo({
+							destination: viewerR.camera.position,
+							orientation: {
+								heading: viewerR.camera.heading,
+								pitch: viewerR.camera.pitch,
+								roll: viewerR.camera.roll
+							},
+							duration: 0.0
+						});
+					}
+				}
+				viewerR.camera.changed.addEventListener(syncViewerR);
+				viewerR.scene.preRender.addEventListener(syncViewerR);
+			},
+
+			/**
+			 * 初始化图层控制树
+			 */
+			initLayerTree() {
+
+				let _self = this;
+
+				mapWork.getAllLayers().then(layers => {
+					layers.map((item) => {
+
+						let num = Number(item.layerorder)
+						if (num < 10) {
+							item.layerorder = '0' + item.layerorder
+						}
+
+						//透明度
+						item.opacity = Number(item.opacity);
+
+						//默认展开
+						if (item.isexpand === '1') {
+							_self.expandedKeys.push(item.id);
+						}
+
+						// 复选框默认选中
+						if (item.isinit === '1') {
+							_self.checkedkeys.push(item.id);
+
+							//图层ID
+							let serviceId = "serviceLeft_" + item.layercode + item.layerorder;
+							item.serviceId = serviceId;
+
+							//透明度
+							let opacity = 1;
+							if (item.opacity == null) {
+								opacity = 1;
+							} else {
+								opacity = Number(item.opacity);
+							}
+							item.opacity = opacity;
+
+							mapWork.setLayersControl(window.viewerLeft, item, true).then(res => {
+								if (res === true) {
+
+								} else {
+									ElMessage(res)
+								}
+							});
+						}
+					})
+
+					_self.treeData = deepTree(layers)
+				});
+
+			},
+
+			closeJTPopup() {
+				mapWork.removeSplitScreen(window.viewerLeft);
+			}
+		},
+
+		mounted() {
+			this.initSplitScreen();
+		},
+
+		beforeDestroy() {
+			console.log('实例销毁之前');
+		},
+		destroyed() {
+			console.log('实例销毁完成');
+		}
+	};
+</script>
+
+<style lang="scss">
+	.el-switch--small .el-switch__core .el-switch__action {
+		width: 12rem;
+		height: 12rem;
+	}
+
+	.el-switch--small.is-checked .el-switch__core .el-switch__action {
+		margin-left: calc(-1rem - 12rem);
+	}
+
+	.el-switch__core .el-switch__action {
+		top: 0;
+	}
+
+	.el-slider__button {
+		width: 20rem;
+		height: 20rem;
+	}
+
+	.el-tree-node__content {
+		height: 26rem;
+	}
+
+	.el-switch--small .el-switch__core {
+		height: 16rem;
+	}
+
+	.el-switch--small {
+		padding: 0 5rem;
+	}
+
+	.jt-map-compare {
+		padding-left: 10rem;
+
+		.el-tree {
+			background: none;
+			color: #fff;
+			--el-tree-node-hover-bg-color: #2a67c3;
+
+			.overflowtext {
+				width: auto !important;
+				padding: 0;
+			}
+		}
+
+		.tree-line {
+			.el-tree-node {
+				position: relative;
+				// padding-left: 16rem; // 缩进量
+			}
+
+			.el-tree-node__children {
+				padding-left: 16rem !important; // 缩进量
+
+				.el-tree-node__content {
+					padding-left: 18rem !important;
+				}
+			}
+
+			// 竖线
+			.el-tree-node::before {
+				content: "";
+				height: 100%;
+				width: 1rem;
+				position: absolute;
+				left: -3rem;
+				top: -26rem;
+				border-width: 1rem;
+				border-left: 1rem dashed rgba(255, 255, 255, .8);
+			}
+
+			// 当前层最后一个节点的竖线高度固定
+			.el-tree-node:last-child::before {
+				height: 38rem; // 可以自己调节到合适数值
+			}
+
+			// 横线
+			.el-tree-node::after {
+				content: "";
+				width: 24rem;
+				height: 20rem;
+				position: absolute;
+				left: -3rem;
+				top: 12rem;
+				border-width: 1rem;
+				border-top: 1rem dashed rgba(255, 255, 255, .8);
+			}
+
+			// 去掉最顶层的虚线,放最下面样式才不会被上面的覆盖了
+			&>.el-tree-node::after {
+				border-top: none;
+			}
+
+			&>.el-tree-node::before {
+				border-left: none;
+			}
+
+			// 展开关闭的icon
+			.el-tree-node__expand-icon {
+				font-size: 16rem;
+
+				// 叶子节点(无子节点)
+				&.is-leaf {
+					color: transparent;
+					display: none; // 也可以去掉
+				}
+			}
+		}
+	}
+</style>

+ 314 - 0
src/views/Map3d-自测/components/map-split.vue

@@ -0,0 +1,314 @@
+<script setup>
+	import {
+		Store
+	} from '@/store/index'
+	store = Store();
+
+	import {
+		deepTree
+	} from "@/utils/deepTree.js";
+</script>
+
+<template>
+	<jt-popup title="卷帘对比" :showfooter="isshowfooter" height="120rem" width="620rem" :isEmit="true" @closeJTPopup="closeJTPopup">
+		<div class="jt-map-split">
+			<div class="_left">
+				<div style="line-height: 30rem;float: left;">左侧图层:</div>
+				<el-tree-select v-model="leftModel" :data="leftData" :render-after-expand="true" @change="handleClickLeft" style="width: 200rem; float: left;" />
+			</div>
+			<div class="_right">
+				<div style="line-height: 30rem;float: left;">右侧图层:</div>
+				<el-tree-select v-model="rightModel" :data="rightData" :render-after-expand="true" @change="handleClickRight" style="width: 200rem; float: left;" />
+			</div>
+		</div>
+	</jt-popup>
+</template>
+
+<script>
+	let store = undefined;
+
+	let earthAtLeft = undefined;
+	let earthAtRight = undefined;
+
+	import * as mapWork from "../map"
+
+	//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
+	//例如:import 《组件名称》 from '《组件路径》';
+
+	export default {
+		//import引入的组件需要注入到对象中才能使用
+		components: {},
+
+		//这里存放数据
+		data() {
+
+			return {
+				leftModel: {},
+				leftData: [],
+				leftValue: [],
+				rightModel: {},
+				rightData: [],
+				rightValue: [],
+			};
+		},
+
+		//监听属性 类似于data概念
+		computed: {},
+
+		//监控data中的数据变化
+		watch: {},
+
+		//方法集合
+		methods: {
+			/**
+			 * 左侧图层控制
+			 * @param {Object} item
+			 */
+			handleClickLeft(item) {
+				
+				let _self = this;
+
+				//移除
+				if (earthAtLeft) {
+					mapWork.setLayersControl(window.viewer, _self.leftValue, false);
+				}
+
+				//添加
+				mapWork.setLayersControl(window.viewer, item, true).then(res => {
+					//定位
+					mapWork.setLayersLocation(window.viewer, {
+						serviceId: item.serviceId,
+						parameterset: item.parameterset,
+						loadtype: item.loadtype,
+						isinit: '1',
+					});
+
+					_self.leftValue = item;
+
+					earthAtLeft = window[item.serviceId];
+					earthAtLeft.splitDirection = Cesium.SplitDirection.LEFT;
+				});
+			},
+			
+			/**
+			 * 
+			 * 
+			 * 右侧图层控制
+			 * @param {Object} item
+			 */
+			handleClickRight(item) {
+				
+				let _self = this;
+
+				//移除
+				if (earthAtRight) {
+					mapWork.setLayersControl(window.viewer, _self.rightValue, false);
+				}
+
+				//添加
+				mapWork.setLayersControl(window.viewer, item, true).then(res => {
+					//定位
+					mapWork.setLayersLocation(window.viewer, {
+						serviceId: item.serviceId,
+						parameterset: item.parameterset,
+						loadtype: item.loadtype,
+						isinit: '1',
+					});
+
+					_self.rightValue = item;
+
+					earthAtRight = window[item.serviceId];
+					earthAtRight.splitDirection = Cesium.SplitDirection.RIGHT;
+				});
+
+			},
+
+			/**
+			 * 卷帘对比初始化
+			 */
+			initSplitLayer() {
+				let _self = this;
+				this.viewer = window.viewer;
+
+				let sliderDiv = document.getElementById("image_slider");
+				if (sliderDiv == null) {
+					//创建画布
+					sliderDiv = document.createElement('div');
+					sliderDiv.id = "image_slider";
+					sliderDiv.style.position = "absolute";
+					sliderDiv.style.left = "50%";
+					sliderDiv.style.top = "70rem";
+					sliderDiv.style.backgroundColor = "#d3d3d3";
+					sliderDiv.style.width = "5rem";
+					sliderDiv.style.height = "calc(100% - 70rem)";
+					sliderDiv.style.zIndex = "9999";
+
+					sliderDiv.onmouseover = function() {
+						//设置其背景颜色为黄色
+						this.style.cursor = "ew-resize";
+					};
+
+					/* 加入到页面 */
+					document.body.appendChild(sliderDiv);
+				}
+
+				// 设置图像拆分位置
+				this.viewer.scene.splitPosition = sliderDiv.offsetLeft / sliderDiv.parentElement.offsetWidth; //确定分割点位置,占据父级容器的比例
+
+				if (this.handler) {
+					this.handler.destroy();
+					this.handler = null;
+				}
+				//处理用户输入事件。可以添加自定义功能以在用户输入时执行;参数为任意
+				this.handler = new Cesium.ScreenSpaceEventHandler(sliderDiv);
+				var moveActive = false;
+
+				// 计算拆分
+				function move(movement) {
+					if (!moveActive) {
+						return;
+					}
+
+					//捕获滑动停止的位置
+					var relativeOffset = movement.endPosition.x;
+					var splitPosition = (sliderDiv.offsetLeft + relativeOffset) / sliderDiv.parentElement.offsetWidth;
+					sliderDiv.style.left = `${100.0 * splitPosition}%`;
+					viewer.scene.splitPosition = splitPosition;
+				}
+
+				//对分割条的操作
+				this.handler.setInputAction(function() {
+					moveActive = true;
+				}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
+				this.handler.setInputAction(function() {
+					moveActive = true;
+				}, Cesium.ScreenSpaceEventType.PINCH_START);
+
+				this.handler.setInputAction(move, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
+				this.handler.setInputAction(move, Cesium.ScreenSpaceEventType.PINCH_MOVE);
+
+				this.handler.setInputAction(function() {
+					moveActive = false;
+				}, Cesium.ScreenSpaceEventType.LEFT_UP);
+				this.handler.setInputAction(function() {
+					moveActive = false;
+				}, Cesium.ScreenSpaceEventType.PINCH_END);
+
+				_self.handleClickLeft(_self.leftModel);
+				_self.handleClickRight(_self.rightModel);
+			},
+
+			/**
+			 * 初始化图层控制树
+			 */
+			initLayerTree() {
+				let _self = this;
+
+				mapWork.getLayers().then(layers => {
+					layers.map((item) => {
+						let num = Number(item.layerorder)
+						if (num < 10) {
+							item.layerorder = '0' + item.layerorder
+						}
+
+						//图层ID
+						let serviceId = "service_" + item.layercode + item.layerorder;
+						item.serviceId = serviceId;
+
+						//透明度
+						let opacity = 1;
+						if (item.opacity == null) {
+							opacity = 1;
+						} else {
+							opacity = Number(item.opacity);
+						}
+						item.opacity = opacity;
+
+						item.value = item;
+						item.label = item.layername;
+
+						if (item.layername === "二调") {
+							_self.leftModel = item;
+						}
+						if (item.layername === "三调") {
+							_self.rightModel = item;
+						}
+					})
+
+					_self.leftData = _self.rightData = deepTree(layers)
+					_self.initSplitLayer();
+
+				});
+
+			},
+
+			/**
+			 * 移除卷帘
+			 */
+			removeSplitLayer() {
+				let sliderDiv = document.getElementById("image_slider");
+				if (sliderDiv) {
+					document.body.removeChild(sliderDiv);
+				}
+
+				if (earthAtLeft) {
+					mapWork.setLayersControl(window.viewer, this.leftValue, false);
+					earthAtLeft.splitDirection = Cesium.SplitDirection.NONE;
+				}
+
+				if (earthAtRight) {
+					mapWork.setLayersControl(window.viewer, this.rightValue, false);
+					earthAtRight.splitDirection = Cesium.SplitDirection.NONE;
+				}
+			},
+
+			closeJTPopup() {
+				if (window.viewerLeft) {
+					mapWork.removeSplitScreen(window.viewerLeft);
+				}
+				// mapWork.removeSplitLayer(window.viewer, earthAtLeft, earthAtRight,_self.leftValue,_self.rightValue);
+				this.removeSplitLayer();
+			}
+		},
+
+		//生命周期 - 创建完成(可以访问当前this实例)
+		created() {},
+
+		//生命周期 - 挂载完成(可以访问DOM元素)
+		mounted() {
+			this.initLayerTree();
+		},
+
+		beforeCreate() {}, //生命周期 - 创建之前
+		beforeMount() {}, //生命周期 - 挂载之前
+		beforeUpdate() {}, //生命周期 - 更新之前
+		updated() {}, //生命周期 - 更新之后
+		beforeDestroy() {}, //生命周期 - 销毁之前
+		destroyed() {}, //生命周期 - 销毁完成
+		activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+	};
+</script>
+
+<style lang="scss" scoped>
+	//整体样式
+	.jt-map-split {
+		// padding: 10rem;
+
+		//左侧
+		._left {
+			width: 300rem;
+			float: left;
+		}
+
+		//右侧
+		._right {
+			width: 300rem;
+			float: left;
+			margin-left: 10rem;
+		}
+
+		.el-tree {
+			width: 300rem !important;
+		}
+	}
+</style>

+ 101 - 0
src/views/Map3d-自测/components/map.vue

@@ -0,0 +1,101 @@
+<template>
+	<div id="cesiumContainer2" class="ViewerSplitScreen" style="display: none; border-right: 5rem solid #fff"></div>
+	<div id="cesiumContainer" class="jt-map" ref="cesiumContainer"></div>
+</template>
+
+<script>
+	import * as mapWork from "../map"
+
+	let jt3d = undefined;
+	export default {
+
+		/* 数据 */
+		data() {
+			return {
+
+			}
+		},
+
+		/* 方法 */
+		methods: {
+			/**
+			 * 初始化
+			 */
+			init(el) {
+				//初始化大球
+				this.initMap3d(el);
+				//调用父组件的方法,onload是在父组件的的动态组件component上面的方法,并将jt3d传过去
+				this.$emit("onload", jt3d);
+
+				//设置默认视图
+				mapWork.setView(jt3d);
+
+				// 初始化项目区域范围视角
+				mapWork.fullMap(jt3d);
+
+				//加载天空盒子
+				mapWork.addSkybox(jt3d);	
+
+				//单击事件
+				// mapWork.clickEntity(jt3d);
+
+				//添加镇街边界线——精灵线
+				mapWork.addBoundaryLine(jt3d);
+
+			},
+
+			/**
+			 * 创建大球
+			 */
+			initMap3d(el) {
+
+				jt3d = new jt3dSDK.jtMap3d({
+					container: el,
+				});
+
+				jt3d.statusBar.show = true;
+
+				window["viewer"] = jt3d._viewer;
+				window["viewer"].scene.terrainExaggeration = 100;
+
+				//显示帧率
+				window["viewer"].scene.debugShowFramesPerSecond = true;
+			},
+
+		},
+
+		mounted() {
+			this.init("cesiumContainer");
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.lk-status-bar {
+		font-size: 16rem !important;
+	}
+
+	.jt-map {
+		// width: calc(100% - 0rem);
+		// height: calc(100vh - 70rem);
+		height: 100vh;
+		margin: 0;
+		padding: 0;
+		overflow: hidden;
+		background-color: blue;
+		border: 0rem solid red;
+	}
+
+	//分屏样式
+	.ViewerSplitScreen {
+		float: left;
+		width: calc(50% - 2.5rem);
+		// height: calc(100vh - 70rem);
+		height: 100vh;
+		margin: 0;
+
+		.lk-status-bar {
+			width: calc(50% - 0rem) !important;
+		}
+	}
+</style>

+ 242 - 0
src/views/Map3d-自测/components/measure.vue

@@ -0,0 +1,242 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage
+	} from 'element-plus';
+
+	import {
+		inject
+	} from "vue";
+
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	<div class="jt-measure">
+		<el-row :gutter="20" style="margin-left: 0rem; margin-right: 0rem; ">
+			<el-col :span="8" v-for="(item,index) in measure" @click="handleMeasure(item.type,index)">
+				<el-avatar shape="circle" :size="70" :class="currentIndex===index?'selectStyle':'defaultStyle'">
+					<i :class="[item.icon,currentIndex===index?'selectFontStyle':'']" />
+				</el-avatar>
+				<div style="margin-top: 5rem; font-size: 14rem;" :class="currentIndex===index?'selectFontStyle':''">{{item.label}}</div>
+			</el-col>
+		</el-row>
+		<div class="jt-btn" style="margin: 8rem;">
+			<el-button color="rgb(255 100 100)" @click="clearMeasurementData"><span style="color: #fff;width: 300rem;">清空测量数据</span></el-button>
+		</div>
+	</div>
+</template>
+
+<script>
+	let jt3d = undefined;
+	let popup = undefined;
+
+	export default {
+		props: {
+
+		},
+		watch: {
+
+		},
+
+		/* 数据 */
+		data() {
+			return {
+				currentIndex: -1,
+				measure: [{
+						label: '长度测量(贴地)',
+						type: 'measureLength',
+						number: 0,
+						icon: 'iconfont icon-thin-_pencil_rul'
+					},
+					{
+						label: '面积测量(贴地)',
+						type: 'measureArea',
+						number: 1,
+						icon: 'iconfont icon-svgmianjiceliang'
+					},
+					{
+						label: '高度测量',
+						type: 'measureHeight',
+						number: 2,
+						icon: 'iconfont icon-svggaoduceliang'
+					},
+					{
+						label: '空间距离',
+						type: 'measureSpatialLength',
+						number: 3,
+						icon: 'iconfont icon-svgkongjianceliang'
+					},
+					{
+						label: '三角测量',
+						type: 'measureTriangle',
+						number: 4,
+						icon: 'iconfont icon-svgsanjiaoceliang'
+					},
+					{
+						label: '坐标测量',
+						type: 'pickUp',
+						number: 5,
+						icon: 'iconfont icon-svgzuobiaoceliang'
+					},
+				],
+			}
+		},
+
+		/* 方法 */
+		methods: {
+			/**
+			 * 测量事件
+			 * @param {Object} type 测量类型
+			 * @param {Object} index 第几个被选中
+			 */
+			handleMeasure(type, index) {
+				this.currentIndex = index;
+
+				//移除左键单击事件
+				if (jt3d.handlerLeftClick) {
+					jt3d.handlerLeftClick.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
+				}
+
+				jt3d.CommonTools.clear();
+
+				switch (type) {
+					case "measureLength": //长度测量(贴地)
+						jt3d.CommonTools.measureLength(function(error) {
+							ElMessage.error(error)
+						});
+						break;
+					case "measureArea": //面积测量(贴地)
+						jt3d.CommonTools.measureArea(function(error) {
+							ElMessage.error(error)
+						});
+						break;
+					case "measureHeight": //高度测量
+						jt3d.CommonTools.measureHeight()
+						break;
+					case "measureSpatialLength": //空间距离
+						jt3d.CommonTools.measureSpatialLength(function(error) {
+							ElMessage.error(error)
+						});
+						break;
+					case "measureTriangle": //三角测量
+						jt3d.CommonTools.measureTriangle()
+						break;
+					case "pickUp": //坐标测量
+						ElMessage("点击位置开始测量");
+						this.pickUp();
+						break;
+				}
+			},
+
+			/**
+			 * 坐标测量
+			 */
+			pickUp() {
+				let _self = this;
+
+				if (popup) {
+					popup.close();
+				}
+
+				jt3d.SketchViewModel.sketchTools('point', {
+					onComplete(cPoint, gPoint) {
+						if (gPoint.lng) {
+							let html = "";
+							html += "<div style='text-align: left;'>";
+							html += "<p>经度:" + gPoint.lng.toFixed(6) + "</p>";
+							html += "<p>纬度:" + gPoint.lat.toFixed(6) + "</p>";
+							html += "<p>高度:" + gPoint.height.toFixed(2) + "米</p>";
+							html += "</div>";
+
+							let position = {
+								x: Number(gPoint.lng),
+								y: Number(gPoint.lat),
+								z: Number(gPoint.height)
+							}
+
+							// popup = new jt3dSDK.PopupWindow.HtmlWindow(window["viewer"], position, "位置信息", html,40);
+							popup = new jt3dSDK.PopupWindow.HtmlWindow(window["viewer"], cPoint, "位置信息", html, -30);
+						}
+					},
+					onError(message) {
+						
+					}
+				});
+			},
+
+			/**
+			 * 清空测量数据
+			 */
+			clearMeasurementData() {
+				this.currentIndex = -1;
+				jt3d.CommonTools.clear();
+				if (popup) {
+					popup.close();
+				}
+
+				//还原左键单击事件
+				this.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+			},
+		},
+
+		mounted() {
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.el-avatar{
+		width: 70rem !important;
+		height: 70rem !important;
+		font-size: 14px !important;
+		cursor: pointer;
+	}
+	
+	.el-button{
+		height: 32rem;
+		font-size: 16rem;
+		padding: 8rem 15rem;
+	}
+	
+	.jt-measure {
+		.el-col {
+			padding: 10rem;
+			// color: rgba(90, 172, 255, 1.0);
+			color: #fff;
+		}
+
+		i {
+			display: inline-block;
+			width: 100%;
+			height: 36rem;
+			line-height: 36rem;
+			text-align: center;
+			border-radius: 5rem;
+			font-size: 40rem;
+			// color: rgba(90, 172, 255, 1.0);
+			color: #fff;
+			transition: all .3s;
+			-webkit-transition: all .3s
+		}
+
+		.selectStyle {
+			// background: rgba(135, 182, 254, 0.5);
+			background: rgb(0 44 126);
+			--el-avatar-size: 70rem !important;
+		}
+
+		.defaultStyle {
+			background: #ffffff00;
+			--el-avatar-size: 70rem !important;
+		}
+
+		.selectFontStyle {
+			color: #fff;
+		}
+	}
+</style>

+ 278 - 0
src/views/Map3d-自测/components/navigation.vue

@@ -0,0 +1,278 @@
+<script setup>
+
+	import jt3dNavigation from 'cesium-navigation-es6';
+
+	import {
+		inject
+	} from "vue";
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	
+</template>
+
+<script>
+	let jt3d = undefined;
+	export default {
+		props: {
+
+		},
+
+		/**
+		 * 数据
+		 */
+		data() {
+			return {
+		
+			}
+		},
+
+		/**
+		 * 方法
+		 */
+		methods: {
+			/**
+			 * 比例尺、指南针
+			 */
+			initNavigation(jt3d) {
+				let options = {};
+				// 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是Cesium.Cartographic 和 Cesium.Rectangle.
+				options.defaultResetView = Cesium.Rectangle.fromDegrees(121.13766, 36.99670, 121.94984, 37.55286);
+				// options.defaultResetView = Cesium.Cartographic.fromDegrees(103.84,31.15,24000);
+				// options.defaultResetView = Cesium.Cartographic.fromDegrees(Cesium.Math.toRadians(103.84),Cesium.Math.toRadians(31.15),Cesium.Math.toRadians(24000));
+				options.orientation = {
+					heading: Cesium.Math.toRadians(0),
+					pitch: Cesium.Math.toRadians(-90),
+					roll: 0
+				};
+			
+				//相机延时
+				options.duration = 4; //默认为3s
+			
+				// 用于启用或禁用罗盘。
+				options.enableCompass = true;
+				// 用于启用或禁用指南针外环。
+				options.enableCompassOuterRing = true;
+				// 用于启用或禁用缩放控件。
+				options.enableZoomControls = true;
+				// 用于启用或禁用距离图例。
+				options.enableDistanceLegend = false;
+			
+				//修改重置视图的tooltip
+				options.resetTooltip = "重置视图";
+				//修改放大按钮的tooltip
+				options.zoomInTooltip = "放大";
+				//修改缩小按钮的tooltip
+				options.zoomOutTooltip = "缩小";
+			
+				//如需自定义罗盘控件,请看下面的自定义罗盘控件
+				new jt3dNavigation(jt3d._viewer, options);
+			},
+
+		},
+
+		mounted() {
+			//比例尺、指南针
+			this.initNavigation(jt3d);
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	$jt3d-text-color:#fff;
+	$jt3d-content-color:#fff;
+
+	$jt3d-select-bg:red;
+
+	.query-keyword {
+		position: absolute;
+		top: 80rem;
+		width: 200rem;
+		left: 10rem;
+		border: 1rem solid rgb(0 44 126 / 100%);
+
+		.el-input {
+			--el-input-bg-color: rgb(0 44 126 / 50%);
+			--el-input-border-color: rgb(0 44 126 / 50%);
+			--el-input-placeholder-color: #fff;
+
+			--el-fill-color-blank: rgb(0 44 126 / 80%);
+			--el-text-color-regular: #fff;
+			--el-color-primary: #fff --el-border-radius-base:0rem;
+			--el-border-radius-base: 0rem;
+
+			.el-button {
+				background-color: rgb(0 44 126 / 100%);
+				color: #fff;
+			}
+		}
+
+		.autocomplete {
+			--el-fill-color-blank: rgb(0 44 126 / 0%);
+		}
+	}
+
+	.autocomplete ul {
+		font-family: sans-serif;
+		position: absolute;
+		list-style: none;
+		background: rgb(0 44 126 / 30%);
+		margin: 0;
+		width: 80%;
+		margin-top: 1rem;
+		margin-left: -1rem;
+		border: 1rem solid rgb(0 44 126 / 100%);
+	}
+
+	.autocomplete ul li {
+		text-decoration: none;
+		display: block;
+		background: rgb(0 44 126 / 30%);
+		color: #fff;
+		padding: 5rem;
+		margin-left: -40rem;
+		text-align: left;
+	}
+
+	.autocomplete ul li:hover,
+	.autocomplete ul li.focus-list {
+		color: white;
+		background: #2F9AF7;
+	}
+
+	.query-result {
+		position: absolute;
+		border-top: none;
+		padding-bottom: 0rem;
+		width: 100%;
+		z-index: 100;
+		border: 1rem solid rgb(0 44 126 / 100%);
+		background: rgb(0 44 126 / 30%);
+		margin-left: -1rem;
+
+		--el-fill-color-blank: rgb(0 44 126 / 0%);
+		--color: #fff;
+		--el-color-primary: #fff;
+
+		.query-result__item {
+			height: 80rem;
+			padding: 0 10rem;
+			display: flex;
+			justify-content: flex-start;
+			align-items: center;
+			margin-left: -40rem;
+			text-align: left;
+
+			&:hover {
+				// background-color: var(--mars-select-bg);
+			}
+
+			.query-result__context {
+				flex-grow: 1;
+				width: 90%;
+
+				.query-result-text {
+					font-size: 16rem;
+					width: 200rem;
+					font-family: Source Han Sans CN;
+					font-weight: 400;
+					// color: var($jt3d-text-color);
+					color: $jt3d-text-color;
+
+					.query-result-text_num {
+						width: 20rem;
+						height: 20rem;
+						margin-right: 5rem;
+						display: inline-block;
+						text-align: center;
+						background: rgb(0 44 126 / 100%);
+					}
+				}
+
+				.query-result-sub {
+					font-size: 14rem;
+					width: 200rem;
+					margin-left: 19rem;
+					font-family: Source Han Sans CN;
+					font-weight: 400;
+					// color: var($jt3d-content-color);
+					color: $jt3d-content-color;
+				}
+			}
+
+			.query-result__more {
+				font-size: 14rem;
+				font-family: Source Han Sans CN;
+				font-weight: 400;
+				// color: var($jt3d-content-color);
+				color: $jt3d-content-color;
+			}
+		}
+
+		.query-result__page {
+			display: flex;
+			justify-content: space-between;
+			padding: 5rem;
+
+			.query-result-allcount {
+				font-size: 14rem;
+				// color: var($jt3d-text-color);
+				color: $jt3d-text-color;
+			}
+		}
+	}
+	
+	/* 四个边角样式 */
+	// .borderstyle {
+	// 	position: relative;
+	// 	width: 100%;
+	// 	height: 490rem;
+	// 	padding: 10rem;
+	// 	border: 1rem solid #008aff70 !important;
+	// 	background-color: rgba(5, 45, 115, 0.7) !important;
+	// 	box-shadow: 0 4rem 15rem 1rem #02213bb3;
+	
+
+		.angle-border {
+			position: absolute;
+			width: 12rem;
+			height: 12rem;
+		}
+	
+		.angle-border-blue {
+			position: absolute;
+			width: 70rem;
+			height: 30rem;
+		}
+	
+		.left-top-border {
+			top: -2rem;
+			left: -2rem;
+			border-left: 2rem solid #008affdd;
+			border-top: 2rem solid #008affdd;
+		}
+	
+		.right-top-border {
+			top: -2rem;
+			right: -2rem;
+			border-right: 2rem solid #008affdd;
+			border-top: 2rem solid #008affdd;
+		}
+	
+		.left-bottom-border {
+			bottom: -2rem;
+			left: -2rem;
+			border-bottom: 2rem solid #FFFFFF;
+			border-left: 2rem solid #FFFFFF;
+		}
+	
+		.right-bottom-border {
+			bottom: -2rem;
+			right: -2rem;
+			border-right: 2rem solid #FFFFFF;
+			border-bottom: 2rem solid #FFFFFF;
+		}
+	// }
+</style>

+ 318 - 0
src/views/Map3d-自测/components/printmap.vue

@@ -0,0 +1,318 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage
+	} from 'element-plus';
+
+	import {
+		ref
+	} from "vue";
+	import {
+		inject
+	} from "vue";
+	import html2canvas from "html2canvas";
+
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	<div class="jt-MapPrinting">
+		<div class="middleviewer">
+			<el-input v-model="inputValue.mapname" placeholder="请输入地图名称" @focus="getfous" @blur="onblur" />
+			<div class="viewer">
+				<div id="printbox" ref="print"></div>
+				<div class="viewertop" display='block' ref="thumbnailmap"></div>
+				<div style="display:none" ref="originalmap"></div>
+			</div>
+		</div>
+		<div class="viewerbottom">
+			<!-- <el-button color="rgb(20 136 255)" v-print="printObj"><span style="color: #fff;font-size: 16rem;">打 印</span></el-button> -->
+			<el-button color="rgb(255 100 100)" @click="download"><span style="color: #fff;font-size: 16rem;">下 载</span></el-button>
+		</div>
+	</div>
+</template>
+
+<script>
+	let jt3d = undefined;
+	export default {
+		data() {
+			return {
+				inputValue: {
+					mapname: "默认地图",
+				},
+
+				printObj: {
+					id: "printbox",
+					popTitle: "", // 打印配置页上方的标题
+					extraCss: "background-color:red",
+					preview: false, // 是否启动预览模式,默认是false
+					previewTitle: " 关闭预览", // 打印预览的标题
+					previewPrintBtnLabel: "点击打印", // 打印预览的标题下方的按钮文本,点击可进入打印
+					zIndex: 20002, // 预览窗口的z-index,默认是20002,最好比默认值更高
+					previewBeforeOpenCallback() {
+						console.log("正在加载预览窗口!")
+					}, // 预览窗口打开之前的callback
+					previewOpenCallback() {
+						console.log("已经加载完预览窗口,预览打开了!");
+					}, // 预览窗口打开时的callback
+					beforeOpenCallback() {
+						console.log("开始打印之前!");
+					}, // 开始打印之前的callback
+					openCallback() {
+						console.log("执行打印了!");
+					}, // 调用打印时的callback
+					closeCallback() {
+						console.log("关闭了打印工具!");
+					},
+					clickMounted() {
+						console.log("点击v-print绑定的按钮了!");
+					},
+					standard: "",
+					extarCss: "",
+				},
+			};
+		},
+		methods: {
+			//当选择器的输入框获得焦点时触发,标题获取焦点清空输入框
+			getfous() {
+				this.inputValue.mapname = ""
+			},
+
+			//当选择器的输入框失去焦点时触发
+			onblur() {
+				//删除print组件的内容
+				this.$refs.print.innerHTML = "";
+				// 获取标题
+				let value = this.inputValue.mapname;
+
+				//获取输入框的缺省内容
+				let text = value.length > 0 ? value : '默认地图标题';
+				let canvas = this.changcanvastitile(this.$refs.originalmap.lastChild, text);
+				let url = canvas.toDataURL('image/png', 5.0)
+				let img = document.createElement('img');
+				img.style.display = "block"
+				img.style.width = canvas.style.width;
+				img.style.height = canvas.style.height;
+				img.src = url
+				this.$refs.print.appendChild(img);
+			},
+
+			//下载按钮
+			download() {
+				if (this.$refs.originalmap.children.length <= 0) {
+					ElMessage.error("截图未成功");
+					return
+				}
+				let value = this.inputValue.mapname;
+				//获取输入框的缺省内容
+				let text = value.length > 0 ? value : '默认地图标题';
+
+				let img = this.$refs.print.lastChild;
+				let a = document.createElement('a');
+				a.style.display = 'none';
+				a.download = text + '.png';
+				a.href = img.src;
+				document.body.appendChild(a);
+				a.click();
+				document.body.removeChild(a);
+			},
+
+			//更新打印标题
+			changcanvastitile(canvas, text) {
+
+				//清理标题位置区域
+				let width = parseInt(canvas.style.width.slice(0, -2));
+				let height = parseInt(canvas.style.height.slice(0, -2));
+				//获取上下文
+				const ctx = canvas.getContext('2d');
+				//清理标题问题
+				ctx.clearRect(0, 0, width, 160)
+				//设置字体
+				ctx.font = "bold 50rem arial";
+				document.fonts.load(ctx.font);
+				//设置填充颜色
+				ctx.fillStyle = "black";
+				//循环输入标题,字间距50rem
+				for (let i = 0; i < text.length; i++) {
+					//第I个字的水平位置=((canvs.leght)/2-(text.legth)*letterspace/2+i*letterspace)
+					let x = Math.ceil(width / 2) - (text.length - 1) * 50 + i * 100
+					//水平绘制填充文本
+					ctx.fillText(text[i], x, 100);
+				}
+				return canvas;
+			},
+
+			//打印地图截屏
+			screenshot() {
+				this.$refs.print.innerHTML = "";
+				this.$refs.thumbnailmap.innerHTML = ""
+				this.$refs.originalmap.innerHTML = '';
+				this.inputValue.mapname = "默认地图"
+				html2canvas(this.$parent.$parent.$refs.refMap3d.$refs.cesiumContainer, {
+
+					// backgroundColor: null, //画出来的图片有白色的边框,不要可设置背景为透明色(null)
+					useCORS: true, //支持图片跨域
+					scale: 1, //设置放大的倍数
+					// tainTest:false,
+					// foreignObjectRendering: true,//// 是否在浏览器支持的情况下使用ForeignObject渲染
+					dpi: 300,
+					// width:1920,
+					// height:1080
+
+				}).then(
+					(canvas) => {
+						let url = canvas.toDataURL('image/png', 5.0)
+						let img = document.createElement('img');
+						img.style.display = "block"
+						img.style.width = "calc(100% - 0rem)"
+						img.style.height = "calc(100% - 0rem)";
+						img.src = url
+						//缩略图
+						this.$refs.thumbnailmap.appendChild(img);
+						//创建新的canvas
+						let canvasnew = this.createmap(canvas)
+						let urla = canvasnew.toDataURL('image/png', 5.0)
+						let imga = document.createElement('img');
+						imga.style.display = "block"
+						imga.style.width = canvas.style.width / 2;
+						imga.style.height = canvas.style.height / 2;
+						imga.src = urla
+						//原图
+						this.$refs.originalmap.appendChild(canvasnew);
+						//打印图
+						this.$refs.print.appendChild(imga)
+					}
+				)
+			},
+
+			createmap(img) {
+				//渲染之前先清理掉所有所有指定canvas
+				if (document.getElementById('canvasid')) {
+					document.getElementById('canvasid').remove();
+				}
+				let width = parseInt(img.style.width.slice(0, -2));
+				let height = parseInt(img.style.height.slice(0, -2));
+
+				let canvas = this.createHDCanvas(width + 60, height + 160, 'block')
+
+				//获取上下文
+				const ctx = canvas.getContext('2d');
+				//获取图片对象
+				ctx.drawImage(img, 30, 120, width, height)
+				// let value = this.$refs.refinput.value;
+				let value = this.inputValue.mapname;
+				let text = value.length > 0 ? value : '默认地图标题';
+				console.log("text")
+				console.log(text)
+				ctx.clearRect(0, 0, width, 120)
+				//设置字体
+				ctx.font = "bold 50rem arial";
+				//设置填充颜色
+				ctx.fillStyle = "black";
+				//循环输入标题,字间距50rem
+				for (let i = 0; i < text.length; i++) {
+					//第I个字的水平位置=((canvs.leght)/2-(text.legth)*letterspace/2+i*letterspace)
+					let x = Math.ceil(width / 2) - (text.length - 1) * 50 + i * 100
+					//水平绘制填充文本
+					ctx.fillText(text[i], x, 100);
+				}
+				return canvas;
+			},
+			createHDCanvas(w = 300, h = 150, display = 'block') {
+				let ratio = window.devicePixelRatio * 1 || 1;
+				let canvas = document.createElement('canvas');
+				canvas.id = "canvasid";
+				canvas.width = w * ratio; // 实际渲染像素
+				canvas.height = h * ratio; // 实际渲染像素
+				canvas.style.display = display;
+				canvas.style.width = `${w}rem`; // 控制显示大小
+				canvas.style.height = `${h}rem`; // 控制显示大小
+				canvas.style.backgroundColor = "red";
+				// setTransform() 允许您缩放、旋转、移动并倾斜当前的环境
+				canvas.getContext('2d').setTransform(ratio, 0, 0, ratio, 0, 0);
+				return canvas;
+			},
+		},
+
+		mounted() {
+			// //获取角色
+			// this.info = JSON.parse(localStorage.getItem("person"));
+			// //获取角色id
+			// this.id = this.info.id;
+			// this.$bus.on("screenshot", (e) => {
+			// 	console.log("aaaaa")
+			// 	this.screenshot()
+			// })
+		},
+	};
+</script>
+
+<style lang="scss" scoped>
+	.jt-MapPrinting {
+		width: 100%;
+		height: 100%;
+		overflow: hidden;
+
+		--el-fill-color-blank: rgb(0 44 126 / 68%);
+		--el-text-color-regular: rgb(216 240 255);
+		--el-border-color: rgb(35 135 255);
+
+		.middleviewer {
+			height: 92%;
+
+			.viewer {
+				position: relative;
+				width: 100% !important;
+				height: calc(100% - 29rem) !important;
+				overflow: hidden;
+
+				.viewertop {
+					width: calc(100% - 2rem);
+					height: calc(100% - 2rem);
+					border: 1rem solid rgb(35 135 255);
+					position: absolute;
+					top: 0;
+					left: 0;
+				}
+			}
+		}
+
+		.viewerbottom {
+			margin: 10rem;
+		}
+	}
+
+	::v-deep .el-input {
+		flex-grow: 0 !important;
+		width: calc(100%);
+		height: 30rem !important;
+		letter-spacing: 100rem;
+	}
+
+	//输入框文字颜色
+	::v-deep .el-input__inner {
+		color: rgb(255, 255, 255);
+		text-align: center;
+	}
+
+	//输入框背景色
+	::v-deep .el-input__wrapper {
+		background-color: rgba(255, 255, 255, 0) !important;
+	}
+
+	::v-deep .el-button {
+		border-radius: 3rem !important;
+		height: 32rem;
+	}
+
+	::v-deep .el-button--primary {
+		background-color: rgba(64, 158, 255, 0.6) !important;
+	}
+
+	::-webkit-scrollbar {
+		width: 0rem;
+	}
+</style>

+ 465 - 0
src/views/Map3d-自测/components/query-graphics.vue

@@ -0,0 +1,465 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage,
+		ElLoading
+	} from 'element-plus';
+
+	import {
+		inject
+	} from "vue";
+
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	<div class="jt-query-graphics">
+		<el-row :gutter="20" style="margin-left: 0rem; margin-right: 0rem">
+			<el-col :span="8" v-for="(item,index) in queryGraphics" @click="handleQueryGraphics(item.type,index)">
+				<el-avatar shape="circle" :size="70" :class="currentIndex===index?'selectStyle':'defaultStyle'">
+					<i :class="[item.icon,currentIndex===index?'selectFontStyle':'']" />
+				</el-avatar>
+				<div style="margin-top: 5rem; font-size: 14rem;" :class="currentIndex===index?'selectFontStyle':''">{{item.label}}</div>
+			</el-col>
+		</el-row>
+	</div>
+</template>
+
+<script>
+	let jt3d = undefined;
+	let loading = undefined;
+
+	import {
+		Store
+	} from '@/store/index'
+	let store = Store();
+
+	import {
+		deepTree
+	} from "@/utils/deepTree.js";
+
+	export default {
+		props: {
+
+		},
+		watch: {
+
+		},
+
+		/* 数据 */
+		data() {
+			return {
+				currentIndex: -1,
+				queryGraphics: [{
+						label: '点查询',
+						type: 'Point',
+						number: 0,
+						icon: 'iconfont icon-svgdianchaxun'
+					},
+					{
+						label: '线查询',
+						type: 'Line',
+						number: 1,
+						icon: 'iconfont icon-svgxianchaxun'
+					},
+					{
+						label: '圆形查询',
+						type: 'Circle',
+						number: 2,
+						icon: 'iconfont icon-svgyuanxingchaxun'
+					},
+					{
+						label: '矩形查询',
+						type: 'Rectangle',
+						number: 3,
+						icon: 'iconfont icon-svgjuxingchaxun'
+					},
+					{
+						label: '多边形',
+						type: 'Polygon',
+						number: 4,
+						icon: 'iconfont icon-svgduobianxingchaxun'
+					},
+					{
+						label: '清除',
+						type: 'clear',
+						number: 5,
+						icon: 'iconfont icon-shanchu'
+					},
+				],
+			}
+		},
+
+		/* 方法 */
+		methods: {
+			/**
+			 * 查询事件
+			 * @param {Object} type 查询类型
+			 * @param {Object} index 第几个被选中
+			 */
+			handleQueryGraphics(type, index) {
+				let _self = this;
+				this.currentIndex = index;
+
+				//移除左键单击事件
+				if (jt3d.handlerLeftClick) {
+					jt3d.handlerLeftClick.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); //移除事件
+				}
+
+				jt3d.CommonTools.clear();
+				switch (type) {
+					case "Point": //点查询
+						jt3d.CommonTools.queryByPoint(function(coordinates) {
+							console.log(coordinates)
+
+							//还原左键单击事件
+							_self.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+
+							/* 转换坐标 */
+							let points = coordinates.split(',');
+
+							_self.initQuery({
+								spatialType: '点',
+								coordinate: Number(points[0]) + " " + Number(points[1]),
+								buffer: ''
+							});
+
+						});
+						break;
+					case "Line": //线查询
+						jt3d.CommonTools.queryByLine(function(coordinates) {
+							console.log(coordinates)
+
+							//还原左键单击事件
+							_self.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+
+							/* 转换坐标 */
+							let points = coordinates.split(',');
+							let pointsArray = [];
+							for (let i = 0; i < points.length;) {
+								pointsArray.push(Number(points[i]) + " " + Number(points[i + 1]));
+								i = i + 2;
+							}
+
+							_self.initQuery({
+								spatialType: '线',
+								coordinate: pointsArray.join(','),
+								buffer: ''
+							});
+						});
+						break;
+					case "Circle": //圆形查询
+						jt3d.CommonTools.queryByCircle(function(coordinates, radius) {
+							console.log("圆点:" + coordinates + ",半径:" + radius)
+
+							//还原左键单击事件
+							_self.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+
+							/* 转换坐标 */
+							let points = coordinates.split(',');
+
+							_self.initQuery({
+								spatialType: '点',
+								coordinate: Number(points[0]) + " " + Number(points[1]),
+								buffer: radius
+							});
+
+						});
+						break;
+					case "Rectangle": //矩形查询
+						jt3d.CommonTools.queryByRectangle(function(coordinates) {
+							console.log(coordinates)
+
+							//还原左键单击事件
+							_self.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+
+							/* 转换坐标 */
+							let points = coordinates.split(',');
+							let pointsArray = [];
+							for (let i = 0; i < points.length;) {
+								pointsArray.push(Number(points[i]) + " " + Number(points[i + 1]));
+								i = i + 2;
+							}
+
+							_self.initQuery({
+								spatialType: '面',
+								coordinate: pointsArray.join(','),
+								buffer: ''
+							});
+
+						});
+						break;
+					case "Polygon": //多边形查询
+						jt3d.CommonTools.queryByPolygon(function(coordinates) {
+							console.log(coordinates)
+
+							//还原左键单击事件
+							_self.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+
+							/* 转换坐标 */
+							let points = coordinates.split(',');
+							let pointsArray = [];
+							for (let i = 0; i < points.length;) {
+								pointsArray.push(Number(points[i]) + " " + Number(points[i + 1]));
+								i = i + 2;
+							}
+
+							_self.initQuery({
+								spatialType: '面',
+								coordinate: pointsArray.join(','),
+								buffer: ''
+							});
+
+						});
+						break;
+					case "clear": //清除查询效果
+						this.currentIndex = -1;
+
+						//清除绘制
+						jt3d.CommonTools.clear();
+
+						//还原左键单击事件
+						this.$parent.$parent.$refs.refMap3d.clickEntity(jt3d);
+
+						//清除高亮显示
+						let list = jt3d._dataSources.getByName("单击高亮显示")
+						list.forEach(res => {
+							jt3d._dataSources.remove(res)
+						})
+
+						//清除定位样式
+						if (jt3d.LocateUtil._locationEntity) {
+							window["viewer"].entities.remove(jt3d.LocateUtil._locationEntity);
+						}
+						break;
+				}
+			},
+
+			/**
+			 * @param {Object} options
+			 */
+			initQuery(options) {
+				let _self = this;
+				let treeNodes = [];
+
+				//清除高亮显示
+				let list = jt3d._dataSources.getByName("单击高亮显示")
+				list.forEach(res => {
+					jt3d._dataSources.remove(res)
+				})
+
+				//清除定位样式
+				if (jt3d.LocateUtil._locationEntity) {
+					window["viewer"].entities.remove(jt3d.LocateUtil._locationEntity);
+				}
+
+				const getData = () => {
+
+					if (store.queryMapTables.length > 0) {
+						//查询等待框
+						loading = ElLoading.service({
+							lock: true,
+							text: 'Loading',
+							background: 'rgba(0, 0, 0, 0.7)',
+						});
+
+						let data = [];
+						store.queryMapTables.forEach((itemTable, index) => {
+							let result = getAxios(itemTable, options);
+							data.push(result);
+						})
+
+						Promise.all(data).then(itemList => {
+
+							console.log("itemList", itemList) //itemList返回的数据是按顺序的
+							//执行自己接下来的操作
+							//doSomething
+
+							itemList.forEach((item, index) => {
+								let field = item.table;
+								let tableName = item.table[0].tableName;
+								let tableDescription = item.table[0].tableDescription;
+
+								if (item.data.features.length > 0) {
+									//添加父节点
+									let parentNode = {
+										id: tableName,
+										parentid: "CIM",
+										label: tableDescription + "(" + item.data.features.length + ")",
+									};
+									treeNodes.push(parentNode);
+
+									item.data.features.forEach((itemData, index) => {
+
+										//**************高亮显示****************
+
+										// /* 转换坐标 */
+										// let positions = itemData.geometry.coordinates[0][0].map(point => {
+										// 	return Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2] || 0);
+										// });
+
+										// //先创建一个CustomDataSource源,然后把entity存入这里面
+										// let Polygon = new Cesium.CustomDataSource("单击高亮显示");
+										// jt3d._dataSources.add(Polygon);
+										// //添加数据的方式
+										// Polygon.entities.add({
+										// 	polygon: {
+										// 		hierarchy: new Cesium.PolygonHierarchy(positions),
+										// 		material: Cesium.Color.fromCssColorString("rgba(255,0,255,.7)"),
+										// 		classificationType: Cesium.ClassificationType.BOTH,
+										// 	},
+										// });
+
+										//**************高亮显示****************
+
+										let childNode = {
+											id: itemData.properties["id"],
+											parentid: tableName,
+											field: field,
+											data: itemData,
+										};
+
+										switch (tableName) {
+											//==============规划管理数据-重要控制线=========================
+											case "yjjbnt": //永久基本农田
+												childNode.label = itemData.properties["cfzr"] + "(" + itemData.properties["zzsxmc"] + ")"
+												break;
+											case "yjtz": //永久基本农田调整
+												childNode.label = itemData.properties["zldwmc"] + "(" + itemData.properties["dlmc"] + ")"
+												break;
+											case "bnrgdbh": //不纳入耕地保护目标
+												childNode.label = itemData.properties["zldwmc"] + "(" + itemData.properties["dlmc"] + ")"
+												break;
+											case "gdbhrw": //耕地保护任务
+												childNode.label = itemData.properties["zldwmc"] + "(" + itemData.properties["dlmc"] + ")"
+												break;
+
+												//==============规划管理数据-历史规划==============
+											case "tdzgh": //土地利用总体规划
+												childNode.label = itemData.properties["ghdlmc"]
+												break;
+											case "jsyd": //建设用地管制区
+												childNode.label = itemData.properties["id"]
+												break;
+
+												//==============现状类数据-森林资源-森林资源调查==============
+											case "slyzt": //2019年森林资源管理一张图
+												childNode.label = itemData.properties["id"]
+												break;
+
+												//==============现状类数据-国土调查==============
+											case "ed2009": //二调
+												childNode.label = itemData.properties["zldwmc"] + "(" + itemData.properties["dlmc"] + ")"
+												break;
+											case "ed2020": //二调2020
+												childNode.label = itemData.properties["zldwmc"] + "(" + itemData.properties["dlmc"] + ")"
+												break;
+											case "ed2021": //二调2021
+												childNode.label = itemData.properties["zldwmc"] + "(" + itemData.properties["dlmc"] + ")"
+												break;
+											case "sddltb": //三调   
+												childNode.label = itemData.properties["zldwmc"] + "(" + itemData.properties["dlmc"] + ")"
+												break;
+										}
+
+										treeNodes.push(childNode);
+									});
+								}
+							});
+
+							//处理查询结果树
+							if (treeNodes.length > 0) {
+
+								_self.$parent.$parent.$refs.refQueryResult.expandedKeys = []
+								_self.$parent.$parent.$refs.refQueryResultPopup.isshow = true;
+								_self.$parent.$parent.$refs.refQueryResult.treeData = deepTree(treeNodes);
+
+								//默认选中第一个节点并赋予选中样式
+								_self.$nextTick(function() {
+									let currentNode = _self.$parent.$parent.$refs.refQueryResult.treeData[0].children[0];
+									let currentKey = currentNode.id;
+									_self.$parent.$parent.$refs.refQueryResult.currentKey = currentKey;
+									_self.$parent.$parent.$refs.refQueryResult.$refs.tree.setCurrentKey(currentKey);
+									_self.$parent.$parent.$refs.refQueryResult.handleNodeClick(currentNode);
+								});
+
+								//expandedKeys默认展开treedata第一层,加载第一层数据
+								_self.$parent.$parent.$refs.refQueryResult.expandedKeys.push(_self.$parent.$parent.$refs.refQueryResult.treeData[0].id)
+							}
+
+							//清除绘制
+							jt3d.CommonTools.clear();
+
+							//关闭等待框
+							loading.close()
+
+						})
+					}
+				}
+
+				const getAxios = (itemTable, options) => {
+					return new Promise(function(resolve, reject) {
+						_self.$http.get('/getSpatialQuery', {
+							tableName: itemTable,
+							spatialType: options.spatialType,
+							coordinate: options.coordinate,
+							buffer: options.buffer
+						}).then(res => {
+							resolve(res)
+						});
+					}).catch(err => {
+
+					})
+				}
+
+				getData();
+			},
+		},
+
+		mounted() {
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.jt-query-graphics {
+		.el-col {
+			padding: 10rem;
+			// color: rgba(90, 172, 255, 1.0);
+			//color: #55ffff;
+			color: #fff;
+		}
+
+		i {
+			display: inline-block;
+			width: 100%;
+			height: 36rem;
+			line-height: 36rem;
+			text-align: center;
+			border-radius: 5rem;
+			font-size: 40rem;
+			// color: rgba(90, 172, 255, 1.0);
+			// color: #55ffff;
+			color: #fff;
+			transition: all .3s;
+			-webkit-transition: all .3s
+		}
+
+		.selectStyle {
+			// background: rgba(135, 182, 254, 0.5);
+			background: rgb(0 44 126);
+		}
+
+		.defaultStyle {
+			background: #ffffff00;
+		}
+
+		.selectFontStyle {
+			color: #fff;
+		}
+	}
+</style>

+ 365 - 0
src/views/Map3d-自测/components/query-keyword.vue

@@ -0,0 +1,365 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage
+	} from 'element-plus';
+
+	/**
+	 * element-plus字体
+	 */
+	import {
+		Search,
+		DArrowRight
+	} from '@element-plus/icons-vue';
+	import {
+		inject
+	} from "vue";
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	<div class="query-keyword fadein-left">
+		<el-input v-model="search.searchKey" placeholder="请输入查询关键字" @change="searchKeyChange" @input="searchKeyChange" clearable>
+			<template #append>
+				<el-button :icon="Search" @click="btnSearchClick" />
+			</template>
+		</el-input>
+		<div class="autocomplete " v-if="search.searchListShow">
+			<ul>
+				<li v-for="(item,index) in search.searchCompleteData" :key="index" @click="SearchSelect(index)">
+					{{ item }}
+				</li>
+			</ul>
+		</div>
+		<div class="query-result" v-if="resultListShow">
+			<template v-if="resultCompleteData && resultCompleteData.length">
+				<ul>
+					<li v-for="(item, i) in resultCompleteData" :key="i" class="query-result__item" @click.stop="flyTo(item)">
+						<div class="query-result__context">
+							<p class="query-result-text" :title="item.name">
+								<span class="query-result-text_num">{{ i + 1 }}</span>
+								{{ item.name }}
+							</p>
+							<p class="query-result-sub">{{ item.label }}</p>
+						</div>
+						<p class="query-result__more">
+							<el-icon>
+								<DArrowRight />
+							</el-icon>
+						</p>
+					</li>
+				</ul>
+				<div class="query-result__page">
+					<p class="query-result-allcount">共{{ resultCompleteData.length }}条结果</p>
+					<el-pagination layout="prev, pager, next" size="small" :total="resultCompleteData.length" pageSize="1" :simple="true" />
+				</div>
+			</template>
+		</div>
+	</div>
+</template>
+
+<script>
+	let jt3d = undefined;
+	export default {
+		props: {
+
+		},
+
+		/**
+		 * 数据
+		 */
+		data() {
+			return {
+				search: {
+					searchKey: "", // input框输入的值,用v-model双向绑定
+					searchDataList: [], // autocomplete查询数据,一般由后端返回
+					searchCompleteData: [], // autocomplete查询到的数据
+					searchListShow: false,
+				},
+				resultCompleteData: [], // 查询结果
+				resultListShow: false,
+				pagination: {
+					size: "small",
+					total: 0,
+					pageSize: 6,
+					simple: true
+				}
+			}
+		},
+
+		/**
+		 * 方法
+		 */
+		methods: {
+			
+			/**
+			 * 在 Input 值改变时触发
+			 * 当 modelValue 改变时,当输入框失去焦点或用户按Enter时触发
+			 */
+			searchKeyChange() {
+				let _self = this;
+				this.search.searchListShow = true;
+				this.resultListShow = false;
+				let searchRegex = new RegExp(this.search.searchKey, 'i');
+				this.search.searchCompleteData = []; // 先把原有的数据清空,重新查询
+				if (this.search.searchKey === '') return; //如果什么都没有输入,则不用查找
+				this.search.searchDataList.forEach((item) => {
+					if (searchRegex.test(item.label)) {
+						_self.search.searchCompleteData.push(item.label)
+					}
+				});
+			},
+
+			/**
+			 * 选中联想查询数据
+			 * @param {Object} index
+			 */
+			SearchSelect(index) {
+				this.search.searchListShow = false;
+				console.log(this.search.searchCompleteData[index]);
+				this.getSearchData(this.search.searchCompleteData[index]);
+			},
+
+			/**
+			 * 查询按钮
+			 */
+			btnSearchClick() {
+				if (this.search.searchKey === "") {
+					ElMessage("请输入查询关键字");
+					return;
+				}
+				this.getSearchData(this.search.searchKey);
+			},
+
+			/**
+			 * 数据查询
+			 * @param {Object} queryString
+			 */
+			getSearchData(queryString) {
+				let _self = this;
+				_self.$http.get('/getTableList', {
+					tableName: 'base_sys_role',
+					sqlWhere: " label like '%" + queryString + "%'",
+					orderByField: ''
+				}).then(res => {
+					console.log('从服务端搜索数据', res.data)
+					_self.resultCompleteData = res.data;
+					_self.resultListShow = true;
+					_self.search.searchListShow = false;
+				});
+			}
+		},
+
+		mounted() {
+			let _self = this;
+			_self.$http.get('/getTableList', {
+				tableName: 'base_sys_role',
+				sqlWhere: '',
+				orderByField: ''
+			}).then(res => {
+				console.log('从服务端搜索数据', res.data)
+				_self.search.searchDataList = res.data;
+			});
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	$jt3d-text-color:#fff;
+	$jt3d-content-color:#fff;
+
+	$jt3d-select-bg:red;
+
+	.query-keyword {
+		position: absolute;
+		top: 80rem;
+		width: 200rem;
+		left: 10rem;
+		border: 1rem solid rgb(0 44 126 / 100%);
+
+		.el-input {
+			--el-input-bg-color: rgb(0 44 126 / 50%);
+			--el-input-border-color: rgb(0 44 126 / 50%);
+			--el-input-placeholder-color: #fff;
+
+			--el-fill-color-blank: rgb(0 44 126 / 80%);
+			--el-text-color-regular: #fff;
+			--el-color-primary: #fff --el-border-radius-base:0rem;
+			--el-border-radius-base: 0rem;
+
+			.el-button {
+				background-color: rgb(0 44 126 / 100%);
+				color: #fff;
+			}
+		}
+
+		.autocomplete {
+			--el-fill-color-blank: rgb(0 44 126 / 0%);
+		}
+	}
+
+	.autocomplete ul {
+		font-family: sans-serif;
+		position: absolute;
+		list-style: none;
+		background: rgb(0 44 126 / 30%);
+		margin: 0;
+		width: 80%;
+		margin-top: 1rem;
+		margin-left: -1rem;
+		border: 1rem solid rgb(0 44 126 / 100%);
+	}
+
+	.autocomplete ul li {
+		text-decoration: none;
+		display: block;
+		background: rgb(0 44 126 / 30%);
+		color: #fff;
+		padding: 5rem;
+		margin-left: -40rem;
+		text-align: left;
+	}
+
+	.autocomplete ul li:hover,
+	.autocomplete ul li.focus-list {
+		color: white;
+		background: #2F9AF7;
+	}
+
+	.query-result {
+		position: absolute;
+		border-top: none;
+		padding-bottom: 0rem;
+		width: 100%;
+		z-index: 100;
+		border: 1rem solid rgb(0 44 126 / 100%);
+		background: rgb(0 44 126 / 30%);
+		margin-left: -1rem;
+
+		--el-fill-color-blank: rgb(0 44 126 / 0%);
+		--color: #fff;
+		--el-color-primary: #fff;
+
+		.query-result__item {
+			height: 80rem;
+			padding: 0 10rem;
+			display: flex;
+			justify-content: flex-start;
+			align-items: center;
+			margin-left: -40rem;
+			text-align: left;
+
+			&:hover {
+				// background-color: var(--mars-select-bg);
+			}
+
+			.query-result__context {
+				flex-grow: 1;
+				width: 90%;
+
+				.query-result-text {
+					font-size: 16rem;
+					width: 200rem;
+					font-family: Source Han Sans CN;
+					font-weight: 400;
+					// color: var($jt3d-text-color);
+					color: $jt3d-text-color;
+
+					.query-result-text_num {
+						width: 20rem;
+						height: 20rem;
+						margin-right: 5rem;
+						display: inline-block;
+						text-align: center;
+						background: rgb(0 44 126 / 100%);
+					}
+				}
+
+				.query-result-sub {
+					font-size: 14rem;
+					width: 200rem;
+					margin-left: 19rem;
+					font-family: Source Han Sans CN;
+					font-weight: 400;
+					// color: var($jt3d-content-color);
+					color: $jt3d-content-color;
+				}
+			}
+
+			.query-result__more {
+				font-size: 14rem;
+				font-family: Source Han Sans CN;
+				font-weight: 400;
+				// color: var($jt3d-content-color);
+				color: $jt3d-content-color;
+			}
+		}
+
+		.query-result__page {
+			display: flex;
+			justify-content: space-between;
+			padding: 5rem;
+
+			.query-result-allcount {
+				font-size: 14rem;
+				// color: var($jt3d-text-color);
+				color: $jt3d-text-color;
+			}
+		}
+	}
+	
+	/* 四个边角样式 */
+	// .borderstyle {
+	// 	position: relative;
+	// 	width: 100%;
+	// 	height: 490rem;
+	// 	padding: 10rem;
+	// 	border: 1rem solid #008aff70 !important;
+	// 	background-color: rgba(5, 45, 115, 0.7) !important;
+	// 	box-shadow: 0 4rem 15rem 1rem #02213bb3;
+	
+
+		.angle-border {
+			position: absolute;
+			width: 12rem;
+			height: 12rem;
+		}
+	
+		.angle-border-blue {
+			position: absolute;
+			width: 70rem;
+			height: 30rem;
+		}
+	
+		.left-top-border {
+			top: -2rem;
+			left: -2rem;
+			border-left: 2rem solid #008affdd;
+			border-top: 2rem solid #008affdd;
+		}
+	
+		.right-top-border {
+			top: -2rem;
+			right: -2rem;
+			border-right: 2rem solid #008affdd;
+			border-top: 2rem solid #008affdd;
+		}
+	
+		.left-bottom-border {
+			bottom: -2rem;
+			left: -2rem;
+			border-bottom: 2rem solid #FFFFFF;
+			border-left: 2rem solid #FFFFFF;
+		}
+	
+		.right-bottom-border {
+			bottom: -2rem;
+			right: -2rem;
+			border-right: 2rem solid #FFFFFF;
+			border-bottom: 2rem solid #FFFFFF;
+		}
+	// }
+</style>

+ 300 - 0
src/views/Map3d-自测/components/queryResult.vue

@@ -0,0 +1,300 @@
+<script setup>
+	import {
+		formattingTime
+	} from '@/assets/js/localtime.js';
+
+	import {
+		inject
+	} from "vue";
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+<template>
+	<div class="jt-queryResult">
+		<div class="_left">
+			<el-tree class="tree-line queryResultTree" ref="tree" node-key="id" :data="treeData" :default-expanded-keys="expandedKeys" :current-node-key="currentKey" @node-click="handleNodeClick" highlight-current />
+		</div>
+		<div class="_right">
+			<div id="detailDiv"></div>
+		</div>
+	</div>
+</template>
+
+<script>
+	let jt3d = undefined;
+
+	export default {
+		props: {
+			tree: {
+				type: Object,
+				default () {
+					return []
+				}
+			}
+		},
+		data() {
+			return {
+				treeData: this.tree,
+				currentKey: "",
+				expandedKeys: [], //对应要展开的节点id
+			}
+		},
+		methods: {
+			/**
+			 * 树单击事件
+			 */
+			handleNodeClick(treeNode) {
+
+				let _self = this;
+
+				return new Promise((resolve, reject) => {
+
+					if (treeNode.parentid != 'CIM') {
+
+						//清除高亮显示
+						let list = jt3d._dataSources.getByName("单击高亮显示")
+						list.forEach(res => {
+							jt3d._dataSources.remove(res)
+						})
+
+						//高亮显示并定位显示详细信息
+						jt3d.PolygonObject.generatePolygonByPoints(treeNode.data.geometry.coordinates[0][0], {
+							color: [255, 0, 255, 0],
+							outline: true,
+							outlineWidth: 5,
+							outlineColor: [0, 255, 180, 1]
+						}).then((locationEntity) => {
+							// 初始化定位参数
+							let options = {};
+							options.duration = Cesium.defaultValue(options.duration, 2);
+							options.heading = Cesium.defaultValue(options.heading, 0);
+							options.pitch = Cesium.defaultValue(options.pitch, -60);
+							options.range = Cesium.defaultValue(options.range, 800.0);
+
+							let flyToEntity = jt3d.LocateUtil.flyToEntity(locationEntity, options);
+							flyToEntity.then(function(flag) {
+								//详细信息
+								let strHtml = "";
+								strHtml += "<table>";
+								strHtml += "<thead>";
+								strHtml += "<tr>";
+								strHtml += "<th>属性名</th>";
+								strHtml += "<th>属性值</th>";
+								strHtml += "</tr> ";
+								strHtml += " </thead>";
+								strHtml += "<tbody>";
+
+								var field = treeNode.field;
+								var properties = treeNode.data.properties
+								field.forEach(itemField => {
+									if (itemField.isDisplay === 1) {
+										var fieldDesc = itemField.fieldDescription || itemField
+											.fieldName;
+										var fieldVals = properties[itemField.fieldName];
+
+										//日期格式
+										if (itemField.fieldType === 1) {
+											let time = new Date(fieldVals).getTime();
+											fieldVals = formattingTime(time);
+										}
+
+										if (fieldVals != null && fieldVals != "" && fieldVals !=
+											undefined) {
+											strHtml += "<tr>";
+											strHtml += "<td>" + fieldDesc + "</td>";
+											strHtml += "<td>" + fieldVals + "</td>";
+											strHtml += "</tr>";
+										}
+									}
+								});
+
+								strHtml += "</tbody>";
+								strHtml += "</table>";
+
+								let divb = document.getElementById('detailDiv')
+								divb.innerHTML = strHtml; //设置显示的数据,可以是标签.
+
+							});
+
+						});
+					}
+
+					resolve(1)
+				})
+			},
+
+		},
+		mounted() {}
+	}
+</script>
+
+<style lang="scss">
+	.jt-queryResult {
+		overflow: hidden;
+
+		//左侧树
+		&>div:nth-child(1) {
+			width: 220rem;
+			height: 380rem;
+			float: left;
+			overflow: auto;
+			border-right: 5rem solid #ddd;
+
+			.el-tree {
+				background: rgb(28 59 112 / 0%);
+				height: calc(100% - 2rem);
+				color: #fff;
+				--el-tree-node-hover-bg-color: #2a67c3;
+				--el-font-size-base: 14rem;
+
+				.overflowtext {
+					width: auto !important;
+					padding: 0;
+				}
+			}
+
+
+
+			.tree-line {
+				.el-tree-node {
+					position: relative;
+				}
+
+				.el-tree-node__children {
+					padding-left: 16rem !important; // 缩进量
+
+					.el-tree-node__content {
+						padding-left: 18rem !important;
+					}
+				}
+
+				//高亮显示选中样式
+				.el-tree-node.is-current>.el-tree-node__content {
+					background: #2a67c3;
+				}
+
+				// 竖线
+				.el-tree-node::before {
+					content: "";
+					height: 100%;
+					width: 1rem;
+					position: absolute;
+					left: -3rem;
+					top: -26rem;
+					border-width: 1rem;
+					border-left: 1rem dashed rgba(255, 255, 255, .8);
+				}
+
+				// 当前层最后一个节点的竖线高度固定
+				.el-tree-node:last-child::before {
+					height: 38rem; // 可以自己调节到合适数值
+				}
+
+				// 横线
+				.el-tree-node::after {
+					content: "";
+					width: 24rem;
+					height: 20rem;
+					position: absolute;
+					left: -3rem;
+					top: 12rem;
+					border-width: 1rem;
+					border-top: 1rem dashed rgba(255, 255, 255, .8);
+				}
+
+				// 去掉最顶层的虚线,放最下面样式才不会被上面的覆盖了
+				&>.el-tree-node::after {
+					border-top: none;
+				}
+
+				&>.el-tree-node::before {
+					border-left: none;
+				}
+
+				// 展开关闭的icon
+				.el-tree-node__expand-icon {
+					font-size: 16rem;
+
+					// 叶子节点(无子节点)
+					&.is-leaf {
+						color: transparent;
+						display: none; // 也可以去掉
+					}
+				}
+			}
+
+		}
+
+		//右侧基本信息
+		&>div:nth-child(2) {
+			width: calc(100% - 240rem);
+			height: calc(100% - 0rem);
+			float: left;
+			margin-left: 10rem;
+			font-size: 14rem;
+			padding-top: 5rem;
+
+			table {
+				border-collapse: collapse;
+				margin: 0 auto;
+				text-align: center;
+				width: 100%;
+			}
+
+			table td,
+			table th {
+				// border: 1rem solid #ddd;
+				color: #fff;
+				height: 30rem;
+			}
+
+			table thead th {
+				background-color: rgb(28 59 112 / 100%);
+				border: 2rem solid #ddd;
+			}
+
+			table tr:nth-child(odd) {
+				background: rgb(40 89 172 / 60%);
+				border-left: 2rem solid #ddd;
+				border-right: 2rem solid #ddd;
+				border-bottom: 1rem solid #ddd;
+			}
+
+			table tr:nth-child(even) {
+				background: rgb(28 59 112 / 60%);
+				border-left: 2rem solid #ddd;
+				border-right: 2rem solid #ddd;
+				border-bottom: 1rem solid #ddd;
+			}
+
+			// thead 表头固定,tbody 滚动
+			table>thead>tr {
+				display: table;
+				width: 100%;
+				table-layout: fixed;
+			}
+
+			table>tbody {
+				display: block;
+				height: 340rem;
+				/* 隐藏水平溢出内容 */
+				overflow-x: hidden;
+				/* 当垂直内容超出显示高度时以滚动条形式展示 */
+				overflow-y: auto;
+			}
+
+			table>tbody>tr {
+				/* 将tr设置为table元素,以此达到内容沾满table的效果 */
+				display: table;
+				/* 将tr宽度设置为100%,以此达到内容沾满table的效果 */
+				width: 100%;
+				/* 设置table-layout为fixed以达到首行和内容行对其的效果 */
+				table-layout: fixed;
+			}
+
+			table>tbody>tr>td {
+				border-right: 2rem solid #ddd;
+			}
+		}
+	}
+</style>

+ 401 - 0
src/views/Map3d-自测/components/special-effects.vue

@@ -0,0 +1,401 @@
+<script setup>
+	import {
+		inject
+	} from "vue";
+
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	<div class="jt-weather-effects">
+		<el-collapse v-model="activeName" accordion>
+			<el-collapse-item name="特效效果">
+				<template #title>
+					<span class='iconfont icon-tianqizitiku43' />天气特效
+				</template>
+				<el-row :gutter="20">
+					<el-col :span="8" v-for="(item,index) in weather" @click="handleWeatherEffects(item.type,index)">
+						<el-avatar shape="circle" style="width:70rem;height: 70rem;" :class="currentIndex===index?'selectStyle':'defaultStyle'">
+							<i :class="[item.icon,currentIndex===index?'selectFontStyle':'']" />
+						</el-avatar>
+						<div style="margin-top: 5rem; font-size: 14rem;" :class="currentIndex===index?'selectFontStyle':''">{{item.label}}</div>
+					</el-col>
+				</el-row>
+			</el-collapse-item>
+			<el-collapse-item name="天空样式">
+				<template #title>
+					<span class='iconfont icon-tianqizitiku43' />天空样式
+				</template>
+				<el-row :gutter="20">
+					<el-col :span="8" v-for="(item,index) in skybox" @click="handleSkybox(item.type,index)">
+						<!-- <el-avatar :src="item.url" /> -->
+						<el-avatar shape="circle" src="https://empty" style="width:70rem;height: 70rem;">
+							<img :src="item.url" />
+						</el-avatar>
+						<div style="margin-top: 5rem; font-size: 14rem;" :class="currentIndex===index?'selectFontStyle':''">{{item.label}}</div>
+					</el-col>
+				</el-row>
+			</el-collapse-item>
+			<!-- <el-collapse-item name="粒子效果">
+				<template #title>
+					<span class='iconfont icon-tianqizitiku43' />粒子效果
+				</template>
+				<div class="el-collapse-item__content">
+					<el-button color="rgb(20 136 255)" @click="ParticleSystem('add')">加载粒子效果</el-button>
+					<el-button color="rgb(255 100 100)" @click="ParticleSystem('remove')"><span style="color: #fff;">清除粒子效果</span></el-button>
+				</div>
+			</el-collapse-item>
+			<el-collapse-item name="热力图">
+				<template #title>
+					<span class='iconfont icon-tianqizitiku43' />热力图
+				</template>
+				<div class="el-collapse-item__content">
+					<el-button color="rgb(20 136 255)" @click="HeatMap('add')">添加热力图</el-button>
+					<el-button color="rgb(255 100 100)" @click="HeatMap('remove')"><span style="color: #fff;">清除热力图</span></el-button>
+				</div>
+			</el-collapse-item> -->
+		</el-collapse>
+	</div>
+</template>
+
+<script>
+	let jt3d = undefined;
+
+	export default {
+		data() {
+			return {
+				activeName: "特效效果",
+				currentIndex: -1,
+				weather: [{
+						label: '雨天',
+						type: 'rain',
+						number: 0,
+						icon: 'iconfont icon-yu'
+					},
+					{
+						label: '雪天',
+						type: 'snow',
+						number: 1,
+						icon: 'iconfont icon-huaban'
+					},
+					{
+						label: '雾天',
+						type: 'fog',
+						number: 2,
+						icon: 'iconfont icon-tianqizitiku43'
+					},
+					{
+						label: '关闭天气',
+						type: 'remove',
+						number: 3,
+						icon: 'iconfont icon-cloudofftianqiguanbi'
+					},
+				],
+				skybox: [{
+						label: '晚霞',
+						type: '晚霞',
+						number: 0,
+						url: 'jt3dSDK/imgs/skybox/01/py.png'
+					},
+					{
+						label: '蓝天',
+						type: '蓝天',
+						number: 1,
+						url: 'jt3dSDK/imgs/skybox/03/py.jpg'
+					},
+					{
+						label: '阴天',
+						type: '阴天',
+						number: 2,
+						url: 'jt3dSDK/imgs/skybox/02/py.jpg'
+					},
+					{
+						label: '蓝色星空',
+						type: '蓝色星空',
+						number: 3,
+						url: 'jt3dSDK/imgs/skybox/05/pz.jpg'
+					},
+					{
+						label: '紫色星空',
+						type: '紫色星空',
+						number: 4,
+						url: 'jt3dSDK/imgs/skybox/04/ny.jpg'
+					},
+				],
+			}
+		},
+		props: {},
+		watch: {},
+
+		/* 方法 */
+		methods: {
+			/**
+			 * 天空盒子事件
+			 * @param {Object} type 天空盒子类型
+			 * @param {Object} index 第几个被选中
+			 */
+			handleSkybox(type, index) {
+				this.currentIndex = index;
+
+				jt3d.SceneEffects.SkyBox.setGroundSkyBox({
+					type: type
+				});
+			},
+
+			/**
+			 * 天气特效事件
+			 * @param {Object} type 天气类型
+			 * @param {Object} index 第几个被选中
+			 */
+			handleWeatherEffects(type, index) {
+				this.currentIndex = index;
+				switch (type) {
+					case "rain": //雨天
+						jt3d.SceneEffects.Weather.removeEffect();
+						jt3d.SceneEffects.Weather.addRainEffect({
+							tiltAngle: 0.3,
+							rainSize: 0.5,
+							rainSpeed: 70
+						});
+						break;
+					case "snow": //雪天
+						jt3d.SceneEffects.Weather.removeEffect();
+						jt3d.SceneEffects.Weather.addSnowEffect();
+						break;
+					case "fog": //雾天
+						jt3d.SceneEffects.Weather.removeEffect();
+						jt3d.SceneEffects.Weather.addFogEffect();
+						break;
+					case "remove": //移除天气特效
+						this.currentIndex = -1;
+						jt3d.SceneEffects.Weather.removeEffect()
+						break;
+
+				}
+			},
+
+			/**
+			 * 粒子效果
+			 */
+			ParticleSystem(type) {
+				let options = {};
+				// 初始化参数默认值
+				options.duration = Cesium.defaultValue(options.duration, 2);
+				options.heading = Cesium.defaultValue(options.heading, 0.5); //指向,默认值0.0(北)
+				options.pitch = Cesium.defaultValue(options.pitch, -40); //俯仰角, 垂直向下。默认值-90(向下看)。
+				options.range = Cesium.defaultValue(options.range, 150); //距目标点距离
+
+				const position = {
+					x: 121.554042,
+					y: 37.395186,
+					z: 25.60
+				};
+
+				// 定位到点
+				let flyToPoint = jt3d.LocateUtil.flyToPoint({
+					longitude: position.x,
+					latitude: position.y,
+					height: position.z,
+					duration: options.duration,
+					heading: options.heading,
+					pitch: options.pitch,
+					range: options.range,
+				});
+				flyToPoint.then(function() {
+					// alert(1111)
+				});
+
+				if (type === "add") {
+
+					const positionF = {
+						x: 121.554042,
+						y: 37.395186,
+						z: 25.60
+					};
+
+					this.fireArr = [];
+					this.waterArr = [];
+
+					let fireEntity = jt3d.SceneEffects.ParticleSystem.createParticleFire([positionF.x, positionF.y, positionF.z])
+					this.fireArr.push(fireEntity)
+
+					const positionW = {
+						x: 121.553975,
+						y: 37.395075,
+						z: 18.10
+					};
+
+					let waterEntity = jt3d.SceneEffects.ParticleSystem.createParticleWater([positionW.x, positionW.y, positionW.z])
+					this.waterArr.push(waterEntity)
+
+				}
+				if (type === "remove") {
+					for (var i = 0; i < this.fireArr.length; i++) {
+						this.fireArr[i].remove()
+					}
+					for (var i = 0; i < this.waterArr.length; i++) {
+						this.waterArr[i].remove()
+					}
+				}
+			},
+
+			/**
+			 * 热力图
+			 */
+			HeatMap(type) {
+
+				if (type === "add") {
+					let viewer = this.viewer = window["viewer"];
+
+					// 矩形坐标
+					var bounds = {
+						west: 121.563298,
+						south: 37.284514,
+						east: 121.565298,
+						north: 37.286514,
+					};
+
+					// 初始化CesiumHeatmap
+					var heatMap = this.heatMap = CesiumHeatmap.create(
+						viewer, // 视图层
+						bounds, // 矩形坐标
+						// heatmap相应参数
+						{
+							backgroundColor: "rgba(0, 0, 0, 0)",
+							radius: 50,
+							maxOpacity: .5,
+							minOpacity: 0,
+							blur: .75
+						}
+					);
+
+					//加载数据,生成热力图
+					// 添加数据 最小值,最大值,数据集
+					heatMap.setWGS84Data(0, 100, getData(300));
+					viewer.zoomTo(viewer.entities);
+
+					if (this._layer) {
+						//移除热力图
+						this.viewer.entities.remove(this.heatMap._layer);
+					} else {
+						this._layer = this.heatMap._layer;
+					}
+
+					// 数据格式:动态数据 [{x: -97.6433525165054, y: 45.61443064377248, value: 11.409122369106317}]
+					function getData(length) {
+						var data = [];
+						for (var i = 0; i < length; i++) {
+							var x = 121.563298 + Math.random() * (121.565298 - 121.563298);
+							var y = 37.284514 + Math.random() * (37.286514 - 37.284514);
+							var value = Math.random() * 100;
+							data.push({
+								x: x,
+								y: y,
+								value: value
+							});
+						}
+						return data;
+					}
+				}
+				if (type === "remove") {
+
+					//移除热力图
+					this.viewer.entities.remove(this.heatMap._layer);
+				}
+			}
+		},
+
+		mounted() {
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.el-avatar{
+		width: 70rem !important;
+		height: 70rem !important;
+		font-size: 14px !important;
+		cursor: pointer;
+	}
+	
+	::v-deep .el-collapse-item__content {
+		padding: 10rem;
+		// padding-bottom: 0rem;
+		overflow-y: hidden;
+	}
+
+	::v-deep .el-collapse-item__header {
+		background: url(@/assets/images/bg_collapse_title.png) no-repeat;
+		background-size: 350rem 40rem;
+		// background-color: rgb(22 90 190);
+		// background-color: rgb(5 45 100 /60%);
+		background-color: rgb(30 130 255);
+		border-bottom: 0;
+	}
+
+	.el-col {
+		padding: 10rem;
+		// color: rgba(90, 172, 255, 1.0);
+		color: #fff;
+	}
+
+	.jt-weather-effects {
+		position: relative;
+
+		.iconfont {
+			padding: 0 10rem;
+		}
+
+		.el-collapse {
+			--el-collapse-border-color: rgb(0 44 126 / 0%);
+
+			--el-collapse-header-text-color: #ffffff;
+			--el-collapse-header-font-size: 13rem;
+			--el-collapse-content-bg-color: rgb(0 44 126 / 0%);
+			--el-collapse-content-font-size: 13rem;
+			--el-collapse-content-text-color: rgb(216 240 255);
+
+			--el-collapse-header-height: 40rem;
+			--el-collapse-header-bg-color: rgb(30 130 255);
+
+			--el-fill-color-blank: rgb(0 44 126 / 68%);
+			--el-text-color-regular: rgb(216 240 255);
+			--el-border-color: rgb(35 135 255);
+
+			.el-collapse-item__content {
+				padding: 10rem;
+				// padding-bottom: 0rem;
+			}
+		}
+
+		i {
+			display: inline-block;
+			width: 100%;
+			height: 36rem;
+			line-height: 36rem;
+			text-align: center;
+			border-radius: 5rem;
+			font-size: 40rem;
+			// color: rgba(90, 172, 255, 1.0);
+			color: #fff;
+			transition: all .3s;
+			-webkit-transition: all .3s
+		}
+
+		.selectStyle {
+			// background: rgba(135, 182, 254, 0.5);
+			background: rgb(0 44 126);
+		}
+
+		.defaultStyle {
+			background: #ffffff00;
+		}
+
+		.selectFontStyle {
+			// color: #fff;
+			color: #55ffff;
+		}
+	}
+</style>

+ 240 - 0
src/views/Map3d-自测/components/toolbars.vue

@@ -0,0 +1,240 @@
+<script setup>
+	/**
+	 * element-plus组件
+	 */
+	import {
+		ElMessage
+	} from 'element-plus';
+
+	/**
+	 * element-plus字体
+	 */
+	import {
+		ArrowDown
+	} from '@element-plus/icons-vue';
+
+	import {
+		inject
+	} from "vue";
+
+	import {
+		Store
+	} from '@/store/index'
+	store = Store()
+	
+	const getMapInstance = inject("getMapInstance");
+	let jt3d = getMapInstance();
+	
+	import * as mapWork from "../map"
+
+	import {
+		useWidget
+	} from "@/common/store/widget"
+
+
+	const {
+		activate,
+		disable
+	} = useWidget()
+
+	const showWidget = (widget) => {
+		//全图
+		if (widget === "fullMap") {
+			mapWork.fullMap(jt3d);
+		}
+		//绕点自旋
+		else if (widget === "rotateCamera") {
+			ElMessage.warning('在地图上单击进行自旋,再次单击停止自旋')
+			mapWork.setMapSpin(jt3d);
+		}
+		//清除所有
+		else if (widget === "clearAll") {
+
+		} else {
+			// if (window.viewerLeft) {
+			// 	disable("map-compare")
+			// 	// mapWork.removeSplitScreen(window.viewerLeft);
+			// }
+			
+			activate(widget)
+		}
+	}
+</script>
+
+<template>
+	<div class="jt-toolbars fadein-right">
+		<template v-for="(item, i) in toolDatas" :key="i">
+			<div v-if="item.router && !item.children" class="toolbar-item" @click="showWidget(item.router)">
+				<i :class="item.icon" />
+				<span class="title">{{ item.name }}</span>
+			</div>
+			<el-dropdown v-if="item.children && !item.router" class="toolbar-item">
+				<span class="el-dropdown-link">
+					<i :class="item.icon" />
+					<span class="title">{{ item.name }}</span>
+					<el-icon class="el-icon--right">
+						<ArrowDown />
+					</el-icon>
+				</span>
+				<template #dropdown>
+					<span slot="slot" class="text"></span>
+					<el-dropdown-menu>
+						<el-dropdown-item v-for="child in item.children" :title="child.name" @click="showWidget(child.router)">
+							<i :class="child.icon" />
+							<span>{{ child.name }}</span>
+						</el-dropdown-item>
+					</el-dropdown-menu>
+				</template>
+			</el-dropdown>
+		</template>
+	</div>
+</template>
+
+<script>
+	let store = undefined;
+	export default {
+		name: "jt-toolbars",
+		data() {
+			return {
+				// toolDatas:store.menuList,
+				toolDatas: [{
+						name: "绕点自旋",
+						icon: "iconfont icon-chaxunzuobiaozhi",
+						router: "rotateCamera"
+					},
+					{
+						name: "全图",
+						icon: "iconfont icon-chaxunzuobiaozhi",
+						router: "fullMap"
+					},
+					{
+						name: "底图",
+						icon: "iconfont icon-dituzuobiao",
+						router: "manage-basemap"
+					},
+					{
+						name: "图层",
+						icon: "iconfont icon-winfo-icon-tucengkongzhi",
+						router: "manage-layer"
+					},
+					{
+						name: "工具",
+						icon: "iconfont icon-xitong1",
+						children: [{
+								name: "卷帘对比",
+								icon: "iconfont maxsize icon-juanlian",
+								router: "map-split"
+							},
+							{
+								name: "分屏对比",
+								icon: "iconfont minsize icon-fenping",
+								router: "map-compare"
+							},
+							{
+								name: "地区导航",
+								icon: "iconfont icon-zhijiantou",
+								router: "location-region"
+							},
+							{
+								name: "视角标签",
+								icon: "iconfont icon-fushi",
+								router: "viewerlabel"
+							},
+						]
+					},
+					{
+						name: "清除",
+						icon: "iconfont icon-shanchu",
+						router: "clearAll"
+					},
+				]
+			}
+		},
+		/* 方法 */
+		methods: {},
+
+		mounted() {
+
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.text::before {
+		position: absolute;
+		width: 0rem;
+		height: 0rem;
+		left: calc(50% - 5rem);
+		top: -5rem;
+		content: '';
+		transform: rotate(45deg);
+		z-index: 10;
+		box-sizing: border-box;
+		border-bottom: 5rem solid transparent;
+		border-right: 5rem solid transparent;
+		border-top: 5rem solid rgba(255, 255, 255, 1);
+		border-left: 5rem solid rgba(255, 255, 255, 1);
+		// background: rgba(5, 45, 115, .8) !important;
+	}
+
+	.jt-toolbars {
+		position: absolute;
+		top: 80rem;
+		width: auto;
+		right: 20rem;
+		cursor: pointer !important;
+		padding: 0rem 10rem !important;
+		margin: 0rem !important;
+		background-image: none !important;
+		border: 1rem solid;
+		border: none;
+		border-radius: 2rem !important;
+		background-color: rgb(0 44 126 / 65%);
+		height: 40rem;
+		box-sizing: border-box;
+		line-height: 38rem;
+		text-align: left;
+		user-select: none;
+
+		cursor: default;
+
+		.toolbar-item {
+			display: inline-block;
+			padding: 0rem 10rem;
+
+			margin: 0rem;
+			height: calc(100% - 4rem);
+			color: #fff;
+			font-size: 15rem;
+			vertical-align: middle;
+
+			&:hover {
+				background-color: rgba(255, 255, 255, 0.3);
+			}
+
+			.title {
+				font-size: 16rem;
+			}
+		}
+
+		.toolbar-item:nth-last-child(1) {
+			padding-right: 0rem;
+		}
+		
+		.iconfont{
+			margin-right: 5rem;
+		}
+
+		.el-icon {
+			margin-right: 5rem;
+			color: #fff;
+		}
+
+		.el-dropdown {
+			// vertical-align: middle;
+			height: 40rem;
+			line-height: 38rem;
+			box-sizing: border-box;
+		}
+	}
+</style>

+ 316 - 0
src/views/Map3d-自测/components/viewerlabel.vue

@@ -0,0 +1,316 @@
+<script setup>
+	import {
+		inject
+	} from "vue";
+	import html2canvas from 'html2canvas';
+	import {Store} from '@/store/index';
+	store = Store()
+	import {
+		blobToBase64,
+		base64ToBlob
+	} from '@/assets/js/blobtobase64';
+	const getMapInstance = inject("getMapInstance");
+	jt3d = getMapInstance();
+</script>
+
+<template>
+	<div class="mainview">
+		<div class="header">
+			<input @input="getName()" id="inputValue" type="text" placeholder="创建视角标签" />
+			<el-button v-if="store.userport=='PC'" type="primary" @click="addviewer" size="small">添加</el-button>
+			<el-button type="primary" @click="searchviewer" size="small">查询</el-button>
+		</div>
+		<div class="middleviewer">
+			<div class="viewer" v-for="(res,index) in ImgurlList" :key="index">
+				<div class="viewertop">
+					<img :src="res.url" @click="flyto(res.info)">
+				</div>
+				<div class="viewerbottom">
+					{{res.name}}
+					<img src="@/assets/images/delete.png" class="deleteImg" @click="deleteviewer(res,index)" />
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script>
+	let store = undefined;
+	let jt3d = undefined;
+	export default {
+		data() {
+			return {
+				viewersName: '', //视角标签名称
+				ImgurlList: [], //截图地址列表
+			}
+		},
+		methods: {
+			//获取输入框值
+			getName() {
+				this.viewersName = document.getElementById("inputValue").value;
+			},
+
+			//跳转方法
+			flyto(options) {
+				jt3d.LocateUtil.flyToPoint(options)
+			},
+
+			//删除方法,传keyvalue以及需要修改属性
+			deleteviewer(item, index) {
+				//删除对应数组内的对象
+				this.ImgurlList.splice(index, 1)
+				if (item.id) {
+					this.$http.get('/delete', {
+						tableName: 'map_angle',
+						keyValue: item.id,
+					}).then(res => {
+						console.log(res.data)
+					})
+				}
+			},
+
+			//添加视角标签,当前页存数组,向数据库传入相机参数
+			addviewer() {
+				//获取当前界面截图方法
+				html2canvas(
+					this.$parent.$parent.$refs.refMap3d.$refs.cesiumContainer, {
+						// backgroundColor: null, //画出来的图片有白色的边框,不要可设置背景为透明色(null)
+						useCORS: true, //支持图片跨域
+						scale: 1 / 8, //设置放大的倍数
+					}
+				).then(canvas => {
+					//截图用img元素承装,显示在页面的上
+					let url = canvas.toDataURL('image/png')
+					//经纬度、高度
+					// 获取 相机姿态信息
+					let heading = window["viewer"].scene.camera.heading
+					let pitch = window["viewer"].scene.camera.pitch
+					let roll = window["viewer"].scene.camera.roll
+					let position = window["viewer"].scene.camera.positionCartographic
+					let longitude = Cesium.Math.toDegrees(position.longitude) //y
+					let latitude = Cesium.Math.toDegrees(position.latitude) //x
+					let height = position.height
+					let info = {
+						latitude: latitude,
+						longitude: longitude,
+						height: height,
+						pitch: Cesium.Math.toDegrees(pitch),
+						roll: Cesium.Math.toDegrees(roll),
+						heading: Cesium.Math.toDegrees(heading)
+					}
+					//dom for循环渲染列表
+					this.ImgurlList.unshift({
+						url: url,
+						name: this.viewersName,
+						info: info
+					})
+
+					//base64转换为二进制文件
+					// let blob = base64ToBlob(url)
+					// //文件转为文件流
+					// let formData = new FormData();
+					// formData.append('file',blob)
+
+					let data = {
+						name: this.viewersName,
+						x: latitude,
+						y: longitude,
+						z: height,
+						pitch: Cesium.Math.toDegrees(pitch),
+						roll: Cesium.Math.toDegrees(roll),
+						heading: Cesium.Math.toDegrees(heading),
+						screenshot: url,
+						// screenshot: '',
+						userId: this.id,
+						// id:0
+					}
+
+					//添加数据接口
+					this.$http.post('/postSubmit', {
+						tableName: 'map_angle',
+						keyValue: '',
+						formData: data,
+					}).then(res => {
+						console.log(res)
+						if (res.success == true) {
+							console.log('添加成功')
+							document.getElementById("inputValue").value = ''
+						}
+					})
+				}).catch(err => {
+					console.log(err)
+				})
+			},
+			searchviewer() {
+				this.info = JSON.parse(localStorage.getItem('person'))
+				this.id = this.info.id
+				//获取所有图片数据
+				this.$http.get('/getTableList', {
+					tableName: 'map_angle', //
+					sqlWhere: "name like '%" + this.viewersName + "%'",
+					orderByField: ''
+				}).then(res => {
+					console.log('获取图片', res.data)
+					this.ImgurlList = [];
+					res.data.forEach(item => {
+						let info = {
+							latitude: item.x,
+							longitude: item.y,
+							height: item.z,
+							pitch: item.pitch,
+							roll: item.roll,
+							heading: item.heading
+						}
+						// let url = blobToBase64(item.screenshot)
+						//dom for循环渲染列表
+						this.ImgurlList.push({
+							url: item.screenshot,
+							name: item.name,
+							info: info,
+							id: item.id
+						})
+					})
+
+					// console.log('img列表',this.ImgurlList)
+				})
+			}
+		},
+
+		mounted() {
+			this.info = JSON.parse(localStorage.getItem('person'))
+			this.id = this.info.id
+			//获取所有图片数据
+			this.$http.get('/getTableList', {
+				tableName: 'map_angle', //
+				sqlWhere: '', //+ this.loginForm.id
+				orderByField: ''
+			}).then(res => {
+				console.log('获取图片', res.data)
+				if(res.data.length == 0) return
+				res.data.forEach(item => {
+					let info = {
+						latitude: item.x,
+						longitude: item.y,
+						height: item.z,
+						pitch: item.pitch,
+						roll: item.roll,
+						heading: item.heading
+					}
+					// let url = blobToBase64(item.screenshot)
+					//dom for循环渲染列表
+					this.ImgurlList.push({
+						url: item.screenshot,
+						name: item.name,
+						info: info,
+						id: item.id
+					})
+				})
+
+				// console.log('img列表',this.ImgurlList)
+			})
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.el-button--small{
+		--el-button-size:24rem;
+		font-size:12rem;
+		padding: 5rem 12rem;
+	}
+	
+	.mainview {
+		width: 100%;
+		height: 100%;
+
+		.header {
+			width: 100%;
+			display: flex;
+
+			input,
+			input:focus {
+				outline: none;
+				width: 185rem !important;
+				border: 1rem solid rgba(255, 255, 255, 0.8);
+				margin-right: 10rem;
+				height: 26rem !important;
+				color: rgba(255, 255, 255, 1);
+				background-color: rgba(255, 255, 255, 0) !important;
+				border-radius: 3rem;
+			}
+		}
+
+		.middleviewer {
+			width: 322rem;
+			height: 100%;
+			margin-left: 7rem;
+
+			.viewer {
+				width: 322rem !important;
+				height: 240rem !important;
+				margin-top: 15rem;
+				border: 1rem solid #ffffff !important;
+				border-radius: 1rem !important;
+
+				.viewertop {
+					width: 322rem !important;
+					height: 210rem !important;
+
+					img {
+						width: 100% !important;
+						height: 100% !important;
+					}
+				}
+
+				.viewerbottom {
+					line-height: 30rem !important;
+					text-align: center !important;
+					width: 322rem !important;
+					height: 30rem !important;
+					position: relative;
+					background-color: rgba(15, 145, 185, 0.7);
+
+					.deleteImg {
+						width: 24rem;
+						height: 24rem;
+						right: 5rem;
+						top: 3rem;
+						position: absolute;
+					}
+				}
+			}
+		}
+	}
+
+	::v-deep .el-input {
+		flex-grow: 0 !important;
+		width: 200rem !important;
+		// display: inline !important;
+		// margin-left: 5rem;
+		margin-right: 10rem;
+		height: 30rem !important;
+	}
+
+	//输入框文字颜色
+	::v-deep .el-input__inner {
+		color: rgba(255, 255, 255, 1)
+	}
+
+	//输入框背景色
+	::v-deep .el-input__wrapper {
+		background-color: rgba(255, 255, 255, 0) !important;
+	}
+
+	::v-deep .el-button {
+		border-radius: 3rem !important;
+
+	}
+
+	::v-deep .el-button--primary {
+		background-color: rgba(64, 158, 255, 0.6) !important;
+	}
+
+	::-webkit-scrollbar {
+		width: 0rem;
+	}
+</style>

+ 79 - 0
src/views/Map3d-自测/index.js

@@ -0,0 +1,79 @@
+// import {
+// 	defineAsyncComponent
+// } from 'vue';
+// export default {
+// 	install(app) {
+// 		// const req = require.context('./', false, /\.vue$/) //获取当前文件夹下的所有.vue文件,并返回一个对象
+// 		const req =
+// 			import.meta.glob('./*.vue'); // //获取当前文件夹下的所有.vue文件,并返回一个对象
+// 			debugger
+// 		Object.keys(req).forEach(item => { // Object.keys遍历,返回一个包含所有属性名的数组,对数组遍历,根据属性名,通过obj[属性名]的方式拿取到属性值,相较于for in的优势在于只遍历了属性名,而非属性名和属性值全部遍历,性能有优化
+// 			debugger
+// 			const com = req(item).default //在default包裹层下拿到属性名
+// 			app.component(com.name, com)
+// 		})
+// 	}
+// }
+
+
+/*
+ **全局注册组件
+ */
+import {
+	defineAsyncComponent
+} from 'vue';
+const components =import.meta.glob('./components/*.vue'); // 异步方式,获取当前文件夹下的所有.vue文件,并返回一个对象
+export default function install(app) {
+	for (const [key, value] of Object.entries(components)) {
+	  const name = key.slice(key.lastIndexOf('/') + 1, key.lastIndexOf('.'));
+	  app.component(name, defineAsyncComponent(value));
+	}
+}
+
+
+/*
+ **全局注册组件
+ */
+// import { defineAsyncComponent } from 'vue';
+// //获取components目录下所有的文件信息
+// const modulesFiles = import.meta.globEager('./*.vue')// 异步方式,获取当前文件夹下的所有.vue文件,并返回一个对象
+// const pathList = []
+// //遍历拿到所有的文件名称
+// for (const path in modulesFiles) {
+//     pathList.push(path)
+// }
+// //全局批量注册components下所有组件
+// export default {
+//     install(app) {
+//         pathList.forEach((path) => {
+// 			debugger
+//             const component = modulesFiles[path].default;
+// 			const name = path.slice(path.lastIndexOf('/') + 1, path.lastIndexOf('.'));
+//             app.component(component.name, component)
+// 			 // app.component(name, defineAsyncComponent(component))
+//         })
+//     }
+// }
+
+
+// const app = createApp(App);
+// function registerGlobalAsyncComponents(app: VueApp) {
+//   const modules = import.meta.glob('./**/*.vue');
+//   for (const path in modules) {
+//     const result = path.match(/.*\/(.+).vue$/);
+//     if (result) {
+//       const name = result[1];
+//       const component = modules[path];
+//       app.component(name, defineAsyncComponent(component));
+//     }
+//   }
+// }
+
+
+// const modules = import.meta.glob('./components-new/*.vue');
+// const components: any = ref({});
+// Object.entries(modules).forEach(([path, asyncCom]) => {
+//   const name = path.replace(/\.\/components-new\/(.*)\.vue/, '$1');
+//   components.value[name] = markRaw(defineAsyncComponent(asyncCom));
+// });
+

+ 1136 - 0
src/views/Map3d-自测/map.js

@@ -0,0 +1,1136 @@
+import {
+	Store
+} from '@/store/index'
+let store = Store();
+
+import http from '@/utils/http.js'
+
+// import * as jt3dSDK from '/public/jt3dSDK/jt3d.es.js';
+
+import map_xzqh_zj from '@/assets/dataFile/xz.json';
+
+let jtMap3d = undefined; // 地图对象
+
+/**
+ * 初始化地图业务,生命周期钩子函数(必须)
+ * 框架在地图初始化完成后自动调用该函数
+ * @param  mapInstance 地图对象
+ */
+export function onMounted(mapInstance) {
+	jtMap3d = mapInstance // 记录首次创建的map
+
+	debugger
+}
+
+//所有图层
+export function getAllLayers() {
+
+	return new Promise((resolve, reject) => {
+
+		//获取地图图集id
+		let roleId = store.roleId
+		let atlasLayersSqlWhere = '"roleId"' + " = " + roleId + " "
+
+		//获取图集
+		http.get('/getTableList', {
+			tableName: 'sys_map_atlas_layers', //表名
+			sqlWhere: atlasLayersSqlWhere, //查询条件
+			orderByField: '' //排序字段
+		}).then(res => {
+			resolve(res.data)
+		});
+	});
+}
+export function getLayers() {
+
+	return new Promise((resolve, reject) => {
+
+		//获取地图图集id
+		let roleId = store.roleId
+		let atlasLayersSqlWhere = '"roleId"' + " = " + roleId + " and " + '"atlasType"' + "='图层'"
+
+		//获取图集
+		http.get('/getTableList', {
+			tableName: 'sys_map_atlas_layers', //表名
+			sqlWhere: atlasLayersSqlWhere, //查询条件
+			orderByField: '' //排序字段
+		}).then(res => {
+			resolve(res.data)
+		});
+	});
+}
+
+export function getBaseMaps() {
+
+	return new Promise((resolve, reject) => {
+
+		//获取地图图集id
+		let roleId = store.roleId
+		let atlasLayersSqlWhere = '"roleId"' + " = " + roleId + " and " + '"atlasType"' + "='底图'"
+
+		//获取图集
+		http.get('/getTableList', {
+			tableName: 'sys_map_atlas_layers', //表名
+			sqlWhere: atlasLayersSqlWhere, //查询条件
+			orderByField: '' //排序字段
+		}).then(res => {
+			resolve(res.data)
+		});
+	});
+}
+
+/**
+ * 单击事件
+ */
+export function clickEntity(jt3d) {
+
+	if (jt3d.handlerLeftClick) {
+		jt3d.handlerLeftClick.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); //移除事件
+	}
+
+	jt3d.handlerLeftClick = new Cesium.ScreenSpaceEventHandler(
+		jt3d._viewer.scene.canvas
+	);
+	//注册大球单机事件
+	jt3d.handlerLeftClick.setInputAction(function(e) {
+		var pick = jt3d._viewer.scene.pick(e.position); //拾取当前的entity对象
+		var cartesian = jt3d._viewer.scene.pickPosition(e.position); //获取当前点坐标
+		if (Cesium.defined(cartesian)) {
+			//将笛卡尔坐标转换为地理坐标
+			let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
+			//将弧度转为度的十进制度表示
+			let lng = Cesium.Math.toDegrees(cartographic.longitude);
+			let lat = Cesium.Math.toDegrees(cartographic.latitude);
+			let alt = cartographic.height; //高度
+
+			initQuery({
+				spatialType: '点',
+				coordinate: lng + " " + lat,
+				buffer: ''
+			});
+		}
+	}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+}
+
+
+/**
+ * 设置默认视图-初始化中国区域范围视角
+ */
+export function setView(jt3d) {
+	// jt3d.flytoChina();
+
+	//初始化中国区域范围视角
+	jt3d.setViewChina();
+
+	// jt3d.setView({
+	// 	longitude: 103.84, //经度
+	// 	latitude: 31.15, // 维度
+	// 	height: 24000000, // 高度
+	// 	heading: 0, // 偏航
+	// 	pitch: -90, // 俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球
+	// 	roll: 0.0 // 翻滚
+	// });
+}
+
+/**
+ * 全图-飞行到项目区域范围视角
+ */
+export function fullMap(jt3d) {
+	// 初始化项目区域范围视角
+	let optionsS = {
+		west: 116.883783, //西
+		south: 36.573500, //南
+		east: 117.326923, //东
+		north: 36.329733, //北
+		isRemove: false, //定位完成后是否删除
+		duration: 3, //飞行时间
+		heading: 0,
+		pitch: -90,
+		range: 60000
+	};
+	
+	let optionsE = {
+		west: 116.883783, //西
+		south: 36.573500, //南
+		east: 117.326923, //东
+		north: 36.329733, //北
+		isRemove: true, //定位完成后是否删除
+		duration: 3, //飞行时间
+		heading: 0,
+		pitch: -60,
+		range: 60000
+	};
+
+	var fullMapPromise = jt3d.fullMap(optionsS);
+	fullMapPromise.then(function(flyPromise) {
+		jt3d.fullMap(optionsE);
+	});
+}
+
+/**
+ * 设置天空盒子
+ */
+export function addSkybox(jt3d) {
+	//设置天空盒子,默认蓝天
+	let SceneEffects = new jt3dSDK.SceneEffects.SkyBox(window.viewer);
+	SceneEffects.setGroundSkyBox();
+}
+
+/**
+ * 添加镇街边界线——精灵线
+ */
+export function addBoundaryLine(jt3d) {
+	let PolylineObject = new jt3dSDK.PolylineObject(jt3d._viewer);
+	PolylineObject.drawPolylineByGeoJson(map_xzqh_zj, {
+		width: 5,
+		color: '#04FFFF',
+		isImageAlpha: true, //用图片自带颜色
+		duration: 3000,
+		imgUrl: "jt3dSDK/imgs/polylinematerial/spriteline1.png"
+	});
+}
+
+/**
+ * 控制地图服务的显示及隐藏
+ * @param {Object} viewer
+ * @param {Object} options 
+ */
+export function setLayersControl(viewer, options, checked) {
+
+	let layer = new jt3dSDK.layer(viewer);
+	var imageryLayers = viewer.imageryLayers;
+
+	//参数集
+	let parameterset = options.parameterset;
+	if (options.parameterset instanceof Object) {
+		parameterset = options.parameterset;
+	} else if (options.parameterset != "" && options.parameterset != null && options.parameterset != undefined) {
+		parameterset = JSON.parse(options.parameterset);
+	}
+
+	return new Promise((resolve, reject) => {
+		switch (options.loadtype) {
+			case "DEM": //地形服务(DEM)
+				if (checked) {
+
+					//设置参数
+					let _options = {
+						url: options.datasource,
+					}
+					if (parameterset) {
+						if (parameterset.terrainExaggeration) { //地形夸张系数
+							_options.terrainExaggeration = parameterset.terrainExaggeration;
+						}
+					}
+					layer.addTerrain(_options);
+
+					resolve(true);
+				} else {
+					layer.removeTerrain().then(res => {
+						resolve(true);
+					});
+				}
+				break;
+
+			case "Cesium3DTileset": //加载3DTileset地图服务--实景
+
+				if (checked) {
+
+					if (window[options.serviceId]) {
+						window[options.serviceId].show = true;
+					} else {
+						//设置参数
+						let _options = {
+							id: options.serviceId,
+							url: options.datasource,
+						}
+						if (parameterset) {
+							if (parameterset.height) {
+								_options.height = parameterset.height;
+							}
+							if (parameterset.alpha) {
+								_options.alpha = parameterset.alpha;
+							}
+						}
+						//加载实景
+						layer.addCesium3DTileset(_options, function(serviceId) {
+							window[serviceId].show = true;
+							resolve(true);
+						});
+					}
+				} else {
+					if (window[options.serviceId]) {
+						//3DTileset数据量比较大,会报很多cesium错误
+						// layer.removeScenePrimitives({
+						// 	serviceId: options.serviceId
+						// }).then(res => {
+						// resolve(true);
+						// });
+
+						window[options.serviceId].show = false;
+
+						resolve(true);
+					}
+				}
+
+				break;
+			case "Cesium3DTileset_BM": //加载3DTileset地图服务--白膜
+				if (checked) {
+
+					if (window[options.serviceId]) {
+						window[options.serviceId].show = true;
+					} else {
+						//设置参数
+						let _options = {
+							id: options.serviceId,
+							url: options.datasource,
+						}
+						if (parameterset) {
+							if (parameterset.color) {
+								_options.color = parameterset.color;
+							}
+						}
+
+						//加载白膜
+						layer.addCesium3DTilesetBm(_options, function(serviceId) {
+							window[serviceId].show = true;
+							resolve(true);
+						});
+					}
+				} else {
+					if (window[options.serviceId]) {
+						// layer.removeScenePrimitives({
+						// 	serviceId: options.serviceId
+						// }).then(res => {
+						// resolve(true);
+						// });
+
+						window[options.serviceId].show = false;
+						resolve(true);
+					}
+				}
+				break;
+
+
+			case "GeoJsonPoint": //GeoJsonPoint
+				if (checked) {
+
+					//设置参数
+					let _options = {
+						id: options.serviceId,
+						url: options.datasource,
+					}
+
+					if (parameterset) {
+						if (parameterset.billboard instanceof Object) {
+							let billboard = parameterset.billboard;
+							_options.billboard = billboard;
+						}
+
+						if (parameterset.label instanceof Object) {
+							let label = parameterset.label;
+							_options.label = label;
+						}
+					}
+
+					layer.addBillboardByJson(_options, function(serviceId) {
+						resolve(true);
+					});
+
+				} else {
+					layer.removeDataSources({
+						serviceId: options.serviceId,
+					}).then(res => {
+						resolve(true);
+					});
+				}
+				break;
+			case "GeoJsonPolyline": //GeoJsonPolyline
+				if (checked) {
+
+					//设置参数
+					let _options = {
+						id: options.serviceId,
+						url: options.datasource,
+					}
+
+					if (parameterset) {
+
+						if (parameterset.clampToGround) { //是否贴地
+							_options.clampToGround = parameterset.clampToGround;
+						}
+						if (parameterset.isImageAlpha) { //是否采用图片颜色
+							_options.isImageAlpha = parameterset.isImageAlpha;
+						}
+						if (parameterset.imgUrl) { //精灵线图片
+							_options.imgUrl = parameterset.imgUrl;
+						}
+						if (parameterset.color) { //指定线的颜色
+							_options.color = parameterset.color;
+						}
+						if (parameterset.width) { //线宽
+							_options.width = parameterset.width;
+						}
+						if (parameterset.duration) { //持续时间 毫秒,越小越快
+							_options.duration = parameterset.duration;
+						}
+						if (parameterset.count) { //重复次数
+							_options.count = parameterset.count;
+						}
+						if (parameterset
+							.direction) { //direction=vertical 纵,order='-'(由下到上) , '+"(由上到下)
+							_options.direction = parameterset.direction;
+						}
+						if (parameterset
+							.order) { //direction=horizontal 横,order='-'(顺时针) , '+'(逆时针)
+							_options.order = parameterset.order;
+						}
+					}
+
+					layer.addPolylineByGeoJson(_options, function(serviceId) {
+						resolve(true);
+					});
+				} else {
+					layer.removeDataSources({
+						serviceId: options.serviceId,
+					}).then(res => {
+						resolve(true);
+					});
+				}
+				break;
+			case "GeoJsonWall": //GeoJson Wall
+				if (checked) {
+
+					//设置参数
+					let _options = {
+						id: options.serviceId,
+						url: options.datasource,
+					}
+
+					if (parameterset) {
+
+						if (parameterset.clampToGround) { //是否贴地
+							_options.clampToGround = parameterset.clampToGround;
+						}
+						if (parameterset.minimunHeights) { //最低高度
+							_options.minimunHeights = parameterset.minimunHeights;
+						}
+						if (parameterset.maximumHeights) { //最高高度
+							_options.maximumHeights = parameterset.maximumHeights;
+						}
+						if (parameterset.color) { //指定墙体的颜色
+							_options.color = parameterset.color;
+						}
+						if (parameterset.trailImage) { //墙体图片
+							_options.trailImage = parameterset.trailImage;
+						}
+						if (parameterset.duration) { //持续时间 毫秒,越小越快
+							_options.duration = parameterset.duration;
+						}
+						if (parameterset.count) { //重复次数
+							_options.count = parameterset.count;
+						}
+						if (parameterset.direction) { //direction=vertical 纵,order='-'(由下到上) , '+"(由上到下)
+							_options.direction = parameterset.direction;
+						}
+						if (parameterset.order) { //direction=horizontal 横,order='-'(顺时针) , '+'(逆时针)
+							_options.order = parameterset.order;
+						}
+					}
+
+					// .json文件需要放到public文件夹下,直接调用,
+					layer.addWallByJson(_options, function(serviceId) {
+						resolve(true);
+					});
+				} else {
+					layer.removeDataSources({
+						serviceId: options.serviceId,
+					}).then(res => {
+						resolve(true);
+					});
+				}
+				break;
+			case "entitiesGltf": //gltf/glb
+				if (checked) {
+
+					//设置参数
+					let _options = {
+						id: options.serviceId,
+						url: options.datasource,
+						points: [],
+					}
+
+					if (parameterset) {
+						if (parameterset.points) { //模型位置
+							_options.points = parameterset.points;
+
+							if (parameterset.minimumPixelSize) { //模型最小刻度
+								_options.minimumPixelSize = parameterset.minimumPixelSize;
+							}
+							if (parameterset.maximumScale) { //模型的最大比例尺大小,设置模型最大放大大小
+								_options.maximumScale = parameterset.maximumScale;
+							}
+							if (parameterset.silhouetteColor) { //模型轮廓颜色
+								_options.silhouetteColor = parameterset.silhouetteColor;
+							}
+							if (parameterset.alpha) { //模型透明度
+								_options.alpha = parameterset.alpha;
+							}
+							if (parameterset.heading) { //以弧度为单位的航向分量
+								_options.heading = parameterset.heading;
+							}
+							if (parameterset.pitch) { //以弧度为单位的航向分量
+								_options.pitch = parameterset.pitch;
+							}
+							if (parameterset.roll) { //以弧度为单位的滚动分量
+								_options.roll = parameterset.roll;
+							}
+
+							layer.addEntitiesGltf(_options, function(serviceId) {
+
+								resolve(true);
+							});
+
+						} else {
+							resolve("请检测图层表parameterset字段是否设置points");
+						}
+					} else {
+						resolve("请检测图层表parameterset字段是否设置points");
+					}
+				} else {
+					layer.removeEntity({
+						serviceId: options.serviceId,
+					}).then(res => {
+						resolve(true);
+					});
+				}
+				break;
+			case "scenePrimitivesGltf": //加载gltf/glb
+				if (checked) {
+
+					//设置参数
+					let _options = {
+						id: options.serviceId,
+						url: options.datasource,
+						points: [],
+					}
+
+					if (parameterset) {
+						if (parameterset.points) { //模型位置
+							_options.points = parameterset.points;
+
+							if (parameterset.scale) { //放大倍数
+								_options.scale = parameterset.scale;
+							}
+
+							layer.addScenePrimitivesGltf(_options, function(serviceId) {
+								resolve(true);
+							});
+
+						} else {
+							resolve("请检测图层表parameterset字段是否设置points");
+						}
+					} else {
+						resolve("请检测图层表parameterset字段是否设置points");
+					}
+				} else {
+					layer.removeScenePrimitives({
+						serviceId: options.serviceId,
+					}).then(res => {
+						resolve(true);
+					});
+				}
+				break;
+			case "PolygonImageMaterial": //图片材质
+				if (checked) {
+
+					if (parameterset) {
+						if (parameterset.points) {
+							layer.addPolygonImageMaterial({
+								id: options.serviceId,
+								points: parameterset.points,
+								url: options.datasource,
+								alpha: options.opacity
+							}, function(serviceId) {
+								resolve(true);
+							});
+						} else {
+							resolve("请检测图层表parameterset字段是否设置points");
+						}
+					} else {
+						resolve("请检测图层表parameterset字段是否设置points");
+					}
+				} else {
+					layer.removeEntity({
+						serviceId: options.serviceId,
+					}).then(res => {
+						resolve(true);
+					});
+				}
+				break;
+			case "CrImageServerLayer": //贴地所有地形、模型的规划图、网格地图
+
+				if (checked) {
+
+					let floatLayer = new jt3dSDK.CrImageServerLayer({
+						viewer: viewer,
+						url: options.datasource,
+						opacity: options.opacity,
+						show: true
+					});
+					window[options.serviceId] = floatLayer;
+					//添加网格地图
+					// window[options.serviceId].show();
+					resolve(true);
+				} else {
+					window[options.serviceId].hide();
+					resolve(true);
+				}
+				break;
+
+
+			case "UrlTemplateImageryProvider": //加载URL模板服务
+				if (checked) {
+
+					//设置参数
+					let _options = {
+						id: options.serviceId,
+						url: options.datasource,
+						alpha: options.opacity
+					}
+					if (parameterset) {
+						if (parameterset.CRS) { //坐标系
+							_options.CRS = parameterset.CRS;
+						}
+						if (parameterset.minimumLevel) { //最小层级
+							_options.minimumLevel = parameterset.minimumLevel;
+						}
+						if (parameterset.maximumLevel) { //最大层级
+							_options.maximumLevel = parameterset.maximumLevel;
+						}
+					}
+
+					//加载服务
+					layer.addUrlTemplateImagery(_options, function(serviceId) {
+
+						//重置图层顺序
+						setLayerNumber(imageryLayers, {
+							serviceId: serviceId,
+							layertype: options.layertype
+						})
+						resolve(true);
+					});
+				} else {
+					layer.removeImageryProvider({
+						serviceId: options.serviceId
+					}).then(res => {
+						resolve(true);
+					});
+				}
+
+				break;
+			case "WebMapTileServiceImageryProvider": // WMTS地图服务
+				if (checked) {
+
+					//设置参数
+					let _options = {
+						id: options.serviceId,
+						url: options.datasource,
+						layers: 'cia',
+						style: 'default',
+						tileMatrixSetID: 'w',
+						alpha: options.opacity
+					}
+					if (parameterset) {
+						if (parameterset.layers) { //WMTS请求的层名
+							_options.layers = parameterset.layers;
+
+							if (parameterset.style) { //WMTS请求的样式名
+								_options.style = parameterset.style;
+
+								if (parameterset.tileMatrixSetID) { //用于WMTS请求的TileMatrixSet的标识符
+									_options.tileMatrixSetID = parameterset.tileMatrixSetID;
+
+									if (parameterset.minimumLevel) { //最小层级
+										_options.minimumLevel = parameterset.minimumLevel;
+									}
+									if (parameterset.maximumLevel) { //最大层级
+										_options.maximumLevel = parameterset.maximumLevel;
+									}
+
+									layer.addWebMapTileService(_options, function(serviceId) {
+
+										//重置图层顺序
+										setLayerNumber(imageryLayers, {
+											serviceId: serviceId,
+											layertype: options.layertype
+										})
+
+										resolve(true);
+									});
+
+								} else {
+									resolve("请检测图层表parameterset字段是否设置tileMatrixSetID");
+								}
+
+							} else {
+								resolve("请检测图层表parameterset字段是否设置style");
+							}
+
+						} else {
+							resolve("请检测图层表parameterset字段是否设置layers");
+						}
+					} else {
+						resolve("请检测图层表parameterset字段是否设置layers,style,tileMatrixSetID");
+					}
+
+				} else {
+					layer.removeImageryProvider({
+						serviceId: options.serviceId
+					}).then(res => {
+						resolve(true);
+					});
+				}
+				break;
+			case "WebMapServiceImageryProvider": //WMS地图服务
+				if (checked) {
+
+					//设置参数
+					let _options = {
+						id: options.serviceId,
+						url: options.datasource,
+						alpha: options.opacity
+					}
+					if (parameterset) {
+						if (parameterset.layers) { //WMTS请求的层名
+							_options.layers = parameterset.layers;
+
+							if (parameterset.minimumLevel) { //最小层级
+								_options.minimumLevel = parameterset.minimumLevel;
+							}
+							if (parameterset.maximumLevel) { //最大层级
+								_options.maximumLevel = parameterset.maximumLevel;
+							}
+
+							layer.addWebMapService(_options, function(serviceId) {
+
+								//重置图层顺序
+								setLayerNumber(imageryLayers, {
+									serviceId: serviceId,
+									layertype: options.layertype
+								})
+
+								resolve(true);
+							});
+						} else {
+							resolve("请检测图层表parameterset字段是否设置layers");
+						}
+					} else {
+						resolve("请检测图层表parameterset字段是否设置layers");
+					}
+				} else {
+					layer.removeImageryProvider({
+						serviceId: options.serviceId
+					}).then(res => {
+						resolve(true);
+					});
+				}
+				break;
+			case "ArcGisMapServerImageryProvider": // ArcGIS Online和Server的相关服务
+				if (checked) {
+
+					//设置参数
+					let _options = {
+						id: options.serviceId,
+						url: options.datasource,
+						alpha: options.opacity
+					}
+					if (parameterset) {
+						if (parameterset.layers) {
+							_options.layers = parameterset.layers;
+						}
+					}
+
+					//加载服务
+					layer.addArcGisMapServer(_options, function(serviceId) {
+
+						//重置图层顺序
+						setLayerNumber(imageryLayers, {
+							serviceId: serviceId,
+							layertype: options.layertype
+						})
+
+						resolve(true);
+					})
+				} else {
+					layer.removeImageryProvider({
+						serviceId: options.serviceId
+					}).then(res => {
+						resolve(true);
+					});
+				}
+				break;
+			case "TileMapServiceImageryProvider": // 2.5维度地图
+				if (checked) {
+
+					//设置参数
+					let _options = {
+						id: options.serviceId,
+						url: options.datasource,
+						alpha: options.opacity
+					}
+					if (parameterset) {
+						if (parameterset.minimumLevel) { //最小层级
+							_options.minimumLevel = parameterset.minimumLevel;
+						}
+						if (parameterset.maximumLevel) { //最大层级
+							_options.maximumLevel = parameterset.maximumLevel;
+						}
+					}
+
+					layer.addTileMapServiceImagery(_options, function(serviceId) {
+
+						//重置图层顺序
+						setLayerNumber(imageryLayers, {
+							serviceId: serviceId,
+							layertype: options.layertype
+						})
+
+						resolve(true);
+					});
+				} else {
+					layer.removeImageryProvider({
+						serviceId: options.serviceId
+					}).then(res => {
+						resolve(true);
+					});
+				}
+				break;
+
+			default:
+				break;
+		}
+	})
+}
+
+/**
+ * 服务定位
+ * @param {Object} viewer
+ * @param {Object} options
+ */
+export function setLayersLocation(viewer, options) {
+
+	//参数集
+	let parameterset = options.parameterset;
+	if (options.parameterset instanceof Object) {
+		parameterset = options.parameterset;
+	} else if (options.parameterset != "" && options.parameterset != null && options.parameterset != undefined) {
+		parameterset = JSON.parse(options.parameterset);
+	}
+
+	if (options.isinit === '1') {
+		return new Promise((resolve, reject) => {
+			switch (options.loadtype) {
+				case "GeoJsonPolyline": //GeoJsonPolyline
+					resolve(true);
+					break;
+				case "GeoJsonWall": //GeoJsonWall
+					resolve(true);
+					break;
+				case "entitiesGltf": //gltf/glb
+
+					if (parameterset) {
+						if (parameterset.points) { //模型位置
+
+							// let LocateUtil = new jt3dSDK.LocateUtil(viewer);
+							// let flyToEntity = LocateUtil.flyToEntityByPoints([
+							// 	parameterset.points,
+							// ], 'point', {
+							// 	heading: '0',
+							// 	pitch: -90,
+							// 	range: 8880
+							// });
+							viewer.scene.camera.flyTo({
+								//定位坐标点
+								destination: Cesium.Cartesian3.fromDegrees(parameterset.points[0], parameterset.points[1], parameterset.points[2] || 0),
+								duration: 2, //定位的时间间隔
+								orientation: {
+									heading: Cesium.Math.toRadians(56), //方向
+									pitch: Cesium.Math.toRadians(-11), //倾斜角度
+									roll: 0
+								}
+							});
+
+							resolve(true);
+						} else {
+							resolve("请检测图层表parameterset字段是否设置points");
+						}
+					} else {
+						resolve("请检测图层表parameterset字段是否设置points");
+					}
+
+					break;
+				case "scenePrimitivesGltf": //gltf/glb
+
+					if (parameterset) {
+						if (parameterset.points) { //模型位置
+
+							viewer.scene.camera.flyTo({
+								//定位坐标点
+								destination: Cesium.Cartesian3.fromDegrees(parameterset.points[0], parameterset.points[1], parameterset.points[2] || 0),
+								duration: 2, //定位的时间间隔
+								orientation: {
+									// heading: Cesium.Math.toRadians(56), //方向
+									// pitch: Cesium.Math.toRadians(-11), //倾斜角度
+									// roll: 0
+								}
+							});
+
+							resolve(true);
+						} else {
+							resolve("请检测图层表parameterset字段是否设置points");
+						}
+					} else {
+						resolve("请检测图层表parameterset字段是否设置points");
+					}
+
+					break;
+				case "PolygonImageMaterial": //图片材质
+					resolve(true);
+					break;
+				case "CrImageServerLayer": //地形服务(DEM)
+					resolve(true);
+					break;
+				case "DEM": //地形服务(DEM)
+					resolve(true);
+					break;
+				case "UrlTemplateImageryProvider": //加载URL模板服务
+					resolve(true);
+					break;
+				case "WebMapTileServiceImageryProvider": // WMTS地图服务
+					resolve(true);
+					break;
+				case "WebMapServiceImageryProvider": //WMS地图服务
+					resolve(true);
+					break;
+				case "ArcGisMapServerImageryProvider": // ArcGIS Online和Server的相关服务
+					resolve(true);
+					break;
+				case "TileMapServiceImageryProvider": // 2.5维度地图
+					resolve(true);
+					break;
+				case "Cesium3DTileset": //加载3DTileset地图服务--实景
+
+					if (window[options.serviceId]) {
+						viewer.flyTo(window[options.serviceId]);
+						resolve(true);
+					}
+					break;
+				case "Cesium3DTileset_BM": //加载3DTileset地图服务--白膜
+					resolve(true);
+					break;
+				default:
+					resolve(true);
+					break;
+			}
+		})
+	}
+}
+
+/**
+ * 设置服务透明度
+ * @param {Object} viewer
+ * @param {Object} options
+ */
+export function setLayersAlpha(viewer, options) {
+	let layer = new jt3dSDK.layer(viewer);
+
+	if (options.loadtype === "Cesium3DTileset") {
+		//设置实景透明度
+		layer.set3DTileStyle({
+			serviceId: options.serviceId,
+			alpha: options.alpha,
+		});
+	} else if (options.loadtype === "CrImageServerLayer") {
+		let floatLayer = window[options.serviceId];
+		floatLayer.setOpacity(options.alpha)
+	} else if (options.loadtype === "PolygonImageMaterial") {
+		//设置透明度
+		layer.setPolygonImageMaterial({
+			serviceId: options.serviceId,
+			alpha: options.alpha,
+		});
+	} else if (options.loadtype === "entitiesGltf") {
+		//设置透明度
+		layer.setModelStyle({
+			serviceId: options.serviceId,
+			alpha: options.alpha,
+		});
+	} else {
+		layer.setLayersStyle({
+			serviceId: options.serviceId,
+			alpha: options.alpha,
+		});
+	}
+}
+
+/**
+ * 设置图层顺序
+ * @param {Object} imageryLayers
+ * @param {Object} options
+ */
+export function setLayerNumber(imageryLayers, options) {
+
+	// var imageryLayers = viewer.imageryLayers;
+
+	//设置图层初始顺序
+	imageryLayers.lowerToBottom(window[options.serviceId]);
+	imageryLayers.raise(window[options.serviceId]);
+	imageryLayers.raise(window[options.serviceId]);
+	
+	let serviceMark=options.serviceId.split('_')[0]
+
+	getAllLayers().then(layers => {
+		layers.map((item) => {
+			if (item.layercode && item.layerorder) {
+				let id = serviceMark + "_" + item.layercode + item.layerorder
+				let startid = Number(item.layercode + item.layerorder)
+				let strid = Number(options.serviceId.replace(serviceMark + "_", ""))
+
+				if (imageryLayers.contains(window[id])) {
+					if (startid <= strid) {
+						imageryLayers.raise(window[options.serviceId])
+					}
+				}
+			}
+		})
+
+		//底图置底
+		if (options.layertype === "底图影像") {
+			imageryLayers.lowerToBottom(window[options.serviceId]);
+			imageryLayers.raise(window[options.serviceId]);
+		}
+
+		//标注置顶
+		if (options.layertype === '标注') {
+			imageryLayers.raiseToTop(window[options.serviceId]);
+		}
+	});
+}
+
+/**
+ * 移除分屏对比
+ */
+export function removeSplitScreen(viewer) {
+	let mapView1 = document.getElementById("cesiumContainer");
+	let mapView2 = document.getElementById("cesiumContainer2");
+
+	mapView1.className = "jt-map";
+	mapView2.style.display = "none";
+	mapView2.innerHTML = "";
+
+	if (viewer) {
+		viewer.entities.removeAll(); // 删除全部
+		viewer.imageryLayers.removeAll();
+		viewer.scene.primitives.removeAll(); //谨慎使用,可能删除不必要的primitive
+		viewer.destroy();
+	}
+}
+
+/**
+ * 地图绕点自旋
+ */
+export function setMapSpin(jt3d) {
+	//移除左键单击事件
+	if (jt3d.handlerLeftClick) {
+		jt3d.handlerLeftClick.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
+	}
+
+	let SketchViewModel = new jt3dSDK.SketchViewModel(window.viewer, {
+		isClear: true,
+		isDrawPoint: false, //是否标记参考点
+		isRetainDrawPoint: false, //绘制完成是否保留绘制点
+		iconType: 'blue',
+	}, );
+
+	SketchViewModel.sketchTools('point', {
+		onComplete(cPoint, gPoint) {
+			jt3d.setMapSpinByPoint(cPoint, {
+				// height: 100000
+			});
+		},
+		onError(message) {}
+	});
+}
+
+/**
+ * 地图指北
+ */
+export function setMapNorth(jt3d) {
+	jt3d.setMapNorth();
+	jt3d.isSpan = false;
+}
+
+
+/**
+ * 移除卷帘
+ */
+export function removeSplitLayer(viewer, earthAtLeft, earthAtRight) {
+	let sliderDiv = document.getElementById("image_slider");
+	if (sliderDiv) {
+		document.body.removeChild(sliderDiv);
+	}
+	removeSplitLayerLeft(viewer, earthAtLeft);
+	removeSplitLayerRight(viewer, earthAtRight);
+
+	if (earthAtLeft) {
+		earthAtLeft.splitDirection = Cesium.SplitDirection.NONE;
+	}
+
+	if (earthAtRight) {
+		earthAtRight.splitDirection = Cesium.SplitDirection.NONE;
+	}
+}
+/**
+ * 移除左侧图层
+ */
+export function removeSplitLayerLeft(viewer, leftValue) {
+	setLayersControl(viewer, leftValue, false);
+
+	// if (earthAtLeft) {
+	// 	if (earthAtLeft instanceof Cesium.ImageryLayer) {
+	// 		viewer.imageryLayers.remove(earthAtLeft);
+	// 	}
+
+	// 	if (earthAtLeft instanceof Cesium.Cesium3DTileset) {
+	// 		viewer.scene.primitives.remove(earthAtLeft);
+	// 	}
+
+	// 	if (earthAtLeft instanceof Array) {
+	// 		earthAtLeft.forEach((res, index) => {
+	// 			viewer.scene.primitives.remove(res);
+	// 		})
+	// 	}
+	// }
+}
+/**
+ * 移除右侧图层
+ */
+export function removeSplitLayerRight(viewer, rightValue) {
+	setLayersControl(viewer, rightValue, false);
+	// if (earthAtRight) {
+	// 	if (earthAtRight instanceof Cesium.ImageryLayer) {
+	// 		viewer.imageryLayers.remove(earthAtRight);
+	// 	}
+
+	// 	if (earthAtRight instanceof Cesium.Cesium3DTileset) {
+	// 		viewer.scene.primitives.remove(earthAtRight);
+	// 	}
+
+	// 	if (earthAtRight instanceof Array) {
+	// 		earthAtRight.forEach((res, index) => {
+	// 			viewer.scene.primitives.remove(res);
+	// 		});
+	// 	}
+	// }
+}

+ 42 - 0
src/views/Map3d-自测/widget.vue

@@ -0,0 +1,42 @@
+<template>
+  <component :is="widget.component" v-bind="getWidgetAttr(widget)" />
+</template>
+<script lang="ts">
+import { useAttrs, defineComponent, provide } from "vue"
+import type { Widget } from "@/common/store/widget"
+
+export default defineComponent({
+  name: "jt-widget",
+  props: ["widget"],
+  setup(props) {
+    const attrs = useAttrs()
+
+    provide("getCurrentWidget", () => {
+      return props.widget.name
+    })
+
+    const getWidgetAttr = (widget: Widget) => {
+      let attr = {}
+      if (widget.meta && widget.meta.props) {
+        attr = {
+          ...attr,
+          ...widget.meta.props
+        }
+      }
+      if (widget.data && widget.data.props) {
+        attr = {
+          ...attr,
+          ...widget.data.props
+        }
+      }
+      return attr
+    }
+
+    return {
+      attrs,
+      getWidgetAttr
+    }
+  }
+})
+</script>
+

+ 6 - 0
src/views/Map3d/Map3DMain.vue

@@ -202,6 +202,12 @@
 			}
 		},
 
+		created() {
+			store.queryMapTables = [];
+			store.expandedKeys = [];
+			store.checkedkeys = [];
+		},
+
 		mounted() {
 			this.init();
 		}

+ 44 - 35
src/views/Map3d/components/manage-layer.vue

@@ -19,11 +19,11 @@
 		useWidget
 	} from "@/common/store/widget"
 
-	// const {
-	// 	activate,
-	// 	disable,
-	// 	currentWidget
-	// } = useWidget()
+	const {
+		activate,
+		disable,
+		currentWidget
+	} = useWidget()
 	// currentWidget.onUpdate(() => {
 	// 	treeData = []
 	// 	expandedKeys = []
@@ -93,7 +93,7 @@
 			 * @param {Object} data 传递给 data 属性的数组中该节点所对应的对象
 			 */
 			handleClick(data) {
-				let serviceId =  "service_" + data.layercode + data.layerorder;
+				let serviceId = "service_" + data.layercode + data.layerorder;
 				mapWork.setLayersLocation(window.viewer, {
 					serviceId: _serviceId,
 					parameterset: data.parameterset,
@@ -131,19 +131,6 @@
 				let _node = this.$refs.treeRef.getNode(data);
 				if (_node.isLeaf) {
 
-					//图层ID
-					let serviceId = "service_" + data.layercode + data.layerorder;
-					data.serviceId = serviceId;
-
-					//透明度
-					let opacity = 1;
-					if (data.opacity == null) {
-						opacity = 1;
-					} else {
-						opacity = Number(data.opacity);
-					}
-					data.opacity = opacity;
-
 					mapWork.setLayersControl(window.viewer, data, checked).then(res => {
 						if (res === true) {
 
@@ -154,6 +141,16 @@
 
 					this.$refs.treeRef.setChecked(_node, checked); //是否设置子节点,默认为false,利用tree组件渲染后带有的isLeaf(是否为叶子节点)属性,如果为叶子节点就选中。利用tree的API就实现了正确的回显效果	
 
+					if (checked) {
+						if (store.checkedkeys.indexOf(data.id) === -1) {
+							store.checkedkeys.push(data.id);
+						}
+					} else {
+						//过滤
+						store.checkedkeys = store.checkedkeys.filter(id => {
+							return id !== data.id
+						})
+					}
 				} else {
 					//控制子节点
 					this.childNodesChange(node, checked);
@@ -169,19 +166,6 @@
 				let _self = this;
 				node.childNodes.forEach(item => {
 
-					//图层ID
-					let serviceId = "service_" + item.data.layercode + item.data.layerorder;
-					item.data.serviceId = serviceId;
-
-					//透明度
-					let opacity = 1;
-					if (item.data.opacity == null) {
-						opacity = 1;
-					} else {
-						opacity = Number(item.data.opacity);
-					}
-					item.data.opacity = opacity;
-
 					mapWork.setLayersControl(window.viewer, item.data, checked).then(res => {
 						if (res === true) {
 
@@ -191,6 +175,17 @@
 					});
 
 					_self.$refs.treeRef.setChecked(item, checked);
+					if (checked) {
+						if (store.checkedkeys.indexOf(item.data.id) === -1) {
+							store.checkedkeys.push(item.data.id);
+						}
+					} else {
+						//过滤
+						store.checkedkeys = store.checkedkeys.filter(id => {
+							return id !== item.data.id
+						})
+					}
+					
 					_self.childNodesChange(item, checked);
 				});
 			},
@@ -209,9 +204,19 @@
 						if (num < 10) {
 							item.layerorder = '0' + item.layerorder
 						}
-
+						
+						//图层ID
+						let serviceId = "service_" + item.layercode + item.layerorder;
+						item.serviceId = serviceId;
+						
 						//透明度
-						item.opacity = Number(item.opacity);
+						let opacity = 1;
+						if (item.opacity == null) {
+							opacity = 1;
+						} else {
+							opacity = Number(item.opacity);
+						}
+						item.opacity = opacity;
 
 						// //默认展开
 						// if (item.isexpand === '1') {
@@ -224,7 +229,11 @@
 						// }
 					})
 
-					_self.treeData = deepTree(layers)
+					_self.treeData = deepTree(layers);
+					//复选框初始化选中
+					_self.$nextTick(() => {
+						_self.$refs.treeRef.setCheckedKeys(_self.checkedkeys, true);
+					});
 				});
 			}
 		},

+ 14 - 42
src/views/Map3d/components/map-compare.vue

@@ -108,20 +108,7 @@
 			handleCheckBoxChange(checked, data, node) {
 				let _node = this.$refs.treeRef.getNode(data);
 				if (_node.isLeaf) {
-
-					//图层ID
-					let serviceId = "serviceLeft_" + data.layercode + data.layerorder;
-					data.serviceId = serviceId;
-
-					//透明度
-					let opacity = 1;
-					if (data.opacity == null) {
-						opacity = 1;
-					} else {
-						opacity = Number(data.opacity);
-					}
-					data.opacity = opacity;
-
+					
 					mapWork.setLayersControl(window.viewerLeft, data, checked).then(res => {
 						if (res === true) {
 
@@ -144,19 +131,6 @@
 			childNodesChange(node, checked) {
 				let _self = this;
 				node.childNodes.forEach(item => {
-					//图层ID
-					let serviceId = "serviceLeft_" + item.data.layercode + item.data.layerorder;
-					item.data.serviceId = serviceId;
-
-					//透明度
-					let opacity = 1;
-					if (item.data.opacity == null) {
-						opacity = 1;
-					} else {
-						opacity = Number(item.data.opacity);
-					}
-					item.data.opacity = opacity;
-
 					mapWork.setLayersControl(window.viewerLeft, item.data, checked).then(res => {
 						if (res === true) {
 
@@ -282,9 +256,20 @@
 						if (num < 10) {
 							item.layerorder = '0' + item.layerorder
 						}
-
+						
+						//图层ID
+						let serviceId = "serviceLeft_" + item.layercode + item.layerorder;
+						item.serviceId = serviceId;
+						
 						//透明度
-						item.opacity = Number(item.opacity);
+						let opacity = 1;
+						if (item.opacity == null) {
+							opacity = 1;
+						} else {
+							opacity = Number(item.opacity);
+						}
+						item.opacity = opacity;
+
 
 						//默认展开
 						if (item.isexpand === '1') {
@@ -295,19 +280,6 @@
 						if (item.isinit === '1') {
 							_self.checkedkeys.push(item.id);
 
-							//图层ID
-							let serviceId = "serviceLeft_" + item.layercode + item.layerorder;
-							item.serviceId = serviceId;
-
-							//透明度
-							let opacity = 1;
-							if (item.opacity == null) {
-								opacity = 1;
-							} else {
-								opacity = Number(item.opacity);
-							}
-							item.opacity = opacity;
-
 							mapWork.setLayersControl(window.viewerLeft, item, true).then(res => {
 								if (res === true) {
 

+ 6 - 30
src/views/Map3d/components/map-split.vue

@@ -65,7 +65,7 @@
 			 * @param {Object} item
 			 */
 			handleClickLeft(item) {
-				
+
 				let _self = this;
 
 				//移除
@@ -86,10 +86,10 @@
 					_self.leftValue = item;
 
 					earthAtLeft = window[item.serviceId];
-					earthAtLeft.splitDirection = Cesium.SplitDirection.LEFT;
+					earthAtLeft.splitDirection = Cesium.SplitDirection.LEFT; //-1.0
 				});
 			},
-			
+
 			/**
 			 * 
 			 * 
@@ -97,7 +97,7 @@
 			 * @param {Object} item
 			 */
 			handleClickRight(item) {
-				
+
 				let _self = this;
 
 				//移除
@@ -118,7 +118,7 @@
 					_self.rightValue = item;
 
 					earthAtRight = window[item.serviceId];
-					earthAtRight.splitDirection = Cesium.SplitDirection.RIGHT;
+					earthAtRight.splitDirection = Cesium.SplitDirection.RIGHT; //1.0
 				});
 
 			},
@@ -242,32 +242,8 @@
 
 			},
 
-			/**
-			 * 移除卷帘
-			 */
-			removeSplitLayer() {
-				let sliderDiv = document.getElementById("image_slider");
-				if (sliderDiv) {
-					document.body.removeChild(sliderDiv);
-				}
-
-				if (earthAtLeft) {
-					mapWork.setLayersControl(window.viewer, this.leftValue, false);
-					earthAtLeft.splitDirection = Cesium.SplitDirection.NONE;
-				}
-
-				if (earthAtRight) {
-					mapWork.setLayersControl(window.viewer, this.rightValue, false);
-					earthAtRight.splitDirection = Cesium.SplitDirection.NONE;
-				}
-			},
-
 			closeJTPopup() {
-				if (window.viewerLeft) {
-					mapWork.removeSplitScreen(window.viewerLeft);
-				}
-				// mapWork.removeSplitLayer(window.viewer, earthAtLeft, earthAtRight,_self.leftValue,_self.rightValue);
-				this.removeSplitLayer();
+				mapWork.removeSplitLayer(window.viewer);
 			}
 		},
 

+ 50 - 20
src/views/Map3d/components/toolbars.vue

@@ -21,10 +21,10 @@
 		Store
 	} from '@/store/index'
 	store = Store()
-	
+
 	const getMapInstance = inject("getMapInstance");
 	let jt3d = getMapInstance();
-	
+
 	import * as mapWork from "../map"
 
 	import {
@@ -34,28 +34,58 @@
 
 	const {
 		activate,
-		disable
+		isActivate,
+		disable,
+		currentWidget,
+		updateWidget,
+		getWidget
 	} = useWidget()
 
 	const showWidget = (widget) => {
-		//全图
-		if (widget === "fullMap") {
+
+		if (widget === "fullMap") { //全图
 			mapWork.fullMap(jt3d);
-		}
-		//绕点自旋
-		else if (widget === "rotateCamera") {
+		} else if (widget === "rotateCamera") { //绕点自旋
 			ElMessage.warning('在地图上单击进行自旋,再次单击停止自旋')
 			mapWork.setMapSpin(jt3d);
-		}
-		//清除所有
-		else if (widget === "clearAll") {
-
-		} else {
-			// if (window.viewerLeft) {
-			// 	disable("map-compare")
-			// 	// mapWork.removeSplitScreen(window.viewerLeft);
-			// }
+		} else if (widget === "clearAll") { //清除所有
+
+		} else if (widget === "map-compare") { //分屏对比
+
+			if (!isActivate("manage-layer")) {
+				activate("manage-layer");
+			} else {
+				updateWidget("manage-layer", {
+					data: {
+						//graphic: markRaw(graphic)
+					}
+				})
+			}
+
+			if (isActivate("map-split")) {
+				disable("map-split")
+				mapWork.removeSplitLayer(window.viewer);
+			}
+
+			activate(widget)
+
+		} else if (widget === "map-split") { //卷帘对比		
+			if (isActivate("map-compare")) {
+				disable("map-compare")
+				mapWork.removeSplitScreen(window.viewerLeft);
+			}
+			activate(widget)
+		}else {
+			if (isActivate("map-compare")) {
+				disable("map-compare")
+				mapWork.removeSplitScreen(window.viewerLeft);
+			}
 			
+			if (isActivate("map-split")) {
+				disable("map-split")
+				mapWork.removeSplitLayer(window.viewer);
+			}
+
 			activate(widget)
 		}
 	}
@@ -203,7 +233,7 @@
 			padding: 0rem 10rem;
 
 			margin: 0rem;
-			height: calc(100% - 4rem);
+			// height: calc(100% - 4rem);
 			color: #fff;
 			font-size: 15rem;
 			vertical-align: middle;
@@ -220,8 +250,8 @@
 		.toolbar-item:nth-last-child(1) {
 			padding-right: 0rem;
 		}
-		
-		.iconfont{
+
+		.iconfont {
 			margin-right: 5rem;
 		}
 

+ 52 - 74
src/views/Map3d/map.js

@@ -6,6 +6,7 @@ let store = Store();
 import http from '@/utils/http.js'
 
 // import * as jt3dSDK from '/public/jt3dSDK/jt3d.es.js';
+import "@jintian/Map3dSDK"
 
 import map_xzqh_zj from '@/assets/dataFile/xz.json';
 
@@ -148,7 +149,7 @@ export function fullMap(jt3d) {
 		pitch: -90,
 		range: 60000
 	};
-	
+
 	let optionsE = {
 		west: 116.883783, //西
 		south: 36.573500, //南
@@ -208,6 +209,20 @@ export function setLayersControl(viewer, options, checked) {
 		parameterset = JSON.parse(options.parameterset);
 	}
 
+	//在显示的图层中,如果图层配置可以查询,则进行查询
+	if (options.querytable) {
+		if (checked) {
+			if (store.queryMapTables.indexOf(options.querytable) === -1) {
+				store.queryMapTables.push(options.querytable);
+			}
+		} else {
+			//过滤
+			store.queryMapTables = store.queryMapTables.filter(tableName => {
+				return tableName !== options.querytable
+			})
+		}
+	}
+
 	return new Promise((resolve, reject) => {
 		switch (options.loadtype) {
 			case "DEM": //地形服务(DEM)
@@ -987,8 +1002,8 @@ export function setLayerNumber(imageryLayers, options) {
 	imageryLayers.lowerToBottom(window[options.serviceId]);
 	imageryLayers.raise(window[options.serviceId]);
 	imageryLayers.raise(window[options.serviceId]);
-	
-	let serviceMark=options.serviceId.split('_')[0]
+
+	let serviceMark = options.serviceId.split('_')[0]
 
 	getAllLayers().then(layers => {
 		layers.map((item) => {
@@ -1019,25 +1034,6 @@ export function setLayerNumber(imageryLayers, options) {
 }
 
 /**
- * 移除分屏对比
- */
-export function removeSplitScreen(viewer) {
-	let mapView1 = document.getElementById("cesiumContainer");
-	let mapView2 = document.getElementById("cesiumContainer2");
-
-	mapView1.className = "jt-map";
-	mapView2.style.display = "none";
-	mapView2.innerHTML = "";
-
-	if (viewer) {
-		viewer.entities.removeAll(); // 删除全部
-		viewer.imageryLayers.removeAll();
-		viewer.scene.primitives.removeAll(); //谨慎使用,可能删除不必要的primitive
-		viewer.destroy();
-	}
-}
-
-/**
  * 地图绕点自旋
  */
 export function setMapSpin(jt3d) {
@@ -1071,66 +1067,48 @@ export function setMapNorth(jt3d) {
 	jt3d.isSpan = false;
 }
 
+/**
+ * 移除分屏对比
+ */
+export function removeSplitScreen(viewer) {
+	let mapView1 = document.getElementById("cesiumContainer");
+	let mapView2 = document.getElementById("cesiumContainer2");
+
+	mapView1.className = "jt-map";
+	mapView2.style.display = "none";
+	mapView2.innerHTML = "";
+
+	if (viewer) {
+		viewer.entities.removeAll(); // 删除全部
+		viewer.imageryLayers.removeAll();
+		viewer.scene.primitives.removeAll(); //谨慎使用,可能删除不必要的primitive
+		// viewer.destroy();
+	}
+}
 
 /**
  * 移除卷帘
  */
-export function removeSplitLayer(viewer, earthAtLeft, earthAtRight) {
+export function removeSplitLayer(viewer) {
 	let sliderDiv = document.getElementById("image_slider");
 	if (sliderDiv) {
 		document.body.removeChild(sliderDiv);
 	}
-	removeSplitLayerLeft(viewer, earthAtLeft);
-	removeSplitLayerRight(viewer, earthAtRight);
 
-	if (earthAtLeft) {
-		earthAtLeft.splitDirection = Cesium.SplitDirection.NONE;
-	}
+	let leftLayer = null
+	let rightLayer = null
+	viewer.imageryLayers._layers.map((imageryLayer, index) => {
+		if (imageryLayer.splitDirection == -1) {
+			imageryLayer.splitDirection = Cesium.SplitDirection.NONE;
+			leftLayer = imageryLayer
+		}
 
-	if (earthAtRight) {
-		earthAtRight.splitDirection = Cesium.SplitDirection.NONE;
-	}
-}
-/**
- * 移除左侧图层
- */
-export function removeSplitLayerLeft(viewer, leftValue) {
-	setLayersControl(viewer, leftValue, false);
-
-	// if (earthAtLeft) {
-	// 	if (earthAtLeft instanceof Cesium.ImageryLayer) {
-	// 		viewer.imageryLayers.remove(earthAtLeft);
-	// 	}
-
-	// 	if (earthAtLeft instanceof Cesium.Cesium3DTileset) {
-	// 		viewer.scene.primitives.remove(earthAtLeft);
-	// 	}
-
-	// 	if (earthAtLeft instanceof Array) {
-	// 		earthAtLeft.forEach((res, index) => {
-	// 			viewer.scene.primitives.remove(res);
-	// 		})
-	// 	}
-	// }
-}
-/**
- * 移除右侧图层
- */
-export function removeSplitLayerRight(viewer, rightValue) {
-	setLayersControl(viewer, rightValue, false);
-	// if (earthAtRight) {
-	// 	if (earthAtRight instanceof Cesium.ImageryLayer) {
-	// 		viewer.imageryLayers.remove(earthAtRight);
-	// 	}
-
-	// 	if (earthAtRight instanceof Cesium.Cesium3DTileset) {
-	// 		viewer.scene.primitives.remove(earthAtRight);
-	// 	}
-
-	// 	if (earthAtRight instanceof Array) {
-	// 		earthAtRight.forEach((res, index) => {
-	// 			viewer.scene.primitives.remove(res);
-	// 		});
-	// 	}
-	// }
+		if (imageryLayer.splitDirection == 1) {
+			imageryLayer.splitDirection = Cesium.SplitDirection.NONE;
+			rightLayer = imageryLayer
+		}
+	})
+
+	viewer.imageryLayers.remove(leftLayer);
+	viewer.imageryLayers.remove(rightLayer);
 }