fangmingyue 2 years ago
parent
commit
1f322705eb
55 changed files with 2549 additions and 1596 deletions
  1. 15
    0
      .vscode/launch.json
  2. 2
    2
      config/defaultSettings.js
  3. 40
    40
      config/proxy.js
  4. 31
    26
      config/routes.js
  5. BIN
      public/logo.png
  6. BIN
      public/logo2.png
  7. BIN
      src/assets/images/screen/header-title.png
  8. 18
    9
      src/components/AMap/weather.js
  9. 2
    1
      src/components/CooperativeSearch/index.jsx
  10. 0
    3
      src/components/ECharts/index.jsx
  11. 31
    0
      src/components/GISMap/index.jsx
  12. 29
    0
      src/components/GISMap/map.js
  13. 71
    0
      src/components/GISMap/marker.js
  14. 92
    0
      src/components/GISMap/style.less
  15. 19
    28
      src/components/GeoMap/CarsMarker.js
  16. 2
    2
      src/components/GeoMap/RuralMarker.js
  17. 2
    3
      src/components/GeoMap/marker.js
  18. 2
    1
      src/components/ScreenBox/ScreenHeader/style.less
  19. 2
    1
      src/components/Upload/UploadImage.jsx
  20. 0
    3
      src/pages/JobStatistics/RevenueExpenditure/index.jsx
  21. 91
    0
      src/pages/Machinery/GIS/components/WorkListModel.jsx
  22. 60
    0
      src/pages/Machinery/GIS/detail.jsx
  23. 152
    1
      src/pages/Machinery/GIS/index.jsx
  24. 0
    59
      src/pages/Machinery/GPS/edit.jsx
  25. 0
    99
      src/pages/Machinery/GPS/index.jsx
  26. 198
    0
      src/pages/Machinery/Machinery/Edit/components/BasicInfo.jsx
  27. 132
    0
      src/pages/Machinery/Machinery/Edit/components/DeviceInfo.jsx
  28. 113
    0
      src/pages/Machinery/Machinery/Edit/components/DeviceList.jsx
  29. 5
    370
      src/pages/Machinery/Machinery/Edit/index.jsx
  30. 20
    8
      src/pages/Machinery/MachineryType/index.jsx
  31. 27
    0
      src/pages/Machinery/Org/RuralMarker.js
  32. 0
    11
      src/pages/Machinery/Org/index.jsx
  33. 58
    0
      src/pages/Machinery/Person/components/OrgTree.jsx
  34. 100
    0
      src/pages/Machinery/Person/components/RoleModel.jsx
  35. 161
    0
      src/pages/Machinery/Person/components/UserModal.jsx
  36. 48
    278
      src/pages/Machinery/Person/index.jsx
  37. 27
    5
      src/pages/MonitoringScreen/components/List/index.jsx
  38. 16
    9
      src/pages/MonitoringScreen/components/MachineryType.jsx
  39. 12
    4
      src/pages/MonitoringScreen/components/WorkArea.jsx
  40. 11
    3
      src/pages/MonitoringScreen/components/WorkData.jsx
  41. 161
    149
      src/pages/MonitoringScreen/index.jsx
  42. 18
    34
      src/pages/OrderManage/JobWarning/detail.jsx
  43. 109
    91
      src/pages/OrderManage/dispatch.jsx
  44. 21
    108
      src/pages/PlatformMessageManagement/MessageManageList/index.jsx
  45. 80
    0
      src/pages/SystemManagement/Classification/index.jsx
  46. 177
    0
      src/pages/SystemManagement/Sensing/index.jsx
  47. 24
    0
      src/pages/SystemManagement/Subsoiler/index.jsx
  48. 15
    38
      src/pages/customer/index.jsx
  49. 197
    207
      src/pages/document.ejs
  50. 2
    2
      src/services/device.js
  51. 15
    1
      src/services/job.js
  52. 59
    0
      src/services/monitoringScreen.js
  53. 8
    0
      src/services/person.js
  54. 8
    0
      src/services/workMessage.js
  55. 66
    0
      src/utils/mapTogcj02.js

+ 15
- 0
.vscode/launch.json View File

@@ -0,0 +1,15 @@
1
+{
2
+    // 使用 IntelliSense 了解相关属性。 
3
+    // 悬停以查看现有属性的描述。
4
+    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
5
+    "version": "0.2.0",
6
+    "configurations": [
7
+        {
8
+            "type": "pwa-chrome",
9
+            "request": "launch",
10
+            "name": "Launch Chrome against localhost",
11
+            "url": "http://localhost:8080",
12
+            "webRoot": "${workspaceFolder}"
13
+        }
14
+    ]
15
+}

+ 2
- 2
config/defaultSettings.js View File

@@ -7,12 +7,12 @@ const Settings = {
7 7
   fixedHeader: false,
8 8
   fixSiderbar: true,
9 9
   colorWeak: false,
10
-  title: '南阳智慧农机系统',
10
+  title: '邓州市源盛农机数据可视化平台',
11 11
   pwa: false,
12 12
   menu: {
13 13
     locale: false,
14 14
   },
15
-  logo: 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
15
+  logo: './logo2.png',
16 16
   // iconfontUrl: '//at.alicdn.com/t/font_3221810_t3g0tvsigf.js',
17 17
 };
18 18
 export default Settings;

+ 40
- 40
config/proxy.js View File

@@ -1,40 +1,40 @@
1
-/**
2
- * 在生产环境 代理是无法生效的,所以这里没有生产环境的配置
3
- * -------------------------------
4
- * The agent cannot take effect in the production environment
5
- * so there is no configuration of the production environment
6
- * For details, please see
7
- * https://pro.ant.design/docs/deploy
8
- */
9
-export default {
10
-  dev: {
11
-    // localhost:8000/api/** -> https://preview.pro.ant.design/api/**
12
-    '/api/': {
13
-      // 要代理的地址
14
-      // target: 'http://192.168.89.147:7080',
15
-      // target: 'http://192.168.89.25:7080',
16
-      target: 'http://machine.njyunzhi.com',
17
-      // 配置了这个可以从 http 代理到 https
18
-      // 依赖 origin 的功能可能需要这个,比如 cookie
19
-      changeOrigin: true,
20
-    },
21
-  },
22
-  test: {
23
-    '/api/': {
24
-      target: 'https://proapi.azurewebsites.net',
25
-      changeOrigin: true,
26
-      pathRewrite: {
27
-        '^': '',
28
-      },
29
-    },
30
-  },
31
-  pre: {
32
-    '/api/': {
33
-      target: 'your pre url',
34
-      changeOrigin: true,
35
-      pathRewrite: {
36
-        '^': '',
37
-      },
38
-    },
39
-  },
40
-};
1
+/**
2
+ * 在生产环境 代理是无法生效的,所以这里没有生产环境的配置
3
+ * -------------------------------
4
+ * The agent cannot take effect in the production environment
5
+ * so there is no configuration of the production environment
6
+ * For details, please see
7
+ * https://pro.ant.design/docs/deploy
8
+ */
9
+export default {
10
+  dev: {
11
+    // localhost:8000/api/** -> https://preview.pro.ant.design/api/**
12
+    '/api/': {
13
+      // 要代理的地址
14
+      // target: 'http://127.0.0.1:7080',
15
+      target: 'http://192.168.89.147:7080',
16
+      // target: 'http://machine.njyunzhi.com',
17
+      // 配置了这个可以从 http 代理到 https
18
+      // 依赖 origin 的功能可能需要这个,比如 cookie
19
+      changeOrigin: true,
20
+    },
21
+  },
22
+  test: {
23
+    '/api/': {
24
+      target: 'https://proapi.azurewebsites.net',
25
+      changeOrigin: true,
26
+      pathRewrite: {
27
+        '^': '',
28
+      },
29
+    },
30
+  },
31
+  pre: {
32
+    '/api/': {
33
+      target: 'your pre url',
34
+      changeOrigin: true,
35
+      pathRewrite: {
36
+        '^': '',
37
+      },
38
+    },
39
+  },
40
+};

+ 31
- 26
config/routes.js View File

@@ -73,14 +73,14 @@ export default [
73 73
   },
74 74
   {
75 75
     path: '/customer',
76
-    name: '户管理',
76
+    name: '户管理',
77 77
     icon: 'IdcardOutlined',
78 78
     access: 'customer',
79 79
     component: '../layouts/BasicLayout',
80 80
     routes: [
81 81
       {
82 82
         path: '/customer/index.jsx',
83
-        name: '户列表',
83
+        name: '户列表',
84 84
         access: 'customerList',
85 85
         icon: 'smile',
86 86
         component: './customer',
@@ -124,24 +124,17 @@ export default [
124 124
         component: './Machinery/Machinery/Edit',
125 125
         hideInMenu: true,
126 126
       },
127
-      // {
128
-      //   path: '/Machinery/GPS',
129
-      //   name: '设备管理',
130
-      //   access: 'device',
131
-      //   component: './Machinery/GPS',
132
-      // },
133
-      // {
134
-      //   path: '/Machinery/GPS/edit.jsx',
135
-      //   name: '设备编辑',
136
-      //   component: './Machinery/GPS/edit.jsx',
137
-      //   hideInMenu: true,
138
-      // },
139
-      // {
140
-      //   path: '/Machinery/GIS',
141
-      //   name: '农机GIS',
142
-      //   access: 'gis',
143
-      //   component: './Machinery/GIS',
144
-      // },
127
+      {
128
+        path: '/Machinery/GIS',
129
+        name: '农机GIS',
130
+        component: './Machinery/GIS',
131
+      },
132
+      {
133
+        path: '/Machinery/GIS/detail.jsx',
134
+        name: 'GIS详情',
135
+        component: './Machinery/GIS/detail.jsx',
136
+        hideInMenu: true,
137
+      },
145 138
     ],
146 139
   },
147 140
   {
@@ -204,12 +197,6 @@ export default [
204 197
         access: 'st-work',
205 198
         component: './JobStatistics/Job',
206 199
       },
207
-      // {
208
-      //   path: '/JobStatistics/RevenueExpenditure',
209
-      //   name: '收支统计',
210
-      //   access: 'st-finance',
211
-      //   component: './JobStatistics/RevenueExpenditure',
212
-      // },
213 200
     ],
214 201
   },
215 202
   {
@@ -293,6 +280,24 @@ export default [
293 280
         access: 'setting',
294 281
         component: './SystemManagement/BasicParameters',
295 282
       },
283
+      {
284
+        path: '/SystemManagement/Subsoiler',
285
+        name: '深松机',
286
+        access: 'setting',
287
+        component: './SystemManagement/Subsoiler',
288
+      },
289
+      {
290
+        path: '/SystemManagement/Sensing',
291
+        name: '传感设备列表',
292
+        access: 'setting',
293
+        component: './SystemManagement/Sensing',
294
+      },
295
+      {
296
+        path: '/SystemManagement/Classification',
297
+        name: '分类管理',
298
+        access: 'setting',
299
+        component: './SystemManagement/Classification',
300
+      },
296 301
     ],
297 302
   },
298 303
 

BIN
public/logo.png View File


BIN
public/logo2.png View File


BIN
src/assets/images/screen/header-title.png View File


+ 18
- 9
src/components/AMap/weather.js View File

@@ -1,18 +1,27 @@
1 1
 const SERVER_KEY = 'a30b66a26ea1890fd656cf11cb2647fb';
2 2
 
