index.jsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import React, { useState, useEffect, useRef } from 'react'
  2. import { Input, Button, Spin, Modal } from 'antd'
  3. import consts from '@/basic/consts'
  4. import { useDebounceFn } from 'ahooks'
  5. import { SearchOutlined } from '@ant-design/icons'
  6. import { queryStaff, apiChangeSupervisor } from '@/services/staff'
  7. import styles from '@/pages/Customer/Company/components/ConnectCompany/index.less'
  8. const StaffModal = ({ visible, onCancel, id, onSelect, preUrl }) => {
  9. const scrollRef = useRef()
  10. const [state, setState] = useState({
  11. loading: true,
  12. list: [],
  13. current: 1,
  14. pageSize: 10,
  15. noMore: false,
  16. total: 0
  17. })
  18. const initData = async params => {
  19. const { data: { list, total } = { list: [], total: 0 }, code = -1 } = await queryStaff({
  20. ...params,
  21. waiver: true
  22. })
  23. if (code === consts.RET_CODE.SUCCESS) {
  24. if (params?.current === 1) {
  25. scrollRef.current?.scrollTo({ top: 0 })
  26. // 请求的是第一页
  27. setState({ ...state, list, total, loading: false, searchVal: params?.search })
  28. } else {
  29. setState({
  30. ...state,
  31. list: state.list.concat(list),
  32. total,
  33. searchVal: params?.search,
  34. loading: false,
  35. current: params?.current || 1
  36. })
  37. }
  38. }
  39. }
  40. useEffect(() => {
  41. initData({ current: 1, pageSize: 10 })
  42. }, [])
  43. const onChange = e => {
  44. const { value = '' } = e.target || e.currentTarget
  45. initData({ search: value, current: 1, pageSize: state.pageSize })
  46. }
  47. const { run: handleInputChange } = useDebounceFn(onChange)
  48. // 关联上司
  49. const connectStaff = async dataId => {
  50. const { code = -1 } = await apiChangeSupervisor(preUrl, { id, dataId })
  51. if (code === consts.RET_CODE.SUCCESS) {
  52. onSelect()
  53. setTimeout(() => {
  54. onCancel()
  55. }, 80)
  56. }
  57. }
  58. const handleListScroll = () => {
  59. // 未滚动到底部
  60. if (scrollRef.current.scrollHeight - scrollRef.current.clientHeight <= scrollRef.current.scrollTop) {
  61. // 已到底部
  62. if (state.current * state.pageSize > state.total) {
  63. setState({ ...state, noMore: true })
  64. return
  65. }
  66. state.current * state.pageSize < state.total &&
  67. initData({ current: state.current + 1, pageSize: state.pageSize, search: state.searchVal })
  68. }
  69. }
  70. return (
  71. <Modal
  72. visible={visible}
  73. onCancel={onCancel}
  74. width="43vw"
  75. getContainer={() => document.getElementById('root')}
  76. title={
  77. <Input
  78. prefix={<SearchOutlined />}
  79. className={styles.inputSearch}
  80. placeholder="输入员工名称搜索"
  81. onChange={handleInputChange}
  82. />
  83. }
  84. footer={false}>
  85. <div className={styles.modalContent} ref={scrollRef} onScroll={handleListScroll} style={{ paddingBottom: 0 }}>
  86. <Spin spinning={state.loading}>
  87. {state.list.map(item => (
  88. <div key={item.id} className={styles.card}>
  89. <span className="w-1/6">{item.username}</span>
  90. <span className="w-1/6">{item.departmentName}</span>
  91. <span className="w-1/6">{item.position}</span>
  92. <span className="w-1/2 flex justify-between">
  93. <span>{item.emergencyContacts}</span>
  94. <Button type="primary" size="small" onClick={() => connectStaff(item.id)}>
  95. 关联
  96. </Button>
  97. </span>
  98. </div>
  99. ))}
  100. </Spin>
  101. {state.noMore && <div className="text-center text-gray-400 my-4">已到底部</div>}
  102. </div>
  103. </Modal>
  104. )
  105. }
  106. export default StaffModal