index.jsx 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. import React, { useState, useEffect, useRef } from 'react'
  2. import { connect, useModel } from 'umi'
  3. import { getBusinessList } from '@/services/customer'
  4. import consts from '@/consts'
  5. import { Select, Tooltip, Input } from 'antd'
  6. import AddBusiness from './components/AddBusiness'
  7. import Detail from './components/BusinessDetail'
  8. import { useModal } from '@/components/Modal'
  9. import CompanyDetail from '../Company/components/CompanyDetail'
  10. import { Funnel } from '@ant-design/charts'
  11. import BasicTable from '@/components/Table'
  12. import { getPermAuthCache } from '@/utils/auth'
  13. import { PermDataTypeEunm } from '@/pages/Customer/Company/components/PermSelect'
  14. const Business = ({ dispatch, groupList, shouldUpdate, loading }) => {
  15. const [defaultPermAuthCache, defaultStaffIds] = getPermAuthCache(PermDataTypeEunm.CUSTOMER)
  16. const tRef = useRef(null)
  17. const { toggleDrawer, setDrawerProps } = useModal()
  18. const [state, setState] = useState({
  19. orderIds: [],
  20. params: { businessGroupId: null },
  21. groupParams: { staffIds: defaultStaffIds, dataPermission: defaultPermAuthCache },
  22. funnelData: []
  23. })
  24. const { initialState: { permData } = { permData: {} } } = useModel('@@initialState')
  25. const handleSearch = value => {
  26. setState({ ...state, params: { ...state.params, search: value } })
  27. }
  28. const initGroupList = (payload = {}) => {
  29. dispatch({
  30. type: 'business/fetchGroup',
  31. payload
  32. })
  33. }
  34. useEffect(() => {
  35. if (!groupList) {
  36. initGroupList(state.groupParams)
  37. }
  38. if (groupList) {
  39. const group = groupList[0]
  40. if (group) {
  41. console.log(
  42. group.items
  43. ?.filter(item => !item.endProcess)
  44. ?.map(item => ({ ...item, percentage: parseInt(item.percentage, 10) }))
  45. )
  46. setState({
  47. ...state,
  48. params: { ...state.params, businessGroupId: group.value },
  49. funnelData: group.items
  50. ?.filter(item => !item.endProcess)
  51. ?.map(item => ({ ...item, percentage: parseInt(item.percentage, 10) }))
  52. })
  53. }
  54. }
  55. }, [groupList, state.groupParams])
  56. useEffect(() => {
  57. if (shouldUpdate) {
  58. tRef.current.reload()
  59. }
  60. }, [loading, shouldUpdate])
  61. // 展示drawer
  62. const showDrawer = (id, isCompany = false) => {
  63. setDrawerProps({
  64. closable: true,
  65. onClose: () => toggleDrawer(),
  66. bodyStyle: {
  67. height: '100vh',
  68. overflowY: 'hidden'
  69. },
  70. children: isCompany ? (
  71. <CompanyDetail dataId={id} />
  72. ) : (
  73. <Detail dataId={id} orderIds={state.orderIds} group={groupList} />
  74. )
  75. })
  76. toggleDrawer()
  77. }
  78. const columns = [
  79. {
  80. dataIndex: 'name',
  81. title: '商机名称',
  82. width: '10%',
  83. render: (text, record) => (
  84. <span
  85. onClick={() => showDrawer(record.id)}
  86. className="text-primary cursor-pointer hover:text-[#967bbd]"
  87. >
  88. {text}
  89. </span>
  90. )
  91. },
  92. {
  93. dataIndex: 'customerName',
  94. title: '单位名称',
  95. width: '20%',
  96. render: (text, record) =>
  97. record.customerId && (
  98. <span
  99. onClick={() => showDrawer(record.customerId, true)}
  100. className="text-primary cursor-pointer hover:text-[#967bbd]"
  101. >
  102. {text}
  103. </span>
  104. )
  105. },
  106. {
  107. dataIndex: 'businessStatusName',
  108. title: '商机状态',
  109. width: '10%'
  110. },
  111. {
  112. dataIndex: 'responsible',
  113. width: '10%',
  114. title: '负责人'
  115. },
  116. {
  117. dataIndex: 'remark',
  118. title: '备注',
  119. width: '10%'
  120. },
  121. {
  122. dataIndex: 'updateTime',
  123. title: '最后跟进时间',
  124. ellipsis: true
  125. },
  126. {
  127. dataIndex: 'createTime',
  128. title: '创建时间',
  129. ellipsis: true
  130. },
  131. {
  132. dataIndex: 'staffName',
  133. title: '创建人',
  134. width: '10%'
  135. }
  136. ]
  137. const conifg = {
  138. xField: 'name',
  139. yField: 'count',
  140. shape: 'pyramid',
  141. conversionTag: false
  142. }
  143. const handleOnPermChange = ({ staffIds, dataPermission }) =>
  144. setState({ ...state, groupParams: { ...state.groupParams, staffIds, dataPermission } })
  145. return (
  146. <div className="h-full w-full flex flex-row justify-between">
  147. <div className="h-full w-3/20 rounded-4px shadow-card">
  148. <div className="p-4 border-b-1 border-solid border-black border-opacity-10 bg-[#f7f9fa] flex justify-around items-center">
  149. <div className="w-1/2 text-md">商机漏斗</div>
  150. <div className="w-1/2">
  151. {groupList && (
  152. <Select
  153. size="small"
  154. className="w-full"
  155. bordered={false}
  156. options={groupList}
  157. defaultValue={groupList[0]?.value}
  158. onChange={(id, option) => {
  159. setState({
  160. ...state,
  161. params: { ...state.params, businessGroupId: id },
  162. funnelData: option.items
  163. .filter(item => !item.endProcess)
  164. .map(item => ({ ...item, percentage: parseInt(item.percentage, 10) }))
  165. })
  166. }}
  167. />
  168. )}
  169. </div>
  170. </div>
  171. <div className="p-4 bg-white " style={{ height: 'calc(100% - 1rem*2 - 20px)' }}>
  172. <div className="max-h-1/3">
  173. <Funnel data={state.funnelData} {...conifg} />
  174. </div>
  175. </div>
  176. </div>
  177. <div className="w-17/20">
  178. <div className="ml-8 bg-white shadow-card">
  179. <BasicTable
  180. actionRef={tRef}
  181. mainMenuType="customer"
  182. columnStateType="BUSINESS"
  183. onPermChange={handleOnPermChange}
  184. params={state.params}
  185. rowKey={record => record.id}
  186. columns={columns}
  187. request={async (params, sort, filter) => {
  188. if (!state.params.businessGroupId) {
  189. return {
  190. data: [],
  191. success: true,
  192. total: 0
  193. }
  194. }
  195. const {
  196. code = -1,
  197. data: { business = [], total = 0 }
  198. } = await getBusinessList({ ...params, ...sort, ...filter })
  199. setState({ ...state, orderIds: business.map(item => item.id) })
  200. return {
  201. data: business,
  202. success: code === consts.RET_CODE.SUCCESS,
  203. total
  204. }
  205. }}
  206. search={false}
  207. toolbar={{
  208. search: (
  209. <Tooltip placement="bottom" title="输入商机名称、单位名称">
  210. <Input.Search
  211. style={{ width: '300px' }}
  212. allowClear={true}
  213. placeholder={`在${
  214. permData[PermDataTypeEunm.CUSTOMER]?.find(
  215. item => item.value === defaultPermAuthCache
  216. )?.label
  217. }下搜索`}
  218. onSearch={handleSearch}
  219. />
  220. </Tooltip>
  221. ),
  222. actions: [
  223. <AddBusiness
  224. key="add"
  225. groupList={state.groupList}
  226. reload={() => tRef.current?.reload()}
  227. />
  228. ]
  229. }}
  230. />
  231. </div>
  232. </div>
  233. </div>
  234. )
  235. }
  236. export default connect(({ business, refresh, loading }) => ({
  237. groupList: business.groupList,
  238. loading: loading.models.business,
  239. shouldUpdate: refresh.business
  240. }))(Business)