知与行后台管理端

index.jsx 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  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 } 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 Attribution from './components/attribution'
  9. import IntegralRecord from './components/integralRecord'
  10. import ModalRecommendRecord from './components/recommend'
  11. import ChangeStatus from './components/changeStatus'
  12. import BuildSelect from '../../../components/SelectButton/BuildSelect'
  13. import AuthButton from '@/components/AuthButton';
  14. const { Option } = Select;
  15. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  16. const { Meta } = Card;
  17. /**
  18. *
  19. *
  20. * @param {*} props
  21. * @returns
  22. */
  23. function body(props) {
  24. const { getFieldDecorator, getFieldsValue } = props.form
  25. // eslint-disable-next-line react-hooks/rules-of-hooks
  26. const [dataSource, setDataSource] = useState({ records: [] })
  27. // eslint-disable-next-line react-hooks/rules-of-hooks
  28. // const [columns, setColumns] = useState(privateColumns)
  29. // 默认私客
  30. // eslint-disable-next-line react-hooks/rules-of-hooks
  31. const [customerType, setCustomerType] = useState('private')
  32. // 调整归属 ============ start
  33. // eslint-disable-next-line react-hooks/rules-of-hooks
  34. const [gVisibleData, setGVisibleData] = useState({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
  35. // 调整归属 ============= end
  36. // 积分记录 ============ start
  37. // eslint-disable-next-line react-hooks/rules-of-hooks
  38. const [recordVisibleData, setRecordVisibleData] = useState({ visible: false, customerId: '' })
  39. // 积分记录 ============= end
  40. // 变更状态 ============ start
  41. // eslint-disable-next-line react-hooks/rules-of-hooks
  42. const [statusVisibleData, setStatusVisibleData] = useState({ visible: false, customerId: '', status: '' })
  43. // 变更状态 ============= end
  44. // 推荐客户
  45. const [recommendVisibleData, setRecommendVisibleData] = useState({ visible: false, customerId: '' })
  46. // eslint-disable-next-line react-hooks/rules-of-hooks
  47. useEffect(() => {
  48. getList({ pageNumber: 1, pageSize: 10, customerType })
  49. }, [])
  50. function getList(params) {
  51. // 网路请求
  52. request({ ...apis.customer.customerRecommend, params: { ...params } }).then(res => {
  53. setDataSource(res)
  54. }).catch(err => {
  55. // eslint-disable-next-line no-unused-expressions
  56. <Alert
  57. style={{
  58. marginBottom: 24,
  59. }}
  60. message={err}
  61. type="error"
  62. showIcon
  63. />
  64. })
  65. }
  66. function displayNone() {
  67. setRecordVisibleData({ visible: false, customerId: '' })
  68. setGVisibleData({ visible: false, customerId: '', realtyConsultant: '' })
  69. setStatusVisibleData({ visible: false, customerId: '', status: '' })
  70. setRecommendVisibleData({ visible: false, customerId: '' })
  71. }
  72. // 提交事件
  73. function handleSubmit(e) {
  74. displayNone()
  75. e.preventDefault();
  76. props.form.validateFields((err, values) => {
  77. if (!err) {
  78. getList({ pageNum: 1, pageSize: 10, customerType, ...values })
  79. }
  80. });
  81. }
  82. // Change 事件
  83. function handleSelectChange(e) {
  84. // eslint-disable-next-line no-console
  85. console.log(e)
  86. }
  87. // 分页
  88. function onChange(pageNum) {
  89. // eslint-disable-next-line react-hooks/rules-of-hooks
  90. getList({ pageNumber: pageNum, pageSize: 10, customerType })
  91. }
  92. // 私客/公客切换
  93. function radioButtonHandleSizeChange(e) {
  94. displayNone()
  95. const { value } = e.target
  96. setCustomerType(value)
  97. //setColumns(value === 'private' ? privateColumns : publicColumns)
  98. getList({ pageNumber: 1, pageSize: 10, customerType: value })
  99. }
  100. function handleReset() {
  101. props.form.resetFields();
  102. getList({ pageNumber: 1, pageSize: 10, customerType })
  103. }
  104. // 这里有个 Bug, 就是 Modal 弹框,会联动出现, 比如 我点击 调整归属的Model弹框, 那么 积分记录的Model弹框莫名其妙的也显示了
  105. // 所有这里临时解决方法是,弹出一个Modal对话框的时候,把其他的对话框给隐藏
  106. function showGM(record) {
  107. setGVisibleData({ visible: true, customerId: record.customerId, realtyConsultant: record.realtyConsultant, buildingId: record.buildingId })
  108. setRecordVisibleData({ visible: false, customerId: '' })
  109. setStatusVisibleData({ visible: false, customerId: '' })
  110. setRecommendVisibleData({ visible: false, customerId: '' })
  111. }
  112. function showRecord(record) {
  113. setRecordVisibleData({ visible: true, customerId: record.customerId })
  114. setGVisibleData({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
  115. setStatusVisibleData({ visible: false, customerId: '' })
  116. setRecommendVisibleData({ visible: false, customerId: '' })
  117. }
  118. function showStatus(record) {
  119. setRecordVisibleData({ visible: false, customerId: '' })
  120. setGVisibleData({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
  121. setRecommendVisibleData({ visible: false, customerId: '' })
  122. setStatusVisibleData({ visible: true, customerId: record.customerId, status: record.status })
  123. }
  124. // 推荐客户
  125. function showRecommend(personId) {
  126. setRecordVisibleData({ visible: false, customerId: '' })
  127. setGVisibleData({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
  128. setStatusVisibleData({ visible: false, customerId: '', status: '' })
  129. setRecommendVisibleData({ visible: true, customerId: personId })
  130. }
  131. function toCustomerDateil(record) {
  132. router.push({
  133. pathname: '/customer/customerlist/customerDetail',
  134. query: {
  135. id: record.customerId,
  136. },
  137. });
  138. }
  139. // 私客详情
  140. function publicCustomerDetail(record) {
  141. router.push({
  142. pathname: '/customer/customerlist/publicCustomerDetail',
  143. query: {
  144. id: record.personId,
  145. },
  146. });
  147. }
  148. function exportCustomer () {
  149. const fieldsValue = getFieldsValue()
  150. request({ ...apis.customer.customerRecommendExport, responseType: 'blob', params: { ...fieldsValue, customerType } })
  151. .then(response => {
  152. download(response)
  153. }).catch(error => {
  154. })
  155. }
  156. function download (data) {
  157. if (!data) {
  158. return
  159. }
  160. const url = window.URL.createObjectURL(new Blob([data]))
  161. const link = document.createElement('a')
  162. link.style.display = 'none'
  163. link.href = url
  164. link.setAttribute('download', '客户列表.xlsx')
  165. document.body.append(link)
  166. link.click()
  167. }
  168. // 关闭调整归属的窗口
  169. function closeAttribution() {
  170. setGVisibleData({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
  171. getList({ pageNum: 1, pageSize: 10, customerType, ...props.form.getFieldsValue() })
  172. }
  173. // 回调关闭所有弹框
  174. function closeAll() {
  175. setRecordVisibleData({ visible: false, customerId: '' })
  176. setGVisibleData({ visible: false, customerId: '', realtyConsultant: '', buildingId: '' })
  177. setStatusVisibleData({ visible: false, customerId: '', status: '' })
  178. setRecommendVisibleData({ visible: false, customerId: '' })
  179. getList({ pageNum: 1, pageSize: 10, customerType, ...props.form.getFieldsValue() })
  180. }
  181. const publicColumns = [
  182. {
  183. title: '头像',
  184. dataIndex: 'picture',
  185. key: 'picture',
  186. align: 'center',
  187. width: '15%',
  188. render: (_, record) => <Avatar shape="square" src={customerType === 'private' ? record.picture : record.avatarurl} size={64} icon="user" />,
  189. },
  190. {
  191. title: '姓名',
  192. dataIndex: 'name',
  193. key: 'name',
  194. align: 'center',
  195. width: '10%',
  196. // eslint-disable-next-line no-nested-ternary
  197. render: (_, record) => <><span>{customerType === 'private' ? record.name : record.nickname}</span></>,
  198. },
  199. {
  200. title: '电话',
  201. dataIndex: 'phone',
  202. key: 'phone',
  203. align: 'center',
  204. width: '15%',
  205. },
  206. {
  207. title: '推广人员',
  208. dataIndex: 'sharePersonName',
  209. key: 'sharePersonName',
  210. align: 'center',
  211. width: '15%',
  212. },
  213. {
  214. title: '性别',
  215. dataIndex: 'sex',
  216. key: 'sex',
  217. align: 'center',
  218. width: '10%',
  219. // eslint-disable-next-line no-nested-ternary
  220. render: (_, record) => <><span>{record.sex === 1 ? '男' : record.sex === 2 ? '女' : '未知'}</span></>,
  221. },
  222. {
  223. title: '操作',
  224. dataIndex: 'customerId',
  225. key: 'customerId',
  226. align: 'center',
  227. width: '25%',
  228. // eslint-disable-next-line no-nested-ternary
  229. render: (_, record) => (
  230. <>
  231. <AuthButton>
  232. <Button className={customerType === 'private' ? Styles.displayS : Styles.text } type="link" onClick={() => publicCustomerDetail(record)}>查看详情</Button>
  233. </AuthButton>
  234. &nbsp;&nbsp;
  235. <AuthButton>
  236. <Button className={customerType === 'private' ? Styles.displayS : Styles.text } type="link" onClick={() => showRecommend(record.personId)}>推荐客户</Button>
  237. </AuthButton>
  238. </>
  239. ),
  240. },
  241. ]
  242. const privateColumns = [
  243. {
  244. title: '头像',
  245. dataIndex: 'picture',
  246. key: 'picture',
  247. align: 'center',
  248. width: '15%',
  249. render: (_, record) => <Avatar shape="square" src={customerType === 'private' ? record.picture : record.avatarurl} size={64} icon="user" />,
  250. },
  251. {
  252. title: '姓名',
  253. dataIndex: 'name',
  254. key: 'name',
  255. align: 'center',
  256. width: '10%',
  257. // eslint-disable-next-line no-nested-ternary
  258. render: (_, record) => <><span>{customerType === 'private' ? record.name : record.nickname}</span></>,
  259. },
  260. {
  261. title: '电话',
  262. dataIndex: 'phone',
  263. key: 'phone',
  264. align: 'center',
  265. width: '15%',
  266. },
  267. {
  268. title: '性别',
  269. dataIndex: 'sex',
  270. key: 'sex',
  271. align: 'center',
  272. width: '10%',
  273. // eslint-disable-next-line no-nested-ternary
  274. render: (_, record) => <><span>{record.sex === 1 ? '男' : record.sex === 2 ? '女' : '未知'}</span></>,
  275. },
  276. {
  277. title: '置业顾问',
  278. dataIndex: 'consultantName',
  279. key: 'consultantName',
  280. align: 'center',
  281. width: '15%',
  282. // eslint-disable-next-line no-nested-ternary
  283. render: (_, record) => (
  284. <>
  285. <span>{record.consultantName}</span>
  286. <br />
  287. <span>{record.consultTel}</span>
  288. </>
  289. ),
  290. },
  291. {
  292. title: '推广人员',
  293. dataIndex: 'sharePersonName',
  294. key: 'sharePersonName',
  295. align: 'center',
  296. width: '15%',
  297. },
  298. {
  299. title: '客户状态',
  300. dataIndex: 'reportRecommendStatus',
  301. key: 'reportRecommendStatus',
  302. align: 'center',
  303. width: '10%',
  304. // eslint-disable-next-line no-nested-ternary
  305. render: (text, records) => {
  306. if (records.status === 1) { return '报备' }
  307. if (records.status === 2) { return '到访' }
  308. if (records.status === 3) { return '认筹' }
  309. if (records.status === 4) { return '签约' }
  310. },
  311. },
  312. {
  313. title: '操作',
  314. dataIndex: 'customerId',
  315. key: 'customerId',
  316. align: 'center',
  317. width: '25%',
  318. // eslint-disable-next-line no-nested-ternary
  319. render: (_, record) => (
  320. <>
  321. &nbsp;
  322. <AuthButton name="admin.customer.recommend.edit.id.put" noRight={null}>
  323. <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => showStatus(record)}>变更状态</Button>
  324. &nbsp;&nbsp;
  325. <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => showGM(record)}>调整归属</Button>
  326. </AuthButton>
  327. &nbsp;&nbsp;
  328. <AuthButton name="admin.customer.recommend.get" noRight={null}>
  329. <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => toCustomerDateil(record)}>查看详情</Button>
  330. </AuthButton>
  331. &nbsp;&nbsp;
  332. <AuthButton name="admin.mine.taPointsRecords.id.get" noRight={null}>
  333. <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => showRecord(record)}>积分记录</Button>
  334. </AuthButton>
  335. &nbsp;
  336. <AuthButton name="admin.mine.taPointsRecords.id.get" noRight={null}>
  337. <Button className={customerType === 'private' ? Styles.text : Styles.displayS} type="link" onClick={() => showRecommend(record.personId)}>推荐客户</Button>
  338. </AuthButton>
  339. </>
  340. ),
  341. },
  342. ]
  343. return (
  344. <>
  345. {console.log('customerType', customerType)}
  346. <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
  347. {customerType === 'private' && <Form.Item>
  348. {getFieldDecorator('buildingId')(
  349. <BuildSelect />,
  350. )}
  351. </Form.Item>}
  352. {customerType === 'private' && <Form.Item>
  353. {getFieldDecorator('status')(
  354. <Select style={{ width: '180px' }} placeholder="状态" onChange={handleSelectChange}>
  355. <Option value={1}>报备</Option>
  356. <Option value={2}>到访</Option>
  357. <Option value={3}>认筹</Option>
  358. <Option value={4}>签约</Option>
  359. </Select>,
  360. )}
  361. </Form.Item>}
  362. <Form.Item>
  363. {getFieldDecorator('name')(
  364. <Input
  365. prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
  366. placeholder="姓名"
  367. />,
  368. )}
  369. </Form.Item>
  370. <Form.Item>
  371. {getFieldDecorator('tel')(
  372. <Input
  373. prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
  374. placeholder="电话"
  375. />,
  376. )}
  377. </Form.Item>
  378. {customerType === 'private' && <Form.Item>
  379. {getFieldDecorator('consultName')(
  380. <Input placeholder="置业顾问" />,
  381. )}
  382. </Form.Item>}
  383. {customerType === 'private' && <Form.Item>
  384. {getFieldDecorator('consultTel')(
  385. <Input placeholder="置业顾问电话" />,
  386. )}
  387. </Form.Item>}
  388. <Form.Item>
  389. <Button type="primary" htmlType="submit" >
  390. 查询
  391. </Button>
  392. <Button style={{ marginLeft: 8 }} onClick={handleReset}>
  393. 重置
  394. </Button>
  395. </Form.Item>
  396. </Form>
  397. <Button type="primary" onClick={() => exportCustomer()} style={{ float: 'right', margin: '20px 0', zIndex: 1 }}>
  398. 导出
  399. </Button>
  400. <div style={{ margin: '20px 0'}}>
  401. <AuthButton name="admin.customer.recommend.get" noRight={null}>
  402. <Radio.Group value={customerType} onChange={radioButtonHandleSizeChange} buttonStyle="solid">
  403. <Radio.Button value="private">私客</Radio.Button>
  404. <Radio.Button value="public">公客</Radio.Button>
  405. </Radio.Group>
  406. </AuthButton>
  407. </div>
  408. {customerType === 'private' ?
  409. <Table dataSource={dataSource.records} columns={privateColumns} pagination={{ total: dataSource.total, onChange }} rowKey="customerList" /> :
  410. <Table dataSource={dataSource.records} columns={publicColumns} pagination={{ total: dataSource.total, onChange }} rowKey="customerList" />
  411. }
  412. {/* 调整归属 */}
  413. <Attribution visibleData={gVisibleData} onCancel={() => closeAttribution()}/>
  414. {/* 积分记录 */}
  415. <IntegralRecord visibleData={recordVisibleData} onCancel={() => closeAll()} />
  416. {/* 变更状态 */}
  417. <ChangeStatus visibleData={statusVisibleData} onCancel={() => closeAll()}/>
  418. {/* 推荐客户 */}
  419. <ModalRecommendRecord visibleData={recommendVisibleData} onCancel={() => closeAll()}/>
  420. </>
  421. );
  422. }
  423. const WrappedBody = Form.create({ name: 'body' })(body);
  424. export default WrappedBody