3
-export default function getWeather(city) {
4
-  const url = `https://restapi.amap.com/v3/weather/weatherInfo?key=${SERVER_KEY}&city=${city}&extensions=all`;
5
-
6
-  return fetch(url)
3
+export default function getWeather() {
4
+  // 先获取当前位置
5
+  return fetch(`https://restapi.amap.com/v3/ip?key=${SERVER_KEY}`)
7 6
     .then((res) => res.json())
8 7
     .then((res) => {
9
-      if (res.info === 'OK') {
10
-        return res.forecasts;
8
+      if (res.adcode) {
9
+        const url = `https://restapi.amap.com/v3/weather/weatherInfo?key=${SERVER_KEY}&city=${res.adcode}&extensions=all`;
10
+
11
+        return fetch(url)
12
+          .then((res) => res.json())
13
+          .then((res) => {
14
+            if (res.info === 'OK') {
15
+              return res.forecasts;
16
+            } else {
17
+              return Promise.reject(res.info);
18
+            }
19
+          })
20
+          .catch((err) => {
21
+            console.log(err.message);
22
+          });
11 23
       } else {
12 24
         return Promise.reject(res.info);
13 25
       }
14
-    })
15
-    .catch((err) => {
16
-      console.log(err.message);
17 26
     });
18 27
 }

+ 2
- 1
src/components/CooperativeSearch/index.jsx View File

@@ -4,7 +4,7 @@ import { getCooperativeList, getCooperativeDetail } from '@/services/cooperative
4 4
 
5 5
 const Option = Select.Option;
6 6
 export default (props) => {
7
-  const { value, onChange, ...otherProps } = props;
7
+  const { value, onChange, disabled, ...otherProps } = props;
8 8
 
9 9
   const [list, setList] = useState([]);
10 10
 
@@ -42,6 +42,7 @@ export default (props) => {
42 42
       onSearch={handleSearch}
43 43
       onChange={onChange}
44 44
       notFoundContent={null}
45
+      disabled={disabled}
45 46
       {...otherProps}
46 47
     >
47 48
       {list.map((item) => {

+ 0
- 3
src/components/ECharts/index.jsx View File

@@ -42,10 +42,8 @@ import Styles from './style.less';
42 42
 export default forwardRef((props, ref) => {
43 43
   const domRef = useRef();
44 44
   const echartsRef = useRef();
45
-
46 45
   useEffect(() => {
47 46
     echartsRef.current = echarts.init(domRef.current);
48
-
49 47
     const handleResize = () => {
50 48
       echartsRef.current.resize();
51 49
     };
@@ -57,7 +55,6 @@ export default forwardRef((props, ref) => {
57 55
       echartsRef.current.dispose();
58 56
     };
59 57
   }, []);
60
-
61 58
   useEffect(() => {
62 59
     if (echartsRef.current) {
63 60
       echartsRef.current.setOption(props.option);

+ 31
- 0
src/components/GISMap/index.jsx View File

@@ -0,0 +1,31 @@
1
+import { useRef } from "react";
2
+import useMap from './map';
3
+import { useMarker, startAnimation, pauseAnimation, resumeAnimation, stopAnimation } from './marker';
4
+import './style.less';
5
+
6
+export default (props) => {
7
+  const { lineArr } = props
8
+  const container = useRef()
9
+  //生成地图
10
+  const { amapRef, map } = useMap(container);
11
+  //生成marker
12
+  useMarker(amapRef, map, lineArr);
13
+
14
+  return (
15
+    <>
16
+      <div ref={container} id="container" style={{ height: '700px', position: 'relative' }} >
17
+        <div className="input-card">
18
+          <h4>轨迹回放控制</h4>
19
+          <div className="input-item">
20
+            <input type="button" className="btn" value="开始动画" id="start" onClick={startAnimation} />
21
+            <input type="button" className="btn" value="暂停动画" id="pause" onClick={pauseAnimation} />
22
+          </div>
23
+          <div className="input-item">
24
+            <input type="button" className="btn" value="继续动画" id="resume" onClick={resumeAnimation} />
25
+            <input type="button" className="btn" value="停止动画" id="stop" onClick={stopAnimation} />
26
+          </div>
27
+        </div>
28
+      </div>
29
+    </>
30
+  )
31
+}

+ 29
- 0
src/components/GISMap/map.js View File

@@ -0,0 +1,29 @@
1
+import React, { useEffect, useRef, useState } from 'react';
2
+import loader from '@/components/AMap/loader';
3
+
4
+const plugins = ['AMap.MoveAnimation'];
5
+export default (containerRef) => {
6
+  const amapRef = useRef();
7
+  const [map, setMap] = useState();
8
+
9
+  useEffect(() => {
10
+    loader(plugins)
11
+      .then((AMap) => {
12
+        amapRef.current = AMap;
13
+
14
+        const mapInst = new AMap.Map(containerRef.current, {
15
+          zoom: 17,
16
+          resizeEnable: true,
17
+          center: [112.093131, 32.692095],
18
+        });
19
+
20
+        //
21
+        setMap(mapInst);
22
+      })
23
+      .catch((err) => {
24
+        console.log(err.message);
25
+      });
26
+  }, [containerRef]);
27
+
28
+  return { amapRef, map };
29
+};

+ 71
- 0
src/components/GISMap/marker.js View File

@@ -0,0 +1,71 @@
1
+import React, { useEffect, useMemo, useRef } from 'react';
2
+
3
+let marker, lineArr;
4
+export function useMarker(amapRef, map, lujing) {
5
+  useMemo(() => {
6
+    if (!amapRef.current) return;
7
+    marker = new amapRef.current.Marker({
8
+      icon: 'https://a.amap.com/jsapi_demos/static/demo-center-v2/car.png',
9
+      offset: new amapRef.current.Pixel(-13, -26),
10
+    });
11
+  }, [map]);
12
+
13
+  useEffect(() => {
14
+    if (!amapRef.current || !marker || !lujing || lujing.length == 0) {
15
+      return;
16
+    }
17
+    lineArr = lujing;
18
+    //https://lbs.amap.com/api/jsapi-v2/documentation#marker
19
+    // 动态添加地图和marker的定位
20
+    marker.setPosition(lineArr[0]);
21
+    marker.setMap(map);
22
+    var polyline = new amapRef.current.Polyline({
23
+      map: map,
24
+      path: lineArr,
25
+      showDir: true,
26
+      strokeColor: '#28F', //线颜色
27
+      // strokeOpacity: 1,     //线透明度
28
+      strokeWeight: 6, //线宽
29
+      // strokeStyle: "solid"  //线样式
30
+    });
31
+
32
+    var passedPolyline = new amapRef.current.Polyline({
33
+      map: map,
34
+      strokeColor: '#AF5', //线颜色
35
+      strokeWeight: 6, //线宽
36
+    });
37
+    //给marker添加监控
38
+    marker.on('moving', function (e) {
39
+      passedPolyline.setPath(e.passedPath);
40
+      //marker运动时将marker置位地图中心
41
+      map.setCenter(e.target.getPosition(), true);
42
+    });
43
+    //地图跟随marker移动
44
+    map.setFitView();
45
+  }, [map, lujing]);
46
+}
47
+export function startAnimation() {
48
+  if (marker) {
49
+    marker.moveAlong(lineArr, {
50
+      // 每一段的时长
51
+      duration: 500, //可根据实际采集时间间隔设置
52
+      // JSAPI2.0 是否延道路自动设置角度在 moveAlong 里设置
53
+      autoRotation: true,
54
+    });
55
+  }
56
+}
57
+export function pauseAnimation() {
58
+  if (marker) {
59
+    marker.pauseMove();
60
+  }
61
+}
62
+export function resumeAnimation() {
63
+  if (marker) {
64
+    marker.resumeMove();
65
+  }
66
+}
67
+export function stopAnimation() {
68
+  if (marker) {
69
+    marker.stopMove();
70
+  }
71
+}

+ 92
- 0
src/components/GISMap/style.less View File

@@ -0,0 +1,92 @@
1
+html {
2
+  font-size: 12px;
3
+}
4
+
5
+.input-card {
6
+  display: flex;
7
+  flex-direction: column;
8
+  min-width: 0;
9
+  word-wrap: break-word;
10
+  background-color: #fff;
11
+  background-clip: border-box;
12
+  border-radius: .25rem;
13
+  width: 22rem;
14
+  border-width: 0;
15
+  border-radius: 0.4rem;
16
+  box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
17
+  position: absolute;
18
+  z-index: 9;
19
+  bottom: 1rem;
20
+  right: 1rem;
21
+  -ms-flex: 1 1 auto;
22
+  flex: 1 1 auto;
23
+  padding: 0.75rem 1.25rem;
24
+}
25
+
26
+h4 {
27
+  font-family: inherit;
28
+  line-height: 1.8;
29
+  font-weight: 300;
30
+  color: inherit;
31
+  font-size: 1.1rem;
32
+  margin-top: 0;
33
+  margin-bottom: .5rem
34
+}
35
+
36
+.input-item {
37
+  position: relative;
38
+  display: -ms-flexbox;
39
+  display: flex;
40
+  -ms-flex-wrap: wrap;
41
+  flex-wrap: wrap;
42
+  -ms-flex-align: center;
43
+  align-items: center;
44
+  width: 100%;
45
+  height: 3rem;
46
+}
47
+
48
+.input-item:last-child {
49
+  margin-bottom: 0;
50
+}
51
+
52
+.btn {
53
+  display: inline-block;
54
+  font-weight: 400;
55
+  font-size: 1rem;
56
+  margin-right: 1.2rem;
57
+  width: 9rem;
58
+  text-align: center;
59
+  white-space: nowrap;
60
+  vertical-align: middle;
61
+  -webkit-user-select: none;
62
+  -moz-user-select: none;
63
+  -ms-user-select: none;
64
+  user-select: none;
65
+  border: 1px solid transparent;
66
+  transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
67
+  background-color: transparent;
68
+  background-image: none;
69
+  color: #25A5F7;
70
+  border-color: #25A5F7;
71
+  padding: .25rem .5rem;
72
+  line-height: 1.5;
73
+  border-radius: 1rem;
74
+  -webkit-appearance: button;
75
+  cursor:pointer;
76
+}
77
+
78
+.btn:hover {
79
+  color: #fff;
80
+  background-color: #25A5F7;
81
+  border-color: #25A5F7;
82
+  text-decoration: none
83
+}
84
+
85
+.btn:focus {
86
+  outline: 0;
87
+  box-shadow: none;
88
+}
89
+
90
+.input-card .btn:last-child{
91
+  margin-right: 0;
92
+}

+ 19
- 28
src/components/GeoMap/CarsMarker.js View File

@@ -2,6 +2,7 @@ import markerImg from '@/assets/images/screen/map-marker.png';
2 2
 import carsImg from '@/assets/images/screen/map-cars.png';
3 3
 import videoStartImg from '@/assets/images/screen/map-video-start.png';
4 4
 import videoStopImg from '@/assets/images/screen/map-video-stop.png';
5
+import { useRef } from 'react';
5 6
 
6 7
 export default function getCarsMarker(AMap, map, opts = {}) {
7 8
   const marker = new AMap.Marker({
@@ -11,43 +12,33 @@ export default function getCarsMarker(AMap, map, opts = {}) {
11 12
     ...opts,
12 13
   });
13 14
 
14
-  //
15
-  const { machineryId, name, orgName } = opts?.extData;
15
+  const { machineryId, name, orgName, thumb } = opts?.extData;
16 16
 
17 17
   marker.setLabel({
18 18
     direction: 'top',
19
-    offset: new AMap.Pixel(0, 0),
19
+    //偏移单位是px
20
+    offset: new AMap.Pixel(-88, -180),
20 21
     content: `
21 22
     <div class="SquareBox-box-carsMarker" onclick="openVideo('${machineryId}')">
22
-    <div class="border_corner-carsMarker border_corner_left_top-left" ></div>
23
-    <div class="border_corner-carsMarker border_corner_right_top-right" ></div>
24
-    <div class="border_corner-carsMarker border_corner_left_bottom-left" ></div>
25
-    <div class="border_corner-carsMarker border_corner_right_bottom-right" ></div>
26
-    <div class="SquareBox-body-carsMarker">
27
-    <div>
28
-    <div>
29
-    </div>
30
-    <div>
31
-      <div  class="map-top-border">
32
-        <img class="map-top-cars borderBox" src="${carsImg}" alt="" />
33
-        <img class="map-top-start borderBox" src="${videoStartImg}" alt="" />
34
-        <img class="map-top-stop borderBox" src="${videoStopImg}" alt="" />
35
-      </div>
36
-
37
-
38
-      <div  class="map-button-border">
39
-      
23
+      <div class="border_corner-carsMarker border_corner_left_top-left" ></div>
24
+      <div class="border_corner-carsMarker border_corner_right_top-right" ></div>
25
+      <div class="border_corner-carsMarker border_corner_left_bottom-left" ></div>
26
+      <div class="border_corner-carsMarker border_corner_right_bottom-right" ></div>
27
+      <div class="SquareBox-body-carsMarker">
28
+        <div  class="map-top-border">
29
+          <div style="width:100%;text-align:center">
30
+            <img  class="map-top-cars borderBox" src="${thumb}" alt="" />
31
+          </div>
32
+          <img class="map-top-start borderBox" src="${videoStartImg}" alt="" />
33
+          <img class="map-top-stop borderBox" src="${videoStopImg}" alt="" />
34
+        </div>
35
+        <div  class="map-button-border">      
40 36
         <div class="carsName">名称:${name}</div>
41 37
         <div class="map-button-border-carsRural carsName">
42 38
         <div >归属:${orgName}</div>
43 39
         <span> \>> </span>
44
-        </div>
45
-  
46
-      </div>
47
-
48
-
49
-    </div>
50
-  </div> `,
40
+      </div>   
41
+    </div> `,
51 42
   });
52 43
 
53 44
   return marker;

+ 2
- 2
src/components/GeoMap/RuralMarker.js View File

@@ -9,7 +9,7 @@ export default function getRuralMarker(AMap, map, opts = {}) {
9 9
   });
10 10
 
11 11
   // 合作社数据
12
-  const { name, address, machineNum, phone } = opts?.extData;
12
+  const { name, address, machineryNum, phone } = opts?.extData;
13 13
 
14 14
   marker.setLabel({
15 15
     direction: 'top',
@@ -18,7 +18,7 @@ export default function getRuralMarker(AMap, map, opts = {}) {
18 18
     <div class='geo-map-rural-box' >
19 19
       <div class="borderBox"><span class='geo-map-rural-text-span borderBox'>名 称</span>:${name}</div>
20 20
       <div class="borderBox"><span class='geo-map-rural-text-span borderBox'>地 址</span>:${address}</div>
21
-      <div class="borderBox">农机数量:${machineNum} 辆</div>
21
+      <div class="borderBox">农机数量:${machineryNum} 辆</div>
22 22
       <div class="borderBox">联系电话:${phone}</div>
23 23
     </div>`,
24 24
   });

+ 2
- 3
src/components/GeoMap/marker.js View File

@@ -18,19 +18,18 @@ export function useMarker(amapRef, map, list) {
18 18
         });
19 19
       });
20 20
     }
21
-  }, [map, list]);
21
+  }, [map, list, amapRef]);
22 22
 
23 23
   return markerListRef;
24 24
 }
25 25
 
26 26
 export function useMarkerVisible(map, markerListRef, typeId) {
27 27
   useEffect(() => {
28
-    console.log(typeId, markerListRef.current);
29 28
     if (!map || !markerListRef.current) return;
30 29
 
31 30
     markerListRef.current.forEach((marker) => {
32 31
       const item = marker.getExtData();
33 32
       marker.setMap(item.typeId === typeId ? map : null);
34 33
     });
35
-  }, [map, typeId]);
34
+  }, [map, markerListRef, typeId]);
36 35
 }

+ 2
- 1
src/components/ScreenBox/ScreenHeader/style.less View File

@@ -42,7 +42,8 @@
42 42
     justify-content: center;
43 43
 
44 44
     & > img {
45
-      height: 50%;
45
+      width: 48%;
46
+      height: 48%;
46 47
     }
47 48
   }
48 49
 

+ 2
- 1
src/components/Upload/UploadImage.jsx View File

@@ -1,9 +1,10 @@
1 1
 import React, { useState } from 'react';
2 2
 import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
3
+import { message } from 'antd';
3 4
 import Upload from './Upload';
4 5
 
5 6
 function beforeUpload(file) {
6
-  const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'||file.type==='image/gif';
7
+  const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/gif';
7 8
   if (!isJpgOrPng) {
8 9
     message.error('请上传 JPG , PNG或GIF 图片!');
9 10
   }

+ 0
- 3
src/pages/JobStatistics/RevenueExpenditure/index.jsx View File

@@ -1,3 +0,0 @@
1
-export default (props) => {
2
-  return <div>收支统计</div>;
3
-};

+ 91
- 0
src/pages/Machinery/GIS/components/WorkListModel.jsx View File

@@ -0,0 +1,91 @@
1
+import {
2
+  Button,
3
+  Modal,
4
+  DatePicker,
5
+} from 'antd';
6
+import { useState, useRef } from 'react';
7
+import PageTable from '@/components/PageTable';
8
+import moment from 'moment';
9
+import { history } from 'umi';
10
+import { getJobList } from '@/services/job'
11
+
12
+const formatterTime = (val) => {
13
+  return val ? moment(val).format('YYYY-MM-DD HH:mm') : '';
14
+};
15
+const { RangePicker } = DatePicker;
16
+export default (props) => {
17
+  const { editModal, onCancel, machineryId } = props
18
+  const actionRef = useRef();
19
+
20
+  const [start, setStartDate] = useState()
21
+  const [end, setEndDate] = useState()
22
+  const handelChange = (date, dateStrings) => {
23
+    setStartDate(dateStrings[0])
24
+    setEndDate(dateStrings[1])
25
+  }
26
+  const Reset = () => {
27
+    setStartDate()
28
+    setEndDate()
29
+    actionRef.current.reload();
30
+  }
31
+  const goDetail = (id) => {
32
+    history.push(`./GIS/detail.jsx?id=` + id);
33
+  }
34
+
35
+  const columns = [
36
+    {
37
+      title: '订单号',
38
+      dataIndex: 'orderNo',
39
+      key: 'orderNo',
40
+      search: false
41
+    },
42
+    {
43
+      title: '农机手',
44
+      dataIndex: 'workerName',
45
+      key: 'workerName',
46
+      search: false
47
+    },
48
+    {
49
+      title: '作业时间',
50
+      dataIndex: 'endDate',
51
+      key: 'endDate',
52
+      render: (t, render) => formatterTime(render.startDate) + ' ~ ' + formatterTime(render.endDate),
53
+      renderFormItem: (_, record) => <RangePicker placeholder={['开始日期', '结束日期']} format='YYYY-MM-DD' onChange={handelChange} />
54
+    },
55
+    {
56
+      title: '操作',
57
+      valueType: 'option',
58
+      render: (_, record) => [
59
+        <Button
60
+          style={{ padding: 0 }}
61
+          type="link"
62
+          key={1}
63
+          onClick={() => goDetail(record.jobId)}
64
+        >
65
+          查看GIS
66
+        </Button>
67
+      ],
68
+    }
69
+  ]
70
+  return (
71
+    <Modal
72
+      forceRender
73
+      width='1024px'
74
+      title='农机GIS列表'
75
+      visible={editModal}
76
+      onCancel={onCancel}
77
+      destroyOnClose={true}
78
+      footer={null}
79
+    >
80
+      <PageTable
81
+        request={getJobList}
82
+        actionRef={actionRef}
83
+        columns={columns}
84
+        rowKey="jobId"
85
+        options={false}
86
+        params={{ machineryId: machineryId, start, end }}
87
+        onReset={Reset}
88
+      />
89
+    </Modal>
90
+  )
91
+}

+ 60
- 0
src/pages/Machinery/GIS/detail.jsx View File

@@ -0,0 +1,60 @@
1
+import { PageHeaderWrapper } from '@ant-design/pro-layout';
2
+import { Card, Button, Descriptions } from 'antd';
3
+import { useEffect, useState } from 'react';
4
+import { getJobDetail, getJobGISDetail } from '@/services/job'
5
+import moment from 'moment';
6
+import { history } from 'umi';
7
+import getCoordinate from '@/utils/mapTogcj02'
8
+import GISMap from '@/components/GISMap';
9
+
10
+const goBack = () => {
11
+  history.goBack();
12
+};
13
+const formatterTime = (val) => {
14
+  return val ? moment(val).format('YYYY-MM-DD HH:mm') : '';
15
+};
16
+export default (props) => {
17
+  const { location } = props;
18
+  const { id } = location.query;
19
+  const [workInfo, setWorkInfo] = useState()
20
+  const [nlocationList, setNewLocationList] = useState()
21
+  useEffect(() => {
22
+    if (id) {
23
+      getJobDetail(id).then((res) => {
24
+        setWorkInfo(res)
25
+        getJobGISDetail({ jobId: id }).then((gisRes => {
26
+          let list, newlocation
27
+          list = gisRes.map(item => {
28
+            newlocation = getCoordinate(item.lng, item.lat);
29
+            return [newlocation.longitude, newlocation.latitude]
30
+          })
31
+          setNewLocationList(list)
32
+        })).catch(err => {
33
+          console.log(err.message);
34
+        })
35
+      }).catch(err => {
36
+        console.log(err.message);
37
+      })
38
+    }
39
+  }, [id])
40
+  return (
41
+    <PageHeaderWrapper extra={[<Button key={id} type="default" onClick={() => goBack()}>
42
+      返回
43
+    </Button>]}>
44
+      <Card title='作业详情'>
45
+        <Descriptions labelStyle={{ justifyContent: 'flex-end', minWidth: '5em' }} >
46
+          <Descriptions.Item label="订单号">{workInfo?.orderNo}</Descriptions.Item>
47
+          <Descriptions.Item label="合作社">{workInfo?.orgName}</Descriptions.Item>
48
+          <Descriptions.Item label="农机">{workInfo?.machineryName}</Descriptions.Item>
49
+          <Descriptions.Item label="农机手">{workInfo?.workerName}</Descriptions.Item>
50
+          <Descriptions.Item label="作业面积">{workInfo?.area}亩</Descriptions.Item>
51
+          <Descriptions.Item label="作业时间">{formatterTime(workInfo?.startDate)}~{formatterTime(workInfo?.endDate)}</Descriptions.Item>
52
+          <Descriptions.Item label="作业地址">{workInfo?.address}</Descriptions.Item>
53
+        </Descriptions>
54
+      </Card>
55
+      <Card style={{ minHeight: '700px', marginTop: '32px' }}>
56
+        <GISMap lineArr={nlocationList} />
57
+      </Card>
58
+    </PageHeaderWrapper>
59
+  );
60
+};

+ 152
- 1
src/pages/Machinery/GIS/index.jsx View File

@@ -1,3 +1,154 @@
1
+import React, { useRef, useEffect, useState } from 'react';
2
+import { Button, Select } from 'antd';
3
+import { PageHeaderWrapper } from '@ant-design/pro-layout';
4
+import PageTable from '@/components/PageTable';
5
+import { getMachineryList } from '@/services/machinery';
6
+import { getMachineryTypeList } from '@/services/machineryType';
7
+import { getCooperativeList } from '@/services/cooperative';
8
+import WorkListModel from './components/WorkListModel';
9
+
10
+const { Option } = Select;
11
+
1 12
 export default (props) => {
2
-  return <div>农机GIS</div>;
13
+  const actionRef = useRef();
14
+  const [machineryTypeList, setMachineryTypeList] = useState([]);
15
+  const [cooperativeList, setCooperativeList] = useState([]);
16
+  const [editModal, setEditModal] = useState(false);
17
+  const [machineryId, setMachineryId] = useState();
18
+
19
+
20
+  const showList = (val) => {
21
+    setMachineryId(val.machineryId)
22
+    setEditModal(true)
23
+  }
24
+  const onCancel = () => {
25
+    setEditModal(false)
26
+  }
27
+  useEffect(() => {
28
+    getCooperativeList({ pageSize: 999 }).then((res) => {
29
+      setCooperativeList(res.records);
30
+    }).catch((err) => {
31
+      console.log(err.message)
32
+    });
33
+    getMachineryTypeList({ pageSize: 999 }).then((res) => {
34
+      setMachineryTypeList(res.records);
35
+    }).catch((err) => {
36
+      console.log(err.message)
37
+    });
38
+  }, []);
39
+  const columns = [
40
+    {
41
+      title: '合作社',
42
+      dataIndex: 'orgId',
43
+      key: 'orgId',
44
+      hideInTable: true,
45
+      renderFormItem: (item, field, form) => {
46
+        return (
47
+          <Select>
48
+            {cooperativeList.map((item) => (
49
+              <Option value={item.orgId} key={item.orgId}>
50
+                {item.name}
51
+              </Option>
52
+            ))}
53
+          </Select>
54
+        )
55
+      }
56
+    },
57
+    {
58
+      title: '名称',
59
+      dataIndex: 'name',
60
+      key: 'name',
61
+    },
62
+    {
63
+      title: '合作社',
64
+      dataIndex: 'orgName',
65
+      key: 'orgName',
66
+      search: false
67
+    },
68
+    {
69
+      title: '农机类型',
70
+      dataIndex: 'typeId',
71
+      key: 'typeId',
72
+      renderFormItem: (item, field, form) => {
73
+        return (
74
+          <Select>
75
+            {machineryTypeList.map((item) => (
76
+              <Option value={item.typeId} key={item.typeId}>
77
+                {item.name}
78
+              </Option>
79
+            ))}
80
+          </Select>
81
+        );
82
+      },
83
+      hideInTable: true,
84
+    },
85
+    {
86
+      title: '农机类型',
87
+      dataIndex: 'typeName',
88
+      key: 'typeName',
89
+      search: false,
90
+    },
91
+    {
92
+      title: '区域',
93
+      dataIndex: 'regionName',
94
+      key: 'regionName',
95
+      search: false,
96
+    },
97
+    {
98
+      title: '农机单价',
99
+      dataIndex: 'price',
100
+      key: 'price',
101
+      render: (t) => t / 100,
102
+      search: false,
103
+    },
104
+    {
105
+      title: '主图',
106
+      dataIndex: 'thumb',
107
+      key: 'thumb',
108
+      width: 150,
109
+      render: (t) => <img width={110} src={t} alt="" />,
110
+      search: false,
111
+    },
112
+    {
113
+      title: '工作状态',
114
+      dataIndex: 'jobStatus',
115
+      key: 'jobStatus',
116
+      search: false,
117
+      render: (_, record) => {
118
+        return record.jobStatus == 1 ? '使用中' : '空闲中';
119
+      },
120
+    },
121
+    {
122
+      title: '状态',
123
+      dataIndex: 'status',
124
+      key: 'status',
125
+      search: false,
126
+      render: (_, record) => {
127
+        return record.status === 1 ? '正常' : '维修中';
128
+      },
129
+    },
130
+    {
131
+      title: '操作',
132
+      valueType: 'option',
133
+      render: (_, record) => [
134
+        <Button style={{ padding: 0 }} type="link" key={1} onClick={() => showList(record)}>
135
+          农机GIS
136
+        </Button>,
137
+      ],
138
+    },
139
+  ];
140
+
141
+  return (
142
+    <PageHeaderWrapper>
143
+      <PageTable
144
+        request={getMachineryList}
145
+        actionRef={actionRef}
146
+        columns={columns}
147
+        rowKey="machineryId"
148
+        options={false}
149
+        scroll={{ x: 1000 }}
150
+      />
151
+      <WorkListModel editModal={editModal} onCancel={onCancel} machineryId={machineryId} />
152
+    </PageHeaderWrapper>
153
+  );
3 154
 };

+ 0
- 59
src/pages/Machinery/GPS/edit.jsx View File

@@ -1,59 +0,0 @@
1
-import { Input, Card, Select, Button, message } from 'antd';
2
-import { useEffect, useState } from 'react';
3
-import { Form } from 'antd';
4
-import { history } from 'umi';
5
-import ProCard from '@ant-design/pro-card';
6
-
7
-const { Option } = Select;
8
-const goBack = () => {
9
-  history.goBack();
10
-};
11
-const FormItem = Form.Item;
12
-export default (props) => {
13
-  const [form] = Form.useForm();
14
-  const [loading, setLoading] = useState(false);
15
-
16
-  const formItemLayout = {
17
-    //布局
18
-    labelCol: { span: 6 },
19
-    wrapperCol: { span: 14 },
20
-  };
21
-
22
-  const Submit = (values) => {
23
-    setLoading(false);
24
-  };
25
-
26
-  return (
27
-    <Card>
28
-      <ProCard tabs={{ type: 'card' }} style={{ marginTop: '16px' }}>
29
-        <ProCard.TabPane key={1} tab="设备管理">
30
-          <Form {...formItemLayout} onFinish={Submit} form={form}>
31
-            <FormItem
32
-              label="设备ID"
33
-              name="shopName"
34
-              rules={[{ required: true, message: '请输入' }]}
35
-            >
36
-              <Input placeholder="请输入" style={{ width: '350px' }} />
37
-            </FormItem>
38
-            <FormItem label="设备号" name="title" rules={[{ required: true, message: '请输入' }]}>
39
-              <Input placeholder="请输入" style={{ width: '350px' }} />
40
-            </FormItem>
41
-            <FormItem label=" " colon={false}>
42
-              <Button type="default" onClick={() => goBack()}>
43
-                返回
44
-              </Button>
45
-              <Button
46
-                type="primary"
47
-                loading={loading}
48
-                htmlType="Submit"
49
-                style={{ marginLeft: '4em' }}
50
-              >
51
-                保存
52
-              </Button>
53
-            </FormItem>
54
-          </Form>
55
-        </ProCard.TabPane>
56
-      </ProCard>
57
-    </Card>
58
-  );
59
-};

+ 0
- 99
src/pages/Machinery/GPS/index.jsx View File

@@ -1,99 +0,0 @@
1
-import { history, Link } from 'umi';
2
-import { useRef } from 'react';
3
-import { Button, message, Popconfirm } from 'antd';
4
-import { PlusOutlined } from '@ant-design/icons';
5
-import { PageHeaderWrapper } from '@ant-design/pro-layout';
6
-import ProTable, { TableDropdown } from '@ant-design/pro-table';
7
-
8
-export default (props) => {
9
-  const dataSource = [
10
-    {
11
-      id: 9,
12
-      key: '1',
13
-      name: '胡彦斌',
14
-      age: 32,
15
-      status: 1,
16
-      zz: '西湖区湖底公园1号',
17
-    },
18
-  ];
19
-
20
-  // 测试内容👆-------------------------
21
-
22
-  const actionRef = useRef();
23
-  const gotoDetail = (id) => {
24
-    history.push(`./GPS/edit.jsx`);
25
-  };
26
-
27
-  const handleDelete = (e) => {
28
-    deleteNote(e.noteId).then((res) => {
29
-      message.success('删除成功');
30
-      actionRef.current.reload();
31
-    }).catch((err) => {
32
-      console.log(err.message)
33
-    });
34
-  };
35
-
36
-  const actions = () => [
37
-    <Button key="add" type="primary" icon={<PlusOutlined />} onClick={() => gotoDetail()}>
38
-      新增
39
-    </Button>,
40
-  ];
41
-  const columns = [
42
-    {
43
-      title: 'ID',
44
-      key: 'zz',
45
-      dataIndex: 'zz',
46
-    },
47
-    {
48
-      title: '设备号',
49
-      dataIndex: 'name',
50
-      key: 'name',
51
-    },
52
-    {
53
-      title: '状态',
54
-      dataIndex: 'status',
55
-      // initialValue: 'all',
56
-      key: 'status',
57
-      valueEnum: {
58
-        0: { text: '已启用', status: 'Success' },
59
-        1: { text: '已禁用', status: 'Error' },
60
-      },
61
-    },
62
-
63
-    {
64
-      title: '操作',
65
-      valueType: 'option',
66
-      key: 'option',
67
-      ellipsis: true,
68
-      width: 200,
69
-      render: (_, record) => [
70
-        <Link key={2} to={`./GPS/edit.jsx`}>
71
-          编辑
72
-        </Link>,
73
-        <Popconfirm
74
-          key={3}
75
-          title="您是否确认删除 ?"
76
-          onConfirm={() => handleDelete(record)}
77
-          okText="确定"
78
-          cancelText="取消"
79
-        >
80
-          <a href="#">删除</a>
81
-        </Popconfirm>,
82
-      ],
83
-    },
84
-  ];
85
-
86
-  return (
87
-    <PageHeaderWrapper>
88
-      {/* <ProTable
89
-        dataSource={dataSource}
90
-        columns={columns}
91
-        // request={getNoteList} 请求
92
-        // rowKey="noteId"
93
-        options={false}
94
-        toolBarRender={actions}
95
-        actionRef={actionRef}
96
-      /> */}
97
-    </PageHeaderWrapper>
98
-  );
99
-};

+ 198
- 0
src/pages/Machinery/Machinery/Edit/components/BasicInfo.jsx View File

@@ -0,0 +1,198 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { history } from 'umi';
3
+import { Form, Input, DatePicker, Select, Button, message } from 'antd';
4
+import moment from 'moment';
5
+import ExtendContent from '@/components/ExtendContent';
6
+import { UploadImage, UploadImageList } from '@/components/Upload';
7
+import Money from '@/components/Money';
8
+import { addMachinery, updateMachinery, getMachineryDetail } from '@/services/machinery';
9
+import { getMachineryTypeList } from '@/services/machineryType';
10
+import { getRegionList } from '@/services/region';
11
+import { getCooperativeList } from '@/services/cooperative';
12
+
13
+const { Option } = Select;
14
+const FormItem = Form.Item;
15
+const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 14 } };
16
+
17
+const goBack = () => {
18
+  history.goBack();
19
+};
20
+
21
+export default (props) => {
22
+  const { id, onSuccess } = props;
23
+
24
+  const [form] = Form.useForm();
25
+  const [loading, setLoading] = useState(false);
26
+  const [imageList, setImageList] = useState([]);
27
+  //农机类型列表
28
+  const [machineryTypeList, setMachineryTypeList] = useState([]);
29
+  //区域列表
30
+  const [regionList, setRegionList] = useState([]);
31
+  //合作社列表
32
+  const [cooperativeList, setCooperativeList] = useState([]);
33
+
34
+  const onSubmit = (data) => {
35
+    var newData = { ...data };
36
+    if (data.buyDate) {
37
+      newData = { ...data, buyDate: data.buyDate.format('YYYY-MM-DD HH:mm:ss') };
38
+    }
39
+    setLoading(true);
40
+    if (id) {
41
+      updateMachinery(id, newData)
42
+        .then(() => {
43
+          setLoading(false);
44
+          message.success('数据更新成功');
45
+          goBack();
46
+        })
47
+        .catch((err) => {
48
+          setLoading(false);
49
+          message.error(err.message || err);
50
+        });
51
+    } else {
52
+      addMachinery(newData)
53
+        .then((res) => {
54
+          setLoading(false);
55
+          message.success('数据保存成功');
56
+          history.replace(`./Edit?id=${res.machineryId}`);
57
+        })
58
+        .catch((err) => {
59
+          setLoading(false);
60
+          message.error(err.message || err);
61
+        });
62
+    }
63
+  };
64
+
65
+  const imageInput = (image) => {
66
+    return {
67
+      uid: image.imageId,
68
+      url: image.url,
69
+    };
70
+  };
71
+
72
+  const imageOutput = (image) => {
73
+    return {
74
+      imageId: image?.raw?.imageId,
75
+      targetId: id,
76
+      url: image.url,
77
+    };
78
+  };
79
+
80
+  useEffect(() => {
81
+    getMachineryTypeList({ pageSize: 500 })
82
+      .then((res) => {
83
+        setMachineryTypeList(res.records);
84
+      })
85
+      .catch((err) => {
86
+        console.log(err.message);
87
+      });
88
+    getRegionList({ pageSize: 500 })
89
+      .then((res) => {
90
+        setRegionList(res.records);
91
+      })
92
+      .catch((err) => {
93
+        console.log(err.message);
94
+      });
95
+    getCooperativeList({ pageSize: 500 })
96
+      .then((res) => {
97
+        setCooperativeList(res.records);
98
+      })
99
+      .catch((err) => {
100
+        console.log(err.message);
101
+      });
102
+  }, []);
103
+
104
+  useEffect(() => {
105
+    if (id) {
106
+      //编辑时获取基本信息内容
107
+      getMachineryDetail(id)
108
+        .then((res) => {
109
+          form.setFieldsValue({
110
+            ...res,
111
+            buyDate: res.buyDate ? moment(res.buyDate, 'YYYY-MM-DD') : null,
112
+          });
113
+        })
114
+        .catch((err) => {
115
+          console.log(err.message);
116
+        });
117
+    }
118
+  }, [id]);
119
+
120
+  return (
121
+    <Form {...formItemLayout} onFinish={onSubmit} form={form}>
122
+      <FormItem label="农机名" name="name" rules={[{ required: true, message: '请输入农机名' }]}>
123
+        <Input placeholder="请输入农机名" style={{ width: '350px' }} />
124
+      </FormItem>
125
+      <FormItem
126
+        label="农机类型"
127
+        name="typeId"
128
+        rules={[{ required: true, message: '请选择农机类型' }]}
129
+      >
130
+        <Select style={{ width: '350px' }}>
131
+          {machineryTypeList.map((item) => (
132
+            <Option value={item.typeId} key={item.typeId}>
133
+              {item.name}
134
+            </Option>
135
+          ))}
136
+        </Select>
137
+      </FormItem>
138
+      <FormItem label="主图" name="thumb" rules={[{ required: true, message: '请选择主图' }]}>
139
+        <UploadImage />
140
+      </FormItem>
141
+      <FormItem label="农机banner图集" name="images">
142
+        <UploadImageList
143
+          value={imageList}
144
+          onChange={setImageList}
145
+          input={imageInput}
146
+          output={imageOutput}
147
+        />
148
+      </FormItem>
149
+      <FormItem label="区域" name="regionId" rules={[{ required: true, message: '请选择区域' }]}>
150
+        <Select style={{ width: '350px' }}>
151
+          {regionList.map((item) => (
152
+            <Option value={item.regionId} key={item.regionId}>
153
+              {item.name}
154
+            </Option>
155
+          ))}
156
+        </Select>
157
+      </FormItem>
158
+      <FormItem
159
+        label="归属合作社"
160
+        name="orgId"
161
+        rules={[{ required: true, message: '请选择归属合作社' }]}
162
+      >
163
+        <Select style={{ width: '350px' }}>
164
+          {cooperativeList.map((item) => (
165
+            <Option value={item.orgId} key={item.orgId}>
166
+              {item.name}
167
+            </Option>
168
+          ))}
169
+        </Select>
170
+      </FormItem>
171
+      <FormItem label="单价" name="price" rules={[{ required: true, message: '请输入价格' }]}>
172
+        <Money style={{ width: '350px' }} />
173
+      </FormItem>
174
+      <FormItem label="购买时间" name="buyDate">
175
+        <DatePicker format="YYYY-MM-DD" style={{ width: '350px' }} />
176
+      </FormItem>
177
+      <FormItem label="状态" name="status" rules={[{ required: true, message: '请选择' }]}>
178
+        <Select placeholder="请选择农机状态" style={{ width: '350px' }}>
179
+          <Option value={1}>正常</Option>
180
+          <Option value={0}>维修</Option>
181
+        </Select>
182
+      </FormItem>
183
+      {id && (
184
+        <FormItem label="详细信息" colon={false}>
185
+          <ExtendContent targetType="machinery" targetId={id} onCancel={goBack} />
186
+        </FormItem>
187
+      )}
188
+      <FormItem label=" " colon={false}>
189
+        <Button type="default" onClick={goBack}>
190
+          返回
191
+        </Button>
192
+        <Button type="primary" loading={loading} htmlType="submit" style={{ marginLeft: '4em' }}>
193
+          保存
194
+        </Button>
195
+      </FormItem>
196
+    </Form>
197
+  );
198
+};

+ 132
- 0
src/pages/Machinery/Machinery/Edit/components/DeviceInfo.jsx View File

@@ -0,0 +1,132 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { history } from 'umi';
3
+import { Form, Drawer, Select, InputNumber, message, Button } from 'antd';
4
+import { getDeviceDetail, addDevice } from '@/services/device';
5
+import DeviceList from './DeviceList';
6
+import { useMemo } from 'react';
7
+
8
+const { Option } = Select;
9
+const FormItem = Form.Item;
10
+const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 14 } };
11
+
12
+const goBack = () => {
13
+  history.goBack();
14
+};
15
+
16
+export default (props) => {
17
+  const { machineryId } = props;
18
+
19
+  const [form] = Form.useForm();
20
+  const [loading, setLoading] = useState(false);
21
+  const [visible, setVisible] = useState(false);
22
+  const [deviceDetail, setDeviceDetail] = useState();
23
+  const [hatcId, setHatcId] = useState();
24
+
25
+  const onSubmit = (data) => {
26
+    if (!deviceDetail || !deviceDetail.deviceNo) {
27
+      message.error('请先绑定设备');
28
+      return;
29
+    }
30
+
31
+    const apiConfig = JSON.stringify({
32
+      ...data,
33
+      deviceId: hatcId,
34
+    });
35
+
36
+    // 表单的提交, 实际上是把 form 内容 + 其余字段 融合一起提交
37
+    setLoading(true);
38
+    addDevice({ ...deviceDetail, machineryId, apiConfig })
39
+      .then((res) => {
40
+        message.success('保存成功!');
41
+        setLoading(false);
42
+        goBack();
43
+      })
44
+      .catch((err) => {
45
+        setLoading(false);
46
+        console.log(err.message);
47
+      });
48
+  };
49
+
50
+  const handleCheck = (terminalId, hatcDevice) => {
51
+    setHatcId(hatcDevice.deviceId);
52
+    setDeviceDetail({
53
+      ...(deviceDetail || {}),
54
+      deviceNo: terminalId,
55
+      deviceType: hatcDevice.productKey,
56
+    });
57
+    setVisible(false);
58
+  };
59
+
60
+  useEffect(() => {
61
+    if (machineryId) {
62
+      //获取设备信息内容
63
+      getDeviceDetail(machineryId).then((res) => {
64
+        if (!res) return;
65
+
66
+        setDeviceDetail(res);
67
+        const apiConfig = JSON.parse(res.apiConfig) || {};
68
+
69
+        // 表单内容只是整个数据的一个 JSON 字段
70
+        form.setFieldsValue({
71
+          netType: apiConfig.netType,
72
+          channel: apiConfig.channel,
73
+        });
74
+      });
75
+    }
76
+  }, [machineryId, form]);
77
+
78
+  const deviceName = useMemo(() => {
79
+    if (!deviceDetail) return '未绑定';
80
+
81
+    return `${deviceDetail.deviceType}-${deviceDetail.deviceNo}`;
82
+  }, [deviceDetail]);
83
+
84
+  return (
85
+    <>
86
+      <Form {...formItemLayout} onFinish={onSubmit} form={form}>
87
+        <FormItem label="设备">
88
+          <Button type="link" onClick={() => setVisible(true)}>
89
+            {deviceName}
90
+          </Button>
91
+        </FormItem>
92
+        <FormItem
93
+          label="通道号"
94
+          name="channel"
95
+          rules={[{ required: true, message: '请输入通道号' }]}
96
+        >
97
+          <InputNumber min={1} placeholder="请输入通道号" style={{ width: '350px' }} />
98
+        </FormItem>
99
+        <FormItem
100
+          label="网络类型"
101
+          name="netType"
102
+          rules={[{ required: true, message: '请选择网络类型' }]}
103
+        >
104
+          <Select placeholder="请选择网络类型" style={{ width: '350px' }}>
105
+            <Option value={0}>内网</Option>
106
+            <Option value={1}>电信</Option>
107
+            <Option value={2}>移动</Option>
108
+            <Option value={3}>联通</Option>
109
+          </Select>
110
+        </FormItem>
111
+        <FormItem label=" " colon={false}>
112
+          <Button type="default" onClick={goBack}>
113
+            返回
114
+          </Button>
115
+          <Button type="primary" loading={loading} htmlType="submit" style={{ marginLeft: '4em' }}>
116
+            保存
117
+          </Button>
118
+        </FormItem>
119
+      </Form>
120
+      <Drawer
121
+        title="设备列表"
122
+        width={500}
123
+        closable={false}
124
+        onClose={() => setVisible(false)}
125
+        visible={visible}
126
+        destroyOnClose
127
+      >
128
+        <DeviceList value={deviceDetail && deviceDetail.deviceNo} onChange={handleCheck} />
129
+      </Drawer>
130
+    </>
131
+  );
132
+};

