index.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. import React, {
  2. useCallback,
  3. useEffect,
  4. useMemo,
  5. useRef,
  6. useState,
  7. } from "react";
  8. import styles from "./index.module.scss";
  9. import { Button, Input, Popconfirm, Table } from "antd";
  10. import classNames from "classnames";
  11. import { baseUpUrl } from "@/utils/http";
  12. import A1ORenFile from "./A1ORenFile";
  13. import A1OMove from "./A1OMove";
  14. import { A1OFileType } from "@/types";
  15. import { useDispatch, useSelector } from "react-redux";
  16. import { RootState } from "@/store";
  17. import {
  18. A1_APIOgetList,
  19. A1_APIOdel,
  20. A1_APIOdownload,
  21. } from "@/store/action/A1Project";
  22. import { MessageFu } from "@/utils/message";
  23. import A1OupFile from "./A1OupFile";
  24. import { authFilesLookFu, urlChangeFu } from "@/utils/authFilesLook";
  25. import AuthCom from "@/components/AuthCom";
  26. type Props = {
  27. projectId: number;
  28. projectName: string;
  29. };
  30. function A1Outer({ projectId, projectName }: Props) {
  31. const dispatch = useDispatch();
  32. // 从仓库获取左侧写死列表 和 展示列表
  33. const { A1OleftArr, A1OtableInfo } = useSelector(
  34. (state: RootState) => state.A1Project
  35. );
  36. const [fromData, setFromData] = useState({
  37. parentId: 1,
  38. searchKey: "",
  39. pageNum: 1,
  40. pageSize: 10,
  41. });
  42. // 文件名的输入
  43. const searchKeyTime = useRef(-1);
  44. const searchKeyChange = useCallback(
  45. (e: React.ChangeEvent<HTMLInputElement>) => {
  46. clearTimeout(searchKeyTime.current);
  47. searchKeyTime.current = window.setTimeout(() => {
  48. setFromData({
  49. ...fromData,
  50. searchKey: e.target.value,
  51. pageNum: 1,
  52. });
  53. }, 500);
  54. },
  55. [fromData]
  56. );
  57. // 封装发送请求的函数
  58. const getListFu = useCallback(() => {
  59. dispatch(A1_APIOgetList({ ...fromData, projectId }));
  60. // 清空选中
  61. setSelectedRowKeys([]);
  62. }, [dispatch, fromData, projectId]);
  63. useEffect(() => {
  64. getListFu();
  65. }, [getListFu]);
  66. // 一级的高亮
  67. const [tab1, setTab1] = useState({} as A1OFileType);
  68. useEffect(() => {
  69. setTab1(A1OleftArr[0]);
  70. }, [A1OleftArr]);
  71. // 二级的选择
  72. const [tab2, setTab2] = useState({ id: 0, name: "" });
  73. // 一级的切换
  74. const cutTab1Fu = useCallback(
  75. (id: number, name: string) => {
  76. setTab2({ id: 0, name: "" });
  77. setTab1({ id, name } as A1OFileType);
  78. if (id !== fromData.parentId)
  79. setFromData({ ...fromData, parentId: id, pageNum: 1 });
  80. },
  81. [fromData]
  82. );
  83. // 点击表格里面的 文件夹 进入 2级
  84. const toTowFilesFu = useCallback(
  85. (id: number, type: 0 | 1, name: string) => {
  86. if (type === 1) {
  87. setTab2({ id, name });
  88. setFromData({ ...fromData, parentId: id, pageNum: 1 });
  89. }
  90. },
  91. [fromData]
  92. );
  93. // 页码变化
  94. const paginationChange = useCallback(
  95. () => (pageNum: number, pageSize: number) => {
  96. setFromData({ ...fromData, pageNum, pageSize });
  97. },
  98. [fromData]
  99. );
  100. // 关于表格的多选
  101. const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
  102. // 新建文件夹或者 重命名
  103. const [renFile, setRenFile] = useState({} as A1OFileType);
  104. // 点击移动之后出来的数据
  105. const [moveId, setMoveId] = useState({ id: 0, name: "" });
  106. // 点击表格里面的删除
  107. const delById = useCallback(
  108. async (id: number) => {
  109. const res = await A1_APIOdel(id);
  110. if (res.code === 0) {
  111. MessageFu.success("删除成功!");
  112. getListFu();
  113. }
  114. },
  115. [getListFu]
  116. );
  117. // 点击表格里面的 文件夹 的下载
  118. const downFilesFu = useCallback(async (id: number, name: string) => {
  119. const res = await A1_APIOdownload(id);
  120. if (res.code === 0) {
  121. urlChangeFu(res.data, true, undefined, name);
  122. }
  123. }, []);
  124. // 点击批量下载
  125. const downSelectFu = useCallback(async () => {
  126. const res = await A1_APIOdownload(selectedRowKeys.join(","));
  127. if (res.code === 0) {
  128. urlChangeFu(res.data, true, undefined, projectName);
  129. // 清空选中
  130. setSelectedRowKeys([]);
  131. }
  132. }, [projectName, selectedRowKeys]);
  133. // 点击-批量上传
  134. const [upFileId, setUpFileId] = useState(0);
  135. const columns = useMemo(() => {
  136. return [
  137. {
  138. title: "文件名",
  139. render: (item: A1OFileType) =>
  140. item.name.length >= 30 ? (
  141. <span style={{ cursor: "pointer" }} title={item.name}>
  142. <span
  143. onClick={() => toTowFilesFu(item.id, item.type, item.name)}
  144. className={classNames(item.type === 1 ? "A1OfilesTable" : "")}
  145. >
  146. {item.name.substring(0, 30) + "..."}
  147. </span>
  148. </span>
  149. ) : (
  150. <span
  151. onClick={() => toTowFilesFu(item.id, item.type, item.name)}
  152. className={classNames(item.type === 1 ? "A1OfilesTable" : "")}
  153. >
  154. {item.name}
  155. </span>
  156. ),
  157. },
  158. {
  159. title: "创建用户",
  160. dataIndex: "creatorName",
  161. },
  162. {
  163. title: "创建时间",
  164. dataIndex: "createTime",
  165. },
  166. {
  167. title: "操作",
  168. render: (item: A1OFileType) => (
  169. <>
  170. {authFilesLookFu(item.name,'') ? (
  171. <Button
  172. size="small"
  173. type="text"
  174. onClick={() => authFilesLookFu(item.name, item.filePath)}
  175. >
  176. 查看
  177. </Button>
  178. ) : null}
  179. {item.type === 1 ? (
  180. <AuthCom aId="1094">
  181. <Button
  182. size="small"
  183. type="text"
  184. onClick={() => downFilesFu(item.id, item.name)}
  185. >
  186. 下载
  187. </Button>
  188. </AuthCom>
  189. ) : (
  190. <AuthCom aId="1094">
  191. <Button
  192. size="small"
  193. type="text"
  194. onClick={() =>
  195. urlChangeFu(item.filePath, true, undefined, item.name)
  196. }
  197. >
  198. 下载
  199. </Button>
  200. </AuthCom>
  201. )}
  202. <Button size="small" type="text" onClick={() => setRenFile(item)}>
  203. 重命名
  204. </Button>
  205. {item.type === 1 ? null : (
  206. <AuthCom aId="1095">
  207. <Button
  208. size="small"
  209. type="text"
  210. onClick={() => setMoveId({ id: item.id, name: item.name })}
  211. >
  212. 移动
  213. </Button>
  214. </AuthCom>
  215. )}
  216. <AuthCom aId="1096">
  217. <Popconfirm
  218. title="删除后无法恢复,是否删除?"
  219. okText="删除"
  220. cancelText="取消"
  221. onConfirm={() => delById(item.id)}
  222. okButtonProps={{ loading: false }}
  223. >
  224. <Button size="small" type="text" danger>
  225. 删除
  226. </Button>
  227. </Popconfirm>
  228. </AuthCom>
  229. </>
  230. ),
  231. },
  232. ];
  233. }, [delById, downFilesFu, toTowFilesFu]);
  234. // 当前位置
  235. const nowLoc = useMemo(() => {
  236. return {
  237. tag: (
  238. <>
  239. <span
  240. className="A1OnowLocRow"
  241. onClick={() => cutTab1Fu(tab1.id, tab1.name)}
  242. >
  243. {tab1.name}
  244. </span>
  245. {tab2.id ? <span> / {tab2.name}</span> : null}
  246. </>
  247. ),
  248. txt: tab1.name + (tab2.id ? ` / ${tab2.name}` : ""),
  249. };
  250. }, [cutTab1Fu, tab1.id, tab1.name, tab2.id, tab2.name]);
  251. return (
  252. <div className={styles.A1Outer}>
  253. <div className="A1Otop">
  254. <div className="A1Otop1">
  255. <span>文件名:</span>
  256. <Input
  257. maxLength={30}
  258. style={{ width: 300 }}
  259. placeholder="请输入文件名称,最多30字"
  260. allowClear
  261. onChange={(e) => searchKeyChange(e)}
  262. />
  263. &emsp;&emsp;
  264. <span className="A1OnowLoc">当前位置:{nowLoc.tag}</span>
  265. </div>
  266. <div className="A1Otop2">
  267. {tab2.id ? null : (
  268. <>
  269. <AuthCom aId="1092">
  270. <Button
  271. type="primary"
  272. onClick={() =>
  273. setRenFile({
  274. id: -1,
  275. name: "",
  276. type: 1,
  277. parentId: tab1.id,
  278. } as A1OFileType)
  279. }
  280. >
  281. 新建文件夹
  282. </Button>
  283. &emsp;
  284. </AuthCom>
  285. </>
  286. )}
  287. <AuthCom aId="1093">
  288. <Button
  289. type="primary"
  290. onClick={downSelectFu}
  291. disabled={selectedRowKeys.length <= 0}
  292. >
  293. 批量下载
  294. </Button>
  295. </AuthCom>
  296. &emsp;
  297. <AuthCom aId="1091">
  298. <Button
  299. type="primary"
  300. onClick={() => setUpFileId(tab2.id ? tab2.id : tab1.id)}
  301. >
  302. 批量上传
  303. </Button>
  304. </AuthCom>
  305. &emsp;
  306. </div>
  307. </div>
  308. {/* 表格主体 */}
  309. <div className="A1OtableBox">
  310. <div className="A1OtableBox1">
  311. <div className="A1OtableBox1_1">目录</div>
  312. {A1OleftArr.map((v) => {
  313. // 子标题用 , 隔开
  314. const temp = v.name.split(',')
  315. return (
  316. <div
  317. onClick={() => cutTab1Fu(v.id, temp[0])}
  318. className={classNames(
  319. "A1OtableBox1_2",
  320. tab1.id === v.id ? "A1OtableBox1_2Ac" : ""
  321. )}
  322. key={v.id}
  323. >
  324. <p>{temp[0]}</p>
  325. {temp[1] && (
  326. <span style={{
  327. textAlign: 'center'
  328. }}>{temp[1]}</span>
  329. )}
  330. </div>
  331. )
  332. })}
  333. </div>
  334. <div className="A1OtableBox2">
  335. <Table
  336. rowSelection={{
  337. type: "checkbox",
  338. selectedRowKeys,
  339. onChange: (selectedRowKeys: React.Key[]) => {
  340. setSelectedRowKeys(selectedRowKeys);
  341. },
  342. }}
  343. scroll={{ y: 560 }}
  344. dataSource={A1OtableInfo.list}
  345. columns={columns}
  346. rowKey="id"
  347. pagination={{
  348. showQuickJumper: true,
  349. position: ["bottomCenter"],
  350. showSizeChanger: true,
  351. current: fromData.pageNum,
  352. pageSize: fromData.pageSize,
  353. total: A1OtableInfo.total,
  354. onChange: paginationChange(),
  355. }}
  356. />
  357. </div>
  358. </div>
  359. {/* 点击 新建 文件夹 或者 重命名 */}
  360. {renFile.id ? (
  361. <A1ORenFile
  362. addFu={() => setFromData({ ...fromData, searchKey: "", pageNum: 1 })}
  363. editFu={() => getListFu()}
  364. closeFu={() =>
  365. setRenFile({ id: 0, name: "", type: 0 } as A1OFileType)
  366. }
  367. fileInfo={renFile}
  368. projectId={projectId}
  369. />
  370. ) : null}
  371. {/* 点击移动 */}
  372. {moveId.id ? (
  373. <A1OMove
  374. mId={moveId}
  375. id1={tab1}
  376. id2={tab2}
  377. closeFu={() => setMoveId({ id: 0, name: "" })}
  378. projectId={projectId}
  379. moveSuFu={() => getListFu()}
  380. />
  381. ) : null}
  382. {/* 点击批量上传 */}
  383. {upFileId ? (
  384. <A1OupFile
  385. myUrl={baseUpUrl + "cms/item/upload"}
  386. fromData={{ parentId: upFileId, projectId }}
  387. nowLoc={nowLoc.txt}
  388. closeFu={() => setUpFileId(0)}
  389. upFileFu={() => getListFu()}
  390. />
  391. ) : null}
  392. </div>
  393. );
  394. }
  395. const MemoA1Outer = React.memo(A1Outer);
  396. export default MemoA1Outer;