李志伟 3 years ago
parent
commit
a3e7c91cec

+ 11
- 0
config/routes.js View File

@@ -78,6 +78,17 @@ export default [
78 78
         path: '/Machinery/Cooperative/edit.jsx',
79 79
         name: '合作社编辑',
80 80
         component: './Machinery/Cooperative/edit.jsx',
81
+        // hideInMenu: true,
82
+      },
83
+      {
84
+        path: '/Machinery/Employees',
85
+        name: '员工列表',
86
+        component: './Machinery/Employees',
87
+      },
88
+      {
89
+        path: '/Machinery/Employees/edit.jsx',
90
+        name: '员工编辑',
91
+        component: './Machinery/Employees/edit.jsx',
81 92
         hideInMenu: true,
82 93
       },
83 94
     ],

+ 132
- 0
src/components/AMap/SearchPOI.jsx View File

@@ -0,0 +1,132 @@
1
+
2
+import { useState, useEffect, useRef } from 'react'
3
+import loader from './loader'
4
+import { newMarker, autoPos, autoPoi } from './utils'
5
+
6
+const plugins = ['AMap.Scale', 'AMap.ToolBar', 'AMap.Geolocation', 'AMap.Autocomplete', 'AMap.PlaceSearch']
7
+
8
+export default (props) => {
9
+  const { className, style, onChange, value, setAddress, setLocName, setPkLocName, setParkingAddress, roomBoole } = props
10
+
11
+  const map = useRef()
12
+  const container = useRef()
13
+  const inputRef = useRef()
14
+  const posMarker = useRef()
15
+  const [currentPos, setCurrentPos] = useState([]);
16
+
17
+
18
+  const handleClick = (e) => {
19
+    const locationNmae = e?.target?.w?.label?.locationNmae
20
+    const name = e?.target?.w?.label?.name
21
+    const position = e?.target?.w?.label?.position
22
+    if (roomBoole) {
23
+      setLocName(name || '')
24
+      setAddress(locationNmae || '')
25
+    } else {
26
+      setPkLocName(name || '')
27
+      setParkingAddress(locationNmae || '')
28
+
29
+    }
30
+
31
+
32
+    const { lnglat } = e
33
+    const pos = [lnglat.getLng(), lnglat.getLat()]
34
+    posMarker.current.setMap(map.current);
35
+    setCurrentPos(pos)
36
+    onChange(pos.join(','))
37
+
38
+  }
39
+
40
+
41
+  useEffect(() => {
42
+    loader(plugins).then((AMap) => {
43
+      const instance = new AMap.Map(container.current, { zoom: 12 })
44
+      instance.addControl(new AMap.Scale())
45
+      instance.addControl(new AMap.ToolBar())
46
+
47
+      // 尝试自动定位到当前位置
48
+      if (!props.value) {
49
+        instance.addControl(autoPos(AMap))
50
+      }
51
+
52
+      // 当前选中点 - 初始的时候没有定位
53
+      posMarker.current = newMarker(AMap, {
54
+        active: true,
55
+        position: props.value ? props.value.split(',') : undefined,
56
+      })
57
+
58
+      if (props.value) {
59
+        posMarker.current.setMap(instance);
60
+      }
61
+
62
+      // POI 搜索
63
+      autoPoi(instance, AMap, inputRef, { click: handleClick })
64
+
65
+      instance.on('click', handleClick);
66
+      map.current = instance
67
+    })
68
+  }, [])
69
+
70
+  useEffect(() => {
71
+    if (value) {
72
+      setCurrentPos(value.split(','))
73
+    }
74
+  }, [value])
75
+
76
+  useEffect(() => {
77
+    if (currentPos.length) {
78
+      if (posMarker.current) {
79
+        posMarker.current.setPosition(currentPos)
80
+      }
81
+      if (map.current) {
82
+        map.current.setCenter(currentPos);
83
+      }
84
+      if (currentPos.length && map.current) {
85
+        posMarker.current.setMap(map.current)
86
+      }
87
+    }
88
+  }, [currentPos])
89
+
90
+
91
+  const boxStyle = {
92
+    width: '100%',
93
+    height: '400px',
94
+    position: 'relative',
95
+    ...(style || {}),
96
+  }
97
+
98
+  const mapStyle = {
99
+    height: '100%',
100
+    width: '100%',
101
+    margin: 0,
102
+  }
103
+
104
+  const inputStyle = {
105
+    width: '200px',
106
+    padding: '5px',
107
+    position: 'absolute',
108
+    zIndex: 9999,
109
+    right: '30px',
110
+    lineHeight: '1em',
111
+  }
112
+
113
+  const inputSty1 = {
114
+    ...inputStyle,
115
+    top: '50px',
116
+  }
117
+
118
+  const inputSty2 = {
119
+    ...inputStyle,
120
+    top: '10px',
121
+    background: 'rgba(255, 255, 255, .9)',
122
+    border: '1px solid #bbb',
123
+  }
124
+
125
+  return (
126
+    <div className={className} style={boxStyle}>
127
+      <div ref={container} style={mapStyle} id="poi-map-wrapper"></div>
128
+      <input placeholder="请输入搜索关键字" ref={inputRef} style={inputSty1} />
129
+      <input value={`坐标: ${currentPos.join(',')}`} style={inputSty2} disabled />
130
+    </div>
131
+  )
132
+}

