feat(auth): login/get/logout

This commit is contained in:
2026-02-11 10:54:43 +08:00
parent 1444cbc665
commit e17242eec3
19 changed files with 1808 additions and 302 deletions

View File

@@ -3,7 +3,7 @@
import { useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import api from "@/services/api";
import { Media, PaginatedResponse } from "@/services/types";
import { Media, PagedMedia } from "@/services/types";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Upload, Trash2, Copy } from "lucide-react";
@@ -20,8 +20,7 @@ export default function MediaPage() {
const { data, isLoading } = useQuery({
queryKey: ["media"],
queryFn: async () => {
const res = await api.get<PaginatedResponse<Media>>("/media");
return res.data;
return api.get<PagedMedia>("/media");
},
});
@@ -41,9 +40,9 @@ export default function MediaPage() {
setUploading(false);
},
onError: () => {
setUploading(false);
toast({ title: "上传失败", variant: "destructive" });
}
setUploading(false);
toast({ title: "上传失败", variant: "destructive" });
},
});
const deleteMutation = useMutation({
@@ -73,9 +72,13 @@ export default function MediaPage() {
};
if (isLoading) {
return <div className="p-8 text-center text-muted-foreground">...</div>;
return (
<div className="p-8 text-center text-muted-foreground">...</div>
);
}
const mediaItems = data?.items || [];
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
@@ -89,14 +92,14 @@ export default function MediaPage() {
disabled={uploading}
/>
<Button disabled={uploading}>
<Upload className="mr-2 h-4 w-4" />
<Upload className="mr-2 h-4 w-4" />
{uploading ? "上传中..." : "上传图片"}
</Button>
</div>
</div>
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4">
{data?.data.map((item) => (
{mediaItems.map((item: Media) => (
<Card key={item.id} className="overflow-hidden group">
<CardContent className="p-0 relative aspect-square">
<Image
@@ -124,14 +127,14 @@ export default function MediaPage() {
</div>
</CardContent>
<div className="p-2 text-xs text-muted-foreground truncate">
{format(new Date(item.created_at), "yyyy-MM-dd")}
{format(new Date(item.created_at), "yyyy-MM-dd")}
</div>
</Card>
))}
{data?.data.length === 0 && (
<div className="col-span-full text-center py-10 text-muted-foreground">
</div>
{mediaItems.length === 0 && (
<div className="col-span-full text-center py-10 text-muted-foreground">
</div>
)}
</div>
</div>