张延森 3 anni fa
parent
commit
bc641a2249

+ 7
- 34
src/components/GeoMap/CarsMarker.js Vedi File

3
 import videoStartImg from '@/assets/images/screen/map-video-start.png';
3
 import videoStartImg from '@/assets/images/screen/map-video-start.png';
4
 import videoStopImg from '@/assets/images/screen/map-video-stop.png';
4
 import videoStopImg from '@/assets/images/screen/map-video-stop.png';
5
 
5
 
6
-
7
-
8
-export default (AMap, map, opts = {}) => {
6
+export default function getCarsMarker(AMap, map, opts = {}) {
9
   const marker = new AMap.Marker({
7
   const marker = new AMap.Marker({
10
-    map,
11
     icon: markerImg,
8
     icon: markerImg,
12
     anchor: 'top-center',
9
     anchor: 'top-center',
13
     offset: new AMap.Pixel(0, 0),
10
     offset: new AMap.Pixel(0, 0),
14
     ...opts,
11
     ...opts,
15
   });
12
   });
16
 
13
 
17
-  let show = false;
18
-
19
-  // 
20
-  const { carsName, carsRural } = opts?.extData;
14
+  //
15
+  const { machineryId, name, orgName } = opts?.extData;
21
 
16
 
22
   marker.setLabel({
17
   marker.setLabel({
23
     direction: 'top',
18
     direction: 'top',
24
     offset: new AMap.Pixel(0, 0),
19
     offset: new AMap.Pixel(0, 0),
25
     content: `
20
     content: `
26
-    <div class="SquareBox-box-carsMarker" onclick="openVideo()">
21
+    <div class="SquareBox-box-carsMarker" onclick="openVideo('${machineryId}')">
27
     <div class="border_corner-carsMarker border_corner_left_top-left" ></div>
22
     <div class="border_corner-carsMarker border_corner_left_top-left" ></div>
28
     <div class="border_corner-carsMarker border_corner_right_top-right" ></div>
23
     <div class="border_corner-carsMarker border_corner_right_top-right" ></div>
29
     <div class="border_corner-carsMarker border_corner_left_bottom-left" ></div>
24
     <div class="border_corner-carsMarker border_corner_left_bottom-left" ></div>
42
 
37
 
43
       <div  class="map-button-border">
38
       <div  class="map-button-border">
44
       
39
       
45
-        <div class="carsName">名称:${carsName}</div>
40
+        <div class="carsName">名称:${name}</div>
46
         <div class="map-button-border-carsRural carsName">
41
         <div class="map-button-border-carsRural carsName">
47
-        <div >归属:${carsRural}</div>
42
+        <div >归属:${orgName}</div>
48
         <span> \>> </span>
43
         <span> \>> </span>
49
         </div>
44
         </div>
50
   
45
   
55
   </div> `,
50
   </div> `,
56
   });
51
   });
57
 
52
 
58
-
59
-  // marker.on('click', () => {
60
-  //   if (show) {
61
-  //     marker.setLabel({ content: '' });
62
-  //     show = false;
63
-  //     return;
64
-  //   }
65
-
66
-
67
-  //   if (!content) {
68
-  //     marker.setLabel({ content: '' });
69
-  //   } else {
70
-  //     marker.setLabel({
71
-  //       direction: 'top',
72
-  //       offset: new AMap.Pixel(0, 0),
73
-  //       content: `<div class='geo-map-marker-label' ><div class='geo-map-marker-label-text'>${ruralName}</div></div>`,
74
-  //     });
75
-  //   }
76
-
77
-  //   show = true;
78
-  // });
79
-
80
   return marker;
53
   return marker;
81
-};
54
+}

+ 7
- 35
src/components/GeoMap/RuralMarker.js Vedi File

1
 import ruralMarkerImg from '@/assets/images/screen/map-rural.png';
1
 import ruralMarkerImg from '@/assets/images/screen/map-rural.png';
2
 
2
 