+ 0
- 0
src/components/AMap/index.jsx View File


+ 19
- 0
src/components/AMap/loader.js View File

@@ -0,0 +1,19 @@
1
+import AMapLoader from '@amap/amap-jsapi-loader';
2
+
3
+const WEB_KEY = '29259f677b42900507074fd92ecb628a'
4
+const SERVER_KEY = '3be0a9567a794d2690d378476f057a6f'
5
+
6
+export default (plugins, uiPlugins) => {
7
+  return AMapLoader.load({
8
+    "key": WEB_KEY,              // 申请好的Web端开发者Key,首次调用 load 时必填
9
+    "version": "1.4.15",   // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
10
+    "plugins": plugins || [],           // 需要使用的的插件列表,如比例尺'AMap.Scale'等
11
+    "AMapUI": {             // 是否加载 AMapUI,缺省不加载
12
+      "version": '1.1',   // AMapUI 缺省 1.1
13
+      "plugins": uiPlugins || [],       // 需要加载的 AMapUI ui插件
14
+    },
15
+    "Loca": {                // 是否加载 Loca, 缺省不加载
16
+      "version": '1.3.2'  // Loca 版本,缺省 1.3.2
17
+    },
18
+  })
19
+}

+ 8
- 0
src/components/AMap/style.less View File

@@ -0,0 +1,8 @@
1
+:global{
2
+  #poi-map-wrapper {
3
+    .amap-marker-label{
4
+      border: 0;
5
+      background-color: transparent;
6
+    }
7
+  }
8
+}

+ 96
- 0
src/components/AMap/utils.js View File

