index.jsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. import React, { useState, useEffect, useRef, useMemo } from 'react'
  2. import ProTable from '@ant-design/pro-table'
  3. import { useTableScroll } from '@/hooks/useAutoTable'
  4. import { Button, message } from 'antd'
  5. import { connect } from 'dva'
  6. import consts from '@/consts'
  7. import { queryCompany, apiAddCompany } from '@/services/company'
  8. import LazyCascader from '@/components/LazyCascader'
  9. import CompanyDetail from '@/pages/Customer/Company/components/CompanyDetail'
  10. import AddCompany from '@/pages/Customer/Company/components/AddCompany'
  11. import { useModal } from '@/components/Modal'
  12. import { formatValues } from '@/components/LazyCascader'
  13. import PersonLabel from './components/PersonLabel'
  14. import { TagTypeEnum } from './components/PersonLabel'
  15. import { TagDataTypeEnum } from './components/PersonLabel'
  16. import { LabelModeType } from './components/PersonLabel'
  17. import { IconPark } from '@/components/SvgIcon'
  18. import { apiBatchLink } from '@/services/customer'
  19. const Company = props => {
  20. const { personTagColorMap, teamTagColorMap, personTags, teamTags, dispatch } = props
  21. const { toggleDrawer, setDrawerProps } = useModal()
  22. const tRef = useRef(null)
  23. const [selectKeys, setSelectKeys] = useState([])
  24. const [tagState, setTagState] = useState({
  25. tagIds: [],
  26. tagCooperationIds: []
  27. })
  28. const tag = useMemo(() => {
  29. const personTagMap = {}
  30. const teamTagMap = {}
  31. personTags.forEach(item => {
  32. personTagMap[item.id] = {
  33. text: (
  34. <>
  35. <span
  36. className="zh-circle-icon zh-mg-right-3"
  37. style={{ backgroundColor: personTagColorMap[item.id] }}
  38. />
  39. <span>{item.name}</span>
  40. </>
  41. )
  42. }
  43. })
  44. teamTags.forEach(item => {
  45. teamTagMap[item.id] = {
  46. text: (
  47. <>
  48. <span
  49. className="zh-circle-icon zh-mg-right-3"
  50. style={{ backgroundColor: teamTagColorMap[item.id] }}
  51. />
  52. <span>{item.name}</span>
  53. </>
  54. )
  55. }
  56. })
  57. return { personTagMap, teamTagMap }
  58. }, [personTags, teamTags])
  59. const [state, setState] = useState({
  60. id: '',
  61. params: {},
  62. visible: false
  63. })
  64. const [addCompany, setAddCompany] = useState({
  65. visible: false,
  66. loading: false
  67. })
  68. // 重置到默认值,包括表单
  69. const initData = () => {
  70. tRef.current.reset()
  71. }
  72. // 刷新
  73. const refreshData = () => {
  74. tRef.current.reload()
  75. }
  76. const handleAddCompany = async values => {
  77. setAddCompany({ ...addCompany, loading: true })
  78. const params = formatValues(values)
  79. const { code = -1 } = await apiAddCompany(params)
  80. if (code === consts.RET_CODE.SUCCESS) {
  81. message.success('新增成功')
  82. }
  83. // 请求完了
  84. setAddCompany({ ...addCompany, loading: false, visible: false })
  85. initData()
  86. }
  87. useEffect(() => {
  88. if (!personTags.length) {
  89. dispatch({
  90. type: 'company/fetchTags',
  91. payload: { tagType: TagTypeEnum.PERSONTAG, tagColumn: TagDataTypeEnum.COMPANY }
  92. })
  93. }
  94. if (!teamTags.length) {
  95. dispatch({
  96. type: 'company/fetchTags',
  97. payload: { tagType: TagTypeEnum.TEAMTAG, tagColumn: TagDataTypeEnum.COMPANY }
  98. })
  99. }
  100. }, [])
  101. const handleSearch = value => {
  102. setState({ ...state, params: { ...state.params, search: value, current: 1 } })
  103. }
  104. const onDistrictChange = value => {
  105. const [province = '', city = '', area = ''] = value
  106. setState({ ...state, params: { ...state.params, current: 1, province, city, area } })
  107. }
  108. // 展示drawer
  109. const showDrawer = id => {
  110. setDrawerProps({
  111. closable: true,
  112. onClose: () => toggleDrawer(),
  113. bodyStyle: {
  114. height: '100vh',
  115. overflowY: 'hidden'
  116. },
  117. children: <CompanyDetail id={id} />
  118. })
  119. toggleDrawer()
  120. }
  121. const columns = [
  122. {
  123. title: '客户名称',
  124. dataIndex: 'companyName',
  125. key: 'companyName',
  126. width: 150,
  127. render: (companyName, record) => <a onClick={() => showDrawer(record.id)}>{companyName}</a>
  128. },
  129. {
  130. title: '地区',
  131. dataIndex: 'local',
  132. key: 'local',
  133. width: 100
  134. },
  135. {
  136. title: '个人标签',
  137. dataIndex: 'biaoqian',
  138. key: 'biaoqian',
  139. width: 100,
  140. filters: true,
  141. valueEnum: tag.personTagMap,
  142. render: (_, record) => (
  143. <div className="zh-align-center zh-flex-wrap">
  144. {record.tagIds.map(item => (
  145. <span
  146. key={record.id + item}
  147. className="zh-circle-icon zh-mg-right-3"
  148. style={{ backgroundColor: personTagColorMap[item] }}
  149. />
  150. ))}
  151. <PersonLabel
  152. dataId={record.id}
  153. tagIds={record.tagIds}
  154. tagType={TagTypeEnum.PERSONTAG}
  155. tagColumn={TagDataTypeEnum.COMPANY}
  156. checkCallBack={refreshData}
  157. modeType={LabelModeType.column}>
  158. <IconPark type="add" theme="filled" size="20" fill="#868e96" className="zh-pointer" />
  159. </PersonLabel>
  160. </div>
  161. )
  162. },
  163. {
  164. title: '协作标签',
  165. dataIndex: 'tagCooperationIds',
  166. key: 'tagCooperationIds',
  167. width: 80,
  168. filters: true,
  169. valueEnum: tag.teamTagMap,
  170. render: (_, record) => (
  171. <div className="zh-align-center zh-flex-wrap">
  172. {record.tagCooperationIds.map(item => (
  173. <span
  174. key={record.id + item}
  175. className="zh-circle-icon zh-mg-right-3"
  176. style={{ backgroundColor: personTagColorMap[item] }}
  177. />
  178. ))}
  179. <PersonLabel
  180. dataId={record.id}
  181. tagIds={record.tagCooperationIds}
  182. tagType={TagTypeEnum.TEAM}
  183. tagColumn={TagDataTypeEnum.COMPANY}
  184. checkCallBack={refreshData}
  185. modeType={LabelModeType.column}>
  186. <IconPark type="add" theme="filled" size="20" fill="#868e96" className="zh-pointer" />
  187. </PersonLabel>
  188. </div>
  189. )
  190. },
  191. {
  192. title: '联系人',
  193. dataIndex: 'clientTotal',
  194. key: 'clientTotal',
  195. width: 80
  196. },
  197. {
  198. title: '公司性质',
  199. dataIndex: 'nature',
  200. key: 'nature',
  201. width: 80
  202. },
  203. {
  204. title: '公司地址',
  205. dataIndex: 'address',
  206. key: 'address',
  207. width: 80
  208. },
  209. {
  210. title: '公司传真',
  211. dataIndex: 'fax',
  212. key: 'fax',
  213. width: 80
  214. },
  215. {
  216. title: '网址',
  217. dataIndex: 'webservice',
  218. key: 'webservice',
  219. width: 80
  220. },
  221. {
  222. title: '乘车路线',
  223. dataIndex: 'ride',
  224. key: 'ride',
  225. width: 80
  226. },
  227. {
  228. title: '地标建筑',
  229. dataIndex: 'landmarks',
  230. key: 'landmarks',
  231. width: 80
  232. },
  233. {
  234. title: '参考住宿',
  235. dataIndex: 'stay',
  236. key: 'stay',
  237. width: 80
  238. },
  239. {
  240. title: '备注',
  241. dataIndex: 'remarks',
  242. key: 'remarks',
  243. width: 80
  244. }
  245. ]
  246. const [columnsStateMap, setColumnsStateMap] = useState({
  247. address: {
  248. show: false
  249. },
  250. nature: {
  251. show: false
  252. },
  253. fax: {
  254. show: false
  255. },
  256. webservice: {
  257. show: false
  258. },
  259. ride: {
  260. show: false
  261. },
  262. stay: {
  263. show: false
  264. },
  265. landmarks: {
  266. show: false
  267. },
  268. remarks: {
  269. show: false
  270. }
  271. })
  272. const hanleRowSelectChange = selectedRowKeys => {
  273. setSelectKeys(selectedRowKeys)
  274. }
  275. const toolbarOptionsChange = (type, ids) => {
  276. setTagState({ ...tagState, [type]: ids })
  277. }
  278. const { getScrollRef } = useTableScroll(columns, selectKeys)
  279. // 批量设置-确认触发
  280. const tagsSettingConfirm = async clientIds => {
  281. if (tagState.tagIds.length) {
  282. await apiBatchLink({
  283. tagIds: tagState.tagIds,
  284. dataIds: clientIds,
  285. dataType: TagDataTypeEnum.COMPANY,
  286. tagType: TagTypeEnum.PERSONTAG
  287. })
  288. }
  289. if (tagState.tagCooperationIds.length) {
  290. await apiBatchLink({
  291. tagIds: tagState.tagIds,
  292. dataIds: clientIds,
  293. dataType: TagDataTypeEnum.COMPANY,
  294. tagType: TagTypeEnum.PERSONTAG
  295. })
  296. }
  297. refreshData()
  298. }
  299. const renderTableAlert = ({ selectedRowKeys }) => {
  300. return (
  301. <div className="zh-flex-row">
  302. <div className="zh-mg-right-5">
  303. <PersonLabel
  304. tagType={TagTypeEnum.PERSONTAG}
  305. tagColumn={TagDataTypeEnum.COMPANY}
  306. checkCallBack={toolbarOptionsChange}
  307. modeType={LabelModeType.toolbar}>
  308. {tagState.tagIds.length ? (
  309. <Button>
  310. {tagState.tagIds.map(item => (
  311. <span
  312. key={item}
  313. className="zh-circle-icon zh-mg-right-3"
  314. style={{ backgroundColor: personTagColorMap[item] }}
  315. />
  316. ))}
  317. <IconPark type="down" />
  318. </Button>
  319. ) : (
  320. <Button>
  321. 个人标签
  322. <IconPark type="down" />
  323. </Button>
  324. )}
  325. </PersonLabel>
  326. </div>
  327. <div className="zh-mg-right-5">
  328. <PersonLabel
  329. tagType={TagTypeEnum.TEAMTAG}
  330. tagColumn={TagDataTypeEnum.COMPANY}
  331. checkCallBack={toolbarOptionsChange}
  332. modeType={LabelModeType.toolbar}>
  333. {tagState.tagCooperationIds.length ? (
  334. <Button>
  335. {tagState.tagCooperationIds.map(item => (
  336. <span
  337. key={item}
  338. className="zh-square-icon zh-mg-right-3"
  339. style={{ backgroundColor: teamTagColorMap[item] }}
  340. />
  341. ))}
  342. <IconPark type="down" />
  343. </Button>
  344. ) : (
  345. <Button>
  346. 协作标签
  347. <IconPark type="down" />
  348. </Button>
  349. )}
  350. </PersonLabel>
  351. </div>
  352. <Button onClick={() => tagsSettingConfirm(selectedRowKeys)}>
  353. <IconPark type="check" size={14} />
  354. 确认
  355. </Button>
  356. </div>
  357. )
  358. }
  359. return (
  360. <div className="zh-container">
  361. <ProTable
  362. rowKey={record => record.id}
  363. search={false}
  364. actionRef={tRef}
  365. params={state.params}
  366. request={async (params, sort, filter) => {
  367. const {
  368. code = -1,
  369. data: { customer = [], total = 0 } = { customer: [], total: 0 }
  370. } = await queryCompany({ ...params, ...sort, ...filter })
  371. return {
  372. data: customer,
  373. success: code === consts.RET_CODE.SUCCESS,
  374. total
  375. }
  376. }}
  377. headerTitle="客户"
  378. bordered
  379. toolbar={{
  380. search: {
  381. allowClear: true,
  382. onSearch: handleSearch
  383. },
  384. actions: [
  385. <LazyCascader onChange={onDistrictChange} key="lazyCascader" />,
  386. <AddCompany onConfirm={handleAddCompany} key="addCompanyBtn" />
  387. ]
  388. }}
  389. rowSelection={{
  390. onChange: hanleRowSelectChange,
  391. type: 'checkbox'
  392. }}
  393. tableAlertRender={renderTableAlert}
  394. scroll={getScrollRef}
  395. columnsStateMap={columnsStateMap}
  396. onColumnsStateChange={map => setColumnsStateMap(map)}
  397. columns={columns}
  398. />
  399. </div>
  400. )
  401. }
  402. export default connect(({ company }) => ({
  403. personTagColorMap: company.personTagColorMap,
  404. personTags: company.personTags,
  405. teamTagColorMap: company.teamTagColorMap,
  406. teamTags: company.teamTags
  407. }))(Company)