1// lib/actions.ts
2'use server';
3
4import { revalidatePath } from 'next/cache';
5import { redirect } from 'next/navigation';
6import { z } from 'zod';
7
8const PostSchema = z.object({
9 title: z.string().min(3, "标题至少需要3个字符"),
10 content: z.string().min(10, "内容至少需要10个字符")
11});
12
13export async function createPost(formData: FormData) {
14 const data = {
15 title: formData.get('title'),
16 content: formData.get('content')
17 };
18
19 const result = PostSchema.safeParse(data);
20
21 if (!result.success) {
22 return { error: result.error.flatten() };
23 }
24
25 const post = await db.post.create({
26 data: result.data
27 });
28
29 revalidatePath('/blog');
30 redirect('/blog');
31}
32
33// app/blog/new/page.tsx
34import { createPost } from '@/lib/actions';
35
36export default function NewPostPage() {
37 return (
38 <form action={createPost} className="space-y-4 max-w-lg mx-auto">
39 <div>
40 <label htmlFor="title" className="block text-sm font-medium">
41 标题
42 </label>
43 <input
44 type="text"
45 name="title"
46 id="title"
47 required
48 className="mt-1 block w-full rounded-md border-gray-300"
49 />
50 </div>
51 <div>
52 <label htmlFor="content" className="block text-sm font-medium">
53 内容
54 </label>
55 <textarea
56 name="content"
57 id="content"
58 required
59 rows={5}
60 className="mt-1 block w-full rounded-md border-gray-300"
61 />
62 </div>
63 <button
64 type="submit"
65 className="w-full py-2 px-4 bg-blue-500 text-white rounded-md"
66 >
67 发布
68 </button>
69 </form>
70 );
71}