# -*- coding: utf-8 -*- from collections import defaultdict from django.db.models import Q from gm_types.doris import CARD_TYPE from gm_types.mimas import ( TRACTATE_PLATFORM, TRACTATE_REPLY_HIGHLIGHT ) from gm_types.error import ERROR as CODES from gm_dataquery.dict_mixin import to_dict from gm_rpcd.all import RPCDFaultException from qa.views.mark import get_author_id_by_business_id from utils.rpc import gen, get_current_user from utils.stat_log import SocialStatLogForUserAction from talos.cache.base import reply_cache as reply_msg_cache from talos.tools.replies_tool import ReplyTool from talos.views.tractate.tractate import update_tractate_special_info from talos.libs.datetime_utils import get_timestamp_or_none from qa.utils.decorator import listing from talos.rpc import bind_context, bind from talos.services.tractate.tractate import TractateService from talos.services.tractate.reply import TractateReplyService from talos.services.tractate.vote import TractateReplyVoteService from talos.services import get_user_from_context, UserService, UserConvertService from talos.services.doctor import DoctorService from talos.tools.tractate_reply_tool import reply_update_cache, get_reply_ids from talos.tasks.tractate import reply_push, applet_replied_push, applet_reply_summary_push uri_pre = 'mimas/tractate_reply/' @bind_context(uri_pre + 'create', with_context=True) def create_tractate_reply(ctx, tractate_id, content, replied_id=None, top_id=None, images=[]): """ 回复创建 :param ctx: :param tractate_id: :param content: :param replied_id: :param top_id: :param images: 图片列表[{"image_url": "width": 0, "height": 0}] :return: """ user = get_user_from_context(ctx) if not user: return gen(CODES.LOGIN_REQUIRED) tractate = TractateService.healthy(tractate_id) result = { "replied_user_id": "", "replied_user_portrait": "", "replied_user_name": "" } replied = None if not top_id and not replied_id: top_id = 0 if replied_id and not top_id: top_id = replied_id if replied_id: replied_info = TractateReplyService.get_by_id(pk=replied_id) replied_user_info = UserConvertService.get_user_info_by_user_id(replied_info.user_id) result.update({ "replied_user_id": replied_user_info.get("user_id", 0), "replied_user_portrait": replied_user_info.get("portrait", ""), "replied_user_name": replied_user_info.get("user_name", ""), "replied_user_info": replied_user_info, }) reply = TractateReplyService.create( content=content, user_id=user.id, tractate_id=tractate_id, extra={ "top_id": top_id, "replied_id": replied_id, "source_id": TRACTATE_PLATFORM.GM, "images": images, } ) replied_user_id = replied_info.user_id if replied_id else tractate.user_id if user.id != replied_user_id: rt = ReplyTool(reply_msg_cache, replied_user_id) rt.receive_tractate_reply(reply.id) reply_push.delay(user_id=user.id, tractate_id=tractate_id, reply_id=reply.id, content=content) # 小程序推送 applet_replied_push.delay(reply.id) applet_reply_summary_push.apply_async((reply.id,), countdown=86400) # 用户行为埋点 评论相关 SocialStatLogForUserAction.stat_log_for_reply( content_type=SocialStatLogForUserAction.CONTENT_TYPE.user_post, content_id=tractate_id, user_id=user.id ) #更新一级评论下的评论数 if top_id: result.update({"top_id": int(top_id)}) TractateReplyService.update_reply_count(top_reply_id=top_id) else: result.update({"replies": []}) TractateService.incr_tractate_reply(tractate=tractate) reply_update_cache(user_id=user.id, tractate_id=tractate_id, reply_id=reply.id) result.update({ 'id': reply.id, 'content': reply.content, 'create_time': get_timestamp_or_none(reply.create_time), "replied_id": int(replied_id) if replied_id else '', "user_name": user.nickname, "user_id": user.id, "user_portrait": user.portrait, "is_vote": False, "vote_num": 0, "status": TRACTATE_REPLY_HIGHLIGHT.DARK, "reply_count": 0, "reply_user_info": UserConvertService.get_user_info_by_user_id(user.id), }) return result @bind_context(uri_pre + 'receive', with_context=True) def get_replies_by_ids(ctx, replies_ids): user = get_user_from_context(ctx) if not user: return gen(CODES.LOGIN_REQUIRED) if not replies_ids: return {} replies_dict = TractateReplyService.get_replies_info(reply_ids=replies_ids) user_ids = [] replied_ids = [] tractates_ids = [] for _, reply in replies_dict.items(): user_ids.append(reply["user_id"]) replied_ids.append(reply["replied_id"]) tractates_ids.append(reply["tractate_id"]) replied_dict = TractateReplyService.get_replies_info(reply_ids=replied_ids) users_dict = UserService.get_users_by_user_ids(user_ids) tractates_dict = TractateService.list_tractate_by_ids(tractates_ids) reply_images_dic = TractateReplyService.get_reply_images_by_reply_ids( reply_ids=(replies_ids + replied_ids) ) doctors_dict = {} doctors = DoctorService.get_doctor_from_user_ids(user_ids) for doctor in doctors: doctors_dict[doctor.user_id] = doctor result = {} for reply_id, reply in replies_dict.items(): reply_user = users_dict.get(reply["user_id"], {}) doctor = doctors_dict.get(reply["user_id"], {}) doctor_info = {} if doctor: doctor_info = { "user_id": doctor.user_id, "doctor_id": doctor.id, "name": doctor.name, } replied = {} if reply["replied_id"]: item = replied_dict.get(reply["replied_id"], {}) if item: replied = { "id": reply["replied_id"], "content": reply["content"], "images": reply_images_dic.get(reply["replied_id"], []), } tractate = {} tractate_obj = tractates_dict.get(reply["tractate_id"]) if tractate_obj: tractate = { "id": tractate_obj.id, "content": tractate_obj.content, "user_id": tractate_obj.user_id } info = { "id": reply["id"], "reply_date": reply["create_time"], "reply_content": reply["content"], "images": reply_images_dic.get(reply["id"], []), "tractate": tractate, "replied": replied, "reply_user": { "id": reply_user.id, "name": reply_user.nickname, "portrait": reply_user.portrait, }, "author": { "id": user.id, "name": user.nickname, "portrait": user.portrait, }, "doctor": doctor_info, } result[str(reply_id)] = info return result @bind(uri_pre + 'top/list') #@listing() def list_top_reply(ctx, tractate_id, offset=0, count=10, sort_condition=None): """一级回复列表""" user = get_user_from_context(ctx) tractate = TractateService.healthy(tractate_id) replies = TractateReplyService.list_top_reply_by_tractate_id(tractate_id, offset, count) reply_ids , user_ids = [], [] for reply in replies: reply_ids.append(reply.get("id")) user_ids.append(reply.get("user_id")) users = UserConvertService.get_user_info_by_user_ids(user_ids) reply_images_dic = TractateReplyService.get_reply_images_by_reply_ids(reply_ids) for reply in replies: reply_user_info = users.get(reply.get('user_id'), {}) if not reply_user_info: continue reply.update({ "user_nickname": reply_user_info.get("user_name", ""), "user_portrait": reply_user_info.get("portrait", ""), "reply_user_info": reply_user_info, "images": reply_images_dic.get(reply.get("id"), []), }) reply_num_total = tractate.reply_num return { 'replies': replies, 'reply_num_total': reply_num_total } @bind(uri_pre + 'second_list') @listing() def gets_second_reply(reply_id, offset=0, count=10, user_id=None, sort_condition=None): """二级回复列表""" second_reply = TractateReplyService.get_second_reply_by_top_id( top_id=int(reply_id), offset=int(offset), count=int(count), sort_condition=sort_condition) user_ids, _reply_ids, replied_ids = set(), set(), set() for reply_item in second_reply: _user_id = reply_item.get("user_id", 0) _replied_id = reply_item.get("replied_id", 0) _id = reply_item.get("id", 0) if _user_id: user_ids.add(_user_id) if _replied_id: replied_ids.add(_replied_id) if _id: _reply_ids.add(_id) # 点赞状态 vote_reply_ids = TractateReplyVoteService.model.objects.filter( user_id=user_id, reply_id__in=_reply_ids, is_online=True ).values_list("reply_id", flat=True) # 图片 reply_images_dic = TractateReplyService.get_reply_images_by_reply_ids(_reply_ids) # 评论数据信息 replied_infos = TractateReplyService.get_replies_info(reply_ids=replied_ids) replyed_user_ids = set(v.get("user_id", 0) for v in replied_infos.values()) all_user_ids = user_ids | replyed_user_ids users = UserConvertService.get_user_info_by_user_ids(all_user_ids) for reply in second_reply: reply_user_info = users.get(reply.get('user_id', 0), {}) if not reply_user_info: continue replied_info = replied_infos.get(reply.get('replied_id'), {}) replied_user_info = users.get(replied_info.get('user_id', 0), {}) if not replied_user_info: continue reply.update({ "images": reply_images_dic.get(reply.get("id"), []), "is_vote": True if reply.get('id') in vote_reply_ids else False, "user_name": reply_user_info.get("user_name", ""), "user_portrait": reply_user_info.get("portrait", ""), "replied_user_id": replied_user_info.get("user_id", 0), "replied_user_name": replied_user_info.get("user_name", ""), "replied_user_portrait": replied_user_info.get("portrait", ""), "reply_user_info": reply_user_info, "replied_user_info": replied_user_info, }) return second_reply @bind(uri_pre + 'top_list') @listing() def list_top_reply_by_tractate_ids(tractate_ids, offset=0, count=2, sort_condition=None): """多个帖子一级评论""" result, user_ids, reply_ids = {}, [], [] for tractate_id in tractate_ids: _replies_list = TractateReplyService.list_top_reply_by_tractate_id( tractate_id=tractate_id, offset=offset, count=count, sort_condition=sort_condition ) user_ids.extend([reply.get('user_id') for reply in _replies_list]) reply_ids.extend([reply.get("id") for reply in _replies_list]) result[str(tractate_id)] = _replies_list users = UserConvertService.get_user_info_by_user_ids(user_ids) reply_images_dic = TractateReplyService.get_reply_images_by_reply_ids(reply_ids) for k, item in result.items(): for reply in item: _user_info = users.get(reply.get("user_id", 0), {}) if not _user_info: continue reply.update({ "images": reply_images_dic.get(reply.get("id"), []), "user_nickname": _user_info.get("user_name", ""), "user_portrait": _user_info.get("portrait", ""), "reply_user_info": _user_info, }) return result @bind(uri_pre + 'top_list_include_second_comments') @listing() def list_top_reply_include_second_comments( tractate_ids, offset=0, count=2, user_id=None, sort_condition=None, top_id=None, reply_id=None ): """多个帖子一级评论 二级评论""" result = {} SECOND_COUNT, START_INDEX = 2, 0 for tractate_id in tractate_ids: # 一级评论数据 top_reply_infos = TractateReplyService.list_top_reply_by_tractate_id( tractate_id=int(tractate_id), offset=int(offset), count=int(count), sort_condition=sort_condition, top_id=top_id, ) top_reply_user_ids, vote_reply_ids = set(), [] second_user_ids, repied_ids = set(), [] # 一级评论处理用户,点赞状态,二级评论及子评论逻辑 for item in top_reply_infos: _user_id = item.get("user_id", 0) _id = item.get("id", 0) if _user_id: top_reply_user_ids.add(_user_id) if _id: vote_reply_ids.append(_id) second_reply_id = None if top_id == _id and top_id != reply_id: second_reply_id = reply_id # 二级评论 second_reply = TractateReplyService.get_second_reply_by_top_id( top_id=_id, count=SECOND_COUNT, offset=START_INDEX, reply_id=second_reply_id ) # 处理一级评论的子评论 item['replies'] = second_reply for reply in second_reply: _reply_user_id = reply.get("user_id", 0) _replied_id = reply.get("replied_id", 0) _second_reply_id = reply.get("id", 0) if _reply_user_id: second_user_ids.add(_reply_user_id) if _replied_id: repied_ids.append(_replied_id) if _second_reply_id: vote_reply_ids.append(_second_reply_id) # 处理二级评论、被评论用户信息 replied_infos = TractateReplyService.get_replies_info(reply_ids=repied_ids) replyed_user_ids = set(v.get("user_id", 0) for v in replied_infos.values()) # 取所有用户信息 _all_user_ids = top_reply_user_ids | second_user_ids | replyed_user_ids all_user_infos = UserConvertService.get_user_info_by_user_ids(_all_user_ids) # 取所有已经被点赞的评论id voted_reply_ids = TractateReplyVoteService.get_vote_status( user_id=user_id, tractate_id=tractate_id, reply_ids=vote_reply_ids) # 图片 all_reply_images_dic = TractateReplyService.get_reply_images_by_reply_ids(vote_reply_ids) # 评论信息处理 for top_reply_info in top_reply_infos: top_reply_user_info = all_user_infos.get(top_reply_info.get("user_id", 0), {}) if not top_reply_user_info: continue top_reply_info.update({ "user_name": top_reply_user_info.get("user_name", ""), "user_portrait": top_reply_user_info.get("portrait", ""), "is_vote": bool(top_reply_info.get("id", 0) in voted_reply_ids), "top_reply_user_info": top_reply_user_info, "images": all_reply_images_dic.get(top_reply_info.get("id", 0), []), }) # 二级评论信息处理 for second_reply in top_reply_info.get('replies', []): second_reply_user_info = all_user_infos.get(second_reply.get("user_id", 0), {}) if not second_reply_user_info: continue replied_info = replied_infos.get(second_reply.get('replied_id'), {}) replied_info_user_info = all_user_infos.get(replied_info.get("user_id", 0), {}) if not replied_info_user_info: continue second_reply.update({ "is_vote": bool(second_reply.get("id", 0) in voted_reply_ids), "user_name": second_reply_user_info.get("user_name", ""), "user_portrait": second_reply_user_info.get("portrait", ""), "replied_user_id": replied_info_user_info.get("user_id", ""), "replied_user_name": replied_info_user_info.get("user_name", ""), "replied_user_portrait": replied_info_user_info.get("portrait", ""), "second_reply_user_info": second_reply_user_info, "replied_user_info": replied_info_user_info, "images": all_reply_images_dic.get(second_reply.get("id", 0), []), }) result[str(tractate_id)] = top_reply_infos return result @bind(uri_pre + 'reply_popup') @listing() def get_reply_in_popup(tractate_id, offset=0, count=5, user_id=None, sort_condition=None): """评论弹窗~获取评论(一级和二级)""" SECOND_COUNT, START_INDEX = 2, 0 TractateService.healthy(tractate_id) # 一级评论数据 top_reply_infos = TractateReplyService.list_top_reply_by_tractate_id( tractate_id=int(tractate_id), offset=int(offset), count=int(count), sort_condition=sort_condition ) top_reply_user_ids, vote_reply_ids = set(), [] second_user_ids, repied_ids = set(), [] # 一级评论处理用户,点赞状态,二级评论及子评论逻辑 for item in top_reply_infos: _user_id = item.get("user_id", 0) _id = item.get("id", 0) if _user_id: top_reply_user_ids.add(_user_id) if _id: vote_reply_ids.append(_id) # 二级评论 second_reply = TractateReplyService.get_second_reply_by_top_id( top_id=_id, count=SECOND_COUNT, offset=START_INDEX, sort_condition=sort_condition ) # 处理一级评论的子评论 item['replies'] = second_reply for reply in second_reply: _reply_user_id = reply.get("user_id", 0) _replied_id = reply.get("replied_id", 0) _second_reply_id = reply.get("id", 0) if _reply_user_id: second_user_ids.add(_reply_user_id) if _replied_id: repied_ids.append(_replied_id) if _second_reply_id: vote_reply_ids.append(_second_reply_id) # 处理二级评论、被评论用户信息 replied_infos = TractateReplyService.get_replies_info(reply_ids=repied_ids) replyed_user_ids = set(v.get("user_id", 0) for v in replied_infos.values()) # 取所有用户信息 _all_user_ids = top_reply_user_ids | second_user_ids | replyed_user_ids all_user_infos = UserConvertService.get_user_info_by_user_ids(_all_user_ids) # 取所有已经被点赞的评论id voted_reply_ids = TractateReplyVoteService.get_vote_status( user_id=user_id, tractate_id=tractate_id, reply_ids=vote_reply_ids) # 图片 all_reply_images_dic = TractateReplyService.get_reply_images_by_reply_ids(vote_reply_ids) #评论信息处理 for top_reply_info in top_reply_infos: top_reply_user_info = all_user_infos.get(top_reply_info.get("user_id", 0), {}) if not top_reply_user_info: continue top_reply_info.update({ "user_name": top_reply_user_info.get("user_name", ""), "user_portrait": top_reply_user_info.get("portrait", ""), "is_vote": bool(top_reply_info.get("id", 0) in voted_reply_ids), "top_reply_user_info": top_reply_user_info, "images": all_reply_images_dic.get(top_reply_info.get("id", 0), []), }) # 二级评论信息处理 for second_reply in top_reply_info.get('replies', []): second_reply_user_info = all_user_infos.get(second_reply.get("user_id", 0), {}) if not second_reply_user_info: continue replied_info = replied_infos.get(second_reply.get('replied_id'), {}) replied_info_user_info = all_user_infos.get(replied_info.get("user_id", 0), {}) if not replied_info_user_info: continue second_reply.update({ "is_vote": bool(second_reply.get("id", 0) in voted_reply_ids), "user_name": second_reply_user_info.get("user_name", ""), "user_portrait": second_reply_user_info.get("portrait", ""), "replied_user_id": replied_info_user_info.get("user_id", ""), "replied_user_name": replied_info_user_info.get("user_name", ""), "replied_user_portrait": replied_info_user_info.get("portrait", ""), "second_reply_user_info": second_reply_user_info, "replied_user_info": replied_info_user_info, "images": all_reply_images_dic.get(second_reply.get("id", 0), []), }) return top_reply_infos @bind(uri_pre + 'light_reply') def get_light_reply(tractate_id, user_id=None, target_reply_id=None): """获取高亮评论""" SECOND_COUNT, START_INDEX = 2, 0 more_highlight = True if not target_reply_id: return gen(CODES.PARAMS_INCOMPLETE) top_info = TractateReplyService.get_highlight_reply(target_reply_id=target_reply_id) if not top_info: return [] user_ids, replied_ids, vote_reply_ids = set(), set(), set() user_ids.add(top_info.get('user_id')) vote_reply_ids.add(top_info.get("id")) second_replies = TractateReplyService.get_second_reply_by_top_id( top_id=top_info.get('id'), count=SECOND_COUNT, target_reply_id=target_reply_id) for reply in second_replies: _reply_user_id = reply.get("user_id", 0) _replied_id = reply.get("replied_id", 0) _second_reply_id = reply.get("id", 0) if _reply_user_id: user_ids.add(_reply_user_id) if _replied_id: replied_ids.add(_replied_id) if _second_reply_id: vote_reply_ids.add(_second_reply_id) replied_infos = TractateReplyService.get_replies_info(reply_ids=replied_ids) for key, value in replied_infos.items(): user_ids.add(value.get('user_id', 0)) #获取用户是否点过赞 voted_reply_ids = TractateReplyVoteService.get_vote_status( user_id=user_id, tractate_id=tractate_id, reply_ids=vote_reply_ids ) # 图片 all_reply_images_dic = TractateReplyService.get_reply_images_by_reply_ids(vote_reply_ids) # 所有用户 all_user = UserConvertService.get_user_info_by_user_ids(user_ids) for second_reply in second_replies: second_reply_user_info = all_user.get(second_reply.get("user_id", 0), {}) if not second_reply_user_info: continue replied_info = replied_infos.get(second_reply.get('replied_id'), {}) replied_info_user_info = all_user.get(replied_info.get("user_id", 0), {}) if not replied_info_user_info: continue if not top_info['status'] and second_reply['status'] == TRACTATE_REPLY_HIGHLIGHT.LIGHT: more_highlight = False second_reply.update({ "is_vote": True if second_reply.get('id') in voted_reply_ids else False, "user_name": second_reply_user_info.get("user_name", ""), "user_portrait": second_reply_user_info.get("portrait", ""), "replied_user_id": replied_info_user_info.get("user_id", ""), "replied_user_name": replied_info_user_info.get("user_name", ""), "replied_user_portrait": replied_info_user_info.get("portrait", ""), "second_reply_user_info": second_reply_user_info, "replied_user_info": replied_info_user_info, "images": all_reply_images_dic.get(second_reply.get("id", 0), []), }) top_user_info = all_user.get(top_info.get("user_id", 0), {}) top_info.update({ "replies": second_replies, "user_id": top_user_info.get("user_id", 0), "user_name": top_user_info.get("user_name", ""), "user_portrait": top_user_info.get("portrait", ""), "is_vote": True if top_info.get('id') in voted_reply_ids else False, "top_reply_user_info": top_user_info, "images": all_reply_images_dic.get(top_info.get("id", 0), []), }) if not top_info['status'] and more_highlight: top_info['status'] = TRACTATE_REPLY_HIGHLIGHT.MORE_LIGHT return [top_info] @bind(uri_pre + 'get_info') def get_reply_by_id(reply_id): if not reply_id: return gen(CODES.PARAMS_INCOMPLETE) reply = TractateReplyService.get_by_id(pk=int(reply_id)) reply = to_dict(reply) user_info = UserConvertService.get_user_info_by_user_id(reply.get('user_id')) reply_images_dic = TractateReplyService.get_reply_images_by_reply_ids([reply.id]) reply.update({ "user_nickname": user_info.get("user_name", ""), "user_portrait": user_info.get("portrait", ""), "reply_user_info": user_info, "images": reply_images_dic.get(reply.id, []), }) return reply @bind(uri_pre + 'get_by_tractate') #@listing() def get_reply_by_tractate(user_id, offset=0, count=10, tractate_from='', use_new_query=False): """ :param user_id: :param offset: :param count: :param tractate_from: 7.12.0 帖子入口 :param use_new_query: 7.12.0 版本兼容 :return: """ if not user_id: return gen(CODES.LOGIN_REQUIRED) data = get_reply_ids(user_id=user_id) dic_reply = data.get('dic_reply') reply_infos = TractateReplyService.get_replies_info(reply_ids=data.get('reply_ids', [])) reply_images_dic = TractateReplyService.get_reply_images_by_reply_ids(reply_ids=data.get('reply_ids', [])) _tractate_ids = TractateService.get_tractate_ids_by_query_and_order( query=Q(id__in=data.get('tractate_ids', [])), order_by=["-id"], offset=offset, size=count, tractate_from=tractate_from, use_new_query=use_new_query ) tractate_list = [] if _tractate_ids: tractates_info_dic = TractateService.get_tractate_infos_by_ids( tractate_ids=_tractate_ids, need_special_info=True, tractate_from=tractate_from, use_new_query=use_new_query, ) # 增加浏览量 TractateService.tractate_view_increase_num(tractates_info_dic.get("valid_tractate_ids", [])) tractate_list = update_tractate_special_info(tractates_info_dic.get("tractate_list", []), _tractate_ids, user_id) for tractate in tractate_list: _reply_id = dic_reply.get(tractate.get('tractate_id')) if _reply_id: _reply_data = reply_infos.get(_reply_id) if not _reply_data: continue _reply_data.update({ "images": reply_images_dic.get(_reply_id, []), }) tractate['reply'] = _reply_data return tractate_list @bind_context(uri_pre + 'received_aggregation', with_context=True) def tractate_reply_reseived_aggregation(ctx): result = { "count": 0, "last_user_info": {}, "create_time": 0, } user = get_user_from_context(ctx) if not user: return result info = TractateReplyService.get_tractate_reply_count_info(user.id) count = info["count"] last_user_id = info["last_user_id"] created_time = info["create_time"] if not count or not last_user_id: return result # get_user_from_context # last_user_info = UserConvertService.get_user_info_by_user_id(last_user_id) result["count"] = count result["create_time"] = get_timestamp_or_none(created_time) _user_info = { "nickname": user.nickname, "portrait": user.portrait, } result["last_user_info"] = _user_info return result @bind(uri_pre + 'read') def tractate_reply_read(): user = get_current_user() if not user: return TractateReplyService.read_all(user.id) @bind('mimas/mark/tractate_replies') def get_mark_tractate_replies(tractate_ids, sort_type=None, first_reply_count=2, second_reply_count=1): """ 打卡贴的评论 2条一级 + 1条二级 :param tractate_ids: :param sort_type: :param first_reply_count: :param second_reply_count: :return: """ result = { "replies": {}, } if not tractate_ids: return result user = get_current_user() _user_id = user and user.id or None replies_ids = set() tractate_ids = list(map(int, tractate_ids)) # 一级评论 first_replies = TractateReplyService.top_replies_by_tractate_ids( tractate_ids, sort_type=sort_type ) first_reply_ids = first_replies.get('first_reply_ids', []) user_ids = first_replies.get('first_reply_user_ids', set()) first_replies = first_replies.get('first_replies', {}) reply_voted_ids = TractateReplyVoteService.get_vote_status( user_id=_user_id, tractate_id=None, reply_ids=first_reply_ids ) replies_ids.update(first_reply_ids) # 二级评论 second_reply_dict = TractateReplyService.get_second_replies_by_first_ids( first_reply_ids, count=second_reply_count, ) user_ids.update(second_reply_dict.get('second_reply_user_ids', set())) user_dict = TractateService.get_user_info_by_user_ids(user_ids) second_replies = second_reply_dict.get('second_reply', {}) replies_ids.update(second_reply_dict.get('second_reply_ids', [])) # 二级评论的评论数 second_reply_count_dic = TractateReplyService.get_second_replies_count(second_reply_dict.get('second_reply_ids', [])) reply_images_dict = TractateReplyService.get_reply_images_by_reply_ids(reply_ids=replies_ids) # 一二级评论拼接 reply_dict = defaultdict(list) for (tractate_id, reply_id), reply in first_replies.items(): first_reply_id = reply.get('reply_id') author_id = reply.get('user_id', 0) if not first_reply_id: continue reply['author'] = user_dict.get(author_id, {}) reply['is_vote'] = first_reply_id in reply_voted_ids reply['images'] = reply_images_dict.get(first_reply_id, []) second_reply = second_replies.get(first_reply_id, {}) if second_reply: second_reply['author'] = user_dict.get(second_reply.get('user_id', 0), {}) second_reply['images'] = reply_images_dict.get(second_reply.get('id'), []) second_reply['reply_count'] = second_reply_count_dic.get(second_reply.get('id'), 0) reply['comments'] = [second_reply] reply_dict[str(tractate_id)].append(reply) result['replies'] = reply_dict return result