@@ -0,0 +1,96 @@
1
+
2
+const iconNoraml = '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png';
3
+const iconActive = '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-red.png';
4
+
5
+export function newMarker(AMap, options = {}) {
6
+  const { active = false, ...params } = options;
7
+  const icon = new AMap.Icon({
8
+    size: new AMap.Size(25, 34),
9
+    image: active ? iconActive : iconNoraml,
10
+    imageSize: new AMap.Size(25, 34),
11
+  })
12
+  const offset = new AMap.Pixel(-13, -30)
13
+
14
+  return new AMap.Marker({ icon, offset, ...params });
15
+}
16
+
17
+export function autoPos(AMap, options = {}) {
18
+  return new AMap.Geolocation({
19
+    enableHighAccuracy: true,//是否使用高精度定位,默认:true
20
+    timeout: 10000,          //超过10秒后停止定位,默认:5s
21
+    buttonPosition: 'RB',    //定位按钮的停靠位置
22
+    buttonOffset: new AMap.Pixel(10, 20),//定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
23
+    zoomToAccuracy: true,   //定位成功后是否自动调整地图视野到定位点
24
+    ...options,
25
+  });
26
+}
27
+
28
+const labelStyle = `
29
+  padding: .5em .8em;
30
+  border-radius: .25rem;
31
+  background-color: white;
32
+  box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2);
33
+`
34
+
35
+export function autoPoi(map, AMap, inputRef, evt) {
36
+
37
+
38
+  var locationNmae = ''
39
+
40
+  const markers = [];
41
+  const input = inputRef.current
42
+
43
+  const destroy = () => {
44
+    if (markers.length) {
45
+      markers.forEach((m) => map.remove(m))
46
+      markers.splice(0, markers.length)
47
+    }
48
+  }
49
+
50
+  const handleSearchResult = (status, result) => {
51
+    // 先清空
52
+    destroy();
53
+
54
+    const { pois } = result.poiList;
55
+    (pois || []).forEach((poi) => {
56
+      const { location, name } = poi;
57
+      const pos = `${location.lng},${location.lat}`
58
+
59
+      const marker = newMarker(AMap, {
60
+        map,
61
+        position: location,
62
+
63
+        label: {
64
+          content: `<div style="${labelStyle}">${name}</div>`,
65
+          direction: 'top',
66
+          name: name,
67
+          locationNmae: locationNmae,
68
+          position: pos,
69
+
70
+
71
+        },
72
+      })
73
+      marker.on('click', evt.click)
74
+      markers.push(marker)
75
+    })
76
+    // map.setZoom(18);
77
+    map.setFitView();
78
+  }
79
+
80
+  const placeSearch = new AMap.PlaceSearch({ pageSize: 20 });
81
+  const autoComplete = new AMap.Autocomplete({ input });
82
+
83
+
84
+  // 选择自动填充
85
+  autoComplete.on('select', e => {
86
+    const val = `${e.poi?.district}${e.poi?.address}`
87
+    locationNmae = val
88
+    placeSearch.setCity(e.poi.adcode)
89
+    placeSearch.search(e.poi.name, handleSearchResult)
90
+
91
+  })
92
+
93
+  autoComplete.on('error', (err) => console.error(err))
94
+
95
+  return autoComplete;
96
+}

+ 43
- 0
src/components/POI/POI.jsx View File

@@ -0,0 +1,43 @@
1
+import { useEffect, useState } from 'react'
2
+import { Button, Modal } from 'antd'
3
+import SearchPOI from '@/components/AMap/SearchPOI'
4
+
5
+export default (props) => {
6
+  const { value, onChange, placeholder, setLocName, setAddress, setPkLocName, setParkingAddress, roomBoole } = props
7
+
8
+  const [showModal, setShowModal] = useState(false);
9
+  const [location, setLocation] = useState()
10
+
11
+  const handleOk = () => {
12
+    onChange(location)
13
+    setShowModal(false)
14
+  }
15
+
16
+  useEffect(() => {
17
+    setLocation(value)
18
+  }, [value])
19
+
20
+  return (
21
+    <div>
22
+      <Button type="link" onClick={() => setShowModal(true)}>{value || placeholder}</Button>
23
+      <Modal
24
+        title="请选择地址"
25
+        visible={showModal}
26
+        width={800}
27
+        bodyStyle={{ padding: 0 }}
28
+        onOk={handleOk}
29
+        onCancel={() => setShowModal(false)}
30
+      >
31
+        <SearchPOI
32
+          value={location}
33
+          onChange={onChange}
34
+          setLocName={setLocName}
35
+          setAddress={setAddress}
36
+          setPkLocName={setPkLocName}
37
+          setParkingAddress={setParkingAddress}
38
+          roomBoole={roomBoole}
39
+        />
40
+      </Modal>
41
+    </div>
42
+  )
43
+}

+ 11
- 1
src/pages/Machinery/Cooperative/index.jsx View File

@@ -1,6 +1,7 @@
1 1
 import React from 'react';
2 2
 import { history, Link } from 'umi';
3 3
 import { Button, Popconfirm, message, Tooltip } from 'antd';
4
+import { PlusOutlined } from '@ant-design/icons';
4 5
 // import { getPersonList, exportPersonList } from '@/services/person';
5 6
 import { PageHeaderWrapper } from '@ant-design/pro-layout';
6 7
 import moment from 'moment';
@@ -11,6 +12,15 @@ const formatterTime = (val) => {
11 12
 };
12 13
 
