index.tsx 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. import useCopy from "@/Hook/useCopy"
  2. import React, { useCallback, useEffect, useState } from "react"
  3. import { Carousel, Image, message, Pagination, Popconfirm, Spin } from 'antd'
  4. import style from './index.less'
  5. import FileModal from './components/fileModal'
  6. import { useModel } from "umi"
  7. import ImgModal from "./components/imgModal"
  8. import TreeBox from "./components/tree"
  9. import SortModal from "./components/fileModal/sortModal"
  10. import { EyeOutlined } from "@ant-design/icons"
  11. import ImgsModal from "./components/imgsModal"
  12. import MoveTo from "./components/moveTo"
  13. import VideoNews from "@/pages/launchSystemNew/components/newsModal/videoNews"
  14. import { getVideoImgUrl } from "@/utils/utils"
  15. import useFileDrop from "@/Hook/useFileDrop"
  16. import { RcFile } from "antd/lib/upload"
  17. import UploadsTable from "./components/uploadsTable"
  18. interface News {
  19. id: number,
  20. sysMediaId: number,
  21. sortIndex: number,
  22. title: string,
  23. thumbUrl: string,
  24. author: string,
  25. digest: string,
  26. showCoverPic: boolean,
  27. content: string,//内容只在调取详情时获取
  28. contentSourceUrl: string,//文章地址
  29. needOpenComment: boolean,
  30. onlyFansCanComment: boolean
  31. }
  32. interface Item {
  33. id: number,
  34. folder: boolean,//是否是文件夹
  35. mediaType: 'VIDEO' | 'IMG' | 'PAGE',//类型
  36. number: string,//编号
  37. title: string,//名称
  38. url: string,//链接
  39. belongType: string,//所属类型
  40. createTime: string,//创建时间
  41. description: string,//k图文描述
  42. news?: News[]//图文内容
  43. knewsThumbUrl: string, // 图片链接
  44. knewsThumbId: number,//本地图片ID
  45. knewsThumbInfo: any,//k客服详情
  46. videoTitle: string,//视频标题
  47. width: number, // 宽
  48. height: number, // 高
  49. pageSpecsList?: any[],
  50. }
  51. interface Props {
  52. isAll?: boolean,//是否允许全选默认开启
  53. height?: any,//当使用为弹窗组件时设置高度以免太高
  54. noFile?: boolean,//是否禁止选择文件夹
  55. setPage?: (type: 0 | 1 | 2 | 3, data?: any) => void, // 0 创建 1 查看 2 复制
  56. isBack?: boolean, // 是否需要回填
  57. }
  58. function FlieBox(props: Props) {
  59. const { isAll = true, height, noFile = false, setPage, isBack = false } = props
  60. const { state, set, dels, list, get, onFile, allFile, delPupOn, delPupOff, changeClickFile, editFile, fileClick, treeClick, pathClick, getList, edit_media_folder, get_folder_tree } = useModel(isAll ? 'useLaunchAdq.useBdMedia' : 'useLaunchAdq.useBdMediaPup')
  61. const { fileVisible, belongUser, selectFile, selectItem, delPupId, xy, rightClickPup, path, publicPath, parentId, imgVisrible, imgsVisrible, mediaType, sortVisible, num } = state
  62. const { copy } = useCopy()
  63. const fileImg = require('../../../public/file.png')
  64. const [moveId, setMoveId] = useState<any>('')//移动的素材ID
  65. const [treeEl, item, folderId, setActionId, setHoverId] = TreeBox({ data: get_folder_tree.data, belongUser })
  66. const [listData, setListData] = useState<any>({})
  67. const [showImg, setShowImg] = useState(-1)
  68. /********************************/
  69. let moveSelected = document.getElementById("moveSelected"); // 选区
  70. let fileContent = document.getElementById("file_content"); // 内容区
  71. const [startPoint, setStartPoint] = useState({ x: 0, y: 0, flag: false }); // 记录鼠标开始按下坐标 flag 是否开启拖拽
  72. const [isSelect, setIsSelect] = useState<boolean>(false) // 记录是否框选过素材
  73. const [sourceList, setSourceList] = useState<any>({})
  74. const [moveShow, setMoveShow] = useState<boolean>(false)
  75. /********************************/
  76. // 处理数据
  77. useEffect(() => {
  78. let newList: any = {}
  79. listData?.records?.forEach((item: { id: number }) => {
  80. newList[item.id] = JSON.parse(JSON.stringify(item))
  81. })
  82. setSourceList(newList)
  83. }, [listData?.records])
  84. // 获取数据
  85. useEffect(() => {
  86. setListData(list?.data)
  87. }, [list, mediaType])
  88. /**复制编号 */
  89. const copyId = useCallback((e: React.MouseEvent<HTMLSpanElement, MouseEvent>, value: string) => {
  90. e.stopPropagation()//阻止冒泡传递到文件夹被点击事件
  91. copy(value)
  92. }, [])
  93. /**全局右键菜单 */
  94. const Menu = useCallback((props: { isItem?: boolean }) => {
  95. if (props.isItem && isAll) {
  96. return <ul style={{ top: xy?.y, left: xy?.x }} className={style.menu} >
  97. {(isAll || num === 100) && <li onClick={() => allFile('xz')}>全选</li>}
  98. {(isAll || num === 100) && listData?.records && listData?.records?.some((item: { id: number }) => selectFile?.includes(item.id)) && <li onClick={() => allFile('qx')} style={{ color: 'red' }}>取消选择</li>}
  99. {mediaType === 'PAGE' && !rightClickPup.folder ? <>
  100. {/* <li onClick={() => { setPage && setPage(1, rightClickPup.id) }}>查看</li> */}
  101. <li onClick={() => { setPage && setPage(2, rightClickPup.id) }}>复制</li>
  102. <li onClick={() => { setPage && setPage(3, rightClickPup.id) }}>批量复制</li>
  103. </> : <>
  104. <li onClick={() => { editFile() }}>编辑</li>
  105. </>}
  106. {mediaType !== 'PAGE' && !rightClickPup.folder && <li onClick={() => { copy(rightClickPup?.url) }}>复制链接</li>}
  107. <li onClick={() => { set({ actionItem: rightClickPup, sortVisible: true }) }}>编辑排序</li>
  108. <li onClick={() => { set({ fileVisible: true }) }}>新建文件夹</li>
  109. <li onClick={() => { set({ imgVisrible: true }) }}>新建素材</li>
  110. {isAll && selectFile && selectFile?.length > 0 && <li onClick={() => { setMoveShow(true) }}>移动至</li>}
  111. <li onClick={(e) => { delPupOn(rightClickPup.id); onFile(e, rightClickPup, isAll, true) }} style={{ color: 'red' }}>删除</li>
  112. {isAll && selectFile && selectFile?.length > 0 && <li onClick={dels} style={{ color: 'red' }}>删除选中文件</li>}
  113. </ul>
  114. }
  115. return <ul style={{ top: xy?.y, left: xy?.x }} className={style.menu}>
  116. {(isAll || num === 100) && <li onClick={() => allFile('xz')}>全选</li>}
  117. {(isAll || num === 100) && listData?.records && listData?.records?.some((item: { id: number }) => selectFile?.includes(item.id)) && <li onClick={() => allFile('qx')} style={{ color: 'red' }}>取消选择</li>}
  118. {//防止K图文无限嵌套创建判断
  119. (isAll !== false) && <li onClick={() => { set({ fileVisible: true }) }}>新建文件夹</li> //: <li>此处无法新建操作</li>
  120. }
  121. {mediaType === 'PAGE' ? isAll ? <li onClick={() => { setPage && setPage(0) }}>新建素材</li> : <li>此处无法新建操作</li> : <li onClick={() => { set({ imgVisrible: true }) }}>新建素材</li>}
  122. {mediaType === 'IMG' && <li onClick={() => { set({ imgsVisrible: true }) }}>批量新建素材</li>}
  123. {isAll && selectFile && selectFile?.length > 0 && <li onClick={dels} style={{ color: 'red' }}>删除选中文件</li>}
  124. </ul>
  125. }, [xy, rightClickPup, allFile, mediaType])
  126. /**鼠标右键 */
  127. const rightMenu = useCallback((e: any, isItem?: any) => {
  128. e.stopPropagation()
  129. e.preventDefault()
  130. let x = e.clientX;
  131. let y = e.clientY;
  132. set({ xy: { x, y } })
  133. if (isItem) {
  134. set({ rightClickPup: isItem })
  135. } else {
  136. set({ rightClickPup: { id: 'all' } })
  137. }
  138. return false;
  139. }, [])
  140. /**左键点击页面隐藏菜单 */
  141. useEffect(() => {
  142. function fnc(e: any) {
  143. set({ rightClickPup: { id: '' } })
  144. }
  145. document.addEventListener('click', fnc)
  146. return () => {
  147. document.removeEventListener('click', fnc)
  148. }
  149. }, [])
  150. // /**切换个人|公共|父目录ID变化清空选中的文件*/
  151. useEffect(() => {
  152. if (!isBack) {
  153. set({ selectFile: [], selectItem: [] })
  154. }
  155. if (belongUser == '1' && path) {//处理切换个人|公共时保留路径层级的请求
  156. set({ parentId: path[path?.length - 1]?.id || null })
  157. }
  158. if (belongUser == '0' && publicPath) {
  159. set({ parentId: publicPath[publicPath?.length - 1]?.id || null })
  160. }
  161. }, [belongUser, parentId, path?.length, publicPath?.length])
  162. /**卸载组件处理 */
  163. useEffect(() => {
  164. return () => {
  165. set({ parentId: null })
  166. }
  167. }, [])
  168. /**获取目录树*/
  169. useEffect(() => {
  170. get_folder_tree.run({ belongUser, mediaType })
  171. }, [isAll, mediaType, belongUser])
  172. // 点击目录树进入对应目录
  173. useEffect(() => {
  174. if (item) {
  175. let { icon, children, ...arg } = item
  176. treeClick(arg)
  177. }
  178. }, [item])
  179. // 拖动事件配置
  180. const moveConfig = useCallback((item: any) => {
  181. return {
  182. draggable: true,
  183. onDragStart: (ev: any) => {
  184. let img = document.createElement('img')
  185. img.src = fileImg;
  186. ev.dataTransfer.setDragImage(img, 0, 0)
  187. console.log('item---->', item)
  188. setMoveId(item.id)
  189. },
  190. onDragEnd: (e: any) => {
  191. if (folderId !== '' && moveId !== '') {
  192. edit_media_folder.run({ sysMediaId: moveId, folderId, mediaType }).then(res => {
  193. message.success('操作成功')
  194. list.refresh()
  195. })
  196. }
  197. setActionId('')
  198. setHoverId('')
  199. setMoveId('')
  200. },
  201. }
  202. }, [folderId, moveId, mediaType])
  203. /** 判断2个元素是否重合 */
  204. const elementsOverlap = (el1: HTMLElement, el2: HTMLElement) => {
  205. const domRect1 = el1.getBoundingClientRect();
  206. const domRect2 = el2.getBoundingClientRect();
  207. return !(
  208. domRect1.top > domRect2.bottom ||
  209. domRect1.right < domRect2.left ||
  210. domRect1.bottom < domRect2.top ||
  211. domRect1.left > domRect2.right
  212. );
  213. }
  214. /**记录鼠标down event */
  215. const onMouseDown = ({ target: { dataset }, pageX, pageY }: any) => {
  216. const { type } = dataset
  217. if (isBack && num !== 100) return
  218. if (moveSelected && type === 'right-boxzones') {
  219. moveSelected.style.top = pageY + 'px';
  220. moveSelected.style.left = pageX + 'px';
  221. setStartPoint({ x: pageX, y: pageY, flag: true })
  222. }
  223. }
  224. /**记录鼠标抬起事件 */
  225. const onMouseUp = () => {
  226. if (startPoint.flag && moveSelected) {
  227. setStartPoint({ x: 0, y: 0, flag: false })
  228. moveSelected.style.width = '0px';
  229. moveSelected.style.height = '0px';
  230. moveSelected.style.top = '0px';
  231. moveSelected.style.left = '0px';
  232. moveSelected.style.bottom = '0px';
  233. moveSelected.style.right = '0px';
  234. }
  235. }
  236. /** 鼠标移动事件 */
  237. const onMouseMove = ({ pageX, pageY }: any) => {
  238. const { x, y, flag } = startPoint
  239. if (flag) {
  240. if (moveSelected) {
  241. if (pageX < x) { //表示左移
  242. moveSelected.style.left = pageX + 'px';
  243. moveSelected.style.width = (x - pageX) + 'px'; //向左移动的距离作为选区的宽
  244. } else {
  245. moveSelected.style.width = (pageX - x) + 'px';
  246. }
  247. if (pageY < y) { //向上移动
  248. moveSelected.style.top = pageY + 'px';
  249. moveSelected.style.height = (y - pageY) + 'px';
  250. } else {
  251. moveSelected.style.height = (pageY - y) + 'px';
  252. }
  253. //通过得到的left和top加上元素自身的宽高来计算选区的right和bottom
  254. moveSelected.style.bottom = Number(moveSelected.style.top.split('px')[0]) + Number(moveSelected.style.height.split('px')[0]) + 'px';
  255. moveSelected.style.right = Number(moveSelected.style.left.split('px')[0]) + Number(moveSelected.style.width.split('px')[0]) + 'px';
  256. if (fileContent && fileContent?.children?.length > 0) {
  257. //找出选中的区域并激活
  258. let checkboxs: any = fileContent?.children
  259. for (let i = 0; i < checkboxs?.length; i++) {
  260. let id = checkboxs[i]?.getAttribute('data-id')
  261. if (elementsOverlap(moveSelected, checkboxs[i]) && id) {
  262. id = Number(id)
  263. let state = selectFile?.some((i) => i === id)
  264. if (!state) {//新增
  265. setIsSelect(true)
  266. set({ selectFile: [...selectFile as number[], id] })
  267. if (isBack) {
  268. set({ selectItem: [...selectItem, sourceList[id]] })
  269. }
  270. }
  271. }
  272. }
  273. }
  274. }
  275. }
  276. }
  277. /** 鼠标离开可拖动区域事件 */
  278. const onMouseLeave = () => {
  279. if (startPoint.flag && moveSelected) {
  280. setStartPoint({ x: 0, y: 0, flag: false })
  281. moveSelected.style.width = '0px';
  282. moveSelected.style.height = '0px';
  283. moveSelected.style.top = '0px';
  284. moveSelected.style.left = '0px';
  285. }
  286. }
  287. // 获取拖拽的文件
  288. const [fileList, setFileList] = useState<FileList>()
  289. const [uploadVisible, setUploadVisible] = useState<boolean>(false)
  290. const { isDragOver, dropAreaProps } = useFileDrop((fileList) => {
  291. if (!moveId) {
  292. setFileList(fileList)
  293. setUploadVisible(true)
  294. }
  295. });
  296. return <div style={{ display: 'flex', flexFlow: 'row', width: '100%', padding: get_folder_tree?.data?.length ? 0 : '0 16px 0' }}>
  297. {get_folder_tree?.data?.length > 0 && <div style={{ flexShrink: 0 }}>
  298. {treeEl}
  299. </div>}
  300. <div
  301. style={{ flex: 1, padding: '10px 0px 0px' }}
  302. data-type="right-boxzones"
  303. onMouseDown={onMouseDown}
  304. onMouseUp={onMouseUp}
  305. onMouseLeave={onMouseLeave}
  306. onMouseMove={onMouseMove}
  307. onDoubleClick={() => {
  308. if (isSelect) {
  309. set({ selectItem: [] }); set({ selectFile: [] })
  310. }
  311. }}
  312. >
  313. <div
  314. className={style.files}
  315. data-type="right-boxzones"
  316. onContextMenu={rightMenu}
  317. style={height ? { height } : {}}
  318. {...(mediaType !== 'PAGE' ? dropAreaProps : {})}
  319. >
  320. {mediaType !== 'PAGE' && isDragOver && !moveId && <div className={`${style.placeholder} ${isDragOver ? style.dragOver : ''}`}><span>拖动文件到这里</span></div>}
  321. {/* 层级路径 */}
  322. <div className={style.path} >
  323. {//存在渲染个人本地路径不存在执行公共本地
  324. belongUser == '1' && path?.map((item: { title: string }, index: number) => {
  325. return <span key={index} onClick={() => { pathClick({ ...item, index }) }} >
  326. <span className={path?.length !== index + 1 ? style.path_color : ''}>{item?.title}</span>
  327. {path?.length !== index + 1 && <span className={style.rt} >{'>'}</span>}
  328. </span>
  329. })
  330. }
  331. {belongUser == '0' && publicPath?.map((item: { title: string }, index: number) => {
  332. return <span key={index} onClick={() => { pathClick({ ...item, index }) }} >
  333. <span className={publicPath?.length !== index + 1 ? style.path_color : ''}>{item?.title}</span>
  334. {publicPath?.length !== index + 1 && <span className={style.rt} >{'>'}</span>}
  335. </span>
  336. })}
  337. </div>
  338. {/* 内容 */}
  339. <Spin spinning={list.loading} style={{ width: '100%' }}>
  340. <div className={style.file_content} data-type="right-boxzones" id="file_content">
  341. {listData?.records?.map((item: Item, index: number) => {
  342. if (item.folder) {
  343. {/* 文件夹模板 */ }
  344. return <Popconfirm
  345. title="确定要删除吗?"
  346. onConfirm={() => { dels(item) }}
  347. okText="是"
  348. cancelText="否"
  349. onCancel={delPupOff}
  350. visible={delPupId === item.id}
  351. key={item.id}
  352. >
  353. <Spin tip='正在请求素材详情,请耐心等待...' spinning={get?.loading}>
  354. <div
  355. className={`${style.flex_box} ${selectFile?.some((id: number) => id === item.id) ? style.action : ''}`}
  356. onContextMenu={(e) => { rightMenu(e, item) }}
  357. onClick={(e) => {
  358. e.stopPropagation()
  359. e.preventDefault()
  360. changeClickFile(e, item, isAll, noFile)
  361. }}
  362. onDragStart={(e: any) => {
  363. e.preventDefault()
  364. }}
  365. >
  366. <img src={fileImg}
  367. className={style.flex_box_img}
  368. onClick={(e: any) => { e.stopPropagation(); fileClick(item) }}
  369. onDragOver={(ev) => {
  370. ev.preventDefault()
  371. }}
  372. onDrop={() => {
  373. if (item.id !== folderId) {
  374. setActionId(item.id)
  375. }
  376. }}
  377. />
  378. <span className={style.flex_box_name} >{item?.title}</span>
  379. <span className={style.flex_box_id} onClick={(e) => { copyId(e, item?.number) }} >{item?.number}</span>
  380. </div>
  381. </Spin>
  382. </Popconfirm>
  383. } else {
  384. {/* 图片模板 ,视频模板,音频模板*/ }
  385. let topPageElements: any
  386. let topName: string = ""
  387. if (mediaType === 'PAGE' && item?.pageSpecsList) {
  388. topPageElements = item?.pageSpecsList[0]?.pageElementsSpecList[0]
  389. }
  390. let El = null
  391. if (mediaType === 'IMG') {
  392. El = <Image
  393. rootClassName={style.imgData}
  394. src={item.url}
  395. onClick={(e) => {
  396. e.stopPropagation()
  397. let className = (e.target as any).className
  398. if (className === 'ant-image-mask-info') {
  399. setShowImg(index)
  400. } else {
  401. changeClickFile(e, item, isAll, noFile)
  402. }
  403. }}
  404. preview={{
  405. visible: showImg === index,
  406. maskClassName: style.maskClass,
  407. onVisibleChange: (value) => {
  408. if (!value) {
  409. setShowImg(-1)
  410. }
  411. }
  412. }}
  413. />
  414. } else if (mediaType === 'VIDEO') {
  415. El = <VideoNews src={item.url} />
  416. } else if (mediaType === 'PAGE') {
  417. switch (topPageElements?.elementType) {
  418. case 'TOP_IMAGE':
  419. topName = "顶部图片"
  420. El = <Image
  421. src={topPageElements?.topImageSpec?.imageUrl}
  422. preview={{ visible: false, maskClassName: style.maskClass }}
  423. onClick={(e) => {
  424. e.stopPropagation()
  425. let className = (e.target as any).className
  426. if (className === 'ant-image-mask-info') {
  427. setPage && setPage(1, item.id)
  428. } else {
  429. changeClickFile(e, item, isAll, noFile)
  430. }
  431. }}
  432. />
  433. break
  434. case 'TOP_SLIDER':
  435. topName = "顶部轮播图"
  436. El = <>
  437. <Carousel autoplay style={{ width: 150, textAlign: 'center' }}>
  438. {topPageElements?.topSliderSpec?.imageUrlList?.map((url: string, index: number) => <div key={index}>
  439. <Image
  440. preview={{ visible: false, maskClassName: style.maskClass }}
  441. src={url}
  442. onClick={(e) => {
  443. e.stopPropagation()
  444. let className = (e.target as any).className
  445. if (className === 'ant-image-mask-info') {
  446. setPage && setPage(1, item.id)
  447. } else {
  448. changeClickFile(e, item, isAll, noFile)
  449. }
  450. }} />
  451. </div>)}
  452. </Carousel>
  453. </>
  454. break
  455. case 'TOP_VIDEO':
  456. topName = "顶部视频"
  457. El = <Image
  458. src={getVideoImgUrl(topPageElements?.topVideoSpec?.videoUrl)}
  459. preview={{ visible: false, maskClassName: style.maskClass }}
  460. onClick={(e) => {
  461. e.stopPropagation()
  462. let className = (e.target as any).className
  463. if (className === 'ant-image-mask-info') {
  464. setPage && setPage(1, item.id)
  465. } else {
  466. changeClickFile(e, item, isAll, noFile)
  467. }
  468. }}
  469. />
  470. break
  471. }
  472. }
  473. return <Popconfirm
  474. title="确定要删除吗?"
  475. onConfirm={() => { dels(item.id) }}
  476. okText="是"
  477. cancelText="否"
  478. onCancel={delPupOff}
  479. visible={delPupId === item.id}
  480. key={item.id}
  481. >
  482. <Spin tip='正在请求素材详情,请耐心等待...' spinning={get?.loading} data-id={item.id}>
  483. <div
  484. className={`${style.image_box} ${!isBack ? (selectFile?.some((id: number) => id === item.id) ? style.action : '') : (selectItem?.some((item1: { url: string }) => item1.url === item.url) ? style.action : '')}`}
  485. onContextMenu={(e) => { rightMenu(e, item) }}
  486. onClick={(e) => { changeClickFile(e, item, isAll) }}
  487. {...moveConfig(item)}
  488. >
  489. <span className={`${style.select}`} onClick={(e) => { changeClickFile(e, item, isAll) }}>
  490. <span role="img" aria-label="check" style={{ color: '#fff' }}><svg viewBox="64 64 896 896" focusable="false" data-icon="check" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"></path></svg></span>
  491. </span>
  492. {El}
  493. <span className={style.flex_box_name} onClick={(e) => { copyId(e, item?.videoTitle || item?.title) }}>{item?.videoTitle || item?.title}</span>
  494. {mediaType === 'PAGE' ? <span>{topName}</span> : <span>{item?.width}*{item.height}</span>}
  495. </div>
  496. </Spin>
  497. </Popconfirm>
  498. }
  499. })}
  500. </div>
  501. </Spin>
  502. {/* 鼠标右键菜单 */}
  503. {rightClickPup.id ? rightClickPup.id === 'all' ? <Menu /> : <Menu isItem /> : null}
  504. {/* 新建文件弹窗 */}
  505. {fileVisible && <FileModal isAll={isAll} />}
  506. {/* 编辑排序 */}
  507. {sortVisible && <SortModal isAll={isAll} />}
  508. {/* 新建非图文 */}
  509. {imgVisrible && <ImgModal isAll={isAll} />}
  510. {imgsVisrible && <ImgsModal isAll={isAll} />}
  511. {/* 移动至 */}
  512. {moveShow && <MoveTo visible={moveShow} onClose={() => setMoveShow(false)} isAll={isAll} catalogueData={get_folder_tree.data} />}
  513. </div>
  514. <div className={style.pagination}>
  515. {/* 分页 */}
  516. {listData?.records?.length > 0 && <Pagination
  517. showSizeChanger
  518. onChange={(page: number, pageSize?: number) => {
  519. getList({ pageSize, pageNum: page })
  520. }}
  521. onShowSizeChange={(current: number, size: number) => {
  522. getList({ pageSize: size, pageNum: current })
  523. }}
  524. pageSizeOptions={['10', '20', '30', '50', '100']}
  525. current={listData?.current}
  526. defaultPageSize={30}
  527. total={listData?.total}
  528. />}
  529. </div>
  530. <div className={style.moveSelected} id='moveSelected' />
  531. </div>
  532. {uploadVisible && <UploadsTable
  533. parentId={parentId}
  534. belongUser={belongUser}
  535. mediaType={mediaType}
  536. visible={uploadVisible}
  537. fileList={fileList}
  538. onClose={() => {
  539. setUploadVisible(false)
  540. setFileList(undefined)
  541. }}
  542. onChange={() => {
  543. setUploadVisible(false)
  544. setFileList(undefined)
  545. list.refresh()
  546. }}
  547. />}
  548. </div>
  549. }
  550. export default React.memo(FlieBox)