完成博客增删改查

This commit is contained in:
2025-05-16 22:10:21 +08:00
parent e782b926a4
commit 4f5f771e2b
5 changed files with 163 additions and 6 deletions

View File

@@ -0,0 +1,146 @@
"use client"
import React, { use, useState } from "react"
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Button } from "@/components/ui/button"
import { toast } from "sonner"
import { Textarea } from "@/components/ui/textarea"
import { Plus } from "lucide-react"
import { Resource } from "@/lib/types/resource"
import { AdminApi } from "@/lib/api"
import useSWR from "swr"
import { ApiError } from "next/dist/server/api-utils"
import { Skeleton } from "@/components/ui/skeleton"
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
interface BlogEditProps {
id: string;
children?: React.ReactNode;
onRefresh: () => void;
}
export default function BlogEdit({ id, children, onRefresh }: BlogEditProps) {
const [open, setOpen] = useState(false)
const { data: blog, error, isLoading, mutate } = useSWR(
open ? `/api/admin/web/blog/${id}` : null,
() => AdminApi.web.blog.get(id),
{
revalidateOnFocus: false,
revalidateOnReconnect: false,
revalidateIfStale: false,
dedupingInterval: 5000,
}
)
const handleSubmit = async () => {
if (!blog) return;
try {
await AdminApi.web.blog.update(id, {
title: blog.title,
description: blog.description,
contentUrl: blog.contentUrl,
});
toast.success("更新成功")
setOpen(false);
onRefresh();
} catch (error) {
toast.error((error as ApiError).message || "更新失败")
}
}
const handleDelete = async () => {
try {
await AdminApi.web.blog.remove(id);
toast.success("删除成功")
setOpen(false);
onRefresh();
} catch (error) {
toast.error((error as ApiError).message || "删除失败")
}
}
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
{children}
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle></DialogTitle>
</DialogHeader>
{
blog && (
<>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="title" className="text-right">
</Label>
<Input
id="title"
className="col-span-3"
value={blog.title}
onChange={(e) => mutate({ ...blog, title: e.target.value }, false)}
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="description" className="text-right">
</Label>
<Input
id="description"
className="col-span-3"
value={blog.description}
onChange={(e) => mutate({ ...blog, description: e.target.value }, false)}
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="contentUrl" className="text-right">
URL
</Label>
<Input
id="contentUrl"
className="col-span-3"
value={blog.contentUrl}
onChange={(e) => mutate({ ...blog, contentUrl: e.target.value }, false)}
/>
</div>
</div>
<DialogFooter>
<div className="w-full flex justify-between">
<div>
<Button variant='destructive' onClick={handleDelete}></Button>
</div>
<div>
<Button type="button" variant='secondary' onClick={() => setOpen(false)}></Button>
<Button type="button" onClick={handleSubmit} className="ml-5"></Button>
</div>
</div>
</DialogFooter>
</>
)
}
</DialogContent>
</Dialog>
)
}

View File

@@ -10,11 +10,13 @@ import {
} from "@/components/ui/table"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
import { Blog } from "@/lib/types/blog"
import BlogEdit from "./BlogEdit"
import { Button } from "@/components/ui/button"
interface BlogTableProps {
blogs: Blog[],
error?: string,
onRefresh?: () => void,
onRefresh: () => void,
}
export default function BlogTable({ blogs, error, onRefresh }: BlogTableProps) {
@@ -53,9 +55,9 @@ export default function BlogTable({ blogs, error, onRefresh }: BlogTableProps) {
<TableCell>{blog.description}</TableCell>
<TableCell>{blog.contentUrl}</TableCell>
<TableCell className="text-right">
{/* <ResourceEdit id={resource.id} onRefresh={() => onRefresh()}>
<BlogEdit id={blog.id} onRefresh={() => onRefresh()}>
<Button variant={'outline'} size={'sm'}></Button>
</ResourceEdit> */}
</BlogEdit>
</TableCell>
</TableRow>
))}