|
@@ -1,8 +1,9 @@
|
|
|
import React, { useState, useRef, useEffect } from 'react'
|
|
|
import { useRequest, request } from 'umi'
|
|
|
-import { Button, Input, message, Modal } from 'antd'
|
|
|
+import { Button, Input, message, Modal, Spin } from 'antd'
|
|
|
import { fetchStaffList } from '@/services/user/api'
|
|
|
-import { LoadingOutlined, MoreOutlined } from '@ant-design/icons'
|
|
|
+import { useDebounceFn } from 'ahooks'
|
|
|
+import consts from '@/utils/consts'
|
|
|
|
|
|
interface ConnectModalProps {
|
|
|
postUrl: string
|
|
@@ -11,6 +12,7 @@ interface ConnectModalProps {
|
|
|
dataId?: string
|
|
|
onReload?: () => void
|
|
|
show?: boolean
|
|
|
+ closeAfterSelect?: boolean
|
|
|
onShowChange?: (isShow: boolean) => void
|
|
|
}
|
|
|
const ConnectModal: React.FC<ConnectModalProps> = ({
|
|
@@ -20,11 +22,20 @@ const ConnectModal: React.FC<ConnectModalProps> = ({
|
|
|
show,
|
|
|
onShowChange,
|
|
|
postUrl,
|
|
|
+ closeAfterSelect = true,
|
|
|
showButton = true
|
|
|
}) => {
|
|
|
- const containerRef = useRef<HTMLDivElement>(null)
|
|
|
+ const scrollRef = useRef<HTMLDivElement>(null)
|
|
|
const [visible, setVisible] = useState(false)
|
|
|
- const [searchVal, setSearchVal] = useState('')
|
|
|
+ const [state, setState] = useState({
|
|
|
+ laoding: true,
|
|
|
+ list: [],
|
|
|
+ searchVal: '',
|
|
|
+ current: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ total: 0,
|
|
|
+ noMore: false
|
|
|
+ })
|
|
|
|
|
|
const { run: tryConnectStaff } = useRequest(
|
|
|
(params: API.AddRoleStaffCommonParams) =>
|
|
@@ -36,9 +47,6 @@ const ConnectModal: React.FC<ConnectModalProps> = ({
|
|
|
manual: true,
|
|
|
onSuccess: async () => {
|
|
|
message.success('关联成功')
|
|
|
- if (!show) {
|
|
|
- setVisible(false)
|
|
|
- }
|
|
|
await onReload()
|
|
|
},
|
|
|
onError: e => {
|
|
@@ -47,48 +55,48 @@ const ConnectModal: React.FC<ConnectModalProps> = ({
|
|
|
}
|
|
|
)
|
|
|
|
|
|
- const {
|
|
|
- run: tryQueryStaffList,
|
|
|
- data,
|
|
|
- noMore,
|
|
|
- loadMore,
|
|
|
- loadingMore
|
|
|
- } = useRequest(
|
|
|
- result =>
|
|
|
- fetchStaffList({
|
|
|
- current: result?.list.length / 10 + 1 || 1,
|
|
|
- pageSize: 10,
|
|
|
- search: searchVal
|
|
|
- }),
|
|
|
- {
|
|
|
- manual: true,
|
|
|
- loadMore: true,
|
|
|
- ref: containerRef,
|
|
|
- isNoMore: (res: API.BasicFetchResult<API.StaffItem>) => res.list.length >= res.total,
|
|
|
- refreshDeps: [searchVal]
|
|
|
+ const initData = async params => {
|
|
|
+ const { data: { list, total } = { list: [], total: 0 }, code = -1 } = await fetchStaffList(
|
|
|
+ params
|
|
|
+ )
|
|
|
+ if (code === consts.RET_CODE.SUCCESS) {
|
|
|
+ if (params?.current === 1) {
|
|
|
+ scrollRef.current?.scrollTo({ top: 0 })
|
|
|
+ // 请求的是第一页或者搜索框
|
|
|
+ setState({ ...state, list, total, laoding: false, searchVal: params?.search })
|
|
|
+ } else {
|
|
|
+ setState({
|
|
|
+ ...state,
|
|
|
+ list: state.list.concat(list),
|
|
|
+ total,
|
|
|
+ searchVal: params?.search,
|
|
|
+ laoding: false,
|
|
|
+ current: params?.current || 1
|
|
|
+ })
|
|
|
+ }
|
|
|
}
|
|
|
- )
|
|
|
+ }
|
|
|
|
|
|
- const handleSearch = (value: string) => {
|
|
|
- setSearchVal(value)
|
|
|
- setTimeout(() => {
|
|
|
- tryQueryStaffList()
|
|
|
- }, 250)
|
|
|
+ const onChange = e => {
|
|
|
+ // const { value = '' } = e.target || e.currentTarget
|
|
|
+ initData({ search: e, current: 1, pageSize: state.pageSize })
|
|
|
}
|
|
|
|
|
|
- const { list = [] }: { list: API.StaffItem[] } = data || {}
|
|
|
+ const { run: handleInputChange } = useDebounceFn(onChange)
|
|
|
+
|
|
|
useEffect(() => {
|
|
|
if (show || visible) {
|
|
|
- tryQueryStaffList()
|
|
|
+ initData({ current: 1, pageSize: 10 })
|
|
|
}
|
|
|
}, [show, visible])
|
|
|
|
|
|
const handleOnCancel = () => {
|
|
|
- if (onShowChange !== undefined) {
|
|
|
+ // 不可关闭
|
|
|
+ if (onShowChange) {
|
|
|
onShowChange(false)
|
|
|
- } else {
|
|
|
- setVisible(false)
|
|
|
+ return
|
|
|
}
|
|
|
+ setVisible(false)
|
|
|
}
|
|
|
|
|
|
const itemSelectHandler = async (staffId: string) => {
|
|
@@ -97,8 +105,36 @@ const ConnectModal: React.FC<ConnectModalProps> = ({
|
|
|
params.id = dataId
|
|
|
}
|
|
|
await tryConnectStaff(params)
|
|
|
+ if (!closeAfterSelect) {
|
|
|
+ const nList = state.list.map(item => {
|
|
|
+ const nItem = { ...item, disable: false }
|
|
|
+ if (item.id === staffId) {
|
|
|
+ nItem.disable = true
|
|
|
+ }
|
|
|
+ return nItem
|
|
|
+ })
|
|
|
+ setState({ ...state, list: nList })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
handleOnCancel()
|
|
|
}
|
|
|
+
|
|
|
+ const handleListScroll = () => {
|
|
|
+ // 未滚动到底部
|
|
|
+ if (
|
|
|
+ scrollRef.current.scrollHeight - scrollRef.current.clientHeight <=
|
|
|
+ scrollRef.current.scrollTop
|
|
|
+ ) {
|
|
|
+ // 已到底部
|
|
|
+ if (state.current * state.pageSize > state.total) {
|
|
|
+ setState({ ...state, noMore: true })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ initData({ current: state.current + 1, pageSize: state.pageSize, search: state.searchVal })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
return (
|
|
|
<>
|
|
|
{showButton && (
|
|
@@ -111,32 +147,44 @@ const ConnectModal: React.FC<ConnectModalProps> = ({
|
|
|
onCancel={handleOnCancel}
|
|
|
getContainer={false}
|
|
|
width="60vw"
|
|
|
+ footer={null}
|
|
|
title={
|
|
|
<Input.Search
|
|
|
placeholder="搜索员工(姓名)"
|
|
|
- onSearch={value => handleSearch(value)}
|
|
|
- onPressEnter={e => handleSearch(e.currentTarget.value)}
|
|
|
+ onSearch={value => handleInputChange(value)}
|
|
|
+ onPressEnter={e => handleInputChange(e.currentTarget.value)}
|
|
|
style={{ width: '95%' }}
|
|
|
allowClear={true}
|
|
|
/>
|
|
|
}>
|
|
|
- <div ref={containerRef} className="h-60vh overflow-y-auto overflow-x-hidden">
|
|
|
- {list.map(item => (
|
|
|
- <div className="group-item-card" key={item.id}>
|
|
|
- <div className="w-4/3 flex justify-between">
|
|
|
- <span className="w-1/5">{item.username}</span>
|
|
|
- <span className="w-2/5">{item.phone}</span>
|
|
|
- <span className="w-1/5">{item.position}</span>
|
|
|
- <span className="w-1/5">{item.category}</span>
|
|
|
- </div>
|
|
|
- <div className="w-1/4 flex justify-end">
|
|
|
- <span className="btn-outline" onClick={() => itemSelectHandler(item.id)}>
|
|
|
- 选择ta
|
|
|
- </span>
|
|
|
+ <div
|
|
|
+ ref={scrollRef}
|
|
|
+ onScroll={handleListScroll}
|
|
|
+ className="h-60vh overflow-y-auto overflow-x-hidden">
|
|
|
+ <Spin spinning={state.laoding}>
|
|
|
+ {state.list.map(item => (
|
|
|
+ <div className="group-item-card" key={item.id}>
|
|
|
+ <div className="w-4/3 flex justify-between">
|
|
|
+ <span className="w-1/5">{item.username}</span>
|
|
|
+ <span className="w-2/5">{item.phone}</span>
|
|
|
+ <span className="w-1/5">{item.position}</span>
|
|
|
+ <span className="w-1/5">{item.category}</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="w-1/4 flex justify-end">
|
|
|
+ {item.disable ? (
|
|
|
+ <span className="text-xs">已选择</span>
|
|
|
+ ) : (
|
|
|
+ <span className="btn-outline" onClick={() => itemSelectHandler(item.id)}>
|
|
|
+ 选择ta
|
|
|
+ </span>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- ))}
|
|
|
- {noMore && <div className="text-center text-gray-400">已到底部</div>}
|
|
|
+ ))}
|
|
|
+ </Spin>
|
|
|
+ {state.noMore && <div className="text-center text-gray-400 mt-2">已到底部</div>}
|
|
|
+ {/* {noMore && <div className="text-center text-gray-400">已到底部</div>}
|
|
|
{!noMore && (
|
|
|
<div className="flex justify-center mt-3 cursor-pointer">
|
|
|
{loadingMore ? (
|
|
@@ -145,7 +193,7 @@ const ConnectModal: React.FC<ConnectModalProps> = ({
|
|
|
<MoreOutlined rotate={90} style={{ fontSize: 24 }} onClick={loadMore} />
|
|
|
)}
|
|
|
</div>
|
|
|
- )}
|
|
|
+ )} */}
|
|
|
</div>
|
|
|
</Modal>
|
|
|
</>
|