+ 113
- 0
src/pages/Machinery/Machinery/Edit/components/DeviceList.jsx View File

@@ -0,0 +1,113 @@
1
+import { useState, useEffect } from 'react';
2
+import { Button, Card, Descriptions, Input, List } from 'antd';
3
+import { getHatcDeviceList } from '@/services/device';
4
+import selectedImg from '@/assets/selectedImg.png';
5
+
6
+const { Search } = Input;
7
+
8
+// 列表是海康设备
9
+// props 传过来的是映射ID
10
+
11
+export default (props) => {
12
+  const { value, onChange } = props;
13
+
14
+  const [loading, setLoading] = useState(false);
15
+  const [hatcDeviceList, setHatcDeviceList] = useState([]); // 所有数据
16
+  const [list, setList] = useState([]); // 页面展示数据
17
+  const [checked, setChecked] = useState();
18
+
19
+  // 搜索
20
+  const onSearch = (val) => {
21
+    if (val == '' || val === undefined || val === null) {
22
+      setList(hatcDeviceList);
23
+    } else {
24
+      setList(hatcDeviceList.filter((x) => x.terminalId.toLowerCase().includes(val.toLowerCase())));
25
+    }
26
+  };
27
+
28
+  //选中设备
29
+  const handleSelect = (item) => {
30
+    setChecked(item);
31
+  };
32
+
33
+  // 提交
34
+  const handleSubmit = () => {
35
+    onChange(checked.terminalId, checked);
36
+  };
37
+
38
+  // 过滤列表
39
+  useEffect(() => {
40
+    setLoading(true);
41
+    getHatcDeviceList({ pageSize: 500 })
42
+      .then((res) => {
43
+        setHatcDeviceList(res.records);
44
+        setList(res.records);
45
+        setLoading(false);
46
+      })
47
+      .catch(() => {
48
+        setLoading(false);
49
+      });
50
+  }, []);
51
+
52
+  useEffect(() => {
53
+    if (!hatcDeviceList || !hatcDeviceList.length) return;
54
+    if (!value) return;
55
+
56
+    if (!checked || value !== checked.terminalId) {
57
+      const target = hatcDeviceList.filter((x) => x.terminalId === value)[0];
58
+      setChecked(target);
59
+    }
60
+  }, [value, checked, hatcDeviceList]);
61
+
62
+  return (
63
+    <div style={{ display: 'flex', height: '100%', flexDirection: 'column' }}>
64
+      <Search
65
+        placeholder="请输入终端ID"
66
+        allowClear
67
+        enterButton="搜索"
68
+        size="middle"
69
+        onSearch={onSearch}
70
+        style={{ padding: '24px' }}
71
+      />
72
+      <List
73
+        split={false}
74
+        style={{ padding: '12px 0', flex: 1, overflowY: 'auto', background: 'rgb(240,242,245)' }}
75
+      >
76
+        {list.map((item) => (
77
+          <List.Item key={item.deviceId} onClick={() => handleSelect(item)}>
78
+            <Card className="listCard" hoverable>
79
+              <Descriptions
80
+                labelStyle={{ width: '72px', display: 'inline-block', textAlign: 'end' }}
81
+              >
82
+                <Descriptions.Item span={3} label="型号名称">
83
+                  {item.modelName}
84
+                </Descriptions.Item>
85
+                <Descriptions.Item span={3} label="协议">
86
+                  {item.protocol}
87
+                </Descriptions.Item>
88
+                <Descriptions.Item span={3} label="终端ID">
89
+                  {item.terminalId}
90
+                </Descriptions.Item>
91
+                <Descriptions.Item span={3} label="通道列表">
92
+                  {item.deviceChannelList}
93
+                </Descriptions.Item>
94
+              </Descriptions>
95
+              {checked && checked.deviceId === item.deviceId && <img src={selectedImg} />}
96
+            </Card>
97
+          </List.Item>
98
+        ))}
99
+      </List>
100
+      <div style={{ padding: '24px' }}>
101
+        <Button
102
+          type="primary"
103
+          style={{ float: 'right' }}
104
+          loading={loading}
105
+          onClick={handleSubmit}
106
+          disabled={!checked}
107
+        >
108
+          确定
109
+        </Button>
110
+      </div>
111
+    </div>
112
+  );
113
+};

+ 5
- 370
src/pages/Machinery/Machinery/Edit/index.jsx View File

@@ -1,386 +1,21 @@
1
-import { useState, useEffect } from 'react';
2
-import { history } from 'umi';
3
-import { Form, Input, Drawer, DatePicker, Select, InputNumber, message, Button, List, Card, Descriptions } from 'antd';
4 1
 import ProCard from '@ant-design/pro-card';
5 2
 import { PageHeaderWrapper } from '@ant-design/pro-layout';
6
-import moment from 'moment';
7
-import ExtendContent from '@/components/ExtendContent';
8
-import { UploadImage, UploadImageList } from '@/components/Upload';
9
-import Money from '@/components/Money';
10
-import { addMachinery, updateMachinery, getMachineryDetail } from '@/services/machinery';
11
-import { getMachineryTypeList } from '@/services/machineryType';
12
-import { getRegionList } from '@/services/region';
13
-import { getDeviceList, getdeviceDetail, getTerminalDeviceList, addDevice } from '@/services/device';
14
-import { getCooperativeList } from '@/services/cooperative';
15
-import selectedImg from '@/assets/selectedImg.png'
16
-import './style.less'
3
+import BasicInfo from './components/BasicInfo';
4
+import DeviceInfo from './components/DeviceInfo';
5
+import './style.less';
17 6
 