13 14
 export default (props) => {
15
+  const actions = () => [
16
+    <Button key="add" type="primary" icon={<PlusOutlined />} onClick={() => gotoDetail()}>
17
+      新增合作社
18
+    </Button>,
19
+  ];
20
+  const gotoDetail = (id) => {
21
+    const queryStr = id ? `?id=${id}` : '';
22
+    history.push(`./Cooperative/edit.jsx${queryStr}`);
23
+  };
14 24
   const columns = [
15 25
     {
16 26
       title: '合作社名',
@@ -71,7 +81,6 @@ export default (props) => {
71 81
         </Popconfirm>,
72 82
       ],
73 83
     },
74
-    // 农机列表点击进入详情页 下面是轨迹上面是时间
75 84
   ];
76 85
   const handleDelete = () => {};
77 86
   return (
@@ -82,6 +91,7 @@ export default (props) => {
82 91
         columns={columns}
83 92
         rowKey="cooperativeId"
84 93
         options={false}
94
+        toolBarRender={actions}
85 95
         scroll={{ x: 1000 }}
86 96
       />
87 97
     </PageHeaderWrapper>

+ 149
- 0
src/pages/Machinery/Employees/edit.jsx View File

@@ -0,0 +1,149 @@
1
+import { Form, Input, Card, InputNumber, Select, message, Button } from 'antd';
2
+import { history } from 'umi';
3
+import ProCard from '@ant-design/pro-card';
4
+import { useState, useEffect } from 'react';
5
+// import { getTagList } from '@/services/tag';
6
+// import { addAttaList, gettaTouristForm, EditaddAttaList } from '@/services/AttaList'
7
+
8
+const { TextArea } = Input;
9
+const { Option } = Select;
10
+const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 14 } };
11
+
12
+const goBack = () => {
13
+  history.goBack();
14
+};
15
+const FormItem = Form.Item;
16
+export default (props) => {
17
+  const { location } = props;
18
+  const { id } = location.query;
19
+  const [form] = Form.useForm();
20
+  const [listForm, setListForm] = useState({});
21
+  const [loading, setLoading] = useState(false);
22
+  const [imageList, setImageList] = useState([]);
23
+
24
+  const Submit = (data) => {
25
+    const typeList = (data.typeList || []).map((x) => {
26
+      return { ...x, targetId: id, targetType: 'tourist' };
27
+    });
28
+    setLoading(true);
29
+
30
+    // if (id) {
31
+    //   EditaddAttaList(id, { ...listForm, ...data, imageList, typeList }).then(() => {
32
+    //     setLoading(false);
33
+    //     message.success('数据更新成功');
34
+    //     goBack();
35
+    //   })
36
+    //     .catch(err => {
37
+    //       setLoading(false);
38
+    //       message.error(err.message || err);
39
+    //     });
40
+    // } else {
41
+    //   addAttaList({ ...data, imageList, typeList }).then((res) => {
42
+    //     setLoading(false);
43
+    //     message.success('数据保存成功');
44
+    //     history.replace(`/Attractions/Edit?id=${res.touristId}`)
45
+    //   })
46
+    //     .catch(err => {
47
+    //       setLoading(false);
48
+    //       message.error(err.message || err);
49
+    //     });
50
+    // }
51
+  };
52
+
53
+  //地址--占位
54
+  const [newLocName, setLocName] = useState('');
55
+  const [newAddress, setAddress] = useState('');
56
+
57
+  const selectTagList = (params) => {
58
+    // return getTagList({
59
+    // }).then((res) => {
60
+    // }).catch((err) => {
61
+    //   return {
62
+    //     success: false,
63
+    //   }
64
+    // })
65
+  };
66
+
67
+  const imageInput = (image) => {
68
+    return {
69
+      uid: image.imageId,
70
+      url: image.url,
71
+    };
72
+  };
73
+
74
+  const imageOutput = (image) => {
75
+    return {
76
+      imageId: image?.raw?.imageId,
77
+      shopId: id,
78
+      url: image.url,
79
+    };
80
+  };
81
+  useEffect(() => {
82
+    selectTagList();
83
+    // if (id) {
84
+    //   gettaTouristForm(id).then((res) => {
85
+    //     setListForm(res)
86
+    //     form.setFieldsValue(res)
87
+    //     setImageList(res?.imageList || [])
88
+    //   })
89
+    // }
90
+  }, [id]);
91
+
92
+  return (
93
+    <Card>
94
+      <ProCard tabs={{ type: 'card' }}>
95
+        <ProCard.TabPane key={1} tab="员工编辑">
96
+          <Form {...formItemLayout} onFinish={Submit} form={form}>
97
+            <FormItem label="姓名" name="name" rules={[{ required: true, message: '请输入姓名' }]}>
98
+              <Input placeholder="请输入姓名" style={{ width: '350px' }} />
99
+            </FormItem>
100
+            <FormItem
101
+              label="手机号"
102
+              name="phone"
103
+              rules={[{ required: true, message: '请输入手机号' }]}
104
+            >
105
+              <Input placeholder="请输入手机号" style={{ width: '350px' }} />
106
+            </FormItem>
107
+            <FormItem
108
+              label="所属机构"
109
+              name="cooperative_id"
110
+              rules={[{ required: true, message: '请选择所属机构' }]}
111
+            >
112
+              <Select style={{ width: '350px' }}>
113
+                <Option value="6" key="6">
114
+                  {6}
115
+                </Option>
116
+                <Option value="7" key="7">
117
+                  {7}
118
+                </Option>
119
+              </Select>
120
+            </FormItem>
121
+            <FormItem label="角色" name="role" rules={[{ required: true, message: '请选择角色' }]}>
122
+              <Select style={{ width: '350px' }}>
123
+                <Option value="6" key="6">
124
+                  农机手
125
+                </Option>
126
+                <Option value="7" key="7">
127
+                  合作社负责人
128
+                </Option>
129
+              </Select>
130
+            </FormItem>
131
+            <FormItem label=" " colon={false}>
132
+              <Button type="default" onClick={() => goBack()}>
133
+                返回
134
+              </Button>
135
+              <Button
136
+                type="primary"
137
+                loading={loading}
138
+                htmlType="submit"
139
+                style={{ marginLeft: '4em' }}
140
+              >
141
+                保存
142
+              </Button>
143
+            </FormItem>
144
+          </Form>
145
+        </ProCard.TabPane>
146
+      </ProCard>
147
+    </Card>
148
+  );
149
+};

+ 72
- 0
src/pages/Machinery/Employees/index.jsx View File

@@ -0,0 +1,72 @@
1
+import React from 'react';
2
+import { history, Link } from 'umi';
3
+import { Button, Popconfirm, message, Tooltip } from 'antd';
4
+// import { getPersonList, exportPersonList } from '@/services/person';
5
+import { PageHeaderWrapper } from '@ant-design/pro-layout';
6
+import moment from 'moment';
7
+import PageTable from '@/components/PageTable';
8
+
9
+const formatterTime = (val) => {
10
+  return val ? moment(val).format('YYYY-MM-DD HH:mm:ss') : '';
11
+};
12
+
13
+export default (props) => {
14
+  const columns = [
15
+    {
16
+      title: '姓名',
17
+      dataIndex: 'name',
18
+      key: 'name',
19
+    },
20
+    {
21
+      title: '手机号',
22
+      dataIndex: 'phone',
23
+      key: 'phone',
24
+    },
25
+    {
26
+      title: '所属机构',
27
+      dataIndex: 'title',
28
+      key: 'title',
29
+    },
30
+    {
31
+      title: '角色',
32
+      dataIndex: 'role',
33
+      key: 'role',
34
+    },
35
+    {
36
+      title: '注册时间',
37
+      dataIndex: 'createData',
38
+      key: 'createData',
39
+    },
40
+    {
41
+      title: '操作',
42
+      valueType: 'option',
43
+      render: (_, record) => [
44
+        <Link key={1} to={`./edit.jsx`}>
45
+          编辑
46
+        </Link>,
47
+        <Popconfirm
48
+          key={2}
49
+          title="您是否确认删除 ?"
50
+          onConfirm={() => handleDelete(record.cooperativeId)}
51
+          okText="确定"
52
+          cancelText="取消"
53
+        >
54
+          <a href="#">删除</a>
55
+        </Popconfirm>,
56
+      ],
57
+    },
58
+  ];
59
+  const handleDelete = () => {};
60
+  return (
61
+    <PageHeaderWrapper>
62
+      <PageTable
63
+        // request={getPersonList}
64
+        // expfunc={exportPersonList}
65
+        columns={columns}
66
+        rowKey="employeesId"
67
+        options={false}
68
+        scroll={{ x: 1000 }}
69
+      />
70
+    </PageHeaderWrapper>
71
+  );
72
+};