From 8e9b23e7e8f5205b43c140439503c5f834926634 Mon Sep 17 00:00:00 2001 From: ditiqi Date: Wed, 22 Jan 2025 19:25:55 +0800 Subject: [PATCH] add --- apps/server/src/models/post/post.router.ts | 1 + apps/server/src/models/post/post.service.ts | 1 + .../PostEditor/context/PostEditorContext.tsx | 113 ++++++++++++++++++ .../PostEditor/layout/PostEditorLayout.tsx | 22 ++++ apps/web/src/routes/index.tsx | 60 ++++++---- 5 files changed, 177 insertions(+), 20 deletions(-) create mode 100644 apps/web/src/components/models/post/PostEditor/context/PostEditorContext.tsx create mode 100644 apps/web/src/components/models/post/PostEditor/layout/PostEditorLayout.tsx diff --git a/apps/server/src/models/post/post.router.ts b/apps/server/src/models/post/post.router.ts index 40398bb..3181ae7 100755 --- a/apps/server/src/models/post/post.router.ts +++ b/apps/server/src/models/post/post.router.ts @@ -35,6 +35,7 @@ export class PostRouter { } as Prisma.InputJsonObject; // 明确指定类型 return await this.postService.create(input, { staff }); }), + softDeleteByIds: this.trpc.protectProcedure .input( z.object({ diff --git a/apps/server/src/models/post/post.service.ts b/apps/server/src/models/post/post.service.ts index 0f3f6e0..e6207bf 100755 --- a/apps/server/src/models/post/post.service.ts +++ b/apps/server/src/models/post/post.service.ts @@ -27,6 +27,7 @@ export class PostService extends BaseService { params: { staff?: UserProfile; tx?: Prisma.PostDelegate }, ) { args.data.authorId = params?.staff?.id; + // args.data.resources const result = await super.create(args); EventBus.emit('dataChanged', { type: ObjectType.POST, diff --git a/apps/web/src/components/models/post/PostEditor/context/PostEditorContext.tsx b/apps/web/src/components/models/post/PostEditor/context/PostEditorContext.tsx new file mode 100644 index 0000000..2f6bd5c --- /dev/null +++ b/apps/web/src/components/models/post/PostEditor/context/PostEditorContext.tsx @@ -0,0 +1,113 @@ +import { createContext, useContext, ReactNode, useEffect } from "react"; +import { useForm, FormProvider, SubmitHandler } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { z } from "zod"; +import { api, usePost } from "@nice/client"; +// import { PostDto, PostLevel, PostStatus } from "@nice/common"; +// import { api, usePost } from "@nice/client"; +import toast from "react-hot-toast"; +import { useNavigate } from "react-router-dom"; +import { Post, PostType } from "@nice/common"; +// 定义帖子表单验证 Schema + +const postSchema = z.object({ + title: z.string().min(1, "标题不能为空"), + content: z.string().min(1, "内容不能为空"), + resources: z.array(z.string()).nullish(), + isPublic: z.boolean(), + signature: z.string().nullish(), +}); +// 定义课程表单验证 Schema + +export type PostFormData = z.infer; +interface PostEditorContextType { + onSubmit: SubmitHandler; + editId?: string; // 添加 editId + part?: string; + // course?: PostDto; +} +interface PostFormProviderProps { + children: ReactNode; + editId?: string; // 添加 editId 参数 + part?: string; +} +const PostEditorContext = createContext(null); +export function PostFormProvider({ children, editId }: PostFormProviderProps) { + const { create, update } = usePost(); + const { data: post }: { data: Post } = api.post.findById.useQuery( + { + id: editId, + }, + { enabled: !!editId } + ); + const navigate = useNavigate(); + const methods = useForm({ + resolver: zodResolver(postSchema), + defaultValues: { + resources: [], + }, + }); + useEffect(() => { + if (post) { + const formData = { + title: post.title, + content: post.content, + signature: (post.meta as any)?.signature, + }; + methods.reset(formData as any); + } + }, [post, methods]); + const onSubmit: SubmitHandler = async ( + data: PostFormData + ) => { + try { + if (editId) { + // await update.mutateAsync({ + // where: { id: editId }, + // data: { + // ...data + // } + // }) + toast.success("课程更新成功!"); + } else { + const result = await create.mutateAsync({ + data: { + type: PostType.POST, + ...data, + resources: data.resources?.length + ? { + connect: data.resources.map((id) => ({ + id, + })), + } + : undefined, + }, + }); + // navigate(`/course/${result.id}/editor`, { replace: true }); + toast.success("发送成功!"); + } + methods.reset(data); + } catch (error) { + console.error("Error submitting form:", error); + toast.error("操作失败,请重试!"); + } + }; + return ( + + {children} + + ); +} + +export const usePostEditor = () => { + const context = useContext(PostEditorContext); + if (!context) { + throw new Error("usePostEditor must be used within PostFormProvider"); + } + return context; +}; diff --git a/apps/web/src/components/models/post/PostEditor/layout/PostEditorLayout.tsx b/apps/web/src/components/models/post/PostEditor/layout/PostEditorLayout.tsx new file mode 100644 index 0000000..06e6fa6 --- /dev/null +++ b/apps/web/src/components/models/post/PostEditor/layout/PostEditorLayout.tsx @@ -0,0 +1,22 @@ +import { ReactNode, useEffect, useState } from "react"; +import { Outlet, useNavigate, useParams } from "react-router-dom"; + +import { motion } from "framer-motion"; +import { NavItem } from "@nice/client"; +import { PostFormProvider } from "../context/PostEditorContext"; + +export default function PostEditorLayout() { + const { id } = useParams(); + + return ( + <> + +
+
+ +
+
+
+ + ); +} diff --git a/apps/web/src/routes/index.tsx b/apps/web/src/routes/index.tsx index 5d29743..5364c1d 100755 --- a/apps/web/src/routes/index.tsx +++ b/apps/web/src/routes/index.tsx @@ -20,6 +20,7 @@ import CourseContentForm from "../components/models/course/editor/form/CourseCon import { CourseGoalForm } from "../components/models/course/editor/form/CourseGoalForm"; import CourseSettingForm from "../components/models/course/editor/form/CourseSettingForm"; import CourseEditorLayout from "../components/models/course/editor/layout/CourseEditorLayout"; +import PostEditorLayout from "../components/models/post/PostEditor/layout/PostEditorLayout"; interface CustomIndexRouteObject extends IndexRouteObject { name?: string; @@ -57,8 +58,22 @@ export const routes: CustomRouteObject[] = [ { index: true, element: , - } - + }, + ], + }, + { + path: "post", + children: [ + { + path: ":id?/editor", + element: , + children: [ + { + index: true, + element: , + }, + ], + }, ], }, { @@ -67,24 +82,29 @@ export const routes: CustomRouteObject[] = [ { path: ":id?/editor", element: , - children: [{ - index: true, - element: - }, - { - path: 'goal', - element: - }, - { - path: 'content', - element: - }, - { - path: 'setting', - element: - } - ] - } + children: [ + { + index: true, + element: , + }, + { + path: "goal", + element: , + }, + { + path: "content", + element: ( + + ), + }, + { + path: "setting", + element: ( + + ), + }, + ], + }, ], }, {