18
-const { Option } = Select;
19
-const { Search } = Input;
20
-const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 14 } };
21
-
22
-const goBack = () => {
23
-  history.goBack();
24
-};
25
-const FormItem = Form.Item;
26 7
 export default (props) => {
27 8
   const { location } = props;
28 9
   const { id } = location.query;
29
-  const [form] = Form.useForm();
30
-  const [loading, setLoading] = useState(false);
31
-  const [imageList, setImageList] = useState([]);
32
-  //农机类型列表
33
-  const [machineryTypeList, setMachineryTypeList] = useState([]);
34
-  //区域列表
35
-  const [regionList, setRegionList] = useState([]);
36
-  //合作社列表
37
-  const [cooperativeList, setCooperativeList] = useState([]);
38
-
39
-  const Submit = (data) => {
40
-    var newData = { ...data }
41
-    if (data.buyDate) {
42
-      newData = { ...data, buyDate: data.buyDate.format('YYYY-MM-DD HH:mm:ss') };
43
-    }
44
-    setLoading(true);
45
-    if (id) {
46
-      updateMachinery(id, newData)
47
-        .then(() => {
48
-          setLoading(false);
49
-          message.success('数据更新成功');
50
-          goBack();
51
-        })
52
-        .catch((err) => {
53
-          setLoading(false);
54
-          message.error(err.message || err);
55
-        });
56
-    } else {
57
-      addMachinery(newData)
58
-        .then((res) => {
59
-          setLoading(false);
60
-          message.success('数据保存成功');
61
-          history.replace(`./Edit?id=${res.machineryId}`)
62
-        })
63
-        .catch((err) => {
64
-          setLoading(false);
65
-          message.error(err.message || err);
66
-        });
67
-    }
68
-  };
69
-
70
-  const imageInput = (image) => {
71
-    return {
72
-      uid: image.imageId,
73
-      url: image.url,
74
-    };
75
-  };
76
-
77
-  const imageOutput = (image) => {
78
-    return {
79
-      imageId: image?.raw?.imageId,
80
-      targetId: id,
81
-      url: image.url,
82
-    };
83
-  };
84
-
85
-
86
-  //设备信息
87
-  const [deviceForm] = Form.useForm();
88
-  const [visible, setVisible] = useState(false);
89
-  const [terminalId, setTerminalId] = useState();
90
-  //设备列表
91
-  const [deviceList, setDeviceList] = useState([]);
92
-  const [device, setDevice] = useState();
93
-  const [bind, setBind] = useState(false);
94
-  const [deviceLoading, setDeviceLoading] = useState(false);
95
-  const [deviceDetail, setDeviceDetail] = useState();
96
-
97
-  //弹出设备列表抽屉
98
-  const changeCamera = () => {
99
-    if (device != null) {
100
-      getTerminalDeviceList(device.deviceId).then((res) => {
101
-        setDeviceList([res]);
102
-        setVisible(true);
103
-      })
104
-    } else {
105
-      setVisible(true);
106
-    }
107
-
108
-  }
109
-  const handleClose = () => {
110
-    setVisible(false);
111
-  }
112
-  const onSearch = (val) => {
113
-    if (val == '') {
114
-      getDeviceList({ pageSize: 500 }).then((res) => {
115
-        setDeviceList(res.records);
116
-      })
117
-    } else {
118
-      setTerminalId(val)
119
-    }
120
-  }
121
-  //选中设备
122
-  const handleSelect = (item) => {
123
-    setDevice(item);
124
-  }
125
-  const handleOk = () => {
126
-    if (device != null) {
127
-      setBind(true)
128
-    }
129
-    handleClose();
130
-  }
131
-  const submitDevice = (data) => {
132
-    if (!bind) {
133
-      message.info('请绑定摄像头');
134
-      return;
135
-    }
136
-    let obj = {
137
-      deviceId: device.deviceId,
138
-      channel: data.channel,
139
-      netType: data.netType
140
-    }
141
-    let config = JSON.stringify(obj);
142
-    setDeviceLoading(true);
143
-    addDevice({ ...deviceDetail, machineryId: id, apiConfig: config }).then((res) => {
144
-      message.success('保存成功!');
145
-      setDeviceLoading(false);
146
-      goBack();
147
-    }).catch((err) => {
148
-      setDeviceLoading(false);
149
-      console.log(err.message);
150
-    })
151
-  }
152
-  useEffect(() => {
153
-    getDeviceList({ terminalId: terminalId, pageSize: 500 }).then((res) => {
154
-      setDeviceList(res.records);
155
-    })
156
-  }, [terminalId])
157
-
158
-  useEffect(() => {
159
-    getMachineryTypeList({ pageSize: 500 }).then((res) => {
160
-      setMachineryTypeList(res.records);
161
-    }).catch((err) => {
162
-      console.log(err.message)
163
-    });
164
-    getRegionList({ pageSize: 500 }).then((res) => {
165
-      setRegionList(res.records);
166
-    }).catch((err) => {
167
-      console.log(err.message)
168
-    });
169
-    getCooperativeList({ pageSize: 500 }).then((res) => {
170
-      setCooperativeList(res.records);
171
-    }).catch((err) => {
172
-      console.log(err.message)
173
-    });
174
-  }, [])
175
-
176
-
177
-  useEffect(() => {
178
-    if (id) {
179
-      //编辑时获取基本信息内容
180
-      getMachineryDetail(id).then((res) => {
181
-        form.setFieldsValue({ ...res, buyDate: res.buyDate ? moment(res.buyDate, 'YYYY-MM-DD') : null });
182
-      }).catch((err) => {
183
-        console.log(err.message)
184
-      });
185
-      //获取设备信息内容
186
-      getdeviceDetail(id).then((res) => {
187
-        setDeviceDetail(res);
188
-        if (res) {
189
-          //json字符串转普通对象
190
-          let confit = JSON.parse(res.apiConfig)
191
-          deviceForm.setFieldsValue(confit);
192
-          if (res && res.deviceId != null) {
193
-            //获取绑定设备详情
194
-            getTerminalDeviceList(confit.deviceId).then((res) => {
195
-              setDevice(res);
196
-              setBind(true)
197
-            })
198
-          }
199
-        }
200
-      })
201
-    }
202
-  }, [id]);
203 10
 
204 11
   return (
205 12
     <PageHeaderWrapper>
206 13
       <ProCard tabs={{ type: 'card' }} style={{ minHeight: '700px' }}>
207 14
         <ProCard.TabPane key={1} tab="基本信息">
208
-          <Form {...formItemLayout} onFinish={Submit} form={form}>
209
-            <FormItem
210
-              label="农机名"
211
-              name="name"
212
-              rules={[{ required: true, message: '请输入农机名' }]}
213
-            >
214
-              <Input placeholder="请输入农机名" style={{ width: '350px' }} />
215
-            </FormItem>
216
-            <FormItem
217
-              label="农机类型"
218
-              name="typeId"
219
-              rules={[{ required: true, message: '请选择农机类型' }]}
220
-            >
221
-              <Select style={{ width: '350px' }}>
222
-                {machineryTypeList.map((item) => (
223
-                  <Option value={item.typeId} key={item.typeId}>
224
-                    {item.name}
225
-                  </Option>
226
-                ))}
227
-              </Select>
228
-            </FormItem>
229
-            <FormItem label="主图" name="thumb" rules={[{ required: true, message: '请选择主图' }]}>
230
-              <UploadImage />
231
-            </FormItem>
232
-            <FormItem label="农机banner图集" name="images">
233
-              <UploadImageList
234
-                value={imageList}
235
-                onChange={setImageList}
236
-                input={imageInput}
237
-                output={imageOutput}
238
-              />
239
-            </FormItem>
240
-            <FormItem
241
-              label="区域"
242
-              name="regionId"
243
-              rules={[{ required: true, message: '请选择区域' }]}
244
-            >
245
-              <Select style={{ width: '350px' }}>
246
-                {regionList.map((item) => (
247
-                  <Option value={item.regionId} key={item.regionId}>
248
-                    {item.name}
249
-                  </Option>
250
-                ))}
251
-              </Select>
252
-            </FormItem>
253
-            <FormItem
254
-              label="归属合作社"
255
-              name="orgId"
256
-              rules={[{ required: true, message: '请选择归属合作社' }]}
257
-            >
258
-              <Select style={{ width: '350px' }}>
259
-                {cooperativeList.map((item) => (
260
-                  <Option value={item.orgId} key={item.orgId}>
261
-                    {item.name}
262
-                  </Option>
263
-                ))}
264
-              </Select>
265
-            </FormItem>
266
-            <FormItem label="单价" name="price" rules={[{ required: true, message: '请输入价格' }]}>
267
-              <Money style={{ width: '350px' }} />
268
-            </FormItem>
269
-            <FormItem label="购买时间" name="buyDate">
270
-              <DatePicker format="YYYY-MM-DD" style={{ width: '350px' }} />
271
-            </FormItem>
272
-            <FormItem label="状态" name="status" rules={[{ required: true, message: '请选择' }]}>
273
-              <Select placeholder="请选择农机状态" style={{ width: '350px' }}>
274
-                <Option value={1}>正常</Option>
275
-                <Option value={0}>维修</Option>
276
-              </Select>
277
-            </FormItem>
278
-            {id && (
279
-              <FormItem label="详细信息" colon={false}>
280
-                <ExtendContent targetType="machinery" targetId={id} onCancel={goBack} />
281
-              </FormItem>
282
-            )}
283
-            <FormItem label=" " colon={false}>
284
-              <Button type="default" onClick={goBack}>
285
-                返回
286
-              </Button>
287
-              <Button
288
-                type="primary"
289
-                loading={loading}
290
-                htmlType="submit"
291
-                style={{ marginLeft: '4em' }}
292
-              >
293
-                保存
294
-              </Button>
295
-            </FormItem>
296
-          </Form>
15
+          <BasicInfo id={id} />
297 16
         </ProCard.TabPane>
298 17
         <ProCard.TabPane key={2} disabled={!id} tab="设备信息">
299
-          <Form {...formItemLayout} onFinish={submitDevice} form={deviceForm}>
300
-            <FormItem label='摄像头'  >
301
-              <Button type='link' onClick={changeCamera}>{bind ? '已绑定' : '未绑定'}</Button>
302
-            </FormItem>
303
-            <FormItem
304
-              label="通道号"
305
-              name='channel'
306
-              rules={[{ required: true, message: '请输入通道号' }]}
307
-            >
308
-              <InputNumber min={1} placeholder="请输入通道号" style={{ width: '350px' }} />
309
-            </FormItem>
310
-            <FormItem
311
-              label="网络类型"
312
-              name='netType'
313
-              rules={[{ required: true, message: '请选择网络类型' }]}
314
-            >
315
-              <Select placeholder="请选择网络类型" style={{ width: '350px' }}>
316
-                <Option value={0}>内网</Option>
317
-                <Option value={1}>电信</Option>
318
-                <Option value={2}>移动</Option>
319
-                <Option value={3}>联通</Option>
320
-              </Select>
321
-            </FormItem>
322
-            <FormItem label=" " colon={false}>
323
-              <Button type="default" onClick={goBack}>
324
-                返回
325
-              </Button>
326
-              <Button
327
-                type="primary"
328
-                loading={deviceLoading}
329
-                htmlType="submit"
330
-                style={{ marginLeft: '4em' }}
331
-              >
332
-                保存
333
-              </Button>
334
-            </FormItem>
335
-          </Form>
336
-          <Drawer
337
-            title="摄像头列表"
338
-            width={500}
339
-            closable={false}
340
-            onClose={handleClose}
341
-            visible={visible}
342
-          >
343
-            <div style={{ display: 'flex', height: '100%', flexDirection: 'column' }}>
344
-              <Search
345
-                placeholder="请输入终端ID"
346
-                allowClear
347
-                enterButton="搜索"
348
-                size="middle"
349
-                onSearch={onSearch}
350
-                style={{ padding: '24px' }}
351
-              />
352
-              <List split={false} style={{ padding: '12px 0', flex: 1, overflowY: 'auto', background: 'rgb(240,242,245)' }}>
353
-                {
354
-                  deviceList.map(item =>
355
-                    <List.Item key={item.deviceId} onClick={() => handleSelect(item)}>
356
-                      <Card className='listCard' hoverable>
357
-                        <Descriptions labelStyle={{ width: '72px', display: 'inline-block', textAlign: 'end' }} >
358
-                          <Descriptions.Item span={3} label='型号名称'>{item.modelName}</Descriptions.Item>
359
-                          <Descriptions.Item span={3} label='协议'>{item.protocol}</Descriptions.Item>
360
-                          <Descriptions.Item span={3} label='终端ID'>{item.terminalId}</Descriptions.Item>
361
-                          <Descriptions.Item span={3} label='通道列表'>{item.deviceChannelList}</Descriptions.Item>
362
-                        </Descriptions>
363
-                        {
364
-                          device && item.deviceId == device.deviceId && <img src={selectedImg} />
365
-                        }
366
-                      </Card>
367
-                    </List.Item>
368
-                  )
369
-                }
370
-
371
-              </List>
372
-              <div style={{ padding: '24px' }}>
373
-                <Button
374
-                  type="primary"
375
-                  style={{ float: 'right' }}
376
-                  loading={loading}
377
-                  onClick={handleOk}
378
-                >
379
-                  确定
380
-                </Button>
381
-              </div>
382
-            </div>
383
-          </Drawer>
18
+          <DeviceInfo machineryId={id} />
384 19
         </ProCard.TabPane>
385 20
       </ProCard>
386 21
     </PageHeaderWrapper>

+ 20
- 8
src/pages/Machinery/MachineryType/index.jsx View File

@@ -41,7 +41,7 @@ export default (props) => {
41 41
             actionRef.current.reload();
42 42
           })
43 43
           .catch((err) => {
44
-            console.log(err.message)
44
+            console.log(err.message);
45 45
           });
46 46
       },
47 47
     });
@@ -53,12 +53,14 @@ export default (props) => {
53 53
   };
54 54
 
55 55
   const handleDelete = (val) => {
56
-    deleteMachineryType(val).then(() => {
57
-      message.success('删除成功');
58
-      actionRef.current.reload();
59
-    }).catch((err) => {
60
-      console.log(err.message)
61
-    });
56
+    deleteMachineryType(val)
57
+      .then(() => {
58
+        message.success('删除成功');
59
+        actionRef.current.reload();
60
+      })
61
+      .catch((err) => {
62
+        console.log(err.message);
63
+      });
62 64
   };
63 65
 
64 66
   const Submit = (data) => {
@@ -159,9 +161,19 @@ export default (props) => {
159 161
         footer={null}
160 162
       >
161 163
         <Form {...formItemLayout} onFinish={Submit} form={form}>
162
-          <FormItem label="分类名" name="name">
164
+          <FormItem label="分类名" name="name" rules={[{ required: true, message: '请选择' }]}>
163 165
             <Input placeholder="请输入分类名" />
164 166
           </FormItem>
167
+          <FormItem
168
+            label="是否大屏展示"
169
+            name="screenStatis"
170
+            rules={[{ required: true, message: '请选择' }]}
171
+          >
172
+            <Select placeholder="请选择是否大屏展示">
173
+              <Option value={0}>否</Option>
174
+              <Option value={1}>是</Option>
175
+            </Select>
176
+          </FormItem>
165 177
           <FormItem label="状态" name="status" rules={[{ required: true, message: '请选择' }]}>
166 178
             <Select placeholder="请选择是否发布">
167 179
               <Option value={1}>发布</Option>

+ 27
- 0
src/pages/Machinery/Org/RuralMarker.js View File

@@ -0,0 +1,27 @@
1
+import ruralMarkerImg from '@/assets/images/screen/map-rural.png';
2
+
3
+export default function getRuralMarker(AMap, map, opts = {}) {
4
+  const marker = new AMap.Marker({
5
+    icon: ruralMarkerImg,
6
+    anchor: 'top-center',
7
+    offset: new AMap.Pixel(0, 0),
8
+    ...opts,
9
+  });
10
+
11
+  // 合作社数据
12
+  const { name, address, machineryNum, phone } = opts?.extData;
13
+
14
+  marker.setLabel({
15
+    direction: 'top',
16
+    offset: new AMap.Pixel(0, 0),
17
+    content: `
18
+    <div class='geo-map-rural-box' >
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">农机数量:${machineryNum || 0} 辆</div>
22
+      <div class="borderBox">联系电话:${phone}</div>
23
+    </div>`,
24
+  });
25
+
26
+  return marker;
27
+}

+ 0
- 11
src/pages/Machinery/Org/index.jsx View File

@@ -225,20 +225,9 @@ export default (props) => {
225 225
                   ))}
226 226
                 </Select>
227 227
               </FormItem>
228
-              {/* <FormItem
229
-                label="身份"
230
-                name="role"
231
-                rules={[{ required: true, message: '请选择身份' }]}
232
-              >
233
-                <Select placeholder="请选择身份" style={{ width: '350px' }}>
234
-                  <Option value="合作社" key="合作社" />
235
-                  <Option value="个体户" key="个体户" />
236
-                </Select>
237
-              </FormItem> */}
238 228
               <FormItem label="员工数">{listForm?.workerNum || 0}</FormItem>
239 229
               <FormItem label="农机数">{listForm?.machineryNum || 0}</FormItem>
240 230
               <FormItem label="订单完成数">{listForm?.orderNum || 0}</FormItem>
241
-              <FormItem label="评分">{listForm?.score || 0}</FormItem>
242 231
               <FormItem label=" " colon={false}>
243 232
                 <Button type="primary" loading={loading} htmlType="submit">
244 233
                   保存

+ 58
- 0
src/pages/Machinery/Person/components/OrgTree.jsx View File

@@ -0,0 +1,58 @@
1
+import React, { useState, useEffect } from 'react';
2
+import {
3
+  Card,
4
+  Tree,
5
+} from 'antd';
6
+import { getCooperativeList } from '@/services/cooperative';
7
+
8
+export default (props) => {
9
+  const { setOrgId, setCooperativeList } = props
10
+  const [data, setData] = useState([]);
11
+
12
+  // 动态生成树
13
+  const handelNode = (item) => {
14
+    let node = (
15
+      <div
16
+        key={item.orgId}
17
+        style={{
18
+          justifyContent: 'space-between',
19
+          display: 'flex',
20
+          padding: '8px 0',
21
+        }}
22
+      >
23
+        <span>{item.title}</span>
24
+      </div>
25
+    );
26
+    return node;
27
+  };
28
+  const onSelect = (checkedKeys, info) => {
29
+    if (info.selected) {
30
+      setOrgId(info.node.key);
31
+    } else {
32
+      setOrgId();
33
+    }
34
+  };
35
+  useEffect(() => {
36
+    getCooperativeList({ pageSize: 500 })
37
+      .then((res) => {
38
+        setCooperativeList(res.records);
39
+        const list = res.records?.map((item) => {
40
+          return { title: item.name, key: item.orgId };
41
+        });
42
+        setData(list);
43
+      })
44
+      .catch((err) => {
45
+        console.log(err.message);
46
+      });
47
+  }, [])
48
+  return (
49
+    <Card title="合作社列表">
50
+      <Tree
51
+        onSelect={onSelect}
52
+        className="treeClass"
53
+        titleRender={(data) => handelNode(data)}
54
+        treeData={data}
55
+      />
56
+    </Card>
57
+  )
58
+}

+ 100
- 0
src/pages/Machinery/Person/components/RoleModel.jsx View File

@@ -0,0 +1,100 @@
1
+import React, { useState, useEffect } from 'react';
2
+import {
3
+  Modal,
4
+  message,
5
+  List,
6
+  Checkbox,
7
+} from 'antd';
8
+import { getRoleList } from '@/services/role';
9
+import { addUserUserRole, deleteUserRole } from '@/services/userRole';
10
+export default (props) => {
11
+
12
+  const { rUserId, setRUserId, currentCheckbox, setCurrentCheckbox, editRoleModal, setEditRoleModal } = props
13
+  const [roleList, setRoleList] = useState([]);
14
+  const [rLoading, setRLoading] = useState(false);
15
+
16
+  //授权弹窗点击取消按钮
17
+  const onRoleCancel = () => {
18
+    setRUserId();
19
+    setCurrentCheckbox();
20
+    setEditRoleModal(false);
21
+  };
22
+  //授权角色弹窗点击保存按钮
23
+  const handelOk = () => {
24
+    if (!currentCheckbox) {
25
+      message.info('请选择角色');
26
+      return;
27
+    }
28
+    setRLoading(true);
29
+    if (currentCheckbox.length === 0) {
30
+      deleteUserRole(rUserId)
31
+        .then(() => {
32
+          message.success('取消授权角色成功');
33
+          setRLoading(false);
34
+          onRoleCancel();
35
+        })
36
+        .catch((err) => {
37
+          console.log(err.message);
38
+          setRLoading(false);
39
+        });
40
+    } else {
41
+      addUserUserRole(
42
+        rUserId,
43
+        currentCheckbox.map((item) => {
44
+          return { userId: rUserId, roleId: item };
45
+        }),
46
+      )
47
+        .then(() => {
48
+          message.success('授权角色成功');
49
+          setRLoading(false);
50
+          onRoleCancel();
51
+        })
52
+        .catch((err) => {
53
+          console.log(err.message);
54
+          setRLoading(false);
55
+        });
56
+    }
57
+  };
58
+  const handleCheckboxChange = (list) => {
59
+    setCurrentCheckbox(list);
60
+  };
61
+  useEffect(() => {
62
+    //获取角色列表数据
63
+    getRoleList({ pageSize: 999 })
64
+      .then((res) => {
65
+        setRoleList(res.records);
66
+      })
67
+      .catch((err) => {
68
+        console.log(err.message);
69
+      });
70
+  }, []);
71
+  return (
72
+    <Modal
73
+      forceRender
74
+      title="授权角色"
75
+      visible={editRoleModal}
76
+      onCancel={onRoleCancel}
77
+      keyboard={false}
78
+      maskClosable={false}
79
+      destroyOnClose={true}
80
+      onOk={handelOk}
81
+      confirmLoading={rLoading}
82
+    >
83
+      <Checkbox.Group
84
+        style={{ width: '100%' }}
85
+        value={currentCheckbox}
86
+        onChange={handleCheckboxChange}
87
+      >
88
+        <List
89
+          dataSource={roleList}
90
+          renderItem={(item) => (
91
+            <List.Item>
92
+              <Checkbox value={item.roleId}>{item.name}</Checkbox>
93
+            </List.Item>
94
+          )}
95
+        />
96
+      </Checkbox.Group>
97
+    </Modal>
98
+
99
+  )
100
+}

+ 161
- 0
src/pages/Machinery/Person/components/UserModal.jsx View File

@@ -0,0 +1,161 @@
1
+import {
2
+  Button,
3
+  Modal,
4
+  Form,
5
+  Input,
6
+  message,
7
+  Radio,
8
+  Select,
9
+} from 'antd';
10
+import { useEffect, useState } from 'react';
11
+import Search from '@/components/CooperativeSearch';
12
+import {
13
+  addUser,
14
+  updateUser,
15
+  getDefaultPassword
16
+} from '@/services/user';
17
+
18
+const FormItem = Form.Item;
19
+const { Option } = Select;
20
+const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 14 } };
21
+export default (props) => {
22
+  const { editModal, onCancel, actionRef, form, orgId, userId } = props
23
+  const [loading, setLoading] = useState(false);
24
+  const [password, setPassWord] = useState('');
25
+
26
+  // 编辑弹窗的表单提交
27
+  const Submit = (values) => {
28
+    const newData = { ...values };
29
+    if (!newData.sex && newData.sex !== 0) {
30
+      newData.sex = 1;
31
+    }
32
+    setLoading(true);
33
+    if (!/^1[0-9]{10}$/.test(newData.phone)) {
34
+      message.warning('请输入正确的十一位手机号');
35
+      setLoading(false);
36
+      return false;
37
+    }
38
+    if (
39
+      !/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(
40
+        newData.idCard,
41
+      )
42
+    ) {
43
+      message.warning('请输入正确的身份证号');
44
+      setLoading(false);
45
+      return false;
46
+    }
47
+
48
+    if (userId) {
49
+      updateUser(userId, newData)
50
+        .then(() => {
51
+          setLoading(false);
52
+          message.success(`修改成功`);
53
+          onCancel();
54
+          actionRef.current.reload();
55
+        })
56
+        .catch((err) => {
57
+          setLoading(false);
58
+          console.log(err.message);
59
+        });
60
+    } else {
61
+      addUser(newData)
62
+        .then(() => {
63
+          setLoading(false);
64
+          message.success(`保存成功`);
65
+          onCancel();
66
+          actionRef.current.reload();
67
+        })
68
+        .catch((err) => {
69
+          setLoading(false);
70
+          message.error(err.message || err);
71
+        });
72
+    }
73
+  };
74
+  // 弹窗表单中合作社搜索框改变事件目前没用
75
+  const handelChange = () => { };
76
+  useEffect(() => {
77
+    //获取账号默认密码
78
+    getDefaultPassword()
79
+      .then((res) => {
80
+        setPassWord(res);
81
+      })
82
+      .catch((err) => {
83
+        console.log(err.message);
84
+      });
85
+  }, [])
86
+  return (
87
+    <Modal
88
+      forceRender
89
+      title={userId ? '人员编辑' : '人员新增'}
90
+      visible={editModal}
91
+      onCancel={onCancel}
92
+      keyboard={false}
93
+      maskClosable={false}
94
+      destroyOnClose={true}
95
+      footer={null}
96
+    >
97
+      <Form {...formItemLayout} onFinish={Submit} form={form}>
98
+        <FormItem label="用户名" name="userName" rules={[{ required: true, message: '请输入' }]}>
99
+          <Input placeholder="请输入" />
100
+        </FormItem>
101
+        <FormItem label="性别" name="sex" rules={[{ required: true, message: '请选择' }]}>
102
+          <Radio.Group>
103
+            <Radio value={1}>男</Radio>
104
+            <Radio value={0}>女</Radio>
105
+          </Radio.Group>
106
+        </FormItem>
107
+        <FormItem label="手机号" name="phone" rules={[{ required: true, message: '请输入' }]}>
108
+          <Input maxLength="11" placeholder="请输入" />
109
+        </FormItem>
110
+        <FormItem label="身份证" name="idCard" rules={[{ required: true, message: '请输入' }]}>
111
+          <Input placeholder="请输入" />
112
+        </FormItem>
113
+        <FormItem
114
+          label="登录账号"
115
+          name="loginName"
116
+          rules={[{ required: true, message: '请输入登录账号' }]}
117
+        >
118
+          <Input placeholder="请输入" />
119
+        </FormItem>
120
+        <FormItem label=" " colon={false} style={{ height: '4px', marginTop: '-28px' }}>
121
+          <span style={{ opacity: '0.7' }}>默认密码{password}</span>
122
+        </FormItem>
123
+        <FormItem label="所属合作社" name="orgId" rules={[{ required: true, message: '请输入' }]}>
124
+          <Search placeholder="请输入合作社" disabled={orgId && !userId ? true : false} onChange={handelChange} />
125
+        </FormItem>
126
+        {userId && (
127
+          <FormItem
128
+            label="合作社管理员"
129
+            name="isOrgManager"
130
+            rules={[{ required: true, message: '请选择' }]}
131
+          >
132
+            <Select placeholder="请选择是否启用">
133
+              <Option value={false}>否</Option>
134
+              <Option value={true}>是</Option>
135
+            </Select>
136
+          </FormItem>
137
+        )}
138
+        <FormItem label="状态" name="status" rules={[{ required: true, message: '请选择' }]}>
139
+          <Select placeholder="请选择是否启用">
140
+            <Option value={1}>启用</Option>
141
+            <Option value={0}>禁用</Option>
142
+          </Select>
143
+        </FormItem>
144
+        <FormItem label=" " colon={false}>
145
+          <Button type="default" onClick={onCancel}>
146
+            取消
147
+          </Button>
148
+          <Button
149
+            type="primary"
150
+            loading={loading}
151
+            htmlType="Submit"
152
+            style={{ marginLeft: '4em' }}
153
+          >
154
+            确认
155
+          </Button>
156
+        </FormItem>
157
+      </Form>
158
+    </Modal>
159
+
160
+  )
161
+}

