feat: 创建博客支持slug字段了
This commit is contained in:
@@ -5,6 +5,9 @@ export class CreateBlogDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
title: string;
|
title: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
slug: string;// 允许空串,但如果为空则需要手动设置为null,防止数据库唯一键冲突
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
description: string;
|
description: string;
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ export class BlogService {
|
|||||||
.digest('hex');
|
.digest('hex');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (typeof blog.slug === 'string' && blog.slug.trim().length === 0) {
|
||||||
|
blog.slug = null;
|
||||||
|
}
|
||||||
|
|
||||||
const newBlog = this.blogRepository.create(blog);
|
const newBlog = this.blogRepository.create(blog);
|
||||||
return this.blogRepository.save(newBlog);
|
return this.blogRepository.save(newBlog);
|
||||||
|
|||||||
@@ -27,12 +27,37 @@ export default function AddBlog({ children, onRefresh }: AddBlogProps) {
|
|||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [blog, setBlog] = useState({
|
const [blog, setBlog] = useState({
|
||||||
title: "",
|
title: "",
|
||||||
|
slug: "",
|
||||||
description: "",
|
description: "",
|
||||||
contentUrl: "",
|
contentUrl: "",
|
||||||
permissions: [] as BlogPermission[],
|
permissions: [] as BlogPermission[],
|
||||||
password: "",
|
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 () => {
|
const handleSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await AdminAPI.createBlog({
|
const res = await AdminAPI.createBlog({
|
||||||
@@ -44,6 +69,7 @@ export default function AddBlog({ children, onRefresh }: AddBlogProps) {
|
|||||||
toast.success("添加成功");
|
toast.success("添加成功");
|
||||||
setBlog({
|
setBlog({
|
||||||
title: '',
|
title: '',
|
||||||
|
slug: '',
|
||||||
description: '',
|
description: '',
|
||||||
contentUrl: '',
|
contentUrl: '',
|
||||||
permissions: [],
|
permissions: [],
|
||||||
@@ -92,6 +118,17 @@ export default function AddBlog({ children, onRefresh }: AddBlogProps) {
|
|||||||
onChange={(e) => setBlog({ ...blog, description: e.target.value })}
|
onChange={(e) => setBlog({ ...blog, description: e.target.value })}
|
||||||
/>
|
/>
|
||||||
</div>
|
</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">
|
<div className="grid grid-cols-4 items-center gap-4">
|
||||||
<Label htmlFor="contentUrl" className="text-right">
|
<Label htmlFor="contentUrl" className="text-right">
|
||||||
文章URL
|
文章URL
|
||||||
@@ -137,8 +174,13 @@ export default function AddBlog({ children, onRefresh }: AddBlogProps) {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter >
|
<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" variant='secondary' onClick={() => setOpen(false)}>取消</Button>
|
||||||
<Button type="button" onClick={handleSubmit}>保存</Button>
|
<Button type="button" onClick={handleSubmit}>保存</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { clientFetch } from "../client";
|
|||||||
import { Blog } from "@/lib/types/blog";
|
import { Blog } from "@/lib/types/blog";
|
||||||
import { BlogPermission } from "@/lib/types/Blog.Permission.enum";
|
import { BlogPermission } from "@/lib/types/Blog.Permission.enum";
|
||||||
import { Role } from "@/lib/types/role";
|
import { Role } from "@/lib/types/role";
|
||||||
|
import { APIError } from "../common";
|
||||||
|
|
||||||
export interface UserEntity {
|
export interface UserEntity {
|
||||||
userId: string;
|
userId: string;
|
||||||
@@ -87,9 +88,28 @@ export async function updateResource(id: string, data: UpdateResourceParams) {
|
|||||||
interface CreateBlogParams {
|
interface CreateBlogParams {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
slug: string;
|
||||||
contentUrl: string;
|
contentUrl: string;
|
||||||
|
permissions: BlogPermission[];
|
||||||
|
password: string;
|
||||||
}
|
}
|
||||||
export async function createBlog(data: CreateBlogParams) {
|
export async function createBlog(data: CreateBlogParams) {
|
||||||
|
data.title = data.title.trim()
|
||||||
|
data.description = data.description.trim()
|
||||||
|
data.slug = data.slug.trim()
|
||||||
|
data.contentUrl = data.contentUrl.trim()
|
||||||
|
data.password = data.password.trim()
|
||||||
|
|
||||||
|
if (data.title.length === 0) {
|
||||||
|
throw new APIError('标题不得为空')
|
||||||
|
}
|
||||||
|
if (data.description.length === 0) {
|
||||||
|
throw new APIError('描述不得为空')
|
||||||
|
}
|
||||||
|
if (data.contentUrl.length === 0) {
|
||||||
|
throw new APIError('文章链接不得为空')
|
||||||
|
}
|
||||||
|
|
||||||
return clientFetch<Blog>('/api/admin/web/blog', {
|
return clientFetch<Blog>('/api/admin/web/blog', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
|
|||||||
Reference in New Issue
Block a user