- {(libsQ.data ?? []).map((l) => (
-
-
- {l.name}
- #{l.id}
-
-
{l.root_path}
-
-
- {
- fileRefs.current[l.id] = el;
- }}
- type="file"
- multiple
- accept=".cbz,.zip,.pdf,.epub,.txt,.md"
- className="hidden"
- onChange={(e) => {
- void onFiles(l.id, e.target.files);
- e.target.value = "";
- }}
- />
-
- 白名单:cbz/zip/pdf/epub/txt/md
-
-
+
+
库管理
+
+ {libsQ.isPending && (
+
+ {Array.from({ length: 3 }).map((_, i) => (
+
))}
- {(libsQ.data ?? []).length === 0 && !libsQ.isPending && (
-
还没有库,用上方表单创建。
- )}
+ )}
+
+ {libs.map((l) => (
+
e.preventDefault()} onDrop={(e) => onDrop(e, l.id)}>
+
+
+ {l.name}
+ #{l.id}
+
+ {l.root_path}
+
+
+
+ {
+ fileRefs.current[l.id] = el;
+ }}
+ type="file"
+ multiple
+ accept=".cbz,.zip,.pdf,.epub,.txt,.md"
+ className="hidden"
+ onChange={(e) => {
+ void onFiles(l.id, e.target.files);
+ e.target.value = "";
+ }}
+ />
+
+ 白名单:cbz/zip/pdf/epub/txt/md · 也可直接拖文件进卡片
+
+
+ ))}
+ {libs.length === 0 && !libsQ.isPending &&
还没有库,用上方表单创建。
}
);
diff --git a/frontend/src/pages/admin/Users.tsx b/frontend/src/pages/admin/Users.tsx
index ae48636..03bc73e 100644
--- a/frontend/src/pages/admin/Users.tsx
+++ b/frontend/src/pages/admin/Users.tsx
@@ -2,9 +2,16 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useState, type FormEvent } from "react";
import { api } from "../../api/client";
import { useAuth } from "../../auth/AuthContext";
-import { TopBar } from "../../components/TopBar";
import { toast } from "../../components/Toaster";
-import { btn, btnPrimary, card, input } from "../../components/ui";
+import {
+ AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent,
+ AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger,
+} from "@/components/ui/alert-dialog";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
+import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
+import { Skeleton } from "@/components/ui/skeleton";
export default function AdminUsers() {
const qc = useQueryClient();
@@ -39,55 +46,68 @@ export default function AdminUsers() {
}
return (
-
-
-
-
用户管理
-
-
-
-
- | ID |
- 用户名 |
- 角色 |
- 创建时间 |
- |
-
-
-
+
+
用户管理
+
+ {usersQ.isPending ? (
+
+ ) : (
+
+
+
+ ID
+ 用户名
+ 角色
+ 创建时间
+
+
+
+
{(usersQ.data ?? []).map((x) => (
-
- | {x.id} |
- {x.username} |
- {x.role} |
- {x.created_at.slice(0, 19).replace("T", " ")} |
-
-
- |
-
+
+ {x.id}
+ {x.username}
+ {x.role}
+ {x.created_at.slice(0, 19).replace("T", " ")}
+
+
+
+
+
+
+
+ 删除用户 {x.username}?
+ 该用户的阅读进度与书签一并删除。
+
+
+ 取消
+ del.mutate(x.id)}>
+ 删除
+
+
+
+
+
+
))}
-
-
-
+
+
+ )}
);
}