+ 48
- 278
src/pages/Machinery/Person/index.jsx View File

@@ -4,138 +4,56 @@ import {
4 4
   Popconfirm,
5 5
   Modal,
6 6
   Form,
7
-  Input,
8 7
   message,
9
-  Radio,
10
-  Select,
11
-  List,
12 8
   Row,
13 9
   Col,
14
-  Card,
15
-  Tree,
16
-  Checkbox,
17 10
 } from 'antd';
18 11
 import { PlusOutlined } from '@ant-design/icons';
19
-import { getCooperativeList } from '@/services/cooperative';
20 12
 import {
21 13
   getUserList,
22
-  addUser,
23 14
   deleteUser,
24 15
   updateUser,
25
-  getDefaultPassword,
26 16
   getUserDetail,
27 17
 } from '@/services/user';
28
-import { getRoleList } from '@/services/role';
29
-import { getUserRoleList, addUserUserRole, deleteUserRole } from '@/services/userRole';
18
+import { getUserRoleList } from '@/services/userRole';
30 19
 import { PageHeaderWrapper } from '@ant-design/pro-layout';
31 20
 import PageTable from '@/components/PageTable';
32 21
 import moment from 'moment';
33
-import Search from '@/components/CooperativeSearch';
34 22
 import './index.less';
23
+import OrgTree from './components/OrgTree';
24
+import UserModal from './components/UserModal';
25
+import RoleModel from './components/RoleModel';
35 26
 
36
-const FormItem = Form.Item;
37
-const { Option } = Select;
38 27
 const formatterTime = (val) => {
39 28
   return val && val !== '-' ? moment(val).format('YYYY-MM-DD') : '-';
40 29
 };
41 30
 export default (props) => {
42 31
   //编辑弹窗
43
-  const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 14 } };
44 32
   const [form] = Form.useForm();
45 33
   const [editModal, setEditModal] = useState(false);
46
-  const [loading, setLoading] = useState(false);
47 34
   const [userId, setuserId] = useState();
48
-  const [password, setPassWord] = useState('');
49 35
   const [cooperativeList, setCooperativeList] = useState([]);
50 36
 
51 37
   const [editRoleModal, setEditRoleModal] = useState(false);
52
-  const [rLoading, setRLoading] = useState(false);
53 38
   const [rUserId, setRUserId] = useState();
54
-  const [roleList, setRoleList] = useState([]);
55 39
   const [currentCheckbox, setCurrentCheckbox] = useState();
56 40
   //列表数据
57 41
   const actionRef = useRef();
58
-  const [data, setData] = useState([]);
59 42
   const [orgId, setOrgId] = useState();
60 43
 
61
-  // 动态生成树
62
-  const handelNode = (item) => {
63
-    let node = (
64
-      <div
65
-        key={item.orgId}
66
-        style={{
67
-          justifyContent: 'space-between',
68
-          display: 'flex',
69
-          padding: '8px 0',
70
-        }}
71
-      >
72
-        <span>{item.title}</span>
73
-      </div>
74
-    );
75
-    return node;
76
-  };
77
-  const onSelect = (checkedKeys, info) => {
78
-    if (info.selected) {
79
-      setOrgId(info.node.key);
80
-    } else {
81
-      setOrgId();
82
-    }
83
-  };
84
-  // 编辑弹窗的表单提交
85
-  const Submit = (values) => {
86
-    const newData = { ...values };
87
-    if (!newData.sex && newData.sex !== 0) {
88
-      newData.sex = 1;
89
-    }
90
-    setLoading(true);
91
-    if (!/^1[0-9]{10}$/.test(newData.phone)) {
92
-      message.warning('请输入正确的十一位手机号');
93
-      setLoading(false);
94
-      return false;
95
-    }
96
-    if (!/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(newData.idCard)) {
97
-      message.warning('请输入正确的身份证号');
98
-      setLoading(false);
99
-      return false;
100
-    }
101
-
102
-    if (userId) {
103
-      updateUser(userId, newData).then(() => {
104
-        setLoading(false);
105
-        message.success(`修改成功`);
106
-        onCancel();
107
-        actionRef.current.reload();
108
-      }).catch((err) => {
109
-        setLoading(false);
110
-        console.log(err.message)
111
-      });
112
-    } else {
113
-      addUser(newData)
114
-        .then(() => {
115
-          setLoading(false);
116
-          message.success(`保存成功`);
117
-          onCancel();
118
-          actionRef.current.reload();
119
-        })
120
-        .catch((err) => {
121
-          setLoading(false);
122
-          message.error(err.message || err);
123
-        });
124
-    }
125
-
126
-  };
127 44
   //表单点击取消按钮
128 45
   const onCancel = () => {
129 46
     setuserId();
130 47
     form.resetFields();
131 48
     setEditModal(false);
132 49
   };
133
-  // 弹窗表单中合作社搜索框改变事件目前没用
134
-  const handelChange = () => { };
135 50
 
136 51
   // 列表点击编辑按钮
137 52
   const handleEdit = (val) => {
138 53
     setuserId(val.userId);
54
+    if (!userId && orgId) {
55
+      form.setFieldsValue({ orgId: orgId })
56
+    }
139 57
     setEditModal(true);
140 58
   };
141 59
   //列表点击删除按钮
@@ -146,7 +64,7 @@ export default (props) => {
146 64
         actionRef.current.reload();
147 65
       })
148 66
       .catch((err) => {
149
-        console.log(err.message)
67
+        console.log(err.message);
150 68
       });
151 69
   };
152 70
   //列表切换人员状态方法
@@ -165,119 +83,66 @@ export default (props) => {
165 83
             actionRef.current.reload();
166 84
           })
167 85
           .catch((err) => {
168
-            console.log(err.message)
86
+            console.log(err.message);
169 87
           });
170 88
       },
171 89
     });
172 90
   };
173
-
91
+  //点击授权角色方法
174 92
   const handleRole = (val) => {
175 93
     setRUserId(val.userId);
176
-    getUserRoleList({ user_id: val.userId }).then((res) => {
177
-      if (res.length !== 0) {
178
-        setCurrentCheckbox(res.map((item) => item.roleId));
179
-      }
180
-    }).catch((err) => {
181
-      console.log(err.message)
182
-    });
94
+    getUserRoleList({ user_id: val.userId })
95
+      .then((res) => {
96
+        if (res.length !== 0) {
97
+          setCurrentCheckbox(res.map((item) => item.roleId));
98
+        }
99
+      })
100
+      .catch((err) => {
101
+        console.log(err.message);
102
+      });
183 103
     setEditRoleModal(true);
184 104
   };
