CalculateListPage.tsx 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. import { Avatar, List, message, Checkbox, Row, Col, Space, Button } from "antd";
  2. import type { CheckboxProps } from "antd";
  3. import { useEffect, useState } from "react";
  4. import {
  5. del_file_by_id,
  6. get_fileInfo_by_id,
  7. searchDuplicateFile,
  8. } from "@/services";
  9. import { message as tauriMessage } from "@tauri-apps/api/dialog";
  10. import styles from "./CalculateListPage.module.less";
  11. import { useParams } from "react-router";
  12. import { insertSearchFilesPasamsType } from "@/types/files";
  13. import type { GetProp } from "antd";
  14. import File from "@/plugins/tauri-plugin-file/file";
  15. import { CopyText } from "@/components/Table/CopyText";
  16. export default function CalculateListPage() {
  17. let { fileId } = useParams();
  18. const [data, setData] = useState<FileItem[]>([]);
  19. const [removeList, setRemoveList] = useState<string[]>([]);
  20. interface FileItem {
  21. sourceId: number;
  22. ids: string;
  23. hash: string;
  24. count: number;
  25. firstItem: insertSearchFilesPasamsType;
  26. otherItems: insertSearchFilesPasamsType[];
  27. }
  28. const appendData = async () => {
  29. const [isError, searchDuplicateFileRes] = await searchDuplicateFile({
  30. sourceId: `${fileId}`,
  31. });
  32. if (!isError) {
  33. typeof searchDuplicateFileRes === "string" &&
  34. (await tauriMessage(searchDuplicateFileRes, {
  35. title: "查询失败",
  36. type: "error",
  37. }));
  38. console.log(searchDuplicateFileRes);
  39. }
  40. if (Array.isArray(searchDuplicateFileRes)) {
  41. const newData: any[] = [];
  42. await searchDuplicateFileRes.reduce(
  43. async (prevPromise: any, currentFile: any) => {
  44. // 等待上一个 Promise 完成
  45. await prevPromise;
  46. const ids = currentFile.ids.split(",");
  47. const firstItem = await get_fileInfo_by_id(ids[0], `${fileId}`);
  48. const otherItems = await Promise.allSettled(
  49. ids
  50. .map((id: string) => {
  51. if (id === ids[0]) {
  52. return false;
  53. }
  54. return get_fileInfo_by_id(id, `${fileId}`);
  55. })
  56. .filter((elm: any) => elm)
  57. );
  58. newData.push({
  59. ...currentFile,
  60. firstItem: firstItem[0],
  61. otherItems: otherItems
  62. .map((elm) => {
  63. if (elm.status === "fulfilled" && !elm.value[1]) {
  64. setRemoveList()
  65. return elm.value[0];
  66. }
  67. return false;
  68. })
  69. .filter((elm: any) => elm),
  70. });
  71. return Promise.resolve(0);
  72. },
  73. Promise.resolve(0)
  74. );
  75. setData(newData);
  76. }
  77. };
  78. useEffect(() => {
  79. appendData();
  80. }, []);
  81. const onChange = (
  82. checkedValues: string[]
  83. ) => {
  84. console.log("checked = ", checkedValues);
  85. if (Array.isArray(checkedValues)) {
  86. // setRemoveList(checkedValues.filter(elm => typeof elm === 'string'));
  87. setRemoveList(checkedValues)
  88. }
  89. // value={removeList}
  90. };
  91. const CheckboxContent = (item: insertSearchFilesPasamsType) => (
  92. <div className={styles.CheckboxContent}>
  93. <div className={styles.path}>
  94. <CopyText width="300px" color="#333" ellipsisLine={1} name={item.path || ''}></CopyText>
  95. </div>
  96. <div className={styles.modified_time}>
  97. <CopyText width="100px" color="#333" name={item.modified_time || ''}></CopyText>
  98. </div>
  99. <div className={styles.modified_time}>
  100. <CopyText width="100px" color="#333" name={item.file_size || ''}></CopyText>
  101. </div>
  102. <div className={styles.modified_time}>
  103. <CopyText width="100px" color="#333" ellipsisLine={1} name={item.name || ''}></CopyText>
  104. </div>
  105. </div>
  106. );
  107. async function removeFilesByDB() {
  108. const filesRes = await Promise.allSettled(removeList.map(path => File.rmFile(path)))
  109. if(removeList.length === 1) {
  110. console.log(106, filesRes);
  111. if(filesRes[0].status === "fulfilled" && filesRes[0].value.code === 200) {
  112. setRemoveList([])
  113. del_file_by_id(
  114. removeList[0],
  115. `${fileId}`
  116. );
  117. message.success(`${removeList[0]} 删除成功!`)
  118. appendData();
  119. return
  120. }
  121. await tauriMessage(removeList[0], {
  122. title: "删除失败",
  123. type: "error",
  124. });
  125. }
  126. const rmSuccess = filesRes.filter(res => {
  127. console.log(116, res);
  128. return res.status === 'fulfilled' && res.value.code === 200
  129. })
  130. if (rmSuccess.length) {
  131. await rmSuccess.reduce(async(prev: any, item: any)=> {
  132. await prev();
  133. console.log(119, item.value.data);
  134. return del_file_by_id(
  135. item.value.data,
  136. `${fileId}`
  137. );
  138. }, Promise.resolve(0));
  139. message.success( `${rmSuccess.length}个文件删除成功! ${filesRes.length - rmSuccess.length}个文件删除失败!`)
  140. appendData();
  141. return;
  142. }
  143. await tauriMessage('当前操作异常,请重新尝试!', {
  144. title: "删除失败",
  145. type: "error",
  146. });
  147. }
  148. return (
  149. <div className={styles.CalculateListPage}>
  150. <div
  151. style={{
  152. padding: "24px",
  153. }}
  154. >
  155. <Space>
  156. <Button type="primary" danger onClick={() => removeFilesByDB()}>
  157. 删除选中的文件
  158. </Button>
  159. <Button type="primary">统一移动到指定目录</Button>
  160. <Button type="primary">导出</Button>
  161. </Space>
  162. <div style={{ marginBottom: "12px" }}></div>
  163. <Checkbox.Group onChange={onChange} style={{ width: "100%" }} value={removeList}>
  164. <div style={{ width: "100%" }}>
  165. {data.map((item: FileItem) => (
  166. <div
  167. key={item.hash}
  168. style={{
  169. backgroundColor: 'var(--color-2)',
  170. marginBottom: '24px'
  171. }}
  172. >
  173. <div className={styles.CheckboxGroup}>
  174. <Checkbox value={item.firstItem.path}>
  175. {CheckboxContent(item.firstItem)}
  176. </Checkbox>
  177. </div>
  178. <div
  179. style={{
  180. border: '1px solid var(--color-1)',
  181. padding: "12px 3px",
  182. }}
  183. className={styles.CheckboxGroup}
  184. >
  185. {item.otherItems.map((otherItem) => (
  186. <div key={otherItem.path}>
  187. <Checkbox value={otherItem.path}>
  188. {CheckboxContent(otherItem)}
  189. </Checkbox>
  190. </div>
  191. ))}
  192. </div>
  193. </div>
  194. ))}
  195. </div>
  196. </Checkbox.Group>
  197. </div>
  198. </div>
  199. );
  200. }