3
-
4
-
5
-
6
-export default (AMap, map, opts = {}) => {
3
+export default function getRuralMarker(AMap, map, opts = {}) {
7
   const marker = new AMap.Marker({
4
   const marker = new AMap.Marker({
8
-    map,
9
     icon: ruralMarkerImg,
5
     icon: ruralMarkerImg,
10
     anchor: 'top-center',
6
     anchor: 'top-center',
11
     offset: new AMap.Pixel(0, 0),
7
     offset: new AMap.Pixel(0, 0),
12
     ...opts,
8
     ...opts,
13
   });
9
   });
14
 
10
 
15
-  let show = false;
16
-
17
   // 合作社数据
11
   // 合作社数据
18
-  const { ruralName, ruralAddress, ruralNumber, ruralPhone, } = opts?.extData;
12
+  const { name, address, machineNum, phone } = opts?.extData;
19
 
13
 
20
   marker.setLabel({
14
   marker.setLabel({
21
     direction: 'top',
15
     direction: 'top',
22
     offset: new AMap.Pixel(0, 0),
16
     offset: new AMap.Pixel(0, 0),
23
     content: `
17
     content: `
24
     <div class='geo-map-rural-box' >
18
     <div class='geo-map-rural-box' >
25
-      <div class="borderBox"><span class='geo-map-rural-text-span borderBox'>名 称</span>:${ruralName}</div>
26
-      <div class="borderBox"><span class='geo-map-rural-text-span borderBox'>地 址</span>:${ruralAddress}</div>
27
-      <div class="borderBox">农机数量:${ruralNumber}</div>
28
-      <div class="borderBox">联系电话:${ruralPhone}</div>
19
+      <div class="borderBox"><span class='geo-map-rural-text-span borderBox'>名 称</span>:${name}</div>
20
+      <div class="borderBox"><span class='geo-map-rural-text-span borderBox'>地 址</span>:${address}</div>
21
+      <div class="borderBox">农机数量:${machineNum} 辆</div>
22
+      <div class="borderBox">联系电话:${phone}</div>
29
     </div>`,
23
     </div>`,
30
   });
24
   });
31
 
25
 
32
-
33
-  // marker.on('click', () => {
34
-  //   if (show) {
35
-  //     marker.setLabel({ content: '' });
36
-  //     show = false;
37
-  //     return;
38
-  //   }
39
-
40
-
41
-  //   if (!content) {
42
-  //     marker.setLabel({ content: '' });
43
-  //   } else {
44
-  //     marker.setLabel({
45
-  //       direction: 'top',
46
-  //       offset: new AMap.Pixel(0, 0),
47
-  //       content: `<div class='geo-map-marker-label' ><div class='geo-map-marker-label-text'>${ruralName}</div></div>`,
48
-  //     });
49
-  //   }
50
-
51
-  //   show = true;
52
-  // });
53
-
54
   return marker;
26
   return marker;
55
-};
27
+}

+ 38
- 61
src/components/GeoMap/index.jsx Vedi File

1
-import React, { useEffect, useRef, useState } from 'react';
1
+import React, { useEffect, useMemo, useRef, useState } from 'react';
2
 import { Modal, Button } from 'antd';
2
 import { Modal, Button } from 'antd';
3
-import loader from '@/components/AMap/loader';
4
-import getMarker from './marker';
5
-import getRuralMarker from './RuralMarker';
6
-import getCarsMarker from './CarsMarker';
7
-
8
-import geoPolygon from './geoPolygon';
3
+import useMap from './map';
4
+import { useMarker, useMarkerVisible } from './marker';
9
 import Styles from './style.less';
5
 import Styles from './style.less';
10
 import RadioGroup from '../ScreenBox/Radio/RadioGroup';
6
 import RadioGroup from '../ScreenBox/Radio/RadioGroup';
11
 
7
 
