diff --git a/API.md b/API.md index 8cb2060..96fd0d1 100644 --- a/API.md +++ b/API.md @@ -276,69 +276,49 @@ * inner_size: 内嵌评论数量,默认5 * inner_page: 内嵌评论当前页,默认1 -返回 - -普通评论 +返回 楼中楼评论 ```json { "data": [ { "username": "Benny", - "date": "2021-06-17 10:54:19", - "browser": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.13; rv:85.1) Gecko/20100101 Firefox/85.1", - "content": "test", + "date": "2021-06-22 18:26:42", + "browser": "PostmanRuntime/7.28.0", + "content": "父评论benny", "resource_id": 233, - "id": "60cab95baa7f515ea291392b", - "children": [], - "children_count": 0 - } - ], - "count": 1, - "resource_id": 233 -} - -``` - -楼中楼 - -```json -{ - "data": [ - { - "username": "Benny", - "date": "2021-06-17 10:54:19", - "browser": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.13; rv:85.1) Gecko/20100101 Firefox/85.1", - "content": "test", - "resource_id": 233, - "id": "60cab95baa7f515ea291392b" + "type": "parent", + "id": "60d1bae2d87ce6e9a2934a0f" }, { "username": "Benny", - "date": "2021-06-15 10:54:19", - "browser": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.13; rv:85.1) Gecko/20100101 Firefox/85.1", - "content": "test8888", + "date": "2021-06-22 18:24:44", + "browser": "PostmanRuntime/7.28.0", + "content": "父评论benny", "resource_id": 233, - "id": "60cab95baa7f515ea2988888", + "type": "parent", + "ack": false, "children": [ { - "username": "Alex", - "date": "2021-05-31 16:58:21", + "username": "admin", + "date": "2021-06-22 18:25:12", "browser": "PostmanRuntime/7.28.0", - "content": "评论17", - "id": "60c838a12a5620b7e4ba5dfc", - "resource_id": 233 + "content": "admin子评2论2", + "resource_id": 233, + "type": "child", + "id": "60d1ba88d87ce6e9a2934a0c" }, { - "username": "Paul", - "date": "2021-05-22 16:58:21", + "username": "admin", + "date": "2021-06-22 18:25:08", "browser": "PostmanRuntime/7.28.0", - "content": "评论14", - "id": "60c838a12a5620b7e4ba1111", - "resource_id": 233 + "content": "admin子评论2", + "resource_id": 233, + "type": "child", + "id": "60d1ba84d87ce6e9a2934a0a" } ], - "children_count": 2 + "id": "60d1ba6cd87ce6e9a2934a08" } ], "count": 2, @@ -396,22 +376,15 @@ * DELETE `/api/comment`,提交json数据 -删除子评论 + ```json { - "parent_id": "60cab935e9f929e09c91392a", - "child_id": "60cab935e9f929e09c91392a1111111" + "comment_id": "60cab935e9f929e09c91392a" } ``` +不用关心comment_id是子评论还是父评论,会自动删除 -删除父评论 - -```json -{ - "parent_id": "60cab935e9f929e09c91392a" -} -``` 返回被删除的数量,HTTP 200表示删除成功,404表示未找到这条留言 diff --git a/yyetsweb/Mongo.py b/yyetsweb/Mongo.py index 2adb721..f655cdd 100644 --- a/yyetsweb/Mongo.py +++ b/yyetsweb/Mongo.py @@ -106,48 +106,55 @@ class BlacklistMongoResource(BlacklistResource): class CommentMongoResource(CommentResource, Mongo): def __init__(self): super().__init__() - self.page = 1 - self.size = 5 + self.inner_page = 1 + self.inner_size = 5 + self.projection = {"ip": False, "parent_id": False} - def convert_objectid(self, data): - final_data = [] + @staticmethod + def convert_objectid(data): + # change _id to id, remove _id for item in data: item["id"] = str(item["_id"]) item.pop("_id") - final_data.append(item) - # legacy issues - if item.get("children") is None: - item["children"] = [] + for child in item.get("children", []): + child["id"] = str(child["_id"]) + child.pop("_id") - # 嵌套评论同样也要支持分页 - # 新评论在上 - item["children"].reverse() - item["children_count"] = len(item["children"]) - item["children"] = item["children"][(self.page - 1) * self.size: self.page * self.size] - return final_data + def find_children(self, parent_data): + for item in parent_data: + children_ids = item.get("children", []) + condition = {"_id": {"$in": children_ids}, "deleted_at": {"$exists": False}, "type": "child"} + children_data = self.db["comment"].find(condition, self.projection) \ + .sort("_id", pymongo.DESCENDING).limit(self.inner_size).skip((self.inner_page - 1) * self.inner_size) + children_data = list(children_data) + if children_data: + item["children"] = [] + item["children"].extend(children_data) def get_comment(self, resource_id: int, page: int, size: int, **kwargs) -> dict: - inner_page = kwargs.get("inner_page", 1) - inner_size = kwargs.get("inner_size", 5) - self.page = inner_page - self.size = inner_size - condition = {"resource_id": resource_id, "deleted_at": {"$exists": False}} + self.inner_page = kwargs.get("inner_page", 1) + self.inner_size = kwargs.get("inner_size", 5) + condition = {"resource_id": resource_id, "deleted_at": {"$exists": False}, "type": {"$ne": "child"}} if resource_id == -1: condition.pop("resource_id") count = self.db["comment"].count_documents(condition) - data = self.db["comment"].find(condition, projection={"ip": False}) \ + data = self.db["comment"].find(condition, self.projection) \ .sort("_id", pymongo.DESCENDING).limit(size).skip((page - 1) * size) + data = list(data) + self.find_children(data) + self.convert_objectid(data) return { - "data": self.convert_objectid(list(data)), + "data": data, "count": count, "resource_id": resource_id } def add_comment(self, captcha: str, captcha_id: int, content: str, resource_id: int, - ip: str, username: str, browser: str, comment_id=None) -> dict: + ip: str, username: str, browser: str, parent_comment_id=None) -> dict: returned = {"status_code": 0, "message": ""} verify_result = CaptchaResource().verify_code(captcha, captcha_id) + # verify_result["status"] = 1 if not verify_result["status"]: returned["status_code"] = HTTPStatus.BAD_REQUEST returned["message"] = verify_result["message"] @@ -159,8 +166,8 @@ class CommentMongoResource(CommentResource, Mongo): returned["message"] = "资源不存在" return returned - if comment_id: - exists = self.db["comment"].find_one({"_id": ObjectId(comment_id)}) + if parent_comment_id: + exists = self.db["comment"].find_one({"_id": ObjectId(parent_comment_id)}) if not exists: returned["status_code"] = HTTPStatus.NOT_FOUND returned["message"] = "评论不存在" @@ -174,29 +181,37 @@ class CommentMongoResource(CommentResource, Mongo): "content": content, "resource_id": resource_id } - if comment_id is None: - # 普通评论 - basic_comment["children"] = [] - self.db["comment"].insert_one(basic_comment) + if parent_comment_id is None: + basic_comment["type"] = "parent" else: - # 嵌套评论 - object_id = uuid.uuid1().hex - basic_comment["id"] = object_id - self.db["comment"].find_one_and_update({"_id": ObjectId(comment_id)}, - {"$push": {"children": basic_comment}} + basic_comment["type"] = "child" + # 无论什么评论,都要插入一个新的document + inserted_id: str = self.db["comment"].insert_one(basic_comment).inserted_id + + if parent_comment_id is not None: + # 对父评论的子评论,需要给父评论加children id + self.db["comment"].find_one_and_update({"_id": ObjectId(parent_comment_id)}, + {"$push": {"children": inserted_id}} + ) + self.db["comment"].find_one_and_update({"_id": ObjectId(inserted_id)}, + {"$set": {"parent_id": ObjectId(parent_comment_id)}} ) returned["status_code"] = HTTPStatus.CREATED returned["message"] = "评论成功" return returned - def delete_comment(self, parent_id: str, child_id: str = None): + def delete_comment(self, comment_id): current_time = ts_date() - if child_id is None: - count = self.db["comment"].update_one({"_id": ObjectId(parent_id), "deleted_at": {"$exists": False}}, - {"$set": {"deleted_at": current_time}}).modified_count + count = self.db["comment"].update_one({"_id": ObjectId(comment_id), "deleted_at": {"$exists": False}}, + {"$set": {"deleted_at": current_time}}).modified_count + # 找到子评论,全部标记删除 + parent_data = self.db["comment"].find_one({"_id": ObjectId(comment_id)}) + if parent_data: + child_ids = parent_data.get("children", []) else: - count = self.db["comment"].update_one({"_id": ObjectId(parent_id), "deleted_at": {"$exists": False}}, - {"$pull": {"children": {"id": child_id}}}).modified_count + child_ids = [] + count += self.db["comment"].update_many({"_id": {"$in": child_ids}, "deleted_at": {"$exists": False}}, + {"$set": {"deleted_at": current_time}}).modified_count returned = {"status_code": 0, "message": "", "count": -1} if count == 0: diff --git a/yyetsweb/database.py b/yyetsweb/database.py index 53a195a..0d4b9ce 100644 --- a/yyetsweb/database.py +++ b/yyetsweb/database.py @@ -152,7 +152,7 @@ class CommentResource: username: str, browser: str, comment_id=None) -> dict: pass - def delete_comment(self, parent_id: str, child_id: str = None): + def delete_comment(self, comment_id:str): pass diff --git a/yyetsweb/handler.py b/yyetsweb/handler.py index 0259d8c..98f86fe 100644 --- a/yyetsweb/handler.py +++ b/yyetsweb/handler.py @@ -151,11 +151,13 @@ class UserHandler(BaseHandler): self.write(resp) @gen.coroutine + @web.authenticated def patch(self): resp = yield self.add_remove_fav() self.write(resp) @gen.coroutine + @web.authenticated def get(self): resp = yield self.get_user_info() self.write(resp) @@ -222,6 +224,7 @@ class UserLikeHandler(BaseHandler): return {"LIKE": self.instance.get_user_like(username)} @gen.coroutine + @web.authenticated def get(self): resp = yield self.like_data() self.write(resp) @@ -295,11 +298,10 @@ class CommentHandler(BaseHandler): # payload = {"id": "obj_id"} payload = json.loads(self.request.body) username = self.get_current_user() - parent_id = payload["parent_id"] - child_id = payload.get("child_id") + comment_id = payload["comment_id"] if self.instance.is_admin(username): - result = self.instance.delete_comment(parent_id, child_id) + result = self.instance.delete_comment(comment_id) self.set_status(result["status_code"]) return result else: @@ -312,11 +314,13 @@ class CommentHandler(BaseHandler): self.write(resp) @gen.coroutine + @web.authenticated def post(self): resp = yield self.add_comment() self.write(resp) @gen.coroutine + @web.authenticated def delete(self): resp = yield self.delete_comment() self.write(resp) @@ -356,6 +360,7 @@ class AnnouncementHandler(BaseHandler): self.write(resp) @gen.coroutine + @web.authenticated def post(self): resp = yield self.add_announcement() self.write(resp)