material.tsx 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. import React, { forwardRef, Ref, useContext, useEffect, useImperativeHandle, useRef, useState } from "react"
  2. import style from './index.less'
  3. import { Breadcrumb, Button, Card, Checkbox, Dropdown, Empty, message, Modal, Pagination, Radio, Spin, Typography } from "antd"
  4. import { DispatchCloudNew } from "."
  5. import { delMaterialApi, getFolderListApi, getMaterialListApi } from "@/services/adqV3/cloudNew"
  6. import { useAjax } from "@/Hook/useAjax"
  7. import { useSize } from "ahooks"
  8. import './global.less'
  9. import { useModel } from "umi"
  10. import { CheckboxValueType } from "antd/lib/checkbox/Group"
  11. import MoveFile from "./moveFile"
  12. import { ItemType } from "antd/lib/menu/hooks/useItems"
  13. import UploadFile from "./uploadFile"
  14. import UpdateCreate from "./updateCreate"
  15. import { formatSecondsToTime, getVideoImgUrl } from "@/utils/utils"
  16. import { ExclamationCircleOutlined } from "@ant-design/icons"
  17. import UpdateFile from "./updateFile"
  18. import Details from "./details"
  19. import useFileDrop from "@/Hook/useFileDrop"
  20. import UploadsTable from "./uploadsTable"
  21. const { Text } = Typography;
  22. interface Props {
  23. /** 新增文件夹 */
  24. onAddFolder?: () => void
  25. onUpdateFolder?: (data: any) => void
  26. onDelFolder?: (id: number, name: string) => void
  27. }
  28. interface MaterialRef {
  29. folderRefresh: () => void
  30. search: (value: {
  31. searchType: "file" | "folder";
  32. keyword?: string;
  33. }) => void
  34. }
  35. /**
  36. * 素材列表
  37. * @returns
  38. */
  39. const Material = forwardRef(({ onAddFolder, onUpdateFolder, onDelFolder }: Props, ref1: Ref<MaterialRef>) => {
  40. /********************************/
  41. const { initialState } = useModel('@@initialState');
  42. const { breadcrumdData, setSelectedKeys, setBreadcrumdData, setMaterialParams, materialParams, selectedKeys, treeData, folderCreateBy, findParentKeys, loadedKeys, handleUpdateFolder, batchFolderVisible, setBatchFolderVisible, handleType, setHandleType } = useContext(DispatchCloudNew)!;
  43. const ref = useRef<HTMLDivElement>(null);
  44. const size = useSize(ref);
  45. const [folderList, setFolderList] = useState<{ id: number, folderName: string, createBy: number, description?: string }[]>([])
  46. const [rowNum, setRowNum] = useState<number>(0)
  47. const [checkedFolderList, setCheckedFolderList] = useState<CheckboxValueType[]>([])
  48. const [checkFolderAll, setCheckFolderAll] = useState<boolean>(false);
  49. const [indeterminateFolder, setIndeterminateFolder] = useState<boolean>(false);
  50. const [moveVisible, setMoveVisible] = useState<boolean>(false)
  51. const [moveType, setMoveType] = useState<'folder' | 'file'>('folder')
  52. const [batchType, setBatchType] = useState<'folder' | 'file'>()
  53. const [checkedList, setCheckedList] = useState<CheckboxValueType[]>([])
  54. const [uploadVisible, setUploadVisible] = useState<boolean>(false)
  55. const [updateOwnerData, setUpdateOwnerData] = useState<{ visible?: boolean, folderId: number }>({ folderId: 0 })
  56. const [updateFileData, setUpdateFileData] = useState<{ visible?: boolean, initialValues: any }>({ visible: false, initialValues: {} })
  57. const [detailsData, setDetailsData] = useState<{ visible?: boolean, data: any }>({ visible: false, data: {} })
  58. const getFolderList = useAjax((params) => getFolderListApi(params))
  59. const delMaterial = useAjax((params) => delMaterialApi(params))
  60. const getMaterialList = useAjax((params) => getMaterialListApi(params))
  61. /********************************/
  62. useImperativeHandle(ref1, () => ({
  63. // 刷新文件夹
  64. folderRefresh() {
  65. getFolder()
  66. },
  67. search(value) {
  68. setHandleType('file')
  69. setMaterialParams(data => ({ ...data, ...value, pageNum: 1 }))
  70. }
  71. }));
  72. // 根据内容宽度计算列数
  73. useEffect(() => {
  74. if (size?.width) {
  75. let rowNum = Math.floor((size?.width - 26) / 200)
  76. setRowNum(rowNum || 1)
  77. }
  78. }, [size?.width])
  79. useEffect(() => {
  80. cancelSelect()
  81. if (isShowFolder()) {
  82. // 文件夹
  83. getFolder()
  84. } else {
  85. // 文件
  86. getFile()
  87. }
  88. }, [selectedKeys, handleType, materialParams])
  89. /** 获取下级文件夹 */
  90. const getFolder = () => {
  91. let parentId: number | undefined;
  92. if (selectedKeys?.length) {
  93. const parentIdArr = (selectedKeys[0] as string).split('-')
  94. const parentIdArrLength = parentIdArr.length
  95. parentId = Number(parentIdArr[parentIdArrLength - 1])
  96. }
  97. getFolderList.run({ parentId }).then(res => {
  98. setFolderList(() => res || [])
  99. })
  100. }
  101. // 搜索素材
  102. const getFile = () => {
  103. let parentId: number | undefined;
  104. if (selectedKeys?.length) {
  105. const parentIdArr = (selectedKeys[0] as string).split('-')
  106. const parentIdArrLength = parentIdArr.length
  107. parentId = Number(parentIdArr[parentIdArrLength - 1])
  108. }
  109. let params = JSON.parse(JSON.stringify(materialParams))
  110. if (params?.width || params?.height) {
  111. params.sizeQueries = [{ width: params?.width, height: params?.height, relation: '=' }]
  112. delete params?.width
  113. delete params?.height
  114. } else {
  115. delete params?.sizeQueries
  116. }
  117. getMaterialList.run({ ...params, folderId: parentId })
  118. }
  119. // 文件夹选择
  120. const onCheckboxChange = (checkedValues: CheckboxValueType[]) => {
  121. let data: any[] = []
  122. if (batchType === 'folder') {
  123. data = folderList
  124. } else {
  125. data = getMaterialList?.data?.records || []
  126. }
  127. setCheckedFolderList(checkedValues)
  128. setIndeterminateFolder(!!checkedValues.length && checkedValues.length < data.length);
  129. setCheckFolderAll(checkedValues.length === data.length);
  130. };
  131. // 取消选择
  132. const cancelSelect = () => {
  133. setCheckFolderAll(false)
  134. setCheckedFolderList([])
  135. setIndeterminateFolder(false)
  136. setCheckedList([])
  137. }
  138. // 是否管理员
  139. const isAdmin = () => {
  140. return ['999'].includes(initialState?.currentUser?.powerLevel?.toString() || '')
  141. }
  142. // 是否有权限
  143. const isPermission = (createBy: any) => {
  144. return initialState?.currentUser?.userId?.toString() === createBy.toString()
  145. }
  146. // 文件夹更多
  147. const getItems = (item: any) => {
  148. let data: ItemType[] = []
  149. if (isPermission(item.createBy)) {
  150. data.push({ label: '编辑', style: { fontSize: 12 }, key: 'edit', onClick: () => onUpdateFolder?.(item) })
  151. if (!!selectedKeys?.[0]) {
  152. data.push({
  153. label: '移动', style: { fontSize: 12 }, key: 'move', onClick: () => {
  154. setCheckedList([item.id])
  155. setMoveType('folder')
  156. setMoveVisible(true)
  157. }
  158. })
  159. } else if (isAdmin()) {
  160. data.push({
  161. label: '修改文件夹所属人', style: { fontSize: 12 }, key: 'createBy', onClick: () => {
  162. setUpdateOwnerData({ visible: true, folderId: item.id })
  163. }
  164. })
  165. }
  166. data.push({ label: <span style={{ color: 'red', fontSize: 12 }}>删除</span>, key: 'del', onClick: () => onDelFolder?.(item.id, item?.folderName) })
  167. } else {
  168. if (isAdmin() && !selectedKeys?.[0]) {
  169. data.push({
  170. label: '修改文件夹所属人', style: { fontSize: 12 }, key: 'createBy', onClick: () => {
  171. setUpdateOwnerData({ visible: true, folderId: item.id })
  172. }
  173. })
  174. }
  175. }
  176. return data
  177. }
  178. // 删除素材
  179. const delFile = (id: number, name: string) => {
  180. Modal.confirm({
  181. title: <strong>{`删除素材“${name}”`}</strong>,
  182. icon: <ExclamationCircleOutlined />,
  183. content: '是否确定删除该素材',
  184. okText: '确认',
  185. cancelText: '取消',
  186. className: 'modalResetCss',
  187. onOk: () => {
  188. return new Promise((resolve: (value: unknown) => void) => {
  189. delMaterial.run(id).then(res => {
  190. if (res) {
  191. message.success('删除成功');
  192. getMaterialList.refresh()
  193. resolve('')
  194. }
  195. })
  196. })
  197. }
  198. });
  199. }
  200. // 操作素材 更多
  201. const getItemsFile = (item: any) => {
  202. let data: ItemType[] = []
  203. if (isPermission(item.createBy)) {
  204. data.push({
  205. label: <div onClick={(e) => {
  206. e.stopPropagation()
  207. e.preventDefault()
  208. setUpdateFileData({ visible: true, initialValues: item })
  209. }}>编辑</div>, style: { fontSize: 12 }, key: 'edit'
  210. })
  211. if (!!selectedKeys?.[0]) {
  212. data.push({
  213. label: <div onClick={(e) => {
  214. e.stopPropagation()
  215. e.preventDefault()
  216. setCheckedList([item.id])
  217. setMoveType('file')
  218. setMoveVisible(true)
  219. }}>移动</div>, style: { fontSize: 12 }, key: 'move'
  220. })
  221. }
  222. data.push({
  223. label: <div style={{ color: 'red', fontSize: 12 }} onClick={(e) => {
  224. e.stopPropagation()
  225. e.preventDefault()
  226. delFile(item.id, item?.materialName)
  227. }}>删除</div>, key: 'del'
  228. })
  229. }
  230. return data
  231. }
  232. // 是否展示文件夹
  233. const isShowFolder = () => {
  234. return handleType === 'folder'
  235. }
  236. // 获取拖拽的文件
  237. const [fileList, setFileList] = useState<FileList>()
  238. const [uploadsVisible, setUploadsVisible] = useState<boolean>(false)
  239. const { isDragOver, dropAreaProps } = useFileDrop((fileList) => {
  240. console.log('fileList--->', fileList)
  241. setFileList(fileList)
  242. setUploadsVisible(true)
  243. });
  244. return <div className={style.material}>
  245. <div className={style.operates}>
  246. <div className={style.left_bts}>
  247. <Checkbox
  248. onChange={(e) => {
  249. setHandleType(e.target.checked ? 'folder' : 'file')
  250. setMaterialParams({ pageNum: 1, pageSize: 30 })
  251. setBatchFolderVisible(false)
  252. cancelSelect()
  253. }}
  254. checked={handleType === 'folder'}
  255. ><span style={{ fontSize: 12 }}>是否操作文件夹</span></Checkbox>
  256. {handleType === 'folder' && <Button onClick={() => onAddFolder?.()} disabled={folderCreateBy ? !isPermission(folderCreateBy) : false}>新建文件夹</Button>}
  257. {(!selectedKeys?.[0] && handleType === 'folder') && <>
  258. <Button type="primary" disabled={folderCreateBy ? !isPermission(folderCreateBy) : false} onClick={() => setUploadVisible(true)}>上传素材</Button>
  259. </>}
  260. {handleType === 'folder' ? <>
  261. {!!selectedKeys?.[0] && <Button onClick={() => { setBatchFolderVisible(true); setBatchType('folder') }} disabled={folderCreateBy ? !isPermission(folderCreateBy) : false}>批量操作文件夹</Button>}
  262. </> : <>
  263. <Button type="primary" disabled={folderCreateBy ? !isPermission(folderCreateBy) : false} onClick={() => setUploadVisible(true)}>上传素材</Button>
  264. <Button onClick={() => { setBatchFolderVisible(true); setBatchType('file') }} disabled={folderCreateBy ? !isPermission(folderCreateBy) : false}>批量操作素材</Button>
  265. </>}
  266. </div>
  267. <div className={style.left_bts}>
  268. <Button type="link" loading={getMaterialList.loading} onClick={() => {
  269. getMaterialList.refresh()
  270. }}>刷新</Button>
  271. </div>
  272. </div>
  273. {batchFolderVisible ? <div className={style.operates}>
  274. <div className={style.left_bts}>
  275. <Checkbox
  276. onChange={(e) => {
  277. setCheckedFolderList(
  278. e.target.checked ? batchType === 'folder' ?
  279. folderList.map(item => item.id) :
  280. getMaterialList?.data?.records?.filter((item: { createBy: any }) => isPermission(item.createBy)).map((item: { id: any }) => item.id) :
  281. []
  282. )
  283. setIndeterminateFolder(false)
  284. setCheckFolderAll(e.target.checked)
  285. }}
  286. disabled={batchType === 'folder' ? folderList?.length ? false : true : !getMaterialList?.data?.records?.some((item: { createBy: any }) => isPermission(item.createBy))}
  287. indeterminate={indeterminateFolder}
  288. checked={checkFolderAll}
  289. >全选</Checkbox>
  290. <span style={{ color: '#1890FF' }}>已选{checkedFolderList?.length || 0}个{batchType === 'file' ? '素材' : '文件夹'}</span>
  291. </div>
  292. <div className={style.left_bts}>
  293. <Button disabled={checkedFolderList?.length === 0} onClick={() => {
  294. setCheckedList(checkedFolderList)
  295. setMoveVisible(true)
  296. setMoveType(batchType as any)
  297. }}>{batchType === 'folder' ? '移动文件夹' : '移动素材'}</Button>
  298. <Button type="primary" onClick={() => {
  299. setBatchFolderVisible(false)
  300. }}>完成</Button>
  301. </div>
  302. </div> : (materialParams?.materialName || materialParams?.materialType || (materialParams?.designerIds && materialParams?.designerIds?.length > 0) || materialParams?.width || materialParams?.height) ? <div className={style.operates}>
  303. <span>搜索「素材」
  304. {materialParams?.materialName && <span style={{ fontSize: 12 }}>关键词【{materialParams.materialName}】</span>}
  305. {(materialParams?.designerIds && materialParams?.designerIds?.length > 0) && <span style={{ fontSize: 12 }}>设计师ID【{materialParams.designerIds.join(',')}】</span>}
  306. {materialParams?.materialType && <span style={{ fontSize: 12 }}>素材类型【{materialParams.materialType === 'video' ? '视频' : '图片'}】</span>}
  307. {materialParams?.width && <span style={{ fontSize: 12 }}>素材宽【{materialParams.width}】</span>}
  308. {materialParams?.height && <span style={{ fontSize: 12 }}>素材高【{materialParams.height}】</span>}
  309. </span>
  310. </div> : <div className={style.operates}>
  311. <Breadcrumb>
  312. {breadcrumdData.map((item, index) => <Breadcrumb.Item key={item.key}>
  313. {breadcrumdData.length !== index + 1 ? <a
  314. style={{ color: '#1890ff' }}
  315. onClick={() => {
  316. setBreadcrumdData(data => data.splice(0, index + 1))
  317. setSelectedKeys(item.currentKey === '0' ? [] : [item.currentKey])
  318. }}
  319. >{item.label}</a> : item.label}
  320. </Breadcrumb.Item>)}
  321. </Breadcrumb>
  322. </div>}
  323. <div className={`${style.content} content_global`}>
  324. <Spin spinning={getFolderList.loading || getMaterialList.loading}>
  325. <div className={style.content_scroll} ref={ref} {...dropAreaProps}>
  326. {isDragOver && <div className={`${style.placeholder} ${isDragOver ? style.dragOver : ''}`}><span>拖动文件到这里</span></div>}
  327. {(isShowFolder() && folderList.length > 0) || (!isShowFolder() && getMaterialList?.data?.records?.length > 0) ? <Checkbox.Group value={checkedFolderList} style={{ width: '100%' }} onChange={onCheckboxChange}>
  328. <div className={style.content_scroll_div}>
  329. {isShowFolder() ? folderList.map((item) => <div key={item.id} className={style.content_row} style={{ width: rowNum ? (1 / rowNum * 100) + '%' : 200 }}>
  330. <Card
  331. hoverable
  332. bodyStyle={{ padding: 0 }}
  333. className={`${style.content_col}`}
  334. cover={<div className={style.content_cover} style={{ height: 120 }}>
  335. {batchFolderVisible && <div className={style.checkbox}><Checkbox value={item.id} disabled={!isPermission(item.createBy)} /></div>}
  336. <img src={require('../../../../../public/file.png')} height={'100%'} alt="" />
  337. </div>}
  338. onDoubleClick={() => {
  339. if (!batchFolderVisible) {
  340. let newExpandedKeys = '0-' + item.id
  341. if (selectedKeys?.[0]) {
  342. newExpandedKeys = selectedKeys[0] + '-' + item.id
  343. }
  344. findParentKeys(newExpandedKeys, treeData)
  345. setSelectedKeys([newExpandedKeys])
  346. // 判断是否加载了下级文件 加载了 就不更新
  347. if (!loadedKeys.includes(newExpandedKeys))
  348. handleUpdateFolder(newExpandedKeys)
  349. }
  350. }}
  351. >
  352. <div className={style.body}>
  353. <Text ellipsis>{item?.folderName}</Text>
  354. </div>
  355. <div className={style.actions}>
  356. <div style={{ height: 22 }}></div>
  357. {isPermission(item.createBy) || (!selectedKeys?.[0] && isAdmin()) ? <Dropdown menu={{
  358. items: getItems(item)
  359. }}>
  360. <a onClick={e => e.preventDefault()} style={{ fontSize: 11 }}>更多</a>
  361. </Dropdown> : <a style={{ fontSize: 11 }}>无权限操作</a>}
  362. </div>
  363. </Card>
  364. </div>) : getMaterialList?.data?.records.map((item: any) => <div key={item.id} className={style.content_row} style={{ width: rowNum ? (1 / rowNum * 100) + '%' : 200 }}>
  365. <Card
  366. hoverable
  367. bodyStyle={{ padding: 0 }}
  368. className={`${style.content_col}`}
  369. cover={<div style={{ height: 120, padding: 0 }} className={style.content_cover}>
  370. {batchFolderVisible && <div className={style.checkbox}><Checkbox value={item.id} disabled={!isPermission(item.createBy)} /></div>}
  371. {item.materialType === 'video' && <div className={style.playr}>
  372. <img src={require('../../../../../public/image/play.png')} alt="" />
  373. </div>}
  374. <div className={style.file_info}>
  375. <div>{item.width}*{item.height}</div>
  376. {item.materialType === 'video' && <div>{formatSecondsToTime(Math.floor(item.videoDuration))}</div>}
  377. </div>
  378. <img src={item.materialType === 'image' ? item.ossUrl : getVideoImgUrl(item.ossUrl)} className={style.coverImg} alt="" />
  379. </div>}
  380. onClick={() => { setDetailsData({ visible: true, data: item }) }}
  381. >
  382. <div className={style.body}>
  383. <div className={style.title}><Text ellipsis>{item?.materialName}</Text></div>
  384. <a className={style.detailBt}>详情</a>
  385. </div>
  386. <div className={style.actions}>
  387. <div style={{ height: 22 }}></div>
  388. {isPermission(item.createBy) ? <Dropdown
  389. menu={{
  390. items: getItemsFile(item)
  391. }}
  392. >
  393. <a onClick={e => { e.preventDefault(); e.stopPropagation() }} style={{ fontSize: 11 }}>更多</a>
  394. </Dropdown> : <a style={{ fontSize: 11 }}>无权限操作</a>}
  395. </div>
  396. </Card>
  397. </div>)}
  398. </div>
  399. </Checkbox.Group> : <div style={{ height: '100%', width: '100%', alignContent: 'center' }}><Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /></div>}
  400. </div>
  401. </Spin>
  402. </div>
  403. {handleType === 'file' && <div className={style.fotter}>
  404. <Pagination
  405. size="small"
  406. total={getMaterialList?.data?.totalRow || 0}
  407. showSizeChanger
  408. showQuickJumper
  409. pageSize={getMaterialList?.data?.pageSize || 30}
  410. current={getMaterialList?.data?.pageNumber || 1}
  411. onChange={(page: number, pageSize: number) => {
  412. setMaterialParams({ ...materialParams, pageNum: page, pageSize })
  413. }}
  414. />
  415. </div>}
  416. {/* 移动文件 素材 */}
  417. {moveVisible && <MoveFile
  418. moveType={moveType}
  419. checkedList={checkedList}
  420. userId={initialState?.currentUser?.userId?.toString() || ''}
  421. visible={moveVisible}
  422. onClose={() => {
  423. setMoveVisible(false)
  424. cancelSelect()
  425. }}
  426. onChange={(selectedKey: string) => {
  427. getFolder()
  428. setMoveVisible(false)
  429. if (moveType === 'folder') {
  430. handleUpdateFolder(selectedKeys[0] as string)
  431. if (loadedKeys.includes(selectedKey)) {
  432. handleUpdateFolder(selectedKey)
  433. }
  434. } else {
  435. getMaterialList.refresh()
  436. }
  437. cancelSelect()
  438. setBatchFolderVisible(false)
  439. }}
  440. />}
  441. {/* 上传文件 */}
  442. {uploadVisible && <UploadFile
  443. folderId={breadcrumdData[breadcrumdData.length - 1].key}
  444. userId={(initialState?.currentUser?.userId || 0) as number}
  445. visible={uploadVisible}
  446. onChange={() => {
  447. setUploadVisible(false)
  448. getMaterialList.refresh()
  449. }}
  450. onClose={() => {
  451. setUploadVisible(false)
  452. }}
  453. />}
  454. {/* 修改所属人 */}
  455. {updateOwnerData.visible && <UpdateCreate
  456. {...updateOwnerData}
  457. onClose={() => {
  458. setUpdateOwnerData({ visible: false, folderId: 0 })
  459. }}
  460. onChange={() => {
  461. getFolder()
  462. setUpdateOwnerData({ visible: false, folderId: 0 })
  463. }}
  464. />}
  465. {/* 修改素材 */}
  466. {updateFileData?.visible && <UpdateFile
  467. {...updateFileData}
  468. onClose={() => {
  469. setUpdateFileData({ visible: false, initialValues: {} })
  470. }}
  471. onChange={() => {
  472. getMaterialList.refresh()
  473. setUpdateFileData({ visible: false, initialValues: {} })
  474. }}
  475. />}
  476. {/* 素材详情 */}
  477. {detailsData?.visible && <Details
  478. {...detailsData}
  479. onClose={() => {
  480. setDetailsData({ visible: false, data: {} })
  481. }}
  482. onChange={() => {
  483. getMaterialList.refresh()
  484. }}
  485. />}
  486. {/* 拖动上传 */}
  487. {uploadsVisible && <UploadsTable
  488. folderId={breadcrumdData[breadcrumdData.length - 1].key}
  489. userId={(initialState?.currentUser?.userId || 0) as number}
  490. visible={uploadsVisible}
  491. fileList={fileList}
  492. isPermission={!!(folderCreateBy && isPermission(folderCreateBy))}
  493. onClose={() => {
  494. setUploadsVisible(false)
  495. setFileList(undefined)
  496. }}
  497. onChange={() => {
  498. setUploadsVisible(false)
  499. setFileList(undefined)
  500. getMaterialList.refresh()
  501. }}
  502. />}
  503. </div>
  504. })
  505. export default React.memo(Material)