index.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import React, { useEffect, useRef, useState } from "react"
  2. import style from './index.less'
  3. import Folder from "./folder";
  4. import Material from "./material";
  5. import { Card, message, Modal } from "antd";
  6. import '../../tencentAdPutIn/index.less'
  7. import { DataNode, EventDataNode } from "antd/lib/tree";
  8. import { delFolderApi, getFolderListApi } from "@/services/adqV3/cloudNew";
  9. import { useAjax } from "@/Hook/useAjax";
  10. import ManageFolder from "./manageFolder";
  11. import { ExclamationCircleOutlined, FolderOpenOutlined, FolderOutlined } from "@ant-design/icons";
  12. import { updateTreeData } from "./const";
  13. import Search from "./search";
  14. export const DispatchCloudNew = React.createContext<CLOUDNEW.CloudNewReactContent | null>(null);
  15. /**
  16. * 新版素材库
  17. * @returns
  18. */
  19. const CloudNew: React.FC = () => {
  20. /**********************************/
  21. const refMaterial = useRef(null);
  22. const [treeData, setTreeData] = useState<DataNode[]>([]);
  23. const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
  24. const [queryFormFolder, setQueryFormFolder] = useState<CLOUDNEW.GetFolderListProps>({})
  25. const [folderVisible, setFolderVisible] = useState<boolean>(false)
  26. const [folderLoading, setFolderLoading] = useState<boolean>(false)
  27. const [breadcrumdData, setBreadcrumdData] = useState<CLOUDNEW.BreadcrumdData[]>([{ label: '全部素材', key: 0, currentKey: '0' }])
  28. const [loadedKeys, setLoadedKeys] = useState<string[]>([]) // 已经加载了的节点
  29. const [initialValuesFolder, setInitialValuesFolder] = useState<any>({})
  30. const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]); // 目录树打开控制
  31. const [folderCreateBy, setFolderCreateBy] = useState<number>() // 获取最上层文件夹创建人
  32. const [batchFolderVisible, setBatchFolderVisible] = useState<boolean>(false) // 批量操作文件夹控制
  33. const [handleType, setHandleType] = useState<'folder' | 'file'>('file') // 操作类型
  34. const [materialParams, setMaterialParams] = useState<CLOUDNEW.GetMaterialListProps>({ pageNum: 1, pageSize: 30 })
  35. const getFolderList = useAjax((params) => getFolderListApi(params))
  36. const delFolderAjax = useAjax((params) => delFolderApi(params))
  37. /**********************************/
  38. useEffect(() => {
  39. handleGetFolder()
  40. }, [queryFormFolder?.folderName])
  41. useEffect(() => {
  42. if (breadcrumdData.length > 1) {
  43. let folderId = breadcrumdData[1].key
  44. setFolderCreateBy(getFolderList.data.find((item: { id: number; }) => item.id === folderId).createBy)
  45. } else {
  46. setFolderCreateBy(undefined)
  47. }
  48. }, [breadcrumdData, getFolderList.data])
  49. // 获取顶级文件夹列表
  50. const handleGetFolder = () => {
  51. setFolderLoading(() => true)
  52. setLoadedKeys(() => [])
  53. getFolderList.run({ folderName: queryFormFolder?.folderName }).then(res => {
  54. setFolderLoading(() => false)
  55. setTreeData(() => res?.map((item: { folderName: any; id: any; }) => ({
  56. title: item.folderName,
  57. key: '0-' + item.id,
  58. icon: ({ selected }: any) => (selected ? <FolderOpenOutlined style={{ color: 'rgb(255, 202, 40)' }} /> : <FolderOutlined style={{ color: 'rgb(255, 202, 40)' }} />),
  59. })) || [])
  60. }).catch(() => setFolderLoading(false))
  61. }
  62. // 下级目录
  63. const handleUpdateFolder = (parentIdStr: string) => {
  64. const parentIdArr = parentIdStr.split('-')
  65. const parentIdArrLength = parentIdArr.length
  66. const parentId = Number(parentIdArr[parentIdArrLength - 1])
  67. return getFolderListApi({ parentId }).then(res => {
  68. setLoadedKeys(loadedkeys => [...loadedkeys, parentIdStr].filter(item => !item.includes(parentIdStr + '-')))
  69. setExpandedKeys(expandedKeys => [...expandedKeys, parentIdStr])
  70. setTreeData(origin =>
  71. updateTreeData(origin, parentIdStr, res?.data?.map((item: { folderName: any; id: any; }) => ({
  72. title: item.folderName,
  73. key: parentIdStr + '-' + item.id,
  74. icon: ({ selected }: any) => (selected ? <FolderOpenOutlined /> : <FolderOutlined />)
  75. })) || []),
  76. );
  77. })
  78. }
  79. // 查找所有菜单列表(m面包屑)
  80. const findParentKeys = (key: string, tree: DataNode[]) => {
  81. let newBreadcrumdData: CLOUDNEW.BreadcrumdData[] = [{ label: '全部素材', key: 0, currentKey: '0' }]
  82. let keys = key.split('-')
  83. let treeData: DataNode[] = JSON.parse(JSON.stringify(tree))
  84. let currentKey: string = '0'
  85. keys.forEach((item, index) => {
  86. if (index !== 0) {
  87. currentKey = currentKey + '-' + item
  88. let treeD = treeData.find(item => item.key === currentKey)
  89. if (treeD) {
  90. if (treeD?.children) {
  91. treeData = treeD.children
  92. }
  93. newBreadcrumdData.push({ label: treeD?.title as string, key: Number(item), currentKey })
  94. }
  95. }
  96. })
  97. setBreadcrumdData(newBreadcrumdData)
  98. };
  99. // 删除文件夹
  100. const delFolder = (id: number, name: string) => {
  101. Modal.confirm({
  102. title: <strong>{`删除文件夹“${name}”`}</strong>,
  103. icon: <ExclamationCircleOutlined />,
  104. content: '是否确定删除该文件夹',
  105. okText: '确认',
  106. cancelText: '取消',
  107. className: 'modalResetCss',
  108. onOk: () => {
  109. return new Promise((resolve: (value: unknown) => void) => {
  110. delFolderAjax.run(id).then(res => {
  111. if (res) {
  112. message.success('删除成功');
  113. (refMaterial.current as any).folderRefresh()
  114. if (selectedKeys[0] === '0' || !selectedKeys[0]) {
  115. setTreeData(data => data.filter(item => item.key !== ('0-' + id)))
  116. } else {
  117. handleUpdateFolder(selectedKeys[0] as string)
  118. }
  119. resolve('')
  120. }
  121. })
  122. })
  123. }
  124. });
  125. }
  126. return <>
  127. <div className={style.cloudNew_layout}>
  128. <DispatchCloudNew.Provider value={{
  129. treeData, setTreeData,
  130. selectedKeys, setSelectedKeys,
  131. queryFormFolder, setQueryFormFolder,
  132. breadcrumdData, setBreadcrumdData,
  133. loadedKeys, setLoadedKeys,
  134. findParentKeys, handleUpdateFolder,
  135. expandedKeys, setExpandedKeys,
  136. folderCreateBy, setFolderCreateBy,
  137. batchFolderVisible, setBatchFolderVisible,
  138. handleType, setHandleType,
  139. materialParams, setMaterialParams
  140. }}>
  141. {/* 搜索 */}
  142. <Search
  143. onSearch={(value) => (refMaterial.current as any)?.search(value)}
  144. />
  145. <Card
  146. style={{ height: '100%', flex: '1 0', overflow: 'hidden' }}
  147. bodyStyle={{ padding: 0, overflow: 'auto hidden', height: '100%' }}
  148. className="cardResetCss buttonResetCss"
  149. bordered
  150. >
  151. <div className={style.cloudNew}>
  152. {/* 文件夹 */}
  153. <Folder
  154. loading={folderLoading}
  155. onLoadData={(treeNode: EventDataNode<DataNode>) => {
  156. return new Promise<void>(async (resolve) => {
  157. console.log('Trigger Select', treeNode);
  158. await handleUpdateFolder(treeNode.key as string)
  159. resolve()
  160. })
  161. }}
  162. />
  163. {/* 素材列表 */}
  164. <Material
  165. onAddFolder={() => {
  166. setFolderVisible(true)
  167. }}
  168. onUpdateFolder={(data) => {
  169. setInitialValuesFolder(data)
  170. setFolderVisible(true)
  171. }}
  172. onDelFolder={delFolder}
  173. ref={refMaterial}
  174. />
  175. </div>
  176. </Card>
  177. </DispatchCloudNew.Provider>
  178. </div>
  179. {/* 文件夹新增修改 */}
  180. {folderVisible && <ManageFolder
  181. initialValues={initialValuesFolder}
  182. parentIdStr={selectedKeys?.[0] as string || '0'}
  183. visible={folderVisible}
  184. onClose={() => {
  185. setFolderVisible(false)
  186. }}
  187. onChange={(newData) => {
  188. setFolderVisible(false)
  189. if (initialValuesFolder?.id) {
  190. (refMaterial.current as any).folderRefresh()
  191. if (selectedKeys?.[0]) {
  192. handleUpdateFolder(selectedKeys[0] as string)
  193. } else {
  194. setTreeData(data => data.map(item => {
  195. return item.key === ('0-' + newData.id) ? { ...item, title: newData.folderName } : item
  196. }))
  197. }
  198. setInitialValuesFolder(undefined)
  199. } else {
  200. (refMaterial.current as any).folderRefresh()
  201. if (selectedKeys?.[0]) {
  202. handleUpdateFolder(selectedKeys[0] as string)
  203. } else {
  204. // handleGetFolder()
  205. setTreeData(data => [...data, { title: newData.folderName, key: '0-' + newData.id, icon: ({ selected }: any) => (selected ? <FolderOpenOutlined style={{ color: 'rgb(255, 202, 40)' }} /> : <FolderOutlined style={{ color: 'rgb(255, 202, 40)' }} />) }])
  206. }
  207. }
  208. }}
  209. />}
  210. </>
  211. }
  212. export default CloudNew