index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. <template>
  2. <div ref="containerRef" class="map-container">
  3. <div ref="mapRef" id="YztMap" class="map-container2" />
  4. </div>
  5. </template>
  6. <script setup lang="ts">
  7. import 'ol/ol.css';
  8. import mmJson from '@/assets/json/mm2.json';
  9. import { olMap } from '@/utils/olMap/olMap';
  10. import {getPointInfoList} from '@/api/globalMap';
  11. import { getDictLabel } from '@/utils/dict';
  12. import { methodList, titleList } from '../data';
  13. import { pointDetailTemplate } from '@/components/Map/mapData';
  14. import useMapStore from '@/store/modules/map';
  15. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  16. const { point_type } = toRefs<any>(proxy?.useDict('point_type'));
  17. const mapStore = useMapStore();
  18. const emits = defineEmits(['handleShowWarehouse', 'handleShowVideo', 'handleShowPeople', 'closeDetailDialog', 'resize']);
  19. const mapRef = ref(null);
  20. const containerRef = ref();
  21. let map, mapUtils;
  22. const mapList = reactive({
  23. satellite2: [
  24. { layer: 'map', layerType: 'WMTS', code: 'YZT1708679726700', zIndex: '-100', visible: true },
  25. { layer: 'map', layerType: 'WFS', code: 'YZT1712111943104', zIndex: '-99', visible: true },
  26. { layer: 'annotation', layerType: 'WMTS', code: 'YZT1695608158269', zIndex: '-98', visible: true }
  27. ],
  28. satellite3: [
  29. { layer: 'map', layerType: 'WMTS', code: 'YZT1708679726700', zIndex: '-99', visible: true },
  30. { layer: 'annotation', layerType: 'WMTS', code: 'YZT1695608158269', zIndex: '-98', visible: true }
  31. ],
  32. imageMap: [
  33. { layer: 'map', layerType: 'WMTS', code: 'YZT1640925052482', zIndex: '-99' },
  34. { layer: 'annotation', layerType: 'WMTS', code: 'YZT1695608158269', zIndex: '-98', visible: true }
  35. ],
  36. imageMap2: [
  37. { layer: 'map', layerType: 'JSON', code: 'gd', zIndex: '-99', visible: true },
  38. { layer: 'annotation', layerType: 'WMTS', code: 'YZT1695608158269', zIndex: '-98', visible: true }
  39. ]
  40. });
  41. // 监听地图类型变化
  42. watch(
  43. () => mapStore.activeMap,
  44. () => {
  45. if (!mapUtils) return;
  46. mapUtils.replaceLayers(mapList[mapStore.activeMap]);
  47. }
  48. );
  49. watch(
  50. () => mapStore.showMask,
  51. () => {
  52. if (mapStore.showMask) {
  53. mapUtils.createVecByJson2(mmJson, { strokeWeight: 2 });
  54. } else {
  55. mapUtils.removeMask3(true);
  56. }
  57. }
  58. );
  59. const init = () => {
  60. mapStore.setMapLoaded(false);
  61. mapUtils = new olMap({
  62. dom: mapRef.value,
  63. id: mapList[mapStore.activeMap],
  64. center: mapStore.mapState.center,
  65. zoom: mapStore.mapState.zoom,
  66. minZoom: mapStore.mapState.minZoom,
  67. maxZoom: mapStore.mapState.maxZoom,
  68. showScale: true,
  69. drawTool: {
  70. use: true
  71. },
  72. // 加载完成事件
  73. onLoadCompleted: (YztMap) => {
  74. map = YztMap;
  75. mapStore.setMapLoaded(true);
  76. map.getView().on('change:resolution', () => {
  77. mapStore.setZoom(map.getView().getZoom().toFixed(2));
  78. });
  79. if (mapStore.showMask) {
  80. mapUtils.createVecByJson2(mmJson, { strokeWeight: 2 });
  81. }
  82. // let drawTool = new DrawTool({ mapUtils, map });
  83. handleResize();
  84. },
  85. onMarkerClick: (data) => {
  86. // 多点位
  87. if (data.type === '1') {
  88. let path = [];
  89. mapStore.pointType.forEach((item) => {
  90. path.push(item.component);
  91. });
  92. getPointInfoList({
  93. option: path.toString(),
  94. longitude: data.longitude.toString(),
  95. latitude: data.latitude.toString()
  96. }).then((res) => {
  97. const data2 = res.data.list;
  98. let content = document.createElement('div');
  99. // content.style.cssText = 'transform: scale(' + containerScale().scaleX + ');';
  100. content.className = 'point-info';
  101. let content2 = '';
  102. content2 += '<div class="title-box"><div class="gradient-text">多点位信息</div></div>';
  103. content2 += '<div class="icon1"></div>';
  104. content2 += '<div class="icon2"></div>';
  105. content2 += '<div class="icon3"></div>';
  106. content2 += '<div class="icon4"></div>';
  107. content.innerHTML = content2;
  108. let tableBox = document.createElement('div');
  109. tableBox.className = 'table-box';
  110. let table = document.createElement('div');
  111. table.className = 'table';
  112. table.innerHTML = '<div class="point-item"><div class="td3">主题</div><div class="td3">名称</div></div>';
  113. data2.forEach((item) => {
  114. item.longitude = data.longitude;
  115. item.latitude = data.latitude;
  116. const div = document.createElement('div');
  117. div.className = 'point-item point-item-hover';
  118. div.innerHTML =
  119. '<div class="td4">' + getDictLabel(point_type.value, item.dataType.toString()) + '</div><div class="td4">' + item.name + '</div>';
  120. div.addEventListener('click', () => {
  121. handlePointDetails(item);
  122. });
  123. table.appendChild(div);
  124. });
  125. tableBox.appendChild(table);
  126. content.appendChild(tableBox);
  127. let closeBtn = document.createElement('div');
  128. closeBtn.className = 'close';
  129. closeBtn.onclick = () => mapUtils.hideInfo(true);
  130. content.appendChild(closeBtn);
  131. mapUtils.showInfo(content, [data.longitude, data.latitude], true);
  132. });
  133. } else {
  134. handlePointDetails(data);
  135. }
  136. }
  137. });
  138. };
  139. const handlePointDetails = (data) => {
  140. let method = methodList[data.dataType];
  141. let title = !!titleList[data.dataType] ? titleList[data.dataType] : '信息';
  142. if (!method) return;
  143. method(data.id).then((res) => {
  144. if (!!pointDetailTemplate[data.dataType]) {
  145. let div = document.createElement('div');
  146. div.className = 'point-info';
  147. let titleDom = document.createElement('div');
  148. titleDom.className = 'title-box';
  149. titleDom.innerHTML = '<div class="gradient-text">' + title + '</div></div>';
  150. div.appendChild(titleDom);
  151. const objs = {
  152. '2': {
  153. title: '物资详情',
  154. method: 'handleShowWarehouse'
  155. },
  156. '41': {
  157. title: '人员列表',
  158. method: 'handleShowPeople'
  159. },
  160. '43': {
  161. title: '历史轨迹',
  162. method: 'handleShowTrack'
  163. }
  164. };
  165. let obj = objs[data.dataType];
  166. if ([4, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58].includes(data.dataType)) {
  167. obj = {
  168. title: '附近视频',
  169. method: 'handleShowVideo'
  170. };
  171. }
  172. if (!!obj) {
  173. let btnBox = document.createElement('div');
  174. let btn = document.createElement('div');
  175. btnBox.className = 'flex';
  176. btn.className = 'btn';
  177. btn.innerHTML = '<div class="video-icon"></div>' + obj.title + '<div></div>';
  178. btn.onclick = () => {
  179. emits(obj.method, data);
  180. };
  181. btnBox.appendChild(btn);
  182. div.appendChild(btnBox);
  183. }
  184. let icon1 = document.createElement('div');
  185. icon1.className = 'icon1';
  186. let icon2 = document.createElement('div');
  187. icon2.className = 'icon2';
  188. let icon3 = document.createElement('div');
  189. icon3.className = 'icon3';
  190. let icon4 = document.createElement('div');
  191. icon4.className = 'icon4';
  192. div.appendChild(icon1);
  193. div.appendChild(icon2);
  194. div.appendChild(icon3);
  195. div.appendChild(icon4);
  196. let table = document.createElement('div');
  197. table.className = 'table-box';
  198. let content = '';
  199. content += '<div class="table">';
  200. const newData = filterTd(res.rows[0], data.dataType);
  201. newData.forEach((item) => {
  202. if (item.type === 'shortText') {
  203. content += '<div class="tr">';
  204. item.data.forEach((item2) => {
  205. content += '<div class="point-item">';
  206. content += '<div class="td1">' + item2.label + '</div><div class="td2">' + item2.value + '</div>';
  207. content += '</div>';
  208. });
  209. content += '</div>';
  210. } else {
  211. content += '<div class="point-item2">';
  212. content += '<div class="td1">' + item.data[0].label + '</div><div class="td2">' + item.data[0].value + '</div>';
  213. content += '</div>';
  214. }
  215. });
  216. content += '</div>';
  217. table.innerHTML = content;
  218. div.appendChild(table);
  219. let closeBtn = document.createElement('div');
  220. closeBtn.className = 'close';
  221. closeBtn.onclick = () => {
  222. mapUtils.hideInfo(true);
  223. emits('closeDetailDialog', data);
  224. };
  225. div.appendChild(closeBtn);
  226. mapUtils.showInfo(div, [data.longitude, data.latitude], -data.scale * data.size[1], true);
  227. } else if (data.dataType === 'video') {
  228. emits('handleShowVideoDetail', res.data, true);
  229. }
  230. });
  231. };
  232. const filterTd = (obj, dataType) => {
  233. let data = [];
  234. let tempData = {};
  235. let i = 0;
  236. const pointDetailTemplateObj = pointDetailTemplate[dataType];
  237. Object.keys(pointDetailTemplateObj).forEach((key) => {
  238. let keyLabel = pointDetailTemplateObj[key];
  239. if (!!keyLabel) {
  240. if (i === 2) {
  241. i = 0;
  242. }
  243. const value = !!obj && !!obj[key] ? obj[key] : '';
  244. if (value && value.length > 8) {
  245. if (i === 0) {
  246. data.push({ type: 'longText', data: [{ label: keyLabel, value: value }] });
  247. i = 0;
  248. } else {
  249. tempData = { type: 'longText', data: [{ label: keyLabel, value: value }] };
  250. }
  251. } else {
  252. if (i === 0) {
  253. data.push({ type: 'shortText', data: [{ label: keyLabel, value: value }] });
  254. } else {
  255. data[data.length - 1].data.push({ label: keyLabel, value: value });
  256. }
  257. i++;
  258. if (!!tempData && JSON.stringify(tempData) !== '{}') {
  259. data.push(tempData);
  260. tempData = {};
  261. i = 0;
  262. }
  263. }
  264. }
  265. });
  266. if (!!tempData && JSON.stringify(tempData) !== '{}') {
  267. data.push(tempData);
  268. }
  269. if (data[data.length - 1].data && data[data.length - 1].data.length === 1 && data[data.length - 1].type === 'shortText') {
  270. data[data.length - 1].type = 'longText';
  271. }
  272. return data;
  273. };
  274. const addMarker = (points) => {
  275. mapUtils.addMarker(points);
  276. };
  277. const clearMarker = () => {
  278. mapUtils.clearMarker();
  279. };
  280. let inverseScale = ref({
  281. inverseScaleX: 1,
  282. inverseScaleY: 1
  283. });
  284. const handleResize = () => {
  285. if (!containerRef.value) return;
  286. map.updateSize();
  287. nextTick(() => {
  288. emits('resize');
  289. });
  290. };
  291. const getMap = () => {
  292. return map;
  293. };
  294. const getMapUtils = () => {
  295. return mapUtils;
  296. };
  297. const getDrawTool = () => {
  298. return mapUtils.getDrawTool();
  299. };
  300. const addSearchMarker = (item) => {
  301. return mapUtils.addSearchMarker(item);
  302. };
  303. // 加载事件
  304. onMounted(() => {
  305. init();
  306. window.addEventListener('resize', handleResize);
  307. });
  308. // 卸载事件
  309. onUnmounted(() => {
  310. window.removeEventListener('resize', handleResize);
  311. });
  312. defineExpose({ getMap, getMapUtils, addSearchMarker, getDrawTool, addMarker, clearMarker });
  313. </script>
  314. <style scoped>
  315. @import '../map.scss';
  316. .map-container2 {
  317. width: 100%;
  318. height: 100%;
  319. position: relative;
  320. overflow: hidden;
  321. }
  322. .map-container {
  323. width: 100%;
  324. height: 100%;
  325. position: relative;
  326. :deep(.ol-scale-line) {
  327. left: unset;
  328. bottom: 16px;
  329. right: 48px;
  330. background-color: transparent;
  331. }
  332. :deep(.ol-scale-line-inner) {
  333. color: #ffffff;
  334. border: 1px solid #fff;
  335. border-top: none;
  336. }
  337. }
  338. </style>