diff --git a/packages/design/components/Topic/Comment.tsx b/packages/design/components/Topic/Comment.tsx index 59cbc7a1f..3165faaa0 100644 --- a/packages/design/components/Topic/Comment.tsx +++ b/packages/design/components/Topic/Comment.tsx @@ -184,16 +184,18 @@ const Comment: FC = ({ - {user.id === creator.id ? ( + {user.id === creator.id && ( <> - + {!replies?.length && ( + + 编辑 + + )} - ) : null} + )} )} diff --git a/packages/design/components/Topic/__test__/Comment.spec.tsx b/packages/design/components/Topic/__test__/Comment.spec.tsx index f2ac321dd..b7f3537a0 100644 --- a/packages/design/components/Topic/__test__/Comment.spec.tsx +++ b/packages/design/components/Topic/__test__/Comment.spec.tsx @@ -99,6 +99,18 @@ describe('Normal Comment', () => { expect(getByText('删除')).toBeInTheDocument(); }); + it('hide edit button if there are subreplies', () => { + const user = { ...mockedCurrentUser, id: 1 }; + const props = buildProps(false, repliesComment, '233', 233, user); + const { container } = render(); + // 选取主评论的操作区域 + const actions = container.querySelector( + '.bgm-comment__box > .bgm-comment__opinions', + )?.textContent; + expect(actions?.includes('编辑')).toBeFalsy(); + expect(actions?.includes('删除')).toBeTruthy(); + }); + it('do not show opinions if not login', () => { const props = buildProps(false, singleComment, '233', 233, null as any); const { container } = render(); diff --git a/packages/website/src/hooks/use-group-post.ts b/packages/website/src/hooks/use-group-post.ts new file mode 100644 index 000000000..d22280a7b --- /dev/null +++ b/packages/website/src/hooks/use-group-post.ts @@ -0,0 +1,19 @@ +import { ok } from 'oazapfts'; +import type { KeyedMutator } from 'swr'; +import useSWR from 'swr'; + +import { ozaClient } from '@bangumi/client'; + +export interface UseGroupPostRet { + data: ozaClient.GroupReply; + mutate: KeyedMutator; +} + +function useGroupPost(id: number): UseGroupPostRet { + const { data, mutate } = useSWR(`/group/post/${id}`, async () => ok(ozaClient.getGroupPost(id)), { + suspense: true, + }); + return { data, mutate }; +} + +export default useGroupPost; diff --git a/packages/website/src/pages/index/group/reply/[id].tsx b/packages/website/src/pages/index/group/reply/[id].tsx new file mode 100644 index 000000000..baf0f3bf2 --- /dev/null +++ b/packages/website/src/pages/index/group/reply/[id].tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Outlet } from 'react-router-dom'; + +import ErrorBoundary from '@bangumi/website/components/ErrorBoundary'; + +const GroupReplyPage = () => ( + 数据库中没有查询到指定话题,话题可能正在审核或已被删除。 }}> + + +); + +export default GroupReplyPage; diff --git a/packages/website/src/pages/index/group/reply/[id]/edit.module.less b/packages/website/src/pages/index/group/reply/[id]/edit.module.less new file mode 100644 index 000000000..5750a3c2e --- /dev/null +++ b/packages/website/src/pages/index/group/reply/[id]/edit.module.less @@ -0,0 +1,14 @@ +.form { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.tipText { + display: block; + margin-bottom: 10px; +} + +.topicLink { + padding: 0 10px; +} diff --git a/packages/website/src/pages/index/group/reply/[id]/edit.tsx b/packages/website/src/pages/index/group/reply/[id]/edit.tsx new file mode 100644 index 000000000..6e229c55d --- /dev/null +++ b/packages/website/src/pages/index/group/reply/[id]/edit.tsx @@ -0,0 +1,96 @@ +import type { TopicDetail } from 'packages/client/client'; +import React, { useState } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { useSWRConfig } from 'swr'; + +import { ozaClient } from '@bangumi/client'; +import { EditorForm, toast, Typography } from '@bangumi/design'; +import useGroupPost from '@bangumi/website/hooks/use-group-post'; +import { useUser } from '@bangumi/website/hooks/use-user'; + +import styles from './edit.module.less'; + +const EditReplyPage = () => { + const { id } = useParams(); + if (!id || Number.isNaN(parseInt(id))) { + throw new Error('参数错误:post ID'); + } + const postId = parseInt(id); + + const { user } = useUser(); + if (!user) { + throw new Error('抱歉,当前操作需要登录后才能继续进行'); + } + + const { data, mutate } = useGroupPost(postId); + if (data.creator.id !== user.id) { + throw new Error('抱歉,你只能修改自己发表的帖子。'); + } + + const { mutate: mutateTopic } = useSWRConfig(); + const navigate = useNavigate(); + + const [sending, setSending] = useState(false); + const [content, setContent] = useState(data.text); + + const handleSubmit = async (text: string) => { + if (!text) { + toast('请填写回复内容', { type: 'error' }); + return; + } + setSending(true); + const response = await ozaClient.editGroupPost(postId, { text }); + if (response.status === 200) { + const topicPath = `/group/topic/${data.topicID}`; + // 确保再次回到此页面时内容是最新的,不需要向后端请求数据,因此将 revalidate 设置为 false + mutate({ ...data, text }, { revalidate: false }); + // 乐观更新回复内容 + await mutateTopic(topicPath, (topic?: TopicDetail) => { + if (!topic) { + return topic; + } + const reply = topic.replies.find((reply) => reply.id === postId); + if (reply) { + reply.text = text; + } + return topic; + }); + navigate(topicPath); + } else { + console.error(response); + toast(response.data.message, { type: 'error' }); + } + setSending(false); + }; + + return ( + <> + + 修改主题 + + {data.topicTitle} + + 的回复 + +
+ +
+ {/* TODO: add right column */} + + ); +}; + +export default EditReplyPage;