andrew hace 4 años
padre
commit
7f439109f1
Se han modificado 86 ficheros con 13119 adiciones y 0 borrados
  1. 111
    0
      estateagents-admin-manager/src/pages/carouselFigure/SelectH5.1.jsx
  2. 135
    0
      estateagents-admin-manager/src/pages/carouselFigure/SelectH5.jsx
  3. 111
    0
      estateagents-admin-manager/src/pages/carouselFigure/SelectHelp.jsx
  4. 106
    0
      estateagents-admin-manager/src/pages/carouselFigure/SelectNews.jsx
  5. 148
    0
      estateagents-admin-manager/src/pages/carouselFigure/customImg/edit.jsx
  6. 81
    0
      estateagents-admin-manager/src/pages/carouselFigure/customImg/list.jsx
  7. 87
    0
      estateagents-admin-manager/src/pages/channel/InviteClients.jsx
  8. 87
    0
      estateagents-admin-manager/src/pages/channel/addChannel.jsx
  9. 193
    0
      estateagents-admin-manager/src/pages/channel/brokerList.jsx
  10. 215
    0
      estateagents-admin-manager/src/pages/channel/channelList.jsx
  11. 68
    0
      estateagents-admin-manager/src/pages/channel/channelList.less
  12. 95
    0
      estateagents-admin-manager/src/pages/channel/editChannel.jsx
  13. 518
    0
      estateagents-admin-manager/src/pages/channel/independentList/index.jsx
  14. 54
    0
      estateagents-admin-manager/src/pages/channel/independentList/style.css
  15. 58
    0
      estateagents-admin-manager/src/pages/channel/independentList/style.less
  16. 54
    0
      estateagents-admin-manager/src/pages/channel/independentList/style.wxss
  17. 111
    0
      estateagents-admin-manager/src/pages/channel/newCustomer/dataRecord.jsx
  18. 322
    0
      estateagents-admin-manager/src/pages/channel/newCustomer/index.jsx
  19. 120
    0
      estateagents-admin-manager/src/pages/channel/newCustomer/personNum.jsx
  20. 121
    0
      estateagents-admin-manager/src/pages/channel/newCustomer/visitNum.jsx
  21. 172
    0
      estateagents-admin-manager/src/pages/channel/recommendClients.jsx
  22. 138
    0
      estateagents-admin-manager/src/pages/charts/CityNums.jsx
  23. 170
    0
      estateagents-admin-manager/src/pages/customer/customerlist/components/BatchAssistConsultant.jsx
  24. 160
    0
      estateagents-admin-manager/src/pages/customer/customerlist/components/assistConsultant.jsx
  25. 146
    0
      estateagents-admin-manager/src/pages/customer/customerlist/components/attribution.jsx
  26. 81
    0
      estateagents-admin-manager/src/pages/customer/customerlist/components/changeStatus.jsx
  27. 160
    0
      estateagents-admin-manager/src/pages/customer/customerlist/components/integralRecord.jsx
  28. 146
    0
      estateagents-admin-manager/src/pages/customer/customerlist/components/recommend.jsx
  29. 217
    0
      estateagents-admin-manager/src/pages/customer/customerlist/customerDetail.jsx
  30. 786
    0
      estateagents-admin-manager/src/pages/customer/customerlist/index.jsx
  31. 183
    0
      estateagents-admin-manager/src/pages/customer/customerlist/publicCustomerDetail.jsx
  32. 209
    0
      estateagents-admin-manager/src/pages/customer/customerlist/publicStyle.less
  33. 69
    0
      estateagents-admin-manager/src/pages/customer/customerlist/style.css
  34. 239
    0
      estateagents-admin-manager/src/pages/customer/customerlist/style.less
  35. 69
    0
      estateagents-admin-manager/src/pages/customer/customerlist/style.wxss
  36. 115
    0
      estateagents-admin-manager/src/pages/customer/drift/index.jsx
  37. 58
    0
      estateagents-admin-manager/src/pages/customer/drift/style.less
  38. 173
    0
      estateagents-admin-manager/src/pages/customer/visiting/index.jsx
  39. 151
    0
      estateagents-admin-manager/src/pages/customer/visiting/style.less
  40. 193
    0
      estateagents-admin-manager/src/pages/eContract/businessConfig/add.jsx
  41. 192
    0
      estateagents-admin-manager/src/pages/eContract/businessConfig/components/SelectCompany.jsx
  42. 157
    0
      estateagents-admin-manager/src/pages/eContract/businessConfig/components/SelectContractTemp.jsx
  43. 186
    0
      estateagents-admin-manager/src/pages/eContract/businessConfig/components/SelectRaise.jsx
  44. 168
    0
      estateagents-admin-manager/src/pages/eContract/businessConfig/components/SelectSeal.jsx
  45. 207
    0
      estateagents-admin-manager/src/pages/eContract/businessConfig/detail.jsx
  46. 277
    0
      estateagents-admin-manager/src/pages/eContract/businessConfig/list.jsx
  47. 141
    0
      estateagents-admin-manager/src/pages/eContract/manage/edit.jsx
  48. 248
    0
      estateagents-admin-manager/src/pages/eContract/manage/list.jsx
  49. 44
    0
      estateagents-admin-manager/src/pages/eContract/manage/styles.less
  50. 156
    0
      estateagents-admin-manager/src/pages/eContract/template/add.jsx
  51. 49
    0
      estateagents-admin-manager/src/pages/eContract/template/detail.jsx
  52. 199
    0
      estateagents-admin-manager/src/pages/eContract/template/list.jsx
  53. 0
    0
      estateagents-admin-manager/src/pages/eContract/template/pdfDetail.jsx
  54. 187
    0
      estateagents-admin-manager/src/pages/funds/accountfunds/components/Basic.jsx
  55. 285
    0
      estateagents-admin-manager/src/pages/funds/accountfunds/components/ConsumerOrder.jsx
  56. 12
    0
      estateagents-admin-manager/src/pages/funds/accountfunds/components/Contact.jsx
  57. 81
    0
      estateagents-admin-manager/src/pages/funds/accountfunds/components/Pay.jsx
  58. 46
    0
      estateagents-admin-manager/src/pages/funds/accountfunds/components/Recharge.jsx
  59. 275
    0
      estateagents-admin-manager/src/pages/funds/accountfunds/components/RechargeOrder.jsx
  60. 46
    0
      estateagents-admin-manager/src/pages/funds/accountfunds/components/Refund.jsx
  61. 250
    0
      estateagents-admin-manager/src/pages/funds/accountfunds/components/RefundOrder.jsx
  62. 128
    0
      estateagents-admin-manager/src/pages/funds/accountfunds/components/ShowVoucher.jsx
  63. 17
    0
      estateagents-admin-manager/src/pages/funds/accountfunds/components/contactText.jsx
  64. 130
    0
      estateagents-admin-manager/src/pages/funds/accountfunds/components/styles.less
  65. 68
    0
      estateagents-admin-manager/src/pages/funds/accountfunds/index.jsx
  66. 142
    0
      estateagents-admin-manager/src/pages/funds/financialContact/index.jsx
  67. 45
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Demand/components/AddDemand.jsx
  68. 56
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Demand/components/BatchDel.jsx
  69. 138
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Demand/detail.jsx
  70. 69
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Demand/detail.less
  71. 87
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Demand/edit.jsx
  72. 255
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Demand/list.jsx
  73. 111
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/add.jsx
  74. 248
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/addH5.jsx
  75. 258
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/components/ContactInfo.jsx
  76. 26
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/components/style.less
  77. 165
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/detail.jsx
  78. 198
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/list.jsx
  79. 56
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/style.css
  80. 338
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/style.less
  81. 53
    0
      estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/style.wxss
  82. 167
    0
      estateagents-admin-manager/src/pages/house/house/add/HouseBatchAdd.jsx
  83. 141
    0
      estateagents-admin-manager/src/pages/house/house/add/index.jsx
  84. 170
    0
      estateagents-admin-manager/src/pages/house/house/edit/components/base.jsx
  85. 322
    0
      estateagents-admin-manager/src/pages/house/house/edit/components/house.jsx
  86. 95
    0
      estateagents-admin-manager/src/pages/house/house/edit/index.jsx

+ 111
- 0
estateagents-admin-manager/src/pages/carouselFigure/SelectH5.1.jsx Ver fichero

@@ -0,0 +1,111 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Select, Modal, Button, Input } from 'antd';
3
+import { apis, fetch } from '../../utils/request';
4
+
5
+const getH5List = fetch(apis.h5Activity.EffectiveList)
6
+const { Search } = Input;
7
+
8
+export default props => {
9
+  const {
10
+    value,
11
+    onChange,
12
+    ...rest
13
+  } = props;
14
+
15
+  const [list, setList] = useState([]);
16
+  const [visible, setVisible] = useState(false);
17
+  const [group, setGroup] = useState({ groupId: undefined, groupName: '请选择' })
18
+  const getGroupTitle = val => {
19
+    return (list.filter(x => x.drainageId == val)[0] || {}).name || '请选择'
20
+  }
21
+  const updateGroup = val => setGroup({ groupId: val, groupName: getGroupTitle(val) })
22
+
23
+  useEffect(() => {
24
+    getH5List({
25
+      params: {
26
+        pageNum: 1,
27
+        pageSize: 999,
28
+        isMiniapp: 1,
29
+        status: 1,
30
+      },
31
+    }).then(data => {
32
+      setList(data.records || [])
33
+
34
+      updateGroup(value ? undefined : value);
35
+    })
36
+  }, []);
37
+  const searchH5 = (e) => {
38
+    getH5List({
39
+      params: {
40
+        buildingId,
41
+        pageNum: 1,
42
+        pageSize: 999,
43
+        activityStatus: 2,
44
+        name: e
45
+      }
46
+    }).then((data) => {
47
+      setList(data.records || [])
48
+
49
+      updateGroup(value ? undefined : value);
50
+    })
51
+  }
52
+
53
+  if (value !== group.groupId) {
54
+    updateGroup(value);
55
+  }
56
+
57
+  const handleChange = val => {
58
+    onChange(val)
59
+  }
60
+
61
+  const setData = val => {
62
+    updateGroup('')
63
+    onChange('')
64
+  }
65
+
66
+  return (
67
+    <div>
68
+      <div onClick={() => setVisible(true)}>{group.groupName}</div>
69
+      <Modal
70
+        title="请选择"
71
+        visible={visible}
72
+        onCancel={() => setVisible(false)}
73
+        footer={[
74
+          <Button key="back" onClick={() => setVisible(false)}>
75
+            取消
76
+            </Button>,
77
+          <Button key="cancel" onClick={() => setData(value)}>
78
+            清空
79
+            </Button>,
80
+          <Button key="submit" type="primary" onClick={() => {
81
+            updateGroup(value)
82
+            onChange(value)
83
+            setVisible(false)
84
+          }}>
85
+            提交
86
+            </Button>
87
+        ]}
88
+      >
89
+        <Search
90
+          placeholder="请输入标题"
91
+          enterButton="搜索"
92
+          size="large"
93
+          onSearch={value => searchH5(value)}
94
+          style={{ marginBottom: '16px' }}
95
+        />
96
+        <Select
97
+          showSearch
98
+          value={value ? parseInt(value) : undefined}
99
+          onChange={handleChange}
100
+          style={{ width: '90%' }}
101
+          filterOption={(input, option) =>
102
+            option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
103
+          }>
104
+          {
105
+            list.map(x => (<Select.Option key={x.drainageId} value={x.drainageId}>{x.name}</Select.Option>))
106
+          }
107
+        </Select>
108
+      </Modal>
109
+    </div>
110
+  );
111
+}

+ 135
- 0
estateagents-admin-manager/src/pages/carouselFigure/SelectH5.jsx Ver fichero

@@ -0,0 +1,135 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Select, Modal, Button, Table, Divider, Tag, Input, Row, Col } from 'antd';
3
+import { apis, fetch } from '../../utils/request';
4
+import Navigate from '@/components/Navigate';
5
+
6
+const { Column, ColumnGroup } = Table;
7
+const getH5List = fetch(apis.h5Activity.EffectiveList)
8
+const { Search } = Input;
9
+export default props => {
10
+  const {
11
+    value,
12
+    onChange,
13
+    ...rest
14
+  } = props;
15
+
16
+  const [list, setList] = useState([]);
17
+  const [visible, setVisible] = useState(false);
18
+  const [group, setGroup] = useState({ groupId: undefined, groupName: '请选择' })
19
+  const getGroupTitle = val => {
20
+    return (list.filter(x => x.drainageId == val)[0] || {}).name || '请选择'
21
+  }
22
+  const updateGroup = val => setGroup({ groupId: val, groupName: getGroupTitle(val) })
23
+
24
+  const buildingId = props.buildingId()
25
+
26
+  useEffect(() => {
27
+    getH5List({
28
+      params: {
29
+        pageNum: 1,
30
+        pageSize: 999,
31
+        isMiniapp: 1,
32
+        status: 1,
33
+        source: 2,
34
+        buildingId,
35
+      },
36
+    }).then(data => {
37
+      const getGroupTitle = val => {
38
+        return (data.records.filter(x => x.drainageId == val)[0] || {}).name || '请选择'
39
+      }
40
+      const updateGroup = val => setGroup({ groupId: val, groupName: getGroupTitle(val) })
41
+      setList(data.records || [])
42
+
43
+      updateGroup(buildingId ? undefined : value);
44
+    })
45
+  }, [buildingId]);
46
+  const searchH5 = e => {
47
+    getH5List({
48
+      params: {
49
+        pageNum: 1,
50
+        pageSize: 999,
51
+        isMiniapp: 1,
52
+        status: 1,
53
+        source: 2,
54
+        name: e
55
+      },
56
+    }).then(data => {
57
+      setList(data.records || [])
58
+      const getGroupTitle = val => {
59
+        return (data.records.filter(x => x.drainageId == val)[0] || {}).name || '请选择'
60
+      }
61
+      const updateGroup = val => setGroup({ groupId: val, groupName: getGroupTitle(val) })
62
+      setList(data.records || [])
63
+      updateGroup(value ? undefined : value);
64
+    })
65
+  }
66
+
67
+  if (value !== group.groupId) {
68
+    updateGroup(value);
69
+  }
70
+
71
+  const handleChange = val => {
72
+    onChange(val)
73
+  }
74
+
75
+  const setData = val => {
76
+    updateGroup(val)
77
+    onChange(val)
78
+    setVisible(false)
79
+  }
80
+
81
+  const clearVal = val => {
82
+    onChange(val)
83
+    setVisible(false)
84
+  }
85
+
86
+  const columns = [
87
+    {
88
+      title: '标题',
89
+      dataIndex: 'name',
90
+      key: 'drainageId',
91
+      align: 'center',
92
+      ellipsis: true,
93
+      render: text => <a>{text}</a>,
94
+    },
95
+    {
96
+      title: '操作',
97
+      align: 'center',
98
+      width: '20%',
99
+      render: (text, record) => (
100
+        <Navigate onClick={() => setData(record.drainageId)}>选择</Navigate>
101
+      ),
102
+    },
103
+  ];
104
+
105
+  return (
106
+    <div>
107
+      <div ><Navigate onClick={() => setVisible(true)}>{group.groupName}</Navigate></div>
108
+      <Modal
109
+        title="请选择"
110
+        visible={visible}
111
+        onCancel={() => setVisible(false)}
112
+        footer={[]}
113
+      >
114
+        <Row>
115
+          <Col span={18}>
116
+            <Search
117
+              placeholder="请输入标题"
118
+              enterButton="搜索"
119
+              size="default"
120
+              allowClear="true"
121
+              onSearch={value => searchH5(value)}
122
+              style={{ marginBottom: '16px' }}
123
+            />
124
+          </Col>
125
+          <Col span={4} offset={1}>
126
+            <Button type="primary" onClick={() => clearVal('')}>清除选择</Button>
127
+          </Col>
128
+        </Row>
129
+
130
+        <Table rowKey={list => list.drainageId} columns={columns} dataSource={list} />
131
+
132
+      </Modal>
133
+    </div>
134
+  )
135
+}

+ 111
- 0
estateagents-admin-manager/src/pages/carouselFigure/SelectHelp.jsx Ver fichero

@@ -0,0 +1,111 @@
1
+import React, { useState, useEffect } from 'react';
2
+
3
+import { Form, Select, Modal, Button, Table, Divider, Tag, Input } from 'antd';
4
+import { apis, fetch } from '../../utils/request';
5
+import Navigate from '@/components/Navigate';
6
+
7
+const { Search } = Input;
8
+
9
+const getHelpList = fetch(apis.helpActivity.effectiveList)
10
+
11
+export default props => {
12
+  const {
13
+    value,
14
+    onChange,
15
+    ...rest
16
+  } = props;
17
+
18
+  const [list, setList] = useState([]);
19
+  const [visible, setVisible] = useState(false);
20
+  const [help, setHelp] = useState({ helpId: undefined, helpName: '请选择助力' })
21
+  const getHelpTitle = val => {
22
+    return (list.filter(x => x.helpActivityId == val)[0] || {}).title || '请选择助力'
23
+  }
24
+
25
+  const updateHelp = val => setHelp({ helpId: val, helpName: getHelpTitle(val) })
26
+
27
+  const buildingId = props.buildingId()
28
+
29
+  useEffect(() => {
30
+    getHelpList({
31
+      params: {
32
+        buildingId,
33
+        pageNum: 1,
34
+        pageSize: 999,
35
+        status: 1
36
+      },
37
+    }).then(data => {
38
+      setList(data.records || [])
39
+
40
+      updateHelp(value ? undefined : value);
41
+    })
42
+  }, [buildingId]);
43
+  const searchHelp = (e) => {
44
+    getHelpList({
45
+      params: {
46
+        buildingId,
47
+        pageNum: 1,
48
+        pageSize: 999,
49
+        status: 1,
50
+        name: e
51
+      },
52
+    }).then(data => {
53
+      setList(data.records || [])
54
+
55
+      updateHelp(value ? undefined : value);
56
+    })
57
+  }
58
+  if (value !== help.helpId) {
59
+    updateHelp(value);
60
+  }
61
+
62
+  const handleChange = val => {
63
+    onChange(val)
64
+  }
65
+
66
+  const setData = val => {
67
+    updateHelp(val)
68
+    onChange(val)
69
+    setVisible(false)
70
+  }
71
+
72
+  const columns = [
73
+    {
74
+      title: '标题',
75
+      dataIndex: 'title',
76
+      key: 'helpActivityId',
77
+      align: 'center',
78
+      ellipsis: true,
79
+      render: text => <a>{text}</a>,
80
+    },
81
+    {
82
+      title: '操作',
83
+      align: 'center',
84
+      width: '20%',
85
+      render: (text, record) => (
86
+        <Navigate onClick={() => setData(record.helpActivityId)}>选择</Navigate>
87
+      ),
88
+    },
89
+  ];
90
+
91
+  return (
92
+    <div>
93
+      <div ><Navigate onClick={() => setVisible(true)}>{help.helpName}</Navigate></div>
94
+      <Modal
95
+        title="请选择"
96
+        visible={visible}
97
+        onCancel={() => setVisible(false)}
98
+        footer={[]}
99
+      >
100
+        <Search
101
+          placeholder="请输入标题"
102
+          enterButton="搜索"
103
+          size="large"
104
+          onSearch={value => searchHelp(value)}
105
+          style={{ marginBottom: '16px' }}
106
+        />
107
+        <Table rowKey={list => list.helpActivityId} columns={columns} dataSource={list} />
108
+      </Modal>
109
+    </div>
110
+  );
111
+}

+ 106
- 0
estateagents-admin-manager/src/pages/carouselFigure/SelectNews.jsx Ver fichero

@@ -0,0 +1,106 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Select, Modal, Button, Table, Divider, Tag, Input } from 'antd';
3
+import { apis, fetch } from '../../utils/request';
4
+import Navigate from '@/components/Navigate';
5
+
6
+const getNewsList = fetch(apis.news.getList)
7
+const { Search } = Input;
8
+
9
+export default props => {
10
+  const {
11
+    value,
12
+    onChange,
13
+    ...rest
14
+  } = props;
15
+
16
+  const [list, setList] = useState([]);
17
+  const [visible, setVisible] = useState(false);
18
+  const [news, setNews] = useState({ newsId: undefined, newsName: '请选择资讯' })
19
+  const getNewsTitle = val => ((list.filter(x => x.newsId == val)[0]) || {}).newsName || '请选择资讯'
20
+  const updateNews = val => setNews({ newsId: val, newsName: getNewsTitle(val) })
21
+
22
+  const buildingId = props.buildingId()
23
+
24
+  useEffect(() => {
25
+    getNewsList({
26
+      params: {
27
+        buildingId,
28
+        pageNum: 1,
29
+        pageSize: 999,
30
+        newsStatus: 0,
31
+      },
32
+    }).then(data => {
33
+      setList(data.records || [])
34
+
35
+      updateNews(buildingId ? undefined : value);
36
+    })
37
+  }, [buildingId]);
38
+  const searchActivity = (e) => {
39
+    getNewsList({
40
+      params: {
41
+        buildingId,
42
+        pageNum: 1,
43
+        pageSize: 999,
44
+        newsStatus: 0,
45
+        title: e
46
+      },
47
+    }).then(data => {
48
+      setList(data.records || [])
49
+
50
+      updateNews(buildingId ? undefined : value);
51
+    })
52
+  }
53
+  if (value !== news.newsId) {
54
+    updateNews(value);
55
+  }
56
+
57
+  const handleChange = val => {
58
+    onChange(val)
59
+  }
60
+
61
+  const setData = val => {
62
+    updateNews(val)
63
+    onChange(val)
64
+    setVisible(false)
65
+  }
66
+
67
+  const columns = [
68
+    {
69
+      title: '标题',
70
+      dataIndex: 'newsName',
71
+      key: 'newsId',
72
+      align: 'center',
73
+      ellipsis: true,
74
+      render: text => <a>{text}</a>,
75
+    },
76
+    {
77
+      title: '操作',
78
+      align: 'center',
79
+      width: '20%',
80
+      render: (text, record) => (
81
+        <Navigate onClick={() => setData(record.newsId)}>选择</Navigate>
82
+      ),
83
+    },
84
+  ];
85
+
86
+  return (
87
+    <div>
88
+      <div ><Navigate onClick={() => setVisible(true)}>{news.newsName}</Navigate></div>
89
+      <Modal
90
+        title="请选择"
91
+        visible={visible}
92
+        onCancel={() => setVisible(false)}
93
+        footer={[]}
94
+      >
95
+        <Search
96
+          placeholder="请输入标题"
97
+          enterButton="搜索"
98
+          size="large"
99
+          onSearch={value => searchActivity(value)}
100
+          style={{ marginBottom: '16px' }}
101
+        />
102
+        <Table rowKey={list => list.newsId} columns={columns} dataSource={list} />
103
+      </Modal>
104
+    </div>
105
+  );
106
+}

+ 148
- 0
estateagents-admin-manager/src/pages/carouselFigure/customImg/edit.jsx Ver fichero

@@ -0,0 +1,148 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Input, Menu, Dropdown, Button, Icon, message, Table, Divider, Tag, Select, Form, Alert } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import channels from '../../channel/channelList.less';
5
+import { connect } from 'dva';
6
+import BuildSelect from '../../../components/SelectButton/BuildSelect'
7
+import { createForm, FieldTypes } from '../../../components/XForm';
8
+import Wangedit from '../../../components/Wangedit/Wangedit'
9
+import router from 'umi/router';
10
+import apis from '../../../services/apis';
11
+import request from '../../../utils/request'
12
+
13
+const { TextArea } = Input;
14
+const { Option } = Select;
15
+
16
+let activityVisible = true
17
+let helpTips = ''
18
+
19
+const setExtraData = (data) => {
20
+    activityVisible = data.imgType === 'index';
21
+  }
22
+
23
+const handleFormValueChange = (props, changedValues, allValues) => {
24
+    setExtraData(allValues)
25
+}
26
+
27
+const XForm = createForm({ onValuesChange: handleFormValueChange })
28
+
29
+const header = props => {
30
+  const {
31
+    currentUser = {
32
+      avatar: '',
33
+      userName: '',
34
+    },
35
+    menu,
36
+  } = props;
37
+
38
+  const imgId = props.location.query.imgId
39
+  const imgType = props.location.query.imgType
40
+
41
+  const [ data, setData ] = useState(imgType === 'index' ? 
42
+  {
43
+    'imgUrl':'https://estateagents.oss-cn-shanghai.aliyuncs.com/miniapp/upload/images/1574145199853-97feda7895c65be33aa234a7b81b37f.jpg',
44
+    'imgType':'index',
45
+    'imgDesc':'小程序首页分享配图',
46
+    'imgDocument': currentUser.orgName+' 精准获客平台'
47
+  } : 
48
+  {
49
+    'imgUrl':'http://njcj.oss-cn-shanghai.aliyuncs.com/icon.png',
50
+    'imgType':'indexNews',
51
+  }
52
+  )
53
+
54
+  if(imgId){
55
+    useEffect(() => {
56
+      getData(imgId);
57
+    },[])
58
+
59
+  // 查询列表
60
+  const getData = (imgId) => {
61
+    request({ ...apis.carsuseFigure.getCustomImg, urlData: { id: imgId} }).then((data) => {
62
+        console.log(data)
63
+        if (data.imgType === 'index'){
64
+            activityVisible = true;
65
+            helpTips = '建议图片尺寸:750*600px,比例5:4,格式:jpg,用于:首页分享';
66
+        }else{
67
+            activityVisible = false;
68
+            helpTips = '建议尺寸:80*80px,比例1:1,格式:jpg,用于:首页资讯logo'
69
+        }
70
+        setData(data)
71
+    })
72
+  }
73
+  }
74
+
75
+  const fields = [
76
+    {
77
+      label: '图片',
78
+      name: 'imgUrl',
79
+      type: FieldTypes.ImageUploader,
80
+      value: data.imgUrl,
81
+      help: helpTips,
82
+      rules: [
83
+        {required: true, message: '请选择图片'},
84
+      ]
85
+    },
86
+    {
87
+      label: '类型',
88
+      name: 'imgType',
89
+      type: FieldTypes.Select,
90
+      value: data.imgType,
91
+      dict: [{
92
+          label: '首页分享',
93
+          value: 'index',
94
+        },
95
+        {
96
+          label: '首页资讯',
97
+          value: 'indexNews',
98
+        },
99
+      ],
100
+      rules: [
101
+        { required: true, message: '请选择类型' },
102
+      ],
103
+    },
104
+    data.imgType === 'index' && {
105
+      label: '分享文案',
106
+      name: 'imgDocument',
107
+      type: FieldTypes.Text,
108
+      value: data.imgDocument,
109
+      rules: [
110
+        { required: true, message: '请输入分享文案' },
111
+      ],
112
+    },
113
+  ]
114
+
115
+  const handleSubmit = values => {
116
+    
117
+    if (imgId) {
118
+      values.imgId = imgId
119
+      request({ ...apis.carsuseFigure.updateCustomImg, data: values,}).then((data) => {
120
+        cancelPage()
121
+      }).catch((err) => {
122
+        message.info(err.msg || err.message)
123
+      })
124
+      }else{
125
+      request({ ...apis.carsuseFigure.addCustomImg, data: values,}).then((data) => {
126
+        cancelPage()
127
+      }).catch((err) => {
128
+        message.info(err.msg || err.message)
129
+      })
130
+      }
131
+  }
132
+
133
+  const cancelPage = () => {
134
+    router.push({
135
+        pathname: '/carouselFigure/customImg/list',
136
+    });
137
+  }
138
+
139
+  return (
140
+    <XForm onSubmit={handleSubmit} onCancel={cancelPage} fields={fields}></XForm>
141
+  )
142
+}
143
+
144
+const WrappedNormalLoginForm = Form.create({ name: 'header' })(header);
145
+
146
+export default connect(({ user }) => ({
147
+  currentUser: user.currentUser,
148
+}))(WrappedNormalLoginForm);

+ 81
- 0
estateagents-admin-manager/src/pages/carouselFigure/customImg/list.jsx Ver fichero

@@ -0,0 +1,81 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Table } from 'antd';
3
+import router from 'umi/router';
4
+import AuthButton from '@/components/AuthButton';
5
+import withActions from '@/components/ActionList';
6
+import EditIcon from '@/components/EditIcon';
7
+import Navigate from '@/components/Navigate';
8
+import apis from '../../../services/apis';
9
+import request from '../../../utils/request'
10
+
11
+const { Column } = Table;
12
+
13
+function header(props) {
14
+  // 获取初始化数据
15
+  const [data, setData] = useState([])
16
+
17
+  useEffect(() => {
18
+    getList({ pageNum: 1, pageSize: 10 });
19
+  }, [])
20
+
21
+  // 查询列表
22
+  const getList = (params) => {
23
+    request({ ...apis.carsuseFigure.customImg, params: { ...params }, }).then((data) => {
24
+      console.log(data, "datadata")
25
+      if (data.records.length > 0) {
26
+        setData(data.records)
27
+      } else {
28
+        setData([
29
+          { 'imgUrl': 'https://estateagents.oss-cn-shanghai.aliyuncs.com/miniapp/upload/images/1574145199853-97feda7895c65be33aa234a7b81b37f.jpg', 'imgType': 'index', 'imgDesc': '小程序首页分享配图' },
30
+          { 'imgUrl': 'http://njcj.oss-cn-shanghai.aliyuncs.com/icon.png', 'imgType': 'indexNews', 'imgDesc': '首页资讯logo' }
31
+        ])
32
+      }
33
+
34
+    })
35
+  }
36
+
37
+  // 跳转到编辑商品
38
+  const toEditCustom = (imgId, imgType) => () => {
39
+    router.push({
40
+      pathname: '/carouselFigure/customImg/edit',
41
+      query: {
42
+        imgId,
43
+        imgType: imgType
44
+      },
45
+    });
46
+  }
47
+
48
+
49
+  // const { getFieldDecorator } = props.form
50
+  return (
51
+
52
+    <>
53
+      <Table dataSource={data}>
54
+        <Column title="图片" dataIndex="imgUrl" key="imgUrl"
55
+          render={(text, record) => (
56
+            <Navigate onClick={toEditCustom(record.imgId, record.imgType)} ><img src={record.imgUrl} height="120px" width="150px" style={{ objectFit: 'contain' }} /></Navigate>
57
+          )} />
58
+        <Column title="类型" dataIndex="imgType" key="imgType"
59
+          render={(text, record) => (
60
+            <span>
61
+              {record.imgType === 'index' ? '首页分享' : record.imgType === 'indexNews' ? '首页资讯' : '请编辑'}
62
+            </span>
63
+          )}
64
+        />
65
+        <Column title="说明" dataIndex="imgDesc" key="imgDesc" />
66
+        <Column title="操作"
67
+          dataIndex="handle"
68
+          key="handle"
69
+          render={withActions((text, record) => [
70
+            <AuthButton name="admin.custom.put" noRight={null}>
71
+              <EditIcon text="编辑" type="edit" onClick={toEditCustom(record.imgId, record.imgType)}></EditIcon>
72
+            </AuthButton>,
73
+          ])}
74
+        />
75
+      </Table>,
76
+    </>
77
+  )
78
+}
79
+const WrappedHeader = Form.create({ name: 'header' })(header);
80
+
81
+export default WrappedHeader

+ 87
- 0
estateagents-admin-manager/src/pages/channel/InviteClients.jsx Ver fichero

@@ -0,0 +1,87 @@
1
+
2
+import React, { useState, useEffect } from 'react';
3
+import { Input, Menu, Dropdown, Button, Icon, message, Table, Divider, Tag, Select } from 'antd';
4
+import { FormattedMessage } from 'umi-plugin-react/locale';
5
+import channels from './channelList.less';
6
+import router from 'umi/router';
7
+import apis from '../../services/apis';
8
+import request from '../../utils/request'
9
+
10
+const { Option } = Select;
11
+function handleChange(value) {
12
+  console.log(`selected ${value}`);
13
+}
14
+const columns = [
15
+  {
16
+    title: '头像',
17
+    dataIndex: 'img',
18
+    key: 'img',
19
+    align: 'center',
20
+
21
+    render: (text, record) => <img src={record.avatarurl} className={channels.touxiang} />,
22
+  },
23
+  {
24
+    title: '用户姓名',
25
+    dataIndex: 'name',
26
+    key: 'name',
27
+    align: 'center',
28
+  },
29
+  {
30
+    title: '电话',
31
+    dataIndex: 'tel',
32
+    key: 'tel',
33
+    align: 'center',
34
+  },
35
+  {
36
+    title: '性别',
37
+    dataIndex: 'sex',
38
+    key: 'sex',
39
+    align: 'center',
40
+    render: (text, record) => <a style={ { color: '#66B3FF' } } >{ record.sex === 1 ? '男' : '女' }</a>,
41
+  },
42
+];
43
+const header = props => {
44
+  // eslint-disable-next-line react-hooks/rules-of-hooks
45
+  const [data, setData] = useState({ channelNmae: [], result: [] })
46
+  // eslint-disable-next-line react-hooks/rules-of-hooks
47
+  useEffect(() => {
48
+    getListInvite({ id: props.location.query.id, pageNum: 1, pageSize: 10 })
49
+  }, [])
50
+
51
+  // function getListInvite(params) {
52
+  //   request({
53
+  //     url: 'api/admin/channel/InviteClientsList',
54
+  //     method: 'GET',
55
+  //     params: { ...params },
56
+  // // eslint-disable-next-line no-shadow
57
+  // }).then(data => {
58
+  //     console.log(data)
59
+  //     setData(data)
60
+  // })
61
+  // }
62
+
63
+  function getListInvite(params) {
64
+    request({ ...apis.channelList.getListInvite, params: { ...params } }).then((data) => {
65
+      setData(data)
66
+  }).catch((err) => {
67
+      console.log(err)
68
+      message.info(err.msg || err.message)
69
+  })
70
+  }
71
+
72
+  // 分页
73
+  function onChange(pageNumber) {
74
+    // eslint-disable-next-line react-hooks/rules-of-hooks
75
+    getListInvite({ pageNum: pageNumber, pageSize: 9 })
76
+  }
77
+  return (
78
+    <>
79
+      <div className={channels.searchBox}>
80
+      </div>
81
+      <Table dataSource={data.records} rowKey="InviteClient" columns={columns} pagination={{ pageSize: 10, total: data.total, onChange }} />
82
+  </>
83
+  )
84
+}
85
+
86
+
87
+export default header

+ 87
- 0
estateagents-admin-manager/src/pages/channel/addChannel.jsx Ver fichero

@@ -0,0 +1,87 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Input, Menu, Dropdown, Button, Icon, message, Table, Divider, Tag, Select, Form, Alert } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import channels from './channelList.less';
5
+import router from 'umi/router';
6
+import apis from '../../services/apis';
7
+import request from '../../utils/request'
8
+
9
+const { TextArea } = Input;
10
+const { Option } = Select;
11
+
12
+const header = props => {
13
+  // eslint-disable-next-line react-hooks/rules-of-hooks
14
+  const [data, setData] = useState({ channelNmae: [], result: [] })
15
+  // eslint-disable-next-line react-hooks/rules-of-hooks
16
+
17
+  // useEffect(() => {
18
+  //   addChannel({ pageNum: 1, pageSize: 10 })
19
+  // }, [])
20
+
21
+  function addChannel(params) {
22
+    request({ ...apis.channelList.addChannel, data: { ...params } }).then((data) => {
23
+      setData(data)
24
+      router.go(-1)
25
+    }).catch((err) => {
26
+      console.log(err)
27
+      message.info(err.msg || err.message)
28
+    })
29
+  }
30
+
31
+  function handleSubmit(e) {
32
+    e.preventDefault();
33
+    props.form.validateFields((err, values) => {
34
+      if (!err) {
35
+        console.log('Received values of form: ', values);
36
+        // eslint-disable-next-line max-len
37
+        addChannel({
38
+          channelName: values.channelName,
39
+          channelContact: values.channelContact,
40
+          contactTel: values.contactTel,
41
+          explain: values.explain
42
+        })
43
+      }
44
+    });
45
+  }
46
+
47
+  const { getFieldDecorator } = props.form;
48
+
49
+  return (
50
+    <>
51
+      <Form labelCol={{ span: 7 }} wrapperCol={{ span: 12 }} onSubmit={handleSubmit}>
52
+        <Form.Item label="渠道名称">
53
+          {getFieldDecorator('channelName', {
54
+            rules: [{ required: true, message: '请输入渠道名称' }],
55
+          })(<Input className={channels.inpuit} />)}
56
+        </Form.Item>
57
+        <Form.Item label="联系人">
58
+          {getFieldDecorator('channelContact', {
59
+            rules: [{ required: true, message: ' 请输入联系人' }],
60
+          })(<Input className={channels.inpuit} />)}
61
+        </Form.Item>
62
+        <Form.Item label="联系电话">
63
+          {getFieldDecorator('contactTel', {
64
+            rules: [{ required: true, message: '请输入联系电话' }],
65
+          })(<Input className={channels.inpuit} />)}
66
+        </Form.Item>
67
+        <Form.Item label="说明描述">
68
+          {getFieldDecorator('explain', {
69
+          })(<TextArea className={channels.inpuitTxt} rows={8} />)}
70
+        </Form.Item>
71
+        <Form.Item wrapperCol={{ span: 15, offset: 8 }}>
72
+          <div style={{ width: '190px' }}>
73
+            <Button type="primary" htmlType="submit">
74
+              保存
75
+          </Button>
76
+            <Button className={channels.formButton} onClick={() => router.go(-1)} htmlType="submit">
77
+              取消
78
+          </Button>
79
+          </div>
80
+        </Form.Item>
81
+      </Form>
82
+    </>
83
+  )
84
+}
85
+
86
+const WrappedNormalLoginForm = Form.create({ name: 'header' })(header);
87
+export default WrappedNormalLoginForm

+ 193
- 0
estateagents-admin-manager/src/pages/channel/brokerList.jsx Ver fichero

@@ -0,0 +1,193 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Input, Menu, Dropdown, Button, Icon, message, Table, Divider, Tag, Select, Form, Avatar } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import channels from './channelList.less';
5
+import router from 'umi/router';
6
+import apis from '../../services/apis';
7
+import request from '../../utils/request'
8
+import Navigate from '@/components/Navigate';
9
+
10
+const { Option } = Select;
11
+function handleChange(value) {
12
+  console.log(`selected ${value}`);
13
+}
14
+
15
+
16
+const menu = (
17
+  <Menu onClick={handleMenuClick}>
18
+    <Menu.Item key="1">
19
+      <Icon type="user" />
20
+      1st menu item
21
+    </Menu.Item>
22
+    <Menu.Item key="2">
23
+      <Icon type="user" />
24
+      2nd menu item
25
+    </Menu.Item>
26
+    <Menu.Item key="3">
27
+      <Icon type="user" />
28
+      3rd item
29
+    </Menu.Item>
30
+  </Menu>
31
+);
32
+const columns = [
33
+  {
34
+    title: '头像',
35
+    dataIndex: 'avatarurl',
36
+    key: 'avatarurl',
37
+    align: 'center',
38
+
39
+    // eslint-disable-next-line jsx-a11y/alt-text
40
+    render: (text, list) => <Avatar shape="square" style={{ color: 'blue', cursor: 'pointer' }} src={list.avatarurl} size={64} icon="user" />,
41
+  },
42
+  {
43
+    title: '用户姓名',
44
+    dataIndex: 'nickname',
45
+    key: 'nickname',
46
+    align: 'center',
47
+    render: (text, list) => <><span>{list.name || list.nickname}</span></>,
48
+  },
49
+  {
50
+    title: '电话',
51
+    dataIndex: 'phone',
52
+    key: 'phone',
53
+    align: 'center',
54
+  },
55
+  {
56
+    title: '性别',
57
+    dataIndex: 'sex',
58
+    key: 'sex',
59
+    align: 'center',
60
+    render: (text, list) => <a>{list.gender === '1' ? '男' : list.gender === '2' ? '女' : '未知'}</a>,
61
+  },
62
+  {
63
+    title: '推荐客户',
64
+    dataIndex: 'recommendCount',
65
+    key: 'recommendCount',
66
+    align: 'center',
67
+    // render: (text, list) => <a style={ { color: '#66B3FF' } } onClick= {() => torecommend(list.personId)} >{ list.recommendCount }</a>,
68
+    render: (text, list) => <Navigate onClick={() => torecommend(list.personId)} >{list.recommendCount}</Navigate>,
69
+  },
70
+  // {
71
+  //   title: '邀请经纪人',
72
+  //   dataIndex: 'inviteCount',
73
+  //   key: 'inviteCount',
74
+  //   align: 'center',
75
+  //   render: (text, list) => <a style={ { color: '#66B3FF' } } onClick= {() => toinvite(list.personId)} >{ list.inviteCount }</a>,
76
+  // },
77
+];
78
+
79
+// 跳转到推荐客户
80
+function torecommend(personId) {
81
+  router.push({
82
+    pathname: '/channel/recommendClients',
83
+    query: {
84
+      id: personId,
85
+    },
86
+  });
87
+}
88
+
89
+// 跳转到邀请经纪人
90
+function toinvite(personId) {
91
+  router.push({
92
+    pathname: '/channel/InviteClients',
93
+    query: {
94
+      id: personId,
95
+    },
96
+  });
97
+}
98
+
99
+
100
+const header = props => {
101
+  // eslint-disable-next-line react-hooks/rules-of-hooks
102
+  const [data, setData] = useState({ list: [] })
103
+
104
+  // eslint-disable-next-line react-hooks/rules-of-hooks
105
+  const [queryData, setQueryData] = useState({})
106
+
107
+  const channelId = props.location.query.id
108
+  //   const [page, changePage] = useState({})
109
+  // eslint-disable-next-line react-hooks/rules-of-hooks
110
+  useEffect(() => {
111
+    getListBroker({ channelId, pageNum: 1, pageSize: 10 })
112
+  }, [])
113
+
114
+  function getListBroker(params) {
115
+    request({ ...apis.channelList.getListBroker, params: { ...params } }).then((data) => {
116
+      setData(data)
117
+    }).catch((err) => {
118
+      console.log(err)
119
+      message.info(err.msg || err.message)
120
+    })
121
+  }
122
+
123
+
124
+  // 搜索
125
+  function queryList() {
126
+    getListBroker({ ...queryData, pageNum: 1, pageSize: 10, channelId })
127
+  }
128
+  // 分页
129
+  function onChange(pageNumber) {
130
+    // eslint-disable-next-line react-hooks/rules-of-hooks
131
+    getListBroker({ pageNum: pageNumber, pageSize: 10, channelId })
132
+  }
133
+  //   // 获取input的值
134
+  //   function onInputChangeName (e) {
135
+  //     // const InputValue = e.target.name.x.value;
136
+  //     setQueryData({ ...queryData, name: e.target.value })
137
+  //  }
138
+
139
+  //  function onInputChangePhone (e) {
140
+  //   // const InputValue = e.target.name.x.value;
141
+  //   setQueryData({ ...queryData, phone: e.target.value })
142
+  // }
143
+  // function refurbishList () {
144
+  //   getListBroker({ pageNum: 1, pageSize: 10 })
145
+  // }
146
+  // eslint-disable-next-line no-undef
147
+  // function handleClick() {
148
+  //   alert('11', this)
149
+  //   console.log('this is:', this);
150
+  // }
151
+
152
+  function handleSubmit(e) {
153
+    e.preventDefault();
154
+    props.form.validateFields((err, values) => {
155
+      console.log('values', values)
156
+      if (!err) {
157
+        console.log('values', values)
158
+        getListBroker({ ...queryData, pageNum: 1, pageSize: 10, channelId, name: values.name, phone: values.phone })
159
+      }
160
+    });
161
+  }
162
+
163
+  function handleReset() {
164
+    props.form.resetFields();
165
+    getListBroker({ pageNum: 1, pageSize: 10, channelId })
166
+  }
167
+  const { getFieldDecorator } = props.form;
168
+  return (
169
+    <>
170
+      <Form layout="inline" onSubmit={handleSubmit}>
171
+        <Form.Item label="姓名">
172
+          {getFieldDecorator('name', {
173
+          })(<Input />)}
174
+        </Form.Item>
175
+        <Form.Item label="电话">
176
+          {getFieldDecorator('phone', {
177
+          })(<Input />)}
178
+        </Form.Item>
179
+        <Form.Item >
180
+          <Button type="primary" htmlType="submit" >搜索</Button>
181
+          <Button onClick={handleReset} style={{ marginLeft: 18 }}>重置</Button>
182
+        </Form.Item>
183
+      </Form>
184
+      <Table style={{ marginTop: '40px' }} dataSource={data.list} columns={columns} pagination={{ pageSize: 10, total: data.total, onChange }} rowKey="brokerList" />
185
+    </>
186
+  )
187
+}
188
+const WrappedNormalLoginForm = Form.create({ name: 'header' })(header);
189
+function handleMenuClick(e) {
190
+  message.info('Click on menu item.');
191
+  console.log('click', e);
192
+}
193
+export default WrappedNormalLoginForm

+ 215
- 0
estateagents-admin-manager/src/pages/channel/channelList.jsx Ver fichero

@@ -0,0 +1,215 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Button, message, Table } from 'antd';
3
+import router from 'umi/router';
4
+import AuthButton from '@/components/AuthButton';
5
+import ChannelSelect from '@/components/SelectButton/channelSelect';
6
+import withActions from '@/components/ActionList';
7
+import EditIcon from '@/components/EditIcon';
8
+import apis from '../../services/apis';
9
+import request from '../../utils/request';
10
+import channels from './channelList.less';
11
+import Navigate from '@/components/Navigate';
12
+
13
+const columns = [
14
+  // {
15
+  //   title: '商品图片',
16
+  //   dataIndex: 'img',
17
+  //   key: 'img',
18
+  //   align: 'center',
19
+
20
+  //   render: (text, record) => <img src={record.img} className={channels.touxiang} />,
21
+  // },
22
+  {
23
+    title: '渠道代码',
24
+    dataIndex: 'channelCode',
25
+    key: 'channelCode',
26
+    align: 'center',
27
+  },
28
+  {
29
+    title: '渠道名称',
30
+    dataIndex: 'channelName',
31
+    key: 'channelName',
32
+    align: 'center',
33
+    render: (text, record) => <Navigate to={`/channel/editChannel?id=${record.channelId}`}>{text}</Navigate>,
34
+  },
35
+  {
36
+    title: '联系人',
37
+    dataIndex: 'channelContact',
38
+    key: 'channelContact',
39
+    align: 'center',
40
+  },
41
+  {
42
+    title: '联系电话',
43
+    dataIndex: 'contactTel',
44
+    key: 'contactTel',
45
+    align: 'center',
46
+  },
47
+  {
48
+    title: '经纪人数',
49
+    dataIndex: 'brokerCount',
50
+    key: 'brokerCount',
51
+    align: 'center',
52
+    render: (text, record) => <Navigate onClick={() => toBroker(record)}>{text}</Navigate>,
53
+  },
54
+  {
55
+    title: '推荐客户有效数',
56
+    dataIndex: 'recommendCount',
57
+    key: 'recommendCount',
58
+    align: 'center',
59
+  },
60
+  {
61
+    title: '引进注册客户',
62
+    dataIndex: 'customerNum',
63
+    key: 'customerNum',
64
+    align: 'center',
65
+    render: (text, record) => <Navigate onClick={() => toNewCustomer(record)}>{text}</Navigate>,
66
+  },
67
+  {
68
+    title: '操作',
69
+    dataIndex: '',
70
+    key: '',
71
+    align: 'center',
72
+    render: withActions((text, record) => [
73
+      <AuthButton name="admin.channel.id.put" noRight={null}>
74
+        <EditIcon text="编辑" type="edit" onClick={() => toedit(record.channelId)} />
75
+      </AuthButton>,
76
+    ]),
77
+  },
78
+];
79
+
80
+// 跳转到添加页面
81
+function toAdd() {
82
+  router.push({
83
+    pathname: '/channel/addChannel',
84
+    query: {
85
+      a: 'b',
86
+    },
87
+  });
88
+}
89
+// 跳编辑页面
90
+function toedit(channelId) {
91
+  // alert(channelId)
92
+  router.push({
93
+    pathname: '/channel/editChannel',
94
+    query: {
95
+      id: channelId,
96
+    },
97
+  });
98
+}
99
+
100
+// 经纪人页面
101
+function toBroker(record) {
102
+  // if (record.brokerCount === 0) {
103
+  //   return
104
+  // }
105
+  router.push({
106
+    pathname: '/channel/brokerList',
107
+    query: {
108
+      id: record.channelId,
109
+    },
110
+  });
111
+}
112
+
113
+// 引进注册用户
114
+function toNewCustomer(record) {
115
+  // if (record.brokerCount === 0) {
116
+  //   return
117
+  // }
118
+  router.push({
119
+    pathname: '/channel/newCustomer',
120
+    query: {
121
+      id: record.channelId,
122
+      name: record.channelName,
123
+      customerNum: record.customerNum,
124
+    },
125
+  });
126
+}
127
+
128
+export default function ChannelList (props) {
129
+  // eslint-disable-next-line react-hooks/rules-of-hooks
130
+  const [data, setData] = useState({ channelNmae: [], result: [] })
131
+  const [channelNmae, setChannelNmae] = useState()
132
+  // eslint-disable-next-line react-hooks/rules-of-hooks
133
+  useEffect(() => {
134
+    localStorage.removeItem('value');
135
+    getList({ pageNum: 1, pageSize: 10 })
136
+  }, [])
137
+
138
+  function getList(params) {
139
+    request({ ...apis.channelList.getList, params: { ...params } }).then((data) => {
140
+      setData(data)
141
+    }).catch((err) => {
142
+      console.log(err)
143
+      message.info(err.msg || err.message)
144
+    })
145
+  }
146
+  // value 的值
147
+  function handleChange(value) {
148
+    // setQueryData({ ...queryData, channelId: value });
149
+    localStorage.setItem('value', value);
150
+  }
151
+  // 查询
152
+  function queryList() {
153
+
154
+    getList({ pageNum: 1, pageSize: 10, channelId: channelNmae })
155
+  }
156
+  // 重置
157
+  function reset() {
158
+    setChannelNmae()
159
+    getList({ pageNum: 1, pageSize: 10 })
160
+  }
161
+
162
+  // 跳编辑页
163
+  function toEdit() {
164
+    router.push({
165
+      pathname: '/integralMall/editGoods',
166
+      query: {
167
+        a: 'b',
168
+      },
169
+    });
170
+  }
171
+
172
+  // 分页
173
+  function onChange(pageNumber) {
174
+    getList({ pageNum: pageNumber, pageSize: 10, channelId: channelNmae })
175
+    // getList({ pageNum: pageNumber, pageSize: 10, ...values })
176
+    // props.form.validateFields((err, values) => {
177
+    //   if (!err) {
178
+    //     getList({ pageNum: pageNumber, pageSize: 10, ...values })
179
+    //   }
180
+    // });
181
+  }
182
+
183
+  function onChannelChange(value) {
184
+    setChannelNmae(value)
185
+  }
186
+
187
+  return (
188
+    <>
189
+      <div className={channels.searchBox}>
190
+        <div>
191
+          <span className={channels.selectName}>渠道名称</span>
192
+          <ChannelSelect value={channelNmae} onChange={onChannelChange}></ChannelSelect>
193
+          {/* 
194
+          <Select defaultValue="请选择" style={{ width: 180 }} onChange={handleChange}>
195
+            <option value="">全部</option>
196
+            {data.channelNmae.map(Item =>
197
+              <Option value={Item.channelId}> {Item.channelName} </Option>,
198
+            )} */}
199
+          {/* {listItems} */}
200
+          {/* </Select> */}
201
+        </div>
202
+        <div >
203
+          <AuthButton name="admin.channel.search" noRight={null}>
204
+            <Button type="primary" onClick={() => queryList()}>搜索</Button>
205
+          </AuthButton>
206
+          <Button onClick={() => reset()} style={{ marginLeft: '8px' }}>重置</Button>
207
+        </div>
208
+      </div>
209
+      <AuthButton name="admin.channel.post" noRight={null}>
210
+        <Button type="danger" onClick={toAdd} className={channels.about} >新增</Button>
211
+      </AuthButton>
212
+      <Table dataSource={data.result.records} columns={columns} rowKey="channelList" pagination={{ pageSize: 10, total: data.result.total, onChange }} />
213
+    </>
214
+  )
215
+}

+ 68
- 0
estateagents-admin-manager/src/pages/channel/channelList.less Ver fichero

@@ -0,0 +1,68 @@
1
+.searchBox {
2
+  font-size: 20px;
3
+  color: red;
4
+  display: flex;
5
+  display: flex;
6
+  align-items: center;
7
+  justify-content: space-between;
8
+  .searchItem {
9
+    min-width: 20px;
10
+    margin-right: 20px;
11
+    text-align: left;
12
+    .anticon-down {
13
+      float: right !important;
14
+    }
15
+  }
16
+}
17
+.addBtn {
18
+  padding: 0 30px;
19
+  height: 36px;
20
+  background-color: #50be00;
21
+  color: #fff;
22
+  margin: 30px 0;
23
+}
24
+.touxiang {
25
+  width: 93px;
26
+  height: 93px;
27
+}
28
+.ant-table-column-title {
29
+  font-weight: 600;
30
+}
31
+
32
+.about {
33
+  padding: 0 30px;
34
+  height: 36px;
35
+  margin: 30px 0;
36
+  margin-left:8px;
37
+}
38
+
39
+.selectName {
40
+  font-size: 14px;
41
+  padding: 0 10px;
42
+  height: 36px;
43
+  color: rgb(10, 10, 10);
44
+  margin: 30px 0;
45
+}
46
+
47
+.inpuit {
48
+  width:50%;
49
+}
50
+
51
+.inpuitTxt {
52
+  width:70%;
53
+}
54
+
55
+
56
+.formButton{
57
+  margin-left: 12% 
58
+}
59
+
60
+.divInput{
61
+  float: 'left'; 
62
+  width: 500
63
+}
64
+.brokerTable{
65
+  padding: 0 30px;
66
+  height: 36px;
67
+  margin: 30px 0;
68
+}

+ 95
- 0
estateagents-admin-manager/src/pages/channel/editChannel.jsx Ver fichero

@@ -0,0 +1,95 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Input, Menu, Dropdown, Button, Icon, message, Table, Divider, Tag, Select, Form, Alert } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import channels from './channelList.less';
5
+import router from 'umi/router';
6
+import apis from '../../services/apis';
7
+import request from '../../utils/request'
8
+
9
+const { TextArea } = Input;
10
+const { Option } = Select;
11
+
12
+const header = props => {
13
+
14
+  // eslint-disable-next-line react-hooks/rules-of-hooks
15
+  useEffect(() => {
16
+    getById()
17
+  }, [])
18
+
19
+
20
+  // 查询当前信息
21
+  function getById(params) {
22
+    request({ ...apis.channelList.getById, urlData: { id: props.location.query.id } }).then((data) => {
23
+      props.form.setFieldsValue(data)
24
+    }).catch((err) => {
25
+      console.log(err)
26
+      message.info(err.msg || err.message)
27
+    })
28
+  }
29
+
30
+  // 编辑
31
+  function editChannel(data) {
32
+    request({ ...apis.channelList.editChannel, urlData: { id: props.location.query.id }, data: { ...data } }).then((data) => {
33
+      router.go(-1)
34
+    }).catch((err) => {
35
+      console.log(err)
36
+      message.info(err.msg || err.message)
37
+    })
38
+  }
39
+
40
+
41
+  function handleSubmit(e) {
42
+    e.preventDefault();
43
+    props.form.validateFields((err, values) => {
44
+      if (!err) {
45
+        console.log('values', values)
46
+        editChannel({ ...values })
47
+      }
48
+    });
49
+  }
50
+  function go() {
51
+    router.push({
52
+      pathname: '/channel/channelList',
53
+    });
54
+  }
55
+
56
+  const { getFieldDecorator } = props.form;
57
+
58
+  return (
59
+    <>
60
+      <Form labelCol={{ span: 6 }} wrapperCol={{ span: 12 }} onSubmit={handleSubmit}>
61
+        <Form.Item label="渠道名称">
62
+          {getFieldDecorator('channelName', {
63
+            rules: [{ required: true, message: '请输入渠道名称' }],
64
+          })(<Input className={channels.inpuit} />)}
65
+        </Form.Item>
66
+        <Form.Item label="联系人">
67
+          {getFieldDecorator('channelContact', {
68
+            rules: [{ required: true, message: ' 请输入联系人' }],
69
+          })(<Input className={channels.inpuit} />)}
70
+        </Form.Item>
71
+        <Form.Item label="联系电话">
72
+          {getFieldDecorator('contactTel', {
73
+            rules: [{ required: true, message: '请输入联系电话' }],
74
+          })(<Input className={channels.inpuit} />)}
75
+        </Form.Item>
76
+        <Form.Item label="说明描述">
77
+          {getFieldDecorator('explain', {
78
+          })(<TextArea className={channels.inpuitTxt} rows={8} />)}
79
+        </Form.Item>
80
+        <Form.Item wrapperCol={{ span: 15, offset: 8 }}>
81
+          <div style={{ width: '190px' }}>
82
+            <Button type="primary" htmlType="submit">
83
+              保存
84
+          </Button>
85
+            <Button className={channels.formButton} onClick={go} htmlType="submit">
86
+              取消
87
+          </Button>
88
+          </div>
89
+        </Form.Item>
90
+      </Form>
91
+    </>
92
+  )
93
+}
94
+const WrappedNormalLoginForm = Form.create({ name: 'header' })(header);
95
+export default WrappedNormalLoginForm

+ 518
- 0
estateagents-admin-manager/src/pages/channel/independentList/index.jsx Ver fichero

@@ -0,0 +1,518 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Table, Avatar, notification, Modal } from 'antd';
3
+import moment from 'moment';
4
+import request from '../../../utils/request';
5
+import apis from '../../../services/apis';
6
+import Styles from './style.less';
7
+import { router } from 'umi';
8
+import AuthButton from '@/components/AuthButton';
9
+import ChannelSelect from '@/components/SelectButton/channelSelect';
10
+
11
+const { Option } = Select;
12
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
13
+const { Meta } = Card;
14
+/**
15
+ * 推荐客户
16
+ */
17
+class ModalTable extends React.Component {
18
+  constructor(props) {
19
+    super(props);
20
+    this.state = {
21
+      dataSource: { records: [] },
22
+      visibleData: { visible: false, customerId: '', realtyConsultant: '' },
23
+    }
24
+  }
25
+
26
+  // 挂载之后
27
+  componentDidMount() {
28
+    this.getList({ pageNumber: 1, pageSize: 5 })
29
+  }
30
+
31
+  componentDidUpdate(preProps, preState) {
32
+    if (this.props.visibleData.customerId !== preState.visibleData.customerId) {
33
+      this.getList({ pageNumber: 1, pageSize: 5 })
34
+      this.setState({ visibleData: this.props.visibleData });
35
+    }
36
+  }
37
+
38
+  // 弹框确定按钮
39
+  // eslint-disable-next-line react/sort-comp
40
+  handleOk() {
41
+    this.setState({ visibleData: { visible: false, customerId: '', realtyConsultant: '' } })
42
+  }
43
+
44
+  // 弹框取消按钮
45
+  handleCancel() {
46
+    this.setState({ visibleData: { visible: false, customerId: '', realtyConsultant: '' } })
47
+    this.props.onCancel()
48
+  }
49
+
50
+  getList(params) {
51
+    // eslint-disable-next-line no-console
52
+    console.log('this.state.visibleData', this.state.visibleData)
53
+    const { customerId } = this.state.visibleData
54
+    if (customerId === '' || customerId === undefined) {
55
+      return
56
+    }
57
+    // 网路请求
58
+    // 网路请求
59
+    request({ ...apis.customer.recommend, urlData: { id: customerId }, params: { ...params } }).then(res => {
60
+      this.setState({ dataSource: res })
61
+    }).catch(err => {
62
+      // eslint-disable-next-line no-unused-expressions
63
+      <Alert
64
+        style={{
65
+          marginBottom: 24,
66
+        }}
67
+        message={err}
68
+        type="error"
69
+        showIcon
70
+      />
71
+    })
72
+  }
73
+
74
+  // 分页
75
+  onChange(pageNum) {
76
+
77
+    this.getList({ pageNumber: pageNum, pageSize: 5, })
78
+
79
+  }
80
+
81
+  render() {
82
+    const columns = [
83
+      {
84
+        title: '头像',
85
+        // eslint-disable-next-line jsx-a11y/alt-text
86
+        render: (text, record) => <Avatar shape="square" src={record.picture} size={64} icon="user" />,
87
+        // render: (text, records) => <img src={records.picture} width={50} height={50} />,
88
+      },
89
+      {
90
+        title: '用户名',
91
+        dataIndex: 'name',
92
+        key: 'name',
93
+        // render: (row) => <><span>{console.log(row, 'row')}{row.name || row.nickname}</span></>,
94
+      },
95
+      {
96
+        title: '电话',
97
+        dataIndex: 'phone',
98
+        key: 'phone',
99
+      },
100
+      {
101
+        title: '性别',
102
+        dataIndex: 'sex',
103
+        key: 'sex',
104
+        render: (text, records) => <span>{records.sex === 1 ? '男' : '女'}</span>,
105
+      },
106
+      {
107
+        title: '意向项目',
108
+        dataIndex: 'intention',
109
+        key: 'intention',
110
+      },
111
+      {
112
+        title: '推荐时间',
113
+        dataIndex: 'createDate',
114
+        key: 'createDate',
115
+        render: (_, record) => <><span>{record.createDate && moment(record.createDate).format('YYYY-MM-DD HH:mm:ss')}</span></>,
116
+      },
117
+      {
118
+        title: '状态',
119
+        // eslint-disable-next-line consistent-return
120
+        render: (text, records) => {
121
+          console.log("retrun", records)
122
+          //     if (records.status === 1) { return '报备' }
123
+          // if (records.status === 2) { return '推荐' }
124
+          // if (records.status === 3) { return '认购' }
125
+          // if (records.status === 4) { return '签约' }
126
+          // if (records.verifyStatus === 1) { return '待审核' }
127
+          // if (records.verifyStatus === 2) { return '审核同意' }
128
+          // if (records.verifyStatus === 3) { return '签约' }
129
+          // if (records.status === 1) { if(records.reportRecommendStatus === 1) {return '报备'} if(records.reportRecommendStatus === 2) {return '推荐'}  }
130
+          // if (records.status === 2) { return '到访' }
131
+          // if (records.status === 3) { return '认购' }
132
+          // if (records.status === 4) { return '签约' }
133
+          // if (records.verifyStatus === 1) { return '待审核' }
134
+          // if (records.verifyStatus === 2) { return '审核同意' }
135
+          // if (records.verifyStatus === 3) { return '签约' }
136
+          if (records.status === 1) {
137
+            if (records.verifyStatus === 0) { return '待审核' }
138
+            if (records.verifyStatus === 1) { return '报备' }
139
+            // if (records.reportRecommendStatus === 1) { return '报备' }
140
+            // if (records.reportRecommendStatus === 2) { return '推荐' }}
141
+            if (records.verifyStatus === 2) { return '审核驳回' }
142
+           }
143
+          if (records.status === 2) { return '到访' }
144
+          if (records.status === 3) { return '认购' }
145
+          if (records.status === 4) { return '签约' }
146
+          // reportRecommendStatus
147
+        },
148
+      },
149
+    ]
150
+    return (
151
+      <>
152
+        <Modal
153
+          title="推荐客户"
154
+          destroyOnClose="true"
155
+          width={900}
156
+          footer={null}
157
+          visible={this.state.visibleData.visible}
158
+          // onOk={() => this.handleOk()}
159
+          onCancel={(e) => this.handleCancel(e)}
160
+        >
161
+          <Table rowKey="independentList" dataSource={this.state.dataSource.records} columns={columns} pagination={{ current: this.state.dataSource.current, pageSize: this.state.dataSource.size, total: this.state.dataSource.total, onChange: e => this.onChange(e) }} />
162
+        </Modal>
163
+      </>
164
+    );
165
+  }
166
+}
167
+// defaultCurrent={1} total={dataSource.total} pageSize={6} onChange={onChange} current={dataSource.current}
168
+
169
+/**
170
+ * 邀请客户
171
+ */
172
+class InviteTable extends React.Component {
173
+  constructor(props) {
174
+    super(props);
175
+    this.state = {
176
+      dataSource: { records: [] },
177
+      visibleData: { visible: false, customerId: '', realtyConsultant: '' },
178
+    }
179
+  }
180
+
181
+  // 挂载之后
182
+  componentDidMount() {
183
+
184
+  }
185
+
186
+  componentDidUpdate(preProps, preState) {
187
+    const { customerId } = this.props.visibleData
188
+
189
+    if (this.props.visibleData.visible !== preState.visibleData.visible) {
190
+      this.getList({ id: customerId, pageNumber: 1, pageSize: 5 })
191
+      this.setState({ visibleData: this.props.visibleData });
192
+    }
193
+  }
194
+
195
+  // 弹框确定按钮
196
+  // eslint-disable-next-line react/sort-comp
197
+  handleOk() {
198
+    this.setState({ dataSource: { records: [] } })
199
+    this.props.onCancel()
200
+  }
201
+
202
+  // 弹框取消按钮
203
+  handleCancel() {
204
+    console.log('345')
205
+    this.setState({ dataSource: { records: [] } })
206
+    this.props.onCancel()
207
+  }
208
+
209
+  getList(params) {
210
+    const { id } = params
211
+    console.log(id)
212
+    if (id === '' || id === undefined) {
213
+      return
214
+    }
215
+    request({ ...apis.customer.InviteClientsList, params: { ...params } }).then(res => {
216
+      this.setState({ dataSource: res })
217
+    }).catch(err => {
218
+      // eslint-disable-next-line no-unused-expressions
219
+
220
+    })
221
+  }
222
+
223
+  // 分页
224
+  onChange(pageNum) {
225
+    this.getList({ pageNumber: pageNum, pageSize: 5 })
226
+  }
227
+
228
+  render() {
229
+    const columns = [
230
+      {
231
+        title: '头像',
232
+        dataIndex: 'img',
233
+        key: 'img',
234
+        align: 'center',
235
+        render: (text, record) => <img src={record.avatarurl} width={50} height={50} />,
236
+      },
237
+      {
238
+        title: '用户姓名',
239
+        dataIndex: 'nickname',
240
+        key: 'nickname',
241
+        align: 'center',
242
+        render: (row) => <><span>{console.log(row, 'row')}{row.name || row.nickname}</span></>,
243
+      },
244
+      {
245
+        title: '电话',
246
+        dataIndex: 'phone',
247
+        key: 'phone',
248
+        align: 'center',
249
+      },
250
+      {
251
+        title: '性别',
252
+        dataIndex: 'sex',
253
+        key: 'sex',
254
+        align: 'center',
255
+        render: (text, list) => <span>{list.sex === 1 ? '男' : '女'}</span>,
256
+      },
257
+    ]
258
+    return (
259
+      <>
260
+        <Modal
261
+          title="邀请经纪人"
262
+          destroyOnClose="true"
263
+          width={900}
264
+          footer={null}
265
+          visible={this.state.visibleData.visible}
266
+          // onOk={() => this.handleOk()}
267
+          onCancel={(e) => this.handleCancel(e)}
268
+        >
269
+          <Table rowKey="independent" dataSource={this.state.dataSource.records} columns={columns} pagination={{ total: this.state.dataSource.total, onChange: e => this.onChange(e) }} />
270
+        </Modal>
271
+      </>
272
+    );
273
+  }
274
+}
275
+
276
+/**
277
+ *
278
+ *主题列表
279
+ * @param {*} props
280
+ * @returns
281
+ */
282
+function body(props) {
283
+  const { getFieldDecorator, getFieldsValue } = props.form
284
+
285
+  // eslint-disable-next-line react-hooks/rules-of-hooks
286
+  const [dataSource, setDataSource] = useState({ records: [] })
287
+
288
+  // eslint-disable-next-line react-hooks/rules-of-hooks
289
+  useEffect(() => {
290
+    getList({ pageNumber: 1, pageSize: 10 })
291
+  }, [])
292
+
293
+
294
+  function openNotificationWithIcon(type, message) {
295
+    notification[type]({
296
+      message,
297
+      description:
298
+        '',
299
+    });
300
+  }
301
+
302
+  function getList(params) {
303
+    // 网路请求
304
+    request({ ...apis.customer.agents, params: { ...params } }).then(res => {
305
+      setDataSource(res)
306
+    }).catch(err => {
307
+      openNotificationWithIcon('error', err)
308
+    })
309
+  }
310
+
311
+  // 提交事件
312
+  function handleSubmit(e) {
313
+    e.preventDefault();
314
+    props.form.validateFields((err, values) => {
315
+      if (!err) {
316
+        getList({ pageNum: 1, pageSize: 10, ...values })
317
+      }
318
+    });
319
+  }
320
+  // eslint-disable-next-line react-hooks/rules-of-hooks
321
+  const [gVisibleData, setGVisibleData] = useState({ visible: false, customerId: '', realtyConsultant: '' })
322
+  // eslint-disable-next-line react-hooks/rules-of-hooks
323
+  const [gInviteData, setGInviteData] = useState({ visible: false, customerId: '', realtyConsultant: '' })
324
+  // Change 事件
325
+  function handleSelectChange(e) {
326
+    // eslint-disable-next-line no-console
327
+    console.log(e)
328
+  }
329
+  function gM(row) {
330
+    setGVisibleData({ visible: true, customerId: row.personId, realtyConsultant: row.realtyConsultant })
331
+
332
+    setGInviteData({ visible: false })
333
+  }
334
+
335
+  function Invite(row) {
336
+    setGInviteData({ visible: true, customerId: row.personId, realtyConsultant: row.realtyConsultant })
337
+
338
+    setGVisibleData({ visible: false })
339
+  }
340
+
341
+  // 分页
342
+  function onChange(pageNum) {
343
+    // eslint-disable-next-line react-hooks/rules-of-hooks
344
+    getList({ pageNumber: pageNum, pageSize: 10 })
345
+  }
346
+
347
+  /**
348
+    * 重置搜索
349
+    */
350
+  function handleReset() {
351
+    props.form.resetFields();
352
+    getList({ pageNumber: 1, pageSize: 10 })
353
+  }
354
+
355
+  function toAudit(cuurentId) {
356
+    router.push({
357
+      pathname: '/customer/recommendCustomer/audit',
358
+      query: {
359
+        id: cuurentId,
360
+      },
361
+    })
362
+  }
363
+
364
+  function exportIndependen() {
365
+    const fieldsValue = getFieldsValue()
366
+    console.log('fieldsValue', fieldsValue)
367
+    request({ ...apis.customer.customerRecommendAgentsExport, responseType: 'blob', params: { ...fieldsValue } })
368
+      .then(response => {
369
+        download(response)
370
+      }).catch(error => {
371
+
372
+      })
373
+  }
374
+
375
+  function download(data) {
376
+    if (!data) {
377
+      return
378
+    }
379
+    const url = window.URL.createObjectURL(new Blob([data]))
380
+    const link = document.createElement('a')
381
+    link.style.display = 'none'
382
+    link.href = url
383
+    link.setAttribute('download', '经纪人.xlsx')
384
+    document.body.append(link)
385
+    link.click()
386
+  }
387
+
388
+  const columns = [
389
+    {
390
+      title: '头像',
391
+      dataIndex: 'avatarurl',
392
+      key: 'avatarurl',
393
+      render: (_, record) => <Avatar shape="square" src={record.avatarurl} size={64} icon="user" />,
394
+    },
395
+    {
396
+      title: '姓名',
397
+      dataIndex: 'nickname',
398
+      key: 'nickname',
399
+      render: (_, record) => <><span>{record.name || record.nickname}</span></>,
400
+    },
401
+    {
402
+      title: '电话',
403
+      dataIndex: 'phone',
404
+      key: 'phone',
405
+    },
406
+    {
407
+      title: '性别',
408
+      dataIndex: 'gender',
409
+      key: 'gender',
410
+      // eslint-disable-next-line no-nested-ternary
411
+      render: (_, record) => <><span>{record.gender === '1' ? '男' : record.gender === '2' ? '女' : '未知'}</span></>,
412
+    },
413
+    {
414
+      title: '类型',
415
+      dataIndex: 'personType',
416
+      key: 'personType',
417
+      render: (_, record) => <><span>{record.personType === 'channel agent' ? '专业经纪人' : '专业经纪人'}</span></>,
418
+    },
419
+    {
420
+      title: '所属渠道',
421
+      dataIndex: 'channelName',
422
+      key: 'channelName',
423
+      render: (_, record) => <><span>{record.channelName}</span></>,
424
+    },
425
+    {
426
+      title: '操作',
427
+      dataIndex: 'customerId',
428
+      key: 'customerId',
429
+      render: (_, record) => (
430
+        <>
431
+          {
432
+            <>
433
+              {/* <span style={{ color: 'rgba(239,39,58,1)' }}>查看详细</span> */}
434
+              {/* <AuthButton name="admin.channel.InviteClientsList.get" noRight={null}>
435
+                <a style={{ color: 'rgba(239,39,58,1)' }} onClick={() => Invite(record)}>邀请经纪人</a>
436
+              </AuthButton> */}
437
+              {/* &nbsp;&nbsp;&nbsp;&nbsp; */}
438
+              <AuthButton name="admin.customer.recommend.id.get" noRight={null}>
439
+                <a style={{ color: 'rgba(239,39,58,1)' }} onClick={() => gM(record)}>推荐客户</a>
440
+              </AuthButton>
441
+            </>
442
+          }
443
+        </>
444
+      ),
445
+    },
446
+  ]
447
+
448
+  // <div>
449
+  //         <span className={channels.selectName}>渠道名称</span>
450
+  //         <Select defaultValue="请选择" style={{ width: 180 }} onChange={handleChange}>
451
+  //           <option value="">全部</option>
452
+  //           {data.channelNmae.map(Item =>
453
+  //             <Option value={Item.channelId}> {Item.channelName} </Option>,
454
+  //           )}
455
+  //           {/* {listItems} */}
456
+  //         </Select>
457
+  //       </div>
458
+  //       <div ></div>
459
+
460
+  return (
461
+    <>
462
+      <Form layout="inline" onSubmit={e => handleSubmit(e, props)} style={{ display: 'flex', alignItems: 'center' }}>
463
+        <Form.Item>
464
+          {getFieldDecorator('channelId')(
465
+            <ChannelSelect />
466
+            //   <Select defaultValue="渠道名称" style={{ width: 180 }} onChange={handleChange}>
467
+            //   <option value="">全部</option>
468
+            //   {data.channelNmae.map(Item =>
469
+            //     <Option value={Item.channelId}> {Item.channelName} </Option>,
470
+            //   )}
471
+
472
+            // </Select>,
473
+          )}
474
+        </Form.Item>
475
+        <Form.Item>
476
+          {getFieldDecorator('name')(
477
+            <Input
478
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
479
+              placeholder="姓名"
480
+            />,
481
+          )}
482
+        </Form.Item>
483
+        <Form.Item>
484
+          {getFieldDecorator('tel')(
485
+            <Input
486
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
487
+              placeholder="电话"
488
+            />,
489
+          )}
490
+        </Form.Item>
491
+        <Form.Item style={{ position: 'absolute', right: '38px' }} >
492
+          <AuthButton name="admin.major.search" noRight={null}>
493
+            <Button type="primary" htmlType="submit" >
494
+              搜索
495
+            </Button>
496
+          </AuthButton>
497
+          <Button style={{ marginLeft: 8 }} onClick={handleReset}>
498
+            重置
499
+          </Button>
500
+        </Form.Item>
501
+      </Form>
502
+      <AuthButton name="admin.major.import" noRight={null}>
503
+        <Button type="primary" onClick={() => exportIndependen()} style={{ float: 'right', margin: '20px 0', zIndex: 1 }}>
504
+          导出
505
+        </Button>
506
+      </AuthButton>
507
+      <Table rowKey="independentIndex" dataSource={dataSource.records} columns={columns} pagination={{ total: dataSource.total, onChange }} />
508
+      {/* 推荐客户 */}
509
+      <ModalTable visibleData={gVisibleData} onCancel={() => setGVisibleData({ visible: false, customerId: '', realtyConsultant: '' })}/>
510
+
511
+      {/* 邀请经纪人 */}
512
+      <InviteTable visibleData={gInviteData} onCancel={() => setGInviteData({ visible: false, customerId: '', realtyConsultant: '' })} />
513
+    </>
514
+  );
515
+}
516
+const WrappedBody = Form.create({ name: 'body' })(body);
517
+
518
+export default WrappedBody

+ 54
- 0
estateagents-admin-manager/src/pages/channel/independentList/style.css Ver fichero

@@ -0,0 +1,54 @@
1
+.SubmitButton {
2
+  background: #ef273a;
3
+  border-radius: 7px;
4
+  border: 0px;
5
+}
6
+.SelectFrom {
7
+  width: 180px;
8
+  background: #ffffff;
9
+  border-radius: 7px;
10
+  border: 1px solid #dbdbdb;
11
+}
12
+.addButton {
13
+  background: #50be00;
14
+  border-radius: 4px;
15
+  border: 0px;
16
+  margin: 10px 0px;
17
+}
18
+.cardText {
19
+  font-size:  0.106rem;
20
+  color: #333;
21
+  line-height: 24px;
22
+  display: flex;
23
+  align-items: center;
24
+  position: relative;
25
+}
26
+.cardItem {
27
+  font-size:  0.106rem;
28
+  font-weight: 400;
29
+  color: #666;
30
+  line-height: 24px;
31
+  display: flex;
32
+  align-items: center;
33
+}
34
+.ediText {
35
+  font-size:  0.106rem;
36
+  color: #ff925c;
37
+  line-height: 24px;
38
+  position: absolute;
39
+  right: 0;
40
+}
41
+.title {
42
+  display: inline-block;
43
+  width:  0.54rem;
44
+  justify-content: space-between;
45
+  text-align: justify;
46
+  text-align-last: justify;
47
+}
48
+.address {
49
+  width: 400px;
50
+  height: 24px;
51
+  text-overflow: ellipsis;
52
+  white-space: nowrap;
53
+  overflow: hidden;
54
+}

+ 58
- 0
estateagents-admin-manager/src/pages/channel/independentList/style.less Ver fichero

@@ -0,0 +1,58 @@
1
+.SubmitButton {
2
+  background: rgba(239,39,58,1);
3
+  border-radius: 6px;
4
+  border: 0px;
5
+}
6
+.SelectFrom {
7
+  width: 180px;
8
+  background: #ffffff;
9
+  border-radius: 6px;
10
+  border: 1px solid #dbdbdb;
11
+}
12
+.addButton {
13
+  background: #50be00;
14
+  border-radius: 4px;
15
+  border: 0px;
16
+  margin: 10px 0px;
17
+}
18
+.cardText {
19
+  color: #333;
20
+  display: flex;
21
+  align-items: center;
22
+  position: relative;
23
+  line-height: 1.5;
24
+  font-size: 0.106rem;
25
+  margin-bottom: 0.08rem;
26
+
27
+}
28
+.cardItem{
29
+  color: #666;
30
+  display: flex;
31
+  align-items: center;  
32
+  line-height: 1.5;
33
+  font-size: 0.106rem;
34
+  margin-bottom: 0.08rem;
35
+}
36
+.ediText {
37
+  font-size: 0.106rem;
38
+  color: #ff925c;
39
+  line-height: 24px;
40
+  position: absolute;
41
+  right: 0;
42
+}
43
+.title{
44
+  display: inline-block;
45
+  width:  0.54rem;
46
+  justify-content: space-between;
47
+  text-align: justify;
48
+  text-align-last:justify
49
+}
50
+
51
+.address { 
52
+  width: 400px;
53
+  height: 24px; 
54
+  text-overflow: ellipsis; 
55
+  white-space: nowrap;
56
+  overflow: hidden;
57
+}
58
+

+ 54
- 0
estateagents-admin-manager/src/pages/channel/independentList/style.wxss Ver fichero

@@ -0,0 +1,54 @@
1
+.SubmitButton {
2
+  background: #ef273a;
3
+  border-radius: 7px;
4
+  border: 0px;
5
+}
6
+.SelectFrom {
7
+  width: 180px;
8
+  background: #ffffff;
9
+  border-radius: 7px;
10
+  border: 1px solid #dbdbdb;
11
+}
12
+.addButton {
13
+  background: #50be00;
14
+  border-radius: 4px;
15
+  border: 0px;
16
+  margin: 10px 0px;
17
+}
18
+.cardText {
19
+  font-size:  0.106rem;
20
+  color: #333;
21
+  line-height: 24px;
22
+  display: flex;
23
+  align-items: center;
24
+  position: relative;
25
+}
26
+.cardItem {
27
+  font-size:  0.106rem;
28
+  font-weight: 400;
29
+  color: #666;
30
+  line-height: 24px;
31
+  display: flex;
32
+  align-items: center;
33
+}
34
+.ediText {
35
+  font-size:  0.106rem;
36
+  color: #ff925c;
37
+  line-height: 24px;
38
+  position: absolute;
39
+  right: 0;
40
+}
41
+.title {
42
+  display: inline-block;
43
+  width:  0.54rem;
44
+  justify-content: space-between;
45
+  text-align: justify;
46
+  text-align-last: justify;
47
+}
48
+.address {
49
+  width: 400px;
50
+  height: 24px;
51
+  text-overflow: ellipsis;
52
+  white-space: nowrap;
53
+  overflow: hidden;
54
+}

+ 111
- 0
estateagents-admin-manager/src/pages/channel/newCustomer/dataRecord.jsx Ver fichero

@@ -0,0 +1,111 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker } from 'antd';
3
+import router from 'umi/router';
4
+import apis from '../../../services/apis';
5
+import request from '../../../utils/request';
6
+import AuthButton from '../../../components/AuthButton';
7
+
8
+
9
+const dataRecord = props => {
10
+    const [data, setData] = useState({})
11
+    const { targetId, targetType, channelId, targetName, buildingId, newCustomers, startDate, endDate } = props.location.query
12
+
13
+    useEffect(() => {
14
+        getList({ pageNum: 1, pageSize: 10 })
15
+
16
+    }, [])
17
+
18
+    const getList = params => {
19
+        request({ ...apis.channelList.newuserList, params: { ...params, targetId: targetId,targetType: targetType,channelId: channelId,buildingId: buildingId,startDate: startDate, endDate: endDate } }).then(data => {
20
+            console.log(data,"dddddddddddd")
21
+          setData(data)
22
+        }).catch(e => {
23
+          console.log(e)
24
+        })
25
+    }
26
+
27
+    const columns = [
28
+        {
29
+            title: '姓名',
30
+            dataIndex: 'nickName',
31
+            key: 'nickName',
32
+            align: 'center',
33
+        },
34
+        {
35
+            title: '电话',
36
+            dataIndex: 'phone',
37
+            key: 'phone',
38
+            align: 'center',
39
+        },
40
+        {
41
+            title: '性别',
42
+            dataIndex: 'gender',
43
+            key: 'gender',
44
+            align: 'center',
45
+        },
46
+        {
47
+            title: '归属地',
48
+            dataIndex: 'province',
49
+            key: 'province',
50
+            align: 'center',
51
+        },
52
+        {
53
+            title: '注册时间',
54
+            dataIndex: 'createDate',
55
+            key: 'createDate',
56
+            align: 'center',
57
+        },
58
+
59
+    ]
60
+
61
+
62
+
63
+    const changePageNum = pageNumber => {
64
+        getList({ pageNum: pageNumber, pageSize: 10 })
65
+    }
66
+
67
+
68
+/**
69
+     * 导出
70
+     */
71
+    const exportExcel = () => {
72
+        // const fieldsValue = getFieldsValue()
73
+        // console.log('fieldsValue', fieldsValue)
74
+        request({ ...apis.channelList.newuserListExport, params: { targetId: targetId,targetType: targetType,channelId: channelId,buildingId: buildingId,startDate: startDate, endDate: endDate } })
75
+          .then(data => {
76
+            if (!data) {
77
+              return
78
+            }
79
+            const url = window.URL.createObjectURL(new Blob([data]))
80
+            const link = document.createElement('a')
81
+            link.style.display = 'none'
82
+            link.href = url
83
+            link.setAttribute('download', '注册用户.xlsx')
84
+            document.body.append(link)
85
+            link.click()
86
+          }).catch(() => {
87
+    
88
+          })
89
+      }
90
+
91
+    return <>
92
+        <div>
93
+            <div>
94
+                <span>内容:{targetName}</span>
95
+                <Button style={{ float: 'right', zIndex: 1 }} onClick={() => router.go(-1)}>
96
+                    返回
97
+               </Button>
98
+            </div>
99
+            <div style={{ marginTop: '20px'  }}>
100
+                <span>注册用户:{newCustomers}</span>
101
+                <Button type="primary" style={{ float: 'right', marginBottom: '20px', zIndex: 1 }} onClick={exportExcel}>导出</Button>
102
+            </div>
103
+            <Table style={{ marginTop: '30px' }} dataSource={data.records || []} columns={columns} pagination={false} rowKey="activityList" />
104
+            {/* <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
105
+        <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} current={data.current} />
106
+      </div> */}
107
+        </div>
108
+    </>
109
+}
110
+
111
+export default dataRecord

+ 322
- 0
estateagents-admin-manager/src/pages/channel/newCustomer/index.jsx Ver fichero

@@ -0,0 +1,322 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, Radio, DatePicker, notification } from 'antd';
3
+import router from 'umi/router';
4
+import moment from 'moment';
5
+import AuthButton from '@/components/AuthButton';
6
+import withActions from '@/components/ActionList';
7
+import EditIcon from '@/components/EditIcon';
8
+import Navigate from '@/components/Navigate';
9
+import styles from '../../style/GoodsList.less';
10
+import BuildSelect from '@/components/SelectButton/BuildSelect'
11
+import QrcodeType from '@/components/SelectButton/QrcodeType1'
12
+import ChannelSelect from '@/components/SelectButton/channelSelect'
13
+import apis from '../../../services/apis';
14
+import request from '../../../utils/request';
15
+
16
+// import RaiseHelpDoc from '../edit/components/RaiseHelpDoc';
17
+
18
+// function getDayBegin(dt) {
19
+//     return moment(dt, 'day').hours(0).minutes(0).seconds(0).milliseconds(0).format('YYYY-MM-DDTHH:mm:ss')+'.000Z';
20
+//   }
21
+
22
+
23
+//   function getDayEnd(dt) {
24
+//     return moment(dt, 'day').hours(23).minutes(59).seconds(59).milliseconds(999).format('YYYY-MM-DDTHH:mm:ss')+'.999Z';
25
+//   }
26
+const { RangePicker } = DatePicker
27
+
28
+const qrcodelist = props => {
29
+    const { id, name, customerNum } = props.location.query
30
+    const [data, setData] = useState([])
31
+    const [showHelp, setShowHelp] = useState(false)
32
+    const [endDate, setEndDate] = useState(new Date())
33
+    const [startDate, setStartDate] = useState(moment().subtract(7, 'day').toDate())
34
+
35
+    // setEndDate(`${moment(dateStrings[1]).format('YYYY-MM-DDT00:00:00.000')}Z`)
36
+    // setStartDate(`${moment(dateStrings[0]).format('YYYY-MM-DDT00:00:00.000')}Z`)
37
+    // 查询列表
38
+    const getList = params => {
39
+        request({ ...apis.channelList.getIntroductionList, params: { ...params, channelId: id } }).then(data => {
40
+            console.log(data)
41
+            setData(data)
42
+        })
43
+    }
44
+    const formatDate = (start, end) => {
45
+        const tempStartDate = `${moment(start).format('YYYY-MM-DDT00:00:00.000')}Z`
46
+        const tempEndDate = `${moment(end).format('YYYY-MM-DDT23:59:59.999')}Z`
47
+        return { startDate: tempStartDate, endDate: tempEndDate }
48
+    }
49
+    // eslint-disable-next-line react-hooks/rules-of-hooks
50
+    useEffect(() => {
51
+        setEndDate(new Date())
52
+        setStartDate(moment().subtract(7, 'day').toDate())
53
+        getList({ pageNum: 1, pageSize: 10, ...formatDate(startDate, endDate) });
54
+    }, [])
55
+
56
+
57
+    const toNewuser = (record) => {
58
+        router.push({
59
+            pathname: '/channel/newCustomer/dataRecord',
60
+            query: {
61
+                channelId: record.channelId,
62
+                targetName: record.targetName,
63
+                targetId: record.targetId,
64
+                targetType: record.targetType,
65
+                buildingId: record.buildingId,
66
+                newCustomers: record.newCustomers,
67
+                ...formatDate(startDate, endDate)
68
+            },
69
+        });
70
+    }
71
+
72
+    const toVisitNum = (record) => {
73
+        router.push({
74
+            pathname: '/channel/newCustomer/visitNum',
75
+            query: {
76
+                channelId: record.channelId,
77
+                targetName: record.targetName,
78
+                targetId: record.targetId,
79
+                targetType: record.targetType,
80
+                buildingId: record.buildingId,
81
+                visitNum: record.visitNum,
82
+                ...formatDate(startDate, endDate)
83
+            },
84
+        });
85
+    }
86
+
87
+    const toPersonNum = (record) => {
88
+        router.push({
89
+            pathname: '/channel/newCustomer/personNum',
90
+            query: {
91
+                channelId: record.channelId,
92
+                targetName: record.targetName,
93
+                targetId: record.targetId,
94
+                targetType: record.targetType,
95
+                buildingId: record.buildingId,
96
+                visitPersons: record.visitPersons,
97
+                ...formatDate(startDate, endDate)
98
+            },
99
+        });
100
+    }
101
+
102
+    /**
103
+     * 导出
104
+     */
105
+    const exportExcel = () => {
106
+        // console.log('fieldsValue', ...props.form.getFieldsValue())
107
+        request({ ...apis.channelList.getIntroductionListExport, params: { channelId: id, ...props.form.getFieldsValue(), ...formatDate(startDate, endDate) } })
108
+            .then(data => {
109
+                if (!data) {
110
+                    return
111
+                }
112
+                const url = window.URL.createObjectURL(new Blob([data]))
113
+                const link = document.createElement('a')
114
+                link.style.display = 'none'
115
+                link.href = url
116
+                link.setAttribute('download', '引进注册用户.xlsx')
117
+                document.body.append(link)
118
+                link.click()
119
+            }).catch(() => {
120
+
121
+            })
122
+    }
123
+
124
+    // 排序
125
+    const handleTableChange = (pagination, filters, sorter) => {
126
+        console.log(pagination, filters, sorter)
127
+        // if (sorter.order === 'ascend') { 
128
+        //     getList({ pageNum: 1, pageSize: 10, ...props.form.getFieldsValue(), startDate, endDate, asc: sorter.columnKey })
129
+        // } else if (sorter.order === 'descend') {
130
+        //     getList({ pageNum: 1, pageSize: 10, ...props.form.getFieldsValue(), startDate, endDate, desc: sorter.columnKey })
131
+        // } else {
132
+        //     getList({ pageNum: 1, pageSize: 10, ...props.form.getFieldsValue(), startDate, endDate });
133
+        // }
134
+        // sortField, sortOrder
135
+        // getList({ pageNum: 1, pageSize: 10, ...props.form.getFieldsValue(), startDate, endDate, sorter.columnKey, sorter.order })
136
+        getList({ channelId: id, ...props.form.getFieldsValue(), ...formatDate(startDate, endDate), sortField: sorter.columnKey, sortOrder: sorter.order })
137
+    };
138
+
139
+    /**
140
+     *
141
+     *
142
+     * @param {*} props
143
+     * @returns
144
+     */
145
+    const columns = [
146
+        {
147
+            title: '类型',
148
+            dataIndex: 'targetType',
149
+            key: 'targetType',
150
+            align: 'center',
151
+            render: (text, record) => <span>{text == 'building' ? '项目' : text == 'activity' ? '报名活动' : text == 'help' ? '助力活动' : text == 'group' ? '拼团活动'
152
+                : text == 'h5' ? 'H5活动' : text == 'live' ? '直播活动' : text == 'news' ? '资讯' : text == 'house' ? '在线选房' : ''}</span>,
153
+        },
154
+        {
155
+            title: '内容',
156
+            dataIndex: 'targetName',
157
+            key: 'targetName',
158
+            align: 'center',
159
+
160
+        },
161
+        {
162
+            title: '关联项目',
163
+            dataIndex: 'buildingName',
164
+            key: 'buildingName',
165
+            align: 'center',
166
+
167
+        },
168
+        {
169
+            title: '注册用户',
170
+            dataIndex: 'newCustomers',
171
+            key: 'new_customers',
172
+            align: 'center',
173
+            sorter: true,
174
+            render: (text, record) => <Navigate onClick={() => toNewuser(record)}>{text}</Navigate>,
175
+
176
+        },
177
+        {
178
+            title: '访问人数',
179
+            dataIndex: 'visitPersons',
180
+            key: 'visit_persons',
181
+            align: 'center',
182
+            sorter: true,
183
+            render: (text, record) => <Navigate onClick={() => toPersonNum(record)}>{text}</Navigate>,
184
+
185
+        },
186
+        {
187
+            title: '访问次数',
188
+            dataIndex: 'visitNum',
189
+            key: 'visit_num',
190
+            align: 'center',
191
+            sorter: true,
192
+            render: (text, record) => <Navigate onClick={() => toVisitNum(record)}>{text}</Navigate>,
193
+        },
194
+    ];
195
+
196
+
197
+    const changePageNum = pageNumber => {
198
+        getList({ pageNum: pageNumber, pageSize: 10, ...props.form.getFieldsValue(), ...formatDate(startDate, endDate) })
199
+    }
200
+
201
+
202
+    // 提交事件
203
+    const handleSubmit = e => {
204
+        e.preventDefault();
205
+
206
+        props.form.validateFields((err, values) => {
207
+            if (!err) {
208
+                console.log(values, 'values')
209
+                getList({ pageNum: 1, pageSize: 10, ...values, ...formatDate(startDate, endDate) })
210
+            }
211
+        });
212
+    }
213
+
214
+    //   // 重置搜索
215
+    function handleReset() {
216
+        props.form.resetFields();
217
+        setEndDate(new Date())
218
+        setStartDate(moment().subtract(7, 'day').toDate())
219
+        getList({ pageNum: 1, pageSize: 10, ...formatDate(moment().subtract(7, 'day').toDate(), new Date()) })
220
+    }
221
+
222
+    function onChangetime(dates, dateStrings) {
223
+        setEndDate(`${moment(dateStrings[1]).format('YYYY-MM-DDT00:00:00.000')}Z`)
224
+        setStartDate(`${moment(dateStrings[0]).format('YYYY-MM-DDT00:00:00.000')}Z`)
225
+        // daterange[1] = `${moment(dateStrings[1]).format('YYYY-MM-DDT00:00:00.000')}Z`
226
+        // daterange[0] = `${moment(dateStrings[0]).format('YYYY-MM-DDT00:00:00.000')}Z`
227
+
228
+    }
229
+
230
+    const getDataOf = days => {
231
+
232
+        setEndDate(new Date())
233
+        setStartDate(moment().subtract(days, 'day').toDate())
234
+
235
+        getList({ pageNum: 1, pageSize: 10, ...formatDate(moment().subtract(days, 'day').toDate(), new Date()) })
236
+        // userResource({ startDate: moment().subtract(days, 'day').toDate(), endDate: new Date() })
237
+    }
238
+
239
+    const dateRange = [moment(startDate), moment(endDate)]
240
+
241
+    const { getFieldDecorator } = props.form
242
+    return (
243
+
244
+        <>
245
+            <div style={{ marginBottom: '20px' }}>
246
+                <span> 渠道{name}总计引进{customerNum}个注册用户</span>
247
+                <Icon type="question-circle" theme="filled" style={{ fontSize: '25px', color: '#F00', marginLeft: '30px' }} onClick={() => setShowHelp(true)} />
248
+                <Button style={{ float: 'right', zIndex: 1 }} onClick={() => router.go(-1)}>
249
+                    返回
250
+               </Button>
251
+            </div>
252
+            <Modal
253
+                title="相关说明"
254
+                centereds
255
+                visible={showHelp}
256
+                footer={null}
257
+                onCancel={() => setShowHelp(false)}
258
+            // width="700px"
259
+            >
260
+                <p style={{ fontSize: '0.106rem', color: '#333', marginBottom: '8px' }}>新增注册用户:</p>
261
+                <p style={{ fontSize: '0.106rem', color: '#999', marginBottom: '8px' }}>通过关联当前渠道的二维码授权手机号的总人数</p>
262
+                <p style={{ fontSize: '0.106rem', color: '#333', marginBottom: '8px' }}>访问人数:</p>
263
+                <p style={{ fontSize: '0.106rem', color: '#999', marginBottom: '8px' }}>通过关联当前渠道的二维码访问小程序的总人数</p>
264
+                <p style={{ fontSize: '0.106rem', color: '#333', marginBottom: '8px' }}>访问次数:</p>
265
+                <p style={{ fontSize: '0.106rem', color: '#999', marginBottom: '8px' }}>通过关联当前渠道的二维码访问小程序的总次数</p>
266
+
267
+
268
+            </Modal>
269
+            <Form layout="inline" style={{ marginBottom: '10px' }} onSubmit={e => handleSubmit(e)}>
270
+                <Form.Item>
271
+                    {getFieldDecorator('state', {
272
+                        initialValue: 'a'
273
+                    })(
274
+                        <Radio.Group buttonStyle="solid" defaultValue="a" >
275
+                            <Radio.Button value="a" onClick={() => getDataOf(7)}>最近7天</Radio.Button>
276
+                            <Radio.Button value="b" onClick={() => getDataOf(30)}>最近1月</Radio.Button>
277
+                        </Radio.Group>,
278
+                    )}
279
+
280
+                </Form.Item>
281
+                {/* <Form.Item>
282
+                        <RangePicker value={dateRange} onChange={handleDateChange} placeholder={['开始日期', '结束日期']} />
283
+                    </Form.Item> */}
284
+                <Form.Item>
285
+
286
+                    <RangePicker
287
+                        ranges={{
288
+                            Today: [moment(), moment()],
289
+                            'This Month': [moment().startOf('month'), moment().endOf('month')],
290
+                        }}
291
+                        value={dateRange}
292
+                        onChange={(_dates, dateStrings) => onChangetime(_dates, dateStrings)}
293
+                        allowClear={false}
294
+                    />
295
+
296
+                </Form.Item>
297
+                <Form.Item>
298
+                    {getFieldDecorator('buildingId')(
299
+                        <BuildSelect style={{ width: '200px' }} />,
300
+                    )}
301
+                </Form.Item>
302
+                <Form.Item>
303
+                    {getFieldDecorator('targetType')(
304
+                        <QrcodeType all visible />,
305
+                    )}
306
+                </Form.Item>
307
+                <Form.Item>
308
+                    <Button type="primary" htmlType="submit" className={styles.searchBtn}>搜索</Button>
309
+                    <Button style={{ marginLeft: 8 }} onClick={handleReset}>重置</Button>
310
+                </Form.Item>
311
+            </Form>
312
+            <Button type="primary" style={{ float: 'right', marginBottom: '20px', zIndex: 1 }} onClick={exportExcel}>导出</Button>
313
+            <Table dataSource={data.records} columns={columns} pagination={false} rowKey={r => r.serialNo} onChange={handleTableChange} />
314
+            <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
315
+                <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={e => changePageNum(e)} current={data.current} scroll={{ y: 500 }} />
316
+            </div>
317
+        </>
318
+    )
319
+}
320
+const WrappedQrcodelist = Form.create({ name: 'qrcodelist' })(qrcodelist);
321
+
322
+export default WrappedQrcodelist

+ 120
- 0
estateagents-admin-manager/src/pages/channel/newCustomer/personNum.jsx Ver fichero

@@ -0,0 +1,120 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker } from 'antd';
3
+import router from 'umi/router';
4
+import apis from '../../../services/apis';
5
+import request from '../../../utils/request';
6
+import AuthButton from '../../../components/AuthButton';
7
+
8
+
9
+const data = [
10
+    {
11
+        nickName: '2342',
12
+        phone: '2342',
13
+        gender: '2342',
14
+        province: '2342',
15
+    },
16
+]
17
+
18
+const dataRecord = props => {
19
+      const [data, setData] = useState({})
20
+      const { targetId, targetType, channelId, targetName, buildingId, visitPersons, startDate, endDate } = props.location.query
21
+
22
+    useEffect(() => {
23
+        getList({ pageNum: 1, pageSize: 10 })
24
+
25
+    }, [])
26
+
27
+    const getList = params => {
28
+        console.log(params)
29
+        request({ ...apis.channelList.personNumList, params: { ...params, targetId: targetId,targetType: targetType,channelId: channelId,buildingId: buildingId,startDate: startDate, endDate: endDate} }).then(data => {
30
+          setData(data)
31
+        }).catch(e => {
32
+          console.log(e)
33
+        })
34
+    }
35
+
36
+    const columns = [
37
+        {
38
+            title: '姓名',
39
+            dataIndex: 'nickName',
40
+            key: 'nickName',
41
+            align: 'center',
42
+        },
43
+        {
44
+            title: '电话',
45
+            dataIndex: 'phone',
46
+            key: 'phone',
47
+            align: 'center',
48
+        },
49
+        {
50
+            title: '性别',
51
+            dataIndex: 'gender',
52
+            key: 'gender',
53
+            align: 'center',
54
+        },
55
+        {
56
+            title: '归属地',
57
+            dataIndex: 'province',
58
+            key: 'province',
59
+            align: 'center',
60
+        },
61
+        {
62
+            title: '访问次数',
63
+            dataIndex: 'visitNum',
64
+            key: 'visitNum',
65
+            align: 'center',
66
+        },
67
+
68
+    ]
69
+
70
+
71
+
72
+    const changePageNum = pageNumber => {
73
+        getList({ pageNum: pageNumber, pageSize: 10 })
74
+    }
75
+
76
+
77
+/**
78
+     * 导出
79
+     */
80
+    const exportExcel = () => {
81
+        // const fieldsValue = getFieldsValue()
82
+        // console.log('fieldsValue', fieldsValue)
83
+        request({ ...apis.channelList.personNumListExport, params: { targetId: targetId,targetType: targetType,channelId: channelId,buildingId: buildingId,startDate: startDate, endDate: endDate} })
84
+          .then(data => {
85
+            if (!data) {
86
+              return
87
+            }
88
+            const url = window.URL.createObjectURL(new Blob([data]))
89
+            const link = document.createElement('a')
90
+            link.style.display = 'none'
91
+            link.href = url
92
+            link.setAttribute('download', '访问人数.xlsx')
93
+            document.body.append(link)
94
+            link.click()
95
+          }).catch(() => {
96
+    
97
+          })
98
+      }
99
+
100
+    return <>
101
+        <div>
102
+            <div>
103
+                <span>内容{targetName}</span>
104
+                <Button style={{ float: 'right', zIndex: 1 }} onClick={() => router.go(-1)}>
105
+                    返回
106
+               </Button>
107
+            </div>
108
+            <div style={{ marginTop: '20px'  }}>
109
+                <span>访问人数:{visitPersons}</span>
110
+                <Button type="primary" style={{ float: 'right', marginBottom: '20px', zIndex: 1 }} onClick={exportExcel}>导出</Button>
111
+            </div>
112
+            <Table style={{ marginTop: '30px' }} dataSource={data.records || []} columns={columns} pagination={false} rowKey="activityList" />
113
+            <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
114
+        <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} current={data.current} />
115
+      </div>
116
+        </div>
117
+    </>
118
+}
119
+
120
+export default dataRecord

+ 121
- 0
estateagents-admin-manager/src/pages/channel/newCustomer/visitNum.jsx Ver fichero

@@ -0,0 +1,121 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker } from 'antd';
3
+import router from 'umi/router';
4
+import apis from '../../../services/apis';
5
+import request from '../../../utils/request';
6
+import AuthButton from '../../../components/AuthButton';
7
+
8
+
9
+const data = [
10
+    {
11
+        nickName: '2342',
12
+        phone: '2342',
13
+        gender: '2342',
14
+        province: '2342',
15
+    },
16
+]
17
+
18
+const dataRecord = props => {
19
+    const [data, setData] = useState({})
20
+    const { targetId, targetType, channelId, targetName, buildingId, visitNum, startDate, endDate } = props.location.query
21
+
22
+    useEffect(() => {
23
+        getList({ pageNum: 1, pageSize: 10 })
24
+
25
+    }, [])
26
+
27
+    const getList = params => {
28
+        console.log(params)
29
+        request({ ...apis.channelList.visitNumList, params: { ...params, targetId: targetId,targetType: targetType,channelId: channelId,buildingId: buildingId,startDate: startDate, endDate: endDate } }).then(data => {
30
+          console.log(data)
31
+          setData(data)
32
+        }).catch(e => {
33
+          console.log(e)
34
+        })
35
+    }
36
+
37
+    const columns = [
38
+        {
39
+            title: '姓名',
40
+            dataIndex: 'nickName',
41
+            key: 'nickName',
42
+            align: 'center',
43
+        },
44
+        {
45
+            title: '电话',
46
+            dataIndex: 'phone',
47
+            key: 'phone',
48
+            align: 'center',
49
+        },
50
+        {
51
+            title: '性别',
52
+            dataIndex: 'gender',
53
+            key: 'gender',
54
+            align: 'center',
55
+        },
56
+        {
57
+            title: '归属地',
58
+            dataIndex: 'province',
59
+            key: 'province',
60
+            align: 'center',
61
+        },
62
+        {
63
+            title: '访问时间',
64
+            dataIndex: 'visitDate',
65
+            key: 'visitDate',
66
+            align: 'center',
67
+        },
68
+
69
+    ]
70
+
71
+
72
+
73
+    const changePageNum = pageNumber => {
74
+        getList({ pageNum: pageNumber, pageSize: 10 })
75
+    }
76
+
77
+
78
+/**
79
+     * 导出
80
+     */
81
+    const exportExcel = () => {
82
+        // const fieldsValue = getFieldsValue()
83
+        // console.log('fieldsValue', fieldsValue)
84
+        request({ ...apis.channelList.visitNumListExport, params: { targetId: targetId,targetType: targetType,channelId: channelId,buildingId: buildingId,startDate: startDate, endDate: endDate } })
85
+          .then(data => {
86
+            if (!data) {
87
+              return
88
+            }
89
+            const url = window.URL.createObjectURL(new Blob([data]))
90
+            const link = document.createElement('a')
91
+            link.style.display = 'none'
92
+            link.href = url
93
+            link.setAttribute('download', '访问次数.xlsx')
94
+            document.body.append(link)
95
+            link.click()
96
+          }).catch(() => {
97
+    
98
+          })
99
+      }
100
+
101
+    return <>
102
+        <div>
103
+            <div>
104
+                <span>内容:{targetName}</span>
105
+                <Button style={{ float: 'right', zIndex: 1 }} onClick={() => router.go(-1)}>
106
+                    返回
107
+               </Button>
108
+            </div>
109
+            <div style={{ marginTop: '20px'  }}>
110
+                <span>访问次数:{visitNum}</span>
111
+                <Button type="primary" style={{ float: 'right', marginBottom: '20px', zIndex: 1 }} onClick={exportExcel}>导出</Button>
112
+            </div>
113
+            <Table style={{ marginTop: '30px' }} dataSource={data.records || []} columns={columns} pagination={false} rowKey="activityList" />
114
+            <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
115
+        <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} current={data.current} />
116
+      </div>
117
+        </div>
118
+    </>
119
+}
120
+
121
+export default dataRecord

+ 172
- 0
estateagents-admin-manager/src/pages/channel/recommendClients.jsx Ver fichero

@@ -0,0 +1,172 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Input, Menu, Dropdown, Button, Icon, message, Table, Divider, Tag, Select, Avatar } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import channels from './channelList.less';
5
+import router from 'umi/router';
6
+import moment from 'moment';
7
+import apis from '../../services/apis';
8
+import request from '../../utils/request'
9
+
10
+const { Option } = Select;
11
+function handleChange(value) {
12
+  console.log(`selected ${value}`);
13
+}
14
+
15
+
16
+const menu = (
17
+  <Menu onClick={handleMenuClick}>
18
+    <Menu.Item key="1">
19
+      <Icon type="user" />
20
+      1st menu item
21
+    </Menu.Item>
22
+    <Menu.Item key="2">
23
+      <Icon type="user" />
24
+      2nd menu item
25
+    </Menu.Item>
26
+    <Menu.Item key="3">
27
+      <Icon type="user" />
28
+      3rd item
29
+    </Menu.Item>
30
+  </Menu>
31
+);
32
+// const dataSource = [
33
+//   {
34
+//     key: '1',
35
+//     img: 'http://img0.imgtn.bdimg.com/it/u=4246326797,2657995307&fm=26&gp=0.jpg',
36
+//     name: '123',
37
+//     age: 32,
38
+//     address: '西湖区湖底公园1号',
39
+//   },
40
+//   {
41
+//     key: '2',
42
+//     img: '',
43
+//     age: 42,
44
+//     address: '西湖区湖底公园1号',
45
+//   },
46
+// ];
47
+
48
+const columns = [
49
+  {
50
+    title: '头像',
51
+    // dataIndex: 'img',
52
+    // key: 'img',
53
+    align: 'center',
54
+
55
+    render: (text, record) => <Avatar shape="square" src={record.picture} size={64} icon="user" />,
56
+  },
57
+  {
58
+    title: '用户姓名',
59
+    dataIndex: 'name',
60
+    key: 'name',
61
+    align: 'center',
62
+    render: (text, record) => <div>{record.name}</div>,
63
+  },
64
+  {
65
+    title: '电话',
66
+    dataIndex: 'phone',
67
+    key: 'phone',
68
+    align: 'center',
69
+  },
70
+  {
71
+    title: '性别',
72
+    dataIndex: 'sex',
73
+    key: 'sex',
74
+    align: 'center',
75
+    render: (text, record) => <span>{record.sex === 1 ? '男' : record.sex === 2 ? '女' : '未知'}</span>
76
+  },
77
+  {
78
+    title: '意向项目',
79
+    dataIndex: 'intention',
80
+    key: 'intention',
81
+    align: 'center',
82
+  },
83
+  {
84
+    title: '推荐时间',
85
+    dataIndex: 'createDate',
86
+    key: 'createDate',
87
+    align: 'center',
88
+    render: (_, record) => <><span>{record.createDate && moment(record.createDate).format('YYYY-MM-DD HH:mm:ss')}</span></>,
89
+  },
90
+  {
91
+    title: '状态',
92
+    dataIndex: 'status',
93
+    key: 'status',
94
+    align: 'center',
95
+    // eslint-disable-next-line consistent-return
96
+    render: (text, records) => {
97
+      //    if (records.status === 1) { if(records.reportRecommendStatus === 0) {return '未审核'} if(records.reportRecommendStatus === 1) {return '报备'} if(records.reportRecommendStatus === 2) {return '推荐'}  }
98
+      // if (records.status === 2) { return '到访' }
99
+      // if (records.status === 3) { return '认购' }
100
+      // if (records.status === 4) { return '签约' }
101
+      // if (records.verifyStatus === 1) { return '待审核' }
102
+      // if (records.verifyStatus === 2) { return '审核同意' }
103
+      // if (records.verifyStatus === 3) { return '签约' }
104
+      // if (records.status === 1) { return '报备' }
105
+      // if (records.status === 2) { return '推荐' }
106
+      // if (records.status === 3) { return '认购' }
107
+      // if (records.status === 4) { return '签约' }
108
+      // if (records.verifyStatus === 1) { return '待审核' }
109
+      // if (records.verifyStatus === 2) { return '审核同意' }
110
+      // if (records.verifyStatus === 3) { return '签约' }
111
+      if (records.status === 1) {
112
+        if (records.verifyStatus === 0) { return '待审核' }
113
+        if (records.verifyStatus === 1) { return '报备' }
114
+        // if (records.reportRecommendStatus === 1) { return '报备' }
115
+        // if (records.reportRecommendStatus === 2) { return '推荐' }}
116
+        if (records.verifyStatus === 2) { return '审核驳回' }
117
+       }
118
+      if (records.status === 2) { return '到访' }
119
+      if (records.status === 3) { return '认购' }
120
+      if (records.status === 4) { return '签约' }
121
+    }
122
+  },
123
+];
124
+
125
+const header = props => {
126
+  // eslint-disable-next-line react-hooks/rules-of-hooks
127
+  const [data, setData] = useState({})
128
+  //   const [page, changePage] = useState({})
129
+  // eslint-disable-next-line react-hooks/rules-of-hooks
130
+  useEffect(() => {
131
+    getListRecommend({ pageNumber: 1, pageSize: 10 })
132
+  }, [])
133
+
134
+  // function getListRecommend(params) {
135
+  //   request({
136
+  //     url: `api/admin/customer/recommend/${props.location.query.id}`,
137
+  //     method: 'GET',
138
+  //     params: { ...params },
139
+  // // eslint-disable-next-line no-shadow
140
+  // }).then(data => {
141
+  //     console.log(data)
142
+  //     setData(data)
143
+  // })
144
+  // }
145
+
146
+  function getListRecommend(params) {
147
+    request({ ...apis.channelList.getListRecommend, urlData: { id: props.location.query.id }, params: { ...params } }).then((data) => {
148
+      setData(data)
149
+    }).catch((err) => {
150
+      console.log(err)
151
+      message.info(err.msg || err.message)
152
+    })
153
+  }
154
+
155
+
156
+  // 分页
157
+  function onChange(pageNum) {
158
+    // eslint-disable-next-line react-hooks/rules-of-hooks
159
+    getListRecommend({ pageNumber: pageNum, pageSize: 10 })
160
+  }
161
+  return (
162
+    <>
163
+      <Table dataSource={data.records} rowKey="recommendClist" columns={columns} pagination={{ pageSize: 10, total: data.total, onChange }} />
164
+    </>
165
+  )
166
+}
167
+
168
+function handleMenuClick(e) {
169
+  message.info('Click on menu item.');
170
+  console.log('click', e);
171
+}
172
+export default header

+ 138
- 0
estateagents-admin-manager/src/pages/charts/CityNums.jsx Ver fichero

@@ -0,0 +1,138 @@
1
+import React, { useState, useEffect } from 'react';
2
+import Echart from '../../components/EchartsTest/EChart';
3
+import { fetch, apis } from '@/utils/request';
4
+
5
+const geoOptions = {
6
+  backgroundColor: '#fff',
7
+  title: {
8
+    text: '城市分布',
9
+    subtext: '数据会存在一定时间延迟',
10
+    left: 40,
11
+    top: 40
12
+  },
13
+  tooltip : {
14
+      trigger: 'item',
15
+      formatter: (params) => {
16
+        return `${params.data.name}: ${params.data.value[2]}`
17
+      }
18
+  },
19
+  geo: {
20
+      map: 'china',
21
+      roam: true,
22
+      zoom: 1.2,
23
+      label: {
24
+        normal: {
25
+          show: true,
26
+          color: '#aaa',
27
+        },
28
+        emphasis: {
29
+          show: true
30
+        }
31
+      },
32
+      itemStyle: {
33
+          normal: {
34
+              areaColor: '#f3f3f3',
35
+              borderColor: '#ddd'
36
+          },
37
+          emphasis: {
38
+              areaColor: '#eee'
39
+          }
40
+      }
41
+  },
42
+}
43
+
44
+const getCityData = fetch(apis.indexEcharts.personCity)
45
+
46
+const mapDataRange = x => {
47
+  // 映射区间 [1, 100000] => [rangeStart, rangeEnd]
48
+  const min = 1
49
+  const max = 100000
50
+  const rangeStart = 16
51
+  const rangeEnd = 24
52
+
53
+  return rangeStart + (x - min) * (rangeEnd - rangeStart) / (max - min)
54
+}
55
+
56
+const CityNums = (props) => {
57
+  const [data, setData]= useState([])
58
+
59
+  useEffect(() => {
60
+    getCityData().then(response => {
61
+      const { selectCityUser = [] } = response || {}
62
+      const data = selectCityUser.map((item) => {
63
+        return {
64
+          name: item.name,
65
+          value: [item.lng - 0, item.lat - 0, item.cityCount]
66
+        }
67
+      })
68
+      setData(data)
69
+    })
70
+  }, [])
71
+
72
+  const options = {
73
+    ...geoOptions,
74
+    series: [
75
+      {
76
+        name: '人数',
77
+        type: 'scatter',
78
+        coordinateSystem: 'geo',
79
+        data,
80
+        symbolSize: 10,
81
+        label: {
82
+            normal: {
83
+                formatter: '{b}',
84
+                position: 'right',
85
+                show: false
86
+            },
87
+            emphasis: {
88
+                show: true
89
+            }
90
+        },
91
+        itemStyle: {
92
+            normal: {
93
+                color: '#DB3C4B'
94
+            }
95
+        }
96
+      },
97
+      {
98
+          name: '前三',
99
+          type: 'effectScatter',
100
+          coordinateSystem: 'geo',
101
+          data: data.sort(function (a, b) {
102
+              return b.value[2] - a.value[2];
103
+          }).slice(0, 3),
104
+          symbolSize: function (val) {
105
+              return mapDataRange(val[2]);
106
+          },
107
+          showEffectOn: 'render',
108
+          rippleEffect: {
109
+              brushType: 'stroke'
110
+          },
111
+          hoverAnimation: true,
112
+          label: {
113
+              normal: {
114
+                  formatter: '{b}',
115
+                  position: 'right',
116
+                  show: false
117
+              }
118
+          },
119
+          itemStyle: {
120
+              normal: {
121
+                  color: '#DB3C4B',
122
+                  shadowBlur: 10,
123
+                  shadowColor: '#333'
124
+              }
125
+          },
126
+          zlevel: 1
127
+      }
128
+    ],
129
+  }
130
+
131
+  return (
132
+    <div style={{ marginBottom:'40px', width: '100%', borderRadius: '12px', boxShadow: '0px 0px 9px 1px rgba(0,0,0,0.12)', overflow: 'hidden' }}>
133
+      <Echart options={options} style={{ width: '100%', height: '600px' }} ></Echart>
134
+    </div>
135
+  )
136
+}
137
+
138
+export default CityNums;

+ 170
- 0
estateagents-admin-manager/src/pages/customer/customerlist/components/BatchAssistConsultant.jsx Ver fichero

@@ -0,0 +1,170 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Table, Avatar, Radio, Modal, Descriptions, notification } from 'antd';
3
+import moment from 'moment';
4
+import request from '../../../../utils/request';
5
+import apis from '../../../../services/apis';
6
+import Styles from '../style.less';
7
+import BuildSelect from '../../../../components/SelectButton/BuildSelect'
8
+
9
+
10
+const { Option } = Select;
11
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
12
+const { Meta } = Card;
13
+
14
+/**
15
+ * 分配置业顾问
16
+ *
17
+ * @param {*} props
18
+ * @returns
19
+ */
20
+class ModalAttribution extends React.Component {
21
+  constructor(props) {
22
+    super(props);
23
+    console.log(props, 'props')
24
+    this.state = {
25
+       dataSource: { records: [] },
26
+       visibleData: { visible: false, customerId: [], buildingName: '' },
27
+    }
28
+  }
29
+
30
+  // 挂载之后
31
+  componentDidMount() {
32
+    // this.getList({ pageNumber: 1, pageSize: 5 })
33
+  }
34
+
35
+  componentDidUpdate(preProps, preState) {
36
+    console.log(this.props.visibleData)
37
+    if (this.props.visibleData.visible !== preState.visibleData.visible) {
38
+      this.getList({ pageNumber: 1, pageSize: 5,buildingId: this.props.visibleData.buildingId})
39
+      this.setState({ visibleData: this.props.visibleData });
40
+    }
41
+  }
42
+
43
+  // 弹框确定按钮
44
+  // eslint-disable-next-line react/sort-comp
45
+  handleOk() {
46
+    this.props.onCancel()
47
+  }
48
+
49
+  // 弹框取消按钮
50
+  handleCancel() {
51
+    this.props.onCancel()
52
+  }
53
+
54
+  changBuilding(buildingId){
55
+    this.getUserList({ pageNumber: 1, pageSize: 5, buildingId: buildingId })
56
+    this.setState({ visibleData: { visible: this.props.visibleData.visible, customerId: this.props.visibleData.customerId, buildingName: buildingId } });
57
+  }
58
+
59
+  getUserList(params){
60
+    console.log('params: ', params)
61
+    if (params.buildingId === '' || params.buildingId === null || params.buildingId === undefined) {
62
+      return
63
+    }
64
+    // 网路请求
65
+    request({ ...apis.customer.buildingConsultant, params: { ...params } }).then(res => {
66
+      this.setState({ dataSource: res })
67
+    }).catch(err => {
68
+      message.err(err)
69
+    })
70
+  }
71
+
72
+  getList(params) {
73
+    // 网路请求
74
+    console.log('params: ', params)
75
+    request({ ...apis.customer.buildingConsultant , params: { ...params }}).then(res => {
76
+      this.setState({ dataSource: res })
77
+    }).catch(err => {
78
+      
79
+    })
80
+  }
81
+
82
+  openNotificationWithIcon = (type, message) => {
83
+    notification[type]({
84
+      message,
85
+      description:
86
+        '',
87
+    });
88
+  };
89
+
90
+   // 分页
91
+  onChange(pageNum) {
92
+    this.getList({ pageNumber: pageNum, pageSize: 5, buildingId: this.state.visibleData.buildingName ||this.props.visibleData.buildingId})
93
+
94
+    // this.getUserList({ pageNumber: pageNum, pageSize: 5, buildingId: this.state.visibleData.buildingName })
95
+  }
96
+
97
+  // 提交
98
+  submitGm(record) {
99
+    // 网路请求
100
+    request({ ...apis.customer.batchConsultantAssist, data: { userId: record.userId
101
+      ,buildingId:this.state.visibleData.buildingName  || this.props.visibleData.buildingId
102
+      , customerIds: this.state.visibleData.customerId } }).then(res => {
103
+      // eslint-disable-next-line no-unused-expressions
104
+      debugger
105
+      if(res!= null && res.failNum > 0 ){
106
+        this.openNotificationWithIcon('success', '共'+res.totalNum+'条数据,失败操作'+res.failNum+'条')
107
+      }else{
108
+        this.openNotificationWithIcon('success', '操作成功')
109
+      }
110
+      this.handleCancel()
111
+    }).catch(err => {
112
+      // eslint-disable-next-line no-unused-expressions
113
+  
114
+    })
115
+  }
116
+
117
+  render() {
118
+    const columns = [
119
+      // {
120
+      //   title: '编号',
121
+      //   dataIndex: 'userId',
122
+      //   key: 'userId',
123
+      // },
124
+      {
125
+        title: '姓名',
126
+        dataIndex: 'userName',
127
+        key: 'userName',
128
+      },
129
+      {
130
+        title: '电话',
131
+        dataIndex: 'phone',
132
+        key: 'phone',
133
+      },
134
+      {
135
+        title: '部门',
136
+        dataIndex: 'department',
137
+        key: 'department',
138
+      },
139
+      {
140
+        title: '岗位',
141
+        dataIndex: 'position',
142
+        key: 'position',
143
+      },
144
+      {
145
+        title: '操作',
146
+        dataIndex: 'personId',
147
+        key: 'personId',
148
+        // eslint-disable-next-line no-nested-ternary
149
+        render: (_, record) => <>{ <Button type="danger" onClick={() => this.submitGm(record)}>确定</Button>}</>, },
150
+    ]
151
+    return (
152
+      <>
153
+        <Modal
154
+            title="分配置业顾问"
155
+            width={800}
156
+            destroyOnClose="true"
157
+            footer={null}
158
+            visible={this.state.visibleData.visible}
159
+            onCancel={(e) => this.handleCancel(e)}
160
+          >
161
+            <span>你正在为{this.props.visibleData.customerId.length}位公客分配置业顾问</span><br/><br/>
162
+            {this.props.visibleData.buildingId == null && <BuildSelect onChange={this.changBuilding.bind(this)} value={this.state.visibleData.buildingName} />}
163
+            <Table rowKey="BatchAssistConsultant" dataSource={this.state.dataSource.records} columns={columns} pagination={{pageSize: 5, total: this.state.dataSource.total, onChange: e => this.onChange(e) }} />
164
+          </Modal>
165
+      </>
166
+    );
167
+  }
168
+}
169
+
170
+export default ModalAttribution

+ 160
- 0
estateagents-admin-manager/src/pages/customer/customerlist/components/assistConsultant.jsx Ver fichero

@@ -0,0 +1,160 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Table, Avatar, Radio, Modal, Descriptions, notification } from 'antd';
3
+import moment from 'moment';
4
+import request from '../../../../utils/request';
5
+import apis from '../../../../services/apis';
6
+import Styles from '../style.less';
7
+import BuildSelect from '../../../../components/SelectButton/BuildSelect'
8
+
9
+
10
+const { Option } = Select;
11
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
12
+const { Meta } = Card;
13
+
14
+/**
15
+ * 分配置业顾问
16
+ *
17
+ * @param {*} props
18
+ * @returns
19
+ */
20
+class ModalAttribution extends React.Component {
21
+  constructor(props) {
22
+    super(props);
23
+    this.state = {
24
+       dataSource: { records: [] },
25
+       visibleData: { visible: false, customerId: '', buildingName: '' },
26
+    }
27
+  }
28
+
29
+  // 挂载之后
30
+  componentDidMount() {
31
+    // this.getList({ pageNumber: 1, pageSize: 5 })
32
+  }
33
+
34
+  componentDidUpdate(preProps, preState) {
35
+    console.log(this.props.visibleData)
36
+    if (this.props.visibleData.visible !== preState.visibleData.visible) {
37
+      this.getList({ pageNumber: 1, pageSize: 5, customerId: this.props.visibleData.customerId,buildingId:this.props.visibleData.buildingId })
38
+      this.setState({ visibleData: this.props.visibleData });
39
+    }
40
+  }
41
+
42
+  // 弹框确定按钮
43
+  // eslint-disable-next-line react/sort-comp
44
+  handleOk() {
45
+    this.props.onCancel()
46
+  }
47
+
48
+  // 弹框取消按钮
49
+  handleCancel() {
50
+    this.props.onCancel()
51
+  }
52
+
53
+  changBuilding(buildingId){
54
+    this.getUserList({ pageNumber: 1, pageSize: 5, buildingId: buildingId })
55
+    this.setState({ visibleData: { visible: this.props.visibleData.visible, customerId: this.props.visibleData.customerId, buildingName: buildingId } });
56
+  }
57
+
58
+  getUserList(params){
59
+    console.log('params: ', params)
60
+    if (params.buildingId === '' || params.buildingId === null || params.buildingId === undefined) {
61
+      return
62
+    }
63
+    // 网路请求
64
+    request({ ...apis.customer.buildingConsultant, params: { ...params } }).then(res => {
65
+      this.setState({ dataSource: res })
66
+    }).catch(err => {
67
+      
68
+    })
69
+  }
70
+
71
+  getList(params) {
72
+    // 网路请求
73
+    request({ ...apis.customer.buildingConsultant, params: { ...params } }).then(res => {
74
+      this.setState({ dataSource: res })
75
+    }).catch(err => {
76
+      
77
+    })
78
+  }
79
+
80
+  openNotificationWithIcon = (type, message) => {
81
+    notification[type]({
82
+      message,
83
+      description:
84
+        '',
85
+    });
86
+  };
87
+
88
+   // 分页
89
+  onChange(pageNum) {
90
+    this.getList({ pageNumber: pageNum, pageSize: 5, customerId: this.props.visibleData.customerId, buildingId: this.state.visibleData.buildingName ||this.props.visibleData.buildingId})
91
+  }
92
+
93
+  // 提交
94
+  submitGm(record) {
95
+    debugger
96
+    // 网路请求
97
+    request({ ...apis.customer.consultantAssist, urlData: { id: this.state.visibleData.customerId }, 
98
+      data: { userId: record.userId,buildingId:this.state.visibleData.buildingName  || this.props.visibleData.buildingId } }).then(res => {
99
+      // eslint-disable-next-line no-unused-expressions
100
+      
101
+      this.openNotificationWithIcon('success', '操作成功')
102
+      this.handleCancel()
103
+    }).catch(err => {
104
+      // eslint-disable-next-line no-unused-expressions
105
+    })
106
+  }
107
+
108
+  render() {
109
+    const columns = [
110
+      // {
111
+      //   title: '编号',
112
+      //   dataIndex: 'userId',
113
+      //   key: 'userId',
114
+      // },
115
+      {
116
+        title: '姓名',
117
+        dataIndex: 'userName',
118
+        key: 'userName',
119
+      },
120
+      {
121
+        title: '电话',
122
+        dataIndex: 'phone',
123
+        key: 'phone',
124
+      },
125
+      {
126
+        title: '部门',
127
+        dataIndex: 'department',
128
+        key: 'department',
129
+      },
130
+      {
131
+        title: '岗位',
132
+        dataIndex: 'position',
133
+        key: 'position',
134
+      },
135
+      {
136
+        title: '操作',
137
+        dataIndex: 'personId',
138
+        key: 'personId',
139
+        // eslint-disable-next-line no-nested-ternary
140
+        render: (_, record) => <>{ <Button type="danger" onClick={() => this.submitGm(record)}>确定</Button>}</>, },
141
+    ]
142
+    return (
143
+      <>
144
+        <Modal
145
+            title="分配置业顾问"
146
+            width={800}
147
+            destroyOnClose="true"
148
+            footer={null}
149
+            visible={this.state.visibleData.visible}
150
+            onCancel={(e) => this.handleCancel(e)}
151
+          >
152
+            {this.props.visibleData.buildingId == null && <BuildSelect  onChange={this.changBuilding.bind(this)} value={this.state.visibleData.buildingName} />}
153
+            <Table rowKey="assistConsultant" dataSource={this.state.dataSource.records} columns={columns} pagination={{pageSize: 5, total: this.state.dataSource.total, onChange: e => this.onChange(e) }} />
154
+          </Modal>
155
+      </>
156
+    );
157
+  }
158
+}
159
+
160
+export default ModalAttribution

+ 146
- 0
estateagents-admin-manager/src/pages/customer/customerlist/components/attribution.jsx Ver fichero

@@ -0,0 +1,146 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Table, Avatar, Radio, Modal, Descriptions, notification } from 'antd';
3
+import moment from 'moment';
4
+import request from '../../../../utils/request';
5
+import apis from '../../../../services/apis';
6
+import Styles from '../style.less';
7
+
8
+
9
+const { Option } = Select;
10
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
11
+const { Meta } = Card;
12
+
13
+/**
14
+ * 调整归属
15
+ *
16
+ * @param {*} props
17
+ * @returns
18
+ */
19
+class ModalAttribution extends React.Component {
20
+  constructor(props) {
21
+    super(props);
22
+    this.state = {
23
+       dataSource: { records: [] },
24
+       visibleData: { visible: false, customerId: '', realtyConsultant: '', buildingId: '' },
25
+    }
26
+  }
27
+
28
+  // 挂载之后
29
+  componentDidMount() {
30
+    // this.getList({ pageNumber: 1, pageSize: 5 })
31
+  }
32
+
33
+  componentDidUpdate(preProps, preState) {
34
+    console.log(this.props.visibleData)
35
+    if (this.props.visibleData.visible !== preState.visibleData.visible) {
36
+      this.getList({ pageNumber: 1, pageSize: 5, buildingId: this.props.visibleData.buildingId })
37
+      this.setState({ visibleData: this.props.visibleData });
38
+    }
39
+  }
40
+
41
+  // 弹框确定按钮
42
+  // eslint-disable-next-line react/sort-comp
43
+  handleOk() {
44
+    this.props.onCancel()
45
+  }
46
+
47
+  // 弹框取消按钮
48
+  handleCancel() {
49
+    this.props.onCancel()
50
+  }
51
+
52
+  getList(params) {
53
+    console.log('params: ', params)
54
+    if (params.buildingId === '' || params.buildingId === null || params.buildingId === undefined) {
55
+      return
56
+    }
57
+    // 网路请求
58
+    request({ ...apis.customer.buildingConsultant, params: { ...params } }).then(res => {
59
+      console.log('res',res);
60
+      this.setState({ dataSource: res })
61
+    }).catch(err => {
62
+      // eslint-disable-next-line no-unused-expressions
63
+      
64
+    })
65
+  }
66
+
67
+  openNotificationWithIcon = (type, message) => {
68
+    notification[type]({
69
+      message,
70
+      description:
71
+        '',
72
+    });
73
+  };
74
+
75
+   // 分页
76
+  onChange(pageNum) {
77
+    this.getList({ pageNumber: pageNum, pageSize: 5, buildingId: this.props.visibleData.buildingId })
78
+  }
79
+
80
+  // 提交
81
+  submitGm(record) {
82
+    // 网路请求
83
+    request({ ...apis.customer.recommendEdit, urlData: { id: this.state.visibleData.customerId }, data: { customerId: this.state.visibleData.customerId, realtyConsultant: record.userId } }).then(res => {
84
+      // eslint-disable-next-line no-unused-expressions
85
+      this.openNotificationWithIcon('success', '操作成功')
86
+      this.handleCancel()
87
+    }).catch(err => {
88
+      // eslint-disable-next-line no-unused-expressions
89
+      this.openNotificationWithIcon('error', err)
90
+    })
91
+  }
92
+
93
+  render() {
94
+    const columns = [
95
+      // {
96
+      //   title: '编号',
97
+      //   dataIndex: 'userId',
98
+      //   key: 'userId',
99
+      // },
100
+      {
101
+        title: '姓名',
102
+        dataIndex: 'userName',
103
+        key: 'userName',
104
+      },
105
+      {
106
+        title: '电话',
107
+        dataIndex: 'phone',
108
+        key: 'phone',
109
+      },
110
+      {
111
+        title: '部门',
112
+        dataIndex: 'department',
113
+        key: 'department',
114
+      },
115
+      {
116
+        title: '岗位',
117
+        dataIndex: 'position',
118
+        key: 'position',
119
+      },
120
+      {
121
+        title: '操作',
122
+        dataIndex: 'personId',
123
+        key: 'personId',
124
+        // eslint-disable-next-line no-nested-ternary
125
+        render: (_, record) => <>{ this.props.visibleData.realtyConsultant != record.userId && <Button type="danger" onClick={() => this.submitGm(record)}>确定</Button>}</>,
126
+      },
127
+    ]
128
+    return (
129
+      <>
130
+        <Modal
131
+            title="选择置业顾问"
132
+            width={800}
133
+            destroyOnClose="true"
134
+            footer={null}
135
+            visible={this.state.visibleData.visible}
136
+            // onOk={() => this.handleOk()}
137
+            onCancel={(e) => this.handleCancel(e)}
138
+          >
139
+            <Table rowKey="attribution" dataSource={this.state.dataSource.records} columns={columns} pagination={{ total: this.state.dataSource.total, pageSize: this.state.dataSource.size, onChange: e => this.onChange(e) }} />
140
+          </Modal>
141
+      </>
142
+    );
143
+  }
144
+}
145
+
146
+export default ModalAttribution

+ 81
- 0
estateagents-admin-manager/src/pages/customer/customerlist/components/changeStatus.jsx Ver fichero

@@ -0,0 +1,81 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Table, Avatar, Radio, Modal, Descriptions, notification } from 'antd';
3
+import moment from 'moment';
4
+import request from '../../../../utils/request';
5
+import apis from '../../../../services/apis';
6
+import Styles from '../style.less';
7
+
8
+class ChangeStatus extends React.Component {
9
+  constructor(props) {
10
+    super(props)
11
+    this.state = {
12
+      value: '',
13
+      visibleData: { visible: false, customerId: '' },
14
+    }
15
+  }
16
+
17
+  componentDidUpdate(preProps, preState) {
18
+    if (this.props.visibleData.customerId !== preState.visibleData.customerId) {
19
+      this.setState({ visibleData: { ...this.props.visibleData } })
20
+      this.setState({ value: this.props.visibleData.status })
21
+    }
22
+  }
23
+
24
+  // 弹框取消按钮
25
+  handleCancel() {
26
+    this.props.onCancel()
27
+  }
28
+
29
+  onChange = e => {
30
+    this.setState({
31
+      value: e.target.value,
32
+    });
33
+  };
34
+
35
+  openNotificationWithIcon = (type, message) => {
36
+    notification[type]({
37
+      message,
38
+      description:
39
+        '',
40
+    });
41
+  };
42
+
43
+  submitButton = e => {
44
+    // 网路请求
45
+    request({ ...apis.customer.recommendEdit, urlData: { id: this.state.visibleData.customerId }, data: { customerId: this.state.visibleData.customerId, status: this.state.value } }).then(res => {
46
+      // eslint-disable-next-line no-unused-expressions
47
+      this.openNotificationWithIcon('success', '操作成功')
48
+      this.handleCancel()
49
+    }).catch(err => {
50
+      // eslint-disable-next-line no-unused-expressions
51
+      this.openNotificationWithIcon('error', err)
52
+    })
53
+  }
54
+
55
+  render() {
56
+    return (
57
+      <>
58
+          <Modal
59
+            title="变更状态"
60
+            width={800}
61
+            destroyOnClose="true"
62
+            footer={null}
63
+            visible={this.state.visibleData.visible}
64
+            // onOk={() => this.handleOk()}
65
+            onCancel={(e) => this.handleCancel(e)}
66
+          >
67
+            <Radio.Group onChange={this.onChange} value={this.state.value}>
68
+              <Radio value={1}>客户报备</Radio>
69
+              <Radio value={2}>客户到访</Radio>
70
+              <Radio value={3}>客户认购</Radio>
71
+              <Radio value={4}>客户签约</Radio>
72
+            </Radio.Group>
73
+
74
+            <Button type="danger" onClick={this.submitButton}>确定</Button>
75
+          </Modal>
76
+      </>
77
+    )
78
+  }
79
+}
80
+
81
+export default ChangeStatus

+ 160
- 0
estateagents-admin-manager/src/pages/customer/customerlist/components/integralRecord.jsx Ver fichero

@@ -0,0 +1,160 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Table, Avatar, Radio, Modal, Descriptions, notification } from 'antd';
3
+import moment from 'moment';
4
+import request from '../../../../utils/request';
5
+import apis from '../../../../services/apis';
6
+import Styles from '../style.less';
7
+
8
+
9
+const { Option } = Select;
10
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
11
+const { Meta } = Card;
12
+
13
+/**
14
+ * 积分记录
15
+ *
16
+ * @param {*} props
17
+ * @returns
18
+ */
19
+class ModalIntegralRecord extends React.Component {
20
+  constructor(props) {
21
+    super(props);
22
+    this.state = {
23
+       dataSource: { result: { records: [] }, totalPoints: 0 },
24
+       visibleData: { visible: false, customerId: '' },
25
+    }
26
+  }
27
+
28
+  // 挂载之后
29
+  componentDidMount() {
30
+    this.getList({ pageNumber: 1, pageSize: 5 })
31
+  }
32
+
33
+  componentDidUpdate(preProps, preState) {
34
+    if (this.props.visibleData.customerId !== preState.visibleData.customerId) {
35
+      this.getList({ pageNumber: 1, pageSize: 5 })
36
+      this.setState({ visibleData: this.props.visibleData });
37
+    }
38
+  }
39
+
40
+  // 弹框确定按钮
41
+  // eslint-disable-next-line react/sort-comp
42
+  handleOk() {
43
+    this.props.onCancel()
44
+  }
45
+
46
+  // 弹框取消按钮
47
+  handleCancel() {
48
+    this.props.onCancel()
49
+  }
50
+
51
+  openNotificationWithIcon = (type, message) => {
52
+    notification[type]({
53
+      message,
54
+      description:
55
+        '',
56
+    });
57
+  }
58
+
59
+  getList(params) {
60
+    const { customerId } = this.state.visibleData
61
+    if (customerId === '' || customerId === undefined) {
62
+      return
63
+    }
64
+    // 网路请求
65
+    // 网路请求
66
+    request({ ...apis.customer.taPointsRecords, urlData: { id: customerId }, params: { ...params } }).then(res => {
67
+      this.setState({ dataSource: res })
68
+    }).catch(err => {
69
+      this.openNotificationWithIcon('error', err)
70
+    })
71
+  }
72
+
73
+   // 分页
74
+  onChange(pageNum) {
75
+    this.getList({ pageNumber: pageNum, pageSize: 5 })
76
+  }
77
+
78
+  // 积分类型
79
+  showChangeType(str) {
80
+    switch (str) {
81
+      case 'goods':
82
+        return '兑换商品'
83
+      case 'checkin':
84
+        return '签到'
85
+      case 'share-poster':
86
+        return '分享'
87
+      case 'signup-agent':
88
+        return '授权手机号'
89
+      case 'activity_checkin':
90
+        return '活动签到'
91
+      case 'document_verify':
92
+          return '资料审核'  
93
+      case 'recommend-customer':
94
+        return '推荐客户'
95
+        case 'group':
96
+        return '拼团'
97
+        case 'recommend-customer':
98
+        return '推荐客户'
99
+      default:
100
+        return '未知类型'
101
+    }
102
+  }
103
+
104
+  // 判断是否是 - 开头
105
+  subPoints(points) {
106
+    const subStr = points.toString().substring(0, 1)
107
+    if (subStr === '-') {
108
+      return true
109
+    }
110
+    return false
111
+  }
112
+
113
+// eslint-disable-next-line class-methods-use-this
114
+  render() {
115
+    const columns = [
116
+      {
117
+        title: '序号',
118
+        dataIndex: 'index',
119
+        key: 'index',
120
+        render: (text, record, index) => <span>{index + 1}</span>,
121
+        // render: (text, record, index) => <span>{(this.state.dataSource.result.total - this.state.dataSource.result.records.length) * 1 + index + 1}</span>,
122
+      },
123
+      {
124
+        title: '积分类型',
125
+        dataIndex: 'changeType',
126
+        key: 'changeType',
127
+        render: (_, record) => <span>{this.showChangeType(record.changeType) }</span>,
128
+      },
129
+      {
130
+        title: '积分变化',
131
+        dataIndex: 'pointsAmount',
132
+        key: 'pointsAmount',
133
+        // render: (pointsAmount, record) => { <span style={this.subPoints(pointsAmount) && {color: 'red'}}>{ pointsAmount }</span> },
134
+      },
135
+      {
136
+        title: '发生时间',
137
+        dataIndex: 'createDate',
138
+        key: 'createDate',
139
+        render: (createDate, records) => <span> {moment(createDate).format('YYYY-MM-DD')}</span>,
140
+      },
141
+    ]
142
+    return (
143
+      <>
144
+        <Modal
145
+            title={ '当前可用积分:' + (this.state.dataSource.totalPoints  || 0 )}
146
+            width={800}
147
+            destroyOnClose="true"
148
+            footer={null}
149
+            visible={this.state.visibleData.visible}
150
+            // onOk={() => this.handleOk()}
151
+            onCancel={e => this.handleCancel(e)}
152
+          >
153
+            <Table dataSource={this.state.dataSource.result.records} columns={columns} pagination={{pageSize: 5, total: this.state.dataSource.result.total, onChange: e => this.onChange(e) }} />
154
+          </Modal>
155
+      </>
156
+    );
157
+  }
158
+}
159
+
160
+export default ModalIntegralRecord

+ 146
- 0
estateagents-admin-manager/src/pages/customer/customerlist/components/recommend.jsx Ver fichero

@@ -0,0 +1,146 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Table, Avatar, Radio, Modal, Descriptions, notification } from 'antd';
3
+import moment from 'moment';
4
+import request from '../../../../utils/request';
5
+import apis from '../../../../services/apis';
6
+import Styles from '../style.less';
7
+
8
+
9
+const { Option } = Select;
10
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
11
+const { Meta } = Card;
12
+
13
+/**
14
+ * 推荐客户
15
+ *
16
+ * @param {*} props
17
+ * @returns
18
+ */
19
+class ModalRecommendRecord extends React.Component {
20
+  constructor(props) {
21
+    super(props);
22
+    this.state = {
23
+       dataSource: [],
24
+       visibleData: { visible: false, customerId: '' },
25
+    }
26
+  }
27
+
28
+  // 挂载之后
29
+  componentDidMount() {
30
+    this.getList({ pageNumber: 1, pageSize: 5 })
31
+  }
32
+
33
+  componentDidUpdate(preProps, preState) {
34
+    // console.log('this.props.visibleData', this.props.visibleData)
35
+    if (this.props.visibleData.customerId !== preState.visibleData.customerId) {
36
+      this.getList({ pageNumber: 1, pageSize: 5 })
37
+      this.setState({ visibleData: this.props.visibleData });
38
+    }
39
+  }
40
+
41
+  // 弹框确定按钮
42
+  // eslint-disable-next-line react/sort-comp
43
+  handleOk() {
44
+    this.props.onCancel()
45
+  }
46
+
47
+  // 弹框取消按钮
48
+  handleCancel() {
49
+    this.props.onCancel()
50
+  }
51
+
52
+  openNotificationWithIcon = (type, message) => {
53
+    notification[type]({
54
+      message,
55
+      description:
56
+        '',
57
+    });
58
+  }
59
+
60
+  getList(params) {
61
+    const { customerId } = this.state.visibleData
62
+    if (customerId === '' || customerId === undefined) {
63
+      return
64
+    }
65
+    console.log('customerId', customerId)
66
+    // 网路请求
67
+    // 网路请求
68
+    request({ ...apis.customer.recommendClient, urlData: { id: customerId }, params: { ...params } }).then(res => {
69
+      this.setState({ dataSource: res })
70
+    }).catch(err => {
71
+      this.openNotificationWithIcon('error', err)
72
+    })
73
+  }
74
+
75
+   // 分页
76
+  onChange(pageNum) {
77
+    this.getList({ pageNumber: pageNum, pageSize: 5 })
78
+  }
79
+
80
+  render() {
81
+    const columns = [
82
+      {
83
+        title: '头像',
84
+        // eslint-disable-next-line jsx-a11y/alt-text
85
+        render: (text, records) => <img src={records.picture} width={50} height={50} />,
86
+      },
87
+      {
88
+        title: '用户名',
89
+        dataIndex: 'name',
90
+        key: 'name',
91
+      },
92
+      {
93
+        title: '电话',
94
+        dataIndex: 'phone',
95
+        key: 'phone',
96
+      },
97
+      {
98
+        title: '性别',
99
+        dataIndex: 'sex',
100
+        key: 'sex',
101
+        render: (text, records) => <span>{records.sex === 1 ? '男' : '女'}</span>,
102
+      },
103
+      {
104
+        title: '意向项目',
105
+        dataIndex: 'intention',
106
+        key: 'intention',
107
+      },
108
+      {
109
+        title: '推荐时间',
110
+        dataIndex: 'createDate',
111
+        key: 'createDate',
112
+        render: (_, record) => <><span>{ record.createDate && moment(record.createDate).format('YYYY-MM-DD HH:mm:ss') }</span></>,
113
+      },
114
+      {
115
+        title: '状态',
116
+        // eslint-disable-next-line consistent-return
117
+        render: (text, records) => {
118
+          if (records.verifyStatus === 0) { return '未审核' }
119
+          if (records.verifyStatus === 1) {
120
+            if (records.reportRecommendStatus === 1) { return '报备' }
121
+            if (records.reportRecommendStatus === 2) { return '推荐' }
122
+           }
123
+          if (records.verifyStatus === 2) { return '审核不通过' }
124
+        },
125
+      },
126
+    ]
127
+    return (
128
+      <>
129
+        <Modal
130
+            title="推荐客户"
131
+            width={800}
132
+            destroyOnClose="true"
133
+            footer={null}
134
+            visible={this.state.visibleData.visible}
135
+            // onOk={() => this.handleOk()}
136
+            onCancel={(e) => this.handleCancel(e)}
137
+          >
138
+            {console.log('this.state.dataSource11111111111', this.state.dataSource.total)}
139
+            <Table dataSource={this.state.dataSource.records} rowKey="integralrecord" columns={columns} pagination={{ total: this.state.dataSource.total, pageSize: this.state.dataSource.size, onChange: e => this.onChange(e) }} />
140
+          </Modal>
141
+      </>
142
+    );
143
+  }
144
+}
145
+
146
+export default ModalRecommendRecord

+ 217
- 0
estateagents-admin-manager/src/pages/customer/customerlist/customerDetail.jsx Ver fichero

@@ -0,0 +1,217 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Table, Pagination, Button } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import styles from './style.less';
5
+import apis from '../../../services/apis';
6
+import request from '../../../utils/request';
7
+import moment from 'moment';
8
+import BuildSelect from '../../../components/SelectButton/BuildSelect'
9
+
10
+import router from 'umi/router';
11
+import Prompt from 'umi/prompt';
12
+
13
+function header(props) {
14
+  /**
15
+   * @param {*} props
16
+   * @returns
17
+   */
18
+  // eslint-disable-next-line react-hooks/rules-of-hooks
19
+  const [data, setData] = useState([{}])
20
+  const [tableData, setTableDataData] = useState([{}])
21
+  const [dataConsultant, setDataonsultant] = useState({})
22
+  const [intentionData, setIntentionData] = useState([])
23
+  const [buildingIdValue, setBuildingIdData] = useState()
24
+
25
+  // eslint-disable-next-line react-hooks/rules-of-hooks
26
+  useEffect(() => {
27
+    getById()
28
+    toLoadIntention()
29
+  }, [])
30
+
31
+  function toLoadIntention() {
32
+    const arr = []
33
+    // 意向值
34
+    for (let i = 0; i < intentionData.length; i++) {
35
+      const a = [].concat(
36
+        intentionData.concat([{
37
+          key: i,
38
+          name: `Edward King ${i}`,
39
+          age: 32,
40
+          address: `London, Park Lane no. ${i}`,
41
+        }]),
42
+      )
43
+      arr.push(a)
44
+    }
45
+    setIntentionData(arr)
46
+  }
47
+
48
+  // 查询
49
+  const { id } = props.location.query;
50
+  function getById(params) {
51
+    if (id === '' || id === undefined) {
52
+      return
53
+    }
54
+    // eslint-disable-next-line max-len
55
+    request({ ...apis.customer.CustomerRecommendGet, urlData: { id }, params: { ...params, pageNumber: 1, pageSize: 10 } }).then(res => {
56
+      setData(res)
57
+      if (res.visitRecords) {
58
+        setTableDataData(res.visitRecords)
59
+      }
60
+      setDataonsultant(res.geoInfo)
61
+      setIntentionData(res.intentions)
62
+    })
63
+  }
64
+  // 分页
65
+  function onChange(number) {
66
+    if (id === '' || id === undefined) {
67
+      return
68
+    }
69
+    // eslint-disable-next-line max-len
70
+    request({ ...apis.customer.CustomerRecommendGet, urlData: { id }, params: { pageNumber: number, pageSize: 10 } }).then(res => {
71
+      setData(res)
72
+      setTableDataData(res.visitRecords)
73
+      setDataonsultant(res.geoInfo)
74
+    })
75
+  }
76
+
77
+  function changBuilding(buildingId) {
78
+    setBuildingIdData(buildingId)
79
+    getById({ pageNumber: 1, pageSize: 10, buildingId: buildingId })
80
+  }
81
+
82
+  const columns = [
83
+    {
84
+      title: '访问事件',
85
+      dataIndex: 'activity',
86
+      key: 'activity',
87
+      align: 'center',
88
+    },
89
+    {
90
+      title: '访问内容',
91
+      dataIndex: 'activityName',
92
+      key: 'activityName',
93
+      align: 'center',
94
+    },
95
+    {
96
+      title: '访问时间',
97
+      dataIndex: 'visitTime',
98
+      key: 'visitTime',
99
+      align: 'center',
100
+      render: (_, record) => <span> {moment(record.visitTime).format('YYYY-MM-DD HH:mm:ss')}</span>,
101
+    },
102
+    {
103
+      title: '停留时间',
104
+      dataIndex: 'visitDuration',
105
+      key: 'visitDuration',
106
+      align: 'center',
107
+      render: (_, record) => <span>{record.visitDuration === null ? 0 : record.visitDuration}秒</span>,
108
+    },
109
+  ]
110
+  // 意向
111
+  const intention = [
112
+    {
113
+      title: <span styles={{ color: '#222', fontSize: '24px' }}>项目名称</span>,
114
+      dataIndex: 'name',
115
+      width: '64%',
116
+      render: (_, record) => <span>{record.buildingName}</span>,
117
+    },
118
+    {
119
+      title: <span styles={{ color: '#222', fontSize: '24px' }}>意向值</span>,
120
+      dataIndex: 'address',
121
+      render: (_, record) => <span >{record.intention}</span>,
122
+    },
123
+  ];
124
+  return (
125
+    <>
126
+      <div style={{ textAlign: 'right', marginBottom:'16px'}}>
127
+        <Button onClick={() => router.go(-1)}>返回</Button>
128
+      </div>
129
+
130
+      <div className={styles.cardBox}>
131
+        <div className={styles.rightBox}>
132
+          <p className={styles.tit}>客户信息</p>
133
+          <div className={styles.flexBox}>
134
+            <img className={styles.touxiang} src={data.picture && data.picture} />
135
+            <div className={styles.right}>
136
+              <p className={styles.rightItem}>用户名称:{data.name}</p>
137
+              <p className={styles.rightItem}>手机号码:{data.phone}</p>
138
+              <p className={styles.rightItem}>首次访问时间:{data.visitTime && moment(data.visitTime).format('YYYY-MM-DD')}</p>
139
+            </div>
140
+            <div className={styles.Centered}>
141
+              <p>访问时长:{data.duration}秒</p>
142
+              <p>访问次数:{data.visitTimes}次</p>
143
+              <p className={styles.rightItem}>客户描述:{data.describe}</p>
144
+              {/* <p>预约人数:{ data.visiteNum }</p> */}
145
+            </div>
146
+            <div className={styles.rightCentered}>
147
+              <p >需求类型:{data.demandType}</p>
148
+              <p >价格区间:{data.priceRange}</p>
149
+              <p >物业类型:{data.realtyManageType}</p>
150
+              {/* <p>预约人数:{ data.visiteNum }</p> */}
151
+            </div>
152
+            {/* <p className={styles.rightItem}>预约到访时间:{data.appointmentTime && moment(data.appointmentTime).format('YYYY-MM-DD') }</p> */}
153
+            <div className={styles.rightInfo}>
154
+              <p className={styles.rightItem}>国家:{dataConsultant && dataConsultant.country}</p>
155
+              <p className={styles.rightItem}>省份:{dataConsultant && dataConsultant.provience}</p>
156
+              <p className={styles.rightItem}>城市:{dataConsultant && dataConsultant.city}</p>
157
+              <p className={styles.rightItem}>来源渠道:{data.personFrom ? data.personFrom : "其他"}</p>
158
+              {/* <p className={styles.rightItem}>详细信息:</p> */}
159
+              {/* <p className={styles.rightItem}>意向项目:{data.intention }</p> */}
160
+              {/* <p className={styles.rightItem}>客户说明:{ data.verifyRemark }</p> */}
161
+            </div>
162
+          </div>
163
+        </div>
164
+      </div>
165
+      <br></br>
166
+      <div className={styles.cardBox}>
167
+        <div className={styles.rightBoxCentre}>
168
+          <p className={styles.tit}>置业顾问信息</p>
169
+          <div>
170
+            <img className={styles.touxiangphoto} src={data.consultant && data.consultant.photo} />
171
+            <p >{data.consultant && data.consultant.userName}</p>
172
+          </div>
173
+          <div className={styles.rightphone}>
174
+            {/* <p className={styles.infoItem}>姓名:{ data.consultant && data.consultant.name }</p>
175
+          <p className={styles.infoItem}>部门:{ data.consultant && data.consultant.department }</p> */}
176
+            <p className={styles.infoItem}>号码:{data.consultant && data.consultant.phone} </p>
177
+            <p className={styles.infoItem}>岗位:{data.consultant && data.consultant.position}</p>
178
+          </div>
179
+          <div className={styles.left}>
180
+            <p className={styles.infoItem}>公司:{data.consultant && data.consultant.orgName} </p>
181
+            <p className={styles.infoItem}>
182
+              所属项目:
183
+            {
184
+                data.consultant && data.consultant.projects.map((item, _) => <span>{item}</span>)
185
+              }
186
+            </p>
187
+          </div>
188
+        </div>
189
+        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
190
+        <div className={styles.leftBoxCentre}>
191
+          {/* <div className={styles.tit}>
192
+                <span>项目名称</span>
193
+                <span style={{ marginLeft: '50%' }}>意向值</span>
194
+          </div> */}
195
+          {/* <img className={styles.touxiang} src={ data.picture && data.picture } /> */}
196
+          {/* <div className={styles.infoItem}> */}
197
+          <Table bordered={false} columnWidth={10} columns={intention} dataSource={intentionData} pagination={false} scroll={intentionData && intentionData.length >= 3 ? { y: 240 } : false} width={500} />
198
+          {/* </div> */}
199
+        </div>
200
+
201
+      </div>
202
+      <div className={styles.recordBox}>
203
+        <p className={styles.tableName}>访问记录</p>
204
+        <BuildSelect onChange={changBuilding} value={buildingIdValue} />
205
+        <Table dataSource={tableData.records} columns={columns} style={{ marginTop: '15px' }} pagination={{ pageSize: 10, total: tableData.total, onChange }} />
206
+        {/* <Pagination showQuickJumper defaultCurrent={1} total={data.records} onChange={e => changePageNum(e)} current={data.visitRecords.total}/> */}
207
+      </div>
208
+      <Prompt message={location =>
209
+        location.pathname.startsWith("/customer/customerlist")
210
+          ? true
211
+          : (localStorage.removeItem("priPageParams"), localStorage.removeItem("pubPageParams"), localStorage.removeItem("state"))} />
212
+    </>
213
+  )
214
+}
215
+const WrappedHeader = Form.create({ name: 'header' })(header);
216
+
217
+export default WrappedHeader

+ 786
- 0
estateagents-admin-manager/src/pages/customer/customerlist/index.jsx Ver fichero

@@ -0,0 +1,786 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Table, Avatar, Radio, Modal, Descriptions, message } from 'antd';
3
+import moment from 'moment';
4
+import request from '../../../utils/request';
5
+import apis from '../../../services/apis';
6
+import Styles from './style.less';
7
+import router from 'umi/router';
8
+import withActions from '@/components/ActionList';
9
+import Attribution from './components/attribution'
10
+import AssistConsultant from './components/assistConsultant'
11
+import BatchAssistConsultant from './components/BatchAssistConsultant'
12
+import IntegralRecord from './components/integralRecord'
13
+import ModalRecommendRecord from './components/recommend'
14
+import ChangeStatus from './components/changeStatus'
15
+import BuildSelect from '../../../components/SelectButton/BuildSelect'
16
+import AuthButton from '@/components/AuthButton';
17
+import Navigate from '@/components/Navigate';
18
+import WxDictSelect from '@/components/SelectButton/WxDictSelect';
19
+import Prompt from 'umi/prompt';
20
+import EditIcon from '@/components/EditIcon';
21
+
22
+
23
+const { Option } = Select;
24
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
25
+const { Meta } = Card;
26
+
27
+/**
28
+ *
29
+ *
30
+ * @param {*} props
31
+ * @returns
32
+ */
33
+function body(props) {
34
+  const { getFieldDecorator, getFieldsValue } = props.form
35
+
36
+  // eslint-disable-next-line react-hooks/rules-of-hooks
37
+  const [dataSource, setDataSource] = useState({ records: [] })
38
+  // eslint-disable-next-line react-hooks/rules-of-hooks
39
+  const [dataPub, setDataPub] = useState({ records: [] })
40
+  // 默认私客
41
+  // eslint-disable-next-line react-hooks/rules-of-hooks
42
+  const [customerType, setCustomerType] = useState('private')
43
+
44
+  // 调整归属 ============  start
45
+  // eslint-disable-next-line react-hooks/rules-of-hooks
46
+  const [gVisibleData, setGVisibleData] = useState({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
47
+  // 调整归属 ============= end
48
+
49
+  // 积分记录 ============  start
50
+  // eslint-disable-next-line react-hooks/rules-of-hooks
51
+  const [recordVisibleData, setRecordVisibleData] = useState({ visible: false, customerId: '' })
52
+  // 积分记录 ============= end
53
+
54
+  // 变更状态 ============  start
55
+  // eslint-disable-next-line react-hooks/rules-of-hooks
56
+  const [statusVisibleData, setStatusVisibleData] = useState({ visible: false, customerId: '', status: '' })
57
+  // 变更状态 ============= end
58
+
59
+  // 推荐客户
60
+  const [recommendVisibleData, setRecommendVisibleData] = useState({ visible: false, customerId: '' })
61
+
62
+  const [assistVisibleData, setAssistVisibleData] = useState({ visible: false, customerId: '', buildingId: '' })
63
+
64
+  const [loadingStatus, setLoadingStatus] = useState(false)
65
+
66
+  // 选中的公客信息
67
+  const [personInfo, setPersonInfo] = useState([])
68
+
69
+  const [batchAssistVisibleData, setBatchAssistVisibleData] = useState({ visible: false, customerId: [], buildingId: '' })
70
+
71
+  const [currentSelectedRows, setSelectedRows] = useState([])
72
+
73
+  const [selectedRowKeys, setSelectedRowKeys] = useState([])
74
+
75
+  // eslint-disable-next-line react-hooks/rules-of-hooks
76
+  useEffect(() => {
77
+    // localStorage.setItem("state", JSON.stringify({ value }))
78
+    if (localStorage.getItem("state")) {
79
+      console.log(localStorage.getItem("state"), 'state')
80
+      if (JSON.parse(localStorage.getItem("state")) == 'private') {
81
+        const localStorageValue = JSON.parse(localStorage.getItem('priPageParams'))
82
+        localStorageValue.startCreateDate = localStorageDate(localStorageValue.startCreateDate)
83
+        localStorageValue.endCreateDate = localStorageDate(localStorageValue.endCreateDate)
84
+        props.form.setFieldsValue(localStorageValue);
85
+        getList({ pageNumber: 1, pageSize: 10, ...JSON.parse(localStorage.getItem("priPageParams")) })
86
+      } else {
87
+        setCustomerType('public')
88
+        const localStorageValue = JSON.parse(localStorage.getItem("pubPageParams"))
89
+        localStorageValue.startCreateDate = localStorageDate(localStorageValue.startCreateDate)
90
+        localStorageValue.endCreateDate = localStorageDate(localStorageValue.endCreateDate)
91
+        props.form.setFieldsValue(localStorageValue);
92
+        getList({ pageNumber: 1, pageSize: 10, ...JSON.parse(localStorage.getItem("pubPageParams")) })
93
+      }
94
+
95
+    } else {
96
+      localStorage.setItem("priPageParams", JSON.stringify({ pageNumber: 1, pageSize: 10, customerType }))
97
+      getList({ pageNumber: 1, pageSize: 10, customerType })
98
+    }
99
+  }, [])
100
+
101
+  function getList(params) {
102
+    // 网路请求
103
+    if (params.startCreateDate) {
104
+      params.startCreateDate = moment(params.startCreateDate).format('YYYY-MM-DD HH:mm:ss');
105
+    }
106
+    if (params.endCreateDate) {
107
+      params.endCreateDate = moment(params.endCreateDate).format('YYYY-MM-DD HH:mm:ss');
108
+    }
109
+    request({ ...apis.customer.customerRecommend, params: { ...params } }).then(res => {
110
+      if (params.customerType === 'private') {
111
+        setDataSource(res)
112
+      } else {
113
+        setDataPub(res)
114
+      }
115
+    }).catch(err => {
116
+      // eslint-disable-next-line no-unused-expressions
117
+      <Alert
118
+        style={{
119
+          marginBottom: 24,
120
+        }}
121
+        message={err}
122
+        type="error"
123
+        showIcon
124
+      />
125
+    })
126
+  }
127
+
128
+  function displayNone() {
129
+    setRecordVisibleData({ visible: false, customerId: '' })
130
+    setGVisibleData({ visible: false, customerId: '', realtyConsultant: '' })
131
+    setStatusVisibleData({ visible: false, customerId: '', status: '' })
132
+    setRecommendVisibleData({ visible: false, customerId: '' })
133
+  }
134
+
135
+  // 提交事件
136
+  function handleSubmit(e) {
137
+    displayNone()
138
+
139
+    setPersonInfo([])
140
+    setSelectedRowKeys([])
141
+
142
+    e.preventDefault();
143
+    props.form.validateFields((err, values) => {
144
+      if (!err) {
145
+        if (values.startCreateDate) {
146
+          values.startCreateDate = moment(values.startCreateDate).format('YYYY-MM-DD HH:mm:ss');
147
+        }
148
+        if (values.endCreateDate) {
149
+          values.endCreateDate = moment(values.endCreateDate).format('YYYY-MM-DD HH:mm:ss');
150
+        }
151
+        if (customerType === 'private') {
152
+          localStorage.setItem("priPageParams", JSON.stringify({ customerType: 'private', ...values }))
153
+          getList(JSON.parse(localStorage.getItem("priPageParams")))
154
+        } else {
155
+          localStorage.setItem("pubPageParams", JSON.stringify({ customerType: 'public', ...values }))
156
+          getList(JSON.parse(localStorage.getItem("pubPageParams")))
157
+        }
158
+        // getList({ pageNum: 1, pageSize: 10, customerType, ...values })
159
+
160
+
161
+      }
162
+    });
163
+  }
164
+
165
+  // Change 事件
166
+  function handleSelectChange(e) {
167
+    // eslint-disable-next-line no-console
168
+    console.log(e)
169
+  }
170
+
171
+  const localStorageDate = (date) => date ? moment(date) : ''
172
+
173
+  // 分页
174
+  function onChange(pageNum) {
175
+    // eslint-disable-next-line react-hooks/rules-of-hooks
176
+    props.form.validateFields((err, values) => {
177
+      if (!err) {
178
+        localStorage.setItem("state", JSON.stringify(customerType))
179
+        if (customerType === 'private') {
180
+          localStorage.setItem("priPageParams", JSON.stringify({ pageNumber: pageNum, pageSize: 10, customerType: 'private', ...props.form.getFieldsValue() }))
181
+          getList(JSON.parse(localStorage.getItem("priPageParams")))
182
+        } else {
183
+          localStorage.setItem("pubPageParams", JSON.stringify({ pageNumber: pageNum, pageSize: 10, customerType: 'public', ...props.form.getFieldsValue() }))
184
+          getList(JSON.parse(localStorage.getItem("pubPageParams")))
185
+        }
186
+
187
+
188
+      }
189
+    });
190
+  }
191
+
192
+  // 私客/公客切换
193
+  function radioButtonHandleSizeChange(e) {
194
+
195
+    displayNone()
196
+
197
+    props.form.resetFields();
198
+    const { value } = e.target
199
+    setCustomerType(value)
200
+    localStorage.setItem("state", JSON.stringify(value))
201
+    if (value === 'private') {
202
+      if (localStorage.getItem("priPageParams")) {
203
+        const localStorageValue = JSON.parse(localStorage.getItem("priPageParams"))
204
+        localStorageValue.startCreateDate = localStorageDate(localStorageValue.startCreateDate)
205
+        localStorageValue.endCreateDate = localStorageDate(localStorageValue.endCreateDate)
206
+        props.form.setFieldsValue(localStorageValue);
207
+        getList(JSON.parse(localStorage.getItem("priPageParams")))
208
+      } else {
209
+        localStorage.setItem("priPageParams", JSON.stringify({ pageNumber: 1, pageSize: 10, customerType: value }))
210
+        getList({ pageNumber: 1, pageSize: 10, customerType: value })
211
+      }
212
+
213
+    } else {
214
+
215
+      if (localStorage.getItem("pubPageParams")) {
216
+        const localStorageValue = JSON.parse(localStorage.getItem("pubPageParams"))
217
+        localStorageValue.startCreateDate = localStorageDate(localStorageValue.startCreateDate)
218
+        localStorageValue.endCreateDate = localStorageDate(localStorageValue.endCreateDate)
219
+        props.form.setFieldsValue(localStorageValue);
220
+
221
+        getList({ pageNumber: 1, pageSize: 10, customerType, ...JSON.parse(localStorage.getItem("pubPageParams")) })
222
+      } else {
223
+        localStorage.setItem("pubPageParams", JSON.stringify({ pageNumber: 1, pageSize: 10, customerType: 'public' }))
224
+        getList({ pageNumber: 1, pageSize: 10, customerType: 'public' })
225
+      }
226
+    }
227
+
228
+    //setColumns(value === 'private' ? privateColumns : publicColumns)
229
+
230
+  }
231
+
232
+  function handleReset() {
233
+    props.form.resetFields();
234
+    if (customerType === 'private') {
235
+      localStorage.setItem("priPageParams", JSON.stringify({ pageNumber: 1, pageSize: 10, customerType: 'private' }));
236
+      getList(JSON.parse(localStorage.getItem("priPageParams")))
237
+    } else {
238
+      localStorage.setItem("pubPageParams", JSON.stringify({ pageNumber: 1, pageSize: 10, customerType: 'public' }))
239
+      getList(JSON.parse(localStorage.getItem("pubPageParams")))
240
+    }
241
+
242
+  }
243
+
244
+
245
+  // 这里有个 Bug, 就是 Modal 弹框,会联动出现, 比如 我点击 调整归属的Model弹框, 那么 积分记录的Model弹框莫名其妙的也显示了
246
+  // 所有这里临时解决方法是,弹出一个Modal对话框的时候,把其他的对话框给隐藏
247
+
248
+  function showGM(record) {
249
+    setGVisibleData({ visible: true, customerId: record.customerId, realtyConsultant: record.realtyConsultant, buildingId: record.buildingId })
250
+    setRecordVisibleData({ visible: false, customerId: '' })
251
+    setStatusVisibleData({ visible: false, customerId: '' })
252
+    setRecommendVisibleData({ visible: false, customerId: '' })
253
+    setBatchAssistVisibleData({ visible: false, customerId: '', buildingId: '' })
254
+  }
255
+
256
+  function showRecord(record) {
257
+    setRecordVisibleData({ visible: true, customerId: record.personId })
258
+    setGVisibleData({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
259
+    setStatusVisibleData({ visible: false, customerId: '' })
260
+    setRecommendVisibleData({ visible: false, customerId: '' })
261
+    setBatchAssistVisibleData({ visible: false, customerId: '', buildingId: '' })
262
+  }
263
+
264
+  function showStatus(record) {
265
+    setRecordVisibleData({ visible: false, customerId: '' })
266
+    setGVisibleData({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
267
+    setRecommendVisibleData({ visible: false, customerId: '' })
268
+    setStatusVisibleData({ visible: true, customerId: record.customerId, status: record.status })
269
+    setBatchAssistVisibleData({ visible: false, customerId: '', buildingId: '' })
270
+  }
271
+
272
+  // 推荐客户
273
+  function showRecommend(personId) {
274
+    setRecordVisibleData({ visible: false, customerId: '' })
275
+    setGVisibleData({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
276
+    setStatusVisibleData({ visible: false, customerId: '', status: '' })
277
+    setRecommendVisibleData({ visible: true, customerId: personId })
278
+    setBatchAssistVisibleData({ visible: false, customerId: '' })
279
+  }
280
+
281
+  //分配置业顾问
282
+  function assistConsultant(personId, buildingId) {
283
+    setGVisibleData({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
284
+    setRecordVisibleData({ visible: false, customerId: '' })
285
+    setStatusVisibleData({ visible: false, customerId: '' })
286
+    setRecommendVisibleData({ visible: false, customerId: '' })
287
+    setAssistVisibleData({ visible: true, customerId: personId, buildingId: buildingId })
288
+    setBatchAssistVisibleData({ visible: false, customerId: '', buildingId: '' })
289
+  }
290
+
291
+  function batchAssistConsultant() {
292
+    console.log(personInfo, 'personInfo')
293
+    console.log(personInfo.length)
294
+    if (personInfo.length <= 0) {
295
+      return message.info('请至少选择一条数据');
296
+    }
297
+
298
+    const compareSet = new Set();
299
+    personInfo.filter(record => {
300
+      compareSet.add(record.buildingName)
301
+    })
302
+
303
+    if (compareSet.size != 1) {
304
+      return message.info('选中的公客存在于不同项目中,请分开进行分配置业顾问操作');
305
+    }
306
+
307
+    // const newSelectedRows = personInfo.filter()  
308
+
309
+    // console.log(newSelectedRows,'newSelectedRows')
310
+
311
+    setGVisibleData({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
312
+    setRecordVisibleData({ visible: false, customerId: '' })
313
+    setStatusVisibleData({ visible: false, customerId: '' })
314
+    setRecommendVisibleData({ visible: false, customerId: '' })
315
+    setAssistVisibleData({ visible: false, customerId: '', buildingId: '' })
316
+    setBatchAssistVisibleData({ visible: true, customerId: personInfo, buildingId: personInfo[0].buildingId })
317
+  }
318
+
319
+  function toCustomerDateil(record) {
320
+    router.push({
321
+      pathname: '/customer/customerlist/customerDetail',
322
+      query: {
323
+        id: record.customerId,
324
+      },
325
+    });
326
+  }
327
+  // 私客详情
328
+  function publicCustomerDetail(record) {
329
+    router.push({
330
+      pathname: '/customer/customerlist/publicCustomerDetail',
331
+      query: {
332
+        id: record.personId,
333
+      },
334
+    });
335
+  }
336
+
337
+  function exportCustomer() {
338
+    setLoadingStatus(true)
339
+    const fieldsValue = getFieldsValue()
340
+    if (fieldsValue.startCreateDate) {
341
+      fieldsValue.startCreateDate = moment(fieldsValue.startCreateDate).format('YYYY-MM-DD HH:mm:ss');
342
+    }
343
+    if (fieldsValue.endCreateDate) {
344
+      fieldsValue.endCreateDate = moment(fieldsValue.endCreateDate).format('YYYY-MM-DD HH:mm:ss');
345
+    }
346
+    request({ ...apis.customer.customerRecommendExport, responseType: 'blob', params: { ...fieldsValue, customerType } })
347
+      .then(response => {
348
+        download(response)
349
+        setLoadingStatus(false)
350
+      }).catch(error => {
351
+        message.err('连接超时');
352
+        setLoadingStatus(false)
353
+      })
354
+  }
355
+
356
+  function download(data) {
357
+    if (!data) {
358
+      return
359
+    }
360
+    const url = window.URL.createObjectURL(new Blob([data]))
361
+    const link = document.createElement('a')
362
+    link.style.display = 'none'
363
+    link.href = url
364
+    link.setAttribute('download', '客户列表.xlsx')
365
+    document.body.append(link)
366
+    link.click()
367
+  }
368
+
369
+  // 关闭调整归属的窗口
370
+  function closeAttribution() {
371
+    setGVisibleData({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
372
+    if (customerType === 'private') {
373
+      getList(JSON.parse(localStorage.getItem('priPageParams')))
374
+    } else {
375
+      getList(JSON.parse(localStorage.getItem('pubPageParams')))
376
+    }
377
+  }
378
+  // 回调关闭所有弹框
379
+  function closeAll() {
380
+    setRecordVisibleData({ visible: false, customerId: '' })
381
+    setGVisibleData({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
382
+    setStatusVisibleData({ visible: false, customerId: '', status: '' })
383
+    setRecommendVisibleData({ visible: false, customerId: '' })
384
+    setAssistVisibleData({ visible: false, customerId: '', buildingId: '' })
385
+    setBatchAssistVisibleData({ visible: false, customerId: '' })
386
+    if (customerType === 'private') {
387
+
388
+      getList(JSON.parse(localStorage.getItem("priPageParams")))
389
+    } else {
390
+
391
+      getList(JSON.parse(localStorage.getItem("pubPageParams")))
392
+    }
393
+    // getList({ pageNum: 1, pageSize: 10, customerType, ...props.form.getFieldsValue() })
394
+  }
395
+
396
+  const rowSelection = {
397
+    selectedRowKeys,
398
+    onChange: (selectedRowKeys, selectedRows) => {
399
+      console.log('selectedRowKeys:', selectedRowKeys, 'selectedRows: ', selectedRows);
400
+      setSelectedRowKeys(selectedRowKeys)
401
+      const newSelectedRows = personInfo.filter(x => !selectedRows.some(y => x.customerId === y.customerId))     // 去重
402
+        .concat(selectedRows)                                                                 // 新增选择
403
+        .filter(x => selectedRowKeys.some(y => y === x.customerId))                             // 去掉未选的数据
404
+
405
+      // setSelectedRows(newSelectedRows)
406
+      console.log(newSelectedRows, "33333333333333333333")
407
+      setPersonInfo(newSelectedRows)
408
+    },
409
+  };
410
+
411
+  const publicColumns = [
412
+    {
413
+      title: '头像',
414
+      dataIndex: 'picture',
415
+      key: 'picture',
416
+      align: 'center',
417
+      width: '10%',
418
+      // render: (_, record) => <Avatar shape="square" style={{ color: 'blue', cursor: 'pointer' }} onClick={() => publicCustomerDetail(record)} src={customerType === 'private' ? record.picture : record.avatarurl} size={64} icon="user" />,
419
+      render: (_, record) => <Avatar shape="square" style={{ color: 'blue', cursor: 'pointer' }} onClick={() => publicCustomerDetail(record)} src={record.picture} size={64} icon="user" />,
420
+    },
421
+    {
422
+      title: '姓名',
423
+      dataIndex: 'name',
424
+      key: 'name',
425
+      align: 'center',
426
+      width: '10%',
427
+      // eslint-disable-next-line no-nested-ternary
428
+      render: (_, record) => <><Navigate onClick={() => publicCustomerDetail(record)}>{record.name || record.nickname}</Navigate></>,
429
+    },
430
+    {
431
+      title: '电话',
432
+      dataIndex: 'phone',
433
+      key: 'phone',
434
+      align: 'center',
435
+      width: '15%',
436
+    },
437
+    {
438
+      title: '是否归属项目',
439
+      dataIndex: '',
440
+      key: '',
441
+      align: 'center',
442
+      width: '10%',
443
+      render: (_, record) => <><span>{record.buildingId != null ? '是' : '否'}</span></>,
444
+    },
445
+    {
446
+      title: '归属项目',
447
+      dataIndex: 'buildingName',
448
+      key: 'buildingName',
449
+      align: 'center',
450
+      width: '15%',
451
+    },
452
+    {
453
+      title: '推广人员',
454
+      dataIndex: 'sharePersonName',
455
+      key: 'sharePersonName',
456
+      align: 'center',
457
+      width: '10%',
458
+    },
459
+    {
460
+      title: '性别',
461
+      dataIndex: 'sex',
462
+      key: 'sex',
463
+      align: 'center',
464
+      width: '10%',
465
+      // eslint-disable-next-line no-nested-ternary
466
+      render: (_, record) => <><span>{record.sex === 1 ? '男' : record.sex === 2 ? '女' : '未知'}</span></>,
467
+    },
468
+    {
469
+      title: '操作',
470
+      dataIndex: 'customerId',
471
+      key: 'customerId',
472
+      align: 'center',
473
+      width: '20%',
474
+      render: withActions((text, record) => [
475
+        <EditIcon color="#FF4A4A" text="查看详情" onClick={() => publicCustomerDetail(record)} />,
476
+        <AuthButton name="admin.customer.recommend" noRight={null}>
477
+          <Button className={customerType === 'private' ? Styles.displayS : Styles.text} type="link" onClick={() => showRecommend(record.personId)}>推荐客户</Button>
478
+        </AuthButton>,
479
+        <AuthButton name="admin.customer.assign" noRight={null}>
480
+          <Button className={customerType === 'private' ? Styles.displayS : Styles.text} type="link" onClick={() => assistConsultant(record.customerId, record.buildingId)}>分配置业顾问</Button>
481
+        </AuthButton>,
482
+        <AuthButton name="admin.mine.taPointsRecords.point.record" noRight={null}>
483
+          <Button className={Styles.text} type="link" onClick={() => showRecord(record)}>积分记录</Button>
484
+        </AuthButton>
485
+      ]),
486
+      // render: (_, record) => (
487
+      //   <>
488
+      //     {/* <AuthButton name="admin.customer.public.detail" noRight={null}>
489
+      //       <Button className={customerType === 'private' ? Styles.displayS : Styles.text } type="link" onClick={() => publicCustomerDetail(record)}>查看详情</Button>
490
+      //     </AuthButton>
491
+      //     &nbsp;&nbsp; */}
492
+      //     <AuthButton name="admin.customer.recommend" noRight={null}>
493
+      //       <Button className={customerType === 'private' ? Styles.displayS : Styles.text} type="link" onClick={() => showRecommend(record.personId)}>推荐客户</Button>
494
+      //     </AuthButton>
495
+      //     <AuthButton name="admin.customer.assign" noRight={null}>
496
+      //       <Button className={customerType === 'private' ? Styles.displayS : Styles.text} type="link" onClick={() => assistConsultant(record.customerId, record.buildingId)}>分配置业顾问</Button>
497
+      //     </AuthButton>
498
+      //     <AuthButton name="admin.mine.taPointsRecords.point.record" noRight={null}>
499
+      //       <Button className={Styles.text} type="link" onClick={() => showRecord(record)}>积分记录</Button>
500
+      //     </AuthButton>
501
+      //   </>
502
+      // ),
503
+    },
504
+  ]
505
+
506
+  const privateColumns = [
507
+    {
508
+      title: '头像',
509
+      dataIndex: 'picture',
510
+      key: 'picture',
511
+      align: 'center',
512
+      width: '10%',
513
+      render: (_, record) => <Avatar shape="square" style={{ color: 'blue', cursor: 'pointer' }} onClick={() => toCustomerDateil(record)} src={customerType === 'private' ? record.picture : record.avatarurl} size={64} icon="user" />,
514
+    },
515
+    {
516
+      title: '姓名',
517
+      dataIndex: 'name',
518
+      key: 'name',
519
+      align: 'center',
520
+      width: '10%',
521
+      // eslint-disable-next-line no-nested-ternary
522
+      render: (_, record) => <><Navigate onClick={() => toCustomerDateil(record)}>{customerType === 'private' ? record.name : record.nickname}</Navigate></>,
523
+    },
524
+    {
525
+      title: '电话',
526
+      dataIndex: 'phone',
527
+      key: 'phone',
528
+      align: 'center',
529
+      width: '10%',
530
+    },
531
+    {
532
+      title: '性别',
533
+      dataIndex: 'sex',
534
+      key: 'sex',
535
+      align: 'center',
536
+      width: '10%',
537
+      // eslint-disable-next-line no-nested-ternary
538
+      render: (_, record) => <><span>{record.sex === 1 ? '男' : record.sex === 2 ? '女' : '未知'}</span></>,
539
+    },
540
+    {
541
+      title: '置业顾问',
542
+      dataIndex: 'consultantName',
543
+      key: 'consultantName',
544
+      align: 'center',
545
+      width: '10%',
546
+      // eslint-disable-next-line no-nested-ternary
547
+      render: (_, record) => (
548
+        <>
549
+          <span>{record.consultantName}</span>
550
+          <br />
551
+          <span>{record.consultTel}</span>
552
+        </>
553
+      ),
554
+    },
555
+    {
556
+      title: '归属项目',
557
+      dataIndex: 'buildingName',
558
+      key: 'buildingName',
559
+      align: 'center',
560
+      width: '10%',
561
+    },
562
+    {
563
+      title: '推广人员',
564
+      dataIndex: 'sharePersonName',
565
+      key: 'sharePersonName',
566
+      align: 'center',
567
+      width: '10%',
568
+    },
569
+    {
570
+      title: '客户状态',
571
+      dataIndex: 'reportRecommendStatus',
572
+      key: 'reportRecommendStatus',
573
+      align: 'center',
574
+      width: '10%',
575
+      // eslint-disable-next-line no-nested-ternary
576
+      render: (text, records) => {
577
+        if (records.status === 1) { return '报备' }
578
+        if (records.status === 2) { return '到访' }
579
+        if (records.status === 3) { return '认购' }
580
+        if (records.status === 4) { return '签约' }
581
+      },
582
+    },
583
+    {
584
+      title: '操作',
585
+      dataIndex: 'customerId',
586
+      key: 'customerId',
587
+      align: 'center',
588
+      width: '20%',
589
+      render: withActions((text, record) => [
590
+        <EditIcon color="#FF4A4A" text="查看详情" onClick={() => toCustomerDateil(record)} />,
591
+        <AuthButton name="admin.customer.recommend.edit.id.put" noRight={null}>
592
+          <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => showStatus(record)}>变更状态</Button>
593
+        </AuthButton>,
594
+
595
+        <AuthButton name="admin.customer.recommend.belong" noRight={null}>
596
+          <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => showGM(record)}>调整归属</Button>
597
+        </AuthButton>,
598
+
599
+        <AuthButton name="admin.mine.taPointsRecords.point.record" noRight={null}>
600
+          <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => showRecord(record)}>积分记录</Button>
601
+        </AuthButton>,
602
+
603
+        <AuthButton name="admin.mine.taPointsRecords.id.get" noRight={null}>
604
+          <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => showRecommend(record.personId)}>推荐客户</Button>
605
+        </AuthButton>
606
+      ]),
607
+      // render: (_, record) => (
608
+      //   <>
609
+      //     <AuthButton name="admin.customer.recommend.edit.id.put" noRight={null}>
610
+      //       <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => showStatus(record)}>变更状态</Button>
611
+      //     </AuthButton>
612
+      //     <AuthButton name="admin.customer.recommend.belong" noRight={null}>
613
+      //       <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => showGM(record)}>调整归属</Button>
614
+      //     </AuthButton>
615
+
616
+      //     {/* <AuthButton name="admin.customer.recommend.get" noRight={null}>
617
+      //       <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => toCustomerDateil(record)}>查看详情</Button>
618
+      //     </AuthButton>
619
+      //       &nbsp;&nbsp; */}
620
+      //     <AuthButton name="admin.mine.taPointsRecords.point.record" noRight={null}>
621
+      //       <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => showRecord(record)}>积分记录</Button>
622
+      //     </AuthButton>
623
+      //     <AuthButton name="admin.mine.taPointsRecords.id.get" noRight={null}>
624
+      //       <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => showRecommend(record.personId)}>推荐客户</Button>
625
+      //     </AuthButton>
626
+
627
+      //   </>
628
+      // ),
629
+    },
630
+  ]
631
+
632
+  return (
633
+    <>
634
+      <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
635
+        {customerType === 'public' && <Form.Item>
636
+          {getFieldDecorator('belongStatus')(
637
+            <Select style={{ width: '180px' }} placeholder="是否归属项目" onChange={handleSelectChange}>
638
+              <Option value={1}>是</Option>
639
+              <Option value={0}>否</Option>
640
+            </Select>,
641
+          )}
642
+        </Form.Item>}
643
+        <Form.Item>
644
+          {getFieldDecorator('buildingId')(
645
+            <BuildSelect />,
646
+          )}
647
+        </Form.Item>
648
+        {customerType === 'private' && <Form.Item>
649
+          {getFieldDecorator('status')(
650
+            <Select style={{ width: '180px' }} placeholder="状态" onChange={handleSelectChange}>
651
+              <Option value={1}>报备</Option>
652
+              <Option value={2}>到访</Option>
653
+              <Option value={3}>认筹</Option>
654
+              <Option value={4}>签约</Option>
655
+            </Select>,
656
+          )}
657
+        </Form.Item>}
658
+        <Form.Item>
659
+          {getFieldDecorator('name')(
660
+            <Input
661
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
662
+              placeholder="姓名"
663
+            />,
664
+          )}
665
+        </Form.Item>
666
+        <Form.Item>
667
+          {getFieldDecorator('tel')(
668
+            <Input
669
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
670
+              placeholder="电话"
671
+            />,
672
+          )}
673
+        </Form.Item>
674
+        {customerType === 'private' && <Form.Item>
675
+          {getFieldDecorator('consultName')(
676
+            <Input placeholder="置业顾问" />,
677
+          )}
678
+        </Form.Item>}
679
+        {customerType === 'private' && <Form.Item>
680
+          {getFieldDecorator('consultTel')(
681
+            <Input placeholder="置业顾问电话" />,
682
+          )}
683
+        </Form.Item>}
684
+        <Form.Item >
685
+          {getFieldDecorator('startCreateDate')(
686
+            <DatePicker placeholder="注册开始时间" format="YYYY-MM-DD HH:mm:ss" showTime={{ format: 'HH:mm:ss' }} />)}
687
+        </Form.Item>
688
+        <Form.Item >
689
+          {getFieldDecorator('endCreateDate')(
690
+            <DatePicker placeholder="注册结束时间" format="YYYY-MM-DD HH:mm:ss" showTime={{ format: 'HH:mm:ss' }} />)}
691
+        </Form.Item>
692
+        <Form.Item>
693
+          {getFieldDecorator('sceneType')(
694
+            <WxDictSelect />,
695
+          )}
696
+        </Form.Item>
697
+        <Form.Item>
698
+          {getFieldDecorator('sharePersonName')(
699
+            <Input placeholder="推广人" />,
700
+          )}
701
+        </Form.Item>
702
+        <Form.Item>
703
+          <AuthButton name="admin.customer.recommend.search" noRight={null}>
704
+            <Button type="primary" htmlType="submit" >
705
+              搜索
706
+              </Button>
707
+          </AuthButton>
708
+          <Button style={{ marginLeft: 8 }} onClick={handleReset}>
709
+            重置
710
+            </Button>
711
+        </Form.Item>
712
+      </Form>
713
+      {
714
+        customerType === 'private' ?
715
+          <AuthButton name="admin.customer.import" noRight={null}>
716
+            <Button type="primary" loading={loadingStatus} onClick={() => exportCustomer()} style={{ float: 'right', margin: '20px 0', zIndex: 1 }}>
717
+              导出
718
+          </Button>
719
+          </AuthButton> :
720
+          <>
721
+            <AuthButton name="admin.customer.import" noRight={null}>
722
+              <Button type="primary" onClick={() => batchAssistConsultant()} style={{ float: 'right', margin: '20px 0', marginLeft: '20px', zIndex: 1 }}>
723
+                批量分配置业顾问
724
+          </Button>
725
+            </AuthButton>
726
+            <AuthButton name="admin.customer.import" noRight={null}>
727
+              <Button type="primary" loading={loadingStatus} onClick={() => exportCustomer()} style={{ float: 'right', margin: '20px 0', zIndex: 1 }}>
728
+                导出
729
+          </Button>
730
+            </AuthButton>
731
+          </>
732
+      }
733
+
734
+
735
+      <div style={{ margin: '20px 0' }}>
736
+        <Radio.Group value={customerType} onChange={radioButtonHandleSizeChange} buttonStyle="solid">
737
+          <Radio.Button value="private">私客</Radio.Button>
738
+          <Radio.Button value="public">公客</Radio.Button>
739
+        </Radio.Group>
740
+      </div>
741
+      {customerType === 'private' ?
742
+        <Table
743
+          // onRow={record => {
744
+          //   return {
745
+          //     onClick: () => toCustomerDateil(record),
746
+          //   };
747
+          // }}
748
+          dataSource={dataSource.records} columns={privateColumns} pagination={{ current: dataSource.current, total: dataSource.total, pageSize: dataSource.size, onChange }} rowKey={r => r.customerId} /> :
749
+        <Table rowSelection={rowSelection}
750
+          // onRow={record => {
751
+          //   return {
752
+          //     onClick: () => publicCustomerDetail(record),
753
+          //   };
754
+          // }}
755
+          dataSource={dataPub.records} columns={publicColumns} pagination={{ current: dataPub.current, total: dataPub.total, pageSize: dataPub.size, onChange }} rowKey={r => r.customerId} ></Table>
756
+      }
757
+
758
+      {/* 调整归属 */}
759
+      <Attribution visibleData={gVisibleData} onCancel={() => closeAttribution()} />
760
+
761
+      {/* 积分记录 */}
762
+      <IntegralRecord visibleData={recordVisibleData} onCancel={() => closeAll()} />
763
+
764
+      {/* 变更状态 */}
765
+      <ChangeStatus visibleData={statusVisibleData} onCancel={() => closeAll()} />
766
+
767
+      {/* 推荐客户 */}
768
+      <ModalRecommendRecord visibleData={recommendVisibleData} onCancel={() => closeAll()} />
769
+
770
+      {/* 分配置业顾问 */}
771
+      <AssistConsultant visibleData={assistVisibleData} onCancel={() => closeAll()} />
772
+
773
+      {/* 批量分配置业顾问 */}
774
+      <BatchAssistConsultant visibleData={batchAssistVisibleData} onCancel={() => closeAll()} />
775
+
776
+      <Prompt message={location =>
777
+        location.pathname.startsWith("/customer/customerlist")
778
+          ? true
779
+          : (localStorage.removeItem("priPageParams"), localStorage.removeItem("pubPageParams"), localStorage.removeItem("state"))} />
780
+    </>
781
+  );
782
+}
783
+
784
+const WrappedBody = Form.create({ name: 'body' })(body);
785
+
786
+export default WrappedBody

+ 183
- 0
estateagents-admin-manager/src/pages/customer/customerlist/publicCustomerDetail.jsx Ver fichero

@@ -0,0 +1,183 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Table, Pagination, Button } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import publicStyle from './publicStyle.less';
5
+import apis from '../../../services/apis';
6
+import request from '../../../utils/request';
7
+import moment from 'moment';
8
+import BuildSelect from '../../../components/SelectButton/BuildSelect'
9
+
10
+import router from 'umi/router';
11
+import Prompt from 'umi/prompt';
12
+
13
+function header(props) {
14
+  /**
15
+   * @param {*} props
16
+   * @returns
17
+   */
18
+  // eslint-disable-next-line react-hooks/rules-of-hooks
19
+  const [data, setData] = useState([{}])
20
+  const [tableData, setTableDataData] = useState([{}])
21
+  const [dataConsultant, setDataonsultant] = useState({})
22
+  const [intentionData, setIntentionData] = useState([])
23
+  const [buildingIdValue, setBuildingIdData] = useState()
24
+
25
+  // eslint-disable-next-line react-hooks/rules-of-hooks
26
+  useEffect(() => {
27
+    getById()
28
+    toLoadIntention()
29
+  }, [])
30
+
31
+  function toLoadIntention() {
32
+    if (intentionData) {
33
+      return
34
+    }
35
+    const arr = []
36
+    // 意向值
37
+    for (let i = 0; i < intentionData.length; i++) {
38
+      const a = [].concat(
39
+        intentionData.concat([{
40
+          key: i,
41
+          name: `Edward King ${i}`,
42
+          age: 32,
43
+          address: `London, Park Lane no. ${i}`,
44
+        }]),
45
+      )
46
+      arr.push(a)
47
+    }
48
+    setIntentionData(arr)
49
+  }
50
+
51
+  // 查询
52
+  const { id } = props.location.query;
53
+  function getById(params) {
54
+    if (id === '' || id === undefined) {
55
+      return
56
+    }
57
+
58
+    request({ ...apis.customer.cecommendPublic, urlData: { id }, params: { ...params } }).then(res => {
59
+      setTableDataData(res.visitRecords)
60
+      setData(res)
61
+      setDataonsultant(res.geoInfo)
62
+      setIntentionData(res.intentions)
63
+    })
64
+  }
65
+  // 分页
66
+  // 分页
67
+  function onChange(number) {
68
+    if (id === '' || id === undefined) {
69
+      return
70
+    }
71
+    request({ ...apis.customer.cecommendPublic, urlData: { id }, params: { pageNumber: number, pageSize: 10 } }).then(res => {
72
+      setData(res)
73
+      setTableDataData(res.visitRecords)
74
+      setDataonsultant(res.geoInfo)
75
+    })
76
+  }
77
+
78
+  function changBuilding(buildingId) {
79
+    setBuildingIdData(buildingId)
80
+    getById({ pageNumber: 1, pageSize: 10, buildingId: buildingId })
81
+  }
82
+
83
+  const columns = [
84
+    {
85
+      title: '访问事件',
86
+      dataIndex: 'activity',
87
+      key: 'activity',
88
+      align: 'center',
89
+    },
90
+    {
91
+      title: '访问内容',
92
+      dataIndex: 'activityName',
93
+      key: 'activityName',
94
+      align: 'center',
95
+    },
96
+    {
97
+      title: '访问时间',
98
+      dataIndex: 'visitTime',
99
+      key: 'visitTime',
100
+      align: 'center',
101
+      render: (_, record) => <span> {moment(record.visitTime).format('YYYY-MM-DD HH:mm:ss')}</span>,
102
+    },
103
+    {
104
+      title: '停留时间',
105
+      dataIndex: 'visitDuration',
106
+      key: 'visitDuration',
107
+      align: 'center',
108
+      render: (_, record) => <span>{record.visitDuration === null ? 0 : record.visitDuration}秒</span>,
109
+    },
110
+  ]
111
+  // 意向
112
+  const intention = [
113
+    {
114
+      title: 'Name',
115
+      dataIndex: 'name',
116
+      width: 200,
117
+      render: (_, record) => <span>{record.buildingName}</span>,
118
+    },
119
+    {
120
+      title: 'Address',
121
+      dataIndex: 'address',
122
+      render: (_, record) => <span style={{ marginLeft: '50%' }}>{record.intention}</span>,
123
+    },
124
+  ];
125
+
126
+  return (
127
+    <>
128
+      <div style={{ textAlign: 'right', marginBottom: '16px' }}>
129
+        <Button onClick={() => router.go(-1)}>返回</Button>
130
+      </div>
131
+      <div className={publicStyle.cardBox}>
132
+        {/* { console.log("data:",data),console.log("data:",dataConsultant)} */}
133
+        <div className={publicStyle.rightBox}>
134
+          <p className={publicStyle.tit}>客户信息</p>
135
+          <img className={publicStyle.touxiang} src={data.avatarurl && data.avatarurl} />
136
+          <div className={publicStyle.right}>
137
+            <p className={publicStyle.rightItem}>用户名称:{data.name === null ? data.nickname : data.name}</p>
138
+            <p className={publicStyle.rightItem}>手机号码:{data.phone}</p>
139
+            <p className={publicStyle.rightItem}>首次访问时间:{data.visitTime && moment(data.visitTime).format('YYYY-MM-DD')}</p>
140
+          </div>
141
+          <div className={publicStyle.Centered}>
142
+            <p>访问时长:{data.duration}秒</p>
143
+            <p>访问次数:{data.visitTimes}次</p>
144
+            <p className={publicStyle.rightItem}>来源渠道:{data.personFrom ? data.personFrom : '其他'}</p>
145
+            {/* <p>预约人数:{ data.visiteNum }</p> */}
146
+          </div>
147
+          {/* <p className={styles.rightItem}>预约到访时间:{data.appointmentTime && moment(data.appointmentTime).format('YYYY-MM-DD') }</p> */}
148
+          <div className={publicStyle.rightInfo}>
149
+            <p className={publicStyle.rightItem}>国家:{data && data.country}</p>
150
+            <p className={publicStyle.rightItem}>省份:{data && data.province}</p>
151
+            <p className={publicStyle.rightItem}>城市:{data && data.city}</p>
152
+            {/* <p className={styles.rightItem}>详细信息:</p> */}
153
+            {/* <p className={styles.rightItem}>意向项目:{data.intention }</p> */}
154
+            {/* <p className={styles.rightItem}>客户说明:{ data.verifyRemark }</p> */}
155
+          </div>
156
+        </div>
157
+        {/* { console.log("data:",data),console.log("data:",dataConsultant)} */}
158
+        <div className={publicStyle.leftBoxCentre}>
159
+          <div className={publicStyle.tit}>
160
+            <span>项目名称</span>
161
+            <span style={{ float: 'right' }}>意向值</span>
162
+          </div>
163
+          {/* <img className={styles.touxiang} src={ data.picture && data.picture } /> */}
164
+          <div className={publicStyle.infoItem}>
165
+            <Table columnWidth={10} showHeader={false} columns={intention} dataSource={intentionData} pagination={false} scroll={intentionData.length >= 3 ? { y: 240 } : false} />
166
+          </div>
167
+        </div>
168
+      </div>
169
+      <div className={publicStyle.recordBox}>
170
+        <p className={publicStyle.tableName}>访问记录</p>
171
+        <BuildSelect onChange={changBuilding} value={buildingIdValue} />
172
+        <Table dataSource={tableData.records} columns={columns} style={{ marginTop: '15px' }} pagination={{ pageSize: 10, total: tableData.total, onChange }} />
173
+      </div>
174
+      <Prompt message={location =>
175
+        location.pathname.startsWith("/customer/customerlist")
176
+          ? true
177
+          : (localStorage.removeItem("priPageParams"), localStorage.removeItem("pubPageParams"), localStorage.removeItem("state"))} />
178
+    </>
179
+  )
180
+}
181
+const WrappedHeader = Form.create({ name: 'header' })(header);
182
+
183
+export default WrappedHeader

+ 209
- 0
estateagents-admin-manager/src/pages/customer/customerlist/publicStyle.less Ver fichero

@@ -0,0 +1,209 @@
1
+.SubmitButton {
2
+  background: rgba(239,39,58,1);
3
+  border-radius: 7px;
4
+  border: 0px;
5
+}
6
+.text {
7
+  color: rgba(239,39,58,1);
8
+}
9
+.SelectFrom {
10
+  width: 180px;
11
+  background: #ffffff;
12
+  border-radius: 7px;
13
+  border: 1px solid #dbdbdb;
14
+}
15
+.addButton {
16
+  background: #50be00;
17
+  border-radius: 4px;
18
+  border: 0px;
19
+  margin: 10px 0px;
20
+}
21
+.cardText {
22
+  color: #333;
23
+  display: flex;
24
+  align-items: center;
25
+  position: relative;
26
+  line-height: 1.5;
27
+  font-size: 0.106rem;
28
+  margin-bottom: 0.08rem;
29
+
30
+}
31
+.cardItem{
32
+  color: #666;
33
+  display: flex;
34
+  align-items: center; 
35
+  line-height: 1.5;
36
+  font-size: 0.106rem;
37
+  margin-bottom: 0.08rem; 
38
+}
39
+.ediText {
40
+  font-size: 0.106rem;
41
+  color: #ff925c;
42
+  line-height: 24px;
43
+  position: absolute;
44
+  right: 0;
45
+}
46
+.title{
47
+  display: inline-block;
48
+  width:  0.54rem;
49
+  justify-content: space-between;
50
+  text-align: justify;
51
+  text-align-last:justify
52
+}
53
+
54
+.address { 
55
+  width: 400px;
56
+  height: 24px; 
57
+  text-overflow: ellipsis; 
58
+  white-space: nowrap;
59
+  overflow: hidden;
60
+}
61
+
62
+.pitchButton { 
63
+  border-color: rgba(255,126,72,1);
64
+  background-color: rgba(255,126,72,1);
65
+  color: rgba(255,255,255,1); 
66
+}
67
+.noButton {
68
+  border-color: rgba(255,126,72,1);
69
+  color: rgba(255,126,72,1);
70
+}
71
+.displayS {
72
+  display: none;
73
+}
74
+
75
+
76
+// 客户详情样式
77
+.cardBox{
78
+  display: flex;
79
+  .leftBox{
80
+    width:90%;
81
+    min-width:28.5%;
82
+    height:315px;
83
+    background:rgba(255,255,255,1);
84
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
85
+    border-radius:8px;
86
+    display: inline-block;
87
+    margin-right: 30px;
88
+    padding: 30px;
89
+    overflow: hidden;
90
+  }
91
+  .rightBox{
92
+    width:865px;
93
+    min-width:342px;
94
+    height:290px;
95
+    background:rgba(255,255,255,1);
96
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
97
+    border-radius:8px;
98
+    display: inline-block;
99
+    margin-right: 30px;
100
+    padding: 30px;
101
+    overflow: hidden;
102
+  }
103
+  .rightBox{
104
+    width:-webkit-fill-available;
105
+    height:315px;
106
+    min-width: 70%;
107
+    background:rgba(255,255,255,1);
108
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
109
+    border-radius:8px;
110
+    display: inline-block;
111
+    padding: 30px;
112
+    overflow: hidden;
113
+    position: relative;
114
+  }
115
+  .rightBoxCentre{
116
+    width:865px;
117
+    height:315px;
118
+    min-width: 60%;
119
+    background:rgba(255,255,255,1);
120
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
121
+    border-radius:8px;
122
+    display: inline-block;
123
+    padding: 30px;
124
+    overflow: hidden;
125
+    position: relative;
126
+  }
127
+  .leftBoxCentre{
128
+    width:100%;
129
+    height:315px;
130
+    background:rgba(255,255,255,1);
131
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
132
+    border-radius:8px;
133
+    display: inline-block;
134
+    padding: 30px;
135
+    overflow: hidden;
136
+    position: relative;
137
+  }
138
+  .tit{
139
+    font-size:0.15rem;
140
+    font-weight:600;
141
+    color:#222;
142
+    margin: 10px 0 0 0;
143
+  }
144
+  .touxiang{
145
+    width: 120px;
146
+    width: 120px;
147
+    border-radius: 6px;
148
+    margin: 30px 0 20px 0;
149
+  }
150
+  .infoItem{
151
+    color:#666;
152
+    font-size: 0.1rem;
153
+    margin: 0 0 10px 0;
154
+    
155
+  }
156
+  .rightItem{
157
+    color:#666;
158
+    font-size: 0.1rem;
159
+    margin: 0 0 15px 0;
160
+  }
161
+  .right{
162
+    position: absolute;
163
+    top:108px;
164
+    left:170px;
165
+  }
166
+  .left{
167
+    position: absolute;
168
+    top:108px;
169
+    left:60%;
170
+  }
171
+  .rightInfo{
172
+    position: absolute;
173
+    top:108px;
174
+    left:80%;
175
+  }
176
+
177
+  .Centered{
178
+    position: absolute;
179
+    top:108px;
180
+    left:50%;
181
+    margin: 0 0 15px 0;
182
+    color:#666;
183
+    font-size: 0.1rem;
184
+  }
185
+
186
+  .rightCentered{
187
+    position: absolute;
188
+    top:108px;
189
+    left:55%;
190
+    margin: 0 0 15px 0;
191
+    color:#666;
192
+    font-size: 0.1rem;
193
+  }
194
+  
195
+}
196
+.recordBox{
197
+  width:100%;
198
+  background:rgba(255,255,255,1);
199
+  box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
200
+  border-radius:8px;
201
+  margin-top: 30px;
202
+  padding: 30px;
203
+  .tableName{
204
+    font-size:24px;
205
+    font-weight:600;
206
+    color:#222;
207
+  }
208
+}
209
+

+ 69
- 0
estateagents-admin-manager/src/pages/customer/customerlist/style.css Ver fichero

@@ -0,0 +1,69 @@
1
+.SubmitButton {
2
+  background: #ef273a;
3
+  border-radius: 7px;
4
+  border: 0px;
5
+}
6
+.text {
7
+  color: #ef273a;
8
+}
9
+.SelectFrom {
10
+  width: 180px;
11
+  background: #ffffff;
12
+  border-radius: 7px;
13
+  border: 1px solid #dbdbdb;
14
+}
15
+.addButton {
16
+  background: #50be00;
17
+  border-radius: 4px;
18
+  border: 0px;
19
+  margin: 10px 0px;
20
+}
21
+.cardText {
22
+  font-size:  0.106rem;
23
+  color: #333;
24
+  line-height: 24px;
25
+  display: flex;
26
+  align-items: center;
27
+  position: relative;
28
+}
29
+.cardItem {
30
+  font-size:  0.106rem;
31
+  font-weight: 400;
32
+  color: #666;
33
+  line-height: 24px;
34
+  display: flex;
35
+  align-items: center;
36
+}
37
+.ediText {
38
+  font-size:  0.106rem;
39
+  color: #ff925c;
40
+  line-height: 24px;
41
+  position: absolute;
42
+  right: 0;
43
+}
44
+.title {
45
+  display: inline-block;
46
+  width:  0.54rem;
47
+  justify-content: space-between;
48
+  text-align: justify;
49
+  text-align-last: justify;
50
+}
51
+.address {
52
+  width: 400px;
53
+  height: 24px;
54
+  text-overflow: ellipsis;
55
+  white-space: nowrap;
56
+  overflow: hidden;
57
+}
58
+.pitchButton {
59
+  border-color: #ff7e48;
60
+  background-color: #ff7e48;
61
+  color: #ffffff;
62
+}
63
+.noButton {
64
+  border-color: #ff7e48;
65
+  color: #ff7e48;
66
+}
67
+.displayS {
68
+  display: none;
69
+}

+ 239
- 0
estateagents-admin-manager/src/pages/customer/customerlist/style.less Ver fichero

@@ -0,0 +1,239 @@
1
+.SubmitButton {
2
+  background: rgba(239,39,58,1);
3
+  border-radius: 7px;
4
+  border: 0px;
5
+}
6
+.text {
7
+  color: rgba(239,39,58,1);
8
+}
9
+.SelectFrom {
10
+  width: 180px;
11
+  background: #ffffff;
12
+  border-radius: 7px;
13
+  border: 1px solid #dbdbdb;
14
+}
15
+.addButton {
16
+  background: #50be00;
17
+  border-radius: 4px;
18
+  border: 0px;
19
+  margin: 10px 0px;
20
+}
21
+.cardText {
22
+  color: #333;
23
+  display: flex;
24
+  align-items: center;
25
+  position: relative;
26
+  line-height: 1.5;
27
+  font-size: 0.106rem;
28
+  margin-bottom: 0.08rem;
29
+
30
+}
31
+.cardItem{
32
+  color: #666;
33
+  display: flex;
34
+  align-items: center; 
35
+  line-height: 1.5;
36
+  font-size: 0.106rem;
37
+  margin-bottom: 0.08rem; 
38
+}
39
+.ediText {
40
+  font-size: 0.106rem;
41
+  color: #ff925c;
42
+  line-height: 24px;
43
+  position: absolute;
44
+  right: 0;
45
+}
46
+.title{
47
+  display: inline-block;
48
+  width:  0.54rem;
49
+  justify-content: space-between;
50
+  text-align: justify;
51
+  text-align-last:justify
52
+}
53
+
54
+.address { 
55
+  width: 400px;
56
+  height: 24px; 
57
+  text-overflow: ellipsis; 
58
+  white-space: nowrap;
59
+  overflow: hidden;
60
+}
61
+
62
+.pitchButton { 
63
+  border-color: rgba(255,126,72,1);
64
+  background-color: rgba(255,126,72,1);
65
+  color: rgba(255,255,255,1); 
66
+}
67
+.noButton {
68
+  border-color: rgba(255,126,72,1);
69
+  color: rgba(255,126,72,1);
70
+}
71
+.displayS {
72
+  display: none;
73
+}
74
+
75
+
76
+// 客户详情样式
77
+.cardBox{
78
+  display: flex;
79
+  .leftBox{
80
+    width:1000px;
81
+    min-width:350px;
82
+    height:1000px;
83
+    background:rgba(255,255,255,1);
84
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
85
+    border-radius:8px;
86
+    display: inline-block;
87
+    margin-right: 30px;
88
+    padding: 30px;
89
+    overflow: hidden;
90
+  }
91
+  .rightBox{
92
+    width:865px;
93
+    min-width:342px;
94
+    height:290px;
95
+    background:rgba(255,255,255,1);
96
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
97
+    border-radius:8px;
98
+    display: inline-block;
99
+    margin-right: 30px;
100
+    padding: 30px;
101
+    overflow: hidden;
102
+  }
103
+  .rightBox{
104
+    width:-webkit-fill-available;
105
+    height:315px;
106
+    min-width: 100%;
107
+    background:rgba(255,255,255,1);
108
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
109
+    border-radius:8px;
110
+    display: inline-block;
111
+    padding: 30px;
112
+    overflow: hidden;
113
+    position: relative;
114
+  }
115
+  .rightBoxCentre{
116
+    width:865px;
117
+    height:345px;
118
+    min-width: 60%;
119
+    background:rgba(255,255,255,1);
120
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
121
+    border-radius:8px;
122
+    display: inline-block;
123
+    padding: 30px;
124
+    overflow: hidden;
125
+    position: relative;
126
+  }
127
+  .leftBoxCentre{
128
+    width:100%;
129
+    height:345px;
130
+    background:rgba(255,255,255,1);
131
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
132
+    border-radius:8px;
133
+    display: inline-block;
134
+    padding: 30px;
135
+    overflow: hidden;
136
+    position: relative;
137
+  }
138
+  .tit{
139
+    font-size:0.15rem;
140
+    font-weight:600;
141
+    color:#222;
142
+    margin: 10px 0 0 0;
143
+  }
144
+  .flexBox{
145
+    display: flex;
146
+    align-items: end;
147
+  }
148
+  .touxiang{
149
+    width: 120px;
150
+    width: 120px;
151
+    border-radius: 6px;
152
+    margin: 30px 0 20px 0;
153
+  }
154
+  .touxiangphoto{
155
+    width: 80px;
156
+    height: 80px;
157
+    margin: 38px 0 0px 0;
158
+  }
159
+  .infoItem{
160
+    color:#666;
161
+    font-size: 0.1rem;
162
+    margin: 0 0 30px 0;
163
+    
164
+  }
165
+  .rightItem{
166
+    color:#666;
167
+    font-size: 0.1rem;
168
+    margin: 0 0 15px 0;
169
+  }
170
+  .right{
171
+    width: 25%;
172
+    min-width: 1.3rem;
173
+    margin-left: 0.1rem;
174
+    padding-top: 0.3rem;
175
+    // position: absolute;
176
+    // top:108px;
177
+    // left:170px;
178
+  }
179
+  .rightphone{
180
+  
181
+    position: absolute;
182
+    top:108px;
183
+    left:170px;
184
+  }
185
+  .left{
186
+    position: absolute;
187
+    top:108px;
188
+    left:60%;
189
+  
190
+  }
191
+  .rightInfo{
192
+    width: 25%;
193
+    min-width: 1.3rem;
194
+    margin-right: 0.1rem;
195
+    padding-top: 0.3rem;
196
+    // position: absolute;
197
+    // top:108px;
198
+    // left:80%;
199
+  }
200
+
201
+  .Centered{
202
+    width: 25%;
203
+    // position: absolute;
204
+    // top:108px;
205
+    // left:30%;
206
+    min-width: 1.3rem;
207
+    margin: 0 0 15px 0;
208
+    color:#666;
209
+    font-size: 0.1rem;
210
+    padding-top: 0.3rem;
211
+  }
212
+
213
+  .rightCentered{
214
+    // position: absolute;
215
+    // top:108px;
216
+    // left:55%;
217
+    width: 25%;
218
+    min-width: 1.3rem;
219
+    margin: 0 0 15px 0;
220
+    padding-top: 0.3rem;
221
+    color:#666;
222
+    font-size: 0.1rem;
223
+  }
224
+  
225
+}
226
+.recordBox{
227
+  width:100%;
228
+  background:rgba(255,255,255,1);
229
+  box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
230
+  border-radius:8px;
231
+  margin-top: 30px;
232
+  padding: 30px;
233
+  .tableName{
234
+    font-size:24px;
235
+    font-weight:600;
236
+    color:#222;
237
+  }
238
+}
239
+

+ 69
- 0
estateagents-admin-manager/src/pages/customer/customerlist/style.wxss Ver fichero

@@ -0,0 +1,69 @@
1
+.SubmitButton {
2
+  background: #ef273a;
3
+  border-radius: 7px;
4
+  border: 0px;
5
+}
6
+.text {
7
+  color: #ef273a;
8
+}
9
+.SelectFrom {
10
+  width: 180px;
11
+  background: #ffffff;
12
+  border-radius: 7px;
13
+  border: 1px solid #dbdbdb;
14
+}
15
+.addButton {
16
+  background: #50be00;
17
+  border-radius: 4px;
18
+  border: 0px;
19
+  margin: 10px 0px;
20
+}
21
+.cardText {
22
+  font-size:  0.106rem;
23
+  color: #333;
24
+  line-height: 24px;
25
+  display: flex;
26
+  align-items: center;
27
+  position: relative;
28
+}
29
+.cardItem {
30
+  font-size:  0.106rem;
31
+  font-weight: 400;
32
+  color: #666;
33
+  line-height: 24px;
34
+  display: flex;
35
+  align-items: center;
36
+}
37
+.ediText {
38
+  font-size:  0.106rem;
39
+  color: #ff925c;
40
+  line-height: 24px;
41
+  position: absolute;
42
+  right: 0;
43
+}
44
+.title {
45
+  display: inline-block;
46
+  width:  0.54rem;
47
+  justify-content: space-between;
48
+  text-align: justify;
49
+  text-align-last: justify;
50
+}
51
+.address {
52
+  width: 400px;
53
+  height: 24px;
54
+  text-overflow: ellipsis;
55
+  white-space: nowrap;
56
+  overflow: hidden;
57
+}
58
+.pitchButton {
59
+  border-color: #ff7e48;
60
+  background-color: #ff7e48;
61
+  color: #ffffff;
62
+}
63
+.noButton {
64
+  border-color: #ff7e48;
65
+  color: #ff7e48;
66
+}
67
+.displayS {
68
+  display: none;
69
+}

+ 115
- 0
estateagents-admin-manager/src/pages/customer/drift/index.jsx Ver fichero

@@ -0,0 +1,115 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Table, Avatar, Alert, Select, Button } from 'antd';
3
+
4
+import request from '../../../utils/request';
5
+import apis from '../../../services/apis';
6
+import Styles from './style.less'
7
+import WxDictSelect from '@/components/SelectButton/WxDictSelect';
8
+
9
+function costomerDrift(props) {
10
+  const { getFieldDecorator } = props.form
11
+  // eslint-disable-next-line react-hooks/rules-of-hooks
12
+  const [dataSources, setDataSources] = useState({ records: [] })
13
+
14
+  // eslint-disable-next-line react-hooks/rules-of-hooks
15
+  useEffect(() => {
16
+   getList({ pageNumber: '1', pageSize: '10' })
17
+  }, [])
18
+
19
+  function getList(params) {
20
+    request({ ...apis.customer.drift, params: { ...params } }).then(res => {
21
+      setDataSources(res)
22
+    }).catch(err => {
23
+      // eslint-disable-next-line no-unused-expressions
24
+      <Alert
25
+        style={{
26
+          marginBottom: 24,
27
+        }}
28
+        message={err}
29
+        type="error"
30
+        showIcon
31
+      />
32
+    })
33
+  }
34
+
35
+  // 分页
36
+  function onChange(pageNum) {
37
+    // eslint-disable-next-line no-console
38
+    console.log('Page: ', pageNum);
39
+    getList({ pageNumber: pageNum, pageSize: 10 })
40
+  }
41
+
42
+  //重置搜索
43
+  function handleReset() {
44
+    props.form.resetFields();
45
+    getList({ pageNumber: '1', pageSize: '10' })
46
+  }
47
+
48
+  // 提交事件
49
+  function handleSubmit(e) {
50
+    e.preventDefault();
51
+    props.form.validateFields((err, values) => {
52
+      if (!err) {
53
+        console.log('提交数据: ', values)
54
+        const { startDate } = values
55
+        getList({ pageNum: 1, pageSize: 10, ...values })
56
+      }
57
+    });
58
+  }
59
+
60
+  const columns = [
61
+    {
62
+      title: '头像',
63
+      dataIndex: 'avatarurl',
64
+      key: 'avatarurl',
65
+      render: (_, record) => <Avatar shape="square" src={record.avatarurl} size={64} icon="user" />,
66
+    },
67
+    {
68
+      title: '姓名',
69
+      dataIndex: 'nickname',
70
+      key: 'nickname',
71
+    },
72
+    {
73
+      title: '性别',
74
+      dataIndex: 'gender',
75
+      key: 'gender',
76
+      // eslint-disable-next-line no-nested-ternary
77
+      render: (_, record) => <><span>{ record.gender === '1' ? '男' : record.gender === '2' ? '女' : '未知' }</span></>,
78
+    },
79
+    {
80
+      title: '用户来源',
81
+      dataIndex: 'sceneAlias',
82
+      key: 'sceneAlias',
83
+      render: (_, record) => <><span>{ record.sceneAlias ? record.sceneAlias : '其他'}</span></>,
84
+    },
85
+  ];
86
+  
87
+  return (
88
+    <>
89
+      <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
90
+        <Form.Item>
91
+          {getFieldDecorator('sceneType')(
92
+            <WxDictSelect />,
93
+          )}
94
+        </Form.Item>
95
+
96
+        <Form.Item>
97
+            {/* <AuthButton name="admin.customer.recommend.search" noRight={null}> */}
98
+            <Button type="primary" htmlType="submit" >
99
+              搜索
100
+            </Button>
101
+            {/* </AuthButton> */}
102
+            <Button style={{ marginLeft: 8 }} onClick={handleReset}>
103
+              重置
104
+            </Button>
105
+        </Form.Item>
106
+      </Form>
107
+      <Table style={{marginTop:'10px'}} dataSource={dataSources.records} rowKey="drift" columns={columns} pagination={{ total: dataSources.total, onChange }} />
108
+    </>
109
+    // eslint-disable-next-line max-len
110
+    
111
+  )
112
+}
113
+
114
+const WrappedBody = Form.create()(costomerDrift);
115
+export default WrappedBody

+ 58
- 0
estateagents-admin-manager/src/pages/customer/drift/style.less Ver fichero

@@ -0,0 +1,58 @@
1
+.SubmitButton {
2
+  background: rgba(239,39,58,1);
3
+  border-radius: 7px;
4
+  border: 0px;
5
+}
6
+.SelectFrom {
7
+  width: 180px;
8
+  background: #ffffff;
9
+  border-radius: 7px;
10
+  border: 1px solid #dbdbdb;
11
+}
12
+.addButton {
13
+  background: #50be00;
14
+  border-radius: 4px;
15
+  border: 0px;
16
+  margin: 10px 0px;
17
+}
18
+.cardText {
19
+  color: #333;
20
+  display: flex;
21
+  align-items: center;
22
+  position: relative;
23
+  line-height: 1.5;
24
+  font-size: 0.106rem;
25
+  margin-bottom: 0.08rem;
26
+
27
+}
28
+.cardItem{
29
+  color: #666;
30
+  display: flex;
31
+  align-items: center; 
32
+  line-height: 1.5;
33
+  font-size: 0.106rem;
34
+  margin-bottom: 0.08rem; 
35
+}
36
+.ediText {
37
+  font-size: 0.106rem;
38
+  color: #ff925c;
39
+  line-height: 24px;
40
+  position: absolute;
41
+  right: 0;
42
+}
43
+.title{
44
+  display: inline-block;
45
+  width:  0.54rem;
46
+  justify-content: space-between;
47
+  text-align: justify;
48
+  text-align-last:justify
49
+}
50
+
51
+.address { 
52
+  width: 400px;
53
+  height: 24px; 
54
+  text-overflow: ellipsis; 
55
+  white-space: nowrap;
56
+  overflow: hidden;
57
+}
58
+

+ 173
- 0
estateagents-admin-manager/src/pages/customer/visiting/index.jsx Ver fichero

@@ -0,0 +1,173 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Table, Avatar } from 'antd';
3
+import moment from 'moment';
4
+import request from '../../../utils/request';
5
+import apis from '../../../services/apis';
6
+import Styles from './style.less';
7
+import BuildSelect from '../../../components/SelectButton/BuildSelect'
8
+import AuthButton from '@/components/AuthButton';
9
+
10
+const columns = [
11
+  {
12
+    title: '头像',
13
+    dataIndex: 'picture',
14
+    key: 'picture',
15
+    align: 'center',
16
+    width: '15%',
17
+    render: (_, record) => <Avatar shape="square"  size={64} icon="user" />,
18
+  },
19
+  {
20
+    title: '姓名',
21
+    dataIndex: 'name',
22
+    key: 'name',
23
+    align: 'center',
24
+    width: '10%',
25
+    // eslint-disable-next-line no-nested-ternary
26
+    // render: (_, record) => <><span>{customerType === 'private' ? record.name : record.nickname}</span></>,
27
+  },
28
+  {
29
+    title: '电话',
30
+    dataIndex: 'phone',
31
+    key: 'phone',
32
+    align: 'center',
33
+    width: '15%',
34
+  },
35
+  {
36
+    title: '性别',
37
+    dataIndex: 'sex',
38
+    key: 'sex',
39
+    align: 'center',
40
+    width: '15%',
41
+  },
42
+  {
43
+    title: '置业顾问',
44
+    dataIndex: 'asdf',
45
+    key: 'asdf',
46
+    align: 'center',
47
+    width: '15%',
48
+  },
49
+  {
50
+    title: '置业顾问电话',
51
+    dataIndex: 'tel',
52
+    key: 'tel',
53
+    align: 'center',
54
+    width: '15%',
55
+  },
56
+  {
57
+    title: '到访时间',
58
+    dataIndex: 'time',
59
+    key: 'time',
60
+    align: 'center',
61
+    width: '15%',
62
+  },
63
+]
64
+
65
+const data = [
66
+
67
+]
68
+
69
+function onChangetime(dates, dateStrings) {
70
+ 
71
+  // setEndDate(dateStrings[1])
72
+  // setStartDate(dateStrings[0])
73
+  
74
+}
75
+
76
+function exportReport() {
77
+  // request({ ...apis.customer.customerRecommendReportExport, responseType: 'blob' })
78
+  //   .then(response => {
79
+  //     download(response)
80
+  //   })
81
+}
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+function body (props) {
90
+  const { getFieldDecorator, getFieldsValue } = props.form
91
+  const { RangePicker } = DatePicker;
92
+
93
+  function handleReset() {
94
+    props.form.resetFields();
95
+    // getList({ pageNumber: 1, pageSize: 10, customerType })
96
+  }
97
+
98
+  function handleSubmit(e) {
99
+ 
100
+  }
101
+
102
+  // 分页
103
+  function onChange(pageNum) {
104
+    props.form.validateFields((err, values) => {
105
+      if (!err) {
106
+        getList({ pageNumber: pageNum, pageSize: 5, ...values })
107
+      }
108
+    });
109
+    // getList({ pageNumber: pageNum, pageSize: 9 })
110
+  }
111
+
112
+  return (
113
+    <>
114
+    <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
115
+       <Form.Item>
116
+          {getFieldDecorator('buildingId')(
117
+            <BuildSelect />,
118
+          )}
119
+        </Form.Item>
120
+       
121
+        <Form.Item>
122
+          {getFieldDecorator('name')(
123
+            <Input
124
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
125
+              placeholder="姓名"
126
+            />,
127
+          )}
128
+        </Form.Item>
129
+        <Form.Item>
130
+          {getFieldDecorator('tel')(
131
+            <Input
132
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
133
+              placeholder="电话"
134
+            />,
135
+          )}
136
+        </Form.Item>
137
+        
138
+         <Form.Item label="到访时间">
139
+          { getFieldDecorator('time')(
140
+            <RangePicker
141
+            style={{ width: '400px' }}
142
+            // placeholder="到访时间"
143
+            // ranges={{
144
+            //   Today: [moment(), moment()],
145
+            //   'This Month': [moment().startOf('month'), moment().endOf('month')],
146
+            // }}
147
+            // defaultValue={[moment(new Date(new Date().setDate((new Date().getDate() - 6))), 'YYYY-MM-DD HH:MM:SS'), moment(new Date(), 'YYYY-MM-DD HH:MM:SS')]}
148
+            showTime
149
+            onChange={onChangetime}
150
+          />
151
+          )}
152
+        </Form.Item>
153
+        <Form.Item>
154
+            <Button type="primary" htmlType="submit" >
155
+              搜索
156
+            </Button>
157
+            <Button style={{ marginLeft: 8 }} onClick={handleReset}>
158
+              重置
159
+            </Button>
160
+        </Form.Item>
161
+      </Form>
162
+      <Button type="primary" onClick={() => exportReport()} style={{ float: 'right', margin: '20px 0', zIndex: 1 }}>
163
+        导出
164
+      </Button>
165
+
166
+      <Table dataSource={data} columns={columns} pagination={{ total: data.total, onChange }} />
167
+      {/* pagination={{ total: dataSource.total, onChange }} */}
168
+    </>
169
+  );
170
+}
171
+const WrappedBody = Form.create({ name: 'body' })(body);
172
+
173
+export default WrappedBody

+ 151
- 0
estateagents-admin-manager/src/pages/customer/visiting/style.less Ver fichero

@@ -0,0 +1,151 @@
1
+.SubmitButton {
2
+  background: rgba(239,39,58,1);
3
+  border-radius: 7px;
4
+  border: 0px;
5
+}
6
+.text {
7
+  color: rgba(239,39,58,1);
8
+}
9
+.SelectFrom {
10
+  width: 180px;
11
+  background: #ffffff;
12
+  border-radius: 7px;
13
+  border: 1px solid #dbdbdb;
14
+}
15
+.addButton {
16
+  background: #50be00;
17
+  border-radius: 4px;
18
+  border: 0px;
19
+  margin: 10px 0px;
20
+}
21
+.cardText {
22
+  color: #333;
23
+  display: flex;
24
+  align-items: center;
25
+  position: relative;
26
+  line-height: 1.5;
27
+  font-size: 0.106rem;
28
+  margin-bottom: 0.08rem;
29
+
30
+}
31
+.cardItem{
32
+  color: #666;
33
+  display: flex;
34
+  align-items: center; 
35
+  line-height: 1.5;
36
+  font-size: 0.106rem;
37
+  margin-bottom: 0.08rem; 
38
+}
39
+.ediText {
40
+  font-size: 0.106rem;
41
+  color: #ff925c;
42
+  line-height: 24px;
43
+  position: absolute;
44
+  right: 0;
45
+}
46
+.title{
47
+  display: inline-block;
48
+  width:  0.54rem;
49
+  justify-content: space-between;
50
+  text-align: justify;
51
+  text-align-last:justify
52
+}
53
+
54
+.address { 
55
+  width: 400px;
56
+  height: 24px; 
57
+  text-overflow: ellipsis; 
58
+  white-space: nowrap;
59
+  overflow: hidden;
60
+}
61
+
62
+.pitchButton { 
63
+  border-color: rgba(255,126,72,1);
64
+  background-color: rgba(255,126,72,1);
65
+  color: rgba(255,255,255,1); 
66
+}
67
+.noButton {
68
+  border-color: rgba(255,126,72,1);
69
+  color: rgba(255,126,72,1);
70
+}
71
+.displayS {
72
+  display: none;
73
+}
74
+
75
+
76
+// 客户详情样式
77
+.cardBox{
78
+  display: flex;
79
+  .leftBox{
80
+    width:342px;
81
+    min-width:342px;
82
+    height:511px;
83
+    background:rgba(255,255,255,1);
84
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
85
+    border-radius:8px;
86
+    display: inline-block;
87
+    margin-right: 30px;
88
+    padding: 30px;
89
+    overflow: hidden;
90
+  }
91
+  .rightBox{
92
+    width:-webkit-fill-available;
93
+    height:511px;
94
+    min-width: 800px;
95
+    background:rgba(255,255,255,1);
96
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
97
+    border-radius:8px;
98
+    display: inline-block;
99
+    padding: 30px;
100
+    overflow: hidden;
101
+    position: relative;
102
+  }
103
+  .tit{
104
+    font-size:24px;
105
+    font-weight:600;
106
+    color:#222;
107
+    margin: 10px 0 0 0;
108
+  }
109
+  .touxiang{
110
+    width: 120px;
111
+    width: 120px;
112
+    border-radius: 6px;
113
+    margin: 30px 0 20px 0;
114
+  }
115
+  .infoItem{
116
+    color:#666;
117
+    font-size: 19px;
118
+    margin: 0 0 10px 0;
119
+    
120
+  }
121
+  .rightItem{
122
+    color:#666;
123
+    font-size: 19px;
124
+    margin: 0 0 15px 0;
125
+  }
126
+  .right{
127
+    position: absolute;
128
+    top:108px;
129
+    left:170px;
130
+  }
131
+  .rightInfo{
132
+    position: absolute;
133
+    top:50px;
134
+    left:50%;
135
+  }
136
+  
137
+}
138
+.recordBox{
139
+  width:100%;
140
+  background:rgba(255,255,255,1);
141
+  box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
142
+  border-radius:8px;
143
+  margin-top: 30px;
144
+  padding: 30px;
145
+  .tableName{
146
+    font-size:24px;
147
+    font-weight:600;
148
+    color:#222;
149
+  }
150
+}
151
+

+ 193
- 0
estateagents-admin-manager/src/pages/eContract/businessConfig/add.jsx Ver fichero

@@ -0,0 +1,193 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker, Radio, Upload, InputNumber } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import router from 'umi/router';
5
+import moment from 'moment';
6
+import SelectCity from '../../../components/SelectButton/CitySelect'
7
+import BuildSelect2 from '../../../components/SelectButton/BuildSelect2'
8
+import LivePlatSelect from '../../../components/SelectButton/LivePlatSelect'
9
+import CitySelect3 from '../../../components/SelectButton/CitySelect3'
10
+import ImageUpload from '../../../components/XForm/ImageUpload'
11
+import Wangedit from '../../../components/Wangedit/Wangedit'
12
+import apis from '../../../services/apis';
13
+import request from '../../../utils/request';
14
+import AuthButton from '@/components/AuthButton';
15
+import SelectContractTemp from './components/SelectContractTemp';
16
+import SelectRaise from './components/SelectRaise';
17
+import SelectCompany from './components/SelectCompany';
18
+import SelectSeal from './components/SelectSeal';
19
+
20
+const { Option } = Select;
21
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
22
+
23
+let cityId = ''
24
+let contractTemplateName = ''
25
+let targetName = ''
26
+
27
+const header = props => {
28
+  const { salesBatchId } = props.location.query
29
+  const [ saleBatchData, setSaleBatchData ] = useState({})
30
+  const [showHelp, setShowHelp] = useState(false)
31
+
32
+  // const [targetName, setTargetName] = useState({})
33
+  const [companyName, setCompanyName] = useState({})
34
+  // const [contractTemplateName, setContractTemplateName] = useState('')
35
+  const [contractTemplateLink, setContractTemplateLink] = useState('')
36
+
37
+  const cancelPage = () =>{
38
+    router.push({
39
+      pathname: '/eContract/businessConfig/list',
40
+    });
41
+  }
42
+
43
+   //打开新页面
44
+   const openIndexImg = () => {
45
+    if(contractTemplateLink){
46
+     window.open(contractTemplateLink);
47
+    }else{
48
+      message.info('请选择合同模板');
49
+    }
50
+ }
51
+
52
+  function highlightsTypeChange(e) {
53
+    setTypeState(e.target.value)
54
+  }
55
+
56
+  function disabledDate(current) {
57
+    // Can not select days before today and today
58
+    return current && current < moment().endOf('day');
59
+  }
60
+
61
+  function companyOnSuccess(e){
62
+    console.log(e)
63
+    setCompanyName(e)
64
+  }
65
+
66
+  function contractOnSuccess(e){
67
+    contractTemplateName = e.name
68
+    request({ ...apis.taEcontract.taContractTemplateById, urlData: {id: e.id} }).then((data) => {
69
+      setContractTemplateLink(data.contractTemplateAddress)
70
+    })
71
+  }
72
+
73
+  function targetOnSuccess(e){
74
+    console.log('targetOnSuccess', e)
75
+    targetName = e
76
+    console.log('targetOnSuccess', targetName)
77
+  }
78
+
79
+  function sealOnSuccess(e){
80
+    console.log('sealOnSuccess', e)
81
+  }
82
+
83
+  function handleSubmit (e) {
84
+    e.preventDefault();
85
+    props.form.validateFields((err, values) => {
86
+      console.log(values)
87
+      if (!err){
88
+        request({ ...apis.taEcontract.addTaContractBusiness, data: { ...values },}).then((data) => {
89
+          message.info("保存成功")
90
+          router.push({
91
+            pathname: '/eContract/businessConfig/list',
92
+          });
93
+        }).catch((err) => {
94
+          message.info(err.msg || err.message)
95
+        })
96
+      }
97
+    });
98
+  }
99
+
100
+  const { getFieldDecorator } = props.form;
101
+
102
+  return (
103
+    <>
104
+      <Form labelCol={{ span: 7 }} wrapperCol={{ span: 12 }} onSubmit={handleSubmit}>
105
+        <Form.Item label="合同标题">
106
+          {getFieldDecorator('contractTemplateId', {
107
+            rules: [{ required: true, message: ' 请选择合同模板' }],
108
+          })(<SelectContractTemp  onSuccess={e => contractOnSuccess(e)}/>)}
109
+          {getFieldDecorator('contractTemplateName')(<Input  hidden={true}/>)}
110
+        </Form.Item>
111
+        <Form.Item label="合同文件">
112
+          {getFieldDecorator('contractTemplate')}<Button type="danger" style={{marginRight:'20px'}} onClick={openIndexImg}>查看文件</Button>
113
+        </Form.Item>
114
+        <Form.Item label="关联业务类型"> 
115
+          {getFieldDecorator('targetType', {
116
+              rules: [{ required: true, message: '请选择发布状态' }],
117
+            })(<Select placeholder="关联业务类型" style={{ width: '400px' }}>
118
+            <Option value="raise">房源认筹</Option>
119
+          </Select>)}
120
+        </Form.Item>
121
+        <Form.Item label="关联业务">
122
+          {getFieldDecorator('targetId', {
123
+            rules: [{ required: true, message: ' 请选择关联业务' }],
124
+          })(<SelectRaise targetType={props.form.getFieldValue('targetType')} onSuccess={e => targetOnSuccess(e)}/>)}
125
+          {getFieldDecorator('targetName', {initialValue:targetName,
126
+            rules: [{ required: true, message: ' 请选择关联业务' }],
127
+          })(<Input  hidden={true}/>)}
128
+        </Form.Item>
129
+        <Form.Item label="甲方" help="系统会在业务需要时自动签所选企业印章,比如用户在签署认筹合同前系统会自动签署企业印章。">
130
+          {getFieldDecorator('companyId', {
131
+            rules: [{ required: true, message: ' 请选择关联企业' }],
132
+          })(<SelectCompany onSuccess={e => companyOnSuccess(e)}/>)}
133
+          {getFieldDecorator('companyName', {initialValue:companyName,
134
+            rules: [{ required: true, message: ' 请选择关联业务' }],
135
+          })(<Input  hidden={true}/>)}
136
+        </Form.Item>
137
+        <Form.Item label="甲方印章" style={{marginTop:'20px'}}>
138
+          {getFieldDecorator('sealId', {
139
+            rules: [{ required: true, message: ' 请选择企业印章' }],
140
+          })(<SelectSeal companyId={props.form.getFieldValue('companyId')} onSuccess={e => sealOnSuccess(e)}/>)}
141
+        </Form.Item>
142
+        <Form.Item label="甲方签章定位关键字" help="关键字为合同文件中的文字内容(能被ctrl+f 查找功能检索到)。法大大按此关键字进行签章位置的定位,将电子章盖在这个关键字上面。凡出现关键字的地方均可能会盖上指定用户的电子章,建议关键字在合同中保持唯一。">
143
+          {getFieldDecorator('signatoryKeywords', {
144
+            rules: [{ required: true, message: '请输入甲方签章定位关键字' }],
145
+          })(<Input maxLength={20} style={{width:'400px'}}/>)}
146
+        </Form.Item>
147
+        <Form.Item label="甲方关键字签章策略" style={{marginTop:'20px'}}> 
148
+          {getFieldDecorator('signatoryStrategy', {
149
+              rules: [{ required: true, message: '请选择甲方关键字签章策略' }],
150
+            })(<Select placeholder="甲方关键字签章策略" style={{ width: '400px' }}>
151
+            <Option value="2">最后一个关键字签章</Option>
152
+            <Option value="0">所有关键字签章</Option>
153
+            <Option value="1">第一个关键字签章</Option>
154
+          </Select>)}
155
+        </Form.Item>
156
+        <Form.Item label="乙方签章定位关键字" help="关键字为合同文件中的文字内容(能被ctrl+f 查找功能检索到)。法大大按此关键字进行签章位置的定位,将电子章盖在这个关键字上面。凡出现关键字的地方均可能会盖上指定用户的电子章,建议关键字在合同中保持唯一。">
157
+          {getFieldDecorator('customerKeywords', {
158
+            rules: [{ required: true, message: '请输入乙方签章定位关键字' }],
159
+          })(<Input maxLength={20} style={{width:'400px'}}/>)}
160
+        </Form.Item>
161
+        <Form.Item label="乙方关键字签章策略" style={{marginTop:'20px'}}> 
162
+          {getFieldDecorator('customerStrategy', {
163
+              rules: [{ required: true, message: '请选择乙方关键字签章策略' }],
164
+            })(<Select placeholder="乙方关键字签章策略" style={{ width: '400px' }}>
165
+            <Option value="2">最后一个关键字签章</Option>
166
+            <Option value="0">所有关键字签章</Option>
167
+            <Option value="1">第一个关键字签章</Option>
168
+          </Select>)}
169
+        </Form.Item>
170
+        <Form.Item label="发布状态"> 
171
+          {getFieldDecorator('status', {
172
+              rules: [{ required: true, message: '请选择发布状态' }],
173
+            })(<Select placeholder="发布状态" style={{ width: '400px' }}>
174
+            <Option value='0'>否</Option>
175
+            <Option value='1'>是</Option>
176
+          </Select>)}
177
+        </Form.Item>
178
+        <Form.Item wrapperCol={{ span: 15, offset: 7 }}>
179
+          <Button type="primary" htmlType="submit"style={{marginRight:'20px'}}>
180
+            确定
181
+          </Button>
182
+          <Button onClick={() => router.go(-1)}>
183
+            取消
184
+          </Button>
185
+        </Form.Item>
186
+      </Form>
187
+    </>
188
+  )
189
+}
190
+
191
+const WrappedHeader = Form.create({ name: 'header' })(header);
192
+
193
+export default WrappedHeader

+ 192
- 0
estateagents-admin-manager/src/pages/eContract/businessConfig/components/SelectCompany.jsx Ver fichero

@@ -0,0 +1,192 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Select, Modal, Button, Table, Divider, Tag, Input,Row,Col,Icon, Pagination } from 'antd';
3
+import request from '../../../../utils/request';
4
+import apis from '../../../../services/apis';
5
+import moment from 'moment';
6
+import Navigate from '@/components/Navigate';
7
+
8
+const { Column, ColumnGroup } = Table;
9
+const { Search } = Input;
10
+const SelectContractTemp = props => {
11
+  const {
12
+    value,
13
+    onChange,
14
+    ...rest
15
+  } = props;
16
+
17
+  const [list, setList] = useState([]);
18
+  const [dataInfo, setDataInfo] = useState({ list: [], total: 0 });
19
+  const [visible, setVisible] = useState(false);
20
+  const [group, setGroup] = useState({ groupId: undefined, groupName: '甲方企业' })
21
+  const getGroupTitle = val => {
22
+    return (list.filter(x => x.companyId == val)[0] || {}).companyName || '请选择'
23
+  }
24
+  const updateGroup = val => setGroup({ groupId: val, groupName: getGroupTitle(val) })
25
+
26
+  const buildingId = props.buildingId
27
+
28
+  useEffect(() => {
29
+    getList({ pageNum: 1, pageSize: 10 })
30
+  }, [buildingId]);
31
+
32
+  // 查询列表
33
+  const getList = (params) => {
34
+    request({ ...apis.taEcontract.taCompanyList, params: { ...params } }).then((data) => {
35
+      setList(data.records || [])
36
+      setDataInfo(data)
37
+      updateGroup(buildingId ? undefined : value);
38
+    })
39
+  }
40
+
41
+  const searchContractTemp = (e) => {
42
+    getList({ pageNum: 1, pageSize: 10 })
43
+  }
44
+
45
+  if (value !== group.groupId) {
46
+    updateGroup(value);
47
+  }
48
+
49
+  const handleChange = val => {
50
+    onChange(val)
51
+  }
52
+
53
+  const setData = val => {
54
+    updateGroup(val.id)
55
+    onChange(val.id)
56
+    setVisible(false)
57
+    props.onSuccess(val.name);
58
+  }
59
+
60
+  // 提交事件
61
+  const handleSubmit = (e, props) => {
62
+    e.preventDefault();
63
+    e.stopPropagation();
64
+    props.form.validateFields((err, values) => {
65
+      if (!err) {
66
+        getList({ pageNum: 1, pageSize: 10, companyName: values.companyName, companyCode: values.companyCode })
67
+      }
68
+    });
69
+  }
70
+
71
+  const changePageNum = pageNumber => {
72
+    getList({ pageNum: pageNumber, pageSize: 10, ...props.form.getFieldsValue() })
73
+  }
74
+
75
+  //重置搜索
76
+  function handleReset () {
77
+    props.form.resetFields();
78
+    getList({ pageNum: 1, pageSize: 10 })
79
+  }
80
+
81
+  const clearVal = val => {
82
+    onChange(val)
83
+  }
84
+
85
+   //打开新页面
86
+   const openIndexImg = () => {
87
+    const newWin=window.open('about:blank');
88
+    newWin.location.href="https://easydoc.xyz/s/24703398/3SqDkJDw/F8szOMk0"
89
+  }
90
+
91
+  const columns = [
92
+    {
93
+      title: '企业名称',
94
+      dataIndex: 'companyName',
95
+      key: 'companyName',
96
+      align: 'center',
97
+      ellipsis: true,
98
+    },
99
+    {
100
+      title: '企业编号',
101
+      dataIndex: 'companyCode',
102
+      key: 'companyCode',
103
+      align: 'center',
104
+      ellipsis: true,
105
+    },
106
+    {
107
+      title: '实名认证状态',
108
+      dataIndex: 'status',
109
+      key: 'status',
110
+      align: 'center',
111
+      ellipsis: true,
112
+      render: (status) => <span>{status === 0 ? '未认证' : status === 1 ? "管理员资料已提交" : status === 2 ? "企业基本资料(没有申请表)已提交" : status === 3 ? "已提交待审核" : 
113
+      status === 4 ? '审核通过' : status === 5 ? "审核不通过" : status === 6 ? "人工初审通过" : "" }</span>,
114
+    },
115
+    {
116
+      title: '印章数',
117
+      dataIndex: 'sealNum',
118
+      key: 'sealNum',
119
+      align: 'center',
120
+      ellipsis: true,
121
+    },
122
+    {
123
+      title: '自动签章授权状态',
124
+      dataIndex: 'authorizeStatus',
125
+      key: 'authorizeStatus',
126
+      align: 'center',
127
+      ellipsis: true,
128
+      render: (authorizeStatus) => <span>{authorizeStatus === '3000' ? '已授权' : '未授权' }</span>,
129
+    },
130
+    {
131
+      title: '操作',
132
+      align: 'center',
133
+      width: '20%',
134
+      render: (text, record) => (
135
+        <span>
136
+          {record.sealNum >0 && record.authorizeStatus === '3000' && <Navigate onClick={() => setData({id:record.companyId, name:record.companyName})}>选择</Navigate>}
137
+        </span>
138
+      ),
139
+    },
140
+  ];
141
+
142
+  const { getFieldDecorator } = props.form
143
+
144
+  return (
145
+    <div>
146
+      <div>{group.groupName}<Navigate onClick={() => setVisible(true)}>选择关联企业</Navigate></div>
147
+      <Modal
148
+        title="选择关联企业"
149
+        visible={visible}
150
+        onCancel={() => setVisible(false)}
151
+        footer={[]}
152
+        width={1500}
153
+      >
154
+        <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
155
+        <Form.Item>
156
+          {getFieldDecorator('companyName')(
157
+            <Input
158
+            prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
159
+            placeholder="企业名称"
160
+          />,
161
+          )}
162
+        </Form.Item>
163
+        <Form.Item>
164
+          {getFieldDecorator('companyCode')(
165
+            <Input
166
+            prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
167
+            placeholder="企业编号"
168
+          />,
169
+          )}
170
+        </Form.Item>
171
+        <Form.Item>
172
+          <span style={{color:'#999'}}>可选企业必须已认证通过、已上传印章且授权了自动签章。</span><Navigate onClick={openIndexImg}>查看电子合同接入手册</Navigate>
173
+        </Form.Item>
174
+        <Form.Item>
175
+          <Button type="primary" htmlType="submit" >
176
+                 搜索
177
+          </Button>
178
+          <Button style={{ marginLeft: 8 }} onClick={handleReset}>
179
+                 重置
180
+          </Button>     
181
+        </Form.Item>
182
+      </Form>
183
+      <Table rowKey={list => list.drainageId} columns={columns} dataSource={list} pagination={false} />
184
+      <Pagination defaultCurrent={1} total={dataInfo.total} onChange={e => changePageNum(e)} current={dataInfo.current}/>
185
+      </Modal>
186
+    </div>
187
+  )
188
+}
189
+
190
+const WrappedHeader = Form.create({ name: 'SelectContractTemp' })(SelectContractTemp);
191
+
192
+export default WrappedHeader

+ 157
- 0
estateagents-admin-manager/src/pages/eContract/businessConfig/components/SelectContractTemp.jsx Ver fichero

@@ -0,0 +1,157 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Select, Modal, Button, Table, Divider, Tag, Input,Row,Col,Icon ,Pagination} from 'antd';
3
+import request from '../../../../utils/request';
4
+import apis from '../../../../services/apis';
5
+import moment from 'moment';
6
+import Navigate from '@/components/Navigate';
7
+
8
+const { Column, ColumnGroup } = Table;
9
+const { Search } = Input;
10
+const SelectContractTemp = props => {
11
+  const {
12
+    value,
13
+    onChange,
14
+    ...rest
15
+  } = props;
16
+
17
+  const [list, setList] = useState([]);
18
+  const [dataInfo, setDataInfo] = useState({ list: [], total: 0 });
19
+  const [visible, setVisible] = useState(false);
20
+  const [group, setGroup] = useState({ groupId: undefined, groupName: '合同标题' })
21
+  const getGroupTitle = val => {
22
+    return (list.filter(x => x.contractTemplateId == val)[0] || {}).contractTemplateName || '请选择'
23
+  }
24
+  const updateGroup = val => setGroup({ groupId: val, groupName: getGroupTitle(val) })
25
+
26
+  const buildingId = props.buildingId
27
+
28
+  useEffect(() => {
29
+    getList({ pageNum: 1, pageSize: 10 })
30
+  }, [buildingId]);
31
+
32
+  // 查询列表
33
+  const getList = (params) => {
34
+    request({ ...apis.taEcontract.taContractTemplateList, params: { ...params } }).then((data) => {
35
+      setList(data.records)
36
+      setDataInfo(data)
37
+      updateGroup(buildingId ? undefined : value);
38
+    })
39
+  }
40
+
41
+  const searchContractTemp = (e) => {
42
+    getList({ pageNum: 1, pageSize: 10 })
43
+  }
44
+
45
+  if (value !== group.groupId) {
46
+    updateGroup(value);
47
+  }
48
+
49
+  const handleChange = val => {
50
+    onChange(val)
51
+  }
52
+
53
+  const setData = val => {
54
+    updateGroup(val.id)
55
+    onChange(val.id)
56
+    setVisible(false)
57
+    props.onSuccess(val);
58
+  }
59
+
60
+  // 提交事件
61
+  const handleSubmit = (e, props) => {
62
+    e.preventDefault();
63
+    e.stopPropagation();
64
+    props.form.validateFields((err, values) => {
65
+      if (!err) {
66
+        getList({ pageNum: 1, pageSize: 10, contractTemplateName:values.contractTemplateName })
67
+      }
68
+    });
69
+  }
70
+
71
+  //重置搜索
72
+  function handleReset () {
73
+    props.form.resetFields();
74
+    getList({ pageNum: 1, pageSize: 10 })
75
+  }
76
+
77
+  const clearVal = val => {
78
+    onChange(val)
79
+  }
80
+
81
+  const changePageNum = pageNumber => {
82
+    getList({ pageNum: pageNumber, pageSize: 10, ...props.form.getFieldsValue() })
83
+  }
84
+
85
+  const columns = [
86
+    {
87
+      title: '合同编号',
88
+      dataIndex: 'contractTemplateId',
89
+      key: 'contractTemplateId',
90
+      align: 'center',
91
+      ellipsis: true,
92
+    },
93
+    {
94
+      title: '合同标题',
95
+      dataIndex: 'contractTemplateName',
96
+      key: 'contractTemplateName',
97
+      align: 'center',
98
+      ellipsis: true,
99
+    },
100
+    {
101
+      title: '新增时间',
102
+      dataIndex: 'createDate',
103
+      key: 'createDate',
104
+      align: 'center',
105
+      ellipsis: true,
106
+      render: (x, row) => <><span>{`${moment(row.createDate).format('YYYY-MM-DD HH:mm:ss')}`}</span></>,
107
+    },
108
+    {
109
+      title: '操作',
110
+      align: 'center',
111
+      width: '20%',
112
+      render: (text, record) => (
113
+        <Navigate onClick={() => setData({id:record.contractTemplateId, name:record.contractTemplateName})}>选择</Navigate>
114
+      ),
115
+    },
116
+  ];
117
+
118
+  const { getFieldDecorator } = props.form
119
+
120
+  return (
121
+    <div>
122
+      <div>{group.groupName}<Navigate onClick={() => setVisible(true)}>选择合同模板</Navigate></div>
123
+      <Modal
124
+        title="选择合同模板"
125
+        visible={visible}
126
+        onCancel={() => setVisible(false)}
127
+        footer={[]}
128
+        width='1000px'
129
+      >
130
+        <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
131
+        <Form.Item>
132
+          {getFieldDecorator('contractTemplateName')(
133
+            <Input
134
+            prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
135
+            placeholder="合同标题"
136
+          />,
137
+          )}
138
+        </Form.Item>
139
+        <Form.Item>
140
+          <Button type="primary" htmlType="submit" >
141
+                 搜索
142
+          </Button>
143
+          <Button style={{ marginLeft: 8 }} onClick={handleReset}>
144
+                 重置
145
+          </Button>     
146
+        </Form.Item>
147
+      </Form>
148
+      <Table rowKey={list => list.drainageId} columns={columns} dataSource={list} pagination={false} />
149
+      <Pagination defaultCurrent={1} total={dataInfo.total} onChange={e => changePageNum(e)} current={dataInfo.current}/>
150
+      </Modal>
151
+    </div>
152
+  )
153
+}
154
+
155
+const WrappedHeader = Form.create({ name: 'SelectContractTemp' })(SelectContractTemp);
156
+
157
+export default WrappedHeader

+ 186
- 0
estateagents-admin-manager/src/pages/eContract/businessConfig/components/SelectRaise.jsx Ver fichero

@@ -0,0 +1,186 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Select, Modal, Button, Table, Divider, Tag, Input,Row,Col,Icon, Pagination } from 'antd';
3
+import request from '../../../../utils/request';
4
+import apis from '../../../../services/apis';
5
+import BuildSelect from '../../../../components/SelectButton/BuildSelect'
6
+import moment from 'moment';
7
+import Navigate from '@/components/Navigate';
8
+
9
+const { Column, ColumnGroup } = Table;
10
+const { Search } = Input;
11
+const SelectContractTemp = props => {
12
+  const {
13
+    value,
14
+    onChange,
15
+    ...rest
16
+  } = props;
17
+
18
+  const [list, setList] = useState([]);
19
+  const [dataInfo, setDataInfo] = useState({ list: [], total: 0 });
20
+  const [visible, setVisible] = useState(false);
21
+  const [group, setGroup] = useState({ groupId: undefined, groupName: '关联业务' })
22
+
23
+  const targetType = props.targetType;
24
+  
25
+  const getGroupTitle = val => {
26
+    return (list.filter(x => x.raiseId == val)[0] || {}).salesBatchName || '请选择业务类型'
27
+  }
28
+  const updateGroup = val => setGroup({ groupId: val, groupName: getGroupTitle(val) })
29
+
30
+  const buildingId = props.buildingId
31
+
32
+  useEffect(() => {
33
+    getList({ pageNum: 1, pageSize: 10, status: 1 })
34
+  }, [buildingId]);
35
+
36
+  // 查询列表
37
+  const getList = (params) => {
38
+    request({ ...apis.house.taRaiseList, params: { ...params } }).then((data) => {
39
+      setList(data.records || [])
40
+      setDataInfo(data)
41
+      updateGroup(buildingId ? undefined : value);
42
+    })
43
+  }
44
+
45
+  const searchContractTemp = (e) => {
46
+    getList({ pageNum: 1, pageSize: 10 })
47
+  }
48
+
49
+  if (value !== group.groupId) {
50
+    updateGroup(value);
51
+  }
52
+
53
+  const handleChange = val => {
54
+    onChange(val)
55
+  }
56
+
57
+  const changePageNum = pageNumber => {
58
+    getList({ pageNum: pageNumber, pageSize: 10, status: 1, ...props.form.getFieldsValue() })
59
+  }
60
+  const setData = val => {
61
+    updateGroup(val.id)
62
+    onChange(val.id)
63
+    setVisible(false)
64
+    props.onSuccess(val.name);
65
+  }
66
+
67
+  // 提交事件
68
+  const handleSubmit = (e, props) => {
69
+    e.preventDefault();
70
+    e.stopPropagation();
71
+    props.form.validateFields((err, values) => {
72
+      if (!err) {
73
+        getList({ pageNum: 1, pageSize: 10, buildingId:values.buildingId, salesBatchName:values.salesBatchName })
74
+      }
75
+    });
76
+  }
77
+
78
+  //重置搜索
79
+  function handleReset () {
80
+    props.form.resetFields();
81
+    getList({ pageNum: 1, pageSize: 10 })
82
+  }
83
+
84
+  const clearVal = val => {
85
+    onChange(val)
86
+  }
87
+
88
+  const columns = [
89
+    {
90
+      title: '销售批次名',
91
+      dataIndex: 'salesBatchName',
92
+      key: 'salesBatchName',
93
+      align: 'center',
94
+    },
95
+    {
96
+      title: '楼盘名称',
97
+      dataIndex: 'buildingName',
98
+      key: 'buildingName',
99
+      align: 'center',
100
+    },
101
+    {
102
+      title: '认筹开始时间',
103
+      dataIndex: 'raiseStartTime',
104
+      key: 'raiseStartTime',
105
+      align: 'center',
106
+      render: (x, row) => <><span>{`${moment(row.raiseStartTime).format('YYYY-MM-DD HH:mm:ss')}`}</span></>,
107
+    },
108
+    {
109
+      title: '认筹结束时间',
110
+      dataIndex: 'raiseEndTime',
111
+      key: 'raiseEndTime',
112
+      align: 'center',
113
+      render: (x, row) => <><span>{`${moment(row.raiseEndTime).format('YYYY-MM-DD HH:mm:ss')}`}</span></>,
114
+    },
115
+    {
116
+      title: '锁房方式',
117
+      dataIndex: 'houseLockingType',
118
+      key: 'houseLockingType',
119
+      align: 'center',
120
+      render: (x, row) => <><span>{row.houseLockingType == 'auto' ? "自动锁房" : "手动锁房"}</span></>,
121
+    },
122
+    {
123
+      title: '缴费方式',
124
+      dataIndex: 'payType',
125
+      key: 'payType',
126
+      align: 'center',
127
+      render: (x, row) => <><span>{row.payType == 'offLine' ? "线下缴费" : row.payType == 'onLine' ? "线上缴费" : "线上缴费,线下缴费"}</span></>,
128
+    },
129
+    {
130
+      title: '操作',
131
+      align: 'center',
132
+      width: '20%',
133
+      render: (text, record) => (
134
+        <Navigate onClick={() => setData({id:record.raiseId, name:record.salesBatchName})}>选择</Navigate>
135
+      ),
136
+    },
137
+  ];
138
+
139
+  const { getFieldDecorator } = props.form
140
+
141
+  return (
142
+    <div>
143
+      <div>{group.groupName}<Navigate onClick={() => setVisible(true)}>{targetType != undefined && '选择关联业务'}</Navigate></div>
144
+      <Modal
145
+        title="选择关联业务"
146
+        visible={visible}
147
+        onCancel={() => setVisible(false)}
148
+        footer={[]}
149
+        width={900}
150
+      >
151
+        <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
152
+        <Form.Item>
153
+          {getFieldDecorator('buildingId')(
154
+            <BuildSelect />,
155
+          )}
156
+        </Form.Item>
157
+        <Form.Item>
158
+          {getFieldDecorator('salesBatchName')(
159
+            <Input
160
+            prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
161
+            placeholder="销售批次名"
162
+          />,
163
+          )}
164
+        </Form.Item>
165
+        <Form.Item>
166
+          <span style={{color:'#AAAAAA'}}>仅显示已发布的销售批次对应的认筹</span>
167
+        </Form.Item>
168
+        <Form.Item>
169
+          <Button type="primary" htmlType="submit" >
170
+                 搜索
171
+          </Button>
172
+          <Button style={{ marginLeft: 8 }} onClick={handleReset}>
173
+                 重置
174
+          </Button>     
175
+        </Form.Item>
176
+      </Form>
177
+      <Table rowKey={list => list.drainageId} columns={columns} dataSource={list} pagination={false}/>
178
+      <Pagination defaultCurrent={1} total={dataInfo.total} onChange={e => changePageNum(e)} current={dataInfo.current}/>
179
+      </Modal>
180
+    </div>
181
+  )
182
+}
183
+
184
+const WrappedHeader = Form.create({ name: 'SelectContractTemp' })(SelectContractTemp);
185
+
186
+export default WrappedHeader

+ 168
- 0
estateagents-admin-manager/src/pages/eContract/businessConfig/components/SelectSeal.jsx Ver fichero

@@ -0,0 +1,168 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Select, Modal, Button, Table, Divider, Tag, Input,Row,Col,Icon, Avatar, Pagination } from 'antd';
3
+import request from '../../../../utils/request';
4
+import apis from '../../../../services/apis';
5
+import moment from 'moment';
6
+import Navigate from '@/components/Navigate';
7
+
8
+const { Column, ColumnGroup } = Table;
9
+const { Search } = Input;
10
+const SelectContractTemp = props => {
11
+  const {
12
+    value,
13
+    onChange,
14
+    ...rest
15
+  } = props;
16
+
17
+  const [list, setList] = useState([]);
18
+  const [dataInfo, setDataInfo] = useState({ list: [], total: 0 });
19
+  const [visible, setVisible] = useState(false);
20
+  const [group, setGroup] = useState({ groupId: undefined, groupName: '合同标题' })
21
+  const getGroupTitle = val => {
22
+    return (list.filter(x => x.sealId == val)[0] || {}).sealImg || '请选择'
23
+  }
24
+  const updateGroup = val => setGroup({ groupId: val, groupName: getGroupTitle(val) })
25
+
26
+  const companyId = props.companyId
27
+
28
+  useEffect(() => {
29
+    getList({ pageNum: 1, pageSize: 10 })
30
+  }, [companyId]);
31
+
32
+  // 查询列表
33
+  const getList = (params) => {
34
+    request({ ...apis.taEcontract.taCompanySealList, params: { ...params, companyId:companyId } }).then((data) => {
35
+      setList(data.records || [])
36
+      setDataInfo(data)
37
+      updateGroup(companyId ? undefined : value);
38
+    })
39
+  }
40
+
41
+  const searchContractTemp = (e) => {
42
+    getList({ pageNum: 1, pageSize: 10 })
43
+  }
44
+
45
+  if (value !== group.groupId) {
46
+    updateGroup(value);
47
+  }
48
+
49
+  const handleChange = val => {
50
+    onChange(val)
51
+  }
52
+
53
+  const setData = val => {
54
+    updateGroup(val.id)
55
+    onChange(val.id)
56
+    setVisible(false)
57
+    props.onSuccess(val.name);
58
+  }
59
+
60
+  // 提交事件
61
+  const handleSubmit = (e, props) => {
62
+    e.preventDefault();
63
+    e.stopPropagation();
64
+    props.form.validateFields((err, values) => {
65
+      if (!err) {
66
+        getList({ pageNum: 1, pageSize: 10, sealName:values.sealName })
67
+      }
68
+    });
69
+  }
70
+
71
+  const changePageNum = pageNumber => {
72
+    getList({ pageNum: pageNumber, pageSize: 10, ...props.form.getFieldsValue() })
73
+  }
74
+
75
+  //重置搜索
76
+  function handleReset () {
77
+    props.form.resetFields();
78
+    getList({ pageNum: 1, pageSize: 10 })
79
+  }
80
+
81
+  const clearVal = val => {
82
+    onChange(val)
83
+  }
84
+
85
+  const columns = [
86
+    {
87
+      title: '印章编号',
88
+      dataIndex: 'sealId',
89
+      key: 'sealId',
90
+      align: 'center',
91
+      ellipsis: true,
92
+    },
93
+    {
94
+      title: '印章名称',
95
+      dataIndex: 'sealName',
96
+      key: 'sealName',
97
+      align: 'center',
98
+      ellipsis: true,
99
+    },
100
+    {
101
+      title: '印章图',
102
+      dataIndex: 'sealImg',
103
+      key: 'sealImg',
104
+      align: 'center',
105
+      ellipsis: true,
106
+      render: (_, record) => <Avatar shape="square" style={{color: 'blue',cursor: 'pointer'}} src={record.sealImg} size={64} icon="user" />,
107
+    },
108
+    {
109
+      title: '印章上传时间',
110
+      dataIndex: 'createDate',
111
+      key: 'createDate',
112
+      align: 'center',
113
+      ellipsis: true,
114
+      render: (x, row) => <><span>{`${moment(row.createDate).format('YYYY-MM-DD HH:mm:ss')}`}</span></>,
115
+    },
116
+    {
117
+      title: '操作',
118
+      align: 'center',
119
+      width: '20%',
120
+      render: (text, record) => (
121
+        <Navigate onClick={() => setData({id:record.sealId, name:record.sealName})}>选择</Navigate>
122
+      ),
123
+    },
124
+  ];
125
+
126
+  const { getFieldDecorator } = props.form
127
+
128
+  return (
129
+    <div>
130
+      <div>
131
+        <Avatar shape="square" style={{color: 'blue',cursor: 'pointer'}} src={group.groupName} size={54} icon="user" />
132
+  <a style={{marginLeft:'30px', color: '#1D74D9' }} onClick={() => setVisible(true)}>{companyId != undefined && '选择企业印章'}</a>
133
+      </div>
134
+      <Modal
135
+        title="选择企业印章"
136
+        visible={visible}
137
+        onCancel={() => setVisible(false)}
138
+        footer={[]}
139
+        width={900}
140
+      >
141
+        <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
142
+        <Form.Item>
143
+          {getFieldDecorator('sealName')(
144
+            <Input
145
+            prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
146
+            placeholder="印章名称"
147
+          />,
148
+          )}
149
+        </Form.Item>
150
+        <Form.Item>
151
+          <Button type="primary" htmlType="submit" >
152
+                 搜索
153
+          </Button>
154
+          <Button style={{ marginLeft: 8 }} onClick={handleReset}>
155
+                 重置
156
+          </Button>     
157
+        </Form.Item>
158
+      </Form>
159
+      <Table rowKey={list => list.drainageId} columns={columns} dataSource={list} pagination={false} />
160
+      <Pagination defaultCurrent={1} total={dataInfo.total} onChange={e => changePageNum(e)} current={dataInfo.current}/>
161
+      </Modal>
162
+    </div>
163
+  )
164
+}
165
+
166
+const WrappedHeader = Form.create({ name: 'SelectContractTemp' })(SelectContractTemp);
167
+
168
+export default WrappedHeader

+ 207
- 0
estateagents-admin-manager/src/pages/eContract/businessConfig/detail.jsx Ver fichero

@@ -0,0 +1,207 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker, Radio, Upload, InputNumber } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import router from 'umi/router';
5
+import moment from 'moment';
6
+import SelectCity from '../../../components/SelectButton/CitySelect'
7
+import BuildSelect2 from '../../../components/SelectButton/BuildSelect2'
8
+import LivePlatSelect from '../../../components/SelectButton/LivePlatSelect'
9
+import CitySelect3 from '../../../components/SelectButton/CitySelect3'
10
+import ImageUpload from '../../../components/XForm/ImageUpload'
11
+import Wangedit from '../../../components/Wangedit/Wangedit'
12
+import apis from '../../../services/apis';
13
+import request from '../../../utils/request';
14
+import AuthButton from '@/components/AuthButton';
15
+import SelectContractTemp from './components/SelectContractTemp';
16
+import SelectRaise from './components/SelectRaise';
17
+import SelectCompany from './components/SelectCompany';
18
+import SelectSeal from './components/SelectSeal';
19
+
20
+const { Option } = Select;
21
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
22
+
23
+
24
+const header = props => {
25
+  const contractBusinessId = props.location.query.id
26
+  const [ contractBusinessData, setContractBusinessData ] = useState({})
27
+
28
+  const [targetName, setTargetName] = useState({})
29
+  const [companyName, setCompanyName] = useState({})
30
+  const [contractTemplateName, setContractTemplateName] = useState({})
31
+  const [contractTemplateLink, setContractTemplateLink] = useState('')
32
+
33
+  if(contractBusinessId){
34
+    useEffect(() => {
35
+      getContractBusinessData(contractBusinessId);
36
+    },[])
37
+
38
+  // 查询列表
39
+  const getContractBusinessData = (contractBusinessId) => {
40
+    request({ ...apis.taEcontract.taContractBusinessById, urlData: {id: contractBusinessId} }).then((data) => {
41
+        setContractBusinessData(data)
42
+        request({ ...apis.taEcontract.taContractTemplateById, urlData: {id: data.contractTemplateId} }).then((data) => {
43
+          setContractTemplateLink(data.contractTemplateAddress)
44
+        })
45
+    }) 
46
+  }
47
+  }
48
+
49
+
50
+  const cancelPage = () =>{
51
+    router.push({
52
+      pathname: '/eContract/businessConfig/list',
53
+    });
54
+  }
55
+
56
+   //打开新页面
57
+   const openIndexImg = () => {
58
+     if(contractTemplateLink){
59
+      window.open(contractTemplateLink);
60
+     }else{
61
+       message.info('请选择合同模板');
62
+     }
63
+  }
64
+
65
+  function highlightsTypeChange(e) {
66
+    setTypeState(e.target.value)
67
+  }
68
+
69
+  function disabledDate(current) {
70
+    return current && current < moment().endOf('day');
71
+  }
72
+
73
+  function companyOnSuccess(e){
74
+    console.log(e)
75
+    setCompanyName(e)
76
+  }
77
+
78
+  function contractOnSuccess(e){
79
+    console.log('contractOnSuccess', e)
80
+    setContractTemplateName(e.name)
81
+    request({ ...apis.taEcontract.taContractTemplateById, urlData: {id: e.id} }).then((data) => {
82
+      setContractTemplateLink(data.contractTemplateAddress)
83
+      console.log(contractTemplateLink,'dddddddddd')
84
+    })
85
+  }
86
+
87
+  function targetOnSuccess(e){
88
+    console.log('targetOnSuccess', e)
89
+    setTargetName(e)
90
+  }
91
+
92
+  function sealOnSuccess(e){
93
+    console.log('sealOnSuccess', e)
94
+  }
95
+
96
+  function handleSubmit (e) {
97
+    e.preventDefault();
98
+    props.form.validateFields((err, values) => {
99
+      if (!err){
100
+        request({ ...apis.taEcontract.updateTaContractBusinessById, urlData: {id: contractBusinessId}, data: { ...values },}).then((data) => {
101
+          message.info("保存成功")
102
+          router.push({
103
+            pathname: '/eContract/businessConfig/list',
104
+          });
105
+        }).catch((err) => {
106
+          message.info(err.msg || err.message)
107
+        })
108
+      }
109
+    });
110
+  }
111
+
112
+  const { getFieldDecorator } = props.form;
113
+
114
+  return (
115
+    <>
116
+      <Form labelCol={{ span: 7 }} wrapperCol={{ span: 12 }} onSubmit={handleSubmit}>
117
+        <Form.Item label="合同标题">
118
+          {getFieldDecorator('contractTemplateId', {initialValue:contractBusinessData.contractTemplateId,
119
+            rules: [{ required: true, message: ' 请选择合同模板' }],
120
+          })(<SelectContractTemp  onSuccess={e => contractOnSuccess(e)}/>)}
121
+          {getFieldDecorator('contractTemplateName', {initialValue:contractBusinessData.contractTemplateName,
122
+            rules: [{ required: true, message: ' 请选择关联业务' }],
123
+          })(<Input  hidden={true}/>)}
124
+        </Form.Item>
125
+        <Form.Item label="合同文件">
126
+          {getFieldDecorator('contractTemplateId')}<Button type="danger" style={{marginRight:'20px'}} onClick={openIndexImg}>查看文件</Button>
127
+        </Form.Item>
128
+        <Form.Item label="关联业务类型"> 
129
+          {getFieldDecorator('targetType', {initialValue:contractBusinessData.targetType,
130
+              rules: [{ required: true, message: '请选择发布状态' }],
131
+            })(<Select placeholder="关联业务类型" style={{ width: '400px' }}>
132
+            <Option value="raise">房源认筹</Option>
133
+          </Select>)}
134
+        </Form.Item>
135
+        <Form.Item label="关联业务">
136
+          {getFieldDecorator('targetId', {initialValue:contractBusinessData.targetId,
137
+            rules: [{ required: true, message: ' 请选择关联业务' }],
138
+          })(<SelectRaise targetType={props.form.getFieldValue('targetType')} onSuccess={e => targetOnSuccess(e)}/>)}
139
+          {getFieldDecorator('targetName', {initialValue:contractBusinessData.targetName,
140
+            rules: [{ required: true, message: ' 请选择关联业务' }],
141
+          })(<Input  hidden={true}/>)}
142
+        </Form.Item>
143
+        <Form.Item label="甲方" help="系统会在业务需要时自动签所选企业印章,比如用户在签署认筹合同前系统会自动签署企业印章。">
144
+          {getFieldDecorator('companyId', {initialValue:contractBusinessData.companyId,
145
+            rules: [{ required: true, message: ' 请选择关联企业' }],
146
+          })(<SelectCompany onSuccess={e => companyOnSuccess(e)}/>)}
147
+          {getFieldDecorator('companyName', {initialValue:contractBusinessData.companyName,
148
+            rules: [{ required: true, message: ' 请选择关联业务' }],
149
+          })(<Input  hidden={true}/>)}
150
+        </Form.Item>
151
+        <Form.Item label="甲方印章" style={{marginTop:'20px'}}>
152
+          {getFieldDecorator('sealId', {initialValue:contractBusinessData.sealId,
153
+            rules: [{ required: true, message: ' 请选择企业印章' }],
154
+          })(<SelectSeal companyId={props.form.getFieldValue('companyId')} onSuccess={e => sealOnSuccess(e)}/>)}
155
+        </Form.Item>
156
+        <Form.Item label="甲方签章定位关键字" help="关键字为合同文件中的文字内容(能被ctrl+f 查找功能检索到)。法大大按此关键字进行签章位置的定位,将电子章盖在这个关键字上面。凡出现关键字的地方均可能会盖上指定用户的电子章,建议关键字在合同中保持唯一。">
157
+          {getFieldDecorator('signatoryKeywords', {initialValue:contractBusinessData.signatoryKeywords,
158
+            rules: [{ required: true, message: '请输入甲方签章定位关键字' }],
159
+          })(<Input maxLength={20} style={{width:'400px'}}/>)}
160
+        </Form.Item>
161
+        <Form.Item label="甲方关键字签章策略" style={{marginTop:'20px'}}> 
162
+          {getFieldDecorator('signatoryStrategy', {initialValue:contractBusinessData.signatoryStrategy,
163
+              rules: [{ required: true, message: '请选择甲方关键字签章策略' }],
164
+            })(<Select placeholder="甲方关键字签章策略" style={{ width: '400px' }}>
165
+            <Option value="2">最后一个关键字签章</Option>
166
+            <Option value="0">所有关键字签章</Option>
167
+            <Option value="1">第一个关键字签章</Option>
168
+          </Select>)}
169
+        </Form.Item>
170
+        <Form.Item label="乙方签章定位关键字" help="关键字为合同文件中的文字内容(能被ctrl+f 查找功能检索到)。法大大按此关键字进行签章位置的定位,将电子章盖在这个关键字上面。凡出现关键字的地方均可能会盖上指定用户的电子章,建议关键字在合同中保持唯一。">
171
+          {getFieldDecorator('customerKeywords', {initialValue:contractBusinessData.customerKeywords,
172
+            rules: [{ required: true, message: '请输入乙方签章定位关键字' }],
173
+          })(<Input maxLength={20} style={{width:'400px'}}/>)}
174
+        </Form.Item>
175
+        <Form.Item label="乙方关键字签章策略" style={{marginTop:'20px'}}> 
176
+          {getFieldDecorator('customerStrategy', {initialValue:contractBusinessData.customerStrategy,
177
+              rules: [{ required: true, message: '请选择乙方关键字签章策略' }],
178
+            })(<Select placeholder="乙方关键字签章策略" style={{ width: '400px' }}>
179
+            <Option value="2">最后一个关键字签章</Option>
180
+            <Option value="0">所有关键字签章</Option>
181
+            <Option value="1">第一个关键字签章</Option>
182
+          </Select>)}
183
+        </Form.Item>
184
+        <Form.Item label="发布状态">
185
+          {getFieldDecorator('status', {initialValue:contractBusinessData.status,
186
+              rules: [{ required: true, message: '请选择发布状态' }],
187
+            })(<Select placeholder="发布状态" style={{ width: '300px' }}>
188
+            <Option value={0}>否</Option>
189
+            <Option value={1}>是</Option>
190
+          </Select>)}
191
+        </Form.Item>
192
+        <Form.Item wrapperCol={{ span: 15, offset: 7 }}>
193
+          <Button type="primary" htmlType="submit"style={{marginRight:'20px'}}>
194
+            确定
195
+          </Button>
196
+          <Button onClick={() => router.go(-1)}>
197
+            取消
198
+          </Button>
199
+        </Form.Item>
200
+      </Form>
201
+    </>
202
+  )
203
+}
204
+
205
+const WrappedHeader = Form.create({ name: 'header' })(header);
206
+
207
+export default WrappedHeader

+ 277
- 0
estateagents-admin-manager/src/pages/eContract/businessConfig/list.jsx Ver fichero

@@ -0,0 +1,277 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import router from 'umi/router';
5
+import moment from 'moment';
6
+import AuthButton from '@/components/AuthButton';
7
+import withActions from '@/components/ActionList';
8
+import EditIcon from '@/components/EditIcon';
9
+import styles from '../../style/GoodsList.less';
10
+import SelectCity from '../../../components/SelectButton/CitySelect'
11
+import BuildSelect from '../../../components/SelectButton/BuildSelect'
12
+import apis from '../../../services/apis';
13
+import request from '../../../utils/request';
14
+import Navigate from '@/components/Navigate';
15
+
16
+
17
+const { Option } = Select;
18
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
19
+
20
+const header = props => {
21
+  const sampleId  = props.location.query.id;
22
+  const sampleName = props.location.query.sampleName;
23
+  const [data, setData] = useState({})
24
+  const [demend, setDemend] = useState({})
25
+  const [contractBusinessList, setContractBusinessList] = useState([])
26
+  const [contractBusinessIndexList, setContractBusinessIndexList] = useState([])
27
+  const [batchDel, setBatchDel] = useState({visable:false,demandIds:''})
28
+  const [addDemand, setAddDemand] = useState({visable:false})
29
+
30
+  useEffect(() => {
31
+    if(sampleId){
32
+      getList({ pageNum: 1, pageSize: 10, sampleId: sampleId });
33
+    }else{
34
+      getList({ pageNum: 1, pageSize: 10});
35
+    }
36
+    
37
+  }, [])
38
+
39
+  // 查询列表
40
+  const getList = (params) => {
41
+    console.log(params);
42
+    request({ ...apis.taEcontract.taContractBusinessList, params: { ...params } }).then((data) => {
43
+      console.log(data)
44
+      setData(data)
45
+    })
46
+  }
47
+
48
+  // 跳转到编辑
49
+  const toDetail = rowData => () => {
50
+    if(rowData) {
51
+      router.push({
52
+      pathname: '/eContract/businessConfig/detail',
53
+      query: {
54
+        id: rowData.contractBusinessId,
55
+      },
56
+    });
57
+      return
58
+    }
59
+  }
60
+
61
+  /**
62
+   *
63
+   *
64
+   * @param {*} props
65
+   * @returns
66
+   */
67
+
68
+  const columns = [
69
+    {
70
+      title: '合同标题',
71
+      dataIndex: 'contractTemplateName',
72
+      key: 'contractTemplateName',
73
+      align: 'center',
74
+      render:  (x, row) => <Navigate onClick={toDetail(row)}>{row.contractTemplateName}</Navigate>,
75
+    },
76
+    {
77
+      title: '关联业务类型',
78
+      dataIndex: 'targetType',
79
+      key: 'targetType',
80
+      align: 'center',
81
+      render: (x, row) => <><span>{row.targetType === 'raise' ? '房源认筹' : ''}</span></>
82
+    },
83
+    {
84
+      title: '关联业务标题',
85
+      dataIndex: 'targetName',
86
+      key: 'targetName',
87
+      align: 'center',
88
+    },
89
+    {
90
+      title: '甲方',
91
+      dataIndex: 'companyName',
92
+      key: 'companyName',
93
+      align: 'center',
94
+    },
95
+    {
96
+      title: '发布状态',
97
+      dataIndex: 'status',
98
+      key: 'status',
99
+      align: 'center',
100
+      render: (text, records) => {
101
+        if (records.status === 1) { return '是' }
102
+        if (records.status === 0) { return '否' }
103
+      },
104
+    },
105
+    {
106
+      title: '新增时间',
107
+      dataIndex: 'createDate',
108
+      key: 'createDate',
109
+      align: 'center',
110
+      render: (x, row) => <><span>{`${moment(row.createDate).format('YYYY-MM-DD HH:mm:ss')}`}</span></>
111
+    },
112
+    {
113
+      title: '修改时间',
114
+      dataIndex: 'updateDate',
115
+      key: 'updateDate',
116
+      align: 'center',
117
+      render: (x, row) => <><span>{`${moment(row.updateDate).format('YYYY-MM-DD HH:mm:ss')}`}</span></>
118
+    },
119
+    {
120
+      title: '操作',
121
+      dataIndex: 'handle',
122
+      key: 'handle',
123
+      align: 'center',
124
+      render: withActions((text, record) => [
125
+        <AuthButton name="admin.eContractBusiness.detail.get" noRight={null}>
126
+           <EditIcon text="查看详情" type="look" onClick={toDetail(record)} />
127
+          {/* <a style={{ color: '#66B3FF' }} onClick={toDetail(record)} >查看详情</a> */}
128
+        </AuthButton>,
129
+      ])
130
+    },
131
+  ];
132
+  
133
+  const rowSelection = {
134
+    selectedRowKeys: contractBusinessIndexList,
135
+    onChange: (selectedRowKeys, selectedRows) => {
136
+      setContractBusinessList(selectedRows)
137
+      setContractBusinessIndexList(selectedRowKeys)
138
+    },
139
+  };
140
+
141
+  const changePageNum = pageNumber => {
142
+    getList({ pageNum: pageNumber, pageSize: 10, ...props.form.getFieldsValue() })
143
+  }
144
+
145
+  // 提交事件
146
+  const handleSubmit = (e, props) => {
147
+    e.preventDefault();
148
+    props.form.validateFields((err, values) => {
149
+      if (!err) {
150
+        getList({ pageNum: 1, pageSize: 10, ...values })
151
+      }
152
+    });
153
+  }
154
+
155
+  //重置搜索
156
+  function handleReset () {
157
+    props.form.resetFields();
158
+    getList({ pageNum: 1, pageSize: 10 })
159
+  }
160
+
161
+  function showBatchDel(e){
162
+  
163
+    if (demandIds.length <= 0){
164
+      message.info("请选择数据");
165
+      return;
166
+    }
167
+    setBatchDel(e);
168
+    if(!e.visable){
169
+      getList()
170
+    }
171
+  }
172
+
173
+  function batchDelTaContractBusiness(){
174
+    console.log(contractBusinessList)
175
+    if (contractBusinessList.length <= 0){
176
+      message.info('请至少选择一条数据')
177
+      return;
178
+    }
179
+    Modal.confirm({
180
+      title: '确认将所选的' + contractBusinessList.length + '条业务配置删除?',
181
+      okText: '确认',
182
+      cancelText: '取消',
183
+      onOk () {
184
+        request({ ...apis.taEcontract.batchDelTaContractBusiness, data: {contractBusinessList} }).then((data) => {
185
+          message.info('操作成功!')
186
+          setContractBusinessIndexList([])
187
+          getList({ pageNum: 1, pageSize: 10 })
188
+        }).catch((err) => {
189
+          console.log('111111', err)
190
+        })
191
+      }
192
+    });
193
+  }
194
+
195
+  function addContractManage(){
196
+    router.push({
197
+      pathname: '/eContract/businessConfig/add',
198
+    });
199
+  }
200
+
201
+  const { getFieldDecorator } = props.form
202
+  return (
203
+
204
+    <>
205
+      <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
206
+        <Form.Item>
207
+          {getFieldDecorator('contractName')(
208
+            <Input
209
+            prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
210
+            placeholder="合同标题"
211
+          />,
212
+          )}
213
+        </Form.Item>
214
+        <Form.Item>
215
+          {getFieldDecorator('targetType')(
216
+            <Select style={{ width: '180px' }} placeholder="业务类型">
217
+                <option value="">全部</option>
218
+                <option value="raise">房源认筹</option>
219
+            </Select>
220
+          )}
221
+        </Form.Item>
222
+        <Form.Item>
223
+          {getFieldDecorator('targetName')(
224
+            <Input
225
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
226
+              placeholder="业务标题"
227
+            />,
228
+          )}
229
+        </Form.Item>
230
+        <Form.Item>
231
+          {getFieldDecorator('companyName')(
232
+            <Input
233
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
234
+              placeholder="甲方"
235
+            />,
236
+          )}
237
+        </Form.Item>
238
+        <Form.Item>
239
+          {getFieldDecorator('status')(
240
+            <Select style={{ width: '180px' }} placeholder="发布状态">
241
+                <option value="">全部</option>
242
+                <option value='1'>是</option>
243
+                <option value='0'>否</option>
244
+            </Select>
245
+          )}
246
+        </Form.Item>
247
+        
248
+        <Form.Item>
249
+            <AuthButton name="admin.taShareActivity.search" noRight={null}>
250
+                <Button type="primary" htmlType="submit" className={styles.searchBtn}>
251
+                    搜索
252
+                </Button>
253
+            </AuthButton>
254
+            <AuthButton name="admin.taShareActivity.search" noRight={null}>
255
+                <Button style={{ marginLeft: 8 }} onClick={handleReset}>
256
+                        重置
257
+                </Button>
258
+            </AuthButton>
259
+        </Form.Item>
260
+      </Form>
261
+      <AuthButton name="admin.eContractBusiness.add.post" noRight={null}>
262
+        <Button type="danger" onClick={() => addContractManage()} className={styles.addBtn}>新增</Button>
263
+      </AuthButton>
264
+      <AuthButton name="admin.eContractBusiness.del" noRight={null}>
265
+        <Button type="primary" onClick={() => batchDelTaContractBusiness()} className={styles.addBtn} style={{marginLeft:'30px'}}>删除</Button>
266
+      </AuthButton>
267
+      <Table rowSelection={rowSelection}
268
+        style={{marginTop:'30px'}} dataSource={data.records} columns={columns} pagination={false} rowKey="activityList" />
269
+      <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
270
+        <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} current={data.current} />
271
+      </div>
272
+    </>
273
+  )
274
+}
275
+const WrappedHeader = Form.create({ name: 'header' })(header);
276
+
277
+export default WrappedHeader

+ 141
- 0
estateagents-admin-manager/src/pages/eContract/manage/edit.jsx Ver fichero

@@ -0,0 +1,141 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker, Row, Col } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import Styles from './styles.less';
5
+import router from 'umi/router';
6
+import moment from 'moment';
7
+
8
+import apis from '../../../services/apis';
9
+import request from '../../../utils/request';
10
+
11
+
12
+import AuthButton from '@/components/AuthButton';
13
+
14
+
15
+const header = props => {
16
+
17
+    const id = props.location.query.id
18
+
19
+    const [data, setData] = useState({})
20
+
21
+    useEffect(() => {
22
+
23
+        getList(id);
24
+
25
+
26
+    }, [])
27
+
28
+    const getList = (id) => {
29
+        request({ ...apis.manage.detail, urlData: { id: id } }).then((data) => {
30
+            setData(data)
31
+        })
32
+    }
33
+
34
+    const onArchives = () => {
35
+        request({
36
+            ...apis.manage.archives,
37
+            urlData: { id: id },
38
+            data: { contractId: parseInt(id), archives: true }
39
+        }).then((data) => {
40
+            setData(data)
41
+            message.info("归档成功")
42
+
43
+        })
44
+    }
45
+
46
+    const datas = [
47
+        {
48
+            name: "合同标题",
49
+            value: data.contractName
50
+        },
51
+        {
52
+            name: "关联业务类型",
53
+            value: data.targetType,
54
+            render: () => <><span>{data.targetType == "raise" ? "房源认筹" : ""}</span></>,
55
+        },
56
+        {
57
+            name: "关联业务",
58
+            value: data.targetName
59
+
60
+        },
61
+        {
62
+            name: "关联单据类型",
63
+            value: data.invoiceTargetType,
64
+            render: () => <><span>{data.invoiceTargetType == "raise_record" ? "认筹单" : ""}</span></>,
65
+        },
66
+        {
67
+            name: "关联单据编号",
68
+            value: data.invoiceTargetId
69
+        },
70
+        {
71
+            name: "甲方名称",
72
+            value: data.signatoryName,
73
+
74
+        },
75
+        {
76
+            name: "甲方签署时间",
77
+            value: data.signatoryTime,
78
+            render: <><span>{data.signatoryTime ? moment(data.signatoryTime).format('YYYY-MM-DD HH:mm:ss') : ''}</span></>
79
+        },
80
+        {
81
+            name: "乙方名称",
82
+            value: data.customerName
83
+        },
84
+        {
85
+            name: "乙方手机号",
86
+            value: data.customerTel
87
+        },
88
+        {
89
+            name: "乙方身份证号",
90
+            value: data.customerIdcard
91
+        },
92
+        {
93
+            name: "乙方签署时间",
94
+            value: data.customerTime,
95
+            render: <><span>{data.customerTime ? moment(data.customerTime).format('YYYY-MM-DD HH:mm:ss') : ''}</span></>
96
+        },
97
+        {
98
+            name: "已签署合同",
99
+            // value:data.,
100
+            render: (x, row) => <><a type="button" className={Styles.btn} href={data.contractViewUrl} target="_blank">查看合同</a> <a href={data.contractDownloadUrl} download="234.pdf" style={{ color: '#1D74D9', marginLeft: '30px' }}>下载合同</a> </>
101
+        },
102
+        {
103
+            name: "是否归档",
104
+            value: data.archives,
105
+            render: (x, row) => <><span>{data.archives ? '是' : '否'}</span>{!data.archives && <a onClick={() => onArchives(data.contractId)} style={{ color: '#1D74D9', marginLeft: '30px' }}>归档</a>}  </>
106
+        },
107
+        {
108
+            name: "归档时间",
109
+            value: data.archivesTime,
110
+            render: <><span>{data.archivesTime ? moment(data.archivesTime).format('YYYY-MM-DD HH:mm:ss') : ''}</span></>
111
+        },
112
+    ]
113
+
114
+
115
+    return (
116
+
117
+        <>
118
+            <div align="right"><Button onClick={() => router.go(-1)}>返回</Button></div>
119
+
120
+            {datas.map((x) => {
121
+                return <Row style={{ margin: '20px 0' }}>
122
+                    <Col span={5} className={Styles.title} align="right" >
123
+                        {x.name}
124
+                    </Col>
125
+                    <Col span={9} offset={2} className={Styles.text}>
126
+                        {
127
+                            x.render ? typeof x.render === 'function' ? x.render(props) : x.render : x.value
128
+                        }
129
+                    </Col>
130
+                    <Col span={2} offset={4}>
131
+                    </Col>
132
+                </Row>
133
+            })}
134
+        
135
+
136
+        </>
137
+    )
138
+}
139
+
140
+
141
+export default header

+ 248
- 0
estateagents-admin-manager/src/pages/eContract/manage/list.jsx Ver fichero

@@ -0,0 +1,248 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, Table, Pagination, DatePicker } from 'antd';
3
+import router from 'umi/router';
4
+import moment from 'moment';
5
+import withActions from '@/components/ActionList';
6
+import EditIcon from '@/components/EditIcon';
7
+import AuthButton from '@/components/AuthButton';
8
+import styles from '../../style/GoodsList.less';
9
+import apis from '../../../services/apis';
10
+import request from '../../../utils/request';
11
+import Navigate from '@/components/Navigate';
12
+
13
+
14
+const { RangePicker } = DatePicker;
15
+
16
+const header = props => {
17
+  const [data, setData] = useState({})
18
+
19
+  useEffect(() => {
20
+    getList({ pageNum: 1, pageSize: 10 });
21
+  }, [])
22
+
23
+  // 查询列表
24
+  const getList = (params) => {
25
+    request({ ...apis.manage.list, params: { ...params } }).then((data) => {
26
+      console.log(data)
27
+      setData(data)
28
+    })
29
+  }
30
+
31
+  // 跳转到编辑
32
+  const toDetail = id => () => {
33
+    if (id) {
34
+      router.push({
35
+        pathname: '/eContract/manage/edit',
36
+        query: {
37
+          id,
38
+        },
39
+      });
40
+
41
+    }
42
+  }
43
+
44
+  /**
45
+   *
46
+   *
47
+   * @param {*} props
48
+   * @returns
49
+   */
50
+
51
+  const columns = [
52
+    {
53
+      title: '合同标题',
54
+      dataIndex: 'contractName',
55
+      key: 'contractName',
56
+      align: 'center',
57
+      render:  (x, row) => <Navigate onClick={toDetail(row.contractId)}>{row.contractName}</Navigate>,
58
+    },
59
+    {
60
+      title: '甲方名称',
61
+      dataIndex: 'signatoryName',
62
+      key: 'signatoryName',
63
+      align: 'center',
64
+
65
+    },
66
+    {
67
+      title: '甲方是否签署',
68
+      align: 'center',
69
+      render: (x, row) => <><span>{row.signatoryTime ? '是' : '否'}</span></>
70
+    },
71
+    {
72
+      title: '甲方签署时间',
73
+      dataIndex: 'signatoryTime',
74
+      key: 'signatoryTime',
75
+      align: 'center',
76
+      render: (x, row) => <><span>{row.signatoryTime ? `${moment(row.signatoryTime).format('YYYY-MM-DD HH:mm:ss')}` : ''}</span></>
77
+    },
78
+    {
79
+      title: '乙方名称',
80
+      dataIndex: 'customerName',
81
+      key: 'customerName',
82
+      align: 'center',
83
+
84
+    },
85
+    {
86
+      title: '乙方是否签署',
87
+      align: 'center',
88
+      render: (x, row) => <><span>{row.customerTime ? '是' : '否'}</span></>
89
+
90
+    },
91
+    {
92
+      title: '乙方签署时间',
93
+      dataIndex: 'customerTime',
94
+      key: 'customerTime',
95
+      align: 'center',
96
+      render: (x, row) => <><span>{row.customerTime ? `${moment(row.customerTime).format('YYYY-MM-DD HH:mm:ss')}` : ''}</span></>
97
+    },
98
+    {
99
+      title: '是否归档',
100
+      dataIndex: 'archives',
101
+      key: 'archives',
102
+      align: 'center',
103
+      render: (x, row) => <><span>{row.archives ? '是' : '否'}</span></>
104
+
105
+    },
106
+    {
107
+      title: '归档时间',
108
+      dataIndex: 'archivesTime',
109
+      key: 'archivesTime',
110
+      align: 'center',
111
+      render: (x, row) => <><span>{row.archivesTime ? `${moment(row.archivesTime).format('YYYY-MM-DD HH:mm:ss')}` : ''}</span></>
112
+    },
113
+    {
114
+      title: '操作',
115
+      dataIndex: 'handle',
116
+      key: 'handle',
117
+      align: 'center',
118
+      render: withActions((text, record) => [
119
+        <AuthButton name="admin.eContractManager.detail.get" noRight={null}>
120
+          <EditIcon text="查看详情" type="look" onClick={toDetail(record.contractId)} />
121
+        </AuthButton>,
122
+      ]),
123
+    },
124
+  ];
125
+
126
+  const rowSelection = {
127
+    onChange: (selectedRowKeys, selectedRows) => {
128
+      console.log('selectedRowKeys:', selectedRowKeys, 'selectedRows: ', selectedRows);
129
+      setDemandIds(selectedRows)
130
+    },
131
+  };
132
+
133
+  const changePageNum = pageNumber => {
134
+    getList({ pageNum: pageNumber, pageSize: 10, ...props.form.getFieldsValue() })
135
+  }
136
+
137
+  // 提交事件
138
+  const handleSubmit = (e, props) => {
139
+    e.preventDefault();
140
+    props.form.validateFields((err, values) => {
141
+      if (!err) {
142
+        const { archivesDate, ...submitValue } = values
143
+        if (null != archivesDate && archivesDate.length > 0) {
144
+          const [archivesStartDate, archivesEndDate] = archivesDate
145
+          submitValue.archivesStartDate = moment(archivesStartDate).format('YYYY-MM-DD');
146
+          submitValue.archivesEndDate = moment(archivesEndDate).format('YYYY-MM-DD');
147
+        }
148
+        console.log(submitValue)
149
+        getList({ pageNum: 1, pageSize: 10, ...submitValue })
150
+      }
151
+    });
152
+  }
153
+
154
+  // 重置搜索
155
+  function handleReset() {
156
+    props.form.resetFields();
157
+    getList({ pageNum: 1, pageSize: 10 })
158
+  }
159
+
160
+
161
+  const { getFieldDecorator } = props.form
162
+  return (
163
+
164
+    <>
165
+      <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
166
+        <Form.Item>
167
+          {getFieldDecorator('contractName')(
168
+            <Input
169
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
170
+              placeholder="合同标题"
171
+            />,
172
+          )}
173
+        </Form.Item>
174
+        <Form.Item>
175
+          {getFieldDecorator('signatoryName')(
176
+            <Input
177
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
178
+              placeholder="请输入甲方名称"
179
+            />,
180
+          )}
181
+        </Form.Item>
182
+        <Form.Item>
183
+          {getFieldDecorator('customerName')(
184
+            <Input
185
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
186
+              placeholder="请输入乙方名称"
187
+            />,
188
+          )}
189
+        </Form.Item>
190
+        <Form.Item>
191
+          {getFieldDecorator('signatoryStatus')(
192
+            <Select style={{ width: '180px' }} placeholder="甲方是否签署">
193
+              <option value="">全部</option>
194
+              <option value="1">是</option>
195
+              <option value="0">否</option>
196
+            </Select>,
197
+          )}
198
+        </Form.Item>
199
+        <Form.Item>
200
+          {getFieldDecorator('customerStatus')(
201
+            <Select style={{ width: '180px' }} placeholder="乙方是否签署">
202
+              <option value="">全部</option>
203
+              <option value="1">是</option>
204
+              <option value="0">否</option>
205
+            </Select>,
206
+          )}
207
+        </Form.Item>
208
+        <Form.Item>
209
+          {getFieldDecorator('archives')(
210
+            <Select style={{ width: '180px' }} placeholder="是否归档">
211
+              <option value="">全部</option>
212
+              <option value="1">是</option>
213
+              <option value="0">否</option>
214
+            </Select>,
215
+          )}
216
+        </Form.Item>
217
+
218
+        <Form.Item>
219
+
220
+          {getFieldDecorator('archivesDate')(
221
+            <RangePicker placeholder={['归档开始时间', '归档结束时间']} />,
222
+          )}
223
+        </Form.Item>
224
+        <Form.Item>
225
+          <AuthButton name="admin.taShareActivity.search" noRight={null}>
226
+            <Button type="primary" htmlType="submit" className={styles.searchBtn}>
227
+              搜索
228
+                </Button>
229
+          </AuthButton>
230
+          <AuthButton name="admin.taShareActivity.search" noRight={null}>
231
+            <Button style={{ marginLeft: 8 }} onClick={handleReset}>
232
+              重置
233
+                </Button>
234
+          </AuthButton>
235
+        </Form.Item>
236
+      </Form>
237
+
238
+
239
+      <Table style={{ marginTop: '30px' }} dataSource={data.records} columns={columns} pagination={false} rowKey="activityList" />
240
+      <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
241
+        <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} current={data.current} />
242
+      </div>
243
+    </>
244
+  )
245
+}
246
+const WrappedHeader = Form.create({ name: 'header' })(header);
247
+
248
+export default WrappedHeader

+ 44
- 0
estateagents-admin-manager/src/pages/eContract/manage/styles.less Ver fichero

@@ -0,0 +1,44 @@
1
+.title {
2
+    height     : 45px;
3
+    font-size  : 16px;
4
+    font-family: PingFangSC-Regular, PingFang SC;
5
+    font-weight: 400;
6
+    color      : rgba(102, 102, 102, 1);
7
+    line-height: 45px;
8
+   
9
+}
10
+.text {
11
+    font-size  : 16px;
12
+    font-family: PingFangSC-Regular, PingFang SC;
13
+    // font-weight: 400;
14
+    color      : rgba(51, 51, 51, 1);
15
+    line-height: 45px;
16
+}
17
+
18
+.btn {
19
+    width        : 140px;
20
+    height       : 45px;
21
+    background   : rgba(255, 126, 72, 1);
22
+    border-radius: 7px;
23
+    line-height  : 43px;
24
+    font-size    : 20px;
25
+    font-family  : PingFangSC-Regular, PingFang SC;
26
+    font-weight  : 400;
27
+    color        : rgba(255, 255, 255, 1);
28
+    text-align: center;
29
+}
30
+.btn:hover{
31
+    color        : rgba(255, 255, 255, 1);
32
+}
33
+
34
+.rebtn {
35
+    width:140px;
36
+    height:45px;
37
+    background:rgba(255,255,255,1);
38
+    border-radius:7px;
39
+    border:1px solid rgba(156,156,156,1);
40
+    font-size:20px;
41
+font-weight:400;
42
+color:rgba(102,102,102,1);
43
+line-height:28px;
44
+}

+ 156
- 0
estateagents-admin-manager/src/pages/eContract/template/add.jsx Ver fichero

@@ -0,0 +1,156 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Upload, Input, Modal, Menu, Dropdown, Button, Icon, message, Table, Divider, Tag, Select, Form, Alert } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import XForm, { FieldTypes } from '../../../components/XForm';
5
+import router from 'umi/router';
6
+import apis from '../../../services/apis';
7
+import request from '../../../utils/request';
8
+import { fetch } from '../../../utils/request';
9
+import moment from 'moment';
10
+
11
+const header = props => {
12
+
13
+  const [data, setData] = useState({})
14
+  const [flag, setFlag] = useState({})
15
+  const [uploadTip, setUploadTip] = useState({})
16
+  const [loading, setLoading] = useState({})
17
+  const uploadFile = fetch(apis.image.upload)
18
+
19
+
20
+  useEffect(() => {
21
+    setFlag(false);
22
+    setUploadTip("请选择合同文件")
23
+    setLoading(false)
24
+  }, []);
25
+
26
+  const upload = () => {
27
+    console.log("上传")
28
+  }
29
+
30
+  const removeFile = () => {
31
+    console.log("删除文件")
32
+  }
33
+
34
+  const uploaderProps = {
35
+    name: 'file',
36
+    accept: '.pdf',
37
+    showUploadList: true,
38
+    customRequest({
39
+      action,
40
+      file,
41
+      headers,
42
+      onError,
43
+      onProgress,
44
+      onSuccess,
45
+      withCredentials,
46
+    }) {
47
+      const data = new FormData()
48
+      data.append('file', file)
49
+
50
+      uploadFile({ data }).then((img) => {
51
+        setFlag(true)
52
+        setUploadTip("上传成功")
53
+        setData({
54
+          contractTemplateAddress: img
55
+        })
56
+        onSuccess(img, file)
57
+      }).catch(onError);
58
+
59
+      return {
60
+        abort() {
61
+          console.log('upload progress is aborted.');
62
+        },
63
+      };
64
+    },
65
+    onRemove(file) {
66
+      setFlag(false)
67
+      setUploadTip("请选择合同文件")
68
+    }
69
+  }
70
+
71
+  const fields = [
72
+    {
73
+      label: '合同标题',
74
+      name: 'contractTemplateName',
75
+      type: FieldTypes.Text,
76
+      value: data.contractTemplateName,
77
+      rules: [
78
+        { required: true, message: '标题长度20字以内不能有空格', pattern: new RegExp('^[^ ]+$') },
79
+        { max: 20, message: '标题长度不能超过20个字符' }
80
+      ],
81
+      placeholder: "标题长度20字以内不能有空格"
82
+    },
83
+    {
84
+      label: '合同文件',
85
+      name: 'contractTemplateAddress',
86
+      // type: FieldTypes.text,
87
+      value: data.contractTemplateAddress,
88
+      // beforeUpload: (e) => photoBeforeUpload(e),
89
+      rules: [
90
+        { required: true, message: '请选择合同文件' },
91
+      ],
92
+      render: <div><Upload beforeUpload={beforeUpload} {...uploaderProps}><Button disabled={flag}>{uploadTip}</Button></Upload></div>,
93
+      help: <div>仅支持pdf格式,合同必须按规则生成,否则无法正确签章。未按规则生成合同导致的问题,致云免除相关责任。详细要求查看
94
+        <a href='https://easydoc.xyz/s/24703398/3SqDkJDw/odnmIIwl' style={{ color: '#66B3FF' }} target='_blank'>《合同模板制作要求》</a></div>
95
+    },
96
+
97
+  ]
98
+
99
+  function beforeUpload(file) {
100
+    console.log(file, 'file')
101
+    return new Promise((resolve, reject) => {
102
+      if (file.type === 'application/pdf') {
103
+          resolve(file)
104
+      } else {
105
+        message.info('仅支持PDF格式')
106
+        reject()
107
+      }
108
+    })
109
+  }  
110
+
111
+  const handleSubmit = (values) => {
112
+    let submitValues = values;
113
+    submitValues.contractTemplateAddress = data.contractTemplateAddress
114
+
115
+    props.form.validateFields((err, values) => {
116
+      console.log(values)
117
+      if (!err) {
118
+        request({ ...apis.taEcontract.addContractTemplate, data: { ...submitValues }, }).then((data) => {
119
+          router.push({
120
+            pathname: '/eContract/template/list',
121
+            query: {
122
+              //   salesBatchId: data.salesBatchId,
123
+            },
124
+          });
125
+        }).catch((err) => {
126
+          message.info(err.msg || err.message)
127
+        })
128
+      }
129
+    });
130
+  }
131
+  //model
132
+  const handleShowModel = val => {
133
+    setVisible(true);
134
+  }
135
+
136
+  const handleCancel = val => {
137
+    setVisible(false);
138
+  }
139
+
140
+  const cancelPage = () => {
141
+    router.push({
142
+      pathname: '/eContract/template/list',
143
+    });
144
+  }
145
+
146
+  return (
147
+    <>
148
+      <div>
149
+        <XForm onSubmit={handleSubmit} onCancel={cancelPage} fields={fields}></XForm>
150
+      </div>
151
+    </>
152
+  )
153
+}
154
+
155
+const WrappedNormalLoginForm = Form.create({ name: 'header' })(header);
156
+export default WrappedNormalLoginForm

+ 49
- 0
estateagents-admin-manager/src/pages/eContract/template/detail.jsx Ver fichero

@@ -0,0 +1,49 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker, InputNumber, Checkbox, Row, Col } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import XForm, { FieldTypes } from '../../../components/XForm';
5
+import router from 'umi/router';
6
+import moment from 'moment';
7
+import apis from '../../../services/apis';
8
+import request from '../../../utils/request';
9
+import Navigate from '@/components/Navigate';
10
+
11
+const header = props => {
12
+  const templateId = props.location.query.id;
13
+  const [data, setData] = useState({})
14
+
15
+  useEffect(() => {
16
+    getData(templateId);
17
+  }, [])
18
+
19
+  const getData = (templateId) => {
20
+    request({ ...apis.taEcontract.getContractTemplate, urlData: { id: templateId } }).then((data) => {
21
+      setData(data)
22
+      props.form.setFieldsValue(data)
23
+    })
24
+  }
25
+
26
+  const toCancel = () => {
27
+    router.go(-1)
28
+  }
29
+
30
+  return (
31
+    <>
32
+      <div align="right"><Button onClick={() => toCancel()}>返回</Button></div>
33
+
34
+      <Form labelCol={{ span: 6 }} wrapperCol={{ span: 14 }} style={{ position: 'relative' }}>
35
+        <Form.Item label="合同标题">
36
+          <span>{data.contractTemplateName}</span>
37
+        </Form.Item>
38
+        <Form.Item label="合同文件">
39
+          <div>
40
+            <Navigate to={data.contractTemplateAddress}>查看文件</Navigate>
41
+          </div>
42
+        </Form.Item>
43
+      </Form>
44
+    </>
45
+  )
46
+}
47
+
48
+const WrappedHeader = Form.create({ name: 'header' })(header);
49
+export default WrappedHeader

+ 199
- 0
estateagents-admin-manager/src/pages/eContract/template/list.jsx Ver fichero

@@ -0,0 +1,199 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker, notification } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import router from 'umi/router';
5
+import moment from 'moment';
6
+import styles from '../../style/GoodsList.less';
7
+import SelectCity from '../../../components/SelectButton/CitySelect'
8
+import BuildSelect from '../../../components/SelectButton/BuildSelect'
9
+import apis from '../../../services/apis';
10
+import request from '../../../utils/request';
11
+import AuthButton from '@/components/AuthButton';
12
+import withActions from '@/components/ActionList';
13
+import EditIcon from '@/components/EditIcon';
14
+import Navigate from '@/components/Navigate';
15
+// import RaiseHelpDoc from '../edit/components/RaiseHelpDoc';
16
+
17
+const { Option } = Select;
18
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
19
+ 
20
+const header = props => {
21
+  // eslint-disable-next-line react-hooks/rules-of-hooks
22
+  const [data, setData] = useState({ list: [], total: 0 })
23
+  //   const [page, changePage] = useState({})
24
+  const [contractList, setContractList] = useState([])
25
+  const [time, setTime] = useState('')
26
+  const [showHelp, setShowHelp] = useState(false)
27
+
28
+  // 查询列表
29
+  const getList = params => {
30
+    request({ ...apis.taEcontract.listContractTemplate, params: { ...params } }).then(data => {
31
+      console.log(data)
32
+      setData(data)
33
+    })
34
+  }
35
+
36
+  // eslint-disable-next-line react-hooks/rules-of-hooks
37
+  useEffect(() => {
38
+    getList({ pageNum: 1, pageSize: 10 });
39
+  }, [])
40
+
41
+  const toAdd = rowData => () => {
42
+    router.push({
43
+      pathname: '/eContract/template/add',
44
+    });
45
+  }
46
+
47
+  function openNotificationWithIcon(type, message) {
48
+    notification[type]({
49
+      message,
50
+      description:
51
+        '',
52
+    });
53
+  }
54
+
55
+  const toDel = rowData => () =>{
56
+    if(contractList.length < 1){
57
+      openNotificationWithIcon('error', '请先选择需要删除的合同模板')
58
+      return
59
+    }
60
+
61
+    Modal.confirm({
62
+      title: '确定将所选的'+ contractList.length +'条合同模板删除?',
63
+      okText: '确定',
64
+      cancelText: '取消',
65
+      onOk () {
66
+        console.log(contractList,'contractList');
67
+        request({ ...apis.taEcontract.batchDeleteContractTemplate, data: contractList, }).then((data) => {
68
+          message.info("操作成功")
69
+          getList({ pageNum: 1, pageSize: 10 });
70
+        }).catch((err) => {
71
+          // message.info(err.msg)
72
+        })
73
+      },
74
+    });
75
+  }
76
+
77
+  const toDetail = (record) => () => {
78
+    router.push({
79
+        pathname: '/eContract/template/detail',
80
+        query: {
81
+          id: record.contractTemplateId
82
+        },
83
+    });
84
+}
85
+
86
+  /**
87
+   *
88
+   *
89
+   * @param {*} props
90
+   * @returns
91
+   */
92
+  const columns = [
93
+    {
94
+      title: '合同标题',
95
+      dataIndex: 'contractTemplateName',
96
+      key: 'contractTemplateName',
97
+      align: 'center',
98
+      render:  (x, row) => <Navigate onClick={toDetail(row)}>{row.contractTemplateName}</Navigate>,
99
+    },
100
+    {
101
+      title: '新增时间',
102
+      dataIndex: 'createDate',
103
+      key: 'createDate',
104
+      align: 'center',
105
+      render: (x, row) => <><span>{`${moment(row.createDate).format('YYYY-MM-DD HH:mm:ss')}`}</span></>,
106
+    },
107
+    {
108
+      title: '操作',
109
+      dataIndex: '',
110
+      key: '',
111
+      align: 'center',
112
+      render: withActions((text, record) => [(
113
+          <AuthButton name="admin.eContractTemplate.detail.get" noRight={null}>
114
+            <EditIcon type="look" text="查看详情" onClick={toDetail(record)}></EditIcon>
115
+          </AuthButton>
116
+      ),])
117
+    },
118
+  ];
119
+  const getSignList = dynamicId => {
120
+    router.push({
121
+      pathname: '/activity/SignList',
122
+      query: {
123
+        dynamicId,
124
+      },
125
+    });
126
+  }
127
+
128
+  const changePageNum = pageNumber => {
129
+    getList({ pageNum: pageNumber, pageSize: 10, ...props.form.getFieldsValue() })
130
+  }
131
+
132
+  const rowSelection = {
133
+    onChange: (selectedRowKeys, selectedRows) => {
134
+      console.log('selectedRowKeys:', selectedRowKeys, 'selectedRows: ', selectedRows);
135
+      setContractList(selectedRows)
136
+    },
137
+  };
138
+
139
+  // 提交事件
140
+  const handleSubmit = e => {
141
+    e.preventDefault();
142
+    props.form.validateFields((err, values) => {
143
+      if (!err) {      
144
+        getList({ pageNum: 1, pageSize: 10, ...values })
145
+      }
146
+    });
147
+  }
148
+
149
+  // 重置搜索
150
+  function handleReset () {
151
+    props.form.resetFields();
152
+    setTime('')
153
+    getList({ pageNum: 1, pageSize: 10 })
154
+  }
155
+
156
+  const { getFieldDecorator } = props.form
157
+  return (
158
+
159
+    <>
160
+      {/* style={{ display: 'none' }} */}
161
+      <div id="qrcode"></div>
162
+      <Form layout="inline" onSubmit={e => handleSubmit(e)}>
163
+        <Form.Item>
164
+          {getFieldDecorator('contractTemplateName')(
165
+             <Input
166
+             prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
167
+             placeholder="合同标题"
168
+           />,
169
+          )}
170
+        </Form.Item>
171
+        <Form.Item>
172
+          <AuthButton name="admin.buildingDynamic.search" noRight={null}>
173
+            <Button type="primary" htmlType="submit" className={styles.searchBtn}>
174
+              搜索
175
+            </Button>
176
+          </AuthButton>
177
+          <Button style={{ marginLeft: 8 }} onClick={handleReset}>
178
+            重置
179
+            </Button>
180
+        </Form.Item>
181
+      </Form>
182
+      <AuthButton name="admin.eContractTemplate.add.post" noRight={null}>
183
+        <Button type="danger" className={styles.addBtn} onClick={toAdd()}>新增</Button>
184
+      </AuthButton>
185
+      <AuthButton name="admin.eContractTemplate.del" noRight={null}>
186
+        <Button type="primary" className={styles.addBtn} onClick={toDel()} style={{marginLeft:'30px'}}>删除</Button>
187
+      </AuthButton>
188
+      <Table rowSelection={rowSelection}
189
+       dataSource={data.records} columns={columns} pagination={false} rowKey={r => r.contractTemplateId} />
190
+      <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
191
+        <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={e => changePageNum(e)} current={data.current}/>
192
+      </div>
193
+      {/* <RaiseHelpDoc visible={showHelp} onCancel={() => setShowHelp(false)} /> */}
194
+    </>
195
+  )
196
+}
197
+const WrappedHeader = Form.create({ name: 'header' })(header);
198
+
199
+export default WrappedHeader

+ 0
- 0
estateagents-admin-manager/src/pages/eContract/template/pdfDetail.jsx Ver fichero


+ 187
- 0
estateagents-admin-manager/src/pages/funds/accountfunds/components/Basic.jsx Ver fichero

@@ -0,0 +1,187 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Button, Modal, Input, Row, Col, message } from 'antd';
3
+import router from 'umi/router';
4
+import moment from 'moment';
5
+import Navigate from '@/components/Navigate';
6
+import AuthButton from '@/components/AuthButton';
7
+import apis from '../../../../services/apis';
8
+import request from '../../../../utils/request';
9
+import Styles from './styles.less';
10
+import Recharge from './Recharge'
11
+import Refund from './Refund'
12
+import Pay from './Pay'
13
+import Contact from './Contact'
14
+
15
+function Basic(props) {
16
+
17
+    // const [taNoticeList, setTaNoticeList] = useState([])
18
+    const [data, setData] = useState({})
19
+    const [visible, setvisiblea] = useState(false)
20
+    const [confirmLoading, setConfirmLoading] = useState(false)
21
+    const [title, setTitle] = useState()
22
+    const [amount, setAmount] = useState()
23
+    useEffect(() => {
24
+        getData();
25
+    }, [])
26
+    // 查询列表
27
+
28
+    const getData = params => {
29
+        request({ ...apis.funds.get, params: { ...params } }).then(data => {
30
+            setData(data)
31
+        })
32
+    }
33
+
34
+    const handleOkRecharge = e => {
35
+        console.log(e, '123123')
36
+        if (e == 0) {
37
+            message.error('充值金额不能为0')
38
+            return
39
+        }
40
+        if (e) {
41
+
42
+            request({ ...apis.funds.saveOrder, data: { amount: Math.round(e * 100) } }).then(data => {
43
+                setAmount(data)
44
+                showModal('pay')
45
+            }).catch(err => {
46
+                console.log(err)
47
+            })
48
+
49
+        }
50
+
51
+
52
+    };
53
+    // data: { amount: e }
54
+    const handleOkRefund = e => {
55
+        console.log(e, e * 100, '123123')
56
+
57
+        if (e) {
58
+            request({ ...apis.funds.saveRefundOrder, data: { amount: Math.round(e * 100) } }).then(data => {
59
+                message.info('申请退款成功')
60
+                setvisiblea(false)
61
+            }).catch(err => {
62
+                console.log(err)
63
+            })
64
+        }
65
+        // setConfirmLoading(true)
66
+        // setTimeout(() => {
67
+        //   this.setState({
68
+        //     visible: false,
69
+        //     confirmLoading: false,
70
+        //   });
71
+        // }, 2000);
72
+        // setvisiblea(false)
73
+    };
74
+
75
+    const handleOkRepay = e => {
76
+        console.log(e, '123123')
77
+        if (e === 'success') {
78
+            showModal('contact')
79
+        } else {
80
+            // showModal()
81
+            Modal.error({
82
+                title: '充值失败',
83
+                // content: 'some messages...some messages...',
84
+            });
85
+            setvisiblea(false)
86
+        }
87
+        // setConfirmLoading(true)
88
+        // setTimeout(() => {
89
+        //   this.setState({
90
+        //     visible: false,
91
+        //     confirmLoading: false,
92
+        //   });
93
+        // }, 2000);
94
+
95
+    };
96
+
97
+    const toNewContact = () => {
98
+
99
+        router.push({
100
+            pathname: '/funds/financialContact',
101
+            // query: {
102
+            //   id: rowData.raiseId,
103
+            //   buildingId: rowData.buildingId,
104
+            //   salesBatchId: rowData.salesBatchId,
105
+        })
106
+
107
+    }
108
+
109
+
110
+    const showModal = value => {
111
+        if (value === 'recharge') {
112
+            setTitle('线上充值')
113
+        }
114
+        if (value === 'refund') {
115
+            setTitle('申请退款')
116
+        }
117
+        if (value === 'pay') {
118
+            setTitle('扫码支付')
119
+        }
120
+        if (value === 'contact') {
121
+            setTitle('联系我们')
122
+        }
123
+        setvisiblea(true)
124
+    };
125
+
126
+    const handleCancel = () => {
127
+        console.log('Clicked cancel button');
128
+        setvisiblea(false)
129
+    };
130
+
131
+    return (
132
+
133
+        <>
134
+            对资金有疑问? <Navigate onClick={() => toNewContact()}>请联系我们</Navigate>
135
+            <div style={{ display: 'flex', margin: '20px 0 40px' }}>
136
+                <div className={Styles.redHeader}>
137
+                    <div className={Styles.redHeaderTop}><div className={Styles.redHeaderTopText}>总充值金额/元</div><div className={Styles.redHeaderTopNum}>{data.totalRechargeAmount / 100 || 0}</div></div>
138
+                    <div className={Styles.redHeaderBottom}> 对账请在充值订单中查看充值状态为“已支付”的充值记录</div>
139
+                </div>
140
+                <div className={Styles.redHeader} style={{ margin: '0 40px' }}>
141
+                    <div className={Styles.redHeaderTop}><div className={Styles.redHeaderTopText}>已消费金额/元</div><div className={Styles.redHeaderTopNum}>{data.purchaseAmount / 100 || 0}</div></div>
142
+                    <div className={Styles.redHeaderBottom}>对账请在消费订单中查看消费状态为“成功”的消费记录</div>
143
+                </div>
144
+                <div className={Styles.redHeader}>
145
+                    <div className={Styles.redHeaderTop}><div className={Styles.redHeaderTopText}>已退款额/元</div><div className={Styles.redHeaderTopNum}>{data.totalRefund / 100 || 0}</div></div>
146
+                    <div className={Styles.redHeaderBottom}>对账请在退款订单中查看退款状态为“已退款”的退款记录</div>
147
+                </div>
148
+
149
+                <div className={Styles.redHeader} style={{ margin: '0 40px' }}>
150
+                    <div className={Styles.redHeaderTop}><div className={Styles.redHeaderTopText}>退款冻结额/元</div><div className={Styles.redHeaderTopNum}>{data.refundBlockedAmount / 100 || 0}</div></div>
151
+                    <div className={Styles.redHeaderBottom}>对账请在退款订单中查看退款状态为“已申请”的退款记录</div>
152
+                </div>
153
+                <div className={Styles.redHeader}>
154
+                    <div className={Styles.redHeaderTop}><div className={Styles.redHeaderTopText}>账户余额/元</div><div className={Styles.redHeaderTopNum}>{data.availableBalance / 100 || 0}</div></div>
155
+                    <div className={Styles.redHeaderBottom}>账户余额=总充值金额-已消费金额-已退款额-退款冻结额</div>
156
+                </div>
157
+            </div>
158
+            <div style={{ textAlign: 'center', marginTop: '272px' }}>
159
+                <AuthButton name="admin.funds.account.recharge" noRight={null}>
160
+                    <Button className={Styles.btn} type="primary" htmlType="submit" onClick={() => showModal('recharge')}>充值</Button>
161
+                </AuthButton>
162
+                <AuthButton name="admin.funds.account.refund" noRight={null}>
163
+                    <Button className={Styles.btn} style={{ marginLeft: '80px' }} onClick={() => showModal('refund')}>退款</Button>
164
+                </AuthButton>
165
+            </div>
166
+
167
+            <Modal
168
+                title={title}
169
+                visible={visible}
170
+                // onOk={handleOk}
171
+                confirmLoading={confirmLoading}
172
+                onCancel={handleCancel}
173
+                footer={null}
174
+                width="1000px"
175
+                maskClosable={false}
176
+            >
177
+                {title === '线上充值' && <Recharge value={e => handleOkRecharge(e)}></Recharge>}
178
+                {title === '申请退款' && <Refund balance={data.availableBalance / 100 || 0} value={e => handleOkRefund(e)}></Refund>}
179
+                {title === '扫码支付' && <Pay amount={amount} visible={visible} value={e => handleOkRepay(e)}></Pay>}
180
+                {title === '联系我们' && <Contact></Contact>}
181
+
182
+            </Modal>
183
+        </>
184
+    )
185
+}
186
+
187
+export default Basic

+ 285
- 0
estateagents-admin-manager/src/pages/funds/accountfunds/components/ConsumerOrder.jsx Ver fichero

@@ -0,0 +1,285 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, Breadcrumb, DatePicker } from 'antd';
3
+import router from 'umi/router';
4
+import moment from 'moment';
5
+import apis from '../../../../services/apis';
6
+import request from '../../../../utils/request';
7
+import Navigate from '@/components/Navigate';
8
+import AuthButton from '@/components/AuthButton'
9
+
10
+const { Option } = Select
11
+const { RangePicker } = DatePicker
12
+
13
+
14
+function RechargeOrder(props) {
15
+
16
+    // const [taNoticeList, setTaNoticeList] = useState([])
17
+    const [data, setData] = useState({})
18
+    const [modalData, setModalData] = useState([])
19
+    const [visible, setvisiblea] = useState(false)
20
+
21
+    useEffect(() => {
22
+        getList({ pageNum: 1, pageSize: 10 });
23
+    }, [])
24
+    // 查询列表
25
+
26
+    const getList = params => {
27
+
28
+        const { LocalDate, ...values } = params
29
+        if (LocalDate != null && LocalDate.length > 0) {
30
+            const [startTime, endTime] = LocalDate
31
+            values.startTime = `${moment(startTime).format('YYYY-MM-DDT00:00:00')}Z`;
32
+            values.endTime = `${moment(endTime).format('YYYY-MM-DDT23:59:59')}Z`;
33
+        } else {
34
+            values.startTime = null
35
+            values.endTime = null
36
+        }
37
+        // if (params.startTime) {
38
+        //     params.startTime = `${moment(params.startTime).format('YYYY-MM-DDT00:00:00')}Z`;
39
+        // }
40
+        // if (params.endTime) {
41
+        //     params.endTime = `${moment(params.endTime).format('YYYY-MM-DDT23:59:59')}Z`;
42
+        // }
43
+        // console.log("请求数据", params)
44
+        request({ ...apis.funds.consumeOrderByConditionlist, params: { ...values, consumeType: 'RedPacket' } }).then(data => {
45
+            setData(data)
46
+        })
47
+    }
48
+
49
+    function handleSubmit(e) {
50
+        e.preventDefault();
51
+        props.form.validateFields((err, values) => {
52
+            if (!err) {
53
+                // eslint-disable-next-line no-console
54
+                console.log('提交数据: ', values)
55
+                getList({ pageNum: 1, pageSize: 10, ...values });
56
+            }
57
+        });
58
+    }
59
+
60
+    function handleReset() {
61
+        props.form.resetFields();
62
+
63
+        getList({ pageNum: 1, pageSize: 10 })
64
+    }
65
+
66
+    const showModal = (row) => {
67
+        setvisiblea(true)
68
+        setModalData(row)
69
+    }
70
+
71
+    const changePageNum = e => {
72
+        props.form.validateFields((err, values) => {
73
+            if (!err) {
74
+                // eslint-disable-next-line no-console
75
+                console.log('提交数据: ', values)
76
+                getList({ pageNum: e, pageSize: 10, ...values })
77
+            }
78
+        });
79
+
80
+    }
81
+
82
+    const columns = [
83
+        {
84
+            title: '订单编号',
85
+            dataIndex: 'tradeNo',
86
+            key: 'tradeNo',
87
+            align: 'center',
88
+        },
89
+        {
90
+            title: '消费金额',
91
+            dataIndex: 'amount',
92
+            key: 'amount',
93
+            align: 'center',
94
+            render: x => <><span>{x / 100 || ''}</span></>,
95
+        },
96
+        {
97
+            title: '消费方式',
98
+            dataIndex: 'itemType',
99
+            key: 'itemType',
100
+            align: 'center',
101
+            // render: () => <>红包</>,
102
+            render: (x, row) => <><span>{`${row.consumeType === 'RedPacket' ? '红包' : ''}`}</span></>,
103
+        },
104
+        {
105
+            title: '活动名称',
106
+            dataIndex: 'activityName',
107
+            key: 'activityName',
108
+            align: 'center',
109
+        },
110
+        {
111
+            title: '消费下单时间',
112
+            dataIndex: 'createDate',
113
+            key: 'createDate',
114
+            align: 'center',
115
+            render: (x, row) => <><span>{`${moment(row.visitTime).format('YYYY-MM-DD HH:mm:ss')}`}</span></>,
116
+        },
117
+        {
118
+            title: '接收人手机号',
119
+            dataIndex: 'phone',
120
+            key: 'phone',
121
+            align: 'center',
122
+            render: (x, row) => <><Navigate onClick={() => showModal(row)}>{x}</Navigate> </>,
123
+        },
124
+        {
125
+            title: '消费状态',
126
+            dataIndex: 'tradingStatus',
127
+            key: 'tradingStatus',
128
+            align: 'center',
129
+            render: (x, row) => <><span>{row.tradingStatus === 'success' ? '成功' : '失败'}</span></>,
130
+        },
131
+    ]
132
+
133
+    function download(data) {
134
+        // if (!data) {
135
+        //     console.log('234')
136
+        //     return
137
+        // }
138
+        const url = window.URL.createObjectURL(new Blob([data]))
139
+        const link = document.createElement('a')
140
+        link.style.display = 'none'
141
+        link.href = url
142
+        link.setAttribute('download', '消费订单.xlsx')
143
+        document.body.append(link)
144
+        link.click()
145
+    }
146
+
147
+    const exportReport = () => {
148
+        const requestParams = props.form.getFieldsValue();
149
+
150
+        const { LocalDate, ...values } = requestParams
151
+        if (LocalDate != null && LocalDate.length > 0) {
152
+            const [startTime, endTime] = LocalDate
153
+            values.startTime = `${moment(startTime).format('YYYY-MM-DDT00:00:00')}Z`;
154
+            values.endTime = `${moment(endTime).format('YYYY-MM-DDT23:59:59')}Z`;
155
+        } else {
156
+            values.startTime = null
157
+            values.endTime = null
158
+        }
159
+        // if (requestParams.startTime) {
160
+        //     requestParams.startTime = `${moment(requestParams.startTime).format('YYYY-MM-DDT00:00:00')}Z`;
161
+        // }
162
+        // if (requestParams.endTime) {
163
+        //     requestParams.endTime = `${moment(requestParams.endTime).format('YYYY-MM-DDT23:59:59')}Z`;
164
+        // }
165
+        request({ ...apis.funds.exportConsumeOrderByCondition, responseType: 'blob', params: { ...values, consumeType: 'RedPacket' } }).then(data => {
166
+            download(data)
167
+        }).catch()
168
+    }
169
+
170
+    const { getFieldDecorator } = props.form
171
+
172
+    return (
173
+
174
+        <>
175
+            <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
176
+                <Form.Item>
177
+                    {getFieldDecorator('tradeNo')(
178
+                        <Input
179
+                            placeholder="订单编号"
180
+                        />,
181
+                    )}
182
+                </Form.Item>
183
+
184
+
185
+                <Form.Item>
186
+                    {getFieldDecorator('LocalDate')(
187
+                        <RangePicker placeholder={['消费开始时间', '消费结束时间']} />,
188
+                    )}
189
+                </Form.Item>
190
+                {/* 
191
+
192
+                <Form.Item>
193
+                    {getFieldDecorator('startTime')(
194
+                        <DatePicker placeholder="消费开始时间" />,
195
+                    )}
196
+                </Form.Item>
197
+                <Form.Item>
198
+                    {getFieldDecorator('endTime')(
199
+                        <DatePicker placeholder="消费结束时间" />,
200
+                    )}
201
+                </Form.Item> */}
202
+                <Form.Item>
203
+                    {getFieldDecorator('tradingStatus')(
204
+                        <Select style={{ width: '180px' }} placeholder="消费状态">
205
+                            <Option value="">全部</Option>
206
+                            <Option value="success">成功</Option>
207
+                            <Option value="fail">失败</Option>
208
+                        </Select>,
209
+                    )}
210
+                </Form.Item>
211
+                <Form.Item>
212
+                    {getFieldDecorator('consumeType')(
213
+                        <Select style={{ width: '180px' }} placeholder="消费方式">
214
+                            <Option value="">全部</Option>
215
+                            <Option value="RedPacket">红包</Option>
216
+                        </Select>,
217
+                    )}
218
+                </Form.Item>
219
+                <Form.Item>
220
+                    {getFieldDecorator('phone')(
221
+                        <Input
222
+                            placeholder="接收人手机号"
223
+                        />,
224
+                    )}
225
+                </Form.Item>
226
+                <Form.Item>
227
+                    <Button type="primary" htmlType="submit"> 搜索</Button>
228
+                    <Button style={{ marginLeft: 8 }} onClick={handleReset}>重置</Button>
229
+                </Form.Item>
230
+            </Form>
231
+            <div style={{ marginTop: '20px' }}>
232
+                <AuthButton name="admin.funds.account.recharge" noRight={null}>
233
+                    <Button type="primary" onClick={() => exportReport()} style={{ float: 'right', marginBottom: '20px', zIndex: 1 }} >导出</Button>
234
+                </AuthButton>
235
+            </div>
236
+            <Table dataSource={data.records} columns={columns} pagination={false} style={{ marginTop: '20px' }} />
237
+            <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
238
+                <Pagination
239
+                    showQuickJumper
240
+                    defaultCurrent={1}
241
+                    total={data.total} onChange={e => changePageNum(e)} current={data.current} />
242
+            </div>
243
+            <Modal
244
+                title="接收人信息"
245
+                visible={visible}
246
+                // onOk={handleOk}
247
+                // confirmLoading={confirmLoading}
248
+                onCancel={() => setvisiblea(false)}
249
+                footer={null}
250
+            // width="1000px"
251
+            // maskClosable={false}
252
+            >
253
+                <Form labelCol={{ span: 7 }} wrapperCol={{ span: 12 }}>
254
+                    <Form.Item label="昵称">
255
+
256
+                        <span>{modalData.nickname}</span>
257
+
258
+                    </Form.Item>
259
+                    <Form.Item label="头像">
260
+
261
+                        <img src={modalData.avatarurl} alt="" width="100px" height="100px" />
262
+
263
+                    </Form.Item>
264
+                    <Form.Item label="姓名">
265
+
266
+                        <span>{modalData.name || modalData.nickname}</span>
267
+
268
+                    </Form.Item>
269
+                    <Form.Item label="手机号">
270
+
271
+                        <span>{modalData.phone}</span>
272
+
273
+                    </Form.Item>
274
+                </Form>
275
+            </Modal>
276
+        </>
277
+
278
+    )
279
+}
280
+
281
+
282
+const WrappedRechargeOrder = Form.create({ name: 'RechargeOrder' })(RechargeOrder);
283
+
284
+export default WrappedRechargeOrder
285
+

+ 12
- 0
estateagents-admin-manager/src/pages/funds/accountfunds/components/Contact.jsx Ver fichero

@@ -0,0 +1,12 @@
1
+import React from 'react';
2
+import ContactText from './contactText'
3
+
4
+const Recharge = () => (
5
+    <>
6
+        <span style={{ fontSize: '22px', color: '#979797', lineHeight: '30px' }}>重要说明:</span>
7
+        <div style={{ fontSize: '18px', color: '#333', lineHeight: '34px', marginTop: '20px' }}>
8
+            您已充值成功,微信充值到账为T+7,因此,充值金额7日后才能到账,为不影响客户使用,实际活动金额由致云预先充值垫付,需要在使用预算前和运营人员确认致云余额是否充足,<ContactText />
9
+        </div>
10
+    </>
11
+)
12
+export default Recharge

+ 81
- 0
estateagents-admin-manager/src/pages/funds/accountfunds/components/Pay.jsx Ver fichero

@@ -0,0 +1,81 @@
1
+import React, { useState, useEffect, useMemo } from 'react';
2
+import { Button, Input, Row, Col, message } from 'antd';
3
+import QRCode from 'qrcode.react';
4
+import Styles from './styles.less';
5
+import apis from '../../../../services/apis';
6
+import request from '../../../../utils/request';
7
+
8
+
9
+let intervalState = true
10
+const Recharge = props => {
11
+
12
+    const { amount } = props
13
+    console.log(amount, 'amount')
14
+    const { orderInfo } = amount
15
+    console.log(orderInfo, 'orderInfo')
16
+    useEffect(() => {
17
+        console.log(props.visible, 'props.visible')
18
+
19
+        return () => clearInterval(getByInfo);
20
+        // setTimeout(() => { getByInfo() }, 1000)
21
+    }, [props.visible])
22
+
23
+
24
+    const getByInfo = setInterval(() => {
25
+        if (intervalState) {
26
+            intervalState = false
27
+            request({ ...apis.funds.getByInfo, params: { orderId: orderInfo.orderId } }).then(data => {
28
+                if (data.tradingStatus === 'processing') {
29
+                    // clearInterval(getByInfo)
30
+                    // props.value()
31
+                    // if (!visible) { clearInterval(getByInfo) }
32
+                    intervalState = true
33
+                } else if (data.tradingStatus === 'success') {
34
+                    message.info('充值成功')
35
+                    clearInterval(getByInfo)
36
+
37
+                    props.value('success')
38
+                } else {
39
+                    message.info('充值失败')
40
+                    clearInterval(getByInfo)
41
+                    props.value('fail')
42
+                }
43
+                // tradingStatus
44
+                // setTimeout(() => { getByInfo() }, 1000)
45
+            }).catch(err => {
46
+                console.log(err)
47
+                clearInterval(getByInfo)
48
+                message.info('充值失败')
49
+                props.value('fail')
50
+            })
51
+        }
52
+    }, 2000)
53
+
54
+
55
+    return (
56
+        <>
57
+            <div style={{ fontSize: '18px', fontWeight: '400', color: '#333333' }}>
58
+                <span onClick={props.value}>充值金额{amount.amount / 100 || 0}元</span><span style={{ marginLeft: '80px' }}>微信商户手续费率{amount.mchPayRate}</span><span style={{ marginLeft: '80px' }}>手续费{amount.serviceFee / 100 || 0}元</span>
59
+                {/* <img src="" alt="" width:/> */}
60
+            </div>
61
+            <div style={{ height: '278px', borderRadius: '12px', border: '1px solid rgba(218,218,218,1', margin: '40px 0', display: 'flex' }}>
62
+                <div className={Styles.box}>
63
+                    <QRCode
64
+                        value={amount.payQrCode}  //value参数为生成二维码的链接
65
+                        size={194} //二维码的宽高尺寸
66
+                        fgColor="#000000"  //二维码的颜色
67
+                    />
68
+                    {/* <img src={amount.payQrCode} alt="" /> */}
69
+                </div>
70
+                <div className={Styles.boxRight}>
71
+                    <div className={Styles.child}>
72
+                        <p style={{ lineHeight: '43px', height: '43px', marginBottom: '5px' }}><span style={{ fontSize: '32px', fontWeight: '600', color: '#EF273A' }}>¥{amount.realAmount / 100 || 0}</span><span style={{ marginLeft: '5px' }}>应付金额</span></p>
73
+                        <p>仅支持微信支付</p>
74
+                    </div>
75
+
76
+                </div>
77
+            </div>
78
+        </>
79
+    )
80
+}
81
+export default Recharge

+ 46
- 0
estateagents-admin-manager/src/pages/funds/accountfunds/components/Recharge.jsx Ver fichero

@@ -0,0 +1,46 @@
1
+import React, { useState } from 'react';
2
+import { Button, Input, Row, Col } from 'antd';
3
+import Styles from './styles.less';
4
+import Navigate from '@/components/Navigate';
5
+import ContactText from './contactText'
6
+
7
+const Recharge = props => {
8
+
9
+    const [value, setValue] = useState()
10
+    // /^1[3456789]\d{9}$/
11
+    function onChange(e) {
12
+        // if (e.target.value < 0) return
13
+        // if (e.target.value == '') { setValue(e.target.value); return }
14
+        // if (!(/^[0-9]{1,5}([.][0-9]{1,2})?$/.test(e.target.value))) return
15
+        // if (e.target.value > balance) { setValue(balance); return }
16
+        // // console.log('changed', e.target.value);
17
+        // setValue(e.target.value)
18
+        if (e.target.value == '') { setValue(e.target.value); return }
19
+        if (e.target.value < 0) return
20
+        if (!(/^[0-9]{1,5}([.][0-9]{1,2})?$/.test(e.target.value))) return
21
+        if (e.target.value > 99999.99) { setValue(99999.99); return }
22
+        console.log('changed', e.target.value);
23
+        setValue(e.target.value)
24
+
25
+    }
26
+    return (
27
+        <>
28
+            <Row>
29
+                <Col span={3}> <span style={{ fontSize: '20px', color: '#666' }}>充值金额/元</span></Col>
30
+                <Col span={17} offset={1}>
31
+                    <Input type="number" min={0} step={0.01} value={value} onChange={onChange} style={{ marginBottom: '40px' }}></Input>
32
+                    <span style={{ fontSize: '20px', color: '#979797', lineHeight: '30px' }}>重要说明:</span>
33
+                    <p style={{ fontSize: '18px', color: '#333', marginBottom: '8px', marginTop: '20px' }}>1.充值流程:输入充值金额-点击确定-扫码支付-支付成功。</p>
34
+                    <p style={{ fontSize: '18px', color: '#333', marginBottom: '8px' }}>2.因微信限制,微信充值有手续费,因此充值金额中应包含手续费,费率1%。</p>
35
+                    <p style={{ fontSize: '18px', color: '#333', marginBottom: '8px' }}>3.微信充值到账为T+7,因此,充值金额7日后才能到账,为不影响客户使用,实际活动金额由致云预先充值垫付,需要在使用预算前和运营人员确认致云余额是否充足。充值后请联系我们。</p>
36
+                    <p style={{ fontSize: '18px', color: '#333', marginBottom: '8px' }}>4.您也可使用银行卡转账/支付宝支付/对公账户打款/现金支付等方式充值,具体方式<ContactText /></p>
37
+                </Col>
38
+            </Row>
39
+            <div style={{ textAlign: 'center', marginTop: '40px' }}>
40
+                <Button className={Styles.btn} type="primary" htmlType="submit" onClick={() => props.value(value)}>充值</Button>
41
+
42
+            </div>
43
+        </>
44
+    )
45
+}
46
+export default Recharge

+ 275
- 0
estateagents-admin-manager/src/pages/funds/accountfunds/components/RechargeOrder.jsx Ver fichero

@@ -0,0 +1,275 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, Breadcrumb, DatePicker } from 'antd';
3
+import router from 'umi/router';
4
+import moment from 'moment';
5
+import Navigate from '@/components/Navigate'
6
+import apis from '../../../../services/apis';
7
+import request from '../../../../utils/request';
8
+import AuthButton from '@/components/AuthButton';
9
+import ShowVoucher from './ShowVoucher';
10
+
11
+const { RangePicker } = DatePicker
12
+
13
+
14
+const { Option } = Select
15
+
16
+function RechargeOrder(props) {
17
+
18
+    // const [taNoticeList, setTaNoticeList] = useState([])
19
+    const [data, setData] = useState({})
20
+
21
+    const [showVoucher, setShowVoucher] = useState({})
22
+    //     {
23
+    //         visible: false,
24
+    //         bannerList: ['//njcj.oss-cn-shanghai.aliyuncs.com/miniapp/upload/images/1591609582282-1584614514971-504167f68a5d43ee693949b26498ef21.jpg', '//njcj.oss-cn-shanghai.aliyuncs.com/miniapp/upload/images/1591609582282-1584614514971-504167f68a5d43ee693949b26498ef21.jpg'],
25
+    //     },
26
+    // )
27
+
28
+    useEffect(() => {
29
+        getList({ pageNum: 1, pageSize: 10 });
30
+    }, [])
31
+    // 查询列表
32
+
33
+    const getList = params => {
34
+
35
+
36
+        const { LocalDate, ...values } = params
37
+        if (LocalDate != null && LocalDate.length > 0) {
38
+            const [payStartTime, payEndTime] = LocalDate
39
+            values.payStartTime = `${moment(payStartTime).format('YYYY-MM-DDT00:00:00')}Z`;
40
+            values.payEndTime = `${moment(payEndTime).format('YYYY-MM-DDT23:59:59')}Z`;
41
+        } else {
42
+            values.payStartTime = null
43
+            values.payEndTime = null
44
+        }
45
+        // if (params.payStartTime) {
46
+        //     params.payStartTime = `${moment(params.payStartTime).format('YYYY-MM-DDT00:00:00')}Z`;
47
+        // }
48
+        // if (params.payEndTime) {
49
+        //     params.payEndTime = `${moment(params.payEndTime).format('YYYY-MM-DDT23:59:59')}Z`;
50
+        // }
51
+
52
+        request({ ...apis.funds.czlist, params: { ...values } }).then(data => {
53
+            setData(data)
54
+        })
55
+    }
56
+    const openImg = data => {
57
+        setShowVoucher(
58
+            {
59
+                visible: true,
60
+                bannerList: data,
61
+            },
62
+        )
63
+    }
64
+
65
+    const changePageNum = e => {
66
+        props.form.validateFields((err, values) => {
67
+            if (!err) {
68
+                // eslint-disable-next-line no-console
69
+                console.log('提交数据: ', values)
70
+                getList({ pageNum: e, pageSize: 10, ...values })
71
+            }
72
+        });
73
+
74
+    }
75
+
76
+
77
+    function handleSubmit(e) {
78
+        e.preventDefault();
79
+        props.form.validateFields((err, values) => {
80
+            if (!err) {
81
+                // eslint-disable-next-line no-console
82
+                console.log('提交数据: ', values)
83
+                getList({ pageNum: 1, pageSize: 10, ...values })
84
+            }
85
+        });
86
+    }
87
+
88
+    function handleReset() {
89
+        props.form.resetFields();
90
+
91
+        getList({ pageNum: 1, pageSize: 10 })
92
+    }
93
+
94
+    const columns = [
95
+        {
96
+            title: '订单编号',
97
+            dataIndex: 'tradeNo',
98
+            key: 'tradeNo',
99
+            align: 'center',
100
+        },
101
+        {
102
+            title: '充值金额',
103
+            dataIndex: 'amount',
104
+            key: 'amount',
105
+            align: 'center',
106
+            render: x => <><span>{x / 100 || ''}</span></>,
107
+        },
108
+        {
109
+            title: '充值方式',
110
+            dataIndex: 'isOffline',
111
+            key: 'isOffline',
112
+            align: 'center',
113
+            render: x => <><span>{x ? '运营手工充值' : '业务线上充值'}</span></>,
114
+        },
115
+        {
116
+            title: '下单时间',
117
+            dataIndex: 'createDate',
118
+            key: 'createDate',
119
+            align: 'center',
120
+            render: (x, row) => <><span>{`${moment(row.createDate).format('YYYY-MM-DD HH:mm:ss')}`}</span></>,
121
+        },
122
+        {
123
+            title: '充值凭证',
124
+            dataIndex: 'certificateUrlList',
125
+            key: 'certificateUrlList',
126
+            align: 'center',
127
+            render: (x, row) => <>{row.certificateUrlList == null ? '' : <Navigate onClick={() => openImg(x)}>查看</Navigate>}</>,
128
+        },
129
+        {
130
+            title: '充值状态',
131
+            dataIndex: 'tradingStatus',
132
+            key: 'tradingStatus',
133
+            align: 'center',
134
+            render: (x, row) => <><span>{row.tradingStatus == 'processing' ? '待支付' : (row.tradingStatus == 'success' ? '已支付' : '失败')}</span></>,
135
+        },
136
+        {
137
+            title: '支付时间',
138
+            dataIndex: 'payDate',
139
+            key: 'payDate',
140
+            align: 'center',
141
+            render: (x, row) => <><span>{row.payDate == null ? "" : `${moment(row.payDate).format('YYYY-MM-DD HH:mm:ss')}`}</span></>,
142
+        },
143
+    ]
144
+
145
+    const { getFieldDecorator } = props.form
146
+
147
+    function download(data) {
148
+        // if (!data) {
149
+        //     console.log('234')
150
+        //     return
151
+        // }
152
+        const url = window.URL.createObjectURL(new Blob([data]))
153
+        const link = document.createElement('a')
154
+        link.style.display = 'none'
155
+        link.href = url
156
+        link.setAttribute('download', '充值订单.xlsx')
157
+        document.body.append(link)
158
+        link.click()
159
+    }
160
+
161
+    const exportReport = () => {
162
+        const requestParams = props.form.getFieldsValue();
163
+
164
+        
165
+        const { LocalDate, ...values } = requestParams
166
+        if (LocalDate != null && LocalDate.length > 0) {
167
+            const [payStartTime, payEndTime] = LocalDate
168
+            values.payStartTime = `${moment(payStartTime).format('YYYY-MM-DDT00:00:00')}Z`;
169
+            values.payEndTime = `${moment(payEndTime).format('YYYY-MM-DDT23:59:59')}Z`;
170
+        } else {
171
+            values.payStartTime = null
172
+            values.payEndTime = null
173
+        }
174
+        // if (requestParams.payStartTime) {
175
+        //     requestParams.payStartTime = `${moment(requestParams.payStartTime).format('YYYY-MM-DDT00:00:00')}Z`;
176
+        // }
177
+        // if (requestParams.payEndTime) {
178
+        //     requestParams.payEndTime = `${moment(requestParams.payEndTime).format('YYYY-MM-DDT23:59:59')}Z`;
179
+        // }
180
+        request({ ...apis.funds.czexportList, responseType: 'blob', params: { ...values } }).then(data => {
181
+            download(data)
182
+        }).catch()
183
+    }
184
+
185
+    return (
186
+
187
+        <>
188
+            <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
189
+                <Form.Item>
190
+                    {getFieldDecorator('tradeNo')(
191
+                        <Input
192
+                            placeholder="订单编号"
193
+                        />,
194
+                    )}
195
+                </Form.Item>
196
+
197
+                <Form.Item>
198
+                    {getFieldDecorator('LocalDate')(
199
+                        <RangePicker placeholder={['支付开始时间', '支付结束时间']} />,
200
+                    )}
201
+                </Form.Item>
202
+
203
+
204
+                {/* <Form.Item>
205
+                    {getFieldDecorator('payStartTime')(
206
+                        <DatePicker placeholder="支付开始时间" />,
207
+                    )}
208
+                </Form.Item>
209
+                <Form.Item>
210
+                    {getFieldDecorator('payEndTime')(
211
+                        <DatePicker placeholder="支付结束时间" />,
212
+                    )}
213
+                </Form.Item> */}
214
+                <Form.Item>
215
+                    {getFieldDecorator('isOffline')(
216
+                        <Select style={{ width: '180px' }} placeholder="充值方式">
217
+                            <Option value="">全部</Option>
218
+                            <Option value={0}>业务线上充值</Option>
219
+                            <Option value={1}>运营手工充值</Option>
220
+                        </Select>,
221
+                    )}
222
+                </Form.Item>
223
+                <Form.Item>
224
+                    {getFieldDecorator('tradingStatus')(
225
+                        <Select style={{ width: '180px' }} placeholder="充值状态">
226
+                            <Option value="">全部</Option>
227
+                            <Option value="processing">待支付</Option>
228
+                            <Option value="success">已支付</Option>
229
+                            <Option value="fail">失败</Option>
230
+                        </Select>,
231
+                    )}
232
+                </Form.Item>
233
+                {/* <Form.Item>
234
+                    {getFieldDecorator('tel')(
235
+                        <Input
236
+                            placeholder="充值方式"
237
+                        />,
238
+                    )}
239
+                </Form.Item>
240
+                <Form.Item>
241
+                    {getFieldDecorator('tel')(
242
+                        <Input
243
+                            placeholder="充值状态"
244
+                        />,
245
+                    )}
246
+                </Form.Item> */}
247
+                <Form.Item>
248
+                    <Button type="primary" htmlType="submit"> 搜索</Button>
249
+                    <Button style={{ marginLeft: 8 }} onClick={handleReset}>重置</Button>
250
+                </Form.Item>
251
+            </Form>
252
+            <div style={{ marginTop: '20px' }}>
253
+                <AuthButton name="admin.funds.account.export" noRight={null}>
254
+                    <Button type="primary" onClick={() => exportReport()} style={{ float: 'right', marginBottom: '20px', zIndex: 1 }} >导出</Button>
255
+                </AuthButton>
256
+            </div>
257
+            <Table dataSource={data.records} columns={columns} pagination={false} style={{ marginTop: '20px' }} />
258
+            <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
259
+                <Pagination
260
+                    showQuickJumper
261
+                    defaultCurrent={1}
262
+                    total={data.total} onChange={e => changePageNum(e)} current={data.current} />
263
+            </div>
264
+
265
+            {showVoucher.visible && <ShowVoucher bannerList={showVoucher.bannerList} closeSwiper={() => setShowVoucher({ visible: false })} />}
266
+        </>
267
+
268
+    )
269
+}
270
+
271
+
272
+const WrappedRechargeOrder = Form.create({ name: 'RechargeOrder' })(RechargeOrder);
273
+
274
+export default WrappedRechargeOrder
275
+

+ 46
- 0
estateagents-admin-manager/src/pages/funds/accountfunds/components/Refund.jsx Ver fichero

@@ -0,0 +1,46 @@
1
+import React, { useState } from 'react';
2
+import { Button, Input, Row, Col } from 'antd';
3
+import Styles from './styles.less';
4
+import ContactText from './contactText'
5
+
6
+const Recharge = props => {
7
+    const { balance } = props
8
+
9
+    // if (e.target.value == 0) { setValue(0); return }
10
+    // if (e.target.value <= 0) return
11
+    // if (!(/^[0-9]{1,5}([.][0-9]{1,2})?$/.test(e.target.value))) return
12
+    // if (e.target.value > 99999.99) { setValue(99999.99); return }
13
+    // console.log('changed', e.target.value);
14
+    // setValue(e.target.value)
15
+
16
+    const [value, setValue] = useState()
17
+
18
+    function onChange(e) {
19
+        console.log('changed', e.target.value);
20
+        // if (e.target.value == 0) { setValue(); return }
21
+        if (e.target.value < 0) return
22
+        if (e.target.value == '') { setValue(e.target.value); return }
23
+        if (!(/^[0-9]{1,5}([.][0-9]{1,2})?$/.test(e.target.value))) return
24
+        if (e.target.value > balance) { setValue(balance); return }
25
+        // console.log('changed', e.target.value);
26
+        setValue(e.target.value)
27
+
28
+    }
29
+    return (
30
+        <>
31
+            <Row>
32
+                <Col span={3}> <span style={{ fontSize: '20px', color: '#666' }}>退款金额/元</span></Col>
33
+                <Col span={17} offset={1}>
34
+                    <Input type="number" min={0} step={0.01} value={value} onChange={onChange} style={{ marginBottom: '40px' }}></Input>
35
+                    <span style={{ fontSize: '20px', color: '#979797', lineHeight: '30px' }}>账户余额:{balance}元</span>
36
+                    <p style={{ fontSize: '18px', color: '#333', marginBottom: '8px', marginTop: '20px' }}>因微信商户平台限制,需先提交退款申请,提交后会冻结退款额对应余额资金,冻结金额无法使用,若您的平台有正在举办的活动等需要消费的地方,请预留充足的余额。如有疑问, <ContactText /></p>
37
+                </Col>
38
+            </Row>
39
+            <div style={{ textAlign: 'center', marginTop: '40px' }}>
40
+                <Button className={Styles.btn} type="primary" htmlType="submit" onClick={() => props.value(value)}>确认申请</Button>
41
+
42
+            </div>
43
+        </>
44
+    )
45
+}
46
+export default Recharge

+ 250
- 0
estateagents-admin-manager/src/pages/funds/accountfunds/components/RefundOrder.jsx Ver fichero

@@ -0,0 +1,250 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, Breadcrumb, DatePicker } from 'antd';
3
+import router from 'umi/router';
4
+import moment from 'moment';
5
+import withActions from '@/components/ActionList';
6
+import EditIcon from '@/components/EditIcon';
7
+import apis from '../../../../services/apis';
8
+import AuthButton from '@/components/AuthButton';
9
+import request from '../../../../utils/request';
10
+import Navigate from '@/components/Navigate'
11
+import ShowVoucher from './ShowVoucher';
12
+
13
+const { Option } = Select
14
+
15
+const { RangePicker } = DatePicker
16
+
17
+function RechargeOrder(props) {
18
+
19
+    // const [taNoticeList, setTaNoticeList] = useState([])
20
+    const [data, setData] = useState({})
21
+
22
+    const [showVoucher, setShowVoucher] = useState({})
23
+
24
+    useEffect(() => {
25
+        getList({ pageNum: 1, pageSize: 10 });
26
+    }, [])
27
+    // 查询列表
28
+
29
+    const getList = params => {
30
+
31
+        const { LocalDate, ...values } = params
32
+        if (LocalDate != null && LocalDate.length > 0) {
33
+            const [refundStartTime, refundEndTime] = LocalDate
34
+            values.refundStartTime = `${moment(refundStartTime).format('YYYY-MM-DDT00:00:00')}Z`;
35
+            values.refundEndTime = `${moment(refundEndTime).format('YYYY-MM-DDT23:59:59')}Z`;
36
+        } else {
37
+            values.refundStartTime = null
38
+            values.refundEndTime = null
39
+        }
40
+        // if (params.refundStartTime) {
41
+        //     params.refundStartTime = `${moment(params.refundStartTime).format('YYYY-MM-DDT00:00:00')}Z`;
42
+        // }
43
+        // if (params.refundEndTime) {
44
+        //     params.refundEndTime = `${moment(params.refundEndTime).format('YYYY-MM-DDT23:59:59')}Z`;
45
+        // }
46
+        request({ ...apis.funds.refundlist, params: { ...values } }).then(data => {
47
+            setData(data)
48
+        })
49
+    }
50
+
51
+    function handleSubmit(e) {
52
+        e.preventDefault();
53
+        props.form.validateFields((err, values) => {
54
+            if (!err) {
55
+                // eslint-disable-next-line no-console
56
+                console.log('提交数据: ', values)
57
+                getList({ pageNum: 1, pageSize: 10, ...values })
58
+            }
59
+        });
60
+    }
61
+
62
+    const openImg = data => {
63
+        setShowVoucher(
64
+            {
65
+                visible: true,
66
+                bannerList: data,
67
+            },
68
+        )
69
+    }
70
+
71
+    function handleReset() {
72
+        props.form.resetFields();
73
+
74
+        getList({ pageNum: 1, pageSize: 10 })
75
+    }
76
+
77
+    const changePageNum = e => {
78
+        props.form.validateFields((err, values) => {
79
+            if (!err) {
80
+                // eslint-disable-next-line no-console
81
+                console.log('提交数据: ', values)
82
+                getList({ pageNum: e, pageSize: 10, ...values })
83
+            }
84
+        });
85
+
86
+    }
87
+
88
+    const columns = [
89
+        {
90
+            title: '订单编号',
91
+            dataIndex: 'tradeNo',
92
+            key: 'tradeNo',
93
+            align: 'center',
94
+        },
95
+        {
96
+            title: '退款金额(元)',
97
+            dataIndex: 'amount',
98
+            key: 'amount',
99
+            align: 'center',
100
+            render: (x, row) => <><span>{`${row.amount / 100}`}</span></>,
101
+        },
102
+        {
103
+            title: '退款创建时间',
104
+            dataIndex: 'createDate',
105
+            key: 'createDate',
106
+            align: 'center',
107
+            render: (x, row) => <><span>{`${moment(row.createDate).format('YYYY-MM-DD HH:mm:ss')}`}</span></>,
108
+        },
109
+        {
110
+            title: '退款状态',
111
+            dataIndex: 'auditStatus',
112
+            key: 'auditStatus',
113
+            align: 'center',
114
+            // width: '20%',
115
+            render: (x, row) => <><span>{row.auditStatus == 'checking' ? '已申请' : (row.auditStatus == 'agree' ? '已退款' : '已驳回')}</span></>,
116
+        },
117
+        {
118
+            title: '驳回原因',
119
+            dataIndex: 'auditResult',
120
+            key: 'auditResult',
121
+            align: 'center',
122
+            width: '20%',
123
+        },
124
+
125
+        {
126
+            title: '退款凭证',
127
+            dataIndex: 'certificateUrlList',
128
+            key: 'certificateUrlList',
129
+            align: 'center',
130
+            render: (x, row) => <>{row.certificateUrlList == null ? '' : <Navigate onClick={() => openImg(x)}>查看</Navigate>}</>,
131
+        },
132
+        {
133
+            title: '操作',
134
+            dataIndex: 'num',
135
+            key: 'num',
136
+            align: 'center',
137
+            render: withActions((text, row) => [
138
+
139
+                <EditIcon type="look" text="查看联系人" onClick={() => router.push({
140
+                    pathname: '/funds/financialContact',
141
+                })}> </EditIcon>,
142
+
143
+
144
+            ]),
145
+        },
146
+    ]
147
+
148
+    function download(data) {
149
+        // if (!data) {
150
+        //     console.log('234')
151
+        //     return
152
+        // }
153
+        const url = window.URL.createObjectURL(new Blob([data]))
154
+        const link = document.createElement('a')
155
+        link.style.display = 'none'
156
+        link.href = url
157
+        link.setAttribute('download', '退款订单.xlsx')
158
+        document.body.append(link)
159
+        link.click()
160
+    }
161
+
162
+    const exportReport = () => {
163
+        const requestParams = props.form.getFieldsValue();
164
+        const { LocalDate, ...values } = requestParams
165
+        if (LocalDate != null && LocalDate.length > 0) {
166
+            const [refundStartTime, refundEndTime] = LocalDate
167
+            values.refundStartTime = `${moment(refundStartTime).format('YYYY-MM-DDT00:00:00')}Z`;
168
+            values.refundEndTime = `${moment(refundEndTime).format('YYYY-MM-DDT23:59:59')}Z`;
169
+        } else {
170
+            values.refundStartTime = null
171
+            values.refundEndTime = null
172
+        }
173
+        // if (requestParams.refundStartTime) {
174
+        //     requestParams.refundStartTime = `${moment(requestParams.refundStartTime).format('YYYY-MM-DDT00:00:00')}Z`;
175
+        // }
176
+        // if (requestParams.refundEndTime) {
177
+        //     requestParams.refundEndTime = `${moment(requestParams.refundEndTime).format('YYYY-MM-DDT23:59:59')}Z`;
178
+        // }
179
+        request({ ...apis.funds.refundexportList, responseType: 'blob', params: { ...values } }).then(data => {
180
+            download(data)
181
+        }).catch()
182
+    }
183
+
184
+    const { getFieldDecorator } = props.form
185
+
186
+    return (
187
+
188
+        <>
189
+            <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
190
+                <Form.Item>
191
+                    {getFieldDecorator('tradeNo')(
192
+                        <Input
193
+                            placeholder="订单编号"
194
+                        />,
195
+                    )}
196
+                </Form.Item>
197
+
198
+                <Form.Item>
199
+                    {getFieldDecorator('LocalDate')(
200
+                        <RangePicker placeholder={['退款开始时间', '退款结束时间']} />,
201
+                    )}
202
+                </Form.Item>
203
+                {/* <Form.Item>
204
+                    {getFieldDecorator('refundStartTime')(
205
+                        <DatePicker placeholder="退款开始时间" />,
206
+                    )}
207
+                </Form.Item>
208
+                <Form.Item>
209
+                    {getFieldDecorator('refundEndTime')(
210
+                        <DatePicker placeholder="退款结束时间" />,
211
+                    )}
212
+                </Form.Item> */}
213
+                <Form.Item>
214
+                    {getFieldDecorator('auditStatus')(
215
+                        <Select style={{ width: '180px' }} placeholder="退款状态">
216
+                            <Option value="">全部</Option>
217
+                            <Option value="checking">已申请</Option>
218
+                            <Option value="unagree">已驳回</Option>
219
+                            <Option value="agree">已退款</Option>
220
+                        </Select>,
221
+                    )}
222
+                </Form.Item>
223
+                <Form.Item>
224
+                    <Button type="primary" htmlType="submit"> 搜索</Button>
225
+                    <Button style={{ marginLeft: 8 }} onClick={handleReset}>重置</Button>
226
+                </Form.Item>
227
+            </Form>
228
+            <div style={{ marginTop: '20px' }}>
229
+                <AuthButton name="admin.funds.account.export" noRight={null}>
230
+                    <Button type="primary" onClick={() => exportReport()} style={{ float: 'right', marginBottom: '20px', zIndex: 1 }} >导出</Button>
231
+                </AuthButton>
232
+            </div>
233
+            <Table dataSource={data.records} columns={columns} pagination={false} style={{ marginTop: '20px' }} />
234
+            <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
235
+                <Pagination
236
+                    showQuickJumper
237
+                    defaultCurrent={1}
238
+                    total={data.total} onChange={e => changePageNum(e)} current={data.current} />
239
+            </div>
240
+            {showVoucher.visible && <ShowVoucher bannerList={showVoucher.bannerList} closeSwiper={() => setShowVoucher({ visible: false })} />}
241
+        </>
242
+
243
+    )
244
+}
245
+
246
+
247
+const WrappedRechargeOrder = Form.create({ name: 'RechargeOrder' })(RechargeOrder);
248
+
249
+export default WrappedRechargeOrder
250
+

+ 128
- 0
estateagents-admin-manager/src/pages/funds/accountfunds/components/ShowVoucher.jsx Ver fichero

@@ -0,0 +1,128 @@
1
+import React from 'react';
2
+import Swiper from 'swiper';
3
+import styles from './styles.less'
4
+import closeImg from '../../../../assets/close2.png';
5
+import classNames from 'classnames';
6
+import 'swiper/css/swiper.min.css';
7
+
8
+class ShowVoucher extends React.Component {
9
+    constructor(props) {
10
+        super(props);
11
+        this.state = {
12
+            bannerList: this.props.bannerList,
13
+        }
14
+
15
+        this.slider = null
16
+    }
17
+
18
+    componentDidMount() {
19
+        this.showSwiper()
20
+
21
+
22
+    }
23
+
24
+
25
+    showSwiper() {
26
+        //swiper初始化
27
+        const { bannerList } = this.state
28
+        if (bannerList.length > 1) {
29
+            this.swiper = new Swiper('.swiper-container', {
30
+                slidesPerView: 1,
31
+                loop: true,
32
+                autoplay: {
33
+                    disableOnInteraction: false,
34
+                },
35
+                touchRatio: 1.5,
36
+                pagination: {
37
+                    el: '.swiper-pagination',
38
+                    bulletElement: 'li',
39
+                    clickable: true,
40
+                    bulletActiveClass: 'antd-pro-pages-swiper-style-active',
41
+                },
42
+                observer: true,
43
+                observeParents: true,
44
+            })
45
+        } else {
46
+            this.swiper = new Swiper('.swiper-container', {
47
+                loop: false,
48
+                observer: true,
49
+                observeParents: true,
50
+            })
51
+        }
52
+    }
53
+
54
+    render() {
55
+
56
+        const { bannerList } = this.state
57
+        // const showSwiper = window.localStorage.getItem(storageKey)
58
+        return (
59
+            <>
60
+                {bannerList.length > 0 && <div className={styles.mask}>
61
+                    <div className={styles.content}>
62
+                        <img src={closeImg} alt="" className={styles.close} onClick={() => this.props.closeSwiper()} />
63
+                        <div className={classNames(['swiper-container', styles.carousel])} >
64
+                            <div className={classNames(['swiper-wrapper', styles.carousel])} >
65
+                                {bannerList.map((item, index) =>
66
+                                    <div key={'swiper' + index} className={classNames(['swiper-slide', styles.carouselItem])} >
67
+                                        {/* <img style={{ width: '100%', borderRadius: '10px' }} src={item} alt="" /> */}
68
+                                        <img style={{ maxHeight: '504px', borderRadius: '10px' }} src={item} alt="" />
69
+                                    </div>,
70
+                                )}
71
+                            </div>
72
+                            <div className={classNames(['swiper-pagination', styles.dots])} ></div>
73
+                        </div>
74
+                    </div>
75
+                </div>}
76
+            </>
77
+        )
78
+    }
79
+}
80
+
81
+
82
+export default ShowVoucher
83
+
84
+
85
+
86
+
87
+
88
+// import React, { useState, useEffect } from 'react';
89
+// import Carousel, { Modal, ModalGateway } from 'react-images';
90
+
91
+// const ShowVoucher = props => {
92
+//     const { bannerList = [], open, onClose } = props;
93
+//     const [modalIsOpen, setModalIsOpen] = useState(open)
94
+//     useEffect(() => {
95
+//         setModalIsOpen(open)
96
+//     }, [bannerList, open])
97
+
98
+//     const toggleModal = () => {
99
+//         setModalIsOpen(!modalIsOpen)
100
+//         if (typeof onClose === 'function') {
101
+//             onClose()
102
+//         }
103
+
104
+//     }
105
+//     const styleInit = {
106
+//         header: (base, state) => ({ //头部样式
107
+//             position: 'absolute',
108
+//             top: 90,
109
+//             right: 90,
110
+//             zIndex: 9999,
111
+//         }),
112
+//         view: (base, state) => ({
113
+//             textAlign: 'center',
114
+//             height: state.isFullscreen ? '100%' : 600  //当点击全屏的时候图片样式
115
+//         })
116
+//     }
117
+//     return (
118
+//         <ModalGateway >
119
+//             {modalIsOpen ? (
120
+//                 <Modal onClose={toggleModal} >
121
+//                     <Carousel views={bannerList} styles={styleInit} />
122
+//                 </Modal>
123
+//             ) : null}
124
+//         </ModalGateway>
125
+//     );
126
+
127
+// }
128
+

+ 17
- 0
estateagents-admin-manager/src/pages/funds/accountfunds/components/contactText.jsx Ver fichero

@@ -0,0 +1,17 @@
1
+import React from 'react'
2
+import Navigate from '@/components/Navigate';
3
+
4
+const ContactText = () => {
5
+    // const toNewContact = () => {
6
+    //     const aTag = document.createElement('a')
7
+
8
+    //     aTag.setAttribute('href', `${window.location.origin}${window.location.pathname}#/funds/financialContact`);
9
+    //     aTag.setAttribute('target', '_blank')
10
+    //     document.body.appendChild(aTag)
11
+    //     aTag.click();
12
+    // }
13
+    return <a href={`${window.location.origin}${window.location.pathname}#/funds/financialContact`} style={{ color: '#1D74D9' }} target="_blank">请联系我们</a>
14
+
15
+}
16
+
17
+export default ContactText

+ 130
- 0
estateagents-admin-manager/src/pages/funds/accountfunds/components/styles.less Ver fichero

@@ -0,0 +1,130 @@
1
+
2
+  .redHeader{
3
+    width: 20%;
4
+    // height: 217px;
5
+    background:rgba(249,249,249,1);
6
+    border-radius:12px;
7
+    padding: 20px 24px;
8
+    .redHeaderTop{
9
+      text-align: center;
10
+      height: 122px;
11
+      font-family:PingFangSC-Regular,PingFang SC;
12
+      font-size:18px;
13
+      font-weight:400;
14
+      color:rgba(51,51,51,1);
15
+      .redHeaderTopText{
16
+        font-size:18px;
17
+        color:rgba(51,51,51,1);
18
+      }
19
+      .redHeaderTopNum{
20
+        font-size:48px;
21
+        font-weight:500;
22
+        color:rgba(255,126,72,1);
23
+line-height: 97px;
24
+      }
25
+    }
26
+    .redHeaderBottom{
27
+      padding-top: 10px;
28
+      border-top:1px solid rgba(216,216,216,1);
29
+      font-size:16px;
30
+      font-weight:400;
31
+      color:rgba(153,153,153,1);
32
+      // line-height:22px;
33
+    }
34
+  }
35
+
36
+  .mask{
37
+    width: 100vw;
38
+    height: 100vh;
39
+    // max-height: 600px;
40
+    background-color: rgba(0,0,0,0.32);
41
+    position: fixed;
42
+    z-index: 999;
43
+    top: 0;
44
+    left: 0;
45
+}
46
+
47
+  .btn {
48
+    width: 140px;
49
+    height: 45px;
50
+  }
51
+
52
+  .box{
53
+    height: 204px;
54
+    width: 204px;
55
+    // background-color:red;
56
+    margin: 37px 40px 40px 249px;
57
+    // borderRadius: '12px', border: '1px solid rgba(218,218,218,1', margin: '40px 0' 
58
+      // width: 100px; 
59
+      // height: 100px;
60
+      // border-radius:5px;
61
+      background: linear-gradient(to left, #1D74D9, #1D74D9) left top no-repeat, 
62
+            linear-gradient(to bottom, #1D74D9, #1D74D9) left top no-repeat, 
63
+            linear-gradient(to left, #1D74D9, #1D74D9) right top no-repeat,
64
+            linear-gradient(to bottom, #1D74D9, #1D74D9) right top no-repeat, 
65
+            linear-gradient(to left, #1D74D9, #1D74D9) left bottom no-repeat,
66
+            linear-gradient(to bottom, #1D74D9, #1D74D9) left bottom no-repeat,
67
+            linear-gradient(to left, #1D74D9, #1D74D9) right bottom no-repeat,
68
+            linear-gradient(to left, #1D74D9, #1D74D9) right bottom no-repeat;
69
+      background-size: 2px 10px, 10px 2px, 2px 10px, 10px 2px; 
70
+      padding: 5px;
71
+      // background-color:#aaaaaa
72
+    
73
+  }
74
+  .boxRight{
75
+    width: 400px;
76
+    margin: 40px 0;
77
+    // position: absolute;
78
+    // top: 50%;
79
+    // transform: translate(50%,-50%);
80
+    position:relative;
81
+    .child{
82
+      position: absolute;
83
+    top: 50%;
84
+    transform: translate(0,-50%);
85
+    font-size:18px;
86
+font-weight:400;
87
+color:rgba(102,102,102,1);
88
+float: left;
89
+// line-height:25px;
90
+    }
91
+  }
92
+
93
+  .content{
94
+    width: 32vw;
95
+    min-width: 757px;
96
+    height: 21.3vw;
97
+    min-height: 504px;
98
+    position: absolute;
99
+    left: 50%;
100
+    top: 110px;
101
+    transform: translateX(-50%);
102
+    border-radius: 10px;
103
+    .close{
104
+        width: 40px;
105
+        height: 40px;
106
+        position: absolute;
107
+        top: -22px;
108
+        right: -22px;
109
+        z-index: 9;
110
+    }
111
+}
112
+
113
+.carousel {
114
+  width: 32vw;
115
+  min-width: 757px;
116
+  height: 21.3vw;
117
+  min-height: 504px;
118
+  border-radius: 10px;
119
+  text-align: center;
120
+  
121
+  .carouselItem{
122
+      width: 32vw;
123
+      min-width: 757px;
124
+      height: 21.3vw;
125
+      min-height: 504px;
126
+      position: relative;
127
+      display: inline-block;
128
+     
129
+  }
130
+}

+ 68
- 0
estateagents-admin-manager/src/pages/funds/accountfunds/index.jsx Ver fichero

@@ -0,0 +1,68 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Radio } from 'antd';
3
+import router from 'umi/router';
4
+import moment from 'moment';
5
+import apis from '../../../services/apis';
6
+import request from '../../../utils/request';
7
+import Basic from './components/Basic';
8
+import RechargeOrder from './components/RechargeOrder'
9
+import ConsumerOrder from './components/ConsumerOrder'
10
+import RefundOrder from './components/RefundOrder'
11
+
12
+const H5configuration = props => {
13
+
14
+    const [tab, setTab] = useState('1')
15
+    const [data, setData] = useState({})
16
+
17
+    const id = props.location.query.id
18
+    // const type = props.activeType
19
+
20
+
21
+    useEffect(() => {
22
+        console.log(props)
23
+        // getData({ id: id, type: type })
24
+
25
+    }, [])
26
+
27
+    const getData = (params) => {
28
+
29
+        // request({ ...apis.activityDataStatis.getStatisticData, params: { ...params, } }).then((data) => {
30
+        //     console.log(data)
31
+        //     setData(data || {})
32
+        // })
33
+    }
34
+
35
+    function tabsCallback(e) {
36
+
37
+        setTab(e.target.value)
38
+    }
39
+    const onDetai = (e) => {
40
+        console.log(e)
41
+        setTab('4')
42
+    }
43
+
44
+
45
+    return <>
46
+
47
+        <div>
48
+            <Radio.Group value={tab} buttonStyle="solid" onChange={e => tabsCallback(e)}>
49
+                <Radio.Button value="1">基本信息</Radio.Button>
50
+                <Radio.Button value="2">充值订单</Radio.Button>
51
+                <Radio.Button value="3">消费订单</Radio.Button>
52
+                <Radio.Button value="4">退款订单</Radio.Button>
53
+            </Radio.Group>
54
+            <div style={{ marginTop: '20px' }}>
55
+                {/* 基本信息 */}
56
+                {(tab === '1' && <Basic />)}
57
+                {/* 充值订单 */}
58
+                {(tab === '2' && <RechargeOrder />)}
59
+                {/* 消费订单 */}
60
+                {(tab === '3' && <ConsumerOrder />)}
61
+                {/* 退款订单 */}
62
+                {(tab === '4' && <RefundOrder />)}
63
+            </div>
64
+        </div>
65
+    </>
66
+}
67
+
68
+export default H5configuration

+ 142
- 0
estateagents-admin-manager/src/pages/funds/financialContact/index.jsx Ver fichero

@@ -0,0 +1,142 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, Breadcrumb } from 'antd';
3
+import router from 'umi/router';
4
+import moment from 'moment';
5
+import apis from '../../../services/apis';
6
+import request from '../../../utils/request';
7
+
8
+function financialContact(props) {
9
+
10
+    // const [taNoticeList, setTaNoticeList] = useState([])
11
+    const [data, setData] = useState({})
12
+
13
+    useEffect(() => {
14
+        getList({ pageNum: 1, pageSize: 10 });
15
+    }, [])
16
+    // 查询列表
17
+
18
+    const getList = params => {
19
+        request({ ...apis.funds.list, params: { ...params } }).then(data => {
20
+            setData(data)
21
+        })
22
+    }
23
+
24
+    function handleSubmit(e) {
25
+        e.preventDefault();
26
+        props.form.validateFields((err, values) => {
27
+            if (!err) {
28
+                // eslint-disable-next-line no-console
29
+                console.log('提交数据: ', values)
30
+                getList({ ...values })
31
+            }
32
+        });
33
+    }
34
+
35
+    function handleReset() {
36
+        props.form.resetFields();
37
+
38
+        getList({ pageNum: 1, pageSize: 10 })
39
+    }
40
+
41
+    const columns = [
42
+        {
43
+            title: '姓名',
44
+            dataIndex: 'contactName',
45
+            key: 'contactName',
46
+            align: 'center',
47
+        },
48
+        {
49
+            title: '性别',
50
+            dataIndex: 'sex',
51
+            key: 'sex',
52
+            align: 'center',
53
+            render: x => <span>{x == 1 ? '男' : x === 2 ? '女' : '未知'}</span >,
54
+        },
55
+        {
56
+            title: '头像',
57
+            dataIndex: 'avatar',
58
+            key: 'avatar',
59
+            align: 'center',
60
+            render: (x, row) => <img src={row.avatar} alt="" width="93px" height="93px"></img >,
61
+        },
62
+        {
63
+            title: '固话',
64
+            dataIndex: 'telephone',
65
+            key: 'telephone',
66
+            align: 'center',
67
+        },
68
+        {
69
+            title: '手机号',
70
+            dataIndex: 'phone',
71
+            key: 'phone',
72
+            align: 'center',
73
+        },
74
+        {
75
+            title: '头衔',
76
+            dataIndex: 'appellation',
77
+            key: 'appellation',
78
+            align: 'center',
79
+        },
80
+    ]
81
+
82
+    const changePageNum = pageNumber => {
83
+        props.form.validateFields((err, values) => {
84
+            if (!err) {
85
+                getList({ pageNum: pageNumber, pageSize: 10, ...values })
86
+            }
87
+        });
88
+    }
89
+
90
+
91
+    const { getFieldDecorator } = props.form
92
+
93
+    return (
94
+
95
+        <>
96
+            <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
97
+                <Form.Item>
98
+                    {getFieldDecorator('contactName')(
99
+                        <Input
100
+                            placeholder="姓名"
101
+                        />,
102
+                    )}
103
+                </Form.Item>
104
+                <Form.Item>
105
+                    {getFieldDecorator('telephone')(
106
+                        <Input
107
+                            placeholder="固话"
108
+                        />,
109
+                    )}
110
+                </Form.Item>
111
+                <Form.Item>
112
+                    {getFieldDecorator('phone')(
113
+                        <Input
114
+                            placeholder="手机号"
115
+                        />,
116
+                    )}
117
+                </Form.Item>
118
+                <Form.Item>
119
+                    <Button type="primary" htmlType="submit"> 搜索</Button>
120
+                    <Button style={{ marginLeft: 8 }} onClick={handleReset}>重置</Button>
121
+                </Form.Item>
122
+            </Form>
123
+            {/* <div style={{ marginTop: '20px' }}>
124
+                <Button type="primary" style={{ float: 'right', marginBottom: '20px', zIndex: 1 }} >导出</Button>
125
+            </div> */}
126
+            <Table dataSource={data.records} columns={columns} pagination={false} style={{ marginTop: '20px' }} />
127
+            <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
128
+                <Pagination
129
+                    showQuickJumper
130
+                    defaultCurrent={1}
131
+                    total={data.total} onChange={e => changePageNum(e)} current={data.current} />
132
+            </div>
133
+        </>
134
+
135
+    )
136
+}
137
+
138
+
139
+const WrappedFinancialContact = Form.create({ name: 'financialContact' })(financialContact);
140
+
141
+export default WrappedFinancialContact
142
+

+ 45
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Demand/components/AddDemand.jsx Ver fichero

@@ -0,0 +1,45 @@
1
+import React, { PureComponent, useState, useEffect } from 'react'
2
+import { Modal, Row, Col, Table, Pagination, Button, Form, Input,message } from 'antd'
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import router from 'umi/router';
5
+import AuthButton from '@/components/AuthButton';
6
+
7
+// import Style from './style.less'
8
+// import HotBlock from '../HotBlock'
9
+import apis from '../../../../services/apis';
10
+import request from '../../../../utils/request';
11
+
12
+const BatchDel = props => {
13
+
14
+    function sampleList(record) {
15
+        router.push({
16
+          pathname: '/h5SampleManager/h5Sample/list',
17
+        })
18
+    }
19
+
20
+  return (
21
+    <>
22
+      <Modal footer={null} title="新增需求单" visible={props.visible} onCancel={props.onCancel} width={600}>
23
+        <div style={{textAlign:'center', marginBottom:'15px'}}>
24
+            <span style={{fontSize:'15px'}}>请到H5样例中筛选并查看详情后从详情提交需求单</span><br/>
25
+        </div>
26
+        <Form >
27
+          <Form.Item wrapperCol={{ span: 15, offset: 8 }}>
28
+            <Button type="primary" onClick={() => sampleList()}>
29
+              查看全部样例
30
+            </Button>
31
+            <Button onClick={props.onCancel} style={{marginLeft:'20px'}}>
32
+              取消
33
+            </Button>
34
+          </Form.Item>
35
+        </Form>
36
+        
37
+        
38
+      </Modal>
39
+    </>
40
+  );
41
+}
42
+
43
+const WrappedBase = Form.create({ name: 'BatchDel' })(BatchDel);
44
+
45
+export default WrappedBase

+ 56
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Demand/components/BatchDel.jsx Ver fichero

@@ -0,0 +1,56 @@
1
+import React, { PureComponent, useState, useEffect } from 'react'
2
+import { Modal, Row, Col, Table, Pagination, Button, Form, Input,message } from 'antd'
3
+// import EnDash from '../EnDash'
4
+import AuthButton from '@/components/AuthButton';
5
+
6
+// import Style from './style.less'
7
+// import HotBlock from '../HotBlock'
8
+import apis from '../../../../services/apis';
9
+import request from '../../../../utils/request';
10
+
11
+const BatchDel = props => {
12
+  const taRaiseRecords = props.demandIds;
13
+  function handleSubmit (e) {
14
+    e.preventDefault();
15
+    props.form.validateFields((err, values) => {
16
+      if (!err){
17
+        request({ ...apis.taH5SampleManager.batchDelDemands, data: { taH5Demands: taRaiseRecords }, }).then((data) => {
18
+          const resultMessage = '操作成功,其中'+data.successNum+'条成功删除,'+data.failNum+'条非作废/提交状态未删除。'
19
+          message.info(resultMessage)
20
+          props.onSuccess(false);
21
+        }).catch((err) => {
22
+          message.info(err.msg || err.message)
23
+        })
24
+      }
25
+    });
26
+  }
27
+
28
+  const { getFieldDecorator } = props.form;
29
+
30
+  return (
31
+    <>
32
+      <Modal footer={null} title="确认删除" visible={props.visible} onCancel={props.onCancel} width={600}>
33
+        <div style={{textAlign:'center', marginBottom:'30px'}}><span style={{fontSize:'20px'}}>确认将所选{taRaiseRecords.length}条数据删除?</span></div>
34
+        <div style={{textAlign:'center', marginBottom:'15px'}}>
35
+            <span style={{fontSize:'15px'}}>可删除条件:需求单状态 为已提交或作废</span><br/>
36
+        </div>
37
+        <Form labelCol={{ span: 7 }} wrapperCol={{ span: 12 }} onSubmit={handleSubmit}>
38
+          <Form.Item wrapperCol={{ span: 15, offset: 10 }}>
39
+            <Button type="primary" htmlType="submit" >
40
+              确定
41
+            </Button>
42
+            <Button onClick={props.onCancel} style={{marginLeft:'20px'}}>
43
+              取消
44
+            </Button>
45
+          </Form.Item>
46
+        </Form>
47
+        
48
+        
49
+      </Modal>
50
+    </>
51
+  );
52
+}
53
+
54
+const WrappedBase = Form.create({ name: 'BatchDel' })(BatchDel);
55
+
56
+export default WrappedBase

+ 138
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Demand/detail.jsx Ver fichero

@@ -0,0 +1,138 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker, InputNumber, Checkbox, Row, Col} from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import XForm, { FieldTypes } from '../../../components/XForm';
5
+import router from 'umi/router';
6
+import moment from 'moment';
7
+import apis from '../../../services/apis';
8
+import request from '../../../utils/request';
9
+import AuthButton from '@/components/AuthButton';
10
+import Wangedit from '../../../components/Wangedit/Wangedit'
11
+import TextArea from 'antd/lib/input/TextArea';
12
+import Navigate from '@/components/Navigate';
13
+
14
+const { Option } = Select;
15
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
16
+
17
+
18
+const header = props => {
19
+  const demandId  = props.location.query.id;
20
+  const [demandData, setDemandData] = useState({})
21
+
22
+  useEffect(() => {
23
+    getDemandData(demandId);
24
+  },[])
25
+
26
+  // 查询列表
27
+  const getDemandData = (demandId) => {
28
+      request({ ...apis.taH5SampleManager.taH5DemandById, urlData: {id: demandId} }).then((data) => {
29
+          setDemandData(data)
30
+          props.form.setFieldsValue(data)
31
+      })
32
+  }
33
+
34
+  // 跳转到编辑
35
+  const toDetail = rowData => () => {
36
+    if(rowData) {
37
+      router.push({
38
+      pathname: '/h5SampleManager/h5Demand/edit',
39
+      query: {
40
+        id: demandId,
41
+      },
42
+    });
43
+      return
44
+    }
45
+  }
46
+
47
+  function sampleDetail(sampleId){
48
+    request({ ...apis.taH5SampleManager.taH5SampleById, urlData: { id: sampleId } }).then((data) => {
49
+      router.push({
50
+        pathname: '/h5SampleManager/h5Sample/detail',
51
+        query: {
52
+          id: sampleId,
53
+        },
54
+      });
55
+    }).catch(err => {
56
+      message.info("该H5样例已取消发布或已删除")
57
+    })
58
+  }
59
+
60
+  function handleSubmit (e) {
61
+    e.preventDefault();
62
+    props.form.validateFields((err, values) => {
63
+      if (!err){
64
+        console.log(values,'valuesvaluesvalues')
65
+        if (values.payType == 'onLine' && (values.payDescriptionOnline == '' || values.payDescriptionOnline == null)){
66
+            message.info("请填写线上缴费说明");
67
+            return;
68
+        }
69
+        if (values.payType == 'offLine' && (values.payDescriptionOffline == '' || values.payDescriptionOffline == null)){
70
+          message.info("请填写线下缴费说明");
71
+          return;
72
+        }
73
+        if ((values.payType == 'onLine' && (values.payDescriptionOnline == '' || values.payDescriptionOnline == null)) ||
74
+            (values.payType == 'offLine' && (values.payDescriptionOffline == '' || values.payDescriptionOffline == null))){
75
+          message.info("请填写缴费说明");
76
+          return;
77
+        }
78
+        
79
+        let {liveTime, ...submitValue} = values
80
+        if (values.raiseStartTime > values.raiseEndTime){
81
+          message.info("认筹结束时间大于认筹开始时间")
82
+          return;
83
+        }
84
+        submitValue.raiseStartTime = moment(submitValue.raiseStartTime).format('YYYY-MM-DD HH:mm:ss')
85
+        submitValue.raiseEndTime = moment(submitValue.raiseEndTime).format('YYYY-MM-DD HH:mm:ss')
86
+        submitValue.payType = values.payType.toString();
87
+        submitValue.raisePrice = submitValue.raisePrice * 100;
88
+        request({ ...apis.house.addRaise, data: { ...submitValue },}).then((data) => {
89
+          message.info("保存成功")
90
+          router.push({
91
+            pathname: '/house/raise/list',
92
+          });
93
+        }).catch((err) => {
94
+          message.info(err.msg || err.message)
95
+        })
96
+      }
97
+    });
98
+  }
99
+
100
+  const { getFieldDecorator } = props.form;
101
+
102
+  return (
103
+    <>
104
+      <Form labelCol={{ span: 7 }} wrapperCol={{ span: 12 }} onSubmit={handleSubmit}>
105
+        <Form.Item label="样例名">
106
+          <Navigate onClick={() => sampleDetail(demandData.sampleId)}>{demandData.sampleName}</Navigate>
107
+        </Form.Item>
108
+        <Form.Item label="下单人">
109
+          <span>{demandData.orderer}</span>
110
+        </Form.Item>
111
+        <Form.Item label="联系方式">
112
+        <span>{demandData.phone}</span>
113
+        </Form.Item>
114
+        <Form.Item label="下单时间">
115
+        <span>{`${moment(demandData.createDate).format('YYYY-MM-DD HH:mm')}`}</span>
116
+        </Form.Item>
117
+        <Form.Item label="更新时间">
118
+        <span>{`${moment(demandData.updateDate).format('YYYY-MM-DD HH:mm')}`}</span>
119
+        </Form.Item>
120
+        <Form.Item label="需求单状态">
121
+        <span>{demandData.demandStatus === 1 ? "已提交": demandData.demandStatus === 2 ?"处理中":demandData.demandStatus === 3?"已交付":"作废"}</span>
122
+        </Form.Item>
123
+        <Form.Item label="需求描述">
124
+          {getFieldDecorator('demandContent')(<Wangedit contenteditable={false}/>)}
125
+        </Form.Item>
126
+        <Form.Item wrapperCol={{ span: 15, offset: 7 }}>
127
+          <Button type="primary"  onClick={toDetail(demandId)} style={{marginRight:'20px'}}>
128
+            修改需求
129
+          </Button>
130
+        </Form.Item>
131
+      </Form>
132
+    </>
133
+  )
134
+}
135
+
136
+const WrappedHeader = Form.create({ name: 'header' })(header);
137
+
138
+export default WrappedHeader

+ 69
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Demand/detail.less Ver fichero

@@ -0,0 +1,69 @@
1
+.searchBox {
2
+    font-size: 20px;
3
+    color: red;
4
+    display: flex;
5
+    display: flex;
6
+    align-items: center;
7
+    justify-content: space-between;
8
+    .searchItem {
9
+      min-width: 20px;
10
+      margin-right: 20px;
11
+      text-align: left;
12
+      .anticon-down {
13
+        float: right !important;
14
+      }
15
+    }
16
+  }
17
+  .addBtn {
18
+    padding: 0 30px;
19
+    height: 36px;
20
+    background-color: #50be00;
21
+    color: #fff;
22
+    margin: 30px 0;
23
+  }
24
+  .touxiang {
25
+    width: 93px;
26
+    height: 93px;
27
+  }
28
+  .ant-table-column-title {
29
+    font-weight: 600;
30
+  }
31
+  
32
+  .about {
33
+    padding: 0 30px;
34
+    height: 36px;
35
+    margin: 30px 0;
36
+    margin-left:8px;
37
+  }
38
+  
39
+  .selectName {
40
+    font-size: 14px;
41
+    padding: 0 10px;
42
+    height: 36px;
43
+    color: rgb(10, 10, 10);
44
+    margin: 30px 0;
45
+  }
46
+  
47
+  .inpuit {
48
+    width:50%;
49
+  }
50
+  
51
+  .inpuitTxt {
52
+    width:70%;
53
+  }
54
+  
55
+  
56
+  .formButton{
57
+    margin-left: 12% 
58
+  }
59
+  
60
+  .divInput{
61
+    float: 'left'; 
62
+    width: 500
63
+  }
64
+  .brokerTable{
65
+    padding: 0 30px;
66
+    height: 36px;
67
+    margin: 30px 0;
68
+  }
69
+  

+ 87
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Demand/edit.jsx Ver fichero

@@ -0,0 +1,87 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Input, Menu, Dropdown, Button, Icon, message, Table, Divider, Tag, Select, Form, Alert } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import Wangedit from '../../../components/Wangedit/Wangedit'
5
+import router from 'umi/router';
6
+import channels from './detail.less';
7
+import apis from '../../../services/apis';
8
+import request from '../../../utils/request'
9
+
10
+const { TextArea } = Input;
11
+const { Option } = Select;
12
+
13
+const header = props => {
14
+
15
+  // eslint-disable-next-line react-hooks/rules-of-hooks
16
+  useEffect(() => {
17
+    getById()
18
+  }, [])
19
+
20
+
21
+  // 查询当前信息
22
+  function getById(params) {
23
+    request({ ...apis.taH5SampleManager.taH5DemandById, urlData: { id: props.location.query.id } }).then((data) => {
24
+      props.form.setFieldsValue(data)
25
+    }).catch((err) => {
26
+      console.log(err)
27
+      message.info(err.msg || err.message)
28
+    })
29
+  }
30
+
31
+  // 编辑
32
+  function editDemandById(data) {
33
+    console.log('datadata', data)
34
+    console.log('props.location.query.id', props.location.query.id)
35
+    request({ ...apis.taH5SampleManager.updateH5DemandById, urlData: { id: props.location.query.id }, data: { ...data } }).then((data) => {
36
+      router.go(-1)
37
+    }).catch((err) => {
38
+      console.log(err)
39
+      message.info(err.msg || err.message)
40
+    })
41
+  }
42
+
43
+
44
+  function handleSubmit(e) {
45
+    e.preventDefault();
46
+    props.form.validateFields((err, values) => {
47
+      if (!err) {
48
+        console.log('values', values)
49
+        if (values.demandContent == '<p><br></p>') {
50
+          message.info("请填写需求内容")
51
+          return
52
+        }
53
+        editDemandById({ ...values })
54
+      }
55
+    });
56
+  }
57
+  function go() {
58
+    router.push({
59
+      pathname: '/h5SampleManager/h5Demand/list',
60
+    });
61
+  }
62
+
63
+  const { getFieldDecorator } = props.form;
64
+
65
+  return (
66
+    <>
67
+      <Form labelCol={{ span: 6 }} wrapperCol={{ span: 12 }} onSubmit={handleSubmit}>
68
+        <Form.Item label="修改需求" help="注意,修改的需求可能会大幅增加开发时间,请在增加前和联系人确认,若需求对应开发工作量较大,可能需要重新评估报价和开发周期,因此,建议一次性提交完全部需求">
69
+          {getFieldDecorator('sampleName')(<Input disabled={true} />)}
70
+        </Form.Item>
71
+        <Form.Item label="需求描述" style={{ marginTop: '20px' }}>
72
+          {getFieldDecorator('demandContent', {
73
+            rules: [{ required: true, message: '请输入需求描述' }],
74
+          })(<Wangedit />)}
75
+        </Form.Item>
76
+        <Form.Item wrapperCol={{ offset: 9 }}>
77
+          <div style={{ display: 'flex', alignItems: 'center', width: '220px' }}>    <Button type="primary" htmlType="submit">
78
+            保存
79
+          </Button>
80
+            <Button className={channels.formButton} onClick={() => router.go(-1)}>取消</Button></div>
81
+        </Form.Item>
82
+      </Form>
83
+    </>
84
+  )
85
+}
86
+const WrappedNormalLoginForm = Form.create({ name: 'header' })(header);
87
+export default WrappedNormalLoginForm

+ 255
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Demand/list.jsx Ver fichero

@@ -0,0 +1,255 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import router from 'umi/router';
5
+import moment from 'moment';
6
+import styles from '../../style/GoodsList.less';
7
+import SelectCity from '../../../components/SelectButton/CitySelect'
8
+import BuildSelect from '../../../components/SelectButton/BuildSelect'
9
+import apis from '../../../services/apis';
10
+import request from '../../../utils/request';
11
+import BatchDel from './components/BatchDel';
12
+import AddDemand from './components/AddDemand';
13
+import AuthButton from '@/components/AuthButton';
14
+import withActions from '@/components/ActionList';
15
+import EditIcon from '@/components/EditIcon';
16
+import Navigate from '@/components/Navigate';
17
+
18
+const { Option } = Select;
19
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
20
+
21
+const header = props => {
22
+  const sampleId  = props.location.query.id;
23
+  const sampleName = props.location.query.sampleName;
24
+  const [data, setData] = useState({})
25
+  const [demend, setDemend] = useState({})
26
+  const [demandIds, setDemandIds] = useState([])
27
+  const [batchDel, setBatchDel] = useState({visable:false,demandIds:''})
28
+  const [addDemand, setAddDemand] = useState({visable:false})
29
+
30
+  useEffect(() => {
31
+    if(sampleId){
32
+      getList({ pageNum: 1, pageSize: 10, sampleId: sampleId });
33
+    }else{
34
+      getList({ pageNum: 1, pageSize: 10});
35
+    }
36
+    
37
+  }, [])
38
+
39
+  // 查询列表
40
+  const getList = (params) => {
41
+    console.log(params);
42
+    request({ ...apis.taH5SampleManager.taH5Demand, params: { ...params } }).then((data) => {
43
+      console.log(data)
44
+      setData(data)
45
+    })
46
+  }
47
+
48
+  // 跳转到编辑
49
+  const toDetail = rowData => () => {
50
+    if(rowData) {
51
+      router.push({
52
+      pathname: '/h5SampleManager/h5Demand/detail',
53
+      query: {
54
+        id: rowData.demandId,
55
+      },
56
+    });
57
+      return
58
+    }
59
+  }
60
+
61
+  /**
62
+   *
63
+   *
64
+   * @param {*} props
65
+   * @returns
66
+   */
67
+
68
+  const columns = [
69
+    {
70
+      title: '样例名',
71
+      dataIndex: 'sampleName',
72
+      key: 'sampleName',
73
+      align: 'center',
74
+      render:  (x, row) => <Navigate onClick={toDetail(row)}>{row.sampleName}</Navigate>,
75
+    },
76
+    {
77
+      title: '下单人',
78
+      dataIndex: 'orderer',
79
+      key: 'orderer',
80
+      align: 'center',
81
+      
82
+    },
83
+    {
84
+      title: '联系方式',
85
+      dataIndex: 'phone',
86
+      key: 'phone',
87
+      align: 'center',
88
+    },
89
+    {
90
+      title: '下单时间',
91
+      dataIndex: 'createDate',
92
+      key: 'createDate',
93
+      align: 'center',
94
+      render: (x, row) => <><span>{`${moment(row.createDate).format('YYYY-MM-DD HH:mm:ss')}`}</span></>
95
+    },
96
+    {
97
+      title: '需求单状态',
98
+      dataIndex: 'demandStatus',
99
+      key: 'demandStatus',
100
+      align: 'center',
101
+      render: (text, records) => {
102
+        if (records.demandStatus === 1) { return '已提交' }
103
+        if (records.demandStatus === 2) { return '处理中' }
104
+        if (records.demandStatus === 3) { return '已交付' }
105
+        if (records.demandStatus === 4) { return '作废' }
106
+      },
107
+    },
108
+    {
109
+      title: '操作',
110
+      dataIndex: 'handle',
111
+      key: 'handle',
112
+      align: 'center',
113
+      render: withActions((text, record) =>[ (
114
+        <AuthButton name="admin.h5Demand.detail.get" noRight={null}>
115
+          <EditIcon type="look" text="查看详情" onClick={toDetail(record)}></EditIcon>
116
+        </AuthButton>
117
+      )]
118
+      ),
119
+    },
120
+  ];
121
+  
122
+  const rowSelection = {
123
+    onChange: (selectedRowKeys, selectedRows) => {
124
+      console.log('selectedRowKeys:', selectedRowKeys, 'selectedRows: ', selectedRows);
125
+      setDemandIds(selectedRows)
126
+    },
127
+  };
128
+
129
+  const changePageNum = pageNumber => {
130
+    getList({ pageNum: pageNumber, pageSize: 10, ...props.form.getFieldsValue() })
131
+  }
132
+
133
+  // 提交事件
134
+  const handleSubmit = (e, props) => {
135
+    e.preventDefault();
136
+    props.form.validateFields((err, values) => {
137
+      if (!err) {
138
+        
139
+        if (values.startCreateDate != null){
140
+          values.startCreateDate = moment(values.startCreateDate).format('YYYY-MM-DD HH:mm:ss')
141
+        }
142
+        if (values.endCreateDate != null){
143
+          values.endCreateDate = moment(values.endCreateDate).format('YYYY-MM-DD HH:mm:ss')
144
+        }
145
+        getList({ pageNum: 1, pageSize: 10, ...values })
146
+      }
147
+    });
148
+  }
149
+
150
+  //重置搜索
151
+  function handleReset () {
152
+    props.form.resetFields();
153
+    getList({ pageNum: 1, pageSize: 10 })
154
+  }
155
+
156
+  function showBatchDel(e){
157
+  
158
+    if (demandIds.length <= 0){
159
+      message.info("请选择数据");
160
+      return;
161
+    }
162
+    setBatchDel(e);
163
+    if(!e.visable){
164
+      getList()
165
+    }
166
+  }
167
+
168
+  function addDemandInfo(e){
169
+    setAddDemand(e);
170
+  }
171
+
172
+  const { getFieldDecorator } = props.form
173
+  return (
174
+
175
+    <>
176
+      <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
177
+        <Form.Item>
178
+          {getFieldDecorator('sampleName',{
179
+            initialValue: sampleName
180
+          })(
181
+            <Input
182
+            prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
183
+            placeholder="样例名"
184
+          />,
185
+          )}
186
+        </Form.Item>
187
+        <Form.Item>
188
+          {getFieldDecorator('orderer')(
189
+            <Input
190
+            prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
191
+            placeholder="下单人"
192
+          />,
193
+          )}
194
+        </Form.Item>
195
+        <Form.Item>
196
+          {getFieldDecorator('phone')(
197
+            <Input
198
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
199
+              placeholder="联系方式"
200
+            />,
201
+          )}
202
+        </Form.Item>
203
+        <Form.Item>
204
+          {getFieldDecorator('startCreateDate')(
205
+            <DatePicker showTime={{ format: 'HH:mm:ss' }} placeholder="下单时间开始时间"/>,
206
+          )}
207
+        </Form.Item>
208
+        <Form.Item>
209
+          {getFieldDecorator('endCreateDate')(
210
+            <DatePicker showTime={{ format: 'HH:mm:ss' }} placeholder="下单时间结束时间"/>,
211
+          )}
212
+        </Form.Item>  
213
+        <Form.Item>
214
+          {getFieldDecorator('demandStatus')(
215
+            <Select style={{ width: '180px' }} placeholder="需求单状态">
216
+                <option value="">全部</option>
217
+                <option value="1">已提交</option>
218
+                <option value="2">处理中</option>
219
+                <option value="3">已交付</option>
220
+                <option value="4">作废</option>
221
+            </Select>
222
+          )}
223
+        </Form.Item>
224
+        <Form.Item>
225
+            <AuthButton name="admin.taShareActivity.search" noRight={null}>
226
+                <Button type="primary" htmlType="submit" className={styles.searchBtn}>
227
+                    搜索
228
+                </Button>
229
+            </AuthButton>
230
+            <AuthButton name="admin.taShareActivity.search" noRight={null}>
231
+                <Button style={{ marginLeft: 8 }} onClick={handleReset}>
232
+                        重置
233
+                </Button>
234
+            </AuthButton>
235
+        </Form.Item>
236
+      </Form>
237
+      <AuthButton name="admin.h5Demand.add.post" noRight={null}>
238
+        <Button type="danger" onClick={() => addDemandInfo({visable:true})} className={styles.addBtn}>新增</Button>
239
+      </AuthButton>
240
+      <AuthButton name="admin.h5Demand.del" noRight={null}>
241
+        <Button type="primary" onClick={() => showBatchDel({visable:true, demandIds: demandIds})} className={styles.addBtn} style={{marginLeft:'30px'}}>删除</Button>
242
+      </AuthButton>
243
+      <AddDemand visible={addDemand.visable} onCancel={() => addDemandInfo({visable:false})}></AddDemand>
244
+      <BatchDel visible={batchDel.visable} demandIds={batchDel.demandIds} onCancel={() => showBatchDel({visable:false, demandIds: ''})} onSuccess={() => showBatchDel({visable:false, demandIds:'' })}/>
245
+      <Table rowSelection={rowSelection}
246
+        style={{marginTop:'30px'}} dataSource={data.records} columns={columns} pagination={false} rowKey="activityList" />
247
+      <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
248
+        <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} current={data.current} />
249
+      </div>
250
+    </>
251
+  )
252
+}
253
+const WrappedHeader = Form.create({ name: 'header' })(header);
254
+
255
+export default WrappedHeader

+ 111
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/add.jsx Ver fichero

@@ -0,0 +1,111 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker, InputNumber, Checkbox, Row, Col} from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import XForm, { FieldTypes } from '../../../components/XForm';
5
+import router from 'umi/router';
6
+import moment from 'moment';
7
+import apis from '../../../services/apis';
8
+import request from '../../../utils/request';
9
+import AuthButton from '@/components/AuthButton';
10
+import Wangedit from '../../../components/Wangedit/Wangedit'
11
+import TextArea from 'antd/lib/input/TextArea';
12
+
13
+const { Option } = Select;
14
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
15
+
16
+
17
+const header = props => {
18
+  const sampleId  = props.location.query.id;
19
+  const sampleName  = props.location.query.sampleName;
20
+  const [sampleData, setSampleData] = useState({})
21
+
22
+//   useEffect(() => {
23
+//     getSampleData(sampleId);
24
+//   },[])
25
+
26
+//   // 查询列表
27
+//   const getSampleData = (demandId) => {
28
+//       request({ ...apis.taH5SampleManager.taH5DemandById, urlData: {id: demandId} }).then((data) => {
29
+//           setDemandData(data)
30
+//           props.form.setFieldsValue(data)
31
+//       })
32
+//   }
33
+
34
+  // 跳转到编辑
35
+  const toDetail = rowData => () => {
36
+    if(rowData) {
37
+      router.push({
38
+      pathname: '/h5SampleManager/h5Demand/edit',
39
+      query: {
40
+        id: demandId,
41
+      },
42
+    });
43
+      return
44
+    }
45
+  }
46
+
47
+  function handleSubmit (e) {
48
+    e.preventDefault();
49
+    props.form.validateFields((err, values) => {
50
+      if (!err){
51
+        values.sampleId = sampleId
52
+        values.sampleName = sampleName
53
+        request({ ...apis.taH5SampleManager.addTaH5Demand, data: { ...values },}).then((data) => {
54
+          message.info("保存成功")
55
+          router.go(-1);
56
+        }).catch((err) => {
57
+          message.info(err.msg || err.message)
58
+        })
59
+      }
60
+    });
61
+  }
62
+
63
+  const { getFieldDecorator } = props.form;
64
+
65
+  return (
66
+    <>
67
+      <Form labelCol={{ span: 7 }} wrapperCol={{ span: 12 }} onSubmit={handleSubmit}>
68
+        <Form.Item label="样例名">
69
+          {/* {getFieldDecorator('sampleName')(<Input disabled={true}/>)} */}
70
+          <span>{sampleName}</span>
71
+        </Form.Item>
72
+        <Form.Item label="下单人">
73
+          {getFieldDecorator('orderer',{
74
+          rules: [
75
+            {
76
+              required: true,
77
+              message: '请填写下单人',
78
+            },
79
+          ],
80
+        })(<Input maxLength={20}/>)}
81
+        </Form.Item>
82
+        <Form.Item label="联系方式">
83
+          {getFieldDecorator('phone',{
84
+          rules: [
85
+            {
86
+              required: true,
87
+              message: '请填写正确的联系方式',
88
+              // max:11,
89
+              // min:11,
90
+              pattern: new RegExp('^1[0-9]{10}$'),
91
+            },
92
+          ],
93
+        })(<Input/>)}
94
+        </Form.Item>
95
+        <Form.Item label="需求描述">
96
+          <span style={{color:'rgba(0, 0, 0, 0.45)', fontSize:'14px'}}>请在下方填写定制化内容,如替换样例中的企业名称、logo文案等,如暂不确定,可先不填,提交后可在H5需求单详情中继续修改</span>
97
+          {getFieldDecorator('demandContent')(<Wangedit />)}
98
+        </Form.Item>
99
+        <Form.Item style={{ width: '400px', margin: 'auto', display: 'flex', justifyContent: 'space-between' }}>
100
+            <Button type="primary" htmlType="submit">保存</Button>
101
+            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
102
+            <Button onClick={() => router.go(-1)}>取消</Button>
103
+         </Form.Item>
104
+      </Form>
105
+    </>
106
+  )
107
+}
108
+
109
+const WrappedHeader = Form.create({ name: 'header' })(header);
110
+
111
+export default WrappedHeader

+ 248
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/addH5.jsx Ver fichero

@@ -0,0 +1,248 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker, InputNumber, Checkbox, Row, Col } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import router from 'umi/router';
5
+import moment from 'moment';
6
+import apis from '../../../services/apis';
7
+import request from '../../../utils/request';
8
+import AuthButton from '@/components/AuthButton';
9
+import ImageUploader from '../../../components/XForm/ImageUpload';
10
+import BuildSelect from '../../../components/SelectButton/BuildSelect2'
11
+
12
+const header = props => {
13
+    const sampleId = props.location.query.id;
14
+
15
+    const [data, setData] = useState({})
16
+
17
+    const [visible, setVisible] = useState(false)
18
+    // const sampleName = props.location.query.sampleName;
19
+    // const [sampleData, setSampleData] = useState({})
20
+
21
+    //   useEffect(() => {
22
+    //     getSampleData(sampleId);
23
+    //   },[])
24
+
25
+    //   // 查询列表
26
+    //   const getSampleData = (demandId) => {
27
+    //       request({ ...apis.taH5SampleManager.taH5DemandById, urlData: {id: demandId} }).then((data) => {
28
+    //           setDemandData(data)
29
+    //           props.form.setFieldsValue(data)
30
+    //       })
31
+    //   }
32
+
33
+    // 跳转到编辑
34
+    const toDetail = rowData => () => {
35
+        if (rowData) {
36
+            router.push({
37
+                pathname: '/h5SampleManager/h5Demand/edit',
38
+                query: {
39
+                    id: demandId,
40
+                },
41
+            });
42
+            return
43
+        }
44
+    }
45
+
46
+    function handleSubmit(e) {
47
+        e.preventDefault();
48
+        props.form.validateFields((err, values) => {
49
+            if (!err) {
50
+                values.h5SampleId = sampleId
51
+                values.endDate = moment(values.endDate._d).format('YYYY-MM-DD HH:mm:ss')
52
+                values.isMiniapp = 1
53
+                values.fromH5Sample = true
54
+                request({ ...apis.activity.addtaDrainage, data: { ...values } }).then(data => {
55
+                    message.info('操作成功')
56
+                    setData(data)
57
+                    setVisible(true)
58
+
59
+                }).catch(err => {
60
+                    message.error(err.msg || err.message)
61
+                })
62
+
63
+                // values.sampleName = sampleName
64
+                // request({ ...apis.taH5SampleManager.addTaH5Demand, data: { ...values } }).then(() => {
65
+                //     message.info('保存成功')
66
+                //     // router.go(-1);
67
+                // }).catch((err) => {
68
+                //     message.info(err.msg || err.message)
69
+                // })
70
+            }
71
+        });
72
+    }
73
+
74
+    function disabledDate(current) {
75
+        // Can not select days before today and today 
76
+        // console.log(current, 'current')
77
+        // return current && current < moment().startOf('day');
78
+        return current < moment().add(0, 'd');
79
+    }
80
+
81
+    const disabledHours = () => {
82
+        const hours = [];
83
+        console.log(moment().hour(), 'moment().hour()')
84
+        for (let i = 0; i < moment().hour(); i++) {
85
+            hours.push(i);
86
+        }
87
+        return hours;
88
+    };
89
+
90
+    const disabledMinutes = currentDate => {
91
+        const currentMinute = moment().minute();
92
+        const currentHour = moment(currentDate).hour();
93
+        const minutes = [];
94
+        if (currentHour === moment().hour()) {
95
+            for (let i = 0; i <= currentMinute; i++) {
96
+                minutes.push(i);
97
+            }
98
+        }
99
+        return minutes;
100
+    };
101
+
102
+    const disabledTime = dateTime => {
103
+        if (moment(dateTime).isBefore(moment(), 'day')) {
104
+            return {
105
+                disabledHours: () => [],
106
+                disabledMinutes: () => [],
107
+            };
108
+        }
109
+        console.log(moment(dateTime).isSame(moment(), 'day'), 'moment(dateTime).isSame(moment(), )')
110
+        console.log(moment(dateTime).isSame(moment().add(1, 'days'), 'day'), 'moment(dateTime).isSame(moment().add(1,  )')
111
+        if (moment(dateTime).isSame(moment().add(1, 'days'), 'day')) {
112
+            return {
113
+                disabledHours: () => disabledHours(dateTime),
114
+                disabledMinutes: () => disabledMinutes(dateTime),
115
+            };
116
+        }
117
+    };
118
+
119
+    const toH5Edit = () => {
120
+        router.push({
121
+            pathname: '/activity/drainage/h5edit',
122
+            query: {
123
+                id: data.activityId,
124
+                name: data.name,
125
+                drainageId: data.drainageId,
126
+            },
127
+        });
128
+    }
129
+
130
+    const toDrainageDetail = () => {
131
+        router.push({
132
+            pathname: '/activity/drainage/DetailDrainage',
133
+            query: {
134
+                drainageId: data.drainageId,
135
+            },
136
+        });
137
+    }
138
+
139
+    const { getFieldDecorator } = props.form;
140
+
141
+    function validatorNum(rule, value, callback) {
142
+        callback(value < 1 || value > 1000 ? '人数必须大于0 小于 1000' : undefined);
143
+    }
144
+
145
+    return (
146
+        <>
147
+            <Form labelCol={{ span: 7 }} wrapperCol={{ span: 12 }} onSubmit={handleSubmit}>
148
+                <Form.Item label="H5活动名称">
149
+                    {getFieldDecorator('name', {
150
+                        rules: [
151
+                            {
152
+                                required: true,
153
+                                message: '请填写活动名称',
154
+                            },
155
+                        ],
156
+                    })(<Input placeholder="H5活动名称" />)}
157
+                </Form.Item>
158
+                <Form.Item label="选择项目">
159
+                    {getFieldDecorator('buildingId')(
160
+                        <BuildSelect />,
161
+                    )}
162
+                </Form.Item>
163
+                <Form.Item label="下架时间">
164
+                    {getFieldDecorator('endDate', {
165
+                        // initialValue: formsdate.endDate ? moment(formsdate.endDate, 'YYYY-MM-DD HH:mm:ss') : null,
166
+                        rules: [
167
+                            { required: true, message: '请输入下架时间' },
168
+
169
+                            // {
170
+                            //     validator: (rule, value, callback) => {
171
+                            //         callback(moment(value).isSame(moment().add(1, 'days'), 'day') ? '金额最多5位整数 2位小数' : undefined)
172
+                            //     }
173
+                            // }
174
+
175
+                        ]
176
+                    })(
177
+                        <DatePicker
178
+                            showTime={{ format: 'HH:mm:ss' }}
179
+                            disabledDate={disabledDate}
180
+                            disabledTime={disabledTime}
181
+                            showToday={false}
182
+                        />,
183
+                    )}
184
+                </Form.Item>
185
+                <Form.Item label="分享设置" help="建议图片尺寸:750*600px,比例5:4,格式:jpg">
186
+                    {getFieldDecorator('shareImg', {
187
+                        // initialValue: formsDate.shareImg,
188
+                        rules: [
189
+                            { required: true, message: '请选择分享图片' },
190
+                        ]
191
+                    })(<ImageUploader />)}
192
+                </Form.Item>
193
+                <Form.Item label="活动分享语" help="可使用{name}代表用户昵称。">
194
+                    {getFieldDecorator('shareTitle', {
195
+                        // initialValue: formsDate.shareTitle,
196
+                        rules: [
197
+                            { required: true, message: '请输入活动分享语' },
198
+                        ]
199
+                    })(
200
+                        <Input
201
+                            placeholder="分享语,不超过15个字"
202
+                            maxLength="15"
203
+                        />,
204
+                    )}
205
+                </Form.Item>
206
+                <Form.Item label="中间页飞机图" help="建议图片尺寸:750*1667px,比例9:20,格式:jpg。图片底部不要放置关键信息。">
207
+                    {getFieldDecorator('middleImg', {
208
+                        // initialValue: formsDate.middleImg,
209
+                        rules: [
210
+                            { required: true, message: '请选择中间页飞机图' },
211
+                        ]
212
+                    })(<ImageUploader />)}
213
+                </Form.Item>
214
+                <Form.Item style={{ width: '400px', margin: 'auto', display: 'flex', justifyContent: 'space-between' }}>
215
+                    <Button type="primary" htmlType="submit">保存</Button>
216
+            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
217
+            <Button onClick={() => router.go(-1)}>取消</Button>
218
+
219
+                </Form.Item>
220
+                <Row>
221
+                    <Col span={7}></Col>
222
+                    <Col span={17}><span style={{ color: '#ef273a' }}>发布后请到资源位管理中关联资源位图,否则客户看不到</span></Col>
223
+                </Row>
224
+            </Form>
225
+            <Modal
226
+                title="新增成功"
227
+                visible={visible}
228
+                // onOk={handleOk}
229
+                // confirmLoading={confirmLoading}
230
+                onCancel={() => setVisible(false)}
231
+                footer={null}
232
+            // width="1000px"
233
+            // maskClosable={false}
234
+            >
235
+                建议修改内容以适合您的项目,若有红包等需要消费的内容,请到资金管理中查看余额是否充足
236
+                <div style={{ width: '300px', margin: '30px auto', display: 'flex', justifyContent: 'space-between' }}>
237
+                    <Button type="primary" style={{ width: '140px' }} onClick={toH5Edit}>修改配置</Button>
238
+
239
+                    <Button style={{ width: '140px' }} onClick={toDrainageDetail}>查看H5活动详情</Button>
240
+                </div>
241
+            </Modal>
242
+        </>
243
+    )
244
+}
245
+
246
+const WrappedHeader = Form.create({ name: 'header' })(header);
247
+
248
+export default WrappedHeader

+ 258
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/components/ContactInfo.jsx Ver fichero

@@ -0,0 +1,258 @@
1
+import React, { useEffect, useState } from 'react'
2
+import { Button, Radio, Icon, Form, Input, Row, Col, Modal, notification, Checkbox, Select, InputNumber } from 'antd';
3
+import { render } from 'react-dom';
4
+import request from '../../../../utils/request';
5
+import apis from '../../../../services/apis';
6
+import styles from './style.less';
7
+import cardImg from '../../../../assets/card.png';
8
+import girlImg from '../../../../assets/girl.png';
9
+import boyImg from '../../../../assets/boy.png';
10
+
11
+
12
+const formItemLayout = {
13
+  labelCol: {
14
+    xs: { span: 24 },
15
+    sm: { span: 3 },
16
+  },
17
+  wrapperCol: {
18
+    xs: { span: 24 },
19
+    sm: { span: 16 },
20
+  },
21
+};
22
+
23
+/**
24
+ * 项目类型 form 表单子组件
25
+ *
26
+ * @param {*} props
27
+ */
28
+class TypeForm extends React.Component {
29
+
30
+  componentDidMount() {
31
+    console.log(this.props.type, 'this.props.type')
32
+    this.props.form.setFieldsValue(this.props.type)
33
+  }
34
+
35
+  onChange(e, name) {
36
+    // console.log(e)
37
+    this.props.form.validateFieldsAndScroll((err, values) => {
38
+      if (!err) {
39
+        this.props.onSuccess(values)
40
+      }
41
+    });
42
+  }
43
+
44
+  close() {
45
+    this.props.onClose(this.props.form.getFieldsValue(['buildingTypeId']))
46
+  }
47
+
48
+  render() {
49
+    const { getFieldDecorator } = this.props.form;
50
+
51
+    return (
52
+      <>
53
+        <Col span={24} className={styles.card} >
54
+          <Form {...formItemLayout} style={{ padding: '30px 26px' }}>
55
+            <div className={styles.flexItem}>
56
+              <img src={this.props.type.avatar} height="50px" width="50px" style={{ borderRadius: '50%', margin: ' 0 7px 0 10px' }} /><span>{this.props.type.contactName}</span>
57
+            </div>
58
+            <div className={styles.flexItem} style={{ justifyContent: 'space-between' }}>
59
+              <div>
60
+                {this.props.type.sex != '' && this.props.type.sex != null && <div className={styles.flexItem}>
61
+                  <div className={styles.left}> 性别 </div>
62
+                  <div className={styles.right} style={{ display: 'flex', alignItems: 'center' }}>{this.props.type.sex == '1' ? '男' : '女'}<img src={this.props.type.sex == '1' ? boyImg : girlImg} height="16px" width="16px" style={{ marginLeft: '5px' }} /></div>
63
+                </div>}
64
+                {this.props.type.appellation != '' && this.props.type.appellation != null && <div className={styles.flexItem}>
65
+                  <div className={styles.left}><img src={cardImg} height="18px" width="24px" /></div>
66
+                  <div className={styles.right}>{this.props.type.appellation}</div>
67
+                </div>}
68
+                {this.props.type.telephone != '' && this.props.type.telephone != null && <div className={styles.flexItem}>
69
+                  <div className={styles.left}> 固话 </div>
70
+                  <div className={styles.right}>{this.props.type.telephone}</div>
71
+                </div>}
72
+                {this.props.type.phone != '' && this.props.type.phone != null && <div className={styles.flexItem}>
73
+                  <div className={styles.left}> 手机 </div>
74
+                  <div className={styles.right}>{this.props.type.phone}</div>
75
+                </div>}
76
+                {this.props.type.mail != '' && this.props.type.mail != null && <div className={styles.flexItem}>
77
+                  <div className={styles.left}> 邮箱 </div>
78
+                  <div className={styles.right}>{this.props.type.mail}</div>
79
+                </div>}
80
+                {this.props.type.address != '' && this.props.type.address != null && <div className={styles.flexItem}>
81
+                  <div className={styles.left}> 联系地址 </div>
82
+                  <div className={styles.right}>{this.props.type.address}</div>
83
+                </div>}
84
+              </div>
85
+              {this.props.type.wxCardImg != null && this.props.type.wxCardImg != '' &&
86
+              <div style={{ textAlign: 'center' }}>
87
+                <img src={this.props.type.wxCardImg} height="80px" width="80px" />
88
+                <p style={{ margin: ' 0px', fontSize: '0.096rem', color: '#666' }}>扫码添加微信好友</p>
89
+                <p sstyle={{ margin: ' 0px', fontSize: '0.096rem', color: '#666' }}>备注H5活动咨询</p>
90
+              </div>}
91
+            </div>
92
+          </Form>
93
+        </Col>
94
+      </>
95
+    )
96
+  }
97
+}
98
+
99
+const WrappedTypeForm = Form.create({ name: 'TypeForm' })(TypeForm);
100
+
101
+/**
102
+ *项目类型组件
103
+ *
104
+ * @param {*} props
105
+ */
106
+class ProjectTypeBody extends React.Component {
107
+
108
+  constructor(props) {
109
+    super(props)
110
+    this.state = {
111
+      one: false,
112
+      projectType: [],
113
+      defaultCheckboxValue: [], // 多选框默认选中的值
114
+      visible: true,
115
+      data: [],
116
+      sampleId: props.sampleId,
117
+      // data: [{ buildingTypeId: '1', buildingTypeName: '公寓', price: '10', decoration: '全包', rightsYear: '10', status: '1' }, { buildingTypeId: '2', buildingTypeName: '住宅', price: '10', decoration: '全包', rightsYear: '10', status: '1' }, { buildingTypeId: '3', buildingTypeName: '太平房', price: '10', decoration: '全包', rightsYear: '10', status: '1' }],
118
+    }
119
+  }
120
+
121
+  componentDidMount() {
122
+    this.getList({ pageNum: 1, pageSize: 999 })
123
+  }
124
+
125
+  componentDidUpdate(prevProps) {
126
+    // 典型用法(不要忘记比较 props):
127
+    if (this.props.value !== prevProps.data && !this.state.one) {
128
+      this.setValue()
129
+      this.setState({ one: true })
130
+    }
131
+  }
132
+
133
+  onSuccess = (values, item) => {
134
+    const newData = this.getNewProjectType(values)
135
+    this.setState({ data: newData })
136
+    if (typeof this.props.onChange === 'function') {
137
+      this.props.onChange(newData)
138
+    }
139
+  }
140
+
141
+  onCheckboxChange = checkedValues => {
142
+    const checked = (`${checkedValues}` || '').split(',')
143
+    const { projectType } = this.state
144
+    const buildingType = projectType.filter(item => checked.includes(`${item.buildingTypeId}`))
145
+
146
+    const tempDate = buildingType.map(item => ({ buildingTypeId: item.buildingTypeId, buildingTypeName: item.buildingTypeName, startPrice: null, endPrice: null, priceType: "average", decoration: null, rightsYear: null, status: '1' }))
147
+    const updateProjectDate = this.updateProjectType(tempDate)
148
+    console.log('updateProjectDate: ', updateProjectDate)
149
+    this.setState({ data: updateProjectDate })
150
+    this.setState({ defaultCheckboxValue: updateProjectDate.map(item => item.buildingTypeId) })
151
+  }
152
+
153
+  onClose = e => {
154
+    console.log(2)
155
+    const { data } = this.state
156
+    console.log('onClose——data: ', data)
157
+    console.log('onClose: ', e.buildingTypeId)
158
+    const buildingType = data.filter(item => e.buildingTypeId !== item.buildingTypeId)
159
+    console.log('onClose——data111: ', buildingType)
160
+    this.setState({ data: buildingType })
161
+    this.setState({ defaultCheckboxValue: buildingType.map(item => item.buildingTypeId) })
162
+    if (typeof this.props.onChange === 'function') {
163
+      this.props.onChange(buildingType)
164
+    }
165
+  }
166
+
167
+  getNewProjectType = values => {
168
+    const data = []
169
+    this.state.data.map(item => {
170
+      if (item.buildingTypeId === values.buildingTypeId) {
171
+        data.push(values)
172
+      } else {
173
+        data.push(item)
174
+      }
175
+    })
176
+    console.log('getNewProjectType', getNewProjectType)
177
+    return data
178
+  }
179
+
180
+  updateProjectType = values => {
181
+    // 获取所有复选框选中的id
182
+    const valueIdArray = values.map(item => item.buildingTypeId)
183
+    // console.log('valueIdArray: ', valueIdArray)
184
+
185
+    // 获取 data 中已经赋值的数据  交集
186
+    const valueData = this.state.data.filter(item => valueIdArray.includes(item.buildingTypeId))
187
+    // console.log('valueData: ', valueData)
188
+
189
+    // 获取 非 data中数据(也就是没有赋值),交集
190
+    const trueValueArr = valueData.map(item => item.buildingTypeId)
191
+    const trueValueData = values.filter(item => !trueValueArr.includes(item.buildingTypeId))
192
+
193
+    // console.log('trueValueData: ', trueValueData)
194
+
195
+    // 把两个 数组的值,合并返回
196
+    return valueData.concat(trueValueData)
197
+  }
198
+
199
+  getList = params => {
200
+    request({ ...apis.taH5SampleManager.taContactList, urlData: { id: this.state.sampleId } }).then(res => {
201
+      this.setState({ data: res.records })
202
+      console.log(this.state.data, 'data');
203
+    }).catch(err => {
204
+      this.openNotificationWithIcon('error', err.message)
205
+    })
206
+  }
207
+
208
+  setValue = () => {
209
+    let tempData = []
210
+    let tempCheckboxValue = []
211
+    const { value } = this.props
212
+    // console.log('value: ', value)
213
+    if (value !== undefined && value !== null) {
214
+      tempData = value
215
+      tempCheckboxValue = tempData.map(item => item.buildingTypeId)
216
+      this.setState({ defaultCheckboxValue: tempCheckboxValue })
217
+      this.setState({ data: tempData })
218
+    }
219
+  }
220
+
221
+  openNotificationWithIcon = (type, message) => {
222
+    notification[type]({
223
+      message,
224
+      description: '',
225
+    })
226
+  }
227
+
228
+  handleOk = e => {
229
+    this.setState({
230
+      visible: false,
231
+    });
232
+  };
233
+
234
+  handleCancel = e => {
235
+    this.setState({
236
+      visible: false,
237
+    });
238
+  };
239
+
240
+  showMadel = () => {
241
+    this.setState({ visible: true })
242
+    this.getList({ pageNum: 1, pageSize: 999 })
243
+  }
244
+
245
+  render() {
246
+    return (
247
+      <>
248
+        <Row type="flex" justify="space-between">
249
+          {
250
+            this.state.data.map(item => <WrappedTypeForm type={item} key={item.buildingTypeId} onSuccess={(e) => this.onSuccess(e, item)} onClose={(e) => this.onClose(e)} />)
251
+          }
252
+        </Row>
253
+      </>
254
+    )
255
+  }
256
+}
257
+
258
+export default ProjectTypeBody

+ 26
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/components/style.less Ver fichero

@@ -0,0 +1,26 @@
1
+.card{
2
+    position: relative;
3
+    border: 1px solid #eee;
4
+    margin-top: 16px;
5
+    min-width: 480px;
6
+    box-shadow: 0px 0px 10px 4px rgba(0;0;0;0.12);
7
+    border-radius: 6px;
8
+   
9
+    .flexItem{
10
+        display: flex;
11
+        align-items: center;
12
+        .left{
13
+            font-size: 0.096rem;
14
+            color: #666;
15
+            width: 0.4rem;
16
+            text-align: right;
17
+            line-height: 0.2rem;
18
+            margin-right: 0.2rem;
19
+        }
20
+        .right{
21
+            font-size: 0.1rem;
22
+            color: #333;
23
+            text-align: right;
24
+        }
25
+    }
26
+}

+ 165
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/detail.jsx Ver fichero

@@ -0,0 +1,165 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker, InputNumber, Checkbox, Row, Col } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import XForm, { FieldTypes } from '../../../components/XForm';
5
+import router from 'umi/router';
6
+import moment from 'moment';
7
+import apis from '../../../services/apis';
8
+import request from '../../../utils/request';
9
+import AuthButton from '@/components/AuthButton';
10
+import Wangedit from '../../../components/Wangedit/Wangedit'
11
+import DragableUploadImageList from './components/ContactInfo'
12
+import TextArea from 'antd/lib/input/TextArea';
13
+import copy from 'copy-to-clipboard';
14
+import copyImg from '../../../assets/copy.png';
15
+import Navigate from '@/components/Navigate';
16
+
17
+const { Option } = Select;
18
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
19
+
20
+
21
+const header = props => {
22
+  const sampleId = props.location.query.id;
23
+  const [demandData, setDemandData] = useState({})
24
+  const [demandNum, setDemandNum] = useState()
25
+
26
+  useEffect(() => {
27
+    getDemandData(sampleId);
28
+  }, [])
29
+
30
+  // 查询列表
31
+  const getDemandData = (demandId) => {
32
+    request({ ...apis.taH5SampleManager.taH5SampleById, urlData: { id: sampleId } }).then((data) => {
33
+      setDemandData(data)
34
+      setDemandNum(data.demandNum)
35
+      props.form.setFieldsValue(data)
36
+    })
37
+  }
38
+
39
+  // 跳转到编辑
40
+  const toDetail = rowData => () => {
41
+
42
+    request({ ...apis.taH5SampleManager.taH5SampleById, urlData: { id: sampleId } }).then((data) => {
43
+      if (rowData) {
44
+        router.push({
45
+          pathname: '/h5SampleManager/h5Sample/add',
46
+          query: {
47
+            id: sampleId,
48
+            sampleName: demandData.sampleName
49
+          },
50
+        });
51
+        return
52
+      }
53
+    }).catch(err => {
54
+      message.info("该H5样例已取消发布或已删除")
55
+    })
56
+
57
+
58
+  }
59
+
60
+  const toAddH5 = rowData => () => {
61
+    router.push({
62
+      pathname: '/h5SampleManager/h5Sample/addH5',
63
+      query: {
64
+        id: sampleId,
65
+        sampleName: demandData.sampleName
66
+      },
67
+    });
68
+
69
+
70
+  }
71
+  const toCancel = () => {
72
+    router.go(-1)
73
+  }
74
+
75
+  function viewDemand() {
76
+    router.push({
77
+      pathname: '/h5SampleManager/h5Demand/list',
78
+      query: {
79
+        id: sampleId,
80
+        sampleName: demandData.sampleName,
81
+      },
82
+    });
83
+  }
84
+
85
+  //打开新页面
86
+  const copyLink = (e) => {
87
+    copy(e)
88
+    message.info('复制成功')
89
+  }
90
+
91
+  function handleSubmit(e) {
92
+  }
93
+
94
+  function newTab(e) {
95
+    console.log(e, 'eeeeeeee')
96
+    const newWin = window.open('about:blank');
97
+    newWin.location.href = e
98
+  }
99
+
100
+  const { getFieldDecorator } = props.form;
101
+
102
+  return (
103
+    <>
104
+      <Form labelCol={{ span: 6 }} wrapperCol={{ span: 14 }} style={{ position: 'relative' }} onSubmit={handleSubmit}>
105
+        <Form.Item label="样例名">
106
+          <span>{demandData.sampleName}</span>
107
+        </Form.Item>
108
+        {demandData.sampleTryLink != '' && demandData.sampleTryLink != null && <Form.Item label="样例体验链接" help="请复制发送到手机,用手机微信打开,PC端打开样式比例与手机端不同,以手机端为准">
109
+          <span>{demandData.sampleTryLink}</span><span style={{ marginLeft: '10px' }}><a onClick={(e) => copyLink(demandData.sampleTryLink)} style={{ color: 'orange' }}> <img src={copyImg} height="16px" width="14px" /> 复制链接</a></span>
110
+        </Form.Item>}
111
+        {demandData.sampleTryCode != '' && demandData.sampleTryCode != null && <Form.Item label="样例体验小程序码/二维码" help="请使用微信扫码查看样例体验">
112
+          <img src={demandData.sampleTryCode} height="100px" width="120px" />
113
+        </Form.Item>}
114
+        {demandData.taContactList != null && demandData.taContactList != '' && <Form.Item label="联系人">
115
+          <span style={{ color: 'rgba(0, 0, 0, 0.45)', fontSize: '14px' }}>若您想在您的小程序举办类似活动,请联系以下联系人咨询,或直接点击底部的 提交需求 按钮下单,下单后与联系人沟通定制活动</span>
116
+          <DragableUploadImageList sampleId={sampleId}></DragableUploadImageList>
117
+        </Form.Item>}
118
+        <Form.Item label="样例内容">
119
+          {demandData.sampleType === 'link' && <div><span style={{ color: 'rgba(0, 0, 0, 0.45)', fontSize: '14px' }}>点击链接查看内容</span><br /></div>}
120
+          {demandData.sampleType === 'rich' ? getFieldDecorator('sampleContent')(<div dangerouslySetInnerHTML={{ __html: demandData.sampleContent }}></div>) : getFieldDecorator('sampleContentLink')(<Navigate to={demandData.sampleContentLink}>{demandData.sampleContentLink}</Navigate>)}
121
+        </Form.Item>
122
+        <Form.Item wrapperCol={{ span: 15, offset: 7 }}>
123
+          <div style={{ margin: '0.16rem 0 0.06rem' }}>
124
+            {!!demandData.h5TemplateId && <AuthButton name="admin.h5Sample.activity.add" noRight={null}>
125
+              <Button type="primary" onClick={toAddH5(sampleId)} style={{ marginRight: '20px' }}>
126
+                创建H5活动
127
+              </Button>
128
+            </AuthButton>}
129
+            <Button type="primary" onClick={toDetail(sampleId)} style={{ marginRight: '20px' }}>
130
+              提交需求
131
+          </Button>
132
+            <Button danger onClick={() => toCancel()} style={{ marginLeft: '20px' }}>
133
+              取消
134
+          </Button>
135
+          </div>
136
+        </Form.Item>
137
+        <div style={{ position: 'fixed', right: '0.4rem', bottom: '6%' }}>
138
+          {!!demandData.h5TemplateId && <AuthButton name="admin.h5Sample.activity.add" noRight={null}>
139
+            <div style={{ display: 'flex', alignItems: 'center', minWidth: '1.1rem', justifyContent: 'space-between', marginBottom: '20px' }}>样例可直接使用 <span style={{ color: '#EF273A', margin: '0 0.1rem' }}>>></span>
140
+              <Button type="primary" onClick={toAddH5(sampleId)} >
141
+                创建H5活动
142
+              </Button>
143
+            </div>
144
+          </AuthButton>}
145
+          <div style={{ display: 'flex', alignItems: 'center', minWidth: '1.1rem', justifyContent: 'space-between' }}>我想办类似活动 <span style={{ color: '#EF273A', margin: '0 0.1rem' }}>>></span>
146
+            <Button type="primary" onClick={toDetail(sampleId)} >
147
+              提交需求
148
+              </Button>
149
+          </div>
150
+
151
+          {demandNum != 0 && <div style={{ display: 'flex', alignItems: 'center', minWidth: '1.1rem', justifyContent: 'space-between', marginTop: '10px' }}>已有{demandNum + '个'}需求单 <span style={{ margin: '0 0.1rem' }}>>></span>
152
+            <Button danger onClick={() => viewDemand()}>
153
+              查看需求
154
+            </Button>
155
+          </div>
156
+          }
157
+        </div>
158
+      </Form>
159
+    </>
160
+  )
161
+}
162
+
163
+const WrappedHeader = Form.create({ name: 'header' })(header);
164
+
165
+export default WrappedHeader

+ 198
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/list.jsx Ver fichero

@@ -0,0 +1,198 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, message, Col, Pagination, Alert, notification, Modal } from 'antd';
3
+import moment from 'moment';
4
+import request from '../../../utils/request';
5
+import apis from '../../../services/apis';
6
+import Styles from './style.less';
7
+import { router } from 'umi';
8
+import AuthButton from '@/components/AuthButton';
9
+import SelectCity from '../../../components/SelectButton/CitySelect'
10
+
11
+
12
+const { Option } = Select;
13
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
14
+const { Meta } = Card;
15
+
16
+const tempDate = [{ code: 's101' }]
17
+
18
+function openNotificationWithIcon(type, message) {
19
+  notification[type]({
20
+    message,
21
+    description:
22
+      '',
23
+  });
24
+}
25
+
26
+/**
27
+ *卡片
28
+ *
29
+ * @returns
30
+ */
31
+function CartBody(props) {
32
+  const { data } = props
33
+
34
+  function toEdi(record) {
35
+    router.push({
36
+      pathname: '/h5SampleManager/h5Sample/detail',
37
+      query: {
38
+        id: record.sampleId,
39
+      },
40
+    })
41
+  }
42
+  const tagList = data.tag.split(',')
43
+
44
+  // src={((data.buildingImg && data.buildingImg[0]) || {}).url}background: `url(${item.caseCoverImg})` style={{ background: `url(((data.buildingImg && data.buildingImg[0]) || {}).url)` }}
45
+  const { buildingImg } = data
46
+  console.log("buildingImg1: ", data.coverImg)
47
+  return (
48
+    <Card
49
+      hoverable
50
+      onClick={() => toEdi(data)}
51
+      style={{ minWidth: '330px', borderRadius: '12px', margin: '10px 20px 10px 0', boxShadow: '0px 0px 16px 2px rgba(0,0,0,0.12)' }}
52
+    // cover={}
53
+    // bodyStyle={{ padding: '10px 20px' }}
54
+    >
55
+      {/* 因为 background 方式设置图片背景,如果 图片url 存在空格或者其他特殊字符,导致显示不出来,需要进行 encodeURI(xxx) 转码 */}
56
+      {tagList.length > 0 && <div className={Styles.recommderTagBox}>
57
+        {tagList.map((tag, index) =>
58
+          <span key={index + 'tag'} style={index % 2 == 0 ? { background: '#4886FF' } : { background: '#34BD28' }} className={Styles.recommderTag}>{tag}</span>
59
+        )}
60
+      </div>
61
+
62
+      }
63
+      <img className={Styles.cover} style={{ backgroundImage: `url('` + data.coverImg + `')` }}   ></img>
64
+      <p className={Styles.cardText} style={{ padding: '0.1rem 0.096rem',marginBottom:'0px' }}>
65
+        {/* <span className={Styles.title}>样例名</span> */}
66
+        <span style={{ textOverflow: 'ellipsis', whiteSpace: 'nowrap', overflow: 'hidden' }}>{data.sampleName}</span>
67
+      </p>
68
+    </Card>
69
+  )
70
+}
71
+
72
+/**
73
+ *
74
+ *
75
+ * @param {*} props
76
+ * @returns
77
+ */
78
+function body(props) {
79
+  const { getFieldDecorator } = props.form
80
+
81
+  // eslint-disable-next-line react-hooks/rules-of-hooks
82
+  const [dataSource, setDataSource] = useState({ records: [], size: 0 })
83
+
84
+  // eslint-disable-next-line react-hooks/rules-of-hooks
85
+  useEffect(() => {
86
+    getList({ pageNum: 1, pageSize: 9 })
87
+  }, [])
88
+
89
+  function getList(params) {
90
+    // 网路请求
91
+    request({ ...apis.taH5SampleManager.taH5Sample, params: { ...params } }).then(res => {
92
+      setDataSource(res)
93
+      console.log("res:", res)
94
+    }).catch(err => {
95
+      // eslint-disable-next-line no-unused-expressions
96
+      <Alert
97
+        style={{
98
+          marginBottom: 24,
99
+        }}
100
+        message={err}
101
+        type="error"
102
+        showIcon
103
+      />
104
+    })
105
+  }
106
+
107
+  // 提交事件
108
+  function handleSubmit(e) {
109
+    e.preventDefault();
110
+    props.form.validateFields((err, values) => {
111
+      if (!err) {
112
+        // eslint-disable-next-line no-console
113
+        console.log('提交数据: ', values)
114
+        const { startDate } = values
115
+        if (values.startDate !== undefined) {
116
+
117
+          values.startDate = `${moment(startDate).format('YYYY-MM-DDT00:00:00.000')}Z`
118
+        }
119
+        getList({ pageNum: 1, pageSize: 9, ...values })
120
+      }
121
+    });
122
+  }
123
+
124
+  // Change 事件
125
+  function handleSelectChange(e) {
126
+    // eslint-disable-next-line no-console
127
+    console.log(e)
128
+  }
129
+
130
+  // 分页
131
+  function onChange(pageNumber) {
132
+    // eslint-disable-next-line react-hooks/rules-of-hooks
133
+    getList({ pageNum: pageNumber, pageSize: 9, ...props.form.getFieldsValue() })
134
+  }
135
+
136
+
137
+  /**
138
+   * 重置搜索
139
+   */
140
+  function handleReset() {
141
+    props.form.resetFields();
142
+    getList({ pageNum: 1, pageSize: 9 })
143
+  }
144
+
145
+  function onSuccess() {
146
+    getList({ pageNum: 1, pageSize: 9 })
147
+  }
148
+
149
+
150
+  return (
151
+    <>
152
+      <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
153
+        <Form.Item>
154
+          {getFieldDecorator('sampleName')(
155
+            <Input
156
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
157
+              placeholder="样例名"
158
+            />,
159
+          )}
160
+        </Form.Item>
161
+        <Form.Item>
162
+          {getFieldDecorator('tag')(
163
+            <Input
164
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
165
+              placeholder="标签"
166
+            />,
167
+          )}
168
+        </Form.Item>
169
+        <Form.Item>
170
+          <Button type="primary" htmlType="submit">
171
+            搜索
172
+            </Button>
173
+          <Button style={{ marginLeft: 8 }} onClick={handleReset}>
174
+            重置
175
+            </Button>
176
+        </Form.Item>
177
+      </Form>
178
+
179
+      {/* 卡片内容,显示楼盘项目  */}
180
+      <Row style={{ paddingTop: ' 16px' }}>
181
+        {
182
+          dataSource.records.map((item, _) => (
183
+            <Col span={8}>
184
+              <CartBody data={item} key={item.buildingId} onSuccess={() => onSuccess()} />
185
+            </Col>
186
+          ))
187
+        }
188
+      </Row>
189
+      {/* 分页 */}
190
+      <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
191
+        <Pagination showQuickJumper defaultCurrent={1} total={dataSource.total} onChange={onChange} pageSize={dataSource.size} />
192
+      </div>
193
+    </>
194
+  );
195
+}
196
+const WrappedBody = Form.create({ name: 'body' })(body);
197
+
198
+export default WrappedBody

+ 56
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/style.css Ver fichero

@@ -0,0 +1,56 @@
1
+.SubmitButton {
2
+  background: #3a91d5;
3
+  border-radius: 7px;
4
+  border: 0px;
5
+}
6
+.SelectFrom {
7
+  width: 180px;
8
+  background: #ffffff;
9
+  border-radius: 7px;
10
+  border: 1px solid #dbdbdb;
11
+}
12
+.addButton {
13
+  border-radius: 4px;
14
+  border: 0px;
15
+  margin: 10px 0px;
16
+}
17
+.cardText {
18
+  font-size: 0.106rem;
19
+  color: #333;
20
+  line-height: 1.5;
21
+  display: flex;
22
+  align-items: center;
23
+  position: relative;
24
+  margin-bottom: 0.08rem;
25
+}
26
+.cardItem {
27
+  font-size: 0.106rem;
28
+  font-weight: 400;
29
+  color: #666;
30
+  display: flex;
31
+  align-items: center;
32
+  line-height: 1.5;
33
+  font-size: 0.106rem;
34
+  margin-bottom: 0.08rem;
35
+
36
+}
37
+.ediText {
38
+  font-size: 0.106rem;
39
+  color: #ff925c;
40
+  position: absolute;
41
+  right: 0;
42
+}
43
+.title {
44
+  display: inline-block;
45
+  width: 0.54rem;
46
+  justify-content: space-between;
47
+  text-align: justify;
48
+  text-align-last: justify;
49
+}
50
+.address {
51
+  width: 400px;
52
+  height: 24px;
53
+  text-overflow: ellipsis;
54
+  white-space: nowrap;
55
+  overflow: hidden;
56
+}

+ 338
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/style.less Ver fichero

@@ -0,0 +1,338 @@
1
+.SubmitButton {
2
+  background: #3a91d5;
3
+  border-radius: 7px;
4
+  border: 0px;
5
+}
6
+.SelectFrom {
7
+  width: 180px;
8
+  background: #ffffff;
9
+  border-radius: 7px;
10
+  border: 1px solid #dbdbdb;
11
+}
12
+.addButton {
13
+  border-radius: 4px;
14
+  border: 0px;
15
+  margin: 10px 0px;
16
+}
17
+.cardText {
18
+  font-size: 0.096rem;
19
+  color: #333;
20
+  display: flex;
21
+  align-items: center;
22
+  position: relative;
23
+}
24
+
25
+.cardItem{
26
+  font-size: 0.106rem;
27
+  font-weight: 400;
28
+  color: #666;
29
+  display: flex;
30
+  align-items: center;  
31
+  margin-bottom: 0.08rem;
32
+  .title{
33
+    display: inline-block;
34
+    width: 0.58rem;
35
+  
36
+    min-width: 0.58rem;
37
+    justify-content: space-between;
38
+    text-align: justify;
39
+    text-align-last:justify
40
+  }
41
+  
42
+}
43
+// .cardText{
44
+//   font-size: 0.106rem;
45
+//   font-weight: 400;
46
+//   color: #666;
47
+//   display: flex;
48
+//   align-items: center;  
49
+//   margin-bottom: 0.08rem;
50
+//   .title{
51
+//     display: inline-block;
52
+//     width: 0.58rem;
53
+  
54
+//     min-width: 0.58rem;
55
+//     justify-content: space-between;
56
+//     text-align: justify;
57
+//     text-align-last:justify
58
+//   }
59
+  
60
+// }
61
+.ediText {
62
+  font-size: 0.106rem;
63
+  color: #ff925c;
64
+  position: absolute;
65
+  right: 0;
66
+
67
+}
68
+
69
+
70
+.address { 
71
+  width: 400px;
72
+  height: 24px; 
73
+  text-overflow: ellipsis; 
74
+  white-space: nowrap;
75
+  overflow: hidden;
76
+}
77
+.cover{
78
+  width: 100%;
79
+
80
+  padding-bottom: 66.8%;
81
+  background-size: 100% 100% !important;
82
+ 
83
+  border-radius: 12px 12px 0 0;
84
+  
85
+    // height: '14vw';
86
+}
87
+.recommderTagBox{
88
+  position: absolute;
89
+  width: 100%;
90
+  bottom: 0.33rem;
91
+  text-align: right;
92
+
93
+}
94
+.recommderTag{
95
+ 
96
+  color: #fff;
97
+  line-height: 0.13rem;
98
+  // width: 0.4rem;
99
+  background:rgba(52,189,40,1);
100
+  text-align: center;
101
+  border-radius: 4px;
102
+  font-size: 0.09rem;
103
+  display: inline-block;
104
+  margin-left: 0.1rem;
105
+  padding: 0 0.08rem;
106
+  margin-top: 10px;
107
+
108
+}
109
+.SubmitButton {
110
+  background: rgba(239,39,58,1);
111
+  border-radius: 7px;
112
+  border: 0px;
113
+}
114
+.text {
115
+  color: rgba(239,39,58,1);
116
+}
117
+.SelectFrom {
118
+  width: 180px;
119
+  background: #ffffff;
120
+  border-radius: 7px;
121
+  border: 1px solid #dbdbdb;
122
+}
123
+.addButton {
124
+  background: #50be00;
125
+  border-radius: 4px;
126
+  border: 0px;
127
+  margin: 10px 0px;
128
+}
129
+
130
+.cardItem{
131
+  color: #666;
132
+  display: flex;
133
+  align-items: center; 
134
+  line-height: 1.5;
135
+  font-size: 0.106rem;
136
+  margin-bottom: 0.08rem; 
137
+}
138
+.ediText {
139
+  font-size: 0.106rem;
140
+  color: #ff925c;
141
+  line-height: 24px;
142
+  position: absolute;
143
+  right: 0;
144
+}
145
+.title{
146
+  display: inline-block;
147
+  width:  0.54rem;
148
+  justify-content: space-between;
149
+  text-align: justify;
150
+  text-align-last:justify
151
+}
152
+
153
+.address { 
154
+  width: 400px;
155
+  height: 24px; 
156
+  text-overflow: ellipsis; 
157
+  white-space: nowrap;
158
+  overflow: hidden;
159
+}
160
+
161
+.pitchButton { 
162
+  border-color: rgba(255,126,72,1);
163
+  background-color: rgba(255,126,72,1);
164
+  color: rgba(255,255,255,1); 
165
+}
166
+.noButton {
167
+  border-color: rgba(255,126,72,1);
168
+  color: rgba(255,126,72,1);
169
+}
170
+.displayS {
171
+  display: none;
172
+}
173
+
174
+
175
+// 客户详情样式
176
+.cardBox{
177
+  display: flex;
178
+  .leftBox{
179
+    width:1000px;
180
+    min-width:350px;
181
+    height:1000px;
182
+    background:rgba(255,255,255,1);
183
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
184
+    border-radius:8px;
185
+    display: inline-block;
186
+    margin-right: 30px;
187
+    padding: 30px;
188
+    overflow: hidden;
189
+  }
190
+  .rightBox{
191
+    width:865px;
192
+    min-width:342px;
193
+    height:290px;
194
+    background:rgba(255,255,255,1);
195
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
196
+    border-radius:8px;
197
+    display: inline-block;
198
+    margin-right: 30px;
199
+    padding: 30px;
200
+    overflow: hidden;
201
+  }
202
+  .rightBox{
203
+    width:-webkit-fill-available;
204
+    height:315px;
205
+    min-width: 100%;
206
+    background:rgba(255,255,255,1);
207
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
208
+    border-radius:8px;
209
+    display: inline-block;
210
+    padding: 30px;
211
+    overflow: hidden;
212
+    position: relative;
213
+  }
214
+  .rightBoxCentre{
215
+    width:865px;
216
+    height:345px;
217
+    min-width: 60%;
218
+    background:rgba(255,255,255,1);
219
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
220
+    border-radius:8px;
221
+    display: inline-block;
222
+    padding: 30px;
223
+    overflow: hidden;
224
+    position: relative;
225
+  }
226
+  .leftBoxCentre{
227
+    width:100%;
228
+    height:345px;
229
+    background:rgba(255,255,255,1);
230
+    box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
231
+    border-radius:8px;
232
+    display: inline-block;
233
+    padding: 30px;
234
+    overflow: hidden;
235
+    position: relative;
236
+  }
237
+  .tit{
238
+    font-size:0.15rem;
239
+    font-weight:600;
240
+    color:#222;
241
+    margin: 10px 0 0 0;
242
+  }
243
+  .flexBox{
244
+    display: flex;
245
+    align-items: end;
246
+  }
247
+  .touxiang{
248
+    width: 120px;
249
+    width: 120px;
250
+    border-radius: 6px;
251
+    margin: 30px 0 20px 0;
252
+  }
253
+  .touxiangphoto{
254
+    width: 80px;
255
+    height: 80px;
256
+    margin: 38px 0 0px 0;
257
+  }
258
+  .infoItem{
259
+    color:#666;
260
+    font-size: 0.1rem;
261
+    margin: 0 0 30px 0;
262
+    
263
+  }
264
+  .rightItem{
265
+    color:#666;
266
+    font-size: 0.1rem;
267
+    margin: 0 0 15px 0;
268
+  }
269
+  .right{
270
+    width: 25%;
271
+    min-width: 1.3rem;
272
+    margin-left: 0.1rem;
273
+    padding-top: 0.3rem;
274
+    // position: absolute;
275
+    // top:108px;
276
+    // left:170px;
277
+  }
278
+  .rightphone{
279
+  
280
+    position: absolute;
281
+    top:108px;
282
+    left:170px;
283
+  }
284
+  .left{
285
+    position: absolute;
286
+    top:108px;
287
+    left:60%;
288
+  
289
+  }
290
+  .rightInfo{
291
+    width: 25%;
292
+    min-width: 1.3rem;
293
+    margin-right: 0.1rem;
294
+    padding-top: 0.3rem;
295
+    // position: absolute;
296
+    // top:108px;
297
+    // left:80%;
298
+  }
299
+
300
+  .Centered{
301
+    width: 25%;
302
+    // position: absolute;
303
+    // top:108px;
304
+    // left:30%;
305
+    min-width: 1.3rem;
306
+    margin: 0 0 15px 0;
307
+    color:#666;
308
+    font-size: 0.1rem;
309
+    padding-top: 0.3rem;
310
+  }
311
+
312
+  .rightCentered{
313
+    // position: absolute;
314
+    // top:108px;
315
+    // left:55%;
316
+    width: 25%;
317
+    min-width: 1.3rem;
318
+    margin: 0 0 15px 0;
319
+    padding-top: 0.3rem;
320
+    color:#666;
321
+    font-size: 0.1rem;
322
+  }
323
+  
324
+}
325
+.recordBox{
326
+  width:100%;
327
+  background:rgba(255,255,255,1);
328
+  box-shadow:0px 0px 16px 2px rgba(0,0,0,0.12);
329
+  border-radius:8px;
330
+  margin-top: 30px;
331
+  padding: 30px;
332
+  .tableName{
333
+    font-size:24px;
334
+    font-weight:600;
335
+    color:#222;
336
+  }
337
+}
338
+

+ 53
- 0
estateagents-admin-manager/src/pages/h5SampleManager/h5Sample/style.wxss Ver fichero

@@ -0,0 +1,53 @@
1
+.SubmitButton {
2
+  background: #3a91d5;
3
+  border-radius: 7px;
4
+  border: 0px;
5
+}
6
+.SelectFrom {
7
+  width: 180px;
8
+  background: #ffffff;
9
+  border-radius: 7px;
10
+  border: 1px solid #dbdbdb;
11
+}
12
+.addButton {
13
+  border-radius: 4px;
14
+  border: 0px;
15
+  margin: 10px 0px;
16
+}
17
+.cardText {
18
+  font-size: 0.106rem;
19
+  color: #333;
20
+  line-height: 24px;
21
+  display: flex;
22
+  align-items: center;
23
+  position: relative;
24
+}
25
+.cardItem {
26
+  font-size: 0.106rem;
27
+  font-weight: 400;
28
+  color: #666;
29
+  display: flex;
30
+  align-items: center;
31
+  margin-bottom: 0.08rem;
32
+}
33
+.ediText {
34
+  font-size: 0.106rem;
35
+  color: #ff925c;
36
+  position: absolute;
37
+  right: 0;
38
+  margin-bottom: 0.08rem;
39
+}
40
+.title {
41
+  display: inline-block;
42
+   width: 0.54rem;
43
+  justify-content: space-between;
44
+  text-align: justify;
45
+  text-align-last: justify;
46
+}
47
+.address {
48
+  width: 400px;
49
+  height: 24px;
50
+  text-overflow: ellipsis;
51
+  white-space: nowrap;
52
+  overflow: hidden;
53
+}

+ 167
- 0
estateagents-admin-manager/src/pages/house/house/add/HouseBatchAdd.jsx Ver fichero

@@ -0,0 +1,167 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, Tabs, Radio, DatePicker, message, Upload, Table, Modal } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import moment from 'moment';
5
+import router from 'umi/router';
6
+import { fetch } from '../../../../utils/request';
7
+import apis from '../../../../services/apis';
8
+import XForm, { FieldTypes } from '../../../../components/XForm';
9
+import ApartmentSelect from '../../../../components/HouseSelect/ApartmentSelect';
10
+import request from '@/utils/request';
11
+
12
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
13
+const { TextArea } = Input;
14
+
15
+function HouseBatchAdd(props) {
16
+
17
+const [data, setData] = useState({list: [], total: 0})
18
+
19
+const [uploadFile, setUploadFile] = useState(null)
20
+
21
+const uploadExcel = fetch(apis.house.uploadExcel)
22
+
23
+const [loadingState, setLoadingState] = useState(false)
24
+
25
+const uploaderProps = {
26
+  name: 'file',
27
+  accept: '.xls, .xlsx',
28
+  showUploadList: false,
29
+  customRequest({
30
+    action,
31
+    file,
32
+    headers,
33
+    onError,
34
+    onProgress,
35
+    onSuccess,
36
+    withCredentials,
37
+  }) {
38
+    setLoadingState(true);
39
+    const data = new FormData()
40
+    data.append('file', file)
41
+    data.append('salesBatchId', props.location.query.salesBatchId)
42
+    data.append('buildingId', props.location.query.buildingId)
43
+
44
+    setUploadFile(file)
45
+
46
+    uploadExcel({ data }).then((res) => {
47
+      setLoadingState(false);
48
+      setData(res)
49
+      onSuccess(res, file);
50
+    }).catch(err => {
51
+      setLoadingState(false);
52
+    });
53
+
54
+    return {
55
+      abort() {
56
+        console.log('upload progress is aborted.');
57
+      },
58
+    };
59
+  },
60
+}
61
+
62
+//取消
63
+function handleCancel(){
64
+  router.push({
65
+    pathname: '/house/house/edit',
66
+    query: {
67
+      id: props.location.query.salesBatchId,
68
+      buildingId: props.location.query.buildingId,
69
+    },
70
+  });
71
+}
72
+
73
+function batchSaveHouse() {
74
+  if(null == uploadFile){
75
+    message.error('请先上传房源数据,再提交')
76
+    return
77
+  }
78
+  setLoadingState(true);
79
+  const uploadData = new FormData()
80
+  uploadData.append('file', uploadFile)
81
+  uploadData.append('salesBatchId', props.location.query.salesBatchId)
82
+  uploadData.append('buildingId', props.location.query.buildingId)
83
+
84
+  request({ ...apis.house.saveExcelValue, data: uploadData,headers: "content-type=multipart/form-data" }).then(res => {
85
+    setLoadingState(false);
86
+    Modal.info({
87
+      title: '新增房源成功',
88
+      content: '请确认全部数据正常,然后在房源详情页 销售批次栏 选择 发布状态 为“是” 将房源 发布到小程序。如需要置业顾问或用户分享,请在房源详情中配套海报图和分享图。',
89
+      okText: '确定',
90
+      onOk() {
91
+        router.push({
92
+          pathname: '/house/house/edit',
93
+          query: {
94
+            id: props.location.query.salesBatchId,
95
+            buildingId: props.location.query.buildingId,
96
+          },
97
+        });
98
+      },
99
+    });
100
+    
101
+  }).catch(err => {
102
+    setLoadingState(false);
103
+    // openNotificationWithIcon('error', err.message)
104
+  })
105
+}
106
+
107
+const columns = [
108
+  {
109
+    title: '期/区',
110
+    dataIndex: 'termName',
111
+    key: 'termName',
112
+  },
113
+  {
114
+    title: '楼栋',
115
+    dataIndex: 'blockName',
116
+    key: 'blockName',
117
+  },
118
+  {
119
+    title: '单元',
120
+    dataIndex: 'unitName',
121
+    key: 'unitName',
122
+  },
123
+  {
124
+    title: '层',
125
+    dataIndex: 'floorName',
126
+    key: 'floorName',
127
+  },
128
+  {
129
+    title: '房号',
130
+    dataIndex: 'roomName',
131
+    key: 'roomName',
132
+  },
133
+  {
134
+    title: '价格(万元)',
135
+    dataIndex: 'price',
136
+    key: 'price',
137
+  },
138
+  // {
139
+  //   title: '预选基础热度',
140
+  //   dataIndex: 'heat',
141
+  //   key: 'heat',
142
+  // },
143
+  {
144
+    title: '发布状态',
145
+    dataIndex: 'status',
146
+    key: 'status',
147
+    render: status => <><span>{status == 0 ? '否' : status == 1 ? '是' : ''}</span></>,
148
+  },
149
+]
150
+
151
+
152
+return (
153
+  <>
154
+    <div style={{ marginBottom: '30px' }} ><span>1.导入房源先下载模板--></span><a href="http://njcj.oss-cn-shanghai.aliyuncs.com/%E6%88%BF%E6%BA%90%E6%A8%A1%E6%9D%BF.xlsx" download="房源模板.xlsx"><Button type="primary" htmlType="submit">下载模板</Button></a></div>
155
+    <div style={{ marginBottom: '30px' }}>2.使用excel打开模板文件,编辑房源数据并保存</div>
156
+    <div style={{ marginBottom: '30px' }}><span>3.将编辑好的文件上传--></span><Upload {...uploaderProps}><Button type="primary" htmlType="submit" loading={loadingState}>上传</Button></Upload></div>
157
+    <span>4.检查导入的数据是否正常 ↓,不正常则重新编辑保存再次上传,请仔细阅读模板中的编辑规则</span>
158
+    <Table dataSource={data.list} columns={columns} pagination={{ total: data.total }} style={{ marginTop: '20px' }} rowKey="House" />
159
+
160
+    <div style={{ marginTop: '30px' }}>5.全部正常请点击提交</div>
161
+    <Button type="primary" loading={loadingState} onClick={() => batchSaveHouse()}>提交</Button>
162
+    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
163
+    <span>暂时未确定房源?  --></span><Button onClick={() => handleCancel()}>以后处理</Button>
164
+  </>
165
+)
166
+}
167
+export default HouseBatchAdd

+ 141
- 0
estateagents-admin-manager/src/pages/house/house/add/index.jsx Ver fichero

@@ -0,0 +1,141 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, DatePicker, InputNumber, Checkbox, Row, Col} from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import XForm, { FieldTypes } from '../../../../components/XForm';
5
+import router from 'umi/router';
6
+import moment from 'moment';
7
+import styles from '../../../style/GoodsList.less';
8
+import SelectCity from '../../../../components/SelectButton/CitySelect'
9
+import BuildSelect from '../../../../components/SelectButton/BuildSelect'
10
+import ImageUpload from '../../../../components/XForm/ImageUpload'
11
+import apis from '../../../../services/apis';
12
+import request from '../../../../utils/request';
13
+import AuthButton from '@/components/AuthButton';
14
+import SaleBatchHelpDoc from '../edit/components/SalesBatchHelpDoc';
15
+
16
+const { Option } = Select;
17
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
18
+
19
+
20
+
21
+
22
+const header = props => {
23
+  const { salesBatchId } = props.location.query
24
+  console.log(salesBatchId)
25
+  const [ saleBatchData, setSaleBatchData ] = useState({})
26
+  const [showHelp, setShowHelp] = useState(false)
27
+  if(salesBatchId){
28
+    useEffect(() => {
29
+      getSaleBatchData(salesBatchId);
30
+    },[])
31
+
32
+  // 查询列表
33
+  const getSaleBatchData = (salesBatchId) => {
34
+      request({ ...apis.system.taPolicy, urlData: {id: salesBatchId} }).then((data) => {
35
+          console.log(data)
36
+          setSaleBatchData(data)
37
+      })
38
+    }
39
+  }
40
+
41
+  const cancelPage = () =>{
42
+    router.push({
43
+      pathname: '/house/house/list',
44
+    });
45
+  }
46
+
47
+
48
+  function handleSubmit (e) {
49
+    e.preventDefault();
50
+    props.form.validateFields((err, values) => {
51
+      if (!err){
52
+        let {preSelectTime, ...submitValue} = values
53
+        if(null != preSelectTime && preSelectTime.length > 0){
54
+          const [preselectionStartTime, preselectionEndTime] = preSelectTime
55
+          submitValue.preselectionStartTime = moment(preselectionStartTime).format('YYYY-MM-DD HH:mm:ss');
56
+          submitValue.preselectionEndTime = moment(preselectionEndTime).format('YYYY-MM-DD HH:mm:ss');
57
+        }else{
58
+          submitValue.preselectionStartTime = null
59
+          submitValue.preselectionEndTime = null
60
+        }        
61
+        // getList({ pageNum: pageNumber, pageSize: 10, ...submitValue })
62
+        console.log(submitValue)
63
+        request({ ...apis.house.addTaSalesBatch, data: { ...submitValue },}).then((data) => {
64
+          message.info("保存成功,请上传房源")
65
+          console.log(data,"datattttttt")
66
+          router.push({
67
+            pathname: '/house/house/batch',
68
+            query: {
69
+              salesBatchId: data.salesBatchId,
70
+              buildingId: data.buildingId,
71
+            },
72
+          });
73
+        }).catch((err) => {
74
+          message.info(err.msg || err.message)
75
+        })
76
+      }
77
+    });
78
+  }
79
+
80
+  const { getFieldDecorator } = props.form;
81
+
82
+  return (
83
+    <>
84
+      <Form labelCol={{ span: 7 }} wrapperCol={{ span: 12 }} onSubmit={handleSubmit}>
85
+        <Form.Item label="销售批次名">
86
+          {getFieldDecorator('salesBatchName', {
87
+            rules: [{ required: true, message: '请输入销售批次名' }],
88
+          })(<Input maxLength={20} placeholder="为本次销售命名,如二期销售" />)}
89
+        </Form.Item>
90
+        <Form.Item label="销售楼盘">
91
+          {getFieldDecorator('buildingId', {
92
+            rules: [{ required: true, message: ' 请输入销售楼盘' }],
93
+          })(<BuildSelect />)}
94
+        </Form.Item>
95
+        <Form.Item label="备注">
96
+          {getFieldDecorator('remark')
97
+            (<Input maxLength={20} placeholder="本次销售哪几栋楼,多少套房源等"/>)}
98
+        </Form.Item>
99
+        <Form.Item label="发布状态">
100
+          {getFieldDecorator('status', {
101
+              rules: [{ required: true, message: '请选择发布状态' }],
102
+            })(<Select placeholder="发布状态" style={{ width: '300px' }}>
103
+            <Option value="0">否</Option>
104
+            <Option value="1">是</Option>
105
+          </Select>)}
106
+        </Form.Item>
107
+        <Form.Item label="房源显示价格">
108
+          {getFieldDecorator('displayHousePrice', {
109
+              rules: [{ required: true, message: '请选择房源是否显示价格' }],
110
+            })(<Select placeholder="房源是否显示价格" style={{ width: '300px' }}>
111
+            <Option value="false">否</Option>
112
+            <Option value="true">是</Option>
113
+          </Select>)}
114
+        </Form.Item>
115
+        <Form.Item label="分栋鸟瞰图" help="建议尺寸:690*388px,比例16::9,格式:jpg,文件小于300KB。分栋鸟瞰图会显示在楼盘详情页面。用户点击进入查看全部发布房源。可以适当在图中添加引导语。">
116
+              {getFieldDecorator('aerialViewImg', {
117
+                  rules: [{ required: true, message: '请上传分栋鸟瞰图' }],
118
+              })(
119
+                <ImageUpload />,
120
+              )}
121
+        </Form.Item>  
122
+        <Form.Item label="说明信息">
123
+          <Icon type="question-circle" theme="filled" style={{ fontSize: '18px', color: '#F00' }} onClick={() => setShowHelp(true)} />
124
+        </Form.Item> 
125
+        <Form.Item wrapperCol={{ span: 15, offset: 7 }}>
126
+          <Button type="primary" htmlType="submit"style={{marginRight:'20px'}}>
127
+            下一步
128
+          </Button>
129
+          <Button onClick={() => router.go(-1)}>
130
+            取消
131
+          </Button>
132
+        </Form.Item>
133
+      </Form>
134
+      <SaleBatchHelpDoc visible={showHelp} onCancel={() => setShowHelp(false)} />
135
+    </>
136
+  )
137
+}
138
+
139
+const WrappedHeader = Form.create({ name: 'header' })(header);
140
+
141
+export default WrappedHeader

+ 170
- 0
estateagents-admin-manager/src/pages/house/house/edit/components/base.jsx Ver fichero

@@ -0,0 +1,170 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Input, Button, Icon, Select, Tabs, Radio, DatePicker, message, Upload } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import moment from 'moment';
5
+import router from 'umi/router';
6
+import styles from '../../../../style/GoodsList.less';
7
+import XForm, { FieldTypes } from '../../../../../components/XForm';
8
+import apis from '../../../../../services/apis';
9
+import BuildSelect from '../../../../../components/SelectButton/BuildSelect';
10
+import request from '../../../../../utils/request';
11
+import SalesBatchHelpDoc from './SalesBatchHelpDoc';
12
+import MiniQRCode from '@/components/MiniQRCode';
13
+
14
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
15
+const { TextArea } = Input;
16
+
17
+const Base = props => {
18
+  const salesBatchId = props.salesBatchId.batchId
19
+  const [ saleBatchData, setSaleBatchData ] = useState({})
20
+  const [showHelp, setShowHelp] = useState(false)
21
+  
22
+  if(salesBatchId){
23
+    useEffect(() => {
24
+      getSaleBatchData(salesBatchId);
25
+    },[])
26
+
27
+  // 查询列表
28
+  const getSaleBatchData = (salesBatchId) => {
29
+    request({ ...apis.house.getTaSalesBatch, urlData: {id: salesBatchId} }).then((data) => {
30
+        setSaleBatchData(data)
31
+    })
32
+  }
33
+  }
34
+
35
+  const cancelPage = () =>{
36
+    router.push({
37
+      pathname: '/house/house/list',
38
+    });
39
+  }
40
+  const fields = [
41
+    {
42
+      label: '销售批次名',
43
+      name: 'salesBatchName',
44
+      type: FieldTypes.Text,
45
+      value: saleBatchData.salesBatchName,
46
+      rules: [
47
+        {
48
+          required: true,
49
+          message: '销售批次名不合法',
50
+          max:20,
51
+        },
52
+      ],
53
+    },
54
+    {
55
+      label: '销售楼盘',
56
+      name: 'buildingId',
57
+      render: <BuildSelect />,
58
+      value: saleBatchData.buildingId,
59
+      rules: [
60
+        {
61
+          required: true,
62
+          message: '请选择销售楼盘',
63
+        },
64
+      ],
65
+    },
66
+    {
67
+      label: '备注',
68
+      name: 'remark',
69
+      type: FieldTypes.Text,
70
+      value: saleBatchData.remark,
71
+      rules: [
72
+        {
73
+          message: '最多20字',
74
+          max:20
75
+        }
76
+      ],
77
+    },
78
+    {
79
+      label: '发布状态',
80
+      name: 'status',
81
+      type: FieldTypes.Select,
82
+      dict: [{label:"否",value:0},{label:"是",value:1}],
83
+      value: saleBatchData.status != null ? saleBatchData.status : 1,
84
+      rules: [
85
+        {
86
+          required: true,
87
+          message: '请选择发布状态',
88
+        },
89
+      ],
90
+    },
91
+    {
92
+      label: '房源显示价格',
93
+      name: 'displayHousePrice',
94
+      type: FieldTypes.Select,
95
+      dict: [{label:"否",value:false},{label:"是",value:true}],
96
+      value: saleBatchData.displayHousePrice != null ? saleBatchData.displayHousePrice : true,
97
+      rules: [
98
+        {
99
+          required: true,
100
+          message: '请选择房源显示价格',
101
+        },
102
+      ],
103
+    },
104
+    // {
105
+    //   label: '预选时间',
106
+    //   name: 'preSelectTime',
107
+    //   type: FieldTypes.RangePicker,
108
+    //   props: {showTime : 'HH:mm:ss' },
109
+    //   value: saleBatchData.preselectionStartTime != null ? [moment(saleBatchData.preselectionStartTime, 'YYYY-MM-DD HH:mm:ss'), moment(saleBatchData.preselectionEndTime, 'YYYY-MM-DD HH:mm:ss')] : null,
110
+    //   rules: [
111
+    //     { required: true, message: '请选择预选时间' },
112
+    //   ],
113
+    // },
114
+    {
115
+      label: '分栋鸟瞰图',
116
+      name: 'aerialViewImg',
117
+      type: FieldTypes.ImageUploader,
118
+      value: saleBatchData.aerialViewImg,
119
+      help: '建议图片尺寸:690*388px,比例16::9,格式:jpg,文件小于300KB。分栋鸟瞰图会显示在楼盘详情页面。用户点击进入查看全部发布房源。可以适当在图中添加引导语。',
120
+      rules: [
121
+        {
122
+          required: true,
123
+          message: '请选择分栋鸟瞰图',
124
+        },
125
+      ],
126
+    },
127
+    {
128
+      label: '扫码查看房源列表',
129
+      name: 'qrCode',
130
+      // type: FieldTypes.ImageUploader,
131
+      value: saleBatchData.qrCode,
132
+      // props: { disabled: true },
133
+      render: <MiniQRCode targetId={saleBatchData.salesBatchId} page="onlineSelling/pages/houseList/index" />
134
+    },
135
+    {
136
+      label: '说明',
137
+      name: 'buildingId',
138
+      render: <Icon type="question-circle" theme="filled" style={{ fontSize: '18px', color: '#F00' }} onClick={() => setShowHelp(true)} />,
139
+      value: saleBatchData.buildingId,
140
+    },
141
+  ]
142
+  
143
+    const handleSubmit = values => { 
144
+      let {preSelectTime, ...submitValue} = values
145
+        if(null != preSelectTime && preSelectTime.length > 0){
146
+          const [preselectionStartTime, preselectionEndTime] = preSelectTime
147
+          submitValue.preselectionStartTime = moment(preselectionStartTime).format('YYYY-MM-DD HH:mm:ss');
148
+          submitValue.preselectionEndTime = moment(preselectionEndTime).format('YYYY-MM-DD HH:mm:ss');
149
+        }else{
150
+          submitValue.preselectionStartTime = null
151
+          submitValue.preselectionEndTime = null
152
+        }        
153
+        console.log(submitValue)
154
+        request({ ...apis.house.updateTaSalesBatch, urlData: {id: salesBatchId},data: submitValue, }).then((data) => {
155
+          message.info("保存成功")
156
+          // cancelPage()
157
+        }).catch((err) => {
158
+        message.info(err.msg || err.message)
159
+      })
160
+    }
161
+    
162
+  return (
163
+    <>
164
+      <XForm onSubmit={handleSubmit} onCancel={cancelPage} fields={fields}></XForm>
165
+      <SalesBatchHelpDoc visible={showHelp} onCancel={() => setShowHelp(false)} />
166
+    </>
167
+  );
168
+}
169
+
170
+export default Base

+ 322
- 0
estateagents-admin-manager/src/pages/house/house/edit/components/house.jsx Ver fichero

@@ -0,0 +1,322 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Radio, Tag, Tooltip, Tabs, Table, notification, Modal } from 'antd';
3
+import moment from 'moment';
4
+import request from '../../../../../utils/request';
5
+import apis from '../../../../../services/apis';
6
+import Styles from './style.less';
7
+import { router } from 'umi';
8
+import BlockSelect from '../../../../../components/HouseSelect/BlockSelect'
9
+import UnitSelect from '../../../../../components/HouseSelect/UnitSelect'
10
+import FloorSelect from '../../../../../components/HouseSelect/FloorSelect'
11
+import RoomSelect from '../../../../../components/HouseSelect/RoomSelect'
12
+import ApartmentSelect from '../../../../../components/HouseSelect/ApartmentSelect';
13
+import styles from '../../../../style/GoodsList.less';
14
+import EditIcon from '@/components/EditIcon';
15
+
16
+/**
17
+ *图片设置
18
+ *
19
+ * @param {*} props
20
+ * @returns
21
+ */
22
+function House(props) {
23
+  // eslint-disable-next-line react-hooks/rules-of-hooks
24
+  const [data, setData] = useState([])
25
+  const [viable, setViable] = useState(false)
26
+  const [houseIdList, setHouseIdList] = useState([])
27
+  const [selectedRowKeys, setSelectedRowKeys] = useState([])
28
+
29
+  useEffect(() => {
30
+    getList()
31
+  }, [])
32
+
33
+  function openNotificationWithIcon(type, message) {
34
+    notification[type]({
35
+      message,
36
+      description:
37
+        '',
38
+    });
39
+  }
40
+
41
+  function getList(params) {
42
+    // 网路请求
43
+    request({ ...apis.house.taHousingResources, params: { ...params, salesBatchId: props.salesBatchId, buildingId: props.buildingId } }).then(res => {
44
+      console.log(res, "resresres")
45
+      setData(res)
46
+    }).catch(err => {
47
+      openNotificationWithIcon('error', err.message)
48
+    })
49
+  }
50
+
51
+  // 重置搜索
52
+  function handleReset() {
53
+    props.form.resetFields();
54
+    getList({ pageNumber: 1, pageSize: 10 })
55
+  }
56
+
57
+  // 分页
58
+  function changePageNum(pageNumber) {
59
+    // eslint-disable-next-line react-hooks/rules-of-hooks
60
+    getList({ pageNumber: pageNumber, pageSize: 10, ...props.form.getFieldsValue() })
61
+  }
62
+
63
+  const rowSelection = {
64
+    selectedRowKeys,
65
+    onChange: (selectedRowKeys, selectedRows) => {
66
+      console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
67
+      setSelectedRowKeys(selectedRowKeys)
68
+      setHouseIdList(selectedRows)
69
+    },
70
+  };
71
+
72
+  function showEdi(e) {
73
+    props.onSuccess(e);
74
+  }
75
+
76
+  //打开model
77
+  function showAparement() {
78
+    if (houseIdList.length < 1) {
79
+      openNotificationWithIcon('error', '请先选择需要改变的房源')
80
+      return
81
+    }
82
+    setViable(true)
83
+  }
84
+
85
+  function handleCancel() {
86
+    setViable(false)
87
+  }
88
+
89
+  // 提交事件
90
+  const handleSubmit = e => {
91
+    e.preventDefault();
92
+    props.form.validateFields((err, values) => {
93
+      if (!err) {
94
+        console.log('提交数据: ', values)
95
+
96
+        getList({ pageNumber: 1, pageSize: 10, ...values })
97
+      }
98
+    });
99
+  }
100
+
101
+  // model提交事件
102
+  const handleSubmitApartMent = e => {
103
+    props.form.validateFields((err, values) => {
104
+      // if (!err) {
105
+      if (!values.apartmentIdSelected) {
106
+        openNotificationWithIcon('error', '请选择户型')
107
+        return
108
+      }
109
+      request({ ...apis.house.changeApartment, data: { apartmentId: values.apartmentIdSelected, houseIdList } }).then(res => {
110
+        setViable(false)
111
+        setSelectedRowKeys([])
112
+        setHouseIdList([])
113
+        getList({ pageNumber: data.current, pageSize: 10 })
114
+        openNotificationWithIcon('success', '操作成功')
115
+      }).catch(err => {
116
+        openNotificationWithIcon('error', err.message)
117
+      })
118
+      // }
119
+    });
120
+  }
121
+  /**
122
+   * 删除
123
+   *
124
+   * @param {*} record
125
+   */
126
+  function deleteHouseResource(record) {
127
+    Modal.confirm({
128
+      title: '确定将所选房删除?',
129
+      content: '如果只是不想让用户看到房源,请修改发布状态为否,删除房源会导致大量关联数据异常。若房源有预选记录或认筹记录则无法删除,请先删除预选记录。',
130
+      okText: '确定',
131
+      cancelText: '取消',
132
+      onOk() {
133
+        // 网路请求
134
+        request({ ...apis.house.houseDelete, urlData: { id: record.houseId } }).then(res => {
135
+          getList({ pageNumber: 1, pageSize: 10 })
136
+          openNotificationWithIcon('success', '操作成功')
137
+        }).catch(err => {
138
+          // openNotificationWithIcon('error', err.message)
139
+        })
140
+      },
141
+      onCancel() { },
142
+    });
143
+  }
144
+
145
+
146
+  const columns = [
147
+    {
148
+      title: '房源编号',
149
+      dataIndex: 'houseId',
150
+      key: 'houseId',
151
+    },
152
+    {
153
+      title: '房源',
154
+      render: (x, row) => <><span>{row.termName}/{row.blockName}/{row.unitName}/{row.floorName}/{row.roomName}</span></>,
155
+    },
156
+    // {
157
+    //   title: '期/区',
158
+    //   dataIndex: 'termName',
159
+    //   key: 'termName',
160
+    // },
161
+    // {
162
+    //   title: '楼栋',
163
+    //   dataIndex: 'blockName',
164
+    //   key: 'blockName',
165
+    // },
166
+    // {
167
+    //   title: '单元',
168
+    //   dataIndex: 'unitName',
169
+    //   key: 'unitName',
170
+    // },
171
+    // {
172
+    //   title: '层',
173
+    //   dataIndex: 'floorName',
174
+    //   key: 'floorName',
175
+    // },
176
+    // {
177
+    //   title: '房号',
178
+    //   dataIndex: 'roomName',
179
+    //   key: 'roomName',
180
+    // },
181
+    {
182
+      title: '价格(万元)',
183
+      dataIndex: 'price',
184
+      key: 'price',
185
+    },
186
+    {
187
+      title: '对应户型',
188
+      dataIndex: 'apartmentName',
189
+      key: 'apartmentName',
190
+    },
191
+    // {
192
+    //   title: '预选基础热度',
193
+    //   dataIndex: 'heat',
194
+    //   key: 'heat',
195
+    // },
196
+    // {
197
+    //   title: '预选实际热度',
198
+    //   dataIndex: 'realHeat',
199
+    //   key: 'realHeat',
200
+    //   render:  (x, row) => <><span style={{color: 'blue',cursor: 'pointer'}} onClick={() => showEdi({type: "preselection",houseId: row.houseId})}>{row.realHeat}</span></>,
201
+    // },
202
+    {
203
+      title: '发布状态',
204
+      dataIndex: 'status',
205
+      key: 'status',
206
+      render: status => <><span>{status == 0 ? '否' : status == 1 ? '是' : ''}</span></>,
207
+    },
208
+    {
209
+      title: '最后修改人',
210
+      dataIndex: 'updateName',
211
+      key: 'updateName',
212
+    },
213
+    {
214
+      title: '最后修改时间',
215
+      dataIndex: 'updateDate',
216
+      key: 'updateDate',
217
+      render: (x, row) => <><span>{row.updateDate != null ? `${moment(row.updateDate).format('YYYY-MM-DD HH:mm:ss')}` : null}</span></>,
218
+    },
219
+    {
220
+      title: '操作',
221
+      dataIndex: 'apartmentId',
222
+      key: 'apartmentId',
223
+      render: (_, record) => (
224
+        <>
225
+          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
226
+            <div style={{ marginRight: '16px' }} onClick={() => showEdi({ type: "add", houseId: record.houseId })}> <EditIcon text="编辑" color='#ff925c' type="edit"></EditIcon></div>
227
+            <div onClick={() => deleteHouseResource(record)}><EditIcon text="删除" color='#FF4A4A' type="delete"></EditIcon></div>
228
+          </div>
229
+        </>
230
+      ),
231
+    },
232
+  ]
233
+  const { getFieldDecorator } = props.form
234
+  return (
235
+    <>
236
+      <div align="right" style={{ marginTop: '-52px', marginBottom: '20px' }}><Button onClick={() => router.go(-1)}>返回</Button></div>
237
+      <Form layout="inline" onSubmit={e => handleSubmit(e)}>
238
+        <Form.Item>
239
+          {getFieldDecorator('termName')(
240
+            <Input placeholder="请输入期/区" />
241
+          )}
242
+        </Form.Item>
243
+        <Form.Item>
244
+          {getFieldDecorator('blockName')(
245
+            <Input placeholder="请输入楼栋" />
246
+          )}
247
+        </Form.Item>
248
+        <Form.Item>
249
+          {getFieldDecorator('unitName')(
250
+            <Input placeholder="请输入单元" />
251
+          )}
252
+        </Form.Item>
253
+        <Form.Item>
254
+          {getFieldDecorator('floorName')(
255
+            <Input placeholder="请输入层" />
256
+          )}
257
+        </Form.Item>
258
+        <Form.Item>
259
+          {getFieldDecorator('roomName')(
260
+            <Input placeholder="请输入房号" />
261
+          )}
262
+        </Form.Item>
263
+        <Form.Item>
264
+          {getFieldDecorator('apartmentId')(
265
+            <ApartmentSelect buildingId={props.buildingId} />
266
+          )}
267
+        </Form.Item>
268
+        <Form.Item>
269
+          {getFieldDecorator('status')(
270
+            <Select placeholder="发布状态" style={{ width: '120px' }}>
271
+              <Option value="0">否</Option>
272
+              <Option value="1">是</Option>
273
+            </Select>,
274
+          )}
275
+        </Form.Item>
276
+        <Form.Item>
277
+          {getFieldDecorator('houseId')(
278
+            <Input placeholder="请输入房源编号" />,
279
+          )}
280
+        </Form.Item>
281
+        <Form.Item>
282
+          <Button type="primary" htmlType="submit" >
283
+            搜索
284
+          </Button>
285
+          <Button style={{ marginLeft: 8 }} onClick={handleReset}>
286
+            重置
287
+            </Button>
288
+        </Form.Item>
289
+      </Form>
290
+      <Button type="danger" onClick={() => showEdi({ type: "add", houseId: '' })} style={{ marginTop: '20px' }}>新增房源</Button>
291
+      <Button type="primary" onClick={() => showEdi({ type: "batch" })} style={{ marginLeft: '18px' }}>批量导入房源</Button>
292
+      <Button type="primary" onClick={() => showAparement()} style={{ marginLeft: '18px' }}>批量修改对应户型</Button>
293
+
294
+      <Table rowSelection={rowSelection} dataSource={data.records} columns={columns} pagination={{ defaultCurrent: 1, current: data.current, total: data.total, onChange: e => changePageNum(e) }} style={{ marginTop: '20px' }} rowKey={r => r.houseId} />
295
+
296
+      <Modal
297
+        title="批量修改对应户型"
298
+        width={400}
299
+        destroyOnClose="true"
300
+        footer={null}
301
+        visible={viable}
302
+        onOk={() => this.handleOk()}
303
+        onCancel={e => handleCancel(e)}
304
+      >
305
+        <Form onSubmit={e => handleSubmitApartMent(e)}>
306
+          <Form.Item label="将所选房源对应户型信息修改为" >
307
+            {getFieldDecorator('apartmentIdSelected')(
308
+              <ApartmentSelect buildingId={props.buildingId} />
309
+            )}
310
+          </Form.Item>
311
+          <Form.Item style={{ width: '400px', margin: 'auto', display: 'flex', justifyContent: 'space-between' }}>
312
+            <Button type="primary" htmlType="submit">保存</Button>
313
+                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
314
+                <Button onClick={() => handleCancel()}>取消</Button>
315
+          </Form.Item>
316
+        </Form>
317
+      </Modal>
318
+    </>
319
+  )
320
+}
321
+const WrappedHeader = Form.create({ name: 'House' })(House);
322
+export default WrappedHeader

+ 95
- 0
estateagents-admin-manager/src/pages/house/house/edit/index.jsx Ver fichero

@@ -0,0 +1,95 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Radio, Tag, Tooltip, Tabs, notification } from 'antd';
3
+import moment from 'moment';
4
+import request from '../../../../utils/request';
5
+import apis from '../../../../services/apis';
6
+import { router } from 'umi';
7
+
8
+import Base from './components/base'
9
+import HouseTab from './components/houseTab'
10
+import Poster from './components/poster'
11
+import Share from './components/share'
12
+import ShareRecord from './components/shareRecord'
13
+import VisitRecord from './components/visitRecord'
14
+
15
+
16
+const { Option } = Select
17
+const { TabPane } = Tabs;
18
+
19
+const formItemLayout = {
20
+  labelCol: {
21
+    xs: { span: 24 },
22
+    sm: { span: 2 },
23
+  },
24
+  wrapperCol: {
25
+    xs: { span: 24 },
26
+    sm: { span: 16 },
27
+  },
28
+};
29
+
30
+function openNotificationWithIcon(type, message) {
31
+  notification[type]({
32
+    message,
33
+    description:
34
+      '',
35
+  });
36
+}
37
+
38
+function EditHouse(props) {
39
+  const {salesBatchId} = props.location.query.id;
40
+  console.log(props.location.query.id)
41
+  const [tab, setTab] = useState('base')
42
+  const [salesBatchData, setSalesBatchData] = useState({ salesBatchId: undefined })
43
+  const [houseId, setHouseId] = useState('')
44
+
45
+  function tabsCallback(e) {
46
+    setTab(e.target.value)
47
+  }
48
+
49
+  // building 回调
50
+  function buildingOnSuccess(e) {
51
+    setBuildingData(e)
52
+  }
53
+
54
+  function housTabChange(e) {
55
+    setHouseId(e.houseId)
56
+    setTab('preselectionRecord')
57
+  }
58
+
59
+  const batchId = salesBatchData.salesBatchId || (props.location.query && props.location.query.id)
60
+
61
+  return (
62
+    <>
63
+      <Radio.Group value={ tab } buttonStyle="solid" onChange={e => tabsCallback(e)}>
64
+        <Radio.Button value="base">销售批次信息</Radio.Button>
65
+        <Radio.Button value="house">房源信息</Radio.Button>
66
+        <Radio.Button value="poster">海报设置</Radio.Button>
67
+        <Radio.Button value="share">分享设置</Radio.Button>
68
+        {/* <Radio.Button value="preselectionImg">预选热度图</Radio.Button> */}
69
+        {/* <Radio.Button value="preselectionRecord">预选记录</Radio.Button> */}
70
+        {/* <Radio.Button value="identifyingChips">认筹单</Radio.Button> */}
71
+        {/* <Radio.Button value="pay">缴费单</Radio.Button> */}
72
+        {/* <Radio.Button value="refund">退费单</Radio.Button> */}
73
+        <Radio.Button value="shareRecord">分享记录</Radio.Button>
74
+        <Radio.Button value="visitRecord">分享访问记录</Radio.Button>
75
+      </Radio.Group>
76
+      <div style={{ marginTop: '20px' }}>
77
+        { (tab === 'base' && <Base salesBatchId={{ batchId }} onSuccess={e => buildingOnSuccess(e)}/>)} 
78
+        { (tab === 'house' && <HouseTab salesBatchId={props.location.query.id} buildingId={props.location.query.buildingId} onSuccess={e => housTabChange(e)}/>)}
79
+        { (tab === 'poster' && <Poster salesBatchId={{ batchId }}/>)}
80
+        { (tab === 'share' && <Share salesBatchId={{ batchId }}/>)}
81
+        { (tab === 'preselectionImg' && <PreselectionImg salesBatchId={batchId} />)}
82
+        { (tab === 'preselectionRecord' && <PreselectionRecord houseId={houseId} buildingId={props.location.query.buildingId} salesBatchId={{ batchId }}/>)}
83
+        { (tab === 'identifyingChips' && <IdentifyingChips houseId={houseId} buildingId={props.location.query.buildingId} salesBatchId={{ batchId }}/>)}
84
+        { (tab === 'pay' && <PaymentChips salesBatchId={{ batchId }}/>)}
85
+        { (tab === 'refund' && <Refund salesBatchId={{ batchId }}/>)}
86
+        { (tab === 'shareRecord' && <ShareRecord salesBatchId={{ batchId }}/>)}
87
+        { (tab === 'visitRecord' && <VisitRecord salesBatchId={{ batchId }}/>)}
88
+      </div>
89
+    </>
90
+  )
91
+}
92
+
93
+const WrappedEditHouseForm = Form.create({ name: 'editHouse' })(EditHouse);
94
+
95
+export default WrappedEditHouseForm