index.jsx 3.4 KB

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