188 lines
7.3 KiB
TypeScript
188 lines
7.3 KiB
TypeScript
'use client'
|
||
|
||
import { Button } from "@/components/ui/button";
|
||
import {
|
||
Dialog,
|
||
DialogContent,
|
||
DialogDescription,
|
||
DialogFooter,
|
||
DialogHeader,
|
||
DialogTitle,
|
||
DialogTrigger,
|
||
} from "@/components/ui/dialog"
|
||
import { Input } from "@/components/ui/input";
|
||
import { Label } from "@/components/ui/label";
|
||
import { BlogPermission } from "@/lib/types/Blog.Permission.enum";
|
||
import { useState } from "react";
|
||
import { toast } from "sonner";
|
||
import { BlogPermissionCheckBoxs } from "./BlogPermissionCheckBoxs";
|
||
import { AdminAPI } from "@/lib/api/client";
|
||
|
||
interface AddBlogProps {
|
||
children: React.ReactNode;
|
||
onRefresh: () => void;
|
||
}
|
||
|
||
export default function AddBlog({ children, onRefresh }: AddBlogProps) {
|
||
const [open, setOpen] = useState(false);
|
||
const [blog, setBlog] = useState({
|
||
title: "",
|
||
slug: "",
|
||
description: "",
|
||
contentUrl: "",
|
||
permissions: [] as BlogPermission[],
|
||
password: "",
|
||
});
|
||
|
||
const handleCopyShareURL = () => {
|
||
const slug = blog.slug.trim();
|
||
if (slug.length === 0) {
|
||
return toast.warning('请先填写Slug')
|
||
}
|
||
|
||
let url = `${window.location.origin}/blog/${slug}`;
|
||
|
||
const password = blog.password.trim();
|
||
if (blog.permissions.includes(BlogPermission.ByPassword)) {
|
||
if (password.length === 0) {
|
||
return toast.warning('开启了密码保护,但没有填写有效的密码,无法生成有效URL')
|
||
} else {
|
||
url += `?p=${blog.password.trim()}`;
|
||
}
|
||
}
|
||
|
||
navigator.clipboard.writeText(url).then(() => {
|
||
toast.success('复制成功');
|
||
}, () => {
|
||
toast.error('复制失败,请手动复制');
|
||
});
|
||
};
|
||
|
||
const handleSubmit = async () => {
|
||
try {
|
||
const res = await AdminAPI.createBlog({
|
||
...blog,
|
||
});
|
||
if (res) {
|
||
setOpen(false);
|
||
onRefresh();
|
||
toast.success("添加成功");
|
||
setBlog({
|
||
title: '',
|
||
slug: '',
|
||
description: '',
|
||
contentUrl: '',
|
||
permissions: [],
|
||
password: '',
|
||
})
|
||
} else {
|
||
throw new Error();
|
||
}
|
||
} catch (error) {
|
||
toast.error((error as Error).message || "添加失败");
|
||
}
|
||
}
|
||
|
||
return (
|
||
<Dialog open={open} onOpenChange={setOpen}>
|
||
<DialogTrigger asChild>
|
||
{children}
|
||
</DialogTrigger>
|
||
<DialogContent className="sm:max-w-100">
|
||
<DialogHeader>
|
||
<DialogTitle>添加博客</DialogTitle>
|
||
<DialogDescription>
|
||
保存前请确认博客信息填写正确、权限配置合理
|
||
</DialogDescription>
|
||
</DialogHeader>
|
||
<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) => setBlog({ ...blog, title: e.target.value })}
|
||
/>
|
||
</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) => setBlog({ ...blog, description: e.target.value })}
|
||
/>
|
||
</div>
|
||
<div className="grid grid-cols-4 items-center gap-4">
|
||
<Label htmlFor="slug" className="text-right">
|
||
Slug
|
||
</Label>
|
||
<Input
|
||
id="slug"
|
||
className="col-span-3"
|
||
value={blog.slug}
|
||
onChange={(e) => setBlog({ ...blog, slug: e.target.value })}
|
||
/>
|
||
</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) => setBlog({ ...blog, contentUrl: e.target.value })}
|
||
/>
|
||
</div>
|
||
<div className="grid grid-cols-4 items-center gap-4">
|
||
<Label className="text-right">
|
||
文章权限
|
||
</Label>
|
||
<div className="col-span-3">
|
||
{
|
||
<BlogPermissionCheckBoxs
|
||
permissions={blog.permissions}
|
||
onCheckedChange={(p, n) => setBlog({
|
||
...blog,
|
||
permissions: n ?
|
||
[...blog.permissions, p] :
|
||
[...blog.permissions].filter(p => p !== p),
|
||
})}
|
||
/>
|
||
}
|
||
</div>
|
||
</div>
|
||
{
|
||
blog.permissions.includes(BlogPermission.ByPassword) &&
|
||
<div className="grid grid-cols-4 items-center gap-4">
|
||
<Label htmlFor="password" className="text-right">
|
||
密码
|
||
</Label>
|
||
<Input
|
||
id="password"
|
||
className="col-span-3"
|
||
value={blog.password}
|
||
onChange={(e) => setBlog({ ...blog, password: e.target.value })}
|
||
/>
|
||
</div>
|
||
}
|
||
</div>
|
||
<DialogFooter >
|
||
<div className="flex justify-between w-full">
|
||
<Button type="button" variant='outline' onClick={handleCopyShareURL}>复制分享链接</Button>
|
||
<div>
|
||
<Button type="button" variant='secondary' onClick={() => setOpen(false)}>取消</Button>
|
||
<Button type="button" onClick={handleSubmit}>保存</Button>
|
||
</div>
|
||
</div>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
)
|
||
} |