init
This commit is contained in:
237
src/components/move-file-dialog.tsx
Normal file
237
src/components/move-file-dialog.tsx
Normal file
@@ -0,0 +1,237 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { FileType, getFilePage } from "@/apis/file";
|
||||
import { Folder, FolderInput, CircleAlert, MoveRight } from "lucide-react";
|
||||
import clsx from "clsx";
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||
import { DirectoryBreadcrumb } from "@/components/directory-breadcrumb";
|
||||
import { DataTable } from "@/components/data-table";
|
||||
import { Pagination } from "@/components/pagination";
|
||||
import { useMoveFile } from "@/hooks/use-move-flie";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { getCoreRowModel, useReactTable } from "@tanstack/react-table";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
export function useColumns(handleChangeParentId: any) {
|
||||
return [
|
||||
{
|
||||
accessorKey: "fileName",
|
||||
header: "目录名",
|
||||
size: 200,
|
||||
cell: ({ row }: any) => (
|
||||
<div
|
||||
className={clsx(
|
||||
"w-full flex items-center gap-1 break-all",
|
||||
"cursor-pointer hover:underline hover:text-primary group",
|
||||
)}
|
||||
onClick={() => {
|
||||
handleChangeParentId(row?.original);
|
||||
}}
|
||||
>
|
||||
<Folder size={18} className="text-amber-500 group-hover:hidden" />
|
||||
<FolderInput
|
||||
size={18}
|
||||
className="text-amber-500 group-hover:block hidden"
|
||||
/>
|
||||
<span>{row.getValue("fileName")}</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
type MoveFileDialogProps = {
|
||||
open: boolean;
|
||||
setOpen: (open: boolean) => void;
|
||||
data?: any;
|
||||
refetch?: () => void;
|
||||
params: any;
|
||||
};
|
||||
|
||||
export function MoveFileDialog({
|
||||
open,
|
||||
setOpen,
|
||||
data,
|
||||
refetch,
|
||||
params,
|
||||
}: MoveFileDialogProps) {
|
||||
// 选中行
|
||||
const [rowSelection, setRowSelection] = useState({});
|
||||
// 当前打开的目录层级
|
||||
const [openDirectorys, setOpenDirectorys] = useState([]);
|
||||
// 文件目录ID
|
||||
const [parentId, setParentId] = useState(0);
|
||||
// 分页
|
||||
const [pagination, setPagination] = useState({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
// 查询数据
|
||||
const query = useQuery<any>({
|
||||
queryKey: ["moveFiles", pagination, parentId, params],
|
||||
queryFn: () =>
|
||||
getFilePage({
|
||||
...params,
|
||||
parentId: parentId || 0,
|
||||
pageSize: pagination.pageSize,
|
||||
pageNo: pagination.pageIndex + 1,
|
||||
fileType: FileType.DIRECTORY,
|
||||
}).then((res) => res.data),
|
||||
enabled: open,
|
||||
});
|
||||
|
||||
// 切换上级ID
|
||||
const handleChangeParentId = (record: any) => {
|
||||
setParentId(record.id);
|
||||
// 重置分页
|
||||
table.setPageIndex(0);
|
||||
// @ts-ignore
|
||||
setOpenDirectorys((prev: any) => [...prev, record]);
|
||||
// 重置选中数据
|
||||
table.resetRowSelection();
|
||||
};
|
||||
|
||||
// 过滤当前目录
|
||||
const list = useMemo(
|
||||
() =>
|
||||
query?.data?.entityList?.filter((item: any) => item.id !== data?.id) ||
|
||||
[],
|
||||
[query, data],
|
||||
);
|
||||
// 表格
|
||||
const columns = useColumns(handleChangeParentId);
|
||||
const table = useReactTable({
|
||||
data: list,
|
||||
columns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
manualPagination: false,
|
||||
rowCount: query?.data?.totalCount || 0,
|
||||
pageCount: query?.data?.pageCount || 0,
|
||||
onPaginationChange: setPagination,
|
||||
autoResetPageIndex: false,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
state: {
|
||||
pagination,
|
||||
rowSelection,
|
||||
},
|
||||
});
|
||||
|
||||
const changeOpenDirectorys = (record?: any) => {
|
||||
setParentId(record?.id);
|
||||
// 重置分页
|
||||
table.setPageIndex(0);
|
||||
// @ts-ignore
|
||||
setOpenDirectorys((prev: any[]) => {
|
||||
const index = prev.findIndex((item: any) => item.id === record?.id);
|
||||
if (index > -1) {
|
||||
return [...prev.slice(0, index + 1)];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
// 重置选中数据
|
||||
table.resetRowSelection();
|
||||
};
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
setParentId(0);
|
||||
// 重置分页
|
||||
table.setPageIndex(0);
|
||||
// @ts-ignore
|
||||
setOpenDirectorys([]);
|
||||
// 重置选中数据
|
||||
table.resetRowSelection();
|
||||
};
|
||||
|
||||
const { move, moveIsPending } = useMoveFile({
|
||||
onSuccess: () => {
|
||||
refetch?.();
|
||||
setOpen(false);
|
||||
},
|
||||
});
|
||||
|
||||
const handleSubmit = () => {
|
||||
move({
|
||||
...data,
|
||||
parentId,
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
reset();
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
const currentDirectory = useMemo(
|
||||
() => openDirectorys?.[openDirectorys?.length - 1],
|
||||
[openDirectorys],
|
||||
);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogContent className="w-[680px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
{data?.fileType === FileType.DIRECTORY ? "移动目录" : "移动文件"}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="overflow-hidden space-y-2">
|
||||
<DirectoryBreadcrumb
|
||||
directorys={openDirectorys}
|
||||
onChangeDirectorys={changeOpenDirectorys}
|
||||
/>
|
||||
<div className="max-h-[400px] overflow-y-auto relative border rounded-lg">
|
||||
<DataTable table={table} query={query} />
|
||||
<Pagination
|
||||
table={table}
|
||||
simple
|
||||
className="p-2 justify-end sticky bottom-0 left-0 right-0 z-10 bg-white"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 text-sm overflow-hidden">
|
||||
<span className="flex-1 overflow-hidden text-primary clamp-1 truncate p-2 rounded-lg bg-gray-100">
|
||||
{data?.fileName}
|
||||
</span>
|
||||
<MoveRight size={16} className="flex-none" />
|
||||
<span className="flex-1 overflow-hidden text-amber-500 clamp-1 truncate inline-flex items-center gap-1 p-2 rounded-lg bg-gray-100">
|
||||
<Folder size={16} className="flex-none " />
|
||||
{currentDirectory?.fileName || "根目录"}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Alert className="!bg-amber-50 !border-amber-200">
|
||||
<CircleAlert />
|
||||
<AlertTitle>
|
||||
您确定要将{data?.fileType === FileType.DIRECTORY ? "目录" : "文件"}
|
||||
移动到该目录下吗?
|
||||
</AlertTitle>
|
||||
<AlertDescription>
|
||||
如果是目录,则目录下的所有文件和子目录都会被移动
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">取消</Button>
|
||||
</DialogClose>
|
||||
<Button type="submit" disabled={moveIsPending} onClick={handleSubmit}>
|
||||
{moveIsPending && <Spinner />}确定
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user