index.tsx 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. import {
  2. defineComponent,
  3. reactive,
  4. PropType,
  5. onMounted,
  6. watchEffect,
  7. watch,
  8. computed,
  9. } from 'vue';
  10. import { useRoute, useRouter } from 'vue-router';
  11. import isString from 'lodash/isString';
  12. import useMarkerStore, { MarkerType } from '@/store/useMarkerStore';
  13. import MapView from '../MapView';
  14. import { useDaHuaStore } from '@/store';
  15. /** @ts-ignore */
  16. import icon_map_yjcl from '@/assets/icons/home/yjcl.svg';
  17. /** @ts-ignore */
  18. import icon_map_yjsj from '@/assets/icons/home/yjsj.svg';
  19. /** @ts-ignore */
  20. import icon_map_yjdw from '@/assets/icons/home/yjdw.svg';
  21. /** @ts-ignore */
  22. import icon_map_yjdw_w from '@/assets/icons/home/icon_map_yjdw_w.svg';
  23. /** @ts-ignore */
  24. import icon_map_yjck from '@/assets/icons/home/yjck.svg';
  25. /** @ts-ignore */
  26. import icon_map_yjck_w from '@/assets/icons/home/icon_map_yjck_w.svg';
  27. /** @ts-ignore */
  28. import icon_map_spjk from '@/assets/icons/home/spjk.svg';
  29. /** @ts-ignore */
  30. import icon_map_dcz from '@/assets/icons/home/icon_map_dcz.svg';
  31. /** @ts-ignore */
  32. import icon_map_dpf from '@/assets/icons/home/dpf.svg';
  33. /** @ts-ignore */
  34. import icon_map_dbsb from '@/assets/icons/home/dbsb.svg';
  35. import './index.scss';
  36. import {
  37. GET_INCIDENT_DIALOG_HTML,
  38. GET_TEAM_DIALOG_HTML,
  39. GET_VEHICLES_DIALOG_HTML,
  40. GET_VIDEO_DIALOG_HTML,
  41. GET_WAREHOUSE_DIALOG_HTML,
  42. GET_SINGLE_DEVICE_DIALOG_HTML,
  43. renderElement,
  44. } from './dialog';
  45. import { IncidentItemDetail } from '@/api/incident';
  46. import { useIncidentStore } from '@/store';
  47. import Popup from '../Popup';
  48. import { ElMessage } from 'element-plus';
  49. import { isEmpty } from 'lodash';
  50. import clsx from 'clsx';
  51. import { SingleDeviceItem } from '@/api/resource';
  52. const MARKER_MAP_TYPES = [
  53. // '待派发事件',
  54. // '待处置事件',
  55. '路况信息',
  56. '视频监控',
  57. '应急车辆',
  58. '应急队伍',
  59. '应急仓库',
  60. '应急事件',
  61. '单兵',
  62. ] as const;
  63. export type MarkerMapType = typeof MARKER_MAP_TYPES[number];
  64. interface State {
  65. map: any;
  66. types: MarkerMapType[];
  67. trafficLayerIds: any[];
  68. timer?: NodeJS.Timer | null;
  69. trafficStatus: boolean;
  70. markers: MarkerType[];
  71. positions: string[];
  72. hasTypes: string[];
  73. // theSocket: null;
  74. }
  75. interface ActionType {
  76. type: MarkerMapType;
  77. hasActioned: boolean;
  78. action: Function;
  79. remove: Function;
  80. }
  81. // locationType + resourceType
  82. const RESOURCE_ICON_MAP = {
  83. '11': icon_map_yjck_w, // 水上 仓库
  84. '21': icon_map_yjck, // 陆上 仓库
  85. '12': icon_map_yjdw_w, // 水上 队伍
  86. '22': icon_map_yjdw, // 陆上 队伍
  87. '13': icon_map_yjcl, // 水上 车辆
  88. '23': icon_map_yjcl, // 陆上 车辆
  89. };
  90. const getResourceIcon = (locationType: string, resourceType: string) => {
  91. // @ts-ignore
  92. return RESOURCE_ICON_MAP[locationType + resourceType] || '';
  93. };
  94. // 路况信息刷新间隔
  95. const REFRESH_TRAFFIC_TIME = 60000;
  96. // let theSocket = null;
  97. // let vPlayArea =null;
  98. const getIncidentImage = (status: MarkerType['status']) =>
  99. status?.toString() === '1'
  100. ? icon_map_yjsj
  101. : status?.toString() === '2'
  102. ? icon_map_dpf
  103. : status?.toString() === '3'
  104. ? icon_map_dcz
  105. : icon_map_yjsj;
  106. export default defineComponent({
  107. name: 'MarkerMap',
  108. props: {
  109. adrsMapTypes: {
  110. type: Array as PropType<string[]>,
  111. default: MARKER_MAP_TYPES,
  112. },
  113. marker: Object as PropType<IncidentItemDetail | undefined | null>,
  114. readonly: Boolean,
  115. },
  116. setup(props, ctx) {
  117. const state = reactive<State>({
  118. map: null,
  119. types: [],
  120. trafficLayerIds: [],
  121. timer: undefined,
  122. trafficStatus: false,
  123. markers: [],
  124. positions: [],
  125. hasTypes: [],
  126. // theSocket:null
  127. });
  128. const store = useMarkerStore();
  129. const incidentStore = useIncidentStore();
  130. const daHuaStore = useDaHuaStore();
  131. const router = useRouter();
  132. const route = useRoute();
  133. // const theSocket = null;
  134. const adrsMapTypes = computed(() =>
  135. props.adrsMapTypes.map((i) => ({
  136. name: i,
  137. disabled: route.query.id && i === '应急事件',
  138. })),
  139. );
  140. const actionTypes = computed<ActionType[]>(() => [
  141. {
  142. type: '路况信息',
  143. hasActioned: state.trafficStatus,
  144. action: toggleControlTraffic,
  145. remove: toggleControlTraffic,
  146. },
  147. {
  148. type: '应急事件',
  149. hasActioned: state.hasTypes.includes('应急事件'),
  150. action: () =>
  151. handleAddMarkers('应急事件', store.incident, icon_map_dpf),
  152. remove: () => handleRemoveMarkers('应急事件', store.incident),
  153. },
  154. {
  155. type: '视频监控',
  156. hasActioned: state.hasTypes.includes('视频监控'),
  157. action: () =>
  158. // console.log(store.videoSurveillance);
  159. handleAddMarkers('视频监控', store.videoSurveillance, icon_map_spjk),
  160. remove: () => handleRemoveMarkers('视频监控', store.videoSurveillance),
  161. },
  162. {
  163. type: '应急车辆',
  164. hasActioned: state.hasTypes.includes('应急车辆'),
  165. action: () =>
  166. handleAddMarkers('应急车辆', store.emergencyVehicles, icon_map_yjcl),
  167. remove: () => handleRemoveMarkers('应急车辆', store.emergencyVehicles),
  168. },
  169. {
  170. type: '应急队伍',
  171. hasActioned: state.hasTypes.includes('应急队伍'),
  172. action: () =>
  173. handleAddMarkers('应急队伍', store.emergencyTeam, icon_map_yjdw),
  174. remove: () => handleRemoveMarkers('应急队伍', store.emergencyTeam),
  175. },
  176. {
  177. type: '应急仓库',
  178. hasActioned: state.hasTypes.includes('应急仓库'),
  179. action: () =>
  180. handleAddMarkers('应急仓库', store.emergencyWarehouse, icon_map_yjck),
  181. remove: () => handleRemoveMarkers('应急仓库', store.emergencyWarehouse),
  182. },
  183. {
  184. type: '单兵',
  185. hasActioned: state.hasTypes.includes('单兵'),
  186. action: () =>
  187. handleAddMarkers('单兵', store.singleDevice, icon_map_dbsb),
  188. remove: () => handleRemoveMarkers('单兵', store.singleDevice),
  189. },
  190. ]);
  191. const getMarkerPopupHTML = (type: MarkerMapType, marker: MarkerType) => {
  192. switch (type) {
  193. case '应急事件':
  194. // case '待派发事件':
  195. // case '预警事件':
  196. default:
  197. return GET_INCIDENT_DIALOG_HTML(marker, async () => {
  198. marker.id && (await incidentStore.getIncidentItem(marker.id));
  199. await router.push(`/incidentDetail?id=${marker?.id}`);
  200. handleSetDetailMarker(marker);
  201. store.currentIncident = marker;
  202. });
  203. case '单兵': {
  204. var callback = () => {
  205. console.log(marker['deviceCode']);
  206. console.log(marker['userId']);
  207. // daHuaStore.DAHUAUserObj(marker["userId"]).then(deviceUser=>{
  208. // console.log(deviceUser);
  209. // let memberObj = {
  210. // userName:deviceUser.userName,
  211. // userId:deviceUser.userCode,
  212. // region:deviceUser.paasId,
  213. // type:'single',
  214. // // speak:'true',
  215. // number:deviceUser.userPhone,
  216. // deviceId:marker["deviceCode"],
  217. // channelId:marker["channelId"],
  218. // }
  219. // let meetObj = JSON.parse(localStorage.getItem('meeting'));
  220. // let memberList = [];
  221. // memberList.push(meetObj.member==null||meetObj.member==undefined?"":meetObj.member[0]);
  222. // memberList.push(memberObj);
  223. // meetObj.member = memberList
  224. // console.log(meetObj);
  225. // daHuaStore.DAHUAMeetingMember(meetObj).then(data=>{
  226. // // console.log(11111111)
  227. // daHuaStore.DAHUAMeetingUser(meetObj.meetId);
  228. // daHuaStore.DAHUAUserInfo().then(u => {
  229. // console.log(u,'+++++++');
  230. // initSocket(u.userCode,memberObj);
  231. // })
  232. // })
  233. // console.log(memberObj);
  234. // meetObj.mebmber.push(memberObj);
  235. const DAHUA = document.getElementById('DAHUA') as HTMLIFrameElement;
  236. DAHUA?.contentWindow?.postMessage(
  237. {
  238. key: 'danbing',
  239. value: marker['userId'],
  240. deviceId: marker['deviceCode'],
  241. channelId: marker['channelId'],
  242. },
  243. '*',
  244. );
  245. daHuaStore.dahuaUserVisible = true;
  246. // console.log(daHuaStore.deviceUser);
  247. };
  248. return GET_SINGLE_DEVICE_DIALOG_HTML(
  249. marker as SingleDeviceItem,
  250. callback,
  251. );
  252. }
  253. case '应急仓库':
  254. return GET_WAREHOUSE_DIALOG_HTML(marker);
  255. case '应急车辆':
  256. return GET_VEHICLES_DIALOG_HTML(marker);
  257. case '应急队伍':
  258. return GET_TEAM_DIALOG_HTML(marker);
  259. case '视频监控':
  260. return GET_VIDEO_DIALOG_HTML(marker, () => {
  261. if(marker['status'] == 1){
  262. const DAHUA = document.getElementById('DAHUA') as HTMLIFrameElement;
  263. DAHUA?.contentWindow?.postMessage(
  264. {
  265. key: 'video',
  266. value: marker['userId'],
  267. deviceId: marker['deviceCode'],
  268. channelId: marker['channelId'],
  269. },
  270. '*',
  271. );
  272. daHuaStore.dahuaUserVisible = true;
  273. }else{
  274. ElMessage.warning('设备离线,请联系大华相关人员');
  275. }
  276. });
  277. }
  278. };
  279. const videoplay = (item: { type: string; userId: any; channelId: any }) => {
  280. console.log('播放视频');
  281. console.log(item);
  282. if (!window.theSocket.websocket) {
  283. ElMessage.warning('请先打开视频插件');
  284. return;
  285. }
  286. if (item.type == 'client') {
  287. window.slectOptionmini(item.userId).then((arr: any) => {
  288. if (arr) {
  289. window.vPlayArea.openAppVideo(arr);
  290. }
  291. });
  292. } else if (item.type == 'single') {
  293. //播放单兵视频
  294. pullFlow(item.channelId);
  295. } else if (item.type == 'vehicle') {
  296. //播放车载视频
  297. pullFlow(item.channelId);
  298. } else if (item.type == 'uav_dev') {
  299. //播放无人机视频
  300. pullFlow(item.channelId);
  301. }
  302. };
  303. const pullFlow = (channelId: any) => {
  304. channelId &&
  305. window.vPlayArea &&
  306. window.vPlayArea.realTimeVideo([{ channelId }]);
  307. };
  308. const initSocket = (
  309. userCode: string,
  310. memberObj: {
  311. userName?: any;
  312. userId: any;
  313. region?: any;
  314. type: string;
  315. number?: any;
  316. deviceId?: any;
  317. channelId: any;
  318. },
  319. ) => {
  320. const self = this;
  321. console.log(userCode);
  322. localStorage.setItem('userId', userCode);
  323. //初始websocket实例,保存在window中方便调用。一个浏览器tab页面只能初始化一次。所有的控件窗口,通过该websocket实例去生成不同的窗口实例,不同的控件窗口通过自己的窗口实例去调用初始化、关闭、隐藏等
  324. window.theSocket = new window.InitWebSocketClass(
  325. userCode,
  326. localStorage.getItem('DAHUA_token'),
  327. {
  328. //客户端登陆成功通知;
  329. loginSuccess: (v: any) => {
  330. console.log(2222222222222222);
  331. console.log('loginSuccess-->', v);
  332. initWnd();
  333. },
  334. //客户端窗口被拉起通知
  335. onCreateVideoSuccess: (v: any) => {
  336. console.log('客户端onCreateVideoSuccess-----', v);
  337. },
  338. //重点:统一分发客户端ws消息;vue 可以统一用$bus分发.第三方消息分发自定
  339. onSocketBackInfos: (data: {
  340. method: string;
  341. params: { result: number; handleName: string };
  342. }) => {
  343. //视频窗口创建成功通知
  344. if (
  345. data &&
  346. data.method === 'createVideoDialogReuslt' &&
  347. data.params.result === 0
  348. ) {
  349. if (data.params.handleName === '#vPlayArea') {
  350. //客户端窗口创建好后,界面显示窗口;
  351. window.vPlayArea.resize();
  352. ElMessage.warning('视频窗口创建成功!');
  353. videoplay(memberObj);
  354. }
  355. }
  356. },
  357. },
  358. );
  359. // console.log(theSocket);
  360. //socket实例初始化websocket回调方法;
  361. window.theSocket
  362. .initWebSocket()
  363. .then((v: any) => {
  364. if (v) {
  365. ElMessage.warning('视频插件登陆完成!');
  366. }
  367. })
  368. .catch(() => {
  369. ElMessage.warning('若要观看实时视频,请先安装视频插件');
  370. });
  371. };
  372. const initWnd = () => {
  373. console.log(1111);
  374. //左边窗口类型参数 分割 2行2列
  375. const typeObj = {
  376. rows: 2,
  377. cols: 2,
  378. wndSpaceing: 10,
  379. embedVideoMode: true,
  380. playerCtrlBarEnable: false,
  381. displayMode: 0,
  382. playMode: 0,
  383. playParams: {},
  384. };
  385. //左边窗口实例
  386. window.vPlayArea = new window.VideoPlay(
  387. '#vPlayArea',
  388. window.theSocket.websocket, //一个浏览器tab页面公用一个
  389. window.theSocket.socketCode, //一个浏览器tab页面公用一个
  390. typeObj,
  391. );
  392. //左边窗口初始化
  393. window.vPlayArea.init();
  394. };
  395. const updateTrafficSource = () => {
  396. if (state.map.getSource('Traffic')) {
  397. state.map.removeSource('Traffic');
  398. }
  399. state.map.addSource('Traffic', {
  400. type: 'vector',
  401. traffic: true,
  402. tiles: [
  403. 'mineserver://data/dynamic-traffic/ertic?servicetype=0&z={z}&x={x}&y={y}',
  404. ],
  405. });
  406. };
  407. const updateTrafficLayerVisibility = (v: 'none' | 'visible') => {
  408. state.trafficLayerIds.forEach(function (id) {
  409. if (state.map?.getLayer(id)) {
  410. state.map?.setLayoutProperty(id, 'visibility', v);
  411. }
  412. });
  413. };
  414. const toggleControlTraffic = () => {
  415. if (state.trafficStatus) {
  416. state.trafficStatus = false;
  417. if (state.timer) {
  418. clearInterval(state.timer);
  419. state.timer = null;
  420. }
  421. updateTrafficLayerVisibility('none');
  422. } else {
  423. state.trafficStatus = true;
  424. if (state.timer) {
  425. clearInterval(state.timer);
  426. state.timer = null;
  427. }
  428. updateTrafficSource();
  429. state.timer = setInterval(function () {
  430. updateTrafficSource();
  431. }, REFRESH_TRAFFIC_TIME);
  432. updateTrafficLayerVisibility('visible');
  433. }
  434. };
  435. const handleAddMarkers = (
  436. type: MarkerMapType,
  437. markers: State['markers'],
  438. image: any,
  439. ) => {
  440. console.log(state.markers);
  441. state.markers.push(
  442. ...markers.map((i) => {
  443. const nextImage =
  444. type === '应急事件'
  445. ? getIncidentImage(i?.status)
  446. : i.locationType && i.resourceType
  447. ? getResourceIcon(
  448. i.locationType.toString(),
  449. i.resourceType.toString(),
  450. )
  451. : image;
  452. const popup = new window.minemap.Popup({
  453. anchor: 'left',
  454. closeOnClick: true,
  455. closeButton: false,
  456. offset: [10, 25],
  457. maxWidth: 'max-content',
  458. // autoPan: true,
  459. }).setDOMContent(getMarkerPopupHTML(type, i));
  460. return {
  461. locations: i.locations,
  462. popup,
  463. marker:
  464. i.locations &&
  465. new window.minemap.Marker(renderElement(nextImage), {
  466. offset: [-25, -25],
  467. })
  468. .setLngLat({
  469. lng: i.locations?.split(',')[0],
  470. lat: i.locations?.split(',')[1],
  471. })
  472. .setPopup(popup)
  473. .addTo(state.map),
  474. };
  475. }),
  476. );
  477. state.positions.push(...markers.map((i) => i.locations).filter(isString));
  478. handleFitBounds();
  479. };
  480. const handleFitBounds = () => {
  481. if (state.positions.length === 0) {
  482. return;
  483. }
  484. const locations = state.positions.map((i) => i.split(',').map(Number));
  485. const leftTop = locations.reduce((carry, next) => {
  486. if (carry.length === 0) return next;
  487. return [Math.min(carry[0], next[0]), Math.max(carry[1], next[1])];
  488. }, []);
  489. const rightBottom = locations.reduce((carry, next) => {
  490. if (carry.length === 0) return next;
  491. return [Math.max(carry[0], next[0]), Math.min(carry[1], next[1])];
  492. }, []);
  493. const leftTopBounds: number[][] = new window.minemap.LngLat(...leftTop)
  494. .toBounds(5000)
  495. .toArray();
  496. const rightBottomBounds: number[][] = new window.minemap.LngLat(
  497. ...rightBottom,
  498. )
  499. .toBounds(5000)
  500. .toArray();
  501. state.map.fitBounds([
  502. rightBottomBounds.reduce((carry, next) => {
  503. if (carry.length === 0) return next;
  504. return [Math.max(carry[0], next[0]), Math.min(carry[1], next[1])];
  505. }, []),
  506. leftTopBounds.reduce((carry, next) => {
  507. if (carry.length === 0) return next;
  508. return [Math.min(carry[0], next[0]), Math.max(carry[1], next[1])];
  509. }, []),
  510. ]);
  511. };
  512. const handleRemoveMarkers = (
  513. type: MarkerMapType,
  514. markers: State['markers'],
  515. ) => {
  516. state.hasTypes = state.hasTypes.filter((t) => t !== type);
  517. const locations = markers.map((i) => i.locations);
  518. state.markers.forEach((m) => {
  519. if (locations.includes(m.locations)) {
  520. m.marker?.remove();
  521. m.popup?.remove();
  522. m.popup = null;
  523. m.marker = null;
  524. }
  525. });
  526. state.markers = state.markers.filter(
  527. (m) => !locations.includes(m.locations),
  528. );
  529. state.positions = state.positions.filter((p) => !locations.includes(p));
  530. handleFitBounds();
  531. };
  532. const handleRemoveAllMarkers = () => {
  533. state.markers.forEach((m) => {
  534. m.marker?.remove();
  535. m.popup?.remove();
  536. });
  537. state.markers = [];
  538. state.positions = [];
  539. };
  540. const handleSetDetailMarker = (marker: MarkerType) => {
  541. handleRemoveAllMarkers();
  542. const locations = marker.locations?.split(',').map(Number);
  543. if (!locations) {
  544. ElMessage.error({ message: '该点位无地址经纬度' });
  545. return;
  546. }
  547. // 获取事件周围的 5km 内的 监控点
  548. const bounds: number[][] = new window.minemap.LngLat(...locations)
  549. .toBounds(10000)
  550. .toArray();
  551. const videos = store.videoSurveillance.reduce((carry, next) => {
  552. const [lng, lat] = next.locations?.split(',') ?? [];
  553. // bounds [right-bottom[lng, lat],left-top[lng, lat], ]
  554. if (
  555. Number(lng) > bounds[0][0] &&
  556. Number(lng) < bounds[1][0] &&
  557. Number(lat) > bounds[0][1] &&
  558. Number(lat) < bounds[1][1]
  559. ) {
  560. carry.push(next);
  561. }
  562. return carry;
  563. }, [] as MarkerType[]);
  564. // 开启路况信息
  565. if (!state.types.includes('路况信息')) {
  566. state.types.push('路况信息');
  567. state.hasTypes.push('路况信息');
  568. toggleControlTraffic();
  569. }
  570. handleAddMarkers('应急事件', [marker], icon_map_dpf);
  571. handleAddMarkers('视频监控', videos, icon_map_spjk);
  572. // state.markers[0].marker.togglePopup();
  573. };
  574. onMounted(async () => {
  575. window.minemap.util.getJSON(
  576. 'http://61.147.254.211:21009/service/solu/style/id/12878',
  577. function (error, data) {
  578. data.layers.forEach(function (layer: any) {
  579. //判断是否道路线图层
  580. if (
  581. layer.type == 'line' &&
  582. layer.source == 'Traffic' &&
  583. layer['source-layer'] == 'Trafficrtic'
  584. ) {
  585. state.trafficLayerIds.push(layer.id);
  586. }
  587. });
  588. },
  589. );
  590. try {
  591. const html = document.createElement("div");
  592. actionTypes.value.forEach(atypes => {
  593. if (atypes?.action == null) return;
  594. const name = atypes.type;
  595. const c = (atypes?.action?.toString().split("handleAddMarkers"));
  596. if (c.length <= 1) return;
  597. const args1 = c[1].replaceAll("(","").replaceAll(")","");
  598. // debugger
  599. const args = args1.split(",");
  600. if (eval(args[2]) == undefined) return;
  601. const div = document.createElement("div");
  602. div.className = "tipitem"
  603. const imagee = renderElement((eval(args[2])));
  604. div.append(imagee);
  605. const c1 = document.createElement("span"); c1.innerHTML = (name);
  606. div.append(c1);
  607. html.append(div);
  608. });
  609. state.map["tipcontentRef"].append(html);
  610. } catch (ee) {
  611. }
  612. state.map.on('load', function () {
  613. updateTrafficSource();
  614. //如果底图没有配置路况图层,需要自己手动增加
  615. state.map.addLayer({
  616. id: 'trafficlines',
  617. type: 'line',
  618. source: 'Traffic',
  619. 'source-layer': 'Trafficrtic',
  620. layout: {
  621. 'line-join': 'round',
  622. 'line-cap': 'round',
  623. },
  624. paint: {
  625. 'line-color': {
  626. property: 'status',
  627. stops: [
  628. [0, '#999999'],
  629. [1, '#66cc00'],
  630. [2, '#ff9900'],
  631. [3, '#cc0000'],
  632. [4, '#9d0404'],
  633. ],
  634. },
  635. 'line-width': {
  636. stops: [
  637. [5, 1],
  638. [18, 3],
  639. ],
  640. base: 1.2,
  641. },
  642. },
  643. });
  644. state.trafficLayerIds.push('trafficlines');
  645. state.trafficStatus = false;
  646. updateTrafficLayerVisibility('none');
  647. store.getAllResources();
  648. store.getAllsingleDevice();
  649. store.getAllvideoDevice();
  650. store.getHDIncidentList();
  651. });
  652. if (!route.query.id) return;
  653. // 如果存在id
  654. await incidentStore.getIncidentItem(route.query.id as string);
  655. // @ts-ignore
  656. handleSetDetailMarker(incidentStore.incidentDetail.baseInfo ?? {});
  657. // const vPlayAreaEl = document.getElementById('vPlayArea');
  658. // vPlayAreaEl &&
  659. // (vPlayAreaEl.style.height = window.innerHeight - 20 + 'px');
  660. // window.theSocket && window.theSocket.resize();
  661. });
  662. watch(
  663. () => store?.currentIncident,
  664. (next) => {
  665. if (!isEmpty(next)) {
  666. handleSetDetailMarker({
  667. ...next,
  668. });
  669. } else {
  670. handleRemoveAllMarkers();
  671. if (state.types.includes('应急事件')) {
  672. state.types.forEach((next) => {
  673. actionTypes.value.forEach((item) => {
  674. if (next === item.type) {
  675. state.hasTypes.push(item.type);
  676. item.action();
  677. }
  678. });
  679. });
  680. } else {
  681. state.map?.flyTo({
  682. center: [118.29564, 33.97441],
  683. zoom: 14,
  684. bearing: 10,
  685. pitch: 30,
  686. duration: 2000,
  687. });
  688. }
  689. }
  690. },
  691. );
  692. watch(
  693. () => state.types,
  694. (next) => {
  695. actionTypes.value.forEach((item) => {
  696. if (next.includes(item.type) && !item.hasActioned) {
  697. state.hasTypes.push(item.type);
  698. item.action();
  699. }
  700. if (!next.includes(item.type) && item.hasActioned) {
  701. item.remove();
  702. }
  703. });
  704. },
  705. );
  706. return () => (
  707. <div class="task-map-container">
  708. <MapView v-model:map={state.map} />
  709. {/* <div style="width:35%;height:20%;background-color:blue"> */}
  710. {/*<div id='vPlayArea' style="width:30%;"/>*/}
  711. {/* </div> */}
  712. <div
  713. class={clsx('address-type-card-container', {
  714. ['in-detail']: props.readonly,
  715. })}>
  716. <Popup
  717. class={clsx('address-type-card', {
  718. ['in-detail']: props.readonly,
  719. })}>
  720. <el-checkbox-group v-model={state.types}>
  721. {adrsMapTypes.value &&
  722. adrsMapTypes.value?.map((t) => (
  723. <>
  724. {!t.disabled && (
  725. <el-checkbox key={t} class="card-item" label={t.name} />
  726. )}
  727. </>
  728. ))}
  729. </el-checkbox-group>
  730. <i class="card-border-bottom-left"></i>
  731. <i class="card-border-bottom-right"></i>
  732. </Popup>
  733. </div>
  734. </div>
  735. );
  736. },
  737. });