185
-  //授权弹窗点击取消按钮
186
-  const onRoleCancel = () => {
187
-    setRUserId();
188
-    setCurrentCheckbox();
189
-    form.resetFields();
190
-    setEditRoleModal(false);
191
-  };
192
-  const handelOk = () => {
193
-    if (!currentCheckbox) {
194
-      message.info('请选择角色');
195
-      return;
196
-    }
197
-    setRLoading(true);
198
-    if (currentCheckbox.length === 0) {
199
-      deleteUserRole(rUserId)
200
-        .then(() => {
201
-          message.success('取消授权角色成功');
202
-          setRLoading(false);
203
-          onRoleCancel();
204
-        })
205
-        .catch((err) => {
206
-          console.log(err.message)
207
-          setRLoading(false);
208
-        });
209
-    } else {
210
-      addUserUserRole(
211
-        rUserId,
212
-        currentCheckbox.map((item) => {
213
-          return { userId: rUserId, roleId: item };
214
-        }),
215
-      )
216
-        .then(() => {
217
-          message.success('授权角色成功');
218
-          setRLoading(false);
219
-          onRoleCancel();
105
+
106
+  //监控
107
+  useEffect(() => {
108
+    if (userId) {
109
+      getUserDetail(userId)
110
+        .then((res) => {
111
+          if (res.orgId === '-1') {
112
+            form.setFieldsValue({ ...res, orgId: cooperativeList[0].orgId });
113
+          } else {
114
+            form.setFieldsValue(res);
115
+          }
220 116
         })
221 117
         .catch((err) => {
222
-          console.log(err.message)
223
-          setRLoading(false);
118
+          console.log(err.message);
224 119
         });
225
-    }
226
-  };
227
-  const handleCheckboxChange = (list) => {
228
-    setCurrentCheckbox(list);
229
-  };
230
-  useEffect(() => {
231
-    //获取账号默认密码
232
-    getDefaultPassword().then((res) => {
233
-      setPassWord(res);
234
-    }).catch((err) => {
235
-      console.log(err.message)
236
-    });
237
-    //获取合作社列表数据
238
-    getCooperativeList({ pageSize: 999 }).then((res) => {
239
-      setCooperativeList(res.records);
240
-      const list = res.records?.map((item) => {
241
-        return { title: item.name, key: item.orgId };
242
-      });
243
-      setData(list);
244
-    }).catch((err) => {
245
-      console.log(err.message)
246
-    });
247
-    //获取角色列表数据
248
-    getRoleList({ pageSize: 999 }).then((res) => {
249
-      setRoleList(res.records);
250
-    }).catch((err) => {
251
-      console.log(err.message)
252
-    });
253
-  }, []);
254
-  useEffect(() => {
255
-    if (userId) {
256
-      getUserDetail(userId).then((res) => {
257
-        if (res.orgId === '-1') {
258
-          form.setFieldsValue({ ...res, orgId: cooperativeList[0].orgId });
259
-        } else {
260
-          form.setFieldsValue(res);
261
-        }
262
-      }).catch((err) => {
263
-        console.log(err.message)
264
-      });
265 120
     } else {
266
-      form.resetFields();
121
+      if (orgId) {
122
+        form.setFieldsValue({ orgId: orgId })
123
+      } else {
124
+        form.resetFields();
125
+      }
267 126
     }
268
-  }, [userId]);
127
+  }, [orgId, userId]);
269 128
 
270 129
   const actions = () => [
271
-    <Button key="add" type="primary" icon={<PlusOutlined />} onClick={() => setEditModal(true)}>
130
+    <Button key="add" type="primary" icon={<PlusOutlined />} onClick={handleEdit}>
272 131
       新增
273 132
     </Button>,
274 133
   ];
275 134
   const columns = [
276 135
     {
277
-      title: '用户名',
136
+      title: '姓名',
278 137
       dataIndex: 'userName',
279 138
       key: 'userName',
280 139
     },
140
+    {
141
+      title: '昵称',
142
+      dataIndex: 'nickName',
143
+      key: 'nickName',
144
+      search: false,
145
+    },
281 146
     {
282 147
       title: '性别',
283 148
       dataIndex: 'sex',
@@ -355,14 +220,7 @@ export default (props) => {
355 220
     <PageHeaderWrapper>
356 221
       <Row gutter={16}>
357 222
         <Col span={6}>
358
-          <Card title="合作社列表">
359
-            <Tree
360
-              onSelect={onSelect}
361
-              className="treeClass"
362
-              titleRender={(data) => handelNode(data)}
363
-              treeData={data}
364
-            />
365
-          </Card>
223
+          <OrgTree setOrgId={setOrgId} setCooperativeList={setCooperativeList} />
366 224
         </Col>
367 225
         <Col span={18}>
368 226
           <PageTable
@@ -378,96 +236,8 @@ export default (props) => {
378 236
           />
379 237
         </Col>
380 238
       </Row>
381
-      <Modal
382
-        forceRender
383
-        title={userId ? '人员编辑' : '人员新增'}
384
-        visible={editModal}
385
-        onCancel={onCancel}
386
-        keyboard={false}
387
-        maskClosable={false}
388
-        destroyOnClose={true}
389
-        footer={null}
390
-      >
391
-        <Form {...formItemLayout} onFinish={Submit} form={form}>
392
-          <FormItem label="用户名" name="userName" rules={[{ required: true, message: '请输入' }]}>
393
-            <Input placeholder="请输入" />
394
-          </FormItem>
395
-          <FormItem label="性别" name="sex">
396
-            <Radio.Group>
397
-              <Radio value={1}>男</Radio>
398
-              <Radio value={0}>女</Radio>
399
-            </Radio.Group>
400
-          </FormItem>
401
-          <FormItem label="手机号" name="phone" rules={[{ required: true, message: '请输入' }]}>
402
-            <Input maxLength="11" placeholder="请输入" />
403
-          </FormItem>
404
-          <FormItem label="身份证" name="idCard" rules={[{ required: true, message: '请输入' }]}>
405
-            <Input placeholder="请输入" />
406
-          </FormItem>
407
-          <FormItem label="登录账号" name="loginName" rules={[{ required: true, message: '请输入登录账号' }]}>
408
-            <Input placeholder="请输入" />
409
-          </FormItem>
410
-          <FormItem label=" " colon={false} style={{ height: '4px', marginTop: '-28px' }}>
411
-            <span style={{ opacity: '0.7' }}>默认密码{password}</span>
412
-          </FormItem>
413
-          <FormItem label="所属合作社" name="orgId" rules={[{ required: true, message: '请输入' }]}>
414
-            <Search placeholder="请输入合作社" onChange={handelChange} />
415
-          </FormItem>
416
-          {
417
-            userId && <FormItem label="合作社管理员" name="isOrgManager" rules={[{ required: true, message: '请选择' }]}>
418
-              <Select placeholder="请选择是否启用">
419
-                <Option value={false}>否</Option>
420
-                <Option value={true}>是</Option>
421
-              </Select>
422
-            </FormItem>
423
-          }
424
-          <FormItem label="状态" name="status" rules={[{ required: true, message: '请选择' }]}>
425
-            <Select placeholder="请选择是否启用">
426
-              <Option value={1}>启用</Option>
427
-              <Option value={0}>禁用</Option>
428
-            </Select>
429
-          </FormItem>
430
-          <FormItem label=" " colon={false}>
431
-            <Button type="default" onClick={onCancel}>
432
-              取消
433
-            </Button>
434
-            <Button
435
-              type="primary"
436
-              loading={loading}
437
-              htmlType="Submit"
438
-              style={{ marginLeft: '4em' }}
439
-            >
440
-              确认
441
-            </Button>
442
-          </FormItem>
443
-        </Form>
444
-      </Modal>
445
-      <Modal
446
-        forceRender
447
-        title="授权角色"
448
-        visible={editRoleModal}
449
-        onCancel={onRoleCancel}
450
-        keyboard={false}
451
-        maskClosable={false}
452
-        destroyOnClose={true}
453
-        onOk={handelOk}
454
-        confirmLoading={rLoading}
455
-      >
456
-        <Checkbox.Group
457
-          style={{ width: '100%' }}
458
-          value={currentCheckbox}
459
-          onChange={handleCheckboxChange}
460
-        >
461
-          <List
462
-            dataSource={roleList}
463
-            renderItem={(item) => (
464
-              <List.Item>
465
-                <Checkbox value={item.roleId}>{item.name}</Checkbox>
466
-              </List.Item>
467
-            )}
468
-          />
469
-        </Checkbox.Group>
470
-      </Modal>
239
+      <UserModal editModal={editModal} onCancel={onCancel} actionRef={actionRef} form={form} orgId={orgId} userId={userId} />
240
+      <RoleModel rUserId={rUserId} setRUserId={setRUserId} currentCheckbox={currentCheckbox} setCurrentCheckbox={setCurrentCheckbox} editRoleModal={editRoleModal} setEditRoleModal={setEditRoleModal} />
471 241
     </PageHeaderWrapper>
472 242
   );
473 243
 };

+ 27
- 5
src/pages/MonitoringScreen/components/List/index.jsx View File

@@ -1,4 +1,4 @@
1
-import React, { useEffect, useMemo, useRef, useState } from 'react';
1
+import React, { useCallback, useEffect, useRef } from 'react';
2 2
 import { Swiper, SwiperSlide } from 'swiper/react';
3 3
 import { Autoplay } from 'swiper';
4 4
 import 'swiper/css';
@@ -7,14 +7,30 @@ import Item from './Item';
7 7
 import Styles from './style.less';
8 8
 
9 9
 export default (props) => {
10
-  // 每次加载 4 个
11
-  const tm = 4;
12 10
   const { title, color, children } = props;
13
-
11
+  const swiperRef = useRef();
14 12
   const classList = classNames(Styles['list-title'], {
15 13
     [Styles['yellow-title']]: color !== 'green',
16 14
     [Styles['green-title']]: color === 'green',
17 15
   });
16
+  const initAutoPlay = useCallback(
17
+    (swiper) => {
18
+      if (!children?.length || children?.length <= 3) {
19
+        swiper.autoplay.stop();
20
+      } else {
21
+        swiper.autoplay.start();
22
+      }
23
+    },
24
+    [children?.length],
25
+  );
26
+
27
+  useEffect(() => {
28
+    if (swiperRef.current) {
29
+      initAutoPlay(swiperRef.current);
30
+    }
31
+  }, [children?.length, initAutoPlay]);
32
+
33
+  const enable = children?.length && children?.length > 3;
18 34
 
19 35
   return (
20 36
     <div className={Styles['screen-list']}>
@@ -23,12 +39,18 @@ export default (props) => {
23 39
       </div>
24 40
       <Swiper
25 41
         height={48}
42
+        onSwiper={(swiper) => {
43
+          swiperRef.current = swiper;
44
+          initAutoPlay(swiper);
45
+        }}
26 46
         className={Styles['list-body']}
47
+        //因为loop只能在组件初始化时改变所以加一个不让它创建初始化的属性就可以了
48
+        init={false}
27 49
         autoplay={{
28 50
           delay: 2500,
29 51
           disableOnInteraction: false,
30 52
         }}
31
-        loop
53
+        loop={enable}
32 54
         loopAdditionalSlides={2}
33 55
         modules={[Autoplay]}
34 56
         direction="vertical"

+ 16
- 9
src/pages/MonitoringScreen/components/MachineryType.jsx View File

@@ -1,4 +1,4 @@
1
-import React, { useMemo } from 'react';
1
+import React, { useEffect, useMemo, useState } from 'react';
2 2
 import * as echarts from 'echarts/core';
3 3
 import deepCopy from '@/utils/deepCopy';
4 4
 import { hex2Rgb } from '@/utils/color';
@@ -85,14 +85,21 @@ const defaultOpt = {
85 85
 };
86 86
 
87 87
 export default (props) => {
88
-  const option = useMemo(() => deepCopy(defaultOpt), []);
89
-  option.yAxis.data = props.source.map((x) => x.name);
90
-  option.series[0].data = props.source.map((x, i) => ({
91
-    value: x.value,
92
-    itemStyle: {
93
-      color: colorList[i % 3],
94
-    },
95
-  }));
88
+  const option2 = useMemo(() => deepCopy(defaultOpt), []);
89
+
90
+  const [option, setOption] = useState(option2);
91
+
92
+  useEffect(() => {
93
+    var option3 = { ...option2 };
94
+    option3.yAxis.data = props.source.map((x) => x.name);
95
+    option3.series[0].data = props.source.map((x, i) => ({
96
+      value: x.value,
97
+      itemStyle: {
98
+        color: colorList[i % 3],
99
+      },
100
+    }));
101
+    setOption(option3);
102
+  }, [props.source]);
96 103
 
97 104
   return <BasicChart title="农机类型统计" option={option} />;
98 105
 };

+ 12
- 4
src/pages/MonitoringScreen/components/WorkArea.jsx View File

@@ -1,4 +1,4 @@
1
-import React, { useEffect, useMemo, useRef } from 'react';
1
+import React, { useEffect, useMemo, useState } from 'react';
2 2
 import deepCopy from '@/utils/deepCopy';
3 3
 import { colorArr } from '@/components/ScreenBox/utils';
4 4
 import BasicChart from './BasicChart';
@@ -36,9 +36,17 @@ const defaultOpt = {
36 36
 };
37 37
 
38 38
 export default (props) => {
39
-  const option = useMemo(() => deepCopy(defaultOpt), []);
40
-  option.series[0].data = props.source;
41
-  (option.series[0].data[0] || {}).selected = true; // 设置第一个是选中状态
39
+  const option2 = useMemo(() => deepCopy(defaultOpt), []);
40
+
41
+  const [option, setOption] = useState(option2);
42
+
43
+  useEffect(() => {
44
+    var option3 = { ...option2 };
45
+    option3.series[0].data = props.source;
46
+    // 设置第一个是选中状态
47
+    (option3.series[0].data[0] || {}).selected = true;
48
+    setOption(option3);
49
+  }, [props.source]);
42 50
 
43 51
   return <BasicChart title="农机作业量面积统计" option={option} />;
44 52
 };

+ 11
- 3
src/pages/MonitoringScreen/components/WorkData.jsx View File

@@ -1,4 +1,4 @@
1
-import React, { useEffect, useMemo, useRef } from 'react';
1
+import React, { useEffect, useMemo, useState } from 'react';
2 2
 import deepCopy from '@/utils/deepCopy';
3 3
 import { colorArr } from '@/components/ScreenBox/utils';
4 4
 import BasicChart from './BasicChart';
@@ -44,8 +44,16 @@ const defaultOpt = {
44 44
 };
45 45
 
46 46
 export default (props) => {
47
-  const option = useMemo(() => deepCopy(defaultOpt), []);
48
-  option.series[0].data = props.source;
47
+  const option2 = useMemo(() => deepCopy(defaultOpt), []);
48
+
49
+  const [option, setOption] = useState(option2);
50
+
51
+  useEffect(() => {
52
+    var option3 = { ...option2 };
53
+    option3.series[0].data = props.source;
54
+    // 设置第一个是选中状态
55
+    setOption(option3);
56
+  }, [props.source]);
49 57
 
50 58
   return <BasicChart title="农机作业数统计" option={option} />;
51 59
 };

+ 161
- 149
src/pages/MonitoringScreen/index.jsx View File

@@ -1,18 +1,27 @@
1
-import React, { useCallback, useEffect, useRef, useState } from 'react';
2
-import { history, Link } from 'umi';
3
-import classNames from 'classnames';
4
-import ScreenHeader from '@/components/ScreenBox/ScreenHeader';
1
+import getWeather from '@/components/AMap/weather';
5 2
 import GeoMap from '@/components/GeoMap';
6
-import StatisCard from '@/components/ScreenBox/StatisCard';
3
+import ScreenHeader from '@/components/ScreenBox/ScreenHeader';
7 4
 import SquareBox from '@/components/ScreenBox/SquareBox';
8
-import getWeather from '@/components/AMap/weather';
9
-import { useParticlesJs } from './hook';
10
-import MachineryType from './components/MachineryType';
5
+import StatisCard from '@/components/ScreenBox/StatisCard';
6
+import classNames from 'classnames';
7
+import { useEffect, useRef, useState } from 'react';
8
+import {
9
+  getBasic,
10
+  getOrgDetail,
11
+  getTypeList,
12
+  getAreaDetail,
13
+  getMachineryBar,
14
+  getWorkNumPie,
15
+  getTypeBasic,
16
+  getMessageList,
17
+} from '@/services/monitoringScreen';
11 18
 import MachineryStatus from './components/MachineryStatus';
19
+import MachineryType from './components/MachineryType';
20
+import { useParticlesJs } from './hook';
12 21
 
13
-import WorkArea from './components/WorkArea';
14
-import List from './components/List';
15 22
 import ColorFont from './components/ColorFont';
23
+import List from './components/List';
24
+import WorkArea from './components/WorkArea';
16 25
 import WorkData from './components/WorkData';
17 26
 import Styles from './style.less';
18 27
 
@@ -20,11 +29,9 @@ export default (props) => {
20 29
   const screenRef = useRef();
21 30
   const [weather, setWeather] = useState('暂无天气信息');
22 31
 
23
-  const [machineryTypeData, setMachineryTypeData] = useState([
24
-    { name: '收割机', value: 200 },
25
-    { name: '播种机', value: 100 },
26
-    { name: '农药机', value: 50 },
27
-  ]);
32
+  const [basic, setBasic] = useState();
33
+
34
+  const [machineryTypeData, setMachineryTypeData] = useState([]);
28 35
 
29 36
   const [machineryStatusData, setMachineryStatusData] = useState([
30 37
     { name: '预约', value: 350 },
@@ -34,109 +41,115 @@ export default (props) => {
34 41
     { name: '维修', value: 380 },
35 42
   ]);
36 43
 
37
-  const [workData, setWorkData] = useState([
38
-    { name: '收割机', value: 35 },
39
-    { name: '播种机', value: 35 },
40
-    { name: '农药机', value: 30 },
41
-    { name: '其他', value: 180 },
42
-  ]);
44
+  const [workData, setWorkData] = useState([]);
43 45
 
44
-  const [workAreaData, setWorkAreaData] = useState([
45
-    { name: '收割机', value: 350 },
46
-    { name: '播种机', value: 900 },
47
-    { name: '农药机', value: 650 },
48
-    { name: '其他', value: 180 },
49
-  ]);
46
+  const [workAreaData, setWorkAreaData] = useState([]);
50 47
 
51
-  const [machineTypeList, setMachineTypeList] = useState([
52
-    { id: 't0', name: '合作社' },
53
-    { id: 't1', name: '收割机' },
54
-    { id: 't2', name: '播种机' },
55
-    { id: 't3', name: '农药机' },
56
-  ]);
48
+  const [machineTypeList, setMachineTypeList] = useState([{ id: 't0', name: '合作社' }]);
57 49
 
58
-  const [orgList, setOrgList] = useState([
59
-    {
60
-      orgId: 1,
61
-      name: '合作社1',
62
-      address: '合作社地址1',
63
-      phone: '13823838438',
64
-      machineNum: 12,
65
-      lnglat: [112.039556, 32.775169],
66
-    },
67
-    {
68
-      orgId: 2,
69
-      name: '合作社2',
70
-      address: '合作社地址2',
71
-      phone: '13823838438',
72
-      machineNum: 68,
73
-      lnglat: [112.181692, 32.759002],
74
-    },
75
-    {
76
-      orgId: 3,
77
-      name: '合作社3',
78
-      address: '合作社地址3',
79
-      phone: '13823838438',
80
-      machineNum: 3,
81
-      lnglat: [111.958532, 32.631875],
82
-    },
83
-    {
84
-      orgId: 4,
85
-      name: '合作社4',
86
-      address: '合作社地址4',
87
-      phone: '13823838438',
88
-      machineNum: 42,
89
-      lnglat: [112.164526, 32.603536],
90
-    },
91
-  ]);
50
+  const [orgList, setOrgList] = useState();
92 51
 
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
-    },
129
-  ]);
52
+  const [machineList, setMachineList] = useState([]);
53
+  const [appointList, setAppointList] = useState();
54
+  const [acceptList, setAcceptList] = useState();
130 55
 
131 56
   useEffect(() => {
132
-    getWeather('邓州市')
57
+    //顶部基本数据
58
+    getBasic()
59
+      .then((res) => {
60
+        var data = {};
61
+        for (let i = 0; i < res.length; i++) {
62
+          const element = res[i];
63
+          data[element.name] = element.value;
64
+        }
65
+        setBasic(data);
66
+      })
67
+      .catch((err) => {
68
+        console.log(err.message);
69
+      });
70
+    //地图上合作社的marker
71
+    getOrgDetail()
72
+      .then((res) => {
73
+        res.forEach((item) => {
74
+          item.lnglat = [item['lng'] - 0, item['lat'] - 0];
75
+          item.machineryNum = item.machineryNum - 0;
76
+        });
77
+        setOrgList(res);
78
+      })
79
+      .catch((err) => {
80
+        console.log(err.message);
81
+      });
82
+    //获取地图上所有农机markers
83
+    getTypeBasic()
84
+      .then((res) => {
85
+        res.forEach((item) => {
86
+          item.lnglat = [item.location.split(',')[0] - 0, item.location.split(',')[1] - 0];
87
+        });
88
+        setMachineList(res);
89
+      })
90
+      .catch((err) => {
91
+        console.log(err.message);
92
+      });
93
+    //获取地图左侧选择的农机列表
94
+    getTypeList()
95
+      .then((res) => {
96
+        let data = [].concat(machineTypeList);
97
+        res.forEach((item) => {
98
+          data.push({ id: item.typeId, name: item.name });
99
+        });
100
+        setMachineTypeList(data);
101
+      })
102
+      .catch((err) => {
103
+        console.log(err.message);
104
+      });
105
+    //作业面积统计
106
+    getAreaDetail()
107
+      .then((res) => {
108
+        setWorkAreaData([].concat(res));
109
+      })
110
+      .catch((err) => {
111
+        console.log(err.message);
112
+      });
113
+    //农机类型统计
114
+    getMachineryBar()
115
+      .then((res) => {
116
+        setMachineryTypeData(res);
117
+      })
118
+      .catch((err) => {
119
+        console.log(err.message);
120
+      });
121
+    //农机作业数统计
122
+    getWorkNumPie()
123
+      .then((res) => {
124
+        setWorkData(res);
125
+      })
126
+      .catch((err) => {
127
+        console.log(err.message);
128
+      });
129
+
130
+    getMessageList({ messageType: 'appoint' })
131
+      .then((res) => {
132
+        setAppointList(res);
133
+      })
134
+      .catch((err) => {
135
+        console.log(err.message);
136
+      });
137
+    getMessageList({ messageType: 'accept' })
138
+      .then((res) => {
139
+        setAcceptList(res);
140
+      })
141
+      .catch((err) => {
142
+        console.log(err.message);
143
+      });
144
+
145
+    getWeather()
133 146
       .then((res) => {
134 147
         if (res && res.length) {
135
-          const { casts } = res[0];
148
+          const { casts, city } = res[0];
136 149
           const { dayweather, nighttemp, daytemp } = casts[0];
137 150
           const [min, max] =
138 151
             parseInt(nighttemp) > parseInt(daytemp) ? [daytemp, nighttemp] : [nighttemp, daytemp];
139
-          setWeather(`${dayweather} ${min}-${max} °C`);
152
+          setWeather(`${city} ${dayweather} ${min}-${max} °C`);
140 153
         } else {
141 154
           setWeather('暂无天气信息');
142 155
         }
@@ -168,10 +181,30 @@ export default (props) => {
168 181
           </div>
169 182
           <div className={classNames(Styles['grail-content'], Styles['pd-lr-40'])}>
170 183
             <div className={Styles['statis-container']}>
171
-              <StatisCard color="#23E8AE" icon="icon1" value={2346} title="农机总数(台)" />
172
-              <StatisCard color="#0BDAFF" icon="icon2" value={528} title="农机使用数(台)" />
173
-              <StatisCard color="#F5CC5C" icon="icon3" value={168} title="总预约数(台)" />
174
-              <StatisCard color="#C579FF" icon="icon4" value={1568} title="总服务数(台)" />
184
+              <StatisCard
185
+                color="#23E8AE"
186
+                icon="icon1"
187
+                value={basic?.totalMachineryNum}
188
+                title="农机总数(台)"
189
+              />
190
+              <StatisCard
191
+                color="#0BDAFF"
192
+                icon="icon2"
193
+                value={basic?.totalMachineryUsed}
194
+                title="农机使用数(台)"
195
+              />
196
+              <StatisCard
197
+                color="#F5CC5C"
198
+                icon="icon3"
199
+                value={basic?.totalOrderNum}
200
+                title="总预约数"
201
+              />
202
+              <StatisCard
203
+                color="#C579FF"
204
+                icon="icon4"
205
+                value={basic?.totalServiceNum}
206
+                title="总服务数"
207
+              />
175 208
             </div>
176 209
             <GeoMap machineTypeList={machineTypeList} orgList={orgList} machineList={machineList} />
177 210
           </div>
@@ -191,49 +224,28 @@ export default (props) => {
191 224
             <div className="flex" style={{ padding: '20px 0' }}>
192 225
               <div className="flex-1">
193 226
                 <List title="预约订单">
194
-                  <div>
195
-                    <ColorFont color="#F5CC5C">[快乐每一天]</ColorFont> 32s前预约了一台收割机,
196
-                    <ColorFont color="#44F68B">[收割机001]</ColorFont> 接到了此订单!
197
-                  </div>
198
-                  <div>
199
-                    <ColorFont color="#F5CC5C">[幸福人生]</ColorFont> 58分钟前预约了一台收割机,
200
-                    <ColorFont color="#44F68B">[播种机008]</ColorFont> 接到了此订单!尽快赶到!
201
-                  </div>
202
-                  <div>
203
-                    <ColorFont color="#F5CC5C">[灿烂人生]</ColorFont> 2个小时前预约了一台收割机,
204
-                    <ColorFont color="#44F68B">[收割机007]</ColorFont>{' '}
205
-                    接到了此订单!正在赶往目的地!
206
-                  </div>
207
-                  <div>
208
-                    <ColorFont color="#F5CC5C">[快乐每一天]</ColorFont> 32s前预约了一台收割机,
209
-                    <ColorFont color="#44F68B">[收割机001]</ColorFont> 接到了此订单!
210
-                  </div>
211
-                  <div>
212
-                    <ColorFont color="#F5CC5C">[幸福人生]</ColorFont> 58分钟前预约了一台收割机,
213
-                    <ColorFont color="#44F68B">[播种机008]</ColorFont> 接到了此订单!尽快赶到!
214
-                  </div>
215
-                  <div>
216
-                    <ColorFont color="#F5CC5C">[灿烂人生]</ColorFont> 2个小时前预约了一台收割机,
217
-                    <ColorFont color="#44F68B">[收割机007]</ColorFont>{' '}
218
-                    接到了此订单!正在赶往目的地!
219
-                  </div>
227
+                  {appointList?.map((item) => {
228
+                    return (
229
+                      <div key={item.messageId}>
230
+                        <ColorFont color="#44F68B">[{item.appointTime}]</ColorFont>{' '}
231
+                        <ColorFont color="#F5CC5C">{item.appointPerson}</ColorFont> 预约了一台
232
+                        {item.appointMachineryType}。
233
+                      </div>
234
+                    );
235
+                  })}
220 236
                 </List>
221 237
               </div>
222 238
               <div className={classNames('flex-0', Styles['footer-middle'])} />
223 239
               <div className="flex-1">
224 240
                 <List title="作业订单" color="green">
225
-                  <div>
226
-                    <ColorFont color="#44F68B">[收割机001]</ColorFont>
227
-                    32s前接到了一个订单,距离目的地还有3.2公里,请农户耐心等待!
228
-                  </div>
229
-                  <div>
230
-                    <ColorFont color="#44F68B">[播种机008]</ColorFont>{' '}
231
-                    2分钟前接到一个订单,距离目的地还有3.8公里,请农户耐心等待!
232
-                  </div>
233
-                  <div>
234
-                    <ColorFont color="#44F68B">[收割机007]</ColorFont>{' '}
235
-                    2个小时前接到一个订单,距离目的地还有3.8公里,请农户耐心等待!
236
-                  </div>
241
+                  {acceptList?.map((item) => {
242
+                    return (
243
+                      <div key={item.messageId}>
244
+                        <ColorFont color="#44F68B">[{item.acceptTime}]</ColorFont>{' '}
245
+                        <ColorFont color="#F5CC5C">{item.acceptPerson}</ColorFont> 接到了一个订单。
246
+                      </div>
247
+                    );
248
+                  })}
237 249
                 </List>
238 250
               </div>
239 251
             </div>

+ 18
- 34
src/pages/OrderManage/JobWarning/detail.jsx View File

@@ -1,7 +1,7 @@
1 1
 import React, { useState, useEffect } from 'react';
2 2
 import { Card, Form, Button } from 'antd';
3 3
 import ProCard from '@ant-design/pro-card';
4
-import { getOrderDetail } from '@/services/order'
4
+import { getOrderDetail } from '@/services/order';
5 5
 import { history } from 'umi';
6 6
 
7 7
 const FormItem = Form.Item;
@@ -15,44 +15,28 @@ export default (props) => {
15 15
   const [dispatch, setDispatch] = useState();
16 16
 
17 17
   useEffect(() => {
18
-    getOrderDetail(id).then((res) => {
19
-      setDispatch(res)
20
-    }).catch((err) => {
21
-      console.log(err.message)
22
-    });
23
-  }, [id])
18
+    getOrderDetail(id)
19
+      .then((res) => {
20
+        setDispatch(res);
21
+      })
22
+      .catch((err) => {
23
+        console.log(err.message);
24
+      });
25
+  }, [id]);
24 26
   return (
25 27
     <Card>
26 28
       <ProCard tabs={{ type: 'card' }}>
27 29
         <ProCard.TabPane key={1} tab="订单详情">
28 30
           <Form {...formItemLayout}>
29
-            <FormItem label="订单号">
30
-              {dispatch?.orderNo}
31
-            </FormItem>
32
-            <FormItem label="客户姓名">
33
-              {dispatch?.personName}
34
-            </FormItem>
35
-            <FormItem label="联系电话">
36
-              {dispatch?.phone}
37
-            </FormItem>
38
-            <FormItem label="预约地址">
39
-              {dispatch?.address}
40
-            </FormItem>
41
-            <FormItem label="预约时间">
42
-              {dispatch?.appointmentDate}
43
-            </FormItem>
44
-            <FormItem label="合作社名">
45
-              {dispatch?.orgName}
46
-            </FormItem>
47
-            <FormItem label="农机类型">
48
-              {dispatch?.typeName}
49
-            </FormItem>
50
-            <FormItem label="农机">
51
-              {dispatch?.machineryName}
52
-            </FormItem>
53
-            <FormItem label="农机手">
54
-              {dispatch?.workName}
55
-            </FormItem>
31
+            <FormItem label="订单号">{dispatch?.orderNo}</FormItem>
32
+            <FormItem label="农户姓名">{dispatch?.personName}</FormItem>
33
+            <FormItem label="联系电话">{dispatch?.phone}</FormItem>
34
+            <FormItem label="预约地址">{dispatch?.address}</FormItem>
35
+            <FormItem label="预约时间">{dispatch?.appointmentDate}</FormItem>
36
+            <FormItem label="合作社名">{dispatch?.orgName}</FormItem>
37
+            <FormItem label="农机类型">{dispatch?.typeName}</FormItem>
38
+            <FormItem label="农机">{dispatch?.machineryName}</FormItem>
39
+            <FormItem label="农机手">{dispatch?.workName}</FormItem>
56 40
             <FormItem label=" " colon={false}>
57 41
               <Button type="default" onClick={() => goBack()}>
58 42
                 返回

+ 109
- 91
src/pages/OrderManage/dispatch.jsx View File

@@ -1,7 +1,7 @@
1 1
 import React, { useState, useEffect } from 'react';
2 2
 import { Card, Form, Button, Select, message, Modal } from 'antd';
3 3
 import ProCard from '@ant-design/pro-card';
4
-import { getOrderDetail } from '@/services/order'
4
+import { getOrderDetail } from '@/services/order';
5 5
 import { getMachineryList, getduty } from '@/services/machinery';
6 6
 import { history } from 'umi';
7 7
 import { getUserList } from '@/services/user';
@@ -18,116 +18,123 @@ export default (props) => {
18 18
   const { id } = location.query;
19 19
   const [dispatch, setDispatch] = useState();
20 20
   const [loading, setLoading] = useState(false);
21
-  const [dispatchId, setDispatchId] = useState()
21
+  const [dispatchId, setDispatchId] = useState();
22 22
   const [machineryList, setMachineryList] = useState([]);
23
-  const [userList, setUserList] = useState([])
23
+  const [userList, setUserList] = useState([]);
24 24
 
25 25
   const [cancelLoading, setCancelLoading] = useState(false);
26 26
 
27 27
   const submit = () => {
28 28
     if (!dispatch.machineryId) {
29 29
       message.warning('请选择调度的农机');
30
-      return
30
+      return;
31 31
     }
32 32
     if (!dispatch.workerId) {
33 33
       message.warning('请选择农机手');
34
-      return
34
+      return;
35 35
     }
36
-    setLoading(true)
37
-    addDispatch(dispatch).then(res => {
38
-      message.success('调度成功');
39
-      setLoading(false);
40
-      goBack()
41
-    }).catch((err) => {
42
-      setLoading(false);
43
-      message.error(err.message || err);
44
-    });
36
+    setLoading(true);
37
+    addDispatch(dispatch)
38
+      .then((res) => {
39
+        message.success('调度成功');
40
+        setLoading(false);
41
+        goBack();
42
+      })
43
+      .catch((err) => {
44
+        setLoading(false);
45
+        message.error(err.message || err);
46
+      });
45 47
   };
46 48
   const changeMachinery = (e) => {
47
-    getduty(e, { date: dispatch.appointmentDate.substr(0, 10) }).then((res => {
48
-      if (res.length != 0) {
49
-        message.info('该农机当天已有' + res.length + '条调度信息');
50
-      }
51
-      setDispatch({ ...dispatch, machineryId: e })
52
-    })).catch((err) => {
53
-      console.log(err.message)
54
-    });
55
-  }
49
+    getduty(e, { date: dispatch.appointmentDate.substr(0, 10) })
50
+      .then((res) => {
51
+        if (res.length != 0) {
52
+          message.info('该农机当天已有' + res.length + '条调度信息');
53
+        }
54
+        setDispatch({ ...dispatch, machineryId: e });
55
+      })
56
+      .catch((err) => {
57
+        console.log(err.message);
58
+      });
59
+  };
56 60
   const changeUser = (e) => {
57
-    setDispatch({ ...dispatch, workerId: e })
58
-  }
61
+    setDispatch({ ...dispatch, workerId: e });
62
+  };
59 63
   const onCancel = () => {
60 64
     Modal.confirm({
61 65
       title: '确认取消?',
62 66
       okText: '确认',
63 67
       cancelText: '取消',
64 68
       onOk() {
65
-        setCancelLoading(true)
66
-        cancelDispatch(dispatchId).then(() => {
67
-          setCancelLoading(false)
68
-          setDispatchId()
69
-          setDispatch({ ...dispatch, machineryId: null, workerId: null })
70
-          message.success('取消成功');
71
-        }).catch((err) => {
72
-          setCancelLoading(false);
73
-          message.error(err.message || err);
74
-        });
69
+        setCancelLoading(true);
70
+        cancelDispatch(dispatchId)
71
+          .then(() => {
72
+            setCancelLoading(false);
73
+            setDispatchId();
74
+            setDispatch({ ...dispatch, machineryId: null, workerId: null });
75
+            message.success('取消成功');
76
+          })
77
+          .catch((err) => {
78
+            setCancelLoading(false);
79
+            message.error(err.message || err);
80
+          });
75 81
       },
76 82
     });
77
-  }
83
+  };
78 84
   useEffect(() => {
79
-
80
-    getOrderDetail(id).then((res) => {
81
-      res.machineryId = null
82
-      res.typeId = res.machineryType
83
-      setDispatch(res)
84
-      getMachineryList({ orgId: res.orgId, status: 1, typeId: res.typeId, pageSize: 999 }).then((res2) => {
85
-        setMachineryList(res2.records)
86
-      }).catch((err) => {
87
-        console.log(err.message)
85
+    getOrderDetail(id)
86
+      .then((res) => {
87
+        res.machineryId = null;
88
+        res.typeId = res.machineryType;
89
+        setDispatch(res);
90
+        getMachineryList({ orgId: res.orgId, status: 1, typeId: res.typeId, pageSize: 999 })
91
+          .then((res2) => {
92
+            setMachineryList(res2.records);
93
+          })
94
+          .catch((err) => {
95
+            console.log(err.message);
96
+          });
97
+        getUserList({ org_id: res.orgId, pageSize: 999 })
98
+          .then((res3) => {
99
+            setUserList(res3.records);
100
+          })
101
+          .catch((err) => {
102
+            console.log(err.message);
103
+          });
104
+        if (res.dispatchStatus == 1) {
105
+          getdispatchId(id)
106
+            .then((res4) => {
107
+              setDispatchId(res4.dispatchId);
108
+              setDispatch({ ...res, machineryId: res4.machineryId, workerId: res4.workerId });
109
+            })
110
+            .catch((err) => {
111
+              console.log(err.message);
112
+            });
113
+        }
114
+      })
115
+      .catch((err) => {
116
+        console.log(err.message);
88 117
       });
89
-      getUserList({ org_id: res.orgId, pageSize: 999 }).then(res3 => {
90
-        setUserList(res3.records)
91
-      }).catch((err) => {
92
-        console.log(err.message)
93
-      });
94
-      if (res.dispatchStatus == 1) {
95
-        getdispatchId(id).then(res4 => {
96
-          setDispatchId(res4.dispatchId)
97
-          setDispatch({ ...res, machineryId: res4.machineryId, workerId: res4.workerId })
98
-        }).catch((err) => {
99
-          console.log(err.message)
100
-        });
101
-      }
102
-    }).catch((err) => {
103
-      console.log(err.message)
104
-    });
105
-  }, [id])
118
+  }, [id]);
106 119
   return (
107 120
     <Card>
108 121
       <ProCard tabs={{ type: 'card' }}>
109 122
         <ProCard.TabPane key={1} tab="订单调度">
110 123
           <Form {...formItemLayout}>
111
-            <FormItem label="客户姓名">
112
-              {dispatch?.personName}
113
-            </FormItem>
114
-            <FormItem label="联系电话">
115
-              {dispatch?.phone}
116
-            </FormItem>
117
-            <FormItem label="预约地址">
118
-              {dispatch?.address}
119
-            </FormItem>
120
-            <FormItem label="预约时间">
121
-              {dispatch?.appointmentDate}
122
-            </FormItem>
123
-            <FormItem label="合作社名">
124
-              {dispatch?.orgName}
125
-            </FormItem>
126
-            <FormItem label="农机类型">
127
-              {dispatch?.typeName}
128
-            </FormItem>
124
+            <FormItem label="农户姓名">{dispatch?.personName}</FormItem>
125
+            <FormItem label="联系电话">{dispatch?.phone}</FormItem>
126
+            <FormItem label="预约地址">{dispatch?.address}</FormItem>
127
+            <FormItem label="预约时间">{dispatch?.appointmentDate}</FormItem>
128
+            <FormItem label="合作社名">{dispatch?.orgName}</FormItem>
129
+            <FormItem label="农机类型">{dispatch?.typeName}</FormItem>
129 130
             <FormItem label="农机">
130
-              <Select placeholder="请选择" value={dispatch?.machineryId} onChange={changeMachinery} allowClear style={{ width: '350px' }}>
131
+              <Select
132
+                placeholder="请选择"
133
+                value={dispatch?.machineryId}
134
+                onChange={changeMachinery}
135
+                allowClear
136
+                style={{ width: '350px' }}
137
+              >
131 138
                 {machineryList.map((item) => (
132 139
                   <Option value={item.machineryId} key={item.machineryId}>
133 140
                     {item.name}
@@ -136,7 +143,13 @@ export default (props) => {
136 143
               </Select>
137 144
             </FormItem>
138 145
             <FormItem label="农机手">
139
-              <Select placeholder="请选择" value={dispatch?.workerId} onChange={changeUser} allowClear style={{ width: '350px' }}>
146
+              <Select
147
+                placeholder="请选择"
148
+                value={dispatch?.workerId}
149
+                onChange={changeUser}
150
+                allowClear
151
+                style={{ width: '350px' }}
152
+              >
140 153
                 {userList.map((item) => (
141 154
                   <Option value={item.userId} key={item.userId}>
142 155
                     {item.userName}
@@ -148,15 +161,20 @@ export default (props) => {
148 161
               <Button type="default" onClick={() => goBack()}>
149 162
                 返回
150 163
               </Button>
151
-              {
152
-                dispatchId ?
153
-                  <Button loading={cancelLoading} onClick={onCancel} style={{ marginLeft: '4em' }}>
154
-                    取消调度
155
-                  </Button> :
156
-                  <Button type="primary" loading={loading} onClick={submit} style={{ marginLeft: '4em' }}>
157
-                    保存
158
-                  </Button>
159
-              }
164
+              {dispatchId ? (
165
+                <Button loading={cancelLoading} onClick={onCancel} style={{ marginLeft: '4em' }}>
166
+                  取消调度
167
+                </Button>
168
+              ) : (
169
+                <Button
170
+                  type="primary"
171
+                  loading={loading}
172
+                  onClick={submit}
173
+                  style={{ marginLeft: '4em' }}
174
+                >
175
+                  保存
176
+                </Button>
177
+              )}
160 178
             </FormItem>
161 179
           </Form>
162 180
         </ProCard.TabPane>

+ 21
- 108
src/pages/PlatformMessageManagement/MessageManageList/index.jsx View File

@@ -1,126 +1,39 @@
1
-import { history, Link } from 'umi';
2
-import { useRef, useState, useEffect } from 'react';
3
-import { Button, Popconfirm, message, Tooltip } from 'antd';
4
-import { PlusOutlined, QuestionCircleOutlined, DownOutlined } from '@ant-design/icons';
5 1
 import { PageHeaderWrapper } from '@ant-design/pro-layout';
6
-import ProTable from '@ant-design/pro-table';
2
+import PageTable from '@/components/PageTable';
3
+import { getWorkMassageList } from '@/services/workMessage'
7 4
 
8 5
 export default (props) => {
9
-  const dataSource = [
10
-    {
11
-      id: 2121329,
12
-      title: '这是是一个标题标题',
13
-      name: '胡彦斌',
14
-      pushPerson: '农机手',
15
-      status: 'APP内消息中心推送',
16
-    },
17
-  ];
18
-  const gotoDetail = (id) => {
19
-    history.push(`./MessageEdit`);
20
-  };
21
-
22
-  const actions = () => [
23
-    <Button key="add" type="primary" icon={<PlusOutlined />} onClick={() => gotoDetail()}>
24
-      新增商户
25
-    </Button>,
26
-  ];
27 6
   const columns = [
28 7
     {
29
-      title: '消息ID',
30
-
31
-      key: 'id',
32
-      dataIndex: 'id',
33
-      search: false,
34
-
35
-      render: (t, record) => (
36
-        <Link key={1} to={`./edit?id=${record.shopId}`}>
37
-          {record.shopName}
38
-        </Link>
39
-      ),
40
-    },
41
-
42
-    {
43
-      title: '消息标题',
44
-      key: 'title',
45
-      dataIndex: 'title',
46
-      render: (t, record) => (
47
-        <Link key={1} to={`./package?shopId=${record.shopId}`}>
48
-          {record?.packageNum}
49
-        </Link>
50
-      ),
8
+      title: '订单号',
9
+      key: 'orderNo',
10
+      dataIndex: 'orderNo',
51 11
     },
52
-
53 12
     {
54
-      title: '推送对象',
55
-      key: 'pushPerson',
13
+      title: '消息',
14
+      key: 'messageType',
15
+      dataIndex: 'messageType',
56 16
       search: false,
57
-      dataIndex: 'pushPerson',
58
-      render: (t, record) => (record.pushPerson === 1 ? '农机手' : '农户'),
59
-    },
60
-
61
-    {
62
-      title: '推送方式',
63
-      key: 'status',
64
-      dataIndex: 'status',
65
-      // render: (t, record) => record.status === 1 ? '发布' : '未发布',
66
-      formItemProps: { label: '推送方式' },
67
-      valueType: 'select',
68
-      valueEnum: {
69
-        0: { text: '通知栏推送' },
70
-        1: { text: 'APP内消息中心推送' },
71
-        2: { text: '短信推送' },
17
+      render: (t, record) => {
18
+        console.log(t);
19
+        if (t === 'appoint') {
20
+          return record.appointTime + ' ' + record.appointPerson + ' 预约了一台' + record.appointMachineryType + '。'
21
+        }
22
+        else {
23
+          return record.acceptTime + ' ' + record.acceptPerson + ' 接到了一个订单。'
24
+        }
72 25
       },
73
-    },
74
-
75
-    {
76
-      title: (
77
-        <>
78
-          创建时间
79
-          <Tooltip placement="top">
80
-            <QuestionCircleOutlined style={{ marginLeft: 4 }} />
81
-          </Tooltip>
82
-        </>
83
-      ),
84
-      width: 140,
85
-      key: 'createdAt',
86
-      dataIndex: 'createdAt',
87
-      valueType: 'date',
88
-      // render: (t) => formatterTime(t),
89
-      sorter: (a, b) => a.createdAt - b.createdAt,
90
-    },
91
-
92
-    {
93
-      title: '操作',
94
-      valueType: 'option',
95
-      width: '300px',
96
-      render: (_, record) => [
97
-        <Link key={2} to={`./MessageEdit`}>
98
-          编辑
99
-        </Link>,
100
-        <Popconfirm
101
-          key={3}
102
-          title="您是否确认删除 ?"
103
-          onConfirm={() => handleDelete(record.noticeId)}
104
-          okText="确定"
105
-          cancelText="取消"
106
-        >
107
-          <a href="#">删除</a>
108
-        </Popconfirm>,
109
-      ],
110
-    },
26
+    }
111 27
   ];
112 28
 
113 29
   return (
114 30
     <PageHeaderWrapper>
115
-      {/* <ProTable
116
-        dataSource={dataSource}
31
+      <PageTable
32
+        request={getWorkMassageList}
117 33
         columns={columns}
118
-        // request={getList}
119
-        rowKey="id"
34
+        rowKey="messageId"
120 35
         options={false}
121
-        toolBarRender={actions}
122
-        scroll={{ x: 1000 }}
123
-      /> */}
36
+      />
124 37
     </PageHeaderWrapper>
125 38
   );
126 39
 };

+ 80
- 0
src/pages/SystemManagement/Classification/index.jsx View File

@@ -0,0 +1,80 @@
1
+import React, { useState, useEffect, useRef } from 'react';
2
+import { Button, Popconfirm, Modal, Form, Input, message } from 'antd';
3
+import { PageHeaderWrapper } from '@ant-design/pro-layout';
4
+import PageTable from '@/components/PageTable';
5
+
6
+export default (props) => {
7
+  const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 14 } };
8
+  const [form] = Form.useForm();
9
+  const [editModal, setEditModal] = useState(false);
10
+  const [loading, setLoading] = useState(false);
11
+  const [regionId, setRegionId] = useState();
12
+  const actionRef = useRef();
13
+
14
+  const dataSource = [
15
+    {
16
+      key: '1',
17
+      name: '监控记录仪',
18
+      createDate: '2022-06-05',
19
+      status: '',
20
+    },
21
+    {
22
+      key: '2',
23
+      name: '深松传感器',
24
+      createDate: '2022-03-27',
25
+      status: '',
26
+    },
27
+    {
28
+      key: '3',
29
+      name: '无人机设备',
30
+      createDate: '2022-03-13',
31
+      status: '',
32
+    },
33
+    {
34
+      key: '4',
35
+      name: '',
36
+      createDate: '2022-03-13',
37
+      status: '',
38
+    },
39
+    {
40
+      key: '5',
41
+      name: '',
42
+      createDate: '2022-03-13',
43
+      status: '',
44
+    },
45
+  ];
46
+
47
+  const columns = [
48
+    {
49
+      title: '分类名',
50
+      dataIndex: 'name',
51
+      key: 'name',
52
+    },
53
+    {
54
+      title: '创建时间',
55
+      dataIndex: 'createDate',
56
+      key: 'createDate',
57
+      search: false,
58
+      width: 340,
59
+    },
60
+    {
61
+      title: '状态',
62
+      dataIndex: 'status',
63
+      key: 'status',
64
+      search: false,
65
+    },
66
+  ];
67
+
68
+  return (
69
+    <PageHeaderWrapper>
70
+      <PageTable
71
+        columns={columns}
72
+        dataSource={dataSource}
73
+        actionRef={actionRef}
74
+        options={false}
75
+        // toolBarRender={actions}
76
+        scroll={{ x: 1000 }}
77
+      />
78
+    </PageHeaderWrapper>
79
+  );
80
+};

+ 177
- 0
src/pages/SystemManagement/Sensing/index.jsx View File

@@ -0,0 +1,177 @@
1
+import React, { useState, useEffect, useRef } from 'react';
2
+import { Button, Popconfirm, Modal, Form, Input, message } from 'antd';
3
+import { PageHeaderWrapper } from '@ant-design/pro-layout';
4
+import moment from 'moment';
5
+import PageTable from '@/components/PageTable';
6
+
7
+const formatterTime = (val) => {
8
+  return val && val !== '-' ? moment(val).format('YYYY-MM-DD') : '-';
9
+};
10
+const FormItem = Form.Item;
11
+
12
+export default (props) => {
13
+  const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 14 } };
14
+  const [form] = Form.useForm();
15
+  const [editModal, setEditModal] = useState(false);
16
+  const [loading, setLoading] = useState(false);
17
+  const [regionId, setRegionId] = useState();
18
+  const actionRef = useRef();
19
+
20
+  // const Submit = (values) => {
21
+  //   setLoading(true);
22
+  //   if (regionId) {
23
+  //     updateRegion(regionId, values).then(() => {
24
+  //       setLoading(false);
25
+  //       message.success(`修改成功`);
26
+  //       onCancel();
27
+  //       actionRef.current.reload();
28
+  //     }).catch((err) => {
29
+  //       setLoading(false);
30
+  //       console.log(err.message)
31
+  //     });
32
+  //   } else {
33
+  //     addRegion(values)
34
+  //       .then(() => {
35
+  //         setLoading(false);
36
+  //         message.success(`保存成功`);
37
+  //         onCancel();
38
+  //         actionRef.current.reload();
39
+  //       })
40
+  //       .catch((err) => {
41
+  //         setLoading(false);
42
+  //         message.error(err.message || err);
43
+  //       });
44
+  //   }
45
+  // };
46
+  // const handelEdit = (val) => {
47
+  //   setRegionId(val.regionId);
48
+  //   form.setFieldsValue(val);
49
+  //   setEditModal(true);
50
+  // };
51
+  // const onCancel = () => {
52
+  //   setRegionId();
53
+  //   form.resetFields();
54
+  //   setEditModal(false);
55
+  // };
56
+  // const handleDelete = (id) => {
57
+  //   deleteRegion(id)
58
+  //     .then(() => {
59
+  //       message.success('删除成功');
60
+  //       actionRef.current.reload();
61
+  //     })
62
+  //     .catch((err) => {
63
+  //       console.log(err.message)
64
+  //     });
65
+  // };
66
+  // useEffect(() => {
67
+  //   if (regionId) {
68
+  //   } else {
69
+  //     form.resetFields();
70
+  //   }
71
+  // }, [regionId]);
72
+  // const actions = () => [
73
+  //   <Button key="add" type="primary" icon={<PlusOutlined />} onClick={() => setEditModal(true)}>
74
+  //     新增
75
+  //   </Button>,
76
+  // ];
77
+  const columns = [
78
+    {
79
+      title: '行号',
80
+      dataIndex: 'name',
81
+      key: 'name',
82
+    },
83
+    {
84
+      title: '设备编号',
85
+      dataIndex: 'name',
86
+      key: 'name',
87
+      search: false,
88
+    },
89
+    {
90
+      title: '设备类型',
91
+      dataIndex: 'name',
92
+      key: 'name',
93
+    },
94
+    {
95
+      title: '在线状态',
96
+      dataIndex: 'name',
97
+      key: 'name',
98
+    },
99
+    {
100
+      title: '注册时间',
101
+      dataIndex: 'createDate',
102
+      key: 'createDate',
103
+      render: formatterTime,
104
+      search: false,
105
+      width: 240,
106
+    },
107
+    {
108
+      title: '绑定农机',
109
+      dataIndex: 'name',
110
+      key: 'name',
111
+      search: false,
112
+    },
113
+    {
114
+      title: '操作',
115
+      valueType: 'option',
116
+      width: 160,
117
+      render: (_, record) => [
118
+        <Button type="link" style={{ padding: 0 }} key={1} onClick={() => handelEdit(record)}>
119
+          编辑
120
+        </Button>,
121
+        <Popconfirm
122
+          key={2}
123
+          title="您是否确认删除 ?"
124
+          onConfirm={() => handleDelete(record.regionId)}
125
+          okText="确定"
126
+          cancelText="取消"
127
+        >
128
+          <Button style={{ padding: 0 }} type="link">
129
+            删除
130
+          </Button>
131
+        </Popconfirm>,
132
+      ],
133
+    },
134
+  ];
135
+
136
+  return (
137
+    <PageHeaderWrapper>
138
+      <PageTable
139
+        columns={columns}
140
+        actionRef={actionRef}
141
+        rowKey="regionId"
142
+        options={false}
143
+        // toolBarRender={actions}
144
+        scroll={{ x: 1000 }}
145
+      />
146
+      {/* <Modal
147
+        forceRender
148
+        title={regionId ? '区域编辑' : '区域新增'}
149
+        visible={editModal}
150
+        onCancel={onCancel}
151
+        keyboard={false}
152
+        maskClosable={false}
153
+        destroyOnClose={true}
154
+        footer={null}
155
+      >
156
+        <Form {...formItemLayout} onFinish={Submit} form={form}>
157
+          <FormItem label="区域名" name="name" rules={[{ required: true, message: '请输入' }]}>
158
+            <Input placeholder="请输入" />
159
+          </FormItem>
160
+          <FormItem label=" " colon={false}>
161
+            <Button type="default" onClick={onCancel}>
162
+              取消
163
+            </Button>
164
+            <Button
165
+              type="primary"
166
+              loading={loading}
167
+              htmlType="Submit"
168
+              style={{ marginLeft: '4em' }}
169
+            >
170
+              确认
171
+            </Button>
172
+          </FormItem>
173
+        </Form>
174
+      </Modal> */}
175
+    </PageHeaderWrapper>
176
+  );
177
+};

+ 24
- 0
src/pages/SystemManagement/Subsoiler/index.jsx View File

@@ -0,0 +1,24 @@
1
+import React, { useState, useEffect, useRef } from 'react';
2
+import { Descriptions, Form, Card } from 'antd';
3
+import { PageHeaderWrapper } from '@ant-design/pro-layout';
4
+
5
+export default (props) => {
6
+
7
+  return (
8
+    <PageHeaderWrapper>
9
+      <Card>
10
+        <Descriptions title="深松机平台参数" column={1}>
11
+          <Descriptions.Item label="接口域名">inter-query.huidatech.cn</Descriptions.Item>
12
+          <Descriptions.Item label="账号密码">njsyzkj0641</Descriptions.Item>
13
+          <Descriptions.Item label="密码">dTX7o3</Descriptions.Item>
14
+          <Descriptions.Item label="厂家ID">njsyzkj_hd_20221014155214766</Descriptions.Item>
15
+          <Descriptions.Item label="推送GUID">401cf971587342619ffcf7bbad1ef92d</Descriptions.Item>
16
+          <Descriptions.Item label="大写缩写">njsyzkj</Descriptions.Item>
17
+          <Descriptions.Item label="公司名称">南京市云致科技服务有限公司</Descriptions.Item>
18
+          <Descriptions />
19
+          <Descriptions>参数由平台配置,请勿修改,如需修改,请联系技术</Descriptions>
20
+        </Descriptions>
21
+      </Card>
22
+    </PageHeaderWrapper >
23
+  );
24
+};

+ 15
- 38
src/pages/customer/index.jsx View File

@@ -3,69 +3,46 @@ import { DatePicker } from 'antd';
3 3
 import { PageHeaderWrapper } from '@ant-design/pro-layout';
4 4
 import moment from 'moment';
5 5
 import PageTable from '@/components/PageTable';
6
-import { getUserList } from '@/services/user'
6
+import { getPersonList } from '@/services/person';
7 7
 
8 8
 const formatterTime = (val) => {
9 9
   return val ? moment(val).format('YYYY-MM-DD HH:mm') : '';
10 10
 };
11
-const { RangePicker } = DatePicker;
12 11
 
13 12
 export default (props) => {
14
-  const [start, setStartDate] = useState()
15
-  const [end, setEndDate] = useState()
16
-
17
-  const handelChange = (date, dateStrings) => {
18
-    setStartDate(dateStrings[0])
19
-    setEndDate(dateStrings[1])
20
-  }
21 13
   const ref = useRef();
14
+
22 15
   const Reset = () => {
23
-    setStartDate()
24
-    setEndDate()
25 16
     ref.current.reload();
26
-  }
17
+  };
27 18
 
28 19
   const columns = [
29 20
     {
30
-      title: '姓名',
31
-      dataIndex: 'name',
32
-      key: 'name',
21
+      title: '昵称',
22
+      dataIndex: 'nickName',
23
+      key: 'nickName',
33 24
     },
34 25
     {
35 26
       title: '头像',
36 27
       dataIndex: 'avatar',
37 28
       key: 'avatar',
38
-      search: false
29
+      render: (src) =>
30
+        src != '-' && (
31
+          <img src={src} alt="" style={{ width: '64px', height: '64px', borderRadius: '4px' }} />
32
+        ),
33
+      search: false,
39 34
     },
40 35
     {
41 36
       title: '手机号',
42 37
       dataIndex: 'phone',
43 38
       key: 'phone',
44 39
     },
45
-    {
46
-      title: '身份',
47
-      dataIndex: 'type',
48
-      key: 'type',
49
-      dataIndex: 'position',
50
-      render: (_, record) => {
51
-        return record.position === 'farmer'
52
-          ? '农户'
53
-          : record.position === 'worker'
54
-            ? '农机手' : ''
55
-      },
56
-      valueType: 'select',
57
-      valueEnum: {
58
-        'farmer': { text: '农户' },
59
-        'worker': { text: '农机手' },
60
-      },
61
-    },
62
-
63 40
     {
64 41
       title: '注册时间',
65 42
       dataIndex: 'createDate',
66 43
       key: 'createDate',
67 44
       render: (t, render) => formatterTime(render.createDate),
68
-      renderFormItem: (_, record) => <RangePicker placeholder={['开始日期', '结束日期']} format='YYYY-MM-DD' onChange={handelChange} />
45
+      search: false,
69 46
     },
70 47
   ];
71 48
 
@@ -73,11 +50,11 @@ export default (props) => {
73 50
     <PageHeaderWrapper>
74 51
       <PageTable
75 52
         actionRef={ref}
76
-        request={getUserList}
53
+        request={getPersonList}
77 54
         // expfunc={exportPersonList}
78 55
         columns={columns}
79
-        rowKey="userId"
80
-        params={{ start, end }}
56
+        rowKey="personId"
57
+        params={{ identity: 'farmer' }}
81 58
         onReset={Reset}
82 59
         options={false}
83 60
       />

+ 197
- 207
src/pages/document.ejs View File

@@ -1,238 +1,228 @@
1 1
 <!DOCTYPE html>
2 2
 <html lang="en">
3
-  <head>
4
-    <meta charset="UTF-8" />
5
-    <meta name="theme-color" content="#1890ff" />
6
-    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
7
-    <meta
8
-      name="keywords"
9
-      content="antd,umi,umijs,ant design,Scaffolding, layout, Ant Design, project, Pro, admin, console, homepage, out-of-the-box, middle and back office, solution, component library"
10
-    />
11
-    <meta
12
-      name="description"
13
-      content="
14
-    An out-of-box UI solution for enterprise applications as a React boilerplate."
15
-    />
16
-    <meta
17
-      name="description"
18
-      content="
19
-      Out-of-the-box mid-stage front-end/design solution."
20
-    />
21
-    <meta
22
-      name="viewport"
23
-      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
24
-    />
25
-    <title>Ant Design Pro</title>
26
-    <link rel="icon" href="<%= context.config.publicPath +'favicon.ico'%>" type="image/x-icon" />
27
-    <script src="./js/particles.min.js"></script>
28
-    <script src="./js/jsWebControl-1.0.0.min.js"></script>
29
-  </head>
30
-  <body>
31
-    <noscript>
32
-      <div class="noscript-container">
33
-        Hi there! Please
34
-        <div class="noscript-enableJS">
35
-          <a href="https://www.enablejavascript.io/en" target="_blank" rel="noopener noreferrer">
36
-            <b>enable Javascript</b>
37
-          </a>
38
-        </div>
39
-        in your browser to use Ant Design, Out-of-the-box mid-stage front/design solution!
3
+
4
+<head>
5
+  <meta charset="UTF-8" />
6
+  <meta name="theme-color" content="#1890ff" />
7
+  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
8
+  <meta name="keywords"
9
+    content="antd,umi,umijs,ant design,Scaffolding, layout, Ant Design, project, Pro, admin, console, homepage, out-of-the-box, middle and back office, solution, component library" />
10
+  <meta name="description" content="
11
+    An out-of-box UI solution for enterprise applications as a React boilerplate." />
12
+  <meta name="description" content="
13
+      Out-of-the-box mid-stage front-end/design solution." />
14
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
15
+  <title>邓州农机数据可视化平台</title>
16
+  <link rel="icon" href="./logo.png" type="image/x-icon" />
17
+  <script src="./js/particles.min.js"></script>
18
+  <script src="./js/jsWebControl-1.0.0.min.js"></script>
19
+</head>
20
+
21
+<body>
22
+  <noscript>
23
+    <div class="noscript-container">
24
+      Hi there! Please
25
+      <div class="noscript-enableJS">
26
+        <a href="https://www.enablejavascript.io/en" target="_blank" rel="noopener noreferrer">
27
+          <b>enable Javascript</b>
28
+        </a>
40 29
       </div>
41
-    </noscript>
42
-    <div id="root">
43
-      <style>
44
-        html,
45
-        body,
46
-        #root {
47
-          height: 100%;
48
-          margin: 0;
49
-          padding: 0;
50
-        }
51
-        #root {
52
-          background-repeat: no-repeat;
53
-          background-size: 100% auto;
54
-        }
55
-        .noscript-container {
56
-          display: flex;
57
-          align-content: center;
58
-          justify-content: center;
59
-          margin-top: 90px;
60
-          font-size: 20px;
61
-          font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode',
62
-            Geneva, Verdana, sans-serif;
63
-        }
64
-        .noscript-enableJS {
65
-          padding-right: 3px;
66
-          padding-left: 3px;
67
-        }
68
-        .page-loading-warp {
69
-          display: flex;
70
-          align-items: center;
71
-          justify-content: center;
72
-          padding: 98px;
73
-        }
74
-        .ant-spin {
75
-          position: absolute;
76
-          display: none;
77
-          -webkit-box-sizing: border-box;
78
-          box-sizing: border-box;
79
-          margin: 0;
80
-          padding: 0;
81
-          color: rgba(0, 0, 0, 0.65);
82
-          color: #1890ff;
83
-          font-size: 14px;
84
-          font-variant: tabular-nums;
85
-          line-height: 1.5;
86
-          text-align: center;
87
-          list-style: none;
88
-          opacity: 0;
89
-          -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
90
-          transition: -webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
91
-          transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
92
-          transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86),
93
-            -webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
94
-          -webkit-font-feature-settings: 'tnum';
95
-          font-feature-settings: 'tnum';
96
-        }
30
+      in your browser to use Ant Design, Out-of-the-box mid-stage front/design solution!
31
+    </div>
32
+  </noscript>
33
+  <div id="root">
34
+    <style>
35
+      html,
36
+      body,
37
+      #root {
38
+        height: 100%;
39
+        margin: 0;
40
+        padding: 0;
41
+      }
97 42
 
98
-        .ant-spin-spinning {
99
-          position: static;
100
-          display: inline-block;
101
-          opacity: 1;
102
-        }
43
+      #root {
44
+        background-repeat: no-repeat;
45
+        background-size: 100% auto;
46
+      }
103 47
 
104
-        .ant-spin-dot {
105
-          position: relative;
106
-          display: inline-block;
107
-          width: 20px;
108
-          height: 20px;
109
-          font-size: 20px;
110
-        }
48
+      .noscript-container {
49
+        display: flex;
50
+        align-content: center;
51
+        justify-content: center;
52
+        margin-top: 90px;
53
+        font-size: 20px;
54
+        font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode',
55
+          Geneva, Verdana, sans-serif;
56
+      }
111 57
 
112
-        .ant-spin-dot-item {
113
-          position: absolute;
114
-          display: block;
115
-          width: 9px;
116
-          height: 9px;
117
-          background-color: #1890ff;
118
-          border-radius: 100%;
119
-          -webkit-transform: scale(0.75);
120
-          -ms-transform: scale(0.75);
121
-          transform: scale(0.75);
122
-          -webkit-transform-origin: 50% 50%;
123
-          -ms-transform-origin: 50% 50%;
124
-          transform-origin: 50% 50%;
125
-          opacity: 0.3;
126
-          -webkit-animation: antspinmove 1s infinite linear alternate;
127
-          animation: antSpinMove 1s infinite linear alternate;
128
-        }
58
+      .noscript-enableJS {
59
+        padding-right: 3px;
60
+        padding-left: 3px;
61
+      }
129 62
 
130
-        .ant-spin-dot-item:nth-child(1) {
131
-          top: 0;
132
-          left: 0;
133
-        }
63
+      .page-loading-warp {
64
+        display: flex;
65
+        align-items: center;
66
+        justify-content: center;
67
+        padding: 98px;
68
+      }
134 69
 
135
-        .ant-spin-dot-item:nth-child(2) {
136
-          top: 0;
137
-          right: 0;
138
-          -webkit-animation-delay: 0.4s;
139
-          animation-delay: 0.4s;
140
-        }
70
+      .ant-spin {
71
+        position: absolute;
72
+        display: none;
73
+        -webkit-box-sizing: border-box;
74
+        box-sizing: border-box;
75
+        margin: 0;
76
+        padding: 0;
77
+        color: rgba(0, 0, 0, 0.65);
78
+        color: #1890ff;
79
+        font-size: 14px;
80
+        font-variant: tabular-nums;
81
+        line-height: 1.5;
82
+        text-align: center;
83
+        list-style: none;
84
+        opacity: 0;
85
+        -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
86
+        transition: -webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
87
+        transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
88
+        transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86),
89
+          -webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
90
+        -webkit-font-feature-settings: 'tnum';
91
+        font-feature-settings: 'tnum';
92
+      }
141 93
 
142
-        .ant-spin-dot-item:nth-child(3) {
143
-          right: 0;
144
-          bottom: 0;
145
-          -webkit-animation-delay: 0.8s;
146
-          animation-delay: 0.8s;
147
-        }
94
+      .ant-spin-spinning {
95
+        position: static;
96
+        display: inline-block;
97
+        opacity: 1;
98
+      }
148 99
 
149
-        .ant-spin-dot-item:nth-child(4) {
150
-          bottom: 0;
151
-          left: 0;
152
-          -webkit-animation-delay: 1.2s;
153
-          animation-delay: 1.2s;
154
-        }
100
+      .ant-spin-dot {
101
+        position: relative;
102
+        display: inline-block;
103
+        width: 20px;
104
+        height: 20px;
105
+        font-size: 20px;
106
+      }
155 107
 
156
-        .ant-spin-dot-spin {
157
-          -webkit-transform: rotate(45deg);
158
-          -ms-transform: rotate(45deg);
159
-          transform: rotate(45deg);
160
-          -webkit-animation: antrotate 1.2s infinite linear;
161
-          animation: antRotate 1.2s infinite linear;
162
-        }
108
+      .ant-spin-dot-item {
109
+        position: absolute;
110
+        display: block;
111
+        width: 9px;
112
+        height: 9px;
113
+        background-color: #1890ff;
114
+        border-radius: 100%;
115
+        -webkit-transform: scale(0.75);
116
+        -ms-transform: scale(0.75);
117
+        transform: scale(0.75);
118
+        -webkit-transform-origin: 50% 50%;
119
+        -ms-transform-origin: 50% 50%;
120
+        transform-origin: 50% 50%;
121
+        opacity: 0.3;
122
+        -webkit-animation: antspinmove 1s infinite linear alternate;
123
+        animation: antSpinMove 1s infinite linear alternate;
124
+      }
163 125
 
164
-        .ant-spin-lg .ant-spin-dot {
165
-          width: 32px;
166
-          height: 32px;
167
-          font-size: 32px;
168
-        }
126
+      .ant-spin-dot-item:nth-child(1) {
127
+        top: 0;
128
+        left: 0;
129
+      }
169 130
 
170
-        .ant-spin-lg .ant-spin-dot i {
171
-          width: 14px;
172
-          height: 14px;
173
-        }
131
+      .ant-spin-dot-item:nth-child(2) {
132
+        top: 0;
133
+        right: 0;
134
+        -webkit-animation-delay: 0.4s;
135
+        animation-delay: 0.4s;
136
+      }
174 137
 
175
-        @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
176
-          .ant-spin-blur {
177
-            background: #fff;
178
-            opacity: 0.5;
179
-          }
180
-        }
138
+      .ant-spin-dot-item:nth-child(3) {
139
+        right: 0;
140
+        bottom: 0;
141
+        -webkit-animation-delay: 0.8s;
142
+        animation-delay: 0.8s;
143
+      }
144
+
145
+      .ant-spin-dot-item:nth-child(4) {
146
+        bottom: 0;
147
+        left: 0;
148
+        -webkit-animation-delay: 1.2s;
149
+        animation-delay: 1.2s;
150
+      }
181 151
 
182
-        @-webkit-keyframes antSpinMove {
183
-          to {
184
-            opacity: 1;
185
-          }
152
+      .ant-spin-dot-spin {
153
+        -webkit-transform: rotate(45deg);
154
+        -ms-transform: rotate(45deg);
155
+        transform: rotate(45deg);
156
+        -webkit-animation: antrotate 1.2s infinite linear;
157
+        animation: antRotate 1.2s infinite linear;
158
+      }
159
+
160
+      .ant-spin-lg .ant-spin-dot {
161
+        width: 32px;
162
+        height: 32px;
163
+        font-size: 32px;
164
+      }
165
+
166
+      .ant-spin-lg .ant-spin-dot i {
167
+        width: 14px;
168
+        height: 14px;
169
+      }
170
+
171
+      @media all and (-ms-high-contrast: none),
172
+      (-ms-high-contrast: active) {
173
+        .ant-spin-blur {
174
+          background: #fff;
175
+          opacity: 0.5;
186 176
         }
177
+      }
187 178
 
188
-        @keyframes antSpinMove {
189
-          to {
190
-            opacity: 1;
191
-          }
179
+      @-webkit-keyframes antSpinMove {
180
+        to {
181
+          opacity: 1;
192 182
         }
183
+      }
193 184
 
194
-        @-webkit-keyframes antRotate {
195
-          to {
196
-            -webkit-transform: rotate(405deg);
197
-            transform: rotate(405deg);
198
-          }
185
+      @keyframes antSpinMove {
186
+        to {
187
+          opacity: 1;
199 188
         }
189
+      }
200 190
 
201
-        @keyframes antRotate {
202
-          to {
203
-            -webkit-transform: rotate(405deg);
204
-            transform: rotate(405deg);
205
-          }
191
+      @-webkit-keyframes antRotate {
192
+        to {
193
+          -webkit-transform: rotate(405deg);
194
+          transform: rotate(405deg);
206 195
         }
207
-      </style>
208
-      <div
209
-        style="
196
+      }
197
+
198
+      @keyframes antRotate {
199
+        to {
200
+          -webkit-transform: rotate(405deg);
201
+          transform: rotate(405deg);
202
+        }
203
+      }
204
+    </style>
205
+    <div style="
210 206
           display: flex;
211 207
           flex-direction: column;
212 208
           align-items: center;
213 209
           justify-content: center;
214 210
           height: 100%;
215 211
           min-height: 420px;
216
-        "
217
-      >
218
-        <img src="<%= context.config.publicPath +'pro_icon.svg'%>" alt="logo" width="256" />
219
-        <div class="page-loading-warp">
220
-          <div class="ant-spin ant-spin-lg ant-spin-spinning">
221
-            <span class="ant-spin-dot ant-spin-dot-spin"
222
-              ><i class="ant-spin-dot-item"></i><i class="ant-spin-dot-item"></i
223
-              ><i class="ant-spin-dot-item"></i><i class="ant-spin-dot-item"></i
224
-            ></span>
225
-          </div>
226
-        </div>
227
-        <div style="display: flex; align-items: center; justify-content: center">
228
-          <img
229
-            src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
230
-            width="32"
231
-            style="margin-right: 8px"
232
-          />
233
-          Ant Design
212
+        ">
213
+      <img src="./logo.png" alt="logo" width="256" />
214
+      <div class="page-loading-warp">
215
+        <div class="ant-spin ant-spin-lg ant-spin-spinning">
216
+          <span class="ant-spin-dot ant-spin-dot-spin"><i class="ant-spin-dot-item"></i><i
217
+              class="ant-spin-dot-item"></i><i class="ant-spin-dot-item"></i><i class="ant-spin-dot-item"></i></span>
234 218
         </div>
235 219
       </div>
220
+      <div style="display: flex; align-items: center; justify-content: center">
221
+        <img src="./logo.png" width="32" style="margin-right: 8px" />
222
+        南京云致
223
+      </div>
236 224
     </div>
237
-  </body>
238
-</html>
225
+  </div>
226
+</body>
227
+
228
+</html>

+ 2
- 2
src/services/device.js View File

@@ -5,7 +5,7 @@ import request from '@/utils/request';
5 5
  * @param {*} params
6 6
  * @returns
7 7
  */
8
-export const getDeviceList = (params) => request('/hatc-device', { params });
8
+export const getHatcDeviceList = (params) => request('/hatc-device', { params });
9 9
 
10 10
 /**
11 11
  * 通过设备号查询相关设备列表  选好了点击绑定时根据当前选择的设备id查询
@@ -21,7 +21,7 @@ export const getTerminalDeviceList = (id) => request(`/hatc-device/${id}`);
21 21
  * @param {*} params
22 22
  * @returns
23 23
  */
24
-export const getdeviceDetail = (id) => request(`/machinery/${id}/device`);
24
+export const getDeviceDetail = (id) => request(`/machinery/${id}/device`);
25 25
 
26 26
 //  新增修改设备信息
27 27
 /**

+ 15
- 1
src/services/job.js View File

@@ -1,8 +1,22 @@
1 1
 import request from '@/utils/request';
2 2
 
3 3
 /**
4
- * 查询农机列表
4
+ * 查询作业列表
5 5
  * @param {*} params
6 6
  * @returns
7 7
  */
8 8
 export const getJobList = (params) => request('/work-job', { params });
9
+
10
+/**
11
+ * 查询作业详情
12
+ * @param {*} params
13
+ * @returns
14
+ */
15
+export const getJobDetail = (id) => request(`/work-job/${id}`);
16
+
17
+/**
18
+ * 查询作业GIS
19
+ * @param {*} params
20
+ * @returns
21
+ */
22
+export const getJobGISDetail = (params) => request(`/machinery-gps`, { params });

+ 59
- 0
src/services/monitoringScreen.js View File

@@ -0,0 +1,59 @@
1
+import request from '@/utils/request';
2
+
3
+/**
4
+ * 基本数据统计
5
+ * @param {*} params
6
+ * @returns
7
+ */
8
+export const getBasic = (params) => request('/screen-data/basic', { params });
9
+
10
+/**
11
+ * 所有合作社
12
+ * @param {*} params
13
+ * @returns
14
+ */
15
+export const getOrgDetail = (params) => request('/screen-data/org', { params });
16
+
17
+/**
18
+ *  农机类型列表
19
+ * @param {*} params
20
+ * @returns
21
+ */
22
+export const getTypeList = (params) => request('/screen-data/machinery-type', { params });
23
+
24
+/**
25
+ *  农机作业面积统计
26
+ * @param {*} params
27
+ * @returns
28
+ */
29
+export const getAreaDetail = (params) => request('/screen-data/machinery-type/area', { params });
30
+
31
+/**
32
+ *  农机类型统计(左上角柱状图)
33
+ * @param {*} params
34
+ * @returns
35
+ */
36
+export const getMachineryBar = (params) =>
37
+  request('/screen-data/machinery-type/machinery', { params });
38
+
39
+/**
40
+ *  农机作业数统计
41
+ * @param {*} params
42
+ * @returns
43
+ */
44
+export const getWorkNumPie = (params) =>
45
+  request('/screen-data/machinery-type/work-job', { params });
46
+
47
+/**
48
+ *  依据类型查询农机
49
+ * @param {*} params
50
+ * @returns
51
+ */
52
+export const getTypeBasic = (params) => request('/screen-data/machinery/all', { params });
53
+
54
+/**
55
+ *  获取消息通知列表
56
+ * @param {*} params
57
+ * @returns
58
+ */
59
+export const getMessageList = (params) => request('/screen-data/message', { params });

+ 8
- 0
src/services/person.js View File

@@ -0,0 +1,8 @@
1
+import request from '@/utils/request';
2
+
3
+/**
4
+ * 查询用户列表
5
+ * @param {*} params
6
+ * @returns
7
+ */
8
+export const getPersonList = (params) => request('/person', { params });

+ 8
- 0
src/services/workMessage.js View File

@@ -0,0 +1,8 @@
1
+import request from '@/utils/request';
2
+
3
+/**
4
+ * 查询消息列表
5
+ * @param {*} params
6
+ * @returns
7
+ */
8
+export const getWorkMassageList = (params) => request('/work-message', { params });

+ 66
- 0
src/utils/mapTogcj02.js View File

@@ -0,0 +1,66 @@
1
+//纬度转换
2
+function transformLatitude(x, y) {
3
+  let num = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
4
+  num += ((20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0) / 3.0;
5
+  num += ((20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin((y / 3.0) * Math.PI)) * 2.0) / 3.0;
6
+  num +=
7
+    ((160.0 * Math.sin((y / 12.0) * Math.PI) + 320 * Math.sin((y * Math.PI) / 30.0)) * 2.0) / 3.0;
8
+  return num;
9
+}
10
+//经度转换
11
+function transformLongitude(x, y) {
12
+  let num = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
13
+  num += ((20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0) / 3.0;
14
+  num += ((20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin((x / 3.0) * Math.PI)) * 2.0) / 3.0;
15
+  num +=
16
+    ((150.0 * Math.sin((x / 12.0) * Math.PI) + 300.0 * Math.sin((x / 30.0) * Math.PI)) * 2.0) / 3.0;
17
+  return num;
18
+}
19
+// 坐标转换
20
+function calculation(longitude, latitude) {
21
+  let a = 6378245.0; // 卫星椭球坐标投影到平面地图坐标系的投影因子。
22
+  let ee = 0.00669342162296594323; // 椭球的偏心率。
23
+  let lat = transformLatitude(longitude - 105.0, latitude - 35.0);
24
+  let lng = transformLongitude(longitude - 105.0, latitude - 35.0);
25
+  let radLat = (latitude / 180.0) * Math.PI;
26
+  let magic = Math.sin(radLat);
27
+  magic = 1 - ee * magic * magic;
28
+  let sqrtMagic = Math.sqrt(magic);
29
+  lat = (lat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * Math.PI);
30
+  lng = (lng * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * Math.PI);
31
+  return {
32
+    longitude: lng,
33
+    latitude: lat,
34
+  };
35
+}
36
+// 判断是否为国外坐标
37
+function isOutOfChina(longitude, latitude) {
38
+  if (longitude < 72.004 || longitude > 137.8347) {
39
+    return true;
40
+  }
41
+  if (latitude < 0.8293 || latitude > 55.8271) {
42
+    return true;
43
+  }
44
+  return false;
45
+}
46
+// GPS坐标 转 高德坐标
47
+function getCoordinate(long, lat) {
48
+  let longitude = Number(long);
49
+  let latitude = Number(lat);
50
+  if (isOutOfChina(longitude, latitude)) {
51
+    //国外
52
+    return {
53
+      longitude: longitude,
54
+      latitude: latitude,
55
+    };
56
+  } else {
57
+    //国内
58
+    let obj = calculation(longitude, latitude);
59
+    return {
60
+      longitude: longitude + obj.longitude,
61
+      latitude: latitude + obj.latitude,
62
+    };
63
+  }
64
+}
65
+
66
+export default getCoordinate;