index.tsx 25 KB

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