LowerList.tsx 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import { Button, Popconfirm, Tabs } from 'antd'
  2. import React, { useMemo } from 'react'
  3. import { dayjsFormat } from '@/utils/utils'
  4. import classNames from 'classnames'
  5. import { isDevMode } from '@/utils/env'
  6. import { VList } from 'virtuallist-antd'
  7. import consts from '@/consts'
  8. import type { ProColumns } from '@ant-design/pro-table'
  9. import ProTable from '@ant-design/pro-table'
  10. import {
  11. updateCustomerService,
  12. delCustomerService,
  13. updateClientService,
  14. delClientService
  15. } from '@/services/customer'
  16. import { useModal } from '@/components/ModalStore'
  17. import { useDispatch, useRequest } from '@umijs/max'
  18. const { TabPane } = Tabs
  19. export enum Servicelog {
  20. /** 上门服务 */
  21. VISIT = '1',
  22. /** 电话拜访 */
  23. CALL = '2',
  24. /** 其他事项 */
  25. OTHER = '3',
  26. /** 在线服务 */
  27. ONLINE = '4'
  28. }
  29. export enum ServiceLogType {
  30. CLIENT,
  31. COMPANY
  32. }
  33. export const servicelogEnum = {
  34. [Servicelog.VISIT]: {
  35. title: '上门服务',
  36. bg: 'bg-hex-886ab5',
  37. text: 'text-hex-886ab5',
  38. border: 'border-hex-886ab5'
  39. },
  40. [Servicelog.CALL]: {
  41. title: '电话拜访',
  42. bg: 'bg-hex-246daf',
  43. text: 'text-hex-246daf',
  44. border: 'border-hex-246daf'
  45. },
  46. [Servicelog.OTHER]: {
  47. title: '其他事项',
  48. bg: 'bg-hex-1ca081',
  49. text: 'text-hex-1ca081',
  50. border: 'border-hex-1ca081'
  51. },
  52. [Servicelog.ONLINE]: {
  53. title: '在线服务',
  54. bg: 'bg-hex-b8795e',
  55. text: 'text-hex-b8795e ',
  56. border: 'border-hex-b8795e'
  57. }
  58. }
  59. type ClientLowerListProps = {
  60. logList: {
  61. log: any[]
  62. }
  63. serviceList: API.ServiceLogItem[]
  64. updatePayload: { main: string; target: string }
  65. }
  66. type ServiceLogItemProps = {
  67. item: API.ServiceLogItem
  68. logType: ServiceLogType
  69. updatePayload: { main: string; target: string }
  70. }
  71. export const ServiceLogItem: React.FC<ServiceLogItemProps> = ({ item, logType, updatePayload }) => {
  72. const dispatchModal = useModal()
  73. const dispatch = useDispatch()
  74. const { run: truUpdate } = useRequest(
  75. logType === ServiceLogType.COMPANY ? updateCustomerService : updateClientService,
  76. {
  77. manual: true,
  78. onSuccess: () => {
  79. dispatch({
  80. type: 'refresh/commitAction',
  81. payload: updatePayload
  82. })
  83. }
  84. }
  85. )
  86. const { run: truDel } = useRequest(
  87. logType === ServiceLogType.COMPANY ? delCustomerService : delClientService,
  88. {
  89. manual: true,
  90. onSuccess: () => {
  91. dispatch({
  92. type: 'refresh/commitAction',
  93. payload: updatePayload
  94. })
  95. }
  96. }
  97. )
  98. const handleOnEdit = async (defaultValues: API.ServiceLogItem) => {
  99. dispatchModal('M_RECORD_ADD', { defaultValues, onConfirm: truUpdate })
  100. }
  101. return (
  102. <div
  103. className={classNames(
  104. 'w-full rounded border-l-2px bg-opacity-6',
  105. servicelogEnum[item.status]?.bg,
  106. servicelogEnum[item.status]?.border
  107. )}>
  108. <div className="p-3 flex flex-col">
  109. <div className="flex justify-between">
  110. <div className="flex">
  111. <div
  112. className="rounded-1/2 w-8 h-8"
  113. style={{
  114. backgroundImage: `url(${
  115. (isDevMode() ? 'http://cld2qa.com' : 'localhost') + (item.avatar ?? consts.DEFAULT_AVATAR)
  116. })`,
  117. backgroundSize: 'cover'
  118. }}
  119. />
  120. <div className="flex flex-col items-center ml-2">
  121. <div className="text-sm font-medium text-opacity-80 text-black">{item.staffName}</div>
  122. <div className="text-xs text-opacity-40 text-black h-4">
  123. {dayjsFormat(item.createTime, 'HH:mm:ss')}
  124. </div>
  125. </div>
  126. </div>
  127. <div className="flex flex-nowrap">
  128. <div className={classNames(servicelogEnum[item.status]?.text, 'font-medium text-sm')}>
  129. {servicelogEnum[item.status]?.title}
  130. </div>
  131. <div
  132. className={classNames(
  133. 'ml-1 text-xs bg-opacity-16 rounded-sm h-5 leading-5 px-1',
  134. servicelogEnum[item.status]?.text,
  135. servicelogEnum[item.status]?.bg
  136. )}>
  137. {dayjsFormat(item.date, 'YYYY-MM-DD')}
  138. </div>
  139. </div>
  140. </div>
  141. <div className="bg-white bg-opacity-80 rounded-sm text-black text-opacity-60 text-sm mt-3 p-2">
  142. {item.mark}
  143. </div>
  144. {item.isOperation ? (
  145. <div className="mt-2">
  146. <Button size="small" onClick={() => handleOnEdit(item)}>
  147. 编辑
  148. </Button>
  149. <Popconfirm title="确认删除该服务记录吗?" onConfirm={() => truDel({ id: item.id })}>
  150. <Button size="small" danger className="ml-1">
  151. 删除
  152. </Button>
  153. </Popconfirm>
  154. </div>
  155. ) : null}
  156. </div>
  157. </div>
  158. )
  159. }
  160. const ClientLowerList: React.FC<ClientLowerListProps> = ({
  161. logList: { log: logs = [] },
  162. serviceList,
  163. updatePayload
  164. }) => {
  165. const tableHeight = (document.body.clientHeight - 124 - 78) / 2
  166. const columns: ProColumns<API.LogItem>[] = [
  167. {
  168. title: '日期',
  169. dataIndex: 'createTime',
  170. key: 'createTime',
  171. width: 160
  172. },
  173. {
  174. title: '操作人',
  175. dataIndex: 'operatorName',
  176. key: 'operatorName',
  177. ellipsis: true,
  178. width: 115
  179. },
  180. {
  181. title: '操作',
  182. dataIndex: 'operationType',
  183. key: 'operationType',
  184. ellipsis: true,
  185. width: 120
  186. },
  187. {
  188. title: '操作内容',
  189. dataIndex: 'content',
  190. key: 'content',
  191. ellipsis: true
  192. }
  193. ]
  194. const vList = useMemo(() => {
  195. return VList({
  196. height: tableHeight,
  197. vid: 'client_log_list'
  198. })
  199. }, [])
  200. return (
  201. <div>
  202. <div className="pl-4">
  203. <Tabs>
  204. <TabPane tab="客户服务记录" key="客户服务记录">
  205. <div className="sheet-panel-record">
  206. {serviceList.map(item => (
  207. <div className="mb-3" key={item.id}>
  208. <ServiceLogItem item={item} logType={ServiceLogType.CLIENT} updatePayload={updatePayload} />
  209. </div>
  210. ))}
  211. </div>
  212. </TabPane>
  213. <TabPane tab="日志" key="日志">
  214. <div className="sheet-panel-record">
  215. <ProTable<API.LogItem>
  216. search={false}
  217. toolBarRender={false}
  218. rowKey="id"
  219. size="small"
  220. columns={columns}
  221. dataSource={logs}
  222. pagination={false}
  223. scroll={{ y: tableHeight }}
  224. components={vList}
  225. />
  226. </div>
  227. </TabPane>
  228. </Tabs>
  229. </div>
  230. </div>
  231. )
  232. }
  233. export default ClientLowerList