index.vue 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198
  1. <template>
  2. <div class="container">
  3. <el-row id="earth" style="height: 100%; width: 100%; display: flex; position: relative">
  4. <el-col style="height: 100%; position: relative" :span="this.leftwidth">
  5. <div class="main-layout" v-on:mouseover="changeActive('2D')" @mousemove="getMouseLocation">
  6. <div id="2DcesiumContainer" class="map" @click="onMapClick"></div>
  7. </div>
  8. </el-col>
  9. <el-col style="height: 100%; position: relative" :span="24 - this.leftwidth">
  10. <div class="main-layout" v-on:mouseover="changeActive('3D')" @mousemove="getMouseLocation">
  11. <div id="3DcesiumContainer" class="map" @click="onMapClick"></div>
  12. </div>
  13. </el-col>
  14. <el-tabs type="border-card" v-model="activeName" tab-position="left" class="menu" :stretch="true"
  15. @tab-click="legendClick">
  16. <!-- <el-tab-pane name="first">
  17. <el-tooltip placement="right" effect="light" slot="label">
  18. <span slot="content" class="item">标绘</span>
  19. <span><i class="el-icon-wind-power"></i></span>
  20. </el-tooltip>
  21. </el-tab-pane> -->
  22. <!-- <el-tab-pane name="second">
  23. <el-tooltip placement="right" effect="light" slot="label">
  24. <span slot="content" class="item">模型</span>
  25. <span><i class="el-icon-receiving"></i></span>
  26. </el-tooltip>
  27. <Model @selectModel="selectModel" :isShow="isShow"></Model>
  28. </el-tab-pane> -->
  29. <!-- <el-tab-pane name="third">
  30. <el-tooltip placement="right" effect="light" slot="label">
  31. <span slot="content" class="item">测量</span>
  32. <span><i class="el-icon-discount"></i></span>
  33. </el-tooltip>
  34. </el-tab-pane> -->
  35. <el-tab-pane name="fouth">
  36. <el-tooltip placement="right" effect="light" slot="label">
  37. <span slot="content" class="item">测想定</span>
  38. <span><i class="el-icon-house"></i></span>
  39. </el-tooltip>
  40. <el-table :data="situation">
  41. <el-table-column label="名称" prop="xdname" width="150px"></el-table-column>
  42. <el-table-column label="操作" align="center">
  43. <template slot-scope="scope">
  44. <el-button type="primary" @click="getJson(scope.row)">导入</el-button>
  45. <!-- <el-button type="primary" @click="saveJson()">保存</el-button> -->
  46. </template>
  47. </el-table-column>
  48. </el-table>
  49. </el-tab-pane>
  50. </el-tabs>
  51. <div class="buttons">
  52. <el-button icon="el-icon-full-screen" circle @click="ismax()"></el-button>
  53. <el-button icon="el-icon-house" circle @click="home()"></el-button>
  54. <el-button icon="el-icon-plus" circle @click="big()"></el-button>
  55. <el-button icon="el-icon-minus" circle @click="small()"></el-button>
  56. <el-button icon="el-icon-download" circle @click="saveJson()"></el-button>
  57. </div>
  58. </el-row>
  59. <div v-if="isShow" class="modeltooltip" ref="modeltooltip">{{ modeltooltip }}</div>
  60. </div>
  61. </template>
  62. <script>
  63. import screenfull from "screenfull";
  64. import fireController from "@/api/fireController.js";
  65. import { getToken } from "@/utils";
  66. import axios from "axios";
  67. import Model from "@/views/situation/Model.vue";
  68. import satelliteModel from '@/assets/model/satelite.glb';
  69. import missileModel from '@/assets/model/basic_missle.glb';
  70. import thaadModel from '@/assets/model/anti-aircraft_gun_fire_control_radar_vehicle.glb';
  71. import centerModel from '@/assets/model/himars_animated.glb';
  72. import { mapGetters } from "vuex";
  73. export default {
  74. components: {
  75. Model
  76. },
  77. computed: {
  78. ...mapGetters([
  79. "dimension"
  80. ])
  81. },
  82. data() {
  83. return {
  84. save : false,
  85. situation: [],
  86. nameIdList:[],
  87. websocket: null,
  88. leftwidth: 12,
  89. unit: [],
  90. satellite: [],
  91. center: [],
  92. move_data: {},
  93. viewer2D: null,
  94. viewer3D: null,
  95. mousevalue: null,
  96. // 选中的点
  97. selectedMarker: null,
  98. // 以前的标记点坐标
  99. oldPosition: null,
  100. activeName: null,
  101. currentLab: {
  102. index: -1,
  103. isActive: false
  104. },
  105. url: "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
  106. isShow: false,
  107. handler3D: null,
  108. handler2D: null,
  109. image: null,
  110. modeltooltip: null,
  111. id: 1
  112. };
  113. },
  114. watch: {
  115. dimension: {
  116. handler: function (val, oldVal) {
  117. console.log(val)
  118. if (val == 2) {
  119. this.leftwidth = 24;
  120. } else if (val == 3) {
  121. this.leftwidth = 0;
  122. } else if (val == 5) {
  123. this.leftwidth = 12;
  124. }
  125. },
  126. },
  127. },
  128. created() {
  129. this.getData();
  130. },
  131. mounted() {
  132. this.cesiumInit();
  133. this.pointMove();
  134. this.startWebSocket();
  135. },
  136. beforeDestroy() {
  137. // 在组件销毁前,关闭WebSocket连接
  138. if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
  139. this.websocket.close();
  140. }
  141. },
  142. methods: {
  143. startWebSocket() {
  144. this.websocket = new WebSocket('ws://localhost:8765');
  145. this.websocket.onopen = () => {
  146. console.log('WebSocket连接已建立!');
  147. };
  148. this.websocket.onmessage = (event) => {
  149. // 处理从WebSocket服务器接收到的消息
  150. const data = JSON.parse(event.data);
  151. console.log('收到消息:', data);
  152. // 在这里处理接收到的数据,更新Vue组件的数据等操作
  153. };
  154. this.websocket.onerror = (error) => {
  155. console.error('WebSocket错误:', error);
  156. };
  157. this.websocket.onclose = () => {
  158. console.log('WebSocket连接已关闭!');
  159. };
  160. },
  161. async saveJson() {
  162. if(this.save){
  163. const jsonData = JSON.stringify(this.jsonData);
  164. const blob = new Blob([jsonData], { type: 'application/json' });
  165. const url = URL.createObjectURL(blob);
  166. const link = document.createElement('a');
  167. link.href = url;
  168. link.download = this.jsonData.xdname + '.json';
  169. document.body.appendChild(link);
  170. link.click();
  171. document.body.removeChild(link);
  172. }
  173. else{
  174. this.$message("请先导入想定文件!!!")
  175. }
  176. // await axios
  177. // .post("http://localhost:8084/admin/online/onlineOperation/updateDatasource/main", {
  178. // params: {
  179. // datasourceId: "1656243335922192384",
  180. // masterData: row,
  181. // slaveData: {}
  182. // }
  183. // })
  184. // .then((res) => {
  185. // console.log("update successfully ");
  186. // });
  187. // const requestData = row
  188. // if(this.websocket && this.websocket.readyState === WebSocket.OPEN){
  189. // this.websocket.send(JSON.stringify(requestData));
  190. // }
  191. // else{
  192. // this.startWebSocket();
  193. // setTimeout(() => {
  194. // this.websocket.send(JSON.stringify(requestData));
  195. // }, 2000);
  196. // }
  197. },
  198. changeItemPosition(data) {
  199. },
  200. async getJson(row) {
  201. let redunit = [];
  202. let blueunit = [];
  203. let satellite = [];
  204. let center = [];
  205. // let fileInfoStr = row.blueunit;
  206. // let fileInfoArr = JSON.parse(fileInfoStr);
  207. // for (let i = 0; i < fileInfoArr.length; i++) {
  208. // await axios
  209. // .get("http://localhost:8084/admin/online/onlineOperation/downloadDatasource/main", {
  210. // params: {
  211. // datasourceId: "1656243335922192384",
  212. // fieldName: "blueunit",
  213. // asImage: false,
  214. // dataId: row.id,
  215. // filename: fileInfoArr[i].filename,
  216. // Authorization: getToken(),
  217. // MenuId: "1656244747347431424"
  218. // }
  219. // })
  220. // .then((response) => {
  221. // // 处理成功的响应
  222. // blueunit.push(response.data);
  223. // })
  224. // .catch((error) => {
  225. // // 处理错误
  226. // console.error(error);
  227. // });
  228. // }
  229. // fileInfoStr = row.redunit;
  230. // fileInfoArr = JSON.parse(fileInfoStr);
  231. // for (let i = 0; i < fileInfoArr.length; i++) {
  232. // await axios
  233. // .get("http://localhost:8084/admin/online/onlineOperation/downloadDatasource/main", {
  234. // params: {
  235. // datasourceId: "1656243335922192384",
  236. // fieldName: "redunit",
  237. // asImage: false,
  238. // dataId: row.id,
  239. // filename: fileInfoArr[i].filename,
  240. // Authorization: getToken(),
  241. // MenuId: "1656244747347431424"
  242. // }
  243. // })
  244. // .then((response) => {
  245. // // 处理成功的响应
  246. // redunit.push(response.data);
  247. // })
  248. // .catch((error) => {
  249. // // 处理错误
  250. // console.error(error);
  251. // });
  252. // }
  253. // fileInfoStr = row.center;
  254. // fileInfoArr = JSON.parse(fileInfoStr);
  255. // for (let i = 0; i < fileInfoArr.length; i++) {
  256. // await axios
  257. // .get("http://localhost:8084/admin/online/onlineOperation/downloadDatasource/main", {
  258. // params: {
  259. // datasourceId: "1656243335922192384",
  260. // fieldName: "center",
  261. // asImage: false,
  262. // dataId: row.id,
  263. // filename: fileInfoArr[i].filename,
  264. // Authorization: getToken(),
  265. // MenuId: "1656244747347431424"
  266. // }
  267. // })
  268. // .then((response) => {
  269. // // 处理成功的响应
  270. // center.push(response.data);
  271. // })
  272. // .catch((error) => {
  273. // // 处理错误
  274. // console.error(error);
  275. // });
  276. // }
  277. // fileInfoStr = row.satellite;
  278. // fileInfoArr = JSON.parse(fileInfoStr);
  279. // for (let i = 0; i < fileInfoArr.length; i++) {
  280. // await axios
  281. // .get("http://localhost:8084/admin/online/onlineOperation/downloadDatasource/main", {
  282. // params: {
  283. // datasourceId: "1656243335922192384",
  284. // fieldName: "satellite",
  285. // asImage: false,
  286. // dataId: row.id,
  287. // filename: fileInfoArr[i].filename,
  288. // Authorization: getToken(),
  289. // MenuId: "1656244747347431424"
  290. // }
  291. // })
  292. // .then((response) => {
  293. // // 处理成功的响应
  294. // satellite.push(response.data);
  295. // })
  296. // .catch((error) => {
  297. // // 处理错误
  298. // console.error(error);
  299. // });
  300. // }
  301. // const jsonData = {}
  302. // id: row.id,
  303. // xdname: row.xdname,
  304. // type: row.type,
  305. // creator: row.creator,
  306. // createtime: row.createtime,
  307. // bluecnt: row.bluecnt,
  308. // target: row.target,
  309. // starttime: row.starttime,
  310. // steptime: row.steptime,
  311. // blueunit: blueunit,
  312. // redunit: redunit,
  313. // satellite: satellite,
  314. // center: center
  315. // };
  316. let fileInfoStr = row.xdfile;
  317. let fileInfoArr = JSON.parse(fileInfoStr);
  318. await axios
  319. .get("http://localhost:8084/admin/online/onlineOperation/downloadDatasource/main", {
  320. params: {
  321. datasourceId: "1656243335922192384",
  322. fieldName: "xdfile",
  323. asImage: false,
  324. dataId: row.id,
  325. filename: fileInfoArr[0].filename,
  326. Authorization: getToken(),
  327. MenuId: "1656244747347431424"
  328. }
  329. })
  330. .then((response) => {
  331. console.log('response.data :>> ', response.data);
  332. // // 处理成功的响应
  333. // jsonData = response.data
  334. blueunit = response.data.blueunit
  335. redunit = response.data.redunit
  336. satellite = response.data.satellite
  337. center = response.data.center
  338. this.save = true
  339. this.jsonData = {
  340. id: row.id,
  341. xdname: row.xdname,
  342. type: row.type,
  343. creator: row.creator,
  344. createtime: row.createtime,
  345. bluecnt: row.bluecnt,
  346. target: row.target,
  347. starttime: row.starttime,
  348. steptime: row.steptime,
  349. blueunit: blueunit,
  350. redunit: redunit,
  351. satellite: satellite,
  352. center: center
  353. }
  354. })
  355. .catch((error) => {
  356. // 处理错误
  357. console.error(error);
  358. });
  359. for(let i =0;i<blueunit.length;i++){
  360. this.markLocationbyJson(parseFloat(blueunit[i].pos.lat),parseFloat(blueunit[i].pos.lon),parseFloat(blueunit[i].pos.height),blueunit[i].name,"blue")
  361. }
  362. for(let i = 0;i<center.length;i++){
  363. let item = center[i]
  364. this.markLocationbyJson(parseFloat(item[center[i].name].properties.lat),parseFloat(item[center[i].name].properties.lon),parseFloat(item[center[i].name].properties.h),item.name,"center")
  365. }
  366. for(let i = 0;i<redunit.length;i++){
  367. this.markLocationbyJson(parseFloat(redunit[i].component_movementjson.properties.launch_lat),parseFloat(redunit[i].component_movementjson.properties.launch_lon),parseFloat(redunit[i].component_movementjson.properties.launch_h),redunit[i].name,"red")
  368. let point1 = {
  369. longitude : parseFloat(redunit[i].component_movementjson.properties.launch_lon),
  370. latitude : parseFloat(redunit[i].component_movementjson.properties.launch_lat),
  371. height :parseFloat(redunit[i].component_movementjson.properties.launch_h)
  372. }
  373. let point2 = {
  374. longitude : parseFloat(redunit[i].component_movementjson.properties.target_lon),
  375. latitude : parseFloat(redunit[i].component_movementjson.properties.target_lat),
  376. height : parseFloat(redunit[i].component_movementjson.properties.target_h)
  377. }
  378. this.markLine(point1,point2,"red")
  379. }
  380. },
  381. //获取所有数据
  382. getData() {
  383. this.getCenter();
  384. this.getSatellite();
  385. this.getUnit();
  386. this.getSituation();
  387. },
  388. // 获取场景想定数据
  389. getSituation() {
  390. let params = {
  391. datasourceId: "1656243335922192384",
  392. filterDtoList: [],
  393. pageParam: {
  394. pageNum: 1,
  395. pageSize: 10
  396. }
  397. };
  398. fireController.situation(this, params).then((res) => {
  399. this.situation = res.data.dataList;
  400. });
  401. },
  402. // 获取作战单元数据
  403. getUnit() {
  404. let params = {
  405. datasourceId: "1657931215497334784",
  406. filterDtoList: [],
  407. pageParam: {
  408. pageNum: 1,
  409. pageSize: 10
  410. }
  411. };
  412. fireController.unit(this, params).then((res) => {
  413. this.unit = res.data.dataList;
  414. });
  415. },
  416. // 获取指挥中心数据
  417. getCenter() {
  418. let params = {
  419. datasourceId: "1654421731512684544",
  420. filterDtoList: [],
  421. pageParam: {
  422. pageNum: 1,
  423. pageSize: 10
  424. }
  425. };
  426. fireController.center(this, params).then((res) => {
  427. this.center = res.data.dataList;
  428. });
  429. },
  430. // 获取预警卫星数据
  431. getSatellite() {
  432. let params = {
  433. datasourceId: "1654424480958648320",
  434. filterDtoList: [],
  435. pageParam: {
  436. pageNum: 1,
  437. pageSize: 10
  438. }
  439. };
  440. fireController.satellite(this, params).then((res) => {
  441. this.satellite = res.data.dataList;
  442. });
  443. },
  444. cesiumInit() {
  445. this.viewer2D = new this.Cesium.Viewer("2DcesiumContainer", {
  446. sceneMode: this.Cesium.SceneMode.SCENE2D,
  447. animation: false, // 是否显示时间轴动画
  448. baseLayerPicker: false,
  449. homeButton: false,
  450. geocoder: false,
  451. timeline: false,
  452. fullscreenButton: false,
  453. sceneModePicker: false,
  454. navigationHelpButton: false,
  455. selectionIndicator: false,
  456. imageryProvider: new this.Cesium.UrlTemplateImageryProvider({
  457. url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
  458. layer: "tdtVecBasicLayer",
  459. style: "default",
  460. format: "image/png",
  461. tileMatrixSetID: "GoogleMapsCompatible",
  462. show: false
  463. })
  464. });
  465. this.viewer3D = new this.Cesium.Viewer("3DcesiumContainer", {
  466. animation: false, // 是否显示时间轴动画
  467. baseLayerPicker: false,
  468. homeButton: false,
  469. geocoder: false,
  470. timeline: false,
  471. fullscreenButton: false,
  472. sceneModePicker: false,
  473. navigationHelpButton: false,
  474. selectionIndicator: false,
  475. // imageryProvider: new this.Cesium.WebMapServiceImageryProvider({
  476. // url: '/geoserver/map/wms',
  477. // // 这里是自定义的图层名称
  478. // layers: 'map',
  479. // parameters: {
  480. // service: 'WMS',
  481. // format: 'image/png',
  482. // transparent: true
  483. // }
  484. // }),
  485. imageryProvider:
  486. // new this.Cesium.WebMapTileServiceImageryProvider({
  487. // url: "http://10.170.16.95:8080/geoserver/gwc/service/wmts/rest/map:map/{style}/{TileMatrixSet}/{TileMatrixSet}:{TileMatrix}/{TileRow}/{TileCol}?format=image/png",
  488. // layer: 'map:map',
  489. // style: 'raster',
  490. // format: 'image/png',
  491. // tileMatrixSetID: 'EPSG:900913', //一般使用EPSG:3857坐标系
  492. // }),
  493. new this.Cesium.UrlTemplateImageryProvider({
  494. url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
  495. layer: "tdtVecBasicLayer",
  496. style: "default",
  497. format: "image/png",
  498. tileMatrixSetID: "GoogleMapsCompatible",
  499. show: false
  500. })
  501. });
  502. this.viewer3D._cesiumWidget._creditContainer.style.display = "none";
  503. this.viewer2D._cesiumWidget._creditContainer.style.display = "none";
  504. this.viewer3D.camera.setView({
  505. destination: new this.Cesium.Cartesian3.fromDegrees(117.918977, 25.0, 1500000)
  506. // 方向,俯视和仰视的视角
  507. // orientation:{
  508. // heading: this.Cesium.Math.toRadians(90),//坐标系旋转90度
  509. // pitch: this.Cesium.Math.toRadians(-45) ,//设置俯仰角度为-45度
  510. // }
  511. });
  512. this.viewer2D.camera.setView({
  513. destination: new this.Cesium.Cartesian3.fromDegrees(117.918977, 25.0, 1500000)
  514. // 方向,俯视和仰视的视角
  515. // orientation:{
  516. // heading: this.Cesium.Math.toRadians(90),//坐标系旋转90度
  517. // pitch: this.Cesium.Math.toRadians(-45) ,//设置俯仰角度为-45度
  518. // }
  519. });
  520. // this.viewer.scene.screenSpaceCameraController.maximumZoomDistance = 1500000; //相机高度的最大值
  521. this.viewer2D.camera.percentageChanged = 0.01;
  522. this.viewer2D.camera.changed.addEventListener(this.sync); //地图移动事件
  523. this.viewer3D.camera.percentageChanged = 0.01;
  524. this.viewer3D.camera.changed.addEventListener(this.sync); //地图移动事件
  525. this.viewer2D.camera.moveEnd.addEventListener(this.getCammeraHeightAndZoom) //地图缩放事件
  526. this.viewer3D.camera.moveEnd.addEventListener(this.getCammeraHeightAndZoom) //地图缩放事件
  527. this.handler2D = new this.Cesium.ScreenSpaceEventHandler(this.viewer2D.scene.canvas);
  528. this.handler3D = new this.Cesium.ScreenSpaceEventHandler(this.viewer3D.scene.canvas);
  529. },
  530. sync() {
  531. if (this.mousevalue == "3D") {
  532. // 三维地图中心点
  533. let center = new this.Cesium.Cartesian2(
  534. Math.floor(this.viewer3D.canvas.clientWidth / 2),
  535. Math.floor(this.viewer3D.canvas.clientHeight / 2)
  536. );
  537. // 转为世界坐标系
  538. let position = this.viewer3D.scene.camera.pickEllipsoid(center);
  539. // 判断中心点是否在椭球体上
  540. if (this.Cesium.defined(position)) {
  541. // 获取三维地图中心点与相机之间的距离
  542. let distance = this.Cesium.Cartesian3.distance(position, this.viewer3D.scene.camera.positionWC);
  543. position = this.convertWorldToCartographic(position);
  544. // 更新二维地图
  545. this.viewer2D.scene.camera.setView({
  546. destination: new this.Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude, distance)
  547. });
  548. }
  549. }
  550. if (this.mousevalue == "2D") {
  551. // 二维地图中心点
  552. let center = new this.Cesium.Cartesian2(
  553. Math.floor(this.viewer2D.canvas.clientWidth / 2),
  554. Math.floor(this.viewer2D.canvas.clientHeight / 2)
  555. );
  556. // 转为世界坐标系
  557. let position = this.viewer2D.scene.camera.pickEllipsoid(center);
  558. // 判断中心点是否在椭球体上
  559. if (this.Cesium.defined(position)) {
  560. // 获取三维地图中心点与相机之间的距离
  561. let distance = this.viewer2D.scene.camera.positionCartographic.height;
  562. position = this.convertWorldToCartographic(position);
  563. // 更新三维地图
  564. this.viewer3D.scene.camera.setView({
  565. destination: new this.Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude, distance)
  566. });
  567. }
  568. }
  569. },
  570. // 将世界坐标系转换为经纬度坐标系
  571. convertWorldToCartographic(worldPosition) {
  572. const ellipsoid = this.viewer2D.scene.globe.ellipsoid;
  573. const cartographic = ellipsoid.cartesianToCartographic(worldPosition);
  574. const longitude = this.Cesium.Math.toDegrees(cartographic.longitude);
  575. const latitude = this.Cesium.Math.toDegrees(cartographic.latitude);
  576. const height = cartographic.height;
  577. return { longitude, latitude, height };
  578. },
  579. // 监听地图变化
  580. changeActive(value) {
  581. this.mousevalue = value;
  582. },
  583. dimensionswitch(value) {
  584. this.dimension = value;
  585. this.selectModel();
  586. },
  587. // 全屏缩小
  588. ismax() {
  589. if (screenfull.isEnabled && screenfull.isFullscreen) {
  590. screenfull.exit();
  591. } else {
  592. screenfull.request();
  593. }
  594. },
  595. /* 获取camera中心点坐标 */
  596. getCenterPosition(is3D = false) {
  597. let viewer = is3D ? this.viewer3D : this.viewer2D;
  598. let result = viewer.camera.pickEllipsoid(
  599. new this.Cesium.Cartesian2(viewer.canvas.clientWidth / 2, viewer.canvas.clientHeight / 2)
  600. );
  601. let curPosition = this.Cesium.Ellipsoid.WGS84.cartesianToCartographic(result);
  602. let lon = (curPosition.longitude * 180) / Math.PI;
  603. let lat = (curPosition.latitude * 180) / Math.PI;
  604. let height = viewer.camera.positionCartographic.height;
  605. return {
  606. lon: lon,
  607. lat: lat,
  608. height: height
  609. };
  610. },
  611. /* 地图放大 */
  612. big() {
  613. let { lon, lat, height } = this.getCenterPosition(this.dimension === 3);
  614. let viewer = (this.dimension === 3 || this.dimension === 5)? this.viewer3D : this.viewer2D;
  615. // 镜头拉进
  616. viewer.camera.flyTo({
  617. destination: this.Cesium.Cartesian3.fromDegrees(lon, lat, height / 1.8),
  618. duration: 1.0
  619. });
  620. },
  621. /* 地图缩小 */
  622. small() {
  623. let { lon, lat, height } = this.getCenterPosition(this.dimension === 3);
  624. let viewer = (this.dimension === 3 || this.dimension === 5) ? this.viewer3D : this.viewer2D;
  625. // 镜头远离
  626. viewer.camera.flyTo({
  627. destination: this.Cesium.Cartesian3.fromDegrees(lon, lat, height * 1.2),
  628. duration: 1.0
  629. });
  630. },
  631. home() {
  632. let viewer = (this.dimension === 3 || this.dimension === 5)? this.viewer3D : this.viewer2D;
  633. viewer.camera.flyTo({
  634. destination: this.Cesium.Cartesian3.fromDegrees(117.918977, 25.0, 1500000),
  635. duration: 2.0
  636. });
  637. },
  638. // tabs 切换点击
  639. legendClick({ index }) {
  640. this.selectModel();
  641. let tab_content = document.querySelectorAll(".menu .el-tabs__content");
  642. if (this.currentLab.index == index) {
  643. tab_content[0].style.display == "none" || ""
  644. ? (tab_content[0].style.display = "block")
  645. : (tab_content[0].style.display = "none");
  646. }
  647. if (this.currentLab.index != index) {
  648. this.currentLab.index = index;
  649. tab_content[0].style.display = "block";
  650. }
  651. },
  652. mouseMove(event) {
  653. if (this.$refs.modeltooltip) {
  654. this.$refs.modeltooltip.style.left = event.pageX - 240 + "px";
  655. this.$refs.modeltooltip.style.top = event.pageY - 115 + "px";
  656. }
  657. },
  658. //显示鼠标经纬度
  659. getMouseLocation(event) {
  660. let {longitude,latitude} = this.getCoordinatesFromEvent(event);
  661. this.$store.commit("app/setMouseLocation",{longitude,latitude});
  662. },
  663. /*根据camera高度近似计算当前层级*/
  664. heightToZoom(height){
  665. var A = 40487.57;
  666. var B = 0.00007096758;
  667. var C = 91610.74;
  668. var D = -40467.74;
  669. return Math.round(D+(A-D)/(1+Math.pow(height/C, B)));
  670. },
  671. getCammeraHeightAndZoom(){
  672. let viewer = (this.dimension === 3 || this.dimension === 5) ? this.viewer3D : this.viewer2D;
  673. //获取当前相机高度
  674. let height = viewer.camera.positionCartographic.height;
  675. let zoom = this.heightToZoom(height);
  676. this.$store.commit("app/setCameraHeightAndZoom",{height,zoom});
  677. },
  678. selectModel(cursorStyle, image, info) {
  679. console.log('image :>> ', image);
  680. let earthMap = document.getElementById("earth");
  681. earthMap.style.cursor = cursorStyle || "auto";
  682. if (cursorStyle) {
  683. document.addEventListener("mousemove", this.mouseMove);
  684. this.isShow = true;
  685. this.image = image;
  686. this.modeltooltip = info;
  687. } else {
  688. document.removeEventListener("mousemove", this.mouseMove);
  689. this.isShow = false;
  690. this.image = null;
  691. this.modeltooltip = null;
  692. }
  693. },
  694. onMapClick(event) {
  695. if (this.isShow && this.modeltooltip === "左键单击确认") {
  696. const { latitude, longitude } = this.getCoordinatesFromEvent(event);
  697. this.markLocation(latitude, longitude);
  698. }
  699. },
  700. // 同时在2D和3D地图上标记坐标
  701. markLocation(latitude, longitude) {
  702. const position = this.Cesium.Cartesian3.fromDegrees(longitude, latitude);
  703. console.log('position :>> ', position);
  704. this.viewer2D.entities.add({
  705. id: this.id,
  706. position: position,
  707. // point: {
  708. // pixelSize: 12, // 调整点的大小,可以增大点的像素大小
  709. // color: this.Cesium.Color.fromCssColorString(this.image.color)
  710. // },
  711. model: {
  712. uri: satelliteModel, // 替换为你的3D模型文件路径
  713. scale: 1.0, // 调整3D模型的缩放大小
  714. minimumPixelSize: 64 // 设置3D模型的最小像素大小,确保在视图中可见
  715. },
  716. label: {
  717. text: this.image.name,
  718. show: true,
  719. font: "18px Helvetica", // 调整标签的字体样式和大小
  720. pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移,向下偏移20像素
  721. }
  722. });
  723. this.viewer3D.entities.add({
  724. id: this.id,
  725. position: position,
  726. // point: {
  727. // pixelSize: 12, // 调整点的大小,可以增大点的像素大小
  728. // color: this.Cesium.Color.fromCssColorString(this.image.color)
  729. // },
  730. model: {
  731. uri: satelliteModel, // 替换为你的3D模型文件路径
  732. scale: 1.0, // 调整3D模型的缩放大小
  733. minimumPixelSize: 64 // 设置3D模型的最小像素大小,确保在视图中可见
  734. },
  735. label: {
  736. text: this.image.name,
  737. show: true,
  738. font: "18px Helvetica", // 调整标签的字体样式和大小
  739. pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移,向下偏移20像素
  740. }
  741. });
  742. this.id++;
  743. },
  744. markLocationbyJson(latitude, longitude,height,name,type) {
  745. const position = this.Cesium.Cartesian3.fromDegrees(longitude, latitude,height);
  746. console.log('position :>> ', position);
  747. let color = ''
  748. let modelUrl = ''
  749. if(type=='red'){
  750. color = 'Red'
  751. modelUrl= missileModel
  752. }
  753. else if(type=='blue'){
  754. color = 'Blue'
  755. modelUrl = thaadModel
  756. }
  757. else if(type=='center'){
  758. color = 'Blue'
  759. modelUrl = centerModel
  760. }
  761. this.viewer2D.entities.add({
  762. id: this.id,
  763. position: position,
  764. point: {
  765. pixelSize: 12, // 调整点的大小,可以增大点的像素大小
  766. color: this.Cesium.Color.fromCssColorString(color)
  767. },
  768. // model: {
  769. // uri: modelUrl, // 替换为你的3D模型文件路径
  770. // scale: 1.0, // 调整3D模型的缩放大小
  771. // minimumPixelSize: 64 // 设置3D模型的最小像素大小,确保在视图中可见
  772. // },
  773. label: {
  774. text: type+' '+name,
  775. show: true,
  776. font: "18px Helvetica", // 调整标签的字体样式和大小
  777. pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移,向下偏移20像素
  778. }
  779. });
  780. this.viewer3D.entities.add({
  781. id: this.id,
  782. position: position,
  783. point: {
  784. pixelSize: 12, // 调整点的大小,可以增大点的像素大小
  785. color: this.Cesium.Color.fromCssColorString(color)
  786. },
  787. model: {
  788. uri: modelUrl, // 替换为你的3D模型文件路径
  789. scale: 1.0, // 调整3D模型的缩放大小
  790. minimumPixelSize: 64 // 设置3D模型的最小像素大小,确保在视图中可见
  791. },
  792. label: {
  793. text: type+' '+name,
  794. show: true,
  795. font: "18px Helvetica", // 调整标签的字体样式和大小
  796. pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移,向下偏移20像素
  797. }
  798. });
  799. this.nameIdList.push({
  800. id: this.id,
  801. name: name
  802. })
  803. this.id++;
  804. console.log('this.viewer3D.entities :>> ', this.viewer3D.entities);
  805. },
  806. // 从鼠标点击事件获取坐标
  807. getCoordinatesFromEvent(event) {
  808. let viewer = this.mousevalue === "2D" ? this.viewer2D : this.viewer3D;
  809. let clickPosition;
  810. if (this.dimension === 5 && this.mousevalue === "3D") {
  811. clickPosition = new this.Cesium.Cartesian2(event.clientX - 1080, event.clientY - 160);
  812. } else {
  813. clickPosition = new this.Cesium.Cartesian2(event.clientX - 280, event.clientY - 160);
  814. }
  815. // 获取地图上的经纬度
  816. const viewerPosition = viewer.scene.camera.pickEllipsoid(clickPosition);
  817. const cartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(viewerPosition);
  818. const latitude = this.Cesium.Math.toDegrees(cartographic.latitude);
  819. const longitude = this.Cesium.Math.toDegrees(cartographic.longitude);
  820. return {
  821. latitude,
  822. longitude
  823. };
  824. },
  825. markLine(point1, point2, color) {
  826. // 从点1和点2的WGS84坐标创建Cartesian3对象
  827. const position1 = this.Cesium.Cartesian3.fromDegrees(point1.longitude, point1.latitude, point1.height || 0);
  828. const position2 = this.Cesium.Cartesian3.fromDegrees(point2.longitude, point2.latitude, point2.height || 0);
  829. // 创建一个带有箭头图标的PolylineMaterial
  830. const material = new this.Cesium.PolylineArrowMaterialProperty(
  831. this.Cesium.Color.fromCssColorString(color || "red")
  832. );
  833. // 将点1和点2之间的连线添加到Viewer中
  834. this.viewer2D.entities.add({
  835. polyline: {
  836. positions: [position1, position2],
  837. width: 5, // 设置线的宽度
  838. material: material,
  839. followSurface: false // 设置为false,使连线保持在固定的高度,不会贴地显示
  840. }
  841. });
  842. this.viewer3D.entities.add({
  843. polyline: {
  844. positions: [position1, position2],
  845. width: 5, // 设置线的宽度
  846. material: material,
  847. followSurface: false // 设置为false,使连线保持在固定的高度,不会贴地显示
  848. }
  849. });
  850. },
  851. // 鼠标点击的事件监听
  852. pointMove() {
  853. // 监听鼠标左键点击事件
  854. this.handler2D.setInputAction((event) => {
  855. if (!this.selectedMarker && !this.modeltooltip) {
  856. const screenPosition = new this.Cesium.Cartesian2(event.position.x, event.position.y);
  857. const pickedEntity = this.viewer2D.scene.pick(screenPosition);
  858. if (this.Cesium.defined(pickedEntity)) {
  859. for (const entity of this.viewer2D.entities.values) {
  860. if (pickedEntity.id.id === entity.id) {
  861. this.selectedMarker = entity;
  862. this.oldPosition = pickedEntity.id.position;
  863. // 显示提示
  864. this.selectModel("pointer", null, "右键取消");
  865. }
  866. }
  867. }
  868. } else if (this.selectedMarker && this.modeltooltip === "右键取消") {
  869. // const material = new this.Cesium.PolylineArrowMaterialProperty(this.selectedMarker.point.color);
  870. console.log('this.viewer2D.entities.values :>> ', this.viewer2D.entities.getById(this.selectedMarker.id).position._value);
  871. let position = this.convertWorldToCartographic(this.viewer2D.entities.getById(this.selectedMarker.id).position._value)
  872. let name = ''
  873. for(let i = 0;i<this.nameIdList.length;i++){
  874. if(this.nameIdList[i].id == this.selectedMarker.id){
  875. name = this.nameIdList[i].name
  876. }
  877. }
  878. for(let i = 0;i<this.jsonData.blueunit.length;i++){
  879. if(name == this.jsonData.blueunit[i].name){
  880. this.jsonData.blueunit[i].pos.lat = position.latitude.toFixed(6)
  881. this.jsonData.blueunit[i].pos.lon = position.longitude.toFixed(6)
  882. this.jsonData.blueunit[i].pos.h = position.height.toFixed(2)
  883. }
  884. }
  885. for(let i = 0;i<this.jsonData.redunit.length;i++){
  886. if(name == this.jsonData.redunit.name){
  887. this.jsonData.redunit.component_movementjson.properties.launch_lon = position.longitude.toFixed(6)
  888. this.jsonData.redunit.component_movementjson.properties.launch_lat = position.latitude.toFixed(6)
  889. this.jsonData.redunit.component_movementjson.properties.launch_h = position.height.toFixed(2)
  890. }
  891. }
  892. for(let i = 0;i<this.jsonData.center.length;i++){
  893. if(name == this.jsonData.center[i].name){
  894. this.jsonData.center[i][name].properties.lon = position.longitude.toFixed(6)
  895. this.jsonData.center[i][name].properties.lat = position.latitude.toFixed(6)
  896. this.jsonData.center[i][name].properties.h = position.height.toFixed(2)
  897. for(let j = 0;j<this.jsonData.redunit.length;j++){
  898. this.jsonData.redunit[j].component_movementjson.properties.target_lon = position.longitude.toFixed(6)
  899. this.jsonData.redunit[j].component_movementjson.properties.target_lat = position.latitude.toFixed(6)
  900. this.jsonData.redunit[j].component_movementjson.properties.target_h = position.height.toFixed(2)
  901. }
  902. // 新的终点坐标
  903. const newEndPoint = this.Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude, position.height);
  904. // 遍历所有的entity对象
  905. this.viewer2D.entities.values.forEach(entity => {
  906. // 检查entity是否为Polyline类型
  907. if (entity instanceof this.Cesium.Entity && entity.polyline) {
  908. // 获取原始的Polyline坐标数组
  909. const positions = entity.polyline.positions.getValue(); // 得到一个Cartesian3数组
  910. // 修改终点坐标为新的坐标
  911. positions[positions.length - 1] = newEndPoint;
  912. // 更新entity的Polyline坐标
  913. entity.polyline.positions = new this.Cesium.CallbackProperty(time => positions, false);
  914. }
  915. });
  916. this.viewer3D.entities.values.forEach(entity => {
  917. // 检查entity是否为Polyline类型
  918. if (entity instanceof this.Cesium.Entity && entity.polyline) {
  919. // 获取原始的Polyline坐标数组
  920. const positions = entity.polyline.positions.getValue(); // 得到一个Cartesian3数组
  921. // 修改终点坐标为新的坐标
  922. positions[positions.length - 1] = newEndPoint;
  923. // 更新entity的Polyline坐标
  924. entity.polyline.positions = new this.Cesium.CallbackProperty(time => positions, false);
  925. }
  926. });
  927. }
  928. }
  929. // this.viewer2D.entities.add({
  930. // polyline: {
  931. // positions: [
  932. // this.oldPosition._value,
  933. // this.viewer2D.entities.getById(this.selectedMarker.id).position._value
  934. // ],
  935. // width: 5, // 设置线的宽度
  936. // material: material,
  937. // followSurface: false // 设置为false,使连线保持在固定的高度,不会贴地显示
  938. // }
  939. // });
  940. // this.viewer3D.entities.add({
  941. // polyline: {
  942. // positions: [
  943. // this.oldPosition._value,
  944. // this.viewer3D.entities.getById(this.selectedMarker.id).position._value
  945. // ],
  946. // width: 5, // 设置线的宽度
  947. // material: material,
  948. // followSurface: false // 设置为false,使连线保持在固定的高度,不会贴地显示
  949. // }
  950. // });
  951. console.log('this.jsonData :>> ', this.jsonData);
  952. this.selectedMarker = null;
  953. this.selectModel();
  954. }
  955. }, this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
  956. // 监听鼠标移动事件,用于移动标记点
  957. this.handler2D.setInputAction((event) => {
  958. if (this.selectedMarker && this.modeltooltip === "右键取消") {
  959. const screenPosition = new this.Cesium.Cartesian2(event.endPosition.x, event.endPosition.y);
  960. const position = this.viewer2D.scene.camera.pickEllipsoid(screenPosition);
  961. this.viewer2D.entities.getById(this.selectedMarker.id).position = position;
  962. this.viewer3D.entities.getById(this.selectedMarker.id).position = position;
  963. }
  964. }, this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  965. // 监听右键
  966. this.handler2D.setInputAction(() => {
  967. if (this.selectedMarker && this.modeltooltip === "右键取消") {
  968. this.viewer2D.entities.getById(this.selectedMarker.id).position = this.oldPosition;
  969. this.selectedMarker = null;
  970. this.selectModel();
  971. }
  972. }, this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  973. this.handler3D.setInputAction((event) => {
  974. if (!this.selectedMarker && !this.modeltooltip) {
  975. const screenPosition = new this.Cesium.Cartesian2(event.position.x, event.position.y);
  976. const pickedEntity = this.viewer3D.scene.pick(screenPosition);
  977. if (this.Cesium.defined(pickedEntity)) {
  978. for (const entity of this.viewer3D.entities.values) {
  979. if (pickedEntity.id.id === entity.id) {
  980. this.selectedMarker = entity;
  981. this.oldPosition = pickedEntity.id.position;
  982. // 显示提示
  983. this.selectModel("pointer", null, "右键取消");
  984. }
  985. }
  986. }
  987. } else if (this.selectedMarker && this.modeltooltip === "右键取消") {
  988. const material = new this.Cesium.PolylineArrowMaterialProperty(this.selectedMarker.point.color);
  989. this.viewer2D.entities.add({
  990. polyline: {
  991. positions: [
  992. this.oldPosition._value,
  993. this.viewer2D.entities.getById(this.selectedMarker.id).position._value
  994. ],
  995. width: 5, // 设置线的宽度
  996. material: material,
  997. followSurface: false // 设置为false,使连线保持在固定的高度,不会贴地显示
  998. }
  999. });
  1000. this.viewer3D.entities.add({
  1001. polyline: {
  1002. positions: [
  1003. this.oldPosition._value,
  1004. this.viewer3D.entities.getById(this.selectedMarker.id).position._value
  1005. ],
  1006. width: 5, // 设置线的宽度
  1007. material: material,
  1008. followSurface: false // 设置为false,使连线保持在固定的高度,不会贴地显示
  1009. }
  1010. });
  1011. this.selectedMarker = null;
  1012. this.selectModel();
  1013. }
  1014. }, this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
  1015. // 监听鼠标移动事件,用于移动标记点
  1016. this.handler3D.setInputAction((event) => {
  1017. if (this.selectedMarker && this.modeltooltip === "右键取消") {
  1018. const screenPosition = new this.Cesium.Cartesian2(event.endPosition.x, event.endPosition.y);
  1019. const position = this.viewer3D.scene.camera.pickEllipsoid(screenPosition);
  1020. this.viewer2D.entities.getById(this.selectedMarker.id).position = position;
  1021. this.viewer3D.entities.getById(this.selectedMarker.id).position = position;
  1022. }
  1023. }, this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  1024. // 监听右键
  1025. this.handler3D.setInputAction(() => {
  1026. if (this.selectedMarker && this.modeltooltip === "右键取消") {
  1027. this.viewer3D.entities.getById(this.selectedMarker.id).position = this.oldPosition;
  1028. this.selectedMarker = null;
  1029. this.selectModel();
  1030. }
  1031. }, this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  1032. }
  1033. }
  1034. };
  1035. </script>
  1036. <style scoped>
  1037. ::v-deep .cesium-infoBox {
  1038. display: none !important;
  1039. }
  1040. ::v-deep .cesium-infoBox-bodyless {
  1041. display: none !important;
  1042. }
  1043. ::v-deep .cesium-infoBox-visible {
  1044. display: none !important;
  1045. }
  1046. .container{
  1047. height: 100%;
  1048. }
  1049. .modeltooltip {
  1050. position: absolute;
  1051. padding: 5px;
  1052. color: #fff;
  1053. font-size: 20px;
  1054. pointer-events: none;
  1055. z-index: 999;
  1056. }
  1057. .myHeader {
  1058. background-color: #1c222b !important;
  1059. color: #fff;
  1060. height: 100%;
  1061. display: flex;
  1062. flex-direction: row;
  1063. align-items: center;
  1064. /*由于flex-direction: column,因此align-items代表的是水平方向*/
  1065. justify-content: center;
  1066. /*由于flex-direction: column,因此justify-content代表的是垂直方向*/
  1067. }
  1068. .myHeader .el-button {
  1069. width: 100px;
  1070. height: 20px;
  1071. padding: 1px 23px;
  1072. }
  1073. .box-card {
  1074. min-height: 100%;
  1075. height: 100%;
  1076. }
  1077. ::v-deep .el-card__body {
  1078. height: 100% !important;
  1079. padding: 0px !important;
  1080. }
  1081. .main-layout {
  1082. height: 100%;
  1083. width: 100%;
  1084. }
  1085. .map {
  1086. width: 100%;
  1087. height: 100%;
  1088. }
  1089. .menu {
  1090. position: absolute;
  1091. height: 400px;
  1092. z-index: 999;
  1093. left: 20px;
  1094. top: 20px;
  1095. }
  1096. ::v-deep .el-tabs--left .el-tabs__header.is-left {
  1097. margin-right: 0px !important;
  1098. }
  1099. .buttons {
  1100. display: flex;
  1101. flex-direction: column;
  1102. align-items: center;
  1103. justify-items: center;
  1104. position: absolute;
  1105. z-index: 999;
  1106. right: 20px;
  1107. top: 20px;
  1108. }
  1109. .el-button {
  1110. margin: 5px !important;
  1111. }
  1112. ::v-deep .el-tabs--border-card>.el-tabs__content {
  1113. width: 300px;
  1114. display: none;
  1115. }
  1116. .model {
  1117. display: flex;
  1118. width: 100%;
  1119. flex-wrap: wrap;
  1120. }
  1121. .model>div {
  1122. width: 50%;
  1123. height: 120px;
  1124. padding: 5px;
  1125. }
  1126. .model>div:hover {
  1127. border: 2px solid blue;
  1128. }
  1129. .model>div:active {
  1130. border: 2px solid red;
  1131. }
  1132. .active {
  1133. border: 2px solid red !important;
  1134. }
  1135. .model .el-image {
  1136. display: block !important;
  1137. }
  1138. ::v-deep .el-image .el-image__inner {
  1139. border: 1px solid #ddd;
  1140. border-radius: 5px;
  1141. }
  1142. .item {
  1143. font-size: 14px;
  1144. /* right: 20px; */
  1145. }
  1146. </style>