diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts index a34c3d1..dbdcbd9 100644 --- a/frontend/src/i18n.ts +++ b/frontend/src/i18n.ts @@ -131,6 +131,12 @@ export const i18nData = { "Are you sure you want to delete the file": "Are you sure you want to delete the file", + // 评论删除相关 + "Delete Comment": "Delete Comment", + "Are you sure you want to delete this comment? This action cannot be undone.": + "Are you sure you want to delete this comment? This action cannot be undone.", + "Comment deleted successfully": "Comment deleted successfully", + // New translations "Change Avatar": "Change Avatar", "Change Username": "Change Username", @@ -344,6 +350,11 @@ export const i18nData = { "Delete File": "删除文件", "Are you sure you want to delete the file": "您确定要删除此文件吗", + "Delete Comment": "删除评论", + "Are you sure you want to delete this comment? This action cannot be undone.": + "您确定要删除此评论吗?此操作不可撤销。", + "Comment deleted successfully": "评论删除成功", + // New translations "Change Avatar": "更改头像", "Change Username": "更改用户名", @@ -556,6 +567,11 @@ export const i18nData = { "Delete File": "刪除檔案", "Are you sure you want to delete the file": "您確定要刪除此檔案嗎", + "Delete Comment": "刪除評論", + "Are you sure you want to delete this comment? This action cannot be undone.": + "您確定要刪除此評論嗎?此操作不可撤銷。", + "Comment deleted successfully": "評論刪除成功", + // New translations "Change Avatar": "更改頭像", "Change Username": "更改用戶名", diff --git a/frontend/src/network/network.ts b/frontend/src/network/network.ts index 583f1d2..25f26a5 100644 --- a/frontend/src/network/network.ts +++ b/frontend/src/network/network.ts @@ -986,6 +986,18 @@ class Network { } } + async deleteComment(commentID: number): Promise> { + try { + const response = await axios.delete( + `${this.apiBaseUrl}/comments/${commentID}`, + ); + return response.data; + } catch (e: any) { + console.error(e); + return { success: false, message: e.toString() }; + } + } + async getServerConfig(): Promise> { try { const response = await axios.get(`${this.apiBaseUrl}/config`); diff --git a/frontend/src/pages/resource_details_page.tsx b/frontend/src/pages/resource_details_page.tsx index ac1267f..8ca68bc 100644 --- a/frontend/src/pages/resource_details_page.tsx +++ b/frontend/src/pages/resource_details_page.tsx @@ -1311,6 +1311,7 @@ function CommentTile({ comment }: { comment: Comment }) { {app.user?.id === comment.user.id && (
+
)} @@ -1456,4 +1457,62 @@ function EditCommentDialog({ ); -} \ No newline at end of file +} + +// 新增:删除评论弹窗组件 +function DeleteCommentDialog({ commentId }: { commentId: number }) { + const [isLoading, setLoading] = useState(false); + const reload = useContext(context); + const { t } = useTranslation(); + + const id = `delete_comment_dialog_${commentId}`; + + const handleDelete = async () => { + if (isLoading) return; + setLoading(true); + const res = await network.deleteComment(commentId); + const dialog = document.getElementById(id) as HTMLDialogElement; + dialog.close(); + if (res.success) { + showToast({ message: t("Comment deleted successfully"), type: "success" }); + reload(); + } else { + showToast({ message: res.message, type: "error" }); + } + setLoading(false); + }; + + return ( + <> + + +
+

{t("Delete Comment")}

+

+ {t("Are you sure you want to delete this comment? This action cannot be undone.")} +

+
+
+ +
+ +
+
+
+ + ); +} diff --git a/server/api/comment.go b/server/api/comment.go index 67a56b1..e72bb11 100644 --- a/server/api/comment.go +++ b/server/api/comment.go @@ -15,6 +15,7 @@ func AddCommentRoutes(router fiber.Router) { api.Get("/:resourceID", listComments) api.Get("/user/:username", listCommentsWithUser) api.Put("/:commentID", updateComment) + api.Delete("/:commentID", deleteComment) } func createComment(c fiber.Ctx) error { @@ -115,3 +116,23 @@ func updateComment(c fiber.Ctx) error { Message: "Comment updated successfully", }) } + +func deleteComment(c fiber.Ctx) error { + userID, ok := c.Locals("uid").(uint) + if !ok { + return model.NewRequestError("You must be logged in to delete comment") + } + commentIDStr := c.Params("commentID") + commentID, err := strconv.Atoi(commentIDStr) + if err != nil { + return model.NewRequestError("Invalid comment ID") + } + err = service.DeleteComment(uint(commentID), userID) + if err != nil { + return err + } + return c.JSON(model.Response[any]{ + Success: true, + Message: "Comment deleted successfully", + }) +} diff --git a/server/dao/comment.go b/server/dao/comment.go index 9ec4d42..44c7439 100644 --- a/server/dao/comment.go +++ b/server/dao/comment.go @@ -83,3 +83,25 @@ func UpdateCommentContent(commentID uint, content string) (*model.Comment, error db.Preload("User").First(&comment, commentID) return &comment, nil } + +func DeleteCommentByID(commentID uint) error { + return db.Transaction(func(tx *gorm.DB) error { + var comment model.Comment + if err := tx.First(&comment, commentID).Error; err != nil { + return err + } + if err := tx.Delete(&comment).Error; err != nil { + return err + } + if err := tx.Model(&model.User{}).Where("id = ?", comment.UserID).Update("comments_count", gorm.Expr("comments_count - 1")).Error; err != nil { + return err + } + if err := tx. + Where("type = ? and ref_id = ?", model.ActivityTypeNewComment, commentID). + Delete(&model.Activity{}). + Error; err != nil { + return err + } + return nil + }) +} diff --git a/server/service/comment.go b/server/service/comment.go index a67c540..b946682 100644 --- a/server/service/comment.go +++ b/server/service/comment.go @@ -84,3 +84,17 @@ func UpdateComment(commentID, userID uint, content string) (*model.CommentView, } return updated.ToView(), nil } + +func DeleteComment(commentID, userID uint) error { + comment, err := dao.GetCommentByID(commentID) + if err != nil { + return model.NewNotFoundError("Comment not found") + } + if comment.UserID != userID { + return model.NewRequestError("You can only delete your own comments") + } + if err := dao.DeleteCommentByID(commentID); err != nil { + return model.NewInternalServerError("Error deleting comment") + } + return nil +}