12
-const plugins = [];
13
-
14
 export default (props) => {
8
 export default (props) => {
15
-  const { machineTypeList } = props;
9
+  const { machineTypeList, orgList, machineList } = props;
16
 
10
 
17
   const container = useRef();
11
   const container = useRef();
18
-  const amapRef = useRef();
19
-  const [map, setMap] = useState();
20
-
12
+  const currentMachineRef = useRef();
13
+  const [machineType, setMachineType] = useState('t0');
21
   const [isModalVisible, setIsModalVisible] = useState(false);
14
   const [isModalVisible, setIsModalVisible] = useState(false);
22
-  const [machineType, setMachineType] = useState();
23
 
15
 
16
+  // 修改地图的默认样式
24
   useEffect(() => {
17
   useEffect(() => {
25
-    loader(plugins).then((AMap) => {
26
-      amapRef.current = AMap;
27
-      const mapInst = new AMap.Map(container.current, {
28
-        mapStyle: 'amap://styles/669a7d8709a9bab0945747a1a1db3327',
29
-        // mapStyle: 'amap://styles/blue',
30
-        zoom: 10,
31
-        resizeEnable: true,
32
-        center: [112.092716, 32.681642],
33
-      });
18
+    const t = setInterval(() => {
19
+      const el = document.querySelector('.amap-ctrl-zoomin');
20
+      if (el) {
21
+        clearInterval(t);
22
+        el.style.color = '#fff';
23
+        document.querySelector('.amap-ctrl-zoomout').style.color = '#fff';
24
+      }
25
+    }, 500);
26
+
27
+    return () => clearInterval(t);
28
+  }, []);
34
 
29
 
35
-      // 遮罩层;
36
-      geoPolygon(AMap, mapInst);
30
+  // 构造地图
31
+  const { amapRef, map } = useMap(container);
37
 
32
 
38
-      //
39
-      setMap(mapInst);
40
-    });
33
+  // 把合作社跟农机合并到一起, 合作社的 typeId 设置为 t0
34
+  const list = useMemo(() => {
35
+    // org 没有 typeId, 因此所有 org 的节点都会带有 typeId = 't0'
36
+    return (orgList || []).map((item) => ({ typeId: 't0', ...item })).concat(machineList || []);
37
+  }, [orgList, machineList]);
41
 
38
 
42
-    window.openVideo = function () {
43
-      console.log(' window.foo 全局方法');
44
-      setIsModalVisible(true);
45
-    };
46
-
47
-    return () => (window.openVideo = undefined);
48
-  }, []);
39
+  // 生成所有的 marker
40
+  const markerListRef = useMarker(amapRef, map, list);
41
+  // 监听选择
42
+  useMarkerVisible(map, markerListRef, machineType);
49
 
43
 
44
+  // 把农机 marker 的点击事件挂载到 window 下面作为全局 function
50
   useEffect(() => {
45
   useEffect(() => {
51
-    if (!map) return;
52
-
53
-    // 先搞一个 marker demo
54
-    getMarker(amapRef.current, map, {
55
-      position: [112.092716, 32.681642],
56
-      extData: { value: '68辆' },
57
-    });
46
+    if (!machineList || !machineList.length) return;
58
 
47
 
59
-    // 合作社图标定位
60
-    getRuralMarker(amapRef.current, map, {
61
-      position: [111.909659, 32.651123],
62
-      extData: {
63
-        ruralName: 'ABC合作社',
64
-        ruralAddress: '南阳市邓州市林扒镇',
65
-        ruralNumber: '9辆',
66
-        ruralPhone: '13613949434',
67
-      },
68
-    });
48
+    window.openVideo = function (machineryId) {
49
+      currentMachineRef.current = machineList.filter((x) => x.machineryId === machineryId)[0];
50
+      setIsModalVisible(true);
51
+    };
69
 
52
 
70
-    // 农机监控
71
-    getCarsMarker(amapRef.current, map, {
72
-      position: [112.115574, 32.65235],
73
-      extData: {
74
-        carsName: '播种机0001',
75
-        carsRural: 'ABC合作社',
76
-      },
77
-    });
78
-  }, [map]);
53
+    return () => (window.openVideo = undefined);
54
+  }, [machineList]);
79
 
55
 
80
   return (
56
   return (
81
     <div className={Styles['geo-map-container']}>
57
     <div className={Styles['geo-map-container']}>
94
       </div>
70
       </div>
95
 
71
 
96
       <div className={Styles['geo-map-body']}>
72
       <div className={Styles['geo-map-body']}>
73
+        {/* 渲染地图 */}
97
         <div ref={container} />
74
         <div ref={container} />
98
       </div>
75
       </div>
99
 
76
 

+ 33
- 0
src/components/GeoMap/map.js Vedi File

1
+import React, { useEffect, useMemo, useRef, useState } from 'react';
2
+import loader from '@/components/AMap/loader';
3
+import geoPolygon from './geoPolygon';
4
+
5
+const plugins = ['AMap.ToolBar'];
6
+export default (containerRef) => {
7
+  const amapRef = useRef();
8
+  const [map, setMap] = useState();
9
+
10
+  useEffect(() => {
11
+    loader(plugins).then((AMap) => {
12
+      amapRef.current = AMap;
13
+      const mapInst = new AMap.Map(containerRef.current, {
14
+        mapStyle: 'amap://styles/669a7d8709a9bab0945747a1a1db3327',
15
+        // mapStyle: 'amap://styles/blue',
16
+        zoom: 10,
17
+        resizeEnable: true,
18
+        center: [112.092716, 32.681642],
19
+      });
20
+
21
+      // 缩放按钮
22
+      mapInst.addControl(new AMap.ToolBar());
23
+
24
+      // 遮罩层;
25
+      geoPolygon(AMap, mapInst);
26
+
27
+      //
28
+      setMap(mapInst);
29
+    });
30
+  }, []);
31
+
32
+  return { amapRef, map };
33
+};

+ 34
- 37
src/components/GeoMap/marker.js Vedi File

1
-import markerImg from '@/assets/images/screen/map-marker.png';
2
-
3
-
4
-export default (AMap, map, opts = {}) => {
5
-  const marker = new AMap.Marker({
6
-    map,
7
-    icon: markerImg,
8
-    anchor: 'top-center',
9
-    offset: new AMap.Pixel(0, 0),
10
-    ...opts,
11
-  });
12
-
13
-  let show = false;
14
-  const content = opts?.extData?.value;
15
-
16
-
17
-  marker.on('click', () => {
18
-    if (show) {
19
-      marker.setLabel({ content: '' });
20
-      show = false;
21
-      return;
22
-    }
23
-
24
-
25
-    if (!content) {
26
-      marker.setLabel({ content: '' });
27
-    } else {
28
-      marker.setLabel({
29
-        direction: 'top',
30
-        offset: new AMap.Pixel(0, 0),
31
-        content: `<div class='geo-map-marker-label' ><div class='geo-map-marker-label-text'>${content}</div></div>`,
1
+import React, { useEffect, useMemo, useRef, useState } from 'react';
2
+import getRuralMarker from './RuralMarker';
3
+import getCarsMarker from './CarsMarker';
4
+
5
+export function useMarker(amapRef, map, list) {
6
+  const markerListRef = useRef();
7
+
8
+  // 农机列表
9
+  useEffect(() => {
10
+    if (!amapRef.current) return;
11
+
12
+    if (list && list.length) {
13
+      markerListRef.current = list.map((item) => {
14
+        const fnMarker = item.typeId === 't0' ? getRuralMarker : getCarsMarker;
15
+        return fnMarker(amapRef.current, null, {
16
+          position: item.lnglat,
17
+          extData: item,
18
+        });
32
       });
19
       });
33
     }
20
     }
34
-
35
-    show = true;
36
-  });
37
-
38
-  return marker;
39
-};
21
+  }, [map, list]);
22
+
23
+  return markerListRef;
24
+}
25
+
26
+export function useMarkerVisible(map, markerListRef, typeId) {
27
+  useEffect(() => {
28
+    console.log(typeId, markerListRef.current);
29
+    if (!map || !markerListRef.current) return;
30
+
31
+    markerListRef.current.forEach((marker) => {
32
+      const item = marker.getExtData();
33
+      marker.setMap(item.typeId === typeId ? map : null);
34
+    });
35
+  }, [map, typeId]);
36
+}

+ 2
- 2
src/components/GeoMap/style.less Vedi File

9
 
9
 
10
   .radio-group {
10
   .radio-group {
11
     position: absolute;
11
     position: absolute;
12
-    top: 5%;
12
+    top: 8%;
13
     left: 5%;
13
     left: 5%;
14
     z-index: 1000;
14
     z-index: 1000;
15
   }
15
   }
16
 
16
 
17
   .geo-map-body {
17
   .geo-map-body {
18
     height: calc(100% - 54px);
18
     height: calc(100% - 54px);
19
-    padding: 0 20px;
19
+    // padding: 0 20px;
20
     background-color: #061e3f;
20
     background-color: #061e3f;
21
     border-right: 1px solid rgba(61, 129, 240, 0.5);
21
     border-right: 1px solid rgba(61, 129, 240, 0.5);
22
     border-left: 1px solid rgba(61, 129, 240, 0.5);
22
     border-left: 1px solid rgba(61, 129, 240, 0.5);

+ 9
- 0
src/global.less Vedi File

75
   flex: 1;
75
   flex: 1;
76
 }
76
 }
77
 
77
 
78
+// 修改大屏地图的 zoom 空间样式
79
+.amap-toolbar {
80
+  background-color: rgba(255, 255, 255, 0.3);
81
+}
82
+
83
+.amap-toolbar span:first-child {
84
+  border-bottom: 1px solid rgba(255, 255, 255, 0.3);
85
+}
86
+
78
 .amap-marker-label {
87
 .amap-marker-label {
79
   background: transparent;
88
   background: transparent;
80
   border: none;
89
   border: none;

+ 78
- 4
src/pages/MonitoringScreen/index.jsx Vedi File

49
   ]);
49
   ]);
50
 
50
 
51
   const [machineTypeList, setMachineTypeList] = useState([
51
   const [machineTypeList, setMachineTypeList] = useState([
52
-    { id: 1, name: '收割机' },
53
-    { id: 2, name: '播种机' },
54
-    { id: 3, name: '农药机' },
52
+    { id: 't0', name: '合作社' },
53
+    { id: 't1', name: '收割机' },
54
+    { id: 't2', name: '播种机' },
55
+    { id: 't3', name: '农药机' },
56
+  ]);
57
+
58
+  const [orgList, setOrgList] = useState([
59
+    {
60
+      orgId: 1,
61
+      name: '合作社1',
62
+      address: '合作社地址1',
63
+      phone: '13823838438',
64
+      machineNum: 12,
65
+      lnglat: [111.888505, 32.854667],
66
+    },
67
+    {
68
+      orgId: 2,
69
+      name: '合作社2',
70
+      address: '合作社地址2',
71
+      phone: '13823838438',
72
+      machineNum: 68,
73
+      lnglat: [111.921464, 32.467361],
74
+    },
75
+    {
76
+      orgId: 3,
77
+      name: '合作社3',
78
+      address: '合作社地址3',
79
+      phone: '13823838438',
80
+      machineNum: 3,
81
+      lnglat: [112.367784, 32.815435],
82
+    },
83
+    {
84
+      orgId: 4,
85
+      name: '合作社4',
86
+      address: '合作社地址4',
87
+      phone: '13823838438',
88
+      machineNum: 42,
89
+      lnglat: [112.311479, 32.580836],
90
+    },
91
+  ]);
92
+
93
+  const [machineList, setMachineList] = useState([
94
+    {
95
+      machineryId: 'm1',
96
+      name: '农机1',
97
+      typeId: 't1',
98
+      orgName: '合作社1',
99
+      lnglat: [111.867906, 32.799276],
100
+    },
101
+    {
102
+      machineryId: 'm2',
103
+      name: '农机2',
104
+      typeId: 't2',
105
+      orgName: '合作社1',
106
+      lnglat: [112.087632, 32.66527],
107
+    },
108
+    {
109
+      machineryId: 'm3',
110
+      name: '农机3',
111
+      typeId: 't1',
112
+      orgName: '合作社2',
113
+      lnglat: [112.237321, 32.631737],
114
+    },
115
+    {
116
+      machineryId: 'm4',
117
+      name: '农机4',
118
+      typeId: 't3',
119
+      orgName: '合作社2',
120
+      lnglat: [112.002488, 32.563476],
121
+    },
122
+    {
123
+      machineryId: 'm5',
124
+      name: '农机5',
125
+      typeId: 't3',
126
+      orgName: '合作社3',
127
+      lnglat: [112.105485, 32.791195],
128
+    },
55
   ]);
129
   ]);
56
 
130
 
57
   useEffect(() => {
131
   useEffect(() => {
95
               <StatisCard color="#F5CC5C" icon="icon3" value={168} title="总预约数(台)" />
169
               <StatisCard color="#F5CC5C" icon="icon3" value={168} title="总预约数(台)" />
96
               <StatisCard color="#C579FF" icon="icon4" value={1568} title="总服务数(台)" />
170
               <StatisCard color="#C579FF" icon="icon4" value={1568} title="总服务数(台)" />
97
             </div>
171
             </div>
98
-            <GeoMap machineTypeList={machineTypeList} />
172
+            <GeoMap machineTypeList={machineTypeList} orgList={orgList} machineList={machineList} />
99
           </div>
173
           </div>
100
           <div className={Styles['grail-right']}>
174
           <div className={Styles['grail-right']}>
101
             <div className="flex flex-column full-height">
175
             <div className="flex flex-column full-height">